123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- #!/bin/sh
- #shellcheck disable=SC2039
-
-
- CHARMENU_FILE="${CHARMENU_FILE:-}"
-
-
- charmenu() {
- #
- # Present "1-char-menu" (but actually N-char) or its parts
- #
- # Usage:
- # CHARMENU_FILE=/path/to/file
- # charmenu [options] full [ARG]...
- # charmenu [options] items
- # charmenu [options] prompt
- # charmenu [options] has ITEM
- #
- # Read file in $CHARMENU_FILE and display either `full`
- # menu, `items` menu (e.g. "y,n,q,?") or just `prompt`.
- #
- # Options:
- #
- # -f FILE, --file FILE Read contents of menu freom FILE
- # instead of variable `$CHARMENU_FILE`.
- #
- # -p PROMPT, --prompt PROMPT Set prompt string to PROMPT.
- # If PROMPT contains '%s', it will be replaced by 'items'
- # menu (eg. "y,n,q"). Note that you most probably want
- # to include space as last character. Default: "What
- # next [%s]? ".
- #
- # -i, --ignore-case Ignore case of user reply. Default:
- # case is respected.
- #
- # -d DLM, --delimiter DLM Use delimiter DLM when printing
- # 'items' menu. Default: "," (comma).
- #
- # Format of menu file is one item per line, where item is
- # delimited from its description by single colon. Leading
- # and trailing spaces and spaces around the colon are
- # stripped.
- #
- # Simple example menu file:
- #
- # a: abort
- # r: retry
- # f: fail
- #
- # You can use printf symbols like `%s` in menu and then
- # call `charmenu full arg1 arg2...` to have your arguments
- # expanded in the full menu. More fleshed out example:
- #
- # . "$(sfpath)" || exit 3
- # shellfu import charmenu
- # shellfu import pretty
- #
- # cat <<EOM >menu
- # r: re-run test %s
- # c: clean screen
- # d: download results to %s
- # q: quit
- # EOM
- #
- # CHARMENU_FILE=menu
- # running=true
- # while $running; do
- # charmenu full "mytest" "some storage"
- # read -r response
- # case $response in
- # r) rerun_test ;;
- # c) reset ;;
- # d) download_results ;;
- # q) running=false ;;
- # *) warn "invalid response: $response"
- # esac
- # done
- # clean_up
- #
- # `charmenu has ITEM` exits with zero if ITEM is a valid
- # menu item. With abort/retry/fail example above, calling
- # `if charmenu has a; echo OK; fi` would print "OK"..
- #
- local mfile # path to menu file
- local prompt # prompt text
- local delim # delimiter (in 'items' menu)
- local cmd # command do execute
- local cases # "-i" in case-insensitive mode
- local menu # loaded menu text
- local alist # loaded list of items
- mfile=$CHARMENU_FILE
- prompt="What next [%s]? "
- delim=,
- while true; do case $1 in
- -d|--delimiter) delim="$2"; shift 2 || return 2 ;;
- -f|--file) mfile="$2"; shift 2 || return 2 ;;
- -i|--ignore-case) cases="-i"; shift ;;
- -p|--prompt) prompt="$2"; shift 2 || return 2 ;;
- full|items|prompt|has) cmd=$1; shift; break ;;
- *) mkusage "full [PRINTF_ARG...]" \
- "items [DELIM]" \
- "prompt [PRINTF_FMT]" \
- "has ITEM" ;;
- esac done
- menu="$(cat "$mfile")"
- alist="$(echo "$menu" | cut -d: -f1 | sed -re 's/^ +//; s/ +$//')"
- #shellcheck disable=SC2059
- case $cmd in
- full) # print the full menu, with any printf notation expanded
- printf "$menu\n" "$@"
- ;;
- items) # print just the list of actions
- echo "$alist" paste -sd"$delim"
- ;;
- prompt) # print prompt for user
- printf "$prompt" "$(charmenu items)"
- ;;
- has) # check if response is valid ("on the menu")
- local res="$1"
- test -n "$res" || return 1 # "" is not valid
- echo "$alist" | grep $cases -e "^$res$"
- return $?
- ;;
- esac
- }
|