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 Sep 15, 2020
1 parent 4289a0b commit 98576c7
Show file tree
Hide file tree
Showing 6 changed files with 610 additions and 52 deletions.
96 changes: 65 additions & 31 deletions lib/core-complete.sh
Expand Up @@ -992,16 +992,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 "$ins" "b$escape_flags"
INSERT=$comps_fixed_part$ret

else
local ret
ble/string#escape-for-bash-specialchars "$CAND" "$escape_flags"; 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" "$escape_flags"; 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 @@ -1249,6 +1256,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 @@ -1315,13 +1355,10 @@ function ble/complete/cand/unpack {
# -W 補完完了時に空白を挿入しない
# -s sabbrev 候補も一緒に生成する
#
#
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 @@ -1418,10 +1455,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 @@ -1565,7 +1600,7 @@ function ble/complete/util/eval-pathname-expansion {
fi
fi

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

ble/util/invoke-hook dtor
}
Expand All @@ -1589,10 +1624,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 @@ -1610,7 +1645,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 @@ -2148,7 +2183,9 @@ function ble/complete/progcomp/.compgen {
# もし 124 だった場合には is_default_completion に retry を設定する。
if [[ $is_default_completion == retry && ! $_ble_complete_retry_guard ]]; then
local _ble_complete_retry_guard=1
ble/complete/progcomp/.compgen "$@"
opts=:$opts:
opts=${opts//:default:/:}
ble/complete/progcomp/.compgen "${opts//:default:/:}"
return "$?"
fi

Expand Down Expand Up @@ -2302,10 +2339,9 @@ function ble/complete/progcomp {
function ble/complete/source:argument/.generate-user-defined-completion {
shopt -q progcomp || return 1

case :$comp_type: in
(*:a:*) local COMPS=${COMPS::1} COMPV=${COMPV::1} COMP2=$((COMP1+1)) ;;
(*:[mA]:*) local COMPS= COMPV= COMP2=$COMP1 ;;
esac
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 @@ -2394,10 +2430,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
17 changes: 15 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]}

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

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

while
if ((wlen>=0)); then
TE_root="$wtype $wlen $tclen $tplen -- $TE_root"
# TE_root に単語ノードを追加
ble/syntax/tree-enumerate/.add-root-element "$wtype" "$wlen" "$tclen" "$tplen"
tclen=0
fi
((inest>=0))
Expand All @@ -207,7 +219,8 @@ function ble/syntax/tree-enumerate/.initialize {
tplen=${nest[4]}
((tplen>=0&&(tplen+=olen)))

TE_root="${nest[7]} $olen $tclen $tplen -- $TE_root"
# TE_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
28 changes: 18 additions & 10 deletions lib/test-util.sh
Expand Up @@ -14,42 +14,42 @@ ble/test/start-section 'util' 1016
stdout= exit=1
ble/test 'bleopt a:=2'
ble/test 'bleopt a' \
stdout="bleopt a='2'"
stdout="bleopt a=2"
ble/test '[[ $bleopt_a == 2 ]]'
ble/test "bleopt | grep 'bleopt a='" \
stdout="bleopt a='2'"
stdout="bleopt a=2"
ble/test 'bleopt a=3'
ble/test 'bleopt a' \
stdout="bleopt a='3'"
stdout="bleopt a=3"

# setter
function bleopt/check:a { value=123; }
ble/test 'bleopt a=4 && bleopt a'
stdout="bleopt a='123'"
stdout="bleopt a=123"
function bleopt/check:a { false; }
ble/test 'bleopt a=5' \
exit=1
ble/test 'bleopt a' \
stdout="bleopt a='123'"
stdout="bleopt a=123"

# 複数引数
ble/test bleopt f:=10 g:=11
ble/test bleopt f g \
stdout="bleopt f='10'${_ble_term_nl}bleopt g='11'"
stdout="bleopt f=10${_ble_term_nl}bleopt g=11"
ble/test bleopt f=12 g=13
ble/test bleopt f g \
stdout="bleopt f='12'${_ble_term_nl}bleopt g='13'"
stdout="bleopt f=12${_ble_term_nl}bleopt g=13"

# bleopt/declare
ble/test bleopt/declare -v b 6
ble/test bleopt b stdout="bleopt b='6'"
ble/test bleopt b stdout="bleopt b=6"
ble/test bleopt/declare -n c 7
ble/test bleopt c stdout="bleopt c='7'"
ble/test bleopt c stdout="bleopt c=7"
ble/test bleopt d:= e:=
ble/test bleopt/declare -v d 8
ble/test bleopt/declare -n e 9
ble/test bleopt d stdout="bleopt d="
ble/test bleopt e stdout="bleopt e='9'"
ble/test bleopt e stdout="bleopt e=9"
)

# ble/test
Expand Down Expand Up @@ -768,6 +768,14 @@ function is-global() (readonly "$1"; ! local "$1" 2>/dev/null)
ble/test 'ble/util/print-quoted-command echo "" "" ""' stdout="echo '' '' ''"
ble/test 'ble/util/print-quoted-command echo a{1..4}' stdout="echo 'a1' 'a2' 'a3' 'a4'"
)
# ble/string#quote-word
(
ble/test 'ble/string#quote-word' ret=
ble/test 'ble/string#quote-word echo' ret='echo'
ble/test 'ble/string#quote-word "hello world"' ret="'hello world'"
ble/test 'ble/string#quote-word "'\''test'\''"' ret="\'test\'"
ble/test 'ble/string#quote-word "a'\''b'\''c"' ret="a\'b\'c"
)

# ble/string#create-unicode-progress-bar
(
Expand Down
3 changes: 3 additions & 0 deletions memo/ChangeLog.md
Expand Up @@ -123,6 +123,9 @@
- syntax: allow single-character variable name in named redirections `{a}<>` `#D1360` 4760409
- complete: quote `#` and `~` at the beginning of word `#D1362` f62fe54
- decode (`bind`): work around `shopt -s nocasematch` (reported by tigger04) `#D1372` 855cacf
- syntax (tree-enumerate): fix unmodified `wtype` of reconstructed words at the end `#D1385` 1111111
- complete: fix a bug that progcomp retry by 124 caused the default completion again `#D1386` 1111111
- complete: fix bugs that quotation disappears on ambiguous completion `#D1387` 1111111

## Compatibility

Expand Down

0 comments on commit 98576c7

Please sign in to comment.