X-Git-Url: http://git.tuebingen.mpg.de/?p=gsu.git;a=blobdiff_plain;f=subcommand;h=1b204e0dc3abe0f31ab8de41b6f148acfb6ec0cf;hp=a07f4145c69adb6fa319dbdaa9c97e3b0a2d5cde;hb=refs%2Fheads%2Fpu;hpb=e08a602e71ba1f9c9bb8e1c493cb4109fc22e952 diff --git a/subcommand b/subcommand index a07f414..d37481c 100644 --- a/subcommand +++ b/subcommand @@ -96,11 +96,12 @@ gsu_check_arg_count() # [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c" gsu_getopts() { - local i c tab=' ' cr=' + local -i i + local c c1 c2 tab=' ' cr=' ' gsu_check_arg_count $# 1 1 - if (($ret < 0)); then + if ((ret < 0)); then gsu_err_msg exit 1 fi @@ -126,7 +127,7 @@ gsu_getopts() result="local _gsu_getopts_opt" for ((i=0; i < ${#1}; i++)); do c1=${1:$i:1} - c2=${1:$(($i + 1)):1} + c2=${1:$((i + 1)):1} result+=" o_$c1=" if [[ "$c2" = ":" ]]; then let i++ @@ -141,7 +142,7 @@ gsu_getopts() " for ((i=0; i < ${#1}; i++)); do c1=${1:$i:1} - c2=${1:$(($i + 1)):1} + c2=${1:$((i + 1)):1} result+="$tab$tab$c1) o_$c1=" if [[ "$c2" = ":" ]]; then result+="\"\$OPTARG\"" @@ -167,26 +168,33 @@ gsu_getopts() _gsu_print_available_commands() { local cmd cmds - local -i count=0 + local -i maxlen=0 cols width=80 count=0 + result=$(stty size 2>/dev/null) + if (($? == 0)); then + gsu_is_a_number "${result#* }" + ((ret >= 0)) && ((result > 0)) && width=$result + fi _gsu_available_commands - cmds="$result" - printf 'Available commands:\n' + cmds=$result + for cmd in $cmds; do + ((${#cmd} > maxlen)) && maxlen=${#cmd} + done + let maxlen++ + ((width < maxlen)) && cols=1 || cols=$((width / maxlen)) + printf 'Available commands:' for cmd in $cmds; do - printf '%s' "$cmd" + ((count % cols == 0)) && printf '\n' + printf '%-*s' $maxlen $cmd let ++count - if (($count % 4)); then - printf '\t' - ((${#cmd} < 8)) && printf '\t' - else - printf '\n' - fi done printf '\n' } # Print all options of the given optstring to stdout if the word in the current # command line begins with a hyphen character. +# +# Returns 0 if the current word does not start with a hyphen, one otherwise. gsu_complete_options() { local opts="$1" cword="$2" cur opt @@ -198,18 +206,18 @@ gsu_complete_options() ret=0 [[ ! "$cur" == -* ]] && return - ret=0 for ((i=0; i < ${#opts}; i++)); do opt="${opts:$i:1}" [[ "$opt" == ":" ]] && continue printf "%s" "-$opt " - let ret++ done + ret=1 } +declare -A _gsu_help_text=() # indexed by autocmd com_prefs_options='e' -_gsu_prefs_txt=" +_gsu_help_text['prefs']=' Print the current preferences. Usage: prefs [-e] @@ -217,7 +225,7 @@ Usage: prefs [-e] If -e is given, the config file is opened with the default editor. Without options, the command prints out a list of all config variables, together with their current value and the default value. -" +' com_prefs() { @@ -225,9 +233,9 @@ com_prefs() gsu_getopts "$com_prefs_options" eval "$result" - (($ret < 0)) && return + ((ret < 0)) && return gsu_check_arg_count $# 0 0 - (($ret < 0)) && return + ((ret < 0)) && return if [[ "$o_e" == "true" ]]; then ret=-$E_GSU_MKDIR @@ -236,7 +244,7 @@ com_prefs() (($? != 0)) && return ret=-$E_GSU_EDITOR result="${EDITOR:-vi}" - "$result" "$conf" + "$result" $conf (($? != 0)) && return ret=$GSU_SUCCESS return @@ -255,7 +263,7 @@ com_prefs() printf "# optional" ;; esac - printf "%s: %s" "$option_type" "$description" + printf " %s: %s" "$option_type" "$description" if [[ "$required" != "yes" && "$required" != "true" ]]; then printf " [%s]" "$default_value" fi @@ -288,12 +296,12 @@ complete_man() [[ "$result" == 'm' ]] && printf 'roff\ntext\nhtml\n' } -_gsu_man_txt=' +_gsu_help_text['man']=' Print the manual. Usage: man [-m ] [-b ] --m: Set output format (text, roff or html). Default: text. +-m: Set output format (text, roff or html). Default: roff. -b: Use the specified browser. Implies html mode. If stdout is not associated with a terminal device, the command @@ -309,9 +317,6 @@ file is displayed as a page in the web browser. If -b is not given, the command stored in the $BROWSER environment variable is executed with the path to the temporary file as an argument. If $BROWSER is unset, elinks(1) is assumed. - -It is recommended to specify the output format with -m as the default -mode might change in future versions of gsu. ' _gsu_read_line() @@ -376,7 +381,7 @@ _gsu_roffify_maindoc() fi if [[ "${line:0:1}" == "$TAB" ]]; then # example _gsu_change_roffify_state 'state' 'example' - printf '%s\n' "$line" + _gsu_print_protected_roff_line "$line" line="$next_line" continue fi @@ -453,14 +458,17 @@ _gsu_roffify_cmds() done } -_gsu_roffify_autocmd() +_gsu_roffify_autocmds() { - local cmd="$1" help_txt="$2" + local cmd help_txt - { - printf 'com_%s()\n' "$cmd" - sed -e 's/^/## /g' <<< "$help_txt" - } | _gsu_roffify_cmds + for cmd in "${!_gsu_help_text[@]}"; do + help_txt="${_gsu_help_text["$cmd"]}" + { + printf 'com_%s()\n' "$cmd" + sed -e 's/^/## /g' <<< "$help_txt" + } | _gsu_roffify_cmds + done } _gsu_roff_man() @@ -482,10 +490,7 @@ EOF printf '\n.SH "GENERIC SUBCOMMANDS"\n' printf 'The following commands are automatically created by gsu\n' - _gsu_roffify_autocmd "help" "$_gsu_help_txt" - _gsu_roffify_autocmd "man" "$_gsu_man_txt" - _gsu_roffify_autocmd "prefs" "$_gsu_prefs_txt" - _gsu_roffify_autocmd "complete" "$_gsu_complete_txt" + _gsu_roffify_autocmds printf '\n.SH "LIST OF SUBCOMMANDS"\n' printf 'Each command has its own set of options as described below.\n' @@ -522,7 +527,7 @@ com_man() o_m='html' browser="$o_b" elif [[ -z "$o_m" ]]; then - o_m='text' + o_m='roff' fi _gsu_isatty && isatty='true' || isatty='false' @@ -597,7 +602,7 @@ com_man() _gsu_available_commands for com in $result; do num=${#com} - (($num < 4)) && num=4 + ((num < 4)) && num=4 echo "${minus_signs:0:$num}" echo "$com" echo "${minus_signs:0:$num}" @@ -608,15 +613,18 @@ com_man() ret=$GSU_SUCCESS } -_gsu_help_txt=" +_gsu_help_text['help']=' Print online help. -Usage: help [command] +Usage: help [-a] [command] Without arguments, print the list of available commands. Otherwise, -print the help text for the given command." +print the help text for the given command. + +-a: Also show the help of automatic commands. Ignored if a command +is given.' -_gsu_complete_txt=" +_gsu_help_text['complete']=' Command line completion. Usage: complete [ ...] @@ -628,11 +636,16 @@ completion. If at least one argument is given, all possible completions are written to stdout. This can be used from the completion function of the subcommand. -" +' +com_help_options='a' com_help() { - local ere tab=' ' + local ere tab=' ' txt + + gsu_getopts "$com_help_options" + eval "$result" + ((ret < 0)) && return _gsu_get_command_regex ere="$result" @@ -641,10 +654,15 @@ com_help() gsu_short_msg "### $gsu_name -- $gsu_banner_txt ###" _gsu_usage 2>&1 { - printf "com_help()\n%s" "$_gsu_help_txt" | head -n 4; echo "--" - printf "com_man()\n%s" "$_gsu_man_txt" | head -n 4; echo "--" - printf "com_prefs()\n%s" "$_gsu_prefs_txt" | head -n 4; echo "--" - printf "com_complete()\n%s" "$_gsu_complete_txt" | head -n 4; echo "--" + if [[ "$o_a" == 'true' ]]; then + _gsu_mfcb() { printf '%s\n' "$2"; } + for cmd in "${!_gsu_help_text[@]}"; do + printf "com_%s()" "$cmd" + txt="${_gsu_help_text["$cmd"]}" + mapfile -n 3 -c 1 -C _gsu_mfcb <<< "$txt" + printf -- '--\n' + done + fi grep -EA 2 "$ere" "$0" } | grep -v -- '--' \ | sed -En "/$ere/"'!d @@ -666,33 +684,33 @@ com_help() y/\n/'"$tab"'/ # and print the sucker - p' - echo - echo "# Try $gsu_name help for info on ." - ret=$GSU_SUCCESS - return - fi - if test "$1" = "help"; then - echo "$_gsu_help_txt" - ret=$GSU_SUCCESS - return - fi - if test "$1" = "man"; then - echo "$_gsu_man_txt" + p + ' | { + local -a cmds=() descs=() + local -i i maxlen=1 + local cmd desc + while read cmd desc; do + ((maxlen < ${#cmd})) && maxlen=${#cmd} + cmds[${#cmds[@]}]=$cmd + descs[${#descs[@]}]=$desc + done + for ((i = 0; i < ${#cmds[@]}; i++)); do + printf '%-*s %s\n' $maxlen ${cmds[$i]} \ + "${descs[$i]}" + done + } + printf "\n# Try %s help for info on , or %s help -a to see\n" \ + "$gsu_name" "$gsu_name" + printf '# also the subcommands which are automatically generated by gsu.\n' ret=$GSU_SUCCESS return fi - if test "$1" = "prefs"; then - echo "$_gsu_prefs_txt" + for cmd in "${!_gsu_help_text[@]}"; do + [[ "$1" != "$cmd" ]] && continue + printf '%s\n' "${_gsu_help_text["$cmd"]}" ret=$GSU_SUCCESS return - fi - if test "$1" = "complete"; then - echo "$_gsu_complete_txt" - ret=$GSU_SUCCESS - return - fi - ret=$GSU_SUCCESS + done _gsu_get_command_regex "$1" ere="$result" if ! grep -Eq "$ere" "$0"; then @@ -719,6 +737,7 @@ com_help() p } ' "$0" + ret=$GSU_SUCCESS } complete_help() @@ -738,7 +757,12 @@ com_complete() local -a candidates; candidates=(\$($0 complete "\$COMP_CWORD" "\${COMP_WORDS[@]}")); - COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur")); + if ((\$? == 0)); then + COMPREPLY=(\$(compgen -W "\${candidates[*]}" -- "\$cur")); + else + compopt -o filenames; + COMPREPLY=(\$(compgen -fd -- "\$cur")); + fi EOF ret=$GSU_SUCCESS return @@ -746,8 +770,8 @@ EOF cword="$1" gsu_is_a_number "$cword" - (($ret < 0)) && return - if (($cword <= 1)); then + ((ret < 0)) && return + if ((cword <= 1)); then _gsu_available_commands echo "${result}" ret=$GSU_SUCCESS @@ -756,8 +780,9 @@ EOF shift words=("$@") cmd="${words[1]}" - ret=$GSU_SUCCESS # It's not an error if no completer was defined - [[ "$(type -t "complete_$cmd")" != "function" ]] && return + # if no completer is defined for this subcommand we exit unsuccessfully + # to let the generic completer above fall back to file name completion. + [[ "$(type -t "complete_$cmd")" != "function" ]] && exit 1 "complete_$cmd" "$cword" "${words[@]}" # ignore errors, they would only clutter the completion output ret=$GSU_SUCCESS @@ -779,18 +804,18 @@ gsu_cword_is_option_parameter() local -a words result= - (($cword == 0)) && return + ((cword == 0)) && return ((${#opts} < 2)) && return shift 2 words=("$@") - prev="${words[$(($cword - 1))]}" + prev="${words[$((cword - 1))]}" [[ ! "$prev" == -* ]] && return n=$((${#opts} - 1)) for ((i=0; i <= $n; i++)); do opt="${opts:$i:1}" - [[ "${opts:$(($i + 1)):1}" != ":" ]] && continue + [[ "${opts:$((i + 1)):1}" != ":" ]] && continue let i++ [[ ! "$prev" =~ ^-.*$opt$ ]] && continue result="$opt" @@ -821,13 +846,13 @@ gsu_get_unnamed_arg_num() shift 2 words=("$@") cur="${words[$cword]}" - prev="${words[$(($cword - 1))]}" + prev="${words[$((cword - 1))]}" result=-1 [[ "$cur" == -* ]] && return [[ "$prev" == -* ]] && [[ "$opts" == *${prev#-}:* ]] && return for ((i=1; i <= $cword; i++)); do - prev="${words[$(($i - 1))]}" + prev="${words[$((i - 1))]}" cur="${words[$i]}" [[ "$cur" == -* ]] && continue if [[ "$prev" == -* ]]; then @@ -837,7 +862,7 @@ gsu_get_unnamed_arg_num() fi let n++ done - result="$(($n - 1))" + result="$((n - 1))" } # Entry point for all gsu-based scripts. @@ -868,7 +893,7 @@ gsu() shift if [[ "$(type -t "com_$arg")" == 'function' ]]; then "com_$arg" "$@" - if (("$ret" < 0)); then + if ((ret < 0)); then gsu_err_msg exit 1 fi @@ -877,6 +902,6 @@ gsu() ret=-$E_GSU_BAD_COMMAND result="$arg" gsu_err_msg - _gsu_print_available_commands + _gsu_print_available_commands 1>&2 exit 1 }