Skip to content

Commit

Permalink
feat: parse arrays of numbers/strings for customizer
Browse files Browse the repository at this point in the history
  • Loading branch information
seasick committed Jan 21, 2024
1 parent b910f88 commit 36df006
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 68 deletions.
70 changes: 54 additions & 16 deletions src/components/Customizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import Accordion from '@mui/material/Accordion';
import AccordionDetails from '@mui/material/AccordionDetails';
import AccordionSummary from '@mui/material/AccordionSummary';
import Autocomplete from '@mui/material/Autocomplete';
import Checkbox from '@mui/material/Checkbox';
import FormControlLabel from '@mui/material/FormControlLabel';
import FormGroup from '@mui/material/FormGroup';
Expand All @@ -19,19 +20,21 @@ type Props = {
};

export default function Customizer({ parameters, onChange }: Props) {
const handleParameterChange =
(isCheckbox) => (event: React.ChangeEvent<HTMLInputElement>) => {
const newParameters = parameters.map((parameter) => {
if (parameter.name === event.target.name) {
return {
...parameter,
value: isCheckbox ? event.target.checked : event.target.value,
};
}
return parameter;
});
onChange(newParameters);
};
const handleParameterChange = (
event: React.ChangeEvent<HTMLInputElement>,
newValue?
) => {
const newParameters = parameters.map((parameter) => {
if (parameter.name === event.target.name) {
return {
...parameter,
value: newValue || event.target.value,
};
}
return parameter;
});
onChange(newParameters);
};

// Group parameters
const groups = useMemo(
Expand Down Expand Up @@ -74,7 +77,7 @@ export default function Customizer({ parameters, onChange }: Props) {
fullWidth
key={parameter.name}
name={parameter.name}
onChange={handleParameterChange(false)}
onChange={handleParameterChange}
value={parameter.value}
sx={{ mt: 2, p: 1 }}
>
Expand All @@ -94,7 +97,7 @@ export default function Customizer({ parameters, onChange }: Props) {
type={parameter.type}
key={parameter.name}
name={parameter.name}
onChange={handleParameterChange(false)}
onChange={handleParameterChange}
value={parameter.value}
InputProps={{
inputProps: {
Expand All @@ -107,14 +110,49 @@ export default function Customizer({ parameters, onChange }: Props) {
sx={{ mt: 2, p: 1 }}
/>
);
} else if (
parameter.type === 'number[]' ||
parameter.type === 'string[]'
) {
return (
<Autocomplete
key={parameter.name}
freeSolo
options={[]}
multiple
value={parameter.value as string[] | number[] | boolean[]}
onChange={handleParameterChange}
renderInput={(params) => {
return (
<TextField
label={parameter.description || parameter.name}
fullWidth
key={parameter.name}
name={parameter.name}
InputProps={{
inputProps: {
maxLength: parameter.range?.max,
min: parameter.range?.min,
max: parameter.range?.max,
step: parameter.range?.step,
},
}}
sx={{ mt: 2, p: 1 }}
{...params}
type={parameter.type}
/>
);
}}
/>
);
} else if (parameter.type === 'boolean') {
return (
<FormGroup key={parameter.name}>
<FormControlLabel
control={
<Checkbox
name={parameter.name}
onChange={handleParameterChange(true)}
onChange={handleParameterChange}
checked={parameter.value === true}
/>
}
Expand Down
35 changes: 31 additions & 4 deletions src/lib/openSCAD/parseParameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,18 @@ type ParameterRange = {
step?: number;
};

type ParameterType =
| 'string'
| 'number'
| 'boolean'
| 'string[]'
| 'number[]'
| 'boolean[]';

export type Parameter = {
name: string;
type: 'string' | 'number' | 'boolean';
value: string | boolean | number;
type: ParameterType;
value: string | boolean | number | string[] | number[] | boolean[];
description?: string;
group?: string;
range?: ParameterRange;
Expand All @@ -28,7 +36,7 @@ export default function parseParameters(script: string): Parameter[] {

const parameters: Record<string, Parameter> = {};
const parameterRegex =
/^([a-z0-9A-Z_$]+)\s*=\s*([^;]+);[\t\f\cK ]*(\/\/.*)?/gm; // TODO: Use AST parser instead of regex
/^([a-z0-9A-Z_$]+)\s*=\s*([^;]+);[\t\f\cK ]*(\/\/[^\n]*)?/gm; // TODO: Use AST parser instead of regex
const groupRegex = /^\/\*\s*\[([^\]]+)\]\s*\*\//gm;

const groupSections: { id: string; group: string; code: string }[] = [];
Expand Down Expand Up @@ -139,12 +147,31 @@ export default function parseParameters(script: string): Parameter[] {

function convertType(rawValue): {
value: string | boolean | number;
type: 'string' | 'number' | 'boolean';
type: ParameterType;
} {
if (/^\d+(\.\d+)?$/.test(rawValue)) {
return { value: parseFloat(rawValue), type: 'number' };
} else if (rawValue === 'true' || rawValue === 'false') {
return { value: rawValue === 'true', type: 'boolean' };
} else if (rawValue.startsWith('[') && rawValue.endsWith(']')) {
// Array type
const arrayValue = rawValue
.slice(1, -1)
.split(',')
.map((item) => item.trim());
if (arrayValue.every((item) => /^\d+(\.\d+)?$/.test(item))) {
return {
value: arrayValue.map((item) => parseFloat(item)),
type: 'number[]',
};
} else if (arrayValue.every((item) => /^".*"$/.test(item))) {
return {
value: arrayValue.map((item) => item.slice(1, -1)),
type: 'string[]',
};
} else {
return { value: arrayValue, type: 'string[]' };
}
} else {
// Remove quotes
rawValue = rawValue.replace(/^"(.*)"$/, '$1');
Expand Down
17 changes: 13 additions & 4 deletions src/openSCADWorker.mts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@ async function exportFile(
params: OpenSCADWorkerInputMessage['params'],
fileType = 'stl'
): Promise<OpenSCADWorkerOutputMessage> {
const parameters = params.map(({ name, value }) => {
if (typeof value === 'string') {
const parameters = params.map(({ name, type, value }) => {
if (type === 'string' && typeof value === 'string') {
value = escapeShell(value);
} else if (type === 'number[]' && Array.isArray(value)) {
value = `[${value.join(',')}]`;
} else if (type === 'string[]' && Array.isArray(value)) {
value = `[${value.map((item) => escapeShell(item)).join(',')}]`;
}

return `-D${name}=${value}`;
});

Expand All @@ -53,9 +58,13 @@ async function preview(
params: OpenSCADWorkerInputMessage['params'],
fileType = 'stl'
): Promise<OpenSCADWorkerOutputMessage> {
const parameters = params.map(({ name, value }) => {
if (typeof value === 'string') {
const parameters = params.map(({ name, type, value }) => {
if (type === 'string' && typeof value === 'string') {
value = escapeShell(value);
} else if (type === 'number[]' && Array.isArray(value)) {
value = `[${value.join(',')}]`;
} else if (type === 'string[]' && Array.isArray(value)) {
value = `[${value.map((item) => escapeShell(item)).join(',')}]`;
}
return `-D${name}=${value}`;
});
Expand Down
Loading

0 comments on commit 36df006

Please sign in to comment.