From 0209a79031cc96fde273cc09ef194d93bb68f8fa Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 19 Aug 2024 10:26:16 -0500 Subject: [PATCH] fix(complete): Don't cause endless completions for bash/zsh Reported on #5677 --- clap_complete/src/command/shells.rs | 30 +++++++++++------ clap_complete/src/env/shells.rs | 33 ++++++++++++------- .../dynamic-command/exhaustive/bash/.bashrc | 18 ++++++---- .../exhaustive/zsh/zsh/_exhaustive | 10 ++++-- .../home/dynamic-env/exhaustive/bash/.bashrc | 19 +++++++---- .../exhaustive/zsh/zsh/_exhaustive | 12 ++++--- .../tests/snapshots/register_minimal.bash | 18 ++++++---- 7 files changed, 92 insertions(+), 48 deletions(-) diff --git a/clap_complete/src/command/shells.rs b/clap_complete/src/command/shells.rs index d7b8b70fe3a..e057c001f69 100644 --- a/clap_complete/src/command/shells.rs +++ b/clap_complete/src/command/shells.rs @@ -187,15 +187,21 @@ impl CommandCompleter for Bash { let script = r#" _clap_complete_NAME() { - export IFS=$'\013' - export _CLAP_COMPLETE_INDEX=${COMP_CWORD} - export _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE} + local IFS=$'\013' + local _CLAP_COMPLETE_INDEX=${COMP_CWORD} + local _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE} if compopt +o nospace 2> /dev/null; then - export _CLAP_COMPLETE_SPACE=false + local _CLAP_COMPLETE_SPACE=false else - export _CLAP_COMPLETE_SPACE=true + local _CLAP_COMPLETE_SPACE=true fi - COMPREPLY=( $("COMPLETER" complete bash -- "${COMP_WORDS[@]}") ) + COMPREPLY=( $( \ + IFS="$IFS" \ + _CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \ + _CLAP_COMPLETE_COMP_TYPE="$_CLAP_COMPLETE_COMP_TYPE" \ + _CLAP_COMPLETE_SPACE="$_CLAP_COMPLETE_SPACE" \ + "COMPLETER" complete bash -- "${COMP_WORDS[@]}" \ + ) ) if [[ $? != 0 ]]; then unset COMPREPLY elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then @@ -471,10 +477,14 @@ impl CommandCompleter for Zsh { let script = r#"#compdef BIN function _clap_dynamic_completer() { - export _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1) - export _CLAP_IFS=$'\n' - - local completions=("${(@f)$(COMPLETER complete zsh -- ${words} 2>/dev/null)}") + local _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1) + local _CLAP_IFS=$'\n' + + local completions=("${(@f)$( \ + _CLAP_IFS="$_CLAP_IFS" \ + _CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \ + COMPLETER complete zsh -- ${words} 2>/dev/null \ + )}") if [[ -n $completions ]]; then compadd -a completions diff --git a/clap_complete/src/env/shells.rs b/clap_complete/src/env/shells.rs index 46a3ee376c2..5b8579f9700 100644 --- a/clap_complete/src/env/shells.rs +++ b/clap_complete/src/env/shells.rs @@ -31,16 +31,21 @@ impl EnvCompleter for Bash { let script = r#" _clap_complete_NAME() { - export IFS=$'\013' - export _CLAP_COMPLETE_INDEX=${COMP_CWORD} - export _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE} + local IFS=$'\013' + local _CLAP_COMPLETE_INDEX=${COMP_CWORD} + local _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE} if compopt +o nospace 2> /dev/null; then - export _CLAP_COMPLETE_SPACE=false + local _CLAP_COMPLETE_SPACE=false else - export _CLAP_COMPLETE_SPACE=true + local _CLAP_COMPLETE_SPACE=true fi - export VAR="bash" - COMPREPLY=( $("COMPLETER" -- "${COMP_WORDS[@]}") ) + COMPREPLY=( $( \ + IFS="$IFS" \ + _CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \ + _CLAP_COMPLETE_COMP_TYPE="$_CLAP_COMPLETE_COMP_TYPE" \ + VAR="bash" \ + "COMPLETER" -- "${COMP_WORDS[@]}" \ + ) ) if [[ $? != 0 ]]; then unset COMPREPLY elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then @@ -347,11 +352,15 @@ impl EnvCompleter for Zsh { let script = r#"#compdef BIN function _clap_dynamic_completer() { - export _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1) - export _CLAP_IFS=$'\n' - export VAR="zsh" - - local completions=("${(@f)$(COMPLETER -- ${words} 2>/dev/null)}") + local _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1) + local _CLAP_IFS=$'\n' + + local completions=("${(@f)$( \ + _CLAP_IFS="$_CLAP_IFS" \ + _CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \ + VAR="zsh" \ + COMPLETER -- ${words} 2>/dev/null \ + )}") if [[ -n $completions ]]; then compadd -a completions diff --git a/clap_complete/tests/snapshots/home/dynamic-command/exhaustive/bash/.bashrc b/clap_complete/tests/snapshots/home/dynamic-command/exhaustive/bash/.bashrc index 668029e8297..71a223df5be 100644 --- a/clap_complete/tests/snapshots/home/dynamic-command/exhaustive/bash/.bashrc +++ b/clap_complete/tests/snapshots/home/dynamic-command/exhaustive/bash/.bashrc @@ -2,15 +2,21 @@ PS1='% ' . /etc/bash_completion _clap_complete_exhaustive() { - export IFS=$'\013' - export _CLAP_COMPLETE_INDEX=${COMP_CWORD} - export _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE} + local IFS=$'\013' + local _CLAP_COMPLETE_INDEX=${COMP_CWORD} + local _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE} if compopt +o nospace 2> /dev/null; then - export _CLAP_COMPLETE_SPACE=false + local _CLAP_COMPLETE_SPACE=false else - export _CLAP_COMPLETE_SPACE=true + local _CLAP_COMPLETE_SPACE=true fi - COMPREPLY=( $("exhaustive" complete bash -- "${COMP_WORDS[@]}") ) + COMPREPLY=( $( \ + IFS="$IFS" \ + _CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \ + _CLAP_COMPLETE_COMP_TYPE="$_CLAP_COMPLETE_COMP_TYPE" \ + _CLAP_COMPLETE_SPACE="$_CLAP_COMPLETE_SPACE" \ + "exhaustive" complete bash -- "${COMP_WORDS[@]}" \ + ) ) if [[ $? != 0 ]]; then unset COMPREPLY elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then diff --git a/clap_complete/tests/snapshots/home/dynamic-command/exhaustive/zsh/zsh/_exhaustive b/clap_complete/tests/snapshots/home/dynamic-command/exhaustive/zsh/zsh/_exhaustive index a7082462b31..fbc8bc36c4d 100644 --- a/clap_complete/tests/snapshots/home/dynamic-command/exhaustive/zsh/zsh/_exhaustive +++ b/clap_complete/tests/snapshots/home/dynamic-command/exhaustive/zsh/zsh/_exhaustive @@ -1,9 +1,13 @@ #compdef exhaustive function _clap_dynamic_completer() { - export _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1) - export _CLAP_IFS=$'\n' + local _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1) + local _CLAP_IFS=$'\n' - local completions=("${(@f)$(exhaustive complete zsh -- ${words} 2>/dev/null)}") + local completions=("${(@f)$( \ + _CLAP_IFS="$_CLAP_IFS" \ + _CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \ + exhaustive complete zsh -- ${words} 2>/dev/null \ + )}") if [[ -n $completions ]]; then compadd -a completions diff --git a/clap_complete/tests/snapshots/home/dynamic-env/exhaustive/bash/.bashrc b/clap_complete/tests/snapshots/home/dynamic-env/exhaustive/bash/.bashrc index 4384e8d1758..ffc7e7907bb 100644 --- a/clap_complete/tests/snapshots/home/dynamic-env/exhaustive/bash/.bashrc +++ b/clap_complete/tests/snapshots/home/dynamic-env/exhaustive/bash/.bashrc @@ -2,16 +2,21 @@ PS1='% ' . /etc/bash_completion _clap_complete_exhaustive() { - export IFS=$'\013' - export _CLAP_COMPLETE_INDEX=${COMP_CWORD} - export _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE} + local IFS=$'\013' + local _CLAP_COMPLETE_INDEX=${COMP_CWORD} + local _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE} if compopt +o nospace 2> /dev/null; then - export _CLAP_COMPLETE_SPACE=false + local _CLAP_COMPLETE_SPACE=false else - export _CLAP_COMPLETE_SPACE=true + local _CLAP_COMPLETE_SPACE=true fi - export COMPLETE="bash" - COMPREPLY=( $("exhaustive" -- "${COMP_WORDS[@]}") ) + COMPREPLY=( $( \ + IFS="$IFS" \ + _CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \ + _CLAP_COMPLETE_COMP_TYPE="$_CLAP_COMPLETE_COMP_TYPE" \ + COMPLETE="bash" \ + "exhaustive" -- "${COMP_WORDS[@]}" \ + ) ) if [[ $? != 0 ]]; then unset COMPREPLY elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then diff --git a/clap_complete/tests/snapshots/home/dynamic-env/exhaustive/zsh/zsh/_exhaustive b/clap_complete/tests/snapshots/home/dynamic-env/exhaustive/zsh/zsh/_exhaustive index 6c5bd28ab50..b280f7c62e0 100644 --- a/clap_complete/tests/snapshots/home/dynamic-env/exhaustive/zsh/zsh/_exhaustive +++ b/clap_complete/tests/snapshots/home/dynamic-env/exhaustive/zsh/zsh/_exhaustive @@ -1,10 +1,14 @@ #compdef exhaustive function _clap_dynamic_completer() { - export _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1) - export _CLAP_IFS=$'\n' - export COMPLETE="zsh" + local _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1) + local _CLAP_IFS=$'\n' - local completions=("${(@f)$(exhaustive -- ${words} 2>/dev/null)}") + local completions=("${(@f)$( \ + _CLAP_IFS="$_CLAP_IFS" \ + _CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \ + COMPLETE="zsh" \ + exhaustive -- ${words} 2>/dev/null \ + )}") if [[ -n $completions ]]; then compadd -a completions diff --git a/clap_complete/tests/snapshots/register_minimal.bash b/clap_complete/tests/snapshots/register_minimal.bash index 925c3835b87..d2da036ce9d 100644 --- a/clap_complete/tests/snapshots/register_minimal.bash +++ b/clap_complete/tests/snapshots/register_minimal.bash @@ -1,14 +1,20 @@ _clap_complete_my_app() { - export IFS=$'/013' - export _CLAP_COMPLETE_INDEX=${COMP_CWORD} - export _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE} + local IFS=$'/013' + local _CLAP_COMPLETE_INDEX=${COMP_CWORD} + local _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE} if compopt +o nospace 2> /dev/null; then - export _CLAP_COMPLETE_SPACE=false + local _CLAP_COMPLETE_SPACE=false else - export _CLAP_COMPLETE_SPACE=true + local _CLAP_COMPLETE_SPACE=true fi - COMPREPLY=( $("my-app" complete bash -- "${COMP_WORDS[@]}") ) + COMPREPLY=( $( / + IFS="$IFS" / + _CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" / + _CLAP_COMPLETE_COMP_TYPE="$_CLAP_COMPLETE_COMP_TYPE" / + _CLAP_COMPLETE_SPACE="$_CLAP_COMPLETE_SPACE" / + "my-app" complete bash -- "${COMP_WORDS[@]}" / + ) ) if [[ $? != 0 ]]; then unset COMPREPLY elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then