mirror of
https://github.com/apple/swift-argument-parser.git
synced 2026-06-06 20:18:23 +00:00
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
307 lines
10 KiB
Bash
307 lines
10 KiB
Bash
#!/bin/bash
|
|
|
|
__math_cursor_index_in_current_word() {
|
|
local remaining="${COMP_LINE}"
|
|
|
|
local word
|
|
for word in "${COMP_WORDS[@]::COMP_CWORD}"; do
|
|
remaining="${remaining##*([[:space:]])"${word}"*([[:space:]])}"
|
|
done
|
|
|
|
local -ir index="$((COMP_POINT - ${#COMP_LINE} + ${#remaining}))"
|
|
if [[ "${index}" -le 0 ]]; then
|
|
printf 0
|
|
else
|
|
printf %s "${index}"
|
|
fi
|
|
}
|
|
|
|
# positional arguments:
|
|
#
|
|
# - 1: the current (sub)command's count of positional arguments
|
|
#
|
|
# required variables:
|
|
#
|
|
# - repeating_flags: the repeating flags that the current (sub)command can accept
|
|
# - non_repeating_flags: the non-repeating flags that the current (sub)command can accept
|
|
# - repeating_options: the repeating options that the current (sub)command can accept
|
|
# - non_repeating_options: the non-repeating options that the current (sub)command can accept
|
|
# - positional_number: value ignored
|
|
# - unparsed_words: unparsed words from the current command line
|
|
#
|
|
# modified variables:
|
|
#
|
|
# - non_repeating_flags: remove flags for this (sub)command that are already on the command line
|
|
# - non_repeating_options: remove options for this (sub)command that are already on the command line
|
|
# - positional_number: set to the current positional number
|
|
# - unparsed_words: remove all flags, options, and option values for this (sub)command
|
|
__math_offer_flags_options() {
|
|
local -ir positional_count="${1}"
|
|
positional_number=0
|
|
|
|
local was_flag_option_terminator_seen=false
|
|
local is_parsing_option_value=false
|
|
|
|
local -ar unparsed_word_indices=("${!unparsed_words[@]}")
|
|
local -i word_index
|
|
for word_index in "${unparsed_word_indices[@]}"; do
|
|
if "${is_parsing_option_value}"; then
|
|
# This word is an option value:
|
|
# Reset marker for next word iff not currently the last word
|
|
[[ "${word_index}" -ne "${unparsed_word_indices[${#unparsed_word_indices[@]} - 1]}" ]] && is_parsing_option_value=false
|
|
unset "unparsed_words[${word_index}]"
|
|
# Do not process this word as a flag or an option
|
|
continue
|
|
fi
|
|
|
|
local word="${unparsed_words["${word_index}"]}"
|
|
if ! "${was_flag_option_terminator_seen}"; then
|
|
case "${word}" in
|
|
--)
|
|
unset "unparsed_words[${word_index}]"
|
|
# by itself -- is a flag/option terminator, but if it is the last word, it is the start of a completion
|
|
if [[ "${word_index}" -ne "${unparsed_word_indices[${#unparsed_word_indices[@]} - 1]}" ]]; then
|
|
was_flag_option_terminator_seen=true
|
|
fi
|
|
continue
|
|
;;
|
|
-*)
|
|
# ${word} is a flag or an option
|
|
# If ${word} is an option, mark that the next word to be parsed is an option value
|
|
local option
|
|
for option in "${repeating_options[@]}" "${non_repeating_options[@]}"; do
|
|
[[ "${word}" = "${option}" ]] && is_parsing_option_value=true && break
|
|
done
|
|
|
|
# Remove ${word} from ${non_repeating_flags} or ${non_repeating_options} so it isn't offered again
|
|
local not_found=true
|
|
local -i index
|
|
for index in "${!non_repeating_flags[@]}"; do
|
|
if [[ "${non_repeating_flags[${index}]}" = "${word}" ]]; then
|
|
unset "non_repeating_flags[${index}]"
|
|
non_repeating_flags=("${non_repeating_flags[@]}")
|
|
not_found=false
|
|
break
|
|
fi
|
|
done
|
|
if "${not_found}"; then
|
|
for index in "${!non_repeating_flags[@]}"; do
|
|
if [[ "${non_repeating_flags[${index}]}" = "${word}" ]]; then
|
|
unset "non_repeating_flags[${index}]"
|
|
non_repeating_flags=("${non_repeating_flags[@]}")
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
unset "unparsed_words[${word_index}]"
|
|
continue
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# ${word} is neither a flag, nor an option, nor an option value
|
|
if [[ "${positional_number}" -lt "${positional_count}" || "${positional_count}" -lt 0 ]]; then
|
|
# ${word} is a positional
|
|
((positional_number++))
|
|
unset "unparsed_words[${word_index}]"
|
|
else
|
|
if [[ -z "${word}" ]]; then
|
|
# Could be completing a flag, option, or subcommand
|
|
positional_number=-1
|
|
else
|
|
# ${word} is a subcommand or invalid, so stop processing this (sub)command
|
|
positional_number=-2
|
|
fi
|
|
break
|
|
fi
|
|
done
|
|
|
|
unparsed_words=("${unparsed_words[@]}")
|
|
|
|
if\
|
|
! "${was_flag_option_terminator_seen}"\
|
|
&& ! "${is_parsing_option_value}"\
|
|
&& [[ ("${cur}" = -* && "${positional_number}" -ge 0) || "${positional_number}" -eq -1 ]]
|
|
then
|
|
COMPREPLY+=($(compgen -W "${repeating_flags[*]} ${non_repeating_flags[*]} ${repeating_options[*]} ${non_repeating_options[*]}" -- "${cur}"))
|
|
fi
|
|
}
|
|
|
|
__math_add_completions() {
|
|
local completion
|
|
while IFS='' read -r completion; do
|
|
COMPREPLY+=("${completion}")
|
|
done < <(IFS=$'\n' compgen "${@}" -- "${cur}")
|
|
}
|
|
|
|
__math_custom_complete() {
|
|
if [[ -n "${cur}" || -z ${COMP_WORDS[${COMP_CWORD}]} || "${COMP_LINE:${COMP_POINT}:1}" != ' ' ]]; then
|
|
local -ar words=("${COMP_WORDS[@]}")
|
|
else
|
|
local -ar words=("${COMP_WORDS[@]::${COMP_CWORD}}" '' "${COMP_WORDS[@]:${COMP_CWORD}}")
|
|
fi
|
|
|
|
"${COMP_WORDS[0]}" "${@}" "${words[@]}"
|
|
}
|
|
|
|
_math() {
|
|
local state
|
|
state="$(shopt -p;shopt -po)"
|
|
trap "${state//$'\n'/;}" RETURN
|
|
shopt -s extglob
|
|
set +o history +o posix
|
|
|
|
local -xr SAP_SHELL=bash
|
|
local -x SAP_SHELL_VERSION
|
|
SAP_SHELL_VERSION="$(IFS='.';printf %s "${BASH_VERSINFO[*]}")"
|
|
local -r SAP_SHELL_VERSION
|
|
|
|
local -r cur="${2}"
|
|
local -r prev="${3}"
|
|
|
|
local -i positional_number
|
|
local -a unparsed_words=("${COMP_WORDS[@]:1:${COMP_CWORD}}")
|
|
|
|
local -a repeating_flags=()
|
|
local -a non_repeating_flags=(--version -h --help)
|
|
local -a repeating_options=()
|
|
local -a non_repeating_options=()
|
|
__math_offer_flags_options 0
|
|
|
|
# Offer subcommand / subcommand argument completions
|
|
local -r subcommand="${unparsed_words[0]}"
|
|
unset 'unparsed_words[0]'
|
|
unparsed_words=("${unparsed_words[@]}")
|
|
case "${subcommand}" in
|
|
add|multiply|stats|help)
|
|
# Offer subcommand argument completions
|
|
"_math_${subcommand}"
|
|
;;
|
|
*)
|
|
# Offer subcommand completions
|
|
COMPREPLY+=($(compgen -W 'add multiply stats help' -- "${cur}"))
|
|
;;
|
|
esac
|
|
}
|
|
|
|
_math_add() {
|
|
repeating_flags=()
|
|
non_repeating_flags=(--hex-output -x --version -h --help)
|
|
repeating_options=()
|
|
non_repeating_options=()
|
|
__math_offer_flags_options -1
|
|
}
|
|
|
|
_math_multiply() {
|
|
repeating_flags=()
|
|
non_repeating_flags=(--hex-output -x --version -h --help)
|
|
repeating_options=()
|
|
non_repeating_options=()
|
|
__math_offer_flags_options -1
|
|
}
|
|
|
|
_math_stats() {
|
|
repeating_flags=()
|
|
non_repeating_flags=(--version -h --help)
|
|
repeating_options=()
|
|
non_repeating_options=()
|
|
__math_offer_flags_options 0
|
|
|
|
# Offer subcommand / subcommand argument completions
|
|
local -r subcommand="${unparsed_words[0]}"
|
|
unset 'unparsed_words[0]'
|
|
unparsed_words=("${unparsed_words[@]}")
|
|
case "${subcommand}" in
|
|
average|stdev|quantiles)
|
|
# Offer subcommand argument completions
|
|
"_math_stats_${subcommand}"
|
|
;;
|
|
*)
|
|
# Offer subcommand completions
|
|
COMPREPLY+=($(compgen -W 'average stdev quantiles' -- "${cur}"))
|
|
;;
|
|
esac
|
|
}
|
|
|
|
_math_stats_average() {
|
|
repeating_flags=()
|
|
non_repeating_flags=(--version -h --help)
|
|
repeating_options=()
|
|
non_repeating_options=(--kind)
|
|
__math_offer_flags_options -1
|
|
|
|
# Offer option value completions
|
|
case "${prev}" in
|
|
'--kind')
|
|
__math_add_completions -W 'mean'$'\n''median'$'\n''mode'
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
_math_stats_stdev() {
|
|
repeating_flags=()
|
|
non_repeating_flags=(--version -h --help)
|
|
repeating_options=()
|
|
non_repeating_options=()
|
|
__math_offer_flags_options -1
|
|
}
|
|
|
|
_math_stats_quantiles() {
|
|
repeating_flags=()
|
|
non_repeating_flags=(--version -h --help)
|
|
repeating_options=()
|
|
non_repeating_options=(--file --directory --shell --custom --custom-deprecated)
|
|
__math_offer_flags_options -1
|
|
|
|
# Offer option value completions
|
|
case "${prev}" in
|
|
'--file')
|
|
__math_add_completions -o plusdirs -fX '!*.@(txt|md)'
|
|
return
|
|
;;
|
|
'--directory')
|
|
__math_add_completions -d
|
|
return
|
|
;;
|
|
'--shell')
|
|
__math_add_completions -W "$(eval 'head -100 '\''/usr/share/dict/words'\'' | tail -50')"
|
|
return
|
|
;;
|
|
'--custom')
|
|
__math_add_completions -W "$(__math_custom_complete ---completion stats quantiles -- --custom "${COMP_CWORD}" "$(__math_cursor_index_in_current_word)")"
|
|
return
|
|
;;
|
|
'--custom-deprecated')
|
|
__math_add_completions -W "$(__math_custom_complete ---completion stats quantiles -- --custom-deprecated)"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
# Offer positional completions
|
|
case "${positional_number}" in
|
|
1)
|
|
__math_add_completions -W 'alphabet'$'\n''alligator'$'\n''branch'$'\n''braggart'
|
|
return
|
|
;;
|
|
2)
|
|
__math_add_completions -W "$(__math_custom_complete ---completion stats quantiles -- positional@1 "${COMP_CWORD}" "$(__math_cursor_index_in_current_word)")"
|
|
return
|
|
;;
|
|
3)
|
|
__math_add_completions -W "$(__math_custom_complete ---completion stats quantiles -- positional@2)"
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
_math_help() {
|
|
repeating_flags=()
|
|
non_repeating_flags=(--version)
|
|
repeating_options=()
|
|
non_repeating_options=()
|
|
__math_offer_flags_options -1
|
|
}
|
|
|
|
complete -o filenames -F _math math
|