Skip to content

Commit

Permalink
progcomp: pass original command path to completion functions
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Jan 28, 2024
1 parent 9045fb8 commit 0cf0383
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
- progcomp: work around slow `make` completion in large repository (reported by blackteahamburger) `#D2117` 5f3a0010
- util(TRAPEXIT): fix condition for `stty sane` in Cygwin `#D2118` a7f604e1
- progcomp: fix the detection of the zoxide completion (reported by 6801318d8d) `#D2120` 29cd8f10
- progcomp: pass original command path to completion functions (reported by REmerald) `#D2125` xxxxxxxx

## Contrib

Expand Down
19 changes: 14 additions & 5 deletions lib/core-complete.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3706,10 +3706,12 @@ function ble/complete/progcomp/patch:cobraV2/get_completion_results.invoke {
## コロン区切りのオプションリストです。
##
## initial ... 最初の単語 (コマンド名) の補完に用いる関数を指定します。
## default ... 既定の補完設定 (complete -D) を用います。
##
## @param[in,opt] cmd
## プログラム補完規則を検索するのに使う名前を指定します。
## 省略した場合 ${comp_words[0]} が使われます。
## プログラム補完規則を検索するのに使う名前を指定します。省略した場合
## ${comp_words[0]} が使われます。opts に initial または default が指定され
## ている場合は使われません。
##
## @var[out] comp_opts
##
Expand Down Expand Up @@ -3743,7 +3745,7 @@ function ble/complete/progcomp/.compgen {
compcmd=_DefaultCmD_
fi
else
compcmd=${comp_words[0]}
compcmd=${cmd:-${comp_words[0]}}
fi

local compdef
Expand Down Expand Up @@ -4104,16 +4106,23 @@ function ble/complete/progcomp {
"ble/cmdinfo/complete:${ucmd##*/}" "$opts"
return "$?"
elif builtin complete -p -- "$ucmd" &>/dev/null; then
cmd=$ucmd
ble/complete/progcomp/.compline-rewrite-command "${qcmds[@]}" "${alias_args[@]}"
ble/complete/progcomp/.compgen "$opts"
return "$?"
elif [[ $ucmd == */?* ]] && builtin complete -p -- "${ucmd##*/}" &>/dev/null; then
ble/string#quote-word "${ucmd##*/}"; qcmds[0]=$ret
# Note (#D2125): Even when we find the completion settings through the
# basename of the command path, we pass the full path to the completion
# function since some completions seem to try to call the command name
# (that is not supposed to be in PATH) to the completion function.
cmd=${ucmd##*/}
ble/string#quote-word "$ucmd"; qcmds[0]=$ret
ble/complete/progcomp/.compline-rewrite-command "${qcmds[@]}" "${alias_args[@]}"
ble/complete/progcomp/.compgen "$opts"
return "$?"
elif ble/complete/progcomp/.try-load-completion "${ucmd##*/}"; then
ble/string#quote-word "${ucmd##*/}"; qcmds[0]=$ret
cmd=${ucmd##*/}
ble/string#quote-word "$ucmd"; qcmds[0]=$ret
ble/complete/progcomp/.compline-rewrite-command "${qcmds[@]}" "${alias_args[@]}"
ble/complete/progcomp/.compgen "$opts"
return "$?"
Expand Down
3 changes: 1 addition & 2 deletions memo/done.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18898,8 +18898,7 @@

というより実の所 simple-word でできるだけ解析していくべきの気がする。と思っ
たが、 ; や変数代入があった時の振る舞い、文法エラーがある場合の振る舞いなど
は用途によってまちまちなのでこんk内は core-complete.sh の側で実装する事に
した。
は用途によってまちまちなので今回は core-complete.sh の側で実装する事にした。

simple-word の終端しない版というのはあっただろうか。なかったが
simple_rex_element をそのまま使えば良い。
Expand Down
64 changes: 64 additions & 0 deletions note.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7071,6 +7071,70 @@ bash_tips
Done (実装ログ)
-------------------------------------------------------------------------------

2024-01-28

* complete: ./manage.py で呼び出した補完が動かない (reported by REmerald) [#D2125]

どうも補完設定的には complete manage.py で登録しているけれども、受け取った
$1 を使ってコマンドを呼び出して補完候補を取得するらしい。

一方で、ble.sh では登録されているコマンドを呼び出す様にしていた筈。何故かと
いうと、

* $1 に quote 等が含まれていると動かなくなるから。

* また、$1 が純粋なコマンド名でない場合 (/ が含まれている場合) に正しく対応
できていない場合にもちゃんと動く様にしたかったというのがある。然し、これ
については実際に問題になる場合があった訳ではないし、この様に逆方向に問題
が起きる可能性があるのであれば気にしない事にする。

? もう一つの問題点はこの様な補完設定は安全なのかという問題もある。つまり、
悪意のある ./manage.py を含むディレクトリに入って ./manage.py を入力して
補完を実行したらその時点でその悪意のあるファイルが実行されてしまう。然し、
これは ./manage.py を実行した時点で覚悟するべき事なのかもしれない。とは言
いつつもしユーザーが実際に [TAB] を押さない限りは大丈夫だと誤認していた時
に問題が発生する。しかし、これは django の設定の問題の気がするので ble.sh
が気にすることではない気がする。

とにかく関連するコードを探して其処に何らかの考察が書き残されていないか確認
する事にする。どうも comp_words の時点で既に調整されている様である。
comp_words を生成した時点ではちゃんとそのままの文字列が含まれている。
ble/complete/progcomp 関数の中で見つかった補完設定に応じてコマンド名を再
quote されたコマンド名本体に書き換えられている。うーん。

多少履歴を辿って見ることにする。どうも */ の除去は dbe87c35 (2021-05-29) で
導入されてそのままの様である。試してみると ble-0.3 では確かに bin/test1 と
すれば bin/test1 というコマンド名が各配列に入っている。dbe87c35 の関連する
項目は #D1581, #D1583 だが何れも */ を除くか除かないかの議論に関しては触れ
られていない。それよりは quote 除去について議論している。つまり、歴史的には
*/ を除去しているのは大した理由があった訳ではないという事。

? そもそも bash はどの様に振る舞うのか? cmd cur prev を補完関数に渡すが cmd
に渡されるのは quote されているのかされていないのか。/ が含まれるのか含ま
れないのか。

うーん。先ず bash は quote されていると補完がそもそも起動しない。
'bin'/test1 等の様にすれば test1 が登録されていれば補完が呼び出されるが、
その場合でも 'bin' に対する quote が自動で外される等の事はない。また、
bash は COMP_WORDS に対しても $1 (cmd) に対してもユーザーが入力した物をそ
のまま指定する様だ。

仕方がないので取り敢えずは */ で除去するのはやめる事にした。

x すると今度は */* に対してそもそも補完が動かなくなった。どうやら .compgen
の現在の実装は complete -p "${comp_words[@]}" が設定されている事が前提に
なっている様だ (という事は今までも quote が必要な場合には complete -p で
登録されている物と comp_words[0] に格納される物が異なって補完が呼び出され
なかったのではないか?)。

コメントを見ると .compgen は cmd という外部変数を通して補完設定取得に用い
るコマンド名を得る事になっているが現在の実装ではそうはなっていない
(progcomp はなっている)。この記述の使用を復活させる事にする。呼び出し元で
cmd という変数が設定されているかどうかを確認する。調べてみた所呼び出し元
は本質的には ble/complete/progcomp だけである。他の場所で呼び出しているの
は initial かdefault を指定しているので cmd は何れにしても参照されないの
で気にしなくて良い。

2024-01-27

* edit: display-shell-version に atuin を追加する [#D2124]
Expand Down

0 comments on commit 0cf0383

Please sign in to comment.