From 5a6626cada5419afefd6a720f73654566946499a Mon Sep 17 00:00:00 2001 From: Kaiiiiiiiii <2761362118@qq.com> Date: Tue, 3 Feb 2026 13:36:15 +0800 Subject: [PATCH] fix: guard empty interactive completion results --- src/shell.rs | 14 ++++++++++++++ templates/bash.txt | 23 ++++++++++++----------- templates/fish.txt | 1 + 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/shell.rs b/src/shell.rs index 8812b1c..3864f74 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -65,6 +65,13 @@ mod tests { .stderr(""); } + #[apply(opts)] + fn bash_init_guards_empty_completion(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { + let opts = Opts { cmd, hook, echo, resolve_symlinks }; + let source = Bash(&opts).render().unwrap(); + assert!(source.contains("[[ -n \"${__zoxide_result}\" ]] || return")); + } + #[apply(opts)] fn bash_shellcheck(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { let opts = Opts { cmd, hook, echo, resolve_symlinks }; @@ -141,6 +148,13 @@ mod tests { .stderr(""); } + #[apply(opts)] + fn fish_init_guards_empty_completion(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { + let opts = Opts { cmd, hook, echo, resolve_symlinks }; + let source = Fish(&opts).render().unwrap(); + assert!(source.contains("and test -n \"$result\"")); + } + #[apply(opts)] fn fish_fishindent(cmd: Option<&str>, hook: InitHook, echo: bool, resolve_symlinks: bool) { let opts = Opts { cmd, hook, echo, resolve_symlinks }; diff --git a/templates/bash.txt b/templates/bash.txt index 86a2884..6b82949 100644 --- a/templates/bash.txt +++ b/templates/bash.txt @@ -178,18 +178,19 @@ if [[ ${BASH_VERSINFO[0]:-0} -eq 4 && ${BASH_VERSINFO[1]:-0} -ge 4 || ${BASH_VER # If there is a space after the last word, use interactive selection. elif [[ -z ${COMP_WORDS[-1]} ]]; then # shellcheck disable=SC2312 - __zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd)" --interactive -- "{{ "${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-2}" }}")" && { - # In case the terminal does not respond to \e[5n or another - # mechanism steals the response, it is still worth completing - # the directory in the command line. - COMPREPLY=("${__zoxide_z_prefix}${__zoxide_result}/") + __zoxide_result="$(\command zoxide query --exclude "$(__zoxide_pwd)" --interactive -- "{{ "${COMP_WORDS[@]:1:${#COMP_WORDS[@]}-2}" }}")" || return + [[ -n "${__zoxide_result}" ]] || return - # Note: We here call "bind" without prefixing "\builtin" to be - # compatible with frameworks like ble.sh, which emulates Bash's - # builtin "bind". - bind -x '"\e[0n": __zoxide_z_complete_helper' - \builtin printf '\e[5n' >/dev/tty - } + # In case the terminal does not respond to \e[5n or another + # mechanism steals the response, it is still worth completing + # the directory in the command line. + COMPREPLY=("${__zoxide_z_prefix}${__zoxide_result}/") + + # Note: We here call "bind" without prefixing "\builtin" to be + # compatible with frameworks like ble.sh, which emulates Bash's + # builtin "bind". + bind -x '"\e[0n": __zoxide_z_complete_helper' + \builtin printf '\e[5n' >/dev/tty fi } diff --git a/templates/fish.txt b/templates/fish.txt index a13edc7..64d1a88 100644 --- a/templates/fish.txt +++ b/templates/fish.txt @@ -101,6 +101,7 @@ function __zoxide_z_complete # If the last argument is empty, use interactive selection. set -l query $tokens[2..-1] set -l result (command zoxide query --exclude (__zoxide_pwd) --interactive -- $query) + and test -n "$result" and __zoxide_cd $result and builtin commandline --function cancel-commandline repaint end