Skip to content

Commit

Permalink
complete: fix bugs that quotation disappears on ambiguous completion
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Dec 2, 2020
1 parent 2bbd0fb commit 048f17e
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 34 deletions.
112 changes: 80 additions & 32 deletions lib/core-complete.sh
Expand Up @@ -206,16 +206,23 @@ function ble/complete/action/util/quote-insert {
[[ $comps_flags == *B* && $COMPS == *'\' && $ins == '\'* ]] && ins=${ins:1}

INSERT=$COMPS$ins
elif [[ $comps_fixed && $CAND == "${comps_fixed#*:}"* ]]; then
local comps_fixed_part=${COMPS::${comps_fixed%%:*}}
local compv_fixed_part=${comps_fixed#*:}
local ins=${CAND:${#compv_fixed_part}}
local ret; ble/string#escape-for-bash-specialchars-in-brace "$ins"
INSERT=$comps_fixed_part$ret

else
local ret
ble/string#escape-for-bash-specialchars "$CAND"; INSERT=$ret
local ins=$CAND comps_fixed_part= compv_fixed_part=
if [[ $comps_fixed && $CAND == "${comps_fixed#*:}"* ]]; then
comps_fixed_part=${COMPS::${comps_fixed%%:*}}
compv_fixed_part=${comps_fixed#*:}
ins=${CAND:${#compv_fixed_part}}
fi

local ret; ble/complete/string#escape-for-completion-context "$ins"; ins=$ret
case $comps_flags in
(*S*) ins=\'$ins ;;
(*E*) ins=\$\'$ins ;;
(*D*) ins=\"$ins ;;
(*I*) ins=\$\"$ins ;;
esac

INSERT=$comps_fixed_part$ins
fi
}

Expand Down Expand Up @@ -453,6 +460,39 @@ function ble/complete/action:variable/init-menu-item {
#==============================================================================
# source

## 関数 ble/complete/source/reduce-compv-for-ambiguous-match
## 曖昧補完の為に擬似的な COMPV と COMPS を生成・設定します。
## @var[in,out] COMPS COMPV
function ble/complete/source/reduce-compv-for-ambiguous-match {
[[ :$comp_type: == *:[amA]:* ]] || return 0

local comps=$COMPS compv=$COMPV
local comps_prefix= compv_prefix=
if [[ $comps_fixed ]]; then
comps_prefix=${comps::${comps_fixed%%:*}}
compv_prefix=${comps_fixed#*:}
compv=${COMPV:${#compv_prefix}}
fi

case $comps_flags in
(*S*) comps_prefix=$comps_prefix\' ;;
(*E*) comps_prefix=$comps_prefix\$\' ;;
(*D*) comps_prefix=$comps_prefix\" ;;
(*I*) comps_prefix=$comps_prefix\$\" ;;
esac

if [[ $compv && :$comp_type: == *:a:* ]]; then
compv=${compv::1}
ble/complete/string#escape-for-completion-context "$compv"
comps=$ret
else
compv= comps=
fi

COMPV=$compv_prefix$compv
COMPS=$comps_prefix$comps
}

## 関数 ble/complete/cand/yield ACTION CAND DATA
## @param[in] ACTION
## @param[in] CAND
Expand Down Expand Up @@ -514,13 +554,14 @@ function ble/complete/cand/unpack {
##

# source:wordlist

#
# -r 指定された単語をエスケープせずにそのまま挿入する
# -W 補完完了時に空白を挿入しない
#
function ble/complete/source:wordlist {
[[ $comps_flags == *v* ]] || return 1
case :$comp_type: in
(*:a:*) local COMPS=${COMPS::1} COMPV=${COMPV::1} ;;
(*:[mA]:*) local COMPS= COMPV= ;;
esac
local COMPS=$COMPS COMPV=$COMPV
ble/complete/source/reduce-compv-for-ambiguous-match
[[ $COMPV =~ ^.+/ ]] && COMP_PREFIX=${BASH_REMATCH[0]}

# process options
Expand Down Expand Up @@ -613,10 +654,8 @@ function ble/complete/source:command/.contract-by-slashes {
}

function ble/complete/source:command/gen.1 {
case :$comp_type: in
(*:a:*) local COMPS=${COMPS::1} COMPV=${COMPV::1} ;;
(*:[mA]:*) local COMPS= COMPV= ;;
esac
local COMPS=$COMPS COMPV=$COMPV
ble/complete/source/reduce-compv-for-ambiguous-match

# Note: cygwin では cyg,x86,i68 等で始まる場合にとても遅い。
# 他の環境でも空の補完を実行すると遅くなる可能性がある。
Expand Down Expand Up @@ -748,7 +787,16 @@ function ble/complete/util/eval-pathname-expansion {
fi
fi

IFS= GLOBIGNORE= eval 'ret=(); ret=($pattern)' 2>/dev/null
if ble/util/is-cygwin-slow-glob "$pattern"; then # Note: #D1168
if shopt -q failglob &>/dev/null || shopt -q nullglob &>/dev/null; then
pattern=
else
set -f
ble/array#push dtor 'set +f'
fi
fi

IFS= GLOBIGNORE= builtin eval "ret=(); ret=($pattern)" 2>/dev/null

ble/util/invoke-hook dtor
}
Expand All @@ -772,10 +820,10 @@ function ble/complete/source:file/.construct-ambiguous-pathname-pattern {
for name in "${names[@]}"; do
((i++)) && pattern=$pattern/
if [[ $name ]]; then
ble/string#escape-for-bash-glob "${name::fixlen}"
ble/string#quote-word "${name::fixlen}"
pattern=$pattern$ret*
for ((j=fixlen;j<${#name};j++)); do
ble/string#escape-for-bash-glob "${name:j:1}"
ble/string#quote-word "${name:j:1}"
pattern=$pattern$ret*
done
fi
Expand All @@ -793,7 +841,7 @@ function ble/complete/source:file/.construct-pathname-pattern {
elif [[ :$comp_type: == *:[mA]:* ]]; then
ble/complete/source:file/.construct-ambiguous-pathname-pattern "$path" 0; local pattern=$ret
else
ble/string#escape-for-bash-glob "$path"; local pattern=$ret*
ble/string#quote-word "$path"; local pattern=$ret*
fi
ret=$pattern
}
Expand Down Expand Up @@ -1221,8 +1269,9 @@ function ble/complete/source:argument/.progcomp {
# もし 124 だった場合には is_default_completion に retry を設定する。
if [[ $is_default_completion == retry && ! $_ble_complete_retry_guard ]]; then
local _ble_complete_retry_guard=1
ble/complete/source:argument/.progcomp "$@"
return
ble/path#remove opts default
ble/complete/source:argument/.progcomp "$opts"
return "$?"
fi

[[ $compgen ]] || return 1
Expand Down Expand Up @@ -1301,10 +1350,11 @@ function ble/complete/source:argument/.progcomp {
## @var[in] (variables set by ble/syntax/parse)
##
function ble/complete/source:argument/.generate-user-defined-completion {
case :$comp_type: in
(*:a:*) local COMPS=${COMPS::1} COMPV=${COMPV::1} COMP2=$((COMP1+1)) ;;
(*:[mA]:*) local COMPS= COMPV= COMP2=$COMP1 ;;
esac
shopt -q progcomp || return 1

local COMPS=$COMPS COMPV=$COMPV
ble/complete/source/reduce-compv-for-ambiguous-match
[[ :$comp_type: == *:[amA]:* ]] && local COMP2=$COMP1

local comp_words comp_line comp_point comp_cword
ble/syntax:bash/extract-command "$COMP2" || return 1
Expand Down Expand Up @@ -1392,10 +1442,8 @@ function ble/complete/source:argument {

function ble/complete/source/compgen {
[[ $comps_flags == *v* ]] || return 1
case :$comp_type: in
(*:a:*) local COMPS=${COMPS::1} COMPV=${COMPV::1} ;;
(*:[mA]:*) local COMPS= COMPV= ;;
esac
local COMPS=$COMPS COMPV=$COMPV
ble/complete/source/reduce-compv-for-ambiguous-match

local compgen_action=$1
local action=$2
Expand Down
15 changes: 13 additions & 2 deletions lib/core-syntax.sh
Expand Up @@ -158,6 +158,17 @@ _ble_syntax_TREE_WIDTH=5
# ble/syntax/tree-enumerate-children proc
# ble/syntax/tree-enumerate-in-range beg end proc

function ble/syntax/tree-enumerate/.add-root-element {
local wtype=$1 wlen=$2 tclen=$3 tplen=$4

# Note: wtype は単語に格納される時に EndWtype テーブルで変換される。
# ble/syntax:bash/ctx-command/check-word-end の実装を参照の事。
[[ ! ${wtype//[0-9]} && ${_ble_syntax_bash_command_EndWtype[wtype]} ]] &&
wtype=${_ble_syntax_bash_command_EndWtype[wtype]}

root="$wtype $wlen $tclen $tplen -- $root"
}

## 関数 ble/syntax/tree-enumerate/.initialize
##
## @var[in] iN
Expand Down Expand Up @@ -194,7 +205,7 @@ function ble/syntax/tree-enumerate/.initialize {

while
if ((wlen>=0)); then
root="$wtype $wlen $tclen $tplen -- $root"
ble/syntax/tree-enumerate/.add-root-element "$wtype" "$wlen" "$tclen" "$tplen"
tclen=0
fi
((inest>=0))
Expand All @@ -207,7 +218,7 @@ function ble/syntax/tree-enumerate/.initialize {
tplen=${nest[4]}
((tplen>=0&&(tplen+=olen)))

root="${nest[7]} $olen $tclen $tplen -- $root"
ble/syntax/tree-enumerate/.add-root-element "${nest[7]}" "$olen" "$tclen" "$tplen"

wtype=${nest[2]} wlen=${nest[1]} nlen=${nest[3]} tclen=0 tplen=${nest[5]}
((wlen>=0&&(wlen+=olen),
Expand Down
33 changes: 33 additions & 0 deletions src/util.sh
Expand Up @@ -694,6 +694,30 @@ function ble/string#escape-for-bash-specialchars-in-brace {
fi
}

function ble/string#quote-word {
ret=$1

local opts=$2 sgrq= sgr0=
if [[ $opts ]]; then
local rex=':sgrq=([^:]*):'
[[ :$opts: =~ $rex ]] &&
sgrq=${BASH_REMATCH[1]} sgr0=$_ble_term_sgr0
rex=':sgr0=([^:]*):'
[[ :$opts: =~ $rex ]] &&
sgr0=${BASH_REMATCH[1]}
fi

local chars=$_ble_term_IFS'"`$\<>()|&;*?[]!^=:{,}#~' q=\'
if [[ $ret == *["$chars"]* ]]; then
local Q="'$sgr0\'$sgrq'"
ret=$sgrq$q${ret//$q/$Q}$q$sgr0
ret=${ret#$q$q} ret=${ret%$q$q}
elif [[ $ret == *["$q"]* ]]; then
local Q="\'"
ret=${ret//$q/$Q}
fi
}

## 関数 ble/string#create-unicode-progress-bar value max width
## @var[out] ret
function ble/string#create-unicode-progress-bar {
Expand Down Expand Up @@ -1152,6 +1176,15 @@ else
}
fi

## 関数 ble/util/is-cygwin-slow-glob word
## Cygwin では // で始まるパスの展開は遅い (#D1168) のでその判定を行う。
function ble/util/is-cygwin-slow-glob {
# Note: core-complete.sh ではエスケープを行うので
# "'//...'" 等の様な文字列が "$1" に渡される。
[[ ( $OSTYPE == cygwin || $OSTYPE == msys ) && ${1#\'} == //* && ! -o noglob ]] &&
ble/util/has-glob-pattern "$1"
}

## 関数 ble/util/eval-pathname-expansion pattern
## @var[out] ret
function ble/util/eval-pathname-expansion {
Expand Down

0 comments on commit 048f17e

Please sign in to comment.