diff --git a/lib/core-complete.sh b/lib/core-complete.sh index 050ca3dd..e14d879d 100644 --- a/lib/core-complete.sh +++ b/lib/core-complete.sh @@ -2501,7 +2501,9 @@ function ble/complete/progcomp/.compgen { else ble/util/assign compdef 'builtin complete -p -- "$compcmd" 2>/dev/null' fi - compdef=${compdef%"$compcmd"} # strip -I, -D, or command_name + # strip -I, -D, or command_name + # #D1579 bash-5.1 では空コマンドに限り '' と出力する様である。 + compdef=${compdef%"${compcmd:-''}"} compdef=${compdef%' '}' ' local comp_prog comp_func compoptions flag_noquote @@ -2553,7 +2555,7 @@ function ble/complete/progcomp/.compgen { local _ble_complete_retry_guard=1 opts=:$opts: opts=${opts//:default:/:} - ble/complete/progcomp/.compgen "${opts//:default:/:}" + ble/complete/progcomp/.compgen "$opts" return "$?" fi diff --git a/lib/core-syntax.sh b/lib/core-syntax.sh index 3b02799e..4d2fd3a6 100644 --- a/lib/core-syntax.sh +++ b/lib/core-syntax.sh @@ -5450,9 +5450,18 @@ function ble/syntax/completion-context/.check-prefix/ctx:quote/.check-container- local wlen2=${nest[1]}; ((wlen2>=0)) || return 1 local wbeg2=$((wlen2<0?wlen2:inest-wlen2)) - if ble/syntax:bash/simple-word/is-simple-or-open-simple "${text:wbeg2:index-wbeg2}"; then - ble/syntax/completion-context/.add argument "$wbeg2" + local wt=${nest[2]} + [[ ${_ble_syntax_bash_command_EndWtype[wt]} ]] && + wt=${_ble_syntax_bash_command_EndWtype[wt]} + if ((wt==CTX_CMDI)); then + ble/syntax/completion-context/.add command "$wbeg2" + elif ((wt==CTX_ARGI||wt==CTX_ARGVI||wt==CTX_ARGEI||wt==CTX_FARGI2||wt==CTX_CARGI2)); then + ble/syntax/completion-context/.add argument "$wbeg2" + elif ((wt==CTX_CPATI)); then # case pattern の内部 + #ble/syntax/completion-context/.add file "$wbeg2" + return + fi fi } diff --git a/memo/ChangeLog.md b/memo/ChangeLog.md index bd0868f6..71173cac 100644 --- a/memo/ChangeLog.md +++ b/memo/ChangeLog.md @@ -124,6 +124,7 @@ - sabbrev (`ble-sabbrev`): fix delayed output before the initialization `#D1573` 5d85238 - main: fix the workaround for `set -u` `#D1575` 76073a9 - history: fix the workaround for bash-3.0 bug of reducing histories `#D1576` 15c9133 +- syntax: fix a bug that argument completion is attempted in nested commands (reported by huresche) `#D1579` 0000000 ## Compatibility diff --git a/note.txt b/note.txt index c02a3eba..d94d5f75 100644 --- a/note.txt +++ b/note.txt @@ -1440,9 +1440,50 @@ bash_tips 0.5 ControlPanel/TUI Framework 0.4 progcolor +2021-05-29 + + * complete: そもそも -F に指定する事のできる文字列には制限がある筈である。こ + れを満たさない場合には強制的に其処で終端させる等の対策が必要なのではないか。 + + 然し、;&| 等が含まれていた場合にどの様に取り扱うべきかは不明である。明らか + に何かが間違っているけれども、だからと言ってその直前までを関数名と捉えるの + にも無理がある様な気がする。然し、それ以外に解釈のしようがないとも言える。 + + * complete: quote していると補完関数が認識されない。例えば git co とすると OK + だが 'git' co とすると反応しない。然し実の所、これは普通の bash でも同様で + ある。普通の bash でも 'git' としている時には git の補完関数は呼び出されな + い。 + + * complete: alias の展開結果で変数代入を除去するべきではないか + + * syntax: \q を着色したい + +2021-05-28 + + * 最下行で ble-reload すると statusline が重複してしまう。ble-detach して + その後に ble-attach した時には問題は発生しない。 + +2021-05-27 + + * wiki の更新 + * wiki: ble-import の -f オプション + * wiki: bleopt の wildcard, -r, -u + * wiki: blehook の -a + + * declare -p -A として見たら contra の状態が壊れた。何だろうか。 + + * やはり source_if() { source "$@"; } 等とすると引数が一つしかない場合に、自 + 分自身が引数であると誤認してロードがキャンセルされる。これは実は簡単に判定 + できるのではないだろうか。 + + % つまり引数が唯一つでしかも自分自身を指している場合には関数内で無引数で + % source されたのであると判定できる。と思ったが違う。これで見えているのは外 + % 側の関数の引数なのだから、必ずしもそういう形になっている訳ではない。 + 2021-05-24 * airline: 説明書を書く。theme の枠組みを整える + https://github.com/akinomyoga/ble.sh/issues/114 (2) * themes の枠組みを整えたい気がする。現状だとユーザーがそれぞれ対応しなけれ ばならない。面倒である。うーん。取り敢えず contrib に適当に加えてみるとい @@ -4665,6 +4706,141 @@ bash_tips 2021-05-29 + * complete: "\a" 等のコマンド名の補完で問題が起こる (reported by huresche) [#D1579] + https://github.com/akinomyoga/ble.sh/issues/116 + + [原因] + + | bash_completion との関連でまた問題が起こっている。最新の bash_completion で + | 再現する事ができた。 + | + | 何れにしてもこれは bash とのインターフェイスの違いなので修正されるのは + | ble.sh の方であろう。そして文面を読む限りは "minimal ''" という名前のコマン + | ドを呼び出そうとしている? これは parse の問題の様な気もするが…。取り敢え + | ず何が起こっているのか調べる。 + + 結局これは ble.sh の側の問題であった。再現条件は bash-5.1 である。 + bash_completion では何故か空文字列に対するコマンドでも complete -F _minimal + '' を登録する様で、しかも bash-5.1 から complete -p の出力の形式が変化した + 事によって ble.sh が -F の解析に失敗して問題が露呈したという事になる。 + + | * "a" では発生しない。"\a" や "$$" では発生する。 + | + | 取り敢えず再現しているので何が起こっているのか調べる事にする。 + | + | % うーん。どうやら。simple word じゃない時にコマンド名を決定できず、結果と + | % して空のコマンド名に対して補完が呼び出されているという形になる。うーん。 + | % この場合にはどうするのが良いだろうか。もう直接 simple-word でない内容を転 + | % 写する? うーん。それも一つの手である。 + | + | と思ったが、そうでもない様である。例えば "$$" というのは simple-word である。 + | 改めて何で空になるのか確認する必要がある。 + | + | "\a" は展開されて \a になるがそれにより補完は最終的に失敗する様だ更に引き続 + | き \\ による補完が呼び出されてそれが evaluate されて \ になる等している。然 + | し、"$$ の場合には数字に展開されて、その後で曖昧補完の為に一文字目 "1" の数 + | 字を使って補完されるという事が起こっている。それでもエラーは発生している。 + | + | 不思議なのは普通に 1 として入力しても問題が生じないという事。というか、やは + | り COMP_WORDS が空になってしまっているのが問題なのだという気がする。 + | + | ? そもそも最初のコマンド名でない場合でも、simple-word でない場合には補完は + | どうなっていただろうか。 + | + | →少し分かった。generate-subwords が5回実行されていて '$$', '', '1', '1', + | '' となっていて問題のエラーは空文字列で呼び出された時に発生している様である + | という事。遡って見るとそもそも compgen-helper-func 自体もその様に呼び出され + | ているという事が分かった。ble/complete/progcomp/.compgen もその様に呼び出さ + | れている。 + | + | ? うーん。不思議なのは "a" 等の普通の表記の時にはその様な事がないという事で + | ある。何故だろうか。調べてみると普通の場合でもちゃんと空文字列による補完 + | が呼び出されている。そもそもこの空の状態での補完の要求が一体何故呼び出さ + | れているのかという疑問は残るが、現在発生しているエラーメッセージとは関係 + | がないという事だろうか。 + | + | 然し空の文字列になる場合を除外してみるとちゃんとエラーメッセージなく補完 + | が実行される様である。 + | + | ? ok: 何故空の文字列で補完 compgen が呼び出されているのだろうか。 + | + | これは曖昧補完で -I による補完を試みているからである。 + | + | ? done: 何故普通のコマンド名の場合には空の文字列で補完が呼び出されても問題 + | が発生していないのか。何故特定の文字列の時にのみエラーメッセージが発生す + | るのだろうか。 + | + | | うーん。不思議な事だ。どうも調べると compdef に変な文字列が入ってくる。つ + | | まり complete -p 自体が予期しない内容の文字列を出力しているという事だろう + | | か。 + | | + | | うーん。どうやら空文字列で呼び出されるのは曖昧補完の為に -I でコマンド名 + | | を保管しようという時の話であって。然し、何故か文字列の種類に応じて -I で + | | 呼び出されたり或いは直接コマンド名で呼び出されたりというのが変化している + | | という様子。もっとちゃんと書くと何故か文字列の種類によって initial が付け + | | られずに compgen が呼び出されるという事。 + | | + | | やはり initial なしで呼び出されるというのは変だ。initial がないという事は + | | コマンド引数としての補完を要求している事に他ならない。然し、空文字列での + | | 補完なのにそれは起こり得ない筈である。呼び出し元を確認する必要がある。調 + | | べてみると何故か "$$ の時には source:argument が生成されているのだという + | | 事が判明した。一体どういう事なのだろうか。source:command は一切生成されて + | | いない。うーん。syntax の context 生成が怪しいという事になるだろうか。 + | | + | | 生成された source を確認してみると declare -a sources=([0]="argument 0") + | | が生成されている。うーん。つまり、core-syntax.sh に於いて単語内部の nest + | | した文脈からだと argument が生成されてしまうという事である。 + + "..." の内部の nest した文脈ではそれがコマンド名か引数内部かに関係なく + argument が生成されてしまうのが原因だった。 + + 確認してみると以下の関数で argument 決め打ちにしている。 + ble/syntax/completion-context/.check-prefix/ctx:quote/.check-container-word + + 判定の為に nest に登録されている単語情報を確認しているが不思議である。 CMDX + や ARGX になっている。CMDI や ARGI ではないのだろうか。特に nest が始まった + のが単語の途中であっても CMDX や ARGX になっている。 + + > function ble/syntax:bash/ctx-command/.check-word-begin { + > if ((wbegin<0)); then + > local octx + > ((octx=ctx, + > wtype=octx, + > ctx=_ble_syntax_bash_command_BeginCtx[ctx])) + + うーん。この部分を見ると wtype は単語が始まった瞬間の文脈を保存している。 + + > function ble/syntax:bash/ctx-command/check-word-end { + > # 単語の中にいない時は抜ける + > ((wbegin<0)) && return 1 + > + > # 未だ続きがある場合は抜ける + > ble/syntax:bash/check-word-end/is-delimiter || return 1 + > + > local wbeg=$wbegin wlen=$((i-wbegin)) wend=$i + > local word=${text:wbegin:wlen} + > local wt=$wtype + > + > [[ ${_ble_syntax_bash_command_EndWtype[wt]} ]] && + > wtype=${_ble_syntax_bash_command_EndWtype[wt]} + + 更に此処で _ble_syntax_bash_command_EndWtype を用いて最終的に記録する wtype + に変換している。という事は実際の判定でも _ble_syntax_bash_command_EndWtype + を参照するべきである。 + + [修正] + + * done: compcmd が空文字列の時に bash は '' を出力する。つまり微妙に quote + するという事。 + + $ complete -o bashdefault "''" + $ complete -o bashdefault '' + $ complete -p + + 試した見た限りでは空文字列の時にだけ '' と出力してそれ以外の場合には直接 + 出力する様である。これについては一つ対策を入れる必要がある。これは他の問 + 題を修正してから取り掛かる。 + * util (assign): Cygwin で assign 一時ファイルの衝突が発生している様だ [#D1578] assign 一時ファイルに BASHPID を付加する様にしたら特に問題は発生しない様子。