Skip to content

Commit

Permalink
complete, syntax (alias): exclude inactive aliases and fix the other …
Browse files Browse the repository at this point in the history
…quoting behavior
  • Loading branch information
akinomyoga committed Dec 19, 2021
1 parent a0b2ad2 commit d6242a7
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 46 deletions.
3 changes: 3 additions & 0 deletions docs/ChangeLog.md
Expand Up @@ -128,6 +128,9 @@
- syntax: revert 371a5a4 and generate empty completion source on syntax error `#D1609` e09fcab
- syntax: strictly check variable names of `for`-statements `#D1692` d056547
- widget `self-insert`: untranslate control chars and insert the last character `#D1696` 5ff3021
- complete (`source:command`): exclude inactive aliases `#D1715` 0000000
- complete (`source:command`): not quote aliases and keywords `#D1715` 0000000
- highlight (`wtype=CTX_CMDI`): check alias names before shell expansions `#D1715` 0000000

## Fixes

Expand Down
68 changes: 50 additions & 18 deletions lib/core-complete.sh
Expand Up @@ -1276,7 +1276,9 @@ function ble/complete/action/quote-insert {
fi

local escape_flags=$quote_escape_flags
if [[ $quote_action == progcomp ]]; then
if [[ $quote_action == command ]]; then
[[ $DATA == *:noquote:* || $COMPS == "$COMPV" && ( $CAND == '[[' || $CAND == '!' ) ]] && return 0
elif [[ $quote_action == progcomp ]]; then
[[ $comp_opts == *:noquote:* ]] && return 0

# bash-completion には compopt -o nospace として、
Expand Down Expand Up @@ -1420,7 +1422,9 @@ function ble/complete/action/quote-insert.batch/awk {
function quote_insert(cand) {
# progcomp 特有
if (quote_action == "progcomp") {
if (quote_action == "command") {
if (comps == compv && cand ~ /^(\[\[|]]|!)$/) return cand;
} else if (quote_action == "progcomp") {
if (is_noquote) return cand;
if (is_nospace && cand ~ / $/ && !is_file(cand)) return cand;
}
Expand Down Expand Up @@ -1766,7 +1770,7 @@ function ble/complete/action:command/get-desc {
case $type in
($_ble_attr_CMD_ALIAS)
local ret
ble/util/expand-alias "$CAND"
ble/alias#expand "$CAND"
title=alias value=$ret ;;
($_ble_attr_CMD_FILE)
local path; ble/util/assign path 'type -p -- "$CAND"'
Expand Down Expand Up @@ -2298,10 +2302,15 @@ function ble/complete/source:command {

ble/complete/source/test-limit ${#arr[@]} || return 1

# keyword 判定用
local rex_keyword=
[[ $COMPS != $COMPV ]] &&
local rex_keyword='^(if|then|else|elif|fi|case|esac|for|select|while|until|do|done|function|time|[{}]|\[\[|coproc)$'
local action=command "${_ble_complete_yield_varnames[@]/%/=}" # WA #D1570 safe
ble/complete/cand/yield.initialize "$action"

# 無効 keyword, alias 判定用
local is_quoted=
[[ $COMPS != "$COMPV" ]] && is_quoted=1
local rex_keyword='^(if|then|else|elif|fi|case|esac|for|select|while|until|do|done|function|time|[!{}]|\[\[|coproc|\]\]|in)$'
local expand_aliases=
shopt -q expand_aliases && expand_aliases=1

local cand icand=0 cands
for cand in "${arr[@]}"; do
Expand All @@ -2311,18 +2320,41 @@ function ble/complete/source:command {
# 厳密一致のディレクトリ名が混入するので削除する。
[[ $cand != */ && -d $cand ]] && ! type "$cand" &>/dev/null && continue

# #D1691 keyword は quote されている場合には無効
if [[ $rex_keyword && $cand =~ $rex_keyword ]]; then
local type; ble/util/type type "$cand"
((${#type[@]}==1)) && continue
if [[ $is_quoted ]]; then
local disable_count=
# #D1691 keyword は quote されている場合には無効
[[ $cand =~ $rex_keyword ]] && ((disable_count++))
# #D1715 alias も quote されている場合には無効
[[ $expand_aliases ]] && ble/is-alias "$cand" && ((disable_count++))
if [[ $disable_count ]]; then
local type; ble/util/type type "$cand"
((${#type[@]}>disable_count)) || continue
fi
else
# 'in' と ']]' は alias でない限り常にエラー
[[ $cand == ']]' || $cand == in ]] &&
! { [[ $expand_aliases ]] && ble/is-alias "$cand"; } &&
continue

if [[ ! $expand_aliases ]]; then
# #D1715 expand_aliases が無効でも compgen -c は alias を列挙してしまうので、
# ここで alias は除外 (type は expand_aliases をちゃんと考慮してくれる)。
ble/is-alias "$cand" && ! type "$cand" &>/dev/null && continue
fi

# alias は quote されては困るので、quote される可能性のある文字を含んでい
# る場合は個別に :noquote: 指定で yield する [ Note: alias 内で許される特
# 殊文字は !#%-~^[]{}+*:@,.?_ である。更にその中で escape/quote の対象と
# なり得る文字は、[*?]{,}!^~#: だけである。_.@+%- は quote されない ]。
if ble/string#match "$cand" '[][*?{,}!^~#]' && ble/is-alias "$cand"; then
ble/complete/cand/yield "$action" "$cand" :noquote:
continue
fi
fi

cands[icand++]=$cand
done
((icand)) || return 1

local "${_ble_complete_yield_varnames[@]/%/=}" # WA #D1570 safe
ble/complete/cand/yield.initialize command
ble/complete/cand/yield.batch command
ble/complete/cand/yield.batch "$action"
}

# source:file, source:dir
Expand Down Expand Up @@ -3518,7 +3550,7 @@ function ble/complete/progcomp {
((_ble_bash<50000)) || shopt -q progcomp_alias || break

local ret
ble/util/expand-alias "$cmd"
ble/alias#expand "$cmd"
[[ $ret == "$cmd" ]] && break
ble/complete/progcomp/.split-alias-words "$ret"
if ((${#ret[@]}==0)); then
Expand Down Expand Up @@ -4590,7 +4622,7 @@ function ble/complete/source:option {
local alias_checked=' '
while local ret; ! ble/complete/mandb/load-cache "$cmd"; do
alias_checked=$alias_checked$cmd' '
ble/util/expand-alias "$cmd" || return 1
ble/alias#expand "$cmd" || return 1
local words; ble/string#split-words ret "$ret"; words=("${ret[@]}")

# 変数代入は読み飛ばし
Expand Down
12 changes: 10 additions & 2 deletions lib/core-syntax.sh
Expand Up @@ -3488,7 +3488,7 @@ function ble/syntax:bash/ctx-command/check-word-end {

if ((ctx==CTX_CMDI)); then
local ret
ble/util/expand-alias "$word"; local word_expanded=$ret
ble/alias#expand "$word"; local word_expanded=$ret

# キーワードの処理
if ((wt!=CTX_CMDXV)); then # Note: 変数代入の直後はキーワードは処理しない
Expand Down Expand Up @@ -6836,6 +6836,14 @@ function ble/progcolor/highlight-filename/.single.wattr {
local p0=${1%%:*} p1=${1#*:}
local wtxt=${text:p0:p1-p0}

# alias はシェル展開等を行う前に判定するべき
if ((wtype==CTX_CMDI)) && ble/alias#active "$wtxt"; then
# Note: [*?] 等の文字が含まれている alias 名の場合 failglob するかもしれ
# ないが、実際は展開されるので問題ない。
ble/progcolor/wattr#setattr "$p0" "$ATTR_CMD_ALIAS"
return 0
fi

local path_opts=after-sep:$highlight_eval_opts
# チルダ展開の文脈でない時には抑制
[[ $wtxt == '~'* ]] && ((_ble_syntax_attr[p0]!=ATTR_TILDE)) && path_opts=$path_opts:notilde
Expand Down Expand Up @@ -7042,7 +7050,7 @@ function ble/progcolor {
checked="$checked$cmd "

local ret
ble/util/expand-alias "$cmd"
ble/alias#expand "$cmd"
ble/string#split-words ret "$ret"
[[ $checked == *" $ret "* ]] && break
cmd=$ret
Expand Down
22 changes: 11 additions & 11 deletions lib/test-util.sh
Expand Up @@ -1353,25 +1353,25 @@ function is-global() (readonly "$1"; ! local "$1" 2>/dev/null)
ble/test 'ble/util/type ret ble/fun1#meth' ret=
)

# ble/util/expand-alias
# ble/alias#expand
(
shopt -s expand_aliases

# Note: 複数段階の展開は実行しない
alias aaa1='aaa2 world'
ble/test 'ble/util/expand-alias aaa1' ret='aaa2 world'
ble/test 'ble/alias#expand aaa1' ret='aaa2 world'
alias aaa2='aaa3 hello'
ble/test 'ble/util/expand-alias aaa2' ret='aaa3 hello'
ble/test 'ble/util/expand-alias aaa1' ret='aaa2 world'
ble/test 'ble/alias#expand aaa2' ret='aaa3 hello'
ble/test 'ble/alias#expand aaa1' ret='aaa2 world'
alias aaa3='aaa4'
ble/test 'ble/util/expand-alias aaa3' ret='aaa4'
ble/test 'ble/util/expand-alias aaa2' ret='aaa3 hello'
ble/test 'ble/util/expand-alias aaa1' ret='aaa2 world'
ble/test 'ble/alias#expand aaa3' ret='aaa4'
ble/test 'ble/alias#expand aaa2' ret='aaa3 hello'
ble/test 'ble/alias#expand aaa1' ret='aaa2 world'
alias aaa4='echo'
ble/test 'ble/util/expand-alias aaa4' ret='echo'
ble/test 'ble/util/expand-alias aaa3' ret='aaa4'
ble/test 'ble/util/expand-alias aaa2' ret='aaa3 hello'
ble/test 'ble/util/expand-alias aaa1' ret='aaa2 world'
ble/test 'ble/alias#expand aaa4' ret='echo'
ble/test 'ble/alias#expand aaa3' ret='aaa4'
ble/test 'ble/alias#expand aaa2' ret='aaa3 hello'
ble/test 'ble/alias#expand aaa1' ret='aaa2 world'
)

# ble/util/is-stdin-ready
Expand Down
35 changes: 33 additions & 2 deletions note.txt
Expand Up @@ -1635,11 +1635,17 @@ bash_tips

2021-12-18

* complete (source:command): quote していても alais が候補として生成されている

* bleopt menu_align_{min,max}
これは別項目で議論する。

* deprecated functions の枠組みを整える。

散発的に deprecate して行くと毎回設定を変更しなければならず面倒なので、
version を指定して特定の version 以降になった時に限り初回だけ警告を表示する
様にするのが良い。

((_ble_version>=500)) && ..... と言った具合。

* complete: FIGNORE と -o filenames

どうやら元の bash では -o filenames が指定された時にのみ FIGNORE が使われる
Expand Down Expand Up @@ -5692,6 +5698,31 @@ bash_tips

2021-12-18

* complete (source:command): quote していても alias が候補として生成されている [#D1715]
その為に、menu の中でエラー着色されている。

うーん。特に自分で alias を生成している訳ではなくて compgen -c -- s 等の時
点で alias が生成される様だ。一方で、 compgen -c -- "'s'" 等とすると、何も
生成されなくなってしまうので alias を除外した生成にする事は難しそうである。

更に compgen -c は expand_aliases が off になっていても alias を列挙する様だ。

一方で、for 等の keyword はどの様に判定しているのだったか。うーん。
source:command で filter している様だ。同じ箇所で alias のチェックもする事
にした。

x fixed: 実装してみたら全て赤くなっている→ これは今回の編集ではなくて前回
の commit の時点で既に駄目になっている。#D1714 で修正した。

x fixed: alias は noquote を付加する必要があるのでは? → 修正した。その他に
も ! や [[ 等は quote しない様にする必要がある。

x fixed: alias が *? 等の文字を含んでいる場合コマンド着色でエラーになってし
まう。修正した。

と思ったが、考えてみれば、そもそも alias 名に一致している場合には展開を試
みる前に alias に確定させるべきなのではないか。

* menu-complete で 30s かかるという話 (2/2) yield quote-insert 高速化の試み [#D1714]
https://github.com/banoris/dotfiles/issues/11

Expand Down
4 changes: 2 additions & 2 deletions src/edit.sh
Expand Up @@ -5994,7 +5994,7 @@ function ble/widget/alias-expand-line.proc {
ble/widget/alias-expand-line.proc
elif [[ $wtype && ! ${wtype//[0-9]} ]] && ((wtype==_ble_ctx_CMDI)); then
local word=${_ble_edit_str:wbegin:wlen}
local ret; ble/util/expand-alias "$word"
local ret; ble/alias#expand "$word"
[[ $word == "$ret" ]] && return 0
changed=1
ble/widget/.replace-range "$wbegin" $((wbegin+wlen)) "$ret"
Expand Down Expand Up @@ -6061,7 +6061,7 @@ function ble/widget/shell-expand-line.expand-word {

# エイリアス展開
if ((wtype==_ble_ctx_CMDI)); then
ble/util/expand-alias "$word"
ble/alias#expand "$word"
[[ $word != $ret ]] && return 0
fi

Expand Down
58 changes: 47 additions & 11 deletions src/util.sh
Expand Up @@ -2910,17 +2910,53 @@ function ble/util/type {
ble/util/assign-array "$1" 'builtin type -a -t -- "$3" 2>/dev/null' "$2"; local ext=$?
return "$ext"
}
## @fn ble/util/expand-alias word
## @var[out] ret
## @exit
## エイリアス展開が実際に行われた時に成功します。
function ble/util/expand-alias {
ret=$1
local type; ble/util/type type "$ret"
[[ $type != alias ]] && return 1
local data; ble/util/assign data 'LC_ALL=C alias "$ret"' &>/dev/null
[[ $data == 'alias '*=* ]] && builtin eval "ret=${data#alias *=}"
}

if ((_ble_bash>=40000)); then
function ble/is-alias {
[[ ${BASH_ALIASES[$1]+set} ]]
}
function ble/alias#active {
shopt -q expand_aliases &&
[[ ${BASH_ALIASES[$1]+set} ]]
}
## @fn ble/alias#expand word
## @var[out] ret
## @exit
## エイリアス展開が実際に行われた時に成功します。
function ble/alias#expand {
ret=$1
shopt -q expand_aliases &&
ret=${BASH_ALIASES[$ret]-$ret}
}
function ble/alias/list {
ret=("${!BASH_ALIASES[@]}")
}
else
function ble/is-alias {
[[ $1 != *=* ]] && alias "$1" >/dev/null
}
function ble/alias#active {
shopt -q expand_aliases &&
[[ $1 != *=* ]] && alias "$1" >/dev/null
}
function ble/alias#expand {
ret=$1
local type; ble/util/type type "$ret"
[[ $type != alias ]] && return 1
local data; ble/util/assign data 'LC_ALL=C alias "$ret"' &>/dev/null
[[ $data == 'alias '*=* ]] && builtin eval "ret=${data#alias *=}"
}
function ble/alias/list {
ret=()
local data iret=0
ble/util/assign-array data 'alias -p'
for data in "${data[@]}"; do
[[ $data == 'alias '*=* ]] &&
data=${data%%=*} &&
builtin eval "ret[iret++]=${data#alias }"
done
}
fi

if ((_ble_bash>=40000)); then
# #D1341 対策 変数代入形式だと組み込みコマンドにロケールが適用されない。
Expand Down

0 comments on commit d6242a7

Please sign in to comment.