Commit ID: 6129766
Version of GNU Bash: 4.4.12(1)-release
enhance-completeブランチでの話題です。
コマンドを実行した後,端末エミュレータの画面に\e[>4;1mと\e[>4;2m(註: \eは実際にはエスケープ)という文字列が余計に表示されてしまいます。
この時,これら二つの文字列は出力の一行目を挟むように表示されます。
$ cat <<.
foo
bar
baz
.
[4;1mfoo[4;2m
bar
baz
また,bleshが改行を処理した場合(例えば$ printf 'foo'を実行した場合)は,\e[>4;1mのみが表示されます。
なお,https://github.com/akinomyoga/ble.sh/issues/6#issuecomment-418952249 などにおいて僕が言及していた,入力時に不明な時点でプロセスが落ちてしまうという現象は, 遅くとも 6129766 において解決を見ました。
なぜ,その現象が @akinomyoga 様の手元では起きず僕の環境で起こったのか,またどうして解決したのかが全く判明していない点が心残りですが,とりあえず良かったです。
二つほど,補完に関して質問(不具合の問題提起ではなく)があるのですが,よろしいでしょうか。
もしも邪魔ならば,以下の文は無視してください。
READMEファイルの「着色の設定」という項目には,自動補完に関する構文強調は見受けられませんが,自動補完の構文強調は設定できないのでしょうか,またもしも設定できるなら,どのようにして指定すればいいでしょうか。
ble-color-setfaceの第1引数として指定すべき値を教えていただけると嬉しいです。
自動補完されている文字列を,瞬時に確定したい場合,どのようなキーを押せばいいでしょうか。また,それをカスタマイズするにはどうすればいいでしょうか。
とりあえず自分でauto_complete/accept-on-end関数あたりかなと思いまして,bleshの設定ファイル内で
ble-bind -m 'vi_imap' -f 'C-x C-i' 'auto_complete/accept-on-end'
などと設定してみたのですが,そのような関数はないとの旨の警告が出てしまいました。
ご報告ありがとうございます! enhance-complete 側は未だ不完全でバグも多くご迷惑をおかけすることも多いと思いますが、試していただいてとても助かります。
\e[>4;1m と \e[>4;2m認識できない制御シーケンスをそのまま出力してしまう端末ってあるんですね…。CSI > 4 ; Ps m は modifyOtherKeys という状態を変更するための (非ANSI標準の) シーケンスです。これは、端末が対応している場合に S-TAB (メニュー補完で補完候補を戻る) や S-RET (自動補完の確定) を (TAB や RET と) 区別できる形で制御シーケンスに符号化してくれるように、端末にお願いするものでした。
対応しているかどうかは TERM や terminfo などを見るだけでは判断が難しいことと、多くの最近の端末 (xterm, mlterm, mintty, RLogin, Tera Term) が対応しているようであること、認識できない制御シーケンスは普通無視されることなどから、取り敢えずシーケンスを出力するようにしていました。これは以下の設定で無効にすることができます。
bleopt term_modifyOtherKeys_external=
bleopt term_modifyOtherKeys_internal=
ところで、対応していない端末でこれらの修飾されたキーを使っていただくには、個別にキー毎に設定していただくしかありません (例えば S-RET は ESC [ 2 7 ; 2 ; 1 3 ~ を、S-TAB は ESC [ 2 7 ; 2 ; 9 ~ を送るように設定)。
すみません。これはその後、こちらで似たような現象が再現することが確認されています (もしかすると独立な別の問題の可能性もありますが)。起こる確率が低い (時々高くなる?) ので原因特定が面倒で今は放置していますが、これはできるだけ早く修正する予定です。
今試してみたら、何度やっても再現できなくなっていますね…。代わりに別の変な振る舞いを発見しましたが、こちらで使っている端末のバグのような気がします。以前の問題もそれだったのかもしれません。取り敢えず再発するまではまた様子見します。
補完関連の着色は現在のところ auto_complete と menu_complete ですね。これは vim mode の設定と同様に load hook 経由で設定する必要があります。 d57c8e9 load hook を追加しました。例えば以下のように設定して頂ければ幸いです (関数名 blerc/complete-load-hook は任意)。
ble/array#push _ble_complete_load_hook blerc/complete-load-hook
function blerc/complete-load-hook {
ble-color-setface auto_complete fg=246
}
auto_complete/accept なのでした。auto_complete/accept-and-execute 編集関数も追加しました。auto_complete/accept-on-end は、fish の動作を模倣するものです。編集文字列の末端で right を押した時に確定する (それ以外の時は通常の right の動作) ためのものでした。auto_complete/accept-word は自動補完で提示されている内容の内、次の空白の直前までを部分確定する編集関数です。これらは全て auto_complete キーマップに登録するものです (foo/bar の形の編集関数は何れも foo に関連するキーマップに登録するためのものという (緩い) 命名規則なのでした)。これも例によって load hook 経由で設定する必要があります。上記の設定と併せて、以下のように設定してください。
ble/array#push _ble_complete_load_hook blerc/complete-load-hook
function blerc/complete-load-hook {
ble-color-setface auto_complete fg=246
ble-bind -m auto_complete -f 'C-x C-i' 'auto_complete/accept'
}
ありがとうございます。いずれも希望通りの挙動になりました。
ところで,これもまた些細なことなのですが,bleshのVim modeにおけるキーバインドは,ble-bindコマンドの-mオプションにvi_imapなどを指定することで,モード毎に分けた設定ができますよね。auto_completeモードの時はVim modeにおいてはどのようなモードだと見做されているのでしょうか。
\e[>4;1m と \e[>4;2m設定をしましたところ,出力されなくなりました。ありがとうございます。
以下,蛇足です。
僕はXfce4デスクトップ環境に付属しているXfce4-Terminalを使っているのですが,これはLibVTEというGTK+用の端末エミュレータライブラリを基にしています。
そしてどうやらLibVTEは(端末界隈の間では)あまり評判がよくないようです。@akinomyoga 様も驚かれていたように,本来無視すべき制御綴りをそのまま出力してしまうというのも低評価の一因なのかなと思っています。
尤も,直接ソースコードを見た訳ではなく,Twitter経由での情報なので真偽不明ですが。
tmux のせいか zsh のせいか libvte のせいか neovim のせいかちょっとわからないのだけど,結論としては色々な入力に 001B ] 112 みたいなシーケンスが挿入されたりしてひどい時には入力が全部 Ctrl が挟まれちゃってまるでダメ
— おるみん (@kotatsu_mi) 2018年4月4日
見たところNeoVimがDECSLRMという制御シーケンスを使おうとしていますね。gnome-terminal(libvte)はこの制御シーケンスに対応していない上、非対応のシーケンスを無視する事も出来ないのでこのような表示になります。
— いわもと こういち (@ttdoda) 2017年7月18日
auto_completeモードの時はVim modeにおいてはどのようなモードだと見做されているのでしょうか。
ble-bind の -m は実は mode ではなくて (key)map を指定しているのですが、部分的・一時的にキーバインディングを上書きするのに各種の keymap を使っています (例えば履歴検索 C-r の為の isearch keymap など)。とは言いつつ、実際には「 auto_complete モード」と思っても良い特別の状態になっていて、自動補完に関係のあるキーは特別に処理をして、それ以外のキーが来たら一旦 auto_complete を抜けて (この時、編集文字列・描画内容の復元を行う) 元のキーマップで処理を行う、というようにしています。
\e[>4;1m と \e[>4;2mこれは端末ごとに判定するの面倒ですね…。面倒なのでマニュアルに書いて必要があれば個別に設定してもらおうと思っていたのでした。
ところで前から思っていたのですが、端末の control sequences は敢えて日本語で書くならば、JIS 規格で使われている「制御列」です。
教えていただきありがとうございます。
ところで前から思っていたのですが、端末の control sequences は敢えて日本語で書くならば、JIS 規格で使われている「制御列」です。
これは恥ずかしい間違いですね……。言い訳ですが,組版言語TeXにおけるControl Sequnceは「制御綴り」と呼ばれている[1]ので,てっきり端末におけるそれも同じ呼び方をすると思い込んでおりました。以後気をつけます。
[1]: 一例ですが http://d.hatena.ne.jp/zrbabbler/20121109/1352482114 や http://xymtex.my.coocan.jp/fujitas2/yatimata2/v200/yatimata2.pdf や http://hak7a3.hatenablog.com/entry/2015/12/20/153805 など。
あー。すみません! 今確認したら間違っていました。「制御列」はまた別のもの (control strings) の訳なのでした…JIS X 0211 の 4.2.24, 4.2.25 辺りです。とはいえど、少なくとも「制御綴り」は端末では使わないです
なるほど。JIS X 0211 4.2.24によると,Control Sequenceは「制御シーケンス」と定義されていますね。これからは語弊がないように,「Control Sequence」,または「CS」と表記するようにします。
お手数お掛けしました。
制御機能についてなのですが、以前自分が纏めかけたもの (contra/escseq.html) があったので体系の全体像を掴むのに参考になるかもしれません (唐突ですみません。今また改めて読んだところ、(少なくとも前半部分は) 我ながら良くまとまっているな、と思ったので)。この文書自体は、以前、自分で端末を作りたいなと思ってまとめ始めたものなのでしたが、途中で飽きました (ECMA-48 5th Edition で入った bidi 対応が凶悪(不明瞭)すぎて、本体の方の開発が止まってしまったので…)。
bleopt term_modifyOtherKeys_{ex,in}ternal=auto を導入し、端末の DA2 応答を見て 「libvte 以外」の時に CSI > 4 m を送信することにしました。閉じますね。