diff options
author | Steven <steven.vasilogianis@gmail.com> | 2022-03-14 17:14:35 -0400 |
---|---|---|
committer | Steven <steven.vasilogianis@gmail.com> | 2022-03-14 17:14:35 -0400 |
commit | 2ca923d6b5ca7c8f90eaf1371a5ded60b62144fb (patch) | |
tree | a2056c6006ca02196150c2d33b62ef4506b56267 /shopenscad.sh |
initial public release
Diffstat (limited to 'shopenscad.sh')
-rwxr-xr-x | shopenscad.sh | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/shopenscad.sh b/shopenscad.sh new file mode 100755 index 0000000..3c71b1f --- /dev/null +++ b/shopenscad.sh | |||
@@ -0,0 +1,238 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | #set -x | ||
4 | |||
5 | OPENSCAD=${OPENSCAD:-"openscad"} | ||
6 | RUN=y | ||
7 | INTERACTIVE= | ||
8 | PRINT_VARS= | ||
9 | USER_OUTPUT_FILENAME= | ||
10 | SCAD_FILE= | ||
11 | SHELL_SKEL= | ||
12 | |||
13 | help() | ||
14 | { | ||
15 | cat <<EOF | ||
16 | $0: parse and execute OpenSCAD files, allowing default variables from input scad | ||
17 | to be overridden with values supplied from the shell. (The parsing of scad | ||
18 | files is done from the shell mostly with sed, and is very primitive) | ||
19 | |||
20 | Usage: $0 [-h] [-n] [-p] [-i] [-o OUTPUT-FILENAME] INPUT.scad | ||
21 | |||
22 | -h, --help display this help | ||
23 | -p, --print-vars print variables parsed from INPUT.scad | ||
24 | -i, --interactive show output command and query for execution | ||
25 | -n, --no-act show output command, do not execute | ||
26 | -s, --shell-skel output a skeleton shell script for generating models | ||
27 | -o, --output-filename Specify an output filename. The following variables are | ||
28 | available to you: | ||
29 | |||
30 | \$VALUES - all values from INPUT.scad. This is the | ||
31 | default (-o '\${VALUES}.stl'): | ||
32 | cube-15-10-5.stl | ||
33 | |||
34 | \$ALL - all variable names and values from INPUT.scad | ||
35 | (-o '\${ALL}.stl'): | ||
36 | shape=cube,width=15,height=10,depth=5.stl | ||
37 | |||
38 | Additionally, all variables parsed from INPUT.scad | ||
39 | are available in the associatve array $SCAD, e.g.: | ||
40 | -o '\${SCAD[part]}.stl' | ||
41 | |||
42 | Usage examples: | ||
43 | |||
44 | 1) Run $OPENSCAD with default values from input scad file: | ||
45 | |||
46 | $ $0 input.scad | ||
47 | |||
48 | 2) You can override variables in the input file with variables passed in | ||
49 | through the shell; this will override "part" and "cubby_width" | ||
50 | paramaters from input scad file. (Note that if the part is a string, | ||
51 | you need to include quotes.): | ||
52 | |||
53 | $ cubby_width=200 part='"bottom"' $0 input.scad | ||
54 | |||
55 | |||
56 | 3) Generate multiple models: | ||
57 | |||
58 | $ for w in 250 300 350 400; do | ||
59 | cubby_width="$w" part="bottom" $0 cubbies.scad | ||
60 | done | ||
61 | EOF | ||
62 | } | ||
63 | |||
64 | parse_options() | ||
65 | { | ||
66 | OPTS=$(getopt \ | ||
67 | --options 'hpinso:' \ | ||
68 | --longoptions 'help,print-vars,interactive,no-act,shell-skel,output-filename:' \ | ||
69 | -- "$@") | ||
70 | eval set -- "$OPTS" | ||
71 | unset OPTS | ||
72 | |||
73 | if [ $# = 0 ]; then | ||
74 | help | ||
75 | exit | ||
76 | fi | ||
77 | |||
78 | while true; do | ||
79 | case "$1" in | ||
80 | -h | --help ) help; exit;; | ||
81 | -p | --print-vars ) PRINT_VARS=y;; | ||
82 | -i | --interactive ) INTERACTIVE=y;; | ||
83 | -n | --no-act ) RUN=;; | ||
84 | -s | --shell-skel ) SHELL_SKEL=y;; | ||
85 | -o | --output-filename ) shift; USER_OUTPUT_FILENAME=$1;; | ||
86 | -- ) shift; break;; | ||
87 | esac | ||
88 | shift | ||
89 | done | ||
90 | |||
91 | SCAD_FILE="$*"; | ||
92 | [ -f "$SCAD_FILE" ] || die "$0: Needs an input scad file" | ||
93 | } | ||
94 | |||
95 | die() { printf 'Error: %s\n' "$*" >&2; exit 1; } | ||
96 | warn() { printf 'Warning: %s\n' "$*" >&2; } | ||
97 | |||
98 | strip_multiline_comments () { | ||
99 | # https://stackoverflow.com/questions/13061785/remove-multi-line-comments | ||
100 | # https://stackoverflow.com/users/751863/steve | ||
101 | sed -r ':a; s%(.*)/\*.*\*/%\1%; ta; /\/\*/ !b; N; ba' | ||
102 | } | ||
103 | |||
104 | strip_trailing_semicolon () { | ||
105 | sed -r 's/;$//' | ||
106 | } | ||
107 | |||
108 | strip_leading_spaces () { | ||
109 | sed -r 's/^ +//' | ||
110 | } | ||
111 | |||
112 | strip_trailing_spaces () { | ||
113 | sed -r 's/ +$//' | ||
114 | } | ||
115 | |||
116 | strip_nonassignments () { | ||
117 | grep -e '^[A-Za-z0-9_]\+\s*=' | ||
118 | } | ||
119 | |||
120 | chomp () { | ||
121 | strip_leading_spaces |strip_trailing_spaces | ||
122 | } | ||
123 | |||
124 | parse_variable () { | ||
125 | #sed -r 's/^([a-zA-Z0-9_]+).*/\1/' | ||
126 | sed -r 's/^([^=]+)=.*/\1/' | ||
127 | } | ||
128 | |||
129 | parse_value () { | ||
130 | #sed -r 's/^.*?=\s*([^;]+);.*$/\1/' | ||
131 | #sed -r 's/^[^=]+\s*=\s*([^;]+);.*$/\1/' | ||
132 | sed -r 's/.*=\s*([^;]+?).*/\1/' | ||
133 | } | ||
134 | |||
135 | val_to_filename () { | ||
136 | echo "$1" |sed -r 's/"//g' |sed -r 's/ /_/g' | ||
137 | } | ||
138 | |||
139 | strip_after_hidden () { | ||
140 | sed -n '/\/\* \[Hidden\] \*\//q;p' "$1" | ||
141 | } | ||
142 | |||
143 | strip_trailing () { | ||
144 | trailing="$1" | ||
145 | input="$2" | ||
146 | echo ${input%${trailing}} | ||
147 | } | ||
148 | |||
149 | main() | ||
150 | { | ||
151 | parse_options "$@" | ||
152 | |||
153 | output_params="" | ||
154 | default_output_filename="" | ||
155 | ALL="" | ||
156 | VALUES="" | ||
157 | val_sep="-" | ||
158 | var_sep="," | ||
159 | declare -A SCAD | ||
160 | declare -a scad_var_order | ||
161 | |||
162 | while IFS= read -r line; do | ||
163 | [ "$line" ] || continue; | ||
164 | clean="$(echo -n "$line" |chomp)" | ||
165 | var=$(echo -n "$clean" |parse_variable |chomp) | ||
166 | |||
167 | # use value provided on command line preferentially to any values in the .scad file | ||
168 | val="" | ||
169 | if [[ -n "${!var}" ]]; then | ||
170 | val=${!var} | ||
171 | else | ||
172 | val=$(echo -n "$clean" |parse_value |chomp) | ||
173 | fi | ||
174 | |||
175 | if [ "$var" ] && [ "$val" ]; then | ||
176 | scad_var_order+=($var); | ||
177 | SCAD[$var]="$val" | ||
178 | output_params+="-D '$var=$val' " | ||
179 | VALUES+="$(val_to_filename "$val")${val_sep}" | ||
180 | ALL+="${var}=$(val_to_filename "$val")${var_sep}" | ||
181 | fi; | ||
182 | done < <(strip_after_hidden $SCAD_FILE | \ | ||
183 | strip_multiline_comments |strip_nonassignments |strip_trailing_semicolon) | ||
184 | |||
185 | if [ "$PRINT_VARS" ]; then | ||
186 | for k in "${scad_var_order[@]}"; do | ||
187 | # Make sure quotes surround openscad strings | ||
188 | case "${SCAD[$k]:0:1}" in | ||
189 | \" ) line="${k}='${SCAD[$k]}'";; | ||
190 | \' ) line=${k}="\"${SCAD[$k]}\"";; | ||
191 | * ) line="${k}=${SCAD[$k]}";; | ||
192 | esac | ||
193 | echo $line | ||
194 | done | ||
195 | exit | ||
196 | fi | ||
197 | |||
198 | if [ "$SHELL_SKEL" ]; then | ||
199 | all_vars=$($0 $SCAD_FILE -p |sed -e 's/^/# /') | ||
200 | cat <<EOF | ||
201 | #!/bin/bash | ||
202 | shopenscad_cmd="$0 $SCAD_FILE " | ||
203 | export \$(echo \$(\$shopenscad_cmd -p)) | ||
204 | ${all_vars} | ||
205 | \$shopenscad_cmd | ||
206 | EOF | ||
207 | exit; | ||
208 | fi; | ||
209 | |||
210 | ALL=$(strip_trailing "$var_sep" "$ALL") | ||
211 | VALUES=$(strip_trailing "$val_sep" "$VALUES") | ||
212 | |||
213 | default_output_filename="${VALUES}.stl" | ||
214 | output_filename="$default_output_filename" | ||
215 | if [ "$USER_OUTPUT_FILENAME" ]; then | ||
216 | output_filename=$(echo $(eval "echo $USER_OUTPUT_FILENAME")) | ||
217 | fi | ||
218 | |||
219 | openscad_str="$OPENSCAD '$SCAD_FILE' "$output_params" -o '$output_filename'" | ||
220 | echo "${openscad_str}" | ||
221 | |||
222 | [ ! "$RUN" ] && [ ! "$INTERACTIVE" ] && exit | ||
223 | |||
224 | if [ "$INTERACTIVE" ]; then | ||
225 | eval_prompt="Evaulate openscad command? (type y for yes, anything else to exit): " | ||
226 | read -p "$eval_prompt" -n1 yes_eval_read | ||
227 | echo | ||
228 | case "$yes_eval_read" in | ||
229 | [Yy]) RUN=y ;; # still true | ||
230 | *) RUN=;; | ||
231 | esac | ||
232 | fi | ||
233 | |||
234 | [ "$RUN" ] && eval "$(echo "$openscad_str")" | ||
235 | } | ||
236 | |||
237 | main "$@" | ||
238 | #parse_options "$@" | ||