Add an automatic check for required option argument

Get rid of manually listing unhandled long options:

Instead of listing options requiring an argument one by one in the
case statement in _hledger_compreply_optarg(), the option completion
lists are searched and if the option does require an argument an
empty COMPREPLY is send. Short options are uncounted for and still
need a manual entry.

This necessitated setting $subcommandOptions beforehand, so it is
moved back where it was -- in the sub-command loop in main().
This commit is contained in:
Vladimir Zhelezov 2020-12-14 07:37:48 +01:00
parent 3eccfb85e0
commit d82e13bb51
2 changed files with 64 additions and 34 deletions

View File

@ -23,6 +23,7 @@ _hledger_completion_function() {
esac esac
local subcommand local subcommand
local subcommandOptions
local i local i
for ((i=1; i<${#words[@]}; i++)); do for ((i=1; i<${#words[@]}; i++)); do
subcommand=${words[i]} subcommand=${words[i]}
@ -40,6 +41,16 @@ _hledger_completion_function() {
)" )"
return 0 return 0
fi fi
if [[ $cur == -* ]]; then
# Replace dashes with underscores and use indirect expansion
subcommandOptions=_hledger_complist_options_${subcommand//-/_}
_hledger_compreply "$(_hledger_compgen "${!subcommandOptions}")"
# Suspend space on completion of long options requiring an argument
[[ ${COMPREPLY[0]} == --*= ]] && compopt -o nospace
return 0
fi
break break
done done
@ -62,18 +73,6 @@ _hledger_completion_function() {
return 0 return 0
fi fi
if [[ $cur == -* ]]; then
local subcommandOptions
# Replace dashes with underscores and use indirect expansion
subcommandOptions=_hledger_complist_options_${subcommand//-/_}
_hledger_compreply "$(_hledger_compgen "${!subcommandOptions}")"
# Suspend space on completion of long options requiring an argument
[[ ${COMPREPLY[0]} == --*= ]] && compopt -o nospace
return 0
fi
# Set this from here on because queries tend to have lots of special chars # Set this from here on because queries tend to have lots of special chars
# TODO: better handling of special characters # TODO: better handling of special characters
compopt -o filenames compopt -o filenames
@ -208,7 +207,7 @@ _hledger_compgen() {
# Try required option argument completion. Set COMPREPLY and return 0 on # Try required option argument completion. Set COMPREPLY and return 0 on
# success, 1 if option doesn't require an argument or out of context # success, 1 if option doesn't require an argument or out of context
_hledger_compreply_optarg() { _hledger_compreply_optarg() {
local optionIndex=$((cword - 1)) local option=${words[cword - 1]}
local match=$cur local match=$cur
local wordlist local wordlist
@ -217,12 +216,12 @@ _hledger_compreply_optarg() {
match="" match=""
# Once input is present, cword is incremented so we compensate # Once input is present, cword is incremented so we compensate
elif [[ $prev == = ]]; then elif [[ $prev == = ]]; then
optionIndex=$((cword - 2)) option=${words[cword - 2]}
fi fi
[[ ${words[optionIndex]} == -* ]] || return [[ $option == -* ]] || return
case ${words[optionIndex]} in case $option in
--alias) --alias)
compopt -o nospace -o filenames compopt -o nospace -o filenames
_hledger_compreply "$( _hledger_compreply "$(
@ -270,10 +269,26 @@ _hledger_compreply_optarg() {
_hledger_compreply "$(compgen -W "$wordlist" -- "$match")" _hledger_compreply "$(compgen -W "$wordlist" -- "$match")"
;; ;;
# Argument required, but no handler (yet) # Argument required, but no handler (yet)
-b|--begin|-e|--end|-p|--period|--depth|--drop) -b|-e|-p)
_hledger_compreply "" _hledger_compreply ""
;; ;;
# Check if an unhandled long option requires an argument
*) *)
local optionList argRequired
if [[ -n $subcommandOptions ]]; then
optionList=${!subcommandOptions}
else
optionList=$_hledger_complist_generic_options
fi
while IFS= read -r argRequired; do
if [[ $argRequired == "$option=" ]]; then
_hledger_compreply ""
return 0
fi
done <<< "$optionList"
return 1 return 1
;; ;;
esac esac

View File

@ -23,6 +23,7 @@ _hledger_completion_function() {
esac esac
local subcommand local subcommand
local subcommandOptions
local i local i
for ((i=1; i<${#words[@]}; i++)); do for ((i=1; i<${#words[@]}; i++)); do
subcommand=${words[i]} subcommand=${words[i]}
@ -40,6 +41,16 @@ _hledger_completion_function() {
)" )"
return 0 return 0
fi fi
if [[ $cur == -* ]]; then
# Replace dashes with underscores and use indirect expansion
subcommandOptions=_hledger_complist_options_${subcommand//-/_}
_hledger_compreply "$(_hledger_compgen "${!subcommandOptions}")"
# Suspend space on completion of long options requiring an argument
[[ ${COMPREPLY[0]} == --*= ]] && compopt -o nospace
return 0
fi
break break
done done
@ -62,18 +73,6 @@ _hledger_completion_function() {
return 0 return 0
fi fi
if [[ $cur == -* ]]; then
local subcommandOptions
# Replace dashes with underscores and use indirect expansion
subcommandOptions=_hledger_complist_options_${subcommand//-/_}
_hledger_compreply "$(_hledger_compgen "${!subcommandOptions}")"
# Suspend space on completion of long options requiring an argument
[[ ${COMPREPLY[0]} == --*= ]] && compopt -o nospace
return 0
fi
# Set this from here on because queries tend to have lots of special chars # Set this from here on because queries tend to have lots of special chars
# TODO: better handling of special characters # TODO: better handling of special characters
compopt -o filenames compopt -o filenames
@ -208,7 +207,7 @@ _hledger_compgen() {
# Try required option argument completion. Set COMPREPLY and return 0 on # Try required option argument completion. Set COMPREPLY and return 0 on
# success, 1 if option doesn't require an argument or out of context # success, 1 if option doesn't require an argument or out of context
_hledger_compreply_optarg() { _hledger_compreply_optarg() {
local optionIndex=$((cword - 1)) local option=${words[cword - 1]}
local match=$cur local match=$cur
local wordlist local wordlist
@ -217,12 +216,12 @@ _hledger_compreply_optarg() {
match="" match=""
# Once input is present, cword is incremented so we compensate # Once input is present, cword is incremented so we compensate
elif [[ $prev == = ]]; then elif [[ $prev == = ]]; then
optionIndex=$((cword - 2)) option=${words[cword - 2]}
fi fi
[[ ${words[optionIndex]} == -* ]] || return [[ $option == -* ]] || return
case ${words[optionIndex]} in case $option in
--alias) --alias)
compopt -o nospace -o filenames compopt -o nospace -o filenames
_hledger_compreply "$( _hledger_compreply "$(
@ -270,10 +269,26 @@ _hledger_compreply_optarg() {
_hledger_compreply "$(compgen -W "$wordlist" -- "$match")" _hledger_compreply "$(compgen -W "$wordlist" -- "$match")"
;; ;;
# Argument required, but no handler (yet) # Argument required, but no handler (yet)
-b|--begin|-e|--end|-p|--period|--depth|--drop) -b|-e|-p)
_hledger_compreply "" _hledger_compreply ""
;; ;;
# Check if an unhandled long option requires an argument
*) *)
local optionList argRequired
if [[ -n $subcommandOptions ]]; then
optionList=${!subcommandOptions}
else
optionList=$_hledger_complist_generic_options
fi
while IFS= read -r argRequired; do
if [[ $argRequired == "$option=" ]]; then
_hledger_compreply ""
return 0
fi
done <<< "$optionList"
return 1 return 1
;; ;;
esac esac