summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven <steven.vasilogianis@gmail.com>2021-11-09 14:21:05 -0500
committerSteven <steven.vasilogianis@gmail.com>2021-11-09 14:21:05 -0500
commitb5a4d62a44f5066ebcf916cd91701ea145ba37d0 (patch)
treea87b3cc8d24a6222669e4a08d5608557db0030b3
parent4767a828663c3c4820d21c044ed94d2d15952bcd (diff)
More documentation; parse args with getopt instead of getopts (stole Andy's argument parsing code, he will never know)
-rwxr-xr-xshopenscad.sh306
1 files changed, 170 insertions, 136 deletions
diff --git a/shopenscad.sh b/shopenscad.sh
index 075290d..4e8f7d0 100755
--- a/shopenscad.sh
+++ b/shopenscad.sh
@@ -1,184 +1,218 @@
1#!/bin/bash 1#!/bin/bash
2# shopenscad.sh: parse a .scad file and generate an openscad command with all 2
3# its var=value's parameterized into -D options, which can be overriden with 3#set -x
4# shell variables. 4
5# 5OPENSCAD=${OPENSCAD:-"openscad"}
6# Usage examples: 6RUN=y
7# 7INTERACTIVE=
8# $ ./shopenscad.sh cubbies.scad 8PRINT_VARS=
9# openscad 'cubbies.scad' -D 'part="divider"' -D 'cubby_width=50' -D 'cubby_depth=180' -D 'cubby_divider_height=90' -D 'thickness=5' -D 'strut_thickness=5' -D 'tab_width=10' -D 'tab_padding=5' -D 'tab_tolerance=0.5' -o 'divider=50=180=90=5=5=10=5=0.5.stl' 9USER_OUTPUT_FILENAME=
10# [openscad output omitted] 10SCAD_FILE=
11# 11
12# (the openscad command is printed and then evaluated, outputing to the file 12help()
13# indicated after the -o flag) 13{
14# 14 cat <<EOF
15# You can also overwrite the variables parsed from your scad file by passing a 15$0: parse and execute OpenSCAD files, allowing default variables from input scad
16# shell variable with the same name: 16 to be overridden with values supplied from the shell. (The parsing of scad
17# 17 files is done from the shell mostly with sed, and is very primitive)
18# $ cubby_width=200 part=\"bottom\" ./shopenscad.sh cubbies.scad 18
19# openscad 'cubbies.scad' -D 'part="bottom"' -D 'cubby_width=200' -D 'cubby_depth=180' -D 'cubby_divider_height=90' -D 'thickness=5' -D 'strut_thickness=5' -D 'tab_width=10' -D 'tab_padding=5' -D 'tab_tolerance=0.5' -o 'bottom=200=180=90=5=5=10=5=0.5.stl' 19Usage: $0 [-h] [-n] [-p] [-i] [-o OUTPUT-FILENAME] INPUT.scad
20# [openscad output omitted] 20
21# 21 -h, --help display this help
22# Now we can easily generate multiple models: 22 -p, --print-vars print variables parsed from INPUT.scad
23# 23 -i, --interactive show output command and query for execution
24# $ for w in 250 300 350 400; do 24 -n, --no-act show output command, do not execute
25# > for p in '"divider"' '"bottom"'; do 25 -o, --output-filename Specify an output filename. The following variables are
26# > cubby_width="$w" part="$p" ./shopenscad.sh cubbies.scad 26 available to you:
27# > done 27
28# > done 28 \$VALUES - all values from INPUT.scad. This is the
29# [openscad output omitted] 29 default:
30 30 cube-15-10-5.stl
31openscad=${OPENSCAD:-"openscad"} 31
32 32 \$ALL - all variable names and values from INPUT.scad:
33# yes_eval=false 33 shape=cube,width=15,height=10,depth=5.stl
34# no_eval=false 34
35 35 Additionally, all variables parsed from INPUT.scad
36interactive=false 36 are available the associatve array $SCAD, e.g.:
37run=true 37 '\${SCAD[part]}.stl'
38print_vars=false 38
39user_output_filename= 39Usage examples:
40 40
41while getopts pino: opt; do 41 1) Run $OPENSCAD with default values from input scad file:
42 case $opt in 42
43 p) print_vars=true ;; # print variables that were parsed 43 $ $0 input.scad
44 i) interactive=true ;; # suppress interactive output -- do eval cmd 44
45 n) run=false ;; # do not eval cmd 45 2) You can override variables in the input file with variables passed in
46 o) user_output_filename="$OPTARG" ;; # override default output filename 46 through the shell; this will override "part" and "cubby_width"
47 esac 47 paramaters from input scad file. (Note that if the part is a string,
48done 48 you need to include quotes.):
49shift $(($OPTIND - 1)) 49
50scad_file="$*" 50 $ cubby_width=200 part='"bottom"' $0 input.scad
51 51
52if [ ! "$scad_file" ]; then 52
53 echo "$0: needs an input scad file" 53 3) Generate multiple models:
54 exit 1 54
55fi; 55 $ for w in 250 300 350 400; do
56 56 cubby_width="$w" part="bottom" $0 cubbies.scad
57function strip_comments () { 57 done
58 strip_multiline_comments 58EOF
59} 59}
60 60
61function strip_multiline_comments () { 61parse_options()
62{
63 OPTS=$(getopt \
64 --options 'hpino:' \
65 --longoptions 'help,print-vars,interactive,no-act,output-filename:' \
66 -- "$@")
67 eval set -- "$OPTS"
68 unset OPTS
69
70 if [ $# = 0 ]; then
71 help
72 exit
73 fi
74
75 while true; do
76 case "$1" in
77 -h | --help ) help; exit;;
78 -p | --print-vars ) PRINT_VARS=y;;
79 -i | --interactive ) INTERACTIVE=y;;
80 -n | --no-act ) RUN=;;
81 -o | --output-filename ) shift; USER_OUTPUT_FILENAME=$1;;
82 -- ) shift; break;;
83 esac
84 shift
85 done
86
87 SCAD_FILE="$*";
88 [ -f "$SCAD_FILE" ] || die "$0: Needs an input scad file"
89
90}
91
92die() { printf 'Error: %s\n' "$*" >&2; exit 1; }
93warn() { printf 'Warning: %s\n' "$*" >&2; }
94
95strip_multiline_comments () {
62 # https://stackoverflow.com/questions/13061785/remove-multi-line-comments 96 # https://stackoverflow.com/questions/13061785/remove-multi-line-comments
63 # https://stackoverflow.com/users/751863/steve 97 # https://stackoverflow.com/users/751863/steve
64 sed -r ':a; s%(.*)/\*.*\*/%\1%; ta; /\/\*/ !b; N; ba' 98 sed -r ':a; s%(.*)/\*.*\*/%\1%; ta; /\/\*/ !b; N; ba'
65} 99}
66 100
67function strip_trailing_semicolon () { 101strip_trailing_semicolon () {
68 sed -r 's/;$//' 102 sed -r 's/;$//'
69} 103}
70 104
71function strip_leading_spaces () { 105strip_leading_spaces () {
72 sed -r 's/^ +//' 106 sed -r 's/^ +//'
73} 107}
74 108
75function strip_trailing_spaces () { 109strip_trailing_spaces () {
76 sed -r 's/ +$//' 110 sed -r 's/ +$//'
77} 111}
78 112
79function strip_nonassignments () { 113strip_nonassignments () {
80 grep -e '^[A-Za-z0-9_]\+\s*=' 114 grep -e '^[A-Za-z0-9_]\+\s*='
81} 115}
82 116
83function chomp () { 117chomp () {
84 strip_leading_spaces |strip_trailing_spaces 118 strip_leading_spaces |strip_trailing_spaces
85} 119}
86 120
87function parse_variable () { 121parse_variable () {
88 #sed -r 's/^([a-zA-Z0-9_]+).*/\1/' 122 #sed -r 's/^([a-zA-Z0-9_]+).*/\1/'
89 sed -r 's/^([^=]+)=.*/\1/' 123 sed -r 's/^([^=]+)=.*/\1/'
90} 124}
91 125
92function parse_value () { 126parse_value () {
93 #sed -r 's/^.*?=\s*([^;]+);.*$/\1/' 127 #sed -r 's/^.*?=\s*([^;]+);.*$/\1/'
94 #sed -r 's/^[^=]+\s*=\s*([^;]+);.*$/\1/' 128 #sed -r 's/^[^=]+\s*=\s*([^;]+);.*$/\1/'
95 sed -r 's/.*=\s*([^;]+?).*/\1/' 129 sed -r 's/.*=\s*([^;]+?).*/\1/'
96} 130}
97 131
98function val_to_filename () { 132val_to_filename () {
99 echo "$1" |sed -r 's/"//g' |sed -r 's/ /_/g' 133 echo "$1" |sed -r 's/"//g' |sed -r 's/ /_/g'
100} 134}
101 135
102function strip_last_char () { 136strip_last_char () {
103 echo "$1" |sed -r 's/.$//' 137 echo "$1" |sed -r 's/.$//'
104} 138}
105 139
106function strip_after_hidden () { 140strip_after_hidden () {
107 echo "$1" |sed -n '/\/\* \[Hidden\] \*\//q;p' cubbies.scad 141 echo "$1" |sed -n '/\/\* \[Hidden\] \*\//q;p' cubbies.scad
108} 142}
109 143
110function strip_trailing () { 144strip_trailing () {
111 trailing="$1" 145 trailing="$1"
112 input="$2" 146 input="$2"
113 echo ${input%${trailing}} 147 echo ${input%${trailing}}
114} 148}
115 149
116output_params="" 150main()
117default_output_filename="" 151{
118all="" 152 parse_options "$@"
119values_only="" 153
120val_sep="-" 154 output_params=""
121var_sep="," 155 default_output_filename=""
122 156 ALL=""
123declare -A scad 157 VALUES=""
124 158 val_sep="-"
125while IFS= read -r line; do 159 var_sep=","
126 [ "$line" ] || continue; 160 declare -A SCAD
127 clean="$(echo -n "$line" |chomp)" 161
128 var=$(echo -n "$clean" |parse_variable |chomp) 162 while IFS= read -r line; do
129 163 [ "$line" ] || continue;
130 # use value provided on command line preferentially to any values in the .scad file 164 clean="$(echo -n "$line" |chomp)"
131 val="" 165 var=$(echo -n "$clean" |parse_variable |chomp)
132 if [[ -n "${!var}" ]]; then 166
133 val=${!var} 167 # use value provided on command line preferentially to any values in the .scad file
134 else 168 val=""
135 val=$(echo -n "$clean" |parse_value |chomp) 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]="$val"
177 output_params+="-D '$var=$val' "
178 VALUES+="$(val_to_filename "$val")${val_sep}"
179 ALL+="${var}=$(val_to_filename "$val")${var_sep}"
180 fi;
181 done < <(echo "$(cat "$SCAD_FILE")" |
182 strip_multiline_comments |strip_after_hidden |strip_nonassignments |strip_trailing_semicolon)
183
184 if [ "$PRINT_VARS" ]; then
185 for k in "${!SCAD[@]}"; do
186 echo ${k}=${SCAD[$k]}
187 done
188 exit
136 fi 189 fi
137 190
138 if [ "$var" ] && [ "$val" ]; then 191 ALL=$(strip_trailing "$var_sep" "$ALL")
139 scad[$var]="$val" 192 VALUES=$(strip_trailing "$val_sep" "$VALUES")
140 output_params+="-D '$var=$val' " 193
141 values_only+="$(val_to_filename "$val")${val_sep}" 194 default_output_filename="$(strip_trailing "-" "${VALUES}").stl"
142 all+="${var}=$(val_to_filename "$val")${var_sep}" 195 output_filename="$default_output_filename"
143 fi; 196 if [ "$USER_OUTPUT_FILENAME" ]; then
144done < <(echo "$(cat "$scad_file")" | 197 output_filename=$(echo $(eval "echo $USER_OUTPUT_FILENAME"))
145 strip_comments |strip_after_hidden |strip_nonassignments |strip_trailing_semicolon) 198 fi
146 199
147 200 openscad_str="$OPENSCAD '$SCAD_FILE' "$output_params" -o '$output_filename'"
148if $print_vars; then 201 echo "${openscad_str}"
149 echo The following variables have been parsed from ${scad_file}: 202
150 for k in "${!scad[@]}"; do 203 [ ! "$RUN" ] && [ ! "$INTERACTIVE" ] && exit
151 echo ${k}=${scad[$k]} 204
152 done; echo 205 if [ "$INTERACTIVE" ]; then
153fi 206 eval_prompt="Evaulate openscad command? (type y for yes, anything else to exit): "
154 207 read -p "$eval_prompt" -n1 yes_eval_read
155#all=$(strip_trailing "$val_sep" "$all") 208 echo
156values_only=$(strip_trailing "$val_sep" "$values_only") 209 case "$yes_eval_read" in
157 210 [Yy]) RUN=y ;; # still true
158default_output_filename="$(strip_trailing "-" "${values_only}").stl" 211 *) RUN=;;
159output_filename="$default_output_filename" 212 esac
160if [ "$user_output_filename" ]; then 213 fi
161 output_filename=$(echo $(eval "echo $user_output_filename")) 214
162fi 215 [ "$RUN" ] && eval "$(echo "$openscad_str")"
163 216}
164#openscad_str="$openscad "$scad_file" "$output_params" -o $(strip_trailing "-" "${values_only}").stl" 217
165openscad_str="$openscad '$scad_file' "$output_params" -o '$output_filename'" 218main "$@"
166#openscad_str="$openscad '$scad_file' "$output_params" -o '${all}.stl'"
167
168# ${open_filename//'/'\\''}
169
170
171echo "${openscad_str}"
172$print_vars || ! $run && ! $interactive && exit
173
174if $interactive; then
175 eval_prompt="Evaulate openscad command? (type y for yes, anything else to exit): "
176 read -p "$eval_prompt" -n1 yes_eval_read
177 echo
178 case "$yes_eval_read" in
179 [Yy]) run=true ;; # still true
180 *) run=false ;;
181 esac
182fi
183
184$run && eval "$(echo "$openscad_str")"