summaryrefslogtreecommitdiff
path: root/shopenscad.sh
diff options
context:
space:
mode:
Diffstat (limited to 'shopenscad.sh')
-rwxr-xr-xshopenscad.sh238
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
5OPENSCAD=${OPENSCAD:-"openscad"}
6RUN=y
7INTERACTIVE=
8PRINT_VARS=
9USER_OUTPUT_FILENAME=
10SCAD_FILE=
11SHELL_SKEL=
12
13help()
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
20Usage: $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
42Usage 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
61EOF
62}
63
64parse_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
95die() { printf 'Error: %s\n' "$*" >&2; exit 1; }
96warn() { printf 'Warning: %s\n' "$*" >&2; }
97
98strip_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
104strip_trailing_semicolon () {
105 sed -r 's/;$//'
106}
107
108strip_leading_spaces () {
109 sed -r 's/^ +//'
110}
111
112strip_trailing_spaces () {
113 sed -r 's/ +$//'
114}
115
116strip_nonassignments () {
117 grep -e '^[A-Za-z0-9_]\+\s*='
118}
119
120chomp () {
121 strip_leading_spaces |strip_trailing_spaces
122}
123
124parse_variable () {
125 #sed -r 's/^([a-zA-Z0-9_]+).*/\1/'
126 sed -r 's/^([^=]+)=.*/\1/'
127}
128
129parse_value () {
130 #sed -r 's/^.*?=\s*([^;]+);.*$/\1/'
131 #sed -r 's/^[^=]+\s*=\s*([^;]+);.*$/\1/'
132 sed -r 's/.*=\s*([^;]+?).*/\1/'
133}
134
135val_to_filename () {
136 echo "$1" |sed -r 's/"//g' |sed -r 's/ /_/g'
137}
138
139strip_after_hidden () {
140 sed -n '/\/\* \[Hidden\] \*\//q;p' "$1"
141}
142
143strip_trailing () {
144 trailing="$1"
145 input="$2"
146 echo ${input%${trailing}}
147}
148
149main()
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
202shopenscad_cmd="$0 $SCAD_FILE "
203export \$(echo \$(\$shopenscad_cmd -p))
204${all_vars}
205\$shopenscad_cmd
206EOF
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
237main "$@"
238#parse_options "$@"