# [[ -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
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++
"
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\""
_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'
}
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]
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()
{
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
(($? != 0)) && return
ret=-$E_GSU_EDITOR
result="${EDITOR:-vi}"
- "$result" "$conf"
+ "$result" $conf
(($? != 0)) && return
ret=$GSU_SUCCESS
return
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
[[ "$result" == 'm' ]] && printf 'roff\ntext\nhtml\n'
}
-_gsu_man_txt='
+_gsu_help_text['man']='
Print the manual.
Usage: man [-m <mode>] [-b <browser>]
--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
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()
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
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()
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'
o_m='html'
browser="$o_b"
elif [[ -z "$o_m" ]]; then
- o_m='text'
+ o_m='roff'
fi
_gsu_isatty && isatty='true' || isatty='false'
_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}"
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 [<cword> <word>...]
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"
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
y/\n/'"$tab"'/
# and print the sucker
- p'
- echo
- echo "# Try $gsu_name help <command> for info on <command>."
- ret=$GSU_SUCCESS
- return
- fi
- if test "$1" = "help"; then
- echo "$_gsu_help_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 <command> for info on <command>, 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" = "man"; then
- echo "$_gsu_man_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" = "prefs"; then
- echo "$_gsu_prefs_txt"
- 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
p
}
' "$0"
+ ret=$GSU_SUCCESS
}
complete_help()
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
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
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
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"
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
fi
let n++
done
- result="$(($n - 1))"
+ result="$((n - 1))"
}
# Entry point for all gsu-based scripts.
shift
if [[ "$(type -t "com_$arg")" == 'function' ]]; then
"com_$arg" "$@"
- if (("$ret" < 0)); then
+ if ((ret < 0)); then
gsu_err_msg
exit 1
fi
ret=-$E_GSU_BAD_COMMAND
result="$arg"
gsu_err_msg
- _gsu_print_available_commands
+ _gsu_print_available_commands 1>&2
exit 1
}