diff --git a/contrib b/contrib index 4fc0bf65..d2c5eb3b 160000 --- a/contrib +++ b/contrib @@ -1 +1 @@ -Subproject commit 4fc0bf65458c45c5619902160d30ee3631fdf6bb +Subproject commit d2c5eb3b7a6ff24498567d80ea8e0b7ee9f1a1c8 diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md index 0ba272f8..c550fa0f 100644 --- a/docs/ChangeLog.md +++ b/docs/ChangeLog.md @@ -115,6 +115,7 @@ - menu-complete: add `bleopt complete_menu_complete_opts` (requested by DUOLabs333) `#D1911` 6a21ebb - edit (`magic-space`): support `bleopt edit_magic_expand=...:alias` (requested by telometto) `#D1912` 63da2ac - auto-complete: cancel auto-complete for `magic-space` `#D1913` 01b4f67 +- complete: support ambiguous completion for command paths `#D1922` xxxxxxx ## Changes @@ -331,8 +332,8 @@ - complete: suppress error messages for non-bash_completion `_parse_help` (reported by nik312123) `#D1900` 267de7f - prompt: fix the marker position for the readline variable `show-mode-in-prompt` (reported by Strykar) `#D1903` 09bb4d3 - highlight: fix a bug that `bleopt filename_ls_colors` is not working (reported by qoreQyaS) `#D1919` b568ade -- bind: fix M-C-@, C-x C-@, and M-C-x (`bash-4.2 -o emacs`) `#D1920` xxxxxxx -- complete (action:file): support `ble/syntax-raw` in the filename extraction (reported by qoreQyaS) `#D1921` xxxxxxx +- bind: fix M-C-@, C-x C-@, and M-C-x (`bash-4.2 -o emacs`) `#D1920` a410b03 +- complete (action:file): support `ble/syntax-raw` in the filename extraction (reported by qoreQyaS) `#D1921` 32277da ## Documentation diff --git a/lib/core-complete.sh b/lib/core-complete.sh index af60050e..9ea1fb3a 100644 --- a/lib/core-complete.sh +++ b/lib/core-complete.sh @@ -2290,34 +2290,51 @@ function ble/complete/source:command/.contract-by-slashes { ' } +## @fn ble/complete/source:command/gen.1 function ble/complete/source:command/gen.1 { - local COMPS=$COMPS COMPV=$COMPV - ble/complete/source/reduce-compv-for-ambiguous-match + # Note #D1922: パス名コマンドの曖昧補完は compgen -c ではなく自前で処理する。 + # ディレクトリ名に関しては ble/complete/source:command/gen の側で生成されるの + # でここでは生成しない。 + if [[ $COMPV == */* && :$comp_type: == *:[maA]:* ]]; then + local ret + ble/complete/source:file/.construct-pathname-pattern "$COMPV" + ble/complete/util/eval-pathname-expansion "$ret"; (($?==148)) && return 148 + ble/complete/source/test-limit "${#ret[@]}" || return 1 + ble/array#filter ret '[[ ! -d $1 && -x $1 ]]' + ((${#ret[@]})) && printf '%s\n' "${ret[@]}" - # Note: cygwin では cyg,x86,i68 等で始まる場合にとても遅い。 - # 他の環境でも空の補完を実行すると遅くなる可能性がある。 - local slow_compgen= - if [[ ! $COMPV ]]; then - slow_compgen=1 - elif [[ $OSTYPE == cygwin* ]]; then - case $COMPV in - (?|cy*|x8*|i6*) - slow_compgen=1 ;; - esac - fi + local COMPS=$COMPS COMPV=$COMPV + ble/complete/source/reduce-compv-for-ambiguous-match - # Note: 何故か compgen -A command はクォート除去が実行されない。 - # compgen -A function はクォート除去が実行される。 - # 従って、compgen -A command には直接 COMPV を渡し、 - # compgen -A function には compv_quoted を渡す。 - if [[ $slow_compgen ]]; then - shopt -q no_empty_cmd_completion && return 0 - ble/util/conditional-sync \ - 'builtin compgen -c -- "$COMPV"' \ - '! ble/complete/check-cancel' 128 progressive-weight else - builtin compgen -c -- "$COMPV" + local COMPS=$COMPS COMPV=$COMPV + ble/complete/source/reduce-compv-for-ambiguous-match + + # Note: cygwin では cyg,x86,i68 等で始まる場合にとても遅い。他の環境でも空 + # の補完を実行すると遅くなる可能性がある。 + local slow_compgen= + if [[ ! $COMPV ]]; then + slow_compgen=1 + elif [[ $OSTYPE == cygwin* ]]; then + case $COMPV in + (?|cy*|x8*|i6*) + slow_compgen=1 ;; + esac + fi + + # Note: 何故か compgen -A command はクォート除去が実行されない。compgen -A + # function はクォート除去が実行される。従って、compgen -A command には直 + # 接 COMPV を渡し、compgen -A function には compv_quoted を渡す。 + if [[ $slow_compgen ]]; then + shopt -q no_empty_cmd_completion && return 0 + ble/util/conditional-sync \ + 'builtin compgen -c -- "$COMPV"' \ + '! ble/complete/check-cancel' 128 progressive-weight + else + builtin compgen -c -- "$COMPV" + fi fi + if [[ $COMPV == */* ]]; then local q="'" Q="'\''" local compv_quoted="'${COMPV//$q/$Q}'" diff --git a/note.txt b/note.txt index ff43b99e..c5c7fed1 100644 --- a/note.txt +++ b/note.txt @@ -2,10 +2,16 @@ 拡張 - * プログラム補完に於いて、 - 補完関数内で compopt -o filter_by_prefix を指定した場合、 + * compopt -o ble/filter-by-prefix + プログラム補完に於いて補完関数内で指定した場合、 生成される候補を接頭辞が一致するものだけに絞り込む。 + * compopt -o ble/syntax-raw + * compopt -o ble/no-mark-directories + * compopt -o ble/prog-trim + * compopt -o ble/no-default + * HISTCONTROL=strip + 制限 * ble.sh を attach しているとき builtin read -e は動かない。 @@ -1855,6 +1861,25 @@ bash_tips - leakvars - keymap の移動 (これは別 commit にする?) +2023-01-24 + + * complete: パス名の曖昧補間でできるだけ各種展開を保持したい + + 現在の実装では quote-insert で生成候補が COMPV に文字列を追加した物の場合に + は COMPV の部分については COMPS で置き換える様になっている。しかし、遡った + 置換がある場合には問答無用で全体が展開されてしまうので、曖昧補間が起こった + 時には必ず全体が展開されてしまう。 + + COMPS を unquoted / 毎に切って、eval して対応する部分 compv を生成して、最 + 長一致するものについて部分 comps で置き換える。unquote / 毎に切るのは個別の + quote-insert でやっていたら大変なので、事前に処理しておく事にする。 + + quote-insert.batch で awk で処理する場合にどうするのかについては微妙。awk + の内部で unquote / 毎に切るのを実装するか或いは外で切ったものを何とかして + awk に渡すかする。外で定義したものを渡す方が見通しが良いと思われる。 + + ToDo 2022-02-03 に関連項目がある。 + 2022-12-09 * edit,complete: alias expansion で alias sudo='sudo ' 等による引数の展開に対応? @@ -6664,6 +6689,33 @@ bash_tips Done (実装ログ) ------------------------------------------------------------------------------- +2023-01-24 + + * 2023-01-02 complete: コマンド名(パス名)の曖昧補間・部分一致など [#D1922] + + 現在の実装だと PATH に見つかっているコマンドについては曖昧補間が有効である + が、パスを指定して補完している時にはそれが無効になっている。関数名について + は / が入っていてもちゃんと生成できている。 + + 補完対象に / が含まれている場合にはファイル名補完と同様にパターンで候補生成 + を行って、その結果を [[ -x file ]] でフィルタする様にするべきなのではないか。 + + ? ok: チルダ展開が展開されてしまう。調べてみると compgen -c の場合にはちゃ + んと ~ が保持される。なので、おそらくチルダ展開の復元などを処理していなかっ + たのだろう。 + + 実はディレクトリ名に関しても同様に処理する必要があったのでは。 + + →何故展開されるのかについて調べてみたら ~ を復元するのは $CAND == + "$COMPV"* の時だけだが、曖昧補完の時にはこれが常に不成立の為に復元しない + という事。これに真面目に対応しようと思ったら COMPS を unquoted / 毎に切っ + て、eval して対応する部分 compv を生成して、最長一致するものについて部分 + comps で置き換えるという処理にする必要がある。これは面倒である。 + + そして、これについては通常引数の曖昧補間についても同様にチルダ展開が展開 + されてしまう。もし対応するとしたらまとめて対応する必要がある。これは独立 + した項目にする事にした。 + 2022-12-13 * fzf-completion: ファイル名に付く suffix の判定ができていない (reported by qoreQyaS) [#D1921] diff --git a/src/util.sh b/src/util.sh index a8e58dd0..2fa1c551 100644 --- a/src/util.sh +++ b/src/util.sh @@ -589,11 +589,25 @@ function ble/array#insert-before { '; builtin eval -- "${_ble_local_script//ARR/$1}" } ## @fn ble/array#filter arr predicate +## @param[in] predicate +## When a function name is specified, the target string is passed +## to the function as the first argument. Otherwise, the value of +## PREDICATE is treated as a command string where the argument can +## be referenced as $1. +function ble/array#filter/.eval { + builtin eval -- "$_ble_local_predicate_cmd" +} function ble/array#filter { + local _ble_local_predicate=$2 + if [[ $2 == *'$'* ]] || ! ble/is-function "$2"; then + _ble_local_predicate=ble/array#filter/.eval + _ble_local_predicate_cmd=$2 + fi + local _ble_local_script=' local -a aARR=() eARR for eARR in "${ARR[@]}"; do - "$2" "$eARR" && ble/array#push "aARR" "$eARR" + "$_ble_local_predicate" "$eARR" && ble/array#push "aARR" "$eARR" done ARR=("${aARR[@]}") '; builtin eval -- "${_ble_local_script//ARR/$1}"