First, use the correct completion return value. The return value of a completion function is significant, if we fail to return success additional completers may be invoked when they otherwise should not be. Also cleanup up the zsh completion, removing the redundant definition of _bluetoothctl and using the _call_program helper where appropriate. Finally, update the bluetoothctl command invocations to account for the media lines printed after some of the non-interactive commands. --- completion/zsh/_bluetoothctl | 133 ++++++++++++++++------------------- src/shared/shell.c | 4 ++ 2 files changed, 66 insertions(+), 71 deletions(-) diff --git a/completion/zsh/_bluetoothctl b/completion/zsh/_bluetoothctl index 610ca2b8d59c..b6f513376532 100644 --- a/completion/zsh/_bluetoothctl +++ b/completion/zsh/_bluetoothctl @@ -1,97 +1,88 @@ #compdef bluetoothctl -__bluetoothctl() { - bluetoothctl "$@" 2>/dev/null -} - _bluezcomp_controller() { local -a controllers - bluetoothctl list | - while read _ MAC NAME; do - controllers+="${MAC//:/\\:}:${NAME//:/\\:}" + _call_program bluez-controller bluetoothctl list | + while read KIND MAC NAME FLAG; do + [[ $KIND == Controller ]] && + controllers+=("${MAC//:/\\:}:${NAME//:/\\:}") done _describe -t controllers 'controller' controllers } _bluezcomp_device() { local -a devices - bluetoothctl devices | - while read _ MAC NAME; do - devices+="${MAC//:/\\:}:${NAME//:/\\:}" + _call_program bluez-device bluetoothctl devices | + while read KIND MAC NAME; do + [[ $KIND == Device ]] && + devices+=("${MAC//:/\\:}:${NAME//:/\\:}") done _describe -t devices 'device' devices } _bluezcomp_agentcap() { - local -a agent_options=(${(f)"$(__bluetoothctl agent help)"}) - agent_options=( "${(@)agent_options:#(on|off)}" ) - compadd -a agent_options + local -a agent_options=(${${(@f)"$(_call_program bluez-agent bluetoothctl agent help)"}:#(on|off)}) + compadd "$@" - -a agent_options } _bluetoothctl_agent() { - local -a agent_options=(${(f)"$(__bluetoothctl agent help)"}) - agent_options+=help - compadd -a agent_options + local -a agent_options=(help ${(@f)"$(_call_program bluez-agent bluetoothctl agent help)"}) + compadd "$@" - -a agent_options } -_bluetoothctl_advertise() { - local -a ad_options=(${(f)"$(__bluetoothctl advertise help)"}) - ad_options+=help - compadd -a ad_options -} +local -a toggle_commands=( + "discoverable" "pairable" "power" "scan" +) -_bluetoothctl() { - local -a toggle_commands=( - "discoverable" "pairable" "power" "scan" - ) +local -a controller_commands=( + "select" "show" +) - local -a controller_commands=( - "select" "show" - ) +local -a device_commands=( + "block" "connect" "disconnect" "info" + "pair" "remove" "trust" "unblock" "untrust" +) - local -a device_commands=( - "block" "connect" "disconnect" "info" - "pair" "remove" "trust" "unblock" "untrust" - ) +# Other commands may be handled by _bluetoothctl_$command +local -a all_commands=( "${(@f)$(_call_program bluetoothctl bluetoothctl --zsh-complete help)}" ) - # Other commands may be handled by _bluetoothctl_$command - local -a all_commands=( "${(@f)$(__bluetoothctl --zsh-complete help)}" ) +local curcontext=$curcontext state line ret=1 +_arguments -C \ + + '(info)' \ + {-h,--help}'[Show help message and exit]' \ + {-v,--version}'--version[Show version info and exit]' \ + + 'mod' \ + '(info)'{-a+,--agent=}'[Register agent handler]:agent:_bluezcomp_agentcap' \ + '(info)'{-t,--timeout}'[Timeout in seconds for non-interactive mode]' \ + '(info)'{-m,--monitor}'[Enable monitor output]' \ + + 'command' \ + '(info):command:->command' \ + '(info):: :->argument' - local curcontext=$curcontext state line ret=1 - _arguments -C \ - + '(info)' \ - {-h,--help}'[Show help message and exit]' \ - {-v,--version}'--version[Show version info and exit]' \ - + 'mod' \ - '(info)'{-a+,--agent=}'[Register agent handler]:agent:_bluezcomp_agentcap' \ - '(info)'{-t,--timeout}'[Timeout in seconds for non-interactive mode]' \ - '(info)'{-m,--monitor}'[Enable monitor output]' \ - + 'command' \ - '(info):command:->command' \ - '(info):: :->argument' - - if [[ $state == "command" ]]; then - _describe -t commands 'command' all_commands - elif [[ $state == "argument" ]]; then - if (( ! ${"${(@)all_commands%%:*}"[(I)${line[1]}]} )); then - _message "Unknown bluetoothctl command: $line[1]" - return 1; - fi - - curcontext="${curcontext%:*:*}:bluetoothctl-$line[1]:" - if ! _call_function ret _bluetoothctl_$line[1]; then - case $line[1] in - (${(~j.|.)toggle_commands}) - compadd on off - ;; - (${(~j.|.)device_commands}) - _bluezcomp_device - ;; - (${(~j.|.)controller_commands}) - _bluezcomp_controller - ;; - esac - fi - return ret +if [[ $state == "command" ]]; then + _describe -t commands 'command' all_commands +elif [[ $state == "argument" ]]; then + if (( ! ${"${(@)all_commands%%:*}"[(I)${line[1]}]} )); then + _message "Unknown bluetoothctl command: $line[1]" + return 1; fi -} && _bluetoothctl + + curcontext="${curcontext%:*:*}:bluetoothctl-$line[1]:" + if ! _call_function ret _bluetoothctl_$line[1]; then + case $line[1] in + (advertise) + compadd - help on off type && ret=0 + ;; + (${(~j.|.)toggle_commands}) + compadd on off && ret=0 + ;; + (${(~j.|.)device_commands}) + _bluezcomp_device && ret=0 + ;; + (${(~j.|.)controller_commands}) + _bluezcomp_controller && ret=0 + ;; + esac + fi + return ret +fi diff --git a/src/shared/shell.c b/src/shared/shell.c index 6b4f7a7ef503..0685a1cdb21a 100644 --- a/src/shared/shell.c +++ b/src/shared/shell.c @@ -1726,6 +1726,10 @@ int bt_shell_get_timeout(void) void bt_shell_handle_non_interactive_help(void) { + if (data.zsh) { + shell_print_menu_zsh_complete(); + exit(EXIT_SUCCESS); + } if (!data.mode) return; if (data.argv[0] != cmplt) -- 2.50.0