From 4fc51ae63394862835e544a01e87aa0e7e6c4112 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Wed, 10 Mar 2021 01:37:27 +0800 Subject: [PATCH] complete: work around autoloaded "fzf" completion settings --- contrib | 2 +- lib/core-complete.sh | 36 +++++++----- memo/ChangeLog.md | 3 +- note.txt | 133 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+), 17 deletions(-) diff --git a/contrib b/contrib index 90a56652..de69ed65 160000 --- a/contrib +++ b/contrib @@ -1 +1 @@ -Subproject commit 90a566521137980b2050c430db2dd359c098d25a +Subproject commit de69ed652f099cb25e43f2d01506d90b8dd4d970 diff --git a/lib/core-complete.sh b/lib/core-complete.sh index 1c1eb55b..ce83194e 100644 --- a/lib/core-complete.sh +++ b/lib/core-complete.sh @@ -1935,7 +1935,7 @@ function ble/complete/source:tilde { local old_cand_count=$cand_count ble/complete/cand/yield-filenames tilde "${candidates[@]}"; local ext=$? - return $((ext?ext:cand_count==old_cand_count)) + return $((ext?ext:cand_count>old_cand_count)) } #------------------------------------------------------------------------------ @@ -2171,7 +2171,8 @@ function ble/complete/progcomp/.compvar-quote-subword { ## @var[out] progcomp_prefix function ble/complete/progcomp/.compvar-initialize { COMP_TYPE=9 - COMP_KEY=${KEYS[${#KEYS[@]}-1]:-9} # KEYS defined in ble-decode/widget/.call-keyseq + COMP_KEY=9 + ((${#KEYS[@]})) && COMP_KEY=${KEYS[${#KEYS[@]}-1]:-9} # KEYS defined in ble-decode/widget/.call-keyseq # Note: 以降の処理は基本的には comp_words, comp_line, comp_point, comp_cword を # COMP_WORDS COMP_LINE COMP_POINT COMP_CWORD にコピーする。 @@ -2241,7 +2242,7 @@ function ble/complete/progcomp/.compgen-helper-prog { local -x COMP_LINE COMP_POINT COMP_TYPE COMP_KEY ble/complete/progcomp/.compvar-initialize local cmd=${COMP_WORDS[0]} cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} - "$comp_prog" "$cmd" "$cur" "$prev" /dev/tty 2>&1; local ret=$? ble/function#pop compopt if [[ $is_default_completion && $ret == 124 ]]; then @@ -2391,6 +2392,8 @@ function ble/complete/progcomp/.compgen { ble/array#push compoptions "-$c" "$o" ;; (F) comp_func=${compargs[iarg++]} + [[ $comp_func == _fzf_* ]] && + ble-import contrib/fzf-completion ble/array#push compoptions "-$c" ble/complete/progcomp/.compgen-helper-func ;; (C) comp_prog=${compargs[iarg++]} @@ -2490,7 +2493,7 @@ function ble/complete/progcomp/.compgen { # Note: 重複候補や順序については考えていない [[ $comp_opts == *:plusdirs:* ]] && ble/complete/source:dir - ((cand_count!=old_cand_count)) + ((cand_count>old_cand_count)) } ## @fn ble/complete/progcomp/.compline-rewrite-command cmd [args...] @@ -3319,6 +3322,13 @@ function ble/complete/candidates/.pick-nearest-sources { fi } +function ble/complete/candidates/clear { + cand_count=0 + cand_cand=() + cand_word=() + cand_pack=() +} + ## @fn ble/complete/candidates/.filter-by-command command ## 生成された候補 (cand_*) に対して指定したコマンドを実行し、 ## 成功した候補のみを残して他を削除します。 @@ -3659,11 +3669,7 @@ function ble/complete/candidates/generate { ble/complete/candidates/comp_type#read-rl-variables local cand_iloop=0 - cand_count=0 - cand_cand=() # 候補文字列 - cand_word=() # 挿入文字列 (~ エスケープされた候補文字列) - cand_pack=() # 候補の詳細データ - + ble/complete/candidates/clear ble/complete/candidates/generate-with-filter none "$opts" || return "$?" ((cand_count)) && return 0 @@ -4881,8 +4887,8 @@ function ble/widget/complete { local COMP1 COMP2 COMPS COMPV local comp_type comps_flags comps_fixed - local cand_count=0 - local -a cand_cand cand_word cand_pack + local cand_count cand_cand cand_word cand_pack + ble/complete/candidates/clear local cand_limit_reached= if [[ $_ble_complete_menu_active && :$opts: != *:regenerate:* && :$opts: != *:context=*:* && ${#_ble_complete_menu_icons[@]} -gt 0 ]] @@ -5974,8 +5980,8 @@ function ble/complete/sabbrev/expand { local flag_source_filter=1 # construct cand_pack - local cand_count=0 - local -a cand_cand=() cand_word=() cand_pack=() + local cand_count cand_cand cand_word cand_pack + ble/complete/candidates/clear local cand COMP_PREFIX= # local settings diff --git a/memo/ChangeLog.md b/memo/ChangeLog.md index 74a76638..0191e9fe 100644 --- a/memo/ChangeLog.md +++ b/memo/ChangeLog.md @@ -10,7 +10,7 @@ - edit: support new options `bleopt edit_line_type={logical,graphical}` (motivated by 3ximus) `#D1442` 40ae242 - complete: support new options `bleopt complete_limit{,_auto}` (contributed by timjrd) `#D1445` b13f114 5504bbc - complete: update the default value of `bleopt complete_limit{,auto}` `#D1500` aae553c - - complete: inject user interruption and complete limits into `bash-completion` through `read` (motivated by timjrd) `#D1504` 0000000 + - complete: inject user interruption and complete limits into `bash-completion` through `read` (motivated by timjrd) `#D1504` 856cec2 `#D1507` 0000000 - edit (kill/copy): combine multiple kills and copies (suggested by 3ximus) `#D1443` 66564e1 - edit (`{kill,copy}-region-or`): fix unconditionally combined kills/copies (reported by 3ximus) `#D1447` 1631751 - canvas: update emoji database and support `bleopt emoji_version` (motivated by endorfina) `#D1454` d1f8c27 @@ -75,6 +75,7 @@ - term: support key sequences and control sequences of Solaris console `#D1481` 6ca0b8c - term: work around Cygwin-console bug of bottom `IL`/`DL` `#D1482` 5dce0b8 - term: work around leaked DA2R in screen from outside terminal `#D1485` e130619 +- complete: work around `fzf` completion settings loaded automatically `#D1508` 0000000 ## Internal changes and fixes diff --git a/note.txt b/note.txt index 162f85fd..8b68be55 100644 --- a/note.txt +++ b/note.txt @@ -4008,6 +4008,139 @@ bash_tips Done (実装ログ) ------------------------------------------------------------------------------- +2021-03-09 + + * COMPAT complete vs fzf: システムによってロードされた fzf で固まる [#D1508] + + これは . /etc/bashrc を読み込むと強制的に読み込まれている設定である。ユーザー + が自分で入れた fzf に関しては contrib/fzf-completion を ble-import して貰う + 事によって問題が起こらない様にしているが、システムによってロードされる fzf + に関しては内容を上書きする隙がない。仕方がないので、core-complete.sh で + _fzf_* が呼び出された時に contrib/fzf-completion を自動的にロードする様にす + る事にした。元より bash-completion を勝手に呼び出したりする様にしているので + 他の framework ありきのコードがあっても気にしない。 + + これは正直 fzf が tty ではなくて stderr になにか出力しようとするのが行けな + い。/dev/tty に出力する様にして欲しい物である。 + + うーん。 fzf のページを見てもそれらしい物は存在しない。環境変数などで指定で + きれば良いのだが。man fzf を見てもそれらしい物は存在しない。そういう機能を + request して見ようと思ったが、考えてみれば自分で fzf を呼び出す時には + 2>/dev/tty をつければ良いだけなので新しい機能として実装する意味がない。ユー + ザー経由で呼び出しているのであればユーザーにその様に指定する様にお願いする + べきなのである。 + + 然し、ble.sh がやっているのは bash progcomp の模倣である。bash の方で問題が + ないのであれば、ble.sh の方で問題が起こるのは余り良くない。うーん。fzf につ + いて関数などで上書きして振る舞いを変える? うーん。それだと fzf-xxx の様な派 + 生コマンドを使われた時に対処できない。結局 bash progcomp を真似て 2 は tty + に繋いだ儘にしておくべきなのだろうか。うーん。 + + というかそもそも fzf が tty に出力する様にしたとして auto-complete に際して + 期待通りに動くかどうかというのは非自明である。取り敢えず試してみる。 + →試してみた所期待通りに動作しない。やはり fzf の設定をそのまま使うのは駄目。 + + ? うーん。実行しても結果が反映されない。COMPREPLY をちゃんと設定しているか? + + ? redraw-line が正しく呼び出されていない。 + + % これは恐らく ESC [ が M-[ になって bind されているのが原因。CSI の構築に + % 失敗した時に M-[ と解釈するべきか或いは ESC [ と解釈するべきかは微妙な所 + % である。然し、CSI を構築する ESC は isolated ESC ではなくて他の文字と一緒 + % に受信した ESC であるべきと考えれば、やはり M-[ と解釈するべきだろうか。 + % そうすると、CSI に失敗した時に 1 byte だけ切り取って ESC を key として生 + % 成しているのを修正するべきである。 + + 改めて確認した所、そもそも CSI 0 n は認識できないシーケンスとして捨てられ + ているという事が判明した。 + + ? その他の問題として fzf を実行している間は modifyOtherKeys の設定によって + fzf の操作ができなくなっているという事がある。うーん。実際に端末に作用す + るかどうか分からないのに補完関数を呼び出す度に端末の状態を変更するという + のも変な感じがする。 + + 面倒なので fzf が補完関数の名前に入っている時に限り特別の動作をする様にする? + 取り敢えず、固まったりしない様に調整した。 + + % x fixed: CSI 5 n が候補の文字列に結合してしまっている。これは何故だろうか。 + % COMPREPLY にはちゃんとした候補が入っている…気がする。 + % + % →これは compgen の標準出力を読み取って候補としているのが原因。元の + % progcomp の -F の場合には標準出力はそのまま端末に繋がっている。それに倣う + % 様に修正した。 + % + % x fixed: 候補が生成されない…と思ったら実は CSI 5 n に対する返答 CSI 0 n に + % よってユーザー入力に依る中断が入って処理がキャンセルされている。fzf の時 + % にはどうにかしてこれに対する対策を行う必要がある。 + % + % a CSI 0 n を受信しても処理を続行するというのは難しい。何故ならば受信した + % 段階ではそれがユーザー入力なのか応答なのか判定する方法がないので。受信 + % して読み取ってから違ったら書き戻すというのも処理としては汚い。 + % + % b それなら CSI 5 n がそもそも伝播しない様に抑える必要がある。うーん。幸い + % にして CSI 5 n は標準出力に、それ以外のメニューの描画は標準エラーに出力 + % されている。従って、_fzf* に対しては標準出力を潰す様にするのが良い気が + % する。 + + 色々対策してみたが実はこれらの対策は contrib/fzf-completion.bash と本質的に + 同じであった。fzf-completion.bash を自動で load する方が良いのではないか。 + + x fixed: progcomp で単一候補を生成したとしても progcomp 以外に sabbrev も表 + 示されてしまって単一確定にならない。うーん。これは _fzf_* で成功して単一 + 確定の場合には既に生成した候補は全て削除するという事にすれば良いのでは。 + →既存の候補は消去する様に実装した。 + + x そもそも既に入力済みの内容を無視している。normal bash で試してみると、既 + に何か入力済みの物がある場合には fzf による completion は起動しない。空の + 文字列の時にだけ fzf による選択が開始される。 + + →これは曖昧補完の為に空文字列で補完候補生成を要求するのが原因であった。 + 曖昧補完の時にはそもそも fzf を呼び出さない様に修正した。 + + * BUG progcomp: 現在 read に介入して中断する様にしているが [#D1507] + + 現在の実装だと + + while read || [[ $REPLY ]]; do ... done + + の様になっていると、無限ループになってしまう。 + 中断する時にも引数に指定した変数は全て空にしておく必要がある。 + + というより、現在の read の実装は普通に呼び出した時であってもちゃんと変数を + 空にしてくれるのか? + + % そもそも元の read の振る舞いが良く分からない。read line とした時にもう読み + % 取る内容がなかったとして line が空になるのかと思いきやそうでもない? と思っ + % たがこれは勘違いだった。試す時に : | read ... とすると subshell の中で値を + % 設定するので、外側の変数には影響が出なかっただけ。 + + うーん。取り敢えず中断の時には内部で