From 3da4bf643148c8ecf5502c0ebb78e837b300d7f2 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Sun, 1 Oct 2023 04:44:05 +0900 Subject: [PATCH] completions/{ssh,rake,capistrano}: Do not rewrite COMP_WORDBREAKS Fix https://github.com/ohmybash/oh-my-bash/issues/471 --- completions/capistrano.completion.sh | 10 +++-- completions/rake.completion.sh | 10 +++-- completions/ssh.completion.sh | 8 ++-- lib/omb-completion.sh | 62 ++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 lib/omb-completion.sh diff --git a/completions/capistrano.completion.sh b/completions/capistrano.completion.sh index 4036276..e165f49 100644 --- a/completions/capistrano.completion.sh +++ b/completions/capistrano.completion.sh @@ -1,9 +1,12 @@ #! bash oh-my-bash.module # Bash completion support for Capistrano. -export COMP_WORDBREAKS=${COMP_WORDBREAKS/\:/} +_omb_module_require lib:omb-completion function _omb_completion_cap { + local cur + _omb_completion_reassemble_breaks : + if [[ -f Capfile ]]; then local recent=$(ls -t .cap_tasks~ Capfile **/*.cap 2> /dev/null | head -n 1) if [[ $recent != '.cap_tasks~' ]]; then @@ -15,9 +18,10 @@ function _omb_completion_cap { cap --all --tasks | cut -d " " -f 2 > .cap_tasks~ fi fi - COMPREPLY=($(compgen -W '$(< .cap_tasks)' -- "${COMP_WORDS[COMP_CWORD]}")) - return 0 + COMPREPLY=($(compgen -W '$(< .cap_tasks)' -- "$cur")) fi + + _omb_completion_resolve_breaks } complete -o default -o nospace -F _omb_completion_cap cap diff --git a/completions/rake.completion.sh b/completions/rake.completion.sh index f139631..98ad024 100644 --- a/completions/rake.completion.sh +++ b/completions/rake.completion.sh @@ -1,17 +1,21 @@ #! bash oh-my-bash.module # Bash completion support for Rake, Ruby Make. -export COMP_WORDBREAKS=${COMP_WORDBREAKS/\:/} +_omb_module_require lib:omb-completion function _omb_completion_rake { + local cur + _omb_completion_reassemble_breaks : + if [[ -f Rakefile ]]; then local recent=$(ls -t .rake_tasks~ Rakefile **/*.rake 2> /dev/null | head -n 1) if [[ $recent != '.rake_tasks~' ]]; then rake --silent --tasks --all | cut -d " " -f 2 > .rake_tasks~ fi - COMPREPLY=($(compgen -W '$(< .rake_tasks~)' -- "${COMP_WORDS[COMP_CWORD]}")) - return 0 + COMPREPLY=($(compgen -W '$(< .rake_tasks~)' -- "$cur")) fi + + _omb_completion_resolve_breaks } complete -o default -o nospace -F _omb_completion_rake rake diff --git a/completions/ssh.completion.sh b/completions/ssh.completion.sh index 3bcb775..fe01b1f 100644 --- a/completions/ssh.completion.sh +++ b/completions/ssh.completion.sh @@ -1,10 +1,12 @@ #! bash oh-my-bash.module # Bash completion support for ssh. -export COMP_WORDBREAKS=${COMP_WORDBREAKS/\:/} +_omb_module_require lib:omb-completion function _omb_completion_ssh { - local cur=${COMP_WORDS[COMP_CWORD]} + local cur + _omb_completion_reassemble_breaks : + if [[ $cur == *@* ]] ; then local -a options=(-P "${cur%%@*}@" -- "${cur#*@}") else @@ -28,7 +30,7 @@ function _omb_completion_ssh { COMPREPLY+=($(compgen -W "$( grep -v '^[[:space:]]*$' /etc/hosts | grep -v '^#' | awk '{for (i=2; i<=NF; i++) print $i}' )" "${options[@]}")) fi - return 0 + _omb_completion_resolve_breaks } complete -o default -o nospace -F _omb_completion_ssh ssh scp diff --git a/lib/omb-completion.sh b/lib/omb-completion.sh new file mode 100644 index 0000000..5fd845d --- /dev/null +++ b/lib/omb-completion.sh @@ -0,0 +1,62 @@ +#! bash oh-my-bash.module +# Copyright 2023 Koichi Murase. +# +# Helper functions for completions +# + +## @fn _omb_completion_reassemble_breaks exclude +## @param[in] $1 exclude Characters to exclude from COMP_WORDSBREAKS +## @var[out] cur[0] Current word after reassembly +## @var[out] cur[1] Part of ${cur[0]} that was originally in previous words +## in COMP_WORDS. +## @arr[out] COMPREPLY This functions empties the array COMPREPLY. +function _omb_completion_reassemble_breaks { + local exclude=$1 + local line=$COMP_LINE point=$COMP_POINT + local breaks=${COMP_WORDBREAKS//[\"\'$exclude]} + + COMPREPLY=() + cur=("${COMP_WORDS[COMP_CWORD]}" '') + + local word rprefix= rword= + for word in "${COMP_WORDS[@]::COMP_CWORD+1}"; do + local space=${line%%"$word"*} + if [[ $space == "$line" ]]; then + # error: COMP_LINE does not contain enough words + return 1 + fi + + word=${word::point - ${#space}} + if [[ $space || $rword == *["$breaks"] || $word == ["$breaks"]* ]]; then + rprefix= + rword=$word + else + rprefix=$rword + rword+=$word + fi + + line=${line:${#space}+${#word}} + ((point -= ${#space} + ${#word})) + ((point >= 0)) || break + done + + cur=("$rword" "$rprefix") +} + +## @fn _omb_completion_resolve_breaks +## Adjust completions generated for the reassembled word +## @var[out] cur[1] Prefix to remove set by _omb_completion_reassemble_breaks +## @arr[out] COMPREPLY This functions empties the array COMPREPLY. +function _omb_completion_resolve_breaks { + if [[ ${cur[1]} ]]; then + local i + for i in "${!COMPREPLY[@]}"; do + if [[ ${COMPREPLY[i]} == "$cur_prefix"* ]]; then + COMPREPLY[i]=${COMPREPLY[i]#"$cur_prefix"} + else + unset -v 'COMPREPLY[i]' + fi + done + COMPREPLY=("${COMPREPLY[@]}") + fi +}