Add completion support for bash 3.2

Bash 3.2 does not have associative arrays, so we hack around that by using
generic varibale names like `opts__$cmd`. We also don't support the "?" alias
anymore.
This commit is contained in:
Thomas Scholtes 2014-02-22 17:59:23 +01:00
parent c5d3483fc3
commit e8e0682aae
4 changed files with 31 additions and 30 deletions

View file

@ -33,7 +33,6 @@ def completion_script(commands):
}
# Help subcommand
aliases['?'] = 'help'
command_names.append('help')
# Add flags common to all commands
@ -42,17 +41,19 @@ def completion_script(commands):
}
# Start generating the script
yield "_beet_setup() {\n"
yield " commands='%s'\n" % ' '.join(command_names)
yield '\n'
yield "_beet() {\n"
yield " local commands='%s'\n" % ' '.join(command_names)
yield "\n"
yield " local aliases='%s'\n" % ' '.join(aliases.keys())
for alias, cmd in aliases.items():
yield(" aliases['%s']='%s'\n" % (alias, cmd))
yield " local alias__%s=%s\n" % (alias, cmd)
yield '\n'
for cmd, opts in options.items():
for option_type, option_list in opts.items():
if option_list:
option_list = ' '.join(option_list)
yield " %s[%s]='%s'\n" % (option_type, cmd, option_list)
yield " local %s__%s='%s'\n" % (option_type, cmd, option_list)
yield ' _beet_dispatch\n'
yield '}\n'

View file

@ -29,7 +29,7 @@
# Note that completion only works for builtin commands and *not* for
# commands provided by plugins.
#
# Currently, only Bash 4.1 and newer is supported.
# Currently, only Bash 3.2 and newer is supported.
#
# TODO
# ----
@ -50,25 +50,22 @@
# * Support long options with `=`, e.g. `--config=file`. Debian's bash
# completion package can handle this.
#
# * Support for Bash 3.2
#
# Main entry point for completion
_beet() {
local cur prev commands
local -A flags opts aliases
# Determines the beets subcommand and dispatches the completion
# accordingly.
_beet_dispatch() {
local cur prev
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
_beet_setup
# Look for the beets subcommand
local arg cmd=
for (( i=1; i < COMP_CWORD; i++ )); do
arg="${COMP_WORDS[i]}"
if _list_include_item "${opts[_global]}" $arg; then
if _list_include_item "${opts___global}" $arg; then
((i++))
elif [[ "$arg" != -* ]]; then
cmd="$arg"
@ -77,8 +74,8 @@ _beet() {
done
# Replace command shortcuts
if [[ -n $cmd && -n ${aliases[$cmd]} ]]; then
cmd=${aliases[$cmd]}
if [[ -n $cmd ]] && _list_include_item "$aliases" "$cmd"; then
eval "cmd=\$alias__$cmd"
fi
case $cmd in
@ -93,13 +90,15 @@ _beet() {
;;
esac
}
complete -o filenames -F _beet beet
# Adds option and file completion to COMPREPLY for the subcommand $1
_beet_complete() {
if [[ $cur == -* ]]; then
local completions="${flags[_common]} ${opts[$1]} ${flags[$1]}"
local opts flags completions
eval "opts=\$opts__$1"
eval "flags=\$flags__$1"
completions="${flags___common} ${opts} ${flags}"
COMPREPLY+=( $(compgen -W "$completions" -- $cur) )
else
COMPREPLY+=( $(compgen -f -- $cur) )
@ -107,7 +106,7 @@ _beet_complete() {
}
# Add global options and commands to the completion
# Add global options and subcommands to the completion
_beet_complete_global() {
case $prev in
-h|--help)
@ -128,10 +127,12 @@ _beet_complete_global() {
esac
if [[ $cur == -* ]]; then
local completions="${opts[_global]} ${flags[_global]}"
local completions="$opts___global $flags___global"
COMPREPLY+=( $(compgen -W "$completions" -- $cur) )
elif [[ -n $cur && -n "${aliases[$cur]}" ]]; then
COMPREPLY+=( ${aliases[$cur]} )
elif [[ -n $cur ]] && _list_include_item "$aliases" "$cur"; then
local cmd
eval "cmd=\$alias__$cur"
COMPREPLY+=( $cmd )
else
COMPREPLY+=( $(compgen -W "$commands" -- $cur) )
fi
@ -139,8 +140,9 @@ _beet_complete_global() {
# Returns true if the space separated list $1 includes $2
_list_include_item() {
[[ $1 =~ (^|[[:space:]])"$2"($|[[:space:]]) ]]
[[ " $1 " == *[[:space:]]$2[[:space:]]* ]]
}
# This is where beets dynamically adds the _beet_setup function. This
# This is where beets dynamically adds the _beet function. This
# function sets the variables $flags, $opts, $commands, and $aliases.
complete -o filenames -F _beet beet

View file

@ -8,7 +8,7 @@ initcli() {
completes() {
for word in "$@"; do
[[ ${COMPREPLY[@]} =~ "$word" ]] || return 1
[[ " ${COMPREPLY[@]} " == *[[:space:]]$word[[:space:]]* ]] || return 1
done
}
@ -133,9 +133,6 @@ test_list_options() {
test_help_command() {
initcli help '' &&
completes $COMMANDS &&
initcli '?' '' &&
completes $COMMANDS &&
true
}

View file

@ -750,7 +750,8 @@ class CompletionTest(_common.TestCase):
'test_completion.sh')
# Tests run in bash
tester = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE,
shell = os.environ.get('BEETS_TEST_SHELL', '/bin/bash')
tester = subprocess.Popen(shell, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
# Load complection script