From 2ea8f9a13ae0309cc595cbb1316acef52af4afa8 Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 9 Nov 2021 14:21:05 -0500 Subject: More documentation; parse args with getopt instead of getopts (stole Andy's argument parsing code, he will never know) --- shopenscad.sh | 306 ++++++++++++++++++++++++++++++++-------------------------- 1 file 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 @@ #!/bin/bash -# shopenscad.sh: parse a .scad file and generate an openscad command with all -# its var=value's parameterized into -D options, which can be overriden with -# shell variables. -# -# Usage examples: -# -# $ ./shopenscad.sh cubbies.scad -# 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' -# [openscad output omitted] -# -# (the openscad command is printed and then evaluated, outputing to the file -# indicated after the -o flag) -# -# You can also overwrite the variables parsed from your scad file by passing a -# shell variable with the same name: -# -# $ cubby_width=200 part=\"bottom\" ./shopenscad.sh cubbies.scad -# 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' -# [openscad output omitted] -# -# Now we can easily generate multiple models: -# -# $ for w in 250 300 350 400; do -# > for p in '"divider"' '"bottom"'; do -# > cubby_width="$w" part="$p" ./shopenscad.sh cubbies.scad -# > done -# > done -# [openscad output omitted] - -openscad=${OPENSCAD:-"openscad"} - -# yes_eval=false -# no_eval=false - -interactive=false -run=true -print_vars=false -user_output_filename= - -while getopts pino: opt; do - case $opt in - p) print_vars=true ;; # print variables that were parsed - i) interactive=true ;; # suppress interactive output -- do eval cmd - n) run=false ;; # do not eval cmd - o) user_output_filename="$OPTARG" ;; # override default output filename - esac -done -shift $(($OPTIND - 1)) -scad_file="$*" - -if [ ! "$scad_file" ]; then - echo "$0: needs an input scad file" - exit 1 -fi; - -function strip_comments () { - strip_multiline_comments + +#set -x + +OPENSCAD=${OPENSCAD:-"openscad"} +RUN=y +INTERACTIVE= +PRINT_VARS= +USER_OUTPUT_FILENAME= +SCAD_FILE= + +help() +{ + cat <&2; exit 1; } +warn() { printf 'Warning: %s\n' "$*" >&2; } + +strip_multiline_comments () { # https://stackoverflow.com/questions/13061785/remove-multi-line-comments # https://stackoverflow.com/users/751863/steve sed -r ':a; s%(.*)/\*.*\*/%\1%; ta; /\/\*/ !b; N; ba' } -function strip_trailing_semicolon () { +strip_trailing_semicolon () { sed -r 's/;$//' } -function strip_leading_spaces () { +strip_leading_spaces () { sed -r 's/^ +//' } -function strip_trailing_spaces () { +strip_trailing_spaces () { sed -r 's/ +$//' } -function strip_nonassignments () { +strip_nonassignments () { grep -e '^[A-Za-z0-9_]\+\s*=' } -function chomp () { +chomp () { strip_leading_spaces |strip_trailing_spaces } -function parse_variable () { +parse_variable () { #sed -r 's/^([a-zA-Z0-9_]+).*/\1/' sed -r 's/^([^=]+)=.*/\1/' } -function parse_value () { +parse_value () { #sed -r 's/^.*?=\s*([^;]+);.*$/\1/' #sed -r 's/^[^=]+\s*=\s*([^;]+);.*$/\1/' sed -r 's/.*=\s*([^;]+?).*/\1/' } -function val_to_filename () { +val_to_filename () { echo "$1" |sed -r 's/"//g' |sed -r 's/ /_/g' } -function strip_last_char () { +strip_last_char () { echo "$1" |sed -r 's/.$//' } -function strip_after_hidden () { +strip_after_hidden () { echo "$1" |sed -n '/\/\* \[Hidden\] \*\//q;p' cubbies.scad } -function strip_trailing () { +strip_trailing () { trailing="$1" input="$2" echo ${input%${trailing}} } -output_params="" -default_output_filename="" -all="" -values_only="" -val_sep="-" -var_sep="," - -declare -A scad - -while IFS= read -r line; do - [ "$line" ] || continue; - clean="$(echo -n "$line" |chomp)" - var=$(echo -n "$clean" |parse_variable |chomp) - - # use value provided on command line preferentially to any values in the .scad file - val="" - if [[ -n "${!var}" ]]; then - val=${!var} - else - val=$(echo -n "$clean" |parse_value |chomp) +main() +{ + parse_options "$@" + + output_params="" + default_output_filename="" + ALL="" + VALUES="" + val_sep="-" + var_sep="," + declare -A SCAD + + while IFS= read -r line; do + [ "$line" ] || continue; + clean="$(echo -n "$line" |chomp)" + var=$(echo -n "$clean" |parse_variable |chomp) + + # use value provided on command line preferentially to any values in the .scad file + val="" + if [[ -n "${!var}" ]]; then + val=${!var} + else + val=$(echo -n "$clean" |parse_value |chomp) + fi + + if [ "$var" ] && [ "$val" ]; then + SCAD[$var]="$val" + output_params+="-D '$var=$val' " + VALUES+="$(val_to_filename "$val")${val_sep}" + ALL+="${var}=$(val_to_filename "$val")${var_sep}" + fi; + done < <(echo "$(cat "$SCAD_FILE")" | + strip_multiline_comments |strip_after_hidden |strip_nonassignments |strip_trailing_semicolon) + + if [ "$PRINT_VARS" ]; then + for k in "${!SCAD[@]}"; do + echo ${k}=${SCAD[$k]} + done + exit fi - if [ "$var" ] && [ "$val" ]; then - scad[$var]="$val" - output_params+="-D '$var=$val' " - values_only+="$(val_to_filename "$val")${val_sep}" - all+="${var}=$(val_to_filename "$val")${var_sep}" - fi; -done < <(echo "$(cat "$scad_file")" | - strip_comments |strip_after_hidden |strip_nonassignments |strip_trailing_semicolon) - - -if $print_vars; then - echo The following variables have been parsed from ${scad_file}: - for k in "${!scad[@]}"; do - echo ${k}=${scad[$k]} - done; echo -fi - -#all=$(strip_trailing "$val_sep" "$all") -values_only=$(strip_trailing "$val_sep" "$values_only") - -default_output_filename="$(strip_trailing "-" "${values_only}").stl" -output_filename="$default_output_filename" -if [ "$user_output_filename" ]; then - output_filename=$(echo $(eval "echo $user_output_filename")) -fi - -#openscad_str="$openscad "$scad_file" "$output_params" -o $(strip_trailing "-" "${values_only}").stl" -openscad_str="$openscad '$scad_file' "$output_params" -o '$output_filename'" -#openscad_str="$openscad '$scad_file' "$output_params" -o '${all}.stl'" - -# ${open_filename//'/'\\''} - - -echo "${openscad_str}" -$print_vars || ! $run && ! $interactive && exit - -if $interactive; then - eval_prompt="Evaulate openscad command? (type y for yes, anything else to exit): " - read -p "$eval_prompt" -n1 yes_eval_read - echo - case "$yes_eval_read" in - [Yy]) run=true ;; # still true - *) run=false ;; - esac -fi - -$run && eval "$(echo "$openscad_str")" + ALL=$(strip_trailing "$var_sep" "$ALL") + VALUES=$(strip_trailing "$val_sep" "$VALUES") + + default_output_filename="$(strip_trailing "-" "${VALUES}").stl" + output_filename="$default_output_filename" + if [ "$USER_OUTPUT_FILENAME" ]; then + output_filename=$(echo $(eval "echo $USER_OUTPUT_FILENAME")) + fi + + openscad_str="$OPENSCAD '$SCAD_FILE' "$output_params" -o '$output_filename'" + echo "${openscad_str}" + + [ ! "$RUN" ] && [ ! "$INTERACTIVE" ] && exit + + if [ "$INTERACTIVE" ]; then + eval_prompt="Evaulate openscad command? (type y for yes, anything else to exit): " + read -p "$eval_prompt" -n1 yes_eval_read + echo + case "$yes_eval_read" in + [Yy]) RUN=y ;; # still true + *) RUN=;; + esac + fi + + [ "$RUN" ] && eval "$(echo "$openscad_str")" +} + +main "$@" -- cgit v1.2.3