done.txt (5241640B)
1 # -*- coding:utf-8 -*- 2 3 ******************************************************************************* 4 実装ログ 5 ------------------------------------------------------------------------------- 6 7 2023-04-03 8 9 * main (adjust-builtin-wrappers): IFS= が設定されてしまう @ bash-5.0 (reported by pt12lol) [#D2030] 10 https://github.com/akinomyoga/ble.sh/issues/311 11 12 POSIXLY_CORRECT=y の環境で IFS= ble/bash/read を実行していた為に IFS= が関 13 数呼び出し後も残る様になってしまったのだった。 14 15 ? 然し不思議なのは何故か bash-5.0 だけで振る舞いが再現するという事。 16 bash-5.1 以降は関数呼び出しの変数代入は posix であっても環境に残らない様 17 になっているのは良い。然し、bash-4.4 以前については bash-5.0 と同様に環境 18 に tempenv が残る様に見える。何故この時にだけ問題がないのだろうか。或いは、 19 何処か別のレベルで local IFS が設定されているという事か、或いは呼び出し元 20 の local POSIXLY_CORRECT=y は影響を与えないという事なのだろうか。よく分か 21 らないが取り敢えずは問題は封じた筈なので気にしない事にする。 22 23 取り敢えず関数呼び出しの前に変数代入を置かない様にする。明らかに ble.sh の 24 内部だけで使われる関数については気にしなくて良い。util.sh の一般のライブラ 25 リ関数についてはちゃんと posix を避ける様にする事にする。 26 27 ? これよりも前には問題にならなかったのかというのが疑問である→どうも試して 28 みた所 read や builtin read では tempenv は posix モードであったとしても 29 環境には残らない様である。つまり、本当にシェル関数特有の振る舞いだったと 30 いう事である。 31 32 builtin read から ble/bash/read に置き換えられたのが a5b10e8b である。こ 33 れは #D1981 に関係している。 34 35 2023-04-02 36 37 * bgproc: bash-4.2 での bgproc#start で {bgproc[0]} は存在しないというエラーメッセージ [#D2029] 38 39 これは exec {fdvar}redirect で発生しているエラーだった。bash-4.1,4.2では 40 {fdvar} の fdvar として配列要素には対応していない。 41 42 * bgproc: シェルの終了時に即座に強制終了するオプションをつける? (motivated by bkerin) [#D2028] 43 https://github.com/akinomyoga/ble.sh/discussions/309#discussioncomment-5498921 44 45 然し実際にそれが良い事なのか分からない。というか現状の実装ではそうはなって 46 いないのだったか? → child session はちゃんとすぐに終了する。然し端末が閉じ 47 ない。これは stderr, stdout, stdin の何れかが未だ開いたままになっているのが 48 原因と思われる。 49 50 .kill ではちゃんと全部閉じている筈と思ったがよく考えたらスタートしたプロセ 51 ス自体が stderr を保持しているのが原因の気がする。 52 53 そのまま強制終了するというのもどうかという気がするが、それならばそれで良い。 54 55 * done: 或いは終了チェックの interval をより短くする。これは 56 ble/util/bgproc#stop/.wait で使っている 1000 という値を設定できる様にすれ 57 ば良い。然し、これを変更したとして実際に終了にかかる時間がそんなに速くな 58 るのだろうか。 59 60 うーん。或いは conditional-sync の progressive-weight を使う? と思ったが 61 conditional-sync は新しいサブシェルを待つ物なので単に或る条件を待つという 62 事には使えない。conditional-sync を拡張して任意の条件を待つ事ができるよう 63 にする可能性も考えたが、 64 65 a うーん。或いはコマンドを開始するのではなくて既存のプロセスを待つという 66 機能を持たせる? この時に conditional-sync に足りていないのは kill を二 67 段階で行う機能である。SIGKILL を送る様にするオプションは実装しているが、 68 kill で駄目だった時に段階的に SIGKILL を送るという機能は実装していない。 69 そういう機能も追加して良いかもしれない。 70 71 うーん。取り敢えず conditional-sync を2回呼び出して二回目で SIGKILL を 72 指定すれば良いのだと気づいたので conditional-sync 自体に段階的に kill 73 を実行する機能は実装しなくて良かった。 74 75 b 或いはコマンドが空の時には指定された条件だけを待つという振る舞いにする。 76 この場合にはコマンドの kill までは実行しない。 77 78 然しもし原因が .kill の interval による物なのだとしても、 79 stdout/stderr/stdin を封じている限りは生きているというのは .kill が原因な 80 のではないのでは? 然し、プロセスが瞬間的に終了する事ができなかった場合に 81 は .kill による自動 kill が起動する迄は bgproc が保持している stderr が開 82 いたままである。然し、その場合には timeout になるまで相当待たなければなら 83 ない (既定では 10sec である。或いは SIGKILL まで更に 10sec ある)。 84 85 * ok: と思ったがもしかすると .kill 自体が fd を保持しているから bg 86 process が終了しない可能性? と思ったがそれも変だ。.kill 自体は fd を閉 87 じてから呼び出している筈 → 実際に確認した。 88 89 ? ok: ところで set -m して起動した bgproc のなかで更にパイプやサブシェルな 90 どを立ち上げた時に更に別の PGID になっているとその別の PGID までは kill 91 しきれないのでは。なので set +m を中で実行しなければならないのでは。 92 93 →と思ったが、実験してみた限りでは set -m が実際に効果を持つのはそれを呼 94 び出したサブシェルだけの様である。なので更に入れ子で呼び出された物に関し 95 ては敢えて set -m を実行しない限りはちゃんと元の pgid に属する様になって 96 いる。 97 98 即座に終了する方法について考えたがこれは単に kill-timeout を 0 に設定すれば 99 良いのでは。結局向こうで起こっている事が何か分からないのでどうしようもない。 100 101 * 2023-04-03 うーん。即座に終了しないのは subshell の stdout/stderr/stdin 102 を閉じていても、ble/fd で保持している fd が残っているからでは。 103 ble/fd#finalize を呼び出せば良いだろうか。或いは tty に関しては 104 ble/fd#finalize での自動 close を抑制していただろうか。 105 106 →確認してみると ble/fd#finalize には tty は登録されていない様だ。という 107 か寧ろ msleep 等が使っている fd を削除してしまう様だから中で sleep が使え 108 なくなってしまう。ble/fd#finalize は呼び出しても仕方がない。 109 110 うーん。待避している fd を閉じても駄目の様である。どうも builtin exit 0 111 を呼び出して終了しようとしているのだがその時に redirect をしている。その 112 redirect によって保管している fd が未だ生きている様だ。つまり、本当に全て 113 閉じようと思ったら redirect によって保管している物も全て閉じる必要がある。 114 すべて閉じる為には fd を列挙しなければならない。 115 116 a 一定の範囲の fd を全て閉じる? linux (もしくは bash) は現在の所は 255 付 117 近に redirect にの fd を保管している様だが os によってはもっと巨大な値 118 に保存しているかもしれない。なので可能性のある fd を全てスキャンすると 119 いう訳にも行かない気がする。 120 121 b 或いは /proc/$BASHPID/fd の中にある物を全て閉じる? 然しこれも使えるシス 122 テムが限られている。 123 124 また fd をスキャンして閉じるとしても msleep 等が使っている fd を閉じてし 125 まうとサブシェルの動作に問題を起こしてしまう。これについては -t で判定し 126 て端末だけを閉じる様にすれば良い気もする。 127 128 * make: インストール時に元のコメントなどの情報への pointer をつける (suggested by bkerin) [#D2027] 129 https://github.com/akinomyoga/ble.sh/discussions/309#discussioncomment-5498921 130 131 make_command.sh install からでは元のソースがどれかは原理的には分からないが、 132 取り敢えず現状では ble.sh 以外は全て対応するファイルが同名で存在しているの 133 で、その仮定の下でファイル名を含める事にした。ble.sh についても ble.pp と 134 src/*.sh を全て含める事にした。 135 136 果たしてコメントを削除しないインストールが本当に必要なのかは謎だが一応機能 137 としてはつけておく事にした。何れにしても元々ある日本語のコメントは個人用の 138 物であって他の人に見せる為のものではない。 139 140 * bgproc: bash-3 で idle.cancel がないと表示される [#D2026] 141 142 実装を改めて確認してみたらそもそも bash-3 に対する考慮が全く入っていない。 143 然し、将来的に bash-3 でも idle を使える様にする可能性を考えると単にバージョ 144 ンで判定するのもよくない気がする。結局 function#try で調整する事にする。 145 146 2023-03-26 147 148 * menu-complete (linewise): 長い行がある時に表示が崩れる (reported by bkerin) [#D2025] 149 https://github.com/akinomyoga/ble.sh/issues/307 150 151 これは実装を詳しく調べてみたら選択時の部分更新の時の幾何を記録する部分で、 152 描画範囲を限定した時の記録が残っていないのが原因だった。そもそも linewise 153 は試験的に最初に実装したもので余り真面目に実装されていない感じがする。その 154 後で desc の実装でもっとちゃんと実装されてその時に限定された描画範囲につい 155 てちゃんと対応が行われている。その desc に使われた仕組みを linewise からも 156 使うだけで良かった。 157 158 然しそれとは別に長い候補を入力した時に panel の高さが変わった時に menu の高 159 さを制限した上で再描画を行う仕組みが欲しい。これについては簡単ではなさそう 160 なので別の項目で議論する事にする。 161 162 2023-03-16 163 164 * edit: bind -x で PS1 も一時的に復元する (requested by adoyle-h) [#D2024] 165 https://github.com/akinomyoga/ble.sh/issues/304 166 167 lincheney/fzf-tab-completion で退避中の一時 PS1 が表示されるというから何か 168 と思ったら自分で PS1 を出力しているのだった。 169 170 * 2023-03-06 menu-complete: 番号で選択する (requested by bkerin) [#D2023] 171 https://github.com/akinomyoga/ble.sh/discussions/284 172 173 これは実は実装はそんなに大変ではない気がする。 174 175 LASTWIDGET のチェックは必要? 否、他のものは全て抜けるから関係ない? と思っ 176 たが TAB や cursor key 等の移動コマンドの後も番号はリセットしたい。なのでや 177 はり LASTWIDGET はチェックする。番号が溜まって一致する物がなくなったら一つ 178 ずつ古い文字を削除して一致するものが出るまで削る。一つも一致しなかったら削 179 る前にリセットして新しい文字自体をなかった事にする? 180 181 試しに実装してみたが操作性に疑問が残る。先ず menu-complete の中に入らないと 182 番号で選択できない。一方で、menu を表示しているだけの場合にも選択しようとす 183 るのが自然の気がする。 184 185 a menu-complete の外からでも M-0 等で選択できる様にするとしても 186 menu-complete に入らずに select しても仕方がない。 187 188 もう一つの問題点は menu が表示されていたらどの文脈であっても M-0 で menu 189 に入ってしまうのかという事。auto-menu を実装していたりすると実質的に M-0 190 は常に menu に入ってしまうという事になり操作できない。或いは、TAB を二回 191 押した時に complete に入るのと同じ様に、LASTWIDGET が complete だった時に 192 M-0 で menu-complete に入るというのは手の気がする。 193 194 更にもう一つの問題点は menu の中に番号を表示していない時でも番号による選 195 択を有効にするのかという事 → これは M-0 等のキーを使っている時点で、実際 196 に番号が表示されているかどうかに関係なく menu-complete に入るという事で良 197 い気がする。 198 199 b 或いは、menu-complete の外で M-0 等で引数を入力し始めたらその場で 200 menu-complete に入るという可能性も考えられる。 201 202 * どの menu-style についても番号を表示する機能が欲しい。 203 204 設定名を変更する? 205 206 bleopt menu_item_prefix 207 bleopt menu_item_prefix_linewise 208 bleopt menu_item_prefix_align 209 bleopt menu_item_prefix_desc 210 211 と思ったが現在の設定名は他の設定と共に menu_STYLE_NAME の形で一貫している。 212 これを壊すのも変な気がするので、既存のルールは保持する。全体の設定を一括 213 で変更するオプションを用意したい気がするが、その名前は何にするか。単に 214 menu_prefix で良いだろうか。 215 216 bleopt menu_prefix 217 bleopt menu_linewise_prefix 218 bleopt menu_align_prefix 219 bleopt menu_desc_prefix 220 221 取り敢えず align と desc について候補番号に対応した。dense は対応していな 222 い。が、完全性を期する為にはやはり dense も対応した方が良い気がする。→対 223 応した。 224 225 * done: wiki, blerc: menu_prefix, menu_{aling,dense,linewise,desc}_prefix 226 227 * 返信 228 229 for key in {0..9}; do ble-bind -m vi_imap -f "$key" 'append-arg enter-menu'; done 230 for key in {0..9}; do ble-bind -m menu_complete -f "$key" 'menu/append-arg always'; done 231 232 2023-03-14 233 234 * 2021-10-26 ble/builtin/read: WINCH を受信できていない気がする [#D2022] 235 もしかすると subshell の中では受信できないという事なのかもしれない。 236 237 2023-03-14 winsize を更新する関数を作ったのでこれにも対応する事にする。 238 239 % と思ったが WINCH を受信できていない? 問題は WINCH を受信しても LINES 240 % COLUMNS が更新されない事と思ったが、そもそも WINCH を受信できていないという 241 % 事なのだった。 242 % →即時 WINCH を受信できる訳では無いがユーザーが文字を入力した時にちゃんと 243 % 受信できている。 244 245 subshell の中で実行するとちゃんと内部で設定した trap が発火している様に見える。 246 247 * fixed: ble/builtin/read/TRAPWINCH でも update-winsize を呼ぶ事にした。と 248 思ったが 個別に色々処理するよりも単にここで ble/application/onwinch を呼 249 び出してしまうのが自然である→その様に修正した。 250 251 x fixed: "bash: ble/term/visible-bell:/clear: そのようなファイルやディレク 252 トリはありません" というエラーが発生する。/clear は 253 ble/term/visible-bell/.erase-previous-visible-bell から呼び出されるが、こ 254 の関数は $_ble_base_run/$$.visible-bell.* に属している物を全て削除しよう 255 とする。なので subshell で設定された物も削除しようとする。 256 257 この時親 shell で一度も visible-bell を使っていないと visible-bell が初期 258 化されていない状態になっていて問題が生じる。 259 260 或いは subshell で発生した visible-bell は subshell だけで管理する事にし 261 て subshell を抜ける時に始末する事にする? subshell というか read を抜ける 262 時に処理すれば良い → read を終了する時に visible-bell/erase を呼び出して 263 消去する事にした。C-c を押した時には結局中断して駄目なのでは? と思って試 264 してみたが C-c の時にもちゃんとその場で visible-bell/erase が呼び出されて 265 いる様なので、C-c もちゃんと ble.sh の上で処理されているという事なのだろ 266 う。 267 268 実際に read -ep でも WINCH もちゃんと発火している様に見える。LINES, COLUMNS 269 も更新されている。それなのに textmap が更新されていない様な気がする → と思っ 270 たが textmap を更新した後に出力して確認していたので更新されていない様に見え 271 ただけだった。ちゃんと更新されていて新しい端末幅を反映した値になっている。 272 ずれて見えたのは単に端末の折り返しによって行が増えている事による物だった。 273 274 ? reject: redraw-here がちゃんと働いていない様な気がする? と思ったがそもそ 275 も幅が縮まった時には、縦に内容がはみ出てしまってその分まで遡ろうとはしな 276 いので、現在見えている振る舞いが元々意図した物である気がする。なので気に 277 しない。 278 279 * fixed: サイズの変更があった後に read を中断すると親のプロンプトが表示され 280 てから [EOF] 等のマーカーが表示される。何故? 281 282 うーん。read -ep ; read -ep をコマンドから実行すると一つ目の read と二つ 283 目の read の間で既にプロンプトを表示しようとしている。SIGWINCH が走ってそ 284 れで再描画が起こっている? 285 286 ble-edit/attach/TRAPWINCH ではちゃんと _ble_term_state を確認しているのに 287 何故かそれをすりぬけて表示が実行されている。_ble_term_state が一時的に 288 internal になっている様に見える。 289 290 と思ったら分かった気がする。ble/builtin/read/.impl の中で一旦 291 ble/term/enter してその後で ble/term/leave している。この ble/term/leave 292 するよりも前に WINCH が走って其処で internal 状態にあると勘違いしてプロン 293 プトが表示されてしまうということの気がする。何故 subshell の中で実行しな 294 いのかというと C-c やその他の事故で subshell が予期せず終了した時に状態の 295 復元に失敗しない為だろうという気がする。 296 297 →これは ble/application/onwinch を呼び出す時の条件を増やして対処する事に 298 した。 299 300 2023-03-13 301 302 * trap: winch の様々な問題 [#D2021] 303 304 * fixed: bash-4.3..5.0 で ble-reload 後に WINCH が効かない 305 306 一方で Cygwin の bash-4.4 で ble-reload した後に WINCH が正しく処理されな 307 くなっている。chatoyancy 上では bash-5.2 も 4.4 もちゃんと動いている。 308 309 builtin trap WINCH 自体が発火していない様だ。一方でウィンドウサイズを変更 310 した後は謎の PS1 への代入ジョブ (終了ステータス 127) が表示される。而も、 311 その PS1 に代入される値は現在の値とは関係ない。 312 313 うーん。chatoyancy でも 4.4 で再現した。histdb を無効にした状態で reload 314 すると動かなくなる。bash-5.2 では問題になっていない。5.1 でも OK。5.0, 315 4.3 は駄目。bash-4.2 はちゃんと動いている。つまり 4.3,4.4,5.0 の問題。何 316 故 reload だと駄目なのだろうか。 317 318 詳しく調べてみると ble-detach してから ble-attach すると再び動く様になる。 319 これは要するに rl winch hook のインストールが関係しているという事ではない 320 か? 確認してみると実際に winch が再設定されている。既存の trap を確認し 321 てみると、空になっている。つまり unload の時にクリアされているという事。 322 323 unload-for-reload から呼び出している時には WINCH を削除しない事にした。動 324 く様になった。因みに INT についても同様の処理はしなくて良いのか? と思った 325 が取り敢えずは問題は起こっていない気がするので気にしないことにする。現在 326 は WINCH だけ特別扱いする。 327 328 x この実装だと元々存在していた user WINCH trap が消えてしまうのではないか。 329 →実際に確かめてみたら消滅する。別の変数に記録しておく事にした。別の変 330 数に記録しておいた物を拾う処理をする為に、今まで内部 trap を install 済 331 みの時に単に return 0 していたのを trap_string, trap_command を空にして 332 処理を続ける事にした。取り敢えず動いている。 333 334 ? ok: bashrc で ble-attach しても WINCH はちゃんと有効なのか? bash-4.3 以外 335 は大丈夫。 336 337 * ok: bash-4.3 で WINCH が即時発火しない問題 338 339 逆に bash-4.3 は最初から ble-attach しても prompt attach しても WINCH が 340 全然発火していない。というか 4.3 は --norc で起動して WINCH に trap した 341 としても WINCH が発火しない。次にユーザーが入力を試みた時に初めて発火して 342 いる。逆に言えば 4.3 では入力を開始すれば何れにしても正しい幅で描画される。 343 344 これは取り敢えず入力を開始さえすれば直るので取り敢えずは気にしない。 345 346 * fixed: bash-5.2 でコマンド実行中にサイズ変更が発生した時に反映されない問題 347 348 うーん。全てのコマンドを実行する度にサイズ再取得を実行する必要があるか? 349 或いは idle で処理する必要があるかもしれない。 350 351 できるだけ高速に判定する方法が欲しい。複数のコマンドで速度を比較する? 352 353 stty size, resize, tput lines cols, bash -c 354 355 試してみた所、tput が最も速く、その次が stty、更に resize が来て bash -c 356 による方法が最も遅かった。一方で、stty size は ble/term/stty/enter で呼び 357 出している stty とくっつけることができる。取り敢えず優先順位として stty, 358 tput, resize, bash の順に試し、stty による実装が使える場合には 359 ble/term/stty/enter の stty 呼び出しを修正する方法も考慮に入れる事にした。 360 361 取り敢えず実装した。動いている。 362 363 * edit: WINCH で拡大した時のサイズの変わり方が変だ [#D2020] 364 365 調べてみると onwinch が入れ子で呼び出されている。SINGWINCH の処理が入れ子に 366 なっている。bash 自体は入れ子にはしていないが、read-timeout が WINCH 発火を 367 遅延していて、read-timeout の中から主導で呼び出した WINCH の中で、更に trap 368 WINCH が発火している様だ。 369 370 一方で、ble/application/onwinch の実装を見ると入れ子で呼び出した時の対策は 371 ちゃんとしてある様に見える。 372 373 うーん。ble/application/onwinch の中では何れにしても一切の更新処理は実行し 374 たくない。ble/application/onwinch を抜ける時に改めて処理を行いたい。 375 376 ? 今の実装だと _ble_decode_hook_Processing=body|prologue の時に winch を受 377 け取ると後の ble/application/render の際に無駄に二回描画される気がする。 378 どうせ onwinch の中で ble/application/render が発生するのだから、直接 379 ble/application/render を呼び出せば良いのではないか。 380 381 取り敢えず onwinch 全体を WINCH の抑制対象として onwinch の末尾でも WINCH 382 の発火が途中であった時に onwinch を呼び出す様にした。ble/application/render 383 の前に onwinch があった時には ble/application/render をせずに最初から 384 onwinch をする様にした。実装した。動いている。前よりも素早い動作になった。 385 386 * execmark: wrong usage (2), command_not_found (127) 等の文字列 [#D2019] 387 https://qiita.com/Linda_pp/items/1104d2d9a263b60e104b に面白い記述がある 388 389 /usr/include/sysexits.h に幾らか値が定義されている様だ。EX_USAGE..EX_CONFIG 390 が 64..78 に定義されている。 391 392 2023-03-12 393 394 * global: ret が leak する様になっている [#D2018] 395 396 だいぶ遡ってもずっと leak している。何故だろうか。取り敢えず最新版で修正した。 397 398 * ble/util/bgproc#keepalive がリークしていた 399 * ble/complete/sabbrev/expand もリークしていた 400 401 →ずっと遡っても発生している ret の上書きはどうも ble.sh --norc で発生して 402 いる? 調べてみると任意のキー入力の後で低確率で発生している様に見える。或い 403 は auto-complete が関係しているのだろうか。 404 405 * 結局 emacs keymap の __after_widget__ に問題があった。 406 * 更に類似の呼び出しで PS0 についても ret の leak があった。両方とも直した。 407 408 * bgproc: histdb から切り離して再利用可能にする (motivated by bkerin) [#D2017] 409 https://lists.gnu.org/archive/html/help-bash/2023-03/msg00068.html 410 https://github.com/akinomyoga/ble.sh/issues/302#issuecomment-1462977627 411 412 * done: ble/opts#has バグ修正。影響は cmdspec_opts の plus-options だけの様だ。 413 全然判定できていなかった。常にほぼ false になっていたと思われる。 414 415 * done: ble/util/bgproc 既に開いている prefix を指定した場合は以前のものは 416 削除する。 417 418 * done: 複数のプロセスが走っている場合に対応できる様にプロセスグループを作 419 らせる事にする。set -m を実行すれば良い。 420 421 * done: 実は負の引数を kill -0 に渡すことでプロセスグループの何れかのプロ 422 セスが残っているかどうかを判定することができると分かった → これを利用 423 して改めて kill 部分の処理を作り直した。 424 425 * done: どうやらコマンド置換の中でやるとプロセスグループが作られない様だ。 426 なので bgpid=$(set -m; bgproc & echo "$!") ではなくて ble/util/assign 427 bgpid '(set -m; ...)' とする必要がある。 428 429 一方で、そもそもコマンド置換にしていた理由はあったのだったか。もし別の 430 理由があったのであればそれについても () で壊れないか確認する必要がある。 431 調べてみるとコマンド置換を使っていたのは最初からで (#D1925) 特に考察は 432 していない様に見える。取り敢えず普通のプロセス置換にしても大丈夫。 433 434 修正した。 435 436 * done: EXIT (もしくは internal_EXIT) に自動で登録する? 437 438 →と思ったが単なる close ではなくて EXIT の時に特別の処理をしたい時に 439 EXIT もしくは internal_EXIT を設定していると、期せずして先に bgproc#close 440 されてしまって後処理ができなくなってしまう。 441 442 a うーん。後処理を行いたい場合の為に internal_EXIT に登録しない設定を作る? 443 444 特に指定しない場合に自動で終了処理を追加するとしても、internal_EXIT で 445 呼び出して良いのだろうか。他の EXIT 処理が bgproc を利用したいという場 446 合に問題が起こる可能性がある。という事を考えると、EXIT の方に登録するべ 447 き? 然し EXIT の方に登録したとしても呼び出しの順序によって変なことが起 448 こる可能性がある。 449 450 b reject: bgproc/onclose:prefix の中で EXIT 処理を実装してもらう 451 452 別の方法として bgproc#close の中で終了処理としての close なのか一時的な 453 close なのかを判定して各自処理を切り替える方針で実装してもらう? しかし 454 これだと bgproc が生きていても死んでいても実行するべき処理の場合に困る。 455 単に bgproc#close からの呼び出しを期待していると bgproc が走っていない 456 場合にその処理が呼び出されなくなってしまう。それに分かりにくい。 457 458 取り敢えず owner-close-on-exit と no-close-on-exit を opts として指定可能 459 にすることにした。 460 461 * fixed: unload の時にも同様に呼び出すべきなのではないか? というか寧ろ今ま 462 で EXIT でやっていたのは unload でやるべきだったのではないか。 463 464 →histdb と bgproc の両方を EXIT ではなく unload を使う様に変更した。 465 466 * done: close-callback は関数に置き換えるべきなのでは? 結局 bgproc#close を 467 呼び出す必要があるのであれば、opts の中に直接コマンドを記述するよりはちゃ 468 んとした関数を定義して関数名を close-callback に指定することになるが、そ 469 うであるのならば最初から関数名を ble/util/bgproc/close:_ble_histdb 等に固 470 定してそれを直接呼び出す様にした方がわかりやすい。 471 472 また callback の中で ble/util/bgproc#close を呼び出すのも一見して無限ルー 473 プになるのでインターフェイスとして分かりにくい。それよりは単に close 直前 474 の終端処理として呼び出す様にするのが良い気がする。それでも 475 ble/util/bgproc#close を入れ子で呼び出した時の対策は今のまま残しておく事 476 にする。 477 478 * done: request を送る機能 & 死んでいたら再始動する機能 479 480 timeout でデータを削除してしまうと restart 時に問題なのでは? なので 481 timeout 時には [4] だけ消す事にする? timeout で終了した場合と期せず終了し 482 てしまった場合は区別するべき。 483 484 適当にいい加減な bgproc を作って動作確認した。取り敢えず簡単な使い道の範 485 囲ではちゃんと動いている様である。 486 487 また help-bash で提供されていた例に関しても cotnrib/config/github302 に実 488 装してみて動作確認した。動いている気がする。 489 490 面倒なので取り敢えずこれで push する事にする。何れにしても histdb は未だ実 491 験中でドキュメントにも記していないし、また例として実装した perlre-server も 492 help-bash / GitHub #302 の為の例に過ぎないので寧ろテストしてもらうぐらいで 493 良い。 494 495 2023-03-10 496 497 * complete: complete_source_sabbrev_ignore が動いていない [#D2016] 498 499 * done: そもそも全然動作していなかった。修正した。 500 501 * fixed: opts の方も動作をチェックする。no-empty-completion は '\' から始め 502 ても候補が生成されない様だ。うーん。COMPV ではなく COMPS に対して適用する 503 べきである。 504 505 * done: wiki, blerc: complete_source_sabbrev_{opts,ignore} 506 507 2023-03-09 508 509 * readonly blacklist のチェックを m scan に含める (motivated by mozirilla213) [#D2015] 510 https://github.com/akinomyoga/ble.sh/issues/289#issuecomment-1457920928 511 512 * done: m scan 513 514 * done: readonly でファイル名・行番号を表示する。 515 516 * done: 警告の表示の回数上限はパス毎に決める? (dict が使えない場合を除く) 517 518 →一回表示した(パス,行,変数)の組み合わせに関しては二度と表示しない様にす 519 る。トップレベルの呼び出しの時には回数上限を使う。 520 521 * done: 回数上限はコマンドラインの実行ごとにリセットする? 522 523 2023-03-10 ちゃんと動いていない。FUNCNAME を最後の要素までチェックする事にした。 524 525 * complete: option:source を他のコマンド名として呼び出せる様にする (requested by mozirilla213) [#D2014] 526 527 complete: progcomp_alias と同様の処理をその他の補完生成の時にも行う 528 https://github.com/akinomyoga/ble.sh/discussions/287 529 530 と思って source:options の実装を確認したが既にちゃんと alias を考慮した処理 531 になっている。 532 533 より詳しい設定について尋ねたら返信が戻ってきた。要するに、他のコマンドのオ 534 プションを別のコマンドの補完に表示したいという事らしい。これに関しては自前 535 で新しい補完を定義する必要がある。 536 537 * done: それと現在の source:option の生成はコマンド名を決め打ちにしているの 538 で、それを関数に切り出して調整可能にしたい。取り敢えず source:option を真 539 ん中で分割した。 540 541 取り敢えず試しに簡単に実装してみて振る舞いを調べる。動いている気がする。 542 543 2023-03-08 544 545 * contrib: sabbrev 補完候補を生成しない設定 (motivated by mozirilla213) [#D2013] 546 https://github.com/akinomyoga/ble.sh/discussions/288#discussioncomment-5159335 547 548 これを contrib に入れて改良する。例えば simple-word eval する。argument か 549 ら呼び出された時にだけ不活性にする。ADVICE_FUNCNAME で本来の FUNCNAME を記 550 録する (もしくは function#advice 側で advice 関連の FUNCNAME を削除した物を 551 取得して返す関数を作る?)。 552 553 ble.sh 側でも sabbrev は empty completion しない設定や、literal sabbrev 候 554 補の生成を抑える設定などを考えても良い気がする。etc. 555 556 bleopt complete_sabbrev_opts=no-empty-completion:literal 557 558 うーん。実装仕掛けたがこれは literal を実装してからにするべきの気がする。取 559 り敢えず inline, linewise sabbrev を実装した (#D2012)。 560 561 改めて考えてみたが取り敢えず literal sabbrev の類いは wordwise ではないので 562 source:argument では生成しなくて良いという気がする。後になって欲しくなった 563 らその時に考える。 564 565 * 2021-05-19 sabbrev: 単語でなくても任意の文脈で発動する sabbrev が欲しい [#D2012] 566 567 \ 等で前置すれば特に問題ないのではないか? 然し、その為には全ての場合につい 568 て一致するかどうか確認する必要がある。 569 570 2023-03-08 どうも実際に \ に色々割り当てて使おうとしている人がいる様だ。こ 571 の用途だと実際に単語でしか発動しないというのは困るのではないだろうか。 572 https://github.com/akinomyoga/ble.sh/discussions/288#discussioncomment-5226973 573 574 例えば ble-sabbrev --literal 的なオプションにするのはどうだろうか。通常の 575 sabbrev が見つからない場合に --literal sabbrev を試みる。literal sabbrev に 576 関しては -m は対応しなくて良い (もしかしたら最終的に実装する可能性もあるが 577 今ではない)。 578 579 ? resolved: 取り敢えず literal という名前で実装したが本当にそれで良いのか。 580 581 % literal というと -m の反対という気もするし、そもそも sabbrev 自体が 582 % literal である。元々伝えたかったのは文法情報等を無視した sabbrev という 583 % 事だった。例えば context-free sabbrev expansions 等の方が自然の気がする。 584 % 然し、context-free を表現するオプション名として適切な物が思い浮かばない。 585 % 586 % a 何も考えなければ頭文字の -c だが、実際は context 依存の逆という事なの 587 % で変な気がする。 588 % 589 % 或いは漢字変換的な使い方を想定して conversion の頭文字と取る事もでき 590 % る? 然し漢字変換というとどういう名前だろうか。IME と考えて -i とする 591 % か。然しそれだと i は input の i なので一般的すぎて微妙? 否、input 専 592 % 用と思えばやはり良い? 然しオプション名が例えば input-no-insert だとよ 593 % く分からない。やはり実際の呼称と紐づいたオプション文字にしたいと考え 594 % ると呼称自体から丁寧に決めたい。 595 % 596 % b context に依存しないという意味でやはり literal 的な要素があって、そう 597 % 思うと -l でも良い様な気もしてくる。 598 % 599 % c -c の逆という事で -C 等を使うという可能性もある? がやはり分かりにくい 600 % 気がする。 601 % 602 % d -f はどうだろうか。ble-bind -f (bindable Function) という既存の例があっ 603 % てその印象があるが、それを抜きにすれば悪くない気はする。然し、やはり 604 % 自然かというと疑問が残る。 605 % 606 % e 英小文字にしたい。という事を考えると片っ端から可能な物を列挙して考え 607 % てみても良いのかもしれない。zsh alias で既に使われているオプションは 608 % 避けたい。 609 % 610 % zsh alias で使われているのは gmrsL である。grs はそれぞれ alias の種 611 % 類を指定する為のオプションで、-g はグローバル alias (ble-sabbrev に対 612 % 応)、-s は suffix alias (拡張子展開)、-r は通常 alias である。-m 613 % PATTERN はまとめて複数の alias を glob で指定するのに使う。-L は現在 614 % の alias の定義を出力するのに使われる。 615 % 616 % ble-sabbrev では -P を出力に使いたい気がする。 617 % 618 % * -a は grep の -a の様に文字列 (ascii) をそのまま解釈するという意味 619 % に使えるかもしれない。 620 % 621 % 或いは anywhere という意味にも取れる。これが良い気がする (anywhere 622 % という意味に取れば every where -e もありかもしれないが -e はより色々 623 % な意味に取れそう)。でも anywhere というのも微妙なのは、anywhere と 624 % 言いつつカーソルの直前で起こる必要があるという事。何処からスタート 625 % しても良いという意味での anywhere であるが、それを表現するのに丁度 626 % 良い別の表現はあるだろうか。 627 % 628 % * -b は backward? 629 % * -i は inplace という漢字がするけれど違う気もする。 630 % * -djkwyz ??? 631 % x -e は grep の様に次に通常のパターンが来るという意味の引数に使えるか 632 % もしれないが、それはいま目的としている物とは違う気がする。 633 % x -gs は既に zsh で別用途に使われているので混乱の元 634 % x -n は特別な効果を全て削除しているという雰囲気が出るかもしれない? で 635 % もやはり変な気がする 636 % x -o はオプションを指定しそうな気がする。 637 % x -p は出力という漢字がする。 638 % x -q は quoted という感じがするが現在の目的からすると混乱の元 639 % x -t は tail という意味に取れる気もするがそもそも sabbrev は常に末尾 640 % にカーソルがある時に発火している。これは context-free sabbrev 特有 641 % の特徴ではない。類似の考えで -h (here) 的なものも駄目。 642 % x -u は変更のある項目の選択に使いそう? でも ble-sabbrev に既存設定や 643 % 既定値などない為、登録されている全ての物が変更ありになるのでこのオ 644 % プションをその意味で使っても意味がない。 645 % x -v も literal 的なものを想起する。C-v 関係だろう。然し、これも現在 646 % の用途に合っているかというと微妙な気がする。 647 % x -x は何か実行しそう。 648 % 649 % 長い呼称を先に決めてからそれの短縮オプション文字を決めるのが良さそう。 650 % 651 % literal-no-insert, conversion-no-insert, contextfree-no-insert, 652 % inplace-no-insert, inword-no-insert 等。うーん。inword が良い気がしてき 653 % た。類似の物として inword subword, substr, substring, suffix, 等。 654 % inword だと空白も含む略語展開に合わないし、丁度単語に一致している時も変 655 % な気がする。代わりに inline というのも良いのかもしれない、と思ったが 656 % sabbrev 自体既にある意味で inline なので混乱の元かもしれない。唯の置換 657 % と思えば substitute だとか replace だとかもありなのだろうか。然し、これ 658 % も sabbrev 一般の性質を表して言えるのに過ぎない。 659 660 うーん。コマンド行全体に作用する sabbrev も定義したくなって来た。それも定 661 義すれば全体として consistent になる気がする。 662 663 →結局 -l (--linewise) 及び -i (--inline) を両方定義する事にした。これが 664 インターフェイス的にも分かりやすい。 665 666 * done: 取り敢えず実装仕掛けた literal は inline に変更する。と思ったが、-il 667 をまとめて linewise と呼ぶ事にする。 668 669 * done: wordwise vs literal は最長一致に変更する。呼び出し元で一々指定しな 670 くて良い様にする。同時にどの種類の展開が起こったのかを取得できる仕組みを 671 作る。文字で返すのが良い? もしくは終了ステータス? 672 673 * done: 現在の実装では inline も単語で切ってから判定しているが 674 _ble_edit_str 全体に対して適用するべきの気がする。 675 676 * done: 呼び出し元に展開の種類を返す機能。 677 678 * done: ble-sabbrev の -mil は全体に作用する様にインターフェイスを変更する。 679 680 * done: ble-sabbrev に long option を用意する事にする。 681 682 * done: wiki: ble-sabbrev -il 683 684 * done: wiki: edit_magic_opts 685 * done: blerc: edit_magic_opts 686 687 * done: -w で通常の sabbrev の種類を選択できる様にする。通常の sabbrev を選 688 択するのに毎回 --type=wordwise としなければならないのは不便である。 689 690 ? resolved: linewise は本当に linewise と呼んで良いのか? コマンドライン全体 691 に一致するのだから bufferwise とか whole とか all とか exact とかにするべ 692 きなのでは。或いは実際に linewise に一致する様に変更した方が便利? その時 693 にはインデントも許す様にする。extglob を一時的に有効にしないと面倒だろう 694 か。 695 696 [[ $1 == "$key" || $1 == *$'\n'*(["$sp"])"$key" ]] 697 698 或いは $'\n' で切断して trim しても良いかもしれないと思ったがそうすると今 699 度は key に改行や空白が含まれていた場合に都合が悪い。それに trim は regex 700 を使っているので別に extglob よりも早いとも限らない。 701 702 extglob は実装の問題から遅くなる可能性があるがそれは気にしない事にする? 703 と思ったが現在の codebase では extglob はほぼ使っていない。というか確認し 704 てみたらユーザーの提供したパターンなどを評価するときを除いて全く使用して 705 いない。なので、ここでも使わない実装を目指したい様な気もする。 706 707 というか最初に末尾が $key に一致するか確かめてその上で残っている文字列に 708 対して regex で確認を行えば良いだけなのでは? その様に実装する事にする。 709 710 * 2023-03-02 complete (source:argument): sabbrev 候補が気になるのは最初に表示されるから? (motivated by mozirilla213) [#D2011] 711 https://github.com/akinomyoga/ble.sh/discussions/288 712 713 後ろに回した方が良い気がする。修正した。 714 715 コマンド補間についても同様ではないか? と思ったが変数名よりは sabbrev の方が 716 先に来て欲しい。コマンド名と sabbrev だとどちらが先にくる事を期待するのかは 717 微妙である。コマンドは基本的に大量にある。一方で、sabbrev は有限個である。 718 具体的にコマンド名を入力してコマンド名が絞れてきた頃には sabbrev も絞られて 719 いると期待される。なので、コマンド名に関しては表示しなくて良い気がしてきた。 720 721 然しそう考えると引数の場合も本当に sabbrev を後回しにするべきなのか分からな 722 い。と思ったが、引数補間の場合にはオプションの数は少ない可能性がある。一方 723 で予め定義しておいた sabbrev が大量に存在している時には、sabbrev 候補で全部 724 が埋め尽くされて実際に知りたいオプションのリストを見る事ができなくなる。な 725 のでやはり引数補間の場合には sabbrev 候補は後ろに回すべきである。 726 727 * [棄却] prompt: $PWD in airline が更新されない? [#D2010] 728 https://github.com/akinomyoga/ble.sh/discussions/294#discussioncomment-5227252 729 730 bind -x の中でディレクトリを移動してもそれが反映されたりされなかったりする 731 という事。うーん。\w を使っていればちゃんと反映されるのではないか。 732 733 直接 $PWD があれば自動的に抽出される筈だし \w や \W があっても抽出されるの 734 では? と思ったが、勝手に変更をリアルタイムで追跡するのは変だという事になっ 735 た様な気もする。例えばコマンド終了直後の値を表示しておきたいのにすぐに変わっ 736 てしまっては困るのである。 737 738 然しそうだとしても別の理由でプロンプトの再評価が起こった時に結局表示が更新 739 されてしまうのだから、そういう揮発性の情報を表示する時には元より ble.sh で 740 はちゃんと別の変数に記録しておく必要があるのではないか。 741 742 →実際試してみると \w にしておけばちゃんと反映される。$PWD だと反映されない。 743 section 毎のキャッシュがちゃんと働いているからであろう。 744 745 これに関しては更新したければ適切に設計する必要がある。 746 747 * ok: wiki に説明を書く? と思ったら既にちゃんと add-hash が記述されていた。 748 749 実際に簡単なものを作って実演してみる(以下)。動いている。これは後で返信する。 750 これに関しては現状で修正する事はない気がする。 751 752 function ble/prompt/backslash:mypwd { 753 ble/prompt/unit/add-hash '$PWD' 754 ble/prompt/print "$PWD" 755 } 756 bleopt vim_airline_section_c='\q{mypwd}' 757 bind -x '"\C-t": cd - &>/dev/null' 758 759 * complete: limit line length for auto-complete [#D2009] 760 761 "a @b" の時に @ に { を入力すると固まる 762 763 どうも a5b10e8 で問題が発生する様になっている。うーん 764 ble/application/render で固まっている。となるとやはり文法が関係しているので 765 はないか。という気がする。調べて行くと textmap#update で時間がかかっている。 766 どうも巨大な文字列が自動補完で挿入されてそれの解析で時間がかかっている様だ。 767 長さ 50170 になっている。 768 769 x fixed: 自動補完で limit が効いていないのは何故か? line_limit_length は 770 10000 の筈である。それの5倍の長さになっている。 771 772 →挿入の時点では replace-limited を使っている。然し、何故かそれをすり抜け 773 ている。うーん。line_limit_type が editor で、editor の場合には 774 replace-limited の時点では何も行わない。__line_limit__ という名前の特別な 775 キーが送信されてくる仕組みになっている。 776 777 誰が __line_limit__ を送っているのかというと ble/content/check-limit とい 778 う関数である。そしてこの関数はどうやら ble-decode/EPILOGUE から呼び出され 779 ている。丁度最後の render を呼び出す直前である。期待としては表示を試みる 780 前に editor が起動されるという事だが、auto_complete の中にいるので 781 __line_limit__ が単に無視されてそのまま描画ルーチンに入っているということ 782 の様だ。 783 784 うーん。そもそも auto-complete に入るのが間違いの気がするので 785 auto-complete/enter の時点で reject する様に修正した。 786 787 x この巨大な補完候補は何処から生成されているのか? histdb? → どうやら 788 histdb の様である。とても長い単語が登録されているのだろう。histdb の側で 789 余りに長い物は除外するべきだろう。登録する時点で保持する? それとも補完す 790 る時点で保持する? 791 792 取り敢えず今はテストの為にこの長い単語を保持しておく事にする。 793 794 x ok: 幾ら文字列が長かったとしても 50k 程度でフリーズするのは変な気がする。 795 何故? 796 797 →調べてみたら textmap#update で 20s かかって update-syntax (parse) で 798 39s かかっている。更に何処かで 20s ぐらいかかって最終的に表示される。 799 textmap#update は全ての文字の表示位置を計算しているので遅い。parse は勿論 800 時間がかかる。その他も何か一つずつ処理しているか何かなのだろう。つまり、 801 何処かが特別に時間がかかっているのではなくて、全体的に処理に時間がかかっ 802 ているということの様だ。 803 804 うーん。これは結局単に時間がかかっているというだけの事。 805 806 * histdb: もし巨大な単語が紛れ込んでいたとしても検索の時点で文字数に制限を 807 かける事はできないか→取り敢えず検索の時点で文字数に制限をかける事にした。 808 動いている。 809 810 * edit: ~name による "named directory" 展開機能? [#D2008] 811 https://github.com/akinomyoga/ble.sh/discussions/299 812 813 sabbrev の新しい展開の種類として実装する可能性? チルダ展開と同じ文脈で活性 814 化して、それが直前の単語に含まれていた場合に展開する。コマンド実行前に展開 815 する機能は混乱の元なので実行したくない気もするが…。 816 817 * 然し ~xxx の状態で展開されていないと補完が効かない気がする。補完する時に 818 内部で ~xxx も考慮に入れて候補を生成するのは大変だ。なので補完を試みる前 819 に展開するべきの気がする。/ を入力する瞬間か或いは補完を実行する直前か。 820 うーん。というか magic-insert という widget を作る方が良い気がして来た。 821 それで / も magic-insert にしてしまう。 822 823 * 同時にコマンド実行の瞬間に全体をスキャンして展開する仕組みを作っても良い 824 気がする。 825 826 % 取り敢えず magic-insert は実装する。実装した。 827 % 828 % さて、ここでの疑問は既定で / magic-insert を設定しておくべきかどうかという 829 % 事。というか / で履歴展開が実行されると困るのでは。なので、一部の展開だけ行 830 % うべきの気がする。というか alias 展開も実行したくない。 831 % 832 % やっぱり現在の振る舞いは space だからこそ動くのである。magic-insert はやめ 833 % る事にする。 834 835 色々考えると / に対しては sabbrev だけ行う関数を定義するべきの気がする。 836 magic-slash を実装してみた。 837 838 x done: 然し、tilde 展開を装っている場合に普通と違うのは変数代入形式の引数 839 の右辺で : 区切りの位置の最初から sabbrev expansion を試みる必要があると 840 いう事。 841 842 と思ったがこれは通常の sabbrev expansion でも対応するべきの気がする。うー 843 ん。対応した。 844 845 ここでの疑問はこの magic-slash を既定の binding として登録するべきかどうか 846 という事である。或いは ~ で始まる物だけを magic-slash で変換の対象とする? 847 或いは / に感応する sabbrev の category を新しく作る? うーん。~ で始まる物 848 だけを特別扱いするのが良い気がする。 849 850 * done: wiki 851 852 * done: slash-strip: magic-slash で挿入を行う場合は元から sabbrev の定義に 853 含まれる末尾の / は削除する。 854 855 * done: slash-strip: -m の方も対応する必要がある? と思ったが実際にやってみ 856 ると menu-complete が始まった後に / が挿入されて変な事になる。これはちゃ 857 んと magic-space でやっているのと同様に処理する必要がある。一意確定の時に 858 は slash-strip を自前で処理する。 859 860 * syntax: echo alpha[0]+=~ がチルダ展開として認識されていない [#D2007] 861 これは単純なミスだった。修正した。 862 863 * sabbrev: 変数代入右辺での展開の対応 [#D2006] 864 865 変数代入の右辺では右辺に対して sabbrev 展開を行う。: で区切ったフィールドも 866 認識する。 867 868 * ok: 然しこれに対応するには複数の sabbrev 展開位置について考慮に入れる必要 869 がある気がする。例えば locale-key の context に rhs も対応すれば良い気が 870 するが、そうすると今度は通常の sabbrev で = も含めて展開しようとしている 871 物が動かなくなる。と思ったが、現在の設定だと = を含む sabbrev はそもそも 872 定義できないのでは?なので rhs は含めてしまって良い気がする。 873 874 * done: 変数代入右辺の特定 875 876 実際に変数代入の右辺での sabbrev に対応するとしてどの様にして変数代入の右 877 辺を特定するのか。一旦その様な関数を書いたかもしれないと思ったがどのよう 878 に探せば良いか分からない。使っていそうな所を探すのが良い気がする。 879 880 arr=([0]=xxx) 及び var=xxx の場合には rhs でちゃんと抽出できている。問題 881 は argument の時にどの様にしているのかという事。 882 883 a var=xxx の時にどの様に抽出しているのかを確認すれば良いのではないか? 884 885 b 或いは complete 側で source:argument の fallback をどの様に処理している 886 か。うーん。これは単に正規表現で一致させているだけの気がする。 887 888 c と思ったら ble/syntax:bash/find-rhs という名前のそのままな関数があった。 889 この関数を使って見る事にする。 890 891 取り敢えず対応した。更に : による区切りにも対応したい気がするがそれは後回 892 しにする。と思ったがやはり後になると面倒なのでここで対応する事にする。 893 894 * done: rhs や argument (変数代入) の時に : 区切りで一番近いフィールドに対 895 して sabbrev 展開を実行する? 896 897 ":" を含む sabbrev があっても良いが、特に a=...:... の形式をしている時に 898 は効かない様にしてしまっても良い気がする。 899 900 a 取り敢えず simple-word で区切る事にした。 901 902 b もっとちゃんとやろうと思ったら文法情報を参照する事もできるかもしれない。 903 904 特に、rhs の文脈では必ず : で stat を設置しているのだから rhs 内部を舐 905 めて stat に記録された ctx をチェックすれば良いのでは? 906 907 local i 908 for ((i=asrc[1];i<comp_index;i++)); do 909 [[ ${_ble_edit_str:i:1} == : && ${_ble_syntax_stat[i]-} ]] || continue 910 local ctx=${_ble_syntax_stat[i]%%' '*} 911 [[ ${_ble_syntax_bash_command_IsAssign[ctx]-} ]] && 912 ((asrc[1]=i+1)) 913 done 914 915 と思ったがこれだと $() 等の内部にある : も拾ってしまう。なので本当にちゃ 916 んとやろうと思ったら nest 情報も参照しなければならず大変である。今は実 917 装しない事にする。 918 919 * done: _a-zA-Z0-9 に統一する。検索しやすい為。 920 921 * complete: adb completion で "no devices/emulators found" というエラーメッセージ (reported by mozirilla213) [#D2005] 922 https://github.com/akinomyoga/ble.sh/issues/292 923 924 これは結局通常の bash での TAB 補完でも同様のエラーメッセージが発生するとい 925 う事だった。何が問題なのかは分からないが、ちゃんと設定されていない状態で補 926 完を試みようとするとエラーメッセージが表示されるという事なのだろうか。設定 927 されていても設定されていなくても補完の途中でエラーメッセージは出すべきでは 928 ない気がするが、取り敢えずエラーメッセージは封殺する事にする。 929 930 * upstream に報告しようと思ったが何処に報告すれば良いのかよく分からない。 931 platform/system/core に昔 adb.bash が含まれていた? ような含まれていなかっ 932 た様だ。野良 repository に adb.bash が追加されていて、それが広まったとい 933 う可能性もある。或いは、大本の repository では管理していないが配布アーカ 934 イブには含まれていた? 935 936 sdk/bash_completion/adb.bash 的な物もあるようだが。これは大昔だ。 937 https://android.googlesource.com/platform/sdk/+/3056c8e/bash_completion/adb.bash 938 939 ここにもあるがこれは報告者の使っている物とは微妙に異なる様だ。 940 https://github.com/mbrubeck/android-completion 941 942 結局よく分からない。Google が何処か人目に触れないところで最新版を管理して 943 いて配布しているという事なのだろうか。 944 945 * decode: M-S-o in konsole? (reported by mozirilla213) [#D2004] 946 https://github.com/akinomyoga/ble.sh/issues/298 947 948 これは取り敢えず分かった。 ESC O が他のキーの prefix になっている為に次の文 949 字を待っている。失敗した時には decode_error_cseq_discard=1 になっているので 950 全体が捨てられる。という事が起こっている。 951 952 x 保留: テストで ESC [ を何回か押していたら無限ループになって死んでしまった。 953 954 何が起こっているのだろうか。ESC { を複数回押したのがよくなかったのかもし 955 れない。 M-{ は補完をブレース展開で全て挿入する機能になっていて、空のコマ 956 ンドラインで実行すると全てのコマンド名をブレース展開で挿入する事になる。 957 とても長いコマンドラインになって処理に時間がかかっていたのではないか。 958 959 * reject: charseq 毎に timeout を設定できるようにする機能についても考えたが、 960 必要性がない気がする。そもそも keyseq に timeout を指定できる様にしたのは 961 ユーザーがそれで動作を変える (keychord などの様に) ことができるためであっ 962 た。然し、charseq にそのような使い方があるとは思えない。また、考えてみる 963 と timeout が必要なケースも実はかなり限られている。実は ESC <char> の時だ 964 けの個別対応で良い。 965 966 * ok: ESC [ 1 等についても手で入力した場合と続きがある場合で区別が付かない 967 のではないか。と思ったが、手で一瞬で ESC [ 1 まで入力することはできないし、 968 ESC [ で止まった時点で M-[ に確定する気がする。逆に ESC [ 1 まで一気に受 969 信したとしたらこれはより長い CSI シーケンスの一部であると判断するのが自然 970 である。なので、 ESC [ 1 等に対して timeout を考える必要はない。 971 972 取り敢えず timeout を設定する事にした。現在の位置で一致するが続きがあっても 973 良い曖昧なシーケンスの場合、または ESC を受け取った状態の時には 5ms 待って 974 続きが来なければ現在のシーケンスで確定という事にする。取り敢えずは動いている。 975 976 ? yes: vim はちゃんとこの場合に対応しているのだろうか。と思って確認してみた 977 らちゃんと動いている。やはりユーザーから文句があったのだろうか。 978 979 2023-03-06 980 981 * edit (rps1): PS1 に prompt_rps1 の色が残る (reported by linwaytin) [#D2003] 982 https://github.com/akinomyoga/ble.sh/issues/293#issuecomment-1452786142 983 https://github.com/akinomyoga/ble.sh/issues/293#issuecomment-1453507285 984 Ref #D1972 985 986 今迄問題が生じていなかったのは ble/textarea#render/.show-rprompt の直後にプ 987 ロンプト原点以外の場所にカーソルを配置していたので、sgr に色が設定されてい 988 たとしても何れにしても goto.draw の際に色がクリアされていたから。 989 990 それが e128801c1 によってプロンプト原点に強制的に戻る様にしたので PS1 の開 991 始位置に移動する時の sgr0 が出力されなくなって色が残る事となった。元々移動 992 する時に sgr0 を出力したのはそうしないと変な所の色に影響が出てしまう端末を 993 避ける目的があったので、元々 show-rprompt で先頭に戻る CR の直前の時点で 994 _ble_term_sgr0 を出力するべきである。その様に修正した。 995 996 * contrib/prompt-git: git gc したら branch 名など取得できなくなった [#D2002] 997 998 調べてみるとどうも .git/info/refs の中にまとめて記録される様になった様だ。 999 対応した。 1000 1001 2023-03-05 1002 1003 * コマンドラインに文字列を挿入する関数 (zsh print -z) (requested by mozirilla213) [#D2001] 1004 https://github.com/akinomyoga/ble.sh/discussions/291 1005 1006 * done: TMOUT= は ble/bash/read の中で指定してしまうのが良い気がする。 1007 ble/bash/read を使う時に必ず TMOUT= の設定を試みなければならないというの 1008 は面倒な契約であるし忘れてしまう可能性が高い。 1009 1010 * Bash プロセス間通信の整備 1011 1012 これは何らかのプロセス間通信を実装する必要がある気がする。前々から考えて 1013 いた枠組みをこれを機に実装してしまうのが良い気がする。さて、何らかのメッ 1014 セージが来た時にどの瞬間に読み込むのかという問題がある。 1015 1016 a joblist をチェックするタイミング? 今回の場合に丁度良い気がする。 1017 1018 joblist.flush は現在は ble-edit/exec:gexec/.end から呼び出している。コ 1019 マンドを実行していない時の joblist の表示は何処で呼び出している? 1020 →ble/util/joblist.bflush を .insert-newline の中から呼び出していた。 1021 1022 b history_share をチェックしている箇所? これはコマンド実行直前、 1023 discard-line、履歴移動直前等で行っている。今回の場合には余り適していな 1024 い様に思われるし、一般の枠組みとしても適したタイミングを与える様には思 1025 われない。 1026 1027 c 何かキー入力をする度に? 然しこれは何か画面更新をしたい場合等には余り適 1028 していない気がする。 1029 1030 d PRECMD と同じタイミングで呼び出すという手もある気がする。と思ったが、 1031 precmd が呼び出されるのは既に leave-command-layout した後なので不用意に 1032 何かを出力できない気がする。 1033 1034 一方で joblist.bflush のタイミングだとしても問題になる様な気がする。 1035 1036 寧ろ precmd でなにか出力したい時には enter-command-layout / 1037 leave-command-layout を自分で呼び出して出力する事にすれば問題ない気がす 1038 る。既に enter-command-layout には呼び出し階層のカウントも実装している 1039 ので呼び出している箇所が既に command-layout なのかどうかなどについて考 1040 えなくて良い。更に ble/util/buffer の flush 等についても意識しなくて良 1041 い。 1042 1043 % 最終的に複数の処理タイミングの種類を考える必要があるかもしれないが、取 1044 % り敢えずは a という事にする。後で処理タイミングを追加できる様に最初の実 1045 % 装から処理タイミングを指定するフィールドを作っておく。暫定的な名前は何 1046 % にするか。postexec だと複数 exec の時に正しくないし、exec_end にしたと 1047 % してもまた空のコマンドを実行した直後にも発火することを考えると正しくな 1048 % い。 1049 1050 うーん d の方が良い気がしてきた。これにすれば最初の実装における既定の処理 1051 タイミングに対応する名前も precmd で良くてすっきりする。また、単に 1052 blehook internal_PRECMD に ble/message.check を指定しておけば良い。 1053 1054 ユーザーの作成したイベントについても処理できる様にしたい。broadcast の関 1055 数も作りたい。message という関数も用意する。 1056 1057 取り敢えず一通り実装した。試験的な handler print で動作確認もした。 1058 subshell からデータを送信できる事も確認した。 1059 1060 * コマンドラインへの文字列挿入を実装する。 1061 1062 コマンド名は何が良いか。ble-print はない。ble insert-string string ぐらい 1063 にする→結局 append-line にした。文字列を挿入するとしても既に入力されてい 1064 る行に続けて挿入するのも変である。独立な新しい行を追加するのが自然である。 1065 すると insert-string よりは insert-line の方が自然である。line は widget 1066 の名前でもよく使われている。また、現在のカーソル位置などにいきなり挿入す 1067 るのも変な気がする。コマンドラインの末尾に挿入するのが自然である。という 1068 ことを考えると append-line が自然の気がする。 1069 1070 取り敢えず実装した簡単だった。 1071 1072 ? ok: 特に大量の文字列を挿入する時に何が起こるか? line_limit_length のチェッ 1073 クはどの時点で入るのだったか → ble-edit/content/replace-limited によって 1074 挿入している限りはちゃんとチェックが入る様だ。 1075 1076 o C-o とちゃんと一貫した動作になるか→OK ちゃんと動いている。 1077 o 複数の append-line があってもちゃんと動くか → 動いている。 1078 1079 ---- 1080 1081 その他の修正 1082 1083 * main (read): ble/bash/read で bash-5.2 で -r を付け忘れていた。 1084 1085 * main (ble): "- " が名前に含まれている ble.sh 関数 "ble-*" も "ble *" の形 1086 で呼び出せるようにする。 1087 1088 * util: ble/string#quote-word を set -ue 等で呼び出しても大丈夫な様にする。 1089 1090 * util: "builtin : >| file" は単に ">| file" で良い。 1091 1092 * global: builtin read する時の TMOUT= は ble/bash/read の中で指定する 1093 1094 ---- 1095 1096 2023-03-06 直接 eval するのはやはり変な事が起こりそうで嫌なので is-simple 1097 の判定だけ行ってから eval する事にした。 1098 1099 ---- 1100 1101 wiki に ble-append-line の説明を追加した。 1102 1103 * done: wiki: ble append-line 1104 1105 * 2022-07-06 highlight: "function aaa bbb ccc" と素早く入力すると変なエラー着色の残り方をする [#D2000] 1106 1107 % function aaa bbb ccc として C-l すると描画の着色がおかしい。C-l としなく 1108 % ても高速に入力するとこういう事が起こる様だ。 1109 1110 素早く入力した時などに発生し C-l で再描画しても残っている。 1111 1112 調べてみるとどうやらエラー着色が layer に残留してしまうのが原因の様である。 1113 1114 _ble_syntax_attr/tree/nest/stat? 1115 06 a 000 'f' | stat=(CMDX w=- n=- t=-:-) 1116 | a 001 'u' | 1117 | a 002 'n' | 1118 | a 003 'c' | 1119 | a 004 't' | 1120 | a e 005 'i' | 1121 | a 006 'o' | 1122 | a 007 'n' + word=CMDI:0-8/(wattr=d) 1123 3 a 008 ' ' 1124 22 a 009 'f' 1125 1126 しかもこのエラーは単語着色のエラーではなくて文法的に閉じていない時に実施 1127 されるエラー着色である。何故この様な中途半端な事が起こるのかよく分からな 1128 い。うーん。起こる条件が分からない。滅多に起こらない。 1129 1130 これはなかなか再現しないので別項目にして後で考える事にする。 1131 →どうも syntax.sh が遅延ロードされた時に発生する様である。 1132 1133 2023-03-05 SIGWINCH 対策を行った時に改めてこれについて考えた 1134 1135 | * reject: 文法情報が初期化時に壊れるのは SIGWINCH などによって再描画が解 1136 | 析の最中に発生するからではないか。その場合には SIGWINCH の処理を延期す 1137 | るべきである。というか、それは ble/application/render の時点で入れ子で 1138 | render が発生しない様に調整するべきである。→と思って実装を確認したら既 1139 | にその様な実装になっていた。 1140 | 1141 | →というか初期化時に壊れるのは SIGWINCH とは関係ない。ウィンドウサイズ 1142 | を変更していなくても、文字列を素早く入力するだけで文法情報が破壊される 1143 | ので。やはり初期化時に function というのを素早く入力した時に壊れがちで 1144 | ある。特に入力し始めた時に未だ syntax がロードされておらず白黒の状態の 1145 | まま入力した後に発生する気がする。 1146 | 1147 | * reject: ble/syntax/parse の呼び出しを確認してみたが別に入れ子で呼び出さ 1148 | れる等の問題が起こっている訳でもない。 1149 | 1150 | ble/highlight/layer:syntax/update-error-table の実装が関係している気がす 1151 | る。特にコメントアウトされている syntax3_table をクリアする行を入れる様に 1152 | してみると問題は発生しない。うーん。_ble_highlight_layer_syntax3_list に 1153 | 登録されているエラーを削除する事になっているが、この配列に登録されている 1154 | データが壊れるか或いは失われるかずれているか、という事なのだろうか。 1155 | 1156 | どうも _ble_highlight_layer_syntax3_table の compaction が起こっている様 1157 | な気がする。というか layer table は shift の対象だと考えると sparse になっ 1158 | ているのが問題なのでは? うーん。shift の履歴を見ていて気づいた。どうも 1159 | (DMIN,DMAX0,DMAX) の呼び出しが欠けてしまっている? なので本来挿入されるべ 1160 | き要素が挿入されずに sparse になって変な事が起こっている。では何故 1161 | (DMIN,DAMX0,DMAX) が欠けてしまうのだろうか。 1162 | 1163 | →つまり遅延して読み込まれているので、読み込まれた後の (DMIN,DMAX0,DMAX) 1164 | しか受け取れていないという事。 1165 1166 [原因] core-syntax は遅延して読み込まれる。読み込まれる迄は syntax_buff や 1167 その他の layer 固有の buffer は更新されない。そして読み込まれた時に空の配列 1168 として初期化している。 1169 1170 一方で、これらのテーブルに対して layer/update/shift が呼び出される時、配列 1171 は前回の更新時の文字列の長さと同じだけの要素を持つ dense な配列であることを 1172 想定している。ここで実際に要素の足りない配列に対して layer/update/shift が 1173 呼び出されると意図しない compaction 等が発生してエラーの設置位置がずれてし 1174 まう。 1175 1176 [修正] 初期化時に要素の数が足りていない時にはちゃんと補う必要があるという事。 1177 initialize-vars の時点でちゃんと要素を必要な数だけ入れておけば良い。 1178 1179 うーん。然し、どの長さを持っている事が期待されているのかは非自明である。 1180 1181 a initialize-vars の時点での要素数は直前の ble/highlight/layer/update の呼 1182 び出し時における _ble_edit_str の文字数である。もし現在の _ble_edit_str 1183 及び DMIN,DMAX,DMAX0 から遡って取得しようと思ったら DMIN,DMAX0,DMAX が記 1184 録されている場所を知らなければならない。遡っていくと 1185 ble/textarea#update-text-buffer で _ble_edit_dirty_draw_{beg,end,end0} を 1186 拾っている。うーん。これを取得するのは複雑だし、edit.sh からの呼び出しを 1187 仮定する事になる。モジュール外の呼び出し元の情報を参照しなければならない 1188 のでカプセル化に失敗している。 1189 1190 b 或いは別の buffer の要素数をそのまま真似するのが良い様な気がする。という 1191 か plain_buff は必ず存在する事になっているのでその要素数をそのまま真似れ 1192 ば良いのではないか。 1193 1194 実際に plain buff の長さを確認してみたらちゃんと期待通りの要素数を持ってい 1195 る。この要素数を真似て新しい配列を初期化する事にした。動いている。問題は解 1196 決した様に見える。 1197 1198 * term (mlterm), vim-airline: prompt_status_line がちゃんとレイアウトできていない [#D1999] 1199 1200 * mlterm detection 1201 1202 0;96;0 v3.1.0 (2012-03-24) https://github.com/arakiken/mlterm/commit/6ca37d7f99337194d8c893cc48285c0614762535 1203 1;96;0 v3.1.2 (2012-05-20) https://github.com/arakiken/mlterm/commit/6293d0af9cf1e78fd6c35620824b62ff6c87370b 1204 1;277;0 v3.4.2 (2014-12-27) https://github.com/arakiken/mlterm/commit/c4fb36291ec67daf73c48c5b60d1af88ad0487e6 1205 1;279;0 v3.7.2 (2016-08-06) https://github.com/arakiken/mlterm/commit/24a2a4886b70f747fba4ea7c07d6e50a6a49039d 1206 24;279;0 v3.7.2 (2016-08-11) https://github.com/arakiken/mlterm/commit/d094f0f4a31224e1b8d2fa15c6ab37bd1c4c4713 1207 1208 mlterm: どうも status_line の内容がちゃんと表示できていない。カーソルの位置 1209 計算については今の所問題は生じていない様だが。実際に出力されているシーケン 1210 スと、それを出力した時に mlterm がどの様に振る舞うかについて確認しておく必 1211 要がある気がする。 1212 1213 どうやらシーケンスを生成した時点で何故か一番右のフィールドを折り返してしまっ 1214 ている様だ。何故? 1215 1216 最後の全体の trace によって (1\E[80D\E[1B,36) という具合に生成されている。 1217 二つの問題がある。 1218 1219 x fixed: sep の幅を 1 と仮定しているので mlterm ではstatus_line に収まり切 1220 らない内容が設定されている。sep の幅もちゃんと考えて判定を行うべき。 1221 1222 x fixed: confine が指定されているのにも関わらず何故か折り返されている。これ 1223 に関しては ros, cols を確認してみた所、何故か 80x24 になっていた。 1224 status_line の場合には高さ 1 に制限していた筈。或いはその制限を解除する等 1225 しただろうか? 1226 1227 →うーん。確認してみたが prompt_rows=24 に明示的に設定されている。どの段 1228 階で設定されているか確認する事にする。 1229 1230 ble/prompt/unit:_ble_prompt_term_status/update では prompt_rows=1 を設定 1231 している。と思ったら _ble_prompt_term_status は別の物であって 1232 _ble_prompt_status が問題の関数だった。確認してみた所 prompt_cols=1 1233 prompt_cols=$cols としていてこれは明らかに prompt_rows=1 の間違いである。 1234 これを修正したら折り返しが被さってしまう問題はなくなった。 1235 1236 x reject: 初期化時 (char_width_mode 未確定時) に status_line が二重になってしまう問題 1237 1238 更にもう一つの問題は char_width_mode が response によって変化して再描画が 1239 発生した時に、以前出力した status bar が残ってしまって二重になってしまう 1240 問題。 1241 1242 a WINCH の時には全体をクリアしていたので折り返しがあっても問題がなかった。 1243 char_width_mode の変更に際しても同様に間にある内容を消去する様にしても 1244 良いのではないか。うーん。winch の時に何が画面を消去しているのかと思っ 1245 たが、これは恐らく ble/canvas/panel/invalidate height ではないか。 1246 char_width_mode=auto 完了時にも呼び出すか? 1247 1248 x 然し、これを呼び出してしまうと char_width_mode 確定時に結局配置に変更 1249 がなかったとしても必ず再描画を実行しなければならなくなる。再描画の必 1250 要が分かった時にだけ消去するという事はできない物だろうか。 1251 1252 b 或いは bottom-dock の一番上の panel を描画する時点で全消去する? と思っ 1253 たが行数が分からないので bottom-dock の別の panel を消去しない様にする 1254 ことができない。 1255 1256 c 或いは端末からの応答がある迄は描画を開始しない 1257 1258 x 折角色々の処理を遅延させてプロンプトを先に表示する事によって応答を早 1259 くしているのに、端末の応答を待つようにしてしまっては意味がない。また 1260 端末が応答しなかった場合にプロンプトが表示されない事になってしまう。 1261 短い timeout を設定するとその timeout の間だけ確実にフリーズする事に 1262 なるので避けたい。また制御も面倒である。 1263 1264 d もしくは二回完全描画を行い二回目は全消去を実行する。 1265 1266 これはちらつきが気になるし、殆どの場合には必要にならない二回の描画を毎 1267 回実行する事になるので避けたい。特定の条件を満たした時にだけ二回完全描 1268 画にするとしても、完全性を期すのであれば厳密な Unicode version 一致も必 1269 要になるので問題である。 1270 1271 とは言っても結局プロンプトは二回表示しているのでは? と思ったがそれは 1272 git 情報を表示しているから? うーん。基本の設定では、プロンプトは最初に 1273 一回だけ表示すれば十分という事になっている筈。 1274 1275 e 或いは vim-airline を char_width_mode 未確定の時には表示しない様にする? 1276 1277 然し結局応答しない端末が合った時に vim-airline がいつまで経っても表示さ 1278 れないという問題が発生する。 1279 1280 f 或いは最初の char_width_mode は安全側に倒して char_width_mode=east にし 1281 ておく? 然し最近の端末は全て west なので、east を規定値にすると毎回必ず 1282 再表示が起こってやはり不都合なのではないか。 1283 1284 ja_JP の時にだけ最初を char_width_mode=east にする? と思ったがそれでも 1285 mlterm を別の言語で使っている人もいるだろうし、完全な解決にはならない。 1286 1287 しかし再描画が起こって、プロンプトの配置が微妙に変わるだけであれば大し 1288 た問題ではないのでは? と思ったがカーソル位置が変わったり、或いは rps1 1289 の表示位置が変わったり等の事が起こるのはやはり微妙な気もする。うーん。 1290 1291 x これもやはり応答がない west な端末の場合に問題が持続してしまう。 1292 1293 最初の描画の瞬間だけ幅を変更する様にしたらどうか。そうしたとしても、 1294 やはり応答がない端末の場合に変な不整合が起こるかもしれない。次の再描 1295 画の時に再配置するとしても、char_width_mode とは独立に表示幅などを勝 1296 手に弄ると文字幅キャッシュ等で不整合が起こって変な事になる。なので 1297 char_width_mode と _ble_unicode_c2w_ambiguous を独立に一時的に変更し 1298 て処理することは非現実的である。 1299 1300 やはり mlterm の場合には最初から bleopt char_width_mode=east を設定してお 1301 く様にしてもらうしかないのだろうか。逆に言えば最初から 1302 char_width_mode=east を設定してもらうだけで済むのであればそちらの方が良い 1303 気がする。 1304 1305 これには対応しない事にする。 1306 1307 2023-03-06 うーん。~/b.txt にデバグ用のデータを出力していた。行を削除する。 1308 make_command.sh make scan でチェックしていたと思ったが確認した所 a.txt しか 1309 チェックしていなかった。危ない。[a-z].txt を全てチェックする様にした。 1310 1311 * syntax: ${arr[@]@k} に対応できていない [#D1998] 1312 1313 対応した。 1314 1315 2023-03-04 1316 1317 * 2022-10-13 nix completion で止まる問題 (reported by aiotter, Aleksana) [#D1997] 1318 https://github.com/akinomyoga/ble.sh/issues/58#issuecomment-1272222143 1319 1320 これは説明を書く。何処かにこういうののまとめを書く方が良いのではない 1321 かという気がする。 1322 1323 Sorry for the late reply. I have been busy recent days (and am stil 1324 busy actually...). This is actually one of the compatibility 1325 problems that are hard to solve. ble.sh extends the usage of the 1326 programmable completions for auto-complete 1327 1328 やはり問題を解決してから対処する事にする。 1329 1330 2022-12-03 報告を受けた筈なのに何処かに行ってしまったとおもったら #58 の下 1331 にあった。 1332 1333 2022-12-04 cevhyruz への私信での解説を何処かに移植して説明するのが良い気が 1334 する。 1335 1336 https://github.com/akinomyoga/ble.sh/issues/246#issuecomment-1294893636 1337 ここでも少し言及している。 1338 1339 2023-03-03 また issue が上がったので見てみる事にする。 1340 1341 以前の nix-bash-completion のファイルを持ってきて試してみたが動かない。補完 1342 しようとすると行が消えてしまう。調べてみると同じ現象が以下で報告されていて、 1343 しかし最早このリポジトリは管理されていなくて古いということの様に思える。 1344 1345 https://github.com/hedning/nix-bash-completions/pull/22 1346 1347 という事は最新版は何処か別の場所にあるという事になるが何処にあるのだろうか。 1348 というか普通に nix を入れたら入るという事なのだろうか。だとしても何処にある 1349 のか謎である。よく読むと ncfavier が代わりにメンテナンスするとかしないとか。 1350 1351 https://github.com/NixOS/nixpkgs/pull/207224 1352 1353 然し ncfavier の github 上のリポジトリに bash-completion っぽいのはない。別 1354 の場所で管理しているという事なのだろうか。 1355 1356 適当にファイルを漁ってみると以下の場所に nix completion が置いてある。これ 1357 を確認してみる事にする。 1358 1359 /nix/var/nix/profiles/default/share/bash-completion/completions/nix 1360 1361 * syntax: coproc 変数名が alias に一致する時、着色を変更する [#D1996] 1362 1363 うーん。実はもっと詳しく調べてエラー着色にするべきなのではないか? →多少 1364 alias の中身もチェックする事にした。alias の中身が複数の単語に展開される場 1365 合にはエラー着色になる様にした。 1366 1367 展開前の時点でキーワードに一致している場合にはどうするのか。内部での解釈と 1368 は独立に構文解析が行われる事になるので、内部でキーワードに展開されたからキー 1369 ワード着色にするなどの工夫をした所で外側の構文解析が壊れてしまう。 1370 1371 →alias が展開されてキーワードになる場合には、当初はその場で簡単な物だけ処 1372 理する様にしてみたが、結局通常のコマンド処理に fallback する様にした。元々 1373 変数名に一致しない場合にはその様に処理していたので問題ない。 1374 1375 2023-03-03 1376 1377 * menu-complete: enter_menu であっても一意確定なら補完完了する機能 [#D1995] 1378 https://github.com/akinomyoga/ble.sh/discussions/297#discussioncomment-5159146 1379 1380 実装した。menu を既に表示してしまっている時に単に menu に入る処理をしている 1381 所では、既存のメニューを選択してから即座に menu の確定処理を行う。menu を未 1382 だ表示していない時には menu の処理は一切せずにその場で挿入を実行する。menu 1383 を既に表示していて二回連続 TAB を押した時についてはまた別の処理が必要になる。 1384 1385 うーん。単純に opts を継承する事にした。調べてみると menu/enter が処理して 1386 いる opts は backward と今回追加した insert_unique だけなので別の物が指定さ 1387 れていたとしても突然問題になる様には思われない。なので、単に opts を 1388 menu/enter に渡してしまう事にする。この様にすれば個別に insert_unique を実 1389 装しなくて済む。 1390 1391 うーん。widget/menu-complete は enter_menu:insert_unique を既定にしてしまっ 1392 て良いのではないか → 変更した。 1393 1394 * vi: operator:filter で end が文字列の最後の時には追加の改行は入れない [#D1994] 1395 1396 x fixed: うーん。v 等で中途半端な場所にある時に beg は行頭に移動するけれど 1397 も end は行末に移動しない状態でフィルターが適用されて変な事になる。vim の 1398 振る舞いを見ると何れにしても行全体に適用される様である。 1399 1400 実装を確認してみると ble/keymap:vi/expand-range-for-linewise-operator を 1401 呼び出しているので、行志向に拡張するのは意図的に行っている。然し、それが 1402 ちゃんと拡張されていないということの気がする。 1403 1404 →これは思いっきりバグだ。local end と宣言してしまっていたので折角実行し 1405 た変更が関数の呼び出し元に伝わっていなかった。修正した。 1406 1407 どういう条件で改行を挿入するのかは非自明である。取り敢えず変換前の文字列に 1408 改行が含まれていれば改行を挿入する? うーん。空文字列だった時にはそうではな 1409 い気がするし、更に改行が含まれていなかったとしても続きに文字列があればやは 1410 り改行が必要な気がする。 1411 1412 1 end の次に改行以外の文字がある時は改行を入れる必要がある。 1413 1414 2 end の次に改行がある場合でも改行を入れる必要があるのでは。これは二重改行 1415 の時に起こる。然し、非空行の行末に end があった場合 (本来この様な事は起こ 1416 らない筈だが) には改行は入れたくない。 1417 1418 従って非行頭行末の時には改行は省略する? 然し本来この様な状況にはならない 1419 と思っているし、いざなったとしても改行は入れるか入れないかは微妙な気がす 1420 るので、この様な複雑な判定はせずに、この場合でも常に改行を入れるという形 1421 で良い気がする。 1422 1423 つまり end が文字列末尾にあるのでなければ常に改行を挿入するという事で良い気 1424 がする。 1425 1426 * zoxide: zi を bind -x から呼び出すと Enter が効かないらしい (reported by linwaytin) [#D1993] 1427 https://github.com/akinomyoga/ble.sh/issues/293#issuecomment-1451208995 1428 1429 何故か自分の手元では再現しないが取り敢えず stty icanon を実行すれば直る様で 1430 ある。bind -x の度に stty を二回実行するのはコストが高いのでデフォルトで実 1431 行するのは微妙だが、zi を実行した時にだけという事であればそんなに問題にはな 1432 らないだろう。という事で関連する関数を上書きする事にする。 1433 1434 * histdb: bash-3.2 で idle を使おうとして失敗している [#D1992] 1435 1436 bash-3.2 では自動的に kill する機能はなくす? 1437 1438 2023-03-02 1439 1440 * edit: ジョブ情報が出力されるとステータスバーが消える (reported by mozirilla213) [#D1991] 1441 https://github.com/akinomyoga/blesh-contrib/issues/11 1442 Ref #D1800 1443 1444 うーん。これは coproc でなくても sleep 1 & で発生する。joblist の出力部分を 1445 ちゃんと command layout で囲んで置かなければならないという事? 或いは 1446 display-shell-version 等と同じ様にして出力する必要? 1447 1448 ble/widget/print を呼び出せば良い様な気もする。 1449 1450 うーん。出力は joblist.bflush で行われていて buffer に問題の文字列が混入す 1451 るという事になっている様だ。呼び出し元を見るとble/util/joblist.bflush 1452 ble/widget/.insert-newline となっている。つまり、layout 変更の途中の様な気 1453 がするのでこの状態で command layout への切り替えなどすると変な事になる気が 1454 する。後でよく考える必要がある。 1455 1456 一方で joblist.check や ble/util/joblist では直接出力はしていない様なので 1457 joblist.bflush と joblist.flush だけ抑えて置けば大丈夫の気がする。実はこれ 1458 らは三箇所でしか呼び出されていないので対応はそんなに難しくない気がする。 1459 1460 うーん。調べてみたが joblist.bflush を呼び出す所まではちゃんとできている気 1461 がする。それよりも一旦 collapse した状態を抜けていないのが原因の気がする。 1462 実際 joblist.bflush の呼び出しをなくしても問題が発生する。 1463 1464 どうもこれは #D1800 で問題にしていたのと同じ問題の様に見える。うーん。どう 1465 も keep-info が指定されている時には enter/leave-command-layout がバランスす 1466 るという仮定の様な気がする。keep-info が指定されていない時は #D1800 を気に 1467 してコメントが書かれているが、keep-info のついている .insert-newline に関し 1468 ては #D1800 のコメントはついていない。 1469 1470 単に keep-info の時に leave-command-layout を呼び出す様にしたら解決した。 1471 1472 * [棄却] external: coproc c { sleep 1; echo; } とすると文法エラーになる [#D1990] 1473 1474 "bash --norc" だと問題はない。何故? "bash --norc" で .blerc を読み込んでも 1475 問題はない。 mshex をロードしていると blerc をロードしていなくても問題にな 1476 る。何らかの shopt が関係しているという事だろうか。 1477 1478 shopt を完全に合わせてみたがそれでも問題は再現しない。mshex について bisect 1479 するしかないのだろうか。 1480 1481 うーん。分かった。alias c が展開されている。つまり、coproc の次はコマンドで 1482 も良いし変数名でも良いので取り敢えず alias 展開が実行されてしまうという事。 1483 そして一文字エイリアスはよく使われてかつ一文字変数も良く使われるので衝突す 1484 るという事。 1485 1486 2023-03-01 1487 1488 * syntax: 5.3: 配列要素代入の右辺でブレース展開は無効 [#D1989] 1489 https://git.savannah.gnu.org/cgit/bash.git/commit/?h=devel&id=349e21043e362914551277728159f8e55350bad7 1490 1491 これの修正は簡単だった。 1492 1493 * vi_imap: M-S-o に対する fallback が ESC o になっている [#D1988] 1494 1495 これは redispatch の時に S-o が O になっていないのが原因。そもそもの問題と 1496 して S-o も ble-bind を用意しておくべきなのかそれとも常に S に解決するべき 1497 なのかという疑問がある。うーん。然しキーボード上で両者を区別する事に意味は 1498 ない様な気がするのでこれで良い気がする。 1499 1500 ? CapsLock が入っている場合にはどうするべきなのか。この場合には実際のキー入 1501 力として [Shift]+[O key] を送っている気がするが、操作としては "o" を送っ 1502 ているつもりなのではないか…。うーん。CapsLock の状態を取得するのは難しい。 1503 それも送信する様にするプロトコルもある様だが、そういうプロトコルばかりで 1504 はないので CapsLock の情報に依存せずに処理できる方法が望ましい。 1505 1506 うーん。結局 CapsLock は信用できないし CapsLock が入っているからと言って 1507 操作体系を変更するのも変な気がするので、そのまま S-o を信じて S-o は常に 1508 O に変換するということで良い気がする。 1509 1510 * 実は類似の箇所が他にもあるのではないか。検索してみると以下の様なものが見つかった。 1511 1512 $ grc 'KEYS(\[[^][]+\])?&~_ble_decode_Meta' 1513 ./keymap/vi.sh:120: ble/decode/widget/redispatch-by-keys "$esc" "$((KEYS[0]&~_ble_decode_Meta))" "${KEYS[@]:1}" 1514 ./keymap/vi.sh:141: ble/decode/widget/redispatch-by-keys "$esc" "$((KEYS[0]&~_ble_decode_Meta))" "${KEYS[@]:1}" 1515 $ grc '&=?~_ble_decode_Meta' 1516 (同じ物しか当たらなかったので省略) 1517 1518 * reject: 既に似たような処理を何処かで実装している様な気がする。例えばレジ 1519 スターの文字を取得する箇所など。確認する。_ble_decode_Shft で検索すれば見 1520 つかる筈…と思ったが見つからない。 k2c という名前の関数だった気がする。→ 1521 ble/keymap:vi/k2c だった。然しこの関数は C-? を byte に戻す役割であって 1522 S-o を O にするなどの処理を実装した物ではなかった。 1523 1524 なので今回はまた別に実装する必要がある。と思ったが既に上記の検索で当たっ 1525 ていた 141 行目が decompose-meta という関数で汎用に用意した物だった。120 1526 だけ特別に実装したものだった。なので基本的にこの二箇所を修正するだけで良 1527 い。 1528 1529 修正した。と思ったが動作していない。 1530 1531 % うーん。実際に流れてきているキーを確認してみたら既に M-S-o は 1532 % M-O に翻訳されていた。なのでわざわざこの場所で再構成する必要はな 1533 % いのであった。という事はちゃんと処理されていない原因は別の場所に 1534 % あるという事になる。 1535 1536 →よく見たら M-O になっていて欲しいのに M-S-o でも M-O でもなく単 1537 に M-o になっていた。受信しているのは 27;2;111 でありこれは S-o で 1538 あるのにも関わらずちゃんと復元できないという事。 1539 1540 ===== keys ===== 1541 M-o ESC o C-u b l e auto_complete_enter 1542 / d e b u g C-e C-_ e auto_complete_ente 1543 r n d C-m C-m 1544 1545 うーん。最初に受信した時点で S が消えている。どの時点で消滅したの 1546 か確認する必要がある。 1547 1548 分かった。これは意図的に通常文字に対して S だけが付加されている時にそれを削 1549 除している。何故なら xterm & vte で <Meta-Shift-o> というキー入力に対して 1550 M-S-O というシーケンスを送ってくる為。M-S-o というシーケンスが来た場合には 1551 CapsLock が有効になった状態で Meta+Shift+O → M-S-o となったという解釈なの 1552 である。一方で contra は CapsLock 等関係なく実際のキーの組み合わせに一対一 1553 対応する様に処理している。 1554 1555 * 今回はどの様に修正するか。取り敢えず contra での取り扱いについてはそれ専 1556 用に実装する事にした。一方で他の端末での振る舞いについても考える。konsole 1557 はそもそも modifyOtherKeys に対応していない。単に ESC O を最初から送信し 1558 て来ている。 1559 1560 xterm は CSI 27;4;79 ~ で M も S も同時に指定した状態で来ている。これだと 1561 M-S-o になってしまう。然し本当は M-O になって欲しい。どの様に処理するべき 1562 だろうか。 1563 1564 受信時点で調整しようかと思ったがやはり両方許容しておいて良い様な気がして 1565 きた。もし ESC 大文字 で送られてきたら M-O 等の形式にするのは自然だが、 1566 CSI 27;4;79 ~ 等の形式で来た時にどの様に取り扱うかは微妙。 1567 1568 実際に確認してみると既存の binding は M-S-y と M-Y の両方の形式を同時に設 1569 定する様になっている。取り敢えずは現状のままにしておく事にする。 1570 1571 * konsole の端末判定 1572 1573 https://qiita.com/kefir_/items/0bda5e55f43392420d66 '0;115;0' 1574 https://github.com/KDE/konsole/blob/0bd20ac6542de5ea16d06f5af255389a3afa8f67/src/Vt102Emulation.cpp#L2051 '1;115;0' 1575 1576 以下 (2022-02-24) によると v22.03.80 (2022-03-18) より 1 に変わった様だ。 1577 https://github.com/KDE/konsole/commit/0cc64dcf7b90075bd17e46653df3069208d6a590 1578 以下 (2001-09-16) によると v3.0.0 から 0;115;0 だった様だ。 1579 https://github.com/KDE/konsole/commit/2d93fed82aa27e89c9d7301d09d2e24e4fa4416d 1580 1581 2023-03-02 初期化時に _ble_term_TERM が未初期化の状態で modify-key が呼び 1582 出されると負の配列添字になってエラーになる。 1583 1584 * vim mode ! で複数行の結果を返すと描画位置がずれて変な事になる [#D1987] 1585 1586 どうやら行数が増えると駄目な様だ。単に複数行を replace-range で挿入する 1587 widget を作成しても問題は再現しない。終了時の _ble_canvas_y の問題だろうか。 1588 うーん。.replace-range を実行している時の _ble_canvas_y の位置は正しい。ちゃ 1589 んと復帰した位置になっている。またこの時点で buffer.flush を実行しても問題 1590 の振る舞いに変化はなかったので buffering の問題ではない気がする。 1591 1592 * todo: 行末の場合には末尾の改行は省略する。然しこの処置は現在のバ 1593 グを隠してしまうので現在のバグを修正してからにする。 1594 1595 どうやら determine-scroll をした瞬間にずれている? 中身を見ると panel_height 1596 を拡張して更にその分だけカーソル位置も移動したことになっているが、実際には 1597 移動していないということが問題になっている気がする。 1598 1599 何か分かった気がする。 DRAW_BUFF の中身をスクロールの直後で flush したら問 1600 題が発生しなくなった。これが意味する所は、後ろの方の出力で DRAW_BUFF ではな 1601 くて直接 util/buffer に出力している箇所があるという事。特に各行の文字数を調 1602 整する部分が怪しい。 1603 1604 * global: コード中の /dev/tty は予め持っておいた fd に置き換えるべきなのでは [#D1986] 1605 修正した。 1606 1607 * util: readonly を上書きする? (requested by mozirilla213) [#D1985] 1608 https://github.com/akinomyoga/ble.sh/issues/289 1609 1610 其処まで積極的にユーザー環境を上書きして良いのか不明である。 1611 1612 - alias doesn't affect existing functions. 1613 1614 - command line can be easily detected, but this is still incomplete 1615 detection because even if the user does not directly write declare -r, 1616 the functions called by the user could contain declare -gr, etc. 1617 1618 The scope that the readonly is called and the scope of the variable 1619 specified to readonly are unrelated to each other. One needs to test each 1620 variable name whether it is in the global scope or not. 1621 1622 * propagating tempenv にも気をつけなければならない。 1623 1624 $ f1() { ble/variable#is-global fdsafdsa; } 1625 $ fdsafdsa=a f1 1626 1627 このテストだと global ではないと判定されてそれは is-global の判定としては 1628 期待する動作である。然しこれに対して export/readonly を実行すると外側に 1629 propagate してしまう。global に propagate しないという事までちゃんと判定 1630 する方法はあるのだろうか。そもそも tempenv をそうと判定する方法があるのか 1631 という事も疑問である。 1632 1633 まあこの場合は仕方がないと思って諦めるべきだろうか。 1634 1635 これの判定は完全ではない。 1636 1637 * done: global readonly に対しても whitelist は作っても良いのかもしれない。 1638 全て [A-Z0-9_] であり 2 文字以上で Bash の特殊変数に一致していなくて 1639 ble.sh が使っていない変数名? 1640 1641 ble.sh 内部で使っている大文字変数も実は改名するべきの気もする。特に vi.sh 1642 の中で使っている変数が気になる…がこれは禁止リストに入れてしまっても良い 1643 気がする。 1644 1645 小文字でも _ble で始まらない _[a-zA-Z]* の様な変数名も許容して良いのでは 1646 ないか。然し、ble.sh の内部で使っている変数もあるのでそれらは ble.sh の側 1647 で改名する等して避ける事にする。 1648 1649 * done: is-global の実装で readonly が使われている。 1650 1651 * done: adjust builtins: readonly はユーザーによる上書きを許容する。 1652 1653 * done: エラーメッセージは一回しか実行しない→もう何回か表示して良い気がす 1654 る。10回迄表示する事にした。 1655 1656 * ユーザーが既に readonly を上書きしている場合にはどうするのか。 1657 function#push,pop で処理する事にすれば良いだろうか。と思ったがその様にす 1658 るのであれば他の builtin も同様にする必要があるのではないかという事になっ 1659 てくる。もしこれについて考えるのであれば全ての builtin について同時に適用 1660 するべき。 1661 1662 2023-03-02 文法エラーが発生している。bash-4.0 以降では "!" 単体はエラーにな 1663 らないのだろうか。何れにしても修正した。 1664 1665 * exec: BLE_PIPESTATUS 公開する (motivated by mozirilla213) [#D1984] 1666 https://github.com/akinomyoga/ble.sh/issues/290 1667 1668 * done: wiki misc 1669 1670 * ok: 然し、実際に BLE_PIPESTATUS をどの様に PIPESTATUS と使い分けるのかと 1671 いうとよく分からない。現在のコマンドが ble.sh 内での一番最初のコマンドか 1672 どうかの情報がないので両方にアクセスできる時にどちらを選ぶべきか分からな 1673 い。 1674 1675 一応 exec が終わったら BLE_PIPESTATUS を削除すれば良い気もするが、でもそ 1676 もそも exec が終わったら ble.sh の内部なので誰も BLE_PIPESTATUS を参照し 1677 ないので削除してもしなくても関係ない気がする。 1678 1679 然し気にし出したら限がない気がするので考えない事にする。 1680 1681 * ok: 唯一削除したほうが良いかもしれないのは ble-detach する時だが、そうだ 1682 としても ble-detach する時のステータスを復元する必要はないのか。というか、 1683 ble-detach した時の $_ $? などはちゃんと保持されているのか (そもそも保持 1684 する必要があるのかも怪しいが。何故なら ble-detach コマンドを結局呼び出す 1685 のでその $? や $_ が適用されるのでは。より複雑な構成で非自明な場合を考え 1686 る事も可能だが其処まで考えても意味がない気がする)。同様に PIPESTATUS に関 1687 しても敢えて ble-detach の PIPESTATUS を保持する事が有用である様には思え 1688 ない。なので考えなくて良い事にする。 1689 1690 * done: 序でなので POSTEXEC 及び ERREXEC にも BASH_COMMAND を引数に指定する 1691 様に変更する事にした。 1692 1693 * done: README Limitations 1694 1695 * decode: compat zoxide bind -x (reported by linwaytin) [#D1983] 1696 https://github.com/akinomyoga/ble.sh/issues/293 1697 1698 leave-for-widget を毎回呼ぶ事にしてしまっても良いのでは。 1699 1700 ? ここで fzf-key-bindings の advice を残すかどうかが問題になる。もしこれら 1701 の関数を completion にも流用しようとしている人がいてこれらを直接呼び出し 1702 たとすると問題になる。しかし、fzf-completion を弄って (もしくは自分で新し 1703 く設定を作って) いる人がいたら何れにしても fzf-completion はちゃんと動か 1704 ない。なので、現状で中途半端に fzf-key-bindings の中の関数だけ patch して 1705 も余り意味は無いのではないか。 1706 1707 やはり単純に削除してしまって良い気がする。 1708 1709 * ok: もう一つの懸念事項は bind -x の全てに対して毎回呼び出すと重くなるので 1710 はないかという事。うーん。ble.sh の上で更に ble.sh 的な事をしようという様 1711 な事がない限りは多少エスケープシーケンスが端末に沢山送られても別に大した 1712 処理量にはならない気がする。 1713 1714 但し、visible-bell/erase に関してはファイル等をチェックする等するはずなの 1715 で多少のコストはあるかもしれない。然し、ble/util/assign 等もっと沢山の非 1716 自明な事をしているのだから bind -x の時にファイルを確認するぐらいであれば 1717 無視できる筈である。 1718 1719 * 2023-02-21 histdb: 終了時に sqlite3 のエラーが発生して失敗する事がある [#D1982] 1720 1721 Runtime error near line 779: database is locked (5) 1722 1723 調べてみるとどうやら timeout を指定していたとしても BEGIN TRANSACTION は即 1724 座に失敗するらしい。IMMEDIATE を指定する必要がある。 1725 1726 https://blog.ver001.com/sqlite-databaseislocked/ 1727 1728 これは単に IMMEDIATE を指定したがそれ以降エラーは出ていない。これ 1729 で直っていると良いが、エラーがそもそも出る確率が少ない様だから確認 1730 が難しい。次にまた問題が出た時に考える。 1731 1732 2023-03-01 やはりまたエラーが出た。改めて確認してみるとどうやら exec でバッ 1733 クグラウンドで起動した時に timeout が指定できていない。起動時にちゃん 1734 と.timeout を指定する事にした。何度か起動と収量を繰り返したが新しいものの方 1735 では問題は生じない様に見える。と思ったが古い方でも起こる確率はやはり小さい 1736 様なので何とも言えない。 1737 1738 もう一つ気づいた事は histdb の remarks に ANSI 色シーケンスが混入しているこ 1739 と→これは単に .blerc で明示的に colored を指定していたのが悪い。修正した。 1740 更にこれを元にして作成した histdb の既定の remarks にも同様の間違いがあった。 1741 これも修正した。 1742 1743 % 2023-03-03 うーん。やっぱり駄目。何らかの拍子に失敗する。timeout をもっと 1744 % 長く取るか或いは諦めてエラーを強制的に suppress するか。どうも終了する時 1745 % に発生する様なのでエラーメッセージに関してはそれ程気にしなくても良いのか 1746 % もしれない。一方で、終了する瞬間にメッセージが表示されることを思うと実は 1747 % .timeout が短い事による問題ではなくて、やはり .timeout で待たない様な設定 1748 % になっているという事だろうか。と思って気づいたが contrib の dev ブランチ 1749 % に前回の修正があって、それが有効になっていなかった。 1750 1751 取り敢えず平和に動いている様な気がするので #D1992 と一緒に修正を適用する事 1752 にする。 1753 1754 * 2023-02-21 どうも bash-5.2 で WINCH が効かなくなっている [#D1981] 1755 1756 最初は効いているが、同時に複数の WINCH を受け取る等の事が一旦起こるとそれ以 1757 降は WINCH が効かなくなってしまう。bash-5.1 では問題は起こらない。より簡単 1758 な設定で再現しようとしたが再現しない。bash 自体の内部で何が起こっているのか 1759 確認するべきの気がする。 1760 1761 * 更に devel で試してみると無限ループになってしまう。何故? 自前で適当に 1762 setup しても無限ループにはならない。この devel の無限ループでは別に 1763 ble/builtin/trap/.handler が沢山呼び出されている訳でもない様だ。bash の側 1764 で無限ループになっている。 1765 1766 devel 407d9af (20221119) は大丈夫。3687888 (20230220) も大丈夫。という事 1767 は DPF で勝手に書き換えているのが問題という事? 或いは debug version が駄 1768 目という事なのだろうか。どうやら ./configure --with-bash-malloc=no でコン 1769 パイルすると駄目? と思ったが ./configure でも駄目の様だ。どうも maint の 1770 時にだけ発生する問題の様である。うーん。これの優先度は低い。 1771 1772 * うーん。一応 WINCH は受信はできている様だ。然し COLUMNS LINES が更新され 1773 ていないという状態。subshell を呼び出したとしても更新されない。但し内部で 1774 改めて builtin trap 等を実行して WINCH を呼び出すと WINCH 自体が動かなく 1775 なる。 1776 1777 これは結局 histdb の timeout の処理の為に動かしている msleep が良くない様だ。 1778 つまり、ble/util/msleep (中身は read -t) が待っている間に WINCH が来るとそ 1779 の WINCH は消えてなくなるという事。実は 5.1 では read -t の途中で WINCH が 1780 来ても read -t が終わった後にちゃんと WINCH が発火してくれる。これは 1781 sigmask 等を弄ったら動く様にならないだろうか。 1782 1783 改めて bash-5.2 --norc で起動して read -t 5 をしてみたら実はその場 (read -t 1784 の timeout を待たずに) で発火する。何れにしても 5.1 とは振る舞いが微妙に違 1785 うが、これは ble.sh の時に全く発火しないのとは振る舞いが違う。或いは、read 1786 -t の読み取り元の fd の種類によって振る舞いが違うのだろうか。 1787 1788 * ble.sh の中にいると WINCH が不活性になってしまう問題。起動した瞬間に 1789 builtin trap WINCH を実行している場合には問題は生じない。つまり、WINCH の 1790 処理中に更に新しい WINCH が来るなどの事があると不活性になってしまうという 1791 事だろうか。 1792 1793 またこれは bash のバグなのかという事もある。bash のバグとしての修正と、そ 1794 れから既に出ている bash-5.2 に対する workaround の両方を実装する必要があ 1795 る。取り敢えず bash 側で何が起こっているのかについては確認する必要がある。 1796 1797 * WINCH が不活性の時は bash の中で何が起こっているのか。 1798 1799 % 先ず _rl_signal_handler は通常の動作している状態であっても ble.sh の中で 1800 % は呼び出されていない。つまり、自分が設定した WINCH だけが有効になっている 1801 % 状態で、readline signal handler がない状態だろう。これは不活性になってい 1802 % る時でもちゃんと WINCH が活性している時でも問題になっている。 1803 % 1804 % trap でどう設定されるのかを見て呼び出し経路を探る事にする。set_signal を 1805 % 呼び出している。中では trap_handler という関数をシステムに登録している。 1806 % 1807 % 実際に trap_handler が呼び出されているかどうかを確認してみると 1808 % trap_handler までは不活性の状態でも呼び出されている様だ。trap_handler は 1809 % set_trap_state を呼び出して抜ける。更に pending_traps[SIGWINCH]++ が実行 1810 % される。この配列をチェックして実際の trap string を実行している箇所を探せ 1811 % ば良い。 1812 % 1813 % →どうやら set_trap_state までは呼び出されるけれどもその後 1814 % run_pending_traps が実行されない状態になっているということの気がする。 1815 % 1816 % どうも running_trap が有効になったままになってしまい無限ループ状態になっ 1817 % ている。つまり running_trap の復元に失敗している。running_trap はどの様に 1818 % 復元する事になっているのだったか。 1819 % 1820 % どうも parse_and_execute で実行している最中に実行が途切れて戻ってこないの 1821 % が問題の様である。然し何故だろうか。実行しているコマンドの内容による? 特 1822 % 定のコマンドの後に変な事が起こるのか、それとも最後まで実行した挙げ句に変 1823 % な事になるのか。 1824 % 1825 % 調べてみると blehook internal_WINCH の実行途中に制御が消滅する様である。 1826 % どんどん調べていくと結局やはり ret=$(msleep 50; bash -c ... ) として端末 1827 % サイズを取得しようとしている所で失敗している。これを assign に置き換えて 1828 % も失敗する。assign は mapfile で失敗する。つまり、read -t の最中に起こっ 1829 % たシグナルの中で何らかの読み取り動作を実行しようとすると失敗するという事。 1830 % 実際に sigmask で sigwinch が即時発火しない様に修正したら問題は生じなくな 1831 % る。 1832 1833 まとめると、read -t (msleep) で待っている間に SIGWINCH を受信するとその場 1834 で WINCH handler が呼び出され、更にその中で a=$() や mapfile 等の読み取り 1835 を使おうとするとエラーが発生して、run_pending_trap 自体の実行が中途半端に 1836 キャンセルされてしまう。これにより run_pending_trap が設定している 1837 runnning_trap がクリアされずに残ってしまい、入れ子の trap 実行と判定され 1838 て run_pending_trap が全く実行されなくなってしまう。 1839 1840 read -t の実行時に sigmask を指定して SIGWINCH をブロックしておけば変な事 1841 は起こらない。なので 5.3 以降では気にしなくて良い。 1842 1843 以下 ble/application/onwinch の COLUMNS, LINES 取得部分で行った実験コード 1844 1845 | # bash-5.2 では read -t の最中の WINCH がその場で発火して、(1) 内部で 1846 | # ble/util/msleep を実行しようとすると外側の timeout 設定が削除されてロッ 1847 | # クする (2) WINCH が受信できない変な状態になる。 1848 | 1849 | # local ret 1850 | # ble/util/msleep 50 1851 | # ble/util/assign-words ret 'ble/bin/stty size' 1852 | # LINES=${ret[0]} 1853 | # COLUMNS=${ret[1]} 1854 | 1855 | # (ble/util/msleep 50) 1856 | # local cmd='(:); echo "COLUMNS=$COLUMNS LINES=$LINES"' ret 1857 | # ble/util/assign ret '"$BASH" -O checkwinsize -c "$cmd"' 1858 | # builtin eval -- "$ret" 1859 | 1860 | echo "$FUNCNAME @3" >/dev/tty 1861 | # 5.2 コマンド置換 $() を使うと停止する。 1862 | #builtin eval -- "$(sleep 0.05; "$BASH" -O checkwinsize -c '(:); echo "COLUMNS=$COLUMNS LINES=$LINES"' 2>/dev/null)" 1863 | #local ret=$(ble/util/msleep 50; "$BASH" -O checkwinsize -c '(:); echo "COLUMNS=$COLUMNS LINES=$LINES"' 2>/dev/null) 1864 | #local ret=$(sleep 0.05; "$BASH" -O checkwinsize -c '(:); echo "COLUMNS=$COLUMNS LINES=$LINES"' 2>/dev/null) 1865 | #local ret=$(echo echo yes) 1866 | #(echo yes) 1867 | (ble/util/msleep 50) 1868 | echo "$FUNCNAME @3.1" >/dev/tty 1869 | (echo >/dev/null; bash -c ':') 1870 | echo "$FUNCNAME @3.2" >/dev/tty 1871 | (bash -c ':') 1872 | echo "$FUNCNAME @3.3" >/dev/tty 1873 | local _ble_local_tmpfile; 1874 | echo "$FUNCNAME @3.31" >/dev/tty 1875 | ble/util/assign/.mktmp; 1876 | echo "$FUNCNAME @3.32" >/dev/tty 1877 | builtin eval -- "(echo echo yes)" >| "$_ble_local_tmpfile"; 1878 | echo "$FUNCNAME @3.33" >/dev/tty 1879 | local _ble_local_ret=$? _ble_local_arr=; 1880 | echo "$FUNCNAME @3.34" >/dev/tty 1881 | mapfile -t _ble_local_arr < "$_ble_local_tmpfile"; 1882 | echo "$FUNCNAME @3.35" >/dev/tty 1883 | ble/util/assign/.rmtmp; 1884 | echo "$FUNCNAME @3.36" >/dev/tty 1885 | #ble/util/assign ret '(echo echo yes)' 1886 | echo "$FUNCNAME @3.4" >/dev/tty 1887 | local script='(:); echo "COLUMNS=$COLUMNS LINES=$LINES"' 1888 | ble/util/assign ret '"$BASH" -O checkwinsize -c "$script" 2>/dev/null' 1889 | #ble/util/assign ret '(ble/util/msleep 50; "$BASH" -O checkwinsize -c "$script" 2>/dev/null)' 1890 | #builtin eval -- "$ret" 1891 | echo "$FUNCNAME @4 ($ret)" >/dev/tty 1892 1893 5.2 における対策としては ble/util/assign を全く使わないという処置は大変なの 1894 で、(read -t 実行中) または ble/decode/.hook 実行中は SIGWINCH をその場で処 1895 理するのはやめて後回しにする? 然し、これは SIGWINCH に限った問題ではない気 1896 がするので、trap/.handler 全般に read -t を実行中の場合にはそれが終わるまで 1897 trap を pending するという機能が必要の気がする。 1898 1899 ? bash: 然しそもそもの疑問は何故 SIGWINCH が即時発火するのかという事。 1900 run_pending_trap が read -t の最中に呼び出されるという事があるのだろうか? 1901 trap_handler は単にシグナルを受信して pending_traps 配列に記録するだけの 1902 筈なので、何処か別の場所から run_pending_trap を呼び出す必要がある。そう 1903 しないとその場で発火はしないのではないか。 1904 1905 * 再現スクリプト? 少し試してみたが全然再現しない。そもそも別の修正で発生し 1906 なくなるからこれについて簡単なスクリプトで再現する必要は実はない。 1907 1908 * done: 実は builtin read は全て置き換える必要があるのではないか? 序に 1909 _ble_bash_tmout_wa の配列も関数の側で指定する事にする。 1910 1911 builtin read -t 0 や builtin read --help 等は一瞬で終わると思われるし、ま 1912 た内部で実際の読み取りを試行する訳でもなさそうなので入れ子にしても問題は 1913 ないと期待してそのままにする。また detach 状態で呼び出す builtin read に 1914 関してもそのままで良い。 1915 1916 と思ったが動かない。と思ったら分かった。bash version 判定に使っている 1917 _ble_bash が定義されるよりも前の段階で ble/bash/read を _ble_bash に基づ 1918 いて切り替えようとしていた。実際に ble/bash/read が使われるのはもっと後な 1919 ので、もっと後ろに移動する事にした。直った。 1920 1921 2023-02-27 1922 1923 * idle: prompt-defer による自動更新が発生していない気がする [#D1980] 1924 1925 以前は background で処理が完了し次第プロンプトが更新される様にしてその様に 1926 実際に動いていた気がする。しかし現在はキー入力が来るまで更新されない様だ。 1927 1928 →実は idle sleep の最中には表示更新が発生しないという可能性? 或る一定以上 1929 の時間 sleep するのであれば更新するべきである。 1930 1931 * reject: sleep の interval を決定する際に使っている時間が idle.do を開始し 1932 てからの時間になっているがそれで良いのだろうか。最後の task からの時間の 1933 方が良いのではないか。 1934 1935 と思ったが、screen saver 的な使い方や定期的に時刻を更新する使い方を考える 1936 と、task が走る度にリセットされると本来の意図と異なる事になる。なので、や 1937 はり idle.do の開始時刻からの時間を使って決定するという事で良い。 1938 1939 * 取り敢えず待機時間の最初に DO_EVENTS を実行して、それ経由で 1940 ble/application/render を呼び出す様にして見ようと思ったが、これだと毎秒プ 1941 ロンプトの再描画を試行してしまって重いのではないか? 1942 1943 以前に時計を表示する実験をした時にはどのようにしていたか。.blerc にある時 1944 刻表示を確認してみたら時刻を info に表示しているので info だけの更新をそ 1945 の場で呼び出していた。そもそもこれは実際に更新が起こる時に呼び出しを行っ 1946 ているので、再描画を呼び出すのは当たり前である。一方で今回の場合には恐ら 1947 く更新がないのに全体再描画を試行する事になっていて問題である。 1948 1949 DO_EVENTS の中で render を呼び出す条件を指定するべきなのではないか。プロ 1950 ンプト更新の可能性がある場合にそれを伝える仕組みが必要? 現在は一応その枠 1951 組として prompt hash を使っているが、それでも複数のプロンプトを管理してい 1952 ると全てのプロンプト hash を eval しなければならず、それはコスト的に高い 1953 様な気がする。 1954 1955 ? また、DO_EVENTS 経由で描画を実行するのも変な気がする。IS_IDLE と同じ箇所 1956 で上書きするのであれば良いかと思っていがが確認してみたところ IS_IDLE は 1957 decode.sh で上書きしている。ble/application/render を入れるとしたら寧ろ 1958 canvas.sh か edit.sh の様な気がするので、別の箇所で定義しなければならない。 1959 それは避けたいので、ここはそれ専用の hook を用意する方が自然なのではない 1960 か。 1961 1962 * reject: ble/textarea#render-defer.idle という枠組みが edit.sh で既に実装 1963 されている事に気づいた。つまり元から遅延して再描画する仕組みが整っていた? 1964 と思ったがこれはどうやらユーザー入力に対して反応しているのに過ぎない様だ。 1965 更に使っている箇所を確認するとこれは prompt-defer ではなくて単語着色に時 1966 間がかかっている時に先にユーザー入力を処理する、という時に使っている。 1967 wait-for-user-input で中断するかどうかを確認しているのはこれが理由という 1968 事だろう。なのでこれは今回のものとは関係ないし、今回使えるものでもない気 1969 がする。 1970 1971 プロンプト更新の必要性がある可能性があるという事を示す枠組みを入れる? 現在 1972 の invalidate 関係の仕組みがどうなっているのかについて確認する必要がある。 1973 1974 a 先ず以下の panel::invalidate によって 設定される変数に関しては、そのパネ 1975 ル全体について実際に再描画のシーケンスを出力する必要がある事を示している。 1976 つまり、「内容が更新されている可能性がある&もしチェックして必要があれば変 1977 わった部分だけ更新する」というものに使われるものではない。 1978 1979 _ble_prompt_status_dirty=1 1980 _ble_edit_info_invalidated=1 1981 _ble_textarea_invalidated=1 1982 1983 b 次に _ble_prompt_update_dirty は単に現在既にプロンプトが表示されているか 1984 どうかの判定に使っている様な気がする。 1985 1986 % と思ったが処理の流れが何か変な気がする。dirty だったら dirty=dirty という 1987 % 値を設定する。その次の呼び出しで dirty だったら dirty=done に設定し直して 1988 % 改めて再描画するという構造になっている。これは何だかおかしい気がする。必 1989 % ず2回呼び出されるという事? 1990 % 1991 % 実際にこの部分を追加した commit は e199beee であり #D1750 である。この議 1992 % 論では wezterm integration が勝手に PROMPT_COMMAND から何か文字列を出力す 1993 % るという問題に対する workaround を追加している。どうも textarea 以外の枠 1994 % 組みから ble/prompt/update が呼び出された時に、その時点で dirty という事 1995 % になって、それをその後で処理したい時に done を指定している気がする。 1996 % 1997 % うーん。実はプロンプト毎にも _ble_prompt_ps1_dirty 等の様なものを管理して 1998 % いるのでプロンプト自体が毎回重複して出力されるという訳では無い様だ。然し、 1999 % そうだとしても ble/prompt/update が必ず2回 dirty を返すという事になってし 2000 % まって、だとしたらそれはおかしいのではないか? 2001 % 2002 % と思って実際に試してみたが一回しか prompt dirty になっていない。何故だろ 2003 % うか。分かった。そもそもプロンプト内容に変更がなければ dirty にならないの 2004 % である。なので確かめる時には cd の直後の振る舞いを調べるべきである。 2005 % 2006 % うーん。実際に cd 直後のプロンプトの初回更新時に見てみると既に最初の呼び 2007 % 出しの時点でちゃんと _ble_prompt_update_dirty=done になっている。何故? 2008 2009 分かった。現在の実装では ble/application/render の時点で既に 2010 ble/prompt/update を呼び出す事になっているのである。なので、 2011 textarea#render からの ble/prompt/update の呼び出しは単に先に呼び出した時 2012 の計算結果を参照しているのに過ぎない。:check-dirty: というのは実際に 2013 prompt update 操作を試行せずに結果だけ読み取るという取り扱いなのであって、 2014 同時に実際にその結果を使って描画を行うから dity state をクリアするという 2015 役割があるという事なのである。 2016 2017 そしてそもそも :check-dirty: なしでの呼び出しは ble/application/render か 2018 ら必ず毎回行われるので、:check-dirty: 以降のコードも 2019 ble/application/render を呼び出す場合には毎回実行される。なので、 2020 _ble_prompt_update_dirty の値は実際には ble/prompt/update 処理の省略に使 2021 われている訳では無いという事なのである。 2022 2023 c ble/prompt/clear ... これが最も怪しい。と思ったが、この関数を呼び出すと結 2024 局内部で textarea#invalidate を呼び出しているので全体の強制再描画を引き起 2025 こしてしまう。これはではない気がする。 2026 2027 或いは新しい関数を追加してプロンプト情報の更新だけ試みる? hash だけクリア 2028 すれば良いのでは? と思ったが、今は ble/application/render 自体の呼び出し 2029 を省略できないかという事を考えているのであって、hash をクリアして更に 2030 ble/application/render を呼び出すというのでは半分だけである。 2031 2032 というか b の項目は実は余り関係なかったという事が判明した今改めて 2033 _ble_prompt_hash の取り扱いを見てみると、別に _ble_prompt_hash を更新して 2034 いようが更新していまいが ble/prompt/update の各プロンプトの hash 値確認は 2035 全部行っているので、 _ble_prompt_hash をクリアしようがしまいが 2036 ble/application/render を呼び出す限りは同じ事の気がする。 2037 2038 今欲しい物は何かについて改めて考える。idle.do の中で何か更新が必要になって 2039 いないか確認し、もし必要になっていたら強制的に再描画を実施するという事を考 2040 えている。 2041 2042 d 或いは application/render を実際に毎回呼び出してしまっても良いのではない 2043 か? タスクが走る度に実行するとは言っても、実際に本当にタスクを走らせてい 2044 るのであれば、呼び出してしまっても問題がない気がする。 2045 2046 →これで実装してみたら実際に思うように即時に反映される様になったが、今度 2047 は逆に ble/application/render が各キー入力の後に重複して呼び出されるよう 2048 になった。うーん。そもそも ble/application/render を先に呼び出している筈 2049 なので、改めて呼び出す必要はない筈なのである。 2050 2051 今気づいたのだが、実はそもそも auto-complete すら動いていなかった。sleep し 2052 ている時には定期的に抜けて処理を実行する必要があるのであった。 2053 2054 do_events で ble/application/render を呼び出す様にしたがそれでも重複して 2055 ble/application/render が呼び出されている様だ。更に、重複して呼び出されてい 2056 るのにも関わらずプロンプトが期待通りに更新されていない。二つの問題があるの 2057 で分けて考える。 2058 2059 * idle do_events がキー入力毎に複数回呼び出されるのは何故か。 2060 2061 % 背景処理がそんなに実行されるのだろうか。どういう処理が実行されているの 2062 % か出力して観察してみる事にする。 2063 % 2064 % →idle.do の中から呼び出しているのは一回である。これは期待通りである。一 2065 % 方で、bind/.tail からの呼び出しが二回ある。これは期待していない。 2066 % 2067 % 一方で histdb をロードしていない時には各キーストロークに対して2回実行して 2068 % いる。これは期待通りである。idle を実行する前と idle を実行した後。 2069 % 2070 % うーん。これは auto-complete を無効にしても同様である。なので、 2071 % auto-complete を抜ける時に内部的に生成しているキーが原因ではない。という 2072 % かそもそも内部的に生成するキーに関しては bind/.tail は呼び出されない気が 2073 % する。 2074 2075 分かった。これは (1) ユーザー入力があって idle.do から抜ける時 (2) ユーザー 2076 入力の処理の後に抜ける時 (3) 更に auto-complete 等を処理した後に sleep を 2077 開始した時 の三回処理が実行されているという事である。 2078 2079 実際には単に sleep しているだけで最終的に何も実行する前にユーザー入力があっ 2080 た時には抜ける時の render は必要ない。do_events に対する処理は実は 2081 idle.do の内部で呼び出すべきなのかもしれない。そもそも idle.do が中で実際 2082 に処理が行われたかどうかに応じて修了スターテスを決めるというのも変な気が 2083 する。と思ったが「最後にタスクを処理してから do_events を実行したかどうか」 2084 を終了ステータスにするのはもっと変だ。 2085 2086 うーん。do_events は after_task, onaftertask, on_after_task 等に変更する。 2087 blehook idle_on_after_task, blehook idle_after_task うーん。 2088 idle_after_task という名前にする事にする。 2089 2090 実装した。idle 後の再描画も idle_after_task 経由で実行する事にした。取り 2091 敢えず期待通りに動いている。 2092 2093 * プロンプトが prompt-defer で更新されないと思っていたが、上の問題を解決し 2094 たら何故かこちらの問題も発生しなくなっていた。関係していたのだろうか。或 2095 いは、表示されてはいたけれどもデバグ用の情報出力によって紛れて更新されて 2096 いないと勘違いしていた可能性もある。 2097 2098 何度かやってみたが問題は全く発生しなくなっていた。前はほぼ確実に問題が生 2099 じていたのを考えると実際に解決したのだと思って良い気がする。 2100 2101 * menu (linewise): 行番号を表示すると表示レイアウトが壊れる (reported by bkerin) [#D1979] 2102 https://github.com/akinomyoga/ble.sh/discussions/284 2103 https://github.com/akinomyoga/ble.sh/issues/286 2104 2105 これは簡単なミスだった。単に x を更新した後に x を参照していた。すぐ直った。 2106 2107 * completion: fzf-completion がまた動かなくなっている (reported by christianknauer) [#D1978] 2108 https://github.com/akinomyoga/ble.sh/issues/285 2109 2110 コードを調べてみると ble/syntax-raw を指定していても noquote を指定していな 2111 いとちゃんと quote しないという分岐に入らない様だ。一方で、contrib で 2112 2022-11-12 に noquote を外している。議論としては #D1889 である。 2113 2114 https://github.com/akinomyoga/blesh-contrib/commit/e102241466dfda8cf3e7efb6891e223102e0b2a9 2115 https://github.com/akinomyoga/ble.sh/issues/250 2116 2117 ? これは fzf 経由で生成された候補は quote された状態で生成されるけれども、 2118 fzf が更に呼び出している bash_completion の側では quote されていないとい 2119 う事なのだろうか。 2120 2121 具体的にどの様に候補が生成されているの確認する事にする。うーん。 2122 fzf-completion の内部で見ている時点で既に cd sp**[TAB] の時と cd sp[TAB] 2123 の時で quote されるされないが分かれてしまっている。これは ble.sh なしの普 2124 通の bash の時には問題にならなかったのか。何故か。改めて確認する。 2125 2126 うーん。plain bash だとちゃんと動いている。COMPREPLY の内容を確認してみて 2127 も cd sp[TAB] と cd sp**[TAB] で異なる結果を返している。それにも関わらず 2128 どちらも同じく正しい quoting を最終的に実行できているのは何故か。compopt 2129 の呼び出しが粉割れている可能性? compopt によって生成された comp_opts の内 2130 容も確認する事にする。 2131 2132 うーん。"space dir" という名前で生成されている時には compopt -o filenames 2133 が指定されていて、"space\ dir" という形で生成されている時には filenames 2134 が指定されていない。filenames に関してはちゃんと実装しているのか不明であ 2135 る。以前に filenames の時の振る舞いについて確認した気がするが、それはどう 2136 だったか。 2137 2138 元の補完の枠組みの範囲内で noquote は指定していないのだから、ble.sh の内部 2139 で勝手に noquote を指定した物として見做してその上で filenames が指定されて 2140 いる時されていない時で振る舞いを変える等の実装にすると混乱の元である。特に、 2141 本当にユーザーが noquote も指定した時にどう振る舞うのかだとかと整合性が取れ 2142 なくなる。なので、#D1889 以前の様に noquote を改めて指定してその上で条件判 2143 定で振る舞いを調整するというのは良い解決方法ではないと思われる。 2144 2145 ble/syntax-raw が指定されていてかつ filenames が指定されていない時の振る舞 2146 いを変更するのが良い気がする。 2147 2148 * ok: command noquote の時の awk batch の処理が通常の処理と違っている様な気 2149 がする。通常の処理の時には noquote を参照しているが、awk batch では参照し 2150 ていない。通常実装の方の変更に伴って awk 実装も更新しなければらないところ 2151 を忘れていたのではないか。これについては後で確認する必要がある。 2152 2153 % 調べてみるとこの部分は d6242a79 (2021-12) に導入されている。そもそもそ 2154 % れより前には command に対する分岐は存在していなかった。同時に awk batch 2155 % の方にもコードが追加されているが、その時点で異なる条件になっていた様だ。 2156 % これはどういう事だろうか。別の場所で処理されているという事だろうか。 2157 % 2158 % 改めて noquote が処理されている箇所を確認して他で処理されていなければ処 2159 % 理が一致する様に変更する。実際に調べてみたが処理している気配はない。一 2160 % 方で command の場合には DATA に対して判定を行っている。 2161 % 2162 % うーん。そもそも yield.batch の段階では DATA は生成されていない。全体共 2163 % 通の DATA が渡されているだけの気がする。一方で、action:command に対して 2164 % はそもそも DATA が指定されていない? 或いは動的に生成されている可能性も 2165 % ある。 2166 % 2167 % という事は DATA を参照して noquote かどうかを判定しているのは完全に無駄 2168 % な機能? 或いは DATA ではなくて comp_opts の勘違いだろうか。元の意図が完 2169 % 全に分からなくなった。そもそもコマンド名は progcomp で生成していない限 2170 % りは自前で生成しているのだから勝手に noquote が付加される事も考えにくい。 2171 % 将来的に付ける事を考えての処理だったかもしれない。 2172 % 2173 % 1 そもそも action=command を生成しているのは soruce:command しか存在し 2174 % ない。progcomp でコマンド名を生成するとしても action=command にはなら 2175 % ない。 2176 % 2177 % 2 source:command の中では noquote という文字列に対しての取り扱いは存在 2178 % していないように見える。 2179 2180 と思ったら alias の生成に対して :noquote: を指定していた。そして alias の 2181 設定には yield.batch を用いていない。これはコメントで補足が必要である。補 2182 足した。 2183 2184 動作確認する。 2185 2186 x fixed: うーん。quote しない様にしようとしたら単純に元の文字列がそのまま挿 2187 入される様になってしまった。何故だろう。調べるとちゃんと候補は生成されて 2188 いる。 2189 2190 どうやら .apply-partial-comps によって元に復元されてしまっている様だ。うー 2191 ん。comp_opts が syntax-raw の場合にはその処置を行わない様にする? 然し 2192 comp_opts の情報は既に失われている様な気もする。 2193 2194 取り敢えず単一確定の時に progcomp の時は cand_pack DATA に comp_opts が記 2195 録されているのでそれを参照して判定する事にした。そもそもこの様な特別な処 2196 理が必要になるのは bash の既存インターフェイスである progcomp から借用し 2197 ようとしている時の不整合によって起こるのだから、それ以外の場合には問題に 2198 ならない筈である。よって progcomp の時にだけ処理すれば良くて、一般化した 2199 枠組みにする必要はない。 2200 2201 x ok: 今度は普通に補完しようとした時に動作していない。filenames が付加され 2202 ていれば quote に進む筈であるのに。と思ったらこれは単にテストコードの埋込 2203 時に失敗していただけだった。テストコードを除去したらちゃんと動く様になっ 2204 た。 2205 2206 本当にこれで完全なのか等よく分からないが取り敢えず ble/syntax-raw は現在は 2207 fzf しか使っていないし、fzf で動かないのであれば他の枠組みが ble/syntax-raw 2208 を使ったとしてもやはり動かない場合があるという事だろう。なので取り敢えず 2209 fzf に合わせるというので良い気がする。本来は syntax-raw が指定された時には 2210 完全に readline と同じ振る舞いになる事が求められているのかもしれない (つま 2211 り quote する条件もちゃんと調べる?) が取り敢えずは現状のままで良い。 2212 2213 * done: compopt に他の quote を制御するオプションがないかだけは最後に確認しておく。 2214 2215 →特に他には関係のありそうな物はなさそうだ。filenames の項目には trailing 2216 spaces を suppress すると書かれている。これは後で問題になった時に処理する 2217 事にする。 2218 2219 2023-02-21 2220 2221 * prompt: PS1='\g{fg=#FF0000,bold}\$ ' としても色が反映されない [#D1977] 2222 2223 これは単純なバグだった。 2224 2225 * 5.3: case insensitive history search (bash 72c4a0f4) [#D1976] 2226 2227 rlvar search-ignore-case を on にすると readline での検索機能が ignore-case 2228 になる機能が bash devel に実装されている。 2229 2230 実装してみた。 2231 2232 x fixed: 動いていない→ nocasematch を使うべきなのに nocaseglob を使ってい 2233 る場所があった。修正した。 2234 2235 x fixed: 一文字目は大文字小文字が違っても一致しても、続けて文字を入力して行 2236 くとより前の物を探しに行ってしまう。これは文字追加の時の検査で失敗してい 2237 るという事だろうか → 確認したら単に ignore-case を渡すのを忘れていた。直 2238 した。動いている。 2239 2240 x nsearch で一致範囲を着色する機能があるが、大文字小文字が違って見つかった 2241 項目については一致範囲の着色ができていない。カーソル位置も末端になってし 2242 まっている。 2243 2244 2023-02-20 2245 2246 * cygwin: sudo すると PS1 の \u が bash に化けてしまう。何故? [#D1975] 2247 2248 PS1='\u' だと発生しない。 PS1='\u\$ ' だと発生する。Cygwin では '\$' を特別 2249 視してこれが含まれている時には自前処理している。 2250 2251 何と \s で展開していた。これは a9551e54 (2022-03-12 #D1801) で導入されている。 2252 2253 * 2022-06-09 macOS の nawk の振る舞いが変だという事 (reported in killermoehre) [#D1974] 2254 https://github.com/akinomyoga/ble.sh/issues/190 2255 2256 % workaround を追加できるのかどうかも定かではないが、取り敢えずおかしな振る舞 2257 % いをするという事までは確かめていた。これについては改めて調べる事にする。特 2258 % に binding の状態について確認する。 2259 % 2260 % 調べてみるとどうも "上下左右 home/end" などの unbind を正しく実行できていな 2261 % い様である。 2262 % 2263 % a bind/unbind 用のスクリプトに問題がある可能性? → と思ったが別にこれらのファ 2264 % イルはその場で awk によって生成されるのではなくて、昔作ったキャッシュによっ 2265 % て生成された物を再利用しているだけに見える。なので今回は関係ないのではな 2266 % いか。 2267 % 2268 % 逆に言うと報告されている問題は壊れた nawk によってキャッシュが生成される 2269 % 事により被害が拡大している可能性もある。 2270 % 2271 % b TERM による bash の上書きを検出できていない可能性? これが怪しい気がする。 2272 % これの検出を行っている部分のコードを確認する。うーん。先ず勝手に上書きさ 2273 % れたという事が検出されたという訳でもない。或いは検出できないという事が問 2274 % 題になっているのだろうか。然し、検出には awk は使っていないので awk の 2275 % version で振る舞いが変わるのも変である。 2276 % 2277 % 正常に動作する awk の場合にも TERM/is-dirty で引っかかっている様子はない。 2278 % やはりこれは本当に TERM が書き換わった時にだけ起こる問題なのではないか。 2279 % 2280 % c 改めて unbind のコードの部分で何が起こっているのかについて確認する。 2281 % 2282 % うーん。unbind 用のコードは 2283 % ble/decode/bind/.generate-source-to-unbind-default で生成している。なので 2284 % 別にキャッシュをしていた訳ではない。よく考えてみたら、ユーザーがその場で 2285 % binding を変えているかもしれないので、毎回その場で unbind のコードを生成 2286 % しなければならないのだった。 2287 % 2288 % →何と generate-source-to-unbind-default が何も出力していないのだった。うー 2289 % ん。エラーメッセージは、標準エラー出力を使って記録している .save の方に記 2290 % 録されていると思われる → と思ったが標準エラー出力ですら空であった。awk 2291 % が途中で終了してしまっているのだろうか。 2292 % 2293 % うーん。然しこの箇所の awk は LC_ALL=C で動かしている様なので unicode サ 2294 % ポート関係で失敗する訳もないと思われる。一方で報告を受けたエラーはどうも 2295 % unicode サポート関係の様である。 2296 % 2297 % 実際に awk に読み取らせている内容をファイルにダンプして、自分で awk に入れ 2298 % てみてどの様な問題が起こっているのか確認する。と思ったら何も表示されない。 2299 % END まで到達していない。更に確かめていくとそもそもこの自前でコンパイルした 2300 % awk は何を入力しても全く動作していないという事が判明した。つまり、この awk 2301 % は全く動作していない。逆に何故これで今まで微妙にでも動いている様に見えたの 2302 % かが謎である。改めてちゃんと動く apple awk を作る事が必要である。 2303 % 2304 % [結論] Linux 上でコンパイルした apple nawk は実はちゃんとコンパイルできてい 2305 % なくてそもそも全く動作していなかった。 2306 2307 Apple nawk を改めて確認するべきかもしれない。 2308 2309 2023-02-19 改めて apple の awk を見てみたがまた最近更新されている。然し、こ 2310 れに関連する部分が修正された様な形跡はない。恐らくずっとエラーを出力し続け 2311 るつもりなのだろう。よく考えてみたら nawk は元々 unicode にサポートしていな 2312 かったので、macOS awk を強制的に LC_ALL= LC_CTYPE=C で動かしても問題はない 2313 のではないか。 2314 2315 * github actions 2316 2317 うーん。これに関しては取り敢えず GitHub Actions の macos-latest を使って 2318 実験してみる? 取り敢えずダミーのリポジトリを作って見てその上で振る舞いを 2319 実験してみる。 2320 2321 awk --version の出力は "awk version 20200816" であり当てにならない。報告 2322 されている awk も同じ年月日を出力している様だが、blame を見ると問題のエラー 2323 メッセージがソースコードに埋め込まれたのは awk-32 (2021-02-08 もしくは 16 2324 Feb) である。strings で "towc: multibyte conversion failure on:" という文 2325 字列を抽出して見る? →実際にこれを試してみた所、ちゃんと文字列が含まれて 2326 いるという事が分かった。 2327 2328 うーん。LC_ALL=en_US.UTF-8 で特に問題もなく動作している気がする。というか 2329 最初から en_US.UTF-8 が設定されている。色々変えたがよく分からない。因みに 2330 macos-11 ではそもそも multibyte conversion failure のエラーメッセージが 2331 /usr/bin/awk に含まれていないので、これは影響がないのだろうと思われる。 2332 2333 github actions の上で awk-32 をコンパイルする様にしてみたが、それでもエラー 2334 メッセージは再現しない。或いは特定の環境だけで起こる問題? 或いは特定の文 2335 字列に対してだけ発生する問題? 2336 2337 何時迄も保留にしていても仕方がないので取り敢えず対策を入れておく。単に 2338 LC_CTYPE=C を指定する。 2339 2340 2023-02-19 2341 2342 * edit: EXIT trap の中のサブシェルの中で exit が動作しない [#D1973] 2343 2344 builtin exit 自体の処理判定が駄目という事。実際に確認してみるとexit 経由で 2345 これらの close の処理が呼び出されているので入れ子の exit を実行している事に 2346 なっている。入れ子の exit に対する特別の処理を行っている? 2347 2348 →うーん。これは EXIT の中で exit してしまう駄目な設定を回避する為に使って 2349 いる。然し、subshell の中での exit は別に main のシェルを終了させるのに使っ 2350 ている物ではないから気にしなくても良い。なので、単に 2351 _ble_builtin_trap_processing を確認するだけでなくて BASHPID を記録してそれ 2352 から確認する必要がある。もしくは BASH_SUBSHELL の値を確認する。 2353 2354 a _ble_builtin_trap_processing に BASH_SUBSHELL も一緒に記録する 2355 2356 _ble_builtin_trap_processing を現在のどの様に使っているか確認する。現在は 2357 _ble_builtin_trap_processing には基本的には sig の番号を入れているが、特 2358 別に exit:* という値を設定している。値を使っている箇所は実は exit:* かど 2359 うかの判定を行っている所しかない様だ (+ 値が "exit:xxx" の時 trap 2360 postproc に ble/builtin/exit xxx を設定している)。つまり、sig の値を使っ 2361 ている箇所は存在しない? 2362 2363 取り敢えず _ble_builtin_trap_processing に BASH_SUBSHELL を入れる事にした。 2364 2365 * exit の判定条件はどの様にするのが良いか 2366 2367 現在の判定には subshell で実行しているかどうか、attach しているかどうか、 2368 trap を処理中かどうかという三要素を使っている。 2369 2370 attach していない時に関しては、trap 処理中でなければそのまま exit してい 2371 る。trap 処理中の時には DEBUG を用いて上まで bubble する様にしている。先 2372 ず、何故 trap 処理中には bubble を行うのかという事。いきなり終了では駄目 2373 なのだろうか。うーん。でもやはり trap 処理中であれば trap handling の途中 2374 で勝手に終了されては困るという事だろう。 2375 2376 だとすると trap を処理しているサブシェルよりも更に下のサブシェルにいる時 2377 には普通に builtin exit して良いという事になる。 2378 2379 つまり以下で良い様な気がする。 2380 2381 if (trap processing) { 2382 if (trap processing subshell != current subshell) 2383 builtin exit 2384 } else { 2385 if (subshell || unbound) 2386 builtin exit 2387 } 2388 2389 % 実は 2390 % 2391 % if (trap processing subshell != current subshell) 2392 % builtin exit 2393 % else if (unbound) 2394 % builtin exit 2395 % 2396 % で良いのではないか? subshell の中にいて trap の外にいる場合には何れにして 2397 % も trap processing subshell = nil ≠ current subshell なので、最初の分岐 2398 % に入る。と思ったが、unbound の時には !(trap processing) の時にだけ 2399 % builtin exit したい。!(trap processing) かつ unbound の時は最初の分岐に入 2400 % るが、(trap processing) かつシェルレベルが同じの時には、やはり強制的に 2401 % exit する訳には行かない。 2402 2403 改めて整理する。builtin exit せずに特別な処理を実行する必要があるのは、 2404 (1) trap processing を top レベルで処理する為 (2) 実際に抜けようとする時 2405 に job 等のチェックをする為。の二種類がある。(1) の処理に関しては同じサブ 2406 シェルの trap でなければ必要ない。(2) の処理に関してはトップレベルのシェ 2407 ルでかつ attach しているという事。従来の判定は単に ¬(1)∧¬(2) を書き下 2408 しただけの話である。という事で (1) の条件を更新すれば良いだけ。 2409 2410 実装した。動作確認する。ちゃんとその場で終了している。OK 2411 2412 histdb/sqlite3.kill の方は実は exit ではなくて単に return を呼び出しておけ 2413 ば良いのでその様に修正しておく。 2414 2415 2023-02-18 2416 2417 * 2022-10-02 prompt: 実行直前の rps1 の更新時にカーソル位置がずれる [#D1972] 2418 2419 * [reject] dirty 状態の更新時にカーソル位置がずれる? 2420 2421 →これは勘違いだった。或いは別の問題? と思って repository 切り替え直後に 2422 色々入力してみる等したが、rps1 に固定文字列がある場合だとやはり何も問題は 2423 発生しない。なので素早く入力した時にずれが生じる問題も rps1 の更新に伴う 2424 物だったのだろうと思われる。 2425 2426 gnome-terminal と mintty でも起こっている。screen や contra では起 2427 こっていない。 2428 2429 * bleopt prompt_rps1='\q{blerc/rps1}' では発生するが bleopt 2430 prompt_rps1='\q{contrib/git-info}' では発生しない。bleopt 2431 prompt_rps1='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\q{contrib/git-info}' として 2432 幅を合わせてみても再現しない。分かった。時刻が含まれているとずれる。そし 2433 て rps1='$RANDOM' でも再現する。 2434 2435 つまり実行直前の rps1 の更新時にずれが生じているという事。固定文字列を表示 2436 している限りは実行直前に rps1 が再描画されないのでずれが生じないという事。 2437 また、通常の初期描画時にずれが発生しないのは途中に \r 等があってそれによっ 2438 てやはりずれが生じないからなのだと思われる。 2439 2440 rps1 は丁度最後の列のぎりぎりまで文字列を描画する。その時のカーソル位置のず 2441 れの問題によるものだろう。或いは最後のぎりぎりまで描画した後にシーケンスが 2442 続く場合にずれが生じるという事。実際に以下のコマンドで振る舞いに違いが見ら 2443 れる。 2444 2445 $ printf '%*s\e[5Dworld\n' "$COLUMNS" hello 2446 2447 というかそもそも rps1 は relative で trace しているのだから右端に到達した時 2448 にカーソル位置がどうなるのかについては分からないのではないか? 何故右端ぎり 2449 ぎりに出力する様になっているのだったか。実際に確かめると 2450 confine:relative:right:measure-gbox で解析している。 2451 2452 ? つまり、relative なので、例えば複数行のrps1 の時にも mintty や vte では表 2453 示がずれてしまうという事になる。と思って試してみたが複数行の rps1 の表示 2454 自体は普通である。$RANDOM 等を含むとやはり実行直前の更新時に問題のずれが 2455 発生してしまうが。 2456 2457 別に screen や contra の中で逆にずれるという事が起こっている訳でもない。 2458 2459 うーん。どうやってぎりぎりの位置で rps1 内部の移動の時に正しくカーソル位 2460 置を移動できているのか。一旦は rps1 の esc 生成結果を確認する事にする。 2461 2462 \e[205Chello\e[5D\e[205D\e[1B\e[205Cworld\e[5D\e[205D\e[1B\e[206C6785 2463 2464 うーん。何だかすごい移動の仕方をしている。vte や mintty 等の一部の端末に 2465 対して特別なシーケンスを出力しているのかとも考えたが、screen の中で実行し 2466 ても同様に物凄いカーソル移動を行っている。 2467 2468 \e[234Chello\e[5D\e[234D\e[1B\e[234Cworld\e[5D\e[234D\e[1B\e[234C11235 2469 2470 うーん。何故この様な実装になっているのか。justify で right にしている時に 2471 は必ずこの様に振る舞うのだったか。 2472 2473 実際に canvas/trace の中でどの様に処理が進んでいるかを確認してみると、 2474 end-line で生成している内容の時点でこのカーソル移動が発生しているという事 2475 が分かった。更に詳しく見てみると、justify_fields として [改行] と [右寄せ 2476 内容] が含まれている。つまり、改行の操作自体もフィールドとして登録されて 2477 いて、それが一旦カーソルを行頭に移動する役割を果たしているという事。 2478 2479 ? これは恐らく改行ではなく CUD で下に移動した時等の動作も保持する為? 然し 2480 CUD だと実際に端末によって座標計算がずれてしまう気がする。というか 2481 justify する前の解析ではカーソル位置が末端に行っているかどうかも分から 2482 ないのだから CUD を出力したら確実に CUD がそのまま調整無しで出力される 2483 事になり、右寄せの場合には確実にずれが生じる事になる。 2484 2485 結局 CUD 等だと動かない気がするが、これはそもそも rps1 の中で行末でその 2486 様な事を試みる事自体が問題の気がするから気にしなくて良い気がする。 2487 2488 何故複数行 rps1 で問題が起きないのかについては複数行 rps1 に含まれる \n が 2489 実際にカーソルを行頭に運んでいるからなのだと分かった。然し、そうだとして現 2490 在の問題である rps1 の末端でのカーソル位置が不定になってしまう問題に対する 2491 対策には関係がない。 2492 2493 現在の問題に対してどの部分で対策を実装するべきなのかという問題がある。 2494 2495 a trace の時点でカーソルを丁度良い位置に移動してカーソル位置が不定にならな 2496 い様にする? 2497 2498 x 然し、trace は指定した文字列を出力した後のカーソル位置 x y を計算して返 2499 すという事になっている。 2500 2501 これで例えば x=0 等として調整された後の物を出力すると、使う側で続いて続 2502 きの文字列を末尾から続けて出力したい場合等に問題が起こる。 2503 ble/canvas/trace を通して複数の文字列を調整してから出力したとしてもその 2504 振る舞いが変わってしまうのは困る。 2505 2506 x=0 まで移動するのは大袈裟だとして x=cols-2 の位置にカーソルを置くこと 2507 にすれば派手にずれるという事はなくなるが、この様にしたとしても連続して 2508 出力する文字列の一文字目が前の文字列の最後の文字を上書きする事になって 2509 しまうので元のふるまいと厳密に同じにはならない。 2510 2511 b 或いは rps1 の出力の側で調整を行う。 2512 2513 trace 生成結果 (_ble_prompt_rps1_data) の時点で調整を行うか、出力の際に調 2514 整を行うか。最初は生成結果を弄る方が良いと思ったが、出力部分の調整の方が 2515 すっきりする。生成結果の座標などを弄ると、他の箇所で特定の想定の下に座標 2516 位置を参照している箇所があった時に壊れてしまう。少し確認した所その様な場 2517 所はないような気もしたが、ちゃんと確認している訳でもないし、出力部分の調 2518 整で既に十分にすっきりしているのでこちらの方向は考えないことにする。 2519 2520 c うーん。或いは、そもそも \r を prompt_rps1 の末端に加えてから trace を呼 2521 び出すと何が起こるのだろうか。 2522 2523 もし \r が justify_fields に含まれてしまうのであれば、右寄せが効かなくなっ 2524 てしまう。或いは効いたとしても相対移動になってしまうので行頭までは戻って 2525 くれない。 2526 2527 →うーん。やっぱり現在のフィールドの中で先頭に戻るだけで全体の行の先頭に 2528 戻る訳ではない様だ。 2529 2530 →b の方針で実装する事にした。特に出力部分で CR を出力して横位置をクリアし 2531 てしまう事にする。 2532 2533 ? ble/textarea#render/.show-rprompt で 2534 2535 local rps1x=$((_ble_prompt_rps1_data[3]+COLUMNS-_ble_prompt_rps1_gbox[2])) 2536 2537 として出力後のカーソル位置を計算しているのは何故だろうか。 2538 2539 % 単に _ble_prompt_rps1_gbox[2] では駄目なのだろうか。うーん。そもそも 2540 % _ble_prompt_rps1_data[3] と _ble_prompt_rps1_gbox[2] は本来は同じ結果に 2541 % なって欲しい。\r 等が rps1 に含まれている時にずれてしまう。ずれたとして 2542 % この様な方法で計算するのは何故だろうか。 2543 % 2544 % うーん。先ず、 COLUMNS と gbox[2] は一緒になる様にしている筈。ずれると 2545 % したら gbox[2] が COLUMNS よりも左に来てしまうという事である。例えば 3 2546 % 文字左までしか実際の文字列を出力しなかったとする。この時に rps1x は 2547 % data[3] が報告する x 位置よりも 3 文字だけ右側にずらした位置を実際の出 2548 % 力後の位置として報告する様にしている。よく分からない。 2549 % 2550 % 変更履歴を探る事にする。 2551 % 2552 % cf8d9493 2553 % - local rps1x=$((_ble_edit_rprompt[1]+COLUMNS-_ble_edit_rprompt_bbox[2])) 2554 % + local rps1x=$((_ble_prompt_rps1_data[3]+COLUMNS-_ble_prompt_rps1_gbox[2])) 2555 % 4fa139ad (canvas/trace の右寄せ対応 #D1502) 2556 % - local rps1x=${_ble_edit_rprompt[1]} 2557 % + local rps1x=$((_ble_edit_rprompt[1]+COLUMNS-_ble_edit_rprompt_bbox[2])) 2558 % 2559 % 先ず gbox は元々は bbox だった様だ。gbox にしたのは右寄せを実際に出力さ 2560 % れる文字内容に位置で行う様に変更した時に一緒に変更したのだろう。実際に 2561 % このよく分からない調整が付け加えられたのは canvas/trace 側で右寄せが実 2562 % 装された時の様である。#D1502 の議論を確認したがこの補正について特に言及 2563 % している気がしない。 2564 % 2565 % うーん。端末幅が最後に解析してから変わった時に備えての事だろうか。それ 2566 % が一番疑わしい気がする。実際に rps1 の解析を行った後に COLUMNS が増えた 2567 % り減ったりする場合を考えると、うーん。 rprompt[1] が (0,0) から仮描画し 2568 % た時の終了位置で、COLUMNS-_ble_edit_rprompt_bbox[2] が描画開始位置とい 2569 % う事だろうか。なのだとすると現在の実装でこの計算が問題を起こしていない 2570 % のは奇跡の様な気もする。(と思ったが単に rprompt[1] と bbox[2] の両方に 2571 % 同じだけ offset が加わったのだと考えれば余り影響はない)。 2572 % 2573 % そう考えてみたら、そもそも端末幅が変わる様な事を考えなくても、ちゃん 2574 % とこの様にして開始位置の分だけずらす処理をしなければちゃんと計算でき 2575 % ない。 2576 2577 つまり、元々は rprompt[1] + (COLUMNS - bbox[2]) であった。この時 2578 rprompt[1] 及び bbox[2] の計測は x=0 を起点として行った物がそのまま入っ 2579 ていたので、rprompt[1] を直接使う訳には行かなかった。rprompt 表示開始位 2580 置 (COLUMNS - bbox[2]) の分だけ右にずらす為に、これを加算していたのだっ 2581 た。 2582 2583 現在は _ble_prompt_rps1_data[3] に直接実際の描画終了位置が入っているの 2584 で、わざわざ変な補正を実施する必要はないのであった。 2585 2586 ところで #D1502 当時の考え方だと rps1 は右からの相対病がなので端末の幅 2587 が変わっても、適切な位置から描画を開始して相対移動で描画することで、表 2588 示が崩れたりせずに右端にプロンプトを配置できることを意図した様だ。然し、 2589 現在の実装では端末幅が変わる毎に再計算を行う様になったし、そもそも描画 2590 の際にも 0,0 から描画を始めている。なのでその様な配慮の元で描画終了位置 2591 を調整するなどの事は今となっては難しい。 2592 2593 2023-02-16 2594 2595 * histdb: bg process timeout [#D1971] 2596 2597 * 終了を指示した後にもしプロセスが残り続けた時にどうするかの問題について 2598 2599 a .pid ファイルを残したままにすると正常に終了してその後に別のプロセスが同 2600 じ pid を持った時に誤爆する可能性がある。 2601 2602 b .pid ファイルをクリアするとプロセスが残ってしまった時に残り続ける。 2603 2604 c background で一定時間待ってから生存確認をして生きていたら強制終了する事 2605 にすると、bgpid 変数が混ざってしまって変な事になる? と思ったが bg だと 2606 subshell になるので関係ない? どうせ暫く idle にした時に呼び出されるのだ 2607 から、subshell background ぐらい作れば良い気がする。或る一定時間プロセ 2608 スが消えなかったら強制終了する。 2609 2610 d 或いは foreground で暫く待つ? と思ったがビジー状態等の時には結構長くデー 2611 タベース更新に時間がかかるという事もあるかもしれない。なので余りに長く 2612 待つのは非現実的である。 2613 2614 ここは c の方針で良い気がする。実装した。 2615 2616 2023-02-19 うーん。プロセスが残る様になってしまっている。また、tty が閉じら 2617 れるのに時間がかかる様になっている。これも何れかのプロセスが fd を掴んだま 2618 ま残っているのが原因である。 2619 2620 どうも sqlite3.kill のプロセスがやはり残留してしまっている。 2621 2622 % * ble/bin/msleep が固まって動かなくなるのが原因のようだ。msleep の実装は 2623 % run/$$.util.msleep.pipe に対する fd を用いた物だが、もしかするとこの 2624 % pipe ファイルが削除されると動かないのかもしれない。或いは、この fd を開 2625 % いているプロセスが2つ以上ないとだめという事なのかもしれない。一応最初の 2626 % msleep は動作しているので、サブシェルでは msleep は使えないとかそういう 2627 % 問題ではない筈である。 2628 % →これを ble/bin/sleep に変えても元の問題は直らなかったし、逆に本体の問題 2629 % を解決したら別に msleep でもちゃんと動いた。 2630 2631 然し、msleep を ble/bin/sleep に置き換えてもやはり暫くプロセスが生きている 2632 様である。exit を builtin exit に変更したらちゃんと動く様になった。 2633 2634 これは ble/builtin/exit の問題なので別項目で議論する (#D1973)。そもそも実は 2635 ここでは exit よりも return を使うべきなので、ここは単に return に変更する 2636 事にする。動作している。 2637 2638 2023-02-14 2639 2640 * make: no-argument return がまたある。make scan でチェックするべき [#D1970] 2641 2642 $ grc 'return[[:space:]]*($|[;|&])' 2643 2644 * histdb: git info 等追加情報を user の指定で記録できる様にする [#D1969] 2645 → "bleopt histdb_remarks" として実装した。 2646 2647 2023-02-18 そもそも rps1 での dirty 更新が発生していない。因みに 2648 prompt_status_line に関しては dirty 更新は働いている様だ。然し、これは独立 2649 した問題の気がする。 2650 2651 うーん。mintty の中だけでなく、普通に新しいセッションでは全て動いていない。 2652 何故? うーん。histdb_remarks の対応 commit で以降で動かなくなっている。→同 2653 期処理等を破壊したかと思ったが単に dirty_mark の生成コードでバグを埋め込ん 2654 でいただけだった。 2655 2656 * histdb: PS1=(\$ ' で ( を挿入した時にエラーメッセージ [#D1968] 2657 2658 これは master 81e376a (もう存在していない。対応するのは 8d5cab8 が近い) で 2659 は発生していない。 2660 2661 これは最初は syntax のバグかと思ったがどうやら histdb-word で発生している。 2662 2663 うーん。response で現在のコマンド内容と全く関係ない物が生成されている? とい 2664 うかそもそも空の文字列で候補生成されているのではないか。然し、そうだとして 2665 も index が 8 になっているのはよく分からない。 2666 2667 _ble_edit_str='PS1=(\$ '\''' len=9 2668 _ble_edit_ind="5" 2669 ret="8:'.timeout 1001'" # response 2670 2671 うーん。分かった request の時点で全ての単語に対して補完を試みようとしている。 2672 何故かというと現在のカーソル位置がコマンドラインの末端にあるという事を仮定 2673 している。 2674 2675 カーソルが行の途中にある場合には個別に実装する必要があるのではないか。と思っ 2676 たが、カーソルが単語の途中にある時にはその単語について補間する必要はない。 2677 飽くまで単語の末尾にいる時にだけ補完を実行すれば良い。行の途中にいてかつ単 2678 語の末尾にいるという状況では、まだ閉じていない単語の末尾にいるという事はあ 2679 りえない。という事は、現在位置にある単語について調べれば十分である。 2680 2681 うーん。現在の単語の開始位置を調べる方法が非自明だったが (wbegin を stat に 2682 設置せずに一気に読み取ってしまう単語が存在する) 取り敢えず実装した。 2683 2684 * blerc.template: update unicode versions [#D1967] 2685 2686 2023-02-13 2687 2688 * 2021-10-26 edit: winch の際の遡って再描画する条件をより広げる [#D1966] 2689 https://github.com/akinomyoga/ble.sh/issues/142#issuecomment-955181640 2690 https://github.com/akinomyoga/ble.sh/issues/276 2691 ref #D1679 2692 2693 取り敢えず端末の reflow について仮定はする事にする。つまり、行末にまで達し 2694 ていなければ、端末幅を広げた時のその行の次の行が一緒に動くという事はない。 2695 一方で、行末で折返しが起こっていなかったとしても一番最後の列まで文字が存在 2696 している時には、端末によっては行継続として取り扱う可能性があるので、安全側 2697 を取って幅が変化している可能性について考える。 2698 2699 * ok: 直前のコマンドが行末まで文字を埋めている時 2700 2701 | というか直前のコマンドの出力結果が端末末端まで存在している時には結局問題 2702 | になるのではないか? 然し、その様な場合は少ないと考えられる (全画面 TUI な 2703 | コマンドの場合にはそれも怒るかもしれないがその場合には altscreen 上に描画 2704 | すると期待したい)。 2705 | 2706 | また、折返しをちゃんと記録する端末で更に xenl の場合には、(a) 行末ぎりぎ 2707 | りで終わった場合には、 [EOF] マーカーが挿入されるし (b) もし行末で改行を 2708 | した場合には行が切り離されるので端末幅を広げた時に行がくっつくという事も 2709 | ない。折返しを記録せずに単に最後の列に文字があるかどうかだけで再配置をす 2710 | る端末については関知しないとして良い気がする。 2711 2712 その様な場合は少ないし、xenl な端末で折り返しをちゃんと記録していれば、 2713 ble.sh では EOF マーカーがあるので問題にならない筈。 2714 2715 * そもそもこの判定は edit よりは canvas の側で管理するべき事の気もする。 2716 2717 各パネルについて再配置で予期しない結果になる可能性について判定する。 2718 2719 2023-02-13 改めて考える。各パネルの内容を見に行く事にする。実装していない時 2720 は安全側に倒して行数が変わっている可能性を考慮に入れる。 2721 2722 うーん。各パネルは safe/unsafe で判断するのではなくて、最低でも終端点が何処 2723 以降になるのかという事を返す様にすれば良いのではないか? 2724 2725 というか現在のカーソル位置から文字数を割り出して最低でも上から何行目以下に 2726 あるという事までは計算できるのではないか? 2727 2728 * canvas_winch_action に関する端末依存性は色々考えられる: 2729 2730 * 全角文字や emoji, 結合文字などの折り返しはどうなるのか。折り返した事に 2731 よって結合していなかった物が改めてくっついて幅が減るなどの減少はあるだ 2732 ろうか。 2733 2734 * 全角文字が入り切らなくて行末に空白を空けて折り返しがあった時に reflow 2735 でまた行がくっついた時に空けて置いた空白は潰れるのかそれとも残ったまま 2736 になるのか。 2737 2738 →複数回 winch が来たらその回数の分だけ減少している可能性がある。然し、 2739 処理中に届いた WINCH は消滅してしまうのでこれを正確に測るのは困難である。 2740 最悪の場合は伸びた文字数だけ幅が消滅する事があるのではないか? うーん。 2741 最悪でも拡張前の行数よりも沢山の空白が潰れるという事はありえない。 2742 2743 * reflow するかどうかの marker は ECH, EL, DCH によって破壊されるのか其処 2744 に残り続けるのか。 2745 2746 * 行末まで文字が行った時点で reflow mark がつくのか、更に文字が追加されて 2747 次の行に行った時点で reflow mark がつくのか。 2748 2749 * カーソルの位置は reflow と一緒にどの様に動くのか。 2750 2751 * DECSC/DECRC で一時移動していた時に、一旦記録していた位置も一緒に reflow 2752 するのか、それとも戻ってきたら絶対位置に戻ってくるのか。 2753 2754 * 連続的に複数の再配置が起こる端末と一気に最終サイズに於いて再配置が起こ 2755 る端末の振る舞いの違い等も考えられる。 2756 2757 * done: wiki redraw-safe 2758 * done: blerc: redraw-safe 2759 * done: ChangeLog 2760 2761 * README: ビルド過程に対する説明 [#D1965] 2762 2763 勘違いする人が沢山いるし勝手に馬鹿にしている人がいるので README の make の 2764 部分に色々書いておく。 2765 2766 * make/README にも各ファイルの説明を書いている。 2767 2768 * README: Guix package の位置が変わっている [#D1964] 2769 2770 2023-02-12 2771 2772 * prompt: \g{} は ble/color/setface/.spec2g を使う? [#D1963] 2773 https://github.com/akinomyoga/ble.sh/issues/278 2774 2775 そうしたらカスタム face を指定できて、ユーザーが自分で定義する事に直接の意 2776 義が出てくる。 2777 2778 * done: wiki: 他にも faces はあるという事を書く (motivated by bkerin) 2779 2780 2023-02-13 .spec2g は動的な face の為に算術式を返すので、color.sh の枠組み 2781 の外側で算術式評価する様になっていると、後に face 継承などを実装した時に評 2782 価文脈が違って変な事になる可能性がある。評価文脈をちゃんと把握する為に、算 2783 術式評価した結果を返す関数を color.sh の側で用意してそれを呼び出す様にする 2784 べきである。.spec2g は .spec2gexpr に改名し、それとは別に spec2g という関数 2785 を用意してそれを呼び出させる事にした。 2786 2787 * syntax: 5.2 以降では (()) [[]] の直後は } 等が来ても良い [#D1962] 2788 これの修正は簡単。 2789 2790 * color: ble palette の並び方をより分りやすく (suggested by stackoverflow/caoanan) [#D1961] 2791 https://superuser.com/a/1512656/980046 コメント by caoanan 2792 2793 色の排列を考え直す余地はある。現在は横幅 64 使っている。高さが 32 なのは実 2794 は端末の 80x24 には入り切らない。 2795 2796 * syntax: 履歴展開 & "$!", heredoc [#D1960] 2797 2798 bash-4.1 以下で echo "$!" を実行しようとしても履歴展開周りで変な事が起こっ 2799 てコマンドを実行する事ができない。更に bash-3.0 では 2800 2801 bash-3.0: ble/history:bash/resolve-multiline: そのようなファイルやディレクトリはありません 2802 2803 と表示される。 2804 2805 また暫くして実行してみた所違う失敗の仕方をする。どうも本当に履歴展開が起こっ 2806 ている様だ。--norc で実行しても履歴展開が起こって変な事になってしまっている。 2807 つまり、これは ble.sh 自体の問題ではないという事。 2808 2809 a ble.sh の側で履歴展開があるかどうかの判定を行って、履歴展開文字が存在しな 2810 い時には履歴展開をそもそも試みないという可能性? 2811 2812 然しそれだと普通の履歴展開と "$!" が混在している場合には結局履歴展開を実 2813 行することになるので、問題を回避できていない。それに元々の bash の振る舞 2814 いとして履歴展開が起こる筈なのにそれを無理やり回避するのは間違っている気 2815 がする。 2816 2817 b 或いは履歴展開の文法解釈を弄る。というかその様に対応するべきである。そう 2818 すれば混乱もないだろう。 2819 2820 →b の方針で修正する事にする。 2821 2822 * fixed: というか調べてみるとどうやら 4.2 でも "echo!" 等で展開は実施される 2823 様である。これについては対応した。 2824 2825 * fixed: 4.1 以下での $!... の展開 2826 2827 然し今回問題になっているのは 4.1 以下では $! の ! であっても履歴展開を誘 2828 導してしまうという事である。これを文法的に正しく処理するのは難しい。とい 2829 うか、$! に続いて何か文字列があると必ず展開されてしまうという事になる。こ 2830 の振る舞いは困る。もう少し色々試してみる事にする。 2831 2832 $ echo $!a 2833 2834 も履歴展開されてしまう。${!} は展開されない。つまり $! に丁度一致する時に、 2835 $! に引き続き履歴展開がある場合には履歴展開とするという事。 2836 2837 これに対応する為には check-dollar の中で $! に一致した時に 4.1 以下で特別 2838 に check-history-expansion を呼び出す必要がある。所で histchar も考えると 2839 単に '$!' だけ確認すれば良い訳では無い。 2840 2841 因みに check-dollar が有効な文脈は全て履歴展開も有効の様なので、 2842 check-dollar の中で履歴展開を試みるかどうかについて追加の条件で判定を行う 2843 必要はない。 2844 2845 →実装した。取り敢えず実際の bash の振る舞いと同じになる様に履歴展開の着 2846 色がされる様になった。 2847 2848 * fixed: 履歴展開 in heredoc 2849 2850 履歴展開の着色がされていない。また、\\ \$ 等の着色もされていない。但し、 2851 \a 等の元よりエスケープする必要のなかった物についてはエスケープとしては処 2852 理されない。\" もエスケープとしては処理されない。\<LF> はエスケープとして 2853 認識される。\! は unquote されないが履歴展開を抑制する効果はある。 2854 2855 * heredoc 内での \\ \$ \` \<LF> エスケープの着色に対応した 2856 * heredoc 内での履歴展開の着色に対応した 2857 2858 * fixed: 3.0 での ble/history:bash/resolve-multiline のエラーメッセージは依 2859 然として表示される。 2860 2861 どうやら bash-3.0 では resolve-multiline は有効になっていないのに、その外 2862 側で resolve-multiline を呼び出している箇所が2箇所ある。それぞれに対応す 2863 る (mutiline サポートなしの) 実装を提供する事にした。とは言っても 2864 multiline サポートなしなので両方ともほぼ自明な操作である。 2865 2866 * fixed: histreedit は二回連続だと accept するべきなのでは? 4.1 で展開に失 2867 敗する時何度でも失敗する。と思ったが、寧ろ 3.0 で二回連続で実行した時に実 2868 際に実行された方が問題であった。plain Bash だと histreedit だと何回実行し 2869 ようとしても実行できない。 2870 2871 代わりにエラーメッセージが表示される。というか何故エラーメッセージが表示 2872 されていない? in ble.sh → 分かった。ble/widget/.internal-print-command 2873 が $command を被覆している所為でちゃんとエラーメッセージの起こる履歴展開 2874 を評価できていなかった。 2875 2876 * [棄却] histdb: コマンドも histdb-word と同様に数えて良いのではないか? [#D1959] 2877 2878 これは quote 等を除去した状態で数えるのが良い? それとも quote も含めて記録 2879 する? コマンドの種類も記録するべき? 然し、実の所、わざわざ記録しなくても、 2880 後でコマンド履歴を見れば何を呼び出したかは基本的に分かる。 2881 2882 これは #D1958 と同様の理由で今は数えない。実際に必要になったらその時に実装 2883 すれば良いが、実際に必要になるのか分からない。 2884 2885 * [棄却] histdb: histdb-word で一つのコマンドに同じ単語が複数あった時に数える? [#D1958] 2886 2887 然し目的が使用頻度を記録して後の補完での優先順位に役立てるのだとしたら、一 2888 つのコマンドの中で複数同じ単語が登場するのは自明の可能性が高く、使用頻度と 2889 して計上するのは違う気がする。もし実際に単語の使用頻度を興味として知りたい 2890 のであれば、command_history の command を抽出して自前で処理するべきなのであ 2891 る。histdb で記録するのは高速にそういった処理をするのが大変だから補完候補生 2892 成の為のキャッシュとして用いているという側面がある。 2893 2894 * histdb: auto-complete-history で ' を含むコマンドがあると SQL でエラーメッセージが出る [#D1957] 2895 2896 これは単に q=\' qq=\'\' の初期化していない状態でエスケープを実行していたか 2897 らだった。修正した。 2898 2899 * histdb: bash-3.0 で fork したプロセスが消滅してしまう。謎 [#D1956] 2900 2901 普通に自分で実行すると生きている様な気がする。 2902 2903 どうも bash-3.0 では function fname { ... } <&"$fd1" >&"$fd2" 等の様にして 2904 リダイレクトするとちゃんとリダイレクトされていない様だ。何故か /dev/null に 2905 繋ってしまう。中でリダイレクトする様にしたら直った。 2906 2907 * [棄却] histdb-word: edit insert-last-argument 等についても [#D1955] 2908 2909 実は histdb-word を使った方が良いのでは。と思ったが 2910 2911 x 現在の histdb-word の実装だと単語の順序等が失われるし (同じコマンドの中に 2912 含まれている単語は同じ時刻になるのでは) 2913 2914 x また重複する単語があった時に古いものが抜けてしまう (その方が望ましいとい 2915 う考え方もあるかもしれないが、やはり思い出しながら探す時に通り過ぎた後で 2916 もちゃんと現れた方が親切な様な気もする)。 2917 2918 また現在の insert-last-argument の実装を確認すると履歴展開を使って単語を抽 2919 出しているので、結局別に現在の実装で問題があるという訳でもない。寧ろ、現在 2920 の実装は (subshell fork するものの) 他のプロセスとの交信がない分だけ安定し 2921 ているのではないかという気がする。 2922 2923 2023-02-10 2924 2925 * histdb: 4.2 で算術式のエラー(配列負の添字) のエラーが生じている [#D1954] 2926 2927 実は printf %(%s)T に対応しているとは言っても、bash-4.2 では -1 を指定しな 2928 いとちゃんと現在時刻になってくれない様だ。これが為に BLE_SESSION_ID の為の 2929 時刻決定で失敗していた。 2930 2931 * 2023-02-12 bash-4.2 の last_time が 0 になっている。これも同じ事が原因だっ 2932 た。ble/histdb/.get-time の関数の中でも %(%s)T を用いて時刻を取得しようと 2933 していたが、明示的に -1 を指定する必要がある。 2934 2935 * histdb: 3.2以下で session が登録されていない [#D1953] 2936 これは単にデバグ用に置き換えていた関数名 assign2 が残っていたのが原因だった。 2937 2938 * histdb: sqlite のエラーメッセージは端末に表示するようにする [#D1952] 2939 2940 本来は全く表示されない事を期待しているので、もし表示されるのだとしたらバグ 2941 である。なので表示する。 2942 2943 2023-02-06 2944 2945 * 2022-01-23 [対応済み] コマンドのログ機能を作成する [#D1951] 2946 2947 特定のファイルに情報を書き込む。 2948 2949 同時に複数の書き込みがあった場合に混ざり合う危険性がある。滅多に起こらない 2950 と思いたいがちゃんと防止策は作っておく必要がある。例えばシェル毎に履歴を記 2951 録して終了する時に合成するという手が考えられる。合成自体が衝突する自体を防 2952 ぐために mkdir/rmdir を使うのが一つの手である。 2953 2954 コマンドにはコマンド実行前とコマンド実行後の二つに分けて結果を書き込みたい 2955 という欲求がある。という事を考えると、 2956 2957 $ printf '%x/%s/%s.e%s\n' $(printf '%(%s)T' -1) "$HOSTNAME" $$ "$LINENO" 2958 2959 * バックグラウンドのジョブの状態はどの様に記録するのか。うーん。ジョブに関 2960 しては一応 ble.sh の中で追跡はしている。それに従って終端を幾らか荒い尺度 2961 で検出する事はできる。しかし正確な時間は分からない。 2962 2963 プロンプトを表示した時刻も記録しておくと良い様に思われる。しかしそうなる 2964 と大量の記録が残ってしまう事になるのではないか。うーん。プロンプトを表示 2965 した時刻に関しては別に全てを記録する必要はない。前回のプロンプトの表示時 2966 刻だけ覚えておいて、ジョブ変化を検出した時にその情報を備考として乗せるだ 2967 けで良いのである。 2968 2969 * 記録する情報は以下の通り。 2970 2971 cmd, pwd, 終了ステータス(PIPESTATUS), 各種時刻情報, files(自動補完用), 構 2972 文解析情報(後で単語を抽出する為。というか単語の範囲だけで良い). 2973 2974 これを使って処理するのはもしかしたら外部プログラムに頼らなければならない 2975 かもしれない。 2976 2977 或いはデータベース等も保存先として考えても良いのかもしれない。但し、その場 2978 合には sqlite3 等に対する依存性が発生する。一方で、sqlite3 には最低限の排他 2979 制御が含まれている様ではある。 2980 2981 * 2022-06-28 [対応済み] コマンド名の曖昧補完ができない。./adf[tab] [#D1950] 2982 2983 これは . で始まるコマンド名を列挙してそれで補完を実行しようとしている為であ 2984 る。/ が含まれる場合には glob で一致させてその上で実行属性でフィルタする必 2985 要がある気がする。 2986 2987 引数の場合にはできている。うーん。/ が含まれる場合は別に生成するべきなので 2988 はないか。 2989 2990 * 2022-07-20 [解決済み] konsole drag&drop [#D1949] 2991 https://github.com/akinomyoga/ble.sh/issues/211 2992 https://invent.kde.org/utilities/konsole/-/merge_requests/714 2993 2994 konsole に PR を出したが返事がない。この2日の間に別の PR はマージされている。 2995 暫く待っても何も反応がなかったら Bugzilla の方にも提出する事にする。もしく 2996 はメーリングリストに直接問い合わせる。 2997 2998 * [棄却] histdb: 現在の有効なファイル名をコマンドに紐づけて記録する可能性について [#D1948] 2999 3000 * コマンドが前提としているファイルの存在を確認して history を skip する。 3001 3002 ファイル名着色などの情報を参照したい。そうすればファイル名と偶々一致してい 3003 る単語を誤って登録してしまうという事もなくなる。chroma を充実させる動機にも 3004 なる。 3005 3006 複数のファイル名が考えられるので別テーブルに記録する事も考えたが、それだと 3007 データベースサイズが大きくなる気がする。或いは、別テーブルにファイル名だけ 3008 記録しておいて但し id リストを command_history の entry の中に保存するとい 3009 う事にすれば良いのかもしれない。 3010 3011 余り形式を複雑にしても仕方がないしデータベース上でファイル名を操作するとも 3012 思えない。後で特定のファイル名を指定しているコマンドを探るとしても、ファイ 3013 ルの相対パスを解決しなければ使えない。 3014 3015 然し改めて考えたら、既にファイルが存在しているかどうかに関わらず実行するコ 3016 マンドもあるのだからファイル名と一致するかどうかで候補として生成するかどう 3017 かを変えるのは余り良いアイディアではない様な気もする。どうなのだろう。 3018 3019 * 更に改めて考えてみると本当に fish がここまでの情報を記録しているのかも不 3020 明である。oil の zulip ではその様な事を言っている人がいたが、実は単に 3021 fish は cwd だけを見て判定している可能性もある。実際検索しても其処まで積 3022 極的に履歴を記録している訳でもない様だ。2016に初めて cwd を一緒に記録し始 3023 めた程度である。 3024 3025 →今 fish の振る舞いを試してみたが、コマンド実行時に存在したファイルを消し 3026 ても、同じディレクトリで同じファイルが autosuggestion の候補として表示され 3027 る。つまり、(少なくともデフォルトの設定では) fish は別にコマンドライン中に 3028 含まれるファイル名について記録して存在を照合しているという訳ではない様だ。 3029 3030 逆に cd 等の既知のコマンドについてそれが成功するかどうかをその場で判定して 3031 いるというだけの事なのかもしれない。 3032 3033 うーん。これについては棄却する事にする。代わりにコマンドが成功するかどうか 3034 を高速に判定できればそのコマンドをスキップするという機能を項目として残す。 3035 3036 * histdb: 様々の sql query エラーの修正 [#D1947] 3037 3038 * main: bash-3.2 で BLE_SESSION_ID の時刻決定が誤っている。 3039 3040 bash-3.2 でちゃんと words を登録できていない気がする何故? 或いは、もっと 3041 前から駄目だった? と思ったらどうやら時刻が誤っている様だ。そし 3042 て_ble_base_session の時刻を見ると何故か 1000000 分の1の少数にされている。 3043 うーん。結局これは ble/base/initialize-session の初期化が問題だった。 3044 3045 更に bash-3.2 で session が登録されていない。うーん。調べてみた所様々なエラー 3046 が出ていた。bash-3.2 に限らず bash-4.0+ でも sqlite がエラーメッセージを出 3047 しているのを捨てていた。直した。 3048 3049 * 2022-01-08 term: prompt_status_line でずれが生じる端末がやはり存在している。何故だろうか [#D1946] 3050 Ref https://github.com/borisfaure/terminology/pull/115 3051 3052 2022-02-02 windows terminal でもずれる。改めて確認してみる。実は status を 3053 表示していなくても端末の一番下の行で改行をしようとしても改行されないのであ 3054 る。という事はここで使っているシーケンスの内 windows terminal で動作しない 3055 物が存在しているという事。 3056 3057 increase-height.draw が動作していないのではないだろうか。 3058 3059 うーん。もしかして DL をした時に新しく追加した行が削除されて逆スクロールし 3060 ている? 更に IL も動作が変だという事が判明した。 3061 3062 →Cygwin に報告したらすぐに修正してくれた。これで待っていればちゃんとした振 3063 る舞いになる。それまでは仕方がないので我慢する。 3064 3065 * 2022-03-04 terminology でずれる原因は分かった。これは terminology のバグで 3066 ある。以下で変な振る舞いをするという事が分かる。 3067 3068 $ printf 'O\e7\e[%d;%dHA\e8K\n' $LINES $COLUMNS 3069 3070 https://github.com/borisfaure/terminology 報告しようと思ったが何だか良く 3071 分からない。http://issues.terminolo.gy/ から 3072 https://phab.enlightenment.org/project/view/8/ に跳んだが issue を作る方 3073 法が分からないので取り敢えずログインする事にしてみた。そしたら元からある 3074 チケットですら見ることができなくなってしまった。 3075 3076 面倒になったのでこれは PR にして出す事にした。 3077 https://github.com/borisfaure/terminology/pull/115 3078 3079 * terminology version 判定 3080 3081 WA を追加しようと思ったが terminology を判定する方法は実は無い。xterm の 3082 ふりをしているので区別が付かない。もし terminology の区別がつくのだとした 3083 ら、terminology では最後の行を使わない様に修正するのが良い。 3084 3085 DA2 応答は 1.4.0 以降は 61;337;0 である。それより前は 41;285;0 だった様だ。 3086 https://github.com/borisfaure/terminology/commit/96bbfd054b271f7ad7f31e699b13c12cb8fbb2e2 1.4.0 "61;337;0" 3087 https://github.com/borisfaure/terminology/commit/e4d7cb93f2ad3c09d50362cee557815e10997687 1.4.0 "41;337;0" (not-released) 3088 https://github.com/borisfaure/terminology/commit/59ad20f6f8e364b02e1c65ec28f480649eea714a 0.4.0 (DA2 には変更なし) 3089 https://github.com/borisfaure/terminology/commit/526cc2aeacc0ae54825cbc3a3e2ab64f612f83c9 0.3.0 "41;285;0" 3090 https://github.com/borisfaure/terminology/commit/db902446540f5e014694da0ec6fb495cfab15e62 0.2.0 "0;271;0" 3091 https://github.com/borisfaure/terminology/commit/500e7be8b2b876462ed567ef6c90527f37482adb 0.2.0 "1;271;0" (not-released) 3092 https://github.com/borisfaure/terminology/commit/8b822a61d7721fce16e145b57dc67ca6ae8b752d 0.1.0 "\e[?1;0c" DA2 じゃない (initial commit) 3093 3094 まとめると、 3095 3096 terminology-0.1.0 ... DA2 応答は返さない 3097 terminology-0.2.0 ... 0;271;0 3098 terminology-0.3.0 ... 41;285;0 3099 terminology-1.4.0 ... 61;337;0 3100 3101 一応 temrinology はこれで100%ではないが検出できる。然し、考えてみれば検出 3102 できたとしてもどうやって workaround を加えれば良いのか不明である。うーん。 3103 \e8 する前に一旦 \r で行頭に戻るというのが一つの対策かもしれない。 3104 →この対策でちゃんと動く様になった。 3105 3106 * [自然解消] 2022-03-08 上記と同様の現象が bash-3.2 では未だ健在である。何故だろうか。 3107 3108 terminal ID がうまく動いていないという事だろうか。→terminal ID はちゃん 3109 とうまく行っている。terminology 1.4 という事になっている。 3110 3111 また別の問題という事だろうか → patched terminology では発生していない。 3112 つまり同じバグ。 3113 3114 _ble_term_rc がちゃんと置き換わっていない可能性? → そうでもない。ちゃん 3115 と \r が挿入されている。 3116 3117 直接 '\e8' を記述している箇所がある可能性? →うーん。そういう箇所もない。 3118 DECSTBM のテストに用いている \e[r によって wrapnext が不自然な状態になっ 3119 ている可能性? → テストの方にも \r を入れてみたが振る舞いは変わらない。 3120 3121 また問題が発生するのは最初の1回だけの様でもある。つまり、未だ端末の種類を 3122 特定するよりも前の時点で実行した rc により wrapnext が壊れている可能性。 3123 3124 2023-02-06 うーん。今実行したら再現しない。恐らく terminology の側が修正 3125 されたので問題が出なくなったのだろう。なのだとすれば、わざわざ古い 3126 terminology を持ち出してテストするのも大変だし、気にしない事にする。 3127 3128 * fixed: 2022-03-04 terminology で最初のコマンドを実行する迄 C-h 及び BS が 3129 全く効かない。何故だろうか。そもそも C-h を受信できているのかも不明である。 3130 一回コマンドを実行すれば問題なくなる。 3131 3132 builtin bind -X を見た感じが問題ない。然し、何故か bind -X の実行結果に 3133 3134 "\C-h": "ble-decode/.hook 8; builtin eval -- \"$_ble_decode_bind_hook\"" 3135 3136 というのが混入する状態になっている。 3137 3138 ? 何故 terminology だけで発生するのだろうか。うーん。不思議だ。調べるとど 3139 の端末でも bind uvw は何か変な状態になって登録されている状態になってい 3140 る。然し、\C-h も同様に設定されているのは terminology だけである。 3141 3142 然し、そもそも何故 uvw が直接 bind されてそれが bind external に登録さ 3143 れてしまっているのか。これは何らかのミスなのではないか。 3144 3145 そもそもこれらの bind が設定されている箇所を特定すれば何処でこれが起こっ 3146 ているのか判明する筈。 3147 3148 うーん。bind -x を実行している箇所を見たが別に .hook 8 を特別に指定して 3149 いる箇所もないし、decode.bind.50108.UTF-8.bind も特に変な事はない。 3150 3151 * うーん。bind -X で違いが出るという事は bind.save に問題があるのかもしれ 3152 ないと考えたが、どうやらそうでもない様だ。別に bind.save の内容は変化し 3153 ていない。 3154 3155 * bash の version によるバグかもしれないと思って調べてみたが bash-3.2 か 3156 ら 5.1 まで全て問題は再現する。plain Bash + ble.sh --norc でも再現する。 3157 noattach でスタートして ble-attach を使って attach した時にも再現する。 3158 3159 * うーん。分かった。terminology は erase を ^? から ^H に差し替えて端末を 3160 初期化している。これによって UVW? の workaround が効かなくなっていたと 3161 いう事。うーん。つまり、原理的にあらゆる文字がこの影響を受ける可能性が 3162 あるという事では。 3163 3164 --- stty1.txt^I2022-03-08 20:10:24.782885825 +0900 3165 +++ stty2.txt^I2022-03-08 20:10:44.466968954 +0900 3166 @@ -1,5 +1,5 @@ 3167 speed 38400 baud; rows 24; columns 80; line = 0; 3168 -intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>; 3169 +intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; 3170 eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; 3171 werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0; 3172 -parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts 3173 3174 * 愈 bind-tty-special-chars を off にする必要があるという事だろうか。 3175 3176 但し bash-3.0 には bind-tty-special-chars は存在していない様である。 3177 3178 結局これは ble/decode/bind/adjust-uvw で ^H についても同時に上書きする事 3179 にした。これで動いている。adjust-uvw は実際の所、初回呼び出し時だけしか処 3180 理を行わないのでここで多少沢山のコマンドを走らせても困らない。 3181 3182 2023-02-06 一年以上も放置されているのでまた改めて確認する。うーん。どうも少 3183 し弄ったら直った様なのでこれで良い事にする。 3184 3185 * util/idle: background で何が動いているのか分からないので immediate-show で表示する? [#D1945] 3186 3187 オプションで切り替えられる様にする。うるさいので既定では off。 3188 3189 immediate-show で表示していると menu-complete 等他の物が使えなくなるので、 3190 scheme == default の時にだけ ble/util/idle で現在実行中のタスクを表示する。 3191 3192 * info: Emacs の *Messages* の様に後で記録を見返す事ができると良い気がする。 3193 後でログにする事も考えて時刻も含めておく (但しどの様にログにするのかは謎。 3194 info に新しく schene を追加して log という事にして、更に何処かのファイル 3195 にキャッシュとして保存するなど? 何れにしても全然必要性を感じないので今の 3196 所は気にしない事にする)。 3197 3198 * histdb: backup機能 [#D1944] 3199 3200 sqlite3 データベースが破壊される事が実際起こるのか分からないが、消えるとショッ 3201 クなのでバックアップは時々したい。".backup ファイル名" でバックアップを作れ 3202 る様だが、バックアップのファイル名は自分で決める必要がある。またバックアッ 3203 プの頻度も考えたい。取り敢えず終了時に前回のバックアップから時間が経ってい 3204 たらバックアップするという形にするのが良い気がする。前回のバックアップ時刻 3205 はデータベース内部に直接記録してしまって良いのでは。 3206 3207 壊れたファイルで上書きしても駄目なので sqlite3 が壊れていないかのチェックも 3208 行う。チェックに失敗したら警告を発する。データサイズが大きくなってくると 3209 "PRAGMA integrity_check;" は時間がかかるらしい。代わりに "PRAGMA 3210 quick_check;" という物があるらしい。 3211 3212 https://sqlite.org/forum/forumpost/9d9e63a8d4 3213 https://serverfault.com/questions/8048/how-can-i-verify-that-a-sqlite-db3-file-is-valid-consistent 3214 3215 .backup を実行するのと直接コピーするので何が違うのかと思ったが、直接コピー 3216 すると中途半端な transaction のデータもコピーしたり、或いは書き換えながらコ 3217 ピーされたりして壊れるという事。 3218 hourly, daily, weekly, monthly ぐらい backup しておけば十分の気がする。 3219 3220 と思ったが integrity_check を行うのであれば hourly で十分の気がする。或いは 3221 そんなに頻繁に壊れる物でもないと考えれば daily でも良いのかもしれない。 3222 3223 * histdb: sqlite3 のプロセスだけ残ってしまったのをどう始末するか [#D1943] 3224 3225 * sqlite3 のコマンドライン引数に親 pid を含める可能性 3226 3227 考えたが、無駄な文字列を指定できる様な雰囲気はない。と思ったが -cmd を使 3228 えばコメントを指定できるのではないか。然し、その様にしたとしても ps をし 3229 た時に見える様になるだけで、スクリプトから対応する親プロセスを抜き出して 3230 殺すのに使える訳でもない。というか、そもそも sqlite3 のプロセスを列挙する 3231 時点で簡単ではない。なので、これは単に ps をした時に分かりやすいというだ 3232 けの事である。 3233 3234 或いはプロセスツリーで見やすくする為に直接親プロセスから起動して disown 3235 する? と思ったが、やはり無駄なメッセージが表示されてしまう。そもそも、$! 3236 を勝手に書き換えてしまう事になるのでやはり避けたい。 3237 3238 a 別の方法はプロセスを書き込んでおいて他の ble.sh session がそのファイルを 3239 削除する時に中に書かれているプロセス ID に対して kill を送信するという事。 3240 然し、これも pid 記録ファイルの削除のタイミング等によって変な事にならない 3241 かの懸念が残る。 3242 3243 b うーん。或いは。。sqlite3 のプロセス id で run/histdb.$bgpid.ppid という 3244 ファイルを作って置いて、もし run/histdb.$bgpid.ppid に含まれている親プロ 3245 セスが既に存在していなかったらその sqlite3 プロセスは kill する。 3246 3247 c 或いは本当は $$.histdb.pid というファイル名にして中に記録する方が良い様な 3248 気もするが、それだと ble.sh 本体の方の管理によって削除されてしまうので駄 3249 目。或いは、ble.sh 本体の方で *.pid というファイル名だったら中に書かれて 3250 いるプロセスを削除するというルールにしておくという可能性もある。 3251 3252 うーん。その方が今後類似の事をしたいと思った時に consistent に処理できる 3253 様な気がする。 3254 3255 d reject: 別の可能性としては、一つの sqlite3 プロセスを全体で共有するという 3256 可能性? その様にすれば常に一つのインスタンスだけを持っていれば良いし、一 3257 旦起動したら起動しっぱなしで良い気がするので、わざわざ kill しなくても良 3258 い。と思ったが、そうすると今度は stream の同期の問題が出てくる。複数の 3259 query が混ざり合ってしまうともう駄目になってしまう。そもそも同期の問題を 3260 解決する為に sqlite3 を使っているのだから、やはり sqlite3 をセッションご 3261 とに持つのは避けられない。 3262 3263 この b の方法が良い気がする。と思ったが c の方法にする。 3264 3265 * histdb: _ble_histdb_exec_ignore の管理をちゃんとする [#D1942] 3266 3267 現在の実装だと複数の exec lines がある時に最後のコマンドの ignore が最初の 3268 コマンドの ignore として使われる事になってしまっている。 3269 3270 a 毎回判定する事にする? →それだと途中で設定が変更された時に変な事になる。 3271 3272 b 同じ command_id で既に項目が登録されている時にだけ更新する? →無駄にコマ 3273 ンドを発行する事になる気がする。然し、update を使えば該当する項目がない時 3274 には無視されるだけなので、単に request を一回送信するだけである。 3275 3276 これを考えたら単に _ble_histdb_exec_ignore の現在のチェックを削除するだけ 3277 で良い。そもそもよく考えたら session 情報の更新は histdb_ignore に該当し 3278 たとしても行っておくべきだし、何れにしても request は送るのではないか。 3279 3280 c exec line に追加情報を埋め込める様にする? 然し histdb だけの為に専用のフィー 3281 ルドを用意するのは拡張性がよくない (使いたい項目ごとに拡張を行う必要があ 3282 る) し、別の配列に項目を保存するとしてもインデックスの管理などをどうする 3283 のかが分からない。 3284 3285 と思ったが command_id を使って記録すれば良いだけなのでは? そして使ったら 3286 unset する。 3287 3288 結局 c の方針で実装する事にした。結局 ignore されたコマンドに関しては 3289 session 時刻及び cwd も更新されないがそれで良い事にする。 3290 3291 2023-02-05 3292 3293 * histdb: 同じディレクトリの一番最近の履歴を抽出する [#D1941] 3294 3295 有効なファイル名を記録するのよりも先にこちらを実装するべきである。 3296 3297 histdb-history 3298 3299 * ディレクトリが移動した後も追跡できれば追跡する。 3300 3301 ディレクトリの inode を記録するという手もある? 然しファイルシステムが異な 3302 る場合もあるので何とも言えない。別のファイルシステムのディレクトリを掴ん 3303 でしまったら仕方ないので諦める。そもそもディレクトリが移動して元の場所に 3304 ないのであれば別の物を拾っても仕方がない。それを言い出したら一旦ディレク 3305 トリを削除した後に別のディレクトリを移動して持ってきた場合なども考えなけ 3306 ればならなくなる。 3307 3308 と思ったが inode を持っていてもそのディレクトリのパスを取得する方法がない。 3309 ファイルシステム依存で特別のコマンドを走らせれば inode に対応するファイル 3310 名を列挙する事はできるが、一般にはファイルシステムを浚うしかないので単な 3311 る補完の為には現実的に実行できない。 3312 https://stackoverflow.com/questions/14822611/is-there-any-way-that-i-can-search-for-a-file-or-a-filename-using-a-given-inode 3313 3314 可能性があるとしたら移動先のディレクトリでコマンドを実行した事があるとし 3315 たら、inode が一致する物をデータベース内で探して列挙する事はできる。 3316 3317 * うーん。どうやら stat は posix ではないらしい。つまり、inode を取れるか 3318 どうかは分からない。ls -i もあるが、これも明らかに posix ではない。 3319 3320 しかも stat ですら BSD と Linux でオプションの指定方法が異なる。Linux 3321 では stat -c %i file だが BSD では stat -f %i file である。因みに ls 3322 -di file は寧ろ BSD と Linux で同じである。 3323 3324 確認してみた所 ble/file#mtime で既に stat を使っていて -c と -f の判定 3325 も行っていた。取り敢えずこの判定を流用する事にする。 3326 3327 % うーん。track_directory というテーブルを作る事にする。作った。一応登録 3328 % はできている→結局これは使わない事になったので削除した。 3329 3330 一文字コマンド等の自明なコマンドを対象としない。これは histdb_ignore で指定 3331 すれば良さそうな気もするが、実行時間などが気になる場合もあるかもしれないし、 3332 完全なログを後で欲しいという場合もあるかもしれないので、ignore は別に指定で 3333 きる様にするべきかもしれない。つまり、ログに残すかどうかの ignore と補完で 3334 現れるかどうかの ignore は本来は別の物であるのに関わらず元の bash では一緒 3335 くたになっていた (寧ろ元の bash ではログを残すという意味合いは弱くて後でコ 3336 マンドを再利用するというのが目的だったのだから、元の bash で設定ができない 3337 のは理解できる)。 3338 3339 * source:histdb-history で source:history を置き換える? 3340 3341 うーん。それだと .bash_history にあって histdb にない物が表示されなくなる。 3342 また、HISTIGNORE で除去していた物も設定される様になるので不都合があるかも 3343 しれない。strip が HISTCONTROL にある時には strip を実行するべきだろうか? 3344 等色々難しい。そもそも検索時には先頭の空白は無視しても良い気がする…が 3345 sqlite はその様な場合の glob には対応していない。 3346 3347 これの実装は意外と簡単だった。単語補完が難しかったのは実の所、単語の抽出及 3348 び不完全単語のん特定などの処理が難しかったのだという事。 3349 3350 * done: track_directory 登録廃止 3351 3352 一方で、track_directory による inode の検索はそんなに簡単ではない。うーん。 3353 現在ディレクトリで検索して見つからなければ inode で検索して云々としたい所 3354 だが…。うーん。track_directory なるテーブルを作ったのは余り意味がなかっ 3355 た様な気もしてきた。現在いるディレクトリの inode を使って検索すれば良いだ 3356 けなのでは? 元々 track_directory で何をしたかったのかというと、"現在ディ 3357 レクトリ名 → inode の集合" だろうか。然しそれは変である。"inode" は一つ 3358 しか無い筈で、それは現在ディレクトリの inode を参照すれば良い。 3359 3360 結局 command_history に新しく inode カラムを追加してそれを元にして検索する 3361 事にした。 3362 3363 * 2023-01-26 histdb: 形式を変更する時は形式自動アップグレードを実装する [#D1940] 3364 3365 misc/version に基づき行う。ダウングレードが必要ならば代わりにファイル名にバー 3366 ジョン番号を含めて (例: history@chatoyancy.v1.sqlite3) ファイルを開き直す。 3367 3368 正に同じ事 (column がなければ column を追加する) をしようとしている人がいた。 3369 然し、sql query 一発で実行する方法はない様である。 3370 https://stackoverflow.com/questions/56762261/sqlite-how-to-use-select-count-in-case-statement 3371 3372 仕方がないので version を取得してそれを元に upgrade が必要であれば実行する 3373 という事にした。結局これは実装する。実装した。取り敢えず動いている。 3374 3375 * contrib: fzf, bash-preexec などは integration dir に移動する [#D1939] 3376 3377 install 時に symlink を貼る。 3378 3379 古いインストール先を上書きする場合を考えたら symlink でなかったら削除するべ 3380 きでは。→実際にやってみたら timestamp で比較してちゃんと rule が発火するの 3381 で ln -sf で上書きしてしまえばOK。 3382 3383 * histdb: 今までに入力した単語を記録する機能。単語自動補完 (histdb-word) [#D1938] 3384 3385 当初は対応する session_id, exec_id と紐づけて管理する事を考えていたが、其処 3386 までする必要性はあるだろうか。そもそも何故単語を記録するのかというと、補完 3387 で使う為である。そう思ったら、最終使用日時及び使用回数だけ記録すれば良い気 3388 がする。 3389 3390 既存の値から増やすという事を sqlite でするにはどうすればいいのか。と思って 3391 調べてみたら update で既存の値を使った計算式を指定できる様だ。 3392 https://stackoverflow.com/questions/744289/how-to-increase-value-by-a-certain-number 3393 3394 既に登録されていればそれを更新し、そうでなければ新しく挿入する方法は? と思っ 3395 て調べたら色々あるようだ。 3396 https://stackoverflow.com/questions/3634984/insert-if-not-exists-else-update 3397 https://stackoverflow.com/questions/418898/sqlite-upsert-not-insert-or-replace 3398 3399 SQLite-3.24.0 [2018-06-04] で追加された UPSERT という機能が求める機能の気が 3400 する。然し、これは比較的最近の機能なので使えるとは限らない。更に独自拡張な 3401 ので別の sql db では使えない。色々読むと今回の場合は文字列以外は完全に置き 3402 換えるので単に insert or replace で十分の気がする。 3403 3404 2023-02-03 まず最初に newline を実行する前の時点で項目を登録する様にする必 3405 要がある。新しく blehook exec_register を作って、其処から histdb のコマンド 3406 登録を実行する事にした。 3407 3408 * fixed: LINENO の設定と実際の値が変な事になっている気がする。 3409 3410 * fixed: PS1 \# についても更新のタイミングと初期値がおかしい。 3411 3412 * fixed: また、\# は初期値は bash では 1 の様である。然し、現在の実装だと 0 3413 になっている気がする。 3414 3415 * fixed: history_index の値も変である。1 少ない。更に履歴を遡って編集して実 3416 行した場合も変である。histdb_ignore で無視された項目は前の項目よりも次の 3417 項目と同じ履歴番号になるべきである。 3418 3419 取り敢えず実装した。 3420 3421 * fixed: HOSTNAME に / が含まれている時にファイルが作れないのでは。/ は % 3422 に置換する事にした。 3423 3424 更に記録した単語を元にして auto-complete で単語を提示する? 3425 3426 * done: 外部から auto-complete source を追加する枠組みは整えた。 3427 3428 * 現在位置を含む単語を列挙する。これは wbegin を辿っていけば良い筈だが…。 3429 既に類似の事をしている箇所はあるか? 3430 ble/syntax/completion-context/.check-prefix で現在位置が属している単語を 3431 決めている。うーん閉じていない非単語 node の先頭を見つけるのは難しそうだ。 3432 tprev を辿って行って -1 になった所で更に遡って node を見つける? 否、stat 3433 に格納されている nlen を見れば良い気がする。 3434 3435 然し、よく考えてみればそもそも単語の途中にカーソルがいる時に自動補完で単 3436 語として補完するのは変な気がする。特に suffix が続きと一致している時に、 3437 それを skip するのかしないのか。等。(但し skip についてはちゃんと処理して 3438 いるのではないか? ble/complete/insert が処理する) 3439 3440 最後の時点で単語を閉じているのではなかったか? と思ったが syntax_debug を 3441 設定してみてみても単語は閉じていない様だ。単に最後に閉じていない単語のエ 3442 ラーを列挙しているだけ。逆に言えば閉じていない文脈を同様に拾ってその文脈 3443 での単語の開始点を調べれば良いのである。 3444 ble/highlight/layer:syntax/update-error-table の実装を参照すれば良い。 3445 3446 うーん。同様にやってみたが一番上の文脈の情報しか取れない。何故? というか、 3447 同様の処理を実は parse の最後でもやっている様な気がする。何が違うのだろう 3448 か。また、nest-pop を実行する時に tree に登録している様に見えるが、何故そ 3449 れが参照できないのだろうか。 3450 3451 一方で syntax_debug ではちゃんと木構造を再構築できているので何処かには情 3452 報がある筈である。と思ったが tree-enumerate の場合には最初に木構造を閉じ 3453 るための処理を追加で行っていた気がする。→ 3454 ble/syntax/tree-enumerate/.initialize を見たら当にその様な処理を行ってい 3455 た。 3456 3457 * 単純単語の場合にそれがファイル名かどうかを記録する? そうすると最悪単語の 3458 登録数は2倍になる。勿論 simple-word でない物は展開できないので、これは二 3459 倍にはならない。しかし其処までするのも変な気がする。 3460 3461 2023-02-06 words の登録順序が気になる。ちゃんと順序が保たれる様に変更した。 3462 3463 * 5.3: ble/builtin/trap -P [#D1937] 3464 3465 trap に -p と -P の両方が指定されていた場合はどちらが勝つのか? と思ったら両 3466 方指定する事はできませんというエラーになった。ble/builtin/trap でもその様に 3467 実装する。 3468 3469 うーん。builtin trap -P を使ってより効率の良い実装に切り替えようと思ったが、 3470 実際には ble.sh の中では « trap '' xxx » の形になっている事を想定した処理に 3471 なっていた。読み取る時も結局 eval "ble/builtin/$(trap -p INT)" 的な形にして 3472 ble/builtin/trap に委譲して処理している (つまり、eval を使って引数を評価し 3473 ている)。なので今迄通り trap -p を使い続けるので良い気がする。敢えて複雑に 3474 処理を切り替える必要もない。 3475 3476 * 2022-03-19 [対応済み] compat bash-5.2 で \q{...} が動かなくなっている [#D1936] 3477 3478 どうもこれは bleopt の設定時に \ が重複しているのが原因の様だ。表示時の問題 3479 ではなくて本当に値が変わってしまっているという事を確認した。 3480 3481 どうもこれは ${var[@]/%/"=$value"} の振る舞いに関する物の様だ。というかこれ 3482 は既に別に patch を用意した物の気がする。というか既にこの問題を発見してそれ 3483 で修正したという事の気がする。やはり早く patch を提出する事にする。 3484 3485 →これはもう修正を提案して修正されている。現在の 5.2 では何も問題は生じてい 3486 ない。 3487 3488 * 2021-06-12 [対応済み] bash: 開発版 version に関して [#D1935] 3489 3490 実は bash-dev 版は 5.1.xxx の儘推移している。本当は 5.2.xxx-alpha の様な形 3491 にするべきなのではないかという気がする。よく分からない。提案しようかとも思っ 3492 たが実際の所は 5.1.x-maint になっている事から、本来は devel branch は既に出 3493 た version のメンテナンスモードという意味合いだったのかも知れない。然し、こ 3494 の様になっていると次の version かどうかを判定するのに BASH_VERSINFO を利用 3495 する事ができない。今迄は新しい version になる事によって何か機能が減るなどし 3496 て動かなくなるという事はなかったので余り気にならなかったが、"テスト" という 3497 観点から本来は早くに bash-5.2 に増やすべきなのではないかという気がする。 3498 3499 差し当たっての ble.sh の側では release status も見て version を上げる様にす 3500 るのが良いだろうか。と思ったが…。自分はテストの為に release を release に 3501 しているし、逆に maint で動かしているユーザーがいたとしても遅くて使い物にな 3502 らない。自分の relstatus に関してはまた別の値を指定するという手もあるのかも 3503 しれない。と思ったが、それをするぐらいであれば実は configure.ac に於いて 3504 version を 5.2 に書き換えてしまえば良いのである。 3505 3506 2023-02-05 これは一回提案したが自分が決めるんだと言って reject された。仕方 3507 がないんで自分の側で処理する事にする。 3508 3509 * 2021-05-03 [対応済み] 5.2 新機能: READLINE_ARGUMENT [#D1934] 3510 3511 調べてみると引数が存在している時にのみ定義される様である。また今気づいた事 3512 だが -x 属性が入っている。 3513 3514 2023-02-02 3515 3516 * leakvar: いい加減に pending な leakvar fix を入れる [#D1933] 3517 3518 最近の profile.d 変数たちも除外リストに追加する。 3519 3520 * done: key という変数が mshex によって leak している → これは修正した。 3521 3522 j という変数が確率的に leak している。 3523 3524 * ble/syntax/highlight/vartype: ローカル変数を拾っている [#D1932] 3525 3526 declare -p ret (配列), echo ${lookahead} (空変数) などグローバルに存在しな 3527 い変数の属性を拾ってしまっている。 3528 3529 これに対応するには ble/util/print-global-definitions の様にトップレベルの変 3530 数にアクセスする必要があるが subshell 内部で行わないと行けないので問題があ 3531 る。ローカル変数に当たってしまってグローバルを直接見れない時にのみ特別の処 3532 理をするとしても、その判定に ble/variable#is-global 等を呼び出すだけで fork 3533 コストがかかるので既定でこれに対応するのは余り気が進まない。 3534 3535 ? ok: 所で、 ble/util/print-global-definitions の中で呼び出している 3536 ble/variable#is-global は先に declare -g -r してしまっているので、常に真 3537 を返すのではないか。つまり、ローカルかどうかの判定には使えない → と思っ 3538 たが見えている一番上が local readonly であれば global readonly があっても 3539 関係なく新しく local 変数を内側の関数で定義できる様だ。なのでちゃんと判定 3540 する事ができる。 3541 3542 例えば bleopt syntax_ensure_global_variable 等の設定が指定された時にだけ 3543 global 変数の状態を見に行く等? 3544 3545 試しに実装してみたが動かない。readonly にする方式だと ret という変数自体を 3546 新しく定義する事ができなくなるので駄目。結局実装してしまった。うーん。多少 3547 遅くなるかもしれないが気にしない事にする。 3548 3549 2023-02-03 $_ でエラーメッセージが表示される。$$ に対しても readonly からエ 3550 ラーメッセージが表示される。どうも ble/variable#is-global は特別変数に対 3551 して使ったことがなかった様だ。単に stderr を潰す事にした。 3552 3553 2023-02-01 3554 3555 * main: ble-reload が動かなくなっている [#D1931] 3556 3557 "--rcfile=$HOME/.blerc" を指定して再 source しようとして $HOME/.blerc が存 3558 在しない事によって失敗している 3559 3560 * complete: ../ で始まるパスの曖昧補完が効いていない [#D1930] 3561 3562 ../out/data/c2w.wcwidth-compare.musl-vs-12.1.txt[TAB] の曖昧補完が効いていない 3563 3564 どうやら .. を .*.* 等に変換すると .. に一致しなくなってしまう様だ。 3565 ble/complete/source:file/.construct-ambiguous-pathname-pattern を修正したら 3566 すぐ直った。 3567 3568 * canvas: char_width_mode=musl の判定をより正確にする [#D1929] 3569 https://github.com/akinomyoga/ble.sh/issues/269#issuecomment-1407360550 3570 3571 konsole の中で起動すると文字幅スキームが 15.0-musl であると勘違いしている。 3572 何故? 或いは konsole が内部的に musl を使っている可能性? と思ったが、 3573 Unicode 15.0 等もちゃんと認識している。もし本当に musl の実装であれば最新の 3574 Unicode には対応できていない筈。 3575 3576 Refs: #D1880 #D1668 3577 3578 これは fedora でも発生している問題。 3579 3580 * konsole で U+D7B0 の幅が 1 ではなく 2 を返すのが問題の様である。 3581 3582 他の端末の振る舞いを調べる。 3583 3584 * kitty はちゃんと 1 になっていて 15.0-west と判定されている。U+D7B0:U+3099 3585 に対して 1:0 である。 3586 3587 * xterm は 0 を返していて 14.0-west と判定されている。U+D7B0:U+3099 に対し 3588 て 0:0 である。 3589 3590 * terminology は 15.0-west で大丈夫と思ったが、何故か 3099 に対して 2 を返 3591 している。Unicode 15.0 に従っていない気がするが大丈夫なのか? 3592 3593 * lxterminal は U+D7B0:U+3099 に対して 0:0 を返していて 15.0-west になって 3594 いる。 3595 3596 うーん。これらの振る舞いを見るとどの端末も何処か異なる振る舞いをしている。 3597 3598 * というかそもそも ble.sh が使っている musl のテーブル自体も古いという事が 3599 判明した。何処かの野良 github repository から持ってきたが滅茶苦茶古い。こ 3600 れも一緒に更新したい。もしかすると新しい musl では 0 にならないという可能 3601 性もある。確認してみると以下の時点で修正が入っている。 3602 3603 2017-12-18 /src/ctype/{wide,nospacing}.h 3604 2019-10-25 /src/ctype/{wide,nospacing}.h 3605 2020-01-01 /src/ctype/wcwidth.c 3606 2021-12-27 /src/ctype/nospacing.h 3607 3608 % 取り敢えず最新版に更新する事にする。うーん。どうやら D7B0 は以前は幅2だっ 3609 % たが現在は幅 0 の様である。使えない。改めて 3610 % 3611 % $ (source make/canvas.c2w.list-ucsver-detection-codes.sh) 3612 % 3613 % を使ってテーブルを生成してみる。 3614 % 3615 % | -----Unicode EAW+GeneralCategory |musl 3616 % ws[0] U+09FBC | -1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 | 2 3617 % ws[1] U+09FC4 | -1 -1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 | 2 3618 % ws[2] U+031B8 | -1 -1 -1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 | 2 3619 % ws[3] U+0D7B0 | -1 -1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 | 0 (Note: これは結合文字なので xterm/konsole/vte 等で 0 で上書きしている) 3620 % ws[4] U+03099 | 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 | 0 3621 % ws[5] U+09FCD | -1 -1 2 2 2 2 2 -2 2 2 2 2 2 2 2 2 2 | 2 3622 % ws[6] U+1F93B | -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 1 1 1 | 2 3623 % ws[7] U+0312E | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 2 2 | 2 3624 % ws[8] U+0312F | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 2 | 2 3625 % ws[9] U+16FE2 | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 | 2 3626 % ws[10] U+032FF | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 | 2 3627 % ws[11] U+031BB | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 | 1 3628 % ws[12] U+09FFD | -1 -1 2 2 2 2 2 -2 -2 -2 -2 -2 -2 -2 -2 2 2 | 2 3629 % ws[13] U+1B132 | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 | 1 3630 % 3631 % うーん。これを見る限りは musl と Unicode 12.1 の違いはない。プログラムで 3632 % 具体的に Unicode 12.1 との違いを確認する事にする。 3633 % 3634 % $ ./canvas.c2w.wcwidth.exe compare_musl2023 3635 % $ awk '$4 == 0' ../out/data/c2w.wcwidth-compare.musl-vs-12.1.txt 3636 % 00ad wcwidth=1 width(eaw=3,gencat=Cf)=0 0 3637 % 1160..11ff wcwidth=0 width(eaw=1,gencat=Lo)=1 0 3638 % d7b0..d7c6 wcwidth=0 width(eaw=1,gencat=Lo)=1 0 3639 % d7cb..d7fb wcwidth=0 width(eaw=1,gencat=Lo)=1 0 3640 % e007f wcwidth=1 width(eaw=1,gencat=Cf)=0 0 3641 % e01ef wcwidth=1 width(eaw=3,gencat=Mn)=0 0 3642 % 3643 % 最初の四行は他の wcwidth 実装と同じ。なので本質的には最後の2行で区別でき 3644 % る可能性がある。U+E007F はタグをキャンセルするという制御文字。U+E01EF は 3645 % variation selector である。U+E01EF は端末側で特別に処理していると予想され 3646 % るので使うとしたら U+E007f である。 3647 3648 やはりこれを見ると実は musl の最新版は殆ど Unicode と一致している。なので、 3649 敢えて区別する必要もないのではないかと思われる。やはり古い musl を区別す 3650 るのを目的として、musl のテーブルは今まで通り古い musl の物にして、但し、 3651 最近の Unicode を誤って新しい musl と判定しない様に判定の調整を行う。 3652 3653 と言っても konsole が変な振る舞いをしているだけなので気にしなくて良いかも 3654 しれない。 3655 3656 * konsole の wcwidth がどの様に振る舞うのかについてちゃんと調べて判定できれば判定する 3657 3658 更に調べてみると konsole は konsole_wcwidth という関数を持っているらしい。 3659 https://api.kde.org/legacy/4.12-api/applications-apidocs/konsole/html/konsole__wcwidth_8h_source.html 3660 と思ったが現在の konsole には konsole_wcwidth という関数は存在しない。テス 3661 トコードのコメント内にはあるので、恐らく昔は実際にそういう関数が存在した。 3662 改めて konsole_wcwidth を検索してみると11年前のコードなどが当たる。kde-4.12 3663 で検索してみると 2013年12月の記事が出てくる。なので、純粋に古いのだろう。見 3664 つけた。現在のコードは以下にある。 3665 3666 https://github.com/KDE/konsole/blob/master/src/characters/CharacterWidth.src.cpp テンプレート 3667 https://github.com/KDE/konsole/blob/master/src/characters/CharacterWidth.cpp 生成結果 3668 3669 そして幅のテーブルを生成しているコードは以下にある。 3670 3671 https://github.com/KDE/konsole/blob/master/tools/uni2characterwidth/uni2characterwidth.cpp 3672 3673 うーん。konsole の幅スキームまでテーブルを埋め込んで対応するのは大変だ。 3674 しかも version が変わる度に変更される。 3675 3676 分かった。どうやら以下のファイルによって U+D7B0 の幅が上書きされている? 然 3677 し、結果として 2 になっている理由は謎。 3678 3679 https://github.com/KDE/konsole/blob/master/tools/uni2characterwidth/overrides.txt 3680 https://github.com/KDE/konsole/commit/cfff2326f98e1077c519bbb8d18c80262d1e2d1b 導入コミット 3681 3682 うーん。konsole_wcwidth の文字幅を Unicode の文字幅と比べると以下の差分が 3683 ある。wcwidth の段階では U+D7B0 は幅0の様である。つまり、konsole は 3684 grapheme clusters に対応していてそれでハングルだと判定して文字幅2にしてい 3685 るという事だろうか。U+D7B0 は Unicode 6.1 の判定に使われている。代わりに 3686 別の文字にしたらこういう変な事が起こらないで済むだろうか? 3687 3688 $ ./canvas.c2w.wcwidth.exe compare_konsole2023 3689 $ awk '$4==0' ../out/data/c2w.wcwidth-compare.konsole2023-vs-15.0.txt 3690 00ad wcwidth=1 width(eaw=3,gencat=Cf)=0 0 3691 1160..11ff wcwidth=0 width(eaw=1,gencat=Lo)=1 0 3692 d7b0..d7c6 wcwidth=0 width(eaw=1,gencat=Lo)=1 0 3693 d7cb..d7fb wcwidth=0 width(eaw=1,gencat=Lo)=1 0 3694 1f1e6..1f1ff wcwidth=2 width(eaw=1,gencat=So)=1 0 3695 3696 調べてみると Unicode 6.1 で新しく変更された幅は全てハングル関係である。然 3697 し、これらは恐らく全て konsole のハングルの実装によって幅2になってしまう 3698 と予想される。一方でこれらの文字は musl でも全て 2 になっている。つまり、 3699 どの文字を Unicode 6.1 に選んだとしても musl の判定には使えないという事に 3700 なる。 3701 3702 * unicode version も参照して musl を判定する事にする。 3703 3704 うーん。本当に musl2014 の場合には unicode version 判定の時点で特定の ver 3705 になるはずなので、それも一緒に確認する事で musl を判定するのが正しい気が 3706 する。 3707 3708 musl は判定用文字幅は以下のようになっている。 3709 3710 $ ./canvas.c2w.wcwidth.exe vector_musl2014 3711 ws[0]=1 # U+25BD 3712 ws[1]=1 # U+25B6 3713 ws[2]=2 # U+9FBC 3714 ws[3]=2 # U+9FC4 3715 ws[4]=2 # U+31B8 3716 ws[5]=2 # U+D7B0 3717 ws[6]=0 # U+3099 3718 ws[7]=2 # U+9FCD 3719 ws[8]=1 # U+1F93B 3720 ws[9]=1 # U+312E 3721 ws[10]=1 # U+312F 3722 ws[11]=1 # U+16FE2 3723 ws[12]=1 # U+32FF 3724 ws[13]=1 # U+31BB 3725 ws[14]=2 # U+9FFD 3726 ws[15]=1 # U+1B132 3727 3728 これに基づくと char_width_version=10.0 になる。なので 10.0 の時にだけ 3729 musl と判定する事にした。 3730 3731 2023-01-31 3732 3733 * decode: bash-4.4 以下で補完が全く起動されない [#D1928] 3734 3735 cygwin で completion を起動しようとすると固まる。何故? 3736 最近の変更が原因かもしれない。確認する必要がある。 3737 3738 そもそも complete が全く呼び出されていない。色々試してみたがそもそもキー入 3739 力がちゃんと通っていない気がする。 3740 3741 auto-complete 候補が出ていても出ていなくても関係ない。 3742 3743 どうも 138c476 の前後で振る舞いが変わっている。+o posix を追加すると問題が 3744 再現する。どうもそもそも $_ble_bash_options_adjusted が有効になっていない状 3745 態で .hook が呼び出されている。然し、それもなぜだか分からない。 3746 3747 Linux でも bash-4.4 以下で再現する。 3748 3749 うーん。分かって来た。set +o posix すると complete が bash の complete に変 3750 わってしまう。ここで readline のコマンドラインは空なのでコマンド名補完が行 3751 われる。no_empty_cmd_completion off にしているので、そのまま全てのコマンド 3752 の補完を処理しようとして固まる。 3753 3754 set +o posix は実際に変化がある時にのみ実行するべきである。 3755 3756 2023-01-30 3757 3758 * main: 空の LANG に対して警告を表示する (movivated by Ultra980) [#D1927] 3759 https://github.com/akinomyoga/ble.sh/issues/269 3760 3761 文字幅計算がずれる。空の LANG なのに starship&terminal が UTF-8 を想定して 3762 いる。 3763 3764 * main: openSUSE inputrc.keys は強制的に排除する? (motivated by Ultra980) [#D1926] 3765 https://github.com/akinomyoga/ble.sh/issues/268 3766 3767 これが何度も問題を起こしている。 3768 3769 a 最早強制的に off にしても良いのではないか。 3770 3771 b 或いは自前で ~/.inputrc だけ読み取る事にする。 3772 3773 元々 --noinputrc は最早 inputrc とは関係なく bind の出力を plain Bash と 3774 diff を取ってユーザー設定を復元している。という事を考えたらどの方式でユー 3775 ザー設定を復元するかをオプションで選べる様にしても良いのではないか。 3776 3777 --inputrc={none,user,all,diff} 3778 3779 c 或いは、デフォルトとの bind diff を取った後で比較するのではなくて、仮に 3780 ble-bind で全部登録した後の状態で diff を取って残った物だけ採用する? と思っ 3781 たがこれだと問題は解決しない。 3782 3783 と思ったら既に opensuse では振る舞いを変える様になっていた。今までは 3784 https://github.com/openSUSE/aaa_base/pull/84 の修正が入っているかどうかで問 3785 題があるか判定していた気がするが、もう inputrc.keys が存在する時点で問題が 3786 あると判定する事にする。 3787 3788 2023-02-02 実際に openSUSE で試してみたらエラーメッセージが色々表示されてし 3789 まう。改めて確認したところ --inputrc=auto に対する処理で openSUSE での既定 3790 の方法が誤っていた。修正した。 3791 3792 2023-01-26 3793 3794 * 2021-05-17 histdb: 履歴が余りに消滅するので ble.sh の側で独立した履歴の仕組みを作りたい [#D1925] 3795 3796 * 然し何処に履歴ファイルを置くのかという問題がある。 3797 3798 a 今日日、~/.ble_history 的なファイルを置くのは憚られる。 3799 3800 b .cache には消えても良い物を置くべきだから置くなという話もあれば、 3801 3802 c .config はユーザー設定に纏わる物で dotfiles に入れている人もいるから勝手 3803 に書き込まないで欲しいという話もある。 3804 3805 d 結局、.local/share/blesh/xxxx に置く事になるのだろうか。まあ、 3806 .local/share/blesh/data 辺りに置いて置けば良いだろう。然しその為には更に 3807 新しいディレクトリを生成する必要がある。現在は _ble_base, cache, run の三 3808 種類のディレクトリがある。 3809 3810 →これは XDG_STATE_HOME (~/.local/state) 以下に保存する事にする。 3811 3812 履歴はどの様に記録するのが良いか。日付は unix time で記録するのが人間に分か 3813 る様に記録するのか。カレントディレクトリも記録したいし、存在する相対パスも 3814 記録したい。所で存在する相対パスはどの様にして抽出するのが良いのだろうか。 3815 単語着色の時に検知した物を何処かに記録しておく必要がある。 3816 3817 2023-01-25 同期等面倒だし、sqlite3 形式で記録する可能性について考える。既に 3818 atuin 等、他の類似のフレームワークも sqlite を使っている。 3819 3820 * sqlite3 / SQL の使い方 3821 3822 基本的な使い方は以下のページが分かりやすかった。ページが分割されていてペー 3823 ジを移動しにくいが。 3824 3825 https://www.javadrive.jp/sqlite/ 3826 3827 * sqlite3: 直前に挿入した項目の番号は last_insert_rowid() で取得できる。 3828 3829 * sqlite3: シェル側で処理できる様に複数の値を出力する方法は? 3830 NUL-terminatedで出力できるのが望ましい。 3831 3832 以下のページによると NUL separated でデータを読み取る事はできないらしい? 3833 https://www.reddit.com/r/sqlite/comments/a9xort/help_please_cli_line_null_separated/ 3834 3835 以下のページはデータ自体に NUL が含まれている時にどうするかだがこれも微妙に難しいらしい。 3836 https://sqlite-users.sqlite.narkive.com/mMwpNBzZ/getting-text-data-w-embedded-nulls-from-shell 3837 3838 sqlite3 --help |& grep output を実行すると色々使えそうなオプションはある。 3839 3840 * 然し、-newline '\000' 等とすると実際に '\000' という文字列が 3841 separatorとして使われてしまう。或いは -newline __ble_sep__ 等としてそ 3842 れを別のプログラムで置換すれば良い気もするが、大量のデータの場合に全 3843 てが一行に繋がった状態で読み込まれてそれを分割する事になり、効率が気 3844 になる。 3845 3846 * -newline '' も試してみたが、これだと単にデータが separator なしでくっつ 3847 いてしまう。 3848 3849 * -ascii は RS か何かを分割文字として使ってくれるが、それでも RS 自体がデー 3850 タに含まれる場合に困る。 3851 3852 * -quote は sqlite3 の文字リテラル方式で quote してくれる物である。今の 3853 所、これを用いて処理するのが現実的の気がする。-html, -json, -csv, 3854 etc でも独自の方法で曖昧でない様に quote してくれると思われる 3855 が、-quote の方式に比べると規則が複雑になる。 3856 3857 awk で行を読み込んだら 1) 先頭の ' を削除する 2) '' を先頭から順に ' 3858 に置換して行って、一番最後に単独 ' が残っていれば OK. そうでなければ 3859 LFを追加して次の行を読み込んで同様に '' を置換していく。最後に単独 ' 3860 が残っているのをどの様に判定するのかはよく分からない。或いは置換する 3861 前に ' の数を数えて偶数か奇数かで判定する可能性。或いは、最初に末尾の 3862 ' の数を数えて奇数か偶数かを判定する可能性。こちらの方が現実的の様な 3863 気がする。つまり、match(/'+$/, $0) で一致しておいて、RLENGTH が偶数か 3864 奇数かで判定する。以下の様に書けば NUL-separated に変換する事ができる 3865 気がする。 3866 3867 awk ' 3868 { 3869 if (line == "" && sub(/^'/, "") == 0) { 3870 # NULL や数値など 3871 printf("%s%c", $0, 0); 3872 next; 3873 } 3874 3875 if (match(/'+$/, $0) && RLENGTH % 2 == 1) { 3876 sub(/'$/, ""); 3877 line = line $0; 3878 gub(/''/, "'", line); 3879 printf("%s%c", line, 0); 3880 line = ""; 3881 } else { 3882 line = line $0 "\n"; 3883 } 3884 } 3885 ' 3886 3887 * 履歴項目として何を記録するか。 3888 3889 - done: session_id, exec_id, cmd, cwd, start_time, end_time, 各種時刻情報, 3890 $?, $!, $_, PIPESTATUS 3891 3892 - done: user, hostname 等の情報は session_id の方で登録するべきの気がする。 3893 3894 - 記録するべきか微妙な物: BASHOPTS/$- (before/after), ret (after), $@ 3895 (before/after), 背景ジョブ情報 3896 3897 * 関連プロジェクトの情報も集める。これは review として note.txt の上部に残 3898 しておく事にする。 3899 3900 * hook point 3901 3902 素朴には PREEXEC 及び POSTEXEC にて項目を登録 & update すれば良い。一方で、 3903 単語情報やファイル名情報も一緒に記録するのだとしたら、文法情報が消滅する 3904 前に登録しておく必要がある。 3905 3906 a ADDHISTORY を通して記録するのが良いだろうか。その為には 3907 ble/widget/default/accept-line に於いて ble/history/add の位置を移動す 3908 る必要がある。今は histexpand の結果を表示してから ble/history/add をし 3909 ている。然し、histexpand の結果を表示するよりも前に newline を実行しな 3910 ければならず、その時点で文法情報などは失われている。なので、newline を 3911 実行する前に ble/history/add を呼び出す様に変更した方が良いだろうか。 3912 3913 然し、ble/history/add で更に何かを出力する可能性があるのであれば、やは 3914 りそれより前に newline を実行しておく必要があるので使えない。現在の所は 3915 ble/history/add で直接何かを出力するという事はない様である。一方で、 3916 ADDHISTORY を呼び出したら失敗があるという事。 3917 3918 そもそもよく考えてみたら ADDHISTORY は文法情報等とは関係ない気がする。然 3919 し、一方で history の一環として登録するという意味においてやはり history 3920 とは切り離せない。 history.sh を拡張する形で実装するのだとしたらやはり 3921 ADDHISTORYを通して介入するのは自然である。 3922 3923 そうは言っても新しい history の枠組みは既存の history とは全く異なる物で 3924 あって、現在の entry point だけでは不十分である。寧ろ様々な箇所で介入が必 3925 要な気がする。という事を考えると、やはり ADDHISTORY とは別に hook を作成 3926 するべきなのだろうか。 3927 3928 →改めて考えてみたが単に ble/history/add を newline の前に移動しても問題 3929 ない気がしてきた。ADDHISTORY から何かメッセージを標準出力に出す可能性につ 3930 いては、特に有効な使い道も思い浮かばない (とは言いつつ、現状では未だ 3931 ADDHISTORY のタイミングで呼び出しておく必要のある情報など記録していないの 3932 で気にしなくて良い気がする)。 3933 3934 * 速度について 3935 3936 もう一つの懸念点は、この設計だと最低でも ADDHISTORY, PREEXEC, POSTEXEC の 3937 三回の sqlite3 呼び出しが必要になる。 3938 3939 或いは ADDHISTORY の時点で sqlite3 に渡す sql 文を部分的に生成して置いて 3940 その時点では sqlite3 は呼び出さない。sql 文を exec の枠組みの中で保持して 3941 おいて、更に PREEXEC で sql 文を追加した後に呼び出すという形の方が良いか 3942 もしれない。 3943 3944 因みにどういった種類の情報を記録するのかについては現在の文法言語 (現在は 3945 基本的に "bash" しかないが) に依存している。文法言語ごとに指定できる様に 3946 するのが良い気がする。table 名として syntax_bash_filename だとか 3947 syntax_bash_word 等が良い気がする。 3948 3949 長いコマンドの実行中に bash (もしくはコンピュータ全体) がクラッシュする場 3950 合等を考えたら PREEXEC と POSTEXEC は両方とも sqlite3 を呼び出しておくべ 3951 きだろう。 3952 3953 →実際に実装してみた所、PREEXEC, POSTEXEC だけでも結構遅くなる。時間を計 3954 測してみるとそれぞれの呼び出しで 0.070 程度の時間がかかっている。合計で 3955 0.140 である。0.140 ならば短い様な気がしたが実際に sleep 0.140 を実行して 3956 みると確かに遅い。 3957 3958 という事を考えると coproc (bash-4.0) もしくは procsubst を用いて bg で 3959 sqlite3 を実行する必要があるのではないか。以下で coproc で sqlite3 を実行 3960 する事について書かれている。一応技術的には可能の様である。 3961 https://hackerpublicradio.org/eps/hpr3413/full_shownotes.html 3962 3963 もしこれを実装するのだとしたら ADDHISTORY, PREEXEC, POSTEXEC の全てで実行 3964 するというのは別に大変という訳でもない。 3965 3966 →取り敢えず名前付きパイプを用いて実装してみた。どうやら期待どおりに動い 3967 ている様な気がする。stdbuf を使わなくてもその場で応答してくれている。速度 3968 は挿入時に 0.060s ぐらいかかっているが使っている感じだと余り意識しなくて 3969 済む。この 0.060 かかっているのは恐らく rowid の読み取りの為。 3970 3971 うーん。既に非同期にしてしまったので rowid を読み取らなくても直接 3972 (session_id, exec_id) で指定して挿入してしまって良いのではないか→その様 3973 にしたら待ち時間は全くなくなった。rowid は再配置等が途中で起こった時に変 3974 な事になる可能性があるので、今回の様にちゃんと一意のIDで指定できる様にす 3975 るのは大切な事である。 3976 3977 * done: BLE_SESSION_ID などを公開する。これらは contrib/histdb 側ではなくて 3978 ble.sh の方で設定するべきではないか。 3979 3980 コマンド番号については BLE_COMMAND_ID で公開する。BLE_COMMAND_ID は 3981 _ble_edit_CMD を公開する形にし、また reload で減少しない様に対処する。 3982 3983 * done: start_time -> issue_time in TABLE command_history 3984 3985 * done: exec_id と command_id は役割が重複していないか? 3986 3987 _ble_edit_CMD は gexec prologue で increment されている。一方で exec_id 3988 も同様に PREEXEC で increment されている。 3989 3990 * done: また、万が一 command_id が重複した時に何が起こるのかについて考えて 3991 おく必要がある。うーん。以前のコマンドの情報が上書きされて消えてしまうと 3992 いう事の気がする。消えない様に調整などは可能だろうか。 3993 3994 a 例えば session 名を変更する等? 然し、その必要があったという事を外側に伝 3995 える必要がある。或いは、上書きされてしまっても仕方がないと諦める事にす 3996 るか。或いは、既に存在する場合には元々あった方を無難な session に変更す 3997 る等? 3998 3999 b 或いは command_id を何か中途半端な値に書き換える。順番が分からなくなる 4000 と思ったが何れにしても時刻は記録しているので必要があれば時刻を用いて並 4001 び替えるしかない。例えば既存の項目に対して command_id を使われていない 4002 最小の負の値に書き換えるなど。 4003 4004 取り敢えず b の方法を実装してみた。実際にそれを起こすのは大変の気がする。 4005 手で直接 db を弄れば行ける → 実際に重複が起こる様にして試してみたところ 4006 ちゃんと期待通りに動いている。 4007 4008 * done: 将来の history の形式の変更に備えて history_format_version を埋め込 4009 む。misc table でも作って置けば良い。TABLE misc(key, value) に version と 4010 いう項目を入れて整数値で version を指定する事にした。 4011 4012 将来的に形式を変更する暁には version を増やして、また初期化時に version 4013 が小さい場合にはアップグレードし、version が大きい場合には明示的に 4014 version をファイル名に入れてファイルを開き直す。これはその時になってから 4015 また考えれば良い。 4016 4017 * done: sqlite3 を nfs の上で使うと何が起こるのか? 4018 4019 やはり駄目な事になってしまう様である。NFS の設定によってはちゃんと動くけ 4020 れども、恐らくパフォーマンス上の問題から、普通は安全側に倒した設定にはなっ 4021 ていないと考えるべきである。 4022 4023 https://techblog.raccoon.ne.jp/archives/1635140633.html 4024 4025 となるとホスト毎に history を保持するべきの気がする。流石にホスト名に関し 4026 ては重複している場合は考えなくて良いだろう。 4027 4028 NFSv4 は AFS (Andrew file system) の影響を受けてよりファイルロックに関し 4029 て良い振る舞いをするらしいがよく分からない。 4030 4031 →ホスト名を履歴ファイル名に含める事にした。 4032 4033 ? done: HISTIGNORE に一致するコマンドは履歴に登録するべきなのだろうか? 4034 4035 a 登録するべきでない気がする。やはり既存の bash_history の拡張という考え 4036 方だとしたら HISTIGNORE 等の取り扱いにちゃんと従っていて欲しい。そう考 4037 えると preexec ではなく ADDHISTORY で全て追加するべきだろうか。然し、 4038 ADDHISTORY に介入するとしても、別の ADDHISTORY hook によって追加がキャ 4039 ンセルされたという場合も考えられる。また、加工した物を history -s で追 4040 加している場合等も考えると単純にはキャンセルされたかどうか判定できない。 4041 4042 b reject: うーん。ADDHISTORY によるキャンセルは考慮せず、ADDHISTORY に到 4043 達したら問答無用で追加するという事で良い様な気がする。また、現在は 4044 start_time と exec_time_beg を別々に管理しているので start_time は 4045 ADDHISTORY の段階で設定してしまって問題ないのである。一方で、issue のタ 4046 イミングと exec のタイミングがちゃんと交互になっていない場合にどうする 4047 のかについては注意が必要。 4048 4049 c これについては bleopt histdb_ignore で独立な設定として管理して貰うのが 4050 良い気がしてきた。HISTCONTROL の影響も受けない (例えば ignoredups 等に 4051 よって最近のコマンドと同じコマンドだったら履歴には追加しないという振る 4052 舞いも、様々な情報を記録する場合には余り望ましい物ではない)。 4053 4054 うーん。変更の方針としては ble/history/add の時点で histdb の更新も行う。 4055 但し、複数の履歴が絡んでいる事が考えられるので gexec に登録すると分かって 4056 いる時にだけこれを実行する。その時点で _ble_edit_CMD の更新も行う。実行は 4057 ADDHISTORY 経由ではなくて必ず呼び出す事にして、独自に bleopt 4058 histdb_ignore 等の処理を行う。exec の枠組みに対しては exec_id を渡す事に 4059 する。 4060 4061 * done: sqlite3 のプロセスが死んだ時にどうするのか? 4062 4063 毎回 kill で生存確認するのが良い気がする。何れにしても sqlite3 がクラッシュ 4064 すればその親の subshell の bash はすぐに終了するはずなので $! で取ったプ 4065 ロセス ID で生存確認すれば良い。或いは、exec を実行してしまえば $! が直接 4066 sqlite3 になる筈。 4067 4068 * done: last_wd を session に記録する。後でフィルタするのに役立つ。通常は最 4069 初は home で始まって、最後のディレクトリが実際の作業ディレクトリだから。 4070 last_time も記録する。 4071 4072 * reject: coproc による実装 4073 4074 * うーん。coproc は同時に複数起動できないという説が出回っている。 4075 https://lists.gnu.org/archive/html/help-bash/2023-01/msg00181.html 4076 4077 それならば何故変数名を指定できるのか 4078 4079 →うーん。どうもジョブ管理 or exit status の追跡という意味で同時に複数 4080 管理できないというだけであって、同時に複数起動する事自体ができない訳で 4081 はない様な気がする。しかし、そもそも coproc で起動したプロセスをどの様 4082 に管理するのか、どの範囲まで成業できるのかというのが不明である。そもそ 4083 も、現在裏で走っている coproc を閉じる方法はあるのだろうか。 4084 4085 うーん。どうも fd を開放してしまえば coproc が生きている等のエラーは表 4086 示されない様である。勿論、ちゃんと fd を (親プロセス内で) dup して他の 4087 fd として保持しておく必要があるが、その為には coproc は親プロセスで実行 4088 する必要があって、そうすると bash の foreground dead job の振る舞いによっ 4089 て sqlite の項目が表示されてしまう事になる。或いは 4090 __ble_suppress_joblist__ さえ含めておけば問題なく行けるのだろうか。 4091 4092 技術的には可能の様に思われる。 4093 4094 * Cygwin 上では (もしくは bash-5.0 以降では) coproc を使った実装に切り替 4095 える? disown しておけば問題は起こらないだろうか? その場合には親シェルで 4096 coproc を実行する必要がある。fd を取得する為に。或いは coproc で生成し 4097 たジョブの中で更に & を開始して、ジョブ自体は即終了するという手もある。 4098 4099 % 取り敢えず cygwin 上で試してみる事にする。動いている。named pipe は動 4100 % かないけれども coproc は動くという事? 或いは named pipe も実は今は動 4101 % く様になっている可能性? 4102 % 4103 % →今 cygwin を試してみたら実は named pipe でも動く様になっていた。つ 4104 % まり、coproc が動くからと言って昔の bash/cygwin でも coproc が動いた 4105 % かどうかというのは保証がない。他の cygwin/mingw も動作を確認する。 4106 % MinGW 64bit で試してみてもちゃんと動く。cygwin 32bit でも動く。もしか 4107 % すると動かないのは process substitution の時だけだろうか? うーん。 4108 % process substitution でも動く。 4109 % 4110 % 改めて Qiita の記事を確認してみたら動かないのは exec 9<> fifo; read 4111 % -t <&9 をした時である。先に書き出しの側のプロセスを起動しておけば問題 4112 % ない。つまり、今回は先に必ず sqlite3 のプロセスを起動しているので問題 4113 % は起こらない筈なのである。 4114 4115 つまり fifo による実装は Cygwin でも問題なく動く筈なので敢えて Cygwin 4116 で除外する理由もない。msys2 では動くが msys1 では動かないという問題に関 4117 しては、msys1 では mkfifo の時点で失敗するのでそれを以て判定する事がで 4118 きる。 4119 4120 よく考えたら既にユーザーが coproc を作成している時に coproc を開いてしま 4121 うとユーザーが作成した coproc が閉じられてしまって大変な事になる。かと言っ 4122 てサブシェルで coproc を作ってもその fd を親シェルに渡す方法がない。と考 4123 えると fifo に頼らざるを得ない。 4124 4125 * done: 途中でデータベースファイルを切り替えられる様にする。 4126 4127 処理中の exec がある時に切り替えると変な事になるので全て完了した時点で切 4128 り替えを完了させる。通常は複数の exec が設定される事はないので実際上の問 4129 題が生じるかは分からないが。 4130 4131 対応した。 4132 4133 2023-01-24 4134 4135 * [自然解消] 2022-02-03 complete: 補完している時に勝手に変数の中身が展開されてしまう事がある [#D1924] 4136 4137 展開する条件をより制限する事はできないか。或いは、展開せずに置換できるパター 4138 ンを増やす。 4139 4140 最たる場合が echo $_ble_base_cache/mandb[TAB] である。曖昧一致によって遡っ 4141 て置換が起こるが、それによって変数展開の中身まで展開されてしまう。少なくと 4142 も / で区切ってできるだけ展開せずに一致する様にできないだろうか。 4143 4144 ? 曖昧一致に於いて変数展開から得られた文字列は塊で取り扱う? 4145 4146 というかよく考えたら変数の中身に対してまで曖昧一致で一致させるのは変な気 4147 がする。曖昧一致は元の原始的な構成要素に対しては塊で一致する様にするべき 4148 なのではないか。と思ったが 'aaa' の中身の様にユーザーが手で入力した内容に 4149 ついてはやはり曖昧一致であって欲しい。という事を考えると曖昧一致で塊とす 4150 るとしてもその対象は変数展開だけに限られてくるのではないか。 4151 4152 2023-01-24 #D1923 で曖昧一致によって遡って書き換わって展開される場合につい 4153 て対応した。勝手に変数の中身が展開されるパターンがこれだけなのかは分からな 4154 いが、取り敢えずは解決した事にする。暫く使って勝手に展開されてしまう他のケー 4155 スに気づいたらその時に新しく項目を立てて対応する事にする。 4156 4157 * complete: パス名の曖昧補間でできるだけ各種展開を保持したい [#D1923] 4158 4159 現在の実装では quote-insert で生成候補が COMPV に文字列を追加した物の場合に 4160 は COMPV の部分については COMPS で置き換える様になっている。しかし、遡った 4161 置換がある場合には問答無用で全体が展開されてしまうので、曖昧補間が起こった 4162 時には必ず全体が展開されてしまう。 4163 4164 COMPS を unquoted / 毎に切って、eval して対応する部分 compv を生成して、最 4165 長一致するものについて部分 comps で置き換える。unquote / 毎に切るのは個別の 4166 quote-insert でやっていたら大変なので、事前に処理しておく事にする。 4167 4168 quote-insert.batch で awk で処理する場合にどうするのかについては微妙。awk 4169 の内部で unquote / 毎に切るのを実装するか或いは外で切ったものを何とかして 4170 awk に渡すかする。外で定義したものを渡す方が見通しが良いと思われる。 4171 4172 ToDo 2022-02-03 に関連項目がある → #D1924 4173 4174 unquoted / で区切るのは既存の 4175 ble/syntax:bash/simple-word/evaluate-path-spec をそのまま使えば良い。 4176 4177 * reject: あらゆる単語について判定を行うと大変なので CAND が既存のファイル 4178 名に一致する時にだけチェックをおこなう? 未だ存在しないファイル名を候補と 4179 して生成する可能性はあるだろうか。例えば Makefile target 等。うー 4180 ん。-o$HOME/ 等の様に short option の optarg として指定している場合等も考 4181 えたら例え存在していなかったとしても一致するかのチェックはするべきの気が 4182 する。 4183 4184 うーん。fixed part との兼ね合いがどうなるのか分からない。取り敢えず 4185 evaluate-path-spec は noglob で呼び出す事にしてチルダ展開・パラメータ展開等 4186 文脈に依存しない物のみを実行する事にする (コマンド置換、算術展開などは元よ 4187 り simple-word ではないので対象ではない)。 4188 4189 ? quote-insert.initialize で実行するべきか或いは COMPV を評価する時点で 4190 evaluate-path-spec で展開しておくべきか → COMPV を評価する時点で同時に評 4191 価してしまうべきの気がしてきた。 4192 4193 結局 fixed part を拡張する形で実装する事にした。既存の変数である 4194 comps_fixed 及び quote_fixed_comp{s,v}{,_len} 等を配列に拡張して第1要素以降 4195 に部分パスの展開前・展開後を格納する事にする。 4196 4197 実装した。取り敢えずは動いている気がする。 4198 4199 * 2023-01-02 complete: コマンド名(パス名)の曖昧補間・部分一致など [#D1922] 4200 4201 現在の実装だと PATH に見つかっているコマンドについては曖昧補間が有効である 4202 が、パスを指定して補完している時にはそれが無効になっている。関数名について 4203 は / が入っていてもちゃんと生成できている。 4204 4205 補完対象に / が含まれている場合にはファイル名補完と同様にパターンで候補生成 4206 を行って、その結果を [[ -x file ]] でフィルタする様にするべきなのではないか。 4207 4208 ? ok: チルダ展開が展開されてしまう。調べてみると compgen -c の場合にはちゃ 4209 んと ~ が保持される。なので、おそらくチルダ展開の復元などを処理していなかっ 4210 たのだろう。 4211 4212 実はディレクトリ名に関しても同様に処理する必要があったのでは。 4213 4214 →何故展開されるのかについて調べてみたら ~ を復元するのは $CAND == 4215 "$COMPV"* の時だけだが、曖昧補完の時にはこれが常に不成立の為に復元しない 4216 という事。これに真面目に対応しようと思ったら COMPS を unquoted / 毎に切っ 4217 て、eval して対応する部分 compv を生成して、最長一致するものについて部分 4218 comps で置き換えるという処理にする必要がある。これは面倒である。 4219 4220 そして、これについては通常引数の曖昧補間についても同様にチルダ展開が展開 4221 されてしまう。もし対応するとしたらまとめて対応する必要がある。これは独立 4222 した項目にする事にした。 4223 4224 4225 2022-12-13 4226 4227 * fzf-completion: ファイル名に付く suffix の判定ができていない (reported by qoreQyaS) [#D1921] 4228 https://github.com/akinomyoga/ble.sh/issues/264 4229 4230 結局問題は ble/syntax-raw で fzf にファイル名を渡しているので結果として生成 4231 される物が、必ずしもそのままでファイル名になっているとは限らないのが原因だっ 4232 た。 4233 4234 [原因解明] 4235 4236 bash-completion & fzf & ble.sh の組み合わせで再現する事を確認した。色々調べ 4237 た所、単に以下の補完設定でも ble.sh だと問題が再現する。 4238 4239 function _test2a { 4240 compopt -o filenames 4241 COMPREPLY=("~/opt") 4242 } 4243 complete -F _test2a test2a 4244 4245 ble.sh の中の動作を調べると ble/complete/action:file/complete 迄期待通りに 4246 呼び出されているが、そこで分かった。~/が定義されていないのである。 4247 4248 ? ok: fzf の補完で ~ が直接渡って suffix が付かなくなるのは良いとしても、不 4249 思議なのは普通の補完で同様の修正が働かない理由である。そもそも ~/opt は 4250 /home/murase/o に変換してから補完が走る設計にしていた様な気がする。何故 ~ 4251 が直接補完関数に渡っているのだろうか?? 4252 4253 と思ったがよく考えたらテストの問題である。問題再現の為に直接 4254 COMPREPLY=('~/opt') の様にしていただけで、実際に COMP_LINE や COMP_WORDS 4255 に '~' が含まれていた訳では無い。 4256 4257 [修正] 4258 4259 取り敢えず ble/syntax-raw の時にはその場でパス名展開を試行してファイル名か 4260 どうかの判定を実行する事にする。 4261 4262 4263 ? 存在しないファイル名がある時に nullglob で消えてしまうのでは。これだと一 4264 番最後の単語でない物を拾ってテストしてしまう可能性がある。 4265 4266 こういった設定を変更しないでできるパス名展開は存在しただろうか。と思った 4267 が util の eval-pathname-expansion は元からその様な物だった。 4268 4269 * reject: comp_opts の値を記録する事を考える。或いは、DATA は progcomp の時 4270 には常に comp_opts だと仮定して良いのだろうか。と思ったが、駄目。progcomp 4271 のものに関しては問題が起こらないが、それ以外で生成された物について DATA 4272 は別のものを含んでいるので、直接 DATA を読み取っていると誤作動の原因にな 4273 る。 4274 4275 或いはそれが progcomp によって生成された物であるかどうかを判定する方法は 4276 あるのか。確認した所、action=progcomp らしい。action=mandb もあるような気 4277 がしたがそれは source:mandb から生成された物だけの様である。更に、 4278 action=mandb で出てきた物はファイル名ではないのは明らかなので、やはり除外 4279 しても良い。 4280 4281 progcomp から出てくる物は action=progcomp であると仮定して良い。 4282 4283 実装した。動いている。auto-complete の場合でもちゃんと / が挿入される。 4284 4285 x fixed: と思ったが menu-complete の着色の為にファイル名を判定している所で 4286 結局同様にファイル名の判定に失敗して全てが赤くなっている。これにも対応す 4287 る必要がある気がする。 4288 4289 これについても修正を行った。ファイル名取得の処理を共通化して、そしたら簡 4290 単だった。 4291 4292 ? 生成される物が eval した後にファイル名になるという事を仮定しているが本当 4293 にそう思って良いのだろうか。元の bash の振る舞いでは空白が入っていたとし 4294 ても -o filename を指定したら quote してくれるみたいな事になっていたりは 4295 しないのか? 4296 4297 x bash の振る舞いについて確認する事にする。更にそもそも不用意に eval して良 4298 いのかという問題がある。コマンド置換など含まれていたらどうするのか。 4299 syntax/simple-word で判定してから eval するべきなのではないか。 4300 4301 チルダ展開だけを実行するためにはどうしたら良いか。ble/widget/tilde-expand 4302 を確認してみた所、これは command line に含まれる物に対する作用だったので、 4303 単に syntax 情報を参照していた。 4304 4305 コマンド置換が含まれていたらチルダ展開は諦めると思ったがコマンド置換が含 4306 まれていたとしても、結局は quote されるので inactive である。取り敢えずチ 4307 ルダ展開だけ試みるというのが正しい動作の気がする。という事を考えると、最 4308 初がチルダであって次の / までに何か特別な文字が含まれていない時に限ってチ 4309 ルダ展開を試みるという処置が必要である。 4310 4311 先ず最初に作った以下のコードは全て棄却である。 4312 4313 | local -a dtor=() 4314 | if shopt -q nullglob; then 4315 | shopt -u nullglob 4316 | ble/array#push dtor 'shopt -s nullglob' 4317 | fi 4318 | if shopt -q failglob; then 4319 | shopt -u failglob 4320 | ble/array#push dtor 'shopt -s failglob' 4321 | fi 4322 | 4323 | # Note: 一番最後の文字の直後の文脈を知りたいので、末尾に '' を追加して評価 4324 | # してから最後の単語を抜き出す。 4325 | if ble/util/eval-pathname-expansion "$file''" && ((${#ret[@]})); then 4326 | file=${ret[${#ret[@]}-1]} 4327 | else 4328 | file= 4329 | fi 4330 | 4331 | ble/util/invoke-hook dtor 4332 4333 実装し直した。動作確認する。動いている。auto-complete もOK。menu-complete 4334 もOK。その他の微妙なファイル名でも bash と同様に動作する事を確認した。 4335 4336 * bind: M-C-@ が正しく捕まえられていない気がする [#D1920] 4337 4338 bind -s で確認するとマクロ置換後の C-@ が消滅している。これは単にマクロが内 4339 部的に null-terminated string で表現されている為である。 4340 4341 更に同様の状況を考えてみると C-x C-@ も正しく検出できていない。また M-C-x 4342 (in bash-4.2, emacs binding) もその瞬間に検出できていなくて遅延が生じる。実 4343 際にその場で入力を検出できていないという事を確認した。 4344 4345 取り敢えず M-C-@, C-x C-@, M-C-x (bash-4.2 -o emacs) を修正した。 4346 4347 ? reject: これは bash の側で修正するべきなのだろうか? 然し、bash は null 4348 terminated な raw string でマクロを補完していて、これを変更するのは難しい 4349 し其処までする理由もない様な気がする。取り敢えずは現在の workaround を保 4350 持して、bash には何も要求しない方向が妥当の気がする。 4351 4352 * highlight: パス名着色において ls_colors が動いていなかった (reported by qoreQyaS) [#D1919] 4353 https://github.com/akinomyoga/ble.sh/issues/263 4354 4355 どうも type=g:* の形で指定した後にそれを外側で g に反映させる事になっている 4356 のが反映させていなかったのが問題であった。いつ壊れたのか確認した。3f1f472d 4357 #D1095 で type == g:* の時の特別の処理が削除されている。実に3年半も動かない 4358 状態で放置されていた事になる。 4359 4360 ディレクトリ名に関しては単純に今まで対応していなかった。 4361 4362 ble/syntax/highlight/ls_colors の値の返し方自体を変更する事にした。この関数 4363 は今迄二箇所でしか呼び出していなくて、両方で呼び出し側で同様に色の合成など 4364 を行っていたので、その色の合成も ble/syntax/highlight/ls_colors に統合する 4365 事にした。そして直接に g に書き込む様に振る舞いを変更した。その上で / の前 4366 のディレクトリ名の ls_colors による着色にも対応した。動いている。 4367 4368 2022-12-11 4369 4370 * colorglass: オプションで指定した時に256色(またはより少ない色に)に減色する機能? [#D1918] 4371 4372 →よく考えたら bleopt term_true_colors が設定されていなければ自動的に減色さ 4373 れるのではないか。実際に実装を確認してみた所そうなっている。この事を 4374 colorglass の説明に書いておくべきではないか? → 記述した。これで十分である。 4375 4376 * README: RET や C-RET 等について 3.1.1 及び 3.3.6 に対するリンクを含めておく [#D1917] 4377 https://github.com/akinomyoga/ble.sh/issues/262 4378 4379 取り敢えずリンクと説明を書いた。 4380 4381 * _ble_term_TERM (comment): wezterm の commit id は 8 文字では足りない (requested by SuperSandro2000) [#D1916] 4382 https://github.com/akinomyoga/ble.sh/commit/486564ad314cef3f95317e88cf26879378dae507 4383 4384 うーん。行(特に120列)に収まり切らない様な気がするが面倒なので気にしない事にする。 4385 4386 * github/workflows: 何故か grep が windows-latest でクラッシュする [#D1915] 4387 4388 別のリポジトリで試しに実行してみたがやはり再現する。最終的に以下の単純な 4389 workflow の定義ですらクラッシュするという事が分かった。 4390 4391 ---- .github/workflows/build.yml ------ 4392 name: grep-in-windows 4393 on: 4394 push: 4395 branches: 4396 - master 4397 4398 jobs: 4399 check: 4400 runs-on: windows-latest 4401 steps: 4402 - name: Check out 4403 uses: actions/checkout@v3 4404 - name: Check 4405 run: echo 'GNU Awk' | grep -Fi 'GNU Awk' 4406 --------------------------------------- 4407 4408 grep -i や grep -F だけでは問題は発生しない。 grep -Fi や grep -F -i 等、-F 4409 と -i を組み合わせた時にクラッシュする様だ。grep の version は GNU grep 3.0 4410 (2017) の様である。よく分からないが面倒なので grep を使わずに実装する事にす 4411 る。head -1 による処理も一緒に sed で処理すれば良い。 4412 4413 2022-12-08 4414 4415 * ble-reload した時に M-z が効かなくなる [#D1914] 4416 4417 何とそもそも ble-reload にて blerc が読み込まれていない。確認してみると 4418 --rcfile=/dev/null という事になっている。何も指定していない時には 4419 _ble_base_arguments_rcfile は空になっている。なので空の時にはやはり何も指定 4420 せずに source ble.sh するべきであって、何か特定の blerc は指定しない様にす 4421 る。 4422 4423 ? 或いはもしかすると元々指定したかったのは _ble_base_rcfile ではないか? 4424 うーん。そんな気がする→その様に修正した。 4425 4426 * 2021-09-08 complete: sabbrev (magic-space) vs auto-complete [#D1913] 4427 4428 auto-complete で履歴から候補が表示されている時には sabbrev が効かない。そも 4429 そも sabbrev 展開が発生するかどうかも分からないので毎回 auto-complete を抜 4430 けるというのも変な感じがする。理想的には sabbrev が起こった場合は再び 4431 auto-complete を実行し、sabbrev が起こらなかった時には従来の auto-complete 4432 と同様にカーソル位置を一つ進める事を試行する。 4433 4434 うーん。この問題は自動候補の先頭文字が空白の時にのみ起こる。それ以外の時に 4435 は auto-complete を抜けて再度 SP が実行されるのでちゃんと sabbrev も呼び出 4436 される。 4437 4438 2022-12-09 然しそもそも一つ上の keymap で SP に magic-space が割り当てられ 4439 ているのかどうかも非自明である。うーん。やはり SP に対しては一旦 4440 auto-complete を抜けるのが自然な気がする。 4441 4442 或いは一つ上の keymap の SP に magic-space が割り当てられているかどうか判定 4443 する? うーん。ESC に関してはひとつ上の keymap の情報を参照している物があっ 4444 た様な気もするが何だったか。うーん。ESC や M- で検索しても関係ありそうな物 4445 は見つからない。→分かった。bleopt decode_isolated_esc=auto の処理である。 4446 decode.sh の ble/decode/uses-isolated-esc で判定が行われている。 4447 4448 さて実際に magic-space に bind されているという事が分かったとして、どの様に 4449 処理するべきか。その場でいきなり magic-space を呼び出す事を考えたが、そうす 4450 ると auto-complete によって補正されている内容が壊れてしまう。特に 4451 _ble_edit_mark 等の位置も変わってしまう可能性がある。また、magic-space は現 4452 在の keymap を見て振る舞いを変えているので一旦 auto-complete から抜けるか抜 4453 けたふりをする必要がある。色々考えるとやはり本当に一旦抜けて通常の状態に戻っ 4454 てから処理するべきの気がする。 4455 4456 →その様に修正した。 4457 4458 x 今度は magic-space による空白挿入の後に auto-complete が再開しない。よく 4459 考えたら self-insert は登録しているけれども magic-space に関しては登録し 4460 ていない。登録するべき気がする。登録した。試した。ちゃんと期待どおりに動 4461 いている。 4462 4463 * 2021-02-28 magic-space で alias 展開する機能があっても良いのでは? (requested by telometto) [#D1912] 4464 4465 というか magic-space で何を展開するかの集合を設定できる様にするべき? 4466 bleopt edit_magic_expand=sabbrev:history:alias という具合に。 4467 流石にコマンド置換等まで展開するのはやりすぎの様に思われる。 4468 4469 2022-12-08 https://github.com/akinomyoga/ble.sh/discussions/260 4470 4471 まず最初に bleopt を実装する事にする。実装した。 4472 4473 alias expansion についても sabbrev expansion を元にして実装した。 4474 4475 ? ok: ところで他の discussion でも同様の物があった様な気がする。 4476 4477 https://github.com/akinomyoga/ble.sh/discussions/138 4478 4479 ここにある。と思ったが、これは alias expansion ではなくて、magic-space を 4480 コマンド実行時にも呼び出すという話なのだった。というかこの項目が todo に 4481 なかったので新しく項目を作って置く事にした。と思ったら項目自体はあって単 4482 に GitHub#138 へのリンクが記録されていなかっただけだった。 4483 4484 x auto-complete が有効になっていると ' ' が magic-space として働かない。 4485 →これは別に項目が存在していた筈なので別に処理する事にする。 4486 4487 * done: blerc/wiki: bleopt edit_magic_expand の説明。 4488 4489 * 2022-12-03 menu-complete: 一時挿入をしない設定 (requested by DUOLabs333) [#D1911] 4490 https://github.com/akinomyoga/ble.sh/discussions/252#discussioncomment-4293518 4491 4492 * done: complete_auto_after_complete はやはり廃止してより一般のオプションと 4493 して complete_auto_complete_opts=suppress-after-complete とする事にした。 4494 4495 * done: blerc/wiki: update complete_auto_complete_opts 4496 4497 * done: blerc/wiki: add complete_menu_complete_opts 4498 4499 * done: temp-insert -> insert-selection 4500 4501 取り敢えず動いている気がする。多分大丈夫。 4502 4503 * 2022-10-04 refactor(edit): 適当な一時ファイルを作っているのを assign/.mktmp に置き換える [#D1910] 4504 4505 暫く dev にあって邪魔なので些末な修正に過ぎないがもう master に入れる事にす 4506 る。他には特にその場で生成してその場で使用済みになるファイルは存在していな 4507 い様な気がするのでOK。 4508 4509 * term: wezterm が DA2 を変えている。対応する [#D1909] 4510 4511 DA2R が 1;277;0 になっている。xterm との区別ができない気がする。うーん。或 4512 いは 277 だったら wezterm に決め打ちにする? しかし、wezterm である事を利用 4513 しているのは、現状ではどうやら DECSCUSR に対応しているかどうかの判定のみで 4514 ある。然し、xterm も元々 DECSCUSR に対応しているので、その意味でわざわざ 4515 1;277;0 (xterm:277) を wezterm と敢えて判定する必要もない。 4516 4517 念の為、現状での wezterm の DA2 の変更履歴について確認する。 4518 4519 コミット [1] (2022-04-07) で今迄の "0;0;0" から "1;277;0" に変更している。 4520 wezterm のバージョンはどうやら日付と時刻の様である。取り敢えず 4521 _ble_term_TERM では日付だけ考える事にする。このコミットは 20220408 のバージョ 4522 ンで最初に入っている。どうやら vim でマウスを使う為の変更の様である。 4523 4524 [1] https://github.com/wez/wezterm/commit/ad91e3776808507cbef9e6d758b89d7ca92a4c7e 4525 4526 * contrib/fzf-key-bindings: C-r で呼び出した fzf で modifyOtherKeys の状態が変 (reported by SuperSandro2000) [#D1908] 4527 https://github.com/akinomyoga/ble.sh/issues/259 4528 4529 xterm ですらちゃんと動いていない。以前はちゃんと動いていた筈なので 4530 regression の可能性が高い。うーん。ちゃんと hook はできている。つまり、 4531 modifyOtherKeys のシーケンス自体を正しく出力できていない可能性? 内部でどの 4532 ように設定しているかを出力しつつ振る舞いを調べる必要がある。 4533 4534 * うーん。今振る舞いを確認してみた所、xterm でも CSI >4;1m を指定した後で 4535 C-x であっても特殊なシーケンスを送るという事が判明した。うーん。もしかし 4536 て xterm は昔から 4;1 で C-x に対して特殊なシーケンスを送っていたという事 4537 なのだろうか? xterm -v の結果は 371 である。改めて他の xterm についても調 4538 べてみる事にする。 4539 4540 * xterm 322 では 4;1 の時 C-p は通常のシーケンスを送信していた。 4541 4542 * と思ったら直接 xterm 371 を起動して \e[>4;1m を指定しても特に変な事は起こ 4543 らない。うーん。別の箇所で何か modifyOtherKeys が変更されている可能性? 4544 4545 うーんわかった。ble/util/buffer にキャッシュされていて端末に対して出力さ 4546 れていない状態だった。修正した。 4547 4548 2022-12-05 4549 4550 * README: fzf-integration について記述する (motivated by SuperSandro2000, tbagrel1) [#D1907] 4551 https://github.com/akinomyoga/ble.sh/issues/259 4552 https://github.com/akinomyoga/ble.sh/issues/261#issuecomment-1346450426 4553 4554 * display-shell-version にも integration が入っていない時にメッセージを表示 4555 する様にする。fzf についてはメッセージを出力した。 4556 4557 その他 (bash-preexec, zoxide) については必要になった時点で自動的にロードさ 4558 れる事になっているので、その場で未だロードされていなくてもそのままにしてお 4559 く事にする。と思ったが zoxide がない。 4560 4561 * done: zoxide についても情報を表示する事にする。 4562 4563 zoxide の初期化スクリプトで一番古い関数は何だろうか。 4564 4565 __zoxide_hook は以下のコミット (2020-09-16) で _zoxide_hook から改名され 4566 ている。この関数は最新版の zoxide でも存在している。 4567 4568 https://github.com/ajeetdsouza/zoxide/commit/f4525db02fde1efa77f56f9f50b27cc1830d4912 4569 4570 _zoxide_hook は以下のコミット (2020-03-13) で導入されている。 4571 4572 https://github.com/ajeetdsouza/zoxide/commit/9c8e8da71a03f5c3c070247f5b0bffd971a70f62 4573 4574 _zoxide_precmd は以下のコミット (2020-03-11) で追加されている。これが 4575 bash 対応の最初と思われる。 4576 4577 https://github.com/ajeetdsouza/zoxide/commit/f0c5e28fd7e56d7cec045a40154ab4768339da44 4578 4579 取り敢えず __zoxide_hook を使って判定する事にする。 4580 4581 * done: 動作を確認してみた所 _z という関数が存在しない。つまり、zoxide の側 4582 で変更があったという事だろうか。以下のコミット (2021-12-29 v0.8.1..) によ 4583 ると _z から __zoxide_z_complete に改名された様である。 4584 4585 https://github.com/ajeetdsouza/zoxide/commit/d106f4e3580d5594d8f1c96c256a8f085e2781a4 4586 4587 2022-12-13 更に bash_completion を先にロードしておくべきという事についても 4588 記述した。 4589 4590 * colorglass: saturation (彩度) についての設定を追加する (motivated by auwsom) [#D1906] 4591 https://github.com/akinomyoga/ble.sh/issues/258 4592 4593 24-bit color のサポートがない時には256色に減色する機能もつけようと思ったが 4594 自動で検出するのは困難である。既定で256色にして指定した時にだけ256色にする 4595 というのだと、既定では色が思うように変化しなかったり急に変わったりして使い 4596 にくくなる。指定した時にだけ256色に減色するというのもありかもしれないが、其 4597 処までする必要は今の所は感じられない。→取り敢えず項目は作る事にした。 4598 4599 * fixed: contrast -100..100 の境界値も許容する様に修正した。 4600 4601 * fixed: 色がすぐに PS1 に反映されない問題を修正した。trace_hash に 4602 clear-g2sgr cache の回数を含める事にする。 4603 4604 * reject: ble-face で face 設定を変更した時にも clear-g2sgr を呼び出す事に 4605 する? それ程頻繁に変更する事もないので大丈夫だろう 4606 4607 x と思ったが face -> g に関しては毎回完全に計算していてキャッシュしていな 4608 いので g2sgr キャッシュをクリアする必要もない。特に g2sgr は重くなる可 4609 能性があるので余り頻繁にクリアはしたくない。実際に vim-airline が編集す 4610 る度に face を変更しているのでこれでキャッシュをクリアするのは割に合わ 4611 ない。 4612 4613 * それよりはプロンプトの計算が face に依存しているのにプロンプトのキャッ 4614 シュがクリアされないという所が face 更新における問題である。vim-airline 4615 の時には背景色を変更していたが背景色は _ble_lib_vim_airline_mode という 4616 変数で決まっており、更にこの変数は prompt/unit の枠組み経由で更新してい 4617 た。なので何れにしてもプロンプトが更新されるので気にしなくても良かった。 4618 4619 * done: brightness についても対応した。 4620 4621 2022-12-03 4622 4623 * README: bashrc 設定の背景に対するリンクを載せる (motivated by telometto) [#D1905] 4624 https://github.com/akinomyoga/ble.sh/discussions/254#discussioncomment-4284757 4625 4626 日本語の説明はないが仕方がない。 4627 4628 * contrib/README: PATH に fzf が見つかれば _ble_contrib_fzf_base は設定しなくて良い (reported by Strykar) [#D1904] 4629 https://github.com/akinomyoga/blesh-contrib/issues/9 4630 4631 修正した。というか手動で指定したとしても fzf を PATH の中に見つける事ができ 4632 なければ結局動かないのではないか? と思ったが fzf-initialize の中にちゃんと 4633 PATH を追加する処理が組み込まれていた。 4634 4635 と思ったが、存在しないディレクトリを追加していたりしないか? →している。こ 4636 れはディレクトリが存在する時にだけ PATH に追加する事にした。 4637 4638 * prompt: bind 'set show-mode-in-prompt on' が何故か PS1 の後に表示される? (reported by Strykar) [#D1903] 4639 https://github.com/akinomyoga/ble.sh/discussions/256 4640 https://github.com/akinomyoga/ble.sh/discussions/257 4641 4642 実際に試してみるとそうなっている。変なミスである。。。修正した。 4643 4644 2022-12-01 4645 4646 * contrib/colorglass: 実験的に実装したものを追加する事にした [#D1902] 4647 少なくともこれでテーマを自分で作るのが以前よりは簡単になった気がする。 4648 但し調整の仕方は普通のユーザーに対しては少々難しいかもしれない。 4649 同時に自分でフィルターを設定できる様にもする。 4650 4651 * complete: TAB completion の直後でも auto-complete が表示されるのは変だ (reported by DUOLabs333) [#D1901] 4652 https://github.com/akinomyoga/ble.sh/discussions/252 4653 4654 * done: うーん。確かに言われてみれば変な気がする。これは単にバグの気がする。 4655 調べてみる。 4656 4657 ble/complete/auto-complete.idle では _ble_decode_widget_last が 4658 self-insert 等の時にだけ auto-complete が実行される事になっているが、よく 4659 見ると ble/widget/complete または ble/widget/vi_imap/complete の時にも明 4660 示的に auto-complete を誘起する様になっている。これには理由があったのだっ 4661 たか。 4662 4663 関係しているのは 63ddeffd #D0736 と 6081e0a9 "complete: support "bleopt 4664 complete_ac_delay"" (議論なし?) である。うーん。周辺の議論を確認したが、 4665 やはり関係する議論はないし、done.txt で delay についても mention されてい 4666 ない。次の項目番号が #D0727 で auto-complete が導入されたのが #D0724 なの 4667 で、#D0725 か #D0726 以前のどちらかが関係していそうだが、どちらも異なる。 4668 4669 うーん。やはり当初から意図した振る舞いの様な気がしてきた。少なくとも使って 4670 いて問題が起こった事はない。menu-complete に入れば当然モード判定があるので 4671 勝手に auto-complete が混ざって変な事になるという事もない。うーん。オプショ 4672 ンを追加する事にする。実装した。 4673 4674 * done: blerc.template 4675 * done: wiki 4676 4677 ? reject: 既定値を変更するべきか。うーん。少し使ってみる事にする。うーん。 4678 考えて見るにこれを有効にしていたのは単語補完ではなく過去の履歴に自動補完 4679 で一致する可能性を残しておきたかったからだと思われる。一律で無効にしてし 4680 まうと履歴に依るコマンド挿入ができなくなってしまい不便なことがあるかもし 4681 れない。元々明示的に有効にしていたのは他にもそれなりの理由があったのでは 4682 ないかという気がする。というか delay の導入と一緒に導入されていたのだから、 4683 待っていたらコマンド履歴による補完が起動しそうだという期待があったからか 4684 もしれない。更に続く #D0736 では vi でも同様に動く様にわざわざ変更してい 4685 る。そもそも表示していても別に問題はない気がするのでやはり既定では補完を 4686 実行する事にする。 4687 4688 * complete: `#advice: _parse_usage is not a function.` というエラーメッセージ (reported by nik312123) [#D1900] 4689 https://github.com/akinomyoga/ble.sh/issues/251 4690 4691 bash_completion の新しい version を使っていると発生するのかもしれない。と思っ 4692 たがそうでもなかった。まだこれらの関数は bash_completion の内部で改名されて 4693 いない。つまり、_parse_help や _longopt を勝手に定義しているが _parse_usage 4694 を定義していない外部の補完ライブラリが存在する。 4695 4696 ? no: もしくは、古い bash_completion には _parse_usage は存在していなかった? 4697 と思って調べてみたが _parse_usage も _parse_help も bash_completion 4698 68f6f1c68 で同時に導入されているので片方だけが定義されていたという時期は 4699 存在しない様に思われる。 4700 4701 何れにしても _parse_help という関数を勝手に定義する場合を考えると、勝手に他 4702 の関数も定義されていると想定する訳には行かない。単にエラーを suppress する 4703 事にした。 4704 4705 * 2022-10-24 rename to blerc.template [#D1899] 4706 https://github.com/akinomyoga/ble.sh/issues/244#issuecomment-1288439503 4707 4708 書きぶりから blerc を直接編集すれば良いと勘違いしているのかもしれないと思っ 4709 たが別にそういう事ではなかった。しかし、それでも勘違いする人がいるかもしれ 4710 ないので blerc のファイル名を変える事にした。blerc.template という名前にし 4711 ておけば直接編集すれば良いと勘違いする人もいないだろう。 4712 4713 README の該当する部分も更新する。wiki には言及されていない様なので更新しな 4714 くて良い。 4715 4716 * 何処かでリンクされていたのに対して通知した方が良いかもしれない。 4717 4718 * 2022-10-24 複数 widget を実行したい時: Q&A や wiki にも説明を書く (motivated by micimize) [#D1898] 4719 https://github.com/akinomyoga/ble.sh/discussions/241#discussioncomment-3937949 4720 4721 * done: wiki の Q&A を編集した。 4722 4723 README では直接説明をしているが、特に他の部分には記述しない事にした。 4724 4725 というより [編集関数の作成] が wiki における主要な解説部分だが英語版がない。 4726 然し翻訳するのも面倒だし今回の質問のレベルだとこれ全体を翻訳する程のことで 4727 はない。将来的にそういった細かい仕様についての質問が出てきた時に翻訳すれば 4728 良い気がしている。 4729 4730 * 2022-10-24 cancel line by C-c in vi mode (motivated by micimize) [#D1897] 4731 https://github.com/akinomyoga/ble.sh/discussions/241 4732 4733 * done: C-c in blerc 4734 * done: gg & G in blerc 4735 4736 * 2022-10-24 delete word by M-backspace (motivated by KiaraGrouwstra) [#D1896] 4737 https://github.com/akinomyoga/ble.sh/issues/243 4738 4739 * done: blerc に追記した for emacs 4740 4741 * done: vi_imap rlfunc の更新 4742 4743 後 vi_imap の backward-kill-word が widget:kill-backward-uword になってい 4744 たが実際に plain bash で動作を確認する限りはやはり emacs と同じ様に 4745 widget:kill-backward-cword になっている気がする。実際に試してみても uword 4746 は振る舞いが異なる。vi_imap での対応を変更する事にした。 4747 4748 * done: blerc 追記 for vi 4749 4750 2022-11-28 4751 4752 * posix: sh --login at MinGW で沢山エラーメッセージが出て segfault (reported by rashil2000) [#D1895] 4753 https://github.com/akinomyoga/ble.sh/issues/237 4754 4755 % どうも set +p posix してもその効果が次の実行時に消滅するのが原因の様だ。 4756 % Linux などで sh --login をしても再現しない。Cygwin では再現した。Cygwin 4757 % と MinGW だけで今のところ再現している。 4758 4759 取り敢えず set +ev している箇所で +o posix も指定したら問題は発生しなくなる 4760 様である。と思ったが MinGW では問題は起こらなくなるものの Cygwin では依然と 4761 して駄目だった。manual attach でも prompt attach でも Cygwin では動かない。 4762 4763 →何と sh --login で起動した場合は起動時には non posix だがその後で posix 4764 に変化する様だ。 4765 4766 * 一方で Linux で問題が発生していなかったのは単に bashrc が読み込まれていな 4767 かった為である。 4768 4769 また、PROMPT_COMMAND の中から set +o posix した時には問題が生じていない様 4770 にも見える。然し実際に prompt attach を実行してみると問題が生じる。追加で 4771 PROMPT_COMMAND で set +o posix を設定すると問題は生じなくなる。 4772 PROMPT_COMMAND における set +o posix の位置を attach よりも後に変更してみ 4773 ると問題が発生する。 4774 4775 うーん。何らかの瞬間に adjust bash options の制御が変になっている可能性? 4776 そもそも adjust-POSIXLY_CORRECT の呼び出しにまで至っていない気がする。こ 4777 れはユーザーコマンドを実行する瞬間に呼び出される。 4778 4779 1 うーん。元々 ble-attach でもちゃんと adjust は呼び出しているが、そもそ 4780 も既に adjusted の状態になっている為にわざわざ adjust を実行していない 4781 という事の様だ。 4782 4783 そして source ble.sh の時点で調整に入っているのでその後での変更に対して 4784 ちゃんと確認しなくても良いという判断である。というかこれだとユーザーが 4785 自分で set -o posix を設定した時にも問題になる。代わりに他の 4786 bash-options と同じタイミングで restore/adjust するべきなのではないか。 4787 4788 →と思って確認してみた所ちゃんと restore している気がする。と思ったがど 4789 うやら条件判定に失敗して restore がちゃんとされていなかった様だ。これを 4790 直したらちゃんと動く様になった。 4791 4792 % 2 また、何故かこの時点で既に posix モードではなくなっている。或いは関数 4793 % の中でだけ posix モードが自動で消えるなどの仕組みがあるのだろうか。と 4794 % 思ったら単に確認用のスクリプトが間違っていた。 4795 4796 * ble-attach を明示的に呼び出した時にも現在の対策だけで動くのだろうか。或い 4797 は +ev と同様に改めて設定する必要があるだろうか。 4798 4799 % うーん。そもそも +ev と同じ箇所で再調整をしたとしても失敗している。 4800 % segfault する。.hook とは別の場所で調整する必要がある? 取り敢えず 4801 % ble-attach は無事に完了している事は確認した。問題は何処で一番最初に 4802 % ble.sh の処理に突入するかという事である。自然に考えると .hook の筈であ 4803 % る。 4804 4805 →と思ったら単に +ev している箇所が二箇所あったというだけであった。修正し 4806 たら segfault も直った。つまり、何れにしてもこの処理は必要になるという事 4807 である。 4808 4809 * もしこれが問題なのだとすると以前の修正で +ev としていたのは不要だったので 4810 はないか? と思ったが +ev の設定に関しては source ble.sh してから変わると 4811 も思えないし、関係ない? 或いは+ev が必要になったのはユーザーが自分で -ev 4812 を指定した時? 4813 4814 51113237 #D1832 の説明を読むと、これは寧ろ ble-attach を明示的に指定した 4815 時の問題であって、今回の restore し忘れの問題は関係ない。何れにしても 4816 restore はしないのだ。bash -e で起動すると bashrc の読み込み後に設定が変 4817 わるという事の様に見える。なのでやはり必要な気がする。 4818 4819 何れにしても上の項目で +o posix は実行する必要があると判明したので +ev も 4820 保持するのは確定である。 4821 4822 * 2022-10-13 ble/canvas/trace: rps1 の位置の問題 (reported by rashil2000) [#D1894] 4823 https://github.com/akinomyoga/ble.sh/issues/239 4824 4825 * どうも gbox の計算にバグがある。\nworld を指定すると高さ1になっている。 4826 foo\nworld はちゃんと2になっている。というかそもそも終点 x,yの時点でバグ 4827 がある。 4828 4829 PS1 でも同じ様な事が起こるのではないかと思ったがそういう訳でもない。 4830 relative にすると駄目という事なのか。或いは measure-gbox の時にのみ起こる 4831 事なのか。或いは right alignment によって変な事が起こっているのか。align 4832 right が怪しい。 4833 4834 ? invalid: 何と rps1 の中でデバグの為に状態を /dev/tty に出力しようとする 4835 とクラッシュする。history に何かを追加しようとしているが謎 → と思った 4836 が typo で failglob を発生させていた。つまり変な所で ble.sh の動作がク 4837 ラッシュしていたのが原因の気がする。 4838 4839 \n\nbar に対して振る舞いを見てみるとどうも行番号 y がリセットされている様 4840 である。このリセットは最初の \n に対してのみ発生する様である。\n の呼び出 4841 し回数に関しては問題ない。 4842 4843 どうも2回目の end-line の呼び出しの際に y が 1 から 0 に戻ってしまう様だ。 4844 4845 見つけた。どうも最初の行の情報を消去せずに early return している所為で2行 4846 目が1行目と勘違いして処理されている様であった。ちゃんと最初の行の情報をク 4847 リアする様にしたら問題なく動く様になった。というかこれで完全に動く様になっ 4848 たのではないか。 4849 4850 取り敢えずこの問題に対する対処は此処までとする。 4851 4852 * done: テストを追加する。追加した。以前は失敗して今回は成功する事を確認し 4853 た。 4854 4855 * done: 然し starship での問題が完全に解決したかどうかは分からない。そもそ 4856 も被っている場合には rps1 は表示されないのでは? 実際の環境で確認する必要 4857 がある。 4858 4859 % →結局どの環境で以前試したのか分からない。と思ったら chatoyancy の 4860 % ble.sh の中に issue239 という名前のディレクトリがあってそこでテストを実 4861 % 行していた。 4862 4863 新しく chatoyancy 上で再現させて動作確認もした。取り敢えずちゃんと設定す 4864 れば動く。 4865 4866 * 2022-10-28 edit: display-shell-version を直接実行できる様にする (reported by DhruvaG2000) [#D1893] 4867 https://github.com/akinomyoga/ble.sh/issues/246#issuecomment-1294843777 4868 4869 直接 ble/widget/display-shell-version を実行すれば良い。C-x C-v が 4870 効かない端末でもOK。例えば報告者の環境では C-v が「貼り付け」に奪 4871 われていた。 4872 4873 * done: 直接実行しても表示が壊れない様に ble/widget/print を修正した。 4874 * done: issue template を修正した。 4875 * reject: wiki に関しては確認してみたがそもそも C-x C-v の指示も書 4876 いていなかった。敢えてここで新しく解説を追加する必要もない気がす 4877 る。 4878 4879 * 2022-10-28 edit: display-shell-version で git/gmake/gawk の情報を表示 [#D1892] 4880 https://github.com/akinomyoga/ble.sh/issues/246#issuecomment-1294893636 4881 4882 git, gmake 及び gawk の version も表示する? 変な生成のされ方をして 4883 いないか確認する時にこの情報があった方が良い。 4884 4885 これは生成に用いた物の version なので生成時に埋め込むべきの気がする。 4886 4887 * 2022-10-13 github/workflows について (reported by Harduex) [#D1891] 4888 https://github.com/akinomyoga/ble.sh/pull/240 4889 4890 ? cpio -pd を使えば良いのではないか。と思ったが cpio がどのシステム 4891 でも使えるとは限らないし、そもそも cpio のオプションとして何が使え 4892 るかもシステムに依存するのかもしれない。という事でやはり cpio に依 4893 存するというのは避けたい。結局 POSIX cpio には -p はないみたいなの 4894 で (むしろ異なる意味のオプションの様である) GNU cpio の non-POSIX 4895 option を使うのだったら、そもそも GNU tar の -x を使うところなので 4896 ある。 4897 4898 →改めて ble.pp を見てみたら cp -Rf を使っている。これに倣う事にした。 4899 4900 * それとは別に現在 ble-nightly* としているディレクトリ名を何とかした 4901 い。 4902 4903 a done: うーん。そもそも ble-nightly でダウンロードする人は細かい 4904 version 等を気にするとは思えないし、そうでなくとも標準的な手順に 4905 従うと結局ディレクトリの version 名は移動した時に失われてしまう。 4906 なので、初めから単に ble-nightly というディレクトリにしてしまえ 4907 ば良い気がする。→ 変える事にした。 4908 4909 b ユーザーに直接ディレクトリ名を指定させる? しかしそうするとしても 4910 ディレクトリ名は毎回変わるし commit id が含まれているので README 4911 に載せられない。なのでユーザーにその都度 ls などで確認してもらう 4912 必要があって、その為には結局 ble-nightly* などとしてもらう事にな 4913 る気がする。 4914 4915 後は README, wiki 等を更新する。というか wiki に nightly version の 4916 記述はあっただろうか。なかった気がする。追加する必要はあるだろうか。 4917 追加しなくて良い気がする。 4918 4919 % 2022-11-28 ble-nightly.tar.xz 展開後のディレクトリ名について毎回 4920 % 全てを入力するのは大変である。なので、ble-nightly に生成する事に 4921 % する。ディレクトリ名に version が記録されない事になるが、そもそ 4922 % も ble-nightly をダウンロードしている時点で細かい version は気に 4923 % していないのだし、直後に削除する事を想定しているのだから気にして 4924 % も仕方がない。何れにしても ble.sh 本体の内部には記録される。 4925 % 4926 % →これは実質的に 2022-10-13 の議論と同じである。 4927 4928 2022-11-28 所で、これに関しては master に直接変更を push するので 4929 はなく、向こうの branch に push して確認するしかないのでは。と思っ 4930 たが、別に独立に変更をしてから向こうの branch を調整しても良い気が 4931 する。どちらでも良い。取り敢えず dev の上で作業して後で移し替えて 4932 すぐに merge してしまえば良い。 4933 4934 と思ったが既にその様に変更を実施済みである。うーん。後は README を 4935 更新すると書かれている。 4936 4937 * done: README を更新した。PR は何故か curl 版だけしか更新していな 4938 い。関連する物は全て更新するべきである。また日本語の README も更 4939 新した。 4940 4941 * done: ble.pp でも ble-nightly で検索を実施している。これについて 4942 も修正を行う。 4943 4944 というか今までのこのコードは set -f に対して対策はしていたのだっ 4945 たか? failglob と nullglob しか設定していない気がする。<del>何れ 4946 にしても最早パス名展開は使わなくなったので気にしなくて良い。 4947 </del> と思ったがよく見たら昔に展開した結果の始末や cp -Rf 本体 4948 でもパス名展開を使っているのでやはり set +f, -u failglob, -s 4949 nullglob はつけておく必要がある。後、cp -Rf で変な事が起こらない 4950 様に -u nullglob に変更する事にする。 4951 4952 2022-11-12 4953 4954 * test: テストで用いている rm が alias によって rm -i になって失敗する [#D1890] 4955 4956 これはテストの方を修正する事にした。他に類似の箇所はなかった。これは単独修 4957 正で良い。但し #D1889 のcontrib の更新も含める。 4958 4959 * fzf-completion 経由で補完した path の特別文字が正しく quote されない (reported by MK-Alias) [#D1889] 4960 https://github.com/akinomyoga/ble.sh/issues/250 4961 4962 fzf-completion.bash の中で noquote をしているのが原因の様である。noquote を 4963 つけた経緯について調べる。syntax-raw を付加したのは fb145dea (contrib) であ 4964 る。そして noquote をつけた箇所を確認しようとしたがどうも contrib の 4965 initial commit から noquote がついていた様である。つまり、色々の報告があっ 4966 た間も全然修正されなかった振る舞いという事である。なので余り深く考えられて 4967 いる訳でもない気がする。 4968 4969 contrib を導入したのは f2901158 #D1335 (2020-04-16) の様である。contrib の 4970 最初の commit では補完関数の advice は以下の様になっていた。 4971 4972 function _fzf_complete.advice { 4973 [[ :$comp_type: == *:auto:* ]] && return 4974 compopt -o noquote 4975 COMP_WORDS=("${comp_words[@]}") COMP_CWORD=$comp_cword 4976 COMP_LINE=$comp_line COMP_POINT=$comp_point 4977 ble/function#push printf '[[ $1 == "\e[5n" ]] || builtin printf "$@"' 4978 ble/function#advice/do <> /dev/tty >&0 2>&0 4979 ble/function#pop printf 4980 ble/textarea#invalidate 4981 } 4982 4983 そんなに深く考えられている様には思われない。単に noquote を外してしまって良 4984 い気がする。 4985 4986 2022-10-02 4987 4988 * README: Guix の package 一覧に追加する (motivated by kiasoc5) [#D1888] 4989 https://github.com/akinomyoga/ble.sh/issues/235 4990 https://guix.gnu.org/en/packages/blesh-0.4.0-devel2/ 4991 https://guix.gnu.org/ja/packages/blesh-0.4.0-devel2/ 4992 4993 * make: GNUmakefile の contrib/.git に対する依存性を削除する? [#D1887] 4994 https://github.com/NixOS/nixpkgs/pull/185866#issuecomment-1264567117 4995 https://issues.guix.gnu.org/57659#2 4996 4997 どうも nix 系統は package の git を fetch する際に .git を削除する様である。 4998 なので特別に git submodule を GNUmakefile から削除したり、或いは空の .git 4999 ディレクトリを生成したりしている。然し、そもそも .git がなくても正しく動作 5000 する物なのかという疑問もある。 5001 5002 少なくとも親ディレクトリの .git は存在していないとバージョンを決定する事が 5003 できない。contrib/.git には実は余り依存していない気がする。うーん。試してみる。 5004 5005 * done: どうも contrib/contrib.mk の中にある contrib/.git も削除する必要がある。 5006 5007 取り敢えずこれで問題なく動いている様である。そもそも何故 contrib/.git に 5008 対する依存性を持たせていたのかはよく分からない。存在確認だけしかしていな 5009 いのであればそれが最新になっているかどうかを保証できない。そして .git の 5010 存在確認をするだけなのであれば、それによって何を期待しているのかも謎であ 5011 る。 5012 5013 ? 或いは、contrib.mk が存在していながらそのファイルが存在しない (が .git 5014 が存在すれば大丈夫保証される) という事態を想定している? と思ったが、そ 5015 もそもファイル一覧を生成するのに wildcard を使っているのでファイルが存 5016 在していないという事はありえない。。 5017 5018 ? 或いは .git の更新時刻を確認しているのだろうか、と思ったが | の右側に 5019 contrib/.git を指定していたので更新時刻は全く関係ない。存在確認しかして 5020 いない。 5021 5022 ? 或いは単にコピーする前に contrib 最新に更新したかっただけかもしれない。 5023 然し、単に contrib/.git の存在を要求するだけだと更新はされないので意味 5024 がない。今まで更新されなくて問題がなかったのだから気にしなくて良いので 5025 はないか。 5026 5027 やはり contrib/.git の存在確認をする理由がよく分からないので単純に削除す 5028 る事にする。取り敢えずこれだけ修正したら .git がなくても動く様になった。 5029 5030 ? .git が存在していない状態で make をすると何が起こるのか。依然として make 5031 が成功するのだろうか? 以下の二つの変数の値を決定するのに git を使っている。 5032 5033 _ble_init_version 5034 _ble_base_branch 5035 5036 実際に値を確認してみると以下の様になっていた。エラーが出ていても make の 5037 失敗にはならない。 5038 5039 _ble_init_version=0.4.0-devel3+ 5040 _ble_base_branch= 5041 5042 release version ではこれらの変数にどのような値が設定されていたのだったか。 5043 もし、ここに固定の値が入っているのだとすれば .git がない場合にはそれと一 5044 貫した固定した値でも良いのかもしれない → うーん。release version でも、 5045 nightly version でもちゃんと branch 及び hash は生成されている。ble-0.3.0 5046 についても BLE_VERSION に hash が含まれている。 5047 5048 という事を考えるとやはり version/branch に適切な値を入れないという選択肢 5049 はない様な気がする。何れにしても debug の時の情報がかけてしまう事になる。 5050 5051 * done: git commit id の取得失敗時に ble.sh 生成を明示的に失敗させる 5052 5053 GNUmakefile で明示的に .git を要求する様にしてみたが、これだと依然として 5054 ダミーの .git を作って無理やり通そうとする人が現れるのは必至である。やは 5055 りちゃんと hash が取れる事を要求するべきの気がする。hash を取得するのに失 5056 敗したら ble.pp の変換自体を失敗させる仕組みが必要の気がする。 5057 5058 現在は #%$ にその様な機能はない。或いは一旦は #%[] で受け取ってその後で処 5059 理する? と思ったがそもそも #%[] を使っていたとしてもその場で変換を失敗さ 5060 せる仕組みはない様な気がする。 5061 5062 1. 取り敢えずは #%error の様な directive が必要の気がする → と思ったら既 5063 にあった。 5064 5065 2. 更に #%$ の結果を取得する方法か、或いはそのコマンドの失敗に対して即座 5066 に変換が失敗するオプションの様な物が必要ではないか。というかそもそも 5067 gawk でそれが可能なのかも分からない。取り敢えず確認する事にする。以下の 5068 ページによると終了ステータスを gawk から実行したコマンドで取得すること 5069 はできない様だ。なのでコマンド内部で色々して終了ステータスを標準出力に 5070 流す等の事をする必要がある。 5071 5072 https://stackoverflow.com/questions/21296859/how-do-i-get-the-exit-status-of-a-command-in-a-getline-pipeline 5073 5074 今回の場合には hash が空だったら失敗する様にすれば良い。branch については 5075 detached の状態にあって空になることもあるのでチェックしない。取り敢えず実 5076 装した。動いている。system() という関数を mwg_pp.awk に実装した。 5077 5078 ? 更に外側の関係ない .git の commit を拾ってしまう可能性もあるのではない 5079 か? うーん。その様な場合を考えだしたら限がないので考えない事にする。 5080 5081 * ok: GNUmakefile の .git で .git を要求されたらエラーメッセージを表示する 5082 事を考えたが、わざわざ変な事をしなくても良い気がしてきた。もし無理やりダ 5083 ミーの .git を作る人がいても今度は ble.sh の方が失敗する筈。なので、.git 5084 を要求するだけで良い。 5085 5086 * done: 失敗しても壊れた ble.sh が生成されてしまうのを何とかできないか。GNU 5087 make が失敗時にファイルを削除したりしなかったりするが、その条件は何だろう 5088 か。と思ったら .DELETE_ON_ERROR というルールがある様だ。ble.sh を其処に指 5089 定する事にした。 5090 5091 2022-09-28 5092 5093 * benchmark: -o KSH_ARRAY の中のコードが外と同じの気がする [#D1886] 5094 これは fe751acb の最初に benchmark.sh を追加した時からそのままである。 5095 実際 zsh の振る舞いを調べてみると KSH_ARRAYS を設定していると match の中身はずれる 。 5096 5097 2022-11-11 実際に zsh の上で使おうとしたらたくさんの修正が必要になっ 5098 た。取り敢えず現状で分かっている分を追加修正した。 5099 5100 2022-11-28 ksh で動かそうとしたら全然駄目だ。ksh は local を始めとして違い 5101 が大きすぎる。取り敢えず動く様にはしたが、色々違いが大きいので mwg_pp で別 5102 途 ksh 用に修正した物を生成する事にした。 5103 5104 2022-09-26 5105 5106 * vte で unsupported modifyOtherKeys のシーケンスが画面に表示されてしまう (reported by dongxi8) [#D1885] 5107 https://github.com/ohmybash/oh-my-bash/issues/360#issuecomment-1256927443 5108 5109 一旦は解決したと思ったが駄目の様だ。調べてみると vte:* の時には無効化してい 5110 る。実際に Ubuntu 16 LTS で GNOME terminal で試してみると再現した。どうも起 5111 動時に表示される様だ。それ以降は特に何も表示されない。つまり、端末情報を未 5112 だ取得し終わっていない段階で表示されてしまうのが問題という事。 5113 5114 これに対してはどの様に対策したら良いだろうか。例えば端末情報が初期化される 5115 までは modifyOtherKeys は設定しない? 端末情報が出揃った段階で改めて 5116 modifyOtherKeys を設定する。しかし、そうすると端末情報を返答しない端末に於 5117 いて modifyOtherKeys が決して有効化されないという状況になるのではないか。と 5118 思ったが、modifyOtherKeys に応答する現代的な端末では常に DA2 に対しても反応 5119 すると仮定して良いのではないか。 5120 5121 x と思ったが本当だろうか。例えば alacritty は DA2 に対応していなかった気が 5122 する。現在は対応している様だ (v0.11.0)。 5123 5124 https://github.com/alacritty/alacritty/blob/1df32309fe69d4e8113813a3e9049a7039650f44/alacritty_terminal/src/term/mod.rs#L1170 5125 https://github.com/alacritty/alacritty/commit/0dfd8601c92666c45d0c2e056bd68f600a4cbe47 5126 https://github.com/alacritty/alacritty/issues/3100 5127 5128 然し、実は alacritty は modifyOtherKeys の方に対応していない。 5129 5130 https://github.com/alacritty/alacritty/issues/3101 5131 5132 ? DA2 の後に modifyOtherKeys を有効にするというアプローチで問題ないだろうか。 5133 kitty では DA2 を受け取った後に再度 modifyOtherKeys を設定している。なの 5134 で、それが動いているのであれば他の端末についても問題ない筈。 5135 5136 唯、現在の実装だと有効・無効の判定と端末の判定が別々になっている。ユーザー 5137 が internal/external を指定している時には端末のサポートに関係なく強制的に 5138 modifyOtherKeys を出力している。auto の時にのみ端末判定を行っている。これ 5139 で正しく端末状態を設定するにはどうしたら良いだろうか。 5140 5141 うーん。取り敢えず DA2 を受け取る迄は modifyOtherKeys を設定しないように変 5142 更したが本当にこれを実行するのか。或いは bleopt で無効化する様にお願いすれ 5143 ば良いだけなのではないか。そもそも古い vte を使っているのが悪いのであって、 5144 その vte のバグの為にその他の端末についても制限を課すのは変な気がする。一方 5145 で、現実的に DA2 に対応していないが modifyOtherKeys に対応している端末とい 5146 う物が存在するのかというのはまた別の疑問である。うーん。正直 bleopt で各自 5147 無効化してもらうので良い様な気もするが、面倒なのでやはり ble.sh の側で対策 5148 するという事にする。 5149 5150 2022-10-02 テスト: Ubuntu 16 LTS の上での gnome-terminal では問題が直る事を 5151 確認した。Fedora 35 の上の gnome-terminal, kitty, alacritty で問題がない事 5152 を確認した。そもそも gnome-terminal と alacritty は modifyOtherKeys に対応 5153 していないので余りテストの意味はない。chatoyancy (Fedora 36) の上では 5154 terminology, terminator はそもそも modifyOtherKeys に対応していない。xterm, 5155 mlterm は modifyOtherKeys に対応していて問題はない。mintty も問題ない。 5156 恐らく特に問題はないだろうと思われる。 5157 5158 * 2022-09-23 prompt-git: rebase や merge 等の状態を表示したい [#D1884] 5159 5160 色々方法は考えられるがどうやら git-prompt.sh の __git_ps1 で使われている判定方法を用いれば良いらしい。 5161 https://stackoverflow.com/questions/30733415/how-to-determine-if-git-merge-is-in-process 5162 https://stackoverflow.com/questions/3921409/how-to-know-if-there-is-a-git-rebase-in-progress 5163 https://stackoverflow.com/a/3922581/4908404 5164 5165 取り敢えず以下を元にした実装にする。 5166 https://github.com/git/git/blob/4fd6c5e44459e6444c2cd93383660134c95aabd1/contrib/completion/git-prompt.sh#L452-L475 5167 5168 * global: return $? IFS [#D1883] 5169 5170 未だ残っている? もしくは新しく増えた物かもしれない。修正する。 5171 make scan でも $? を検索する様に変更する。 5172 5173 2022-09-25 5174 5175 * test: sha256sum がないというエラー @ macOS [#D1882] 5176 5177 元々 Linux の上で動かす事を想定していたので色々問題が出てくる。 5178 5179 test-util.sh の関数一覧 ToDo も序でに更新する。 5180 5181 * github: GitHub#227 CI tests in macOS/Windows (reported by aiotter) [#D1881] 5182 https://github.com/akinomyoga/ble.sh/pull/227 5183 5184 * macOS の sleep の実装は此処にある。特に変な事をしている訳でもない。 5185 https://github.com/apple-oss-distributions/shell_cmds/blob/main/sleep/sleep.c 5186 5187 * macOS の CI ではテストをスキップする様にする方法について模索する。 5188 5189 https://docs.github.com/ja/actions/learn-github-actions/environment-variables 5190 5191 の環境変数 RUNNER_OS を参照すれば良い。github workflow の中で動いている事 5192 を確認する為に、CI == true 及び GITHUB_ACTION についても確認する。 5193 5194 * macOS で問題が発生した時に誰が解決するのかという問題が生じる気がする。修 5195 正に時間が掛かるし実際の macOS で試してみないと分からない事もある。誰かを 5196 頼ろうと思っても誰に頼んだら良いのかも分からないしすぐ応答してくれるとは 5197 限らない。 5198 5199 その間 nightly が全くビルドされなくなる。という事を考えるとやはり nightly 5200 と macOS のテストは少なくとも分離するべきである。 5201 5202 また直る迄の間ずっと X がならぶ事になる。直す事ができないとずっと失敗する 5203 という事になる。うーん。一方で時々確認しておくという事はしたい気もする。 5204 確認する時だけ macOS をテストに含めるという使い方もあるだろうか?? 5205 5206 * PR に対しては一応実行しておきたい気はする。と言っても minor change や 5207 rebase に対して毎回テストを実行していたら clone stat が大変な事になる。テ 5208 ストを実行する時に approve をする機能があるみたいなので、それをどの様にす 5209 れば良いか確認する。 5210 5211 * msys のテストで色々失敗している。GraphemeCluster に関して調べてみようとし 5212 たが、そもそも msys2 bash の上では $'\U1F6D1' が1文字ではなく2文字とカウ 5213 ントされる様である。 5214 5215 $ a=$'\U1F6D1' 5216 $ echo "${#a}" 5217 2 5218 5219 確認してみた所、実は Cygwin でも同様の問題があるという事が判明した。うー 5220 ん。これは Bash の側で修正するべき事の気がする。或いは Cygwin の側で修正 5221 するべき事の可能性もある。後で調べる事にする。 5222 5223 うーん subst.c:8046 の MB_STRLEN を呼び出している。そしてこの MB_STRLEN 5224 は include/shmbutil.h で 5225 5226 #define MBSLEN(s) (((s) && (s)[0]) ? ((s)[1] ? mbstrlen (s) : 1) : 0) 5227 #define MB_STRLEN(s) ((MB_CUR_MAX > 1) ? MBSLEN (s) : STRLEN (s)) 5228 5229 の様にして定義されている。mbstrlen は lib/sh/shmbchar.c で定義されている 5230 関数である。中では mbrlen を呼び出している。これは標準ライブラリから来て 5231 いる。 5232 5233 ------------------------------------------------------------------------- 5234 5235 cygwin の上で mbrlen を呼び出すコードで再現した。newlib-cygwin の 5236 newlib/libc/stdlib/mbrlen.c (mbrlen) は単に mbrtowc を呼び出している。 5237 newlib/libc/stdlib/mbrtowc.c (mbrtowc) は wchar_t に変換する関数である。 5238 一方で windows では wchar_t は 16bit である。なので surrogate を読み取る 5239 しかないという事。うーん。この状況だとどのように直すのが正しいのか不明である。 5240 5241 * mbrlen の実装を弄って mbrtowc ではなくて Unicode code point を読み取っ 5242 た時のバイト数を返す様に変更すると、今度は他の箇所で mbrtowc との不整合 5243 が問題になる可能性もある。 5244 5245 そもそも bash ですら途中で wchar_t に変換して行う処理があった筈なので問 5246 題が起こる可能性が高い。 5247 5248 * 或いは mbrtowc に変わる mbrtoc32 的な物があれば良いのだが。然し 5249 char32_t は C++ の物だし、もし一連の関数を提供するとしても bash の側で 5250 も大幅な変更と検証が必要になるので色々難しい気がする。 5251 5252 だとすると ble.sh の側で上手に surrogate も処理できる様にする? 然し、 5253 UTF-8 で表されている文字列を bash でちゃんと切り取る事ができるのかも謎で 5254 ある。切り取る事ができたとしてもちゃんと処理できるのだろうか。。。 5255 5256 ------------------------------------------------------------------------- 5257 5258 一つの手は Grapheme Cluster の判定に Surrogate pair も考慮に入れるという 5259 事。或いは既に考慮に入っている? →確認してみたが考慮には入っていない様だ。 5260 5261 GraphemeClusterTable を確認すると surrogate pair U*D800..U+DFFF は全て 0 5262 になっている。つまり通常文字として取り扱われている。これを取り敢えず新し 5263 いカテゴリとして登録する事にする。 5264 5265 取り敢えず実装したが、実際に Cygwin の上で動かすと動かない。どうも 5266 surrogate pair の後半に対して ble/util/s2c を実行しようとしても常に 0 に 5267 なってしまう。これは printf '%s' に渡す前に文字を切断する必要があるが、文 5268 字を切断する時点で空文字列になってしまうから? 調べてみると ${s:i} で切断 5269 した時点で 4byte 中の 3byte が処理された状態になっていて UTF-8 の最後の文 5270 字が切り出されるという事態になっている。 5271 5272 ------------------------------------------------------------------------- 5273 5274 うーん。また変な振る舞いを見つけてしまった。これは bash の側で修正した。 5275 5276 s=$'\U1F6D1' 5277 printf '%d ' "'$s" "'$s" "'$s" 5278 printf '%d ' "'$s" "'x" "'$s" "'x" "'$s" 5279 echo 5280 5281 https://lists.gnu.org/archive/html/bug-bash/2022-09/msg00055.html 5282 5283 他にも色々振る舞いについて修正などが必要だったが取り敢えず通る様になった。 5284 5285 2022-09-16 5286 5287 * canvas: Unicode version 更新 [#D1880] 5288 15.0.0 が出ている。各テーブルを更新したが、更にversion 判定ロジックを改めて 5289 更新する必要がある。 5290 5291 既存の判定用テーブルは #D1668 にある。これを更新する。うーん。このテーブル 5292 を生成するのに使ったスクリプトがある筈。だが見つからない。と思ったら 5293 5294 make/canvas.c2w.list-ucsver-detection-codes.sh 5295 5296 であった。うーん。U+1B132 (平仮名の小さな「こ」) を採用する。更新されたテー 5297 ブルは以下の様な感じ。 5298 5299 | -----Unicode EAW+GeneralCategory-------------------|musl 5300 ws[0] U+09FBC | -1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 | 2 5301 ws[1] U+09FC4 | -1 -1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 | 2 5302 ws[2] U+031B8 | -1 -1 -1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 | 2 5303 ws[3] U+0D7B0 | -1 -1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 | 2 5304 ws[4] U+03099 | 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 | 0 5305 ws[5] U+09FCD | -1 -1 2 2 2 2 2 -2 2 2 2 2 2 2 2 2 2 | 2 5306 ws[6] U+1F93B | -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 1 1 1 | 1 5307 ws[7] U+0312E | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 2 2 | 1 5308 ws[8] U+0312F | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 2 | 1 5309 ws[9] U+16FE2 | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 | 1 5310 ws[10] U+032FF | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 | 1 5311 ws[11] U+031BB | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 | 1 5312 ws[12] U+09FFD | -1 -1 2 2 2 2 2 -2 -2 -2 -2 -2 -2 -2 -2 2 2 | 2 5313 ws[13] U+1B132 | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 | 1 5314 5315 * mandb: longname の説明に対応する short option 名を併記するう (suggested by bbyfacekiller) [#D1879] 5316 https://github.com/akinomyoga/ble.sh/issues/231 5317 5318 これはもしかすると実際に short flag も選択できる様にして欲しいという要求か 5319 もしれないとも思ったがよく分からないので、取り敢えず作ってみて見た目だけ見 5320 せたらそれで良いというのでそのまま採用する事にする。 5321 5322 * color: term_index_colors を優先する様に変更 (motivated by StavromulaBeta) [#D1878] 5323 5324 これで強制的に減色したい時にユーザーが term_index_colors を設定できる。 5325 5326 * [棄却] neovim terminal / vim-autocomplpop で i/a を入力した時の問題 [#D1877] 5327 https://github.com/akinomyoga/ble.sh/issues/232 5328 5329 変な文字列が挿入・実行される 5330 5331 # これは報告者が使っている AutoComplPop というプラグインが古いのが原因だった 5332 5333 neovim は nvim というコマンドで起動する様だ。 5334 5335 再現しない。nvim-0.7.2, bash-5.2-rc2, としても再現しない。 5336 5337 * plain vimrc? .vimrc をコメントアウトして試したが再現しない。 5338 5339 * reject: 或いは i, a に対する delay が関係している可能性? 実際に操作してい 5340 てい ESC がちゃんと即座に処理されていない気がする。 5341 https://vi.stackexchange.com/questions/16148/slow-vim-escape-from-insert-mode 5342 と思って ttimeoutlen や timeoutlen を短い値に変えてみたが振る舞い(遅延)に 5343 変化は見られない。これらの設定は関係ないという事か? 5344 5345 * 27_feedPopup() という文字列が挿入されている。9_feedPopup で検索すると vim 5346 の中にある自動補完の仕組みが関係している様な気がするが詳細はよく分からな 5347 い。これでエラーが出ているという事は、実際に ble.sh がこの文字列を受信し 5348 ているということである。vim の保管機能が意図しない形で ble.sh に対して送 5349 信されて、変な文字列が挿入されると共に実行まで開始されている。 5350 5351 https://askubuntu.com/questions/382407/vim-autocomplpop-issues 5352 5353 このページを見る限り AutoComplPop という何かが関係している? 5354 元々のページ at bitbucket は消滅している? 5355 5356 https://github.com/vim-scripts/AutoComplPop 5357 5358 ここを見ると最後に更新されているのは12年前。runtime path 以下にファイルを 5359 コピーしろと書かれているが runtime path が何か分からない。検索すると 5360 runtimepath という変数に入っているみたいだが、今度は runtimepath という変 5361 数の値を取得する方法が分からない。と思ったら ":set runtimepath^M" で良い 5362 様だ。set で右辺を指定しなければ現在の値が表示される。実際に表示してみる 5363 と以下の様になっている。 5364 5365 # runtimepath=~/.config/nvim,/etc/xdg/nvim,~/.local/share/nvim/site, 5366 # ~/.local/share/flatpak/exports/share/nvim/site, 5367 # /var/lib/flatpak/exports/share/nvim/site, 5368 # /usr/local/share/nvim/site,/usr/share/nvim/site,/usr/share/nvim/runtime, 5369 # /usr/share/nvim/runtime/pack/dist/opt/matchit,/usr/lib/nvim, 5370 # /usr/share/nvim/site/after,/usr/local/share/nvim/site/after, 5371 # /var/lib/flatpak/exports/share/nvim/site/after, 5372 # ~/.local/share/flatpak/exports/share/nvim/site/after, 5373 # ~/.local/share/nvim/site/after,/etc/xdg/nvim/after,~/.config/nvim/after, 5374 # /usr/share/vim/vimfiles/ 5375 5376 取り敢えず .config/nvim に入れる。 5377 5378 OK 再現した。うーん。何故これが発生しているのだろうか。 5379 5380 うーん。然し、そもそも ble.sh をロードしていなかったとしても i または a 5381 を押すと最後に実行したコマンドが強制的に実行される様である。これは変であ 5382 る。そもそも ble.sh だけの問題ではない気がする。 5383 5384 検索すると https://github.com/othree/vim-autocomplpop/issues/9 で同じ現象 5385 が報告されている。というかこれが acp の最新版なのではないか。これを入れて 5386 みたところ、今度は ***** L9 library must be installed! ***** というメッセー 5387 ジが表示される。検索してみたらこれは行番号ではなくて "L9" という名前のラ 5388 イブラリらしい。同じエラーメッセージについての質問があった。 5389 5390 https://stackoverflow.com/questions/22902141/l9-library-must-be-installed-error-occurred 5391 5392 2022-09-14 5393 5394 * prompt: clear-screen 後は same-dir でも transient prompt を残しておく [#D1876] 5395 5396 transient same-dir で起動後の一番最初のプロンプトは全部残しておくべきである。 5397 5398 と思って試して見たがちゃんとそうなっている。或いは clear-screen した時にディ 5399 レクトリ名が消えてしまうという事だったか。これは振る舞いを修正しても良い。 5400 5401 p10k の方の振る舞いを見てみたが clear-screen しても same-dir で trim されて 5402 しまう様である。なのでそういう意味では ble.sh も気にしなくても良いのかもし 5403 れないが、やはり clear-screen した後は残っていて欲しい気がする。 5404 5405 * hook: blehook | cat がデフォルトで着色になっている [#D1875] 5406 5407 bleopt ble-bind ble-face ble-sabbrev 等は問題ない。常に auto の振る舞いである。 5408 これは blehook の read-argument が悪い。修正した。 5409 5410 2022-09-13 5411 5412 * HISTCONTROL に trim 的な物を追加しても良いのではないか (motivated by aiotter) [#D1874] 5413 https://github.com/akinomyoga/ble.sh/issues/226#issuecomment-1243759012 5414 5415 bash のソースを見たら stringlib.c に strip_{leading,trailing} というのがあ 5416 るので trim ではなく strip を名前として使う事にする。 5417 5418 取り敢えず bash の patch も作ってみる事にする。 5419 https://gitlab.com/akinomyoga/bash/-/commit/d43c167e9ec150d1fe4a730475a590d48a4cc9cd 5420 5421 2022-09-06 5422 5423 * decode: ble-bind --cursor で設定したカーソルが反映されない [#D1873] 5424 5425 vi のモードを遷移した時にしか反映されない。set -o emacs や set -o vi を実行 5426 してもそのままである。調べたら keymap#{push,pop} の時にしか cursor を設定し 5427 ていない気がする。base を変更した時や ble-bind で cursor を設定した時にも設 5428 定を反映するべきではないか。 5429 5430 * 現在キーを受け付けている状態かどうかをどうやって判定するか。現在表に出て 5431 いる時にだけ cursor 設定をその場で変更する。それ以外の時には記録してある 5432 状態を書き換える、という具合にすれば良いだろうか。 5433 5434 →これは ble/term/cursor-state/set-internal を指定すれば良いだろうか。 5435 実際、keymap/{push,pop} ではこの set-internal を指定している。 5436 5437 他の箇所で一時的に cursor を書き換えていたりはしないか。つまり、同じ 5438 keymap であっても別の要因で別の cursor を表示しているという事はあるだろう 5439 か。→調べたがその場所はない。基本的に keymap/{push,pop} でしか cursor 5440 shape は変更していない様だ。 5441 5442 * base map を設定している箇所を確認する。恐らく reset-default-keymap だけだ 5443 ろう。他は ble-bind -P で INITIALIZE_DEFMAP をしているがここでは 5444 _ble_decode_keymap はしていない。改めて確認したが _ble_decode_keymap を変 5445 更しているのはやはり decode.sh の中では keymap/{push,pop} と 5446 reset-default-keymap だけである。 5447 5448 * ble-bind で cursor を設定した時にもその場で反映したい→対応した。動作も確 5449 認した。 5450 5451 また、以前の xterm.js の為に指定した workaround が動いていないのではないか。 5452 結局 term enter する時に unknown を設定してしまっている。そして、コメントを 5453 見る限りはこれは vim がカーソルの状態を残したまま終了してしまう事に対する対 5454 策の様である。 5455 5456 うーん。これに対してはどの様に対処するべきだろうか。vim の設定が悪いのだと 5457 思えばわざわざ直さなくても良い。と思ったが元々これは ble.sh の中で keymap 5458 の cursor を設定しているのにも拘らず vim の実行後にその設定が変わってしまう 5459 というのが問題なのであった。 5460 5461 default と unknown という値を区別する事にして、ble.sh が cursor 設定を変更 5462 していない時は default という事にしてユーザーコマンドが変更した cursor につ 5463 いては関知しない事にする。 5464 5465 2022-08-31 5466 5467 * 2022-08-23 complete: progcomp 引数について [#D1872] 5468 https://github.com/scop/bash-completion/issues/790 5469 https://github.com/scop/bash-completion/issues/791 5470 5471 ? ok: そもそも現在の ble.sh の実装だと = などが存在した時の単語の分割の仕方 5472 が異なる。これはやはり Bash に合わせた方が良いのだろうか。と思ったが、 5473 5474 $ test1 a=[TAB] 5475 $ test1 a=b[TAB] 5476 5477 の両パターンの一貫性を考えれば現在の ble.sh の分割の仕方の方が自然だし、 5478 後者を実装しているのであれば前者についても ble.sh の分割の仕方で自然に動 5479 作しそうな物である。という事を考えると、敢えて bash の変な振る舞いに合わ 5480 せる必要はない様に思われる。 5481 5482 * ok: 更に報告された振る舞いで問題になっているのは、分割文字 = の直後で補完 5483 した時に、何故か新しい単語ではなくて = に対する補完になっているという 5484 Bash の振る舞いがそもそもの問題である様な気もする。それを回避する為に $2 5485 に空文字列を設定するというのも何だか変な実装である。 5486 5487 然し一方で分割文字 = 自体を書き換えたいという場合も考えられるので遡って書 5488 き換えられる様に "=" の単語の中に含めて補完するというのもそれはそれで理解 5489 できる。なので Bash 自体に振る舞いの変更を実装して解決するという訳にも行 5490 かない。 5491 5492 ? ok: 所で "echo aaa [TAB] bbb" とした時に ble.sh はどの様に振る舞うのだっ 5493 たか。bash では変な分割のされ方と CWORD の設定のされ方になっているとして 5494 文句が出ていた物である。 5495 5496 →これは ble.sh ではちゃんと途中に空文字列を作成している。OK 5497 5498 ? done: コマンド名自体が COMP_WORDBREAKS で分割される場合にはどう振る舞うべ 5499 きか。Bash の振る舞いを確認してみた所、COMP_* を作成する時点でコマンド名 5500 も COMP_WORDBREAKS に従って分割されてしまっている。一方で、補完関数の $1 5501 に渡される文字列は分割前のコマンド名の様である。 5502 5503 その様に実装する。 5504 5505 bash-completion#791 の実装を単に移植する事にした。 5506 5507 * reject: うーん。そもそも bash の振る舞いを厳密に再現する必要もない様な気 5508 はする。特に simple-word/is-simple-or-open-simple 等を使ってより良く判定 5509 できるのではないかという気がする。然し、取り敢えずは Bash の動作に厳密に 5510 一致する様に振る舞う事にする。そもそもこの振る舞いを便利に使っている補完 5511 があるとも思われないので。 5512 5513 x fixed: そもそも現在の ble.sh において COMP_WORDBREAKS が正常に動作してい 5514 ない気がする。 5515 5516 確認してみた所 ble/syntax:bash/simple-word#break-word に引数を渡し忘れて 5517 いる? ここに単に $wordbreaks を渡せば良いのではないか。 5518 5519 ? 或いは、既定の値 (:=) を使う理由が何かあったのだろうか? 調べる。変更は 5520 6c6bae5 で行われている。これは #D1098 である。この時の議論を確認してみ 5521 たが特にこの部分で特別な取り扱いをするという議論はない。寧ろ 5522 COMP_WORDBREAKS に対応する為の議論なので wordbreaks 変数を全く使ってい 5523 ない現在の実装は変である。 5524 5525 分割子として "$wordbreaks" を指定する様に修正した。 5526 5527 x fixed: 新しく実装した cur が全く反映されない。と思ったら helper-prog (-C) 5528 の方だけ対応していた。helper-func (-F) の方も対応する。動作も確認した。 5529 5530 ? ok: bash の COMP_WORDBREAKS による単語分割は @ や $ や \ に対しても他の分 5531 割文字と同様に働くのか? つまり独立した subword を形成するのだろうか? → 5532 試してみた所、ちゃんと独立した subword になっている。つまり abc@def が 5533 "abc" "@def" と分割される等の特別な事は起こらない。特別な取り扱いは $2 限 5534 定の様だ。 5535 5536 * 何と $2 には現在の単語だけが設定される訳では無い様だ。COMP_WORDBREAKS に 5537 よる分割の前の単語が全て入る可能性がある。 5538 5539 $ test1 abc@def 5540 declare -a COMP_WORDS=([0]="test1" [1]="abc" [2]="@" [3]="def") 5541 <test1><@def><@> 5542 5543 これにもちゃんと対応した。 5544 5545 2022-08-29 5546 5547 * 2022-08-23 blehook HOOK+= を HOOK!= に統一する [#D1871] 5548 5549 * 2022-08-14 nix develop が保存された EPOCHREALTIME を復元しようとしている [#D1870] 5550 https://discourse.nixos.org/t/nix-print-dev-env-command-shows-some-assinments-to-readonly-variables/20916 5551 https://github.com/NixOS/nix/pull/6800 5552 5553 一方で ble.sh は EPOCHREALTIME が勝手に別の機能に置き換えられると動作が全く 5554 おかしくなるので (そしてはそれは他の EPOCHREALTIME を参照しているスクリプト 5555 も同様であろう)、勝手に EPOCHREALTIME の機能を消去させられてしまっては困る。 5556 5557 * そもそも Bash では EPOCHREALTIME をそのまま上書きしても意味がない。一旦 5558 unset しなければならない。実際に上書きしている箇所で unset をしているのか 5559 どうかまでは明言されていないが、報告されているエラーメッセージを観察する 5560 限りは unset は試みられていない。unset が最初に試みられていたのであれば、 5561 5562 bash: unset: EPOCHREALTIME: cannot unset: readonly variable 5563 5564 というエラーメッセージになっていた筈である。 5565 5566 * もし unset してまで固定した時刻にしたかったのだとすれば、そして実際にそれ 5567 をやったとしたら ble.sh の内部の時刻関連の制御が滅茶苦茶になる。場合によっ 5568 ては固まってしまうかもしれない。 5569 5570 というかもし対話シェルで使っているなのだとしたら 5571 5572 ? というかそもそも何故対話シェルの設定と print-dev-env 的なコマンド的な設定 5573 が混ざり合っているのだろうか。 5574 5575 % ? 会話を見ると print-dev-env は単に現在のシェル変数を出力するのに使って 5576 % いるだけの様に見える。sed でフィルタ等するという話をしている。なので、 5577 % 対話シェルとして動作するとも思えない。 5578 % 5579 % ? nix develop でエラーメッセージが表示されると書いている。nix develop 5580 % を調べてみると、 nix shell + 開発用のコマンドという環境に入るらしい。 5581 % なので bashrc を読み込む。問題は print-dev-env が何故同じシェルで呼び 5582 % 出されるのかという事である。特に直接 print-dev-env を自分で明示的に呼 5583 % び出しているのではなくて、nix develop を実行した時に自動で実行される 5584 % のだという事を書いている。謎だ。 5585 % 5586 % ? 仮に ble.sh が --lib で読み込まれるのだとしても、それを bashrc から読 5587 % み込むというのも変な話である。もし ble.sh の関数を個別のシェルスクリ 5588 % プトで使いたかったとしても、それは使うシェルスクリプトの中で個別に 5589 % source するべきなのであって、bashrc で一括して読み込むという使い方は 5590 % 想定していない。 5591 % 5592 % ? 或いは print-dev-env というのはシェル関数なのだろうか。 5593 5594 % https://github.com/NixOS/nix/blob/master/src/nix/develop.cc を見ると、 5595 % どうも print-dev-env と develop は内部のコードを共有しているという事の 5596 % 様だ。つまり、develop の中で呼び出された print-dev-env が EPOCHREALTIME 5597 % を触ってのではなくて、nix develop のコード自体が EPOCHREALTIME に触ろう 5598 % としているのである。更に、print-dev-env も develop も単に現在の値を出力 5599 % しているだけであって、明示的に EPOCHREALTIME に値を設定するコードが含ま 5600 % れているという訳では無い様な気がする。 5601 % 5602 % そういう事を考えると、そもそもこの現在の値を出力するコードの時点で、 5603 % EPOCHREALTIME, EPOCHSECONDS, SECONDS, LINENO, BASH_LINENO, FUNCNAME, 5604 % BASH_SOURCE, BASH_VERSION, BASH_VERSINFO, BASH_COMMAND 等の変数に値を代 5605 % 入しようとしているのが間違っている。 5606 5607 develop.cc のコードを確認した。先ず、print-dev-env は、実質的に nix 5608 develop を中で呼び出してその環境における変数を出力するという様な処理を行っ 5609 ている。そして、正にそれが目的なのだろうという気がする。 5610 5611 nix develop は何処かに .json で保存されている変数を読み取ってそれを bash 5612 に設定しようとしている様に見える。その .json に EPOCHREALTIME が記録され 5613 ているのは恐らく何か別の用途にも使われる事を想定しての物だろう。一方で、 5614 nix develop で使う時には幾ら何でも全ての変数を復元するのは変である。 5615 BASH_* は避けるべきだし (もしかするとこれらは既に保存する時点で除外されて 5616 いるのかもしれない)、その他の FUNCNAME や LINENO 等も復元を試みるのは滅茶 5617 苦茶である。 5618 5619 BASH_VERSINFO は bash が readonly にしていてこれに関しては警告が出ていな 5620 いというのは BASH_* は除外しているという事なのだろうという気がする。 5621 5622 ? NixOS/nix #6800 も謎である。error ではなく warning だったと言って閉じてい 5623 るのも謎だし、zsh では readonly だからと言って bash で動く nix develop の 5624 上でスキップするというのもよく分からない。 5625 5626 * 色々 develop.cc を読んだりして思った事は TLATER の 99% sure と言っている 5627 内容はかなり怪しいという事だ。恐らくこの TLATER は何も分かっていなくて出 5628 鱈目な事を書いている。 5629 5630 或いは実際に何処か別の箇所で EPOCHREALTIME も明示的に保存しているのだろう 5631 か。でもコードを見る限りは ignoreVars でブラックリスト式にしているし、恐 5632 らく全ての変数を出力しているのだろうという気がする。 5633 5634 やはり TLATER は出鱈目を書いている。もし本当にそうなのだというのであれば 5635 わざわざ 99% sure などと書かないし、というか 100% sure とも書かずに、断定 5636 で書くはずである。I'm sure なんとかとか書いている時点で勝手に推測をしてい 5637 るのに過ぎない。 5638 5639 そもそも本当に build environment を同一にしたいのであれば、単に変数の値を 5640 変更したとしても意味がない。システムの時刻自体を固定しなければならないの 5641 ではないか。そもそも最近の bash の機能である EPOCHREALTIME を参照してビル 5642 ドを行うシステムがどれだけ存在するのかというのも謎である。そしてシステム 5643 の時刻を固定しているのであれば、わざわざこの様な処理は必要がない筈である。 5644 5645 5646 →と思ったがこの json はもしかすると各 derivation の作者が手書きで用意す 5647 る物なのだろうか。なのだとしたら EPOCHREALTIME を誤って設定している人がい 5648 ても不思議ではないのかもしれない。然し検索してみてもその様な物は見つから 5649 ない (とは言いつつ GitHub の検索は余り当てにならない。経験上最近検索され 5650 たページに含まれている文字列しか検索対象になっていないような気がする)。 5651 5652 https://github.com/NixOS/nix/search?q=EPOCHREALTIME 5653 https://github.com/NixOS/nixpkgs/search?q=EPOCHREALTIME 5654 5655 2022-08-29 これは結局 nix の側で修正されたので OK 5656 https://github.com/NixOS/nixpkgs/pull/185866 5657 https://github.com/NixOS/nix/pull/6944 5658 5659 * ok: 2022-08-26 何と bash の regex は ^ で文字列の戦闘ではなくて行頭に一致してしまう? [#D1869] 5660 5661 と思ったがそうでもないようだ。特別な条件で発生する。 5662 5663 rex='^b'; [[ $'a\nb' =~ $rex ]]; echo $? ... 一致しない (OK) 5664 rex='^[^a]'; [[ $'a\nb' =~ $rex ]]; echo $? ... 一致しない (OK) 5665 rex='a^'; [[ $'a\nb' =~ $rex ]]; echo $? ... 一致しない (OK) 5666 rex='.^'; [[ $'a\nb' =~ $rex ]]; echo $? ... 何故か一致してしまう????? 5667 rex='.^'; [[ $'ab' =~ $rex ]]; echo $? ... 一致しない (OK) 5668 rex='^.^'; [[ $'a\nb' =~ $rex ]]; echo $? ... 一致しない (OK) 5669 rex=$'\n^'; [[ $'a\nb' =~ $rex ]]; echo $? ... 一致する! 5670 rex=$'a\n^b'; [[ $'a\nb' =~ $rex ]]; echo $? ... 一致する! 5671 rex=$'^..^b'; [[ $'a\nb' =~ $rex ]]; echo $? ... 一致する! 5672 5673 この変な振る舞いは 3.0..5.2 まで全てで再現する。或いは Linux/glibc 側の問題 5674 の可能性もある。 5675 5676 何れにしても .^ や \n^ の様な (single line regex では) 意味のない正規表現で 5677 しか問題が起こっていないので取り敢えずは何もしなくて良い。うーん。例えば ^ 5678 より前に何かが存在する時に限り ^ は multiline mode に変更されるなど? もしか 5679 すると関連して現実的な正規表現でも問題が起こる可能性があるかもしれないが。 5680 5681 だとしたら ^$ で空文字列にしか一致しない様にしているのは不味いのではないか? 5682 5683 $ a='x\n\ny' r='.*^$'; [[ $a =~ $r ]]; echo $? ... 一致しない (OK) 5684 $ a='x\n\ny' r='.+^$'; [[ $a =~ $r ]]; echo $? ... 一致しない (OK) 5685 $ a='x\n\ny' r='.*(^$)'; [[ $a =~ $r ]]; echo $? ... 一致しない (OK) 5686 $ a='x\n\ny' r='.+(^$)'; [[ $a =~ $r ]]; echo $? ... 一致しない (OK) 5687 5688 と思ったがこの場合には問題は起こらない様だ。不思議だ。 5689 5690 取り敢えず問題にはならないとは思われるが、一応注意点として記録はしておく。 5691 5692 * [自然解消] refactor: TRAPRETURN の中に余分な i=1 が残っている [#D1868] 5693 5694 結局関連するコードは #D1867 の際に消滅した。 5695 5696 * trap: gexec による DEBUG の処理を ble/builtin/trap に統合する [#D1867] 5697 * trap DEBUG, ERR についても関数呼び出しに従った構造を記録する。 5698 5699 x 統合する上での問題は trap の中で trap が走った時に 5700 _ble_builtin_trap_postproc 等の変数が混ざって問題にならないかという事。 5701 (そもそも trap の実行中に trap が走るのかどうかもよく分かっていない) → 5702 実際に試してみた所、やはり trap の中で DEBUG trap は走る様だ。 5703 5704 Ref. memo/D1867.recursiveTrapWA-stub.patch (試験的な実装) 5705 5706 これは実は RETURN でも同様なのではないか。trap handler の中で RETURN が発 5707 生するのでは? 5708 5709 a 混ざらない様にするには trap 毎に別の変数に trap_postproc を保存する? 5710 と思ったが RETURN の中で呼び出される RETURN などの状況を考えると単に 5711 trap 毎に変数名を変える方法では対応できない。 5712 5713 % * 以前 RETURN の中で RETURN が呼び出されるというので無限ループ 5714 % になった事がある気がする 5715 % 5716 % →と思って今試してみたらやはりそういう事は起こらない様である。だとす 5717 % れば単に trap 毎に保存すれば良いだけなのではないか。 5718 % 5719 % 以前の議論を探してみた所、実際に以前これについて調べていた (#D1350) 5720 % がその時調べた結果は RETURN は RETURN 以外の trap では発生するという 5721 % 事。RETURN 内部で RETURN は発生しないという事。この時調べたのは、無限 5722 % ループにならないかというのが心配になったからだったという記憶が微妙に 5723 % 残っていただけだろう。 5724 5725 b というか単に trap の nest level を変数に入れておけば良いのでは? そして 5726 _ble_builtin_postproc[_ble_builtin_trap_depth] を参照する。 5727 5728 と思ったが全てを handler に入れておく必要もない気がする。要するに 5729 .handler を呼び出した直後に postproc を評価するのだから、.handler の最後 5730 で postproc を設定すれば良いだけなのでは? と思ったがやはりそう簡単でもな 5731 い。.handler を呼び出した後に eval "${postproc}" を実行する間に別の trap 5732 が走る可能性もあるのである。 5733 5734 c という事を考えると、 5735 5736 depth++; .handler; eval postproc; depth-- 5737 5738 の様な具合にしなければならないのではないか? 然し depth-- を保証する方法 5739 がない。 5740 5741 d 或いは 5742 5743 depth=depth+1 eval '.handler; eval postproc' 5744 5745 という具合にするしかないのだろうか。と思ったがこれも駄目な気がする? 否、 5746 例え .handler と eval の間に別の handler が入ったとしてもその handler 5747 が中途半端に終了しない限りは大丈夫の筈。 5748 5749 5750 _ble_builtin_trap_depth=$((_ble_builtin_trap_depth+1)) builtin eval -- "${_ble_builtin_trap_handler/SIGNUM/1}" 5751 _ble_builtin_trap_handler='ble/builtin/trap/.handler SIGNUM "$BASH_COMMAND" "$@"; builtin eval -- "..." \# "..."' 5752 5753 うーん。これで行けると思ったがやはり駄目だ。eval を入れ子にすると $_ が 5754 変わってしまうので駄目。なので eval を入れ子にしない方法を考えたいが… 5755 或いは trap によって lastarg が変わらないという事にしてしまって一番外側 5756 の eval に \# "${_%%$_ble_term_nl*}" を渡すという手もあるかもしれない。 5757 5758 5759 e 或いは handler の中で local inc したらどうなるだろうか。 5760 5761 handler() { local depth=$((depth+1)); postproc[depth-1]=設定; } 5762 5763 問題が起こるとしたら 5764 5765 ? handler が呼び出されて local depth を実行する間に DEBUG が走った場合? 5766 然しこの場合には実のところ DEBUG の処理が終わったらまた元の状態に戻る 5767 筈なので気にしなくて良い。とにかく postproc を触る前までに depth を 5768 inc して置けば良い筈。 5769 5770 ? 或いは handler が終了してから eval postproc[depth] する間に DEBUG が 5771 走った場合? 実はこれについても特に問題は発生しない様に思われる。 5772 5773 →うーん。やっぱり駄目だ。handler が終了した時に postproc[depth] には 5774 handler が設定した物が入っているが、この時に別の trap が走るとそれが 5775 上書きされてしまう。 5776 5777 代わりに push/pop 方式にするとしても pop せずに抜けてしまった時に、よ 5778 り外側の handler が誤って内側の物が設定した postproc を実行してしまう 5779 事になる。 5780 5781 f 或いは別の方法で trap の入れ子レベルを知る事ができれば良い。と思ったが 5782 難しい。FUNCNAME の中に含まれる ble/builtin/trap/.handler を数える方法 5783 を考えたが、これだと結局 handler ... eval の間に走る trap に対して対処 5784 できない。というか eval の入れ子レベルを取得する方法はないにだろうか。 5785 PS4 の最初の文字を複製する回数でもあるが、これをもっと普通の方法で取得 5786 する方法がないのは何故だろうか。 5787 5788 g うーん。或いは postproc を設定してからそれを評価する迄の間に発生した 5789 trap は全て無効化するという可能性? 5790 5791 x しかしこれも何らかの拍子で postproc が実行されずに終わってしまうとそ 5792 れ以降の全ての trap が実行されなくなってしまう。 5793 5794 然し、実際にそれが発生する事はあるのだろうか。先ず INT は塞いでいる。そ 5795 もそも trap の内部で INT は発生しない気がする。trap の内部で発生する可 5796 能性があるのは DEBUG, RETURN ぐらいの物である。errtrace が設定されてい 5797 れば ERR も発生するかもしれない。 5798 5799 * DEBUG と RETURN には介入している。一方で、ERR には介入していない。 5800 DEBUG と RETURN に関しては無効化すれば良い。ERR で return などが実 5801 行されて trap 終端処理がスキップされた時に問題になる。 5802 5803 その他の理由で実行がキャンセルされる事はあるだろうか。 5804 5805 * 外部からのシグナルの場合には trap handler の実行中には何も起こらな 5806 い。trap handler の実行が終わった後に実行される筈である。 5807 * readline の timeout (TMOUT) に関しては ble.sh は無効化して自前で実 5808 装しているので問題にならない筈。 5809 * KILL を受け取ったら何れにしても終了するので関係ない。 5810 * exit で trap の中から終了する場合…と思ったがこれは起こり得ない。今 5811 ble.sh の trap string を実行しているのだからその他のコマンドが実行 5812 される余地はない。 5813 5814 うーん。別の方法で trap を実行している事を検知する方法はあるだろうか。 5815 5816 * reject: 例えば bash-4.4 以降では trap 実行中に return の戻り値が変 5817 わる事を以て現在 trap の内部かどうかを判定できると思ったが、入れ子 5818 の trap の場合には 2 重か1重かを判定しなければならないのでこの方法 5819 は使えない。そもそも使えたとしても、この振る舞いは議論の対象であり 5820 将来的に変更されるかもしれないし古い bash では使えない。 5821 5822 恐らくこれで基本的に問題ない。 5823 5824 1 DEBUG に対しては postproc 直前の発火に対しては無視する。 5825 5826 2 RETURN に対しては trap/.handler RETURN について無視する。 5827 5828 うーん。これは元からそうなっているのでは? と思ったがそうでもない様 5829 だ。現在は trap 内部の RETURN しか無視していない。これに加えて 5830 blehook/invoke.sandbox | blehook/invoke | ble/builtin/trap/.handler 5831 に対して発火した RETURN も無視したい。 5832 5833 3 ERR に関しては trap/.handler が失敗しない限りは大丈夫の筈。 5834 5835 但し、何らかの拍子に postproc が設定された儘になってしまった時の為に、 5836 随時 postproc をクリアする。例えばトップレベルで呼び出された 5837 ble-decode/.hook でクリアすれば良いのではないか。少なくとも trap 5838 handler の中でトップレベルで ble-decode/.hook が呼び出される事はない。 5839 5840 改めて考え直してみたが同じ trap が入れ子で呼び出される事はやはりないと仮定 5841 して良い気がする。だとすれば a の方法で実装すれば良い。一方で g.2 の 5842 [RETURN 以外の trap についての trap/.handler に対する RETURN] の発火は無視 5843 する事については対処したい。 5844 5845 * RETURN 以外の trap/.handler に対する RETURN を無視する事について。 5846 5847 というか現在の実装の blehook/invoke.sandbox | blehook/invoke | 5848 ble/builtin/trap/.handler のスキップは全て無視して単に BLE_TRAP_FUNCNAME 5849 を参照すれば良いのではないか? 5850 5851 と思ったがそれだけだと駄目である。先ず trap/.handler は内部で色々な関数を 5852 呼び出している。RETURN を extdebug で設定しているとこれらの全ての関数に対 5853 して RETURN が発火して面倒な事になる。 5854 5855 うーん。exit 時に RETURNが呼び出されると思ったが、これは unload で元の 5856 RETURN を復元した後に発生している物である。 5857 5858 * _ble_builtin_trap_{postproc,lastarg} を trap 毎に記録する様に変更する。 5859 5860 _ble_builtin_trap_lastarg については基本的に2つの関数でしか使われていなかっ 5861 たのですぐに修正できた。_ble_builtin_trap_postproc も殆ど同様だったが、但 5862 し edit.sh で DEBUG trap の postproc/lastarg 抽出に使用されていた。これは 5863 _ble_edit_exec_TRAPDEBUG_postproc の代わりに 5864 _ble_builtin_trap_postproc[_ble_builtin_trap_DEBUG] を使う様にすれば良い 5865 だけである。 5866 5867 * #D1853 で最近行った修正について気付いたのだが、実は既に lastarg に改行が 5868 含まれる場合については既に trap/.handler の内側で対処済みであった 5869 (#D1757)。trap string 内の無駄な $_ble_term_nl に関係する消去は除いた。 5870 5871 * _ble_edit_exec_TRAPDEBUG_lastarg も同様に処理する様に変更するべきなのでは 5872 ないか。というか今はどの様に処理しているのだったか→取り敢えず似た様に修 5873 正する事にした。 5874 5875 x fixed: TRAPDEBUG を early return する時に lastexit を復元していなかった。 5876 これは問題である。修正した。 5877 5878 以降は少しずつ TRAPDEBUG の機能を trap/.handler に移植して行く事にする。 5879 5880 * TRAPDEBUG では通常であればユーザートラップは関数の外で postproc を用いて 5881 実行している。一方でこの機能は現在の trap/.handler には存在していない。 5882 5883 この手法の問題はユーザートラップによって設定される lastarg が失われてしま 5884 う事。と考えるとやはり handler の中で実行した方が良いのだろうか。然し、意 5885 図的に trap によって $_ を書き換える事も考えにくいので、やはりこの様にし 5886 て $_ が変わらない様に評価するというのの方が良いのかもしれない。或いはこ 5887 れはオプションで切り替えられる様にする。 5888 5889 * user trap を呼び出す時に ble-attach している時には LINENO を設定している 5890 がどういう事か。これは恐らく LINENO を以前 unset していた為に、trap の中 5891 で LINENO が変な値になってしまう問題があったのだろう。然し現在は LINENO 5892 の機能を上書きしない様にしている。とは言いつつ ble.sh の内部で LINENO を 5893 実行すると関数内部でも一番外側における LINENO が表示されてしまうという問 5894 題がある。 5895 5896 この振る舞いと consistent にする為に今までの様に一番外側の LINENO を設定 5897 していたと考える事もできるが…うーん。どう振る舞わせるのが良いだろうか。 5898 5899 本来の bash における LINENO at trap string は trap/.handler の中では 5900 BASH_LINENO[1] を参照すれば取得できる。但し、これが top-level context の 5901 場合には、 _ble_edit_LINENO を代わりに参照する必要がある。というか、単に 5902 BLE_TRAP_LINENO を修正すれば良いだけなのでは。 5903 5904 * DEBUG も install-hook する? →但し inactive にて。と、思ったが DEBUG の場 5905 合には inactive ともまた微妙に振る舞いが異なる。現状の edit.sh でやってい 5906 る処理のままで良い。 5907 5908 もしかすると DEBUG でやっている様な trap の仕掛け方についても将来的には 5909 ble/builtin/trap に組み込んでも良いかもしれないが今ではない。 5910 5911 2022-08-25 5912 5913 * trap: ユーザーが INT を設定している時は INT によるキャンセルはしない [#D1866] 5914 5915 INT によってコマンドがキャンセルされるのを防ぐ為に trap '' INT としても意味 5916 がない。結局コマンドが中止される処理が走る。 5917 5918 * trap: user trap handler 内で $@ を復元する [#D1865] 5919 5920 2022-08-29 テストが動かなくなった。何故→これは単純なミスだった。shift を実 5921 行したが、それよりも後で $1 を参照している箇所があった。修正した。 5922 5923 * trap: refactor and fix ble/builtin/trap [#D1864] 5924 5925 * ble/builtin/trap 及び blehook 関連のコードが util.sh の中で肥大化して、他 5926 の util 内の関数に対する依存性が問題になってきている。より後ろで定義され 5927 ている関数に依存しているので初期化を遅延させるなどしなければならず不都合 5928 である。コードをもっと後ろに移動する代わりに、ファイルを分離する事にした。 5929 5930 * fixed: 元からあった trap は出力されるのか 5931 5932 これは実装を確認してみると出力されない気がする。実際に試してみるとやはり 5933 出力されない。修正した。 5934 5935 * fixed: そもそも ble/base/unload した時に元の trap を復元するべきなのでは 5936 ないかという気がする。と思って確認してみた所、元から復元する様になってい 5937 た。然しちゃんと動いていない。 5938 5939 * fixed: 然し、trap - INT という設定が外側に伝播しない様だ。EXIT はちゃん 5940 と解除されるが INT と WINCH は外側へ行かない。 5941 5942 と思ったら単に $sig を参照する所を存在しない変数 $index を参照して trap 5943 に渡すシグナル名を決めていたのが原因だった。修正した。 5944 5945 * fixed: というか復元するコードでカスタムシグナルに対しても勝手に trap が 5946 呼び出されてしまう。これは修正するべき。特に install-hook 等を通して設 5947 定された物だけを復元する。 5948 5949 * ok: ble-reload した時に元々ある _ble_builtin_trap_handlers を保持するべき 5950 なのではないか? 現在は上書きしてしまっているので install-hook 経由で設定 5951 されている hook 等は消滅してしまう気がする。 5952 5953 →これは ble/base/unload の際にちゃんと builtin trap を復元する様にしたら 5954 動く様になったので良しとする。 5955 5956 * done: trap CUSTOM なども trap -p で出力 5957 5958 2022-08-24 5959 5960 * trap: RETURN trap はちゃんと動くのだろうか [#D1863] 5961 5962 現在の trap の実装で RETURN はちゃんと設定できるのだろうか? → 試してみた所、 5963 ちゃんと意図した箇所で RETURN trap が呼び出されているが、関係ない場所でも 5964 RETURN が呼び出されてしまっている。更に、設定した関数を抜けた後でも RETURN 5965 が呼び出されている。 5966 5967 本来の Bash の実装を見ると trap RETURN を設定した関数 (追記: とその呼び出し 5968 元) のみで trap RETURN が発火する様である。但し、trap -p / trap -p RETURN 5969 すると何故か関数が抜けた後でも関数内部で使用した RETURN trap が出力される。 5970 然し、trap -p で出力されていてもこれは決して呼び出される事はない様だ。 5971 5972 bash$ function a { trap 'echo RETURN a' RETURN; a2; echo a; }; function a2 { echo a2; }; a; trap -p 5973 a2 5974 a 5975 RETURN a 5976 trap -- 'echo RETURN a' RETURN 5977 ble.sh$ function a { trap 'echo RETURN a' RETURN; a2; echo a; }; function a2 { echo a2; }; a; trap -p 5978 RETURN a 5979 RETURN a 5980 a2 5981 a 5982 RETURN a 5983 trap -- 'echo RETURN a' RETURN 5984 RETURN a 5985 5986 と思ったが、RETURN a が発火している関数を調べてみた 5987 所、_ble_edit_exec_gexec__TRAPDEBUG_adjustだった。そしてこれは declare -ft 5988 を設定している関数なのであった。 5989 5990 % * というか試してみたが実は RETURN は元からそんなに賢い実装ではない様だ。 5991 % 5992 % bash$ function a0 { echo a0; a1; } 5993 % bash$ function a1 { trap 'echo "RETURN:a1"' RETURN; echo a1; a2; } 5994 % bash$ function a2 { trap 'echo "RETURN:a2"' RETURN; echo a2; } 5995 % bash$ a0 5996 % a0 5997 % a1 5998 % a2 5999 % RETURN:a2 6000 % RETURN:a2 6001 % RETURN:a2 6002 % 6003 % 先ず、内側の関数で設定された trap が外側の関数で定義された trap を上書き 6004 % してしまって、関数を抜けた後でもそれが復元される事がない。次に、内側の関 6005 % 数で設定された trap が外側の RETURN を設定しなかった関数でも実行される。 6006 % 6007 % * RETURN trap が ble/builtin/trap に対しても呼び出されてしまう問題に関して 6008 % は、単に RETURN trap の側で上手に処理してもらうべきなのではないか。という 6009 % のも、元から設定した関数とは別の関数で呼び出される可能性があるのだから、 6010 % ちゃんと関数を判定してから実際の処理を行う様に実装してあるべきだからであ 6011 % る。 6012 % 6013 % と思ったが本当だろうか。trap - RETURN をちゃんと実行するようにしていれば 6014 % RETURN が復元されるのではないか。そうでなかったとしても trap - RETURN と 6015 % だけしておけば本来ちゃんと動いたのではないか。 6016 % 6017 % →試してみたらそうだった。RETURN trap の中でちゃんと trap を解除している 6018 % 限りは各関数の RETURN trap が各関数で呼び出されるという形になる様だ。 6019 % 6020 % bash$ function a0 { echo a0; a1; } 6021 % bash$ function a1 { trap 'echo "RETURN:a1"; trap - RETURN' RETURN; echo a1; a2; } 6022 % bash$ function a2 { trap 'echo "RETURN:a2"; trap - RETURN' RETURN; echo a2; } 6023 % bash$ a0 6024 % a0 6025 % a1 6026 % a2 6027 % RETURN:a2 6028 % RETURN:a1 6029 6030 RETURN trap の中でちゃんと 'trap - RETURN' で trap を解除している限りは、 6031 RETURN trap はちゃんと設定した関数の中だけで実行する振る舞いになる。これは 6032 明らかに ble.sh の中では壊れてしまう。 6033 6034 "trap - RETURN" を関数内で実行してもちゃんとその効果は外に持続するだろうか? 6035 6036 $ st() { trap "echo '[RETURN:$1]'" RETURN; } 6037 $ us() { trap - RETURN; } 6038 $ f1() { st f1; echo f1; us; } 6039 $ f1; trap -p 6040 [RETURN:f1] 6041 f1 6042 [RETURN:f1] 6043 trap -- 'echo '\''[RETURN:f1]'\''' RETURN 6044 $ trap - RETURN; trap -p 6045 $ st() { trap "echo '[RETURN:$1]'" RETURN; } 6046 $ us() { trap - RETURN; }; declare -ft us 6047 $ f1() { st f1; echo f1; us; } 6048 $ f1; trap -p 6049 [RETURN:f1] 6050 f1 6051 6052 うーん。駄目持続しない。逆に declare -ft を実行すると削除されるがうーん。もっ 6053 と現実的な設定で実験しないと分からない。 6054 6055 * memo/D1863.RETURN-recursive.sh 6056 6057 意外と簡単にちゃんと動く様にできた。interactive でもスクリプトでも両方と 6058 も期待どおりに動く事を確認した。これと同じ様に実装する事を考える。 6059 6060 うーん。install-hook 等の枠組みを通じて修正するのではなくて RETURN は 6061 RETURN で特別に実装するのが良い気がする。RETURN を設置する時には既存の user 6062 trap を気にする必要もない。単に trap, ble/builtin/trap 内部で発生する 6063 RETURN をスキップするだけで良いのでは? と思ったがスキップする為には結局 6064 trap/.handler の様な複雑な仕組みが必要になる。 6065 6066 実は単に install-hook RETURN inactive にすれば良いという可能性もある? → そ 6067 の様にして見たら各関数ごとに記録されている trap が消滅して駄目だった。trap 6068 を各関数呼び出し階層に対して記録する必要があるのだった。 6069 6070 * どの様に記録してどの様に取り出すかについて落ち着いて考える必要がある。 6071 6072 6073 取り敢えず trap - RETURN されない限りは内側で設定された trap はずっと残る 6074 という事。全ての階層について記録しておいて一番深い階層で記録した物をいつ 6075 も取り出しておくという実装で良いのだろうか。 6076 6077 ? しかし A->B->C1 と呼び出して C1 で設定した trap は A->B では有効である 6078 が、A->B->C2 と更に呼び出した別の関数の中では (C2 が -t を持っていない 6079 限り) 無効の筈である。なので B に戻った時点で C1 のレベルに設定した 6080 handler を除去して B のレベルに再設定するべきではないだろうか。 6081 6082 x と思ったが B に戻った時点を特定する手段がない。結局そのように実装した 6083 としても C2 で有効になってしまうのではないか。 6084 6085 o と思ったが、もし本当に継承されないのだとしたら C2 の中でそもそも 6086 trap/.handler は呼び出されないので気にしなくても良いのではないか。も 6087 し C2 の中で trap/.handler が呼び出されるのだとしたらそれは別の 6088 handler が明示的に設定されたという事であり、その時点で handler が上書 6089 きされてなくなっていると期待して良いのではないか。 6090 6091 ? C2 が -t を持っている場合 (C2/t) や、extdebug/-T が設定されている場合 6092 はどうだろうか。この場合には結局 C1 が設定した handler を呼び出すのが 6093 期待される振る舞いなので handler が C1 のレベルに残留していても特に問 6094 題はない。 6095 6096 ? trap - RETURN した時に別の文脈で設定された handler をどう処理するべきだ 6097 ろうか。基本的には自身のレベルよりも高いレベルの物は全て削除するという 6098 ので良い気がする。然し、別の子関数で設定された物も一緒に削除してしまっ 6099 ては駄目である。 6100 6101 例えば A->B->C1 で設定された handler を A->B->C2/t で trap - RETURN し 6102 た時には 6103 6104 ? というかそもそも A->B->C1 で handler を設定して、その後で A->B->C2 でも 6105 handler を設定して最後に trap - RETURN する場合を考えたら、元々 6106 A->B->C1 に設定した handler は A->B の階層に移動して置かないと問題にな 6107 るのではないか。 6108 6109 と思ったがこれに関しては C2 で handler を新しく設定する時に C2 の階層に 6110 ある handler を B に移動すれば良い? とも思ったがそれだと同じ C2 の呼び 6111 出しで設定した物と区別が付かない。 6112 6113 * extdebug や -T についても確認しておく必要がある → 対応した。 6114 6115 実装した。動いている気がする。FUNCNAME 等が色々面倒な事になるので 6116 BASH_TRAP_{FUNCNAME,SOURCE,LINENO} という変数も提供する事にした。本当はもっ 6117 と色々なパターンでテストするべきの気がするが、 6118 6119 source memo/D1863.RETURN-recursive.sh 6120 6121 が取り敢えず plain Bash と同様に動くのでそれで良い事にする。 6122 6123 * trap: EXIT trap が subshell で発火しない [#D1862] 6124 6125 これは恐らく subshell の中で改めて trap を実行しないと有効にならないのが原 6126 因である。 6127 6128 a subshell の中で初めて trap を実行した場合には改めて同じ trap で trap を実 6129 行する。 6130 6131 b 現在は trap -p の結果と設定しようとしている trap が同一の場合には trap を 6132 スキップしようとしているが、そうではなく毎回ちゃんと実行する様にする。 6133 6134 そもそも同じ trap_command を用いていたからと言って builtin trap の実行を 6135 省略したとしても、そもそも trap 処理自体そんなに思い処理という訳では無い。 6136 なので実行を省略せずに単に毎回実行すれば良いのである。 6137 6138 * done: と思ったが builtin/trap の処理を custom で処理している 6139 ble/builtin/trap:DEBUG 等の関数についてはどうすれば良いのか。うーん。こ 6140 れは ble/builtin/trap:DEBUG 等の関数が存在する時に限ってはちゃんと設定 6141 するという事にすれば良い。 6142 6143 * ok: 然し、その時に疑問なのは DEBUG や ERR や RETURN の様な関数の外側に 6144 対して効果を持たないものがどう振る舞うかという事。うーん。これは落ち着 6145 いて考えたら実は気にしなくても良いかもしれない。 6146 6147 うーん。trap を関数内で実行した時に外に設定が反映されないかもしれないと 6148 いうのが以前の問題だった。一方で、今回は余分に trap を実行した時に外に 6149 影響を与えないかという事である。これは外に影響を与えたとしても与えなかっ 6150 たとしても結局振る舞いは同じ筈なので問題にならない筈である。 6151 6152 * done: WINCH 等の様に readline が介入する物についてどうするのか。これに 6153 関しては subshell で実行している限りは、元々の bash の時点で readline 6154 の hook が設定されないと思われるので気にしなくて良いのではないか。 6155 6156 * done: 確認してみたらそもそもそのような trap/hook に対しては subshell 6157 かどうかの判定を install-hook の時点で行っている。今、新しく trap の 6158 中でも builtin trap を再設置するという様に変更した時、同様の判定が必 6159 要になるのではないだろうか。つまり、subshell の外で実行している時には 6160 readline の介入を破壊しない為に再設置を抑制する。 6161 6162 subshell の中では元々 readline の介入を期待できない (恐らく) ので気に 6163 しなくて良い。 6164 6165 c subshell の中で実行する trap の場合には実は ble.sh による介入は不要になる 6166 のでは。だとすれば単にそのまま builtin trap すれば良い。 6167 6168 EXIT は後述の様に EXIT で ble.sh の終了処理をする為に用いている。 6169 6170 INT はコマンド実行時に ble.sh の処理までキャンセルしてしまわない為に用い 6171 ている。問題の処理は親シェルで行う物なので subshell の中では特に特別な事 6172 はしなくて良い。 6173 6174 % WINCH についても read の中で subshell で使ってはいるが、~~中で改めて設 6175 % 定を行うので~~ trap は自分では実行しないので問題ない。結局設置済みの 6176 % trap WINCH から blehook internal_WINCH 経由で処理を行っている。と思った 6177 % が本当だろうか。本当に read の中で WINCH は呼び出されるのだろうか…と思っ 6178 % たが、やはり確認してみたところちゃんと read の中で install-hook を呼び 6179 % 出しているのでやはり改めて設定はしているのだろう。 6180 6181 WINCH についても親シェルで設定している WINCH への介入を ble.sh でもすると 6182 いう事はない気がする 6183 6184 ? 但し、子プロセスが WINCH を受け取って親シェルがそれを逃した場合には何が 6185 起こるのだろうか?)。 6186 6187 ble-bind -x C-t 'x=$(sleep 5);echo hello;sleep 1' 6188 6189 試してみた所、ちゃんと再配置計算が subshell の外で呼び出される様である。 6190 中で WINCH が呼び出されている気がする。なので子プロセスが受け取ったもの 6191 を更に自分で親シェルに伝達する等という処理は必要ない気がする。 6192 6193 上記は b を採用した。 6194 6195 * そもそも blehook EXIT は親シェルの終了時に呼び出される事を想定して作って 6196 いた。なので、今 subshell の中でも EXIT trap が走る様に変更すると変な事に 6197 なってしまう。 6198 6199 Note: ble/base/unload は ble/builtin/trap/.handler から直接呼び出されてい 6200 る (#D1797)。他に ble/history:bash/TRAPEXIT が登録されている。逆に言えば 6201 subshell EXIT では ble.sh による介入は不要である。 6202 6203 ? blehook EXIT を subshell で使おうと思っても、trap EXIT をユーザーが 6204 subshell で実行しなければ、そもそも subshell の中では有効ではないのでは 6205 ないか。なので blehook EXIT は subshell の中で使えない様にするべきでは 6206 ないのか。 6207 6208 a うーん。この様に微妙な振る舞いになるのだとしたら EXIT は元よりユーザー 6209 には提供しないという事にするべきか。でもそれだとユーザーは trap EXIT 6210 を使わなければならず、一個しか登録できないので自前で色々管理しなけれ 6211 ばならない。blehook はその管理の煩雑さを解決する為に導入した物なので 6212 やはり機能として保持したい。 6213 6214 b 或いは BASHPID 毎に blehook EXIT の内容を記録する事にするか。blehook 6215 に変更があった場合には改めて builtin trap を実行する。 6216 6217 c 或いは開き直って blehook SIGNAL は親シェルのみで発火するという事にし 6218 ても良い。一方で internal_EXIT 等の方については subshell でも実行する 6219 というので良い。そうでないと WINCH 等の処理ができなくなってしまう。 6220 6221 ユーザーが subshell で WINCH を受信したいという状況はあるだろうか? と 6222 思ったが、そもそも subshell に WINCH は元から継承されないし、改めて 6223 trap WINCH をする事になっている。代わりに、"改めて blehook WINCH を設 6224 定する" 方式にしたとしても元から存在している hook をどうしたら良いの 6225 かなど、色々と面倒な事が存在する。という事を考えると、やはり WINCH で 6226 あっても subshell 内では blehook WINCH を一括で呼び出すという様な事は 6227 しない事にする。 6228 6229 うーん。blehook EXIT や blehook INT については c が現実的な気がしてきた。 6230 もしそうだとすればやはり UNLOAD は不要なのではないかという疑惑。と思っ 6231 たが物事は単純ではない。 6232 6233 実際にユーザーに需要がありそうな物は EXIT である (親シェルでしか呼び出 6234 されないとしても)。一方で、ble.sh の内部処理はユーザーの blehook と分離 6235 しておきたい。だとすれば internal_EXIT に登録すれば良いのかというとそう 6236 でもない。何故なら 1) internal_EXIT は EXIT の前に実行されるが、処理の 6237 順序でユーザーの EXIT を実行する前に ble.sh の終了処理をする訳には行か 6238 ない。 2) internal_EXIT は今迄の議論だと subshell かどうかに関係なく実 6239 行するという事になっている。これは blehook EXIT だけでなく通常の trap 6240 EXIT の処理の前処理でもあるからである。という事を考えると内部処理用の 6241 unload hook を用意するのが良い。 6242 6243 →c で実装することにした。 6244 6245 ? ok: 更に上記の事は INT など他の trap でも同様でないか確認しておきたい → 6246 うーん。INT の場合に試してみたがどうも C-c を送ると親シェルがそれを受け 6247 取って処理するのでサブシェルの trap INT は元々呼び出されない様だ。 6248 6249 つまり個別に考えるべきの気がしてきた。 6250 6251 * EXIT の代わりに unload という blehook を導入する事にした。今までの終了 6252 処理は unload で実行する事にして blehook EXIT は trap EXIT と等価な物と 6253 いう事にする。また ble/base/unload は親シェルの中にいる時だけ 6254 trap/.handler から呼び出す。 6255 6256 →と思ったら既に unload は存在していた。しかし誰も使っていない。今まで 6257 history が unload を使わずに EXIT を使っていたのは何か理由があったのだ 6258 ろうか。特に理由もないし寧ろ unload で実行するべき気がしたので単にそれ 6259 を使う様に変更した。 6260 6261 更に、ble/base/unload の subshell かどうかの判定も、既に 6262 ble/base/unload の中に存在していた。 6263 6264 * reject: wiki: EXIT や INT などの blehook は親シェル (main shell) でしか呼 6265 び出されない。WINCH についても → 改めて確認してみたがそもそも INT や 6266 WINCH は wiki に記述されていなかった。EXIT は既に記述として Bash が終了す 6267 る時に呼び出されるとしているので変更しなくて良い。 6268 6269 ? subshell で本当に INT は継承されないのか? 6270 6271 % 先程試した時はコマンド置換 $() でしか試していない。 6272 % 6273 % $ (trap 'echo INT2' INT; echo do;sleep 5;echo done) 6274 % do 6275 % ^CINT2 6276 % done 6277 % $ trap 'echo INT1' INT; (trap 'echo INT2' INT; echo do;sleep 5;echo done) 6278 % do 6279 % ^CINT2 6280 % done 6281 % $ trap 'echo INT1' INT; (echo do;sleep 5;echo done) 6282 % do 6283 % ^C 6284 % 6285 % →やはり外側の INT は継承されない様だ。 6286 % 6287 % 一方で subshell 内部で改めて設定した trap は有効になる。これはコマンド置 6288 % 換の時とは違う。コマンド置換の時には内側の INT の前に外側の trap が INT 6289 % を捉えてしまい、コマンド置換自体を別の方法で強制的に終了してしまう。或い 6290 % は SIGPIPE か SIGTERM が呼ばれていたのかもしれない。と思って色々試したが 6291 % どうもいかなるシグナルも受信していない様だ。もしかすると単純に sleep 5 が 6292 % 中断されるだけで続きの物も実行されるのかと思ったらそうだった。 6293 % 6294 % $ echo $(for sig in INT QUIT TRAP ABRT PIPE ALRM TERM; do trap "echo $sig >/dev/tty" "$sig";done;echo do >/dev/tty; sleep 5; echo done >/dev/tty) 6295 % 6296 % というかその振る舞いは通常の subshell も同じだった。subshell ではなくて一 6297 % 番上で実行しても同じなのであった。というか sleep を実行中に受信した INT 6298 % は結局 bash 側では全く処理されないのであった。 6299 6300 sleep 5 だと sleep が INT を食ってしまって bash の trap INT が呼び出され 6301 ない事があるのでので正しく振る舞いを調べられない事が判明した。改めて busy 6302 wait 等を用いてそれに対して INT を送信して試す必要がある。 6303 6304 # see memo/D1862.INT-in-subshell.sh 6305 6306 $ set_trap;process_something 6307 do 6308 ^CINT 6309 6310 $ (set_trap;process_something) 6311 do 6312 ^CINT 6313 6314 $ echo $(set_trap;process_something) 6315 do 6316 ^CINT 6317 done 6318 $ set_trap;(process_something) 6319 do 6320 ^C 6321 $ set_trap;echo $(process_something) 6322 do 6323 ^C 6324 INT (これは単に外側のシェルで発生した trap INT である) 6325 6326 うーん。直接・サブシェル() の場合には INT で中断する事ができる。コマンド 6327 置換の時には trap は発動するが kill -INT $BASHPID によって自身を中断でき 6328 ていない。そして、外部で設定された trap は何れにしても subshell の中では 6329 発火しない。 6330 6331 # see memo/D1862.INT-in-subshell.sh 6332 6333 $ echo $(set_trap; process_something) 6334 start 6335 ^CINT 6336 end 6337 6338 $ echo $(set_trap; process_something) 6339 start 6340 ^CINT 6341 end 6342 6343 $ (set_trap; process_something) 6344 start 6345 ^CINT 6346 6347 $ echo $(process_something) 6348 start 6349 ^C 6350 6351 うーん。コマンド置換の内部で INT に処理を追加しつつ自身を中断させる方法が 6352 謎。trap を設定していなければその場で INT で終了する。trap INT を単に設定 6353 しただけだと当然 INT による中断は発生しない。一方で trap - INT して kill 6354 -INT $BASHPID しても何故か何の効果も発生しない。 6355 6356 これは bash-dev 特有の問題だろうか。調べてみた所、先ずスクリプトでは発生 6357 せず interactive session で発生する。4.3 まではちゃんとその場で終了する。 6358 4.4 と 5.0 では何故かコマンド置換はその場で終了するが、裏でプロセスが走っ 6359 ていて後になって "end" が出力される。5.1 と dev ではコマンド置換の実行が 6360 待たされる。変な振る舞いだが仕方がない。 6361 6362 2022-08-21 6363 6364 * blehook: wildcard @ に対応する [#D1861] 6365 6366 bleopt, ble-face が対応しているのに blehook が対応していないのは混乱の元。 6367 実際に使いたくなるので対応する。 6368 6369 * history: blehook history_* を blehook history_onchange に統合する [#D1860] 6370 6371 history_{delete,insert,clear} は何れも同じ箇所でセットで登録している。だと 6372 したらわざわざ別の hook にしている意味もない。逆に一貫性を考えたら一つの登 6373 録で全てを一貫した方法で処理しなければならない。 6374 6375 統合した hook の名前については結局 history_change にする事にした。結局 on 6376 をつけ始めたら殆ど全てに on を付けなければならなく成るので余り付けても意味 6377 がない。同様に history_onleave も history_leave に改名する事にする。 6378 6379 * util (ble-import): 調整する [#D1859] 6380 6381 * done: source 時の引数の継承についてチェックする 6382 * done: 既にロード済みのファイル一覧 --list, --list-imported → これは -q, 6383 --query という名前で登録した。 6384 * done: ble-import --help でもっとちゃんとした説明を表示する (wiki も参考) 6385 * done: wiki update. -f の説明がない。-q の説明も追加する。 6386 6387 * blehook: ERR 関連の動作が怪しい [#D1858] 6388 6389 x fixed: 更に ble/builtin/trap 経由で設定した通常の trap が 6390 ble/builtin/trap 経由で削除できていない気がする。USR2 等、他の通常シグナ 6391 ルに対してはちゃんと削除できているので、これは EXIT 等の特別 trap に特有 6392 のバグの気がする。 6393 6394 取り敢えずこれを最初に修正する事にする。 6395 6396 振る舞いを調べてみた所、どうやら関数内部から外側の trap ERR を削除する事 6397 ができない様である。 6398 6399 $ function trapERR { builtin trap "${1--}" ERR; trap -p; }; declare -ft trapERR 6400 $ trapERR 'echo trap ERR'; trap -p 6401 trap -- 'echo trap ERR' ERR 6402 trap -- 'echo trap ERR' ERR 6403 $ trapERR; echo x; trap -p 6404 x 6405 trap -- 'echo trap ERR' ERR 6406 $ declare -pf trapERR 6407 trapERR () 6408 { 6409 builtin trap "${1--}" ERR; 6410 trap -p 6411 } 6412 declare -ft trapERR 6413 6414 declare -ft をしても駄目だった。set -T でも駄目。bash-dev でも駄目。 6415 bash-3.0 でも駄目。set -E を設定していれば OK。但し、trap - ERR を実行す 6416 る瞬間だけ set -E をしていても意味はない。 6417 6418 $ function trapERR { set -E; builtin trap "${1--}" ERR; set +E; trap -p; } 6419 $ trapERR 'echo trap ERR'; trap -p 6420 trap -- 'echo trap ERR' ERR 6421 trap -- 'echo trap ERR' ERR 6422 $ trapERR; echo x; trap -p 6423 x 6424 trap -- 'echo trap ERR' ERR 6425 6426 仕方がないので ERR を削除したい時に限っては代わりに空文字列を 6427 trap string として設定する事にする。 6428 6429 ? trap ERR を設定すると ble.sh の内部処理に対しても trap が呼び出される。特 6430 にコマンドが失敗した後の何らかの処理に対して複数回呼び出されている。成功 6431 したコマンドの後では呼び出されていない様なので、これはちゃんと実装すれば 6432 回避可能な物なのではないだろうか。或いは ERR の実装を誤っているか。 6433 6434 また失敗したコマンドに対して重複して ERR trap が実行されているのも気にな 6435 る。これは調べる必要がある。 6436 6437 ? というよりそもそもこの ERR は SIGERR と同じ物を意図して追加した物なのだ 6438 ろうか。zsh の hooks を確認してみると、その下に TRAPERR と TRAPZERR が 6439 言及されていて、これらは trap の物と大体同一である様だ。つまり各リスト 6440 に対して実行される。 6441 6442 うーん。然し、改めて考えて見るにコマンド実行後の ERR の場合に使う ERRと、 6443 各トップレベルコマンドの設定に使う ERR は区別するべきの様な気がする。どち 6444 らもあった方が良い様な気がするのは難しいところではある。 6445 6446 取り敢えず現状の実装では blehook ERR に登録しても SIGERR に対しては発火し 6447 ない実装になっている。一方で、blehook ERR は SIGERR を誘導する様になって 6448 いる。 6449 6450 * done: うーん。ERR がユーザーによって設定されている時に限って builtin 6451 trap を設定する仕組みを整えたい。install-hook だと強制的に必ず設定を行 6452 う様になっているが → 実装した。動いている。 6453 6454 * done: エラーが起こった時に呼び出される hook は ERREXEC に改名する事にする。 6455 6456 * done: internal_NAME から通常のシグナルの実行をキャンセルする仕組みを整 6457 える。ble.sh 内部の ERR に対しては user ERR trap を発火しない様にする。 6458 6459 取り敢えず実装したが bash-3.2 で無限ループになっている。何故だろう。 6460 と思ったが発火しない処理を追加したら問題は発生しなくなった。 6461 6462 * done: trap に対して BASH_COMMAND を伝播する。bash-3.0,3.1 はそもそも 6463 trap による BASH_COMMAND には対応していない様なので設定しなくて良い 6464 →代わりに _ble_edit_exec_BASH_COMMAND を設定する事にした。 6465 6466 ? ok: 無限ループの最中に発生した ble/builtin/history: unknown option -- 6467 は何だったのか? 少なくとも history -- 1 等はちゃんと動いている。うーん。 6468 もしかすると history -xx-yy の様な引数が渡されたという事なのかもしれな 6469 い。何れにしても今は発生していない問題なので気にしない。 6470 6471 * done: wiki: blehook ERR を ERREXEC に改名。 6472 6473 * reject: 改名に関する枠組みを整える必要はあるだろうか? うーん。ble-0.4 6474 は開発版だし、特に ERR に関しては trap ERR を意図して設定した物と 6475 ERREXEC を意図して設定した物が混ざって混乱の元なので、改名についての 6476 提案はしない事にする。 6477 6478 ? done: history の呼び出しを確認した所 history 1 を builtin なしで直接呼び 6479 出している箇所があるようだ。確認して修正が必要なら修正する。→これは単純 6480 な builtin つけ忘れだったので修正した。 6481 6482 変更点 6483 6484 * TRAPERR は廃止した。以下の場所で言及があるが廃止された旨をコメントする。 6485 https://superuser.com/questions/1512618/autocompletion-background-colour-in-ble-sh 6486 6487 * blehook ERR は trap ERR と分離して ERREXEC に改名した 6488 6489 * 2022-07-13 blehook: blehook の出力結果を init.sh にそのまま載せている人がいる [#D1857] 6490 6491 これだと += なので重複してハンドラーが登録されてしまう。 6492 6493 設定を保存・復元する為に a=$(blehook) として後で eval "$a" する様な使い方も 6494 考えられるので、最初の項目については += ではなく = にするべきではないか。うー 6495 ん。然しそれだと後で設定を merge する時に不便なのではないか。色々考えるとど 6496 うするのが便利なのかは非自明になってくるが、やはり自然な実装という事を考え 6497 たら設定を完全に復元するのに使えるコマンドという事で、最初の項目が = で追加 6498 が += という形にするべきである。 6499 6500 * 2022-07-13 blehook: 内部 hook はユーザーに見えない様にするべきの気もする [#D1856] 6501 6502 つまり同名の小文字 hook を用意してそちらに登録する。hook の発火については呼 6503 び出し元で両方とも呼び出す。入れ子にするという手もあるが色々変な事が起こる 6504 と嫌なので並列にする。 6505 6506 内部使用の trap について確認する。contrib 等によって設定される物は、ユーザー 6507 から見えても良いので、除外する。 6508 6509 * done: blehook DA2R='ble/color/initialize-term-colors' 6510 6511 これはそもそも内部的に使用する hook であって、全て大文字なのは導入時の偶々 6512 の決定だった。後で大文字 = public という事になったので、初めから public 6513 にする意図があった訳では無い。undocumented でもある。なので、これは 6514 term_DA2R に改名してユーザーからは見えない様にする。 6515 6516 * done/checked: blehook ERR='ble/builtin/trap/invoke ERR' 6517 * done/checked: blehook PRECMD='ble/keymap:vi/update-mode-indicator' 6518 6519 * 実は今まで必ず PRECMD が設定されている事により状態 (PS1) の待避・復元が 6520 毎回実行されるという事態になっていた。つまり、本来はユーザーによって設 6521 定された hook もしくは PROMPT_COMMAND がある時にのみ必要だった退避処理 6522 が毎回実行されていたという事。今回新しく internal_PRECMD と PRECMD を分 6523 離した事により待避が必要な時にのみ実行される様になった。 6524 6525 改めて確認した所、待避・復元されている状態は既定では PS1 だけだったので 6526 大した違いはないかもしれない。但し、bleopt 6527 prompt_command_changes_layout が設定されている時には再描画等の複雑な処 6528 理が実行されていた (が、もしユーザーがこの設定変数を設定しているのであ 6529 れば恐らく PROMPT_COMMAND が設定されているので何れにしても再描画は毎回 6530 実行されたのだろうという気はする)。という事を考えるとこの事は大した影響 6531 はなかったと思われる。 6532 6533 * done/checked: blehook EXIT='ble/history:bash/TRAPEXIT' 6534 * done/checked: blehook INT='ble-edit/exec:gexec/.TRAPINT' 6535 * done/checked: blehook WINCH='ble-edit/attach/TRAPWINCH' 6536 6537 * blehook ERR+='ble/function#try TRAPERR' 6538 6539 これは削除しても良いのではないか。undocumented でもある。うーん。取り敢え 6540 ず ERR についての別項目でまとめて対処する事にする。 6541 6542 2022-07-29 6543 6544 * test: cd -P . / README からリンク for nixpkgs (reported by aiotter) [#D1855] 6545 6546 - blesh-share を実行するとスクリプトのファイル名が返される。実際に動かそう 6547 と思うと色々他にも変な所がある。修正するべき。 6548 6549 - LC_ALL が設定されている…。これは大丈夫なのだろうか→調べてみたが ble.sh 6550 の関数は全て LC_ALL に対する対策が個別に為されている様なので気にしなくて 6551 良い。 6552 6553 取り敢えず cd -P . だけは追加して後は nixpkgs 側は変更を依頼する。所で 6554 nixpkgs の各パッケージについての問い合わせ方法・問い合わせ先はあるのだろう 6555 か。maintainer の情報は埋め込まれているが連絡先は書かれていない。 6556 6557 * edit: display-shell-version (C-x C-v) で /etc/os-release も参照する [#D1854] 6558 6559 /etc/os-release の中の NAME= と VERSION= を見れば良さそう? 6560 6561 OpenSUSE は VERSION が何故かコメントアウトされている。PRETTY_NAME はある。 6562 VoidLinux は NAME=void である。VERSION は存在しない。PRETTY_NAME はある。 6563 Arch も VoidLinux と似たような物である。 6564 FreeBSD も実は /etc/os-release を持っている。 6565 6566 - Solaris は /etc/release を持っているが中身はシェルスクリプトではなくテキ 6567 ストファイルである。一番最初の行を抜き出して trim したら OS の名称になる 6568 だろう。 6569 6570 - Minix にも /etc/release があってこれはやはりテキストファイルだった。然し 6571 何故か NetBSD 3.3 と書かれている。もしかして Minix は Minix kernel の上に 6572 NetBSD のパッケージを載せているという事なのか? 調べてみたら Minix 3.2 以 6573 降では NetBSD technology を導入するという様な記事があった。 6574 6575 逆に言えば NetBSD でも /etc/release があって一行目にその情報が書かれてい 6576 るという事だろうか。 6577 6578 * 取り敢えず OS 名は抽出する様にした。 6579 6580 * done: 更に待避した locale 変数も元の状態をできるだけ再現する様にして表示 6581 する事にする。 6582 6583 2022-07-24 6584 6585 * edit: starship (DEBUG trap) がある時に $_ が正しく復元されない [#D1853] 6586 https://github.com/akinomyoga/ble.sh/issues/215 6587 6588 starship で再現。starship の DEBUG trap の処理後に $_ の再設定ができていな 6589 い。以前に関連する項目があった筈。 6590 6591 * 現在の実装を見たら DEBUG に関しては lastarg の復元を諦めていて、その他の 6592 trap の場合には eval に \# つきで渡していた。その他の trap の時に lastarg 6593 の2行目以降が eval によってコマンドとして実行されてしまうという問題がある 6594 のではないか。この問題は認識していた筈である。不完全な状態で放置されてい 6595 たという事だろうか。 6596 6597 何故今中途半端な実装になっているのか、過去の記録について洗ってみる。 6598 6599 * ToDo 2022-02-20 に複数行 lastarg に対する処置の方法の可能性についての言及 6600 がある。と思ったが具体的に heredoc でどの様にこれを再現するのか? 当時何を 6601 考えていたか思い出せない。 6602 6603 例えば以下の様な形にするという事を考えていた様な気がする (32 は使われそう 6604 にない fd)。 6605 6606 eval 32<<xxx \# xxx 6607 yyy 6608 zzz 6609 6610 然し、この方法も最終行の内容が "単語" の形をしている時にしか使えない。そ 6611 れに毎回無駄なパイプまたはファイルを開くのは嫌な感じがする。 6612 6613 * 時期と内容的に #D1782 の対処の時にこの対策を部分的に実装したと思われるが、 6614 見る限りは #D1782 ではこれについての議論は行っていない。 6615 6616 * と思ったが blame して確認してみると dfc62211 (#D1757) で変更されている。 6617 議論 #D1757 のコメントを見たが複数行 lastarg で発生しうる問題については言 6618 及されていない。この時点 (2022-02-02) では気づいていなかったという事なの 6619 だろうか。 6620 6621 結局、DEBUG 以外の trap で複数行 lastarg の場合に問題が起こるのは、単に気づ 6622 いていなかっただけ + 後で気づいたが ToDo に入れて放置していただけである。 6623 6624 取り敢えず暫定的な対策としては lastarg の最初の行までだけを復元するという事。 6625 本当に対策しようと思ったらどの様にするのが良いのかは不明である。(1) DEBUG 6626 の中で return/continue/break 等の制御コマンドを実行した場合に正しく動作しな 6627 いか、(2) $_ を正しく復元できないか のどちらかを選ぶしかない。DEBUG の本来 6628 の目的を考えると制御コマンドは使えないと変である。一方で本来の使い方とは異 6629 なるおかしな使い方が世に蔓延っている。 6630 6631 * ble-reload の時に最初に指定した rcfile, norc を反映するべきではないか [#D1852] 6632 6633 --norc を指定して起動したセッションでも ble-reload をした時に ~/.blerc を読 6634 み込んでしまっている。 6635 6636 元の引数を全て保持する様にしようと考えたが微妙かもしれない。というのも、元 6637 の引数には --norc 等の引数も指定されているかもしれない。これは bashrc の中 6638 で別に ble-attach を呼び出す事を前提としている物なので ble-reload の時にま 6639 で継承するべきではない。更に --test や --lib 等の別の引数が指定されていた時 6640 にもどの様に取り扱うのか微妙である。 6641 6642 という事を考えると、特定の予め選んだオプションについてだけ記録して再指定す 6643 るべきである。というか特に blerc だけ復元すれば良い気がする。 6644 6645 * starship ble-reload で無限ループ (reported by tars0x9752) [#D1851] 6646 https://github.com/akinomyoga/ble.sh/discussions/212#discussioncomment-3205291 6647 6648 自分の手許でやってみた範囲では発生していない。starship を先に初期化してから 6649 ble.sh を有効にしている時に発生する。ble.sh を先に初期化してから starship 6650 を初期化しても再現しない。source ble.sh --noattach, eval starship init, 6651 ble-attach, ble-reload の順番で実行しても再現しない。 6652 6653 nightly を使っているそうなので ble.sh の version の違いではないだろう。 6654 6655 問題のファイルを開きすぎですのエラーが出ている箇所で関数呼び出しスタックを 6656 確認してもらった所、以下の様な結果になった。 6657 6658 | ble/function#advice/before:ble/util/assign 6659 | ble/function#try 6660 | ble/function#advice/.proc 6661 | ble/util/assign 6662 | ble/builtin/trap/install-hook 6663 | ble-edit/attach/.attach ble-edit/attach 6664 | { 6665 | ble/base/attach-from-PROMPT_COMMAND 6666 | ble/function#lambda/0 starship_precmd 6667 | _ble_prompt_update__eval_prompt_command_1 6668 | ble/prompt/update/.eval-prompt_command 6669 | } * 沢山繰り返し 6670 | ble/base/attach-from-PROMPT_COMMAND 6671 | ble/function#lambda/1 6672 | blehook/invoke.sandbox blehook/invoke 6673 | ble-edit/exec:gexec/invoke-hook-with-setexit 6674 | ble/prompt/update ble/application/render 6675 | ble-edit/bind/.tail 6676 | ble-edit/exec:gexec/.end 6677 6678 うーん。再帰呼び出しを防ぐ様な仕組みがあった様な気がするがそれはどうなった 6679 のだったか。改めて確認してみる事にする。うーん。確かにその仕組はあるが、再 6680 帰的に呼び出した際には再帰的に実行される様である。 6681 6682 % 自分の手元で改めて再現を試みているが再現しない。starship の他にも更に別の 6683 % PROMPT_COMMAND を触る設定も読み込んだ時には発生するという事なのではないか。 6684 % 6685 % * 再現はしないが何が起こっているかは分かっている。此処での疑問は何故毎回 6686 % eval-prompt_command を実行する必要があったのかという事である。 6687 % 6688 % 入れ子で呼び出す時に…うーん。これは以前の PROMPT_COMMAND を利用した開始 6689 % 時刻の判定などの為の可能性もある。改めて過去の議論を確認する。 6690 % 6691 % * #D1778 が多少関係しているのではないか。そもそも eval prompt_command を此 6692 % 処で実行する必要性がよく分からない。 6693 % 6694 % →もし PROMPT_COMMAND 経由で attach が呼び出されるのだとしたら、ここで 6695 % eval prompt_command を実行しなくても更に外側で PROMPT_COMMAND の続きの 6696 % 処理が実行された時に必要な処理が行われるのではないか。然し、これは 6697 % PROMPT_COMMAND の後続の設定で PS1 の設定などが行われている時に問題であ 6698 % る。更に、PROMPT_COMMAND の中から様々の出力や端末に対する問い合わせの 6699 % seq 等を送出するという場合にも問題になるかもしれない。 6700 % 6701 % なので、やはり少なくとも一回は eval prompt_command を此処で実行する必要が 6702 % ある。一方で、入れ子で呼び出された回数だけ実行する必要性は謎である。うー 6703 % ん。普通に考えて不要に思われる。 6704 % 6705 % * 然し改めて再帰呼び出しのコードを見ると save_index を指定して 6706 % PROMPT_COMMAND を呼び出している。つまり、save_index による無限ループが発 6707 % 生しない限りはこの様な事にはならない筈なのである。うーん。不思議だ。 6708 % 6709 % とここまで来て分かった様な気がする。save_index を使っている時は 6710 % PROMPT_COMMAND に値を設定して古い PROMPT_COMMAND の実行を行っている。もし 6711 % この時に他の PROMPT_COMMAND[] 要素にも値が設定されていたらどうなるか。そ 6712 % れらも一緒に呼び出されてしまう。特に starship がそこから既存の 6713 % PROMPT_COMMAND を呼び出そうとした時に其処に attach-from-PROMPT_COMMAND が 6714 % 入っていると無限ループが発生する。 6715 % 6716 % 然し、そもそも save_index を使うのは array PROMPT_COMMAND が使えない時で 6717 % はなかったか。つまり、bash 5.0 以下。然し一方で starship がもし bash-5.0 6718 % 以下であるにも拘らずに PROMPT_COMMAND 配列に何か設定した場合には何が起こ 6719 % るか? Fedora 36 の starship (1.2.1 2022-02) で 6720 % 6721 % $ starship init bash --print-full-init 6722 % 6723 % の結果を見ても PROMPT_COMMAND は scalar だと思っている様だ。或いは最近の 6724 % starship で配列 PROMPT_COMMAND に対応する様になったのかもしれない。 6725 % 6726 % 実際に報告によると使っている bash は bash 5.0 の様だ。 6727 6728 うーん。ここまで来て bash 5.0 で試したら再現した。starship の出力を見る限り 6729 は別に PROMPT_COMMAND に配列で設定を行っている訳でもない。具体的に何が起こっ 6730 ているのか確認する。 6731 6732 何が起こっているのか何となく分かった。最初に 6733 6734 starship_precmd -> attach-from-PROMPT_COMMAND 0 -> empty 6735 6736 が設定される。然し、ble-reload の際に 6737 6738 attach-from-PROMPT_COMMAND 0 -> starship_precmd 6739 6740 が設定されるが、以前の attach-from-PROMPT_COMMAND 0 が starshop_precmd の中 6741 に保存されているので starship_precmd がそれを呼び出して、その事によって無限 6742 ループになっている。 6743 6744 うーん。unload する時に starship_precmd の中に記録されている前回の attach 6745 用のコードを除去しなければならないが、それができていないという事。この時に 6746 どうすれば良いか。。うーん。 6747 6748 ? そもそも入れ子で attach-from-PROMPT_COMMAND を呼び出す事を許可しているの 6749 は何故だったか。また入れ子になった呼び出しの各階層における PROMPT_COMMAND 6750 の書き換えをちゃんと追跡しているのは何故だったか。そもそも複数回の 6751 install-prompt-attach を実行していなければ複数の 6752 attach-from-PROMPT_COMMAND が起こる事はないのではないかという気がするが、 6753 何故その様な事を考慮に入れていたのだったか。 6754 6755 或いはそれこそ ble-reload をした時に前に設定されていた内容が消滅してしま 6756 わない様にする為だったかもしれない。つまり、 6757 _ble_base_attach_PROMPT_COMMAND に格納された元の PROMPT_COMMAND が 6758 ble-reload した後に使えなくなってしまうと行けないが、PROMPT_COMMAND は既 6759 に更に別の物によって上書きされてしまっている為に単純に復元できない。その 6760 時は unload するとしても attach-from-PROMPT_COMMAND はそのままにして、昔 6761 の _ble_base_attach_PROMPT_COMMAND を引き続き呼び出させる。という具合になっ 6762 ているのではないか。 6763 6764 なのだとすると、初期化の際に _ble_base_attach_PROMPT_COMMAND を上書きして 6765 クリアしてしまうという実装が誤っているという事。 6766 6767 * check: 元々この仕組は #D1650 (39ebf533) で導入された。然しこの時から既に 6768 記録用の配列はロード時に空に初期化してしまっていた。本当に当初の意図は複 6769 数回の ble.sh のロードだったのだろうか。 6770 6771 →この時の記録を見てみると別に複数回のロードの事を考慮した訳ではなくて、 6772 単に念の為に「何らかの要因」で複数回設定された時に無限ループを防ぐという 6773 物だった様に読める。然しその何らかの要因として ble.sh の複数回ロードは想 6774 定していなかったし、従って複数回のロードに跨って記録配列を保持するという 6775 事は考えていなかったという事である。 6776 6777 * done: PROMPT_COMMAND 配列が bash 5.0 以下で設定されている時の対策をする。 6778 6779 これは報告にあった物とは関係ないがこれも対策しておくべきである。これは 6780 PROMPT_COMMAND と lambda が一致している場合でも横着せずに毎回 6781 PROMPT_COMMAND を local 変数として設定して処理する様にした。一致している 6782 場合には unlocal した後に改めて値を設定し直す事によって処理する。 6783 6784 * util: starship で ble-reload した後に C-d で抜けると滅茶苦茶沢山のログが出る [#D1850] 6785 6786 declare が無引数で呼び出されているという事だろうか。ble-reload していない時 6787 には関係ない。EXIT trap を先ず確認するのが良いだろう → blehook EXIT= とし 6788 ても同様に問題が生じる。trap - EXIT とすると問題は発生せずに exit する事が 6789 できる。 6790 6791 どうも trap handler に "set" という文字列が登録されている様だ。何故? 実際に 6792 trap handler の配列を見てみると以下の様になっている。 6793 6794 declare -a _ble_builtin_trap_handlers=([0]="set") 6795 6796 因みに starship init bash の出力には trap も set も含まれてはいない。うーん。 6797 実際に値を設定している箇所は一箇所しかない様な気がする。確認する。確認して 6798 みた所、実際に ble/builtin/trap -- set EXIT という呼び出しが行われている。 6799 6800 これは元々設定されていたtrapを再設定する時に、元々設定されていたtrapの抽出 6801 に失敗しているという事だろうか。ble/builtin/trap の呼び出し元を確認すると 6802 6803 ble/builtin/trap/install-hook 6804 6805 であった。やはり既存設定の抽出に失敗しているという事だろう → うーん。何故 6806 か builtin trap -p EXIT の結果が本当に trap -- set EXIT になっている様だ。 6807 何事だろうか。unload の差異に set を設定する様になっている可能性? というの 6808 も変な気がする。だとしたら starship と関係ないはず。 6809 6810 どうも ble/base/unload-for-reload に於いて trap -- set EXIT が設定されてい 6811 る様である。つまり、元々の trap を設定する際に誤って set を設定してしまって 6812 いる。 6813 6814 これは結局単純なミスだった。 6815 6816 * main, util: make check が nix-build @ macOS で失敗する (reported by aiotter) [#D1849] 6817 https://github.com/NixOS/nixpkgs/pull/181963#issuecomment-1193125126 6818 6819 * fixed: 他に sh -c 'echo -n $PID' において echo が -n を特別に解釈していな 6820 い事によってそのまま出力してしまっている問題があった。これは元々自分の環 6821 境で動かす事を想定していた為に適当にしていた事が悪い。修正した。 6822 6823 * done: readlink が期待通りに動作していない。nix-build の外でも発生している。 6824 6825 うーん。これは readlink が一体どの実装を選択しているのかに依存する。 6826 6827 * nix-build @ macOS で一体何が選ばれるのか確認したい。と思って実装を確認 6828 したがこれは実際にどう動作するか確認するまでもなく .resolve-loop 一択で 6829 ある。なので、.resolve-loop のテストを実行すれば良い。 6830 6831 * 先ずそもそも $PWD 自体が symlink だった時にどの様に振る舞うべきなのか? 6832 うーん。これはちゃんと考えていなかった。 6833 6834 readlink -f の振る舞いを見ると現在のディレクトリがリンクだった時に、そ 6835 れについても全て解決している。ble/util/readlink の目的を考えると其処ま 6836 でする必要はないが、実装毎の差異を吸収する為には其処までしなければなら 6837 ないのだろうか。 6838 6839 と思ったがこれはテストを実行する時に cd -L . をしておけば良いのでは。 6840 →というか ble/test/chdir で移動する時に cd -L "..." で移動すれば良い。 6841 6842 改めて実装を確認してみたが、そもそも実装自体が怪しい気がしてきた。確かめる。 6843 6844 実際に代替実装の動作を確認してみた所 Linux の上でも動いていない。動作を確認する。 6845 6846 * fixed: resolve-physical-directory の実装が怪しい。取り敢えず設定されていないか 6847 もしれない pwd を参照しているのはおかしい。修正は必要だがどの様に修正し 6848 て良いのか分からない。 6849 6850 * done: check: mshex の実装を確認する → mshex の実装は古い実装しかなかっ 6851 た。コメントにある taken from はもう古いので削除するべきなのかもしれな 6852 い。念の為再度 grep -r で検索してみたがやはり readlink の実装は単純な物 6853 しかない。 6854 6855 * done: check: #D1720 以前の readlink の改良の時の議論を参照する。これは 6856 #D1720 だった。うーん。しかしここには大した説明は書かれていない。元の参 6857 考にした qiita の記事とその repository も見てみたが、其処にも余りコメン 6858 ト等は書かれていないし、其処から大きく書き換えてしまっているので参考に 6859 はならない様だ。結局改めて動作について確認する必要がある。 6860 6861 恐らく元の resolve-physical-directory の実装で元のディレクトリ名ではな 6862 くて cd -L . した後のディレクトリ名に移動しているのは、現在ディレクトリ 6863 が改名された場合等にも正しいディレクトリに戻る為である。実験してみる事 6864 にする。 6865 6866 Ref: D1849-cd-physdir.sh 6867 6868 分かった事。 6869 6870 1 pwd の結果は最後に cd を実行した時のそのディレクトリのパスになってい 6871 る。PWD を書き換えたとしても変化しない。また現在ディレクトリが他者に 6872 よって改名されたとしても変化しない。新しく現在ディレクトリの位置を取 6873 得し直すという訳では無い様だ。 6874 6875 2 PWD は cd した時のディレクトリのパスに設定されるが当然後から自由に書 6876 き換える事ができる。 6877 6878 また、当然の事ながら PWD の値が信用できるのかという事もある。ユーザーが 6879 勝手に変な値に設定しているかもしれない。pwd の結果を読み取るという手も 6880 あるがファイルに一旦書き込んでそれを読み取るというコストがある。なので、 6881 cd -L . した後に PWD を読み取るというのは確かに一つの手である。 6882 6883 実装を修正して Note を残しておく事にした。 6884 6885 * 先ず初めに nix-build environment では locale が全くないという疑惑。元々の 6886 locale が utf-8 でない上に、そもそも en_US.utf8 を設定するのですら失敗し 6887 ている。どの locale が利用可能かについて調べてもらう必要がある。 6888 6889 これはどうしたら良いのか分からない。取り敢えず locale がどうなっているの 6890 かについて尋ねるのが良い。特に、en_US.utf8 がそもそもないという所を見ると 6891 locale を正しく設定してもらう所から始まる様な気がする。 6892 6893 2022-07-21 6894 6895 * 2022-07-06 syntax: "function word1 word2 word3 word4()" [#D1848] 6896 6897 % word1 がオプション形式の場合何故か word2 まで関数名として認識される。 6898 % word3 に対して type が走ってエラーメッセージが表示されて表示が乱れる。文 6899 % 法構造が一体どういう事になっているのか確認する必要がある 6900 % →どうも関数名として認識される問題とエラーメッセージが表示される問題は独 6901 % 立な問題の様だ。後、オプション形式化どうかは関係ない。 6902 6903 * 関数名として着色される問題。以下のコマンドの形の時に再現する。 6904 6905 $ function aaa bbb() 6906 6907 どうやら a は文法エラーにはちゃんとなっている。然し、単語着色によって 6908 FUNCDEF が上書きされている様だ。 6909 6910 →うーん。分かった。function -t a() と記述すると function -t { a(); } 的 6911 な解釈になっていて、本来は関数名の直後には複合コマンドしか来れないが、コ 6912 マンドがそのまま来てしまっていると解釈されている。一方で、コマンドが来て 6913 は行けない文脈であってもコマンドとしての単語着色が有効になってしまってい 6914 るのがいけない。 6915 6916 然し、本来文法的に其処にコマンドが来ては行けない文脈に於いては単語着色も 6917 有効にならない筈なのに有効になってしまっているのは何故か。例えば "if 6918 true; then false; fi echo" とすると echo は文法エラー的なコマンドであり、 6919 そしてちゃんとエラー着色のままである。 6920 6921 うーん。通常のエラーの場合には単語の種類自体が _ble_attr_ERR になっている。 6922 関数定義の場合にはそれを上書きして消去してしまっているのが原因? 6923 6924 * エラーメッセージは auto-complete の中で発生している様である。 6925 6926 $ function aaa bbb ccc ddd 6927 6928 ddd を入力している時に "ccc" に対してコマンドではないというエラーメッセー 6929 ジが発生する。 6930 6931 →これは結局最終的には bash-completion の _function が悪かった。これはま 6932 た別に bash-completion に出す。 6933 6934 但しそれとは別にそもそも function aaa bbb ccc ddd に対して "function ccc 6935 ddd" に対する補完を試みているという事も変ではある。 6936 6937 a そもそも bbb がエラーになっているのだから、extract-command の時点で bbb 6938 をコマンドとするtべきなのでは? 然し、その他の別の理由でエラーになった 6939 単語が含まれているかもしれない。なので bbb をコマンド名と解釈するのも変 6940 である。 6941 6942 望ましいのはやはり "bbb ccc ddd" に対して補完が実行される事であるが、そ 6943 れを正しく実行する方法はあるだろうか。うーん。やはり extract-command で 6944 エラー単語をスキップせずにコマンドとみなす方法しかない? 然し、エラー単 6945 語が文法的に引数を取らないコマンドに指定された引数の可能性もある。例え 6946 ば、[[ ]] aaa や (( )) aaa など。 6947 6948 b 現在は aaa を単語として登録していない。然し、aaa も単語として登録する様 6949 にすれば良いのでは? 然しそうだとしても "function aaa ccc ddd" に対して 6950 補完が試みられる事になって結局不自然である事に違いはない。 6951 6952 うーん。或いはエラー単語も全て extract-command で生成する引数に含めて、更 6953 に関数名も単語として登録して一緒に抽出する様にする? その方が自然の気がす 6954 る。 6955 6956 と思ったが echo hello (aaaa) bbbb 等の場合にはどの様にするべきだろうか。 6957 実際に現在どの様に抽出されているかを確認してから考える。 6958 6959 * 2022-07-16 改めて考えるに bbb を単なるエラー単語としてではなくエラーコマ 6960 ンドとして登録するべきの気がする。 6961 6962 →どうやら wtype を ATTR_ERR にしているのはコマンドの文脈しかない様である。 6963 なので extract-command で ATTR_ERR が見つかったらそれをコマンドとして取り 6964 扱って良いのではないだろうか。(或いは、ATTR_ERR ではなくて別の新しい分類を 6965 作った方が分かりやすいだろうか。) 6966 6967 更に "[[ ... ]] word" の様な場合には attr には ATTR_ERR を設定していたが 6968 実は文法的にはエラーとしていなかった為、word が既存のファイル名に一致した 6969 りするとエラー着色が解除される等していた。取り敢えず現在の所は此処も新し 6970 いコマンドが開始する物として良い様な気がする。他に ARGX0 が設定される文脈 6971 はあるだろうか 6972 6973 a 新しく CTX_CMDX0 を導入して概ね CTX_ARGX0 と同様に取り扱う。wtype に 6974 CTX_CMDX0/CTX_ARGX0 を設定する? 着色は ATTR_ERR のまま。extract-command 6975 では CMDI, ARGI の他にこの CMDX0 と ARGX0 も考慮に入れる。 6976 6977 うーん。CTX_ARGX0 は設定する必要ない? 6978 6979 ? wtype で CMDI と CMDX0 を区別する必要はそもそもあったのだったか 6980 6981 →CMDI だと普通に着色を実行してしまう気がする。では単に全て CMDI とい 6982 う事にして、attr が ERR だったらコマンド着色をスキップするという手も可 6983 能なのではないかという気もする。うーん。然し単語情報と attr は格納位置 6984 が異なるし、現在の実装では恐らく単語の判定に元々の色を参照している例は 6985 ない。単語に内部構造がある場合等も考えると余り robust でもない様な気が 6986 する。 6987 6988 やはり取り敢えずは CMDX0 を使って単語自体を区別する様にする。 6989 6990 * 取り敢えずは CMDX0 を定義する事にする →定義した。 6991 6992 * lib/core-syntax.sh:3711: elif ((ctx==CTX_CMDXE)); then で ctx=CTX_ARGX0 6993 を設定している。この文脈は { { echo; } >/dev/null } 等の文脈である。こ 6994 の } は CTX_ARGX0 ではなくて別の文脈で読み取るべきの気がする。 6995 6996 やはり CTX_CMDX0 的な物を新しく導入するべきだろうか。その方がすっきりす 6997 る様な気がする。 6998 6999 その場合には現在の ARGX0 を指定している箇所の多くは CMDX0 に変更した方 7000 が良いのかもしれない。例えば (()) ... や () ... や [[ ]] ... 等。うーん。 7001 本当だろうか。これらはやはりそのままで良い気がする。但し補完は発生しな 7002 い様にしなければならない。 7003 7004 2022-07-20 うーん。今改めて確認した所 redirection で別にエラーになって 7005 いる訳でもない。うーん。どう修正したのだったか確認する。CMDX0 にしてい 7006 る。なのに何故エラー着色が消えているのだろうか。 7007 7008 2022-07-24 現在はちゃんとエラーコマンド・エラー着色になっている。制御構 7009 造の終端としても取り扱わない様にしている。これで良いと思われる。 7010 7011 ? ok: CPATX0 についてはどうするのか。これについてもちゃんと考えておきたい。 7012 7013 →これは特に今まで通りで問題ない。元々 wtype = ATTR_ERR を設定した単語 7014 をコマンド名として extract-command するとした案の時に問題が起こる可能性 7015 を考えていた。然し今は CMDX0 を新しく導入して、エラーコマンド名に関して 7016 は wtype として CMDX0 を使って区別する事にした。なので、CPATX0 の単語に 7017 対して ATTR_ERR で単語登録しても問題は生じない。 7018 7019 ? ok: エラーコマンドに対して補完は実行するのか? →これは補完しない様にす 7020 るのが自然の気がする。 7021 7022 →現在はコマンド名は補完しない。一方でエラーコマンドの引数に関しては、 7023 エラーコマンドのコマンド名に従って引数補完を実行する様になっている。こ 7024 の振る舞いで良いだろう。 7025 7026 * aaa を単語として登録するかどうかはまた別の問題で、これは function aaa 7027 [TAB] とした時の補完を progcomp で提供するかどうかという事に関係して来る 7028 様な気がする。 7029 7030 * bash-completion は既存の関数の内容を挿入する事になっているが、その他の 7031 物を挿入したいという可能性はあるだろうか。他にない気がするので現在の関 7032 数定義を挿入するという事で決め打ちで良い気がする。 7033 7034 * また関数定義は複数行からなるが、現在の progcomp の仕組みだと複数行の候 7035 補は全て分割されてしまうので、何れにしても bash-completion を使ってもちゃ 7036 んと動かない。これを回避するには compgen を自前で実装し直すしかない様な 7037 気がする。或いは compgen -0 の patch が取り込まれれば新しい bash では大 7038 丈夫になる。然しそれはまた独立な話題である。 7039 7040 * またこの方針だと func() [TAB] の時に同様の機能を提供できない。 7041 7042 そう思うと補完は progcomp とは別に実装するので良い気がする。そして、もし 7043 そうするのだとしたら aaa を単語として登録する意義は薄いのではないか。これ 7044 は func() [TAB] 及び function func [TAB] の補完の実装時に考えれば良い事で 7045 ある。 7046 7047 2022-07-13 7048 7049 * mandb: ls のオプションの抽出がおかしい [#D1847] 7050 https://github.com/akinomyoga/ble.sh/issues/204#issuecomment-1181790000 7051 7052 * fixed: 手許でも具体的な振る舞いは異なってはいるが ls の man 情報の抽出が 7053 ちゃんとできていない。日本語の説明が混入してしまっている。 7054 7055 実際生成されているキャッシュの man.d/ls を確認すると誤った位置で引数が抽 7056 出されているのを確認できた。確か、空白が2個以上などの条件で分離していたが 7057 それがいけないという事なのではないか。当該箇所を確認してみる事にする。 7058 7059 うーん。途中で出力してみるとどうやら man を変換した時点で変な位置に 7060 __ble_desc__ が挿入されている様である。元の groff ソースを見ると以下の様 7061 になっていた。 7062 7063 | .TP 7064 | \fB\-\-time\fR=\fIWORD\fR \fB\-l\fR と併せて使用し、デフォルトのファイル更新時刻の代わりに 7065 | WORD で指定した時間を表示する: atime/access/use (\fB\-u\fR), 7066 | ctime/status (\fB\-c\fR)。 7067 | \fB\-\-sort\fR=\fItime\fR を指定した場合はソートのキーとして 7068 | 指定した時間が使用される 7069 7070 つまり変な形式で man が書かれているのが原因である。取り敢えずこれには対応 7071 した。動いている。 7072 7073 x fixed: と思ったがやはり動いていない。うーん。"-" を入力してから補完する 7074 時には問題は発生しないが、空文字列から生成すると問題が発生する。キャッ 7075 シュは man.d/ls は問題ないが ls に問題がある。これは合成して新しく ls 7076 を作る時に問題になっているという事だろうか。と思ったら 7077 _parse_help.d/ls.00000000000000 が問題であった。つまり _parse_help への 7078 介入の解析が問題。問題になっている ls --help の出力の行は以下の形をして 7079 いる: 7080 7081 | --author -l と合わせて使用した時、各ファイルの作成者を表示する 7082 7083 うーん。これも空白が3個以上間にある時は説明とオプションの境界と解釈する 7084 などの対処が必要になるだろうか。 7085 7086 x fixed: 更にこれでも変な物が抽出される。以下の物が抽出されている様だ。 7087 7088 | -l と使用した場合、名前でソートし、アクセス時間を表示する。 7089 7090 空白が単一であったとしても後に続く文字列に [、。] が含まれている場合に 7091 はオプション引数として解釈しない様にした。 7092 7093 x fixed: 然しこの様にしても、今度は -l の説明がこの偽物の説明で上書きされ 7094 てしまっている。本当は以下の説明が抽出されて欲しい。 7095 7096 | -l 詳細リスト形式を表示する 7097 7098 複数の同じオプションがある場合にはインデントの最も小さい物を選択する様 7099 にしたい → L4510 で uniq している所を何とかしたい → 取り敢えず一旦 7100 indent の情報と一緒に全部記録して最後に出力する様に変更した。同じ名前の 7101 オプションの説明があった場合は indent の小さい物を優先させる。 7102 7103 * 補完設定の違いによる cache の違い 7104 7105 というかそもそも日本語で表示されたり英語で表示されなかったり一定していな 7106 いのも変である。man/help のどちらかが優先されるのだとしたらちゃんと両方と 7107 も表示されるべきである。うーん。bash-completion 経由で初期化すると --help 7108 の説明を抽出する形になって、built-in completion だと man page が優先され 7109 るのが違いの原因の様である。問題はキャッシュが後々に残ってしまうという事 7110 にある。キャッシュを生成する時にちゃんと両方を個別に記録して後に合成する 7111 必要があるのではないか。 7112 7113 % と思ったが今確認してみるとちゃんと bash-completion の有無で補完の説明が 7114 % 異なるし、オプションの説明の切り出しも変な事にはなっていない。問題がど 7115 % のような条件で発生するのか確認する必要があるのである。と思ったが 7116 % LANG=C.UTF-8 にしていたのだった。LANG=C.UTF-8 にしている時には日本語の 7117 % 説明がオプション引数の部分にくっつく等の事は起こらず、ちゃんと抽出でき 7118 % ている。 7119 7120 うーん。他にも変な現象が起こったりしていた様な気がするが、これは古い 7121 ble.sh で動作している session も書き換えているからなのではないかという気 7122 もする。これについては以前考察した筈なのでまた改めて考察はしない事にする。 7123 7124 * ok: 何故か最初の menu の列だけ sep の " : " が挿入されていない。謎。と思っ 7125 たが、これは単にとても長いオプション名がその列に含まれているからというだ 7126 けの様だ。気にしなくて良い。 7127 7128 * fixed: __ble_decode__ の切り分けの失敗がどの様に起こるのかは気になる。改 7129 めて実装を確認してみるとどうも __ble_desc__ が行の途中に埋め込まれる様な 7130 状況は想定していない? 7131 7132 うーん。mode == "key" の途中で __ble_desc__ が現れる事も原理的にあるし、 7133 また mode == "desc" の途中で __ble_key__ が現れる事もある。→実装してみた 7134 が検証のしようがない。というか面倒である。取り敢えず既存の物がちゃんと動 7135 いているかどうかだけ確認する。 7136 7137 取り敢えず安全側に倒した実装に変更したので動く様になっていると考えたい。他 7138 の可能性として \b を使って上書きする事により太字を再現している場合に、太字 7139 になっている __ble_desc__ や __ble_key__ を検出できないという可能性もあるが、 7140 下手に対策して逆に動かなくなるケースがあっても嫌なので、それは実際に起って 7141 から考える事にする。 7142 7143 * というか、単に修飾を外してからマッチさせる方法だと、実際に欲しい着色や太 7144 字の修飾が外れてしまうので、修飾を外す前の文字列を正規表現で一致させなけ 7145 ればならない。だとすると ble に対して b(\bb)?l(\bl)?e(\be)? 等の様にしな 7146 ければならない。なのだとすれば、逆に動かなくなるケースもない様な気がする。 7147 とは言いつつ実際にあるかも分からない事例に対して実装するのも変な気がする 7148 ので現状のままにする。 7149 7150 2022-07-12 7151 7152 * ble.sh built-in completion で既定でオプションを補完するが他の候補よりも前に来るので邪魔 (reported by geekscrapy) [#D1846] 7153 https://github.com/rsteube/carapace-bin/issues/1219 7154 https://github.com/akinomyoga/ble.sh/issues/204 7155 7156 % と思ったが、よく考えるとそもそも空文字列でオプションも含める様にしたのは 7157 % ちゃんと絞り込みで候補を絞った時にオプションも表示する様にする為だった。 7158 % 空文字列での補完に対してオプションを生成しなかった時に何が起こるのか改め 7159 % て確認する必要がある。 7160 7161 改めて確認したが別にオプション名はソートによってファイル名よりも先に来てい 7162 るのではなく、単に生成する順序に従って先に来ているだけだった。"-" で始まる 7163 補完の時にはオプションを先に表示して、空文字列に対する補完の時にはファイル 7164 名よりも後にオプションを生成する様に変更した。 7165 7166 * 2022-07-12 空文字列からの補完によるオプション生成の時は説明を表示しない。 7167 https://github.com/akinomyoga/ble.sh/issues/204#issuecomment-1181743592 7168 7169 これは本当はその内に詳細に設定できる様にしたいが、色々考えてから実装した 7170 い。然し、今回の場合は確かにその方が良さそうな気がするので既定の動作とし 7171 て採用してしまって良い。 7172 7173 * kitty の keyboard protocol を terminal multiplexer 越しに有効化する (motivated by ferdinandyb) [#D1845] 7174 https://github.com/akinomyoga/ble.sh/issues/209#issuecomment-1179994203 7175 7176 取り敢えず一番外側の kitty に送るのは実装した。 7177 7178 ? pane を切り替えた時に kitty の keybaord protocol が有効になったままになる 7179 事によって問題が発生するのではないか。更に途中で detach した時にも問題に 7180 なるのではないか。 7181 7182 % →これに関しては kitty keyboard protocol は普通のキー操作 (C-b など) に 7183 % ついては通常通りに送信して、C-S-a 等の従来のシーケンスで区別できなかっ 7184 % た物だけについて異なるシーケンスを送る物の筈だから問題ないのではないか。 7185 % 一方で通常の modifyOtherKeys に関しては深刻な問題が起こるのでこの方法は 7186 % 使えない。 7187 % 7188 % これは本当にそうなのか確認する必要がある。一応試した感じではそうだった様 7189 % な気がする。改めて確認する。 7190 % 7191 % →これは確かめて見た所駄目だった。 7192 7193 つまり、中途半端な状態で抜けると外に抜けた時にまともに操作できないという 7194 事になる。特に kitty は keyboard protocol に関して push/pop を数えている 7195 ので外側が ble.sh だったとしても駄目な事になってしまう気がする。 7196 7197 ? 端末マルチプレクサにも modifyOtherKeys を送るべきだろうか。これについては 7198 端末マルチプレクサの振る舞いによる。もし tmux が受信したキーシーケンスを 7199 翻訳して単純なキーシーケンスしか送らない様にしてしまうのであれば tmux に 7200 もちゃんと modifyOtherKeys を送る必要がある。一方でもしそのまま通過させる 7201 のであれば特に設定は必要ない。 7202 7203 これについても tmux, screen の両方について振る舞いを確認する必要がある。 7204 7205 * うーん。tmux について ble.sh なしで直接 printf して振る舞いを確かめよう 7206 としたが tmux 自体が何かを送信しているせいか kitty の設定が解除されてし 7207 まっている? よく分からないので ble.sh つきで確認する事にする。 7208 7209 と思ったがどうやら tmux は extended-keys を on にしても always にしても 7210 kitty の送ってくるキーを正しく認識する事ができない様だ。kitty は余分に 7211 flag 128 を加算している為に tmux が解釈できない function key 7212 modification と判断して裸の文字にしてしまう。例えば C-r を入力すると 7213 133=128+4+1 という function key modification になるが tmux はこれを解釈 7214 不能として 0 にしてしまう。結果として唯の文字である "r" が入力される事 7215 になってしまう。 7216 7217 * screen に関しては完全に透過してしまうので modifyOtherKeys 的な入力を 7218 ble.sh で受け取るのには問題ない。然し、逆に screen が modifyOtherKeys 7219 に全く対応していないので、外側の kitty の設定が全ての window に対して適 7220 用される事になる。つまり window を切り替えた時に ble.sh の外側と内側の 7221 齟齬があると全く動かないという事になる。 7222 7223 うーん。これは実験的機能として封じて置く必要があるだろうか。 7224 7225 * tmux に伺いを立ててみる必要があるのではないか。 7226 7227 * 一方で kitty に関してはどの version からこういう事をするようになったの 7228 かの確認もしておきたい。或いはずっと前からこの様にしていたのだろうか。 7229 過去の version をコンパイルするのは面倒なのでソースコードの変更履歴を追 7230 う必要がある。 7231 7232 取り敢えず tmux のソースコードを確認してみる。一体何処でこれを処理してい 7233 るのか。これは意外と簡単に見つかった。然し疑問点が幾つかある。 7234 7235 * 7 の時だけ IMPLIED_META を付加していないのは何故か。 7236 https://github.com/tmux/tmux/blob/dc6bc0e95acc04cdf43e869294ecba897a11d850/tty-keys.c#L954 7237 7238 うーん。IMPLIED_META の説明を読むとどうも ESC による Meta と function 7239 key modification Alt による Meta を区別する為という様に見える。という事 7240 を考えると、modifiers 7 で IMPLIED_META が抜けているのは単なるミスでは 7241 ないか。 7242 https://github.com/tmux/tmux/blob/dc6bc0e95acc04cdf43e869294ecba897a11d850/tty-keys.c#L114-L118 7243 7244 更にこちらの配列ではちゃんと IMPLIED_META が付加されている。 7245 https://github.com/tmux/tmux/blob/dc6bc0e95acc04cdf43e869294ecba897a11d850/tty-keys.c#L258 7246 7247 * 9 に対しても Meta を付加しているが元からそういう物だったか? 9 は super 7248 なのではないか。これはもしかすると古い DEC のマニュアルの間違いを引きずっ 7249 ているのかもしれない。後で調べる必要がある。 7250 7251 →恐らく問題の変な割当をしているのは xterm のマニュアルだったと思ったが 7252 今確認すると 8 しかない。という事は 9 は一体何処から出てきたのだろうか。 7253 他の端末でこの辺りをもっと aggressive に parse していた物がある筈。例え 7254 ば iTerm2 か vte だった様に思う。それらの実装も確認する必要がある。 7255 7256 うーん。然し他にもこの様な変な事をしている端末がある様な気がする。 7257 7258 * vte について調べてみたがこれは 0,2-8 を hardcode していた。 7259 super/hyper も認識していない。 7260 7261 * iterm2 については以下の部分で flag を生成している? 7262 https://github.com/gnachman/iTerm2/blob/698b83ec79d882ee5acb25b7e358680f9db47e01/sources/iTermRawKeyMapper.m#L48-L83 7263 7264 と思ったが色々と様子がおかしい。lshift, rshift, loption, roption, 7265 lcontrol, rcontrol,... という具合に bit を割り当てている。これだと滅 7266 茶苦茶にずれるのではないか。 7267 7268 * xterm について確認するのが良い気がする。と思ったらここにちゃんと表が 7269 ある。そして 8 は Meta という事になっている。 7270 https://github.com/ThomasDickey/xterm-snapshots/blob/13e30fcb98357d456660fdfc74fc86725a49934f/input.c#L358-L373 7271 7272 向こうにはこの表を提示しておけば良いだろう。 7273 7274 * kitty の実装について確認を取る。ソースコードが滅茶苦茶なので何処に何が 7275 あるのかよく分からないがようやく見つけた。どうやら 128 は NumLock だった様だ。 7276 https://github.com/kovidgoyal/kitty/blob/4c2800b294a4b1189a6f0dfaa236f52d5380bb70/kitty/key_encoding.py#L290 7277 https://github.com/kovidgoyal/kitty/blob/4c2800b294a4b1189a6f0dfaa236f52d5380bb70/kitty/key_encoding.c#L55-L61 7278 7279 * done: numlock を解除したらちゃんと普通の数字の範囲で値を返してくれるという事が分かった。 7280 7281 さてこの numlock がいつ実装されたのかというのを調べてみると 2021-04 で割合最近だ。 7282 https://github.com/kovidgoyal/kitty/commit/4c644b855649f9de29be4feac89cfeae1b981541 7283 7284 * mintty で modifier の割当をどうしているのかも確認しておく 7285 https://github.com/mintty/mintty/blob/b939fa6231ab7f9b5606821135e63d0d22ee3b2e/src/config.h#L7-L8 7286 7287 | vte | S, M, C | 7288 | xterm | S, A, C, M | 7289 | mintty | S, A, C, Win, s, H | 7290 | kitty | S, A, C, s, H, M, CapsLock, NumLock | 7291 7292 これについて contra の escseq.html にも追記しておく事にする。 7293 7294 取り敢えず tmux に変更を提出しておいた。好感触なので何れ merge されるだろう。 7295 7296 * done: wiki: set -g extended-keys について記述する 7297 * done: wiki: 新しいオプションについて記述する。注意事項も含める必要がある。 7298 * done: blerc: 新しいオプションについて記述する。 7299 7300 * wiki: named prompt sequences についても記述するべきなのではないか [#D1844] 7301 7302 ./keymap/emacs.sh:138:function ble/prompt/backslash:keymap:emacs/mode-indicator { 7303 ./keymap/vi.sh:512:function ble/prompt/backslash:keymap:vi/mode-indicator { 7304 ./src/edit.sh:1016:function ble/prompt/backslash:position { 7305 ./src/edit.sh:1024:function ble/prompt/backslash:row { 7306 ./src/edit.sh:1031:function ble/prompt/backslash:column { 7307 ./src/edit.sh:1038:function ble/prompt/backslash:point { 7308 ./src/edit.sh:1042:function ble/prompt/backslash:mark { 7309 ./src/edit.sh:1046:function ble/prompt/backslash:history-index { 7310 ./src/edit.sh:1050:function ble/prompt/backslash:history-percentile { 7311 7312 取り敢えずユーザーも使える事を想定したものは記述した。vim-airline の物は本 7313 来内部使用を意図して実装された物なので省略。 7314 7315 * vi: status_line ではなく mode indicator 自体を変更する方法を与える (motivated by ferdinandyb) [#D1843] 7316 7317 mode indicator の部分をプロンプト設定として提供する事にした。 7318 7319 * done: うーん。vi のモードが変わった時にしか更新されないので、モード以外の 7320 情報を表示しようとしても次にモードが変更される時にしか更新が走らない。 7321 仕方がないので PRECMD に update-mode-indicator を登録する事にした。 7322 * done: emacs の方も同様に設定できる様にするべきの気がする。 7323 7324 * done: blerc, wiki に記述 7325 * done: wiki: prompt_emacs_mode_indicator 7326 * done: wiki: prompt_vi_mode_indicator 7327 * done: wiki: pointers to prompt_*_mode_indicator in §Edit 7328 7329 2022-07-11 7330 7331 * term: kitty の keyboard protocol が有効になっていなかった [#D1842] 7332 https://github.com/akinomyoga/ble.sh/issues/209 7333 7334 返信を書いている時に kitty の振る舞いを確認していて気づいたのだがちゃんと 7335 kitty Keyboard Protocol が有効になっていなかった。"push keyboard mode" の分 7336 岐の条件が反転していた。 7337 7338 2022-07-10 7339 7340 * complete: "g add newdir/z[TAB]" とするとファイル名が消える [#D1841] 7341 7342 % 既に登録されているファイルの場合には問題は起こらない様だ。既に登録されて 7343 % いるファイルがあるディレクトリの中の新しいファイルであっても、そのファイ 7344 % ルが登録されていない場合にはやはりファイル名が消える→というか改めて試し 7345 % た所既に登録されているファイルでもやはりファイル名が消える。 7346 7347 "git add newdir/z[TAB] " の時には問題は生じない。 7348 7349 これは分かった。COMP_POINT が正しく更新されていない。 7350 7351 declare -- COMP_LINE="git add lib/i" 7352 declare -- COMP_POINT="11" 7353 declare -a COMP_WORDS=([0]="git" [1]="add" [2]="lib/i") 7354 declare -- COMP_CWORD="2" 7355 7356 そしてこれは comp_line,comp_point の更新が正しく出来ていない事によると思わ 7357 れる。と思ったがそうでもない様だ。comp_line, comp_point の時点では変な事に 7358 はなっていない。つまり最初のコマンドを差し替える時点で COMP_POINT を更新す 7359 るのを忘れているという事。うーん。と思ったが 7360 7361 declare -- comp_line="g add lib/i" 7362 declare -- comp_point="11" 7363 declare -a comp_words=([0]="git" [1]="add" [2]="lib/i") 7364 declare -- comp_cword="2" 7365 7366 となっていて comp_words と comp_line で不整合が生じている。コマンド名を置き 7367 換える時にちゃんと comp_line, comp_point も置き換える様に修正した。 7368 7369 declare -- comp_line="git add lib/i" 7370 declare -- comp_point="13" 7371 declare -a comp_words=([0]="git" [1]="add" [2]="lib/i") 7372 declare -- comp_cword="2" 7373 7374 * 実装してから思ったが単に .compline-rewrite-command を呼び出せば良いだけで 7375 は。→その様に書き換えた。ちゃんと動作しているのでOK。 7376 7377 * command-help (ble/widget/command-help/.read-man): ble/util/assign/.rmtmp を忘れている [#D1840] 7378 7379 0.2 backport 中に気づいた。これは単純に追加すれば良い。 7380 7381 * encoding:C: 初期化出来ない。大量のエラーメッセージ [#D1839] 7382 7383 0.2 backport 中に気づいたのだが encoding:C で既に削除された関数 7384 ble/init:bind/bind-s が使われている。実際に input_encoding=C にして開始して 7385 みると大量のエラーメッセージが表示されて変な文字列が入力される。 7386 これは単に改めて関数を追加する事にした。 7387 7388 * complete: zoxide completion が動かない (reported by ferdinandyb) [#D1838] 7389 https://github.com/akinomyoga/ble.sh/issues/207 7390 7391 zoxide も fzf と同様の戦略を用いている。 7392 7393 * ok: zoxide については (以前試した時の fzf と違って) stdout/stderr をちゃ 7394 んと繋ぎ変えている様だ? 或いは単に中で呼び出している最新の fzf が 7395 stdout,stderr を /dev/tty に繋ぎ変えているだけかもしれないが。 7396 7397 * ok: zoxide は中で \builtin bind や \builtin printf を用いているので振る舞 7398 いを上書きするのは困難である。builtin を上書きしようにも \builtin local 7399 も使われている事からこれを関数の中で実行する訳にも行かない。 7400 7401 或いは printf, bind を enable で一時的に削除するという事も可能かもしれな 7402 いが色々テストするのが面倒である。 7403 7404 というより stdout は封じているのだし、bind は特に悪さをするという訳でもな 7405 い様な気がするので単にそのまま放置していても特に問題は起こらないのでは。 7406 →取り敢えずそのままにしておいても特に問題は生じていない様な気がする。 7407 7408 x 生成した候補がちゃんと反映されない。何故だろうか。 7409 7410 と思ったら分かったかもしれない。何か端末に送信している為に端末からの返答 7411 が届いていて is-stdin-ready に引っ掛かって補完がキャンセルされている。 7412 7413 % うーん。そしてそれは恐らく 1 ではなくて独自に開いた /dev/tty 経由で送信 7414 % されているので抑制する方法がない。 7415 7416 % → \builtin printf をコメントアウトしたら動く様になった。というか既定で 7417 % は stdout/stderr は抑制していなかった様な気もする。然し、builtin printf 7418 % を抑制する方法がないので困る。と思ったが全体を >/dev/null としてしまえ 7419 % ば良いのでは? 実際にその様にして見たら動く様だ。 7420 7421 2022-07-09 7422 7423 * fzf kill completion が動かない (reported by ferdinandyb) [#D1837] 7424 https://github.com/akinomyoga/ble.sh/issues/206 7425 7426 実際に動かしてみると確かに動かない。呼び出し時の ADVICE_WORDS 及び COMP_* 7427 の値についても確認してみたが特に違いは見られない。もう一つの違いは呼び出し 7428 後に COMP_WORDS が書き換えられているという事。 7429 7430 うーん。_fzf_complete_kill の実装を確認してみると COMP_WORDS を書き換える事 7431 になっている。つまり、何故か書き換えたか或いは書き換えたのにそれが反映され 7432 ていないという事になる。もう少し詳しく振る舞いを調べてみる事にする。 7433 7434 →うーんちゃんと書き換えは発生している。しかし折角書き換えたのにその後でま 7435 た状態が元に戻ってしまっている様だ。と思ったら分かった。advice を付加した関 7436 数を入れ子で呼び出しているので、外側で設定した COMP_WORDS が内側で呼び出さ 7437 れる時に上書きされてしまう。COMP_WORDS が上書きされる事を想定していなかった 7438 のが原因である。 7439 7440 x fixed: それでも未だ動かない。と思ったら内部で caller 0 を呼び出している。 7441 advice を付加した事によって caller がずれているという事。caller のずれは 7442 修正した。実に 5 段も余分に実行している様だ。更に caller 自身の置き換えも 7443 含めて 6 段先の caller を参照する事にする。 7444 7445 x fixed: それとは別に何故か ps で生成しているプロセスのリストの代わりに現在 7446 のディレクトリ以下にあるファイルのリストが表示されている。 7447 7448 と思ったが分かった。_fzf_complete の場合は標準入力に候補を流し込んでいる 7449 事があるので、勝手に /dev/tty に書き換える訳には行かない。使用箇所を確認 7450 してみた所、_fzf_complete の場合には常に標準入力に対して候補を流し込む使 7451 い方しかしていない様なので、_fzf_complete の時は標準入力はそのままにする 7452 事にした。取り敢えず動いている。 7453 7454 2022-07-08 7455 7456 * history: HISTFILE が空の時は履歴ファイルは無効化する [#D1836] 7457 7458 HISTFILE が設定されていない時は既定の位置 (.bash_history) に書き込むのでは 7459 なくそもそも履歴ファイルが無効化される様だ。今まで .bash_history に対して読 7460 み書きしていたのを修正する。 7461 7462 * 整数が IFS に含まれている可能性もあるので ${#...} や $((...)) や >&$fd も quote する [#D1835] 7463 7464 redirection も word-splitting の対象である。今まで数字は空白でないから大丈 7465 夫と考えていたが IFS に数字が含まれている可能性もある。ble.sh は内部では 7466 IFS を調整しているとは言え、ユーザーから呼び出した場合なども考えると一律で 7467 ちゃんと quote する様にするべき。 7468 7469 grc '[<>]&\$' 7470 7471 実は $(()) も同様である。現状では $(()) は数字だから quote しなくて良いと考 7472 えて裸で記述しているが、やはり任意の IFS の可能性を考えると quote するべき 7473 である。これは物凄く沢山ある。 7474 7475 grc ' \$\(\(' 7476 7477 7478 grc '([ (])(\$\(\(([^()]|\([^()]*\))*\)\))([; )]|$)' --exclude=docs 7479 grc '( |=\()(\$\{#([^{}]|\{[^{}]*\})*\})([; )]|$)' --exclude=docs 7480 7481 * complete: command_not_found_handle が自動補完で呼び出されて操作不能になる (reported by telometto, wisnoskij) [#D1834] 7482 https://github.com/akinomyoga/ble.sh/issues/203 7483 https://github.com/akinomyoga/ble.sh/issues/192 7484 7485 stdin に [y/n] を要求するが ble.sh が stdin をブロックしている為に補完が終 7486 了できず操作不能になる。 7487 7488 ? というか入力が受け付けられなくなったとしても C-c だけは効く様にして良いの 7489 ではないか。 7490 7491 x 一方で、C-c をそのまま有効にすると ble.sh の処理自体がその場で止まって 7492 しまう事になる。C-c を trap で捕まえて適切な stack frame まで戻るにして 7493 も再び DEBUG トラップで複雑な事をしなければならない。 7494 7495 x そもそも外部コマンドの C-c を正しく検出できるのかという問題もある。C-c 7496 で外部コマンドだけが終了したとして、その後補完スクリプトがそのまま走っ 7497 た時に変な事にならないかというのは非自明である。 7498 7499 x 更に補完の度に stty を呼び出して C-c の状態を変えなければならない。失敗 7500 すると次に stty を調整する迄 C-c を ble.sh で受信できなくなる。 7501 7502 うーん。色々考えると C-c を一時的に有効にするというのも余り良い選択肢では 7503 ない様に思われる。取り敢えずは command_not_found_handle を一時的に無効に 7504 するしかない。 7505 7506 * bash-completion の側でも修正するべきか。もし plain Bash では progcomp の 7507 最中には command_not_found_handle が無効化されるという事であれば 7508 bash-completion の側で修正は必要にはならない。 7509 7510 command_not_found_handle() { echo "$FUNCNAME is called"; } 7511 7512 7513 既に bash-completion で報告されていないか確認する。 7514 7515 https://github.com/scop/bash-completion/pull/390 7516 7517 ここで既に議論されている。scop は upstream bash に request できないかとい 7518 う事を提案している。他にも色々の箇所でそういうのがあるとも述べている。 7519 7520 と言っても将来的に Bash の側で off にする機能ができるとしても、古い Bash 7521 は依然として存在するので取り敢えず個別に対応していくべきなのではないかと 7522 いう気がする。 7523 7524 取り敢えず command_not_found_handle は function#push する事にする。 7525 7526 * 2022-07-09 未だ直っていないという (reported by telometto) 7527 https://github.com/akinomyoga/ble.sh/issues/192#issuecomment-1179191747 7528 7529 先ずは PackageKit をインストールして動作を確認しようと思ったら既にインス 7530 トールされている。然し /etc/profile.d/PackageKit.sh を確認してみても存在 7531 していない。dnf search で検索してみると PackageKit-command-not-found とい 7532 うのがあったのでそれを入れてみると入った。再現した。 7533 7534 確かに command_not_found が呼び出されて固まっている。然し、 7535 command_not_found は一時的に無効化している筈。command_not_found_handle の 7536 中から呼び出しの構造を調べてみた所、どうやら ble.sh が独自に 7537 __load_completion を呼び出していてその時に command_not_found_handle が走っ 7538 ている様だ。つまり、__load_completion を呼び出す時にも workaround で 7539 command_not_found_handle を無効化する必要があるという事。 7540 7541 ? __load_completion を呼び出す時には別に tty を封じてはいなかった様な気が 7542 するが固まるのは何故だろうか。うーん。不思議だ。確認した所、&>/dev/null 7543 で寧ろ入力ではなくて出力の方を組み替えている。なのに出力は出来て入力は 7544 できないというのも変な事である。 7545 7546 * 2022-07-09 使っていたら元から command_not_found_handle が定義されていなかっ 7547 た時に pop 時に問題が発生する。これは ble/function#{push,pop} の実装の問 7548 題である。 7549 7550 これは function#push 時に関数定義を与えなかった時に関数を unset する機能 7551 を導入した時の手落ちと考えられる。調べてみるとこれは a41279e (#D1720) に 7552 おける変更である。この時に一応 function#pop に対しても対応する変更がなさ 7553 れているが、それが不完全だったという事。 7554 7555 * 2022-07-10 "bash: return: echo: numeric argument required" 7556 https://github.com/akinomyoga/ble.sh/issues/208 7557 7558 これはミスだ。修正する。 7559 7560 2022-07-07 7561 7562 * main: fd 0, 1 が TTY かどうかのチェックが常に偽になっている [#D1833] 7563 Ref #D1749 7564 7565 ble-0.3 に 711c69f (#D1749) を backport している途中に気づいた。今までは 7566 /dev/tty もチェックしていたので、このチェックに失敗しても問題が表面化してい 7567 なかっただけ。ble-0.3 で /dev/tty のチェックをスキップする様にしたら問題が 7568 表面化した。ble-0.3 に対して行ったのと同じ修正を適用する。 7569 7570 2022-07-06 7571 7572 * main, decode: ble-attach & set -e [#D1832] 7573 7574 bash -e で開始した時は寧ろ --attach=prompt でないと駄目な事が分かった。 7575 ble-0.3 及び ble-0.4 で再現した。--attach=prompt を指定していても bashrc 内 7576 部で手動で ble-attach すると失敗する。 7577 7578 うーん。これは ble/decode/.hook で set +e したら回避できるだろうか→どうや 7579 ら回避できる様だ。-e も勝手に無効にはなっていない。 7580 7581 x これは文法エラー等によって状態回復に失敗した時に次の ble-decode/.hook の 7582 呼び出しの時に set -e が消滅する原因になり得るが、その様な事は余り起こら 7583 ないし起こったとしてもそもそも対話セッションで set -e を設定する事の方が 7584 変だから基に思案くても良い? 7585 7586 a 或いは attach した直後だけは set +e を実行する様に変更する? 然し、 7587 attach した直後かどうかを判定するのにまた処理時間を食う気がするし、微妙 7588 な気がする。 7589 7590 b 或いは別の hook に登録するという可能性もある。 7591 7592 c 周りのコードを見渡してみたら既に set +v をしている部分がある。#D0930 が 7593 対応する項目である。確認してみたら今回の -e と同様の事が書かれている。 7594 うーん。前回のコマンドで解除に失敗した時にどうなるのかは非自明だが取り 7595 敢えずここに set -e を追加しておけば良い気がする。 7596 7597 前回のコマンドで解除に失敗した時にはそもそもその場で errexit して終了し 7598 てしまう筈なので、再び .hook が呼び出される事もない気がするので気にしな 7599 くて良い気がする。 7600 7601 取り敢えず c の方針を使う様に修正した。改めてちゃんと動くか確認する→OK 7602 7603 2022-07-05 7604 7605 * bash: history timestamp に問題がある時に history の初期化が正しくない (reported by johnyaku) [#D1831] 7606 https://github.com/akinomyoga/ble.sh/issues/202 7607 7608 bash がエラーメッセージを出力する (bash-5.0+) または segfault する 7609 (bash-4.4-)。現状ではエラーメッセージがそのまま履歴に混入してしまっている。 7610 うーん。stderr も読み取ってしまっているのかと思ったが実際に試してみるとエラー 7611 メッセージが stdout に出力されている。 7612 7613 % これは後で bash に提出する。 7614 % 7615 % * reject: bug-bash: HISTTIMEFORMAT=%s history でエラーメッセージが stdout 7616 % に混入するエラーメッセージは stderr に出力するべきなのではないか。 7617 % 7618 % と思ったがこの文字列はエラーメッセージとしてではなく履歴時刻の文字列の代 7619 % わりに埋め込まれているという事が判明した。という事はやはり history の出力 7620 % の中にメッセージを埋め込むべきという事なのかもしれない。 7621 7622 取り敢えず問題のエラーメッセージは正規表現によるパターンで除去する事にする。 7623 7624 * fixed: 更に履歴を書き込む時にも問題になっている。これも修正した。 7625 7626 * done: 履歴読み込み時に invalid timestamp を検出したらそれを vbell で報告 7627 する様にする。 7628 7629 これで bash-5.0+ 以降でエラーメッセージが履歴に紛れ込むのは修正した。一方で 7630 bash-4.4 以下で segfault してしまうのに対する対策は難しいのではないか。一応 7631 終了ステータスを確認する事で segfault した事は検出できるが、もし検出したと 7632 してどの様に対処するのが良いか。例えば、HISTTIMEFORMAT なしで改めて履歴を読 7633 み直す事にする? 履歴行の境をどの様に判定するべきだろうか。或いは、エラーを 7634 検出した時に vbell に表示してしまって、history の状態は壊れた状態でも仕方が 7635 ないという事にする? それが良い気がする。 7636 7637 * 実際にエラーになった時に問題の行を指摘したい。 7638 7639 どの様な形式の時にエラーになるのか調べようとしたがよく分からない。先ず、 7640 そもそも数字でない場合には timestamp 行として認識されない。数字の後にごみ 7641 が入っていてもそれらは単に無視される。得に巨大な数が指定された時に於いて 7642 問題が生じる様である。問題が起こる最小の整数を探索すると 7643 67768036191644399 であった。これは16進数で見ても特に特別な数ではない 7644 (0xf0c2ab7c542aef)。検索してみたらどうもやはり時刻関係で特別な数字の様で 7645 はある。 7646 7647 > https://mevius.5ch.net/test/read.cgi/unix/1590454119/ 7648 > 7649 > 115名無しさん@お腹いっぱい。2020/06/01(月) 17:52:40.57 7650 > macos での限界 7651 > $ date -r 67768036191644399 7652 > 2147485547年 12月31日 水曜日 23時59分59秒 JST 7653 > $ date -r 67768036191644400 7654 > date: localtime: Value too large to be stored in data type 7655 7656 実際手許の date で試してみても同様である。 7657 7658 $ date --date=@67768036191644399 7659 $ date --date=@67768036191644400 7660 7661 これは一体何が決めているのだろうか。と思ったらどうも 2147485547 年という 7662 のは1900 + 0x7FFFFFFF らしい。つまり localtime で時刻構造体に変換する時に 7663 代入できないという状態になるという事だ。 7664 7665 https://www.wdic.org/w/TECH/21%E5%84%844748%E4%B8%875548%E5%B9%B4%E5%95%8F%E9%A1%8C 7666 7667 67768036191644399 で検索して日本語のページが幾つかしか出てこないのは 7668 upper bound が TZ に依存するからである。 7669 7670 さて、TZ に依存するのだとすればこの数値を threshold に選ぶ事はできない。 7671 それに正規表現で判定できなければ問題の行の検出に於いて不都合である。更に、 7672 この上限の値は time.h の実装にも依存するのではないだろうか。 7673 7674 更に bash-3.2 以下では無限ループになる。関係ない無限ループかもしれないと思っ 7675 たが実際に履歴の timestamp に問題がある時にのみ無限ループになる。何処で無限 7676 ループになっているか確認する。 7677 7678 →実際に ble.sh なしで試して見た所、単に history を実行しただけで無限ループ 7679 になって固まってしまう。これに対する対策は難しい気がする。。builtin history 7680 を呼び出すあらゆる操作で問題が起こる可能性があるという事になるのであるから。 7681 7682 * done: bash-3.2: history の読み出しに使っている部分だけ conditoinal-sync で呼び出す。 7683 7684 conditional-sync で timeout を設定してみたがやはり 100% になってしまう。 7685 という事は関係ない別の history -n 等でも全て無限ループになっているという 7686 事か。と思ったが手許で実行している限りは特に無限ループにはならない。 7687 7688 →と思ったら分かった。.get-min で history | head -1 を呼び出している。こ 7689 の history で無限ループになっている。 7690 7691 ? ok: 実際に conditional-sync で呼び出してみたところ timeout よりも断然早く 7692 中断する。何かと思ったら conditional-sync 経由で呼び出した時には無限ルー 7693 プにならずに 300ms 程度でちゃんと終了する様である。何故だろうか。 7694 7695 もしかすると conditional-sync を使わなくても subshell ならばちゃんと終了 7696 する可能性? と思ったが、元より問題になる箇所では subshell を使っていた。 7697 なので、bg で動かした時にだけ無限ループにならないという事だろうか。だとし 7698 たらやはり conditoinal-sync 経由で呼び出して置くのが楽である。 7699 7700 取り敢えず bash-3.2 でも固まらなくなった。OK 7701 7702 * edit: プロンプト評価時に LINENO は一時的に現在の行番号に設定するべき [#D1830] 7703 7704 →これは DEBUG を PREEXEC に使っている設定でも重要になる。 7705 うーん。DEBUG trap を呼び出す時にも設定するべきだろうか。 7706 →DEBUG trap を呼び出す時にも LINENO を設定する事にした。 7707 7708 2022-06-28 7709 7710 * contrib/prompt-git: untracked content は赤ではない色で表示する for submodule [#D1829] 7711 →untracked files in submodule は単に無視するオプションがあったのでそれを使う事にする。 7712 7713 * contrib/config/execmark: 同じ行に errexit を表示していると気づきにくい [#D1828] 7714 →分けて表示する様にした。 7715 7716 * global: awk -v var=value を介して任意の文字列を渡さない [#D1827] 7717 7718 awk の -v で任意の文字列を渡すことはできない。"" の中であるかのように \? が 7719 処理されてしまうので。文字列をそのまま渡したければ ENVIRON を使うしかない。 7720 7721 * util: ble/string#split-words 最適化 [#D1826] 7722 7723 どうも頻繁に呼び出される割に其処まで早い訳でもない様なので速度について確認 7724 する。うーん。多少弄ったら結構速度が変わったので採用する事にする。 7725 7726 * 既存の呼び出しで引数を複数渡している場合はあるだろうか? →ない様なので分 7727 割文字列の引数は一つしか渡されないと仮定して良い。 7728 7729 * ble/string#split も同様に最適化する。ble/string#split に関しても対象文字 7730 列の引数は必ず単一の様なので、それを仮定する。 7731 7732 * 序に ble/util/assign & ble/string#split-words のパターンは関数にしてしま 7733 う。 7734 7735 * done: refactor: ble/debug/profiler/{end => stop} 7736 * done: ble/debug/profiler: varleak nline 7737 * done: ble/debug/profiler: $prefix.line.txt の行番号の形式変更 7738 7739 * 古い benchmark のスクリプトも追加する事にした。 7740 7741 2022-06-27 7742 7743 * util (eval-pathname-expansion): bash-4.0以下で shopt *glob がクリアされる [#D1825] 7744 7745 ble-0.3 backport で見ていたら気づいた。BASHOPTS (Bash 4.1+) を使って shopt 7746 の状態を記録しているが、Bash 4.0 以下に対する分岐がない。0da0c1c で埋め込ま 7747 れたバグである。visible-bell 消去時に glob 関連の shopt が全て unset されて 7748 しまう事になる。修正した。 7749 7750 * 他の BASHOPTS 使用箇所は問題ないか → 他には ble.pp で使っているだけであ 7751 る。そして ble.pp の使用箇所ではちゃんと分岐している。 7752 7753 2022-06-26 7754 7755 * debug: profiling 機能 (motivated by SuperSandro2000) [#D1824] 7756 7757 LINENO を先ず何とかする。LINENO=... eval '...' とすれば一時的に LINENO を置 7758 き換える事が可能なのではないか。と考えたが、どうやら以前発見した bash の 7759 bug である tempenv=... builtin eval -- 'echo;echo $tempenv' で tempenv が消 7760 滅するバグの為に期待通りに動かない様だ。 7761 7762 うーん。workaround の方法はあるだろうか? 7763 7764 a ここの eval は builtin を使わずに呼び出す? → eval の上書きを現状では許可 7765 しているがこの対応を除去する必要がある。これは避けたい。バージョンごとに 7766 この対策を切り替えるのも面倒である。 7767 7768 b eval を二重にしたら回避できる可能性はあるだろうか → 駄目だ。うーん。駄目。 7769 7770 $ e=1234 builtin eval 'builtin eval ":;echo \$e"' 7771 $ e=1234 builtin eval 'e=1234 builtin eval ":;echo \$e"' 7772 7773 c adjust-builtin の restore を遅延させて eval の内部で実行する可能性? → と 7774 思ったら既にその様になっていた。なので builtin eval にしなくても良い。 7775 7776 時間を合計するプログラムを書いてみたが何だか振る舞いが変だ。そもそも関数呼 7777 び出しをしているのに + の数が増えていない気がする。うーん。説明を見ると 7778 levels of indirection と書いてあるがこれは何か確認する必要がある。→動作を 7779 見たら関数呼び出しでは増えない様だ。つまり、eval 等の数しか数えないという事。 7780 入れ子をちゃんと処理する為には + の数に加えて FUNCNAME の要素数も数える必要 7781 がある? FUNCNAME は関数の内部でしか有効にならず関数内に入るとトップレベルコ 7782 ンテクストの名前 (main) と共に要素数が2増えるので、代わりに常に存在している 7783 BASH_LINENO の要素数を数える事にする。 7784 7785 * done: 関数毎の統計も取る 7786 * done: 前回の記録を最初に読み出す 7787 * done: % を表示する 7788 * done: 前回の記録が複数の物を cat した物の場合にも対応 7789 * done: PS4, bleopt の設定を待避・復元する → この為には ble/base/xtrace で 7790 hook する必要がある → 7791 7792 a bleopt の設定については勝手に色々変わるのも変なので弄らない? 7793 7794 PS4 はユーザーが使いたいかもしれないので待避するのは確定。bleopt の設定 7795 については xtrace/{adjust,restore} の度に動的に変わるのも変なので、やは 7796 り ble/debug/profiler/start した時に設定してそのままにしておくのが良い 7797 のではないか? 7798 7799 →然しそうすると profiling 中にユーザーが間違って debug_xtrace{,_ps4} 7800 を設定した時に動作が変になるのでは。しかし、ble/debug/profiler を動かし 7801 ている最中にこれらの設定を勝手に変更するのがおかしいとも言える。特に 7802 ble/debug の同じ名前空間に属していると思えば ble/debug/profiler を介し 7803 て debug_xtrace{,_ps4} を動かしていると思っても良いのかもしれない。 7804 7805 b 或いは profiler が設定されているかどうかの変数を ble/base/xtrace で見て 7806 処理を切り替える? 7807 7808 c 或いは blehook xtrace_{adjust,restore} を追加する? →これは overhead が 7809 増えるし、もしこれで実装するとしても bleopt をその場で切り替える様な実 7810 装になって何だか変な気がする。其処までする必要もない。 7811 7812 ble/debug/profiler で bleopt debug_xtrace_{,_ps4} を書き換える実装で良い。 7813 7814 * done: blerc, wiki 7815 7816 2022-06-20 7817 7818 * history: bind のエラーメッセージ in 非対話シェル (reported by wukuan405) [#D1823] 7819 https://github.com/akinomyoga/ble.sh/issues/200 7820 7821 これは単に bash が警告を出しているだけである。念の為、確認してみたが、bind 7822 set 及び bind -v は共に動作している。 7823 7824 2022-06-19 7825 7826 * history: erasedups を制限する機能 (motivated by SuperSandro2000) [#D1822] 7827 https://github.com/akinomyoga/ble.sh/issues/198 7828 7829 * done: 初期化時の履歴の個数を記録しておく。 7830 7831 うーん。これを実装する為には一時的な erasedups の除去がちゃんと history -s 7832 の動作に反映されている必要がある。そして反映されないという変な事がある様に 7833 は思われない→実際に動かして試してみたが特に変な振る舞いはしない。ちゃんと 7834 その時の HISTCONTROL に従って動作していると見て良いだろう。 7835 7836 * done: history_erasedups_limit に従って探索の範囲を決定する。 7837 7838 実装した。動作確認した。ちゃんと動いている様な気がする。意外と高速に動作す 7839 る。探索範囲が 20k/100k ぐらいになって漸く awk よりも遅くなる。現実的には一 7840 つの session で 20k もコマンドを打つ事はないだろうから気にしなくて良いだろう。 7841 7842 2022-06-20 コードを眺めていたら無限ループのパスがある。関数名を書き換える時 7843 に修正し忘れていた。直す。 7844 7845 * decode: ble-bind -P の出力で -c binding が変だ。引用符が余分についている [#D1821] 7846 7847 ble-bind -m 'vi_nmap' -c C-z \'fg\' 7848 7849 v0.3 では特に問題はない様だ。修正した。 7850 7851 * decode (bind): inputrc に含まれる # の処理 [#D1820] 7852 7853 % 変数によって処理したり処理しなかったりの様だ。特に文字列を受け取るオプショ 7854 % ンに関しては # 以降の削除はされない。一方で on/off のオプションの場合には 7855 % '#' 以降は無視されている様に見える。→と思ったが違った。単に最初の空白で 7856 % 切っているだけだった。 7857 7858 Bash-5.1 以降では on/off オプションについては空白で区切った最初の単語だけを 7859 見る。Bash-5.0 以前は (# が含まれていたとしても) 全体を見る。うーん。ble.sh 7860 内部では勝手に '#' 以降を削除してから処理しているがこれは正しくない。後で修 7861 正する。これは 0.3 以前に遡って適用する。 7862 7863 * util: rlvar enable-bracketed-paste off に対応する (motivated by ArianaAsl) [#D1819] 7864 https://github.com/akinomyoga/ble.sh/discussions/199 7865 7866 rlvar を直接使う事にすると古い bash で設定を保持できないので bleopt で管理 7867 する事にして、bind enable-bracketed-paste は別名として取り扱う事にする。 7868 7869 * done: bleopt 変数は rlvar とは独立に既定の値を持つ。初期化時に rlvar が既 7870 定と異なる値を持っている場合にはユーザーが設定したと見做してその設定を読 7871 み取る。 7872 7873 * done: Bash が enable-bracketed-paste に対応している時には、bleopt の側の 7874 変数への設定時に同時に enable-bracketed-paste の値を調整する。 7875 7876 * done: bind は既に上書きしているので enable-bracketed-paste に値を設定する 7877 のに介入するのも実装できる。enable-bracketed-paste に対する値の設定は 7878 bleopt への設定に読み替える事にする。rlvar は bleopt 経由で書き換える事に 7879 する。 7880 7881 * done: この仕組を一般化して他の rlvar についても bleopt alias を作成できる 7882 様にする。これは一旦 enable-bracketed-paste に対応した後で考えれば良い。 7883 7884 * done: wiki (skip-completed-text は更新) 7885 * done: blerc 7886 7887 2022-06-18 7888 7889 * emacs: MULTILINE mode メッセージの改善 (motivated by ArianaAsl) [#D1818] 7890 https://github.com/akinomyoga/ble.sh/discussions/199 7891 7892 * done: Q&A に書く。 7893 7894 * done: MULTILINE モードの表示をしない様にする設定 7895 →keymap_emacs_show_multiline という設定変数名を追加した。 7896 7897 * やはり MUTILINE モード名自体を設定する設定項目にする方が良い。 7898 keymap_vi_mode_string_nmap との一貫性により。設定変数名は 7899 keymap_emacs_mode_string_multiline に変更する事にした。 7900 7901 * done: MULTILINE モードの表示メッセージを binding によって変える 7902 7903 * rlvar enable-bracketed-paste の設定の alias bleopt を作成してそれを上書き 7904 する。この方法はその他の補完設定に対しても適用するべきなのではないか。独 7905 立した項目で全体的に対応する事にする。 7906 7907 2022-06-17 7908 7909 * util: erasedups 高速化 (motivated by SuperSandro2000) [#D1817] 7910 https://github.com/akinomyoga/ble.sh/issues/198 7911 7912 一旦ファイルに書き出して awk で処理してから読み出す方式を試してみた。然し単 7913 に配列を走査するよりも遅くなってしまった。 7914 7915 計測してみると awk による処理自体は高速だが書き出しと読み取りの両方で滅茶苦 7916 茶時間がかかっている。printf '%s\n' "${arr[@]}" は遅いのだった。また、 7917 mapfile -d '' も内部では1文字ずつ読むモードに切り替わってしまうのか遅い。こ 7918 れは bash-5.2 以降でしか高速ではないのだった。 7919 7920 過去に同様の事をした気がする → #D1522 が対応する議論であった。 7921 7922 awk による処理は十分に高速の様だ (45ms)。読み取りは nlfix にすれば無視でき 7923 るぐらいコストを小さくできる筈 (改行が大量に含まれていない限り)。 7924 7925 * done: 書き出しの高速化に関して。 7926 7927 printf '%s\0' が遅いので writearray を実装した筈なのに 7928 writearray を確認してみたら遅い。これは別項目で考える事にする。 7929 7930 或いは history の出力を改めて解析した方が余程早いのではないか。と思ったが 7931 history の出力が編集されていると微妙である。基本的には history の出力を使っ 7932 て _ble_history を作っているのだから (そして勝手に Readline の編集が起こっ 7933 ていなければ)、_ble_history の内容と history の出力結果は一致している筈で 7934 ある。一方で、_ble_history_edit の内容に関しては結局配列として出力しなけ 7935 ればならない。_ble_history の書き出しと _ble_history_edit の書き出しを並 7936 列で実行するのだとしたら、_ble_history の側だけを history の出力を使って 7937 高速化しても余り意味がない。 7938 7939 うーん。どうにも書き込みは並列で書き込むとしても精々 170 (printf) までしか 7940 減らせない。更に bash-5.2 では printf は 455 もかかる。mawk でも 434 である。 7941 なので、bash-5.2 だと絶望的である。元々直接ループを回していた時で 790 であ 7942 る。高速化はしているが、結局大して高速化は期待できないのではないか。特に 7943 5.2 以降で高速化しないのであれば古い ver で頑張る意味もない。 7944 7945 * done: 5.2 未満では nlfix で読み取らせる事にした。以下テスト用コード 7946 7947 { 7948 ble/debug/stopwatch/start 7949 ble/debug/stopwatch/stop 'save-data' >/dev/tty 7950 ble/debug/stopwatch/start 7951 ble/debug/stopwatch/stop 'proc-data' >/dev/tty 7952 ble/debug/stopwatch/start 7953 ble/debug/stopwatch/stop "load-data (${#_ble_history[*]}, ${#_ble_history_edit[*]})" >/dev/tty 7954 # DEBUG 7955 local dup=$( ( ( time ble/builtin/history/option:s/erasedups "$cmd" 7956 declare -p _ble_history _ble_history_edit | sha256sum) 7957 ( time ble/builtin/history/option:s/erasedups.awk "$cmd" 7958 declare -p _ble_history _ble_history_edit | sha256sum) ) | uniq -u) 7959 ble/builtin/history/option:s/erasedups "$cmd" 7960 if [[ ! $dup ]]; then 7961 echo "${#delete_indices[@]}: ok" 7962 else 7963 echo "${#delete_indices[@]}: ng" 7964 echo "$dup" 7965 fi >/dev/tty 7966 } 7967 7968 * done: awk0 が使えない場合には書き出しも nlfix にしてしまう? 7969 7970 →その様に実装してみた。nawk は遅くなる。mawk と gawk は十分な速度が出て 7971 いる。それでも \0 の時よりは遅くなる様である。というか、mawk と gawk は結 7972 局 \0 に対応しているので、この nlfix は実際の所使われる事はないという事に 7973 なる。 7974 7975 * 別の可能性として erasedups で探索する範囲を制限するという事も考えられる。 7976 Bash の erasedups は一時的に off にして、手動で見つかった項目を Bash のコ 7977 マンド履歴からも削除するということ。探索範囲については、例えば起動時の 7978 history の大きさを記録しておいて、それ以降に追加された項目のみを検査する 7979 等。うーん。これは別項目として独立させる事にする。 7980 7981 * util: ble/util/writearray 最適化 [#D1816] 7982 Ref. #D1817 7983 7984 やはり巨大な配列になると書き出しが最も遅い。 7985 7986 printf '%s\0' "${_ble_history[@]}" ... 365ms 7987 ble/util/writearray -d '' _ble_history ... 1387ms (mawk だと速い?) 7988 ble/util/writearray --nlfix _ble_history ... 1397ms 7989 7990 と思ったら mawk を使っている場合には writearray も高速なのであった。nawk 7991 と gawk ではとても遅い。#D1522 を見たら多少改善したと書かれているがそうで 7992 もなかったという事だろうか。改めて注意深く計測してみる事にする。→うーん。 7993 単に mawk がコンパイルに失敗して動作していないだけだった。 7994 7995 bash-5.1 7996 [ 0.170960 sec] write by printf 7997 [ 0.035244 sec] write by declare -p 7998 [ 0.236600 sec] write by ${_ble_history[@]@Q} 7999 [ 0.677771 sec] write by nawk 8000 [ 0.428015 sec] write by mawk 8001 [ 1.804527 sec] write by gawk 8002 [ 0.689799 sec] write by nawk --nlfix 8003 [ 0.421999 sec] write by mawk --nlfix 8004 [ 1.806602 sec] write by gawk --nlfix 8005 8006 bash-5.2 8007 [ 0.455534 sec] write by printf 8008 [ 0.023524 sec] write by declare -p 8009 [ 0.690759 sec] write by nawk 8010 [ 0.434321 sec] write by mawk 8011 [ 1.810687 sec] write by gawk 8012 [ 0.693987 sec] write by nawk --nlfix 8013 [ 0.423758 sec] write by mawk --nlfix 8014 [ 1.832763 sec] write by gawk --nlfix 8015 8016 a writearray の awk 高速化? 8017 8018 うーん。やはり writearray の awk を高速化できないだろうか。何処で時間が 8019 かかっているのかを確認する。 8020 8021 % 先ず全ての文字列を連結しているがこれが遅い可能性は? 8022 % 8023 % 連結部分の時間 8024 % [ 0.041765 sec] write by nawk 8025 % [ 0.061284 sec] write by mawk 8026 % [ 0.032100 sec] write by gawk 8027 % 8028 % 無視できる訳でもないが全体の処理時間に比べればずっと小さい。これの最適化 8029 % も考えたい気がするが、これは後でも良い気がする。 8030 % 8031 % declare除去終了時刻 8032 % [ 0.049391 sec] write by nawk → 8ms 8033 % [ 0.062445 sec] write by mawk → 1ms 8034 % [ 0.036025 sec] write by gawk → 4ms 8035 % 全体quote除去 終了時刻 8036 % [ 0.059244 sec] write by nawk → 10ms 8037 % [ 0.062717 sec] write by mawk → 0ms 8038 % [ 0.045702 sec] write by gawk → 9ms 8039 % bashバグ調整 終了時刻 (Bash 5.1 では何もしない筈) 8040 % [ 0.059713 sec] write by nawk → 0ms 8041 % [ 0.062856 sec] write by mawk → 0ms 8042 % [ 0.045834 sec] write by gawk → 0ms 8043 % 変数名除去等 終了時刻 8044 % [ 0.079104 sec] write by nawk → 10ms 8045 % [ 0.078687 sec] write by mawk → 16ms 8046 % [ 0.136127 sec] write by gawk → 91ms 8047 % 8048 % この文字列の全体処理の時点で 8049 % 8050 % [ 0.079104 sec] write by nawk → 38ms 8051 % [ 0.078687 sec] write by mawk → 17ms 8052 % [ 0.136127 sec] write by gawk → 104ms 8053 % 8054 % だけ処理に時間がかかっている。うーん。これはもっと短くできる気がする。末 8055 % 尾の処理に関しては最後にならないと分からない。先ずは入力を結合せずに配列 8056 % に保持するなどして、結合する前に適用するのが良い様な気もする。これは何れ 8057 % にしても結合部分を最適化してから考えるのが良い気がする。 8058 % 8059 % →よく考えてみれば、そもそも declare -p は1行しか出力しないのでここで 8060 % 実際に連結が大量に行われるという事はない。なので、この最初の部分をもっ 8061 % と小さな文字列に分解して処理するという方向での高速化はできない。 8062 8063 dq判定直前 8064 [ 0.079104 sec] write by nawk 8065 [ 0.078687 sec] write by mawk 8066 [ 0.136127 sec] write by gawk 8067 dq判定直後 8068 [ 0.089831 sec] write by nawk 8069 [ 0.076440 sec] write by mawk 8070 [ 0.146535 sec] write by gawk 8071 split直後 8072 [ 0.211504 sec] write by nawk → 122 8073 [ 0.091142 sec] write by mawk → 15 8074 [ 0.230322 sec] write by gawk → 84 8075 8076 うーん。後は普通に loop に時間がかかっているという事 8077 8078 配列添字の除去直後でcontinueした場合 8079 [ 0.443631 sec] write by nawk → 232 8080 [ 0.130103 sec] write by mawk → 39 8081 [ 0.348103 sec] write by gawk → 118 8082 matchループ直後でcontinueした場合 8083 [ 0.657334 sec] write by nawk → 214 8084 [ 0.412463 sec] write by mawk → 282 8085 [ 1.758804 sec] write by gawk → 1410 8086 8087 うーん。これの高速化は難しい様な気がする。正規表現をやめて一文字ずつ処理 8088 する様にしたら更に悪化しそうな気がする。 8089 8090 * reject: 微妙に弄ってみる事にする。元々の時刻を測っておく。 8091 8092 [ 0.698775 sec] write by nawk 8093 [ 0.424295 sec] write by mawk 8094 [ 1.823190 sec] write by gawk 8095 8096 うーん。split を /" / で実行したら良いのではないかと考えたが 8097 [1]=$'...' の形式等もあるので /" / だけで分割するという訳にも行かない。 8098 だからと言って /['"] / で分割してしまうと、其処にあった文字が ' だっ 8099 たのか " だったのかの情報が失われてしまう。なので、この案は駄目だ。 8100 8101 一応、結果が変わってしまうが /" / で分割して処理した時の時間を見てお 8102 く。一応高速化はちゃんとする様である。 8103 8104 [ 0.391338 sec] write by nawk 8105 [ 0.269026 sec] write by mawk 8106 [ 1.267509 sec] write by gawk 8107 8108 やはり writearray の awk をこれ以上高速化する方法はない様な気がする。既 8109 にほぼ最速の実装になっているという気がするのである。 8110 8111 * 先に数十の単位で連結を行って多少復元してから処理を行う? それでも連結 8112 コストはかかるしうーん。どうなのだろうか。 8113 8114 元のコード 8115 8116 function analyze_elements_general(decl, _, arr, i, n, str, elem) { 8117 nlfix_indices = ""; 8118 nlfix_index = 0; 8119 n = split(decl, arr, / /); 8120 for (i = 1; i <= n; i++) { 8121 str = arr[i]; 8122 sub(/^\[[0-9]+\]=/, "", str); 8123 elem = ""; 8124 while (1) { 8125 if (match(str, /'"$rex_dq"'|'"$rex_es"'|'"$rex_sq"'|'"$rex_normal"'|^\\./)) { 8126 mlen = RLENGTH; 8127 elem = elem unquote(substr(str, 1, mlen)); 8128 str = substr(str, mlen + 1); 8129 } else if (str ~ /^[$"'\''\\]/ && i + 1 <= n) { 8130 str = str " " arr[++i]; 8131 } else { 8132 break; 8133 } 8134 } 8135 8136 _process_elem(elem); 8137 } 8138 if (FLAG_NLFIX) 8139 printf("%s\n", nlfix_indices); 8140 return 1; 8141 } 8142 8143 [ 0.723085 sec] write by nawk 8144 [ 0.430691 sec] write by mawk 8145 [ 1.822919 sec] write by gawk 8146 8147 N個ずつ処理する時 8148 8149 function analyze_elements_general(decl, _, arr, i, n, str, elem) { 8150 nlfix_indices = ""; 8151 nlfix_index = 0; 8152 8153 n = split(decl, arr, / /); 8154 str = ""; 8155 elem = ""; 8156 first = 1; 8157 for (i = 1; i <= n; i++) { 8158 str = str " " arr[i]; 8159 if (i % 5 != 0 && i != n) continue; 8160 while (1) { 8161 if (sub(/^ (\[[0-9]+\]=)?/, "", str)) { 8162 if (first) 8163 first = 0; 8164 else 8165 _process_elem(elem); 8166 elem = ""; 8167 } else if (match(str, /'"$rex_dq"'|'"$rex_es"'|'"$rex_sq"'|'"$rex_normal"'|^\\./)) { 8168 mlen = RLENGTH; 8169 elem = elem unquote(substr(str, 1, mlen)); 8170 str = substr(str, mlen + 1); 8171 } else { 8172 break; 8173 } 8174 } 8175 } 8176 _process_elem(elem); 8177 8178 if (FLAG_NLFIX) 8179 printf("%s\n", nlfix_indices); 8180 return 1; 8181 } 8182 8183 5個ずつ処理する時 8184 [ 0.729255 sec] write by nawk 8185 [ 0.368347 sec] write by mawk 8186 [ 1.642443 sec] write by gawk 8187 10個ずつ処理する時 8188 [ 0.714652 sec] write by nawk 8189 [ 0.347246 sec] write by mawk 8190 [ 1.636028 sec] write by gawk 8191 100個ずつ処理する時 8192 [ 0.727583 sec] write by nawk 8193 [ 0.371555 sec] write by mawk 8194 [ 1.678000 sec] write by gawk 8195 8196 "]=" で分割する作戦 8197 8198 "]=" で分割する時 8199 [ 0.438765 sec] write by nawk 39% speedup 8200 [ 0.303779 sec] write by mawk 30% speedup 8201 [ 1.378912 sec] write by gawk 24% speedup 8202 "]=" で分割する時/2個ずつ 8203 [ 0.443567 sec] write by nawk 8204 [ 0.305656 sec] write by mawk 8205 [ 1.368339 sec] write by gawk 8206 "]=" で分割する時/5個ずつ 8207 [ 0.456370 sec] write by nawk 8208 [ 0.306033 sec] write by mawk 8209 [ 1.400369 sec] write by gawk 8210 8211 ループの仕方を多少工夫 8212 [ 0.385840 sec] write by nawk 8213 [ 0.283110 sec] write by mawk 8214 [ 1.295154 sec] write by gawk 8215 8216 この方法で思ったよりは高速になった。 8217 8218 * unquote_dq の最適化 8219 8220 gawkでgensub を使う様に変更 8221 [ 0.388626 sec] write by nawk 8222 [ 0.282651 sec] write by mawk 8223 [ 1.015230 sec] write by gawk 8224 gsubによる実装に変更 8225 [ 0.356890 sec] write by nawk 8226 [ 0.218238 sec] write by mawk 8227 [ 1.016223 sec] write by gawk 8228 unquote判定の簡略化 8229 [ 0.348118 sec] write by nawk 8230 [ 0.213385 sec] write by mawk 8231 [ 0.990123 sec] write by gawk 8232 [ 0.367019 sec] write by nawk 8233 [ 0.211183 sec] write by mawk 8234 [ 1.001340 sec] write by gawk 8235 [ 0.346388 sec] write by nawk 8236 [ 0.211842 sec] write by mawk 8237 [ 1.005543 sec] write by gawk 8238 8239 b reject: ${_ble_history[@]@Q} を解析する可能性? 8240 8241 うーん。或いは declare -p は諦めて ${_ble_history[@]@Q} の結果を解析する 8242 方が簡単で良い? と思ったがこれはこれで処理に時間がかかりそうな予感がする。 8243 何より split が非自明である。 8244 8245 a 単に /' \$?'/ で split すれば良いのか、というと違う気がする。うーん。或 8246 いは実はそれで行ける? 落ち着いて考える…やはり駄目だ。これだと $ があっ 8247 たかどうかの情報が失われてしまう。 8248 8249 b /' '/ で split して更にその後で /' \$'/ で split する? うーん。問題は関 8250 係ない物を誤って split してしまわないかという事。例えば 'a'\'' ' 'b' と 8251 なっていた場合違う所で split してしまう。結局繰り返し match が必要にな 8252 るので処理が重くなる気がする。 8253 8254 或いは先に '\'' を適当に処理してしまう (置換して別の文字にするなど)? と 8255 思ったが今度は $'\n\'\'' 等に於いて関係ない '\'' をひっかけてしまう。 8256 8257 更に ${_ble_history[@]@Q} の評価自体も別にそれほど高速という訳でもない。 8258 200ms かかっている。やはり declare -p の 35ms には勝てないのである。 8259 8260 c 或いは高速化の為に C で処理するプログラムを書いてしまうのも手なのかもしれない。 8261 d もしそうするのであれば寧ろ bash loadable builtin にしてしまう? 8262 8263 これらの処理を実装するのだとしたらもっと広範に渡って bottleneck を C / 8264 builtin 実装に置き換えたい気がする。 8265 8266 以下テストに用いたコード 8267 8268 { 8269 # 計測結果 8270 ( 8271 ble/debug/stopwatch/start 8272 printf '%s\0' "${_ble_history[@]}" >| "$itmp1" 8273 ble/debug/stopwatch/stop "write by printf" >/dev/tty 8274 8275 ble/debug/stopwatch/start 8276 declare -p _ble_history >| "$itmp1" 8277 ble/debug/stopwatch/stop "write by declare -p" >/dev/tty 8278 8279 ble/debug/stopwatch/start 8280 echo "${_ble_history[@]@Q}" >| "$itmp1" 8281 ble/debug/stopwatch/stop "write by \${_ble_history[@]@Q}" >/dev/tty 8282 8283 ble/bin/awk() { "$_ble_bin_awk_type" -v AWKTYPE="$_ble_bin_awk_type" "$@"; } 8284 for _ble_bin_awk_type in nawk mawk gawk; do 8285 ble/debug/stopwatch/start 8286 ble/util/writearray -d '' _ble_history >| "$itmp1" 8287 ble/debug/stopwatch/stop "write by $_ble_bin_awk_type" >/dev/tty 8288 done 8289 8290 for _ble_bin_awk_type in nawk mawk gawk; do 8291 ble/debug/stopwatch/start 8292 ble/util/writearray --nlfix _ble_history >| "$itmp1" 8293 ble/debug/stopwatch/stop "write by $_ble_bin_awk_type --nlfix" >/dev/tty 8294 done 8295 ) 8296 8297 #_ble_bin_awk_type=nawk 8298 #_ble_bin_awk_type=mawk 8299 _ble_bin_awk_type=gawk 8300 ble/bin/awk() { "$_ble_bin_awk_type" -v AWKTYPE="$_ble_bin_awk_type" "$@"; } 8301 ble/util/writearray -d '' _ble_history >| "$itmp1" & local pid1=$! 8302 ble/util/writearray -d '' _ble_history_edit >| "$itmp2" 8303 wait "$pid1" 8304 cat "$itmp1" "$itmp2" | tr '\0' '\n' > 1.txt 8305 printf '%s\0' "${_ble_history[@]}" >| "$itmp1" & local pid1=$! 8306 printf '%s\0' "${_ble_history_edit[@]}" >| "$itmp2" 8307 wait "$pid1" 8308 cat "$itmp1" "$itmp2" | tr '\0' '\n' > 0.txt 8309 command diff -u 0.txt 1.txt > 1.diff 8310 command rm 0.txt 1.txt 8311 } 8312 8313 * [実装済] 2018-03-14 emacs: C-w を続けて実行すると kill-ring に追記にするべき [#D1815] 8314 8315 古い項目。これは既に実装されている。 8316 8317 2022-06-15 8318 8319 * github/workflows: nightly build (contributed by uyha) [#D1814] 8320 https://github.com/akinomyoga/ble.sh/pull/197 8321 8322 色々勝手に建て増しした。nightly build のページに情報を載せた。nightly build 8323 の ble-update ではnightly build を取得する様にした。動作確認もした。 8324 file#hash の取得に使うコマンドは動的ではなくて初期化時に freeze する様にし 8325 た。序でに ble/util/getmtime -> ble/file#mtime に改名して初期化を遅延させる 8326 様にした (これで初期化時の fork/exec は一つ減っただろう)。 8327 8328 2022-06-13 8329 8330 * util (fd#alloc): fd の上限に達した時にどうするか。無限ループになるのではないか [#D1813] 8331 8332 取り敢えず 1024 の探索上限を入れた。探索範囲に見つからなかった時には、元々 8333 の _ble_util_openat_nextfd の上に開く事にする。 8334 8335 2022-06-15 見ていたら誤りを見つけたので追加修正する。 8336 8337 * test: CI にテストを載せる上で既知の false error は全て潰しておく必要がある [#D1812] 8338 8339 今まで CI テストを実行すると clone stats に影響が出ると思って敢えて対応はし 8340 ていなかったが、最近では clone count が多くなって来たのでmasterへのpushにつ 8341 き1回程度のcheckout であれば特にclone stats に影響を与える事もないだろう。 8342 特に今回 nightly build の提案があったので同時にテストも実行してしまうのが良 8343 い気がする。 8344 8345 macOS で今までテストした事はなかったし、そもそも macOS 上で動く様にテストを 8346 書いていなかった。macOS の上でも動く様に調整するべき。 8347 8348 更に、make scan も一緒に実行してしまうのが良い。make scan については色々 8349 false error が出ているので潰す。 8350 8351 2022-06-10 8352 8353 * [棄却] 2021-05-23 main: BASH_XTRACEFD による set -x 出力の抑制? [#D1811] 8354 8355 | | 更に set -x についてもまた駄目になっているかもしれない。→試してみた所 8356 | | attach 部分で無駄なメッセージが沢山表示される様になっていたが実行自体には問 8357 | | 題はない様である。然し、BASH_XTRACEFD を使った方が良いのではないか。これに 8358 | | ついてはまた別の機会について考える事にする。 8359 | 8360 | 現在の抑制の手法だと必要なエラーまで抑制してしまうし、標準エラー出力を抑制す 8361 | る為に結構無理な事をしている。BASH_XTRACEFD を使って実装した方が綺麗になるの 8362 | ではないか。然し、また色々と実装上の不都合が生じるかもしれないので取り敢えず 8363 | 後でゆっくり対処する事にする。 8364 | 8365 | →改めて確認してみたが、BASH_XTRACEFD は代入すると元々設定されていた fd が勝 8366 | 手に閉じられてしまう。 8367 | 8368 | a なので元々設定されていた fd を保存する等の対処が必要になるがその為には様々 8369 | なコマンドを呼び出す必要がある。だとすると結局現在の位置よりも上に 8370 | BASH_XTRACEFD の書き換えのコードを移動することはできないので、現状使ってい 8371 | る { ... } 2>/dev/null による set -x 対策を置き換えるには至らない。 8372 | 8373 | b BASH_XTRACEFD が設定されていなかった時にだけ BASH_XTRACEFD を使って set -x 8374 | を抑制する 8375 | 8376 | % この様にしても BASH_XTRACEFD が既に指定されていた場合の為に { ... } 8377 | % 2>/dev/null の対策は外す事ができない? と思ったが、既に BASH_XTRACEFD が設 8378 | % 定されているのだとしたら {} 2>/dev/null としても意味がない (つまり 2 に出 8379 | % 力される訳ではないので結局全て BASH_XTRACEFD に書き込まれてしまう)。 8380 | 8381 | うーん。然し、BASH_XTRACEFD を一時的に /dev/null に設定するとしても、どの値 8382 | に設定するのかというのが結局問題になる。下手な fd を設定してしまうと変な所 8383 | に書き込まれて問題になる。自分で fd を開くにしても空いている fd を探す必要 8384 | がある。探す為には結局色々とコマンドを呼び出す必要がある。 8385 | 8386 | 色々考えると、単に BASH_XTRACEFD に値を設定するという話ではない。元々設定され 8387 | ている BASH_TRACEFD を待避するのにも、出力先の /dev/null を開くのにも、空いて 8388 | いる fd を探すのにコマンドを呼び出す必要がある。という事を考えると、結局現在 8389 | set +x を実行している位置までは { ... } 2>/dev/null に頼る必要がある。なので、 8390 | 現在行っている対策を減らす効果はない。 8391 | 8392 | 一方で必要なエラーまで抑制してしまっている事についてはどうか。例えば { ... } 8393 | 2>/dev/null を単に除去してしまう。そうすれば set -x の出力も通常のエラーも全 8394 | て表示される様になる。然し、結局 set -x の出力を抑制する方法が他にないので、 8395 | やはり現在の位置までは { ... } 2>/dev/null で対策しておくしかない。 8396 8397 [結論] 当初使えるかもしれないと思ったのは BASH_XTRACEFD への設定が (設定に影 8398 響を受けない) 変数代入だけで行えると考えたからであったが、その前に空いている 8399 fd を探索して更にその fd に対して /dev/null を開く為に builtin を呼び出す必要 8400 がある。従って adjust-builtin-wrappers 以前は結局今までの対策を使う必要があり、 8401 それは現在の対策範囲と変わらない。 8402 8403 * 2022-04-15 ble.sh 内部に対する xtrace (set -x) を有効にする方法 (requested by SuperSandro2000) [#D1810] 8404 https://github.com/akinomyoga/ble.sh/issues/186#issuecomment-1099696862 8405 8406 うーん。取り敢えず無理やり実装してしまって良い気がする。 8407 8408 * 設定 interface をどうするか 8409 8410 と思ったが interface をどのようにするかが微妙である。取り敢えず提案された様 8411 に BLESH_DEBUG 等の環境変数経由で設定する事にするべきか。と思ったが、bleopt 8412 で設定するべきの気がする。例えば、以下の設定がある時には set -x をしないと 8413 いう事。 8414 8415 bleopt debug_xtrace=ファイル名 8416 8417 うーん。これに対応する為にはユーザーの設定した BASH_XTRACEFD を何処かに保存し 8418 ておく必要がある。そしてその為にはファイルディスクリプタの探索等を実装する必 8419 要がある。などなど色々考えると、ロードした瞬間に実行するには処理として複雑す 8420 ぎる。そう思うと BASH_XTRACEFD は切り替えずにそのままユーザーが設定した物に出 8421 力するというので良いのではないか。 8422 8423 * というより元々の 2021-05-23 の項目の意図は set -x の抑制を BASH_XTRACEFD を 8424 使ってできないかという事だった様な気がする。つまり、今回の ble.sh に対する 8425 デバグの目的で BASH_XTRACEFD を設定するという話とは違う話なのではないか。 8426 8427 とは言いつつ set -x を抑制する為に /dev/null に設定するのを、debug_xtrace 8428 が指定されている場合には代わりにそのファイルに BASH_XTRACEFD を設定するべき 8429 だろう。という事を考えれば全く関係ない訳でもない。 8430 8431 取り敢えずこちらを先に対応してから、2021-05-23 の項目に対して set -x 対策で 8432 強制的に抑制している範囲を減らす事ができないか検討するという事で良い気がす 8433 る。 8434 8435 取り敢えず簡単に作って試してみた。あっという間に数百MBに達するので実際にこれ 8436 を使って debug する事が現実的なのかは疑問であるが、本当にクラッシュする時など 8437 には便利かもしれない。然し、幾らか問題点がある。 8438 8439 * fixed: 元々 BASH_XTRACEFD に設定されていた fd を別の番号に dup しておく必要 8440 がある。何故なら BASH_XTRACEFD が変更される瞬間にその fd は閉じられてしまう 8441 から。然しその為には空いている fd を確実に探し出す必要がある。 8442 8443 * fixed: 現在 context を switch する度にファイルを開いているが、debug_xtrace 8444 が設定された時に fd を開いておいて以降はそれを dup するべきなのではないか。 8445 毎回開き直すのは大変だし、ファイル名が相対パスで指定されていた場合、ディレ 8446 クトリ毎にファイルが作られて面倒な事になる。 8447 8448 x 実際に試してみると set -x した時の抑制に失敗している → 何かと思ったら 8449 adjust/restore options は入れ子で呼び出す事を許容しているのだった。対応した。 8450 8451 もっと複雑化と思ったが上記に対応したら原理的な問題ももうない気がする。 8452 8453 2022-06-09 8454 8455 * compat: Oh My Posh と組み合わせると動かないという質問が reddit にある (reported by abyss6166) [#D1809] 8456 https://www.reddit.com/r/linuxquestions/comments/v43hek/oh_my_posh_theme_and_blesh_not_playing_well/ 8457 8458 * 保留: oh-my-posh の設定で vertical-offset -1 を指定すると表示位置をずらす事 8459 ができる。これによって ble.sh の内部でプロンプト領域が上に1行拡張されるのは 8460 仕方がない。これは意図した動作であるし説明すれば分かってくれるのだろうと考 8461 えている。 8462 8463 * oh-my-posh の right prompt の位置計算がうまく行っていない。これの原因は分かっ 8464 た。oh-my-posh は全てのシーケンス毎に \[\] で囲んでいる。ここで rprompt の 8465 幅が分かっている場合に以下の様にしている。 8466 8467 \[\e[1000C\]\[\e[10D\] 8468 8469 一方で ble.sh では \[\] はカーソル位置を変えないという想定をしつつ、また、 8470 各シーケンスを現在のカーソル位置情報に基づいて再構築している。結果として、 8471 例えば幅 80 の端末では上記は 8472 8473 (初期位置0,0) 8474 \e[1000C → 右に 79 列進む (位置0,89) 8475 \] → (位置0,0) 8476 \e[10D → 何もしない (これ以上左に行けないので) 8477 8478 と解釈されて "\e[79C" に翻訳されてしまう。もっと簡単に言うと \[\e[1000C\] 8479 はカーソル位置を変えないので \e[10D は位置(0,0)で実行されると解釈される。本 8480 来は rprompt の為に出力しているシーケンスの全て(文字列も含めて)を \[\] で囲 8481 んで欲しいのである。 8482 8483 ? rprompt (vertical shift なし) ではどの様に描画されるのだろうか。 8484 8485 うーん。この時点で既に変な振る舞いをしている left の newline: true を削除す 8486 るとちゃんと表示できない 。。 8487 8488 と思ったが、どうやらユーザー設定において rprompt の後には必ず left が来て 8489 newline を指定しなければならないようだ。themes の中の設定は全てその様になっ 8490 ている。なので、設計がおかしいとはいえ、これをバグとして報告しても仕方がな 8491 い。 8492 8493 また、端末によって右端での動作が異なるのだという事を考えれば、rprompt で右 8494 端に1文字余裕を持たせて、更に改行を強制的に実行するというのは妥当な選択肢で 8495 ある。但し、その場合には rprompt の側で改行を入れるのが自然な実装だと思われ 8496 るが。 8497 8498 テストをする上では取り敢えず newline: true は入れる事にするのである。 8499 8500 ? bash の \[\] の説明はどうなっているのかというのを見たら単に non-printing 8501 characters を囲むのに使うとしか書かれていなくて、確かにその観点からすると 8502 omp の実装は正しい事になる。なのでこの方面から "正しくないから修正してくれ" 8503 と要請するのは難しい。 8504 8505 * うーん。変更してくれないかと依頼するよりは自分で修正でも出した方が良いので 8506 はないか。と思ってソースコードを確認してみたらどうやら \[\] はハードコード 8507 されている様だ。 8508 8509 https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/src/color/ansi.go#L77-L78 8510 8511 そもそも a.right 自体を \[\] で囲むという発想が誤っている様な気がしないでも 8512 ないが、然し一方で実際にカーソル移動を誘起する場合には \[\] で囲もうが囲ま 8513 まいが何れにしてもカーソル位置のずれは発生するのである。 8514 8515 a ちゃんとした修正を行うにはシーケンス毎に \[\] で囲むのではなくて、最終的 8516 に戻ってくる前提の一連の移動全体を囲むという事になる。然し、そもそも現在 8517 の omp の設計からして right は元に戻ってこない設計になっていて、次の left 8518 で newline: true する事によって問題を解決する仕組みになっている。そして、 8519 それはユーザーの設定項目として公開されているので下手に仕様を修正する訳に 8520 も行かない。 8521 8522 b うーん。一つの workaround は \]\[ のペアを出力時に削除するという事。 8523 8524 \]\[ を置換するには? 出力する箇所で置換するべきという気がする。 8525 8526 Engine.console (strings.Builder) に書き込んで後で Engine.string() で中身 8527 を取り出している様だ。この取り出す時に修正を行えば良いのではないかという 8528 気がする。更にこれは e.print() 経由で文字列に変換して返されている。他に 8529 PrintTooltip 及び PrintDebug でも利用されている。という事を考えると、 8530 e.string() で処理するべきの気がする。 8531 8532 取り敢えず PR を出した。この PR だと完全に問題は解決していなくて、依然とし 8533 て OMP は \[\] の中でカーソル移動を行っているが、これはこれで仕方がないのだ 8534 ろうという気がする。 8535 8536 * history: 終了時の履歴保存の際にエラーメッセージが発生する [#D1808] 8537 8538 これは apple nawk による問題のテスト中に発見した問題である。 8539 8540 | 正しくコンパイルできていない apple awk で起動した際に、↑カーソルキーを3回押 8541 | して C-d で抜けると以下のメッセージが発生する。↓だと発生しない。つまり、履歴 8542 | を遡っていて、その履歴に含まれる項目が処理に混入している可能性もある。 8543 | 8544 | bash: ((: 1*: 構文エラー: オペランドが予期されます (エラーのあるトークンは "*") 8545 | bash: ((: 1*: 構文エラー: オペランドが予期されます (エラーのあるトークンは "*") 8546 | bash: ((: 1*: 構文エラー: オペランドが予期されます (エラーのあるトークンは "*") 8547 | 8548 | ここで何が起こっているのかについては上の事は置いておいても不思議である。 8549 | 8550 | →うーん。どうもこれは↑を3回押すと履歴項目の一番上の内容が消去されてしまう様 8551 | だ。これによって history の結果の履歴番号に dirty mark として * が付加されて、 8552 | 最終的に履歴番号を算術式で処理する時にエラーが発生するという事の様だ。 8553 | 8554 | 実はこれはもっと一般的な問題なのではないか。history の結果を解析する時にこの 8555 | * の可能性を考慮に入れて処理する必要がある → 改めて確認した所、殆どの箇所で 8556 | は既にちゃんと履歴番号の後に "*" が来る場合を考慮に入れていた。今回問題になっ 8557 | たのとは別に1箇所だけ問題が見つかった。 8558 8559 結局原因は history の出力結果の履歴番号の後ろに * という文字が付く場合がある 8560 という事を考慮に入れていない箇所があったということだった。既に殆どのコードで 8561 はちゃんとこの事が考慮に入っていたが、一部のコードで見落としていた。 8562 8563 2022-05-13 8564 8565 * complete: scp の補完で固まる (reported by iantra) [#D1807] 8566 https://github.com/akinomyoga/ble.sh/issues/193 8567 8568 これは前から気になっていた事である。問題は何処に介入するのかという事である。 8569 補完関数全体を subshell で実行する様にしてしまうと 124 を返して再実行した時 8570 に無限ループになってしまう。他にも変数に対する修正が適用されない等の問題が 8571 生じる。なので、もっと内側で conditional-sync を実行する必要がある。 8572 8573 _scp_remote_files を subshell で実行しようとも思ったがそうすると COMPREPLY 8574 を渡すのが面倒だ。というか scp, ssh 等に介入すれば良い。どうせこれらは他の 8575 プロセスを起動するのだから。実際に _scp_remote_files は ssh を呼び出してい 8576 る: 8577 8578 https://github.com/scop/bash-completion/blob/6f1bbda3c66814befa8025d49363b4070ef20008/completions/ssh#L435 8579 8580 と思って実装したが動かない。どうやら $(...) の中で conditional-sync をした 8581 場合、$() が結局本体のプロセスが死ぬまでブロックしてしまうのが原因の様だ。 8582 本当のプロセスを kill -9 しても駄目の様だ。どうも更に子プロセスが起動してい 8583 るのが原因だ。 8584 8585 PGID を確認してみたが command substitution の中で & で呼び出しても固有の 8586 PGID を作成する訳では無い様だ。なので PGID に対して kill を実行すると外側 8587 も含めて予期しない所まで kill されてしまう。 8588 8589 仕方がないので ps を使ってプロセス一覧を取得して其処から kill を実行する 8590 事にする。 8591 8592 * dnf も遅い。dnf に関しては _dnf_commands_helper に介入すれば良さそうだ。 8593 然し、遅延ロードされる関数に確実に介入するには遅延ロードした時に上書きす 8594 る必要がある。うーん。一応 bash-completion に関しては 124 により一旦制御 8595 を返すので介入はできる気がする。 8596 8597 2022-06-02 conditional-sync のミスを push する。暫く手元に置いていたがずっ 8598 とこのままにしておくのは好ましくない。 8599 8600 2022-05-01 8601 8602 * 日本語を含むディレクトリに入ると化けてしまう事に気づいた [#D1806] 8603 Ref #D1798 a9551e5 8604 8605 これは \w, \W, etc 対策の副作用である。修正した。 8606 8607 2022-04-10 8608 8609 * BSD make で実行しようとする人対策 (question by lu9dce) [#D1805] 8610 https://github.com/akinomyoga/ble.sh/issues/184 8611 8612 FreeBSD で make でコンパイルしようとしている人がいる。面倒なので BSD make 8613 用の Makefile も用意して make で実行しても代わりに gmake を呼び出す様にする 8614 事にした。 8615 8616 shebang が #!/bin/bash であるのが原因だと勝手に言っていたが、これは関係ない。 8617 今後も似たような御節介の誤った報告が来るかもしれないので shebang 自体を削除 8618 してしまっても良いのかもしれない。或いは -*- mode: sh; mode: sh-bash -*- に 8619 する。然し、これだと自分の所の設定でしか Bash モードが有効にならないという 8620 問題がある。取り敢えずは現状のままという事にする。今後も何か指摘してくる人 8621 が居たら全部 shebang を削除する事にする。 8622 8623 * blehook に引数が渡されなくなっている (reported by SuperSandro2000) [#D1804] 8624 https://github.com/akinomyoga/ble.sh/issues/185 8625 8626 調べたら invoke.sandbox 経由で呼び出す時に引数が継承されていない。 8627 invoke.sandbox を導入したのは最近である。6fdabf32 が該当する変更である。 8628 https://github.com/akinomyoga/ble.sh/issues/179#issuecomment-1048416510 8629 8630 2022-04-05 8631 8632 * progcomp: cobra で生成される補完が説明を混入させる (reported by SuperSandro2000) [#D1803] 8633 https://github.com/akinomyoga/ble.sh/issues/183 8634 8635 正直 cobra は bash-completion でも問題を起こしているし。元よりとても質が悪 8636 いので余り対応したくないが、だからといって upstream に手を加えるのもまた対 8637 応が遅くてどうしようもないという事が分かっている。不本意ながらこちらで 8638 workaround を加える→取り敢えず対応した。一応動く。 8639 8640 改めて V2 の実装を確認したがやはり bash スクリプトとして質が悪い。 8641 8642 ? そもそも説明を候補に含めるのは hack に過ぎないし、これに依存していると 8643 bind 'set show-all-if-ambiguous' 等の時に正しく動作するのかも怪しい→と思っ 8644 て確認してみたが一応大丈夫の様だ。 8645 8646 以前 bash-completion で make に対して起こったのは一体何だったのか。以下で 8647 ある。 8648 8649 https://github.com/scop/bash-completion/issues/544 8650 https://github.com/scop/bash-completion/pull/546 8651 8652 うーん。調べてみるとこの時とは条件が異なる。この時は COMP_TYPE が 9 or 37 8653 の時には候補を勝手に変更しない様にしていた。これは挿入される候補の始まり 8654 部分を省略できるかどうかの判定であり、少しでも挿入されたら困るので 9 も排 8655 除している。42 は手落ちであろう。一方で今回は始まり部分は変えないので曖昧 8656 の時には後ろに自由に勝手な文字列を追加する事ができる。という事により 8657 37|42 の時にだけ気をつければ良い。 8658 8659 2022-03-19 8660 8661 * menu-complete: 補完候補に含まれる制御文字の反転は xor で行う [#D1802] 8662 8663 prompt seq \w, \W, \s で制御文字の反転を toggle する様にしたが、補完候補の 8664 表示でも同様に toggle した方が良い気がする。#D1798, #D1801 のテストの最中に 8665 実際に制御文字を含むディレクトリを作成して補完を実行した時にやはり気になっ 8666 た。当初は #D1801 の一部として対応したが別項目に分けた方が良い様に感じるの 8667 で分ける事にした。 8668 8669 * done: menu-complete: 特殊文字を含む候補の反転と選択時の反転が重なって見に 8670 くい。反転は重ね書きではなくて toggle にするべきなのではないか。 8671 8672 新しい \e[9807m で対応できるかと思って実装を確認したが trace は使っていな 8673 くて直接画面に出力するのに使うシーケンスを sgr を直接指定することで構築し 8674 ていたので使えなかった。その代わりに反転に使う sgr などをそもそもその場で 8675 g|_ble_color_Revert 等として構築していたのでその | を ^ に置き換える事で 8676 簡単に対応する事ができた。 8677 8678 一方で編集文字列に含まれる制御文字についても気になったがそもそも反転してい 8679 ないので関係ないのであった。 8680 8681 * ok: 更に編集文字列本体についても同様に toggle するべきなのではないか? と 8682 思ったがそもそも現在の実装だと編集文字列に含まれる制御文字は特に反転など 8683 していないので関係ないのであった。 8684 8685 今から新しく対応しようにも現状の実装だと反転の toggle を実装するのは簡単 8686 ではない様なので取り敢えずは対応しない事にする。もし今後必要性を感じた時 8687 に改めて対応する事にすれば良い気がする。一応項目として残しては置く。 8688 8689 2022-03-12 8690 8691 * prompt: bash-5.2 では \w, \W に加えて \s についても escape する様だ [#D1801] 8692 Ref #D1798 8693 8694 bash がなかなか実装しないと思ったらこちらが \w, \W に対する実装を push した 8695 4日後に対応が入った。どうも \s についても escape が入ったという様に commit 8696 message には書かれている。 8697 8698 \s は "bash" という文字列の様だ。これに制御文字が含まれるとは一体どういう状 8699 況だろうか。これを気にするのであれば \h, \H, \u も気にするべきなのではない 8700 か。取り敢えず全てに大して対策を加える事にした。 8701 8702 ? bash-5.2 では ${PS1@P} でもちゃんと \w, \W を escape してくれるのか→ちゃ 8703 んと escape してくれている。 8704 8705 * done: bash-4.4 以上では escape が起こった時に @P を使わない自前実装に切り 8706 替える必要がある。 8707 8708 * bash-5.2 の実装についても改めて確認する。\t はそのまま特殊文字のまま出力 8709 する様だ。その他については zsh の様に \n だとか \t の様な表現には置き換え 8710 ず一貫して ^X という形で表現している。改行は ^J になっている。 8711 8712 \s 以外にも対応している物がないか確認する。 8713 8714 bash-5.2 の対応では sh_backslash_quote_for_double_quotes に手を入れる事に 8715 よって対応が行われている。この関数は本来は eval する時に変な事が起こらな 8716 い様に $`"\ 等を escape するのが目的だったのだと思われるが、同時にエスケー 8717 プまで実行してしまうという算段である。 8718 8719 特にこの機能が有効になるのは第二引数に bit 1 を指定した時で以下が該当する。 8720 8721 ./parse.y:5745: temp = sh_backslash_quote_for_double_quotes (temp, 1); 8722 ./parse.y:5822: temp = sh_backslash_quote_for_double_quotes (t_string, 1); 8723 8724 そしてこれは正に commit msg にある様にそれぞれ \s と \w\W に対する処理で 8725 あった。なので \s, \w, \W 以外に関しては対策は実装されていない。 8726 8727 ? うーん。 ^\ に大して何か変な事が起こったりするのではないか…。例えば 8728 ^\$(echo hello) が実行されてしまう可能性はないのだろうか。試してみたら 8729 問題を再現できてしまった。 8730 8731 $ mkdir $'\034$(echo hello)' 8732 $ cd !$ 8733 8734 ? これは shopt -u promptvars でもちゃんと実行されるのだろうか? →試してみ 8735 たがちゃんと動いている様だ。OK 8736 8737 2022-03-19 これは bash に PATCH を送ったら今日適用されていた。OK 8738 8739 * bash-5.2 では META_CHAR に対しても escape を実装している様だ。うーん。 8740 ble.sh でも対応するべきだろうか。と思ったがよく考えてみたら ble.sh ではそ 8741 もそも編集文字列であっても 80..A0 に対して特別な文字は割り当てていない様 8742 な気もする。これはそれも含めて再考する必要がある。 8743 8744 →と思ったが改めて確認してみたところ 8745 _ble_unicode_GraphemeCluster_ControlRepresentation という配列にちゃんと登 8746 録しているのだった。この新しい実装でもこの配列を参照するべきである。 8747 8748 と思ったが _ble_unicode_GraphemeCluster_ControlRepresentation は単にキャッ 8749 シュしているだけなので代わりに ble/unicode/GraphemeCluster/.get-ascii-rep 8750 を呼び出すべきである。その様に実装し直した。 8751 8752 2022-03-04 8753 8754 * 2021-10-26 ble/builtin/read: status が表示されている気がする [#D1800] 8755 8756 更新はされていないので実際に表示する時の問題である。然し、vi_cmap 等の時に 8757 表示されるのは特に問題ない動作である。という事を考えると、その意味で status 8758 が有効になっていると考えても良いのだろうか? 特に read を widget の中で使っ 8759 ている時には status の高さも考慮に入れて上書きしてしまわない様にするべきな 8760 のではないか。という事を考えると status を有効・無効にする条件を考える必要 8761 がある気がする。 8762 8763 現状で既に read をどの様に表示するかを呼び出している状況で区別していなかっ 8764 たか。つまり、どの panel で表示するかを切り替えていた様な気がする。確認した 8765 所、特に切り替えてはいなくて常に _ble_textarea_panel=1 に表示している様だ。 8766 8767 右プロンプトについても同様に問題が生じそうな気がするのにも拘らず問題は起こっ 8768 ていない。調べてみると右プロンプトに関しては _ble_textarea_panel=0 の時にだ 8769 け有効化されて、有効な時にだけ表示される様になっている様だ。 8770 8771 * fixed: 一方で、prompt_xterm_title 等は read に対しても有効の儘になってい 8772 る気がする。これは出力しない様にするべきなのではないか。或いは、read の中 8773 で一時的に別の値に設定するべきだろうか。 8774 8775 ble/textarea を read 以外の textbox 等に使う場合も考えると、xterm_title 8776 等についてもやはり _ble_textarea_panel=0 の時にだけ表示する様にするべきの 8777 気がする。 8778 8779 * fixed: _ble_prompt_rps1_data[12]=$rps1_enabled という行があるが現在は 8780 [12] は使っていないのではないか。 8781 8782 f6af802c で rps1_enabled を用いて update-textmap の計算を更新する様に変更 8783 したが、これは [12] とは関係ない様だ。 8784 8785 元々 [12] に値を代入する様になったのは cf8d9493 である。此処では 8786 update-textmap で rps1 が有効になっているかどうかを参照する為に [12] に情 8787 報を格納している。然し、先述の f6af802c に於いて最早 rps1_data[12] は参照 8788 されなくなった。 8789 8790 という事を考えると rps1_data[12] に今現在代入しているのは削除して良い。 8791 (或いは現在 rps1_enabled にしているのを rps1_data[12] に代入しても良い気 8792 はするが、一応決定している箇所が異なる様に思われるので現状の儘にする) 8793 8794 うーん。実は status_line は ble/propmt/update とはまた別の管轄の様である。 8795 ble/canvas/panel/render から呼び出された時に表示している気がする。特に 8796 ble/prompt/status#panel::render が呼び出された時に、正しく表示されるべき時 8797 は表示し表示されない時は表示されない様に実装されているのか。特に getHeight 8798 で変な値を返していないかだとかが気になる。 8799 8800 どうやら _ble_edit_layout が normal に戻ってしまっている様だ。本来 8801 _ble_edit_layout はずっと command のままであるべきであるのにも拘らず。何処 8802 で _ble_edit_layout が設定されるのは、特に command 以外の値に設定されるのは 8803 leave-command-layout だけである。確認してみるとどうやら 8804 ble/application/render で leave-command-layout が呼び出されている様子である。 8805 8806 * できるだけ明示的に enter-command-layout と leave-command-layout を対にし 8807 て実行する事にした。 8808 8809 * .insert-newline で enter-command-layout をしているが、それに対応する 8810 leave-command-layout を正しく記述する必要がある。 8811 8812 .insert-newline の呼び出し元。確認してみたがとても沢山ある。 8813 8814 ./src/edit.sh:1491: _ble_edit_line_disabled=1 ble/widget/.insert-newline 8815 ./src/edit.sh:6687: _ble_complete_menu_active= ble/widget/.insert-newline "$opts" 8816 8817 ./src/edit.sh:6701: _ble_edit_line_disabled=1 ble/widget/.newline keep-info 8818 ./src/edit.sh:6750: ble/widget/.newline keep-info 8819 keep-info を指定している時には問題ない。 8820 8821 ./src/edit.sh:6782: ble/widget/.newline 8822 これはコマンド実行 8823 ./src/edit.sh:6865: _ble_edit_line_disabled=1 ble/widget/.newline 8824 ble/widget/edit-and-execute-command.edit 8825 これは最終的に ble-edit/exec/register に至る。 8826 8827 ./src/edit.sh:6760: _ble_edit_line_disabled=1 ble/widget/.insert-newline 8828 ./src/edit.sh:6770: _ble_edit_line_disabled=1 ble/widget/.insert-newline 8829 ./src/edit.sh:9219: ble/widget/.insert-newline 8830 ./src/edit.sh:9221: _ble_edit_line_disabled=1 ble/widget/.insert-newline 8831 ./src/edit.sh:9871: _ble_edit_line_disabled=1 ble/widget/.insert-newline 8832 ./src/edit.sh:9880: _ble_edit_line_disabled=1 ble/widget/.insert-newline 8833 ./src/edit.sh:9905: _ble_edit_line_disabled=1 ble/widget/.insert-newline 8834 ./keymap/vi_test.sh:424: _ble_edit_line_disabled=1 ble/widget/.insert-newline 8835 8836 うーん。一旦 disable して出力して再び描画するというパターンが多い気がする 8837 のでこれは関数にするべきなのではないかという気がする。と思ったが、出力に 8838 用いるコマンドが色々なので、eval の様な形になるだろうか。少々面倒の気がする。 8839 8840 * done: ble/edit/info refactor 8841 8842 aplication/render で leave-command-layout を実行しているのは info をこの 8843 時点で表示させるのが目的だった可能性? 恐らく高さの計算は info/render を呼 8844 び出さないと分からないので先に計算させているのだろうという気がする。 8845 8846 これは本来 getHeight の段階で正しく計算して返すべきである。現在の設計では 8847 info 自体は自身が有効化されているかどうかを把握していなくて外部から表示・ 8848 非表示を制御する構造になっているのがいけないのではないか。 8849 8850 というよりそれを言い出すと textarea も同様なのではないか。textarea の表示 8851 非表示はどの様に制御されているのだったか → _ble_textarea_panel が一致し 8852 ていれば更新する。もし一致していなければそのままにする。もしくは "0:現在 8853 の高さ" を返しているので潰れてしまう事は許容している (_ble_textarea_panel 8854 が復元した時に改めて再描画するという事なのだろう)。そういう意味で 8855 _ble_textarea_panel=-1 等にする事によって textarea を完全に off にする事 8856 も可能である。或る意味、自身で表示・非表示・(現在の状態を保持) の状態を保 8857 持していると言える。info についてもその様な状態を保持させて管理するべきの 8858 気がする。それは getHeight の段階でちゃんと参照する様にする。 8859 8860 改めて確認したが問題はそんなに簡単ではない様な気がする。そもそも render 8861 の段階では info の内容は決定されない。そういう意味に於いて別に問題は起こ 8862 らない筈。問題が起こるのは、ble/edit/info/reveal を実行する事によって内容 8863 を改めて構築し直す必要があるという事の気がする。何故そうなっていたのかと 8864 いうと enter-command-layout に入る時に info の内容を消去しているから。 8865 8866 * 現状では既に leave-command-layout が何処かで呼び出されている前提なんで 8867 改めて info/reveal を呼び出す必要はない。leave-command-layout が呼び出 8868 された時点で info の内容も再構築されている筈だから。 8869 8870 x と思ったら起動時に info が表示されなくなってしまった。うーん。改めてど 8871 ういう条件で再描画が必要になるのか整理して、再描画が必要になった箇所で 8872 必ず invalidated を設定する様に修正する必要がある。 8873 8874 うーん。何だか分かった様な気がする。高さが 0 だとそもそも invalidated 8875 のチェックすら来ないという事なのではないか? と思ったがそれも変である。 8876 例え invaldiated であっても panel::getHeight は呼び出される筈だから。 8877 8878 改めて info が一体どの様にして状態を管理しているのか確認するべきである。 8879 或いは再設計する。_ble_edit_info はもし info が表示されていたとしたら表示 8880 されている内容である。_ble_edit_info_default は既定の内容であってこれは 8881 scene が default になる時に表示される内容である。現在はどうも info が表示 8882 されていないという状態も _ble_edit_info で取り扱おうとしているのが混乱の 8883 原因になっている気がする。 8884 8885 * ok: ble/edit/info/hide を使っている箇所はあるか → 一箇所しかない。これ 8886 は info#collapse に置き換えたと思って良い。 8887 8888 * うーん。構造的にもっと別の方法にした方が良いのかもしれないとも思われる。 8889 8890 ! つまり、render の側でコマンド実行中かそうでないかで動作を切り替える。コ 8891 ! マンド実行中でない時には何れにしても leave-command-layout はコマンド実 8892 ! 行終了後に有効にする。 8893 8894 コマンド実行中にだけ command-layout にするというのの方が正しいのではない 8895 か。とも思ったが、enter-command-layout の時点で実はプロンプトや status, 8896 info 等を削除して command-layout に入っている。という事を考えると、やはり 8897 現状の実装の方が正しい様な気もする。 8898 8899 例えば、仮にその場でだけ command-layout になって、一旦はまた通常 layout 8900 に戻って、それからその後でまた command-layout になってコマンドを実行する 8901 とどうなるのだろうか。 8902 8903 x 空のコマンドしか実行しない状態になっていると leave-command-layout の実行 8904 が抜けてしまうのではないか。 8905 8906 a 空のコマンドがあるかどうかは呼び出し元でちゃんとチェックする前提として、 8907 gexec の側ではスキップは行わない。 8908 8909 b 空のコマンドしかない場合でも leave-command-layout は必ず実行する様にす 8910 る。 8911 8912 然し、そうするとこれは .end の後で実行するしかなくなるが、.end の中で 8913 .tail まで呼び出しているので、.end の後で leave-command-layout を実行し 8914 ても意味がない。改めて .tail 及び再描画を呼び出す必要があって無駄である。 8915 8916 或いは、空のコマンドしか無い場合は特別扱いで leave-command-layout と 8917 .tail を両方呼び出す様にする? 8918 8919 うーん。a の方法の方が良い気がする。 8920 8921 結局 ble-edit/exec/register の側でもチェックを入れる事にした。一部でチェッ 8922 クが重複する事になるが、その方が安全であるし、論理的にすっきりしている。 8923 8924 x fixed: と思ったが複数のコマンドを実行して一部は leave-command-layout を実 8925 行して一部は実行しないという状態になったら一体何が起こるのだろうか。。一 8926 番最後に実行した物が leave-command-layout を実行していると何だか変な事に 8927 なる気がする。 8928 8929 或いは、_ble_app_render_mode として panel の他に command も用意して、 8930 command の時には reveal を実行せずに ble/canvas/panel/render を実行する? 8931 panel の時には leave-command-layout を強制的に呼び出す様にする。コマンド 8932 を実行している間は _ble_app_render_mode=command とする。その方が今迄の実 8933 装に近いしすっきりしている様な気もする。 8934 8935 然し、論理的に正しい事をしているのかどうかというのは良く分からない。 8936 8937 うーん。これに関しては enter/leave で単に既に command かどうかを判定する 8938 のではなくて、enter/leave の深さを数える様に変更する事にした。 8939 8940 2022-03-03 8941 8942 * [解消] 2021-11-21 bash-3.2 で syntax highlighting がロードされるのが遅い [#D1799] 8943 もしかして遅延している? 8944 8945 Ref #D1731 重複 8946 8947 * 2022-01-19 PS1 のディレクトリ名に特殊文字が含まれている場合の取り扱い [#D1798] 8948 https://lists.gnu.org/archive/html/bug-bash/2022-01/msg00051.html 8949 8950 これは不要な互換性の問題を防ぐために Chet がどの様に対処するのかを見てから 8951 それと同じ様に実装するのが良い。 8952 8953 またその他の文字列についても同様に注意が必要なのではないかと思われる。 8954 と思ったが他に任意の文字列を出力する様な状況もない様な気はする。 8955 8956 2022-03-03 これは結局何の修正も入らない様だ。うーん。勝手に ble.sh の側で対 8957 応してしまっても良い。 8958 8959 zsh は ^J や ^I に対しても特別な表示にするのだろうか。それともこれらはその 8960 まま表示するのだろうか。と思って試して見た所、単に \n や \t に置換して表示 8961 する様だ。\001 に対しては ^A と表示する。ESC は ^[ と表示する。 8962 8963 やはり反転する等して強調した方が良い様な気がする。本当にそういう名前を持っ 8964 たディレクトリ名と区別が付かない。新しく trace に SGR(9807) という反転状態 8965 を toggle する番号を追加する事にした。 8966 8967 * main: ble/base/unload 後に ble/util/assign 一時ファイルが残留する [#D1797] 8968 8969 ble/base/clean-up-runtime-directory で毎回 rm が実行されている。どうやら前 8970 回の session が最後に assign に実行をしてそれで一時ファイルが作成されている 8971 様だ。 8972 8973 ble/base/unload を実行した後に trap/.handler で joblist.check を呼び出して 8974 いるのが原因である。或いは、joblist.check は unload 状態にある場合には実行 8975 しなくても良いのではないか。然し、改めて確認すると unload の状態にあるかど 8976 うかを記録している変数はない様だ。そう思うと EXIT の時だけの特別扱いとして 8977 joblist.check をスキップするという可能性? 或いは、unload を実行した時点で 8978 ble/util/assign を使わない実装に切り替える? 8979 8980 a ble/util/unload は trap/.handler 以下で直接実行する。結局勝手に削除されて 8981 は困る物だし、最も重要な物の一部でありモジュールを疎結合にする必要性も薄 8982 い。という事を考えると、unload は特別扱いしても良いのかもしれない。 8983 8984 然し、そもそもの問題として trap handler を jobs で囲んでいた理由を考える 8985 と、やはり unload であっても囲んで実行した方が良い可能性はあるのだろうか。 8986 8987 ? というよりそもそも何故 jobs で囲んでいたのだったか。 8988 8989 思うに、trap handler の中等で外部コマンド等を実行するとその分だけ job 8990 項目が累積してしまう問題を防ぐのが目的だった気がする。今正に終了しよう 8991 としている段階で jobs を表示する機会はない気がするので気にしなくても良 8992 いのではないだろうか → 2回目の joblist の呼び出しは正に 8993 ignore-volatile-jobs で呼び出しているので無視するのが目的である。 8994 8995 問題が起こるとすれば user trap の中で jobs を呼び出した時にごみが沢山表示 8996 される可能性があるという事だが、其処で変な物が表示されても大した問題では 8997 ない様な気がする。というより、そもそも ble.sh がジョブ一覧を管理している 8998 時点で user が実行した jobs からは特定の項目が受け落ちている筈だから、な 8999 い筈の物があるぐらいならそれに比べれば大した問題ではないのでは? という考 9000 え方もできるかもしれない。 9001 9002 ? user trap を jobs で囲む必要性はないのだろうか。 9003 9004 これは本来は user trap の中で発生した余分な jobs entry も削除してしまっ 9005 て良い気がするが、もしかすると本当に job を投げるという事があるかもしれ 9006 ないので、その項目が意図せず消滅しない様に囲むのはやめたのだろうという 9007 様に思われる。何れにしても今回は関係ない。 9008 9009 ? そもそも EXIT の中から終了をキャンセルする事は可能なのだろうか。或いは、 9010 他の要因によって終了がキャンセルされる可能性はあるのだろうか。考えて見 9011 るにその様な方法は存在しない気がする。という事を考えると、jobs の情報を 9012 収集しても仕方がないのではないかという気がする。 9013 9014 o ユーザーが登録した何かが ble.sh に依存しているという可能性もあるのでは 9015 ないか。という事を思うと、やはり unload は外側で一番最後に実行するべき 9016 の気がする。 9017 9018 b 或いは、EXIT の時だけは joblist.check はスキップする。或いは unload して 9019 いる事を何処かに記録するなどして、それに応じて joblist.check をスキップす 9020 る。 9021 9022 c 或いは unload の際に ble/util/asign を書き換えてコマンド置換を使う様にす 9023 る → 然し、そうすると環境に影響を与える事を前提としている 9024 ble/util/assign の呼び出しに対して正しく対処できなくなる。特に今回問題に 9025 なっている joblist.check の呼び出しは環境に対する影響を前提としているので、 9026 この方法では正しい解決方法にはならない気がする。 9027 9028 また、この方法だと結局 fork の回数が終了時に余分に増える事になるので合計 9029 では実行時間は減らない。寧ろ、複数回の ble/util/assign がある様なので、そ 9030 れによって合計時間は増えてしまっている。(但し、終了時なのでユーザー体験を 9031 損ねる事はない様に思われる。) 9032 9033 現在の文脈を変える為に >/dev/null に繋いで現在の環境でも実行するという事 9034 もできるかもしれないが、もしそのコマンドがファイルシステム等に副作用を齎 9035 す物だった場合、二回実行する事によって結果が変わってしまうし、また実行時 9036 間も二倍になるし良い事は何もない。 9037 9038 d 或いは unload している時には何か別のファイルを一時ファイルとして 9039 ble/util/assign を利用する? 然しもしその様なファイルを簡単に安全に作れる 9040 のであれば始めから ble/util/assign は必要ないのでは。 9041 9042 或いは unload している時は ble/util/assign/.rmtmp に於いて rm を明示的に 9043 実行する様にする。然し、これだと結局 fork の数は増えるので意味がない。然 9044 し、少なくとも動作が変わってしまう c よりは現実的な方法である。 9045 9046 # ? 所で here document 等を一時ファイルの代わりに使う事はできるのだろうか。 9047 # と思ったが、最近の bash では here documents は一時ファイルではなく pipe 9048 # になってしまっているので使えない。 9049 # 9050 # 試しに以下を試してみたらファイルの読み書きが出来てしまった。 9051 # 9052 # $ bash-4.4 -c '{ echo check world > /proc/self/fd/0; cat /proc/self/fd/0; } <<< hello' 9053 # 9054 # 然し、bash-5.0 以上では失敗する。bash-5.0 以上でファイルにする為には大 9055 # 量のデータで初期化しなければならないので非現実的な気がする。その他に 9056 # bash が一時ファイルを生成しそうな場合はない気がする。プロセス置換は 9057 # pipe である。 9058 # 9059 # 更に本当にどのシステムで動くのかも定かではない。どうやら bash は一時ファ 9060 # イルを早々に unlink してからコマンドを実行する様である為。 9061 9062 結局 a の方法で、ble/base/unload は別枠で trap handler の最後で実行する事に 9063 した。 9064 9065 2022-03-02 9066 9067 * 2022-02-03 edit: もしかしたら stty sane の頭に空白を置くと良いのでは [#D1796] 9068 9069 先頭に空白を置いたコマンドの履歴登録をなしにする設定にしている人がいる。 9070 9071 或いは勝手に stty sane を HISTIGNORE に設定するという手もある? と思ったが、 9072 それだとユーザーが本当に自分で stty sane を実行した時に履歴に残らないし、或 9073 いは HISTIGNORE を一旦保存して復元する仕組みを作ったとしても何かの拍子に実 9074 行できなかった時にやはり困るし、余り信頼性が高いとは言えない。 9075 9076 これた簡単だが採用する。 9077 9078 * history: detach 状態で終了すると履歴に記録されない [#D1795] 9079 9080 detach 状態で終了した時、また detach している間の履歴が記録されなくなってい 9081 る気がする。EXIT が呼び出されていないのだろうか。また後で確認する。 9082 9083 どうも ble/builtin/history/option:a 迄はちゃんと呼び出して実行しているが、 9084 rskip, wskip の更新が思う様に振る舞っていない様だ。rskip は現在のファイル内 9085 の読み取り位置で、wskip は現在の Bash プロセス内の履歴の書き込み開始位置 9086 (次にファイルに書き込むべき項目の位置) を管理している。history/option:a の 9087 中で呼び出した check-uncontrolled-changes で wskip が先端位置に移動して、そ 9088 の為に何も書き込まれないという状態になっている様に思われる。 9089 9090 そもそも detach 状態で終了した場合、detach 前に実行していたコマンドですら書 9091 き込まれずに終了してしまっている。 9092 9093 * そもそも prevmax!=max だからと言って wskip..prevmax 迄はちゃんと履歴に残 9094 すべきなのではないか。と思ったがそれを記録する手段がない様な気がする。否、 9095 subshell で適当に -r してそれから書き込めば良いのだろうか。 9096 9097 取り敢えず対応した。 9098 9099 * 履歴が倍加する問題が新しく発生していないか確認する。 9100 一応 "history -a;history -c;history -r" に対しては問題は起こっていない。 9101 bashrc で history -r をしても変な事は起こっていない。恐らく大丈夫。 9102 9103 * complete: BUG cygwin$ pdflatex [TAB] で /usr/bin/cat: '': No such file or directory というエラー [#D1794] 9104 Ref #D1637 9105 9106 chat では再現しない。bash-completion はロードされていない。 9107 9108 うーん。これは 2365e09c によるバグである。今迄5ヶ月間ずっと mandb を正しく 9109 抽出する事ができていなかったという事になる。今迄何故気付かなかったのだろう。 9110 不思議である。或いは、また別の方法によって抽出できていたという事か? → そう 9111 いう事だ。つまり、Linux 等では man -w 等を使ってファイルを決定できていたの 9112 で問題がなかったのである。 9113 9114 * edit (exec_elapsed_mark): やはり既定で時・日などの分解能の表示にも対応する [#D1793] 9115 9116 長時間ログインしていた後等にはやはり長い時間経過している事がある。 9117 その時に常に分で表示されると分かりにくい。 9118 9119 * canvas: BUG 何故か2回目の char_width_@=auto がちゃんと動いていない気がする [#D1792] 9120 Ref #D1669 9121 9122 何故だろうか。後で確認する。 9123 9124 改めて試してみたがゆっくりやれば何度やっても問題はない。auto を代入してから 9125 急激に RET 等を実行するとそれ以降は常に west, 7.0 にしかならなくなる。CPR 9126 応答の順序がずれてしまっている可能性? 何処かのタイミングでずれを修正したら 9127 治るのだろうか。 9128 9129 * _ble_term_CPR_hook に何か変な物が残存している可能性を確認。 9130 9131 →分かった。逆だった。timeout のコードが悪さをしていた。timeout 時刻の更 9132 新を行っていなかったので常に timeout する状態になっていてまともに CPR が 9133 受信できなくなっていた。 west, 7.0 というのは CPR 応答がなかった時の既定 9134 の値という事だろう。 9135 9136 ! ? そもそもどの様にしてずれが起こるのか。初めのずれが起こらない様に調整でき 9137 ! るのではないか。 9138 9139 結局 #D1669 の単純なバグだった。修正した。 9140 9141 * blehook -+= は入力しにくいし見にくいので != を一意追加として対応する [#D1791] 9142 9143 * done: != ... 未だ登録されていない時に追加する 9144 * done: -+= ... 後ろに持ってくるという意味に変える。 9145 * done: +-= ... 前に持ってくるという意味で追加する。 9146 9147 * update wiki 9148 9149 * complete: sabbrev を削除する機能がない [#D1790] 9150 9151 削除の仕方としては以下の2種類が考えられる。 9152 9153 ble-sabbrev -r a # bind, complete と同様 9154 ble-sabbrev a=- # trap と同様 9155 9156 後者は本当に "-" に展開させたい時 (実際そういう場合が存在するのかは謎だが) 9157 と衝突するので前者の方が良い気がする。 9158 9159 また、前者を採用するとしたら -r に対して optarg を要求するのか、或いは -r 9160 に対して optarg を要求するのかで振る舞いが変わってくる。 9161 9162 * progcomp: ble.sh 既定の候補を生成しない機能 (motivated by rsteube) [#D1789] 9163 https://github.com/rsteube/carapace/issues/431 9164 9165 > prevent default file completion when no values returned 9166 9167 このオプションを提供する事にする。 9168 9169 現在 "候補が生成されていたら" という意味で生成候補数を参照している箇所を全 9170 て書き換える必要がある気がする。 9171 9172 後 core-complete の中から公開 interface を決めてそれを説明する必要がある気 9173 がする。 9174 9175 * 拡張 comp_opts をまとめる。prog-trim, syntax-raw, filter_by_prefix, 9176 no-mark-directories 9177 9178 現在参照している comp_opts は以下の通り。 9179 9180 $ grc '(comp_opts|DATA):? ==' 9181 9182 元から bash に存在しているオプションは以下の通り: 9183 bashdefault default dirnames filenames noquote nosort nospace plusdirs 9184 9185 * done: 拡張オプション名は分かる様にした方が良いのでは。例えば ble- で始め 9186 る。或いは、- で始める。もしくは -ble- で始める。 9187 9188 " a -prog-trim, -syntax-raw, -filter-by-prefix, -no-default 9189 " 9190 " うーん。- だけだと結局ユーザー的には混乱の元であるというより、すぐにそ 9191 " れが "ble.sh" 特有の機能であると理解しにくいのではないかという気がする。 9192 " 然し一方で "-" で始まっている時点で非標準の機能であるという事は明らかで 9193 " ある。 9194 " 9195 " b ble-prog-trim, ble-syntax-raw, ble-filter-by-prefix, ble-no-default 9196 " 9197 " ble- だけでも十分の気がするが、これだと名前空間的になっていて、もっと細 9198 " かく分類したくなってしまう。 9199 " 9200 " c -ble-prog-trim, -ble-syntax-raw, -ble-filter-by-prefix, -ble-no-defualt 9201 " 9202 " CSS の vendor prefix の様に -ms- だとか -moz-, -webkit-, -o- の様にして 9203 " いる物を真似て -ble- だとか -mwg- だとかで良いのではないかという気がす 9204 " る。-mwg- は今迄使った事がないので ble.sh には組み込まない様にしておき 9205 " たい。 9206 " 9207 " 然し、一方で、他の compopt の枠組みが今後出てくる様にも思われないし、対 9208 " 応していない物を bash に渡したら何れにしてもエラーになるので、結局汎用 9209 " の補完を作成するとしても呼び出し元で場合分けする事になる。なので vendor 9210 " prefix の様な物を設定して場合分けに使える様にする必要があるのかも分から 9211 " ない。この様に名前を分けるのは主にユーザーの側でこれが非標準であるとい 9212 " う事が分かる様にする為の物である。 9213 " 9214 " どれにすれば良いか分からないが、長いものを採用する上で憚りになるのは、単 9215 " に無駄な prefix がついていると読みにくいという事、冗長になるという事であ 9216 " る。一方で、ユーザーや他の人の意見も聞いて最終的に決定するとなると、何れ 9217 " にしても "ble" は入れた方が良いという様に要請されるのは明らかである。 9218 " 9219 " 然し、既に様々の ble.sh の独自機能に使われている opts では ble- 等の 9220 " prefix は使っていないし、今後使う必要も全く無い。その様な物との整合性を考 9221 " えると、やはり特別な prefix は特につけなくても良いのではないかという気も 9222 " してきてしまう。一方で compopt はやはり本来は Bash の機能なので名前空間を 9223 " 乱すのも変である。 9224 " 9225 " うーん。面倒なのでやはり何も新しい prefix は付けずに manual で説明・注意 9226 " 喚起するだけで十分なのではないかという気がしてきた。うーん。本当だろうか。 9227 " 9228 " うーん。- で始まる prefix はそれ単体でオプションの様でもあるからやはり混 9229 " 乱の元の気がする。と思えば prefix を設定するとしても "ble-" 一択の気がし 9230 " てきた。 9231 " 9232 " d 或いは compopt -o prog-trim ではなくて compopt --bleopt prog-trim だと 9233 " か、compopt -O prog-trim だとか、compopt -s prog-trim の様な形の別の指 9234 " 定の仕方をさせるという手もある。内部的には -prog-trim 等で良いのだろう 9235 " という気がする。compopt は実質的に -o, +o だけしかオプションがない (一 9236 " 応 -DEI もある)。或いは prog-trim=on 等でも良いかもしれないと考えたが、 9237 " これは compopt を適用する対象のコマンド名と区別がつかなくなるので駄目。 9238 " 飽くまでオプションの形をしていなければならない。オプションの形をしてい 9239 " る物については仮にそのオプションが存在していなかったとしてもちゃんと知 9240 " らないオプションとしてエラーになる様である。 9241 " 9242 " compopt -s prog-trim; compopt -u prog-trim 9243 " compopt -O prog-trim; compopt +O prog-trim 9244 " compopt -o prog-trim; compopt +o prog-trim 9245 " compopt -o ble-prog-trim; compopt +o ble-prog-trim 9246 " compopt -o -prog-trim; compopt +o -prog-trim 9247 " 9248 " うーん。やはり奇を衒った様な事をするのではなくて単に -o/+o を流用するの 9249 " が自然の気がする。"-" で始まるのも混乱の元である様に思われる。 9250 " 9251 " compopt -prog-trim; compopt +prog-trim 9252 " 9253 " これは短オプションの集合と区別が付かないので却下。 9254 " 9255 " e もう少し異なる名前付けで区別する可能性 9256 " 9257 " compopt -o _prog_trim 9258 " compopt -o progTrim 9259 " compopt -o ProgTrim 9260 " 9261 " これらは Bash のオプションとは違うという雰囲気は出るかもしれないがやは 9262 " り ble に関連するという事が明白ではないし、中途半端に違いを出しても仕方 9263 " がない。 9264 " 9265 " いっその事、関数名に倣って / で分けるというのも手である。 9266 " 9267 " compopt -o ble/prog-trim 9268 " compopt -o ble/filter-by-prefix 9269 " compopt -o ble/syntax-raw 9270 " 9271 " よくある設定の様に "." で名前空間を分けるというのも有効である。 9272 " 9273 " compopt -o ble.prog-trim 9274 " compopt -o ble.filter-by-prefix 9275 " compopt -o ble.syntax-raw 9276 " 9277 " うーん。contrib 等との整合性も考えると / で分けるのが良い気がしてきた。 9278 " つまり、既に "名前 + /" を vendor prefix の様に使って来たのだからそれを 9279 " 踏襲するのが良い。新しい option は ble/no-default という事にする。 9280 9281 結局 "ble/*" で統一する事にした。 9282 9283 [実装] 9284 9285 取り敢えず実装した。 9286 9287 * ok: うーん。然し、もし source:argument をキャンセルしたとしても、結局また 9288 別の source が候補を生成するのではないかという気がする。全ての source を 9289 キャンセルする必要があるだろうか。或いは、また別の source は別の種類の補 9290 完に相当するので気にしない? うーん。気にしないで良い気がしてきた。 9291 9292 それに、候補が複雑な場合には何れにしても source:argument は何も候補を生成 9293 しなくなるが、その時に意図しない別の種類の補完が起動したという記憶はない。 9294 従って、実際の所 source:argument をキャンセルするだけで大体補完は終わるの 9295 ではないか。つまり、argument を跨ぐ様な補完 source は現在はないので 9296 source:argument が一番最後の source であり、だとすると source:argument を 9297 キャンセルするだけで良い。 9298 9299 もし argument を跨ぐ様な補完の可能性があれば、それはまた完全に独立した補 9300 完なので progcomp によって補完がキャンセルされる言われもない様な気がする。 9301 これは今後実際にそういう要望が (仮に) 出た時に考えれば良い。 9302 9303 2022-03-01 9304 9305 * complete (action:command): function の description の quote が邪魔 [#D1788] 9306 9307 最初の2行と末尾の } は削除して良い。また、quote ではなくて trace-text と同 9308 様の表示の仕方にしたい気がする。 9309 9310 trace-text と同様の文字列に変換する関数は既になかったか? 9311 9312 うーん。ble/unicode/GraphemeCluster/.get-ascii-rep という関数があるがこれは 9313 内部的にしか使用されていない。一方で、うーん。というか 9314 ble/canvas/trace-text をそのまま呼び出すべきの気がしてきた。そもそもその為 9315 の関数の筈である。 9316 9317 或いはファイル名と行番号を表示した方が有益の気もする。取り敢えず両方表示す 9318 る事にした。ファイルパスは長くなるので最後の名前だけ表示する事にした。 9319 9320 * complete: --optarg= に対して progcomp が走らない (motivated by rsteube) [#D1787] 9321 9322 これは "--optarg=" 全体に対する引数補完よりも = の右辺 "" に対する優先順位 9323 が高いから。 9324 9325 [導入経緯確認] 9326 9327 然し、この様に引数の途中に = が含まれる時に rhs 補完も実行する様にしたのは 9328 何か別の理由があった様な気もする。その時の記録を確認する必要がある。遡る。 9329 9330 da384044 #D1701 で変更されているがこれで導入された訳ではない。と思ったが 9331 #D1701 よりも前は以下の様になっていて argument でない時にのみ rhs を設置し 9332 ていた。 9333 9334 local word=${text:istat:index-istat} 9335 if ble/syntax:bash/simple-word/is-simple-or-open-simple "$word"; then 9336 # 単語が istat から開始している場合 9337 local src 9338 for src in "${source[@]}"; do 9339 ble/syntax/completion-context/.add "$src" "$istat" 9340 if [[ $src != argument ]]; then 9341 local rex="^([^'\"\$\\]|\\.)*=" 9342 if [[ $word =~ $rex ]]; then 9343 word=${word:${#BASH_REMATCH}} 9344 ble/syntax/completion-context/.add "$src" $((index-${#word})) 9345 fi 9346 fi 9347 done 9348 9349 つまり、やはり #D1701 によってこの取扱が導入された事になる。 9350 9351 * reject: と、思ったが上記のコードはそもそもおかしい。source には大体複数の 9352 文脈が登録されているので結局 rhs は argument の有無に関係なく大体複数生成 9353 される事になる。と思ったが、そうではない。 add rhs ではなくて add "$src" 9354 としているので、 argument 以外については = 以降からでも同様に生成するとい 9355 う取り扱いになっている。 9356 9357 * #D1701 の議論を確認したが大した事は書かれていない。特にこの取扱の変更に関 9358 しては全く触れられていない。然し、実際に source 配列の中身を見ると option 9359 という物が追加されている。これが理由なのではないだろうか。つまり、option 9360 という項目を追加したが、option が = の続きから挿入されるのは変である。な 9361 ので、option も argument と同じく途中から文脈設定する必要性がない。他に 9362 variable:= という物もあるが、これも途中から挿入するのは変である。command 9363 も sabbrev も同様である。結局、途中からの挿入を許すのは source:file だけ 9364 である。という事を考えれば最初から file を固定して = の後の位置に補完開始 9365 点を設置するのは自然である。 9366 9367 然し、そもそも unquoted な = の位置から補完を開始する選択肢を加えたのはどの 9368 時点だろうか。 9369 9370 先ず 2f2f0eb6 (#D0941 eval の引数・変数代入の対応) の時点で既にあった。どう 9371 やら e9ba343f (#D0744 a=[TAB] が a=a=b になる問題に対する対処) で最初に導入 9372 された様だ。この時点でのコードは以下の形をしている。 9373 9374 if [[ $source != argument ]]; then 9375 local sub=${text:wbeg:index-wbeg} 9376 if [[ $sub == *[=:]* ]]; then 9377 sub=${sub##*[=:]} 9378 ble-syntax/completion-context/.add "$source" $((index-${#sub})) 9379 fi 9380 fi 9381 9382 この時は source は配列ではなかった。つまり、$source != argument は実際に 9383 source に argument が含まれていないという事の確認になっていたのだった。後の 9384 変更で source が配列になった時にこの条件がそのまま放置されたのは恐らくバグ 9385 である。 9386 9387 [修正方法] 9388 9389 a "virtual starting point" 的な物を導入してそれに基づいて補完文脈の優先順位 9390 を決定する。 9391 9392 b rhs の補完開始点は飽くまで単語の先頭にして、しかし補完を実際に行う時に = 9393 以降について候補を生成する様に調整する。この時、source:file 等を内部から 9394 呼び出しているが、この source:file に中途半端な位置から補完を開始する仕組 9395 みを取り付ける? と思ったが、COMPV, COMPS 等既に計算済みの物をちゃんと正確 9396 に切り出せる事を保証しなければならないなど、暗黙の仮定を色々持ち込む事に 9397 なり余りすっきりしない。 9398 9399 c 或いはこう言った物は argument の側で全て処理するべきなのではないか? 9400 9401 実際に rhs をなくしてもちゃんと動いている様に見える。うーん。だとしたら完 9402 全に削除してしまっても良い? これについてはやはり導入経緯を確認する必要が 9403 ある→うーん。どうも現在 argument と rhs の両方が生成されているのはバグの 9404 気がする。バグと判断して良い。そもそも argument の側でもちゃんと同様の = 9405 生成を実行している。 9406 9407 どうも rhs と argument の両方が生成されているのは歴史的に見て元々意図した物 9408 ではなかった様に思われる。従って、"c" の様に argument を生成している時には 9409 rhs は生成しない様に修正してしまって良い。 9410 9411 * complete (requote): --prefix='a b c d e' の様に prefix 部分は requote から除外 [#D1786] 9412 Ref #D1787 9413 9414 全体を quote し直す時にオプション的な部分・もしくは変数代入的な部分は除外す 9415 る様にする。例えば --option=hello\ 1\ 2\ 3 が '--option=hello 1 2 3' になる 9416 のではなく、--option='hello 1 2 3' になって欲しいという事。 9417 9418 * edit: 古い terminator で表示が乱れる (reported by dongxi8) [#D1785] 9419 https://github.com/ohmybash/oh-my-bash/issues/314 9420 9421 要するに Terminal 0.98 が使っている vte では DECSCUSR に対応していない。そ 9422 れにも拘らず TERM=xterm にしているので _ble_term_Ss に値が設定されている。 9423 9424 https://bugzilla.gnome.org/show_bug.cgi?id=720821#c33 9425 此処によると DECSCUSR は vte 0.40 で導入された様だ。 9426 9427 古い version の vte で DECSCUSR を無効化するコードを追加する事にする。所で、 9428 vte version と値の関係がどうなっているのか調べる必要がある。うーん。vte 9429 0.28.2 という事なのだろうか。。。そういう気がする。実際に一番最近の 9430 Terminator で vte:66xx になっていて、GitLab 上の最新版は 0.67.x なので、や 9431 はり vte 0.28.2 という事なのだろうという気がする。vte の番号を使って判定す 9432 る事にする。 9433 9434 2022-02-23 9435 9436 * edit: bash-it から detach するとプロンプトが壊れた状態になる [#D1784] 9437 Ref #D1772 9438 9439 # #D1772 に関係はしているが直接の原因ではない。元々 PS1 が退避された状態で 9440 # ble-detach になってしまうのだったが、(1) PROMPT_COMMAND は待避していなかっ 9441 # た (2) PS1 を "待避" した後も通常の場合は PS1 の元の値をそのままにしてい 9442 # たという二重の理由で問題が起こらなかったのである。#D1772 によって両方の振 9443 # る舞いを壊した為に問題として発現した。 9444 9445 oh-my-bash から抜けても同じ状態になる。nix-shell の場合には大丈夫。 9446 9447 どうやら PROMPT_COMMAND に何か設定されているとこうなる様だ。何故 9448 PROMPT_COMMAND があるかどうかで変わるのだろうか。因みに 9449 PROMPT_COMMAND も退避されたままになっている。 9450 9451 うーん。何故か ble-detach/message の中から ble/textarea#render が呼び出され 9452 ている。この時に PS1 adjust が走ってそのままになっている。そもそも何故 9453 ble-detach/message の中で render が呼び出されているのか? うーん。恐らく 9454 stty の設定の為に Bash に制御を戻しても Bash が prompt を表示してくれないの 9455 が問題。その為に ble-detach/mesasge を介して態々プロンプトを描画しているの 9456 である。 9457 9458 a eval-PROMPT_COMMAND の前後の PS1 adjust/restore は attached の時にだけ実 9459 行する? と思ってこれで実装したが…。 9460 9461 そもそも textarea#render を detached 状態で呼び出して問題は発生しないのか。 9462 特に、既に様々の bash option 等を設定した状態で正しく ble-detach/message 9463 を呼び出す事ができるのかすら非自明である。 9464 9465 と思ったが ble-detach/impl は実は restore option までは未だ実行していない 9466 状態の様だ。単に detached state に移行するだけである。 9467 9468 b 或いは ble-detach/message を表示してから ble-detach/impl を実行するべきな 9469 のではないか。 9470 9471 うーん。ble-detach/impl の中で何か出力されたりする可能性はあるのだろうか。 9472 エラーメッセージなど。確認すると、呼び出されているのは以下の 3 項目である。 9473 9474 blehook/invoke DETACH 9475 ble-edit/detach 9476 ble/decode/detach 9477 9478 後ろの2つはともかくとして最初の1つでユーザーが何かメッセージを出力したい 9479 という事があるかもしれない。うーん。という事を考えるとやはり後で 9480 ble-detach/message を実行するべきなのだろうか。 9481 9482 やはり a の方針で修正する事にした。restore-PS1 は本来 ble-edit/detach から 9483 呼び出される物であって、其処で管理している状態は _ble_edit_attached 変数に 9484 格納されているので、この変数の値に基づいて PROMPT_ATTACH の周りで 9485 adjust/restore を行う事にした。 9486 9487 修正した。PROMPT_ATTACH を設定した状態でも問題が生じない事を確認した。また 9488 bash-it, oh-my-bash による動作確認もした。 9489 9490 * [棄却] bashrc: .bashrc.bash-it-minimal から実行するとエラーメッセージが出る [#D1783] 9491 9492 PROMPT_COMMAND に ';:' という文字列が設定されて PROMPT_COMMAND を実行する度 9493 にエラーが発生する。或いは、ble.sh 自体の prompt-attach に失敗している? 9494 9495 →と思ったらこれは単に .bashrc.bash-it-minimal の問題だった。このファイルを 9496 作成した当時は --attach=prompt の時、必ず PROMPT_COMMAND に文字列が設定され 9497 るという事を想定してよかった。現在は bash-5.1 以上では配列を用いて第2要素以 9498 降に設定するので、単に ';:' という文字列を付加するとエラーが発生するのだっ 9499 た。 9500 9501 2022-02-20 9502 9503 * edit: work around exit called from EXIT trap (reported by SuperSandro2000) [#D1782] 9504 https://github.com/akinomyoga/ble.sh/issues/179#issuecomment-1046122787 9505 9506 nix-shell の内部で exit を実行すると2回 [ble: exit] が表示される。これは 9507 nix-shell が設定する EXIT trap の中で再度 exit が呼び出される為である。 9508 ble.sh は独自に trap を処理しているし、また blehook EXIT も実行したいので、 9509 勝手に EXIT の中から本当に exit されると困る。なので、trap handler 実行中に 9510 ble/builtin/exit が呼び出された時には DEBUG trap を設定して、trap の呼び出 9511 し元まで制御を戻して続きの処理を実行することにする。呼び出し元まで戻った時 9512 に exit が trap handler の中で呼び出されたという事を記録しておいて、trap 9513 handler の処理の終わりに元々呼ばれた exit を呼び出し直す。 9514 9515 * exit を trap handler の中で実行した時にはそのまま終了するのではなくて、 9516 trap の処理が完了するまで待ってから終了するべきなのではないか → その様に 9517 実装した。既存の TRAPDEBUG の枠組みにコードを追加して実現した。 9518 9519 x fixed: exit 1 2 の様に余分な引数を指定した時、exit の準備をして [ble: 9520 exit] まで表示した後に exit: too many arguments のエラーが発生して exit 9521 がキャンセルされる。事前に引数の問題はチェックするべきである。 9522 9523 取り敢えず実装して 3.0, 3.2, 5.0 で動作確認した。期待通りに動いている。以下 9524 のコマンドなどを使ってちゃんと全ての EXIT handler が実行される事を確認した。 9525 9526 $ trap 'exit 5' EXIT; exit 9527 $ trap 'echo trap EXIT' EXIT; f1() { echo "$FUNCNAME $*"; exit "$1"; }; blehook EXIT+='f1 2 hello' EXIT+='f1 3 world';exit 9528 9529 ? 関係ないが jobs がある時にユーザーが exit をキャンセルした時、後続の処理 9530 が実行されるのは問題ではないか? これに対しても何らかの対処が必要になるの 9531 ではないか? 9532 9533 ? もし現在の TRAPDEBUG の枠組みが信用できるのであれば try/catch の枠組みを 9534 整備しても良いのかもしれないという気がする。その方が見通しも良いのでは。 9535 然し同じ commit でやるのは大げさな気がする。 9536 9537 上記の exit キャンセルの際の振る舞いに関してはその枠組が整ってから対応す 9538 るのが良い気がする。 9539 9540 →上の2つは別項目で処理する事にした。 9541 9542 x bash-5.2 以降で EXIT trap の stdout が /dev/null になっている。これはどう 9543 したら良いのだろうか。うーん。EXIT trap の時だけ stdout/stdin を繋ぎ直す 9544 のが良いだろうか。 9545 9546 調べてみた所 bash-5.2 以降では exit も EXIT handler も現在の関数の内部で 9547 行われる様だ。これは bash-5.1 までの top-level で実行されていたときと振る 9548 舞いが異なる。と思ったが、bash-4.4..5.1 の振る舞いが変だっただけの様だ。 9549 9550 うーん。builtin exit を呼び出す時の redirection を削除するか? と思ったが、 9551 それだとやはり余分なエラーメッセージが出るのが心配である。という事を考え 9552 ると、元々の stdout/stdin を何処かに記録しておくべきなのだろうという気が 9553 する。 9554 9555 2022-02-20 exit を DEBUG return で再現しようとしても DEBUG trap の対象であ 9556 る "現在のコマンド" は必ず実行されてその後で return/continue 等の効果が現れ 9557 る。なので blehook 内での exit は意図した動作をしない。 9558 9559 % blehook の中で exit をしても trap の実行が其処で終了しない。continue が実 9560 % 行されている筈なのに効いていないのは何故だろうか。うーん。eval の中から 9561 % continue を実行しても効かないのだろうか。 9562 % →それとも bash の特定の version を使っている事によるバグだろうかと思って 9563 % 振る舞いを確認したが、4.0..dev まで全て同じ振る舞いである 9564 9565 →うーん。振る舞いを調べて分かったのは、DEBUG trap が呼び出された対象のコマ 9566 ンドは結局何れにしても実行される様だという事。例えば continue を trap 内部 9567 で実行すると、確かにその場で continue によって制御が変更され、trap 内の続き 9568 の処理も実行されない。そしてtrap の外側にあるループを抜ける。然し、その前に 9569 DEBUG trap の対象であるコマンドはちゃんと実行される様だという事。 9570 9571 ? このコマンド実行をキャンセルする方法はないのだろうか。extdebug が設定され 9572 ていれば trap の戻り値によって振る舞いが変わるらしい。特に 2 を返せばその 9573 場で return を実行する事ができる。然し、continue をその場で実行する方法は 9574 不明である。continue が成功すれば戻り値は 0 になるので DEBUG 対象のコマン 9575 ドは結局実行される。逆にそれを阻止する為に戻り値を 0 以外にしようとすると 9576 continue を失敗させるしかなく、それだと次のループに移る事ができない。或い 9577 は BASH_COMMAND を書き換えたら実行するコマンドを書き換える事ができると言っ 9578 た事はないのだろうか。 9579 9580 実際に extdebug を設定して試しても見たが、マニュアルから予想される通り、 9581 continue が成功すればコマンドも実行するし、コマンドの実行をキャンセルする 9582 には continue を実行する訳には行かない。continue 直前の終了ステータスを変 9583 更しても何の効果もなかった。つまり、continue 自体の戻り値が使われる。 9584 9585 他に次のコマンドを無効にする手法はないのか? というか次のコマンドを無効に 9586 したとしても更にまた次のコマンドが実行されるというのだと際限がない。なの 9587 で、やはり extdebug を一時的に設定して 2 を返す事によって実行を中断させる 9588 しかないのだろうか。 9589 9590 * extdebug を一瞬有効にして return (終了ステータス 2) でトップレベルまで戻 9591 るしかない気がする。 9592 9593 ? extdebug は trap の中で無効化した場合でもその trap に対して失効するのだ 9594 ろうか。これについては振る舞いを確認する必要がある。→やはり trap の中 9595 で shopt -u extdebug すると即座に extdebug の動作はしなくなる様だ。ちゃ 9596 んとどの bash の version でも同様である事を確認した。 9597 9598 だとするとどの時点で extdebug を off にするのかについて確認が必要になる。 9599 然し取り敢えずは sandbox の中で実行しているのであればその呼出元で解除す 9600 る様にすれば良い。※という事は、sandbox の中では未だ DEBUG trap は 9601 clear はしないという事になる。 9602 9603 うーん。取り敢えず実装した。動いている。というかそもそも元々 continue を 9604 hook の中で実行する事を許していたのが変な気もする。或いは、continue 及び 9605 return を使って他の hook の処理に干渉したりできるというのも一つの機能だっ 9606 たかもしれないが、それならそれで別の枠組みを提供するべきの気もする。或い 9607 は、もし return continue を使うとしても trap sandbox の様に終了の仕方を検 9608 出して制御を決めるのが良いのだろうという気がする。 9609 9610 現在は現状のままで良い気がしている。 9611 9612 2022-02-19 9613 9614 * 2022-01-20 \C-x\C-v で bash-completion や terminal ID 等の情報も出力する [#D1781] 9615 9616 bash-completion や oh-my-bash の version と terminal ID について C-xC-v で 9617 出力したい。 9618 9619 * それを issue 報告に貼り付ける様にお願いする。 9620 9621 * terminal ID / version をちゃんと検出する様にする。DA2R も一緒に出力するべ 9622 き。 9623 9624 * bash-it には version 等は存在しないのだろうか。うーん。だからといっていき 9625 なり要求するのも違う気がする。 9626 9627 2022-02-19 取り敢えず実装した。基本的には過去に ble.sh に対して問題を起こし 9628 た物を検出して表示する事にするのが良い。 9629 9630 他の候補として oh-my-bash, bash-it, sbp, bash-preexec, starship 等がある。 9631 全てを検出して表示するのは変な気もする。oh-my-bash, bash-it については現在 9632 の theme (及び有効化しているモジュール) も表示すると良いのだろうという気が 9633 する。oh-my-bash については古い物だと version が存在していない。 9634 9635 * done: bash-preexec は是非検出するべきである。 9636 9637 * done: oh-my-bash の検出は upgrade_oh_my_bash 等を使うのが良い様に思われる。 9638 9639 うーん。個別の設定を ble.sh 本体に入れるのも変なので contrib に含めようと思っ 9640 たが、然し、それはそれでどういうファイル名にしたら良いのかが分からない。こ 9641 れはユーザーが新しく設定を追加するという形の物ではなくて、逆に ble.sh から 9642 blesh-contrib に依存するという形になるので取り扱いが難しい。やはり取り敢え 9643 ずは ble.sh 本体に含めておくのが良いのだろうか。或いは init-*.sh の様に補助 9644 スクリプトとして保持するのが良いのかもしれない。うーん。 9645 9646 →取り敢えずは ble.sh 本体に埋め込む事にする。肥大化してきたら 9647 blesh-contrib に新しくこう言った振る舞いの制御の為のディレクトリでも作って 9648 其処に登録する事にする。 9649 9650 * done: starship 9651 * done: bash-it 9652 * done: sbp 9653 * git: gitstatus 9654 9655 取り敢えず思いつく物は全て登録したのでOK。 9656 9657 2022-02-19 9658 9659 * trap: 初期化時に既存の trap がある時にエラーメッセージが出る (reported by SuperSandro2000) [#D1780] 9660 https://github.com/akinomyoga/ble.sh/issues/179 9661 9662 初期化時に以下のメッセージが出る。 9663 9664 $ nix-shell -p hello 9665 bash: ble-edit/exec/save-BASH_REMATCH: No such file or directory 9666 bash: ble-edit/exec/restore-BASH_REMATCH: No such file or directory 9667 9668 これは一番最近の commit で起こった事だった。新しく既存の trap を保持する様 9669 に修正したが、その時に既存の trap は 9670 9671 * そもそも trap の内部で使うのだから {save,restore}-BASH_REMATCH は移動するべきでは。 9672 9673 →ble.pp に移動した。また同時に source ble.sh 直前の BASH_REMATCH を保持する様に修正した。 9674 9675 * reject: ble/builtin/trap を実際に呼び出す必要はなくて単に値を代入すれば良 9676 いのではないか? その他にしなければならない操作などがあるだろうか。確認す 9677 る。と、思ったが解析するのも面倒である。という事を考えれば、やはりそのま 9678 ま実行する方が良いのではないか。一応 eval して配列に代入すればその3番目の 9679 単語として trap_string を取得する事はできる。 9680 9681 うーん。やはり {save,restore}-BASH_REMATCH さえ移動すれば今の実装で良い気 9682 がする。下手に自前で実装するよりも既にある実装を使った方が (効率は悪いか 9683 もしれないが) コードの管理という点では良い。また、この部分は到底ボトルネッ 9684 クではないので速度を重視する必要も全く無い。 9685 9686 * ble.pp でも BASH_REMATCH を保持する様に修正するべきでは。 9687 9688 [動作確認] 9689 9690 x fixed: source ble.sh の前後で BASH_REMATCH が保持される事を確認する。 9691 9692 と思ったら保持されていない。どうやら restore-BASH_REMATCH の数がバランス 9693 していない様だ。元々 BASH_REMATCH の復元にはチェックが入っていなかった。 9694 という事は、これは意図的に重複して retore-BASH_REMATCH を呼び出す様になっ 9695 ていたということではないのか。gexec での使い方について改めて確認する。 9696 9697 うーん。別に余分に実行しているという事もない。単に ble-attach で adjust 9698 し忘れているのが原因に思われる。 9699 9700 →ble-attach に追加した。更に {adjust,restore}-bash-options と同じ箇所で 9701 ちゃんと呼び出す様に全体をチェックして追加した。 9702 9703 →また _ble_bash_BASH_REMATCH_level が負になっていたので、負にならない様 9704 にチェックを追加する。 9705 9706 2022-02-18 9707 9708 * command-help: 関数の help として関数が定義されたファイルを表示する [#D1779] 9709 9710 関数の定義位置を DEBUG trap 等を使って抽出する事が可能なのではないか? 9711 9712 これは bash_completion の debug の時にも便利である。というか、 9713 bash_completion の version を表示するのにも使える。 9714 9715 と思ったら shopt -s extdebug; declare -F 関数名 で普通に取得できるのだとい 9716 う事が判明した。 9717 https://www.cyberciti.biz/faq/how-to-find-bash-shell-function-source-code-on-linuxunix/ 9718 9719 2022-02-17 9720 9721 * main, edit: 起動時に無駄に PROMPT_COMMAND が実行されるのを防げないか [#D1778] 9722 9723 PS1 に含まれるコマンド置換も同様である。画面サイズが変わる等しない限りは再 9724 計算する必要はない筈である。 9725 9726 今試してみたがそれほど無駄に実行している訳でもない様に思われる。 9727 9728 * 但し、_ble_history_count が初期化される前と初期化された後で 9729 PROMPT_COMMAND が再計算されていたのは修正する事にした。これで恐らく起動時 9730 刻も短くなったのではないかと思われる。これで1回実行が減少した。 9731 9732 * 実は #D1772 の時点で既に1回実行を減らしている筈である。PROMPT_COMMAND を 9733 待避した事によって減っていると期待する。しかし本当にこれで減ったのだろう 9734 か。怪しい → 試して見た所 manual attach の時に回数を一回減らす事ができて 9735 いると判明した。 9736 9737 これで合計で4回実行されていた #D1772 の状況を再現できた。更に減らす事は可能 9738 だろうか。現在 prompt-attach を使っているが、ble-attach の時にはもっと減っ 9739 ても良いのではないか? → 確認してみると manual attach の時には 9740 _ble_history_count が bashrc の中で 1 で、その後で実際の数に増えるという事 9741 の様である。 9742 9743 * うーん。そもそも PROMPT_COMMAND の決定に _ble_history_count が影響を与え 9744 るのだろうか。というのは疑問である。実は PROMPT_COMMAND に関しては 9745 _ble_history_count に関係なく version を決めて良いのではないか? 9746 9747 →その様に変更する事にした。これで manual attach ならば唯1回の 9748 PROMPT_COMMAND の実行になった。 9749 9750 一方で PS1 の評価に関しては history count が影響を与えるので 9751 _ble_history_count が変化したらちゃんと再評価しなければならない。これが二 9752 重に評価されるのは仕方がないと諦める事にする。 9753 9754 * prompt attach の場合には依然として二重に PROMPT_COMMAND が実行されている。 9755 うーん。PROMPT_COMMAND が書き換えられて直接削除できない場合は仕方がないと 9756 して、内部で実行している場合には呼び出しを省略できないのか。と思ったが、 9757 PROMPT_COMMAND 配列の時には結局 bash は全てを実行するし、或いは、内部で保 9758 持している物についてはその場で実行しておかないと bash-preexec.sh の様に内 9759 部で PROMPT_COMMAND を書き換える様な物に対して矛盾のない動作を提供する事 9760 ができない。或いはもっと注意深く考察すれば何かできるのかもしれないが。 9761 9762 或いは逆に ble-attach の中で実行している PROMPT_ATTACH の方を省略させる? 9763 と思ったが、 9764 9765 x その場合 PROMPT_COMMAND 配列でより後にある PROMPT_COMMAND の実行結果が 9766 反映されない事になるし、ble-attach の処理が終わった後に続きで実行される 9767 PROMPT_COMMAND を阻止する事は結局できない。 9768 9769 とは言いつつも scalar PROMPT_COMMAND (他によって修正されていない) または 9770 "配列 PROMPT_COMMAND かつ最終要素" の場合には、続きで別の処理が走らないと 9771 いう事は保証できるので、ble-attach の内部で走る PROMPT_ATTACH は省略でき 9772 る。 9773 9774 2022-02-19 うーん。bash-it のプロンプトが prompt attach で初期化されなくなっ 9775 た。どうやら bash-preexec precmd 経由で bash-it は設定を行っている様で、 9776 bash-preexec が ble.sh によって置き換えられた事によって precmd が実行されな 9777 くなっているのが原因の様だ。うーん。precmd は実行しておくべきの気がしてきた。 9778 →取り敢えず PRECMD を呼び出す様にしたら期待通りに動く様になった。 9779 9780 * 2020-09-01 trap: ble.sh を unload する時に復元する仕組みがあっても良いのではないか [#D1777] 9781 #D1775 と同時に対応した。 9782 9783 * 2020-09-01 desolved: trap: ble.sh で上書きする時に元々存在していた trap はどうなっていたか [#D1776] 9784 Ref #D1775 9785 9786 * util: DEBUG trap 以外についても元からあった trap を拾う様にしたい [#D1775] 9787 Ref #D1772 9788 9789 RETURN と ERR 以外については中から普通に trap を見ることができる筈なので、 9790 そのまま中から値を抽出するというので良い。現在使用しているのは EXIT, WINCH, 9791 INT である。他に bash3 等で USR1 も使っていた筈。 9792 9793 実際に trap を設定しているのは ble/builtin/trap/install-hook の一箇所のみで 9794 ある。ここで trap を読み取って ble/builtin/trap の枠組みで再設定すれば良い。 9795 対応した。 9796 9797 * bash-3.0 でコマンドを実行するとプロンプトの前に変な文字列 '' が出力される [#D1774] 9798 9799 うーん。家に帰ったら再現しなくなった。と思ったら再現の仕方が変化した。C-c 9800 でモードを変更すると '''' という無駄な文字列が表示される。これは一体何処か 9801 ら出てきている物だろうか。 9802 9803 ようやく突き止めた。_ble_term_Ss が余分な引用符で囲まれている。然し何故だろ 9804 うか。調べると cache には含まれていない。だとすれば、blerc かもしくは内部の 9805 端末判定である。 9806 9807 belrc を読み込まない様にしたら表示はされなくなったが、それは単にカーソルの 9808 設定をしていないのでカーソル切り替えシーケンスが出力されていないだけだった。 9809 実際に _ble_term_Ss の値を確認したら引用符が混入していた。という事は端末判 9810 定直後の代入の際に引用符が混入している事になる。 9811 9812 分かった。 bash-3.0 には "${...#$'...'}" が '...' に展開されてしまうバグが 9813 ある様だ。これはチェックの対称に追加する事にする。 9814 9815 ? そもそも他の "${pat#"..."}" 等も大丈夫なのだろうか? 動作を確認する必要が 9816 ある。以下は一応ちゃんと期待通りに動作する様である。 9817 9818 $ v=1 9819 $ echo ${v//"1"/hello} 9820 $ echo "${v//"1"/hello}" 9821 $ echo "<${v#"1"}>" 9822 $ echo "<${v#'1'}>" 9823 $ echo "<${v#1}>" 9824 $ echo "<${v#"1"}>" 9825 $ echo "<${v/#"1"/hello}>" 9826 9827 そんなに気にしなくて良い気がしてきた。 9828 9829 2022-02-15 9830 9831 * 2022-01-23 [解消] 元々存在した DEBUG trap を保持する [#D1773] 9832 Ref #D1772 9833 9834 * exec: 既存の DEBUG trap を保持する (motivated by ammarooo) [#D1772] 9835 https://github.com/akinomyoga/ble.sh/issues/176 9836 9837 * 然し、上記で報告されている物を修正するには PROMPT_COMMAND の実行時にも 9838 DEBUG trap を有効にしなければならない。これは ble.sh の想定していない事で 9839 ある。うーん。面倒であるが有効化する事にした方が良いだろうか。と、思った 9840 が局所的に有効化して後で削除する事はできただろうか。同じ関数 scope 内で削 9841 除すれば良いのだったか。何れにしても既存の DEBUG trap は捕まえる事にする。 9842 9843 速度を計測して問題なければ PROMPT_COMMAND 実行時に DEBUG trap を有効にす 9844 る事にする。その時には ble.sh の内部で直接実行している時にはユーザー trap 9845 は無効になる様に調整する。 9846 9847 時間を計測して無視できないという判断の場合には bleopt で有効化できる様に 9848 する。 9849 9850 →attach 時の既存 trap かそれとも ble.sh load 時の trap か。load した時には 9851 既に trap は置き換えられているので、それ以降 attach 迄に設定された物に関し 9852 ては気にしなくて良い。というか単に無視するしかない。なので、ble.sh load 時 9853 に設定されている trap を復元する方向で考える。 9854 9855 * ble-reload した時にもちゃんと上書きして塗り潰さない様に注意する。一つの手 9856 は trap を復元する事の気がする。これは ble/base/unload で実行すれば良い。 9857 9858 取り敢えずロード時の DEBUG trap を記録する事にする。他にもロード時の INT 等 9859 を保持する様にしたい。 9860 9861 | うーん。trap -p DEBUG を実行すると最初のコマンド実行まではちゃんと存在して 9862 | いる。然し、コマンドを実行した時点で消滅してしまう。 9863 | 9864 | という事を考えると、何処かの時点で消えているという事になる筈だが、実際に 9865 | trap DEBUG を上書きする瞬間で trap -p DEBUG を実行しても何も表示されていな 9866 | い。或いは関数の中からだと外側の trap -p を読み取る事ができないという事なの 9867 | だろうか→試してみるとサブシェルの中からだと見えないが本体のシェルからは例 9868 | え関数内であったとしても読み出す事ができている。 9869 | 9870 | * うーん。何処で trap が削除されているかは分かった。一方で ble/util/assign 9871 | の中だと DEBUG の trap string は正確に読み取れていないという事が判明した。 9872 | 9873 | 何故だろう。eval があると DEBUG が伝播しないという事なのだろうか。 9874 | 9875 | ? ble/util/assign で DEBUG trap の中身を取得できない理由について調べる。うー 9876 | ん。 9877 9878 色々試したがどうやらそもそも関数の中から trap DEBUG が取れるというのは幻だっ 9879 た様だ。一番外側で設定されている DEBUG trap を読み取る場合、全ての呼び出し 9880 階層の関数に -t 属性が予めついている必要がある (呼び出しの最中に -t 属性を 9881 付加しても無駄である。これは set -o functrace についても同様である)。 9882 9883 これが意味する所は何だろうか。うーん。 9884 9885 * ble.sh が最初に DEBUG trap を上書きしようとする時までに外側の DEBUG trap 9886 を読み取る必要がある。source ble.sh した瞬間には、ble.sh の一番外のレベル 9887 であれば ble.sh が source された文脈での trap DEBUG を取得できるかもしれ 9888 ないが、ble.sh 自体が関数内で source された場合には読み取る事ができない。 9889 9890 a reject: という事を考えると、やはり一番最初に DEBUG trap を設定しようとす 9891 る機会に読み取るのが良い気がする。基本的に DEBUG trap を設定するのはコマ 9892 ンド実行の直前であり、コマンド実行は一番外側の文脈で行われるからである。 9893 (然し、将来的に line-editor のプロセスとコマンドを実行するプロセスを分離 9894 した時にどうしたら良いのかについては不明である。というか分離した時には 9895 trap 関連は全て再設計する必要があるので今ここで気にしても仕方がない気がす 9896 る)。 9897 9898 と思って改めて調べてみたが、builtin trap DEBUG が初めて設定されるのは、ユー 9899 ザーが ble/builtin/trap DEBUG を呼び出した時かまたは C-c を押した時である。 9900 従って必ずしも通過するとは限らない。問題点は実際に DEBUG trap が設定され 9901 ているかどうかに拘らず .epilogue 及び .end で trap -- - DEBUG trap を除去 9902 しようとしている事である (但し、.epilogue / .end で実行している trap - 9903 DEBUG は結局何の効果もない)。 9904 9905 a1 そう考えると例えば TRAPDEBUG/enter に関しては毎回コマンドが実行される 9906 前に呼び出されるので、初回にこれが実行された時点で、この中で trap - 9907 DEBUG を読み出すという事が考えられる。 9908 9909 a2 でもそうなって来るとそもそもコマンド実行時に DEBUG trap を読み取る必要 9910 すらない。初回の ble-decode/.hook の直後か直前に読み出してしまえば良い 9911 のではないか? 9912 9913 と思ったがそもそもコマンド実行直前である必要すらない。 9914 9915 b reject: やはり ble.sh がグローバルで読み出された時にはその時点で既存の 9916 trap を読み取るのが安全である。もしグローバルでなかったら代替手段に頼る。 9917 9918 実際に実装してみたが動かない。試しに ble.sh の先頭に以下を記述してみた所、 9919 実は source の中ですら DEBUG は伝播しないのだという事が判明した。 9920 9921 | echo ble.sh:1 9922 | builtin trap -p DEBUG 9923 | echo ble.sh:2 9924 9925 駄目だ。この方法はそもそも使えなかったのである。改めて man bash を確認し 9926 てみる。set -T の説明を読むと、これが設定されていなければ基本的には、関数 9927 もコマンド置換もサブシェルも DEBUG を継承しないと書かれている。然し 9928 source に関しては述べられていない。何故だろう。実際に改めて小さなスクリプ 9929 トを作って試してみると、やはり source の中では DEBUG trap は見えない。 9930 functrace を設定すると source の中でも見える様になる。functrace は man に 9931 は書かれていないけれども source についても DEBUG が継承される様になる。 9932 9933 うーん。ble.sh の外側で set -T を実行させる様な方法は存在しないし、やはり 9934 source ble.sh の中から元々の trap DEBUG を読み取るのは困難である。 9935 9936 結局一旦は実装した以下の変更はなかった事にする。 9937 9938 | diff --git a/src/edit.sh b/src/edit.sh 9939 | index c32bed0..29c96c4 100644 9940 | --- a/src/edit.sh 9941 | +++ b/src/edit.sh 9942 | @@ -5769,6 +5772,17 @@ function ble/builtin/trap:DEBUG { 9943 | ble-edit/exec:gexec/.TRAPDEBUG/trap 9944 | fi 9945 | } 9946 | +function ble/builtin/trap:DEBUG/.initialize { 9947 | + builtin unset -f "$FUNCNAME" 9948 | + if ((!_ble_bash_loaded_in_function)); then 9949 | + local tmp=$_ble_base_run/$$.trap.DEBUG ret 9950 | + builtin trap -p DEBUG >| "$tmp" 9951 | + source "$tmp" # ble/builtin/trap に処理させる 9952 | + ble/util/put '' >| "$tmp" 9953 | + fi 9954 | +} 9955 | +declare -ft ble/builtin/trap:DEBUG/.initialize 9956 | +ble/builtin/trap:DEBUG/.initialize 9957 | 9958 | function ble-edit/exec:gexec/.TRAPINT { 9959 | local sig=130 9960 9961 或いは functrace を on にしてもらうしかないのだ。然し常に functrace を on 9962 にする訳にも行かないし、だからと言って勝手に ble.sh の中から functrace を 9963 off にすると本当に functrace を on にしたい場合に使えなくなる。そうすると、 9964 ble.sh を呼び出す前後で set -T set +T を実行してもらう事になるが、其処ま 9965 でするぐらいであれば、普通に先に ble.sh を先に source してもらうべきであ 9966 る。また、一回でもキー入力をすれば治るのだが最初の一回だけは我慢してもら 9967 うしかないと諦めるのである。 9968 9969 functrace を on にしてもらう様にお願いするのはおかしいとしても、ユーザー 9970 が偶 functrace を on にしていたらそれを利用するべきなのでは? そういう意味 9971 でやはり上のコードは一応含めて置いて良いのではないか? 9972 9973 c 最初のキー入力の直後に解決するという手がある。 9974 9975 グローバルで実行する必要があるので _ble_decode_bind_hook に指定する必要が 9976 ある。然し、他の箇所からも同時に _ble_decode_bind_hook を実行しようとした 9977 時に問題になる。うーん。確認してみた所 _ble_decode_bind_hook に値を設定し 9978 ているのは現在一箇所だけである。なので今までは何も気にする必要はなかった。 9979 9980 c1 _ble_decode_bind_hook には追記式でコマンドを書いていく方式にする可能性。 9981 そして複数の箇所から書き込む事を許す。 9982 9983 c2 _ble_decode_bind_hook を現在書き込んでいる箇所 (gexec/.setup) で処理す 9984 る。 9985 9986 c3 reject: 或いは通常のコマンドとして最初に登録してしまう? と考えたがそう 9987 するとコマンドのカウントが余分に増えてしまうので駄目の気がする。 9988 9989 % 他にも C-x C-v 等、コマンド実行として取り扱っている物があるのではなかっ 9990 % たか。そういった物についてはコマンドのカウントが乱れない様になっている 9991 % のか? と思って確認したがこれらは実は gexec で実行してはいなかった。その 9992 % まま関数の中で実行していた。その時に必要に応じてシェル状態の保存・復元 9993 % をその場で実行して処理しているのだった。 9994 9995 上記 c2 の方法が現状で一番綺麗の気がする。今後、もっと様々な箇所から bind 9996 hook を設定したいという状況になったら c1 の様な方式にすれば良い。 9997 9998 % 取り敢えず、上記の b と c の方法を組み合わせる事にする。先ずは b から実装す 9999 % る事にする→と思ったら b は不可能な事が判明してしまった。 10000 10001 仕方がないので c の方針で実装する事にする。とにかく未だ DEBUG trap が存在し 10002 ていない時にそれをチェックするのが目的。 10003 10004 というか最初のキー入力の時にようやく DEBUG trap を読み取る事ができるという 10005 のが意味する事は…最初のプロンプトの表示の時点では DEBUG trap を正しく動作 10006 させるのは無理という事になるのでは。うーん。もしそうだとすれば報告を受けた 10007 場合に関しては、結局 PROMPT_COMMAND を実行させるしかないという事になる。 10008 10009 或いは、attach した時の DA2 等の返答の際に取得はできる。とは言いつつ DA2 の 10010 返答が戻ってくるまで PROMPT_COMMAND の実行を遅延させる訳にも行かない。とい 10011 う事を考えると、やはり最初の一回は必ず失敗するという事は認めてもらうしかな 10012 い。或いは、最初に ble.sh を source して貰ってそれから最後に attach すると 10013 いうのを徹底してもらうしかない。 10014 10015 * done: 取り敢えず c の方針で早く実装する。実装した。というか b の実装で用 10016 意した関数をそのまま呼び出せば良いのだった。 10017 10018 * done: PROMPT_COMMAND で TRAPDEBUG を有効にする。 10019 10020 * done: functrace も待避・復元オプションに含める。 10021 10022 追加した。これで特に問題が起こるとは思えない。DEBUG で余分に何か呼び出さ 10023 れるという事はあるかもしれない。 10024 10025 ? [保留] bash-4.4..dev まで tmpenv の builtin eval の中から見える値が変。と。これ 10026 は実は既に知っている問題なのではないか。 10027 10028 うーん。逆に bash-4.3 で問題が起こるという事は判明した。bash-4.4 以降では 10029 ちゃんと値が見える筈である。それにも拘らず実際の ble.sh の中では逆に 4.4 10030 以降で値が見えなくなっていた。これは一体どういう事だろうか。 10031 10032 →うーん。これはどうもまた別のバグの様だ。再現した。以下で再現させる事が 10033 できる。これは trap 関連でしか再現しないのだろうか。分からない。 10034 10035 | function print { echo "v=${v:-(not found)}"; } 10036 | function trapdebug { echo "$FUNCNAME:1:v=($v)"; } 10037 | builtin trap 'trapdebug' DEBUG 10038 | v=xxxx eval print 10039 | v=xxxx builtin eval print 10040 10041 と、思ったが、もしかすると DEBUG trap の中からは意図的に tmpenv が見えな 10042 い様になっているのかもしれない。然し、builtin eval の時と eval の時の振る 10043 舞いを比べるとやはり異なるのでこれは意やはり意図したものではない。 10044 10045 これは別項目にする事にする。今は取り敢えず Note だけ残して放置する事にす 10046 る。 10047 10048 [動作確認] 10049 10050 * C1 取り敢えず動作はしている。然し微妙な振る舞いが色々ある。 10051 10052 x C2 fixed: 何故か起動した時に点滅する様になってしまった。一旦表示がクリア 10053 されている? →これはコマンド実行をした時は bind/.tail をコマンド実行後に 10054 実行する為に bind/.tail を抑制するのが原因。今回 DEBUG initialize でも 10055 return 0 をする様に変更してしまったので、DEBUG initialize の時にも 10056 bind/.tail が省略されてしまってしかし DEBUG initialize の場合は自分で 10057 bind/.tail が呼び出されないので、bind/.tail が欠けて bash -x によるプロン 10058 プトの消去が発生して点滅していた。 10059 10060 DEBUG initialize だけの時は return 1 を返す事にした。 10061 10062 x C3 fixed: 後から ble.sh を source した場合、エラーメッセージが出る事も問 10063 題であるが、最初のコマンドの実行時間がシェル開始時刻からコマンド終了時刻 10064 までの時間になってしまっている。 10065 10066 ble.sh なしだと期待通りに時間を計測する事ができている。先に ble.sh を 10067 source した場合でも特に問題は起こっていない。 10068 10069 これは何故だろうか。先に trap を実行しているとどういう事になるかというと、 10070 bashrc の中で time_start されて timer が設定される事になるが最終的に 10071 PROMPT_COMMAND が呼び出されて timer は clear される事になる。然し、その後 10072 で様々の処理が走ってその過程で改めて timer が設定される? と思ったが何によっ 10073 て設定されるのかは謎である。ble-attach した段階で DEBUG は解除されている 10074 のではないのか。と思ったが、違う。実際に解除されていないのだ。それでは全 10075 然駄目だ。恐らく最初の ble-decode/.hook の瞬間に DEBUG trap が呼び出され 10076 て結果として時間にずれが生じているという事だろう。 10077 10078 というか、trap - DEBUG で解除すれば良いのではないか? 10079 →OK. これで治った。 10080 10081 x C4 fixed: 最初に ble.sh を source した場合でもエラーを検出している。これ 10082 はどういう事か。うーん。最初の PROMPT_COMMAND を実行する時点で未だ attach 10083 が完了していないから DEBUG trap の設定が省略されているという可能性? しか 10084 し、それだとエラーが画面ではなく vbell に出力されている理由が分からない。 10085 これは要するに bash が取り敢えず裏で実行した PS1 の評価によって引き起こさ 10086 れているのではないか。 10087 10088 と思ったが、bash が裏で PROMPT_COMMAND を実行するという事があるのだろう 10089 か…。あー。分かった。PS1 については待避しているが、PROMPT_COMMAND につい 10090 ては待避していないのである。 10091 10092 PROMPT_COMMAND が二重に実行されている問題は別枠で修正するべきの気がする。 10093 これは ble-0.3 にも適用する必要がある。と思って動作確認したが二重実行され 10094 るのは最初に呼び出した時だけなので内部で処理する事にする。これは軽微な差 10095 異なので 0.3 に適用する必要はない。 10096 10097 * PROMPT_COMMAND が ble.sh と bash で二重実行される事について 10098 10099 特に PROMPT_COMMAND を待避していた記憶はない。という事は PROMPT_COMMAND 10100 が裏で二重に実行されているのではないか。更に言うと、裏の PROMPT_COMMAND 10101 によって裏の PS1 が設定されてしまっているのではないか。 10102 10103 現状で実際にその様になってしまっているかどうかを確認する事にする。→確 10104 認してみたが別にそういう困った事にはなっていなかった。よく考えてみたら 10105 PROMPT_COMMAND はコマンドが実行された後に実行されるのであって、bash の 10106 枠組みの方でコマンドを実行していないのだから余分に呼び出される事はない 10107 のである。 10108 10109 但し、初回の PROMPT_COMMAND に限っては bash によって実行されるという事 10110 に留意しなければならない。PS1 を待避・復元している所で PROMPT_COMMAND 10111 も待避・復元すれば良いのではないだろうか。但し、初回だけで良い。否、 10112 ble-attach の時に何回 PROMPT_COMMAND が呼び出されるか分からないので、何 10113 回かは実行する必要があるだろうか。これは実際に試して何回実行されるか確 10114 認すれば良い。 10115 10116 確認した所4回呼び出されている。これは確かに呼び出し過ぎである。その内の 10117 1回は bash から直接呼び出されている。残り3回が何処から来ているかは確認 10118 する必要がある。一番最後の物は端末テスト後の再配置だろうと思われるが、 10119 再配置の時に改めて PROMPT_COMMAND を呼び出す必要もないだろうという気が 10120 する。 10121 10122 ? そんなに重い処理でなければ PS1 と一緒に毎回保存・復元すれば良いのでは? 10123 と思ったが、PROMPT_COMMAND 配列を保存・復元するのは面倒なのでやはり保存・ 10124 復元は最初だけにするのが良い様に思われる。 10125 10126 PROMPT_COMMAND 配列の場合には特に設定下側がどの key に対して設定した 10127 かを覚えているかもしれないので、key をずらしてしまうのは良くないので、 10128 特に key も一緒に記録する必要がある。 10129 10130 保存・復元は ble/util/declare-print-definitions PROMPT_COMMAND を用い 10131 る方法と各要素を一つずつ保存復元する方法の二通り考えられる。前者は 10132 fork を沢山するので重い。後者も要素が大量になってくると大変である。 10133 10134 うーん。取り敢えず各要素毎にコピーする事にする。 10135 10136 取り敢えず対応した。ちゃんと動く様になった。 10137 10138 * reject: 待避は bashrc の中から実行している時だけで充分なのではないか。 10139 10140 そんなに重い処理でもないし PS1 を毎回待避している事を思うと 10141 PROMPT_COMMAND を毎回待避しても対した処理にはならないので、気にしなくて 10142 も良いのではないか。 10143 10144 a 然し、bashrc の中から実行しているという事が分かるのであればその時にだ 10145 け待避するのは尤もな気がする。 10146 10147 一方でその様な方法が存在するかどうかはまた別である。以前その様な方法 10148 を思いついた様な気もするし、結局動かなかった様な気もする。思い出せな 10149 い。bash のソースコードを覗いて、何かの振る舞いで interactive / 10150 non-interactive で振る舞いの変わる物があってそれを巧妙に組み合わせれ 10151 ば判定可能なのではないかと思ったが、結局異なる振る舞いを再現させる事 10152 ができなくて諦めた気がする。 10153 10154 b もしくは attach 後の初回の PROMPT_COMMAND の評価の時だけ待避する? し 10155 かし、それだと複数回 attach もしくは reload を行った時に (そもそもそ 10156 の様な使い方は想定していないとは言え)、PROMPT_COMMAND が余分に実行さ 10157 れてしまう事になる。 10158 10159 更にコマンドラインから直接 ble-attach した時や prompt attach した時に 10160 は初回でも PROMPT_ATTACH を待避する必要もない。という事を考えると初回 10161 かどうかというのは本質ではない様に思われる。 10162 10163 c 或いはコマンドを既に一回でも実行していたら OK という考え方もある。こ 10164 れならば複数回 reload した時に PROMPT_COMMAND が重複して実行されると 10165 いうこともない。 10166 10167 一方でやはり初回には余計に PROMPT_COMMAND を待避する事になるが仕方の 10168 ない事なのかもしれない。 10169 10170 また条件によって待避したりしなかったりする場合、現在 PROMPT_COMMAND が 10171 設定されているかどうかを判定する方法が面倒になる。という事を考えると現 10172 状の様に常に PROMPT_COMMAND を待避する様にしておくのが無難の様な気がす 10173 る。或いは、退避はしなくて常にコピーだけはしておくという事にしても良い 10174 が、それだと結局コストは存在しているので中途半端な事をするよりは本当に 10175 待避した方が良い様に思われる。 10176 10177 取り敢えずは現状の様に常に待避する事にして、後で問題になる様であれば条 10178 件を考える事にする。そもそもコマンド実行の時にだけ待避は起こるのだから、 10179 滅多に実行しない操作だし処理のコストが問題になるという事は考えにくい。 10180 もし問題が起こるとすればもっと別の何かのエラーが起こった時の状況復帰に 10181 関係する物だろうと思われる。 10182 10183 ? C5 ok: PS1= とするのは bleopt_internal_suppress_output が設定されていない 10184 時だけになっているが、これも常に実行する様にした方が良いのでは。裏で毎回 10185 コマンド置換などが実行されている様な状態になっているのは無駄である。それ 10186 にもしユーザーが PS1= に何か破壊的な操作・副作用のある操作を実装していた 10187 場合やはり振る舞いが意図しない物になる気がする。なので PS1= を指定するべ 10188 き気がする。 10189 10190 と思って振る舞いを確認してみたがそもそも PS1 は余分に評価されてはいない。 10191 確か端末の状態に応じて Bash はプロンプトの評価を控えるのだった。そしてそ 10192 れに伴って PS1 の評価も実行していない? と思ったが、そもそもコマンドを実行 10193 していないのだからプロンプトの内容も変わらず、従って PS1 の中のコマンド置 10194 換を再評価する機会もないというだけの事の気がする。PROMPT_COMMAND が二重に 10195 実行されない事と同様の事である。 10196 10197 何れにしても PS1 を空にする理由も特にない気がするので PS1= を実行する。と 10198 思ったが、元々不意に ble.sh が落ちた時に不自然な振る舞いにならない為に 10199 PS1= を設定しているのだった。という事を考えるとやはりそのままにして置いた 10200 方が良い? と思ったが、現在中途半端な状態にあるという事が分かる様にした方 10201 が良い気もする。 10202 10203 a 例えば PS2 を代わりに設定する? 10204 10205 x と思ったが、PS2 は PS2 でコマンド置換を含んでいる可能性もあるし、そも 10206 そも異なる物なのでユーザーが意図的に何か PS2 に仕組んでいた時に変な事 10207 になる。 10208 10209 x というか、将来的に PS2 を編集時の行番号等に用いるなどした時に棲み分け 10210 が改めて必要になるのでやはり変な利用方法はしない方が良い。 10211 10212 b [press any key to continue] 等として変な状態にある事が分かる様にするの 10213 が良いのでは。 10214 10215 →具体的に問題を起こしてみてどうなるか試そうと思ったが再現できない。うー 10216 ん。配列の添字関係で実行が停止していた気がするが…。 10217 10218 echo ${_ble 10219 10220 等の中途半端なコマンド文字列で無理やり実行してもちゃんと元の状態に戻る 10221 事ができている。コマンド実行がその場で終了してしまう様な設定が存在した 10222 気がするがどの様にすれば良いのだろう。 10223 10224 * 例えば ${hello?world} などか → 問題なかった。 10225 * set -u だろうか → 問題なかった。 10226 * set -e だろうか → これはそもそもシェルを終了するので関係ない。 10227 * 算術式中の a[-1] だろうか → これも問題ない。 10228 10229 何処かに記録として残っていないだろうか。 10230 10231 * "for ((i=0;i<10;i++)); do sleep 1; done"<C-c> これだ 10232 10233 然し試してみたがこちらで指定した PS1 が反映される訳でもない。 10234 10235 ! 恐らく最初に PS1 を表示した時の計算結果がずっと残っているという事なの 10236 ! だろう。なので、実は中で PS1 を設定しようがどうしようが関係ないという 10237 ! 事。但し、bashrc で直接 attach する時に限ってはその時の PS1 に意味が 10238 ! ある。 10239 ! 10240 ! →と思って bashrc で直接 attach する場合についても試したがそれでも駄 10241 ! 目だった。よく考えたら bash が変な状態になった時にプロンプトを表示す 10242 ! るとして、その時の PS1 の値を使って表示するのだとしたら、コマンド実行 10243 ! 中に失敗したのだとしたらコマンド実行中の PS1 を使って表示するのだから、 10244 ! 待避した PS1 が使われる事はない。という事を考えると待避中の PS1 が使 10245 ! われる事はない様な気がする。 10246 10247 うーん。コマンド実行中の失敗の場合はコマンド実行中の PS1 が使われるので、 10248 待避中の PS1 の値に何を設定するかは関係ない。そもそも PS1 を待避する必 10249 要性があるのかどうかも何だか分からなくなって来た。 10250 10251 * ok: WINCH の時に問題になるのではないか: ble.sh では WINCH した時に、 10252 PROMPT_COMMAND で現在の端末幅に合わせた内容を計算している可能性を考えて、 10253 PROMPT_COMMAND を再度呼び出す事にしている。これで問題が生じることはないか? 10254 10255 →報告されたコードの場合には結局 PROMPT_COMMAND のコード自体に対して 10256 DEBUG trap が走る事によって問題が回避されているので、問題は起こらない筈。 10257 →実際に問題が起こらないという事を確かめた。 10258 10259 一方で PROMPT_COMMAND が余分に呼び出される事で他の問題が生じる可能性はあ 10260 るだろうか。うーん。そもそも PROMPT_COMMAND がコマンド実行後に1回だけしか 10261 呼び出されないという想定は bash のマニュアルにも書いていないし、意味を考 10262 えればプロンプトの再表示時に複数回呼び出されてもおかしくはない気がする。 10263 具体的にそういう動作に依存している枠組みが現れる迄は気にしない事にする。 10264 10265 ? C6 reject: 効率を考えたら実は TRAPDEBUG/enter の時には TRAPDEBUG ではなく 10266 て元のユーザーの trap を直接設定しておけば良いのでは? 10267 10268 現在の TRAPDEBUG の処理 (sandbox でのユーザートラップの実行を含め) は複雑 10269 で重いので直接実行できるのであればその方が良い気がする。 10270 10271 現在 TRAPDEBUG は ble.sh 的には INT の処理の為にしか使っていない。将来的 10272 にもっと別の事に使いたくなる可能性もあるが、取り敢えずは特別な処理は挟ま 10273 ないのだからユーザートラップを直接設定して良い気がする。 10274 10275 一方で TRAPDEBUG は ble.sh の処理自体に対する DEBUG trap を阻止するという 10276 目的もあった。うーん。そうは言っても gexec/.{restore,save}-lastarg 及び 10277 epilogue 等に対する DEBUG trap 程度であれば許しても良い気がする。その直後 10278 に builtin trap - DEBUG で解除しているので、gexec/.end 以降に対してユーザー 10279 の DEBUG trap が実行される事は結局ないと思われる。 10280 10281 .TRAPDEBUG/trap に於いて現在介入する必要がなければ介入しない様にする事にした。 10282 10283 x と思ったら報告者の設定で問題が起こる。やはり ble.sh 内部での処理に対し 10284 ては TRAPDEBUG が発生しない様に制御が必要なのだろうか。 10285 10286 うーん。PROMPT_COMMAND の実行の為の TRAPDEBUG に関しては DEBUG を 10287 filter する為に明示的に TRAPDEBUG で trap する事にした。 10288 10289 * というか単にユーザートラップを実行するだけなのであれば、単に postproc 10290 にユーザートラップをしかければ良いだけでは? その様に実装した。但し、本 10291 来は user trap がなければそもそも DEBUG trap も存在しない筈ではある。但 10292 し、複数コマンドを実行していて最初のコマンドを C-c で殺した時に、次のコ 10293 マンドには TRAPDEBUG が残った状態で実行される。この時にそういう事が起こ 10294 る可能性がある。 10295 10296 o C-c がちゃんと動くか確認する。OK 動いている。 10297 10298 2022-02-16 うーん。やはり直接 trap すると問題が色々発生する。 10299 10300 x 先ず初めに報告にあった物が動かなくなった。報告にあった設定だと 10301 PROMOPT_COMMAND より後に初めて実行した DEBUG trap で時刻が決まる。然し、 10302 直接 trap していると、ble-attach よりも前に設定した trap が 10303 ble-decode/.hook 等にも反応してしまって正しい時刻が決定できない。 10304 10305 従って attach していない状態で ble/builtin/trap が受け取った DEBUG trap 10306 は結局 TRAPDEBUG 経由で実行するのが無難なのではないか。 10307 10308 x 更に、コマンド実行で再設定している DEBUG trap についても今回は問題になっ 10309 ていないが、やはり問題になる可能性がある。直接 user trap を設定すると、 10310 exec:gexec/.* に対して軒並み発火してしまうが、本来これらに対しては発火 10311 して欲しくはないのである。 10312 10313 なのでこの場合にもやはり user trap を直接設定するのは避ける。 10314 10315 x C7 fixed: prompt-attach をした場合全く値が更新されない。これは何故だろう 10316 か。PROMPT_COMMAND が失われている可能性? 確認した。元からあった 10317 PROMPT_COMMAND が消滅している。→修正した。ble/idict#copy の引数が逆だっ 10318 た。 10319 10320 x C8 fixed: 現在は先程まで動いていた物も動かなくなっている。何故? 10321 10322 x fixed: 先ず、起動時に trap が削除できていない所為でコマンドを実行する前は表示 10323 される時刻が前のプロンプトを表示した時刻からの遅延になってしまっている。 10324 これは type=initial でも final でも起こっている。 10325 10326 これの原因は簡単で user trap を直接 trap する様にした為に、ble.sh の内 10327 部 (具体的には最初の ble-decode/.hook) に対して DEBUG trap が動作してし 10328 まっている。 10329 10330 x fixed: 次に、final で実行した場合にはそもそも user trap すら正しく抽出 10331 できていない。少なくとも2コマンド目以降には元々取得できていた筈だがそれ 10332 も動かなくなっている。 10333 10334 これの原因は謎である。もしかすると TRAPDEBUG/.initialize が実行されてい 10335 ない? 先に adjusted が正しく動作しているとすると確かに 10336 TRAPDEBUG/.initialize は呼び出されなくなってしまう。現在の構成の場合に 10337 は TRAPDEBUG/.initialize と adjust は別々に処理する必要がある気がする。 10338 10339 これは試しに attach で adjust を呼び出す様にした所に問題がある。attach 10340 の時点で user trap の初期化が終わっていないので、この時点で adjust を実 10341 行してしまうと user trap が失われてしまう。…と思ったが、それも何だか変 10342 な気がする。adjust では trap - DEBUG を実行していて ble-attach は 10343 declare -ft していないので、ble-attach 内部での trap 解除は外に漏れ出さ 10344 ない筈である。或いは、同じ文脈で TRAPDEBUG/.initialize が実行されてしまっ 10345 ている可能性はある? 10346 10347 分かった、adjust で trap - DEBUG したのは外に伝播しないが、adjusted=1 10348 に設定する為に user trap 読み取りのコードが不活性化してしまっている。 10349 adjusted=1 になる為には user trap も読み取った後でなければならないので 10350 ある。 10351 10352 x C9 fixed: prompt-attach (memo/D1772.bashrc type=initial-prompt) した後に 10353 user trap が設定されたまま残っている。うーん。ble-attach する時に削除する 10354 べきなのではないか。。と思ったが、それだと未だ user trap を読み取っていな 10355 い時に元から存在した設定を削除してしまう事になるので駄目である。 10356 10357 うーん。つまり最初に読み取った時に取り敢えず trap を削除しておくべきとい 10358 う事なのだろうか。コマンド実行中でなければ。 10359 10360 というより prompt-attach の場合、何処でユーザー trap を読み取っているのだ 10361 ろう。と思ったが、initial-prompt の場合には最初に trap DEBUG をユーザーが 10362 呼び出した時点でユーザー trap が読み取られる事になる。 10363 10364 結局初回は必ず trap - DEBUG を実行する事になるという事なのだろうか。初回 10365 の判定はどの様にしたら良いのか。うーん。また新しく変数を増やすのか? 或い 10366 は既存の変数を用いて判定する事はできるだろうか。 10367 10368 そもそも userTrapInitialized という変数はその場合必要になるのだろうか。こ 10369 の変数は実際 gexec/.setup で調整をする必要があるかどうかだけの為に用いら 10370 れている。という事を考えるとこの変数の意味を変えれば良い気がする。 10371 10372 或いは TRAPDEBUG の adjust/restore の状態をちゃんと管理しておいて、一旦 10373 restore したのに未だ adjust していない状態になっていたり、未だそもそも 10374 adjust した状態になっていなかったら元に戻す等の対処が必要になるのではない 10375 か。 10376 10377 →その様に修正した。これで無駄に DEBUG trap が内部で呼び出される事はなく 10378 なった筈。 10379 10380 しかし報告された設定の場合に、初回のコマンド実行の実行時間が正しくない。 10381 これは一回でも無駄な DEBUG trap が PROMPT_COMMAND 実行後に実行されるとも 10382 う駄目なので、実は最初に現れた時点でもう正常動作しないのである。 10383 10384 a そうなると attach の時点で trap を削除するべきなのだろうか。その為には 10385 attach で trap の削除に関係する全ての経路で declare -ft を指定しておく 10386 必要がある。一応どの様な経路で adjust が行われるのかについて確認してお 10387 く事にする。 10388 10389 取り敢えず adjust-PS1 は以下の経路で呼び出されている。 10390 10391 ble-edit/adjust-PS1 10392 ble-edit/attach/.attach 10393 ble-edit/attach 10394 ble-attach 10395 ble/base/attach-from-PROMPT_COMMAND 10396 10397 うーん。ble-edit/attach の直下で TRAPDEBUG/adjust を呼び出してみる事に 10398 する。 10399 10400 x 然し関数内や source 内部で ble-attach した時には結局元の trap を削除 10401 するのに失敗する事になる。一応一番外側が ble-attach かどうかで判定は 10402 できる。また set -T が有効になっている場合にも削除は可能だろう。 10403 10404 他、ble-attach を呼び出す可能性のある関数は全て列挙する。 10405 10406 - ble -> ble/dispatch 10407 - ble/base/attach-from-PROMPT_COMMAND 10408 - ble/base/process-blesh-arguments ... これはいきなり attach する時 10409 10410 色々面倒である。ble/base/attach-from-PROMPT_COMMAND についても、これは 10411 PROMPT_COMMAND に設定して使う事を想定しているが、他の枠組みが何処かの変 10412 数に待避して関数内から呼び出した場合にはやはり trap が見えなくなってし 10413 まう。結局 attach の時点で確実に trap を削除しようとするのは困難である。 10414 10415 b initial-attach の時に問題が起こらない様にするだけであれば、attach の外 10416 の状態であっても trap を実行した時には filter を入れる様にするという手 10417 もある。 10418 10419 うーん。方針が定まらないとどの様に対処するべきか分からない。再度現状につ 10420 いて整理する事にする。 10421 10422 "ble/builitin/trap ... DEBUG" が bashrc で呼び出された時はどの様に振る舞 10423 うべきか。取り敢えず、実際に ble-attach するまでは普通に DEBUG trap が動 10424 作するのが自然である。また、ble-attach した時に如何にして元から存在した 10425 DEBUG trap を不活性にするのかという事。 10426 10427 ! a ble/builtin/trap でユーザーが DEBUG trap を設定した時は、未だ attach し 10428 ! ていなければ user trap を直接設置する。ble-attach を実行した問にそれを 10429 ! 削除する。 10430 ! 10431 ! 然し、trap - DEBUG によって本当の意味で削除するのは条件が限られている。 10432 ! 現在の関数呼び出し経路の全てに trace 属性がついているか、set -T が設定 10433 ! されていてかつ現在の関数呼び出し経路の全てが既知の (set -T を弄らない) 10434 ! 関数であるという事が保証できる場合のみである。取り敢えず trap '' DEBUG 10435 ! とすれば削除はできる気がする。 10436 ! 10437 ! 従って、 10438 ! 10439 ! 1 ble.sh の枠組みの中で ble-attach を最終的に呼び出す可能性のありそうな 10440 ! 関数の全てに declare -ft を付加しておく。 10441 ! 10442 ! 2 ble-attach が呼び出された時に既に user trap が既知の状態になっている 10443 ! 時には trap DEBUG を削除する。 10444 ! 10445 ! 2a 経路上が全て DEBUG を継承していると判断できる時には trap - DEBUG 10446 ! を実行して直接削除する。 10447 ! 10448 ! 2b 経路上で DEBUG が途切れているかもしれない時には仕方がないので trap 10449 ! '' DEBUG を実行する。途中で別の DEBUG を設置したりしない限りはこの 10450 ! DEBUG trap は一番上の階層にまで適用される筈である。 10451 ! 10452 ! 然し面倒なので ble-attach した瞬間には常に trap '' DEBUG で良い気もす 10453 ! る。その様にしておけばわざわざ declare -ft 等の事を考える必要もない。 10454 ! 10455 ! 3 ble-attach が呼び出された時に user trap が既知の状態になっていない時 10456 ! は厄介である。 10457 ! 10458 ! 3a 経路上が全て DEBUG を継承していると判断できる時にはその場で user 10459 ! trap を読み取ることができる。その時には単に trap - DEBUG を追加で実 10460 ! 行して trap を削除すれば良い。 10461 ! 10462 ! 3b それ以外の場合には user trap を取得できない。trap '' DEBUG で削除 10463 ! すると元の user trap を破壊してしまうので実行できない。 10464 ! 10465 ! この方法で気になるのは様々な関数に trace 属性を設定して変な問題が起こら 10466 ! ないのかという事である。これは他の人が設定した DEBUG trap の侵入を許可 10467 ! するという事に他ならない。本来他の人が設定した DEBUG trap でその枠組の 10468 ! 動作に干渉してはならない (したら保証外) なので気にしなくて良い筈という 10469 ! 気もするが、DEBUG trap を使っている側がちゃんと動かない可能性は常に存在 10470 ! する。まあ余り気にしても仕方がないのかもしれない。 10471 ! 10472 ! b ble/buitlin/trap は attach 状態にない時には TRAPDEBUG を設置する。つま 10473 ! り、ble.sh の外側でも TRAPDEBUG で filter しながら動作するという事。こ 10474 ! れはいざ ble-attach を実行した時に意図しない DEBUG を防ぐ目的がある。 10475 ! 10476 ! 然し、これは元から設置されていた DEBUG に対しては無力である。結局、元か 10477 ! ら設置されていた DEBUG に対しても対策をするのであればわざわざ DEBUTRAP 10478 ! 経由にする必要もないのでは? → 然し、元から設置されていた DEBUG に対し 10479 ! ては完全な対策ができない。ble/builtin/trap 経由の時には完全な対策が可能 10480 ! な方法に切り替えるのは妥当である。従って、論点は元から設置されていた 10481 ! DEBUG に対してどれだけ完全な対策を行う事ができるかという事になる。 10482 10483 c 結局 ble/builtin/trap 及び .TRAPDEBUG/restore では必ず TRAPDEBUG 経由で 10484 bind する事にしたので改めて整理し直す。また、現在形路上が全て DEBUG を 10485 継承しているかどうかを判定する関数を作成した。 10486 10487 1 ble.sh の枠組みの中で ble-attach を最終的に呼び出す可能性のありそうな関 10488 数の全てに予め ble/function#trace を実行しておく。 10489 10490 2a global DEBUG が見える状態にある時には、user trap が未知であればその場 10491 で読み取りを行う (__initialize)。そして DEBUG trap を削除する 10492 (__TRAPDEBUG_adjust)。 10493 10494 2b それ以外で user trap が既に読み取り済みもしくは設定済みであれば 10495 DEBUG trap を削除する (__TRAPDEBUG_adjust)。 10496 10497 2c それ以外の時には user trap を保持しなければならないので仕方がないが 10498 そのまま通過。 10499 10500 この方針で行く事にする。実装した。取り敢えず動いている様に見える。後で 10501 制限について書く事にする。 10502 10503 * C10 done: 元から設定されている trap が TRAPDEBUG の類だった時。これは無視 10504 する必要がある。そうしないと最悪無限ループになる。 10505 10506 x C11 fixed: initial-prompt で core-dump する様になってしまった。。何故? 再 10507 帰 trap の可能性を疑って先に対応する事にしたが直らなかった。関係なかった 10508 様だ。 10509 10510 取り敢えずどういう制御パスになっているかだけは確認する。 10511 10512 と思ったら再帰 trap になっていた。再帰判定のコードが間違っていた。修正した。 10513 10514 然し、そもそも何故再帰 trap になってしまうのかというのは謎である。あー分 10515 かった。ble/builtin/trap 経由で user trap を読み取ってもその後で 10516 ble-edit/attach から呼び出した _ble_builtin_trap_DEBUG__initialize で再び 10517 user trap を読み出そうとしてしまうのが問題なのである。これも修正した。 10518 10519 x C12 fixed: bash-5.0 以下で PROMPT_COMMAND が消滅してしまっている。何故か。 10520 copy-state の使い方を間違えている? 10521 10522 これは分かった。attach-from-PROMPT の時は PROMPT_COMMAND の書き換えをチェッ 10523 クしている。なので、中で attach して PROMPT_COMMAND を待避するとそれが保 10524 存されてしまう。 10525 10526 と思ったがそれでも何だか変な気がする。ble-attach は何れにしてもその 10527 PROMPT_COMMAND の保存復元の外側で実施される筈だから。変だ。 10528 10529 うーん。分かった。local PROMPT_COMMAND としていた為に異なるレベルの 10530 PROMPT_COMMAND を触っていて変な事になっていた様だ。unlocal をちゃんと実行 10531 する様にしたら問題なくなった。と、思ったがこれは本当に意図した動作なのだ 10532 ろうか? 新しい PROMPT_COMMAND を実行したくて lcoal PROMPT_COMMAND を実行 10533 していたのではあるまいか? 10534 10535 改めてコードを確認する。うーん。多分大丈夫意図した振る舞いになっている筈。 10536 10537 x C13 wontfix: bash-5.0 以下で type=initial-prompt (memo/D1772.bashrc) に対 10538 し attach 時に vbell で報告者の設定がエラーメッセージを出す。 10539 10540 て、__initialize での DEBUG trap 読み取りに失敗している気がする。というか、 10541 initial なので直接 ble/builtin/trap を経由して trap を設定している筈で、 10542 間違う筈はない…。 10543 10544 うーん。vbell でエラーが表示されるという事は attach した後に bash が 10545 PROMPT_COMMAND を実行しようとして失敗しているという事になる気がするが…。 10546 うーん。つまり? 外側の PROMPT_COMMAND の文字列を eval している時に、 10547 ble-attach の入った ble/function#lambda/0 を実行する所までは良くてその後 10548 に続いている timer_stop の呼び出しに於いて問題が生じているという構図であ 10549 る。うーん。これを回避するのは難しい。 10550 10551 10552 つまり何が起こっているかというと、本来は PROMPT_COMMAND の実行の最初に 10553 timer が設定されてその実行の終わりに timer_stop が呼び出されるのでそれで 10554 良いのだが、prompt attach の瞬間には bash の 10555 10556 PROMPT_COMMAND='ble-prompt-attach ; timer_stop' 10557 10558 の最初に timer が設定されるが、それは ble-attach 内部の PROMPT_COMMAND 呼 10559 び出しで消費される。その後で timer_stop を実行しようとするが、その時点で 10560 既に DEBUG trap は除去されているので対応する DEBUG trap が一度も呼び出さ 10561 れない儘に timer_stop が呼び出されてエラーメッセージが発生する。 10562 10563 うーん。prompt attach は仕組みからして処理の実行順序を変更する事になるの 10564 でこれに対してどの様に処理するべきかは謎である。本当は PROMPT_COMMAND の 10565 最後に実際の attach 操作を持って来たいところだがそういう訳にも行かない。 10566 10567 うーん。其処まで実行順序が厳密でなければならないというのは困る。というか、 10568 そもそも元々のスクリプトが DEBUG が必ず PROMPT_COMMAND よりも前に実行され 10569 る筈という前提で設計されているのがよくない。というか、そもそも DEBUG を用 10570 いた hack を使っている時点でよくない。然し、そうは言ってもうーん。 10571 10572 例えば prompt-attach の時には DEBUG trap はその場では削除しないという事を 10573 考えたが、そうすると結局また問題が生じる。timer_stop が処理するまでは良い 10574 が、その後も DEBUG trap が有効のままなので、DEBUG trap が 10575 ble-decode/.hook 等に対して呼び出されて予期しない時刻になる。また、もし逆 10576 に timer_stop がその PROMPT_COMMAND の中で attach-fromp-PROMPT_COMMAND よ 10577 りも後に呼び出されなかったら結局それも DEBUG trap で設定された timer が残 10578 存してしまう。 10579 10580 これは現状 vbell が出るだけで全く使えない訳ではないので無視する事にする。 10581 それに $timer ではなく timer と書いていれば特に問題もなく利用できる筈であ 10582 る。 10583 10584 * C14 desolved: trap DEBUG より後に ble.sh を source した場合に対する対策 10585 10586 最初の PROMPT_COMMAND 実行の時には特に問題にならない。然しその時に timer 10587 変数が削除される。2回目の PROMPT_COMMAND 実行までに trap が実行されれば問 10588 題は起こらないが、実際は未だ trap DEBUG は取得できていないので自前で設定 10589 することもないし、だからと言ってずっと関数を出ないので既に設定されている 10590 物が発火することもない。 10591 10592 * C15 desolved: prompt-attach の場合の振る舞いについても確認する必要がある。 10593 10594 x C16 ok: bash-3.2 で type=final (memo/D1772.bashrc) の時に初回のコマンド実 10595 行の時間がずれる 10596 10597 他の 3つの attach 方法の場合には問題は生じていない。物によっては最初のプ 10598 ロンプトの時間が 0s になったり 1s になったり 2s になったりして、初期化の 10599 時間が含まれたり含まれなかったりしているがそれは対した事ではない様に思わ 10600 れる。 10601 10602 これは何故だろうか。4.0 では特に何も起こっていない。final の時には 10603 ble-attach を直接呼び出して attach している。うーん。もしかして DEBUG 10604 trap を除去できていない? 10605 10606 うーん。というか 4.0 でも 3.2 でも bashrc の内部では trap を取得できてい 10607 ない様だ。うーん? というか 5.1 ですらもできていない。何故だろう。 10608 is-global-traceable がちゃんと動いていないという事? 10609 10610 →と思ったらこれは単にテスト用の rcfile の名前が .bashrc ではなかった為に 10611 棄却されていただけの事だった。棄却条件を緩めたらちゃんと期待通りに動く様 10612 になった。気にしなくて良い。 10613 10614 x C17 desolved: bash-3.0, 3.1 で後に ble.sh を source した時、何回かコマン 10615 ドを実行してもエラーが出続ける。どうやら trap が消滅している。 10616 10617 →これは今試したら再現しない。ちゃんと動いている。うーん。多分他の物を修 10618 正した時に一緒に直ったのだという事だと思われる。 10619 10620 x C18 wontfix: bash-3.1 で後から ble.sh を source した時に最初のコマンド実行 10621 の時間がずれている。うーん。これは ble-attach 等が DEBUG を継承させられな 10622 いという事に由来する制限である。 10623 10624 うーん。bash-3.1 以下で declare -ft を適用する方法はあるのだろうか。或い 10625 は set -T を設定するしかないのかもしれない。 10626 10627 念の為先に source ble.sh したときについてはちゃんと動く事を確認した。OK 10628 10629 * C19 別項目: その他の trap についても元からあった trap を拾う様にしたい。 10630 うーん。この commit は巨大になり過ぎたし、DEBUG trap 専用の物なので、他の 10631 trap に関しては別項目で対応するのが正解の気がする。 10632 10633 x C20 別項目: bash-3.0 で変な文字列 '' が出力される。 10634 10635 この変なエラーを直さない限り、そもそもちゃんと動いているかどうかまともに 10636 修正する事ができない。というかこの謎の出力は一体何処から来ているのだろう 10637 か。DEBUG trap 関係だろうか。 10638 10639 うーん。これはそもそも今回の話と関係なく起こっている問題の様だ。これは別 10640 枠で修正するべき。そもそも master で、plain bash + plain ble.sh でも再現 10641 する事を確認した。 10642 10643 x C21 fixed: bash-3.0 で結果が常に 0s 10644 10645 調べてみると DEBUG trap が何故かコマンドが終了してからしか呼び出されてい 10646 ない様だ。更に調べると TRAPDEBUG は呼び出されている。と此処で分かった。原 10647 因は BASH_COMMAND が bash-3.0 で設定されていないという事だ。 10648 10649 これは関数内で BASH_COMMAND を参照した時だけでない。trap string で直接 10650 BASH_COMMAND を参照しても同様に BASH_COMMAND には現在実行しているコマンド 10651 の文字列が格納されている (という事を確認した)。 10652 10653 $ func() { echo heloo; }; declare -ft func; trap 'trapdebug "$BASH_COMMAND"' DEBUG; trapdebug() { echo "[$1]"; } 10654 10655 これは仕方のない事である。bash-3.0 では不当に DEBUG trap が握りつぶされな 10656 い様にした。bash-3.0 では余分に DEBUG trap が呼び出される事になるが、これ 10657 は仕方がない。DEBUG trap をしかける側はいつでも大量の関係ない DEBUG trap 10658 を捨てる事が求められているので許容してもらう。 10659 10660 x C22 fixed: bash-3.1 以下で type=final-prompt (memo/D1772.bashrc) に於いて 10661 trap が消滅している? 10662 10663 先ず _ble_builtin_trap_DEBUG_userTrapInitialized によると初期化は実行され 10664 ていない。一方で builtin trap -p の時点でもう消えている。うーん。 10665 10666 どうやら bash-3.0 では bind -x の top レベルでも何故か 10667 attach-from-PROMPT_COMMAND の中で実行している設定になっている様だ。謎。取 10668 り敢えず work around を加える事にした。ちゃんとトップレベルの trap を読み 10669 取る事ができているので OK 10670 10671 * C23 done: refactor name ble/function/is-global-traceable 10672 10673 取り敢えず何れの bash version でも少なくともコマンドを一回実行すればちゃん 10674 と動く様になった様に思われる。これで良しとする。 10675 10676 10677 * C24 一旦何処かに push して diff を観察する。 10678 10679 [制限] 10680 10681 最後に現状の実装の制限についてまとめる。これは何処かにまとめて置いた方が良 10682 い気がする。ソースコードの中に記述するのが最も分かりやすいのではないか。転 10683 記した。 10684 10685 * 先に ble.sh を source した場合は殆どの場合動く。 10686 10687 bash-5.0 以下で先に ble.sh を source して prompt-attach を行い、更に 10688 PROMPT_COMMAND を書き換えた場合には、PROMPT_COMMAND の中で 10689 attach-from-PROMPT_COMMAND よりも後に実行している処理は DEBUG trap が無 10690 効化された状態で実行される事になる。 10691 10692 * 後に ble.sh を source した場合には以下の場合にロード直後は DEBUG trap が 10693 ble.sh 内部の処理に対しても有効になっている。 10694 10695 - (set -T & --attach=attach の時の条件) rcfile が .bashrc でも 10696 .profile でも .bash_profile でもない場合 (これは現在 rcfile の 10697 中にいるかどうかを判定する方法が bash にはない事から、rcfile 10698 かどうかをファイル名と行番号だけから判定しなければならない事に 10699 由来する) 10700 10701 - source ~/.bashrc 等の様にして手動で bashrc を読み込んだ時 (これは 10702 source が DEBUG trap を継承しないという Bash の制限に由来する) 10703 10704 - rcfile から一旦別のファイルを source してそのファイルから ble.sh を 10705 source した時。または関数内から ble.sh を source した時 (これも DEBUG 10706 trap の継承に関する Bash の制限に由来する) 10707 10708 - bash-3.1 以下の時 (これは declare -ft で trace を付加できる関数の関数 10709 名に対する制限に由来する) 10710 10711 * というか結局報告者の提示した設定が不安定すぎるという事に尽きている様な 10712 気もする。この設定は例えば bash-preexec.sh と一緒に使ったとしても崩れる 10713 し (とはいいつつも bash-preexec.sh は他のあらゆるものを壊す気がする)、 10714 また、PROMPT_COMMAND+=$'\n'追加設定 を実行するあらゆる設定に対して脆弱 10715 である。その様ないい加減な設定を使っている時点で完全には対応しきれない。 10716 10717 2022-02-13 10718 10719 * util: EXIT trap を設定していると実際に exit する時に return に空文字列が渡される (reported by SuperSandro2000) [#D1771] 10720 https://github.com/akinomyoga/ble.sh/issues/175 10721 10722 これは明らかに最近書き直した trap handler 周りのの処理の問題である。と思っ 10723 たが return を呼び出している箇所では特に空文字列が渡されそうなコードは見え 10724 ない。再現はできているのでどうなっているか確認する事にする。 10725 10726 →分かった ble/util/setexit に渡す引数が空になっている。と思ったら単に typo 10727 だった。というよりは変数名の変更漏れ。 10728 10729 * [棄却] complete: ls ~/.c{onfig,1}/[TAB] としても候補が生成されない [#D1770] 10730 10731 うーん。これは今迄ちゃんと候補が生成できるだろうと思っていたがそうでもない 10732 様だ。改めて振る舞いを調べてみるのが良い。やはり動かない。bash-completion 10733 の所為でもない。ble.sh の元々の機能を使っていてもやはり生成されない。 10734 10735 というか寧ろ元々の機能を使っているから候補が生成されないという可能性もある? 10736 と思って改めて bash-completion を使って試してみたがそれでも駄目である。取り 10737 敢えず、bash-completion が介在しない場合について振る舞いを確認する。 10738 10739 →と思ったらどうやらブレース展開の一番最後の要素を使って補完を実行する仕組 10740 みになっている様だ。なので、 ls ~/.c{1,onfig}/[TAB] とした場合にはちゃんと 10741 候補が生成される。これは単にそういう設計という事なので修正しなくて良い。 10742 10743 * edit: いつの間にかに rps1 に接した時の計算が壊れてしまっている [#D1769] 10744 10745 改行位置が正しく計算できていない? と思ったが、うーん。これは改行が継続する 10746 様にして欲しいという要望に応えた時に導入したバグの気がする。 10747 10748 Ref #D1745 10749 10750 改めて edit.sh で D1745 に関係している所を確認してみた所… rps1 があるかど 10751 うかのチェックを忘れている。→と思ったがそもそも CR を埋め込む時点でそれは 10752 処理していたのではないか? 確認してみた所 *:relative:* の時には CR は埋め込 10753 まれない様になっている筈。 10754 10755 確認してみると relative が opts に指定されている時と指定されていない時が存 10756 在する。textmap#update の呼び出し元を確認してみると 10757 ble/widget/.update-textmap から呼び出している物については opts を指定してい 10758 なかった。実は結構な確率で ble/widget/.update-textmap 経由で更新が行われる 10759 という事だった様だ。何れにしてもちゃんと同じ引数で textmap#update を呼び出 10760 す必要があるのだった。 10761 10762 * [経緯確認] というか今迄は rps1 が存在していても relative にせずに直接描画 10763 計算をしていたという事になるのではないか。そう思うと今迄動いていたのは偶 10764 だったという事になる。或いは、relative になる様にしたのは #D1745 だったの 10765 だったか。 10766 10767 90a8915c src/edit.sh (Koichi Murase 2019-03-09 11:40:10 +0900 3009) local render_opts= 10768 d84bcd8d src/edit.sh (Koichi Murase 2020-10-11 02:05:09 +0900 3010) [[ $rps1_enabled ]] && render_opts=relative 10769 cf8d9493 src/edit.sh (Koichi Murase 2021-06-07 12:13:56 +0900 3011) COLUMNS=$cols ble/textmap#update "$text" "$render_opts" # [ref] x y 10770 10771 90a8915c src/edit.sh (Koichi Murase 2019-03-09 11:40:10 +0900 2483) local render_opts= 10772 d84bcd8d src/edit.sh (Koichi Murase 2020-10-11 02:05:09 +0900 2484) [[ $rps1_enabled ]] && render_opts=relative 10773 90a8915c src/edit.sh (Koichi Murase 2019-03-09 11:40:10 +0900 2485) COLUMNS=$cols ble/textmap#update "$text" "$render_opts" 10774 10775 90a8915c src/edit.sh (Koichi Murase 2019-03-09 11:40:10 +0900 2064) local render_opts= 10776 b86709af src/edit.sh (Koichi Murase 2019-03-23 12:36:07 +0900 2065) [[ $rps1_show ]] && render_opts=relative 10777 90a8915c src/edit.sh (Koichi Murase 2019-03-09 11:40:10 +0900 2066) COLUMNS=$cols ble/textmap#update "$text" "$render_opts" 10778 10779 90a8915c src/edit.sh (Koichi Murase 2019-03-09 11:40:10 +0900 1668) local render_opts= 10780 90a8915c src/edit.sh (Koichi Murase 2019-03-09 11:40:10 +0900 1669) [[ $flag_rps1 ]] && render_opts=relative 10781 90a8915c src/edit.sh (Koichi Murase 2019-03-09 11:40:10 +0900 1670) COLUMNS=$cols ble/textmap#update "$text" "$render_opts" 10782 10783 b2e2461a ble-edit.sh (Koichi Murase 2017-10-05 01:12:01 +0900 1669) ble/textmap#update # text x y → x y 10784 10785 これを見ると3年前からずっと relative 指定していたけれど、単に絶対移動でも 10786 問題が生じていなかったというだけの様である。確かに論理的には問題は生じ得 10787 なかったのかもしれない。ちゃんと改行は改行として処理していたので。 10788 10789 因みに最初に opts を導入した時点で既に ble/widget/.update-textmap は rps1 10790 に拘らず opts なしで textmap#update を呼び出していた様である。同時に 10791 ble/widget/.update-textmap の textmap#update の呼び出しも修正しているのに 10792 opts を指定しなかったのは唯単に油断したからだろうか。 10793 10794 opts を導入したのは #D0959 であった。そしてこれは確認してみた所、rps1 を 10795 最初に導入した commit だった。という事を考えると本当にずっと relative あ 10796 りとなしの両方で動かしていたという事になる。 10797 10798 * [棄却] git submodule update は even の時にはしなくても良いのでは [#D1768] 10799 https://github.com/raccoonasdf/raccoonpkgs/commit/d7ec0af3db2cd473adcb12a0132e53d3c216dddf 10800 10801 と思って改めて makefile を確認してみたが git submodule update は、 10802 contrib/.git 及び contrib/contrib.mk さえ存在していれば実行されない様な気が 10803 する。或いは、ble-update について話しているのかとも思ったがそれも変な気がす 10804 る。ble-update は結局本体の更新の為にインターネットに接続するのだから、同時 10805 に submodule update を実行しても特に問題になる様にも思われない。 10806 10807 うーん。これはこの上のファイルを記述した人が勘違いしているだけという気がし 10808 てきた。つまり、makefile に git submodule init があるのを見つけて、これは 10809 make の時に必ず呼び出されるのに違いと思っているのではないか。実際には 10810 working tree に展開されていれば呼び出される事はないのだが。或いは、nix の設 10811 定だと submodule fetch するだけで working tree に反映しないという可能性もあ 10812 る。その場合には git submodule は make から呼び出される事になるが、しかし一 10813 方でこれは必ず呼び出さないと行けないものでもある。 10814 10815 一方で現在の ble.sh gitmodules が指している commit と現在 HEAD が異なる時に 10816 は update を自動的に実行することもできる。と思ったが流石にそれは一時的に異 10817 なる物にして試したい時などにとても面倒である。という事を考えると、わざわざ 10818 その様な事はしなくて良い。結局 ble-update を実行した時にちゃんとした状態に 10819 調整される筈。 10820 10821 2022-02-12 10822 10823 * complete: _fzf_path_completion 経由だと ~ で始まるパスのディレクトリの後に / が挿入されない (reported by SuperSandro2000) [#D1767] 10824 https://github.com/akinomyoga/ble.sh/issues/171#issuecomment-1030962166 10825 10826 file: memo/D1760.fzf-completion.bashrc 10827 10828 恐らく compopt か何かが関係しているのだろうという気がするが ~ で始まるかど 10829 うかで問題が再現するかしないかが変わるというのは変だ。~ は ble.sh の側で展 10830 開している筈。という事は ~ がある事によって問題が発生しているという事ではな 10831 い様な気がする。 10832 10833 ? 例えば / で始まる事によって問題が発生するのではないか。或いは subdir/* の 10834 時に問題が発生するという事だろうか。 10835 10836 → / で始めても問題は再現しない。サブディレクトリの下にあってもちゃんと動 10837 いている。本当に ~ で初めた時にだけ問題が起きている様に見える。更に、 10838 bash-completion と組み合わせた時にだけ問題が発生しているという事でもある。 10839 うーん。何が起こっているのだろうか。 10840 10841 取り敢えず候補生成部分を確認するのが良い気がする。 10842 10843 * うーん。実装を見るとやはり compopt が欠けているのが問題である様に見える。 10844 と思って実際に展開する部分を確認してみた所… 10845 10846 CAND='~/.config' INSERT='~/.config' DATA=':noquote:filenames:' 10847 10848 ちゃんと filenames は指定されている。という所で分かった…。"~/.config" と 10849 いう名前で候補が生成されている。これだと本当に '~/.config' という名前のディ 10850 レクトリが存在する時にしか / がつかない。うーん。何が起こっているのか。 10851 10852 ? 先ず 何故 fzf でない場合にはちゃんと補完されていたのか? というか前から補 10853 完されていなかった可能性? 10854 10855 そう思って bash-completion で試してみたがちゃんと動いている。そして以下の 10856 様にちゃんと具体的なディレクトリ名に展開されている。 10857 10858 CAND='/home/murase/.config' INSERT='~/.config' DATA=':filenames:' 10859 10860 うーん。勝手に fzf が ~ に置換してしまっているのが良くない。 10861 10862 * 念の為、ちゃんと ble.sh の側で展開できているか確認する。 10863 10864 COMP_WORDS=('cat' '/home/murase/.con') 10865 10866 ちゃんと展開している。つまり fzf は勝手にこれを ~ に置換してしまっている 10867 という事。変な振る舞いをするものだ。一応確認する事にする。と思ったら、普 10868 通に fzf を起動した時にはそういう変な振る舞いは見られない。うーん。何故? 10869 10870 もしかすると contrib/fzf-completion による介入が原因の可能性もある? 10871 10872 うーん。これだ。 10873 10874 COMP_WORDS=("${comp_words[@]}") COMP_CWORD=$comp_cword 10875 COMP_LINE=$comp_line COMP_POINT=$comp_point 10876 10877 fzf は ** だとか展開前の特別なシーケンスを探す為、展開前の単語を要求して 10878 いる。従って、直接 ~/.config という文字列を渡す事になる。 10879 10880 うーん。という事は fzf を使っている時には 'ba[TAB] 等に対して補完できない 10881 という事にはなるまいか? と思ったら勝手に quote を外された。うーん。仕方が 10882 ない。 10883 10884 * 対策としては noquote が設定されている時にはディレクトリ名かどうかのチェッ 10885 クは CAND ではなくてそれの展開結果に置き換える。もしくは展開結果を用いて 10886 CAND に再代入する? INSERT の方に記録する。 10887 10888 と思ったが、うーん。候補生成の時点では CAND の方しか記録しないのでは。 10889 と思って確認したがちゃんと生成時点で CAND も INSERT も決定していた。 10890 10891 取り敢えず quote-insert で noquote が指定されていた時の CAND/INSERT の決定 10892 方法を修正した。 10893 10894 x fixed: 動いていると思ったら全く候補が生成されなくなって fallback していた。 10895 quote-insert は終了ステータスに意味があるという事だった。 10896 10897 x fixed: 改めて修正すると noquote による特別処理が動いていない、と思ったら 10898 count が空になっている。simple-word/eval で count を得る為には特別な条件 10899 が必要? と思って確認したら opts に "count" を指定する必要があった。修正 10900 した。 10901 10902 * OK: simple-word/eval は count も上書きする様だ → これは opts に count を 10903 指定した時だけの機能なので、一般の場合については変数汚染を気にする必要は 10904 ない。 10905 10906 x fixed: メニューにフルパスで表示されてしまう。これは PREFIX_LEN の初期化を 10907 action:ACTION/initialize よりも後に移動すれば良いのだった。今 CAND も 10908 /initialize によって書き換えられる可能性があるので、書き換えられた後の値 10909 を参照して PREFIX_LEN を決定するべきなのである。 10910 10911 x done: quote_fixed_comps に注意しなければならないのでは? 10912 10913 取り敢えず quote_fixed_comps が設定されている時には CAND の書き換えは 10914 suppress する事にした。一方で、quote_fixed_comps が設定されている時でも上 10915 手にやる方法はあるだろうか。というか、quote_fixed_comps に抵触する場合に 10916 は今迄一体どの様に処理していたのだろうか。よく考えたらもっと後の段で候補 10917 を filter out しているのではないか。もしそうだとしたらここで何かしなくて 10918 も良いのではないかという気がする。 10919 10920 と思ったが、値が先頭一致している場合にはそれに対応する部分まではちゃんと 10921 一致する様に生成しなければならないのではないか。 10922 10923 quote_fixed_comps もしくは comps_fixed がどの様に処理されているのかを改め 10924 て確認する必要がある。 10925 10926 うーん。brace 展開がある時に現在の実装でどう振る舞うのか不安になって来た。 10927 →取り敢えず簡単な場合にはちゃんと期待通りに動いている。然し何故動いてい 10928 るのかは謎である。と、思ったがそもそも fzf はブレース展開がある時に正しく 10929 候補を生成できていない。従って ble.sh の候補生成器に fallback していると 10930 いう事の様である。 10931 10932 そもそも fzf には直接 comp_words を渡しているのだから、それでブレース展開 10933 を潰してしまったとしてもそれをそのまま受け入れて遡った書き換えを実行する 10934 のが自然の気もする。従って quote_fixed_comps を気にする必要はない。 10935 10936 と思ったが fzf 以外が noquote を指定する可能性もあるのでやはり油断はでき 10937 ない。うーん。fzf 以外が noquote を指定した時にちゃんと comps_fixed を処 10938 理する様に修正する必要があるのでは。或いは fzf が指定されていたとしても 10939 comps_fixed を処理する。 10940 10941 a うーん面倒だから quote_fixed_comps がある時は逆に reconstruct した CAND 10942 から INSERT を再度生成するのが良い気もしてきた。 10943 10944 b と思ったが確認すると他にも色々しているのでやはり直接その場で 10945 quote_fixed_comps に関係する処理だけを実行する事にした。 10946 10947 c 他に INSERT を解析して該当部分だけを抜き出すという事も場合によっては可 10948 能だが完全ではないし無意味に複雑になるし、そもそもブレース展開が存在す 10949 る様な文脈では quote の仕方を変化させても意味は変わらない筈なので、再度 10950 INSERT を CAND から再生成してしまっても問題ない気がする。 10951 10952 上記の b の方法で実装する事にした。 10953 10954 * done: progcomp-raw は別の名前にしたい。やはり最終的には ble.sh の拡張であ 10955 ると分かる様に blesh や ble.sh, ble- 等を付けるのが妥当という事になるだろ 10956 う。 10957 10958 ble-progcomp-raw という事に取り敢えずしてみたが、そもそも compopt を設定 10959 するのは progcomp でしか起こらない事なので progcomp を含めるのは冗長であ 10960 る。然しそうすると ble-raw という事になるがこれだと一般的過ぎる気がする。 10961 もう少し絞る方法はないだろうか。 10962 10963 類似の事を指定している箇所があった気がする。それは何でどの様に処理してい 10964 たか。→ "comp_type == *:raw:*" だった。reconstructed (COMPS で quote を 10965 閉じた物) を COMPV に設定していた。context:glob や 10966 context:dynamic-history の generate-sources で raw を設定していた。 10967 10968 うーん。類似してはいるけれども微妙に異なる気もする。ble-syntax-raw にする 10969 か。然しそれだと syntax.sh 由来の物の様にも解釈できる (しかしそれはそれで 10970 実際正しいのではないか。extract-command の結果をそのまま渡す様に修正して 10971 いるのだから)。或いは単に syntax-raw にする? 10972 10973 * 2022-02-02 main: やはり nix-shell の中でも有効にする [#D1766] 10974 Ref #D1747 10975 10976 そもそも nix-shell で ble.sh が欲しい事もあるそうだ。報告がいい加減なので無 10977 駄な修正をした。 10978 https://github.com/akinomyoga/ble.sh/issues/169#issuecomment-1027096640 10979 10980 * 改めて調べてみたら実際に実行するコマンドが exec になるのは ruby がコマン 10981 ド文字列に含まれている時のみの様である。 10982 10983 # というか、ruby という部分文字列が含まれているだけで実装が切り替わるので 10984 # かなりいい加減な実装である。更に、単にこの四文字を探す為だけに 10985 # std::regex を初期化しているのもおかしい。 10986 10987 実際にはユーザーによって指定された文字列 + exit を実行している様だ。なの 10988 で return をすると通常のシェルに入る事ができる、という事になっているのだ。 10989 10990 https://github.com/NixOS/nix/blob/master/src/nix-build/nix-build.cc#L187 10991 10992 # これも単に exit を付加するだけだと quoting の問題で何だか変な事になる気 10993 # がするが大丈夫なのだろうか。これ自体にセキュリティーの問題はないが、こ 10994 # れはセキュリティーの問題が起こるパターンの最たるものである。nix-shell 10995 # の実装はかなり怪しいと言わざるを言えない。 10996 10997 うーん。これに対する対策はどうするのか? IN_NIX_SHELL が設定されている時には 10998 ble-attach を無効化して attach=none であっても prompt attach を強行するとい 10999 う風にするべきだろうか。。 11000 11001 現在 bashrc の中にいるかどうかの判定はどの様にするのだったか。 11002 11003 というか、もし rcfile の名前が固定なのであれば、BASH_SOURCE を使って検出す 11004 る事が可能なのではないだろうか。うーん。"一時ディレクトリ/rc" という形をし 11005 ているらしい。 11006 11007 % そして一時ディレクトリは環境変数に設定されている。 11008 % 11009 % https://github.com/NixOS/nix/blob/73d5f38a47e7c3dea62994cfb8f962976194f767/src/nix-build/nix-build.cc#L428 11010 % 11011 % 例えば [[ ${BASH_SOURCE[${#BASH_SOURCE[@]}-1]} == $NIX_BUILD_TOP/rc ]] で 11012 % テストできるのだろうか。これは実際に nix-shell を入れてみない事には分から 11013 % ない気がする。 11014 % 11015 % →NIX_BUILD_TOP の中身を出力してみたがユーザーの run になっていて nix の 11016 % 一時ディレクトリではない。その他の一時ディレクトリも全てそうである。改め 11017 % て確認してみると tmpDir と TMPDIR は異なる変数だった。 11018 11019 以下を観察すると nix-shell, nix-build という名前の一時ディレクトリになるらしい。 11020 11021 https://github.com/NixOS/nix/blob/73d5f38a47e7c3dea62994cfb8f962976194f767/src/nix-build/nix-build.cc#L95-L101 11022 11023 うーん。というか或いはそもそも IN_NIX_SHELL の時は ble-attach をしたら強制 11024 的に prompt attach で良いのではないかという気がする。と思ったが、そこまです 11025 る事もないので、取り敢えず BASH_SOURCE の末端が /rc だったら prompt attach 11026 を設定する事にした。 11027 11028 これで一応動作はしている。 11029 11030 x 2022-02-04 然し、今度は別のエラーが発生している。bind は builtin じゃない 11031 と出ている。誰かが無効化しているという事なのだろうか。或いは、もしかする 11032 と非対話シェルでは bind は常に存在していないのだろうか→うーん。確かめて 11033 みたが "行編集は有効になっていません" という表示が出るのみである。なので、 11034 nix-shell に於いては何だか怪しげな事がされている? 11035 11036 調べてみると ble-attach の中で発生している。特に ble/decode/initialize の 11037 内部で発生している。不思議なのはちゃんと attach はできているという事。な 11038 ので bind が全く使えないという訳ではないという事。なのに何故 builtin は 11039 bind が存在しないという報告をするのだろうか。 11040 11041 ble/builtin/bind/read-user-settings で問題が生じている。うーん。最初の 11042 builtin bind では何も問題が生じていない。という事は何処かから呼び出してい 11043 る builtin bind の綴を間違えているか或いは余分な文字が混入しているという 11044 事だろうか。 11045 11046 と思ったら分かった。"$BASH" 云々 -c 'builtin bind -m emacs -p' 云々として 11047 既定の binding を読み取っている箇所で問題が起こっている。うーん。そうだと 11048 しても何故 builtin bind が使えないのか? 不思議である。 11049 11050 →うーん。実際のバイナリは以下の様になっている。 11051 11052 $ ls -la /proc/$$/exe 11053 lrwxrwxrwx 1 murase murase 0 2022-02-04 09:14:11 /proc/30092/exe -> /nix/store/xz3kkiscxh01yazxa1dk08q047mfl1fh-bash-interactive-5.1-p12/bin/bash 11054 $ echo "$BASH" 11055 /nix/store/2kh3c4v2vf6d6xg6c9n8zvfpwf3zzwca-bash-5.1-p12/bin/bash 11056 11057 うーん。ちょっと何が起こっているのか分からなくなった。 11058 11059 1 最初 (bashrc source 時): この時点で何故 BASH が現在のシェルではなくて 11060 /bin/bash になっているのか謎である。 11061 11062 SHELL=/bin/bash 11063 BASH=/bin/bash 11064 11065 うーん。SHELL に関しては外から export した物がちゃんと伝播している。 11066 BASH に関しては謎だ。もしかすると bash はビルド時に BASH を埋め込んでい 11067 る? と思ったがそうでもない様に見える。普通に 11068 11069 $ /nix/store/xz3kkiscxh01yazxa1dk08q047mfl1fh-bash-interactive-5.1-p12/bin/bash 11070 11071 としてログインした場合には何も変な事は起こっていない。ちゃんと自身の 11072 BASH が見えている。何か chroot 的な物をして bash をスタートしているのだ 11073 ろうか。bash のソースを見ると shell_name が相対パスでかつ login シェル 11074 ならばユーザー情報から BASH を初期化している。と思ったが、 11075 11076 $ (PATH=/nix/store/xz3kkiscxh01yazxa1dk08q047mfl1fh-bash-interactive-5.1-p12/bin:$PATH; hash -r; bash --login -c 'echo $BASH') 11077 11078 を実行してもちゃんと現在のシェルを見つけることができている。というか、 11079 shell_name の時点で正しく見つけることができているという事か。 11080 11081 2 次に $stdenv/setup で BASH=$SHELL が設定されていると思ったが、そうする 11082 と最終的に BASH=non-interactive-bash になっている理由が分からない。 11083 11084 3 更に最終的な SHELL の値は SHELL=interactive-bash になっている。つまり 11085 SHELL=non-interactive-bash になっている瞬間はない気がする。改めて SHELL 11086 の値について確認してみたが、これは stdenv/setup よりも後に設定されてい 11087 る様なので、最終的に interactive-bash にはなっていてもそれが BASH に反 11088 映されていなくても不思議はない。 11089 11090 うーん。trace を得た。 11091 11092 declare -x SHELL="/bin/bash" 11093 declare -- BASH="/bin/bash" 11094 /nix/store/xcy53qbjynin70g46w1nx011gr7jw8l1-stdenv-linux/setup:1: export SHELL=/nix/store/2kh3c4v2vf6d6xg6c9n8zvfpwf3zzwca-bash-5.1-p12/bin/bash 11095 /nix/store/xcy53qbjynin70g46w1nx011gr7jw8l1-stdenv-linux/setup:14: [[ -n "${BASH_VERSINFO-}" && "${BASH_VERSINFO-}" -lt 4 ]] 11096 /nix/store/xcy53qbjynin70g46w1nx011gr7jw8l1-stdenv-linux/setup:303: [ -z "${SHELL:-}" ] 11097 /nix/store/xcy53qbjynin70g46w1nx011gr7jw8l1-stdenv-linux/setup:304: BASH="$SHELL" 11098 /nix/store/xcy53qbjynin70g46w1nx011gr7jw8l1-stdenv-linux/setup:305: export CONFIG_SHELL="$SHELL" 11099 /nix/store/xcy53qbjynin70g46w1nx011gr7jw8l1-stdenv-linux/setup:309: export shell="$SHELL" 11100 /nix/store/xcy53qbjynin70g46w1nx011gr7jw8l1-stdenv-linux/setup:685: [[ -z "${NIX_SSL_CERT_FILE:-}" && "${IN_NIX_SHELL:-}" != "impure" ]] 11101 /nix/store/xcy53qbjynin70g46w1nx011gr7jw8l1-stdenv-linux/setup:689: [[ -z "${SSL_CERT_FILE:-}" && "${IN_NIX_SHELL:-}" != "impure" ]] 11102 /tmp/nix-shell-49112-0/rc:3: SHELL='/nix/store/xz3kkiscxh01yazxa1dk08q047mfl1fh-bash-interactive-5.1-p12/bin/bash' 11103 /tmp/nix-shell-49112-0/rc:3: [ -n "$PS1" -a -z "$NIX_SHELL_PRESERVE_PROMPT" ] 11104 11105 うーん。setup.sh 1行目で SHELL を書き換えている。。。まとめると、 11106 11107 1 何故か分からないが nix 環境では bash は BASH の初期化に失敗して 11108 /bin/bash を取り敢えず BASH に設定する。 11109 11110 2 $stdenv/setup は非対話シェル用(特にビルド用)の環境であり、非対話用に特 11111 別にコンパイルされた bash の上で動作する事を想定している。なので中で 11112 SHELL と BASH に無理やり固定の値 (非対話 Bash) の値を設定している。 11113 11114 3 更に nix-shell の呼び出し元では SHELL を対話シェルのパスに上書きしてい 11115 る。此処で BASH も同様に更新するべきではないか。 11116 11117 * うーん。面倒になった来たのでやはり nix 用の workaround を追加する事にする。 11118 つまり問題は BASH が変な値になっているのが原因である。という事は無理やり 11119 BASH を補正してしまえば良い。 11120 11121 a 環境の補正は ble.pp で集中して行っている箇所があるので其処で調整する事 11122 にする。と、思ったがよく考えたら nix-shell では setup の中で BASH を勝 11123 手に変更していて、更に、setup は bashrc よりも後で読み込まれるのだから、 11124 ble.sh の初期化時に BASH を補正しても仕方がない。うーん。 11125 11126 b 一つの手は ble-attach の時に BASH を補正するという事。結局 "$BASH" を使っ 11127 ているのは、decode の初期化であって、decode の初期化は ble-attach で呼 11128 び出しているのだから。そして、現在既に ble-attach に nix 用の 11129 workaround が入っている。 11130 11131 上記の b の箇所で BASH を上書きする事にした。 11132 11133 2022-02-09 11134 11135 * edit: exit を実行すると時間計測結果が表示されてしまう [#D1765] 11136 11137 これは何? 恐らく最近のコマンド時間計測と関連しているのだと思うが。そもそも 11138 exit を実行した後に time の結果が表示されうる物なのだろうか。 11139 11140 うーん。以下を実行すると時間が実際に表示される。 11141 11142 time { echo hello; exit; } 11143 11144 以下を実行した場合には特に何も表示されない (exit と単に表示される)。 11145 11146 time { echo hello; TIMEFORMAT=''; exit; } 11147 11148 少なくとも workaround として TIMEFORMAT= は有効であるという事。 11149 以下の様にした場合でもちゃんと出力は抑制される。 11150 11151 function f1 { local TIMEFORMAT=''; exit; }; time f1 11152 11153 然し、この時の問題はユーザーが ble.sh の中で time { ... exit; } を実行した 11154 時に時間表示がされなくなってしまうという事。という事を考えると、やはり外側 11155 で設定する時に何か工夫して外で設定した time に関しては時間測定結果が表示さ 11156 れない様に修正するという事。 11157 11158 うーん。然し、何故これが表示されてしまうのか。本来は別の所に出力されるべき 11159 なのではないか。。。これは bash に報告するべきなのではないか。 11160 11161 * 取り敢えずおかしな現象が起こるという事をもっと簡単な場合で証明する事は可 11162 能だろうか。 11163 11164 実際に振る舞いとしておかしいという事も以下のコマンドで確認する事ができる。 11165 つまり time の出力は 2>/dev/null に吸い込まれるべきであるのにも拘らず、 11166 exit が実行された文脈での 2 の接続先である 2>/dev/tty に出力されてしまう。 11167 11168 $ bash-5.1 --norc 11169 $ function f1 { { echo hello; exit; } 2>/dev/tty; } 11170 $ { time f1; } 2>/dev/null 11171 11172 * →と思ったらどうやら 5.2 では既に修正されている様だ。更に昔の version の 11173 振る舞いも確認してみた所、どうやら 4.4..5.1 で発生する問題の様である。 11174 11175 これに関しては exit の側で workaround をする事にする。これによって 4.4..5.1 11176 では、ユーザーが time { echo hello; exit; } を実行した時に何も表示されなく 11177 なるが、それは仕方がない。 11178 11179 そもそも 4.3 以前では time { echo hello; exit; } に対して結果は出力されなかっ 11180 た様である。という事を思うと、実は 4.4..5.1 は time の内部で exit を実行し 11181 た場合でも時間を表示する様に修正する上での壊れた振る舞いだったという事にな 11182 る。 11183 11184 x 2022-02-13 動いていない。#D1771 をテストする時にで時間計測の結果が出力さ 11185 れてしまう問題が未だ残存している事に気づいた。うーん。既に対策した筈だが 11186 動いていないという事。 11187 11188 うーん。改めて試してみたが確かに全然動いていない。 11189 11190 ? reject: うーん。つまり… trap handler の側の stderr に出力されていると 11191 いう事だろうか。EXIT trap handler は ble.sh は常に設定している。 11192 11193 一応 EXIT trap handler が呼び出されなかった・設定が消えている場合に備え 11194 る為に ble/builitin/exit での対策は残しておく事にする。 11195 11196 と思って trap handler の側で TIMEFORMAT= にしたが効かない。というより 11197 trap handler が呼び出されるよりも前に時間測定結果が表示されている。因み 11198 に EXIT handler はトップレベルで呼び出されている。 11199 11200 うーん。global の TIMEFORMAT を空にしたら表示されなくなった。取り敢えずは 11201 それで実行する事にする。と思ったが…うーん。exit に失敗したら元に戻さなけ 11202 ればならないのでは。因みに global の値を取得するのは少々面倒である。 11203 11204 うーん。後 global の TIMEFORMAT を unset する手段がない。取り敢えず既定値 11205 を代入すれば良いのだろうか。既定値は man bash にあったのでそれをそのまま 11206 使う事にした。 11207 11208 2022-02-05 11209 11210 * [棄却] 2022-01-31 nix-build -A の補完が効かないという問題 [#D1764] 11211 https://github.com/akinomyoga/ble.sh/issues/171#issue-1113799687 11212 11213 取り敢えず nix は入れたが nix コマンドや nix-build コマンドは見つかるのだろ 11214 うか。また nix-shell コマンドも使えるのか気になる所である。 11215 11216 動かない。そもそも通常の bash で動くのだろうか。実際に単に source するとエ 11217 ラーが出る。bash-completion を一緒にロードしないといけない様だ。然し結局通 11218 常の bash で実行しても nix-build -A [TAB] で補完がされる事はなかった。 11219 11220 $ bash --norc 11221 $ source ~/.mwg/git/scop/bash-completion/bash_completion 11222 $ source _nix 11223 11224 一体どの様にするのが良いのだろうか。 11225 11226 →これは結局よく分からないが今は動いている様である。手元でもちゃんと動いて 11227 いる事を確認した。向こうの勘違いか或いは他の問題と関係していたかという事だ 11228 ろう。 11229 11230 * 2021-12-18 ble/util/import でファイル名に関数名として許されない文字が入っていた時の対策が必要では [#D1763] 11231 11232 関数名として許されない文字は実はそんなに多くはない気がする。Unicode 文字の 11233 殆どは関数名に使える。特殊な意味を持つのは ASCII の範囲内に限られるからであ 11234 る。 11235 11236 $' \t\n;|&<>()$`"\'\\' 11237 11238 履歴展開文字 !^ に関しては一時的に履歴展開を無効にして関数を定義すれば行け 11239 る気もしないでもないが面倒なので考えない事にする。 11240 11241 特定の文字 (例えば _) に一律に置き換えてしまって衝突は已む無しとするという 11242 事を考えたが、実は % (url) encoding みたいな事をすれば良いのではないかとい 11243 う気がする。但しその為には沢山置換を実行しなければならない。新しい 11244 strreplace は使えない。置換前の文字を直接使える訳ではないので。 11245 11246 | a 直接ハードコードする 11247 | 11248 | a=' ' b=%20 11249 | a=$'\t' b=%08 11250 | a=$'\n' b=%0A 11251 | ... 11252 | 11253 | b 次の様に pack してループを回す。然し何だか変な気がする。 11254 | 11255 | '%25' ' 20' $'\t08' $'\n0A' ';3B' '&26' '|7C' '<3C' '>3E' '(28' ')29' '$24' '`60' '"22' \'27 \\5C 11256 | 11257 | c それよりは個別にした方がすっきりするのではないか。でも対応が分かりにくい。 11258 | 11259 | $'% \t\n;|&<>()$`"\'\\' 11260 | 25,20,08,0A,3B,26,7C,3C,3E,28,29,24,60,22,27,5C 11261 | 11262 | 然しこれならファイル名にこれらの文字が含まれていないかどうかの確認も簡単 11263 | である。改めて文字コード順に並べる事にする。 11264 | 11265 | chars=%$'\t\n !"$&\'();<>\\^`|' 11266 | rep=(%{25,08,0A,20,21,22,24,26,27,28,29,3B,3C,3E,5C,5E,60,7C}) 11267 | rep=(%{25,08,0A,2{0..2},24,2{6..9},3B,3C,3E,5C,5E,60,7C}) 11268 | 11269 | d 或いは次の様にする。 11270 | 11271 | '%':%25 $'\t':%08 $'\n':%0A ' ':%20 '!':%21 '"':%22 '$':%24 '&':%26 11272 | \':%27 '(':%28 ')':%29 ';':%3B '<':%3C '>':%3E \\:%5C '^':%5E '`':%60 11273 | '|':%7C 11274 11275 c の方針で考える事にした。実装した。取り敢えず空白を含むファイル名で試した 11276 ら動いているのでOK. 11277 11278 2022-02-02 11279 11280 * render: 処理途中に WINCH が来ると途中状態のデータに対して処理が走ってデータが壊れる [#D1762] 11281 11282 以下のテスト中に描画の無限ループを検出した。 11283 https://github.com/akinomyoga/ble.sh/issues/173#issuecomment-1028479357 11284 11285 更に色々やっていると tree_node に inconsistency が発生した。というところで 11286 分かった。恐らく描画処理の途中で SIGWINCH が走った所為で、中途半端な状態で 11287 新しい描画が始まる事によってデータを破壊している。処理の途中で描画は実行し 11288 ない様にする必要がある。 11289 11290 特に PROLOGUE と EPILOGUE の間で SIGWINCH が来た時には EPILOGUE の末尾で改 11291 めて再描画を実行する様にする必要があるのではないか。 11292 11293 後、描画処理が終わった後のサイズ変更検知も実行するべきなのかもしれない。と 11294 思ったが、それは実は通常の描画の際にも毎回実行するべき事なのではないか。 11295 11296 * mandb: rsync --no-while-f[TAB] で説明が一緒に挿入されてしまう [#D1761] 11297 11298 DATA を挿入しているのだろうか。。或いは、単一確定の場合に postprocess が走っ 11299 ていなくて直接補完されている。後で確認する必要がある。 11300 11301 →どうやら ACTION progcomp で生成されている様だ。--no-whole-file に対しては 11302 問題発生するが、--whole-file に対しては問題は発生しない。どうも CAND の時点 11303 で大変な事になっている。 11304 11305 →OK. --no-OPTION の説明を勝手に生成した時に mandb_count++ するのを忘れてい 11306 た為に、mandb 処理がスキップされていたのが原因だった。 11307 11308 * complete: fzf と組み合わせている時に補完の再試行がされない問題 (reported by SuperSandro2000) [#D1760] 11309 https://github.com/akinomyoga/ble.sh/issues/171#issuecomment-1021326168 11310 11311 fzf / bash-completion を両方組み合わせている時に ssh_config から読み取ったホスト名が正しく補完されない問題。 11312 11313 | 先ず普通の bash で動く様にするまでが大変だった。取り敢えず以下の順序で初期化すれば動く。 11314 | 11315 | $ bash --norc 11316 | $ source ~/.mwg/git/scop/bash-completion/bash_completion 11317 | $ _ble_contrib_fzf_base=~/.mwg/git/junegunn/fzf 11318 | $ PATH=$PATH:$_ble_contrib_fzf_base/bin 11319 | $ source $_ble_contrib_fzf_base/shell/completion.bash 11320 | 11321 | 然し、同じ順序で ble.sh を初期化したらちゃんと動く。うーん。初帰化の順序に 11322 | 依存するのではないか。 11323 | 11324 | つまり、bash-completion を fzf よりも先に読み込んでいない為に起こっているの 11325 | ではないかと推測されて、例えば ble.sh を bashrc の最初で source していて 11326 | blerc の中で直接 ble-import を実行しているのだとしたら、その場で fzf 11327 | completion.bash が読み取られる。その後で bashrc に戻ってきて 11328 | bash_completion を初期化しているという可能性がある。 11329 | 11330 | 然し instruction では ble-import -d を使う様にお願いしている筈だ。という事 11331 | を考えると bash-completion を bashrc の後で source していても問題は起こらな 11332 | いのではないかという気がするが…。 11333 11334 * done: fzf-completion は bash-completion よりも先に読み込んでおく必要があ 11335 るという事を何処かに記述しておく。 11336 11337 [問題再現] 11338 11339 嗚呼分かった。2回目以降で動くようになるというのは既にちゃんと報告を受けてい 11340 た。そして実際に報告通りに初回は失敗して2回目以降はちゃんと動くという振る舞 11341 いになっている。 11342 11343 [原因] 11344 11345 | これは補完再実行の仕組みに関係しているのだろう→うーん。戻り値 124 を期待し 11346 | ているのにそもそも 124 を補完関数が返さなくなっているのが問題の様に見える。 11347 | 11348 | →うーん。分かった。retry は default completion の時にだけ確認する様にして 11349 | いたが、実は任意の補完についてやり直しが可能という事なのだろう。bash のマニュ 11350 | アルを見ると 124 による再試行は -D と組み合わせると便利とは書かれているが、-D 11351 | と組み合わせた時にしか有効にならないとは書かれていない。つまり、 11352 | is_default_completion でなくても再試行は行うべきである。 11353 11354 fzf completion はロード時に bash-completion を検出した場合、今後の補完で 11355 _completion_loader による補完を呼び出そうとする。初回の _completion_loader 11356 呼び出し時には 124 を返して Bash に対して補完の再試行を要求する。これはどの 11357 コマンドの補完に対しても同様である。 11358 11359 一方で ble.sh は 124 に対する補完の再試行は complete -D による補完の時だけ 11360 しか許さない様になっていた。従って、fzf が予め設定している ssh に対する補完 11361 設定については、いざ _completion_loader によって内部的に bash-completion が 11362 呼び出されて 124 を返したとしても、補完の再試行が行われない。というのが問題 11363 であった。 11364 11365 [過去の関連修正] 11366 11367 | ? これに関係する修正を最近しなかったか。その時の都合で現在の様な実装になっ 11368 | ている可能性がないかについて確認する。 11369 | 11370 | 98835b5a lib/core-complete.sh (Koichi Murase 2021-05-17 14:52:51 +0900 3036) builtin eval '"$comp_func" "$cmd" "$cur" "$prev"' < /dev/null >&$_ble_util_fd_stdout 2>&$_ble_util_fd_stderr; local ret=$? 11371 | 58e1be46 lib/core-complete.sh (Koichi Murase 2020-02-10 00:42:04 +0800 3037) ble/function#pop compopt 11372 | 4df15e1e complete.sh (Koichi Murase 2017-10-12 00:52:41 +0900 3038) 11373 | 4df15e1e complete.sh (Koichi Murase 2017-10-12 00:52:41 +0900 3039) if [[ $is_default_completion && $ret == 124 ]]; then 11374 | 4df15e1e complete.sh (Koichi Murase 2017-10-12 00:52:41 +0900 3040) is_default_completion=retry 11375 | 4df15e1e complete.sh (Koichi Murase 2017-10-12 00:52:41 +0900 3041) fi 11376 | cdd38598 complete.sh (Koichi Murase 2015-11-23 23:58:01 +0900 3042) } 11377 | 11378 | と思ったが該当部分の判定は4.5年間変化していない。つまり、関係ないはず。 11379 | では最近の問題は何だったろうか。 11380 | 11381 | →うーん。fzf で note.txt を検索しても特に何も出てこない。 11382 | 11383 | * 分かった。これだ bash-completion に対する PR の議論だった。 11384 | https://github.com/scop/bash-completion/pull/653 11385 | 11386 | bash-completion も他の補完が設定されている時にそれを呼び出すという処理を 11387 | している。その時に、これまで bash-completion は 124 が返ってきても何もし 11388 | ていなかったのをちゃんと再実行する様に変更するという PR だった。 11389 | 11390 | 結局最近何か処理した気がするというのは bash-completion の話だったので 11391 | ble.sh は関係ない。つまり、現在の実装になっているのには何の理由もないので 11392 | 単純に修正すれば良いのだという結論。 11393 11394 関連する修正があった様な気がしたがそれは bash-completion の話だった。 11395 11396 問題の箇所を実装した時の議論 #D0534 を確認すると、「complete -D による補完 11397 の時に 124 が返されたら再試行」とはっきりと書かれている。つまり仕様を勘違い 11398 していた事になる。 11399 11400 ? 一方で報告によると auto-complete を off にしたら問題が発生しなくなったと 11401 している。不思議だ。うーん。一節には auto-complete でメニューが初期化され 11402 てその中だけで補完しようとする事によって補完内容が減少してしまっている可能 11403 性。然し、auto-complete ではその様な事は起こらないし、或いは表示されている 11404 物に惑わされて補完候補が生成されないと勘違いしている? 11405 11406 と思ったがもう一つの可能性として TAB に独自の auto-complete 用の binding 11407 を付加している可能性もある。うーん。然し過去に SuperSandro2000 そういう議 11408 論を開いた訳でもない。然しそれでも何処かの説明を見て TAB の設定を追加して 11409 いるという可能性はある。 11410 11411 これは取り敢えず向こうの設定が原因になっている可能性があるので後回しで良い。 11412 11413 * complete: / が symlink に対して付加されたり付加されなかったりする (reported by SuperSandro2000) [#D1759] 11414 https://github.com/akinomyoga/ble.sh/issues/171#issuecomment-1021326168 11415 11416 bash-completion なしでも再現する → これは分かった。bind -v で 11417 mark-symlinked-directories が off になっているのが原因だった。元の bash だ 11418 とこれが off になっていたとしても2回 TAB を押したら結局 / を挿入する様だ。 11419 →もう少し調べてみると ins が空の時には mark-symlinked-directories がなくて 11420 も / を挿入するという事らしい。 11421 11422 うーん。元の bash と同じ振る舞いになる様に調整する事にした。これの判定は手 11423 持ちの情報で既にできたのでその様にした。 11424 11425 * term: wt で 描画中のカーソル移動が気になる [#D1758] 11426 11427 flush する時か、或いは描画シーケンス自体にカーソル消去・表示のコードを埋め 11428 込むべきではないか。 11429 11430 一方で現在の表示状態はまた別の箇所で管理していた筈である。うーん。現在のコー 11431 ドだと cursor-state/hidden は描画とは独立に管理している。なので描画に対して 11432 表示・非表示を埋め込もうとすると buffering によって順序が入れ替わっておかし 11433 な事になる。それよりは画面に出力する瞬間に一時的に hidden にするのが良い気 11434 がする。うーん。buffer.flush に介入するのが一番簡単の気がする。怖いので一部 11435 の端末だけで試験的に実行する? と思ったがテストという観点から考えると取り敢 11436 えず全部 on にして試す事にする。 11437 11438 →実装した。取り敢えず変な影は表示されなくなった。それでも何だか点滅してい 11439 る様な気がするが仕方がない事である。contra/screen では特に問題はない。また 11440 mintty でも特に問題は見られない。mintty/tmux でも問題は見られない。これは採 11441 用する事にする。 11442 11443 * 序でに Windows Terminal の identification も実装する事にする。調べるとど 11444 うも hardcode している様に見える。取り敢えずこれに対して判定する。カーソ 11445 ル形状の変更にも対応している様だ。 11446 11447 https://github.com/microsoft/terminal/blob/bcc38d04cef39fe9d939bf5c10bca5e3bd0a9118/src/terminal/adapter/adaptDispatch.cpp#L779-L782 11448 11449 2022-02-01 11450 11451 * util (trap): SIGWINCH を沢山呼び出した後にどんどん重くなる (reported by SuperSandro2000) [#D1757] 11452 https://github.com/akinomyoga/ble.sh/issues/173#issuecomment-1026891422 11453 11454 これは _ble_builtin_trap_postproc を出力したら分かった。trap handler が走る 11455 度にどんどん $_ の中身が長くなっている。 11456 11457 > ble/util/setexit 1 '' 11458 > ble/util/setexit 1 'ble/util/setexit 1 '\'''\''' 11459 > ble/util/setexit 1 'ble/util/setexit 1 '\''ble/util/setexit 1 '\''\'\'''\'''\''\'\'''\'''\''' 11460 11461 この様になっている。先ず、builtin eval の中から $_ を再設定しようとしても 11462 eval に渡した引数が $_ になってしまうという事が問題である。これはどの様にし 11463 たら良いだろうか。一つの方法は eval "postproc" '#' "lastarg" と呼び出すという事。 11464 11465 x postproc に文法的に壊れた物が入っていた時に変な事になるのではないか。と思っ 11466 たが、postproc を設定しているのは trap handler の枠組み自身なのでちゃんと 11467 した物しか入っていないというのは保証される気がする。 11468 11469 x lastarg に改行が含まれている場合には復元できないのではないか。これはどう 11470 しようもない。 11471 11472 というか今回の問題を除いても $?, $_ を正しく復元できている様に見えない。 11473 trap handler の各ケース done, return, break, continue のそれぞれについて 11474 $?, $_ を正しく保存しなければならない。 11475 11476 先ず return/break/continue の時の $? $_ の振る舞いについて確認する必要がある。 11477 11478 $ trap 'break 1' INT 11479 $ for ((i=0;i<1000000;i++)); do ((a++)); done; echo "_=$_" 11480 ^C 11481 _=1 11482 $ trap 'break' INT 11483 $ for ((i=0;i<1000000;i++)); do ((a++)); done; echo "_=$_" 11484 ^C 11485 _=break 11486 11487 この結果を見ると loop の外で $?, $_ を見ることができる。更に言うと break, 11488 continue に渡された引数ですら取得できる。 for (()) は $? $_ を書き換えない 11489 様に見える。 11490 11491 ? break/continue に引数として許される形式は? 普通の整数はOK 負の整数もOK +1 11492 などもOK 少数は駄目だった。空文字列も駄目だった筈。その様な判定にした。 11493 11494 取り敢えず実装してみたが全然正しく復元できていない。 11495 11496 x fixed: 次に setexit が結局 $_ に設定されてしまっている。何故。と思ったら 11497 '#' が本当に # になってしまっていた。これは直した→すぐに動く様になった。 11498 11499 x fixed: 先ず $_ で取得した lastarg には gexec に使った begin ... end が入っ 11500 ている。これはそのままでも良いのかもしれないし、或いはコマンド実行中かそ 11501 うでないかで振る舞いを変更するべきなのかもしれない。コマンド実行中でない 11502 時にはユーザートラップを呼び出す前に復元してユーザートラップを呼び出した 11503 後に保存する? 11504 11505 % 或いはそもそも保存しなくても良い気がする。本来 trap が別のコマンドに影響 11506 % を与えるというのも変な話である。→と思ったが或る handler の影響は次の 11507 % handler に残っていて欲しい気もする。つまり、ユーザーコマンドに影響が残る 11508 % のは変な気がするが一方で同じ handler の間で $?, $_ がちゃんと保持されてい 11509 % なければ変だという事。やはり保存するべきの様な気がしてきた。 11510 →ユーザートラップによって変更された $_ はちゃんと反映させるべきの気がする。 11511 →うーん。結局トラップ専用の lastarg,lastexit 変数に記録する事にした。 11512 11513 x おまけで ble/dispatch のモード判定にミスを発見した。修正した。 11514 11515 取り敢えず制限はあるがこれで大丈夫の筈。 11516 11517 2022-01-24 11518 11519 * edit: コマンド実行時間計測 [#D1756] 11520 11521 前から気になっていたので実装する。 11522 11523 * time を用いた計測? 少なくとも msec の精度は存在する。prologue にかかる時 11524 間などは気になるが。prologue は含めずに計測するのが良いだろう。 11525 11526 11527 現在の gexec の構造を何処まで変更できるかについて確認しなければならない。 11528 現在の構造に修正したのは 014d17e6 (#D0465)である。うーん。eval を跨ぐと 11529 $_ が継承されない? と思ったが prologue に関しては同じ eval に入れなくても 11530 大丈夫に見える。以下のコマンドを各 bash version で試したがちゃんと動いて 11531 いる。 11532 11533 $ { echo hello world; time builtin eval 'echo "[$_]"'; echo $_; } 11534 11535 うーん。分かった。prologue を同じ eval の中に入れるのは set -v の時の出力 11536 を最低限に抑える為である → 書き換えた。一応ちゃんと $_ 及び $? が復元で 11537 きている事を確かめた。 11538 11539 うーん。ble/util/clock だとか ble/bin/date +%s%6N だとかに頼る方法を考えて 11540 いたが、time の結果を読み取っている現状では tot をそのまま参照すれば良い気 11541 がする。開始時刻に関しては date または printf または SECONDS を用いて取得す 11542 れば良い → 最終的にはやはり ble/util/clock または date +%s%6N に頼る事にし 11543 た。それを tot を用いて補正する。 11544 11545 * SECONDS, EPOCHREALTIME, EPOCHSECONDS を readonly するという事? EPOCH* に 11546 ついては流石に間違えて上書きしたりする事はないと思われる。SECONDS は 11547 ble/util/clock の初期化時に readonly する事にした。EPOCHSECONDS はどうせ 11548 使っていないので関係ない。 11549 11550 * done: カスタマイズインターフェイスについて考えた方が良い気がする。現状で 11551 既存の errexit とどうくっつけるのかというのが問題である。というより、本当 11552 は色分けをしたりしたい所だが、現状 errexit の設計が固定文字列になっている 11553 ので、勝手に弄る余地がなくなってしまっている。 11554 11555 或いは既定値の時にはくっつけるという操作をするというのでも良いかもしれな 11556 い? と思ったがそれも変である。或いは、もっと別枠の設定を用意するというの 11557 も手なのかもしれない→うーん。両方とも無効化して自前で書くというのが良い 11558 気がする。という事を考えたら、現状では exec_errexit_mark と同様に 11559 exec_elapsed_mark を定義すれば良い。 11560 11561 * done: contrib README.md 11562 * done: ChangeLog 11563 * done: blerc: new bleopts 11564 * done: wiki: new bleopts 11565 11566 x 外部コマンドの時間が計れていない? と思ったが単に cxxmatrix に対して端末が 11567 遅いだけなのであった。多分測れている。子シェルを合計するかしないかの設定 11568 があった気がしたけれど、それは多分 times であって関係ないのだ。一応 times 11569 を使えば real 及び sys の子プロセスの内訳も見られる気がする…が BG で動い 11570 ている物が加算されるのかは謎である。 11571 11572 →うーん。times はジョブが終了した瞬間に加算されるので、bg のジョブが丁度 11573 終了したりすると、現在実行しているコマンドの shell/sys の値を評価できなく 11574 なる。そもそも time で取れている情報の筈なので関係ない気もする。。と思っ 11575 たが、シェル本体と子プロセスの時間を区別するのには使えるのかもしれない。 11576 つまり自プロセスの処理時間を取得するのには使える。 11577 11578 x EOF marker が動かなくなっている。確認する必要がある。と思ったがこれは単純 11579 に 2 が /dev/null に繋がっていたというだけの話だった。OK 11580 11581 * edit: bind -x 関数の呼び出しに際しての画面クリアの振る舞いについて (motivated by SuperSandro2000) [#D1755] 11582 https://github.com/akinomyoga/blesh-contrib/issues/6#issuecomment-1020165711 11583 11584 GNU readline は 4.4 で振る舞いを変更した様だ。それ以前はただ単純に現在の編 11585 集位置にカーソルを置いたまま bind -x の関数を呼び出していた。4.4 以降ではプ 11586 ロンプトの終了点・編集文字列の開始点の行にカーソルを置いて bind -x の関数を 11587 呼び出す様になった様だ。実は 11588 11589 https://github.com/junegunn/fzf/issues/490#issuecomment-184402254 11590 11591 でもその事が説明されている気がする (何が書かれているかちゃんとは見ていない 11592 が)。というよりこの振る舞いについては前にも議論した事があるような気がする。 11593 →うーん。#D0915 (90ca3bea) の最後の動作確認の所で微妙に言及しているだけで 11594 ある。これ以降は .hide-current-line も対して更新されていないし振る舞いにつ 11595 いては変更はなかったと思われる。その時は手元で試して振る舞いを決定した気が 11596 するが詳細については記録に残っていないという事。 11597 11598 * patsubWA: compat42 での振る舞い [#D1754] 11599 11600 それとは別に compat42 の効果についても考察する必要がある。compat42 の時には 11601 結局問題が生じるのではないだろうか?? quote しても無駄である。という事を考え 11602 ると compat42 の時は単純に実装を切り替えるというのは動作しない。とは言いつ 11603 つ惨事を防ぐ為にはやはり配慮が必要である。 11604 11605 * patsubWA: bash-dev で \q{} が動かない [#D1753] 11606 11607 うーん。これも patsub が原因の気がする。或いは bash-dev の振る舞いの変化に 11608 よって引き起こされている? 取り敢えず調べる → やはり patsub WA によって動か 11609 なくなっている。bash 側の振る舞いの変化による物ではなかった。 11610 11611 実際の動作を調べる。先ずそもそも \q{} が呼び出されているのか? うーん。呼び 11612 出されていない。つまり @P による展開になってしまっているという事だろうか → 11613 否、@P による展開にはなっていない。 11614 11615 うーん。どうやら \q{} はいつの間にかに \\q{} に変換されてしまっている様子。 11616 何故だろうか。うーん。bleopt_prompt_rps1 の値の時点で \\q{} になってしまっ 11617 ている。つまり、bleopt が悪い。 11618 11619 うーん。引数読み取りの時点で駄目になっている。 11620 11621 $ ble/array#push specs "${var[@]/%/"=$value"}" # #D1570 #D1751 WA checked 11622 $ ble/debug/print-variables var value specs |& cat -v >/dev/tty 11623 var=('bleopt_prompt_rps1') value='\q{blerc/rps1}' specs=('bleopt_prompt_rps1=\\q{blerc/rps1}') 11624 11625 うーん。不思議だ。bash-5.2 のバグだろうか。うーん。これはバグである。という 11626 か /% 等の様にパターンが空の時には escape は処理されないのである。 11627 11628 $ var= rep='&'; echo "${var/%/"$rep"}" 11629 11630 うーん。Bash に報告しようと思ったが思ったよりも複雑である。続きは 11631 bug-report/bash/report31 で議論する事にした。取り敢えず patch は作った。最 11632 終的にどうなるかは分からないが取り敢えずは patch 付きでコンパイルしていれば 11633 今の ble.sh の実装で大丈夫のはず。 11634 11635 * patsubWA: bash-4.3 で \$ になる [#D1752] 11636 11637 これもつい最近までは見られなかった問題である。bash-3.0 迄影響を受けている。 11638 これも patsub_replacement 対策が悪さをしていると見える。 11639 11640 % うーん。_ble_prompt_const_root を出力している箇所から既に問題が起こっている 11641 % 気がするが、_ble_prompt_const_root の値は昔から変わらず "\$" だった様だ。 11642 % 然し、patsub 修正よりも前にはちゃんと単一の $ になっていた。 11643 % 11644 % $ declare -p _ble_prompt_const_root 11645 % declare -- _ble_prompt_const_root="\$" 11646 % 11647 % →これは declare の出力の quote であって、_ble_prompt_const_root の値自体 11648 % は常に単一の '$' だった。 11649 11650 というよりそもそも ble/prompt/print は $ を解釈しないのではなかったのか。だ 11651 とすれば \$ の様にする意味がない。うーん。つまり以前の実装が間違っていたと 11652 いう事。 11653 11654 うーん。分かった。確かに以前の実装は間違っている。escape-characters に渡す 11655 文字集合は '$\`"' ではなく '\$`"' でなければならない。つまり一番最初に '\' 11656 を置換しなければ他の文字の置換結果の '\' も二重に置換してしまう事になる。こ 11657 の様な実装に切り替えたのは patsub の事だと思ったが 11658 11659 % よく考えたらそれよりも前から二重のバグによってたまたま動いていただけに過 11660 % ぎない → これも勘違い。以前は '$' を正しく quote して正しく最終的に '$' 11661 % になっていた。 11662 % 11663 % | function ble/prompt/print { 11664 % | - local text=$1 a b 11665 % | - if [[ ! $prompt_noesc && $text == *['$\"`']* ]]; then 11666 % | - a='\' b='\\' text=${text//"$a"/$b} 11667 % | - a='$' b='\$' text=${text//"$a"/$b} 11668 % | - a='"' b='\"' text=${text//"$a"/$b} 11669 % | - a='`' b='\`' text=${text//"$a"/$b} 11670 % | - fi 11671 % | - ble/canvas/put.draw "$text" 11672 % | + local ret=$1 a b 11673 % | + [[ $prompt_noesc ]] || 11674 % | + ble/string#escape-characters "$ret" '$\"`' 11675 % | + ble/canvas/put.draw "$ret" 11676 % | } 11677 % 11678 % と思ったがこの編集を見ると以前はちゃんと動いていた筈なのである。という事は、 11679 % 先ず初めに '\$' が \\\$ になって、更に評価時に \$ になる筈。不思議である。 11680 % うーん。以前は \$ は \\\$ になって、更に評価された時に \$ になるという仕組 11681 % みだった筈。 11682 11683 何れにしても問題の部分を修正したらちゃんと動く様になった。 11684 11685 % 然し何故これで動くのかは未だに謎である。うーん。何故? 11686 % 11687 % →ずっと遡っていくと実はずっと単一の '$' である。。そして 11688 % _ble_prompt_const_root も単一の '$' である。declare の出力が double 11689 % quoted だから \$ と表示していたけれども実は単一の $ だったという事である。 11690 % つまり勘違いだった。 11691 11692 結局これで万事大丈夫になった。 11693 11694 * patsubWA: bash-4.2 で文法エラーが発生する (bind.delay 周り) [#D1751] 11695 11696 何と、bash-4.2 では "${var//xx/"yy"}" の " は literal になる。テストで検出 11697 された物を少し修正したが他にも沢山ありそうだ。 11698 11699 $ grc '"[^"]*\$\{[[:alnum:]_]+(\[[^][]*\])?//?([^{}]|\{[^{}]*\})+/[^{}"'\'']*"[^"]*([&$]|\\)' --exclude=./test 11700 done: ./keymap/vi_test.sh:44: ble/util/print " initial = \"$i:${in//$nl/"$NL"}\"" 11701 done: ./keymap/vi_test.sh:45: ble/util/print " expected = \"$f:${fin//$nl/"$NL"}\"" 11702 done: ./keymap/vi_test.sh:46: ble/util/print " result = \"$_ble_edit_ind:${_ble_edit_str//$nl/"$NL"}\"" 11703 done: ./lib/core-complete.sh:3432: [[ $progcomp_prefix ]] && cands=("${cands[@]/#/"$progcomp_prefix"}") # WA #D1570 safe 11704 done: ./lib/core-syntax.sh:4414: b='\`' a='`'; str="${str//"$b"/"$a"}" 11705 done: ./lib/core-syntax.sh:4415: b='\"' a='"'; str="${str//"$b"/"$a"}" 11706 done: ./lib/core-syntax.sh:4416: b='\$' a='$'; str="${str//"$b"/"$a"}" 11707 done: ./lib/core-syntax.sh:4417: b='\\' a='\'; str="${str//"$b"/"$a"}" 11708 done: ./lib/core-syntax.sh:4453: a=\\ ; b="\\$a"; ret="${ret//"$a"/"$b"}" 11709 done: ./lib/core-syntax.sh:4454: a=\' ; b="\\$a"; ret="${ret//"$a"/"$b"}" 11710 done: ./lib/core-syntax.sh:4455: a=' ' ; b="$_ble_syntax_bash_heredoc_EscSP"; ret="${ret//"$a"/"$b"}" 11711 done: ./lib/core-syntax.sh:4456: a=$'\t'; b="$_ble_syntax_bash_heredoc_EscHT"; ret="${ret//"$a"/"$b"}" 11712 done: ./lib/core-syntax.sh:4457: a=$'\n'; b="$_ble_syntax_bash_heredoc_EscLF"; ret="${ret//"$a"/"$b"}" 11713 done: ./lib/core-syntax.sh:4458: a=$fs ; b="$_ble_syntax_bash_heredoc_EscFS"; ret="${ret//"$a"/"$b"}" 11714 done: ./src/util.sh:118: ble/array#push specs "${var[@]/%/"=$value"}" # #D1570 WA checked 11715 done: ./src/util.sh:777: ARR=("${ARR[@]::$2}" "${sARR[@]/#/"$4"}" "${ARR[@]:$3}")' # WA #D1570 checked 11716 done: ./src/util.sh:1138: a='!' b='"\!"' ret=${ret//"$a"/"$b"} 11717 done: ./src/util.sh:1165: a=$'\n' b="\$'\n'" ret=${ret//"$a"/"$b"} 11718 done: ./src/util.sh:1401: builtin eval -- "${_ble_local_script//opts/"$1"}" 11719 done: ./src/util.sh:1405: builtin eval -- "${_ble_local_script//opts/"$1"}" 11720 done: ./src/util.sh:1413: builtin eval -- "${_ble_local_script//opts/"$1"}" 11721 done: ./src/util.sh:1421: builtin eval -- "${_ble_local_script//opts/"$1"}" 11722 done: ./src/util.sh:1574: ret=("${ret[@]//$_ble_term_FS,/"$_ble_term_FS"}") # WA #D1570 checked 11723 done: ./src/util.sh:5371: ble/util/put "${_ble_term_visible_bell_show//'%message%'/"$sgr$message"}" >& 11724 11725 取り敢えず全て修正した。一応動作はしている。 11726 11727 * prompt: wezterm shell-integration が PRECMD で何かを出力するがずれる [#D1750] 11728 11729 先ず precmd を呼び出す瞬間のカーソル位置が前回のプロンプトの後になっている 11730 ので、この時点でずれが生じる。これは bash に倣って次のプロンプトの最初にカー 11731 ソルを移動してから呼び出すべきという事なのだろうか。 11732 11733 x ok: 次に、precmd の直前で flush する様にしても座標位置がずれてしまう。特 11734 にコマンドを実行した直後の状態が怪しい。これは別の dock にいたりする事が 11735 原因なのだろうか。。と思ったが、うーん→これは分かった。info を表示してい 11736 る為に内部座標原点にいないのが原因であった。内部座標原点に移動してから 11737 flush したら、表示位置がずれる問題は解決した。 11738 11739 x 然し依然として precmd の中から出力した事自体によってずれが生じる問題につ 11740 いてはそのままである。うーん。info を表示するよりも前に precmd は実行する 11741 べきという事なのだろうか。 11742 11743 ? ok: そもそも precmd と prompt_command は分けて考えるべきなのかもしれない。 11744 11745 コマンド実行ではなくて別の理由で (SIGWINCH などで) プロンプトの再計算が走 11746 る場合に本当に precmd や PROMPT_COMMAND も一緒に呼び出してしまって良いの 11747 かというのも疑問である。端末サイズに応じてプロンプトを更新したいという事 11748 を考えれば PROMPT_COMMAND は WINCH に対して改めて実行したほうが良い気もす 11749 る。然し、PRECMD の意味を考えたら本当にコマンド入力を開始した時にだけ呼び 11750 出したい様な気もする。然し、コマンド入力を開始したい時はやはり 11751 PROMPT_COMMAND なのではという気もする。 11752 11753 その様に色々考えると PROMPT_COMMAND と一緒に実行する現在の設計で問題ない 11754 気もする。そして SIGWINCH でも呼び出して良い。前のプロンプトを捨てて新し 11755 いプロンプトを構築すると考えれば良い。 11756 11757 * ble/prompt/update の呼び出しはより外側に移動しても良いのではないか。 11758 11759 うーん。然し leave in opts のテストがある。これは textarea#render に渡さ 11760 れる引数である。呼び出し元は以下の二箇所。何れも 11761 ble/widget/.insert-newline からの呼び出しである。 11762 11763 ./src/edit.sh:5713: ble/textarea#render leave 11764 ./src/edit.sh:5724: ble/textarea#render leave 11765 11766 うーん。leave の時には改めてその場で ble/prompt/update を呼び出す。少し書 11767 き換えてみる。 11768 11769 実装してみたは良いがよく考えたら現在の実装だとプロンプトの更新が滞る。 11770 11771 * main: /dev/tty が割り当てられていない時にも ble.sh は初期化しない [#D1749] 11772 https://github.com/oilshell/oil/issues/1069#issuecomment-1017189089 11773 11774 Docker でロードしようとしている時に失敗する。 11775 11776 後、--test や --update 等の時には通常コマンドとして動作するので様々のチェッ 11777 クを無視して良い。更に言うとそもそも /dev/tty から端末を取得しようとする事 11778 自体が不要である。取り敢えずその様に実装した。 11779 11780 * canvas: wezterm で DECSTBM のクリアに失敗している [#D1748] 11781 https://github.com/akinomyoga/ble.sh/issues/96#issuecomment-1019570983 11782 11783 kitty もそうだったが \e[;r では DECSTBM をクリアできない模様。 11784 DECSTBM と同様にその場で端末をテストする事にした。修正した。 11785 この問題については解決した。 11786 11787 2022-01-23 11788 11789 * main: IN_NIX_SHELL をチェックする (reported by SuperSandro2000) [#D1747] 11790 https://github.com/akinomyoga/ble.sh/issues/169#issuecomment-1019405936 11791 https://github.com/akinomyoga/ble.sh/issues/169#issuecomment-1019555462 11792 11793 取り敢えず IN_NIX_SHELL をチェックする事にした。 11794 11795 またチェックは rshell やその他のチェックよりも先に行うべきである。特に最初 11796 にエラーメッセージなしで抜けるのであれば、それは他の条件でエラーメッセージ 11797 が表示される前に一番最初にチェックするべきなのである。 11798 11799 * util: _ble_term_TERM が空になっている問題 [#D1746] 11800 11801 mintty で _ble_term_TERM が空になっている。何故か。unknown が設定されるので 11802 はないか。ちゃんと DA2R は受信できている。そして passthrough seq がちゃんと 11803 動いていない in screen. これは修正する必要がある→確認したら物凄く単純なミ 11804 スをしていた。これは恐らく置換か何かをした時の残りであろう。 11805 11806 * 折返しがある時に実際に端末に改行が挿入される (reported by banoris) [#D1745] 11807 https://github.com/akinomyoga/ble.sh/issues/170 11808 11809 これは元々は途中の列で折り返しをする為 (例えば prompt_rps1 の為) に導入した 11810 振る舞いだが、確かに報告にある様にコピー・ペーストしたいという場合もある。 11811 端末の全幅を使っている時には折返しの改行は明示的に挿入しない様にするべきな 11812 のではないか。 11813 11814 全角文字が収まり切らない時に端末がどの様に振る舞うかについても何か仮定を置 11815 かなければならない。折返しの位置で改行は挿入しない。 11816 11817 * うーん。全角文字が入り切らない時に挿入する空白は其処に元々存在した文字を 11818 消去して空白で上書きするという意味合いもあった。という事を考えると、実は 11819 ECH で代替できるのではないか。実は ECH を実行したとしても空白になってしま 11820 う端末も存在するだろうし、末尾の空白は空白とみなさない端末もあるだろうし 11821 実装は色々だろう。 11822 11823 * 改行が挿入されるのが駄目という事であれば一旦 CR で先頭に移動してから LF 11824 を実行すれば良いのではないか? と考えたが多分そういうことじゃない。状況は 11825 逆で、既定では別の独立した行になっていて、然し折返しがあった時に限り2つ 11826 の行を接続するという振る舞いになっているのだと思われる。 11827 11828 という事を考えるとやはり末尾で折返しを発生させる必要があるのである。 11829 11830 ? rps が存在する時は relative になっているだろうか。うーん。xenl のない端末 11831 では改行を挿入していないという事を見ると、改行は挿入しなくてもちゃんとそ 11832 の場で折返しが発生するという事は想定している。 11833 11834 →確認したら実際に rps1 が存在している時には relative になっていた。 11835 11836 [[ $rps1_enabled ]] && render_opts=relative 11837 11838 という事は relative でなければ常に全幅になっているという事を想定して良い 11839 様に思われる。 11840 11841 ? slice してから出力した後のカーソル位置が予測不可能になるのではないか。全 11842 体を一気に出力する場合には次に文字があるかどうかで自動折返しが発生するか 11843 どうか分かる。自動折返しが発生しない時に限り改行を挿入すれば良い。然し部 11844 分更新をしている時には自動折返しが発生しない可能性が常に存在する。その時 11845 に座標が不定になってしまう。直後に行う操作 (CUU) 等によって端末に依って異 11846 なる結果になってしまう。うーん。 11847 11848 というか此処まで来ると bash だってちゃんと動作しているかどうか怪しい物で 11849 ある。然し、readline の場合には基本的に着色はないので、文字の内容は変わら 11850 ないのに色だけ部分的に更新するという事もないのだろうと予想する。なので問 11851 題が発生するケースは存在しない。 11852 11853 ? うーん。何と説明するか。全角折返しの空白や改行の挿入は端末の違いを吸収す 11854 る為に必要だという事を説明する? でも既存の readline は問題を起こしていな 11855 い。しかしそれは着色をしていないので部分更新でも必ず折り返しは発生するか 11856 ら。 11857 11858 うーん。折返しを起こしてかつ後続の文字に干渉しない様な方法というのは存在 11859 するのだろうか。。うーん。存在しない気がする。だとすると、新しく slice 終 11860 端禁止点の様な物を導入して slice をする時には範囲を拡張するという具合にす 11861 る必要がある気がする。うーん。そういう方法しか存在しないだろうか。。。 11862 11863 a 後続の文字によって自動折返しが期待できる時には改行は挿入しない。 11864 11865 slice 禁止点の情報を記録する (実は既に grapheme cluster によって類似の仕 11866 組みが備わっていないのか)。 11867 11868 xenl の端末とそうでない端末でちょうど行末に改行があった場合の振る舞いが変 11869 化するのではないか。それは大丈夫なのだろうか。或いは丁度行末にいる時に改 11870 行を実行する時には二重改行を挿入する? うーん。 11871 11872 →色々考えたが b の方針に比べると考えなければならない事が多すぎる。これは 11873 やはり棄却する。 11874 11875 b 一括出力時に自動折返しの改行文字は削除する。その為には自動折返しの改行文 11876 字として特別な文字を使う。例えば \r は ^M と encode されるので本来は 11877 textmap の中に含まれる事はないと思って良い。 11878 11879 slice する際にまた \r を元に戻す処理をするのが良い気がする。うーん。この 11880 方針で行くのが一番安心の気がする。 11881 11882 ? 丁度行末で改行がある場合の動作? 11883 11884 この方針の際に丁度行末に改行がある場合はちゃんと動作するのだろうか。つ 11885 まり一番最後の文字の末尾に \r があって、それから次の文字の改行が \n と 11886 して来る。この時に slice 後の置換によって内部の \r は削除されてしまうの 11887 で単一の \n になってしまう。うーん。これは駄目だ。一方で \n\n にしたら 11888 良いのかと聞かれるとそれも何だか違う気がする。つまり改行が二重に複製さ 11889 れてしまう。うーん。然し、これは表示される時の表示と実際の内容のずれと 11890 して仕方がないのではないかという気がする。\n\n にするしかない。 11891 11892 一応自動折返し位置に改行がある時に readline がどう表示するのかについて 11893 は確認する事にする。内容は一個の改行だけれども、コピーすると二個の改行 11894 に増えている。やはりこれは仕方がないのだという気がする。 11895 11896 後は _ble_textmap_glyph を触っている所を全て確認すれば良い。うーん。この 11897 配列自体は ble/textarea#update-text-buffer からしか参照されていない様に見 11898 える。うーん。然しそれは変だ。と思ったが、やはりそれで良いのだ。というの 11899 も、通常の文字の端末上の表示は常に同じだからわざわざ textmap を参照する必 11900 要もないのである。最終的に "変更文字" である物だけ置き換えれば良いのであ 11901 る。そして実際自動折返しが発生している物については changed がマークされて 11902 いる。よってこの時点で _ble_textarea_buffer に反映されるのである。 11903 11904 _ble_textarea_buffer を参照している箇所は以下しかない。 11905 11906 ./src/edit.sh:2559: IFS= builtin eval "ret=\"\$ret\${$_ble_textarea_bufferName[*]:i1:i2-i1}\"" 11907 11908 → b の方針で実装した。動いている気がする。 11909 11910 x 2022-01-23 動いていると思ったら勘違いだった。丁度行末に改行がある時に座標 11911 がずれてしまう。何かと思ったら \r\n を \n\n に置換しようという所で、間に 11912 SGR がある為に置換しきれていないのが原因の様である。 11913 11914 うーん。これはどうしたら良いのか。単純な置換だと無理の気がする。或いは間 11915 に来る SGR が既知であれば固定文字列として置換する事もできる。。と思ったが、 11916 そもそも不特定の \r\n の組を対象にして一括置換しようとしているのだから、 11917 固定文字列になっている筈がない。うーん。間に入るのは単一 SGR なのだろうか 11918 →実装を確認した所 sgr 決め打ちである。という事であれば extglob さえ使え 11919 ば置換はできる…と思ったが置換後が固定文字列になってしまうので駄目である。 11920 11921 うーん。という事を考えるとやはり正規表現で \r を一つずつ一致させて処理す 11922 るしか無いのだろうか→うーん。その様にして実装した。CSI seq, ESC seq, 及 11923 び SI SO を跨いで改行を検出する様にした。 11924 11925 2022-01-21 11926 11927 * bash-preexec に本格的に介入する事を考える事にする (motivated by SuperSandro2000) [#D1744] 11928 https://github.com/akinomyoga/ble.sh/issues/96#issuecomment-1016401487 11929 11930 1. bash-preexec の機能を on/off する方法を探す。 11931 特に off にしている時には DEBUG trap は削除する様になっていて欲しい。 11932 11933 そもそも __bp_install で一体何をしているのか等についてもちゃんと確認する 11934 必要がある。以前調べた感じだと PROMPT_COMMAND が他の枠組みに上書きされて 11935 も大丈夫な様に DEBUG を使って実際の登録を行う仕組みになっていた筈である。 11936 11937 2. bash-preexec の機能を PRECMD / PREEXEC で再現できる様にする。 11938 11939 PIPESTATUS を保存する → BLE_PIPESTATUS に記録する事にした。各 hook の中 11940 からはこれを参照すれば最後のコマンドの PIPESTATUS を取得できるという事を 11941 wiki にも書く。該当する hook は PRECMD, PREEXEC, POSTEXEC, ERR である。何 11942 故か CHPWD は該当しない。 11943 11944 * そもそも現状の ble.sh に於いて、最初に bash-preexec をロードして置いて、 11945 後から source ble.sh を実行すると preexec 用の DEBUG trap が削除されてし 11946 まっている。 11947 11948 この振る舞いについてちゃんと調べて解決する必要があるのではないだろうか。 11949 11950 * done: 取り敢えず ble.sh の側で対策を実装する事にする。もし bash-preexec 11951 に適切な API があったとしてもなかったとしてもちゃんと動く様にする。 11952 11953 ble.sh の側で実装するとなると何処かのタイミングで bash-preexec を検出しな 11954 ければならない。元から bash-preexec が存在している場合にはそのまま検出で 11955 きる。後から bash-preexec が読み込まれた時にどの様に対処したら良いのかは 11956 非自明である。 11957 11958 a 一つの方法は precmd_functions 辺りに何か仕掛けておくという事。然し、 11959 bash-preexec が実際に読み込まれるかどうかも分からないのに汚染はしたくな 11960 い気がする。 11961 11962 b だとすると POSTEXEC 辺りで bash-preexec 特有の関数が定義されていないか 11963 どうかチェックするという事になる気がする。これは overhead であるが、ま 11964 あ特に重い処理でもない気がするので気にしなくて良い。 11965 11966 どの様に実装するのかというのも気になる。外部プラグインとして実装するのか 11967 ble.sh 本体に埋め込んでしまうのか。取り敢えず外部プラグインとして実装して 11968 置いて、後で本体に組み込むかどうか決定するのが良い気がする。 11969 11970 →contrib/bash-preexec に実装した。更に読み込み用のコードを ble.sh に埋め 11971 込む事にした。 11972 11973 [テスト] 11974 11975 * テストの方法 11976 11977 ロードの順序や attach の方法など色々考えられる。それらについて全部動作確 11978 認するべきの気がする。以下の場合を確かめる。 11979 11980 % - bash-preexec bashrc / interactive 11981 % - ble.sh (bashrc / interactive) x (prompt / attach) 11982 % - どちらを先に source するか。 11983 % - 両方 interactive の時には同じコマンドの中で source するかどうか。 11984 % - bash-it bashrc / interactive 11985 11986 まとめると以下のロードの組み合わせが存在する。 11987 11988 - done: bp blesh.prompt $ 11989 - done: bp blesh.attach $ 11990 - done: bp $ blesh.prompt 11991 - done: bp $ blesh.attach 11992 - done: $ bp $ blesh.prompt 11993 - done: $ bp $ blesh.attach 11994 - done: $ bp blesh.prompt 11995 - done: $ bp blesh.attach 11996 - done: blesh.prompt bp $ 11997 - done: blesh.attach bp $ 11998 - done: blesh.prompt $ bp 11999 - done: blesh.attach $ bp 12000 - done: $ blesh.prompt $ bp 12001 - done: $ blesh.attach $ bp 12002 - done: $ blesh.prompt bp 12003 - done: $ blesh.attach bp 12004 - done: bash-it $ 12005 - done: $ bash-it 12006 - done: 更に detach した後もちゃんと動くかも確認する 12007 12008 x done: 初回の実行時に trap DEBUG が残っている場合が存在する。特に bp が後 12009 にロードされた時にこれが起こる。後に bp がロードされた時には POSTEXEC で 12010 処理をしているのだから仕方がない。それよりも前の時点で検出する方法はない 12011 のだろうか→というか全パターンで trap DEBUG が初回実行で残ってしまってい 12012 る。これは何が悪いのだろうか。恐らく最初の PROMPT_COMMAND でから install 12013 string を削除できていない。 12014 12015 と、ここで理由が分かった。そもそも contrib/bash-preexec が POSTEXEC から 12016 しか自動ロードされていない。ATTACH 及び ble.sh ソース時にもチェックするべ 12017 きである。 12018 12019 x ok: "bp blesh.attach" 及び "$ bp blesh.attach" に於いて初回のコマンド実行 12020 では未だ contrib/bash-preexec による調整が有効になっていない。但し、動作 12021 に関しては問題ない。これはまあ仕方がないのだろうという気がする。 12022 12023 DEBUG 周りを色々と修正し直す事にした。幾らか弄ったら色々動かなくなった。 12024 12025 x resolved: C-c した時に変なエラーメッセージ (return に空の引数が渡されて 12026 いる) が発生している。これは一体何だろうか。うーん。bash --norc, source 12027 out/ble.sh --norc でも発生する。一旦発生するとその後もずっとコマンドを 12028 実行する度に発生している気がする。 12029 12030 x resolved: C-c で実行をキャンセルできていない→これは正規表現の編集をミ 12031 スして正規表現が不正になっていた。修正した。直った。 12032 12033 * done: ble/builtin/trap/invoke と ble/builtin/trap/invoke+ を統合する。 12034 ble/builtin/trap/invoke+ はもっと単純な戻り値に外で実行するべきコマンド 12035 を出力する。 12036 12037 x resolved: detach した後に TRAPDEBUG が設定されていない。うーん。trap - 12038 DEBUG を実行した時点で builtin trap DEBUG が設定されるべきなのにされない 12039 という問題である。 12040 12041 これは実際に builtin trap DEBUG がされていないのか、或いは実際している 12042 けれどもそれが関数呼び出しの為に途中で消えてしまっているのかどちらなの 12043 だろうか。動作を確認する事にする。 12044 12045 →どうやら _ble_edit_exec_TRAPDEBUG_enabled によって明示的に無効化され 12046 ている様に見える。これは元々何の為の判定だろうか。gexec の中か外かで振 12047 る舞いを変えている様子である→分かった。ble.sh の内部にいる時に即座に 12048 DEBUG trap を有効にすると ble.sh の中で DEBUG が大量に走って不都合とい 12049 う事。 12050 12051 % そういう事であれば _ble_edit_exec_TRAPDEBUG_enabled=1 にする瞬間に 12052 % trapdebug を実行するのが妥当なのではないだろうか。。→と思ったら既に 12053 % ble-edit/exec:gexec/.TRAPDEBUG/enter に於いて TRAPDEBUG をちゃんと実 12054 % 行していた。 12055 12056 そもそも ble-detach した時に _ble_edit_exec_TRAPDEBUG_enabled=1 に最終 12057 的になるのかもよく分からない → 調べてみると空のままの気がする。detach 12058 の際に直接 trapdebug を設定すれば良いのではないだろうか。。と思ったがそ 12059 ういう訳でも無い様な。 12060 12061 % →これは単なる変数名の変更漏れだった。修正した。 12062 12063 うーん。detach の際に ble-edit/exec:gexec/.TRAPDEBUG/enter を実行すれば良 12064 い気がする。 12065 12066 →これはちゃんと動く様になった。また detach した後でも INT が残っていて悪 12067 さをする問題に関しては、TRAPINT で return || break を実行して抜けられる様 12068 にする事にする。 12069 12070 * [保留] "for ((i=0;i<10;i++)); do sleep 1; done" で C-c すると変な事になる。 12071 これは元から動いていなかった物なので今新しく動かなくなったという訳ではな 12072 い。 12073 12074 →うーん。どうもこれは sleep が sigint で終了した時には、bash は trap 12075 handler は起動せずに完全に実行全体を終了してしまうみたいである。 12076 12077 $ trap 'echo TRAPINT' INT 12078 $ for ((i=0;i<10;i++)); do sleep 1; done 12079 ^C 12080 $ 12081 12082 この様に trap が発動する事無く即座に終了してしまう。特に ble.sh の中から 12083 実行する際には実行が完全に終了した後も端末ハンドラーの設定がそのままになっ 12084 ているので、新しいユーザーの入力も RET が来るまでは受け取れないという状態 12085 になってしまっている。これは仕方がない。 12086 12087 * done: wiki trap debug 更新 12088 12089 * done: SIGINT message をもっと見やすく。これはこんな物だろう。 12090 12091 * done: wiki に BLE_PIPESTATUS を記述する。 12092 12093 取り敢えずコミットを作ってしまって良い気がする。 12094 12095 * done: 後は contrib を修正する。 12096 12097 * done: PRECMD は PROMPT_COMMAND よりも前に実行するべき。元々どちらでも良かっ 12098 たが、bash-preexec が最初に実行する様になっているのでそれに倣う。 12099 12100 * global: protect overridden builtins against "set -eu" (reported by SuperSandro2000) [#D1743] 12101 https://github.com/akinomyoga/ble.sh/issues/169 12102 12103 またもや set -uex でロードできなくなっているのでその修正を行う。同時に$- 及 12104 び $BASHOPTS (bash-4.0 以下では自前で再構築) を持ちて状態保存のコードを単純 12105 化した。これで以前よりは効率はよくなったのではないかと思う (nocasematch の 12106 検索は多少時間がかかるかもしれない)。 12107 12108 次に各 builtin に対して対策コードを導入する事にする。 12109 12110 - done: trap (util.sh) 12111 - done: sleep (util.sh) 12112 - done: bind (decode.sh) 12113 - done: read (edit.sh) 12114 - done: exit (edit.sh) 12115 - done: history (history.sh) 12116 12117 そもそも set -eu をありがたがって使っている時点で余り分かっていない人が書い 12118 ているという気がする。何れにしてもその時点で一般には防御が難しいが、NixOS 12119 の用意したスクリプトでだけ set -eu を有効にするというのであれば、仕方がない 12120 のかもしれない。勝手に builtin を上書きしてそれで問題を起こすのは ble.sh が 12121 悪い。これによって状態保存・復元の overhead が生じるが仕方がない。 12122 12123 * prompt: C-c で history_share が有効でない (reported by SuperSandro2000) [#D1742] 12124 https://github.com/akinomyoga/ble.sh/issues/96#issuecomment-1018101640 12125 12126 うーん。確かにそうだ。確か以前もっと高頻度で更新する事についても考察したが、 12127 編集中に何か変な事が起こると大変だと思ってそれは棄却したのだった。然し、C-c 12128 で discard-line する場合には安全に履歴をロードする事ができる。対応する。 12129 12130 2022-01-20 12131 12132 * prompt: cygwin で root prompt mark が正しく表示されなくなっている [#D1741] 12133 12134 よく考えたら ${PS1@P} を使う様にしているからではないか。振る舞いを修正して 12135 いる物が含まれている場合にも ${PS1@P} の仕様は無効化する必要がある。 12136 12137 つまり、cygwin, msys, etc において PS1 に \$ が含まれていたら駄目。 12138 これは簡単な修正だった。 12139 12140 * prompt: bash-it や oh-my-bash で最初のプロンプトの座標計算がずれる [#D1740] 12141 12142 ble.sh を読み込むと最初のプロンプトの表示がずれてしまう。これは ble.sh をロー 12143 ドして最初にプロンプトを表示した時には未だ char_width_{mode,version} が解決 12144 されていないので、既定の設定が使われて座標計算にずれが生じるのが原因である。 12145 12146 本来は bleopt_char_width_{mode,version} が変化していれば再描画される筈なの 12147 であるが何故再描画が走らないのだろうか。取り敢えず 12148 ble/prompt/unit:_ble_prompt_ps1/update の時点で char_width_@ が解説された後 12149 に呼び出されていない。ble/prompt/unit#update _ble_prompt_ps1 は実行されてい 12150 る。という事を考えると、の間で更新が棄却されているという事になる。 12151 12152 ohashref='$_ble_prompt_version::$prompt_ps1,$PWD' である。うーん。本来は 12153 $_ble_prompt_version と同じ所で char_width_@ も参照するべきの気がする。→結 12154 局 prompt_hashref_base に '$_ble_prompt_version' だけが入っていた所 12155 に'$bleopt_char_width_mode,$bleopt_char_width_version' も追加する事で解決し 12156 た。他にも LC_CTYPE が変わった時にも問題になるのではないか、と思ったが 12157 LC_CTYPE がコマンド実行以外で勝手に切り替わる事もないと思われるの 12158 で、_ble_prompt_version でカバーできていると考えるべきである。つまり、 12159 bleopt_char_width_{mode,version} は非同期で変化する可能性があるのでそれに応 12160 じて更新する必要があるという事。 12161 12162 と思ったが、bleopt_char_width_{mode,version} が変化するのは検出できるのだか 12163 ら、其処で、_ble_prompt_version を更新すれば良いだけなのでは→その様に変更 12164 する事にした。実は bleopt_char_width_{mode,version} の他にも 12165 emoji_{opts,version} が存在した。これらも変化があればちゃんとプロンプトを更 12166 新する必要がある可能性がある。全て対応した。ちゃんと動いている。 12167 12168 * bash-5.2 shopt patsub_replacement 対策 [#D1739] 12169 12170 これは #D1738 の一環として発見されたバグであるが bash-0.3 も修正しなければ 12171 ならないので、独立した項目にする事にする。 12172 12173 - util (ble/builtin/trap): $Q から $q へ逆方向で変換されていた。 12174 - util (ble/util/print-global-definitions): ${v//$q//$Q} の様になっていた為 12175 に置換後に余分な / が混入していた。 12176 12177 * 2022-01-13 bash-5.2 shopt patsub_replacement 対策 [#D1738] 12178 12179 % 取り敢えず危なそうな箇所を抽出しておく。うーん。やはり可也面倒である。 12180 % ble/string#replace 等の関数を作るべきなのかもしれない。 12181 % 12182 % $ grc '\$\{[[:alnum:]_]+(\[[^][]*\])?/' --exclude={memo,test,wiki} 12183 % $ grc '\$\{[[:alnum:]_]+(\[[^][]*\])?//?[^{}]*/[^{}]*[$&]' 12184 % $ grc '\$\{[[:alnum:]_]+(\[[^][]*\])?//?([^{}]|\{[^{}]*\})+/[^{}]*([$&]|\\)' 12185 % 12186 % done: ./keymap/vi.sh:6974: ins=${ins//[!$'\n']/"$s"} ★ 12187 % done: ./lib/core-syntax.sh:976: a=${a//@h/$histc1} 12188 % done: ./lib/core-syntax.sh:977: a=${a//@q/$histc2} 12189 % done: ./lib/core-syntax.sh:982: a=${a//@h/$histc1} 12190 % done: ./lib/core-syntax.sh:983: a=${a//@q/$histc2} 12191 % done: ./lib/core-syntax.sh:2255: rex_event=${rex_event//@A/$A} 12192 % done: ./lib/core-syntax.sh:2266: rex_quicksub=${rex_quicksub//@A/[$histc2]} 12193 % done: ./lib/core-syntax.sh:2267: rex_quicksub=${rex_quicksub//@C/$histc2} 12194 % done: ./lib/core-syntax.sh:4453: a=\\ ; b="\\$a"; ret="${ret//"$a"/$b}" ★ 12195 % done: ./src/edit.sh:604: a='\' b='\\' text=${text//"$a"/$b} ★ 12196 % done: ./src/util.sh:118: ble/array#push specs "${var[@]/%/=$value}" # #D1570 WA checked 12197 % done: ./src/util.sh:777: ARR=("${ARR[@]::$2}" "${sARR[@]/#/$4}" "${ARR[@]:$3}")' # WA #D1570 checked 12198 % done: ./src/util.sh:806: ret="${ret// /$1}" 12199 % done: ./src/util.sh:1083: a=${chars1:i:1} b=\\${chars2:i:1} ret=${ret//"$a"/$b} 12200 % done: ./src/util.sh:5305: ble/util/put "${_ble_term_visible_bell_show//'%message%'/$sgr$message}" >&2 12201 % done: ./src/util.sh:5622: local ret=${_ble_term_Ss//@1/$state} 12202 % 12203 % ????: ./src/util.sh:1379: builtin eval -- "${_ble_local_script//opts/$1}" # Note: 配列要素に変な文字が入っていると駄目 12204 % ????: ./src/util.sh:1383: builtin eval -- "${_ble_local_script//opts/$1}" # Note: 配列要素に変な文字が入っていると駄目 12205 % ????: ./src/util.sh:1391: builtin eval -- "${_ble_local_script//opts/$1}" # Note: 配列要素に変な文字が入っていると駄目 12206 % ????: ./src/util.sh:1399: builtin eval -- "${_ble_local_script//opts/$1}" # Note: 配列要素に変な文字が入っていると駄目 12207 % →うーん。これらについては元々配列要素を想定していない実装になっているのでここで改めて気にするのも変である。 12208 % それに配列要素を想定している場合には添字は先に1回だけ評価するべきの気がする。なので、そんなに単純ではない。 12209 % これは今回は見送り。 12210 % 12211 % ok: ./src/util.sh:1516: builtin eval -- "${_ble_local_script//NAME/$1}" 12212 % ok: ./src/util.sh:1899:builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_builtin_trap_n2i}" 12213 % ok: ./src/util.sh:2515: builtin eval -- "${_ble_local_script//ARR/$_ble_local_array}" 12214 12215 外部プロジェクトも気になる。うーん。これは悲惨な結果である。 12216 bashdb, bash-completion, etc. が大抵影響を受ける様に見える。 12217 -> bug-report bash/report31/affected.txt に移した。 12218 12219 bug-bash に再度報告した。結局、当初の提案で実装し直して貰った。 12220 12221 改めて新しい実装に合わせて ble.sh を調整する事にした。改めて丁寧にチェック 12222 を行って行ったところ、先の修正で見過ごしていた所も幾らか見つかった。自動検 12223 出しやすい様にスタイルを統一し、その上で自動検出を記述した。 12224 12225 2022-01-18 12226 12227 * ble-measure の base がやはりずれる。より良い更新式を取得したい [#D1737] 12228 12229 うーん。というより此処まで大きくずれるのであれば nest レベル毎に計測を実施 12230 するべきなのではないか。但し、ble-measure を自信から呼び出して使うと nest 12231 レベルが1だけずれてしまう。然し、それでも nest レベル毎に計測し直した方が遥 12232 かに良い値が出ている。 12233 12234 一応 nest レベルの 1 のずれを補正する事にする。${#FUNCNAME[*]} 1..11 まで計 12235 測してそれを線形フィットする。 12236 12237 | gnuplot> plot 'a.txt' 12238 | gnuplot> f(x) = a * x + b 12239 | gnuplot> b=4500;a=100 12240 | gnuplot> fit f(x) 'a.txt' via a,b 12241 | iter chisq delta/lim lambda a b 12242 | 0 1.5114300000e+05 0.00e+00 3.22e+03 1.000000e+02 4.500000e+03 12243 | 1 3.2658557879e+04 -3.63e+05 3.22e+02 9.857978e+01 4.410413e+03 12244 | 2 1.9568027480e+04 -6.69e+04 3.22e+01 8.865848e+01 4.465751e+03 12245 | 3 1.9468872818e+04 -5.09e+02 3.22e+00 8.771000e+01 4.471467e+03 12246 | 4 1.9468872727e+04 -4.67e-04 3.22e-01 8.770909e+01 4.471473e+03 12247 | iter chisq delta/lim lambda a b 12248 | 12249 | After 4 iterations the fit converged. 12250 | final sum of squares of residuals : 19468.9 12251 | rel. change during last iteration : -4.66698e-09 12252 | 12253 | degrees of freedom (FIT_NDF) : 9 12254 | rms of residuals (FIT_STDFIT) = sqrt(WSSR/ndf) : 46.5103 12255 | variance of residuals (reduced chisquare) = WSSR/ndf : 2163.21 12256 | 12257 | Final set of parameters Asymptotic Standard Error 12258 | ======================= ========================== 12259 | a = 87.7091 +/- 4.435 (5.056%) 12260 | b = 4471.47 +/- 30.08 (0.6726%) 12261 | 12262 | correlation matrix of the fit parameters: 12263 | a b 12264 | a 1.000 12265 | b -0.885 1.000 12266 12267 4471.47 + 87.71 * ${FUNCNAME[*]} 12268 12269 現在のレベルが x の時、x+1 の計測結果は b+a(x+1) になっていると考えられるので、 12270 [b+ax]/[b+a(x+1)] 倍すれば補正できる。 12271 12272 * うーん。最小時間を記録したらそれで更新する様にしたい。 12273 12274 線形フィットを実測値から実施する。然しそうしたとしてどのタイミングでその 12275 値を使用するのだろうか? もし未知の場合には必ずその場で試行するのだとした 12276 ら線形フィットを用意しておく意味はあるのだろうか。 12277 12278 * うーん。a=0 自体にも本来は実行コストが存在する筈である。それを計る事はで 12279 きないのか。例えば a=0;a=0 とやると 670ns ぐらいはかかる。という事は、 12280 600ns ぐらいは a=0 で消費している事になるが、一方でこれをどうやって自動的 12281 に補正するかが問題になる。関数を空にする事ができないのが問題である。 12282 12283 計測する関数定義に return 0 を追加する事にした。これによって実際に計測時 12284 間が 1us 程度増加してしまう様だが仕方がない。3nest 分の遅延と同じなので余 12285 り気にしない事にする。→これで測ってみた所、a=0 の実行時間は最短で 666ns 12286 になった。事前の見積もりと一貫した結果である。 12287 12288 2022-01-11 12289 12290 * def.sh にある設定更新メッセージが make install で削除されるのでは? [#D1736] 12291 12292 # で始まる行は全て一律に削除している。 12293 12294 色々考えたが init-msys2 にある様な変な回避方法はやはり不自然なのでやめたい。 12295 インストールスクリプトでコメント・空白行を削除している箇所を確認した所、意 12296 外と簡単に heredocument だけ出力する様にできそうなので、その様に修正した。 12297 それに伴って init-msys2 にある回避も削除した。ちゃんと正しくインストールさ 12298 れている。 12299 12300 2022-01-09 12301 12302 * test: テストログをファイルに出力する [#D1735] 12303 12304 osh で動くか見る上で出力の形式などが気になったので。 12305 12306 * done: test-decode のテスト項目数がずれているのを直す。 12307 * done: ログをファイルに出力する機能もほしい。 12308 * done: テストの成功率を表示したい。 12309 12310 * global: 算術式 10# が bash-5.1 以降エラーになる [#D1734] 12311 12312 一度対策として書き換えを行ったが不十分だった。全ての箇所を個別にチェックす 12313 るのは大変だし、今後算術式を書く時にまた問題になっても困るので全て 12314 10#0$... と記述する事にした。この様にしておけば正規表現で 10#$ を検出して書 12315 き換える様に促す事ができる。 12316 12317 * mandb: rsync の抽出 正しく抽出できていない [#D1733] 12318 12319 % と思ったが今試したらちゃんと動いている? 12320 % →と思ったらやっぱり動いていない。 12321 12322 ? うーん。gawk regex #D1729 の問題によって失敗していたというだけの事なのか 12323 もしれない。と思って今 gawk で試してみたら問題が再現した。うーん。gawk と 12324 nawk の振る舞いの違いという事か。と思って色々試したが nawk や mawk でも結 12325 局再現した。結局の所 gawk は多分関係ない。 12326 12327 * done: " or " によるオプションの行内列挙 12328 * done: rsync の man の形式の解析 (.IP "--OPTION" \n desc .IP etc) 12329 * done: "--no-OPTION" の説明の自動生成 (for progcomp) 12330 * done: _parse_help における解析 12331 12332 * prompt-git: source .bashrc で reload すると git-prompt のチェックが起動しなくなる [#D1732] 12333 12334 何故だろうか。 12335 12336 ble/contrib/prompt-defer/submit は実行しているが、 12337 ble/contrib/prompt-defer:_ble_contrib_prompt_git_dirty/worker が呼び出され 12338 ていない様だ。うーん。分かった。行番号や時計がクリアされてしまう為に、情報 12339 再取得の条件が満たされなくなってしまっている。 12340 12341 また、ディレクトリのチェック自体は git にいる時にしか実行されないので、単に 12342 他のディレクトリに行くだけでは駄目で別の git repository に入ってから戻って 12343 こないと再計算が発生しない。 12344 12345 * syntax: bash-3.2 で syntax-highlighting の初期化が起こらない [#D1731] 12346 12347 [初期化されない問題] 12348 12349 bash-3.2 で syntax-highlighting のロードが起こらなくなっている。元々どの様 12350 にロードしていたのだったか。ble-0.3 で確認するのが良い。 12351 12352 ble-0.3 では core-syntax-def.sh に以下の様に記述されている。 12353 12354 ble/function#try ble/util/idle.push ble/syntax/import || 12355 ble/syntax/import 12356 12357 それが現在は以下の様になってしまっている。 12358 12359 ble/is-function ble/util/idle.push && 12360 ble-import -d "$_ble_base/lib/core-syntax.sh" 12361 12362 問題の変更は 321371fa #D1593 で行われている。その時の議論を再確認したが特に 12363 bash-3.2 について意識はしていない様に見える。というかこのコミットの変更は以 12364 下の様な物になっている。ble-import -d は idle.push が存在しなければその場で 12365 読み込む。恐らく余り意識せずに書き換えてしまったという事の気がする。 12366 12367 -ble-import -d lib/core-syntax 12368 +ble/is-function ble/util/idle.push && ble-import -d "$_ble_base/lib/core-syntax.sh" 12369 12370 →これは前の様に直すべき様に思われる。 12371 12372 [初期化順序の問題] 12373 12374 或いは bash-3.2 ではその場で ble-import lib/core-syntax を実行してしまうと 12375 問題が生じるのだろうか? 分からないので取り敢えずその場で import するとどう 12376 なるか確認する。うーん。bash-5.1 では特に問題は生じていないみたいだ。然し 12377 bash-3.2 で実行してみると着色が全くされなくなってしまった。後で ble-import 12378 を実行しても解決しない。文法エラーの着色は有効である。syntax_debug を入れて 12379 みると属性に依る着色が全くされていない様である。 12380 12381 →これは独立した問題であるという事が判明した。 12382 12383 ? ble/syntax/attr2iface/color_defface.onload が実行されていないという事なの 12384 だろうか → うーん。これを実行したらちゃんと動く様になった。 12385 12386 つまり color_defface_load が発火されていないか、或いは eval-after-load の 12387 バグだろうか。うーん。実は上記の core-syntax.sh のードは関係なくて、単に 12388 eval-after-load の問題の気もしてきた。うーん。eval-after-load を見るとちゃ 12389 んと登録はされている。然し一方で発火されていない状態の様である。然し、 12390 blehook を改めて確認すると登録した hook は消去されている。何故? 12391 12392 hook の呼び出し元で確認した所ちゃんと登録されている。どうも確認してみたら 12393 ble/syntax/attr2iface/color_defface.onload はちゃんと呼び出されている様だ。 12394 12395 % 一方で ble/color/defface.onload が二回呼び出されている。特に 12396 % color_defface.onload の後に呼び出されている。もしかしてこれによって設定 12397 % がクリアされてしまっている可能性? 12398 % 12399 % と思ったら違った。 ble/{color,syntax}/defface.onload で二種類あるのだった。 12400 12401 * 何れにしても初期化の順序による問題の様である。 12402 12403 % と思って ble/syntax/attr2iface/color_defface.onload の実装を見ていて気づ 12404 % いたが、どうやらその瞬間の face の値を読み取っている? これだと駄目の筈。 12405 % 起動した後に着色を変えられない事になる。 12406 % 12407 % コマンド名はちゃんと変更される。然しこれはよく考えたら後付で取得している 12408 % から? 然し、それも変だ。結局属性から face に変換している筈 → よく考えた 12409 % らこれは iface に対する初期化なのだから、その場で整数値に解決してしまう事 12410 % 自体に問題はない。 12411 12412 何れにしても問題は attr2iface/color_defface.onload は attr -> iface の対 12413 応付を記録しているが、iface が未だ初期化されていない為に全て iface=0 になっ 12414 てしまっているという事の様に思われる。 12415 12416 結局 ble/syntax/defface.onload よりも後に attr2iface/color_defface.onload 12417 を実行しなければならないのにそれが逆転してしまっているのが原因だった。 12418 syntax-color-def.sh において ble/syntax/defface.onload の登録よりも後に 12419 ble-import -d lib/core-syntax を呼び出すべきだったのである。 12420 12421 * util: bash-3.2 で alias 云々のエラーメッセージが出る様になっている [#D1730] 12422 これは単純に alias チェックの際に 2>/dev/null を忘れているのが原因。 12423 12424 * complete: gawk regex warning (reported by telometto) [#D1729] 12425 https://github.com/akinomyoga/ble.sh/issues/167 12426 12427 これは最近追加した ble/complete/action/quote-insert.batch/awk から出ていた。 12428 awk の bracket expression の中のエスケープシーケンスは解釈されるのだった。 12429 なので孤立した \ から警告が発生していた。普段 nawk を使っていたので気づかな 12430 かった。取り敢えず修正した。 12431 12432 ? 他にも類似の問題が別の箇所にあったりはしないだろうか。念の為、全ての 12433 ble/bin/awk のスクリプトを gawk に食わせて見た方が良いのかもしれない。然 12434 しチェックするとしてもどうやってチェックするのか。個別にスクリプトを実行 12435 するのは面倒だし、スクリプトを実行する事によってファイルが作られたりして 12436 しまうかもしれない。また関連する変数などをちゃんと初期化しなければスクリ 12437 プトを正しく再現できないかもしれないし、実行時に正規表現が構築されている 12438 場合にも影響を与える (実行時に正規表現が構築される事はなかった様な気もす 12439 るが)。 12440 12441 一応 bracket expression を含む正規表現を他から取得している箇所だけは再確 12442 認する。特に parse_help の辺り。 12443 12444 * _ble_complete_option_chars は既にちゃんと対策されていて注記まであった。 12445 * 他にもう一箇所 [] の中に \ がある物があったが其処もちゃんと \\ になって 12446 いた。 12447 12448 \ を全体に渡って検索してみたが core-complete の中には他には怪しい物はなかっ 12449 た。 12450 12451 * benchmark.sh にはない。 12452 * history.sh にも沢山 [\\] や [^...\\] があったが、これらもちゃんとエスケー 12453 プされている。 12454 * decode.sh にも幾らかあった。綺麗に awk の中と外でちゃんと \\ と \ が使 12455 い分けられている。 12456 * util.sh もちゃんと使い分けられている。 12457 * edit.sh にはない。ble.pp もない。contrib/prompt-git.bash も大丈夫。 12458 12459 2022-01-08 12460 12461 * complete: WA terminal glitch on xenl (reported by telometto) [#D1728] 12462 https://github.com/akinomyoga/ble.sh/issues/166 12463 12464 再現できた。desc が一列表示でかつ一番最後の項目が丁度ぎりぎり収まるか、或い 12465 はおさまり切らない時に問題が生じるということの様だ。また、一列表示の時に 12466 ellipsis の位置がおかしい問題も見られる。これらは実の所同根ではないかと思わ 12467 れる。 12468 12469 うーん。一つバグは見つけた。しかしこれは関係ない → #D1727 12470 12471 ellipsis の位置と行の終端位置が一致していないが、調べてみると wcolumn は実 12472 際の端末の幅と同じにして trace が呼び出されている。結果を見ると、行の終端位 12473 置が誤っているのではなくて ellipsis を出力する位置が誤っているという事に見 12474 える。 12475 12476 ble/util/c2w 8230; echo $ret としても実際に表示している通りの 1 になっている。 12477 12478 →うーん。これは分かった。これは端末による振る舞いの違いだ。xenl 状態にある 12479 時に CUB をした時に、一番最後の列に移動するか或いは一番最後から二番目の列に 12480 移動するかである。vte は 2 番目になる。screen と contra は一番最後の列にな 12481 る。 12482 12483 * これは一度まとめた事が contra にある筈。と思ったがこれは ech などの振る舞 12484 いについてだった。contra のモードに xenl_ech が存在する。 12485 12486 # 行末にカーソルがある時に ECH, ICH, DCH は行の最後の文字に作用します。 12487 f--- mode_xenl_ech private true 12488 12489 CUB CUF についても調べた事がある筈だが、それは contra にはまとめられてい 12490 ない。 12491 12492 $ printf '%*s\e[10DX\n' $COLUMNS 0123456789 12493 12494 * CUD 前に最後の列に移動する 12495 - xterm, terminology, urxvt, alacritty 12496 - vte (GNOME, xfce4, terminator, lxterminal) 12497 - mlterm, RLogin 12498 12499 * xenl の時は右端の境界にいるかの様に動作する 12500 - kitty, screen, tmux, termit, konsole 12501 - contra, Poderosa 12502 12503 この振る舞いを吸収する様にシーケンスを構築する事はできるだろうか? 12504 12505 % * この振る舞いの対処を過去にした事はあるだろうか。eol mark の場合には直後に 12506 % \r をしているので関係ない。 12507 % 12508 % a CUU CUD などを使って強制的に一番最後の列に移動してから移動を開始する? 然 12509 % し、高さが一行しか無い場合には信用できない。本当に端末の高さが一行しか無 12510 % い場合には使えるが、実際にはどちらか一方にだけ移動できる様な状態になって 12511 % いたとすると元の位置に戻ってくる事ができない。 12512 % 12513 % b BS を使ったら元の位置に戻る事ができるだろうか。試して見た所 screen は BS 12514 % を使うと一番最後から 1 番目のセルに移動する。contra や vte は2番目のセル 12515 % に移動する。うーん。なので BS を使った場合端末によって位置が異なるという 12516 % 事。一応この振る舞いは vttest にあるので、screen 等の一部の例外を除いて動 12517 % くべきという事にしてしまっても良いのかもしれない。と思ったが tmux も 12518 % screen の仲間だ。うーん。やはりこれは端末によって振る舞いが異なる。 12519 % 12520 % c 本来、本当の COLUMNS と現在の cols を区別するべきなのではないかという気が 12521 % する。本当の COLUMNS と一致している時に限り特別な動作を行う。と思ったが、 12522 % そうしたとしても現在の端末がどちらの振る舞いをするのか分からなければ、結 12523 % 局どちらの端末でも動く様に書かなければならない。或いは端末の振る舞いを事 12524 % 前にテストしておく必要がある。 12525 % 12526 % d 或いは CUB CUF を一回実行したら意外とどの端末でも同じになるのかもしれない。 12527 % 試してみる事にする。 12528 % 12529 % - ok: wt, vscode (xterm.js), tmux, screen, xterm 12530 % 12531 % と思ったが、これは本当に端末の一番右端にいる時には使えるけれども、それ以 12532 % 外の時には異なる結果になるから使えない。CUF CUB CUB CUF をするとどうなる? 12533 % Class A -> 0 (-2), Class B -> 0 (-1). これだと全然駄目である。 12534 % 12535 % やはり以前も同じ考察をして無理と判断した様な気もする。しかしそれは canvas 12536 % の bottom dock の話だった様な気がしないでもない。 12537 12538 うーん。そもそもそういう理由があるからこそ相対移動は右端に接しない様に設計 12539 していたという事の様な気もする。menu-style:desc も右端に接しない様に修正す 12540 る事にする。 12541 12542 * complete (menu-style:desc): fix not working "bleopt menu_desc_multicolumn_width=" [#D1727] 12543 12544 menu_desc_multicolumn_width= として multicolumn を無効化しようとするとゼロ 12545 除算のエラーになる。定義していない変数を誤って参照して ncolumn=0 になってい 12546 た。修正した。 12547 12548 * decode: bind の古い形式が使えなくなっている (reported by returntrip) [#D1726] 12549 https://github.com/akinomyoga/ble.sh/issues/165 12550 12551 これは #D1698 (b6fc4f0) の regression だろう。確認した。確かにこの時点で導 12552 入したバグである。テストもちゃんと追加する事にする。以前実験したケースも全 12553 てテストに追加する事にする。 12554 12555 % どうも \C も解釈しなければならない様だ。と思ったが C で終わっていればどう 12556 % でも良いらしい。これは control で終わっていても良い。 12557 12558 修正した。テストを追加した。テストも通っている。 12559 12560 うーん。テストを作って安心したらまた regression 通常の大文字も全て小文字に 12561 して解釈されてしまう。追加修正する。 12562 12563 2022-01-01 12564 12565 * util (ble/function): work around "shopt -u extglob" [#D1725] 12566 12567 #D1723 で extglob が解除された状態で extglob を使って定義された関数を 12568 ble/function#advice した時に失敗するという問題が発生した。そもそも extglob 12569 が解除されてしまっている状態も問題だが、それとは別に extglob を使った関数も 12570 安全に待避して置き換える事ができなければならない。 12571 12572 なので、更に advice 等で関数を再定義する時には extglob を一時的に有効化する 12573 べき → その様に修正した。 12574 12575 12576 2021-12-30 12577 12578 * 2021-12-20 README: oh-my-bash は流石に削除するべきだろう [#D1724] 12579 12580 → oh-my-bash を引き継いだので流石にこれ以上は問題は起こらせない。追々実装 12581 もちゃんとした物に差し替えていく事にする。なので現状では変更しなくても良い 12582 という気がする。と、思ったがたかが 100 commits 程度しかない oh-my-bash を本 12583 当に推して良いのかというのも謎である。 12584 12585 取り敢えずリンクは貼る事にした。 12586 12587 * util (vbell): 外部コマンドを実行する前に vbell 消去はキャンセルするべきでは [#D1723] 12588 12589 ble/term/visible-bell/.erase-previous-visible-bell で set -f が設定されてい 12590 る時にはどうするのか。うーん。ble/util/eval-pathname-expansion を拡張する事 12591 にする。canonical という opts を追加する事にした。 12592 12593 キャンセルするというよりもその場で消去するというので良い気がする。単に 12594 ble/term/visible-bell/.erase-previous-visible-bell さえ呼び出して置けば良い 12595 様に思われる。ble/term/visible-bell/erase という関数を用意した。 12596 12597 後は、これを何処で呼び出すのかという事。ble/term/leave の辺りで呼び出せば良 12598 いのではないかという気がする。 12599 12600 実際に ble/term/leave の呼び出し元を見たが他に適切そうな介入点もない。また、 12601 ble/term/leave で erase するとしたら util.sh の中で閉じていて都合が良い。 12602 ble/term/leave の中で呼び出している個々の設定はどうだろうか。中を見ると 12603 stty, rl-convert-meta を呼び出している。更に leave-for-widget 経由で 12604 bracketed paste, modifyOtherKeys, cursor shape 等の端末の設定を復元している。 12605 うーん。leave-for-widget は fzf の呼び出しの時に使っている。うーん bind -x 12606 経由で何かプログラムを起動する事もあるだろうから、leave-for-widget の中で設 12607 定はするべき気がする →その様にしたら良い感じになった。 12608 12609 ? 所で leave-for-widget,enter-for-widget を呼び出しているのが fzf だけなの 12610 は良いのだろうか。他の人が fzf 的な設定を用意した時に問題になるのではない 12611 か。bind -x の前後で毎回 leave/enter するべきだろうか? 12612 12613 o 処理としては単にシーケンスを投げるだけなのでそんなに重くはないが、 12614 12615 x bind -x した widget を呼び出す度に visible-bell の erase も含めて設定を 12616 変更するのもやりすぎな気がする。 12617 12618 x それに同じ事が標準の ble/widget/* でも言える。ble/widget/* で毎回それを 12619 実行する訳には行かないので、結局は widget を書く人に注意点として提示す 12620 る必要があるのである。という事を考えれば bind -x の時にだけ注意しなくて 12621 良いという具合にわざわざする必要もない気がする。 12622 12623 x もしこれが既存の bash 設定で頻繁に起こる問題であれば、何も考えずに移行 12624 できる様にするべきだったかもしれないが、実際の所余り問題も起こっていな 12625 い様なので現段階では少なくとも様子見というのが正しい気がする。 12626 12627 →現時点では必要がある時にユーザーの側で正しく leave/widget を呼び出して 12628 貰う様にする。もし問題が発生するようであれば bind -x の時にだけは 12629 leave/enter を勝手に呼び出す事にする。 12630 12631 x 2022-01-01 util (eval-pathname-expansion): extglob が勝手に解除される問題 12632 12633 補完しようとした時に構文エラーが表示される問題。bash-completion をロードし 12634 なければ問題は発生しない。エラーが表示された後に ble/funtction#advice が 12635 original:_longopt が見つからないというエラーを出力している。 12636 original:_longopt の定義で失敗しているという事。 12637 12638 実際に定義している部分で定義に使っている文字列を出力させてみたがちゃんと関 12639 数定義が抽出できている。とここで extglob が設定されていない事によるエラーで 12640 はないかと思ったらそうだった。extglob が解除されている。これは直前の変更 12641 #D1724 で設定を復元するのに失敗しているのが原因だろう。該当部分で shopt を 12642 出力して見たら空文字列になっている。ちゃんと canon=1 にはなっている。と、 12643 shopt=$BASH_OPTS ではなくて shopt=$BASHOPTS であるべきだという事に気づいた。 12644 これは修正する必要がある。 12645 12646 然し、実はこの問題は未だ push していない commit の問題だったので実はそん 12647 なに急ぐ事はなかったのだと気づいた。 12648 12649 (本当は関数のテストに際して shopt の設定が変更されていない事などもチェッ 12650 クするべきなのだろうという気がする。そしてそのチェックは実は BASHOPTS と 12651 $- を保存すれば良いだけなので簡単である。) 12652 12653 * complete: echo $abc 迄入力すると progcomp から complete -p の内容が出力される [#D1722] 12654 12655 調べると complete -p -- コマンド名 によって補完設定を読み込む時にコマンド名 12656 が空になっている。comp_words=('$abc') になっている。 12657 12658 | ? そもそも何故 comp_words=('$abc') によって補完が呼び出されているのだろうか。 12659 | コマンド抽出に失敗している気がする。 12660 | 12661 | →これは ble/complete/progcomp/.compline-rewrite-command の問題であって 12662 | extract-command の問題ではなかった。なので個別に気にする必要はない。 12663 | 12664 | ? 次に '$abc' が何故空の文字列に置き換わってしまうのだろうかという事。 12665 | 12666 | →これは分かった。展開自体は complete -p -- $abc によって行われているが 12667 | quote されていない所為で単語無しで設定が読み込まれているという事なのだろ 12668 | う。コメントによると呼び出し元によって quote されている筈という事になって 12669 | いるが何故 quote されていないのだろうか。 12670 | 12671 | stackdump: 12672 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh:1 (ble/complete/progcomp/.compgen) 12673 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh:50 (ble/complete/progcomp/.compgen) 12674 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh:93 (ble/complete/progcomp) 12675 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh:55 (ble/complete/source:argument/.generate-user-defined-completion) 12676 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh:18 (ble/complete/source:argument) 12677 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh:21 (ble/complete/candidates/generate-with-filter) 12678 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh:18 (ble/complete/candidates/generate) 12679 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh:15 (ble/complete/auto-complete/.check-context) 12680 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh:23 (ble/complete/auto-complete.impl) 12681 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh:20 (ble/complete/auto-complete.idle) 12682 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (ble/util/idle.do/.call-task) 12683 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:38 (ble/util/idle.do) 12684 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:3 (ble-edit/bind/.tail) 12685 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:22 (ble-decode/EPILOGUE) 12686 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:81 (ble-decode/.hook) 12687 | 12688 | うーん。行番号が全然当てにならない。 12689 | 12690 | どうやら complete -p -D で呼び出されてその後に再実行によって変な状態になっ 12691 | ている様だ。comp_words の状態は直前の呼び出しでは以下の様な形になっている。 12692 | 12693 | orig_comp_words=('echo' '$abc') comp_words=('$abc') ucmd='echo' qcmds=('echo') 12694 | 12695 | 結局.compgen が参照するのは comp_words だけであるからこの際 ucmd や qcmds 12696 | は関係ない。 12697 12698 [原因] 12699 12700 うーん。分かった。ble/complete/progcomp に於いて、 12701 12702 1 最初のコマンド名の単語評価の際に複数単語に展開されたかまたは単語が変化し 12703 た時に、orig_qcmds にコマンド名の展開結果を再クォートした物を格納する。そ 12704 れ以外の時には orig_qcmds は空である。 12705 12706 2 さて、最後に既定の補完 (complete -D) を実行する為に comp_words を書き換え 12707 る際に orig_qcmds に何か値が設定されていれば、コマンド名が変化していたと 12708 判定して、.complien-rewrite-command を用いて orig_qcmds を適用する様になっ 12709 ている。所が、その判定部分を間違えていて orig_qcmds が空の時であっても 12710 .compline-rewrite-command が呼び出されて、結果としてコマンド名が削除され 12711 るという状態になっていた。 12712 12713 判定を修正したら echo $abc に対しては問題は発生しなくなった。 12714 12715 然し此処で改めて疑問が生まれる。最初の単語の展開結果が空になる時には何が起 12716 こるのだろうか。例えば "$abc [TAB]" に対して何が起こるのか。orig_qcmds は空 12717 なので書き換えは起こらない。すると、$abc がそのまま補完対象になるのではある 12718 まいか。 12719 12720 x fixed: コマンド名の展開結果が空の時には何が起こるのだろうか → 特に変な事 12721 は起こらない様子である。 12722 12723 試してみると一見して問題は起こらない様に見えたが、それは空文字列に対して 12724 は complete -F _minimal '' という設定が存在している為に、そちらが呼び出さ 12725 れて complete -D が試行されないからだった。実際に complete -r -- '' をし 12726 て見たら問題が再現した。 12727 12728 x fixed: うーん。改めて観察する。complete -D の時以外でも quote されずに 12729 complete -p に渡ってしまうケースが存在する様な気がする。.compgen は 12730 is-simple の時には必ず quote されている事を要求する。現在の実装だと 12731 is-simple であっても eval に失敗する等した時にはコマンド名が quote されず 12732 に.compgen に渡されてしまう。結果として .compgen 側で展開されて変な事が起 12733 こる可能性は否定できない (そもそも eval に失敗したりした時点で .compgen 12734 の中でも同様に失敗する様な気もするが)。 12735 12736 →is-simple であれば必ず quote は最終的に実行する様に書き換える事にした。 12737 結果として orig_qcmds は is-simple の時には必ず設定される様になった筈なの 12738 で、complete -D の .compgen に際しては orig_qcmds が設定されているかどう 12739 かを確認するだけで良い筈。 12740 12741 * 2021-12-22 highlight: 0 番目の要素の入っていない配列名の着色 [#D1721] 12742 12743 直した。複数の属性がある時にどの着色にするのかというのは悩ましい所だが、そ 12744 れは今迄の実装でも同様であったので今迄の実装を踏襲する。 12745 12746 ? 着色を合成するという可能性 12747 12748 x 本当は着色を合成するという手もあるのかもしれないが、合成規則や優先順位 12749 を考えるのは面倒だし、結局どれかの属性は他の属性に上書きされるので意味 12750 がない気がする。 12751 12752 o とは言えど、配列 (既定で太字) に関しては他と組み合わせても問題ない筈で 12753 ある様にも思う。 12754 12755 x と思って対応しようとしたがどうも変数の着色は部分的に構文解析レベルで着 12756 色しているのでその場で生成した描画属性で着色する訳には行かない。 12757 12758 x 更に太字は他にも x や luc にも付与している。array/dict の区別に色を使っ 12759 ている。などという事を考えると (太字かどうか) + (色) を使って配列かどう 12760 かと値の性質の両方を表そうというのは無理がある様に思われる。 12761 12762 * readlink 対策: NixOS で皆が readlink 周りに修正を入れている [#D1720] 12763 https://github.com/peterzky/peterzky-overlay/commit/7b98f05e9b8f84f2d43d84db6b2d76c8e93a38df#diff-34e5f3d20be258f6630e6113d3e1409be74cae463b58eb52b5ebe493e9ee2309R20 12764 12765 今迄は /usr/bin:/bin にある readlink しか信用しない事にしていたが、取り敢え 12766 ず readlink が存在さえしていれば単一のパスの読み取りには使えると想定する事 12767 にする。-f が使えるかどうかの判定に /usr/bin/readlink または/bin/readlink 12768 を使う事にする。 12769 12770 readlink が存在しない場合にどうするかについて。 12771 12772 https://qiita.com/ko1nksm/items/873cfb9c6ceb6ef32ec9 12773 12774 このページを見ると ls -l を用いて link を読み取り、cd -P を用いてパスの解決 12775 を行っている。うーん。cd -P を実行した時にディレクトリが戻らなくなるのが心 12776 配だが、まあその様な事は基本的に起こらないと想定して良いだろうか。 12777 12778 元々の実装では別に途中のディレクトリ名の解決はしなくても良いという態度だっ 12779 たが使い方によっては問題になるかもしれないと心配になって来たので、やはり cd 12780 -P を用いて解決する事にした。 12781 12782 * readlink -f を使わない実装について簡単なテストを書いてみたが取り敢えずは 12783 動いている様子である。 12784 12785 というか寧ろ readlink -f を用いて失敗した時にどう振る舞うのかというのが心 12786 配な気もする。 12787 12788 x done: 解決対象のファイル名が - で始まる時に変な事が起こるのではないか? → 12789 これについては修正した。 12790 12791 2021-12-21 12792 12793 * complete (action:mandb): brace の後は space ではなくて , にするべき [#D1719] 12794 12795 ブレース展開の中にいるかどうかは simple_ibrace に非自明な物が設定されている 12796 かどうかで判定できる様に見える。然しこの simple_ibrace は公開されている変数 12797 ではないし途中で書き換わっているかもしれない。それよりは comps_flags 等に情 12798 報が反映されていないか確認する必要がある。実装を見ると x を comps_flags に 12799 追加している様に見えるが、この x はどういう意味だろうか。brace 展開以外の場 12800 合にも追加される可能性があるのだろうか。 12801 12802 comps_flags の説明には含まれていない→と思ったらちゃんと含まれていた。 12803 12804 既存の addtail の実装を見ると brace の中にいるかどうかは comps_flags x で判 12805 定している。なのでそれをそのまま真似すれば良いだろう。 12806 12807 * contrib/git: index に全て登録しただけで非 dirty という事になっているがそれは変だ [#D1718] 12808 12809 ? もっと詳細な情報を取得する為のコマンドは何か。 12810 12811 ? プロンプトの更新を遅延させる一般の枠組みがあると良い気がする。ble.sh 本体 12812 がどんどん肥大化するのは良くないのでprompt-defer.bash 的なファイルに新し 12813 く定義するのが良い。単に現在の git の呼び出しの部分を差し替える事ができる 12814 様にしたら良い気がする。 12815 12816 一つのプロンプト要素の中に複数の更新項目が含まれる場合にはどうするのか。 12817 依存を複数登録するのか、或いは、まとめて更新する事にするのか。 12818 12819 うーん。現在の待ちはどの様に行われているのか確認する→idle経由で状態を更 12820 新している。 ble/prompt/unit/add-hash '$_ble_contrib_prompt_git_dirty' を 12821 通して変更を検出して更新をかけている。 12822 12823 情報を格納する変数も指定するべきなのだろうという気がする。或いは version 12824 変数を作ってそれを参照させるか。或いは id か何かを指定させるというのでも 12825 良い。うーん。何が良いか。 12826 12827 - より詳細な情報を得る為には git status --porcelain を読み出して使うのが良 12828 い。然し、それで本当に足りるのかどうかも分からない。実際にどういった情報 12829 を人々が求めているのかに依存する様な気がする。自分の為という意味であれば、 12830 取り敢えずは index に変更があるかどうかが分かれば良い。 12831 12832 遅延に関係するコードを prompt-defer に分離した。意外とすっきりとできた。 12833 12834 取り敢えずは staged な変更がある場合に色を変えて表示する事にした。実はもっ 12835 と詳しく表示する事を考えても良いが面倒なのでそのままにする。将来的には 12836 git-status だとか git-prompt のエミュレーションを作っても良いのではないかと 12837 いう気がするが、別に自分が使う訳でもないので今は実装しない事にする。 12838 12839 2021-12-19 12840 12841 * menu (align): bleopt menu_align_{min,max} (motivated by banoris) [#D1717] 12842 12843 これは別項目で議論する。というか幅に上限を作っても良いのかもしれないとも思 12844 う。 12845 12846 - done: complete_menu_align -> menu_align_max : 並べる時の align の max 12847 - done: menu_align_min : 並べる時の align の min 12848 12849 - reject: menu_align_item_maxwidth : 項目の幅の最大 → 対応しようかと思った 12850 が、現在の実装では項目の幅の計算には trace-text を使っていて、この 12851 trace-text は高速な代わりに truncate 等の機能がない。trace-text に 12852 truncate を実装するのも trace-text が高速である意義がなくなるし、或いは、 12853 trace にすると遅くなってしまうし、色々と面倒である。この項目についてはそ 12854 れ程積極的に実装する意義がある訳でもない気がするので取り敢えずは実装しな 12855 い事にする。 12856 12857 * done: wiki 12858 * done: blerc 12859 12860 2021-12-18 12861 12862 * complete: コマンド名に一致しない globchar が含まれるとエラーメッセージ [#D1716] 12863 12864 '*' を含む alias を定義すると failglob のメッセージが編集中に現れる。という 12865 か、これは alias に関係なく今迄にも発生していた問題だった様だ。これは別項目 12866 で処理するべき問題の様に思われる。 12867 12868 | bash-completion が有効になっている時に起きる問題の様である。然し、一方で、 12869 | ble.sh が有効でない時には特に問題は生じない。という事は bash が 12870 | bash-completion を呼び出す時にはその問題を自然に回避しているという事だろう 12871 | か。調べる。 12872 | 12873 | ? 何処からエラーが生じているのか? 12874 | 12875 | うーん。そもそも bash-completion が呼び出されているのか怪しい気がしてき 12876 | た。__load_completion を調べてみる事にする。 12877 | 12878 | ble/complete/progcomp/.compgen の stderr を潰したら問題が発生しなくなった 12879 | ので、bash-completion が悪かった訳ではなかった。 12880 | 12881 | ? bash から呼び出された時との違いは何か? 12882 12883 これは分かった。progcomp/.compgen は最初の単語 (コマンド名) が quote 済みで 12884 ある事を想定していた。bash-completion などの関数を通して補完が実行される時 12885 には確かに compline-rewrite-command によって quote された単語に置き換えられ 12886 ていたが、何も補完設定が見つからなかった時の規定の progcomp/.compgen 呼び出 12887 しに対しては、qcmds への書き換えが実行されていなかった。その書き換えを実行 12888 する様に修正した (既定の補完は alias 展開する前の物に対してなので、初回の 12889 qcmds を別に保存しておく事にした)。 12890 12891 * complete (source:command): quote していても alias が候補として生成されている [#D1715] 12892 その為に、menu の中でエラー着色されている。 12893 12894 うーん。特に自分で alias を生成している訳ではなくて compgen -c -- s 等の時 12895 点で alias が生成される様だ。一方で、 compgen -c -- "'s'" 等とすると、何も 12896 生成されなくなってしまうので alias を除外した生成にする事は難しそうである。 12897 12898 更に compgen -c は expand_aliases が off になっていても alias を列挙する様だ。 12899 12900 一方で、for 等の keyword はどの様に判定しているのだったか。うーん。 12901 source:command で filter している様だ。同じ箇所で alias のチェックもする事 12902 にした。 12903 12904 x fixed: 実装してみたら全て赤くなっている→ これは今回の編集ではなくて前回 12905 の commit の時点で既に駄目になっている。#D1714 で修正した。 12906 12907 x fixed: alias は noquote を付加する必要があるのでは? → 修正した。その他に 12908 も ! や [[ 等は quote しない様にする必要がある。 12909 12910 x fixed: alias が *? 等の文字を含んでいる場合コマンド着色でエラーになってし 12911 まう。修正した。 12912 12913 と思ったが、考えてみれば、そもそも alias 名に一致している場合には展開を試 12914 みる前に alias に確定させるべきなのではないか。 12915 12916 * menu-complete で 30s かかるという話 (2/2) yield quote-insert 高速化の試み [#D1714] 12917 https://github.com/banoris/dotfiles/issues/11 12918 12919 #D1710 に於いて、設定を調整すれば以前より大分高速になるようにはしたが、それ 12920 でも yield の速度が気になる。別項目で yield の高速化ができないか考察する事に 12921 した。 12922 12923 * 先ず計測してみる事にする。 12924 12925 | * quote-insert をコメントアウトすると 0.63s かかっている。quote-insert 12926 | があると 2.24s かかっている。うーん。3/4 ぐらいが quote にかかっている 12927 | という事。一方で、quote 作業を gawk 等に任せたとして高速化の程度は限 12928 | られるし、また、gawk が出力した結果を読み出す為に追加の処理が必要にな 12929 | る事に注意する。その様に考えると gawk で quote 処理を実施する事に積極 12930 | 的な意味は見いだせないかもしれない。 12931 | 12932 | * 更に yield 関数の中身まで考えたらより高速化できる可能性もある。→然し 12933 | 文字数を数えたり等の操作が入っているので solaris などの駄目な awk 実 12934 | 装で対応するのが難しい様な気がする。更に filter 等、より様々の事を実 12935 | 装する必要が生じる気がする。 12936 | 12937 | 念の為 filter を抜いてみると 2.02s なので、filter のチェックに 0.22s 12938 | かかっている。quote-insert にかかっているのが 1.61s だった。残りは 12939 | 0.4s である。成程、両方ともくっつけたら大分短くできるのではないかとい 12940 | う気がする。 12941 | 12942 | * というか progcomp ばかり高速化しても仕方がない。全ての yield ループで 12943 | 共通している項目は高速化できるのではないかという気がする。何れにしても 12944 12945 yield loop の処理時間の内訳 12946 ------------ -------------------- 12947 filter 0.22s (fignore, etc) 12948 quote-insert 1.61s 12949 残り 0.40s 12950 12951 * awk で実装してみて速度を比較する。 12952 12953 % うーん。試しに実装してみて比べるのはありかもしれないという程度。そうだ 12954 % としても gawk を呼び出すのにかかる時間を計測して、ある程度以上の項目数 12955 % の時に呼び出す様に変更するのが望ましい。gawk を使ってすら重いという状況 12956 % については余り考えていない。というかそもそも '' 等で補完を開始しようと 12957 % する事が間違っている様な気もする。 12958 12959 done: 先ずは各種の escape を awk で実装する必要がある。 12960 12961 →最終的に awk で色々 quote-insert する所まで実装できた。然し、awk の内部 12962 で test -f file 及び test -e file を判定する事ができないので、必要になる 12963 場合 (progcomp) の場合には予めテストを実行してからそれを awk に渡す事にす 12964 る。 12965 12966 外側でファイル判定する必要がない場合には 28ms であり、ファイル判定する必 12967 要がある場合には 129ms である。更に読み出しの速度も考える必要がある。然し 12968 そうだとしても速度的には十分速い。将来的には沢山の項目数の場合には awk に 12969 移行する事について考えて良いのではないかという気がする。 12970 12971 * 現在の quote-insert の実装も、外側でできるだけ準備をしてから、中では最低 12972 限の判定だけで行ける様に修正する事ができる筈。 12973 12974 その様にした方が現在の awk による実装とも近くなり、両者の一貫性を保ちやす 12975 くなる筈である。 12976 12977 →実装した。然し大して高速化していない。元々 2260ms 程度だったのが 2090ms 12978 程度に減少しただけである。つまり bottleneck はやはり其処ではないという事 12979 だろうか。 12980 12981 うーん。escape-for-bash-specialchars が遅いという事の気がしてきた。という 12982 のも ' を入力した状態で補完するだけで 1600ms にまで減少する為。 12983 12984 * done: refact ble/complete/action/util/ ble/complete/action/? と思ったが色々 12985 の関数が既にある様だから、取り敢えずは現状を維持する事にする。と思ったが、 12986 やはり現在の action/inherit-from は action#inherit-from に改名して、代わ 12987 りに action/util/ を action/ に書き換えた。 12988 12989 * done: 候補の数で awk を使うか使わないかを切り替える様にしたい 12990 12991 ファイル数 従来 nawk mawk gawk 12992 100 24ms 10ms 10ms 12ms 12993 200 43ms 16ms 17ms 19ms 12994 500 106ms 35ms 39ms 41ms 12995 1k 212ms 67ms 76ms 78ms 12996 2k 424ms 128ms 147ms 150ms 12997 5k 1092ms 319ms 360ms 364ms 12998 10k 2094ms 626ms 720ms 723ms 12999 13000 適当に 500 項目以上の時に awk に切り替える事にした。 13001 但し、cygwin/msys の場合には閾値は 2k にまで引き上げる事にする。 13002 13003 * 一般の場合に適用しようとすると改行の取り扱いに気をつけなければならない。 13004 13005 というか progcomp の場合だって \ を使って候補を繋ぐ事ができたという可能性? 13006 と思ったが試しに compgen -f を実行してみたが、改行が含まれるファイル名を 13007 そのまま出力してしまっていて、別々のファイル名の時との区別がつかない実装 13008 になっているので、progcomp に限っては余り気にしなくて良い様に思われる。 13009 13010 一方で一般の場合には awk が \0 区切りに対応しているかどうかで実装方法が変 13011 わってくるのではないかという気がする。更に bash の version に依存して効率 13012 的に読み取る事のできる形式も変わってくるだろう。 13013 13014 取り敢えずは progcomp の場合だけ意識して実装して、改行に関しては注釈を加 13015 えるべきだろうと思われる。 13016 13017 * 改行が含まれている可能性があるかどうかの情報を渡してそれに応じて判定す 13018 る様に変更した。今、quote-insert.batch は終了ステータス 1 を返した時に 13019 何もしない事に注意する。 13020 13021 * 更に quote-insert.batch が使える所ではできるだけ使える様にする→取り敢 13022 えず沢山の候補が生成されそうな場所は全て yield.batch に切り替える様にし 13023 た。 13024 13025 * done: user-input で途中キャンセルできる様にする必要がある。 13026 →conditional-sync 経由で呼び出す様に変更した。動作確認した。 13027 13028 * done: xpg4 の sed でちゃんと "\\\\\\\\&" 置換が期待通りに動くかどうか確認 13029 する必要がある → "\\\\&" としなければならない様だ。その様にした。 13030 13031 x fixed: コマンド候補が全て赤く着色されている 13032 13033 → conditional-sync にした時点で駄目になっている様だ。うーん。 13034 出力結果を確認してみたがファイルは空である。何も出力していない。 13035 A & で起動したコマンドは、どうも外側でリダイレクトした fd から読み出せていない様だ。 13036 A の内部でリダイレクトする様に変更したら動く様になった。 13037 13038 2021-12-22 追加修正。"continue 0" という文が混入していた。 13039 13040 * ble/string#escape-for-bash-specialchars で HT を SP HT に置換しているのは何故? [#D1713] 13041 manu-complete 最適化中に気づいた事。 13042 13043 e344a156 ble-core.sh (Koichi Murase 2018-08-06 13:43:50 +0900 1135) a=$'\t' b=$' \t' ret=${ret//"$a"/$b} 13044 9629b9dd lib/core-complete.sh (Koichi Murase 2018-08-05 15:28:25 +0900 75) a=$'\t' b="\\$a" ret=${ret//"$a"/$b} 13045 13046 うーん。これを見ると e344a156 のリファクタリング時のミスの様な気がする。該 13047 当する項目は #D0719 であるが、たった一行で済ませているという事を考えるとこ 13048 れは本当にミスであると判定して良い。というかそもそも元々の実装自体が間違っ 13049 ている。 13050 13051 改行と同様に $'\t' に置き換えるという手と、恐らく現在・以前の実装で意図して 13052 いたと思われる \[TAB] という形に置き換えるという二つの方針が考えられる。本 13053 来意図していた筈の後者にする事にする。 13054 13055 * main: root ユーザーで入ると the owner of '' is not correct と表示される (reported by zim0369) [#D1712] 13056 https://github.com/akinomyoga/ble.sh/issues/163 13057 13058 _ble_base_run か _ble_base_cache のどちらかの初期化の途中で、ディレクトリ所 13059 有権の問題が起こっている。それからエラーメッセージにも問題がある。うーん。 13060 13061 * 再現の試み 13062 13063 取り敢えず手元で再現できないかどうかは試してからより詳細を求める事にする。 13064 13065 うーん。root と user の両方にインストールしたとしているがどのように入れた 13066 のだろうか。取り敢えず root の home ディレクトリをチェックするべきなのだ 13067 ろうか。うーん。色々やってみたが特に問題は生じていない様だ。 13068 13069 或いはインストールの方法に問題があるのかもしれない。ユーザーから root の 13070 .local/share/blesh にインストールした等。と思ったが、これだとインストール 13071 できない筈である。一方で、root からユーザーのディレクトリにインストールし 13072 た可能性? 然しそれだと root user に switch した時にエラーメッセージが出る 13073 という現象にはならない。 13074 13075 分からないので取り敢えずエラーメッセージを修正して何が表示されるか問い合わ 13076 せる事にする。 13077 13078 2021-12-19 分かった。'/run/user/1000/blesh' である。つまり、XDG_RUNTIME_DIR 13079 が su する前のユーザーのディレクトリのままになっているのが問題である。 13080 13081 * complete: FIGNORE で全てが棄却されるバグ (reported by seanfarley) [#D1711] 13082 https://github.com/akinomyoga/ble.sh/issues/162 13083 13084 これは極めて単純なバグだった。そもそも実は FIGNORE は今まで全く動いていなかっ 13085 たと思われる。 13086 13087 2021-12-16 13088 13089 * menu-complete で 30s かかるという話 (1/2) construct-page のバグ (reported by banoris) [#D1710] 13090 https://github.com/banoris/dotfiles/issues/11 13091 13092 確かに ble.sh は bash で書かれているし遅いが其処まで遅いかっただろうか。自 13093 分の手許でやってみた所、確かに bash-completion を有効にしていると 10k files 13094 に対して 15s かかっている。調べてみると良いだろうという気がする。 13095 13096 ble/complete/progcomp/.filter-and-split-compgen は 0.1s 13097 13098 うーん。_minimal 自体の呼び出しが 4 秒かかっている。ble.sh の外では 0.2s な 13099 のでこの違いは大きい。一体何処から違いが出てくるのだろうか。 13100 13101 % →実際に _minimal の時間を計測しようとしたら _minimal 自体はそんなに遅く 13102 % なかった。実は、それよりは ble/util/assign の読み取りが遅いのではないかと 13103 % いう疑惑。と思ったらそうでもなかった。_filedir が実際に遅くなっている。 13104 13105 * 何やら _filedir が勝手に置き換わっていると思っていたら 13106 /etc/bash_completion/redefine_filedir とかいう変なファイルによって実装が 13107 置き換わっていた。うーん。おかしな事をする物である。 13108 13109 古い実装では while read -r line; do done で一つずつ行を読み出しているので 13110 遅かった。これを置き換えたら _minimal の呼び出しにかかる時間はほぼ 0 になっ 13111 た。然しそれでもやはり 13s ぐらいは待たされる様である。 13112 13113 * その他の bottleneck は、2) yield ループが遅い、3) 一時ページに沢山表示し 13114 ようとしている為に menu 配置の計算が遅いという事がある。 13115 13116 yield ループに関してはどうしようもない。絞り込みをする為には結局事前に実 13117 行しなければならないので、スキップする事はできない。とすると、awk 等を使っ 13118 て加速するという事も考えられるが、処理を重複して実装するのも面倒である。 13119 それでも場合によってはそれを考えても良いのかもしれないとは思う。 13120 13121 * menu 配置で初期化遅延が効いていなかったバグ 13122 13123 | menu 配置に関してもなかなか難しい所がある。C言語で書ければそれで終わりな 13124 | のかもしれないがそれも難しい。或いはより高速な Bash スクリプトのインター 13125 | プリタについても考えてみるが、そもそも制限された Bash の機能を使って実装 13126 | しているので不自然な実装になっている。劇的に早くなるとは思えないのが現状 13127 | である。 13128 | 13129 | 実際に測定する。 13130 | 13131 | [1639646039.075008]compgen:1 13132 | [1639646039.076485]compgen-helper:2 <_minimal echo echo> 13133 | [1639646039.101227]compgen-helper:3 13134 | [1639646039.111599]compgen:2 13135 | [1639646039.111884]compgen:3 13136 | [1639646039.139718]compgen:4 13137 | [1639646039.139801]compgen:5 13138 | [1639646041.294533]compgen:6 13139 | [1639646041.464829]menu#construct:1 13140 | [1639646049.977139]menu#construct:2 13141 | 13142 | 1. compgen 呼び出しは現在は 0.04s 13143 | 2. filter-and-split は 0.028s 13144 | 3. yield に 2.15s かかっている 13145 | 4. construct-page には 8.5s かかっている。 13146 | 13147 | やはり一番重いのは construct-page である。 13148 | 13149 | complete_menu_style や complete_menu_maxlines を設定して1ページに表示する 13150 | 項目の数を制限するしかない気がする。念の為、1ページに表示する項目の数を制 13151 | 限した時に改善するかどうか確認はしておく 13152 | 13153 | →うーん。全然改善していない。8.3s である。もしかすると全項目スキャンして 13154 | いる可能性がある? 13155 | 13156 | 調べてみた所、何と全項目を処理している。しかも 13157 | .measure-candidates-in-page の時点で全て処理していて、これが最も時間を消 13158 | 費している。 13159 13160 結局 menu 配置に関して頁毎に必要なだけ trace を実行しているつもりだったのが、 13161 実は毎回全項目に対して配置計算を実行していたという事が判明した (しかしそう 13162 だとしても、耐えられる速度の範囲だったというのは驚きではある)。 13163 13164 以下の ncell_eol の式を間違えている。 13165 13166 | 43bb0749 lib/core-complete.sh (Koichi Murase 2019-03-23 21:41:19 +0900 119) if [[ $menu_style == align-nowrap ]]; then 13167 | 43bb0749 lib/core-complete.sh (Koichi Murase 2019-03-23 21:41:19 +0900 120) # Note: nowrap が起こるのはすでに wcell == max_wcell の時なので、 13168 | 43bb0749 lib/core-complete.sh (Koichi Murase 2019-03-23 21:41:19 +0900 121) # 改行処理が終わった後に wcell が変化するという事はない。 13169 | 43bb0749 lib/core-complete.sh (Koichi Murase 2019-03-23 21:41:19 +0900 122) local x1=$((ncell%line_ncell*wcell)) 13170 | 43bb0749 lib/core-complete.sh (Koichi Murase 2019-03-23 21:41:19 +0900 123) local ncell_eol=$(((ncell+line_ncell-1)/line_ncell*line_ncell)) 13171 | 43bb0749 lib/core-complete.sh (Koichi Murase 2019-03-23 21:41:19 +0900 124) if ((x1>0&&x1+w>=cols)); then 13172 | 43bb0749 lib/core-complete.sh (Koichi Murase 2019-03-23 21:41:19 +0900 125) # 行送り 13173 | 43bb0749 lib/core-complete.sh (Koichi Murase 2019-03-23 21:41:19 +0900 126) ((ncell=ncell_eol+cand_ncell)) 13174 | 43bb0749 lib/core-complete.sh (Koichi Murase 2019-03-23 21:41:19 +0900 127) elif ((x1+w<cols)); then 13175 13176 元を辿ると以下の様に一番最初に頁を実装した時から間違っていたという事の様だ。 13177 13178 | commit a488e0193927b78ea2066c5d3118ff5a38c6872c 13179 | Author: Koichi Murase <myoga.murase@gmail.com> 13180 | Date: Thu Mar 7 18:29:51 2019 +0900 13181 | 13182 | complete: support pages of menu/style:{align,dense} 13183 | 13184 | a488e019 lib/core-complete.sh (Koichi Murase 2019-03-07 18:29:51 +0900 2117) if [[ $menu_style == align-nowrap ]]; then 13185 | a488e019 lib/core-complete.sh (Koichi Murase 2019-03-07 18:29:51 +0900 2118) # Note: nowrap が起こるのはすでに wcell == max_wcell の時なので、 13186 | a488e019 lib/core-complete.sh (Koichi Murase 2019-03-07 18:29:51 +0900 2119) # 改行処理が終わった後に wcell が変化するという事はない。 13187 | a488e019 lib/core-complete.sh (Koichi Murase 2019-03-07 18:29:51 +0900 2120) local x1=$((ncell%line_ncell*wcell)) 13188 | a488e019 lib/core-complete.sh (Koichi Murase 2019-03-07 18:29:51 +0900 2121) local ncell_eol=$(((ncell+line_ncell-1)/line_ncell*line_ncell)) 13189 | a488e019 lib/core-complete.sh (Koichi Murase 2019-03-07 18:29:51 +0900 2122) if ((x1>0&&x1+w>=cols)); then 13190 | a488e019 lib/core-complete.sh (Koichi Murase 2019-03-07 18:29:51 +0900 2123) # 行送り 13191 | a488e019 lib/core-complete.sh (Koichi Murase 2019-03-07 18:29:51 +0900 2124) ((ncell=ncell_eol+cand_ncell)) 13192 | a488e019 lib/core-complete.sh (Koichi Murase 2019-03-07 18:29:51 +0900 2125) elif ((x1+w<cols)); then 13193 13194 取り敢えずこれについては修正した。 13195 13196 * complete_menu_maxlines を設定したらもっと高速になるか? 13197 →恐らく高速になる。 13198 13199 * 4.0s _filedir -> 0.04s 13200 * 2.2s yield -> ----- 13201 * 8.5s construct-page → 2.50s (これは maxlines を設定する事でもっと減らせる) 13202 13203 うーん。_filedir は外部の問題である。また construct-page は修正したが、全 13204 画面表示にしている場合には効果は限定される。yield に関してはまあ、仕方が 13205 ないのかもしれない。何れにしても construct-page の修正だけでも適用しても 13206 らって、それで様子見する。それでも改善しなかったら yield の高速化について 13207 も真面目に考える事にする。 13208 13209 complete_menu_align 13210 complete_menu_maxlines 13211 complete_limit 13212 13213 * complete: gawk-4.0.2 workaround (reported by Knusper) [#D1709] 13214 https://github.com/akinomyoga/ble.sh/issues/161 13215 13216 これは gawk のバグだった。特定のパターンの正規表現に対して false warning を 13217 出す。影響範囲が大きいと思って一つ一つ対策するのは困難かとも思われたが、正 13218 規表現で問題の正規表現を検出できる気がするので、やはり個別に対策する事にし 13219 た。 13220 13221 2021-12-15 13222 13223 * mandb: オプション候補生成で変な動作が幾つかある [#D1708] 13224 13225 * ...] という謎の項目が生成されている at man.d/man 13226 13227 どうやら以下の項目から生成されている様子だ。 13228 13229 | -m system[,...], --systems=system[,...] 13230 | 13231 | man を含めます。このオプションは $SYSTEM 環境変数を上書きします。 13232 13233 うーん。オプションを分割する時に /,\s*/ ではなくて /,\s+/ で分割する事に 13234 した。スペース無しで記述するという事は考えにくいだろう。或いは 13235 --arg=(hello, world) みたいになっている可能性もなくはないが面倒なので考え 13236 ない。OK 13237 13238 * fixed: declare で空の completion が生成されている。 13239 13240 空の候補については集約の際に混入している様だ → これは修正した。 13241 nodesc のオプションを集める時に name[count++] としていたのを name[count]; 13242 count++に分けた所、count を初期化していなかったので空文字列の添字に格納さ 13243 れる様になってしまっていたのが原因だった。 13244 13245 * fixed: wget の man page 抽出で short option の desc が空になっている。 13246 これは man.d/man 由来である → 修正した。 13247 13248 * progcolor: mandb_opts をキャッシュする様にする [#D1707] 13249 13250 progcolor_optctx と同様に。これは declare のより詳細な実装で mandb_opts を 13251 参照したいから。 13252 13253 * refactor: mandb_opts はコマンド一般用に転化しても良いのではないか [#D1706] 13254 13255 その時には cmdspec に移動して、更にそれを core-complete から読み込む様にす 13256 れば良い。と思ったが help, help-usage 等は名前的には mandb_opts 専用の物で 13257 ある。名前を変更する必要があるかもしれない。 13258 13259 或いは、help:help-usage 等 mandb 専用のオプションはそれ専用の配列に格納する? 13260 13261 取り敢えず現在使われているオプションについて整理する。また、将来的に使い 13262 そうなオプションについても考える。 13263 13264 mandb-disable-man 13265 mandb-help 13266 mandb-help-usage 13267 mandb-usage 13268 13269 plus-options=xxxxx 13270 no-options 13271 stop-options-at=IWORD 13272 stop-options-on=REX_STOP 13273 stop-options-unless=REX_CONT 13274 stop-options-postarg 13275 disable-double-hyphen 13276 13277 加えて no-options も追加するべきかも 13278 13279 →cmdspec に移動して cmdspec_opts に名前を変更した。mandb 特有の項目には 13280 mandb- の接頭辞を付ける事にした。 13281 13282 * done: 説明を書く 13283 13284 2021-12-12 13285 13286 * highlight: declare のオプション名…変数名よりも後にあるのはエラー着色にするべき [#D1705] 13287 これは #D1704 で一緒に対応した。 13288 13289 * complete: declare a -[TAB] でも候補が生成されてしまっている [#D1704] 13290 13291 →調べてみた所、これは declare の引数 (変数形式) が extract-commands で抽出 13292 されていないのが原因であった。引数の種類を調べると ATTR_VAR である。然し色々 13293 と振る舞いを調べると ATTR_VAR はコマンドの前につく a=b の形の変数代入に使わ 13294 れている単語の種類である。 13295 13296 もっと調べると declare a=b の場合には a=b の単語の種類はちゃんと ARGI になっ 13297 ている。また、a=b declare hello の時にも hello の単語の種類はちゃんと ARGI 13298 になっている。つまり、特定の条件で declare hello の変数名が変数代入であるか 13299 の様に単語登録されてしまっているのが原因である。 13300 13301 wtype の決定経緯を調べる。ctx-command/check-word-end に入った時点で既に 13302 wtype == ATTR_VAR になっている。従って、word-begin の段階で ATTR_VAR になっ 13303 ているのが問題である気がする。然し、check-word-begin の段階では wtype = 13304 CTX_ARGVX の様である。つまり、何処かで wtype が書き換わってしまっているのが 13305 原因という事になるのだろうか。 13306 13307 うーん。分かった。ble/syntax:bash/check-variable-assignment の中で ARGVI 及 13308 び ARGEI の時には = の有無に関係なく ATTR_VAR にしてしまっている。これは何 13309 故だったろうか。経緯を調べる必要がある。 13310 13311 | 2f2f0eb6 13312 | @@ -2401,7 +2406,7 @@ function ble-syntax:bash/check-variable-assignment { 13313 | # パターン一致 (var= var+= arr[ のどれか) 13314 | local suffix='=|\+=?' 13315 | ((_ble_bash<30100)) && suffix='=' 13316 | - if ((ctx==CTX_ARGVI)); then 13317 | + if ((ctx==CTX_ARGVI||ctx==CTX_ARGEI)); then 13318 | suffix="$suffix|\[?" 13319 | else 13320 | suffix="$suffix|\[" 13321 |---------------------------------------------------------------------- 13322 | commit 1823c540cfe25c952fc96d8e50ae7dab712aacaf 13323 | Author: Koichi Murase <myoga.murase@gmail.com> 13324 | Date: Mon Nov 27 23:46:09 2017 +0900 13325 | 13326 | syntax (tilde expansion): support ordinary words with variable assignment form 13327 | 13328 | @@ -2054,6 +2112,109 @@ function ble-syntax:bash/check-tilde-expansion { 13329 | ((_ble_syntax_attr[i]=ctx,i+=${#BASH_REMATCH})) 13330 | fi 13331 | [中略] 13332 | + 13333 | +## 関数 ble-syntax:bash/check-variable-assignment 13334 | +## @var[in] tail 13335 | +function ble-syntax:bash/check-variable-assignment { 13336 | + ((wbegin==i)) || return 1 13337 | + 13338 | [中略] 13339 | + 13340 | + # パターン一致 (var= var+= arr[ のどれか) 13341 | + local suffix='=|\+=?' 13342 | + ((_ble_bash<30100)) && suffix='=' 13343 | + if ((ctx==CTX_ARGVI)); then 13344 | + suffix="$suffix|\[?" 13345 | + else 13346 | + suffix="$suffix|\[" 13347 | + fi 13348 | @@ -2577,51 +2760,6 @@ function ble-syntax:bash/ctx-command/.check-word-begin { 13349 | return 0 13350 | } 13351 | 13352 | -## 関数 ble-syntax:bash/ctx-command/.check-assign 13353 | -## @var[in] tail 13354 | -function ble-syntax:bash/ctx-command/.check-assign { 13355 | - ((wbegin==i)) || return 1 13356 | - ((ctx==CTX_CMDI||ctx==CTX_ARGVI)) || return 1 13357 | - 13358 | - # パターン一致 (var= var+= arr[ のどれか) 13359 | - local suffix='=|\+=?' 13360 | - ((_ble_bash<30100)) && suffix='=' 13361 | - if ((ctx==CTX_CMDI)); then 13362 | - suffix="$suffix|\[" 13363 | - elif ((ctx==CTX_ARGVI)); then 13364 | - suffix="$suffix|" 13365 | - fi 13366 |---------------------------------------------------------------------- 13367 | 7d862418 (Koichi Murase 2017-03-01 06:29:55 +0900 2580) ## 関数 ble-syntax:bash/ctx-command/.check-assign 13368 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2581) ## @var[in] tail 13369 | 7d862418 (Koichi Murase 2017-03-01 06:29:55 +0900 2582) function ble-syntax:bash/ctx-command/.check-assign { 13370 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2583) ((wbegin==i)) || return 1 13371 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2584) ((ctx==CTX_CMDI||ctx==CTX_ARGVI)) || return 1 13372 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2585) 13373 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2586) # パターン一致 (var= var+= arr[ のどれか) 13374 | 69bac74a (Koichi Murase 2015-12-24 21:47:15 +0900 2587) local suffix='=|\+=?' 13375 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2588) ((_ble_bash<30100)) && suffix='=' 13376 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2589) if ((ctx==CTX_CMDI)); then 13377 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2590) suffix="$suffix|\[" 13378 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2591) elif ((ctx==CTX_ARGVI)); then 13379 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2592) suffix="$suffix|" 13380 | be5c4616 (Koichi Murase 2015-12-23 22:09:39 +0900 2593) fi 13381 | 13382 | commit be5c461693ddacd2acf581011c3decd1390641d5 13383 | Author: Koichi Murase <myoga.murase@gmail.com> 13384 | Date: Wed Dec 23 22:09:39 2015 +0900 13385 | 13386 | (ble-syntax:bash): special treatment of arguments of `declare'. 13387 | 13388 | * (ble-syntax:bash): declare, typeset, local, export, alias コマンドの引数を文法的に特別に扱う。特に配列構文 =() を許容する。 13389 | その為に新しい文脈値 CTX_ARGVX, CTX_ARGVI を追加する。 13390 | * (ble-syntax:bash): CTX_ARGVI に対する補完候補は変数名。等号 '=' 以降の部分についてはファイル名の補完候補を列挙する。 13391 | * (ble-syntax:bash): 通常の代入構文における配列構文の動作を変更。 13392 | [以下略] 13393 | 13394 | +2015-12-23 13395 | + 13396 | + * ble-syntax:bash declare 配列初期化構文対応 13397 | + 13398 | + > * [2015-02-16] ble-syntax.sh: local a=(arr) a+= 13399 | + > これは declare や local typeset readonly 等を文法的に特別扱いしなければ対応できない 13400 | + 13401 | + 色々試してみた所、以下のコマンドの引数で =() を特別扱いする様である。 13402 | + declare readonly typeset local export alias 13403 | + alias に関しては他のコマンドと全然性質が違う様な気がするし、 13404 | + export に関しては配列の初めの要素しか export されない気がするが、 13405 | + 文法的には両者とも =() の形式を許容する様である。 13406 | + 或いは、他にも同様の形式の引数を許容する組コマンドが存在するかもしれない。 13407 | + 13408 | + (少なくとも echo などの組み込みコマンドや、外部コマンドに関しては 13409 | + 引数に =() 等という物が含まれていると失敗する。) 13410 13411 これを見る限りは特別扱いは ARGVX, ARGVI を導入した最初の瞬間からあった様で 13412 ある。特に後付で ARGVI に対して特別扱いを実装したという訳ではなく、最初から。 13413 実装の経緯を観察する限りはどうも補完で変数名を生成させる為に特別な単語の種 13414 類を割り当てている様な気がする。一方で現在の実装に於いては、補完は特に 13415 wtype を参照している訳ではないのでこの様に特別に取り扱う理由もない気がする。 13416 13417 * ARGVI, ARGEI の際の変数代入で = を要求しない振る舞いは修正する方向で考え 13418 る。 13419 13420 x 然し、そうしたら単語着色が消えてしまった。うーん。ARGVI 及び ARGEI の時に 13421 は単語着色はするべきだろうか。 13422 13423 先ず文法レベルで。それから引数レベルで。 13424 13425 | うーん。先ず初めに、文法レベルでの着色については ARGVI だけで良い。 13426 | ARGEI の時には = 無しで単語が現れたとしたらそれは単語ではないので着色し 13427 | なくて良い。 13428 | 13429 | そもそも文法レベルの着色をするべきなのかという疑問も実は存在する。bash 13430 | の文法的には実は declare hello= は変数代入になっているが、declare hello 13431 | は変数代入になっていないと思われる。という事を考えると文法レベルの着色 13432 | はするべきでない。 13433 13434 引数レベルの着色については declare 系列専用の着色を定義する必要がある。 13435 13436 うーん。ble/cmdinfo/color: という名前も何だか微妙な気がするが、これは後 13437 でいくらでも変更できるので取り敢えずは実装する。既存の実装は存在してい 13438 ない様だ。ble/cmdinfo/chroma: に変更する。 13439 13440 うーん。ファイルを分離しようと思ったが名前はどうしたら良いだろうか 13441 ... やはり cmdinfo は何だか名前として不自然な気がする。core-cmdinfo, 13442 13443 | * core-help, core-man, core-mandb, core-info, core-whatis, core-which, 13444 | これらは既存のマニュアル系のコマンドの名称を取ってきた物。 13445 | 13446 | * core-catalogue, core-manual, core-dictionary, core-book, 13447 | corer-guidebook, core-map, core-cmdmap, core-reference, 13448 | core-commandreference, core-cmdref (reference 系は別の意味になるので 13449 | 駄目), core-library, core-cmdlib, core-spelllib (library 系も別の意味), 13450 | core-spellbook ... 或いはより現実的な物に例えてみる等の方針。 13451 | 13452 | * core-getopt これは、実際に cmdinfo を定義する主要な形態として getopt 13453 | 的な方法を考えている事から。然し、これだけが唯一の定義方法という訳で 13454 | もないし、getopt は更にその上の階層の枠組みに名付けたい気がする。実際 13455 | には、cmdinfo の中に定義する形になるのではないかと考えている。 13456 | 13457 | * core-cmddb, core-database (一般的過ぎる), core-commanddatabase, 13458 | core-cmdspec, core-commandspec, core-cmdspec 13459 13460 うーん。cmdspec の方が幾らかましの気がするので取り敢えず cmdspec という 13461 事にする。 13462 13463 然し本当に cmdspec に定義するべきなのだろうかという疑問も残る。実は 13464 bash-completion でやっている様に contrib/cmdspec/* の下に個別のファイル 13465 として定義した方が良いのではないかという疑惑。うーん。然しそうだとして 13466 も取り敢えずの実験的な実装として cmdspec の中に色々記述して API が落ち 13467 着いてからファイルに分割するというので良い気がする。そう。それがしたかっ 13468 た事の気がする。 13469 13470 o ちゃんと引数レベルでの着色で変数名着色ができている。 13471 13472 o declare の通常引数の後のオプションをエラー着色する機能もOK 13473 13474 * done: コマンドレベルで declare, etc. + alias の着色を行う。 13475 うーん。alias については今回は対応しなくて良い。 13476 13477 * done: 変数代入も extract-command で列挙する。但し、extract command に影響 13478 がない様にしなければならない。 13479 13480 x fixed: もう一つの謎は a=b declare a= の形式の時には変数代入が検出されない 13481 という事。そもそも、変数名着色だって無効化されている。これは一体どういう 13482 事だろう 13483 13484 調べてみると "a=b declare@ " の時には @ の位置に stat ARGX が置かれている 13485 様である。一方で、 "declare@ " の場合には @ の位置には stat は置かれてい 13486 なくて、代わりにその次の位置に ARGVX が置かれている。この振る舞いは他の通 13487 常コマンド (echo など) でも同様であった。CMDXV の特別な振る舞いという事な 13488 のだろうか。 13489 13490 →うーん。正にそれを実行するコードが check-word-end にある。これはどうい 13491 う事だろうか。→分かった。どうもこれは変数代入の直後にはキーワードは来な 13492 いという事を養成する為のコードの様だ。昔は単に ctx=ARGX を設定して抜けれ 13493 ば良かったが、その後の複雑化で只単に ARGX を設定すれば良いという訳ではな 13494 くなった。各文脈に応じた複雑な処理を CMDXV の時にも実行する必要がある。 13495 13496 o ok: declare a -[TAB] での候補生成の抑制は動いている。 13497 13498 幾つか残っているのを修正する必要がある。 13499 13500 * ok: global -- が着色されていない。これは今確認したらちゃんと動いている。 13501 勘違いだったか或いは別の物を修正した時に一緒に直ったか。 13502 13503 * done: blerc, wiki, 移動: argument_error 13504 13505 * done: ble/syntax/progcolor は最早 ble/progcolor で良いのではないか。そも 13506 そも純粋な文法解釈から離れてきていて、bash 特有の実装になっている。 13507 13508 2021-12-11 13509 13510 * [External] bash-completion: printf -v ... [#D1703] 13511 https://github.com/akinomyoga/ble.sh/issues/155#issuecomment-984619516 13512 13513 これは bash-completion 側で対応するべき事の気がする。 13514 13515 取り敢えず --help 対応が終われば、変数名の補完はできないにしても、オプショ 13516 ンの表示ぐらいはできる様になる。printf の場合には最初の引数には '' を指定す 13517 るのが良い気がする → 取り敢えずオプションは表示される様になった。 13518 13519 * [External] bash-completion: better support for "test", "[" [#D1702] 13520 https://github.com/akinomyoga/ble.sh/issues/158 13521 13522 これも bash-completion の側で対応するべき事の気がする。 13523 但しオプションの説明についてはちゃんと生成しなければならない。 13524 progcomp の枠組みで説明も一緒に生成できる仕組みがあっても良いのではないか。 13525 13526 うーん。生成し切れていない物は別枠で指定する? うーん。getoptions 的仕様を確 13527 定する必要がある気がする。 13528 13529 * complete: [[ 及び declare の補完 (requested by EmilySeville7cfg) [#D1701] 13530 https://github.com/akinomyoga/ble.sh/issues/155 13531 https://github.com/akinomyoga/ble.sh/issues/157 13532 13533 | user-customization を許可? 或いは自前で実装しても良い 13534 | 13535 | うーん。declare に関しては a=(....) 等が含まれる場合の取り扱いが謎だし、 13536 | 自前で実装する方が良いのではないかという気もする。 13537 | 13538 | 一方で [[ についてはユーザーが指定できる様にする? と思ったが、それでも今度 13539 | は [[ (a == b && c== d)||x == y ]] 等の様な入れ子構造があった時に、ユーザー 13540 | に渡すコマンドラインを構築するのが大変である (実は現状の実装だとそんなに難 13541 | しくないかもしれないが、此処は将来的に改修する予定なので現段階で下手にユー 13542 | ザーインターフェイスを提供すると、将来弄る時に面倒な事になる)。また'[[' '(' 13543 | 'a' '==' 'b' '&&' ... という具合に分割するのが自然だと思われるが、一方で勝 13544 | 手に空白を挿入しても良いのかだとか色々よく分からない (まあこれは実装を詳し 13545 | く観察して調整すれば済む話ではある)。 13546 | 13547 | うーん。結局、どちらも自前で実装した方が良い様に思われる。これは仕方がない 13548 | ので、取り敢えず自前の実装を提供する事にして customization については諦めて 13549 | 貰う事にする。 13550 13551 将来的に自前で実装する事にする。 13552 13553 取り敢えず declare 系統は簡単な気がするので先に実装することにする。 13554 13555 * done: 現在 source:option に於いて ["--" 以降のオプションを解釈しない] や 13556 [非オプションよりも後のオプションを解釈しない] などの各コマンドの性質はほぼ 13557 ハードコードされている。これを外部から指定できる様にする。 13558 13559 * ok: ble/complete/mandb/get-opts ... alias 展開もする? → refactor して、 13560 alias 展開なども全て処理して mandb が見つかった時点で初めて get-opts を呼 13561 び出す様に変更した。 13562 13563 * done: 更に $_ble_complete_option_chars もちゃんと様々の箇所で使う様にする。 13564 →これは元々より緩いのを部分的に厳しくしているだけなのでそんなに気にしな 13565 くて良い様に思われる。 13566 13567 x fixed: "declare [TAB]" で補完が開始されない。 13568 13569 * done: +o に関しては一番最後の集計時に説明を適用に生成する。 13570 13571 * done: mandb: 現在 + で始まるオプションは積極的に抽出していない。これにも対応したい。 13572 13573 * ble/complete/mandb:help/generate-cache (--help|--usage 抽出用) については対応した。 13574 13575 * generate-from-man は未だ → 対応した。微妙な修正しかしていないが多分これ 13576 で大丈夫。 13577 13578 x "top -[TAB]" が正しく動作しない。 13579 13580 取り敢えず declare については大体完了した。 13581 13582 [[ に関しては文法も考慮したより正しい補完をすぐに実装するのは難しいが、取り 13583 敢えずオプションだけは生成できる様にするのが良い。 13584 13585 * 文脈だけでも確認する → 部分的には対応していたみたいである。ファイル名を 13586 補完していた。其処に source:option を追加する。 13587 * それから空文字列からの補完の設定が欠けていたのでそれも追加する。 13588 * mandb_opts に複数の help=... を記述できる様にする。 13589 * オプション抽出で -a, --file=<...> や -b (this is test) 等の形式の物にも対 13590 応した。 13591 13592 * complete: 沢山 quote が発生する場合には '' で囲むべきなのではないか [#D1700] 13593 13594 然しこれだと、例えば 'a b c' と 'alpha' というファイルがあった時に前者は 'a 13595 b c' を生成して、校舎は alpha を生成する事になり、共通一致部分がなくなって 13596 しまう。共通一致部分をちゃんと求める為には、候補によらない quote の方法に頼 13597 らざるを得ない。そうすると、 a' b c' 等の様な不格好な物になってしまうという 13598 気がする。 13599 13600 或いは最後の挿入時に、COMPS= の時に挿入文字列を修正するという事も可能かもし 13601 れない。 13602 13603 うーん。今までの実装を見ると ACTION/complete で suffix を修正はしているが、 13604 挿入文字列本体 insert を変更している例は見当たらない。然し、呼び出し側の実 13605 装を見る限りは insert を自由に取り替えても問題は無いように見える。というの 13606 も insert 自体が、determine-common-prefix によって動的に生成されているから 13607 である。特に COMPS= だった時によりコンパクトな表現に変更するというのは十分 13608 に考えられる処置である。 13609 13610 実装してみた。良い。置き換える時に違和感があるかもしれないと思ったが、実際 13611 やってみると "絞り込み用の表現" が最終的なコンパクトな表現に切り替わる瞬間 13612 というのは気持ちの良い物である、という感じである。 13613 13614 * done: もう少し積極的になっても良いのではないか。例えば / や = の直後から 13615 補完を開始した場合等にも適用して良いのではないか → 対応した。 13616 13617 x fixed: requote を実装したら頭の悪い auto-complete が表示されている 13618 13619 cd tmp/filename_contains_symbols/'() () [] directory'/ [tmp/filename_contains_symbols/\(\)\ \(\)\ \[\]\ directory] 13620 13621 これは bash-completion がなくても再現する現象である。うーん。 13622 auto_complete の候補表示に於いて ACTION/complete で insert が変更されない 13623 という事を仮定しているのかもしれない。 13624 13625 うーん。ACTION/complete 前の状態を見ると以下の様になっている。 13626 COMPS="tmp/filename_contains_symbols/'() () [] directory'/" 13627 insert="tmp/filename_contains_symbols/\\(\\)\\ \\(\\)\\ \\[\\]\\ 13628 directory" ACTION=file 13629 13630 分かった。insert が COMPS を prefix として保持していないのが原因である。 13631 然し、何故その様な事になっているのだろうか。どうしたらこの様な候補が生成 13632 されるのだろうか。本来は COMPV が共通している筈だから除外されるのではない 13633 のか。 13634 13635 →何故この様な事になっているか分かった。その実、この補完候補は単語を短く 13636 する (末尾の / を除去する) 事を提案しているのである。なので、遡った書き換 13637 えとなって quote が保持されないという形になっているのである。 13638 13639 うーん。遡った書き換えの時にはどうせ全体が置き換わるのだと思えば、やはり 13640 全体を requote してしまっても良いのではないか? 13641 13642 x fixed: そもそもスラッシュが除去される時点で変なのでは? どうやって候補が生 13643 成されているのだろうか → construct-ambiguous-pattern が誤っていた。今ま 13644 でに予期せず遡って置き換えが起こったりしていたが、それの原因の一端は此処 13645 にあるのかもしれない。 13646 13647 * README: 一つのキーで複数の widget を呼び出す方法? (motivated by michaelmob) [#D1699] 13648 https://github.com/michaelmob/portable-config/commit/49f9566afd8b62d47a090328104ad803962e6d3f 13649 13650 説明を書いた。設定例の動作確認もした。 13651 13652 * bind: "" で囲まれていない keyseq \C-l を解釈できない (motivated by cmplstofB) [#D1698] 13653 https://github.com/cmplstofB/dotfiles/blob/master/_dffiles/.config/bash/bashrc#L170-L172 13654 13655 うーん。bash の振る舞いを色々調べてみた所、"" で囲まれていない時にはやはり 13656 完全には解釈しないが、\C-x 等の形の時は解釈できる様だ。 13657 13658 * \C-x\C-y の時には \C-y と解釈される。 13659 * xyz の時には x と解釈される。 13660 * \a も \ と解釈される。 13661 * \C-nop は \C-n となる。 13662 * \C-xC-y は C-y となる。 13663 * \C-axC-b は C-b となる。 13664 * helloC-b も C-b となる。 13665 * helloC-x,TAB も C-x となる。 13666 * C-xTAB も C-x となる。 13667 * TABC-x も C-x となる。 13668 * BC- は C-@ となる。 13669 13670 つまり…最後の "C-文字" が採用される? 13671 13672 * C-M-a および M-C-a は \201 となる。 13673 * C-aalpha-beta は C-b となる。 13674 * \C-a\M-c は \203 である。 13675 * panic-trim-c は \204 である。 13676 13677 つまり、最初に - で split してそれから評価している。 13678 13679 * C-- は C-@ になる。 13680 * C--x は C-x になる。 13681 * - は抑々指定できない (bind に対するオプションと解釈されてしまう)。 13682 inputrc に入れたら恐らく C-@ になるのだろうという気がする。 13683 13684 取り敢えず bash と同様の振る舞いになる事を確認した。 13685 13686 * util (cursor-state): tmux や screen の中では pass through シーケンスを用いる? (motivated by cmplstofB) [#D1697] 13687 https://github.com/cmplstofB/dotfiles/blob/3e41ac47f47cc7788215409a5c3f26635f02d6a0/_dffiles/.config/blesh/blerc#L193 13688 13689 tmux: \ePtmux;%s\e\\ (中に含まれる \e は二重にする) 13690 また tmux; の部分は存在しなくても良い様である (https://gist.github.com/saitoha/4723390) 13691 screen: \eP%s\e\\ 13692 13693 対応した。 13694 13695 * done: 本来は外側の端末の対応状況に応じて _ble_term_Ss を送るべきの気がする。 13696 13697 | 然しそうするとユーザー設定または terminfo の _ble_term_Ss とどちらを優 13698 | 先するべきなのかという問題が生じる。うーん。実質的に _ble_term_Ss は対 13699 | 応しているとしたら一意なので、有限文字列かそうでないかだけが問題である。 13700 | だとすれば、ble.sh の側で外側の端末が Ss に対応していると判定したならば、 13701 | それに対応するシーケンスを送りつけてしまって問題ない気がする。 13702 13703 _ble_term_Ss が空で端末multiplexerの外側の端末が対応していると判断できる時、 13704 独自の判断で外側の端末の対応する DECSCUSR を pass through で送信して良い。 13705 13706 Note: _ble_term_Ss が空でない時には既に外側に pass through で送りつける様に 13707 なっている。但し、_ble_term_Ss に設定された値を尊重する。ユーザーが好みで設 13708 定しているかもしれないので。 13709 13710 →外側の端末情報の取得も実装した。任意の階層だけ入れ子になった端末マルチ 13711 プレクサでもちゃんとカーソル形状の変更が伝播する様になった。 13712 13713 * edit: self-insert の振る舞い [#D1696] 13714 13715 * 一番最後のキーを挿入するべき。現在は一番最初のキーを挿入している。 13716 * C-l 等、対応する制御文字が存在する物については単に ctrl を外すのではなくて、その元々の文字に復元するべきである。 13717 13718 或いは CHARS を直接挿入するべき? → CHARS を確認したが此処には escape 13719 sequence の文字列が入っているという事の気がする。うーん。何れにしても 13720 fallback なので気にしなくて良い様な気がする。 13721 13722 * 類似の物が実は幾つかある。isearch や auto_complete で読み出す部分。 13723 他にも _ble_decode_MaskChar や KEYS[0] を参照している箇所は確認するべきである。 13724 13725 o bind '"\C-t\C-l":self-insert' 13726 o ble-bind -f 'C-t right' self-insert 13727 13728 * wiki: C-BS に対する binding について記述した (found by banoris) [#D1695] 13729 https://github.com/banoris/dotfiles/commit/f36b396c8de18159e9b5cf23974f789e3766d8ba 13730 13731 2021-12-08 13732 13733 * complete: bind -[TAB] で bash-completion がオプションを生成してくれない [#D1694] 13734 ble.sh の外側ではちゃんと生成してくれている。 13735 13736 これは分かった。上書きしている builtin が --usage オプションに対応していな 13737 いのが原因。というか unrecognized option と表示する時に、エラーメッセージと 13738 して usage を出力していて、それに従って usage が出力されているのであった。 13739 13740 うーん。これに対してはどの様に対処するべきだろうか。つまり、bash-completion 13741 は敢えて誤った用法でコマンドを呼び出してその結果を解析している。上書きする 13742 builtin は誤った用法に対するエラー時の振る舞いに対しても同様に振る舞う必要 13743 があるのだろうか? 13744 13745 * mandb: --help から読み出し? [#D1693] 13746 https://github.com/akinomyoga/ble.sh/issues/158 13747 13748 少なくとも builtin に関しては (一部を除き) --help を使っても良いのでは? 13749 13750 bash-completion で --help を呼び出している物に関しては --help を参考にして 13751 も良いのではないかと思われる。_parse_help 辺りに hook してしまえばこちらの 13752 物である。 13753 13754 * というか、--help を使っても良いコマンドのリストを contrib に保持しても良 13755 いのではないかという気がする。 13756 13757 * うーん。bash-completion の _parse_help に hook して、_parse_help が呼び出 13758 されたらそれに対応するオプションを使って db を構築しようとも思ったが、こ 13759 れだと bash-completion が呼び出される迄は更新されない。 13760 13761 それよりは自前で --help が使えるコマンドの一覧を保持していた方が良いので 13762 は? と思ったが、それだと --help を呼び出すのに -h を使うコマンドや '/?' 13763 を使うコマンドなど、コマンド毎の変化を管理するのが面倒である。 13764 13765 それよりは bash-completion 経由で必要な時に情報を読み取る方が良い? 13766 13767 と思ったが、bash-completion で複数の異なるオプションで _parse_help を呼び 13768 出した時に、どの様にキャッシュを統合するのかというのが問題である。そもそ 13769 も man との統合でも問題になる。bash-completion を呼び出す前の時点で man 13770 から呼び出してキャッシュを作ってしまうと以後それを使う様になってしまう。 13771 なので、bash-completion で _parse_help を呼び出した時に man & --help で再 13772 生成しなければならないのではないだろうか。或いは、man から生成されたデー 13773 タと --help から生成したデータは別々に管理する事にして、後でそれを統合す 13774 るという形にするのかもしれない。その時には、_parse_help の他に 13775 _parse_usage だとか或いは _parse_help の異なるオプションの場合についても 13776 全て統合する必要がある。 13777 13778 * man と --help のどちらを優先させるべきか? 13779 13780 | かなり面倒である。後、man による説明と --help による説明のどちらを優先さ 13781 | せるべきなのかという問題も生じる。 13782 | 13783 | o man の方が詳しい説明がある? 13784 | 13785 | x 或いは --help の方が簡潔な説明になっているから menu の desc に表示する 13786 | のに適している? 13787 | 13788 | x man 日本語は古い事があるのでコマンドの --help の方が良い? 13789 | 13790 | o 逆にコマンドには直接日本語の説明が対応されていなくても man では対応され 13791 | ているという事があるのではないか? と思ったが逆のパターンもあるだろうし 13792 | 一概には言えない。 13793 | 13794 | man の方は単にファイルを用意すれば良いだけなので対応は簡単である。一方 13795 | で、翻訳量が多いという観点で --help よりは対応が遅れているのではないか 13796 | という考え方もできる。 13797 | 13798 | 一方で --help の方の日本語対応については、そのコマンドが locale に依存 13799 | して振る舞いを変えなければならないので、そういう意味で対応が遅れている 13800 | 可能性はある。特に python や go や rust 等、新しい言語で書かれた物につ 13801 | いては i17n の標準的な方法が確立しているのか怪しい。とすると対応が遅れ 13802 | ているという可能性があるのではないか。然し、そもそもそう言ったツールに 13803 | 至っては man ですら対応していないかもしれない。結局分からない。 13804 | 13805 | o man から抽出した物については太字や下線等の装飾がついている。--help で 13806 | は装飾をしている事は滅多にない。あったとしても抽出の過程で削除しなけ 13807 | ればならない気がする。 13808 13809 --help を優先させるべきの気がする。つまり、同じオプションに関する説明があっ 13810 たら --help から抽出した物を優先させる。太字等の装飾については諦めるし 13811 かない。 13812 13813 * コマンドによっては man を無効化する選択肢があっても良いのでは? 13814 13815 然し、余分に man から生成したとしても余分な選択肢が表示されるだけで、ある 13816 べき物が欠けるといった形での不都合は生じない。また、man が有用な情報を含 13817 んでいなかったとしても man から何も抜き出せないという形になるだけの気がす 13818 るので気にしなくて良い気がする。 13819 13820 うーん。と思ったが… declare や bind 等は bash のマニュアルからオプション 13821 を拾ってしまうかもしれないのでやはり抑制する機能があっても良いのではない 13822 か。 13823 13824 * bash-completion でオプションを生成したとしても、内部的には _parse_help を 13825 呼ばない可能性はある。そう考えると --help を用いるコマンドのリストを管理 13826 して良い気がする。 13827 13828 * todo: 存在しないコマンドについて mandb cache を生成するのは無駄なのではな 13829 いか。一応存在チェックをしてから mandb 生成を試みるのが良い気がする。 13830 13831 然し、何処かのディレクトリに入っているコマンドの場合にはどうするのか? 13832 abc/def/hello.exe に対して mandb を呼び出す場合には結局 hello.exe が呼び 13833 出されるのではないか。 13834 13835 然し、そもそも abc/def/hello.exe としなければ呼び出せないコマンドで普通に 13836 hello.exe では呼び出せない物が、man の中に説明があるとも考えにくい。とい 13837 う事を考えると、mandb はやはり存在するコマンドに対してだけ生成すれば良い 13838 気がする。 13839 13840 [方針] 13841 13842 * done: 存在しないコマンドに対しては mandb キャッシュは生成しない。 13843 13844 * <del>man は常に有効。</del> 13845 13846 * done: それとは別に --help を使えるコマンドのリストを保持する。printf 等は 13847 その最たる例。man を抑制するリストも用意する。うーん。リストよりは 13848 ble/set# の方が良いのかもしれない。うーん。ble/gset は実装していない。寧 13849 ろ ble/gdict の方が良い気がする。其処に opts 方式で色々格納できる。 13850 13851 * done: _parse_help 及び _parse_usage に trap する。呼び出し方に応じて異な 13852 るファイルに保存する。その後で、既存の個々のキャッシュ (man, help, usage, 13853 ...) を纏めて統合キャッシュを再生成する。 13854 13855 Note: _parse_help は必ずしも補完したいコマンド名に対して呼び出される訳で 13856 はない。例えば gcc については prefix/share/libexec/cc1 的な物に対して 13857 --help が呼び出される。 13858 13859 → _parse_usage をしてもオプションの一覧が取得できるだけで説明を生成でき 13860 る訳でもない。という事を考えれば、_parse_usage には対応しなくて良い気がする。 13861 13862 * done: desc が一つもない場合には desc にする必要はないのではないか。 13863 13864 * done: と思ったが _parse_usage からオプション引数を取るか取らないか程度の 13865 情報は抜き出せるような気もする。実装した。取り敢えずは動いている様な気が 13866 する。 13867 13868 * fixed: hash-pjw の実装が怪しい 13869 13870 * done: help 解析で -a, --aaaa=X は -a X, --aaaa=X に翻訳する必要がある。 13871 13872 2021-12-06 13873 13874 * highlight: for の第一引数のファイル名着色はしない。変数名着色はする [#D1692] 13875 13876 for - の word highlighting で option を除外。というか for の highlighting 13877 を普通のコマンドとして処理しているのはおかしい。 13878 13879 for - in のエラー着色は - だからしていると考えていたがそうではなかった。唯 13880 単に for 文が不完全であることによるエラー着色だった。というか for の第一引 13881 数は変数名に合致しない物を指定した時にはエラー着色になる様にするべきである。 13882 13883 うーん。どうやら for の変数名の部分は here-document の word と同じで、切り 13884 出しは文法的に行われる物の、実際にはコマンド置換もクォート除去も何も解釈さ 13885 れずに直接変数名かどうかの判定対象となる様である。 13886 13887 取り敢えず arr[xxx] 等に対してはエラー着色が出る様にしたが、その他の入れ子 13888 構造 (例えば "for $(echo var)" など) に対してはエラー着色になっていない。 13889 13890 * 2021-09-08 complete: 'fo で補完すると 'for' になってしまうが for はキーワードなので駄目 [#D1691] 13891 13892 元々の compgen では対応しているのに ble.sh が勝手に quote を変更するから 13893 駄目なのだろうかと思ったが、元の compgen -c ではそもそも "'f" や "'f'" を 13894 渡しても何も候補生成されなかった。 13895 13896 更に plain Bash の補完でも 'fo で補完すると 'for' が補完されてしまう。と 13897 いう事を考えると ble.sh だけの問題ではないのでそんなに気にしなくても良い 13898 のかもしれない。 13899 13900 * ble.sh: complete check-here を制限 (reported by EmilySeville7cfg) [#D1690] 13901 https://github.com/akinomyoga/ble.sh/issues/156 13902 13903 check-here を完全に消すと恐らくコマンド名を生成できない。 13904 13905 実装を確認した。ARGX 系統は直前に必ず空白の類が存在して check-prefix で生成 13906 される。なので、ARGX 系統に関しては check-here から削除してしまって問題がな 13907 い様に思われる。 13908 13909 元々、check-here に残していたのは、候補が全く生成できない時にその場で前の単 13910 語に続けて生成したい事があるかもしれないという事だったが、よく考えてみれば 13911 その様な使い方が有用な場合は意図的にその様に設計された限られた状況だし、そ 13912 の様な状況の場合には、前の単語の補完の一部としてその様な候補を生成するべき 13913 である。従って、check-here による ARGX 系統の補完文脈は寧ろ削除するべきであ 13914 る。 13915 13916 x fixed: 2021-12-11 complete: 何故か空の引数から補完を開始する事ができない 13917 13918 | と思ったが、これはもしかするとつい先日修正した物が原因なのかもしれない。 13919 | →うーん。そうだった。これは困る。どう判定するのが良いのだろうか。もう面 13920 | 倒なので空白で判定する。依然として "for \ " の直後で問題になりそうだが仕 13921 | 方がない。 13922 | 13923 | うーん。然し類似のケースとして "echo hello[TAB]" の時には何故問題にならな 13924 | かったのか? 或いは一つでも補完文脈が生成されていれば、check-here は有効化 13925 | されないという事? → と思ったらそうだった。.check-here 関数の一番初めで、 13926 | 既に source が存在していた時には何もせずに戻る様になっている。 13927 | 13928 | つまり、今回の問題点は何だったかというと…FARGI1 及び FARGX1 に対して正し 13929 | く補完を生成しなかった事? うーん。然し実装を見る限りはちゃんと生成しそう 13930 | な物である。 13931 13932 "echo hello[TAB]" で問題にならないのは何れにしても check-prefix で引っか 13933 かって補完文脈が生成されるので、check-here が抑制されるからである。然し、 13934 "for -[TAB]" の時には - から始まる補完文脈を生成できないので、check-here 13935 が始まってしまう。本来、"-" が文法的に正しくないとしたら、その位置からの 13936 補完は存在しないという事で、何も生成しない補完文脈を此処に設置するべきな 13937 のである → 新しく source:none を作成してそれを使う事にした。 13938 13939 x fixed: { echo; } 'f[TAB] を実行すると fi' の様に補完されてしまう。"fi と 13940 すると fi" になるし、$"fi とすると fi" になる。つまり、遡って書き換えが起 13941 こっているのにも拘らず、終端の quote が付加されてしまっている。 13942 13943 これは action:literal-word のバグだった。修正した。 13944 13945 * mandb: 空文字列の時にも mandb に基づくオプション生成を実行するべき [#D1689] 13946 13947 * 2021-08-30 complete: オプションの説明と progcomp の integration を考える (motivated by Shahabaz-Bagwan, bbyfacekiller and EmilySeville7cfg) [#D1688] 13948 https://www.youtube.com/watch?v=YS1vxEhd2Pc 13949 https://github.com/akinomyoga/ble.sh/issues/132#issuecomment-908266634 13950 https://github.com/akinomyoga/ble.sh/issues/152 13951 https://github.com/akinomyoga/ble.sh/issues/155#issuecomment-984596470 13952 13953 complete: 折角 option の説明を抽出する機能を実装しても 13954 bash-completion を使っていると説明が表示されない。 13955 だからと言って bash-completion を無効にするのも惜しい。 13956 13957 やはり bash-completion のオプション生成に介入するべきだろうか。 13958 或いは bash-completion に限らず progcomp を使っている場合には、 13959 最後にオプション名の抽出を試みるというのも手である。 13960 13961 * mandb: awk, sed の man ページからの抽出に失敗している (reported by bbyfacekiller) [#D1687] 13962 https://github.com/akinomyoga/ble.sh/issues/152 13963 13964 当初は bash-completion との integration の問題かとも思ったが、それ以前に 13965 mandb での抽出に於いて awk, sed でそれぞれ異なる形で失敗していた。両方につ 13966 いて対応した。 13967 13968 更に、awk の man page の中にある ".ig ... .." はコメントセクションの様だ。 13969 古いオプションや文章が含まれているらしい。 13970 13971 2021-12-07 更に "wget" も補完されないという事が報告されていた。他にもあるか 13972 もしれないと思って色々動作を確認する。"bc", "mv", "fish" 等に対して追加で抽 13973 出コードの修正を行った。man のオプションの説明の形式には一貫性が全然ないの 13974 でコマンド毎に表現の仕方が異なるというのは問題である。それでも、典型的なパ 13975 ターンというのは有限である筈なので、それで大体カバーできると思うしかない。 13976 13977 2021-12-08 更に "ping" もちゃんと man から抽出できていなかった。 13978 13979 2021-12-09 man から抜き出す時に -c, --cookies=<cookies.txt> の引数が -c の 13980 側に適用されていなかった。help の方の実装を参考にして対応した。 13981 13982 2021-12-12 "top" の抽出に失敗していると思ったら fmt4 の desc が終 13983 端できていなかった。空行がある場合には強制的に中断する事にした。 13984 13985 * 2021-09-06 menu: fish の様に twocolumn 形式で表示する desc を作っても良いのではないか (motivated by Shahabaz-Bagwan) [#D1686] 13986 https://www.youtube.com/watch?v=YS1vxEhd2Pc 13987 https://github.com/akinomyoga/ble.sh/issues/132 13988 13989 或いは任意の column の数に設定できる様にする。或いは、望ましい幅的な物 (最 13990 小幅でも良いかもしれない) を設定して column 数を自動で決定する。 13991 13992 実装してみた。 13993 13994 x fixed: 再表示の際に truncate した内容が表示されてしまう。今までの実装では 13995 候補は truncate されないという前提だったがそれが崩れているという事。 13996 13997 x done: desc/guess についても実装を更新する必要がある。というよりそもそも 13998 guess とは何だったか。 13999 14000 x fixed: カーソルキーによる navigation を再設計する必要がある。今までは Z 14001 型に走査する場合しか考えていなかった。 14002 14003 a N 型に走査する選択肢と Z 型に走査する選択肢の二種類に場合分けして実装す 14004 るか、 14005 14006 b 或いは一般的なアルゴリズムを考えるか (これは効率の良いアルゴリズムは困 14007 難の気がする。) 14008 14009 c 或いは menu-style 側で振る舞いを変更できる様にするか。 14010 14011 N型かZ型かに関してはページを構築した時に何処かの変数に補助情報として記録 14012 すれば良い。N型だとしても desc の場合には上下左右の操作は自明であるのでN 14013 型一般のアルゴリズムを用いるよりも、それ専用の処理を実装した方が良い気が 14014 する。 14015 14016 menu-style 側でカスタムに実装できる様にする事にする。 14017 14018 x fixed: 座標計算がずれる。_ble_b[TAB] において。 14019 14020 x fixed: trace が無限ループになっている気がする。 _ble_[TAB] において。 14021 14022 これは単に各列の行数の計算を間違えて全ての項目を一つのページに含めようと 14023 して巨大なページが出来上がっていたのが原因だった。 14024 14025 * done: desc-raw -> desc に改名する? 14026 14027 古い設定名は desc に移動する。 14028 14029 新しく desc-text を用意する。desc-text はもっと良い名前はないか。 14030 desc-less, desc-esc, ... info が text, esc と言った名前を使っているのでや 14031 はり text で良い気がする。 14032 14033 取り敢えず今は desc-raw は desc の synonym という事にしておく。ble-update 14034 等した時に不整合が起きると問題だし、そもそもそれぐらいなら別に対応してい 14035 ても大した問題にはならない。 14036 14037 * 新しい bleopt の名称を固定する。ドキュメントに記述する 14038 * 新しい widget menu/{forward,backward}-column をドキュメントに記述する 14039 14040 * 2021-08-30 complete: alias desc に alias の内容を表示するべきだろうか (motivated by Shahabaz-Bagwan) [#D1685] 14041 https://www.youtube.com/watch?v=YS1vxEhd2Pc 14042 https://github.com/akinomyoga/ble.sh/issues/132 14043 14044 * reject: 或いはその場で展開してしまう様なオプションを提供しても良いのかも 14045 しれない。その場合には遡った書き換えが起こるので不可逆であるという事。そ 14046 して他の候補が表示されている場合には候補が表示されなくなるなどの問題があ 14047 る。 14048 14049 取り敢えずその場での展開は考えない事にする。後で要望があれば実装するかも 14050 しれない。何れにしてもユーザーがそういう設定を書けば実現できるのだから 14051 ble.sh 側で一々設定しないという態度も考えられる。とは言いつつユーザー側で 14052 ちゃんと実装するには色々と細かい事があるような気もする。 14053 14054 * done: そもそも job 名が補完候補に現れていない気がする。 14055 コマンド名の補完でジョブ名も列挙する事にした。 14056 14057 * done: 変数 (action:variable) についても説明をちゃんと生成する。変数の中身 14058 でも展開すれば良い気がする。 14059 14060 * done: 説明を着色する。現在は単に黒で表示しているが着色した方が分かりやす 14061 いのではないか。或いは種別の方を着色して、展開結果などの値については黒で 14062 表示した方が分かりやすいかもしれない。 14063 14064 実行可能ファイルの着色に関してはパスをシンボリックリンクかどうかで各セグ 14065 メントを着色すると良い気もする。そう考えるとやはり値の方を着色する事も考 14066 えるべきの気がする。 14067 14068 * 2021-09-06 trace: ellipsis の位置が relative の時にずれる [#D1684] 14069 14070 menu_style=desc で説明が表示しきれない時に発生する問題。但し既存の処理にず 14071 れがないか後で確認するべき。これは relative の時の xlimit と実際に表示する 14072 範囲の制御のずれが原因だった。 14073 14074 折返しも全て xlimit で行う事にする。 14075 14076 然しそうすると relative の時の振る舞いが変わってしまう。改めてテストで振る 14077 舞いを確認する必要がある。うーん。やはりテストに失敗が発生している。 14078 relative の時には呼び出し元が気をつけていると想定して xlimit を減少させない 14079 様にするべきなのではないかという気がする。 14080 14081 然しそうすると安易に relative を付けている箇所ではちゃんと COLUMNS を 1 減 14082 少させるという対策が必要になる。 14083 14084 2021-12-05 改めてこれについてどう処理するのが良いか考察する事にする。当初の 14085 問題は ellipsis を relative で置く時に xlimit を元にして位置を決定している 14086 事。然し、relative の時であっても文字を置ける一番右の位置は xenl に依存して 14087 いる。 14088 14089 % * というかそもそも xlimit はどう決定されているのだったか。 xenl または 14090 % relative がある場合には cols でそれ以外の時には cols-1 になっている。 14091 14092 * 改めて修正箇所について確認する。 14093 14094 * 先ず HT の振る舞いについて。移動先が cols よりも先に行ったら cols-1 に 14095 戻すという処理だったのが、今回の修正で xlimit よりも先に行ったら 14096 xlimit-1 に戻すという処理に変更されている。然し、そもそも cols-1 が限界 14097 になっているのは xenl のある端末でもない端末でも同じ振る舞いの筈である。 14098 cols-1 までしか行かないのであれば xenl だろうと xenl でなかろうと、 14099 relative であろうとそうでなかろうと同じである。 14100 14101 これについては元の実装に戻す事にした。 14102 14103 * ASCII 文字列の連続に対する対策も見た感じは的外れの物に見える。というか 14104 これまでの実装でちゃんと xenl (_ble_term_xenl || opt_relative) の時の対 14105 策も行われている様に見える。 14106 14107 うーん。前に行った修正点はやはり色々考えると変である。元々ちゃんと考慮に 14108 入れて作ってある様に見える。 14109 14110 * そもそもの問題点は何だったか。ellipsis を出力するに当たって xenl のない端 14111 末だと、ellipsis を最後に出力しただけで行が変わってしまうという問題がある。 14112 その為、ellipsis の位置を1文字後退した位置に出力する様になっているが、そ 14113 れによってはみ出た文字が表示されてしまっているという事? 14114 14115 然しそれも何だか変である。改めて menu の出力がどうなっているか確認する。 14116 relative:ellipsis で呼び出している。 14117 14118 うーん。ellipsis が出力される状況を見てみたが変な事はない気がする。寧ろ、 14119 何故か xlimit を超えて文字が出力されているのかという事の方が問題である様 14120 に思われる。 14121 14122 | -p file : True, if file exists and is a fifo special file or a p…e 14123 | 0123456789012345678901234567890123456789012345678901234567890123456 14124 14125 xlimit=66, cols=67 になっているのに 67 まで文字が埋められてしまっている。 14126 14127 * 改めて xlimit の決定部分を見て何が問題なのか分かった気がする。 14128 14129 - xenl は _ble_term_xenl で初期化される。 14130 - opt_relative もしくは justify の時には 幅を縮めて xenl=1 に上書きする。 14131 この時の "幅" は xlimit=cols-1 である。 14132 14133 因みに xenl が最初から 1 だった時には xlimit=cols のままである。 14134 14135 うーん。そもそも xlimit は何のための変数だったのか。使用箇所を確認してみ 14136 ると overflow の判定と implicit-move で参照しているに過ぎない。 14137 14138 前者に関しては最終行での幅が xlimit でそれ以外が cols という事になってい 14139 る気がする。 14140 14141 ? done: ellipsis を出力する時にそもそも幅が足りない時にどうするか? 14142 → . の連続に置き換えるのが良い。 14143 14144 ? done: process-overflow で最終行以外での処理は? 14145 →取り敢えず最終行かそれ以外かで xlimit or cols を切り替える事にした。 14146 →改めて考えたがそもそも行末以外での overflow で ellipsis を出力するのは変だ。 14147 という訳で ellipsis は最終行にいる時にだけ出力する事にする。 14148 14149 ? fixed: そもそも xlimit の設定方法は正しいのだろうか。 14150 xenl が元々ある場合には xlimit=cols-1 にする必要性もないのではないか。 14151 →これは改めて考え直して修正した。 14152 14153 ? ok: print+ における overflow 判定は正しいか? 14154 →xenl||wmax-- でちゃんと処理できている。現在の新しい実装では xlimit の減 14155 少は xenl だけで決定されているので。 14156 14157 ? implicit-move で行われている以下の処理は一体何なのか 14158 14159 L1164: ((y++,x=w<xlimit?w:xlimit)) 14160 14161 うーん。これは一応OK? xenl がない場合は一番右の列に移動すると考え、xenl 14162 がある場合には端末の右端に行くと考える。実は xenl がない場合には更に次の 14163 行に行くという考え方もあるかもしれない。何れにしてもコメントにある様に端 14164 末によって振る舞いが変わるのではないかと思われる。 14165 14166 2021-11-28 14167 14168 * 2021-11-05 vim の :term 内部で backspace が効かない (reported by laoshaw) [#D1683] 14169 14170 C-q に続けて backspace を入力しても何も反応はない。auto-complete が表示さ 14171 れている状態で backspace を入力すると auto-complete がキャンセルされる事 14172 から何かしらは受信している。 14173 14174 modifyOtherKeys を off にしても問題は発生する。 14175 14176 ble/debug/keylog#start で確かめてみた所、何と backspace に対して NUL が受 14177 信されている。bash 本体はちゃんと受信できているという事を見ると bind の問 14178 題だろうか。 14179 14180 | * うーん。然し端末 (host to terminal) では DEL と NUL が同じ効果というの 14181 | もある。それに関連して vim terminal が何か勝手に変化させている可能性? 14182 | でもそうだとしたら他の application でもっと問題になる筈である。何より 14183 | readline がちゃんと動いている。 14184 | 14185 | * 最新版の bash でも同様に問題が発生する。なので version 依存のバグという 14186 | 訳でもない様に思われる。 14187 | 14188 | * 単に以下を bind しただけでは問題は再現しない。 14189 | 14190 | $ bind -x '"\C-@": echo NUL' 14191 | $ bind -x '"\C-?": echo DEL' 14192 | $ bind -x '"\C-h": echo BS' 14193 | 14194 | * vim :term の中の ble.sh で builtin bind -Xs の結果を見てもちゃんと \C-? 14195 | に対して 127 が割り当てられている。逆に 0 が割り当てられている hook も 14196 | \C-@ しかない。不思議だ。 14197 | 14198 | * 実際に本当に .hook 経由で NUL が混入しているのか確認した。確かに .hook 14199 | が 0 を引数として受け取っている。これはどういう事なのだろうか。FUNCNAME 14200 | 配列を出力してみたが問題の .hook は top level から呼び出されている。こ 14201 | れも異常はない。だとすると、bind の組み合わせによって変な振る舞いになる 14202 | 可能性があるという事だろうか。 14203 | 14204 | * stty を潰してみたがそうすると端末ハンドラの行エディタらしき物が有効になっ 14205 | てしまってテストできない。 14206 | 14207 | * stty の設定を確認してみた。vim の中では brkint ignpar imaxbel が欠けて 14208 | いる。然し、それらの設定を一致させてみてもやはり問題は振る舞いは治らな 14209 | い。stty の設定によって引き起こされているという訳でもない様だ。 14210 | 14211 | 不思議なのは :term の中では発生して他の端末では発生しないという事である。 14212 | bash の振る舞いがおかしいという事なのだろうか。取り敢えず bash の 14213 | bash_execute_unix_command がどう実行されているかについて確認したほうが良 14214 | い様に思われる。 14215 | 14216 | * bash_execute_unix_command の時点で \C-@ になっているという事を確認した。 14217 | また vim の外側では \C-? である。然し不思議なのは自分で手動で bind した 14218 | 時には特に問題も起こっていないという事なのである。 14219 | 14220 | うーん。この bind -s の設定によって問題が起こっている気がする。それ以外に 14221 | は考えにくいのである。然しそうだとしても :term だけで発生するのは不思議で 14222 | ある。 14223 | 14224 | うーん。bash が受信しているバイト列について追跡する事にする。うーん。何と 14225 | rl_getc の中の read(fd) の段階で 00 を受信している。ble.sh を有効にしてい 14226 | ない時には問題は生じない。ble-detach している時には問題は生じない。うーん。 14227 | 此処まで来ると bind -s の問題ではなくてやはり vim の :term の側の問題の様 14228 | な気がする。 14229 | 14230 | stty 関連の設定を変更して試してみるとどうなるだろうか。と思ったがそれは既 14231 | に試している。端末ハンドラの行エディタが有効になってしまってちゃんと処理 14232 | できない。 14233 | 14234 | うーん。bash の内部状態における端末状態と ble.sh の内部状態における端末状 14235 | 態が異なるというのが原因だろうか。通常の readline における rl_getc の瞬間 14236 | の端末状態を出力する事は可能だろうか。stty を実行すれば良い? 14237 | 14238 | これによる結果はどうも各種 key を undef している事だけが違いである。うー 14239 | ん。undef になっていると勝手に 0x7F が 0x80 になってしまうという事なのだ 14240 | ろうか。 14241 | 14242 | -intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; 14243 | eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt 14244 | = ^R; werase = ^W; lnext = <undef>; discard = <undef>; min = 1; time = 14245 | 0; 14246 | +intr = <undef>; quit = <undef>; erase = <undef>; kill = <undef>; eof = 14247 | ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = 14248 | ^S; susp = <undef>; rprnt = ^R; werase = <undef>; lnext = <undef>; 14249 | discard = <undef>; min = 1; time = 0; 14250 | 14251 | ここで erase undef をしない様にしたらちゃんと vim :term の中でも動く様に 14252 | なった。他に ^C ^U ^\ ^Z (+ あれば ^W ^V ^R) について stty で変更している 14253 | 様だが、 14254 | 14255 | - ^C, ^U, ^Z, ^V, ^R については普通に受信できている。 14256 | - ^W については vim で使われている。 14257 | - ^\ については寧ろ ble.sh の内部ではちゃんと受信できているが、外では受信 14258 | できていない。というか vim :term の外側にいる時でも受信できていない? 14259 14260 [原因] stty erase undef としていたのが原因になっている様である。 14261 14262 一方で、この設定がなくてもちゃんと動作する様に思われる。そもそもこの設定は 14263 何故あるのだろうか。どの様な場合に必要になるのだろうか。 14264 14265 | 然しもし erase undef しなくても受信できるのだとしたらそもそも何の為にそう 14266 | していたのか。昔は icanon 等をしていなかった為に受信できなかったという事 14267 | だろうか。 14268 | 14269 | ? 何処かにコードコメントは残っていないか? → 残っていない。 14270 | 14271 | icanon がない時の対策なのだとしたら、実際に icanon に対する対策を落として振 14272 | る舞いを確認すれば本当にそうか確認できる。うーん。icanon に対する対策を外し 14273 | たとしても ^? は有効である様に見える。逆に icanon があったとしても ^Z は効 14274 | かなくなる。 14275 | 14276 | それぞれの key について改めてちゃんと振る舞うかどうかを確認する事にする。 14277 | 14278 | - ^Z, ^\, ^C ... icanon があっても対策が必要。 14279 | 14280 | - ^U, ^? ... 別に問題は起こらない様に見える。icanon は恐らく関係ない。 14281 | - ^V, ^W, ^R ... これらも問題は起こらない様に見える。icanon を対策していな 14282 | くても振る舞いは変わらない。うーん。これらは単に 14283 | 14284 | うーん。分かった。adjust-uvw で ^U^V^W^? が対策の対象になっている。つまり、 14285 | 初期の実装に於いて ^U^V^W^? が bash の内部的な rebinding によって無効になっ 14286 | ているのを、stty の設定の問題であると誤認して追加した対策コードなのではない 14287 | かという事。そして、実際の所、これらの対策コードは役割を果たしていなかった 14288 | という事なのではないか。 14289 14290 [まとめ] ^U^V^W^? について stty で undef にしていたのは、これらのキーに 14291 bind できない事に対する誤った対策だったと考えられる。これに対する対策は 14292 ble/decode/bind/adjust-uvw で行われている。昔は原因が不明だった為に、念の為 14293 で stty でも undef する様にしていたのだと考えられる。 14294 14295 * 一応古い bash version でもちゃんと動くか確認する。→ bash-3.0, 3.1, 3.2, 14296 4.0, 4.1, 4.2, 4.3, 5.1 でも試した特に問題は起こっていない様である。 14297 14298 2021-11-23 14299 14300 * progcomp: libvirt virsh completion に対する防御 (reported by telometto) [#D1682] 14301 https://github.com/akinomyoga/ble.sh/issues/147 14302 14303 virsh completion を実行した直後にエラーメッセージが出るという事。これは 14304 virsh の補完が IFS=$'\n' と書き換えを行ってそのまま放置するのが原因である。 14305 14306 libvirt に対して patch を送った。accept された。然しこれが実際に 14307 distributions に反映されるのには時間がかかるだろう。workaround として IFS 14308 及び word を tmpenv にする事にした。 14309 14310 * util (modifyOtherKeys): kitty は modifyOtherKeys を廃止する (reported by kovidgoyal) [#D1681] 14311 https://github.com/akinomyoga/ble.sh/issues/110#issuecomment-975732850 14312 14313 * ok: kitty のインストーラのリンクからダウンロードできない。証明書がおかし 14314 い。と思ったら単に vm の時刻がずれていただけだった。 14315 14316 * Ubuntu 20 の VM に残っていた kitty 0.20.3 では既に CSI > 1 u には対応して 14317 いる様子である。DA2R は 1;4000;20 である。然し何だか C-S-? に対する振る舞 14318 いが分からなかったので kitty 0.23.1 に上げてしまった。DA2R は 1;4000;23 14319 である。 14320 14321 * 然し、ctrl+shift+a などが全く効かない。と思って気づいたのだが、どうやら 14322 kitty がそれを解釈している様である。C-S-up, C-S-down はスクロールで C-S-h 14323 は clear-screen か何かだろうか。C-S-a は無反応で C-S-g はちゃんと制御シー 14324 ケンスが送られる。つまり、kitty に割り当てられていない C-S-? に関してはちゃ 14325 んと送信する事ができる。然し、試した感じだと殆どの C-S-? は kitty によっ 14326 て上書きされている様である。 14327 14328 * kitty の ctrl+shift+a を無効にする方法はないのだろうか? うーん。結局一つ 14329 ずつ解除していくしかない様だ。取り敢えず全部解除したらそれっぽい感じになっ 14330 た。 14331 14332 * どの version から CSI > u と CSI < u が存在するのだろうか。というかそもそ 14333 も現在の version でも CSI >4;2m は効くという事なのだろうか。 14334 14335 https://github.com/kovidgoyal/kitty/issues/4075 14336 https://github.com/kovidgoyal/kitty/commit/d6a43a7729d50b6f452ccdb93c746b0e115ebd38 14337 14338 どうやら kitty から modifyOtherKeys が完全に削除される運びとなった様だ。発 14339 端は vim から kitty の modifyOtherKeys の振る舞いが変だという指摘を受けて、 14340 逆上して全削除という事に相成った様だ。 14341 14342 2021-11-12 14343 14344 * main: "alias set=export" としている人がいる (reported by eadmaster) [#D1680] 14345 これは単に退避リストに set を追加するだけで良い。 14346 14347 2021-10-30 14348 14349 * edit: WINCH の際の再描画 (reported by Johann-Goncalves-Pereira, guptapriyanshu7) [#D1679] 14350 https://github.com/akinomyoga/ble.sh/issues/142 14351 14352 * 前回よりも幅が小さい時には行数は同じか増える筈なので遡って削除する。 14353 14354 それ以外で問題が起こるのは幅が増える時という事になる。 14355 14356 * 幅が増えた時、前回 rprompt が表示されている時、またはプロンプトが改行され 14357 ていない時(右端まで到達していない時) には、恐らく右端を通り越して出力した 14358 事による折り返しは起こっていないので、配置に変化はないと仮定する。 14359 14360 と思って実装を確認したが WINCH に対する処理は ble/application/render によっ 14361 て実行しているので、このレベルだと実際の描画内容に基づいて text reflow が起 14362 こったかどうかを判定する術はない。うーん。panel::hasLineWrap の様な関数を追 14363 加する必要がある気がする。 14364 14365 その様に考えると現在の描画内容に応じて遡るかどうかを決定するのは余り綺麗 14366 でない様な気がする。やはり下手に予測しようとするよりもオプションなどで振 14367 る舞いを一括で変更した方が良いのだろうか。 14368 14369 ---- 14370 14371 うーん。然し端末によっては折り返しが起こったかどうかに関わらず、一番右端に 14372 文字があるかどうかで折り返しを判断するという実装も可能かもしれない。そう言っ 14373 た場合にもちゃんと動く様な信頼できる方法があってそれが単純であればその方が 14374 良い。その実装が複雑に成るのであれば、実際その様な端末が確認された訳でもな 14375 いので、其処まで気にしなくても良い。 14376 14377 * info の折返し判定について。うーん。menu は別の描画機構を用いているので、 14378 また別に処理する必要がある。試してみた感じだと menu_style=dense の時には 14379 折り返しになっている様である。 14380 14381 というかこれを考えるとそもそも menu の再配置を先に実行するべきの気もする。 14382 14383 --- 14384 14385 * 取り敢えず暫定的にオプション 14386 14387 段々と大掛かりになって来た気がする。折返しが発生しているかどうかの判定を 14388 用いて遡るかどうか判定するのは今後対応する事にして、現在は暫定処置として 14389 オプションで一括で対応するという方向も考えられる。 14390 14391 bleopt prompt_erase_previous_on_winch=xxx 14392 bleopt textarea_winch_reposition=xxx 14393 bleopt canvas_winch_reposition=xxx 14394 bleopt canvas_winch_position=here|prev| 14395 bleopt canvas_winch_redraw=here|back|clear 14396 14397 うーん。時間がかかっているので取り敢えずはオプションを提供する事にする。 14398 選択肢として redraw-here, redraw-prev, clear を用意する事にした。 14399 14400 * edit: inputrc キャッシュの読み出しでエラーが発生する (reported by laoshaw) [#D1678] 14401 14402 .bashrc から単純に source ble.sh を実行すると以下のエラーが出るという事。 14403 14404 -bash: /Users/user1/.cache/blesh/0.4/decode.inputrc.adict.xterm-256color.emacs: No such file or directory 14405 -bash: /Users/user1/.cache/blesh/0.4/decode.inputrc.adict.xterm-256color.vi_imap: No such file or directory 14406 -bash: /Users/user1/.cache/blesh/0.4/decode.inputrc.adict.xterm-256color.vi_nmap: No such file or directory 14407 14408 直接 source ble.sh を実行した時に問題になっていて、1.3 の方法で設定した時に 14409 問題が発生していなかったのは、source ble.sh を実行した瞬間に既にユーザー設 14410 定がされていたかされていなかったかの違いだろう。なので、この問題は 14411 attach=prompt に特有の問題ではない。 14412 14413 不思議なのは $cache_prefix.settings が存在して中身が一致している事まで確認 14414 しているのにも関わらず $cache_prefix.$keymap が存在しないという事態になって 14415 いるという事。不思議な事である。 14416 14417 うーん。変だそんな事起こらない筈なのに。 14418 14419 * done: 調べてみると copyfile でファイルを読み出すのに失敗すると、ファイル 14420 が正しくコピーされていないのにも関わらず settings が作成される様である。 14421 取り敢えず、copyfile に失敗したら settings は作成しない事にする。 14422 14423 * done: どうやら bash-3.? の時には readfile が実際に読み取れていたとしても 14424 失敗する様になってしまっている。read -d '' で読み取っているので、ファイル 14425 に NUL が含まれない限りは終了ステータスが 1 になってしまうのである。これ 14426 はちゃんと対策をした。読み取れるか読み取れないかの判定は事前にしておく。 14427 14428 | 然し依然として何故報告された事が起こったのかは不明である。 14429 | 14430 | * 或いは書き込み時に問題が発生した可能性もある? 然し、どうやってそれが起こ 14431 | るのか。settings はちゃんと書き込まれている (と思われる) 事から考えると、 14432 | ディレクトリが存在しないだとか書き込み権限が存在しないだとかそういう話で 14433 | はない気がする。copyfile の中でも clobber しているので上書き拒否されたと 14434 | いう訳でもないだろう (というか上書き拒否されたのだとしたら既存のファイル 14435 | が存在した筈なので上記の様なエラーは発生しない筈である。) 14436 | 14437 | また、上記の read の問題かとも思ったがこれは bash-3.? での実装である。エ 14438 | ラーメッセージを見ると 0.4 になっている。と思ったが分かった。0.4 はそもそ 14439 | も bash の version じゃなくて ble.sh の version である。つまり、報告者は 14440 | bash-3.2 を使っている。 14441 14442 報告者は bash-3.2 を使っている為に問題が発生している。 14443 14444 更に suggestion が出ないという問題についてもこれで説明がつく。 14445 14446 * make: macOS make-3.81 で contrib/contrib.mk の依存関係が正しく解決されない (reported by laoshaw) [#D1677] 14447 https://github.com/akinomyoga/ble.sh/issues/145 14448 14449 当初はどういうエラーかと思ったが 3.81 から 4.3 に update したら直ったという 14450 のでやはり make が悪いのだろう。実際に手元に 3.81 をインストールして試して 14451 みた所問題を再現できた。色々試して workaround できる事が分かったのでその様 14452 に対処する事にする。 14453 14454 [make インストールログ] 14455 14456 * make-3.81 14457 14458 そのままだと古い version の make はコンパイルできない。 14459 14460 | /usr/bin/ld: glob/libglob.a(glob.o): in function `glob_in_dir': 14461 | /home/murase/.opt/build/make/make-3.81/glob/glob.c:1361: undefined reference to `__alloca' 14462 | /usr/bin/ld: /home/murase/.opt/build/make/make-3.81/glob/glob.c:1336: undefined reference to `__alloca' 14463 | /usr/bin/ld: /home/murase/.opt/build/make/make-3.81/glob/glob.c:1250: undefined reference to `__alloca' 14464 | /usr/bin/ld: /home/murase/.opt/build/make/make-3.81/glob/glob.c:1277: undefined reference to `__alloca' 14465 | /usr/bin/ld: glob/libglob.a(glob.o): in function `glob': 14466 | /home/murase/.opt/build/make/make-3.81/glob/glob.c:575: undefined reference to `__alloca' 14467 | /usr/bin/ld: glob/libglob.a(glob.o):/home/murase/.opt/build/make/make-3.81/glob/glob.c:726: more undefined references to `__alloca' follow 14468 14469 以下のページによると glob.c の #ifdef を書き換えたら良い。 14470 14471 https://stackoverflow.com/questions/51675200/install-older-version-of-gnu-make-in-ubuntu-18-04 14472 14473 * make-3.82 14474 14475 ble.sh に対して make-3.82 しようとすると segfault する。3.81 で問題になっ 14476 ていた物を削除しても問題は解決しない。検索してみると上記のコンパイルエラー 14477 と同じく glob 関係のバグの様である。 14478 14479 https://stackoverflow.com/questions/52618055/gnu-make-3-82-on-ubuntu-18-04-segfault-in-glob-call 14480 https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/thread/XCYUF5BQLICUAAI3OM7EORCNOKEYP2MF/ 14481 14482 3.82 は 3.81 で行った修正をしてもしなくてもコンパイルできるが、どちらでコ 14483 ンパイルしたとしても segfault する。make-4.0 でやった様に 14484 GLOB_INTERFACE_VERSION を 2 に書き換えても、やはりコンパイルはできるが 14485 segfault する。 14486 14487 https://git.savannah.gnu.org/cgit/make.git/commit/?id=193f1e81edd6b1b56b0eb0ff8aa4b41c7b4257b4 14488 14489 で紹介されている修正を適用したらちゃんと動く様になった。ble.sh の 14490 contrib.mk はちゃんと動作する事が確認できた。 14491 14492 * make-4.0 14493 14494 4.0 についても同じ箇所でコンパイルエラーになる。== を >= に書き換えるとい 14495 う作戦は通用しなかった。GLOB_INTERFACE_VERSION を 2 に書き換えてみたらコ 14496 ンパイルできた。ble.sh の contrib.mk もちゃんと動く。 14497 14498 * make-3.80 も 3.81 と同じ様にしてコンパイルできた。然し、make-3.80 は 14499 $(.FEATURES) を持たないので ble.sh GNUmakefile はもっと新しい version を 14500 使ってくれと文句を出力する様になっている。3.80 は 2002 の version で 19年 14501 も前の version なので切っても仕方がないだろう。 14502 14503 2021-10-21 14504 14505 * main: "ble.sh: This is not an interactive session." (reported by andreclerigo) [#D1676] 14506 14507 恐らく non-interactive session に於いて bash_profile から bashrc が読み込まれている。 14508 bash_profile なので bashrc であると検出できなくてメッセージが表示されている。 14509 何れにしても non-interactive session で読み込もうとしているのがいけないといえば行けない。 14510 14511 →推測で修正してみたが直っていないそうだ。画面を見ると原因が分かった。GDM 14512 が Xsession を source して、 Xsession が /etc/profile 経由で .bashrc を呼び 14513 出しているという事の様だ。つまり、non-interactive script が source .bashrc 14514 をしている可能性を考慮に入れなければならない。この場合には、どう対処するべ 14515 きか。 14516 14517 a warning を表示するというのは違う気がする。ユーザーは [[ $- == *i* ]] を考 14518 慮に入れて bashrc を記述する事を要求されているのである。なので、ble.sh を 14519 source する時にユーザー側で [[ $- == *i* ]] をチェックするか、或いは 14520 ble.sh 自身でも *i* をチェックして silent に return するというのは妥当で 14521 ある。 14522 14523 b 或いは warning は全く表示しないという可能性? しかし、直接 bash ble.sh を 14524 実行された場合や、まるでライブラリであるかの様にプログラムから直接 source 14525 ble.sh を実行した場合などは、明らかに使い方を間違えているのだから warning 14526 を表示しても良い気がする。 14527 14528 c profile, bashrc など経由で ble.sh が source した時には、それが 14529 non-interactive であっても警告は表示しない様にする。何しろ、profile, 14530 bashrc は interactive でも non-interactive でも source され得るのだから、 14531 non-interactive であったとしても使い方を間違えているとまでは言い難い。 14532 14533 Bash が source する可能性があるのは以下である。 14534 14535 - /etc/profile 14536 - ~/.bashrc 14537 - ~/.bash_profile 14538 - ~/.profile 14539 14540 /etc/bashrc などはその他のファイルから呼び出されるので、これらはチェック 14541 しなくても良い? と思ったが、もしかすると何らかのスクリプトが直接 source 14542 /etc/bashrc みたいな事をしている可能性も考えられる。という事を考えると 14543 bashrc も除外リストに入れて置いた方が良いのではないかという気もする。うー 14544 ん。やはり除外リストに入れる事にする。 14545 14546 - /etc/bashrc 14547 14548 2021-10-04 14549 14550 * blerc: 含まれていない face が存在する (reported by Prikalel) [#D1675] 14551 https://github.com/akinomyoga/ble.sh/issues/140 14552 14553 blerc も wiki も共に以下の2つが抜けている。 14554 14555 argument_option 14556 cmdinfo_cd_cdpath 14557 14558 * core-complete-def.sh で ble-color-defface を使っている。 14559 →直した。他に ble-color-defface を使っている箇所はない。 14560 14561 * cmap: find/select が TERM によって定義されていたりいなかったりする [#D1674] 14562 14563 今思ったのだが TERM によって find/select が存在したりしなかったりする事によって、 14564 keymap.emacs や keymap.vi のキャッシュに不整合が生じるのではないか。うーん。 14565 14566 これによって keycode が不整合を起こすのではないか。 14567 $_ble_base_cache/keymap.{emacs,vi} は特に TERM に依存せずに共通の物を用いて 14568 いるので問題が発生する筈である。 14569 14570 * prompt: prompt_ruler で空文字列に展開される文字列を指定すると無限ループになる? [#D1673] 14571 14572 これは直ぐに直った。 14573 14574 x fixed: 但し、属性だけ設定して何も出力しないプロンプトの場合、背景色等も適 14575 用されない。これは trace が実際に文字を出力する迄着色を遅延する為である。 14576 trace に最終的な属性を反映させるオプションを用意しても良いのではないだろ 14577 うか? 或いは既にその様なオプションはあっただろうか。 14578 14579 うーん。trace の実装を確認してみたが、sgr が遅延されるのは clip の時のみ 14580 であって、今回は clip は指定していない。 14581 14582 と、思ったら実際に出力するものを間違えていた。trace で解析した物ではなく 14583 て解析前の物を直接出力する様になっていた。これは修正した。 14584 14585 * canvas (c2w.*.sh): テーブルの初期化に於いて *_ranges は ${!table[@]} に実は置き換えられる? [#D1672] 14586 14587 但し、table に飛び地も記録している場合にはこの方法は使えない。 14588 canvas.c2w.musl.sh を見ていて思ったのだが、他には短縮できそうな物はなかった。 14589 14590 * canvas.emoji: version 毎のテーブルを統合 [#D1671] 14591 14592 c2w.emoji.sh: version 毎にテーブルを作るのではなくて、合成したテーブルを使っ 14593 た方がスペースを節約できるのではないか。 14594 14595 実装し直した。 14596 14597 x fixed: 出力結果を比較してみたが全然違う値になってしまっている。何故だろう 14598 か。うーん。実際に出力されているテーブル自体が何だか違う結果になっている 14599 気がする。何かデータがスキップされてしまっている可能性? 14600 14601 念の為元のデータを確認しておく。U+1F7E5 (128997) が以前は 1 14602 (fully-qualified) だったのが現在は 0 になってしまっている。元のデータには 14603 ちゃんとこれは含まれている。最新のテーブルを確認すると値が消滅している。 14604 14605 →と思ったらミスが見つかった。修正する。 14606 14607 x fixed: emoji_version=13.1 で比較した所、以下の code point の EmojiStatus 14608 が変わってしまっている。 14609 14610 -U+0270F 3 14611 +U+0270F 1 14612 14613 元のデータを参照するとこれは unqualified でなければならない。何故値が変化 14614 してしまっているのだろうか? 新しいテーブルの実装を確認する。270F = 9999 14615 である。 14616 14617 % うーん。最新のテーブルを見るとそもそも 0 になるべきの気がする。何故 1 14618 % になっているのだろうか。と思ったが、分かった。範囲としては 9994-10000 14619 % に含まれていて、9994 は 1 という事になっている。 14620 14621 つまりテーブル生成の時点で何故か 9999 (unqualified) が 9994 (270A) に属す 14622 る形になってしまっているのが原因である。 14623 14624 →これは gawk の中で < による比較が文字列比較になっていたのが原因だった。 14625 int() で整数に変換してから処理する様にした。 14626 14627 o 13.1, 14.0 で比較した。ちゃんと一致している。 14628 o 11.0, 5.0, 2.0, 1.0 でもちゃんと一致する事を確認した。 14629 o 0.6, 0.7 は以前は対応していなかったが対応する事にした。 14630 o 14.0 も新しく対応した。 14631 14632 2021-09-27 14633 14634 * 2021-09-24 decode: 起動中に入力した文字が遅延する問題 [#D1670] 14635 https://github.com/akinomyoga/ble.sh/issues/135#issuecomment-919088879 14636 14637 起動後に最初に文字が入力された時に初めて処理される。 14638 14639 | 但し、これはちゃんと対策できるのかどうか怪しい。うーん。何れにしても現在ど 14640 | の様にしてこの遅延が発生しているのかを調べる必要はある。 14641 | 14642 | * 先ずは単純な bashrc で再現するのだろうか。という事。単純な bashrc だとちゃ 14643 | んと bashrc が終わった段階でバイトを受信する事ができている。 14644 | 14645 | # bashrc 14646 | sleep 1 14647 | bind -x '"A":echo A' 14648 | 14649 | * 次の実験は ble/.hook は受信できているのかという事。実際に次の内容を受信し 14650 | ている: 14651 | 14652 | [recv: 101] [recv: 99] [recv: 104] [recv: 111] # echo 14653 | 14654 | [recv: 192] [recv: 155] [recv: 91] [recv: 50] [recv: 59] [recv: 49] 14655 | [recv: 82] # \e[2;1R 14656 | 14657 | [recv: 192] [recv: 155] [recv: 91] [recv: 62] [recv: 56] 14658 | [recv: 51] [recv: 59] [recv: 52] [recv: 57] [recv: 57] [recv: 48] [recv: 14659 | 48] [recv: 59] [recv: 48] [recv: 99] # \e[>83;49900;0c 14660 | 14661 | うーん。 14662 | 14663 | * ble-decode-char: うーん。同じものをちゃんと受信できている。 14664 | 14665 | [char: 101] [char: 99] [char: 104] [char: 111] 14666 | 14667 | [char: 27] [char: 91] [char: 50] [char: 59] [char: 49] [char: 82] 14668 | 14669 | [char: 27] [char: 91] [char: 62] [char: 56] [char: 51] [char: 59] [char: 14670 | 52] [char: 57] [char: 57] [char: 48] [char: 48] [char: 59] [char: 48] 14671 | [char: 99] 14672 | 14673 | * ble-decode-key: 到達している。 14674 | 14675 | [key: 101] [key: 99] [key: 104] [key: 111] 14676 | 14677 | * call-keyseq: 何も到達しない。 14678 | 14679 | 何が起こっているか分かった…。ble-decode-key に "echo" が届いた時点では、後 14680 | に CPR や DA2R が控えている為にその場では処理されない。然し、CPR や DA2R は 14681 | ble-decode-key を呼び出さないので、そのまま処理が止まったままになる…。と思っ 14682 | たが何だか変だ。改めて調べる。 14683 | 14684 | うーん。やはり既に _ble_edit_str はちゃんと echo という文字列を含んでいる 14685 | 様に見える。という事は call-keyseq とは別の経路でちゃんと文字列が挿入され 14686 | ているという事か。 14687 14688 うーん。分かった。ble-decode-key/.invoke-partial-match の中で文字入力がある 14689 時に _ble_decode_key_batch に文字入力をキャッシュしている。なので次に何らか 14690 の widget が呼び出される迄、キャッシュされたままになってしまう。 14691 14692 なので、何処かでユーザー入力がないと確かめられたら 14693 ble-decode-key/batch/flush を呼び出す必要がある。ble-decode/.hook で呼び出 14694 すのが最も確実だろう。 14695 14696 →直った。syntax highlighting の遅延もちゃんと見える様になった。というより 14697 今迄見えていなかったのはやはりこれによる問題だったのだろう。 14698 14699 * util: CPR に timeout を入れる可能性 [#D1669] 14700 14701 偶々何らかの都合で端末が返答を無視した時などの為に、SECONDS 等を参照して古 14702 い CPR handler は削除してしまうというのが必要になる気がする。handler 毎に設 14703 定しなくても、最後に request を出してから一定以上時間が経過していればその時 14704 点で flush してしまうというのでも良い気がする。 14705 14706 一方で現実的な疑問としてその様に途中で CPR が消えたり、或いは端末が贈り忘れ 14707 たりという事がありうるのか、というのはある。例えば ssh を用いている限りはちゃ 14708 んと stream が hash で繋がっているし、途中で内容が抜けるという事はありえな 14709 い。TCP でそのまま繋がっているとしてもちゃんと途中で抜けがないかチェックは 14710 入っている筈である。udp で接続しているという事はありえない。まして、ローカ 14711 ルの端末・パイプで繋がっている時にはやはり途中で抜けるという事は考えがたい。 14712 14713 これは安全策の為に一応実装しておくという程度の物である。 14714 14715 * もしかすると現実的に ssh 切断→再接続→debugger API で tty を再構築みたい 14716 な事をすると、CPR が抜けるという事が発生するかもしれない。 14717 14718 * canvas (c2w): akinomyoga-emacs / musl-wcwidth の自動判定にも対応する? [#D1668] 14719 14720 voidlinux にそういえば変な標準ライブラリを使っている version があった。改め 14721 て確認すると musl というそうだ。musl wcwidth で検索したらソースコードが出て 14722 きた。この musl-wcwidth について wcwidth の結果を出力してみた所、何だか滅茶 14723 苦茶な結果が返ってくる。musl-wcwidth は 2012 で更新が止まっているので頻繁に 14724 変わる物という訳でもないだろう。 14725 14726 追加で 25b6 をチェックすれば emacs は判定できる。 14727 14728 musl の判定は Unicode versions の判定用の幅も使えば判定できるのではないかと 14729 いう疑惑。どうせどの Unicode version にも合わない様な変な振る舞いの文字があ 14730 るのではないかという気がする。 14731 14732 * その前に musl-wcwidth の実装をしなければならない。musl は元のコードと同じ 14733 様にすればコンパクトにできるが、ライセンス的に面倒なので振る舞いから再構 14734 築するのが良い気がする。やはり2分法で実装するか、或いは… 14735 14736 musl が使っているのはどういう実装だろう。 14737 14738 例えば 256x256 に分けて考えると、256のパターンを 8 整数 (64x8 = 512 = 14739 256x2bits) で表して、更にそれに対して同じ物を潰して higher 8bit から、パ 14740 ターンへの参照を作る。と思ったが、musl の実装を見る限りは曖昧な部分などを 14741 積極的に潰す事によってテーブルを小さくしている様な気がするので、一般のア 14742 ルゴリズムとしては可逆でそんなに簡単に圧縮できるとは思えない。musl がその 14743 様に圧縮されているという前提知識があるので同じ方法を取る事もできるかもし 14744 れないが、そうすると結局ソースコードをそのまま真似た形になってしまい、ま 14745 たライセンスの問題になる。 14746 14747 やはり変な事を考えるよりも愚直に二分法なり何なりで実装するのが最もコンパ 14748 クトな気がする。一方で、効率を考えたら二分法よりも良い方法はあるだろうか。 14749 結局 trie の様な構造を考えることになるのだろうか。 14750 14751 うーん。何れにしても二分法を使う事にする。U+XXXX width を出力した表からテー 14752 ブルを作成するコードがあれば今後も便利であろう。改めて make_command.sh の 14753 内容を確認する。 14754 14755 * musl の判定に既存の文字が使えるかどうかの確認 14756 14757 25bd 25b6 に対しては両方とも幅 1 になる。 14758 14759 Unicode version 判定に用いているコードに関しては 2 2 2 2 0 2 1 1 1 1 1 1 2 という数列を返す。 14760 14761 | -----Unicode EAW+GeneralCategory---------------|musl 14762 U+9FBC | -1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 | 2 14763 U+9FC4 | -1 -1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 | 2 14764 U+31B8 | -1 -1 -1 2 2 2 2 2 2 2 2 2 2 2 2 2 | 2 14765 U+D7B0 | -1 -1 2 2 2 1 1 1 1 1 1 1 1 1 1 ? | 2 何故か動いていない? 14766 U+3099 | 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 | 0 14767 U+9FCD | -1 -1 2 2 2 2 2 -2 2 2 2 2 2 2 2 2 | 2 14768 U+1F93B | -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 1 1 | 1 14769 U+312E | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 2 | 1 14770 U+312F | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 | 1 14771 U+16FE2 | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 | 1 14772 U+32FF | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 | 1 14773 U+31BB | -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 | 1 14774 U+9FFD | -1 -1 2 2 2 2 2 -2 -2 -2 -2 -2 -2 -2 -2 2 | 2 14775 14776 * 何故 D7B0 が動かなくなっているのだろう。現在これを出力しようとすると常に 14777 0 が表示される。 14778 14779 と思ったら _ble_unicode_c2w_custom で上書きされてい 14780 た。_ble_unicode_c2w_custom を一旦削除して判定して、終わったら復元して 14781 _ble_unicode_c2w_custom に含まれるコードだった時に警告を出力する様に変更 14782 した。 14783 14784 * 2021-08-31 wiki, blerc: import_path [#D1667] 14785 14786 done: bleopt import_path の記述が抜けている。blerc にもない。 14787 14788 他にも抜けている物がないか確認するべきなのでは。 14789 14790 done: grapheme_cluster 14791 done: emoji_opts 14792 ok: menu_desc_multicolumn_width これは現在対応中で後で載せる。 14793 14794 取り敢えず一つずつ説明を追加していくのが良い。 14795 14796 * 一方で blerc で抜けている物はもっと沢山ある。 14797 14798 done: keymap_vi_imap_undo 14799 done: keymap_vi_keymodel 14800 done: keymap_vi_operatorfunc 14801 done: keymap_vi_search_match_current 14802 done: term_vi_smap 14803 done: decode_macro_limit 14804 done: idle_interval 14805 done: syntax_debug 14806 14807 これらについては wiki から説明を拾ってくれば良い。 14808 14809 * done: vim_airline_* は全く説明書にない 14810 14811 vim_airline_theme だけは blerc にある。 14812 14813 * edit: powerlevel10k の prompt_add_newline を実装する (motivated by Barbarossa93) [#D1666] 14814 https://github.com/akinomyoga/ble.sh/issues/135#issuecomment-927284636 14815 14816 prompt_ruler='empty-line' 14817 prompt_ruler='-' 14818 prompt_ruler=$'\e[38;5;242m-' 14819 prompt_ruler='---=' 14820 14821 等に対応する。これは実はそんなに難しくないかもしれない。対応した。 14822 14823 対応する powerlevel10k に於ける設定名は以下の通り 14824 14825 POWERLEVEL9K_PROMPT_ADD_NEWLINE=true/false 14826 POWERLEVEL9K_SHOW_RULER=true/false 14827 POWERLEVEL9K_RULER_CHAR=- 14828 POWERLEVEL9K_RULER_FOREGROUND=242 14829 14830 ble.sh では prompt_ruler に ANSI seq を指定できる様にしたので色も一つの変数 14831 で済む。 14832 14833 * [外部 bashrc] Void Linux で文字幅計算がずれる (reported by Barbarossa93) [#D1665] 14834 https://github.com/akinomyoga/ble.sh/issues/135 14835 14836 と思ったがそもそもキャッシュしていない様に見える。という事は何を意味するの 14837 か。うーん。prompt 計算のキャッシュが残っているという事だろうか。そんな気が 14838 する。試してみる事にする。→プロンプトの trace_hash に char_width_mode も入 14839 れて置く事にした。char_width_mode=west にしても前の設定が残っている問題は解 14840 決した。 14841 14842 * 2021-09-26 これは結局 Barbarossa93 の設定に含まれる getCPos で printf 14843 DSR(6) & read CPR していたのが原因だった。この為に ble.sh の遅延処理して 14844 いる CPR の処理と getCPos の CPR の処理が入れ替わって双方で誤った結果を生 14845 み出しているというのが原因であった。 14846 14847 更に、もう一つの報告された問題である入力した文字列が失われるという問題に 14848 ついても、この getCPos が CPR 待ちで読み取っているが為に起こっている問題 14849 であった。この問題は ble.sh をロードしなくても、単に bashrc で時間がかか 14850 るだけで再現するという事が分かった。 14851 14852 * 2021-09-26 PROMPT_COMMAND の中でこの様な事をしても大丈夫な様に対策する? 14853 14854 そもそも技術的に可能なのか分からない。 14855 14856 a PROMPT_COMMAND の呼び出し前の段階でユーザー入力があるかどうかを確認して、 14857 もしユーザー入力があるのであれば一旦その時点で抜けるという事が必要にな 14858 る気がする。然し、現時点で既にその様な実装になっている様な気もする。こ 14859 れは全然対策になっていない。 14860 14861 つまり、textarea#render に入る直前までに返答が返ってくれば処理もできる 14862 が、そうでなければ PROMPT_COMMAND の中で stdin を読み取ろうとした時に、 14863 返答が来るまで待って其処で CPR が読み取られてしまうという事になる。 14864 14865 うーん。やはりこれに対する対策は原理的に困難である様な気がする。 14866 14867 b 或いは、terminal-test.buff を sync (timeout 付き) で処理する可能性もある。 14868 14869 然し、端末が CPR に対応していない時に固まってしまう。 14870 14871 timeout を入れたとしてもその分遅延が生じる事になる。ble.sh では初期化の 14872 遅延を可能な限り減らそうとしているので 50ms でも待つ等という事はしたく 14873 ない。それに timeout した時に、それよりもずっと後になって返答が返って来 14874 た時にまた問題が生じるかもしれないので、timeout はもっと長く設定しなけ 14875 ればならない気がする。もしくは、timeout してしまったら何らかのエラーと 14876 して処理を中断するというのが普通のシェルプログラムの動作として望ましい 14877 が、対話セッションの時にはセッションを抜けるという訳にも行かない。 14878 14879 もし本当に位置を特定したいのであれば、やはり ble.sh の様に非同期で処理 14880 する事が必要で、その為には line editor の event loop に登録するしかない。 14881 ble.sh ではその為の枠組を用意しているので、本当にそういった処理を実施し 14882 たいのであれば、ble.sh の枠組みを経由でカーソル位置を取得してもらうしか 14883 ない。readline に至っては robust な方法はない様な気がする。一応、 14884 readline の動作は高速なので変な遅延が生じる可能性は少ないし、そもそも 14885 readline が返答を必要とする様な要求を出さないので問題が起こる事は余りな 14886 いのだろう。 14887 14888 結局技術的に考えても困難であるし、これの対策はしない事にする。 14889 14890 対策しないとするとどれだけの範囲で問題が生じるか調べておく必要がある。 14891 14892 https://github.com/search?q=filename%3Abashrc+getcpos 14893 https://github.com/Barbarossa93/Muspelheim/blob/c9ea8ffd83ab5c85da47b5c36f39b3ec97b96230/.config/bash/bashrc 14894 14895 検索すると以上の様に報告者の bashrc しか見つからないので、この getCPos を 14896 bashrc の中で使うという手法は報告者独自のものであると推察される。なので、 14897 そんなに多くの設定で使われている物という訳でもないのだろうという気がする。 14898 うーん。以下で検索すると PROOMPT_COMMAND で CPR を取得するのは実は沢山存 14899 在している様だ。 14900 14901 https://github.com/search?q=filename%3Abashrc+PROMPT_COMMAND+%22%5B6n%22 14902 https://github.com/ScoreUnder/scripts-and-dotfiles/blob/f69f2f11739342a7c46fb38a9be2f5a5c803a438/dotfiles/.bashrc.m4 14903 https://github.com/safocl/safocl_profiles/blob/31ce40e9ff4619d1099c4f95c1f717e8a9b389fb/.bashrc 14904 14905 * [再現不可] urxvt: C-l をした直後に何故か反応が遅くなる 14906 14907 C-l の直後以外では問題はない様に見える。うーん。もしかすると C-l の直後以外 14908 ではプロンプトの更新がされていない? 単にプロンプトの計算に時間がかかってい 14909 るという事? 14910 14911 以下の PS1 で再現する 14912 14913 PS1=$'\[\e[38;5;1m\]┏━[\e[38;5;7m\]\w\[\e[38;5;1m\]]\n\[\e[38;5;1m\]┗━━ \[\e[38;5;8m\]■ \[\e[38;5;7m\]' 14914 14915 というか更に以下の PS1 でも再現する 14916 14917 PS1=$'\e[31mA ' 14918 14919 うーん。これは結局再現する事はできなかった。改めて urxvt で提供された 14920 bashrc を実行してみたがそれでも駄目だった。何か urxvt か或いは別の設定が 14921 壊れていたのかもしれない。 14922 14923 * 2021-09-26 workaround を提示したら思っている動作と異なるとの報告が来た。 14924 改めて見てみると、元のコードでしたのは「一番左にいなかったら改行を追加す 14925 る」ではなくて「一番上にいなかったら改行を追加する」という物だった。 14926 14927 少し考えてみたがよく分からない。困難の気がする。powerlevel10k にその機能 14928 があるというので p10k を 6n で検索してみたが、特にその様な文字列は含まれ 14929 ていない様だ。或いは、powerlevel10k はまた異なる手法を用いているのかもし 14930 れない。どうやら 14931 14932 POWERLEVEL9K_PROMPT_ADD_NEWLINE 14933 14934 というのが該当する設定の様である。うーん。これを使っている所を調べると 14935 14936 [[ $P9K_TTY == old ]] && { unset _p9k__empty_line_i; _p9k__display_v[2]=print } 14937 14938 というのを設定している。P9K_TTY は preexec で old に設定されている。 14939 14940 if [[ $_p9k__preexec_cmd == [[:space:]]#(clear([[:space:]]##-(|x)(|T[a-zA-Z0-9-_\'\"]#))#|reset)[[:space:]]# && 14941 $_p9k__status == 0 ]]; then 14942 P9K_TTY=new 14943 elif [[ $P9K_TTY == new && $_p9k__fully_initialized == 1 ]] && ! zle; then 14944 P9K_TTY=old 14945 fi 14946 14947 if [[ $1 == (clear-screen|z4h-clear-screen-*-top) ]]; then 14948 P9K_TTY=new 14949 _p9k__expanded=0 14950 _p9k_reset_prompt 14951 fi 14952 14953 うーん。これを見ると powerlevel10k は単に直前のコマンドを見ている様だ。具 14954 体的に座標を抽出している訳ではない様だ。これなら実装できなくもないが…。 14955 14956 * canvas: 文字幅判定の為の CPR は internal 状態で実行したい [#D1664] 14957 14958 CPR が画面に出力されてしまうのは stty echo の時に DSR(6) が出力されるから。 14959 ちゃんと internal state の時に CPR が出力される様にすれば防げるのではないか。 14960 後で何処から出力されているかを確認する。 14961 14962 と思ったが、CPR の遅延があるのでそれによって表示されているだけかもしれない。 14963 その場合には対策できないかもしれないができるだけ早い段階で DSR を送信してお 14964 く事はできる。 14965 14966 うーん。或いは、コマンド実行が終了した時点で char_width_mode=auto もしくは 14967 char_width_version=auto になっている時に初めて要求を出すというのは一つの手 14968 である。 14969 14970 * done: refactor: 関数名を変更する c2w+ -> c2w: 14971 14972 2021-09-26 14973 14974 * edit (command-help): use ble/util/assign/.mktmp to determine the temporary filename [#D1663] 14975 14976 これは ble/util/readfile の用例を確認している時に気づいた事。 14977 修正した。ちゃんと動いている様な気がする。 14978 14979 2021-09-23 14980 14981 * decode: [openSUSE] bash-it 側の検証に際して色々問題が生じている (reported by cornfeedhobo) [#D1662] 14982 https://github.com/Bash-it/bash-it/pull/1884 14983 14984 https://web.libera.chat/?channel=#bash-it ここの議論はすぐ消滅する 14985 | [8:27:38] → akinomyoga has joined 14986 | [8:31:20] <akinomyoga> Hmm, it seems everything I wrote has been lost after I 14987 | restarted the web browser. I don't get used to IRC, so I didn't know this 14988 | behavior. So there is no log of the channel? 14989 | [9:55:21] <akinomyoga> I summarized the current situation at 14990 | https://github.com/Bash-it/bash-it/pull/1884#issuecomment-923489130 14991 | [12:07:33] ← akinomyoga27 has left (Quit: Client closed) 14992 | [12:08:01] → akinomyoga27 has joined 14993 | [12:08:07] ← akinomyoga27 has left (Client Quit) 14994 | [13:45:22] <cornfeedhobo> akinomyoga: hello again 14995 | [13:45:45] <cornfeedhobo> akinomyoga: yeah, irc doesn't keep history. but i 14996 | have a record of it 14997 | [13:46:02] <akinomyoga> Hello 14998 | [13:46:06] <akinomyoga> Ah, OK 14999 | [13:47:29] <cornfeedhobo> ah, okay, so maybe i can explain the PROMPT_COMMAND 15000 | situation at least 15001 | [13:48:30] <akinomyoga> I have summarized my situation in the GitHub issue 15002 | page. Maybe you can first take a glance at the comment and just explain the 15003 | difference of the setups. 15004 | [13:50:28] <akinomyoga> Unfortunately I will have a meeting 10 minutes 15005 | later. So I think I cannot respond for one or two hours after that. 15006 | [13:50:28] <cornfeedhobo> your comment from an hour ago sums up what I was 15007 | assuming was happening 15008 | [13:50:47] <cornfeedhobo> okay, no worries. sorry i couldn't reply 15009 | sooner. today was filled with meetings. 15010 | [13:52:09] <akinomyoga> OK! Nice! Then I will look for a workaround 15011 | [13:52:51] <cornfeedhobo> awesome! thanks for working through this. your 15012 | attention to detail is impressive. 15013 | [13:53:04] <akinomyoga> thank you! 15014 15015 * done: home/end が効かない。これは結局 find/select を認識する事にした。本 15016 当に openSUSE の workaround の為だけの変更である。Ref #D1648 15017 15018 * done: "preexec が壊れる" という文句について。Ref #D1650 15019 15020 * done: set-mark 及び history-search-{for,back}ward が nmap で対応されてい 15021 ないというエラーメッセージに対する苦情 Ref #D1651 15022 15023 * done: /etc/inputrc{,.keys} が大量に設定を行っている為に初期化が遅い問題 15024 Ref #D1652 15025 15026 * done: error messages on openSUSE ... これは openSUSE における既 15027 知の問題である。これに関する対応は既に openSUSE の最新版には反映 15028 されているので気にしなくて良い。もし今後も openSUSE 15.2, 15.3 15029 のユーザーから報告があるのであれば、ble.sh の側で何らかの 15030 workaround を追加する必要があるかもしれない。 15031 15032 うーん。結局これは openSUSE の問題だし、Tumbleweed では問題は発生しないの 15033 だからわざわざ対応しなくて良い気がする。これは無視する。 15034 15035 うーん。或いは openSUSE 15.2, 15.4 を検出して inputrc を off にしても良い 15036 かもしれない。然し、これは他の WA がちゃんと動く事を確認してから対応する 15037 方が良い。そうしないと WA がちゃんと動くかどうかの feedback を得られない。 15038 これは最後に処理する。 15039 15040 最終的に openSUSE /etc/inputrc.keys が存在して変な keyseq を含んでいる場合 15041 には bind の出力は参照せずに .inputrc を解析する様に変更した。 15042 15043 * edit (widget history-search): support empty=emulate-readline (motivated by jainpratik163) [#D1661] 15044 https://github.com/akinomyoga/ble.sh/issues/139 15045 15046 history-search-{for,back}ward は検索なので一致場所にカーソルを置くという仕 15047 様に今までしてきた。また、空文字列検索の時には空文字列による検索を継続する 15048 為に、敢えてカーソルを先頭に置く様にしていた。しかし、readline の振る舞いを 15049 改めて確認した所、空文字列の時には恰も通常の history-prev を使用して移動し 15050 たかの様に振る舞っていながら、空文字検索を継続しているのだという事が判明し 15051 た。仕方がないので ble.sh でもやはり空文字列検索であっても内部的には 15052 nsearch 状態に突入して、但しカーソル位置は末尾にするという具合に変更する事 15053 にした。 15054 15055 改めて思うに Ref #D1517 https://github.com/akinomyoga/ble.sh/issues/101 で 15056 要望にあった"2. I would like the cursor to move to the end of line while 15057 searching with Up/Down." というのはこの振る舞いに関連しての事だったのではな 15058 いかという気がする。まあ、今となっては考えても仕方のない事なのかもしれない。 15059 15060 [追加] 15061 15062 * 対応したと思ったら動かない。と思ったが、prior に history-search-backward 15063 を束縛しても、nsearch keymap の中で prior が束縛されていないので、続けて 15064 prior が押されると一旦 nsearch を抜けて改めて nsearch が開始される為に、 15065 空文字列検索を続ける事ができないという状態になっていた。nsearch keymap に 15066 も prior/next を束縛する事にした。 15067 15068 ところで、ble.sh は複数行編集に対応しているので、その意味での prior/next を 15069 解釈する方が本当は理に適っているのでは? と思ったが、複数行編集している時に 15070 はその複数行で履歴検索したいという事はないだろうし、代わりに現在カーソルが 15071 ある行の文字列を履歴から検索するとしても、折角複数行のコマンドを編集してい 15072 るのに別のコマンドに移動してしまう事になるので変な感じがする。という事を考 15073 えれば、実は「複数行の時にはページ移動で、単一行の時は履歴検索」という 15074 widget として実装すれば良い気がする。これはまた別項目として残す事にする。 15075 15076 2021-09-22 15077 15078 * README: roadmap [#D1660] 15079 15080 発音の部分が取ってつけた様なので紹介文を書いてみた。 15081 15082 然し何だかふざけた感じになってしまった。特に日本語に関してはどのような言葉 15083 遣いで書いたら良いのか分からない。日本語では説明書にそういう話は書かない気 15084 がする。お菓子の説明にはそのお菓子がどのように成立したかなどの説明があった 15085 りする気がするのでそんな感じで書くのだろうか。真心込めて作りました的な説明 15086 になってしまってそれも何だか変な感じである。とにかく説明書に書くような内容 15087 ではない気がする。 15088 15089 % 縁起: 端緒は二〇一三年三月の末、とある `zsh-syntax-highlighting` の記事に触 15090 % 発され `.bashrc` の片隅で始まった実験でありました。数百行の設定で不完全でも 15091 % 何か着色ができようという当初の安易な期待は即座に裏切られ、行エディタを全て 15092 % 再実装するより他にないことが露見したのであります。一個の独立したスクリプト 15093 % として開発することに改め、名を ZLE (Zsh Line Editor) から借り、シェルで書か 15094 % れたことを示す `.sh` を付して `ble.sh` としました。二週間の実験は、実用に堪 15095 % える完全な行エディタをスクリプトで実装することが可能との結論に終わりました。 15096 % 本格的な実装が始まったのは二〇一五年二月のことです。同年十二月には行エディ 15097 % タとしての機能は大方出揃い、これを以て最初のバージョンとしました。 15098 15099 結局、新しく history and roadmap という section を README に加える事にした。 15100 発音に関する説明は結局 README の上部にそのまま残っている。 15101 15102 * README: sabbrev の例で \word を薦めるのが良い気がする [#D1659] 15103 15104 * README: zsh-abbreviations なる物は存在しない [#D1658] 15105 15106 https://unix.stackexchange.com/questions/6152/zsh-alias-expansion 15107 https://qiita.com/matsu_chara/items/8372616f52934c657214 15108 https://github.com/olets/zsh-abbr 15109 15110 * repo: ディレクトリ構造の整理。docs, make ディレクトリの作成 [#D1657] 15111 15112 * done: make ディレクトリに Unicode 関係のテーブルの生成コードを移動する? 15113 15114 現在は memo/ 以下にファイルを持っているが何だか違う気がする。他に leakvar 15115 の whitelist のファイルなども make 以下に移動した方が良い様な気がする。 15116 15117 make ディレクトリという名前で良いだろうか。tool というディレクトリを一時 15118 作りかけた。うーん。或いは memo の下にサブディレクトリを作る? うーんやは 15119 り make で良い気がする。 15120 15121 * done: ext/mwg_pp.awk も make に移動してしまって良い気がする。此処で問題になるか 15122 もしれないのは GNUmakefile の更新に失敗するかもしれないという事? 然し 15123 make の最中に checkout したりする事はないし、mwg_pp.awk が移動していれば 15124 既に GNUmakefile の方もそれに応じて書き換わっているし、GNUmakefile の方が 15125 書き換わっているのであれば mwg_pp.awk も移動している筈なので問題は起こら 15126 ない筈。 15127 15128 * reject: docs ディレクトリに雑多のファイルを移動する? 15129 15130 x GitHub のシンボリックリンクの問題 15131 15132 色々のファイルを docs ディレクトリに押し込めようと思ったが、git clone 15133 した時に分かりにくいので LICENSE と README に関してはせめて symbolic 15134 link を置こうと思ったが…GitHubのインターフェイスだと symbolic link を 15135 開いても中身の文字列が表示されるだけで、その指し示している先にジャンプ 15136 する事ができない。これはかなり不便である。検索したが余りそういう要望は 15137 ない様である。以下に何やら要望があるが、そもそもこの repository を 15138 GitHub が見ているのかどうかも謎である。 15139 15140 https://github.com/dear-github/dear-github/issues/156 15141 15142 x GitLab など他のサービスだと docs 以下にファイルを置いても認識してくれな 15143 いかもしれない。 15144 15145 これは一先ずは棄却する。後にもっとファイルが増えた時に気になれば対処する。 15146 15147 * done: ChangeLog.md, Release.md ぐらいは docs に移動しても良いのかもしれない。 15148 15149 多くのファイルは現在の場所に取り敢えず残すとしても memo/ChangeLog.md や 15150 memo/Relases.md に関してはまた docs/ 等の下にある方が分かりやすい筈である。 15151 此処での問題は ChangeLog.md を移動すると rebase がしにくくなるという事。 15152 まあ、これは一気にやってしまえば問題はない。 15153 15154 * keymap の下にある物も何処かのタイミングで lib/* に移動したい。0.5 に変更 15155 する時に移動しようとも思っていたが、0.4 がいつ完成するか分からないし、コー 15156 ドの移動を一度に実行すると code frequency にまた大きな spike が立ってしま 15157 うので、release 等とは関係なく思い立った時に実行した方が良いのかもしれな 15158 いとも思う。 15159 15160 何れにしても既存の物についてのディレクトリ構造の変更は、他の変更が pending 15161 になっていない綺麗な状態で実行するべきである気がする。現在は Unicode 関係の 15162 テーブル生成についても、中途半端である。少なくとも c2w 関連の実装が一区切り 15163 してから考えるべきことである様に思われる。 15164 15165 * [棄却] util (readfile): bash-5.2 に $(< xxxx) without fork が実装された [#D1656] 15166 ble/util/readfile にはこれを使うのが良いのではないか。後で速度についても確認する。 15167 15168 | bash-5.1 15169 | 15170 | 201.567 usec/eval: ble/util/readfile var sig.h (x500) 15171 | 1070.529 usec/eval: var=$(< sig.h) (x100) 15172 | 1078.159 usec/eval: var=$(< sig.h) (x100) 15173 | 1067.909 usec/eval: var=$(< sig.h) (x100) 15174 | 1078.159 usec/eval: var=$(< sig.h) (x100) 15175 | 15176 | process-count ... 200位増えている 15177 | $ echo $(echo $BASHPID) 15178 | 29617 15179 | $ ble-measure 'var=$(< sig.h)' 15180 | $ echo $(echo $BASHPID) 15181 | 29810 15182 | 15183 | bash-5.2 15184 | 15185 | 205.423 usec/eval: ble/util/readfile var sig.h (x500) 15186 | 205.131 usec/eval: ble/util/readfile var sig.h (x500) 15187 | 204.201 usec/eval: ble/util/readfile var sig.h (x500) 15188 | 29.551 usec/eval: var=$(< sig.h) (x5000) 15189 | 29.339 usec/eval: var=$(< sig.h) (x5000) 15190 | 29.491 usec/eval: var=$(< sig.h) (x5000) 15191 | 29.623 usec/eval: var=$(< sig.h) (x5000) 15192 | 29.535 usec/eval: var=$(< sig.h) (x5000) 15193 | 15194 | $ echo $(echo $BASHPID) 15195 | 29985 15196 | $ ble-measure 'var=$(< sig.h)' 15197 | $ echo $(echo $BASHPID) 15198 | 30010 15199 15200 現在の実装よりも圧倒的に高速である。但し、現在の実装と比べて問題があるとす 15201 れば改行を保持する事ができないという事である。 15202 15203 うーん。readfile の仕様として自動的に末尾の連続改行は一つにまとめ、改行がな 15204 い時は改行を加えるという事にしても良いのかもしれない。と思ったが、 15205 test-util.sh に末尾改行を保持する事を要請するコードが存在している。 15206 15207 後、互換性を考えると末尾の連続改行については未規定という様にしないと、古い 15208 version で逆に末尾改行を除去するのに逆に処理を追加しなければならなくなる。 15209 15210 色々試してはみた物の速度的にも mapfile と比べてそれほど違うという訳でもない 15211 様な気がしてきた。そもそも readfile の時点でそんなに遅い訳でもない。という 15212 事を考えると、わざわざ改行が消えてしまう $(<) を使う必要はない様な気がする。 15213 15214 * Makefile: 単なる git clone & make install でちゃんとインストールできる様にしたい [#D1655] 15215 https://github.com/Bash-it/bash-it/pull/1884#issuecomment-922615431 15216 15217 特に --recursive をユーザーが指定しなかった時。 15218 現在の実装だと contrib が存在しなかった場合には一回の make だけだと 15219 contrib 以下のインストールするべきファイルが認識されずにインストールされない。 15220 contrib を checkout した時には改めてそれを読み直す様にさせる必要がある。 15221 15222 うーん。これは GNUmakefile を contrib/.git に依存させれば良いのでは? 15223 という気がする。但し、何か変な事が起こるかもしれないので、 15224 何回か手元で実行して確認する必要がある。 15225 15226 うーん。駄目だ最初からやり直してはくれない。実際に Makefile が書き換えられ 15227 る事がないと駄目という事だろうか。contrib の方に .mk を作成してそれを読み込 15228 む様にしなければならないのだろうか。取り敢えずその様に実験してみる事にする。 15229 15230 * prompt: do not evaluate PROMPT_COMMAND for subprompts [#D1654] 15231 15232 #D1654 で観察していて気づいたが現在のコードだと subprompt に対しても 15233 PROMPT_COMMAND を実行している。それは何だか変なので subprompt に対しては 15234 PROMPT_COMMAND は実行しない様に修正する。 15235 15236 これは後で ble-0.3 にも適用したいので commit を分ける事にする。 15237 15238 * vi: ? や / が動かなくなっている [#D1653] 15239 15240 * 表示が滅茶苦茶になってしまう。 15241 * そもそもプロンプトも表示されていない 15242 15243 一方で nsearch で入力させる機能はちゃんと動いている。両者で何かが違うという 15244 事だろうか。→と思ったら nsearch は read -ep を使っていたのだった。 15245 15246 昔は確かに動いていた筈なので先ずは bisect する所から始めるべきの気がする。 15247 手動 bisect の方法について調べながら実行する事にする。 15248 手動 bisect の結果以下が問題の commit であると判明した。 15249 15250 | commit cf8d94930af5a57e7ae9309a16eca7fc3e3479ad (refs/bisect/bad) 15251 | Author: Koichi Murase <myoga.murase@gmail.com> 15252 | Date: Mon Jun 7 12:13:56 2021 +0900 15253 | 15254 | prompt: track dependencies and detect changes 15255 15256 プロンプト計算に失敗しているという事だろう。 15257 15258 うーん。大きな変更すぎて原因はコードを見ても分からない。 15259 恐らく補助プロンプト関係で何か不整合が起きているという事。 15260 例えば prompt update ではスキップしているのに描画の際には考慮に入っている等。 15261 15262 うーん。rps1, status を無効にしてみたがそれでも問題が発生する。 15263 15264 * そもそも ps1 自体表示されていない。 15265 _ble_edit_PS1 は値としてはちゃんと ble/prompt/update の中から見えている。 15266 15267 うーん。_ble_prompt_ps1 の更新は prompt_ps1 を参照している筈。それなのに 15268 subprompt の時と prompt の時で解析結果が異なる。subprompt の時には空の結 15269 果になってしまっている。何故? 15270 15271 そもそも ble/prompt/unit:_ble_prompt_ps1/update が呼び出されていない。 15272 うーん。ohashref が literal 0 になってしまっている。 15273 15274 * そもそもプロンプトを一切表示しない場合でも表示が乱れてしまっている。 15275 panel の高さ計算でミスしている可能性? 例えば復元した時に不整合が生じている等。 15276 というか subprompt に入る段階でも既に何だか変な事になっている。 15277 15278 分かった。_ble_prompt_ps1_data の形式が変わったのに vi.sh の中での 15279 _ble_prompt_ps1_data の初期値をそれに合わせて変更するのを忘れていた。 15280 古い _ble_prompt_ps1_data の初期値が更新済みのデータとして解釈されて 15281 prompt の再計算が行われないまま誤ったデータとして座標計算などが行われていた。 15282 →この初期値の形式を修正するだけで全て動く様になった。 15283 15284 * decode: 巨大 inputrc の翻訳内容をキャッシュする [#D1652] 15285 https://github.com/Bash-it/bash-it/pull/1884#issuecomment-923489130 15286 15287 /etc/inputrc{,.keys} が大量に設定を行っている為に初期化が物凄く遅い問題に 15288 ついて。これは bash の既定の binding に対する cmap cache だけではなくて、 15289 前回の ble.sh 実行時の cmap cache も保持する事で解決する様な気もする。と 15290 いうか寧ろ前回の ble.sh 実行時の状態を使って cmap cache を保持するべきの 15291 気もする。 15292 15293 [現状] 15294 15295 現在どの様にキャッシュしているか確認する。 15296 15297 例えば decode.readline.50108.vi-insert.txt 等に対して保存されている。これ 15298 に対してユーザーが保存した物も付け加えるのはどうだろうか。と思ったが 15299 emacs, vi-insert, vi-command で分けて保存しているのはどういう事だろうか。 15300 うーん。emacs/vi-insert/vi-command の三組で ble.sh の keybinding の状態が 15301 定まる。という事を思うと、ユーザーの inputrc の状態を保存するとしてもやは 15302 り三組を記録する必要がある。そして、それらの保存されたファイルと現在の状 15303 態に相違がない時に限り保存された keybinding の状態を復元するという振る舞 15304 いにする。 15305 15306 --noinputrc で分岐している部分を確認する。noinputrc が指定されている時に 15307 は以下の変数に値を設定している。これらの変数に値が設定されていない時に限 15308 り現在の状態が読み取られる。 15309 15310 _ble_builtin_bind_inputrc_done=noinputrc 15311 15312 これは ble/builtin/bind/initialize-inputrc で参照される。ユーザーの 15313 inputrc を読み取る関数。 15314 15315 _ble_builtin_bind_user_settings_loaded=noinputrc 15316 15317 これは現在の bind -vetc の出力を元に keybinding を設定する関数 15318 ble/builtin/bind/read-user-settings 及び 15319 ble/builtin/bind/.reconstruct-user-settings で処理される。 15320 15321 うーん。この .reconstruct-user-settings の中で呼び出している各ステップで 15322 どれだけ時間がかかっているのかを計測するのが先ずはする事の気がする。もし 15323 かすると bottleneck を見誤っているかもしれない。 15324 15325 実際に時間を計測してみると、比較対象と現在の状態の両方を gawk に入力する 15326 為に集めるので 0.04s かかっている。gawk は 0.016s で終わっている。その後 15327 の ble-bind で 0.77s 消費している。 15328 15329 [修正] 15330 15331 * ok: 入力情報を集める部分については恐らく設定の量に依存しないし、入力情報 15332 が前回と一致しているかどうかというのを判定するのにまた時間がかかるだろう 15333 から、キャッシュの同一性の判定は gawk で処理した後に行うべきの気がする。 15334 15335 * done: 後段の最も時間がかかっている部分について内容を確認する。bind -m xxx 15336 'xxx' というのが約200行続いている。これについてキャッシュできないか考える 15337 べきなのだろう。この時点での内容を何処かに保存しておいて… 15338 15339 % うーん。そもそも初期化の順序がどうなっているのか分からない。この関数の 15340 % 呼び出しが初期化時の物であれば、この時点での keymap の状態は標準の状態 15341 % になっていると考えられるので、"$settings" の内容だけでこれを eval した 15342 % 後の状態が確定するのでキャッシュを読み込んで終わりにする事ができる。一 15343 % 方で、別の場所から呼び出された時には、更に別の設定が keymap に加えられ 15344 % ている可能性もあるので、不用意にキャッシュする事はできない。 15345 % 15346 % →という事を考えると初期化時の呼び出しの時だけキャッシュする様に、呼び 15347 % 出し元から特別な opts を指定する等して区別しなければならない。 15348 % 15349 % もう一つの事はユーザー設定をキャッシュする為には emacs.sh 及び vi.sh を 15350 % 読み込まなければならないという事である。そうすると keymap の遅延読み込 15351 % みが全く為されなくなり意味がない。 15352 % 15353 % * うーん。bind の遅延には対応していたのだったか。もし bind の遅延に対応 15354 % していたとすると更に話はややこしくなる。遅延した物を最後にひとつにま 15355 % とめてその上でキャッシュするという様な仕組みにする必要が出てくる。然 15356 % し、それは複雑すぎる様に思われる。 15357 % 15358 % →うーん。遅延されている。という事を考えると 0.7s かかっているのは実 15359 % 際の ble-bind ではなくて、それをキャッシュする段階でかかっている時間 15360 % という事になる。 15361 % 15362 % というかその前にそもそも遅延がどの段階で実装されているのかを確認する 15363 % 必要がある→うーん。内部関数の ble-decode-key/bind の呼び出しがキャッ 15364 % シュされている。この関数は decode 済みの keys 値と実際のコマンド名 15365 % (ble/widget/xxxx など) を受け取っている。という事を考えると、時間がか 15366 % かっているのは decode の部分なのだろう。 15367 % 15368 % * 元の標準設定が切り替わった時にはどうするのか。その時にもキャッシュを 15369 % 更新しなければならない。 15370 15371 どうも時間がかかっているのは bind -m xxx yyy の yyy に含まれる keyseq 15372 -> keys への翻訳の様に思われる。keymap は最初は初期化されていないと思わ 15373 れるので、翻訳結果は全て ble-decode-key/bind の中でキャッシュされる。そ 15374 のキャッシュ結果を何処かに保存しておけば良いという事になるのではないか。 15375 15376 翻訳過程をキャッシュしているので cmap 及び rlfunc 表の更新だけを気にし 15377 ていればキャッシュの一貫性は保てる。 15378 15379 確認: 本当に初回呼び出しでは全ての keymap が未登録状態か? →実際にそうなっ 15380 ている事を確認した。その条件が満たされている時にのみキャッシュを利用する 15381 事にする。 15382 15383 取り敢えず実装した。動作確認した。inputrc を編集した時にちゃんと更新され 15384 る事も確認した。 15385 15386 * done: 情報を集める箇所で ble/util/cat を3回実行している。これは readfile 15387 か何かに置き換えるべきなのではないか。 15388 →readfile に置き換えた。 15389 15390 * done: というか reconstruct のパイプを assign で分解したら 0.12s から 15391 0.06s に短くなった。パイプは分解した方が良いのか…。 15392 15393 →分解した。 15394 15395 2021-09-21 15396 15397 * edit: set-mark 及び history-search-{for,back}ward を nmap で bind しようとしている [#D1651] 15398 https://github.com/Bash-it/bash-it/pull/1884 15399 15400 これも結局は openSUSE の /etc/inputrc.keys が設定しようとしている設定である。 15401 或いはもしかすると bash-it のどれかの plugin が同様に何か設定しようとしてい 15402 る可能性もある。 15403 15404 うーん。set-mark については単純に v と同一視してしまうのが良い気がする。 15405 15406 一方で、history-search-{for,back}ward に関しては微妙である。 15407 15408 a motion 的に実装するというのが一つの案だったが、history-search は opts に 15409 応じて現在の文字列を置き換える様に動作したり或いは実際に履歴を遡ったり振 15410 る舞いが変わる。前者の時には編集コマンドとして動作するし、後者の場合には 15411 移動コマンドとして動作する。どの様に実装するべきかは一定しない。 15412 15413 x 各場合に対して適切に振る舞いを変更するのも面倒だし、 15414 15415 x 更に、nsearch map の修正はしなくて良いのかという問題まで出てくる。つま 15416 り、nmap から呼び出しているのだとすれば jk で移動できる様にするべきなの 15417 ではないかという事になる。現状の設定では普通の文字列を入力したら普通に 15418 抜けて通常の文字入力をする設定になっている。 15419 15420 よく考えたら opts については bind 経由だと何も指定できないので特定の opts 15421 である事を想定して history-search を nmap 上で動かしても良いのではないか?? 15422 15423 b うーん。vi_imap に一旦抜けてから実行してしまうというのが一つの手である。 15424 この場合の懸念は勝手に imap に移行した事によってユーザーに混乱を来さない 15425 のかという事である。 15426 15427 然し nmap 専用に実装するとすると、実装の複雑さを考えると実装する価値が本 15428 当にあるのか怪しいし、更に振る舞いの複雑さを考えるとそもそもユーザーがちゃ 15429 んと使えるのかというのも怪しい。特に、bind で変な設定をした時にだけ利用で 15430 きる物なのでユーザーが使い方に慣れてくるという事は期待し難い。そう考える 15431 と、nmap 上で motion/edit として実装する方が余程混乱を来す様に思われる。 15432 15433 そう考えると、imap に移行して通常の history-search として振る舞わせる方が 15434 良い様に思われる。 15435 15436 うーん。実は history-isearch については直接束縛する様になっている。 15437 history-isearch は唯単に履歴項目を移動するだけなので問題ないという事なのだ 15438 ろう。 15439 15440 うーん。振る舞いを固定してしまえば普通に edit として振る舞わせて良い気がす 15441 る。と思ったが、vi_imap, emacs の方で動作を履歴移動に変更しているので、やは 15442 り履歴移動として実装する。うーん。そうなると実は history-isearch と同様に修 15443 正無しで nsearch を実装してしまっても良いのではという気がしてくる。 15444 15445 と思ったが、確認してみると nsearch を完了する時に eolfix が必要だし、また検 15446 索開始時もカーソルを一文字ずらす必要がある様な気がする。然し抜ける時にカー 15447 ソルが移動するとなると直感と異なる動作になる可能性もある。 15448 15449 a うーん。一つの案は history-search の opts として新しく nmap を追加して、 15450 更に、history-search の選択範囲の抽出も nmap に依存する様に書き換える。 15451 15452 →opts に設定する事にするとユーザーが自分で ble-bind した時に指定し忘れる 15453 事になる気がするので、直接 _ble_decode_keymap を参照して動作を決定する事 15454 にした。 15455 15456 vi_nmap 及びその他の vi コマンドモードの中にいる時には、検索文字列を決定 15457 する時と一致時のカーソル位置を設定する時にカーソル位置の補正を行う事にし 15458 た。 15459 15460 実装した。見た感じちゃんと動いている。 15461 15462 * main: work around self-modifying PROMPT_COMMAND by bash-preexec (reported by cornfeedhobo) [#D1650] 15463 https://github.com/Bash-it/bash-it/pull/1884 15464 15465 % preexec が動かないと言っている。うーん。そもそも PROMPT_COMMAND の内容が向 15466 % こうとこちらで異なる。こちらで色々試したが再現しない。ちゃんと 15467 % PROMPT_COMMAND には __bp_* が含まれているし、実際に preexec(), precmd() を 15468 % 定義すると期待通りに呼び出されている。 15469 % 15470 % preexec で lambda 経由の呼び出しになる様に無理やり設定した所、どうやら問 15471 % 題を発見した。コマンドを実行する度に preexec, precmd の処理がどんどん追加 15472 % されていく。調べてみると、bash-preexec は PROMPT_COMMAND に自身が含まれて 15473 % いない時、自身を其処に無理やり追加する様である。通常であれば 15474 % PROMPT_COMMAND がそれで修正されて問題は起こらなくなるが、ble.sh が 15475 % PROMPT_COMMAND を復元してしまう為に毎回処理が追加されるという事になってい 15476 % る。 15477 15478 結局 cornfeedhobo は 15479 15480 source bash_it.sh 15481 source ble.sh 15482 15483 と bashrc に書いていた様だ。ble.sh の推奨する使い方からは外れているし、また 15484 blesh.plugin.bash を使って読み込む場合とも異なる。なかなか再現できなかった 15485 理由はこれだった。"minimal setup" としか言わなくて具体的な説明を一切しない 15486 のだから駄目である。minimal setup と言っても色々あるだろうに。 15487 15488 [修正] 15489 15490 これに関してはどうやら PROMPT_COMMAND の変更がちゃんと反映されればループ 15491 が停止する様であるから、PROMPT_COMMAND の変更をちゃんと記録するようにする。 15492 現在の実装だと lambda の関数本体に直接 PROMPT_COMMAND を記録しているが、 15493 やはり変数に記録する事にする。重複して記録されて上書きされて無限ループに 15494 なるのを防ぐ為に、配列にして lambda には配列添字を記録する事にする。 15495 15496 取り敢えず実装して動作確認もした。 15497 15498 * contra oldbug: どうも新しい c2w が問題を起こしている [#D1649] 15499 15500 一番怪しいのは幅の自動判定である → 取り敢えず char_width_version を別の値 15501 に設定すればずれは生じない事を確認した。最悪の場合には既定値を適当に設定す 15502 る事にすれば良い。 15503 15504 % contra では問題は発生しない。という事は受信時の処理で何かがずれているという 15505 % 事だろうか。というより contra も DSR(6) に対応した筈なのに反応していないの 15506 % は何かと思ったら、実はそもそも最新版の contra に入れ替えていなかった。 15507 % 2020-10 の contra を使っていた。contra を差し替えたら問題が消えてしまった。 15508 % 15509 % つまり screen と contra の不整合によって行がずれていただけという事だろうか。 15510 % 取り敢えずこれは無視する事にする。 15511 15512 どうも Linux 上で動かしている時には問題は起こらないが、Cygwin 上で動かして 15513 いると問題が生じる様である。screen / contra で発生する。contra, mintty, 15514 screen / mintty では発生しない。うーん。tmux / contra でも発生しない。 15515 15516 screen で C-a C-a C-a C-a で一旦別の window に行って戻ってくると内容が変わっ 15517 ている。つまり、これは screen の中の端末状態と contra の端末状態がずれてい 15518 るという問題である。特に、screen に於いて変な濁点のような物が行末で出力され 15519 ていて、contra は改行していると思っていて、screen は改行していないと思って 15520 いる気がする。改めて座標計算を弄って調整する必要がある気がする。 15521 15522 どうやら問題の文字を出力すると発生するという事は確かだが不思議な現象が発生 15523 している。問題の文字を出力しない様に ble.sh を修正すると、次の一回は未だ問 15524 題が再現するが、それ以降は再現しなくなる。どういう事だろうか。。うーん。こ 15525 れは単に画面上に問題の文字が残っていて既存の文字の振る舞いを見出していると 15526 いう事の気がする。 15527 15528 また CPR を要求しなくても問題が発生しているので、これは DSR や CPR の問題で 15529 はなくて純粋に文字列を出力した時の振る舞いが問題になっている。 15530 15531 うーん。0x3099 が問題の文字である。もしかすると行頭で 0x3099 を実行するとカー 15532 ソルが前の位置に移動してしまうという事なのかもしれない。[] で囲んで出力する 15533 様に修正したら問題なく動く様になった。 15534 15535 * char_width_{mode=auto,version=auto} とすると重複して要求が走ってしまう。 15536 要求を省略する事はできないか。一つの方法は test-terminal.buff (旧 15537 update.buff) を呼び出す前に未だ処理中であれば test-terminal.buff を呼び出 15538 さないという物。というか、test-terminal.buff の側で処理中かどうかを検出す 15539 れば良い気がする。 15540 15541 取り敢えず DSR を送った回数を記録しておいて、同じ数だけ CPR を受信した時 15542 点で処理完了という事にする様に修正した。 15543 15544 動作確認もしておきたい。先ずは VoidLinux の各端末で version 判定できてい 15545 るか確認する。OK. urxvt, st は version=13.0 で gnome-terminal は 15546 version=14.0 になった。Fedora の上で実行した urxvt は 11.0 になった。ちゃ 15547 んと区別できている様だ。 15548 15549 x 2021-09-26 と思ったら auto が1度処理されると二度と処理されない。 15550 15551 そもそも request が送信されていない気がする。 15552 →これは簡単なミスだった。修正した。 15553 15554 * cmap: home/end が openSUSE で効かない (reported by cornfeedhobo) [#D1648] 15555 https://web.libera.chat/?channel=#bash-it 15556 15557 home/end が効かない。これもまた openSUSE の問題の可能性はある。 15558 これは /etc/inputrc.keys の以下の行が原因であった。 15559 15560 https://github.com/openSUSE/aaa_base/blob/master/files/etc/inputrc.keys#L233-L234 15561 15562 そもそも find/select は terminfo にも存在しないし、terminfo を参照している 15563 だけでは判定する事は不可能である。つまり TERM を直接見て判断しないと 15564 find/select を検出するのは不可能である。一方で openSUSE inputrc.keys は直接 15565 term を参照している。 15566 15567 また openSUSE に対して問題を報告しようと思ったが、xterm 決め打ちならば 1~, 15568 4~ は find/select とする事に明確な問題がある訳でもない様な気がする。問題が 15569 発生するとすれば screen の xterm-256color emulation であるが、どうも確認し 15570 た感じだと手元の screen.xterm-256color と向こうの screen.xterm-256color で 15571 khome, kend の内容が異なる様である。openSUSE の screen は khome, kend は 15572 \e[H, \e[F になっているが、手元の screen.xterm-256color だと khome=\e[1~, 15573 kend=\e[4~ になっている。 15574 15575 もう面倒なので find/select に対応する事にする。結局誰も使わないキーの様な気 15576 もするが、単にトラブルを避ける為に無視するキーの名前という事になる。 15577 →実際に openSUSE で試してみて動作する事を確認した。 15578 15579 2021-09-16 15580 15581 * decode: failglob で cmap 初期化時にエラーになる問題 [#D1647] 15582 15583 Solaris で試している時に気づいた。bashrc の中で ble-bind を実行して、cmap 15584 initialization が其処で走ると failglob の時に cmap cache の読み取りに失敗す 15585 る。 15586 15587 原因は _ble_decode_csimap_kitty_u に直接 keyname が格納されていて、中でも 15588 '*' が悪さをしているという事だった。cache は declare -p による dump で生成 15589 しているので本来は quote されている筈だが、容量を節約する為に quote を外し 15590 ていたのが原因だった (kitty_u 以外は整数なので quote の必要はなかった)。 15591 15592 * edit: stdout.off で stderr だけ suppress という案について (motivated by rashil2000) [#D1646] 15593 https://github.com/akinomyoga/ble.sh/issues/133#issuecomment-910543950 15594 15595 試してみたら普通に動く様である。つまり bash は stderr にしか物を出力しない。 15596 他の環境でも同様に動くか確かめてから適用する事にする。 15597 15598 * Cygwin: OK 15599 * Void Linux: OK 15600 * Ubuntu: OK 15601 * Solaris: OK 15602 * Haiku: OK 15603 * Minux: OK 15604 * BSD: OK 15605 15606 うーん。置き換えてしまって問題ない気がする。 15607 15608 2021-09-15 15609 15610 * canvas: c2w の再設計 [#D1645] 15611 15612 幅の計算は端末によって全然異なる。 15613 15614 更に UAX 11 は可也適当で実際にこれに完全に準拠するという訳には行かない。 15615 多くの端末は wcwidth を参照している。一部の端末は wcswidth を参照するとし 15616 ている。これらの関数が内部で一体どの様なアルゴリズムを用いているか不明で 15617 ある。そもそも locale によっても異なるし、システムによっても異なるかもし 15618 れない。wcwidth のデータベースが一体何処で管理されているのかも分からない。 15619 もし特定の文字の幅について変更の必要があるという判断に至ったら何処に要求 15620 を出せば良いのかすら不明瞭であるし、例えだしたとしてもそれが末端まで波及 15621 するのかどうかも不明である。それらを管理している人たちがちゃんと端末の専 15622 門家であるのかというのも怪しい。wcwidth が整数値を返す事からこれは主に端 15623 末の為の関数の様に思われるから wcwidth のデータベースは TWG が少なくとも 15624 端末に詳しい人が管理するべきなのである。 15625 15626 [これまでに分かった事のまとめ] Ref #D1619 15627 15628 * UAX 11 によればこれが指定するのは実際の幅ではなくて、その文字が属する言 15629 語の典型的な幅なのであって、例えば制御文字について幅2 や A が与えられて 15630 いたとしてもその文字自体が本当に幅2 や A に割り当てられた幅を持つという 15631 訳ではないという事。 15632 15633 結局 UAX 11 は well-defined ではないのである。 15634 15635 * Fedora 31 の wcwidth を参照すると、これは Unicode 11.0 を元にしている様に 15636 見える。また A の文字は幅 1 としている。Cn (未使用) については -1 を返す。 15637 Cc, Cs, Zl, Zp についても -1 を返す。但し例外として NUL は 0 になる。Mn, 15638 Me, Cf は基本的に 0 を返す。以下に掲げる通り Cf の一部は例外として 1 を返 15639 す。 15640 15641 00ad wcwidth=1 width(eaw=3,gencat=Cf)=0 SHY(soft-hyphen) 15642 0600..0605 wcwidth=1 width(eaw=1,gencat=Cf)=0 アラブの数字らしい。何故Cfなのかは謎 15643 06dd wcwidth=1 width(eaw=1,gencat=Cf)=0 ARABIC END OF AYAH (アラビア語?) 15644 070f wcwidth=1 width(eaw=1,gencat=Cf)=0 SYRIAC ABBREVIATION MARK (シリア短縮記号?) 15645 08e2 wcwidth=1 width(eaw=1,gencat=Cf)=0 ARABIC DISPUTED END OF AYAH (アラビア語) 15646 110bd wcwidth=1 width(eaw=1,gencat=Cf)=0 KAITHI NUMBER SIGN 15647 110cd wcwidth=1 width(eaw=1,gencat=Cf)=0 KAITHI NUMBER SIGN ABOVE 15648 15649 他の文字については基本的に UAX 11 に従った幅になっているが、以下の3つの範 15650 囲に関しては例外として UAX 11 とは異なる幅になっている。 15651 15652 1160..11ff wcwidth=0 width(eaw=1,gencat=Lo)=1 ハングル字母 (160字) 15653 3248..324f wcwidth=2 width(eaw=3,gencat=No)=1 囲み文字10-80 (8字) 15654 4dc0..4dff wcwidth=2 width(eaw=1,gencat=So)=1 易経記号 (6字) 15655 15656 [実装] 15657 15658 大体様相が分かったので c2w の新しい実装を構築する事にする。現在の実装と 15659 形式を変更する必要があるかもしれない。現在は条件式を使って簡単に判定で 15660 きる所までは絞り込んでその後で二分法に持ち込んでいる。 15661 15662 1 そうではなくて最初に孤立している文字は先に判定する。ASCIIもテーブルで 15663 直接判定する。 15664 2 code >> 8 を使ってすぐに判定できる物はその場で返すそれ以外の物につい 15665 ては次のステップで使う二分探索テーブルの範囲を指定する。 15666 3 二分探索で絞り込み。 15667 15668 という具合にするのが良い気がする。 15669 15670 * done: 問題点は、code>>8 を実行したとしてもUnicode の範囲を考えると 4352 15671 の区間が存在するという事。だからと言って2分木や patricia を実装するのも大 15672 袈裟な気がする。何より2分木や patricia は遅い。code>>16, code>>8 の2段構 15673 成にするという手も考えられるが、0,1,2,3,E,F,10 が使われているので、結局 15674 1792要素は存在するという事。もう一つの手は code>>8 で加速するのは BMP だ 15675 けにして、それ以外のものは初めから2分探索を実行するという事。うーん。見て 15676 みたが SMP も結構細かいので SMP も最初の判定に含めて良い気がする。 15677 15678 →これについては最終的には BMP, SMP に関しては c>>8 にして、それ以降の物 15679 については c>>12 で振り分ける事にした。 15680 15681 * done: wcwidth が -1 を返す様な物に対してはどの様に対応するべきだろうか。 15682 例えば、一つの方法は他の端末がやっている様に幅 1 を適当に割り当てるという 15683 物。また別の方法は EastAsianWidth に従って割り当てるという物。或いはまた 15684 別の方法としては -1 は保持した儘でテーブルを参照する時に補正する方法。然 15685 し補正する為には EastAsianWidth 特性の値もちゃんと覚えて置かなければなら 15686 ない…等と考えていくとやはり EastAsianWidth と GeneralCategory を別々に管 15687 理する必要があるのではないかという疑惑も出てくる。 15688 15689 % うーん。取り敢えずは EastAsianWidth だけでもスクリプトから参照できる様 15690 % にするべきではないか。GeneralCategory のテーブルサイズも巨大になりそう 15691 % ではあるがそれは仕方がないと思って諦めるか。。 15692 15693 →これに関しては -1 を返す代わりに -1 -2 -3 で、幅1, 幅2, 幅A を区別でき 15694 る様にする事にした。 15695 15696 * reject: もう一つ気になるのは、EastAsianWidth, GeneralCategory から幅に対 15697 応付ける方法には他の可能性はないのかという事である。Unicode は中途半端に 15698 しか指定していないので何らかの方法を決める必要があるが、その方法は固定で 15699 良いのだろうか。そうではなくて、スクリプトの側でより柔軟に設定できる様に 15700 した方が良いという事はないのだろうか。 15701 15702 やはりただでさえ EastAsianWidth だけで巨大なのに GeneralCategory まで入れ 15703 ると大変な事になるので、これは却下する事にする。ライブラリとしてユーザー 15704 が使える様に GeneralCategory のテーブルを作成するという可能性は未だ残って 15705 はいる。 15706 15707 * done: もう一つの問題は Unicode version 依存性をどの様に取り扱うかという事。 15708 全ての Unicode version について情報を纏めて一つのテーブルにするという手と、 15709 Unicode の version 毎にテーブルを用意するという手がある。 15710 15711 ? wcwidth 用の例外措置が必要になる文字の集合も version によって異なるかも 15712 しれず色々面倒である。例外処置について Unicode version 毎に管理するか、 15713 或いは、一括で管理するか。或いは端末ごとに管理する必要があるか。うーん。 15714 wcwidth はシステム等に依存するだろうと思われるので Unicode 由来のデータ 15715 に統合するのは始末が悪い様に思われる。やはり例外は別枠で管理するべきで、 15716 その折には Unicode version 等と紐付けて管理するのは悪手である。それより 15717 は locale/system 毎に管理するべきである。 15718 15719 →wcwidth が Unicode とずれている分については別枠で管理するのが良い。少 15720 なくとも Unicode の version と紐付けて管理するのは悪手である。 15721 15722 version 毎のテーブルにするか或いは一つのテーブルに統合するかは実際に両方 15723 の方式でテーブルを作成してサイズについて比較しかない様な気がする。実の所、 15724 サイズとしてどちらの方が小さくなるのか予想が付かない。 15725 15726 取り敢えずテーブルを作成するコードを書くことにする。どうせなのでもう C++ 15727 で書いてしまう事にしようか? →うーん。formatting などが色々面倒なのでやは 15728 り gawk で実装したのを適当に加工するのが良い気がしてきた。 15729 15730 - 全てを統合したファイルのサイズは 426行 45KB である。単一だと 283行 36KB 15731 である。こうなって来るとやはり統合した物を埋め込むべきの様に思われる。 15732 15733 * ok: 以下は例外処理をしていた物だが新しい c2w でもちゃんと半角になっている 15734 だろうか? 15735 15736 [0x303F]=1 # 半角スペース 15737 15738 →実際に ble/unicode/c2w で確認した所、周辺は2になっているのに関わらず 15739 0x303F は 1 になっているという事が確認できた。なのでこの例外処理はもはや 15740 不要である。 15741 15742 [追加実装] 15743 15744 * done: char_width_version 自動判定 15745 15746 そもそも現在の設定インターフェイスで良いのかという疑問もある。他に、 15747 wcwidth=-1 になるが UAX 11 では幅を指定している物の取り扱いをどうするか 15748 (_ble_unicode_c2w_invalid) の振る舞いの制御等も設定対象の可能性の一つである。 15749 15750 自動判定に関しては実は UnicodeMapping を参照すれば良いという気がする。 15751 target の version で切り替わる文字を使って判定する。然し、端末が微妙に変な 15752 振る舞いをしていたりする場合にはこの方法だと一番近い version を判定できなかっ 15753 たりする可能性もある。例えば、undefined な文字であっても元から幅 2 である事 15754 を予想できた場合には古い Unicode version であったとしても初めから 2 を返し 15755 ていた等という事が考えられる。色々考えると robust に判定する方法は無い様な 15756 気がする。更に絵文字の可能性がある文字については判定に使う事ができない。 15757 15758 何れにしても取り敢えず UnicodeMapping を拾ってみる事にする。 15759 15760 * 4 15761 * 9 15762 * 10 15763 * 12 15764 15765 よく考えたら 負→正 になった等だと wcwidth < 0 に対して 1 を割り当てている 15766 端末での判定ができなくなる。という事を考えると、幅2の文字を使って判定するべ 15767 きなのではないか。 15768 15769 * 42 ... ver1 以降で 2 15770 * 30 ... ver2 以降で 2 15771 * 45 ... ver3 以降で 2 15772 * 63* ... ver4 以降で 1, ver9 以降で 2 15773 * 33 ... ver5 以降で 1 15774 * 15 ... ver6 で 1, ver7 以降で 0 (元々-1) 15775 * 41 ... ver7 以降で 0 (元々2) 15776 * 24 ... ver8 以降で 0 (元々-1) 15777 * 63* ... ver9 以降で 2 (他に56も同様) 15778 * 43 ... ver10 以降で 2 15779 * 44 ... ver11 以降で 2 15780 * 57 ... ver12 以降で 2 15781 * 47 ... ver13 以降で 2 15782 * 46 ... ver14 以降で 2 15783 15784 63 は emoji だった。63 になっている全ての範囲の先頭文字について確認して、 15785 何れも emoji であるという事を確認した。うーん。プログラム的に確認するべきの 15786 気がしてきた。 15787 15788 ver1 U+9FBC(40892) 龼 1->2 (-1 2 2 2 2 2 2 2 2 2 2 2 2 2 2) 15789 ver2 U+9FC4(40900) 鿄 1->2 (-1 -1 2 2 2 2 2 2 2 2 2 2 2 2 2) 15790 ver3 U+31B8(12728) NA 1->2 (-1 -1 -1 2 2 2 2 2 2 2 2 2 2 2 2) 15791 ver4 判別不能 15792 ver5 U+D7B0(55216) ힰ 2->1 (-1 -1 2 2 2 1 1 1 1 1 1 1 1 1 1) 15793 ver6 判別不能 15794 ver7 U+3099(12441) NA 2->1 (2 2 2 2 2 2 2 0 0 0 0 0 0 0 0) 15795 ver8 U+9FCD(40909) 鿍 1->2 (-1 -1 2 2 2 2 2 -2 2 2 2 2 2 2 2) うーん。古い ver でも幅1に注意 15796 ver9 U+1F93B(129339) NA 1->2 (-1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2 1) 15797 ver10 U+312E(12590) ㄮ 1->2 (-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2 2) 15798 ver11 U+312F(12591) ㄯ 1->2 (-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2 2) 15799 ver12 U+16FE2(94178) 翢 1->2 (-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2 2) 15800 ver13 U+32FF(13055) ㋿ 1->2 (-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2) 15801 ver14 U+31BB(12731) ㆻ 1->2 (-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 2) 15802 ver15 U+9FFD(40957) 鿽 1->2 (-1 -1 2 2 2 2 2 -2 -2 -2 -2 -2 -2 -2 -2 2) 15803 15804 実装した。設定を直接上書きする方式に変更する事にした。例えば 15805 char_width_mode=auto にしていると、幅の判定を終えた時には 15806 char_width_mode=west か char_width_mode=east に書き換える。同様にして 15807 char_width_version についても決定した値で上書きする事にする。 15808 15809 * done: blerc, wiki: bleopt char_width_version 15810 15811 対応した。 15812 15813 2021-09-14 15814 15815 * prompt: $? is not properly set in ${PS1@P} (reported by nihilismus) [#D1644] 15816 https://github.com/akinomyoga/ble.sh/issues/136 15817 15818 setexit をしていなかった。 15819 15820 他にも何か影響があったりするだろうか。例えば、その他のシェル設定は復元しな 15821 くても良いのだろうか。PROMPT_COMMAND の前後では何か調整していた気がする… 15822 と思って改めて確認した所 PROMPT_COMMAND は単に PS1 を復元していただけだった。 15823 その他の設定は待避した儘になっている。なので気にしなくて良い。 15824 15825 2021-09-11 15826 15827 * global: resolve leak variables [#D1643] 15828 15829 - fixed: CHARS=([0]="13") 15830 - fixed: git_base=/home/murase/.mwg/src/ble.sh 15831 - fixed: git_base_dir=/home/murase/.mwg/src/ble.sh/.git 15832 - fixed: nhash=$'10:10,10,10,337,10,10,10:justify=\r,\\q{lib/vim-airline}' 15833 - fixed: wattr_buff=([0]="5:72057594037930244") 15834 - fixed: wattr_g=d 15835 - fixed: wattr_pos=101 15836 - fixed: _data=([2]="") 15837 15838 - BASH_REMATCH: これは bleopt 等をユーザーから実行すると書き換わってしまう。 15839 然し、local BASH_REMATCH を実行しようにも readonly でエラーになってしまう。 15840 書き換わるのは問題ないと諦めるしかない。 15841 15842 read, bind, history, etc. 等では保存復元した方が良いかもしれない。 15843 →read, exit, bind, history, trap で保存復元する様にした。 15844 15845 他に初期化時にも問題になるかもしれない…が、そもそも soruce xxx としたら 15846 中で BASH_REMATCH を使っている可能性は排除できないので、これは気にしなく 15847 て良い気がする。 15848 15849 2021-09-08 15850 15851 * width: char_width_mode を変えた時にキャッシュがクリアされていない気がする (reported by Barbarossa93) [#D1642] 15852 https://github.com/akinomyoga/ble.sh/issues/135 15853 15854 * syntax: "\"" が正しくエスケープ着色されない [#D1641] 15855 対応した。 15856 15857 2021-09-01 15858 15859 * util (bleopt, bind): fix interfaces [#D1640] 15860 15861 * bleopt の unknown option のエラーメッセージでオプション名が '-c' 固定になっている。 15862 15863 * 2021-07-20 bind --help の exit status が 1 になっている。2 であるべき。 15864 15865 * complete: 古い bash における -D, -I の対応 [#D1639] 15866 15867 どうやら -D, -I はそれぞれ内部的には _DefaultCmD_, _InitialWorD_ という名 15868 前のコマンドに対する補完として実装されている様である。だとすれば、古い bash 15869 の version で -D, -I に対応するとしたらこれらの単語に対して検査すれば良いの 15870 ではないか。 15871 15872 というか現在の実装で古い bash ではどの様に振る舞うのだったか。 15873 確認した。 -I に関しては version を確認して処理している。 15874 -D に関しては complete -p -D が成功するかどうかで動作を変更している。 15875 15876 * 2021-05-03 edit: support bash-5.2 READLINE_ARGUMENT [#D1638] 15877 15878 5.2 新機能: READLINE_ARGUMENT: 調べてみると引数が存在している時にのみ定義さ 15879 れる様である。また今気づいた事だが -x 属性が入っている。他の READLINE_* も 15880 全て同様である。よく考えてみれば、bind -x で外部コマンドを呼び出す事もある 15881 のだから -x 属性が入っていないと困る。 15882 15883 * 2021-08-23 mandb: manpath コマンドを使っても MANPATH は得られる [#D1637] 15884 15885 また、MANPATH に空パスが含まれている場合にはそれは標準の manpath と解釈される様だ。 15886 15887 manpath の emulation についてちゃんと考える。 15888 15889 MANPATH が設定されていない時または空パスが含まれている時は/etc/man_db.conf 15890 及び ~/.manpath を読み取る必要がある。MANDATORY_MANPATH 及び MANPATH_MAP を 15891 解釈すれば良いだろう。更に PATH 中の bin を share/man に置き換えてディレク 15892 トリが存在するかどうか確認する。 15893 15894 →その様に実装した。 15895 15896 * MANDB_MAP についても実装するべきなのではないか。というか MANDB_MAP とは何 15897 か。説明を見ると MANPATH から CATPATH への対応表の様だが、CATPATH とは何 15898 か。検索してみると整形済みの物をキャッシュしておく場所の様だ。つまり、cat 15899 するだけで説明が読める様な状態でファイルを保存しておく場所という事なのだ 15900 ろう。 15901 15902 実際に指定されている /var/cache/man の下を見ると index.db という 500kB の 15903 ファイルが一個あるだけで、cat するだけという状態ではない様な気がするが、 15904 然しデータベースとして記録しているのだろうと思う。 15905 15906 何れにしてもこれは ble.sh の関知する所ではない。気にしない。 15907 15908 * auto-complete: idle.sleep で異なる時計を参照していた事による無限ループ (reported by rashil2000) [#D1636] 15909 https://github.com/akinomyoga/ble.sh/issues/133 15910 15911 msys2 で auto-complete が特定の状況で実行されないという報告だったが、自分の 15912 手元で complete_timeout_auto= にしてみたらどうやら無限ループになっている気 15913 がする。調べてみると idle.sleep しているのに sleep していない。と思ったら、 15914 どうやら異なる時計を参照していた為に msleep が skip されて、無限に msleep 15915 の要求をし続けている状態になっていた。 15916 15917 これを直したらちゃんと補完候補が表示される様になった。 15918 15919 然しこれについては過去に修正した様な気がする。過去に修正した時の修正漏れか 15920 或いは逆方向に間違えて修正したか。再度確認する必要がある。 15921 15922 * ble/complete/auto-menu.idle の #D1597 での修正 15923 15924 53dd018e で他の箇所を類似の問題により isleep から sleep に切り替えている。 15925 #D1597 である。一方で今回問題になっている箇所は最初から sleep だった様だ。 15926 #D1597 に詳しく説明が書かれている。 15927 15928 改めて実装を確認する。auto-menu.idle は _idle_clock_start を元にしてい 15929 る。_idle_clock_start は ble/util/idle.clock を元にしている。 15930 ble/util/idle.clock は色々実装を切り替えているので環境によって異なる。ま 15931 た、idle.sleep もまた ble/util/idle.clock を元にしている。 15932 15933 * 今回の ble/complete/auto-complete.idle に関しては、唯単に idle.sleep を要 15934 求しているだけの様に見える。但し、最後にユーザー入力があって以降の経過時 15935 間を考慮に入れる為に ble_util_idle_elapsed を用いている。この 15936 ble_util_idle_elapsed は _ble_util_idle_sclock-_idle_sclock_start を元に 15937 していて、更にこれらは ble/util/idle/.sleep で積算される。 15938 15939 うーん。つまり、ble_util_idle_elapsed を参照する限りは isleep を使う必要 15940 があるという事。一方で auto-complete の delay を処理するのは isleep に基 15941 づくべきか sleep に基づくべきかという疑問もある。 15942 15943 * また macOS の 100% も関係しているかもしれない。報告によると履歴のロードに 15944 関係しているという事だが、nawk が走っている間ずっと CPU が動いているとい 15945 う状態になっている可能性もある。と思ったがそうでもなかった。そもそも履歴 15946 の初期化では sleep は行っていない。 15947 15948 2021-08-30 15949 15950 * edit: command-help が効かなくなっている [#D1635] 15951 15952 どうやら以下の commit で external-command を書き換えた時に、内部で使用して 15953 いる変数名 command と command-help で使用している変数名が被ってしまって問題 15954 が起こっている様だ。 15955 15956 7b63c60d src/edit.sh (Koichi Murase 2021-05-06 16:04:39 +0900 8755) local command=$1 15957 15958 一旦は command-help の側でコマンド名を他の変数に待避する様に書き換えてみた 15959 が、うーん。そもそも external-command は呼び出し元の変数名に影響が無い様に 15960 特別な変数名を使うべきである。 15961 15962 * README: やはり ble.sh の読み方を与えるべきかもしれない [#D1634] 15963 https://www.youtube.com/watch?v=YS1vxEhd2Pc 15964 15965 動画の最初で読み方に戸惑いが見られる。やはり発音しやすい発音として blesh を 15966 呈示しておいた方が良い様な気がしてきた。別に正しい読み方がある訳でもないし、 15967 寧ろ個人的には bee-elle-yee-dot-ess-eightch と読んでいるが、やはり膾炙する 15968 のは発音しやすい読み方だろう。 15969 15970 或いは両方提示する。 15971 15972 /blɛʃ/ or /biːɛliː dɑt ɛseɪtʃ/ 15973 15974 うーん。後者は態々 IPA で書く迄の事もなく、くどい感じがする。 15975 15976 少しずつ push した方が GitHub の suggestion に現れる様なので、 15977 試みに今日から一日に 1 commit ずつ push する事にする。check の意味も兼ねて。 15978 15979 他の README に関連する編集も纏めて一つの commit にする事にする。 15980 15981 * README: @oc1024 がリンク切れになっている。やはり質問しているとは言え他の 15982 人をどんどん README に追加していくのは出過ぎた真似だろうか。huesche の件 15983 が偲ばれる。然し一方でこちらが正体を当てた事から oc1024 ではなくてちゃん 15984 と capezotte という名前にアカウントを変更したのかもしれない。何れにしても 15985 capezotte に変えるべきだろうと思われる。 15986 15987 * README: Wiki -> wiki? 15988 15989 Wiki ではなくて wiki なのではないか。README の他にも文頭でないのに Wiki と 15990 書いている箇所があるかもしれない。 15991 15992 改めて検索してみると日本語の記事だと wiki を Wiki と書いている様である。つ 15993 まり、Wiki と capitalize するのは日本語の習慣という事なのだろう。 15994 15995 * README: 各機能の無効化について記述する 15996 https://github.com/akinomyoga/ble.sh/issues/134 15997 15998 * 2021-08-19 st: insert で CSI 4h を送るなど色々変な key sequence を送ってくる [#D1633] 15999 16000 他に以下の物が見られる。 16001 16002 CSI L (C-insert) 16003 CSI J (C-end) 16004 16005 他にも色々ありそうなので一つ一つ既に実装されている物と見比べて調べる必要が 16006 ある。幾つか追加した。ESC[M は他とかちあっている。 16007 16008 2021-08-19 16009 16010 * st: unknown csi error message (reported by Shahabaz-Bagwan) [#D1632] 16011 https://github.com/akinomyoga/ble.sh/issues/132 16012 16013 * 先ず st は DA2 に応答しない。DA1 に対して CSI ?6c を返答する。 16014 16015 何れにしても古い st が一掃されるまでは CSI ?6c を st と解釈するなどの処置 16016 で良い気がする。 16017 16018 と思ったら何と st は TERM に st-256color を設定する様だ。なので先にこれを 16019 見て st と判明したならば DA2 は送信しなくて良い。modifyOtherKeys に関して 16020 も現在の st の構造を見る限りは将来的に実装すると思われない。完全に無効化 16021 するという事で良い気がする。 16022 16023 * ok: 然し報告によると stderr が slave の stdrr に書き込まれると言う…。不 16024 思議な事である。と思って改めて報告を見たら違った。エラーメッセージは起動 16025 元の terminal に表示されているのだった。つまりこれはそもそも期待通りの振 16026 る舞いであり問題はない様に思われる。その旨説明する。 16027 16028 * ok: st で prompt_status_line を有効にしていると座標計算がずれるどうやらこ 16029 れは雷絵文字の幅計算がずれているのが原因の様である。これはまあ仕方の無い 16030 ことである。もしちゃんと対応するのだとしたらまずは st をちゃんと検出でき 16031 る様にしなければならない。 16032 16033 2021-08-26 minux になっている箇所がある。 16034 2021-08-30 #D1633 で一緒に直した。 16035 16036 2021-07-19 16037 16038 * edit: support TMOUT for session timeout [#D1631] 16039 16040 またそれと並行して session TMOUT についても実装したい。うーん。振る舞いにつ 16041 いて確認する。恐らく最後にコマンドを実行してからどれだけ時間が経ったのかで 16042 timeout を実行するという仕組みになっている。これはどの様に実装すれば良いの 16043 だろうか。 16044 16045 動作確認をして見た所、新しいコマンドを実行したタイミングというよりはやはり 16046 accept をしたタイミング、或いは newline を挿入したタイミングでリセットされ 16047 るという事の気がする。 16048 16049 例えば insert-newline に於いてログアウト時刻をセットするという仕組みにする 16050 のが良い気がする。ログアウト時刻が設定されていたらそれまで sleep するという 16051 事にする? 然し、それだと十分に長い timeout にしてたくさんコマンドを実行する 16052 と、実行したコマンドの数だけ待ちタスクが増えて大変な事になってしまう。ユー 16053 ザー入力または sleep で時間を測るというタスクが必要になる気がする。または、 16054 後で外部からタスクの待ち時間を書き換える仕組みが必要になる気がする。 16055 16056 うーん。外部から既存のタスクの待ち時間を書き換える仕組みにするのが良い。 16057 16058 タスク番号を指定して書き換えられる様にする。その為にはタスク登録時に登録し 16059 たタスクの番号が分かる様にするべきである。 16060 16061 ? それから bash-4.0 未満で idle.push が使えない場合にはどうするのか…? これ 16062 は諦めるしかない様な気がする。bash-3.2 以下では TMOUT は動かない。 16063 16064 # 或いは bash-3.2 以下でも read -t 0 もしくは select に対応する様な物を 16065 # loadable builtin 等で用意できればそれはそれで良いのかもしれないが、実の 16066 # ところライセンスなどの問題から loadable builtin で実装するかどうかは悩 16067 # ましい所である。代わりに外部コマンドとして実装するという手もあるが。何 16068 # れにしてもこれは散々別の場所で議論してきた所であるから今ここでは議論し 16069 # ない。 16070 16071 ? どのタイミングでタイマーをリセットするのが良いのか? insert-newline で実行 16072 しようかと考えていたが、insert-newline はコマンド実行前に実施される。本来 16073 はコマンド実行後にプロンプトが最初に表示された時点から実行するべきの様に 16074 思われる。 16075 16076 うーん。という事を考えると POSTEXEC で実行するべきだろうか。また、この場 16077 合には一番最初のプロンプトに対して timeout が設定されないので、ble-attach 16078 に際しても同様に設定をするべきの気がする。 16079 16080 POSTEXEC だと複数回のコマンドが実行される時に余分に timeout が再計算され 16081 る事になる。それよりは /.end 辺りで設定した方が良いのではないかという気も 16082 する。うーん。 16083 16084 或いは、insert-newline で何か行番号等を更新して、PS1 の表示時にその行番号 16085 が変化していたら更新するという具合にするのが良い気がする。 16086 16087 取り敢えず実装した。動いている。表示を多少調整した。 16088 16089 * global: "TMOUT: readonly variable" というエラーメッセージが表示される (reported by farmerbobathan) [#D1630] 16090 https://github.com/akinomyoga/ble.sh/issues/129 16091 16092 問題のエラーメッセージは ble-edit/io/check-stderr から出てきている。 16093 16094 これは /etc/profile.d/ 辺りに readonly TMOUT=xxxx 等という設定が書き込まれ 16095 ているサーバーが存在する事があってその時に発生する。うーん。正直な所そうい 16096 う設定を行うサーバーの方が悪いとしか言いようがない。然し勝手に読み込まれる 16097 のはユーザーとしては仕方がない。 16098 16099 16100 a TMOUT に変な値が設定されている時には -t 巨大な数 というのを指定して誤魔化 16101 すしかない。一方で、毎回 TMOUT の値をチェックするのは効率が悪い。 16102 16103 b 或いは常に -t 巨大な数 を指定するという手もあるのかもしれないが、それだと 16104 read を実行する度に alart/select が設定される事になって効率が悪い。 16105 16106 c 或いは TMOUT に有限の値を設定されている時に限り -t 巨大な数 を設定すると 16107 いう手もあるのかもしれない。 16108 16109 d 或いはユーザー空間に入る時に TMOUT が readonly になっていないか確認して、 16110 TMOUT が readonly になっていたら workaround の必要性を示す変数を設定する 16111 という手がある。取り敢えず TMOUT が readonly の時にだけ振る舞いを変えるの 16112 だとすればこの方針を貫くのが良い。 16113 16114 e 或いは enter する時に TMOUT を未設定にするという手もあるのだろうか? と思っ 16115 たが、それだと session timeout としての TMOUT が動かなくなってしまうので 16116 駄目→と思ったが、確認してみた所、そもそも session timeout としての TMOUT 16117 は ble.sh ではちゃんと動作していなかった。となると、TMOUT は自前で実装す 16118 る必要がある。自前で実装するのだとすれば ble.sh 内部では TMOUT= になる様にして、 16119 read を実行する箇所で TMOUT= を実行する事はない様にすれば良いのである。 16120 16121 _ble_builtin_read_tmout_wa=(-t 巨大な数) 等でも適当に設定してこれを read 16122 の引数に指定する事にする。 16123 16124 [修正] e の方針で実装した。取り敢えず動いている。 16125 16126 * history: ble-attach に使ったコマンド履歴が欠けている。履歴番号にもずれが生じている [#D1629] 16127 Ref #D1120 16128 16129 bashrc から attach した時には欠けているコマンドは存在しない様だ。 16130 16131 % source ble.sh で新しく読み込んだ時にも欠けているコマンドは発生しない。と 16132 % 思ったらこれは気の所為だった。 16133 16134 うーん。然し ble-attach を実行した時点ではちゃんと履歴が登録されている筈だ 16135 から後になって履歴が変化していると考えるべきだろうか→やはり確認してみた所、 16136 一旦履歴項目が追加されているのにも関わらずその後で削除されている様に見える。 16137 16138 履歴を初期化する時点での最後の項目はどうなっているのかについて確認する必要がある気がする。 16139 16140 分かった。これは ble/builtin/history/is-empty で history -p を使っている為 16141 に履歴項目の数が減少している。この関数では BASH_SUBSHELL を参照して 16142 subshell の中にいる時には対策をしない様にしているが、実は subshell の中であっ 16143 ても履歴項目が減る時には減るし、後で履歴データを参照する場合にはちゃんと 16144 subshell の中で history -p を実行しなければならない。 16145 16146 2021-07-13 16147 16148 * 2021-06-28 main: set -Bk 等の場合に対しても対策する [#D1628] 16149 16150 set -B に対してはブレース展開を使っているコードが影響を受ける。ブレース展開を使っているコードは以下で抽出する事ができる。 16151 16152 $ grc '[^$]\{[^[:space:]]*,[^[:space:]]*\}' --exclude={wiki,memo,test,ext} --exclude={lib/test-\*.sh,make_command.sh} 16153 ./keymap/emacs.sh:21: copy{,-forward,-backward}-{c,f,s,u}word 16154 ./keymap/emacs.sh:22: copy-region{,-or} 16155 ./keymap/vi.sh:220: delete-backward-{c,f,s,u}word 16156 ./keymap/vi.sh:221: copy{,-forward,-backward}-{c,f,s,u}word 16157 ./keymap/vi.sh:222: copy-region{,-or} 16158 ./keymap/vi.sh:2799: local _ble_keymap_vi_single_command{,_overwrite}= # single-command-mode は持続させる。 16159 ./keymap/vi.sh:2813: ble/util/unlocal _ble_keymap_vi_single_command{,_overwrite} 16160 ./lib/core-complete-def.sh:78: ble/complete/menu-style:{align,dense}{,-nowrap}/construct-page \ 16161 ./lib/core-complete-def.sh:80: ble/complete/menu-style:desc{,-raw}/construct-page 16162 ./lib/vim-airline.sh:114: for name in {a,b,c,x,y,z,error,term,warning}{,_normal,_insert,_replace,_visual,_commandline,_inactive}; do 16163 ./lib/vim-airline.sh:343: for unit in _ble_lib_vim_airline_section_{a,c,z,b,y,x}; do 16164 ./src/benchmark.sh:231: for n in {1,10,100,1000,10000}\*{1,2,5}; do 16165 ./src/decode.sh:3944: 'M&&E,A[i++]=_ble_decode_Erro|'{254,255} 16166 ./src/edit.sh:7793: ble-decode/keymap:vi_{i,n,o,x,s,c}map/define 16167 ./src/util.sh:2667: builtin unset -f ble/function#advice/{before,after,around,original}:"$name" 2>/dev/null 16168 ./src/util.sh:4218: ble/array#push dirs "$_ble_base"{,/contrib,/lib} 16169 $ grc '[^$]\{[0-9.]+\}' --exclude={wiki,memo,test,ext} --exclude={lib/test-\*.sh,make_command.sh} 16170 ./lib/init-bind.sh:153: for i in {128..255} {0..127}; do 16171 ./src/decode.sh:3937: 'M&&E,A[i++]='{0..127} 16172 ./src/decode.sh:3938: 'C=C<<6|'{0..63}',--M==0&&(A[i++]=C)' 16173 ./src/decode.sh:3939: 'M&&E,C='{0..31}',M=1' 16174 ./src/decode.sh:3940: 'M&&E,C='{0..15}',M=2' 16175 ./src/decode.sh:3941: 'M&&E,C='{0..7}',M=3' 16176 ./src/decode.sh:3942: 'M&&E,C='{0..3}',M=4' 16177 ./src/decode.sh:3943: 'M&&E,C='{0..1}',M=5' 16178 ./src/decode.sh:3985: for i in {0..255}; do 16179 16180 それほど多い訳でもないが代替手段がある訳でもない様な物が多く含まれる。 16181 うーん。これも ble.sh の内部では解除するオプションとするべきの気がする。 16182 16183 set -k に対しては bleopt a=b 等が影響を受ける。他にも影響を受ける物は多く存 16184 在するかもしれない。何れにしてもこのオプションは非現実的である様に思われる 16185 のでやはり ble.sh 内部では解除する事としたい。 16186 16187 * kitty, fzf: modifyOtherKeys で問題が生じている (reported by Nudin) [#D1627] 16188 https://github.com/akinomyoga/ble.sh/issues/126 16189 16190 うーん。fzf が modifyOtherKeys で動かなくなっている。 16191 というか補完全般で問題が生じるのだろうという気がする。 16192 16193 x 何故か知らないがまた kitty で動かなくなっている。うーん試して見た所、いつ 16194 の間にかに \e[>4;0m ですら効かなくなっている様だ。\e[>4m としなければなら 16195 ない。もう面倒なので kitty の時だけ異なる sequence を出力する様に修正する。 16196 16197 以前は確かに修正したと思ったのだが…。確認すると以下で動作する事を確認している。 16198 ということはまた kitty の振る舞いが変わったという事である。 16199 https://github.com/akinomyoga/ble.sh/issues/110#issuecomment-841839605 16200 16201 取り敢えず修正した。動作確認した。OK と思う。 16202 16203 * kitty: keypad enter が変なシーケンスで送られてくる (reported by Nudin) [#D1626] 16204 https://github.com/akinomyoga/ble.sh/issues/127 16205 16206 取り敢えず以下に挙げられているキーの番号を kitty 専用に判定する事にした。 16207 https://sw.kovidgoyal.net/kitty/keyboard-protocol.html#functional-key-definitions 16208 16209 * compat: terminal dnkl/foot は DA2 で 010801 などの文字列を返すようだ (reported by GorrillaRibs) [#D1625] 16210 https://github.com/akinomyoga/ble.sh/issues/128 16211 16212 これが DA2 の判定で8進数と解釈されてしまって問題が発生している。 16213 escape sequence に含まれる数字は全て明示的に10進数で解釈するべきである。 16214 16215 因みに dnkl/foot は DA3 で FOOT という文字列を返すそうだ。 16216 16217 * dnkl/foot を認識する様にした。 16218 * CSI の解釈で 0 が前置されていても良い様に書き直した。 16219 一部の CSI については既に対策されていたが今回全てに対して処理する事にした。 16220 * DA2 の解析はまた別の箇所で行われていた。これも対処する事にした。 16221 * ble/canvas/trace の諸々の制御機能についても対策した。 16222 * SGR の解析部分 (ble/color/read-sgrspec) は既に対処済みだった 16223 16224 https://github.com/akinomyoga/ble.sh/issues/128#issuecomment-878670622 16225 16226 追加修正。10# で後ろに何も数字が続いていないと 5.1 ではエラーになる。 16227 これは修正した。多分大丈夫。 16228 16229 2021-07-12 16230 16231 * emacs モードで vi-bword 使う (requested by SolarAquarion) [#D1624] 16232 https://github.com/akinomyoga/ble.sh/issues/125 16233 16234 調べると vi-bword vi-Bword があって、内部的にはそれぞれ vword uword として 16235 いる。それなら edit.sh に既に定義されている vword, uword を代わりに呼び出し 16236 たら良いのではないか、と考えたが、vword は定義されていない。実装を具体的に 16237 観察すると単純に単語決定に使う文字集合を edit.sh に引き込めば良いという訳で 16238 もない。 16239 16240 観察する限りでは別に emacs mode でこの vi-bword 等を呼び出しても特に問題は 16241 生じない様にも見える。念の為どの変数を参照していてどの変数が emacs mode で 16242 期待している値になっているのかについて確認する。 16243 16244 単語単位の移動は ble/widget/vi-command/forward-word.impl 等で実行されている。 16245 特別な動作をするかどうかは渡された引数 flag で判定している。取り敢えず flag 16246 が空だと仮定するとそのまま ble/widget/vi-command/exclusive-goto.impl 16247 "$index" "$flag" "$reg" が呼び出される。そしてそのまま exclusive-range.impl 16248 に渡される。ble/keymap:vi/needs-eol-fix "$dst" && ((dst--)) が呼び出されて、 16249 移動して、 ble/keymap:vi/adjust-command-mode が呼び出さる。 16250 16251 * 最初の flag に関しては ble/keymap:vi/get-arg 経由で _ble_keymap_vi_reg の 16252 値を読み取っている。これは get-arg を呼び出していれば clear されている筈。 16253 一方で、set -o emacs 等を実行した時にちゃんとクリアされるだろうか。少なく 16254 とも vi-command/accept-line の中では clear-arg が呼び出されている。 16255 16256 vi_imap の中にいる時にちゃんと clear されているのかというのは気になる。一 16257 応 ble/widget/vi_nmap/.insert-mode を呼び出す時にはちゃんと 16258 ble/keymap:vi/clear-arg が事前に呼び出される様に書いてある様である (見落 16259 としはあるかもしれないが)。 16260 16261 emacs-editing-mode 経由で切り替えた時にちゃんと arg が clear されるのかど 16262 うか。見た所は全く考慮に入れていない様に見える。 16263 16264 a reject: keymap に attach する時に clear する? 然し emacs 側で始末するの 16265 も変である。本来独立に実装されているべきである。 16266 16267 b という事を考えると detach 時に処理できる様にするべき? 然しその場合には 16268 新しく __detach__ という特別キーも定義する必要が出てくる。もし定義した 16269 とすると、それを処理するのは何処で行うべきだろうか。 16270 ble/decode/reset-default-keymap を弄れば良い様な気もするが、初回呼び出 16271 しの際には既定で 'emacs' が代入されている為、detach が無意味に呼び出さ 16272 れてしまう気がする。それは変だ。 16273 16274 a 或いは初期値を emacs 以外 (例えば safe) などにするという手もあるだろ 16275 うか。 16276 16277 b 或いは初期値は空でも良いのかもしれない。例え emacs であっても初期化な 16278 しに使える訳ではない筈だから、現状の実装で必ず初期化は実行されている 16279 と見做すべきである様に思われる。 16280 16281 c 或いは safe を代入しておくのでも良いのかもしれない。然し確認してみた 16282 所、safe であっても初期化なしには使えない様である。なので結局 16283 _ble_decode_keymap の初期値は空文字列で良いのではないかという気がする。 16284 16285 もっと全然別の方法で clear される事を保証する事はできないのか。 16286 16287 c 例えば、emacs-editing-mode widget 自体に clear-arg を呼び出すコードを付 16288 加しておくなど。 16289 16290 d それよりは change-editing-mode hook でも定義しておくのが良い様な気もす 16291 る。然し、それだと結局 __detach__ の劣化版にしかならないので、それぐら 16292 いならば b の __detach__ に対応するべきの気がする。 16293 16294 今の所 b が最有力の対処方法である。 16295 16296 ble/keymap:vi/needs-eol-fix については現在の keymap が vi[on]map でなければ 16297 false になるので記にしなくて良い。 16298 16299 ble/keymap:vi/adjust-command-mode については 16300 16301 * _ble_keymap_vi_search_activate が非空の時に何か処理している。 16302 16303 これは様々の検索で使われている気がする。例えば単語検索等の一致で使われて 16304 いる? この状態で vi_imap に入ったりすると値が残る気がする。と思ったが別に 16305 値は代入されていなかった。改めてどの状況でクリアされるか確認する。 16306 16307 * _ble_edit_mark_active == vi_search の時にも何か処理している。 16308 16309 これはどうやら $_ble_keymap_vi_search_activate 経由で代入される様だ。 16310 16311 * _ble_keymap_vi_search_matched が何か有限の整数値を持っている時にも処理がある。 16312 16313 その他は特に何も無いように見える。これらの変数についてそれぞれどう設定さ 16314 れてどう clear されるのか確認する。 16315 16316 うーん。上記に関しては .insert-mode の中で 16317 ble/keymap:vi/search/clear-matched を呼び出す事にした。また、emacs mode に 16318 対しては clear-arg の処理に際して同時に clear-matched も呼び出す事にした。 16319 16320 [動作確認] 16321 16322 o 取り敢えず __detach__ は実装して思い通りに動く事を確認した。 16323 16324 o また vi-bword が動作する事も確認した。テストが面倒なのでこれ以上の細かい 16325 動作確認は省略する。 16326 16327 2021-07-08 16328 16329 * nullglob が勝手に on になってしまう現象 (reported by Lun4m) [#D1623] 16330 https://github.com/akinomyoga/ble.sh/issues/123 16331 16332 nullglob を保存復元している ble/complete/util/eval-pathname-expansion が怪 16333 しいと考えたが実際に動作を確認してみるとどうやらこの関数の外側で状態が書き 16334 換わっている様である。また、補完の最中に設定が書き換わる事に違いない。と思っ 16335 たが分かった…。148 で抜ける時に dtor を実行せずに eval-pathname-expansion 16336 を抜けていた。修正した。 16337 16338 2021-07-04 16339 16340 * bash-completion (_find): error message (reported by oc1024) [#D1622] 16341 https://github.com/akinomyoga/ble.sh/issues/121 16342 https://github.com/scop/bash-completion/issues/509 16343 https://github.com/scop/bash-completion/commit/f1ddf810e4ee6693acb9fab1be1794586aa111a0 16344 16345 これはどうしようもない。bash-completion が悪い。 16346 16347 * ble-0.3: bashrc で bind '"\e[D": backward-char' を実行した時にエラーメッセージ [#D1621] 16348 https://github.com/akinomyoga/ble.sh/issues/122#issuecomment-872690396 16349 16350 2021-06-19 16351 16352 * term: どうも GNOME terminal が terminal identification を変更した様だ [#D1620] 16353 16354 65;600x;1 になっている。 16355 16356 | 6cd4713c5 src/vteseq.cc (2018-03-27) int const version = (VTE_MAJOR_VERSION * 100 + VTE_MINOR_VERSION) * 100 + VTE_MICRO_VERSION; 16357 | 6cd4713c5 src/vteseq.cc (2018-03-27) reply(seq, VTE_REPLY_DECDA2R, {65, version, 1}); 16358 | 16359 | fde88ef7f src/vteseq.cc (2018-03-27) if (version != NULL) { 16360 | fde88ef7f src/vteseq.cc (2018-03-27) for (i = 0; version[i] != NULL; i++) { 16361 | fde88ef7f src/vteseq.cc (2018-03-27) ver = ver * 100; 16362 | fde88ef7f src/vteseq.cc (2018-03-27) ver += atol(version[i]); 16363 | fde88ef7f src/vteseq.cc (2018-03-27) } 16364 | fde88ef7f src/vteseq.cc (2018-03-27) g_strfreev(version); 16365 | fde88ef7f src/vteseq.cc (2018-03-27) } 16366 | fde88ef7f src/vteseq.cc (2018-03-27) g_snprintf(buf, sizeof (buf), _VTE_CAP_ESC "[>65;%ld;0c", ver); 16367 | 16368 | Behdad Esfahbod 16369 | 3b22bcc86 src/vteseq.c (2009-01-06) g_snprintf(buf, sizeof (buf), _VTE_CAP_ESC "[>1;%ld;0c", ver); 16370 | 16371 | f3d79059c src/vteseq.c (2006-02-10) version = g_strsplit(VERSION, ".", 0); 16372 | f3d79059c src/vteseq.c (2006-02-10) if (version != NULL) { 16373 | f3d79059c src/vteseq.c (2006-02-10) for (i = 0; version[i] != NULL; i++) { 16374 | f3d79059c src/vteseq.c (2006-02-10) ver = ver * 100; 16375 | f3d79059c src/vteseq.c (2006-02-10) ver += atol(version[i]); 16376 | f3d79059c src/vteseq.c (2006-02-10) } 16377 | f3d79059c src/vteseq.c (2006-02-10) g_strfreev(version); 16378 | f3d79059c src/vteseq.c (2006-02-10) } 16379 | f3d79059c src/vteseq.c (2006-02-10) ret = g_strdup_printf(_VTE_CAP_ESC "[>1;%ld;0c", ver); 16380 | 16381 | Nalin Dahyabhai 16382 | ddad9e00e src/vte.c (2003-06-27) ret = g_strdup_printf(_VTE_CAP_ESC "[>1;%ld;0c", ver); 16383 | 16384 | 3c6d81bf0 src/vte.c (2002-08-22) version = g_strsplit(VERSION, ".", 0); 16385 | 3c6d81bf0 src/vte.c (2002-08-22) if (version != NULL) { 16386 | 3c6d81bf0 src/vte.c (2002-08-22) for (i = 0; version[i] != NULL; i++) { 16387 | 3c6d81bf0 src/vte.c (2002-08-22) ver = ver * 100; 16388 | 3c6d81bf0 src/vte.c (2002-08-22) ver += atol(version[i]); 16389 | 3c6d81bf0 src/vte.c (2002-08-22) } 16390 | 3c6d81bf0 src/vte.c (2002-08-22) g_strfreev(version); 16391 | 3c6d81bf0 src/vte.c (2002-08-22) } 16392 | 3c6d81bf0 src/vte.c (2002-08-22) ret = g_strdup_printf("1;%ld;0c", ver); 16393 | 16394 | commit 3c6d81bf06becda3f9ab005c7310b2343588115e 16395 | Author: Nalin Dahyabhai <nalin@src.gnome.org> 16396 | Date: Thu Aug 22 23:27:31 2002 +0000 16397 | 16398 | * src/vte.c: Implement send-primary/secondary-device-attributes. Bind 16399 | shift+insert to "paste PRIMARY". Guard against NULL window/icon title 16400 | when telling the child app what they are. 16401 16402 この歴史を観察すると一番最初に vte に実装された時 2002-08 から 1;version;0 であったが、 16403 2018-03 に 65;version;0 に変更された様である。VERSION は何処で定義されているのだろうか。 16404 16405 | 現在の version は meson.build の中に定義されている。 16406 | 16407 | project( 16408 | 'vte', 16409 | ['c', 'cpp'], 16410 | version: '0.65.0', 16411 | 16412 | meson に移行したのは 7566ad673 (2019-04-14) である。この時は 0.57.0 16413 | 16414 | 7566ad673 (Christian Persch 2019-04-14 21:11:43 +0200 20) version: '0.57.0', 16415 | 16416 | それより前は configure.ac に定義されていた様だ。 16417 | 16418 | m4_define([version_major],0) 16419 | m4_define([version_minor],57) 16420 | m4_define([version_micro],0) 16421 | 16422 | fde88ef7f の時点での version は 0.53.0 の様だ 16423 | 16424 | 137e16630 configure.in (Behdad Esfahbod 2010-06-30 15:27:30 -0400 1) m4_define([version_major],0) 16425 | 6f330cc1a configure.ac (Christian Persch 2018-03-12 21:44:43 +0100 2) m4_define([version_minor],53) 16426 | b4b2eb2ce configure.ac (Christian Persch 2018-03-05 21:58:12 +0100 3) m4_define([version_micro],0) 16427 16428 従って 1;5300;0 から 65;5300;1 に移行したという事。 16429 16430 * 他の端末についても確認してみると konsole は 0;115;0 に固定である。 16431 (src/Vt102Emulation.cpp Vt102Emulation::reportSecondaryAttributes) 16432 16433 2021-06-18 16434 16435 * 2021-02-05 canvas: 絵文字シーケンスや grapheme cluster (motivated by huresche) [#D1619] 16436 16437 今まで対応は不可能と思って割り切って考えてきたが実は可能なのではないかとい 16438 う気がしてきた。ゼロ幅の文字が存在しても特に変な事は発生しない気がする。注 16439 意しなければならない事としては dirty 範囲を広げなければならないという事と、 16440 文字の途中で SGR 等を挿入したりする事はできないという事。 16441 16442 一方で端末の側でもこれに対応している必要があるのでテストという観点からは微 16443 妙。contra は対応していないし screen も恐らく対応していない。tmux はどうな 16444 のだろうか。 16445 16446 tmux はこれに対応しているターミナルがないから未だ対応しないという事を言って 16447 いる。一番最近では 2020-05 https://github.com/tmux/tmux/issues/1605 16448 16449 2021-05-30 書記素で動かないという話が来た。 16450 https://github.com/akinomyoga/ble.sh/issues/117 16451 16452 というか逆に動くアプリケーションは一体どれ程あるというのだろうか。振る舞い 16453 を調べてみると、bash は ハート+VS に関してはそれぞれ一文字と解釈している事 16454 によってたまたま良い感じに振る舞っている。 16455 16456 a 対応方法の一つは grapheme cluster を一つの私用文字に置き換えて取り扱う方法。 16457 この方法を取ればカーソル移動や文字の削除等は自然にできる様になる。 16458 16459 後は入力時と出力時に変換を実行すれば良い。入力時に関しては文字挿入時に変 16460 換を実行すれば良い。出力時 (コマンド実行時) には逆方向に変換すれば良い。 16461 入力時に関しては ble-edit/content/reset で変換を行えば良いのではないかと 16462 いう気がする。 16463 16464 問題は履歴検索である様な気がする。検索する時には文字列を変換してから検索 16465 する必要がある。その時にカーソル位置なども変換しなければならない。更に、 16466 検索して一致が見つかった時にまたカーソル位置を復元する必要がある。 16467 16468 ? 此処で問題になるのが検索に於いて書記素の部分的な一致を許すのかという事。 16469 本来の文字列に復元して検索するとすると中途半端な位置で一致する事になる 16470 気がする。 16471 16472 * 或いは逆に履歴の方を変換して保持するという手もあるだろうか。然し、その 16473 時に問題になるのは履歴の全項目について変換を実行しなければならないので 16474 重いという事。更に awk で処理するにしても私用文字と書記素クラスタとの対 16475 応表をどうやって bash と共有するのかという問題が生じる。 16476 16477 a 既に登録されている物に関してはその codepoint を利用したいし、まだ登録 16478 されていない物がある場合には新しい項目を bash に反映させる必要がある。 16479 この方法を採用すると可也面倒な処理が必要になる。 16480 16481 b 或いは、予め対応表を固定しておくというのも手であるが ZWJ sequence 等 16482 も考えると無限にある。ZWJ sequence は対応しないというのも手である。然 16483 し将来的な事を考えると中途半端な手法で無駄に複雑にはしたくない。 16484 16485 * vim のバイト数による移動に関しては注意が必要になる。私用領域の代替文字 16486 のバイト数で換算される事になる。この方法を採用した場合にはその程度の不 16487 都合については我慢する必要がある。 16488 16489 b また別の対応方法は emoji sequence をそのまま文字列として保持して、textmap 16490 やカーソル移動、一文字削除 etc の側で正しく処理するという事。然し、エラー 16491 着色なども考えると中途半端な箇所で SGR を挟む訳にも行かないので着色や構文 16492 解析のレベルでも grapheme cluster を意識する必要が出てくる。 16493 16494 * 全ての widget について注意深く grapheme clusters に対応する必要がある。 16495 カーソル移動、一文字削除、etc. 然し、これらに関しては実は codepoint 単 16496 位の操作になってもまあ許せるのではないだろうか。 16497 16498 ? readline について: 然し、readline は上手にその辺りを処理できている様 16499 にも見える。ただ、これは OS の mb 実装が上手に面倒を見てくれているの 16500 だという見方もできる。恐らく "一文字進む" とかそう言った処理を行う時 16501 に grapheme cluster 単位で処理してくれているという事なのではあるまい 16502 か。 16503 16504 然し、そうすると "一文字を表現するのに要するバイト数" の過程に狂いが 16505 生じるのではないかという気もする。その辺りがどうなっているのかは気に 16506 なる所である。 16507 16508 Readline が Unicode の要求通りの動作を実行できているという事を考えると 16509 codepoint 単位の操作というのは余り良くないかもしれない。一方で zsh はそ 16510 の辺りを適当に処理する事ができている様な気もする。 16511 16512 * 再描画に際しては dirty range の端点が書記素クラスタの内部の中途半端な位 16513 置に発生すると厄介な事になるので拡張する必要がある。 16514 16515 * コマンド実行や履歴検索に関しては特に細かい事を気にする必要はない。然し、 16516 カーソル位置の設定に関しては依然として注意が必要である。 16517 16518 * カーソル移動について。 16519 16520 a 移動する度に位置を cluster boundary に調整する必要があるのではないか。 16521 16522 x よく考えたら、調整するにしてもどちらの端に調整するのかという問題が 16523 ある。例えば、左から右に一文字進んでそれが cluter の内部にある時に、 16524 また左端に調整してしまうとカーソルを移動する事ができなくなってしまう。 16525 16526 b 或いはカーソル移動をする時には (例えば文字数で)、一文字ずつ進んでいか 16527 ないと cluster を認識した移動にはならない。 16528 16529 c 調整する方向を前にいた位置を参考にして決めるという実装も可能かもしれ 16530 ないがその様な ad hoc な方法で自然な動作になるのかは不明である。 16531 16532 d そもそも調整する必要があるのかという話。カーソル移動は文字単位で良い 16533 のではないか。しかしそうすると書記素の真ん中に文字を新しく挿入した時 16534 の処理が非自明になる。取り敢えず textmap の配置再計算に際しては前後の 16535 cluster 境界まで dirty range を拡張して処理する必要がある。その他の構 16536 文解析などの dirty range も同様である。という事を考えれば dirty range 16537 拡張は別に textmap で行う必要はなくて、reset の段階で実行しておけば良 16538 い。 16539 16540 うーん。この手法で行くとしたら d の方針が現実的である。カーソル移動の文 16541 字を書記素単位に変更するのはあらゆる所に影響が出るので大変である。 16542 16543 * textmap に於いて grapheme cluster をどの様に取り扱うのかというのは非自 16544 明である。先ず dirty range を grapheme cluster boundary にまで拡張する。 16545 その上で grapheme cluster の2文字目以降には0幅を割り当てる。といった具 16546 合になるのだろうか。座標から文字を特定しようとした時にどのような振る舞 16547 いになるのかも非自明である。 16548 16549 着色に関しても textmap に於いて土台の文字の方に全て記録する様にして、0 16550 幅になった物には空文字列を設定する事にすれば問題は発生しなくなる。其処 16551 まで考えていくと実は構文解析ですら中途半端になっても大丈夫なのではない 16552 だろうか。つまり textmap に対する修正だけで全部行ける? 16553 16554 残る問題はゼロ幅の文字があっても座標決定等で無限ループなどにならないか 16555 という事。 16556 16557 [実装] 16558 16559 grapheme clusters について真面目に考える前に UAX を改めてまとめるのが先の気 16560 がする。UAX は最初から順に読んでいったが実のところ重要なのは 3.1.1 だけだっ 16561 た。他は全て御託である。 16562 16563 * done: Grapheme_Cluster_Break 表の作成 16564 16565 さて、実装するに当たって一番最初にする必要があるのは、 16566 Grapheme_Cluster_Break プロパティの表を入手するという事。 16567 http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakProperty.txt 16568 にあるそうだ。これを加工して使える様にする。加工するスクリプトは何処に置 16569 くのが良いだろうか。emoji_version の時にはどうしたろうかと思って 3f6c9b9 16570 を確認したがテーブルの生成に使ったスクリプトは見当たらない。 16571 git@github.com:akinomyoga/unidata にも何もなかった。と思ったが 16572 emoji_version の開発 commit は d1f8c27 だった。そして生成スクリプトは 16573 make_command.sh の update-emoji-database にあった。./make_command.sh のリ 16574 ストの一番下にあった所為か見逃していた。 16575 16576 どの様な表現にするのが最も良いだろうか。単一のコードポイントで或る 16577 Grapheme_Cluster_Break を持っている時には単に配列に格納するのが良い気がす 16578 る。それ以外の範囲で値を持っている物に関してはどの様にするのが良いだろう 16579 か。何しろ様々な値を取る可能性があるので、単に境界を並べた配列から検索す 16580 るだけでは済まない。一つの方法は、範囲の先頭については直接配列に値を入れ 16581 る事にする。二分探索で範囲の先頭を求めて、その後で配列を参照して値を取り 16582 出す。というのが良い気がする。取り敢えずどの様な分布になっているのかを確 16583 認する必要がある気がする。 16584 16585 * 孤立 Property は 664 個存在した。更に範囲先頭も含める。範囲は 487 である。 16586 配列項目の数は 664+487*2 = 1618 になる。 16587 16588 因みに二個連続迄を孤立と見做す事にすると 980 個の孤立があり、範囲は 304 16589 にまで減少する。配列項目の数は 980 + 304*2 = 1588 になる。 16590 16591 3個連続迄直接登録にすると 1157 個の直接登録と、239 の範囲登録がある。配 16592 列項目の数は 1157+239*2 = 1635 になり大きさが多少増える。4個の時は 16593 1321/191 になり、配列の大きさは 1703 になり益々増える。5個の時は、 16594 1426/173/1772。10個にすると 2067/80/2217 という具合に増えていく。例えば 16595 配列項目を最小の2倍まで許すとすると、実は可也の物を直接登録しても良いの 16596 ではないかという気がしてくる。50にしたら15818/18なので駄目。30でも 16597 14291/33なので駄目。20にしたら2676/45 なので丁度よいぐらい。 16598 16599 然しまあ速度をそんなに重視しても仕方がない気がする。取り敢えず最小であ 16600 る 2 個連続までを直接登録する事にする。 16601 16602 * \p{Extended_Pictographic} に対する判定も追加しなければならない。という 16603 か\p{Extended_Pictographic} は Grapheme_Cluster_Break の細分になってい 16604 るのだろうか。つまり、全て Other だと良い。Extended_Pictographic が変な 16605 性質を持っているとは思い難い。何か持っているとしても Regional_Indicator 16606 程度であると期待したい。 16607 16608 うーん。Extended_Pictographic 属性は emoji-data.txt に含まれている様だ。 16609 これも emoji version 毎に管理するべきなのだろうか。取り敢えずの実装とし 16610 ては最新版を使う事にする。 16611 16612 調べた限りに於いては Extended_Pictographic は全て Other の様である。な 16613 ので何も気にしなくて良い。取り敢えず最初の boundary を特定するコードに 16614 ついては書いた。 16615 16616 * done: find-previous-boundary のテストも追加したい。 16617 16618 →テストを追加してみたところ見事にミスが見つかった。やはりテストをつけて 16619 よかった。然し、まあ結局はテストを追加したような気もする。更に 16620 find-previous に関してもテストを追加するべき気がする。テストを追加した。 16621 やはり色々ミスが見つかった。そもそもデータの生成にも誤りが見つかった。 16622 16623 * done: Unicode のページにテストケースが見つかった。沢山ある。これらを 16624 import する。行数が沢山あるので圧縮したい。→OKテストケースが 2000 行あっ 16625 たのを 100 行程度にまで小さくした。 16626 16627 またこれらのテストケースにより間違いも発見されたのでそれを後で修正する必 16628 要がある。 16629 16630 x 2件は CRLF の規則を変更した事による物。 16631 16632 x Pictographic Extend* ZWJ Pictographic で位置の決定に失敗している気がす 16633 る。ZWJ:Pictographic の処理に於いて local ret を宣言してしまっていた所 16634 為で戻り値が反映されなくなっていたのを修正した。 16635 16636 x 未だ問題が発生している。Extend を Extended と間違えていた。 16637 16638 x 他はハングルに対する規則が欠けていた。 16639 16640 OK これでテストも全て通る様になった。 16641 16642 * ok: 次の問題は如何にして効率的に文字幅を実装するかという事である。 16643 うーん。効率はさておいて取り敢えず実装する事にする? 16644 16645 Prepend さえ無ければ前の文字に付加していくだけで十分の筈である。絵文字で 16646 ない文字に Emoji_Modifier がついた時に文字の幅を変更するのかというのは謎 16647 である。更に Variation Selector によって幅が変化する場合についても考える 16648 必要がある。うーん。然し…Variation Selector で絵文字かそうかを切り替える 16649 という話ならば Variation Selector の値を見て幅を変更すれば良い。然しこれ 16650 は幅が遡って修正されるという事を意味する。やはり Grapheme_Cluster を特定 16651 して処理する必要があるのだろうか。然し、全ての文字について 16652 Grapheme_Cluster を特定して処理していたら面倒な事この上ない。ASCII だけに 16653 ついて処理をスキップすれば良いだろうか。日本語の文章についてはどうする? 16654 実は Other だけスキップする様にする事が可能だったりしないか? と思ったが、 16655 やはり Encoding に依存しない実装になっている限りは難しい様にも思われる。 16656 UTF-8 の時にだけ特別扱いするのも変な気がする。 16657 16658 やはり Grapheme cluster を特定して実装する必要があるだろうか。 16659 16660 * 最初の文字が非ASCIIの場合には Grapheme_cluster を特定して処理する。最初 16661 の要素に全ての文字を投入するというので良い気がするが、実は core の部分 16662 に指定しても良いのかもしれない。然し、カーソルを移動した後の操作などを 16663 考えるとやはり最初の要素に全ての文字を入れる様に実装しないと処理として 16664 一貫しない感じになる。因みにこの実装の時にはカーソル上下移動した直後に 16665 は、零幅文字の"後"に index を配置するべきである。 16666 16667 * ASCII文字の場合には最後の文字について Grapheme extension を計算すれば十 16668 分である。 16669 16670 処理を開始する境界の特定ができた暁にはこの手法が最も良い気がする。 16671 Grapheme cluster とその幅を計算する関数を実装してそれを呼び出す様にする。 16672 また、対応する文字列と codepoint の数も計算する様にする。xenl のない端末 16673 の場合に行末で Grapheme cluster を構築した時にどうなるかは謎。受信時に 16674 Grapheme cluster を構築してから挿入するタイプの端末ならちゃんとくっつく 16675 (然し timeout などで離れる)。前の行に何があるか見てくっつける実装でもくっ 16676 つく (その時行末が Folding とマークされている時に限りくっつく実装と関係な 16677 くくっつく実装とが存在しそうである)。何も考えていない端末だと離れてしまう。 16678 うーん。取り敢えずくっつくと思って実装しておくのが良い気がする。Grapheme 16679 cluster の対応まで考えたら端末は xenl にせざるを得ない気がする。 16680 16681 * reject: 使わないかもしれないが実装の確認の為に next boundary を実装するの 16682 が良い気がする→結局より高機能な match を定義したので next boundary を個 16683 別に実装する必要は全くなくなった。 16684 16685 * done: GraphemeClusterBreak/match という関数を実装 16686 16687 * done: textmap を最初に修正する。 16688 16689 * done: 取り敢えず非ASCII printable については実装した。 16690 16691 * done: 次は ASCII の末尾で extend する事について考える。 16692 16693 * done: variation selector について考慮に入れる。調べると U+FE0E が TPVS 16694 で FE0F が EPVS である。それぞれ非Emoji/Emojiの切り替えを行う。 16695 16696 取り敢えずはこれで良い気がする。動作確認を先ずは行う。 16697 16698 * 余談: Unicode は 11x64k の文字が原理的に存在する。bit で表現するとすれば 16699 88kB のデータサイズになる。50 の Property を考えるとすると 4.4MB のデータ 16700 サイズになる。小さいとは言えないがそれほど大きいとも言えない。然し、考え 16701 るに漢字などの領域は自明な値になっている筈なので容量は削減できる筈である。 16702 例えば、256文字ずつ組みにして考えるとすれば、最初のインデックスで選別すれ 16703 ば最低でも 1/10 程度には圧縮できるのではないだろうかという気がする。まあ、 16704 余り考えても仕方のない事かもしれないが。 16705 16706 * ok: 位置から文字を特定する関数をちゃんと修正する。特にその位置の最後の文 16707 字に移動する様に修正したい。 16708 16709 現在の ble/textmap#get-index-at の実装について確認する。基本的に f(l) <= 16710 x < f(u) を保つように範囲を狭めていっている。最終的に l と u の間隔が 1 16711 になる迄続ける。この時に l==u になる事はない。l と u は実の所境界に対応し 16712 ていて、f(u) は対応する文字開始位置を返す。 16713 16714 例えば今 A E E E B (A, B は幅 1 で E は幅 0) という具合になっていて位置 1 16715 に対応する index を見つけようとすると… u=4 l=5 しか条件を満たす位置は存 16716 在しない。つまり、期待通りに Extend の後の位置が求められる筈。 16717 16718 これについてはテストでも作成して確認するのが良い気がする。 16719 →OK ちゃんと動いている。 16720 16721 * ok: Emoji sequence を grapheme cluster とは別に処理する必要があるか 16722 16723 Emoji sequences に関してはまた別に表を保持して合成する等しなければならな 16724 い。Emoji sequence は incremental だろうか。つまり ABC が Emoji sequence 16725 であれば AB も Emoji sequence だろうか。まあ、それらの差異については気に 16726 しなくて良いというか、一般にはそうではないとした実装にしておくのが安全な 16727 気がする。何れにしても Emoji sequence の表の形式を考えておく必要がある気 16728 がする。 16729 16730 Emoji_modifier については Grapheme cluster の考慮に入っているのだろうか。 16731 →確認した所、ちゃんと考慮に入っていた。うーん。然し…普通の半角文字に対 16732 して Emoji_Modifier が適用されていたりする場合には一体どういう事になるの 16733 だろうか。気になる。 16734 16735 実は定義済みの Emoji seuquences は全部 Emoji_Modifer による実装で、既に 16736 Grapheme cluster に組み込まれているのではないかという気がしてきた。これに 16737 ついてはまた後で確認する事にする。 16738 16739 定義済みの Emoji sequence について2文字目以降の文字種について確認する。 16740 16741 $ for code in $(awk 'sub(/;.*/,"") {$1="";print}' out/data/unicode-emoji-14.0.txt | 16742 grep -Eo '\b[[:xdigit:]]+\b' | sort -u); do 16743 ble/unicode/GraphemeCluster/c2break $((16#$code)); echo $ret 16744 done | sort -u 16745 12 .. Emoji 16746 2 .. ZWJ 16747 4 .. Extend 16748 6 .. RI 16749 16750 うーん。これだけだと Emoji が ZWJ で接続されているのかそうでないのかが分 16751 からない。やはりちゃんとスクリプトを書いて変換して確認する必要がある気が 16752 する。どう言った属性値のシーケンスが存在するのか確認する。以下の種類のシー 16753 ケンスが存在する。4 は単に無視して良い。1 1 1 1 というのは気になる…。他 16754 は全て Grapheme Cluster の形式をしている→これは単に凡例を拾っているだけ 16755 だった。 16756 16757 seq: 0 4 16758 seq: 0 4 4 16759 seq: 12 16760 seq: 12 2 12 16761 seq: 12 2 12 2 12 16762 seq: 12 2 12 2 12 2 12 16763 seq: 12 2 12 4 16764 seq: 12 2 12 4 2 12 16765 seq: 12 2 12 4 2 12 2 12 16766 seq: 12 4 16767 seq: 12 4 2 12 16768 seq: 12 4 2 12 2 12 2 12 4 16769 seq: 12 4 2 12 2 12 4 16770 seq: 12 4 2 12 4 16771 seq: 12 4 2 12 4 2 12 2 12 4 16772 seq: 12 4 2 12 4 2 12 4 16773 seq: 12 4 4 4 4 4 4 16774 seq: 4 16775 seq: 6 6 16776 16777 という訳で孤立した Extend を除き全て grapheme cluster である。なので 16778 emoji sequence については grapheme cluster に加えて気にする必要はない。 16779 16780 * done: unqualified は既定では Emoji presentation ではなく Text presentation にする 16781 16782 kitty で動作確認した所、文字によって既定で text presentation か emoji 16783 presentation かがまちまちの様である。うーん。どの様にするのが良いか。。 16784 EPVS で初めて絵文字になる物に関しては実は単に "絵文字ではない" という事に 16785 して良い気がする。現在の設定ではユーザーが個別に絵文字か絵文字でないか指 16786 定できるような設計になっていただろうか。 16787 16788 というよりそもそも問題の U+2660 が既定で text か emoji かというのが規格化 16789 されていたりはしないのだろうか。emoji のデータベースを確認すると 16790 fully-qualified, unqualified 等というのがある様だ。 16791 16792 うーん。端末を確認してみた所、絵文字にまともに対応しているのは kitty/vte 16793 系列の様であるからこれの動作に倣う事にした。他の端末の動作に関しては追々 16794 対応していく事にする。そして kitty/vte では unqualified は絵文字ではない 16795 様なのでそれに倣う事にする。 16796 16797 * done: trace-text の実装。 16798 16799 * done: trace の実装。 16800 16801 うーん。lc は困る。基底文字だけを指定すると lc によって装飾が全て消えてし 16802 まう。一方で、一番最後の文字を指定したとしても、端末によっては連続してい 16803 ない出力に関しては前の基底文字を削除してしまうかもしれないし、またそうで 16804 なかったとしても Extend が余分に追加されてしまう事になる。なので、書記素 16805 クラスター全体を出力し直さなければならない筈だが lc (整数値) では表現でき 16806 ない。 16807 16808 これに本当に対応しようと思ったら lc lg の組ではなくて lcs lw lg の組に拡 16809 張するしかない。然し、そもそも lc lg は現在ではデバグ用としてしか意味を為 16810 さないので其処までちゃんと対応する労力を割く必要があるかというと、ない。 16811 一応項目として残しておく事にする。 16812 16813 * done: 制御文字を ^X 等の形に変換するのは GraphemeClusterBreak/match の側 16814 でやった方が良い気がする。然し本当にそうだろうか。これから match を 16815 trace, trace-text でも共有しようと考えている。trace, trace-text での実装 16816 をしてから制御文字を変換するかどうか判断するという方が良い。 16817 16818 * done: 零幅文字: 完全に零幅の単一文字 (Control Character) に関してはやはり 16819 ASCII rep で置き換えるべきの様に思われる。これについてはまた別項目で取り 16820 扱うべきなのだろう。core の欠けている Extend chars に関しては台字として 16821 space か或いは専用の○が存在した気がする。 16822 16823 trace に於いては直接出力したい。なので取り敢えず Unicode 制御文字について 16824 はゼロ幅で出力する事にする。 16825 16826 * ok: 関数名を再考。GraphemeClusterBreak はプロパティ名である。それよりは 16827 ble/unicode/GraphemeCluster/* の形で様々の機能を提供するべきではないか。 16828 もしくは ble/unicode/grapheme-cluster/*. うーん。変数名等を考えると 16829 ble/unicode/GraphemeCluster/* の方が良い気がする。変数名も一緒に考え直す 16830 と良い。 16831 16832 ある程度置き換えたがまた後で改めて考える。特に変数名を 16833 GraphemeClusterBreak のままにするか GraphemeCluster_Break と分けるか。うー 16834 ん。分けずに今のままで良い気がする。 16835 16836 [修正] 16837 16838 * done: kitty は fully-qualified, minimally-qualified, component については 16839 肌の色は幅0で髪については幅2にしている様だ。実際の Unicode の例を見ても髪 16840 は単一の文字で肌の色は Extend の様に見える。 16841 16842 * done: screen, mlterm, terminology 辺りは unqualified も参照している気がす 16843 る。unqualified のテーブルも作るか、或いは、現在のテーブルを拡張して 16844 qualified, unqualified の区別もできる様にするか。うーん。下手にメモリ使用 16845 量が増えるのも否なので一つの配列で qualified/unqualified の両方に対応でき 16846 る様にするのが良い気がする。序に skin/hair の区別もできる様にする? 16847 16848 もし unqualified も判定できる様にしようと思ったら現在の実装を変更する必要 16849 がある。現在は境界に +1 をして行って、奇数の値を持つ境界のみを抜き出す事 16850 によって emoji の範囲を取得している。然し、複数の種類の要素を区別する為に 16851 は、同じ方法は使えない。うーん。種類毎に bit を用意して xor して行けば、 16852 境界はちゃんと抜き出す事ができる。然し問題はそれが始まりの境界なのかそれ 16853 とも終わりの境界なのかを判定する事ができないという事にある。という事を考 16854 えると、始まりである事を表す marker も作った方が良いのでは。うーん。その 16855 様な事をするぐらいであれば、普通に始まりと終わりの bit を用意しておけば良 16856 いだけの気がする。 16857 16858 うーん。始まりを設定する時にその属性値を別の配列に記録する事にするという 16859 事。また、境界を検知する為には xor で記録するという事。より良い方法はある 16860 だろうか。単に前回の属性値を覚えておいてそれと同じかどうかを確認するだけ 16861 で良いのではないか。終端に関しては何も記録しない。 16862 16863 unqualified にも対応して取り敢えず試した全ての端末で絵文字の幅計算が一致 16864 する様になった。 16865 16866 * 0x1F3FB..0x1F3FF や 0x1F202, 0x1F237 は振る舞いが異なる実装が多い。実は古 16867 い Unicode では属性が違ったという事だろうか。確認する必要がある気がする。 16868 と思って unicode.org からファイルを持って来ようとしたがどうも unicode.org 16869 が停止している。 16870 16871 Internet Archive から GraphemeCluster について各 version をダウンロードし 16872 て diff して見ると破壊的変更がない訳ではない様だ。 16873 16874 Unicode 6.0.0 で以下の属性が削除されている (別の属性が割り当てられた可能性もあるが確かめていない) 16875 -06DE ; Extend # Me ARABIC START OF RUB EL HIZB 16876 -0E30 ; Extend # Lo THAI CHARACTER SARA A 16877 -0E32..0E33 ; Extend # Lo [2] THAI CHARACTER SARA AA..THAI CHARACTER SARA AM 16878 -0E45 ; Extend # Lo THAI CHARACTER LAKKHANGYAO 16879 -0EB0 ; Extend # Lo LAO VOWEL SIGN A 16880 -0EB2..0EB3 ; Extend # Lo [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM 16881 16882 うーん。見た感じ結構書き換わっている。やはり各 version について対応するべ 16883 きか。取り敢えず問題の 1F3FB が各 version でどうなっているか確認する。ど 16884 うやら 1F3FB は 9.0 で E_Modifier として導入されて 11.0 で Extend に変更 16885 になった様である。うーん。これは当時の規則を参照する必要があるのだろうか。 16886 16887 1F202,1F237 に関しては GraphemeCluster 的には特に何もないようである。これ 16888 は Emoji の規格の側の取り扱いの変化だろうか。うーん。規格の各 version の 16889 記述を観察してみたが、1F202 は最初から一貫して unqualified である。もっと 16890 ちゃんと書くと 4.0 ではそもそもリストに載っていない。5.0 では 16891 non-fully-qualified という名前。12.0 から unqualified という名前に変更さ 16892 れた。という事は単に OS の locale の wcwidth が変な値を返しているという事 16893 なのだろうという気がする。 16894 16895 実の所、1F3FB の振る舞いに関しても OS の wcwidth が怪しいのではないかとい 16896 う気もしてくる。 16897 16898 wcwidth (C.UTF-8) の振る舞いを確認すると 1F202,1F237 は 2 を返している。 16899 1F3FB..1F3FF も 2 を返している。これらが変な風に振る舞う原因なのだろうか。 16900 16901 * done: urxvt についても確認する 16902 * done: mintty についても確認する 16903 16904 * fixed: 2021-06-21 複数行編集でプロンプトの末尾が消去される? rprompt 関連の可能性 16905 16906 →これは grapheme cluster の対応によって発生する様になった問題の様だ。つま 16907 り何らかの文字列の幅計算に失敗しているという事になる。然し、プロンプト自体 16908 は ASCII だけで構成されている筈で幅計算に問題が発生するというのも不思議であ 16909 る。或いは、一緒に変更した別の部分が問題の原因になっているのかもしれない。 16910 16911 もしかして改行が ^J の幅である 2 で計算されている可能性? だとすると rps1 や 16912 status_line は関係なくどの行でも2文字ずつ内容が削られてしまう筈である。実際 16913 に試してみた所、確かに rps1 や status_line がなくても問題が発生する。更にど 16914 の行も次の行に行く瞬間に2文字右にずれて表示されて、更に次の行の内容を入力し 16915 ようとすると左に2文字ずれて再描画される。何れにしても2文字のずれが生じてい 16916 るのは確かである。 16917 16918 textmap の問題である事を確認した。開業直後の x の位置が 2 になっている。 16919 16920 * UAX 11 を再確認した所、何と combining marks や nonspacing characters に関 16921 しては実は実際の幅に関係なく言語に応じて N, Na, W 等が割り当てられるとい 16922 う。なので、素直に UAX11 の表だけで文字幅を決定するのは危険という事である。 16923 16924 取り敢えず grapheme clusters の中に於いて combining や nonspacing につい 16925 てもちゃんと文字幅を計算できる様にしたい。その為に c2w は 16926 combining/nonspacing に対して 0 を返す様に変更したい。基本の文字幅テーブ 16927 ルも他の物と同様に実装したい。と思ったが最初に下8bitを落としたテーブルで 16928 判定するのが妥当の気がする。SMP に関しては全体に対して適用するという事に 16929 する。 16930 16931 | うーん。取り敢えず wcwidth が返す結果を再現するのが一つの方法の気がする。 16932 | General Category と UAX11 の組み合わせで再現できるだろうか。取り敢えず 16933 | GeneralCategory のテーブルを作成してみたが、可也サイズが大きい。然し、個 16934 | 別に属性を切り出すよりは良い気がするので取り敢えずこれで色々調べてみるの 16935 | が良い気がする。というか、実際には c2w のテーブルさえ持っていれば良いので、 16936 | 最終的にはこの GeneralCategory のテーブルは ble.sh には含めなくても良いの 16937 | かもしれない。 16938 | 16939 | さて、それぞれの category について見ていく。Mn は nonspacing mark, Mc は 16940 | spacing combining mark (??), Me は mark enclosing である。Cc は制御文字で 16941 | Cf は hyphen, ZWJ, ZWNJ 等色々。Cs は surrogate で Co は私用領域。Cn は未 16942 | 使用・予約文字。この中で特別な値を割り当てる必要があるのは Mn, Cc 及び一 16943 | 部の Cf だろうと思われる。Me は一体何だろうか。うーん。grep で見てみると 16944 | これらも combining の様である。Mc も combining の様な気がする。 16945 | 16946 | 0488;COMBINING CYRILLIC HUNDRED THOUSANDS SIGN;Me;0;NSM;;;;;N;;;;; 16947 | 0489;COMBINING CYRILLIC MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; 16948 | 1ABE;COMBINING PARENTHESES OVERLAY;Me;0;NSM;;;;;N;;;;; 16949 | 20DD;COMBINING ENCLOSING CIRCLE;Me;0;NSM;;;;;N;ENCLOSING CIRCLE;;;; 16950 | 20DE;COMBINING ENCLOSING SQUARE;Me;0;NSM;;;;;N;ENCLOSING SQUARE;;;; 16951 | 20DF;COMBINING ENCLOSING DIAMOND;Me;0;NSM;;;;;N;ENCLOSING DIAMOND;;;; 16952 | 20E0;COMBINING ENCLOSING CIRCLE BACKSLASH;Me;0;NSM;;;;;N;ENCLOSING CIRCLE SLASH;;;; 16953 | 20E2;COMBINING ENCLOSING SCREEN;Me;0;NSM;;;;;N;;;;; 16954 | 20E3;COMBINING ENCLOSING KEYCAP;Me;0;NSM;;;;;N;;;;; 16955 | 20E4;COMBINING ENCLOSING UPWARD POINTING TRIANGLE;Me;0;NSM;;;;;N;;;;; 16956 | A670;COMBINING CYRILLIC TEN MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; 16957 | A671;COMBINING CYRILLIC HUNDRED MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; 16958 | A672;COMBINING CYRILLIC THOUSAND MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; 16959 | 16960 | そうすると Mn/Mc/Me は全て combining として幅0にする? うーん。SpacingMark 16961 | を確認してみるとどうも Mc になっている。うーん。という事は Mc については 16962 | EAW による幅をそのまま与えるべきだろうか。分からないので wcwidth の結果に 16963 | 従うというので良い様な気もする。という事は何れにしても wcwidth を自前で再 16964 | 現するという試みが必要である。 16965 | 16966 | うーん。EastAsianWidth を確認してみた所、実は既に此処に General Category 16967 | も附記されている。単にこれを元にして幅を決定すれば良いだけなのでは? 16968 | EastAsianWidth 及び General Category を元にして求めた比較を実装した。 16969 | Mn|Me|Cf を幅 1 にして Unicode 11.0 を使うと最も差分が小さくなる。然しそ 16970 | れでも Cf に関しては wcwidth は 0 だったり 1 だったりまちまちの結果を返す 16971 | 様である。 16972 | 16973 | 2021-09-14 取り敢えず文字幅に関してはちゃんと決着を付けなければならない。 16974 | 改めて現状について確認する。GenCat 及び EAW を元にした幅は 16975 | out/data/c2w.eaw-*.txt に出力してある。このデータは range で出力している 16976 | ので、それぞれどの文字についてずれが発生しているのかは確認しにくい事に注 16977 | 意する。 16978 | 16979 | 先ずは違いを分かりやすく取り出す様に修正しなければならない。うーん。ずれ 16980 | のある各文字について GenCat や文字の名前について確認したいという事を考え 16981 | ると、C++ から EAW のデータを読んで処理する方が良いのだろうか。 16982 | 16983 | 取り敢えず時間を区切って実装することにするのが良い。先ずは形式を確認する。 16984 | 16985 | % * Co については -1 の時と 1 の時がある。 16986 | % 16987 | % 調べてみると wcwidth が 1 を返すのは以下の領域のみである。 16988 | % これらに文字が割り当てられているとは思えないが… 16989 | % 16990 | % e000..f8ff wcwidth=1 width(eaw=3 gencat=Co)=-1 16991 | % f0000..ffffd wcwidth=1 width(eaw=3 gencat=Co)=-1 16992 | % 100000..10fffd wcwidth=1 width(eaw=3 gencat=Co)=-1 16993 | % 16994 | % →と思ったが unassigned に誤って Co を割り当てていたのが駄目だった。 16995 | % unassigned に対して Cn を指定して Cn に対して -1 を返す様にしたら、 16996 | % 残る Co は上の領域だけでしかも全て A であり、これは cjkwidth west と 16997 | % 一貫している。 16998 | % 16999 | % * wcwidth は EAW=W の領域の Co に対しても -1 を返す。なので、-1 を単純に 17000 | % 1 にすれば良いという訳でもない。 17001 | 17002 | * Cc に関しては NUL 以外は wcwidth で -1 になる。 17003 | ble.sh では NUL は取り扱えないのでこのずれは無視して良い気がする。 17004 | 17005 | 0000 wcwidth=0 width(eaw=1,gencat=Cc)=-1 17006 | 17007 | * Cf については wcwidth は殆ど 0 を返すが一部の物について 1 を返す。 17008 | 17009 | 00ad wcwidth=1 width(eaw=3,gencat=Cf)=0 SHY(soft-hyphen) 17010 | 0600..0605 wcwidth=1 width(eaw=1,gencat=Cf)=0 アラブの数字らしい。何故Cfなのかは謎 17011 | 06dd wcwidth=1 width(eaw=1,gencat=Cf)=0 ARABIC END OF AYAH (アラビア語?) 17012 | 070f wcwidth=1 width(eaw=1,gencat=Cf)=0 SYRIAC ABBREVIATION MARK (シリア短縮記号?) 17013 | 08e2 wcwidth=1 width(eaw=1,gencat=Cf)=0 ARABIC DISPUTED END OF AYAH (アラビア語) 17014 | 110bd wcwidth=1 width(eaw=1,gencat=Cf)=0 KAITHI NUMBER SIGN 17015 | 110cd wcwidth=1 width(eaw=1,gencat=Cf)=0 KAITHI NUMBER SIGN ABOVE 17016 | 17017 | うーん。これらは emoji とは関係ない気がする。ので、emoji 関係の 17018 | property を参照しても仕方がない気がする。個別に設定するしかないのだろうか。 17019 | 17020 | * Lo は以下の範囲のみ wcwidth が予測と異なる物になっている。 17021 | 17022 | 1160..11ff wcwidth=0 width(eaw=1,gencat=Lo)=1 ハングル字母 17023 | 3248..324f wcwidth=2 width(eaw=3,gencat=No)=1 囲み文字10-80 17024 | 4dc0..4dff wcwidth=2 width(eaw=1,gencat=So)=1 易経記号 17025 | 17026 | うーん。一体誰が wcwidth のデータベースを作っているのかは謎だが…。 17027 | 17028 | 取り敢えず Fedora の wcwidth に合わせる形で実装することにして将来的に不都 17029 | 合があればその時に改めて環境依存性について考える事にする。また、将来的に 17030 | 別の環境の locale でも wcwidth の振る舞いを調べる必要が生じた時の為に、 17031 | これに使ったコードも残しておく事にする。 17032 17033 → #D1645 にまとめ直した。 17034 17035 段々と大掛かりになって来たので一旦現状で commit を作っておくべきな気がした。 17036 現在の状態は幾つか未だ課題があるものの中途半端な状態という訳でもない。課題 17037 についてまとめて別の項目で議論するべき気がする。 17038 17039 [残っている課題] 別項目で議論 17040 17041 * #T0008 SpacingMark, Prepend は grapheme cluster の修飾でありながらそれ自 17042 体が幅を持つ。つまり、grapheme cluster の幅を拡張する。従って、grapheme 17043 cluster の Extend についても width を grapheme cluster の幅の計算に加算す 17044 る必要がある。その為には c2w をちゃんと設計する必要がある。具体的には幅 0 17045 の Extend に対してはちゃんと 0 を返す様にする必要がある。 17046 17047 * #D1645 上の為に c2w をちゃんと再設計する必要がある 17048 17049 2021-06-13 17050 17051 * 2021-06-06 complete: auto-menu の振る舞いの調整 [#D1618] 17052 17053 * ok: auto_menu に於いては empty_completion の抑制もするべき。というか一般 17054 に auto に対して抑制するべきの気がする。と思ったが、実際に実装を確認する 17055 と既にその様な実装になっていた。no-empty opts を指定していた。 17056 17057 * reject: うーん。auto-menu を既定で on にする事も考えたがこれは流石にうる 17058 さい様な気がする。やはり好き嫌いが出るだろうから既定で on にするのは避け 17059 た方が良い様に思われる。然し、on にした時にはできるだけ自然な動作になる様 17060 に努めたい。 17061 17062 * complete_limit_auto_menu? 17063 17064 導入した。然し、complete_limit_auto_menu を導入すると複数の source から候 17065 補を生成した時に一部の source からの結果だけ抽出してしまう。その時点では 17066 それで良いかもしれないが menu-filter が走ると直ぐに候補の数が少なくなって 17067 候補がなくなってしまう。此処で改めて候補を生成したい所だが、 17068 17069 a complete_limit に引っかかったら全体をキャンセルして中途半端な候補による 17070 menu は表示しない。 17071 17072 b (no items) になったら改めて候補を再生成する。然し、これは何処に実装する 17073 べきだろうか。実装するとしたら menu-filter.idle の気がする。然し、その 17074 menu がどの様に start したかによって振る舞いを変えるべきではないか。例 17075 えばユーザーが明示的に source を指定して候補を生成した場合には勝手に再 17076 生成すると元々のユーザーの与えた絞り込みが消えてしまう。 17077 17078 或いは候補の生成に要した設定を何処かに記録しておいて同じ設定で補完を開 17079 始するという事。入力内容が増えた事によって絞り込み候補が少なくなったり 17080 して曖昧補完に移行するなどの事が考えられる。 17081 17082 同様に menu-filter.idle の開始点よりも前に移動した場合も候補を再生成する 17083 べきなのではないだろうか。 17084 17085 * 2021-06-10 prompt: [最適化] 単純なプロンプト内容は ${PS1@P} で展開? [#D1617] 17086 17087 プロンプトが単純な内容しか含んでいない時には ${PS@P} で計算を省略できるので 17088 はないか。つまり、\X で特別な物を含んでいない限りは bashに任せる事ができる。 17089 (一方で \w の追跡などについては個別に判定する必要がある気もする。) 17090 17091 然しそんなに速度向上には寄与しないのではないかという気もする。結局 trace は 17092 しなければならないからである。 17093 17094 取り敢えず PS1 が単純化どうかの判定をどうするか。\ の後に "安全" でない文字 17095 が続いている物は全て除外するのが良い様に思われる。"安全" な文字を列挙する。 17096 17097 - 0-7aenrdtAT@DhHjlsuvV[]!$\ 17098 - wW ... これらには add-hash を付加したい様に思われる。 17099 - # ... これは駄目。ble.sh 的には内部の bash の番号をちゃんと更新できていない。 17100 17101 意外と簡単に実装できた。動いている。\# も大丈夫。\w の更新も大丈夫。 17102 17103 * 2021-06-06 prompt: エラーはまとめて出力するべき? [#D1616] 17104 17105 現在の実装だとエラーを直接その場に出力する仕組みになっている。然しそうでは 17106 なくて、例えば新しい行を表示する直前等にエラーメッセージを出力するべきの気 17107 がする。その場合にはプロンプトの類を一旦仕舞うなどの工夫が必要である。或い 17108 は、trace 等で計測して出力する事になる。trace で計測したとしても画面の範囲 17109 よりも大きい場合には表示しきれないという事等色々考えるとプロンプトの類を一 17110 旦仕舞うのが妥当な気がする。 17111 17112 特にプロンプトに関連するエラーはプロンプトの表示直前にまとめて表示するのが 17113 良いのではないか。と思ったが、プロンプトの部分更新でもエラーは発生する。と 17114 いう事など考えていくと微妙。というかプロンプトの処理に関しては、 17115 visible-bell で良いのではないかという気がする。 17116 17117 というかそもそもエラーメッセージを表示する意味はあるのだろうか。認識してい 17118 なかったら単純に \q{...} のまま出力すれば良いのではないか。うーん。取り敢え 17119 ずは \q{...} の形でそのまま出力すると共に、visible-bell でも表示する事にし 17120 た。 17121 17122 2021-06-12 17123 17124 * benchmark: ble-measure が bash-4.4 未満で結果を返さなくなっている [#D1615] 17125 17126 これは local TIMEFORMAT= を指定したのが原因だった。 17127 TIMEFORMAT が unset の時には既定の結果になるが、 17128 TIMEFORMAT が空文字列の場合には既定の結果にはならないのだった。 17129 この際なので TIMEFORMAT に単純な文字列を指定して計測する事にした。 17130 17131 この問題は割合最近に埋め込んだ物の気がする。確かめてみる。bbc2a904 17132 src/benchmark.sh 2021-05-19 11:25:18 +0900 である。うーん。この commit は雑 17133 多の物をまとめた commit である。特に ble.pp のロード時間計測コードを 17134 TIMEFORMAT を使って見やすくした時にその序として benchmark.sh で TIMEFORMAT 17135 が書き換えられていた時の対策のコードをちゃんとテストせずに書き加えたのが原 17136 因であった。 17137 17138 * 2021-05-15 util: ^A, ^? を含む排列に関連するテストが失敗している [#D1614] 17139 17140 % ^A 及び ^? に対する declare -p 補正が動かなくなっている @ bash-3.2 17141 % 17142 % #D1522 に於いて bash-3.2 以下では配列表記で ^A が ^A^A^A^A になる事を発見 17143 % したと思ったが、何故か今手許で試してみると ^A^A にしかなっていなくて以前 17144 % のコードでも良かったという事になる。再現するための条件が何かあるのだろう 17145 % か。例えばスクリプト内部では declare -p の結果は ^A^A^A^A になるなど。 17146 % 17147 % うーん。ble/util/assign を介すと確かに ^A^A^A^A になるがそれは scalar も 17148 % array も同様になっている。然し、#D1522 で対処した問題は配列の時にのみ起こっ 17149 % ていた問題の筈なのでこれは関係ない。 17150 % 17151 % 関数内のみで起こる問題の可能性? と思ったがそれも変である。実際に ^A^A^A^A 17152 % にならず ^A^A になっているのは関数内で実行している時である。対話でも ^A^A 17153 % にしかならない。 17154 % 17155 % 元々は memo/D1522.large-array-passing.sh に於いて発生していた問題だった。 17156 % 今となっては writearray の実装を使う様に変更した為に再現していない。うー 17157 % ん。分からないので、取り敢えず改めて各 version での振る舞いを整理してそれ 17158 % で OK とする事にする。 17159 % 17160 % 以下が実際にスクリプトを書いて実行してみた結果。 17161 % 17162 % * bash-3.0, 3.2, 3.2 17163 % declare -- s="x^A^Ay^A^?z" 17164 % declare -a a='([0]="x^A^A^A^Ay" [1]="z^A^A^A^?w")' 17165 % * bash-4.0, 4.1, 4.2, 4.3 17166 % declare -- s="x^A^Ay^A^?z" 17167 % declare -a a='([0]="x^A^Ay" [1]="z^A^?w")' 17168 % * bash-4.4, 5.0, 5.1 17169 % declare -- s="x^Ay^?z" 17170 % declare -a a=([0]=$'x\001y' [1]=$'z\177w') 17171 % * bash-dev 17172 % declare -- s=$'x\001y\177z' 17173 % declare -a a=([0]=$'x\001y' [1]=$'z\177w') 17174 % 17175 % うーん。やっぱり二重にエスケープされている気がする。 17176 % 発生する条件があるのだろうか。 17177 % 17178 % a 関数の中で実行すると発生しなくなる? そういう訳でもない様だ。 17179 % b interactive session で実行すると発生しなくなる? →そうでもない 17180 % c ble.sh をろーどしていると発生しなくなる? →そうでもない 17181 % d サブシェルで実行すると発生しない? →そうでもない 17182 % 17183 % うーん。これは寧ろチェックコードの方の問題だろうか? 17184 % 17185 % a コピーに関しては問題ない 17186 % b 出力に関しては 17187 % c 比較対象の "正解" を生成する時に "正解" が化けている。 17188 % あー。これだった。修正した。というか正解はハードコードする事にした。 17189 17190 17191 結局問題は arr=(...) の形式でテスト用の配列を用意した時点で ^A や ^? が 17192 ^A^A や ^A^? に化けてしまっていた事にあった。それなのに、配列の中には ^A や 17193 ^? が正しく格納されているという前提で declare -p arr の結果だけに着目してい 17194 たのが混乱の原因だった。 17195 17196 * 何と $'\c?' は Bash-4.4 と 4.3 以下で振る舞いが違う様だ。最近書いた関連 17197 するコードを fixup した。 17198 17199 * 他にも類似の問題が生じている。これもテストの問題なのだろうか。 17200 17201 L1482 で発生している問題。うーん。これもやはりテストの側の問題だった。 17202 というかどうやったら正確にテストする事ができるのか? 17203 17204 色々試したが何だか変だ。これは出力する時の問題ではなくて、変数に代入する 17205 時の問題だろうか。特に配列に代入する時に発生する問題? 17206 17207 →うわー。やっぱりそうだった。という事は今 writearray でやっている処理は 17208 正しくない。writearray でやっている処理は arr=() で代入した事によって壊れ 17209 ている内容を正しい物に修正するという様な処理を行っている事になる。 17210 17211 17212 * done: writearray 修正 (^A^A^A^A 対策コード除去) 17213 * done: print-definitions 修正 (^A^A^A^A 対策コード除去) 17214 * done: print-definitions の出力で arr=() の形式を避ける。 17215 print-definitions はどの様に修正したら良いのか非自明である。というのも 17216 ^A 及び ^? を含む時にどの様な内容を出力しても arr=() の形式を使っている 17217 限りは正しい値を代入することができないからである。 17218 17219 取り敢えずこれについては修正した。OK 17220 17221 * 2021-05-15 test: BUG 失敗する様になっている [#D1613] 17222 17223 * quote-command の test に失敗している @ bash-4.3 直した 17224 17225 * ^A, ^? を含む排列に関連するテストが動かなくなっている → #D1614 17226 * ble-measure が bash-4.4 未満で結果を返さなくなっている → #D1615 17227 17228 これらについては別項目で処理する事にする。 17229 17230 * main: DEBUG version の bash で警告を表示する [#D1612] 17231 17232 relstatus が alp*|bet*|dev*|rc*|releng*|maint* の時にはロード時に "遅い" と 17233 いう事を警告するべきではないか。同時に wiki か README にも注意書きを書く必 17234 要はあるだろうか。 17235 17236 * complete: "complete -p" 解析の修正 + 細かい修正 [#D1611] 17237 17238 complete に対する細かい修正が溜まっているのでいい加減に push する。 17239 17240 * 一つは quote された progcomp が正しく unquote されずに続く complete -p 17241 の関数名抽出に渡っている問題の修正。 17242 17243 他は m scan に関連する軽微なミスである。 17244 17245 * local "${_ble_complete_cand_varnames[@]}" の localvar_inherit に対する対 17246 策が間違っている問題。 17247 17248 * 文字数を数えるのに ${#ret[0]} の形式を使ってしまっている問題 (bash-3.0 17249 bug) 17250 17251 * util: bleopt の unknown option の表示が空になる [#D1610] 17252 17253 bleopt で誤ったオプション名を指定した時のエラーメッセージでオプション名が空 17254 文字列になっている。 17255 17256 * prompt: \g{...} [#D1609] 17257 17258 将来的に Bash が \g に対応するとしても \g{...} の形になるとは限らないし、ま 17259 た、\g 単体であれば \g と \g{...} を区別する事によって処理を分ければ良い。 17260 偶々 \g の次に {...} を書きたいという事もそうあるまい。 17261 17262 * reject: idle: 時々自動的に表示更新をかけるべきではないか [#D1608] 17263 17264 裏で処理が走っている間に状態が変化してそれを表示に反映させたい時にはどうす 17265 るのか。現在の実装だとその様な仕組みにはなっていない筈。例えば 17266 textarea#invalidate を実行した時にその場で反映されるだろうか。 17267 17268 処理が一巡したら、もしくはn巡したら更新するのも良い気がする。否、時間を決め 17269 て置いてある程度時間が経ったら更新するというのでも良い。しかしそれならば、 17270 普通の task として n 秒置きに更新をかけるというので良い気がする。その様にし 17271 ておけば idle の他の処理が終わった後でも更新を確認し続ける様になるし自然な 17272 実装であるように思われる。 17273 17274 それとは別に idle 内部の動作によって表示を更新する必要があるのであれば、そ 17275 の動作を起こした側でその場で更新をかけるか或いは新しく task を投入するかす 17276 るべきなのである。 17277 17278 * util (bleopt): 遅延定義された設定項目の check [#D1607] 17279 17280 airline: ble-reload する時に状態が書き換わってしまっているのに bleopt 17281 vim_airline_theme=light の儘なので初期化が正しく為されない。うーん。既定値 17282 から再設定される筈なのだがそれも正しく処理されていない? と思ったがそれは 17283 ble.sh のロード時に処理される事なので遅延ロードされるモジュールの設定には当 17284 て嵌まらないという事。遅延ロードされる時にはその場で "設定" を再現する必要 17285 があるのではないか? 然し、そうすると関連する関数が既に定義済みでないと正し 17286 く動作しない事になる。或いは bleopt -I vim_airline_@ 的な関数を最後に呼び出 17287 して最初期化を強制するという可能性もある。 17288 17289 現在遅延定義される設定項目は恐らく vim_airline 及び vim_surround に限られる。 17290 complete, syntax は ble.sh に設定項目を定義しているので問題にならない。 17291 17292 * done: vim-airline で bleopt -I vim_airline_@ を実行する 17293 17294 * done: 他にも影響のある場所がないか確認する。特に bleopt/check: 17295 を定義しているオプションで、ble.pp の "bleopt -I" よりも後に実行 17296 される可能性のある物が対象である。 17297 17298 確認した所 core-syntax.sh で定義されている check:filename_ls_colors が怪 17299 しい。と思って実際に確認してみた所ちゃんと対策は為されていた。今回のこの 17300 対策を bleopt -I を使う物に置き換える事にする。 17301 17302 * ok: update wiki と思ったが、元々 bleopt はそんなに詳しく説明していなかっ 17303 た。bleopt -u も bleopt -r も wiki には説明が書かれていないので、bleopt 17304 -I について今すぐに追加しなければならないという事はない気がする。一方で、 17305 bleopt のもっと詳しい説明についてはいつか書かなければならない。 17306 17307 * prompt-git: bash 3 では async にできない→修正した [#D1606] 17308 17309 * history: cygwin に於いて arg_offset を処理していない気がするが大丈夫なのか [#D1605] 17310 17311 ble/builtin/history/.load-recent-entries から append:count=$delta という形 17312 で呼び出されている。Cygwin の時でも同様である。count により追加分だけが 17313 background で dump される様子である。arg_offset が使えない時には arg_count 17314 をクリアする等の工夫もされていない。つまり、Cygwin 上では正しく動かないとい 17315 う事? これを実装した時にどう考えていたのか後でログを確認する必要がある気が 17316 する。或いはもしかして何か ToDo に項目が残っていたりするだろうか。 17317 17318 * 現在の実装について記録を確認 17319 17320 うーん。何か ToDo に残っていないか探してみたが cygwin/Cygwin では引っかか 17321 らない。次に arg_offset を導入した時のログを確認してみる。 17322 17323 a 1bfc8ebe 2019-07-09 16:42:26 +0900 が怪しい。うーん。当時の記録を確認して 17324 みたが offset 等の実装の詳細に関する議論は全く残っていない。これは 17325 history.sh を導入した時の議論であって、恐らくこの時に現在の実装の様に 17326 history コマンドの模倣も実装してその過程で offset を導入した。 17327 17328 b と思ったが、その前の f204bc73 src/edit.sh 2019-06-27 20:38:34 +0900 の段 17329 階で既に arg_offset は導入されていた様である。一応 offset がどうのこうの 17330 という議論はあるみたいだが、これはまた別の機能の offset の話の様である。 17331 この時の実装の arg_offset に関係する議論ではない様に見える。更に明示的に 17332 arg_offset で検索をかけてみたが done.txt の中には何も残っていない様である。 17333 17334 c 更にその前の commit に行ってみたらもう arg_offset は残っていない。履歴の 17335 読み取りも直接 mapfile を呼び出しているに留まっている。 17336 17337 うーん。或いは cygwin では offset は使わない様になっていたという可能性はあ 17338 るだろうか。何故 Cygwin の事を考えずに変更を行ったのかかなり理解に苦しむ。 17339 うーん。それとも += を使う事にしていた可能性? うーん。然し再度確認してみて 17340 もその様な雰囲気は見られない。 17341 17342 或いは実はちゃんと実装されていて Cygwin の時には arg_offset があっても問題 17343 ない様になっている可能性? うーん。そんな風になっている雰囲気は見られないが。。 17344 取り敢えず、Cygwin でもちゃんと途中からの追記になる様に修正する必要はあるだ 17345 ろう。 17346 17347 * history: mapfile -O offset で読み取り始めると既存の項目がクリアされない様 17348 だが良いのか? これは Cygwin での実装をどの様にするのかという事にも関連し 17349 ている。 17350 17351 現在の実装を見ている感じだと offset は任意に指定できる訳ではなくて常に末 17352 尾を指定する様になっている気がする。もしそれが正しいのだとしたら既存の項 17353 目の truncate 等について悩む必要はないという事になる。 17354 17355 * ok: 一方で、_ble_history_edit に関しては一番最後に要素が追加されている 17356 可能性があるという事を考えると、やはり truncate しておくべきの気がする。 17357 と思ったが、_ble_history_edit に関しては Cygwin では単に _ble_history 17358 からコピーしているだけなので気にしなくて良い。 17359 17360 * done: 末尾以外の offset を指定できる機能は削除するべきだろうか 17361 17362 別の問題として特に末尾以外の offset が指定された時に後ろに続いているデー 17363 タを削除するべきか或いは保持するべきかという事。やはり offset を指定し 17364 ている箇所がないか確認が必要な気がする。という訳で '\boffset=' で検索し 17365 てみると。 17366 17367 > $ grc '\boffset=[^=]' --exclude=ext | grep -v 'local offset=' 17368 > ./keymap/vi.sh:2973: local ind=${1:-$_ble_edit_ind} offset=$2 17369 > ./lib/core-complete.sh:2221: local word1 index=0 offset=0 sep= 17370 > ./lib/core-complete.sh:4411:## offset=NUMBER 17371 > ./lib/test-edit.sh:11: local _ble_edit_str=$1 index=$2 offset=$3 17372 > ./lib/test-edit.sh:16: local _ble_edit_str=$1 index=$2 offset=$3 17373 > ./src/edit.sh:1880: local index=${1:-$_ble_edit_ind} offset=${2:-0} 17374 > ./src/edit.sh:1914: local index=${1:-$_ble_edit_ind} offset=${2:-0} 17375 > ./src/history.sh:283: ## offset=NUMBER 17376 > ./src/history.sh:301: elif local rex=':offset=([0-9]+):'; [[ :$opts: =~ $rex ]]; then 17377 > ./src/util.sh:617: # Note: Bash 4.3 以下では ${arr[@]:${2:-1}} が offset='${2' 17378 17379 やはり誰も offset は指定していない。この機能は削除する。 17380 17381 結局 truncate はしなくて良いと判断する。何故なら offset が指定されるとし 17382 ても常に末尾に対する追加だからである。 17383 17384 * 次の問題は Cygwin に於いてどの様に追記を実装するのかという事である。 17385 17386 % += を使うと 3.0 で使えない。然し ble/array#push は遅そうである。うーん。 17387 % 複雑になるが opt_source と arg_offset に応じて分岐する事にする。という 17388 % 訳で offset==0 の時には今まで通りにして、それ以外で bash-3.1 以上の場合 17389 % は += に置き換える。bash-3.0 の場合には _ble_history[10000]='str' とい 17390 % う具合に直接 index を指定して出力する事にする。 17391 % 17392 % →結局 arr=() arr+=() は遅いという事が分かったので、arr[ind]=str 一本で 17393 % 実装する事にする。 17394 17395 ? 然し改めて思ったのだが、そもそも array=() や array+=() は arra[]='...' 17396 よりも高速なのだろうか。実験してみる価値はある。 17397 17398 $ for a in {0..3}; do history; done | sed 's/'\''//g;s/^[[:space:]]*[0-9]\{1,\}[[:space:]]*//' > h.txt 17399 $ < h.txt awk 'BEGIN{apos="'\''"}{print "_dbg_history[" NR - 1 "]=" apos $0 apos}' > a.txt 17400 $ < h.txt awk 'BEGIN{apos="'\''";print "_dbg_history+=(";}{print apos $0 apos}END{print ")";}' > b.txt 17401 $ time source a.txt 17402 0.222 17403 $ _dbg_history=(); time source b.txt 17404 0.211 17405 17406 うーん。Cygwin で試してみた限りでは大して変わらない様に見える。若干 17407 arr+=() の方が速いぐらいである。でも bash-3.0 では試していない。Cygwin 17408 には bash 3.0..3.2 は入れていない。然し、一応 Linux で bash 3 でどちら 17409 かが致命的に遅かったりという事がないかを確認する事にする。 17410 17411 $ bash -c 'TIMEFORMAT="%Rs"; time source a.txt' 17412 0.454s 17413 $ bash -c 'TIMEFORMAT="%Rs"; time source b.txt' 17414 0.483s 17415 $ bash-3.0 -c 'TIMEFORMAT="%Rs"; time source a.txt' 17416 0.886s 17417 $ bash-3.0 -c 'TIMEFORMAT="%Rs"; time source b.txt' 17418 b.txt: line 1: syntax error near unexpected token `newline' 17419 b.txt: line 1: `_dbg_history+=(' 17420 0.002s 17421 [ble: exit 1] 17422 $ bash-3.1 -c 'TIMEFORMAT="%Rs"; time source a.txt' 17423 0.770s 17424 $ bash-3.1 -c 'TIMEFORMAT="%Rs"; time source b.txt' 17425 物凄く時間がかかるので中止した 17426 $ bash-3.2 -c 'TIMEFORMAT="%Rs"; time source a.txt' 17427 0.757s 17428 $ bash-3.2 -c 'TIMEFORMAT="%Rs"; time source b.txt' 17429 ^C 17430 [ble: exit 130] 17431 $ bash-4.0 -c 'TIMEFORMAT="%Rs"; time source a.txt' 17432 0.782s 17433 $ bash-4.0 -c 'TIMEFORMAT="%Rs"; time source b.txt' 17434 ^C 17435 [ble: exit 130] 17436 $ bash-4.2 -c 'TIMEFORMAT="%Rs"; time source a.txt' 17437 0.613s 17438 $ bash-4.2 -c 'TIMEFORMAT="%Rs"; time source b.txt' 17439 0.929s 17440 $ bash-4.4 -c 'TIMEFORMAT="%Rs"; time source a.txt' 17441 0.474s 17442 $ bash-4.4 -c 'TIMEFORMAT="%Rs"; time source b.txt' 17443 0.911s 17444 $ bash-5.0 -c 'TIMEFORMAT="%Rs"; time source a.txt' 17445 0.457s 17446 $ bash-5.0 -c 'TIMEFORMAT="%Rs"; time source b.txt' 17447 0.494s 17448 $ bash-dev -c 'TIMEFORMAT="%Rs"; time source a.txt' 17449 0.322s 17450 $ bash-dev -c 'TIMEFORMAT="%Rs"; time source b.txt' 17451 0.383s 17452 17453 この結果を見ると arr+=() は古い bash では致命的に遅い。arr=() について 17454 も確認して置いた方が良いのではないか? 17455 17456 $ < h.txt awk 'BEGIN{apos="'\''";print "_dbg_history=(";}{print apos $0 apos}END{print ")";}' > c.txt 17457 $ bash-dev -c 'TIMEFORMAT="%Rs"; time source c.txt' 17458 0.385s 17459 $ bash-4.4 -c 'TIMEFORMAT="%Rs"; time source c.txt' 17460 0.901s 17461 $ bash-4.2 -c 'TIMEFORMAT="%Rs"; time source c.txt' 17462 0.915s 17463 $ bash-4.1 -c 'TIMEFORMAT="%Rs"; time source c.txt' 17464 1.098s 17465 $ bash-4.0 -c 'TIMEFORMAT="%Rs"; time source c.txt' 17466 1.099s 17467 $ bash-3.2 -c 'TIMEFORMAT="%Rs"; time source c.txt' 17468 1.091s 17469 $ bash-3.1 -c 'TIMEFORMAT="%Rs"; time source c.txt' 17470 1.111s 17471 $ bash-3.0 -c 'TIMEFORMAT="%Rs"; time source c.txt' 17472 1.155s 17473 17474 うーん。この結果を見る限りは arr=() に関しては問題は存在しなかった様で 17475 ある。但しそうだとしても、arr[]=() の方式の方が安定して高速な結果を出し 17476 ている。これは完全に arr[]='...' に切り替えた方が実装もすっきりするので 17477 はないか。 17478 17479 * ok: 一応 #D0701 に議論がある様なので確認しておく。確認した。この時の記 17480 録を見る限りは "_ble_history[index]='...'" 的な方法については速度を計測 17481 していないのだという気がする。なので、この方法自体に何か問題があったと 17482 いう訳ではなく、当時は一顧だにしなかったという事なのだろう。 17483 17484 arr[index]=str を使うように切り替えた。awk 内部での hindex の取り扱いも変 17485 更した。これに伴って nlfix の時の修正インデックスの解釈も変更。nlfix につ 17486 いてはちゃんと変更後も動いている事を確認した。 17487 17488 x fixed: 後は Cygwin で問題なく動くかを確認する。と思ったら動かない。フリー 17489 ズしてしまう。何故だろう。 17490 17491 * うーん。どうも動かない様に見えたのは _ble_history_edit の方をロードし 17492 ていなかったからの様だ。 17493 17494 * C-r でフリーズするのも _ble_history_edit に有限の内容が含まれる様に変 17495 更したら直った。然し、だからと言ってそれだけでフリーズするというのも 17496 解せない。 17497 17498 それだと履歴が全く無い時にはどうなるのだろうか。試してみたが特に問題 17499 は生じなかった。どうも履歴項目で引数が多い物があってそれで遅くなって 17500 しまっているという事の気がする。これはまた再現したら対処するという事 17501 で良い事にする。 17502 17503 これで offset 問題は解決だろうか。trunate に関しては arg_offset が有限の時 17504 は常に末尾に対する追記という事にした。arg_offset=0 の時には配列をクリアする 17505 事にした。その上で offset については Cygwin の場合には直接 arr[index]=str 17506 の形式で初期化する事にしたので問題ない。他の環境では mapfile -O を今まで通 17507 り使う。大丈夫な気がする。 17508 17509 * 2021-05-04 折を見て simple-word/eval のデータ授受にも mapfile -d '' を使う [#D1604] 17510 Ref #D1522 17511 17512 mapfile -d "" が buffered になったら 17513 ble/syntax:bash/simple-word/eval/.print-result (lib/core-syntax.sh) を修正する。 17514 17515 2021-05-08 もう bash の側では修正されている。然し、Cygwin に対しても動作を 17516 変更できないかどうか尋ねてその上で改めて一緒に修正するのが良い気がする。 17517 17518 2021-06-12 未だ Cygwin についても修正できないかの問い合わせはしていないが、 17519 代わりに history のロードの側でも mapfile -d "" を使う様に変更したので、こ 17520 の際一緒に変更を適用する事にする。先に修正のある simple-word/eval を差し置 17521 いて history の方で利用するのは変だし、だからと言って history の方に対する 17522 変更も pending にするのには変更が大きすぎる。 17523 17524 * reject: read -t ... についても同様に bash-5.2 以降で実装を切り替えて良い気がする。 17525 17526 2021-06-12 今改めて考えると read -t の何の振る舞いを切り替えるのか分から 17527 ない。今まで unbuffered になっていた事によって read -d "" を使いたくても 17528 使えなかったのを控えていた箇所はあっただろうか。後、read -t というのは 17529 timeout の指定の事だが、今回の buffered/unbuffered の変化が timeout の振 17530 る舞いにどう影響を与えるのかは不明である。"read -t" の "-t" は唯単に手の 17531 癖で入力した物の様な気がする。 17532 17533 これに関しては取り敢えず棄却で良い気がする。 17534 17535 * history: [最適化] 初期化に新しい mapfile -d '' を使えないか [#D1603] 17536 Ref #D0681 17537 17538 これは ble/util/readarray -d '' で実装されている。と思ったが…そもそも 17539 builtin mapfile を直接使えば良いのではという疑惑もある。一応、他の version 17540 の bash でも使える様にしてあるという利点はあるが。 17541 17542 | というよりそもそも現在の実装になっているのは mapfile -d '' が遅かったからと 17543 | いう解釈は正しいのだろうか。ログを調べてみる必要がある。うーん。適当に検索 17544 | してみたが難しい。git blame で観察してみると 17545 | 17546 | 1bfc8ebe src/history.sh に移動 17547 | 17548 | 現在の実装は 2019-07-09 に大きく書き換えられている。と思ったが…これは単 17549 | にコードを移動しただけの話かもしれない→うーん。やはりそうだった。 17550 | 17551 | f204bc73 src/edit.sh: history -nr の対応 17552 | 17553 | 18fdaf2a Cygwin 対策 17554 | 17555 | c0c7f13e 2018-03-14 これ。この時点で mapfile & nlfix を実装している。まと 17556 | まった議論があるのもこの時のログである。#D0681 である。 17557 17558 うーん。当時のログを確認してみるとそもそも mapfile -d '' で NUL 区切りのデー 17559 タを読み込めるという事を認識していなかった様な節がある。今回改めて実験及び 17560 実装をして見る事にする。Bash version 毎の配列コピー時間についても確認する。 17561 17562 - 取り敢えず実装した。ちゃんと読み込めている。やはり配列コピーよりも 17563 mapfile の方が高速の様である。 17564 17565 * done: 後で printf '[[%s]]\n' "${_ble_history[@]}" > a.txt 等として出力し 17566 た結果を比較して正しいかどうかを検証する。 17567 17568 * done: Cygwin に於ける動作も変更したので動作確認の必要がある。 17569 17570 Cygwin では awk 側で unescape をする様にしたので nlfix は不要である。 17571 17572 動作確認の結果 mapfile -d '' の為に書いたコードでやったのと同じミスを修正 17573 するのを忘れていた。それを修正したらちゃんと動く様になった。OK 17574 17575 これを機に以前の mapfile の修正も適用してしまう事にする。 17576 17577 2021-06-11 17578 17579 * 2021-05-16 edit: BUG とても長いプロンプトにした時に列計算が壊れている (reported by telometto) [#D1602] 17580 また右端から入力を始めた時の折返しが正しくできていない。 17581 17582 2021-06-11 stackoverflow で報告されていた (by telometto) 17583 https://stackoverflow.com/questions/67917673/odd-long-space-in-bash-when-writing-commands 17584 17585 | うーん。ble.sh のバグが stackoverflow で報告されている。これは自分でも気 17586 | づいていた筈の問題である。何故忘れていたのだろう。割合最近気づいた事だっ 17587 | た筈である。調べたら 2021-05-16 の項目を見つけたのでそれに移動する事にす 17588 | る。 17589 17590 取り敢えず修正する。抑々 trace が怪しいという事なので計算結果について確認する。 17591 17592 $ x=0 y=0; LINES=10 COLUMNS=10 ble/canvas/trace 'HelloWorld'; declare -p x y ret 17593 x=10 y=0 17594 $ x=0 y=0; LINES=10 COLUMNS=10 ble/canvas/trace 'HelloWorldH'; declare -p x y ret 17595 x=2 y=2 17596 17597 物凄く意味不明な間違い方をしている。うーん。implicit-move が悪いという所ま 17598 で特定した。と思ったら分かった。折返しが発生すると分かった場合に x+=w を二 17599 重に実行している。2回目の x+=w を削除したら普通の振る舞いに戻った。調べてみ 17600 るとこれは 4fa139ad 2021-03-21 に複数行 "rps1" に対応した時に埋め込んだバグ 17601 であった。 17602 17603 2021-06-10 17604 17605 * prompt: 最適化 git の現在の dirty 状態は background で取得できる様にしたい [#D1601] 17606 17607 prompt-git.bash に実装したい。という事を考えると、 17608 prompt-git.bash は早晩に lib に移動するべきなのではないかという気がする。 17609 17610 これはどの様に実装するか。先ず初めに background で git を起動する。timeout 17611 を指定して直ぐに制御が戻らなければ取り敢えず放置する事にする。その後で結果 17612 が分かったらそれを取り出す。既に git を起動していて未だ結果が分かっていない 17613 時には何もしない。最後に結果が分かってから X 秒経過する迄は以前の結果を参照 17614 する。ディレクトリを移動した場合には、起動中の git はキャンセルして新しいイ 17615 ンスタンスを起動する。と言った位。 17616 17617 一から実装する事も可能だが既存の枠組みに沿った形で出来るだけ実装したい。git 17618 の結果待ちは idle プロセスとして実装する。うーん。history 初期化のコードを 17619 観察した。正にこれと同じことをしたいのである。 17620 17621 うーん。ライブラリにしようと思ったが微妙…。実は ble/util/idle.push -F 17622 tmpfile を使うだけで行ける話ではないか。履歴の場合にはデータが大量だったの 17623 で各ステップを分割して少しずつ処理する必要があった。然し、今回の場合には 17624 git の実行を待つという操作が1回存在するだけである。 17625 17626 実装した。動いている。と思ったが何だか遅い。うーん。ble/util/msleep 20 を入 17627 れるか入れないかで大分変化する。ble/util/msleep 20 なら1秒で50回捌ける様な 17628 気がするがそうでもないのだろうか。うーん。取り敢えず一定時間経過する迄は 17629 version が変化しても無視する事にする。 17630 17631 - 改めて計測してみると vim-airline を有効にしている時ですら一秒間に20プロン 17632 プト表示する事ができている。そもそも一つのプロンプトを表示するのに 50ms 17633 しかかかっていない。なので其処に 20ms 追加するのは 1.5 倍の時間がかかる様 17634 になる事を意味していて体感としてとても遅くなるのだという事。 17635 17636 - 取り敢えず前回の結果からそんなに時間が立っていない時、かつ、前回の要求か 17637 らプロンプト更新が10回以内の時には git の呼び出しは控える事にした。 17638 17639 # 単純な PS1 の時だけの場合のプロンプトの計算速度はどの程度だろうか。試して 17640 # みた所、29,26回/秒 だった。平均で 36.4ms かかっている。14ms の短縮である。 17641 # 此処で PS1 の処理をなくしたとしてもそんなには変わらないのだろうという気 17642 # がする。プロンプトの計算は実はそんなに重くないのだろうという事。 17643 17644 - また Linux では可也高速に git diff --quiet の結果を得る事ができる様なので 17645 ble/util/msleep の時間も 5 まで減らした。これでも大きすぎるかもしれないが、 17646 まあ、頻繁に更新はしない事にしているし特に問題にはならないだろう。 17647 17648 * [dissolved] 2021-05-28 prompt: 最下行で ble-reload すると statusline が重複してしまう [#D1600] 17649 17650 ble-detach してその後に ble-attach した時には問題は発生しない。 17651 →これは確認した所再現しなくなっていた。恐らく #D1592 で解決した問題だろう。 17652 17653 * [reject] 2021-05-24 prompt: プロンプトの変数展開の更新検出 [#D1599] 17654 17655 プロンプト更新検出に於いてプロンプトに含まれて 17656 いる変数展開 $XXXX も自動検出する? 然しエスケープや $() 等も拘ってくると複 17657 雑である。適当な方法で解析できたりしないだろうか。というか、終端を処理する 17658 為に parse していた様な気もする。その辺りについてはまた後で確認する。 17659 17660 $RANDOM や $EPOCHREALTIME 等については除外するべきである。これらの変数への 17661 nref の検出は困難である。という事を考えるとやはりユーザーに任せるという可能 17662 性も考えられるが。 17663 17664 然し一方でプロンプトを計算した瞬間の値を参照したいという需要も考えられる。 17665 例えば $BASH_COMMAND, $LINENO 等がプロンプトに含まれていたとして、その内容 17666 が変わったからといってユーザーはプロンプトの表示を更新する事を想定はしてい 17667 ないのではないか。という事を考えるとやはりユーザーが明示的に要求しない限り 17668 はプロンプトに含まれている変数展開を改めて評価する必要はないのではないかと 17669 いう気がする。 17670 17671 * [ok] 2021-05-24 prompt: 現在のモードの算出の共有化・最適化 [#D1598] 17672 17673 ble/prompt/.get-keymap-for-current-mode やble/keymap:vi/script/get-mode に 17674 関しては一旦計算値を別の変数に格納してそれを参照して値を計算するべきの気が 17675 する。これは git 等の最適化と一緒に新しく枠組みを考える事にする。 17676 17677 取り敢えず枠組みは整えた。そしてこれらの関数では関連する変数に対して 17678 add-hash を実行している。新しい unit にする程の物でもないだろう。一つにはこ 17679 れらの関数はそんなに思い関数でもないという事。そして幾つも何度も実行する様 17680 な物でもないのでキャッシュしても仕方がないのではないかという事。大抵の場合、 17681 依存関係を追跡するコストの方が大きそうである。なので add-hash をして、これ 17682 らを含むプロンプトを再更新させるぐらいで良いだろうと思われる。 17683 17684 * auto-menu: ubuntu20 で auto-menu を有効にしても動いたり動かなかったりである [#D1597] 17685 17686 auto-menu の起動条件 (直前の widget) に対する判定で失敗しているのだろうか。 17687 或いはもっと別の要因だろうか。うーん。或いは idle.sleep に失敗しているとい 17688 う可能性もあるのかもしれない。 17689 17690 どうやら ble_util_idle_elapsed が常に 0 になってしまって時間が経過しない 17691 という事で無限ループになっている様子だ。調べると _ble_util_idle_sclock が 17692 0 の儘で全く動いていない。_ble_util_idle_sclock は ble/util/idle/.sleep 17693 によって増える手筈になっている。ble/util/idle/.sleep は .sleep-until-next 17694 から呼び出される事になっているが、この関数の振る舞いを見るとどうやら 17695 sleep_amount が微妙に負になっている。現在時刻と次のタスクをする時刻を比較 17696 しているが、次のタスクを実行する時刻が何故か現在時刻よりも前の時刻になっ 17697 てしまっている。 17698 17699 現在時刻は ble/util/idle.clock で取得されていて内部的には ble/util/clock 17700 になっている。ble/util/clock は中で EPOCHREALTIME を参照している。一方で 17701 次の時刻 _idle_next_time は何処から来るのかというと task の SXXXX という 17702 エントリーから読み出される。この SXXXX というエントリーは 17703 ble/util/idle.sleep で設定されていて、その関数の中で ble/util/idle.clock 17704 が呼び出されている。整理すると 17705 17706 1 最初に ble/util/idle.sleep が呼び出されてその時の時刻を元にして待ち時刻 17707 が設定される。何らかの処理がなされてその回のループが終了する。 17708 17709 2 次のループに入る前に次の待ち時刻まで sleep する。しかし、この時迄に時刻 17710 が経過して次の待ち時刻を超えてしまうので、スリープ無しで次のループが始 17711 まる。 17712 17713 3 再び auto-menu.idle が開始するが auto-menu.idle は合計 sleep 時間を使っ 17714 て経過時刻を確認する。然し、実際には sleep は行われていないので 17715 auto-menu.idle は時間が経過していないと勘違いして再び sleep を設定して 17716 抜ける。 17717 17718 此処での問題は auto-menu.idle は絶対時刻による待ちを設定しているのにも関 17719 わらず、判定及び残り sleep 時間の算出に sclock つまり sleep 合計時間を使っ 17720 ている事である。どちらかに統一するべきである。裏で重い処理が走っていよう 17721 ともそれはユーザーには見えないのでできるだけ定刻通りに処理を開始するべき 17722 であると思うと、絶対時刻を使用する方に揃えるべきである。 17723 17724 2021-06-09 17725 17726 * 2020-09-07 complete: メニュー絞り込みの着色が残ったままになってしまう事がある [#D1596] 17727 17728 menu_filter が off にならない状況が分かった。auto-complete による単純挿入で 17729 継続した時、menu_filter が更新されない。更に別の機能によって menu が削除さ 17730 れてしまった時にも更新されない? 17731 17732 | と思って実装を確認したがそうでもない様な気がする。実装を確認すると現在の 17733 | keymap が menu-complete でもない限りは menu-filter の処理を走らせている。 17734 | 領域抽出などに失敗した時にも単に menu を clear するだけでそれ以外の特別な 17735 | 解除処理は行っていない。だとすると、menu-filter の着色の側で処理を行って 17736 | いる? 17737 | 17738 | 然し ble/highlight/layer:menu_filter/update を見る限りは現在 menu が表示 17739 | されている場合にのみ着色を行う様になっている。うーん。或いは dirty range 17740 | がない限りはそもそも layer が呼び出されない可能性? と思ったがそれも変であ 17741 | る。何か文字列を入力してもやはり着色が残ってしまうという現象が見えていた 17742 | 筈である。 17743 17744 - やはり振る舞いを見るとちゃんとキャンセルはされている様である。この時に 17745 layer が更新されないのが問題なのだと思われる。 17746 - 更に layer の実装の方も確認してみると、これもちゃんと動いている気がする。 17747 ちゃんと update-dirty-range が呼び出されている。此処で改めて表示が更新さ 17748 れるべきなのである。うーん。勝手に後で表示が変化しているという事なのか。 17749 17750 - 或いは、上の layer が更新を無視してしまっているのか。layer の list を確認 17751 すると plain syntax menu_filter region overwrite_mode disabled になってい 17752 る。 overwrite_mode と disabled は不活性になっていて region は 17753 auto_complete によって設定されている。つまり region が変更を握りつぶして 17754 いるという事。再構築の部分を確認してみると、既存の内容は全て捨てて下層と 17755 現在の範囲着色で完全に再構築している。 17756 17757 うーん。分かった。選択範囲の変更がない場合に、例え下層で何か変更があった 17758 としてもスキップしてしまう様になっている。 17759 17760 ? ok: layer:menu_filter は layer:region を参考にして作られた同様の問題点は 17761 ないだろうか→確認したがその問題はなさそうである。PREV_BUFF を上書きして 17762 返す場合にはちゃんと PREV_UMIN<0 である事を確認している。layer:region が 17763 問題になったのは PREV_BUFF を上書きしているのにも拘らず、元の PREV_BUFF 17764 に起こった変更を拾わなかったのが原因である。 17765 17766 ? ok: さて、今回の修正では選択範囲が存在する時に menu_filter 着色が残ってし 17767 まうという話だったが、実際のコマンド実行に於いても menu_filter の着色が残っ 17768 てしまう様な場合が存在する気がする。と思ったが、実際にコマンドを実行する 17769 段階まで行けば menu_filter の着色は解除されていた様な気もする。これは選択 17770 範囲と関係ない様な気がするが、何故問題がそのまま発声していたのであろうか。 17771 うーん。 17772 17773 というか今回の場合も何故問題が生じていたのかよく分からない。というのも 17774 auto_complete による選択範囲は変わっている筈だからである。うーん。DMIN<0 17775 なのは良い。そして、select[*] と osel[*] が一致している時に限りスキップが 17776 起こっている筈なのである。それなのに、実際に発声している状況を見ると sel 17777 <- osel で変更が起こっている筈なのに着色がスキップされてしまっているとい 17778 う事。どういう事なのだろうか。 17779 17780 →確認してみた所、何といきなり osel が変化している。うーん。DMIN に変更が 17781 あってそれでスキップされていたという事だろうか。うーん。分かったそういう 17782 訳ではない。 17783 17784 何が起こっているかというと… 17785 17786 (1) auto_complete で空白文字が入力されて、カーソル位置と region の開始点 17787 が一文字後ろにずれる。この時点で一旦描画が呼び出される。この時は未だ 17788 menu_filter.idle が走っていないので menu は表示した儘で menu_filter の 17789 着色も有効の儘である。そうすると e[cho ][予測内容] の前半の [] を 17790 menu_filter 着色にして、後半の [] を region 着色した状態になる。 17791 (2) その後で menu-filter.idle が走って menu を削除する。この時、内部的に 17792 はecho [予測内容] の様に書き換わるが選択範囲に変更がない為に、 17793 layer:region が下層の変更を拾わずにその儘になっていた 17794 17795 という事。今まで時々見られた物もこれで説明が着くのではないか。取り敢えず 17796 17797 [まとめ] layer:region が、選択範囲が存在して前回と変更がない時に、下層で変 17798 更があったとしてもそれを反映しない設計になっていたのが原因であった。 17799 17800 * 2021-05-29 bleopt: wildcard を使った時に obsoleted な物も列挙されている [#D1595] 17801 複数単語に展開された時にはフィルタする様にしたら良い。 17802 17803 * blehook: -a を指定しないと直接 hook を指定しても表示されない [#D1594] 17804 17805 % blehook -a face_name による結果の表示も一緒に遅延されている気が 17806 % する。というかそもそも blehook に遅延機能があったのだろうか。。 17807 % そしてその理由は? うーん。見た感じは遅延機能等ない。と思ったが分 17808 % かった。blehook 自体が faces にアクセスしようとして、それで初期 17809 % 化が発生している。 17810 17811 * color: initialize-faces の遅延に関する問題 (motivated by jmederosalvarado) [#D1593] 17812 https://github.com/akinomyoga/ble.sh/issues/96#issuecomment-813185300 17813 17814 * vim-airline: theme を blerc で設定しても何故か暫くすると dark の配色が読み 17815 込まれている気がする。改めて設定し直すと問題は起こらない。theme を変えた瞬 17816 間の配色が何だか変になる。 17817 17818 うーん。調べてみると initialize-faces が2回呼び出されている気がする。何故だ 17819 ろうか。ble/syntax/attr2g 経由である。うーん。分かった。core-syntax.sh が定 17820 義している関数で ble/syntax/attr2g の初期化を遅延しようとしている。然し、最 17821 初にプロンプトを表示した時点で既に initialize-faces が実行されるので、その 17822 後で ble/syntax/attr2g { initialie-faces && ble/syntax/attr2g "$@"; } 等と 17823 すると二重に初期化される様になるのである。eval-after-load 的な仕組みで登録 17824 する必要があるのではないか。 17825 17826 * また、initialize-faces が実行されたら実行した hook はクリアする事にする。 17827 17828 * この際なので GitHub #96 のコメントで指摘されている遅延についても対処する。 17829 17830 沢山の setface 設定を仕込んでいると最初のキーストロークの反応が遅いという 17831 話。これに関しては initialize-faces を idle で実行すれば良い。 17832 17833 idle の登録順序はどうなっているだろうか。ロードした直後の idle の順序を確 17834 認する。complete を絶対パスでロードするように変更して、また syntax より後 17835 にロードする様に変更した。変更後の様子は以下の通り。 17836 17837 [0]="R\\ble/history:bash/resolve-multiline async" 17838 [1]="R\\ble/util/import '/home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh'" 17839 [2]="R\\ble/util/import '/home/murase/.mwg/src/ble.sh/out/lib/core-complete.sh'" 17840 [3]="R\\ble/util/import '/etc/profile.d/modules.sh'" 17841 [10000]="R\\ble/util/msleep/calibrate" 17842 [10001]="R\\ble/textarea#render-defer.idle") 17843 17844 うーん。syntax よりは前に faces は initialize して良いのではないか。とい 17845 う事を考えると、実は一番最初に登録してしまっても問題ない。登録した。 17846 17847 * vim-airline を blerc からロードする様にすると余分な行が表示される [#D1592] 17848 17849 | 調べると \q{lib/vim-airline} の中で問題が発生している。更に調べると 17850 | ble/prompt/unit:_ble_lib_vim_airline_mode/update の中の 17851 | ble/history/get-entry により何かが出力されている。出力内容を調べるとエスケー 17852 | プシーケンスを出力している。エスケープシーケンスの出処を調べる。 17853 | 17854 | | ble-attach 17855 | | ble/term/initialize 17856 | | ble/term/test-DECSTBM 17857 | | ESC7 17858 | | ESC[1;2r 17859 | | ESC[2;1H 17860 | | ESC[1B 17861 | | ESC[6n 17862 | | ESC[;r 17863 | | ESC8 17864 | | ble/decode/attach 17865 | | ESC[>c 17866 | 17867 | 上記の出力内容は単に buffer に残っていただけ。 17868 | これらは特に何も問題を起こさない。 17869 | 以下の内容が問題を起こしている。 17870 | 17871 | | ESC(BESC[m^MESC[2KESC[1M 17872 | | ESC(BESC[mESC[30C 17873 | 17874 | もっと分かり易く書くと以下の形になる。 17875 | 17876 | SGR0 CR 17877 | EL(2) DL(1) ... put-dl.draw 17878 | LF SGR0 CUR(30) 17879 | 17880 | EL(2) DL(1) の組み合わせは put-dl.draw が使っている物である。put-dl.draw に 17881 | 仕掛けて FUNCNAME[@] を出力してみると以下の結果になった。 17882 | 17883 | | ble/canvas/put-dl.draw 17884 | | ble/canvas/panel#set-height.draw 17885 | | ble/canvas/panel/reallocate-height.draw 17886 | | ble/edit/info/.render-content 17887 | | ble/edit/info/show 17888 | | ble/edit/info/immediate-show 17889 | | ble-edit/history/history-message.hook 17890 | | blehook/invoke 17891 | | ble/history:bash/load 17892 | | ble/history:bash/initialize 17893 | | ble/history/initialize 17894 | | ble/history/get-entry 17895 | | ble/prompt/unit:_ble_lib_vim_airline_mode/update 17896 | | ble/prompt/unit#update 17897 | | ble/prompt/backslash:lib/vim-airline 17898 | | ble/prompt/backslash:q 17899 | | ble/function#try 17900 | | ble/prompt/.process-backslash 17901 | | ble/prompt/process-prompt-string 17902 | | ble/prompt/.instantiate 17903 | | ble/prompt/unit:{section}/update 17904 | | ble/prompt/unit:_ble_prompt_status/update 17905 | | ble/prompt/unit#update 17906 | | ble/prompt/update 17907 | | ble/textarea#render 17908 | | ble/textarea#redraw 17909 | | ble-attach 17910 | | ble/base/attach-from-PROMPT_COMMAND 17911 | | ble/function#lambda/0 17912 | 17913 | つまり、ble-attach から呼び出したプロンプト再描画の中で vim-airline が呼び 17914 | 出されて、その中での modified の判定の為に get-edited-entry が呼び出されて 17915 | いるという事。get-edited-entry は内部で ble/edit/info/immediate-show を呼び 17916 | 出して居て、結果として何らかの不都合が生じて計算がずれる。 17917 | 17918 | a reject: 一つの可能性として DRAW_BUFF に出した出力が中途半端になっている事 17919 | によって問題が生じているのではないかと思ったが、DRAW_BUFF を覗いた感じだ 17920 | と特に何も登録はされていない。なので出力のバッファリングが輻輳していると 17921 | いう可能性は考えなくて良い。 17922 | 17923 | b reject: 或いは buffer に既に入っている内容が問題になっている? と思ったが 17924 | そうでもない。その場で buffer.flush して、get-edited-entry の出力だけ潰し 17925 | ても特に問題は生じない。 17926 | 17927 | c reject: 或いは端末に繋がっている時だけしか問題のある出力をしない可能性は 17928 | あるだろうか。つまり e.log に出力された内容を今は観察しているが、実際には 17929 | 端末に繋がっている時に限りもっと色々な出力をしている。具体的には非端末の 17930 | 時にはble/history/initialize は info で何も表示しない可能性。一旦 17931 | get-edited-entry の直後で sleep を入れて何か表示されるのか確認してみる事 17932 | にする 17933 | 17934 | →特に何も表示されない。恐らく端末に繋がっているかどうかの違いで振る舞い 17935 | が変わるという訳ではないと思われる。 17936 | 17937 | →実際に非端末の出力先として 2> >(cat) を使った場合にも問題が再現する。と 17938 | いう訳なので観察している出力で確かに問題が発生しているのだという事。 17939 | 17940 | d reject: もう一つの可能性は後で遅延して履歴読み込みが完了した時に info を 17941 | 削除する時に問題が生じているという可能性。 17942 | 17943 | →これは関係ない。実際に get-edited-entry の stderr を潰せば問題は生じな 17944 | くなっているし、その imbalance が生じる事によって表示が偶々正しくなってい 17945 | るという様には考えがたい。 17946 | 17947 | e reject: 或いは get-edited-entry を呼び出した直後に buffer に入っている内 17948 | 容が後になって問題を起こしている可能性? → 確認したが、get-edited-entry 17949 | 直後には buffer は何も入っていない。これは関係ない。 17950 | 17951 | f もう一つの可能性として全体更新が中途半端になっている事によって座標計算が 17952 | ずれているのではないかという事。然し、問題が生じているのは ble-attach か 17953 | ら直接 ble/textarea#redraw を呼び出した時であって、これは panel/render で 17954 | はないので、textarea と info の描画は独立の筈である。 17955 | 17956 | となって来ると、info から呼び出した set-height の実装か、或いは位置計算に問 17957 | 題が生じているという事になる気がする。出力内容と _ble_canvas_x,y の状態につ 17958 | いて確認する必要がある。 17959 | 17960 | | _ble_lib_vim_airline_mode 17961 | | declare -- _ble_canvas_x="30" 17962 | | declare -- _ble_canvas_y="0" 17963 | | declare -- _ble_canvas_excursion="" 17964 | | ^[(B^[[m^M^[[2K^[[1M 17965 | | ^[(B^[[m^[[30Cdeclare -- _ble_canvas_x="30" 17966 | | declare -- _ble_canvas_y="0" 17967 | | declare -- _ble_canvas_excursion="" 17968 | 17969 | うーん。これを見る限りは canvas 的にはカーソル位置は動かしていないつもりな 17970 | のである。改めてこのシーケンスがどの様に生成されているか確認する。 17971 | 17972 | | _ble_lib_vim_airline_mode 17973 | | declare -- _ble_canvas_x="30" 17974 | | declare -- _ble_canvas_y="0" 17975 | | declare -- _ble_canvas_excursion="" 17976 | | declare -a _ble_canvas_panel_height=([0]="1" [1]="0" [2]="0") 17977 | | [delta=-1,opts=] 17978 | | ^[(B^[[m^M^[[2K^[[1M 17979 | | ^[(B^[[m^[[30C[delta=0,opts=] 17980 | | declare -- _ble_canvas_x="30" 17981 | | declare -- _ble_canvas_y="0" 17982 | | declare -- _ble_canvas_excursion="" 17983 | | declare -a _ble_canvas_panel_height=([0]="0" [1]="0" [2]="0") 17984 | 17985 | うーん。どうやら panel#0 の高さが潰れてしまっている様子。然し、高さが潰れて 17986 | しまっているからと言ってカーソルの位置が変わるのは変である。うーん。 17987 | set-height までは別に座標計算が変な事にはなっていない様だ。set-height を抜 17988 | けた後で座標位置を復元している箇所があって、其処で計算がずれているという事 17989 | の気がする。 17990 | 17991 | うーん。分かった。以下の様な状態になっている。x=0 y=0 content=$'\n' になっ 17992 | ている。content に改行が入っているのだから、本来は y=1 でなければならない筈 17993 | である。何故この様な内容が生成されるのか確認する必要がある。 17994 | 17995 | declare -a _ble_edit_info=([0]="0" [1]="0" [2]=$'\n') 17996 | 17997 | 更に調べると ble/edit/info/.construct-content text 'loading history...' の 17998 | 構築結果がその様になっている。 17999 | 18000 | % 更に辿ると ble/canvas/trace-text がまるで動かなくなっている。何故。。。 18001 | % 18002 | % x=0 y=0; ble/canvas/trace-text 'ABC'; echo "($x,$y)[$ret]" 18003 | % 18004 | % とすると x=0 y=0 ret=$'\n\n' 二重改行になってしまっている。これは大事。 18005 | % いつからこの様な事態になっていたのだろう。今まで気づかなかったのも不思 18006 | % 議である。というより、殆どの機能で着色を使っているので trace-text は余 18007 | % り使われてこなかったのである。更に遡って調べてみると v0.3.0 の時点で既 18008 | % に trace-text は動作していなかった様だ。0.2 系列では 18009 | % ble-edit/info/.construct-text という関数で現在の実装とは全く異なる物凄 18010 | % く単純な実装だった。この時は勿論問題はなかった。 18011 | % 18012 | % まとめると ble/canvas/trace-text は可也昔から壊れていた。v0.3.0 の時点 18013 | % で駄目。一方で v0.2 の段階ではその前身である 18014 | % ble-edit/info/.construct-text だったが、これはとても単純な関数でまた問 18015 | % 題も存在しなかった…と思ったが微妙に関数の仕様を勘違いしていた。 18016 | % trace-text は領域の大きさを外部から与える必要があったのである。 18017 18018 結局何が起こっていたのかというと、ble/edit/info/.construct-content に於いて、 18019 ble/edit/info/.initialize-size が lines=0 を返して、それに対して 18020 ble/canvas/trace-text が変な振る舞いをしていたという事。 18021 18022 問題が3つある。 18023 18024 x fixed: ble/canvas/trace-text は lines が限界に達しているのにも関わらず改 18025 行を末尾に付加してしまう。これは個別に対応した。 18026 18027 x ok: 改行を付加したのにも関わらず y を増やしていない。これは trace-text を 18028 ほぼ再実装した結果発生しなくなった。何故元の実装でこれが発生していたのか 18029 は分からない。そもそも改行 \n ですら trace-text では ^J と表示される。 18030 18031 →これは分かった。ble/canvas/trace-text/.put-nl-if-eol が put-simple の中 18032 と終了時の2回呼び出されている。cols=0 の時には一回実行したとしてもまだ行 18033 末にいると判定されるので二回実行されるのである。 18034 18035 x fixed: ble/canvas/trace-text を初期化する前に、何故か 18036 ble/edit/info/.initialize-size が lines=0 を結果として与えている。 18037 18038 中では ble/canvas/panel/layout/.get-available-height を呼び出している。 18039 18040 % 中で戻り値を確認すると ret=9730ret という謎の値が生成されている。と思っ 18041 % たがこれは debug コードのミスだった。 18042 18043 改めて調べるとこの時点で 0 が生成されている。 18044 18045 declare -a mins=([0]="1" [1]="0" [2]="0" [3]="0") 18046 declare -a maxs=([0]="1" [1]="0" [2]="1" [3]="0") 18047 declare -a heights=([0]="0" [1]="0" [2]="0" [3]="0") 18048 declare -- index="2" 18049 declare -- ret="0" 18050 18051 うーん。この時点で maxs に LINES が設定されて欲しいが 1 になってしまって 18052 いる。うーん。原因が分かった。プロンプトの処理を行っている最中は LINES 18053 COLUMNS を通して描画範囲の大きさを指定しているが、これだと本来のレイアウ 18054 ト処理に影響を与えてしまう。 18055 18056 取り敢えずは ble/canvas/trace は引き続き LINES COLUMNS を参照する事にして 18057 おいて、その外側の instantiate 等については LINES/COLUMNS は別変数経由で 18058 指定する事にする。 18059 18060 書き換えた。これで現在 LINES= 及び COLUMNS= を設定している箇所は全て 18061 ble/canvas/trace の呼び出しか、または ble/textmap#update の呼び出しに限ら 18062 れる事となった。 18063 18064 x fixed: 何故 panel#0 の高さが潰れてしまうのか。本来は此処で高さを変更する 18065 必要はないのではないか。というより高さ 1 の儘であるべきなのではないのか。 18066 特に ble/prompt/update の段階では。 18067 18068 これは LINES=1 を設定していた為に visible-bell 専用の行が引き算されて 0 18069 になってしまっているという事だろう。LINES=1 の時には visible-bell も表示 18070 しない様に修正する必要がある。もしくは visible-bell の表示方法を変更して、 18071 即座に行送りにする。と思ったが、visible-bell を表示した時点で現在の表示内 18072 容を保持する事ができないので、やはり LINES=1 の時には visible-bell は表示 18073 しない様に変更するのが適切だろう。 18074 18075 * done: この問題とは独立に get-edited-entry に於いて最新の値を参照している 18076 時には履歴をロードせずに済ませる様に実装する様にした方が良い。実装した。 18077 取り敢えず vim-airline の modified はこれでもちゃんと動いている。 18078 18079 * done: trace-text のテストを拡充 18080 18081 x 2021-06-08 airline: ロード時に keymap_vi_mode_show=1 に再設定すると表示が 18082 ずれてモード行の位置にプロンプトの残像が残ってしまう 18083 18084 →これは #D1592 を修正したら再現しなくなった。 18085 18086 x 2021-06-08 airline: status 行を表示している時の空コマンド行による改行がス 18087 ムーズではない。 18088 18089 →これも #D1592 の修正で再現しなくなった。LINES/COLUMNS によりレイアウト 18090 再構成が毎回走っていたという事なのだろうか。何れにしても空コマンド行によ 18091 る改行で status line を出した儘にしているかどうかだけ、実装について確認す 18092 るのが良い。 18093 18094 →確認した。textarea (panel#0) の再描画しかしていないので statusline 等に 18095 ついてはその儘の筈。但しプロンプトの再計算が入るので結局再描画はされる様 18096 な気もしないでもない。うまく cache が働いていれば dirty にもならずに再描 18097 画もなくそのまま前の表示が使われるのではないかという気がする。 18098 18099 2021-06-07 18100 18101 * prompt: [最適化] 依存関係追跡の整理・最適化 [#D1591] 18102 18103 x .instantiate の section update で git 情報や現在の vim モードに依存してい 18104 るが、一方で自動的な依存解決による section update が git 情報や vim モー 18105 ドを初期化する前に呼び出されている。 18106 18107 これに関しては本来は git の情報は ble/prompt#update _alpha '' prompt-data 18108 等として初期化する必要があるのではないかという気がする。というか 18109 ble/prompt#update を流用する必要があるのかは謎である。実はデータ専用の関数 18110 を用意しても良いのではないだろうか。そしてデータは好きな様に利用する。 18111 18112 ? そもそも配列を共有している理由はあるのだろうか。。。 18113 18114 version hashref hash に関しては依存関係の管理に関係している。 18115 これは一つ上の枠組みで管理される物なので切り離しても良いのではないか。 18116 一方で (instantiate 7つ組) 及び (tailor データ) はプロンプト情報固有の物である。 18117 18118 但し、version 更新の条件として (instantiate 7つ組) または (tailor データ) 18119 による更新が実際にあったかどうかを使っている。然し、version は一般に外から 18120 その内容が変更されたかどうかを判定する為に用いているから、やはり version 18121 hashref hash の組で管理するべきである。 18122 18123 取り敢えず veresion hashref hash の順序を変更する事にする。 18124 18125 うーん。何だか分からなくなってきた。そもそも現在の構造に欠陥がある様な気が 18126 する。hash を見て更新する必要があるかどうかを観察する事になっているが、依存 18127 関係がある時には hash で参照している先を初めに更新しておかなければ反映され 18128 ない。なので、依存先を先に更新しようと考える訳だが更新に使用する引数が分か 18129 らないという問題が生じる。 18130 18131 a 依存先の hashref を展開して長大な hash で更新確認をする案 18132 18133 % これは version で参照しているから行けないのであって、依存先の hash 本体を 18134 % 依存元が取り込んでしまえば問題ないのでは? とも思われるがそれは変数の時だ 18135 % けである。history index や git の情報など何らかの処理によって確認を取って 18136 % 値を計算してから出ないと分からない物に関してはやはり変数で参照していても 18137 % 駄目である。 18138 18139 依存の更新がグローバル変数の変化を通してのみ発生する場合にはこれで良いが、 18140 実際には git 等の様に現在の値をその都度更新する必要がある物もある。 18141 18142 history index/count に関しても既存のコードを大きく変えたくないので、同様 18143 の仕組みを使って実装したいと考えている。と思ったが、history に関しては変 18144 数経由にした方が良い様な気もする。描画(カーソル移動も含めて)の回数と履歴 18145 移動の回数を数えたら断然描画の回数の方が多いだろうから。 18146 18147 b そもそも各 unit に外から引数を与えられる様になっているのが変である。外か 18148 らプロンプト文字列を与えられなくてもそれ単体として更新をできる様にする。 18149 これはそんなに難しくない筈である。というより、今まで外から引数を指定でき 18150 る形で更新していた事自体が変なのである。 18151 18152 この場合に真面目に考えなければならないのは特定の条件で on/off される様な 18153 プロンプトの存在である。うーん。特定の条件で表示非表示を切り替える様な物 18154 の場合には、消去のコードも自分で生成するか或いは消去は外に任せる事にして、 18155 自身は表示している時の状態を保持し続けるという事か。うーん。これについて 18156 は外からの支持で動作するというので良い気がする。つまり、今までの振る舞い 18157 で良い。特に rps1, xterm_title, etc. に関しては他から参照される事もないの 18158 で、外から呼び出された時にだけ更新すれば良い。更新する必要がないのに古い 18159 依存関係経由で呼び出されるという様な事はないので大丈夫。 18160 18161 1 先ず更新は全て unit#update 経由で実行するという事。現在は class 等とし 18162 て {section}/update を定義しているがこれは廃止する。個別にちゃんと 18163 /update で実装するという事。unit#update には引数は渡さない 18164 18165 prompt-expand-{gbox,bbox} は廃止する。必要ならば呼び出し元で抽出を行う。 18166 と思ったが、helper 関数として存在しても良いのではという気がしないでもな 18167 い。何れにしてもこれは後回し。先ずは大きな構造の方を整理する事にする。 18168 18169 * done: ble/prompt/section#update 廃止 18170 18171 * done: vim-airline-mode は unit として実装する。 18172 18173 * done: ble/prompt/unit:UNIT/section::tailor 削除 18174 18175 これは明らかに実装を複雑化させている。そして tailor だけを invalidate す 18176 るというのも元々は効率の為だったが、既に様々な無駄がある中で余り意味のあ 18177 る最適化である様にも思われない。従って tailor は削除する。 18178 18179 * done: history index/count は変数にする 18180 18181 取り敢えず _ble_history_INDEX 及び _ble_history_COUNT 18182 18183 ? _ble_history_prefix が謎である。設定している箇所は見つかるが解除してい 18184 る所が見つからない。local で宣言している訳でもないし textarea vars に設 18185 定されている訳でもないから復元される事もない様な気がする。 18186 18187 例えば vi.sh で _ble_history_prefix=_ble_keymap_vi_filter_ を設定してい 18188 る。これは ble/keymap:vi/async-commandline-mode から 18189 ble/textarea#save-state _ble_keymap_vi_cmap を呼び出した後に実行されて 18190 いる。と思ったらこれについては _ble_keymap_vi_cmap_history_prefix に手 18191 動で保管して、その後で手動で復元している。vi.sh の中にある物は全てこれ 18192 だった。 18193 18194 ./src/edit.sh:7857: _ble_history_prefix=_ble_edit_read_ 18195 これに関しては subshell で実行しているので戻さなくて大丈夫。 18196 18197 他に設定している箇所はない。 18198 18199 他の ble/history/get-{count,index} に関しては明らかに history を 18200 initialize しなければならない所以外は現状のままで関数経由で取得する事にし 18201 た。直後に history を initialize する場合にはその場で 18202 ble/history/initialize を呼び出して直接 _ble_history_{COUNT,INDEX} を参照 18203 する様に書き換えた。 18204 18205 x 2021-06-09 textmap が更新される前に表示しようとすると col がずれてしまう。 18206 これはその場で更新してしまっても問題ないのではないか。特に textmap の更新 18207 が必要になるという事は dirty という事なので。 18208 18209 →うーん。此処で気づいてしまったが。textmap で使用する文字幅を決定する為 18210 には rps1 の幅が必要で、一方で rps1 の中に配置情報を表示しようとするとそ 18211 の前に textmap を計算しなければならない。取り敢えず rps1 の中に含まれる情 18212 報は 前回の rps1 の幅に基づく textmap の情報と解釈する事にする。 18213 18214 後、もう一つの問題は ble/widget/.update-textmap の内部で呼び出している 18215 textmap が rps1 の幅を考慮できていないという事。 18216 ble/widget/.update-textmap の実装をちゃんと rps1 の幅を考慮に入れる物に書 18217 き換えて、更に backslash:position 等の中から ble/widget/.update-textmap 18218 を呼び出す様に修正した。 18219 18220 * prompt: [最適化] 依存関係の追跡と部分更新の対応 [#D1590] 18221 18222 ble/prompot/clear については各プロンプト毎に設定できる様にするべき。 18223 再描画部分についても dirty かどうかを保持して更新するかしないかを判定するべ 18224 きの気がする。 18225 18226 各プロンプト毎に何に依存しているかのリストと依存している物に対する hash を 18227 自動で生成する様な仕組みが欲しい気がする。仕様としては各プロンプト内部で情 18228 報を参照した時に ble/prompt/add-dependency xxxx を呼び出す。プロンプトの実 18229 体化を司る側ではこれをリストにして管理する。hash を生成する時には、 18230 ble/prompt/data:xxxx/hash を通して関数を呼び出し hash+=:xxxx=$hash を実行す 18231 る。然しこれだと hash のインスタンス化自体に split, for, += が必要になって 18232 重そうである。それよりは、直接 eval できる形にした方が良いのかもしれない。 18233 18234 % つまり 18235 % 18236 % _ble_prompt_version_ref+='$LINENO' 18237 % eval "_ble_prompt_version=$_ble_prompt_version_ref" 18238 % 18239 % という具合にする。invalidate する時には各変数について ((LINENO++)) する等し 18240 % て処理を行う。各プロンプト要素を個別に invalidate できる様に各プロンプト固 18241 % 有の変数も用意する。コマンド実行後には全て更新する様にしたいので共通の更新 18242 % 条件としてそれも含めて置くことにする。 18243 % 18244 % 実際には ble/prompt/add-dependency は重複して呼び出す可能性もあるので [[ 18245 % :$version_ref: == *:'$LINENO':* ]] 等を用いて重複を排除する。 18246 18247 vim-airline の様に複数のサブプロンプトを組み合わせる形の場合には、サブプロ 18248 ンプトの version_ref を集めて判断する必要がある気がする。然し、そうすると長 18249 大な version 文字列になってしまうがそれで良いのだろうか。或いは無条件にサブ 18250 プロンプトを巡回して、その後で全体更新が必要かどうかについて判断するという 18251 のでも良い。その場合にはサブプロンプトの version 番号だけを参照する事にすれ 18252 ば良い。プロンプトのリストに登録する順序に注意する必要がある。 18253 18254 _psx_hashdef ... eval をすれば _psx_hash を計算できるパラメータ展開のコロ 18255 ン区切りのリスト。 18256 _psx_hash ... _psx_hash を eval して得られた文字列。更新を要求する場合 18257 (invalidate) にはこの変数を空にすれば良い。 18258 _psx_version ... プロンプト描画内容が変更された時に増加する番号。 18259 _psx_gdirty ... プロンプト描画内容が更新された時に 1 に設定。 18260 18261 同様に共通 hash を保持する。これが変化した時は全てのプロンプトは強制的に更 18262 新する様に仕組まれる。つまり、全てのプロンプトはこの共通 "prompt" に依存性 18263 を持つとする。この共通 "prompt" には実体が存在しない。PROMPT_COMMAND 及び 18264 PRECMD はこの仮想プロンプトに対して更新する。 18265 18266 _prompt_hashdef 18267 _prompt_hash 18268 _prompt_version 18269 18270 for p in prompt-list; do 18271 local _hash=${p}_hash _hashdef=${p}_hashdef 18272 eval "local new_hash=${!_hashdef}" 18273 [[ ${!_hash} == "$new_hash" ]] && continue 18274 18275 hashdef='$_prompt_version' 18276 18277 update.... 18278 18279 内容に変更があった && ((${p}_version++)) 18280 eval "$_hash=$hashdef $_hashdef=\$hashdef" 18281 done 18282 18283 hashdef の定義は更新時に毎回行う。最初は依存対象として $_prompt_version か 18284 ら始める。 18285 18286 function ble/prompt/reference-prompt { hashdef+=:\$${1}_version; } 18287 function ble/prompt/reference-variable { hashdef+=:\$$1; } 18288 18289 ? 全てのプロンプトを巡回しているとすると使われていないのに更新される物が出 18290 てくるのではないか。そう思うと使う物から順番に要求して、深さ優先順序で更 18291 新していく様にするべきなのではないか。その為には依存先のプロンプトの一覧 18292 を個別に保持する必要がある様な気もする。 18293 18294 hashdef=$_prompt_version:$ps1_version,$ps2_version,...:$var1:$var2:$var3 18295 18296 の様な形にして : で区切った二番目の要素を , で split して其処から依存先を 18297 抽出する様にするというのはどうだろうか。 18298 18299 ? 現在の履歴項目内部の位置など一部の物は事前に関数の実行等が必要になる気が 18300 する。その場合にはどの様に対応するのか。$(ble/history/get-index;echo 18301 $index) を埋め込むのは遅そうである。では評価の前に関数を実行するのかと問 18302 われるとそれもよく分からない。そもそも更新の必要性はプロンプト毎に固定と 18303 いう訳ではなくて、現在表示している内容に依存している。 18304 18305 或いは現在の履歴項目内の位置を常に変数で参照できる様にするべきなのだろう 18306 か。というか何故その様になっていないのだったか。 18307 18308 うーん。history コマンドの使用によって不意に履歴がロードされたり、或いは、 18309 初期化によって history がロードされたりという事を想定しての事の気がする。 18310 実の所、この手のチェックは prologue か何処かで行ってしまえば良いのだとい 18311 う気がする。 18312 18313 うーん。というか現在の履歴項目の位置というのも、read 等によって別の履歴に 18314 切り替わっている時にそれを反映するべきかというのも議論の余地がある。うー 18315 ん。_ble_history_prefix を設定する時にその辺りの更新処理も実行する必要が 18316 ある気がする。 18317 18318 後、共通の変数名をどうするのかというのも困る。_ble_history_ind 及び 18319 _ble_history_count は既にメインのコマンド履歴の為に使われてい 18320 る。_ble_history_count を例えば _ble_history_cnt に解明して、その上で新し 18321 く_ble_history_{count,index} を現在の index/count の変数とする事にすると、 18322 今度は cnt,ind との区別が分かりにくい。やはり名前空間を分けたい気がする。 18323 然し一方でコマンド履歴は特別なので _ble_history, _ble_history_edit に格納 18324 されているというのも妥当である様に思われる。 18325 18326 - reject: _ble_hist_index, _ble_hist_count というのも変である。 18327 - reject: _ble_history_current_index, _ble_history_current_count 18328 - reject: _ble_history_cur_index, _ble_history_cur_count 18329 - reject: _ble_history_prefix_index, _ble_history_prefix_count 18330 - reject: _ble_history_i, _ble_history_c 18331 - reject: _ble_history_cindex, _ble_history_ccount (common) 18332 - reject: _ble_history_gindex, _ble_history_gcount (global) 18333 - reject: _ble_history_pindex, _ble_history_pcount (prefix) 18334 - reject: _ble_history__index, _ble_history__count 18335 - reject: _ble_history_Index, _ble_history_Count 18336 - _ble_history_lineno, _ble_history_lines 18337 これだと繋がりが分かりにくい。 18338 - BLE_HISTORY_INDEX, BLE_HISTORY_COUNT 18339 これは一つの手な気がするがこれをユーザーへの公開変数とする意義はあるのか。 18340 慎重になった方が良い気がする。 18341 - _ble_history_INDEX, _ble_history_COUNT 18342 後でまた仕様変更できるのだという事を考えるとこれぐらいで良いのかもしれない。 18343 18344 ? 設定を新しく変更して別のプロンプトに依存する様になったらどうするのか。うー 18345 ん。そう考えるとプロンプト更新は順番に呼び出すというよりは、必要になった 18346 時に不定期に何度でも更新すれば良い気がする。循環参照にならない様に注意さ 18347 えしておけば特に問題はないだろうという気がする。 18348 18349 [実装] 18350 18351 * done: プロンプト周りの整理が必要になる 18352 18353 先ず ble/prompt/update はプロンプト全般の情報更新に努め、PS1 の結果は呼び 18354 出し元で必要になった時に読み出す様に変更する。 18355 18356 ble/prompt/update の結果の内 x y lc lg は後で使用されている。一方で、g 及 18357 び ret に関しては使われていない気がする。特に ret は直後に別の物で上書き 18358 されているので関係ない。 18359 18360 * ok: 変数 g を削除しても問題ないだろうか。 18361 18362 g に関しては本当の所はどうだろうか。昔の実装では、trace を実行する時に 18363 入力していた様な気もするが…うーん。やはり違うかもしれない。結局 trace 18364 は使っていないし専ら textmap, slice, etc. で使っているのみである。もし 18365 使う事があるとすれば、一番最初の文字の着色だけである。然し、着色に関し 18366 てはに layer に任されている。layer では最初の g を認識して着色を省略す 18367 る等の事はしていただろうか。と考えるとしていない気がする。そもそも 18368 prompt の終端で g を sgr0 以外にしておく必要も分からない。 18369 18370 実際に出力する場所を確認してみると必ず textarea#slice-text-buffer を使 18371 用している。そしてこの関数では必ず端点の g を読み取ってそれに対して sgr 18372 を生成して付加している。なので、prompt 終端の g が表示に影響を与えると 18373 は考えにくい。それとも highlight/layer の実装で g の値を参照する可能性 18374 はあるだろうか。うーん。外の g がどういう値になっているかは定義されてい 18375 ない筈なので参照していない筈。 18376 18377 * reject: PS0 の最後の g をコマンド列の既定着色として用いる可能性: 18378 18379 と思ったが、ユーザーがコマンドに色をつけようとしてわざと g として変な値 18380 を残しておくという事も考えられるだろうか。まあ、それに関しては余り考え 18381 ない事にする。少なくとも現在の実装では考慮に入れていないし、考慮に入れ 18382 るとしても別項目で考察するべき内容である。 18383 18384 それに既定着色を指定できる様にするとなると SGR を生成する段階で様々の修 18385 正が必要になってくる。変更として大きくなってしまうし有用性がよく分から 18386 ないのでこのままにする。そもそも色を設定したいのであれば、ble-face を用 18387 いて設定するべきであって、PS1 経由で着色をするというのは避けてもらうべ 18388 きである。 18389 18390 lc lg の計算は現在 ble/textarea#update-text-buffer 内部で実行しているがこ 18391 れは別の関数にする方が自然なのではないか→別の関数にした。 18392 18393 ble/prompt/.load は最早誰も使っていないので削除しても良いのでは→削除した。 18394 引数の詳しい説明については ble/prompt/.instantiate に移動した。 18395 18396 これ以上の整理に関しては枠組みが完成してからにするべきという気がする。 18397 18398 * 試験的に新しい枠組みを作成する 18399 18400 プロンプトを指定する番号はどの様にしたら良いだろうか。というか番号で指定 18401 できる必要はあるだろうか。考えてみればどうせ色々の変数は指定した prefix 18402 の下で変数を複数作って管理するのだった。という事を考えると実は prefix で 18403 指定すれば良いだけなのではないだろうか。取り敢えず prefix で指定する様に 18404 する。 18405 18406 一番最初は依存関係の解決等は考えずにただ単純に更新するだけの関数にしてみる。 18407 18408 * done: control-string 系全てに _data を付加する 18409 18410 * ok: dirty が個別に設定されていなくても全て再描画する必要が生じる場合も 18411 ある。というか新しいプロンプトを表示する時は常にそう。invalidate の際に 18412 全てに dirty を設定する必要がある? 18413 18414 % 普通に hashref_base (_ble_prompt_version) を確認するだけだと、プロン 18415 % プトの再計算までは行われるが内容が以前と一致した場合に再描画迄は行か 18416 % ない可能性がある。今迄は内容を再計算した時には必ず dirty が代入されて 18417 % プロンプトまで再描画していたが、今回は内容を再計算して更に変化があっ 18418 % た時にだけ dirty が設定されているので、再描画が実施されるとは限らない。 18419 18420 と思って確認したが ble/textarea#invalidate が呼び出された時には全体描画 18421 になって、その時には改めて全て描画される様である。dirty が参照されるの 18422 は一部だけ更新されている時だけである。なのでこれについては気にしなくて 18423 良い。 18424 18425 考えるに dirty は参照される時には参照されるが、参照されない時には参照され 18426 ない。何れにしても全て再描画される場合には dirty は見ずに常に再描画する仕 18427 組みになっているので問題ない。 18428 18429 * done: 変数を参照した時にそれを登録する為の関数を定義する。 18430 18431 関数名は何が良いだろうか。 18432 18433 - reject: ble/prompt/add-variable var 18434 - reject: ble/prompt/add-variable-reference var 18435 - reject: ble/prompt/add-varref var 18436 - reject: ble/prompt/reference-variable var 18437 - reject: ble/prompt/listen var 18438 - reject: ble/prompt/listen-variable var 18439 - reject: ble/prompt/hook-variable var 18440 - reject: ble/prompt/depend-on var 18441 - reject: ble/prompt/add-dependencies var... 18442 - reject: ble/prompt/cite-variable var 18443 - reject: ble/prompt/cite-var var 18444 - ble/prompt/ref var 18445 - ble/prompt/onchange var 18446 - ble/prompt/detect var 18447 - ble/prompt/cite var 18448 - ble/prompt/cite-vars var... 18449 - ble/prompt/reference var 18450 18451 a 将来的に変数以外の物を参照する可能性があるかどうかという事で var を関 18452 数名に入れるかいれないかが決まる気がする。考えて見るに eval して fork 18453 を伴わない物と言えば変数展開以外には算術式展開しか考えられない。とい 18454 う事を考えるとやはり reference で良いのではないだろうか。 18455 18456 b 或いは、"変数" である事を示唆する様な動詞が存在すればそれを使うのが良 18457 い。例えば reference と言えば変数である。 18458 18459 c というか良く考えたら追加する式を直接指定すれば良いだけの話の気がして 18460 きた。つまり、 18461 18462 - ble/prompt/reference '$var' 18463 - ble/prompt/hash '$var' 18464 - ble/prompt/add-hash '$var' 18465 - ble/prompt/add-hashref '$var' 18466 18467 うーん。add-hash が一番無難な気がする。結局内部で何をするかがこの関数名 18468 だけで分かるので。もっと分かりやすくするならば、add-update-hash 等にな 18469 るだろうか。然し短いほうが良いので add-hash にする。 18470 18471 * done: うーん。vim-airline で子プロンプトを参照する様にしたが、よく考え 18472 ると、チェックを行うのは子プロンプトを更新する前なので、子プロンプトの 18473 更新による変化を検出できない。子プロンプトの更新を実施してからチェック 18474 を行う必要がある。 18475 18476 然しここで問題になるのは、子プロンプトに渡すオプションやプロンプト文字 18477 列は事前には分からないという事。子プロンプトが存在する場合には先に子プ 18478 ロンプトを更新してから更新判定を実行する必要がある。うーん。或いは。や 18479 はりプロンプト毎に更新を行う関数を事前に登録しておくべきなのだろうか。 18480 18481 プロンプト section_a を更新する為の関数を登録することにした。 18482 18483 * done: ble/prompt/clear は個別に invalidate または自動検出にする 18484 18485 というか実は更新の必要すらないかもしれない。今となっては必ず全ての 18486 prompt について hashref のインスタンス化を試す様になっている。ここに ps 18487 も含めるべきなのではないか。 18488 18489 と思ったが、現在の実装だと ble/textarea#redraw は何も変更がないと即座に 18490 抜けてしまう様になっている。少なくともプロンプトに関しては更新を行わな 18491 いと駄目なのではないか。 18492 18493 * ble/prompt/clear の使用箇所を改めて確認する 18494 18495 ./ext/.../fzf-marks.plugin.bash:317: [[ $PWD != "$pwd" ]] && ble/prompt/clear 18496 これは \w または \W を参照している時に呼び出す事にする。 18497 他に埋め込まれている変数の場合の可能性もあるが気にしない。 18498 18499 ./keymap/vi.sh:468: ble/prompt/clear 18500 18501 これは show-mode-in-prompt の時に呼び出す物。これは変数に変える事が 18502 できるのでは。 18503 18504 ./src/edit.sh:169: ble/prompt/clear 18505 18506 bleopt_prompt_status_align の変更に伴って更新を行う。うーん。これに 18507 関しては実は prompt#update の hash に値を含めても意味がない。最終的 18508 に生成される esc が同じである以上は dirty と判定されないからである。 18509 特に left と right の切り替えに対してちゃんと処理できない。という事 18510 を考えると hash をクリアするしかない気がする。 18511 18512 結局、ble/prompt#update の内部から ble/prompt:"$prefix"/tailor とい 18513 う関数を呼び出させてその中で加工処理を行う事にした。tailor だけの 18514 invalidate として、ble/prompt#clear _ble_prompt_status tail を呼び 18515 出させる事にした。 18516 18517 ./src/edit.sh:1275: ble/prompt/clear 18518 18519 これは ble/prompt/notify-readline-mode-change である。更にこの関数 18520 の呼び出し元も調べる必要がある? 18521 18522 ./src/edit.sh:7568: ble/prompt/notify-readline-mode-change 18523 18524 これは ble/widget/safe/__attach__ から 18525 18526 ./keymap/vi.sh:7649: ble/prompt/notify-readline-mode-change 18527 18528 これは ble/widget/vi_imap/__attach__ から 18529 18530 というか本当にちゃんと更新されるのだろうか。と思った 18531 が、./keymap/vi.sh:468: ble/prompt/clear は実の所 18532 ble/prompt/notify-readline-mode-change に変えるべきなのでは? と思った 18533 が、vi.sh:468 は show-mode-in-prompt だけでなくプロンプトの表示を切り 18534 替えるのに使う物の気がする。うーん。 18535 18536 * done: ble/prompt/notify-readline-mode-change に関しては自然に変数経由で 18537 更新を検知できる様にする。関数自体を削除した。 18538 18539 x fixed: 何か入力した場合に何も表示されなくなってしまっているこれは何だろう 18540 か。恐らくこれは単に更新した時に expand gbox,bbox が解釈されていないのが 18541 原因だろう。 18542 18543 修正した。問題は発生しなくなった。 18544 18545 x fixed: 2021-06-09 history: isearch 検索を中止した時に履歴の先頭に移動する 18546 様になってしまっている。検索を開始する前の初期化に関係するのだろうか。と 18547 思ったがそうでもない様だ。履歴がロードされた後でも同様に問題が再現する。 18548 18549 これは最近発生する様になった問題である。明らかに prompt の改良に伴っ 18550 て_ble_history_INDEX の記録関係に失敗する様になっている。うーん。 18551 get-index ではちゃんと大きな値を取得する事ができている。逆に復元する時の 18552 様子を見てみると…。 18553 18554 _ble_edit_isearch_arr=([0]="29801:-:0:0:" [1]="29769:-:22:23:f" [2]="29305:-:6:8:fd" [3]="29305:-:6:9:fds") 18555 step=([0]="29801" 18556 18557 うーん。ちゃんと正しい値を読み出す事ができている気がする。という事は現在 18558 の履歴位置が間違っているという事になるのだろうか。うーん。何と、 18559 history/goto の直後に _ble_history_INDEX は空欄になってしまっている。どう 18560 いう事だろうか。 18561 18562 これは分かった。ble/history/set-index の実装で存在しない変数 (削除した変 18563 数) を参照していた。修正した。 18564 18565 * 2021-05-24 airline: 説明書を書く。theme の枠組みを整える [#D1589] 18566 https://github.com/akinomyoga/ble.sh/issues/114 (2) 18567 18568 * done: themes の枠組みを整えたい気がする。現状だとユーザーがそれぞれ対応し 18569 なければならない。面倒である。うーん。取り敢えず contrib に適当に加えてみ 18570 るというのも良い気がする。 18571 18572 * done: _modified には対応していない。 18573 18574 履歴項目については現在の内容とずれている時に modified にできる。最新項目 18575 については何か文字列があれば modified にできる→これは対応した。 18576 18577 * done: themes は自動的に変換する様にできたら良いが調べてみると面倒な気がする。 18578 18579 自動変換は vim スクリプトを書いて行った。取り敢えず themes は現状で良い気 18580 がする。mode_map も抜き出そうと思ったが実は atomic.vim しか設定している物 18581 はなかった。 18582 18583 contrib に一括で追加しようと思ったが止めて置く事にした。もっと普通のファ 18584 イルが増えてからにするのが良い気がする。或いは要求したら自動的に何処から 18585 かダウンロードするというのも手なのかもしれない。 18586 18587 * reject: テーマ用の bleopt を用意する 18588 18589 bleopt vim_airline_theme=xxxx 18590 18591 を設定したら自動で ble-import contrib/airline/xxxx を読み込む様にしたい。 18592 或いはよく考えたら直接 ble-import contrib/airline/xxxx と書けば良いだけな 18593 のではないか。 18594 18595 * 説明に関しては theme を用意してそれを見てもらえれば十分の気がする。但し、 18596 辞書に関しては theme は bash-4.1 以下でも動く様に gdict を使わなければな 18597 らずややこしい。 18598 18599 何れにしても huresche に対する返答で説明するので、その内容を後で Wiki に 18600 転記すれば良い。 18601 18602 * done: というか、考えてみたら ble-import する時に毎回 contrib まで指定する 18603 必要があるのは変な気がする。source path を指定したら其処から自由に source 18604 してもらうべきなのではないのか。 18605 18606 ble-import vim-airline 18607 ble-import core-syntax 18608 ble-import keymap-vi 18609 ble-import prompt-git 18610 ble-import fzf-bingings 18611 ble-import fzf-completion 18612 ble-import airline/landscape 18613 18614 別にこれで良い気がする。寧ろこちらの方が良い。 18615 18616 local user=${XDG_DATA_HOME:-$HOME/.local/share/blesh} 18617 BLE_IMPORT_PATH=$user:$user/lib:$_ble_base:$_ble_base/contrib:$_ble_base/lib 18618 18619 x emacs mode にいる時に vim-airline を呼び出すと真っ黒になって何も表示され 18620 ない。と思ったらこれは inactive face が使われていて、この inactive の設定 18621 が物凄く見にくいという事だった。微妙に色が見える。じれが dark.vim の設定 18622 という事なのでそのままにする事にする。 18623 18624 x 2021-06-10 ble-import の search path として ~/.local/share/blesh を追加し 18625 たが、これだと異なる version の設定ファイルが混在する原因である。そうする 18626 と不整合を生んで変な事になる。特に keymap/vi や keymap/emacs は致命的な問 18627 題を引き起こし得る。という事を考えると、 ~/local/share/blesh は直接は追加 18628 せずに ~/.local/share/blesh/local 等から読み取る様にするべきである。 18629 18630 2021-06-05 18631 18632 * locale によっては正規表現の [a-z] でも駄目 (reported by huresche) [#D1588] 18633 18634 a 一つの方法は全ての文字を [abcdefghijjklmnopqrstuvwxyz] と言った具合にして 18635 並べるという事。これは冗長である。0-9 に関しては C 言語の要求で連続に並ん 18636 でいる事が保証されているので書き出す必要はない。 18637 18638 b もう一つの方法は必要な箇所で LC_COLLATE=C を設定するという事。然し、必要 18639 になる箇所が多岐に渡る。 18640 18641 c 或いは、もう ble.sh の処理を全て LC_COLLATE で囲んでしまうというのも手な 18642 のかもしれない。と思ったが、LC_COLLATE を解除する場所でエラーメッセージが 18643 出るのを抑制しなければならない。とは言え、それはそんなに難しくない。問題 18644 は何処で LC_COLLATE で囲めば良いのかという事。ユーザーコマンドを実行する 18645 前後で切り替えれば良いのだろうか。或いは、PROMPT_COMMAND や hook を呼び出 18646 す時にも配慮しなければならないのだろうか。 18647 18648 * 取り敢えず必要な箇所がどれだけあるかについて確認する。 18649 18650 $ grc -i 'a-fa-f|a-za-z' --exclude=ext 18651 18652 で検索すると流石に沢山ある。さて、もし LC_COLLATE=C を設定するのあれば実 18653 は [:alpha:] や [:alnum:], [:xdigit:] も使えるのではないだろうか。 18654 18655 然し、何れにしても全ての箇所について個別に対応するのは難しい気がする。 18656 18657 * reject: 正規表現を使っている各箇所で LC_COLLATE=C を設定する方針 18658 18659 少し変更してみたがどうにも限界がある様な気がする。この方針は諦める事にす 18660 る。修正は memo/D1588.stub-LC_COLLATE-1.patch に残す。 18661 18662 * reject: bind/.{head,tail} 内部で LC_COLLATE を設定する方針 18663 18664 locale の設定をする時にはユーザーのロケールが壊れている場合に備えて、 18665 stderr を抑制している。然し、無闇に全体を囲んでしまうとエラーメッセージが 18666 全て隠蔽されてしまう。局所的に stderr を抑える事はできないだろうか。試し 18667 に実験してみると以下の様にすれば問題ない様だ。bash-3.0..dev まで全て確認 18668 した。 18669 18670 $ bash -c ' 18671 { LC_COLLATE=alpha; } 2>/dev/null 18672 unlocal() { unset -v "$1"; } 18673 fun() { local LC_COLLATE=fsa 2>/dev/null; unlocal LC_COLLATE 2>/dev/null; } 18674 fun' 18675 18676 この方針でも全てをカバーしきれる訳でもないので微妙である。 18677 18678 うーん。LC_COLLATE=C にする事にするか。取り敢えず内部環境では LC_COLLATE=C 18679 を強制する事にする。LC_ALL の状態も調整する。 18680 18681 * LC_ALL 待避の取り扱いについて 18682 18683 と思ったが現在の実装では LC_ALL も含めて文字コードの振る舞いを決定してい 18684 る。待避した _ble_bash_LC_ALL を使って振る舞いを変更するべきだろうか。或 18685 いは、現在の LC_ALL を使って振る舞いを決定するべきだろうか。うーん。 18686 18687 ここで問題になるのは、LC_ALL を空にしてしまうと LC_CTYPE 等他の設定に影響 18688 を及ぼすという事である。現在、local LC_ALL= LC_COLLATE=C という形で様々な 18689 箇所で待避を行っているが、これだって LC_CTYPE カテゴリの値に影響を与えて 18690 しまう。 18691 18692 a LC_ALL= を設定すると共にその他のカテゴリについても全て LC_ALL を適用す 18693 る。例えば ble/util/locale/project 的な関数を用意して、LC_ALL に有限の 18694 値が設定されている時にはそれを各 LC_* 変数に適用する。然し毎回それを実 18695 行するのは遅くなる原因である。特に変数の数だけ locale の設定が行われる 18696 と考えるとこれは避けたい。 18697 18698 b そもそも LC_ALL は ble.sh の内部では無視するという可能性。LC_ALL は何ら 18699 かのユーティリティーの振る舞いを強制する為に使う物であって、対話環境で 18700 の locale を無理矢理に変更する為に用いる物ではない。寧ろ、そういうのは 18701 LANG を通して変更するべきである。 18702 18703 c LC_ALL が振る舞いに影響を与えたとしても関知しない。これは一つの手である。 18704 LC_ALL を設定している時点で変な振る舞いをしたとしても文句は言えないとい 18705 う立場。然し、そうだとしても例えば Bash は LC_ALL を変更したからと言っ 18706 て変数名の規則が変わる訳でもないし、一貫しない動作になるのは避けたい気 18707 がする。 18708 18709 d 逆に LC_ALL の効果が ble.sh 内部で中途半端に消えたりしても文句は言えな 18710 いという立場。これは現在の振る舞いに近いと言える。 18711 18712 f 或いは射影を adjust の段階で実行するというのも手である。うーん。その方 18713 が現実的な気がして来た。 18714 18715 LC_COLLTE=C に固定してしまっても問題ないだろうか。ユーザーの側で何か気 18716 になる事が発生する可能性はあるだろうか。例えば [a-zA-Z] の振る舞いが 18717 ble.sh 内部 (PROMPT_COMMAND, etc.) で変化してしまうという影響が考えられ 18718 るが、問題になる事は少ない気がする。例えば fzf の振る舞いが変わってしま 18719 うという事も考えられるが、実のところ LC_COLLATE=C ではなくてそのロケー 18720 ルにおける collation を使う必要があるという状況が思い浮かばない。これに 18721 ついては、ロケールに従った振る舞いにしたければ実際に呼び出す側が fzf に 18722 LC_COLLATE を設定するなどしてもらうという形で良い様に考える。 18723 18724 うーん。f の方針で行く事にする。待避するとしたらどの変数を待避する必要が 18725 あるだろうか。Bash は LANG, LC_ALL, LC_COLLATE, LC_MESSAGES, LC_NUMERIC, 18726 LC_TIME に対して変更を検知している。これらに対して全てチェックを行う必要 18727 があるだろうか。 18728 18729 ? ok: ble/variable#copy-state 関数を使おうと思ったがこの関数は対象が配列 18730 や辞書である時に問題になる。要素 [0] が存在していないと配列・辞書全体を 18731 削除してしまう事になる。然し、だからと言って配列・辞書の状態も保存する 18732 となると大変である。 18733 18734 どうも bash-4.4 以降であれば unset -v 'a[0]' という具合にすれば、配列変 18735 数であれば該当要素だけ削除して、通常変数であればその変数を丸ごと削除す 18736 るという動作にする事ができる様である。うーん。という事は、 18737 18738 unset -v 'a[0]' || unset -v a とすれば良いのではないだろうか。 18739 18740 ? reject: (余談) 実は配列かどうかの判定に unset -v 'a[巨大な数]' を使う事 18741 ができる可能性? と思ったがそもそも変数すら存在していない時にも unset 18742 -v 'a[xxx]' は成功する様である。なので、変数が存在している事の確認と共 18743 に判定を実行する必要がある。然し、空配列に対して変数が存在しているかど 18744 うかをどうやって判定するのか。declare -p a として確認する必要があるので 18745 はないか。然し、宣言されているだけで unset な状態になっている場合もあっ 18746 て、その場合には declare -p a も成功してしまう。 18747 18748 * declare -p a 18749 * ((${#a[@]})), [[ ${a[@]} ]] , [[ -v a[@] ]], etc. 18750 18751 色々考えると余り有用ではない様に思われる。特に bash-4.0 以降では辞書と 18752 の区別もしなければならないので unset -v だけでは不十分である。 18753 18754 取り敢えず新しい ble/variable#copy-state を使って実装した。 18755 18756 既存の LC_ALL= LC_COLLATE=C に対する対策等はもう不要になった様な気もするが、 18757 ユーザー環境から呼び出される可能性もあるのではないかなど色々考えると、既存 18758 の対策に関しては今は残しておいて良いのではないかという気がする。 18759 18760 * vte の paste で LF が CR に化けるという話 (reported by alborotogarcia) [#D1587] 18761 https://github.com/akinomyoga/ble.sh/issues/120 18762 18763 最初の報告で自分の手許で試してみても再現しなかったが、端末について確認を取っ 18764 てみると vte であって、更に LF の代わりに CR が送信されて来ているという事が 18765 分かった。 18766 18767 いざ修正しようと思ってコードを確認したら既に workaround は入っている様に見 18768 える。と思ったが、これはあれだ。連続する CR が入っていると変換しきれていな 18769 い。修正した。多少速度が下がったかも知れないが仕方がないだろう。 18770 18771 2021-05-30 18772 18773 * util: stdin, stdout が継承されて新しい端末を開いても元端末に表示される [#D1586] 18774 18775 これは問題だ。取り敢えず inherit は基本的に止める方が良いのだろうか。 18776 指定した fd が別の fd と一致しているかどうかを判定する方法は存在するだろうか。 18777 というか端末 tty の結果が変わったら継承しないという具合にするのが良い気がする。 18778 端末 tty を取得する方法はコマンド tty を実行するしかないのだろうか。 18779 18780 というか別に現在の 0 が端末であれば普通に上書きすれば良い気がする。 18781 その様に修正した。 18782 18783 * decode: Kitty の modifyOtherKeys でまた問題が生じている (reported by lyiriyah) [#D1585] 18784 https://github.com/akinomyoga/ble.sh/issues/118 18785 18786 報告によるとコマンドを実行する前には ESC は ESC としての用を為さないという 18787 事の様である。そしてコマンドを実行すると動く様になるという事。 18788 18789 手許で Kitty で試してみた所再現した。modifyOtherKeys を internal/external 0 18790 に設定すると問題は再現しない。internal 2 にすると再現する。internal 1 に設 18791 定すると問題が発生してしかもコマンドを実行しても直らない。 18792 18793 どうも Kitty で 2 に設定すると一回は modifyOtherKeys が有効になるが、それ以 18794 降は modifyOtherKeys は無効化される? 或いは 2 に設定しようとしても何も起こ 18795 らないという事だろうか。うーん。2 に設定しようとしても何も起こらないという 18796 事の様である。然し、それならば不思議なのは ble.sh は 4;2 を設定する前に 4;1 18797 を送信する様にしているという事。それなのに 4;2 の効果がないというのは不思議 18798 な事である。実際に手許で試してみても 4;1 に設定して 4;2 に設定すると、4;1 18799 に設定したのと同じ状態になる。 18800 18801 問題は二種類ある 18802 18803 * Kitty で \e[>4;1m の時に送信されるキーシーケンスが ble.sh で認識されてい 18804 ない。実際に試してみると ESC を押した瞬間に何かしら送信はされている様であ 18805 る。 18806 18807 これに関しては具体的に何が送信されているのかを確認する。 18808 18809 keylog で調べてみると "ESC [ 2 7 u" を送信して来ている。decode.sh を確認 18810 したがちゃんと認識している。と思ったが isolated ESC ではなくて modifier 18811 ESC として認識されている気がしてきた。調べてみた所、以下の様な流れで処理 18812 される事になり、modifier ESC になってしまう。 18813 18814 ble-decode-char 18815 ble-decode-char/.getent 18816 ble-decode-char/csi/consume 18817 ble-decode-char/csi/.decode 18818 csistat 設定 18819 csistat を ent にコピー 18820 ble-decode-char/csi/clear 18821 ble-decode-char/.send-modified-key "$ent" "$seq" 18822 此処で $1 == 27 の時に 18823 ble-decode-char/.process-modifier Meta を呼び出している。 18824 18825 csi で受信した文字が 27 の場合には IsolatedESC として処理する事にした。特 18826 に CSI シーケンスの処理結果として得られた 27 が modifier ESC になる事はあ 18827 り得ない気がするので csi/.decode の戻り値に対して一括で処理する事にした。 18828 18829 * Kitty で 2 に復帰した時に \e[>4;0m の状態になっている気がする。 18830 \e[>4;1m\e[>4;2m で 2 に設定している筈なのに不思議である。手許で自分で設 18831 定するとちゃんと 4;1 の状態になっている。 18832 18833 次の問題はこれである…。実際に確かめてみると、そもそも有効化の 4;1; 4;2 18834 の所に入っていない様だ。確認してみると 18835 ble/term/modifyOtherKeys/.supported が false になっている。更に調べると 18836 _ble_term_TERM が vte になってしまっている。 18837 18838 DA2R を見て判断する事にする。Kitty の DA2R は一体どういう形式なのだろう。 18839 調べると以下が該当するコードである。 18840 18841 ./kitty/screen.c:1460: write_escape_code_to_child(self, CSI, ">1;" 18842 xstr(PRIMARY_VERSION) ";" xstr(SECONDARY_VERSION) "c"); // VT-220 + 18843 primary version + secondary version 18844 18845 そしてこれらの値は setup.py に於いて 18846 18847 constants = os.path.join('kitty', 'constants.py') 18848 version = tuple( map(int, re.search( r"^version: Version = 18849 Version\((\d+), (\d+), (\d+)\)", constants, re.MULTILINE ).group(1, 2, 3) 18850 )) 18851 cppflags.append('-DPRIMARY_VERSION={}'.format(version[0] + 4000)) 18852 cppflags.append('-DSECONDARY_VERSION={}'.format(version[1])) 18853 18854 という具合にして初期化されている。kitty/constants.py には以下の様な行がある。 18855 18856 version: Version = Version(0, 19, 3) 18857 18858 どうも Kitty の version は永年 0 の様だ? 取り敢えず適当に kitty 用の判定 18859 条件を追加する事にした。 18860 18861 2021-05-29 18862 18863 * syntax: \? を着色したい [#D1584] 18864 18865 色は magenta で良い。\q が現れる箇所はコマンド、"..." である。それぞれ規則 18866 は異なる。特に後者については規則が分かりにくいので色を付ける対象にしたい。 18867 18868 $'...' も別枠で着色する様にしたい。これもちゃんと実装した。これで 18869 $'...' を書く時にどのようなシーケンスが有効でどの様なシーケンスが 18870 無効か分かる。所で bash version 依存性はどうなっているのか確認する 18871 必要がある。 18872 18873 * complete: quote されているコマンド名に対しても補完関数を適切に探索 [#D1583] 18874 18875 quote していると補完関数が認識されない。例えば git co とすると OK だが 18876 'git' co とすると反応しない。然し実の所、これは普通の bash でも同様である。 18877 普通の bash でも 'git' としている時には git の補完関数は呼び出されない。 18878 18879 unquote した上で補完を探索するべきである気がする。但し、alias 展開などに関 18880 しては quote された物で実行するという事。comp_line, comp_words に入っている 18881 のは展開前の quote された物であるので余計な事は考えなくて良い。 18882 18883 * [reject] complete: そもそも -F に指定する事のできる文字列には制限がある筈である [#D1582] 18884 18885 これを満たさない場合には強制的に其処で終端させる等の対策が必要なのではない 18886 か。 18887 18888 然し、;&| 等が含まれていた場合にどの様に取り扱うべきかは不明である。明らか 18889 に何かが間違っているけれども、だからと言ってその直前までを関数名と捉えるの 18890 にも無理がある様な気がする。然し、それ以外に解釈のしようがないとも言える。 18891 18892 或いは途中に空白がある場合には ble.sh の拡張として関数に余分の引数を渡す事 18893 にする? 然し、これは最新の bash-5.1 では使えない事なので古い Bash だけで使 18894 える機能として提供しても仕方がない。結局これは失敗するべきなのではないか。 18895 そして失敗するのだとしたら現状の動作のままで良いという事の気がする。 18896 18897 * complete: alias の展開結果で変数代入を除去するべきではないか [#D1581] 18898 18899 というより実の所 simple-word でできるだけ解析していくべきの気がする。と思っ 18900 たが、 ; や変数代入があった時の振る舞い、文法エラーがある場合の振る舞いなど 18901 は用途によってまちまちなのでこんk内は core-complete.sh の側で実装する事に 18902 した。 18903 18904 simple-word の終端しない版というのはあっただろうか。なかったが 18905 simple_rex_element をそのまま使えば良い。 18906 18907 * __load_completion を呼び出すと -D に相当する処理が勝手に入ってしまう。 18908 complete が駄目な気がする。自前で補完定義を探してロードする関数を作ってみ 18909 たが、その後で気づいたのは __load_completion は別に見つからなかった時に勝 18910 手に既定の定義を使う訳ではないのだという事。 18911 18912 以下の自前の定義は結局使われる事はないのだった。 18913 18914 | _ble_complete_progcomp_bashcomp_initialized= 18915 | _ble_complete_progcomp_bashcomp_dirs=() 18916 | function ble/complete/progcomp/.bashcomp-initialize { 18917 | if [[ ! $_ble_complete_progcomp_bashcomp_initialized ]]; then 18918 | _ble_complete_progcomp_bashcomp_initialized=1 18919 | 18920 | local user repo bin 18921 | user=${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion/completions 18922 | [[ $BASH_COMPLETION_USER_DIR ]] && user=$BASH_COMPLETION_USER_DIR/completions 18923 | ble/string#split repo : "${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" 18924 | bin=./completions 18925 | [[ $BASH_SOURCE == */* ]] && user=${BASH_SOURCE%/*}/completions 18926 | 18927 | local path 18928 | for path in "$user" "${repo[@]}" "$bin"; do 18929 | [[ -d $path ]] && ble/array#push _ble_complete_progcomp_bashcomp_dirs "$path" 18930 | done 18931 | fi 18932 | } 18933 | function ble/complete/progcomp/.load-bash-completion { 18934 | local cmd=$1 18935 | ble/is-function __load_completion || return 1 18936 | ble/complete/progcomp/.bashcomp-initialize 18937 | 18938 | local dir file 18939 | for dir in "${dirs[@]}"; do 18940 | for file in "$dir"/{"$cmd","$cmd.bash","_$cmd"}; do 18941 | [[ -s $file ]] || continue 18942 | source "$file" 18943 | return 0 18944 | done 18945 | done 18946 | 18947 | ((_ble_base>=40000)) || return 1 18948 | ble/is-function _filedir_xspec && 18949 | [[ ${_xspecs[$cmd]+set} ]] && 18950 | complete -F _filedir_xspec "$cmd" 18951 | } 18952 18953 * complete: "\a" 等のコマンド名の補完で問題が起こる (reported by huresche) [#D1579] 18954 https://github.com/akinomyoga/ble.sh/issues/116 18955 18956 [原因] 18957 18958 | bash_completion との関連でまた問題が起こっている。最新の bash_completion で 18959 | 再現する事ができた。 18960 | 18961 | 何れにしてもこれは bash とのインターフェイスの違いなので修正されるのは 18962 | ble.sh の方であろう。そして文面を読む限りは "minimal ''" という名前のコマン 18963 | ドを呼び出そうとしている? これは parse の問題の様な気もするが…。取り敢え 18964 | ず何が起こっているのか調べる。 18965 18966 結局これは ble.sh の側の問題であった。再現条件は bash-5.1 である。 18967 bash_completion では何故か空文字列に対するコマンドでも complete -F _minimal 18968 '' を登録する様で、しかも bash-5.1 から complete -p の出力の形式が変化した 18969 事によって ble.sh が -F の解析に失敗して問題が露呈したという事になる。 18970 18971 | * "a" では発生しない。"\a" や "$$" では発生する。 18972 | 18973 | 取り敢えず再現しているので何が起こっているのか調べる事にする。 18974 | 18975 | % うーん。どうやら。simple word じゃない時にコマンド名を決定できず、結果と 18976 | % して空のコマンド名に対して補完が呼び出されているという形になる。うーん。 18977 | % この場合にはどうするのが良いだろうか。もう直接 simple-word でない内容を転 18978 | % 写する? うーん。それも一つの手である。 18979 | 18980 | と思ったが、そうでもない様である。例えば "$$" というのは simple-word である。 18981 | 改めて何で空になるのか確認する必要がある。 18982 | 18983 | "\a" は展開されて \a になるがそれにより補完は最終的に失敗する様だ更に引き続 18984 | き \\ による補完が呼び出されてそれが evaluate されて \ になる等している。然 18985 | し、"$$ の場合には数字に展開されて、その後で曖昧補完の為に一文字目 "1" の数 18986 | 字を使って補完されるという事が起こっている。それでもエラーは発生している。 18987 | 18988 | 不思議なのは普通に 1 として入力しても問題が生じないという事。というか、やは 18989 | り COMP_WORDS が空になってしまっているのが問題なのだという気がする。 18990 | 18991 | ? そもそも最初のコマンド名でない場合でも、simple-word でない場合には補完は 18992 | どうなっていただろうか。 18993 | 18994 | →少し分かった。generate-subwords が5回実行されていて '$$', '', '1', '1', 18995 | '' となっていて問題のエラーは空文字列で呼び出された時に発生している様である 18996 | という事。遡って見るとそもそも compgen-helper-func 自体もその様に呼び出され 18997 | ているという事が分かった。ble/complete/progcomp/.compgen もその様に呼び出さ 18998 | れている。 18999 | 19000 | ? うーん。不思議なのは "a" 等の普通の表記の時にはその様な事がないという事で 19001 | ある。何故だろうか。調べてみると普通の場合でもちゃんと空文字列による補完 19002 | が呼び出されている。そもそもこの空の状態での補完の要求が一体何故呼び出さ 19003 | れているのかという疑問は残るが、現在発生しているエラーメッセージとは関係 19004 | がないという事だろうか。 19005 | 19006 | 然し空の文字列になる場合を除外してみるとちゃんとエラーメッセージなく補完 19007 | が実行される様である。 19008 | 19009 | ? ok: 何故空の文字列で補完 compgen が呼び出されているのだろうか。 19010 | 19011 | これは曖昧補完で -I による補完を試みているからである。 19012 | 19013 | ? done: 何故普通のコマンド名の場合には空の文字列で補完が呼び出されても問題 19014 | が発生していないのか。何故特定の文字列の時にのみエラーメッセージが発生す 19015 | るのだろうか。 19016 | 19017 | | うーん。不思議な事だ。どうも調べると compdef に変な文字列が入ってくる。つ 19018 | | まり complete -p 自体が予期しない内容の文字列を出力しているという事だろう 19019 | | か。 19020 | | 19021 | | うーん。どうやら空文字列で呼び出されるのは曖昧補完の為に -I でコマンド名 19022 | | を保管しようという時の話であって。然し、何故か文字列の種類に応じて -I で 19023 | | 呼び出されたり或いは直接コマンド名で呼び出されたりというのが変化している 19024 | | という様子。もっとちゃんと書くと何故か文字列の種類によって initial が付け 19025 | | られずに compgen が呼び出されるという事。 19026 | | 19027 | | やはり initial なしで呼び出されるというのは変だ。initial がないという事は 19028 | | コマンド引数としての補完を要求している事に他ならない。然し、空文字列での 19029 | | 補完なのにそれは起こり得ない筈である。呼び出し元を確認する必要がある。調 19030 | | べてみると何故か "$$ の時には source:argument が生成されているのだという 19031 | | 事が判明した。一体どういう事なのだろうか。source:command は一切生成されて 19032 | | いない。うーん。syntax の context 生成が怪しいという事になるだろうか。 19033 | | 19034 | | 生成された source を確認してみると declare -a sources=([0]="argument 0") 19035 | | が生成されている。うーん。つまり、core-syntax.sh に於いて単語内部の nest 19036 | | した文脈からだと argument が生成されてしまうという事である。 19037 19038 "..." の内部の nest した文脈ではそれがコマンド名か引数内部かに関係なく 19039 argument が生成されてしまうのが原因だった。 19040 19041 確認してみると以下の関数で argument 決め打ちにしている。 19042 ble/syntax/completion-context/.check-prefix/ctx:quote/.check-container-word 19043 19044 判定の為に nest に登録されている単語情報を確認しているが不思議である。 CMDX 19045 や ARGX になっている。CMDI や ARGI ではないのだろうか。特に nest が始まった 19046 のが単語の途中であっても CMDX や ARGX になっている。 19047 19048 > function ble/syntax:bash/ctx-command/.check-word-begin { 19049 > if ((wbegin<0)); then 19050 > local octx 19051 > ((octx=ctx, 19052 > wtype=octx, 19053 > ctx=_ble_syntax_bash_command_BeginCtx[ctx])) 19054 19055 うーん。この部分を見ると wtype は単語が始まった瞬間の文脈を保存している。 19056 19057 > function ble/syntax:bash/ctx-command/check-word-end { 19058 > # 単語の中にいない時は抜ける 19059 > ((wbegin<0)) && return 1 19060 > 19061 > # 未だ続きがある場合は抜ける 19062 > ble/syntax:bash/check-word-end/is-delimiter || return 1 19063 > 19064 > local wbeg=$wbegin wlen=$((i-wbegin)) wend=$i 19065 > local word=${text:wbegin:wlen} 19066 > local wt=$wtype 19067 > 19068 > [[ ${_ble_syntax_bash_command_EndWtype[wt]} ]] && 19069 > wtype=${_ble_syntax_bash_command_EndWtype[wt]} 19070 19071 更に此処で _ble_syntax_bash_command_EndWtype を用いて最終的に記録する wtype 19072 に変換している。という事は実際の判定でも _ble_syntax_bash_command_EndWtype 19073 を参照するべきである。 19074 19075 [修正] 19076 19077 * done: compcmd が空文字列の時に bash は '' を出力する。つまり微妙に quote 19078 するという事。 19079 19080 $ complete -o bashdefault "''" 19081 $ complete -o bashdefault '' 19082 $ complete -p 19083 19084 試した見た限りでは空文字列の時にだけ '' と出力してそれ以外の場合には直接 19085 出力する様である。これについては一つ対策を入れる必要がある。これは他の問 19086 題を修正してから取り掛かる。 19087 19088 * util (assign): Cygwin で assign 一時ファイルの衝突が発生している様だ [#D1578] 19089 19090 assign 一時ファイルに BASHPID を付加する様にしたら特に問題は発生しない様子。 19091 なのでやはり assign 一時ファイルの衝突なのだろうと思われる。実際に保存され 19092 たファイル名を観察するとやはり衝突が起こっているかも知れない。 19093 19094 特に頻繁に起こるのは background シェルと親シェルに於ける 19095 ble/function#getdef なのだろうという気がする。取り敢えず、ble/util/assign 19096 におけるファイル名の確保を関数に纏める事にする。 19097 19098 呼び出し元を出力して調べてみた所、そもそもサブシェル内部から呼び出しが発生 19099 しているのは ble/bin/awk の初期化のみの様であった。ble/bin/awk を、 19100 ble/util/assign が設定されてから即座に初期化する様に修正してみた所、 19101 subshell 内部からの ble/util/assign は全く発生しなくなった。 19102 19103 * 他に気になることとしてはファイルの中身が残ってしまっているという事。 19104 19105 dec する場所で一緒に clear する事も考えてみたが、実際に実装を見てみると一 19106 時ファイルの中身を呼び出す前に dec している。読み出し中にエラーがあって中 19107 断した時の事を考えてだろうか。然し、実行が中断してしまう程のエラーが起こ 19108 る状況が分からない。set -ue は off にしているし failglob は起こりようがな 19109 い。なので、dec の位置を変更して dec と一緒にファイルのクリアも行う様にす 19110 るというのは一つの手である。 19111 19112 特に大量のデータがある場合にはやはりファイルの中身をクリアするのが望まし 19113 い。これで多少パフォーマンスが落ちてしまうかもしれないが、問題になりそう 19114 なのは初期化ぐらいの物であって、初期化の場合には色々他にも bottleneck が 19115 あるだろうという事で余り気にしない事にする。いざ初期化時間を縮めようと思っ 19116 たらまた何か別の初期化を遅延させる事にするのが良い。何れにしてもプロファ 19117 イリングした上で決める事である。 19118 19119 取り敢えず今の所はファイルの中身は消去する事にする。 19120 19121 対策は取り敢えずそれでよしという事にする。 19122 19123 2021-05-28 19124 19125 * ble-reload した時に alias が無効になってしまう [#D1577] 19126 19127 何故だろうか。そもそもshopt -u する様な事はない…と思ったが、うーん。これは 19128 単純なミスである。 19129 19130 * history: bash-3.0 で履歴の数が減少していく問題が再発している [#D1576] 19131 19132 これは対策をした筈なのに何故だろうか。 19133 19134 取り敢えず対策コードにちゃんと進入しているのかどうかだけでも確認する。 19135 19136 再現条件が分かった。bashrc からロードしていると発生しないが、コマンドから 19137 source して attach すると発生する。bash-3.1 では再現しない。 19138 19139 該当箇所で確認したがちゃんと復元できている様な気がする。history -p で検索し 19140 てみたらもう一箇所別の場所で呼び出している。其処の判定条件を確認すると 19141 bash-4.0 未満の場合には無条件でサブシェルで実行している様に見える。と思った 19142 がよく見たら _ble_bash となるべき所が _ble_base になってしまっている。 19143 19144 然し、そもそもサブシェルの判定は ((BASH_SUBSHELL)) で判定できるのでこんなに 19145 複雑な式を用いる必要はない。 19146 19147 * done: 算術式の中で誤って _ble_base を使ってしまうという事が余りに多いので 19148 これも make_command.sh に登録しておくのが良い気がする。登録した。 19149 19150 $ grc '\(\(.*\b_ble_base\b.*\)\)' 19151 19152 他には同じミスをしている箇所は存在しなかった様である。 19153 19154 * main: set -u で壊れていないか久しぶりに確認する必要がある気がする [#D1575] 19155 19156 試してみたら沢山のエラーが発生している。というか本来 set +u で待避している 19157 筈なのに何故こんなに沢山のエラーが発生しているのだろうか。不思議である。 19158 一通り attach する迄の部分を修正していったが実は必要なかった。 19159 19160 何故 set +u できていなかったのかというとそもそも adjust-bash-options 自体の 19161 guard で未定義の変数を触っていた為に、adjust-bash-options が実行されていな 19162 かったのが原因だった。それを直したら普通に動く様になった。 19163 19164 * main: expand_alias の設定を変えるのはやはり良くない [#D1574] 19165 19166 現在 ble.sh の内部では完全に alias を無効化しているが、そうすると blerc の 19167 中で alias を使っている場合に対して影響が出るのではないかという気がする。そ 19168 の場合には関数を使う様に指示する事もできるが、やはり alias が使えないという 19169 のは特殊な気がする。 19170 19171 特に何らかのフレームワークを介して意図的に alias を使って様々の事を実現して 19172 いるという場合も考えられる。そういう事を考えると alias を何もかも動かなくし 19173 てしまうのは違う様な気がする。 19174 19175 うーん。expand_aliases が影響を与えるのは主に ble.sh のロード時であって、ロー 19176 ドが完了した暁には殆ど影響はない? 然し、実際には沢山の eval を使っていて 19177 eval は影響を受ける。特にキーワードや builtin に名前が一致する様な alias に 19178 関しては対策を行っている。その他に影響を与える様な変な alias を設定している 19179 人がいたとしたらそれはその人が悪いのであって、ble.sh の関知する所ではないの 19180 ではないか。という事を考えるとやはり alias は有効のまま処理するべきの様な気 19181 がする。 19182 19183 一応 expand_aliases の adjust を導入した時の議論を確認して問題がないか考え 19184 る。該当する議論は #D1519 にある。関連する問題として #D1526 があった。改め 19185 てこれについて考え直すのが良い。 19186 19187 * 少なくとも adjust builtins をした後には expand aliases は必要ないのではな 19188 いかという気がする。或いは、adjust builtins で待避する alias の数を増やす 19189 必要がある気もするが。 19190 19191 これの修正は簡単だった。他に影響が現れるとも思いにくいが一応確認はしておく 19192 事にする。 19193 19194 と思ったらやはり単純ではない様だ。どうやら alias の状態が bind -x を跨いで 19195 戻ってしまうのは shopt -u expand_aliases している時だけの問題ではなくて、 19196 shopt -s expand_aliases だった時にも同様の様である。なので、やはりユーザー 19197 の側でどういう状態になっていたのかという事を記録・復元する必要がある。 19198 19199 * ble-sabbrev の初期化遅延で内容出力迄も遅延されている (bash-3.*) [#D1573] 19200 19201 ble-sabbrev の初期化を遅延しているが、内容確認の為の ble-sabbrev ですら遅延 19202 されて、ロードした時になってから内容が出力される。この振る舞いは修正するべ 19203 きである。然し、これを検出する為には、ble-sabbrev の一時実装の側で引数を解 19204 析する必要がある。 19205 19206 2021-05-27 19207 19208 * canvas: 変数リークしている (buff, trap, {x,y}{1,2}) [#D1572] 19209 19210 buff, trap は直ぐに見つかったが x1,x2,y1,y2 は使っている所が多いと思われる 19211 ので探すのは面倒である。とは言え特にプロンプト関係が怪しいと思われる。 19212 19213 結局 x1,x2,y1,y2 は trace 自体が駄目だった。justify の初期化位置よりも後で 19214 local x1 x2 y1 y2 が宣言されていたのだった。然し、この justify の初期化位置 19215 は此処でなければならなかったのか。そういう理由があった様な気もするがこれに 19216 ついてはテストで確認する必要がある様に感じている。contra によるテストを設定 19217 して確認する必要がある。contra でテストを実行してみた所、特に問題なくテスト 19218 が通った。なのでこの部分の順序変更については気にしなくて良いだろう。 19219 19220 * 新しい ble-face, blehook, bleopt で問題が起こっている [#D1571] 19221 19222 * fixed: blehook で新しい hook を作成できなくなっている。何故だろうか。これ 19223 は引数解析のバグである。 19224 19225 * fixed: ble-face --hel でエラーにならずにコマンドを実行することができてい 19226 る。これは修正した。他にも '-' に対する処理を blehook, bleopt と共に修正 19227 した。 19228 19229 * fixed: ble-face --color=xxxx のエラーメッセージ表示時にエラーが発生する。 19230 直した。blehook, bleopt についても --color=xxxx と指定した時のエラーメッ 19231 セージを改善した。 19232 19233 * done: ble-face の使い方を wiki にまとめる 19234 * done: --help に color の説明を含める。 19235 19236 * bash-3.0 の初期化時に bleopt が出力されてしまっている [#D1570] 19237 19238 % bash-3.1 では特に問題は起こっていない。という事はまた何かの bash bug に嵌っ 19239 % ているのか或いは場合分けのコードで bash-3.0 専用の部分に問題があるのか。 19240 % 19241 % --norc で source すると問題は起こらない。後で source ~/.blerc すると再現 19242 % する。同じセッションで再度呼び出せば再度発生する。これも解析のバグである 19243 % 様な気がする。不思議な事に一回目と二回目で起こる bleopt の位置が異なる。 19244 % 或いは、起こる回数が変わっているという事か。 19245 % 19246 % どうやら bleopt a:=1 という形で呼び出すと read-arguments の結果が空になる 19247 % 様だ。調べるとスカラーに対して ${var[@]/%/=value} 等とすると失敗する様だ。 19248 19249 これはまた bash-3.0 のバグである。うーん。調べた限りだと、 19250 ${scalar[@]/xxxx} の形式は全て空になる。 19251 19252 $ grc '\$\{[a-zA-Z_0-9]+\[[*@]\]/' 19253 19254 で検索してみるとそんなに沢山は存在しない。取り敢えず全て確認 or 対策をする 19255 必要がある。また、m scan に含めるべきである。 19256 19257 * 確認した所、既存のコードは全て配列に対して異実行していたので問題ない 19258 * m scan にも含めた。 19259 19260 x local i "${vars[@]}" に変更漏れがあった。これも後で修正する。 19261 19262 * 後これは遡って適用するべき項目である。なので独立した項目にする事にする。 19263 19264 * util: gdict 再考 [#D1569] 19265 19266 gdict について質問された。説明しようとして思ったのだが、現在の gdict の実装 19267 は ble.sh の中で直接 global dictionary を作る時を想定していて、module の中 19268 から global dict を作る場合は想定していないのだった。bash-4.0 で関数内から 19269 source した時には問題が生じる事になる。 19270 19271 gdict はもっと一般に使う事ができる様にしたい。つまり、必ずしも直接 source 19272 した所から使うのではなくて、一般のスクリプトから使える様にしたいのである。 19273 そう思うと gdict は bash-4.2 以上でのみ使う事にして、それとは別に ble.sh 内 19274 部から使う為の gdict を定義するべきなのではないか。 19275 19276 うーん。でもグローバルに何かを定義するのは常にグローバルであるという想定は 19277 妥当な仮定だという気もする。という事を考えると gdict は現在の実装でも良い気 19278 がする…と考えたが、もしグローバルな文脈でちゃんと定義できるのであればわざ 19279 わざ gdict を使わなくても dict を使えば良いのだという事になる。 19280 19281 * 此処で改めて gdict の存在意義について考えてみると、"関数内で source され 19282 た場合にもグローバルに辞書を宣言したい" という事にある。 19283 19284 a 一つの方法は何処から source された時にも使える様に 4.2 以上でのみ本当の 19285 辞書にしてそれ以外では配列実装に切り替えるという方法。 19286 19287 b 然し、何処かに辞書ごとの実装の種別を記録しておいて、その種類に応じて辞 19288 書実装を切り替えるというのも一つの手である。然し、そうすると複数の変数 19289 に記録する事になってしまうので何だか変な感じがする。 19290 19291 現在の辞書の実装ではキーを x$key にしているので、他の要素は特殊用途の為 19292 に使う事ができる。つまり、要素 0 に種別を格納しておくという事も可能であ 19293 る気がする。然し、配列実装の側では要素 0 はちゃんと意味のある要素として 19294 使っているので其処を変えるのは変な気がする。 19295 19296 或いは、毎回 is-array を呼び出すという手もあるのかもしれないと考えたが、 19297 問題の bash-4.0, 4.1 では is-array の判定に assign を使っているので、辞 19298 書のアクセスの度にファイルの読み書きが発生する事になって気分が悪い。 19299 19300 c 或いは、bash-4.0, 4.1 の時にだけ実装種別の判定を行う様にすれば良いので 19301 ある。 19302 19303 またこの方法の場合には宣言時に [[ $FUNCNAME ]] 等を確認して宣言を切り替 19304 える必要がある。 19305 19306 % if [[ $FUNCNAME ]]; then declare -gA X; 19307 % 19308 % x もう一つこの方法の弱点。この方法では FUNCNAME が期待通りに動く事を想 19309 % 定している。然し、ユーザーが unset FUNCNAME をしてしまっていると 19310 % FUNCNAME は常に存在しない事になってしまい、誤判定してしまう。実は 19311 % FUNCNAME がちゃんと動作しているかどうか確認する為には一回関数を呼び出 19312 % して要素数が変化するか見れば良い。 19313 % 19314 % % 類似の変数として FUNCNAME, BASH_LINENO, BASH_SOURCE が存在する。で 19315 % % は、これらの変数が全て使用不能になっていたらどうすれば良いのだろう 19316 % % か。(改めて確認した所、BASH_LINENO 及び BASH_SOURCE は関数呼び出し 19317 % % でなくても常に存在している様である。そして source の場合にも要素の 19318 % % 数が変化する。という事を考えると関数内かどうかの判定には使えない気 19319 % % がする) 19320 % 19321 % b BASH_LINENO/BASH_SOURCE を使って判定する事は可能だろうか。実際に呼 19322 % び出してみてどの様に動作するか確認する必要がある。うーん。両者とも 19323 % ファイル名と行数しか表示しないので関数かどうかの判定には全く使えな 19324 % い。 19325 % 19326 % c その場合には、caller builtin を使う事ができるだろうか。と思ったがこ 19327 % れも駄目の気がする。これは関数であるかどうかに拘らず実行することの 19328 % できる関数なので、結局関数内にいるかどうかを判定するのには使えない。 19329 % 19330 % caller の出力を確認すれば一応 "関数名" or "source" を確認する事がで 19331 % きる。此処で、"source" 以外の関数名があった時には関数内にいるという 19332 % 事は確定する。逆に全て "source" だった時にはどうだろうか。取り敢え 19333 % ず自分がトップレベルから source されている場合には caller 0 が失敗 19334 % する。この場合には "関数内にはいない" という事が確定する。 19335 % 19336 % d reject: 或いは実際にその context で変数を定義してみたら良いのではな 19337 % いだろうか。と思ったが、それも駄目である。関数内でもし呼び出されて 19338 % いるのだとしたら、結局その関数の文脈にローカル変数が作られるので、 19339 % 確認する立場からすれば何れにせよ変数が見える事になる。問題は現在の 19340 % 文脈 (外側の関数) を抜けた時に自分の手元で定義した変数がちゃんと残 19341 % 存するかどうかという事なのである。 19342 % 19343 % e declare xxxx としてから local で変数が存在するかどうか確認したら分 19344 % かるのではないか。 19345 % 19346 % f よく考えたら local が成功するか失敗するかで確実に判定可能なのではな 19347 % いか。これだ。これで判定する事ができる…。local が別の理由で失敗 19348 % する可能性としてその変数名が特殊変数であったり読み取り専用だった 19349 % り型が変換不能だったりという事が考えられるが、_ble_... に選んで置 19350 % けば特に問題はない。 19351 % 19352 % [source スクリプト内で関数内にいるかどうかの判定方法] 19353 % 19354 % 先ず初めに FUNCNAME が特殊な意味を保持しているかどうかを確認する。これ 19355 % は実際に関数を呼び出してその中で FUNCNAME の要素数が増えているという事 19356 % を確認すれば良い。もし特殊な意味を保持している場合には、FUNCNAME が定義 19357 % されていれば関数内にいるし、或いは FUNCNAME が定義されていなければ関数 19358 % 内ではない。 19359 % 19360 % 次に caller の出力を確認する。caller 0 が失敗すれば即ちトップレベルから 19361 % 直接 source された事を意味しているので、確実に関数外に存在する。caller 19362 % 0,1,2 を失敗するまで逐次呼び出して行って、途中で source 以外の関数名に 19363 % 出会ったら関数内部にいる事が確定する。 19364 19365 local _ble_local_test とでもしておけば関数内部にいるかどうかの判定は可 19366 能である。というか、現在 FUNCNAME を使って実行しているテストもこれに切 19367 り替えるべきなのではないか。 19368 19369 bash-4.2 以上の場合、常に -gA を使う。 19370 bash-3.2 以下の場合、常に配列を使う。 19371 bash-4.0, 4.1 の場合は条件分岐する。 19372 19373 if local _ble_local_test 2>/dev/null; then 19374 NAME=() NAME_keylist= 19375 else 19376 declare -A NAME; NAME=() 19377 fi 19378 19379 その様に書き換えた。 19380 19381 * done: 既存の連想配列に依拠しているコードも、実際に配列が連想配列かどう 19382 かで判定するべきの気がする。 19383 19384 現在は _ble_bash_loaded_in_function で判定を行っている。というか面倒な 19385 ので一部の物に関しては完全に gdict を使った実装に切り替える事にした。3 19386 つ書き換える事になった。 19387 19388 - _ble_decode_kbd__k2c 19389 - _ble_builtin_history_rskip_dict 19390 - _ble_builtin_trap_n2i 19391 19392 _ble_bash_loaded_in_function を使っていても gdict による宣言を使ってい 19393 ない物に関してはそのままにする事にした。 19394 19395 残っている物は以下の物である。うーんこれらも書き換えてしまうべきだろう 19396 か。そちらの方が正直な所メンテナンスしやすい。問題は書き換えでバグが入 19397 らないかという事と、速度的に遅くならないかという事である。特に、現在の 19398 主なターゲットは bash-4.4 以降であると考えると、古い実装に対して配慮し 19399 なくても良い様に思われる。 19400 19401 - ./lib/core-complete.sh:6102:if ble/is-assoc _ble_complete_sabbrev; then 19402 - ./lib/core-syntax.sh:6290:if ble/is-assoc _ble_syntax_highlight_filetype; then 19403 - ./lib/core-syntax.sh:6403:if ble/is-assoc _ble_syntax_highlight_lscolors_ext; then 19404 19405 取り敢えず使われている箇所で速度が気になるかどうかを確認する。結局全部 19406 新しい実装に置き換える事にした。bash-4.2 以上であれば単に関数呼び出しコ 19407 ストと、要素が実際に存在しているかどうかの判定コストが増えるだけである。 19408 結局 s2c のテーブル以外については全て完全に gdict を使う事にした。 19409 19410 * done: sabbrev の書き換えの際に ble/gdict#keys を使った。 19411 実装する必要がある。実装した。 19412 19413 * done: 現在の辞書の中身を表示する為の関数、key の列を取得する為の関数もあっ 19414 た方が良いのではないかという気がする。 19415 19416 ble/gdict#keys については既に上で実装した。 19417 ble/gdict#print については既存の関数を使って実装する事にした。 19418 19419 * 後、bash-4.0, 4.1 で既に連想配列として宣言されている場合にはそれを流用す 19420 るべきなのではないだろうか→その様に書き換えた。OK 簡単に確認も済ませた。 19421 19422 2021-05-25 19423 19424 * util: 設定インターフェイスの細かい修正 [#D1568] 19425 * ble-face 導入 19426 * done: ble-color-setface の出力で ref: を認識する 19427 * done: ble-color-setface で @ の形式に対応する? 19428 * done: ble-face -r で元に戻せる様にしないと themes の切り替えに困る 19429 * done: ble-face -u で変更された face を表示する。 19430 * done: bleopt xxx@xxx=xxxx で一括設定ができる様にする 19431 * done: bleopt 既定値からずれている物だけ出力する機能 19432 * done: bleopt 既定値に戻す機能 19433 * done: blehook internal hook は既定では表示しない機能 19434 19435 2021-05-24 19436 19437 * global: gA をその場で代入しなければ 4.2 でも大丈夫 [#D1567] 19438 19439 共通なコードも多くあったので整理して纏める事にした。大分すっきりした。 19440 19441 2021-05-23 19442 19443 * contrib/git-prompt.sh の変数達は localvar_inherit で駄目なのではないか [#D1566] 19444 というか他にも同様の変数宣言の仕方をしている箇所は色々ある気がする。 19445 →検索して修正した。 19446 19447 * keymap/vi: vim モード表示に関して (reported by huresche) [#D1565] 19448 https://github.com/akinomyoga/ble.sh/issues/114 19449 19450 また vim のモード表示に関連する提案・質問が来ている。何処かに纏めておくべき 19451 であろうと思われる。取り敢えず後で vim mode の wiki ページに少なくとも説明 19452 かまたは説明へのリンクを載せておく必要がある。 19453 19454 * done: 取り敢えず keymap_vi_mode_name_xxxx を変更したら mode name の更新を 19455 予約する様にしなければならない。と思ったが何処で呼び出す様にしたら良いの 19456 だろうか。現在の実装を確認するとモード変更時に update-mode-name を呼び出 19457 している。そしてこの関数は即座に表示を行っている。然し、他の関数から mode 19458 name の設定を変更する場合には、その場で info を表示してしまうと変な事にな 19459 る。 19460 19461 a info pane を表示していない時は内部的に変更するに留める? 内部的に入れ替 19462 えるだけという機能を info に実装する必要がある。また、これだと一連の設 19463 定を変更した時に各項目ごとに info を表示し直すという事になって効率が悪 19464 い。 19465 19466 b やはり更新は遅延させるのが望ましい。然し、遅延させるとしてもどのタイミ 19467 ングで更新を行うのだろうか。やはり info reveal の瞬間に内容を更新するの 19468 が良いのではないかという気がする。 19469 19470 新しく info_reveal hook を追加して b の方針で実装する事にした。 19471 19472 * vim-airline の API を調べてそれをできるだけ再現するようにするという可能性 19473 も考えられる。但し、厳密に再現できる訳でもないと思われるが。vim-airline 19474 の README にはそんなに customization の情報は書かれていない。 19475 19476 * 単に各フィールドの内容が指定できるというだけの事である。 19477 19478 * それから、truncation は ble.sh では実装されれていない機能である。うーん。 19479 これの対応は面倒だ。現在の実装だと trace の中で各フィールドについて計測 19480 を行って、その上で出力を行っている。なので、truncation も原理的には実装 19481 可能であるが、(1) 各フィールドの優先順位はどうやって指定するのか (2) 19482 separator 毎の最大・最小幅をいよいよ実装する必要が出てくる (3) 自動改行 19483 を抑制する など色々修正が必要である。特にどういう仕様にするのかというの 19484 が一番面倒である。自然なインターフェイスで separator 毎の最大・最小幅を 19485 指定できる物だろうか。 19486 19487 よし。vim-airline を真面目に実装する事にする。 19488 19489 ? 各セクションが空の時にセクションを潰したい。然し、一方で各セクションの 19490 内容はプロンプトシーケンスとして実装したい。これの両立は可能だろうか。 19491 うーん。何だか難しそうな気がする。実際に実体化するまでは各セクションが 19492 潰れるかどうかは判断できない。という事は先に各セクションを実体化するし 19493 かない。 19494 19495 * 二重に処理する事になるがそうすると端末固有の SGR を二重に処理する事に 19496 なるのでは。うーん。一旦 ANSI 形式で出力するオプションを実装する必要 19497 がある気がする。 19498 19499 * done: auto-truncation の実装 19500 19501 * done: gitstatus に関しては後で vim-airline を実際に入れて動作を確認する 19502 必要がある。どうも vim-airline は tpope/vim-fugitive を使っている様であ 19503 る。また、dirty 状態かどうかは出力されない様である。取り敢えずよしとす 19504 る事にする。 19505 19506 と思ったが改めて確認したらちゃんと出力されていた。機能を追加した。 19507 19508 * done: ble/color/g2sgr-ansi を実装する 19509 * done: trace ansi の実装 19510 19511 x fixed: prompt_status_line の再描画の時に前回の内容がクリアされない (g=0 19512 の時) 19513 19514 うーん。不思議なのは直接 printf するとちゃんとクリアされるのに、 19515 ble/util/buffer 経由で出力しようとするとクリアされないという事。何故だ 19516 ろう。内容が消滅している可能性? 或いは、DRAW_BUFF か何処かに出力内容が 19517 残っている可能性もあるのかもしれない。 19518 19519 調べてみると ble/util/buffer の中に excursion しているコードが入ってい 19520 る。うーん。どういう事だろうか。誰が ble/util/buffer に内容を入れている 19521 のだろうか…。不思議である。と思ったら enter-command-layout で info や 19522 status を消していて、その為に excursion 状態になっているという事の様だ。 19523 19524 うーん。そもそも WINCH が起こるとこれまでの panel height も全て消えてな 19525 くなる訳だから、panel height に対する差分修正では駄目の筈である。高さを 19526 全て確保し直さなければならない。という事を考えると… height を全て空に 19527 すれば良いのだろうか。或いは。 19528 19529 | →これは結局様々な問題が複合した結果だった。高さの完全再配置が実装され 19530 | ていないのが主な問題。そして LINES COLUMNS が反映される迄にどうやら時間 19531 | がかかる様だというのがもう一つの問題。後者については仕方がないので待ち 19532 | 時間を入れる事にした。 19533 | 19534 | と思ったがこの後者の問題はウィンドウサイズを変更する時に contra がリア 19535 | ルタイムに大量の WINCH を発生させるのが原因の様である。bash trap はシグ 19536 | ナルの回数を覚えていないので単に一回だけ発生している様に見えただけだっ 19537 | た。contra の実装が悪いとも言えるが、然し滑らかにサイズ変更をする端末で 19538 | は普通に起こって良い事なのでこれに対する対策を入れるのは良い事である。 19539 19540 問題は最後の WINCH を捕まえる事ができないという事である。trap handler 19541 を実行している間は実行がブロックされている。WINCH の処理の最後で再度 19542 LINES COLUMNS が変化していないか確認すれば良いのではないか。 19543 →その様に変更したら可也振る舞いが改善した。 19544 19545 x fixed: SIGWINCH で乱れる問題。実は tput で端末の大きさを取得すれば良い 19546 のでは。というか (:) 等を実行しても checkwinsize で更新されるのではない 19547 か。と思ったが tput で取得しても LINES COLUMNS で取得してもずれがある様 19548 である。 19549 19550 x fixed: prompt_status_line が WINCH で再描画されていない? 19551 none になっている時に塗りつぶしを省略しているのが原因である。 19552 huresche にも改めて指摘されたのだった。 19553 19554 x fixed: menu-complete が動かなくなっている。trace に手を入れたのが原因だ 19555 ろうか。 19556 19557 あー。多分、合成がうまく行かなくなっている。改めて実装を確認する。と思っ 19558 たら動く様になっている。これも WINCH をした後に生じる問題だろうか。うー 19559 ん。その様だ。WINCH によって何故動かなくなるのが…謎である。 19560 19561 menu#render-item はちゃんと呼び出されている。ちゃんと出力も構築されてい 19562 る気がする。出力までもちゃんと行っている気がする。ああ。分かったかもし 19563 れない。これは info が invalidate された儘になっているという事なのだろ 19564 う。直した。 19565 19566 * done: https://itchyny.hatenablog.com/entry/20130820/1376978742 19567 此処で紹介されている landscape という配色がなかなか良いのではないか。 19568 と思って確認してみたがコードはなかなか面倒な事をしている。 19569 後でどういう結果になるのか調べてみる事にする。 19570 19571 設定を抜き出しては見たが実際にやってみると白背景だと微妙な感じだ。 19572 19573 * done: theme の設計を考えると eval-after-load ができる様にするべきでは。 19574 うーん。現在の実装だと eval-after-load は def.sh に登録している。然し、 19575 そうではなくて ble-import の枠組みの側で提供するべきなのではないだろう 19576 か。 19577 19578 これは大きな変更になりそうな気がするので後回しにする。 19579 →結局そんなに大きな変更ではなかった。簡単だった。 19580 19581 2021-05-22 19582 19583 * main: set -e の時にロードできない [#D1564] 19584 19585 またロードできなくなっている。これは本当は定期的にテストしなければならない 19586 事の気がする。 19587 19588 * adjust-builtins で失敗している。alias 定義を読み取る時の alias ... と、 19589 alias を削除する時の unalias に於いて存在しない alias を取り扱おうとする 19590 と exit status が 1 になって駄目の様である。 19591 19592 * prompt attach の際にも問題が生じていた。二箇所条件の書き方を変更した。 19593 19594 * blehook でも失敗している。中に於ける if builtin eval ... ; then ... が 19595 駄目の様だ。試してみると 19596 19597 false || true # OK 19598 eval false || true # OK 19599 builtine eval false || true # 駄目 19600 19601 という具合の動作になっている。bash-4.4, dev で確認した。3.0, 3.2 でも同 19602 様の振る舞いである。これは後でバグ報告に持っていく事にする。 19603 19604 問題の箇所は eval を使わない形式に書き換える事にした。 19605 19606 これでまたロードできる様になった。本当は blehook, ble-bind その他のインター 19607 フェイスについても set -e に対する対策をするべきの気もするが取り敢えず何も 19608 設定しない限りに於いては動くので良しとする事にする。そもそも set -e で対話 19609 シェルを使おうとする事自体があり得ない想定なので余り深く考えなくて良い。 19610 19611 * 2021-05-16 complete: tar xf groff-1.19.2.ta[TAB] でエラーが発生する [#D1563] 19612 19613 と思ったらこれは bash-completion だった。また確認してみたところ、これは5週 19614 間前に既に修正されていた様だ。 19615 19616 2021-05-20 19617 19618 * 2021-05-13 tmux-resurrect により vi_imap が empty になる問題 (reported by RakibFiha) [#D1562] 19619 https://github.com/akinomyoga/ble.sh/issues/109 19620 19621 "ble.sh: The keymap 'vi_imap' is empty." というエラーメッセージが出るとの事 19622 だが他には何もメッセージは出ないのだろうか。試しに keymap.vi を空にしてロー 19623 ドしてみると…再現した。 19624 19625 * bash ble.sh --clear-cache オプションを実装した方が良い。 19626 19627 * ファイルが存在するかどうかのチェックをしている箇所は、全て有限の大きさを持っているかどうかを確認した方が良い。 19628 19629 * 空の keymap になっていたらキャッシュ無しで初期化し直す機能を付けた方が良いかもしれない。 19630 19631 うーん。何と再現しなくなってしまった様である。 19632 こうなるとコードを見て憶測で修正するしかなくなる。 19633 19634 # { 19635 # ble/decode/keymap#load isearch dump 19636 # ble/decode/keymap#load nsearch dump 19637 # ble/decode/keymap#load vi_imap dump 19638 # ble/decode/keymap#load vi_nmap dump 19639 # ble/decode/keymap#load vi_omap dump 19640 # ble/decode/keymap#load vi_xmap dump 19641 # ble/decode/keymap#load vi_cmap dump 19642 # } 3>| "$fname_keymap_cache" 19643 19644 あー。もしかすると原因が分かったかもしれない。そもそも前に自分が問題を経験 19645 した時にもそうだったが、ble/decode/keymap#load を改名した事が原因なのであっ 19646 た。此処で、ble.sh が部分的に更新されていたりすると問題になるという事なのだ 19647 ろうという気がする。tmux-resurrect が一体何をしようとしているのかは結局謎な 19648 のであるが、うーん。 19649 19650 そもそも報告者が最新の物でも再現するとかしないとか言っていた時に、毎回 make 19651 をしていたのかというのも疑問の一つである。と思ったが rebuilding と言ってい 19652 るので、其処の所はちゃんとやっているのだろうという気がする。 19653 19654 a あー。もしかすると複数の異なる ble.sh を使っていて cache が混合していると 19655 いうのは十分考えられる可能性である。と思ったが本当にそれで問題が発生する 19656 だろうか。何れにしても呼び出す vi.sh は同じディレクトリにいる ble.sh から 19657 呼び出される筈で中途半端に更新されていない限りは不整合は起こらない筈なの 19658 である。 19659 19660 或いは tmux-resurrect が下手に関数等を保存しているのだとすると変な事が起 19661 こっても仕方ない → 試しに関数を定義して保存・復元して見たが関数は消滅し 19662 ていた。つまり、そういう事は関係ない。 19663 19664 或いは vi.sh の timestamp が偶然未来に設定されてしまったりする様な場合に 19665 も問題が起こったりするかもしれない。 19666 19667 うーん。やはり timestamp が壊れない限りはこれによって変な事が起こったりす 19668 る可能性は低い気がする。 19669 19670 b 後タイムスタンプが nfs などによってずれていたりするとそういう事があったり 19671 するかもしれない。timestamp が信用できない時にはどうしようもない。これは 19672 個々の使用者の側で注意して時刻を合わせてもらうしかない。 19673 19674 * done: 失敗したとしても端末の状態が壊れない様にする。 19675 19676 ? コードを見てみると初期化に失敗した時には完全に空 map になってロードされな 19677 いのではなくて safe keymap に fallback する筈なのだが何故そうなっていない 19678 のだろうか。 19679 19680 これは再現できるので修正はそんなに難しいことはない筈。 19681 19682 2021-05-20 もう返事もないし再現もできないし、向こうでも何だか解決した様な雰 19683 囲気を出しているので取り敢えず対症療法を push する事にする。 19684 19685 * 他にも似たような現象が起こる可能性があるのでキャッシュファイルについて全 19686 て -s を用いてチェックする事にする。 19687 * この際なので _ble_base_cache 内の構造・ファイル名についても整理する事にし 19688 た。 19689 19690 * syntax: ${a~} に対応していない [#D1561] 19691 19692 何れ消えると思っていたがどうも未だ消える気配はない様だ。取り敢えず使える環 19693 境ではちゃんと着色した方が良い様に思われる。 19694 19695 後気付いたのだが実は ${a^^} や ${a,,} も bash-4.0 から使えた様だ。tolower, 19696 toupper の実装に使えるのでは。と思って確認した所、既に 4.0 以上ではこれらを 19697 使う様になっていた。 19698 19699 軽微な修正だがこれだけ放置していても仕方がないのでもう push する。 19700 19701 * prompt: update "PS0" between multiple commands (motivated by tycho-kirchner) [#D1560] 19702 19703 複数のコマンドが一度に実行される時に、それぞれのコマンドについて PS0 が呼び 19704 出される。然し其処から参照される $# の値が更新されない様だった。調べてみる 19705 と、PS0 の更新をチェックする時に、更新の必要があるかどうかの判定をする hash 19706 値が複数のコマンドの間で変化がない為に更新が省略されていたという事。 19707 →hash に $# ($_ble_edit_CMD) も含める様にして対処する事にする。 19708 19709 * decode (ble-bind): ble-bind -m KEYMAP で全ての keymap が出力されている (fixup 750ca38) [#D1559] 19710 19711 これは指定した keymap を表示する様にした方が良い。というか元々そのつもりだっ 19712 た筈で単に対応を忘れていたという事の気がする。 19713 19714 * main: bash ble.sh --test の終了ステータス (fixup bbc2a90) [#D1558] 19715 19716 subshell からのロードを検出する様にした変更に於いて終了ステータスが意図しな 19717 い物になっていた。これは return $? || exit $? に於いて二個目の exit が 19718 return の $? を拾う様になってしまった為。 19719 19720 a 面倒なので、_ble_init_exit は削除しない様に変更して見た。 19721 19722 b しかし別の修正方法として eval を使う物を思いついた。うーん。eval を使う事にする。 19723 19724 棄却した a の修正は此処に供養する。 19725 | diff --git a/ble.pp b/ble.pp 19726 | index c9a11d8..d172c7d 100644 19727 | --- a/ble.pp 19728 | +++ b/ble.pp 19729 | @@ -1398,9 +1398,9 @@ function ble/base/initialize/.clean-up { 19730 | # 一時グローバル変数消去 19731 | builtin unset -v _ble_init_version 19732 | builtin unset -v _ble_init_arg 19733 | - builtin unset -v _ble_init_exit 19734 | builtin unset -v _ble_init_command 19735 | builtin unset -v _ble_init_attached 19736 | + #builtin unset -v _ble_init_exit 19737 | 19738 | # 状態復元 19739 | if [[ $_ble_init_original_IFS_set ]]; then 19740 | @@ -1444,18 +1444,17 @@ ble-import -f lib/_package 19741 | if [[ $_ble_init_command ]]; then 19742 | ble/base/sub:"$_ble_init_command"; _ble_init_exit=$? 19743 | [[ $_ble_init_attached ]] && ble-attach 19744 | - ble/util/setexit "$_ble_init_exit" 19745 | else 19746 | ble/base/process-blesh-arguments "$@" 19747 | + _ble_init_exit=$? 19748 | fi 19749 | 19750 | #%if measure_load_time 19751 | ble/debug/measure-set-timeformat Total nofork; } 19752 | _ble_init_exit=$? 19753 | echo "ble.sh: $EPOCHREALTIME load end" >&2 19754 | -ble/util/setexit "$_ble_init_exit" 19755 | #%end 19756 | 19757 | ble/base/initialize/.clean-up 2>/dev/null # set -x 対策 #D0930 19758 | -{ return $? || exit $?; } 2>/dev/null # set -x 対策 #D0930 19759 | +{ return "$_ble_init_exit" || exit "$_ble_init_exit"; } 2>/dev/null # set -x 対策 #D0930 19760 | ############################################################################### 19761 19762 * global: v0.3-master へのパッチ適用の際に気付いた細かい修正 [#D1557] 19763 細かい修正が溜まって来たので此処で一つずつ修正を適用してしまう事にする 19764 19765 * Makefile で run ではなくて tmp を作っていた。ディレクトリ名を変更した時 19766 に一緒に変更するのを忘れていた。 19767 * ble/function#suppress-stderr に不要なごみ引数 { を渡していた。 19768 * C-w M-w の振る舞いを変更したが、blerc に以前の設定に戻す設定例を入れた。 19769 19770 * IFS の異なる環境に対する対策としてできるだけ _ble_term_IFS を local IFS 19771 にコピーする様に変更していたが、この際なので直接 $' \t\n' と記述してい 19772 る部分をできるだけ全て $_ble_term_IFS に置き換える事にした。 19773 * src/benchmark.sh は独立したファイルとしても使える様にしてきたつもりだっ 19774 たが、ble/util/print, ble/util/print-lines を使う様になっていたので、こ 19775 れらの関数が定義されていない時には定義する様に修正した 19776 19777 2021-05-19 19778 19779 * README: 様々な機能へのリンクを貼った方が良いのではないかという事 [#D1556] 19780 19781 * 現在の初期化だと ble.sh session で source --test 等すると [#D1555] 19782 19783 変な事になるのではないか。これは取り敢えず独立した項目として取り扱う事にする。 19784 19785 * main: subshell 内部で source/reload したら何が起こるのか [#D1554] 19786 19787 source した場合には何も起こらない。うーん。これは単に attach 戦略が prompt 19788 だから attach する前に終了しているという事の気がする。 19789 19790 reload については reload が実際に実行されて色々と _ble_base_run のデータが 19791 破棄される。この状態で ble-detach を実行すると制御できなくなる。tty 状態は 19792 別に問題はない様だ。 19793 19794 * main: AUR blesh-git について [#D1553] 19795 19796 * ok: requirements: ble-update の為に git, gawk があった方が良いのかもしれ 19797 ない? 然し、最終的に AUR helper を呼び出すのであれば余り関係ないのかもし 19798 れない。特に package としては fallback になる事は想定していないので。 19799 19800 * ok: (("$helper_prog" != 0)) 19801 https://aur.archlinux.org/cgit/aur.git/tree/blesh-update.sh?h=blesh-git#n29 19802 19803 (()) の中の quote のルールは変更されている。然し何故か PKGBUILD はそのま 19804 ま何事もなく動作しているどういう事だろうか。shopt が調整されているのだろ 19805 うか。或いは bash の version が違うのだろうか。適当な PKGBUILD を作ってそ 19806 の辺りを出力させたらはっきりするのかもしれない。何れにしても将来的に変更 19807 されるかもしれないという事などを考えると修正した方が良い。 19808 19809 と思ったが改めて試してみたが問題はない様だ。単に手許で試す時に 19810 (("$xxx"!=0)) が ((!=0)) に展開されてエラーになっていただけなのであった。 19811 bash-5.1 で振る舞いが変更されたのは '' による quote の方であった。 19812 19813 * local variables 19814 local PRE_VERSION 19815 local POST_VERSION 19816 19817 恐らく他の所で使うという訳ではないだろう。というか、この関数は PKGBUILD 19818 で使われるのではなくて ble.sh から呼び出しているのであるから他の場所から 19819 使っているという事はない気がする。 19820 19821 * _package.sh は実の所 source するだけなので実行属性は必要ない。唯、source 19822 path を経由して source したい時には実行属性がついている必要があるのだった 19823 か? man bash を確認したがちゃんと実行可能である必要はないとの事が明記され 19824 ている。 19825 19826 というか今知ったがカレントディレクトリよりも PATH の方が優先されるのだそ 19827 うだ。だとすると結構変な事が起こるの可能性もあったのでは。今試しに ~/bin 19828 に ble.sh を登録して、bash --norc から ble.sh ディレクトリの外で source 19829 ble.sh を実行したらちゃんとロードされた。うーん。 19830 19831 * done: contributing に lib/_package.sh を追加する 19832 19833 取り敢えず残っている物については簡単に纏めてこの項目はOKとする。 19834 19835 2021-05-17 19836 19837 * util: inherit special file descriptors [#D1552] 19838 19839 #D1549 で setsid をしたら /dev/tty が見つからなくなって動かなくなった。 19840 /dev/tty が壊れてしまうという事態に対応する為に最初に確保した 19841 _ble_edit_io_std{out,err} を他の場所でも積極的に使う様にするのはどうか。 19842 19843 * 更に考えると毎回 bash を起動する度に新しく fd を確保するのは無駄である。 19844 なのであれば、export して共有してしまえば良いのではないかという気がする。 19845 19846 * また、ふと思ったのだが毎回 /dev/null を開いているのはどうなのだろうか。 19847 dup の方が軽かったりしないのだろうか。然し、/dev/null を dup できるのかと 19848 いうのも疑問である。然し、fork した途端に使えなくなるというのも変なので 19849 /dev/null は dup しても大丈夫なのだという気がする。 19850 19851 $ ble-measure 'echo hello >/dev/null' 19852 7.439 usec/eval: echo hello >/dev/null (x10000) 19853 $ exec {fd}>&14; echo $fd 19854 14 19855 $ ble-measure 'echo hello >&14' 19856 5.035 usec/eval: echo hello >&14 (x20000) 19857 $ ble-measure 'echo hello >&$_ble_base_fd_null' 19858 5.821 usec/eval: echo hello >&$_ble_base_fd_null (x20000) 19859 19860 やはり dup の方が高速である。然し、そもそもの処理時間が短いので気にしても 19861 仕方がないレベルではある。Cygwin でも同様の結果になるだろうか。 19862 19863 $ exec {fd}>/dev/null 19864 $ echo $fd 19865 16 19866 $ ble-measure 'echo hello >&16' 19867 24.920 usec/eval: echo hello >&16 (x5000) 19868 $ ble-measure 'echo hello >/dev/null' 19869 41.100 usec/eval: echo hello >/dev/null (x2000) 19870 $ ble-measure 'echo hello >&$_ble_base_fd_null' 19871 28.320 usec/eval: echo hello >&$_ble_base_fd_null (x5000) 19872 19873 →Cygwin でも dup の方が高速である。変数に入れると少し遅くなる。然し本当に 19874 置き換えてしまっても問題が生じないのかというと分からない。例えば 19875 _ble_base_fd_null がユーザーによって削除または書き換えられてしまったら何が 19876 起こるだろうか。大量のエラーメッセージが出て色々と悲惨な事になる気がする。 19877 後、/dev/null への redirect は可也基本的な事なので、もし置き換えるのだとし 19878 たら何よりも先立って初期化したい気がする。実装を確認すると ble/fd は 19879 ble/array を使用している。 19880 19881 * 取り敢えず fd#alloc のコードや stdin/stdout/stderr のコピーのコードを整理 19882 して、 19883 19884 (1) stdin/stdout/stderr は常にコピーを保持する様に変更する。 19885 19886 (2) bash-4.1 以上では {fd}> ... を使う様にしていたがこれだと 19887 10,11,12,... という番号を使ってしまい、間違って上書きした時に大変な事にな 19888 るかもしれないので、昔の様に 30,31,32,... を使う様に戻す。但し以前はなかっ 19889 た上書き確認を行う。此処で問題になるかもしれないのは、他のフレームワーク 19890 が上書き確認をせずに 30,31,32,... を使おうとした時の事であるが、それは仕 19891 方がない。比較として考えれば 10,11,12,... よりは安全として差し支えないだ 19892 ろう。 19893 19894 (3) openat_base 等のオプションは ble.sh ロード時のオプションから指定でき 19895 る様にする。 19896 19897 * done: wiki で openat_base の項目を編集する 19898 19899 * macOS で groff のエラーが出る (reported by killermoehre) [#D1551] 19900 https://github.com/akinomyoga/ble.sh/issues/112 19901 19902 groff -k というオプションが使えないという事。macOS の groff は v1.19 らしく 19903 これは 2004 の version である。実に17年前の groff である。このオプションは 19904 UTF-8 の man を処理する為に追加した物。実質的に preconv | groff と同じらし 19905 い。しかし、そもそも macOS には preconv がないそうだ。というか。そもそも 19906 groff 1.19 は Unicode に対応しているのだろうか。 19907 19908 取り敢えず groff をインストールして確かめてみる。うーん。全然駄目。そもそも 19909 utf8 device が存在していない様である。何か別の物をインストールすれば良いと 19910 いう訳でもなさそう。device として ascii, latin1, cpxxxx しかない。ascii に 19911 するしかない。man は LANG=C で探す。 19912 19913 然し英語の man を探したとしても本当に groff -man が使えるのかも怪しい。と思っ 19914 たが検索してみると一応 -man には対応している様な気がする。と思ったが -man 19915 ではなくて -m man としなければならない? 19916 https://www.unix.com/man-page/osx/5/groff_tmac/ 19917 19918 どうも試してみたら最新版でも -m man で動作している気がする。 -man と -m man 19919 は synonym という事だろうか。取り敢えず groff -T ascii -m man <<< X | uniq 19920 が動くかどうかを確認する。 19921 19922 と思ったが返信がない。取り敢えずこれで良いのかどうか分からないが #D1550 と 19923 一緒に変更を加えてみる事にする。それでも治らなかったら使う事にする。何か変 19924 更し残している事はあるだろうか? 19925 19926 2021-05-17 と思ったら返事が来た。どうも macOS の groff で -T utf8 も一応は 19927 使える様子である。うーん。という事は \[uXXXX] も取り扱えるのだろうか。 19928 19929 * もし \[uXXXX] が取り扱えるのであれば適当に \[uXXXX] に全て置換してしまえ 19930 ば良い。。。と思ったがどうやってやるのか微妙である。awk で変換しようにも 19931 awk では文字コードを取り出せないので uXXXX の形式に変換するのにも苦労する。 19932 うーん。od を使って binary に変換してそれから nawk で色々処理して、それか 19933 らまた od で元に戻すという様な面倒な処理を実装しなければならない。 19934 19935 % と思ったが binary に戻す方法は不明である。うーん。調べると bash の 19936 % printf \x?? 経由で出力するという事になっている? awk の printf は NUL 19937 % が出力できないとしている。他の文字は大丈夫だろうか。というより何故 NUL 19938 % が出力できないのだろうか。 19939 19940 awk の printf を使うとしたらテストが必要? と思ったが macOS で動けば良いの 19941 だから BSD awk で動けば十分である→今試した限りだと nawk, mawk, gawk で何 19942 れもちゃんとできる。NULもちゃんと出力できるのでOK。 19943 19944 * もしそのまま通過してくれるのであれば特に気にする事はない。が恐らくそうい 19945 う事はないのだろうという気がする。 19946 19947 * 或いは結局全然駄目の可能性もある。うーん。どうなんだろうか。 19948 19949 返事があった。\[uXXXX] で行ける様である。取り敢えず .preconv を実装した。手 19950 許で試してみる限りは動いている気がする。まあ、実際に動かして変な事が起こっ 19951 たらその時にまた考え直せば良い。取り敢えず遠隔で実装できるのは此処までであ 19952 る。 19953 19954 * complete: ssh -option の後の補完が固まる (reported by rlanore, riblo) [#D1550] 19955 https://github.com/akinomyoga/ble.sh/issues/98 19956 19957 $ alias ssh='TERM=xterm ssh' 19958 19959 で再現するとの情報を得た。他に man -w が現れたり消えたりするという情報も。 19960 つまり、一つの man -w が 100% になっているのではなくて man -w が繰り返しルー 19961 プで呼び出されている? また、cache dir に大量のファイルができているという話 19962 も。つまり、ble/util/assign で無限ループを起こしている可能性がある。 19963 19964 $ complete -r 19965 $ source ~/.fzf.bash 19966 $ TERM=xterm ssh -w[TAB] 19967 19968 TERM=xterm ssh -bash: 一致しません: /home/murase/.ssh/config.d/* 19969 19970 ble/complete/source:argument/.generate-from-mandb を見ると alias で展開され 19971 る限りは無限ループする可能性のあるコードがある。但し、重複判定はしている筈 19972 なので alias が有限である限りは無限ループにはならない気がするが…。うーん。 19973 分からない。或いは alias 展開で空文字列になった時に問題が生じる可能性? 19974 19975 OK! 再現できた! 19976 19977 - 自分の手元で再現できなかったのはどうも何か別の設定が勝手に 19978 bash-completion を読み込んでしまうからだった様である。一体何の設定が勝手 19979 に読み取るのかは謎だが、complete -r を実行しても何故か設定が読み込まれて 19980 しまう。と思ったが… ble.sh が __load_completion が存在している時には勝手 19981 にそれを呼び出す様にしていたのだった。そういう設計も考え物といえば考えも 19982 のである。但し、これも unset -f __load_completion すれば解除する事ができ 19983 る筈なのである。 19984 19985 * fixed: 分かった。 ble/complete/source:argument/.contains-literal-option が 19986 variable leak して ret を書き換えしてしまっている。直した。 19987 19988 * done: 更に alias で TERM=... としていても対応できる様に読み飛ばし機能も追 19989 加した。 19990 19991 x fixed: 然し ssh のオプションを抽出するのに失敗している。何故だろうか。改 19992 めて振る舞いについて調べる事にする。ble/util/assign を ble/assign と書い 19993 ていた。修正した。 19994 19995 x fixed: 未だ駄目。と思ったら man を探索する部分で $command とするべき所が 19996 $man になっている。 19997 19998 x fixed: それでも駄目。調べると ssh の man を gzcat する所まではできている。 19999 其処から関係のありそうな物を抽出する所で失敗している。うーん。man から 20000 mdoc に変化するという場合もある様だ。どちらでも良い様に色々書き換える。然 20001 し、それでも nroff の形式がよく分からないので行き当たりばったり的な実装に 20002 なってしまう。取り敢えず Dd, Nm, Xo-Xc に対応した。また後段で __ble_key__ 20003 と __ble_desc__ が同じ行になってしまった場合でも動く様に修正した。 20004 20005 x fixed: エラーが出る groff -[TAB] ... これは nawk に日本語のコメントを渡し 20006 たのが行けなかった。日本語のコメントは除去する様にした。 20007 20008 x fixed: 空白が沢山表示される。連続する空白は1つに縮約する様にしたい。 20009 20010 2021-05-16 20011 20012 * work around Kitty bugs (reported by NoahGorny) [#D1549] 20013 https://github.com/akinomyoga/ble.sh/issues/110 20014 20015 | bash-it に追加する事について考えると言っているがどの様な形で追加するのだろ 20016 | うか。コードを直接追加するのだろうか。その場合には色々と微妙。 20017 | 20018 | * 先ず ble.sh の codebase は bash-it よりも巨大だ。どかんと入れる事が良い事 20019 | なのか分からない。 20020 | 20021 | * ble.sh 自体巨大だし UX 自体を大きく書き換える。それ単体として Issue/PR が 20022 | 頻繁にある。もし単純にスクリプトを追加すると、bash-it に issue が沢山立つ 20023 | 事になる。それよりは ble.sh の側に Issue が来て欲しい。 20024 | 20025 | * 実は結構好みが別れる様であるという事。autosuggestion を off にしたいと 20026 | いう人もいたりするし、syntax-highlighting が遅いという人もいる (これは 20027 | 完全なる思い込みだと思うが…)。 20028 | 20029 | * 独立した設定ファイルが存在するという事から、ユーザーにちゃんと説明する 20030 | 必要があるという事。 20031 | 20032 | * 自分勝手な事だけれども、bash-it の一部として普通になってしまうと star が 20033 | こっちに来なくなる。bash-it の方がメインだと思われるのは嫌である。 20034 | 20035 | * bash-it 自体にパッケージマネージ機能などがあればそれを通してインストール 20036 | して貰うのが良いという気がする。それがなくても単に git clone etc. を内部 20037 | 的にして貰うのが良いという気がする。 20038 | 20039 | * theme の充実を図りたい。これは渡りに船なのではないか。然し、bash-it にも 20040 | theme があるのだという事。 20041 | 20042 | * gitstatus.plugin.bash を見ると別に他のプロジェクトをそのまま追加している 20043 | という訳ではない様である。存在が確認できた時に追加の設定を行っている様に 20044 | 見える。 20045 20046 何だかそういう雰囲気でもなくなったので気にしない事にする。 20047 20048 未だ Kitty で変な状態になるそうである。例えば setsid 関係で何か変な事が起こっ 20049 ている可能性? と思ったがもしそうだとするともっと滅茶苦茶な事が起こる様なの 20050 でこれは多分関係ないのだと思う。 20051 20052 ble-detach をした後でも問題が再現しているという事を述べている。うーん。試し 20053 てみたら分かった。これは modifyOtherKeys の解除ができていない。\e[>4;0m が 20054 効いていないという事なのだろうか。と思ったら、どうもそういう訳でもない。 20055 printf $'\e[>4;0m' を送ったらちゃんと動く様になる。 20056 20057 改めて詳しく見てみると…どうも external の既定は 1 の様である。取り敢えず 20058 workaround を追加する。 20059 20060 2021-05-15 20061 20062 * package: AUR package (suggested by huresche, help by oc1024) [#D1548] 20063 https://github.com/akinomyoga/ble.sh/issues/108 20064 Ref #M0020 PKGUBUILD の書き方 20065 20066 AUR の PKGBUILD の提案を受けた。PKGBUILD の内容を確認してみる。 20067 20068 | > arch=('x86_64') 20069 | 20070 | arch=('any') 20071 | 20072 | > makedepends=('git') 20073 | 20074 | makedepends=('git' 'gawk') 20075 | 20076 | > pkgver() { 20077 | > cd "${srcdir}/${_pkgname}" 20078 | > printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" 20079 | > } 20080 | 20081 | > install -Dm644 ./note.txt "${pkgdir}/usr/share/doc/${_pkgname}/note.txt" 20082 | 20083 | `note.txt` is just a private note but not a part of the documentation. 20084 20085 というか既にパッケージにしている人がいる。 20086 https://aur.archlinux.org/packages/blesh/ 20087 https://aur.archlinux.org/packages/blesh-git/ 20088 20089 PKGBUILD の説明は此処にある 20090 https://wiki.archlinux.org/title/VCS_package_guidelines 20091 https://wiki.archlinux.jp/index.php/PKGBUILD 20092 https://wiki.archlinux.jp/index.php/%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E4%BD%9C%E6%88%90#.E9.96.A2.E6.95.B0_pkgver.28.29 20093 20094 * fixed: 自分で試しに install を実行してみた所 644 になっていない。うーん。 20095 644 もしくは 755 になる様に umask 022 とした。 20096 20097 ble-update を実行すると何が起こるのだろうか。 20098 取り敢えず複数の方法を組み合わせて対応するのが良い。 20099 20100 a /usr/* /opt/* etc であって、 20101 ファイルが存在するけれど書き込み権限がないという時には、 20102 sudo bash "$_ble_base/ble.sh" --update を実行する。 20103 sudo の存在チェックも一応する必要がある気がする。 20104 20105 (a) repository の書き込み権限がない場合と、(b) install 先の書き込み権限が 20106 ない場合の二つがある。(c) それから repository が見つからなくて、install 20107 先の書き込み権限がない場合もある。(a) と (c) の場合には全体を sudo で実行 20108 し直せば良い。但し、(a) の場合には他のユーザーのディレクトリを sudo で更 20109 新してしまうと変な事になるのでユーザーのチェックは必要である。権限昇格し 20110 た後に [[ -O file ]] でチェックすれば良いのだろうか。取り敢えずその方針で 20111 行く。 20112 20113 この為に ble.sh --update に対応する必要がある。 20114 20115 そもそも勝手にアップデートして良いのだろうか。複数のユーザーが勝手にアップ 20116 デートしたらどうなるのだろうか。と思ったが sudo 権限を持っているユーザーが 20117 勝手に物を実行するのが悪い。sudo を使ってインストールするのだからそれなりに 20118 他の人に気を遣うべきである。 20119 20120 b アップデート用のスクリプトを作って sticky bit を付けて無理やりアップデー 20121 トを実行するという手もある。これは他のユーザーが同時にアップデートしたり 20122 する危険性が高いし、管理者権限で現在の ble.sh の状態を管理する事が不可能 20123 になるので駄目。 20124 20125 c package manager が存在したらそれを使うという手を安易に提案されたが、それ 20126 だと package manager を使わずにインストールされたのに勝手に package 20127 manager 経由で再インストールされてしまうという事になりかねない。まあ、 20128 /usr/share に入っている時点で何らかの package manager を経由しているとい 20129 う事は明らかなのだから、余り気にしなくて良いのかもしれない。 20130 20131 と思ったが現在の所は AUR ぐらいしか存在しない。そして AUR ではどの様にアッ 20132 プデートしたら良いのかよく分からない。単に再インストールすれば良いのだろ 20133 うか。或いは一旦削除してそれから入れるのだろうか。 20134 20135 d done: package maintainer の用意したファイルを source するという提案。これ 20136 も確かに一つの手である。例えば lib/init-package.sh を使う。 20137 20138 * 名称について: もしくはlib/init-PACKAGE.bash 等の方が良いかもしれない。 20139 もしこれらのファイルが存在したらそれを source する事にする。PACKAGE と 20140 大文字にしていると PACKAGE の部分を package manager の名前に置き換える 20141 のだと勘違いする人がいるかもしれない。やはり此処は init-package.sh にす 20142 るべきだろうか。然しそうすると今度は他の普通のファイルとの見分けが付か 20143 ない。或いは単に lib/package.sh とするか。或いは、lib/_package.bash と 20144 いう形にするのが良いだろうか。 20145 20146 うーん。lib/_package.bash もしくは lib/_package.sh という事にする。内部 20147 で、ble/package/update なる関数を定義してもらう事にする。 20148 20149 * README にリンクを貼る。README が長くなるのも面倒だし、そもそも普段使って 20150 いる人はコマンドを見なくても分かる筈。という訳で取り敢えずはパッケージ名 20151 だけ分かる様にしておく。 20152 20153 一つ一つのコマンドについては Wiki にページを作る事にすれば良いだろうか。 20154 然し、Wiki のページに跳ぶのも面倒である。それにリンクが沢山あるのも変な感 20155 じがする。或いは、リンクは Wiki のページだけに向かわせる事にする。パッケー 20156 ジ名は単なる文字列とする。それが良い気がする。 20157 20158 2021-05-23 oc1024 に間違いを指摘された。修正する。 20159 20160 2021-05-11 20161 20162 * bind: 無引数 ble-bind で現在の binding を表示。現在の binding の着色 [#D1547] 20163 20164 * complete: ble-sabbrev の出力の着色 [#D1546] 20165 20166 * edit: やはり \C-x\C-v で ble.sh の version を表示したい気がする [#D1545] 20167 20168 ble.sh, version 0.4.0-devel3+c89aa23 (noarch) 20169 20170 Issue template での要求項目も簡単になる。現状だとユーザーに長いコマンドを入 20171 力させている。 20172 20173 * 2019-02-09 うーん。git や bash-it の様に ble.sh でも ble コマンドの様な物を提供するべき? [#D1544] 20174 cf #D1543 20175 20176 % と思ったが既に何処かには ble という名前のコマンドが存在していて、 20177 % これらは Bluetooth のサービスの開始・終了などを実行するのに使われている様子である。 20178 % もしこれらが広範に用いられている物なのだとしたら使いにくい。 20179 % 20180 % また、ble の名前の由来である zle コマンドの事を考えると、 20181 % ble widget の様な使い方を想像してしまうのではないかとの問題もある。 20182 % 20183 % 混乱を防ぐためには ble ではなくて ble.sh または blesh の様な名前が良いだろう。 20184 % しかしそうすると現状の ble-import だとかの機能を呼び出すのに余り適していない気がする。 20185 % つまり、blesh import ... で ble-import が呼び出されるというのは分かりにくい。 20186 % 或いは現状の ble-import を blesh-import に改名するという手もあるかもしれないが、 20187 % そういう事を考え始めると全ての関数を ble から blesh に改名したくなる。 20188 % それは面倒だし、元の zle という名前から離れていくので余りやりたくない。 20189 % 20190 % 実のところ、現状のまま ble-* の方が自動的に補完が効くので嬉しい。 20191 % 20192 % bash.env は bash.env という名前のコマンドを提供する様である。 20193 % https://github.com/midwire/bash.env 20194 % そういう事であれば ble.sh でも ble.sh という名前の関数を提供すれば良い気がする。 20195 % しかし ble.sh が入力しやすいのかというと微妙ではある。 20196 % 20197 % bash-it の場合には bash-it-update だとか bash-it::update だとかだと 20198 % 格好が悪いので bash-it update という形の関数名になるというのは分かる。 20199 20200 結局 ble という名前で定義する事にした。既に同名のコマンドが存在している場合 20201 には、引数を認識できない時に限り元のコマンドを呼び出す事にした。 20202 20203 * main: BLE_ONLOAD [#D1543] 20204 https://github.com/akinomyoga/ble.sh/issues/107 20205 20206 shournal という plugin の作者が PS0, PS1 を使ってコマンド開始・終了を検出し 20207 ようとしている。それはそれで良いのであるが、ble.sh は PREEXEC, POSTEXEC と 20208 いう物を用意している。考えてみれば他の枠組みで使ってもらう為には、ble.sh の 20209 ロードの順序に関係なく PREEXEC, POSTEXEC が存在すればそれに attach できる様 20210 に記述したい。 20211 20212 % ble.sh がロードされた時に呼び出す配列も用意した方が良いのではないか。 20213 % ble.sh がロードされた段階では blehook コマンドは使えないし、blehook の内 20214 % 部形式を上書きしようにも _blehook_h_... だとか様々な配列があって直感的で 20215 % ない。ロードした時に関しては特別に BLE_ONLOAD 的な配列を用意しても良いの 20216 % ではないだろうか。 20217 20218 という事を考えると ble.sh が後からロードされた時の為に 20219 20220 BLE_ONLOAD 20221 20222 という配列を用意して其処に初期化用のコードを登録させるというのが手である。 20223 20224 然し、ble.sh をロードしているからと言って attach しているとは限らない。 20225 plugin が動作を切り替えるのに使える関数を用意するべきなのではないか。現在 20226 ble.sh がロードされていてかつ attach していて更にユーザーコマンドの実行中で 20227 ない時という判定をする必要があるのではないか。 20228 20229 取り敢えず zle を真似て ble という関数で現在の状態を検出できる様にしようと 20230 したが…。ble.sh がロードされていない状況にも対応する為には結局変数に頼るべ 20231 きなのではないか。実のところ特に ${_ble_attached-} をチェックすれば良いので 20232 はないかという気がする。問題は _ble_attached は明らかに内部変数といった形に 20233 なっていて公開に躊躇するという事。 20234 20235 a _ble_attached を BLE_ATTACHED に改名する? 20236 20237 値を設定している箇所は ble.pp 内部の5箇所のみである。なのでこの部分の変更 20238 はそんなに大変ではない。然し参照している物の内には fzf-marks も含まれてい 20239 る。うーん。 20240 20241 b _ble_attached と共に BLE_ATTACHED も使える様にする? 20242 20243 変更している箇所が 5 箇所なので連動して変更するのは簡単である。 20244 20245 また、bash-4.3 以降では nameref を使える。唯、nameref 属性を追加する為に 20246 は -g が必要である。と思ったが -g は 4.2 から使えるので問題はない。 20247 20248 そうは言っても version 毎に連動して変更するコードを実行するしないというの 20249 を切り替えるのも面倒なので、やはり常に明示的に連動して変更する様に書く方 20250 が楽である。 20251 20252 * done: BLE_ATTACHED を公開変数にする。 20253 20254 * done: ble コマンドで現在内部にいるかどうかを判定できる様にする? 20255 [[ $_ble_attach && ! $_ble_edit_exec_inside_userspace ]] 20256 20257 0neGal が ble という名前のコマンドを作っていた。勝手に他の人がコマンドを 20258 作成する前に ble コマンドを予約しておくのが良い気がする。然し、他のコマン 20259 ドと被った時の為に本当の関数名は別にしておく? だとすると何が良いだろうか。 20260 調べると blesh というのも既に Bluetooth Low Energy の CLI ツールとして存 20261 在はしている様である。然しだからと言って blectl だと更に Bluetooth Low 20262 Energy の制御に使うコマンドの様である。ble-cli だとか blecli も同様である。 20263 或いはユーザーから直接使って貰う可能性は考えずに ble/dispatch にするとい 20264 う考えもある。然し、ユーザーに使われる事を想定しないのであれば、抑々別名 20265 として退避する意味もよく分からない。 20266 20267 名前に関しては 2019-02 に既に議論が存在している。ble.sh という名前の関数 20268 を定義するという手についても示唆されている。bash.env や bash-it はそのま 20269 まプロジェクト名がコマンド名になっている。然し、ble.sh は既に沢山の関数を 20270 ble... としているのでやはり ble が最適である様に思われる。 20271 20272 うーん。やはり ble -> ble/dispatch という事にする。と思ったが面倒なのでも 20273 ういきなり ble を定義している。後で問題になった時に処理すれば良い。と思っ 20274 たがやはり ble/dispatch を定義した。 20275 20276 * done: blehook ATTACH, DETACH 対応した。 20277 20278 * PS0 の中での \# の展開結果が異なるという話 (reported by tycho-kirchner) [#D1542] 20279 https://github.com/akinomyoga/ble.sh/issues/107 20280 20281 これはそもそも ble.sh ではコマンドの受付と実行を分離しているからである。こ 20282 の様に疎結合にしたのに逆にその場で実行する様に書き換えるのは設計として許容 20283 できない。それに実際にその様に実装しようとすると色々と複雑になってしまう。 20284 なので、現在の枠組みの範囲内でそれを再現する様に実装しなければならない。 20285 20286 もう一つの問題は ble.sh では同時に複数のコマンドを実行する可能性があるとい 20287 う事。そして、PS0 は各コマンド実行の直前に実行する物であって、PS1 はプロン 20288 プト表示の前に実行する物であるという事。という事を考えると、 20289 20290 [PS0] 20291 COMMAND1 20292 [PS0] 20293 COMMAND2 20294 [PS1] 20295 PROMPT 20296 20297 という形になる可能性もあるのである。 20298 20299 [修正] 20300 20301 * fixed: うーん。時々 Cygwin でプロンプトが表示されてからコマンドが実行され 20302 たりする原因が分かった気がする。これは queue に何かあるのにも拘らず直ぐに 20303 ユーザー入力が来て、それによって再度プロンプトが表示されて、その上でコマ 20304 ンドを実行するから起こることである。 20305 20306 今となっては複数行入力の検出や bracketed paste mode など色々とユーザーの 20307 誤貼り付けに対する対策が整ってきているので、この様な遅延の対策は不要であ 20308 る。という事を考えると、queue に何かある時にはコマンドを実行する様に変更 20309 するというので良い。 20310 20311 20312 * OK: ble-edit/exec:gexec/process は誰も使っていない気がする。これは削除で 20313 良いのではないか。と思ったら勘違いだった。ちゃんと呼び出されている。 20314 20315 x fixed: 改行が含まれる空コマンドの時に ble.sh は実行している気がする。但し、 20316 履歴には登録していない。少なくとも CMD が一個増えてしまっている。何が起こっ 20317 ているのだろうか。 20318 20319 →空かどうかのチェックで空白とタブしか判定していなかった。一方で history 20320 に登録されていなかったのはまた別のフィルタが働いていたという事だろう。 20321 20322 ? 履歴展開の展開結果が空の時には何が起こるのだろうか。と思ったが有限の文 20323 字列から空の履歴展開になる事もない様な気がする。いや !:5 等としたら空に 20324 なるのだろう→と思ったら bad word specifier というエラーになる。やはり 20325 空に展開する事はないという事なのだろうか。 20326 20327 普通に history -s '' としたら空の履歴を登録する事ができて、!履歴番号で 20328 空に展開させる事ができる。空に展開される時にはコマンド実行としては取り 20329 扱われないが、改行はカウントされる。但しカウントされる改行は展開後では 20330 なくて展開前の行数になっている様子である。 20331 20332 x done: 改行が含まれるコマンドの時に LINENO を増加させる。 20333 20334 * done: \# 及び LINENO の振る舞いについて調べる 20335 20336 \# は LINENO ではなくて _ble_edit_CMD を使わなければならない。というか、 20337 LINENO 等の振る舞いに関しても bash の PS0, PS1 の振る舞いに従わなければな 20338 らないのだろうか。両者の振る舞いについて確認する事にする。 20339 20340 うーん。どうやら LINENO の方がペアを特定するのには便利な気がするが何故 20341 CMD の方を使っているのだろうか。 20342 20343 ? どの様な時に LINENO と CMD がずれるのだろうか。normal bash で確かめてみ 20344 ると、どうやら不完全なコマンドを入力して "> " (PS2) で続きを入力した時 20345 にずれる様である。 20346 20347 他に LINENO はコマンドを実行せずに Enter を押した時にも増えるし、一まと 20348 まりのコマンドの中に改行が含まれている時にも改行の数だけ余分に増える。 20349 20350 C-c でコマンドをキャンセルした時にも増える様である。これについては 20351 ble.sh で試したらちゃんとその様になっていたので気にしなくて良い。 20352 20353 ? Bash で \# に対応する変数はないのか。もしあるのであれば同様の名前で提供 20354 するべきなのではないだろうか。 20355 20356 何処で \# の処理がされているのかと思ったが parse.y:6162 20357 (decode_prompt_string) の中にあった。current_command_number という変数 20358 を参照している。そしてこれは eval.c の中で incr されている。そも他の箇 20359 所では全く使われていないので、これは別に Bash の内部の値を取り出そうな 20360 どとはしなくて良い。 20361 20362 * fixed: \# の振る舞いを PS0 の評価後に変化する様に変える 20363 20364 % 取り敢えず \# はコマンドを登録する時に番号を保存する様にする。もし保存 20365 % されていたら其処で振る舞いを書き換える事にする。 20366 20367 _ble_edit_CMD の increment を内部に移動する事にする? この変数は \# を通し 20368 てしか定義されない物の様なので他の場所で影響が出てくる事はない様に思われ 20369 る。なので PS0 の直後で increment する様に変更してしまって問題ない気がす 20370 る。 20371 20372 * Note: どうやら normal bash でも PS0,PS0,PS1 という感じの組み合わせになる 20373 事がある様である。C-v C-j として改行を挟んで独立したコマンドを複数入力し 20374 た場合になる。この時には LINENO は PS0 前に inc されて CMD は PS0 直後に 20375 inc されている様に見える。PS0 に関してはこの振る舞いに倣うのが適切だろう。 20376 20377 元々の報告では PS0 と PS1 が必ず pair になる事を期待しているのだろうか。そ 20378 もそも PS0 はコマンド開始前に出力する物で、PS1 はプロンプト表示前に出力する 20379 物なので必ずしも組になっているとは限らない。 20380 20381 組になっている事を期待するのであれば PREEXEC 及び POSTEXEC を利用するべきな 20382 のである。但し、shournal が単に計測対象開始として PS0 を使って、計測対象終 20383 了として PS1 を使っているというだけなのであれば、PS0 が重複していても特に問 20384 題は生じないのである。 20385 20386 もし PREEXEC, POSTEXEC を使うというのであれば ble.sh が後からロードされた時 20387 にもちゃんと有効化される様に記述する必要がある。。 20388 20389 2021-05-10 20390 20391 * syntax: PS0 から stderr に出力できないという報告を受けた (reported by tycho-kirchner) [#D1541] 20392 https://github.com/akinomyoga/ble.sh/issues/107 20393 20394 一体何をしたいのか謎だがまあ元の bash で動く以上はその動作を利用する設定も 20395 あるだろう。元々その様に実装していたのは set -x の出力を防ぐ為だったが、よ 20396 く見たら PS0 の出力は restore-bash-options の前だったのでこの段階では 2 を 20397 端末に出力しても OK. 20398 20399 * 2021-03-21 gitstatus.plugin.sh の alias builtin で builtin eval 他が破壊されている [#D1540] 20400 https://github.com/akinomyoga/ble.sh/issues/93 20401 https://github.com/romkatv/gitstatus/pull/235 20402 20403 * 取り敢えず暫定的な対策として source ble.sh の時に unalias builtin 等を実 20404 行する事にした。 20405 20406 * 他に source ble.sh した後に gitstatus.plugin.sh が実行されて、更にその後 20407 になって ble-attach した時の事も考える必要がある。 20408 20409 gitstatus.plugin.sh の側で対策できないのか。 20410 34e21707 20411 20412 https://github.com/romkatv/gitstatus/issues/154 20413 ここで本人が builtin を置き換えるのは良くない事だという事を述べている。 20414 20415 > It's generally not a good idea to redefine builtins. If you also redefine 20416 > things like true, local, unset, etc., gitstatus won't work. Please don't 20417 > file a bug in this case but rather fix your config. 20418 20419 eval ... pos parameters 20420 source ... pos parameters 20421 source ... function scope or not (declare var の振る舞い) 20422 unset ... previous-scope dynamic-unset or value-unset 20423 exec ... persistent redirections 20424 これは実際に問題になるという事を確認した。 20425 20426 これは報告したらもっと別の方法で exec bash を検出する方法について議論が始まっ 20427 た。幾つか結構怪しい方法も含めて紹介した。その内の一つの方針で実装してテス 20428 トしてみるそうである。 20429 20430 これも返信が来て色々議論して alias を全く使わない様に向こうが修正してくれた。 20431 しかも後で気づいたのだが gitstatus の作者はあの powerlevel10k の作者でもあっ 20432 た。powerlevel10k は ble.sh と同じく zsh ではあるがシェルで色々と複雑な処理 20433 をゼロから真面目に実装している奴である。 20434 20435 * highlight: 1>&a.txt のファイル名着色 [#D1539] 20436 20437 着色だけでなく補完にも一緒に対応する。 20438 20439 x fixed: 実装してみたが動かない→2箇所 RDRD2 になっていた。CTX_RDRD2 に直す。 20440 20441 x fixed: 3<&- や 3<&4- 等の redirection に対してエラー着色になっている。 20442 20443 x fixed: 1>& 1 に対して補完が効かない→check-prefix に登録していなかった。 20444 20445 x fixed: 1>& に対して補完が効かない。ファイル名だけが生成される。check-here 20446 でもしかすると別の ctx になっている? →調べたらそもそも ARGX になってい 20447 て其処から RDRD2 等に変わっていないので ARGX だと思って補完が開始されてい 20448 るのが原因である。何が問題かというと、次の単語がない時に redirection で 20449 stat を設置していないのが行けない。然し、そもそも RDRD2 等は単語の種類で 20450 あって解析の状態ではないのではないか? と思ったが別にそういう訳でもないら 20451 しい。ちゃんと RDRD2 という ctx になって解析されている。 20452 20453 ここで問題になるのは RDRD2X 的な文脈が存在しないという事にある気がする。 20454 20455 a 或いは一文字も入力されていなくても勝手に RDRD2 を開始してしまうべきなの 20456 だろうか。と思ったが RDRF, etc は nest の中にいるという事を前提とした実 20457 装になっているので、そのまま ctx を設定する訳には行かない。然し、そうは 20458 言っても空の nest を生成する事もできない。 20459 20460 b 或いは stat か何処かの配列に次に来るべき者についての情報を記録するとい 20461 う事にする? 他の所ではその様な事をしていないのに此処だけでその様に処理 20462 するのも変である。 20463 20464 c というかそもそも check-prefix で ARGX の時に redirection を検出するべき 20465 なのではないだろうか。 20466 20467 最終的に c が正しい実装である。そもそも check-here は fallback 的な位置づ 20468 けであり此処に来た時点で実は変な補完になってしまう事は運命づけられている。 20469 20470 * 他に << 及び <<- の後の補完も定義されていなかったのを定義した。適当に 20471 EOF:END:HERE 等としたがもっと別の物を追加するべきかもしれないし、あるいは 20472 ユーザーが設定できる様にするべきかもしれない。 20473 20474 * 全般に fd の補完もできる様にした。 20475 20476 * MSYS2 patch .inputrc [#D1538] 20477 https://github.com/akinomyoga/ble.sh/issues/104 20478 https://sourceforge.net/p/msys2/mailman/msys2-users/thread/CAFLRLk-UX7S%3DTAerNix7HvxDAv4aY2FwZuFZz%3DU%2BTLBAWxCLEg%40mail.gmail.com/#msg37275646 20479 https://github.com/msys2/MSYS2-packages/pull/2490 20480 https://github.com/git-for-windows/build-extra/pull/341 20481 20482 Ref #D1534 20483 20484 特に問題の行は削除するべきであると考えているが返信は未だない。 20485 強い口調で書き過ぎたから無視されているのかも知れないし、 20486 単にこの mailing list には誰もいないという事なのかもしれない。 20487 archive を遡ってもこの mailing list は活発であるとは言い難い。 20488 20489 GitHub にソースを見つけたので PR を出してみた。 20490 こちらも直ぐには返事が来ない。 20491 一応ちゃんと変更の要求は取り込まれた。 20492 20493 https://github.com/msys2/MSYS2-packages/pull/2490 20494 20495 然し本当に git bash の msys と msys2 は一緒なのだろうか…。MSYS2 をインストー 20496 ルして、それから Git Bash もインストールしてみる。Git Bash の方は個人のディ 20497 レクトリには .inputrc はなくて、/etc/inputrc が読み取られている様である (実 20498 際に /etc/inputrc を編集して影響を与えている事を確認した)。そして、実は 20499 /etc/inputrc の内容と MSYS2 の .inputrc の内容は異なるという事も確認できた。 20500 20501 ? ok: MSYS2 の /etc/inputrc はどうなっているのだったか→MSYS2 では 20502 /etc/inputrc は存在していない。なので、今回の変更だけで大丈夫のはず。 20503 20504 ? ok: Cygwin の方にも inputrc があるのではないか→調べたら 20505 /etc/skel/.inputrc があったが、これはちゃんと変な binding は削除されてい 20506 た。検索した感じだとそもそもこの壊れた binding は cygwin の inputrc から 20507 来ていた様な気がする (違ったかもしれないが面倒なのでもう確認しない) ので、 20508 Cygwin の側では誰かが何処かの時点で気づいて削除したという事だろうか。 20509 20510 ? done: Git Bash の /etc/inputrc にも変更要求を出さなければならない 20511 20512 https://github.com/git-for-windows/git-sdk-64/blob/main/etc/inputrc 20513 https://github.com/git-for-windows/git-sdk-64/blob/main/etc/skel/.inputrc 20514 https://github.com/git-for-windows/git-sdk-32/blob/main/etc/inputrc 20515 https://github.com/git-for-windows/git-sdk-32/blob/main/etc/skel/.inputrc 20516 20517 以上にファイルを見つけたがどうも違う様な気がする。これらのリポジトリのコ 20518 ミットを見ると自動的にアップデートされている。なので、これは別の場所に 20519 upstream があるという事を示唆しているのではないか。然し検索してみても関連 20520 する物は見つからない。 20521 20522 https://github.com/search?q=org%3Agit-for-windows+%22msys2+mailing+list%22&type=code 20523 20524 /etc/skel/.inputrc は MSYS2 から継承されるのだと考えたとしても、では 20525 /etc/inputrc は何処から来ているのだろうか。謎である。うーん。もしかして 20526 msys1 が起源になっている? というか Git Bash の MSYS は MSYS2 ではなくて 20527 MSYS1 なのだろうか。MSYS の version は何処でチェックできるのだろうか。 20528 20529 改めて色々読んでいると build-extra も言及されている。適当にディレクトリを 20530 覗いたら inputrc があった。どうも GitHub の検索はファイル名本体には全く一 20531 致しないようだ。 20532 20533 https://github.com/git-for-windows/build-extra/blob/main/git-extra/inputrc 20534 20535 https://github.com/git-for-windows/git/issues/62 では PR は OK と言ってい 20536 るが何処に出したら良いのかについては何も言及していない。msysgit という物 20537 も存在する様だ…そちらにも PR を出す必要があるだろうか、と思って確認した 20538 ら msysgit は Git for Windows の前身であり同じ人が管理していて既に 20539 archive されていた。 20540 20541 ? ok: MSYS-1.0 にも出した方が良いだろうかと思って活動を確認したが Mailing 20542 list は 2013 から動いていないし、最新版も 1.0.12 の 2016 年なので、此処で 20543 修正しても仕方がないと判断する。そもそも、ble.sh の側でも対策を入れたので 20544 実質的に問題は発生しない筈。 20545 20546 2021-05-08 20547 20548 * decode: 初期化時にエラー (reported by RakibFiha) [#D1537] 20549 https://github.com/akinomyoga/ble.sh/issues/106 20550 20551 一番最近の commit を観察したが特に怪しい所はない様に思われる。 20552 20553 キャッシュが壊れている可能性? 然し、キャッシュをクリアしてしまうと問題が再 20554 現しなくなる可能性があるので後回し。 20555 もし ble-update を実行する過程でキャッシュが壊れるのだとしたらどれかの 20556 version から最新版に更新した時に問題が再現するかもしれない。そう思って 20557 026432d 9125795 79d671d 0506df2 032f6b2 からのアップデートを試したが再現は 20558 しなかった。 20559 20560 どの commit で問題が起こる様になったのだろうか。改めて怪しい変更がないか 20561 commit を眺めて見る。試しに bind '"hello":"world"' としたら再現した。改めて 20562 decode-char の呼び出し部分を確認する。もしかするとここを "${chars[*]}" にし 20563 ていたり変数に代入したりする過程でその様に加工してしまっているかもしれない。 20564 と思ったら、本当に "${chars[*]}" にしてしまっていた。一文字の修正である。 20565 20566 2021-05-07 20567 20568 * bind: fix a problem that "bind '"seq":"key"'" causes a loop macro "bind -s key key" (reported by thanosz) [#D1536] 20569 https://github.com/akinomyoga/ble.sh/issues/105 20570 20571 これはどうやら OpenSUSE の inputrc にある、テンキーの / のエスケープシーケ 20572 ンスを / に翻訳する keybinding の問題だった。ble.sh は左辺をキー列に翻訳し 20573 てから bind する。という事なので、 20574 20575 "escape-sequence": "key" 20576 20577 の様な binding が存在すると、key: "key" という形に翻訳されてしまう。そうす 20578 ると無限ループに変換されてしまうという事である。 20579 20580 これの対策は単に左辺と右辺が一致している時に binding を無視するというだけで 20581 良いのだろうか。或いは、それだけでは駄目なケースが存在するだろうか。例えば、 20582 20583 "escape-sequence-long": "escape-sequence-short" 20584 20585 という形になっていたとすると、 20586 20587 key: escape-sequence-short 20588 20589 という形になってしまって結局無限ループになってしまうのではないだろうか。現 20590 在の実装について改めて確認する→やはり左辺が keys で右辺が chars になってい 20591 るので単純に keys と chars を比較するのでは駄目である。結局 chars を keys 20592 に翻訳してから比較する事にした。実装した。テストした。動いている。OK 20593 20594 2021-05-06 20595 20596 * progcomp: aws_completer が呼び出されない (reported by Archehandoro) [#D1535] 20597 https://github.com/akinomyoga/ble.sh/issues/102 20598 20599 これは原因は分かった。complete -p の出力結果が quote されているのに、ble.sh 20600 はそれを直接解釈しようとしているのが原因であった。"'aws_completer'" という 20601 名前のコマンドを実行しようとして失敗している。 20602 20603 そもそもこれは complete -p の出力結果が quote されていたりされていなかった 20604 りするのが原因である。version 毎にどうなっているか確かめてみる事にする。 20605 20606 * コマンド名: コマンド名に関しては現在に至るまで一切 quote されない。 20607 20608 * -C の引数について: bash-3.2 までは裸で引数が出力されるだけであった。 20609 20610 * -F の引数も一切 quote されない。と思ったら bash-5.1 以降で -F を設定する 20611 時にチェックが入る様になった。然し、それでもブレース展開や履歴展開、変数 20612 展開も含める事ができるのでそのまま eval する訳には行かない。 20613 20614 * -WGXPS の引数: 常に quote される 20615 20616 * 引数が出力される順番は固定の様である。問題の -F func -C callback cmd はこ 20617 の順序で必ず最後に出力される。と思ったが、bash-4.0 以降では -C c -F f cmd 20618 の順序に変更になった。 20619 20620 まとめると、 20621 20622 * bash-3.2まで: complete [OPTIONS] -F str -C str cmd 20623 * bash-4.0以降: complete [OPTIONS] -C 'str' -F str cmd 20624 * bash-5.1以降: complete [OPTIONS] -C 'str' -F func cmd 20625 5.1 で安全になったかと思いきや func に !${} を含められるので駄目。 20626 20627 うーん。コマンド名に関しては末尾から削除すれば良い。quote をちゃんと辿って 20628 行けば -F が現れた時点でこれは確実に本物の -F である。更に -F の引数に関数 20629 名として不正な物を指定する理由もないので、-F の直後は一つの単語だけ読み取れ 20630 ば良い。すると残るのは (もしあれば) -C callback 名という事になる。 20631 20632 どの様に実装するか。結局どの bash version であっても -F func が quote され 20633 ないので eval するのは危ない。そもそも callback を設定する時点でその補完が 20634 呼び出された時点で駄目な訳だけれども、取り敢えず滅茶苦茶な事が起こらない様 20635 にする為には真面目に parse するのが良い。 20636 20637 a 後ろから parse するのは問題ないだろうか? ... これは危険である。例えば -F 20638 が見つかったとしてもこれが本当に -F なのかは分からない。偽物の -F で、実 20639 は其処よりも前にも quote されていない引数が潜んでいる可能性がある。 20640 20641 うーん。手順としては先ず初めに末尾にコマンド名が一致していればそれを除去す 20642 る (一致していなかった場合はどうするのかは謎)。次に正規表現で読める所まで読 20643 んで、それを eval する? 読みきれなかった部分については変数に残して置く。読 20644 めた部分を解析する。途中で -F に行き当たったら残りの文字列を特定して、続き 20645 は真面目に parse する事によって結果を得る? というか残りについては " -C " が 20646 含まれているかいないかで取り扱いを変更すれば良い気がする。然し、何らかのオ 20647 プションが -F の後に続いているという事もあるかもしれない。 20648 20649 取り敢えず実装した。動いている。もう一つの問題として aws の補完結果は末尾に 20650 空白を含めているのにも関わらず noquote 等の処置をしていないという事。うーん。 20651 これに関しては…。仕方がないので aws_completer 用の WA とする事にした。また、 20652 コマンド名なのに偶然でディレクトリ名に一致して suffix がついてしまう事につ 20653 いても workaround とした。但し、考えて見るに -F もしくは -C で生成した候補 20654 に対して suffix を付けるのも変な気がする。これについては改めて考えても良い 20655 のかもしれない。 20656 20657 * MSYS2 で Backspace で行全体が削除されるという話 (reported by n1kk) [#D1534] 20658 https://github.com/akinomyoga/ble.sh/issues/104 20659 https://sourceforge.net/p/msys2/mailman/msys2-users/thread/CAFLRLk-UX7S%3DTAerNix7HvxDAv4aY2FwZuFZz%3DU%2BTLBAWxCLEg%40mail.gmail.com/#msg37275646 20660 20661 取り敢えず MSYS2 の .inputrc が怪しいという事で msys2-users に報告した。そ 20662 れとは別に ble.sh の側でも対策する事は可能だろうか。 20663 20664 a 例えば MSYS2 にいる時には .inputrc は読み取らない (--noinputrc) 様にする? 20665 然し .inputrc だけ読み取らない様にしても仕方がない。ユーザー設定も読み取 20666 らない様にしないと bind で自動的に読み込まれた設定を読み取ってしまう事に 20667 なる。 20668 20669 b INPUTRC=/dev/null を設定してから bind で初期化する事により bashrc で設定 20670 されたユーザー設定だけを読み取るという手もある気がするが、これも source 20671 ble.sh よりも先に bind 関連の設定にユーザーが触れていると駄目である。 20672 20673 c 上記の問題は inputrc にある他の設定も全て潰してしまうという事である。それ 20674 ならば、C-? に対応する設定だけ ble.sh default に強制的に設定する様にすれ 20675 ば良いのではないだろうか。 20676 20677 取り敢えず c の方針で実装する事にした。この様にしたとしても C-x C-r で 20678 inputrc を再読込するとまた変な状態になってしまうが、これは仕方がない。 20679 20680 * complete: bash-completion bug workarounds (reported by oc1024) [#D1533] 20681 https://github.com/akinomyoga/ble.sh/issues/97 20682 20683 自分の手許でも色々エラーメッセージが出てうるさい。 20684 20685 bash-completion で修正を掛けるのは面倒だし時間がかかりそう。更に、各種 20686 distribution に波及する迄に更に時間もかかりそうなので取り敢えず暫定的に、 20687 ble.sh の側で bash-completion の実装を上書きする事にしてしまう。 20688 20689 * 2021-05-06 bash-completion 20690 https://github.com/akinomyoga/ble.sh/issues/97 20691 https://github.com/scop/bash-completion/pull/492 20692 Ref #D1533 20693 20694 python のテストを自分で実装したりしなければならず面倒である。 20695 実装した。PR を update した。これは向こうの反応待ち状態である。 20696 20697 * 2021-04-06 localvar_inherit で動かなくなっている [#D1532] 20698 20699 或いは元から動いた事はなかった可能性も? 20700 20701 * localvar_inherit をしていると local -r a した変数に対して、 20702 内側の関数で同名の変数を定義できなくなってしまう。 20703 20704 うーん。それでも未だ色々動かない。というか、バグというかちゃんと書 20705 かれていないコードを洗い出すのに使えるかもしれないとは思う。 20706 20707 * どうやら localvar_inherit になっていると local BASH_COMMAND としても 20708 BASH_COMMAND の値が変化する性質は受け継がれてしまう様である。 20709 20710 | RANDOM でも同様の現象が発生している。 20711 | 20712 | $ f1() { local RANDOM=hello; echo $RANDOM; RANDOM=world; echo $RANDOM; } 20713 | $ shopt -u localvar_inherit; f1 20714 | hello 20715 | world 20716 | $ shopt -s localvar_inherit; f1 20717 | 20034 20718 | 20034 20719 | 20720 | 何が起こっているのだろう。元の変数がそのまま見えているという事だろうか。 20721 | と思ったがそうでもない。unset RANDOM して見たが元の変数が消えるという事は 20722 | なかった。恐らく localvar_inherit の時には値が受け継がれるのではなくて、 20723 | setter/getter が引き継がれてしまっているのが原因なのだろうと思われる。 20724 | 20725 | bash を確認すると subst.c (expand_declaration_argument) では 20726 | localvar_inherit が設定されている時には declare は declare -I と同様の振 20727 | る舞いになる。 declare -I の説明を declare --help で確認すると値と属性を 20728 | 継承すると書かれている。 20729 | 20730 | if creating a local variable, inherit the attributes and value of a 20731 | variable with the same name at a previous scope 20732 | 20733 | と思ったが実装をよく見ても inheriting の値が一切使われていない気がする。 20734 | 不思議である。未実装なのだろうか。或いは何かを見落としている? どうもこの 20735 | 関数は arr=() の形式の引数を処理する時にだけ使われているという事だろうか。 20736 | 20737 | 実際に localvar_inherit の処理を具体的に処理しているのは variables.c の方 20738 | である様に思われる。特に以下の部分 (variables.c:2738) が setter/getter を 20739 | 継承するコードである。 20740 | 20741 | if (localvar_inherit || (flags & MKLOC_INHERIT)) 20742 | { 20743 | /* It doesn't make sense to inherit the nameref attribute */ 20744 | new_var->attributes = old_var->attributes & ~att_nameref; 20745 | new_var->dynamic_value = old_var->dynamic_value; 20746 | new_var->assign_func = old_var->assign_func; 20747 | } 20748 | 20749 | 明示的にコピーしているという事を考えるとこれを覆すのは難しいかも知れない。 20750 | 具体的に変な振る舞いをする例を作ってそれを呈示すれば何か考えて貰えるかも 20751 | しれない。getter/setter が関わっている関数は他にあるだろうか。 20752 | 20753 | INIT_DYNAMIC_VAR で検索するとそういった関数の一覧が得られる。 20754 | 20755 | - "SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds 20756 | - "FUNCNAME", (char *)NULL, get_funcname, null_assign 20757 | - "BASH_ARGV0", (char *)NULL, get_bash_argv0, assign_bash_argv0 20758 | - "BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL 20759 | - "BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell 20760 | - "RANDOM", (char *)NULL, get_random, assign_random 20761 | - "SRANDOM", (char *)NULL, get_urandom, (sh_var_assign_func_t *)NULL 20762 | - "LINENO", (char *)NULL, get_lineno, assign_lineno 20763 | - "BASHPID", (char *)NULL, get_bashpid, null_assign 20764 | - "EPOCHSECONDS", (char *)NULL, get_epochseconds, null_assign 20765 | - "EPOCHREALTIME", (char *)NULL, get_epochrealtime, null_assign 20766 | - "HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL 20767 | - "COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks 20768 | 20769 | TERM の場合はどうなっているのだろうか。これは special_vars という事になっ 20770 | ていて、値が変更した時に特別の関数が呼び出される様になっている。他に 20771 | TERM* や LANG, LC_* 等様々な変数がこれに相当する。これらは local に関係なく 20772 | 常に値が変更したら何か処理する事になっているので今回の振る舞いには関係ない。 20773 | 20774 | やはり勝手に上書きするのが悪いという結論になりそうな変数しか存在しない。 20775 | 敢えて言うならば RANDOM か LINENO ばかりだろうか。LINENO の方も確認したが、 20776 | やはり LINENO に対する代入は無視されて現在の行数が常に表示される様になっ 20777 | ている。因みに LINENO=1234 eval 'echo $LINENO' に関しては 20778 | localvar_inherit を設定しても特に変わりなく同名の tempvar が作成される。 20779 20780 bash のバグか或いは confusing behavior かどうかは別として、古い version 20781 に対しては取り敢えず修正しなければならないので、対策は行う事にする。時間 20782 があれば bash に報告・相談もする事にする。 20783 20784 * もう一つの問題は local -a buff とした後に ble/array#push としていると、前 20785 の配列の内容が既にあった場合にそれの続きとして値を push してしまうという 20786 事。こう言った使い方をしている箇所はないと思っていたが、確かめてみると古 20787 いコードを中心にして沢山あった。と思ったがそんなには無かった。合計で4箇所 20788 だけだった。 20789 20790 上記の事を直したら取り敢えず動いている様に見える。残りは具体的に問題が生じ 20791 てから対処する事にする。 20792 20793 * 2021-04-28 keymap 初期化に失敗した時にそれを検出しているのにも拘らず操作不能になる [#D1531] 20794 20795 $_ble_base_cache/keymap.emacs が空の時、The keymap 'emacs' is empty 等の様 20796 にメッセージが表示されて空かどうかのチェックが為されている筈なのに、その後 20797 に何も操作できなくなる。 20798 20799 ble/decode/attach の中でチェックが起こっている気がするが、その場合には 20800 attach せずに終わって操作不能にはならない筈なので関係ないかもしれない。 20801 20802 今試しに keymap.emacs を空にして bash --norc から ble.sh をロードしてみたが、 20803 stty の状態が変になる物の操作不能になる訳ではない。set -o vi でスタートさせ 20804 てset -o emacs で切り替えようとすると問題が再現する。つまり、detach して 20805 attach した時の問題である。 20806 20807 調べてみるとどうもコマンドは実行されている様である。stdout.off の状態になっ 20808 ている事によって操作できなくなってしまっているという事の様である。そしてそ 20809 れは、ble/decode/attach の呼び出し元の .check-detach の更に呼び出し元におい 20810 て、bind/.tail 経由で改めて stdout.off が実行されているという事になる。これ 20811 を抑制する為に、.check-detach の中で rebind に失敗した時には改めて 20812 .check-detach を呼び出して抜ける処理を実行する事にした。 20813 20814 →然しそれでもやはり stdout.off が呼び出されてしまう。と思ったが、どうも 20815 .check-detach の戻り値を使って実際に detach が起こったかどうかを伝達してい 20816 る様である。ちゃんと再帰的に呼び出した .check-detach の終了ステータスを外に 20817 伝播させる。これで問題なく抜ける様になった。 20818 20819 * 2021-04-06 main (--rcfile): 通常ファイルしか許可していないが [#D1530] 20820 20821 <() や /dev/null を食わせたい事もあるだろう。後、ファイルが見つからなかった 20822 時に結局 ~/.blerc を読み取ってしまうのは不便。ファイルが見つからなかった場 20823 合には何も読み込むべきではない。 20824 20825 --norc オプションにも対応した。 20826 20827 * syntax: eval() { echo yes; } が構文エラーになっている [#D1529] 20828 local, declare も同じ。 20829 20830 これは意外と簡単だった。処理順序を変えるだけで良かった。builtin の処理と 20831 keyword の処理が結合しているから切り離すのに時間がかかるのではないかと思っ 20832 たが、実際には builtin の処理は独立にしても問題ない様な実装になっていた。 20833 20834 * main: freeze-utility-path が一時実装を置き換えなくなっている [#D1528] 20835 20836 ble/bin/sleep を初期化する前に sleep の機能についてテストしている気がする? 20837 と思ったが最初に ble/bin/sleep を絶対パスではなくて command sleep で定義し 20838 ているので問題は起こらないのだった。というより、最近 freeze-utility-path で 20839 既存の関数がある時には上書きをしない様に変更したが、これは駄目だ。元々上書 20840 きする様になっていたのはこの一時的な実装を置き換える為であったのである。 20841 20842 然し、上書きする様に変更してしまうと freeze-utility が ble/bin/awk を上書きしてしまう。 20843 20844 a そうすると一時的な実装とそうでない実装を区別できる様に、関数か変数をマー 20845 カーに使う? 20846 20847 b 或いは初めからもう定義してしまって呼び出した時点でパスを決定する事にする。 20848 初期化の順序によっては fork コストがかかる可能性もあるが、 20849 それも少しだけなので余り気にしなくても良いかもしれない。 20850 20851 問題は ble/util/assign がちゃんと動作する迄に時間がかかるという事だから、 20852 ble/util/assign が準備できたかどうかを変数に記録しておけば良いのでは。 20853 20854 c 或いは ble/util/assign が準備できた時点で .freze-utility を改めて呼び出す 20855 事にする。直接呼び出しても良いし、それだと密結合になるというのであれば、 20856 hook か何かを準備しても良い。 20857 20858 d 或いは今まで通り freeze-utility は上書きをしてしまう様にする。awk に関し 20859 ては上書きしない様にリストから削除しておくか (然し削除の為にまたコードを 20860 書かなければならない。初期化時点では ble/array#remove もない)、或いは 20861 ble/bin/awk.protected か何かの様にして上書きをしない様に関数を定義する。 20862 20863 うーん。大きく変更するのも面倒なので ble/bin/awk.protected を定義するという 20864 方針にする。と思ったが関数が存在するかどうかのテストはやはり util.sh を待た 20865 なければならない。 20866 20867 ? ok: alias が定義されている時に freeze-utility は正しく動作するだろうか? 20868 →これは大丈夫。type -P としているから。 20869 20870 2021-05-04 20871 20872 * util: bleopt/check-all で obsolete な設定も読み取ろうとしてエラーになっている [#D1527] 20873 obsolete なオプションに対しては初期設定のチェックは行わなくて良い。 20874 20875 * syntax: 着色決定時に expand_aliases 設定が退避されている (reported by 3ximus) [#D1526] 20876 https://github.com/akinomyoga/ble.sh/issues/103 20877 20878 0860be0 に於いて内部では alias が展開されない様に shopt -u expand_aliases 20879 を設定していた。然し、よく考えてみたら構文着色等に於いて expand_aliases が 20880 有効かどうかによって処理を変えていた。つまり expand alias の処理の際にちゃ 20881 んと退避した設定を確認する必要がある。 20882 20883 実際に修正しようとしたら話はそう単純ではない様である。そもそも自分で shopt 20884 -s/-u expand_aliases を変更しようとしても完全に無視されてしまう。次のユーザー 20885 状態になる頃には勝手に元の値に戻ってしまっている。何故? 例えば 20886 POSIXLY_CORRECT を手で弄っている所為だろうか。或いは expand_aliases の保存 20887 復元の呼び出しタイミングが混ざっているからだろうか。それとも bind -x の中で 20888 変更した expand_aliases の状態は抜けると消えてしまうという事なのだろうか。 20889 20890 やはり自分では何も操作していないのに expand_aliases の設定が変わってしまっ 20891 ている。うーん。という事は…どうすれば良いのか? 20892 20893 * 内部で shopt -u expand_aliases にしたいというのは…。毎回 bind head で設 20894 定し直すぐらいしかできない→ bind/.head で再設定する様にした。 20895 20896 * ユーザーが設定した設定が保持されないという事に関しては。これは明示的に自 20897 分で保存復元する必要がある。特に restore する時には shopt -u 20898 expand_aliases も明示的に実行する。→これは bind/.head で設定する様にした 20899 ので、わざわざ自分で実行しなくても良い。 20900 20901 * エイリアスを展開する時に一時的に shopt -s expand_aliases 状態を復元する。 20902 と思ったが、それでは駄目だった。様々な所で ble/util/type を呼び出していて、 20903 その結果が alias にならないとそもそも expand-alias 関数自体が呼び出されな 20904 い。修正するべきは expand-alias ではなくて ble/util/type の方である。こち 20905 らを修正したら動く様になった。 20906 20907 * util: test-canvas.sh ext/contra 依存性の解消 [#D1525] 20908 20909 test-canvas.sh がエラーを出す様になっている。試すとテストを取り入れた時から 20910 既にエラーになっている。どういう事だろうか。と思ったが、テスト自体が 20911 ext/contra もしくは contra を前提としていた為に起こっていたエラーだった。存 20912 在しない時には通る様に書いたつもりだったがそうなっていなかった。 20913 20914 * awk で {m,n} は使えないという事 [#D1524] 20915 https://unix.stackexchange.com/questions/354553/awk-repetition-n-is-not-working 20916 Ref #D1522 20917 20918 更に nawk, mawk では十六進表記 0xHHHH も使えない。規格的には optional に対 20919 応しても良いという事になっている様だ。 20920 20921 更に mawk は match("AAA", /AA?A?/) としても2文字しか一致しない。/A(AA?)?/ 20922 という具合にしなければならない。 20923 20924 過去の互換性の為であると言っている割に POSIXLY_CORRECT=always を指定しても 20925 対応するという気配はない。 20926 20927 →特にこれらに引っかかりそうな箇所は今の所は見つからなかった。然し、 20928 今後の為にちゃんと記録しておく必要がある→ #M0019 に残す事にした。 20929 20930 * nawk の方が軽いので既定で nawk を使う様に変えてみる [#D1523] 20931 Ref #D1522 20932 20933 gawk 特有の振る舞いに依存している部分を洗い出す為にもこの変更は有用だろう。 20934 20935 x nawk を使う様にして試してみた所、初期化時に "function" というメッセージが 20936 沢山表示される → これは nawk とは関係なくて freeze-utility で追加したコー 20937 ドで既存の ble/bin/??? が定義されているかどうか確かめる type の出力を 20938 /dev/null に繋いでいなかったのが問題であった。 20939 20940 x また、use-solaris-xpg4 が他から参照されている。mshex にも 20941 akinomyoga.dotfiles にも use-solaris-xpg4 はない気がする。何処由来だろう 20942 か? →これは単に ble.pp に古いコードが残っていただけだった。 20943 20944 他にも様々な問題が発生した様に思われたが全て最近行われた別の変更によるバグ 20945 だった。一通り修正できたので改めてテストを行う。取り敢えず動いている様な気 20946 はする。 20947 20948 * 2021-03-15 巨大なディレクトリで TAB 補完が遅い (2) (reported by timjrd) [#D1522] 20949 https://github.com/akinomyoga/ble.sh/pull/65#issuecomment-798551355 20950 Ref #D1512 20951 20952 修正したと思ったが依然として時間がかかっている。 20953 20954 (1) 調べてみると、どうもconditional-sync が終わった後の 20955 builtin eval -- "$def" 20956 を実行する時に時間がかかっているという事。 20957 20958 これを高速化する方法はあるだろうか。というか assign-array では駄目なのだ 20959 ろうか。と思ったが、ファイル名に改行が含まれている可能性などを考えると駄 20960 目という事? 20961 20962 後気付いたのだが、ファイル名に改行が含まれている場合には何が起こるのだろう 20963 か。source:file はファイル名のチェックをしない様に今回書き換えたが実はこれ 20964 によって改行が含まれているファイル名の断片も生成される様になってはいないか。 20965 然し、eval-pathname-expansion で変な分割のされ方をしない限りは問題は起こら 20966 ないはずである。また、eval を経由して親に結果を渡す事によって、改行を含むファ 20967 イル名でも対応できる様になっている。 20968 20969 うーん。eval の中でも時間がかかっている様に思われたが、これも eval するため 20970 の文字列を構築するのに時間がかかっているという事なのだろう。 20971 20972 $ files=(*) 20973 $ time eval ': "${files[@]@Q}"' 20974 280ms 20975 $ time eval ': "${files[@]}"' 20976 216ms 20977 $ time for a in "${files[@]}"; do break; done 20978 235ms 20979 $ time echo ${#files[@]} 20980 0ms 20981 20982 これらの結果を見るに、インデックスでアクセスする様にするべきという事か。 20983 20984 $ time data=("${files[@]}") 20985 300ms 20986 20987 a ${files[@]:offset:length} を使って切り分ける? 20988 →これは遅い。 20989 20990 $ time : "${files[@]:0:100}" 20991 72ms 20992 $ time : "${files[@]:0:1000}" 20993 77ms 20994 $ time : "${files[@]:0:10000}" 20995 89ms 20996 20997 うーん。これ自体にも時間がかかっている。然し、1000 単位で分割しようとする 20998 と 200k の場合には全て処理するのに 20s かかる。10000 単位ならば 200k ファ 20999 イルに対して 2s 以下で処理できるが、元から 200ms かかっていたのが 2s に増 21000 えるのは微妙な気がする。等の事を考えると、これにかかる時間は仕方がないと 21001 諦めるべきか。 21002 21003 →単に ${arr[@]:xx:yy} が遅いというだけの様だ。 21004 21005 b 直接要素にアクセスする。 21006 21007 以下の様に直接アクセスすれば、全体を一気に置換した時と比べて遜色のない速 21008 度が出る。約2倍程度の速度低下で済んでいる。 21009 21010 $ time for ((i=0;i<200000;i++)); do v=${files[i]}; done 21011 500ms 21012 $ time for ((i=0;i<10000;i++)); do v=${files[i]}; done 21013 29ms 21014 21015 21016 ? 高速な配列の初期化と言えば history.sh である。結局どの様な方法を用いてい 21017 たのだったか。やはり eval だったような気もする。確認する。 21018 21019 うーん cygwin かそうでないかで場合分けしている。Cygwin 以外では mapfile 21020 を使って読み出している。改行を含む要素に関しては後で補正処理を行うという 21021 方法を用いている。Cygwin に於いては source している。中では恐らく直接巨大 21022 な配列のリテラルを指定している。 21023 21024 $ time x=$(declare -p files) 21025 72ms 21026 21027 実は declare -p 自体はそんなに低速ではない。 21028 現在の実装では quote を ${file[x]@Q} を用いて処理しているが、 21029 declare -p を用いれば多少の改善はできるかもしれない。 21030 21031 $ time eval "$(time ret=(*); time declare -p ret)" 21032 real 0m0.326s 21033 real 0m0.071s 21034 real 0m1.345s 21035 21036 $ cd /path/to/big-directory 21037 $ time files=(*) 21038 $ time def=$(declare -p files) 21039 $ time def=ret=${def#*=} 21040 $ time eval "$ret" 21041 21042 具体的に timjrd に計測してもらったがやはり eval "$def" で結構な時間がかかっ 21043 ている様子である。特に 33k の項目に対して 0.87s かかっている。手元では 200k 21044 項目に対して 0.40s かかっている。(線形時間を仮定すれば自分の手元では 33k に 21045 対しては 0.066 で処理できるので余り気にならなかったのだろう。) 21046 21047 因みに手元では配列のコピーも 0.27s かかっている。これはそんなに長くはないが、 21048 向こうでは 0.6s ぐらいかかるのだという事を示唆している。つまり、配列コピー 21049 も気安く行う事はできないのである。 21050 21051 手元でより高速な方法を模索してみる事にする。 21052 21053 a eval "$def" の処理時間は 200k 項目に対して 0.40s である。展開と読み取りに 21054 は 0.67s かかっている。total では 1.07s である。 21055 21056 b printf '%s\0' "${ret[@]}" で出力した結果を mapfile -d '' で読み取る方法を 21057 試してみた。結果、読み取りに 0.74s かかっている。実は eval による手法より 21058 も時間がかかっているという事になる。展開も含めた total の時間は 1.17s で 21059 ある。total で考えれば手法 a とそんなに変わらないが、中断できないという事 21060 が問題である。 21061 21062 更に mapfile -d "" は 4.4 以降でしか使えないので、4.3 以下でも使える様な 21063 read -d '' による方法の速度を計測してみた所、75s かかった。 21064 21065 | if ((_ble_bash>=40300)); then 21066 | printf '%s\0' "${ret[@]}" 21067 | else 21068 | fi 21069 | if ((_ble_bash>=40400)); then 21070 | time ble/util/assign-array0 ret 'ble/util/conditional-sync "$sync_command" "" "" "$sync_opts"' &>/dev/null; local ext=$? 21071 | else 21072 | fi 2>/dev/tty 21073 21074 c source にしたら total 時間を減少させる事ができるだろうか。 21075 21076 2021-05-01 時間が空いてしまったので改めて現状を整理する。問題は subshell で 21077 得たファイルリストをどうやって親シェルに伝達するのかという事。500k の文字列 21078 配列を現実的な時間内に親シェルに伝達し、更に中断も可能である必要がある。 21079 21080 例を交えて説明するとしたい事は以下の事である。現状で、eval "$(< a.tmp)" が 21081 遅いというのが問題である。合計時間が長いというのは未だ良いのだが問題はユー 21082 ザーからの interrupt があった時に中断できないという事にある。 21083 21084 ( 21085 a=({000000..500000}) 21086 declare -p a > a.tmp 21087 ) & 21088 wait $! 21089 eval "$(< a.tmp)" 21090 21091 declare -p a の実行自体はそんなに時間はかからない。また mapfile も比較的高 21092 速である。問題は declare -p a だと eval (遅い) で読み出す必要があって、 21093 mapfile にする為には要素を printf で出力する必要があるという事。 21094 21095 a printf '%s\0' / mapfile -d '' (2.5 + 1.6) 21096 21097 そうだとしても printf '%s\0' で出力して mapfile -t -d '' で読み出すのが一 21098 番高速でかつ中断可能の気がする。と思って試してみた所、mapfile は -d '' を 21099 指定した瞬間に遅くなってしまった。どういう事だろうか。最新版 bash でも同 21100 様である。 21101 21102 b echo / mapfile -t (3.2 + 0.1) 21103 21104 この方法は高速であるが代わりに改行を含む様な要素について特別な対処が必要 21105 である。また時間のかかっている部分での中断も容易である。 21106 21107 特別な対処を実装したら合計で 3.2+0.1 になった。それでも他の方法よりは高速 21108 である。これが現実的な解であるような気がする。合計の処理時間は2倍以上になっ 21109 てしまうが。 21110 21111 c declare -p a | awk ??? 21112 21113 declare -p を awk で処理する事を考えたが awk には行に含まれる文字数の上限 21114 があるのではなかったか。本当にそれを正しく処理できるのだろうかという懸念 21115 は残る。もしそうだとしても物凄く長い行を処理しても処理能力の低下は起こら 21116 ないのだろうか→文字数の制限が厳しいのは sed 実装だった気がする。POSIX 的 21117 には awk も制限があったけれども実際の実装ではそんなに問題にならなかったの 21118 だという気がする。 21119 21120 読み取りの速度を考えると mapfile-nfix で読み取れる形式に変換するのが良い。 21121 つまり、declare の parse を awk で行うという事である。declare の形式は 21122 version によって異なっていたりバグがあったりするが…。 21123 21124 やはり速度という観点で一番良いのは declare -p a | awk して mapfile-nfix で 21125 読み取るという物の様に思われる。それとは別に何故 mapfile -d '' が遅いのかと 21126 いうのは気になる所ではある。 21127 21128 ? 何故 mapfile -d '' は遅いのだろうか。 21129 21130 | 確認してみると delim が \n 以外の場合には unbuffered read に切り替える様 21131 | になっている。何故だろうか。zgetline の実装を見ると delim を引数に受け取 21132 | る様になっている。更に、zgetline は zread もしくは zreadc を呼び出してい 21133 | る。最終的に buffered の場合には read(fileno, buf, bufsz) を呼び出して、 21134 | unbuffered の場合には read(fileno, buf, 1) を繰り返し読む様になっている。 21135 | 実装を読む限り \n かそうでないかで振る舞いを変更する理由もない様な気がす 21136 | る。不思議である。理由について尋ねても良いだろうか。 21137 | 21138 | Greg に最終的な目標は何なのか。不適切な事を Bash で実行しようとしているの 21139 | ではないか、という様に文句を言われるかもしれない。その時の為に説明を書く 21140 | のが良い気がする。 21141 | 21142 | get_file_list() { 21143 | (files=(*); declare -p files > tmpfile) & bgpid=$! 21144 | while :; do 21145 | if has_background_completed "$bgpid"; then 21146 | eval -- "$(< "$tmpfile")" 21147 | return 0 21148 | elif has_user_interrupted; then 21149 | cancel_everything "$bgpid" 21150 | return 1 21151 | else 21152 | my_sleep 0.1 21153 | fi 21154 | done 21155 | } 21156 | 21157 | $ a=({000000..500000}) 21158 | $ printf '%s\n' "${a[@]}" > tmp 21159 | $ mapfile -t a < tmp 21160 | 21161 | $ printf '%s\0' "${a[@]}" > tmp 21162 | $ mapfile -d '' a < tmp 21163 | 21164 | builtins/mapfile.def L187..L194 21165 | > #ifndef __CYGWIN__ 21166 | > unbuffered_read = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE); 21167 | > #else 21168 | > unbuffered_read = 1; 21169 | > #endif 21170 | > 21171 | > if (delim != '\n') 21172 | > unbuffered_read = 1; 21173 21174 これは報告した。 21175 21176 さて declare -p | awk を実装してみたが遅い。実装している内に気づいたが、awk 21177 では文字列の途中から一致させる事ができないので、一致範囲を毎回切り出す必要 21178 があって、これを巨大な文字列に適用すると大変な事になる。今迄の実装で 21179 declare -p | awk が使えていたのは正規表現で一気に全体を置換するという様な簡 21180 単な処理しかして来なかった為である。 21181 21182 →これについては split(s, a, / /) で分割して各要素について処理する様にした 21183 ら改善した。 21184 21185 然しそれでも unescape の処理によって格段に時間がかかっている事は確かである 21186 様な気がする。もっと手っ取り早く変換する事はできないだろうか。例えば "..." 21187 と $'...' の何れかしか使われないという仮定で単純化できないか等。しかし、例 21188 えば空白一文字取って見ても " " の内部と、要素と要素の間の " [...]=" を明確 21189 に区別できる様な正規表現はない様に思われる。或いは "..." 全体に一致する様な 21190 正規表現を書ければ、特定の文字列を []="..." の直後に挿入して、更にその後に 21191 その特定の文字列を使って分割する事が可能だろうか。然し、その為には & または 21192 \1 等による後方参照で元々の文字列を置換後に参照する必要がある。gawk の 21193 gensub を使えば可能かもしれないが、その儘の awk では難しいのではないだろう 21194 か→改めて確認した所、 21195 21196 ? 今試している awk 実装では問題になっていないが、この様な巨大な処理をすると 21197 なると awk 実装によってはとても遅くなる可能性があるのではないだろうか。 21198 21199 | →試してみたらそもそも動作していなかった。動かないと思ったらそもそも nawk 21200 | は {m,n} に対応していない? 21201 | 21202 | $ echo '000' | nawk '/[0-9]{3}/' 21203 | $ echo '000' | mawk '/[0-9]{3}/' 21204 | $ echo '000' | gawk '/[0-9]{3}/' 21205 | 000 21206 | 21207 | この様な事態になっている。これは大変な事である。つまり、ERE は使えると思っ 21208 | て書いていると痛い目を見るという事である。更に調べると gawk-3.0 でも 21209 | --posix または --re-interval オプションを指定する必要があった様だ。 21210 | 21211 | https://unix.stackexchange.com/questions/354553/awk-repetition-n-is-not-working 21212 | 21213 | gawk であれば --posix または POSIXLY_CORRECT=always を指定すれば良いそう 21214 | だが、どの道他の実装では使う事ができない。という事を考えると一概に使えな 21215 | いと思っておくべきである。 21216 | 21217 | * 更に 0xHHHH もエラーメッセージなく勝手に 0 と解釈されていた。 21218 | 21219 | * また printf("%s\0",line) は普通に \0 が null-terminated と見做されて 0 21220 | は出力されない。これは gawk の振る舞いの方が特殊である様に思われる。 21221 | printf("%s%c", line, 0) で出力する事にする。 21222 | 21223 | * mawk は /[0-9][0-9]?[0-9]?/ としても /[0-9][0-9]?/ になってしまう。 21224 21225 色々互換性の問題を修正した。見た感じだと nawk も mawk も gawk よりは高速 21226 である。余り気にしなくても良さそうである。 21227 21228 ? 更に変な内容がなければもっと高速化できるのではないだろうか。 21229 21230 例えば全て []="..." の形式だったならば、最初に " []=" を全て他と当たらな 21231 い様な物 (例えば ^A) に変換して、その後で "" の中身の unescape 処理をして 21232 から分割すれば良いのではないか。unescape は \\ -> ^B, \" -> ", \$ -> $, 21233 \` -> `, ^B -> \ とすれば良い。 21234 21235 取り敢えず新しく実装した ble/util/{read,write}array を使う様に変更してみた。 21236 21237 * main: ble-reload するとプロンプトの計算の箇所で問題が生じる [#D1521] 21238 21239 これは当初 nawk のテスト時に気がついた問題なので nawk に関連して生じている 21240 のかと考えたが、gawk で試しても同様の問題が生じた。 21241 21242 遡って調べてみると実は 82c5ece で発生する様になった問題の様である。 21243 取り敢えず bleopt/check-all でエラーが発生しているのかもしれない。 21244 →これが原因だった。これは独立な問題として commit する事にする。 21245 21246 * set -o posix の時、ユーザーが read -e を呼び出すと [#D1520] 21247 何にも動かなくなるのではないか。 21248 21249 a 然し、read -e 自体が posix の範囲外なので仕方がないという見方もできる。 21250 21251 b 或いは、set -o posix の時には set -o emacs / set -o vi の切り替えを利用して 21252 read が使える様に調整するという事も原理的には可能である。その場合には実際に 21253 bind する対象の keymap が反転するので大幅な改修が必要かもしれない。 21254 21255 x 然し、vi mode 及び emacs mode に切り替える機能も存在した筈である。これを 21256 呼び出されると結局 ble.sh の管理下の keymap が前に出てきて問題になる。 21257 read の中から呼び出された事を検出してどうにかその場で取り繕う事は可能だろ 21258 うか。 21259 21260 c 別の方法で read が呼び出される瞬間を検出できないだろうか。或いは read -e に 21261 よって最初に widget が呼び出された瞬間に POSIX を始めとする様々の設定を回復 21262 する? その場合には C-c で read をキャンセルした場合にまた元に戻す事を忘れて 21263 はならない。 21264 21265 d ユーザーがコマンドを実行する度に realine 設定を完全 unbind して、終わったら 21266 再度 bind し直す。でも、これは文法エラー等によってコマンド実行が中断された 21267 時に、ble.sh session に復帰せずに通常の readline の状態に落ちてしまう。 21268 21269 →どうやら set -o posix でも本来の意味を取り戻す builtin とそうでない 21270 builtin が存在する様で、read の場合には set -o poix であっても関数が定義さ 21271 れていればそちらが呼び出される様である。なので気にしなくて良い。本当に問題 21272 が起こるのは builtin read -e が実行された時になるが、これは元から動いていな 21273 かった。 21274 21275 実の所、builtin read -e に対しても制御を全く失う様な事態にならない様にした 21276 いが、それはまた別に考えた方が良いのでは? と思ったが、此処での考察はその場 21277 合にも同様に適用できる→別項目に残す事にした。 21278 21279 2021-04-30 21280 21281 * 2021-03-21 set -o posix してから source ble.sh すると失敗する [#D1519] 21282 21283 先に source ble.sh してから set -o posix する分には即座に問題は起こらない。 21284 然し ble-attach に失敗するという可能性は存在する。うーん。 21285 関数を新しく定義するという事をしなければ特に問題は発生しない? 21286 21287 POSIX モードに対する処理は関数の外で実行する事にした。同時に順序を変えて一 21288 番最初に POSIX モードを ble.sh 内部状態として調整する事にする。 21289 21290 ? done: 実のところ、enter/leave でユーザーの設定した同名の alias/function 21291 を保存し、それからまた後で復元するという事も原理的には可能なのではないか 21292 21293 …と思ったが、果たして其処までの事をする必要はあるだろうか。保存の為にま 21294 た色々コマンドを走らせなければならなくなるが重くはならないだろうか。と思っ 21295 たが、alias ... declare -pf ... を呼び出すだけなので実はそんなに処理とし 21296 て重い訳ではない。問題は alias や declare が勝手に置き換えられていた時に 21297 ちゃんと動作するのかという話である。 21298 21299 結局実装する事にした。 21300 21301 ? done: 現在二段階に分けて unset -f しているが POSIXLY_CORRECT しているのだ 21302 から、builtin も unset も本来の意味を取り戻している筈で、それならば一回の 21303 unset -f で十分なのではないか。 21304 21305 x fixed: 現在 set -o posix, +o posix を使ってモードを切り替えているが、これ 21306 は setを上書きされていた場合に使えない。直接変数に代入するべきである。更 21307 に言うと、local ... も使えるとは限らない。local が上書きされているかもし 21308 れないから。という事を考えると、これも直接グローバル変数の値を変数代入で 21309 変更するべきである。 21310 21311 →これは確認した所、元から殆どその様になっていた。新しく追加したコードだ 21312 けで set を使っていたので、これを全て POSIXLY_CORRECT=y 及び \builtin 21313 unset -v POSIXLY_CORRECT に書き換えた。また、unset は -o posix の時にだけ 21314 実行する様に変更した。-o posix の時には \builtin unset は本来の意味で解釈 21315 される事が保証されているからである。 21316 21317 ? と思ったが、unset を使って解除する場合には見えている一番上の 21318 POSIXLY_CORRECT が解除されるだけで、更に呼び出し元のスコープで定義され 21319 ている POSIXLY_CORRECT が存在した場合には依然として set -o posix のまま 21320 になるのではないか。 21321 21322 $ f1() { local POSIXLY_CORRECT=y; f2; echo f1:$SHELLOPTS; } 21323 $ f2() { local POSIXLY_CORRECT=y; f3; echo f2:$SHELLOPTS; } 21324 $ f3() { set +o posix; } 21325 $ f1 21326 $ f2 21327 21328 試して見た所、unset POSIXLY_CORRECT だとやはり、更にその上の階層の状態 21329 が見える様になるだけである。そして、set +o posix も全く同じに作用すると 21330 いう事が分かった。 21331 21332 但し考えて見るに ble.sh はトップレベルで動いていてその途中で 21333 POSIXLY_CORRECT を設定して動作するという事もないので、unset が途中の関 21334 数スコープの POSIXLY_CORRECT に当たるという事もない。従って、普通に 21335 unset -v POSIXLY_CORRECT を一回実行するだけで問題ない。 21336 21337 何か問題が起こるとすれば、ble-attach もしくは source ble.sh を実行した 21338 時に複数の local POSIXLY_CORRECT=y の中で実行された時である。然し、この 21339 場合にはどうにも対策の仕様がない。unset -v を繰り返し呼び出す事によって 21340 POSIXLY_CORRECT を解除する事はできるが、然しこれを実行すると呼び出し元 21341 で実行した local POSIXLY_CORRECT の意図を壊してしまい呼び出し元で問題が 21342 生じる可能性がある。 21343 21344 実はこの事まで考えると set +o posix や set -o posix で POSIX 状態を操作 21345 するのは不味いのではないかという気がする。呼び出し元で設定した 21346 POSIXLY_CORRECT の動作を破壊してしまう。 21347 21348 x posix にしていても eval の中の alias 置換を防ぐ事はできないのでは。 21349 alias 展開をオプションで無効にする必要があるのではないか。 21350 そして alias は割とあらゆる箇所で影響が出る。 21351 これは大丈夫だろうと思っている if や [[ 等も対象である。 21352 21353 | a builtin に関しては危ない所を全て \builtin 等に書き換えてしまえば問題ない。 21354 | 21355 | grc '(^|[[:space:];|&('\''"])builtin\b' --exclude={wiki,ext,memo} 21356 | 21357 | b 或いは shopt expand_aliases を off にして処理を行う? うーん。ble.sh の内 21358 | 部では expand_aliases を off にするのが良い気がしてきた。 21359 | 21360 | c と思ったが ble.sh に影響を与える様な alias だけを off にすれば良いので 21361 | あって全ての alias を off にする必要性もない。そして ble.sh に影響を与 21362 | える様な物に関しては、ble.sh の処理中には unalias してしまっている筈な 21363 | ので殆どの場合は大丈夫な筈なのである。 21364 | 21365 | ユーザー実行環境で ble.sh 関数が呼び出されて、その ble.sh の中で eval 21366 | をした時に alias 置換が発生するという状況は考えられるが、まあ、その様な 21367 | 場合にまで気を配る必要は今の所ないと考えている。 21368 | 21369 | 取り敢えず、adjust-builtin-wrappers が呼び出される所までは \builtin の 21370 | 様にして escape する必要がある。後、adjust-builtin-wrappers 自体の処理 21371 | でも対策が必要になる。 21372 | 21373 | * 特に、adjust-builtin-wrappers の中で eval を実行しているが、其処で 21374 | alias 展開が起こると問題である。特に ble/util/assign によって実行され 21375 | る eval が問題になるのではないか。 21376 | 21377 | 後、ble/util/assign の中でも 21378 21379 結局 expand_aliases を off にする事にした。ble.sh を読み込んで 21380 expand_aliases を無効にする迄の部分を \builtin の様に quote すれば良い。 21381 一旦関数を定義してしまえば実行時に書き換わる事はないので、気にしなくて良 21382 い。気にするべきは eval で実行される文字列 (新しく解析される文字列) であ 21383 る。 21384 21385 * resolved: 保存・復元の時に sed を使っているがこれを置き換えられないか。 21386 21387 | これは ble.sh 読み込み時の最初の最初の部分なので sed が PATH に含まれてい 21388 | ない可能性も考える必要がある。sed の代わりに使える物はないだろうか。 21389 | 21390 | a 例えば extglob を有効にしてパラメータ展開で置換を実行するというのは一つ 21391 | の手である。 21392 | 21393 | この方法だと一回 type の出力を変数に格納する必要がある。従って、余分に 21394 | $(subshell) を実行する事になってしまって非効率的である。と思ったが、パ 21395 | イプにする事によっても subshell が 2 つ余分に生成されるのだから、$() に 21396 | しても特に overhead にはならない気がする。 21397 | 21398 | 然し extglob を on/off するのはそれはそれでまた面倒である。 21399 | 21400 | b どうにかして sed の binary を見つけてそれを先に ble/bin/sed に登録して 21401 | しまう? 然し、その為に色々の処理が必要で、その処理を不明な環境で安全に 21402 | 実行するのもまた面倒である。 21403 | 21404 | 後、最初の実行時には注意深い実装が必要かもしれないが、一旦初期化が終わっ 21405 | てしまえば、ble/bin/sed を使っても良いし、ble/util/assign も軽い実装を利 21406 | 用する事ができる。いっその事、初めから初期化前用の実装と、初期化後用の実 21407 | 装に分けても良い気がする。 21408 21409 汚いが extglob で処理する事にした。 21410 21411 実際に動かしてみると bash-3.0 で滅茶苦茶遅い。何故だろうか。bash-3.1 では 21412 特に問題は起きていない。調べてみた所、+([[:lower:]]) とすると遅い。 21413 +([a-z]) は遅くない。直接書く様に修正した。 21414 21415 * 現在の待避コードの順序について考える。 21416 21417 posix だとそもそも ble/* という関数自体定義する事ができない。一旦関数さえ 21418 定義できてしまえば関数呼び出し自体はできる。 21419 21420 FUNCNEST の設定。関数定義はできるが関数呼び出しができないという状態だと駄 21421 目なので。 21422 21423 * 一応各 builtin について動作確認をしておく。 21424 21425 builtin, unset, eval はOK 21426 return, break, continue, local もOK 21427 21428 % declare は駄目だった。というのも関数定義を抽出するのに使っているから。set 21429 % -o posix していても declare は回復できないのだという事。うーん。つまり 21430 % builtin か declare のどちらかは必ず先に unset しないと動かないという事。 21431 % 21432 % local の方を諦める事にした。local を上書きしてもローカルに変数が作られる 21433 % 事になる為、期待した効果を再現する事は不可能になる。なので敢えて上書きし 21434 % ようという人はいないだろう。declare だと機能を勘違いしている人が上書きし 21435 % ている可能性がある。また最初の local POSIXLY_CORRECT が効果を失うのも避け 21436 % たい。 21437 21438 やはり他にも色々動かない物があるので local を諦めるだけでは済まない。やは 21439 り builtin の復元を諦める事にする。そもそも builtin を置き換えようとする 21440 事自体が異常である。何か一つ置き換えを禁止するのだとしたら builtin にする 21441 のが自然ではある。 21442 21443 x fixed: : は保存できていない。もしかすると set -o posix の時には declare 21444 -pf で定義を出力できないという事? 確かめてみたが別にそういう事はない様 21445 である。という事は逆に定義する時に失敗しているという可能性? 21446 21447 x fixed: ble-reload 後に ble-detach を実行すると以下のメッセージが出る。 21448 21449 | bash: builtin: is: シェルのビルトイン関数ではありません 21450 | bash: enable: is: シェルのビルトイン関数ではありません 21451 | bash: enable: a: シェルのビルトイン関数ではありません 21452 | bash: enable: shell: シェルのビルトイン関数ではありません 21453 | bash: unalias: is: 見つかりません 21454 | bash: unalias: a: 見つかりません 21455 | bash: unalias: shell: 見つかりません 21456 | bash: unalias: builtin: 見つかりません 21457 | bash: return: is: 数字の引数が必要です 21458 21459 これを見るに何らかのエラーメッセージがコマンドとして実行されている? 21460 21461 然し、ble-reload の後に履歴が可笑しくなっているのも、ble-detach の後に変 21462 な状態になっているのも治っていない。これらはまた別の問題という事か。 21463 21464 どうも _ble_bash が変な値になっていて、それによって別のコードが呼び出され 21465 ていたという事。そしてそのコードはちゃんとテストされていなかったので元々 21466 バグを持っていて、それが発現していたという事の様である。そもそもそのコー 21467 ドは set -o posix でも動く関数定義取得の為に declare -pf と type を切り替 21468 えて使っていた物だったが、そもそも関数名が通常の識別子である限りは 21469 declare -f を常に使っていれば特に問題はない。基本的には declare -f を使っ 21470 て、: だけは bash の version で切り替える事にした。 21471 21472 以前使っていた declare -pf / type の切り替えによるコードは以下に残して置 21473 く。 21474 21475 | if ((_ble_bash>=40300)); then 21476 | builtin local defs 21477 | ble/base/adjust-builtin-wrappers/.assign ' 21478 | \builtin declare -pf "${builtins1[@]}" : 21479 | \builtin alias "${builtins1[@]}" "${keywords1[@]}" :' 21480 | else 21481 | builtin local fname 21482 | ble/base/adjust-builtin-wrappers/.assign ' 21483 | \builtin declare -pf "${builtins1[@]}" 21484 | \builtin alias "${builtins1[@]}" "${keywords1[@]}" :' 21485 | defs=$'\n'$defs 21486 | 21487 | # Note: bash-3.0 だと何故か extglob +([]) の中で [:alnum:] や [:lower:] 21488 | # を使うと滅茶苦茶遅い。何れにしても locale 依存になるのは避けたいので、 21489 | # 直接 a-z と書くのが良い。 21490 | builtin local pattern=$'\n+([][{}:a-z]) is a function\n' 21491 | if builtin shopt -q extglob; then 21492 | defs=${defs//$pattern/$'\n'} 21493 | else 21494 | builtin shopt -s extglob 21495 | defs=${defs//$pattern/$'\n'} 21496 | builtin shopt -u extglob 21497 | fi 21498 | fi 21499 21500 さて、これで問題は "何故 _ble_bash が消えて無くなるのか" という事に集約さ 21501 れる。(履歴の振る舞いが変になるのも古い bash の history -s の振る舞いが変 21502 だという事と関係しているのだろう。また、C-d の反応が悪いのも関係している 21503 だろう。) 21504 21505 実際に _ble_bash が空になっているという事が確認できた。 21506 21507 そしてそれは何故かというと ble/base/unload-for-reload で _ble_bash を 21508 unset しているのが原因だった。つまり、unload-for-reload を呼び出す迄は 21509 _ble_bash 等の初期化は遅延した方が良いという事なのだろう。builtin に対す 21510 る対策は _ble_bash には頼らずに version 判定するべきなのである。→結局ど 21511 の bash version でも動作する様に常に type を使って関数定義を得る事にした。 21512 21513 x fixed: ble-reload すると何故か履歴項目が最後の項目に対する追記の様になっ 21514 てしまっている。ble-reload ではなくて source ble.sh しても同様の問題が発 21515 生する。bash --rcfile out/ble.sh としても発生している事を考えると mshex 21516 等の他の設定との組み合わせで起こっている問題ではなくてそれ自体として発生 21517 している問題である。 21518 21519 遡って見ると #D1519 の問題であるという事が判明した。これは #D1519 の下で 21520 議論するべきであろう。然し、そうだとしても何が原因になっているのかは謎で 21521 ある。構文着色も動いている様に見えて何だか不思議な動作をしている。原因を 21522 特定する為に幾つか振る舞いを変えて試してみる必要がある。 21523 21524 * 保存していた builtins を復元しない様に変更したが特に変化はない。依然と 21525 して変な振る舞いを続けている。 21526 21527 * adjust/restore-builtin-wrappers を使わない様にしても変な振る舞いを続け 21528 ている。 21529 21530 うーん。コードを見ても怪しい所は見つからない。明らかに機能不全を起こして 21531 いる箇所があるのだから其処を手掛かりに原因を探る方が懸命である様に思われ 21532 る。 21533 21534 ble-detach で発生するエラーについて調べようとしたが原因の設定では再現しな 21535 い様である。再現する為の条件があるという事か? 或いは ble-detach で発生す 21536 るエラーに関しては実は adjust/restore-builtin-wrappers が関係しているとい 21537 う事だろうか。 21538 21539 これの原因は前の項目で判明した _ble_bash の消滅だという事が分かった。一緒 21540 に治った。 21541 21542 2021-04-28 21543 21544 * blerc にユーザーが使いそうな ble-bind を載せても良いのではないか (motivated by Alyetama) [#D1518] 21545 21546 ble-bind -f up 'history-search-backward immediate-accept' 21547 ble-bind -f down 'history-search-forward immediate-accept' 21548 21549 やその他の Vim の説明に書いた ble-bind など。 21550 magic-space の効果をなくす為の ble-bind も。 21551 21552 * nsearch の再設計について (motivated by Alyetama, rashil2000, carv-silva) [#D1517] 21553 https://github.com/akinomyoga/ble.sh/issues/101 21554 https://github.com/akinomyoga/ble.sh/issues/80 21555 21556 一旦は bleopt オプションを追加すると書いたが、ここは widget の引数として 21557 opts を受け取る様にして、readline settings を読み取る時の振る舞いは適当に 21558 Bash に合わせる様にする方が良いのではないかという気がする。或いは、多少はユー 21559 ザーが期待する様な振る舞いに調整しても良い。 21560 21561 * 実際に history 内部を移動するかどうか。現在の振る舞いは history の中から 21562 "load" するという振る舞いになっているが、本当は isearch と同様に history 21563 の内部を "移動" するという振る舞いの方が分かりやすい。 21564 21565 action=load 21566 action=move 21567 21568 * 空文字列の時に唯の行移動に fallback するかどうか。 21569 * 空文字列の時に前回と同じ文字列で検索するという手もある。 21570 21571 empty=line-move 21572 empty=graphical-line-move 21573 empty=logical-line-move 21574 empty=history-move 21575 empty=previous-search 21576 21577 空文字で検索する事はない様に変更する。 21578 21579 * カーソル位置を何処に置くか。 21580 point=end 21581 point=begin 21582 point=preserve 21583 21584 * nsearch status を表示するかどうか。 21585 hide-status 21586 % hide-status-on-empty 21587 21588 * 下を押し続けた時にまた元の状態に戻る様にする。 21589 これはオプションにしなくて良い。 21590 21591 C-x p 等の時には以下の設定で実行する。 21592 21593 action=move:point=preserve:empty=line-move 21594 21595 readline function 経由での呼び出しではできるだけ Bash の振る舞いを再現する? 21596 21597 action=load:point=preserve:empty=line-move 21598 21599 % うーん。実は Bash も空文字列の検索に対しては特別の挙動をしている様だ。 21600 % つまり、今まで議論で一貫性のある振る舞いについて考えていたが、これは既 21601 % に Bash が自然な形で破っているので Bash に従うべきなのである。 21602 21603 →改めて Bash を試してみた所、やはり単純に行を移動しているだけではない様 21604 に見える。カーソルを行末に移動しているが、それによって次の検索内容が変化 21605 するという訳でもない。実際、ble.sh の実装に於いて、空文字列に対して単に行 21606 移動の widget に委譲してしまうと、次の up の呼び出しの時に新しくロードし 21607 た文字列全体に対して再度検索が走ってしまう。 21608 21609 point=end をリクエストされたが正直これはデフォルトにしなくて良い。 21610 変更したければ自分で nsearch に point=end を指定して ble-bind して貰う。 21611 21612 色々考えると実は hide-status-on-empty は実装しなくても良いのではないかとい 21613 う気がしてきた。理由付けとしては空文字列検索を行うオプションはそもそも存在 21614 しないから。というか、hide-status 自体表示する必要がないのかもしれないとも 21615 思った。然し、一応実装しても良い気がする。 21616 21617 21618 [疑問] 21619 21620 * ok: isearch に対する疑問。現在履歴位置の古い内容に一致しないのか。 21621 21622 % よく分からないのは現在履歴項目を遡った状態であった時に、現在の履歴の内容 21623 % に一致したらどうするのかということである。うーん。isearch はちゃんと遡っ 21624 % ている時にはその内容に一致している気がする。が、それは何でかというと他の 21625 % 場所に周遊している時にはその時の編集している内容は履歴に反映させている為 21626 % である。此処での疑問は、cyclic で検索している時に、現在の編集内容では消え 21627 % ているが、現在位置の履歴に残っている文字列に一致する場合に何が起こるのか 21628 % という事 21629 % 21630 % →うーん。試そうとしたが isearch で入力している内に最初の方に入力した文字 21631 % に一致する項目にジャンプするので実の所、この様な状況が発生する事は滅多 21632 % にない。 21633 % 21634 % しかし原理的には現在位置の古い内容に一致してしまう事がある気がする。これ 21635 % を回避するには検索を開始する前に現在の編集内容を履歴に反映させておくか、 21636 % 或いは、cyclic で検索するにしても現在位置には一致しないようにしておくか。 21637 % 現在の実装ではどちらかになっているのだろうか。 21638 % 21639 % コードを確認した所、気になる部分を見つけた。#D1025 で同様の問題があって部 21640 % 分的な修正が行われた様に見える。何れにしても基本的には isearch は非 21641 % cyclic な検索になっているので、そもそも巡回して現在の位置が検索対象になる 21642 % 事がないので気にしなくて良かった。 21643 21644 →isearch は現在履歴位置については自分でテストして、それ以外については非 21645 cyclic な検索で次の項目から検索する様にしているので、現在履歴位置の古い内 21646 容に一致する事はない。 21647 21648 [実装] 21649 21650 * ok: 先ず初めに down を続けた後に元のコマンドライン文字列を回復する機能に 21651 ついて考える。 21652 21653 ? そもそも既に history の途中に移動している状態で nsearch を始めた時はど 21654 うなるのか? →変な振る舞いになっている。#1 から更に down を押したら元に 21655 戻るべきなのに、改めて上方向に検索して #2 という状態になっている。更に 21656 付け加えるならば "echo" という文字列には一致しない。 21657 21658 うーん。元のコマンドライン文字列に戻った時に、nsearch 状態が継続している 21659 とするか、或いは、nsearch 状態から抜けるか。again または input の時には、 21660 元のコマンドライン文字列に戻ってしまうのは変である。元のコマンドライン文 21661 字列に必ずしも一致するとは限らないので。(然し、逆に言えば元のコマンドライ 21662 ン文字列に一致する場合にはどの様に動作するのが自然だろうか?) 21663 21664 | ? 現在のコマンド文字列から検索対象を拾った場合には、元の位置まで戻って来 21665 | たら nsearch 状態を抜けるのは自然である。と思ったが、それはそれで変であ 21666 | る。例えば C-x up で検索を初めて、その後は up/down で移動していた時に突 21667 | 如として nsearch から抜けてしまうと不便である。という事を考えると 21668 | nsearch 状態から抜けるというのは変な話である。 21669 | 21670 | そういう観点から考えると、やはり勝手に nsearch 状態から抜けるのではなく 21671 | て、現在文字列に一致している状態にするのが自然である。一方で、stack の 21672 | 先頭に記録しているのは、現在の一致状態ではなくて、nsearch 開始前の状態 21673 | である。 21674 | 21675 | 例えば、現在のコマンドラインから検索対象を拾った場合に 21676 | は、_ble_edit_nsearch_stack に初めから余分に record を追加しておくのが 21677 | 良いのではないだろうか。つまり、検索開始時に最初に 21678 | _ble_edit_nsearch_stack に検索開始前の状態を保存すると共に、カーソル位 21679 | 置を point=* で指定したのに対応する位置に初期化してしまう。 21680 | 21681 | と思ったが空文字列で empty=previous-search によって検索開始した時には現 21682 | 在のコマンドラインに一致しているとは限らない。など考えると明示的に現在 21683 | のコマンドラインに一致するかどうかはチェックするべきである。 21684 | 21685 | ? input/again の時に元のコマンドライン文字列に一致する場合にどの様に取り 21686 | 扱うか。これは action=load にしているか action=goto にしているかでも振 21687 | る舞いを変えるべきかもしれない。 21688 | 21689 | →input/again でなくても現在のコマンドラインに一致しない可能性があるの 21690 | で、これは input/again かどうかの問題としてではなくて、検索が初期コマン 21691 | ドライン文字列に一致するかどうかの問題として捕らえるべきである。 21692 21693 21694 検索開始時点で現在の状態は _ble_edit_nsearch_stack に記録しておく。次に現 21695 在の行に対して一致するかどうかをチェックして、一致していたらそれも記録に 21696 残す。そしてその次の一致を調べる。 21697 21698 うーん。何だか分からなくなってきた。もし現在のコマンドラインだけに一致す 21699 る時に nsearch をそもそも開始するべきかどうか? という話にもなる。現在の実 21700 装を確認してみた所、一応 nsearch は開始する様だ。然し、highlight も何も起 21701 こらない。うーん。これは実は highlight しても良いのではないだろうかという 21702 気がする。 21703 21704 じゃあ、input 等で指定された検索対象が現在の内容にも履歴にも見つからない 21705 場合にはどの様に振る舞うべきなのだろうか。この場合には、選択範囲も何もな 21706 い状態で nsearch に入るという事の気がする。 21707 21708 振る舞いとしては (1) 何処にも一致しない場合には現在の内容から少しも動かな 21709 いが、それでも nsearch 状態には入る。(2) 現在位置に一致して他に一致しない 21710 場合は、現在位置に一致した状態で固定。 (3) 現在位置にも他の位置にも一致す 21711 る場合には、他の最初に見つかった位置に移動するが down 等で現在位置に戻っ 21712 てくる事ができる。(4) 現在位置に一致せず他の位置に一致する場合には、他の 21713 最初の位置に移動するが down 等で現在位置に戻ってくる事はできない。という 21714 ので良い気がする。 21715 21716 この振る舞いにするのであれば別に難しい事はない気がする。単に最初に現在位 21717 置に一致するかどうかをテストして、一致していたら stack に記録して状態を書 21718 き換えれば良いのである。 21719 21720 実装を確認した感じでは現在のコマンドラインの内容は検索で参照しないし、中 21721 で実際に呼び出している検索処理である isearch も履歴の内容しか参照していな 21722 い。つまり、現在のコマンドラインの内容に対する一致は呼び出し元でちゃんと 21723 処理するという前提になっている。という事を考えると、この実装でも現在の内 21724 容に対する一致は呼び出し元でチェックすれば良い。というより古い内容に一致 21725 しない様に現在位置の一致は自前でする必要がある。 21726 21727 * ok: 実装を確認した所、既に opts は受け取る様になっていた。これに色々とオ 21728 プションを追加すれば良い。 21729 21730 * done: 空文字列の振る舞いとして単に行移動するだけの実装だと再検索で問題が 21731 起こるという事が判明した。これの対処方法は二種類ある。 21732 21733 a 一つは行移動した時に必ず行頭に移動するという事。但し、その場合には検索 21734 文字列は改行を含まない物として、行頭から抽出するという様に振る舞いを変 21735 えなければならない。 21736 21737 問題が起こるのはカーソル位置から検索文字列を取り出す時だけである。でも 21738 一貫性を考えれば、別に常に先頭に移動するという実装で問題ない気がする。 21739 21740 b もうひとつの方法はやはり hide-status-on-empty で対処するという事。或い 21741 は empty=hide-status で良いのかもしれない。 21742 21743 取り敢えず二種類をオプションで指定できる様にした。 21744 21745 * done: opts hide-status 21746 21747 * resolved: 検索対象の文字列を行頭迄にして見たが、実際の検索にはコマンドラ 21748 インの一番最初からの一致しか考えていないので、自分自身に一致することがな 21749 い。これは何だか変な気がする。或いは、現在行だけ置換するという手も考えら 21750 れなくもないが、それはそれで機能として複雑すぎる気がする。やはり、検索対 21751 象はコマンドライン先頭から抽出する事にして、更に、空文字列 up down の移動 21752 後もコマンドライン先頭に移動するべきである。という事を考えると、line-move 21753 というのは変である。history-move しか nsearch とは相容れない気がする。 21754 21755 →line-move は機能として削除する事にする。 21756 21757 x fixed: 今気づいたのだが read -e が動かなくなっている。どうも 856cec2 がい 21758 けない気がする。と思って確認したが別に read -e が動かなくなる様な要因はな 21759 い気がする。或いはもっと最近の修正が原因だろうか。どうも調べてみた所、最 21760 新の ble-bind --cursor の commit によって動かなくなっている様である。何故 21761 だろうか。refactoring で変更漏れがあっただろうか。 21762 21763 refactoring 関連を確認してみたがぱっと見た感じでは変更漏れはない気がする。 21764 だとすると何が変わったのだろうか。何処で失敗しているのか read の中に入っ 21765 て行くべきだろうか。 21766 21767 →分かった。これは ble/decode/keymap/push が 1 を返す様になってしまってい 21768 たのが原因だった。push の一番最後の行に [[ $cursor ]] && do something を 21769 入れた所為で、カーソルが設定されていない keymap/push が失敗する様になって 21770 しまっていた。カーソルの設定に関係なく 0 を返す様に修正した。 21771 21772 x fixed: C-x up/down で移動する内に履歴が書き換わっている気がする。これは 21773 goto と load が入り混じっているからの気がする。ちゃんとその辺りを修正して 21774 からテストするべきである。 21775 21776 x 下方向に検索できない状態になっている。というか goto-match で常に backward 21777 になっているのは変である。 21778 21779 そもそも検索開始位置は現在の履歴位置とするか或いは末端とするのかという問 21780 題がある→確認してみた所、一応検索開始位置は現在の履歴位置になっている様 21781 である。 21782 21783 ? 検索方向を反転する時に古い履歴内容に一致してしまうのではないか。 21784 21785 検索開始位置の履歴項目には含まれていた単語を、編集でそれを消した後に検 21786 索すると、最初の一致が当初の検索方向に離れた箇所で起こる。その時に検索 21787 方向を反転させようとすると、過去の履歴に一致してしまう可能性がある。 21788 21789 この時にはどの様に対処すれば良いか。先ず、検索方向の反転は stack の内容 21790 が1個しか残っていない時に起こる筈である。この時には、検索再開位置は現在 21791 項目か或いは検索開始項目でより検索再開方向に進んだ物を採用する必要がある。 21792 21793 * 既定の動作をどの様にするのが良いのかよく分からなくなってきた。そもそも何 21794 故 nsearch という表示を隠す必要があるのかという事。 21795 21796 特にカーソル位置を末尾に移動するという設定と組み合わせると、連続して同じ 21797 コマンドを実行した時には "カーソル前の文字列を検索する" という動作は最初 21798 の一回だけであり、それ以降には最初の一回で使った検索文字列を繰り返し使う 21799 という動作になっている。つまり、連続で実行している時には通常と異なる状態 21800 になっているというのは明らかである。という事を考えるとその事が分かる様な 21801 表示が必要になる筈である。単に上下で履歴内部を移動するのとは訳が違うので 21802 ある。 21803 21804 zsh の振る舞いを調べてみた所、別にカーソル位置を変な所に移動するという事 21805 はしていない。と思ったが、どうやら history-search-end というモジュールが 21806 あって、それに history-beginning-search-backward-end 等の様な、末尾にカー 21807 ソルを移動する様な同じ機能の物が存在する様である。 21808 https://unix.stackexchange.com/a/97844/121088 21809 21810 取り敢えず C-x up 等によって使える物については自分の思う様に実装する事に 21811 する。先ず action=load ではなくて移動。nsearch status は表示する。point 21812 は現在位置。explicit に呼び出しているのだから空文字列でも普通に nsearch 21813 に入る。 21814 21815 readline 経由で up に割り当てている時には。 21816 21817 a やはり2回 RET して実行されるというのは、保持する。そうすると nsearch 21818 status も表示して置くのが良い。Bash の元々の動作と思うと action=load は 21819 保持した方が良い様な気もする。空文字列の時に空文字列で検索するか、とい 21820 うと微妙。うーん。空文字列の時は history-move が良い気がする。うーん。 21821 21822 b 或いは bash と完全に同一の動作を目指すのであれば、 21823 action=load:hide-status:immediate-accept 等と指定すれば良い。が、それは 21824 それでユーザーが便利にならない。ble.sh の便利さを押し出していきたいので 21825 あればやはり便利な動作を既定の動作とするのが良い気がする 21826 21827 hide-status:immediate-accept:action=load:empty=empty-search:point=end 21828 21829 [Note] 21830 21831 * 空文字列移動: 行指向の通常移動に fallback する選択肢を考えたが、コマンド 21832 ラインの途中に移動すると、カーソル前の文字列が非空になるので、続けて移動 21833 しようとすると予期しない nsearch が始まってしまう。代わりに常に行頭に移動 21834 して検索文字列を行頭から抽出する様にすると、今度は自分自身に一致しなくな 21835 るので動作として分かりにくい。 21836 21837 * C-x up で始めた時は empty=previous-search で良い気がする。うーん。ユーザー 21838 に入力させた時には空文字列を指定したのに前の文字列で検索が始まったら変で 21839 ある。なので既定の動作を previous-search にするのは変である。然し、コマン 21840 ドラインから検索文字列を抽出した時にだけ empty=previous-search にするのも 21841 分かりにくい気がする。 21842 21843 [修正] 21844 21845 x fixed: 描画で一番最後の文字が欠けてしまう。何らかの座標計算が間違っている 21846 という事だろうか。 21847 21848 どうも point=end を指定すると振る舞いがおかしくなる。然し、可笑しな事が起 21849 こる余地などない様な気がする。或いは、_ble_edit_ind の値を勝手に此処では 21850 変えてはいけないという事なのか、或いは、${#_ble_edit_str} の値がここでは 21851 大きな値になっているか。 21852 21853 どうも get-selection によって発生している様な気もする。もしかして空の 21854 selection range を指定すると発生する現象なのだろうか。試してみると、空の 21855 range の数だけカーソル位置がずれるという事が分かった。 21856 21857 分かった。buffer を構築する時に空 range があると "SGR${buff[@]::0}" になっ 21858 て、これが 0 要素に展開されれば良いが、SGR がある為に 1 要素に展開されて 21859 しまって、結果として buffer の要素数が増えてしまっているというのが原因で 21860 あった。そもそも空 range については要素の追加自体を実行しないという形で対 21861 処する事にした。 21862 21863 それとは別に空文字列で検索している時には _ble_edit_mark_active を設定する 21864 必要もない。判定条件を見たら、_ble_edit_ind==end だった時の条件がそのまま 21865 になっていたのが悪かった。これも修正した。 21866 21867 x fixed: 最新行が空文字列の時、最新行に空文字列検索で移動できない。これは 21868 isearch の実装の問題だろうか。或いは最新行が空文字列の時は移動しても登録 21869 されないという事なのか。或いは isearch の検索範囲の判定で有限文字列化空文 21870 字列かで振る舞いが変わるという事か。 21871 21872 →分かった。最新行が空文字列の時に移動しても登録されない事態になっていた。 21873 dirty かどうかの判定で文字列比較を行って同じであれば処理をスキップしてい 21874 たが、そもそも登録されていない時にも "空文字列" になってしまうので、"空文 21875 字列" を登録しようとしても登録されずに終わってしまうというバグであった。 21876 これは修正した。 21877 21878 * done: wiki: widget についての説明を書く。これは rasheil2000 への説明を調整して 21879 乗せれば良い→書いた。 21880 21881 * done: wiki: Q&A から説明へのリンクを書く→書いた。 21882 21883 * done: wiki/Q&A: リンクが間違っている物があった→修正した。 21884 21885 * done: wiki: key bindings について RET, TAB, ESC 等についての説明をちゃん 21886 と書く。 21887 https://github.com/akinomyoga/ble.sh/issues/101#issuecomment-828340592 21888 21889 * done: blerc に何か書いても良いのかもしれない? 或いは Alyetama の言う様に 21890 wizardを作って其処から設定を選択できる様にする。取り敢えず今は blerc には 21891 書かない事にする→やはり書いた。 21892 21893 2021-04-26 21894 21895 * util: 既定の cursor-shape の時には DECSCUSR は出力しない (motivated by jmederosalvarado) [#D1516] 21896 https://github.com/akinomyoga/ble.sh/issues/95 21897 21898 % cursor shape を変更しない場合には external/internal の切り替えでも 21899 % DECSCUSR は出力しない様にするオプション? 21900 →オプションではなく固定でその様な動作に変更した。 21901 21902 そもそもその様な実装になっていると思っていたが…。恐らく一番最初の状態が 21903 unknown になっているのが原因? もし最初の状態が 0 になっていたとして emacs 21904 mode の場合にはそのまま DECSCUSR が全く呼び出されずに済んだ可能性はあったろ 21905 うか。 21906 21907 →実際に試しに最初の状態を unknown から 0 に変更した所、ちゃんと最初のカー 21908 ソル状態が保持される様になった。 21909 21910 ? no: 然し、コマンドを実行した後にカーソル形状を元に戻すという操作が強制で 21911 入っている可能性はあるだろうか? 21912 21913 →確認してみたが、特に external/internal は意識していなくて、また外部コマ 21914 ンドがカーソル形状を変化させてしまうという可能性は考えていない。外部コマ 21915 ンドが停止する時にカーソル形状を戻しておくべきであるという前提に基づいて 21916 いるのであろう。 21917 21918 取り敢えずその前提は仮定する事にする。 21919 21920 条件判定を変更したが、実は初めから値を 0 に設定しておけば同じ動作になるので 21921 はないだろうか…。此処で実装するべきは空文字列だった時と 0 の区別ではないか。 21922 と思ったが、0 を意図してブロックとして指定するユーザーがいるかも怪しい。ブ 21923 ロックであれば 1 を指定すれば良いからである。 21924 21925 諸々考えると単に初期値を unknown から 0 にすれば良いという気がする。 21926 21927 * term/edit: keymap 毎のカーソル形状 (motivated by jmederosalvarado) [#D1515] 21928 https://github.com/akinomyoga/ble.sh/issues/95 21929 21930 現在の実装では auto-complete, menu 等の mini mode 等でカーソル形状は変わら 21931 ないと仮定して、emacs, vi_?map の間の変更だけでカーソル形状の再設定を行って 21932 いる。然し、今後 mini mode におけるカーソル形状の変更も考えると、もっと統一 21933 的にカーソル形状を管理する必要がある気がする。 21934 21935 例えば keymap 毎にカーソル形状を設定できる様にして、keymap の切替時に設定さ 21936 れたカーソル形状に変更する様にする。指定した keymap にカーソル形状が設定さ 21937 れていない場合は、keymap stack 内の前の keymap を参照する。 21938 21939 * この時、既存のカーソル形状の設定はどうするのか。 21940 21941 現在の vi におけるカーソル形状の設定: imap,nmap,omap,xmap,smap,cmap 21942 ... これらの設定に応じてカーソル形状を変化させる様になっている。然し、実 21943 際の実装ではこれらの map は参照せずに設定している気がする… と思ったが確 21944 認したらちゃんと keymap を参照してカーソルを切り替えていた。 21945 21946 設定の方法は bleopt keymap_vi_?map_cursor を介して行っているが、もし 21947 keymap 毎にカーソル形状を管理する様にするという事だと、(1) 既存の設定は翻 21948 訳しなければならない (2) 新しい方法に移行する様に情報を提示する必要がある。 21949 21950 或いは、bleopt keymap_KEYMAP_cursor を一般に使える様にするという手もある 21951 が、これはこれで bleopt 内に名称の構造を作成する事になるので避けたい。 21952 21953 * emacs に対応する。 21954 21955 ? ok: cursor-state を decode.sh から参照しても依存関係的に問題ない 21956 か。cursor-state は何処で実装されているか? → util.sh で定義され 21957 ている様なので大丈夫。 21958 21959 [変更] 21960 21961 * done: 設定の変数名を決める ... _ble_decode_KEYMAP_kmap_cursor 21962 21963 取り敢えずは bleopt_keymap_KEYMAP_cursor を参照して実装する? と思ったが後 21964 の調整が色々面倒になりそうなので、もうこの時点で変数名も決めてしまう事に 21965 する。 21966 21967 元々の keymap の設定は _ble_decode_KEYMAP_kmap_@ に保持している。同様に 21968 _ble_decode_KEYMAP_kmap_cursor を使おうと考えたが、これだと dump/save で 21969 記録されてしまうので微妙である。また、どういう設定コマンドで設定するべき 21970 かという問題もある。 21971 21972 a ble-bind を使って設定を行う? と思っても直感的に変である。例えば 21973 ble-bind -m KEYMAP --cursor 5 とか設定する事になる。うーん。そんなに変 21974 ではないかもしれない? 21975 21976 後、これの呼び出しも遅延する事にすれば実は dump で記録されてしまう問題 21977 も気にしなくて良い気がする。KEYMAP に紐付いているという事を考えても、直 21978 観的に特に問題はない様な気もしてきた。 21979 21980 この場合には ble-bind -P で出力する時にカーソル設定も出力する様にする必 21981 要がある。 21982 21983 a 新しくカーソル設定だけの為のコマンドを用意する? というのもユーザーが覚 21984 える事が増えるだけで余り良くない。 21985 21986 c 或いはやはり bleopt keymap_cursor_KEYMAP という感じにして、多少構造化さ 21987 れた名前の bleopt に変更するに留めるか。 21988 21989 今は取り敢えず a の方針で考える事にする。 21990 21991 * done: ble-bind にオプションを追加する。 21992 * done: ble-bind に於ける遅延初期化について確認する。 21993 * done: refactor: ble-decode-key/dump 其他。 21994 21995 * done: 実装する。keymap/push, pop の際に cursor shape を再設定すれば良い。 21996 21997 % 遡ってもカーソル形状が指定されていない場合には何もしない? 今までに何も 21998 % 設定されていなければ何もしない。今までに何か特別な物が設定されていた場 21999 % 合には 0 または空の文字列で DECSCUSR を呼び出してカーソル形状の設定をク 22000 % リアする。これは実は cursor-shape の側で設定を行っている筈なので気にし 22001 % なくて良い。 22002 22003 遡ってもカーソル形状が指定されていない場合はカーソル形状をクリアする。 22004 22005 * done: keymap_vi_?map_cursor の設定を翻訳する。 22006 22007 書き換えの指示を表示する事にした。然し、遅延ロードで設定が読み込まれる為 22008 に表示が乱れてしまう。これに対応する為にはメッセージを受け取った時に表示 22009 する様にしなければならない。どの様にするのが良いか。或いは invalidate す 22010 る? と思ったが座標計算のずれまでは解決しない。 22011 22012 * reject: term_vi_?map についても keymap 側に設定を移行するべきなのではないか。 22013 22014 然しこれに関しては大して系統的に管理しようとはしていないし、もし何かしよ 22015 うと思う場合でも __attach__ で実行すれば良いのではないか。ただ 22016 し、__attach__ はその keymap を push した時にしか実行されない。一方で、 22017 term は pop して表に出てきた時にも実行する必要があるという点が異なる。そ 22018 ういう意味で ble-bind --cursor と同様に取り扱っても良いのではないか。とい 22019 うより、ble-bind --cursor を止めてもっと汎用的な hook を用意する可能性? 22020 と思ったが、やはり cursor は cursor で管理するのが良い気がする。 22021 22022 term_vi_?map についてはユーザが設定したい時に利用する物なので、現状の儘 22023 naive な実装をするままで良い。複雑な仕様にするとユーザーが混乱する。 22024 22025 * done: vi における動作テストを行う。 22026 22027 * done: wiki: ble-bind に追記 22028 * done: wiki: 既存の keymap_vi_?map_cursor を廃止。 22029 * done: update blerc 22030 22031 * 2021-04-04 keymap/emacs: emacs mode でも cursor shape を設定できる様にする [#D1514] 22032 https://github.com/akinomyoga/ble.sh/issues/95 22033 22034 % keymap/vi と同様に実装した。本来は auto-complete や menu 等の mini mode の 22035 % 中でカーソルの形が変化することも考慮に入れて、もっと統一的な枠組みでカーソ 22036 % ルの形状を管理するべきな気もするが、現在は external/internal 及び major 22037 % mode の切り替えのみでカーソル形状を変更する取り決めにして、直接カーソル形状 22038 % の設定を各 major mode の切り替えで記述している。 22039 % 22040 % 2021-04-26 設定を変更した時に直ぐに反映する様にするには? →取り敢えず 22041 % keymap/vi と同様にカーソルの形状はトップレベルで決まっていると考えて、基底 22042 % keymap が emacs かどうかだけで変更を適用する様にした。然し、既に上の段落で 22043 % 記述した様に、mini mode 毎にカーソル形状を変更する為にはちゃんと構造化して 22044 % カーソルを変更する仕組みを整備しなければならない。 22045 % 22046 % * 今の暫定実装だと、emacs モード内で vi に移行している時に意図しない動作に 22047 % なる。vi は毎回自分の状態に応じてカーソルを設定しようとするとので、emacs 22048 % の中で vi に移行していたとしても関係なくカーソル形状を変更してくる。なの 22049 % で、emacs 内の vi でも vi のカーソル形状の設定は有効であると考えるべきで 22050 % ある。 22051 % 22052 % 暫定実装では基底が emacs かどうかで判定しているが、そうではなくて、keymap 22053 % stack の内部でカーソルが設定されている一番上の keymap を使って判定するべ 22054 % きなのではないだろうか。 22055 % 22056 % これも keymap ベースの判定方法なので、やはり keymap を基準にした実装に切 22057 % り替えるべきの気がしてきた。 22058 22059 この変更は結局 #D1515 の実装に伴ってキャンセルした。一応変更は 22060 memo/D1503.stub.patch に残しておく。 22061 22062 2021-03-15 22063 22064 * 2021-03-03 syntax: 実は "${v#...}" の中身も tilde 展開の対象の様である [#D1513] 22065 https://lists.gnu.org/archive/html/help-bash/2021-03/msg00003.html 22066 22067 bash-1.14 から bash-dev まで一貫して再現する。 22068 bash -c 'v=/home/murase/test; echo "${v##~/}"' 22069 22070 : の後は特に展開対象という訳ではない様だ。変数代入形式の単語でも特に展開は 22071 しない。つまり本当に先頭に ~ がある時にのみ展開が発生する。 22072 22073 $ bash -c 'v=x:/home/murase/test; echo "${v##x:~/}"' 22074 $ bash -c 'v=a=/home/murase/test; echo "${v##a=~/}"' 22075 $ bash -c 'v=a=x:/home/murase/test; echo "${v##x:a=~/}"' 22076 22077 序でに、この振る舞いについては実はマニュアルにちゃんと記載されている。 22078 22079 > In each of the cases below, word is subject to tilde expansion, 22080 > parameter expansion, command substitution, and arithmetic 22081 > expansion. 22082 22083 対象は ${v-w} ${v+w} ${v?w} ${v=w} ${v#w} ${v%w} である。他は関係ない。 22084 22085 * 他に posix モードに於いては変数代入形式の単語についてチルダ展開は起こさな 22086 い→これの対策も実装した。OK 22087 22088 * 巨大なディレクトリで TAB 補完が遅くなる (reported by timjrd) [#D1512] 22089 https://github.com/akinomyoga/ble.sh/pull/65#issuecomment-798551355 22090 22091 再現する事ができたので対応する事にする。200k のファイルまたはディレクトリが 22092 存在する所で TAB を押して少ししてから別のユーザー入力を押した時に直ぐにキャ 22093 ンセルされない。時には数秒待たされる事もある。現在の実装では補完時に別のプ 22094 ロセスを使っているので展開自体に時間がかかっているとしてもすぐにキャンセル 22095 される筈? 22096 22097 ? 然し、本当にユーザー入力に対して即座にキャンセルするという事にして良いの 22098 だろうか。ある程度の interval は置くべきなのではないだろうか。と思ったが、 22099 実際の所、現在の実装で既にユーザー入力がある時にはすぐにキャンセルする動 22100 作になっていて、単にキャンセルが成る迄に待たされてしまうという動作になっ 22101 ているという事を考えるとこれは気にしなくて良い。 22102 22103 →元から即座にキャンセルになる。ただ現状の実装ではキャンセルに時間がかかっ 22104 ているだけ。 22105 22106 どうも TAB 補完の時には conditional-sync による実行がされていないのではない 22107 かという気がする。取り敢えず何処で時間がかかっているかを確認する。 22108 22109 →絞り込みをかけていった所、ble/complete/source:file に於いて、生成したファ 22110 イルの存在確認とディレクトリかどうかの確認に時間がかかっていた。 22111 22112 ? 然しそもそもこの確認は必要なのだろうか。現在の実装では nullglob を設定す 22113 る様にしているので存在しないファイル名が生成される事はないのではないか。 22114 やはり確認してみると nullglob を設定しているので改めてファイルの存在確認 22115 を行う必要はない筈。-e または -h で確認を行っているがこれは全ての生成され 22116 たファイル名に対して真であると考えられる。従ってこの処理は不要である。 22117 22118 →特にファイル名の生成の時にはチェックはしない様に変更する事にした。ディ 22119 レクトリの場合にも予めパターンに / を含めているので、ディレクトリ以外が混 22120 入するとも考えられない。従って、全て使う事にする。但し、末尾の / は除去す 22121 る。 22122 22123 然し、これまでの処理ではファイルの存在確認を全てのファイルに対して再実行し 22124 ていた。つまり、-d -e -h を実行していた。stat を何度も繰り返す事になるし、 22125 そもそもループで 200k ものファイルを回していたという事になる。なのに、手元 22126 の計算機ではかなり短い時間で処理できていた。bash は意外と遅くないという事な 22127 のだろうか。何れにしても環境によってはこれらのファイルアクセスに時間がかか 22128 るというのは理解できる。 22129 22130 実のところこれが本当に報告された問題に関係しているのかは分からないが、少な 22131 くとも性能の改善はあるだろう。他にも bottleneck があるかもしれないがこれで 22132 良い事にした。 22133 22134 * 2021-03-07 bleopt 初期化時に最初から存在する設定をチェックする? [#D1511] 22135 22136 というのも ble-update や version up に従って設定名が変わるかもしれないから。 22137 ただ、今までに設定を破壊的に変更した事はないので余り気にしなくても良いのか 22138 もしれない。 22139 22140 % その場でチェックをする為にはチェック用の関数が bleopt/declare の時点で存在 22141 % している必要がある。check 関数が定義されている時にはそれが bleopt/declare 22142 % よりも前になる様に書き換えていく。 22143 % 22144 % x 以下の関数は定義時にちゃんと関数群が存在しているか確かめているが、その関 22145 % 数群は未だ定義されていなかったりする。これらの初期化順序についてちゃんと 22146 % 再考する必要があるのではないか。 22147 % 22148 % - canvas: bleopt/check:char_width_mode 22149 % - util: bleopt/check:input_encoding 22150 % 22151 % 或いは値の設定に関しては ble.sh の基本的な初期化が終わった後に一括してチェッ 22152 % クを行う様にする? そうすると既定値を何処かに記録しておく必要があるのでは 22153 % ないか。 22154 22155 その場でチェックする様にすると dependency injection 的に用意される設定値の 22156 場合に (オプションを宣言した時点では設定値が登録されておらず、後で各設定値 22157 が補助関数の定義などを通して登録される場合) 問題が起こる。 22158 22159 結局、様々のモジュールを読み込んだ後で最後に一括してユーザによって指定され 22160 た値のチェックを行う事にした。既存の設定に関してチェック用関数の順序を変更する必要はない。 22161 22162 2021-03-09 22163 22164 * README: uninstall に .cache の事が書かれていない [#D1510] 22165 書いた。 22166 22167 * README: 0.3 に関しては release note の側に書いておくべきなのでは [#D1509] 22168 記入した。0.1..0.3 の情報を書いた。各 Release ページに使い方を記入した。 22169 22170 * COMPAT complete vs fzf: システムによってロードされた fzf で固まる [#D1508] 22171 22172 これは . /etc/bashrc を読み込むと強制的に読み込まれている設定である。ユーザー 22173 が自分で入れた fzf に関しては contrib/fzf-completion を ble-import して貰う 22174 事によって問題が起こらない様にしているが、システムによってロードされる fzf 22175 に関しては内容を上書きする隙がない。仕方がないので、core-complete.sh で 22176 _fzf_* が呼び出された時に contrib/fzf-completion を自動的にロードする様にす 22177 る事にした。元より bash-completion を勝手に呼び出したりする様にしているので 22178 他の framework ありきのコードがあっても気にしない。 22179 22180 これは正直 fzf が tty ではなくて stderr になにか出力しようとするのが行けな 22181 い。/dev/tty に出力する様にして欲しい物である。 22182 22183 うーん。 fzf のページを見てもそれらしい物は存在しない。環境変数などで指定で 22184 きれば良いのだが。man fzf を見てもそれらしい物は存在しない。そういう機能を 22185 request して見ようと思ったが、考えてみれば自分で fzf を呼び出す時には 22186 2>/dev/tty をつければ良いだけなので新しい機能として実装する意味がない。ユー 22187 ザー経由で呼び出しているのであればユーザーにその様に指定する様にお願いする 22188 べきなのである。 22189 22190 然し、ble.sh がやっているのは bash progcomp の模倣である。bash の方で問題が 22191 ないのであれば、ble.sh の方で問題が起こるのは余り良くない。うーん。fzf につ 22192 いて関数などで上書きして振る舞いを変える? うーん。それだと fzf-xxx の様な派 22193 生コマンドを使われた時に対処できない。結局 bash progcomp を真似て 2 は tty 22194 に繋いだ儘にしておくべきなのだろうか。うーん。 22195 22196 というかそもそも fzf が tty に出力する様にしたとして auto-complete に際して 22197 期待通りに動くかどうかというのは非自明である。取り敢えず試してみる。 22198 →試してみた所期待通りに動作しない。やはり fzf の設定をそのまま使うのは駄目。 22199 22200 ? うーん。実行しても結果が反映されない。COMPREPLY をちゃんと設定しているか? 22201 22202 ? redraw-line が正しく呼び出されていない。 22203 22204 % これは恐らく ESC [ が M-[ になって bind されているのが原因。CSI の構築に 22205 % 失敗した時に M-[ と解釈するべきか或いは ESC [ と解釈するべきかは微妙な所 22206 % である。然し、CSI を構築する ESC は isolated ESC ではなくて他の文字と一緒 22207 % に受信した ESC であるべきと考えれば、やはり M-[ と解釈するべきだろうか。 22208 % そうすると、CSI に失敗した時に 1 byte だけ切り取って ESC を key として生 22209 % 成しているのを修正するべきである。 22210 22211 改めて確認した所、そもそも CSI 0 n は認識できないシーケンスとして捨てられ 22212 ているという事が判明した。 22213 22214 ? その他の問題として fzf を実行している間は modifyOtherKeys の設定によって 22215 fzf の操作ができなくなっているという事がある。うーん。実際に端末に作用す 22216 るかどうか分からないのに補完関数を呼び出す度に端末の状態を変更するという 22217 のも変な感じがする。 22218 22219 面倒なので fzf が補完関数の名前に入っている時に限り特別の動作をする様にする? 22220 取り敢えず、固まったりしない様に調整した。 22221 22222 % x fixed: CSI 5 n が候補の文字列に結合してしまっている。これは何故だろうか。 22223 % COMPREPLY にはちゃんとした候補が入っている…気がする。 22224 % 22225 % →これは compgen の標準出力を読み取って候補としているのが原因。元の 22226 % progcomp の -F の場合には標準出力はそのまま端末に繋がっている。それに倣う 22227 % 様に修正した。 22228 % 22229 % x fixed: 候補が生成されない…と思ったら実は CSI 5 n に対する返答 CSI 0 n に 22230 % よってユーザー入力に依る中断が入って処理がキャンセルされている。fzf の時 22231 % にはどうにかしてこれに対する対策を行う必要がある。 22232 % 22233 % a CSI 0 n を受信しても処理を続行するというのは難しい。何故ならば受信した 22234 % 段階ではそれがユーザー入力なのか応答なのか判定する方法がないので。受信 22235 % して読み取ってから違ったら書き戻すというのも処理としては汚い。 22236 % 22237 % b それなら CSI 5 n がそもそも伝播しない様に抑える必要がある。うーん。幸い 22238 % にして CSI 5 n は標準出力に、それ以外のメニューの描画は標準エラーに出力 22239 % されている。従って、_fzf* に対しては標準出力を潰す様にするのが良い気が 22240 % する。 22241 22242 色々対策してみたが実はこれらの対策は contrib/fzf-completion.bash と本質的に 22243 同じであった。fzf-completion.bash を自動で load する方が良いのではないか。 22244 22245 x fixed: progcomp で単一候補を生成したとしても progcomp 以外に sabbrev も表 22246 示されてしまって単一確定にならない。うーん。これは _fzf_* で成功して単一 22247 確定の場合には既に生成した候補は全て削除するという事にすれば良いのでは。 22248 →既存の候補は消去する様に実装した。 22249 22250 x そもそも既に入力済みの内容を無視している。normal bash で試してみると、既 22251 に何か入力済みの物がある場合には fzf による completion は起動しない。空の 22252 文字列の時にだけ fzf による選択が開始される。 22253 22254 →これは曖昧補完の為に空文字列で補完候補生成を要求するのが原因であった。 22255 曖昧補完の時にはそもそも fzf を呼び出さない様に修正した。 22256 22257 * BUG progcomp: 現在 read に介入して中断する様にしているが [#D1507] 22258 22259 現在の実装だと 22260 22261 while read || [[ $REPLY ]]; do ... done 22262 22263 の様になっていると、無限ループになってしまう。 22264 中断する時にも引数に指定した変数は全て空にしておく必要がある。 22265 22266 というより、現在の read の実装は普通に呼び出した時であってもちゃんと変数を 22267 空にしてくれるのか? 22268 22269 % そもそも元の read の振る舞いが良く分からない。read line とした時にもう読み 22270 % 取る内容がなかったとして line が空になるのかと思いきやそうでもない? と思っ 22271 % たがこれは勘違いだった。試す時に : | read ... とすると subshell の中で値を 22272 % 設定するので、外側の変数には影響が出なかっただけ。 22273 22274 うーん。取り敢えず中断の時には内部で </dev/null を builtin read に食わせて 22275 処理する事にした。option -e が指定されていても /dev/null に繋がっている時に 22276 は特に readline も起動せずに期待通りに動作する筈。 22277 22278 * [OK] edit: read -a ARRAY に対応していない? [#D1506] 22279 22280 と思ったが実はちゃんと対応していた。抑 -a ARRAY は bash-4.0 の時点でちゃん 22281 と存在している。調べたら bash-2.0 で配列に対応した当初から存在している様で 22282 ある。 22283 22284 対応していない様に見えたが実のところ read -e で読み取った結果を改めて 22285 builtin read で解釈されているので特別に実装しなくてもちゃんと振る舞いを再現 22286 できているのである。 22287 22288 * wiki: bleopt openat_base [#D1505] 22289 22290 現在は実は積極的には使われていないという事。 22291 また、既に重複して開かない様に対策が為されているという事。 22292 22293 →どの時点で対策が導入されたか確認しようとしたら実は ble-0.1 の時からちゃん 22294 と或る程度の衝突回避はある様だった。問題が発生するのは ble.sh が fd を使い 22295 始めた後でユーザーがそれを上書きしてしまった場合である。この問題は今も依然 22296 としてある。従って、現在の文章はそのままにする。但し、Bash 4.0 以下でしか使 22297 われないという事は書いておいて良いだろう。 22298 22299 wiki を編集した。 22300 22301 2021-03-07 22302 22303 * progcomp: やはりファイルが大量にあるシステムで遅い (reported by timjrd) [#D1504] 22304 https://github.com/akinomyoga/ble.sh/pull/65#issuecomment-791932281 22305 22306 試しに complete -r して見ると発生しなくなる。 22307 22308 という事は bash_completion が悪さをしているのだろうか。 22309 22310 * fzf completion も勝手にロードされている。fzf completion の実装が悪いのか 22311 と思って fzf の completion をロードしない様にしたがそれでも問題は発生する。 22312 22313 * highlight_filenme= としても特に問題は改善しない。逆に 22314 complete_auto_complete= として highlight_filename=1 のままの場合には特に 22315 問題も生じない。着色もそんなに時間をかけずに実行できている。という事を考 22316 えるとやはり progcomp 特有の問題である様に思われる。 22317 22318 * bash の progcomp の場合には特に問題は生じていない。という事は -F で呼び出 22319 した関数を強制的に中断する機能があるのか、或いは -F の関数の呼び出し自体 22320 にはそんなに処理時間がかかっていなくて後の処理で時間がかかっているという 22321 事なのか。何れにしても計測が必要になる。 22322 22323 実際に処理をブロックしているのは以下の関数の呼び出しの様だ。 22324 22325 $ _minimal 'echo' '' 'echo' 22326 22327 然し普通に呼び出してもそんなに時間がかかる事はない。 22328 22329 ---- 22330 22331 _minimal の呼び出しに時間計測をかける。結局 _filedir の中にあるループがいけ 22332 ないのだという事。うーん。ble.sh の中で実行すると 20 秒も待たされるが、bash 22333 progcomp から呼び出すと 1.2 秒で終了する。何故だろう。 22334 22335 実際に候補を bash progcomp 内で生成しているのか確認してみるとちゃんと候補は 22336 生成されている。 22337 22338 もしかして read で変な処理をしているのが行けないという事だろうか。でもそん 22339 なに重い処理はしていない。うーん。オプションの処理をしているが、bash 22340 progcomp の時にも現在 attach しているかどうかのチェックは行っている。そんな 22341 に差が開く物なのか。 22342 22343 実際に unset -f と read() { ble/builtin/read "$@"; } で囲んでみたら 0.6s に 22344 縮まった。1/60 の時間になった。 22345 22346 ---- 22347 22348 これに対する対策はどのようにするのが良いか。 22349 22350 a progcomp で compgen する時だけは unset -f read する? と思ったが、この状態 22351 で read -e を内部で呼び出されるなどすると変な事になってしまう。 22352 22353 b decode-detach/attach するのは処理量的に好ましくない気がする。特に 22354 auto-complete で何度も呼び出されるのに、実際に時間がかかるかどうか分から 22355 ない処理のために毎回 detach/attach するのは大変。 22356 22357 c 或いは _filedir 等の各関数に対して .advice around で unset -f read を行う? 22358 22359 d 或いは read の中に complete_polling_cycle を仕込む。うーん。これが一番 22360 smart な気がしてきた…。 22361 22362 * canvas: Kitty が CSI ; r に対して何もしない (reported by timjrd) [#D1503] 22363 https://github.com/akinomyoga/ble.sh/pull/65#issuecomment-791932281 22364 22365 抑 CSI ; r にしていたのは DECSLRM CSI ; s に合わせる為であり、DECSLRM を 22366 CSI ; s にしていたのは、SCOSC と区別する為に引数の数に基づく heuristics を 22367 用いている為である。CSI r 自体については SUNSCRL と conflict が存在している 22368 が、SUNSCRL を実装している端末は Solaris console ぐらいしかないだろう。なの 22369 で、CSI r をそのまま出力しても問題ないと判断する。 22370 22371 然し、引数の省略をすると動作しないというのは Kitty のバグなのではないのか。 22372 まあ Kitty の全体的なデザイン等について知らないので、もしかすると Kitty は 22373 全体的にそういう感じなのかもしれない。何れにしても Kitty の端末エミュレーショ 22374 ンは元より滅茶苦茶なので気にしても仕方がない。 22375 22376 2021-03-03 22377 22378 * 2021-02-28 canvas/trace: align=right,center に対応する [#D1502] 22379 22380 高さについても同様に対応しても良いのかもしれないがそれは必要になってからで 22381 良い。 22382 22383 rps1 の各行右揃えに対応しようと思ったが問題がある。範囲計算がちゃんとできな 22384 いという事。rps1 が横幅一杯に広がれる様にする為には trace の計測開始点は 22385 x=0 でなければならない。然しこれで measure-bbox すると範囲が x=0..COLUMNS 22386 になって横幅一杯になってしまう。一方で、rps1 を表示する時には実際に文字が出 22387 力される範囲を取得したい。これはどの様にするのが良いか。 22388 22389 a 描画開始点を実際に文字が出力される範囲の bbox の左上になる様にする? 然し 22390 それは最後まで範囲計算をしないと求められない。一番最後に、出力シーケンス 22391 の先頭に移動シーケンスをつけ加えれば実装できるが実装が汚くなる。特に右寄 22392 せしていない場合でも同様の機能を提供する等の事を考えると変である。 22393 22394 更に、bbox の左上の位置というのが分かりやすいのかも不明である。何故なら呼 22395 び出し元は配置の結果として何処が bbox の左上になるのかという事を知らない 22396 からである。これは、呼び出し元で bbox の中身の配置について全く関知せずに、 22397 一つの blackbox として取り扱うという場合にのみ妥当である様に思われる。 22398 22399 b 或いは描画開始点を右上にするという手も考えられる。右寄せの場合にはその方 22400 が自然に思われる。 22401 22402 b1 計測の時には取り敢えず x=0 にして計測を行って、その後でユーザーが指定 22403 した (x,y) を起点とした描画シーケンスを構築するのである。然し、その時に 22404 は左に向かうシーケンス等が何処で壁に当たって止まるのかという振る舞いが 22405 変わってしまう。 22406 22407 b2 代わりに unbounded な空間で計測をしてから再配置をするという事を考える 22408 と、今度は折角計測した内容が実は一行の中に収まらなかったという様な自体 22409 が生じる可能性もある。然し、これに関しては現在の実装でも似たような物で 22410 ある。しかし、少なくとも一つのフィールドの幅が行内に収まっていればOK。 22411 一つ一つのフィールドについて絶対範囲ではなくて幅や高さで制限をかける事 22412 になるが、それはまた実装が無駄に複雑になってしまう。 22413 22414 c 或いは measure-bbox で文字列の範囲とカーソル移動の範囲の二種類のどちらを 22415 計測するか指定する事ができるようにする? 22416 22417 両方の情報が欲しい場合も考えられるので、x1 x2 y1 y2 に加えて、x1c x2c y1c 22418 y2c 等を用意する? 少なくともカーソル移動は文字列を包摂するべきである。変 22419 数が増えるのも面倒なので x1[1] x2[1] y1[1] y2[1] 等の様に配列にしてその第 22420 二要素以降に値を格納するという考え方もある。然し、これはインターフェイス 22421 として分かりにくい。 22422 22423 measure-bbox の振る舞いを切り替えられる様にするというのはやはり問題がある 22424 気がする。何れにしても両方の情報が必要になるからである。justify で配置を 22425 する時に出力された文字列の範囲を元にして配置を行うと、端にぶつかった時に 22426 座標計算がずれてしまう可能性がある。一方で、right align の大きさを調べる 22427 為には right を表示する必要がある。 22428 22429 d 行毎に ret x1 x2 y1 y2 x y を算出する。これらの変数を全て配列にする。各行 22430 の bbox の左上 (x1,y1) を ret の出力開始点とする? (x1,y1) への移動に関し 22431 ては自前で実行する。その他の align も全て自分で処理する。 22432 22433 これは微妙。これならそもそも trace に実装する必要もない様な気がする。 22434 (一応 sc/rc で囲んでいる部分やシーケンスを跳ばすという処理が非自明だが) 22435 そもそも trace に渡す前に分割して指定していれば良かったのである。 22436 22437 % 調べて見た所、実は現在の実装は既に文字を出力した範囲の bbox を使う様になっ 22438 % ていた。という事は…。現在の実装で既に right を指定した時の範囲も表示して 22439 % いる物の範囲になっているという事? 22440 % →勘違いだった。ループの最後で記録しているが、これは制御機能によって移動 22441 % した後でも通過する場所に書かれている。 22442 22443 表示が乱れる場合の事を考えると right の時には一旦右端に移動してから其処から 22444 の相対移動で描画するのが良い気がする。これは right の時の特別な取り扱い。 22445 22446 * 現在の範囲追跡のコードを整理するという可能性。現在は移動を伴わないエスケー 22447 プシーケンスであっても記録を行う様になっている。これは無駄な気がする。 22448 22449 また、全てに対して一律に範囲追跡を行っているので、文字列出力のみに対して 22450 計算する等の事ができない。と思ったが、結局最終的に文字列範囲とカーソル移 22451 動範囲の両方の情報が必要になるのであれば、文字列出力範囲に関しては独立し 22452 たコードで実装を行う筈で、これは気にしなくて良い。 22453 22454 opts measure-gbox として出力した文字列の範囲を計算する事にした。 22455 22456 * justify の時に最後に jg[xy][12] から g[xy][12] に転写する 22457 22458 * main-loop の下部の ((w>0)) の処理について 22459 22460 * 何故折返し処理を此処でしているのだろうか? w として有限の幅を設定する制 22461 御機能は限られている。調べた所、print+ と単一文字の時の二通りしか無い。 22462 単一文字に関しては行に収まらない場合には事前に改行を実施している。行に 22463 ぎりぎり収まる時の振る舞いはどうなっているか。うーん。 22464 22465 * gbox は此処で処理するべきの気がする。有限幅の文字列がある時には此処に来 22466 るのだから。というよりこの処理自体を関数にしても良いのではないかという 22467 気もする。 22468 22469 * そもそも此処で行っている処理は put-ascii や put-atomic で行うべきなので 22470 はないだろうか。 22471 22472 →全て各制御機能及び print の内部で measure-bbox, gbox の処理を行う様に変 22473 更した。 22474 22475 取り敢えず rps1 の複数行も実装して動作確認した。OKだと思う。 22476 22477 2021-02-28 22478 22479 * 2021-02-06 render-defer.idle の優先順位を下げたい [#D1501] 22480 22481 現在の実装では ble/textarea#render-defer.idle が menu-filter, auto-menu, 22482 auto-complete よりも先に来ているが、これは後に来るべき。特に menu-filter よ 22483 りも先に来ないと絞り込み状態の着色がずっと残ってしまう。 22484 22485 menu-filter を render-defer.idle よりも前に挿入するべきである。どの様にすれ 22486 ば良いか。 22487 22488 a 特定の要素の前に挿入するという操作を実装しても良いと思ったが、その為だけ 22489 に関数を用意するのも変である。それよりはオプションで指定できる様にする方 22490 が実装としては自然である。その時に挿入点よりも後に詰まって存在している要 22491 素はシフトする。 22492 22493 b 或いは初めから各 background の優先順位を指定して登録してしまうという手も 22494 ある。というよりその方が自然である。どうせ決め打ちになるのでその方が柔軟 22495 に対応できる。 22496 22497 現在 background idle (10000+) に登録される処理は以下の通り 22498 - ble/util/msleep/calibrate 22499 - ble/textarea#render-defer.idle 22500 - ble/complete/menu-filter.idle 22501 - push-background ble/complete/auto-complete.idle 22502 - push-background ble/complete/auto-menu.idle 22503 22504 うーん。単に menu-filter を 9999 に登録すれば良い? これが単純で分かりやすい 22505 対応であろう。 22506 22507 * 2021-01-31 complete: change bleopt complete_limit default [#D1500] 22508 22509 実は今回の subshell による実行でしなくても良くなったのではないか。と思った 22510 が、元の報告だと別にグロブパターンと関係なく遅いという話だった気がする。と、 22511 思ったが補完の話だったのでやはりグロブパターンというかファイル名補完に関係 22512 がある。 22513 22514 うーん。やはり 500 というのは上限としては小さすぎる様な気がする。 22515 auto-complete の 200 というのも小さすぎる様な気がする。もっと増やしても良い 22516 のではないかという気がする。5000 vs 2000 ぐらい。というか tab 補完に対して 22517 制限する必要があるのだろうか。 22518 22519 ? globpat を含んでいるかのどうかの判定は実は failglob を使った方が早いかも 22520 しれない。現在の正規表現に基づく実装と速度を比較する価値はあるかもしれな 22521 い。しかし、../../.. みたいなパスが含まれている可能性等も考えると下手な事 22522 はできない。 22523 22524 * [自然解消?] 2021-02-01 complete: slow tab completion after globstar words (reported by 3ximus) [#D1499] 22525 https://github.com/akinomyoga/ble.sh/issues/82#issuecomment-770390986 22526 22527 パス名展開を compvar 構築時に全ての単語に対して実行しているのが原因かと思っ 22528 て#D1457 で compvar 用の timeout を導入してみたがどうも関係なかった様だ。報 22529 告に依ると globstar の着色が終わった後でも遅いという話だ。これはこちらの手 22530 元では再現しないという事が分かった。恐らく cache が働いているのだろうと思う。 22531 22532 2021-02-04 新しい commit で改善したそうであるが、それでもパターンがない時よ 22533 りも遅いそうである。 22534 22535 2021-02-27 22536 22537 * canvas/panel: set-height で高さ拡張時にその時の sgr0 が bce で適用されてしまう [#D1498] 22538 22539 < /dev/tcp/..../80 で赤色になっている時に実行すると赤い行ができてしまう。 22540 これは sgr0 をせずに set-height を実行する事によって発生している事態である。 22541 そもそも赤い状態をそのままにして放置している事自体が変なのかもしれないが、 22542 取り敢えず set-height をする前に sgr0 をする必要はある気がする。 22543 22544 $_ble_term_sgr0 を出力する様にしてみた。 22545 22546 しかし、どうも ble/canvas/goto.draw する時にまた $_ble_term_sgr0 を出力する 22547 様なので、重複してしまう。問題が発生するのは、ble/canvas/goto.draw の時に既 22548 に目的地にいる場合で、その時は既定では sgr0 の出力も省略されてしまう。 22549 goto.draw の opts=sgr0 は、例え移動が起こらなくても sgr0 の出力を行うという 22550 物であった。→方針を変更して goto.draw に sgr0 を指定して其処で強制的に 22551 sgr0 を出力するという事にした。 22552 22553 * エラーメッセージ "bash: ((: '0': syntax error:" (reported by rux616) [#D1497] 22554 https://github.com/akinomyoga/ble.sh/issues/92 22555 22556 [状況] 22557 22558 bash: ((: '0': syntax error: operand expected (error token is "'0'") 22559 22560 * 最近発生する様になったという事。 22561 22562 * 一度発生し始めると色々なキーを入力する度にメッセージが出るという事。 22563 22564 * RET TAB BS 及び function keys が全滅。0-9 や numpad key も駄目。 22565 何故か # や & 等の記号は OK 22566 22567 これは decoder が関係している気がする→2021-02の変更点を探してみたが特に怪 22568 しい所はない。 22569 22570 * 連想配列が配列に化けてしまって発生しているという可能性もある。 22571 然し、連想配列の添字に quote 付きの文字列を指定する事があるだろうか。 22572 そもそも連想配列の添字に指定した '' が除去の対象だったかどうか怪しい。 22573 →試してみた所、どうやら展開の対象の様である。 22574 22575 最初は発生していなくて途中から発生する様になるというのも不思議な事である。 22576 22577 再現できた。というか空の blerc でも再現できた。どうも set -o vi だと発生し 22578 なくて set -o emacs だと発生する様だ。 22579 22580 bleopt default_keymap=vi でも起きなくなる。 22581 bleopt default_keymap=emacs; set -o vi だと起きる。 22582 bleopt default_keymap=safe でも起こらない。 22583 22584 うーん。emacs.sh の問題かとも思ったが最近変更した内容に関係のありそうな箇所 22585 は存在しない。だとすると別の場所で発生した問題が emacs.sh の中でたまたま見 22586 える様になっただけと考えるのが自然だろうか。 22587 22588 取り敢えずなにかエラーメッセージが出ているという事はその場所を特定するとい 22589 うのは簡単の筈である。 22590 22591 | 取り敢えず PROLOGUE と EPILOGUE の間だという事は分かった。decode byte 関 22592 | 連ではない。home を押しても一組しかエラーメッセージが出てきていないという 22593 | 事と、keymap safe, vi では発生していないという事から考えるに。だとすると 22594 | 残っているのは widget 実行辺りなのだが、様々な widget で発生している事か 22595 | ら __before_widget__ が怪しい。 22596 | 22597 | →確かに __before_widget__ だった。特に ble-edit/undo/add の中でエラーが 22598 | 発生している。 22599 | 22600 | % 更に ble-edit/undo/.get-current-state の内部で実行が途絶えている。と思っ 22601 | % たがそうでもなかった。その次の行の辺りだった。 22602 | % 22603 | % _ble_edit_undo_index に整数が入っている筈なのに history という文字列が入っ 22604 | % ている。と思ったら勘違いだった。_ble_edit_sttr に history という文字列が 22605 | % 入っているだけだった。 22606 | 22607 | やはり .get-current-state だった。調べると _ble_edit_undo_index の中に 22608 | '0' という文字列が設定されている。これは何処から来るのか調べる必要がある。 22609 22610 分かった。配列を保存・復元する時に quote-words 的な処理で囲んだ要素を eval 22611 で評価するべき所が単に split-words で評価していたのが原因。最初は 22612 quote-words 的な処理にに書き換えたのが原因かと思ったが、逆で eval していた 22613 所を split-words に書き換えてしまったのが原因だった。つまり、犯人は 5f9adfe 22614 だった。IFS の調整として分割を全て split-words に置き換えた時に余分に書き換 22615 えてしまったのが原因。 22616 22617 修正した。 22618 22619 * ok: 他に似たような書き換えミスがなかったかどうか確認してみたが大丈夫の様 22620 である。 22621 22622 後で改めて見てみたら修正によって破壊している。最近どうも全然駄目だ。毎回修 22623 正する時に新しいミスを導入にしている。改めて修正した。 22624 22625 2021-02-24 22626 22627 * Makefile: keymap/*.txt に対する規則を削除してはいけなかった (reported by nihilismus) [#D1496] 22628 https://github.com/akinomyoga/ble.sh/issues/91 22629 22630 f25a6e8 が悪い。22日15時過ぎに push したと思うから大体1.5日の間壊れていた事 22631 になる。これは良くない。修正した。動作確認もする必要がある。 22632 22633 2021-02-23 22634 22635 * util: vbell で座標計算がずれる [#D1495] 22636 22637 [状況] 22638 22639 | 座標計算がずれる様になっている。ble.sh のディレクトリで空コマンドラインで 22640 | TAB 補完を実行しようとすると、complete_limit に達すると同時に sabbrev 候補 22641 | の \ が一次挿入される。この時に座標が一つ左にずれる。 22642 | 22643 | 8856a04 では問題は起こっていない。3cadd54 では問題が発生している。37363be 22644 | でも発生している。3cadd54 は ecb8888 に対応する。 22645 | 取り敢えず問題の commit は 69228fa にあると分かった。 22646 | 22647 | * bleopt edit_vbell= にすると問題は発生しなくなる。 22648 | * visible-bell の先頭で return して実際の処理を行わない様にすると発生しなく 22649 | なる。 22650 | 22651 | 問題の commit では vbell に対する修正も色々入っている。やはりこの辺りが怪し 22652 | い。 22653 | 22654 | これは sc/rc による問題だろうか。然し、_ble_term_sc= _ble_term_rc= としても 22655 | 問題は再現している。fork の直前で return 0 すれば問題は生じない。つまり 22656 | .show 自体の問題というよりは出力が混ざる事による問題の様な気がする。 22657 | 然し buffer.flush を fork 直前に挿入しても何も効果はない。 22658 | 22659 | うーん。タイミングが丁度悪いという事なのだろう。 22660 22661 あー。分かった。save-position/restore-position しているが、この時に 22662 _ble_canvas_{x,y} を参照している。然し、これらの値は subshell の中では更新 22663 されない。これが理由で座標計算がずれてしまうのである。 22664 22665 [解決法] 22666 22667 どの様に対策すれば良か。何が問題かと言うと…bottom-dock に対応する為に 22668 SC/RC を使っていて、それが visible-bell の使っている SC/RC と衝突していると 22669 いう事。コマンドライン上に居る時には visible-bell の為に SC/RC しても良いが、 22670 bottom-dock にいる時には visible-bell が SC/RC すると本来のコマンドライン上 22671 の位置が失われてしまって問題になる。これを防ぐ為に visible-bell では一旦コ 22672 マンドライン上に復帰してから visible-bell を表示する事にしている。 22673 22674 どの様に解決するべきか。 22675 22676 a IPCか何かを使って vbell の状態変化を親シェルに伝達して描画は親シェルで行 22677 う様にする? 然しどの様に伝達するのが良いだろうか。 22678 22679 - シグナルは bind -x の内部ではチェックされない (もしくは bash の内部的に 22680 はチェックされているのかもしれないが対応する trap handler の呼び出しが 22681 遅延される)。然し、或いはそれでも良いのかもしれない。例えば現在 22682 bash-3.0 における C-d の読み取りは外部プロセスに行わせていて、C-d を検 22683 出したらファイルに書き込んでシグナルを送信する仕組みになっている。 22684 22685 - tty に文字を挿入する事ができれば decode の枠組みに自然にイベントを組み 22686 入れる事ができるが、実際の所 tty に文字を外部から挿入する事はできない。 22687 シグナルを 22688 22689 - FIFO か何かを使って通信するというのはよくある方法だが、現在の実装では 22690 visible-bell を実行する度に新しくプロセスを立ち上げているので、pipe を 22691 沢山管理しなければならないので非効率的である。 22692 22693 - ファイルを使って処理をするという手が考えられる。bash-3.0 C-d でやってい 22694 る様にファイルに書き込んでからシグナルで通知する。然し、複数のプロセス 22695 が走っている場合には出力が混ざりあった時に問題が発生する。mkdir 等を使っ 22696 て同期するという手も考えられなくはないが益々処理が重くなってしまう。 22697 22698 プロセスごとにファイルを作って処理するという手も考えられる。そして、読 22699 み取り用のプロセスは一つに絞る事にする。というか実は親プロセスで読み取 22700 りを実行すれば良いだけの気もする。ファイル書き込み中の同期に関しては、 22701 現在既に visible-bell でやっている様に複数の状態通知様ファイルを作って 22702 ファイルが空かどうかで判定する様にすれば良い。 22703 22704 b そもそも別のプロセスを作る必要があるだろうか。全て親シェルで実行すれば良 22705 いのではないだろうか。折に触れて状態をチェックしつつ sleep して時間が来た 22706 ら親シェルが書き換え・消去を行う。 22707 22708 然し、この方法の問題点は Bash 3.0 である。read -t 0 がないので、ユーザー 22709 入力が来た事の判定ができない。ユーザー入力があると想定してすぐ抜ける様に 22710 していると、実際にユーザー入力がなかった時に bind -x による制御が戻ってこ 22711 ないので、次にユーザー入力があるまで vbell の処理をする事ができなくなって 22712 しまう。ユーザー入力がないと想定して処理を続けると、vbell が表示されてい 22713 る間ユーザー入力が処理できなくなって固まった様になってしまう。 22714 22715 そうするとやはり別プロセスに任せてそれをシグナルで処理するという事になる 22716 のだろうか。実際の所、シグナルハンドラーの中での処理は色々と怪しい事が起 22717 こるのでやりたくない。 22718 22719 複数のサブシェルとメッセージをやり取りする様な一般的な枠組みを整えるのも 22720 手なのかもしれないと思う。 22721 22722 c 取り敢えず今まで通り sc..rc が自由に使える前提で処理する 22723 22724 今まで問題が起こっていなかったのは SC したまま放置される様な状況がなかっ 22725 たからである。その為いつでも SC...RC を気兼ねなく用いる事ができて親シェル 22726 の _ble_canvas_{x,y} の状態に依存せずに実装する事ができていた。本当の所、 22727 タイミングが悪ければ SC...RC が overlap して描画が乱れる可能性は 0 ではな 22728 いが確率的にはとても小さい筈。というのもシーケンスの書き出しは buffer に 22729 貯めてできるだけ atomic に行っているので。 22730 22731 実は現在の所は SC/RC によって bottom-dock を実現しているとは言え、カーソ 22732 ルを bottom-dock に放置する様な事はしていない。なので、visible-bell の書 22733 き換えを行う時には常に SC..RC は閉じていると想定して良いのではないか。 22734 22735 取り敢えず現在は c の方針で回避する事にする。 22736 22737 * tui: trace に align/justify 機能を実装する [#D1494] 22738 22739 prompt_status_line に右寄せの内容と左寄せの内容を表示するという需要はある。 22740 原理的にはユーザーの側で自前で実装してもらう事は可能である。然し、文字幅を 22741 考慮に入れる等すると実は非自明である。 22742 22743 * prompt_status_line の中で適当に文字列を分割・計測したりして処理する方法も 22744 考えたが非効率な気がするし、エスケープシーケンスの中に justify の文字が含 22745 まれていたり、或いは prompt 展開の結果として justify の文字が現れる場合な 22746 どにも対応したいと思うとより下流で処理するべきである。 22747 22748 * また、prompt_rps1 に於いても現在の実装では描画内容全体を一塊として右寄せ 22749 しているが、各行について右寄せをする様にしたい。 22750 22751 その様に考えると trace の中で一括して実装した方が理に適っている気がする。 22752 22753 * justify のデザイン 22754 22755 | justify 用の文字の幅を保持するかしないかという問題が存在する。空白で 22756 | justify する場合にはどんなに狭くても空白一個分は開けなければならない。そ 22757 | うでないと英単語が互いにくっついてしまう事になる。他の制御文字等でフィー 22758 | ルドを区切る場合にはどうするか。うーん。その場合でも空白一個分は開けて置 22759 | きたい気がするが、しかし一方で | 等の様な記号を含める場合にはフィールドセ 22760 | パレータの分の空白があると邪魔なのではないか。 22761 | 22762 | 後、間を埋める文字についても指定できて良いのではないかという気がする。つ 22763 | まり、...... で埋めたり ------ で埋めたりするという事。実際に Emacs は 22764 | ---- で余分な部分を埋めているし、TeX の目次の様に .... で埋める様な機能が 22765 | あっても良い様な気がする。 22766 | 22767 | 指定方法について考える事にする。例えば、図形文字を sep に指定した場合には 22768 | 少なくとも 1 文字は其処にあると想定する。間を埋める場合にはその図形文字を 22769 | 繰り返す。制御文字を sep に指定した場合には幅が狭い時には零幅になる事を許 22770 | 容する。sep として複数の文字を指定できる様にし、それぞれの sep に応じて振 22771 | る舞いを変える。 22772 | 22773 | この方法の問題点は本文の中に fill 文字と同じ文字がある時に困るという事。 22774 | そう考えると fill 文字はやはり外部から指定できる様にした方が良いのではな 22775 | いか。でもそうすると間隔毎に異なる fill を使う事ができない。必ずしも sep 22776 | と fill を同じにしなくても良い。各 sep 毎に fill を指定できる様にするとい 22777 | うのも手である。但し、その場合にどうやって引数を指定するのかは謎である。 22778 | 22779 | というか空白の時にだけ特別扱いすれば良いだけなのでは。空白で justify する 22780 | のは英文の場合である。似たような文脈で空白以外で justify するという状況は 22781 | 考えにくい。 22782 22783 仕様: 連続する同じ SEP がある時、その数はその SEP によって挿入される間隔 22784 の weight を表す。同じ SEP が離れて複数ある場合は、その SEP の間の文字列 22785 をその SEP に対応する FILL と解釈する。例えば SEP SEP -- SEP の場合はこの 22786 SEP の間隔の weight は 2 で fill は "--" と考える。 22787 22788 最小間隔は通常 0 であるが SEP が空白の時は特別で 1 である。これは通常の英 22789 文の様なものを想定した特別規則である。 22790 22791 実装方法について考える。やはり put-atomic, put-ascii を修正する事になる。 22792 clip とは相容れない。clip も処理しようと思ったら先に配置を決めておいて、 22793 その後で再び trace に入れて clip を実行する等という具合にする必要がある。 22794 22795 clip と同様に出力する文字だけちゃんと配置できれば問題ない。 22796 その上で気にする必要があるのは "現在の塊" の範囲と、 22797 span weight である。 22798 22799 うーん。measure についても justify が設定されている場合には注意が必要である。 22800 これも clip と同様に最初の実行では justify 用に使用して、後の実行に於いて改 22801 めて計算し直すのが適切である用に思われる。 22802 22803 はみ出そうになった場合はどうするべきか。これは confine 等の取り扱いにも依る 22804 のではないかという気がするが、それらの処理は put-atomic, put-ascii の外側で 22805 為されている気がするので後で個別に考えれば良い。 22806 22807 うーん。put-atomic 等の中では実は何も気にしなくて良い気がする。 22808 22809 * reject: というか sep が図形文字の場合には、最初の各セグメントの幅計測時に 22810 は取り敢えず sep の幅も考慮に入れても良いのではないだろうか。うーん。やは 22811 り考慮に入れない方が自然の気がする。 22812 22813 * done: xI yI を記録する。変数名は jxI jyI 等の方が良いのかもしれない。 22814 →jx0, jy0 という名前にした。 22815 22816 * resolved: 現在の実装だとはみ出る場合にどうすれば良いか想定していない。という 22817 よりはみ出る場合に対して対策する必要はあるのだろうか。そもそも最初の点と 22818 最後の点だけ記録して、measure-bbox の内容は反映しなくても良いのではないか。 22819 その方が柔軟に設定できる様な気がする。 22820 22821 →各フィールドについて初期位置と最終位置だけを元にして配置を決定する様に 22822 変更する事にした。 22823 22824 然し、これだと右端を超えて描画されてしまう可能性が排除できない。うーん。 22825 その場合には適切に shift か clip を行う必要がある気がする。やはり初期位置 22826 と最終位置ではなくて幾何的に位置を決定する必要があるだろうか。でも、x1:x2 22827 が初期位置・最終位置の範囲外にはみ出ているという事は元からフィールド間で 22828 overlap があるという事に他ならないのだから、overlap してしまう事自体は問 22829 題ないのではないか。 22830 22831 範囲外に収まらない時にのみ位置を shift するという処置を導入する事にする。 22832 →その様に修正した。 22833 22834 * resolved: xenl の問題について。 22835 22836 一番右端に寄った時に改行してしまう様な端末の場合、下手に一番右まで fill 22837 してしまうと描画が壊れてしまう。一番最後に出力した文字が右端に接触してい 22838 る時に改行が起こると想定しても良いかもしれないが、もし描画の途中で複数回 22839 右端に接触するという様な事があった場合、やはり描画が崩れてしまう。 22840 22841 xenl のある端末の場合には一番右端まで領域を使ったとしても問題がないのかと 22842 思いきや、実は相対移動で左に移動しようとした時に結局ずれが生じてしまう。 22843 基本的に relative で移動している時には右端は使えないと考えるべきなのであ 22844 る。 22845 22846 [実装] 然し、status line ではやはり右端まで使いたい。やはり一番右端に接触 22847 するのは、それぞれの行に於いて唯一回最後だけという想定をして良いだろうか。 22848 うーん。一応一番最後の位置と x2 が一致しているか確かめて、もしそうであれ 22849 ば一番右端に一番最後に接触したと想定する事にする。 22850 22851 →そうするとやはり結局 measure-bbox は有効にする必要がある。 22852 22853 x ok: ble/canvas/trace/.process-overflow に関しては justify に対して 22854 opt_relative を入れる事にすれば問題ない筈だが…。うーん。 22855 22856 これは微妙だ。xenl cap のない端末ではそもそも最後の文字を出力しない様にし 22857 なければならない。というかそういう観点で言ったら実は、現在の 22858 opt_nooverflow の実装は駄目なのでは…。xenl のない端末で改行が発生してし 22859 まう。でも、opt_relative の時には OK である。 22860 22861 少し xenl の取り扱いについて調整した。 22862 22863 x ok: 現在の実装では !xenl の時に ble/canvas/trace で無駄な改行が入ってしま 22864 うのではないか。少し確認が必要である。どの様に検証するか。うーん。 22865 22866 と思ったが問題の計算をしている所では opt_clip || opt_relative を仮定して 22867 いたので、そもそも端に接触するという事はないと考えている。なので、勝手に 22868 新しく改行が挿入されてしまうという心配は要らないという話だった。一方で、 22869 新しく導入した justify が関係して来る時には何が起こるだろうか。うーん。す 22870 ぐに .NEL を実行していて、更に .NEL の中では x==cols かどうかについてチェッ 22871 クしている訳ではないので大丈夫の筈。というか、justify の時には最初に仮想 22872 的な領域に書き込んでいて、右端で改行してしまう事に関しては後の再配置の時 22873 に処理する事になっているので気にしなくて良い。そういう意味では、後の xenl 22874 の処理に関しても同様。 22875 22876 * done: 他に改行が必要になりそうな箇所を一つずつ探していく事にする。 22877 22878 * ble/canvas/trace/.put-ascii.draw は justify の時には途中で改行する可能 22879 性のある動作はしない様にしてある。大丈夫の筈。 22880 22881 * その他の通常文字(全角)の挿入の場合も範囲に入る時のみに文字列を出力する 22882 様にしてあるので勝手に改行が発生する事はない筈。 22883 22884 * done: VT, CR, IND, RI でどの様に処理するのが良いかは微妙。別の行に移っ 22885 たと見做すのか或いは、また同じ行に戻ってきたら align するのか。というか、 22886 行った先でまた出力など起こす事を考えると、うーん? でも CR 以外は列番号 22887 は保持される。という事を考えると水平配置は途切れないと考えるのが自然な 22888 のではないか。 22889 22890 VT/IND/RI に関しては何も処置はしない事にする。 22891 22892 CR に関しては微妙である…。新しいフィールドという事にするか? 然しそれだ 22893 と指定もしていない sep が有効になっている感じで変である。うーん。jx0 に 22894 戻るというのが自然な振る舞いの気がする。 22895 22896 * ok: CUU,CUD,CUF,CUB に関しては相対移動なので同じフィールド内での移動と 22897 解釈する事にする。 22898 22899 * ok: HPA,CUP,CHA 等に関しては列番号を直接操作するので水平位置が途切れる 22900 様な気がする。然し、だからと言って別の行に移る訳でもないし…。これで移 22901 動しても同じフィールドの中にいるという事にする。 22902 22903 * done: SC/RC に関してはどの様に取り扱うのが良いか。SC/RC についても 22904 SC/RC の内部にいる間はsep・改行も含めて特別な処理はしない様にするのが良 22905 い気がする。 22906 22907 * done: \1..\2 による保存・復元。これに関しては field を跨いで復元される 22908 と微妙な感じだが…。うーん。或いは \1..\2 の内部では field の処理は無効 22909 化する? それが自然な気がする。これは後で実装する事にする。 22910 22911 * done: 空白文字の sep については特別扱いする。前の要素に空白文字を含めてし 22912 まって良い→と思ったがそれだと行折返しが発生した時に行末に余分な単語が含 22913 まれてしまう。 22914 22915 ここは単に右に一文字ずらす事で span を最低限保つという方式にした。 22916 22917 然し、この時の問題点は、他の種類の sep と混合していた時に、必ずしも空白に 22918 対応する sep に確保した span が割り当てられるとは限らない事。うーん。各 22919 span に対して "最低限これだけの幅は確保する" という制御は必要になるだろう。 22920 最初の計測の時点でその情報を参照するのだから、その情報も sep の記録に一緒 22921 に記録することにするのが良い気がして来た→その様に書き換えた。 22922 22923 * ok: opt_relative を imply する。opt_measure も imply する。これらは判定を 22924 flags を用いて行う様にしたい。 22925 22926 →これらは適当に実装した。 22927 22928 1 現在の実装では opts=relative -> R, opts=measure-bbox -> M, opts=justify 22929 -> J を割り当てた。 22930 2 更に、char flags だと算術式の中で使えないので、別に変数 opt_relative (R), 22931 opt_measure (M or J) を用意した。 22932 3 他に、xenl についても opt_relative の時には自動的に imply する様にした。 22933 22934 * done: $trace_flags == *M* が設定されている時に、範囲を改めて計算する。 22935 →実装した。 22936 22937 特に center align している時に範囲を正確に抽出できているか確認する。でき 22938 ている。OK 22939 22940 * done: test: フィールドの x1:x2 が範囲外にはみ出る時に正しくシフトできてい 22941 るか。 22942 22943 →うーん。右端に一文字余裕を残した実装になっている。これは意図的な物だっ 22944 たか。確認する。うーん。xlimit が 29 になっている 22945 22946 % →と思ったらこれは意図的な物だった。範囲を右端にはみ出ているので xenl 22947 % のない環境では xlimit を一文字減少させている。 22948 22949 しかしよく考えたら、シフトを実装した今この取り扱いは不要な気がする。つま 22950 り、xenl のある端末では別に一番右端まで行っても良い。シフトがあるので右端 22951 を超えてしまう事はない。一方で、xenl のない端末の場合には常に駄目。 22952 22953 * ok: 行末で begin-line してその後に改行が入るとどうなるのか。 22954 即座に end-line して空で終われば良し。そうでなければ対策が必要。 22955 22956 →うーん。その様な状況があるのだろうか。元々何故このような事を考えたのか 22957 思い出せない。要するに $'\nhello' 等の様になっている時にどうなるかという事? 22958 この時は空の文字列が作られて終わるだけの気がする気にしなくて良い。 22959 22960 と思ったが、現在の実装だと空の行に対しても無駄に処理をしている。この辺り 22961 は最適化の余地がある。取り敢えず justify_fields と DRAW_BUFF の中身を確認 22962 して空ならそのまま戻る様にした。 22963 22964 * done: clip している時にも対応する。これの対応はどの様にするべきか。 22965 22966 a 内部で再帰的に trace を呼び出して二回処理を行う。この時 opts を構築する 22967 のが面倒そうである。 22968 22969 b trace の中身の中心部分を別の関数に分けてそれを二回呼び出す様にする。 22970 22971 思うに殆どの opts は一回描画内容を決定したら継承しなくて良い気がする。 22972 寧ろ clip 処理は clip だけに徹するべきの気がする。という観点から考えると、 22973 方針 a に従って後で clip 用に trace を一回実行するのが良い気がする。 22974 22975 * reject: 改行をしても別のフィールドには移らないオプション? 同じフィールド内で改行 22976 を行う。その時には xI:y+1 に戻る。 22977 22978 また、フィールド内での CR はそのフィールドの開始位置に戻るべきでは。と思っ 22979 たが元からそういう実装になっていた。 22980 22981 うーん。そういう事をしたければ \r\v 等とすれば良いのではないか。実際それ 22982 で動く筈。 22983 22984 x justify:confine が変な動きをしている。一方で justify:truncate は動いている。 22985 →これは confine の側のバグだった。修正した。 22986 22987 * done: 空白の時は空白で fill する。 22988 22989 [追加修正] 22990 22991 x \r が含まれている時に振る舞いが変である。→これは \r でフィールドの先頭に 22992 移動した時に追跡座標 x を正しく設定していなかったのが原因だった。修正した。 22993 22994 o \v の動作については確認した。恐らく大丈夫。IND/RI も試していない 22995 が大丈夫だろう。 22996 22997 * 2021-02-06 tui: trace に clip 機能を実装する [#D1493] 22998 Ref #T0007 22999 23000 Note: これは元々 tui 計画の一部として実装した物だったが prompt_status_line 23001 や prompt_rps1 の為の align 実装に使う為に、trace を大幅に拡張したいという 23002 事で、独立な commit として適用する事にした。 23003 23004 2021-02-22 23005 23006 * prompt: status line が最初の起動時に表示されていない [#D1492] 23007 23008 | 何故だろうか。。。うーん。プロンプトが初期化される前だから? でもプロンプト 23009 | が初期化されたら…うーん? 23010 | 23011 | screen の中だと遅れて statusline が表示されるが、contra の中にいると次に何 23012 | か新しく表示されるまで何も表示されない。そもそもこの違いは何処から来るのだ 23013 | ろうか。screen の場合には誰かが invalidate しないと再描画がなされない筈なの 23014 | である。 23015 | 23016 | * screen で何故再描画が実施されるのか。調べてみると何らかのデータを受信した 23017 | 折に screen の中での再描画が走っている。 23018 | 23019 | DA2R を受信した時に再描画が走っているのだろうと思ったがそうでもない様だ。 23020 | contra でも DA2R は受信している。また、DA2R を受信してから一拍置いてから 23021 | 再描画が走っている様に見える。 23022 | 23023 | もう少し詳しく受信しているバイト列を確認する事にする。 23024 | 23025 | % うーん。分かった気がする。screen が CPR に応答した時に char_width_mode 23026 | % が変わって invalidate が起こっているのではないかという気がする。contra 23027 | % については CPR に応答していないが為に char_width_mode による invalidate 23028 | % が起こっていない、という事なのだろう。 23029 | % 23030 | % →と思ったがやはり CPR ではない様である。先ず contra は一切 CPR に返事を 23031 | % しないのは予想通り。一方で、screen はそもそも char_width_mode についての 23032 | % CPR 要求はしていない。何故なら char_width_mode に emacs を指定しているか 23033 | % ら自動判定にはなっていないのである。代わりに DECSTBM の判定に使っている 23034 | % CPR を受信している。然し、その受信した CPR を完全に無視する様に書き換えて 23035 | % もやはり再描画は発生しているのである。 23036 | 23037 | 再描画が起こっている理由について調べる。$caret_state が変化している事によ 23038 | る再描画の様子である。 23039 | 23040 | ? yes: というより本当にこの dirty の判定の所まで到達しているのだろうか。 23041 | もっと前の段階て撥ねられていないだろうか。と思ったが、大丈夫の様だ。こ 23042 | の判定の部分までは到達している。 23043 | 23044 | caret_state の値について出力して確認してみる。 23045 | 23046 | contra 内部 screen 内部 23047 | ---------------- ------------------ 23048 | old=0:0:0::: old=0:0:0::: 23049 | new=0:0:0::: new=0:0:0::: 23050 | dirty:2 dirty:2 23051 | old=0:0:0::: old=0:0:0::: 23052 | new=0:0:0::: new=0:0:0::: 23053 | dirty:clean dirty:clean 23054 | old=0:0:0::: 23055 | new=1:0:0::: 23056 | dirty:3 23057 | chars=(DA2R...) chars=(DA2R CPR) 23058 | CPR ble/term/t 23059 | old=1:0:0::: old=0:0:0::: 23060 | new=1:0:0::: new=0:0:0::: 23061 | dirty:clean dirty:clean 23062 | old=1:0:0::: old=0:0:0::: 23063 | new=1:0:0::: new=1:0:0::: 23064 | dirty:clean dirty:3 23065 | 23066 | 起動の振る舞いを見ると contra の場合には、CPR DA2R の応答を貰うよりも前に 23067 | 再描画の機会がある様だ。うーん。 23068 | 23069 | ? 不思議な事に keymap_vi_load の実行は比較的最初に済んでいるという事であ 23070 | る。もう一つの不思議な事は contra の内部でも dirty:3 が発生しているのに 23071 | も拘らず prompt update が実行されていないという点。prompt の update の 23072 | 条件についても確認するべき気がする。 23073 | 23074 | どうやらプロンプトが更新されたりされなかったりするのは history を読み込 23075 | んだり読み込まなかったりする事による物のようである。何故端末が異なると 23076 | history の読み込みに影響が出るのかは謎である。しかも、確率的にではなく 23077 | て確実にそれぞれの端末で異なる一貫した動作になっているのも不思議な事で 23078 | ある。 23079 23080 [状況] 23081 23082 最初に描画する瞬間は未だ keymap も読み込んでいない状態なので keymap_vi_load 23083 を経由して設定される prompt_status_line も表示されない。その後で 23084 keymap_vi_load が実行され、更にその後で再描画がかかる。 23085 23086 違いは再描画がかかるタイミングが contra の中と screen の中で何故か異なる事 23087 によって出てくる様に見える。 23088 23089 * keymap_vi_load との前後関係は実は関係ない。再描画がかかるのは何れにしても 23090 既に prompt_status_line が初期化された後の話なので、もしプロンプトの更新 23091 がかかるのであればどちらの場合でもちゃんとステータスラインが表示される筈 23092 である。 23093 23094 * 代わりにコマンド履歴の読み込みのタイミングとの前後関係が問題になっている。 23095 screen の中では DA2R, CPR を受信した後に再描画が起こるが、この段階でコマ 23096 ンド履歴が読み込み済み状態になっている。これにより再描画に際してプロンプ 23097 トの再計算が実施される。一方で contra の場合には DA2R を受信する前に再描 23098 画がかかって、この時には未だコマンド履歴が読み込まれていない。この為に、 23099 プロンプトの更新の必要がないと判定されてプロンプトの更新無しで再描画だけ 23100 が行われている。 23101 23102 何れにしても設計としてはプロンプトの設定を変更したら ble/prompt/clear を実 23103 行するべきで、更に、ble/prompt/clear を実行する時には 23104 ble/textarea#invalidate も実行するべきという事。 23105 23106 * global: IFS 対策 [#D1491] 23107 23108 多くの関数は IFS が普通の値になっているという事を前提にして書かれている。 23109 ble.sh の中では一時的に IFS を設定して動作する様になっているが、 23110 ユーザーから使用された時に IFS に変な値が設定されている可能性は排除でいない。 23111 23112 * 引数を $* で渡された時の対策は取り敢えず grc -F で ${* もしくは $* に一致させて確認した。 23113 * 配列に対する単語分割 =($...) に関してもチェックは行った。 23114 23115 * 他に配列を結合する処理に関しても注意が必要になる可能性がある。 23116 つまり、aa="${arr[*]}" の形の処理である。 23117 23118 grc '\$\{[[:alnum:]_]+\[\*\]' --exclude={test,ext,wiki} 23119 23120 取り敢えずこれも大体対応した。 23121 23122 * builtin read も IFS に依存して振る舞いが変わる。 23123 23124 他にも IFS が影響を与える様な状況はあるだろうか。恐らく他にもあると思うが、 23125 すぐには思い浮かばないので取り敢えずこれぐらいで良いだろう。 23126 23127 * global: 現在様々な関数が引数として text... を受け取っているが [#D1490] 23128 23129 実の所複数の引数を受け取る事に意味は余りない。 23130 実際に複数の引数をこれらの関数に渡している箇所があるとは思えない。 23131 現在は毎回 IFS を設定してこれらの引数を結合する様にしているが、 23132 そもそもその様な処理すら必要ないのではないか。 23133 23134 * done: (main) ble/util/put 23135 * done: (main) ble/util/print 23136 * done: (util) ble/string#escape-* 23137 * done: (util) ble/string#{toggle-case,toupper,tolower} 23138 * done: (util) ble/string#[lr]?trim 23139 * done: (util) ble/string#capitalize 23140 * done: (util) ble/util/buffer 23141 * done: (util) ble/string#split-lines 23142 * done: (util) ble/util/idle.push 23143 * done: (vi) ble/keymap:vi/string#encode-rot13 23144 * done: (complete) ble/complete/cand/yield 23145 * done: (canvas) ble/canvas/put.draw 23146 * done: (edit) ble-edit/hist_expanded.update 23147 * done: (edit) ble/widget/(in|ex)ternal-command 23148 * done: (edit) ble/widget/execute-command 23149 23150 * global: ロード時にエラーが出る (reported by 0neGal) [#D1489] 23151 https://github.com/akinomyoga/ble.sh/issues/85 23152 23153 bash: ((: 4 0: syntax error in expression (error token is "0") 23154 23155 うーん。 "4 0" という文字列が何処から混入するのかという事。 23156 "4 0" という文字列があるという事は何処かにそういう変数が存在しているという事? 23157 と思って declare -p の結果を grep で検索して 4 0 の組み合わせを探そうとしたが見つからない。 23158 配列に、要素を跨ってその様な値が格納されているのかとも思ったが、そうでもない。 23159 23160 だとするとグローバル変数ではなくて内部で一時的に生成された文字列に問題が起きているという事? 23161 23162 ((${#aaa[*]})) となるべき所を ((${aaa[*]})) にしてしまっているというのが怪しい。 23163 と思ったが m scan で引っ掛からない。 23164 sub:scan/array-count-in-arithmetic-expression でちゃんとチェックしている。 23165 23166 3588158 で発生している。前に動いていた時はいつの version かと思ったが、 23167 どうも 0.3.3 を動かしていた様なので実は 0.4 でも前からずっと問題があった可能性もある。 23168 23169 うーん。エラーメッセージから察するに "4 0" が完全な算術式として評価されよう 23170 としているという事。これにより ((...)) の形のコマンドで発生しているとすると 23171 かなり発生箇所を制限する事ができる。 23172 23173 | ./lib/core-complete.sh:2847: ((${simple_ibrace%:*})) && comps_fixed=1 23174 | ./lib/core-complete.sh:3282: if ((${simple_ibrace%:*})); then 23175 | ./lib/core-complete.sh:3293: if ((${simple_ibrace%:*})); then 23176 | 23177 | simple_ibrance に値を設定している箇所は限られている。そしてその何れの場所 23178 | でも確実に 数字:数字 の形になっているので、変な事が起こる余地はない。 23179 | 23180 | ./src/canvas.sh:1725: (($3)) && ((x=0,y++)) 23181 | 23182 | ble/textmap#hit/.getxy.cur の第三引数…ではなかった。ここでは textmap 配 23183 | 列に含まれる単語を分割している。もしかして IFS に変な値を設定されていると 23184 | いう事? と思ったがその影響が残っているのだとしたらもっと色々な大変な事が 23185 | 起こってしまう筈。そして実際に IFS= にして起動してみたが特にエラーメッセー 23186 | ジは出ていない。 23187 | 23188 | もう一つここが違いそうな理由は、報告によると起動時のみに問題が起こるとい 23189 | う事であった。然し、もしここが本当に問題になるのだとしたらそれ以降もずっ 23190 | と危ない感じになる気がする。 23191 | 23192 | 何れにしてもこの部分はもっとまともな実装に置き換えて良い気がする。 23193 | 23194 | ./src/color.sh:955: (($name)) && return 0 23195 | 23196 | name=_ble_faces__$1 としているので此処からは '4 0' という値は出てこない。 23197 | 23198 | ./src/util.sh:3244: (($2)) 23199 | 23200 | これは ble/util/test-rl-variable の第二引数である。使用箇所を確認したが第 23201 | 2引数はそもそも指定していないか指定していたとしても 1 か 0 である。なので、 23202 | これも違うだろう。 23203 23204 然し、変数に alpha='4 0' 等の値が入っていてそれを ((alpha)) 等として実行し 23205 た場合にも同じエラーメッセージが発生するので本当にこの部分で発生しているの 23206 かというのは分からない。一方で $(()) の中で実行した場合にはエラーメッセージ 23207 が異なる物になるので、やはり (()) の中で発生しているというのは確定して良い。 23208 23209 もしかすると bashrc の内部で ble-attach すると問題が発生する可能性? 23210 23211 できた。再現できた。IFS= を ble-attach の直前に記入すると問題が生じる。 23212 23213 どうやらコメントに依ると unset IFS にしている様である。という事は…。ble.sh 23214 をロードした時に unset 状態の IFS を保存して復元する時に空文字列になってし 23215 まうのが問題の原因になっている。 23216 23217 * done: IFS の unset 状態も復元する様にする。復元する様にした。 23218 23219 更にその後で空文字列の IFS が問題を引き起こしている。掘り下げていくと 23220 textarea#redraw の中で問題が発生している。 23221 23222 * done: 空の IFS でも単語分割ができる様に個々の関数を書き換える。 23223 23224 * 結局 ble/textmap#getxy.cur の問題だった。先に上で修正したと思っていたが 23225 修正漏れがあった。これで動く様になった。 23226 23227 * 他にも IFS=$' \t\n' でないと動かない様なコードはないだろうかと調べると 23228 ble/canvas/trace の sc/rc がそれだった。修正した。 23229 23230 * 他にも ble/textmap#update の中でも単語分割を使っている様子だったが、こ 23231 れは関数の先頭で IFS を設定しているので問題にならない。 23232 ble/string#split-words で書き換えようと思ったが performance の問題だろ 23233 う。そのままにしておく事にした。 23234 23235 * 他のファイルも探したら沢山あったのでこの際全て修正する事にした。他にも 23236 IFS の値で振る舞いが変化する物は沢山あるのでこれだけで local IFS=$' 23237 \t\n' しなくてよくなったりはしないが、念の為変な動作を起こさない様にし 23238 ておく。 23239 23240 x fixed: 全部直した筈だと思ったが ble-bind がエラーを出力している。 23241 →"$*" の類も全て IFS を気にする必要がある。取り敢えず util.sh の関数については 23242 IFS の値に拘らず動作する様に修正した。 23243 23244 * keymap/vi: vim mode strings の設定をもっと柔軟にできる様にする (motivated by 0neGal) [#D1488] 23245 https://github.com/akinomyoga/ble.sh/issues/85 23246 23247 Note: 0neGuyDev は名前が 0neGal に変化した様だ。 23248 23249 * done: wiki vim のページ hook の説明で := の : が余分。 23250 * done: wiki vim の設定のページで全ての項目に注意書きを書く。 23251 23252 何れにしても Cygwin での IL/DL の問題 (#D1482) に取り敢えずの決着をつけてから。 23253 →IL/DL の問題を解決したが未だ status line の問題 (#D1487) は残っていた。 23254 その後 status line の問題も解決した。 23255 23256 どうやら Vim では mode() を用いて現在のモードを表現する文字列を取得する事が 23257 できるらしい。然し、mode() だけでは表しきれない情報も存在する様である。取り 23258 敢えず似た関数を用意さえすれば既存の枠組みを使って mode を status ilne に表 23259 示する事ができるのではないか。 23260 23261 | Mode | `mode()` | 23262 |:----------------------------------------------------------------------------------------------|:---------| 23263 | INSERT | i | 23264 | REPLACE<br/>VREPLACE | R | 23265 | NORMAL<br/>(insert)<br/>(replace)<br/>(vreplace) | n | 23266 | VISUAL<br/>(insert) VISUAL<br/>(replace) VISUAL<br/>(vreplace) VISUAL | v | 23267 | VISUAL LINE<br/>(insert) VISUAL LINE<br/>(replace) VISUAL LINE<br/>(vreplace) VISUAL LINE | V | 23268 | VISUAL BLOCK<br/>(insert) VISUAL BLOCK<br/>(replace) VISUAL BLOCK<br/>(vreplace) VISUAL BLOCK | ^V | 23269 | SELECT<br/>(insert) SELECT<br/>(replace) SELECT<br/>(vreplace) SELECT | s | 23270 | SELECT LINE<br/>(insert) SELECT LINE<br/>(replace) SELECT LINE<br/>(vreplace) SELECT LINE | S | 23271 | SELECT BLOCK<br/>(insert) SELECT BLOCK<br/>(replace) SELECT BLOCK<br/>(vreplace) SELECT BLOCK | ^S | 23272 23273 これらは基本的にはそのモードに入る為に使うコマンドが使われる。 23274 然し、normal の n や select の s は名前から来ている。 23275 23276 これに倣えば。拡張するとしたら VREPLACE は gR になるだろうか。 23277 insert, replace, vreplace は それぞれ i^O R^O gR^O になる。 23278 でもどうせ組み合わせるのであれば、実の所 ^O は必要ないのではないか。 23279 23280 つまり、/(i|R|gR)?(n|v|V|^V|s|S|^S)?/ - ε (4x8-1=32-1=31種) という事になる。 23281 23282 うーん。サンプルを見ると Rv というのが存在しているが実際に試してみると R に 23283 なっている。何故だろうか。後、やはり gR というのは都合が悪い気がする。 23284 vreplace の文字はまた別に考えたい。小文字の r を考えたがどうやら既に PROMPT 23285 というのの為に使われている様だ。だとすると ^R という事になるだろうか。うー 23286 ん。取り敢えず ^R という事にする。そもそも制御文字を使うとうのが良い事なの 23287 か微妙だが。RSTUV で何れも近い値というのも比較的良い事の気がする。 23288 23289 * テストに用いた vimrc を移動する。 23290 23291 * edit: prompt_status_line の表示が崩れる [#D1487] 23292 23293 | prompt_status_line を試しに組み合わせて見たら表示がおかしくなっている。うー 23294 | ん。status の報告する文字列の高さが間違っているのが原因かとも思ったがそうで 23295 | もない。常に高さ1を強制する様に書き換えてみたがそれでも同じ問題が発生してい 23296 | る為である。 23297 | 23298 | という事はスペースを確保する時のコードが間違っているという事だろうか。これ 23299 | は丁度 stub branch で議論している物と関係する。というより stub branch の方 23300 | で何か修正を入れた気がする。その修正を適用してからこの問題が未だ継続してい 23301 | るか調べてその上で対処するべきだろう。 23302 | 23303 | →どうやら問題は継続している様だ。何故だろうか。なぜか知らないが高さを確保 23304 | できていないのが原因である。 23305 23306 [再現] 23307 23308 prompt_status_line を表示してかつ keymap_vi_mode_show= を使って vim mode 23309 string を表示しない設定にすると、一番下の行でコマンド実行した後に status 23310 line が消去されずに複製されて残ってしまう。 23311 23312 振る舞いを調べると高さの確保は一応している様子である。毎回 1->2 に増やして 23313 いる。コマンドを実行した直後には高さ 1 という事になっている為であろう。然し、 23314 問題点が幾つかある 23315 23316 * コマンド実行中にはステータス行は消去する筈なのに消去されていない。うーん。 23317 実装によるとコマンドを実行する前に ble/prompt/status#collapse を呼び出す 23318 事になっている。そして其処では set-height を用いてステータス行を消去する 23319 事になっている。然し消去できていない。 23320 23321 調べてみるとそもそも status#collapse が呼び出されていない?? いや、これは 23322 呼び出されている。という事は set-height の途中で消えているという事であり、 23323 それはつまり元から高さが 0 だったという事。高さが増える事なく status line 23324 が表示されていたという事である。 23325 23326 うーん。何かと思ったら reallocate-height.draw が呼び出されていない。現在の 23327 実装では他のパネルの高さが不整合になっていない限り reallocate-height.draw 23328 は呼び出されないのである。うーん。取り敢えず status#panel::render の中で 23329 reallocate-height.draw を試みるべきだろうか。 23330 23331 status#panel::render の中で現在の高さを確認して足りなければ再配置を要求する 23332 様に変更した。これで OK の筈。これによって textarea の方に皺寄せが行く可能 23333 性もあるが、取り敢えずはこれで良い事にする。また後で reallocate-height につ 23334 いては考え直すのが良い→別項目を立てた。 23335 23336 * decode: rlfunc.txt ファイルを移動する [#D1486] 23337 23338 * .srcoption の中身も更新した。 23339 * GNUmakefile も書き換えた。 23340 * decode.sh も書き換えた。 23341 * 他に make_command.sh と vi.sh の中で言及していたファイル名を書き換えた。 23342 * 序でに散らばっていたテスト用のファイルをリポジトリに追加しておく。 23343 23344 * term: screen で attach した時に時々 _ble_term_* が壊れる現象 [#D1485] 23345 23346 screen で attach すると何故か色々壊れる現象があったが、どうも contra からの 23347 DA2R がそのまま screen の内部の shell に伝播しているという事の気がする。 23348 DA2R を受信した時に最初に受信した時の値を保持する様にするべきではないか。 23349 もしくは一旦受信したら blehook で削除しておく。 23350 23351 2021-02-21 23352 23353 * decode (rlfunc): vi-replace in imap, vi-editing-mode in nmap (reported by onelittlehope) [#D1484] 23354 23355 それから vi-replace in imap 及び vi-editing-mode in nmap は未実装である。 23356 23357 * vi-editin-mode in nmap: 先ずは vi-editing-mode を vi-command で使うと何が 23358 起こるのかについて確認する。→どうやら vi_nmap を抜けて imap に戻る様であ 23359 る。うーん。これは単に vi_nmap/insert-mode にすれば良い気がする。 23360 23361 * vi-replace はどうやら replace-mode に入る為のコマンドの様だ。そしてこれは 23362 insert と同じで良いのではないか?? と思ったがうーん。vi-command では "R" 23363 に割り当てられている。つまり、文字幅に応じた replace-mode に入るべきであ 23364 る。 23365 23366 | vi_imap でも同等の replace-mode に入るための widget を追加するべきだろう 23367 | か。と思って、vi_imap/normal-mode-without-insert-leave & 23368 | vi_nmap/replace-mode を組み合わせて新しい widget を作りかけていたら、どう 23369 | やら既に存在していた様だ。vi_imap/overwrite-mode である。というより、既定 23370 | の insert がこれになっていた。 23371 | 23372 | なので作りかけた以下の関数は廃止。 23373 | 23374 | function ble/widget/vi_imap/replace-mode { 23375 | ble-edit/content/clear-arg 23376 | _ble_edit_mark_active= 23377 | _ble_edit_overwrite_mode=R 23378 | _ble_keymap_vi_insert_overwrite=R 23379 | ble/keymap:vi/update-mode-name 23380 | } 23381 23382 所で、既存の vi_imap/overwrite-mode は ble-edit/content/clear-arg がない 23383 が良いのだろうか。と思ったが、よく考えたら vi_imap では引数を指定する方法 23384 が存在しない。という事を考えたら別になくても良いという事なのだろうか。ま 23385 あ、ble-edit/content/clear-arg して困る事はない。もしかすると誰かが 23386 vi_imap でも arg を設定できる様に binding を追加するかもしれない。 23387 23388 結局二つとも既存の widget を辞書に登録するだけで済ませる事にした。 23389 23390 * decode (rlfunc): 既存の束縛の読み取り時にエラー (reported by onelittlehope) [#D1483] 23391 https://github.com/akinomyoga/ble.sh/issues/89 23392 23393 二種類の問題がある。 23394 23395 * 一つは LC_CTYPE であろう。現在のエンコーディングに一致しないバイト列が文 23396 字列に含まれている場合、bash の正規表現は一致に失敗する。もしくは何か変な 23397 一致の仕方をする。 23398 23399 $ alpha=$'"\x9B": self-insert' 23400 $ rex='^"[^"]*$' 23401 $ [[ $alpha =~ $rex ]] 23402 23403 然し実際に試してみたがそんな事は起こっていない。susu-linux の regcmop は 23404 振る舞いが違うという事なのだろうか。これについては no closing ... という 23405 メッセージを出している部分をもう少し詳しく見る必要がある。 23406 23407 * もう一つは vi_imap/vi_nmap で vi-replace/vi-editing-mode に対応していない 23408 という事。これは単に対応していないというだけの事なのでできるだけ対応する 23409 様にする。 23410 23411 然し、以下は期待通りに動いている。 23412 23413 rex='^"([^\"]|\\.)*$' 23414 [[ $'"\x9B": self-insert' =~ $rex ]]; echo $? 23415 23416 できた。再現できた。 23417 23418 bind '"\x9b1;2H": beginning-of-line' 23419 source ble.sh 23420 23421 更に良くメッセージを見ると正規表現でテストを実行する前に既に文字列が削れ 23422 て '"' だけになっている。 23423 23424 →これについては修正した。 23425 23426 https://github.com/akinomyoga/ble.sh/issues/89#issuecomment-782824259 23427 追記: 簡単なミスをしていた。修正する。 23428 23429 https://github.com/akinomyoga/ble.sh/issues/89#issuecomment-782827987 23430 追記: まだ駄目だった。何度でも同じミスをしている…。ちゃんと実際にテストしなければならない。 23431 23432 2021-02-20 23433 23434 * term: Cygwin console で最終行で IL/DL すると画面消去されるバグ [#D1482] 23435 23436 Solaris に加えて Cygwin console も何だか変な振る舞いをしている。 23437 どうも一番下の行で .insert-newline をすると画面の内容が全て消える。 23438 分かった。どうやら一番下の行で IL すると問答無用で画面クリアされる。 23439 これは明らかにバグである。Cygwin をアップデートしてみる事にする。 23440 23441 →cygwin を update して見たが修正されていない。なので、結局 ble.sh の側で対 23442 策をしなければならない。この様な壊れた IL に対して対策を実行する事は可能な 23443 のだろうか。 23444 23445 * 取り敢えず現在位置が分かっていれば対応は可能である様に思われる。一番下の行 23446 にいる時には IL の代わりに CSI 2K を実行すれば良い。それ以外の行にいる時に 23447 は特に問題は起こらない様だ。 23448 23449 うーん。最下部にいるかどうかで振る舞いを変えるのは難しい気がする。取り敢 23450 えず複数行の IL, DL の時にはちゃんと計算ができていれば最下行になる事はな 23451 い。問題は単一行の IL 及び DL で以下に最下行での IL/DL を避けるかという事。 23452 23453 最下行にいない時には以降の内容を下に一行ずらす役割がある。うーん。それよ 23454 り下に内容があると分かっている場合には IL/DL を実行し、それより下に内容が 23455 ないという場合には DL を実行するというのが可能な対策方法である。 23456 23457 うーん。かなり面倒臭い。というより CYGWIN の側で修正してもらえばこの様な 23458 面倒な事はしなくても良い筈なのである。取り敢えずこの workaround の為に本 23459 体の描画アルゴリズムを変更する事はしない事にする。 23460 23461 IL/DL の中だけで対策可能であればそれを実施する。そうでなければ何もしない。 23462 23463 例えば IND CUU を実行して一番下の行にダミー行を挿入して、その上で DL/IL 23464 を実行してから、RI かスクロールを実行してまた元に戻すという実装は可能だろ 23465 うか。→ SD,SU を実行してみたが消えてしまった行は戻ってこない様である。RI 23466 も同様に一度消えた内容が戻って来る物ではない。うーん。現在最下行にいるか 23467 どうかを判定して動作を切り替えるしかないのか。 23468 23469 | a 結局 DSR(6) で現在位置を問い合わせて一番下の行にいる時には CSI 2K で行 23470 | 消去する事にした。 23471 | 23472 | x これで以前よりも全画面消去が起こる場面は減ったが、それでもやはり全画面消 23473 | 去が依然として発生している。何故だろうか。IL/DL を実行している箇所は既に 23474 | 全て抑えてある。とすれば IL/DL とは別に未だ全画面消去を引き起こす物が存在 23475 | しているという事。 23476 | 23477 | 問題が発生している場所での出力内容を確認すると 23478 | 23479 | ^[(B^[[m^[[1B^M^[[2K^[[1M^[(B^[[m^[[1A^[[31C^[(B^[[m 23480 | 23481 | printf '\e(B\e[m\e[1B\r\e[2K\e[1M\e(B\e[m\e[1A\e[31C\e(B\e[m' 23482 | 23483 | うーん。全消去が起きそうな気配は何処にもない気がする。と思ったが、よく見 23484 | たら DL(1) が含まれている。これは一体何処から現れたのだろう…。あー。分かっ 23485 | た。。DSR(6) で問い合わせする前に flush しないと駄目だ。 23486 | 23487 | そして各スタックにある DRAW_BUFF にアクセスして出力予定の内容を全て集めて 23488 | flush しなければならない。然し、DRAW_BUFF の中には取り敢えず内容を構築し 23489 | て保存する為の物だったり、後で再解釈する為の物だったりする可能性もあり、 23490 | 一律に出力して良い内容7日どうかも分からない。という事を考えると put-il, 23491 | put-dl の中で現在位置を検出して出力するという対策は全然駄目である。 23492 | 23493 | | if ((_ble_bash>=40000)) && [[ ( $OSTYPE == cygwin || $OSTYPE == msys ) && $TERM == xterm-256color ]]; then 23494 | | # Cygwin console (pcon) では最終行で IL/DL すると画面全体がクリアされる。 23495 | | function ble/canvas/.put-il.workaround { 23496 | | local count=$1 23497 | | ((count==1)) || return 1 23498 | | 23499 | | # Cygwin console 以外なら対策不要 23500 | | [[ ! $_ble_term_DA2R ]] || return 1 23501 | | 23502 | | # 現在のカーソル位置の取得 23503 | | local reply= 23504 | | printf '\e[6n' >/dev/tty 23505 | | IFS= read -r -d R -t 0.1 reply </dev/tty 23506 | | local rex='([0-9]*);([0-9]*)' 23507 | | [[ $reply =~ $rex ]] || return 1 23508 | | local l=$((10#${BASH_REMATCH[1]})) 23509 | | local c=$((10#${BASH_REMATCH[2]})) 23510 | | 23511 | | ((l==LINES)) || return 1 23512 | | 23513 | | DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 23514 | | return 0 23515 | | } 23516 | | function ble/canvas/put-il.draw { 23517 | | local value=${1-1} 23518 | | ((value>0)) || return 0 23519 | | ble/canvas/.put-il.workaround "$value" && return 0 23520 | | DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_il//'%d'/$value} 23521 | | DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 # Note #D1214: 最終行対策 cygwin, linux 23522 | | } 23523 | | function ble/canvas/put-dl.draw { 23524 | | local value=${1-1} 23525 | | ((value>0)) || return 0 23526 | | ble/canvas/.put-il.workaround "$value" && return 0 23527 | | DRAW_BUFF[${#DRAW_BUFF[*]}]=$_ble_term_el2 # Note #D1214: 最終行対策 cygwin, linux 23528 | | DRAW_BUFF[${#DRAW_BUFF[*]}]=${_ble_term_dl//'%d'/$value} 23529 | | } 23530 | | fi 23531 | 23532 | b 別の手段を考える。一番上の行を犠牲にする事になるが SU/SD を組み合わせる。 23533 | 23534 | DRAW_BUFF[${#DRAW_BUFF[*]}]=$'\e[S\e[A\e[M\e[B\e[T' 23535 | 23536 | うーん。一応動いている様な気がするが、この対策法の問題点は DA2 を返さない 23537 | 端末で SU/SD に対応してない物があると描画がずれてしまうという事である。 23538 | 23539 | あとちらつきが激しく出ているという事。やはり対策を実施するのは最 23540 | 低限にしたい。 23541 | 23542 | c また別の手法。一番下の行は諦めて DL/IL をする前に必ず IND/CUU を実行して 23543 | 一番下の行は使わない様にするという作戦。これは実際に試してみた所レイアウ 23544 | ト崩れるので使えない。 23545 23546 改めてそれぞれの方法の問題点について整理する 23547 23548 a DSR(6) で問い合わせて判定する方法。 23549 23550 o この方法は出力をキャッシュしていなければ確実に最終行を判定できる。 23551 23552 x 然し実際にはカーソル移動なども含めて出力内容を複雑にキャッシュしている 23553 ので、その場で現在位置を取得したとしても全く意味がない。キャッシュを 23554 flush するにしても、それぞれのキャッシュがその場で画面に出力する事を想 23555 定した物でない場合もあり困難。 23556 23557 b SU/SD の組み合わせを用いる。 23558 23559 x 一番上の行の内容が犠牲になる。 23560 x 画面がちらつく。 23561 23562 o これについては panel 内部で動作している限りは panel の最終行にいる時 23563 にだけ対策をする。これでちらつきはある程度抑える事ができる。それでも、 23564 panel の最終行にいる時にはちらつきが出るが、そもそも本当に最終行にい 23565 る時のちらつきは抑える事ができないので、我慢する。 23566 23567 x Cygwin console であると誤判定した時に、その端末が SD/SU に対応していな 23568 いと悲惨な事になる。 23569 23570 c 一番下の行は常に空になる様にしておく。 23571 23572 x 使える領域が一行減ってしまう。 23573 x 今までの座標計算が狂ってしまうので注意深く全体を書き直す必要がある。 23574 23575 d panel で一番下の行にいると分かっている時は単に EL(2) で良い。 23576 23577 panel で一番下の行にいるという事が分かっている場合には、IL を一番下の行 23578 で実行する代わりに単に端末の最上部で DL をすれば良いのではないだろうか。 23579 と思ったが全然違う結果になるので駄目だ。 23580 23581 或いは panel で一番下の行にいるという事が分かっているのであれば何処か別 23582 の行で IL/DL すれば良いのではないか。と思ったが、それだと端末最終行にい 23583 なかった時にずれるべき内容がずれずに残るのではないか。と思ったが、そも 23584 そも panel 外の内容に関しては関知しなくて良い。 23585 23586 整理すると panel で一番下の行にいる時、panel の最上部で IL/DL を実行す 23587 る。その上で panel の最下部で EL(2) を実行すれば良い。うーん。実は最下 23588 部で EL(2) を実行するだけで良い気がしてきた。 23589 23590 結局 b に d を組み合わせて実装した。どうも既存の IL/DL は全て panel 管理下 23591 にある様だ。という事なので実は実質的に d だけでうまく行くという事。 23592 23593 x fixed: と思ったがどうも SU/SD の対策がコマンドを実行する度に発動している 23594 様子だ。と思ったがこれは単純ミスだった。opts=$2 を忘れて opts を使ってい 23595 た。 23596 23597 ? IND を \n にして見たが微妙かもしれない。端末によっては現在の x の位置をずらしてしまうから。 23598 然し、現在の設計では ind によって位置がずれてしまう事も想定しているのではなかったか。 23599 23600 と思ったが IND に対応していない物も沢山ある様だ。なのでやはり \n に頼るべきなのだろう。 23601 23602 IND を使っている箇所について改めて確認する必要がある。ちゃんと x=0 にしているか? 23603 23604 →どうも _ble_term_ind の使用は canvas.sh の中で閉じている様子である。 23605 put-ind.draw も内部でしか使われていない。殆どの箇所で既に対策済みか或いは 23606 元から column 0 にいる状態で使っている。 23607 23608 問題に成るのは ble/canvas/put-move-y.draw の内部での使用で、mc の中で動作 23609 している時には CUU の代わりに IND を使っている。put-move.draw が何処で使 23610 われているか確認すると相対移動・noscrc で使っている。_ble_term_{sc,rc} も 23611 使えないし、相対移動なので後で絶対位置を指定して補正というのも使えない。 23612 ここは IND/LF で col が移動しない状況で使われていると期待するしかない。 23613 23614 →うーん。現在の init-term だと LF が優先されてしまう。IND に端末が対応し 23615 ている事を期待して $'\eD' を使った方が安全に思われる。 23616 23617 * term: sum (Solaris console) IND/RI が使えない。他色々動いていない [#D1481] 23618 23619 * RI が使えない時にどの様にすれば良いか。 23620 23621 * 使っている箇所の一つは vbell である。 23622 23623 例えば prompt の上の行に一行 IL するという方針だと…。vbell を表示する度 23624 にずれてしまう。今ここで欲しいのは "上に一行も余裕がない時限定で一行確保 23625 する" という機能である。 23626 23627 * ble/canvas/put-ri.draw 23628 23629 これは2箇所から使われている。両方とも 23630 ble/canvas/panel/ensure-tmargin.draw という関数の中から使われていて、この 23631 関数は vbell から使う為の物である。 23632 23633 * ble/canvas/panel#clear-after.draw 23634 これは単に cuu に置き換えれば良い気がする→置き換えた。 23635 23636 結局 vbell が問題になる。_ble_term_ri が空の時に別の手法で vbell を表示す 23637 る? 23638 23639 a 例えば xterm_title を使って表示するか。 23640 23641 元から設定されている値を保存・復元したりするのが面倒である。push/pop の 23642 エスケープシーケンスも存在するかもしれないが、それに対応しているかどう 23643 かの判定も面倒である。というより RI を対応していない端末が xterm title 23644 等に対応しているとは思えない。この手法は追求しても余り意味がない。 23645 23646 b 或いは、一番下の行に表示するというのは可能だろうか。 23647 23648 この方法を取る場合には現在の canvas の tmargin の取り扱いを工夫しなけれ 23649 ばならない。というか RI が使えない場合には canvas の tmargin も振る舞い 23650 が微妙な気がする。 23651 23652 c もしくは _ble_term_ri を使わずに被っても良いので先頭行を使う。 23653 23654 然し、やはり内容が上書きされてしまうというのは都合が悪い様に思われる。 23655 23656 d もしくは毎回一番上に行を挿入する。 23657 23658 この方法だと bell が表示される度に行がどんどん下の方に移動してしまって 23659 余り嬉しい事にはならない。一応 IND を使って下に行きすぎない様に調整する 23660 事はできる。top/bottom dock に分かれている場合には制御が面倒である。 23661 23662 現在の ble/canvas/panel/ensure-tmargin.draw の実装について確認する。 23663 DECSTBM が存在する場合には、スクロール領域を設定して bottom dock を固定する。 23664 その上で RI を実行して canvas 原点の上に tmargin 行だけスペースを確保する。 23665 23666 それ以外の場合には即座に RI で canvas 原点の上にスペースを確保する。 23667 bottom に関しては破壊されてしまうのは我慢して invalidate する。 23668 23669 さて、RI が使えない場合にどの様に内容をシフトするのか。場合分けして考え 23670 る。DECSTBM が使える場合にはやはり bottom dock を固定して於いて、その上 23671 で、top_height+tmargin だけ IND を実行する。これで少なくとも top dock 23672 の下に tmargin だけのスペースができる。その後で IL を一番上で実行すれば 23673 良い。 23674 23675 うーん。完全ではないが d の方針で何とか誤魔化す事にした。 23676 23677 * done: modifyOtherkeys がそのまま出力される。 23678 23679 これは linux や minix と同様に出力しない様に変更。 23680 23681 * done: home csi 214 z / end csi 210 z 23682 23683 これは contra の escseq.html にまとめてある物に一致する気がするので確認する。 23684 23685 * done: OSC がそのまま出力されている 23686 23687 面倒なので xterm_title の所で直接 term の判定を行って切り替える。 23688 OSC を無視できるかどうかを各 OS のコンソールで確認する。 23689 freebsd, linux, haiku ではちゃんと無視できている。 23690 minix 及び sun は失敗している。 23691 23692 * prompt_eol_mark 関連のカーソル移動に使われているシーケンスにも問題のある 23693 物がある。_ble_term_sc, _ble_term_rc の既定値が \e[s, \e[u になっていたが、 23694 これらは寧ろ少数派なので \e7, \e8 に切り替える事にした。Solaris では 23695 terminfo に \e7, \e8 は載っていないが実際には使える。 23696 23697 また _ble_term_xenl に関しても terminfo になかった事から既定で 1 になって 23698 いたが、Solaris では 0 にする必要がある。修正した。序でに xenl がない時に 23699 は 0 ではなくて空文字列にする事にする。 23700 23701 x ok: RI がない時の vbell の振る舞いが駄目。再度実装を確認する。 23702 うーん。幾らか修正して、更に必要な時にだけ高さを確保する様に変更した。 23703 23704 そもそも sun console は下から出ていくと上に戻るという変な振る舞いをするの 23705 でまともに対応するのが難しい。適当な所で良しとするのが良い。 23706 23707 * done: delete キーで ^? (DEL) が送信される。これについては TERM=sun* の時 23708 に ^? を delete に変換して対策する事にした。実は既に infocmp kdch1 が ^? 23709 の時にはこの対策が実施されていたが、sun* の terminfo に kdch1 が登録され 23710 ていなかったのが原因だった。 23711 23712 x 文字 x が入力できない。emacs にするとちゃんと入力できる。.blerc を別名に 23713 すると入力できる。と思ったがこれは set -o vi が実行されなくなるからだった。 23714 更に時々 segfault もする。またランダムな文字列を実行しようともする。 23715 23716 これは恐らく "x?" で bind が形成されてその後でそれが削除される事により、 23717 x 単体の入力に対して出鱈目な文字列が実行されているという事なのだろう。 23718 では誰が x に bind しているのだろうか。。不思議である。 23719 23720 うーん。inputrc は存在していないし、bind は特に直接呼び出されてはいない様 23721 だし、という事を考えると ble.sh で呼び出している builtin bind が問題を起 23722 こしているという事なのだろうか。 23723 23724 generate-source-to-unbind-default の出力を保存してそれを読ませてみたら 23725 問題が発生するという事が分かった。特に問題のある行もない…と思いきや、 23726 23727 builtin bind -r 'x1c' (bash-4.1) 23728 23729 という変な行が混入している。これは一体何処から出てきた物だろうか。普通に 23730 動いている環境で実行してみると 23731 23732 builtin bind -r '\x1c' (bash-4.4) 23733 23734 という結果になっている。つまり、これは bash-4.1 特有の処置ではなくて一般 23735 に行われている処置である。 23736 23737 問題の箇所を確認してみると awk で sub(/.../, "\"\\x1c\"") としている。 23738 つまり Solaris awk はこの \\ を消してしまうという事。と思っていたら、 23739 既にその問題点についてコメントに書かれていた。'\'' に対しては対策されていたが、 23740 直接 \ が現れる場合については対策されていなかったのが原因。 23741 特に \x の組み合わせが x に変換されてしまうという問題の様である。 23742 \x についても対応すると共にコードの整理を行った。 23743 23744 * complete/mabdb: man awk の内容を抽出しきれていない [#D1480] 23745 23746 先ず .PD という行が挿入されている事が原因の様である。 23747 .PD という行は皆無視しても良い様な気がしたので無視する。 23748 更に、複数のオプションに対して一つの説明がなされている場合に対応した。 23749 23750 キャッシュファイルは LANG 毎に別にするべき気がする。特に LC_MESSAGES に従って 23751 設定するべき。 23752 23753 * edit: "echo " の状態で \C-x\C-v するとバージョン情報が灰色 [#D1479] 23754 23755 これは外部コマンドを実行する時に sgr0 をちゃんとしていないのが原因。何処で 23756 sgr0 をすれば良いのかと悩んだが取り敢えず insert-newline は新しい行に行くと 23757 いう意味なのだから sgr0 するのが自然である。他に外部コマンドを実行する瞬間 23758 にも sgr0 を実行する。 23759 23760 * bash-4.4 で emacs mode で C-x * が効かなくなっている [#D1478] 23761 23762 vi から emacs モードに切り替えると emacs モードで C-x が効かない。 23763 keyseq-timeout が長い時には問題は起こらない。 23764 23765 [状況] 23766 23767 | これは keyseq-timeout が関係している様だ。更に、一度 emacs モードにしてしま 23768 | うと、vim モードに戻しても依然として効かない状態が続いている。 23769 | 23770 | keyseq-timeout を長く設定してみたところ問題は発生しなくなったので、これはつ 23771 | まり "C-x ?" の組み合わせで 登録してキーを読み取ろうとしている事自体に何ら 23772 | かの問題があるという事なのだろう。という気がする。 23773 | 23774 | 然し vi に戻しても問題が持続しているのは不思議な事である。詳しく調べてみる 23775 | と vi に戻すと C-x 一回の入力に付き C-x が2回入力されている様子である。不思 23776 | 議な事である。 23777 | 23778 | * 普通に emacs モードから始めた場合には問題は起こらない。 23779 | * 同じモードで detach/attach しても問題は起こらない。 23780 | * 一回のコマンドで ble/decode/detach; ble/detach/attach しても問題は起こらない。 23781 | * ble-detach して set -o して ble-attach すると再現する。 23782 | 23783 | % 問題の一部は分かった。unbind cache に於いて "C-x ?" の組み合わせについて 23784 | % emacs モードの時にしか unbind していない。然し、これはモードに拘らず 23785 | % unbind するべきではないのか。つまり、set -o でモードを切り替えた時には元々 23786 | % と異なる keymap になっている為に [[ -o emacs ]] で判定したのと異なる 23787 | % keymap に作用する可能性がある? と思ったがそれは変だ。[[ -o emacs ]] になっ 23788 | % ているのであれば実際にその keymap になっている筈だし、unbind する時には一 23789 | % 旦元の keymap にしてから戻す様にしていた筈である。実際に 23790 | % ble/decode/detach においてその様に処理している。 23791 | 23792 | * ble-bind -m emacs -P で確認した限りは特に違いは見られない。という事を考え 23793 | るとやはり bind の側の問題であろう。何故違いが生じるのだろうか。 23794 | 23795 | 全く同じ binder を用いていても問題が生じる物なのだろうか。何より異なる 23796 | keymap に対して作用しているのに影響が出るのは何故だろうか。うーん。 23797 | 23798 | うーん。builtin bind の呼び出しを全て検査すれば大丈夫だろうか。 23799 | と思って builtin を置換する実験をして見たら滅茶苦茶になる。 23800 | 何かと思ったら eval を通して $* を参照する場合には、 23801 | 関数の中から実行すると $* が変わってしまって駄目という事。 23802 | なので、builtin を置き換えて bind の呼び出しを監視する作戦は使えない。 23803 | 23804 | 直接 bash のソースを弄ってデバグする? うーん。 23805 | そもそも一体どういう状態になっているのかというのが謎である。 23806 | vi の時には何故二回連続で C-x が受信される事態になっているのか。 23807 | 本当に C-x が二回連続で受信されているのだろうか。。 23808 | 或いは C-xC-x の entry が xmap にされていると 23809 | C-x に対しても勝手に C-x C-x のマッピングが呼びされてしまうという事なのか。 23810 | もしそうだとしたら再現は簡単で良い。 23811 23812 というより version 毎にちゃんと動いているか確認する。 23813 23814 bash-4.4 vi: 動いている 23815 bash-4.4 vi->emacs: 駄目(何も受信されない) #1 23816 bash-4.4 vi->emacs->vi: 駄目(C-x が二回受信される) #2 23817 bash-4.3: 全部OK 23818 bash-4.2 vi: 動いている 23819 bash-4.2 vi->emacs: 動いている 23820 bash-4.2 vi->emacs->vi: 駄目(何も受信されない) #3 23821 3.0..4.1 は 4.2 と同じ振る舞いである。 23822 23823 取り敢えず 4.4 の振る舞いだけは修正したい。 23824 23825 うーん。#2 については何が起こっているか分かった気がする。以下で再現できる。 23826 23827 $ bash-4.4 --norc -o vi 23828 $ bind -x '"\C-x":echo X' 23829 $ bind -x '"\C-x\C-x":echo XX' 23830 $ bind -r '\C-x\C-x' 23831 kbd <C-x><500ms> → XX と表示される 23832 23833 #1 についても何が起こっているか分かった気がする。 23834 23835 $ bash-4.4 --norc 23836 $ bind -r '\C-x' 23837 $ bind -x '"\C-x\C-x":echo XX' 23838 $ bind 'set keyseq-timeout 1' 23839 23840 この状態だと C-x を押して timeout すると何も起こらない。 23841 keyseq-timeout を短く設定してしまうのが問題という事。 23842 23843 問題 #3 では何が起こっているのだろうか。何も受信できていないというのが気に 23844 なる。emacs に移動した時に既に \C-x\C-x の bind -x & bind -r は終わっている 23845 筈である。この時点で cmd_xmap は問題がない筈。 23846 23847 #3 に関しては以下の様にして再現する事ができる。 23848 23849 $ bind -x '"\C-x\C-x":echo XX' 23850 $ bind -r '\C-x\C-x' 23851 $ set -o vi 23852 $ bind -x '"\C-x":echo X' 23853 kbd <C-x> 23854 23855 [対処] 23856 23857 | 敢えて \C-x\C-x の場所に何か変な値を設置しておく? 23858 | というかこれは元々の \C-x を検出する時の問題に関係するのではないか。 23859 | 実は以下のようにおけば問題ないのでは。 23860 | 23861 | bind -x '"\C-x\C-x":C-x 用の文字列' 23862 | bind -r '\C-x\C-x' 23863 | bind -x '"\C-x":C-x用の文字列' 23864 | 23865 | 少し実験してみる事にする。 23866 | 23867 | 取り敢えず問題の再現から。bash-4.2 で以下で落ちる事を確認した。 23868 | bash-4.1,4.0,3.2 でも同様に落ちる。bash-3.1,3.0 では変な文字列を実行しよう 23869 | として失敗する。以前の実験で 3.2 だけ無限ループになったのは偶々だったのでは 23870 | ないかと思われる。 23871 | 23872 | bind -r '\C-x\C-b' 23873 | bind -x '"\C-x":echo X' 23874 | kbd <C-x><C-b> 23875 | 23876 | さて、これの WA として \C-x\C-x を一回 bind してから unbind すると 23877 | いうのは有効か確認する。うーん。 23878 | 23879 | o 一応この対策をして置けば何れの場合にも crash はしなくなる。 23880 | 23881 | o bash-4.4 の場合にはこれで完全にOK。- 但し、bash-3.0..4.2 の場合にはこれを 23882 | 実行すると shadow binding timeout が発生しなくなってしまうので、-o emacs 23883 | の時にだけ実行する様にした方が良い。 23884 | 23885 | 0 bash-3.0..4.2 の場合には vi->emacs->vi とした時に C-x で何も受け取れなく 23886 | 成る問題 #3 は持続している。然しそれでも、従来行っていた "C-x ?" に全て 23887 | bind する作戦と同等の振る舞いを一つの binding で実現できているので、これ 23888 | だけでも新しい手法に移行する価値はある。 23889 | 23890 | vi の側でも bind -x & -r を実行すれば検出できる様にはなるが、C-x 単体での検 23891 | 出ができなくなってしまう。でもそれは emacs keymap を一度でも使うのであれば 23892 | 避けようがないので、受容するしかない。或いは、emacs でも vi の上で動作する 23893 | 様にすれば良いのかもしれないが…。 23894 | 23895 | 取り敢えずこれがどの bash version でも再現するのかを確かめる。Bash-4.0 以下 23896 | では C-x を押すと行が新しくロードされる。これが意味する所は、 bind -x によっ 23897 | て unix_execute_command は呼び出されているが、対応する文字列の探索に失敗し 23898 | ているという事の気がする。 23899 | 23900 | ? 或いは一度は却下した bind -s '"\C-x": "\xC0\x98"' を用いる方法について再 23901 | 検討しても良いのかもしれない。遅延が生じるという事が述べられているが、ど 23902 | の bash の version で起こるのか等について記録が残っていない。 23903 | 23904 | * 先ずは遅延を再現しなければならない。そしてどの様な状況で問題になるのか 23905 | を確認しなければならない。 23906 | 23907 | →うーん。bash-4.4 で bind 'set keyseq-timeout 500' にしたら再現できた。 23908 | これは何故発生しているかと言うと C-x ? が (過去に) 存在していた時に 23909 | '"\C-x":"\xC0\x98"' を実行する為には結局 timeout/mismatch が必要だから 23910 | である。 23911 | 23912 | 然しこの遅延に関しては "C-x ?" 全バインドの手法を取ったとしても共通であ 23913 | る。特に問題になるのは C-x C-x と連続で入力した時に、この C-x C-x の組 23914 | で認識されれば即座に反映されないという事である。"C-x ?" なら即座に反映 23915 | される。'"\C-x":"\xC0\x98"' だと 23916 | 23917 | C-x C-x 23918 | \xC0 \x98 C-x 23919 | 23920 | の様な形になるので余った C-x が残ってしまう。 23921 | 23922 | x 更に、bash-4.2 で '"\C-x":"\xC0\x98"' を適用してみたが、結局遅延が存在 23923 | する事には変わりがない様で、意味がない。bash-4.3 以降は現在は問題なく動 23924 | 作するので、対策は bash-4.2 以下に対してになるが、bash-4.2 以下では 23925 | keyseq-timeout を指定する事もできないのでこの遅延をどうにかする事はでき 23926 | ない。 23927 | 23928 | ? というかこの単一 bind 手法だと結局 C-x C-x とした時に遅延が生じるのではな 23929 | いだろうか→確かめた。実際にそうだった。やはり単一 bind は駄目である。 23930 | bash-4.4 ならば keyseq-timeout を短くすれば未だ何とかなるが bash-4.2 以下 23931 | では次の操作をしない限りは C-x C-x に対して結果を受信する事ができない。 23932 23933 [対処法比較] 23934 23935 単一C-x (C-xC-xを一旦設定) 23936 23937 4.4 ... keyseq-timeout の分だけ遅延が生じる。keyseq-timeout を 0 にすれば 23938 問題ない。何故 timeout 遅延が生じるのかと言うと、元々 emacs keymap には 23939 C-x ? の組み合わせが登録されていて、それらが全て削除されていたとしても 23940 (或いは削除しきれていないのかもしれない)、確定状態にならないからなのだ 23941 と言う気がする。 23942 23943 ※C-xC-xを一旦設定する措置をしないとコマンドが登録されていない旨のエラー 23944 が発生する。 23945 23946 4.2 ... timeout がないので key 一個分だけ遅延してしまう。keyseq-timeout 23947 を 0 にする訳にも行かない。 23948 23949 ※C-xC-xを一旦設定する措置をしないとそもそも、次の key が来ていざ確定し 23950 た時にクラッシュしたりランダムな文字列を実行したりして問題になる。 23951 23952 全 "C-x ?" の束縛 (C-x は unbind しておく) 23953 23954 4.4 ... keyseq-timeout により timeout が発生すると "C-x" 単一で確定が為さ 23955 れるが、その時に何も実行されない。keyseq-timeout を十分長くすれば気にな 23956 らなくなる…かもしれないが、それでも振る舞いとしては微妙。 23957 23958 ※C-x にも bind する様にしておくと今度は C-x に対して C-xC-x に対応する 23959 コマンドが実行されてしまう。 23960 23961 4.2 ... key 一個分の遅延はない。emacs では特に何も問題は発生しない。但し、 23962 一旦 emacs で "C-x ?" の組み合わせに対して全 bind を実行していると、vi 23963 の側で単一 C-x に対して bind しようとした時に支障が出る。 23964 23965 これを防ぐ為には "C-x ?" の組み合わせについて直接 -x を設置するのではな 23966 くて、文字列マクロ経由で読み取る様にするべきではないか。という事。この 23967 時の問題は…。やはり \C-x が再び現れると key 遅延が発生する事。つまり、 23968 bind '"\C-x\C-x":"\xC0\x98\x18"' 等とすると、\x18 (\C-x) に対して再び 23969 key 一個分の遅延が発生する。なので、'"\C-x\C-x":"\xC0\x98\xC0\x98"' と 23970 する必要がある。 23971 23972 * 一方で、"\xC0" や "\x98" に関しては複数バイトの束縛は行わないので、 23973 "\xC0" の timeout/key 遅延について問題が新しく発生する事はない筈。 23974 23975 Bash 4.4 では単一 C-x を採用する。Bash 4.2 以下では今まで通り "C-x ?" を全 23976 束縛するが、vi に影響が出ない様にマクロ経由で束縛する事にする。 23977 23978 2021-02-18 23979 23980 * syntax: !; 及び time; の後の文脈 [#D1477] 23981 23982 !; 及び time; の後の文脈で } fi done esac を要求しているが実際は任意のコマ 23983 ンドの筈である。少なくともそうなっている様に見える。問題の部分では #D0592 23984 を参照しているが、これは大きな書き換えなので特にこの部分で何故この様にした 23985 のかは謎。コメントには明示的に CTX_CMDXE と書かれている。そんな事はない筈な 23986 のに不思議である。 23987 23988 よく #D0592 を見てみたら "time ; echo" でエラーになると書かれている。 23989 うーん。bash の version かと思って試したらそうだった。bash 4.3 以前は 23990 "time ; echo" がエラーになるのであった。一方で 4.4 以降は OK 23991 23992 2021-02-15 23993 23994 * 2017-10-01 syntax: case $x in (a b) : ;; esac のパターン "a b" はエラー [#D1476] 23995 これも #D1474 で対応した。此処に挙げられているテストケースは有用だった。 23996 23997 どうやら一個の単語までしか駄目な様子? 23998 23999 更に case aaa in ((aaa)) echo;; esac 等の様に () の入れ子もエラーになる。 24000 shopt -s/-u extglob に拘らずエラーになる。 24001 一方で extglob の @() に関しては中で () の入れ子が可能である。 24002 つまり、case の中の (...) と extglob @(...) の文脈は異なる。 24003 24004 他にも違いはある。@(<>) は許されるが、in (<>) は許されない。 24005 @(&&) は許されるが in (&&) は許されない。 24006 in (a|a|a) は許されるが in (a||a) や in (||) は許されない。 24007 in (&), in (|), in (;), in (<), in (>) は何れも駄目。 24008 in (a&b), in (a;b), in (a<b), in (a>b) も何れも駄目。 24009 24010 どうも全然違う文脈の様に思われてきた。 24011 24012 現在の実装では ble-syntax:bash/ctx-case から CTX_PATN に突入している。 24013 (他に CTX_PATN に入っている箇所を探すと、 24014 関数の引数の括弧に何か変な物が入っている場合と、 24015 コマンドの途中で突然括弧が現れた場合である。 24016 これらはエラーに対する復帰としての CTX_PATN なのでそんなに気にしなくて良い) 24017 24018 どうも振る舞いを観察すると ctx-conditions と ctx-globpat の中間のように思う。 24019 単語を設置しなければならないという観点で言うと ctx-conditions に近い。 24020 一方で対応している構文の集合という観点で言うと ctx-globpat が幾らか近いように思う。 24021 24022 2017-11-27 追記 24023 どうやら () の中の単語ではチルダ展開も有効のようだ。以下で hello が出力される。 24024 case a=~ in (a=/home/murase) echo hello; esac # これは対応済み 24025 case a=/home/murase in (a=~) echo hello; esac 24026 24027 * syntax: case x) とした時の ")" の着色が括弧でちゃんと囲んだ時と異なる [#D1475] 24028 これは #D1474 における再実装で一緒に修正した。 24029 24030 * syntax: case a in @) で @() と入力すると fatal error [#D1474] 24031 24032 case a in ) の状態でパターンに @() を入力しようとするとシフトエラーになる 24033 24034 | もっと具体的に調べてみると case a in @) の状態で @ の直後に ( を挿入する 24035 | となる。シフトエラーになるという事は case a in @) と入力した時点で壊れて 24036 | いると考えられる。 24037 | 24038 | | 先に ) を入力した時 24039 | | $ case a in @) 24040 | | _ble_syntax_attr/tree/nest/stat? 24041 | | 18 a 000 'c' | stat=(CMDX w=- n=- t=-:-) 24042 | | | a 001 'a' | 24043 | | | a 002 's' | 24044 | | | a 003 'e' + word=CMDI:0-4/(wattr=d) 24045 | | 39 a 004 ' ' stat=(CARGX1 w=- n=- t=$4:-) 24046 | | 40 a 005 'a' + word=ARGI:@3>5-6/(wattr=d) stat=(CARGX1 w=- n=- t=$4:-) 24047 | | 41 a 006 ' ' stat=(CARGX2 w=- n=- t=$6:-) 24048 | | 42 a 007 'i' | stat=(CARGX2 w=- n=- t=$6:-) 24049 | | | a 008 'n' + word=CARGI2:@5>7-9/(wattr=d) 24050 | | 34*a 009 ' ' stat=(CASE w=- n=- t=$9:-) 24051 | | 30*a 010 '@' | nest=(CMDX w=- n=- t=$9:-) stat=(CASE w=- n=- t=$9:-) 24052 | | 30*a s 011 ')' + word="none":@8>10-12 stat=(PATN w=- n=@10 t=-:$9) 24053 | | | s 012 ^@ stat=(CMDX w=- n=- t=$12:-) 24054 | | 24055 | | 先に @ を入力した時 24056 | | $ case a in @) 24057 | | _ble_syntax_attr/tree/nest/stat? 24058 | | 18 a 000 'c' | stat=(CMDX w=- n=- t=-:-) 24059 | | | a 001 'a' | 24060 | | | a 002 's' | 24061 | | | a 003 'e' + word=CMDI:0-4/(wattr=d) 24062 | | 39 a 004 ' ' stat=(CARGX1 w=- n=- t=$4:-) 24063 | | 40 a 005 'a' + word=ARGI:@3>5-6/(wattr=d) stat=(CARGX1 w=- n=- t=$4:-) 24064 | | 41 a 006 ' ' stat=(CARGX2 w=- n=- t=$6:-) 24065 | | 42 a 007 'i' | stat=(CARGX2 w=- n=- t=$6:-) 24066 | | | a 008 'n' + word=CARGI2:@5>7-9/(wattr=d) 24067 | | 34 a 009 ' ' stat=(CASE w=- n=- t=$9:-) 24068 | | 30*a 010 '@' | nest=(CMDX w=- n=- t=$9:-) stat=(CASE w=- n=- t=$9:-) 24069 | | 30*a 011 ')' + word="none":@8>10-12 stat=(PATN w=- n=@10 t=-:$9) 24070 | | | s 012 ^@ stat=(CMDX w=- n=- t=$12:-) 24071 | 24072 | これら二つを比較しても違いは 011 の位置の s という記号のみである。この s 24073 | というのが何であるかは覚えていないが、実のところこの二つの両方で問題が再 24074 | 現するので @ を先に入力するか ) を先に入力するかは問題には関係ない。 24075 | 24076 | @の代わりに X を挿入した場合にどうなるか調べる。X に引き続いて ( 24077 | を挿入しても問題は発生しない。 24078 | 24079 | | $ case a in X) 24080 | | _ble_syntax_attr/tree/nest/stat? 24081 | | 18 a 000 'c' | stat=(CMDX w=- n=- t=-:-) 24082 | | | a 001 'a' | 24083 | | | a 002 's' | 24084 | | | a 003 'e' + word=CMDI:0-4/(wattr=d) 24085 | | 39 a 004 ' ' stat=(CARGX1 w=- n=- t=$4:-) 24086 | | 40 a 005 'a' + word=ARGI:@3>5-6/(wattr=d) stat=(CARGX1 w=- n=- t=$4:-) 24087 | | 41 a 006 ' ' stat=(CARGX2 w=- n=- t=$6:-) 24088 | | 42 a 007 'i' | stat=(CARGX2 w=- n=- t=$6:-) 24089 | | | a 008 'n' + word=CARGI2:@5>7-9/(wattr=d) 24090 | | 34 a 009 ' ' stat=(CASE w=- n=- t=$9:-) 24091 | | 30 a 010 'X' | nest=(CMDX w=- n=- t=$9:-) stat=(CASE w=- n=- t=$9:-) 24092 | | 30 a 011 ')' + word="none":@8>10-12 stat=(PATN w=- n=@10 t=-:$9) 24093 | | | s 012 ^@ stat=(CMDX w=- n=- t=$12:-) 24094 | 24095 | 然し木構造を調べても X の時と @ の時で全く同じ状態になっている。な 24096 | のにシフトでエラーが発生するというのは不思議である。 24097 | →改めて確認した所、一番最初に発生するエラーはシフトエラーではなかった。 24098 | 24099 | | ble/syntax/tree-enumerate/.initialize/FATAL2 24100 | | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:4 (ble/syntax/tree-enumerate) 24101 | | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:6 (ble/syntax/print-status/.dump-tree) 24102 | | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:8 (ble/syntax/print-status) 24103 | | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:74 (ble/highlight/layer:syntax/update) 24104 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:13 (ble/highlight/layer/update) 24105 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:10 (ble/textarea#update-text-buffer) 24106 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:76 (ble/textarea#render) 24107 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:3 (ble-edit/bind/.tail) 24108 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:18 (ble-decode/EPILOGUE) 24109 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:79 (ble-decode/.hook) 24110 | 24111 | print-status の段階でエラーが発生している。つまり、直前の状態が問 24112 | 題なのではなくて ( を入力した直後の状態が壊れているのである。 24113 | 24114 | | _ble_syntax_attr/tree/nest/stat? 24115 | | 18 a e 000 'c' | stat=(CMDX w=- n=- t=-:-) 24116 | | | a e 001 'a' | 24117 | | | a e 002 's' | 24118 | | | a e 003 'e' + word=CMDI:0-4/(wattr=d) 24119 | | 39 a e 004 ' ' stat=(CARGX1 w=- n=- t=$4:-) 24120 | | 40 a e 005 'a' + word=ARGI:@3>5-6/(wattr=d) stat=(CARGX1 w=- n=- t=$4:-) 24121 | | 41 a e 006 ' ' stat=(CARGX2 w=- n=- t=$6:-) 24122 | | 42 a e 007 'i' | stat=(CARGX2 w=- n=- t=$6:-) 24123 | | | a e 008 'n' + word=CARGI2:@5>7-9/(wattr=d) 24124 | | 34 a e 009 ' ' stat=(CASE w=- n=- t=$9:-) 24125 | | 31*a e 010 '@' | nest=(PATN w=- n='none':10- t=-:$9) stat=(CASE w=- n=- t=$9:-) 24126 | | |*a e 011 '(' | 24127 | | 6*a es 012 ')' + word="none":10-13 stat=(PATN w=- n=@10 t=-:-) 24128 | | | s 013 ^@ stat=(PATN w=- n=@10 t=$13:$9) 24129 | 24130 | というか、")" が存在しなくても普通に @( と入力しただけでエラーになってい 24131 | る。a@( としている時には大丈夫である。これはつまり単語と nest が同じ場所 24132 | で始まる事によってエラーになっているという事だろうか。うーん。確かに a@( 24133 | とすると a の位置と @ の位置の両方に nest が設定されている。という事は、 24134 | @( を入力した時に同時に二箇所に nest を設定しようとして状態が破壊されてい 24135 | るのである。だとすると $( でも問題が発生する筈→発生した。" でも問題が発 24136 | 生した。うーん。根本的に nest を再考する必要があるのかもしれない。 24137 24138 [状況] 24139 24140 以下の何れでも問題が発生する。原因は同じ位置に2つの nest を設置しようとして 24141 いる事にある。 24142 24143 - case a in @( 24144 - case a in $( 24145 - case a in " 24146 - case a in (x);;" 24147 24148 nest の位置をずらそうとしても " の場合には一文字しか無いのでずらす事ができ 24149 ない。逆にパターンの側の nest の位置を一文字前にずらすという事も考えたが、 24150 必ずしもパターンの前が空白とは限らない。例えば ;; など。この場合には結局同 24151 じ位置に nest を設置するしかない。或いは ;; の位置に nest を設置してしまう 24152 という手もあるのかもしれないが、それは不自然だし色々とまた変な問題が発生し 24153 そうである。 24154 24155 [修正] 24156 24157 やはり解決策としては同じ位置に nest を設置できる様にするという事。然し、現 24158 状のコードで nest が同じ位置に設置されないという前提は何処で使っていただろ 24159 うか。場合によって単に対応するだけでは済まないかもしれない。 24160 24161 或いはもう一つの方法として、そもそも case パターンを nest にする必要があっ 24162 たのかという事。この方法の方が確実に簡単に修正できる気がする。然し、nest に 24163 した理由は何だろうか。単に既存の CTX_PATN を使いたかったからというのであれ 24164 ば簡単である。 24165 24166 コードを確認してみたがやはり nest を使わないとすると新しい文脈値が必要にな 24167 りそうである。更に、元から case pattern の中は単語が一個だけになる様に制限 24168 を加える予定だった。これに対応する為には結局新しい文脈値が必要だったのだ。 24169 case pattern の単語数も一緒に対応してしまうのが良いだろう。 24170 24171 うーん。実はコマンド文脈で読み取った方が良い? とも思ったがそうでも 24172 ない気もする。例えば | の取り扱いが異なる。& や ; 等他の delim の 24173 場合にはエラーにする必要がある。|| は一まとまりではなく一文字ずつ取る。 24174 | の直後は再び単語を受け付けて OK。など。 24175 24176 - done: ble/syntax:bash/ctx-command-case-pattern 24177 24178 実装したが無限ループになってしまう。調べると parse の中で同じ位置に対してずっ 24179 と計算している。 24180 24181 parse (i=19): ctx=78 ble/syntax:bash/ctx-command-case-pattern-expect 24182 24183 $ case x in @() echo ;; esac 24184 24185 問題は ;; の直前で起きている様だ。これは BASH_REMATCH が途中で書き換わって 24186 いたのが見落としだった。修正した。OK 動いている。 24187 24188 ---------------------------------------------------------------------- 24189 24190 2021-02-19 assertion failure が出た。 24191 24192 assertion failure: ((_ble_syntax_bash_command_isARGI[ctx])) 24193 invalid ctx=79 in words 24194 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:15 (ble/syntax:bash/ctx-command) 24195 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:86 (ble/syntax/parse) 24196 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:7 (ble-edit/content/update-syntax) 24197 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:75 (ble/textarea#render) 24198 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:3 (ble/textarea#panel::render) 24199 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:5 (ble/function#try) 24200 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:8 (ble/canvas/panel/render) 24201 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:3 (ble-edit/bind/.tail) 24202 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:18 (ble-decode/EPILOGUE) 24203 24204 [再現] 24205 24206 | 以下のコマンドラインに於いて "'; の ; の前にカーソルを置いて、其処から BS 24207 | の autorepeat で削除を行うと確率的に上記のエラーが発生する。不思議なのは 24208 | ctx=79 は最近追加した CTX_CPATQ であり、これは case の時にしか発生しない筈 24209 | の物であるという事。現状では何処にも case はないので ctx が 79 になる事はな 24210 | い様に思われる。core-syntax.sh の中を再度確認してみたが混入する事はない気が 24211 | する。 24212 | 24213 | $ debug/builtin() { unset -f builtin; IFS=" " eval 'echo "[$*]"'; builtin "$@"; local _ext=$?; echo "[$* ($_ext)]"; 24214 | builtin() { debug/builtin "$@"; }; return "$_ext"; } 24215 | 24216 | $ d() { unset -f builtin; A=" " : ': "[$*]"'; : "$@"; : a=$?; : "[$* ($a)]"; } 24217 | 24218 | $ : helloworldhelloworld; A=" " :; : a=$?; : "[$* ($a)]" 24219 | 24220 | あー。成程。79 が現れたのは BS で消す途中に ;; が現れる為である。確率的に発 24221 | 生していたのは、丁度 ";;" の時に文法の再解析が起こるか起こらないかである。 24222 | 一つずつ BS を押していれば必ず発生する。 24223 | 24224 | $ :; :;: a=$?;: 24225 | 24226 | OK. 以下が最小再現コードである。以下の状態から間の空白を削除するとエラーになる。 24227 | 24228 | $ ; ;a=1 24229 | 24230 | というより変な事をしなくても普通に以下で問題が発生する。 24231 | 24232 | $ case x in a=1 24233 24234 取り敢えず 79 が出るのは別にバグではないという事は確認できた。 24235 そして修正は簡単だった。これは fixup にする。 24236 24237 2021-02-10 24238 24239 * ble/builtin/read: 空文字列の時 C-d でキャンセルしない [#D1473] 24240 24241 使い心地が変だと思って plain Bash で試してみたら C-d でちゃんとキャンセルに 24242 なる。ble/builtin/read もこれと同様に振る舞うべきである。 24243 24244 →これも実装した。これは簡単な修正。 24245 24246 * ble/builtin/read: 全く描画されなくなっている [#D1472] 24247 24248 これは ble/canvas/panel/render において描画するかどうかを各パネルの高さで決 24249 定しているが、textarea は textarea#render の中で高さを決定する事にしている。 24250 なので高さがいつまでも 0 の儘になってしまって結局全く描画されないという事態 24251 になっている。 24252 24253 | 本来は描画を実行する前に高さを決定するべきなのである。然し、現在の実装では 24254 | 中身の計算が重いために必要になるまで計算しない事にしている。うーん。 24255 | getHeight を受け取った時点で中身の計算を終わらせるべきだろうか。然し、希望 24256 | の高さを伝えたからと言って必ずしもその高さが通るとも限らないし、結局結果に 24257 | よっては再計算する必要が出てくる可能性は変わらない。 24258 | 24259 | その様に考えると結局現在の様な実装でも変わらないのではないかという気はする。 24260 | 或いは 0 という高さは特別な高さという事にして中身がある場合には必ず有限の高 24261 | さを指定する事にする? 24262 | 24263 | 然し、0を特別扱いする事にすると一時的に高さを 0 にして再び後で高さが有限に 24264 | なる可能性がある時、そしてその高さが有限になる機会が render の中で得られる 24265 | 場合に困る。なので、0 であってもやはり render は呼び出すべきなのではないだ 24266 | ろうか。 24267 | 24268 | うーん。然しそうすると… textarea を隠したい時にも必ず textarea が表示され 24269 | てしまうという事になってしまう。或いは、textarea を隠したい時には 24270 | _ble_textarea_panel には -1 などの値を代入しておくというルールにする? とい 24271 | うよりそもそも表示・非表示という状態は height とは別に持っておくべきなので 24272 | ある。 24273 24274 * 表示・非表示の状態は height とは別に持っておくべき。現在の実装では取り敢 24275 えず各実装に任せる事にする。 24276 24277 * render では取り敢えず高さ 0 であっても全ての panel について 24278 $class#panel::render を呼び出す事にする。これは render の中でレイアウトを 24279 計算する時に高さを変更したくなるかもしれないからである。 24280 24281 * reject: 将来的には textarea#render を textarea#layout と textarea#render 24282 に分ける事も考えるべきかもしれない。 24283 24284 | 少し textarea#layout と textarea#render に分ける事も考えたが、これをして 24285 | も結局何も変わらない。というのも、textarea#layout で高さを計算する時に自 24286 | 身の高さを変更すると結局、他のパネルの高さも全て再計算になる。なので、再 24287 | 帰的な高さ変更の可能性は、高さ計算を textarea#layout に分離したとしても本 24288 | 質的には解決していない。何か利があるとすれば最後の描画処理が省略できるだ 24289 | けである。そして最後の描画処理は ble.sh ではそんなに重い処理ではないので 24290 | 意味がない。 24291 | 24292 | また、今まで問題が起こらなかった理由でもあるが textarea は高さを要求する 24293 | が、info は高さが足りなければ他から奪おうという事はしないので、高さの更新 24294 | が再帰的になる事はない。特に textarea よりも info の方が後に render を行 24295 | うという事もあるので特に問題になっていない。(実は今までは info が描画した 24296 | 内容を textarea が truncate するという事になっていたのではないかという気 24297 | がするので、現在の実装のほうがよりまともなのであろう) 24298 24299 * 結局 height 更新の無限ループは可能性として排除できない。それは render の 24300 中で height 設定をしても、layout の中で height 設定をしても同じことである。 24301 最終的には誰かが皺寄せを食うという事にしておけば何れにしても問題にならな 24302 いし、そうでなければそもそも解が存在しない。現在の実装では info が皺寄せ 24303 を食う事になっている。 24304 24305 * global: 今度はまた別の連想配列のエラーが出ている (reported by 0xC0ncord) [#D1471] 24306 https://github.com/akinomyoga/ble.sh/issues/86#issuecomment-776165286 24307 24308 新しいシェルを開いてもエラーが出ていると書いているが本当だろうか? 24309 もしこれが同じシェルだとしたら ble-update で駄目な事になるというのは理解できる。 24310 取り敢えずその為の修正だけは入れる事にした。 24311 24312 * global: 連想配列の中身が bash-4.2 関数内ble.shソースで消滅する (reported by 0xC0ncord) [#D1470] 24313 https://github.com/akinomyoga/ble.sh/issues/86 24314 24315 4.2 で動かないという話。調べると問題の _ble_builtin_trap_n2i は連想配列であ 24316 る。という事は -g の指定が怪しい。実際に ble.sh を関数内で source したら再 24317 現できた。 24318 24319 然し、手元で reduced case を作ってみると動いている様な気がする。WINCH に対 24320 するシグナル番号を取得する時に結果が空になってしまってい 24321 る。_ble_builtin_trap_n2i から引いている。然し、 _ble_builtin_trap_n2i の値 24322 を見るとちゃんと SIGWINCH に対して 28 が割り当てられている様に見える。と思っ 24323 てよく見てみたら、途中で _ble_builtin_trap_n2i の中身が空になっている。もし 24324 かして、bash-4.2 だと属性は global まで適用されるが、値が local になってし 24325 まっているという事か。 24326 24327 実際に試してみると確かに中身が空になる。うーん。今までは -gA を 40200 以上 24328 という条件で使っていたが、これは 40300 以上という条件に引き上げるべきだろう。 24329 24330 * 結局最小再現コードは以下の様になった 24331 24332 $ bash-4.2 -c 'a(){ declare -gA d=([k]=v);};a;declare -p d' 24333 declare -A d='()' 24334 $ bash-4.3 -c 'a(){ declare -gA d=([k]=v);};a;declare -p d' 24335 declare -A d='([k]="v" )' 24336 24337 * reject: 判定条件を変数に入れて再利用できるようにする? と思ったがどうせそ 24338 の次の判定で細かく場合分けするので全体の条件だけ変数に入れて再利用しても 24339 却って分かりにくいだけである。これは棄却。 24340 24341 * reject: 連想配列の使い方に応じて declare -gA を使う bash version を切り替える? 24342 24343 使い方によっては引き続き 40200 でも大丈夫かもしれない。つまり、ble.sh を 24344 source した段階では空の儘で、実際に使っていく中で中に値をキャッシュすると 24345 いう場合。或いは、単にキャッシュとして使うという場合にも問題は起こらない。 24346 然し、実際に関数の中で値が初期化されるかどうかは attach の仕方にも依存す 24347 る。更に、これは関数内で ble.sh を source するという特殊な場合に於いての 24348 み影響が出るので余り細かい最適化を考えても仕方がない。 24349 24350 全て 40300 に書き換えた。まあ、これで何も起こらないだろう。 24351 24352 2021-02-09 24353 24354 * 2021-02-01: spike branch で tab completion で crash する (reported by 3ximus) [#D1469] 24355 https://github.com/akinomyoga/ble.sh/issues/82#issuecomment-770390986 24356 24357 Ref: これは #D1452 / #D1468 と同じ問題。詳細は #D1468 で議論。 24358 24359 eval-pathname-expansion の中で死んでいるのだろうか。failglob などの判定に失 24360 敗している可能性もある。つまり、shopt -s failglob が設定されている時に、 24361 globpat が含まれているのに含まれていないと判定された時に、set -f 等の操作を 24362 行わずにパス名展開を直接実行して、それにより強制的に終了してしまっている可 24363 能性。 24364 24365 →でも元々 failglob があっても大丈夫な様に eval を使って評価していた筈→本 24366 当だろうか。eval だけで failglob を回避する事ができていたのだろうか。 24367 syntax の方で .set-result という関数を用意したのは何か理由があったのでは 24368 ないか。と思ったが、.set-result は failglob を避ける為の物ではなくて展開 24369 結果を格納する為の物だった。 24370 24371 →更に、現在の判定方法で globpat を見逃すとも考えづらい。 24372 24373 実際に手元で failglob の設定下で補完を試みたが変な事は起こっていない。bash 24374 version の違いかもしれないとも思ったが別に 5.1 でも dev でも変な事はない。 24375 3.2 や 4.0 4.3 4.4 で試しても違いはない。 24376 24377 →hangは観測できたという話をしたらどうやら正確にはcrash ではなくて hang し 24378 ていた様だ。そして振る舞いを見る限りに於いては自分の手元で観測した hang と 24379 全く同じである。 24380 24381 * 2021-02-03 TAB completion に於いて conditional-sync で hang する [#D1468] 24382 Ref: #D1452 と #D1469 は実はこの問題と同一であった。 24383 24384 chatoyancy で再現している。 24385 24386 3ximus の報告した crash は観測されていないが代わりに linux 上で hang すると 24387 いう現象は起こっている。親 shell が固まっていて一方で子 shell はいつまで経っ 24388 ても終了しないという状態になる。これはどういう状態だろうか。子 shell に対し 24389 て kill を実行するとその時点で終了して親 shell も使える様になる。時々、再び 24390 子 shell を生成してそれが固まるという現象は発生している。subshell が発生し 24391 ている状態で固まっているという様子を見る限りは恐らく conditional-sync で変 24392 な問題が起こっているのだと思われるが分からない。 24393 24394 * 親shellの CPU が微妙に動いている。 24395 * ユーザー入力しても何故か親シェルが中断しない 24396 24397 改めて condtional sync の実装を確認してみると2回 fork している。1つの fork 24398 はジョブ管理によって変なメッセージが発生するのを避ける為。2つ目の fork が実 24399 際に & で bg job を起動する為の物。症状として見られていた hanging shell は 24400 実は worker ではなくて最初の subshell の様だ。更に詳しく調べてみるとどうや 24401 ら msleep の中で停止してしまっているようだ。つまりこれは Cygwin 上で発生し 24402 ていた #D1452 のフリーズと全く同じ問題である。 24403 24404 Cygwin のテストケースと同じ物で再現できるだろうか。 24405 24406 ( echo {1..1000} & builtin read -t 0.000100 v < /dev/udp/0.0.0.0/80 ) >/dev/null 24407 24408 Linux では /dev/udp ではなくて fifo を使っている筈。 24409 24410 OK 再現した。 24411 24412 $ mkfifo a.pipe 24413 $ exec 9<>a.pipe 24414 $ test1() { (eval "echo {0..$count}" & builtin read -u 9 -t 0.001 v) >/dev/null; echo ok $((count++)); } 24415 $ bind -t '"\C-t":test1' 24416 24417 これは結局 bash のバグなので別の場所で議論する事にした。 24418 24419 workaround を考える。 24420 24421 A 一つの方向は先ず変な事が起こる発生確率を下げるという事。 24422 然し、それでも read -t がブロックする可能性は 0 ではない。 24423 これは実の所 /dev/zero を使っていても同様の筈である。 24424 とにかく変な事が発生する確率は 0 ではないという事。 24425 24426 変な事が起こる確率を下げる為に。もう一つの可能性は以下の様に、 24427 $() を使って fork して、その後で read timeout を 24428 一番外側で実行するという事。 24429 24430 { pid=$({ echo OK >&3; sleep 10; } &>/dev/null & echo $!); } 3>&1 24431 24432 疑問としは孫シェルを wait できるのかという事。→うーん。駄目だった。 24433 24434 bash: wait: pid 9447 はこのシェルの子プロセスではありません 24435 24436 wait できない。という事は終了ステータスを検知する方法がない。或いは 24437 ble/util/assign と同様に終了ステータスは自前のファイル経由で読み取るとい 24438 う手もあるのかもしれないが…。とにかく面倒になってしまうという事は避けら 24439 れない。 24440 24441 そもそもこの方向で問題を軽減できるのかどうかも非自明である。 24442 24443 B read timeout を使わない方法を模索するべきなのかもしれない。 24444 然し read timeout が使えないとなるとやはり方法は絞られてくる。 24445 一つの方法は普通にコマンドの sleep を呼び出すという事。 24446 24447 然し、spawn のコストと、更に sleep の分解能が秒単位しか無いという可能性が 24448 ある。そう考えると read timeout はどのシステムでも使う事ができるかなり便 24449 利な機能だったのである。 24450 24451 c というよりそもそも conditional-sync ではデフォルトでユーザの入力を待って 24452 いるのだから、read -t を sleep に使うのではなくて、直接ユーザー入力を検出 24453 するのに使えば良いのではないのか? と思ったが駄目だ。read -t 0 ならばユー 24454 ザー入力を読み取らずに検査する事ができるが、read -t 0.001 だとユーザー入 24455 力を消費してしまう。そうなると気軽に実行できない。或いは、ユーザー入力を 24456 読み取る事ができた暁にはその場で ble-decode-char するという手もある? 24457 24458 うーん。然し、_ble_bind_hook の中で実行した bind/.tail の中で 24459 ble-decode-char するとすると、例えば其処でコマンド実行が _ble_bind_hook 24460 に大して設定された時に、それがその場で実行されない可能性がある。更に、設 24461 定した物が実行される前に消滅してしまう可能性すらある。ble-decode-char を 24462 その場で実行する方式にすると色々木にしなければならない事が多い。 24463 24464 d conditional-sync に限っては ALRM を subshell から投げれば良いのでは。と思っ 24465 て試してみたが、何も設置していない状態で kill -ALRM $$ すると親シェルが終 24466 了してしまう。ALRM に何か無視する様に ble.sh でハンドラを設置しても良いが、 24467 それはそれでまた面倒事が増える。 24468 24469 うーん。二つの方向性がある。全般に msleep の問題を解決するという事と 24470 conditional-sync の問題を解決するという事。今までの発生頻度から考えると 24471 conditional-sync の対策だけをしても当面は大丈夫な気もするが、何れは msleep 24472 の問題を完全解決したい。そうなった暁には conditional-sync の対策は不要にな 24473 るし、また conditional-sync の問題だけ解決するのは臭いものに蓋をしているだ 24474 けで本質的問題の解決にはなっていない。それよりは msleep 自体の問題を解決す 24475 る様に考えたいのである。 24476 24477 仕方がないので cygwin と同じ手法で回避する事にした。 24478 24479 2021-02-13 /dev/zero による workaround を追加したがよく考えたら /dev/zero 24480 が全ての環境にあるとは限らないし、ある環境でも read をブロックしてくれるか 24481 は微妙である。と思ったが /dev/zero で止まるかどうかは bash の側の実装の問題 24482 なので、もし /dev/zero が 0 を出力し続けるのであれば、ちゃんとブロックはす 24483 るだろうと思われる。 24484 24485 /dev/zero が存在する環境について一度確認はしておきたい。Solaris, Minix に存 24486 在する。FreeBSD, Haiku にも存在した。当然 Cygwin と Linux にも存在する。 24487 MSYS2 でも OK だった。何れも read -t 0.2 < /dev/zero がちゃんと期待通りに動 24488 いた。という事を考えれば基本的に全ての環境で /dev/zero が使えると考えて良い 24489 のではないだろうか。 24490 24491 2021-02-04 24492 24493 * global: read timeout は $?==142 とは限らない [#D1467] 24494 24495 read timeout は本当に常に 142 なのか。と思ったが現在の用例では 142 は 24496 conditional-sync によって固定で返されているので気にしなくて良い。因みに 24497 bash のソースコードを確認する限りは 142 は hardcoded ではない。 24498 24499 * edit (ble/builtin/read/.loop): うーん。予め 142 に対応する終了ステータス 24500 を調べておくか、或いは 128 以上を一括で timeout と解釈するか。マニュアル 24501 には "128 より大きな値になる" とだけ書かれている。マニュアルに従った判定 24502 にするのが良い気がする。 24503 24504 * util (ble/util/msleep/.use-read-timeout): これは現在は使っていない。何れ 24505 にしても Cygwin/MSYS の時にだけチェックする様にすれば、これらのシステムで 24506 は 142 固定と期待されるので大丈夫。 24507 24508 * util (bleopt): bleopt でパイプに繋いでいても _ble_term_sgr0 が出力されている場合がある [#D1466] 24509 追加で関連する関数に於いて --color オプションで着色を制御できるようにする。 24510 * "--color" options for bleopt, blehook, ble-color-setface 24511 24512 * 2021-02-01 highlight: highlight_timeout_sync=0 にしても遅い (reported by 3ximus) [#D1465] 24513 https://github.com/akinomyoga/ble.sh/issues/82#issuecomment-770390986 24514 24515 % OK. Sorry, I actually reproduce this level of delay at my side too, but I 24516 % haven't regarded it as *terrible*. That's probably because I know what 24517 % `ble.sh` is doing in the background. I felt that it's actually doing a good 24518 % job considering how strange things `ble.sh` is doing in the background. 24519 % 24520 % →と思ったが、bleopt highlight_timeout_sync=0 を実行していなかった。これを 24521 % 実行したら自分のところでは特に問題もなく動く様になった。当初は実装のバグか 24522 % とも思ったが、一部の host の上でだけ動作しないという事があるだろうか。 24523 % 24524 % Do you think it is related to `ffmpeg` running in the background? I see in 24525 % the `top` pane multiple instances of `ffmpeg` are running, but the load 24526 % average is smaller than 2, which means that those `ffmpeg` instances are 24527 % waiting for an interrupt in more than half of their running time. If those 24528 % `ffmpeg` are encoding some video clips, they may be waiting for disk I/O. 24529 % 24530 % →と思ったが disk I/O 待ちだと status D になる筈である。画面を見る限りはそ 24531 % うなっていない。更に -x11grab というオプションについて調べてみるとこれはス 24532 % クリーンキャプチャである。つまり、これらの ffmpeg は単にこの説明を作るため 24533 % に起動しているだけで、問題には関係してこない。 24534 24535 何れにしてもこれは background highlighting におけるユーザー入力による中断速 24536 度に関係している。でもどの部分が悪さをしているのか分からない。 24537 24538 1. 入力検出? 24539 2. 生存検出? 24540 3. 或いは kill & wait だろうか。 24541 24542 どうも background highlighting のユーザー入力によるキャンセルの応答が遅い様 24543 である。自分の手元では残念ながら再現しない。取り敢えず勘で可能性のある時間 24544 のかかりそうな箇所に関連した時間計測を依頼したがぴんと来ない。多分、別の所 24545 に原因があるのではないか。 24546 24547 2021-02-04 追加報告では遅い時もあるしそうでない時もあるそうだ。後、遅いとは 24548 言っている割にそれ程遅い訳でもない気がする。単に複数のパス名展開が試みられ 24549 るのでそれぞれについてタイムアウトが試みられて遅くなっているというだけなの 24550 ではないか。という訳で、取り敢えずの修正として一度 timeout を起こしたら後続 24551 の eval も即刻で timeout する様に修正した。 24552 24553 それから conditional-sync をチェックする頻度も変更する事にする。取り敢えず 24554 これで改善するかどうか判断する事にする。 24555 24556 | 後、timeout は total でカウントするべきなのかもしれない。或いは一つ 24557 | timeout したらそれ以降は timeout が必要になる物はもう処理しない様に変更す 24558 | る。 24559 24560 2021-02-05 新しい報告で上記の cumulative timeout & shorter polling interval 24561 で改善するという事が確かめられた。問題は現在の cumulative timeout によって 24562 本来短時間で着色できる単語が着色されずに残ってしまう可能性について。 24563 24564 然し、そもそも cumulative timeout で本当に改善しているのかというのは謎であ 24565 る。今 highlight_timeout_sync=0 にしている。とすると highlight_timeout_sync 24566 が効いていないか、或いは highlight_timeout_async の側での cumulative 24567 timeout が効いているか。highlight_timeout_async の側での timeout が効いてい 24568 るとすると何故なのか。ユーザー入力がある場合には何れにしても has-input の 24569 チェックによってキャンセルされるのではないか。うーん。手元で試してみたが余 24570 り違いが分からない。 24571 24572 * done: syntax_eval_polling_interval について doc を記述する 24573 24574 * 展開済みであっても展開される単語の数に比例して遅い (reported by 3ximus) [#D1464] 24575 https://github.com/akinomyoga/ble.sh/issues/82#issuecomment-772529714 24576 24577 * 以前大量の入力を与えた時に遅いという事を解決した時に似たような事があった 24578 気がする。パス名展開がなかったとしても大量の単語を含む配列をコピーすると 24579 遅いという話。 24580 24581 前に経験した時にはどの様な事が原因でどのように対策したのだったか。記録を 24582 漁ってみると #D1302 に関連しそうな内容が書かれている。 24583 24584 > chars=("${...[@]}" "$@") が 13 秒もかかっている。何故? 24585 24586 うーん。改めて試してみたがそんなに遅くない。関数経由で代入して改善したと 24587 いう事が書かれているが、実際に試してみても関数経由で代入すると却って遅く 24588 なる。またパス名展開の影響かとも思ったが set -f しても大して変化しない。 24589 結局再現はできない。 24590 24591 再現ができないので現在発生している問題が具体的にどういう物なのか調べる事 24592 もできない。取り敢えずまた計測をお願いするしかないのだという気がする。予 24593 想では cache が巨大である為に起こっている事ではないか。 24594 24595 * reject: そういう意味では既に議論した様に、単語ごとに展開済みの単純な情報 24596 を記録する事にして必要になった時は eval まで取りに行くのではなくて一部だ 24597 け記録する事にするという手もある。 24598 24599 →今は其処までしなくても良いという気がする。 24600 24601 取り敢えず simple-word/eval のキャッシュとして完全な情報を記録する物と、最 24602 初の単語だけ記録する物を用意して、highlighting の内部では主に最初の単語だけ 24603 を参照する様に変更した。 24604 24605 * syntax: tilde で始まる単語の着色がされない? (reported by 3ximus) [#D1463] 24606 https://github.com/akinomyoga/ble.sh/issues/82#issuecomment-772529714 24607 24608 と思ったがそうでもない。条件が不明 24609 24610 % notilde 関連かと思ったが違った。どうも evaluate-path-spec が after-sep の時 24611 % に変な振る舞いをしている。spec の抽出に失敗している。 24612 % 24613 % $ ble/syntax:bash/simple-word/evaluate-path-spec '~/work/idt/**/*.sh' after-sep 24614 % $ declare -p spec path 24615 % declare -a spec=([0]="~/wo" [1]="~/work/id" [2]="~/work/idt/**/*." [3]="~/work/idt/**/*.sh") 24616 % declare -a path=([0]="/home/murase/wo" [1]="/home/murase/work/id" [2]="" [3]="/home/murase/work/idt/agh/src/addon/make_latex_embedfont_css.sh") 24617 % 24618 % と思ったら単に evaluate-path-spec の使い方を間違っていただけだった。 24619 % 正しく sep を指定したら evaluate-path-spec の結果は期待した物になった。 24620 24621 改めて evaluate-path-spec の中で何が起こっているのか調べたら確かに失敗している。 24622 24623 wtxt='~/**/*.sh' path_opts='stopcheck:timeout-highlight:cached:after-sep' ext='1' 24624 spec=('~/' '~/**/' '~/**/*.sh') 24625 path=('/home/murase/' '' '') 24626 24627 どうも stopcheck の有無で結果が変わる様である。 24628 ble/syntax:bash/simple-word/eval '~/**/*.sh' stopcheck; ext=$?; ble/debug/print-variables ext ret 24629 24630 問題を狭めて行った所、原因が分かった。これは単純なミスである。 24631 command="print-result $word" とするべき所を 'print-result $word' にしていた。修正した。 24632 24633 2021-02-03 24634 24635 * edit: status line に対応しても良いのではないか [#D1462] 24636 24637 →改めて確認してみた所、prompt_status_line という設定が既に存在していた。 24638 24639 ? terminfo tsl/fsl に対応している TERMは存在するのか 24640 24641 これは terminfo の tsl fsl を使って何かを表示する物だが、実のところ 24642 tsl/fsl に対応している TERM はなかなかない。少なくとも screen, xterm は違 24643 う。 24644 24645 * tmux の term entry には tsl/fsl が存在しているが、シーケンスを見るとこ 24646 れは prompt_xterm_title と同じ OSC であって間違っている。terminfo の説 24647 明を読む限りに於いては、tsl/fsl は端末の特別な行で内部ではエスケープシー 24648 ケンスなども普通に使える物と見られる。という事を考えると、tmux の様に振 24649 る舞うのは間違っている気がする。 24650 24651 * cygwin も tmux と同様である。但し、OSC 0 ; ではなくて OSC ; になってい 24652 る。0 は省略可能という事なのだろう。 24653 24654 * kterm には \e[?E\e[?..T ... \e[?F という物が登録されている。 24655 * aixterm は \e[?..T ... \e[?F 24656 * aixterm は \e[?..T ... \e[?F 24657 24658 うーん。何れにしても最近の端末エミュレータに存在する様な物ではない気がする 24659 ので、取り敢えず prompt_status_line は ble.sh の新しい機能の為に使う事にし 24660 てしまって良い。 24661 24662 既存の tsl/fsl によるタイトルは別名の設定にする事にする。 24663 prompt_terminfo_status という名前にでもするか。terminfo だけでなく termcap 24664 にも存在するようだから、prompt_termcap_status の方が良いのかもしれない。或 24665 いは、prompt_term_status にするか。 24666 24667 * status line の区別がやはり付きにくい。背景色を設定できる様にしても良いのではないだろうか。 24668 元々 trace にその様な機能があった様な気がする。改めて確認する。なかったので新しく実装した。 24669 24670 * syntax: echo ${!_} と入力すると誤った代入ですというエラーメッセージが表示される [#D1461] 24671 そもそも "${!_}" を実行しようとするとエラーメッセージが出るが、 24672 これが着色等の際に発生するのは良くない。何処で発生しているのか確認する必要がある。 24673 24674 これは新しく追加した ble/syntax:bash/simple-word/is-simple-noglob の中で起 24675 こしている展開に対して2>/dev/null を付加すれば良かった。未だ master に push していない 24676 修正なので commit を fixup しようかと思ったが、実装ログが面倒な事になるので、 24677 下手に fixup するのは止める事にする。 24678 24679 * benchmark: EPOCHREALTIME は LC_NUMERIC 依存 (reported by 3ximus) [#D1460] 24680 24681 報告の画像で出ているエラーが何だろうと思って ble-measure の実装を 24682 見たが変な事はない。と思ったが此処で気づいた。EPOCHREALTIME の小数 24683 点は locale 依存である。という訳で対策する事にした。 24684 24685 * global: help の類の整理 [#D1459] 24686 * bleopt: --help に対応していない 24687 * blehook: --help が単純すぎる 24688 24689 * canvas: status line を最終行に表示する可能性 (suggested by 0neGuyDev) [#D1458] 24690 https://github.com/akinomyoga/ble.sh/issues/85 24691 24692 元々の提案は vim の mode 名という事だったが、vim の mode 名だけを最終行に表 24693 示するのか、或いは補完候補等の情報も全て最終行付近に表示するのかという可能 24694 性がある。Emacs 等を考えると補完候補も最終行に表示するのが自然な気がする。 24695 なので、実装としては info を丸ごと一番最後に表示する可能性について考えて良 24696 い気がする。 24697 24698 最終行に表示する為に必要な事。 24699 24700 a 一つの方法は \e7 \e8 で現在位置を記録するという事。これは visible-bell で 24701 既にやっている事。問題になるのは info の内容を構築する時に \e7 \e8 を使え 24702 ないという事。trace に明示的に禁止・代替するオプションを付ける必要がある 24703 かもしれない。 24704 24705 b もう一つの方法は DSR(6)/CPR で問い合わせるという方法。実はこの方法は未だ 24706 ble.sh には積極的に取り入れた事はない。とはいいつつも歴史的な端末でも軒並 24707 みこれに対応しているので、全ての端末で使えると思って良い。問題になるのは 24708 応答に時間がかかるので頻繁に問い合わせる訳には行かないという事。どのタイ 24709 ミングで問い合わせるのが良いのか非自明であるという点。 24710 24711 取り敢えず実装としては a の方針を試すのが自然な気がする。実は canvas の 24712 panel を調整するだけで、他の部分は触れずに実装できてしまうのではないだろう 24713 か。前にも似た様な事を考えた事があるような気がしないでもない。 24714 24715 自身の高さ変更だけでなく他の panel の高さ変更の時にも注意が必要。 24716 特に高さを増やす時。 24717 24718 * ok: bell を表示する為の行が canvas origin の一つ上に確保されている事に注 24719 意する。と思ったが、\e7\e8 で移動するのであれば実は余り関係ないという気が 24720 する。 24721 24722 ? reject: 間に適当な高さの空 panel を設置すれば良いのではないか、と思ったが 24723 間の高さが不明なので関係ない。 24724 24725 * vfill 以降の高さが 0 の時に変な事が起こらないか 24726 →これについてはちゃんと意識して実装する事にした。 24727 24728 うーん。取り敢えず実装した。canvas.sh に対する修正だけで大体動いているが細 24729 かい所で変な事が起こっている。 24730 24731 x fixed: C-l をしても画面の一番上に移動しなくなってしまう。何故だろうか。 24732 →これは clear-screen する時に下部に excursion している状態で行っていたので、 24733 その後 textarea を描画する時に _ble_term_rc で位置が復元されるのが原因だった。 24734 24735 x 空コマンドを実行した時に info が押し出されて消える。実装を見ると 24736 ble/widget/.insert-newline の *:keep-info:* が該当する部分だがちゃんと動 24737 きそうな気がする。と思ったら canvas.sh の panel#increase-total-height が 24738 未実装だったのを思い出した。 24739 24740 % と思ったがよく見たらちゃんと実装できている気がする。然し整理した。それで 24741 % も動かない。そもそも普通に C-q C-j で改行を入力した時も info が消えてしまっ 24742 % ている。うーん。increase-height に失敗している? 24743 24744 やっぱり実装できていなかった。端末の高さが十分に高い時は、全体の高さは増 24745 えない。うーん。制御機能を工夫してこれを何とかする方法は実際に存在するの 24746 だろうか。勿論 CPR や他の機能を使えば可能なのだろうと思うが基本的な移動と 24747 IND RI の組み合わせでできない物だろうか。 24748 24749 うーん。無理の気がする。CUU&CUD の累積でできるのではないかと考えたが、累 24750 積させる方法が存在しない。 24751 24752 24753 やはり DECSTBM 等に依存するしかないのだろうか。或いは CPR を利用する。も 24754 しくは、再描画する。再描画が現実的な気がする、と思ったがサイズが変化する 24755 可能性がある場合全般に問題が発生するので、やはり現実的ではないように思わ 24756 れる。うーん。CPR を毎回発行して現在位置を記録する様にした方が良いのだろ 24757 うか。 24758 24759 a reject: CPR の可能性について→余り現実的でない気がする 24760 24761 ble/term/enter の辺りで CPR を発行する様にする事を考えたが。或いは 24762 ble/textarea#invalidate を発行する度に実行した方が良いのではないか。うー 24763 ん。然し、描画しようとしている時に即座に返答が帰ってくる訳でもない。と 24764 いって CPR が帰って来るまでブロックするというのも変だし、続きを async 24765 に処理するとういのも変である。やはり CPR は飽くまで補助的に使うべきなの 24766 だという気がする。或いは、画面の大きさが変わる時に初めて CPR 要求を出す 24767 という考え方もある。然し、そうすると async に処理しなければならなくな 24768 る…或いはその場で入力を待っても良いのかもしれないが…やはり駄目。別の 24769 入力を先に受信したりすると変な事になる。 24770 24771 b done: 再描画の可能性について→呼び出し元で再描画が必要化判定するのは困難なの 24772 で event を発火するなどして対処する。 24773 24774 実の所、再描画の為の関数を用意する筈だったので丁度良いのではないか。うー 24775 ん。再描画というよりは invalidate して、後で再描画するという形にするの 24776 が良い。invalidate については…。全体を invalidate するというのも考えら 24777 れるが一部を invalidate するというのも考えられる。矩形で invalidate さ 24778 れた領域を記録できる様にするのが良い気がする。 24779 24780 →invalidate を呼び出してそれからそれを記録して、更に次の render の時に 24781 改めて反映させるというコードを ble-edit/info について新しく書いた。 24782 ble/textarea に関しては既に実装した関数を適当に呼び出すだけで良いという 24783 事にする。 24784 24785 c done: DECSTBM を使う可能性について。取り敢えず最近の端末はこれに対応している 24786 だろうと想像されるのでこれを使うというので良い気がする。ble.sh 起動時に 24787 DECSTBM に対応しているかどうかを検出する。 24788 24789 * done: DECSTBM の判定コード 24790 取り敢えず判定コードを書いた。 24791 24792 →と思ったら行が消滅してしまう。うーん。→ IND の代わりに CUD を使って 24793 DECSTBM をテストする事にした。動いている。OK 24794 24795 x fixed: cursor-position (DECSTBM が使えない場合) が info の中になってしまっている 24796 _ble_canvas_panel_focus という変数を用意した。 24797 然し、それでも振る舞いが変である。 24798 24799 x fixed: (DECSTBM が使えない場合) 一番最後の行での描画が重複している。 24800 24801 DECSTBM の有無で振る舞いが逆になってしまっている。これは明らかに 24802 set-height の振る舞いに (少なくとも片方は) 間違いがあるという事。 24803 24804 →これは単純にバグだった。 24805 24806 x fixed: DECSTBM を使っている時に一番最後から二行目が使われない。 24807 24808 DECSTBM を使わない場合にはちゃんと動いているのでここにも何が間違いがある。 24809 24810 * util (visible-bell) との干渉について 24811 24812 x fixed: 実は visible-bell の実装にバグがある。 24813 24814 RI を使って現在編集のコマンドと被らない様にしているが、実は現在行と被らな 24815 い様にしているだけであって、実際には編集文字列の2行目以降にいる時には 24816 visible-bell が上書きしてしまう。 24817 24818 x fixed: 先頭行の visible-bell で info が消滅する。 24819 24820 * resolved: _ble_term_{sc,rc} ... util.sh で使っている箇所がある 24821 24822 * ok: visible-bell の中の trace で sc rc を使えない様にするべきでは? と思っ 24823 たが、visible-bell は純粋な text という事になっているので今は関係ない。 24824 将来的には esc seq も指定できる様にする可能性もあるが今は考えない。 24825 24826 * resolved: ble/canvas 内で他にも _ble_term_{sc,rc} を使っている箇所がある。 24827 これは曖昧文字幅の問い合わせに使っていた。 24828 24829 * ok: _ble_term{sc,rc} は edit.sh でも使っている箇所がある。 24830 →adjust-eol で使っている。これは大丈夫の筈。 24831 24832 * ok: ble/canvas/panel#report-cursor-position 等については影響がないか確認 24833 が必要。ble/canvas/panel#get-origin についても。 24834 24835 get-origin に関しては core-complete.sh で menu の構築で使われている様だが、 24836 絶対位置として他の panel の座標系と混ぜて使っている訳ではないので問題ない。 24837 24838 report-cursor-position に関してはパネルの局所座標を引数に指定しているので 24839 呼び出し元は気にしなくて良い。特に問題も無い様に思われる。 24840 24841 * done: trace で SC/RC を emulate する (with opts=noscrc) 24842 24843 * done: bleopt で制御できる様にする 24844 24845 * blerc に bleopt info_display を追記する。 24846 24847 2021-02-01 24848 24849 * complete: support "bleopt complete_timeout_compvar" (motivated by 3ximus) [#D1457] 24850 https://github.com/akinomyoga/ble.sh/issues/82#issuecomment-770390986 24851 24852 これは progcomp の関数を呼び出す時にパス名展開を実行しているからである。 24853 一応、応答がなくなるという事はないが補完に不自然に時間がかかるのは避けたい。 24854 progcomp の為に展開する時は noglob で展開する事も考えたが、 24855 展開した文字列を quote しているので、noglob で呼び出すと例えば *.txt 24856 が '*.txt' 等になってしまって意図しない結果になってしまう。 24857 24858 どの様にするのが良いのかは不明である。或いは timeout したら '*.txt' にして 24859 しまうというのでも良いのかもしれない。 24860 24861 bleopt complete_timeout_progcomp_glob=200 等の設定にして、timeout したら 24862 noglob で呼び出すというので良い気がする。 24863 24864 retry-noglob-on-timeout という opts を追加する事にする。 24865 24866 新しい bleopt の変数名は何が良いだろうか。 24867 24868 complete_timeout_progcomp_glob だと長い。 24869 それに似たような変数が沢山あって気になる。 24870 そもそも単に timeout としていると何の timeout か分からない。 24871 24872 ちゃんとした名前にするなら glob_timeout が良いが長い。 24873 一単語でこれを表現できないか。fsys_timeout, path_timeout, ... 24874 やはり専用の単語は存在しない以上は一単語にするのは難しい。 24875 また、似たような設定をまとめるという立場からすると以下の様な 24876 変数名で良いのではないかという気もしないでもないが、微妙。 24877 24878 glob_timeout_progcomp 24879 glob_timeout_sync_highilght 24880 glob_timeout_async_highilght 24881 glob_timeout_auto_complete 24882 24883 やはり highlight_*, complete_* という名前にしたい。 24884 24885 highlight_timeout_sync 24886 highlight_timeout_async 24887 complete_timeout_auto 24888 complete_timeout_compvar 24889 24890 →これは実際に試してみたが改善していない。 24891 24892 * setup を動詞の様に使っている箇所が多くて気になるので修正する [#D1456] 24893 24894 set up に代わる動詞を探しても余り良いのが見つからない。文脈に応じて全く違う 24895 表現に改めた関数もある。set up だけの場合には関数名としてはくっつけて setup 24896 としても良い事にした。setup-xxx というのは気になるのでせめて set-up-xxx の 24897 様に変更した。 24898 24899 2021-01-30 24900 24901 * edit: emoji の表を更新する (reported by endorfina) [#D1455] 24902 https://github.com/akinomyoga/ble.sh/issues/84 24903 24904 更新しようと思ったが現在のコードを確認すると色々工夫して高速化している。 24905 少し面倒である。取り敢えずデータのダウンロードだけは行う事にする。 24906 24907 https://unicode.org/Public/emoji/ 24908 24909 色々考えて現在のコードの構造に近い形で再実装した。実は以前の実装に 24910 はバグがあった。 24911 24912 以前のテーブルは https://github.com/vim-jp/issues/issues/1086 から 24913 拾ってきた物だったが、これは 2017 年の物だったので報告のあった 24914 flamingo の絵文字 (2018) は含まれていなかったのだ。 24915 24916 * syntax: 構文解析で無限ループになっている [#D1454] 24917 24918 特定のコマンドの編集で固まってしまったので gdb でアタッチしてみたらstack が 24919 300 段ぐらいまで成長している。問題の起こるコマンドを探ってみると、[[ ]] が 24920 あるかどうかで振る舞いが変わる様だ。 24921 24922 [再現] 24923 24924 $ for f in *; do [[ ]]; done 24925 24926 に於いて、* の直前に "out/" を挿入しようとすると無限ループになる。 [[ ]] で 24927 はない別のコマンドの時には発生しない。 24928 24929 24930 [原因] 24931 24932 | 構文構造を確かめてみると確かに構造が破壊されている。正常な場合にはちゃんと 24933 | 単語の chain が繋がって木構造を形成している。しかし、問題が起こるコマンドの 24934 | 場合、[[ ]] の兄要素が記録されていない。唯、これだけで無限ループになるとい 24935 | うのも変である。無限ループになってしまう原因も探りたい気がする。 24936 | 24937 | 正常時 24938 | 24939 | | $ for f in *; do :; done 24940 | | _ble_syntax_attr/tree/nest/stat? 24941 | | 18*a 000 'f' | stat=(CMDX w=- n=- t=-:-) 24942 | | |*a 001 'o' | 24943 | | |*a 002 'r' + word=CMDI:0-3/(wattr=d) 24944 | | 16*a 003 ' ' stat=(FARGX1 w=- n=- t=$3:-) 24945 | | 7*a 004 'f' + word=ARGI:@2>4-5/(wattr=d) stat=(FARGX1 w=- n=- t=$3:-) 24946 | | 36*a 005 ' ' stat=(FARGX2 w=- n=- t=$5:-) 24947 | | 37*a 006 'i' | stat=(FARGX2 w=- n=- t=$5:-) 24948 | | |*a 007 'n' + word=FARGI2:@4>6-8/(wattr=d) 24949 | | 58*a 008 ' ' stat=(FARGX3 w=- n=- t=$8:-) 24950 | | 31*aw 009 '*' + word=ARGI:@7>9-10/(wattr=m1:72057594037934596) stat=(FARGX3 w=- n=- t=$8:-) 24951 | | 12*a 010 ';' stat=(FARGX3 w=- n=- t=$10:-) 24952 | | 68*a 011 ' ' stat=(CMDXD w=- n=- t=$10:-) 24953 | | 20*a 012 'd' | stat=(CMDXD w=- n=- t=$10:-) 24954 | | |*a 013 'o' + word=CMDI:@9>12-14/(wattr=d) 24955 | | 17*a 014 ' ' stat=(CMDX1 w=- n=- t=$14:-) 24956 | | 2*aw 015 ':' + word=CMDI:@13>15-16/(wattr=72057594037930241) stat=(CMDX1 w=- n=- t=$14:-) 24957 | | 12*a 016 ';' stat=(ARGX w=- n=- t=$16:-) 24958 | | 1*a 017 ' ' stat=(CMDX w=- n=- t=$16:-) 24959 | | 19*a 018 'd' | stat=(CMDX w=- n=- t=$16:-) 24960 | | |*a 019 'o' | 24961 | | |*a 020 'n' | 24962 | | |*a 021 'e' + word=CMDI:@15>18-22/(wattr=d) 24963 | | | s 022 ^@ stat=(CMDXE w=- n=- t=$22:-) 24964 | | \_ 'for' 24965 | | \_ 'f' 24966 | | \_ 'in' 24967 | | \_ '*' 24968 | | \_ 'do' 24969 | | \_ ':' 24970 | | \_ 'done' 24971 | 24972 | 異常時 24973 | 24974 | | $ for f in *; do [[ ]]; done 24975 | | _ble_syntax_attr/tree/nest/stat? 24976 | | 18 a 000 'f' | stat=(CMDX w=- n=- t=-:-) 24977 | | | a 001 'o' | 24978 | | | a 002 'r' + word=CMDI:0-3/(wattr=d) 24979 | | 16 a 003 ' ' stat=(FARGX1 w=- n=- t=$3:-) 24980 | | 7 a 004 'f' + word=ARGI:@2>4-5/(wattr=d) stat=(FARGX1 w=- n=- t=$3:-) 24981 | | 36 a 005 ' ' stat=(FARGX2 w=- n=- t=$5:-) 24982 | | 37 a 006 'i' | stat=(FARGX2 w=- n=- t=$5:-) 24983 | | | a 007 'n' + word=FARGI2:@4>6-8/(wattr=d) 24984 | | 58 a 008 ' ' stat=(FARGX3 w=- n=- t=$8:-) 24985 | | 31 aw 009 '*' + word=ARGI:@7>9-10/(wattr=m1:72057594037934596) stat=(FARGX3 w=- n=- t=$8:-) 24986 | | 12 a 010 ';' stat=(FARGX3 w=- n=- t=$10:-) 24987 | | 68 a 011 ' ' stat=(CMDXD w=- n=- t=$10:-) 24988 | | 20 a 012 'd' | stat=(CMDXD w=- n=- t=$10:-) 24989 | | | a 013 'o' + word=CMDI:@9>12-14/(wattr=d) 24990 | | 17 a 014 ' ' stat=(CMDX1 w=- n=- t=$14:-) 24991 | | 12 a 015 '[' || nest=(ARGX0 w=- n=- t=-:-) stat=(CMDX1 w=- n=- t=$14:-) 24992 | | | a 016 '[' |+ word=CMDI:15-17/(wattr=d) 24993 | | 32 a 017 ' ' | stat=(CONDX w=- n=@15 t=$17:-) 24994 | | 12 a 018 ']' || stat=(CONDX w=- n=@15 t=$17:-) 24995 | | | a 019 ']' ++ word="none":15-20>@19 word=CONDI:@16>18-20/(wattr=d) 24996 | | 12 a 020 ';' stat=(ARGX0 w=- n=- t=$20:-) 24997 | | 1 a 021 ' ' stat=(CMDX w=- n=- t=$20:-) 24998 | | 19 a 022 'd' | stat=(CMDX w=- n=- t=$20:-) 24999 | | | a 023 'o' | 25000 | | | a 024 'n' | 25001 | | | a 025 'e' + word=CMDI:@19>22-26/(wattr=d) 25002 | | | s 026 ^@ stat=(CMDXE w=- n=- t=$26:-) 25003 | | \_ '[[ ]]' 25004 | | | \_ '[[' 25005 | | | \_ ']]' 25006 | | \_ 'done' 25007 | 25008 | どうも auto-complete が有効になっていると発生する様だ。 25009 | 入力のタイミングにも依る。一旦構文解析が終了してから無限ループに入る。 25010 | 25011 | 無限ループに入る時の構造 25012 | 25013 | | $ for f in out/*; do [[ ]]; done 25014 | | _ble_syntax_attr/tree/nest/stat? 25015 | | 18 a 000 'f' | stat=(CMDX w=- n=- t=-:-) 25016 | | | a 001 'o' | 25017 | | | a 002 'r' + word=CMDI:0-3/(wattr=d) 25018 | | 16 a 003 ' ' stat=(FARGX1 w=- n=- t=$3:-) 25019 | | 26 a 004 'f' + word=ARGI:@2>4-5/(wattr=d) stat=(FARGX1 w=- n=- t=$3:-) 25020 | | 36 a 005 ' ' stat=(FARGX2 w=- n=- t=$5:-) 25021 | | 37 a 006 'i' | stat=(FARGX2 w=- n=- t=$5:-) 25022 | | | a 007 'n' + word=FARGI2:@4>6-8/(wattr=d) 25023 | | 58 a 008 ' ' stat=(FARGX3 w=- n=- t=$8:-) 25024 | | 59*a 009 'o' stat=(FARGX3 w=- n=- t=$8:-) 25025 | | |*a 010 'u' 25026 | | |*a 011 't' 25027 | | |*a 012 '/' | 25028 | | 31 a s 013 '*' + word=ARGI:@10>12-14 stat=(FARGI3 w=FARGX3:9- n=- t=-:$8) 25029 | | 12 a s 014 ';' stat=(FARGX3 w=- n=- t=$14:-) 25030 | | 68 a s 015 ' ' stat=(CMDXD w=- n=- t=$14:-) 25031 | | 20 a s 016 'd' | stat=(CMDXD w=- n=- t=$14:-) 25032 | | | a s 017 'o' + word=CMDI:@13>16-18/(wattr=d) 25033 | | 17 a s 018 ' ' stat=(CMDX1 w=- n=- t=$18:-) 25034 | | 12 a s 019 '[' || nest=(ARGX0 w=- n=- t=-:-) stat=(CMDX1 w=- n=- t=$18:-) 25035 | | | a s 020 '[' |+ word=CMDI:19-21/(wattr=d) 25036 | | 32 a s 021 ' ' | stat=(CONDX w=- n=@19 t=$21:-) 25037 | | 12 a s 022 ']' || stat=(CONDX w=- n=@19 t=$21:-) 25038 | | | a s 023 ']' ++ word="none":19-24>@23 word=CONDI:@20>22-24/(wattr=d) 25039 | | 12 a s 024 ';' stat=(ARGX0 w=- n=- t=$24:-) 25040 | | 1 a s 025 ' ' stat=(CMDX w=- n=- t=$24:-) 25041 | | 19 a s 026 'd' | stat=(CMDX w=- n=- t=$24:-) 25042 | | | a s 027 'o' | 25043 | | | a s 028 'n' | 25044 | | | a s 029 'e' + word=CMDI:@23>26-30/(wattr=d) 25045 | | | s 030 ^@ stat=(CMDXE w=- n=- t=$30:-) 25046 | | \_ '[[ ]]' 25047 | | | \_ '[[' 25048 | | | \_ ']]' 25049 | | \_ 'done' 25050 | 25051 | うーん。変だ。やはり構文解析で起こっている無限ループではない様だ。とすると 25052 | 何が別の箇所で無限ループになっている。特に auto-complete で起こっているとい 25053 | う事、応答もしなくなる (SIGINT にも反応しない) という事から、 25054 | eval-pathname-expansion が怪しいのではないか。 25055 | 25056 | やはり /dev/zero で問題が発生しているという事なのだろうか…と思ったが、 25057 | msleep を read -t を使わない手法に置き換えても同様に無限ループになる事から 25058 | read -t ... /dev/zero の問題ではない。(それに [[ ]] によって構文構造がおか 25059 | しくなっている時にのみ発生するという事だから、やはり構文構造に関係のある問 25060 | 題なのだろう)。 25061 | 25062 | * 一つ怪しい箇所は extract-command である。core-complete.sh 関連でコマンド 25063 | ライン内部の文法構造に関連する所と言えばこれしかない気がする。→実際に確 25064 | かめてみたが無限ループは extract-command とは関係ない所で起こっている様だ。 25065 | 25066 | * パス名展開の中で起こっているとも考えにくい。何故ならばファイルの少ない場 25067 | 所でも問題が発生しているから。それに関数呼び出しが何十段にもなる事から、 25068 | 関数呼び出し自体で問題が発生しているというのは明らかである。 25069 | 25070 | 呼び出されている関数名を調べる事ができれば簡単なのだが難しい。 25071 | 25072 | * そもそも本当に auto-complete.idle の中で発生しているのだろうか。と思って 25073 | 確かめたらどうやら違う様だ。だとすると、bgworker による textarea#render 25074 | が怪しい? 25075 | 25076 | 調べてみたらそうだった。更に textarea#render の中で怪しい所に絞り込みをか 25077 | ける。どうやら update-text-buffer の中で問題が発生している。update-syntax 25078 | の問題ではないようだ。update-text-buffer の中では layer/update を呼び出し 25079 | ているので、恐らく layer:syntax/update が変な事になっているのだろう。 25080 | 25081 | やはり ble/highlight/layer:syntax/update-word-table の中で無限ループになっ 25082 | ている様だ。 25083 | 25084 | ble/syntax/tree-enumerate-in-range で無限に要素が列挙されているか、或いは 25085 | ble/highlight/layer:syntax/word/.update-attributes/.proc の中で無限ループ 25086 | になっているかである。後者だった。 25087 | 25088 | ble/syntax:bash/extract-command-by-noderef が怪しい。実際に中を調べるとど 25089 | うやら ble/syntax/tree#previous-sibling が無限に兄要素を生成している様だっ 25090 | た。何故その様な事になるのか。 25091 | 25092 | OK. 原因が分かった。 25093 | 1. 木構造が壊れている 25094 | 2. 単語情報のシフトに失敗する 25095 | 3. 兄要素の位置がずれて何も単語が登録されていない位置を参照している 25096 | 4. 空の単語情報なので兄の相対位置が '' = 0 に評価されて自己参照している。 25097 | という具合にして空単語でループが出来上がっている。実際に問題が起こっている 25098 | 時の木構造を見るとその様になっている。 25099 25100 まとめると二つの問題がある。 25101 25102 * [[ ]] の解析で構文木の兄情報が欠けてしまっている。nest-push する時に何故 25103 か tprev が記録されていないのが原因であろう。 25104 25105 * 木構造が壊れている時に ble/syntax:bash/extract-command-by-noderef の中で 25106 兄ノードを探索する時に、一旦、空の単語情報に行き当たると自己参照して無限 25107 に兄ノードを取得してしまうという問題がある。 25108 25109 [修正] 25110 25111 後者に関しては、単語がちゃんと登録されているかどうか確認する様に実装を変更 25112 した。構文木の欠陥があった場合にそれを出力する様にした。これで構文木が壊れ 25113 ていても無限ループにはならない。 25114 25115 前者に関しては何処で問題が生じているか分かった気がする。word-cancel した時 25116 に tprev の情報を復元しきれていないという事。然し、不思議なのは word-cancel 25117 は単語が設置された後に呼び出されるのだから tprev は既にその新しい値になって 25118 いる筈だという事。なので、改めて tprev を計算する必要はない筈なのである。 25119 25120 うーん。もしかして二回連続で word-pop が起こった為に情報が消滅しているとい 25121 う事だろうか…。つまり nest-pop も既に終わっている状態という可能性? 25122 25123 →恐らく2回連続で word-pop をした時に、外側の word から順に pop しているの 25124 がいけないのではないか。内側の word から順に pop するべきという事の気がする。 25125 いや、それも変だ外側の word を pop する時に内側の単語も全部削除するべきなの 25126 ではないか。うーん…? 或いは単語を設置する直前の状態に復元するというのが正 25127 しい振る舞いだろうか。 25128 25129 改めて振る舞いについて何が起こっているのか考える事にする。 25130 25131 A B [ [ X Y ] ] という状態になっている。但し [...] が単語の範囲である。そも 25132 そもどう言った情報が記録されているかというと。 25133 25134 * 外側の単語については、tchild=(Yの位置), tprev=(Bの位置) になっている。 25135 * 内側の単語については、tchild=- tprev=- になっている。 25136 * 二つの単語を設置し終わった時の解析状態は、tchild=(Yの位置) tprev=- である。 25137 * 一つ単語終端を削除した時の解析状態は tchild=(Yの位置) tprev=(Bの位置) であるべき。 25138 * 更にもう一つ単語終端を削除した時の解析状態は tchild=- tprev=- になる。 25139 → word-cancel を2回施した時はこの状態を復元しているという事。 25140 25141 実際の振る舞いを見ると tprev が初めから空になっている。これは nest-push を 25142 実行した為の気がする。nest-pop もちゃんと実行しておくべきの気がする? うーん。 25143 確認してみると別に nest-push した事によって tprev になっている訳ではない気 25144 がする。どういう事だろうか。そもそも inest=-1 になっている。変だ。 25145 25146 ※現在の解析状態は "もしここで単語を閉じたらその単語にどの様な tchild, 25147 tprev が割り当てられるか" を表している。つまり、現在の文脈における 25148 tchild/tprev ではなくて、一つ上に上がった時の tchild/tprev である事に注意す 25149 る。 25150 25151 よく分からなくなった。取り敢えず現在の実装を理解することは諦めて、改めてど 25152 の様に実装するべきかについて考えてみることにする。word-cancel は二種類の考 25153 え方がある。それぞれについて適切な実装は何だろうか。 25154 25155 a 閉じてしまった単語を閉じる前の状態にする。 25156 25157 この場合には実は単純に word に格納されている tclen tplen をそれぞれ 25158 tchild tprev に変換すれば良い。 25159 25160 b そもそも単語がそもそも始まるよりも前の状態に戻す。 25161 25162 この場合には tchild は記録されている単語の tprev で、tprev については変化 25163 はない。という事を考えると…。実は現在の実装はこちらを狙った物であると考 25164 える事ができる。 25165 25166 この場合には word-cancel は実は一回だけしか呼び出さなくて良い。そして、一 25167 番外側の単語を削除すると同時に中に設置されている単語も全て削除するべきで 25168 ある。中に設置されている単語を削除するにはどうすれば良いか。tchild を辿っ 25169 て削除していく必要がある。面倒な事である。というか、tprev に至る迄を全削 25170 除で良いのではないだろうか。 25171 25172 2021-01-28 25173 25174 * syntax/simple-word/eval: キャッシュ機能を付ける [#D1453] 25175 25176 特に一回の着色 (layer:syntax/update) の中では同じ評価は一回しかしない様に工 25177 夫したい。キャッシュは dict に保存したいが二種類の問題がある。 25178 25179 1. eval の展開結果は配列なのでそれをどうにか再評価可能な形式に変換する必要 25180 がある。bash-4.4 以降であれば ${ret[@]@Q} を用いれば良い。古い bash では 25181 この形式に合わせて記録を行う。 25182 25183 2. bash3 では dict がないので工夫が必要 25184 25185 取り敢えずこれは必要である。 25186 25187 | うーん。それどころか一つのキーストロークの中でずっとキャッシュしても良いの 25188 | ではないか。tail 辺りで clear すれば良い。と思ったが余り変な事をしても駄目 25189 | な気もする。これだと bind 以外の枠組みで syntax/simple-word/eval を呼び出し 25190 | た時にキャッシュが全くクリアされなくて問題に成るのではないか。 25191 | 25192 | 例えば ble/builtin/read を使った時にキャッシュクリアが全くされないという事 25193 | になってしまう。但し、現在は read に対しては構文着色も auto-complete も有効 25194 | にしていないが。うーん。或いは widget を呼び出すタイミングでキャッシュをク 25195 | リアするという手もあるかもしれない…が、やはり ble/textarea#render と同じタ 25196 | イミングでクリアするのが自然な気がする。うーん。 25197 | 25198 | ble/textarea#render の中で clear してしまう? と思ったが、それはそれでやはり 25199 | 問題になる。将来的に textarea ではない物に対するキーボード操作も考えたいと 25200 | いう事を思うと、textarea#render の中からキャッシュをクリアするというのはや 25201 | はり変だ。 25202 | 25203 | そもそも汎用性を考えるのだとしたら cache は opts に指定した時にだけ使うとい 25204 | うので良い気がする。キャッシュをクリアする関数も別に公開しておいて、cache 25205 | を使う場合には自分でキャッシュの管理をせよという事にすれば良いのである。 25206 25207 25208 * done: dict を整備する。 25209 * done: キャッシュする様にする 25210 * done: キャッシュクリア用の関数を公開する 25211 25212 * 2021-01-26 util: Cygwin 上で ble/util/msleep がフリーズしてしまう [#D1452] 25213 25214 | 何故だろうか。普通にユーザコマンドとして実行した場合には特に問題は発生して 25215 | いない。サブシェルで実行しても問題は発生していない。内部 stty でサブシェル 25216 | で実行すると問題が起こる? 25217 | 25218 | →どうも繰り返し実行すると発生する様である。 25219 | 25220 | 以下を実行するとかなりの確率で固まる。 25221 | ( echo {1..1000} & builtin read -t 0.000100 v < /dev/udp/0.0.0.0/80 ) >/dev/null 25222 25223 以下によって通常の bash でも固まるという事が分かった。Cygwin 特有の振る舞い 25224 である。Linux 上で試した限りでは問題は起こらない。 25225 25226 ( echo {0..1000} >/dev/null & builtin read -t 0.001 v < /dev/udp/127.0.0.1/80 ) 25227 25228 他の実装だと exec 9<(sleep) を起動して置くという物や、builtin sleep を使う 25229 という物がある。 25230 25231 a builtin sleep 25232 25233 builtin sleep はコンパイラが利用可能なときにしか使えないのでこれに依存し 25234 たくない。飽くまで exec 9<(sleep) を使って実装して可能であれば builtin 25235 sleep を使うという様にする形になる。 25236 25237 b 現在の /dev/udp/0.0.0.0/80 を弄って解決できないか 25238 25239 うーん。不思議だ。'echo {1..1000}' を a.sh に書き出して置いて以下の様にす 25240 ると再現しない。 25241 25242 ( . a.sh >/dev/null & builtin read -t 0.001 v < /dev/udp/127.0.0.1/80 ) 25243 25244 関数を function a { echo {1..1000}; } として a>/dev/null とした場合は再現する。 25245 25246 * builtin read は read に置き換えても発生する。 25247 * 0.0.0.0 を 0.0.0.1 にすると通信エラーになって別の意味で使えない。 25248 * 127.0.0.1/80 でも再現する。 25249 * >/dev/null を >a.txt にしても再現する。 25250 * read を試みる前に様々なリダイレクトをしてみても状況は変わらない。 25251 * {0..1000} の部分や 0.001 の部分を変えると発生確率が下がる。 25252 25253 うーん。微妙。というか環境が Cygwin だけというのであれば、最初からバイナ 25254 リを用意しておくという手もある。 25255 25256 うーん。やはり Cygwin ではもっと別の実装を考えた方が良いだろうか。 25257 25258 c exec 9< <(sleep) 25259 25260 改めて exec 9< <(sleep) を試してみた所、遅延は殆どない様なので、これを採 25261 用する事にする。 25262 25263 思えば今までにも時々あった Cygwin で固まってしまう問題はこれが原因だったの 25264 かもしれない。直前に fork してから is-stdin-ready を確認する機会が余りなかっ 25265 たり、或いはその他の条件で発生しにくかったりして再現しにくかったという事の 25266 気がする。という事を考えるとやはり /dev/udp/0.0.0.0/80 は今後は使わない方が 25267 良い気がする。 25268 25269 →c の方法を使う事にした。古いコミットを参考にしてコードを復元する。 25270 8bb54be acb7163 d14557c f53c26d 25271 25272 また udp によるコードを使いたくなるかもしれないので、取り敢えず今の所は 25273 bleopt internal_msleep_socket というオプションで udp 方式に切り替えられる様 25274 にしてコードを残しておく事にする。 25275 25276 ---------------------------------------- 25277 25278 procsubst による実装に切り替えてもやはり同様の問題が発生する様だ…。 25279 うーん。どうした物だろうか。というかこれは bug-bash に報告しても良いのではないか。 25280 然し、normal Bash で再現させようとしても再現しない。然し症状としては同じなので、 25281 Cygwin における read のタイムアウトに問題があるという事は確かなのだろう。 25282 25283 うーん。やはり Cygwin 用に特別にコンパイル済み sleep builtin を提供する? 25284 25285 今試したら fifo が Cygwin 上でも動く様になっている。最近動く様になったのだ 25286 ろうか。或いは cygwin バージョンの問題だろうか。うーん。取り敢えず試しに動 25287 かしてみて、それで失敗したら procsubst に切り替えるという作戦にする。 25288 25289 →駄目。やはり同じ問題が発生する。FIFO でも駄目という事。 25290 read -t を使うのが本質的に駄目という事なのだろう。 25291 唯、確率は格段に小さくなっている。 25292 25293 sleep 10 | { echo {1..1000} >/dev/null & read -t 0.001 v; echo end; } 25294 25295 この様にしている時には特に問題も発生しない様だ。 25296 25297 builtin read -t "$v" v < "$$.pipe" 25298 25299 この実装にしても固まる時には固まる。 25300 25301 % 何と、builtin sleep を使っても同様に固まるという事が判明した。 25302 % つまり、read -t の問題ではない。Cygwin 自体に問題があるという事? 25303 % スレッドが停止するともう二度と動かないという種類の何か…。 25304 % →と思ったら勘違いだった。builtin sleep を使っているつもりが、 25305 % 別の方式をつかっていたのだった。 25306 25307 一応 /dev/zero は期待通りに動く。但し、CPU 100% になるという事には注意する。 25308 短時間の sleep であれば /dev/zero に頼っても良いかもしれない。と考えたが、 25309 短時間の sleep を繰り返し使う場合などを考えるとやはり cpu100% になるのは好 25310 ましくない気もする。 25311 25312 /dev/ptmx を試してみた。これはちゃんとブロックするし、勝手に停止してしまう 25313 事もないが代わりの問題として bash が終了しなくなってしまうという物がある。 25314 然し、通常の bash で同様の事をしても特に問題は発生しない様だ。何故だろうか。 25315 というか exec 9<&- を実行しようとしただけで固まってしまう。これは問題である。 25316 25317 ble/util/msleep/.use-read-timeout socket check 25318 ble/util/msleep/.use-read-timeout fifo.exec2 check || 25319 ble/util/msleep/.use-read-timeout procsub 25320 ble/util/msleep/.use-read-timeout fifo.open1 25321 ble/util/msleep/.use-read-timeout zero.open1 25322 ble/util/msleep/.use-read-timeout zero.exec1 25323 25324 -------------------------------------------------------------------------- 25325 25326 結局 loadable builtin を使う事にしようと思って実装したが…。loadable 25327 builtin のライセンスはどうなっているのだったか。普通に考えるとこれは GPLv2 25328 に感染する気がする。という事は loadable builtin のソースコードをつけて配布 25329 するのは難しいという事になる。うーん。loadable builtin ならば OK という訳 25330 は…ないだろう。GPLv2 的に。調べたら正にそういう項目について記述されていた。 25331 25332 https://www.gnu.org/licenses/gpl-faq.ja.html#GPLAndPlugins 25333 25334 従って loadable builtins を使う方針は採用できない。結局、他の手法について考 25335 える必要があるのである。或いは確率が小さければ cygwin でも read -t を使って 25336 大丈夫だろうか、と思ったが conditional-sync を使っている限り、従来よりも格 25337 段に問題が起こる確率が高い。やはり read -t は諦めるべきだろうか。 25338 25339 或いは conditional-sync の時だけ別の方法を用いるという可能性もある…。が、 25340 別の方法に心当たりがある訳ではない。どうしようもない。バイナリを添付する訳 25341 にも行かない。 25342 25343 -------------------------------------------------------------------------- 25344 25345 取り敢えず /dev/zero では未だ hang が起きた事はないので、これで様子見する事にする。 25346 25347 * util,syntax,complete: 配列内容の記録時に @Q を使った print に切り替える [#D1451] 25348 大した高速化ではないと思うがコードの整理も兼ねて。 25349 25350 * syntax: auto-complete 内部の pathname-expansion についても conditional-sync を使う (motivated by 3ximus) [#D1450] 25351 https://github.com/akinomyoga/ble.sh/issues/82 (for auto-complete) 25352 25353 取り敢えず [[ :$comp_type: != *:sync:* ]] の時には stop_check で実行して、 25354 それ以外の場合には強制的に実行するという方針で行く。 25355 25356 ble/complete/util/eval-pathname-expansion に関してはそんなに面倒そうではない。 25357 ble/complete/util/eval-pathname-expansion は常にグロブパターンを伴って呼び出されるので場合分けは必要ない。 25358 常に conditional-sync を使えば良いのではないかという気がする。 25359 うーん。 *:sync:* が含まれる時だけはそのまま展開を実行する。 25360 →eval-pathname-expansion については対応した。恐らくこれで良いだろう。 25361 25362 次に complete の内部から沢山の simple-word/eval を利用している。 25363 これらについても一つずつ確認して行く必要がある。 25364 25365 以下の四つの関数が core-syntax.sh における stop_check を指定して実行するべき関数である。 25366 実際に使われているのは前者2つだけの様である。 25367 25368 - ble/syntax:bash/simple-word/eval 25369 - ble/syntax:bash/simple-word/evaluate-path-spec 25370 - ble/syntax:bash/simple-word/detect-separated-path 25371 - ble/syntax:bash/simple-word/locate-filename 25372 25373 | $ grc 'simple-word/(eval|locate|detect)' lib/core-complete.sh 25374 | f lib/core-complete.sh:1970: ble/syntax:bash/simple-word/eval "$subword" "$eval_opts" 25375 | f lib/core-complete.sh:1980: ble/syntax:bash/simple-word/eval "$subword" noglob 25376 | lib/core-complete.sh:2006: ble/syntax:bash/simple-word/eval "$ret"; local value1=$ret 25377 | lib/core-complete.sh:2011: ble/syntax:bash/simple-word/eval "$ret" 25378 | lib/core-complete.sh:2072: ble/syntax:bash/simple-word/eval "$ret"; word=$ret 25379 | lib/core-complete.sh:2093: ble/syntax:bash/simple-word/eval "$ret"; left=$ret 25380 | lib/core-complete.sh:2806: ble/syntax:bash/simple-word/eval "$word" && 25381 | lib/core-complete.sh:2861: ble/syntax:bash/simple-word/eval "$ret*" && ((${#ret[*]})) && 25382 | lib/core-complete.sh:3048: local ret; ble/syntax:bash/simple-word/eval "$pattern" 25383 | lib/core-complete.sh:3050: ble/syntax:bash/simple-word/eval "$pattern*" 25384 | lib/core-complete.sh:3223: elif ble/syntax:bash/simple-word/eval "$reconstructed"; then 25385 | lib/core-complete.sh:3229: ble/syntax:bash/simple-word/eval "${reconstructed::${simple_ibrace#*:}}" 25386 | lib/core-complete.sh:3234: # Note: failglob により simple-word/eval が失敗した時にここに来る。 25387 | lib/core-complete.sh:3624: ble/syntax:bash/simple-word/evaluate-path-spec "$word0"; spec0=("${spec[@]}") path0=("${path[@]}") 25388 | lib/core-complete.sh:3625: ble/syntax:bash/simple-word/evaluate-path-spec "$word1"; spec1=("${spec[@]}") path1=("${path[@]}") 25389 | lib/core-complete.sh:3705: if ble/syntax:bash/simple-word/eval "$common_reconstructed" && 25390 | lib/core-complete.sh:3731: ble/syntax:bash/simple-word/eval "$notilde$ret" noglob && 25391 | lib/core-complete.sh:3733: ble/syntax:bash/simple-word/eval "$notilde$common_reconstructed" noglob && 25392 | lib/core-complete.sh:3761: ble/syntax:bash/simple-word/eval "$ret" && 25393 | lib/core-complete.sh:4206: ble/syntax:bash/simple-word/eval "$ret" 25394 | lib/core-complete.sh:4706: ble/syntax:bash/simple-word/eval "$ret" 25395 | lib/core-complete.sh:4930: ble/syntax:bash/simple-word/eval "$ret" 25396 | lib/core-complete.sh:5573: if ble/syntax:bash/simple-word/eval "$ret" && local compv_new=$ret; then 25397 | lib/core-complete.sh:5968: ble/syntax:bash/simple-word/eval "$ret" || continue 25398 25399 - ble/complete/progcomp/.compvar-generate-subwords/impl2 25400 この関数は eval を呼び出している。複数の単語に展開される時にそれを全て取得している。 25401 25402 - ble/complete/source:argument/.contains-literal-option 25403 この関数は noglob を指定して変換を試すべきの気がするのでその様に変更する。 25404 25405 - ble/complete/progcomp/.compvar-quote-subword 25406 25407 - ble/complete/source:argument 25408 failglob で展開に失敗した時に * を付加して再度挑戦するのに使っている。 25409 - ble/complete/source:glob 25410 - ble/complete/candidates/.pick-nearest-sources 25411 - ble/complete/candidates/determine-common-prefix 25412 - ble/complete/candidates/determine-common-prefix/.apply-partial-comps 25413 ここでは evaluate-path-spec を使っている。 25414 - ble/complete/insert-common 25415 25416 以上は候補生成時に使われる関数群である。 25417 全てユーザー入力があったらキャンセルという形で良い気がする。 25418 元々 148 を返す仕様の関数になっているので 148 の伝播についても面倒な対応は不要。 25419 25420 - ble/complete/menu-filter 25421 これは .filter-candidates の戻り値を返すのを忘れている気がする。 25422 →修正した。 25423 25424 - ble/widget/auto_complete/self-insert 25425 これは微妙。どの様にすればよいだろうか。 25426 timeout はまあいらない気がする。 25427 ユーザー入力によって interrupt されたらそのまま false を返せば、 25428 auto_complete モードから抜けるという動作になる。これで良い。 25429 25430 - ble/complete/source:sabbrev 25431 % 展開した結果が使用されていない。バグが有る気がする。 25432 % →と思ったが iniitialize の中で参照されていた。 25433 25434 [修正] 25435 25436 * done: 毎回 timeout 等を設定するのは大変なので関数を用意する。 25437 * done: simple-word/{eval,evaluate-path-spec} の呼び出しを置き換える。 25438 25439 x timeout した時に 142 を返すのを 148 に置き換えているが、 25440 これだと auto-complete 内部で timeout した時に、 25441 後続の idle まで中断してしまうのではないだろうか。 25442 25443 →これは idle.do の側で修正する事にした。そもそも IS_IDLE で条件を差し替 25444 える事ができるようにしているので、呼び出した task の終了ステータスを信用 25445 する訳には行かない筈なのだ。 25446 25447 此処で気になるのは complete における 148 の意味が必ずしもユーザ入力ではな 25448 くて、auto-complete における timeout の場合もあるという事になってしまった 25449 事だが、これが重大な結果を生み出す様には思われないので、取り敢えずはこれ 25450 で良いとする。 25451 25452 * highlight: グロブパターンが含まれるファイル名の着色が遅い (reported by 3ximus) [#D1449] 25453 https://github.com/akinomyoga/ble.sh/issues/82 (for highlighting) 25454 25455 glob expansion を subshell で実行してユーザー入力があったら timeout させる 25456 方針について考察。timeout は必要だろうか。 25457 25458 * 或いは、もういきなり中断しても良いかもしれない。着色は次の rendering の時 25459 に反映させれば良いという発想。然し、その場合には再 rendering を発生させる 25460 為にどうにかして部分 invalidate しなければならない。或いは再描画の条件に 25461 着色未完の状態を含めても良いのかもしれない。着色の更新に関しては 25462 ble/textarea#update-text-buffer を呼び出した時に実行される。実は dirty 25463 range の有無に関わらず毎回 layer/update は呼び出される様だ。考えてみれば 25464 region の着色等は dirty range に関係なく変化する可能性があるので、この振 25465 る舞いも妥当である。 25466 25467 一般に単語着色に関してはユーザーの入力があったら中断してしまって良いので 25468 はないだろうか。background worker の方で処理する事にすれば良い (但し、 25469 bash3 だと判定できないので難しい。bash3 に関しては loadable builtin が使 25470 えれば自前でそれを使ってしまうという手もある)。 25471 25472 * キャッシュする可能性。同じ単語が繰り返し使われている場合に処理を短縮する 25473 為。これは特殊な場合にしか効果が現れない。余り効果はないのではないかとい 25474 う気がする。 25475 25476 * globpat が含まれる場合にだけ subshell 実行する? 25477 globpat があるかどうかに関しては正規表現で判定すれば良い。 25478 25479 "**" が含まれる場合にだけ subshell 実行するという可能性も考えたが、"*" や 25480 "?" だけでも大量のファイル名に展開される可能性もあるので、"*" だけ特別扱 25481 いしても仕方がない。 25482 25483 * reject: ファイル数が多いディレクトリだけで subshell 実行する? 25484 25485 ディレクトリ移動はそんなに頻繁に行わない筈なのでファイル数をディレクトリ 25486 移動をする度に確認すれば良いのではないか。と思ったが引数に 25487 dir1/dir2/... と指定する事もできるのでファイル数が多いディレクトリに現在 25488 いるかどうかという情報は余り当てにならない。 25489 25490 "/" が含まれるかどうかを事前に判定する可能性もあるが、変数展開の中に / が 25491 含まれる可能性もあるので、完全に判定するのは難しい。 25492 25493 * そもそも単語が単純な場合には展開の操作すら必要ないのではないか。 25494 25495 {} も quote も history expan も param も ~ もない場合。 25496 25497 [実装] 25498 25499 * done: 取り敢えずユーザーからの入力がある場合には着色を中断する。サブシェ 25500 ルの中で実行する。後で着色し直す可能性については取り敢えず考えない。 25501 25502 取り敢えず実装してみたが、微妙。とにかく入力を続ければ応答が全くないとい 25503 う訳ではないが、常に位置文字分だけ遅延している。何故だろうか。一文字だけ 25504 次の文字が来ている場合に次の文字が来ているという事を検出できていないとい 25505 う事だろうか。うーん。ble/decode/has-input の問題であろう。 25506 25507 * done: simple-word/eval-noglob を eval ... noglob に書き換える 25508 25509 * done: 以下の関数の呼び出し元で適切に stop_check を設定する様にする? 25510 25511 ble/syntax:bash/simple-word/detect-separated-path 25512 ble/syntax:bash/simple-word/evaluate-path-spec 25513 ble/syntax:bash/simple-word/locate-filename 25514 25515 特に bash3 で stop_check を行うかどうか。bash3 で stop_check をしたとして 25516 も常に is-stdin-ready は false になるので、唯単に今まで通りにブロックされ 25517 るだけである。然し、そうであるならば最初から subshell を生成する必要もな 25518 い。やはり bash3 では stop_check を省略する様に工夫する必要があるのではな 25519 いか。と思ったが、それならば simple-word/eval の側で bash3 では 25520 stop_check しないという様にしても良い気がする。 25521 →その様にする事にした。 25522 25523 結局上記の3関数では常に stop_check を指定して、 25524 bash3 についての特別な取り扱いは simple-word/eval の側で実装した。 25525 25526 * done: 以下の関数について 148 を返した時の振る舞いを正しく実装する。 25527 25528 148 を返した時に現在はエラー着色にしているが、 25529 そうではなくて着色せずに抜ける事にする。 25530 25531 ble/syntax:bash/simple-word/evaluate-path-spec [done] 25532 ble/syntax/progcolor/word:default/.highlight-filename [done] 25533 ble/syntax/progcolor/word:default [ok] 25534 ble/syntax:bash/simple-word/locate-filename/.exists [done] 25535 ble/syntax:bash/simple-word/locate-filename [done] 25536 ble/syntax/progcolor/word:default [ok] 25537 ble/syntax:bash/simple-word/detect-separated-path [done] 25538 ble/syntax/progcolor/word:default/.detect-separated-path [done] 25539 ble/syntax/progcolor/word:default [ok] 25540 25541 取り敢えず ble/syntax/progcolor/word:default まで行って抜ければ、 25542 単語情報として何か間違った物が登録される事はない。 25543 25544 x ok: ble/decode/has-input で次の文字が来ている判定しているが、一文字分だけずれ 25545 がある様に見える。何が起こっているのか調べる必要がある。 25546 25547 調べてみると既に次の文字は受信している様である。 25548 問題は未だ処理しきっていないのに描画が実施されているという事である。 25549 コールスタックを見るとちゃんと EPILOGUE から呼び出されている。 25550 つまり、ちゃんと文字を処理してからという事になっている筈である。 25551 25552 と此処で理由が分かった。入力した文字を表示する為に配色を計算しているのだから、 25553 配色を計算している間は未だ文字が描画されないというのは道理である。 25554 やはり timeout を入れないと変である。 25555 25556 conditional-sync に timeout 機能も付ける事にする。 25557 25558 * done: 着色せずに抜けた場合にはその事を記録に残す (progcolor_dirty)。 25559 これは ble/syntax/progcolor/word:default に対して実行すれば良い。 25560 或いは idle に bgworker を登録するだけでも良い? 25561 と思ったが、それだと沢山の bgworker が生成されてしまう気がする。 25562 idle に bgworker を登録するとしても、 25563 未着色単語がある事の情報は何処かに記録する必要がある。 25564 25565 実は未着色範囲を管理した方が自然な実装になる気もする。 25566 例えば _ble_syntax_word_async_u{min,max} 等の変数に記録する。 25567 bgworker ではこれを _ble_syntax_word_u{min,max} に反映させて 25568 その上で着色を実行する…と思ったが shift 等の取り扱いがどうなるのか分からない。 25569 _ble_syntax_word_u{min,max} の場合にはどの様にしていただろうか。 25570 というより、_ble_syntax_word_u{min,max} が設定されるのはどのタイミングだろうか。 25571 25572 % うーん。ble/syntax/parse/touch-updated-word で変更している。そしてこれは 25573 % ble/syntax/parse の中で呼び出される物である。一方で、ble/syntax/parse は 25574 % ble-edit/content/update-syntax から単体で呼び出される事もある。という事を 25575 % 考えると、此処で設定された _ble_syntax_word_u{min,max} は処理される事なく 25576 % 次の ble/syntax/parse に伝播する可能性があるという事。その時に必要になる 25577 % と考えられる shift が実行されていない。 25578 % 25579 % _ble_syntax_attr_u{min,max} についても同様である。これらもちゃんと shift 25580 % する必要がある。 25581 % 25582 % →と思ったら、ble/syntax/parse/shift の中でちゃんと shift されていた。 25583 % _ble_syntax_word_ 及び _ble_syntax_attr_ が接頭辞になっていたのだった。 25584 25585 25586 * done: 着色せずに残っている部分を着色する bgworker を実装する。 25587 最後まで完了した時に progcolor_dirty を clear する。 25588 25589 * done: highlight_timeout_background: bg で着色している時の timeout は長めに取る。 25590 25591 x fixed: 実際に試してみると相変わらず止まってしまう。CPUがぶんぶん回っている。 25592 25593 調べてみると eval が stop_check なしで呼び出されている。 25594 stackdump してみると以下の様な呼び出しになっている。 25595 どうやら simple-word/eval の呼び出し元のチェックに漏れがあった様だ。 25596 25597 stackdump: 25598 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:27 (ble/syntax:bash/simple-word/eval) 25599 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:17 (ble/syntax/progcolor/eval-word) 25600 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:5 (ble/syntax/progcolor/word:default/.is-option-context) 25601 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:26 (ble/syntax/progcolor/word:default/.impl) 25602 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:3 (ble/syntax/progcolor/word:default) 25603 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:7 (ble/syntax/progcolor/default) 25604 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:31 (ble/syntax/progcolor) 25605 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:8 (ble/highlight/layer:syntax/word/.update-attributes/.proc) 25606 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:12 (ble/syntax/tree-enumerate-in-range) 25607 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:2 (ble/highlight/layer:syntax/word/.update-attributes) 25608 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:4 (ble/highlight/layer:syntax/update-word-table) 25609 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:32 (ble/highlight/layer:syntax/update) 25610 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:12 (ble/highlight/layer/update) 25611 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:9 (ble/textarea#update-text-buffer) 25612 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:75 (ble/textarea#render) 25613 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:2 (ble-edit/bind/.tail) 25614 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:17 (ble-decode/EPILOGUE) 25615 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:78 (ble-decode/.hook) 25616 25617 取り敢えずこれについては修正した。 25618 25619 x ok: 次におかしいのは、既に着色済みの筈単語も改めて毎回着色されている様な気がするという事。 25620 25621 と思ったらやはり気の所為だろうか。。。今度はちゃんと新しい単語に対しての 25622 み処理が行われている様な気がする。と思ったが、どうも word:default 自体は 25623 新しい単語に対してのみ呼び出されているが、simple-word/eval は何度も呼び 25624 出されているという事の様である。呼び出し履歴を探ると以下の様になっている。 25625 25626 ble/syntax:bash/simple-word/eval 25627 ble/syntax/progcolor/eval-word 25628 ble/syntax/progcolor/word:default/.is-option-context 25629 ble/syntax/progcolor/word:default/.impl 25630 ble/syntax/progcolor/word:default 25631 ble/syntax/progcolor/default 25632 ble/syntax/progcolor 25633 ble/highlight/layer:syntax/word/.update-attributes/.proc 25634 ble/syntax/tree-enumerate-in-range 25635 ble/highlight/layer:syntax/word/.update-attributes 25636 ble/highlight/layer:syntax/update-word-table 25637 ble/highlight/layer:syntax/update 25638 ble/highlight/layer/update 25639 ble/textarea#update-text-buffer 25640 ble/textarea#render 25641 ble-edit/bind/.tail 25642 ble-decode/EPILOGUE 25643 ble-decode/.hook 25644 25645 うーん。分かった。ble/syntax/progcolor/word:default/.is-option-context で 25646 全ての引数に対して評価を行っている。ble/syntax/progcolor/eval-word で一応 25647 キャッシュはしているが、これは一回の着色の内部でのキャッシュであって、着 25648 色を跨いだキャッシュは行っていない。これはまた別の箇所で対策するべきの気がする。 25649 25650 x fixed: 展開が timeout した時にエラー着色になっている。 25651 timeout の時には d で削除する事にしてみたが、 25652 d ではなく 0 になってしまって黒で塗潰されている。 25653 25654 どうやら #setattr は g を設定するのであって、 25655 wattr の指定を行える物ではない様だ。 25656 25657 * reject: 実は pathname expansion に限らずユーザー入力がある時には単語着色 25658 は中断して良いのではないだろうか。 25659 25660 うーん。これは様子見。早く着色が終わる物から順に着色して行かないと、一番 25661 遅い着色によって他の着色がブロックされてしまう。なので、軽い物は先に処理 25662 するべき。何段階にも分けるのは現実的でないので、現状は重い単語だけ処理を 25663 後回しにする事にする。 25664 25665 x fixed: ble/util/assign の混線に関連して発生していた様々な問題 25666 25667 x "bash: 予期しないトークン `(' 周辺に構文エラーがあります" というエラー 25668 メッセージが出る。何処かにバグが有るという事。background で実行している 25669 時に発生している気がする。先ずは再現性。 25670 25671 x うーん。操作していると突然 hang して暫くして emacs が起動した 25672 25673 何やら操作していたら "# reached line_limit_length=10000" に抵触して、そ 25674 の後に emacs が起動した。2500項目の要素を含んだ "ret=(......) fdsa1 25675 aaaa" と言った感じの内容が入力されている。これが意味する所は何 25676 か。_ble_edit_str に内容が展開されているのが原因と考えられるが何が起こっ 25677 ているのだろうか。 25678 25679 a ble-decode-char に紛れ込むとは考えにくい。 25680 25681 b terminal の echo back に引っかかっているとも考えにくい。そもそもその為 25682 にはそれ専用の escape sequence で囲まなければならないし、それを出力する 25683 ような事が起こるとも思えない。 25684 25685 c _ble_edit_str を直接編集している箇所もないだろうし、 25686 25687 d 一つの可能性は ble/util/assign の混線である。然し、そうだとしても 25688 ble/util/assign で挿入内容を決定する様な機会があるだろうか。 25689 25690 TAB は入力していなかったと思う。従って補完が関係している可能性は取り敢 25691 えず除外する事にする。 25692 25693 →あー。分かった。ble/util/assign の混線である。conditional-sync で 25694 timeout した時に動かしていたプロセスを kill するのを忘れていた為に、遅 25695 延して ble/util/assign の一時ファイルに様々な情報が書き込まれて変な事が 25696 起こっていたという事。一つ前の問題もこれに関連して発生していた現象であ 25697 ろうと推測される。取り敢えず再びいろいろ試して問題が再現しないか確認す 25698 る必要がある。 25699 25700 x fixed: failglob が発生する様な状況で failglob にならなくなっている。何 25701 故だろうか。これは瞬間的に timeout になっている所為で、failglob で失敗 25702 するよりも先に timeout 142 を返して、その為に着色が無効化されているのが 25703 原因だった。 25704 25705 * done: glob が有効な場合でも実は最初に noglob で展開を行って、其処に 25706 rex='[*?]|\[.*\]|[@+!]\(.*\)' が含まれている時に限り改めて 25707 subshell で実行するという形式にしても良いのではないだろうか。 25708 25709 これに関してはわざわざ noglob で展開を行わなくても、 25710 変数代入を実行すれば良いのではないだろうか。 25711 builtin eval -- "tmp=$word" 25712 25713 * done: bash3 では globstar を一時的に off にする事も考える。 25714 25715 然し、そうするとユーザに対して嘘の情報を提供する事になる。本来は一致する 25716 筈なのに failglob して赤色に着色される等の可能性。そういう事を考えるとや 25717 はり時間がかかっても良いから着色するか、或いは着色自体を諦めるか。簡単な 25718 内容の場合には着色を諦めても良いのではという気がする。 25719 25720 或いは、** が含まれる場合に限って着色を諦めるという手もある。即座に 142 25721 を出力する様にすれば良い。これで OK 25722 25723 * done: 変数展開の中まで参照して noglob かどうかを判定する前に、 25724 先に extract-parameter-names & 変数内容の復元をするべき。 25725 25726 再び eval の構造を大きく書き換えたが取り敢えずは動作している模様である。 25727 取り敢えず conditional-sync を経由した展開も動いている様子だ。OK 25728 25729 x 別項目: 全く同じ内容で eval を連続して2回試すという事が頻繁に起こっている。 25730 これは何だろうか。やはり eval-word による呼び出しと、それから本当の着色用 25731 の呼び出しが混ざっているという事だろうか。これに関しては、eval の呼び出し 25732 をキャッシュする事で対応できる気がする。 25733 25734 但し呼び出しをキャッシュすると言っても、bash3 でどの様に対処するべきかは 25735 微妙である。やはり汎用の hash 辞書のインターフェイスを準備するべきかもし 25736 れない。 25737 25738 これは調べてみた所、ble/syntax:bash/simple-word/detect-separated-path と 25739 ble/syntax:bash/simple-word/evaluate-path-spec の二箇所で発生していれう事 25740 の様である。これは eval の内容をキャッシュする様にすれば解決する話である。 25741 独立項目で取り扱う事にする。 25742 25743 2021-01-25 25744 25745 * edit: change default behavior of "C-w" and "M-w" to operate on backward words (reported by 3ximus) [#D1448] 25746 25747 ? done: C-w の振る舞いを readline に合わせる? 25748 25749 後、やはりここまで来ると普通の bash との振る舞いの違いが俄然気になってくる。 25750 やはり C-w は kill-uword ではなくて kill-backward-uword であるべきなのではないか。 25751 やはり既定で kill-backward-uword にする様に変更する。 25752 M-w による copy-backward-word についてはどうするか。 25753 どうも readline の copy-backward-word は widget copy-uword と同じ振る舞いの様である。 25754 しかし、M-w は元の readline では使われていないし、 25755 ble.sh の M-w でどの様に振る舞っても問題はない気がする。 25756 25757 ? ok: C-w で kill-uword する現在の振る舞いに何か理由があっただろうか。 25758 何か理由があって敢えて現在の振る舞いにしている可能性もある。 25759 25760 bbbd155f src/edit.sh (Koichi Murase 2019-03-22 07:28:24 +0900 6763) ble-decode/keymap:safe/.bind 'C-w' 'kill-region-or kill-uword' 25761 1fc7cbaf ble-edit.sh (Koichi Murase 2017-12-04 20:48:17 +0900 6185) ble-decode/keymap:safe/.bind 'C-w' 'kill-region-or uword' 25762 f18485f0 (Koichi Murase 2017-12-04 14:36:52 +0900 4442) ble-bind -f 'C-w' 'kill-region-or uword' 25763 3aa7fa66 (Koichi Murase 2017-12-03 18:31:00 +0900 4461) ble-bind -f 'C-w' 'kill-region-or uword' 25764 6ca737d2 (Koichi Murase 2015-02-28 12:48:55 +0900 54) ble-bind -f 'C-w' 'kill-region-or uword' 25765 ^c68412b (Koichi Murase 2015-02-09 03:13:19 +0900 3381) ble-bind -f 'C-w' 'kill-region-or uword' 25766 25767 どうやら一番最初に commit した時から現在の振る舞いだった様だ。 25768 ここから分かる事は現在の振る舞いに根拠はないという事。 25769 実装初期に kill-backward-uword がなかったか不完全だった時からこうである可能性がある。 25770 なので、振る舞いを現時点で変更しても何の問題もない。 25771 25772 copy-uword vs copy-backward-uword についても全く同じだった。 25773 最初から M-w は copy-uword になっていた。 25774 25775 これは他の ble versions にも適用した方が良いと思われるので独立した commit にする事にした。 25776 25777 * edit ({kill,copy}-region-or): fix unconditionally combined kills/copies (reported by 3ximus) [#D1447] 25778 https://github.com/akinomyoga/ble.sh/issues/83#issuecomment-766831785 25779 25780 C-w で無限に文字列が追加されてしまうという事を指摘された。 25781 25782 % 何故だろう。手許で確認した時には動いている様に見えたのに。と思ったが手許で 25783 % 試した時は C-k や C-u を使っていたために気づかなかったという事の気がする。 25784 % →と思ったら分かった。テストのために自分で ble-bind していたが、 25785 % その時に kill-region-or を使っていなかった。 25786 25787 kill-region-or または copy-region-or の中で 25788 ble/decode/widget/call を用いて widget を呼び出した時に 25789 LASTWIDGET が {kill,copy}-region-or に書き換わる為に、 25790 無条件に前回のコマンドが切り取りコマンドであったと判定されてしまうのが原因。 25791 取り敢えず修正した。ble/decode/widget/* の関数がまた増えてしまったが仕方がない。 25792 25793 * mandb: man のオプションの情報が文字化けしている [#D1446] 25794 25795 % キャッシュが全然使われていない。毎回再生成されている様に見える 25796 % と思ったが、これは単に core-complete.sh が更新されたから、 25797 % それに応じて更新されているというだけの事だった。 25798 25799 データを再生成してもやはり同様に文字化けしてしまう。 25800 25801 調べると nroff は UTF-8 には対応していない様だ。groff は groff -k にて 25802 UTF-8 に対応する様だ。更に -k に加えて -Tutf8 も必要だった。 25803 25804 groff ではなくて nroff の時にはどうするのかという問題は残るが、まあ groff 25805 のないシステムでは UTF-8 の man は存在しないと思って良い気がする。なので取 25806 り敢えずは気にしない事にする。 25807 25808 * 2020-11-02 complete: support complete_limit{,_auto} (contributed by timjrd) [#D1445] 25809 https://github.com/akinomyoga/ble.sh/issues/64 25810 https://github.com/akinomyoga/ble.sh/issues/65 25811 25812 これは時間はかかったが無事に merge まで行った。 25813 25814 * done: source:file において substr を実装する。 25815 * done: filter を自前で実行する場合には cand/yield 内部での filter は不要。 25816 これは flag_source_filter=1 を設定して実行する事にした。 25817 * done: timjrd を README/acknowledgement に追加する。 25818 * done: complete_limit_reached にリークが存在している。 25819 ちゃんと source:* や candidates/generate などのコメントに使う変数を記述して、 25820 それから auto-complete の中で candidates/generate を呼び出す前に local で宣言する。 25821 25822 * main: nfs の上に _ble_base_run があると問題になるのでは [#D1444] 25823 取り敢えずローカルに runtime directory を作る時には $HOSTNAME も含める事にした。 25824 XDG_RUNTIME_DIR 及び /tmp を使う場合には host specific であると期待してその儘にする。 25825 25826 2021-01-22 25827 25828 * edit: C-w で kill-ring への追加を実装するという事 (suggested by 3ximus) [#D1443] 25829 https://github.com/akinomyoga/ble.sh/issues/83#issuecomment-764893198 25830 25831 これについては先ず初めに仕様を確定しなければならない。 25832 25833 例えば前方を切り取るコマンドの場合には必ず左に挿入する事にする? と思ったが、 25834 そうすると C-k を連続で使用した時に、切り取られる行の順序が逆になってしまう。 25835 25836 ? というよりどの様なコマンドが存在しているだろうか。 25837 25838 | 調べると C-k, C-u, C-w, M-d, M-h で kill-... を実行している。 25839 | 25840 | widget 名で言うと 25841 | - kill-{forward,backward}-{?word,{graphical-,logical-,}line,text} 25842 | これの対応は簡単。backward に削除する場合には prepend し、 25843 | forward に削除する場合には append すれば良い。 25844 | - kill-{?word,{graphical-,logical-,}line} 25845 | これは微妙。emacs でどの様に振る舞っているだろうかと考えたが、 25846 | よく考えてみたらその様に振る舞う物は存在しない気がする。 25847 | 25848 | emacs.rlfunc.txt で対応表を見てみたが、kill-line に対応する 25849 | rlfunc kill-whole-line しか振る舞いを確認できる物が存在しない。そして、 25850 | この rlfunc kill-whole-line は kill-line と違って、 25851 | コマンドライン全体を切り取ってしまうのでやはり振る舞いとして異なる。 25852 | 25853 | と思ったが、実際に readline で実行してみると kill-whole-line は 25854 | 前回の内容に append する様である。取り敢えず ble.sh でもその様に振る舞う事にする。 25855 | 25856 | - kill-region 25857 | これは前回の内容は完全に忘れるという振る舞いで良い。 25858 | 25859 | - vi_imap/delete-backward-word 25860 | これは実は kill-ring には何も影響を与えない様だ。取り敢えず無視する事にする。 25861 | readline の vi mode の時には kill するが combine はしない様だ。 25862 25863 →結論としては、kill-region,kill-region-or 以外の kill-* は全て対象という事。 25864 kill-backward-* に関しては prepend で、それ以外については append という事。 25865 25866 ? ok: append/prepend をした時に元々あった内容を上書きするのか、 25867 新しく項目が追加されるのか。 25868 →試して見た所、上書きする様である。 25869 25870 ? done: /.*-range の allow_empty という引数は必要なのだろうか。 25871 kill,copy,delete に関しては決して指定される事はない。 25872 replace に関しては大体指定されている。 25873 指定されていない物は意図的な物かどうか確認する必要がある。 25874 25875 - ./keymap/vi.sh:3995: ble/widget/.replace-range "$eol1" "$eol2" "$text" 25876 - ./keymap/vi.sh:4016: ble/widget/.replace-range "$eol1" "$bol2" "$text" 25877 上記二つに関しては eol1<eol2 が保証されているのでどちらでも良い。 25878 - ./lib/core-complete.sh:5832: ble/widget/.replace-range "$pos" "$comp_index" "$value" 25879 - ./lib/core-complete.sh:5865: ble/widget/.replace-range "$pos" "$comp_index" "$value" 25880 - ./lib/core-complete.sh:5871: ble/widget/.replace-range "$pos" "$comp_index" '' 25881 上記3つに関しても同様に pos<comp_index が保証されている。 25882 - ./lib/vim-surround.sh:509: ble/widget/.replace-range "$beg" "$end" "$content" 25883 operator なので幅0になる事は余りない気がするが、例えば編集文字列が空の時? 25884 →うーん。その様な場合であっても cs 経由でしかこの operator は呼び出されないので、 25885 結局、delimiter を使って範囲を切り出そうとする段階で失敗してしまう。 25886 結局、この operator が空文字列に対して呼び出される事はない気がする。 25887 25888 もし仮に呼び出される事があったとしても、allow_empty を指定する方が自然。 25889 25890 replace-range については常に allow_empty という事にする。 25891 kill,copy,delete については常に not allow_empty という事にする。 25892 →書き換えた。 25893 25894 ? done: copy でも同様に振る舞う必要があるだろうか。 25895 →実際に試してみた所、同様に振る舞う様である。。。 25896 25897 動かしていて気づいたが、C-k で行末の改行を削除できていない…。 25898 これは別 commit での bugfix にする事にする。 25899 25900 * edit: support "bleopt edit_line_type" (motivated by 3ximus) [#D1442] 25901 https://github.com/akinomyoga/ble.sh/issues/83 25902 25903 手で一つ一つ logical-line を明示的に指定するよりは、 25904 一つのオプションで一括で切り替えられる様にした方が良い。 25905 更に、今まで既定で graphical line を使っていたのを、 25906 logical line を使う様に変更する事にする。 25907 25908 * edit (sword): fix definition of sword (motivated by 3ximus) [#D1441] 25909 https://github.com/akinomyoga/ble.sh/issues/83#issuecomment-764893198 25910 25911 この質問で具体的に各単語がどのような定義になっているのか説明しようとして 25912 コードを参照した時に気づいた。sed によって & が置換前の文字列に展開されて、 25913 変な事になっていたのが原因。 25914 25915 2021-01-17 25916 25917 * LC_CTYPE の切り替えエラーが出る (reported by 3ximus) [#D1440] 25918 https://github.com/akinomyoga/ble.sh/issues/81 25919 25920 実際に確かめてみたら確かにエラーメッセージが出る。 25921 過去に対策したつもりだったが対策の仕方が間違っていた。 25922 色々実験した所、結局余計に一つ関数呼び出しをしなければ駄目な様だ。 25923 自動で stderr を抑制するように書き換える汎関数を作って対応する事にした。 25924 25925 2021-01-01 25926 25927 * decode (ble-decode-kbd): support various keyseq specifications [#D1439] 25928 https://github.com/urbainvaes/fzf-marks/pull/41 25929 https://github.com/urbainvaes/fzf-marks/pull/43 25930 25931 上記で ble.sh 特有の binding を追加してもらったが、ble-bind がユーザーが自 25932 由に対応キーを指定できる様に公開されている変数 FZF_MARKS_JUMP の形式に合わ 25933 ない為に C-g 決め打ちになってしまっている。ble-bind でも bind と同様の形式 25934 で keyseq を指定できる様にしたい。 25935 25936 25937 2020-12-25 25938 25939 * edit: f1 で関数定義を表示する時に LESS=-r が効いていない [#D1438] 25940 これは bash のバグの様である。バグ報告は bug-report でする事にして、 25941 ここでは簡単に修正してしまう。 25942 25943 * edit: 2020-12-09 READLINE_MARK, etc. の値が残ってしまっている [#D1437] 25944 25945 これは ble/textarea#adjust-for-bash-bind によって設定されている値である。 25946 コマンドを実行する時に復元・保存する様にするのが良いのではないだろうか。 25947 25948 * 何故か READLINE_LINE, READLINE_POINT が export されている。 25949 と思ったが、これは ble.sh を bind -x の内部で動かしているからであった。 25950 READLINE_LINE 及び READLINE_POINT が 25951 25952 * 普通の bash で実行するとどうなるのかと思ったが、どうやら自分で設定した 25953 READLINE_LINE 及び READILNE_POINT があっても bind -x の実行と共に削除され 25954 てしまう様である。 25955 25956 取り敢えず adjust/restore する様にした。コマンドの実行の間で値が保存される 25957 様にした。bind -x が実行されても値がクリアされる事はない。 25958 25959 2020-12-20 25960 25961 * [解消] 2020-09-27 SIGWINCH で job メッセージが出る [#D1436] 25962 2020-12-20 これは #D1435 と同一の問題であろう。直ったと見て良い。 25963 25964 SIGWINCH に対して次の様な job メッセージが表示される様になっている。 25965 [1] 終了 [[ -n $_dotfiles_blesh_manual_attach ]] | [[ -n $_dotfiles_blesh_manual_attach ]] 25966 これは .bashrc で設定されている関数の一部である。何故? 25967 25968 調べてみるとそもそも関数ですらなくて、 25969 これは ble-attach を呼び出す条件の中に含まれているコマンドだと分かった。 25970 つまり SIGWINCH に際して ble-attach 関連の何かが呼び出されて、 25971 そして最後に呼び出された ble-attach の呼び出し時のコマンド文字列が何処かに保持されている? 25972 もしくは再び .bashrc が source されている可能性もあるがやはりそれは変だ。 25973 25974 2020-10-10 今試してみると再現しない。 25975 25976 25977 * edit: WINCH 後に偽のジョブ情報が表示される (reported by 3ximus) [#D1435] 25978 https://github.com/akinomyoga/ble.sh/issues/78 25979 25980 前回報告を受けていた謎のジョブ終了メッセージについて。 25981 これは端末のサイズを変えた直後に起こるという新情報を得た。 25982 3ximus/dotfiles の .bashrc を確認して再現を試みた所、 25983 git-prompt.sh, prompt_7.sh, ble.sh の組み合わせで再現できた。 25984 25985 更に設定を最小化していく。どうやら fork があると 25986 jobs にメッセージが乗る様になってしまうらしい。 25987 25988 これの回避方法としてどの様な方法があるか。 25989 25990 a jobs で得た新しいイベントを除去する? 25991 然し、これの問題点は唯の fork と、 25992 本当にジョブとして起動したコマンドの区別が付かないという事。 25993 25994 振る舞いの違いとしては trap handler の中で発生したfork に対応するジョブの 25995 情報は trap handler を抜けた時に消滅しているという事である。 25996 25997 但し、バックグラウンドとして起動したコマンドのジョブ情報もtrap handler を 25998 抜けると消えてしまうのかもしれない。試せば分かるが面倒なので必要になった 25999 ら確認する事にする。 26000 26001 b もう一つの方法はシグナルを処理している時は 26002 jobs の更新は行わないという物。これが妥当な気がする。 26003 26004 ? この現象が起こるのは WINCH だけなのか、或いは別のシグナルでも発生するのか。 26005 →確認した所、INT でも同様にジョブ情報に fork が乗る様である。 26006 26007 trap '(true); jobs' INT 26008 26009 ? 現在シグナルの中にいるかどうかを判定する方法は存在するだろうか。 26010 或いは ble.sh の枠組みの中で trap-handler 経由で呼び出されたか 26011 どうかの情報を用いて判定する? 26012 26013 trap-handler の中にいるかどうかの判定方法。一つは return を 26014 使って関数を抜けた時に、直前の exit status を返すか、 26015 或いは固定の exit status を返すかを見るという方法。 26016 よく考えたらこれは bash-4.4 以降でしか使えない。 26017 Bash はこの部分について振る舞いを変更したのだった。 26018 26019 % 取り敢えず b の方向で実装する事にする。 26020 % ble.sh の中での jobs の仕様実態について確認する。 26021 % 26022 % どうやら指定した名称に対応する jobs が存在するかどうかの確認にも 26023 % jobs -- "$value" を使用している様である。これについては、偶々 26024 % value に一致する終了したジョブ名が存在すると jobs -- "$value" を実行する事によって 26025 % その情報がジョブ情報のリストから削除されてしまう。この問題を回避する為に 26026 % jobs -- "$value" を実行する為に ble/util/joblist.check を実行しているが、 26027 % trap handler の中で joblist.check をスキップしてしまうと、 26028 % そのジョブ情報が正しく拾われずに消滅してしまう可能性が残る。 26029 % trap handler の内部では jobs はサブシェルで実行するのが良い気がする。 26030 % 26031 % 1 done: 何れにしても最初に trap handler の中で実行しているかどうかを確認す 26032 % る必要がある。特に ble.sh の実装が原因で発生する変なメッセージを防げれば 26033 % 良いので、trap/.handler の中でローカル変数を定義する事にする。 26034 % 26035 % 2 done: jobs を使っている箇所を確認する。 26036 % 26037 % * util.sh は ble/util/joblist だけでしか jobs を呼び出していない。修正した。 26038 % * core-syntax.sh も ble/syntax/highlight/cmdtype/.is-job-name だけで使っ 26039 % ている。対策した。 26040 % * edit.sh では ble/builtin/exit で終了する時にユーザに確認を求める所で実 26041 % 行しているが、exit する時には何れにしてもジョブ一覧を出力するので敢えて 26042 % 直接実行する。変なジョブ情報が出力される事になってしまうがこれは仕方が 26043 % ない。 26044 % * 他に ble/widget/command-help/.type で jobs -- "" を実行している。これに 26045 % ついても修正を行った。 26046 % 26047 % 3 動作確認: さて、実際に修正して見た所直っていない。どうも trap を抜けた後 26048 % も変なジョブ情報は残っている様である。ユーザのコマンドとして jobs を実行 26049 % すれば変なジョブは消えてなくなっているが、bind -x の中から jobs を呼び出 26050 % すと全て出力されてしまうという事だろうか。 26051 % 26052 % サブシェルの中で jobs を実行する様にした結果か、余計に大量の偽ジョブが登 26053 % 録されてしまっている。 26054 % 26055 % 改めて bind -x を組み合わせた時の動作についても確認する→うーん。再現した…。 26056 % WINCH の直後の bind -x の中で jobs を実行すると偽情報が出る。 26057 % 別の bind -x を一回実行してから次の bind -x で jobs を実行しても再現する。 26058 % bind -x 以外の入力を行った後でも、bind -x の中で jobs を実行すると再現する。 26059 % 一回でもユーザコマンドを (空でも良いので) 実行すると、偽情報は出なくなる。 26060 % 26061 % こうなって来ると変なジョブ情報が消えるのを待つ作戦に頼るのは困難である。 26062 % 今までの変更は取り敢えずなかった事にする。 26063 26064 うーん。trap/.handler の中で jobs を敢えて実行して結果が描画に回る前に 26065 偽情報をクリアしてしまう事にする。blehook WINCH を実行する前に joblist 更新をして、 26066 更に実行した直後にも joblist の更新を行う。二回目の joblist の更新では、 26067 一時的に現れてそれで直ぐに消滅したイベントはイベントとして登録しない事にした。 26068 26069 これだと blehook WINCH を実行している最中に終了した本当のジョブ終了の情報が 26070 消滅すrことになるが、実際に blehook を実行している途中に jobs の状態変化を 26071 Bash が受信するのか不明だし、もしそうだとしても blehook WINCH の処理のよう 26072 なごく短時間でその様な事が起こる確率は低いと考えられる。なので、気にしない 26073 事にする。 26074 26075 取り敢えず動いてはいる様子である。 26076 26077 2020-12-14 26078 26079 * progcomp: : や = の quote の取り扱い (reported by 3ximus) [#D1434] 26080 https://github.com/akinomyoga/ble.sh/issues/77 26081 26082 ? そもそも \=, \: の様にエスケープしていたのは何故だったか。 26083 26084 ? bash-completion の提供した補完に対して \= や \: の様にエスケープを実施す 26085 る必要はあっただろうか。その辺りの実装はどの様になっていたのだったか。 26086 26087 関連しそうな物を探す。ble-0.3 では = のエスケープはしていない。 26088 26089 #D1133 でコマンド名に関しては =, : の quote はしない様にしている。 26090 #D1098 6c6bae56 で = や : のエスケープが導入されている。 26091 #D1094 では = や : による候補の分割を議論している。 26092 26093 うーん。元々エスケープは #D1098 で導入された物の様だが深くは考察していない。 26094 改めてどの様に振る舞うのが自然か考察する必要がある。 26095 26096 * そもそも ble.sh の補完は展開後の結果を生成して貰う前提になっている。 26097 一方で bash の補完は展開前の結果を生成する事を許容している。 26098 例えば abc$(echo hello) の様な文字列を補完で生成する事すら可能なのである。 26099 それどころか複数単語からなる展開結果にする事も可能の筈である。 26100 26101 * それでは progcomp の結果はそのまま挿入する事にすれば良いのではないか 26102 とも思われるが此処で問題になるのは、ble.sh の側で適当に展開を実行してから 26103 COMP_LINE を構築して progcomp に渡しているという事である。 26104 26105 これは途中に $var 等の単純な展開等が含まれている場合でも 26106 progcomp で補完を実行できる様にする為に必要。 26107 26108 この時、progcomp が展開前の補完結果を生成した時に、 26109 それを如何に元のコマンドライン文字列に反映させるのかが問題になる。 26110 26111 x [OK] 手許では再現していないが scp chat\:down[TAB] で chat\: が消滅してしまう? 26112 26113 notepc の方は bash_completion が入っていないので今試せない。 26114 * chat は port を変えているので localhost: から試そうとしてもできない。 26115 localhost や chat を .ssh/config に登録してパスワード無しで補完できる様にしたが、 26116 補完候補は出してくれない様である。 26117 * hp2019 -> chat を試してみたが再現しない。local にも mkdir downloads したが再現しない。 26118 26119 うーん。取り敢えずそもそも何故失敗するのか考える? 26120 plain bash で実行したところ failglob で失敗している。 26121 shopt -u failglob にしたら ble.sh の中でも補完が動く様になった。 26122 26123 そして chat\: が消滅してしまう問題に関しては、 26124 plain bash でも再現する事ができた。 26125 これは bash-completion の問題である。 26126 26127 特にローカルのカレントディレクトリに "host:..." というファイルが存在する時に、 26128 host\:... と入力している可能性があって、この時に host: の部分が消滅してしまう 26129 という問題が発生する。 26130 26131 https://github.com/scop/bash-completion/issues で報告をしようかと考えたが、 26132 もしかすると最新版で直っている可能性もあるので、 26133 最新版の bash-completion を試してみても良い。 26134 26135 うーん。progcomp による展開結果が空白などを含んでいる時にどのように振る舞うのか。 26136 plain bash はそのまま何も加工を行わずに展開してしまう。うーん。 26137 blesh ではどの様に取り扱うべきか。 26138 26139 * できるだけ progcomp が提供した quote を保持する様にしたい。 26140 然し、これは現実的には難しいのではないか。 26141 26142 a = 及び : についてだけ quote しているかそうでないか保持する? それ以外の 26143 文字については自分で quote し直す。 26144 26145 その為には progcomp が生成した単語について = や : で分割を試して、その 26146 上でそれぞれ quote してから再結合する? これだといかにも処理量が大きい。 26147 非効率的である。 26148 26149 これは処理方法として複雑でありユーザから見たら不自然で予測不能に見える 26150 かもしれない。処理の重さとしては次に述べる方法よりは現実的である。 26151 26152 b 入力済みの部分に一致する部分を除去してそのまま挿入。 26153 26154 ここで問題になっているのは既に入力済みの部分に対応する文字列を 26155 どの様に取り除くのかという事であった。二分法を用いる等して 26156 これについて既に入力済みの部分を除去する方法はないだろうか。 26157 26158 どの様にしたら良いのかを調べる必要がある。二分探索で調べるという方法と、 26159 1 unit ずつ読み取って行くという方法の二種類を考える事ができる。 26160 26161 * 二分探索で調べるというのは複雑な気がする。元の文字列について途中で切 26162 断して二分探索していくという手も考えられるが、変数名の途中など変な所 26163 で切断すると内容が空になるなどして意図しない結果になってしまう。 26164 26165 * 取り敢えず 1 unit (simple word element) ずつ読み取って行って、切断す 26166 るという方法? 然し、'...' 等の様に一気に読み取る事ができるliteral 等 26167 になっているとすると、実装が複雑になる。面倒である。そもそも処理が複 26168 雑になる。面倒である。 26169 26170 c 今まで通り基本的に progcomp が生成した物は展開毎と見做して quote を行う。 26171 = 及び : は基本的には quote を加えない。compopt -o filename で quote が 26172 明示的に指定された時にのみ =, : の quote を行う。 26173 26174 これは progcomp が quote を自前で行って候補を生成した時に問題になる。つ 26175 まり quote が二重に為される事になり、意図しない結果になってしまう。然し、 26176 この問題は今までにも存在していた問題の筈である。取り敢えずの修正として 26177 は妥当である。 26178 26179 取り敢えず今までも quote を勝手にする事による問題はあった。 26180 全てを一度に解決するのは難しいししなくても良い。 26181 此処は c の方針で修正する事にする。 26182 26183 2020-12-13 26184 26185 * README: ((_ble_bash)) && ble-attach だと set -u の時駄目 [#D1433] 26186 ble.sh ロードに失敗した時や ble.sh を意図的に読み込まなかった時に 26187 _ble_bash が存在しないので内容をチェックする前にエラーになってしまう。 26188 26189 [[ ${BLE_VERSION-} ]] && ble-attach にするべき。 26190 26191 2020-12-10 26192 26193 * complete/mandb: FreeBSD 上で man 情報の抽出に失敗している [#D1432] 26194 26195 | freebsd には roff, nroff, troff 等が存在していない。 26196 | それでも man が動作している事を考えると、 26197 | 何らかの方法で man pages を変換しているという事の筈。 26198 | それについて調べて対応する。 26199 26200 対応した。FreeBSD では mandoc というコマンドを使って変換を行っている。 26201 nroff と同様に -man 等を指定する事ができる様だが、 26202 どうやら FreeBSD は -man ではなくて -mdoc を想定して man pages を書いている様だ。 26203 という訳なので -mdoc を前提として抽出をする様に書き換えた。 26204 26205 ちゃんと nroff を使う版も動いている。OK 26206 26207 * highlight: command \^J-a とした時に -a がオプションとして着色されない (reported by cmplstofB) [#D1431] 26208 https://github.com/akinomyoga/ble.sh/issues/76 26209 26210 現在の着色では \-a や ''-a 等の様に quote がある場合には、 26211 意図的にオプションとしての着色を避けている。 26212 そういう意味に於いて \^J-a もやはりオプションの前に quote が 26213 ある物として取り扱ってオプションとしての着色が無効になっている。 26214 26215 a 然し意味的に考えるとやはり \^J は単語の一部に含まれない様にするのが自然に 26216 も思われる。 26217 26218 ? その様に構文解析を変更する事は恐らく簡単だろうが、単語の一部として解析 26219 しない部分文字列がコマンドラインに含まれる事による副作用などはあるだろ 26220 うか。思うにリダイレクションなども単語の一部として登録していないので、 26221 特にこの事で問題が発生する事はない気がする。 26222 26223 また sabbrev の単語判定でもやはり語頭の \^J は含まれない様にしたい。 26224 26225 語頭の \^J は skip する事にする。これはどの様に実装すれば良いか? 26226 ^J や空白を処理している箇所で一緒に処理すれば良いだろうか。 26227 26228 取り敢えず構文解析は修正した。多分大丈夫。副作用が起こるかもしれないが、 26229 それは実際に何かが起こってから見るという事で良いだろう。 26230 うーん。問題が起こるとすれば二次的に起こる問題ではなくて、 26231 構文解析自体が変になる可能性が高い気がするが多分大丈夫。 26232 26233 * color: italic が描画できていないという (by rlanore) [#D1430] 26234 https://github.com/akinomyoga/ble.sh/issues/73 26235 26236 試してみると手許では動いている。対応していない端末で使おうとしているのではないか。 26237 この Issue には返信がないがもう一つの新しい Issue に対して Terminal 情報を載せている。 26238 Terminator 1.92 を使っている様である。 26239 26240 Cygwin 付属の Terminator 0.98 は italic に対応していない。 26241 Cygwin 附属の GNOME terminal は対応している。 26242 vte のソースコードを見ると 2012 には italic 関連のコードが存在している様だ。 26243 2014 にまた別のフォント初期化コードが追加されている。然し一方で pango も呼び出している。 26244 これが実際に X11 環境で使われるのかどうかはよく分からない。 26245 26246 →これは結局向こうの tmux の設定が問題であった。手許で試して見たところに依 26247 るとどうも tmux は default-terminal の値に応じて自身の振る舞いも変更する様 26248 である。これについて wiki の manual にも書いておく必要があるのではないか。 26249 →wiki に説明を追加した。 26250 26251 * complete/mandb: ^H が大量に挿入される (reported by rlanore) [#D1429] 26252 https://github.com/akinomyoga/ble.sh/issues/75 26253 26254 これは nroff で太字を表現するのに <CHAR>^H<CHAR> を出力する物がある為。 26255 なので、単に .\b を削除すれば良い。 26256 26257 取り敢えず修正してみたが本当に動くか微妙。複数の OS で試す必要があるのではないか。 26258 freebsd で試して見たところ、troff がないので動いていない。 26259 これについては後で対応する事にする。 26260 26261 2020-12-09 26262 26263 * complete: 補完候補が更新されない問題 (reported by 3ximus) [#D1428] 26264 https://github.com/akinomyoga/ble.sh/issues/74 26265 26266 これは明らかに menu-filter で候補がなくなった時に、 26267 元の候補を全て表示する様に変更したのが原因である。 26268 やはり一致しなくなった時点で候補は表示しない様に変更する事にした。 26269 26270 b 或いは別の変更方法として、候補再生成のフラグを設定して、 26271 この時にはメニューから候補を拾う事はしない様にする? 26272 26273 x と思ったが、そうすると結局候補を全て表示する意味がない? 候補を表示する 26274 のはメニューから選択させる為であるが、メニューから候補を拾わない様にし 26275 た時点でそれが使えない? 26276 26277 % x と思ったが連続 TAB や、明示的な menu-complete の bind の時には、候 26278 % 補の再生成をせずに menu に入る事が可能になる。 26279 26280 でも連続 TAB の場合は最初の TAB の時点で候補再生成が起こるので、表示し 26281 ている候補が使われる事はない。明示的な menu-complete の bind についても 26282 既定では C-TAB 等余り使われなさそうな物になっているので設計に考慮に入れ 26283 なくて良い気がする。 26284 26285 此処まで処理を複雑にしても余り有用ではなさそう。次の TAB で候補一覧はすぐ 26286 に消えてしまうので、絞り込み前の候補一覧を表示しても却って混乱を生むだけ 26287 である。この選択肢は却下である。 26288 26289 2020-12-08 26290 26291 * util/term: lxterminal, gnome-terminal で vte の検出に失敗している [#D1427] 26292 これはソースコードを確認してみた所、xterm の version 抽出コードを追加した時 26293 に動かなくなった物の様に見える。修正した。 26294 26295 2020-12-01 26296 26297 * prompt: PROMPT_COMMAND で変更した PS1 がその場で反映されない (reported by 3ximus) [#D1426] 26298 https://github.com/akinomyoga/ble.sh/issues/72 26299 26300 確認した。これは書き換えミスである。prompt_ps1_final 等の書き換えの時に、 26301 更新の必要性があるかどうかの判定を PROMPT_COMMAND よりも前に持ってきたのが行けない。 26302 26303 これはどの様に修正したら良いだろうか。PROMPT_COMMAND は更新の必要がある時に 26304 のみ実行したい。或いは :leave: の時にも実行するべきだろうか。leave の時に 26305 PROMPT_COMMAND は実行しなくても良い気がしてきた。うん。その様に変更する。 26306 26307 * complete: 単語補完で = の右辺の . で始まるファイル名が補完されない (reported by cmplstofB) [#D1425] 26308 https://github.com/akinomyoga/ble.sh/issues/71 26309 26310 これは試してみた所、a= で補完してから . を入力して絞り込みをすると、最初の 26311 a= の時に . で始まる候補が列挙されていなかった為に、絞り込みモードに入って 26312 も . で始まる候補が列挙されないままになるという問題。a=. まで入力してから初 26313 めて補完を開始する様にしたらちゃんと . で始まるファイル名でも補完できる。 26314 26315 修正の方向性として二つ考えられる。 26316 26317 a 一つは最初から . で始まるファイルも列挙しておくという事。 26318 26319 つまり dotglob を有効にして補完を実行すれば良い。 26320 26321 この方法だと . から始まるファイル名も全部表示されて煩い様な気もするが、よ 26322 く考えれば一文字でも入力していればこれらの候補は表示されないのだし、. を 26323 含めて候補生成しても特に問題ない気がする。 26324 26325 b もう一つの方向性は a=. まで入力した後に先頭一致する候補が見つからないと分 26326 かった時点で候補を再生成するという事。 26327 26328 x この方法だと BS で巻き戻して再度候補を表示しようと思ってももう戻ってこ 26329 ないという問題がある。改めてその場所から補完を実行しなければならなくな 26330 る。 26331 26332 x また . が部分一致している場合には、先頭の . が部分一致を意図した物なの 26333 か、或いは . で始まるファイルを改めて生成するべきかの判断が付かない。安全 26334 側に倒すとすれば . から始まるファイルを再生成すれば良い気もするが、そうす 26335 ると部分一致を意図していた時に位置文字入力する度に候補が再生成される事に 26336 なり重くなる。或いは、本当に特定のコマンドの時にだけ再生性を行うという事 26337 になり不自然な気がする。 26338 26339 x a の方針で実装してみたが実際に動かしてみると動かない。というよりユーザが 26340 dotglob を有効にしても勝手に dotglob が off になってしまう。何故だろうか。 26341 うーん。 26342 26343 * ble.sh だけしか読み込んでいなくても勝手に dotglob が off になってしまう。 26344 * 補完を試みない限りは dotglob に変化はない。 26345 * dotglob という文字列を含むコードを全てコメントアウトしても dotglob が 26346 off になってしまう。 26347 26348 どうやら GLOBIGNORE= : を実行しただけで dotglob の設定が変わってしまう様 26349 だ。そしてこの振る舞いは bash のマニュアルに書かれている。 26350 26351 現在の実装で GLOBIGNORE を設定しているのは core-complete.sh だけである。 26352 glob 展開を抑制して split を実行する箇所では GLOBIGNORE=* ではなくて set 26353 +f を用いる様に変更を行った。その他の eval-pathname-expansion は現在の 26354 GLOBIGNORE の設定に忠実に展開を実行するので GLOBIGNORE には触らない。 26355 26356 改めて GLOBIGNORE の取り扱いについて考え直す必要がある。local GLOBIGNORE 26357 とすると bash-3.0, 3.1 で影響が残ってしまう問題があった。ここでは何処かに 26358 値を保存しておいてそれを復元するという形にするべきか。 26359 26360 →その様に書き直した。dotglob はこれで勝手に書き換わらない。. で始まる候 26361 補もちゃんと出力される様になった。 26362 26363 * highlight: ~+ 等のチルダ展開が着色されない (reported by cmplstofB) [#D1424] 26364 https://github.com/akinomyoga/ble.sh/issues/71 26365 26366 Cygwin 上では再現しなかったが Linux 上では再現した。調べてみると 26367 ble/syntax:bash/simple-word/locate-filename/.exists を呼び出した時点で単語 26368 が ''~+ の様に書き換えられていて意図的にチルダ展開が無効になっている。 26369 26370 調べてみると構文解析の段階で ~ に tilde 属性が設定されていない時には 26371 notilde が指定される様になっていた。実際に構文解析の結果を見ると何故か ~+ 26372 の時には ~ にチルダ展開の着色が為されていない。これは構文解析の問題である。 26373 26374 どうも分かった。shopt -s extglob になっていると +() の可能性が考えられるの 26375 で、~+ が来ても ~ 迄で構文解析が一旦切れる。これでチルダ展開の可能性を判定 26376 しようとすると、後ろに余分な文字が存在するという理由でチルダ展開が無効化さ 26377 れる。なので tilde が構文着色されない。結果として単語着色でチルダ展開が無効 26378 化されている。 26379 26380 そもそも extglob が有効になっている時に + が含まれている単語は単純単語なの 26381 だろうかという疑問もある→実際に試して見るとちゃんと単純単語として認識され 26382 ている。+() が含まれている場合には単純単語ではない。よく考えたら当たり前と 26383 いえば当たり前。() が含まれているかどうかだけ判定すれば良いのだから。 26384 26385 a reject: うーん。現在の文字集合ベースの判定ではなくて simple-word で判定し 26386 てしまうというのが自然な気がしてきた。但し、/: 等は含まれない様にする。と 26387 思ってその様に書き換えてみた。 26388 26389 x しかし、よく考えてみたらこの場所に於ける判定は構文解析の 1 step である。 26390 なので、simple-word の様に複数の解析ステップを跨ぐ様な先読みを実行する 26391 と変な事になる。なので、やはり元の実装のように chars ベースで判定しなけ 26392 ればならないのである。 26393 26394 b reject: 一回の解析で読みきれない様なチルダ展開は着色しなくても良いのでは 26395 ないかという説。例えばユーザー名として a~b~c の様な変な物を選んだ時に、果 26396 たして ble.sh が ~a~b~c の様なチルダ展開に対して正しく処理を行う必要があ 26397 るのかという話。 26398 26399 そうは言ってもユーザー名の場合には変なユーザー名にするのが悪いという事に 26400 なるが (ble.sh に限らず様々な場所で問題が起こるだろう)、~+ に関しては標準 26401 で存在する特別な指定なので、やはりちゃんと処理したい。 26402 26403 c + を特別扱いする? 結局これが現実的な解になるのだろう。 26404 26405 ~+ の時にはこれ全体をチルダ展開として抽出する? と思ったがそうすると ~+ ま 26406 でが解析終了点と判定されて、~+(echo hello) 等を正しく構文解析できなくなる。 26407 26408 或いは ~+ で始まる時だけ完全に独立に実装し直す事にする? 26409 26410 色々試行錯誤したが、既存のコードと同じ処理にして但し、~+ がチルダ展開でな 26411 かった時に ~ まで後退するという実装方法にする事にした。 26412 26413 d ~ の直後で切れても良いがその直後が + の時には特別にチルダ展開を許容する? 26414 と思ったが、これだと ~+aaa 等の時にもチルダ展開として着色されてしまう。駄 26415 目。 26416 26417 x 結局 c の方針で実装したが今度は ~+(echo) が動かなくなった。ちゃんと解析位 26418 置を後退する様にした筈なのに。というより ~+ がチルダ展開として着色されて 26419 いる。 26420 26421 →分かった。 ~+( となっていて "(" が delimiter として登録されているので、~+ 26422 と ( の間で単語が切れていると判定されてしまっている。これは駄目。"(" は 26423 delimiter として登録しなくても良い気がする。→そのように直した。 26424 26425 動いている気がする。 26426 26427 2020-11-27 26428 26429 * complete: dynamic sabbrev が動かなくなっていた (reported by darrSonik) [#D1423] 26430 これは cand/yield を sabbrev/expand の中で使っていたが、 26431 cand/yield に対する要求が増えていたのが原因だった。修正した。 26432 他の ble/complete/cand/yield の箇所で問題がないかも確認した。 26433 本来は積極的にテストを追加するべきなのである。 26434 然し、対話的な昨日に対してテストを追加するのは面倒である。 26435 26436 2020-11-26 26437 26438 * 2020-03-22 syntax: { echo $fd; } {fd}>&0 の着色が変 [#D1422] 26439 これは単語着色の除去ができていない問題であろう。 26440 26441 →これは #D1421 と全く同じ問題で、#D1421 に伴って自然解消した。 26442 26443 * 2017-11-26 highlight: 配列代入の解析の不整合? [#D1421] 26444 26445 最初から arr[index まで入力した時の着色と 26446 arr[index] まで入力してから一文字削除した時の着色が異なる。 26447 26448 | _ble_syntax_attr/tree/nest/stat? 26449 | 7 aw 000 'a' stat=(CTX_CMDX w=- n=- t=-:-) 26450 | 8 a e 001 '[' nest=(CTX_VRHS w=ATTR_VAR:0- n=- t=-:-) 26451 | 8*a 002 'a' stat=(CTX_EXPR w=- n=@1 t=-:-) 26452 | 6*a e 003 'b' 26453 | | s 004 ^@ stat=(CTX_EXPR w=- n=@1 t=-:-) 26454 | \_ 'a[ab' 26455 | \_ '[ab' 26456 | 26457 | _ble_syntax_attr/tree/nest/stat? 26458 | 7 aw 000 'a' | stat=(CTX_CMDX w=- n=- t=-:-) 26459 | 8 aw 001 '[' || nest=(CTX_VRHS w=ATTR_VAR:0- n=- t=-:-) 26460 | 8*aw 002 'a' || stat=(CTX_EXPR w=- n=@1 t=-:-) 26461 | |*aw 003 'b' || 26462 | 8*aw 004 ']' ++ word=CTX_CMDI:0-5>@4 word="a[":1-5 stat=(CTX_EXPR w=- n=@1 t=-:-) 26463 | | s 005 ^@ stat=(CTX_ARGX w=- n=- t=$5:-) 26464 | \_ 'a[ab]' 26465 | \_ '[ab]' 26466 | 26467 | _ble_syntax_attr/tree/nest/stat? 26468 | 7 a 000 'a' stat=(CTX_CMDX w=- n=- t=-:-) 26469 | 8 a e 001 '[' nest=(CTX_VRHS w=ATTR_VAR:0- n=- t=-:-) 26470 | 8*aw 002 'a' stat=(CTX_EXPR w=- n=@1 t=-:-) 26471 | 6*awe 003 'b' 26472 | | s 004 ^@ stat=(CTX_EXPR w=- n=@1 t=-:-) 26473 | \_ 'a[ab' 26474 | \_ '[ab' 26475 26476 どうも構文の状態は同じだ。単語の着色が異なる。 26477 しかしそもそも何故単語着色が起こっているのだったか。 26478 単語着色は CTX_CMDI としての着色が残っているということ。 26479 これは単語着色の側の問題であって、解析の問題ではない。 26480 26481 2019-02-13 "{ echo; } 3>&1" と入力した時にも 26482 似たような事になる。"{ echo; } 3" まで入力した時の単語エラー着色が 26483 最後まで残ってしまう。#D0930 26484 26485 2020-11-26 改めて振る舞いを確認してみる。a[a とすると単語が消滅している。 26486 また、a の場所に単語着色が残っている。消滅した単語に対する処理がない事が原因。 26487 26488 消滅単語に関する処理は今どうしているのだったか。note.txt の中を検索してみた 26489 がよく分からない。消滅単語の範囲にある単語について再度着色を実行するという 26490 事が書かれているが…。 26491 26492 うーん。ble/highlight/layer:syntax/update-word-table の内部で消滅した単語の範囲を 26493 _ble_syntax_word_u{min,max} 及び color_u{min,max} に反映させている。 26494 更に ble/highlight/layer:syntax/word/.apply-attribute 0 "$iN" d を実行して、 26495 color_u{min,max} の内部にある属性を全て消去している。 26496 その後で漸く各単語の属性に基づく着色を計算している。 26497 つまり、消滅単語の範囲が狭すぎる。恐らく単語登録位置の範囲であって、 26498 単語が実際に横たわっていた範囲ではないのである。 26499 26500 然し実際に ble/syntax/vanishing-word/register の実装を見てみると、 26501 ちゃんと wbeg, wend を得てそれに基づいて範囲を更新している。 26502 これが意味する所は何か。消滅した単語がちゃんと登録されていないという事か? 26503 vanishing-word の中で変数を出力してみたが、どうやら lbeg,lend が狭く設定されている所為で 26504 wbeg,wend が狭められてゼロ幅になっている様である。lbeg,lend とは何か。何を目的とした引数か。 26505 26506 確認してみるとどうやら 0:i1 に更新範囲を制限している。 26507 つまり、解析開始点よりも前に位置する消滅単語についてしか消去していない。 26508 これを 0:i2 に拡張したらどうなるだろうか…。もしかすると、 26509 既存の消去しては行けない単語についても消去してしまう可能性もある。 26510 実装について確認する必要がある。 26511 26512 確認すると実際に単語終端が i1:i2 の外にある単語が残っていると、この単語につ 26513 いての着色が消されてしまう気がする。と思ったが、単語終端が外側にあってもそ 26514 の一部が i1:i2 の内側にあるのであれば、必ずその単語は属性再計算の対象になる 26515 のだからちゃんと更新されて然るべきである。うーん。0:i1 で vanishing-word を 26516 制限していたのは単に最初の clear を最小限にするのが目的というだけの気がする。 26517 というか color_u{min,max} を広げれば良いだけの話では? と思ったがどう広げる 26518 のが良いのかという事を考えると結局 vanishiing-word を見て最小限の広げ方に留 26519 めるのが良い気がする。という訳で、やはり vanishing-word の方を広げる事にする。 26520 26521 取り敢えず修正した。効率化する為に syntax:layer/fill も 26522 新しく ble/dense-array#fill-range という関数を作って置き換えた。 26523 動いている。上記の a[a] の着色も { echo; } 3>&1 の着色も直った。 26524 取り敢えずはこれで様子見という事で良い気がする。 26525 26526 * 2020-11-07 highlight: declare 等に指定したオプションの着色についても対応する [#D1420] 26527 →declare の着床は特別にしていると考えていたが実際に見てみると、 26528 通常の引数と同じ仕組みを通じて処理していた。特に CTX_ARGVI も 26529 オプションの判定に含めるだけで対応する事ができた。 26530 26531 2020-11-20 26532 26533 * highlight: bin が存在しないディレクトリで bin/ とした時にエラー着色されなくなっている [#D1419] 26534 26535 どの様に変更して動かなくなったのか調べようとしたが、 26536 逆に今までの実装で何故動いていたのかよく分からなくなった。 26537 今までの実装を見る限りはディレクトリ名でなければやはり着色されない気がする。 26538 26539 * highlight: option を cut/paste すると何故か着色されない [#D1418] 26540 ファイル名に関しても同様に着色されなくなってしまっている。 26541 何が起こっているのかについて調べる必要がある。 26542 26543 そもそも以前の version ではちゃんと動いていただろうか。 26544 やっぱり前の version では動いている。 26545 犯人は一番最後の commit である事も確定した。 26546 そんなに変な変更はしていない筈なので簡単なミスではないか。 26547 然し、何が原因か思い当たる節もない。 26548 同じ単語でも着色される時とされない時があるから、 26549 単語着色の決定自体に問題がある訳ではない気がする。 26550 26551 うーん。どうも comp_words の時点で単語が一つ少なくなってしまっている。 26552 調べると実は別に単語が減っている訳ではない。 26553 ループに戻って確認してみると途中で i が書き換わっている。 26554 変数リークだった。修正した。 26555 26556 2020-11-16 26557 26558 * complete: echo ~ TAB としてメニューを表示した後 [#D1417] 26559 存在しないチルダ展開を試みると ~ が重複して挿入されてしまう問題。 26560 26561 これは何が起こっているのだろうか。 26562 メニューを表示していない時には何も起こらない。 26563 26564 ~x が空の文字列に展開されてその後に文字列が挿入されている可能性? 26565 menu 経由の候補に対する曖昧補完かもしれない。 26566 然し、~x となっている物は展開されない筈だし何かが変。 26567 具体的に何が起こっているのか確かめる必要がある。 26568 26569 メニューから初期化した cand_cand 及び cand_word は特に変な事にはなっていない。 26570 そもそも既存の文字列を保持したまま挿入されるという点が何か変である。 26571 ~1234 が ~~1234 になる。1234 が何処から来たのかという事を考えると、 26572 これは候補から生成された文字列ではない? 26573 26574 調べてみると ble/complete/candidates/determine-common-prefix が既に 26575 ~~1234 という文字列を返している。 26576 26577 * 調べていくと count-match-chars が 0 を返してそのまま結合している。 26578 何故 ~ を共有しているのに count-match-chars が 0 になる? 26579 と思って comp_filter_pattern を確認してみたが何故か空である。 26580 26581 →単に count-match-chars は comp_filter_pattern を使わないからだった。 26582 なので init を実行する必要はない。確認するべきは COMPV でった。 26583 26584 * それから common0 を展開した結果が /home/murase になってしまっている。 26585 うーん。後に何か文字列が続く事によってそこまでの展開結果が変化してしまう、 26586 という状況を今まで考慮に入れていなかった。この場合にどの様に取り扱うのかは微妙。 26587 26588 取り敢えず COMPS で見た時の共通部分は縮約する? 26589 或いはチルダに関しては何らかの特別な取り扱いを行う? 26590 よく考えたらグロブ展開でも同様の事は起こるのではないか。 26591 という事を考えるとチルダに関してだけ特別扱いしても仕方がない。 26592 26593 結局、既存の文字列 ~1234 と共通部分 ~ を比較したい所が、 26594 ~1234 と ~ の比較になってしまっていて、 26595 それが展開されて ~1234 と /home/murase の比較になってしまっている。 26596 26597 うーん。明確な解決方法はない気がするが COMPS を通じて縮約する事にする? 26598 或いは * や ~ などを特別扱いして縮約するか…。 26599 glob を off にして ~ 展開も off にして見る? 26600 26601 →取り敢えず noglob, notilde で展開した結果を用いて挿入を行う事にした。 26602 得られた結果に含まれる *?[ などの glob は全て glob として quote せずに挿入してしまう。 26603 これが意味する所は 'a*b' となっていたとしても、a*b になってしまうという事。 26604 これは実装の制限である。 26605 26606 * complete: source:file の実装で ~+ 等の特別なチルダ展開の候補が列挙されない [#D1416] 26607 26608 これについては一度考察した様な気もするが忘れた。と思って改めて実装を確認し 26609 てみるとチルダ展開による候補生成は ~ 単体でも発生するので、実は ~ だけでも 26610 起動する筈である。しかし実際には動いていない。 26611 26612 x fixed: 動く筈のチルダ展開による候補生成が動いていない。調べてみると 26613 yield-filenames の中で消滅している様だ。更に調べると cand/yield の中で消 26614 滅している。filter:head/test で除外されている様だ。head は実際には何の制 26615 限も行わないという物なので head/test の実装を true に置き換える事にした。 26616 26617 と思ったがそれで良いのだろうか…。現在の実装だと取り敢えず可能な候補を全 26618 て列挙しているので、filter をしない様にすると全て列挙されてしまう。 26619 26620 一方で filter を実行する様にすると filter 側は $COMPV (/home/user) でフィ 26621 ルタしようとしているのに、こちら側は ~user を渡そうとするので常に除去され 26622 てしまう。ちゃんと filter する為には COMPS を用いて filter する必要がある。 26623 →その様に実装した。OK。動いている。 26624 26625 ? ok: head/test を true に置き換える事による影響は? 他の箇所で従来から直接 26626 filter:head/test を呼び出していた箇所での振る舞いが変化してしまわないか確 26627 認する必要がある。 26628 26629 →やはり filter:head を書き換えるのは止めた。filter:none を新しく追加して 26630 最初の候補生成の時にだけ filter:none を指定して、それ以外の filter では 26631 既定で head を使用する事にした。 26632 26633 また、今まで menu-filter は head に一致する物のみを絞り込んでいたが、候補 26634 が全て現在入力済み単語に一致しない場合は、最初に生成された候補を全て表示 26635 する事にした。遡って書き換わる様な候補を補完器が生成したかもしれないし、 26636 もしそうでなくても生成された候補の中から選べる様にするのは一つの手であるから。 26637 26638 もしかすると候補が全く生成されない時には再度補完器を呼び出す様になってい 26639 るかもしれないと思って確認したが、特にそういう事はしていない様だ。よく考 26640 えたらその様に実装すると本当に一致しない文字列を入力した時に、文字を入力 26641 する度に補完器を呼び出す事になって効率が悪い。なのでその様な実装になって 26642 いるとは考えにくい。なので、この可能性は考えなくて良い。(もしそうなってい 26643 たら勝手に全候補を返すという様に振る舞いを変える訳には行かなくなる。) 26644 26645 * complete: CDPATH を設定していると候補が重複して生成される (reported by Lennart00) [#D1415] 26646 https://github.com/ohmybash/oh-my-bash/pull/183 26647 oh-my-bash の Issue を見ていたら偶然発見した。 26648 26649 確かにそうだ。そして . を CDPATH に指定する意味があるのかと思ったが、色々試 26650 してみると、どうやら CDPATH を指定していると現在のディレクトリよりも CDPATH 26651 で見つかったディレクトリの方が優先される。これを防ぐために . を CDPATH に含 26652 めるという方法が使える様である。 26653 26654 後、action:file にして候補を登録しているがこれだとディレクトリが見つからな 26655 いのでエラー着色になってしまう。新しい action を定義する事にする。 26656 26657 * うーん。現在、カレントディレクトリ以下のディレクトリ名については 26658 source:dir を通じて列挙しているが、CDPATH で既に見つかった物と同じファイ 26659 ル名を持つディレクトリについては yield しない様にする必要がある。 26660 26661 どの様に処理するべきだろうか。source:dir で何らかの除外条件を外部から指定 26662 できる様に書き換えるか、或いは source:dir の実装を真似て自前で実装するか。 26663 26664 →改めて自前で complete:cd 内部で source:dir と同様の事を実行する事にした。 26665 一部の共通処理は source:tilde として括りだす。実装した。動いている気がする。 26666 26667 動作確認する。 26668 26669 x fixed: "[[ ${$1[x\$2]+set} ]]: 誤った代入です" というエラーメッセージ。 26670 これは ble/set#contains の内部でのクォート忘れ。 26671 26672 x fixed: cdhist 候補の背景色が濃すぎる気がする→変更した。 26673 26674 x fixed: 現在のディレクトリ由来のファイル名も cdhist 着色になっている。 26675 これはディレクトリ名に付加した / を除去するのを忘れて . と比較していた為。 26676 26677 x fixed: bleopt complete_menu_style=desc にして見た所 segfault した。無限再帰だろうか 26678 →action:cdpath/get-desc を定義する所を action:file/get-desc を上書きしていた。 26679 そして、内部では action:file/get-desc を呼び出していた。 26680 26681 x fixed: やはりg値を合成すると見にくい色になってしまう。 26682 ディレクトリの種類に応じた色は desc の方で着色するべきでは。 26683 26684 * complete (source:file): tilde expansion の補完が filter されずに登録される気がする [#D1414] 26685 26686 際にコードを調べてみると他にも filter されずに登録されてしまう箇所があった 26687 ので一緒に修正した。 26688 26689 flag_source_filter に対する修正はyield-filenames の中ではなくて、 26690 yield-filenames に渡すファイル名を生成している側である呼び出し元で行うべき 26691 である。その様に書き換えた。 26692 26693 2020-11-15 26694 26695 * 2020-11-13 complete: cd の曖昧補完で意図せず遡って書き換わる (reported by cmplstofB) [#D1413] 26696 https://github.com/akinomyoga/ble.sh/issues/67 26697 26698 これは yield で filter する様にした結果である。progcomp は実行する前に 26699 compvを reduce する。一方で source:dir は compv が reduce されていないとい 26700 う前提の下で、maA フラグに従って候補を生成する。その時に filtering は意図的 26701 に offにしている。ここで progcomp の中から source:dir を呼び出すと reduce 26702 されたcompv で生成された候補が全て filter なしで登録されてしまう。 26703 26704 この問題に対する正しい対処法は何だろうか。bash progcomp の枠組みにおける呼 26705 び出しでは、曖昧補完には対応していないので現状通り reduce して良い。 26706 complete:cd に関しては曖昧補完を認識しているので、勝手に reduce しない様に 26707 するべきだろうか。 26708 26709 * complete:* で個別に曖昧補完に対応する? 26710 26711 o ble.sh native な補完設定という事であればそれが自然な気がする。 26712 26713 x 全ての complete:* の実装は曖昧補完に対応する必要がある。ユーザーが補完 26714 を実装するのが面倒になってしまう。 26715 26716 →然し現状ではドキュメントも整備していないし実際に自分で定義しているユー 26717 ザもいないから、破壊的変更は気にせずできる。 26718 26719 →ユーザが真面目に実装していなかった場合には head に対応する候補が毎回 26720 生成されるだけなので 2回目以降の呼び出しでは filter されて何も生成さ 26721 れない。処理時間が無駄に増えるだけである。ユーザの入力があれば候補生 26722 成を停止している様にしているので見た目の動作としては何も問題は発生し 26723 ない。 26724 26725 取り敢えずその様に書き換える事にしたい。この時、reduce はもっと後で実行する必要がある。 26726 26727 →実装を確認してみた所、実は progcomp は COMPS, COMPV を全く参照していな 26728 い? つまり、単純に COMPS, COMPV に対する補正をしない様に変更すればOK? 26729 26730 色々書き換えた。結局、COMPS, COMPV はそのままにして、comp_* の方を適当に 26731 reduce した物に書き換える事にした。これで問題は起こらない筈。元のデータを書 26732 き換えていないし、bash progcomp と blesh progcomp で同じ変数を見ているので、 26733 両者で曖昧補完に対応した補完実装もできるし、対応していない補完実装もできる。 26734 26735 以下デバグに使った .bashrc の設定 26736 26737 | # bashrc 26738 | 26739 | blehook/eval-after-load complete debug1 26740 | debug1() { 26741 | ble/cmdinfo/complete:cd() { 26742 | local ret 26743 | ble/complete/source:file/.construct-pathname-pattern "$COMPV"; local pattern=$ret 26744 | ble/debug/print-variables COMPS COMPV pattern 26745 | ble/complete/util/eval-pathname-expansion "$pattern/" 26746 | ble/debug/print-variables ret 26747 | ble/complete/util/eval-pathname-expansion "$pattern" 26748 | ble/debug/print-variables ret 26749 | } >> a.txt 2>&1 26750 | } 26751 | 26752 | comp1() { 26753 | ble/debug/print-variables COMP1 COMP2 comp_type 26754 | ble/debug/print-variables comp_cword comp_words 26755 | ble/debug/print-variables COMP_CWORD COMP_WORDS 26756 | } &>/dev/tty 26757 | complete -F comp1 comp1 26758 26759 * complete: 一旦 option の補完を実行すると bleopt complete_menu_style が書き換わる [#D1412] 26760 26761 local bleopt_complete_menu_style として書き換わらない様にしている筈なのに。 26762 これは auto_complete 経由で書き換わっている? 26763 →やはり auto-complete であった。修正した。 26764 26765 * syntax: simple-word でない時にエラー着色になってしまう (reported by cmplstofB) [#D1411] 26766 https://github.com/akinomyoga/ble.sh/issues/68 26767 26768 #D1409 の書き換えに伴うバグだろう。 26769 26770 これは簡単なミスだった。is-simple のチェックが抜けていた。locate-filename 26771 を使う場合は内部で is-simple に相当するチェックを行っていたが、それ以外の単 26772 語全体をファイル名として判定する場合には is-simple チェックがなくなっていた。 26773 直した。 26774 26775 2020-11-12 26776 26777 * syntax: オプションの単語着色にも対応したい [#D1410] 26778 26779 コードを少し確認してみたが複雑になりそう。- で始まる物については強制的にオプ 26780 ションと見做す様にする。但し、-- が途中にある場合には着色しない様にする。 26781 26782 と思ったがその様に実装する為には、コマンド抽出をして -- がないかどうか確認す 26783 る必要が出てくる。つまり、処理が重くなる可能性があるという事? と思ったが現在 26784 の実装ではコマンド抽出はどうなっていたのだったか。独自の着色を許すのだとした 26785 ら何れにしてもコマンド抽出を始めに実行しなければならない。そして各単語につい 26786 て毎回コマンド抽出をしていると非効率である事から、普通に考えて単語情報はちゃ 26787 んと既にあると考えるのが自然。現在の実装を確認。 26788 26789 呼び出し元で -- の確認をしてオプションを付加するのが良い気がする? 実装を確認 26790 してみたが、単に各単語について word:default を呼び出しているだけであった。つ 26791 まり、つまり単語について調べる必要がある。 26792 26793 実装してみたが微妙。途中に = や : がある場合は除外している。本来は = の左側 26794 と右側で独立に着色を決定したい。右側も着色する為には右側に対してパス名の着色 26795 を適用できる様にしなければならない。 26796 26797 パス名については =, : で区切って着色を与えているが最後のパスしか着色していな 26798 い。パス名の着色について再考してから対応する必要がある気がする。 26799 26800 → #D1409 で一緒に実装した。 26801 26802 * -- という引数が指定された後はオプションとして解釈しないという処置が未実装。 26803 →対応した。 26804 26805 * mandb による補完候補の着色にも同じ色を用いる。 26806 26807 * highlight: =, : で区切られたパス名の着色について再考 [#D1409] 26808 26809 現在の実装では locate-filename で最初に全体に一致を試みて、それから次に先頭 26810 から順に削っていくという方法になっている。この様になっているのは 26811 https://... 等の形式の URL または C:\... の形式のファイル名を認識する為であ 26812 る。これを拡張して任意の場所で切れる様にするにはどうしたら良いか? 26813 26814 例えば A:B:C となっていたとする。できるだけ長く一致させたいので A:B:C から順 26815 に試していく? A:B, A と試して、駄目であれば B:C, B, C という順に試していく。 26816 途中で一致した場合にはそれで確定して、未処理の文字列についてまた続きから試す。 26817 26818 現在の実装では =, : を等価に取り扱っているが、= は最初の一つだけ処理する様に 26819 したい。或いは、最初に = で分割して、その後で : で分割する? 何だかよく分から 26820 ない。。。というより、= については左辺の形に制限を加えるべき。変数代入形式か、 26821 或いは -[-[:alnum:]_]+ で一致させる事にする。 26822 26823 a. ^-[-[:alnum:]_]+= に一致する場合には、= 以前を強制的にオプション着色にす 26824 る。この場合には右辺の中の = は分割に寄与しない。右辺は : で分割しても良い。 26825 b. ^[[:alnum:]_]+= に一致する場合には全体をファイル名と見做しても良いし、或 26826 いは、右辺をファイル名と見做しても良い。右辺は : で分割しても良い。 26827 c. それ以外の場合には = は分割でない。: で分割しても良い。 26828 26829 1 先ず初めにオプションに一致するか確認して、もし一致したら其処までを処理済みにする。 26830 2 オプションに一致しない場合には変数代入の形式になっているか確認して、 26831 もし変数代入の形式であれば = を可能な分割点の候補として登録する。 26832 3 残りの部分は : を分割点の候補として登録する。 26833 4 分割点の候補を元にしてできるだけ長く一致させる。 26834 26835 eval の戦略についても考える必要がある? 分割点が決まったら先に各要素を eval 26836 してしまうか、或いは、試行の度に eval を実行するか。うーん。各要素を eval し 26837 てから繋ぐ事を考えていたが、実は試行の度に eval しても良いのではないかという 26838 気がしてきた。OK 26839 26840 * done: ble/syntax/progcolor/wattr#* の整備 26841 26842 次に考えるべき事。各パス要素毎に着色をするとすると、前のパス要素の結果を明 26843 示的に処理しなくても自動で構築できる様な方法で登録する必要がある。 26844 26845 wattr を動的に構築できる様に枠組み (ble/syntax/progcolor/wattr#*) を整えた。 26846 先ずは既存の振る舞いを壊さない様に wattr#* に移行する。以前よりもコードが 26847 すっきりした。 26848 26849 更に progcolor/word:default についても全体に wattr#* を使う様に書き換えた。 26850 前より少しぐちゃっとしている気がしないでもないが、恐らく慣れの問題だろう。 26851 客観的に考えれば変数の変な取り回しも除かれて前よりも整理されている筈。 26852 26853 オプションの着色は後回しにして、取り敢えずパス名の着色について再度。 26854 26855 取り敢えず = による分割は確定という事にして、探索は : 区切りだけにする。或い 26856 は , も区切り文字として解釈しても良いかもしれない。というのも、 26857 -Wl,-rpath,... 等の様なオプションの指定の仕方をする事がある為。 26858 26859 * done: locate-filename を複数のパスを抽出する様に書き換える。 26860 →書き換えた。ret は配列になり第一要素は今迄と同じく範囲の開始である。 26861 但し、最後の範囲ではなくて最初の範囲の開始である事には違いがある。 26862 これだと範囲の開始点以降全てをファイル名とみなす実装に於いて問題が出るが、 26863 関数の意味的にはそんなに変な拡張ではないので良しとする。 26864 26865 * done: locate-filename を用いて新しく各パス要素を着色する様に変更した。動い 26866 ている。古い実装はもう削除しても良い様な気がしている。オプションに関しても 26867 ちゃんと動いている。 26868 26869 * ok: highlight: echo hello:~ において ~ の着色が行われない。と思ったが、こ 26870 れは恐らく意図した振る舞いである。と思ってコードを確認したが、やはりちゃん 26871 と処理していない気がする。変数代入形式の時には ~ を有効にしたい。と思って 26872 実際に試してみるとちゃんと変数代入形式の場合には ~ の着色が有効になってい 26873 る。これについてはどうやって実現されているのか改めて確認が必要である。 26874 26875 →これについては分かった。文法解釈を参照して tilde がチルダ展開の物かどうか 26876 判定している。この実装で良い。 26877 26878 x fixed: パス要素が誤っている場合に locate-filename でファイル名と検出されず 26879 に着色されない。この場合には途中の正しいディレクトリ名までは着色したいが、 26880 全体が無効な文字列となってしまっているので全く着色されない。 26881 26882 認識できないパスに関してはどの様に取り扱うか。: で強制的に区切って着色する 26883 か、或いは greedy に探索して駄目だった所からまた : を見つけて着色するか。 26884 自然な振る舞いになる様にしようとすると後者になるが、実装が複雑になる。もし 26885 その様に実装するのであれば、: で区切ってから着色するのではなくて、最初から 26886 / と : で区切りながらパスを着色して行く実装にするべきだった。 26887 26888 うーん。再実装するべきだろうか。再実装するとするとファイルが存在しない時の 26889 取り扱いについて確認が必要。コマンド名の時にはエラー着色にしていた。然しコ 26890 マンド名は : による分割の対象ではないので問題ない。 26891 26892 うーん。どうするのが良いか。: で区切るという規則の引数の場合には何れにして 26893 も : で分割する。ファイルが存在するかしないかで : で区切るかそうでないかが 26894 変わるという事はありえない。一方で URL を受け付ける様な引数の場合には : で 26895 区切るという事はない。色々考えると、URL 判定は : で区切った後に実行するの 26896 ではなくて、最初に実行するべきなのでは。URL に一致しない時に指定された引数 26897 が : で区切ったパスなのかそうでないのかの判定が現在の問題である。 26898 26899 うーん。結局全体が一致しなければ即座に : 区切りであると判断して良いのでは 26900 ないだろうか。と思ったが新しい未だ存在していないファイルを指定する場合で、 26901 ディレクトリ名に : が含まれている場合には全体を path として取り扱っても良 26902 いのではないだろうか。つまり、先ず初めに / で切りながら存在するディレクト 26903 リまで取得を行う。ディレクトリが存在しなくなってそれ以降に : が含まれてい 26904 たら : で区切られる物と見做す。ディレクトリ名に : が含まれていた場合には強 26905 制的に : は無効で良いのではないか。整理すると以下の様になる。 26906 26907 1 最初に全体に対して URL 判定 / C:\... 判定を行う。 26908 2 / で切りながら存在するディレクトリまで読んでいく。 26909 3 (2) のディレクトリ名に : が含まれていれば : 区切りではない。 26910 4 (2) の残り部分に : が含まれていれば : 区切りである。 26911 つまり存在するパスに : が含まれず存在しない部分に 26912 : が含まれる時にのみ : 区切りである。 26913 どちらにも : が含まれない時にはどう取り扱っても良いので、 26914 実際の所は、存在するパスに : が含まれていれば : 区切りではない。 26915 : が含まれていなければ : 区切りである。という判定で良い。 26916 26917 x ok: 実装してみたがかなり遅い。と思ったが、これは eval の中でグローバル変数 26918 の復元等の複雑な処理を行っている為である。$HOME などのパラメータ展開が存在 26919 する場合にはそんなには遅くならない。 26920 26921 これに関してはまた別の課題として後で考える事にするのが良い。 26922 26923 x detect-separated-path を実装したら動かなくなっている。常に単一パスと判定さ 26924 れている。調べたら detect-separated-path の中でファイルが存在しているかど 26925 うかの判定をするのを忘れていた。常に存在する取り扱いになっていた。修正した。 26926 26927 しかし、未だ動かない。今度は locate-filename が動いていない気がする。丁寧 26928 に見てみると実は wtxt を更新するのを忘れていた。直した。今度は動いている。 26929 26930 うーん。PATH=... の場合にはこれで動く様になったが、今度は通常の引数の場合 26931 に全く動いていない。prefix が存在しない場合でも動かなくなっている。何故だ 26932 ろう。 26933 26934 * syntax: [:alnum:] 等を使ってしまったが [#D1408] 26935 26936 良く考えたら locale 依存で変な文字も含むのでやはり直接 a-zA-Z0-9 等と指定す 26937 る必要がある。 26938 26939 →これは全体的に書き直した。vi.sh の [:alnum:] は vim の単語の判定に似せた物 26940 なので [:alnum:] で良い。decode.sh に残っている [:alnum:] に関しても、通常文 26941 字でない事の判定なのでそのままで良い。 26942 26943 2020-11-11 26944 26945 * global: 改めて ble/bin/* の使用について確認する [#D1407] 26946 26947 core-syntax.sh に関しては #D1406 により完全に ble/bin/* は排除した。 26948 26949 edit.sh に関しては 26950 26951 - bash-4.3 以下で ttyname を取得する為に tty を使用している 26952 - command-help を表示する為に awk, man を使用している。 26953 - removed: suppress_bash_output の終了処理で rm を使用している。 26954 実はこれは _ble_base_run の一括の削除に任せれば良いのではないか。 26955 →うーん。やっぱりそうだ。$_ble_base_run で削除されるのだから 26956 わざわざここで rm を呼び出す必要はない。 26957 ファイルの存在・非存在が振る舞いに影響を与える物でもない。 26958 一応中身をクリアしておく事にする。 26959 - bash-3.2 以下では C-d を捉える為に色々していて、その為に 26960 grep, rm, mkfifo を使っている。これは仕方がない。 26961 26962 ble.pp 26963 26964 - rm, mkdir, chmod, readlink: ble.sh のディレクトリの初期化・終了処理 26965 26966 def.sh 26967 26968 - blehook/.compatibility-ble-0.3/check: cat (ユーザーにメッセージを表示する) 26969 26970 util.sh 26971 26972 - ble/util/declare-print-definitions: awk 26973 declare -p の出力結果のバグを修正する為に用いている。 26974 - ble/util/strftime (bash-4.1 以下): date 26975 - ble/util/msleep (bash-4.3 以下): rm, mkfifo, sleep, sleepenh, usleep, etc. 26976 - ble/util/getmtime: date, stat (この関数自体使われていない) 26977 - ble/term/stty: stty ユーザーコマンドを実行する時の環境の調整 26978 26979 decode.sh 26980 26981 - ble/decode/nonblocking-read: od (大量の入力があった時の処理の為) 26982 - ble/decode/cmap/initialize: awk (cmap キャッシュ初期化) 26983 - ble/decode/bind/.generate-source-to-unbind-default: (初期化) 26984 - ble-bind -L: sed 26985 - ble/builtin/bind/.reconstruct-user-settings: sed, cat, mv, awk 26986 26987 benchmark.sh 26988 26989 - (diagnose) ble-measure: awk (小数の計算) 26990 26991 history.sh 26992 26993 - awk, mv, sed, wc 26994 26995 core-complete.sh 26996 26997 - (performance) grep, sed, awk, sort 26998 - (mandb) man, gzip, nroff, mkdir 26999 27000 取り敢えず wiki/Note.md にまとめた。 27001 27002 * 他に > でリダイレクトしている箇所がまた現れていたのでこれを >| に修正する。 27003 27004 * syntax: enable -p | grep で builtin を判定しているのは何故か [#D1406] 27005 27006 core-syntax.sh 及び edit.sh (command-help) で以下の様な判定をしている。 27007 27008 enable -p | ble/bin/grep -q -F -x "enable $cmd" &>/dev/null 27009 27010 何故単に type -t $cmd を用いなかったのか。或いは初期からあったコードの可能性 27011 もある。と思ったが 3 forks + 2 exec と書いている事から速度については意識して 27012 いた筈の気もする。どの時点でこのコードになったのか経緯を調べる必要がある。 27013 27014 変更履歴を辿ると以下の様になっている。 27015 27016 9aa1e267 (Koichi Murase 2015-02-16 03:55:37 +0900 2396) elif enable -p | fgrep -xq "enable $cmd" &>/dev/null; then 27017 a4f89a71 (Koichi Murase 2015-12-03 08:10:41 +0900 4425) elif enable -p | command grep -q -F -x "enable $cmd" &>/dev/null; then 27018 1649187a (Koichi Murase 2018-02-12 13:52:39 +0900 5832) elif enable -p | ble/bin/grep -q -F -x "enable $cmd" &>/dev/null; then 27019 27020 9aa1e267 は一番最初に ble-syntax.sh を repository に追加した commit である。 27021 つまり、enable -p の使用は一番最初期のコードの名残である。 27022 これは type -t $cmd を用いた実装に切り替えて良い気がする。 27023 27024 と思ったが微妙。どうも keyword が quote されていてコマンドとして取り扱う必要 27025 がある時に、どうやってそのコマンドの種類を特定するのかという話の様だ。 27026 loadable builtin で keyword と同名のコマンドをロードしていた時にどの様に取り 27027 扱うのかという事。type -tは "keyword" を返すので使えない。 27028 27029 * 実際にダミーの builtin を作成して試してみる? Cygwin で builtin をコンパイ 27030 ルしようとしたらできない。昔コンパイルした様な気がする。その時にはどうした 27031 のだったか。libbash.dll 的な何かを作った様な気がする。 27032 27033 ? と思ったが bash の既定の loadale builtin ではどの様にコンパイルしている 27034 のだろうか。或いは、実は cygwin 上では loadable builtin はコンパイルしな 27035 い? →実際に確認した所コンパイルされていない。Makefile は生成されている 27036 のでディレクトリに入って make して見るが、そうするとやはり同様のエラーが 27037 出てコンパイルできない様だ。 27038 27039 bash の Makefile に ($(Program) に対するルールを弄って) 以下を追加して libbash.dll を得た。 27040 27041 libbash: libbash-5.0.11.dll 27042 libbash-5.0.11.dll: .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP) 27043 $(PURIFY) $(CC) $(BUILTINS_LDFLAGS) $(LIBRARY_LDFLAGS) $(LDFLAGS) -shared -o $@ $(OBJECTS) $(LIBS) 27044 27045 これに対してリンクしてビルドすると一応ビルドはできた。然し実際に実行してみ 27046 ようとすると先ず libbash-5.0.11.dll が存在しないとロードに失敗する。そして 27047 実際に実行してみると libbash-5.0.11 の内部の変数に対して処理を実行している 27048 様で、本体の bash に対して変数に対するアクセスが反映されていない。駄目だ。 27049 27050 唯、keyword と同名の物が存在する時にどう振る舞うのかについての実験はできる 27051 だろう。これで実際に簡単なコマンドを作成して実行してみる事にした。hello と 27052 いう名前の builtin コマンドは無事に作成して呼び出す事ができたが、time や 27053 while と言った名前のコマンドについては駄目。enable -f でロードする所までは 27054 できるが、実際に呼び出そうとするとコマンドが見つかりませんでしたというメッ 27055 セージが出て実行されない。 27056 27057 これは cygwin 特有の問題だろうか。chat でも試してみたが駄目だった。 27058 bash-3.0 でも振る舞いは同じである。つまり、enable -p で確認するとちゃんと 27059 出力されていたとしても keyword と同名のコマンドは定義しても使えない。 27060 27061 % 結局、enable -p は実際にその builtin が使えるかどうかの判定には使えない。 27062 % 表示されていても keyword に一致するコマンドは実行する事ができないからで 27063 % ある。 27064 27065 と、思ったら 'while' を上書きするとコマンドが見つかりません、という状態に 27066 なるが、'time' というコマンドを上書きするとちゃんと動く。'while' を続けて 27067 ロードすると 'time' までも使えなくなってしまう。Cygwin でも再現した。 27068 27069 試してみて分かった事は enable -p はコマンドを実際に使えても使えなくても表示 27070 してしまうが、enable "$cmd" はコマンドが有効でないと失敗するという事。 27071 27072 うーん。分かった。type -a -t $cmd を実行すれば良い。実際に使える時に2番目以 27073 降にちゃんと候補が表示される。ちゃんと 'while' をロードすると他も使えなくな 27074 るという振る舞いも type -a に反映されている。どうせなので ble/util/type で 27075 -a を指定して全ての候補について取得してしまう事にした。 27076 27077 2020-11-06 27078 27079 * complete: コマンドラインオプションの説明を表示する機能 [#D1405] 27080 https://www.reddit.com/r/bash/comments/joafpu/is_it_possible_to_achieve_zsh_like_completion_in/ 27081 27082 やはりそういった要望は存在する物である。 27083 27084 x 然し、問題は man から抽出するにしても --help から抽出するにしても、別にこ 27085 れらのファイルは文法が決まっている訳でもないので、抽出ミスが生じる可能性が 27086 あるという事である。 27087 27088 man (roff) の形式の方が未だ信頼性はある。然し、サブコマンドのオプションを 27089 拾う可能性や諸々がある。更に -- の後に続く引数がオプションとして取り扱われ 27090 るかそうでないかというのもコマンドに依存して色々だろうと考えられる。これら 27091 に対する完全な解は存在しないと思われる。或る程度の間違いをユーザに許容して 27092 もらわなければならない。これに関してはオプションでユーザに有効化してもらう 27093 事にするのが良い気がする。 27094 27095 x 更に言うと --help を認識しないコマンドで勝手に実行すると困るものだって存在 27096 するかもしれない。例えばユーザーが作った command.sh 等のような物は引数を水 27097 に既定の処理を実行する物だって存在する。という事を考えると勝手に知らないコ 27098 マンドに対して --help をつけて呼び出す訳には行かない。 27099 27100 zsh でどうなっているのか調べてみる。autoload -U compinit; compinit とすると 27101 初期化される? オプションを補完している時にはオプション名と説明が表示されるが、 27102 ファイル名が表示されている時にはファイル名だけが表示される。何を補完している 27103 かに応じて表示の形式を変更している様である。そもそも引数が - で始まらない場 27104 合にはオプション名は補完候補に出さない。また - で始まる引数の場合には通常の 27105 ファイル名は補完候補に出さない。という具合に排他的になっているからである。 27106 27107 ble.sh の argument でもその様に実装して良いのかもしれない。現在の実装だと - 27108 で始まる引数であってもファイル名に曖昧補完してしまって使いにくい。- で始まる 27109 場合には専らにオプションとして補完するのが自然だろう。 27110 27111 zsh のオプションの説明は grep で確認した所 man でも --help でもない。どうも、 27112 自前で用意した説明を表示している可能性? 27113 27114 * man の解析 27115 取り敢えず ble.sh では man を解析するという具合にしても良い気がする。 27116 man の解析は…awk を使っても良いだろうという気がする。 27117 然しその前に man の文法についてちゃんと調べておく必要がある気がする。 27118 27119 - .XX は特別に処理する必要がある。 27120 - \- は - に置換する。 27121 - \^ は空文字列に置換する。 27122 (grep の man で -- が \-\^\- とエスケープされている。\-\- だと駄目な理由が存在する?) 27123 groff を見ると \^ はとても小さな空白 (1/12em よりも小さい)という事になっている。 27124 - [ や ] の周辺の空白は除去する。 27125 - "..." はそのまま表示する。 27126 27127 groff のマニュアルを見ても .TP 等は載っていない。 27128 https://man7.org/linux/man-pages/man7/roff.7.html に載っている .XX には 27129 結構 man で使われている物が載っているがそれでも .TP は載っていない。 27130 27131 - https://linuxjm.osdn.jp/html/LDP_man-pages/man7/man.7.html に .TP が載っている。 27132 https://linuxjm.osdn.jp/html/GNU_groff/man7/groff_man.7.html にも説明が載っている。 27133 どうやら -mNAME でマクロ定義ファイル NAME.tmac を読み込む事ができて、 27134 man の指定は an.tmac というマクロファイルにあるので roff のオプションに 27135 -man と指定できるという仕組みになっている様である。 27136 27137 - 様々の複雑な指定が存在している事を考えると man のソースではなくて、 27138 man の出力を見るべきだろうか。うーん。或いは、 27139 自前で色々弄った後に groff に食わせる。groff -Tascii -man file.1 で行ける。 27140 試しに適当な内容を作って groff に食わせたが何も起こらない。 27141 どうも .TH で最初にページ名などを初期化しなければならない様だ。 27142 groff がない場合はどうするのか。troff と nroff を試してみたが、 27143 troff はよく分からない出力結果になった。nroff は groff と同じ結果。 27144 調べると troff は印刷専用のようである。 27145 27146 うーん。候補と表示内容を変更したい時にはどうすれば良いか。 27147 既存の物でそれを実行していた物があったような気もするし、 27148 なかった様な気もする。表示内容を勝手に変更した時の問題は、 27149 部分一致の太文字を表示できなくなるという事。 27150 という事を考えるとやはり候補と表示内容は一致させている気がする。 27151 27152 →と思ったら init-menu-item で prefix と suffix を指定する事ができる。 27153 ここで [=WHEN] だとかその他諸々を記録すれば良い。 27154 27155 取り敢えず補完の表示に必要な情報は抽出できた様な気がする。 27156 然し問題点はこれをどのように bash の配列に記録するのかという事。 27157 例えば抽出した情報はファイルに保存しておく。 27158 補完を実行する時にその情報を読み取り候補生成する。 27159 全てのデータを DATA に保存してしまう事にすれば良い気がする。 27160 27161 * 指定したコマンドに対応する man を探し当てる方法? 27162 MANPATH 及び /usr/share/man を探す? 27163 man1, man8 の辺りを探索すれば良い気がする。 27164 : で区切られたパスからファイルを探す関数は既にあっただろうか。 27165 ない気がする。新しく実装して良い気がする。 27166 27167 manpath は /etc/manpath.config), ~/.manpath, MANPATH 27168 /usr/local/etc/man_db.conf など様々な場所に保存されている? 27169 どうやら man -w で manpath 一覧が出力される様だ。 27170 更に man -w grep 等で実際のファイルの場所が出力される様だ。 27171 然し、これは POSIX ではない様である。 27172 27173 従って、(1) man -w grep を試す (2) man -w を試す (3) /etc/* を読み取る (4) 27174 MANPATH を参照する…。と思ったが、/etc/* の中身は結構複雑である。そもそも 27175 /etc/* の設定に対応している man 実装は高機能なので -w ぐらい対応していても 27176 良い気がする。殊更に独自実装をする必要はないのではないか。単に 27177 /usr/share/man:/usr/local/share/man:/usr/local/man を探索すれば良いのでは 27178 ないだろうか。→その様に実装した。実は簡単だった。わざわざパス検索用の関数 27179 を用意する程でもない? 27180 27181 これ以降の変更は core-complete.sh に対する変更が必要なので取り敢えずここまで。 27182 27183 * 実際に得られた結果を用いて実装した所、呆気なく動いている様な気がする。 27184 27185 x done: 但し、説明を表示する為には bleopt を desc-raw に設定していなければな 27186 らない。という事を考えると menu_style を動的に変更できる仕組みを整えるべき 27187 かもしれない。然し、menu_style が動的に変わってしまうと問題になるので、 27188 menu の何処かに記録しておく必要がある…と思ったがそれは既にその様にしてい 27189 る筈。これも簡単に対応できた。 27190 27191 * complete: filter を cand/yield の中で実行する枠組みを整える (motivated by timjrd) [#D1404] 27192 27193 filter:substr に対して source:file がより緩い条件で候補を生成したとしても、 27194 後の filter:substr/filter で除外されてしまう。そもそも後で一括して filter す 27195 る事自体が物事を複雑にしている。cand/yield で cand_cand その他に登録する時点 27196 で filter してしまって良い様な気がする。 27197 27198 更に、source:file でフィルタを実行しても良いという事を確かめる必要がある。 27199 27200 先ずその様に書き換えても問題が起こらないかを確認する。 27201 27202 * 先ず filter でやっている事を確認する。 27203 27204 filter-by-regex は cand_cand に対してフィルターを実行している。 27205 filter-word-by-prefix は cand_word に対してフィルターを実行している。 27206 →これは別の filtering で使っている物であって関係ない。 27207 cand_cand は補完単語を格納していて、cand_word が実際に挿入される文字列を格納している。 27208 filter-by-command はコマンドを指定できる物である。 27209 実際に使っているのは filter:substr 27210 27211 * 問題がある。独自に filter すると filter:substr/match の実装が乖離してしまう。 27212 つまり、メニュー選択で太字の着色がなされなくなってしまう。 27213 候補ごとにフィルターを記録する様にするとまた面倒になる。 27214 27215 或いは始めから一致位置を計算して記録する事にする? 然し実際には使われない事 27216 の方が多いのでやはり重さを考えると一致位置を一緒に計算するのは避けたい。 27217 action に処理を紐付ける事にする? 然し filter の種類の情報も記録しなければならない。 27218 27219 取り敢えず独自にフィルターを実行するかどうかはさておき、 27220 cand/yield の内部でフィルタを実行するという実装にはする。 27221 そちらの方が自然だからである。 27222 27223 * done: comp_filter_type と comp_filter_pattern の宣言されている場所、 27224 代入されている場所、使用している箇所を確認する。 27225 現状では別々の場所で宣言・代入しているが、 27226 両者の取り扱いを統一できればしたい。 27227 27228 comp_filter_type について先ず調べる。 27229 27230 宣言 ble/complete/candidates/generate-with-filter 27231 ここで宣言したものは以下で使用されている。 27232 使用 ble/complete/source:* 27233 27234 通常の補完の場合にはどうだったかと思ったが、 27235 調べてみると head フィルタを使っていたので、 27236 ちゃんと ble/complete/candidates/generate-with-filter 27237 を経由して呼び出されていた。 27238 27239 ble/complete/source:* の呼び出し元は他には存在していない。 27240 27241 宣言 ble/complete/menu-complete.class/render-item 27242 ここでの宣言・設定はこの関数の中で閉じている気がする。 27243 ややこしいのでこれは単に filter_type 等に変更するのが良い気がする。 27244 宣言 ble/widget/auto_complete/self-insert 27245 ここでの宣言・設定もこの関数の中で閉じてはいるが、 27246 comp_filter_pattern については共有している。 27247 対称性を考えるとこのまま comp_filter_type で良い気がする。 27248 27249 comp_filter_pattern について次に調べる。 27250 27251 宣言 ble/widget/complete 27252 宣言 ble/complete/menu-filter/.filter-candidates 27253 宣言 ble/complete/auto-complete/.check-context 27254 宣言 ble/widget/auto_complete/self-insert 27255 宣言 ble/complete/source:sabbrev 27256 27257 どうやら兎に角 filter を呼び出している箇所で全て宣言している様である。 27258 27259 設定 ble/complete/candidates/filter:*/init 27260 使用 ble/complete/candidates/filter:*/filter 27261 使用 ble/complete/candidates/filter:*/test 27262 27263 実際の値の設定などに関しては filter 内部で閉じている。 27264 27265 filter の関数を呼び出している箇所は多岐に渡る。 27266 27267 ble/widget/complete 27268 ble/complete/insert-common 27269 ble/complete/candidates/determine-common-prefix 27270 ble/complete/cndidates/filter:*/count-match-chars [OK] 27271 ble/complete/insert-braces 27272 ble/complete/insert-common.. 27273 27274 ble/complete/menu-complete.class/render-item 27275 ble/complete/cndidates/filter:*/match [OK] 27276 27277 ble/complete/menu-filter/.filter-candidates 27278 これは内部で宣言・使用する事にした。 27279 27280 ble/widget/auto_complete/self-insert 27281 これも内部で宣言・使用する事にした。 27282 27283 関数 ble/complete/menu/generate-candidates-from-menu 27284 27285 ここで comp_filter_pattern の値を復元しようとしているが、実際には空の値 27286 を設定している。source の内部でしか使わないからというコメントが書かれて 27287 いるが、実際には insert-common の内部でcount-match-chars を使っている。 27288 と思ったが、count-match-chars は実は comp_filter_pattern は使っていなかっ 27289 た。従って comp_filter_type も comp_filter_pattern も使っていない。代わ 27290 りに、自分で filter_type も自分で明示して呼び出す必要がある。 27291 27292 実は全く使っていないのであればそもそも comp_filter_pattern を設定する必 27293 要はないのでは。というより ble/widget/complete の内部で宣言する必要はな 27294 いのではないか。 27295 27296 うーん。ble/complete/candidate/filter:*/init 等の呼び出しを実行する 27297 関数を追加してしまう? comp_filter_type はその時に pattern と一緒に宣言する。 27298 27299 ble/complete/candidates/filter#init head "$COMPS" 27300 ble/complete/candidates/filter#apply 27301 ble/complete/candidates/filter#test "$cand" 27302 27303 match, count-match-chars は stateless なので直接呼び出して使う事にする。 27304 27305 * done: 現在 comp_filter_pattern は ble/widget/complete の内部で宣言しているが、 27306 これは実際に filter を使う箇所で宣言するだけで良いのではないか。 27307 改めて filter#* が使われている箇所を確認する。 27308 27309 - ble/complete/candidates/generate-with-filter 27310 comp_filter_type, comp_filter_pattern は ble/widget/complete ではなく 27311 generate-with-filter の内部で宣言する事にした。 27312 - ble/complete/menu-filter/.filter-candidates 27313 これは既にその場で宣言している。 27314 - ble/widget/auto_complete/self-insert 27315 これも既にその場で宣言している。 27316 - ble/complete/source:sabbrev 27317 これは source の内部なので comp_filter_type, 27318 comp_filter_pattern は既に宣言されている。 27319 27320 次に cand/yield の内部で filter を実行する様に変更する。 27321 27322 * done: その様に変更した。というより一行追加しただけである。 27323 同時に複数の関数が不要になった気がする。 27324 大分コードが綺麗になった気がする。 27325 27326 ? cand/yield で filter するとしても、menu-filter では結局 filter されてしま 27327 う。従って menu-filter でも filter 方法を変更する必要があるのではないか。 27328 27329 或いは substr では候補を何も生成せずに hsubseq まで行ってから substr に相 27330 当する候補を生成して、もし何もなければ本来の subseq や hsubseq を生成する 27331 という方針も考えられる…。と思ったが、そうすると別の source による結果が 27332 存在する時に substr でそちらの候補だけが表示される事になり不自然な結果に 27333 なる。 27334 27335 そもそも曖昧補完の substr で path component 毎に substr にして生成する必 27336 要性があるだろうか。考えてみたが余り複雑な事をしてもユーザがついて行けな 27337 い。という事を考えると、やはり *dir1/dir2/file* の形式だけを取り敢えず許 27338 すというので良いのではないか。或いは何も生成しない。 27339 27340 % source 側で(既定と異なる) filter するに当たっての現状の問題点は以下の二つ 27341 % 27342 % * menu-filter で結局通常の filter 動作で除外されてしまうという事 27343 % * menu の着色でどのように一致したのかの着色が正しく反映されない事 27344 % 27345 % * 共通部分の何処までを挿入するかの決定。 27346 % 27347 % これは実は各候補毎に決定しているのではなくて共通の設定として決定しているの 27348 % で、単純に source:file に合わせて計算するという事はできない。これは遡った 27349 % 書き換えが起こった時に今までの候補生成ができなくなる事を防ぐ為のものなので 27350 % 特別な処理はしなくて大丈夫な気がする。しかし source:file の様に足並みを外 27351 % すような物があった場合に本当に正しく動くのかに関しては注意が必要である。 27352 % 27353 % そもそも共通部分の挿入によって候補生成が破壊されるのはどのような時だったか。 27354 % うーん。分かった。まず最初に通常の common-prefix を求めているが、曖昧補完 27355 % の場合には必ずしも common-prefix が元々の COMPV の文字を全て含んでいるとは 27356 % 限らない。(本来は common-prefix ではなくて common subseq に対応する何かを 27357 % 求める必要があるが、展開などを考えると難しいという事か)。 27358 % 27359 % DATA 経由で特別な動作を実装する? 27360 % 27361 % * source:file は action:file 及び action:tilde を生成している。 27362 % と思ってよく見てみると action:tilde の場合にはチルダ展開のみしか 27363 % 候補生成していないので、実際には action:file を気にすれば良い。 27364 % 27365 % 一方で source:glob も action:file を生成している。 27366 % source:glob については曖昧補完の時には候補を生成していない。 27367 % 27368 % 何れにしても action:file に対して DATA を指定している物は存在していないので、 27369 % 気にせずに DATA に新しく filter_type 等指定しても良い気がする。 27370 % と思ったら source:argument も file を生成している。 27371 % 27372 % 自前の filter を実行しているかどうかに関しては、 27373 % cand/yield の時点で判定可能なので、内部で処理する? 27374 % と思ったが自前でフィルタしていても元のフィルタの振る舞いに準拠している可能性もある。 27375 % その場合には自分で処理するのではなくてやはり既定の filter に処理してもらいたい。 27376 % 27377 % うーん。改めて確認すると construct-pathname-pattern を使用している箇所は複数存在する。 27378 % 27379 % source:file,directory でファイル名を列挙している箇所 (action:file)。 27380 % source:argumet で = の右側のファイルを生成している箇所 (action:file_rhs)。 27381 % source:command でディレクトリ名を列挙している箇所 (action:command)。 27382 27383 うーん。色々考えると substr を source:file に対して特別に実装する必要がある 27384 のか疑問である。実のところ同等の候補が subseq, hsubseq で生成されるのだから 27385 substr の段階で候補を生成しなくても良い気がする。 27386 27387 特別な実装はしないという事に決めた。 27388 27389 * syntax: [!...] が常にエラー着色になっている問題 [#D1403] 27390 27391 うーん。これは ble/syntax:bash/simple-word/is-simple が成功しているのに、 27392 ble/syntax:bash/simple-word/evaluate-path-spec が失敗しているのが行けない。 27393 正規表現の構築で ! を含めるのを忘れているという事だろうか。 27394 27395 is-simple で使っている正規表現は以下の通り。 27396 local letter='\[[!^]|[^'${_ble_syntax_bashc_simple}']' 27397 _ble_syntax_bash_simple_rex_element='('$bquot'|'$squot'|'$dquot'|'$param'|'$letter')' 27398 _ble_syntax_bash_simple_rex_word='^'$_ble_syntax_bash_simple_rex_element'+$' 27399 27400 evaluate-path-spec で使っている正規表現は以下の通り。 27401 local letter1='[^'$sep$_ble_syntax_bashc_simple']' 27402 rex_element='('$bquot'|'$squot'|'$dquot'|'$param'|'$letter1')+' 27403 27404 あー。分かった。letter で特別扱いしている物を入れるのを忘れている。 27405 27406 他にも同様の違いがある物が色々ある。これは #D1303 の cmplstofB さんの報告が 27407 あった時の修正で中途半端な修正になっていたのが原因。合わせて関連する letter 27408 の正規表現も一括して修正する。 27409 27410 * syntax: glob bracket expression で POSIX [...] に対応していない (reported by alvinseville7cf) [#D1402] 27411 https://github.com/akinomyoga/ble.sh/issues/66 27412 27413 これは簡単に対応できると思ったが動いていない。何故? 27414 どうも [...] の2文字目は既に特別に処理してしまっている様子。 27415 と思ったがそうではなかった。条件コマンドの [[ を判定する為に、 27416 [[ の連なりは連続して読み取るという事にしていたのである。 27417 27418 これをどうにかして防ぐ? [[= [[. [[: の時には 1 文字だけしか読まない様にする? 27419 これだと余分に先読みしている事になるが仕方がない。 27420 27421 またそれとは別の問題として [![:lower:]] が何故か常にエラー着色になる。 27422 failglob かどうかに関わらず。履歴展開が関係している可能性? 27423 というより [!x].txt としてもエラー着色になっている。 27424 もう ! が存在しているだけでエラーという事なのだろうか。 27425 うーん。然し glob でなければ問題は起こっていない気がする。 27426 [^x].txt でもエラー着色になる。 27427 27428 更に [[:lower:]] が simple words ではない事になっている? 27429 27430 2020-10-10 27431 27432 * 2020-09-07 prompt: rps1 の内容が長くなった時に表示が乱れる [#D1401] 27433 次の行に改行してしまう。これは表示している内容に依存せずに長さだけで決まる様だ。 27434 27435 入力部分に未だ 10 文字程度の余裕がある段階で問題が発生している。 27436 これはもしかするとプロンプトを表示しなくする条件と関連している可能性? 27437 或いはプロンプトの範囲を制限する事に失敗している可能性? 27438 スペースが限られている時に rprompt をどの様に処理しているか確認する必要がある。 27439 27440 変なのは長さが足りなくなると一番最後の列から表示し始める様に変化してしまう 27441 という事。謎。或いは本当は全く表示しない様にした筈なのに表示されてしまって 27442 いるという事なのだろうか。 27443 27444 →分かった。修正した。rps1_show の時にだけ表示するべき所が常に表示される様 27445 になっていた。 27446 27447 * 然し、rps1_clear と rps1_show というのがあって、これの違いは何だろうか。 27448 rps1_clear は前回は表示されていたけれども新しく消す事になったという事を表 27449 すのだろうか。だとすると、動的に rps1 の内容が変化した時に残像の様な物が 27450 残ってしまうのではないだろうか。と思ったが、残像が残ってしまうのはどの様 27451 にしてもやはりそうなのではないかという気がする。 27452 27453 % →取り敢えず rprompt を描画する場合には先ず消去を行う事にした。(本来は 27454 % rprompt の前回の表示内容を管理してそれに応じて消去・更新をするべきなの 27455 % だとは思われる。) 27456 27457 と思ったら、消去に関しては既にその様になっていた。然し、消去の判定は単に 27458 rps1_transient によって、次の行に移る時に削除するという処理だけの様である。 27459 rps1 の内容が変更された時には前の描画を削除するという様な処理は行わない様 27460 である。というより、rps1 の内容が変更されたという事が分かる時には既に前回 27461 の rps1 の内容についての情報は喪われているので現在の実装では消去する事が 27462 できない。 27463 27464 現在の実装では transient によって rps1 が消去された時に、改めて 27465 ble/textarea#render/.cleanup-trailing-spaces-after-newlineを呼び出してい 27466 る。これが何だったかというと…。端末に無駄な空白が記録されるのを防ぐ為だっ 27467 た。rps1 が表示されている時にその間に空白が埋められるのは仕方がないとして、 27468 rps1 がない時には空白ではなくて NUL がそこにあるという状態にしたい。 27469 27470 - rps1_clear=1 rps1_show= → 消去 27471 - rps1_clear= rps1_show=1 → 描画or再描画 27472 - rps1_clear= rps1_show= → 前回表示した物のまま 27473 27474 前回表示していなくて今回新しく表示する場合はどうなるか? 27475 →大丈夫。消去して新しく描画する事になる。 27476 前回表示していて今回表示しない場合にはどうなるか。 27477 →表示したままになってしまう。これだと表示を取り消す筈なのにそのまま 27478 前回の内容が残ってしまう。 27479 27480 問題は前回表示していたのか表示していなかったのかの情報が記録されていない 27481 という事。前回表示していたかどうかに関わらず動作する方法は存在するだろう 27482 か。前回表示していても表示していなくても、今回表示するのであれば 27483 $_ble_edit_rprompt_dirty に委ねれば良い。では今回表示しない場合にどうする 27484 か。前回表示していれば消去するし、前回表示していなければそのままで良い。 27485 取り敢えず毎回消去すれば良いだろうか。然し、そうすると表示していない状態 27486 の時には更新がある度に毎回消去が発生する事になり非効率的であ 27487 る。_ble_edit_rprompt_dirty を参照しても表示を実行していないので常に 1 に 27488 設定されている。そういう事を考えるとやはり新しい変数を作って現在非表示か 27489 どうかを管理した方が良いのではないだろうか。 27490 27491 →取り敢えずコードを整理した。rps1_{enabled,clear,show} 等の様々な変数が 27492 あったが、整理して rps1_enabled だけを用いる事にした。 27493 27494 * prompt: 丁度折返しの起こる場所の直後が全角文字の時に空白文字が余分に入る [#D1400] 27495 screen の中でも発生しているし contra の中でも発生している。 27496 →確認したら普通に padding 文字の幅の計算をみすしていた。修正した。 27497 27498 * ble_debug 配列の表示が冗長なのを改善できないか [#D1399] 27499 多少コンパクトになる様にして quote を着色する様にした。 27500 27501 * ble_debug 改名 [#D1398] 27502 bleopt syntax_debug に改名した。 27503 27504 * complete: shopt progcomp_alias とは何だろう [#D1397] 27505 progcomp の補完関数の探索に alias 展開も考慮に入れるという物。 27506 この機能自体は ble.sh にもある様な気がするが、 27507 実際に progcomp に対して有効になっていたかは分からない。 27508 →これは実際に確かめてみた所、実装済みだった。 27509 単に shopt -q progcomp_alias を見て機能を無効化できる様にした。 27510 27511 * menu: やはり上下移動は一番最初の列を覚えておくべき [#D1396] 27512 実装した。逆方向の探索の実装は非効率的な気がする。 27513 現在の実装では最初から全ての要素を見ていって調べる事になっている。 27514 27515 a 一つの方法は二分探索して同じ行の始まりに移動するという事。 27516 b もう一つの方法は逆方向から要素を参照するという事。最近の実験によれば実は 27517 配列を逆方向に触るのは最近の bash ではそんなに遅くない。何より大量の要素 27518 を抱えた配列でなければ問題は起こらない。今の場合は探索対称の配列は現在の 27519 ページに含まれている要素しか含んでいないので、要素数が物凄く沢山という事 27520 もないし、逆方向に探索する事による速度の問題はないと考えられる。 27521 27522 取り敢えず逆方向から一つずつ見ていく方式で再実装した。 27523 速度は改善した気がする。ちゃんと動いている。 27524 27525 2020-09-26 27526 27527 * edit: 行末まで色が残ってしまう問題を修正したと思ったが直っていない [#D1395] 27528 27529 % どうやら contra & ble.sh のバグが組み合わさって 27530 % screen の内部でも再現しなくなっていただけで未だ問題は直っていない様だ。 27531 27532 否、rps1 が表示されている時には問題ないが、rps1 がない時に問題が生じるという事の様だ。 27533 27534 * 2020-09-01 color: 24bit color を使うと背景色がおかしくなる [#D1394] 27535 27536 これは contra の方で修正した。 27537 27538 | $ ble-color-setface command_builtin 'fg=#4bd' 27539 | $ echo hello 27540 | $ echo 27541 | $ 27542 | 27543 | auto_complete の背景色がクリアされないまま残ってしまっている? 27544 | printf '\e[m' してもそのままになってしまう。 27545 | C-l しても背景色がクリアされないまま残っている。 27546 | layer のキャッシュに削除しきれない物が残っている? 27547 | と思ったがそうでもないようだ。 27548 | 27549 | どうも contra の方のバグの様な気がする。ED 等の塗りつぶしに使う属性が 27550 | 書き換えられてしまっているか或いは描画時のブラシの管理が狂っている。 27551 | contra x11 でも再現する。xterm, mintty では再現しない。 27552 | やはり contra のバグだろう。 27553 27554 * edit: mc の対策として sgr0 を省略する様にしたら着色が残ってしまう様になった [#D1393] 27555 27556 何故だろうか。うーん。contra の中だと発生しない。 27557 screen の中だと発生する。mintty や cygwin/ConPTY でも発生する。 27558 27559 contra の中で発生していないし rps1 がなくても発生している事を考えると、 27560 別に空白文字が実際に大量に出力されているという訳でもないのだろう。 27561 具体的にどの様な出力がされているのかについて調べてみる事にする。 27562 27563 →調べると ECH(113) が出力されている。成程、これで contra と他の terminal の 27564 振る舞いの違いが説明できる。ECH の出どころは何処か。put-ech.draw を見張って 27565 見たが此処は通過しない様だ。_ble_term_ech で調べると、 27566 27567 * reject: もう一つは textmap#update にある。eraser という所で行のそれ以降の 27568 文字列を消去している。取り敢えずここに _ble_term_sgr0 を入れる事にする。 27569 →と思ったが此処を修正しても何も変化がない。此処は関係ない? 27570 27571 ? 懸念: SGR を復元する必要があるのではないか? 27572 27573 _ble_textmap_ichg は関係あるだろうか。 27574 _ble_textmap_ichg は改行について登録している。 27575 というかこれは #T0005 で議論している内容である。 27576 #T0005 の内容は改行にエラー着色がある時にそれをどう表示するかという話。 27577 改行の "SGR が行末まで反映されるのを防ぐ" のではなくて、 27578 "一文字だけ着色" などの細かい制御をどうするかという話である。 27579 確かに、全く表示しないというのでも良いのかなど色々単純ではない。 27580 今回は textmap#update に対しては変更は行わない事にする。 27581 27582 * ok: もう一つの箇所は ble/textarea#render/.erase-forward-line.draw である。 27583 ここにも _ble_term_sgr0 を入れる事にした。 27584 →これにより動く様になった。 27585 27586 * ok: rps がない場合には EL が使われている。 27587 この時にもちゃんと対策する必要があるのでは。 27588 →これも上と同じ箇所での処理である。同様に _ble_term_sgr0 を入れる。 27589 27590 * ok: contra が ECH に対して現在の背景色を適用しないのは意図的だったか。 27591 うーん。変だ。既定では mode_bce が true なので現在の背景色で ECH する筈。 27592 然し、実際には反映されていない。何故だろうか。うーん。これはバグである。 27593 →これは contra を修正した。 27594 27595 * edit: mc と一緒に使うと mc が固まる (reported by onelittlehope) [#D1392] 27596 https://github.com/akinomyoga/ble.sh/issues/62 27597 27598 報告した症状は起動時に 10s の delay が入るということ。 27599 これは自分の手許でも再現する。 27600 27601 | 何故だろうか。取り敢えず実行してみると mc は新しく PTY を作って、その中で 27602 | bash を interactive に起動する様子である。 27603 | 27604 | というか mc はどういう言語で書かれているんだ? PTY を生成しているという事は 27605 | bash という事はなかろう。何のために bash を起動している? 不思議なのは実際に 27606 | コマンドを実行する場合にはnon-interactive の bash が使われているということ。 27607 | 或いは、ble.sh がロードされていなければ interactive になるのか。fallback と 27608 | して non-intarcive の bash になっているのか。 27609 | →どうやらその様である。 27610 | ble.sh なしで起動した時には interactive mode になっている。 27611 27612 * mc はコマンドを受け取る為に PTY を開いて中で bash を interactive mode で起動する。 27613 然し、ble.sh が有効の時には何らかの timeout により non-interactive bash に fallback する。 27614 27615 | prompt-attach をしない様にすればOK? と思ったが実際に attach するとやはり動かない。 27616 | うーん。mc は一体何を期待しているのだろうか。或いは… C-q 等の状態になっている可能性? 27617 | 或いは stty の状態を ble.sh が変更しようとするのがいけない可能性? 27618 | 27619 | もしかして mc はプロンプトが表示されるのを待っている可能性? 27620 | そして PS1= を設定している。と思ったが、vi モードの時には -- INSERT -- を表示するから 27621 | それを prompt だと判定しても良いのではないかという気がする。 27622 | 実際に一回起動してから source ble.sh すると -- INSERT -- をプロンプトだと思う様である。 27623 | それに PS1= を設定するのにプロンプトが表示されるのを待つというのは変である。 27624 27625 mc の中にいる事を判定できる方法はあるだろうか。例えば環境変数が設定されているかなど。 27626 調べてみると以下の変数が設定されているので検出する事は可能である。 27627 そもそも mc は自身の line editor を使っている様なので、 27628 ble.sh が使えなくても特に問題はない。 27629 なので基本的には mc の内部では ble.sh を無効にするという方法で良い筈。 27630 27631 declare -x MC_SID="30814" 27632 declare -x MC_TMPDIR="/var/tmp/mc-murase" 27633 27634 一方で何故この様な振る舞いになるのか調べておく必要はある。 27635 ソースコードは以下にある。C言語で書かれている。 27636 https://github.com/MidnightCommander/mc 27637 27638 | ソースコードを検索してみたが特に bind を使って bash と交信しているという事はない気がする。 27639 | 27640 | * TERM も別に mc の物を設定しているという訳ではない。 27641 | * ble-0.1 でも同様に問題は発生する。 27642 | * PS1 に変な物が指定されているという事もない。 27643 | * PS1='\$ ' として見ても問題は変わらない。 27644 | * bleopt_internal_suppress_bash_output= を試したがやはり振る舞いは変わらない。 27645 | 27646 | mc は一体何を待っているのだろうか。エラーメッセージもないので分からない。 27647 | mc のソースコードの何処かに non-interactive で起動するのと 27648 | interactive で起動するのの二種類が存在する筈である。 27649 | 或いは PTY ありとなしで起動しているだけの可能性もあるが。 27650 | うーん。grantpt で検索したら subshell/common.c に init_subshell という関数があって、 27651 | 其処で色々と初期化している様に見える。 27652 | 27653 | mc をコンパイルした。試してみる。確かに init_subshell の中で 10s 過ごしている。 27654 | 27655 | どうも PROMPT_COMMAND に pwd >&XXX を設定していて、 27656 | これが実行されるのを待っている様だ。 27657 | と思ったが、もしそうならば --noattach & attach でちゃんと動く筈なのでは。 27658 | 実際に試してみると PROMPT_COMMAND は ble-attach 時には空になっている。 27659 | →PROMPT_COMMAND を何処で設定しているのかと思ったら一回起動した後に、 27660 | PROMPT_COMMAND=... というコマンドを pty 経由で入力している。 27661 | 27662 | ble.sh はコマンド履歴を受け取っていない気がする? 27663 | それなのに .bash_history にはちゃんと文字列が追加されている。 27664 | これは一体どういう事なのだろうか。別の経路で bash 本体がコマンドを受信している? 27665 | と思ったが分からない。それは考えにくいという気がする。 27666 | 或いは単に見落としだろうか→見落としだった。 27667 | ちゃんと実行されていた。然し問題はコマンドの途中の改行で分割されて実行されているという事。 27668 | 多分 syntax が初期化される前なので文法チェックがなされずに直接コマンド実行されているという事? 27669 27670 状況をまとめると。mc は bash に対して 'PROMPT_COMMAND=云々' というコマンドを送信する。 27671 そして次のプロンプトが表示される時に PROMPT_COMMAND に設定した pwd >&15 というコマンドを経由して 27672 現在のディレクトリを受信する。現在のディレクトリを受信する迄待ち 10s で timeout すると失敗と見做す。 27673 27674 ble.sh は最初のコマンドを受信するが受信した文字列を、 27675 途中の改行で分割して個別に実行しようとする為、PROMPT_COMMAND の設定に失敗する。 27676 従って pwd >&15 がいつまでも実行されないのでブロックされる事になる。 27677 27678 syntax.sh がロードされていない状態でもちゃんと 27679 文法チェックをする様にした方が良いのかもしれない。 27680 27681 うーん。分かった。何故効かないのかというと \n (C-j) を使って改行を入力しているからだ。 27682 一方で ble.sh では C-j を強制実行に割り当てている。 27683 27684 % 取り敢えず ble-bind -s C-j $'\r' 等としておけば問題は発生しない様だ。 27685 % 報告されているもう一つの問題もこれで一緒に解決する。 27686 % 対策としては MC の中にいる時には既定で上記の設定に切り替える。 27687 % もしくは最初のコマンド実行迄は C-j を強制的に C-m に読み替える様にする。 27688 % MC の中にいるかどうかをより正確に判定するにはどうすれば良いか。 27689 % MC_SID の有無だと更に subshell の中に入った時にも対策が起動してしまう。 27690 % 27691 % * 強制的に attach している筈なのに ble-detach 状態になっている。何故か。 27692 % と思ったらそもそも ble-attach していなかった。そしてble-bind で解決したかに見えたのも、 27693 % 単に ble-attach していなかったからである。 27694 27695 改めて回避方法について考える。ble-bind -f C-j nop とすると、 27696 ごみの bash_history すら追加されなくなる事を見ると、 27697 ちゃんと ble-bind は効果を持っている。然し、反応がなくなってしまう。 27698 27699 とここで分かった。先ず ble.sh の C-m は文法構造に関係なく、 27700 続きに何か入力がある時には改行挿入と見做す。 27701 そして一旦改行がコマンドラインに入ると以降は multiline mode になって 27702 以降どんなに改行が現れても改行挿入にしかならない。 27703 27704 つまり ble.sh の C-m でも C-j でもない振る舞いにしなければならない。 27705 うーん。accept-line でも文法チェックを行う? 27706 →結局 accept-line に syntax という引数を与えるか、 27707 或いは $$MC_SID == $$ 且つ LINENO == 0 の時に文法的に完全かどうかをチェックする事にした。 27708 27709 x fixed: 実際にコマンド履歴に妙な物が大量に出力されている。 27710 これについてもどうにかする必要がある。 27711 或いは特に問題が発生しない限りはコマンド履歴に変な物が登録される事はないのだろうか。 27712 27713 というか普通に bash が起動できた場合にもこのごみが出力されるのだろうか。 27714 →確かにごみが .bash_history に残ってしまう。 27715 cd の記録程度であればまあ残っていても良い気がするが、 27716 PROMPT_COMMAND 云々は .bash_history に残す理由もないし消したい所である。 27717 27718 うーん。ble.sh だと PROMPT_COMMAND= と PS1= の二種類のコマンドが履歴に書き 27719 込まれてしまって、最初の物は空白が前置されているので HISTCONTROL に 27720 ignorespace が入っている distro では何も起こらないが、二番目の PS1= は空白 27721 が前置されていないので本当に履歴に書き込まれてしまう。所が bash の中で実行 27722 すると PROMPT_COMMAND しか設定されない。この違いは何処から来るのだろうか。 27723 或いは何かのエラーが起こった時に fallback として PS1 を設定している? 27724 27725 ソースコードを見るとちゃんと PROMPT_COMMAND と共に PS1= が送信される様になっている。 27726 然し実際に起動した物を見ると PS1 は設定されていない様に見える。何故。 27727 うーん。どうもこれは kill -STOP $$ がどの時点で発動するかという問題の様だ。 27728 元の bash では \n が来た時にコマンドの解釈が途切れるので、 27729 その時点で SIGSTOP が来て bash が取り敢えず動作を停止する? 27730 一方で、ble.sh では kill -STOP をしてもお構いなく入力されたコマンドを全て実行する。 27731 結果として後に続く PS1= も一緒に実行されるという事である。 27732 27733 これは意図的にその様に動作する様にしているのだと思われるが何故かはよくわからない。 27734 取り敢えず現状のままに ble.sh の中では PS1= も実行してしまうという振る舞いのままにする。 27735 cd に関してはユーザの設定で HISTCONTROL=ignorespace でも追加してもらう事にする。 27736 27737 x fixed: プロンプトが消滅している。これは rps1 やその他の特別なプロンプトを 27738 $MC_SID == $$ の時には表示しない様にすれば良い気がする。 27739 と思ってその様に対策したがそれでもプロンプトが消滅したままである。 27740 27741 明示的にプロンプトの設定を全て削除してもやはりプロンプトは消滅したままである。 27742 というかそもそもプロンプトが食われてしまって何も表示されない。 27743 という事はプロンプトを抽出するコードで何か問題が生じているという事。 27744 27745 調べると正に read_subshell_prompt という関数が存在している。 27746 うーん。というかもしかして kill -STOP を用いて区切れを判定している? 27747 そして kill -STOP のタイミングが変なのでプロンプトではなくコマンドの出力と思われている可能性。 27748 然し、実際にはプロンプトが消滅してしまっているという事を考えるとやはり違うのだろうか。 27749 或いはプロンプトが消滅してしまっているのは単に \r\e[K して現在行を消去しているからという可能性もある。 27750 それにテストしている最中に -- INSERT -- をプロンプトと認識してしまう事もあったので、 27751 恐らく kill -STOP のタイミングによる問題ではないのではないか。 27752 27753 * 改めて read_subshell_prompt の動作について確認する必要がある。 27754 27755 read_subshell_prompt の呼び出しを見てみると通常の bash では一回しか呼び出 27756 されていないのに、ble.sh の中ではコマンドを実行する度に 3 回呼び出されてい 27757 る。最初の呼び出しでは空文字列が読み取られ、二回目の呼び出しでちゃんと内容 27758 が読み取られる。最後の呼び出しで \e[m が読み取られて終わる。 27759 どうして呼び出しの回数が異なるのか。 27760 27761 何処から呼び出されているのか。filemanager/layout.c の do_load_prompt から 27762 呼び出されている。そして do_load_prompt は更に load_prompt から呼び出され 27763 ている。呼び出し経路を調べてみると、 27764 27765 bash (1) do_load_prompt -> read_subshell_prompt (有限) 27766 ble.sh (1) do_load_prompt -> read_subshell_prompt (空) 27767 ble.sh (2) load_prompt -> do_load_prompt -> read_subshell_prompt (有限) 27768 ble.sh (3) load_prompt -> do_load_prompt -> read_subshell_prompt (sgr0) 27769 27770 の様になっている。ble.sh では load_prompt 経由の読み取りが余分にある。 27771 そして load_prompt は filemanager/midnight.c の初期化時に 27772 27773 add_select_channel (mc_global.tty.subshell_pty, load_prompt, NULL); 27774 27775 の様にして登録されている以外は使われていない。要するに pty で何か受け取っ 27776 た時に load_prompt が呼び出されるという事の様に思われる。それにしても何を 27777 trigger にして呼び出されるのだろうか。 27778 27779 * 3回目の read_subshell_prompt の呼び出しで sgr0 を読み取ってしまうのが原因に思われる。 27780 この3回目の read_subshell_prompt が起こらない様にすればよいのではないか。 27781 その為にはこの sgr0 の出どころを調べる必要がある。 27782 27783 何が起こっているのか分かった。ble/textarea#render を実行すると、 27784 特に更新の必要がない場合には ble/textarea#focus が呼び出され、 27785 カーソル位置を ble/textarea#render の現在位置に移動する。 27786 この時に sgr0 を出力してから移動しようとするのである。 27787 27788 もう一つの疑問は何故二つに分けて出力されているのかという事。 27789 うーん。分かった。ble/textarea#render -> ble/util/idle.do 27790 -> ble/textarea#render の順に呼び出されている。従って、 27791 ble/textarea#render が二回呼び出されるのである。 27792 27793 うーん。goto しても移動がない場合には _ble_term_sgr0 は出力しない事にする? 27794 他に影響があるかどうか分からないが多分大丈夫だろう。 27795 →これでちゃんと動くようになった。実は set -o vi でもちゃんと動いている。 27796 -- INSERT -- を表示するタイミングとプロンプトを表示するタイミングが偶々 27797 良い感じになっていたからだと思われる。 27798 27799 それでも C-o の画面に戻るとプロンプトが消滅してしまってはいる。これは画面 27800 の一番下にいる時に発生している。どうも mc はコマンドを実行する時に画面の一 27801 番下の行にカーソルを持ってくる様である。ble.sh の canvas は行を全て管理で 27802 きていると思っているから、消去したい panel に普通に CUD で移動して削除しよ 27803 うとする。然し、実際には CUD で移動するのに失敗して誤って現在の行を削除し 27804 てしまうという事。これは対策できる気がする。対策した。 27805 27806 * widget: keymap による自動的な振る舞いの切り替えの仕組みを作る [#D1391] 27807 27808 うーん。何だか面倒になってきた。そもそも vi_imap の時にだけ振る舞いが変わる 27809 物が多過ぎて widget が色々異なるのが面倒である。ble/widget/newline を呼び出すだけで 27810 現在の keymap に応じて適切に振る舞いを変更する様に変更したらどうだろうか。 27811 edit.sh に全ての実装を書き込むと edit.sh が肥大化してしまうので、 27812 動作を自動的に切り替える仕組みを作るというのでも良い。 27813 27814 と思ったが ble/widget/newline に関してはユーザの好みで振る舞いを変えたい事もあるかもしれない。 27815 等と考えると、keymap で固定してしまうのではなくやはり自分で設定できる様にするべきだろうか。 27816 うーん。然し、それはオプションで制御できる様にしても良い気がする。 27817 或いは、もしユーザが自前で widget を作るのだとしたらそれは備え付けの ble/widget/newline とは 27818 関係がないのだから気にしなくても良い。 27819 27820 というか今その対策をする必要はあるだろうか。 27821 うーん。この対策をせずに実装しようとすると、 27822 accept-line についても vi_imap 云々という keymap 判定をしなければならなくなる。 27823 取り敢えず暫定の実装として accept-line の内部で keymap 判定を実行する様にするか、 27824 或いは先に keymap 判定を自動的に実行する仕組みを作って整理してから accept-line 27825 に対する対策を実行するか。 27826 27827 先に ble/widget/newline 等の実装を自動で切り替える仕組みを実装する事にする。 27828 対象は newline, accept-single-line-or, accept-line である。 27829 27830 accept-single-line に関しては vi-command 版もある。 27831 vi-command/accept-single-line-or は vi_nmap でしか使われていないが、 27832 名称的には vi_[onx]map で使っても問題がない様に設計されている気がする。 27833 27834 これらにちゃんと対応する為には vi_omap, vi_xmap についても機能を追加するか、 27835 或いは vi_nmap しか対応しないか、或いは vi_[onx]map の時には特別に 27836 vi_command も一緒に探索する事にするか。取り敢えずは vi_nmap だけの対応で良い 27837 気がしてきた。 27838 27839 * dispatch 先の関数名をどうするか。 27840 27841 a 取り敢えずの実装としては ble/widget/NAME に対して ble/widget/KEYMAP/NAME 27842 を試行する事にした。このルールは既存の緩やかなルールに合致しているので既 27843 存のコードを大きく書き換える必要はないだろう。 27844 27845 b また ble/widget/NAME/.keymap:KEYMAP 等の名称よりはわかりやすい気がする。 27846 と思ったが、: が含まれる場合も widget として列挙されない様な気がする。と 27847 いう事は ble/widget/NAME/keymap:default でも良い様な気もする。 27848 27849 うーん。keymap 特有の accept-line を呼び出す時に内部的に accept-line を 27850 呼び出したい時にble/widget/accept-line ではなくて 27851 ble/widget/default/accept-line を呼び出さなければならないという事を思う 27852 と、ble/widget/accept-line/keymap:default の方が良い? と思ったが、何れに 27853 しても ble/widget/accept-line/keymap:default と書いて呼び出さなければな 27854 らない。ble/widget/accept-line の儘で呼び出せる方法はないのである。なの 27855 で、やはり名称は ble/widget/default/accept-line でも変わらない。 27856 27857 c この観点だと ble/widget/accept-line.default や 27858 ble/widget/accept-line.vi_imap 等だったら分かりやすかったかもしれないが、 27859 ble/widget/*.* の形式の補助関数は沢山あるのでそれと被ってしまう問題があ 27860 る。 27861 27862 やはり取り敢えずは dispatch 先の関数名は a の方針で行く事にする。 27863 27864 [変更] 27865 27866 - done: newline 対応した。 27867 - done: accept-single-line-or 27868 27869 実はこれは今対応する必要はない? というのも accept-line から newline を呼び 27870 出した時にもう既に自動的に keymap に対応する関数が呼び出される様になっている。 27871 従って特別に実装する必要はないのではないか。 27872 27873 一方でコードの綺麗さという観点で考えるとやはり此処は統一した枠組みの上で実 27874 装したい。うーん。やっぱり accept-single-line-or についても keymap dispatch 27875 に対応する事にする。 27876 27877 - done: accept-line 27878 これも既に vi-command/accept-line という物があるので keymap dispatch にする。 27879 vi-command/accept-line は vi_nmap/accept-line に名称を変更。 27880 実は vi_nmap/accept-single-line-or はこれで不要になる。 27881 27882 他にも vi_imap/... 等は存在している気がするが、これらは互いに呼び出す等の事 27883 をして複雑になっている訳でもないので、追々置き換えていけば問題ない。 27884 取り敢えず動いている気がするので気にしない事にする。 27885 27886 2020-09-15 27887 27888 * [解消] 2020-09-07 complete: 空白を含むファイル名の補完候補が増殖する [#D1390] 27889 Note: #D1389 で解決した。 27890 27891 更にファイル名のパターンによって同じ候補が沢山表示されることもある。 27892 これは一般の引数で発生する。complete -r しても同様。 27893 どうもファイル名に含まれている空白の数だけ候補が増殖する様子である。 27894 27895 これは bash_completion では発生しない。 27896 自前の補完を用いた時に発生する問題である。 27897 27898 先ずは再現させなければならないが再現できない。新しい ble.sh で自然 27899 に直ったのかとも思ったが古いセッションでやっても再現しない。 27900 →再現できた。少なくともファイル名に完全一致している状態で<TAB>すると起こる。 27901 然し新しい ble.sh では再現できていない。 27902 27903 一応何が原因で発生していたのか調べる必要がある。OK。発生は確かめた。 27904 次に確認するべき事は何かというと、…候補生成で何が起こっているのかという事。 27905 27906 分かった。これも glob pattern が単語分割されているのが原因だった。 27907 echo 'a b c' に対してパターンが以下の様になり、 27908 結果として3つに展開されていたという事である。 27909 27910 pattern: ret='*a* *b* *c*' 27911 expanded: ret=('a b c' 'a b c' 'a b c') 27912 27913 これは #D1389 で自然に解決したと見て良い。 27914 27915 * 2020-09-10 complete: mkdir aaaaaaaaaaa. とすると無限ループになる [#D1389] 27916 →aの数が少ないと問題が起きない。という事を考えるとこれは曖昧補完で使っている 27917 正規表現またはパス名展開による物と思われる。 27918 実際には無限ループになっているという訳ではなくて指数関数的に処理量が大きくなっている。 27919 これに対する対策はしておかなければならない。 27920 27921 同じ文字数でも abcdefg.... という文字列だと問題は起こらない。 27922 つまりこれは同じ文字が連続で存在している時に発生する問題である。 27923 27924 一つの対策方法は同じ文字が複数並んでいる時の曖昧文字列生成について。 27925 然しそれでも abababababa というパターンに対しては脆弱になるのではないか。 27926 27927 というよりそもそも、a*a となっている時に最初の * の中に 27928 a が含まれる事を禁止すれば良いのではないか。 27929 a*b の場合には b を禁止する。その様にすれば必ず literal b match は、 27930 a の後に現れる最初の b という事になるので曖昧さはなくなり、 27931 様々な種類のパターン一致を試す必要もなくなるのではないか。 27932 そしてそれはグロブパターンならば *([!b]) 等とすれば良い。 27933 正規表現ならば [^b]* とすれば良い。 27934 27935 然し、本当にこれで問題ないだろうか。実はこれによって一致しなくなっ 27936 てしまうパターンなどがあったりするのではないか? と思ったが…。多分 27937 大丈夫である。元のパターンで一致する文字列であれば必ず制限をかけた 27938 パターンでも一致するという事を示せば良い。そしてそれは自明の事のよ 27939 うに思われる。 27940 27941 chatoyancy 上で再現できないと思ったらどうやら bash-4.4 では問題が 27942 起きるが bash-5.0 では問題は起きない様子だ。何れにしても再現できる 27943 様になったので修正できる。 27944 27945 取り敢えず *([!b]) に変換する様にしてみたがこれでちゃんと動作するかは分からない。 27946 先ずはちゃんと ambiguous expansion が働くかどうか。動く。 27947 そして bash-4.4 で遅くなってしまう問題も解決している。 27948 取り敢えずこれで様子見する事にする。 27949 27950 * 2020-09-10 最初に起動した時に bleopt prompt_screen_title が反映されていない [#D1388] 27951 27952 これは分かった。ble.sh は _ble_term_TERM を見て 27953 prompt_screen_title を出力するかどうか決めている。然し 27954 _ble_term_TERM は DA2 応答があるまでは代入されない。 27955 最初は空なのである。 27956 27957 _ble_term_TERM が空の時には TERM も確認する事にした。 27958 流石に screen, screen.* に設定しているのは screen か tmux だけだろう。 27959 screen が xterm に設定している場合には判定できないが仕方がない。 27960 27961 * 2020-09-07 complete: メニュー補完で引用符が消える [#D1387] 27962 27963 引用符で囲んでいる状態でメニュー補完すると引用符が消える。何故だろう 27964 試していた所メニュー補完でなくても問題が生じる事が分かった。 27965 これは cd の引数でだけ発生する? →どうもその様である。 27966 27967 然しディレクトリ名のパターンによって発生したりしなかったりする。 27968 OK. 再現する。 27969 27970 $ mkdir 'a b' 27971 $ cd 'a b <--この状態で TAB を押すと引用符が消える。 27972 27973 実は bash_completion を有効にしている場合は cd だけでなく mkdir でも起こる。 27974 原因が同じかどうかは分からない。 27975 27976 ble/cmdinfo/complete:cd を削除すると再現しない。 27977 ble/cmdinfo/complete:cd で直接 ble/complete/source:file,dir 等を実 27978 行する様にしている場合は再現する。 27979 27980 →普通にquote-insert も呼び出している…と思ったが、調べてみると、 27981 COMPS も COMPV も設定されていないということが判明した。何故。 27982 27983 →調べると一回目の呼び出しではちゃんと有限の文字列になっていて引用符も含ま 27984 れている。然し、それに対しては候補生成に失敗して、更に 曖昧補完として 27985 COMPS, COMPV を空にして再度呼び出された時に候補が生成されるという事である。 27986 ここで二つの問題がある。 27987 27988 x fixed: 何故最初の引用符ありの補完に失敗しているのか 27989 27990 これは分かった。glob で "$COMPV"*/ に等価な物を生成しようとしているが、 27991 27992 % $COMPV の部分をエスケープする時に空白文字のエスケープをしていないのが原 27993 % 因。然し、実際に一文字ずつエスケープする必要があっただろうか。実は 27994 % '...'*/ としたり、或いは最早 "$COMPV"*/ でも良かったのではないだろうか。 27995 % 然し、それはどの様にパス名展開を引き起こしているのかに依存する。もし 27996 % eval "a=($pattern)" としているのであれば良いが、もし a=($pattern) とし 27997 % ているのであれば quote 除去や変数展開は使えない。展開は実際に 27998 % ble/complete/util/eval-pathname-expansion で行われていて、その中では以 27999 % 下の様にして展開が実行されている。 28000 % 28001 % IFS= GLOBIGNORE= builtin eval 'ret=(); ret=($pattern)' 2>/dev/null 28002 % 28003 % つまり後者なので quote 除去や変数展開は使えないのである。 28004 % 28005 % ? 然しここで疑問が生じる。もしこの様にしているのであれば、何故空白をファ 28006 % イル名の一部としてパス名展開が行われないのか。と思ったが、それよりも 28007 % 先に単語分割が先に行われてしまう。 28008 % 28009 % ? もう一つの可能性として eval "ret=(); ret=($pattern)" の様に書き換える 28010 % という事。こちらの方が融通が効くのではないかという気がする。然し、 28011 % "$COMPV" の様な特定の変数の値が保持されている事を前提とする物は使いた 28012 % くない。だとすると '...' による quote に頼る事になる。実は \ に対する 28013 % グロブ自体の quote と対して変わらないのではないかという気がする。 28014 % 28015 % 然し、もしちゃんと \ によるエスケープで動作できる様にするのであれば、 28016 % その儘の形で意図した物にちゃんと一致する様にパターンを構築した方が自 28017 % 然の気がする。という事を色々考えるとやはり現状の方針を変えずにエスケー 28018 % プを修正するという方向で直す。 28019 % 28020 % ? ファイル名に改行が含まれている場合にはどうなるのか? 28021 % 28022 % この場合は単純に pattern=$'a\\\nb*' 等としても一致しない気がする。 28023 % 実験してみる事にする。動かない。というより気づいてしまったが、 28024 % 実は通常の空白であっても \ を前置しても単語分割を防ぐ事はできない様だ。 28025 % 28026 % ? ok: bash-5.0 pathname expansion quirk の問題はあるか 28027 % 28028 % 一方で bash-5.0 の特別な振る舞いとして \ が含まれているか含まれていな 28029 % いかで、ret=($PATTERN) とした時に PATTERN がグロブパターンとして取り 28030 % 扱われるかどうかが切り替わるという話がある。これは bash-5.1 でまた昔 28031 % の動作に戻った。これに関しては、ble.sh で使う時には必ず * 等のパター 28032 % ンを含んでいるから常に意図的にパス名展開の対象であるので"意図せずパス 28033 % 名展開が起こった" という事態にはならない。 28034 28035 →変数に含まれるグロブパターンに於いて空白をエスケープする手段は存在しな 28036 いという事が判明した。つまり ret=($pattern) という展開自体が駄目という事。 28037 代わりに pattern を適切にエスケープした上で eval "ret=($pattern)" とする 28038 必要がある。 28039 28040 先ず ble/complete/util/eval-pathname-expansion の呼び出し元を確認する。 28041 全て ble/complete/source:file/.construct-pathname-pattern の結果を使っている。 28042 なので、両方を書き換えれば問題ない。 28043 28044 ? util: 実は ble/util/eval-pathname-expansion でも同様に注意が必要なのでは? 28045 と思ったが、調べてみると ble/util/eval-pathname-expansion では始めから 28046 eval "ret=($1)" の形式を採用していたのでこの手の問題は発生しない。 28047 28048 * 単に pattern='"$COMPV"*' とすれば良いのではないかと考えたが、 28049 それだと is-cygwin-slow-glob の判定をすり抜けてしまうので、 28050 やはり自分で展開して quote する形にするのが良い気がする。 28051 28052 どの様に quote するか。単純に考えれば '...' で良いが特別の文字を含む時に 28053 限って'...' の形式に移行するというのでも良い気がする。 28054 →これに対しては新しく ble/string#quote-command という関数を作った。 28055 取り敢えずこの問題に関しては修正された気がする。 28056 28057 x 二回目の補完で COMPS が消滅しているのにも関わらず、COMPS が存在していると 28058 いう前提での文脈に応じた escape をしている。これは単に COMPS に応じて 28059 escape の種類を変えるという事で対処できる。 28060 28061 quote-insert から呼び出している escape では comps_flags を参照している。 28062 28063 こちらについては修正されていない。先に前者の方を修正してしまったので、 28064 改めてこれを再現させる方法を考えなければならない。と思ったが、 28065 単に head による候補列挙を一時的に停止すれば良いだけの気がする。 28066 28067 と思ったら空白を含むファイルの補完候補が増殖する問題が邪魔をして再現でき 28068 ない。取り敢えずそちらを先に解決する事にする。と思ったが勘違いだった。中 28069 途半端に head による候補列挙をスキップした為に候補が重複して生成されてい 28070 ただけだった。取り敢えず問題を再現させる所までは行った。原因は明らかであ 28071 る。問題はどの様にしてこれを実装するべきかという事である。 28072 28073 元々の quote では元々存在している文字列を置換しないという事を前提としてい 28074 た。なので quote 状態は破壊されないという前提であった。或いは COMPV がちゃ 28075 んと quote 状態に対応しているという前提があったのである。然し、曖昧補完の 28076 時には COMPV を強制的に置換してしまっているので、quote 状態と COMPV が対 28077 応していない状態になっているのが元々の問題点である。 28078 28079 COMPV を置換せずに曖昧補完であるという事を伝達するか、或いは曖昧補完の時 28080 には quote 状態のフラグも一緒に変化させてしまうか。後者の場合には、元々の 28081 quote の種類が補完によって変わってしまうという事を意味する。やはりできる 28082 だけ quote の種類は保持する様に置換を実行したい。或いは現状のままで 28083 COMPV= が特別に曖昧補完であるという事にして、quote を処理するという方針? 28084 この方が良い様な気がしてきた。 28085 28086 念の為 COMPV= を設定している箇所について確認する。調べるとどうやら各 28087 source に於いて独自の判断で COMPV を空にしている様である。これは本来は内 28088 部の変数にコピーしてから改変するべきなのではないかという事。COMPV はその 28089 儘にしておく事で quote の側ではこれにより補完で遡った書き換えが起こったか 28090 どうかを正しく判定する事ができる。 28091 28092 | a 例えば COMPV から compv にコピーして処理するという事。この時に何らかの 28093 | 問題が生じる可能性があるだろうか。COMPV を使用している箇所について確認 28094 | する。結果分かった事は COMPV は候補生成の時にしか使われていなくて、寧ろ 28095 | 元の文字列を参照する必要があるのは quote をする時だけの様であるという事。 28096 | つまり、逆に COMPV は現状の様に処理して、代わりに別の変数に本来の COMPV 28097 | を保持するべきではないか、という事。もしくは COMP_POINT か何かの変数を 28098 | 用いて自前で COMPV に対応する文字列を抽出する? 28099 | 28100 | と思ったが、COMPV は eval 後の値である為そう単純ではない。というか、本 28101 | 当に COMPV による判定だったろうか? 28102 | 28103 | 判定は [[ $comps_flags == *v* && $CAND == "$COMPV"* ]] で行われている。 28104 | 28105 | この時に一致している部分までを COMPS に置き換えてそれ以降をエスケープし 28106 | て追記している。うーん。或いは、COMPS= COMPV= としたのが行けなくて、 28107 | COMPS に引用符などを保持して置くべきだったのかもしれない。それは一つの 28108 | 解決方法である。 28109 | 28110 | x compv の使用箇所について確認を行う。ほとんど使われていない。使われて 28111 | いるのは filter を実施する関数内で icasematch を実行する為に内部で 28112 | lower case に変換して差し替える為に置き換えている所のみである。 28113 | 28114 | x 然し一方で小文字の compv を特殊変数名とするのには抵抗がある。やはりで 28115 | きるだけ特殊な関数の間で共有して動的スコープでアクセスする変数は 28116 | prefix をつけるか大文字にするかして区別する様にしたい。 28117 | 28118 | b COMPV= とする時に COMPS の方にちゃんと引用符等の quote も含めた値を設定 28119 | する。もしくは、quote 状態のフラグを修正する。 28120 | 28121 | c 或いは COMPS が空で quote 状態が設定されている時には曖昧補完として 28122 | COMPS/COMPV が上書きされたと判定する? 28123 28124 うーん。b の方法が現在のところ一番良い様な気がする。取り敢えず COMPS= 28125 COMPV= を実行している箇所を関数に置き換える事にする。と思ったが微妙な事が 28126 残る…。COMPS=${COMPS::1} 及び COMPV=${COMPV::1} しているのは駄目である。 28127 例えば COMPS が 'hello' だった場合に、COMPS=\' COMPV=h という状態になって 28128 しまう。これだと h が補完後に消滅してしまう事になる。現状でも問題になるの 28129 ではないだろうか。今まで問題が起こらなかったのは何故だろうか…。 28130 28131 実際に試してみると確かに問題が発生している。 28132 28133 $ touch hello 28134 $ echo 'hll <-- ここで TAB を押すと補完結果が 'ello' になってしまう。 28135 28136 COMPS=${COMPS::1} としている部分も含めてちゃんと対応する必要がある。一方 28137 でどの様に切り出すのが正しいのかというのはかなり謎。うーん。COMPS は別に 28138 自分で勝手に作り出しても良いのではないだろうか。どうせ曖昧補完なので遡っ 28139 て書き換わってしまうのは仕方がない。それに実際に置換する時には、呼び出し 28140 元の関数で処理するので書き換わった COMPS の影響はない。飽くまで候補生成に 28141 影響を与えるだけなので気にしなくても良い。 28142 28143 という訳で何れにしても COMPS として適当な物を合成する方針にする。これだと 28144 例えば abc"def<TAB> とした時に "abcdef... になるという動作になるが、まあ 28145 それで良いだろうという気がする。 28146 28147 x 取り敢えず実装した…と思って動作確認したら全く直っていない。どういう事 28148 だろうか。確認したら簡単なミスだった。コードの整理もした。 28149 28150 ? ok: source:command を見ると command の曖昧補完は起こらない様になっている? 28151 と思ったが実際にやってみると動いている。何故だろうか。確認する必要がある。 28152 28153 改めて確認すると source:command/gen を呼び出して更にその中の 28154 source:command/gen.1 に於いて曖昧補完の設定をして実際の展開を行っている。 28155 これについてはOK 28156 28157 ? comps_fixed がある時 (ブレース展開がある時) 曖昧補完を実行しようとすると何が起こるのか? 28158 28159 | 例えばブレース展開がある所までは展開結果が一致していたとしても、引用符 28160 | 関連で書き換えが起こるとすると補完できないという事になるのでは。以下を 28161 | 試したら補完できなかった。これについては他を修正してから改めて確認する。 28162 | 28163 | 28164 | $ touch hello 28165 | $ echo h{'ll<TAB> 28166 | 28167 | これに関しては曖昧補完の場合でも comps_fixed に対応する部分まではそのまま 28168 | にして補完を実行するのが良い気がする。問題は、h{xxx,ll<TAB> とした時に何 28169 | 処までが fixed_part なのかという事。"h{xxx," が fixed part になって展開結 28170 | 果が h になるのであればOK。何れにしても取り敢えず実装して様子を見る。 28171 28172 →これは次のテスト項目で一緒に取り扱う事にする。 28173 28174 以下の動作確認を行う。 28175 28176 | $ touch hello 28177 | $ echo 'hll<TAB> 28178 | $ echo 'hello' 28179 | これは動いた。 28180 | 28181 | $ echo h"ll<TAB> 28182 | $ echo "hello" 28183 | 28184 | これは動かない。何故だろうか。うーん。もしかして h"ll は単純単語ではない? 28185 | 実際に呼び出してみると別に単純単語でないという事はない。ちゃんと h"ll" に 28186 | 変換してその上で hll に変換される。一応 h'll の場合には期待通りに全体が 28187 | '...' で囲まれた形で補完されるので当初期待した機能はちゃんと実装できてい 28188 | る。問題は何故 ' で動いて " で動かないのかという事。これはまた独立に調べ 28189 | る必要がある。 28190 | 28191 | $ echo h{'ll<TAB> 28192 | $ echo h{'ello', 28193 | 28194 | これも動かない。echo h{ello', になってしまう。ブレース展開の場合には 28195 | quote が外されてしまうので、末端の ' をつけてはいけないという事。ブレース 28196 | 展開があっても適当な所で始まりの quote を挿入する様にしなければならないの 28197 | である。と思ったが、分からない。 28198 | 28199 | 調べてみると先ず $CAND == "$COMPV"* のテストには失敗する。曖昧補完先頭一 28200 | 致の場合には COMPV=hl という具合に最初の一文字を含んでいるからである。 28201 | 28202 | * うーん。実は COMPV に既に文字が含まれている場合には先頭一致でも COMPV 28203 | に新しい文字を追加する必要はない。そうしないと CAND == COMPV のフィルタ 28204 | リングで無駄に候補が削られてしまうから。というよりそもそも hl から始ま 28205 | る単語しか生成されなくなってしまう。と思ったが、それは或る意味期待した 28206 | 事なのでは? うーん。然し、やはり h から始まる単語にした方が直感的な気が 28207 | する。その点に関してはまた後で修正する。 28208 | 28209 | x ok: もう一つの問題は何故か COMPV に文字列を設定しているのにも関わらず、 28210 | 関係ない候補が沢山生成されているという事である。後でフィルタリングされ 28211 | るとは言え無駄である。これは bash_completion だろうか。或いは ble.sh 自 28212 | 体の問題だろうか。→ complete -r したら生成されなく鳴ったのでこれは 28213 | bash_completion である。無視して良い。 28214 | 28215 | x pinned: 何故か quote-insert の時に COMPS/COMPV が変化してしまっている。 28216 | quote-insert は source:* の中で呼び出されているのではないのか。実際に確 28217 | かめてみると source:argument の中で呼び出されている。つまりちゃんと 28218 | COMPS/COMPV は補正されている筈である? やはり内部で書き換わってしまって 28219 | いる。代入している箇所は他にはない気がする。一体何が起こっているのか改 28220 | めて確認する。先ず何処で書き換わっているのかを特定する。 28221 | 28222 | うーん。どうやら分かった。 COMPS/COMPV を補正しているのは 28223 | .generate-user-defined-completion の中であるが、実際に yield しているの 28224 | はそれよりも外側の関数という事の様である。何故だろう。 28225 | 28226 | 分かった…。source:file がそもそも曖昧補完に対応していないか壊れている? 28227 | 調べてみると source:file はパス名展開を用いて曖昧候補を生成する仕組みに 28228 | なっている。つまり別の枠組みで生成している。 28229 | 28230 | これは今までにもあったバグだろうかと思って調べてみるとやはり以前から存 28231 | 在していたバグの様である。これも別に修正しなければならない。と思ったが、 28232 | これの前に修正したバグで再現していただけかもしれない。何だか分からない。 28233 | 少なくとも新しく問題が起こる様になった訳ではない。 28234 | 28235 | * comps_fixed が quote を含んでいないという点には注意する。この時何処かに 28236 | は quote を入れる必要があるのである。これについては改めて考察する必要が 28237 | ある。 28238 28239 問題がまた絡み合ってきたので改めて現状について整理する。以下のテストケース 28240 を考える。 28241 28242 $ touch hello 28243 $ echo 'hll<TAB> 28244 28245 $ echo h"ll<TAB> 28246 28247 $ complete -r 28248 $ echo 'hll<TAB> 28249 28250 $ echo h{'ll<TAB> 28251 28252 上記が全て動くようにならなければならない。既知の問題は、 28253 28254 x fixed: source:file の実装で曖昧補完の時の quote 再現に対応できていない。 28255 これに対応する為にはどうしたら良いか。うーん。単純に開始 quote を 28256 quote-insert の側で挿入してしまうという事? まあそれで良い気がする。これは 28257 "曖昧補完による特別処置 COMPV= の時の特別な振る舞い" ではなくて、一般に 28258 "COMPV にも comps_fixed にも一致しなかった時の振る舞い" として適当な物で 28259 あるから ad hoc な処置ではない。 28260 28261 x fixed: ブレース展開がある時 comps_fixed は "h{" になるのであって、quote 28262 の開始 "'" を含む訳ではない。comps_fixed に続いて quote 文脈に応じた 28263 quote 開始を挿入する必要がある。 28264 28265 これに関しても comps_flags に応じて勝手に引用符を挿入するというので良い気がする。 28266 comps_fixed に入る文字列はちゃんと quote を閉じていると期待したい。 28267 因みに h{aaa,'ll となっている場合は comps_fixed は一体どうなるのか? 28268 と思って調べた所、 28269 28270 * done: [[ $compv ]] のチェック in reduce。COMPV から compv_fixed を取り除 28271 いた後 compv= (空文字列) になっている時に、"最初の一文字を切り出す" 処理 28272 をするのは変である。見た感じ問題が起こりそうな気配もないがちゃんとチェッ 28273 クしておく。 28274 28275 o echo 'hll<TAB> 28276 o echo 'hll<TAB> (complete -r) 28277 o echo h{'ll<TAB> (complete -r) 28278 o echo h{aaaa,'ll<TAB> (complete -r) 28279 28280 * complete: bash_completion の autoload が初回に失敗する問題 [#D1386] 28281 28282 [まとめ] これは echo h"ll 中に見つかった不自然な振る舞いから。結局、 28283 autoload した後再度補完を実施する事を要求する 124 の終了ステータス 28284 を受け取った時、改めて補完関数の探索からやり直す所で、default opts 28285 が残っていた所為で、新しい補完設定ではなくて再び complete -D の補 28286 完設定を使って読み取りを行おうとしていた事が原因だった。これは 124 28287 を受け取った時に default opts を削除して再度補完を実行する様に変更 28288 して解決した。 28289 28290 | 不思議な事に最初の一回はちゃんと補完されて、二回目以降からは補完 28291 | 候補が一致しない物も含めて全て表示される様になる。 28292 | 28293 | 最初の呼び出しではプログラム補完が見つからずにデフォル 28294 | トの補完が走って、それが失敗する事によって次の曖昧補完に移行し 28295 | ている。二回目以降の補完ではプログラム補完が呼び出されてそれが 28296 | 成功するので曖昧補完が走らない。 28297 | 28298 | プログラム補完が見つからないとご判定されているのかと考えたが、 28299 | 実際に補完は見つかっておらず complete -p echo しても補完指定が 28300 | 見つかりませんでしたと表示される。という事は別の箇所で echo に 28301 | 対する補完指定が設定されているという事になる。何処だろうか。 28302 | 28303 | 恐らく default を使って compgen を呼び出したタイミングだろう。 28304 | 中を覗くとちゃんとデフォルトの補完が読み込まれて 124 を返して、 28305 | 結果として再度補完が走って、最終的にちゃんと補完が呼び出される。 28306 | 28307 | % ここで気づいた事…。何故か compgen に渡されている compv が空 28308 | % になっている。124 で再ロードした後にのみちゃんと値が設定され 28309 | % ている。と思ったらこれは勘違いだった。 28310 | 28311 | 一回目と二回目を比較してみると…どうも compopt の内容が違う。ど 28312 | うして前者では候補が生成されず (期待通り)、後者では合致しない候 28313 | 補が生成されてしまうのか。 28314 | 28315 | H2332:builtin compgen -o bashdefault -o de 28316 | fault -F ble/complete/progcomp/.compgen-he 28317 | lper-func -- 'hll' 2>/dev/null 28318 | comp_func=_python_argcomplete_global 28319 | 28320 | H2332:builtin compgen -F ble/complete/prog 28321 | comp/.compgen-helper-func -- 'hll' 2>/dev/ 28322 | null 28323 | comp_func=_minimal 28324 | 28325 | 補間関数も含めて比較してみると両者が異なっている。何故? というよ 28326 | りリロードして評価した筈なのに何故再度同じ関数が呼び出されている 28327 | のか?? 漸く分かった。compgen の引数に "default" が入っているので、 28328 | 124 で再ロードしても default 用の補間関数が呼び出されてしまうと 28329 | いう問題であった。 28330 28331 * complete: echo h"ll<TAB> で bash_completion が全ファイル名を列挙する [#D1385] 28332 28333 [まとめ] これは extract-command で閉じていない単語を回収するのに失 28334 敗していたのが原因だった。閉じていない単語を仮に実体化していたがそ 28335 の時の単語の種類 wtype が CTX_ARGX になっていた。然し、 28336 extract-command は CTX_ARGI しか回収していなかった。単語を仮に実体 28337 化する時に、ctx-word-end で実際にやっているのと同様に wtype を補正 28338 する事にした。 28339 28340 | これはどうも bash_completion が入っていると駄目のようである。 28341 | bash_completion の生成する候補に問題がある? 28342 | もしくは、progcomp による yield に問題がある? 28343 | うーん。実は bash_completion による候補は filtering で全て消える? 28344 | 28345 | 一回どのような候補が生成されているのか確認する必要がある? 取り敢 28346 | えず bash_completion は全てのファイル名を列挙する。filter:head 28347 | は何もしていない様に見える。実際に動作を見てみると何もしていない。 28348 | つまり、progcomp が生成した物をそのまま使うという作戦になってい 28349 | る。これはまあ理解できる。一方で bash_completion が遡って書き換 28350 | えの起こる候補を全て出すのも理解できる。 28351 | 28352 | これに完全に対応する為には bash_completion の生成した候補に対し 28353 | てフィルタをかける必要があるが…うーん。フィルタをかけて有限個の 28354 | 候補が残ればOK、そうでなければそのまま沢山の候補を保持するという 28355 | 作戦? でもよくわからないのは最初の補完ではちゃんと補完ができると 28356 | いう事。何故だろう。 28357 | 28358 | 改めて bash_completion の振る舞いについて確認する。ble.sh なしで 28359 | 実行すると h"ll に対してエラーメッセージが出るが最終的にはちゃん 28360 | と何も候補を生成せずに終わる。然し、経由だと全ての候補が列挙され 28361 | てしまっている。つまり、ble.sh の時と bash の時でやはり何らかの 28362 | 違いがあるという事だろうか。具体的に ble.sh による呼び出しの時と、 28363 | bash による呼び出しの時でどのような違いがあるのかについて調べる 28364 | 事にする。 28365 | 28366 | * 取り敢えず今までに埋め込んだデバグ用の出力は全て削除する。 28367 | * _minimal に対して advice を仕掛ける。 28368 | 28369 | | ble.sh の下では、 28370 | | ----------------- 28371 | | 28372 | | COMP_CWORD='1' COMP_KEY='67108969' COMP_LINE='echo ' 28373 | | COMP_POINT='5' COMP_TYPE='9' 28374 | | COMP_WORDS=('echo' '') 28375 | | COMPREPLY=('a b' 'a b' 'a' 'bc' 'a xyz' 'h ello') 28376 | | 28377 | | bash の下では 28378 | | ------------- 28379 | | 28380 | | COMP_CWORD='1' COMP_KEY='9' COMP_LINE='echo h"ll' 28381 | | COMP_POINT='9' COMP_TYPE='9' 28382 | | COMP_WORDS=('echo' 'h"ll') COMPREPLY=() 28383 | 28384 | 成程、これは ble.sh が悪い。COMP_WORDS の復元に失敗している。空 28385 | の単語になってしまっている。COMPV 等に基づく候補生成はちゃんと動 28386 | いているという事を考えると、extract-command か或いは COMP_WORDS 28387 | の構築に失敗している。 28388 | 28389 | 確かめた所、extract-command の時点で失敗しているという事が判明し 28390 | た。問題は h'll の時にはちゃんと成功しているのに何故 h"ll の時に 28391 | はうまく行かないのかという事。" が中に構造を持つ事ができるという 28392 | 事に関係しているだろうか。 28393 | 28394 | 実際に構文木を見てみると確かに nest が設置されていて単語が構築で 28395 | きていない状態になっている。本来は擬似的に文法構造を閉じてその上 28396 | で解析するのではなかったか。覚えていないがその様な処理が何処かに 28397 | あった筈。これである。 28398 | 28399 | ble/syntax/tree-enumerate/.initialize で TE_root を 28400 | ${_ble_syntax_tree[iN-1]} の補正版として初期化している。本来はこ 28401 | れによって nest が閉じられて単語になって欲しいのだが、実際にはそ 28402 | うはなっていない。然し、f11 による画面でも文法構造が確定せずエラー 28403 | の様な状態になっている。と思ったが f11 による画面では文法構造を 28404 | 閉じていないので当然といえば当然である。具体的に問題の起こる状況 28405 | で TE_root がどの様に復元されているかを確認すると以下の様になっ 28406 | ている。 28407 | 28408 | TE_root='3 4 0 5 -- none 3 -1 -1 -- ' 28409 | 28410 | 3 は wtype で 4 は現在の単語の長さである。此処までは正しい。0 は 28411 | 子単語までの offset であり、実は同じ位置に子単語が存在している。 28412 | 子ノードは wtype=none (nest 構造) であり、長さは 3 である。子や 28413 | 兄要素は存在しない。実際にこれに問題があるのかどうかの判定は分か 28414 | らない。見た感じは明らかな異常はない様に見える。特に長さが "4" 28415 | となっている以上は長さ4の単語を抜き出せて良いのではないだろうか。 28416 | 28417 | 何故正しく単語を抜き出せないのかについては、実際にどの様に 28418 | tree-enumerate が走るのか確認するしかない。 28419 | 28420 | * 色々分かった。TE_root の復元によって生成された単語は CTX_ARGX 28421 | になっている。一方で通常の単語は CTX_ARGI である。 28422 | extract-command では ARGI な単語しか収集していない。つまり 28423 | ARGX による単語は register-word が呼び出されず登録されない事に 28424 | なる。 28425 | 28426 | 一方で、一番最初に見つかった単語の終端がが現在の起点の位置より 28427 | も前にある場合には、現在の起点の位置に長さ 0 の単語が存在して 28428 | いると見做して、"" の単語を挿入する。この空単語は ARGX になっ 28429 | てスキップされた単語とは何の関係もない。 28430 | 28431 | この状況に於いてどのように修正するのが正しいか。TE_root を構築す 28432 | る時に ARGX → ARGI の規則を適用するのが良い気がする。その様にし 28433 | たらあっさりと動く様になった。 28434 28435 2020-09-05 28436 28437 * ln23.para.bscc が何故か SM(?1004) Any event mouse を設定する [#D1384] 28438 これにより focus/blur で SS3 I, SS3 O が送信される様になって 28439 ble.sh が混乱している。SS3 I は TAB になっている。 28440 SS3 O は何のキーにも束縛していないので ESC O O という入力になってしまう。 28441 取り敢えず SS3 O を認識する様に修正する。 28442 28443 2020-09-03 28444 28445 * 2020-08-31 util: is-global の実装はちゃんとしているのだろうか [#D1383] 28446 つまり変数が unset 状態にある場合等に対しても予想通りに動作するのだろうか。 28447 また、現在の実装ではヘルパー関数を用いているがこれは本当に必要だろうか。 28448 28449 →試してみると global に declare だけしている変数を local と勘違いする様である。 28450 global に declare だけしている時に readonly すると local でも変数を作れるという事? 28451 と思ったらテストの問題だった。テストは恐らく関数の中で実行しているので、 28452 トップレベルに declare v1u 等としているつもりでも関数内に変数が作成されている。 28453 declare -g を使って明示的にグローバルに unset 変数を作成してテストした所ちゃんと動くことを確かめられた。 28454 28455 * 2020-08-03 ble.sh ロード方法と attach 戦略に対する考察 [#D1382] 28456 関連 (attach=prompt): #D0940, #D0737, #D1124 28457 28458 そろそろ .bashrc の設定方法を変更しても良いのではないだろうか。 28459 特に、 .bashrc の末尾に記述するのが良い気がする。 28460 或いは未だ先頭に . ble.sh を記述する必要性があっただろうか。 28461 28462 ユーザーが ble.sh の有無で bashrc の中の設定を切り替える場合がある。 28463 この場合には最初に source して BLE_VERSION を用いて判定するのが良い。 28464 然し、ble.sh の有無はユーザが独自に判定している場合も多いので、 28465 わざわざこれの為に二箇所に ble.sh のコードを書くのはやはり変かもしれない。 28466 28467 * BLE_VERSION を使って判定する為にはちゃんと読み込みに失敗した時に 28468 unset されていなければならない。ちゃんとその様になっているか。 28469 28470 * _ble_bash と BLE_VERSION の初期化されている位置をまとめた。 28471 * また、_ble_bash 初期化前に値を参照している箇所があったので使わない様に修正した。 28472 * BLE_VERSINFO についても同様に unset する様にした。 28473 * ble/base/unload で _ble_bash, BLE_VERSION, BLE_VERSINFO を削除する様にした。 28474 28475 以下の attach 戦略に対する考察は #T0004 に纏め直した 28476 28477 | 初に記述すると他のフレームワークが勝手に PROMPT_COMMAND を書き換えた時に動かない。 28478 | 後に記述すると他の設定で ble.sh の有無で切り替えを行いたい時に不便である。 28479 | うに、どの場所に記述しても動く様にするのが本当は良いのだろう。 28480 | 状の問題点としては PROMPT_COMMAND を上書きされると動かないという事だけである。 28481 | 28482 | 或いは、その場で attach してしまう方向で改良する手もあるのかもしれない。 28483 | と思ったがそれだと PS1 の設定などが反映される前にプロンプトを表示してしまう? 28484 | その直後に PS1 が設定されて次のキーボード入力の際に更新されるのだろうが、 28485 | それだとちらついたりしてよくない。 28486 | 28487 | 或いは、その場で attach した時には最低限の処理を行って、 28488 | それでユーザの入力を受け付ける様にする。 28489 | PROPMT_COMMAND が生きていれば続きの処理を行って、 28490 | もし上書きされて動いていない場合でもできるだけ問題が起こらない様に処理する。 28491 | 28492 | ble-attach して最初は出力抑制しない作戦 28493 | 28494 | もっと具体的に考える。その場で attach した時の問題点は何かというと、 28495 | attach してプロンプトを表示して、然しその後で bashrc の中から何か 28496 | メッセージが画面に表示しようとしても出力が抑制されているので 28497 | 内容が消えてしまうという事である。 28498 | 28499 | 然し、ble-attach の時は出力を抑制しないでその次のユーザの入力の 28500 | 時に初めて抑制をするという手もある。 28501 | 28502 | x この時には最初のユーザ入力の際に一瞬だけちらつきが発生してしま 28503 | う。 28504 | 28505 | x もう一つの問題点は ble-attach した後に、bashrc の別のシェル設 28506 | 定が画面に何か出力すると表示が乱れてしまうという事である。 28507 | 28508 | 後者の問題を解決する為に、プロンプトの表示は PROMPT_COMMAND まで 28509 | 遅延するという可能性もある。 28510 | 28511 | x しかし、そうすると起動までの時間が気になる。ble-attach すると 28512 | いう事は bind するという事で、bind するという事は keymap の初 28513 | 期化を行うという事である。つまり時間がかかる。本来はそれより前 28514 | にプロンプトは表示しておきたい。まあ、これはそれ程気にしなくて 28515 | も良いかもしれない。 28516 | 28517 | 前者のちらつきの問題に関しては、PROMPT_COMMAND が正しく機能すれ 28518 | ば特に問題ない筈である。 28519 | 28520 | ble-attach して出力抑制もする。後で出力内容を dump する作戦 28521 | 28522 | 或いは ble-attach してから次のユーザ入力を得るまでの間に bashrc 28523 | から出力された内容は適当なタイミングで画面に出力する様にする? 28524 | これは一つの手であるような気がする。PROMPT_COMMAND が有効であれば、 28525 | その瞬間にそれまでに出力された内容を dump すれば良い。 28526 | 28527 | x ただし、時間のかかる処理やプログレスバー等の表示があると最後に 28528 | 一気に表示するので期待はずれの動作になる 28529 | 28530 | x 更にユーザの入力を求める処理があると何も表示されない状態になっ 28531 | て困る。いざ /dev/tty に対して読み書きするプログラムがあったとし 28532 | ても、今度は逆に画面の表示が乱れてしまう。 28533 | 28534 | 等などの事を考えるとやはり ble-attach してから、後の bashrc の処 28535 | 理を適当に流すというのは難しいのではないか。或いは本格的に bash 28536 | の出力を別のプロセスに繋げて、そのプロセスで出力内容を選別しなが 28537 | ら適当に描画を乱さない様に調整する? と思ったがそれだと本格的に端 28538 | 末を実装する様な物だし、/dev/tty を使われたら結局調整もできなく 28539 | なる。駄目。 28540 | 28541 | 或いは trap RETURN もしくは trap DEBUG を用いて PROMPT_COMMAND 28542 | を監視する? 上書きされたり破壊されたりしたら復元する。 28543 | 28544 | 関連する議論が #D1124 及び D#0737 にある。然しこれも微妙である。 28545 | 28546 | x trap DEBUG はコマンドの実行直前に実行されるので、bashrc の一番 28547 | 最後の行で PROMPT_COMMAND が書き換えられると駄目。それに trap 28548 | DEBUG 自体を上書きされてしまうと動かなくなってしまう。それに 28549 | trap DEBUG は結構面倒である。 28550 | 28551 | x trap RETURN は bashrc の末尾では発生しないようなのでこれは全然 28552 | 使えない。 28553 | 28554 | れ以外に不定期で呼び出される hook の類は存在しただろうか。本当は 28555 | OMPT_COMMAND が変更された時にそれを検出できたら良い。或いは 28556 | OMPT_COMMAND に対する読み書きを全て hook できたら良い。然し、ス 28557 | リプトだけでそれを実現する方法はないのだろうという気がする。 28558 | 28559 | EXIT はプロセスが終了する時にしか呼び出されないし、ERR もコマン 28560 | ドが失敗した時にしか発生しない。bashrc の最後に自動的に失敗する 28561 | コマンドを呼び出させる方法もない。 28562 | 28563 | command_not_found_handle はコマンドが見つからない場合にしか呼び 28564 | 出されない。それにディストリビューションによって何か処理が設定さ 28565 | れるだろうから PROMPT_COMMAND と同様の問題がある。寧ろ、処理の追 28566 | 加という事ができないので PROMPT_COMMAND にも増して使いづらい。 28567 | 28568 | bashrc の処理を見たら bashrc の最後に介入する方法が見つかったり 28569 | しないか。と思ったが eval の最後に何もないように bashrc の最後に 28570 | も特別な物は何もないだろうという気がしてならない。 28571 | 28572 | bash は maybe_execute_file という関数を用いて bashrc を呼び出す 28573 | 様である。調べてみるとどうもファイルの中身を丸ごと文字列 string 28574 | に読み込んで、更にそれを parse_and_execute で一気に実行する様で 28575 | ある。第三引数のフラグには SEVAL_RESETLINE を設定している。然し、 28576 | parse_and_execute の中には介入できそうな場所はやはりない。 28577 | 28578 | 或いは execute_prompt_command を見たら何かないだろうか。またはそ 28579 | の呼び出し元。execute_prompt_command を見たら単に PROMPT_COMMAND 28580 | を見ているだけである。呼び出し元は parse_command であり、その冒 28581 | 頭で run_pending_command を呼び出している。うーん。これが使える? 28582 | 28583 | kill -USR2 $$ をしたら trap handler が実行されるのはどのタイミン 28584 | グだろうか。もし bashrc が終わってから一括で実行されるのであれば 28585 | kill -USR2 $$ で bashrc 直後の処理を予約できる。 28586 | 28587 | うーん。駄目だった。その場で実行される。kill -USR2 $$ & として見 28588 | ても駄目だった。USR2 が届いてから次のコマンドを実行する直前に実 28589 | 行されるという事の様である。 28590 | 28591 | PROMPT_COMMAND の代わりに PS1 に $(kill -USR2 $$) をしかける等の 28592 | 手もあるかもしれないが、これは PROMPT_COMMAND と同じ問題が在る。 28593 | というより、PS1 は追記ではなく置き換えて使う物なので 28594 | PROMPT_COMMAND よりも信頼性は低い。 28595 | 28596 | もし PROMPT_COMMAND を上書きした犯人がいるのだとしたら、上書き後 28597 | のコマンドを必ず実行する筈で、だとすればそれを trap DEBUG で判定 28598 | できるのではないか。 28599 | 28600 | | そして bashrc の中か外かの判定ができれば OK. と思ったが #D1124 28601 | | を見ると 4.3 以降で動く微妙な方法しかない様だ。 28602 | | 28603 | | * reject: 或いは bashrc の中で declare などしておけばそれが消滅 28604 | | した事を見れば bashrc の外に来たと分かる? と思ったが実際に試し 28605 | | てみるとbashrc の中で設定した declare はそのままグローバルスコー 28606 | | プになる様だ。なのでこれは使えない。 28607 | | 28608 | | どうやら関数の中で ${BASH_SOURCE[-1]} を参照してそれが bashrc と 28609 | | 一致しているかを確かめれば良さそうだ。と思ったが…。現在の 28610 | | bashrc が何かを知る方法がない。BASH_ENV に入っているのは別の変数 28611 | | の様子だ。grep して確かめると BASH_ARGV の末端には bashrc の名称 28612 | | が格納されている様だが、これは関数の中では何れにしてもトップレベ 28613 | | ルの関数名が入っているので区別できないのでは。 28614 | | 28615 | | 唯、一つ明らかなのは、bashrc の中にいる間は BASH_SOURCE に何か設 28616 | | 定されていて、PROMPT_COMMAND を実行しようとした瞬間には何も設定 28617 | | されていないという状態になるという事。なので原理的に可能である。 28618 | | 28619 | | x PROMPT_COMMAND に関数定義だけ設定されている等の時、DEBUG は呼 28620 | | び出されないのでは。まあその様な特殊な場合には仕方がない。 28621 | | 28622 | | * 重大な問題として bashrc の中で source ble.sh したのと、普通の 28623 | | 対話コマンドの一部として source bashrc して間接的に source 28624 | | ble.sh したのをどう区別するのかという事。後者の場合には、 28625 | | source bashrc; echo hello 等としていた時のためにトップレベルま 28626 | | で戻ったとしても即座に PROMPT_COMMAND になったと判定して発火す 28627 | | るのではなくて、本当の PROMPT_COMMAND が現れるまで待たなければ 28628 | | ならないのでは無いか。 28629 | | 28630 | | LINENO を参照すれば判定できる? と思ったが LINENO は対話コマン 28631 | | ドではコマンドの番号であるが、bashrc の中ではファイル内の行番 28632 | | 号という事になっている。使えない。 28633 | | 28634 | | うーん。もしかして BASH_LINENO[-1] が常に0? 28635 | 28636 | PROMPT_COMMAND など外部のコマンドの実行直前に発火したい。bashrc 28637 | の外に出た事を検出する必要がある。 28638 | 28639 | * DEBUG で [[ ${FUNCNAME[-1]} == source ]] である事を監視して最 28640 | 初にそれが破れた瞬間を PROMPT_COMMAND もしくは別のコマンドと考 28641 | えれば良い気がする。 28642 | 28643 | * [[ $BASH_COMMAND == $PROMPT_COMMAND ]] は使えない。何故なら 28644 | PROMPT_COMMAND が単一のコマンドとは限らないから。それに古い 28645 | version の bash だと BASH_COMMAND は本当に今のコマンド [[ 28646 | ... ]] になってしまうので当てにできない。 28647 | 28648 | x PROMPT_COMMAND が空に設定されてしまった時や、PROMPT_COMMAND に 28649 | 関数定義だけが記述された場合には検出ができなくなってしまうが、 28650 | その様な場合は稀であるし、それで逃したとしても次の別のコマンド 28651 | の実行時に attach が発火するので問題ない気がする。 28652 | 28653 | * 現在 rcfile の実行中である場合には ${BASH_LINENO[-1]} == 0 に 28654 | なっている。 28655 | 28656 | 然しよく考えたら rcfile かどうかを区別する必要はあるのだろうか。 28657 | 対話コマンドで source .bashrc と入力した場合を考えると、この場 28658 | 合にも .bashrc の中で PROMPT_COMMAND を上書きされる可能性を考 28659 | えると同様に対策が必要になるのではないだろうか。 28660 | 28661 | * rcfile で実行している時には rcfile の外に出た瞬間に attach 28662 | して良い。何故ならば rcfile の外に出たら次は PROMPT_COMMAND 28663 | の実行以降であり既に attach のタイミングになっているから。 28664 | 28665 | * 対話コマンドで実行している時には top level の source を抜け 28666 | たとしてもすぐに attach して良いとは限らない。何故ならその後 28667 | に直接また別のコマンドを記述しているかもしれないから。ここで 28668 | 出来るのは PROMPT_COMMAND に別の値が設定されていた時にそれを 28669 | ble.sh のそれに修正する事である。然し、現在 PROMPT_COMMAND 28670 | が実行されている時に限れば、その場で attach しなければならな 28671 | い。その為には現在実行しているのが PROMPT_COMMAND なのか或い 28672 | は通常のコマンドなのかを判定する必要がある。それは 28673 | BASH_LINENO が増えたかどうかで判定できるだろうか? と思ったが 28674 | 多分難しい。 28675 | 28676 | * どうやら HISTCMD / ${_histcmd@P} の結果で判定できる気がする。 28677 | 対話コマンドの実行中は HISTCMD には履歴項目の個数が入ってい 28678 | るが、PROMPT_COMMAND の実行中は 1 に展開される。HISTCMD が 28679 | unset されていたとしても ${_histcmd@P} (_histcmd='\!') は 1 28680 | に展開される。HISTCMD が unset されているかどうかは 28681 | ((HISTCMD++)) して数が変化するかどうかを確認すれば良い。 28682 | 28683 | * ソースコードも確認したがやはり PROMPT_COMMAND を区別するのは 28684 | 本質的に難しい? PROMPT_COMMAND は parse_and_execute 経由で実 28685 | 行していて、この時フラグに SEVAL_NONINT|SEVAL_NOHIST を指定 28686 | している。つまり $- を見たら違いが分かるかもしれない? と思っ 28687 | て確認したら通常コマンドも PROMPT_COMMAND も himBHs だった。 28688 | 28689 | 別に分かった事は rcfile の処理中は $- に s が存在していなく 28690 | て、PROMPT_COMMAND の時には s が存在しているという事。s は何 28691 | か。man によると bash の起動時の -s は位置パラメータの指定が 28692 | あるかどうか? いや、標準入力から読み取るモードになっている時 28693 | に s が入るのである。 28694 | 28695 | 類似の変数として $BASHOPTS があるが、こちらは rcfile とそれ 28696 | 以降で違いは見られない。 28697 | 28698 | bash の変数 "interactive" で振る舞いが変わる物を使って 28699 | interactive の状態を検出できるだろうか。ソースコードを検索す 28700 | ると取り敢えず alias は non-interactive の時にだけ有効になっ 28701 | ている気がする。 28702 | 28703 | * DEBUG trap の取り扱いが難しいという事に注意する。これについて 28704 | は未解決の task が存在した筈である。 28705 28706 28707 2020-08-29 28708 28709 * 2020-08-24 auto-menu を有効にしていると vbell がずっと鳴っている状態になる [#D1381] 28710 auto-menu は大々的には告知していないし manual にあるだけなので 28711 使っている人はいないのだろうという気がするが修正する必要がある。 28712 28713 * 2020-08-23 main: bash-5.1 で PROMPT_COMMANDS が定義されている時 --attach=prompt が効かない [#D1380] 28714 28715 PROMPT_COMMANDS 経由で attach する様にしなければならない。 28716 また PRPOMPT_COMMANDS 経由で attach した場合は、 28717 attach した後に自身を消去する必要がある。 28718 28719 書いている内に分からなくなった。PROMPT_COMMAND と共存する為にどう 28720 したら良いのか。結局 bug-bash で議論を呼びかけてみたが良い解決方法 28721 は存在しないし、Chet はこれに対する対策はする気がない様である。 28722 28723 * Chet は distro が PROMPT_COMMANDS と PROMPT_COMMAND の両方に設定 28724 を行うと主張しているが謎である。もし両方有効になるという具合に宣 28725 伝したらちゃんとバージョンを見て一方だけに設定するに違いない。そ 28726 の場の思いつきで適当な事を書いているのではないかと疑わしい。 28727 28728 * 結局、不完全な対策方法しかない。或いは PROMPT_COMMAND を 28729 readonly unset するか。と思ったがそうした所で警告が発生されるだ 28730 けで問題が解決する訳ではない。 28731 28732 取り敢えず不完全な解ではあるが、PROMPT_COMMAND に値が設定されてい 28733 て、かつ PROMPT_COMMANDS に何も設定されていない時に限り、 28734 PROMPT_COMMAND を PROMPT_COMMANDS に変換して、その上で値を設定する 28735 事にした。まあ、これが妥当な妥協点であろう。 28736 28737 2020-08-31 attach した後に PROMPT_COMMANDS から項目を削除するのを忘れていた。 28738 と思って気づいたが PROMPT_COMMANDS を実行中に PROMPT_COMMANDS を編集すると何が起こるのか。 28739 →実際に試してみると PROMPT_COMMANDS を再代入した時に後続の処理が実行されなくなる。 28740 なので ble/array#remove を使うのではなくて空文字列で上書きするか unset するかする必要がある。 28741 28742 - 新しく ble/array#replace を実装してそれを使う様にするか。 28743 然しもしこの bash の振る舞いが修正されるのだとしたら、 28744 わざわざ新しく変な関数を追加する必要もないのではないか。 28745 28746 - 問題は現在の bash-dev の振る舞いが変更される見込みはあるのかという事である。 28747 これが意図的な振る舞いだとしたらそうなる可能性はない。 28748 もしこれが意図的な振る舞いでないとしたら、 28749 現在の振る舞いが直感的であるとは思われないので変更の余地はある。 28750 もしこれにより実際に変な事 (メモリ破壊など) が起こる可能性があるのであれば、 28751 明らかに問題であるのでパッチを受け入れて貰える可能性がある。 28752 28753 % 従って何れにしても先ずは bash の実装を調べるという事である。 28754 bash の振る舞いに関してはまた別に議論する事にした。 28755 28756 2020-08-31 と改めて確認してみたら PROMPT_COMMANDS は PROMPT_COMMAND に改名されていた。 28757 コードを書き換えなければならない。書き換えた。 28758 面倒なので取り敢えずは bash の将来的な修正はさておくとして ble/array#replace を使った。 28759 28760 2020-08-25 28761 28762 * syntax: syntax-highlighting を無効にする機能 (requested by pjmp) [#D1379] 28763 https://github.com/akinomyoga/ble.sh/issues/61 28764 28765 #58 に関連して実装しようかと思っていたが丁度 request が来た。実装する 28766 28767 * done: 取り敢えず三種類のオプションを実装した。 28768 * done: wiki と blerc にも説明を書いた。 28769 28770 * 完全に着色を消滅させるには以下を実行すれば良い筈だが、 28771 自動補完やメニュー補完による一次挿入などが見えなくなるので余り有用性はないだろう。 28772 28773 $ _ble_term_color=1 28774 $ bleopt term_true_colors=none 28775 28776 これはコメントで書くだけに留める。 28777 28778 * done: 動作テストも実施した。幾つか修正した。 28779 28780 2020-08-22 28781 28782 * prompt: bleopt prompt_screen_title や prompt_xterm_title 等を用意しても良い [#D1378] 28783 28784 * done: 自動的に screen/tmux を判定してこれらを有効にする。 28785 どちらも異なる TERM を設定している事があるので DA2R によって判定したい。 28786 28787 https://qiita.com/kefir_/items/0bda5e55f43392420d66 によると tmux の DA2 は 28788 0;95;0 という事になっているが実際に確かめてみると 84;0;0 になっている。 28789 0:95:0 だと xterm と区別がつかないので無視する事にする。 28790 28791 * done: ASCII 以外の文字を自動的に # 等に置換する機能も考えられる。 28792 28793 * done: tsl, fsl で囲む様にする。と思ったが微妙な気がする。 28794 tsl, fsl は status line の内容を指定する物で、 28795 tmux の terminfo は OSC 0 と同一視しているが、 28796 xterm 等他の terminfo は OSC 0 とは考えていない。 28797 tmux は確かに OSC 0 の内容をステータスに表示するからそれで正しいのだろう。 28798 然し、端末によってはステータスバーが別個にある場合もあり必ずしも 28799 tsl/fsl が OSC 0 に対応している訳ではない。 28800 28801 →新しく独立した設定を作成する事にした。 28802 28803 結果として 28804 - bleopt prompt_xterm_title 28805 - bleopt prompt_screen_title 28806 - bleopt prompt_status_line 28807 の三種類の設定を追加する事になった。 28808 28809 * done: wiki.en, wiki.ja, blerc 28810 28811 * prompt: bleopt prompt_rps1= を clear しても内容が残り続けて表示が乱れる [#D1377] 28812 prompt_rps1 に別の有限の大きさの文字列を指定した時には問題は起こらない。 28813 これは prompt_rps1= の時に rprompt の情報が全く更新されないのが問題だった。 28814 クリアすらされなくなってしまう。修正した。 28815 28816 * contrib: prompt-git で適当にキャッシュを行うようにしたい [#D1376] 28817 ble.sh の側からは cache の更新を管理するために、 28818 _ble_prompt_update という変数を提供する事にした。 28819 contrib/prompt-git でキャッシュする様にした。 28820 28821 これは mshex で screen の window-title にリポジトリ名を表示するため。 28822 取り敢えず mshex にこれを利用して git name を PS1 screen title から 28823 表示する様に実装してみた。動いている。 28824 28825 * complete: menu に高さ制限を加えるオプションを追加する [#D1375] 28826 28827 menu に高さ制限を加えた方が良いかもしれない。 28828 自動的に表示される物で画面がクリアされてしまうのは不便といえば不便である。 28829 自動で表示する場合には menu に高さ制限を加えるのも一つの手である。 28830 然し、自動でメニューを表示した後に手動のメニューに移行する場合にどのようにするのか。 28831 例えば、メニューの項目に入る時に再配置が起こるのは問題がある気がする。 28832 然し、だからと言って TAB で表示したメニューと自動で表示したメニューで 28833 高さが異なるままメニュー選択に入るのも一貫性がない様な気がする。 28834 28835 実は、通常の場合でも高さ制限を加えたいという需要はあるかもしれない。 28836 ユーザが高さ制限を指定してそれを TAB 補完でも自動メニューの共通の設定とするのが自然。 28837 28838 どの様に高さを決定しているのかを調べようとしたが、 28839 どうも cols lines の変数の初期化が怪しい。 28840 複雑になりそうなので先に auto_menu だけでも commit する事にする。 28841 28842 | - "$menu_class"/render-item 28843 | - ble/complete/menu#render-item 28844 | - ble/complete/menu-style:align/construct/.measure-candidates-in-page 28845 | - "$menu_style"/construct-page 28846 | - ble/complete/menu#construct (init) 28847 | - "$menu_style"/construct-page (done) 28848 | - ble/complete/menu#select (init) 28849 | 28850 | - "$menu_style"/guess 28851 | - ble/complete/menu#construct (done) 28852 | 28853 | - [fixed] ble/complete/menu#construct 28854 | これは中で使っている様に見えるが呼び出し元を確認しても設定している様子がない。 28855 | 更に、同じ関数内の後で local cols lines として初期化を行っている。 28856 | これは書き換えのミスではないだろうか。 28857 | 28858 | 少なくとも一つのケースで cols= lines= と空である事を確認した。つまりこれはミスである。 28859 | 28860 | - [fixed] ble/complete/menu#select (1) 28861 | 内部で cols lines を初期化しているがどの関数が使っているのか不明。 28862 | ble/complete/menu/show しか使っていない様に見えるが、 28863 | ble/complete/menu/show は cols lines を外から受け付けたりはしない筈である。 28864 | 後で再確認する→やはり ble/complete/menu/show は cols lines を外から受け付けない。 28865 | この初期化は削除する事にする。 28866 | 28867 | - ble/complete/menu#select (2) 28868 | もう一箇所では cols lines を初期化した後に 28869 | ble/complete/menu#render-item を呼び出している。 28870 | これは必要な初期化である。 28871 28872 既存の cols lines の仕様については整理した。OK 28873 新しく行数を制限する様に実装した。動いている。OK 28874 28875 * prompt: \q{...} で存在しない物を指定した時 [#D1374] 28876 文字を入力するたびにエラーメッセージが表示される。 28877 これが意味する所は実はキー入力をする度にプロンプトの計算を 28878 再実行しているのではないかという事。 28879 確認する必要がある。 28880 28881 先ず再現する事を確認する→再現する。つまり毎回 instantiate しているという事。 28882 分かった…。強制的に更新する場合に force=1 を設定する所が、最初から force=1 になっていた。 28883 06381c96 (2020-05-21 12:32:58 +0900) で埋め込まれたバグである。 28884 修正したら毎回 instantiate するという事はなくなった。 28885 28886 然しこれが速度に大きな影響を与えているとは思われない。 28887 と思ったら…何と毎回シェル展開まで実行していた。 28888 つまり $() 等のコマンドもキー入力が起こる度に呼び出されていた事になる。 28889 28890 * 2020-08-05: complete: auto-complete で menu も出してしまう? [#D1373] 28891 28892 * bleopt complete_auto_menu=DELAY で設定する。 28893 ble/complete/auto-complete.idle の中で 28894 ble/complete/auto-complete.impl の直後に 28895 local delay=$((bleopt_complete_auto_menu)) 28896 ble/util/idle.push -S"$delay" "show-menu" を呼び出して 28897 遅延でメニューを表示させる。 28898 28899 と思ったがよく考えたら自動補完候補とメニュー補完では候補が異なる。 28900 特に履歴項目から自動補完を実行している時。 28901 というか自動補完を実行している時は候補一覧を保存していない気がする。 28902 28903 或いは別に自動補完とメニュー補完の内容が一致していなくても良い気がする。 28904 →取り敢えず独立な内容を提示する様にする事にする。 28905 28906 適当に実装してみたら微妙な事になっている。 28907 これらはゆっくり修正すれば良い気がする。 28908 28909 x fixed: コマンドラインが空でもメニューが表示されてしまう。 28910 空白の文字列からは補完が開始しない様にするべきかもしれない。 28911 ble/widget/complete に non-empty 的な opt を追加する。 28912 28913 →今度は二文字以上入力しないと show_menu されない様になってしまった。 28914 何故だろうか。とにかくまた後で調べる事にする。 28915 →これは以下の問題を解決したら一緒に直った。 28916 28917 x fixed: menu が表示される場合と表示されない場合がある。 28918 auto-complete で self-insert した時に起動しない様になっていた。 28919 auto_complete/self-insert の直後でも起動する様に修正した。 28920 28921 x fixed: 最後のユーザー入力からの経過時間で起動するべきところが、 28922 最初の auto-complete からの経過時間で起動している。 28923 これは auto-complete と同様の方法で起動するべきではないだろうか。 28924 28925 x fixed: menu が表示されている状態で一文字でも入力するとメニューが閉じてしまう。 28926 これは menu-filter 状態になっていないから? 28927 勝手に menu-filter 状態に移行するのも考え物だが…。 28928 28929 どうやら menu-filter が無効になっている様子だ。 28930 _ble_complete_menu_active= になっている。 28931 調べてみると一旦は _ble_complete_menu_active=1 になるが、 28932 直後に get-active-range に失敗して menu/clear が呼び出される様だ。 28933 28934 分かった。auto-complete の中から menu に入っている為に、 28935 記録される left,right の中身が auto-complete によって 28936 一時的に挿入されている物を含む様になっている。 28937 menu 表示次の状態記録で keymap が auto_complete の時には、 28938 一時的に挿入されている文字列を除去する事にした。 28939 28940 * todo: complete_auto_menu の説明 28941 * done: blerc 28942 * done: wiki 英語 28943 * done: wiki 日本語 28944 28945 2020-08-06 28946 28947 * fzf の設定でエラーが発生する (reported by tigger04) [#D1372] 28948 https://github.com/akinomyoga/ble.sh/issues/60 28949 28950 bind '"...": fzf-file-widget' の様に -x を 28951 指定し忘れたかの様なエラーメッセージが出ている。 28952 更に、_fzf_setup_completion というコマンドが 28953 存在しないというメッセージも出ている。 28954 然し、fzf のソースを見る限りはその様な事はあり得ない。変だ。 28955 28956 | fzf を最新版に更新してもらったが変化はない。 28957 | 実際に使われている completions.bash, key-bindings.bash を貼って貰ったが 28958 | やはり勝手に編集しているという事はなくて 28959 | 28960 | ? bash 5.0.18 が悪い? 28961 | コンパイルし直してみたが別に問題は発生していない。 28962 | 28963 | ? 或いは ble.sh が bind を上書きする前に fzf が bind を実行して、 28964 | その後で ble.sh が bind -X の設定を読み取る時に失敗している? 28965 | 28966 | 然し、そうだとしても _fzf_setup_completion の問題の説明が付かない。 28967 | というより、_fzf_setup_completion のエラーが 28968 | どう ble.sh と関わってくるのか謎である。 28969 | 28970 | x fixed: .fzf.bash を先に実行すると設定が反映されていない? 28971 | →試しに先に .fzf.bash を source する様にしてみたが機能していない。 28972 | というより、そもそも bind -x の結果がちゃんと呼び出されていない気がする。 28973 | 或いは、bind の出力結果から設定を復元する機能が有効になっていない? 28974 | 28975 | 調べると ble/builtin/bind/read-user-settings で復元する機能が有効になる筈。 28976 | ここでちゃんとユーザ設定として fzf の設定が残っているか確認する。 28977 | →何とユーザー設定は空である。 28978 | 28979 | うーん。どうも途中でクラッシュしている様だ。 28980 | 振る舞いを見ると標準出力に何か出力しようとすると終了する。 28981 | SIGPIPE が怪しい。という事は後段の awk が勝手に終了してしまっている。 28982 | →分かった。ble/bin/awk を呼び出すべき所を /ble/bin/awk を呼び出そうとしていた。 28983 | つまり、そもそも後段のプログラムが正しく起動していなかったのが原因。 28984 | これを修正した所、ちゃんと fzf の設定が反映される様になった。 28985 | 28986 | そして .fzf.bash を先に読み込んでも 28987 | 報告されているエラーメッセージは特に表示されない。 28988 | 28989 | うーん。やはり謎である。取り敢えず確実である。 28990 | 28991 | shopt -s extdebug 28992 | ble/function#advice before bind \ 28993 | '[[ ${ADVICE_WORDS[*]} == *fzf* ]] && ble-stackdump' 28994 | 28995 | これを試してもらおうと思ったがそもそも contrib 経由で呼び出している時には、 28996 | bind を封じている筈なので bind からエラーメッセージが出てくる筈がない。 28997 | これが示唆する事は何かというと @tigger04 は別の箇所で .fzf.bash も呼び出している。 28998 | 28999 | 恐らく Option 2 で出ているエラーメッセージは .fzf.bash を 29000 | 他の場所で source しない様にお願いすれば解決する。 29001 | 一方で _fzf_setup_completion が見つからないというエラーメッセージの方は謎である。 29002 | 29003 | どうやって調べたら良いのか。 29004 | そもそも問題のメッセージは本当に completions.bash の中で発生しているのか。 29005 29006 bashrc の内容を教えてくれた。 29007 29008 * どうも _fzf_setup_completion は bashrc の中から直接呼び出している様だ。 29009 ble.sh を設定していると何が問題になるのかというと、 29010 fzf の設定の初期化が遅延されるので、 29011 .fzf.bash を読み込んだ直後に _fzf_setup_completion を実行しても 29012 設定が未定義になっているという事である。 29013 29014 これは .fzf.bash の中の ble-import で -d を指定しない様にすれば良い。 29015 29016 * うーん。次の報告が来た。 29017 やはり ble.sh (bind) のエラーは bind の中で発生しているらしい。 29018 もしかすると shopt によって変な振る舞いをしている可能性? 29019 29020 あー。分かった nocaseglob が悪いんだ。 29021 改めて bashrc を見ると nocasematch が設定されている。 29022 29023 ? では何故自分の手元で実行した時には問題が発生していなかったのか。 29024 調べてみるとやはり問題は起こらない。 29025 何故かと言うと、blerc は nocasematch の設定よりも先に呼び出されるからである。 29026 @tigger04 が option 2 をどの様に構成したのかは分からないが、 29027 或いは option 2 を設定した上で更に .fzf.bash も source したという可能性がある。 29028 これは option 2 の使い方として予期したものではないのでこちらでは再現できなかった。 29029 29030 29031 何れにしても問題は明らかになったのでそれの対策をする。 29032 この nocasematch の問題に対してはどの様に対処すれば良いだろうか。 29033 先ず nocasematch の設定について動作を確認する。 29034 どうも nocasematch が入っていると [[ a == A ]] すら一致してしまう。 29035 これは問題になるのではないか。特に opts で一文字の物は変な事が起こる可能性がある。 29036 29037 と思って調べてみると ble/base/adjust-bash-options で 29038 ちゃんと nocasematch の調整は行っている。 29039 うーん。では何故ちゃんと nocasematch の状態になっていないのか。 29040 と思ったが、分かった気がする。そう、builtin bind はユーザの側から呼び出されるので、 29041 nocasematch によって調整されていない文脈で呼び出される可能性があるのである。 29042 29043 core-complete.sh の nocasematch は実は不要なのではないか、 29044 と思ったが、この部分は逆に敢えて一時的に nocasematch を有効にして、 29045 大文字・小文字に関係ない補完を実現するのに使われているのだった。 29046 これはこのままで良い。 29047 29048 取り敢えず bind については nocasematch を一時的に保存復元する事にする。 29049 29050 2020-08-04 29051 29052 * textarea: vi-mode strings がある時の計算がおかしい (reported by tigger04) [#D1371] 29053 https://github.com/akinomyoga/ble.sh/issues/60 29054 29055 先ず、再現するかどうかを確認する必要がある。 29056 再現する。どうも、プロンプトを更新する度に vi-ins-mode-string が 29057 有効になったり無効になったりしてるようである。 29058 29059 * 呼び出し元を調べる必要がある? 29060 呼び出し経路を調べると殆ど同じだが、 29061 ble-edit/bind/.tail の中での行番号が 3 だと有効で 4 だと無効になっている? 29062 然し、両方とも更に呼び出しているのは ble/textarea#render である。 29063 調べてみると、3行目は idle.do の前で、 29064 4行目は idle.do で何らかの処理が走った後である。 29065 然し、これだけで振る舞いが変化するというのも不思議である。 29066 29067 * fixed: 分かった。_ble_decode_keymap が原因だった。 29068 と思ったが、別に表示が乱れる訳ではない…。 29069 もしかすると別の原因かもしれないが取り敢えず直した。 29070 29071 以下はデバグに使ったコード。 29072 29073 > #ble-stackdump "$(cat -A <<< "$expanded")" >> a.txt 29074 > echo "opts=$opts" >> a.txt 29075 > echo "processed: $(cat -A <<< "$processed")" >> a.txt 29076 > echo "expanded: $(cat -A <<< "$expanded")" >> a.txt 29077 > bind -v | grep -E 'show-mode|mode-string' >> a.txt 29078 > echo ---------------------- >> a.txt 29079 29080 * もう一つの問題がある。auto_complete から抜けて prompt の内容が変化しても、 29081 prompt の再描画が実行されていない。prompt の再計算はちゃんとできている。 29082 prompt が変化したらそれを検出できる様にしているのではなかったか。 29083 prompt の再計算と描画がどの様に呼び出されているか改めて確認する。 29084 29085 prompt の再描画は _ble_textarea_invalidated が設定されている時にのみ発生する。 29086 ここで prompt が変更された時に全体を再描画するか、もしくは 29087 部分更新でも特定の条件で prompt の再描画を実施するかという選択肢がある。 29088 部分更新でも prompt の再描画を実行するのが良い気がする。 29089 29090 ble/prompt/.instantiate はプロンプトに変更があったかどうかを終了ステータスで知らせる。 29091 29092 2020-07-18 29093 29094 * TERM=xterm-direct で一部の色が正しく表示されない [#D1370] 29095 どうも TERM=xterm-direct の時には 256 色を terminfo から使う事ができない様である。 29096 という事を考えると xterm-direct の時には init-term.sh で特別に処理する必要がある? 29097 2:r:g:b の形式で 16 色を決め打ちで設定してしまう事も考えたが、 29098 それだとユーザが好みで設定した 16 色の色を使わない事になってしまって良くない。 29099 やはり、ユーザの設定した 16 色を利用する様にする必要がある気がする。 29100 29101 * color: xterm の最新版の既定の TERM が xterm-direct になっていた [#D1369] 29102 xterm は 24bit color を direct color という呼ぶ事にした様だ。 29103 29104 当初 xterm の version 判定を使おうとしたが、もしかするとユーザが 29105 24bit color を使いたくなくて敢えてversion を使うという事もあるかも 29106 しれないと考えて、取り敢えずは TERM だけで判定する事にする。 29107 29108 2020-06-04 29109 29110 * bash-5.1 のその他の変更。ble.sh に修正が必要かもしれない項目 [#D1368] 29111 29112 > 3. New Features in Bash 29113 > 29114 > j. shell-transpose-words: a new bindable readline command that uses the same 29115 > definition of word as shell-forward-word, etc. 29116 > 29117 > p. BASH_REMATCH is no longer readonly. 29118 > 29119 > 4. New Features in Readline 29120 > 29121 > c. Readline automatically switches to horizontal scrolling if the terminal has 29122 > only one line. 29123 > 29124 > e. rl-clear-display: new bindable command that clears the screen and, if 29125 > possible, the scrollback buffer (bound to emacs mode M-C-l by default). 29126 29127 新しい readline bindable に関しては自動的に検出する枠組みを作っても良いのではないか。 29128 一応、以下のコマンドで列挙できる: 29129 29130 $ join -v1 <(bash-dev -c 'bind -l' 2>/dev/null | sort) <(sort keymap/emacs.rlfunc.txt) 29131 29132 現在の所は clear-display, shell-transpose-words が新しい bindable である。 29133 shell-transpose-words は良い。 29134 29135 clear-display は clear-screen と何が違うのだろう。 29136 というより scroll buffer まで clear するという事が果たして可能なのだろうか。 29137 →よく分からないので実際に実装を調べてみると termcap E3 を用いて scroll を clear している様だ。 29138 https://www.man7.org/linux/man-pages/man5/user_caps.5.html によるとこれは ncurses の拡張? 29139 tput clear で出力されるのはこれであると書かれている。 29140 また、infocmp -x | grep E3 としても何も出てこない。 29141 →一方で通常の clear は clear_screen/clear/cl だそうだ。うーん。変だ。 29142 →https://invisible-island.net/xterm/terminfo.html によると E3=\E[3J らしい。 29143 つまり、\E[2J が clear_screen で、\E[3J が clear_display という事だ。 29144 取り敢えず現状は \e[3J を直接その場で出力する事にした。 29145 29146 横スクロールに関しては複雑ですぐには実装できそうにないので別項目で議論する。 29147 29148 * syntax: bash-5.1 では time -- が許される (from Bash-4.1 CHANGES) [#D1367] 29149 以前は time -p -- echo は OK だったが、 29150 time -- echo は -- がコマンド名と解釈されてしまって駄目だった。 29151 29152 2020-05-20 29153 29154 * prompt: transient prompt (suggested by Dave-Elec) [#D1366] 29155 https://github.com/akinomyoga/ble.sh/issues/57#issuecomment-631648877 29156 29157 powerline10k に transient prompt という設定があるそうだ。 29158 しかし、README には機能の存在は紹介されているが設定の仕方が書かれていない。 29159 https://github.com/romkatv/powerlevel10k#transient-prompt 29160 Reddit に使い方が投稿されている。 29161 https://www.reddit.com/r/zsh/comments/dsh1g3/new_powerlevel10k_feature_transient_prompt/ 29162 trim するらしい。使い方が良く分からない。 29163 29164 AndyChuがプロンプトを書き換えてコマンド開始時刻を表示する話について言及していた。 29165 https://github.com/oilshell/oil/issues/719 29166 https://redandblack.io/blog/2020/bash-prompt-with-updating-time/ 29167 https://news.ycombinator.com/item?id=22912226 29168 29169 zsh の "setopt transient_rprompt" に関しては二値の設定なので余り参考にならない。 29170 29171 実装に関しては簡単そうである。既に rps1_transient を実装している。 29172 単に opts == *:leave:* を見てプロンプトを切り替えれば良い様に見える。 29173 trim するのは実は非効率的である気がする。 29174 (或いは .newline 等の別のレベルで trim しても良い。) 29175 どの様な機能を実装するかについて考察してから実装するのが良い。 29176 29177 bleopt ps1_transient=same-dir:trim 29178 bleopt ps1_transient= 29179 29180 * これを機にプロンプト設定の名前も整理するのが良い。 29181 29182 bleopt prompt_ps1_preexec= 29183 bleopt prompt_ps1_transient= 29184 bleopt prompt_rps1= 29185 bleopt prompt_rps1_preexec= 29186 bleopt prompt_rps1_transient= 29187 29188 bash を終了する時にも置き換えるのだとしたら、preexec は変ではないか。 29189 と思ったが、プロンプトの再描画は .newline の時に実行されるのであって、 29190 Bash を終了する時には置き換えられない。という事を考えるとやはり preexec 29191 という名前が適切な気がする。"exit" で抜ける場合にはちゃんと消える。 29192 C-d 等、widget 経由で抜ける時には消えない。取り敢えずそれで問題ない気がする。 29193 29194 transient には same-dir を指定できる様にする。 29195 と思ったが preexec との相互作用が変な気もする。 29196 "same-dir を指定すると preexec が使われない" という動作である。変である。 29197 更に、transient になにか指定しないと ps1_preexec が表示されないというのも変だ。 29198 29199 思うに ps1_preexec だけで良いのではないか。 29200 これが有限の文字列であればそれに置き換える。 29201 ps1_transient=trim が設定されていれば更に trim する。 29202 それ以外の場合には ps1_preexec も ps1 も表示しない。 29203 29204 名前については preexec よりも final の方が良い気がしてきた。 29205 29206 実装 29207 29208 * done: 取り敢えず prompt_{ps1_{final,preexec},rps1_final} を追加した。 29209 * done: 古い設定名も書き換える。 29210 * done: 古い設定名に対する警告を表示する。 29211 29212 * done: trim の対応? → 対応した。 29213 然しやはり ps1_transient を指定した時に trim でなければ 29214 プロンプトを完全に消すというのは変な気がする。 29215 然しだからと言って既定で trim というのは rps1_transient と振る舞いが違う。 29216 →やはり対称性を重視して完全にプロンプトを消す事にした。 29217 29218 x fixed: 動かしてみると keep-info の時に info が消滅している→直した。 29219 29220 * done: blerc, Manual を更新する。新しい設定の追加と名称変更についての注記。 29221 これらについてはちゃんと更新した。 29222 29223 * prompt: プロンプトに vim mode を表示できる様にする (suggested by Dave-Elec) [#D1365] 29224 https://github.com/akinomyoga/ble.sh/issues/57 29225 29226 keymap_vi_nmap_name 以外のモード名の設定。 29227 29228 [関連情報] 29229 29230 * readline には以下の変数が存在する。 29231 set show-mode-in-prompt on 29232 set vi-cmd-mode-string "(cmd)" 29233 set vi-ins-mode-string "(ins)" 29234 29235 ble.sh ではいきなり独立行にこれを表示するので、 29236 この設定が使えなくなってもそれ程迄に気にする人はいないだろう。 29237 29238 * prompt に新しい設定を追加するには。 29239 特に \p{name} 的な形式で指定できる様にしたい。 29240 p の代わりにもっとましな文字を使いたい。例えば、 29241 29242 a 正規表現の参照的には \k<name> \k'name' \k{name} 29243 \'name' 或いは \'{name} \{name} \"{name} 29244 29245 b printf %()T 的には、\(name)N 等? でも分かりにくい。 29246 29247 c zsh prompt は %D{strftime format} に対応している。 29248 zsh では以下の特殊文字について既に % が定義されている。 29249 %% %# %! %? %_ %^ %/ %~ %. %{..%} %(...) 29250 %<...< %>...> %[>...] %[<...] 29251 29252 d 良く考えたら既に Bash も \D{format} に対応している。 29253 この様に考えると \X{...} の形式にするのは確定。 29254 \! \# \$ \[ \] は既に使われている。 29255 この雰囲気だと \' \" 等は今後も使われる事が無さそうな気がする。 29256 \'{name} 等でどうだろうか。取り敢えず \'{name} で対応する事にする。 29257 29258 [変更] 29259 29260 * done: ble-edit/prompt/backslash:name は 29261 ble/prompt/backslash:name に変更する事にする。 29262 Recipe から以前の名前を使っている人がいるかもしれないので、 29263 関数が見つからない場合には古い名前を使用する。 29264 29265 * fixed: 実際に動かしてみて気付いたが \'{name} だと、 29266 PS1 を指定する時のエスケープと被ってしまって良くない。 29267 別の文字にするか或いは \{name} にする? 29268 \{name} は余り使いたくない。やはり \D{name} が存在する以上は 29269 それに従うのが自然だろうと思われる。 29270 29271 アルファベットは今後使われる可能性がある。 29272 従ってやはり記号の類が良い気がする。 29273 \?{name} は正規表現の名前に似ているが、 29274 \? が別の目的で使われないとも限らない。 29275 うーん。\:{name} にしようか。lisp 的に \,{name} でも良い? 29276 或いはやはりアルファベットを使うか。\q にするのが良い気がしてきた。 29277 29278 OK 動いている。\q{name} というのも分かりやすい気がしている。 29279 29280 * done: mode名を表示しない設定を作るのも良い気がしている。 29281 bleopt keymap_vi_mode_show= 29282 取り敢えず対応した。動作確認をして修正もした。 29283 29284 * done: 次にモードが変化した時にプロンプトを invalidate することについて考える。 29285 これはもう全体を invalidate してしまっても良い気がする。 29286 更にそれと同時に prompt のキャッシュも強制的に更新させる必要がある。 29287 →実はこれは単に ble/prompt/clear を呼び出せば良いという事だろうか。 29288 そんな気がする。取り敢えず動いているという事を確認した。 29289 29290 * done: readline の設定に対応するべきだろうか? 29291 29292 取り敢えず振る舞いについて確認する。 29293 29294 set show-mode-in-prompt on 29295 set emacs-mode-string "@" 29296 set vi-cmd-mode-string "(cmd)" 29297 set vi-ins-mode-string "(ins)" 29298 29299 bind で設定する時に "\1\2" 等とした場合に、 29300 bind -v ではどの様に出力されるのだろうか。 29301 →何と直接表示された。つまりこれは ble/prompt/print で追加するべき。 29302 29303 * モードが変化した時に ble/prompt/notify-readline-mode-change 29304 を呼び出して強制的に prompt を再計算させる事にする。 29305 29306 vi 内部でのモードの変更は update-mode で実行すれば良い。 29307 emacs, vi の切り替えに関しては現状の枠組みでは必ず 29308 reset-default-keymap 経由で実行される。そしてその際には __attach__ が呼び出される。 29309 従って __attach__ でモードをチェックして set show-mode-in-prompt になっていたら 29310 prompt を強制更新するという具合にするので良い。 29311 29312 動作確認を実行する。以下の設定で期待通りに動く事を確認した。OK 29313 29314 bind 'set show-mode-in-prompt on' 29315 ble-bind -m vi_imap -f C-t emacs-editing-mode 29316 ble-bind -m emacs -f C-t vi-editing-mode 29317 29318 * done: Manual を更新する。新しい bleopt を追記した。 29319 * done: vi guide も更新する 29320 * done: blerc も更新する。新しい bleopt を追記 29321 29322 * done: Manual: プロンプト文字列に関する説明 29323 プロンプトの改造の仕方の説明 29324 これらは rps1 付近に追記すれば良いだろう。 29325 或いはプロンプトに関する独立した章を設ける。 29326 readline variable の解釈についてもちゃんと書きたい。 29327 29328 [返答の準備] 29329 29330 取り敢えずサンプルを提示する? 29331 或いは、contrib にサンプルを追加してしまっても良い気がする。 29332 →contrib に追加した。 29333 29334 2020-05-18 29335 29336 * 複数行履歴中の \ が q に化けてしまう (reported by cmplstofB) [#D1364] 29337 https://github.com/akinomyoga/ble.sh/issues/56 29338 29339 これは 4bcbd71 support timestamp で導入されたバグである。簡単な修正だった。 29340 29341 一方の複数行コマンドの復元ができていない問題に関しては謎。 29342 一回再現できたが、もう二度と再現しない。何故だろう。 29343 再現できた時には eval -- $'a q\nb q\nc' の形になっていた。 29344 履歴ファイルには eval -- $'a \\\nb \\\nc' で登録されているので、 29345 つまり、mlfix が走った後で history/load が走って、その時になにかに失敗している。 29346 然し、何をどう失敗するとこうなるのか謎。取り敢えず様子見。 29347 29348 2020-05-16 29349 29350 * 元のリポジトリが消滅している時にも update を可能にする [#D1363] 29351 https://github.com/rux616/init/blob/7e1a5d2e0dbaa792f4a0a4830ea2f8b92b433b44/install#L422 29352 →その様に修正した。 29353 29354 * util: escape 単語先頭の ~ や # は escape しなくて良いのか [#D1362] 29355 ble/string#escape-for-bash-specialchars 29356 29357 調べてみると core-complete.sh が使っている。 29358 29359 * そして試しに touch '#hello' '~hello' で調べてみると正しく escape されない。 29360 →これについては修正した。 29361 x 単語先頭以外でも \# \~ に修正されてしまう。 29362 単語先頭かどうかを判定する事は可能だろうか。 29363 29364 * fixed: 更に \~hello に至ってはチルダ展開が起こって補完候補にも現れない。 29365 '~hello' の場合にはちゃんと候補が列挙される。 29366 →どうもこれは bash-completion が悪い様である。 29367 然し、'~' の場合にはちゃんと生成できている。何が悪いのだろうか。 29368 具体的にどの様な情報が渡されているのか確かめる必要がある。 29369 29370 調べるとシェル関数の引数である cur prev に渡されている情報が悪い。 29371 cur="'~" の時には bash-completion は何も生成できない。 29372 cur="\\~" の場合には bash-completion は何故かユーザー名を列挙する。 29373 然し、よく考えてみるとそもそも COMP_WORDS の方も対応する様に 29374 エスケープしなければならないのではないか。 29375 その上で COMP_WORDS に一致する様に cur prev を用意するべきなのではないか。 29376 もっと振る舞いを調べると bash-completion は引数と COMP_WORDS の両方の情報を使っている。 29377 29378 * 先ず COMP_WORDS の値を修正する必要がある。修正した。 29379 * 更に、cur prev として渡している値も COMP_WORDS に変更したら動く様になった。 29380 29381 ? no: 然し、この部分は過去に何らかの議論があってこの様に修正した気がする。 29382 29383 | 改めてこの部分について調べる必要がある。調べると c8433971 43bb0749 が怪しい。 29384 | 29385 | 2018-08-05 09:15:39 c8433971 29386 | 2019-03-23 21:41:19 43bb0749 29387 | 29388 | と思ったが、 c8433971 は quote を変更しただけである。更に遡る。 29389 | 29390 | 2015-11-24 04:05:14 1929132b (complete.sh) ここで導入されている。 29391 | 29392 | 更にその前のコードはどうなっていたかと言うと、以下の様な具合になっていて、 29393 | そもそも COMP_WORDS と comp_words の区別がなかったし、更に関数に引数を渡していなかった。 29394 | というより上の commit の僅か 4 時間前の事である。要するに実装してすぐに 29395 | cur=${comp_words[comp_cword]} だったという事である。 29396 | 29397 | | 2015-11-23 23:58:01 cdd38598 (complete.sh) 29398 | | function ble-complete/source/argument/.compgen-helper-vars { 29399 | | COMP_WORDS=("${comp_words[@]}") 29400 | | COMP_LINE="$comp_line" 29401 | | COMP_POINT="$comp_point" 29402 | | COMP_CWORD="$comp_cword" 29403 | | COMP_TYPE=9 29404 | | COMP_KEY="${KEYS[${#KEYS[@]}-1]:-9}" # KEYS defined in .ble-decode-key/invoke-command 29405 | | } 29406 | | function ble-complete/source/argument/.compgen-helper-func { 29407 | | local -a COMP_WORDS 29408 | | local COMP_LINE COMP_POINT COMP_CWORD COMP_TYPE COMP_KEY 29409 | | ble-complete/source/argument/.compgen-helper-vars 29410 | | [[ $comp_func ]] && eval "$comp_func" 29411 | | } 29412 29413 結論: COMP_WORDS ではなくて comp_words を使っているのに特に意味はない。 29414 未だ COMP_WORDS と comp_words に区別のなかった一番最初の実装の時からこうだった。 29415 従って気兼ねなく変更する事ができる。変更した。 29416 29417 * ~ は ble.sh が勝手に展開してから bash_completion に渡しているが、 29418 ~ の儘にして渡した方が良いのではないだろうか。 29419 特に ~ という単独の単語の時にのみ特別扱いとするのである。 29420 29421 →対応した。候補はちゃんと生成される様になったが、 29422 quote されてしまう。\~murase という具合に。これは期待する動作ではない。 29423 実際に bash の場合には勝手に quote されるという事はなかった。 29424 complete -p echo しても特に -o noquote が指定されている訳でもないし、 29425 また、compopt の呼び出しを確認しても compopt -o filenames が呼び出されるだけで 29426 compopt -o noquote が呼び出されるわけでもない。 29427 29428 元の Bash の振る舞いについても確認しておく必要がある。 29429 →どうやら元々の Bash は ~ に関しては quote しない様だ。 29430 そう思って quote しない様にしてみたら 29431 今度は \~hello の様なファイル名で期待通りに動かない。 29432 候補としては ~hello が生成されている。 29433 29434 不思議な事が起きている。bash_completion 経由だとメニューの表示には 29435 \ 無しで表示されているのにも拘らず実際に補完される時には \ 付きで挿入される。 29436 自分で作った補完関数で試してみるとどちらも COMPREPLY に格納した通りにしかならない。 29437 或いは文脈に応じて bash_completion は quote の仕方を変えるという事なのだろうか。 29438 →分かった。bash は compopt -o filenames が指定されている時、 29439 ローカルファイル名に "~..." が一致する時に限り tilde の quote を実施する。 29440 29441 →Bash の振る舞いの通りに実装してみたがこれで良いのか分からない。 29442 本来はいつでも先頭の ~ は quote するべきの気もするがまあこれで大丈夫だろう。 29443 29444 2020-05-14 29445 29446 * loadable builtins を積極的に使うという可能性について [#D1361] 29447 29448 | builtin mkdir, rmdir, rm, mktemp -d 等を積極的に使っても良いのではないか。 29449 | 然し問題点はユーザが /usr/bin/mkdir を使いたい時に 29450 | 勝手に builtin の方が呼び出されるという事。 29451 | という事を考えると enable を使って一時的に有効にして使う? 29452 | 29453 | 然し、元から有効だったかどうかをどの様に判定するのか。 29454 | 調べてみたが type コマンドを使うぐらいしか方法がない気がする。 29455 | enable の終了ステータスを使って判定する方法はあるだろうか。 29456 | やはりない気がする。やはり勝手に enable/disable するのは良くない気がする。 29457 | 29458 | といってサブシェルで実行するというのだと fork は結局する。 29459 | でも fork/exec よりは効率が良い様な気もする。 29460 29461 * というより、sleep の場合でも問題が起きるのではないだろうか。 29462 調べてみると coreutils sleep は 1s や 1m 等の指定を受け付けるが、 29463 builtin sleep は整数と小数にしか対応していない。 29464 これの対策については真面目に考える必要がある。 29465 29466 a 例えば sleep は関数で上書きしてしまって内部では command sleep を呼び出す。 29467 然し、msleep からは builtin sleep を使う様にする。 29468 然し、これはこれでユーザが sleep 関数を定義したい場合や、 29469 ユーザが enable -f ./sleep を実行したい場合に不都合が起きる。 29470 29471 うーん。builtin と明示的に指定した時にのみ builtin として使える、 29472 という感じの仕組みがあると良いのだが、難しい。 29473 29474 b 或いは、いっその事 ble.sh 専用の builtin を作ってしまうというのも手なのである。 29475 x loadable builtin に手を出したらもう ble.sh の存在意義が失われる気がする。 29476 それだったら初めから loadable builtins だけで全部実装すれば良かったのである。 29477 x 一応コンパイラの存在しない環境の為に loadable builtin を使わない 29478 場合も用意する事ができるが、頻度が低くなるとテストが十分にできな 29479 くなり問題を起こす可能性がある。然し、その為の単体テストではない 29480 のだろうか。という事を考えるとそういう意味では問題はない。 29481 29482 取り敢えずこれはそれ程深刻ではない気がするので放置で良いのではないか? 29483 或いは 1m や 1s 等の表記にシェル関数を使って対応してしまうという可能性。 29484 どうせならその方が良いという気がする。 29485 29486 取り敢えず coreutils 的な sleep をシェル関数で実装する事にした。 29487 この様にすればユーザが普通の sleep の機能を使いたい場合でも大丈夫だし、 29488 或いは enable -f sleep で sleep を有効にして組み込み sleep を使いたい場合でも 29489 どちらでも大丈夫。 29490 29491 他に現実的な解もない気がするのでこれで良しとする。 29492 29493 [結論] 29494 29495 色々考えた結果 sleep 以外に関しては builtin を読み込むのは却って管 29496 理が複雑になるという事。また、それ程迄に必要という訳でもないという 29497 事。それよりは stty を builtin にするべきという事。 29498 29499 loadable builtins には既定で mkfifo, mkdir 等、システムのユーティ 29500 リティと同名の物が提供されている。loadable builtins を読み込むとシ 29501 ステムのユーティリティが上書きされてしまう。loadable builtin の方 29502 が一般的にシステムが提供するコマンドよりも機能が少ないので問題にな 29503 る。 29504 29505 mkdir() { /usr/bin/mkdir "$@"; } とすれば単に mkdir と呼び出した時 29506 には必ずシステムのユーティリティを呼び出して、builtin mkdir とした 29507 時にだけ読み込んだ物を使う様にできる。然し、この様にすると逆にユー 29508 ザが意図的に loadable builtin の mkdir を読み込んだ時に、builtin 29509 を読み込んでいるのにも拘らず builtin が使われないという状況になっ 29510 てしまう。 29511 29512 sleep は他に良い代替手段がないという事と、coreutils sleep の振る舞 29513 いをシェル関数でも実現できるという事から、load してシェル関数によ 29514 る実装で上書きする事にした。一方で mkfifo, mktemp, mkdir は 29515 SELinux の context 等の対応が難しい。rm は更に様々な機能がある。 29516 29517 [まとめ] 29518 29519 ユーザが file コマンドを使いたい場合と builtin を使いたい場合があ 29520 る。それに干渉したくないので基本的に同名の loadable builtins は使 29521 わない。代わりに ble 的な builtin を作成して其処から様々な関数を呼 29522 び出すという可能性はある。 29523 29524 * syntax: 何故か {aa}> はちゃんと認識されるが {a}>&1 は認識されない [#D1360] 29525 文字数が1文字だと駄目になっているようだ。 29526 これは簡単な修正だった。 29527 29528 * main: ble-update で新しい commit が fetch できなかったとしても [#D1359] 29529 現在の ble.sh repo の状態が、現在ロードされている version と違えば 29530 その場で reload するべきなのではないか。 29531 29532 序でに一時ファイルを全て $_ble_base_run/$$/ という 29533 ディレクトリに移動することを考えたが、これだとディレクトリを作る為に 29534 fork が必要になるので初期化時間が伸びてしまう。 29535 これは取り敢えずは現状の儘にしておくという事で良い。 29536 29537 2020-05-13 29538 29539 * complete: 変数代入の中で変数名の補完が効かない [#D1358] 29540 例えば var=1234 が存在している時に x=$va に対して補完が効かない。 29541 29542 実際に試してみると v=$B に対して "rhs 2" という候補しか生成されていない。 29543 うーん。"variable 3" という物が生成されても良いのではないか。 29544 以前、変数代入を代入の右辺からの候補を生成する様にした。 29545 この時に元々ある候補が生成されなくなってしまったという事。 29546 29547 調べると .check-prefix から直接 .check-prefix/ctx:rhs に移動している。 29548 そして其処で rhs の開始点まで遡るという事をしている。 29549 確かに $B となっている時の懐石再開点は $ の直前であり、其処での文脈は VRHS である。 29550 逆に通常の文脈ではどの様に処理していたのだったか。 29551 例えば ARGI の時には inside-argument を呼び出している。 29552 更にその中で ble/syntax/completion-context/.check/parameter-expansion を呼び出しているのだった。 29553 29554 他にも似たような物はないか確認したが > file$BASH や 29555 time $BASH でもパラメータ展開の補完ができなかった。 29556 29557 29558 * prompt: PS0 という物が Bash 4.4+ には存在する様である [#D1357] 29559 何故か http://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html には反映されていない。 29560 もしかするとこのマニュアルは更新が Bash 4.3 で止まっているのかもしれない。 29561 https://github.com/rcaloras/bash-preexec/issues/28 29562 http://superuser.com/a/1052132 29563 https://stackoverflow.com/questions/43201274 29564 これは対応した。簡単だった。 29565 29566 2020-05-12 29567 29568 * history: "bleopt history_share=1" でエラーメッセージが発生する (reported by rux616) [#D1356] 29569 https://github.com/akinomyoga/ble.sh/issues/50#issuecomment-627061087 29570 29571 これは新しく埋め込んだバグだろう。エラーメッセージを見ると、 29572 ble/history:bash/resolve-multiline/readfile であろう。 29573 要するに新しい履歴項目がない場合にそもそも TMPBASE.part が作られないという事では? 29574 調べると reason=resolve の時には作られるけれども、reason=read の時には作られない。 29575 29576 然し、ble/history:bash/resolve-multiline/readfile の呼び出し元を確認した時に不思議なのは、 29577 ちゃんと呼び出し元ではファイルが空でないという事を確認しているという事。 29578 #%s の行しか存在していない時にはこういう事が起こるのかもしれないが、 29579 それも何だか変である。実際に何が起こっているのか再現させて調べるしかない。 29580 29581 →再現させる事ができた。然し、ファイルの中身はちゃんと存在している。awk が悪い? 29582 これは単純なミスであった。修正した。 29583 29584 * LC_COLLATE=C で検索すると未だ LC_COLLATE=C func の形式の物が残っている [#D1355] 29585 これは問題が起こるので避ける様にした筈。調べると 29586 LC_XXX=C external_cmd の場合には問題は起こらない様子である。 29587 従って、組み込み機能で処理を行う場合には全て local に入れる必要がある。 29588 29589 その他、わざわざ bash-4.1 で処理を切り替えている物を 29590 新旧 bash のどちらでも動く方法を使う様に統一した。 29591 29592 2020-05-11 29593 29594 * main: bashrc で source ble.sh を2回実行すると固まる (reported by GavinRay97) [#D1354] 29595 https://github.com/akinomyoga/ble.sh/issues/51 29596 29597 bashrc に設定したら ble-reload というメッセージが表示されて操作できなくなる。 29598 ble 0.3.2 で source ble.sh を2回実行すると発生する。 29599 ble-0.4 でも ble-attach を手で実行すると発生する。 29600 29601 また ble-0.4 で同じ事を --attach=prompt で実行すると 29602 リダイレクトエラーが沢山発生する。文字列を入力する度に発生する。 29603 これはつまり stdout.on, off で問題が発生しているという事だろう。 29604 (too many open files とは一体どういう事だろうか。) 29605 29606 bashrc の中で2回以上 source ble.sh するとエラーが発生する。 29607 29608 $ bash --rcfile bashrc.1.bash 29609 bash: リダイレクトエラー: ファイル記述子を複製できません: Too many open files 29610 bash: /dev/null: Too many open files 29611 bash: リダイレクトエラー: ファイル記述子を複製できません: Too many open files 29612 bash: /dev/null: Too many open files 29613 bash: リダイレクトエラー: ファイル記述子を複製できません: Too many open files 29614 bash: /dev/null: Too many open files 29615 bash: リダイレクトエラー: ファイル記述子を複製できません: Too many open files 29616 bash: /dev/null: Too many open files 29617 29618 これはどうも単に stdout.off の状態でロードすると駄目という問題の気がする。 29619 29620 ? と思ったが --attach=prompt でも問題が起こるという事はそんなに簡単ではない。 29621 →ソースコードを確認した所、別に attach しなくても ble.sh を読み込んだ時点で 29622 ble/fd#alloc _ble_edit_io_stdout '>&1' 29623 ble/fd#alloc _ble_edit_io_stderr '>&2' 29624 を使ってリダイレクト先を設定している。 29625 というよりこれらは実は明示的に /dev/tty に繋ぐべきなのでは? 29626 29627 * 取り敢えず修正としては /dev/tty に繋ぐという事。 29628 * unload の際に stdout.on を実行するという事。 29629 実際に確認してみた所、ちゃんと stdout.on が呼び出される様に実装してある気がする。 29630 29631 またもう一つ変なのは --attach=prompt を使っているという事は、 29632 二回目の ble.sh の時点では未だ stdout.off の状態になっていない筈という事。 29633 それでも問題が発生するというのは何か別の事が起こっている? 29634 →実際に確認してみた所 1 も 2 も /dev/null に繋がっている。 29635 stdout.off の状態になっているという事を意味する? 29636 29637 何処で stdout.off が呼び出されているのか調べようとしたが、 29638 実は stdout.off は呼び出されていない? 29639 何らかの別の場所で 1,2 が /dev/null に繋がれている? 29640 そもそも本当に 1,2 は /dev/null に繋がっているのだろうか。 29641 29642 また、ls -la /proc/$$/fd を見た感じだと _ble_edit_io_stdout 等はちゃんと 29643 tty に繋がっている。変な物に繋がっているという事はない様である。 29644 29645 x fixed: PROMPT_COMMAND 無限ループ 29646 29647 % ? too many open files というエラーメッセージは恐らく間違ったメッセージの気がする。 29648 % →これについては確認してみた所、別に沢山の file descriptors を開いている訳ではない。 29649 % という事はつまりこれは単にエラーメッセージが間違っているだけである。 29650 29651 うーん。stdout.off で実際に確かめてみた所、 29652 実は本当にファイルディスクリプタを使い果たしている様だった。 29653 というか PROMPT_COMMAND で無限ループになっているという事の様だ。 29654 29655 これは一体どの様にして回避したら良いのか。 29656 PROMPT_COMMAND が ble/base/attach-from-PROMPT_COMMAND なら 29657 _ble_base_attach_PROMPT_COMMAND を上書きしないというのが愚直な対策だが、 29658 ユーザが PROMPT_COMMAND="$PROMPT_COMMAND;..." 等と変更していた場合を考えると、 29659 コンポ天気な対策になっていない。 29660 29661 % fixed: 先ず ble/base/attach-from-PROMPT_COMMAND の最初で 29662 % _ble_base_attach_from_prompt= を設定して何度も実行されない様にする? 29663 % と思ったが違う気がする。_ble_base_attach_from_prompt= は 29664 % 何度も attach を実行してしまわない為の物であって、 29665 % PROMPT_COMMAND の呼び出しを抑制する為の物ではない。 29666 % 29667 % 実際に attach しているかどうかに関わらず 29668 % PROMPT_COMMAND を入れ子で実行してしまわない為の物である。 29669 % 29670 % →lambda を使って実装し直したので結局この修正は不要になった。 29671 29672 * 問題は何処にあるのか。 29673 29674 更に元々ユーザが設定していたコマンドは何処に退避するのか? 29675 現状の設定だと _ble_base_attach_PROMPT_COMMAND= に待避されていた 29676 ユーザのコマンドは消滅してしまう。うーん。 29677 実は unload する時に復元するべきなのではないだろうか。 29678 と思ったが更にユーザが PROMPT_COMMAND を変更していた場合、 29679 勝手に復元する訳には行かなくなる。 29680 29681 二回実行した時に既に退避していたコマンドを実行するのか、 29682 或いは完全に削除してしまうのかどうするべきか。 29683 29684 | そもそも ble.sh を reload する事を許しているのはユーザが source ~/.bashrc 29685 | した時に改めて初期化する事を可能にする為。そういう事を考えると、 29686 | PROMPT_COMMAND が累積して行くというのは変といえば変な話である。 29687 | 本来は bashrc の先頭でクリアしてしまうべきなのではないかという気がする。 29688 | 29689 | 然し、現実にはわざわざその様にする事はない。 29690 | というか重複して実行されても良いのではないだろうか。 29691 | その様になってしまうのはユーザが何度も実行するから。 29692 | と思ったがユーザが登録する時には PROMPT_COMMAND に既に 29693 | 自分の設定した文字列が含まれているかどうかを確認してからという事もある。 29694 | そういう事を考えると、やはり何度も実行してしまうのは変な気がする。 29695 | 29696 | というか同じ問題が普通に reload した時にも起こる。 29697 | _ble_base_attach_PROMPT_COMMAND= に指定していた設定が消滅するという事。 29698 | これに対してどう処理するのが正しいのか。。 29699 | 29700 | 本来は ble.sh の設定した PROMPT_COMMAND は一時的な物なので跡形もなく消したい。 29701 | 然し、実際にはユーザの別の設定に取り込まれたりするので後で消し去れない事もある。 29702 | その時に如何に透明になる事ができるかというのが問題である。 29703 | 29704 | _ble_base_attach_PROMPT_COMMAND を配列にして上書きする? 29705 | 或いは _ble_base_attach_PROMPT_COMMAND に既に値が設定されていた場合には、 29706 | それを更に別の変数に退避して、ble/base/attach-from-PROMPT_COMMAND が 29707 | 二重に呼び出された時にそれを実行するという事にする? 29708 | 29709 | うーん。ble/base/attach-from-PROMPT_COMMAND という名前ではなくて、 29710 | 適当にラムダ関数として重複の無いようにその場で関数を生成する? 29711 | そうすればちゃんとそれに紐付いた関数として呼び出す事ができる。 29712 | うーん。それが良い気がしてきた。 29713 29714 * lambda で実装するのが良い気がしてきた。 29715 29716 改めて方針について整理する。 29717 実際に登録するのはラムダ関数にする。 29718 そのラムダ関数から ble/base/attach-from-PROMPT_COMMAND を呼び出す。 29719 古い PROMPT_COMMAND は変数に保存するのではなくて、ラムダの本体に埋め込む。 29720 また、ラムダを削除する為に、ble/base/attach-from-PROMPT_COMMAND にラムダの関数名を渡す様にする。 29721 29722 ble/base/attach-from-PROMPT_COMMAND 'old-prompt-command' "$FUNCNAME" 29723 29724 ble/function#lambda 変数名 'function-body' というインターフェイスにする。 29725 29726 * ok: lambda を使って実装した時に再帰呼び出しが発生する可能性はあるだろうか。 29727 考えてみる。 29728 29729 一回目の source で PROMPT_COMMAND=lambda/1 になる。 29730 元の PROMPT_COMMAND は lambda/1 から呼び出される。 29731 二回目の source で PROMPT_COMMAND=lambda/2 になって 29732 此処から lambda/1 が呼び出される。 29733 29734 実際に PROMPT_COMMAND が評価されるとどうなるか。 29735 29736 | - lambda/2 29737 | - ble/base/attach-from-PROMPT_COMMAND lambda/1 lambda/2 29738 | 1 PROMPT_COMMAND=lambda/1 29739 | 2 lambda/1 29740 | | - ble/base/attach-from-PROMPT_COMMAND 元々の値 lambda/1 29741 | | 1 PROMPT_COMMAND=元々の値 29742 | | 2 元々の値 29743 | | 3 PRECMD-=lambda/1 29744 | | 4 _ble_base_attach_from_prompt= 29745 | | 5 ble-attach 29746 | 3 PRECMD-=lambda/2 29747 | 4 [[ $_ble_base_attach_from_prompt ]] || return 29748 29749 の様になって無限ループは防げる。 29750 29751 PRECMD が重複して登録されてしまっているのは気になるが、 29752 まあ大丈夫だろうという気がする。 29753 PROMPT_COMMAND が複数回実行される程度の気がする。うーん。本当だろうか。 29754 PRECMD 経由だと何が起こるかというと…。 29755 登録した順に呼び出されるという事を考えると変な事になる。 29756 29757 | - lambda/1 29758 | - ble/base/attach-from-PROMPT_COMMAND 元々の値 lambda/1 29759 | 1 local PROMPT_COMMAND=元々の値 (PROMPT_COMMAND (lambda/2) != 元々の値なので local) 29760 | 2 元々の値 29761 | 3 PRECMD-=lambda/1 29762 | 4 _ble_base_attach_from_prompt= 29763 | 5 ble-attach 29764 | - lambda/2 29765 | - ble/base/attach-from-PROMPT_COMMAND lambda/1 lambda/2 29766 | 1 PROMPT_COMMAND=lambda/1 29767 | 2 lambda/1 29768 | | ble/base/attach-from-PROMPT_COMMAND 元々の値 lambda/1 29769 | | 1 PROMPT_COMMAND=元々の値 29770 | | 2 元々の値 29771 | | 3 PRECMD-=lambda/1 29772 | 3 PRECMD-=lambda/2 29773 | 4 [[ $_ble_base_attach_from_prompt ]] || return 29774 29775 この様に考えてみると単に "元々の値" が二回実行されるだけである。 29776 或る意味これは自然と言えば自然な気もする。 29777 ユーザが二回初期化を実行したのだから。 29778 そして各 source ble.sh 毎に1回ずつプロンプトの計算が走る。 29779 また、最終的には PROMPT_COMMAND も PRECMD も解除される。 29780 29781 次の場合はユーザが後になって PROMPT_COMMAND を修正した時に何が起こるかという事。 29782 これについては PROMPT_COMMAND の復元が行われないというだけで PRECMD は削除される。 29783 PROMPT_COMMAND の復元に関しては実は行われなくてもそう大きな問題にはならない気がする。 29784 attach も二度は起こらないし単に無駄に関数呼び出しが実行されるだけである。 29785 29786 * ok: ble.sh が PROMPT_COMMAND を設置した後にユーザが更に何か追加する可能性がある。 29787 →これに関しても lambda を使って実装すれば大した問題にはならない。 29788 29789 x fixed: これで --prompt=attach に対しては動くかと思いきやプロンプトが表示されない。 29790 これは /dev/null にリダイレクトしているのが原因である。 29791 と思ったがよく見るとちゃんと PROMPT_COMMAND の標準エラーは外に伝わる様になっている。 29792 という事はこれが原因ではないという事? ble-attach がそう何度も実行されるとは考えにくい。 29793 29794 然し、実際のこのリダイレクトを修正したら問題が発生しなくなった。 29795 何が起こっているのだろうか。番号を指定してリダイレクトしている事によって 29796 何らかのファイルディスクリプタが上書きされてしまっている? 29797 29798 或いは、2>/dev/null によって ble-attach の内部で実行した恒久的な exec redirection 29799 が復元されてしまっているのが原因だろうか。何か違いが生まれるとすればこれしかない。 29800 然し、何故これによってその様な症状になるのかというのは謎である。 29801 29802 →何だか分からないがやはり attach は一番最後に行うべき気もするし、 29803 そういう意味でも一番外側で実行するべきである。その様に修正した。 29804 29805 結局、--attach=prompt の時のファイルディスクリプタの問題と、 29806 ble-attach を強制的に実行した時に何も表示されなくなる問題は独立の問題だった。 29807 それがはっきりした今改めて状況について整理する。 29808 29809 * ble-attach を実行したあとで source ble.sh を実行した時に、 29810 本来であれば stdout.off が unload で呼び出される筈で、 29811 結果として stdout.off, on が破壊されるという事はない筈である。 29812 29813 という事は起こっている問題は stdout.on, off の問題ではない? 29814 或いは stdout.off に失敗している所為でこれが起こっている? 29815 まずはこれがどちらなのかを確認する必要がある。 29816 29817 →確認した。二回目の初期化に於いて stdout.off 状態になっている。 29818 ここでの謎は何故 unload で stdout.on が実行されなかったのかという事。 29819 29820 実際に調べてみるとちゃんと stdout.on は呼び出されていて 29821 状態は復元されている。と思ったら分かった。 29822 ble/base/unload-for-reload &>/dev/null として呼び出していたので、 29823 ble/base/unload-for-reload の実行が終わった後に 29824 1,2 が呼び出し前の状態に復元されてしまうのだった。 29825 29826 そもそもこの &>/dev/null は何の為の物だったろうか。 29827 これを削除してしまっても特に問題はないのではないだろうか。 29828 或いは set -x 等の状態復元に関係があるだろうか。 29829 実は set -x の状態復元は此処では行っていない様に見える。 29830 →実際に set -x を実行してみたが特に何か出力されるという事もない様だ。 29831 29832 念の為この部分の変更を履歴を調べておく。 29833 29834 | 59995c62 (Koichi Murase 2015-08-11 19:42:02 +0900 226) if [[ $_ble_base ]]; then 29835 | fc45be68 (Koichi Murase 2019-01-11 20:38:38 +0900 227) if ! ble/base/unload-for-reload &>/dev/null; then 29836 | fc45be68 (Koichi Murase 2019-01-11 20:38:38 +0900 228) echo "ble.sh: ble.sh seems to be already loaded." >&2 29837 | fc45be68 (Koichi Murase 2019-01-11 20:38:38 +0900 229) return 1 29838 | fc45be68 (Koichi Murase 2019-01-11 20:38:38 +0900 230) fi 29839 | 59995c62 (Koichi Murase 2015-08-11 19:42:02 +0900 231) fi 29840 | 29841 | 59995c62 (Koichi Murase 2015-08-11 19:42:02 +0900 226) if [[ $_ble_base ]]; then 29842 | 59995c62 (Koichi Murase 2015-08-11 19:42:02 +0900 227) echo "ble.sh: ble.sh seems to be already loaded." >&2 29843 | 59995c62 (Koichi Murase 2015-08-11 19:42:02 +0900 228) return 1 29844 | 59995c62 (Koichi Murase 2015-08-11 19:42:02 +0900 229) fi 29845 | 29846 | commit fc45be6841be364d152cb2228e662ca842bf4fc3 29847 | Author: Koichi Murase <myoga.murase@gmail.com> 29848 | Date: Fri Jan 11 20:38:38 2019 +0900 29849 | 29850 | main: support "ble-update" 29851 29852 対応する項目は #D0874 の様である。 29853 ちゃんとは読んでいないが特に >/dev/null の処置についての言及はない様である。 29854 取り敢えず何も起こっていない様なのでそのままで良い事にする。bash-3.0 でも大丈夫。 29855 29856 * [別要因] menu: bleopt complete_menu_style=dense の座標計算が間違っている? [#D1353] 29857 29858 | dense-nowrap では問題が起きていない事を見ると wrap で問題が発生しているという事か。 29859 | 29860 | 初め trace-text に渡している nonewline オプションが悪いのではないかと思ったが関係ない? 29861 | nonewline は confine 等とは関係なくて、単に改行文字を出力しないという事らしい。 29862 | 勝手に wrap するのは許す実装になっている気がする。 29863 | 29864 | そもそも何故座標計算がずれてしまうのか。どういう座標になっているのか? 29865 | 29866 | dense-nowrap で問題が発生しないということは 29867 | やはり右端で折り返す候補が来た時の処理が問題になっている。 29868 | 29869 | 幅は174 である。x0=169 で始まって x=19 で終わっている。 29870 | 出力している文字列は generate-release-note.sh である。 29871 | gener 折返し ate-release-note.sh という具合になる筈である。 29872 | 何も間違う所はない気がする。 29873 | 29874 | うーん。更に実際に描画している物を見ると複数行ある筈の所が同じ行に出力されている。 29875 | 最終的に行がカーソル位置が上に移動してしまっている。 29876 | 29877 | 何だかわからないので実際に表示を行っている部分を確認する。 29878 | construct-page が実際に出力するシーケンスを esc に格納している。 29879 | これを出力して確認してみるのが良いという気がする。 29880 | 29881 | かなり謎の振る舞いをしている。というか cat して表示した内容と、 29882 | Emacs で開いてみてみた内容が対応していないこれはどういう事か。 29883 | 暫く観察してこれは screen が悪いのではないかという事に思い至る…。 29884 | echo {1..100} を実行してみると改行せずに途中までしか表示されない。 29885 | 試しに新しい画面を C-a C-c で開いてみると直る。 29886 | DECAWM が変な状態になっているという事? 29887 | echo $'\e[?7h' としたら直る? 7l を何処かで間違って実行してしまったという事だろうか。 29888 | ble.sh の中には少なくとも 7l という文字列はない。 29889 | ble.sh の変数の中にも 7l が含まれている物はない。 29890 | という事はこれは恐らく何か別のプログラムが変な設定をして抜けたか、 29891 | 或いは別のプログラムがクラッシュした時に残したなにかである。 29892 | この pty では ssh はしていないと思うので途中で接続が切れて中途半端になったという事ではないと思う。 29893 | 29894 | 或いは履歴を探すとそういうコマンドが残っている様だ。 29895 | このセッションで実行した物ではない様に思われるが、 29896 | 子 bash で試してそのままになっているという事の様な気もする。 29897 | と思ったがこの bash を起動したのは 2020-04-26 23:43:05 JST だし、 29898 | この bash 自体が別の bash の子供という訳でもない。不思議である。 29899 29900 結局これは端末の状態が変になっていただけであった。DECAWM が無効になっていた。 29901 然し、何故この様な状態になってしまったのかは終に分からない。 29902 ble.sh 自体には CSI ? 7 l を実行しそうな物は含まれていないので、木にしなくて良さそう。 29903 29904 * complete: blerc で bleopt complete_menu_style を設定できない (reported by rux616) [#D1352] 29905 https://github.com/akinomyoga/ble.sh/issues/54 29906 29907 指定した設定が存在しているかどうかのチェックをその場で行っている。 29908 core-complete.sh の初期化前なのでその設定が存在している事を確認できないのが原因。 29909 core-complete-def.sh に complete_menu_style 用の autoload を追加する事にした。 29910 これは単純な修正なのでテストしなくても良いだろうという気がする。 29911 29912 * history: HISTTIMEFORMAT によるタイムスタンプが記録されない (reported by rux616) [#D1351] 29913 https://github.com/akinomyoga/ble.sh/issues/50 29914 29915 まずは bash の振る舞いについて調べる必要がある。 29916 29917 | というかそもそも HISTTIMEFORMAT がどの様に動作するか理解していない…。 29918 | 後、自分で HISTTIMEFORMAT を実装するとしてもコマンドの時刻をどの様に取得すれば良いのだろうか。 29919 | 29920 | HISTTIMEFORMAT を設定している時には history コマンドで表示する時に timestamp が表示されるそうだ。 29921 | それとは別に HISTTIMEFORMAT が表示される様だ。 29922 | 29923 | というか今気づいたが history -s で読み込ませた場合は時刻情報が欠落してしまうのではないか。 29924 | と思ったがそもそもファイルに出力された時刻情報を bash は読み取るのだろうか? 29925 | 何だか変な time format で記録した場合には復元できないし、 29926 | そもそもデフォルトでは出力していないので時刻情報は復元できない。 29927 | 29928 | ? ファイルに保存された時刻を読み取るのか? 29929 | ファイルに記録されるのは unixtime 値である。 29930 | そしてちゃんと読み取る様になっている様だ。 29931 | 29932 | ? 時刻が記録されていない場合には時刻はどうなるのか。 29933 | history -w で書き出すとどうなるのか。 29934 | 29935 | →何と HISTTIMEFORMAT が設定されているかどうかによって、 29936 | bash の複数行履歴の記録の on/off が変化する様である。 29937 | うーん。つまり? どうすれば良いのかというと? 29938 | 29939 | 例えば、ble.sh が使う場合には常に HISTTIMEFORMAT=%s を指定する? 29940 | そうすれば常に複数行履歴が有効になった状態で 29941 | 履歴に対して特別な処理をせずにファイルを読み取る事ができる。 29942 | 29943 | もう少し振る舞いは異なる様である。 29944 | 29945 | HISTTIMEFORMAT が設定されていてかつ 29946 | 読み取るファイルの一番最初の行が #%s の形式である場合に、 29947 | bash は複数行履歴モードに移行する。 29948 | この時 #%s の形式の行が現れるまでを次のコマンドとする。 29949 | 29950 | それ以外の場合にはそれぞれの行を履歴項目として取り扱う。 29951 | 29952 | どちらの振る舞いの場合でも履歴の時刻は読み取られる。 29953 | HISTTIMEFORMAT が設定されていてもされていなくても。 29954 | 直前に時刻が記録されていないコマンドに関しては、 29955 | bash を起動した時の時刻が用いられる。 29956 | 29957 | ? HISTTIMEFORMAT は空かどうかで判定されるのか、 29958 | それとも変数が存在しているかしていないかで判定されるのか? 29959 | 29960 | ファイルの書き出し、ファイルの読み取り(複数行モード)、 29961 | history による出力のそれぞれに対する影響を調べる必要がある。 29962 | 29963 | ファイルの読み取りに関しては変数が存在していれば複数行モードに為る (bash 5.0)。 29964 | ファイルの書き出しに関しても変数が存在していれば書き出される。 29965 | history による出力に関しては空文字列と変数が存在していないという状況は 29966 | 動作に違いを与えないので調べても仕方がない。 29967 | 29968 | ? HISTTIMEFORMAT が設定されていない時でもコマンドの時刻は記録されているか。 29969 | 確認したがちゃんと記録されている様に見える。 29970 | 後で HISTTIMEFORMAT を設定しても history コマンドで時刻が表示されるし、 29971 | ファイルにもちゃんと時刻が書き出される様になる。 29972 | 29973 | ? HISTTIMEFORMAT が設定されていない時でも #%s の行は読み取られるか? 29974 | →ちゃんと読み取られている。 29975 | 29976 | ? HISTTIMEFORMAT が設定されている時に ble.sh の履歴の初期化が壊れるのではないか。 29977 | つまり、全ての履歴が結合した状態で初期化されてしまうのではないだろうか。 29978 | これは動作を後で確認する必要がある。 29979 | 29980 | →履歴ファイルの先頭行 #%s が存在しているとこれが発生する。 29981 | ble.sh の初期化で読み取る際に使うファイルは ble.sh が生成する物なので、 29982 | #%s を全てに出力するか、或いは一個も出力しないかは自分で決められる。 29983 | 29984 | ? #%s の形式以外のコメント行はどう取り扱われるのか。 29985 | 29986 | "#%s hello" でも認識された。"#X%s" だと駄目で "#%sX" だと認識される。 29987 | " #%s" だと駄目。"# %s" でも駄目。"#1.5..." としたら 1 と読み取られた。 29988 | という事は、bash は行が "#数字" で始まっているかどうかを見ている。 29989 | もし当てはまれば整数を読み取る。読み取れない部分が残っていても無視する。 29990 | "#-1" としても時刻行とは認識されなかった。 29991 | 29992 | "#001" とすると 1 になった。 "#010" にすると 10 になった。8進数表記にはならない。 29993 | 29994 | "#0x10" としてみたら "0x10: 無効なタイムスタンプです" になった。 29995 | どうやら文字列として記録している? そして history コマンドで出力しようとすると、 29996 | 標準出力にこれが出力される。つまり、history の出力に混入する。 29997 | HISTTIMEFORMAT= の時にはエラーメッセージは出力されない。 29998 | HISTTIMEFORMAT=A の時にはエラーメッセージが出力される。 29999 | 恐らく HISTTIMEFORMAT が非空の文字列の時にのみ文字列を整数に変換して 30000 | strftime を呼び出す等しているのだろう。 30001 | 30002 | 更に、"#0x10hello" とするとエラーメッセージも "0x10hello" に変わる。 30003 | つまり、16進数表記の場合には文字列全体を時刻として読み取るという事? 30004 | 30005 | どうやら試してみると先頭が 0 の時だけ振る舞いが異なる様である。 30006 | なにか特別な解釈なのかもしれないと考えて 00:11:11 や 00-09-20 等として見たが 30007 | 別に時刻や日付として読み取ってくれそうな気配はない。 30008 | 30009 | ? 時刻行の先頭の # は常に # だろうか。或いはユーザの設定で変わりうる? 30010 | 何だかそういう設定が bash に存在した気がする。と思って調べたがなかった。 30011 | 恐らく記憶にあったのは readline variable comment-begin '#' であろう。 30012 | 然しこれは履歴ファイルに使われるものではなくて insert-command rlfunc 30013 | で使われる物である。 30014 | 30015 | ? history -s で $'#123\necho hello' とすると何が起こるか? 30016 | →そのまま "#12345 改行 echo WORLD" 等の様なコマンドが登録された。 30017 | つまり「自動的に切り離して時刻として解釈する」というような機能は実装されていない。 30018 30019 Bash の HISTTIMEFORMAT についてまとめた結果は #M0017 に書いた。 30020 30021 ここで、何に対応しなければならないか。 30022 __ble_ext__ に unixtime 値を含める様に拡張するのは簡単である。 30023 然し、どういう風に振る舞うべきかというのについて考える必要がある。 30024 30025 * done: 履歴ファイルに時刻を記録するという事。 30026 それから履歴ファイルに記録された時刻を読み取るという事。 30027 30028 取り敢えず順番に対応する事にする。 30029 取り敢えず対応してみたがそもそも振る舞いは bash-3.2 でも同じなのだろうか。 30030 確認する必要がある→OK bash-3.2 でも HISTTIMEFORMAT= で出力される。 30031 bash-3.0 でも同様に振る舞う事を確認した。 30032 bash-3.0 でも HISTTIMEFORMAT='__ble_time_%s__' は有効である。 30033 30034 試しに多少動かしてみたら動かなかった。修正した。 30035 取り敢えず書き出しはできている様子である。 30036 但し、時刻の読み取りはできていないので起動時の時刻になっている。 30037 30038 * done: 履歴ファイルに書き込まれた時刻を正しく読み取るようにしたい。 30039 30040 history -r とそれから最初の履歴の初期化について。 30041 そもそも最初の履歴の初期化はどの様に行っているか。確認する。 30042 30043 ble/history:bash/load で実行しているのは 30044 Bash のコマンド履歴を ble.sh の配列に読み出す作業である。 30045 Bash のコマンド履歴自体には何も手を加えていないので此処では時刻について考えなくて良い。 30046 30047 ble/history:bash/resolve-multiline に関しては実装の方法について再考しなければならない。 30048 先ず、古い bash の version でも先頭行が #%s である時に複数行モードが有効になるのかという事。 30049 →どうもこれは bash-4.4 以降の機能の様である。従って、#%s を利用して複数行読み取りに対応したとしても、 30050 その実装は bash-4.4 以降でしか使えない。history -s による実装は依然として削除できない。 30051 30052 1. 取り敢えず現在の方針としては history -s 及び history -r による実装を修正する。 30053 ファイルに出力してそれを読み取らせる場合には、 30054 #%s という行を出力する様にすれば良いだけの気がする。 30055 history -s で複数行を読み込ませている部分に関してはどうしようもないので諦める。 30056 30057 2. その後で bash-4.4 以降で #%s を用いて複数行を読み取らせる実装を用意する。 30058 これは後で実装する。 30059 30060 取り敢えず実装した。意図通りに動くかを試す必要がある。 30061 取り敢えずは動いている様な気がする。 30062 30063 x fixed: mlfix.0.part の1行目に空白行が出力されている。 30064 元のファイルには存在しない筈だし、builtin history もこれを出力しているとは考えにくい。 30065 これは一体何だろうか→分かった。 30066 存在していなかった変数 scalar_array[scalar_count] = ... と代入していた。 30067 以前は scalar_array[scalar_count++] としていたので 0 に評価されてちゃんと 0 番目の要素に代入されていた。 30068 今回 ++ を独立した行で実行する様に変更したので本来 0 に格納されるべきデータが "" に格納されていた。 30069 scalar_count を明示的に初期化する様に変更して修正した。 30070 30071 * done: builtin history -a file で履歴をファイルに書き出している箇所では、 30072 意図せず #%s が出力されない様に HISTTIMEFORMAT を unset しておく。 30073 30074 * local && unset でちゃんと出力されなく為るという事を確認する必要がある。 30075 →確認した所駄目だった。どうも HISTTIMEFORMAT の変数の place holder 30076 が存在するだけで有効になるという事の様である。 30077 30078 どうも local で unset しても変数が存在している限りは #%s が出力される様だ。 30079 仕方がないので後の処理で削除するという事にする。 30080 30081 これに関しては builtin history -aw 等の出力を ble.sh が利用している箇所は 30082 一箇所しかなかったので其処を修正するだけで済んだ。 30083 30084 * done: 残っている __ble_ext__ があればそれについて対応が必要か確認する。 30085 残っているのは load だけである。そしてこれは 30086 _ble_history etc にデータをロードするのに使っているだけなので、 30087 日付の情報は関係ない。此処も修正するかどうか? 30088 不要といえば不要であるが、複数の箇所で異なる方法を用いているのも変な気がする。 30089 一方で使いもしない出力をさせるとそれはそれでややこしい。 30090 取り敢えずここは __ble_ext__ のまま残して置く事にする。 30091 30092 * done: mlfix で bash-4.4 以降では #%s を用いて複数行を読み取らせる様にする。 30093 ファイルの最初の行に '#%s' を指定すれば複数行として読み取ってくれる筈である。 30094 30095 | history -s の代わりに HISTTIMEFORMAT=%s history -r file として、 30096 | 複数行モードで履歴を読み取らせるという手がある気がする。 30097 | その場合には自分で $'' を decode してファイルに書き込む必要がある。 30098 | 30099 | この振る舞いは bash のどの version でも同じだろうか。 30100 | またどの shopt の集合でも同じだろうか。 30101 | これについては確認する必要がある。 30102 | →bash-4.4 以降で複数行として読み取る様になった様である。 30103 | 30104 | 何れにしても awk で #%s を出力する様に加工すれば良いという事の気がする。 30105 30106 その他の箇所で複数行コマンドを初期化するのに 30107 history -s を使っている箇所はあっただろうか。ない気がする。 30108 30109 うーん。これは実装してしまう事にする。 30110 30111 と思ったが eval -- $'...' の形式を復号しなければならない。 30112 どうやって復号するのが良いだろうか。 30113 実際にこの形に加工している部分を探す。awk で加工している。 30114 以下のコードである。 30115 30116 gsub(/['$apos'\\]/, "\\\\&", text); 30117 gsub(/\n/, "\\n", text); 30118 gsub(/\t/, "\\t", text); 30119 text = "eval -- $'$apos'" text "'$apos'" 30120 30121 基本的にはこの操作の逆手順を実行すれば良い筈。だが。 30122 ユーザがこれと同様のコマンドを実行していて、 30123 其処に \e 等の別の種類のコマンドを混入させていたらどうなるのか。 30124 すると復号しきれない文字が残ってしまう。 30125 30126 或いは全種類のエスケープシーケンスに対応する? 30127 と思ったが上記のエスケープで生成できない様な 30128 コマンド文字列の場合には復号しない様に修正すれば良いのである。 30129 そしてその検出は正規表現で十分にできる。 30130 30131 実装した。ちゃんと動いている気がする。 30132 30133 * ok: 特定の条件で history のHISTTIMESTAMPの出力は ?? になってしまった筈。 30134 この場合にどの様に振る舞うかはちゃんと考えておく必要がある。 30135 30136 bash 4.0 以降では履歴の初期化は idle で実行しているので問題はない筈。 30137 つまり、もし問題が起こるとしたら bash-3.2 である。 30138 →うーん。複数行コマンドの日時が起動時に置き換わってしまっているという事以外は大丈夫。 30139 prompt attach を採用しているからだろうか→特に問題は起こっていない。 30140 30141 元々 \?\? は何処で導入されたのか。調べると ble-0.1 の時点で __ble_ext__ がある。blame した。 30142 4e97b41a (Koichi Murase 2015-02-19 00:41:20 +0900 3327) /^ *[0-9]+\*? +(__ble_ext__|\?\?)/{ 30143 e7606868 (Koichi Murase 2015-02-12 02:55:39 +0900 2131) /^ *[0-9]+\*? +(__ble_ext__|\?\?)/{ 30144 30145 | commit e7606868bbbb04ed7087a180317bd56446460304 30146 | Author: Koichi Murase <myoga.murase@gmail.com> 30147 | Date: Thu Feb 12 02:55:39 2015 +0900 30148 | 30149 | - ble-decode.sh, ble-edit.sh: ble の detach 機能の実装 30150 | - ble-decode.sh: exit 後に stty が壊れているのを修正 30151 | - ble-color.sh: 色の付け方を修正・追加 30152 30153 うーん。大した記録は残っていない。 30154 一応 #D0129 が対応する項目の様だが単に rcfile 内部での履歴の読み取りに対応したというだけ。 30155 或いはサブシェルで実行していたりすると発生するのだろうか。 30156 そもそも bash-3.2 で ble-attach した時に mlfix は呼び出されているのだろうか。 30157 見ると複数行の履歴項目が復元されているのでちゃんと処理はされている筈。 30158 と思ったが、よく考えたら初めて必要になった時まで遅延させているのだった。 30159 30160 * fixed: bash-3.2 で history_lazyload= にして初期化時に読み込ませると、 30161 '#%s' の行もコマンドの行として読み込まれてしまっている。 30162 何が起こっているのだろうか。つまり、builtin history が '#%s' もコマンドとして出力している? 30163 30164 % これはその後の bash の初期化で修正される様だ。 30165 →修正されるというよりは、サブシェルで builtin history -n で履歴を読み込んだ結果であり、 30166 本体のシェルには影響を与えない様になっているという事の様だ。 30167 一方で直接に bashrc に history -n を書き込んで実行してみると、 30168 確かに履歴に #%s の行が混入して面倒な事になってしまっている。 30169 30170 と思ったら ble/history:bash/load/.generate-source のコメントに rcfile として 30171 実行すると HISTTIMEFORMAT を指定しても ?? になるという旨が書かれている。 30172 然し、現在ではこれは再現していない。うーん。 30173 親シェルで実行していた時にだけ発生していたのだろうか。 30174 然し、実際に history -n history を直接実行した場合でも問題は発生していなかった。謎。 30175 30176 * ok: bash-3.2 で mlfix が実行されているのは確かの様に思われるが、 30177 一体何処で実行されているのだろうか。そもそも本当に実行されているのか。 30178 実際にソースコードを観察するとどこでも呼び出していない気がする。 30179 然し、実際に複数行 escape が外されている。 30180 Bash が勝手にコマンドの内容を書き換えるのは不可能である。 30181 或いは load で書き換えられているのか、と思ったが、load は 30182 _ble_history シェル変数にロードするだけで Bash のコマンド履歴を編集したりはしない。 30183 30184 結局、ble-stackdump して分かった事は、 30185 コマンドを実行するタイミングで history -p が呼び出されて、 30186 その結果として resolve-multiline が呼び出されるという事らしい。 30187 というか実際に ble/builtin/history/option:p のコメントにその様に書かれていた。 30188 30189 @ out/ble.sh:4 (ble/history:bash/resolve-multiline/.worker) 30190 @ out/ble.sh:13084 (ble/history:bash/resolve-multiline.impl) 30191 @ out/ble.sh:660 (ble/history:bash/resolve-multiline) 30192 @ out/ble.sh:7 (ble/builtin/history/option:p) 30193 @ out/ble.sh:1 (ble/edit/hist_expanded/.core) 30194 @ out/ble.sh:1 (ble-edit/hist_expanded/.expand) 30195 @ out/ble.sh:-2169 (ble/util/assign) 30196 @ out/ble.sh:5 (ble-edit/hist_expanded.update) 30197 @ out/ble.sh:3433 (ble/widget/accept-line) 30198 @ /home/murase/.mwg/src/ble.sh/out/keymap/vi.sh:7352 (ble/widget/vi_imap/accept-single-line-or) 30199 @ out/ble.sh:5089 (ble-decode/widget/.call-keyseq) 30200 @ out/ble.sh:48 (ble-decode-key) 30201 @ out/ble.sh:51 (ble-decode-char/.send-modified-key) 30202 @ out/ble.sh:156 (ble-decode-char) 30203 @ out/ble.sh:11 (ble/encoding:UTF-8/decode) 30204 @ out/ble.sh:4927 (ble-decode/.hook) 30205 30206 という事はつまり、bashrc の中で history -p を呼び出すと変な事になる? 30207 一応履歴が空の時には mlfix を呼び出さない様に修正した。 30208 30209 確かにこの様に history -p に伴って遅延して mlfix を実行する様にすれば、 30210 HISTTIMEFORMAT が変な値になる事もないし、 30211 また時刻が history -n によって読み込んだ変な値になっているという事もない。 30212 特に問題はないだろうという気がする。 30213 30214 2020-05-06 30215 30216 * bash-4.4 trap return の work around はあるか [#D1350] 30217 30218 現在の Bash の振る舞いでは関数内でも無引数 return なら 30219 外側の終了ステータスになってしまうが、もしこれは解釈Aに修正してもらうと、 30220 ユーザートラップが無引数 return を実行したのか有引数 return を実行したのかを 30221 正しく判定しなければならなく為る。 30222 30223 a 実は return() { builtin return $?; } とすれば問題を解決できる? 30224 と一瞬思ったがこれだと return できなくなるので駄目である。 30225 30226 a 或いは alias return='ble/builtin/return; return' とでもして 30227 何とかなる? と思ったが、引数は結局取れない。 30228 30229 b RETURN トラップで何とか検出できないか。 30230 つまり function return を実行したらなにか変数に記録して、 30231 次の RETURN で実際に RETURN を実行させる事にする。 30232 30233 そして検出したらその場で RETURN する。 30234 と思ったが trap を実行している途中には RETURN トラップは無効なのでは。 30235 trap の中で trap を呼び出せるのかについて確認する必要がある。 30236 30237 →確認した所、RETURN trap の中では RETURN は発火しない。 30238 DEBUG trap の中では RETURN が発火する。 30239 つまり RETURN 以外の trap handler の中では RETURN が発火するという事。 30240 30241 % 例えば RETURN と return() { _return_status=${1:-$?}; } を組み合わせて何とかする。 30242 % もし呼び出されたフレームが trap のフレームであれば 30243 % 30244 % return() { 30245 % local status=$? 30246 % _return_arg=$1 30247 % if ((_trap_level==${#FUNCNAME[@]}+1)); then 30248 % _return_status=${1:-$status} 30249 % else 30250 % _return_status=${1:-$_trap_preceding_status} 30251 % fi 30252 % } 30253 % builtin trap '[[ $_return_status ]] || builtin return' RETURN 30254 % 30255 % ? trap の中で RETURN trap は有効か? 30256 % 30257 % うーん。色々面倒である。取り敢えず ble/builtin/trap で 30258 % return を実行できる様に修正してから調整するべきである。 30259 30260 →そもそもの問題として RETURN は関数の内部で実行される様なので、 30261 return() { ... } で return の機能を再現する事はできない。 30262 30263 或いは DEBUG/RETURN の両方を trap してどちらか最初に呼び出された方を用いて 30264 "return xxx" を実行するという手がある。何れにしても込み入った方法になる。 30265 30266 これは困難である。取り敢えず保留という事にする。 30267 30268 * trap: bash handler の継承が一体どうなっているのかは謎 [#D1349] 30269 bash の場合サブシェルの中で見ると handler が継承されていたりいなかったりするのでは。 30270 どういう規則になっているのか。どのハンドラーが継承されてどのハンドラーが継承されないのか。 30271 RETURN DEBUG と -o functrace, declare -tf との関係。 30272 ERR と -o errtrace の関係。RETURN, DEBUG では今から実行しようとしているコマンドを知る事ができるのか。 30273 ソースコードと行番号は知ることができそうな気がする。実行が eval string で定義された関数の場合には、 30274 行番号を知ったとしてもよく分からないのでは。そもそも BASH_SOURCE は何になるのか。 30275 30276 →取り敢えず #M0016 にまとめた。 30277 30278 * trap: 現在の実装だとユーザが INT に何か設定していても無視されてしまうのでは [#D1348] 30279 というより何が起こるのか不明である。 30280 然し、C-c を禁止するというのも変な気がする。 30281 後で可能な設計について考える。 30282 30283 →これは取り敢えず新しい枠組みを使ってユーザの設定した物を実行し、 30284 ユーザが return/break/continue を実行した場合にはそれを実行する様にした。 30285 然し、ble.sh 自体が設定している DEBUG trap による中止もそのままである。 30286 30287 * trap: ユーザ trap handler 内部で return を実行した時の振る舞い [#D1347] 30288 ユーザが DEBUG トラップに return を設定した場合には何が起こるのか 30289 というより全般にユーザが return を設定した時にその場で関数を抜ける、 30290 という振る舞いが再現できていない。 30291 30292 全ての hook は 'hook; if [[ $_ble_trap_return ]]; then return; fi' 30293 の様な形にするか或いは 'hook; builtin eval -- "$_ble_util_trap_hook"' 30294 の様な形にする必要があるのである。 30295 30296 因みにユーザが return で抜けたかどうかを判定するのは簡単である。 30297 というのも eval ''; _ble_builtin_trap_done=$? 的な感じにすれば良い為。 30298 もし _ble_builtin_trap_done が設定されていなければ return で抜けたという事。 30299 30300 (取り敢えずは Bash 4.4 無引数 return の問題は後回しにする。) 30301 30302 * 現状の設計について確認する。 30303 30304 _ble_builtin_trap_reserved に登録されているシグナルは特別な処理を実行する。 30305 それ以外のシグナルについては Bash の builtin trap をそのまま使う。 30306 reserved への登録は必ず ble/builtin/trap/reserve で行う。 30307 EXIT, INT, WINCH, DEBUG, USR1 を reserve している。 30308 30309 その他のシグナルについては大丈夫だが 30310 これらのシグナルについてはちゃんと処理する必要がある。 30311 30312 問題は reserve したシグナルに対する本当の trap を何処で設置しているのかという事。 30313 30314 取り敢えず先に DEBUG から対応しようと考えたが微妙である。 30315 現在の実装では DEBUG は INT を受信した時にだけ ble.sh で設定する事になっている。 30316 そしてユーザーが設定したとしても取り消される仕組みになっている。 30317 30318 DEBUG は特に全てのコマンドの前で設定されるので不要であれば外しておきたい。 30319 ユーザの設定した trap か ble.sh の設定した trap のどちらかがある時に有効になる様に実装したい。 30320 取り敢えず USR2 辺りで試験的に実装してみて枠組みを確定させるのが良い気がする。 30321 →取り敢えず USR2 で実験してみた結果は成功である。 30322 trap handler 内部での return も再現できている。 30323 勿論 FUNCNAME 等は異なる値になっているがそれは仕方ない。 30324 その他に振る舞いを左右する別の物があったりするだろうか。 30325 30326 実は、continue や break 等も本来は正しく処理したいのである。 30327 30328 | * DEBUG trap の性質について調べる事にする。 30329 | 30330 | * 取り敢えず return, continue, break は DEBUG trap で検出できる。 30331 | →実は bash-3.0 では BASH_COMMAND には trap handler 30332 | の文字列自体が入ってしまっているので、 30333 | この方法では return/continue/break は検出できない。 30334 | 30335 | continue, break に引数が指定された時にどのように検出するかに関係する。 30336 | 30337 | ? declare -ft を設定した関数では DEBUG が継承されるというが、 30338 | 間に普通の関数が挟まっていても活性化するのか? 30339 | →駄目。活性化しない。やはり飽くまでも "継承" という事の様である。 30340 | つまり、signal handler を呼び出す際に改めて trap DEBUG し直す必要がある。 30341 | 30342 | ? debug trap が有効でない関数の中で trap を呼び出して出力した時に、 30343 | DEBUG trap は列挙されないのか、それとも列挙されるけれども不活性という事なのか。 30344 | →列挙されない。 30345 | 30346 | ? 関数内部で trap DEBUG した時に、外側の trap が破壊されたりしないか。 30347 | →trap DEBUG で削除した場合には外側の trap DEBUG に影響はない。 30348 | →trap cmd DEBUG で登録した場合には、bash-4.3 以下では外側の trap DEBUG に影響はない。 30349 | 然し、bash-4.4 以降では外側の trap DEBUG も書き換わってしまう。 30350 | 30351 | ユーザの設定した trap DEBUG の有効・無効を管理するのは実は大変である。 30352 | 現在の関数の位置と一緒に覚えておく必要がある。 30353 | 関数の終端で解除するという事をしなければならない。 30354 | その為には RETURN 等にも仕掛けなければならないだろうか。 30355 | 30356 | ? 関数内部で trap DEBUG した時に、 30357 | 全く同じ trap DEBUG の内容でもちゃんと有効になるだろうか。 30358 | 30359 | →全く同じ内容で定義した時にそれが有効になったかどうかをどうやって判定するのか。 30360 | もし判定する事ができないのだとすればそれは実質動作に変化がないという事なので、 30361 | 有効になっても有効にならなくても何の問題もない。 30362 | 30363 | 或いは、関数内部で無効にになっている状態で改めて trap DEBUG を設定した時に 30364 | 有効になるのかどうかという疑問だとすれば、それは当然有効になる筈である。 30365 | 念の為に確かめる事にする→ちゃんと無効から有効に変化するという事を確認した。 30366 | 30367 | うーん。色々考えるとやはり別の trap を使うというのは 30368 | その trap の元々の機能も保持しなければならないので大変である。 30369 | 更に RETURN や DEBUG 自体の return/continue/break はどうやって検出するのか等、 30370 | 色々複雑になってしまう。 30371 | 30372 | ? DEBUG trap の中で DEBUG trap は有効か? 30373 | 実際に試してみると trap で設定する事はできるが発火しない。 30374 | BASH_COMMAND は書き換わらない。 30375 | 30376 | つまり DEBUG trap 自体を再現する為に DEBUG は使えないという事。 30377 | 30378 | * RETURN trap の性質について調べる。 30379 | 30380 | ? declare -ft, set -T の効果について。 30381 | これは DEBUG と同様に継承が決まる。 30382 | 30383 | ? 関数を抜けるコマンドが実行された後に呼び出される。 30384 | BASH_COMMAND は一番最後に実行したコマンドが入っている。 30385 | return を使った時には return コマンドである。 30386 | 30387 | ? 関数内で発火するのか、それとも関数外で発火するのか。 30388 | 関数内で発火する気がする→実際に試してみたらそうだった。 30389 | 内部で更に return を実行すると無限ループになる。 30390 | 勿論、条件付きで return すれば無限ループにはならない。 30391 | その場合には終了ステータスを書き換える事が可能になる。 30392 | 30393 | さて、この RETURN トラップの性質を考えると、 30394 | continue/break を関数で上書きするという作戦は使えない事になる。 30395 30396 a もしくは DEBUG trap を使えば面倒な事をしなくても 30397 実際に実行したコマンド (continue/break 等) を検出できるだろうか。 30398 実はその方が良いという気がする。 30399 30400 うーん。結構面倒な気がするので DEBUG trap による continue/break の 30401 引数の検出は実装しなくても良いという気がする。これは制限である。 30402 或いは完全に異なる方法で検出する方法はあるだろうか。 30403 30404 b 行番号とファイル名からソースコードを割り出してそこから読み取る? 30405 然し、continue break の引数に指定されている単語が複雑な物の場合、 30406 特に副作用がある物やコマンド置換等の場合にはそれを実行する訳には行かない。 30407 30408 c やはり RETURN trap を犠牲にして continue, break を emulate する方法を考える? 30409 因みに builtin continue, builtin break をユーザが使っている場合には不可能。 30410 30411 ? continue/break で実際に抜けられるのよりも大きな値を指定した時にどうなるか。 30412 →全てのループを抜ける。失敗するという事はない。 30413 呼び出し元関数のループには影響を与えない。 30414 30415 色々の事を考えると continue/break の引数に対応するのは複雑になりすぎる。 30416 そもそも trap を ble.sh の枠組みの上で完全に再現するのは難しそうである。 30417 30418 取り敢えずの実装 (break/continue の引数には対応しない) については 30419 以下のコマンドを用いてちゃんと動くかを確認した。 30420 30421 $ ble/builtin/trap/.set-signal-handler USR2 30422 $ trap 'echo world; return 123' USR2 30423 $ f1() { local i; echo BEGIN; while :; do sleep 0.01; done; echo END; } 30424 $ (sleep 1; kill -USR2 $$) & { f1; echo $?; } 30425 $ trap 'echo world; break' USR2 30426 $ (sleep 1; kill -USR2 $$) & { f1; echo $?; } 30427 30428 2020-05-02 30429 30430 * .s AAA と入力すると表示が乱れる [#D1346] 30431 30432 | 更にシグナルハンドラ関連の配列添字エラーが発生する。 30433 | これは一体どういう事だろうか。eba9b92 で再現している。 30434 | bash --rcfile out/ble.sh では発生しない。 30435 | 30436 | →どうやらこれは PS1= を internal_suppress_bash_output=1 30437 | の時に実行しない様に変更した事と関係している。この PS1 の出力は 30438 | bash によって出力されている物だろうか。 30439 | suppress してリダイレクトしているのに表示されてしまっている理由は何だろう。 30440 | stdout.on, stdout.off がちゃんと動いていないという事なのだろうか。 30441 | 30442 | PS1 と _ble_edit_PS1 に別の値を設定して確かめた所、 30443 | 確かに bash が勝手にプロンプトを出力しているのだという事が判明した。 30444 | 特に文字が先頭に移動するという事から、bash はプロンプトを出力した後に 30445 | \r 等を出力しているという事だろうか。或いは、ble.sh の枠組みに於いて、 30446 | \r を出力するタイミングと文字を出力するタイミングの間に 30447 | bash が介入してしまうという事だろうか。 30448 | 30449 | 或いは、bash-5.0 では実は suppress の効果がないという可能性。 30450 | 確かめてみた所 bash-4.1 以降で問題が発生する様子である。 30451 | どのタイミングで bash のプロンプトが表示されるのか確かめる。 30452 | うーん。どうも .s が含まれる場合に処理がクラッシュして off が呼び出されていない? 30453 | →その様だ。stdout.off が消滅している。何故? bashrc の設定と何か関係ある? 30454 | failglob で終了してしまっている可能性が濃厚である。 30455 | と思って shopt -u failglob で試してみたが問題は解決しない。 30456 | 30457 | 調べると idle.do の中で起こっている。更に auto-complete.idle の中で起こっている。 30458 | どんどん掘っていくと ble/complete/source:argument の中で発生している。 30459 | 30460 | →結局これは bash-completion の __load_completion の実装で 30461 | xspecs[$cmd] の $cmd に .s 等を渡すとエラーになってその場で実行が終わる為の様だ。 30462 | eval で囲んでみたがそれでも実行が停止してしまう様だ。 30463 | 30464 | もし仮にクラッシュを防げたとしても根本的な問題として 30465 | xspecs の定義が消滅してしまうという問題は関数内で source している限り残る。 30466 | 然し、これはどうしようもない。うーん。或いは xspecs が連想配列でない場合には 30467 | __load_completion を呼び出さないという事にする? 30468 | 30469 | 然し問題はそもそも bash-completion の呼び出し方にある。 30470 | その時点で何が起こっても仕方がないと諦めるしかないのではないか。 30471 30472 * まとめるとこれは bash_completion が内部で declare -A _xspecs で連想配列を宣言しているが 30473 関数内で bash_completion を source している為にこの宣言が環境に残らない。 30474 連想配列以外について _xspecs[.s] の様な参照を行うとエラーになってその場で色々の実行が終了してしまう。 30475 internal_suppress_bash_output の設定の処理についても行われずに終了してしまう。 30476 30477 * ok: 然し、直接 source する様にしても問題が解決しない 30478 何故だろうと思っていたら、実は . と source で振る舞いが違う? 30479 と思ったらこれは function#advice で remove しても関数として残留する事が原因だった。 30480 30481 つまり、関数内で実行しているので source 内の declare の類は 30482 その関数のスコープの中に作成されてしまう。 30483 同様の問題が function#advice remove unset でも起こるのではないか。 30484 常に dynamic unset になってしまう。 30485 従って、advice する物がなくなったら元に戻すというのが正しい筈。 30486 30487 →これはその様に修正した。OK 30488 30489 bash-completion については自分で直接 source してもらうしか解決方法はない。 30490 従ってこれについては諦める事にする。 30491 30492 或いは bind -x の exec 経由で bash-completion を 30493 実行するという手がない訳ではない。 30494 然し、何れにしてもその他の枠組みを用いた場合でも autoload すると、 30495 bash-completion は正しく初期化する事ができないという事になる。 30496 まあ取り敢えずは気にしない事にする。 30497 30498 2020-04-27 30499 30500 * SIGWINCH でちゃんとプロンプトの計算が更新されていない [#D1345] 30501 30502 要約: builtin trap WINCH 後に readline でコマンドを実行しないと、 30503 readline が COLUMNS/LINES の更新に使っている handler が設置されない。 30504 30505 というより、空コマンドで RET を押しても更新されない。 30506 そもそもプロンプトのキャッシュで COLUMNS:LINES を参照していなかったのか。 30507 →うーん。確認すると COLUMNS が入っている。 30508 30509 という事はつまりそもそも ble-edit/prompt/update まで到達していない? 30510 然し、それも変な気がする。何しろ RET を押しても更新されないのだから。 30511 →実は更にその次の部分でのキャッシュにより更新が抑えられている? 30512 30513 うーん。trace_hash にもちゃんと COLUMNS が記録されている。 30514 というか rps1 ですら再計算されていない。という事は、やはり 30515 ble-edit/prompt/update にまで到達していないと見るべきか。 30516 30517 不思議だ。手許で新しく実行してみると症状が再現しない。 30518 然し、ble-reload した場合には再現している。 30519 何らかの条件で発生したりしなかったりするのだろうか。 30520 振る舞いを調べるとやはりそもそも SIGWINCH を受信していない? 30521 と思ったがそれも変である。そうだとしたら再描画されていない筈。 30522 30523 取り敢えず reload では再現するので其処を手がかりに調べていく事にする。 30524 →分かった。新しいセッションでも reload すると再現する様になる。 30525 然し、cygwin では常に再現する。 30526 →分かった。COLUMNS, LINES が更新されていない様だ。 30527 それから SIGWINCH もその場では実行されなくなっている。 30528 ユーザが何かを入力したタイミングで初めて SIGWINCH が発火する。 30529 30530 問題は何故最初は動いていたのに reload すると動かなくなるのかという事。 30531 何らかの操作が関係しているのだろうか。或いは、二回以上 SIGWINCH すると 30532 振る舞いが変わってしまうという事なのだろうか。 30533 30534 更に stty の状態やリダイレクトの構造も関係してくるのかもしれない。 30535 確認したがリダイレクトの構造については変化はない。 30536 stty についても stty 自体が悪さをしているという事はないだろう。 30537 何かあるとしても特定の stty の時に何かをすると再現するという事だろう。 30538 30539 →再現した。或いは builtin trap を実行する環境に問題があるのかもしれない。 30540 ble-detach して builtin trap して ble-attach しても問題は発生しない。 30541 問題が発生している時に ble-detach; ble-attach すると直る。 30542 30543 今までの振る舞いを整理すると。 30544 30545 * ble-reload すると問題が発生する様になる。 30546 * builtin trap -- ... WINCH するだけで発生する。 30547 * ble-attach; ble-detach すると直る。 30548 ? 他の bash version は? 30549 bash-4.1 以下では常に問題が発生している。 30550 bash-4.2 以降は bash-5.0 と同じ振る舞いである。 30551 つまり、この振る舞いは特に最近導入された物ではないし、 30552 寧ろ古い bash の方が振る舞いが酷いという事である。 30553 ? WINCH 以外の builtin trap でも問題は発生するか? 30554 →しない。WINCH を設定したときにだけ振る舞いが変化する。 30555 30556 問題は何処に在るのか。そしてどの様に避ける事ができるのか。 30557 ble-attach; ble-detach で直るのは何故なのか。 30558 一旦 readline に戻すと良くなるという事なのか、 30559 或いは、何らかの設定 (stty) 等が変更されてしまうという事なのか。 30560 然し、stty の問題であれば何か一つでもコマンドを実行すれば 30561 変な振る舞いにはならずに元と同じ様になる筈である。 30562 30563 ? bleopt_internal_suppress_bash_output= bash でも再現するのか。 30564 →bleopt_internal_suppress_bash_output= では発生しない。 30565 つまり勝手に標準入出力を繋ぎ変えているつけである。 30566 これは単純なスクリプトで再現するのは難しそうだし、 30567 再現できたとしてもそんな変な事をしているのが悪いという事になる。 30568 30569 然し、それでは何故普通に attach した時には問題がなくて、 30570 biltin trap -- し直した時にだけ問題が発生するのだろうか。 30571 30572 ? ble-detach; ble-attach をその場で実行したら直るだろうか。 30573 (振る舞いを見ると治らない様な気もする。 30574 一回通常の状態で bind -x から抜ける必要がある気がする。) 30575 30576 ble-detach/impl と ble-attach を呼び出せば良いだろうか。 30577 →これだと直らない。 30578 30579 或いは、edit.sh の ble/widget/.change-editing-mode では 30580 次の操作を実行している。 30581 ble/decode/reset-default-keymap 30582 ble/decode/detach 30583 ble/decode/attach 30584 →これでも直らない (reset-default-keymap は試していないが関係ないだろう)。 30585 30586 % と思ったら builtin trap しても再現しなくなってしまった。 30587 % と思ったら分かった。 WINCH ではなくて USR2 に対して実行していた。 30588 30589 ? 子bashで問題が発生している状態で終了したら、 30590 親bashでも問題が発生したままだろうか。 30591 →親bashでは問題は発生していない。 30592 つまり、これは tty の状態というよりは 30593 やはり bash のプロセスの中で起こっている問題である。 30594 bash のプロセスの側で修正されるべき物である。 30595 30596 ? internal_suppress_bash_outputを一瞬だけ有効にするという手もなくはない? 30597 30598 追記: 原因は別の所にあったのでこの方法では何も解決しない。 30599 30600 % 本当に可能だろうか。そしてそれで本当に解決するのか。 30601 % 30602 % builtin trap で上書きが実行される瞬間、または、 30603 % ble-reload が行われた後に対策を実行する必要がある。 30604 % そもそも ble-reload はどのタイミングで再ロードを実施しているのか。 30605 % 現在の実装だと prompt で再ロードを実行している。 30606 % 30607 % * 棄却: Bash の PROMPT_COMMAND で ble-attach すれば問題は解決するのでは? 30608 % この prompt command の表示は何処で実行されるのか。 30609 % Bash による物なのか或いは ble.sh 自身による物なのか。 30610 % →確認した所、ble.sh 自身の eval-prompt の中から実行されている。 30611 % --attach=prompt と同様の状態に持っていく事はできないのだろうか。 30612 % 30613 % ここでの問題は PROMPT_COMMAND が実際に呼び出されるのかという事。 30614 % →試してみたが bind -x の関数の呼び出しの直後には呼び出されない。 30615 % WINCH の後でも呼び出されない。 30616 % PROMPT_COMMAND から ble-attach するのはできない。 30617 % 30618 % ここでの問題は其処ではない。suppress_bash_output を無効にするという事。 30619 % 一時的に無効にすることは果たして可能だろうか。 30620 % 確認してみた所、internal_suppress_bash_output は元々有効なのを 30621 % 一時的に無効にするのは可能である様に見える。有効な時にだけ行う初期化がある。 30622 % 無効な時には何も初期化はしない。 30623 % 30624 % と思ったが無効な時の stdout.on stdout.off を上書きしていた。 30625 % stdout.on と stdout.off に internal_suppress_bash_output= の時に 30626 % 処理を動的に切り替える様にすれば良い様な気がする。 30627 % 30628 % 然し一時的に切り替えたとして誰が復元するのか。 30629 % うーん。それよりは internal_suppress_bash_output=tmpoff 等の様に 30630 % 特別な値を設定して、その特別な値の時にだけ対策を実行する? 30631 % そして一回特別な処理をしたら後はまた普通の値 (1) に戻す。 30632 % 30633 % * PS1 の保存・復元方法の変更 30634 % 30635 % | ここで問題になる可能性があるのは PS1= にする対処を 30636 % | bash_completion の為に諦めた事である。 30637 % | PS1= に有限の文字列が含まれている為、初期化スクリプトが勘違いする。 30638 % | 実際の所 bash_completion は二度以上初期化しないのでここでは関係ない。 30639 % | 然し、その他のスクリプトで二度以上実行する必要のあるものがあるかもしれない。 30640 % | そして、最初のプロンプトを表示してユーザ待ち状態になっている時に 30641 % | ble-import を実行する可能性は高い。 30642 % | 30643 % | というより、本当に PS1= を諦める必要があったのだろうか、という疑問が残る。 30644 % | PS1= のタイミングを本当に一番最後にしていれば問題は起こらなかったのではないか。 30645 % | →調べると PS1 は殆ど常に待避した状態になっていて 30646 % | コマンドを実行する直前と直後にだけ復元するという事になっている。 30647 % | 実は単に stdout.{on,off} のタイミングで保存・復元すれば良いのでは。 30648 % 30649 % もし一時的に internal_suppress_bash_output を無効化するのであれば、 30650 % 同時に PS1 の待避の方法も変更する必要がある。現在はユーザコマンドを実行する度に 30651 % PS1 を復元するという方策を取っているが、実は stdout.{on,off} を呼び出す度に 30652 % 保存・復元を実行するという形にすれば良い。その場合には _ble_edit_PS1 の代わりに 30653 % PS1 を直接編集する様に変更する必要がある。もしくは PS1 を _ble_edit_PS1 にコピーする。 30654 % read 等を実行する際に一時的に _ble_edit_PS1 を変更しているが、 30655 % これはどうなのだろう。。と思ったが、これは save/restore-vars で復元されるのだった。 30656 % なので実は PS1 を直接上書きする方法でも良い気がして来た。 30657 30658 原因について調べればもっと良い回避方法が見つかる可能性もある。 30659 30660 * そもそも RET でコマンドを実行すると一時的に直るのは何故だろうか。 30661 30662 要約: stty を実行するとその場で COLUMNS/LINES が更新される。 30663 WINCH によって更新される訳ではないし、WINCH handler が修正される訳でもない。 30664 30665 | 特に echo を実行しただけで直るというのは不思議である。 30666 | 或いは、もっと早くに COLUMNS が修正されているが、 30667 | 単にプロンプトが更新されていないだけ? 30668 | 30669 | →確認すると確かに echo を実行した直後に初めて COLUMNS が更新されている。 30670 | これが意味する所は何だろうか。epilogue/prologue で何かが起こっている? 30671 | 30672 | →分かった。term/enter,leave を省略すると 30673 | コマンドを実行しても COLUMNS が更新されない。 30674 | これは stty を実行すると直るという事だろうか。 30675 | →その様だ。特に stty sane でも良いので実行すると COLUMNS が更新される。 30676 | 30677 | 或いは bash で何か操作したら直るかもしれない。 30678 | shopt -u checkwinsize; shopt -s checkwinsize を stdout.on に入れてみたが 30679 | 特に何も変化はない。COLUMNS も更新されない。 30680 30681 * bind -x で再現する事は可能だろうか。 30682 例えば。trap WINSIZE を実行してから一度でも 30683 stdout.on で制御を bash に戻せば状態は元に戻るのである。 30684 30685 逆に言えば、生の bash でこの状態を再現する為には 30686 全ての bind -x に bind しなければならない? 30687 と思ったがユーザが特定のキーしか押さないという事にすれば十分再現できる? 30688 30689 取り敢えず C-t で bash suppress に入って C-y で抜ける様な bashrc を作った。 30690 更にここで builtin trap -- WINCH を実行するのである。 30691 取り敢えず手許のスクリプトでは問題を再現する事ができた。 30692 30693 不思議なのはこのスクリプトだと最初から winch を trap していたとしても、 30694 suppress している時に WINCH が呼び出されず、COLUMNS も更新されない事。 30695 ble.sh の場合には bash-4.2 以降では既定では suppress していても 30696 ちゃんと WINCH が更新されているという事なのである。 30697 30698 ここでの疑問は何故 "bind -x" 外で trap を設定した時に 30699 ble.sh でちゃんと動いている様に見えるのかという事である。 30700 30701 [問題] 30702 30703 * bash-4.2 以降では reload すると問題が発生する。 30704 * bash-4.1 では常に問題が発生している。 30705 * Cygwin でも常に問題が発生している。 30706 30707 bash-4.2 以降の初期状態の様に振る舞わせる事が可能であればそれで良いが、 30708 現状の様子を見ると bash-4.1, Cygwin では問題が発生している。 30709 従って可能であれば bash-4.1, Cygwin でも常に動くような対策が欲しい。 30710 30711 a 一つの可能性は毎 bind -x で stty sane を実行するという事。これは 30712 重い。或いは空コマンドを実行する場合 (newline) でも stty sane を 30713 実行するという事。これもある程度の重さが残ってしまう気がする。 30714 30715 stty sane 以外の方法で COLUMNS を更新させる事は可能だろうか。 30716 30717 b 例えば winsize の通知を要求する terminal sequence はあるのだろう 30718 か。端末エミュレータ側では termios で端末サイズなど設定してしま 30719 うので、端末自体がこれに対応しているという話は効いたことがない。 30720 端末ハンドラ経由で要求するしかないのだろうか。簡単な terminal 30721 sequence でサイズを要求できないのか。 30722 30723 c 或いは現在の端末のサイズを変更するシーケンスを送れば強制的に 30724 WINCH をその場で発生させる事ができるだろうか。然し、その為には端 30725 末のサイズを知っていなければならない。或いは端末のサイズを実質的 30726 に変更しないシーケンスを送る事ができたとしても、端末側がサイズが 30727 変更なかった場合に termios に設定しないのだとしたら、或いは端末 30728 ハンドラが変更チェックを行っていたとしたらこれは効果がない。 30729 30730 bash のソースを確認すると値の設定を行っているのは恐らく 30731 sh_set_lines_and_columns である。そして呼び出し元は lib/sh/winsize と 30732 readline である。lib/sh/winsize は get_new_window_size を提供している。 30733 get_new_window_size は第一引数に from_sig というのがあるが、 30734 これは使われていないし、また、呼び出し元でも 0 しか指定していない。 30735 readline 側での呼び出し元は _rl_get_screen_size である。 30736 また readline 内部にも sh_set_lines_and_columns の実装がある。 30737 lib/readline/shell.c である。でもこれは readline を standalone で 30738 コンパイルした時に使われる物ではないかとの疑惑がある。 30739 30740 [未解決の謎] 30741 30742 * 何故 bash-4.2 以降 / linux では WINCH を検出できているのか。 30743 というかそのまま bash を抜けると親 bash はちゃんと動くので、 30744 端末ハンドラの設定ではない。やはり bash 自体が何だか変な事になっている。 30745 30746 Bash の実装について確認する 30747 30748 | bash の振る舞いについて調べている。どうも biltin trap で WINCH に登録すると 30749 | bash は別のシグナルハンドラを signal で登録し直す様である。 30750 | builtin trap -- WINCH していると sig.c sigwinch_sighandler が呼び出されない。 30751 | 何も実行していないと呼び出される。他に検索してみたが直接に trap handler を 30752 | 設定している箇所は見つからなかった。だとすると普通の siginal の一つとして 30753 | signal handler が登録されているという事になる。本当だろうか?? 30754 | signal 関数の呼び出しを検索してみると readline の他には sig.c しか存在しない。 30755 | 結局 set_signal_handler 関数で全て設定しているという事だろうか。 30756 | 30757 | 実装を見るとどうも sigaction という sycall を使っている。 30758 | 直接に signal を使っているという訳ではない様である。 30759 | 一応、実際にこの関数が本当に呼び出されているか確認する。 30760 | →何と物凄い勢いで呼び出されている。SIGWINCH だけを拾う。 30761 | →調べてみると fork する度に呼び出されている様である。 30762 | サブシェルの起動時にも呼び出されている。 30763 | これだと余り参考にならない気がする。 30764 | 30765 | うーん。0x480040 というアドレスの関数を設定している。 30766 | それ以外の関数は設定していない様だ。 30767 | そしてこの 0x480040 とは何だろう。 30768 | どうやら sigwinch_sighandler の様である。 30769 | 然しこれは呼び出されていなかった筈である。 30770 | 30771 | どうやら trap_handler が登録されてはいるけれども、 30772 | サブシェルを起動する時にはそれをキャンセルする為に 30773 | sigwinch_sighandler が登録されているということの様である。 30774 | 30775 | | なのでここで観察するべきは trap_handler の方である気がする。 30776 | | 調べてみると変な状態になった後でもちゃんと trap_handler は起動されている。 30777 | | という事はその後の処理の流れが変だという事になる。 30778 | | trap_handler の中では実はシグナルハンドラは処理しない。 30779 | | 単に pending_traps 配列に情報を記録するだけである。 30780 | | interrupt_immediately は試した範囲では 0 である。 30781 | | すると run_pending_traps の中で何か変な事が起こっている? 30782 | | 30783 | | run_pending_traps が呼ばれるタイミングを調べようとしたが呼び出されない。。。 30784 | | 一度 run_pending_traps が呼び出されれば大量に run_pending_traps が呼び出される。 30785 | | 然し、trap -- を実行した後だと何も実行されない。不思議である。 30786 | | run_pending_traps の呼び出し元は沢山ある。builtin trap を実行すると 30787 | | 何処かの呼び出し元で何かが変化するという事。 30788 | | 30789 | | run_pending_trapsの振る舞いを調べる必要がある。 30790 | | 正常に動作している時に run_pending_traps が一回だけ処理される。 30791 | | 呼び出し元は check_signals_and_traps で更に 30792 | | 呼び出し元は bash_event_hook である。 30793 | | この関数は実は rl_signal_event_hook に対して関数ポインタとして設定される。 30794 | | 有効・無効が bashline_{set,reset}_event_hook で切り替えられる様になっている。 30795 | | 30796 | | 振る舞いを見ると以下の様になっている。 30797 | | 30798 | | - trap_handler 30799 | | - bashline_set_event_hook 30800 | | - (interrupt が設定されていないので 30801 | | その場では run_pending_traps は実行しない) 30802 | | - _rl_signal_handler 30803 | | - bashline_reset_event_hook 30804 | | - bash_event_hook 30805 | | - check_signals_and_traps 30806 | | - run_pending_traps 30807 | | 30808 | | bashline_{set,reset}_event_hook は毎回設定・解除する様である。 30809 | | 一方で builtin trap した場合にも bashline_set_event_hook が呼び出されている。 30810 | | 2回目以降には呼び出される事は無いようである。 30811 | | 30812 | | そして、問題が起こっている時にはそもそも 30813 | | _rl_signal_handler も呼び出されない様だ。 30814 | | RL_CHECK_SIGNALS というマクロの中で呼び出されている。 30815 | | そしてこのマクロは色々なところから呼び出されている。 30816 | | 取り敢えず一番怪しい signals.c から見る。 30817 | | rl_check_signals という関数から呼び出されている。 30818 | | 然しこの関数は誰も使っていない様に見える。 30819 | | RL_CHECK_SIGNALS マクロ自体に __FILE__, __LINE__ を出力する様に細工を入れた。 30820 | | 結果として呼び出し元は input.c:625 である様だ。 30821 | | 30822 | | _rl_caught_signal と errno == EINTR をチェックしている。 30823 | | 30824 | | 漸く違いを見つけた。getc で EINTR を受け取った時に、 30825 | | 問題が発生していない時には _rl_caught_signal = 28 (WINCH) なのに、 30826 | | 問題が起こっている時には _rl_caught_signal = 0 になっている。 30827 | | これを強制的に 28 に書き換えたらどうなるだろうか。 30828 | | →うーん。一段階深くまで行くようにはなったが結局止まっている。 30829 | | bashline_set_event_hook が呼び出されていないからの気がする。 30830 | | 30831 | | 先に bashline_set_event_hook の呼び出し箇所について確認するのが良い気がする。 30832 | | 確認すると trap_handler の中に説明が書かれている。 30833 | | EINTR で反応をする事ができる、とその様に書かれている。 30834 | | 此処で bashline_set_event_hook を呼び出している。 30835 | | その様にする条件は RL_ISSTATE (RL_STATE_SIGHANDLER) だそうである。 30836 | | これは何だろうか。 30837 | | #define RL_ISSTATE(x) (rl_readline_state & (x)) のように定義されている。 30838 | | rl_readline_state の状態が異なるという事なのだろう。 30839 | | 実際に rl_readline_state を出力してみると 4800e が 4000e に変化している。 30840 | | この 8 というのが丁度 している。 30841 | | その様にする条件は RL_STATE_SIGHANDLER なのだろう。 30842 | | ではこの RL_STATE_SIGHANDLER というのは何処で設定or解除されるのか? 30843 | 30844 | ここで問題が2種類ある (1) SIGWINCH までは受信している。 30845 | しかし trap handler が何故か実行されない。(2) COLUMNS が更新されない。 30846 | それぞれ何故なのだろうか。 30847 | 30848 | うーん。どうやらやはり rl_sigwinch_handler が呼び出されるか 30849 | trap_handler が呼び出されるかの違いらしい? 30850 | 両方とも trap_handler が呼び出されている様に見えたが、 30851 | 実際には通常時は rl_sigwinch_handler 経由で trap_handler が呼び出されて、 30852 | それ以外の場合には rl_sigwinch_handler が呼び出されるという仕組みになっている様だ。 30853 | 30854 | そして builtin trap を実行すると sigwinch_handler が消滅する。 30855 | 何らかのタイミングで再度設置されるというだけの様な気がする。 30856 | 30857 | うーん。sig.c の set_signal_handler を見る限りでは trap_handler しか設定していない。 30858 | 実は他に rl_set_sighandler という関数が存在して其処で rl_sigwinch_handler が設定される様だ。 30859 | また、普通の readline 環境で builtin trap -- WINCH を実行するとこの 30860 | trap_handler の呼び出しと rl_set_sighandler の呼び出しが両方実行される。 30861 | 30862 | [set_signal_handler (sig.c)] SIGWINCH trap_handler (25353) 30863 | [rl_set_sighandler (signals.c)] SIGWINCH rl_sigwinch_handler (25353) 30864 | 30865 | $ builtin trap -- 'ble-edit/attach/TRAPWINCH' WINCH; sleep 5 30866 | を実行してみて判明したのは rl_set_sighandler は builtin trap に対して発生しているのではなくて、 30867 | readline に制御が戻ってきた時に改めて設定する物である様だ。 30868 | 30869 | うーん。rl_maybe_set_sighandler という関数から呼び出されていて、 30870 | この関数自体は普通の readline で毎回コマンドを呼び出す度に呼び出される。 30871 | そしてこの関数は rl_set_signals という関数から呼び出される。 30872 | 30873 | rl_set_signals という関数がコマンドを呼び出す度に呼び出されるという事の様だ。 30874 | 然し不思議なのは ble/term/enter, leave を実行すると回復するという事である。何故? 30875 | 実は WINCH は呼び出されていないけれども何らかの理由で COLUMNS, LINES が更新されるという事だろう。 30876 | →実際に WINCH handler が呼び出されていないという事を確認した。 30877 30878 今までに分かった Bash の振る舞いについて以下にまとめる。 30879 30880 1. builtin trap は trap_handler という関数を登録する。 30881 これは SIGWINCH に対しても同様である。 30882 30883 2. readline はユーザがコマンドを実行し終わったタイミングで 30884 rl_set_signals - rl_maybe_set_sighandler - rl_set_sighandler(SIGWINCH) として、 30885 rl_sigwinch_handler を SIGWINCH に登録し直す。 30886 この rl_sigwinch_handler が COLUMNS, LINES を更新してくれるのである。 30887 そして元々登録されていた関数も呼び出してくれる。 30888 30889 然し、ble.sh では bind -x でユーザのコマンドを処理しているので、 30890 readline の rl_set_signals が呼び出される機会がない。 30891 そうすると壊れたままという事になる。 30892 30893 # * なので PROMPT_COMMAND で attach したとしても解決はしない。 30894 # 30895 # * ble-detach してから ble-attach すると問題が解決して見えたのは、 30896 # 単に readline としてコマンドを実行したからであった。 30897 # つまり、コマンドであれば何でも良かった。 30898 # 30899 # * ble/term/enter, leave で解決した様に見えたのも少し違った。 30900 # ble/term/enter, leave を実行すると stty が呼び出されて 30901 # その場で COLUMNS, LINES は修正されるが、 30902 # 実はもう一度 winsize を変更するとまた変な状態になる。 30903 # これは一時的に COLUMNS の状態が正しくなるというだけで、 30904 # trap 関連で変な状態になっているというのを修正する事にはなっていない。 30905 # 30906 # ? ok: suppress をしていないと問題が起こらないのは何故か。 30907 # →問題が起こっていない様に見えたのは勘違いだった。 30908 # 今試してみると suppress しない場合でもちゃんと問題が発生している。 30909 # 30910 # * Cygwin で bash-4.2 以降でも問題が起こっている原因は分からない。 30911 # Cygwin ではまた別のタイミングで rl_set_signals 等を実行しているのかもしれない。 30912 # 或いは、単に trap_handler が別の理由で中断しているというだけかもしれない。 30913 # これはまた別の機会に考える事にする。 30914 # 30915 # ? 保留: bashline_set_event_hook が builtin trap で呼び出されているのは何故か。 30916 # これについては未だ調べていないが、全体について大体分かったし、 30917 # この部分は余り関係無さそうなので今は調べなくて良い。 30918 30919 30920 ここで考えるべき事は何か。 30921 30922 a rl_set_signals を誘起する別の手法について考える。 30923 b builtin trap を二度としない様にする。 30924 30925 b の方が現実的かもしれない。が、ble-update で違う値になる場合に為る時は 30926 もう一度実行せざるを得ない。しかし、そういう事はめったに起きないし、 30927 そもそもこの問題はそんなに大きな問題ではない。一時的に表示が乱れる程度なのだ。 30928 という事を考えると、取り敢えずは b の方で良い気がする。 30929 30930 * [棄却] rl_set_signals を誘起させる方法について 30931 少し試してみたがうまく行かないので諦める事にする。 30932 30933 もし a が可能であればそちらの方が良いので少し確認しておく事にする。 30934 rl_reset_after_signal という関数が呼び出している。 30935 _rl_callback_newline, rl_callback_read_char という関数も特定の条件の元で呼び出している。 30936 後は readline 関数が一番最初の最初の初期化で呼び出している。 30937 可能性があるとすれば rl_reset_after_signal である。 30938 30939 →然し、これが呼び出されるのは INT, TSTP, TTIN, TTOU, TERM, HUP, ALRM, QUIT である。 30940 例えば INT を上書きして invoke するというのもありなのかもしれない。 30941 試しに実装してみる事にする。 30942 30943 TSTP, TTIN, TTOU, INT, TERM, HUP, QUIT, WINCH は全て再設定の対象の様である。 30944 という事は INT を上書きするのも問題が発生するという事。うーん。 30945 30946 もっと具体的に見る事にする。rl_reset_after_signal は _rl_handle_signal から呼び出される。 30947 更にこれは _rl_signal_handler から呼び出される。更に SIGHANDLER_RETURN から呼び出され、 30948 これは rl_signal_handler から呼び出される。つまり。rl_signal_handler が設定されている 30949 シグナルを使わなければならない。その場で trap すると trap_handler が設定されてしまうので、 30950 その様な handler をその場で生成する事はできない。とすれば。うーん。分からない。 30951 原理的にはどれか一つに何か無害な物が設定されていれば特に問題は起こらない筈。 30952 30953 取り敢えず TSTP, TTIN, TTOU は特に何も起こらない様である。 30954 これらに特に何も設定されていなかったらそれを使うという事で良いのだろうか。 30955 取り敢えず試してみる事にする。 30956 →実際に試してみた所全く呼び出されない。どういう事だろう。 30957 何か trap に登録していないと駄目という事だろうか。 30958 30959 # Induce "rl_reset_after_signal" to set up rlhook 30960 for sig in TTOU TERM QUIT; do 30961 ble/util/assign trap "builtin trap -p $sig" || continue 30962 [[ ! $trap ]] || continue 30963 kill -"$sig" "$$" 30964 return 0 30965 done 30966 30967 うーん。駄目だ。動かない。諦める事にする。 30968 30969 調べてみると TTOU に確かにハンドラが設定されている気がするが実際には呼び出されない。 30970 もっと別の仕組みによってもみ消されているのか、或いは、 30971 単に別の場所で handler が上書きされてしまっているのか。 30972 どうしたら上書きされているか分かるだろうか。 30973 signal を2回呼び出す? 或いはもしそもそも全く呼び出されないのだとすれば。 30974 signal SIG_DFL を呼び出して中身を出力して抜ければ良い気もする。 30975 30976 うーん。やはり呼び出されない。そして TTOU を再設定する時に確認したが、 30977 やはり rl_signal_handler が設定されている。別のものは設定されていない。 30978 どうも自分で kill を呼び出すと何も起こらない様だ。 30979 子プロセスから呼び出しても何も起こらない。 30980 別の通信方法を使っているとしても不思議である。 30981 時間の無駄なので深追いするのはやめる事にする。 30982 30983 2020-04-26 30984 30985 * bash-completion が有効になっていない→ PS1= の影響だった [#D1344] 30986 何かと思っていたが、分かった。 30987 bash-completion は PS1='' かどうかで対話シェルかどうかを判定している。 30988 本来対話シェルかどうかの判定には $- を使うべきである。 30989 30990 * bash-completion が何故 PS1 を使っているのか 30991 30992 良く分からない。 30993 30994 * bash の振る舞い 30995 動作を調べてみると (PS1= bash) として起動すると PS1 は空になる。 30996 (unset -v PS1; bash) として起動すると PS1 にはデフォルト値が設定される。 30997 bash-1.14 の時点でその様に振る舞っている。 30998 然し、bash-completion はその様に実装されていない気がする。 30999 31000 また $- についても bash-1.14 の時点でちゃんと i を含んでいる。 31001 31002 うーん。改めてソースコードを見ると shellcheck=sh としているので、 31003 その他のシェルの場合を考慮に入れていると解釈できる。 31004 BASH_VERSION をチェックしている時点で bash と確定しているので、 31005 $- を使わない理由は "${-%%i*}" != "$-" が構文エラーになる処理系があるという事か。 31006 少なくとも dash は対応している。 31007 31008 * The Bourne sh で試してみたら ${var%i*} に対応していない様だ。 31009 結局 $- に i が含まれているかどうかを判定する為には case..esac が必要という事? 31010 →と思ったが [ -n "$BASH_VERSION" ] && [ $- == ${-%i*} ] で普通に動いている。 31011 31012 多分、the Bourne sh などどのシェルでもエラーにならなくて、 31013 簡単で分かりやすいからである。 31014 31015 何れにしても PS1 を使って対話環境かどうかを判定しているスクリプトは他にもありそうである。 31016 31017 a という事を考えると PS1= の上書きはしない様にしても良いのかもしれない。 31018 元々 PS1= にしているのは Bash の出力を抑制する為だった。 31019 然し、現在の stdout.on, off を実装してからは実は必要ないはず。 31020 31021 記録を辿ったが PS1= にする理由については殆ど書かれていない。 31022 一番最初のメモである #D0002 によると C-d を受け取る為に必要らしい。 31023 当初は stty を実行していなかったからそれと関係するかもしれない。 31024 現在は stty で調整しているが bash-3.2 ではそれも動かない。 31025 31026 取り敢えず bash-3.2 で PS1= にしなくても動くか確認する。 31027 →問題なく動いている。internal_suppress_bash_output を有効にしていない 31028 時に PS1 が空になって設定が誤作動するのは仕方がない。 31029 そもそも internal_suppress_bash_output はデバグ用の設定だから気にしなくて良い。 31030 31031 b 或いは或る程度はシェルの状態を復元して ble-import する方が良いのかもしれないと考えたが、 31032 ble-import の中で実行している以上は set -e だとかのユーザ環境に対して適用する 31033 事を意図した様な設定は off にしておきたい気もする。 31034 31035 飽くまで ble-import は blesh 空間で実行するという仕様という事にする。 31036 但し PS1 等の変数は多くのスクリプトが使う物という事で空欄にするのはやめる。 31037 31038 取り敢えず a の方針で変更した。 31039 31040 結局これは外部のスクリプトを ble-import で初期化した時に起こる問題なので 31041 影響範囲は少ないだろう。唯一 fzf は ble-import で読み取る設定を紹介しているが、 31042 fzf は $- を使って判定していた筈なので影響はないのである。 31043 31044 * OK: preexec の振る舞いについての調査 [#D1343] 31045 preexec は全てのコマンドの前に実行する物なのか、 31046 或いは、ユーザコマンドの開始前に実行する物なのか。 31047 zsh での振る舞いと bash-exec での振る舞いを調べる必要がある。 31048 31049 * zsh で試してみた所、ユーザのコマンドを実行しようとした時に実行される。 31050 各コマンドの前で毎回実行するという事はない。 31051 31052 % autoload -Uz add-zsh-hook 31053 % preexec_func1() { echo "[$LINENO]"; } 31054 % add-zsh-hook preexec preexec_func1 31055 % echo 31056 % for i in {0..10}; do echo hello; done 31057 31058 * 一方で Bash の DEBUG は全てのコマンドの前に実行される。 31059 特に "for i in {0..10}" という部分に対しても毎回呼び出される様だ。 31060 31061 $ trap 'echo "[DEBUG] $BASH_COMMAND"' DEBUG 31062 [DEBUG] 31063 $ for i in {0..10}; do echo hello; done 31064 [DEBUG] for i in {0..10} 31065 [DEBUG] echo hello 31066 hello 31067 ... 31068 31069 * bash-preexec はどうだろうか。試してみた所、 31070 ちゃんとユーザコマンドの実行前に一回だけ実行される。 31071 31072 $ bash --norc 31073 $ . bash-preexec.sh 31074 $ preexec() { echo "[preexec] $BASH_COMMAND"; } 31075 $ echo hello 31076 [preexec] echo hello 31077 hello 31078 $ for i in {0..10}; do echo hello; done 31079 [preexec] for i in {0..10} 31080 hello 31081 hello 31082 ... 31083 31084 従って、現状の動作で問題ない。 31085 31086 2020-04-24 31087 31088 * [棄却] LC_ALL= LC_COLLATE=C 等の指定をしているが、 [#D1342] 31089 もしユーザーが LC_ALL に自分の言語情報を指定していた時にはどうなるのか。 31090 そういう事を考えると LANG に LC_ALL:LANG から導出した値を指定する必要があるのではないか。 31091 31092 うーん。然し勝手に LC_ALL を空にしてそれから LANG に値を設定すると、 31093 LC_ALL で上書きしていた他の locale (LC_CTYPE) は一体どうなるのだろうか。 31094 例えば LC_CTYPE を LC_ALL で上書きしていたとする。 31095 ここで LC_ALL をクリアしてそれを LANG に設定したとする。 31096 LANG よりも LC_CTYPE の方が優先される事から、 31097 上書きされていた筈の LC_CTYPE が有効になってしまう。 31098 31099 x そういう事を考えると完全に対応する為には 31100 全ての locale 項目に対して値を再計算する必要がある。非効率である。 31101 x 更に locale 項目に値を設定する度に内部で locale の構築が行われる。 31102 locale の構築はファイルの読み取りなども発生し重い処理になるので、 31103 できるだけ少なくしたい。 31104 x 更に、ユーザが LC_CTYPE などを指定したとしてもそれが有効になってはならない。 31105 LC_ALL で強制している筈だからである。 31106 然し個別に locale を指定する場合にその振る舞いは再現できない。 31107 31108 などなどという事を考えるとユーザが指定した LC_ALL の効果を正しく保持するというのは難しい。 31109 飽くまで LC_ALL は特別な場合の回避方法であるという事を考えると、 31110 ble.sh の特別の関数の中では LC_ALL の効果がなかった事にしても良い様に思う。 31111 31112 * util: LANG=en_US.utf8 の時の bash-3.2 の振る舞いが変である [#D1341] 31113 ref memo/D1341.locale-and-casematch.sh 31114 31115 c2s のテストで見つかった。ble/string#toupper で問題が発生していた。 31116 調べると LC_ALL= LC_COLLATE=C func と指定しても bash-4.1 以下では効果が出ない。 31117 31118 local LC_ALL= LC_COLLATE=C 31119 func 31120 31121 等の様にして実行しないと駄目の様である。 31122 31123 LC_ALL= LC_CTYPE=C については大丈夫なのだろうか。 31124 と思って試すと大丈夫に見えたが良く見たら既に対策されていた。 31125 つまりこの問題は或る意味で既知の問題だったのである。 31126 31127 * test: ble.sh --test でテストを実行する? [#D1340] 31128 interactive session に入らずに色々実行する機能? 31129 31130 * というより複数の bash version でテストする機能も作りたい気がする。 31131 然し、毎回全ての version でテストするのも大変である。 31132 →と思ったがユーザの環境によって異なるし、 31133 31134 呼び出す時には結局何れかの version の bash から 31135 更に様々な bash の version に ble.sh を読み込ませなければならない。 31136 親の bash では実は ble.sh を読み込む必要は全く無い。 31137 という事を考えると、実は make_command.sh 辺りに実装するべきなのではないか。 31138 31139 m check には既にソースコードのパターン検出によるチェックがある。 31140 然し、m check と言えば普通はテストである。 31141 現在の check は別の名前に変更したい。名前は何が良いか。 31142 lint という程でもないし、check-pattern は長い。 31143 check-all で全部チェックするというのでも良いのかもしれない。 31144 31145 うーん。取り敢えず scan という事にする。 31146 31147 * test を実行する時に version を表示したい。 31148 表示する様に変更した。 31149 31150 2020-04-19 31151 31152 * 後、READLINE_MARK に対応したがちゃんと範囲チェックを忘れていないか確認する [#D1339] 31153 →確認した所、これについては READLINE_POINT ですらチェックしていなかった。 31154 チェックする様に修正した。 31155 31156 * PROMPT_COMMANDS の判定を declare -p で行っているが、 [#D1338] 31157 これだと "配列として宣言したが unset である" という状況で 31158 PROMPT_COMMAND に fallback しないという問題があるのではないか。 31159 というより bash ではどの様に振る舞っているか確認する必要がある。 31160 →bash-dev で振る舞いを確認した所、配列要素が 1 つ以上あるかどうかで決まっている様だ。 31161 31162 →然し bash-3.2 以下では declare a123 としただけで要素が 1 になってしまう。 31163 という事を考えると set/unset も一緒に使って判定するのが良い? 31164 と思ったが a123[1]=hello 等の時に判定できなくなってしまう。 31165 或いは declare a123 は a123=('') と等価なのだからその様に取り扱うというので良い気もする。 31166 というか本質的に declare a123 は declare a123= と等価なので区別してはならない。OK 31167 31168 * ble-stackdump の開始フレームがずれている [#D1337] 31169 ble/util/stackdump という内部実装に分けた為である。 31170 分ける必要があっただろうか。或いは、開始フレームを外から変更できる様にする? 31171 後、BASH_LINENO の参照を誤っている。取り敢えず修正した。 31172 31173 * syntax: 変数展開で bash-5.1 で UuLK という operator が追加されている [#D1336] 31174 というより、bash-4.3 では operator は無効にするべきでは。 31175 →確かめてみた所ちゃんとその様な実装になっていた。 31176 31177 2020-04-16 31178 31179 * fzf で複数行モードに入ってしまうという報告 (reported by Brendonk13) [#D1335] 31180 https://github.com/akinomyoga/ble.sh/issues/49 31181 31182 もっと再現を簡単になるまで絞ってから報告して欲しい。 31183 fzf を入れた。再現しない。bfs を今度は入れる必要がある。 31184 或いは find でも再現するかどうか事前に確かめるべきなのではないか。 31185 というか FZF_ALT_C_COMMAND の中に tr -d だとか C-j だとか記入している時点でおかしい。 31186 確認してみると始めての issue 報告という事である。初心者である。 31187 初めての issue 報告をする人というのは結構いるようである。 31188 31189 bfs を入れようとしたがコンパイルできない。 31190 README を参照したが各 distribution のパッケージが並んでいるだけで 31191 実際のコンパイル方法は make しか書かれていない。 31192 必要なライブラリが -lacl -lcap -lattr である。 31193 検索すると libacl libcap libattr で入りそうである。 31194 駄目だった。全て元から入っていた。 31195 sudo dnf install lib{acl,cap,attr}-devel としたら入った。 31196 31197 取り敢えず動作は確認した。然し問題は発生していない。 31198 どうやらディレクトリ名を選択させて cd を実行する様だ。 31199 予想できるのは fzf は "cd ディレクトリ名" を入力して 31200 続いて決定を押しているのだろうという事。 31201 というか、これは bfs は関係ないのでは。 31202 31203 さて、現在再現しないのは ble.sh に特別に調整した 31204 key-binding を実行しているからである。 31205 普通の fzf の bind でどう動作するのか確認する必要がある。 31206 うーん。fzf の設定 .fzf.bash を dotfiles に追加してしまうか。 31207 或いは ble.sh のディレクトリに追加してしまうというのも手である。 31208 何しろ ble.sh の対応の為に追加した物なのだから。 31209 31210 →特別の調整を外したら再現した。絞り込みに入る。 31211 先ず bfs を外す。bfs の設定がなくても再現した。 31212 fzf の key-bindings.bash を確認すると以下の様になっている。 31213 確かに C-m の後に沢山の文字列が設定されている。 31214 恐らくこれは編集文字列とカーソル位置を保存して 31215 それからカーソル位置を復元する為の物であろう。 31216 bind -m emacs-standard '"\ec": " \C-b\C-k \C-u`__fzf_cd__`\e\C-e\er\C-m\C-y\C-h\e \C-y\ey\C-x\C-x\C-d"' 31217 31218 31219 [contrib を整備する] 31220 31221 うーん。毎回この様に説明を書くのは面倒である。 31222 31223 a reject: 一つの方法は fzf に修正を入れてもらうという事。 31224 然し、こちらは 115 star の小さなライブラリである。 31225 一方であちらは 28.5k star の巨大なリポジトリである。 31226 このような小さなライブラリの要求をいちいち飲んでいたら大変である。 31227 という訳でどう考えても PR を出しても対応してくれるとは思えない。 31228 幾らインターフェイスが綺麗だとしても。 31229 31230 もし可能性があるとしたら key-bindings.blesh 等のようなファイルを作るのが良いか。 31231 然し、そうすると同じ bash でも .fzf.bash と .fzf.blesh を使い分ける必要が出てくる。 31232 それよりは key-bindings.bash の中で自動的に振り分ける方が良いのではないか。 31233 31234 b もう一つの方法は ble.sh で ble-import -d lib/fzf-key-bindings とできる様にする事。 31235 この方法の問題点は fzf の場所を事前に指定する必要があるという事。 31236 一番簡単なのは .fzf.bash を source するという事。 31237 然しそうすると結局 fzf の変な key-bindings が登録されてしまう。 31238 31239 或いは "fzf" だけインストールしてもらって、 31240 fzf のパスから辿るという方法。これはユーザに特別の指定をしてもらう必要がある。 31241 31242 c reject: 或いは .fzf.bash -> fzf/shell/key-bindings.bash を検出して、 31243 その中で実行される bind は自動的に無効にして、 31244 代わりに blesh の特別の binding をその場で実行するという方針? 31245 31246 これは何が問題かというといざユーザが key-bindings.bash を編集しても反映されないという事。 31247 更にユーザが何が起こっているのか理解するのに時間がかかるという事。 31248 というか何が起こっているのかを解明するのは物凄く難しいという気がする。 31249 これはかなり大変な書き換えである。 31250 31251 d 或いは、.fzf.bash の中で source "..." となっている部分を自分で書き換えてもらう。 31252 然し、沢山設定を書くのは面倒なので設定に関しては以下のファイルを用意する。 31253 31254 lib/fzf-key-bindings.sh 31255 lib/fzf-completions.sh 31256 lib/fzf-git.sh 31257 31258 まあ、これぐらいが妥当な気がする。然し、問題はどうやって _fzf_base を伝えるかという事。 31259 .fzf.bash にこれを設定する項目はあるだろうか→うーん。無いような気がする。 31260 結局何かは source しなければならない。まあ、自分で source すれば良いという気がする。 31261 31262 うーん。contrib というディレクトリでも作る事にしようか。 31263 或いは、blesh-contrib というリポジトリを作る事にする? 31264 そうした方が他の人が設定を追加しやすくなるという気がするのである。 31265 contrib の中に theme 等のサブディレクトリを更に作る? 31266 或いは単に contrib/theme-*.sh 等の様にするか。 31267 その方が良い気がする。 31268 blesh-contrib というリポジトリを作成する事に決めた。 31269 31270 * 作成した設定をテストする。 31271 31272 * ble.sh からどの様にリンクするのが良いだろうか。 31273 31274 # さて、問題はどの様に git submodule を追加するかという事。 31275 # 相対パスで設定できるという話だった気がする。 31276 # うーん。該当する記事が見つからないが試してみる事にする。 31277 # と思ったら空の repository は追加できないそうだ。 31278 # 仕方がないので取り敢えず簡単な内容で作成する。 31279 31280 submodule contrib を使う? 31281 というより他に思い浮かばない。 31282 或いは、別 repository として管理するのは OK としても 31283 明示的に link はしないという様にする? 31284 だとしても結局何処かで download しなければならないのだから、 31285 submodule を使ってしまっても問題ないという気がするのである。 31286 31287 x ok: submodule を使った時の問題は同期が面倒という事。 31288 然し、install 先に直接 repository を作成するとしても同期が面倒なのは変わりない。 31289 寧ろその方が ble-update 等の処理が複雑になって面倒である。 31290 という事を考えると、やはり中で submodule を管理するのが良い。 31291 31292 * submodule の同期をする必要があるという観点に関しては、 31293 contrib/.git が存在しない時には 31294 git submodule update --init --recursive を make の中で呼び出せば良い。 31295 ble-update に対してもこれを実行する。 31296 31297 * done: 試しに相対パスでもちゃんと GitHub から同期できるか確認した。 31298 →できた。これで大丈夫。 31299 31300 * done: Makefile の設定も行った。 31301 2回実行しなければならない気がするが、まあ大丈夫だろう。 31302 と思ったが make して out/ble.sh を source している場合は微妙。 31303 31304 * done: ble-update で更新する様にする。これは pull --recursive で良いのでは。 31305 と思ったが実際にそういう物はあるのだろうか。 31306 $ git pull --recurse-submodules という物があるらしいが、 31307 これを実行すると .gitmodules を書き換えて最新の物に更新してしまうらしい。 31308 という事で必要なのは以下のコマンドの様である。 31309 $ git submodule update --recursive --remote 31310 --remote の意味はよく分からない。うーん。--help で観察すると、 31311 sha1 hash ではなくて branch に基づいて同期する様である。 31312 考え直してみるとその方が都合が良い。という訳で取り敢えずこれを使う事にする。 31313 不整合が起こるのではないかという心配もあるが、まあ使ってみて問題が起こってから考える。 31314 31315 * done: 次に追加した fzf-*.sh がちゃんと動くかをテストする必要がある。 31316 動作確認した。 31317 31318 * done: 次は contrib の README に説明を書く事にする。説明を書いた。 31319 31320 * resize で hang するとの事 (reported by killermoehre) [#D1334] 31321 https://github.com/akinomyoga/ble.sh/issues/48 31322 31323 PS1 について尋ねたら以下の結果になった。 31324 31325 > ^A^[]133;D;0^G^B^A^[]0;cXXXXXXX@apfelkuchen:~^G^B^A^[]133;A^G^B$ ^A^[]133;B^G^B 31326 31327 これは以下の設定に対応する。 31328 31329 PS1='\[\e]133;D;0\a\]\[\e]0;cXXXXXXX@apfelkuchen:~\a\]\[\e]133;A\a\]$ \[\e]133;B\a\]' 31330 31331 | Additional questions. 31332 | 31333 | **Question 3**: Does the problem reproduce with `PROMPT_COMMAND=''`? 31334 | For example, please add the line `PROMPT_COMMAND=` before the line of 31335 | `ble-attach` in `.bashrc` as follows: 31336 | 31337 | ```bash 31338 | # bashrc 31339 | 31340 | [[ $- == *i* ]] && source /path/to/blesh/ble.sh --noattach 31341 | 31342 | # ... 31343 | 31344 | PROMPT_COMMAND= # <-- This line 31345 | ((_ble_bash)) && ble-attach 31346 | ``` 31347 | 31348 | **Question 4**: Does the problem reproduce with `source ble.sh` in 31349 | interactive sessions? To try this, please follow the following steps: 31350 | 31351 | 1. Open terminal 31352 | 2. Type the following commands 31353 | 31354 | ```bash 31355 | $ bash --norc 31356 | $ PS1='\$ ' 31357 | $ PROMPT_COMMAND= 31358 | $ source /path/to/ble.sh 31359 | ``` 31360 | 31361 | 3. Resize before input anything 31362 | 31363 | 31364 | --attach=attach 31365 | 31366 | $ trap 'ble-stackdump > /dev/tty' USR1 31367 31368 31369 再現できたので原因を解明する。 31370 結局、read -r aaa bbb を builtin read -r aaa bbb に変更したら動く様になった。 31371 或いは以下の変更で治る。おかしい。これは bash のバグなのではあるまいか。 31372 31373 | +++ b/src/edit.sh 31374 | @@ -6998,8 +6998,8 @@ function ble/builtin/read { 31375 | [[ $__ble_command ]] || return "$__ble_ext" 31376 | 31377 | # 局所変数により被覆されないように外側で評価 31378 | - builtin eval -- "$__ble_command" 31379 | - return 31380 | + builtin eval -- "$__ble_command"; local ext=$? 31381 | + return "$ext" 31382 | } 31383 | function read { ble/builtin/read "$@"; } 31384 31385 return "$ext" の代わりに 'ble/util/setexit "$ext"; return' としても問題が発生する。 31386 %または return を完全に削除しても問題が発生する 31387 →勘違いだった。return を実行した場合には問題は発生しない。 31388 他の version でも発生するのかを確かめてみた。 31389 31390 [Bash 用最小再現コード] 31391 31392 Bash のバグの可能性があるので Bash だけで再現できるか試みる。 31393 31394 | bash-4.4 でも再現する。 31395 | 31396 | * bash-4.3 だと別のエラーが発生する。 31397 | このエラーは iterm2 を読み込まない場合には発生していない気がする。 31398 | 31399 | $ bash-4.3: history: 書き込みエラー: Broken pipe 31400 | bash-4.3: history: 書き込みエラー: Broken pipe 31401 | Segmentation fault (コアダンプ) 31402 | 31403 | うーん。これは何だろうか。iterm2 の読み込みと関係がある? 31404 | 不思議である。history がどう関係してくるのか謎である。 31405 | 一応 __bp_preexec_invoke_exec が history を内部で呼び出している様だが、 31406 | 実際にこれが問題の原因なのかどうかについては不明である。 31407 | 31408 | * bash-4.2 では問題は発生しない。 31409 | bash-4.0 でも問題は発生しない。 31410 | 31411 | * ok: bash-3.2 だと変なエラーが発生して無限ループする。 31412 | これは precmd の問題の気がする。 31413 | 31414 | | bash-3.2: branch.ab: syntax error: invalid arithmetic operator (error token is ".ab") 31415 | | bash-3.2: branch.ab: syntax error: invalid arithmetic operator (error token is ".ab") 31416 | | bash-3.2: branch.ab: syntax error: invalid arithmetic operator (error token is ".ab") 31417 | | 31418 | | stackdump は以下の通り 31419 | | @ iterm2_shell_integration_local.sh:13 (iterm2_print_user_vars) 31420 | | @ iterm2_shell_integration.sh:374 (iterm2_print_state_data) 31421 | | @ iterm2_shell_integration.sh:-8 (__iterm2_precmd) 31422 | | @ iterm2_shell_integration.sh:-471 (__bp_precmd_invoke_cmd) 31423 | | ... 31424 | | @ iterm2_shell_integration_local.sh:13 (iterm2_print_user_vars) 31425 | | @ iterm2_shell_integration.sh:374 (iterm2_print_state_data) 31426 | | @ iterm2_shell_integration.sh:-8 (__iterm2_precmd) 31427 | | @ iterm2_shell_integration.sh:-471 (__bp_precmd_invoke_cmd) 31428 | | @ iterm2_shell_integration.sh:-16230 (__bp_install) 31429 | | @ /home/murase/.local/share/blesh/ble.sh:7 (ble-edit/prompt/update/.eval-prompt_command.1) 31430 | | @ /home/murase/.local/share/blesh/ble.sh:-429 (ble-edit/prompt/update/.eval-prompt_command) 31431 | | @ /home/murase/.local/share/blesh/ble.sh:33 (ble-edit/prompt/update) 31432 | | @ /home/murase/.local/share/blesh/ble.sh:308 (ble/textarea#render) 31433 | | @ /home/murase/.local/share/blesh/ble.sh:14091 (ble/textarea#redraw) 31434 | | @ /home/murase/.local/share/blesh/ble.sh:3 (ble-attach) 31435 | | @ zzz-attach-ble.sh:28 (source) 31436 | | @ .bashrc:0 (source) 31437 | 31438 | iterm2_print_user_vars の中を調べると確かに branch.ab という文字列が使われている。 31439 | 連想配列は bash 3.2 で存在しないのでそれが原因で問題が起きているのだろう。 31440 | 然し、__bp_precmd_invoke_cmd は呼び出されていない。 31441 | よく考えたら bp_precmd は trap DEBUG を使っている。 31442 | つまり、branch.ab によって構文エラーが発生して DEBUG か何かが発生し、 31443 | その結果として無限ループが発生しているという事だろうか。 31444 | まあ、bash3.2 に関しては考えない事にする。 31445 | 31446 | 取り敢えず最小再現を作成する事にする。 31447 | 恐らく WINCH の中では return が思うように動かないという事? 31448 | 31449 | $ function f1 { false; return; }; function f2 { f1; } 31450 | $ trap 'while f1; do echo hello; break; done' WINCH 31451 31452 再現した。最小化する。 31453 31454 $ f1() { false; return; }; trap 'f1; echo exit=$?' WINCH 31455 31456 実は別のシグナルでも問題ないのではないか。 31457 31458 $ f1() { false; return; }; trap 'f1; echo exit=$?' USR1; kill -USR1 0 31459 31460 うーん。もしこれが Bash のバグだとしても、Bash 4.4, 5.0 が世の中に現れてしまった以上は、 31461 これに対する対策を ble.sh の側で実行する必要がある。もしくは、return を上書きするか…。 31462 と思ったが return を関数で上書きすると setexit と同じ意味になってしまって、 31463 元々の return の意味を失ってしまうので駄目である。という訳でやはり return を 31464 修正しなければならないのであった。 31465 31466 取り敢えず行末にある return を全て修正していく事にする。 31467 修正した。これで恐らく全ての return に明示的に終了ステータスが指定されている。 31468 31469 2020-04-14 31470 31471 * 2020-01-23 stackdump [#D1333] 31472 31473 以下の様な内容。再現しない。編集手順を記録する? 後、その場で ble_debug=1 にする機能が欲しい。 31474 31475 | echo 1 2 3 4 5 8 9 10 | ( read numbers; set -- $numbers; i=0 i1=0; for n; do if ((n!=i)); then if ((i==i0)); then echo $i0-$i; ; ((i++)); done ) 31476 | 31477 | ble/syntax/tree-enumerate/.initialize/FATAL1 31478 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:26 (ble/util/assert) 31479 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:4 (ble/syntax/tree-enumerate/.initialize) 31480 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:6 (ble/syntax/tree-enumerate) 31481 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:6 (ble/syntax/parse/shift.method2) 31482 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:19 (ble/syntax/parse/shift) 31483 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:7 (ble/syntax/parse) 31484 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:73 (ble-edit/content/update-syntax) 31485 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:3 (ble/textarea#render) 31486 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:16 (ble-edit/bind/.tail) 31487 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:50 (ble-decode/EPILOGUE) 31488 | 31489 | 取り敢えず f11 で ble_debug を toggle して f12 で編集履歴を出力する様にした @ blerc 31490 | 本質的にはそんなに複雑な構造はしていないのだからすぐに再現しそうな気がしたが再現しない。 31491 | 或いは一時的な物で既に直ってしまった可能性もなくはない。 31492 | echo 1 | ( echo; for n; do if ((n!=i)); then if ((i==i0)); then echo $i0-$i; ; ((i++)); done ) 31493 31494 [再現] 2020-04-14 再現した。 31495 31496 | echo {1..9}|(read numbers;set -- $numbers;i=0;i0=0;for n;do if((n!=i));then echo $i0-$i;i=$n;done) 31497 | 31498 | ble_debug 構造を入手した。然し何処から手をつけたら良いのか分からない。 31499 | 取り敢えず diff を取ってみる事にする。本質的な違いは以下の様になる。 31500 | 31501 | --- D0000.a.expected-1.txt^I2020-04-14 11:57:31.268375794 +0900 31502 | +++ D0000.a.error-1.txt^I2020-04-14 12:01:30.567636568 +0900 31503 | @@ -86,24 +86,21 @@ 31504 | 14 a 083 '$' || stat=(ARGX w=- n=@14 t=$82:$11) 31505 | 7 a 084 'i' || 31506 | | a 085 '0' || 31507 | - 4 a 086 '-' || stat=(ARGI w=ARGX:83- n=@14 t=-:$82) 31508 | -14 a 087 '$' || stat=(ARGI w=ARGX:83- n=@14 t=-:$82) 31509 | + 4 a 086 '-' || stat=(ARGI w=ARGX:83- n=@24 t=-:$82) 31510 | +14 a 087 '$' || stat=(ARGI w=ARGX:83- n=@24 t=-:$82) 31511 | 7 a 088 'i' |+ word=ARGI:@81>83-89/(wattr=d) 31512 | -12 a 089 ';' | stat=(ARGX w=- n=@14 t=$89:$11) 31513 | - 7 a 090 'i' || stat=(CMDX w=- n=@14 t=$89:$11) 31514 | +12 a 089 ';' | stat=(ARGX w=- n=@24 t=$89:$24) 31515 | + 7 a 090 'i' || stat=(CMDX w=- n=@24 t=$89:$24) 31516 | 8 a 091 '=' || 31517 | -14 a 092 '$' || stat=(VRHS w=_ble_attr_VAR:90- n=@14 t=-:$89) 31518 | +14 a 092 '$' || stat=(VRHS w=_ble_attr_VAR:90- n=@24 t=-:$89) 31519 | 26 a 093 'n' |+ word=_ble_attr_VAR:@88>90-94/(wattr=m2:d,$:d) 31520 | -12 a 094 ';' | stat=(CMDXV w=- n=@14 t=$94:$11) 31521 | -19 a 095 'd' || stat=(CMDX w=- n=@14 t=$94:$11) 31522 | +12 a 094 ';' | stat=(CMDXV w=- n=@24 t=$94:$24) 31523 | +19 a 095 'd' || stat=(CMDX w=- n=@24 t=$94:$24) 31524 | | a 096 'o' || 31525 | | a 097 'n' || 31526 | | a 098 'e' |+ word=CMDI:@93>95-99/(wattr=d) 31527 | -12 a 099 ')' + word="(":@10>14-100>@98 stat=(CMDXE w=- n=@14 t=$99:$11) 31528 | - | s 100 ^@ stat=(CMDXE w=- n=- t=$100:-) 31529 | + 6 a e 099 ')' stat=(CMDXE w=- n=@24 t=$99:$24) 31530 | + | 100 ^@ stat=(CMDXE w=- n=@24 t=$99:$24) 31531 | 31532 | 確認すると $i0-$i の - の時点で nest の座標がずれている。 31533 | どうも read numbers; set -- は関係ない気がする。 31534 | 編集履歴を dump する機能はあっただろうか。 31535 | この通りに編集したら再現するかどうかを先ず確認する必要がある。 31536 | 31537 | 13:echo {1..9} | 31538 | 16:echo {1..9} | () 31539 | 22:echo {1..9} | (read --) 31540 | 21:echo {1..9} | (read -) 31541 | 20:echo {1..9} | (read ) 31542 | 45:echo {1..9} | (read numbers; set -- $numbers;) 31543 | 28:echo {1..9} | (read numbers;set -- $numbers;) 31544 | 57:echo {1..9} | (read numbers;set -- $numbers;for n;do done) 31545 | 54:echo {1..9} | (read numbers;set -- $numbers;for n;do ;done) 31546 | 58:echo {1..9} | (read numbers;set -- $numbers;for n;do echo ;done) 31547 | 48:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do echo ;done) 31548 | 57:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do cho ;done) 31549 | 57:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do ho ;done) 31550 | 57:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do o ;done) 31551 | 57:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do ;done) 31552 | 74:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==0));then\;done) 31553 | 73:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==0));then;done) 31554 | 72:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==0));the;done) 31555 | 71:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==0));th;done) 31556 | 70:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==0));t;done) 31557 | 69:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==0));;done) 31558 | 68:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==0));done) 31559 | 67:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==0);done) 31560 | 66:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==0;done) 31561 | 65:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==;done) 31562 | 69:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==n));;done) 31563 | 68:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==n));done) 31564 | 67:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==n);done) 31565 | 66:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==n;done) 31566 | 65:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i==;done) 31567 | 64:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i=;done) 31568 | 63:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((i;done) 31569 | 62:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ((;done) 31570 | 61:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if (;done) 31571 | 60:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if ;done) 31572 | 59:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if;done) 31573 | 63:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if(());done) 31574 | 65:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if((n==i));done) 31575 | 62:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if((n=i));done) 31576 | 63:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if((n!=i));done) 31577 | 80:echo {1..9} | (read numbers;set -- $numbers;i=0;for n;do if((n!=i));echo $i0-$i;done) 31578 | 53:echo {1..9} | (read numbers;set -- $numbers;i=0;i0=0;for n;do if((n!=i));echo $i0-$i;done) 31579 | 78:echo {1..9} | (read numbers;set -- $numbers;i=0;i0=0;for n;do if((n!=i));then echo $i0-$i;done) 31580 | 94:echo {1..9} | (read numbers;set -- $numbers;i=0;i0=0;for n;do if((n!=i));then echo $i0-$i;i=$n;done) 31581 | 56:echo {1..9} | (read numbers;set -- $numbers;i=0;i0=0;for if((n!=i));then echo $i0-$i;i=$n;done) 31582 | 31583 | 駄目だ。再現しない。微妙な操作の違いですぐに再現しなくなるという事か、 31584 | 或いは、より前の履歴編集によって種が仕込まれている必要があるのか、 31585 | もっと別の際限条件が存在するのか。文字列の挿入位置にも関係がありそう。 31586 | また、paste 等を実行すると incremental な解析にならずに一気に解析するので問題が起こらないという可能性も。 31587 | 31588 | 直感としては read/set の部分は関係ない気がする。for の辺りが怪しい。 31589 | 再現できた。だいぶ短くできた気がする。これは実は最初の :| も関係ないのでは。 31590 | 内部で ;; が発生すると起こる問題ではないだろうか。 31591 | 31592 | 4::|() 31593 | 18::|(:;for n;do done) 31594 | 15::|(:;for n;do ;done) 31595 | 9::|(:;i=0;for n;do ;done) 31596 | 34::|(:;i=0;for n;do if((i==0));then\;done) 31597 | 33::|(:;i=0;for n;do if((i==0));then;done) 31598 | 32::|(:;i=0;for n;do if((i==0));the;done) 31599 | 31::|(:;i=0;for n;do if((i==0));th;done) 31600 | 30::|(:;i=0;for n;do if((i==0));t;done) 31601 | 29::|(:;i=0;for n;do if((i==0));;done) 31602 | 28::|(:;i=0;for n;do if((i==0));done) 31603 | 27::|(:;i=0;for n;do if((i==0);done) 31604 | 26::|(:;i=0;for n;do if((i==0;done) 31605 | 25::|(:;i=0;for n;do if((i==;done) 31606 | 24::|(:;i=0;for n;do if((i=;done) 31607 | 23::|(:;i=0;for n;do if((i;done) 31608 | 22::|(:;i=0;for n;do if((;done) 31609 | 28::|(:;i=0;for n;do if((n!=i));done) 31610 | 41::|(:;i=0;for n;do if((n!=i));echo $i0-$i;done) 31611 | 14::|(:;i=0;i0=0;for n;do if((n!=i));echo $i0-$i;done) 31612 | 39::|(:;i=0;i0=0;for n;do if((n!=i));then echo $i0-$i;done) 31613 | 55::|(:;i=0;i0=0;for n;do if((n!=i));then echo $i0-$i;i=$n;done) 31614 | 31615 | 短縮した。 31616 | 31617 | 2:() 31618 | 16:(:;for n;do done) 31619 | 12:(:;for n;do;done) 31620 | 7:(:;i=0;for n;do;done) 31621 | 34:(:;i=0;for n;do if((i));echo $i-$j;done) 31622 | 11:(:;i=0;i=1;for n;do if((i));echo $i-$j;done) 31623 | 33:(:;i=0;i=1;for n;do if((i));then echo $i-$j;done) 31624 | 45:(:;i=0;i=1;for n;do if((i));then echo $i-$j;i;done) 31625 | 31626 | 実は直前の状態まで大丈夫だったのではないか? 31627 | と思って試してみたが駄目だった。やはり編集履歴が必要。 31628 | 2つ前から始めたら再現した。 31629 | 31630 | 44:(:;i=0;i=1;for n;do if((i));echo $i-$j;done) 31631 | 33:(:;i=0;i=1;for n;do if((i));then echo $i-$j;done) 31632 | 45:(:;i=0;i=1;for n;do if((i));then echo $i-$j;i;done) 31633 | 31634 | 初期状態を少しずつ小さくしてみる。 31635 | 31636 | (:;for n;do if((i));echo $i-$j;done) 再現する 31637 | (:;for n;do if((i));echo;done) 再現しない 31638 | (:;for n;do if((i));: $i;done) 再現しない 31639 | (:;for n;do if((i));: $i-$j;done) 再現する 31640 | (for n;do if((i));: $i-;done) 再現する 31641 | (if((i));: $i-;:) 再現する 31642 | (:;$i-;:) 再現しない 31643 | (:;: $i-;:) 再現する 31644 | 31645 | 結局以下で発生するという所までは突き止めた。 31646 | 31647 | 11:(:;: $i-;:) 31648 | 8:(:;then : $i-;:) 31649 | 14:(:;then : $i-;;:) 31650 | 31651 | (: $i-;:) でも再現する。更に then でなくても良い様だ。 31652 | 31653 | 9:(: $i-;:) 31654 | 6:(echo : $i-;:) 31655 | 13:(echo : $i-;i;:) 31656 31657 更に (:: $i-;:) から始めても再現する。 31658 最初の空白挿入操作で既に変な状態になっていると考えられる。 31659 31660 10:(:: $i-;:) 31661 3:(: : $i-;:) 31662 10:(: : $i-;i;:) 31663 31664 初期状態 31665 _ble_syntax_attr/tree/nest/stat? 31666 12*a 000 '(' | nest=(CMDXE w=- n=- t=-:-) stat=(CMDX w=- n=- t=-:-) 31667 2*aw 001 ':' || stat=(CMDX1 w=- n=@0 t=-:-) 31668 2*aw 002 ':' |+ word=CMDI:1-3/(wattr=216173653992204032) stat=(CMDI w=CMDX1:1- n=@0 t=-:-) 31669 3*a 003 ' ' | 31670 14*a 004 '$' || stat=(ARGX w=- n=@0 t=$3:-) 31671 7*a 005 'i' || 31672 4*a 006 '-' |+ word=ARGI:@2>4-7/(wattr=d) stat=(ARGI w=ARGX:4- n=@0 t=-:$3) 31673 12*a 007 ';' | stat=(ARGX w=- n=@0 t=$7:-) 31674 2*aw 008 ':' |+ word=CMDI:@6>8-9/(wattr=72057594037930241) stat=(CMDX w=- n=@0 t=$7:-) 31675 12*a 009 ')' + word="(":0-10>@8 stat=(ARGX w=- n=@0 t=$9:-) 31676 | s 010 ^@ stat=(CMDXE w=- n=- t=$10:-) 31677 31678 31679 空白挿入後の状態 (yが正しい状態でxが異常になった状態) 31680 --- D0000.b.y.txt^I2020-04-14 12:58:01.259916873 +0900 31681 +++ D0000.b.x.txt^I2020-04-14 12:56:49.470879943 +0900 31682 @@ -2,12 +2,12 @@ 31683 12 a 000 '(' | nest=(CMDXE w=- n=- t=-:-) stat=(CMDX w=- n=- t=-:-) 31684 2 aw 001 ':' |+ word=CMDI:1-2/(wattr=72057594037930241) stat=(CMDX1 w=- n=@0 t=-:-) 31685 3 a 002 ' ' | 31686 - 4 a 003 ':' |+ word=ARGI:@1>3-4/(wattr=m1:d,$:d) stat=(ARGX w=- n=@0 t=$2:-) 31687 - 3 a 004 ' ' | stat=(ARGX w=- n=@0 t=$4:-) 31688 -14 a 005 '$' || stat=(ARGX w=- n=@0 t=$4:-) 31689 + 4 a s 003 ':' |+ word=ARGI:@1>3-4/(wattr=m1:d,$:d) stat=(ARGX w=- n=@0 t=$2:-) 31690 + 3 a s 004 ' ' | stat=(ARGX w=- n=@0 t=$4:-) 31691 +14 a s 005 '$' || stat=(ARGX w=- n=@0 t=$4:-) 31692 7 a 006 'i' || 31693 - 4 a 007 '-' |+ word=ARGI:@3>5-8/(wattr=d) stat=(ARGI w=ARGX:5- n=@0 t=-:$4) 31694 -12 a 008 ';' | stat=(ARGX w=- n=@0 t=$8:-) 31695 - 2 aw 009 ':' |+ word=CMDI:@7>9-10/(wattr=72057594037930241) stat=(CMDX w=- n=@0 t=$8:-) 31696 -12 a 010 ')' + word="(":0-11>@9 stat=(ARGX w=- n=@0 t=$10:-) 31697 + 4 a 007 '-' |+ word=ARGI:@3>5-8/(wattr=d) stat=(ARGI w=ARGX:5- n=@1 t=-:$4) 31698 +12 a s 008 ';' | stat=(ARGX w=- n=@0 t=$8:-) 31699 + 2 aw s 009 ':' |+ word=CMDI:@7>9-10/(wattr=72057594037930241) stat=(CMDX w=- n=@0 t=$8:-) 31700 +12 a s 010 ')' + word="(":0-11>@9 stat=(ARGX w=- n=@0 t=$10:-) 31701 | s 011 ^@ stat=(CMDXE w=- n=- t=$11:-) 31702 31703 31704 [原因] 31705 31706 | 更新範囲を見てみると ": : " の4文字だけなので、 31707 | これは shift の失敗によって起こっている不整合である。 31708 | では何故 shift に失敗するのか。shift のバグは流石にもうないと思っていたのに。 31709 | 而も、shift が起こる条件が良くわからない。他の場合には起こっていなかった筈である。 31710 | 不思議なのはその他の nest の shift はちゃんとできているという事。 31711 | "-" に設置されている stat の nest だけ shift できていない。 31712 | 31713 | shift.stat を観察してみた。ここで stat の中にある nlen を更新している。 31714 | 然し、何か変である。というか shift を実行する前から既に shift 済みの気がする。 31715 | 一体どういう事だろうか。或いは j=7 というのは shift 前のインデックスという事か。 31716 | だとすると j=6 に対して shift.stat が呼び出されていないという事になる。 31717 | j=7:nlen=7:beg=2:end0=2:shift=1 31718 | 31719 | →確認してみた所配列の再配置は shift の後だった。つまり j は shift 前の位置である。 31720 | そして shift.stat が呼び出されていないという事なのだろうと思われる。 31721 | というのも shift.stat は全体に対して実行しているのではなくて、 31722 | 必要のありそうな物を tree-enumerate で列挙するという形になっている様だから。 31723 | 31724 | * shift.method2 の実装に関する記録を探す。 31725 | 要するにこの shift.method2 が悪いというのは明らかであるが、 31726 | そもそも何故この様な複雑な事をしているのだったか。 31727 | done.txt を method2 で検索しても見つからない。 31728 | blame を確認すると e74c1163 と書かれている。 31729 | 日付は 2016-04-07 になっている。#D0321 に議論が残っている。 31730 | 結構複雑な変更だったのだろうか。議論がごちゃごちゃとしていて分からない。 31731 | どうも tplen と tclen に関しては単語内部に対する探索を実行しているが、 31732 | nlen に対しては何らかの仮定の下にスキップを行っている。 31733 | そしてその仮定が崩れているのではないかというのが今回の問題点。 31734 | 31735 | また別の shift.impl2 に関する議論は #D0223 にある。 31736 | 然し、こちらは単純なバグ修正なので深い事は何も書かれていない。 31737 | 31738 | 結局見つからない。結局改めて何が行われているかコードを読まなければない。 31739 | 31740 | shift として何が必要かについて考える。 31741 | wlen, nlen, tplen, tclen 等は全て相対位置で記録しているので、 31742 | 基本的には shift は必要ないはずである。shift が必要になるのは、 31743 | wlen, nlen, tplen, tclen が変更領域に跨っている場合と考えられる。 31744 | shift 対象としては stat / tree / nest の3種類がある。 31745 | 31746 | shift.stat では stat 内の情報と beg/end0 の情報だけで更新している。 31747 | 変更領域を超えた参照についてはそのまま shift して、 31748 | 変更領域内部 (inclusive) に対する参照については消滅した物として、 31749 | 参照点を変更領域末端まで移動する。 31750 | shift.tree も実質同様である。shift.nest も同様であった。 31751 | 31752 | shift.stat, nest に関しては j2 まで全て呼び出す形になっている? 31753 | 但し、変更領域の後の nest の内部にある物に関してはスキップできる。 31754 | 何故ならば参照はその中で閉じている筈だから。 31755 | 31756 | * 或いは最近の TE_nofs に関係する修正でバグが埋め込まれた可能性もあるだろうか? 31757 | TE_nofs etc の様に変数名を書き換えたのは 9cb35832 である。 31758 | 試しに 9cb35832~ を checkout して見たが同じ問題が発生している。 31759 | v0.2-master でも発生した。v0.1-master では発生していない気がする。 31760 | どうやら #D0321 の e74c1163 の段階では発生していなかった様である。 31761 | 31762 | 犯人は分かった 035ad68 この commit で問題が発生する様になっている。 31763 | 2017-02-25 の事である。#D0364 が該当する項目である。 31764 | さて、実際に修正した内容を確認すると…。うーん。 31765 | _shift2_j=j の位置を変更しただけである。 31766 | という事は元からあったバグがこれで発現しただけという事なのだろうか。 31767 31768 但し単語内部の場合には外側の nest に対して参照がある可能性がある。 31769 そう考えるとスキップできる tree というのは nest に限られるのでは。 31770 →やはりこれが悪い様に思われる。 31771 31772 取り敢えず、スキップするのは nest の時だけにする事にした。問題は発生しなくなった。 31773 31774 ? 単語ごとに nest を設置しないのは何故か。 31775 というよりそもそも何故 nest を単語の時に更新していなかったのか。 31776 31777 * nest を辿る事によって文法の解釈を変えたりという事に nest を使っている。 31778 然しこれは主に単語の内部での解釈についてなので 31779 実は単語ごとに nest を作っても大した影響はないのではないか。 31780 →nest-type を呼び出している箇所を確認したが、 31781 やはり単語でも nest を作る様にして問題は発生しない様に感じる。 31782 * また解析状態一致の判定にも使っている。実は解析状態一致の判定に関しては、 31783 寧ろ単語ごとに nest を作った方が都合が良いのかもしれない。 31784 * そもそも "単語" という概念と "nest" という概念を独立に管理する必要はあるのだったか。 31785 解析状態に wlen と nlen の両方があるがその必要は本当にあったのだろうか。 31786 * 解析状態の一致判定に時間がかかる様になるかもしれない。 31787 というのも一致を判定する為に毎回 nest 配列の中身を辿る必要が出てくるから。 31788 単語に対しても nest を作る様にしてしまうと毎回辿る nest が多くなってしまう。 31789 31790 始めから再設計するのだとしたら nlen と wlen は統合した気がするが、 31791 現在の実装でそうなっている以上は敢えて変える必要もないように感じている。 31792 wlen/nlen をくっつけると多少効率が下がるかもしれないし、 31793 また解析器の部分を全体的に書き換えなければならなくなる可能性がある。 31794 別に其処までしなくても良いという様に感じている。 31795 31796 31797 ? 単語の場合でもその文脈に於ける nest が空であればスキップできるのではないか。 31798 * tree 構造に nlen は記録していただろうか。ble_debug で観察すると記録していない気がする。 31799 実際に確認したが記録はしていない様だ。単語の場合には wlen を nest の場合には nlen を記録している。 31800 つまり、単語の場合に外側の nlen を記録するという事はしていないのである。 31801 寧ろ、nlen は stat の側にしか記録していない。 31802 31803 或いは単語と同じ位置に記録してある stat の中にある nlen を参照するという手もある。 31804 然し、単語の終端に必ず stat が設置されているかどうかは非自明である、 31805 少なくともそういう要求を意識して実装はしていない。 31806 見た感じは一致している様にも見えるが際どい。 31807 31808 * 然し、よく考えてみればこれでスキップできる様にしたとしても、 31809 結局 $() 等の構造の内部では余り意味がない。 31810 結局 ${} 等の nest を作る構造単位で飛ばすという処理だけでしか 31811 本質的には高速にする事ができない。 31812 その様に考えると単語の時にわざわざ nest が空かどうかを判定しても仕方がない気がする。 31813 一方で、設計の綺麗さよりも効率を考えるのであれば、やはりトップレベルで沢山コマンドを 31814 入力する場合が大半であるから、そう考えると nest をチェックしても良い。 31815 31816 色々考えると、単語の場合に nest の情報を無理して取得してスキップをするのは 31817 現在の実装を考えると余り綺麗ではない上にそんなに効率化する訳でもない気がする。 31818 という事から対応しない事にする。 31819 スキップはネストの時にだけ行う事とする。 31820 31821 * edit: set +H としても次のコマンドの実行の時には履歴展開が有効になってしまう [#D1332] 31822 set -H についても記録・復元するべきである。 31823 31824 というよりもそもそも何故 set -H が設定されているのだったか。 31825 D0110 によるとそもそも履歴展開が実行されないということの様だ。 31826 確かに自前で history -p を呼び出して履歴展開を実行している。 31827 という事は eval では履歴展開は発生しないという事を意味する。 31828 set -H は履歴展開を起こす為に念の為に設定した物であって、 31829 特にいま history -p を使って自前で展開しているので不要である。 31830 単に削除する事にする。 31831 31832 * 棄却 2020-04-02 highlight: hello! () { echo; } として hello! としても関数名着色にならない [#D1331] 31833 と思ったがこれは履歴展開を含む単語は単純単語ではないと判断される為である。 31834 更に、単語の境界が必ず履歴展開の終端とも限らない。 31835 例えば echo hello!; は !; で履歴展開になっている。 31836 従って hello! の部分だけ見て ! が末端にあるからと言って、 31837 それが履歴展開にならないという事は保証できないのである。 31838 これは対応しない。 31839 31840 * syntax: ${#@a} の着色 [#D1330] 31841 どうも $@ に修飾 # とごみ a がついていると解析している気がする。 31842 然し、実際には $# に修飾 @a がついていると解釈するべきである。 31843 他に ${##0} もエラー着色になっている。 31844 これは ${##} に 0 がついているという具合に解釈されている気がするが 31845 実際には $# に #0 という修飾がついているという様に 31846 解釈しなければならないのである。 31847 31848 関連して現在の実装では ${-[@]} の様な物も許容されているが、 31849 これは実際の bash では許容されない組み合わせである。 31850 これらについて正しく判定する事は可能だろうか。 31851 31852 可能な組み合わせについて全て列挙すれば良いのだろうか。 31853 特に一文字特別パラメータについては別に取り扱えば良い気がする。 31854 31855 * 現在の実装では先ず初めに普通の変数名の場合には 31856 ${var} ${!var} ${#var} ${!var@} ${!var[@]} ${var[@]} ${var@flags} 等が存在する。 31857 うーん。整理すると以下の 9 の組み合わせが存在して、 ${#var@} だけが定義されていない。 31858 因みに ${var[0]} 等の場合の取り扱いは ${var} の時と全く同様である。 31859 31860 ${var} ${var[@]} ${var@} ${var[@]@} 31861 ${!var} ${!var[@]} ${!var@} ${!var[@]@} 31862 ${#var} ${#var[@]} ${#var@} ${#var[@]@} 31863 31864 それぞれ以下の意味を持つ。 31865 普通の展開 配列一覧 フラグ 配列フラグ 31866 間接参照 配列キー一覧 変数名 間接参照*2 31867 文字数 配列要素数 <Error> <Error> 31868 31869 *1: 3列目に関してはフラグはなくて良いが4列目に関してはフラグ文字は1文字以上必要? 31870 と思ったがそうではなくて変数が定義されていない場合はフラグがなくても良い。 31871 変数が定義されている場合にはフラグがないとエラーになってしまう。 31872 *2: 何故か全要素を結合した文字列を一つの変数として扱おうとする。 31873 31874 うーん。振る舞いを見ていると @Flag に関しては寧ろ [-+^,?] と同じ取扱の気がする。 31875 特に # の後には続けられないという点はそれに同じである。 31876 但し、${!var@} は特別に取り扱わなければならない。${!var@F} とするとエラーになる。 31877 31878 * またパラメータの場合にはどうなっているだろうか。 31879 試してみると色々の気がする。取り敢えず数字パラメータから調べる。 31880 基本的には普通の変数と同じだが配列添字の形式が存在しない、という事が違う。 31881 31882 ${1} ${1@} 31883 ${!1} ${!1@} 31884 ${#1} ${#1@}=err 31885 31886 * 特殊パラメータの場合はどうか。先ず - や ? の場合にはどうか。 31887 これらは特に迷う事もなく、位置パラメータと同じ取扱の気がする。 31888 31889 * @ や * の場合は何だか良くわからない。 31890 ${@} ... これは位置パラメータ一覧 31891 ${!@} ... これは "\${$*}" と取り扱われる様だ。 31892 ${#@} ... これは $# に等価の様である。 31893 $# に @Flag がついているのかと思いきや ${#*} でも同様に動く。 31894 然し ${#@Q} とすると $# に @Q という動作になる。 31895 ${@@} ... これはちゃんとフラグとして取り扱われる。 31896 ${!@@} ... これも ${!@} に対するフラグになっている様だ。 31897 ${#@@} ... これはエラーである。 31898 31899 * # の場合 31900 $# ... これは位置パラメータの数 31901 ${!#} ... これは $# の間接参照である。つまり "\$$#" という事で最後の引数を取るのに使える。 31902 ${##} ... これは $# の文字数を数えている。 31903 ${#@} ... これは上述の解釈が優先される? そして ${#@Q} だと $# + @Q になる。 31904 ${!#@} ... これはエラーになるが ${!#@Q} は ${!#} + @Q という解釈に為る。 31905 ${##@} ... これはエラーにならない。恐らく $# + #@ という解釈になっている。 31906 31907 * ! の場合 31908 $! ... PID 31909 ${!!} ... これは履歴展開になってしまう。履歴展開を off にするとエラー。 31910 ${#!} ... これは 0 に展開された。どういう事だろうか。 31911 →sleep 1 & してからだとちゃんと有限の値、文字数に展開された。 31912 つまり $! の文字数を数えている。 31913 ${!@} ... (上記) これは $@ の間接参照という取り扱いになっている。 31914 ${!!@} ... これはどうやってもエラーである。 31915 ${#!@} ... これもどうやってもエラーになってしまう。 31916 31917 * 取り扱いを纏めると、パラメータ展開の内容は 31918 31919 (1) 前置詞: !, # 31920 (2) パラメータ名: var var[0] var[@] 1 - @ # ! の何れかに分類できる。 31921 (3) 後置修飾: #... %... //... @... -... +... ?... など色々。 31922 但し、前置詞 # がついている時にはパラメータ名の直後で終了しなければならない。 31923 空白が入る事もない。 31924 31925 * 例外的な形式として ${!var@} という物がある。 31926 これは var@ というパラメータ名という訳でもない。 31927 後置修飾できないし、! の前置修飾という解釈も難しい。 31928 つまり特別に許された形であるという様に解釈できる。 31929 既に現在の実装で特別に取り扱って実装する様になっているのでこれはそのまま。 31930 31931 * 前置詞 # と本体 # と 後置修飾 # は紛らわしいが、 31932 1. 一番はじめの文字が # だった時には ${#ParamName} に一致するか確認。 31933 2. もしその形式で解釈できない時は 1 文字目をパラメータ名として解釈。 31934 という順番で処理されている様に見える。少なくともそうすれば一致する。 31935 31936 ble.sh の実装ではどの様に取り扱うべきか。 31937 取り敢えず、@... に関しては別に取り扱う事にする。 31938 \[ に関しては var の形式のときにだけ許容する様に変更する。 31939 先に ${#param} を試して、それで駄目だった時に ${param...} 及び ${!param...} を試す。 31940 31941 x fixed: ${var@} がエラー着色になっている。 31942 これは空のフラグとして処理されているのだろうか。 31943 →bash 4.3 で駄目で bash 4.4 から許容される様になっているので空のフラグという事である。 31944 31945 実装した。実際に動かして試してみる事にする。 31946 31947 x fixed: ${!var@Q} の着色が異なっている。${!var@} の特別扱いはすぐに } で閉じている時だけでは。 31948 x ${!1} がエラー着色になる。${!-} もエラー着色になる。 31949 - ok: ${#var[@]@Q} は実際にはエラーだが許容している。 31950 - ok: ${!!@} も bash ではエラーだが許容する様になっている。 31951 31952 2020-04-12 31953 31954 * util (conditional-sync): サブシェルで実行しているのは何故か [#D1329] 31955 テストを書いていて気づいたが check 用のコマンドで親環境を参照・変更する事ができない。 31956 考えてみれば同期的なサブシェルなので 31957 親環境の変数は変化しないので直接親に取りに行く必要はない。 31958 そして cancel-check のコマンドが副作用を持つというのも変である。 31959 然し、変更できないというのは不便な気もする。 31960 31961 * そもそもサブシェルで実行する必要はあったのだろうか。 31962 記録を探すと #D1080 である。然し、議論には詳しいことは何も書かれていない。 31963 一行 "遅くならないように修正した" としか書かれていない。 31964 うーん。特に問題もなかったのではないかという気がしてきた。 31965 サブシェルを除いてみる事にする。 31966 →特に変化は見られない様である。 31967 31968 と思ったが分かった気がする。内部で & を使ってコマンドを起動している。 31969 直接対話シェルでこれを実行すると jobs の変なメッセージが表示されて邪魔になる。 31970 丁度 ble/util/visible-bell で同様にサブシェルの中から & を使ってコマンドを起動している。 31971 少し試してみた限りでは conditional-sync では問題は発生していないが、 31972 何らかの条件で表示される可能性がある。という事なので現状のままサブシェルで実行する事にする。 31973 31974 * というか現在の実装でこれが功を奏している様に見えない。 31975 相変わらず c と打つと処理に時間がかかっている様な気がする? 31976 →実際に試してみると実は conditional-sync が使われていない様だ。 31977 実装を確認してみた所、補完文字列が空の時にのみ conditional-sync 31978 が使われるということの様である。 31979 31980 一文字cだけの時でもかなり時間がかかっている。5.8s-6s かかっている。 31981 cに対する候補の数はそんなに多くない。279件である。 31982 因みに0文字の時には 20s かかっている様だ。 31983 2文字 'cd' の時には、0.074sである。 31984 総合するに、何か時間のかかるコマンドが存在している? 31985 →調べると cy で 4.9s かかっている。 31986 31987 もっと全体的に調べてみる事にする。 31988 function measure-compgen { { time compgen -A command -- "$1" | wc -l >&3; } 2>&1 | head -2; } 3>&1 31989 31990 a 216 real 0m0.750s k 105 real 0m0.535s u 150 real 0m0.614s 4 1 real 0m0.118s 31991 b 2270 real 0m0.518s l 250 real 0m0.929s v 54 real 0m0.293s 5 1 real 0m0.129s 31992 c 297 real 0m5.649s m 323 real 0m0.853s w 178 real 0m0.567s 6 1 real 0m0.116s 31993 d 252 real 0m0.826s n 81 real 0m0.292s x 336 real 0m1.249s 7 1 real 0m0.116s 31994 e 108 real 0m0.384s o 53 real 0m0.299s y 9 real 0m0.156s 8 1 real 0m0.118s 31995 f 178 real 0m0.669s p 396 real 0m1.173s z 46 real 0m0.261s 9 1 real 0m0.127s 31996 g 291 real 0m1.144s q 42 real 0m0.260s 0 0 real 0m0.140s 31997 h 80 real 0m0.341s r 155 real 0m0.540s 1 11 real 0m0.114s 31998 i 248 real 0m1.071s s 298 real 0m0.817s 2 11 real 0m0.114s 31999 j 18 real 0m0.165s t 297 real 0m1.039s 3 1 real 0m0.118s 32000 32001 A 15 real 0m0.165s K 3 real 0m0.184s U 10 real 0m0.141s [ 4 real 0m0.141s 32002 B 15 real 0m0.143s L 16 real 0m0.153s V 6 real 0m0.137s ] 1 real 0m0.128s 32003 C 134 real 0m0.204s M 41 real 0m0.189s W 75 real 0m0.256s { 1 real 0m0.128s 32004 D 59 real 0m0.185s N 23 real 0m0.151s X 24 real 0m0.186s } 1 real 0m0.127s 32005 E 11 real 0m0.131s O 8 real 0m0.132s Y 0 real 0m0.119s 32006 F 15 real 0m0.141s P 34 real 0m0.159s Z 1 real 0m0.128s 32007 G 7 real 0m0.125s Q 0 real 0m0.137s ! 1 real 0m0.114s 32008 H 12 real 0m0.144s R 40 real 0m0.157s . 2 real 0m0.166s 32009 I 12 real 0m0.137s S 61 real 0m0.200s : 1 real 0m0.125s 32010 J 0 real 0m0.120s T 17 real 0m0.156s @ 18 real 0m0.125s 32011 32012 この結果を見ると 1 文字の時は全般に遅い。 32013 32014 ca 18 real 0m0.191s ck 2 real 0m0.126s cu 5 real 0m0.140s c4 0 real 0m0.116s 32015 cb 0 real 0m0.125s cl 43 real 0m0.203s cv 0 real 0m0.120s c5 0 real 0m0.115s 32016 cc 4 real 0m0.138s cm 9 real 0m0.156s cw 2 real 0m0.125s c6 0 real 0m0.122s 32017 cd 2 real 0m0.163s cn 0 real 0m0.127s cx 0 real 0m0.115s c7 0 real 0m0.142s 32018 ce 23 real 0m0.185s co 61 real 0m0.262s cy 16 real 0m4.925s c8 2 real 0m0.120s 32019 cf 2 real 0m0.135s cp 12 real 0m0.145s cz 2 real 0m0.134s c9 2 real 0m0.118s 32020 cg 2 real 0m0.126s cq 0 real 0m0.136s c0 0 real 0m0.123s 32021 ch 35 real 0m0.285s cr 12 real 0m0.163s c1 0 real 0m0.150s 32022 ci 3 real 0m0.143s cs 9 real 0m0.144s c2 0 real 0m0.116s 32023 cj 2 real 0m0.119s ct 21 real 0m0.187s c3 0 real 0m0.120s 32024 32025 ga 7 real 0m0.151s gk 2 real 0m0.141s gu 2 real 0m0.160s g4 0 real 0m0.130s 32026 gb 5 real 0m0.139s gl 18 real 0m0.203s gv 40 real 0m0.283s g5 0 real 0m0.120s 32027 gc 20 real 0m0.179s gm 0 real 0m0.144s gw 0 real 0m0.117s g6 0 real 0m0.116s 32028 gd 22 real 0m0.229s gn 14 real 0m0.187s gx 0 real 0m0.130s g7 1 real 0m0.129s 32029 ge 33 real 0m0.218s go 2 real 0m0.124s gy 0 real 0m0.137s g8 0 real 0m0.117s 32030 gf 6 real 0m0.145s gp 14 real 0m0.176s gz 4 real 0m0.141s g9 0 real 0m0.132s 32031 gg 0 real 0m0.119s gq 0 real 0m0.141s g0 0 real 0m0.118s 32032 gh 0 real 0m0.147s gr 30 real 0m0.249s g1 0 real 0m0.130s 32033 gi 14 real 0m0.221s gs 22 real 0m0.183s g2 0 real 0m0.113s 32034 gj 0 real 0m0.119s gt 32 real 0m0.278s g3 0 real 0m0.125s 32035 32036 ia 0 real 0m0.129s ik 0 real 0m0.126s iu 0 real 0m0.130s i4 0 real 0m0.131s 32037 ib 11 real 0m0.154s il 0 real 0m0.117s iv 0 real 0m0.117s i5 0 real 0m0.116s 32038 ic 10 real 0m0.153s im 19 real 0m0.196s iw 2 real 0m0.116s i6 126 real 0m0.722s 32039 id 5 real 0m0.141s in 33 real 0m0.225s ix 0 real 0m0.117s i7 0 real 0m0.125s 32040 ie 5 real 0m0.126s io 0 real 0m0.129s iy 0 real 0m0.134s i8 0 real 0m0.127s 32041 if 8 real 0m0.149s ip 11 real 0m0.156s iz 0 real 0m0.116s i9 0 real 0m0.114s 32042 ig 1 real 0m0.114s iq 0 real 0m0.116s i0 0 real 0m0.128s 32043 ih 0 real 0m0.128s ir 3 real 0m0.121s i1 0 real 0m0.115s 32044 ii 0 real 0m0.118s is 13 real 0m0.142s i2 0 real 0m0.117s 32045 ij 0 real 0m0.148s it 0 real 0m0.129s i3 0 real 0m0.118s 32046 32047 la 32 real 0m0.198s lk 2 real 0m0.127s lu 17 real 0m0.194s l4 2 real 0m0.138s 32048 lb 0 real 0m0.150s ll 3 real 0m0.129s lv 0 real 0m0.125s l5 0 real 0m0.114s 32049 lc 4 real 0m0.123s lm 0 real 0m0.128s lw 10 real 0m0.131s l6 0 real 0m0.119s 32050 ld 8 real 0m0.149s ln 4 real 0m0.142s lx 60 real 0m0.380s l7 0 real 0m0.115s 32051 le 10 real 0m0.146s lo 22 real 0m0.197s ly 10 real 0m0.132s l8 0 real 0m0.126s 32052 lf 0 real 0m0.128s lp 7 real 0m0.140s lz 22 real 0m0.204s l9 0 real 0m0.133s 32053 lg 0 real 0m0.133s lq 0 real 0m0.137s l0 0 real 0m0.123s 32054 lh 0 real 0m0.115s lr 2 real 0m0.129s l1 0 real 0m0.118s 32055 li 16 real 0m0.197s ls 9 real 0m0.137s l2 0 real 0m0.124s 32056 lj 0 real 0m0.132s lt 6 real 0m0.126s l3 2 real 0m0.117s 32057 32058 pa 21 real 0m0.195s pk 16 real 0m0.182s pu 11 real 0m0.160s p4 0 real 0m0.117s 32059 pb 2 real 0m0.138s pl 11 real 0m0.161s pv 0 real 0m0.124s p5 0 real 0m0.119s 32060 pc 11 real 0m0.138s pm 6 real 0m0.144s pw 4 real 0m0.128s p6 0 real 0m0.120s 32061 pd 62 real 0m0.301s pn 3 real 0m0.125s px 0 real 0m0.117s p7 0 real 0m0.115s 32062 pe 28 real 0m0.168s po 38 real 0m0.194s py 38 real 0m0.248s p8 0 real 0m0.115s 32063 pf 10 real 0m0.144s pp 6 real 0m0.131s pz 0 real 0m0.117s p9 0 real 0m0.123s 32064 pg 4 real 0m0.140s pq 0 real 0m0.116s p0 0 real 0m0.130s 32065 ph 1 real 0m0.119s pr 44 real 0m0.227s p1 2 real 0m0.128s 32066 pi 12 real 0m0.185s ps 43 real 0m0.244s p2 2 real 0m0.126s 32067 pj 0 real 0m0.115s pt 20 real 0m0.181s p3 0 real 0m0.129s 32068 32069 ta 20 real 0m0.188s tk 2 real 0m0.126s tu 2 real 0m0.143s t4 2 real 0m0.135s 32070 tb 2 real 0m0.130s tl 6 real 0m0.137s tv 0 real 0m0.130s t5 0 real 0m0.134s 32071 tc 23 real 0m0.201s tm 2 real 0m0.119s tw 2 real 0m0.125s t6 0 real 0m0.126s 32072 td 5 real 0m0.135s tn 0 real 0m0.121s tx 0 real 0m0.115s t7 0 real 0m0.121s 32073 te 92 real 0m0.390s to 6 real 0m0.151s ty 7 real 0m0.122s t8 0 real 0m0.127s 32074 tf 12 real 0m0.187s tp 9 real 0m0.151s tz 6 real 0m0.147s t9 0 real 0m0.117s 32075 tg 6 real 0m0.136s tq 0 real 0m0.132s t0 0 real 0m0.122s 32076 th 3 real 0m0.134s tr 25 real 0m0.194s t1 22 real 0m0.226s 32077 ti 10 real 0m0.146s ts 14 real 0m0.164s t2 0 real 0m0.116s 32078 tj 0 real 0m0.120s tt 19 real 0m0.188s t3 0 real 0m0.115s 32079 32080 xa 6 real 0m0.143s xk 14 real 0m0.188s xu 0 real 0m0.119s x4 0 real 0m0.136s 32081 xb 0 real 0m0.131s xl 14 real 0m0.163s xv 4 real 0m0.143s x5 0 real 0m0.116s 32082 xc 23 real 0m0.185s xm 28 real 0m0.215s xw 13 real 0m0.141s x6 0 real 0m0.129s 32083 xd 36 real 0m0.239s xn 0 real 0m0.125s xx 2 real 0m0.134s x7 0 real 0m0.115s 32084 xe 8 real 0m0.153s xo 4 real 0m0.141s xy 0 real 0m0.126s x8 80 real 0m0.464s 32085 xf 14 real 0m0.179s xp 14 real 0m0.155s xz 20 real 0m0.198s x9 0 real 0m0.115s 32086 xg 2 real 0m0.141s xq 0 real 0m0.119s x0 2 real 0m0.129s 32087 xh 4 real 0m0.124s xr 6 real 0m0.137s x1 6 real 0m0.144s 32088 xi 10 real 0m0.147s xs 21 real 0m0.186s x2 0 real 0m0.128s 32089 xj 0 real 0m0.118s xt 4 real 0m0.135s x3 0 real 0m0.116s 32090 32091 cy i6 lx te x8 辺りの組み合わせが重い。cy は cygwin だろう。 32092 i6 と x8 は i686 と x86 であろう。te は tex で lx は lx の様だ。 32093 3文字だと i68 0.7s x86 0.4s cyg 4.9s が重い。 32094 4文字だと cygg 0.7s cygc 0.5s cygp,cygf,cygk 0.4s が重い。 32095 32096 * edit: bash-5.1 PROMPT_COMMANDS 及び READLINE_MARK [#D1328] 32097 bash 5.1 のこれらの機能にはいずれ対応しなければならない。 32098 簡単に対応できるのでもう対応してしまう事にする。 32099 32100 * decode: ble-0.3 を使うと二回目以降の起動で ble/widget/ が見つからない [#D1327] 32101 というエラーが沢山発生してまともに操作する事ができなくなる。 32102 調べると decode table が変な事になっている。 32103 複数の要素からなる項目が全て分割されてしまっている。 32104 初期化した直後は配列の内容はちゃんとしているが、すぐに変な状態になる。 32105 何処か別の場所で書き換えているとは考えがたい。 32106 32107 と思って書き換わっている場所を探っていった所、 32108 cmap/initialize の中で壊れていた。そこで分かった。 32109 cmap のキャッシュを記録する時に keymap のキャッシュもダンプしている。 32110 それによって keymap が上書きされてしまうのであった。 32111 特に容量を減らす為に cmap のダンプの出力から引用符を削除していたので 32112 cmap を再ロードした時に複数の単語からなる binding が全て分割されてしまっていたのだった。 32113 32114 これについては ble-bind を実行する前に cmap/initialize を 32115 実行する様にして、更に cmap/initialize の中のキャッシュの記録についても 32116 cmap に関係のある行だけを選別して保存する様に修正した。 32117 取り敢えずこれで直った様である。 32118 0.4 の方でも安全の為に cmap に関係のある行だけを選別して記録する事にした。 32119 32120 * util: has-glob-pattern の判定がサブシェルの中ではできない [#D1326] 32121 failglob を使って判定しているがサブシェルの中だと 32122 eval を用いて評価していたとしてもその場で終了してしまう。 32123 32124 サブシェルの中でも failglob が発生しない様にする方法はあるのか。 32125 例えば nullglob を用いるという手があるのではないか? 32126 32127 * util: ble/util/print-global-definitions で未定義変数と配列に対応する [#D1325] 32128 32129 ble/util/print-global-definitions で定義されていない変数が 32130 空の変数名として抽出される様になっている。 32131 unset という事を検出する事は可能だろうか。 32132 32133 そもそも宣言されていないという事と宣言されているけれども unset である 32134 という事は今回は区別しない事にする。そもそも途中でローカル変数が定義されている時、 32135 "宣言されていない" という状態にするのは不可能なので、 32136 状態を再現するとしても "宣言しているが unset" という状態にするしかない。 32137 32138 unset であるという事を検出する事はできるか。試してみた所できる様子である。 32139 32140 * 配列に対応できていないという事が判明した。実は現在の用途では配列要素を指定する 32141 という事は無いような気がするけれども、関数の設計としては配列名であっても 32142 正しくグローバルに於ける配列を取得できる様にしておくべきである。 32143 32144 配列かどうかの判定はどうするか。配列かどうかの判定は。 32145 is-array を用いているが、実はこの関数は、普通の配列と連想配列を判定できない。 32146 is-array の実装を見直すべきだろうか。改めて is-array の実装を計測してみた。 32147 compgen による方法は遅い。実は ble/util/assign declare -p した方が速いのでは。 32148 と思って実測してみたらそうだった。これは declare -p による方法に切り替える必要がある。 32149 32150 配列の場合には実装はどの様にするべきだろうか。 32151 値を value=("${name[@]}") でコピーする方式だと飛びの在る配列の時に中身が変化する。 32152 一つずつ key を抽出して保存するのも大変である。 32153 ということであれば declare -p の出力をそのまま使う? 32154 然し、declare -p の出力には様々なバグが有るという事が判明している。 32155 そうすると declare-print-definiitions を呼び出す事にするか。 32156 それはそれで計算量が大きい。然し他に手段はないのである。 32157 或いは新しい bash の場合には declare -p を呼び出して、 32158 古い問題のある bash の場合には declare-print-definitions を呼び出す? 32159 32160 調べると修正が必要になるのは bash-3.2 以下の様である。 32161 32162 * fixed: さて値を unset にする為には declare && unset すれば良いだろうと思っていたら 32163 何と思うように動いてくれないという事が判明した。変だ。 32164 localvar_unset が実装されたために振る舞いが変わったという事なのだろうか。 32165 32166 | →何と a=1 f として呼び出した時と、a=1; f として 32167 | 呼び出したときで a の振る舞いが異なる? どうも a=1 f として呼び出すと、 32168 | f のローカル変数として定義される? いや何だか変である。よく分からない。 32169 | 32170 | 以下は全ての bash 3.0..5.0 で declare -x a=1 が表示される。 32171 | $ bash -c 'f1() { local a; declare -p a; }; a=1 f1' 32172 | 32173 | 以下は 4.1 以下では declare -x a= であり、 32174 | 4.3 では変数が見つからず、他は declare -x a である。 32175 | $ bash -c 'f1() { local a; declare -p a; }; export a=1; f1' 32176 | 32177 | 以下は 4.3 以下では変数が見つからず 4.4 以降では declare a である。 32178 | $ bash -c 'f1() { local a; unset -v; declare -p a; }; export a=1; f1' 32179 | 32180 | 以下を試しても特に振る舞いの違いは見えない。 32181 | bash -c 'f1(){ local a;unset -v a;declare -p a;};f2(){ local a=1;f1;};f2' 32182 | 32183 | では何故テスト環境でだけ上の変数が再び見える様になってしまっているのか。 32184 | 或いは対話環境では別の振る舞いをするなどの違いが在るのだろうか。試してみる。 32185 | →対話環境でも振る舞いは同じである。然し ble.sh をロードしていると振る舞いが違う。 32186 | 32187 | eval の中で実行すると振る舞いが変わる? →そうではなかった。 32188 | $ eval 'f1(){ local a;unset -v a;declare -p a;};f2(){ local a=1;f1;};f2' 32189 | 32190 | bind -x の中で実行すると振る舞いが変わる? →そうでもなかった。 32191 | $ text='f1(){ local a;unset -v a;declare -p a;};f2(){ local a=1;f1;};f2' 32192 | $ bind -x '"\C-t": eval "$text"' 32193 | 32194 | shopt の違いが効いているのだろうかと思って確かめてみたが、 32195 | 違いは failglob と histappend histreedit, hostcomplete しかない。 32196 | これらは振る舞いには関係ないだろう。 32197 | 32198 | NOBLE=1 で起動しても再現しない。其処から source ble.sh すると再現する様になる。 32199 | 更にその後で ble-detach しても再現したままである。不思議だ。bash-4.4 でも再現する。 32200 | うーん。何らかの変数が効いているのか或いは、builtin の上書きが関係しているのか、 32201 | それとも何らかの操作をすると不可逆的に bash の振る舞いが変化してしまうのか。 32202 | というか一度はテストに通過していた気もする。 32203 | 32204 | bash-3.0..5.0 の全てでこの現象が再現している。謎である。 32205 32206 状況をまとめると ble.sh をロードすると current-scope unset が 32207 dynamic に動作する様になってしまう。と此処まで書いて分かった。 32208 最近 unset を関数で上書きしてユーザが変更できない様にしたのだった。 32209 然し、そうすると unset の振る舞いが変化してしまう事になる。 32210 32211 やはり unset を関数で上書きするのは悪手である。修正する。 32212 32213 * fixed: 現在の ble/variable#has-attr の実装だと変数 attr に対して正しく取得できない。 32214 get-attr の場合にはインターフェイスから attr が取得できないというのは分かる。 32215 然し、has-attr の場合には attr について動作しないというのは不自然である。 32216 単に真偽値を終了ステータスで変え雨だけなのであるから。 32217 これは実際に ble/util/print-global-definition で使いたいので対応する事にした。 32218 32219 32220 * 実は bash-4.2 未満でも現在見ている変数がグローバルかどうか判定できるのではないか。 32221 というのもグローバル変数に対して -r を設定すると、 32222 ローカル変数としても定義する事が不可能になるから。 32223 ローカル変数に対して -r を設定した場合には新しく上書きする変数を定義できる。 32224 32225 問題はグローバル変数に対して -r 属性を関数内から付加する事ができるのかという事。 32226 →readonly を使うとちゃんとグローバル変数に対して -r 属性を付加できた。 32227 →typeset -r を使った時には同じスコープに変数が作成される。 32228 32229 2020-04-11 32230 32231 * 解消 2019-04-29 bashbug: #D1078 の bash-5.0 のバグを報告する? [#D1324] 32232 一応最新版で確認はしておいた方が良いかもしれない。 32233 と思ったが、どうせパッチを作るのであればその時に気づく筈である。 32234 32235 2020-04-11 これは既に PATCH を報告済みである。 32236 32237 * decode: bind --help の終了ステータスは 2 の様だ [#D1323] 32238 その他の buitlin も全て --help に対しては 2 で終了する様だ。 32239 32240 exit unset bind read history trap を上書きしている。 32241 その内で正しく 2 を返しているのは unset, history のみである。 32242 確認した所、何れも本来の builtin は 2 を返している。 32243 bind exit read trap は修正する必要がある。 32244 32245 2020-04-10 32246 32247 * complete: bash-dev で 10# のエラーが出ている [#D1322] 32248 "0>10#: invalid integer constant (エラーのあるトークンは "10#")" 32249 →これは簡単に修正できた。一箇所しか 10# はなかった。 32250 32251 * failglob: bash-4.3 で $? を入力するとエラーメッセージが出る [#D1321] 32252 syntax highlighting が効いているのに違いないという気がする。 32253 特に変数の内容を調べるコードが怪しい気がする。 32254 うーん。get-attr だろうか→正にそれである。 32255 これは直った。 32256 32257 * _ble_decode_input_buffer で不正な添字というエラーが発生する [#D1320] 32258 bash-4.1 以下で発生する様である。 32259 うーん。((i=-1,i>=0&&a[i--])) が bash-4.1 以下で駄目の様である。 32260 うーん。これは算術式のバグである。今まで知らなかったバグだ。 32261 →と思って確認したら既に分岐内の配列参照は実行されるという事が書かれている。 32262 唯、それが配列添字の中でも起こるという事は新たな発見であった。 32263 32264 一応類似の物が存在しないか確認する。 32265 grc '(\|\||\?|&&)[[:alnum:]_]+\[' 32266 取り敢えずは問題無さそうである。 32267 32268 2020-04-09 32269 32270 * ble/util/openat は関数名を変更するべきでは [#D1319] 32271 openat という unix の関数が存在して、 32272 これは指定した fd からの相対パスでファイルを開くという物である。 32273 恐らく readlink で読みだしたリンク先を開くようなそういう関数なのだろう。 32274 32275 名前が同じで機能が全く異なるのは良くないので名称を変えたい。 32276 また、ble/util/is-fd-open という関数も作成した。 32277 そういう事を考えると、以下の様な感じに改名すると良さそうな気がする。 32278 ble/fd#is-open 32279 ble/fd#alloc 32280 ble/fd#close 32281 32282 うーん。この際なので解明する。 32283 32284 * util: 実は openat で行っている fd の生死判定は : >&fd でできるのでは [#D1318] 32285 現在の実装では bash 4.0 以下では自分で適当な場所に fd を開いている。 32286 然し、既存の fd と被る場合には 3.0 では先に fd を閉じて置かなければならない。 32287 また 3.1 では fd を閉じても変な事になってしまう。 32288 仕方がないので 3.1 の時にだけ特別に fd が開いているかどうかを 32289 /dev/fd/.. または /proc/self/fd/.. で判定している。 32290 32291 然し、実は : >&fd で判定できるのではないかという事。 32292 これならば環境依存せずに高速に判定する事ができる。 32293 内部的には dup2 を 3 回程度実行するだけの気がする。 32294 32295 * ok: fdが再利用できない? 32296 然し、これによって今までは再利用していた fd が再利用されなくなって 32297 fd を無駄に使う様になってしまうのではないか。と思ったが、 32298 よく考えたら bash-4.1 以降では {fd}<> を使うので何れにしても再利用されない。 32299 bash 4.0 以下でだけ再利用する理由もないので、毎回判定する事にする。 32300 32301 或いは、O_CLOEXEC を設定する方法があれば良い。。 32302 が少し考えてみたがその様な裏技の様な物はない気がする。 32303 或いは、export _ble_util_cloexec=10:11:12 等として上書き可能な 32304 fd を export して知らせるという手もあるが其処までする必要があるのかは謎である。 32305 32306 総じて fd は再利用しなくても良いという様に結論づける。 32307 32308 * ok: これによって openat_base は不要になったのではないか、と一瞬思ったが、 32309 ble.sh の側で重複判定をしていたとしても別のシェルプログラムが同じ領域を 32310 勝手に上書きして使うという事態になっていると結局問題が起こる。 32311 従って wiki の openat_base の説明は更新しなくても良い。 32312 32313 2020-04-08 32314 32315 * test: テストフレームワークの整理 [#D1317] 32316 幾らか実装したので実装済みのものはこちらに移動する。 32317 32318 * 単体テストの機能 32319 * done: 複数行 stdout を指定しやすくする? 32320 * done: stderr のチェック 32321 * done: テストのタイトル→これは '# title' の形式の単語で指定する。 32322 32323 * その他の細かい動作について 32324 * done: start-section で自動的に end-section を呼び出す 32325 * done: start-section で開いた fd を閉じる 32326 * done: 並列テストに向けて一時ファイルが被らない様に BASHPID をファイル名に含める 32327 * done: diff のファイル名を分かりやすくする。 32328 32329 * テストに BASHPID を使っているが bash-3 で使えない。 32330 bash-3 以下では sh -c $PPID を使って BASHPID を更新する事にした。 32331 と思ったが、これだと feature-test を使っている環境で変な事になるのでは? 32332 まあ、テストだけで使う様にすれば問題はない様な気がする。 32333 それ以外の場所では version を分けて local BASHPID 等とする事にする。 32334 32335 * 2020-03-11 test: oilshell に Travis でテストを自動化せよと (suggested by andychu) [#D1316] 32336 実のところテストらしいテストは何もないのだが。 32337 自動化テストについて思うところ。 32338 32339 →取り敢えずのテストの枠組みは形が見えてきたのでこれは考察済みという事にする。 32340 32341 # そもそも何故そういう GitHub 上のテストを設定する気が余りしないのかというと、 32342 # 32343 # 1 先ず interactive session でないと ble.sh をロードしない様になっているので、 32344 # 其処を弄って特別に起動できる様にしなければならないという事。 32345 # つまり、そもそもローカルでテストが自動化出来ていないのである。 32346 # 32347 # 2 GitHub 上でやるという事は不完全な形で push するという事を想定しているようで嫌だ。 32348 # テストを自動化するぐらいであればローカルでちゃんとテストを通してから 32349 # GitHub 上でテストを通すという事にするのが良い気がする。 32350 # そもそも Travis は発火するまでに時間がかかる。それぐらいならば手許である。 32351 # 32352 # 然し、手許で毎回テストを実行する訳ではないし、 32353 # 複雑な事を実装している時に関係のない部分が火を吹いたりすると 32354 # 頭が混乱するのでテストは一括で行いたい様な気もしたり。 32355 # 色々考えるとやはり最低限は手許でテストしつつも 32356 # 自動化して GitHub 上での自動化されたテストにも頼るというので良いという気がする。 32357 # 32358 # 3 そして十分な数のテストが存在していないという事。 32359 # これはテストを準備しなければならない。。 32360 # 32361 # 4 対話的なプログラムのテストを書くのは面倒だという事。 32362 # 特にテストケースの "正解" をどう記述するのかという事、 32363 # どうやってそれを確認するのかという事。 32364 # 32365 # 然し、よく考えてみればそういうのはどのプログラムでも同じである。 32366 # 従って、結局どのプログラムでもテストという物は 32367 # 一般的なユーティリティの部分だけに留まって 32368 # 本質的な処理に近い部分のテストはおろそかになる物ではないかという気がする。 32369 # なので余り気にせずにコア部分に近い部分だけテストしておけば良いという事なのかもしれない。 32370 # 32371 # というかよく考えてみると regression という物を殆ど経験していない。 32372 # それも大体作ったらそのままで変更する頻度はそんなにないという事。 32373 # それから変更する場合には実際に使っている箇所を大体ちゃんと確認するので、 32374 # regression が起こりにくいという事。 32375 # まあ全くないという訳ではないので多少は役に立つかもしれないというぐらい。 32376 # 自動化テストというのは一回通せば済むものではなくて、 32377 # 毎回テストする事に利点があるのである。つまり regression。 32378 # そういう意味では ble.sh の開発の形態自体が 32379 # 自動化テストをしなくても大丈夫な形に適合してしまっている。 32380 # 32381 # 一方で自動化する事によって新しいテストを書くという動機にはなって、 32382 # それによって得られる物は大きい気がする。 32383 # ただ毎回テストするという事には余り意味はないのかもしれないが。 32384 # 然しそれを言い出すとどのプロジェクトも結局同じ気もする。 32385 32386 2020-04-07 32387 32388 * menu: menu が表示されている状態で確定すると [#D1315] 32389 INSERT の行が消える。というより座標計算もずれている気がする。 32390 今まで status がすぐに消えて何だろうと思っていたがこれで 32391 再現する事ができるのである。 32392 32393 | 扨、何故これが起こるのだろうか。menu が表示されているというだけで、 32394 | 別に menu に入っているという訳ではない。うーん。不思議だ。 32395 | 32396 | clear-content の段階では特に問題は生じていない。 32397 | menu が表示されていない場合でも表示されている場合でもちゃんと初期ょしているし、 32398 | panel の高さの情報もちゃんと更新できている。 32399 | 32400 | そうすると ble-edit/info/reveal の方で問題が発生しているのだろうか。 32401 | うーん。不思議だ。ちゃんと動作している様に見える。 32402 | 32403 | 或いは _ble_canvas_x, _ble_canvas_y の座標がずれている? 32404 | →別に違いは見られない。 32405 | 32406 | うーん。どうも一瞬表示されてそれから消滅している様に見える。 32407 | 少なくとも高さの確保に失敗している事は確かである。表示している位置がずれている。 32408 | 追加されるべき行が追加されていない。 32409 32410 →なんか変だと思ったら分かった。コマンドが実行される前に表示を実行している。 32411 menu/clear 経由で再描画されているのだった。これは #D1290 の変更が原因である。 32412 うーん。menu#clear で immediate-clear ではなくて単なる clear にしたら直った。 32413 clear の時には reveal が呼び出される迄は info の更新は行われないのである。 32414 32415 * history: 履歴が倍加する現象が再度発生している [#D1314] 32416 32417 [原因] 32418 32419 遡ると 8cf17f7 で発生する様になっている。大分前である。 32420 前回の倍加問題の修正のすぐ後に再度発生する様になっている。 32421 然し、今まで倍加する問題は観測されなかった。 32422 という事は何か別の設定と相互作用を起こしてこれが発生している。 32423 32424 どうやら /etc/bashrc の中に history -a が存在しているのが行けない様だ。 32425 この時に一体何が起こるのだろうか。というか、ble と関係在るのだろうか。 32426 と思ったが ble で古い version を使った場合には発生していないので、 32427 やはり ble との相互作用が原因になっているのは確かである。 32428 32429 最近変わった事は何かというと /etc/bashrc の読み込みを 32430 source ble.sh よりも後に移動した事である。うーん。 32431 もしかしてこれはどのユーザでも同様に発生するのではないだろうか。 32432 全然駄目である。良くない。 32433 何れにしても source ble.sh を実行した後に history -a する事で 32434 何か ble.sh の想定が崩れてしまっているという事が考えられる。 32435 というか、/etc/bashrc が history -a を実行する時に履歴が空である事を想定している可能性? 32436 32437 サブシェルの中で history -a を実行しても問題は発生しない。 32438 という事は history -a を実行した事によって何らかの計算がずれて、 32439 それによって何か変な事が発生しているという事。 32440 32441 特に終了時に全体が書き込まれてしまっている。 32442 うーん。これはつまり、initialize に於いて 0 が初期位置として記録されてしまっている? 32443 _ble_builtin_history_wskip の値が変になっているのではないか。 32444 調べると空になっている。辿るとこれは ble/builtin/history/.get-max 32445 の結果を使っている。そしてこれの結果が空になっている。 32446 実装を確認すると builtin history 1 の最初の単語を使っている。 32447 つまり、履歴が読み込まれていない時にこれを呼び出すと空になる。 32448 32449 うーん。履歴を強制的に読み出すにはどうしたら良いか? 32450 32451 [現状の振る舞い] 32452 32453 どうも記憶によると bashrc で履歴を history -r すると、 32454 その時点で history が倍加してしまうという事だった気がする。 32455 32456 * history -a 32457 さて bashrc で history -a を実行した時の振る舞いが分からない。 32458 見てみると別に何も変化は起こらない気がする。 32459 或いは手で source した時にその場でそれまでの履歴を保存するのが目的なのだろうか。 32460 もしそうだとすると履歴が読み込まれていない時には history -a は実行しない、 32461 という具合に変更する事ができる。或いは履歴が読み込まれていなくても、 32462 history -a によって何らかの変化が発生する可能性はあるのだろうか。うーん。 32463 32464 うーん。履歴が読み込まれていない時は history -a は無視するというのが正しい気がする。 32465 32466 * history -r 32467 ble.sh をロードしている時に bashrc で history -r を実行するとどうなるか。 32468 ble.sh がない場合にはこれによって履歴が倍加するのではないかと危惧したが、 32469 実際に試してみるとそのような事は発生していない様だ。何故? 32470 或いは古い bash の version だけでの問題だったのだろうか。 32471 32472 * history -n 32473 コメントを参照してみると履歴倍加が発生するのは history -n を実行した時の様だ。 32474 →実際に試してみると確かに再現する。 32475 32476 [対策] 32477 32478 うーん。どう対策するのが良いのか。或いは、.initialize の時に 32479 history -r を実行してしまえば問題が発生しない可能性? 32480 と思って実行してみたら倍加している。h とした時点で倍加している。 32481 単に history -r しただけではそうならないのに、 32482 何故 ble.sh の中から history -r を呼び出すと倍加しているのか。。 32483 32484 然し、bash で history -a 及び history -w を実行しても何も起こらないのだとすれば、 32485 history -aw を bashrc の中で呼び出した時には何も実行しないというのが正しいのではないか。 32486 然しそれでも問題はある。history -s で履歴項目を追加した後に history -a を実行したらどうなるのか。 32487 そうすると結局履歴を読み込む前の状態で wskip が記録されてしまい、 32488 終了時に結局履歴が倍加してしまう。 32489 32490 そもそも bash の振る舞い自体がおかしいのが行けないのではある。 32491 もし bash の制限がなかったとしたらどの様に振る舞いのが自然だろうか。 32492 要するに bash の初回 load の後に wskip を設定するべきという事なのである。 32493 現在の実装ではどうなっているか。bash が内部的に load するのを検出する事はできない。 32494 一方で、それ以外の history の動きについては追跡する事ができる。 32495 32496 →bashの振る舞いを確認すると bashrc の中で history -s で履歴を追加した時には、 32497 実は HISTFILE の読み込みが抑制される様である。 32498 history -n では抑制されないのに変な事である。 32499 32500 ble.sh ではどの様に振る舞うべきだろうか。 32501 32502 | 寧ろ初回にロードした時に history を読み込んでしまう? 32503 | と思ったがそれだと HISTFILE を設定する前に読み込みが実行されてしまい、 32504 | 意図しない事になる。最終的な HISTFILE で読み込みをしたいという事を考えると、 32505 | できるだけ履歴の読み込みは遅延しなければならないのである。 32506 | そしてそれを実現する為には結局 bash に読み込ませるというのが現実的なのである。 32507 | 32508 | * その場合 history -aw は無視で良い。 32509 | 32510 | * bash では history -s は実行すると履歴が初期化されなくなる。 32511 | これは ble.sh でもそのまま実行すれば良い気がする。 32512 | と思ったが本当だろうか。実際に読み込んでいないのに、 32513 | rskip の値がファイルの末端に設定される。 32514 | 32515 | * history -r をするとその場で読み込んで rskip が設定されるが、 32516 | 然し、bash によって勝手に追加で読み込みが実施されて履歴が倍加する。 32517 | と思ったが実際に試してみるとそういう現象は起こっていない様だ。 32518 | これに関しては現状のままで良い? 32519 | 32520 | うーん。微妙である。history -r で明示的にファイルを指定して読み込む事もある。 32521 | 或いは何も指定せずに history -r を実行した時にのみ読み込みを initialize で実行しない。 32522 | それ以外の場合には history -r に先立って明示的に履歴ファイルを読み取る? 32523 | 32524 | 或いは history -r の時にはわざわざ履歴を読み出さなくても良いのではという気もする。 32525 | 但し、これをすると bash による後の読み込みも抑制されてしまう。 32526 | 32527 | * history -n を実行してみると…。ble.sh の枠組みの中では何も発生しない様だ。 32528 | 少なくとも history 1 をしても何も出力されない。 32529 | そして履歴の倍加も起こっていない。 32530 | 本当に何もしていないのだとすれば倍加が起こらないのは当然である。 32531 | 実装を確認してみる事にする。 32532 | 32533 | →rskip が最初にファイルの長さに初期化される為に読み取りが実施されないという事の様だ。 32534 | うーん。これは本来は未だ読み取りが実行されていないのだから rskip は 0 に設定しておいて、 32535 | bash が勝手に新しく読みだした時に改めて更新するべきという事の気がする。 32536 | 32537 | うーん。或いは history 1 をして空だったら history -r を実行するという事? 32538 32539 なかなか仕様が定まらない。 32540 32541 | どういう振る舞いが自然なのかという方針を明確にしなければならない。 32542 | 元の bash の振る舞いを多少変更しても構わない。 32543 | 然し元の bash の上で実現可能でなければならない。 32544 | 実現可能性に関しては実は頑張ればどうにでもなる気がする。 32545 | 32546 | 問題はやはり履歴が未初期化の時にどういう振る舞いが自然なのかという事である。 32547 | 32548 | * history -aw に関しては何も実行しない。 32549 | 32550 | * history -c に関しては後の履歴読み込みを無効化する。 32551 | これは取り敢えず一旦読み取ってしまってその後で -c すれば良い。 32552 | 32553 | →その様に実装したら bash が勝手に履歴を読み取って、 32554 | それによって履歴が倍加してしまった。うーん。 32555 | 一筋縄では行かない。bash が履歴読み取りをするかしないかの条件に 32556 | 現在空であるかどうかというのも関わってくるという事? 32557 | 32558 | そもそも元の bash ではどの様に振る舞うのだったか。 32559 | →history -c をしても bash が履歴ファイルを読み取る。 32560 | つまり、history -c の場合も未初期化の場合には何もしない事にすれば良い。 32561 | 32562 | * history -s に関してはやはり履歴を読み取ってから、 32563 | その後にデータを追記する様にするのが良い気がする。 32564 | 32565 | 実際に ble.sh で動かしてみた所、読み取れていない。何故? 32566 | と思ったら decode attach していない時には単純に history -s 32567 | を呼び出すだけという実装になっていた。これは修正する。 32568 | 別に初期化はどのタイミングで実行しても問題ない筈なので。 32569 | 32570 | * history -r に間しては微妙である。 32571 | 履歴の読み取りを抑制してしまって良いのか。 32572 | 元の bash の振る舞いを見ると history -r file でファイルから読み込んで、 32573 | 更にその後で履歴ファイルからも読み取るという振る舞いになっている。 32574 | 32575 | もう少し色々試してみても良いという気がする。 32576 | →試してみた所 bash は history -r を実行すると、 32577 | 履歴を二重に読み取ってしまう。 32578 | 実はこれは現在の ble.sh の振る舞いと同じである。 32579 | history -r によって履歴が倍加するのは許容する。 32580 | 32581 | * history -n に関しては履歴をその場で読み取って、 32582 | 追加で読み取るという事はしない。 32583 | 32584 | 後、単に履歴が空なのと実際に見初期化であるのをどのように区別するのか、 32585 | という問題が在る。history -c; source ble.sh とした場合に履歴が 32586 | ファイルから読み込まれてしまうのは果たして自然なのかという事である。 32587 | その他の方法で見初期化である事を判定する方法は存在するだろうか。 32588 | →これはどうしようもない。空ならばみ初期化と見做す事にする。 32589 32590 32591 まとめると、履歴が未初期化かどうかは現在履歴が空かどうかで行う。 32592 (Bash も履歴が空かどうかで履歴読み出しを実行するかしないかを決める様である。) 32593 未初期化の時の history の各操作の振る舞いは以下の様に決める。 32594 32595 * history -awcd は何も実行しない。 32596 * history -snr は HISTFILE を読み取った後に実行する。 32597 これは bash の振る舞いとは異なるがこの振る舞いの方が現実的である。 32598 * history -p に関しては何も対処せず普通に実行する 32599 履歴の倍加は起こらないという事を確認した。 32600 32601 この仕様の下で履歴が倍加するのは history -r を実行した時である。 32602 但し、保存される履歴に関しては倍加されず飽くまでも実行時に倍加するのみである。 32603 因みに元の bash でも history -r を実行すると履歴が倍加する。 32604 意図的に履歴を追加で読み取るという操作と区別がつかないのでこの振る舞いで問題ない。 32605 32606 x fixed: __ble_edit__ が付加される? 32607 これは何だろう。というよりそもそも __ble_edit__ を付加するのは何故だったか。 32608 →調べたらこれは __ble_ext__ の間違いであった。 32609 61f4bd1 で __ble_edt__ を __ble_edit__ に直したが、直し方が違った。 32610 これは ble-0.3 にはない問題なので commit を分ける必要もない。 32611 今回、一緒にこれも直してしまう。 32612 32613 2020-04-06 32614 32615 * global: builtin declare は oil が対応しないと言っている [#D1313] 32616 そもそも ble.sh でも declare の上書きは削除しているので、 32617 ここで builtin を指定する必要はない気がする。 32618 何より他の declare -p だとか local では builtin は指定していない。 32619 32620 削除している物についての無駄な builtin は消す事にする。 32621 使われている箇所を確認すると以下の通り。 32622 32623 | $ grc --exclude=\*.md -Wg,--color=none -o 'builtin [[:alpha:]]+' | 32624 | grep --color=none -Eo 'builtin [[:alpha:]]+' | 32625 | sort | uniq -c | sort -rn 32626 | 179 builtin eval 32627 | 65 builtin history 32628 | 42 builtin bind 32629 | 28 builtin read 32630 | 28 builtin printf 32631 | 23 builtin trap 32632 | 13 builtin exit 32633 | 10 builtin unset 32634 | 10 builtin echo 32635 | 8 builtin kill 32636 | 8 builtin compgen 32637 | 6 builtin complete 32638 | 3 builtin cd 32639 | 2 builtin unalias 32640 | 2 builtin type 32641 | 2 builtin sleep 32642 | 2 builtin mapfile 32643 | 2 builtin compopt 32644 | 1 builtin return 32645 32646 この内で unset によって上書きをキャンセルしているのは以下の3種類だけである。 32647 eval, unset, unalias 32648 32649 % * eval: うーん。eval は 179 箇所で builtin eval している。 32650 % 然し、eval に関してはユーザが勝手に削除すると悲惨な事になると予想されるので、 32651 % まあ、取り敢えずそのままにしておく事にするのが良い気がする。 32652 % →と思って確認した所 builtin なしで eval している箇所も沢山ある。 32653 % 数えたら 149 箇所である。これは取り敢えず後で修正する。 32654 % 32655 % * ok: builtin unset に関しては調べると unlocal で使っている。 32656 % これは確かに関数などに置き換えられていると意図した様に動かない可能性が高いので、 32657 % 明示的に builtin unset を指定する事にする。Note を追記しておいた。 32658 % 32659 % →やはり全て builtin を記述する事にしたので Note は削除した。 32660 % # Note #D1313: unset は上書きできない様にしているので基本的にはbuiltin をつけな 32661 % # くて良いが、unlocal に用いる時だけはローカル変数のスコープの兼ね合いから明 32662 % # 示的に builtin unset として置きたい。 32663 % 32664 % * unalias については上書き削除の目的だけでしか builtin unalias はない。 32665 % そのままで良いという事にする? 32666 % うーん。或いは全て builtin で呼び出す事にしようか。 32667 32668 readonly だけ抜けているのは妙なのでこれも上書きをキャンセルする事にする。 32669 export, alias, unalias についてはそのままという事にする。 32670 32671 * done: builtin をつけるかつけないかの一貫性は保って置きたい。 32672 やはり eval/unset/unalias はすべて builtin をつける事にした。 32673 eval についてはつけ終わった。unset についても終わった。 32674 unalias は少ししか無い。 32675 32676 * done: builtin eval の後に -- を付ける必要のある箇所について確認する。 32677 32678 * done: unset を自分で定義して readonly にしてしまえば良いのでは? 32679 →試しにその様にしてみる事にした。 32680 32681 * util (bleopt): 未定義の設定が name:= で定義されない [#D1312] 32682 値が同じであると判定されて代入がスキップされていた。修正した。 32683 32684 * decode (ble-bind): エラーメッセージ修正 [#D1311] 32685 keymap が見つからない時のエラーメッセージで keymap 名が出力されていない。 32686 32687 * global: local -i 仕様の削除 [#D1310] 32688 oil が対応していない。元々排除しようと思っていた。 32689 良い機会なので削除する事にする。 32690 32691 g2sgr 及び layer/update が引数を受けるのに使っている。 32692 使用箇所を確認したが何れの場所も整数しか入らない様に見える。単に削除する。 32693 ble-measure は内部的に使っていたが意味のない物だったので単に削除する。 32694 32695 * test: テストフレームワーク [#D1309] 32696 32697 既存のフレームワークについて確認する。 32698 32699 * bats 32700 これは自分で 成功・失敗 を判定しなければならない。 32701 例えば期待する出力と実際の出力を比較するという様な機能はない? 32702 唯単に集計するだけの枠組みの様に思われる。 32703 32704 * oil/test 32705 これは期待する出力と実際の出力を比較する機能がある。 32706 終了ステータスを確認する機能もある。 32707 様々なシェルで同時にテストする機能もある。 32708 シェル毎に期待する結果を比較する事もできる。 32709 32710 * 様々なシェルで同時にテストする事ができたのは、 32711 oil のテストはシェルに対するテストで、 32712 個別のテストが独立した小さなプログラムだからである。 32713 通常のシェルスクリプトのテストの場合には、 32714 シェルスクリプト全体を読み込んだ上で実行しなければならないので、 32715 ble.sh の様な巨大なスクリプトの場合には向かない。 32716 32717 対応するとしても、一つのシェルで一気にテストを実行して、 32718 それを後で集計するという形式にする必要がある。 32719 その様な実装であれば実は後で実装すれば良いので余り気にしなくても良い。 32720 32721 * shellspec 32722 https://qiita.com/ko1nksm/items/9053e9c1e42a2ae9033e 32723 並列でテストする機能がある。 32724 coverage を計測する機能がある。 32725 期待する出力と実際の出力を比較する機能もある。 32726 32727 既存フレームワークを眺めた結果の考察 32728 32729 * 実際の所、oil/test 的な仕組みが最も使いやすいのではないかという気がする。 32730 但し、テストに要する時間に関しては微妙かもしれない。 32731 32732 * 何れのフレームワークも何らかの DSL を作っている。 32733 bats 及び shellspec は特に奇を衒った事をしている。 32734 然し、正直な感想を言えば DSL を作ることで便利になっているのかは微妙である。 32735 余り DSL を作った事による利点を活かせていない気がする。 32736 32737 それに DSL にするとその DSL のデザインに気を取られてしまう。 32738 できるだけシェルとして自然な形にまとめられないか。 32739 32740 例えば、テストのタイトルは変数に入れる。 32741 テストのスクリプトは関数として定義する。 32742 それでも、期待する出力及び終了ステータスは直に書きたい。 32743 heredoc で定義するしか無いだろうか。 32744 32745 | TITLE='hello world' 32746 | test() { 32747 | コマンド 32748 | } 32749 | ble/test <<EOF 32750 | ## COMMENT 32751 | 何らかのコメント 32752 | ## EXPECT 32753 | 通常の期待出力 32754 | ## EXPECT 0 BUG bash-3.0 32755 | bash-3.0 における出力 32756 | EOF 32757 32758 もしくは 32759 32760 | title='hello world' 32761 | test() { 32762 | ... 32763 | } 32764 | ble/test/expect <<EOF 32765 | ... 32766 | EOF 32767 | ble/test/expect -x0 -tBUG -sbash-3.0 <<EOF 32768 | ... 32769 | EOF 32770 | ble/test test 32771 32772 うーん。或いは、alias を使ってしまう? 32773 →然し、試してみて思ったのは heredoc だと 32774 インデントが TAB しか使えないという制限がある。 32775 そしてそれを意識しなければならないのは辛い。 32776 32777 heredoc 以外だと oil, shellspec の様にコメントを使う手があるが、 32778 それだと結局ひとつ上の枠組みで何らかの処理をする必要があり、 32779 結局 DSL を構築するのと大差ないという気がする。 32780 32781 そういう事であれば ble.sh の場合には 32782 mwg_pp を使ってスクリプトを生成するのが自然である。 32783 と思ったが mwg_pp の枠組みでもインデントを検出するのは難しい。 32784 そうすると結局新しい DSL を作る事になってしまうのか。 32785 32786 うーん。取り敢えずすべて忘れて実装してみたが、 32787 これで良い気がしてきた。取り敢えずはこれでやって行く事にする。 32788 32789 2020-04-01 32790 32791 * bash-5 で heredoc を failglob で使うと駄目 [#D1308] 32792 変数に含まれる \ がパス名展開を誘起してそれにより失敗する。 32793 これも今実行してみると再現しない。但し、これに関しては原因を探れば 32794 再現する方法も自然に分かるという気がする。 32795 32796 調べると nparam に問題の文字列を格納している。 32797 然し、nparam 自体はパス名展開の対象となる様な文脈では用いられていない。 32798 だとすると stat の方が怪しいだろうか。 32799 と思って眺めていると ble/syntax:bash/is-complete に怪しい所がある。 32800 というかこの is-complete とは何だろうか。うーん。 32801 32802 ble-edit/is-single-complete-line から参照されている。 32803 複数行でかつ貼り付けでない時に呼び出される。未だ再現しない。 32804 →分かった。echo <<$(echo EOF) で再現した。 32805 そして見つけた箇所を修正したらちゃんと再現しなくなった。OK 32806 32807 * OK: history: "history -d 負の数" にちゃんと対応していたか? [#D1307] 32808 bash-5.0 changes を見ていて気付いたが対応した記憶がない。 32809 と思って実装を確認してみたらちゃんと実装していた。OK 32810 32811 * global: TMOUT が設定されているとあらゆる read が timeout して [#D1306] 32812 変なことになってしまうのではないだろうか。 32813 32814 先ず初めに TMOUT の振る舞いについて調べる事にする。 32815 * -t が指定されている時には TMOUT の影響は無いようである。 32816 * TMOUT に不正な値を指定してもエラーになる訳ではなく単に無視される。 32817 '1 2' などの数値の後に何かごみがある場合でも無視される。 32818 * 算術式展開は実行されない。 32819 * 負の値を指定しても無視されるだけである。 32820 * 十六進数リテラルは無視される。 32821 32822 m check で read があるので基本的に builtin read だけ確認すれば良い。 32823 32824 * read の TMOUT に対応した。 32825 と思ったがわざわざ自分で -t を指定する必要はあっただろうか。 32826 実は builtin read が自動的に TMOUT を読むから不要なのではないか。 32827 と思ったが、-e を指定している時には自分で処理しなければならない。 32828 →確認した。この実装で問題ない。 32829 32830 * global: shopt -s assoc_expand_once という設定は丁度 extra subscript expansions [#D1305] 32831 を off にする為の設定の様である。然し、これは連想配列に対してしか有効でない様だ。 32832 以下の例では、連想配列にした途端に添字展開が行われなくなる例。 32833 32834 $ shopt -s assoc_expand_once 32835 $ expr='x[$(echo hello >/dev/tty)]' 32836 $ ((expr)) 32837 hello 32838 $ declare -A x 32839 $ ((expr)) 32840 $ 32841 32842 うーん。これを考えると実は連想配列の添字について再度確認しなければならないのでは。 32843 32844 $ shopt -s assoc_expand_once 32845 $ declare -A A 32846 $ key=123; A[$key]=1234 32847 $ declare -p A 32848 declare -A A=([123]="1234" ) 32849 $ echo ${A[$key]} 32850 1234 32851 $ A["x$key"]=321 32852 $ declare -p A 32853 declare -A A=([x123]="321" ) 32854 32855 まとめると、A[...]=... 及び ${A[...]} は影響を受けない。 32856 算術式の中の配列添字の展開は影響を受ける。 32857 history.sh の [\$file] は shopt を変更して対応するか、 32858 或いは shopt の設定に依存しない形に書き換える必要がある。 32859 これは書き換える方向で調整する事にする。 32860 32861 * global: OK: shopt -u expand_aliases という設定がある事に気付いた [#D1304] 32862 現在の ble.sh ではこの設定に関係なく alias を展開している気がする。 32863 と思って確かめてみたが最初に type で種類をチェックしている。 32864 どうやら -u expand_aliases の時には type で見つからない様なので、 32865 現在の実装でちゃんと expand_aliases に応じた振る舞いになっている。 32866 以下の二つともその様な実装になっている。 32867 - ble/util/expand-alias 32868 - ble/widget/command-help/.type 32869 32870 2020-03-29 32871 32872 * syntax: [!...] が履歴展開文字を含む為に単純単語ではなくなっている (reported by cmplstofB) [#D1303] 32873 https://github.com/akinomyoga/ble.sh/issues/47 32874 32875 [!...] に関しては unquoted [! の場合には必ず履歴展開は無効になる様だ。 32876 例えば [echo!echo] だと履歴展開が有効だが 32877 [echo[!echo] だと履歴展開は無効である。 32878 という事なので [! の組み合わせを無条件に単純単語に含めて良い様にしてOK? 32879 と思ったら [echo[!echo だと履歴展開は有効になる様である。よく分からない。 32880 32881 [!echo] 無効 32882 [a!echo] 有効 32883 [a[!echo] 無効 32884 [a[!echo 有効 32885 32886 * reject: 逆に履歴展開を許容するという案はあるだろうか? 32887 然し、s/aaa/bbb/ は副作用を持つ。 32888 これが問題になるケースがあるのではないだろうか。 32889 うーん。やはりある気がする。サブシェルで実行するという手もあるが面倒である。 32890 何より単語が沢山ある時に速度が低下してしまう。履歴展開の文字が含む場合だけ 32891 特別扱いしても良いがそれはそれで面倒な事になる。 32892 32893 ? no: というかそもそも simple-word/eval で履歴展開は実施されるのだったか。 32894 取り敢えず [! を許容しても eval の内部で履歴展開が発生しない事は確認した。 32895 少なくともこの変更によって副作用が発生したりおかしな事が発生することはない。 32896 32897 | $ ble/syntax:bash/simple-word/eval '[A[!echo'; echo $ret 32898 | [![!echo 32899 | $ ble/syntax:bash/simple-word/eval '[A[!echo]'; echo $ret 32900 | 32901 | $ ble/syntax:bash/simple-word/eval '[a[!echo]'; echo $ret 32902 | a 32903 32904 eval で履歴展開が実施されるとしてもされないとしても下手に一致して着色されると 32905 履歴展開の着色が単語着色で上書きされてしまってそれはそれで分かりにくい。 32906 やはり履歴展開が起こる場合には履歴展開の着色が有効になっていて欲しい。 32907 履歴展開は時に破滅的な結果を齎すのでこれが上書きされるのは避けたい。 32908 [a[! のパターンに関しては現在構文レベルでも判定できていないし、 32909 閉じる ] を見るまで分からないのでこれは相当先読みしないと判定できない。 32910 従って将来的に構文的にも対応することはないと思われる。 32911 従って [a[! のパターンで履歴展開が有効になるケースは取り敢えず無視して良い。 32912 32913 2020-03-27 32914 32915 * decode: 大量貼り付け高速化に関連する問題の修正 [#D1302] 32916 32917 * fixed: bash-4.1 で日本語を入力すると謎の空白が入ってしまう。 32918 以前はこの現象はなかった筈。UTF-8 decode を調べたが特に問題はない。 32919 ble-decode-key で受信しているキーの列にも問題は見られない。 32920 どうも batch-insert で変な空白が追加されている様子である。 32921 →ble/util/chars2s の問題であるという事が判明した。 32922 →分かった。join する所のエスケープを間違えていた。修正した。 32923 32924 * fixed: bash-4.3 で途中までしか入力できない。 32925 nonblocking-read の結果が空になっている。 32926 うーん。何とそもそも builtin read で一文字も読めていない? 32927 →builtin read を実行したら 142 になって何も入っていない。 32928 そして実際にはデータを読み終わっている様子である。 32929 32930 →実際に試してみると bash-4.3 以下では 32931 timeout した時には読み取ったデータは失われてしまう様だ。 32932 これの回避方法は存在するだろうか。うーん。取り敢えず… 32933 1 byte ずつ読み取る方法で実装してみる事にした。 32934 →実装した。動作している。まとめて読み取るのよりは遅いが、 32935 bind -x 経由よりも格段に高速である。 32936 32937 * fixed: bash-4.3 で .check-abort に失敗している。 32938 何故か無引数で ble-decode/.hook が呼び出されている様である。何故? 32939 先ず FUNCNAME を調べる。 32940 32941 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1073 (ble-stackdump) 32942 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:4634 (ble-decode/.hook ) 32943 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (ble-decode/.hook 54) 32944 32945 つまり再帰的な ble-decode/.hook の時に引数を渡すのを忘れている? 32946 % 調べるとどうやら ble/array#pop が動作していない様である。 32947 % 手で実行すると動作しているように見える。 32948 % と思ったら ble/array#pop の使い方を誤っていただけだった。動いている。 32949 違った、その前に既に _ble_decode_input_buffer に大量の空文字列が登録されている。 32950 32951 →分かった。これは書き換えた時に split-words が split になってしまっていた。 32952 32953 * fixed: bash-4.3 nonblocking の読み取りで空白が全て消滅している。どういう事だろう。 32954 と思ったら分かった。これは IFS である。一文字しか読み取らない場合でも IFS= は必要だ。 32955 IFS= を設定したら直った。 32956 bash-4.0 で 10k 文字入力したら遅いが動かない事はない。 32957 32958 * resolved: bash-4.4 で試したら先ず nonblocking-read でブロックしている気がする。 32959 少なくとも progress-bar が止まってしまっている。 32960 動作確認する必要がある。それから nonblocking-read は bash 3.* では使えない。 32961 少数の read -t に対応していないので。 32962 32963 local time1=$EPOCHREALTIME 32964 local time2=$EPOCHREALTIME 32965 bc -l <<< $time2-$time1; echo N=$N 32966 32967 確認してみた所、先ず ble/array#push に 1.0s かかっている。 32968 うーん。これは後で対策を考える必要がある。 32969 更に、decoding... が表示されるまでに時間がかかる。 32970 然し、一応待っていれば動作はする様である。 32971 因みに2回目の貼り付けではそんなに時間がかかっていない? 32972 不思議である。これは何だろうか…。 32973 32974 * ble-decode/.hook 内のボトルネック 32975 array#pop は一瞬で終わっている。 32976 chars=("${...[@]}" "$@") が 13 秒もかかっている。何故? 32977 更に分割すると chars=("${input_buffer[@]}") だけでも13秒かかっている。 32978 うーん。関数経由で chars に代入する様に変更したら 0.4s に減少した。 32979 然し、push の方は 0.9s からこれ以上縮まりそうにない。 32980 これは諦める事にする。 32981 32982 * ble-decode/.hook 内の progress bar (nonblocking-read) が全く動かない 32983 と思ったがこれは上と全く同じ原因だった。0.9s の push を縮めるしかない。 32984 32985 * resolved: bash-4.4: 更に processing input が開始するまでにも時間がかかる。 32986 これも配列のコピーが原因だった。91s かかっていたのが 0.86s にまで短くなった。 32987 32988 * resolved: bash-4.0: constructing text が終わった後が長い。止まっている。 32989 もしかしてそもそも editor 起動が有効になっていない可能性? 32990 CPUはずっと走っている。→ずっと経ってから確認したら editor が起動していた。 32991 後でCPU時間を確認すると13m走り続けていた様だ。 32992 何が起こっていたのだろうか。 32993 32994 と思ったら char2s の中でとんでもない事をしていた。 32995 毎文字 join していた。ループの外に出した。 32996 然し、それを修正しても大分時間がかかっている。何故。 32997 32998 うーん。どうも配列に格納したデータを読み取ると物凄く時間がかかる様だ。 32999 文字列に 0x80 未満の文字を格納してそれを引く様にしたら一瞬で起動した。 33000 14s かかっていたのが 0.245s である。 33001 33002 % debug1=$' \x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F' 33003 % debug1=$debug1$'\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F' 33004 % debug1=$debug1$'\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F' 33005 % debug1=$debug1$'\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F' 33006 % debug1=$debug1$'\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F' 33007 % debug1=$debug1$'\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F' 33008 % debug1=$debug1$'\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F' 33009 % debug1=$debug1$'\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F' 33010 % function ble/util/chars2s.impl { 33011 % local -a buff=() 33012 % local c i=0 33013 % for c; do 33014 % if ((c<0x80)); then 33015 % ret=${debug1:c:1} 33016 % else 33017 % ble/util/c2s.cached "$c" 33018 % fi 33019 % buff[i++]=$ret 33020 % done 33021 % IFS= builtin eval 'ret="${buff[*]}"' 33022 % } 33023 33024 色々 benchmark して調べたがどうも遅い原因の一つは大量の引数を抱えた関数から 33025 子供の関数を呼び出すのが思いという事のようである。上で改善したのは純粋に 33026 文字列にした事で高速化したのではなくて関数呼び出しが減った事による効果である。 33027 再度計測し直してみた所、寧ろ文字列の index を用いて参照すると遅くなる様である。 33028 文字列の長さを工夫すればもう少し高速化できるのかもしれないが面倒なので考えない。 33029 33030 2020-03-24 33031 33032 * ble-bind: Unknown widget `-'. という表示が出る (reported by dylankb) [#D1301] 33033 https://github.com/akinomyoga/ble.sh/issues/46 33034 33035 調べてみると未対応の rlfunc があるとこれが必ず出る様だ。 33036 取り敢えず修正する必要がある。未対応です、という表示が出るのが望ましい。 33037 33038 或いは無害な物に関しては nop を出して無視する。 33039 調べたが skip-csi-sequence については nop では駄目である。 33040 そもそも bind しては行けない。 33041 無害な物に関しては nop に束縛するのではなくて何にも束縛しない。 33042 33043 * arrow-key-prefix は何かと思って bash のソースを確認したら、 33044 次の文字を読み取って ABCD だったらカーソルキーの既定動作に 33045 dispatch するという感じの物だった。 33046 恐らく SS3 A/B/C/D だとか ESC A/B/C/D だとか、 33047 そう言った物に一括で束縛する為の物なのだろうと思われる。 33048 これは無視ではなくて未対応とするべき。 33049 というより新しく widget を作っても良いのかもしれない。 33050 33051 * tty-status は ioctl(TIOCSTAT) を呼び出すらしい。 33052 これは何かと思って検索したら /* generate status message */ 33053 /* simulate ^T status message */ 等という説明が見られる。 33054 FreeBSD/OpenBSD にはあるが Linux にはない機能の雰囲気である。 33055 これは適当に模倣して実装しても良いのかもしれない。 33056 これも取り敢えず未対応という事で良いだろう。 33057 33058 取り敢えずちゃんとエラーメッセージは出るようにした。 33059 次の報告が来た。恐らく emacs-editing-mode と vi-editing-mode 33060 を bind しようとしている /etc/profiles.d/? があるという事だろう。 33061 勝手に変な設定をしようとするものがあるのも考えようだが、 33062 然し、bash 互換を考える上では避けようがないという事なのだろう。 33063 何処かには ble.sh の様に bash の細かい動作に依存する設定があるはずで、 33064 つまり ble.sh の上で他の ble.sh 実装が動くかどうかというレベルの話になる。 33065 少しでも穴があれば動かなくなるという事なのである。 33066 33067 emacs-editing-mode / vi-editing-mode の動作について確認する。 33068 bash で試してみた所によるとこれらは set -o emacs / set -o vi 33069 の設定まで変更する様である。ble.sh ではどの様に対応するべきか。 33070 set -o emacs を変更せずに実行するか。或いは、実際に set -o emacs 33071 を実行する事によって対処するか。もし set -o emacs を使って実装すると 33072 したら実は結構簡単な気がする。然し、default_keymap=emacs 等としていた 33073 場合には set -o vi をしても振る舞いに変化がないという事になってしまう。 33074 そういう意味では default_keymap も一緒に弄ってしまうというのが手なのだろうか。 33075 33076 取り敢えず、ble.sh edit.sh で set -o が変化した時にどう振る舞っているか確認する。 33077 確認した所、set -o emacs/vi が変わった場合には単に ble.sh が動作の基準としている 33078 keymap を切り替えるだけであって、その上で何が動いているかに関しては関知していない雰囲気だ。 33079 33080 * bleopt default_keymap=... を設定した時に reset-default-keymap を実行する様にする。 33081 現在だとこれを実行してもその場では keymap は変化しない様である。 33082 →対応した。何事もなく動作している。意外と呆気ない事だ。 33083 * set -o emacs/vi をどの様に実行するか。 33084 確認したが .check-detach は gexec の後に呼び出されている。 33085 つまり、set -o emacs/vi をコマンドとして実行するか、 33086 或いは、.check-detach で行っているのと同様の操作をその場で実行するか。 33087 後者で実装するのが自然である。 33088 33089 うーん。単純に set -o ... してから以下を実行すれば良いだけ? 33090 ble/decode/reset-default-keymap 33091 ble/decode/detach 33092 ble/decode/attach 33093 33094 * decode: 大量の貼り付けの高速化3 (report by dylankb) [#D1300] 33095 33096 * うーん。ble/util/c2s が遅いのだと考えて高速化してみた。 33097 大分高速化した気がする。然し、緑が 99% になってから、 33098 赤色が表示されるまでの時間は変化していない。 33099 33100 | # A. NUL を unset してから実行 33101 | local index0=$index ret ins 33102 | for ((;index<N;index++)); do 33103 | ((chars[index])) || unset -v 'chars[index]' 33104 | ble/widget/batch-insert.progress 2357 33105 | done 33106 | ble/util/chars2s "${chars[@]:index0}"; ins=$ret 33107 | 33108 | # B. 連続する非零のコード毎に変換を実行 33109 | local p q=$index ret ins= 33110 | for ((p=q;q<N;q++)); do 33111 | if ((!chars[q])); then 33112 | if ((p<q)); then 33113 | ble/util/chars2s "${chars[@]:p:q-p}"; ins=$ins$ret 33114 | fi 33115 | ((p=q+1)) 33116 | fi 33117 | ble/widget/batch-insert.progress 33118 | done 33119 | 33120 | # C. 一文字ずつ変換 33121 | local ret ins= 33122 | while ((index<N)); do 33123 | ble/util/c2s "${chars[index]}"; ins=$ins$ret 33124 | ((index++)) 33125 | ble/widget/batch-insert.progress 33126 | done 33127 33128 * decode phase も実は簡略化できる筈。 33129 receive + decode を read & printf ' に変換するのである。 33130 と思ったが本当だろうか。整数に変換する必要があるが、 33131 それを高速に実行する事は可能だろうか。 33132 33133 もうひとつ気になるのは screen 越しだと 33134 bracketed paste mode が有効になっていない気がする。 33135 或いは bracketed paste の終了がちゃんと受信されていない? 33136 まあ、これに関しては別に考える事にすれば良い気がする。 33137 33138 * そうすると processing input... の部分が気になる。 33139 うーん。これは _ble_decode_char__hook を使ってループを回しているのが悪い。 33140 というか bracketed paste に関しては decode の側で特別に取り扱ってしまって良いのでは? 33141 但し、それによってどれだけ高速化するのかについては疑問が残るが…。 33142 33143 見ていて気付いたが progress bar は 50 文字毎に表示している。 33144 53kB に入力に対しては 1000 回update する事になる。 33145 これが実はボトルネックなのでは。。と思って確かめてみた。 33146 50 から 200 にしたら 10s だったのが 6s に縮んだ。 33147 計算するに 5s 弱が実質の計算時間だったという事。 33148 逆に言えば 5s よりも早くはならない。 33149 33150 さて、decode の側で key の解釈の時に一括で処理する事を考えてみたが、 33151 よく考えてみたら現在は _ble_decode_char__hook に介入しているので、 33152 key の解釈よりも前の段階での介入である。つまり、key の解釈で 33153 一括処理する様に変更しても対して意味がないのである。 33154 33155 _ble_decode_char__hook で本質的に関係する部分だけ抜き出すと。 33156 33157 * ((_ble_debug_keylog_enabled)) の時は一括処理を諦める。 33158 * [[ $_ble_decode_keylog_chars_enabled ]] のときも諦める。 33159 * 次の文字が _ble_decode_Erro の時には処理しない。 33160 33161 これらの元でループ構造は以下の様に単純化される。 33162 33163 | while 33164 | ((ble_decode_char_rest)) 33165 | do 33166 | char=${chars[ichar]} 33167 | ((ble_decode_char_rest--,ichar++)) 33168 | 33169 | ((char&=~_ble_decode_Macr)) 33170 | 33171 | # decode error character 33172 | # if ((char&_ble_decode_Erro)) 33173 | 33174 | if [[ $_ble_decode_char__hook ]]; then 33175 | ((char==_ble_decode_IsolatedESC)) && char=27 # isolated ESC -> ESC 33176 | char を処理する 33177 | fi 33178 | done 33179 33180 うーん。decode.sh の側で "次の文字を読む" という操作を提供しても良い気がしてきた。 33181 その様に実装した。大分高速になった気がする。 33182 33183 * さて、緑から赤に移る時の沈黙は何だろうか。 33184 引数を大量に渡すのに時間がかかっているという事だろうか。 33185 と思ったらそうではないようだ。 33186 33187 文字列の置換処理に時間がかかっている? 33188 33189 X:1584874227.928681 33190 Y:1584874227.929155 33191 Z:1584874227.936170 33192 W:1584874227.942291 33193 N:1584874231.373286 33194 33195 と思ったら違う。この処理に時間がかかっている: chars=(${chars//:/' '}) 33196 もしかしてパス名展開が試みられているという事だろうか。 33197 3秒もかかっている。ble/string#split を使ったら 0.03 にまで短縮した。 33198 33199 X:1584874420.330993 33200 Y:1584874420.367348 33201 33202 * 残っているのは byte を読み取る部分…。 33203 UTF-8 safe な byte を読み取ったらその次の瞬間に一気に読み取って良いのではないか。 33204 然し、UTF-8 safe な byte かどうかの判定で余計に時間がかかってはいけないし、 33205 よく考えたら日本語主体の文章の場合には UTF-8 safe な値はなかなか期待できない。 33206 一応改行は大丈夫だが改行のない文章が大量にやってきた場合はどうするのか。 33207 33208 或いは、LC_CTYPE=C にして一気に読み取ってしまえば良いのかもしれない。 33209 decode に関しても余り深く考えずに一気に実行する? 33210 うーん。システムのエンコーディングと受信のエンコーディングが一致している 33211 時に限るが、そのまま組み立ててしまって良いのではないか。 33212 33213 うーん。取り敢えず実験的に実装してみる事を考える事にする。 33214 33215 受信をする時に問題になるのは NUL を含む文字列は受信できないという事。 33216 中途半端なバイトが含まれる時に ${str::x} の様な処理ができないという事。 33217 mapfile には timeout がないので read に頼るしかない。 33218 33219 * decode は結構時間がかかっている。 33220 というか今思ったが現在の decode の処理は改善できる気がする。 33221 33222 先ず初めに現在の変換時間を計測する。約12.7s 33223 X:1584885577.441244 33224 Y:1584885590.163676 33225 33226 約12.2s 先ず配列に代入してから ble-decode-char を呼び出しているのを、 33227 直接一つずつ ble-decode-char を呼び出す様に変更してみる。殆ど違いはない。 33228 X:1584885521.873851 33229 Y:1584885534.093266 33230 33231 約11.8s 算術式の不要な空白を全て潰してしまうとどうなるか。 33232 これも微妙に短くはなるが本質的な違いではない様に思われる。 33233 X:1584885811.187881 33234 Y:1584885822.967141 33235 33236 約11.0s byte<0x80 だけ特別扱いしたらこう。 33237 X:1584886104.316627 33238 Y:1584886115.267994 33239 | ((byte&=0xFF)) 33240 | ((mode)) && (((byte&0xC0)!=0x80&&(cha0=_ble_decode_Erro|code,mode=0))) 33241 | if ((byte<0x80)); then 33242 | char=$byte 33243 | else 33244 | ((byte<0xF0?(byte<0xC0?(byte<0x80?(char=byte):( 33245 | mode==0?(char=_ble_decode_Erro|byte):(code=code<<6|byte&0x3F,--mode==0&&(char=code))) 33246 | ):(byte<0xE0?(code=byte&0x1F,mode=1):(code=byte&0x0F,mode=2))):(byte<0xFC?(byte<0xF8?( 33247 | code=byte&0x07,mode=3):(code=byte&0x03,mode=4)):(byte<0xFE?(code=byte&0x01,mode=5):( 33248 | char=_ble_decode_Erro|byte))))) 33249 | fi 33250 33251 約11.0s テーブルに入れて見たが速度は変わらない。 33252 よく考えてみたら byte<0x80 だけ特別扱いするのと対して変わらない。 33253 X:1584886995.051122 33254 Y:1584887006.049388 33255 | ((byte&=0xFF)) 33256 | ((mode)) && (((byte&0xC0)!=0x80&&(cha0=_ble_decode_Erro|code,mode=0))) 33257 | ((_ble_encoding_utf8_decode_table[byte])) 33258 33259 約11.0s 完全にテーブルに入れてみても対して変わらない。 33260 X:1584887425.167250 33261 Y:1584887436.189649 33262 | function ble/encoding:UTF-8/decode { 33263 | local code=$_ble_encoding_utf8_decode_code 33264 | local mode=$_ble_encoding_utf8_decode_mode 33265 | local byte=$1 33266 | local cha0= char= 33267 | local stray='cha0=_ble_decode_Erro|code,mode=0' 33268 | ((_ble_encoding_utf8_decode_table[$1&0xFF])) 33269 | _ble_encoding_utf8_decode_code=$code 33270 | _ble_encoding_utf8_decode_mode=$mode 33271 | [[ $cha0 ]] && ble-decode-char "$cha0" 33272 | [[ $char ]] && ble-decode-char "$char" 33273 | } 33274 33275 約10.9s うーん。変数名を少し短くしてみたら微妙に改善した。 33276 X:1584887850.303309 33277 Y:1584887861.235152 33278 33279 約9.9s decode を複数の引数を受け取るように変更したら改善した。 33280 X:1584915662.010331 33281 Y:1584915671.917756 33282 33283 約4.2s 何と ble/array#push を A[i++]= に書き換えたら物凄く高速になった。 33284 結局全体で 5s ぐらいしかかかっていない。40s からの劇的な改善である。 33285 X:1584916592.860743 33286 Y:1584916597.017316 33287 33288 大分改善した。取り敢えずはスクリプト上での 33289 decoder はこれで良しとする。 33290 33291 * もっと巨大なデータを受信した時に外部プログラムを起動して 33292 decode する可能性? 33293 33294 awk を使うか。或いは od を使って上手にできないか。 33295 或いは、printf $'' してから "${str::}" で読み取る手法? 33296 これは UTF-8 依存になるので、UTF-8 の側で処理する? 33297 33298 というか現在の実装だって UTF-8 の側で処理して良い気がする。 33299 33300 例えばこう。 33301 ble/util/printf ret '\x%02x' "$@" 33302 eval "ret=\$'$ret'" 33303 33304 * 問題は 0 をどうするのかという事。 33305 0 は 0 に翻訳するという事で良い。 33306 33307 →0の処理方法について確認しようとしたら微妙。 33308 \xC0\x80 にしたら実は表現できるかもしれないと考えたが、 33309 実際にやってみると二文字に分割されて解釈されている。 33310 文字数のカウントも2文字になっている。 33311 33312 これが意味する所は、bind 経由で受信した 2B 表現も、 33313 bash の中で直接にバイトに変換すると破壊されてしまうという事。 33314 C0,C1 はその意味で特別に処理しなければならないのである。 33315 33316 * そもそも本当に高速になるのか? 33317 これは実験してみないと分からない。 33318 実際に実装してみたが 5.2s である。 33319 寧ろ遅くなっている気がする。 33320 X:1584923880.134245 33321 Y:1584923885.336910 33322 33323 うーん。何だか振る舞いが変である。 33324 わかった。修正した。変数 M を上書きしていた。 33325 33326 改めて計測する。やはり 5.2s である。 33327 X:1584937548.825580 33328 Y:1584937554.059262 33329 33330 その場で printf -v するようにした。 33331 % 5.7s, 5.6s である。計測ミスだった。 33332 % X:1584937775.759084 33333 % Y:1584937781.359048 33334 % X:1584937714.687243 33335 % Y:1584937720.327925 33336 約4.6s になった。高速化している。 33337 X:1584937868.273119 33338 Y:1584937872.934848 33339 33340 元々の s2c の場合の速度を見ると 5.22s だった。 33341 printf の中で index 指定をするのを避けたら 4.85s になった。 33342 ${s:k:1} ではなく ${s:k} を渡すと 5.17s に遅くなる。 33343 長い文字列を渡しているのが遅い原因だろうか。 33344 %d を '%d' に quote したら 4.86s である。誤差の範囲内。 33345 33346 さて、元の実装の速度が 4.1s であったから、 33347 これは寧ろ遅くなっている。 33348 printf -v で数値を取り出すのは自前で計算するよりも遅いという事。 33349 33350 そもそも何故この実装を考えたのかというと、 33351 文字コードを抽出する事を想定していなかったから。 33352 そのまま文字列を構築してそれをファイルに出力するという想定だった。 33353 33354 取り敢えず実装は此処に残して置く事にする。 33355 33356 | function ble/encoding:UTF-8/decode2 { 33357 | local C=$_ble_encoding_utf8_decode_code 33358 | local M=$_ble_encoding_utf8_decode_mode 33359 | local S='e=_ble_decode_Erro|C,M=0' 33360 | 33361 | local -a B; B=("$@") 33362 | local -a A=() 33363 | local a=0 e= c= 33364 | 33365 | local -a stop=(); stop[0]=1 stop[192]=1 stop[193]=1 33366 | local i N=$# 33367 | for ((i=0;i<N;)); do 33368 | while ((i<N)) && ((stop[B[i]]||M)); do 33369 | e= c= 33370 | ((_ble_encoding_utf8_decode_table[B[i]&255])) 33371 | [[ $e ]] && A[a++]=$e 33372 | [[ $c ]] && A[a++]=$c 33373 | ((i++)) 33374 | done 33375 | 33376 | ((i<N)) || break 33377 | 33378 | j=$i 33379 | while ((j<N)) && [[ ! ${stop[B[j]]} ]]; do ((j++)); done 33380 | 33381 | local ret 33382 | ble/util/sprintf ret '\\x%02x' "${B[@]:i:j-i}" 33383 | eval "local s=\$'$ret'" 33384 | if [[ $s ]]; then 33385 | local k K=${#s} 33386 | for ((k=0;k<K;k++)); do 33387 | ble/util/s2c "${s:k:1}" 33388 | A[a++]=$ret 33389 | done 33390 | fi 33391 | i=$j 33392 | done 33393 | _ble_encoding_utf8_decode_code=$C 33394 | _ble_encoding_utf8_decode_mode=$M 33395 | ((a)) && ble-decode-char "${A[@]}" 33396 | } 33397 33398 * done: s2c の実装を見直す。 33399 33400 * done: うーん。bind で -s を経由して受信している時には、 33401 read を直接実行すると変な事になるのではないか。 33402 つまり、read を実行するのは通常文字の直後である必要があるのでは。 33403 取り敢えず、-s 経由で受信される可能性のある文字について init-bind で確認する必要あり。 33404 -s 経由の受信で一番最後の文字以外の文字については read-nonblock を実行してはならない。 33405 33406 取り敢えず対応した。また今後の変更の為に init-bind.sh に説明を書いた。 33407 本当は init-bind.sh の側で変数などを提供するのが良いのかもしれないが、 33408 面倒だし、今後マクロが追加される事があるのかも不明なので取り敢えず放置する。 33409 本当は他の人が将来的に編集する可能性なども考えると良くないのかもしれないが。 33410 33411 2020-03-14 33412 33413 * rps を設定している時に変な文字で右余白が埋められている…。 [#D1299] 33414 一体これは何だろうか。後で調べる必要がある。 33415 33416 これは screen-4.99 のバグである。 33417 33418 | うーん。怪しいと思ったのは ble/textmap#update の中の 33419 | eraser の生成部分であるが確認してみると変な事は起こりそうにない。 33420 | というより場合分けが ech があるかないかで決まっている。 33421 | うーん。端末の方の ECH が壊れている可能性? 33422 | 33423 | mintty でも再現するからこれは screen/contra の問題ではない。 33424 | mintty の場合には空白の様に見えるが実際に選択しようとすると 33425 | 普通の空白と違って選択する事ができるのでこれはやはり何か変だ。 33426 | 単に ech しただけではやはりこの変な現象は起こらない。 33427 | とすると改行がある場合のセル内容を書き換えている別の箇所で問題が起きている? 33428 | 33429 | →うーん。空白を挿入した場合には特に問題は起こらない様だ。 33430 | やっぱり何かが ECH で変? 然し、空白挿入+ECH の場合や、 33431 | ECH+空白挿入 の場合には問題は発生しない。 33432 | だとすると問題の謎の文字はこれらの直前に描画されていて、 33433 | ECH では消えないけれども空白によっては上書きされる、という事? 33434 | 33435 | ble/textmap#update では _ble_textmap_glyph に値を代入している。 33436 | これを参照している箇所は edit.sh ble/textarea#update-text-buffer 33437 | の変更文字の置き換えだけである。 33438 | layer:plain/update はどうしているのかと思ったら独自に値を設定している。 33439 | ここでは改行は _ble_term_el を直接使っている。 33440 | うーん。調べたがやはり変な事は起こっていない気がする。 33441 | 33442 | screen の外では再現しない。と思ったら実は以下で再現すると分かった。 33443 | printf 'A\e[107m\e[X\n' 33444 | 33445 | これは ble.sh のバグではないという事になる。contra のバグであろうか。 33446 | 取り敢えず screen-4.7.0 では発生しないという事を確認した。 33447 | mintty x screen-4.99 でも再現する事を確かめた。 33448 | mintty だけでは再現しない。 33449 33450 * complete: menu-filter を off にすると変な事になる [#D1298] 33451 https://oilshell.zulipchat.com/#narrow/stream/121540-oil-discuss/topic/.23257.20typing.20past.20the.20last.20column.20(interactive.20features) 33452 33453 menu-filter が無効の時は 1. menu filter 着色はしない。 33454 2. menu から候補を拾う機能は off にしておくべき? 33455 或いは、前回の menu を表示した時からカーソル位置が変化していない時にのみ使う。 33456 これは後で対応しなければならない。 33457 33458 というより menu から候補を拾う時に menu-filter を実行すれば良いのではないか。 33459 と思っていざ修正しようとしたら既にそういう実装になっていた。 33460 但し、menu-filter が有効になっているかの判定が足りていなかったのだ。 33461 2行修正(complete_menu_filter の判定追加)しただけで治ってしまった。 33462 33463 2020-03-13 33464 33465 * decode: 大量の貼り付けの高速化2 (report by dylankb) [#D1297] 33466 Ref #D1296 #D1293 33467 33468 やはり未だ遅い。具体的に計測してみた。dylankb の報告によると 33469 最初に decode が始まるまでが長いという事であるが。 33470 手許で計測している範囲では以下の様な構成である。 33471 33472 recv 9sec 33473 decode 10sec 33474 process 50sec 33475 show 70sec 33476 33477 別に受信にはそんなに時間はかかっていない。 33478 show に関しては editor に置き換えればそんなに時間はかからない。 33479 つまり目下の所のボトルネックは process である。 33480 色々弄って計測してみる事にする。 33481 33482 o (20sec短縮) 文字列に追記する様にしていたが配列に変更してみた。 33483 この時 process は 30sec だった。受信バイト数は 53184 bytes であった。 33484 もう一度貼り付けてみて process の間に速度低下が見られるか確認する。 33485 33486 process の間の速度を観察すると実は寧ろ高速化していく。 33487 つまり残りのバイトを管理している構造がボトルネックになっている気がする。 33488 $1==126 (~) のチェックをできるだけ早く行って見る事にしたが、 33489 30sec だった。全然速度は変わっていない。 33490 batch-insert の時間は 8sec だった。これは殆ど無視できる。 33491 33492 o (3sec短縮) 配列の容量を時々縮める様にしたら 27sec になった。 33493 多少は効果があるのかもしれないが誤差の範囲内である。 33494 33495 o (17sec短縮) ble-decode-char で set -- 及び shift ではなくて 33496 を使う様に変更したら一気に 10sec にまで縮んだ。 33497 コードを整理した。今後はこれを使う事にする。 33498 33499 現在は以下の様になっている。 33500 33501 recv 9sec 33502 decode 10sec 33503 process 10sec (bracketed-paste) 33504 insert 10sec (batch-insert) 33505 show 70sec 33506 33507 * done: recv の過程を表示する様にする。 33508 特に大量のデータを受信した時に表示すると良い。 33509 decode_abort_char によるチェックはどのタイミングでするか? 33510 input_buffer に対する検査を行っている。 33511 33512 と思ったが recv の途中では decode_abort_char を受信できない。 33513 パイプに流し込まれた全てのデータを取り出さないと 33514 ユーザが中止の為に入力した文字は受信できないのである。 33515 33516 実装してみたが何だか変だ。 33517 →色々修正した。動く様になった。こんな所だろう。 33518 33519 * fixed: 何故か2回目以降の貼り付けが物凄く遅い。 33520 と思ったら editor を起動する時に term/leave, 33521 enter を実行しなければならないのだった。 33522 直した。 33523 33524 * done: batch-insert に関しても大容量の場合には 33525 progress を表示する事にした。 33526 33527 2020-03-12 33528 33529 * bracketed-paste: やはり貼り付けに N^2 の時間がかかるのは何だか変な気がする [#D1296] 33530 33531 1 先ず batch-insert は改行を含んでいるのだろうか。 33532 →調べてみた所、どうも batch-insert が全く呼び出されていない。 33533 33534 うーん。has-input の判定が間違っている。 33535 恐らく input_buffer, char_buffer がある前は動いていたが、 33536 buffer する様になってから動かなくなったのだろう。 33537 然し、ble_decode_char_rest があればちゃんと has-input になる筈。 33538 ということはそもそもこの判定にすら達していない? 33539 33540 →一文字ずつ入力している時にはちゃんと到達しているが、 33541 貼り付けをした時には全然達していない。 33542 と思ったが分かった気がする。bracketed paste である。 33543 33544 * fixed: どうも bracketed paste で受信した文字列を貯める所が遅い様だ。 33545 実際に文字を挿入する所ではそんなに時間はかかっていない。 33546 →どうも paste_end の判定部分の気がする。 33547 と思って判定を追加してみたら大分高速化した。 33548 33549 * fixed: 然し、今度は self-insert にかかる時間の方が気になる。 33550 試してみると emacs の方では大分高速である。 33551 うーん。改めて vi でやってみるとやはり遅い。 33552 emacs の方では一文字ずつ挿入するのを諦めている? 33553 ちょっと調べてみる事にする。emacs は batch-insert を用いている。 33554 vi_imap が self-insert を使っているのが遅いのである。 33555 文字数が多い場合には vi_imap でも batch-insert を使う様にするか。 33556 というか何で始めから batch-insert では駄目だったのだろうか? 33557 33558 うーん。始めの実装は #D0639 にある。特に記述はない。 33559 この議論 #D0683 は余り関係ない。 33560 何故か #D0720 LASTWIDGET の実装時に何か修正している? 33561 ここの議論を読むと self-insert を拡張して同時に文字を挿入等と書いているので、 33562 実はこの時点では batch-insert が存在していなかった? 33563 調べてみると batch-insert が実装されたのは #D0849 である。 33564 という事は、恐らく batch-insert に対応した時に更新を忘れていたか、 33565 そのまま置き換えても問題ないか判断がつかなかったから放置された。 33566 33567 取り敢えず vi_imap でも batch-insert を使う様に変更してみる。 33568 またテストとして imap repeat が batch-insert でも意図通りになるか確認する。 33569 →ちゃんと \C-c3a<paste>\C-[ で意図した通りに繰り返される。OK 33570 vi_nmap での実装も vi_imap の実装を最終的に呼び出している。OK 33571 33572 2 改行がある度に構文解析をしているという可能性はないか? 33573 上の対処でかなり高速になったので、構文解析を無駄に実行しているという可能性はない。OK 33574 33575 報告者の様子を見るとそもそも decoding というのが表示されるまでに時間がかかる? 33576 多分、結構遅いホストを使っているという事なのだろうと思われる。 33577 そうだとしても多少は高速化出来ないものだろうか。 33578 decoding というのが表示されるまでに実行するのは単に input buffer に貯めるだけの筈。 33579 33580 3 うーん。input_buffer に貯めるという部分はこれ以上の高速化のしようはない気がする。 33581 律速はスクリプトの側ではなくて readline の側にあると考えてよいのではないか。 33582 分からないが取り敢えずそう想定して良い気がする。 33583 33584 すると高速化の余地があるのは結局 bracketed-paste における終了条件だけである。 33585 33586 * 大量のテキストを貼り付けた時の動作 (suggested by dylankb) [#D1295] 33587 https://github.com/akinomyoga/ble.sh/issues/45 33588 33589 * 幾つか確認をしたが結局 C-x C-e を自動で呼び出す様に変更する事になる気がする。 33590 edit-and-execute をそのまま呼び出してしまって良いのだろうか。。 33591 然し、よく考えると edit-and-execute を実行するとしても、 33592 受信したバイト列を使って内容を編集してその後でエディタを起動する必要があるのでは。 33593 33594 或いはそれ自体を別のプログラムで実行するという可能性? 33595 例えば awk の方が多少高速に実行できるかもしれない。 33596 と思ったがどうだろう。微妙である。 33597 33598 何れにしても batch-insert に介入を行う。 33599 →と思ったが batch-insert で全て処理されると保証できるのか? 33600 batch-insert よりも後のユーザ入力が失われてしまう事になる。 33601 それらも全て処理した上でエディタを起動しなければならない。 33602 33603 うーん。取り敢えず batch_insert_limit という設定名は変える。 33604 挿入操作の所々で batch_insert_limit の制限をチェックする事にする。 33605 →取り敢えず暫定的に edit_capacity, edit_overflow としている。 33606 33607 x fixed: insert-word が曖昧候補に対して動作していない。 33608 確認してみたがどうも曖昧の種類を a から amA に拡張した時に 33609 変更を忘れていたという事の気がする。 33610 恐らく意図的に mA に対しては実行しないという事ではないと思われる。 33611 実際に self-insert に於いてはちゃんと ramA に対してテストしている。 33612 insert-word でも ramA に対して適用する様に書き換えた。 33613 33614 * done: 取り敢えず discard については実装したと思う。 33615 * done: rename replace-limited 33616 * done: replace-limited と adjust 云々はくっつける。 33617 33618 x fixed: edit-and-execute ではコマンドを灰色にして表示するべき。 33619 或いはコマンドを表示しない様に隠すべき。 33620 取り敢えず灰色にして表示する方向。 33621 33622 * done: edit_overflow=truncate も実装したい。 33623 それから edit_overflow=editor も実装したい。 33624 然し、このチェックは一体何処で実行すれば良いだろうか。 33625 というか edit-and-execute は編集内容を表示したのだったか。 33626 33627 先ず初めは truncate を実装する事にする。 33628 何処でチェックを入れるべきだろうか。 33629 batch-insert の直後でチェックする? 33630 然し、それだと通常の操作で truncate した時に適用されない。 33631 33632 全ての入力の後に処理するのは非効率的だ。 33633 なので描画のタイミングの直前ぐらいでチェックするのが良い気がする。 33634 33635 * done: 処理が重くなるのを防ぐ為には batch-insert 33636 でも適宜 truncate するのが良い。 33637 →その様にした。 33638 33639 o ok: truncate をテストする必要がある。 33640 truncate は何となく動いている気がする。 33641 33642 x fixed: discard に関しては挿入できる所までは挿入する筈なのに 33643 限界に達する時には何も挿入されないという事態になっている。 33644 何故だろうか。.replace-range が動いていない気がする。 33645 → inslimit を使って制限する所を iend-ibeg で制限していた。 33646 元々 inslimit を inslimit = max(inslimit, iend-ibeg) と書こうとして、 33647 そのまま次の操作と融合して変な記述になっていた。修正した。 33648 33649 * done: 次に実装するのは editor である。 33650 簡単に実装した。これで本当に動くのだろうか。 33651 33652 * ok: editor をテストする 33653 取り敢えず動いている気がする。 33654 コマンドラインに何も表示しないのは寂しいので 33655 コメントで範囲を超過したというメッセージを残す事にした。 33656 33657 * done: 設定変数 editor を追加する 33658 blerc / wiki.ja / wiki.en 33659 33660 * done: 設定変数 x 2 33661 * done: 設定変数 x 2 in wiki ja 33662 * done: 設定変数 x 2 in blerc 33663 * done: 設定変数 x 2 in wiki en 33664 33665 * done: 後、履歴に巨大なデータが残るのも困る。 33666 history_limit_length という設定変数も追加したい。 33667 実装した。説明も追加した。 33668 33669 * done: エディタの起動に失敗した場合はどうなるのか。 33670 truncate した方が良いのではないか? 33671 →その様に実装した。 33672 33673 * done: truncate 等する時に特殊モードを抜ける。 33674 truncate する時にも mark や ind などがずれるので 33675 auto_complete や nsearch 等の様々なモードで変な事が起こりそうである。 33676 それを避ける為には特別のキーを発行してそれで truncate を処理するという手もある? 33677 例えば content_truncate もしくは content_editor 等の様に。 33678 →或いは truncate が起こったら truncate を実行してから 33679 content_truncate または content_editor を呼出して通知するという事にする。 33680 33681 これは後で実装する事にする。 33682 →実装する。実装した。動いている。 33683 と思ったが何か変な気がする。 33684 33685 isearch の途中にこれが発生したら何が起こるのか。 33686 うーん。isearch が強制終了する? それだけなら良いが、 33687 isearch の途中で editor が起動するというのは変である。 33688 editor が起動する条件を変更するべきなのではないか。 33689 というか edit-and-execute だって、vi_nmap では違う振る舞いをするべきなのでは。 33690 色々考えると、line limit というキーではなくて "キャンセル" 的なキーを実装して、 33691 更に元のモードによっては edit-and-execute は実行しないという様にする必要があるのでは。 33692 33693 % と思ったが、その場でそれを実行することはできるのだろうか。 33694 % つまり queue に溜まっているキー入力に先立って処理する事は可能だろうか。 33695 % あと描画のタイミングで処理するというのも変である。 33696 % と思ったが decode.sh の中に直接チェックを書き込むのも変だし、 33697 % EPILOGUE 辺りに書き加えるのが正しい気がする。 33698 % →実装を確認してみたが ble-decode-key を呼び出せば 33699 % その場で実行する様になっている。 33700 % つまりこれに関しては気にしなくても良い。 33701 33702 改めて keymap を観察する。うーん。read 等でも 33703 edit-and-execute が発生すると困る。 33704 色々考えるにこの edit-and-execute の呼び出しは、 33705 寧ろ keymap の上で実行するべきの気がする。 33706 33707 safe, emacs, read, vi_imap, vi_cmap, vi_nmap で対応した。 33708 isearch, nsearch, lastarg, yankpop では握り潰すのが良い気がする。 33709 vi_smap, vi_xmap, vi_omap, vi_digraph では何も処理しない (エラー)。 33710 menu menu_complete auto_complete dabbrev でも握り潰す。 33711 取り敢えず全ての keymap に対して処理は書いた。 33712 33713 結構書き換えてしまったので改めてテストする必要がある。 33714 33715 o vi_imap, emacs では動いた。 33716 x fixed: read で動いていない。何故? 33717 と思ったが EPILOGUE を呼び出していないので当然といえば当然。追加した。 33718 x fixed: 今度は syntax で assertion が火を吹いている。何故。 33719 _ble_edit_str を直接編集すると起こる種類の問題である。 33720 然しその様な事はしていない様に見える。 33721 →と思ったら _ble_edit_str に直接代入していた。修正した。 33722 x fixed: vi operator が全く動かなくなっている何故? 33723 つい直前までは動いている。という事はまた何かを破壊した? 33724 不思議だ。何も破壊していない気がする。 33725 →これは vi_omap の __default__ が line_limit を受信して、 33726 それによって omap を抜けているのが問題だった。 33727 __line_limit__ は無視する事にした。 33728 x fixed: vi_nmap では一応動いているが truncate の時に 33729 vi_imap に落ちるのは分かりにくい。 33730 edit-and-execute を実際に行う場所で vi_imap に落ちる様に変更した。 33731 x fixed: 2文字以上の組み合わせの keyseq が使えなくなっている。 33732 これは全然駄目だ。その様に考えると __line_limit__ は、 33733 mouse と同様に keyseq には関与するべきではないのでは。 33734 と思ったが、処理が重くなるのも嫌なので長さの検査をしてから 33735 __line_limit__ を呼び出す方が良い気がしてきた。 33736 →その様に変更した。 33737 o ok: 取り敢えず read, vi_nmap は確認した。 33738 x fixed: vi_cmap で表示が変になっている。うーん。 33739 これはどうしたら良いのか。 33740 →分かった。 .newline していたのが行けない。修正した。 33741 x fixed: vi_digraph では無視する様にしないといけない気がする。 33742 (実際に呼び出される事があるのかどうかは不明だが) 33743 33744 今の所、emacs, vi_[inc]map, read は動作確認した。 33745 isearch, vi_omap でも問題ないことを確認した。 33746 safe は emacs と本質的に同じなので気にしなくて良い。 33747 vi_digraph にも対応した。vi_[sx]map はまあ大丈夫だろう。 33748 握りつぶしている物に関しては基本的に問題ない筈。 33749 33750 * done: 既定値は editor で良いのだろうか…。 33751 いきなり editor が起動すると混乱の元なのではないか。 33752 或いは none の方が良いのでは? うーん。取り敢えず none にする。 33753 33754 * test: test-core.sh がエラーを吐いている (reported by andychu) [#D1294] 33755 https://oilshell.zulipchat.com/#narrow/stream/121540-oil-discuss/topic/.23257.20typing.20past.20the.20last.20column.20(interactive.20features) 33756 33757 調べたら ble/string#escape-for-bash-specialchars の仕様変更による物である。 33758 3番目の引数に flags を受け取る様になって、そこに b を指定した時にだけ 33759 brace の quote を行うという様に変更されている。反映した。 33760 更に言うと test-core.sh という名前も古い。test-util.sh でなければならない。 33761 33762 * decode: modifyOtherKeys の時の abort [#D1293] 33763 C-\ で abort するという話を書いたが。 33764 よく考えてみると modifyOtherKeys にしている時には動かないのでは。 33765 33766 さて、modifyOtherKeys にしていると C-c を押しても 3 は決して入って来ない。 33767 ble-decode-key の直前で待ち伏せしなければならない。 33768 然し、現在の実装だと ble-decode-key の結果はキャッシュされていないので、 33769 其処で待ち伏せする事にするとそれより前の処理は全て実行された後になる。 33770 それだとキャンセルした事にならない。 33771 或いは key の計算と実行を切り離して key を検査してから実行を行うべきか。 33772 33773 然し、確認してみて思ったが検査はやはり byte のレベルで実行しなければならない。 33774 実際に char のキャッシュも byte のレベルでしかキャンセルしない様になっている 33775 (唯、制御文字に関しては decode を通しても変化しないという前提はある気がする)。 33776 33777 その様に考えると、decode_abort_char に複数のバイトから為るシーケンスを 33778 登録できる様にしなければ動く様にはならないという気がする。 33779 33780 うーん。decode_abort_seq なる物を定義して byte を受け取った時に判定する。 33781 然し、それだとユーザが端末ごとに正しい値を設定しなければならない。 33782 更に modifyOtherKeys なので理解するのが難しい。 33783 やはり自動的に検出する様にしなければならない。 33784 33785 うーん。可能なシーケンスは実は有限個しかない。 33786 と思ったが本当だろうか。chars と bytes に跨って記録される事もあるのでは。 33787 然し、シーケンスの到着のタイミング等を考えるとそれが起こるとは考えにくい。 33788 取り敢えずは bytes に全て含まれている場合を考える事にする。 33789 33790 CSI の表現で 2 種類ある。> の有無で 2 種類ある。CSI >? 27 ; 5 ; code 33791 27~ 形式 と u 形式で 2 種類ある。 33792 33793 →これについては実装した。 33794 33795 2020-03-08 33796 33797 * vi: vi-commandn/nth-column の算術式がおかしい (reported by andychu) [#D1292] 33798 https://github.com/oilshell/oil/issues/620#issuecomment-596189684 33799 33800 osh -n で見つかったバグである。後で全体的に確認する必要があるという気がする。 33801 多分、osh -n は一番最初に見つかった物しか報告していない。 33802 →やはりそうだった。もう一つバグを見つけた。 33803 然し殆どは ((${prefix}xx=...)) の形式だった。 33804 33805 2020-02-27 33806 33807 * 2020-02-06 quoted-insert で制御文字を入力できる様にする [#D1291] 33808 mintty で modifyOtherKeys を有効にしているので 33809 quoted-insert で C-t 等の基本的なキーですら修飾されている。 33810 つまり、制御文字を入力する事ができない。 33811 33812 然し、本当に modifyOtherKeys を入力したい場合や、 33813 或いは、本当に端末が送ってくる内容を知りたい場合もある。 33814 その場合には勝手にキー入力をいい感じに翻訳されると困る。 33815 然し、やはり制御文字を入力したいという事がある気がする。 33816 33817 C-q と C-v で二種類あるのだから片方に別の物を割り当てるという手もある。 33818 やはり特殊なキーシーケンスを取得するという場合よりも、 33819 C-q 等の特殊文字を入力する場合の方が多い。C-x に対しては、 33820 やはり C-x が挿入される様にするべきである。しかしそれを実行するには 33821 key を decode しなければならない。するとその他の key に関しては 33822 それを発生させたシーケンスを復元するか記録するかしないといけない。 33823 記録するとしても Meta が関わってきた場合には更に複雑になってしまう。 33824 或いはキーを完全にデコードする前に判定する事は可能だろうか、 33825 と思ったが CSI u で送られてくる以上は最後まで見ないと分からない。 33826 33827 a 或いは寧ろ予め用意したシーケンスをそのまま返す様にしてしまう? 33828 然し、それはそれで混乱の元である。特別なキーに対して実際の端末と異なる物を挿入すると、 33829 ユーザが端末のテストなどをする際に変な事になってしまう。 33830 b 或いは各キーに対してどのシーケンスが使われたかという情報を decoder 側で全て記録する? 33831 然し、それをするぐらいであれば現在のキーに対応するシーケンスだけ取得できる様にすれば良い。 33832 33833 結局現在のキーを構築するに至ったキーの列を記録する事にした。 33834 取り敢えず動いているので満足である。 33835 33836 RLogin は ! 等に対して S-1 等を送信して来る。単に S- を除去するだけでは駄目。 33837 S-数字の時には日本語キーボード配列を想定して適当に記号に変換する事にした。 33838 但し、S-数字 にしか対応していない。純粋は記号キーについては補正していないが、 33839 実は RLogin は既定では記号キーは修飾しない設定になっている。 33840 うーん。端末識別をもう少し詳しくしてみる事にした。 33841 33842 * complete: clear menu on discard-line (reported by animecyc) [#D1290] 33843 https://github.com/akinomyoga/ble.sh/issues/44 33844 これは意図した振る舞いである、と書こうとしたが振る舞いが変である。 33845 ソースコードを見ると history.onleave 経由で menu/clear 呼び出される筈である。 33846 実際に確かめてみると呼び出されてはいるが既に menu が非アクティブになっている。 33847 最初からアクティブになっていない可能性? と思ったがちゃんとアクティブになる 33848 コードパスを通過している。 33849 33850 と思ったら edit.sh 側に active を解除するコードがある。 33851 というより正に .newline の中で明示的に clear している。 33852 確認するとこれが追加されたのは aae8b264 である。 33853 これは menu-filter 着色を解除して最後に行内容を表示する為の処置である。 33854 insert-newline を呼び出す時に内部で再描画を行うので。 33855 33856 2020-02-19 33857 33858 * term: menu が正しく消去されないとの事 (reported by killermoehre) [#D1289] 33859 https://github.com/akinomyoga/ble.sh/issues/42 33860 33861 これは terminfo と termcap で同じ名前の項目 dl があった所為だった。 33862 二文字の terminfo で termcap と異なる物は注意して調べた方が良い。 33863 33864 ri: OK, el: OK, il: OK, ed: 駄目, dl: 駄目 33865 一方で ed, dl に対応する termcap 側の cd 及び DL は曖昧ではない。 33866 これらに関しては terminfo/termcap 両方対応している環境では 33867 cd, DL を確認する事にする。 33868 33869 % もし ed, dl で terminfo 側を優先させる環境があったとすれば 33870 % それはそれで問題になる気がするが仕方がない。 33871 % と思ったが、DL 及び cd を使っている限りは問題が発生しないので、 33872 % これでちゃんと解決できている。OK 33873 33874 * term: support contra SPD [#D1288] 33875 contra で SPD(3) 等を実行してもカーソル移動が破壊しない為に 33876 terminfo cache の書き換え。CU[UDFB] の代わりに [HV]P[RB] を使う。 33877 33878 * 2020-02-14 時々 bind が壊れる現象があって何かと思っていたら [#D1287] 33879 TERM を変更すると Bash は inputrc を再読込するらしい。 33880 TERM=xterm infocmp 等とするだけで壊れるのである。 33881 33882 これを検出する方法はあるだろうか。或いは阻止する方法。 33883 厄介なのは変更してまた元に戻しても壊れるという事。 33884 33885 a reject: 或いは typeset -r TERM してしまうという手は? 33886 →そうすると全く変更できなくなるので駄目。 33887 33888 b reject: 或いは拾えなかった時に rebind する? 33889 と思ったが拾えないのだから検出できない。 33890 33891 c reject: INPUTRC=/dev/null に設定する? 33892 と思ったが問題が発生するのはユーザ環境なので、 33893 ユーザ環境で一時的に INPUTRC を復元している時に問題が起こる。 33894 INPUTRC を上書きした状態でユーザ環境に戻すと、 33895 今度はユーザが bash 等を起動した時に inputrc が読み込まれなくなってしまう。 33896 33897 →気付いたのはこれは inputrc とは関係ないという事。 33898 inputrc 読み込みを阻止しても readline 自体の初期化によって 33899 terminfo を元にして bind が実行される。 33900 33901 d 実行が完了する度に全 bind を実行する手 33902 然し、全 bind の時には unbind もしなければならない。 33903 inputrc が編集された場合には前回の unbind スクリプトは使えない。 33904 すると unbind を自動的に生成しなければならない? 33905 33906 e 或いは、実行が完了する度に builtin bind -ps をチェックする手 33907 33908 a 後者は bind -s の出力結果が ble.sh 自身の物なのか判定が必要。 33909 結局完全に対応する為には awk を起動するなどする必要がある。 33910 b 或いは前回の呼び出しと状態を比較するというので十分の気がする。 33911 c bind -p だけチェック。 33912 確認した所 inputrc と関係なく書き換えられる様である。 33913 そして beginning-of-line 等が必ず書き換わる様に見えるので、 33914 取り敢えず bind -p だけチェックすれば十分だろうか。 33915 そして # 以外で始まる行が含まれていれば検出したとする。 33916 単に builtin bind -p | grep -v ^# でも良いのかもしれない。 33917 33918 | またチェックするのと全 bind を実行するのとどちらの方が重いのかという話。 33919 | 33920 | 以下を実行すると 1.6ms である。Cygwin では 33ms 33921 | $ check1() { ble/util/assign hello 'builtin bind -sp'; [[ $hello == "$value2" ]]; } 33922 | $ ble-measure check1 33923 | 33924 | 以下は 2.86ms (Cygwin 77.5ms) だった。 33925 | $ ble-measure 'builtin bind -p | grep -v ^#' 33926 | 33927 | 以下は 4.5ms である。Cygwin では 31ms 33928 | $ ble-measure ble/decode/rebind 33929 | 33930 | 以下は 19.2ms である。Cygwin では 247ms 33931 | $ ble-measure 'ble/decode/detach; ble/decode/attach' 33932 | 変な設定に shadow されない為にはこちらを実行する必要がある。 33933 | 33934 | % Cygwin は何れにしても遅い様だ。ファイルに書き込むからだろうか。 33935 | % どうも ble/util/assign の中で出力する内容の量に比例して時間がかかっている。 33936 | % 取り敢えず Cygwin の事は考えなくて良いという事にする。 33937 | % 33938 | % うーん。今 ble/decode/bind/unbind の実装を確認して気付いたが、 33939 | % 実は昔にキャッシュした結果を使って unbind している。 33940 | % つまり、キャッシュした時から変化があったりすると unbind できない。 33941 | % 指示通りに設定していれば bashrc の先頭で実行するので 33942 | % ユーザの設定に左右される可能性は低いが、 33943 | % inputrc の設定には左右されてしまう。 33944 | % 33945 | % と思ったが何か変だ。このキャッシュしている内容は 33946 | % ble.sh による binding の設定・削除である。 33947 | % 元々の binding の復元・削除ではない。 33948 | % 確認するべきなのは 33949 | % ble/decode/detach と ble/decode/attach なのだった。 33950 | 33951 | コマンド実行の時間と比べれば 4.5ms や 31ms は短いので 33952 | そんなには気にならない様にも思う。或いはもっと別のタイミングで再チェックを行う? 33953 | と思ったが、コマンドの実行以外にもっと疎らなチェックのタイミングはない気がする。 33954 | もしコマンドの実行でチェックしないとその後の編集の何れかのタイミングで再度 33955 | binding を実行しなければならないので面倒である。 33956 | 33957 | ? TERM を書き換えると勝手に初期化される振る舞いは妥当なのだろうか。 33958 | 例えばユーザが明示的に home になにか割り当てていた時に、 33959 | TERM が書き換わる度にそれが上書きされてしまうという事にならないのか。 33960 | と思って振る舞いを確認した所、既にその binding が存在している場合には、 33961 | 勝手に上書きしてしまう等の事は発生しない様だ。 33962 | ちゃんとできている。 33963 | 33964 | prefix の \e や O を単体で取り出したい等という変な事をしない限りは 33965 | これでちゃんと動く様になっているのである。うーん。これには文句はつけづらい。 33966 33967 コマンドを実行する度に bind をチェックするのが一番速い。 33968 対応としては bind -p の出力を記録して比較する。 33969 特に Cygwin で遅いが stty が 55ms なのでそれに比べれば小さい。 33970 bind -p だけならば 21ms で比較できている。 33971 33972 取り敢えず実装する。 33973 33974 * ok: 初回はコマンドを実行する前に記録するべきの気がする。 33975 →これは decode/bind/bind の側で記録する事にした。 33976 * done: TERM を記録しておいてそれが変更したらチェックしなくても再読み込みを実施する。 33977 * ok: 動作確認 33978 33979 追記: ble-reload の時に変なメッセージが出る様になったと思ったら 33980 これが原因だった。bind している状態の時に限り rebind を実行する様に変更した。 33981 33982 # エラーメッセージは emacs mode ではないのに keymap 'emacs' is empty となっていて、 33983 # これは source ble.sh した時に default keymap が emacs に取り敢えずなって、 33984 # 本来は attach の時に正しいものに決定されるはずが、attach の前に ble/decode/attach 33985 # を呼び出してしまってエラーになっていたという事である。 33986 33987 2020-02-12 33988 33989 * 2020-01-17 syntax: ${var/#} ${var/%} も特別に着色する [#D1286] 33990 33991 * decode: ble-import -d (--delay) [#D1285] 33992 * ble-import の guard は常に絶対パスで行う様に変更した。 33993 33994 * decode: macro 無限ループ防止? [#D1284] 33995 macro 再帰に条件を設けても良いのでは? と思ったが、 33996 現在の仕組みだと一旦一番上に抜けてから実行する様になっているので、 33997 macro の階層は簡単には分からない様になっている。 33998 macro の階層ではなくて文字数で判定するのでも良いかもしれない。 33999 然し、問題は階層・文字数で制限したとしても一つのマクロから呼び出される 34000 マクロが2以上だと鼠算式に増えるので容易に実質止まらないループを作れる事。 34001 34002 要するに一つのマクロ呼び出しから起こるマクロ呼び出しの総数に制限を掛ければ良い。 34003 マクロの中ではないマクロ呼び出しでカウンタをクリアして、 34004 マクロの中でのマクロ呼び出しではカウンタをインクリメントしながら回数に制限を掛ける。 34005 マクロの中なのかそうでないのかはどう判定すれば良いか? 34006 これは ble-decode-key 辺りで変数を定義する事にすれば良い? 34007 34008 →実装した。 34009 34010 * decode: ble-bind -L が BSD sed でエラーを出す (reported by dylankb) [#D1283] 34011 https://github.com/akinomyoga/ble.sh/issues/41#issuecomment-585068803 34012 何と sed -r を使っていた。恐らく ble-bind -L は元々自分のデバグの為に作った 34013 関数を ble-bind の機能として転用した為に環境依存の実装が残っていたのだろう。 34014 34015 * ble-sabbrev は complete 経由でなくても呼び出せる様に改良する [#D1282] 34016 対応した。 34017 34018 * complete: auto_complete で failglob の時 ^? が直接挿入される問題 [#D1281] 34019 及び fzf で auto-complete の時に complete -D を使うと 34020 fzf の設定が bash-completion で上書きされてしまう問題。 34021 34022 fzf completion を試していた時に auto-complete で ^? が self-insert される状態になった 34023 これは何かのバグだろうか。 34024 34025 fzf で最初の候補を選択した直後に auto-complete 状態になるが、 34026 その時に backspace を押すと ^? が self-insert される。何故? 34027 その他の場合にはそういう事にはならない。 34028 34029 →これも auto-complete では fzf を起動しない事にしたので、 34030 余り気にしなくても良いのかもしれない。しかし、 34031 何故こういう事になってしまうのかについては調べる必要がある? 34032 34033 そもそも self-insert されるというのが不思議である。 34034 →これは vi_imap/__default__ であろう。 34035 問題は何故元々の C-? が働かずに __default__ が呼び出されているのかという事。 34036 然し、C-? が bind されていない map があったろうか。。 34037 34038 というかどの様に再現したら良いのか。。改めて設定を変えて試す必要がある。 34039 駄目だ再現できない。最近の変更で変わったとは思えない。 34040 最近の変更はコメントの編集と reconstruct-user-settings だけである。 34041 或いは reconstruct-user-settings で bind が上書きされた可能性もなくはないが、 34042 そうだとしたら ^? が挿入されるという振る舞いにはならない筈。 34043 34044 再現した。vim ** <TAB> で再現した。と思ったら再現しなくなった。 34045 34046 * fixed: 然し一度 vim ** で fzf を実行して確定すると以降は二度と fzf が起動しなくなる。 34047 補完設定を確認してみると _filedir_xspec に置き換わっている。 34048 fzf が内部で dynamic loading を実行しているのが原因だろう。 34049 然し、これは ble.sh なしでも再現するのではないか? 34050 →試してみたが ble.sh なしでも勝手に置き換わるという事は無い様だ。 34051 34052 そもそも ble.sh の上で vim ** が動いていない。 34053 メニューは出るがその後で置換が発生していない。 34054 詳しく何が起こっているのか確認する必要がある。 34055 34056 最初に fzf の completer はロードされている。 34057 誰かが上書きしている。 34058 ble.sh による __load_completion の呼び出しは行われていない。 34059 fzf が自身で書き換えている可能性も見たがそうでもない。 34060 外側で書き換わってしまっている。 34061 34062 complete を hook して調べる必要がある。 34063 うーん。_python_argcomplete_global というのが勝手にロードしている。 34064 そして _python_argcomplete_global は complete -p -D に登録されている。 34065 そもそもの話、何故 complete -p -D が呼び出されているのかという話でもある。 34066 あー。分かった。auto-complete で default にフォールバックしているからだ。。 34067 これの work around はどうすれば良いか。 34068 34069 元々意図した事は default の fzf でない補完設定を実行するという事。 34070 然し、fzf でない補完設定の -D は complete を呼び出してしまう。 34071 或いは fzf に既定の補完を呼び出させるのが良いのではないだろうか。 34072 34073 うーん。取り敢えず -o default を指定するのではなくて別の方法で 34074 default の呼び出しを抑止してみる事にした。然し駄目だ。何故だろう。 34075 と思ったら -o default を fzf が指定しているのだった。 34076 -o default が指定された時には complete -D 34077 を呼び出すのではなくて組み込みの補完を呼び出さなければならない。 34078 というか実は初めからそのような実装になっていた。 34079 従って前回の変更で付け加えた機能は不要だったのである。 34080 削除した。この問題は発生しなくなった。 34081 34082 * ^? が挿入される問題は未だ解決していない気がする。 34083 然し再現できない。再現の条件が良くわからない。 34084 34085 auto-complete が表示されているという事は auto-complete の中にいると仮定して良い? 34086 この時に ^? を受信するとどうなるかというと auto-complete を一旦抜けて外で 34087 処理を行ってその後でまた auto-complete に入る。もしくは auto-complete の中にいる儘で 34088 ^? を挿入する。 34089 34090 ble/widget/auto_complete/self-insert の実装を見ると 0x7F が直接入って来た場合には 34091 そのまま挿入される事になる。恐らく __defchar__ もその様になっているのだろうと想像される。 34092 然し、何処で 0x7F が発生するのだろうか。 34093 ble/widget/vi_imap/__default__ が変換している? 34094 そしてそれを auto-complete が受け取っている可能性? 34095 34096 再現する気配がないので昔の状態に戻して改めて再現を試みる。 34097 34098 $ touch a\*\*b 34099 $ vim a** 34100 34101 この状態で \C-i\C-g\C-? とすると再現する。 34102 もう一回試した。やはり再現する。 34103 うーん。最新の commit にすると再現しなくなる。 34104 34105 この変な状態を調べる。 34106 取り敢えず self-insert に stackdump をしかける。 34107 →どうやら self-insert は引っ掛かっていない様だ。 34108 という事は auto_complete/self-insert に引っ掛かっている? 34109 引っ掛かっていた。stackdump の引数の機能が欲しい。cherry-pick する事にする。 34110 →git checkout 1f14571 src/util.sh で取り出した。 34111 34112 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (ble/widget/auto_complete/self-insert ) 34113 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:46 (ble-decode/widget/.call-keyseq ) 34114 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:58 (ble-decode-key/.invoke-partial-match 127) 34115 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:45 (ble-decode-key 127) 34116 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:79 (ble-decode-char/.send-modified-key 127) 34117 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:51 (ble-decode-char 127) 34118 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:45 (ble/encoding:UTF-8/decode 127) 34119 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (ble-decode/.hook 127) 34120 34121 どうも 127 がそのまま変換されずに到達している様だ。 34122 よく考えてみれば確かに 127 は DEL として取り扱っているので、 34123 そのまま変換されずに到達するというのは今迄の意図した取り扱いである気がしてきた。 34124 * 他の keymap で問題が起こらなかったのは DEL が明示的に bind されている為。 34125 * auto-complete でも問題が起こらなかったのは ^? で始まる補完候補がなかった為。 34126 然し、何故か今回の判定では ^? が続きにあるという勘違いをしてそのまま挿入してしまう。 34127 34128 具体的にどういう事になっているのか調べる。と思ったら…。成る程。 34129 34130 comp_filter_type='head' compv_new='' _ble_complete_ac_cand='.git' 34131 34132 failglob になって、その結果として compv_new='' になって、 34133 空文字列が入力されている状態という事になって、 34134 結果として何でも受け入れてしまうという状態になっているという事。 34135 34136 [修正] 34137 34138 対処方法としては (1) done: 先ず DEL を直接送信する設計は止める事にする。 34139 (2) done: 展開に失敗したら素直に諦める。 34140 DEL に対する bind は改めて確認してみたが特に問題になりそうにはない。 34141 34142 2020-02-10 34143 34144 * [bash-completion] failglob: 以下のエラーメッセージが補完で出る [#D1280] 34145 "[murase@hp2019 0 bin]$ ln -s ~/.mwgbash: 一致しません: \~/.mwg" 34146 34147 →これはbash-completion の問題だった。 34148 そもそも bash-completion は failglob に対応できていない。 34149 34150 | 何故? そもそもグロブパターンですらないのに 34151 | →調べたらエラーが出た。うーん。 34152 | どうも \ が含まれているだけでパターンとして取り扱われる様だ。 34153 | value='\~/.mwg' 34154 | echo $value 34155 | 34156 | 何処でこのエラーメッセージが発生しているのだろうか。 34157 | と思ったら再現しなくなった。うーん。これは fzf の方のバグだろうか。 34158 | →再現した。ln コマンドで再現する。ln _fzf_path_completion である。 34159 | 34160 | 辿って行くと _longopt (bash-completion) がエラーを発生させている。 34161 | _longopt に対して bash-completion は ln ~/.mwg -s という引数を渡している。 34162 | うーん。ble.sh なしで bash-completion を使った時にも failglob で同じエラーが発生する。 34163 | つまり、これは bash-completion の問題である。 34164 34165 * util: ble/util/stackdump は >&1 に出力するべきなのでは [#D1279] 34166 使う側が目的に応じて出力を変更するべき。 34167 後 ble/util/stackdump を直接使っている箇所を ble-assert 34168 もしくは ble/util/assert に置き換えられないか。 34169 →ble/util/assert で書き直した。 34170 34171 * [棄却] edit: 既定で bind している fg は builtin fg の方が良い? [#D1278] 34172 或いは fg のままの方が良い? 34173 もしユーザが fg を上書きしているのだとすればそれなりに機能を追加している 34174 という事の気がするので fg の儘の方が良いのではないかという気がする。 34175 34176 * complete: BSD sed? が bind -p の解析で misencoded char のエラーを出す (reported by dylankb) [#D1277] 34177 https://github.com/akinomyoga/ble.sh/issues/41#issuecomment-583892006 34178 これは最近追加したコードが悪いのに違いない。分かった。修正した。 34179 34180 →実際に FreeBSD 試してみた所エラーメッセージはでていない。 34181 つまり、これは BSD sed ではない? どの sed がエラーメッセージを出しているのだろう。 34182 然し、検索するとどの頁も macOS の sed は BSD sed だと言っている。 34183 BSD sed にも色々亜種が有って FreeBSD の物と macOS の物では振る舞いが違うという事なのか? 34184 34185 2020-02-09 34186 34187 * edit: PS1, PROMPT_COMMAND, PRECMD に於いて BASH_COMMAND, _ を復元 [#D1276] 34188 cygwin 問題報告の例を作る上で BASH_COMMAND を用いる use case が 34189 ある事に気付いたが、これが ble.sh では動かない。修正した。 34190 34191 * complete: fzf complete cd が動かない (reported by dylankb) [#D1275] 34192 https://github.com/akinomyoga/ble.sh/issues/41 34193 fzf が動かないという話。これは既に解決済みの話。彼は古い version を使っている。 34194 然し、二つ目の項目に関しては前の修正とは関係ない。 34195 先ず再現を試みたがそもそも fzf の振る舞いを再現する事ができない。 34196 34197 [原因] 34198 34199 少なくとも cd の補完に関しては ble/cmdinfo/complete:cd で処理しているので、 34200 fzf が幾ら設定を追加しようとも関係ない筈だ。そして ble/cmdinfo/complete:cd 34201 が報告されたエラーを出力している筈である。しかし、そうだとしても、 34202 34203 -bash: cd: too many arguments 34204 [ble: exit 1] 34205 34206 というのはどういう事であろうか。まるで cd ** でコマンドを実行したかの様である。 34207 というか [ble: exit 1] と表示されるという事は実際に 34208 cd ** でコマンドを実行したということであろう。 34209 fzf をロードしていると同じ事が起こるのだろうか? 34210 34211 少し fzf だけをロードして試してみる事にする。 34212 先ず cd **TAB とするとちゃんと fzf が起動する。そして置き換わる。 34213 また cd ** で直接実行すると報告されたのと同じエラーメッセージが出る。 34214 恐らく dylankb は TAB で fzf を起動してそのまま一番最初の物で確定する癖になっているのだ。 34215 その想定で、先ず fzf がちゃんと起動する様に修正する必要がある。 34216 34217 取り敢えず ble/cmdinfo/complete:cd を取り除く。 34218 それから fzf が呼び出されているかの確認を行う。 34219 34220 分かった。二種類の問題がある。 34221 34222 x ble/cmdinfo/complete:cd 34223 これは unset するしかない。 34224 34225 x < /dev/null にしているという事。 34226 うーん。< /dev/null に関しては 34227 ユーザの側で </dev/tty を開く様にお願いすれば良い。 34228 (しかし、こういう微妙な仕様の違いでひっかかるのは注意を要する。) 34229 →これも /dev/tty に繋ぐようにして試してみたが直らない。 34230 34231 x '**' を ble.sh が独自に最初の単語に展開している事 34232 と思ったがそうでもない。 34233 fzf にはちゃんと '**' という文字列が渡っている。 34234 どうした理由かは分からないが。 34235 34236 x 分かった。原因は COMP_WORDS である。 34237 34238 これの解決方法は。どの様にして COMP_WORDS を調整するか。 34239 34240 [解決方法] 34241 34242 a ユーザに comopt を指定してもらう。指定がある場合に振る舞いの変更を行う。 34243 complete の設定に予め含めるというのはできない。非標準のオプションだから。 34244 34245 "" 等の quote の事も考えると pathname expansion だけ実行しない 34246 という様にするのか、或いは展開そのものを全くしないという事にするのか。 34247 中途半端に展開しても今度は '**' と指定した時に困るのだから、 34248 展開そのものを全く実行しないという様にするのが自然である。 34249 34250 その為には _fzf_dir_completion という関数を上書きしなければならない。 34251 % 然し、_fzf_dir_completion 側の実装と合わせなければならない。 34252 % そう言えば以前デバグの為に関数に処理を付け加える advice 云々という関数を定義した様な気がする。 34253 % しかし今簡単に探してみると見つからない。 34254 % そもそもどういう関数名だったかなど。うーん。 '"function' で探して見つからないので、 34255 % その関数は恐らく全然別の所で定義した物の気がする。 34256 % →分かった。song526 の ble.sh の中に measure.sh という commit していないスクリプトがあった。 34257 % 中を覗いてみたが advice の様な汎用性を持たせた実装にはなっていなかった。 34258 34259 何れにしても新しく関数を追加する必要があるという事なのである。 34260 34261 →結局他にも問題が沢山あるという事が分かった。 34262 オプションを指定するだけで解決できる様な問題ではない。 34263 34264 b 或いは ble/cmdinfo/complete:cd を上書きしてもらう? 34265 こちらの方が手軽である。然し comp_reply を読む必要がある。 34266 と思ったが、nospace だとか色々のオプションをどの様に処理するのか? 34267 これまでの方法だと compgen が色々何とかしてくれた。 34268 34269 function ble/cmdinfo/complete:cd { 34270 local COMP_LINE=$comp_line 34271 local -a COMP_WORDS=("${comp_words[@]}") 34272 local COMP_CWORD=$comp_cword 34273 local COMP_POINT=$comp_point 34274 local -a COMP_REPLY=() 34275 _fzf_dir_completion "${comp_words[0]}" "${comp_words[comp_cword]}" "${comp_words[comp_cword-1]}" >/dev/pts/7 34276 compopt() { echo "compopt $*"; } 34277 comp_opts+=:nospace: 34278 local cand 34279 for cand in "${COMPREPLY[@]}"; do 34280 ble/complete/cand/yield word "$cand" "" 34281 done 34282 ble/textarea#invalidate 34283 return 0 34284 } 34285 34286 うーん。結構長い関数になってしまう。 34287 34288 実際にこれを動かして試してみると無限ループになっている。何故? 34289 未だ再現していない。うーん。再現しない。何だったのだろうか。 34290 34291 x fixed: 更にもう一つの問題点は fzf が表示を書き換えてしまっているので、 34292 表示が乱れてしまっているという事。これは invalidate を呼び出せば良い。 34293 実際に試してみて解決する事を確かめた。 34294 34295 x もう一つの問題点はこれが interactive な補完を呼び出すという事。 34296 現状の実装では auto_complete も同じ枠組みを使っているので、 34297 auto_complete によって fzf が呼び出されてしまってこれは面倒。 34298 34299 更に色々試してみた結果 compopt の処理もしなければならないし、 34300 色々面倒である。結局やはり ble.sh の progcomp 経由で実行した方が良い気がする。 34301 34302 c 結局 fzf の側の関数を動的に書き換えて振る舞いを変更する事にした。 34303 34304 * 一旦適当に reply しておく。 34305 34306 % ## 3. ble.sh closes stdin/stdout while `fzf` is used 34307 % 34308 % Sometimes a user-provided completer consumes or flushes stdin 34309 % unintentionally. But this causes the problem for 34310 % auto-complete. Because auto-complete is performed in the 34311 % background, the user inputs will be lost if the background 34312 % user-provided completer flushes stdin. For this reason, ble.sh 34313 % by default closes the standard streams of user-provided 34314 % completers. If user-provided completers really want to do 34315 % something with stdin/stdout, the completer need to open 34316 % `/dev/tty` for itself. But `fzf` does not do that. 34317 34318 調べながら書いていたら時間を食ってしまった。 34319 後、上の内容は結局本当か分からない。 34320 実際に fzf のソースを見てみると /dev/tty を開いている箇所がある。 34321 従って、試している時に発生した hang はこれとは関係ないのかもしれない。 34322 34323 →実際に試してみたらやはり fzf は /dev/tty を開かずに実行しようとして、 34324 それで hang してしまっている。やはり /dev/tty の対策はしなければならない。 34325 34326 [実装] 34327 34328 取り敢えずおおまかな実装をしてから細かい振る舞いの調整を行えば良い。 34329 以下の二つを上書きすれば良い気がする。 34330 34331 __fzf_generic_path_completion 34332 _fzf_complete 34333 追加: _fzf_complete_kill 34334 34335 * 無限ループになっている原因は分かった。auto-complete である。 34336 auto-complete の中では fzf を起動しない様にした所、動いている。 34337 34338 * 今度の問題は ble.sh が勝手に変換結果をフィルタしてしまうという事。 34339 ** のまま変化しない。 34340 うーん。候補の生成まではちゃんとできている。 34341 しかし再度の候補生成が試みられてそれで何も生成されずに終わっている。 34342 34343 →あー。何が起こっているのか分かった。補完がキャンセルされている。 34344 何故かと言うと fzf が DSR(5) を要求してその返答が届いているから。 34345 ble.sh は補完の計算中にユーザ入力が来たと思って補完処理を中断する。 34346 これによって何も起こらないという事が発生している。 34347 34348 * ESC [ 0 n が not found というエラーメッセージが出ている。 34349 % bind していても処理されないという事。 34350 % というか bind '"\e[0n":...' はどのレベルで処理されるのだろう? 34351 % →確認してみた所、以下の様に登録されていた。うーん。 34352 % ble-bind -m 'vi_imap' -f 'M-[ 0 n' 'redraw-line' 34353 % 34354 % これはどうしたら良いか。blesh では認識できない 34355 % escape sequences は無視する様にしている。 34356 % それは terminal が不意に何か変な response をした時に 34357 % ユーザの入力と勘違いして変な振る舞いをしないようにする為。 34358 % なのでこの設計を変更するつもりはない。 34359 % 34360 % ならば正しい設定は一体何か? 34361 % 結局これを正しいシーケンスとして登録する事である。 34362 % ble-bind -k 'ESC [ 0 n' DSR 34363 34364 うーん。結局 fzf の DSR(5) による hack を封じる事にしたので 34365 これの対策はしなくても良いのである。 34366 34367 2020-02-08 34368 34369 * proghl の中で行った fix を ble-0.3 にも適用しなければならない [#D1274] 34370 続いて patch を適用していく必要がある。適用した。 34371 34372 * msys1: C-d の受信について [#D1273] 34373 34374 mkfifo がエラーになっている。Function not implemented と表示される。 34375 sleep に関しては cygwin 用の実装を使っている。 34376 stderr.pipe に関してエラーになっている様だ。これの所為で C-d も受信できていない。 34377 34378 C-d の受信に関しては bind 'set bind-tty-spacial-chars off' にしたら 34379 受信できるかもしれないと考えたが実際に試してみるとできない。 34380 やはり駄目の様だ。 34381 34382 もしかして msys2 も駄目なのかもしれないと思って msys2 で mkfifo を試したら動いた。 34383 つまりやはり msys1.0 に fifo (pipe) が実装されていないという事なのだ。 34384 因みに coproc も 3.2 以下には存在しない。 34385 34386 そうすると、pipe を使わない代替実装を考えなければならない。 34387 実は以前は pipe を使わない実装だったような気もする。 34388 34389 | a pipe を単に普通のファイルに置き換える実装を考えてみたが駄目そう。 34390 | > stderr.pipe としても一度 exec したものをそのまま使っていると、 34391 | 以前の末尾の位置の続きに書き込まれてしまう。 34392 | 毎回 exec する必要があるのではという気がする。 34393 | b プロセス置換で実装してみようとしたがプロセス置換も 34394 | Function not implemented になった。 34395 | c そうすると何度も sleep しながら待つ実装になるだろうか。。 34396 | 試しに tail -f を実行してみたら良い感じに動く。 34397 | 更にファイルを truncate した事もちゃんと検出してくれる。 34398 | tail は優秀なのではないか。然し、遅延があるのが気になる。 34399 | 内部的に sleep して実装しているのだろうか。 34400 | 自分で細かく sleep コマンドを呼び出すよりは良い。 34401 | 取り敢えずこれで実装する事にする。 34402 | 34403 | →実装してみたが微妙。遅いし消滅している入力もある気がする。 34404 | 後、親 Bash が死んだ後も生き続けている気がする。 34405 | もっと別の実装方法を考える? 34406 | 34407 | 入力が消滅するのは stderr.off の瞬間にファイルをクリアするからだった。 34408 | クリアしないで追記する様にしたら入力は消滅しない様になった。 34409 | 但し、エラーを沢山出すとディスクに際限なく書き出してしまう。 34410 | 34411 | sleep を使うにしてももっと実装を工夫しなければならない。 34412 | 34413 | 解決しなければならない問題が幾つか在る。 34414 | x いつ誰がファイルをクリアするのか。 34415 | 書き込み元がクリアする事にすると 34416 | 読み取りする前に消えてしまう行が出てくる。 34417 | 読み取り側がクリアする事にすると、 34418 | 書き込み元はそれを知らないので、 34419 | いきなりファイルの途中から続きを書き出してしまう。 34420 | 34421 | 或いは2つのファイルを交互に使う等してこの制限を回避する事は可能だろうか。 34422 | 然し、読み取り側は書き込み元がどちらのファイルを使っているのか検出する術がない。 34423 | ファイルAとファイルBのどちらの内容の方が先に読み取るべき物なのか分からない。 34424 | 34425 | d 思いついた。これは書き込み元が新しくファイルを開く時に、 34426 | データの出力先が有限のサイズを持っている場合には、 34427 | 新しく別名でファイルを開く事にすれば良いのである。 34428 | そして読み取り側がファイルをクリアする事にする。 34429 | 34430 | 書き込み元がファイルサイズをチェックしてから 34431 | 実際にファイルを開く間に何か変化があるという事はない。 34432 | 読み取り側はファイルを短くする事はあっても長くする事はないので、 34433 | 一旦空のファイルであると判定が出たらそれが他の要因で変化する事はない。 34434 | 34435 | 実装してみる事にする。と思ったが駄目だ。 34436 | x 読み取り側がどれを読み取ったら良いのかが分からない。 34437 | 若い番号から順に読み取れば良いと考えていたが、 34438 | 考えてみるとファイルをクリアしてしまうと、 34439 | 親がまた若い番号から書き込み始めてしまうので、 34440 | 一概に若い番号から順に読み取れば良いという訳ではない気がする。 34441 | →クリアは大きい番号のファイルから順番にするという規則にする。 34442 | x それでも駄目。順番に消していっている途中に書き込み側が 34443 | 有限の番号で開くとその後でそれより若い番号を消去する事になる。 34444 | x それに読み取り側がどのタイミングでファイルの末端が来たと 34445 | 判断すれば良いのかも分からない。 34446 | 未だ書き込み中かもしれないからである。 34447 | 或いは、特別な信号を書き込む事にする? 34448 | 34449 | 色々バグがあったりして動かなかったりしたが動く様になった。 34450 | と思ったら C-c で子プロセスが勝手に終了してしまう。 34451 | うーん。trap -- '' INT QUIT としたら終了しなくなったが、 34452 | 今度は遅延が生じる様になってしまった。どうして trap が遅延に影響するのだろう? 34453 | 良くわからない。 34454 | 34455 | 更に sleep を高頻度で回しているのでやはり HDD のアクセスが気になるのである。 34456 | うーん。tail -f の方が現実的なのかもしれない等と考える。 34457 | 34458 | e うーん。或いは lastpipe 等を弄って何か上手にできないのか。 34459 | cat | exec 5<&0 みたいな事をする等…。 34460 | 然し、これはデータの流れが逆である。寧ろ first pipe 的な物が必要である。 34461 | 34462 | 試しに cat README.md | exec 5<&0; read line <&5 として見たが 34463 | ディスクリプタは開いてなかった。と思ったが last pipe するのを忘れていた。 34464 | 然し shopt -s lastpipe を実行した後でも <&5 しようとすると 34465 | bad file descriptor と出て、fd がそもそもない場合と同じエラーメッセージ。 34466 | Bash が色々の fd を閉じてしまっているという事の気がする。 34467 | 或いは元の状態を復元している。 34468 | なので、lastpipe を使って何とかする事はできない。 34469 34470 最初に試したのは c の実装 34471 34472 | : >| "$_ble_edit_io_fname2.pipe" 34473 | { 34474 | tail -f "$_ble_edit_io_fname2.pipe" 2>/dev/null | ble-edit/stdout/check-ignoreeof-loop tail & disown 34475 | } &>/dev/null 34476 | function ble-edit/bind/stdout.off { 34477 | ble/util/buffer.flush >&2 34478 | ble-edit/bind/stdout/check-stderr 34479 | exec 1>>$_ble_edit_io_fname1 2>"$_ble_edit_io_fname2.pipe" 34480 | } 34481 34482 x どうも消滅している入力がある気がする。 34483 更にユーザの入力が前後してしまって UTF-8 を破壊したり 34484 色々遅延に関係して変な事が起こっている。 34485 34486 x この実装だと無限に読み取り続けようとしてしまう。 34487 親を定期的にチェックして親がいなくなったら終了する様に書き換えてみたが、 34488 それでも tail の方が終了しないで残ってしまう様だ。 34489 tail -f は誰かが kill しなければならないのである。 34490 34491 結局、d の複数のファイルに分散して書き込む方向性で実装して 34492 以下の様なコードができたが思い通りに動かない。 34493 34494 | { 34495 | builtin trap -- '' INT QUIT 34496 | while kill -0 $$ &>/dev/null; do 34497 | declare index=0 processed= 34498 | while file=$_ble_edit_io_fname2.$((index++)); [[ -e $file ]]; do 34499 | [[ -s $file ]] || continue 34500 | processed=1 34501 | while :; do 34502 | if ! IFS= builtin read -r line && [[ ! $line ]]; then 34503 | kill -0 $$ &>/dev/null || exit 34504 | ble/util/msleep 100 34505 | continue 34506 | fi 34507 | 34508 | [[ $line == __BLE_STDERR_EOF__ ]] && break 34509 | 34510 | [[ $line == *[^$_ble_term_IFS]* ]] && 34511 | ble/util/print "$line" >> "$_ble_edit_io_fname2" 34512 | 34513 | if ble-edit/stdout/check-ignoreeof-message "$line"; then 34514 | ble/util/print eof >> "$_ble_edit_io_fname2.proc" 34515 | kill -USR1 $$ 34516 | ble/util/msleep 100 34517 | fi 34518 | done < "$file" 34519 | : >| "$file" 34520 | done 34521 | [[ $processed ]] || ble/util/msleep 100 34522 | done & disown 34523 | } &>/dev/null 34524 | 34525 | _ble_edit_io_fname2_write= 34526 | function ble-edit/bind/stdout.on { 34527 | exec 1>&$_ble_edit_io_stdout 2>&$_ble_edit_io_stderr 34528 | [[ -s $_ble_edit_io_fname2_write ]] && 34529 | ble/util/print __BLE_STDERR_EOF__ >> "$_ble_edit_io_fname2_write" 34530 | return 0 34531 | } 34532 | function ble-edit/bind/stdout.off { 34533 | ble/util/buffer.flush >&2 34534 | ble-edit/bind/stdout/check-stderr 34535 | local index=0 highest=-1 34536 | while [[ -e $_ble_edit_io_fname2.$index ]]; do 34537 | [[ -s $_ble_edit_io_fname2.$index ]] && highest=$index 34538 | ((index++)) 34539 | done 34540 | _ble_edit_io_fname2_write=$_ble_edit_io_fname2.$((highest+1)) 34541 | exec 1>>$_ble_edit_io_fname1 2>"$_ble_edit_io_fname2_write" 34542 | } 34543 34544 問題点は以下の通り 34545 34546 x trap -- '' INT QUIT をして置かないと C-c 等を入力した時に 34547 この補助プロセスが終了してしまう。 34548 34549 一連の一時ファイルを削除する補助プロセスがないと、 34550 一時ファイルがどんどん増えて親シェルの動作がどんどん重くなる。 34551 これについては補助プロセスがいなくなった事を検出して 34552 適宜再起動する様にすれば良い気もする。 34553 34554 x trap -- '' INT QUIT をすると今度は謎の遅延が発生する様になる。 34555 次の入力を受け取らないとシグナルが受信されないという事になる。 34556 34557 x また sleep を頻繁に呼び出すので常にディスクがアクセス状態になる。 34558 command sleep 以外の待ち時間の費やし方を考える必要がある。 34559 適当に /dev/udp/127.0.0.1/0 等を開いて誤魔化す? にしても、 34560 read が小数に対応していないので timeout できない。 34561 34562 % 今の所は単純に C-d を諦めるという実装にするしかない気がしている。 34563 34564 もしこのシステムが msys1 なのだとしたら、 34565 gcc があると期待して良い。 34566 そして gcc があるという事は C プログラムが使える? 34567 g++ は使えないかもしれない。 34568 何れにしても gcc が使えるならば Sleep も使える。 34569 そして tail -f の代替をコンパイルする事もできる。 34570 34571 然し tail -f 方式はタイミングの問題で 34572 出力が失われてしまうのが問題なのだった。 34573 やはり複数ファイルを使う必要があるのか。 34574 或いは、一つのファイルで頑張る方法があるだろうか。 34575 34576 複数ファイルを使う方法に頼ると子プロセスが消えた時に 34577 無限にファイルが増えていく事になる。これは避けたい。 34578 とするとファイル数に上限を定める事になる。 34579 それぐらいならば 2 つのファイルで頑張る方法を考えるべきでは? 34580 34581 gcc が使えるのであればファイル名を変更する事が可能である。 34582 ファイル名を変更できるという事は、可能性が増えるという事。 34583 改めて考え直す事にする。 34584 34585 親プロセスを A としてバックグラウンドプロセスを B とする。 34586 A は既存のファイル F に只管追記する事にする。 34587 B は mv F G してから G を読み続ける。 34588 新しく F が生成される迄は G の読み取りを試み続ける。 34589 これで行ける気がする。 34590 34591 ? yes: 問題は今書き込んでいる途中のファイルを読み取れるのか。 34592 そして読み取れたとして一旦 EOF に達した後に続きが書き込まれた時に、 34593 再度続きの読み取りを再開する事ができるのかという事。 34594 試してみた所できる様だ。 34595 34596 1文字ずつ読み取るのはできた。まとめて読み出すのもできた。 34597 34598 ? 次の問題は親プロセスが存在しているかどうかをチェックする事ができるのかという事。 34599 これは WINPID を知っていればできる筈。然し、WINPID を取得することは可能か? 34600 或いは普通に親プロセス? と思ったが親プロセスなのか親の親プロセスなのか分からない。 34601 うーん。msys には /dev も /proc もない。 34602 34603 少なくとも cygwin PID から WINPID に変換できれば Win API が使える。 34604 https://stackoverflow.com/questions/1679337/convert-a-cygwin-pid-to-a-windows-pid 34605 34606 cygwin の場合には include <sys/cygwin.h> とすれば良い様だ。 34607 msys の場合にはそんな簡単な訳ではない様だ。 34608 或いは msys の dll を見たら行けるのかもしれないが面倒なので止める。 34609 結局 ps コマンドを実行してその結果を解析するしか無いのだろうか。 34610 34611 取り敢えず WINPID は取得できる。次にするべき事は。 34612 Windows でのプロセス存在確認は GetExitCodeProcess で行うそうだ。 34613 https://stackoverflow.com/questions/1591342/c-how-to-determine-if-a-windows-process-is-running 34614 その為に PROCESS_QUERY_INFORMATION を指定して OpenProcess する。 34615 34616 % 実装して動かそうとしたら駄目。 34617 % unlink に失敗している。unlink せずに真面目に rename する事にしてみたが、 34618 % それも失敗した。どういう事だろうか。開いていると rename できないのか、 34619 % 或いは tmp に作成しているから rename できないのか。。色々試す必要がある。 34620 % 34621 % HOME に作ったファイルは rename で移動できる。 34622 % tmp の下の $_ble_base_run に作ったファイルも rename で移動できる。 34623 % うーん。変だファイルを開きっぱなしにしていてもちゃんと移動できる。 34624 % 更に移動した後も続きが書き込まれているという事を確認した。 34625 % →これは結局 is_file の実装のバグだった。return FALSE するのを忘れていた。 34626 % 34627 % それならば rename せずに unlink でも行けるかもしれないと思ったが駄目だった。 34628 34629 取り敢えず何となく動く様にはなったが、 34630 沢山入力すると permission denied のエラーが発生する。うーん。 34631 そもそも入力を受け取る度にファイルを作成するというのも効率が悪い。 34632 特定の回数毎に開き直すという実装でも問題ないのではないかという気がする。 34633 ファイルを開き直すのは時々にするという手もあるのかもしれない。 34634 →と思って試してみた所駄目だった。どうも dup するともう使えなくなる様だ。。 34635 34636 ではエラーメッセージを封じるのか? というと難しい。 34637 エラーメッセージを封じる為には 2 をリダイレクトしなければならないが、 34638 今は 2 の接続先を変更したいので 2 をリダイレクトする訳には行かないのである。 34639 うーん。最初に適当なファイルに繋いで、それから 2 をリダイレクトする? 34640 34641 [関連項目] 34642 34643 * fixed: この bleopt_internal_ignoreeof_trap という変数は意味があるのか? 34644 サブシェルの中で見ているので親シェルで設定が変化しても追随できない。 34645 寧ろ、受信する側で bleopt_internal_ignoreeof_trap に応じて無視するべきでは。 34646 或いは、bleopt_internal_ignoreeof_trap が空ならそもそも対策コードを実行しない。 34647 →これは抑もの bleopt_internal_ignoreeof_trap の使い方が間違っていた気がする。直した。 34648 34649 2020-02-07 34650 34651 * MSYS 1.0 を使ってみたら全然動かない [#D1272] 34652 34653 * msys の version 判定は uname -r を実行すれば良い。 34654 というか _ble_term_CR が空かどうかで判定できる気がする。 34655 34656 * MSYS1.0 に至っては _ble_term_CR=$'\r' ですら効かない様だ。 34657 仕方がないので _ble_term_cr=$'\e[G' で代用すれば良い。 34658 34659 ? check $_ble_base_cache/cygwin.term 34660 cygwin.term を確認してみると cr, ich, dch, ech, Ss が空欄になっている。 34661 重要なのは cr だけである。それなのに _ble_term_cr=$'\e[G' しても未だ変だ。 34662 他に実装されてはいるが振る舞いが変な制御機能があるという事なのだろう。 34663 例えば RI や IND が実装されていないという事だろうか。 34664 34665 ? yes: これは cygwin console か? 34666 というより TERM を cygwin にしているがこれは本当に cygwin console か? 34667 実は cygwin pseudo console の気がする。と思ったが実際に実行してみると 34668 256色対応もちゃんとできていないのでこれは pseudo console ではない。 34669 やはり cygwin console なのである。 34670 pcon に切り替える機能は実装されていないだろうから当然である。 34671 丁度 cygwin-3.0.7 と同様に特別な事をしていなければ cygwin console なのである。 34672 34673 * fixed: _ble_term_xenl と _ble_term_ind を修正したら何となく動く様になった。 34674 34675 ? ok: xenl が効いていない? 34676 % しかしよく見てみると _ble_term_xenl=1 にすると無条件に eol mark が表示される。 34677 % _ble_term_xenl=0 にすると無条件に eol mark が表示されない。 34678 % と思ったがこれは勘違いである。echo hello として eol mark が表示されないと勘違いした。 34679 34680 * fixed: getent が無いというエラーメッセージが出る。 34681 →検査している気になっていたが実は bash 3.1 では、 34682 type a b c の中で一つでも存在していれば成功するという事なのか? 34683 →どうもその様である。つまり ble.pp にあるコードは修正する必要がある。 34684 調べた所 Bash 4.0 以上で全てのコマンドが見つかった時に真になる様だ。 34685 修正した。 34686 34687 * fixed: よく考えたら構文解析で bash version をチェックするのを忘れていた。 34688 34689 * MSYS2 では paste-from-clipboard という readline 関数が追加されている様だ? [#D1271] 34690 確認するとやはり paste-from-clipboard は cygwin 版の bash にはない。 34691 何れにしても新しく対応する事にする。これは /dev/clipboard を見れば良い。 34692 →実装した。動作確認した。動いている。OK 34693 34694 * msys2: 端末の座標計算が時々おかしい。 [#D1270] 34695 https://github.com/akinomyoga/ble.sh/issues/40#issuecomment-582941178 34696 34697 DA2R を見ると mintty 30000 の気がする。 34698 実際に Options... を開いてみると mintty 3.1.0 is available 34699 という感じの内容が表示される。 34700 34701 或いは何か msys の terminfo か tput が壊れているという事だろうか。 34702 うーん。これについてもちゃんと調べる必要がある。 34703 取り敢えず cygwin の term cache と比較してみる? 34704 34705 → xterm-256color.term (Cygwin) と xterm.term (MSYS2) を比較してみたが、 34706 着色と DECSCUSR しか違いは見られなかった。これらは配置には関係ない。 34707 従って、やはり MSYS2 の mintty の振る舞いが変なのだという気がする。 34708 もしそうだとしたらどの様にして変な振る舞いの原因を特定するのか。 34709 そしてどの様にして workaround をすれば良いのか。 34710 結構面倒な問題である。そもそも他の端末で異常は発生していない。 34711 もし純粋に mintty のバグであるのであれば、これは ble.sh で対処しなくても良い。 34712 34713 これは CR が効いていないという事? 或いは stty の状態が変? 34714 以下は stty -a の diff である。微妙な違いはあるが関係ない気がする。 34715 実際に cygwin を msys 側に合わせてみたが問題は再現しない。 34716 | --- stty -a (cygwin)^I2020-02-07 07:21:43.088892300 +0800 34717 | +++ stty -a (msys)^I2020-02-07 07:21:47.549238700 +0800 34718 | @@ -4,7 +4,7 @@ 34719 | werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0; 34720 | -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts 34721 | -ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff 34722 | --iuclc ixany imaxbel iutf8 34723 | +-iuclc -ixany imaxbel -iutf8 34724 | opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 34725 | isig icanon iexten echo echoe echok -echonl -noflsh -tostop echoctl echoke 34726 | -flusho 34727 次に CR の振る舞いを確認する。特に問題なく動いている様に見える。 34728 何と ${#_ble_term_cr} を出力してみたら中身が空である。。 34729 34730 分かった。_ble_term_cr='^M' を実行すると中身が空になる。 34731 _ble_term_cr=$'\r' だと大丈夫。 34732 その他の駄目なパターンはあるだろうか。 34733 変数に入っている _ble_term_cr の場合は大丈夫の様だ。 34734 34735 うーん。これの対策方法は不明である。 34736 a 一つの方法は _ble_term_cr で CR を使わないという方法。 34737 別の制御機能 (hpa) 等を用いて _ble_term_cr を模倣する。 34738 これの問題は本当に CR が欲しい所で _ble_term_cr を使っている箇所がないかという事。 34739 確認してみた所そういう場所はないようである。 34740 b もう一つの方法は _ble_term_cr=$'\r' という形式で記録するという事。 34741 うーん。前者の方が楽だが、こちらの方が妥当の気がする。 34742 declare-print-definitions を修正する? 34743 修正したほうが良い気がする。もし MSYS2 でこれが一般に問題になるのであれば、 34744 その他の場所で記録した CR も消滅するという事である。 34745 という事であれば declare-print-definition 等で根本から修正する必要がある。 34746 34747 declare -p の振る舞いについて確認しておく。 34748 34749 bash-3.1 declare -- a="\$" bash-3.1 declare -a a='([0]="\$")' ")'h-3.1 declare -a a='([0]=" 34750 bash-3.2 declare -- a="\$" bash-3.2 declare -a a='([0]="\$")' ")'h-3.2 declare -a a='([0]=" 34751 bash-4.0 declare -- a="\$" bash-4.0 declare -a a='([0]="\$")' ")'h-4.0 declare -a a='([0]=" 34752 bash-4.2 declare -- a="\$" bash-4.2 declare -a a='([0]="\$")' ")'h-4.2 declare -a a='([0]=" 34753 bash-3.0 declare -- a="\$" bash-3.0 declare -a a='([0]="\$")' ")'h-3.0 declare -a a='([0]=" 34754 bash-4.1 declare -- a="\$" bash-4.1 declare -a a='([0]="\$")' ")'h-4.1 declare -a a='([0]=" 34755 bash-4.3 declare -- a="\$" bash-4.3 declare -a a='([0]="\$")' ")'h-4.3 declare -a a='([0]=" 34756 bash-4.4 declare -- a="\$" bash-4.4 declare -a a=([0]="\$") bash-4.4 declare -a a=([0]=$'\r') 34757 bash-5.0 declare -- a="\$" bash-5.0 declare -a a=([0]="\$") bash-5.0 declare -a a=([0]=$'\r') 34758 34759 どうも declare -p は一貫して ".." に囲んで出力する様だ。 34760 但し、Bash 4.4, 5.0 で制御文字が含まれている場合を除く。 34761 Bash 4.4, 5.0 の場合にはそもそも ^M が含まれないという事だから、 34762 ^M が含まれる場合には "" の中にあると仮定して良いだろう。 34763 従って ^M を $_ble_term_CR に変換する。 34764 _ble_term_CR は本体の方で直接 $'\r' を代入すれば良いだろう。 34765 34766 固定文字列とそうでない物は大文字と小文字で区別する事にする。 34767 * _ble_term_{soh,del,fs} も変更する? 34768 * 然しそうすると _ble_term_nl も変更しなければならず面倒だ。 34769 取り敢えず _ble_term_nl は出力に使っているから変更は保留。 34770 他は特殊用途でしか使っていないのである。 34771 34772 取り敢えず動いている気がする。これで良い。 34773 ble-0.3 に移植した。動いている。OK 34774 34775 * ble-decode/has-input [#D1269] 34776 →これはマージのミスだった。修正した。 34777 34778 2020-02-06 34779 34780 * [勘違い] msys2: inputrc の `$if` が正しく解析されていない [#D1268] 34781 https://github.com/akinomyoga/ble.sh/issues/40#issuecomment-582941178 34782 34783 うーん。これはシェルコマンドに変換している筈なので、 34784 そんなに問題になる事はない筈。 34785 一旦どの様なシェルコマンドに変換されているのか確認する必要がある。 34786 34787 →これは実はちゃんと処理できていた。勘違いだった。 34788 paste-from-clipboard という関数が定義されている特別な状況に対する 34789 $if なのかと思ったが、実は MSYS bash は拡張機能として 34790 paste-from-clipboard という機能が用意されているのだった。 34791 34792 * inputrc のコメントが正しく除去されていない [#D1267] 34793 https://github.com/akinomyoga/ble.sh/issues/40#issuecomment-582941178 34794 34795 元々の実装の時にコメントは実は行頭から始まらなければならない 34796 という事を確認したのではなかったのか。 34797 これについても実際に試して調べる必要がある。 34798 34799 "\C-t": end-of-line 34800 "\C-t": end-of-line # hello ->comment 34801 "\C-t": end-of-line# hello ->not-comment 34802 "\C-t": "end-of-line # hello" ->not-comment 34803 34804 うーん。ちゃんと quote も考えた上での処理になっている様だ。 34805 そして # は単語の先頭でなければならない。 34806 更に、bind '...' に指定した時でもちゃんと # をコメントとして認識している。 34807 bind -x '"\C-t": echo hello # world' の場合には # world 以降もコマンドの一部になっている。 34808 bind '"\C-t": "echo" # world' の場合にはコメントとして取り扱われている。 34809 single quote でも実はマクロとして取り扱われ、 34810 中にある # はコメントとして取り扱われてしまう事はない。 34811 $ bind '"\C-t":'\''echo\'\'' # \'\''world test'\' 34812 で試してみた所 echo' # 'world test という文字列が登録できたので、 34813 single quote の中でも \' は有効なのだと思われる。 34814 34815 取り敢えず実装した。未だ見落としがあるかもしれないが取り敢えずこれで良い気がする。 34816 34817 * ble-0.3 に於ける ble-reload は未だにおかしい [#D1266] 34818 https://github.com/akinomyoga/ble.sh/issues/40#issuecomment-582941178 34819 34820 Ref: #D1223 #D1199 #D1130 34821 34822 ble-update を ble-0.3.2 に対して実行してみたら 34823 PS1 等の環境変数が失われている。というかコマンド実行されている? 34824 直した筈の問題が直っていない。 34825 取り敢えず一番最初に修正するべきなのはこれの気がする。 34826 34827 commit d35682a で導入した .prologue 呼び出しを 34828 commit 59c1ce4 で別の場所に移動している。 34829 これは ble-0.3 ではどの様に適用されているだろうか。 34830 ble-0.3 に適用したのは ce93c08 である。 34831 別に prologue が消滅する等の事は起こっていない。 34832 34833 うーん。実際に症状を確認してみると [ble: detached] と表示されている。 34834 改めて cygwin で確認してみると再現する。やはり MSYS2 特有の問題ではない。 34835 ble-0.4 では再現しないので ble-0.3 特有の問題である。 34836 取り敢えず [ble: detached] を手がかりに調べる。 34837 34838 どうも。ble-reload を --attach=prompt にしたのにも拘らず、 34839 check-detach において prompt-attach の時の処理を省略したのが原因の様だ。 34840 改めて色々ちゃんと動くか確かめる事にする。 34841 * ble-detach 34842 * ble-attach 34843 * ble-detach && ble-attach 34844 * ble-reload 34845 * source ble.sh --noattach && ble-attach 34846 * source ble.sh --noattach 34847 * source ble.sh --attach=prompt 34848 * source ble.sh --attach=attach 34849 34850 一応何れも問題なく動いている様な気がする。 34851 34852 * ble-reload && PROMPT_COMMAND= 34853 34854 これは駄目だった。。。どの様にするのが良いだろうか。 34855 修正した。PROMPT_COMMAND を再度上書きする方式で良かった。 34856 改めて上記のテストも行った。全て大丈夫である。 34857 34858 * msys2: root 権限があるかどうかの判定ができない [#D1265] 34859 https://github.com/akinomyoga/ble.sh/issues/40#issuecomment-582941178 34860 34861 cygwin の手法を流用しようとしたら常に root 権限がある事になってしまう。 34862 調べてみると全てのユーザを msys を起動したユーザと見せかけている。 34863 然し、実際には異なるので何か書き込もうとすると permission denied で失敗する。 34864 というか Windows の標準のコマンドで管理者権限が在るかどうか 34865 判定できる物はないのだろうか。 34866 34867 或いは EUID もしくは UID を見たら分かったりするだろうか。 34868 34869 と思ったら実際に起動してみると何故かちゃんと判定できている。 34870 判定には EUID を用いているが実際に EUID を実行してみても 0 ではない。 34871 しかも $_ble_edit_prompt__string_root を出力してみると '$' である。 34872 何処で入れ替わっているのか?? 或いはもしかして元の bash の PS1 が表示されている? 34873 34874 と思ったら分かった。そもそも PS1 に # がハードコードされている。 34875 逆に言えば何処かに判定するコードが存在しているという事である。 34876 探せば良い。 34877 34878 今これが作業中なのでこれについて調べる事にする。 34879 /etc/bash.bashrc に検出コードがある。 34880 if [[ -n "$(command -v getent)" ]] && id -G | grep -q "$(getent -w group 'S-1-16-12288' | cut -d: -f2)" 34881 then _ps1_symbol='\[\e[1m\]#\[\e[0m\]' 34882 else _ps1_symbol='\$' 34883 fi 34884 34885 これを見ると、_ps1_symbol が定義されていて # を含んでいたら privileged と思って良い。 34886 と思ったが、その直後に unset しているので駄目だ。役に立たない。 34887 自分で改めて同様のコードを走らせる必要があるだろうか。 34888 上を参考にして実装した。動作確認した。OK 34889 34890 * msys2 で動かない [#D1264] 34891 https://github.com/akinomyoga/ble.sh/issues/40 34892 34893 見た所 sleep の実装が火を吹いている。cygwin と同じ取扱で良いだろう。 34894 取り敢えず動くには動く様になった。 34895 34896 その他調べると色々と振る舞いがおかしい。 34897 これらは別項目で処理する事にする。 34898 34899 うーん。面倒なので proghl を merge してしまう事にしよう。 34900 34901 2020-02-05 34902 34903 * decode: fix error message "command=${[key]-}" for mouse input [#D1263] 34904 マウスは正式対応していないが contra のテストで有効にして 34905 試していたらエラーメッセージが出る。 34906 確認してみると、思い切り未初期化の変数を参照している。修正した。 34907 34908 2020-02-03 34909 34910 * 2020-01-17 Minix における問題 [#D1262] 34911 34912 x resolved: ble-reload の後に固まる問題ももしかしてこれだろうか? 34913 と思ったが症状的に独立な問題だろう。 34914 →これは別項目で修正した。 34915 34916 x ok: minix を試していると固まる。と思ったら core.784 として巨大な 34917 ファイルができている。1.7GB である。道理で固まる訳である。 34918 ファイルシステムが固まるので他のプロセスもブロックされる。 34919 検索すると以下の頁が見つかるが余り参考にはならない。 34920 https://wiki.minix3.org/doku.php?id=soc:2011:debugger 34921 34922 而もこれは ble-detach した状態であった。但し CPU は 100% ではなくて 34923 50% になっていた。何らかの別の原因で segfault して、 34924 その結果として core を dump するのに忙しくて 50% になっていたと 34925 考えるのが自然である。 34926 34927 これは恐らくまた別の問題である。これに関しては気にしない事にする。 34928 34929 x ok: set: tabcomplete というオプションはありませんというエラーになる。 34930 /etc/profile に set -o tabcomplete というのが記述されている。 34931 bash にはその様なオプションはない (或いは過去のバージョンにはあったのだろうか)。 34932 →これは minix の問題であって ble.sh の問題ではない。 34933 34934 * TERM=minix support 34935 x fixed: 起動時に c という文字が現れる事について。 34936 x fixed: コマンドを実行する度に 200404;1 等と表示される。 34937 これは明らかに bracketed paste mode と modifyOtherKeys である。 34938 どうやら CSI ? h ですら minix は対応していない様だ。 34939 取り敢えず対応した。他にも CSI ? を使っている箇所は在る気がする。 34940 x fixed: eof 判定が動いていない。xenl cap が誤っている? 34941 xenl=0 にしてみても変化はなかった。 34942 取り敢えず行末での振る舞いがどうなっているか調べる必要がある。 34943 →一応 xenl の様な気がする。今の実装はどうなっているのだったか。 34944 →どうやら SC,RC を使っている様だ。SC,RC を使わない実装? 34945 →使わない実装に切り替えて見た。多分大丈夫。 34946 x fixed: SCOSC,RC が動いていない。tput sc / tput rc は失敗する。 34947 \e7\e8 も動かない。恐らく minix にはないのだろう。 34948 これの対策は何? 先ず離れた場所に移動しない。 34949 一行上か或いは panel 3 を利用する。 34950 一行上を利用するのが自然の気がする。 34951 34952 ? 然し、delay 後のカーソル位置を取得する方法が分からない。 34953 特に delay は別プロセスで実行しているので、 34954 そのプロセスは fork 時の _ble_canvas_x しか知らない。 34955 メッセージを消去するのは諦める? 34956 →諦める事にした。 34957 - canvas.sh 未ロード時の vbell も rc を使っているが、 34958 対応はしない事にする。実際、使われていない気がする。 34959 使っているとしても稀なので気にしない事にする。 34960 x fixed: delete が ^? になっている。 34961 これは tput kD || tput kdch1 を参照して決める事にした。 34962 x fixed: C-r が効かない ... reprint undef にしたら直った。 34963 これも対策を加えた。 34964 34965 * locale: 例によって locale を切り替えられないというエラーが出ている。 34966 何処から発生しているのだろうか。一つずつ確認していくしかない? 34967 34968 取り敢えず補完で沢山メッセージが出るので source:argument を塞いで見たが沢山出る。 34969 どうも関係ない様だ。そもそも起動した時にエラーメッセージが出る。 34970 34971 これらは単体で実行しても特に変なメッセージは出ない。 34972 done: ble/util/.has-bashbug-printf-uffff 34973 done: ble/util/is-stdin-ready 34974 done: ble/util/msleep/.check-sleep-decimal-support 34975 34976 以下の関数は対策が必要な気がする。 34977 done: ble/widget/.locate-forward-byte 34978 ok: ble/decode/bind/.generate-source-to-unbind-default 34979 done: ble/builtin/bind/.parse-keyname 34980 done: ble/builtin/bind/.reconstruct-user-settings 34981 done: ble/widget/vi-command/nth-byte 34982 34983 % どうも ble/util/is-stdin-ready が怪しい気がする。 34984 % と思って色々変更してみたがどうも関係ない様だ。 34985 34986 改めて補完の振る舞いを調べるとメニューを表示する時に、 34987 メニューの項目と同じ数だけメッセージが表示される様だ。 34988 trace が悪いという事だろうか? 34989 ble/canvas/trace-tex を手で実行してみたら再現した。 34990 こういう関数で再現する事が分かった。 34991 どうもローカル変数の始末は 2>/dev/null がなくなってから? 34992 34993 fun() { local LC_COLLATE=C; } 2>/dev/null 34994 34995 trace-text を修正したらメッセージは出なくなった。 34996 34997 * 2020-01-17 Haiku における問題 [#D1261] 34998 34999 x ok: Haiku で ble-reload 時に変なメッセージが出る。 35000 まあこれは bash-4.4 の問題かもしれない。 35001 →CentOSでやると日本語でエラーメッセージが表示されていて、 35002 その長さなどが一致している気がするので Haiku のエラーメッセージは 35003 やはり bind 回りの Bash のバグだろう。 35004 35005 x ok: また、sleep を呼び出すと Terminal のタイトルバーに 35006 それが一々表示されて面倒である。別の実現方法を考えた方が良い? 35007 もし /dev/zero があるならば /dev/zero を読み出そうとするとどうなるか確認してもよい。 35008 CPU を食わないのであればそれで行く。 35009 35010 →read -t 1.0 でも同様に Terminal のタイトルが変更される。 35011 どうも何のプログラムであってもブロックされていると何か出る様だ。 35012 短い read -t 0.01 をループで回しても同じだった。 35013 なのでこれはどうしようもない。 35014 35015 2020-02-02 35016 35017 * decode: 遅延 bind で正しい key に割り当てられていない [#D1260] 35018 これは cmap が初期化されていないのに ble-bind を呼び出したからである。 35019 bashrc の中から ble-bind も bind も呼び出される可能性がある事を考えると、 35020 cmap/initialize 及び decode/initialize はそれぞれ ble-bind, bind から 35021 呼び出す様にしておかなければならない。もしくは初めから呼び出しておく。 35022 ble-bind がある度に初期化済みかどうかを確認するのは非効率的だろうか。 35023 余り考えない事にする。そもそも ble-bind は重いので気にしない。 35024 35025 序でに blerc を遅延で読み込む事も考えてみたが、 35026 ble.sh による PS1 等を待避した特別な環境で評価すると変な事になるので、 35027 やはり今まで通り最初にロードする事にする。 35028 35029 一連の変更により ble-bind は自動的に遅延される様になったので、 35030 eval-after-load により手で遅延させる必要がなくなった。 35031 これに伴い wiki の記述も変更して良いのでは→更新した。 35032 35033 * 2019-02-09 bind: `bind -XpPS` 等から現在の設定を読み取る? [#D1259] 35034 35035 現状で bind -X が信用出来ないので、完全な対応は不可能である。 35036 その様に考えるとやはり builtin bind を上書きして設定を読み取る方が現実的である。 35037 なので、現在の bashrc の冒頭でロードして、末尾で attach するという形式は当面変わらない。 35038 35039 * Note: 2019-12-14 bind -X については bash に修正が入った。 35040 https://lists.gnu.org/archive/html/bug-bash/2019-12/msg00053.html 35041 35042 * Note: 2019-12-30 detach 時の復元に関して。 35043 現状では bind -X の設定を読み込んでから 35044 bind -ps の設定を読み込む様にしている。 35045 これで古い bind -x の設定によって bind -ps の設定が上書きされてしまう事はなく、 35046 逆に bind -x の設定を bind -ps で上書きした後には ble.sh の復元でも上書きされる。 35047 問題が起こるのは bind -x した後にそれを bind -r して、 35048 それ以降に何も bind していない場合である。 35049 試してみたが何にも bind していないキーは列挙されない。 35050 35051 * Note: 2019-12-30 特にこの項目が意図しているのは 35052 detach 時の復元ではなくて attach 時に ble.sh keymap に反映させるという話である。 35053 一方で bind -Xps の出力は \C-\ の振る舞いが微妙なので色々面倒である。 35054 35055 2020-02-01 やはり README を読まずにいきなり bashrc の末尾で source して 35056 ble.sh が key binding を上書きしている。unbind が設定できるようにするべき、 35057 等と言いがかりをつけて来る人が現れた。やはり bind -Xps から設定を読み取れる様にしたい。 35058 35059 ? Bash \C-\ vs \C-\\ Bug の処理 35060 さて、その時に問題になるのが C-\ をどう解釈するのかという事。 35061 取り敢えず \C-\M または \M-\C 以外の時は単独で解釈する事にする? 35062 否、\C-\\ も特別扱いしなければならない。うーん。 35063 →これは ble/builtin/bind の実装の問題なので別に考えるべき事? 35064 或いは ble.sh では \C-\\ に対応する事にして、 35065 但し、bind の出力は補正して記録する様にする。という事? 35066 そもそも補正する事は可能なのだろうか。 35067 35068 先ず、既定の設定との差分を取りたい。 35069 取り敢えず既定の設定は以下の様な感じにして取得できる。 35070 bash-$a --norc -i -c 'bind -p' | sed '/^#/d;s/"\\M-/"\\e/' 35071 既定の設定との差分はどの様にして取るのが良いか。 35072 diff を呼び出してその結果を解析するのは面倒である。 35073 それならば awk で複雑になるかもしれないがちゃんと処理する方が良い気がする。 35074 →取り敢えず awk を使って検出できる様にはなった。 35075 然し、検出した物をどのタイミングで評価すれば良いのか。 35076 35077 inputrc を読み取る作戦にしていた時はどのようにしていたか。 35078 うーん。inputrc の読み取り自体を遅延して、 35079 最初に bind を呼び出した時に読み出す様にしていた気がする。 35080 →やはりそうなっている。 35081 35082 ? では何故その場で bind を評価する様にしていたのか。 35083 35084 | 何故 bind 自体を遅延する様にしていなかったのか。 35085 | これには何か理由があった様な気がするが思い出せない。 35086 | →inputrc の読み取りに最初に対応したのは #D1038 であった。 35087 | inputrc の読み取りのタイミングについて議論があるのは #D1127 である。 35088 | ここでの議論によると、bind をした順序によってどちらが上書きされて 35089 | どちらが残るのかが変わるので順序は変更できない。 35090 | なので、bind を実行する前に inputrc は読み込んでおかなければならない、 35091 | という話になっている。 35092 35093 bind の順序を保持する為に bind 前に inputrc を読んでおく必要があるという話 35094 35095 それならば全ての bind を遅延させる事にしておけば問題ないという気がする。 35096 35097 [実装] 35098 35099 * done: bind の評価は keymap 初期化迄遅延する様にする #D1258 35100 * done: readline 既定の設定をキャッシュする 35101 これは簡単。 35102 * done: ユーザ設定を読んでそれを反映させる。 35103 これも実装した。特に問題なく動いている気がする。 35104 35105 * done: \C-\, \C-\\ の補正の可能性 35106 https://lists.gnu.org/archive/html/bug-bash/2020-01/msg00037.html 35107 そもそも ble/builtin/bind ではどの様に解釈していたのだったか? 35108 と思って確認してみると ble/util/keyseq2chars で解釈している。 35109 35110 ble/util/keyseq2chars の解釈は微妙に間違っている気がするので、 35111 新しい Bash-5.1 の解釈に合わせて更新することにした。 35112 取り敢えず動いている様である。 35113 35114 更に、bind の出力結果をこの形式に合うように補正する事を考える。 35115 どの様に補正するか? 取り敢えず \C-\ の次に \ が来て文字列が終わっている場合は OK 35116 それ以外の場合には \C-\ は C-\\ に修正するべきなのである。 35117 →修正するコードを書いた。 35118 35119 取り敢えず動いている。良いのではないだろうか。 35120 但し、bind -X は Bash 4.3 以降でしか使えないので、 35121 Bash-4.3 以降でしか "何処でも source ble.sh できる" とは書けない。 35122 35123 * decode: bind の評価を keymap 初期化迄遅延 [#D1258] 35124 35125 どの keymap に記録する様にするのが良いのか。 35126 1. bind に直接 -m が指定されている時はそれを使う。 35127 2. bleopt で keymap が指定されている場合にはそれを使う。 35128 inputrc の中ではそれは無視する? うーん。 35129 inputrc の中で keymap を指定している時にはそれを使う。 35130 或いは bind 経由の時には ble の keymap は無視して、 35131 その時の vi/emacs の keymap で処理してしまって問題ない? 35132 取り敢えず default_keymap は考えずに実装する。 35133 そもそも今迄もその様に実装していたのではなかったのか。 35134 35135 実装を辿っていくと 35136 ble-decode-key/{bind,unbind} 辺りが最終的には呼び出されている。 35137 ble/builtin/bind の枠組みよりは更にその上の枠組に於いて、 35138 bind の呼び出しを遅延させる方が実装として自然である。 35139 その様に修正する事にする。 35140 35141 現在の実装では ble-decode/DEFAULT_KEYMAP を呼び出した時に 35142 keymap も完全にロードしてしまう仕組みになっている。 35143 うーん。完全にロードする必要がない時には別の関数を呼び出す? 35144 35145 * done: ble-decode-key/bind の引数に kmap を指定する様に変更する 35146 * done: DEFAULT_KEYMAP は INITIALIZE_DEFMAP に改名した 35147 35148 うーん。遅延させる様にしようとしたが、 35149 これだとあらゆる keymap が遅延されてしまう。 35150 どのタイミングで具体的に keymap を生成するのか。 35151 遅延させるのは default-keymap だけで良いのではないのか。 35152 35153 そもそも現在の keymap の初期化順序としてどのような可能性があるのか分からない。 35154 ? INITIALIZE_DEFMAP は必ず通過するのか? 調べてみたがそうでもない気がする。 35155 以下の様な構成になっている。 35156 35157 | ble-decode/keymap/load 35158 | <del>ble/util/import "keymap/$1.sh"</del> 35159 | ble-decode/keymap:$1/define 35160 | ble-decode/keymap/register "$1" 35161 | 35162 | ble-decode/keymap/push 35163 | ble-decode/keymap/load 同上 35164 | 35165 | ble/builtin/bind/.initialize-kmap 35166 | ble-bind/load-keymap 35167 | ble-decode/keymap/load 同上 35168 | ble-bind 35169 | ble-bind/load-keymap 35170 | ble-decode/keymap/load 同上 35171 | 35172 | ble-edit/bind/load-keymap-definition 35173 | ble-edit/bind/load-keymap-definition:"$name" 35174 | source "$_ble_base/keymap/$name.sh" 35175 | ここでは /define までは必ずしも呼び出さない。呼び出す場合もある。 35176 35177 * done: ble-decode/keymap:$1/define の中で regiter, onload を呼び出す。 35178 と思ったが /define の呼び出し元が限られているのだとすれば、 35179 呼び出し元を本当に制限して、呼び出し元の側で必要な処理を実行すれば良い気がする。 35180 35181 /define の呼び出し元を列挙する。結局本質的に一箇所しか無い様なのでOK 35182 35183 と思って修正したが、よく考えると各 editing-mode でのキャッシュは 35184 onload でユーザの指定した修正を適用する前の物を dump しなければならない。 35185 うーん。opts=raw とした時には onload は実行しない様にする? 35186 或いは opts=dump とした時に特定の fd に対して raw の定義を出力する? 35187 後者を採用する事にした。 35188 35189 * done: ble-decode/keymap:$1/define に関しては keymap/$1.sh は参照しない。 35190 これは本当にそれで良いのだろうか。 35191 将来的にはこちらの方を keymap/$1.sh にして、editing mode の方を別名にするべきでは。 35192 と思ったが現状で利用していないのでそれで良い。 35193 それにその keymap を利用する機能がロードされた時に 35194 ble-decode/keymap:$1/define が定義される様に計らうべきである。 35195 よって、 ble-decode/keymap/load からは keymap/$1.sh のロードは削除する。 35196 * done: ble-edit/bind/load-keymap-definition の中の source は import に置き換える。 35197 * done: ble-edit/bind/load-{keymap-definition -> editing-mode} 35198 x fixed: 見事に起動しなくなった。駄目だ。うーん。ble-bind が動いていない様だ。 35199 →これは簡単なミスだった。修正した。 35200 * done: /define の中で自分で ble_bind_keymap 等を設定しなくても良くなった。削除する。 35201 削除した。動いている。 35202 35203 | 結局、以下の様な仕組みになっている様だ。 35204 | 35205 | 1. 先ず初めに編集モード全体の読み込みを行う 35206 | ble-decode/INITIALIZE_DEFMAP 35207 | ble-edit/bind/load-editing-mode 35208 | ble-decode/keymap:$1/define の存在を保証 35209 | 2. 次に必要になった時に各 keymap を初期化する 35210 35211 * done: ble/builtin/bind/.initialize-kmap, ble-bind/load-keymap の呼び出しを省略する 35212 取り敢えずこれらの関数では basemap 名の取得に留める事にした。 35213 * ble-decode/INITIALIZE_DEFMAP の呼び出しを削減する。(初期化を遅延する) 35214 * done: ble/builtin/read で ble-decode/keymap/push read する前に 35215 ble-decode/INITIALIZE_DEFMAP を呼び出していたが無駄な気がするので削除する。 35216 これは本当に大丈夫だろうか? keymap/pop した後に固まる可能性は? 35217 →やはり keymap/pop した後も _ble_edit_read_accept=1 経由で停止するので、 35218 元々設定されていた keymap が使われるという事は起こらない。 35219 やはりなくて良い気がする。 35220 * ok: ble-decode/INITIALIZE_DEFMAP を適切な名前に変更 35221 これは現状のままで良さそうな気がする。 35222 * done: .onload で遅延させた設定を読み込む様にした 35223 35224 * ok: keymap:*/define に対して軒並み autoload しているが 35225 % これは今でも必要だろうか。今回の改修で不要になった可能性は? 35226 % 元々の動機を調べて不要になったのであれば削除する。 35227 →これはやはり ble-bind で変な keymap に誤って登録しない為に、 35228 どの様な keymap が存在するかを事前に分かる様にする為に残す事にする。 35229 35230 [動作確認] 35231 35232 本当に遅延されているのだろうか? 初期化のタイミングを調べれば良い。 35233 x fixed: bind.delay.$keymap の中を覗くと引数が全く保存されていない。 35234 これは ble/util/pritn-quoted-command のバグだった。修正した。 35235 取り敢えず遅延はされている様である。 35236 しかし、widget が見つからないというエラーメッセージが出る。 35237 うーん。widget のチェックも遅延させるべきだろうか? 35238 35239 2020-02-01 35240 35241 * syntax: ((1))a と入力するとエラーメッセージが出る [#D1257] 35242 これは恐らく着色のコードが悪い。修正した。 35243 coproc 対応の時の抜けだった。 35244 35245 * Bash Readline 束縛との互換性 [#D1256] 35246 fzf の様な既定の bash の binding を想定する様な枠組みの場合、 35247 ble.sh 側の binding が少しでも違うと動かなくなる。 35248 その意味でちゃんと何れの機能もそれなりに同じ振る舞いをする様になっているか? 35249 35250 * emacs mode に関しては全ての widget に対応している。 35251 binding に関しては完全に一致させているか確認していないが、 35252 だいたい大丈夫だろうという気がする。問題が出てから対処すれば良い。 35253 35254 * vi に関しては未だ対応していない機能が幾らかある。 35255 しかしこれらは default の binding を持つものだろうか? 35256 35257 vi-back-to-indent 35258 vi-complete 35259 vi-eof-maybe 35260 vi-overstrike 35261 vi-overstrike-delete 35262 vi-tilde-expand 35263 vi-yank-arg 35264 vi-yank-pop 35265 35266 確認する必要がある。 35267 35268 * vi_nmap: 35269 * done: backward-word (C-left, M-left) forward-word 35270 実はこれらに関しては既に登録されている。 35271 vi-command/forward-vword (C-left) 35272 更に M-left, M-right にも対応する? 35273 特に vi_nmap ならば M- を設定しても問題ない気がする。 35274 然し本当に問題ないだろうか。 35275 35276 isolated ESC 関係の判定は ble-decode/uses-isolated-esc で行っている。 35277 中を確認すると vi の時には問答無用で isolated ESC は ESC として処理される。 35278 M- 束縛があっても M- 修飾にはならない様である。 35279 なので M-... を束縛しても問題は起こらない。 35280 35281 然し、一方で他に何も M- が束縛されていない状態でこれを束縛するのは 35282 統一性にかけるのではないかとも思う。そもそも vi-command には他に 35283 M- は登録されていなかったのだろうか。或いは積極的に登録されている? 35284 →調べてみた所他には登録されていない。M-left, M-right だけが登録されている。 35285 35286 もう一つの問題として実際に CSI 1 ; 3 D や CSI 1 : 3 C を送る端末があるのか、という事。 35287 もしそのような端末が存在しないのであればわざわざここで対応する必要もないのではとも思う。 35288 然し、世の中には絶対はない。設定して問題ないのであれば設定しておいて問題もなかろう。 35289 という訳で設定する事にした。 35290 35291 * done: kill-word (C-delete) 35292 これに関しては新しく widget を作成する必要がある気がする。 35293 作成した vi-rlfunc/kill-word 35294 35295 * done: insert-comment (#) 35296 うーん。これに関してはどの様に対応するのが良いか。 35297 これは編集行に対する編集を伴う。 35298 その様なコマンドの実装例があるとやりやすい。 35299 35300 確認すると replace-char, undo ぐらいである。 35301 中を見ると両方とも 35302 ble/keymap:vi/mark/{start,end}-edit-area を使っている。 35303 35304 ble/keymap:vi/repeat/record はどのように呼び出せばよいのか? 35305 と思ったが insert-comment は実行を伴うので . で繰り返せるというのは変である。 35306 なのでこれは完全に無視して問題ない。 35307 35308 * done: quoted-insert (C-q, C-v: batting している) 35309 これは仕方がない。無視する。 35310 唯、widget は準備しても良いのかもしれない。 35311 35312 うーん。これはどうやって実装したら良いのだろうか。 35313 →丁度 vi-command/replce-char と quoted-insert を組み合わせれば良い。 35314 35315 * done: unix-line-discard (C-u: batting) 35316 これは現状では vi_nmap/backward-line-scroll になっている。 35317 難しい。unix-line-discard の方がシェルとしては自然な気がする。 35318 backward-line-scroll を実際に使っている人がどれだけいるのか? 35319 特にシェルでは複数行の操作をする事は余りない。 35320 という事を考えると unix-line-discard にした方が良い? 35321 然し、unix-line-discard が破壊的操作であると考えると現状の方が安全である。 35322 うーん。これも保留という事にする。 35323 35324 但し、明示的に unix-line-discard を bind した時に対応できるようにはするべき。 35325 35326 * done: vi-eof-maybe (C-d: batting) 35327 これは現在 bind されている機能とは違う物だろうか。 35328 →振る舞いを調べてみると vi-eof-maybe は現在のコマンドを実行する様だ。 35329 もし空の場合には終了する。 35330 →新しく widget だけ実装した。 35331 35332 * done: vi-tilde-expand (&) 35333 これは新しく実装しようとしたが @edit tilde-expand で良い気がする。 35334 35335 * vi-yank-arg (_) 35336 うーん。これの対応は面倒である。 35337 →readline の振る舞いを調べた所、一旦 insert-mode に入ってから 35338 挿入を行う様である。という事であれば対応はそんなに大変ではない。 35339 引数は認識していない気がする。 35340 35341 うーん。D と似たような感じに実装すれば良い? 35342 と思ったけれども違う。 35343 面倒なので append-mode を呼び出して self-insert, insert-last-argument 35344 を順番に呼び出すという安直な実装にした。多分これで大丈夫なのではないか。 35345 と思ったが irepeat による記録が行われていない…。うーん。 35346 35347 然し、insert-last-argument の様な複雑なモードの後も 35348 imap repeat が有効というのも変な気がするので、 35349 いっその事 imap repeat はキャンセルする事にする。 35350 35351 取り敢えず動いている様な気がするのでもう気にしない。 35352 35353 * ok: vi_imap に関しては対応できていない物はない気がする。 35354 35355 * ok: bash の s, S vi-subst は一体何? 35356 →これは s と S を共通の rlfunc から呼び出せる様にしたというだけの物だった。 35357 現状のままで振る舞いとしては一致しているので気にしなくて問題ない。 35358 35359 * fzf が動かないという問題の報告 (reported by jpninanjohn) [#D1255] 35360 https://github.com/akinomyoga/ble.sh/issues/38 35361 これは fzf が shell-expand-line & history-expand を使っている為に起こった問題である。 35362 彼は README を読んでいない。 35363 35364 ? 然し、何故 history-expand を実行する必要があるのだろうか。 35365 最初から展開結果の文字列を出力しては駄目だったのだろうか。 35366 末尾の改行の為? →試してみて分かった。shell-expand-line だと勝手に改行が削除される。 35367 35368 然し、試した結果 "`command`" ならば改行がちゃんと保持される様である。 35369 確かに echo `...` で生成すると単語分割の対象になって、 35370 改行の類は効果としては空白と同じなので自然である。 35371 * 然し、だからと言って fzf に "`__fzf_history__`" を提案したとすると、 35372 今度は ble.sh の側で明示的に quote された状態になってしまって動かない。 35373 従って、fzf に "`...`" の形式を提供しても意味がない。 35374 35375 * ble.sh の振る舞いを Bash の振る舞いに近づけるとしても。 35376 echo "echo hello" が echo echo hello に展開されたり、 35377 或いは "`...`" がコマンドの実行結果その物になったり、 35378 色々と振る舞いが異なるのである。 35379 35380 近づけるというよりは破壊的に変更しなければならない気がする。 35381 然し、元々の機能が echo "echo hello" を echo echo hello 35382 に変換してしまうぐらい潔い物なのだとしたら、 35383 逆にそれに合わせても良いのかもしれない等とも考える。 35384 35385 bash の振る舞いに合わせる事を考える。 35386 更に fzf の他の binding もちゃんと動くか確認する。 35387 35388 * done: shell-expand-line の振る舞いを bash と同様の物に修正する事にした。 35389 その前に bash の振る舞いについて再度確認しておく。 35390 35391 * 展開結果に含まれる quote は一切処理されない。 35392 ~$ function ff2 { echo '"echo hello"'; } 35393 ~$ echo `ff2` 35394 -> echo "echo hello" 35395 35396 うーん。quote を実行している一行をコメントアウトしただけで 35397 bash と同じ振る舞いになった様な気がする。 35398 shell-expand-line に引数として quote を与えなければ、 35399 bash と同じ振る舞いになる様に変更した。 35400 35401 o fzf の動作確認 35402 その他の binging (C-t, M-c) も試してみたがこれらは問題なく動いている。 35403 これでよしという事にする。 35404 35405 * syntax: eval の引数のファイル名が着色されていない [#D1254] 35406 というか、eval の引数はコマンドとして解釈しつつ着色したい気がする。 35407 一方で。'...' としてコマンドを記述できる事を考えると、 35408 awk '...' や sh -c '...' で考えているのと同様に着色したい気もする。 35409 35410 取り敢えずの所は引数として着色するのが妥当なのではないか? 35411 →確認してみると単語の種類は ARGEI になっている。 35412 補完はコマンド名になっている。 35413 着色はされていない。 35414 35415 % 分かった気がする。コマンドとして補完されているのは、 35416 % 恐らくコマンドラインの一番最初の単語になっているから。 35417 % eval a=() echo としていたので a=() の手前でコマンドラインが途切れている。 35418 % →と思って確認してみたが eval echo g++ としても全てコマンドとして補完される。 35419 35420 実装を確認すると CTX_ARGEI に variable:= command file が割り当てられていた。 35421 35422 x fixed: CTX_ARGEI の補完でディレクトリ名が a/ と a になっていて 35423 絞り込みが出来ていない。コマンドの場合にもディレクトリ名には / を入れずに、 35424 suffix に / を指定するべきでは。と思ったが、その場合にはコマンド名と 35425 ディレクトリ名が重複していた場合に問題にならないか。 35426 35427 更に言うと、異なる種類の見た目が同じ候補があった場合に 35428 どちらの action を採用するのかという問題が残る。 35429 結局、補完対象の文字列を合わせたとしても問題は解決しない。 35430 35431 そもそもコマンド名でもファイル名でもどちらでも良い、 35432 という文脈が不自然なのである。どちらか限定できる様にならないか? 35433 35434 →結局この文脈ではコマンド名の生成時にディレクトリを列挙しない様に修正した。 35435 source:command で引数を受け取る様にして、 35436 D が含まれている時にはディレクトリ名列挙を抑制する。 35437 35438 さて、補完はこれで余り気にしなくて良い気がする。 35439 問題の着色が為されていない問題について。何故着色が為されていないのだろうか。 35440 コマンドの抽出はちゃんとできているだろうか? 35441 →分かった。肝心の progcolor/word:default で CTX_ARGEI を見るのを忘れていた。修正した。 35442 35443 * OK: syntax: eval a=() echo helo=() の構文エラーを検出できていない [#D1253] 35444 →と思ったが、これは eval の時点で構文エラーになっているのではなくて、 35445 eval から呼び出されたコマンドの評価の場面で構文エラーになっているのではないか。 35446 実際に以下を試してみたら何もエラーは発生しなかった。 35447 $ bash -n -c 'eval a=() echo c=()' 35448 35449 * syntax: 何と coproc に対応していない [#D1252] 35450 35451 普通のコマンドと同様に処理しておけば取り敢えず問題ないと思っていたが、 35452 実際にやってみるとエラー着色になってしまっている。 35453 そもそも coproc のコマンド部分には特別なコマンドも指定できる。 35454 35455 | 然し、coproc はどうやって [COPROC] の部分を変数名かコマンド名か判断しているのだろうか。 35456 | 試しに coproc hello echo としたら、hello がコマンド名と認識された。 35457 | というか coproc COPROC echo -e hello としても COPROC がコマンド名として解釈された。 35458 | 35459 | coproc var ((...)) 35460 | coproc var { ... } 35461 | coproc var do 35462 | 35463 | どうも関数と同じ構文の様な気がする。つまり、後に複合コマンドを期待する。 35464 | もし複合コマンドが来なかったら通常のコマンドとして処理する。 35465 | 35466 | 1. coproc の後に普通のC単語以外の単語が来たらコマンドだと思う。後は通常処理。 35467 | C単語が来たら取り敢えず変数の可能性を考える。 35468 | 2. C単語の後に複合コマンド (キーワード) が来たら受け付ける。 35469 | (coproc var と複合コマンドの間には改行も入れられない様だ) 35470 | それ以外の場合にはC単語をコマンドという事にして、新しい単語は普通の引数という事にする。 35471 35472 [文法まとめ] 35473 35474 a coproc の次の単語がキーワードなら、複合コマンドとして取り扱われる。 35475 因みに then, coproc, fi, ! 等の複合コマンドの開始でないキーワードでも、 35476 取り敢えず複合コマンドとして解釈をしようとし、後の文法エラーになる。 35477 但し、time は例外である。ここではキーワードとして扱われない。 35478 キーワードとして扱われる物を列挙する。 35479 - ( (( 35480 - { } ! [[ 35481 - if then elif fi, while until do done, for select case esac 35482 - coproc, function 35483 b それ以外で、次の単語がC単語でない時は、通常のコマンドとして取り扱われる。 35484 c それ以外の時、次の単語はC単語である。更にその次の単語 word2 を調べる。 35485 c1 word2 がキーワードなら、word1 は変数名として取り扱い、 35486 word2 は複合コマンドとして取り扱われる。 35487 c2 それ以外の時は、word1 は通常コマンドとして取り扱われる。 35488 35489 | どの様に実装するのが良いだろうか。 35490 | 35491 | a coproc が来たら取り敢えず特別な文脈にする。 35492 | 最初の単語の読み終時に単純な単語かどうかの判定を行い、 35493 | もし単純な単語であるならば前方に先読みを実施する。 35494 | [[:space:]]*(複合コマンド) の形式をしていたら、 35495 | 最初の単語は変数名であったと見做して着色・単語設定する。 35496 | それ以外の場合にはコマンドとして着色・単語設定する。 35497 | 35498 | b 実は coproc を受け取った時点で先読みを実施してしまっても良いのでは? 35499 | 先読みを実施する時に何か問題が起こるだろうか。 35500 | 35501 | % o 寧ろ無闇に文脈値を増やすよりは良いのではないだろうか。 35502 | % と思ったが、文脈値は結局増やさなければならない気がする。 35503 | % "変数名の後に複合コマンドを期待する文脈" 35504 | % というのを新しく追加しなければならない。 35505 | 35506 | 文脈値をどうせ増やすのであれば、a の方針で良い気がする。 35507 | 35508 | →a の方針で実装する。 35509 35510 実装した。動いている。 35511 35512 x fixed: progcolor が中途半端にしか動いていない? 35513 coproc hello world から単語を削除して coproc hello に 35514 すると progcolor ではない単語着色になっている。 35515 (単語着色がされていないという訳ではない。) 35516 35517 どの様なコマンド抽出になっているのかを確認する必要がある。 35518 確認した所、以下の様になっていた。coproc が親コマンドになっている。 35519 うーん。自身が CTX_CMDI の時には親を抽出しない様にすれば良い? 35520 comp_cword='1' comp_line='coproc hello' comp_point='12' comp_words=('coproc' 'hello') 35521 35522 確認した。自身が CTX_CMDI であっても兄を探索する様になっていた。修正した。 35523 35524 2020-01-31 35525 35526 * 2020-01-23 Cygwin でテスト vi_test が失敗している [#D1251] 35527 35528 | 操作を実行した後のカーソルの位置が一文字ずれている様だ。 35529 | コマンドラインで実行すると特に変な振る舞いをする事はない様だ。 35530 | 35531 | ble-0.3.1 でもテストが失敗している。こちらは linux でも再現する。 35532 | テスト自身のバグである可能性が高い様な予感がしている。 35533 | 35534 | うーん。そもそも何故 linux と結果が異なるのか。 35535 | Cygwin 特有の処理に問題があるとすればもっと広範に渡って影響が出るのではないか。 35536 | bash の version の違いかとも思ったが version を合わせても再現する。 35537 | 35538 | 実際に再生されている内容を確認してみると変な事になっている。 35539 | 65 32 104 101 108 108 111 0 0 0 0 0 0 35540 | C-[ と入力した物が 0 0 0 0 0 0 に変換されている。どういう事か? 35541 | 記録されているレジスタの中身は "A helloM-xM-^DM-^@M-^@M-^AM-^[" である。 35542 | 35543 | どうもレジスタの値に変換する時点で変な事になっている様だ。 35544 | 記録されたキー列は 65 32 104 101 108 108 111 67108955 であるが、 35545 | それを文字列に変換した結果が $'A hello\370\204\200\200\201\233' になっている。 35546 | これは変だ。ble/decode/charlog#encode の実装を確認してみると 35547 | 唯単に文字コードから文字列に変換しているだけ。linux で動いているという事は、 35548 | キー列の時点で修飾が外れているのか、或いは文字にエンコードしても 35549 | 巨大なコードポイントを持つ UTF-8 文字として取り扱われているのか。 35550 | →linux で動いているのを確認してみた所、ちゃんと一つの文字として扱われている。 35551 | →更に文字列に変換した結果も同じになっている。 35552 | 35553 | →うーん。記録された register の値を出力する時に表示が異なる。 35554 | 本質的にはバイナリとしての中身は同じであるのにも拘らず (本当か?)。 35555 | OSについている UTF-8 復号器が真面目に不正な文字を除去するか、 35556 | 或いは素朴な UTF-8 復号をそのまま用いるかの違いという事だろうか。 35557 | ? UTF-8 6byte 表現の各バイトを更に UTF-8 符号化している可能性? 35558 | →バイト数を確認してみた所 13 であり、これは 'A hello' (7) + 6 に 35559 | なっているので 6 byte 表現は 6byte 表現のままである。 35560 | ? そもそもこの記録された文字列の文字数はどう数えられている? 35561 | →13になった。つまり、UTF-8 の不正な表現は1文字ではなくて、 35562 | 6文字と数えられているという事になる。うーん。 35563 | 35564 | つまり。。ここで考えなければならないのは、 35565 | charlog#encode, decode で巨大な数を保存・復元できる様にする事。 35566 | 特に復元の際に UTF-8 5,6バイト表現としての復元を試みる? 35567 | 35568 | (但し、bash 3.2 ではうまく変換できていない様にも見える) 35569 | 35570 | * そもそも何故 linux と cygwin で振る舞いが変わっているのか。 35571 | これは bash の実装の問題なのかもっと下の枠組みの問題なのか。 35572 | 35573 | * 巨大な文字コードを無理やり文字に変換することの是非 35574 | 現在は UTF-8 を仮定しているから動いているが、 35575 | 例えば LANG=C の場合にはそもそも 256 以上のコードを表現できない。 35576 | ESC seq に頼るしか無いのではないか。 35577 | 35578 | これを実装した時にはどの考えていたのだったか。 35579 | blame で確認する。commit は 06698a4f である。#D1026 に議論がある。 35580 | うーん。大して考えていない様な気がする。 35581 | 他の文字コードに対応する時には、その文字コードで割当てられていない 35582 | 文字を用いて特別に処理するしかない。 35583 35584 取り敢えず状況を整理する。 35585 * 修飾したキーを記録する為に巨大な数を UTF-8 encode している。 35586 結果として UTF-8 としては本来不正である様な表現に変換される。 35587 * Linux ではその文字の長さは 1 になるが Cygwin では 6 になる。 35588 * 復号する時に一文字ずつ復号するのでその時に 35589 Cygwin では元の文字が分解されてしまう。不正なバイトなので 0 になる。 35590 35591 | 確認する。 35592 | 35593 | linux$ ble/util/c2s 67108955; echo "${#ret}:$ret" | cat -A 35594 | 1:M-|M-^DM-^@M-^@M-^AM-^[$ 35595 | cygwin bash-4.4$ ble/util/c2s 67108955; echo "${#ret}:$ret" | cat -A 35596 | 6:M-xM-^DM-^@M-^@M-^AM-^[$ 35597 | cygwin bash-5.0$ ble/util/c2s 67108955; echo "${#ret}:$ret" | cat -A 35598 | 6:M-xM-^DM-^@M-^@M-^AM-^[$ 35599 | 35600 | と思って出力された内容を見ると何だか変だ。 35601 | 最初の文字が M-x になっている。Linux では M-l である。 35602 | 35603 | 調べてみると printf \Uxxxxxxxx が駄目の様だ。 35604 | 以下のコマンドが linux と cygwin で異なる結果になる。 35605 | cat が勝手に変換している可能性も考えたが od -tx1 で見るとやはり違う。 35606 | $ printf '\U0400005b\n' | cat -A 35607 | 35608 | つまり、これは復号の問題ではなくて key -> s 符号化の問題? 35609 | 何故 cygwin と linux で振る舞いが変わるのかというと実際に使っている実装が異なるから? 35610 | printf の実装を確認してみると u32cconv という関数を呼び出している。 35611 | 35612 | うーん。u32cconv の実装を見ると早速変な所がある。 35613 | 取り敢えず wchar_t が 4B の環境では wctomb を使っている。 35614 | 2B の環境では surrogate pair に変換してから wcstombs にしている。 35615 | もし wcstombs がちゃんと surrogate pair に対応しているのであれば問題は起こらない。 35616 | さて、今回の場合はそもそも値が Unicode の範囲外である為、 35617 | この wcstombs も呼び出される事はない (そもそも surrogate pair で表せない)。 35618 | 35619 | さて結局 u32toutf8 という関数の返す結果が壊れているという事が分かった。 35620 | うーん。この最後の if の 1B 目が間違っている気がする? f8 ではなくて fc では。 35621 | そしてこれは最近報告に上がっていた物である気がする。 35622 | これだ https://lists.gnu.org/archive/html/bug-bash/2019-11/msg00042.html 35623 | そして patch の中身を見ると自分が思ったのと完全に同じ修正だった…。 35624 | 35625 | * 影響を受ける bash のバージョンは? 35626 | さて、Bash のバグだと分かった所で。どうやって対処するべきか。 35627 | 因みにこのバグはいつからあるものだろうか。先ずそもそも printf が \U.... 35628 | に対応したのは bash 4.2 からで、最初から間違っていた様だ。 35629 | → Bash 4.2 -- 5.0 の全て。 35630 | 35631 | * 果たして復号の方は問題ないのか確認が必要である。 35632 | →駄目だった。 35633 | $ ret=$'\xfc\x84\x80\x80\x81\x9b'; echo "${#ret}:$ret" | cat -A 35634 | 1:... linux 35635 | 6:... cygwin 35636 | 35637 | $ ret=$'\xfc\x84\x80\x80\x81\x9b'; ble/util/s2c "$ret"; echo $ret 35638 | 67108955 linux 35639 | 0 cygwin 35640 | 35641 | linux で動いている物が cygwin では動かない。 35642 | 35643 | $ ret=$'\xfc\x84\x80\x80\x81\x9b'; printf %d "'$ret" 35644 | 67108955 linux 35645 | 0 cygwin 35646 | 35647 | 切り出しだけの問題かと思いきや、' を指定した場合でも駄目の様だ。 35648 | 35649 | この printf %d 'c の実装を確認する。整数引数を読み取る時に、 35650 | getintmax という関数を呼び出している。その中で ' を確認できたら、 35651 | asciicode() という関数の結果を返している。 35652 | というか ' の代わりに " でも良い様だ…。知らなかった。 35653 | 35654 | うーん。asciicode の中を確認すると mbtowc という関数を呼び出していて、 35655 | この関数が -1 を返している。つまり不正な UTF-8 である事を検出している。 35656 | これは bash の側に無理やり変更を押し込む訳にも行かない。 35657 | かと言って cygwin の mbtowc の実装事態に変更を押し込むのも変である。 35658 | (linux では mbtowc が恐らく変な UTF-8 でもそれなりに解釈するのだろう) 35659 35660 改めて整理する。 35661 * key値から文字列に変換する時、以下で報告されているバグによって誤った形式になる 35662 https://lists.gnu.org/archive/html/bug-bash/2019-11/msg00042.html 35663 * それとは別に Cygwin の mbtowc は範囲外 UTF-8 に対してエラーを検出する。 35664 恐らく Linux の mbtowc は範囲外 UTF-8 でも旧規格の通りに復号するのだろう。 35665 35666 | そもそも現在の実装は UTF-8 を前提としている。 35667 | UTF-8 に依存しない実装に変換するべきなのではないか。 35668 | 文字列として埋め込む事ができるのは "文字" と制御文字だけである。 35669 | 35670 | 以前の実装ではエスケープシーケンスを用いていたが問題として長くなり過ぎる。 35671 | →今あらためて確認した所カーソルキーはエスケープシーケンスに変換されている。 35672 | 他にも様々な入力を試してみたが何れもちゃんとエスケープシーケンスになっている。 35673 | C-[ だけがエスケープシーケンスになっていないのであった。調べる。 35674 | vi.sh の側で加工しているのだろうか、と思ったがそうではなかった。 35675 | decode を通過する文字をそのまま記録している様だ。 35676 | ble-decode-char の中を通過する文字をそのまま計測している様だ。 35677 | 35678 | つまり更に上の ble-decode-byte が C-[ を処理している。 35679 | ble-decode-byte は各符号化方式で実装していて特に ESC について意識している訳ではない。 35680 | とすれば最終的には init-bind に行き着く? うーん。然し中を確認すると U+07FF を送信している様に見える。 35681 | 35682 | 何処で C-[ になるのか分からない。と思ったら分かった…。 35683 | これはテストが悪いのだった。 35684 | 35685 | _ble_keymap_vi_test_ble_decode=ble-decode-char で評価関数を ble-decode-char にしながら 35686 | C-[ という修飾キーを指定したのが悪かった。 35687 | これにより本来文字として受信しない筈の文字を受信させてテストを実行していたのだった。 35688 35689 結論としては 35690 * vi_test が悪かった。テストのデコーダに ble-decode-char を指定しているのに 35691 テストの入力に key C-[ を指定していたのがいけなかった。 35692 * charlog#encode, decode は key の符号化・復号はそもそも想定していなかった。 35693 なので Unicode 範囲外の文字に対して対策はしなくて良い。 35694 35695 kspec に IsolatedESC を指定できる様にする。 35696 或いは U+07FF の様な形式で文字を指定できる様にする。 35697 →@ESC @NUL U+xxxx の形式に対応した。 35698 35699 x fixed: Linux 上でマクロが動かなくなった。と思ったら ble-decode-kbd の 35700 中のチェックで keyname は _alnum で構成されていなければならないというチェックが入っていた。 35701 _alnum に加えて @ も keyname を構成する文字として許す事にした。 35702 x fixed: U+07FF が動かない。と思ったら正規表現の誤りだった。修正した。 35703 35704 テストが全て通る様になった。OK 35705 35706 2020-01-30 35707 35708 * auto-complete: C-e でも補完確定にするべきなのでは? [#D1250] 35709 追加した。 35710 35711 * highlight: pathname に含まれるディレクトリのシンボリックリンク [#D1249] 35712 ディレクトリとしての着色になっているが、シンボリックリンクの時には 35713 そうなる様に着色した方が親切である。 35714 →実装を見て気づいたが実は普通のディレクトリ名の判定の時点で 35715 シンボリックリンクのディレクトリ名であっても末尾に / がついていると、 35716 通常のディレクトリであるかの様に着色されていた。 35717 末尾に / がついている場合には [[ -h dir ]] は失敗するのだ。 35718 35719 末尾に / がついていてもそれがシンボリックリンクかどうかを判定する様にした。 35720 実装した。確認した。 35721 35722 * 履歴の上下で menu-filter が保持されている。これは変だ [#D1248] 35723 動作上の問題はないが設計として何だか変である。 35724 35725 調べると menu-filter は menu がアクティブの時にしか有効にならない。 35726 更に、履歴を移動すると menu は消える筈だ。なので menu-filter は働かない筈。 35727 と思ったら、履歴を移動した時に menu が消えるのは menu-filter が消しているのだった。 35728 従って履歴を移動しても前の内容と一貫している場合には menu は消えない。 35729 履歴を移動した時に menu を消すようにして良い気がする。 35730 35731 history_onleave に登録すれば良い。登録した。動作確認した。OK 35732 35733 2020-01-26 35734 35735 * progcolor: / を含むコマンド着色が変だ [#D1247] 35736 パスを指定して呼び出すコマンドが全てディレクトリであるかの様に着色されている。 35737 / を含む関数名の場合には問題は起こっていない。 35738 最近の変更によって問題が起こる様になった→これは簡単だった。修正した。 35739 35740 * global: 一箇所でしか使われていない識別子 [#D1246] 35741 一箇所でしか使われていない識別子は怪しい。 35742 ./make_command.sh check-words でそういう物を検索できる様にした。 35743 怪しい物を幾つか直した。結構バグが沢山ある様だという事。 35744 他に ./make_command.sh check-varnames も作った。 35745 35746 * ret が leak している。alias 展開関連の様である。 35747 * 他に ch が漏れている。 35748 これの修正は簡単だった。すぐに見つかった。 35749 然し更に見ていると ble/builtin/bind/.parse-keyname で 35750 致命的に間違えている事を発見した。C-SPC や DEL や Rubout 35751 等が全く解釈できていなかった。修正した。 35752 * dist が漏れているがこれは mshex bashrc m/g だろう。 35753 →と思ったが dist という変数は使われていなかった。 35754 更に ble.sh の中も検索してみたが dist という変数は使われていない。 35755 問題のセッションで history | grep してみたがやはり見つからない。 35756 不思議な事だ。ble.sh のセッションでも確認するとやはり dist に値が入っている。 35757 →declare の出力を検索して分かった。mshex/cdhist/cd だった。 35758 直した。然し今まで気づいていなかった事が不思議である。 35759 35760 * progcolor: コマンド毎の着色の設定を可能にする [#D1245] 35761 35762 コマンド毎に引数の着色を実行するには。 35763 % * コマンド毎の着色を行う関数の名前について。 35764 % 現在 ble/cmdinfo/{help,complete}:command が使われている。 35765 % ble/cmdinfo/highlight:command を使う事にする。 35766 % * と思ったが標準入力だとかヒアドキュメントだとかについての設定は? 35767 % これは別の関数を用意するか或いは引数の振りをして渡すか。 35768 % 別の関数を用意するのが自然に思われる。 35769 →#D0581 の考察を確認した所 color, color-stdin が提案されている。 35770 #D0581 の名前を採用する事にする。 35771 35772 現在着色を計算しているのは 35773 ble/highlight/layer:syntax/word/.update-attributes という関数である。 35774 この関数は木構造を使って色を決定している。 35775 単語毎に着色を計算しているので現在の実装ではコマンドが分からない。 35776 各単語毎にコマンドを抽出するのは如何にも非効率である。 35777 それとは別にやはり一回の highlight:command の呼び出しで全て着色したい。 35778 35779 [仕様] 35780 35781 * done: ble/cmdinfo/color:command を用いる。 35782 * done: comp_line 等一連の変数を提供する 35783 * comp_dirty 的な配列に各単語の着色を更新する必要があるかどうかを格納する。 35784 着色を更新したら comp_dirty に更新した事を表す値を書き込む。 35785 →comp_flags 的な変数に "d" という文字を入れる事にする。 35786 →これは現状では wattr に - が設定されているかどうかで判定している。 35787 実際に今迄の実装でもその様にしていた気がする。 35788 もし上書きするのであれば敢えて set-wattr を呼び出せば良い。 35789 35790 [実装] 35791 35792 問題が複雑化してきたので複数に分けて実装する事にする。 35793 35794 * done: cmdinfo/color が存在している場合にはそれを呼び出す。 35795 cmdinfo/color の中で使いやすい様に関数名は変更する。 35796 また変数名も被らない様にする必要がある。 35797 うーん。特に i である。 35798 →これは取り敢えず TE_i TE_nofs という変数名を使う様に書き換えた。 35799 35800 * done: 先ずコマンド毎に着色する様に修正する #D1242 35801 35802 * done: コマンド名を使って着色設定を探索する。 35803 これは core-complete.sh の設定を参考にすれば良い。 35804 →着色設定を呼び出す所まで実装した。 35805 35806 x fixed: コマンド名だけの時にカスタム着色が動いていない気がする。 35807 これは extract-command-by-noderef 関数が 35808 CTX_CMDI に対して動作していなかったのが原因だった。修正した。 35809 x fixed: 引数を入力して行くと着色が消えてしまう。 35810 これは umin,umax の範囲内にある属性は全て消去されるのが原因。 35811 その後で _ble_syntax_word_{umin,umax} の範囲内の単語が再着色される 35812 予定になっている。つまり、この範囲の外の単語について着色をすると 35813 その着色は全て消去されてしまうという事になる。 35814 →_ble_syntax_word_{umin,umax} も更新する様に変更した。 35815 35816 35817 * progcolor: proghl の名前を考える → progcolor に変更 [#D1244] 35818 35819 proghl は余りにも分かりにくい。 35820 * proghilite, proghighlight 長い。 35821 * highlight (ble/syntax/highlight) 35822 単なる highlight は既に色々な所で使っている。 35823 * proglite, proglight, proglit 35824 何の事だか分からない。分かりにくい。 35825 * proghili もっと何が言いたいか分からない。 35826 * philite, philight: 変だ。 35827 何か既存の単語で良さそうな意味があって 35828 似た響きの物があれば使っても良いのかもしれない。 35829 * progcolor, progcol 35830 実の所、色だけではない。装飾も含まれる。 35831 然し、既存の枠組みで既に color という名前は使っている。 35832 35833 後、これらに共通するのは単語単位の着色であるという事が 35834 名前に現れていない。prog があれば補完と同様に単語単位に 35835 動くという事が連想されるかもしれないというぐらい。 35836 35837 * wordlite, wordcolor, wordgraphics, wordg 35838 * proggraph, progg, progface, wordface 35839 実際に設定するのは g 値であって実は face ではないのだ。 35840 35841 うーん。この中では progcolor, proglight, 35842 wordface だろうか。或いは proglite。 35843 →progcolor or proglite 35844 うーん。余り奇を衒わずに progcolor で行くのが良い気がする。 35845 35846 2020-01-25 35847 35848 * この肥大化した memo.txt は何とかした方が良い [#D1243] 35849 35850 [動機] 35851 35852 幾ら git が差分で管理してくれると言っても、 35853 例えば git pull の時にはダウンロードするファイルの集合について 35854 差分を計算して圧縮してくれても、手元にある分からの差分にはしてくれてない気がする。 35855 というのも ble-update の度に 1MB ぐらいのデータをダウンロードしている。 35856 多少のアップデートの癖に 1MB もダウンロードするのは避けたい。 35857 35858 それに巨大な memo.txt が見える所にあるのも見苦しい。 35859 memo subdir の中に過去のログについては移動するのが良い気がする。 35860 然し、追跡などを考えると、うーん。 35861 今の memo.txt という名前のファイルは一旦変更する? 35862 ファイル名を変更しないと移動を検出してくれないのだ。 35863 35864 [変更] 35865 35866 取り敢えず現在の memo.txt は memo/done.txt 辺りに移動する事にする。 35867 そして todo に関しては todo.txt に移動する。 35868 ChangeLog に関しては memo/ChangeLog.txt に移動する? 35869 今まで C-prior C-next で移動して記入していたが面倒である。 35870 その様に考えると分離した方が楽だ。 35871 というか見た目をチェックしたいので ChangeLog.md にしてしまうのが良い。 35872 35873 x うーん。然し、溜まってきたら一気に done.txt に移動する方式だと、 35874 無駄に編集行数が増えてしまう事になるのではないか。 35875 然し、毎回 done に追記する方式にすると結局同じ事になる。 35876 という事を考えると適当にファイルを分割して昔のファイルには触らない様にするのが正しい? 35877 git 的にはそういう事になるのだろう。然し、それはそれで不便である。 35878 という事になればやはり git の差分の行が増えるのは仕方がないという事にして 35879 時々一気に移動する事にする。 35880 35881 でももし上記の様に git の都合を無視するのだとすれば、 35882 実は今まで通りに一つのファイルで作業しても良いのではないかという気がする。 35883 うーん。しかし、それはそれで運用が面倒なのである。 35884 git が大規模なソースコードの移動を検出してくれれば問題はないし、 35885 或いは git が巨大なファイルの一部だけの変更を検出してくれれば問題ない。 35886 うーん。これは結局利便性がどうだとか git がどうだとかではなくて見た目の問題なのだろうか。 35887 後は git におけるダウンロードの問題。そういう実利的な事を考えれば。 35888 35889 今までの問題 35890 x git のダウンロードが遅くなる。 35891 x 巨大なファイルがトップレベルにあって見苦しい。 35892 x 他の人が見た時に何がどうなっているのか分かりにくい。 35893 35894 分割した時の問題 35895 x 検索が二つのファイルに跨っていて面倒。 35896 x 時々一気にログを移動する事にすると編集量が無駄に増える。 35897 また移動した時にはダウンロードが遅くなる。 35898 35899 他の代替案はあるだろうか。 35900 35901 a 実のところ本当に項目ごとにファイルを作るという手もある。 35902 しかしそうすると今度は検索がもっと面倒な事になってしまう。 35903 或いは、grep を使うべきなのだろうか。 35904 35905 b 或いは 100 項目ごとに done.txt を分けるという手もある。 35906 100 項目であればそんなに巨大にはならないし、毎回追加して良い。 35907 そして将来的にくっつける事は絶対にしないという規則にする。 35908 そうは言っても検索はますます面倒になる。 35909 35910 c 編集するのは一つの塊のファイルだけれども、 35911 git に保存する時には適当に分割して保存する様にする? 35912 35913 % 或いは自動的に make でくっつける様にする? 35914 % しかしそれはそれで編集が面倒だ。 35915 % 編集したら分割した内容を保存する仕組みなど作れるかもしれないが面倒である。 35916 % と思ったがこれはこれで一つの手なのかもしれない 35917 35918 これは技術的には可能だし色々の物事を解決する様な気もするが、 35919 たかがメモのためにこれをするのは大袈裟だしやらなくて良い。 35920 35921 * 2019-12-31 progcolor: 単語着色をコマンド単位で実行する様に変更 [#D1242] 35922 35923 * done: 中で extract-command を呼び出す? 35924 35925 と思ったが extract-command は単語の位置情報などは抽出しない。 35926 それっぽいコマンドを再構築してしまって、 35927 元の文字列の情報は失われてしまうのである。 35928 35929 a extract-command を拡張する? 35930 35931 b extract-command と同様の手法を新しく実装する? 35932 extract-command で使わない機能があればそれを整理できる。 35933 と思ったが comp_line 等の変数をそのまま提供する事にすると 35934 機能を減らす事はできない様な気がする。 35935 従って extract-command を拡張する方が自然である。 35936 35937 因みに node[ofs+4] をチェックしているので 35938 同じ単語を二度以上着色する事は既に防いでいるので余り気にしなくて良い? 35939 35940 ? 但し、子ノードに対する処理がどうなっているかについては確認が必要。 35941 | どうも子ノードの処理は "単語" の子としてではなくて、 35942 | "入れ子" の子として処理している様である。 35943 | なので単語の処理の時には気にしなくて良いという事だろうか? 35944 | と思ったがそうでもない? tree-enumerate-in-range は 35945 | 木構造とは全く関係なく列挙する機能だろうか。 35946 | →実際に読んでみるとその様に記述されている。なる程。 35947 | 特に末尾から順番に列挙されているのだとすれば、 35948 | 何も考えずに実装すれば良い気がする。 35949 結論: 単語着色の決定に用いている tree-enumerate-in-range 35950 は入れ子構造に関係なく末尾から列挙する関数なので気にしなくて良い。 35951 35952 うーん。i nofs 及び node という変数を参照できる。 35953 extract_command を拡張するとすれば i と nofs を記録すれば良い? 35954 取り敢えず i と nofs を tree_words という配列に書き出す事にした。 35955 35956 ちゃんと抽出できている様な気がする。 35957 また重複して着色が計算されるという事も起こっていない。 35958 35959 x と思ったら $() の入れ子が閉じていない時にちゃんと動いていない。 35960 nest の外側を抽出してしまっている? 35961 35962 | うーん。分かった extract-command は位置しか受け取っていないので、 35963 | 同じ位置で複数の単語が入れ子構造で閉じていると、 35964 | そのどれか一つだけしか着色しないという事になるのである。 35965 | 35966 | なので extract-command を実施する時には nofs も指定できる様にしなければならない。 35967 | 35968 | 現在の処理では以下の部分で単語を見つけて、 35969 | その後で .construct を呼び出している。 35970 | 実は見つける処理は不要なのではないかという事。 35971 | if [[ $wtype =~ ^[0-9]+$ && ! $EC_has_word ]]; then 35972 | EC_has_word=$wtype 35973 | return 35974 | fi 35975 | 35976 | 外部から指定したオプションでこの辺りを制御できる様にしたい。 35977 | 外部から i,nofs を指定したとしてどの様にすれば良いのか? 35978 | 35979 | a 外から指定した単語に対応する親を見つけるにはどうしたら良いのか? 35980 | 結局末尾から全て探索しなければならないのではないか。 35981 | 或いは親を見つけずにコマンドラインを構築する方法はあるだろうか。 35982 | つまり弟要素を親を見つけずに見つける方法。 35983 | 結局末部から探索しないとならないので親を見つけるのと大差ない。 35984 | 親は一回見つければ良いのに対して子は幾つもあるので、 35985 | 実際には親から見つけた方が効率が良い。 35986 | 35987 | b それならば最初から着色単語を見つける時に親情報を取れば良いのでは。 35988 | しかし現在は enumerate-in-range を使っている。親情報なしに 35989 | 指定した範囲の構造を取得する様にしている。 35990 | 35991 | それならば末尾から探索して行って親情報と一緒に 35992 | tree-enumerate した方が良いのではないか。 35993 | 然しこの方法だとコマンドラインが長くなった時に効率が悪くなる。 35994 | 然し、現在の方法が本当に効率が良いのかというのは微妙である。 35995 | と思ったが殆どの更新は文字単位であるのでやはりそういう微妙な 35996 | 更新に対して高速に動作して欲しい。 35997 | 35998 | 親情報をキャッシュしてもし変更があれば修正するという構造にできないか。 35999 | これは最初の実装の時に詳しく考察した筈である。 36000 | 然し、結局確定的な答えは得られていない。 36001 | 36002 | そもそもよく考えたら効率の良い単語着色の方法は 36003 | 未だに模索の途中だったのだ。従ってこれを機に考え直しても良い。 36004 | →2015-08-16 の議論が正にその議論である。 36005 | 丁度 tree-enumerate-in-range の改善についても考察している。 36006 | tree-enumerate-in-range の問題点についても述べられている。 36007 | その時の議論では補助的なデータ構造を構築する可能性や、 36008 | 解析時に構築する情報の拡張についても考えているが、 36009 | 取り敢えず高速化は置いておいて tree-enumerate 36010 | で末端から探索する形に変更するというので良い気がする。 36011 | 36012 | c reject: 逆方向から並行して解析しておく案? 36013 | 36014 | 現在の解析は先頭から順番に実行して、或る点での情報は 36015 | 後ろの情報に依存しない様になっている。これによって、 36016 | 途中からの解析に対応しているのである。従って、 36017 | 未来の情報である弟ノードの情報は本質的に取得できない。 36018 | 36019 | では逆に末端から解析する様にしたらどうなるだろうか。 36020 | その様にすれば弟ノードも列挙できるのではないか。 36021 | 36022 | x 然し、それだとコードを大幅に書き直す事になるし、 36023 | そもそもシェルの言語として末端からの解析ができる様に 36024 | なっているかというと怪しい。例えば $() や <() や 36025 | $(()) 等は何れも先頭から読むからできるのである。同様に 36026 | {} や ${} もそうである。 36027 | x そもそも書き途中で括弧が閉じていない 36028 | 場合には末端がどのような文脈か分からないので解析を始められない。 36029 | 或いは末端が普通の文脈であるという仮定で解析を無理やり 36030 | 実行できるかもしれないが、その結果として得られる文法エラーの結果は 36031 | ユーザの直感とは全くかけ離れた物になるだろうと思われる。 36032 | x そもそも先頭からの解析と末端からの解析が矛盾してしまう 36033 | ので両方の結果を用いて兄弟の単語を抽出するという事自体が 36034 | 一体どういう事なのかというのが分からなくなる。 36035 36036 現状をまとめると: 36037 36038 * 指定した単語 (i,nofs) についてコマンドを抽出したい。 36039 具体的には兄弟ノードを全て集めて単語を探索する。 36040 * 兄ノードに関しては辿る事ができるが、 36041 * 弟ノードに関しては親からでないと辿ることができない。 36042 * 然し、親を知るためには結局末尾から探索しなければならない。 36043 - 高速化の為に事前に木情報を構築する可能性もあるが、 36044 更新がある度に効率的にその木を更新するのは困難である。 36045 - 逆方向の解析案はそもそも文法的に定義が難しい 36046 36047 | d 前方に順番に探索していって最初に現れた一つ上のレベルの 36048 | ノードが親であるという様に判断すれば良いのではないか。 36049 | 36050 | この方法と末尾から辿る方法とどちらの方が効率的だろうか。 36051 | 末尾から辿る方法だと子ノードの細かい構造をスキップする事ができる。 36052 | 36053 | 前方に探索する場合だと弟ノードとその子孫の全てをチェックする事になる。 36054 | しかし末尾から辿る方法だと続くコマンドについても全て列挙する事になる。 36055 | どちらのケースの方が可能性として多いのかという事である。 36056 | 後者の方がケースとしては多いのだという気がする。 36057 | という事を考えると、実は前方に探索する方が良いのではないか。 36058 | 36059 | x ok: もう一つの問題は前方に探索する場合には一セルずつ処理しなければならない、 36060 | という事である。末尾から探索する場合には木情報を利用するので、 36061 | 配列に対する検査は単語の数だけに留まっている。 36062 | 或いは何らかの方法を用いて次の非空ノードまでの距離を検査できるだろうか。 36063 | →これは実装可能な気がする。non-empty-indices みたいな物を作れる。 36064 | 36065 | e 末尾から探索する時に適当な場所で当たりをつけて処理を 36066 | 省略することはできないか。 36067 | 36068 | つまり沢山のコマンドが後ろに並んでいる状態だと、 36069 | その全ての単語について検査を行わなければならない。 36070 | もしコマンドが何らかの入れ子の中にある場合には、 36071 | 大体の場合はコマンドはトップレベルにあるだろうから、 36072 | 適当な真ん中あたりの単語についてそれがトップレベルであれば、 36073 | 親はそれよりも後ろにあるという事を結論づける事ができる。 36074 | x 然し、適当な真ん中あたりの何処に単語があるのか探すのは 36075 | それはそれでもう一つの探索処理である (一応対処方法はある)。 36076 | x そもそも入れ子の中にある状況は限られている。 36077 | うーん。これは大した高速化にはならないだろう。 36078 | x 当たらなかった場合のコストが高い。 36079 | 最悪の場合は全体が一つの入れ子の中にある場合で、 36080 | その場合には二分法をしようにも末端まで繰り返し 36081 | テストを繰り返した挙げ句に結局末尾から探索しなければならない。 36082 | →まあ、一回テストに失敗したら諦めるという手法を用いれば良い。 36083 36084 取り敢えず前方に探索して親ノードもしくは次の弟コマンド 36085 が見つかったら其処から探索を開始するという方針を取る事にする。 36086 36087 前方に探索する場合には工夫して次の木情報がある単語まで 36088 スキップするか、或いは普通に一セルずつ確認するか。 36089 思うに工夫する為のコストも軽くはないし、 36090 唯実装が複雑になるだけなので今回は一セルずつ確認する。 36091 36092 [実装] 36093 36094 | 先ずデータ構造がどうなっているのか改めて確認する。 36095 | 1 nofs が有限であれば 36096 | その親が既に親になっているので其処から探索を始めれば良い。 36097 | 2 nofs==0ならば親になるノードを探索する。 36098 | 特に _ble_syntax_tree を前方に一セルずつ確認する。 36099 | 36100 | ここで疑問は単語の情報だけを見て親が存在するか 36101 | どうかを判定する事は可能だろうかという事。 36102 | nest との関係はどうなっていたのか。 36103 | - 現状の実装では nest も word も tree に格納されている。 36104 | 両者が混ざり合う事はなくて必ず親要素の中に収まる様になっている筈。 36105 | 従って word/nest を意識せずに単に親を調べれば良い。 36106 | 然し、ここでの問題はその単語に親が存在するかどうかの判定。 36107 | - 余り覚えていないが word の親は必ず nest である。 36108 | 単語の下に直接単語があるという状況は考えにくい。 36109 | うーん。不可能の気がする。今構造を確認したところによると、 36110 | _ble_syntax_tree には自分の深さに関連する情報や 36111 | 親に関する情報は全く記録されていない。 36112 | 構造を拡張するのはそれはそれで複雑である。 36113 | 36114 | 現状の情報を用いて実装するにはどうしたら良いか。 36115 | というかそもそも親ノードが存在するかどうかを知る必要はあるか? 36116 | 考えてみればない気がする。 36117 | 36118 | というか実装していても思ったがそもそも弟を辿るのであれば、 36119 | その時点で単語を回収すれば良いのでは。。。 36120 36121 取り敢えず実装した。tree#next-sibling, tree#previous-sibling という 36122 関数を新しく実装してそれを使って実装したら綺麗にできた。 36123 既存の extract-command もこれを使って実装したらもっと楽で 36124 見通しが良かったのではないかとも思う。 36125 36126 さてこれで再度テストを行う事にする。 36127 見た所動いている様な気がする。 36128 36129 x fixed: tree-enumerate の内部変数名の変更に伴う問題。 36130 書き換えてみたら echo $(echo hello) 等が正しく着色できなくなった。 36131 36132 そもそもなぜ変数名を書き換えようと思ったのだったか。 36133 36134 % うーん。tree-enumerate の中で動作する関数を作るとすると。 36135 % 勝手に tree-enumerate の情報が書き換わると動作しなくなる。 36136 % 然しだからと言って i nofs を local で被覆して使えなくすると、 36137 % 今度は内部でまた続きの tree-enumerate をしたい時にできなくなる。 36138 % 然し、それは具体的にどの様な状況だったか。 36139 36140 →取り敢えず二箇所変更漏れを修正したら動く様になった気がする。 36141 変数名を書き換える事が得策なのかは分からないが、 36142 取り敢えずこれをベースにして考える事にしたい。 36143 36144 更にこの修正によって前者の症状についても消えてしまった。 36145 然し前者の問題は独立に解決しなければならない問題である。 36146 36147 2020-01-24 36148 36149 * Bash 3.2 ^A, ^? を含む配列に対する対策 [#D1241] 36150 36151 更に履歴に格納されている値も変化している。 36152 history -s で登録されている値は合っている。 36153 何処でずれるのだろうか。。。 36154 36155 よく考えたらこれは可也広範に亘るのではないだろうか。 36156 そもそも配列の複製 arr2=("${arr1[@]}") を安全に実行できるのだろうか。 36157 これは別項目を立てて対策を考えるべきである。 36158 36159 どういう操作が安全でどういう操作が駄目なのか。 36160 対策する事は可能だろうか。 36161 36162 * arr2=("${arr1[@]}") これは安全の様だ 36163 * arr1=("$del" "$soh") これも安全の様だ 36164 36165 取り敢えず _ble_term_del 等に入れれば良い? 36166 これで declare-print-definitions に関しては大丈夫な気がする。 36167 36168 ble.sh の中で特に問題になりそうなのは何処か。 36169 36170 * history の読み取り。 36171 これはスクリプトを構築してそれを eval している。 36172 うーん。対策を入れてみたが効いていない気がする。 36173 これはまた別の所で問題になっているのだろうか。 36174 或いは置換が効いていない? 36175 →これは簡単なミスだった。修正したら動く様になった。 36176 36177 * binding のキャッシュ? 36178 →これは declare-print-definitions の方を対策した。 36179 恐らく大丈夫だろう。直接 declare -p を呼び出している箇所を全て塞げばOK 36180 36181 * vi のマクロの記録? 36182 これは eval の様な事はしていないので大丈夫の筈。 36183 36184 他に "eval -- ..." となっている箇所を探してみたが恐らく大丈夫。 36185 基本的に直接 ^A や ^? の文字が arr=(...) の形式の中に現れていなければ大丈夫なのだ。 36186 36187 * BASH_REMATCH は local と宣言してから使うべきなのではないか [#D1240] 36188 或いは、local と宣言する事ができない可能性はあるだろうか? 36189 これは試してみる価値はある。と思って試してみたら、 36190 local と宣言する事ができなかった。エラーが表示される。 36191 更に、無視して実行するとグローバルの BASH_REMATCH が書き換えられてしまう。 36192 従って、この方向性に基づく BASH_REMATCH 書き換え対策はできない。 36193 36194 * Bash 3.2 で存在する変数名を入力すると無限ループになる [#D1239] 36195 ble-0.3 では発生していない。 36196 36197 これは予想通り 93dab7b が原因の様である。 36198 然し不思議なのは無限ループが発生する要素が何処かにあるのか? という事。 36199 36200 どうも既に出ていた bash-3.2: _ble_syntax_attr[i-1]: bad array subscript 36201 というエラーは実はこれに関連している様である。これが意味する所は。。 36202 i=0 になってしまっている? 36203 36204 一箇所修正した。これで無限ループは直った。 36205 然し bad array subscript は依然として出ている。 36206 改めて bad array subscript がいつから出る様になったのか確認する。 36207 やはり 93dab7b が原因の様である。 36208 36209 改めて探してみると未だ BASH_REMATCH の書き換えの影響が出そうな部分があった。修正した。 36210 36211 * stty: Bash 3.2 で変なエラーメッセージが出ている [#D1238] 36212 /usr/bin/stty: invalid integer argument: `\001\177' 36213 /usr/bin/stty: invalid integer argument: `\001\177' 36214 36215 調べると ^? $'\x7F' を arr=() の形式で配列に代入すると勝手に ^A^? になる様だ。 36216 更に調べると declare -p は ^? を勝手に ^A^? に変換するらしい。面倒だ。 36217 というか配列の要素の中に ^? が含まれている場合、 36218 これを正しく補正して arr=() の形式にする事ができない。うーん。 36219 取り敢えず別項目を立てて処理する事にする #D1241 36220 36221 * ble/syntax/parse の遅延が動いていない [#D1237] 36222 update-syntax で is-function でチェックしているが、 36223 これだと autoload で定義している物に当たってロードされてしまう。 36224 36225 これは遅延させると何か問題でも発生したのだったか? 36226 以前も同じ事を確認した様な気がしないでもない。 36227 それに今でもちゃんと遅延されている様な気もする。 36228 36229 * ble-update: 実は |& は Bash 4.0 の機能だった [#D1236] 36230 使わない様に修正した。 36231 36232 序でなので文法の方も bash version をチェックして処理を切り替える様にした。 36233 36234 * decode (ble/builtin/bind): keyseq を読む時に標準入力を見ているがこれは変 [#D1235] 36235 #D1233 の問題を再現する過程で bind '"...": ...' を呼び出す事によって、 36236 後々の Bash の終了に寄与することが分かった。理由は "..." を解析する為に 36237 ble-decode-char を使っていて、その中でユーザの入力がないか確認しているからだった。 36238 然し、"..." を解析する時にはユーザの入力を確認する必要はないし、 36239 もし仮にユーザの入力があったとしても其処で処理は変わらない筈である。 36240 36241 と思って確認したら確かにちゃんとユーザの入力の有無に寄らない振る舞いになっていたが、 36242 チェックの順序が反転していた (元々は生起確率の低い判定を後に回そうとしていたが、 36243 ユーザの入力の有無の確認はコストの高い判定なので先に判定しても変ではない。 36244 何より論理的には先に判定するのが自然である。) 修正した。 36245 36246 * decode: bleopt_default_keymap=safe で inputrc がエラーになっている [#D1234] 36247 これは ble/builtin/bind/rlfunc2widget でちゃんと処理されていないのが原因 36248 36249 2020-01-23 36250 36251 * 2020-01-17 ble.sh: cygwin コンソールで実行するとすぐに閉じてしまう [#D1233] 36252 →これは結局 cygwin のバグだった。bug-report の方で取り扱う。 36253 36254 * vi_test: stackdump [#D1232] 36255 36256 また別の stackdump。Cygwin で C-\ C-\ を実行するとテストに失敗する。 36257 続いて失敗したテストを手で再現しようと思って "qaA hello" まで入力したところで stackdump が出た。 36258 再現してくれない→再現した。 36259 36260 何か編集文字列がある時にテストを実行してその後に発生する。 36261 Cygwin 以外でも再現した。つまり、これは Cygwin でテストに失敗するのとは別の理由。 36262 36263 現在の再現手順は "w C-\ C-\ i SP" である。 36264 まず初めにこれが最近の変更と関係していないか確認する。 36265 ble-0.4.0 で再現する。ble-0.3.1 はまた別のバグが出ている。 36266 これはまたテスト自身のバグだろうという気がする。 36267 遡ってみたがだいぶ昔から問題があった様だ。 36268 途中でテスト自体の不良などによって追うのが面倒になったので何処で始まったかは気にしない事にする。 36269 36270 取り敢えずテストのコードを弄って最小化する。 36271 と思ったらテストコードで最初の状態を復元している所でミスを見つけた。 36272 復元しているのに復元されていなかったので変だったのだ。 36273 36274 2020-01-22 36275 36276 * benchmark: ble-measure の較正 [#D1231] 36277 現在の自動較正だと a=1 が負になるなど問題が起こっているので、 36278 もっとちゃんと計測する様にする。特に a=1 の評価にかかる時間も考慮する。 36279 と思ったのだがどうも計測環境で速度が変化する? 36280 よく考えたら a=1 でちゃんと評価できているのであれば 36281 a=1 に対してはほぼ 0 になって欲しい。しかし有意に負になっている。 36282 36283 もしかすると関数内で評価すると時間が違うという事なのだろうか? 36284 →なるほど。確かに 100ns ぐらい差がある様に見える。 36285 計測が行われている環境を調べると 36286 36287 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:7 (ble-stackdump) 36288 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:4 (ble-measure) 36289 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:2 (ble/util/msleep/.calibrate-loop) 36290 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (ble/util/msleep/calibrate) 36291 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:35 (ble/util/idle.do/.call-task) 36292 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:4 (ble/util/idle.do) 36293 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:16 (ble-edit/bind/.tail) 36294 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:50 (ble-decode/EPILOGUE) 36295 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (ble-decode/.hook) 36296 36297 という事になっているので、9 段階ぐらい入れ子になっている。 36298 この入れ子に対する評価もした方が良いのだろうか? 36299 取り敢えず試しに計測してみる事にする。 36300 36301 真面目に較正する関数を ble-measure/calibrate とした。 36302 然しこれには時間がかかる。従って、普通にロードした時は a=1 36303 の計測結果を元に最終的な結果を比例で予測する事にした。 36304 36305 実際には測定のループ回数等色々な要素に影響される気がする。 36306 これ以上は追求しない事にする。 36307 36308 * refactor: merge subdir "test" into "memo" [#D1230] 36309 test というディレクトリになっているが実際テストでない。 36310 これは実装上の実験に使っている。寧ろ memo の下に移動するべきである。 36311 36312 * test/bash_history.erasedup.sh 36313 36314 このファイルは実装に関係している筈で、 36315 ここよりは memo/ の中にあるべきファイルの気がする。 36316 然し、どの項目に対応するファイルだろうか。 36317 ファイル名を memo.txt の中で検索してみても見つからない。 36318 blame してみて分かったのは、実はこのファイルは一番最初の commit から存在している。 36319 つまり本当に最初の最初に追加された物である。 36320 36321 memo.txt を辿ると本当の最初の commit は 36322 恐らく 2013-06-13 の状態から殆ど変えていない。 36323 従って 2013-06-13 以前の項目のどれかに対応している。 36324 特に議論もないので最初に対応した時に既に試したという事の気がする。 36325 #D0016 が恐らく最初に対応した時のメモである。 36326 36327 * ファイル test-source.sh は何だろう。 36328 確認してみるとこれも最初から存在したファイルの様だ。 36329 中を覗くとこれは恐らく ble.sh のファイルの位置を特定する方法を模索した時の物。 36330 うーん。何処で最初にこの機能を実装したのか。他のファイルを読み取るのに必要。 36331 例えば初期のファイルで言えば cmap 等が他のファイルとして用意した物。 36332 #D0028 に _ble_term_sc の言及が在るので恐らくこれ以前に既に test-source.sh はあった。 36333 然し、直接に対応する項目は記録されていない様に見える。 36334 36335 結論から言えばこれらのファイルはごくごく 36336 最初期のファイルなので対応する項目はないと考えて良い。 36337 この時にどの様にファイルに名前をつけるか。 36338 36339 今後、対応する項目を一切作らずにテストファイルだけ追加するという事はあるだろうか。 36340 もしないのであれば、対応する項目のないテストファイルは 36341 D0000 にしてしまっても良いかもしれない。 36342 36343 * history: fix a bug that history append does not work with "set -C" (reported by cmplstofB) [#D1229] 36344 https://github.com/akinomyoga/ble.sh/issues/37 36345 "bash: /run/user/1000/blesh/NNNN.history.app" というエラーメッセージが出るとの事。 36346 36347 これは見落とし。他にも類似の物がないか探したが他は古いテスト用のコードしかなかった。 36348 またチェックするのも面倒なのでテスト用のコードも全部修正する。 36349 36350 2020-01-21 36351 36352 * util: 16進数リテラルの着色に失敗している (reported by cmplstofB) [#D1228] 36353 https://github.com/akinomyoga/ble.sh/issues/36#issuecomment-576625143 36354 36355 何か正規表現を間違えている? と思って確認したらそもそも対応を忘れていた。 36356 36357 * util: ble/util/{save,restore}-vars に失敗している (reported by cmplstofB) [#D1227] 36358 https://github.com/akinomyoga/ble.sh/issues/36 36359 36360 * 変数名の抜けはないか? →無いような気がする。 36361 未初期化の変数が配列ではなくて変数として記録されている可能性? 36362 (然し、一旦配列になったのであればそれ以降は配列のままでいて欲しい) 36363 36364 * 或いは未だ restore-vars に問題が残っているか。 36365 →全て配列として復元すれば元に戻る筈と思って試したら直らない。 36366 つまり変数名の列挙に失敗しているという事になる。 36367 36368 と思ったが間違う要素がない。。何がいけないのだろう。 36369 そもそも座標計算がおかしいという事は、 36370 スカラーの復元に失敗しているという事である。 36371 36372 うーん。かなり謎。何で? 少し色々実験してみる必要がある。 36373 先ず、vars を配列として保存・復元する様に書き換えてみる。 36374 →違いは見られない。 36375 36376 一つずつ書き換えて確かめてみる事にした。 36377 と思って書き換えている内に分かった。 36378 多分この部分を書き直すのを忘れている、と思ったらそうだった。 36379 修正した。 36380 36381 2020-01-18 36382 36383 * cygwin: cygwin console で USER が空になっている [#D1226] 36384 取り敢えずユーザー名はもし設定されていなければ設定する。 36385 id -un でユーザー名は取得できる筈である。 36386 36387 これも #D1225 と一緒に対応した。 36388 36389 * cygwin: cygwin console で "-u指定されたファイルが見つかりません" エラー [#D1225] 36390 36391 これは 3.0.7 でも発生している。恐らく補完だろう。 36392 "-u指定されたファイルが見つかりません" というメッセージが表示される。 36393 64bit でも 32bit でも同様に出る。中で更に起動した Bash では再現しない。 36394 36395 この行が駄目だった。 36396 ble/util/assign-array arr 'ble/bin/sort -u <<< "$compgen"' # 1 fork/exec 36397 36398 そして ble/bin/sort を見てみると 36399 ble/bin/sort() { '/cygdrive/c/WINDOWS/system32/sort' "$@"; } 36400 等という事になっていた。道理で駄目な訳だ。 36401 他にも Windows に同盟のコマンドがあるという事がありそう。 36402 うーん。面倒なのでもう先頭に追加してしまう事にする。。 36403 36404 * main: .blerc がない時は ~/.config/blesh/... から読み取っても良いのでは [#D1224] 36405 然しどういう名前が良いだろうか。 36406 ~/.config/blesh/blerc なのか、 36407 ~/.config/blesh/blerc.sh なのか、 36408 ~/.config/blesh/init.sh なのか、 36409 或いはもっと別の名前が良いか。 36410 取り敢えず init.sh にする事にした。 36411 36412 * ble-reload の後に固まる (reported by dylankb) [#D1223] 36413 https://github.com/akinomyoga/ble.sh/issues/35 36414 36415 [再現] 36416 36417 | 再現できない。色々の OS で試してみたが再現しない。 36418 | 36419 | うーん。或いは Bash 5.0.11 の問題である可能性はあるか? 36420 | →確認してみたが Fedora で 5.0.11 でも再現しないし、 36421 | また FreeBSD も確認してみた所元から 5.0.11 だった。 36422 | 36423 | 再現しないと思ったがもしかして。。。--noattach が駄目? 36424 | あー。そうだった。うーん。#D1199 で直した筈なのだが。 36425 | 確認してみると D1199 で直したのは単純に source ble.sh --noattach 36426 | した時の話であって、source ble.sh --noattach && ble-attach 36427 | したら固まった。全然直っていなかった。 36428 36429 $ source ble.sh --noattach && ble-attach で再現する 36430 36431 [状況] 36432 36433 | これを直す為にはどうしたら良いのか。 36434 | #D1199 でどの様に直したのか確認する必要がある。 36435 | 調べると #D1199 の commit がないと思ったら ble-0.3 の問題として 36436 | ble-0.3 に修正が入っていた。と言っても対症療法的な物で、 36437 | ble-reload に対してしか修正が入っていなかったのだった。 36438 | 5bcea69 がその修正である。参考にならない。 36439 | 36440 | 参考にするべきはこれである #D1130 d35682a caa46c2 36441 | 36442 | うーん。分かった。 36443 | _ble_edit_detach_flag に値が設定されている時、 36444 | ble-attach は ble-detach (遅延) をキャンセルする事になるので、 36445 | 何もせずに抜けてしまう。これによって attach しているのにしていない、 36446 | という様な中途半端な状態になってしまっているのである。 36447 | 然し、そもそも _ble_attached になっているのが行けないのでは? 36448 | _ble_attached の設計を考え直すべきなのではないかという気がする。 36449 | 36450 | 今一度 _ble_edit_detach_flag と _ble_attached の意味について考える。 36451 | _ble_attached は実際に attach されているかどうかにするべきである。 36452 | そして、_ble_edit_detach_flag は複数の値を取りうる。 36453 | それぞれの意味について確認する。 36454 | 36455 | _ble_edit_detach_flag=detach 36456 | これは ble-detach を呼び出した時に設定される。 36457 | もし epilogue でこれが設定されていればその時に detach を実行する。 36458 | 或いは ble-attach でキャンセルする事も可能である。 36459 | 36460 | _ble_edit_detach_flag=reload これは reload 検知時に設定される。 36461 | 特に reload 検知前に attach していた時にこれが発生する。 36462 | その場で完全に detach してしまいその後で reload を設定するのである。 36463 | % 後の振る舞いとしては自動的に再 attach する事を示唆する。 36464 | % と思ったが本当だろうか。違う気がする。 36465 | % source した時に --noattach 等を指定していた場合には、 36466 | % やはり勝手に attach しないという事になるのであろう。 36467 | 後の振る舞いとしては。現在の bind -x が終了する時に 36468 | detach 状態であるのであればメッセージを表示する、という所だろうか。 36469 | 36470 | さて、この時に ble-detach が呼び出された場合にはどうなるのか? 36471 | うーん。_ble_attach が設定されていれば ble-detach を実行する。 36472 | もし _ble_attach が設定されていれば実行の必要はない。 36473 | 36474 | うーん。実はこれは detach と等価なのでは? 36475 | と思ったが .prologue を呼び出しているという所が異なる。 36476 | うーん。何だか分からないが色々複雑な状態を復元しなければならないので 36477 | 呼び出す必要があるという事だろうか。 36478 | 36479 | 然し、source ble.sh を実行した時点で色々と状態を調整している。 36480 | そして抜ける瞬間にそれを復元している。しかしながらその状態は 36481 | 更にその外側で復元される?? 何だかよく分からない。 36482 | 36483 | 先ず記録されているのは実行環境であって、 36484 | ble.sh環境は一意であると考えている。 36485 | 36486 | attach が発生する場合は以下の様になる。 36487 | 36488 | コマンド実行 source ble.sh attach epilogue 36489 | [ble.sh] →[実行環境A]→[ble.sh] → [実行環境B] → [ble.sh] → [ble.sh?] 36490 | 36491 | attach が発生しない場合は以下の様になる。 36492 | epilogue prologue 36493 | [ble.sh] →[実行環境A]→[ble.sh] → [実行環境B] → [ble.sh] → [実行環境] 36494 | 36495 | もしここで prologue を呼び出していないとするとどうなるのだろうか? 36496 | つまり代わりに detach と同じ処理をするとどうなるのかという事。 36497 | うーん。PS1 等が消滅するという事は考えにくいし、何も問題がない気がする。 36498 | そもそも PS1 が消滅していたのは何故だったか。 36499 | 恐らく epilogue を重複して呼び出してしまったから? 36500 | epilogue が重複すると ble.sh 環境を実行環境として記録する事になってしまう。 36501 | 色々考えるとやはり prologue は必要がない気がする。 36502 | 36503 | やっぱり何か不思議だ。detach の時にはほんの少ししか復元をしていない。 36504 | 何故問題が起こらないのだろうか? と思ったが分かった気がする。 36505 | どのタイミングで detach を実行したかの違いなんだ。 36506 | reload の時には先に detach してしまうので epilogue で状態が壊される。 36507 | なので再び prologue を呼び出す必要がある。 36508 | detach の時には epilogue の後に detach しているので、 36509 | その時点でちゃんと状態が作られている。なので、簡単で良い。 36510 | 36511 | という事は .check-detach に入った時の _ble_attached の状態で場合分けすれば良い。 36512 36513 _ble_attached の意味を変更して実際に attach/detach しているかの状態を保持する事にした。 36514 _ble_edit_detach_flag に関しては reload と detach を区別しない処理に変更した。 36515 代わりに、_ble_edit_detach_flag が立っているのに既に detach されている状態と、 36516 まだ detach していない状態で場合分けする本来の目的に適う実装方法である。 36517 36518 [確認] 36519 36520 取り敢えず修正して動かして振る舞いを確認する。チェックするのは、 36521 36522 ble-reload 36523 ble-detach; ble-attach 36524 source "$_ble_base/ble.sh" --noattach 36525 source "$_ble_base/ble.sh" --prompt 36526 source "$_ble_base/ble.sh" --noattach && ble-attach 36527 36528 一応問題なく動いている気がする。 36529 36530 x source "$_ble_base"/ble.sh --noattach してから ble-attach すると変だ。 36531 36532 普通に ble-detach してから ble-attach する時との違いは何だろうか。 36533 やはり状態として変な状態になっている? ちゃんと復元しきれていない? 36534 然し attach 直前は別に変な振る舞いは見せていなかった筈。 36535 36536 ble-attach する時に PS1 の restore に失敗している可能性? 36537 うーん。何がおかしいのだろうか。 36538 36539 というか状態がおかしいというよりは [EOF] のマークが表示されているのが問題。 36540 ble-attach した時にプロンプトをその場で描画してしまうかそうでないかの違いは何? 36541 36542 うーん。やっぱり attach 時に [EOF] が表示されるのは変である。 36543 .prologue で何か変な物がしかけられたのが原因だろう。 36544 36545 分かった。ble-decode/PROLOGUE で 36546 ble-edit/exec:gexec/restore-state を呼び出して、 36547 ble-edit/exec:gexec/.epilogue が呼び出されている。 36548 その時に EOL 補正が入ってしまっているのである。 36549 対症療法的ではあるが _ble_edit_exec_inside_prologue= を設定する。 36550 36551 ? よく考えるとこれだと prompt に失敗した時にやはり変な状態になるのでは。 36552 →実際に確かめてみたところ駄目になった。追加で修正する必要がある。 36553 修正した。 36554 36555 * 2019-02-09 manual: 英語版 [#D1222] 36556 取り敢えず完成した。 36557 36558 2020-01-17 36559 36560 * Error `ble/builtin/trap: invalid signal specification "-".` (reported by dylankb) [#D1221] 36561 https://github.com/akinomyoga/ble.sh/issues/33#issuecomment-575476866 36562 36563 | うーん。何故だろう。調べるとこのエラーメッセージを出力するのは、 36564 | trap -p で sigspecs に - が含まれていた場合、もしくは、 36565 | trap で sigspecs に - が含まれていた場合。 36566 | うーん。何れにしても sigspecs に - が混入するのが怪しい。 36567 | sigspecs に - が混入する状況で怪しい箇所がある。 36568 | この箇所に入る条件は何か hlpE の何れも指定されていなくて、 36569 | 更に sigspecs が何も登録されていない場合に、 36570 | command を上書きしてそれから…あ、分かった。 36571 | 36572 | trap INT とすると INT のハンドラが削除されるのだ。 36573 | それを実現する為に ble/builtin/trap では、 36574 | 1. trap INT を引数として順番に処理すると最初は INT が command として解釈される。 36575 | 2. 引数解析の終端で引数がもう終わっているという事が分かったら、 36576 | trap INT を trap - INT であったかの様に書き換える。 36577 36578 本来の trap は trap INT で INT のハンドラが削除される。 36579 ble/builtin/trap でそれに対する対応が壊れていた。修正した。 36580 36581 2020-01-15 36582 36583 * codespell [#D1220] 36584 36585 gawk のメーリングリストに fossil というサイトの人が投稿している。 36586 36587 | codespell という機能を使って spell ミスを発見しているのだという。 36588 | その spell ミスの発見はローカルで動かせないのだろうか、と探してみる。 36589 | GitHub で探してみたら以下のプロジェクトが在る。 36590 | 36591 | https://github.com/codespell-project/codespell 36592 | 36593 | この codespell の頁に heads-up (注意喚起) がある。 36594 | fossies.org の頁に codespell を使っているのだと書かれている様だ。 36595 | https://github.com/codespell-project/codespell/issues/1315 36596 | https://fossies.org/features.html#codespell 36597 | 36598 | 其処にコメントしている jschleus というのが Jens つまり fossies の宣伝をしている人。 36599 | https://github.com/jschleus 36600 | https://github.com/letsencrypt/boulder/issues/4633 36601 | 36602 | 検索すると他にも様々なプロジェクトに対して去年の10月ぐらいから投稿している様だ。 36603 | https://github.com/search?q=codespell+fossies&type=Commits 36604 | 36605 | この人は他の人の作った物を自分の物であるかの様に人に貢献している。 36606 36607 36608 取り敢えず codespell にかけて見た。 36609 36610 * brance expansion in memo.txt 36611 * print filename and lines for -i 2 36612 * 他の候補を入力できる様にする。 36613 * 短い単語や大文字の短い単語 (略語) は無視するオプション 36614 * -i2 と -i1 の書き換える時の操作が違うので間違える。 36615 -i1 でそのまま C-m すると書き換えられる。 36616 -i2 でそのまま C-m すると書き換えが起こらない。 36617 何も入力せずに C-m した時には書き換えは起こらない様にするべきなのではないか。 36618 * -i2 で行が長い時にどの単語か分からない。 36619 * 辞書に登録されている "変換" だけにしか対応していない。 36620 文字の交換だとかについても全部手で一つ一つ登録されている。 36621 自動的に一致度を計算してどうとかそういう仕組ではない様だ。 36622 不毛である。 36623 36624 2020-01-13 36625 36626 * util: 自動補完の区切り文字を設定できる様にする (suggestion by dylankb) [#D1219] 36627 https://github.com/akinomyoga/ble.sh/issues/33#issuecomment-573528032 36628 36629 / で区切る様にしたいとの事だ。 36630 試してみると確かに fish では / も区切りになっている。 36631 新しい機能なので ble-0.4 に入れる事にする。 36632 と思ったけれどどうしようか。取り敢えず ble-0.4 に実装する事にした。 36633 36634 2020-01-12 36635 36636 * util: 構文着色を単体で呼び出せる様にする [#D1218] 36637 history の一覧を表示して着色したり、 36638 或いは単語内の着色で別の言語を着色する時に必要である。 36639 36640 * done: 各 layer の initialize-vars を実装する。 36641 * change: update-syntax は呼び出し側で管理する事にした。 36642 * done: ble/highlight/layer/update の interface を変更する。 36643 BLELINE_RANGE_UPDATE は廃止する。というか誰も使っていない。 36644 →一箇所使っている箇所があったがそもそも本当に正しかったのかも謎。 36645 →と思って適当に umin に書き換えたら動かなくなった。 36646 DMIN 変数に内容を保存してそれを使う事にした。 36647 36648 単体で構文着色を実行する関数を作成する。作成した。 36649 36650 然しよく考えたら別に現在の複雑な仕組みを使わなければならない言われはない。 36651 他の拡張や普通の構文着色の仕組みと同じように正規表現で一括で一致させてしまえば 36652 良いのではないだろうか。現在の枠組みを使う事の利点は部分更新に対応できるという事である。 36653 36654 という事を考えるとやはり部分更新に対応するのが良い気がするのである。 36655 だとするとキャッシュを指定できるようにしなければならない。 36656 36657 * util: {save,restore}-arrs は {save,restore}-vars に統合する [#D1217] 36658 36659 実の所、全て配列であるかの様に取り扱っても問題ないし、 36660 また ble/is-array の判定は最新の bash では ${parameter@a} を使っているので 36661 そんなに重くない。毎回 arrs と vars の両方を呼び出すのは不毛なので、 36662 全て {save,restore}-vars で処理する様にして問題ない。 36663 36664 * done: save-arrs, restore-arrs を削除する。 36665 * done: ARRNAMES を VARNAMES に統合する。 36666 36667 * 2020-01-05 Homebrew でインストールしたら動かないという報告 [#D1216] 36668 https://github.com/akinomyoga/ble.sh/issues/33 36669 36670 これは結局手元では再現できなかったし、 36671 何だか良く分からない内に向こうでも直ってしまった様だ。 36672 相手の報告を見ると相手の勘違いという事はなくて 36673 * 確かに変な状態が発生していたのは確かである。 36674 keymap をキャッシュから読み取った時に配列ではなくて普通の変数になっていた。 36675 * それも相手の環境では再現性があった 36676 (新しく ble.tar.xz をダウンロードして最初の1回は動くがそれ以降は動かない 36677 という事を書いていたので何度か試してその振る舞いが判明したという事である)。 36678 36679 | [原因解明] 36680 | 36681 | 変だ。Homebrew には登録していない。 36682 | 取り敢えず返信でどうやって formula を使ったのかという事を質問した。 36683 | 然し、後で調べてみるとどうも GitHub から自動生成する事ができる様だ。 36684 | 何だかよく分からない。 36685 | →結局 Homebrew で ble.sh を入れたというのは勘違いだった。 36686 | 36687 | 更に keymap/emacs.sh がなかったとしても別のエラーになる。 36688 | また cache の keymap.emacs の中身を空にした場合でも 36689 | もっと前のチェックで引っかかるので別のエラーメッセージになる筈だ。 36690 | - まるで DEFAULT_KEYMAP の上書きに失敗しているかの様だ。 36691 | 取り敢えず DEFAULT_KEYMAP を上書きしなかった場合に同じエラーメッセージになる事を確かめた。 36692 | 36693 | 然し他に手がかりがない。。 36694 | 36695 | うーん。DEFAULT_KEYMAP を readonly にした場合でも同じ問題が生じる様だ。 36696 | また上書きエラーのメッセージは表示されない様だ。 36697 | 然し探しても関数を常に readonly にする機能がある訳でもない気がする。 36698 | 本当にこれが勝手に readonly になってしまう事があるだろうか。 36699 | 取り敢えず readonly かどうかは以下のコマンドで確認できる。 36700 | declare -f +r ble-decode/DEFAULT_KEYMAP 36701 | 36702 | その他の可能性として何があるだろうか。 36703 | 例えば _ble_decode_emacs_kmap_ が local になっている可能性? 36704 | 関数内部から source をするのは既に試したが問題は起こっていない。 36705 | 36706 | それよりも後で source して実行すると動くというのも不思議である。 36707 | bashrc 中で実行すると起こる何らかの不具合だろうか??? 36708 | 36709 | というか彼は何故 bash_profile に設定を書いているのだろうか。 36710 | それがそもそもの間違いである可能性は? 36711 | 試してみたが bash_profile に書いたとしても 36712 | 全く呼び出されないか或いはちゃんと動くかのどちらかである。 36713 | 36714 | 分からないので取り敢えず返事待ちである。 36715 | 36716 | ? ok: cache が cache.d になっているのは何故なのだろうか。 36717 | XDG の判定に失敗しているという事だろうか。 36718 | →あー。分かった。これは ~/.cache というディレクトリが存在していないという事。 36719 | なのでこれは飽くまで意図した動作の範囲内である。 36720 | 36721 | 追加の返信が来た。 36722 | 36723 | * 色々の問題が複雑に絡み合っている気がする。 36724 | - ble-edit/detach を実行すると ble-decode/... is not found になったそうだ。 36725 | 何でだろう。余り考えにくい事である。 ble-decode なので ble-edit/detach を 36726 | うち間違えた訳ではない。 36727 | - 更にもう一度入力したら今度は shell が終了してしまったそうだ。 36728 | 実際に試してみたがエラーは起こらないし、もう一度入力しても何も起こらない。 36729 | 但し、stty の状態は復元しない様子である。 36730 | - 更にまた別のセッションで実行すると syntax error になったそうで。 36731 | 何が起こっているのか全く分からない。 36732 | 36733 | 取り敢えずこれに関しては最新の ble-0.3 を試してもらって 36734 | 様子を見る事にする。もしかすると治るかもしれない。 36735 | 何れにしても最初のロードではちゃんと動くので何かが変なんだ。 36736 | 36737 | * 分かった事は _ble_keymap_emacs_kmap_ が配列になっていないという事。 36738 | 何が原因だろうか。nawk による処理で print definition がちゃんと動いていない? 36739 | 36740 | nawk では ENVIRON が使えないという噂があったので調べてみたが動いている気がする。 36741 | というかどうやって dump していたのだったか。 36742 | ble-decode/keymap/dump emacs を使っている。 36743 | 更に内部では ble/util/declare-print-definitions という関数を使っている。 36744 | 36745 | うーん。nawk に差し替えてもちゃんと動いている。Bash 5 でも Bash 3.2 でも問題ない。 36746 | $ ble/bin/awk() { /usr/bin/nawk "$@"; } 36747 | $ ble/util/declare-print-definitions arr 36748 | arr=([0]="1" [1]="3" [2]="4321" [3]="231") 36749 | 36750 | うーん。何が原因なのだろうか。向こうで実行してもらうという手もある。 36751 | 何れにしても改めて向こうに以下を試してもらう必要がある。 36752 | $ grep _emacs_ "$_ble_base_cache/keymap.emacs" 36753 | $ arr=(1 2 3) 36754 | $ declare -p arr | cat -A 36755 | $ ble/util/declare-print-definitions arr | cat -A 36756 | $ cat -A <<< $IFS 36757 | 36758 | うーん。もしかして IFS が変な値を持っているのが原因という可能性はある? 36759 | 36760 | 取り敢えず _ble_keymap_emacs_kmap_ の出力結果が 36761 | 配列でなくスカラーになっていた時に現象が再現するかについて確認する。 36762 | →取り敢えず右辺を '...' で囲むと報告されているのと同じ状態になるという事は分かった。 36763 | やはり ble/util/declare-print-definitions が不味いという事なのだろう。 36764 | 36765 | ? 或いは busybox awk など更に別の実装を使っている可能性はあるだろうか。 36766 | nawk, mawk, busybox awk の何れを試しても ble/util/declare-print-definitions 36767 | はちゃんと動いている様に見える。やはりよく分からない。 36768 | 36769 | * is-keymap は配列かどうかも含めて検査するべきではないか。 36770 | と思って実装を確認したがこれはどうやら register されたかどうかの判定。 36771 | 従って関係ないのであった。これはまあ修正しなくても良い。 36772 | 36773 | + done: 解決後に bash_profile ではなくて bashrc に書く様にお願いする 36774 | →これは適当な折に説明を書いた 36775 | + done: 解決後に chsh しないのかという事を尋ねる 36776 | →これも向こうが疑問に思っていたのでその折に説明した 36777 36778 2020-01-11 36779 36780 * ble.sh session からログアウトした時の Bash の終了ステータス [#D1215] 36781 36782 C-d で抜けると 2 や 255 になっている。 36783 exit コマンドで抜けた場合は 0 である。この違いは何処から? 36784 普通の Bash session から C-d でログアウトした時は 0 である。 36785 36786 →これは何故か exit の引数に "$ext" を渡していて、 36787 然し ext という変数がそもそも存在していなかったのが原因だった。 36788 恐らく ble/builtin/exit の実装における builtin exit "$ext" をコピーしたからか、 36789 或いは実装の途中で "$ext" が実際に存在していたかのどちらかである。 36790 何れにしてもこれを exit 0 に書き換える事にした。 36791 36792 * 未だ linux console の振る舞いが変だ [#D1214] 36793 36794 最後の行で DL (CSI M) しても何も起こらない。この振る舞いは普通じゃない。 36795 もし ANSI に反していないのだとしても修正しても良いのではないだろうか? 36796 (然し、他のプログラム vim や emacs はこれをどの様に取り扱っているのだろうか。) 36797 36798 * Linux console を調べる 36799 % Linux に対する修正を考える場合どの様にしたら良いのだろうか。 36800 % 様々な文書に目を通さなければならないらしい。 36801 % https://github.com/torvalds/linux/blob/master/Documentation/translations/ja_JP/howto.rst 36802 % 36803 % そもそも問題の linux console は linux に含まれているのかという所から謎。 36804 % https://elixir.bootlin.com/linux/latest/source/include/linux/console.h#L145 これは多分違う。 36805 % /dev/console 的な意味でのコンソールである。うーん。clone する? 36806 % 実のところどれだけの容量があるのか分からない。実際に clone を試みると712万のファイルがある。 36807 % 例によって github の connection は 30KiB/s と低速である。 36808 % 1/1000コピーした時点で 4MiB になっている。つまり合計で 4GiB ぐらいある? 36809 % 36810 % 調べると github は単なるミラーで本家は kernel.org にあるそうだ。 36811 % という訳で github は遅いので kernel.org からクローンする事にする。 36812 % と思ったら kernel.org は github にも増して遅い。駄目だ。 36813 36814 うーん。cygwin でも同じ振る舞いになるという事は、まあ許容するしかないのだろうか。 36815 後で興味があれば該当部分のコードを確認する事にする。 36816 36817 * 後で見たらダウンロードが終わっていた。結局 1.2GiB 程度だった様だ。 36818 また時間帯によるのだろうか平均で 52KiB という事だった。 36819 20秒で1MiB,1分で3MiB,100分で300MiB,400分で1.2GiBである。約6時間。 36820 * grc '\bSGR\b' で検索するとどうやら linux/drivers/tty/vt/vt.c に console の機能がある。 36821 * CSI M, L の機能は csi_{M,L} という関数で実装されていて、 36822 実際の処理は con_scroll という関数で実行している。この con_scroll が怪しい。 36823 * 因みに 2;R;G;B にも対応している様だ (表示できるかどうかは別なのだろうが)。 36824 →調べてみると rgb_{fore,back}ground という関数で色相を元にして 16 色コードに変換している。 36825 36826 取り敢えず ble.sh 側で対策を考える。 36827 というかこの振る舞いは cygwin コンソールと同じ? #D1147 に記録がある。 36828 うーん。最終行に於ける DL は信用できない物なのか。 36829 36830 * そもそも最終行の時にだけ注意すれば良いのだろうか? 36831 以前 cygwin の console を観察した時には丁度ぴったり 36832 下にある行が消える時には必ず動かないという事だった。 36833 →今確認した所そういう問題は発生していない様だ。 36834 36835 * linux console での振る舞いが怪しい [#D1213] 36836 調べると arch では発生していない。arch の kernel は 5.4.8-arch-1 である。 36837 ubuntu では 5.0.0-37-generic である。うーん。取り敢えず古い kernel の方に合わせて 36838 変なシーケンスは送らない様に修正する? 36839 36840 * highlight: ${var@a} 等の変換に対する着色に対応していない (for bash 4.4) [#D1212] 36841 36842 * highlight: 変数名で配列名・整数・読み取り専用などに応じて色を変えるか? [#D1211] 36843 →取り敢えず配列・読み取り専用・整数の属性について判定を行う事にした。 36844 36845 環境変数かどうかの属性と大文字・小文字属性もある。 36846 というかこの機能は知らなかった。 36847 36848 ? -l -u を使えば tolower をもっと簡単に実装できるのでは? 36849 x 然し調べてみると、問題点は全角アルファベットなども全て変換してしまうという事。 36850 これが実際に望ましい結果なのかどうかは用途に応じて考える必要がある。 36851 因みに ${var,,?} の形式の場合にも全角も含めて全て変換される。 36852 但し、こちらの場合には ${var,,[A-Z]} 等の様にして制御する事が可能である。 36853 36854 実際に string#tolower の使用箇所を見てみると、 36855 特に半角だけを特別扱いする必要のある場所もない。 36856 従ってこのままで良い。 36857 36858 また、-l, -u の機能は Bash 4.0 からであり、 36859 ${var,,} の機能も Bash 4.0 からなので、結局どちらを使っても良い。 36860 -l, -u を使うと一旦別の変数に代入しなければならなくなるので、 36861 実の所、現状のまま ${var,,} を使うのが良いだろうという気がする。 36862 36863 * Bash 4.3 の ChangeLog に -c という属性に対する言及があるがこれは何? 36864 36865 | j. Converting an existing variable to a nameref variable now turns off the 36866 | -i/-l/-u/-c attributes. 36867 36868 うーん。ChangeLog の他の箇所には出て来ないし、 36869 また、declare --help にも書かれていない。 36870 然し、実際に実行してみたところ使える様だ。 36871 36872 * highlight: 変数名の着色、算術式の着色 [#D1210] 36873 36874 * fast-syntax-highlighting は変数が存在するかしないかによる判定も行っている 36875 36876 というか ble.sh でもこれは簡単にチェックできるのではないだろうか。 36877 存在する変数と存在しない変数。現在の解析は純粋に文法で行っているので 36878 変数の存在・不存在によって着色を変えるという事は考えていなかった。 36879 これは文法レベルの着色で対応するべき事なのか或いは 36880 もっと上のレイヤーで着色するべき事なのか。 36881 うーん。というか変数の中身が空かどうかにも応じてチェックして良いのでは。 36882 36883 set -u の時にはエラー着色をしようと思ったが、 36884 ${var-} や ${var+} の時にはエラーにならないなどの規則が面倒。 36885 と思ったが、現在の解析では - や + が続きにあるかどうかを 36886 その場で判定しているのでこれの対応はそんなに難しくない。 36887 一方で、編集している途中で変数の状態が変わってしまう可能性はあるだろうか? 36888 それから構文解析する関数の中で使っている一時変数が勝手に存在する事になる可能性? 36889 36890 算術式の変数名に関しても着色できるはず。 36891 配列・連想配列や整数の属性? 読み取り専用やexport,local,etc. 36892 36893 頭が動いていない。今何をしようとしていたのかと言うと、 36894 declare の引数の色は何処で決まったのかという事。 36895 これは実は単語の始まりの時に既に決まっているのではないだろうか。 36896 書き換えようとして思ったが declare aaa の時には変数が存在していても 36897 存在していなくても文法的には有効なのであるから色を変える必要はないのでは。 36898 と思ったが、一貫性を考えるのであればやはり色を与えても良い気がする。 36899 うーん。その文脈で色が必要かどうかに関係なく着色する事にする。 36900 36901 2020-01-10 36902 36903 * util: support Minix (OS) [#D1209] 36904 36905 Minix の上でも msleep の実装が駄目だった。 36906 今度は read -u 番号 による指定が使えない雰囲気である。 36907 36908 また Minix では HOSTNAME が IP Address になっていた。 36909 この場合に PS1 の \h が IP アドレスの最初の番号だけを表示する。 36910 これは都合が悪いので IPv4 の形式の場合には \h は省略しない事にした。 36911 36912 他に Minix に ble.sh を持っていく時に make dist しようとしたら 36913 エラーが発生したので修正した。 36914 36915 * util: support Haiku (OS) [#D1208] 36916 36917 Haiku 上で動かしてみると先ず sleep が動かない。 36918 mkfifo 等の機能が完全ではないという事の様に見える。 36919 Cygwin と同様に /dev/udp/0.0.0.0/80 を使ってみたがそれも駄目だった。 36920 通常の sleep コマンドに fallback する事にした。 36921 一応 GNU coreutils sleep が入っているので全く動かないという事はない。 36922 36923 次に stty がエラーメッセージを出力している。lnext はないと言っている。 36924 確かに POSIX を見るとサポートされている文字の種類はそんなにない。 36925 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/stty.html 36926 現在使っているのは kill lnext werase erase intr quit susp である。 36927 kill intr erase quit susp はある。lnext, werase はない。 36928 仕方がないので初回起動時にチェックする事にする。 36929 36930 後は cmap で home,end,insert,delete の類の表現を調べるのに使っている 36931 tput で terminfo を想定していたが termcap でも大丈夫な様に修正した。 36932 36933 2020-01-07 36934 36935 * global: workaround Solaris awk [#D1207] 36936 36937 % Solaris の awk は ENVIRON が使えない。POSIX には ENVIRON が載っているのにも関わらず。 36938 % POSIX "In addition, all environment variables shall be visible via the awk variable ENVIRON." 36939 % 最近 POSIX に載ったという事なのだろうか。なるほど、 36940 % "Several features have been added based on newer implementations of awk:" のリストに載っている。 36941 % これによると -v assignment も新しい機能だそうだ。 36942 % 36943 % 何れにしても ENVIRON がなくても動くようにしなければならない。 36944 % 36945 % どの様にして文字列を渡すのが懸命だろうか。 36946 % a 一つの方法は -v var=... で渡す方法。 36947 % 然し、... の部分をエスケープしなければならない。 36948 % どの文字をエスケープする必要があるだろうか。\ だけ? 36949 % 更に -v も新しい機能だそうだ。 36950 % 実際に Solaris の awk に対して使ってみるとエラーになる。 36951 % 36952 % b 或いは "..." の部分に埋め込むしかないのだろうか。 36953 % 面倒な事である。 36954 % 36955 % * !a[$0]++ が使えないので a[$0]++ != 0 としなければならない。 36956 % * また BEGIN を二つ以上含む事もできない。 36957 % というか一番最初でなければならない様だ。 36958 % * 何と Solaris の awk は user-defined function すら定義できない? 36959 % うーん。これはどうしようもない。 36960 36961 Solaris の awk は絶望的に使えない。関数が使えないのでもうどうしようもない。 36962 36963 調べると普通は /usr/xpg4/bin/awk (nawk) を使うそうな。 36964 36965 何と。xpg4 awk も他の awk と異なる動作をする。nawk と同じであるかの様に説明されていたが、 36966 実際のところ他の nawk とも違う振る舞いをしている様だ。以下の様にすると確かめられる。 36967 $ echo "'" | /usr/xpg4/bin/awk -v apos=\' '{APOS=apos "\\" apos apos;gsub(apos,APOS);print}' 36968 36969 APOS=apos "\\\\" apos apos にすれば良いかと思いきや、 36970 そうすると今度は別の gawk,nawk,mawk が期待したのと異なる結果になる。 36971 うーん。どの様にしたらまともな動作にする事ができるだろうか。 36972 取り敢えず動くようにした。問題なく動いている様に見える。 36973 後で問題が起こるかもしれないが、取り敢えずこれで良い事にする。 36974 36975 * color: ble-color-setface の警告メッセージ (reported by cmplstofB) [#D1206] 36976 https://github.com/akinomyoga/ble.sh/commit/1885b541dfc200d9a0d2b5e8d6959d132462a008#r36687109 36977 36978 古い形式 face:*, iface:* を使った時の警告メッセージが間違っていた。 36979 36980 * global: FreeBSD, Arch Linux, etc. 対策 [#D1205] 36981 36982 - make が GNU make とは限らない。 36983 - which があるとは限らない 36984 - man があるとは限らない 36985 - LC_COLLATE を変えようとするとエラーメッセージが出る @ Arch Linux 36986 何故かは分からない。 36987 →これは分かった。日本語の locale しか生成していなかった。 36988 実際に試した環境は LANG=en_US.UTF-8 であったが、 36989 実は en_US.UTF-8 の locale が生成されていなかったのである。 36990 何れにしてもシステムの設定に少し異常が在るだけで使えなくなるのも不便なので 36991 やはり無理やりメッセージは封じ込める事にする。 36992 36993 * [自然解消] 2019-07-02 term: tput が terminfo (ncurses) ではなくて termcap の場合? [#D1204] 36994 Ref #D1203 36995 36996 | sentaku ではそれに対応している。ble.sh では terminfo ではなかった場合には、 36997 | 既定で ANSI のシーケンスを用いる様になっている。 36998 36999 これは実際には問題にはならないと思っていたが実際に問題になっていた。 37000 terminfo の項目名と似た名前の別の termcap 項目が呼び出されて変な事になっていた。 37001 37002 * term: FreeBSD に入れてみたら着色が動かない [#D1203] 37003 どうやら tput が terminfo ではなくて termcap で動いているのが理由。 37004 修正することにした。今は動いている。 37005 37006 * Makefile: BSD sed では i... と書けないそうだ (reported by dylankb) [#D1202] 37007 https://github.com/akinomyoga/ble.sh/issues/33#issuecomment-571234160 37008 37009 修正しなければならない。修正した。 37010 37011 2020-01-06 37012 37013 * syntax: 解析状態の異常 in Bash <= 4.1 [#D1201] 37014 function a { local IFS=\;; hello+=("${@:1}"); }; a 1 2 3; declare -p hello 37015 で hello の直前で C-u すると解析状態のエラーになる。 37016 function x { local A=\;; h+=("${@:1}"); } でもなる。 37017 function x { h+=("${@:1}"); } でもなる。 37018 { h+=("${@:1}"); } でもなる。 37019 { h+=("$@"); } でもなる。 37020 { h=("$@") でもなる。 37021 { h=("$a") でもなる。 37022 { h=("$(echo)"); } でもなる。 37023 37024 Bash 5 では再現しない。Bash 4.2 でも再現しない。 37025 Bash 4.1 で再現する。これの対応は調べるのが面倒そうだ。 37026 ble_debug=1 で状態の違いを比較する。 37027 37028 | Bash 4.0 37029 | _ble_syntax_attr/tree/nest/stat? 37030 | 18 a 000 '{' ++ word=CMDI:0-1>@0/(wattr=d) word="none":0-1 nest=(CMDI w=CMDX:0- n=- t=-:-) stat=(CMDX w=- n=- t=-:-) 37031 | 17 a 001 ' ' stat=(CMDX1 w=- n=- t=$1:-) 37032 | 7 a 002 'h' | stat=(CMDX1 w=- n=- t=$1:-) 37033 | 8 a 003 '=' | 37034 | 12 a 004 '(' || nest=(VRHS w=_ble_attr_VAR:2- n=- t=-:$1) 37035 | 9 a 005 '"' |||| nest=(VALI w=VALI:5- n='none':4- t=-:-) stat=(VALX w=- n=@4 t=-:-) 37036 | 14 a 006 '$' |||| stat=(QUOT w=- n=@5 t=-:-) 37037 | 7 a 007 'a' |||| 37038 | 9 a 008 '"' ||++ word=VALI:5-9>@8/(wattr=d) word="none":5-9 stat=(QUOT w=- n=@5 t=-:-) 37039 | 12 a 009 ')' ++ word=_ble_attr_VAR:@0>2-10>@9/(wattr=d) word="none":4-10>@8 stat=(VALX w=- n=@4 t=$9:-) 37040 | | s 010 ^@ stat=(CMDXV w=- n=- t=$10:-) 37041 | 37042 | Bash 4.2 37043 | _ble_syntax_attr/tree/nest/stat? 37044 | 18 a 000 '{' ++ word=CMDI:0-1>@0/(wattr=d) word="none":0-1 nest=(CMDI w=CMDX:0- n=- t=-:-) stat=(CMDX w=- n=- t=-:-) 37045 | 17 a 001 ' ' stat=(CMDX1 w=- n=- t=$1:-) 37046 | 7 a 002 'h' | stat=(CMDX1 w=- n=- t=$1:-) 37047 | 8 a 003 '=' | 37048 | 12 a 004 '(' || nest=(VRHS w=_ble_attr_VAR:2- n=- t=-:$1) 37049 | 9 a 005 '"' |||| nest=(VALI w=VALI:5- n='none':4- t=-:-) stat=(VALX w=- n=@4 t=-:-) 37050 | 14 a 006 '$' |||| stat=(QUOT w=- n=@5 t=-:-) 37051 | 7 a 007 'a' |||| 37052 | 9 a 008 '"' ||++ word=VALI:5-9>@8/(wattr=d) word="none":5-9 stat=(QUOT w=- n=@5 t=-:-) 37053 | 12 a 009 ')' ++ word=_ble_attr_VAR:@0>2-10>@9/(wattr=d) word="none":4-10>@8 stat=(VALX w=- n=@4 t=$9:-) 37054 | | s 010 ^@ stat=(CMDXV w=- n=- t=$10:-) 37055 37056 特に違いは見られない。エラーが起こった後の状態についても確認してみる。 37057 37058 | Bash 4.0 _ble_syntax_attr/tree/nest/stat? 37059 | 7 a s 000 'h' | stat=(CMDX w=- n=- t=-:-) 37060 | 8 a s 001 '=' | 37061 | 12 a s 002 '(' || nest=(VRHS w=_ble_attr_VAR:0- n=- t=-:-) 37062 | 9 a s 003 '"' |||| nest=(VALI w=VALI:3- n='none':2- t=-:-) stat=(VALX w=- n=@2 t=-:-) 37063 | 14 a s 004 '$' |||| stat=(QUOT w=- n=@3 t=-:-) 37064 | 7 a s 005 'a' |||| 37065 | 9 a s 006 '"' ||++ word=VALI:3-7>@6/(wattr=d) word="none":3-7 stat=(QUOT w=- n=@3 t=-:-) 37066 | 12 a s 007 ')' ++ word=_ble_attr_VAR:@-1>0-8>@7/(wattr=d) word="none":2-8>@6 stat=(VALX w=- n=@2 t=$7:-) 37067 | | s 008 ^@ stat=(CMDXV w=- n=- t=$8:-) 37068 | 37069 | Bash 4.2 _ble_syntax_attr/tree/nest/stat? 37070 | 7 a s 000 'h' | stat=(CMDX w=- n=- t=-:-) 37071 | 8 a s 001 '=' | 37072 | 12 a s 002 '(' || nest=(VRHS w=_ble_attr_VAR:0- n=- t=-:-) 37073 | 9 a s 003 '"' |||| nest=(VALI w=VALI:3- n='none':2- t=-:-) stat=(VALX w=- n=@2 t=-:-) 37074 | 14 a s 004 '$' |||| stat=(QUOT w=- n=@3 t=-:-) 37075 | 7 a s 005 'a' |||| 37076 | 9 a s 006 '"' ||++ word=VALI:3-7>@6/(wattr=d) word="none":3-7 stat=(QUOT w=- n=@3 t=-:-) 37077 | 12 a s 007 ')' ++ word=_ble_attr_VAR:0-8>@7/(wattr=d) word="none":2-8>@6 stat=(VALX w=- n=@2 t=$7:-) 37078 | | s 008 ^@ stat=(CMDXV w=- n=- t=$8:-) 37079 | 37080 | @@ -6,5 +6,5 @@ 37081 | 14 a s 004 '$' |||| stat=(QUOT w=- n=@3 t=-:-) 37082 | 7 a s 005 'a' |||| 37083 | 9 a s 006 '"' ||++ word=VALI:3-7>@6/(wattr=d) word="none":3-7 stat=(QUOT w=- n=@3 t=-:-) 37084 | -12 a s 007 ')' ++ word=_ble_attr_VAR:@-1>0-8>@7/(wattr=d) word="none":2-8>@6 stat=(VALX w=- n=@2 t=$7:-) 37085 | +12 a s 007 ')' ++ word=_ble_attr_VAR:0-8>@7/(wattr=d) word="none":2-8>@6 stat=(VALX w=- n=@2 t=$7:-) 37086 | | s 008 ^@ stat=(CMDXV w=- n=- t=$8:-) 37087 37088 確かに違いが現れてはいるが。。うーん。-1 という要素に何か親がいるかの様な取り扱いになっている。 37089 更新範囲についても確認しておく事にする。うーん。Bash-4.0 では最初の 4 文字についてだけの更新である。 37090 Bash-4.2 では全体に対して更新が実行されている。うーん。再計算範囲は一致しているのだろうか。 37091 37092 何れにしても Bash-4.2 以上では正しく動いているのだからこれはアルゴリズムの問題というよりは 37093 Bash の仕様の問題である筈だから修正はそんなに難しくはないのだと思われる。 37094 37095 * 再計算範囲 in ble/syntax/parse を出力して確かめる 37096 ble/syntax/parse/determine-parse-range の結果は同じ様だ。 37097 i1='0' i2='0' j2='2' 37098 i1='0' i2='0' j2='2' 37099 37100 * shift を実行した直後の状態は以下の通り。やはり違いはない様だ。 37101 37102 | _ble_syntax_stat=( 37103 | '1 -1 -1 -1 -1 -1 none 1' 37104 | '17 -1 -1 -1 0 -1 none 1' 37105 | '17 -1 -1 -1 0 -1 none 1' '' '' 37106 | '23 -1 -1 1 -1 -1 none 1' 37107 | '5 -1 -1 1 -1 -1 none 1' '' 37108 | '5 -1 -1 3 -1 -1 none 1' 37109 | '23 -1 -1 5 0 -1 none 1' 37110 | '13 -1 -1 -1 0 -1 none 1' 37111 | '1 -1 -1 -1 1 -1 none 1' 37112 | '1 -1 -1 -1 2 -1 none 1' 37113 | '43 -1 -1 -1 0 -1 none 1') 37114 | _ble_syntax_tree=( 37115 | '2 1 0 -1 d nnone 1 -1 -1 -' '' '' '' '' '' '' '' 37116 | '24 4 0 -1 d nnone 4 -1 -1 -' 37117 | '7 8 0 8 - nnone 6 1 -1 -' '' '' 37118 | '2 1 -1 3 d') 37119 | _ble_syntax_nest=( 37120 | '2 0 1 -1 -1 -1 none none' '' '' '' 37121 | '11 2 7 -1 -1 2 none none' 37122 | '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37123 | _ble_syntax_attr=('118' '17' '7' '8' '12' '9' '14' '7' '9' '12' '12' '1' '119') 37124 | 37125 | _ble_syntax_stat=( 37126 | '1 -1 -1 -1 -1 -1 none 1' 37127 | '17 -1 -1 -1 0 -1 none 1' 37128 | '17 -1 -1 -1 0 -1 none 1' '' '' 37129 | '23 -1 -1 1 -1 -1 none 1' 37130 | '5 -1 -1 1 -1 -1 none 1' '' 37131 | '5 -1 -1 3 -1 -1 none 1' 37132 | '23 -1 -1 5 0 -1 none 1' 37133 | '13 -1 -1 -1 0 -1 none 1' 37134 | '1 -1 -1 -1 1 -1 none 1' 37135 | '1 -1 -1 -1 2 -1 none 1' 37136 | '43 -1 -1 -1 0 -1 none 1') 37137 | _ble_syntax_tree=( 37138 | '2 1 0 -1 d nnone 1 -1 -1 -' '' '' '' '' '' '' '' 37139 | '24 4 0 -1 d nnone 4 -1 -1 -' 37140 | '7 8 0 8 - nnone 6 1 -1 -' '' '' 37141 | '2 1 -1 3 d') 37142 | _ble_syntax_nest=( 37143 | '2 0 1 -1 -1 -1 none none' '' '' '' 37144 | '11 2 7 -1 -1 2 none none' 37145 | '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37146 | _ble_syntax_attr=('118' '17' '7' '8' '12' '9' '14' '7' '9' '12' '12' '1' '119') 37147 37148 * 中途停止条件についても確認する 37149 37150 | _tail_syntax_stat[i-i2]='17 -1 -1 -1 0 -1 none 1' _stat='1 -1 -1 -1 -1 -1 none 1' 37151 | _tail_syntax_stat[i-i2]='23 -1 -1 1 -1 -1 none 1' _stat='23 -1 -1 1 -1 -1 none 1' 37152 | _tail_syntax_stat[i-i2]='5 -1 -1 1 -1 -1 none 1' _stat='5 -1 -1 1 -1 -1 none 1' 37153 | 37154 | _tail_syntax_stat[i-i2]='17 -1 -1 -1 0 -1 none 1' _stat='1 -1 -1 -1 -1 -1 none 1' 37155 | _tail_syntax_stat[i-i2]='23 -1 -1 1 -1 -1 none 1' _stat='23 -1 -1 1 -1 -1 none 1' 37156 | _tail_syntax_stat[i-i2]='5 -1 -1 1 -1 -1 none 1' _stat='5 -1 -1 1 -1 -1 none 1' 37157 | _tail_syntax_stat[i-i2]='5 -1 -1 3 -1 -1 none 1' _stat='5 -1 -1 3 -1 -1 none 1' 37158 | _tail_syntax_stat[i-i2]='23 -1 -1 5 0 -1 none 1' _stat='23 -1 -1 5 0 -1 none 1' 37159 | _tail_syntax_stat[i-i2]='13 -1 -1 -1 0 -1 none 1' _stat='13 -1 -1 -1 0 -1 none 1' 37160 37161 * 分からないのでもっと詳しく。うーん。不思議だ。_tail_syntax_* は一致しているが、 37162 ble/syntax/parse/nest-equals の結果が異なっている。 37163 という事は比較する瞬間の _ble_syntax_* が異なっているという事だろうか。 37164 37165 | _tail_syntax_stat=('17 -1 -1 -1 0 -1 none 1' '' '' '23 -1 -1 1 -1 -1 none 1' 37166 | '5 -1 -1 1 -1 -1 none 1' '' '5 -1 -1 3 -1 -1 none 1' '23 -1 -1 5 0 -1 none 1' 37167 | '13 -1 -1 -1 0 -1 none 1' '1 -1 -1 -1 1 -1 none 1' '1 -1 -1 -1 2 -1 none 1' 37168 | '43 -1 -1 -1 0 -1 none 1') 37169 | _tail_syntax_tree=('' '' '' '' '' '' '24 4 0 -1 d nnone 4 -1 -1 -' 37170 | '7 8 0 8 - nnone 6 1 -1 -' '' '' '2 1 -1 3 d') 37171 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37172 | _tail_syntax_attr=('7' '8' '12' '9' '14' '7' '9' '12' '12' '1' '119') 37173 | _tail_syntax_stat[i-i2]='17 -1 -1 -1 0 -1 none 1' _stat='1 -1 -1 -1 -1 -1 none 1' 37174 | _tail_syntax_stat[i-i2]='23 -1 -1 1 -1 -1 none 1' _stat='23 -1 -1 1 -1 -1 none 1' 37175 | inest='2' ext='1' 37176 | _tail_syntax_stat[i-i2]='5 -1 -1 1 -1 -1 none 1' _stat='5 -1 -1 1 -1 -1 none 1' 37177 | inest='3' ext='0' 37178 | 37179 | _tail_syntax_stat=('17 -1 -1 -1 0 -1 none 1' '' '' '23 -1 -1 1 -1 -1 none 1' 37180 | '5 -1 -1 1 -1 -1 none 1' '' '5 -1 -1 3 -1 -1 none 1' '23 -1 -1 5 0 -1 none 1' 37181 | '13 -1 -1 -1 0 -1 none 1' '1 -1 -1 -1 1 -1 none 1' '1 -1 -1 -1 2 -1 none 1' 37182 | '43 -1 -1 -1 0 -1 none 1') 37183 | _tail_syntax_tree=('' '' '' '' '' '' '24 4 0 -1 d nnone 4 -1 -1 -' 37184 | '7 8 0 8 - nnone 6 1 -1 -' '' '' '2 1 -1 3 d') 37185 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37186 | _tail_syntax_attr=('7' '8' '12' '9' '14' '7' '9' '12' '12' '1' '119') 37187 | _tail_syntax_stat[i-i2]='17 -1 -1 -1 0 -1 none 1' _stat='1 -1 -1 -1 -1 -1 none 1' 37188 | _tail_syntax_stat[i-i2]='23 -1 -1 1 -1 -1 none 1' _stat='23 -1 -1 1 -1 -1 none 1' 37189 | inest='2' ext='1' 37190 | _tail_syntax_stat[i-i2]='5 -1 -1 1 -1 -1 none 1' _stat='5 -1 -1 1 -1 -1 none 1' 37191 | inest='3' ext='1' 37192 | _tail_syntax_stat[i-i2]='5 -1 -1 3 -1 -1 none 1' _stat='5 -1 -1 3 -1 -1 none 1' 37193 | inest='3' ext='1' 37194 | _tail_syntax_stat[i-i2]='23 -1 -1 5 0 -1 none 1' _stat='23 -1 -1 5 0 -1 none 1' 37195 | inest='2' ext='1' 37196 | _tail_syntax_stat[i-i2]='13 -1 -1 -1 0 -1 none 1' _stat='13 -1 -1 -1 0 -1 none 1' 37197 | inest='-1' ext='0' 37198 | 37199 | --- a1.txt^I2020-01-06 18:58:23.708919459 +0800 37200 | +++ a2.txt^I2020-01-06 18:58:14.185056620 +0800 37201 | @@ -10,4 +10,10 @@ 37202 | _tail_syntax_stat[i-i2]='23 -1 -1 1 -1 -1 none 1' _stat='23 -1 -1 1 -1 -1 none 1' 37203 | inest='2' ext='1' 37204 | _tail_syntax_stat[i-i2]='5 -1 -1 1 -1 -1 none 1' _stat='5 -1 -1 1 -1 -1 none 1' 37205 | - inest='3' ext='0' 37206 | + inest='3' ext='1' 37207 | + _tail_syntax_stat[i-i2]='5 -1 -1 3 -1 -1 none 1' _stat='5 -1 -1 3 -1 -1 none 1' 37208 | + inest='3' ext='1' 37209 | + _tail_syntax_stat[i-i2]='23 -1 -1 5 0 -1 none 1' _stat='23 -1 -1 5 0 -1 none 1' 37210 | + inest='2' ext='1' 37211 | + _tail_syntax_stat[i-i2]='13 -1 -1 -1 0 -1 none 1' _stat='13 -1 -1 -1 0 -1 none 1' 37212 | + inest='-1' ext='0' 37213 37214 * ble/syntax/parse/nest-equals を呼び出した時の _ble_syntax_nest, _tail_syntax_nest を比較する 37215 37216 | inest='2' ext='1' 37217 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37218 | _ble_syntax_nest=('' '' '11 2 7 -1 -1 -1 none none' '' '' '' '' '' '' '' '') 37219 | inest='3' ext='0' 37220 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37221 | _ble_syntax_nest=('' '' '11 2 7 -1 -1 -1 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37222 | 37223 | inest='2' ext='1' 37224 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37225 | _ble_syntax_nest=('' '' '11 2 7 -1 -1 -1 none none' '' '' '' '' '' '' '' '') 37226 | inest='3' ext='1' 37227 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37228 | _ble_syntax_nest=('' '' '11 2 7 -1 -1 -1 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37229 | inest='3' ext='1' 37230 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37231 | _ble_syntax_nest=('' '' '11 2 7 -1 -1 -1 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37232 | inest='2' ext='1' 37233 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37234 | _ble_syntax_nest=('' '' '11 2 7 -1 -1 -1 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37235 | inest='-1' ext='0' 37236 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37237 | _ble_syntax_nest=('' '' '11 2 7 -1 -1 -1 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37238 | 37239 | --- a1.txt^I2020-01-06 19:04:07.351970453 +0800 37240 | +++ a2.txt^I2020-01-06 19:06:12.204172380 +0800 37241 | @@ -1,6 +1,6 @@ 37242 | inest='2' ext='1' 37243 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37244 | _ble_syntax_nest=('' '' '11 2 7 -1 -1 -1 none none' '' '' '' '' '' '' '' '') 37245 | -inest='3' ext='0' 37246 | +inest='3' ext='1' 37247 | _tail_syntax_nest=('' '' '11 2 7 -1 -1 2 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37248 | _ble_syntax_nest=('' '' '11 2 7 -1 -1 -1 none none' '24 0 24 1 -1 -1 none none' '' '' '' '' '' '' '') 37249 37250 うーん。何と状態は完全に同じなのに違う結果を返している? 37251 37252 * ble/syntax/parse/nest-equals の中の動作について詳しく追う。 37253 37254 | parent_inest='2' i1='0' i2='0' 37255 | parent_inest='2' _onest='11 2 7 -1 -1 2 none none' _nnest='11 2 7 -1 -1 -1 none none' 37256 | parent_inest='3' i1='0' i2='0' 37257 | parent_inest='3' _onest='24 0 24 1 -1 -1 none none' _nnest='24 0 24 1 -1 -1 none none' 37258 | onest=('24' '0' '24' '1' '-1' '-1' 'none' 'none') 37259 | parent_inest='0' _onest='' _nnest='' 37260 | onest=() 37261 | 37262 | parent_inest='2' i1='0' i2='0' 37263 | parent_inest='2' _onest='11 2 7 -1 -1 2 none none' _nnest='11 2 7 -1 -1 -1 none none' 37264 | parent_inest='3' i1='0' i2='0' 37265 | parent_inest='3' _onest='24 0 24 1 -1 -1 none none' _nnest='24 0 24 1 -1 -1 none none' 37266 | onest=('24' '0' '24' '1' '-1' '-1' 'none' 'none') 37267 | parent_inest='2' _onest='11 2 7 -1 -1 2 none none' _nnest='11 2 7 -1 -1 -1 none none' 37268 | parent_inest='3' i1='0' i2='0' 37269 | parent_inest='3' _onest='24 0 24 1 -1 -1 none none' _nnest='24 0 24 1 -1 -1 none none' 37270 | onest=('24' '0' '24' '1' '-1' '-1' 'none' 'none') 37271 | parent_inest='2' _onest='11 2 7 -1 -1 2 none none' _nnest='11 2 7 -1 -1 -1 none none' 37272 | parent_inest='2' i1='0' i2='0' 37273 | parent_inest='2' _onest='11 2 7 -1 -1 2 none none' _nnest='11 2 7 -1 -1 -1 none none' 37274 | parent_inest='-1' i1='0' i2='0' 37275 37276 parent_inest の更新に失敗している様だ。 37277 37278 とここで分かった。算術式のバグを踏んでいる。修正した。問題は発生しなくなった。 37279 37280 * 今度は Bash 3.2 で ble-reload の後に core-*.sh が読み込まれない問題が発生している [#D1200] 37281 bash-3.2: ble/complete/sabbrev/expand: No such file or directory 等と言っている。 37282 37283 振る舞いを調べると新しく load するとこれらの関数は delayed load の関数に置き換わり、 37284 delayed load の関数では最初に自身を unset してから ble/util/import して、 37285 その後に再実行するという作戦を取っている。 37286 この unset によって関数が削除されてそのまま実行できない状態になるという事だろう。 37287 37288 そして ble/util/import が再実行できない様になっている。うーん。 37289 つまり以前の読み込み済みのマーカーを削除できていない。 37290 37291 と思ったら bash 3.2 では BASHPID が存在していない? 37292 37293 どうやってサブシェルかどうかを判定すれば良いだろうか。 37294 $SHLVL はサブシェルでは更新されていなかった。 37295 $PPID もサブシェルでは更新されていなかった。 37296 Linux ならば /proc/self を readlink すれば良い? 37297 と思ったが実はこれだと readlink の pid が得られるだけだった。 37298 37299 検索したら質問があって其処で sh -c 'echo $PPID' というのが紹介されていた。 37300 更にその下で紹介されていたのは BASH_SUBSHELL という変数だった。 37301 https://unix.stackexchange.com/questions/524506/how-can-i-detect-if-im-in-a-subshell 37302 37303 調べてみると BASH_SUBSHELL は 3.0 で導入されたが、 37304 4.4 未満では echo $BASH_SUBSHELL | cat や <(echo $BASH_SUBSHELL) 37305 ではこの値が inc されないという問題があったそうだ。 37306 なので現在 subshell にいるかどうかの判定に使うのには信頼性が低い。 37307 37308 * done: 0.1, 0.2 にも同様の修正を適用する 37309 37310 * ble-0.3 で ble-reload の hang は直っていない様だ… [#D1199] 37311 前に修正した時の物と同じ物だろうか。 37312 一応 ble-0.3 にも同じ patch を適用しているが修正しきれていないという事になるか。 37313 関連する前の修正はこれである: #D1130 d35682a caa46c2 37314 #D1130 の記録を見てみたがよく分からない。余り参考にならなさそう。 37315 37316 * fixed: 一応 ble/base/unload-for-reload を実行した時の症状は似ているのではないか。 37317 37318 仕方がないのでこれは一つずつ確かめていく必要がある。 37319 先ず処理の流れを確かめる。 37320 37321 ble/base/unload-for-reload で _ble_edit_detach_flag=reload が設定される。 37322 ble-edit/exec:gexec/.end で .check-detach が呼び出されて、 37323 更にその中で _ble_edit_detach_flag=reload の時には 37324 メッセージが出力されて ble-edit/exec:gexec/.eval-prologue が呼びされる。 37325 何故ここで eval-prologue なのだろうか。PS1 等を復元する為? 37326 更に .end の中で通常ならば ble/term/enter, 37327 ble-edit/bind/.tail が呼びされる所、 37328 何も呼び出されずに終了する事になる。 37329 .end は最後に実行されるコマンドである。 37330 37331 さて、この時にどの様な状態になるのかというのが問題である。 37332 特に .tail が呼び出されないという事は出力がそのまま端末に繋がった儘という事。 37333 それは寧ろ期待している事なのではあるまいか。 37334 ble/term/enter が呼び出されないという事は 37335 端末の状態も通常のコマンドを実行しているのと同じという事。 37336 37337 では何故コマンドの入力が効かないのか。 37338 というか ble-decode/detach 等はしなくても良いのだろうか。 37339 うーん。ble-edit/detach, ble-decode/detach の療法を実行している。 37340 37341 うーん。どのコマンドを入力しても 37342 bash: self-insert: コマンドが見つかりません 37343 bash: accept-line: コマンドが見つかりません 37344 という状態になってしまっている。これはどういう事なのか。 37345 そもそも self-insert, accept-line をコマンドとして実行しようとする文脈が分からない。 37346 更にあらゆる入力が self-insert 及び accept-line しか呼び出さない状態になっている。 37347 →何と bind -x '"...":self-insert' で復元されている? 様な気がする。変だ。 37348 37349 less "$_ble_base_run/$$.bind.save" で復元用のスクリプトを見ると全てに -x がついている。 37350 うーん。分かった。ble/bin/echo が定義されていないのに ble/bin/echo を使う様に 37351 patch が追加されたのがいけなかった。これでエラーが発生して、 37352 __BINDP__ というマーカが出力されない事によって復元用の全ての bind が -x になってしまっていた。 37353 これについて修正した所 ble/base/unload-for-reload に関しては動く様になった。 37354 37355 * fixed: 然し、ble-reload で固まってしまう問題に関しては全く直っていない。 37356 うーん。どうも bind できていないという気がする。 37357 やはりだ。ble.sh を読み込んだ時に ble-decode/bind が呼び出される。 37358 ble-reload を呼び出した時に ble-decode/unbind だけが呼び出されて、 37359 ble-decode/bind が呼び出されていない。 37360 37361 実際に ble-0.4 の場合にはちゃんと ble-decode/bind が呼び出されている。 37362 この違いは何処から出てくるのだろうか。 37363 ble-0.4 で ble-reload で再 attach が呼び出される経路を見ると。 37364 どうも最後に描画状態を更新する時にプロンプトの再計算があって、 37365 其処で attach される様だ。 37366 37367 stackdump: 37368 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:17 (ble-stackdump) 37369 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:38 (ble/decode/attach) 37370 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:10 (ble-attach) 37371 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (ble/base/attach-from-PROMPT_COMMAND) 37372 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:13 (ble-edit/prompt/update/.eval-prompt_command) 37373 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:46 (ble-edit/prompt/update) 37374 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:3 (ble/textarea#render) 37375 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:15 (ble-edit/bind/.tail) 37376 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:7 (ble-edit/exec:gexec/.end) 37377 37378 素早く入力しても起こる事は変わらない様子だ。 37379 では ble-0.3 の場合には何が起こっているのだろうか。 37380 というか ble-edit/bind/.tail は呼び出されているのだろうか? 37381 37382 うーん。そもそも何故 .tail が呼び出されているのかというのが謎である。 37383 うーん。ble-0.4 では普通に .check-detach を通過している。 37384 調べてみると ble-0.3 の reload でも普通に .check-detach を通過している。 37385 37386 どうも reload した時にどの戦略を取るのかというのが違っている様子である。 37387 うーん。prompt 経由で attach する戦略を既定にしたら動く様になるのだろうか? 37388 →動くようになった。既に PROMPT_COMMAND が設定されている場合でも動くだろうか。 37389 →動く。OK 37390 37391 * util: Bash-3.2 で bash-preexec.sh と一緒に使うと初回コマンド実行時にエラーメッセージ (reported by dylankb) [#D1198] 37392 https://github.com/akinomyoga/ble.sh/issues/33#issuecomment-570949575 37393 37394 $ echo hello 37395 bash-3.2: read: ` prompt_command_array': not a valid identifier 37396 hello 37397 37398 prompt_command_array の read に失敗している。 37399 うーん。prompt_command_array なる変数は ble.sh では使っていない。 37400 調べてみると bash-preexec.sh にその様な変数が存在している様だ。 37401 正に以下の行が問題を起こしている事を示唆している。 37402 IFS=';' read -ra prompt_command_array <<< "$PROMPT_COMMAND" 37403 37404 * bash-preexec.sh を一緒にロードするとどうなるかテストする。 37405 37406 https://github.com/rcaloras/bash-preexec 37407 git@github.com:rcaloras/bash-preexec.git 37408 37409 エラーメッセージが再現した! 37410 然しその他のエラーは再現していない。 37411 つまりこれは独立した問題なのだろうという気がする。 37412 37413 症状を見ると bash-3.2 では起こるが bash-5 では起こらない。 37414 bash-4.0 でも起こらない。bash-3.1 で起こる。 37415 bash-3.0 ではそもそも bash-preexec.sh が文法エラー。 37416 37417 ble-0.4 でも同様の症状が発生する。 37418 37419 x 実はそれとは別に trap コマンドの引数の解析が誤っている。 37420 というのも invalid signal spec "-" というエラーメッセージが表示される。 37421 これについては bash の仕様を改めて調べる必要がある。 37422 37423 取り敢えず先に ` prompt_command_array' の方を片付ける事にする。 37424 うーん。どうも変だ。あー。分かった。これは引数解析のバグだ。 37425 と思ったが ble/array#push が悪いという事の気がする。 37426 IFS を設定すると動かなくなるという事が確認できた。 37427 $ array=(1); ble/array#push array 1 3; declare -p array 37428 $ array=(1); IFS=\; ble/array#push array 1 3; declare -p array 37429 うーん。然し実装を見てみると eval "$1+=(\"\${@:2}\")" である。 37430 これは bash 3.2 のバグである? 37431 37432 うーん。然し普通に hello+=("$@") を実行しても問題は発生していない。 37433 どうやら hello+=("${@:1}") の形式を使うと駄目な様だ。 37434 (IFS=\;; function a { printf '(%s)' "${@:1}"; }; a 1 2 3) 37435 これでも "${@:1}" の形式では引数がくっついてしまう。 37436 37437 2020-01-05 37438 37439 * main: 複数の ble.sh の version を使っている時に cache が混ざるのでは? [#D1197] 37440 cache 全般の問題として 37441 複数の ble.sh version を混ぜて使っていると駄目なのでは。 37442 cache ファイルが ble.sh 本体と比べて新しいかどうかで判定しているが、 37443 複数の ble.sh を混ぜて使っているとその関係が反転したりする。 37444 従って更新されないという事が普通に起こる気がする。 37445 37446 これに対応する為には cache ディレクトリ自体に ble.sh version を入れるか、 37447 或いは cache ファイルのそれぞれに ble.sh version を入れるかする必要がある。 37448 うーん。cache ディレクトリに ble.sh version を入れる事にする。 37449 適当に ${BLE_VERSION%%[-+]*} でも加えたら良いのでは。 37450 →patch level で形式が変わる可能性は低いし、 37451 異なる patch level を複数使い分ける事も考えにくい。 37452 major.minor だけで充分の気がする。 37453 37454 * ble-update は shallow clone で良い気がする [#D1196] 37455 ただ、これを今更変更しても 0.3.0 には反映されないのでは。 37456 と思ったがこれも fix として投入してしまえば問題ない。 37457 37458 * decode: "Failed to load the default keymap" で失敗した時に状態復元できていない (reported by dylankb) [#D1195] 37459 https://github.com/akinomyoga/ble.sh/issues/33 37460 これも上の報告のエラーメッセージの後に変な状態になっている様子から気づいた。 37461 37462 ? Failed to で失敗した時に stty を復元するべきでは? 37463 調べてみると復元している気がする。 37464 と思ったが stty/finalize を呼び出していて、ここでは stty -echo にしている。 37465 何故だろう? と思って遡って見るがどうも最初に stty/finalize を作成した時 (2015-02-11) 37466 からずっと stty -echo だった様である。今と昔では detach の方法が違うので、 37467 実はこれについては変更しても良いのではないかという気がする。後で考察する必要がある。 37468 37469 * done: これについて整理する。stty/finalize は ble/term/finalize から呼び出されている。 37470 ble/term/finalize は ble-detach/impl (ble.pp) と ble-attach 失敗時 (ble.pp) 37471 ble-decode/detach (decode.sh) 内部で呼び出されている。 37472 - ble-attach 失敗時には直前に ble-decode/detach が呼び出されている事が期待できる。 37473 - ble-detach/impl の場合にはやはり ble-decode/detach が直前で呼び出されている。 37474 - ble-decode/detach が呼び出されるのは上記の二箇所以外に 37475 set -o vi|emacs によって編集モードが変わった時の reattach の時である。 37476 37477 うーん。ble/term/finalize は ble-decode/detach 37478 の中で呼び出されるという事にして問題ない気がする。 37479 というのも attach の場合には ble/decode/attach で 37480 ble/term/initialize を呼び出しているからである。 37481 37482 無駄な呼び出しを削除した。確認してみると ble/term/{initialize,finalize} 37483 共に一箇所だけから呼び出される様になった。前よりもすっきりしたと思う。 37484 37485 さて、ble/term/finalize 引いては ble/term/stty/finalize も一箇所だけから呼び出される。 37486 この時に stty echo でも問題が生じないかについて調べる。 37487 取り敢えず問題は発生していない気がする。ble-detach では大丈夫。 37488 人為的に Failed to load the default keymap を起こした時も大丈夫。 37489 37490 * util: macOS での初期化時に bash-3.2 で "usage: sleep seconds" のエラーメッセージが出る (reporeted by dylankb) [#D1194] 37491 https://github.com/akinomyoga/ble.sh/issues/33 37492 これは上の報告のエラーメッセージを見ている時に気づいた。 37493 37494 ? sleep の引数がどうのこうのというエラーが出てもいる。関係は? 37495 →これはまた別の問題だった。というか sleep の小数対応判定が完全に間違っていた。 37496 coreutils sleep であっても false になってしまっていた。 37497 また macOS の場合には sleep は期待した物であると考えて良さそう。 37498 なので macOS のチェックと "usage: sleep seconds" が両方表示されたら OK という事にする。 37499 37500 2020-01-02 37501 37502 * 2019-05-27 history: 履歴のリアルタイム同期? [#D1193] 37503 現在は新しくコマンドを実行した時にだけ同期を行っている。 37504 履歴を参照する度に毎回同期を行う様にしたい。 37505 37506 更新のタイミングに関して。 37507 一回の widget の実行の中で読み込みを何度も実行すると、 37508 途中で get-index 等の値が勝手に変化したりする事になって混乱の元である。 37509 という事を考えると widget 毎に初回の history access の時にだけ更新するのが良い。 37510 widget を呼び出す時にローカル変数か何かを設定しておいてそれをクリアする様にする。 37511 初回の history アクセスの際にそのローカル変数が空だったら値を設定して更新を行う。 37512 更新は、もし履歴が初期化済みだったら増えた分だけ配列に追加するというのを実行する。 37513 37514 vim の mark 等で現在履歴項目に対して記録してある内容は shift する必要がある。 37515 他に現在の履歴項目関連で修正しなければならない物は何があるだろうか。 37516 例えば isearch の位置に関しては修正が必要になるのではないか。 37517 isearch の範囲に関しても修正が必要になる気がする。 37518 これらは以前まとめた history コマンドの対応の項目とも関連してくる。 37519 実のところそちらを先に実装してからの方が良いのかもしれない。 37520 - history: _ble_edit_history_ind の修正などが必要 37521 - ble-edit/undo: hindex の修正などが必要 37522 37523 同期のタイミングは難しい。 37524 例えば履歴を遡っている時に編集中の最新のコマンドはどうなるのか。 37525 最新のコマンドは _ble_edit_history_edit[N] に記録されている。 37526 この時新しいコマンドを読み取ってしまうと最新のコマンドは上書きされてしまう。 37527 vi.sh の mark や undo 等も同様である。 37528 最新の内容は新しいコマンドを読み取る前に待避して置かなければならない。 37529 37530 * 2020-01-02 これに関しては一番下の項目にいる時にだけ同期を実行する事にすれば良いのでは。 37531 % 或いは一番下の項目にいて更に下キーを押した時に限り自動ロードを試みる事にする。 37532 % →と思ったが現在の編集行の後に新しく履歴が追加されるのが自然なのか、 37533 % 或いは現在の編集業の前に新しく履歴が追加されるのが自然なのかは難しい。 37534 % その様に考えるとやはりコマンドを実行した時など履歴に登録がなされて 37535 % 新しい行がロードされる機会に更新が行われる方が動作として分かりやすい。 37536 % →やはり新しい履歴は現在の編集行の前に挿入されるべきである。 37537 % そうしないと履歴の順序などが変な事になってしまう。 37538 37539 逆に一番下の項目から遡ろうとする時に同期を実行するという手? 37540 或いは一番下の行に戻ってきた瞬間に同期を実行する。 37541 その様にするのが現在の所一番自然な気がする。 37542 37543 そもそも勝手に読み込みが為されるのが分かりやすいのかどうかというのもある。 37544 他の端末で大量にコマンドを実行した時に、 37545 現在の編集中のコマンド履歴が遠くなってしまうのは分かりにくくないか。 37546 しかし、それはそもそもコマンド履歴の共有をする時の分かりにくさでもある。 37547 コマンド履歴の共有を行っているのであれば実は大量のコマンドがあっても 37548 それを共有するというのが自然な振る舞いなのではないだろうか。 37549 37550 [実装] 37551 37552 取り敢えず一番下の履歴項目への(または、からの)移動の時に 37553 履歴の読み込みを試みる方向での実装を考える事にする。 37554 37555 一番下の履歴項目に関連して何か登録してある物があれば 37556 それを更新する必要がある。然し、それはコマンド履歴を登録せずに 37557 新しい行をロードする時にも同じ事なのではないか。 37558 つまり現状の実装で大丈夫ならば一番下の履歴項目に関連して 37559 ロードしている限りに於いては問題は起こらないのではないかという気がする。 37560 37561 * 自動読み込みによってプロンプト (\!) は変更されるか? 37562 所で履歴項目の番号がプロンプトに表示されるのだとすれば、 37563 それが読み込みの瞬間に変化するというのは見られるのかもしれない。 37564 と思って確かめたが履歴項目の番号に展開される backslash はなかった。 37565 と思ったが違った \! というのがそれに対応するのだった。 37566 然し、途中で履歴項目の番号が変化したとしても prompt の更新は 37567 local version=$COLUMNS:$_ble_edit_lineno 37568 で判定しているので更新はその場ではかからないのである。 37569 →変更されない。これはややこしい。 37570 或いは読み込みがあった時には強制的に _ble_edit_lineno 37571 を更新しても良いのかもしれないが。うーん。でもそれはそれで変だ。 37572 _ble_edit_lineno は独立した意味を持っている。 37573 然し実行した後で履歴展開を使用したい場合を考えると、 37574 其処に表示されている番号は当然正しい番号であって欲しい。 37575 37576 取り敢えず現在の実装を確認する事にする。 37577 history_share がある時には option:n を呼び出していて、 37578 更に ble/builtin/history/.read が呼び出されている。 37579 この中で新しい項目の読み込みを行っている。 37580 - 更に呼び出している ble/history:bash/resolve-multiline/readfile 37581 を確認してみたがこれは違う。bash の history に対する修正を行っているのみである。 37582 - ble/builtin/history/.read を確認すると ble/history:bash/load を呼び出していて、 37583 これが丁度 background で while case (0)...(6) をやっている関数である。 37584 中を確認するとここで mapfile で履歴を読み取ると共に 37585 複数行履歴の解決も実行している。 37586 何を確認するのだったか。どのように更新されるのかを確認するのだった。 37587 更新されるのは _ble_history 及び _ble_history_edit である。 37588 従って現在編集中の行が存在する場合には _ble_history_edit の内容は待避する必要がある。 37589 確認する事にする。というか undo 履歴などもある筈である。全て shift する必要があるのでは。 37590 37591 blehook の history_delete, history_clear に対応して 37592 逆に history_insert 的な操作を実装する必要がある気がする。 37593 37594 * undo 情報は何処で clear されているのか? 37595 というか空の行で実行した時に undo 履歴が clear されないのでは?? 37596 と思って確認してみたら clear されていた。どうなっている? 37597 空の行を実行すると .newline が呼び出される。 37598 中では ble/history/onleave.fire 37599 ble/widget/.newline/clear-content が呼び出されている。 37600 - clear-content の方は何も実行していない。 37601 - onleave.fire の方は history_onleave を invoke している。 37602 然し history_onleave に登録されているのは 37603 ble/keymap:vi/mark/history-onleave.hook だけである。 37604 37605 どうも変だと思って再度確認した所、 37606 実は undo 情報は clear されていなかった。 37607 空行で実行した後も undo 履歴は残っているのだった。 37608 これはこれで妥当な振る舞いの様な気がする。 37609 37610 取り敢えず謎は解けた。history_insert でも対応する事にするのが良さそう。 37611 option:n の読み取りに於いて history_insert が呼び出される様に実装した。 37612 取り敢えず history_share で option:n を呼び出す様にする。 37613 37614 [テスト] 37615 37616 一応動作はしている様子であるが変な事がある。 37617 37618 x fixed: 何故かロードが起こると bell が鳴る 37619 まあ n 件履歴項目が更新されましたなどと表示できるならばそれはそれで便利かもしれない。 37620 どうも option:n の中で発生している気がする。 37621 37622 調べてみるとどうも ble/widget/.bell が直接 ble-edit/history/goto の中から呼び出されている。 37623 あー。これはどうも分かった。option:n の中で更に history/goto が呼び出されている。 37624 内部では get-count が未だ更新されていない状態なので変な事になる。 37625 と思ったがどの経由で呼び出されているのかが分からない。 37626 history.sh では少なくとも直接は呼び出していない。 37627 37628 うーん。どうも ble-edit/history/history-insert.hook である。 37629 blehook/invoke history_insert の前に count を更新するのが良いだろうか。 37630 →_ble_history_count を更新してから invoke history_insert する様に変更した。 37631 37632 x fixed: 同時に二重に呼び出された時の振る舞いについて考えて置かなければならない。 37633 ちゃんと関数を呼び出し直す等の対策が必要になるのではないだろうか。 37634 →改めて goto を呼び出し直す事にした。 37635 x fixed: と思ったら無限ループになってクラッシュした。 37636 修正した。読み込みが起こった時にだけ goto (2回目) を呼び出す様にした。 37637 37638 x fixed: 未だ bell が鳴る。詳細を調べてみる。分かった。そもそも行き先の index の値が変だ。 37639 何故この様な結果になるのだろうか。。。 37640 37641 分かった。ble-edit/history/history-insert.hook の中で履歴項目を移動しているが、 37642 実は history.sh の側で既に履歴項目を移動しているのである。 37643 うーん。これによる移動をどうやって処理するのが正しいのか。。 37644 37645 調べると _ble_history_ind は edit.sh 側では一切触っていない。 37646 従ってこれの移動に関しては history.sh に任せるべきなのでは。 37647 これの移動に伴って edit.sh 側でしておかなければならない処理はあっただろうか。 37648 つまり単に移動するだけではなくて goto を呼び出す必要があった理由は何だろうか。 37649 37650 確かめてみると _ble_history_ind はちゃんと history.sh の側で更新されている。 37651 つまり今まで二重更新になっていた。 37652 うーん。goto を呼び出す事によって ind, mark が更新されるという事はある様だ。 37653 然しそれ以外の事に関しては何もない。そして ind,mark が勝手に更新されるというのも変な話だ。 37654 つまり単純に処理をしないというのが自然な実装である。単に hook を削除する事にした。 37655 37656 x fixed: 何故か PS1 が更新されない。PS1 の更新は試みられないのだったか? 37657 37658 どうやら内部的にはちゃんと prompt は変化している様子である。 37659 単に出力されていない。prompt の更新だけ簡単にできないかと思ったが 37660 色々と複雑そうだ。更に、prompt の変化があったかどうかも判定しなければならないが、 37661 rps だとか色々ある。仕方がないので invalidate を直接呼び出す事にした。 37662 37663 x fixed: うーん。検索中にキャンセルして現在編集位置に戻って来た時にロードが起こったりすると面倒。 37664 という事を考えると特別な keymap の時にはやはり history_share は off にするべきなのでは。 37665 37666 keymap を検索して isearch の時には読み込みを抑制する事にした。 37667 一方で nsearch や lastarg は history/goto を呼び出す事はないので 37668 そもそも history/goto に入ってくる事はないのでチェックしなくて良い。 37669 37670 2020-01-01 37671 37672 * history: history コマンドが --help に対応していない [#D1192] 37673 x 'unknown option "-$c"' という文字列が出力される。 37674 37675 * shopt -s xpg_echo の時変な事になるのではないか [#D1191] 37676 現在様々の出力を ble/bin/echo を通して行っているが、 37677 ble/bin/echo は builtin echo を使っていて、 37678 builtin echo は xpg_echo の影響を受けてエスケープシーケンスを解釈する様になる。 37679 これは予期せぬ振る舞いの原因になる。 37680 37681 printf で実装したいが完全なる echo の代替実装は難しい。 37682 先ず echo -n とそれ以外の echo で分ける必要がある。 37683 また複数の引数が指定されている時にどうするか? 37684 と思ったが複数の引数が指定されている場合は単に "$*" とすれば良いのだ。 37685 37686 ble/bin/echo 自体の関数名についての議論は #D1035 で行われている。 37687 この記録を見ると ble/bin/echo という関数名は取り敢えずの物の様だ。 37688 また関数名が速度に影響するとは言っても微々たる物なのでそんなに気にしなくて良い。 37689 echo という関数名を保持したのは -n という引数を解釈していたからである。 37690 今内部実装を printf に切り替えるとしたら -n という引数は使えない。 37691 ややこしいので別の関数名にするべきである。 37692 37693 以下の二種類の関数にする事にした。 37694 ble/util/print (改行を出力する) 37695 ble/util/put (改行を出力しない) 37696 37697 * ble.sh はプロンプトやエイリアスの設定を提供する物ではなくて [#D1190] 37698 基盤の枠組みを提供する物であるという旨を何処かに書いておくと良いかもしれない。 37699 つまり他の bash-it や oh-my-bash と併用する事もできるのだという事。 37700 37701 ただ、bash-it や oh-my-bash がそんなに便利で凄いかというと微妙。 37702 結局プロンプトを提供しているだけなのではないかという気がする。 37703 37704 * edit: support "shopt promptvars" [#D1189] 37705 この設定が存在している事に気づいていなかった。 37706 この設定が unset 状態にある時 PS1 の展開に於いて 37707 パラメータ展開、コマンド置換、算術式展開、クォート削除が実行されないそうだ。 37708 現在の実装について確認する。クォート削除が実行されないとすると、 37709 このクォート削除を想定としたクォートは必要ないという事になる。 37710 振る舞いについて確認する必要がある。 37711 37712 →うーん。やはり試してみた所 $ や ` が \ された形で埋め込まれてしまう。 37713 うーん。適当に対応した。promptvars が設定されていない場合には 37714 $`"\ の escape は実行しない様に変更した。多分これでちゃんと動いている。 37715 37716 * color: face の定義で ref を設定しても良いのではないか [#D1188] 37717 算術式なので簡単に実現できる気がするが技術的にはどうだろう。 37718 →調べてみると face に対応する sgr はキャッシュされている。 37719 _ble_faces_sgr という配列に格納されている。 37720 然し、この配列を触っている箇所は少ないので 37721 実はそんなに問題ではないかもしれない。 37722 37723 更に実はこのキャッシュは殆ど使われていないのではないか。 37724 syntax は ble/syntax/attr2g で直接 g 値を得ている。 37725 _ble_faces_sgr を使っているのは iface2sgr 及び face2sgr だけである。 37726 調べてみると iface2sgr は ble/color/list-faces しか使っていない。 37727 と思ったが face2sgr の方は結構使われている。 37728 - core-syntax は ble/syntax/print-status/ctx の中からしか使っていない。 37729 debug 用の関数なので速度に関しては実はそんなに気にしなくて良いのでは。 37730 - color.sh は ble/highlight/layer:{region,disabled}/update で使っている。 37731 - util.sh は bleopt, blehook の現在の状態の表示に使っている。 37732 他に ble/term/visible-bell の表示色の決定に使っている。 37733 やはり余り速度が重要になりそうな場面では使っていない。 37734 実装を g 値 → sgr という様にその場で変換する様に書き換えて問題ない気がする。 37735 或いは遅ければ別の枠組みを整えれば良いのである。 37736 或いは ref の時だけは空欄にしておいて空欄の時は毎回生成するという仕組みにする? 37737 →面倒なので何も考えずに毎回生成で良い気がする。 37738 37739 仕様について考える事にする。今までの face:... iface:... の意味を変える? 37740 もしくは新しく faceref:... の様な定義方法を使う? 37741 37742 恐らく使っている人は皆無である。従って問題にはならない。 37743 もし使っている人がいたとして循環する様な定義にしていたとしても、 37744 Bash 算術式には上限があるので意図的に回避しない限りは無限ループになる事はない。 37745 37746 従って意味を変える事にする。設定のコピーもできる様にしておく。 37747 37748 * done: _ble_faces_sgr を使わずにその場で g2sgr を呼び出す様に変更 37749 37750 * done: ble/color/{i,}face2{g,sgr} の戻り値を g, sgr に格納しているが 37751 この仕様は他の類似の関数と異なっている。 37752 これを ret を返す様に変更してはどうか。 37753 g や sgr に代入する関数は getg や get-sgr 的な 37754 関数名であるべきである。 37755 37756 他に g や sgr を直接に返す仕様の関数は存在しただろうか。 37757 37758 * done: setface の face:... iface:... の意味を変更する 37759 と思ったが ref:... copy:... に変更する事にした。 37760 そして face:... iface:... は廃止する事にした。obsolete 37761 取り敢えずサポートは続けるが警告を出す。 37762 37763 * done: wiki に説明は書いた 37764 37765 37766 2019-12-31 37767 37768 * complete: alias についても展開後のコマンド名を元にして [#D1187] 37769 補完関数を見つけに行っても良いのではないだろうか。 37770 37771 と思ったが mshex で定義されている alias の場合は微妙かもしれない。 37772 d や v や *:date や *:view に展開されるが、だからと言って 37773 date や view コマンドと同様に使うことができるかというと微妙。 37774 一応 g や m は git や make として使う事もできるので使っても良い。 37775 これに関しては mshex の側で良い様に取り扱えば良い。 37776 一部のコマンドだけ mshex/alias/git の様な関数名にするのも 37777 変だし mshex/alias:git に対する補完設定を登録するのが自然な気がする。 37778 その時には他のコマンドの設定を参照するという設定を行いたい。 37779 37780 * done: 他のコマンドの設定を参照するという設定 37781 37782 | a complete -F として空白を含む物も指定できるという事を悪用すれば、 37783 | complete -F "dummy --import git" g 的な記述もできる。 37784 | そうすると実際に読み取る際には complete -F dummy --import git g になる。 37785 | 然し、この方法は危ない。将来的に空白を含む関数名を指定できなくなるかもしれない。 37786 | それに ble.sh を load していない時には全く使えない設定になってしまう。 37787 | 37788 | b しかしだからと言って complete -F --import:git g 等とすると 37789 | 今度は原理的な問題として --import:git という名前の関数と区別がつかない。 37790 | またその様な関数が定義されていなかったとしても、 37791 | ble.sh を load していない時にはエラーメッセージの元になる。 37792 | 37793 | c 或いは complete -F ... -- '--special g' という感じに登録する? 37794 | これはスペースを含む様なコマンドが存在しない事から、紛らわしい事はない。 37795 | 問題はスペースを含む様なコマンド名が将来的に禁止されるかもしれないという事。 37796 | 37797 | やはり complete を使って無理やり登録するというのは違う気がする。 37798 | 37799 | d ble.sh の補完関数の仕組みから progcomp を呼び出せる様にする? 37800 | これが妥当な気がする。というより何故今までこれができなかったのだろう。 37801 | 構造を確認する事にする。 37802 | 37803 | どうも ble/complete/source:command/.progcomp を呼び出すだけの様だ。 37804 | 但し、指定したコマンド名に対応する規則で補完する為には 37805 | comp_words, comp_line, comp_point を書き換えなければならない。 37806 | うーん。或いは、規則を検索するのに使うコマンド名だけ変えれば良い? 37807 | 37808 | これは d で実装する事にする。 37809 | progcomp の第二引数にコマンド名を指定する事にした。 37810 37811 →最終的な仕様は ble/complete/progcomp git 等の様にして関数を呼び出す事とした。 37812 37813 g に関しては単純に以下の様な関数を定義すれば良い気がする。 37814 function ble/cmdinfo/complete:g { ble/complete/source:argument/progcomp '' git; } 37815 実際に試してみたが動かない。うーん。分かった。 37816 補完設定は遅延ロードになっていてその遅延ロードに使うコマンド名は 37817 comp_words から拾っている。従って comp_words を弄らなければ動かないのである…。 37818 37819 →結局 comp_words, comp_line, comp_point を再構築する事にした。 37820 動く様になった。これに関してはこれで良いという事にする。 37821 37822 alias に関してはどの様にするのが良いだろうか。 37823 complete で見つからなかったとしても complete -D による 37824 completion loader で実際には定義が見つかる可能性もある。 37825 然し completion loader まで行ってしまうと _minimal 等になってしまう。 37826 つまり本来は completion loader まで行ってその中で見つからなかった時に 37827 alias による展開結果に対して補完を試みるという様にしたいのである。 37828 然し、ble.sh の枠組みの中からではそれを検出するのは難しい。 37829 37830 うーん。或いは。complete -D に行く前に既に定義済みの物がないか確認する。 37831 というのの方が自然ではないか。こうするとその alias 専用の 37832 completion loader による遅延補完設定があった時にそれが使われなくなってしまうが、 37833 まあ alias に対して補完設定があるとも思えないのでそれで良いだろうか。 37834 うーん。然し本当だろうか。alias diff='colored diff' みたい 37835 になっていて colored 及び diff に対する遅延補完設定が存在していると、 37836 diff に対する補完設定は永久に呼び出されない。常に colored になってしまう。 37837 唯、この場合には colored が diff の補完設定を呼び出すべきではないか? 37838 と思ったがそれを実行させる為には comp_line の構築で colored diff の 37839 diff の部分も含める様にしなければならない。しかし、その様にすると 37840 実際には文法的にどの様な構造が入ってくるか分からないので、 37841 再度単語などの解析を実行しなければならない状況になる。面倒である。 37842 37843 * done: 取り敢えず実装した。遅延ロードとの関係については気にしない事にする。 37844 37845 * done: 或いは解決の際に勝手に __load_completion を呼び出しても良いのではないだろうか。 37846 37847 * done: alias で展開した時に増えた引数も comp_line の復元に入れるべきなのではないだろうか。 37848 →入れる事にする。但しその時に comp_cword の書き換えも実行しなければならない。 37849 テストしてみる事にする。 37850 37851 * done: 補完設定の検索は ble/cmdinfo も一緒に行うべき。 37852 alias の展開による補完関数の呼び出しが動いていない。 37853 と思ったら分かった…。g は ble/cmdinfo 経由で補完しているので 37854 補完設定が見つからないのだった。つまり補完設定の検索は外側の枠組みで実行するべきという事では。 37855 一つ外側の枠組みで補完設定を検索する事にした。 37856 ユーザが呼び出す ble/complete/progcomp という関数は、 37857 ble/cmdinfo/complete:cmd と complete -p cmd の両方を参照して補完を実行する。 37858 37859 2019-12-30 37860 37861 * 2019-11-23 complete: comps_flags の b と B が重複している [#D1186] 37862 nocaseglob の時に動かなくなるという旨がコメントで説明されているのにも 37863 関わらずその直上で b と B に別々の意味を割り当てているのである。 37864 これは simple-word の時点で重複した定義になっている事に注意する。 37865 37866 うーん。調べたが b が設定されている箇所を見つける事ができない。 37867 b はブレース展開の途中にいる時に設定されるそうだ。 37868 →分かった。これは core-complete.sh の中で設定していた。 37869 simple_ibrace に非自明な値が設定されていた時に b が設定される。 37870 37871 →ブレース展開の途中にいる時は x を使う事にした 37872 37873 ? fixed: 所で書き換えている途中で気づいたのだが ble/complete/util/construct-glob-pattern 37874 の中で comps_flags に i が含まれていないかテストしている。 37875 しかし、調べても i が設定される箇所はないし、何処にも説明もない。 37876 I ($"...") を意図しているとは考えづらい。これは何だろうか。 37877 37878 →これは恐らく :$comp_type: == *:i:* の誤りである。 37879 何故この様に二重にチェックしている構造になっているかというと、 37880 実は先に construct-ambiguous-regex を実装して、 37881 その実装を元にして construct-glob-pattern を実装したからではないかと思われる。 37882 37883 取り敢えずその様な想定で書き直した。 37884 再度確認する。やはり comps_flags に i が入り込む経路は存在しない。 37885 37886 * 2019-01-20 manual: Emacs 編集モード [#D1185] 37887 簡単にページを作った。特に詳しく説明する事もなく 37888 キー束縛を列挙するだけに留めたが、それで十分だろう。 37889 37890 2019-12-29 37891 37892 * color: true color support [#D1184] 37893 37894 https://github.com/brujoand/sbp 37895 37896 256色でもまあ問題はないだろうと思っていたが。 37897 よく考えてみたら既存の PS1 の設定の中には true color を使っている物もある。 37898 ble.sh の実装では PS1 を ble.sh で再解釈して terminfo で変換して出力するので、 37899 PS1 に true color を設定していてもそれがプロンプトに反映されない。 37900 つまり ble.sh が 24bit color に対応していないというだけで済まず、 37901 24bit color を想定したプロンプトの設定も動かなくなる。 37902 対応しなければならない。 37903 37904 [実装方法] 37905 37906 | 現在 gflags は何 bit 残っていただろうか。確認する。 37907 | 37908 | bit 0-8 : bold italic underline revert invisible strike blink 37909 | bit 8-16 : 前景色 37910 | bit 16-24: 背景色 37911 | bit 24,25: 前景色・背景色のon/off 37912 | 37913 | うーん。bit 26-32 の6bit と 32-64 の 32bit が残っている。 37914 | 本当に 24bit x 2 対応をするのか。。 37915 | 色の記録に追加で 32bit 必要になる。 37916 | 更に 24bit かどうかの判定に 2bit 必要になる。 37917 | そうすると残り 4 bit しかなくなる。うーん。 37918 | 将来的に fast blink だとか他の物に対応する余裕は全くなくなる。 37919 | 37920 | a もっと上手に code extension する方法を考える。 37921 | 今 8-16,32-48,24 の 25bit の組み合わせで何を表現できるかについて考える。 37922 | 現在使用している空間は以下の通りである。 37923 | 0000000 ... transparent 37924 | 10000XX ... 256色 37925 | 加えて以下を true color として使いたい。 37926 | 0XXXXXX ... RGB 24bit 37927 | 但し黒色 000000 は transparent 37928 | に既に使われているので表現できない。 37929 | 代わりに256色16番を使って表現すれば良い。 37930 | 実は 37931 | 1YYYYXX ... 256色 + 他の属性 37932 | という様にすれば他の属性を保持できない事もない。 37933 | 但し、24bit color と共存する事はできない。 37934 | 37935 | この方法の問題点は処理が複雑になるという事。 37936 | 37937 | b 或いは 24bit 本当に必要なのだろうか。。という疑問。 37938 | Web で考えると実のところ #rrggbb でなくて #rgb で足りる様な気もする。 37939 | つまり 12bit で十分なのではないかという可能性。 37940 | だとすれば 8bit 拡張するだけで良いのではないかという。。 37941 | 37942 | 然し何れの方法を取るとしても ble の内部実装の問題なので、 37943 | 実はいつでも好きに切り替える事ができる。何なら bleopt で 37944 | 切り替えられる様にしても良い。なので、ここは気楽に実装して問題ない気がする。 37945 | 取り敢えず後半の 32bit は使ってしまう事にする。 37946 37947 結論: gflags の内部表現はいつでも切替可能なので気にせず実装する 37948 それに将来別の属性が増えるとも考えにくい (増えるとしたら色空間だろう)。 37949 37950 [実装] 37951 37952 * 先ず後半 24bit に値を格納しても問題ない事を確認する 37953 37954 * done: 後半 24bit に値がある時にそれを出力するコード 37955 減色処理と一緒に実装しなければならない。 37956 37957 * done: gspec を解釈するコード 37958 37959 うーん。減色するに当たって 6x6x6 cube の階調がどうなっているか 37960 意識しなければならない。 37961 37962 * info: 6x6x6 cube 及び 24 grayscale 階調について。 37963 37964 | 等間隔で分割するならば 0 51 102 153 204 255 になる。 37965 | 一方で Poderosa の場合には 0 95 135 175 215 255 になっている。 37966 | うーん。両方実装する? 或いは…。うーん。取り敢えず等間隔を想定して実装する。 37967 | 等間隔でない場合に対しては後で考える事にする。 37968 | 24 gray scale に関しては 10k + 8 である。 37969 | と思ったがこれも何だかやってみると変である。 37970 | 元を辿ってみる。Poderosa の mwg.Rosa/Colors.cs の Xterm256Gray24 37971 | の表の中から拾った物で、これは 0x08 から始まって 0xEE で終わっている。 37972 | 0xEE = 255 - 17 = 238 である。うーん。全然等間隔ではない…。 37973 | 37974 | 等間隔で変換するならばどうなるか。 37975 | 10*23=230, 11*23=253 うーん。RLogin はどの様な実装になっているか。 37976 | RLogin は単に 11k になっている。offset はない。 37977 | 結局色々の terminal を調べる事にした。 37978 | 37979 | 11k 0..253 RLogin 37980 | 10k+8 8..238 Poderosa, xterm, contra, urxvt256c, mintty, mlterm, alacritty 37981 | 37982 | 51k 0..255 RLogin 37983 | k?55+40k:0 0..255 Poderosa, xterm, contra, urxvt256c, mintty, mlterm, alacritty 37984 | 37985 | % 6x6x6 cube の等間隔でない場合に対応する? 37986 | % 実はこれは 88colors の 4x4x4 に変換する時にも問題になる気がする。 37987 | % →圧倒的に非等間隔の端末が殆どなのでそれに従う事にする。 37988 | 37989 | % alacritty は grayscale の黒 232 以外は xterm と同じ。 37990 | % grayscale の黒 232 は本当に黒である。 37991 | % →変だと思って再度試してみたら 8 になった。 37992 | % 丁度文字の上をスポイトで抽出していただけの様だ。 37993 | % 結局 xterm と完全に同じ 37994 37995 RLogin 以外は xterm に従っている。 37996 Poderosa, xterm, contra, urxvt256c, mintty, mlterm で試した。 37997 更に alacritty, termit, lxterminal も試した。 37998 37999 terminology はなんか変な結果になる。何かの補正をかけているのだろうか。 38000 真っ黒が 2:2:2 であり、真っ青 (0,0,5) が 15:15:255 である。 38001 (0,0,1) が 4:4:97 である。(0,0,2)=6:6:137 (0,0,3)=9:9:177 38002 (0,0,4)=12:12:216 ちょっと規則が掴めない。彩度に制限をかけているのだろうか。 38003 gray scale に関しては特に変な事はなく xterm と同じく 8..238 の様だ。 38004 38005 RLogin は 6x6x6 は 51k で、grayscale は 11k である。単純明快。 38006 38007 [テスト] 38008 38009 うーん。取り敢えず一通り対応した様な気がする。本当だろうか? 38010 取り敢えず。実行してみる。 38011 38012 * 減色モードからテストする。 38013 x fixed: 構文エラー。算術式の括弧を閉じ忘れていた 38014 x fixed: 前景色の代わりに背景色が設定されている。 38015 g#setbg-index がないと怒られる。 38016 これは背景色用の関数名が g#setfg-index になっていた。 38017 x fixed: 構文エラー "g&>>16&0xFF" 38018 これは実装後に整理していた時に紛れたエラー。& 消し忘れ。 38019 x fixed: うーん。微妙な色を指定しても全部青になってしまう。何故? 38020 確認してみるとどうやら g 値への変換は期待通り動いている。 38021 然し、sgr に変換する時に駄目になっている気がする。 38022 分かった。g=$((ccode>>8&0xFF)) が g=$((ccode>>8&&0xFF)) 38023 になっていた。 38024 38025 x resolved: fg=#08d,bg=#f15 を設定したら誤った添字エラーになった。 38026 負の添字の配列要素は作れないのだった。 38027 どうしたら良いか…。ずらす? うーん。4bit 全体にずらす事にする。 38028 38029 というか今気づいたが今分断されている bit をまとめても良いのでは。 38030 改めて配置について考える事にする。例えば以下の様にする。。 38031 38032 00-08: attributes 38033 08-32: fg 38034 32-56: bg 38035 57 fg indexed 38036 58 bg indexed 38037 38038 x ok: この方法の問題は intmax_t が 32 bit のシステムで動かないという事。 38039 うーん。まあ仕方がない。というか shift 量が 32 を超えている時点で 38040 現状の実装でも 32bit の環境では動かない事になる。 38041 と思ったが実は 24bit color に触らない様にさえしていれば大丈夫? 38042 38043 然し、疑問は intmax_t が 32 な環境が果たしてこの世に存在しているのか 38044 という事である。或いは bash は 64bit 整数は使っていないのだろうか。 38045 https://www.jpcert.or.jp/sc-rules/c-int00-c.html やっぱり 64 bit 整数は 38046 少なくとも規格上は必ず存在する事になっていて、従って intmax_t は 64bit 38047 以上になるような気がする。但し、全てのシステムが規格に準拠しているとは 38048 限らないということには注意しなければならない。 38049 38050 うーん。取り敢えず intmax_t < 64 なシステムは捨てて良いだろう。 38051 捨てるというのが現状で妥当な判断である。 38052 38053 取り敢えず対応した。動いている。 38054 38055 * 24bit モードをテストする。 38056 38057 x fixed: term_true_colors を設定しても変わらないと思ったら、 38058 SGR がキャッシュされていたのだった。 38059 term_true_colors の変更と共に SGR のキャッシュを削除する様にした。 38060 表示されている。OK。 38061 38062 * sbp を試してみた。 38063 x fixed: sbp を試してみた。着色されない。もしかして PS1 の解析ルーチンは別? 38064 と思ったが trace でも ble/color/read-sgrspec を使っている筈。 38065 何故動かないのか。うーん。どうやら setbg-rgb が動いていない。 38066 38067 確認した所 rgb の r,g,b が g を被覆していた。 38068 rgb から RGB に書き換えたつもりだったが書き換え漏れがあったのだった。直した。 38069 38070 取り敢えず truecolor support はできたかなという気がする。 38071 38072 [256色判定] 38073 38074 * 256色判定はどうするのか? 38075 terminfo にそれ専用の項目があったようななかった様な。 38076 38077 https://gist.github.com/XVilka/8346728 によると 38078 "RGB" cap がある場合には setaf, setab を使って設定できるらしい。 38079 というか、今までの 256 色指定をしたい時はどうしたら良いのか謎。 38080 この仕様は D. Thomas による嫌がらせとしか思えない。 38081 https://lists.gnu.org/archive/html/bug-ncurses/2017-02/msg00018.html 38082 https://lists.gnu.org/archive/html/bug-ncurses/2013-10/msg00008.html 38083 要するに DT の主張は initc で十分の筈だという事。 38084 それから ncurses は 16bit 整数で動いているので 24bit 色は無理という事。 38085 38086 http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=e463e57 38087 https://qiita.com/__hage/items/4d8ad65b70e4d6142599 では 38088 Emacs の為に "setb24", "setf24" という項目を追加すれば良いという事になっている。 38089 TERM に -24bit (38:2:r:g:b) もしくは -24bits (38;2;r;g;b) を付ける話もある。 38090 38091 http://lists.schmorp.de/pipermail/rxvt-unicode/2016q2/002251.html 38092 tmux は "tc" という cap を見る様だ。 38093 38094 うーん。判定は難しい気がする。 38095 結局ユーザが #xxxxxx だとかを使ったらもうその時点で 38096 24bit 対応であると想定して良いのではないだろうか。 38097 それで変な結果になっても仕方がないという事にする。 38098 38099 将来的には自動判定を行う様にしたい。 38100 現段階では強制的に有効と見做す事にする。 38101 38102 2019-12-28 38103 38104 * wiki: 設定集を書く事にする Recipes とでも名前をつけようか [#D1183] 38105 38106 - [ble: exit %d] の消し方 38107 - auto-complete の色の変更の仕方 38108 38109 うーん。Q&A的だが他にも色々書ける筈。 38110 rps1 に現在の git の位置を表示するとか。 38111 38112 * #M0004 を参考に animation gif を作ろうとしたが 38113 使ったソフトウェアが分からない。何も記録に残っていない。 38114 前回の日付 2018-03-18 を元に Chrome のダウンロード履歴を 38115 探ったら LINEcap というソフトウェアをダウンロードしている。 38116 使ってみると覚えがあるのでこれである。 38117 38118 キー入力を表示するソフトウェアも分からない。 38119 これはダウンロードの履歴を見ても分からなかった。 38120 記憶によるとソースコードを弄って改造した筈である。 38121 なので何処かにソースコードがあるか GitHub にあるか GitLab にある。 38122 GitHub を確認してみたが fork していないので、GitHub にはない。 38123 GitHub の star にも記録は残っていなかった。寧ろ LINEcap が star されている。 38124 38125 適当にまた Google で検索してみる。KeyCastOW 何だか見覚えがある気がする。 38126 https://github.com/brookhong/KeyCastOW これだろうか。 38127 そうだった。ファイルを検索したら mag:.mwg/src/ble.sh/test/capture/KeyCastOW にあった。 38128 また分からなくなると嫌なので移動する事にする。GitHub にも上げた。 38129 38130 と思って実行しようとしたら Avira に隔離された。 38131 Avira の隔離を復元したら戻ってきたが今度は管理者権限を使っても 38132 ファイルが書き換えられないし削除もできない状態になった。 38133 これだとコンパイルできない…。親ディレクトリごと移動した後で削除できた。 38134 しかしその後も同じファイル名でファイルを作る事ができない。 38135 仕方がないのでプロジェクトのディレクトリを再び丸ごと移動した。 38136 38137 取り敢えず前と同様にキャプチャできる様になったので #M0004 を更新する。 38138 38139 * edit: [ble: exit %d] のメッセージを消したいという要望があった [#D1182] 38140 https://superuser.com/questions/1512618/autocompletion-background-colour-in-ble-sh#comment2288342_1512656 38141 38142 取り敢えず TRAPERR を定義してくれという様に書いたが分かりにくい。 38143 そういう設定変数を用意しようと思う。 38144 38145 * done: 実装した。 38146 * done: update blerc 38147 * done: update wiki 38148 38149 * done: TRAPERR と関係なく常に実行する様にしてはどうか。 38150 * done: trap ERR の設定も実行するべきなのではないか。 38151 * done: 終了ステータスを再設定して TRAPERR, trap ERR を呼び出すべきでは。 38152 ble/builtin/trap/invoke, blehook/invoke, ble/function#try で 38153 終了ステータスを伝播する様に修正した。 38154 38155 * done: 仕様変更について comment を残す。 38156 38157 README か何処かに設定について記述する。 38158 Q&Aページでも作る事にしようか。英語で書く? 38159 Wiki に英語版と日本語版を作りたい。 38160 説明書の下部に作るか。或いは別のページとして作るか。 38161 うーん。説明書とは独立なページにしたい気がする。 38162 Q&Aというよりは設定集という感じにするのが良さそう。 38163 →これは別項目を建てる事にした。 38164 38165 2019-12-27 38166 38167 * complete: bash-completion-partial-path を試してみたら変な動作をする [#D1181] 38168 38169 元々 bash-completion-partial-path は以下の help-bash に対する投稿で知った。 38170 https://lists.gnu.org/archive/html/help-bash/2019-12/msg00014.html 38171 この作者は今年の 7 月にプロジェクトを始めた段階で大々的に宣伝している。 38172 StackOverflow でもあらゆる場所で関連する質問に対して回答しているのだった。 38173 38174 展開内容が重複して挿入されてしまう。置換されるべき内容が消えてくれない。 38175 何が起こっているのだろうか。生成した候補を insert-common の見ると自前での候補生成と同じだ。 38176 更に調べてみるとどうやら comps_flags に a が含まれているかいないかの違いの気がする。 38177 然し a が含まれていなかったとしてもそれはそれでそれなりの結果になるべきなのではないか。 38178 38179 更に調べると determine-common-prefix の時点で変な結果が返ってきている様子だ。 38180 うーん。原因が分かった。comp_type に amAi が含まれている時には、 38181 曖昧前方一致であると解釈して一致しない部分に関しては保持する様になっている。 38182 然し、実際には曖昧一致という訳ではないのに i が入っている所為でこの処理が入ってしまっている。 38183 i だけしかない時には強制的に置換してしまって良いのではあるまいか。 38184 38185 然し果たしてそれで良いのだろうか。もし候補が複数あって、 38186 共通部分だけを挿入した時に候補が減少する様だと困る。 38187 問題はそういう曖昧一致を progcomp の側で実行された時。 38188 どのような曖昧一致戦略を取ったのか分からないので、 38189 曖昧一致部分だけを挿入するという事ができない。 38190 結局挿入は行わないというのが正しい選択なのだろうか。 38191 38192 [対策] 38193 38194 * done: 曖昧一致共通部分に含まれない部分を保持する処理を cand_count>1 の時にだけ実行する? 38195 38196 うーん。結局この処理の部分全体を cand_count>1 の時に実行する様にすれば良いのか? 38197 38198 * 前にこの辺りの判定については弄った事がある気がする。 38199 38200 | どのように弄ったのか確認する必要がある。 38201 | →調べてみた 6456d87d (2018-09-05) の時点で既に cand_count に関わらず 38202 | 曖昧一致の場合には一致しなかった部分を保持する様になっている。 38203 | →更に遡ると 64cdadc7 (2018-08-01) に於いて曖昧一致が実装されて 38204 | この時点では cand_count に関わらず曖昧一致で 38205 | 元の文字列に一致しない場合は一切の補完を実行しない様になっていた。 38206 | 38207 | | Commit 64cdadc "complete: implement ambiguous matching (bleopt complete_ambiguous)" 38208 | | lib/core-complete.sh 38209 | | 38210 | | if [[ $opt_ambiguous ]]; then 38211 | | # 曖昧一致に於いて複数の候補の共通部分が 38212 | | # 元の文字列に曖昧一致しない場合は補完しない。 38213 | | [[ $common =~ $rex_ambiguous_compv ]] || common=$COMPV 38214 | | fi 38215 | 38216 | つまり。cand_count>1 を敢えて cand_count==1 でも同様に処理する様にしたのではなく、 38217 | 始めから何も考えずに cand_count==1 でも制限をかけていた。という事になる。 38218 | うーん。或いは一番最初の設計の時にその辺りまで考察したのだったか。 38219 | 調べて見る必要がある。該当する項目は #D0707 であった。 38220 | 読んでみると其処までは考えていなかった様だ。 38221 | つまりこの部分の処理は全て cand_count > 1 の時にのみ実行する様に変更して良い気がする。 38222 38223 結論: 最初の実装から cand_count については確認していなかった。 38224 38225 * 改めてこの変更によってどのような影響が出るかについて少し考察しておく事にする。 38226 38227 先ず曖昧一致の候補を生成する時に、生成時点で filter してしまって、 38228 実のところ入力済みの部分全体に一致する訳ではない候補が生成される可能性はあるだろうか。 38229 例えば function name で最初の */ までしか候補として列挙しないという処置など 38230 によって曖昧一致候補の前半部分だけが単一の候補として列挙されて、 38231 入力文字列の後半部分が補完挿入時に失われてしまう可能性について。 38232 38233 うーん。その様な可能性はない気がする。やはり既に入力している文字列があるのであれば、 38234 候補生成ではそれも含めて生成しなければならない。 38235 もしそれを省略してしまって補完によって挿入済みの部分が失われてしまっても、 38236 それは補完候補生成器が意図した事なのかそうでないのかは外からは判定できない。 38237 38238 その様に考えるとやはり単一候補の場合には完全に置換してしまって良い気がする。 38239 38240 結論: 実施する。cand_count>1 の時にだけこの対処を実行する。 38241 38242 * done: 上の対策だけでは不十分である。実際に候補生成器が曖昧一致で複数候補を生成した時に 38243 どの様にして挿入を実行したら良いのだろうか。 38244 ble.sh の側ではどの様に曖昧一致が実施されたのかを知る術はない。 38245 挿入は行わない様にするのが自然な気がする。 38246 38247 x ok: 然しそうだとしても menu-filter が走ると候補が全て消滅してしまう。 38248 →と思ったが menu-filter の実装を見てみると head, substr, hsubseq, subseq の 38249 順番に試して一番最初に生き残る物を採用するという仕組みになっている。 38250 従って候補生成器が勝手に曖昧一致で生成してもちゃんと生成できる。OK 38251 38252 うーん。曖昧一致でないのに先頭一致しない候補が複数生成された時は 38253 補完挿入は実行しない。という実装に問題はあるだろうか。 38254 38255 →結局、曖昧一致でない時は共通部分が入力文字列の拡張になっていない場合には、 38256 補完挿入を実行しないという実装にする事にした。 38257 もし共通部分が入力文字列を拡張する場合には、 38258 補完挿入を許す事にする。 38259 38260 * done: ignore-case でない場合も対策しなければならない 38261 然し、よく考えたら i が入っていなくても progcomp が 38262 前方を書き換える様な候補を複数生成する事は可能性として残る。 38263 その様な場合にはどうしたら良いのだろうか。 38264 38265 現状の実装ではコメントに "Note: #D0768 文法的に単純であれば (構造を破壊しなければ) 38266 遡って書き換えが起こることを許す。" と書かれている。 38267 #D0768 の議論を確認した。うーん。ここの考察では勝手に progcomp が 38268 前方一致しない候補を生成する事に関しては想定していない様だ。 38269 前方一致するかどうかの判定を追加する事にする。 38270 38271 [検証] 38272 38273 取り敢えず動いている。候補が複数生成される場合にちゃんと展開が抑止される事も確認した。 38274 実のところ bash-completion-partial-path を読み込まない時の方が良好に動作する。 38275 というのも ble.sh がちゃんと曖昧一致であるという事を知って determine-common-prefix する為。 38276 38277 然し、普通に ble.sh なしで bcpp を動かしてみるとちゃんと 38278 共通部分の挿入まで実施してくれる。うーん。どうするのが良いのだろうか。 38279 実際に bash で mkdir -p aloha/hello/{wip/tt,world/{tech,test}} としてやってみると、 38280 echo a/h/w/t が echo aloha/hello/w になってしまう。t の情報が消える。 38281 但し、続けて TAB を押した時に限れば menu-complete に入って候補が選べる。 38282 menu-complete に入らずに別の操作をすると入力内容が失われる。 38283 38284 そういう意味で言えば ble.sh でも曖昧な候補によって 38285 入力済み文字列が消滅する事を許しても良いのかもしれない? 38286 menu-complete を既に実装しているのであるから。 38287 試しに一回消滅する事を許してみる。うーん。動く。 38288 38289 [対策2] 38290 38291 オプションで外部の枠組みで生成された先頭一致しない候補によって、 38292 入力済み文字列が失われてしまう事を許可する事にする。 38293 設定変数 complete_allow_reduction を追加した。 38294 38295 * 検索してみたら丁度2時間前に質問が superuser.com に来ていた… [#D1180] 38296 https://superuser.com/questions/1512618/autocompletion-background-colour-in-ble-sh 38297 38298 Issue を建てるのが恥ずかしかったのだろうか。取り敢えず対応して返信してしまう事にする。 38299 * done: ble-color-{set,def}face を無引数で呼び出した時に現在の設定の一覧を出力する様にした。 38300 * done: README に追記した。OK 38301 38302 2019-12-18 38303 38304 * bind -X の修正が入ったのでキーバインドの復元に bind -X を入れられる [#D1179] 38305 またユーザ設定を起動時に読み取るというのもできるのではないか。 38306 38307 →確認したところ既に復元の時に bind -X を入れる様になっていた。 38308 つまり bind -r した設定も一緒に復元されてしまう。 38309 他の bind で上書きしたのが復元されてしまうのは困るので、 38310 他の bind の復元の方を後に持ってくる様に変更する事にした。 38311 38312 ユーザ設定を起動時に読み取るのは面倒なので対応しなくて良い気がする。 38313 そもそも bind -x に限らず現状の実装では設定を読み取る事は試みていない。 38314 38315 2019-12-16 38316 38317 * edit: 現状の実装では改行と同時に更に次の文字が来ている時 [#D1178] 38318 その場でコマンドを実行せずに複数行編集に入るようになっている。 38319 然し、ssh を使っている場合やそもそも使っている機械が遅い時、 38320 簡単に複数行モードに突入してしまって使いづらい。 38321 38322 * 先ず初めにこの振る舞いをオプションにする。 38323 38324 この振る舞いは何処で判定していただろうか。 38325 ble-edit/is-single-complete-line という関数だろうか。 38326 38327 →bleopt accept_line_threshold という変数を追加した。 38328 38329 誤ってペーストしてしまった時には悲惨な事になるが仕方がない。 38330 或いは何文字以上の時には複数行編集モードに入るなど、 38331 そう言った制御をする事は一応可能である様に思う。 38332 現状で大量の入力があった場合には取りあえず読み取るだけ読み取って 38333 その後で処理するという仕組みになっている。 38334 38335 * 大量の入力があった時 (n文字以上) の時にだけ 38336 複数行編集モードに入る様にする。 38337 38338 これに対応する為には現状で大量の入力があった時に 38339 どの様に振る舞うのだったかを確認しておく必要がある。 38340 →_ble_decode_input_buffer に格納している。 38341 38342 _ble_decode_input_count は has-input 等からも参照している変数である。 38343 この変数を元にして残り文字数を判定してそれで改行を実行するかどうかを 38344 判定するというので良い気がする。 38345 →実際にやってみると動かない。どうも文字デコードまで終わった上で 38346 実際のコマンドが実行されている様だ。つまり、ble_decode_char_rest 38347 も参照すれば良い? 38348 38349 2019-11-23 38350 38351 * 2019-09-03 menu-complete: グロブパターンを含む単語をメニュー補完すると正しくない結果になる [#D1177] 38352 echo *.p として menu-complete から a.pdf を選択すると *.pa.pdf になってしまう。 38353 38354 % →と思ったがそもそも *.p に一致するファイル名が存在しない場合であり、 38355 % この場合には *.p の末尾から新しく補完が始まるのであった。 38356 % つまり a.pdf は *.p に一致するファイル名として生成されたのではなく、 38357 % *.p と関係なく完全に新しく生成された候補である。 38358 % 38359 % 問題点はその場所で生成された候補であるのにも拘らず、 38360 % *.p を含むように候補が生成されている事である。 38361 38362 分かった。*.p に一致する候補が存在しない場合 failglob になっていると、 38363 空文字列に展開されて、更にその空文字列から候補が生成されているのであった。 38364 38365 failglob になった瞬間に glob によるパターン絞り込みに変更するのが筋である。 38366 そしてそれでも一致する候補がなかった場合に限りそのままの文字列を保持する。 38367 38368 eval の箇所で何が起こっているのか調べる必要がある。 38369 →やはり failglob している。failglob すると空文字列の展開結果になって、 38370 それを元にして候補を生成してしまっている。 38371 38372 failglob の時にはそもそも候補を生成しないか、 38373 或いは続きに何か入力すれば候補が存在する様にできる、 38374 という状態を期待して word* で候補を生成する。 38375 38376 取り敢えず実装した。 38377 38378 * 共通部分の挿入を実装する可能性について。 38379 38380 x 共通部分を挿入した事によって何らかのファイル名に厳密一致してしまうと、 38381 それ以降はそのファイルしか補完できなくなってしまう。 38382 例えば a1x.pdf a2x1.pdf というファイルがあったとして、 38383 a?x で補完を実施して共通部分として a?x.pdf まで挿入してしまうと、 38384 その時点で a2x1.pdf が候補として列挙されなくなってしまう。 38385 38386 だからと言って a?x*.pdf という具合に挿入するのも面倒である。 38387 38388 x また * の部分に手動で何か入力したかったかもしれない。 38389 38390 その様に考えると勝手に共通部分を挿入するのはお節介の気がする。 38391 実装も面倒である。取り敢えずここでは対応しない事にする。 38392 後でもしこれが有用であると思われればその時に実装すれば良い。 38393 38394 2019-11-17 38395 38396 * 2019-10-02 ble.sh で ${!var_@} がエラー着色になっている [#D1176] 38397 38398 x fixed: 調べると $10 は bash では ${1}0 と解釈されるのに 38399 ${10} であるかの様に処理されていた。 38400 これについても修正を行った。 38401 38402 適当であるが修正した。${!head@ ... } の ... の部分は 38403 エラー着色する様にしてみたが対応はいい加減である。 38404 38405 2019-11-15 38406 38407 * vim-arpeggio 及び ble-bind -T wiki に追記する [#D1175] 38408 38409 2019-11-14 38410 38411 * kj 及び jk の "同時押し" による操作の要望が来た (request by divramod) [#D1174] 38412 https://github.com/akinomyoga/ble.sh/issues/31 38413 38414 単独の k, j と区別する為には timeout に対応する必要がある。 38415 これに対応する為にはどうすればよいか。 38416 38417 a ESC の受信に用いている方法は汎用的には使えない。 38418 特に ESC の timeout と他の timeout を独立に設定できない。 38419 そんなに重要な機能ではない様に思われるので、 38420 38421 b idle (bash-4.0 以降) を用いて実装するというのが良い気がする。 38422 idle を用いて実装するとして timeout の情報をどの様に記録するのか 38423 という問題が存在する。 38424 38425 調べてみると現在の実装ではそれまでに入力されたキーの 38426 列から続きがあるかないかについて判定している。 38427 つまりキーの列を登録する時に続きがあるかどうかも含めて 38428 木の情報を構築している。ここに timeout の情報を記録するには、 38429 先ず、各キー列に対する timeout を記録すると共に、 38430 キー束縛を更新する度に最長の timeout を更新するという事が必要になる。 38431 38432 或いは別の方法として各キー列に対して timeout を設定するのではなくて、 38433 各ノードに対して timeout を設定するという事にしても良いのかもしれない。 38434 例えば jk 同時押しに対応するのだとしたら "j" と "k" に対して timeout 38435 を設定しておく事にする。もし timeout が設定されていて続きがあるキーの場合には 38436 "_100:command" を登録する事にする (100 が timeout である)。 38437 もし待っているキーが存在しなくてかつ 100 待っても何も来なければこの時点で 38438 command を実行する。待っているキーがあって 100 待つ内に続きのキーが到着したら、 38439 続きのキーを処理してそれでも解決しなければ command を実行する様にすれば良い。 38440 うーん。"解決しなかった時" は続きのキーが存在しない場合として処理する必要がある? 38441 38442 つまり、以下の様な方針で実装する必要がある。 38443 * キー列の解決に失敗した時の再一致の際には timeout は無視してその場で確定する 38444 * 通常の解決の際にだけ timeout を処理する事にする 38445 38446 現状の実装で再一致はどの様に実装していただろうか。 38447 →.invoke-partial-match で特別に処理していた。 38448 timeout を導入してもこの部分の処理を変更する必要はなさそう。OK 38449 38450 とりあえず実装した。結局 idle を使って実装するのではなくて、 38451 その場で入力待ちをして実装する事にした。 38452 timeout 待ちの状態で自動補完が走ったりしても混乱の元であるから、 38453 却ってこの実装で良かったのではないかという気がする。 38454 38455 - bind, unbind, print で対応した。 38456 - dispatch 及び invoke-partial-match でも対応した。 38457 - "ble-bind -T kspecs timeout" に対応した。 38458 注意としては kspecs を先頭部分に含む別の kspecs に対して 38459 既に key bindings を設定している時にのみ使えるという事。 38460 38461 - github のページを確認して何が要求されているか改めて確認する。 38462 - ユーティリティ関数を追加しても良いという気がする。 38463 vim-arpeggio というのの説明を読んだ。 38464 vim-arpeggio では3つ以上のキーも受け付ける様である。 38465 何れにしてもユーティリティ関数を vim-arpeggio.sh という名前の拡張で提供する事にした。 38466 38467 2019-09-22 38468 38469 * edit: read, exit に --help を指定しても説明が表示されない [#D1173] 38470 対応した。 38471 38472 2019-09-04 38473 38474 * prompt: 変な文字が出力されてしまう (reported by Dave-Elec) [#D1172] 38475 https://github.com/akinomyoga/ble.sh/issues/30 38476 38477 調べてみると \[\] に対応して出力している筈の 38478 \1 \2 がそのまま出力されている気がする。うーん。 38479 ble/canvas/trace を調べてみた所、\001, \002 を処理しているが、 38480 それに伴って \001, \002 自体の出力を抑止する処理を忘れていた。直した。 38481 38482 2019-09-03 38483 38484 * 2019-08-05 [自然解消] vi: 起動した瞬間のカーソルの形状 [#D1171] 38485 調べてみるとちゃんと最初に 0 を設定している。 38486 これは完全に contra のバグだったと思って良いのだろうか? 38487 現状で tx11 を起動してみると確かに問題は解消している様な気がする。 38488 これに関しては再現したらその時に考え直す事にする。 38489 38490 2019-08-25 38491 38492 * edit: コマンド a[{1,2}]=3 を実行するとエラーになって状態がおかしくなる [#D1170] 38493 38494 $ a[1+]=2 38495 でもなる。 38496 $ eval 'a[1+]=2; echo hello' 38497 としてもなる。 38498 $ a[1+]=2; echo ] 38499 としてもなる。eval の中でも影響が残ってしまうというのは不思議だ。 38500 38501 以下の様にして試してみる。"a" とエラーメッセージしか表示されない。 38502 配列添字で算術式のエラーが生じると、 38503 eval どころか関数呼び出しの入れ子も全て無視して実行が中断する様だ。 38504 $ function f() { eval 'a[1+]=1'; } 38505 $ echo a; f; echo b 38506 38507 failglob の時には中断は eval の外までは波及しなかった。 38508 これに対する対策はどうした物だろうか。 38509 そもそも全く実行しないという手? 38510 38511 少なくとも epilogue 等の呼び出しに失敗したとしても、 38512 正しく状態が復元される様にはしたい所なのである。 38513 そもそも何故 PS1 が失われてしまうのか。 38514 調べると adjust/restore-PS1 とは独立に明示的に PS1= している箇所がある。 38515 これは adjust-PS1 経由でクリアする事にした。 38516 38517 また、途中で実行が中断されて epilogue/end が呼び出されなかった場合の為、 38518 それを検出して必要に応じてその場で epilogue/end を呼び出す様に修正する。 38519 関数呼び出しが深いので FUNCNEST があると動かなくなるが 38520 滅多に起こらない事なので気にしない事にする。 38521 38522 * prompt: bash の cd //... と PS1 \w の表示 (information by cmplstofB) [#D1169] 38523 https://github.com/akinomyoga/ble.sh/commit/2cf8cc7a2c39f1c0ceb3016a5f3ca745c27b9b5d#r34820891 38524 試したら PS1 の中の \w と \W の表示が変になるという事が分かったので修正する。 38525 38526 2019-08-17 38527 38528 * complete: cygwin で "echo //" と入力すると待たされる [#D1168] 38529 これは何だろうか…。何処かで処理が止まっているという事。 38530 bleopt complete_auto_complete= としても遅いのは変わらない。 38531 38532 色々調べると問題が起こっているのは一箇所では無い様に見える。 38533 time [[ -e //$RANDOM || -h //$RANDOM ]] とすると物凄く時間がかかる。 38534 bash --norc の上で実行しても同様に時間がかかる事から ble.sh の所為ではない。 38535 Windows の何か特殊なディレクトリでも見に行っているという事なのだろうか。 38536 38537 というか問題が起こっている箇所は一箇所ではない。 38538 少なくとももう一つ止まっている箇所がある。 38539 以下に列挙していく事にする。と思ったが一つずつ 38540 潰して行った方が効率が良いのではないか。 38541 38542 - ble/syntax:bash/simple-word/locate-filename 38543 38544 探してみると echo //* というのを実行しても待たされるという事が分かった。 38545 一般に Cygwin では // で始まるパスは駄目な様だ。 38546 更に、// は / と同一視されるのかと思いきや、そうでもない。 38547 全く触る事ができないパスになっている様な気がする。 38548 何しろ echo //* としても何も表示されないし、 38549 または ls -la // とすると Permission denied という事になる。 38550 ls -dl // とするとディレクトリという事になる様なので '//' の時だけ有効? 38551 38552 2019-08-13 38553 38554 * [棄却] char_width_mode=emacs での斜め矢印の文字幅 [#D1167] 38555 この文字である ↗ 38556 38557 ble.sh の上では幅2と計算されている。しかし、 38558 emacs 上での取り扱いは幅1であり、そして contra でも1である。 38559 自前の screen の cjkwidth emacs でも 1 であり、 38560 それから自前の Poderosa の文字幅計算でも 1 である。 38561 これは ble.sh の方を合わせるべきの気がする。 38562 38563 どうも contra のコードを調べてみると、 38564 これは絵文字と判定されている様である。 38565 一方で A ではない文字とも判定されている。 38566 38567 これは emoji_width の設定の問題なので bash 自体の問題ではない。 38568 取り敢えず emoji_width を設定せずに使う事にした。 38569 絵文字を使う為にはやはり emacs/screen/端末 などが 38570 全て対応していないと幅の計算が駄目になるのである。 38571 38572 * exec: failglob したコマンドがサブシェルにあると固まって動かなくなる [#D1166] 38573 例えば echo ? | echo で固まってしまう。 38574 よく考えたらどう対処したら良いか分からない…。 38575 →分かった…これは subshell で ble/base/unload が起こっているのが原因である。 38576 ble/base/unload で BASHPID をチェックする様にしたらあっさりと直った。 38577 他の hook に関してもチェックした方が良いのではないか。 38578 38579 2019-08-06 38580 38581 * syntax: 何とサブシェル () の直後に then 等を置いても OK らしい [#D1165] 38582 yash のサンプルを見ていて気づいた。bash でもそうだった。 38583 試すと then, fi, 等が置ける。(()) の直後は駄目の様だ。 38584 [[ ]] の直後も駄目の様子である。} の直後は大丈夫。 38585 その様に考えると } の直後と同じ文脈という事になるか。 38586 どうも完全に CTX_CMDXE の様である。CTX_CMDXE にする。 38587 38588 2019-08-03 38589 38590 * vi_test: マクロ再生に失敗している [#D1164] 38591 手動で実行してみるとちゃんと動作する様に見える。 38592 マクロ再生中にマクロ再生は再帰的に実行しない、 38593 というのが引っ掛かっているのだろうか。という気がする。 38594 38595 と思ったらそうではなかった。 38596 ちゃんと再生部分までは到達しているが記録を読み出す所で失敗している。 38597 うーん。a (97) は空である…。マクロ記録中の再帰の抑制だろうか…。 38598 38599 うーん。ちゃんとマクロ記録の設定は開始しているが、 38600 何故か一文字もマクロからの文字が ble-decode-char の 38601 該当部分を通過しない…何故だろうか。 38602 と思ったら分かった…。vi_test は ble-decode-char は介さずに、 38603 直接に ble-decode-key を呼び出しているのでキーボードマクロは使えないのだ…。 38604 38605 代わりに ble-decode-char を呼び出す様にしてみたが、 38606 そうすると今度は処理が遅延されてしまってその場で実行されない。 38607 と思って ble-decode-char の中を覗いたら ble_decode_char_sync という変数がある。 38608 これを使ったら期待通りに動く様になった。 38609 38610 * vi_nmap: C-x が効かなくなっていると思ったら、 [#D1163] 38611 C-x C-e を登録してしまった為に動かなくなっていたのだった。 38612 うーん。テストは通る様になったがそれでもやはり C-x がすぐには効かない。 38613 C-x は二個の組でしか受信できていない様子である。 38614 vi_test で実行するとちゃんと一個ずつ受信できているので、 38615 decode.sh の中で詰まっているという訳ではない様に思う。 38616 38617 何と bash-4.3 では動くけれども bash-4.4 以降では動かなくなっている。 38618 うーん。実際に出力してみると C-x に対する作戦が異なる様だ。 38619 というか emacs と vi で bind の戦略を変更しても良いのかも知れない…。 38620 面倒なので binder の中に emacs/vi の判定条件を入れる事にした。 38621 38622 (というかそもそも何故条件判定を使わずに bash version 毎に 38623 スクリプトを生成していたのだったか。恐らく初期化の速度を気にしての事だろう。 38624 実は物凄く高速なので気にしなくても良いという気もするが、 38625 何れにしても bash-5.0 では条件分岐も必要ないのでこれで良いという気がする) 38626 38627 * init-bind: "C-\ C-\" が効かなくなっている @ bash-5.0 [#D1162] 38628 そもそも受信できているのだろうか…。 38629 うーん。受信できていない…。 38630 どうも bash-5.0 から受信できなくなっている様である。 38631 うーん。前に修正した物との関連は? #D1078 これである。 38632 これの気がする。単に表示が変なだけではなく実際に振る舞いが変なのである…。 38633 取り敢えず bind "\x1c" とすれば動かない事は無いようである。 38634 38635 2019-07-30 38636 38637 * util: "bash: INT 云々" というエラーメッセージが出る [#D1161] 38638 declare | less で \<INT\> を検索して見てみると 38639 _ble_builtin_trap_handlers=([1000]="INT") という状況になっている。 38640 そしてこれは以下の部分で引き起こされているのではないかという気がする。 38641 function ble-edit/exec:exec/.eval-epilogue { 38642 trap - INT DEBUG 38643 ble/base/adjust-bash-options 38644 38645 と思ったがこれは gexec ではなくて exec なので関係ない気がする…。 38646 という事はまた何処か別の所で引き起こされている…。 38647 何れにしても恐らく古い trap 呼び出しによって変な物が登録されているのである。 38648 そしてそれは状況を見るに trap - INT DEBUG なのである。 38649 試しに実行してみる事にする。再現した…。引数の読み取りが変なんだ。 38650 38651 2019-07-27 38652 38653 * syntax: echo "${var/[a/b]/c}" これが正しく解析できていない [#D1160] 38654 echo "${var#[a}" これも駄目である。 38655 →これは物凄く単純なミスだった。修正した。 38656 38657 * syntax: echo ${var##@(((a)))} とした時の着色が変だ [#D1159] 38658 echo @(((a))) に対してはちゃんと動いている。 38659 取り敢えず対応する開始部分と同じ色に着色する様にする事にした。 38660 38661 * 2015-02-16 ${ ... } 内の文法チェック [#D1158] 38662 extglob (但し '}' で強制終了する必要がある。 38663 一旦全て読み取ってから後付けで着色する?) 38664 →これは #D1157 と一緒に対応した。 38665 38666 * 2017-11-22 syntax: ${var##...} における check-glob の対応 [#D1157] 38667 ctx-bracket-expression に関しては、 38668 新しい nctx への対応が必要になる。 38669 38670 実はこれに関しては文法の解釈には寄与しない。 38671 38672 a つまり、CTX_PATN に対しても @( は } が来たら終了する。 38673 これだと CTX_PATN についても bashc を弄る必要が出てくる。 38674 実は親が CTX_PWORD の時に '}' を追加して、 38675 check-word-end で終了する様にすれば良いだけなのではないかという考え方もある。 38676 38677 b そもそも CTX_PATN に入らずに @+?!(|) を全て着色するという手もある。 38678 しかしそれだと pattern ではない物まで着色されてしまう。 38679 それならそもそも色を付けない方が良い。 38680 38681 c 或いは CTX_PATN を複製して CTX_PWORD から呼び出した時用の新しいものを作る。 38682 と思ったが現状の CTX_PATN と比べて殆ど違いはないので a の方が良さそうに思う。 38683 38684 所で CTX_PWORD と言っても様々な文脈がある。 38685 文脈によってはパターンが無効になる場合もある。 38686 % 以下の xxx の場所では有効で yyy では無効である。 38687 % ${a//xxx/yyy} ${a#xxx} ${a%xxx} 38688 % ${a:-yyy} ${a:=yyy} ${a:+yyy} 38689 % ${a,xxx} ${a^xxx} 38690 % →試してみたが yyy だとパス名展開に使われる様だ。つまり有効である。 38691 現状では何も考えず全て CTX_PWORD にしている。 38692 そもそも文法的に許されないものも全て許可している。 38693 パターンの着色に対応する前にこの様々なパラメータ展開の着色に対応するべきである。 38694 38695 * 現状では CTX_PATN 内部でブレース展開が常に有効になっている。 38696 ${var#pattern} を解析しているとき 38697 CTX_PATN からブレース展開が呼び出されない様にする。 38698 これは CTX_PATN が "}" で終了することを許すかどうかと同じ条件判定を使えば良い。 38699 38700 2019-07-27 cmplstofB さんから報告があった。 38701 https://github.com/akinomyoga/ble.sh/issues/29 38702 成る程、構文解析を適当にやっているとこういう事になるのである。 38703 ちゃんと対応する必要がある。 38704 38705 * ${a//.../...} の形式の時は / で globpat は中断する様である。 38706 つまり、${a//[a/a]/hello} は、${a//'[a'/'a]/hello'} と解釈される。 38707 38708 38709 ? CTX_BRAX 及び CTX_PATN については入れ子等で 38710 外部の文脈をどう継承するかが複雑だった気がする。 38711 どの様になっていたのだったかを調べる。 38712 38713 →#D0622 の 7 に詳しく書かれている。 38714 特にブレース展開まで絡んできた時の振る舞いなのであった。 38715 引用すると以下の様になっている。 38716 38717 > 以下のとき、ブレース展開は無効となり通常文字列として読み取られる。 38718 > - CTX_CONDI/CTX_VRHS/CTX_RDRS からブレース展開を試みるとき 38719 > - CTX_VRHS/CTX_RDRS によって不活性化した CTX_PATN/CTX_BRAX からブレース展開を試みるとき 38720 > - CTX_CONDI の直下にある CTX_BRAX(有効) からブレース展開を試みるとき 38721 > 以下のとき、ブレース展開は不活性となりブレース展開として有効になったときエラーを設置する。 38722 > - CTX_RDRF/CTX_RDRD からブレース展開を試みるとき 38723 > - 不活性の CTX_BRACE1/CTX_BRACE2 から入れ子のブレース展開を試みるとき 38724 > その他のとき、ブレース展開は有効になる。但し、bash と違い以下の場合を含む 38725 > - CTX_BRAX によって不活性化した CTX_PATN からブレース展開を試みるとき 38726 > CTX_BRACE1/CTX_BRACE2 から CTX_PATN/CTX_BRAX に入る時は特別な処理は何も必要ない。 38727 38728 この話でいうと CTX_PWORD の時は特に "CTX_VRHS/CTX_RDRS によって不活性化した 38729 CTX_PATN/CTX_BRAX" 等と同様にブレース展開を無効にすれば良い。 38730 CTX_BRAX 及び CTX_PATN 自体の複雑さではなかったという事か。 38731 38732 然し、この入れ子を遡ってどの文脈にいるのかを判定するのが、 38733 どの様に実装されているのかは確認しておく必要がある気がする。 38734 うーん。ntype に glob_attr=* という形式の文字列を格納している様だ。 38735 そして * の部分に親の文脈値を入れている。実は此処に CTX_PWORD を入れておけば良いのでは? 38736 38737 ? うーん。現状の CTX_BRAX の動作が分からない。 38738 解析の結果を見ると "a[b(" と入力すると、 38739 "(" が現れた時点で CTX_BRAX を抜けている気がする。 38740 然し、そもそも ble/syntax:bash/check-glob に入って来ない。 38741 →もしかすると ble/syntax:bash/ctx-bracket-expression.end で抜けている? 38742 →うーん。そうだった。多分ここで抜けている。 38743 38744 取り敢えず実装する。CTX_PWORD で check-glob を実行する。 38745 38746 * done: ${var%%@(a|b[hello} の時 CTX_BRAX も CTX_PATN も同時に抜けるべき。 38747 現状の実装では実は CTX_PATN の強制終了条件は存在していない様だ…。 38748 38749 色々実装した。動いている気がする。 38750 38751 * syntax: 'a=[' と入力するとエラーメッセージが出る [#D1156] 38752 38753 というか試していたら凄いバグを見つけた。 38754 a=[ と入力しただけでエラーメッセージが出力される。 38755 これは failglob か? と思ったが failglob を外していてもメッセージは出る。 38756 先にこれを片付ける事にする。何処から発生しているのだろうか。 38757 38758 うーん。構文解析か或いは単語着色か…うーん。単語着色が怪しい気がする。 38759 →試しに update-word-table を /dev/null にして見た所メッセージが出なくなった。 38760 どうも ble/syntax:bash/simple-word/evaluate-path-spec の中で発生している。 38761 ble/syntax:bash/simple-word/evaluate-path-spec [ / noglob で再現する。 38762 ble/syntax:bash/simple-word/eval-noglob [ でまた再現した…。うーん。 38763 38764 2019-07-24 38765 38766 * edit: 何と DEBUG トラップが物凄く大量に呼び出されている気がする [#D1155] 38767 うーん。そもそも DEBUG を登録するのは SIGINT を停止する為である。 38768 それなのに DEBUG を常に trap していると処理が遅くなるのではないか。 38769 38770 実際に何回呼び出されたのか、というのを調べてみると 38771 やはり物凄い勢いで呼び出されている。 38772 すぐに数百回の呼び出しに到達してしまう。 38773 やはり動的に trap/untrap を実行する様にした方が良い気がしてきた。 38774 38775 うーん。どの様にするのが良いか。 38776 現状ではどの様に動作するか…。 38777 というかそもそも ble.sh の内部で動いている時には DEBUG trap は不要である。 38778 という事を考えればコマンドを実行する直前に DEBUG trap を有効にして、 38779 コマンドを実行した後に DEBUG trap を削除するという様にしても良い気がする。 38780 更に言うとコマンドを実行する前ですら DEBUG trap を必ず入れる必要があるかは微妙。 38781 そもそも DEBUG trap を入れるのは SIGINT を捕まえた時にそれを停止する為である。 38782 それならばその時点で DEBUG trap を仕掛ける様にすれば良いのではないだろうか。 38783 38784 * done: 先ず設計としては blehook DEBUG は取り敢えず廃止するという事。 38785 * done: 次に必要のある時にだけ builtin trap DEBUG するという事。 38786 38787 x fixed: うーん。C-c が動かなくなっている。 38788 前は確かに動いていたのだという事は確認した。何がいけないのだろうか。 38789 うーん。そもそも SIGINT を捕まえられていない気がする。 38790 然し、builtin trap を見るとちゃんと登録されているし、 38791 手で blehook/invoke INT を呼び出してもちゃんと動くと確認できる。 38792 → builtin trap -- 'blehook/invoke INT' INT を改めて実行する様にしたら動く様になった。 38793 38794 * done: 次に ble/builtin/trap DEBUG は prologue/epilogue の間でしか起こらない様にするという事。 38795 38796 x fixed: やはり漏れがある。ble-edit/exec:gexec/.* に対しては呼び出さない事にした。 38797 x fixed: 未だ変だ。と思ったら直接 builtin trap -- ... DEBUG されている? 38798 これは ble/builtin/trap/reserve を忘れていた。 38799 x fixed: コマンドの終了ステータスが0以外の時にも何故か余分に呼び出されている。 38800 しかも同じコマンドに対して2回呼び出されている。何故? 38801 38802 % echo A; false; echo C という具合にすると 38803 % false の直前で TRAPDEBUG が2回呼び出される。 38804 38805 echo A; bash -c 'echo X;false'; echo C で調べた所、 38806 直前で2回呼ばれるのではなくて、実行直前と実行直後の2回呼ばれる様子である。 38807 うーん。もしかして ERR トラップを実行する直前に 38808 DEBUG も呼び出されているという事か? 38809 38810 どの様に解決するかというと…。 38811 例えば ERR トラップを解除してそれからまた設定するという具合にする? 38812 というよりそもそも何の為に ERR を捕まえていたのだったか…。 38813 現状のコードを見ても何か特別な処理をしている様には見えない。 38814 元々のソースコードを見ると ERR は実際には使われていないのだった。 38815 38816 うーん。ERR関連は削除する事にした。 38817 ユーザが自分で ERR を設定した時には諦める事にする。 38818 というか bash の既定の振る舞いとしてそれは正しいのだろう。 38819 38820 * done: ble/builtin/trap DEBUG を prologue/epilogue の間で呼び出した時には、 38821 その場で exec:gexec/trap を実行する様にする必要がある。 38822 38823 これには ble/builtin/trap 側で set/reset 38824 関連で関数を呼び出す仕組みを追加すれば良い。 38825 38826 x fixed: 実際に実装してみた所、ble/builtin/trap の中で実行している 38827 return 0 に対しても反応してしまっている…。 38828 まあ、これは面倒なので気にしない事にしようか…。 38829 38830 a 或いは、現状の振る舞いの方が寧ろ自然とも考えられるかもしれない。 38831 何れにしても ble の関数をユーザから呼び出せば trap は発動するのである。 38832 と思ったらそんな事はなかった trap を設定した関数呼び出しより外にしか効果はないのである。 38833 b 或いはグローバルで発生した DEBUG だけを取り扱う様にすれば良いだろうか… 38834 と思ったがグローバルかどうかを検出する方法は実は存在しない。 38835 c 或いは ble/builtin/trap を明示的に跳ねる? と思ったが、 38836 これも BASH_COMMAND に ble/builtin/trap が入っている訳ではないので 38837 検出する事ができない。 38838 d trap 側で return 0 を使わない様にする? 38839 と思ったがそれだけだと不十分である。複数の trap を同時に仕掛ける場合などに 38840 続く trap を設定する段階で沢山の DEBUG を呼び出してしまう。 38841 e その様に考えると ble/builtin/trap の中にいるかどうかを 38842 表す変数を作っても良いのかもしれない。 38843 結局 _ble_builtin_trap_inside という変数を作ってそれで判定する事にした。 38844 38845 * done: DEBUG の trap は終了ステータスが意味を持つ 38846 .TRAPDEBUG の意味を反転させれば良い? 38847 →紆余曲折あったが意味は反転させた。 38848 ちゃんと 2 以外の時には単に終了ステータス失敗を返す様になっている。 38849 38850 2019-07-23 38851 38852 * main: 実は FUNCNEST 対策はそんなに難しくないのではないか [#D1154] 38853 38854 試してみる。 38855 - FUNCNEST=0 の時には制限はない。 38856 - FUNCNEST=1 の時には一回は関数を呼び出すことができる。 38857 - eval f1 や eval 'eval f1' や eval "eval 'eval f1'" の様な入れ子は幾らでもできる。 38858 - 更に初めに呼び出した関数の中で local FUNCNEST= 等としておけば 38859 その中では自由に関数を呼び出す事ができる。 38860 - 関数の中で FUNCNEST を小さな値にしたらその場で死んでしまうのか? 38861 →別に何も問題は起こらない。続きも実行されるし、 38862 関数を抜ける時にエラーになるという事もない。 38863 つまり FUNCNEST は関数に入る時にだけチェックされるのである。 38864 38865 38866 set -ex の類と同様に ble/base/adjust-bash-options と 38867 ble/base/restore-bash-options で退避・復元する事にした。 38868 問題は ble/base/adjust-bash-options を呼び出す迄に死なないかという事と、 38869 それから ble/base/restore-bash-options を呼び出した後に死なないかという事。 38870 38871 ble/base/adjust-bash-options を呼び出している箇所は以下の通り。 38872 - ble.pp ロードの初め → 最初の関数呼び出しがこれなので OK 38873 - ble/attach → これも ble/attach さえ呼び出す事ができていればOK? 38874 と思ったが微妙かも知れない…。FUNCNEST=1 だと ble/attach は呼び出せるけれども、 38875 その退避を行う為の adjust-bash-options は呼び出せないという事になる。うーん。 38876 local FUNCNEST で呼び出してから unlocal を使ってグローバルを修正する? 38877 と思ったけれども、それだと unlocal が必要かどうかの判定ができない。 38878 やはり外で FUNCNEST 退避を行うべきだろうか。 38879 38880 仕方がないので変数に実行するべきコマンドを入れて、それを eval する事にした。 38881 - edit.sh の save-last-exit 及び epilogue で呼び出されている。 38882 これに関しては save-last-exit, epilogue で FUNCNEST を調整すれば良い。 38883 38884 ble/base/restore-bash-options を呼び出している箇所は以下の通り。 38885 - ble.pp ロードの末尾。これはOK。一番最後に付け加えれば良い。 38886 - prologue の中。.setexit は直接記述する様に変更しなければならなかった。 38887 - ble-edit/bind/.check-detach の中。 38888 check-detach で return 0 すればもう関数は呼び出さない? 38889 check-detach は exec:gexec/.end からしか呼ばれていなくて、 38890 この .end の中では check-detach が 0 を返したらすぐ終了する様になっている。 38891 また gexec/.end はトップレベルで呼び出される事になっているので、 38892 改めて関数が呼び出されるという事もない。OK 38893 38894 多分。これで大丈夫。これで動かなかったらそもそも set -e で死んでいる筈。 38895 取り敢えず死ぬという事はないけれども実は FUNCNEST が消去されてしまっている。 38896 38897 うーん。どうやらコマンド実行中に trap 経由で実行される物は FUNCNEST が退避できていない。 38898 - blehook/invoke では local FUNCNEST= してしまう事にする。 38899 38900 * main: set -e の設定が消滅している気がする [#D1153] 38901 % と思ったが…。うーん。もしかすると意図的に対応を諦めた? 38902 % そんな気もする。しかし #D0930 では特に議論されていない様にも思う。 38903 % それに ble/base/restore-bash-options では明示的に復元を試みている。 38904 うーん set -e にすると何も起こっていないのではなくて、 38905 その場ですぐに抜けてしまっていてそれに気づいていなかったという事らしい。 38906 然し、エラーを発生させていないのに終了してしまうというのは怖い。 38907 何があったのだろうか…。あー。分かった気がする…。直した。 38908 38909 また set -x にすると trap/invoke DEBUG が物凄く沢山のメッセージを出してしまう。 38910 これに関しても対策を施した。 38911 38912 * blehook: trap を置き換える? [#D1152] 38913 その為には trap の仕様を確認しなければならない。 38914 38915 * done: blehook で引数を渡すのは関数名またはコマンド名を指定した時だけにする事にした。 38916 38917 * 取り敢えず実装した。少し動かしてみたがちゃんと動いている気がする。置き換えても良い気がする。 38918 38919 * ERR が無駄に沢山呼ばれる。setexit で呼ばれている気がする…。 38920 ERR に対しても介入するべきではあるまいか。 38921 38922 * bind: コマンドを実行した後はプロンプトを再計算するべきなのではないか [#D1151] 38923 特に C-z を fg に割り当てているが、これによって出入りしてプログラムが終了した後には 38924 やはりプロンプトを再計算したいという気がするのである。 38925 特に、何も実行しないコマンドであっても次の行に表示上移動するのだから。 38926 38927 現在の実装では ble-edit/prompt/update で 38928 local version=$COLUMNS:$_ble_edit_LINENO を見てプロンプトの再計算が必要かどうか判定している。 38929 LINENO だけではなくて ble/widget/execute-command でも何かカウントするべきなのでは。 38930 ble/widget/.insert-newline で _ble_edit_lineno++ する事にした。 38931 ble/widget/.newline は _ble_edit_lineno++ _ble_edit_LINENO++ の両方を実行する。 38932 ble/widget/.insert-newline は片方だけ実行するという事にした。 38933 _ble_edit_LINENO が変化する箇所は他にはないので _ble_edit_LINENO 38934 の代わりに _ble_edit_lineno を prompt の version 判定に用いて問題ないだろう。 38935 38936 * highlight: 入力した URL の最初の // だけが着色されるのは変な感じがする [#D1150] 38937 http:// の形式をしている時には : 区切りにするのをやめるべきなのではあるまいか。 38938 →URLの形式の単語を着色する所まで実装した。 38939 38940 2019-07-22 38941 38942 * bash 2 でロードしてみた所 ble.sh がロードされないのは良いが、 [#D1149] 38943 何のメッセージも表示されない。と思ったら set -x 対策として 38944 標準出力・エラー出力を封じているのだった。 38945 ble.sh からのエラーメッセージだけは表示する様に修正する。 38946 38947 他に builtin コマンド (非標準) を使っている所を使わない様に修正した。 38948 38949 2019-07-21 38950 38951 * 以下の設定に関してはもう ble.sh 側で勝手に弄っても良いのではないか? [#D1148] 38952 どうせ bashrc の一番始めに書いてもらう事になっている。 38953 38954 ((_ble_bash>=40100)) && builtin bind 'set skip-completed-text on' 38955 ((_ble_bash>=40300)) && builtin bind 'set colored-stats on' 38956 ((_ble_bash>=40400)) && builtin bind 'set colored-completion-prefix on' 38957 38958 * Cygwin console のバグについて [#D1147] 38959 38960 - Cygwin は ED(2) "ESC [ 2 J" が駄目 38961 - Cygwin は RI の振る舞いがおかしい 38962 - Cygwin は最終行での DL "ESC [ M" が駄目 38963 - Cygwin は CUF() の行き先が行末 $ の時に何処にも移動しない。 38964 38965 これは最新の cygwin を確認したら全て直っていた。 38966 但し、TERM=xterm-256color になっているので区別はできる。 38967 また最新版でも ED(2) はカーソル位置を変える、等の振る舞いの違いはある。 38968 何れにしてもこれは別の場所で扱う事にする。 38969 38970 * blehook: blehook に hook 名を指定しても無視される [#D1146] 38971 これは単純なミスだった。修正した 38972 38973 * blehook: 初期化の順序によって load hook が実行されない事がある [#D1145] 38974 38975 % cygwin で M-b 等が全部 ESC b と解釈されている 38976 Cygwin は関係なかった。 38977 38978 [状況整理] 38979 38980 | 0.4.0-devel1+30cc31c の既存のセッションでは再現していない 38981 | 0.4.0-devel1+362ab05 の既存のセッションでは再現している。 38982 | 最新の version でも再現している。 38983 | 確かに checkout して比較してみるとそれぞれその通りになった。 38984 | 二分法で絞り込む。2ea7cfd は未だ大丈夫である。 38985 | caa46c2 はもう駄目になっている。af758e5 も駄目。 38986 | af758e5~ だと大丈夫である。という事は犯人は af758e5 である。 38987 | .inputrc の読み取りタイミングの変更で駄目になった。 38988 | 38989 | 特に bind で ESC から始まる何かを登録するともう駄目なのだろう。 38990 | と思ったがそれを削除しても問題は再現するままである。 38991 | --noinputrc を指定したら再現しなくなった。 38992 | 38993 | うーん。ble-bind -m vi_imap -P の結果を見比べた所、 38994 | そもそも inputrc で ESC で始まる物が登録されていた場合、 38995 | hook が呼び出されていない? という事の様だ。うーん。 38996 | つまり inputrc の中で vi_imap がロードされて、 38997 | その後で blerc などの設定が適用されている? 38998 | 38999 | というのも変だ。そもそも mshex による設定も消えてなくなっている。 39000 | という事を思えばまた別の理由によって load hook 39001 | が呼び出されなくなっているという事か。 39002 | 39003 | 実際に試してみるとやはり load hook が起動された瞬間には未だ 39004 | 登録されていない様である。 39005 | うーん。そもそも mshex の load hook も定義されていない。 39006 | どのタイミングで load hook が呼び出されているのだろう…。 39007 39008 しなければならない事は (1) 現状で何が起きているかの解明と、 39009 (2) load_hook に関しては既にロード済みであればすぐに実行する、 39010 という仕組みを整えるという事。 39011 39012 調べてみるといきなり keymap_load が実行されている様子だ。 39013 どうも blerc の中で keymap_load, keymap_vI_load が実行されている。 39014 確かに blerc の中で bind を呼び出しているのでそうなるのは分かる。 39015 以前同じ事が起こっていなかったのは bind 呼び出し時に keymap 初期化をする 39016 というのを最近追加したからである。 39017 39018 [対処] 39019 39020 どの様に対処するのかという事。 39021 39022 * 少なくとも load hook に関しては既に load 済みであれば 39023 その場で実行する事にする。 39024 39025 * ok: どの様な関数名にするのが良いだろうか。これは emacs を参考にする。 39026 そういう関数名があった筈と思ったが思い出せない。 39027 →探したら mwg-doxygen.el で使われていた eval-after-load である。 39028 39029 ble/util/eval-after-load という関数名にでもするか。 39030 或いは blehook/eval-after-load の方が良いだろうか。 39031 取り敢えず後者で定義する事にしようかと考える。 39032 39033 * done: そして blehook/eval-after-load を実行する為には 39034 それが既に実行されたかどうかという情報を記録しておく必要がある。 39035 39036 a それ専用の変数を定義しておくか。 39037 変数名をどうするのかという事と変数の汚染が気になってしまう。 39038 b 或いは辞書にするか。 39039 辞書にすると bash-4.0 未満に対する対応を別に実装しなければならないので面倒である。 39040 c 或いは変数の代わりに関数を定義するか。 39041 うーん。関数を定義する方法だと reload の時に関数を削除するのが面倒である。 39042 然し変数で記録したとしてもそれを消去する必要性を考えたら面倒である事は変わりない気はする。 39043 39044 取り敢えず変数に記録する事にする。OK 39045 39046 * done: 変数名を変更する事にした。変更した。 39047 取り敢えず blehook_h_NAME に handlers を格納し、 39048 blehook_c_NAME にこれまでの呼び出し回数を格納する事にした。 39049 39050 * done: というか今思ったのだが blehook に関して、 39051 blehook_* という変数名にしておく必要はあるのだろうか。。 39052 39053 bleopt の場合には source する前に何か値を予め設定しておきたい可能性もあった。 39054 然し、blehook の場合には結局 def.sh で =() として初期化してしまうのだという事を考えると、 39055 公開変数にしておく意味がない。或いは、既存の hook を保持する事にするか? 39056 然し、blehook は上書きではなくて累積なので既存の hook を残しておくと、 39057 だとすれば ble-reload の時にどんどんと hook が累積して行く事になり駄目。 39058 39059 従って、これに関しては blehook は _ble_hook_ 的な変数名に改名するのが賢明だろう。 39060 そうは言いつつもそんなに影響は広範には亘らないので変更は少なくて済みそうである。 39061 今慌てて修正しなくても後でゆっくり名前を変えれば良いという事の気がする。 39062 39063 結局変数の使い方を変えたので一緒に名前も変更する事にした。 39064 39065 * 同時に _ble_version という変数も用意する事にした。 39066 単一の変数で大小比較をできる様にしたスカラー値。 39067 39068 これで枠組みを変更してしまったので既存の枠組みを使っている 39069 人に対する警告の様な物を表示するべきなのではないだろうか。 39070 然し、そのチェックは何処で実行するのか。 39071 idle で実行すれば良い気がする。 39072 idle が実行されるのは keymap 関係はロードし終わった時の筈だから。 39073 と思ったが単に blerc を読み込んだ後で実行すれば良い気がする。 39074 bashrc の中で設定している人に関しては関知しない事にする。 39075 39076 2019-07-20 39077 39078 * cygwin: 未だ cygwin での振る舞いが変である [#D1144] 39079 行末補正が効いていない。というか塗りつぶされてしまう。 39080 _ble_term_xenl=1 にしてみると余分な改行が入ってしまう。 39081 39082 取り敢えず調査を継続する事にする。 39083 そもそも行末補正の為に何を出力しているのだったかを確認する。 39084 39085 先ず eol mark を出力して restore cursor する。 39086 実は eol mark は関係無さそう。 39087 その後で行頭から CUF で COLUMNS-3 文字進む。 39088 更に二文字挿入してから CR で行頭に戻る。という事をしている。 39089 うーん。実際にその様に制御シーケンスを出力させるとちゃんと動いている。 39090 分かった事は printf A だと行末補正が効くが printf AAA だと効かないという事。 39091 もっと調べると丁度 3 文字の時にだけ変な事が起こる…。 39092 39093 →printf で再現できた。 39094 $ printf 'AA\e[154C12\rX\n' 39095 $ printf 'AAA\e[154C12\rX\n' # 駄目 39096 $ printf 'AAAA\e[154C12\rX\n' 39097 39098 $ printf 'AAA\e[154CX\r\nhello\n' 39099 うーん。分かった。丁度 $((COLUMNS+1)) 列目に移動しようとすると 39100 "動かない" という動作になっている…。 39101 この場合どの様に対処したら良いのだろうか…。 39102 39103 二つの対処が在る。先ず Cygwin の側での何故その様になっているのかの解明と、解決。 39104 それから ble.sh の側での対策である。Cygwin の側は後で考える事にして、 39105 ble.sh の側でどの様にして対策するのかという事。 39106 a うーん。一つの方法は現在位置を問い合わせてそれに応じて出力するかどうかを決定するという物。 39107 正直この方法は採用したくない。ユーザによる入力と前後してしまうからである。 39108 39109 丁度ぴったり移動する場合でもちゃんと前に移動する方法はあるのだろうか。 39110 39111 b 例えば一文字ずつ前に進む? うーん。酷いやり方だが他に方法がないのであれば仕方がない。 39112 これが現実的な解という事になってしまう。例えば 157 列あるのだとすれば、 39113 157 x 3 (\e[C) = 471 bytes 出力する事になる。 39114 39115 - 移動に使える別のシーケンスは存在するだろうか。 39116 39117 c 或いは b の方針で一文字ずつではなくて2文字4文字等と組み合わせて何とかならないか…。 39118 然し現在位置に対して何の仮定も置けないのだとすると、 39119 2文字以上を実行する時は常に失敗の危険性がある…。 39120 と思ったが現在位置が問題の位置より左にあれば大丈夫だし、 39121 問題の位置より右にあれば其処で失敗しても後の CUF で十分に末端に到達できる。 39122 とにかく目的は末端に到達する事なのである。末端に到達できさえすれば良い。 39123 39124 兎に角目標は"少なくとも N 文字前進する"という事である。 39125 取り敢えず N = N/2 + (N-N/2) に分けて、 39126 取り敢えずN/2進めれば残りは "(N-N/2)文字前進する" という同様の問題に帰着できる。 39127 一気に N/2 文字進む事ができれば余り沢山の文字列を出力しなくても済む。 39128 39129 今、残り前進可能数が R とする。またN>1であると仮定する。RとNの大小関係は分からない。 39130 39131 a a=N/2進むとすると、 39132 丁度 a==R+1 の時に問題になってしまう。 39133 この時 R = N/2-1 であるから、R < N/2 <= N-N/2 なので 39134 後半の "N-N/2前進する" というステップに於いて、 39135 十分に行末まで達する事が可能である。 39136 39137 b 代わりに N-N/2 + N/2 に分ける場合はどうだろうか。 39138 つまり取り敢えず a=N-N/2 だけ進む。 39139 N-N/2==R+1 の時に問題が発生してこの時 R = N-N/2-1 である。 39140 Nが奇数の時 R = N-N/2-1 = N/2 である。 39141 Nが偶数の時 R = N/2-1 である。従って、 R <= N/2 である。 39142 なのでこの様にしても十分に行末まで達する事ができる。 39143 こちらの方が効率が良さそうである。 39144 39145 つまり、N文字前進したい時、取り敢えず ceil(N/2) だけ進んで 39146 floor(N/2)前進したいという問題に帰着できる。 39147 半々になるので log の長さの文字列で大丈夫になる。 39148 39149 ? ここで気になるのが何故 margin を " " と二文字にしているのかという事。 39150 これは何らかの理由でその様にしたのだったか。blame してみる。 39151 39152 $ g blame src/edit.sh 39153 5084b02a ble-edit.sh (Koichi Murase 2018-08-31 13:40:32 +0900 3846) ble/canvas/put.draw " $_ble_term_cr$_ble_term_el" 39154 $ g blame 5084b02a~ -- ble-edit.sh 39155 650b3f14 (Koichi Murase 2015-03-04 01:17:38 +0900 2984) ble-edit/draw/put " $_ble_term_cr$_ble_term_el" 39156 $ g blame 650b3f14~ -- ble-edit.sh 39157 ^c68412b (Koichi Murase 2015-02-09 03:13:19 +0900 2100) echo -n "$_ble_term_sc${eof}$_ble_term_rc((xenl?cols-2:cols-3))C ^M" 39158 これが initial commit である。つまり一番初めから空白二文字でやっていた。git では追跡できない。 39159 39160 #D0004 を読んだらちゃんと説明が書かれていた。これは xenl の時に 39161 "(1)行末に移動する(2)次の行に移動する"という具合に2文字必要だからなのであった。 39162 39163 つまり xenl でない時には気にしなくても良いという事である。 39164 特に Cygwin 専用のコードを書く上では考えなくて良いという事である。 39165 39166 * cygwin terminal で久しぶりに動かしてみたら様子がおかしい [#D1143] 39167 一番下の行で -- INSERT -- が残った儘になってしまうし、 39168 vbell が表示される度に描画位置がどんどんずれていく。 39169 うーん。全然駄目だ。実は 0.1 の時からずっと動いていなかったらしい。 39170 39171 試してみて分かった事は、cygwin terminal では、 39172 1. RI 及び IND は必ず其処に行を挿入してしまうという事 39173 本来は画面の一番上にいる時にのみ行を挿入するべきなのである。 39174 2. DL で現在行以降の行数以上を引数に指定すると何も起こらないという事。 39175 3. 更に \e[$((LINES+1))H すると画面の 39176 一番下に行って IND したのと同じ効果がある…。 39177 39178 さて対策或いは代替手段はあるだろうか。 39179 効率の悪い方法だったとしても TERM=cygwin の時にだけそれをすれば良い。 39180 39181 [Cygwin の振る舞いについて調査] 39182 39183 | というか cygwin に patch を送りたい気分ではある。 39184 | cygwin のソースコードを確認してみる。 39185 | 以前 cygwin の release note で DECSCUSR の事が書いてあった事を思い出して 39186 | newlib-cygwin/winsup/cygwin の中で grc DECSCUSR したら直ぐに見つかった。 39187 | 39188 | $ grc DECSC 39189 | ./fhandler_console.cc:1980: case 'q': /* Set cursor style (DECSCUSR) */ 39190 | ./fhandler_console.cc:2642: else if (*src == '7') /* DECSC Save cursor position */ 39191 | 39192 | というか cygwin をビルドし直した所でそれをテストするのは面倒である。 39193 | うーん。或いは bash を同じディレクトリに入れてダブルクリックすれば良いだけか? 39194 | 39195 | * IL,DLのコードは以下の通り。 39196 | 39197 | | case 'L': /* AL - insert blank lines */ 39198 | | n = con.args[0] ?: 1; 39199 | | cursor_get (&x, &y); 39200 | | scroll_buffer (0, y, -1, -1, 0, y + n); 39201 | | break; 39202 | | case 'M': /* DL - delete lines */ 39203 | | n = con.args[0] ?: 1; 39204 | | cursor_get (&x, &y); 39205 | | scroll_buffer (0, y + n, -1, -1, 0, y); 39206 | | break; 39207 | 39208 | 而もILをALとtypoしている? 然し ICH を IC 39209 | と書いていたりもするから何か古い略号なのかもしれない。 39210 | 肝心の部分は恐らく 0..y+n を y だけ scroll するという意味? 39211 | 本来は y..$ を n 行スクロールするべきの気がする。 39212 | 39213 | 振る舞いを見るとどうも y+n が範囲外の時には何も起こらないという事の様だ。 39214 | でもよく分からない。scroll_buffer の実装を観察しようか。 39215 | 39216 | | void __reg3 39217 | | dev_console::scroll_buffer (HANDLE h, int x1, int y1, int x2, int y2, 39218 | | int xn, int yn) 39219 | | { 39220 | | /* Scroll the screen context. 39221 | | x1, y1 - ul corner 39222 | | x2, y2 - dr corner 39223 | | xn, yn - new ul corner 39224 | | Negative values represents current screen dimensions 39225 | | */ 39226 | | SMALL_RECT sr1, sr2; 39227 | | CHAR_INFO fill; 39228 | | COORD dest; 39229 | | fill.Char.UnicodeChar = L' '; 39230 | | fill.Attributes = current_win32_attr; 39231 | | 39232 | | fillin (h); 39233 | | sr1.Left = x1 >= 0 ? x1 : dwWinSize.X - 1; 39234 | | sr1.Top = y1 >= 0 ? y1 : b.srWindow.Bottom; 39235 | | sr1.Right = x2 >= 0 ? x2 : dwWinSize.X - 1; 39236 | | sr1.Bottom = y2 >= 0 ? y2 : b.srWindow.Bottom; 39237 | | sr2.Top = b.srWindow.Top + scroll_region.Top; 39238 | | sr2.Left = 0; 39239 | | sr2.Bottom = (scroll_region.Bottom < 0) ? 39240 | | b.srWindow.Bottom : b.srWindow.Top + scroll_region.Bottom; 39241 | | sr2.Right = dwWinSize.X - 1; 39242 | | if (sr1.Bottom > sr2.Bottom && sr1.Top <= sr2.Bottom) 39243 | | sr1.Bottom = sr2.Bottom; 39244 | | dest.X = xn >= 0 ? xn : dwWinSize.X - 1; 39245 | | dest.Y = yn >= 0 ? yn : b.srWindow.Bottom; 39246 | | ScrollConsoleScreenBufferW (h, &sr1, &sr2, dest, &fill); 39247 | | } 39248 | | 39249 | | inline void 39250 | | fhandler_console::scroll_buffer (int x1, int y1, int x2, int y2, 39251 | | int xn, int yn) 39252 | | { 39253 | | con.scroll_buffer (get_output_handle (), x1, y1, x2, y2, xn, yn); 39254 | | } 39255 | | 39256 | | inline void 39257 | | fhandler_console::scroll_buffer_screen (int x1, int y1, int x2, int y2, 39258 | | int xn, int yn) 39259 | | { 39260 | | if (y1 >= 0) 39261 | | y1 += con.b.srWindow.Top; 39262 | | if (y2 >= 0) 39263 | | y2 += con.b.srWindow.Top; 39264 | | if (yn >= 0) 39265 | | yn += con.b.srWindow.Top; 39266 | | con.scroll_buffer (get_output_handle (), x1, y1, x2, y2, xn, yn); 39267 | | } 39268 | 39269 | コメントを読んで引数の意味が分かった。 39270 | 結局矩形 (0,y+n)-($,$) に関して、左上を (0,y) に持って行きなさい、 39271 | とそういう指定の仕方をしているのである。 39272 | そして基本的にはそれを ScrollConsoleScreenBufferW に渡している。 39273 | 実はこれは Win API である。 39274 | https://docs.microsoft.com/en-us/windows/console/scrollconsolescreenbuffer 39275 | これは BitBlt 的なそういう感じの API なのである。 39276 | 従って、もし移動する元の rectangle が潰れていると何も起きないという事だろうか。 39277 | 39278 | うーん。これを直すとすると、移動する矩形が潰れる時には代わりに消去を行うという事。 39279 | もしくは、スクロールした後の部分を明示的に空白で埋めるという事。 39280 | 余り綺麗な方法ではない。単に cygwin にバグ報告するだけに留めて置くか。 39281 | 39282 | * RI の方に関しては… 39283 | 39284 | 何と単純に "scroll down" として実装されている…。 39285 | 39286 | | else if (*src == 'M') /* Reverse Index (scroll down) */ 39287 | | { 39288 | | con.fillin (get_output_handle ()); 39289 | | scroll_buffer_screen (0, 0, -1, -1, 0, 1); 39290 | | con.state = normal; 39291 | | } 39292 39293 まとめると。Cygwin はスクロールには Win API を使っていて、 39294 スクロール対象が潰れてしまう時は DL が効かない。 39295 また RI に関しては完全に1行スクロールとして実装されてしまっている。 39296 39297 Cygwin のこの様な変な振る舞いを逆に利用して何かいい感じに処理できないだろうか。 39298 \e[H で範囲外に移動できてしまうという事を思えば実は \e[A でも範囲外に移動できるのでは? 39299 と思ったらそうだった…。RI に関してはそれで何とかする事にする…。 39300 但し、本当に一番始めに起動した時には \e[A で上に行く事ができない。RI なら上に行く事ができる。 39301 仕方がないので、\e[A に補正する時に RI で上に行を挿入してしまう事にした。 39302 39303 39304 [Cygwin の識別に関して] 39305 39306 | 一応 Cygwin terminal の DA2R を見ておく事にする。 39307 | 67;201102;0 であった。うーん。これは version によって変わったりするのだろうか。 39308 | Google で検索してみる。どれだけ安定しているのか。と思ったら検索すると一件として当たらない…。 39309 | Cygwin DA2 で検索しても有用な情報は出てこない。というか直接ソースコードを見れば良いのか? 39310 | 以下の行が当たった。 39311 | 39312 | ./fhandler_console.cc:2204: __small_sprintf (buf, "\033[>67;%d%02d;0c", 39313 | 39314 | 実際にソースコードを当たってみると… 39315 | うーん。そもそも 67 は Cygwin 固有の様である。 39316 | というか contra で採用した 67 と被っている気がする。。 39317 | まあそれは後で考える事にする。 39318 | 39319 | /* Generate Secondary Device Attribute report, using 67 = ASCII 'C' 39320 | to indicate Cygwin (convention used by Rxvt, Urxvt, Screen, Mintty), 39321 | and cygwin version for terminal version. */ 39322 | __small_sprintf (buf, "\033[>67;%d%02d;0c", 39323 | CYGWIN_VERSION_DLL_MAJOR, CYGWIN_VERSION_DLL_MINOR); 39324 | 39325 | マクロの値を確認すると…。 39326 | 39327 | ./include/cygwin/version.h:13:#define CYGWIN_VERSION_DLL_MAJOR 3001 39328 | ./include/cygwin/version.h:14:#define CYGWIN_VERSION_DLL_MINOR 0 39329 | 39330 | ぜんぜん違う値である気がする。blame で追跡してみる。 39331 | 39332 | $ g blame -L 2200,2300 fhandler_console.cc 39333 | ... 39334 | 8fd4bd2bf1 (Corinna Vinschen 2009-12-19 15:37:10 +0000 2203) and cygwin version for terminal version. */ 39335 | 8382778cdb (Takashi Yano 2019-04-01 00:47:47 +0900 2204) __small_sprintf (buf, "\033[>67;%d%02d;0c", 39336 | 8382778cdb (Takashi Yano 2019-04-01 00:47:47 +0900 2205) CYGWIN_VERSION_DLL_MAJOR, CYGWIN_VERSION_DLL_MINOR); 39337 | 8fd4bd2bf1 (Corinna Vinschen 2009-12-19 15:37:10 +0000 2206) else 39338 | ... 39339 | 39340 | 何と最近書き換わっている…。しかも日本人…。 39341 | http://cygwin.1069669.n5.nabble.com/PATCH-Reworks-for-console-code-td145437.html#a145459 39342 | ここに記録が残っている。巨大な変更と一緒にしれっと DA2 を書き換えている。 39343 | 何れにしても 24bit color が cygwin で使える様になったのだろうか…。 39344 | 39345 | と思ったがただ単に改行が追加されただけの様である。 39346 | というか体裁を勝手に変更するというので追跡をしにくくするのはやめて欲しい。 39347 | 而も別の変更に紛れ込ませてそれを実行するというのが行儀が悪い。やばい。 39348 | 何れにしても、その前の変更は 2009 年なので大分昔である。 39349 | 39350 | $ g blame -L 1600,2300 8382778cdb~ -- fhandler_console.cc 39351 | ... 39352 | b86f999af1 (Christopher Faylor 2011-06-06 05:02:13 +0000 2078) /* Generate Secondary Device Attribute report, using 67 = ASCII 'C' 39353 | b86f999af1 (Christopher Faylor 2011-06-06 05:02:13 +0000 2079) to indicate Cygwin (convention used by Rxvt, Urxvt, Screen, Mintty), 39354 | 8fd4bd2bf1 (Corinna Vinschen 2009-12-19 15:37:10 +0000 2080) and cygwin version for terminal version. */ 39355 | 8fd4bd2bf1 (Corinna Vinschen 2009-12-19 15:37:10 +0000 2081) __small_sprintf (buf, "\033[>67;%d%02d;0c", CYGWIN_VERSION_DLL_MAJOR, CYGWIN_VERSION_DLL_MINOR); 39356 | 8fd4bd2bf1 (Corinna Vinschen 2009-12-19 15:37:10 +0000 2082) else 39357 39358 [実装] 39359 39360 結局 DA2R が ^67;[0-9]{3,};0$ の形であれば良さそうなのである。 39361 というかこれは何処で判定すれば良いのだろうか…。 39362 39363 DL に関してはどの様にしようか。 39364 使用箇所を確認すると ble/canvas/put-dl.draw からしか使っていない。 39365 そして ble/canvas/put-dl.draw は複数の箇所から使われている。 39366 うーん。ble/canvas/put-dl.draw のレベルで何か修正はできるだろうか。 39367 つまり正しい DL の振る舞いをそれ単体で模倣する事ができるか、という事。 39368 39369 うーん。DLする前にDLされる予定の行を消去しておけば良いのでは。。 39370 つまり EL を実行してしまえば良いのである。と思ったが EL は行数指定による消去ではない。 39371 つまり、各行に移動して EL を実行しなければならないので面倒である。 39372 範囲を消去する制御機能は他にあったろうか。他には CSI J (ED) ぐらいしかない。 39373 然し、これは全消去的になってしまうので駄目。 39374 39375 各行に移動するとしても cygwin の \e[B 等の移動は勝手にスクロールを引き起こしてしまう。 39376 と思ったが却って都合が良いのかもしれない。 39377 同じ回数 \e[A を呼び出せばちゃんと戻ってくるという事だから。 39378 39379 2019-07-18 39380 39381 * blehook: zsh の add-zsh-hook で提供している物を提供できるのではないか [#D1142] 39382 https://qiita.com/mollifier/items/558712f1a93ee07e22e2 39383 39384 zsh の chpwd について試してみたが cd を実行する度に実行される様だ。 39385 つまりコマンド実行中にN回ディレクトリを移動すればN回実行される。 39386 正直便利なのかよく分からない。中で cd して処理をしてまた元のディレクトリに戻る、 39387 という様なシェル関数を書いたりすると、例えば chpwd に ls を仕掛けていたりすると 39388 何度も ls が表示されて悲しい事になってしまうのではないか。 39389 39390 それよりはまたプロンプトに戻ってきた時に chpwd が呼び出される方が便利である。 39391 他に addhistory 及び periodic が存在する。後者は存在意義が不明。 39392 39393 * done: trap_exit は exit に改名して良い気がする。対応した。 39394 39395 * done: ユーザ向けと内部向けの hook が混ざって分かりにくいので 39396 ユーザ向けの hook は大文字で提供する事にした。 39397 39398 * done: zshaddhistory は履歴に追加するかしないかを終了ステータスで指定するらしい。 39399 →対応した。と思ったが思うように動いていない。と思ったら 39400 blehook/invoke するのを大文字にするのを忘れていた。 39401 39402 * ok: periodic については対応しない事にした。 39403 対応したければ各自で時刻を記録すれば良い。 39404 39405 * 2019-07-09 global: 148 と 147 の区別をしたい [#D1141] 39406 現在の実装では広範に亘って 148 が用いられているが、 39407 実は 148 は二種類あって has-input の時と、 39408 或いは唯単にユーザの入力を待つ状態というのがある。 39409 更に 148 の中でも実際に read で読み取れる状態と、 39410 或いは ble.sh の枠組みの中に未処理のデータが残っている場合がある。 39411 39412 % というか async で呼び出すのは idle.do の中からだけなので、 39413 % 実は ble-decode/has-input ではなくて ble/util/is-stdin-ready を使うべきでは。 39414 % と思って ble/util/idle を調べてみると ble/util/idle/IS_IDLE を使っている。 39415 % ble/util/idle/IS_IDLE は decode.sh で上書きされていて、 39416 % 其処の説明によると decode 途中の状態の場合にはすぐに続きのバイトが来るはず、 39417 % という論理になっている様だ。うーん。何だか分からないが取り敢えず 39418 % ble/util/idle/IS_IDLE を使っておくのが綺麗の様に思う。 39419 39420 取り敢えず、idle 処理の中でどのようにするかというと。 39421 ble/util/idle/IS_IDLE じゃなくなったら return 148 するという事。 39422 それ以外の理由で一旦処理を停止するという時には return 147 するという事。 39423 39424 また ble/util/idle/IS_IDLE は decode に於いて 39425 has-input で上書きされているがこれが妥当なのかについても考察の必要がある。 39426 そもそも ble/util/idle.do が呼び出された時点で中途半端な状態で 39427 入力がずっと来ないという事はないのではないかと思われるのである。 39428 これは ble/util/idle.do の呼び出し箇所を一つ一つ確認していく必要がある。 39429 39430 [変更に関して] 39431 39432 - decode.sh では実は 148 か 147 かというのはチェックしていない。 39433 - vi.sh における 148 は全てユーザーの次の入力を待つ為の物だから 39434 実は全て 147 である。 39435 - 逆に complete.sh における 148 は全て中断の為の物だからそのままで良さそう。 39436 ble/complete/menu#start に関してだけは 147 の様な気がする。 39437 但し現状ではこの関数は誰も使っていない。 39438 ble/complete/sabbrev/expand も 147 である。 39439 - history.sh の中は全て 148 である。 39440 - vim-surround.sh は全部 147 39441 - edit.sh は検索関連は 148 で他は 147 だった。 39442 - util.sh は idle/fiberchain は 148 で、CPR request は 147 である。 39443 39444 * highlight: / で区切られた関数名の着色 [#D1140] 39445 / より前の部分をディレクトリ名と解釈しようとして、 39446 然しディレクトリが存在しないので黒色になってしまう。 39447 これは簡単な修正だった。 39448 39449 * history 移行: blehook の枠組みを整える? [#D1139] 39450 bleopt と同様に。既存の hook に関しては変数名を変更する等して移行する。 39451 _ble_decode_char_hook 等に関しては揮発性の hook で少し性質が異なるので関係ない。 39452 39453 取り敢えず雑多の hook を統一的に扱える様にした。 39454 39455 * blehook の引数の指定の仕方は将来の事を考えると 39456 bleopt や ble-sabbrev と同じ様にした方が良いのでは。 39457 変更する事にした。対応した。 39458 39459 * highlight: declare の引数でブレース展開が着色されていない [#D1138] 39460 解析の途中状態を確認してみると ARGVR になっている。 39461 39462 * どうもこれは check-brace-expansion の実装が悪い気がする。 39463 inactive になる条件として文脈値が以下の何れかという事になっているが。 39464 39465 CTX_CONDI CTX_CONDQ CTX_RDRS CTX_VRHS 39466 CTX_ARGVR CTX_ARGER CTX_VALR 39467 39468 今試してみると declare a={a,b,c} でも a=([0]={a,b,c}) でも 39469 ブレース展開は実施される様だ。更に eval a={x,y,z} でもブレース展開が実施される。 39470 興味深い事に a=([0]={a,b,c}) でブレース展開が実施されると要素 0 に対する代入ではなくて、 39471 '[0]=a' '[0]=b' '[0]=c' という三つの要素を持った配列が初期化される。 39472 因みに a=([0]=a [0]=b [0]=c) とやるとちゃんと要素 0 に対する代入になっている。 39473 a=([{0..10}]=c) とするとちゃんと 11 個の要素の全てに c を代入するという意味になる。 39474 値の側でブレース展開を実行した時にだけ変な事になるのだ。 39475 39476 取り敢えず上記の文脈値の内の最後の三つに関してはブレース展開無効化を解除する。 39477 39478 * もう一つの疑問は declare -p ble_{a,b,c}_ とすると、 39479 = も来ていないのに何故か { から右辺になってしまうという事である。 39480 うーん。ARGER の時や VALR の時にはちゃんと判断できているという事を思うと、 39481 ARGVR の時にすぐに ARGVR になってしまうのは意図的な物だろうか。 39482 例えば着色を変数の色ではなくて黒色に変えるという事を目的とした。 39483 39484 ble/syntax:bash/check-variable-assignment の以下の部分が原因である。 39485 確かにこれは何かの理由があってこの様にした記憶がある。 39486 記録には残っているだろうか。うーん。見つからない。 39487 39488 | if ((ctx==CTX_ARGVI||ctx==CTX_ARGEI)); then 39489 | suffix="$suffix|\[?" 39490 39491 試しにこの部分を除いてみると今度は単語着色が為されなくなる。 39492 この部分が書かれたのは 1823c540 で 2017-11-27 23:46:09 である。 39493 確認すると #D0636 で ARGVR の導入について書かれている。 39494 39495 うーん。試しに ARGVR ではなくて ARGVI の儘になるようにしてみたが、 39496 着色としては余り変わっていない。a{1..3}b=10 とした時に 39497 b の位置まで変数として着色するのかどうかというのが問題である。 39498 因みに a{1..3}b=~ とした時にはチルダ展開とは見做されなかった。 39499 つまり a{1..3}b=~ は bash の構文解析としては変数代入ではないのだ。 39500 その様に考えると a までで ARGVR に変化してしまうという振る舞いでも 39501 まあ矛盾はないのかなという気はする。寧ろ b まで着色して 39502 = 以降を右辺として扱うという事だとチルダ展開が有効になってしまう。 39503 (チルダ展開が有効でない = の右辺) の様な文脈を無駄には作りたくない。 39504 従って即座に ARGVI は ARGVX に変換するというので良い気がする。 39505 39506 結局これに関しては現状のままという事にする。 39507 39508 2019-07-17 39509 39510 * history: PREFIX_history_onleave -> _ble_history_onleave [#D1137] 39511 vi.sh は onleave_hook に登録しているがこれは 39512 [[ ! $_ble_history_prefix ]] の時にしか対応していないのではないか。 39513 観察した。実は全ての prefix の場合にこれを実行しても良い気がする。 39514 というかそもそも PREFIX_history_onleave を PREFIX 毎にする理由は何か。 39515 実は全体に対して登録して良い気がする。そして、 39516 PREFIX 毎の操作をしたければ PREFIX を調べれば良いのである。 39517 この修正もそんなに難しくなかった。簡単である。 39518 39519 * 2019-07-09 history 移行: 検索機能だとか、或いは他の履歴の管理などに関しては [#D1136] 39520 追々 history.sh に移行する事にしようと考える。 39521 取り敢えず、今回の移行では bash history との接続部分だけにしておく。 39522 39523 Bash のコマンド履歴と、その他の独立な履歴の管理について。 39524 移行するにしても名前を分かりやすくしたい。 39525 Bash のコマンド履歴を ble/history と名付けてしまっている。 39526 一方で、その他の独立した履歴およびそれらを統合的に扱う仕組みをどう名付けるか。 39527 同じ様に ble/history という名前にしてしまうと両者が混ざってしまって厄介である。 39528 39529 コマンド履歴と同期した物を ble/history のままにして、 39530 新しい枠組みを ble/hist, ble/history/general 等の別名か子として定義するか。 39531 或いは、コマンド履歴と同期した物を ble/history:edit だとか、 39532 或いは ble/history:bash 等のようにするか。これが良さそう。 39533 39534 さて移動するとしてもどの関数を移動したら良いだろうか。 39535 39536 - 先ず履歴検索ルーチンに関しては移動しなければならない。 39537 と思って調べてみたが実は関数二個だけで閉じていた。238行しかない。 39538 - 他に prefix 関連の操作を移動する事にした。 39539 39540 やってみると意外と簡単にできた。ちゃんと疎結合になっていたので 39541 多少書き換えるだけで簡単に分離する事が可能だった。 39542 39543 x fixed: bash:history にしたら無限にエラーメッセージが表示される様になってしまった。 39544 これは ble/util/idle に登録するコマンド名に : を使えないという事だろう…。 39545 39546 x 更に実は履歴が全く動かなくなっていた。うーん。 39547 どうも set-index がちゃんと動いていないという事? 39548 OK これも修正した。 39549 39550 * decode: DA1 応答の読み取りに失敗して変な文字列が入力される (reported by miba072) [#D1135] 39551 https://github.com/akinomyoga/ble.sh/issues/28 39552 39553 どうも DA2 に対して DA1 応答が為されている様である。DA1 に応答する様に修正した。 39554 39555 後、よく考えたら認識できないキーシーケンスはその時点で破棄するべきでは。 39556 と思ったがデフォルトで破棄する設定になっている様な…。 39557 或いは ble-0.3 の時点では状況が違っただろうか。 39558 どうも調べると 0.3 では CSI seq に関してはちゃんと処理していない様だ。 39559 うーん。色々修正しなければならなそう。 39560 39561 念の為、以前 0.4 で何処で修正したのかを確認する。 39562 2019-04-01 ab1b8b0 である。#D1056 だ。 39563 うーん。ab1b8b0 を覗いたら別に他に影響も無さそうなので cherry-pick してしまう事にした。 39564 39565 2019-07-16 39566 39567 * highlight: ファイル名のディレクトリ部分の着色で、 [#D1134] 39568 ディレクトリ名にパス名展開があると正しく着色されない。 39569 と思ったら理由が分かった…。 39570 39571 * fixed: 一番最初に一致した物がディレクトリ名でないという事なのだ。 39572 ディレクトリまたはシンボリックリンクだった時にのみ着色をしているのが行けないのである。 39573 うーん。これに対処する為には / も含めて展開する必要があるのではないか。 39574 つまり単語の区切れ目を / の直前ではなくて / の直後にする必要があるのである。 39575 然し今の振る舞いになっている理由があった筈である。 39576 という事を考えるとオプションで制御する様にする? 39577 39578 x fixed: 今度は */a.txt について */a.t 等の様に途中まで入力した状態では 39579 全体がエラー着色されてしまうという事が分かった。 39580 と思ったが、これは実は failglob による問題である。 39581 failglob であっても途中のディレクトリ名まで一致している時には 39582 ディレクトリ名を着色しても良いのではないだろうか。 39583 39584 x supported: 更にコマンド名の時にもディレクトリ部分に着色がされていない。 39585 これについても対応した。 39586 39587 * highlight: コマンド名は : で区切った着色をしても仕方がないのでは [#D1133] 39588 現状では例えば : を含む関数名をクォートなしで入力するとエラー着色になる。 39589 39590 ? ok: そもそも : を含むコマンド名を補完する事は可能だったか 39591 →確認したところ、補完に関しては : があってもちゃんと動作する様だ。 39592 : 以降の文字列に基づいた補完が起動するという事もなくて、 39593 始めから全体に対する補完が試みられているので問題ない。 39594 39595 着色をするコードが何処にあったのかを確認する。 39596 これは ble/highlight/layer:syntax/word/.update-attributes/.proc の中で 39597 取り敢えず単語の種類に依らずに単語の開始位置をずらしているのが良くない。 39598 特に、ble/syntax:bash/simple-word/locate-filename "$wtxt" を呼び出して処理している箇所。 39599 これは文脈依存で実行する様にしなければならない。 39600 39601 更にコマンド名の補完の場合には : による区切りは有効でない。 39602 従って : まで escape する必要性は実はない。 39603 core-complete の中を調べて見ると quote-insert の中で殆どは escape を実行している。 39604 その他の箇所では common-prefix で曖昧一致をした時に escape をしている。 39605 曖昧一致の時は流石にエスケープしても仕方がないと認める事にする。 39606 39607 取り敢えず quote-insert の方を調べる。quote-insert の呼び出し元を探すと、 39608 結局全て action:action/initialize の中からである。 39609 特に action:command の時に関しては直接 quote-insert を呼び出している。 39610 39611 2019-07-14 39612 39613 * edit: BUG bash-3.2 で "echo \改行" と入力するとエラーメッセージが出る [#D1132] 39614 bash-3.2: syntax error near unexpected token `"${@:2}"' というメッセージ。 39615 然し、その様な物が書かれている箇所は限られている。 39616 39617 [問題位置特定] 39618 39619 一つの場所は以下の所。何が文法的な問題が起こるとも思われない。 39620 実際にここを &>/dev/null して見たが何も変化はなかった。 39621 というかよく考えたらこれは bash-3.0 用のコードなので関係ない。 39622 39623 function ble/util/sprintf { 39624 local -a args; args=("${@:2}") 39625 ble/util/assign "$1" 'builtin printf "${args[@]}"' 39626 } 39627 39628 その次の箇所は ble/util/fiberchain#resume/.core の中である。 39629 これも同様に配列の初期化をしているだけなので文法的にどうという 39630 事がある用には思われない。実際に &>/dev/null してもメッセージに変化はない。 39631 39632 他は decode 関係しか無いので多分関係はないだろう。 39633 39634 では何処から ${@:2} という文字列が出てきたのだろう。 39635 $ grep -E '"\$\{@:2\}"' ~/.bash_history としても結果は 39636 echo "${@:2}" という1行だけである。これはこのデバグの為に実行したコマンドだ。 39637 39638 仕方がないので次の方策として絞り込みをかける事にする。 39639 先ず auto-complete と menu-filter を切る…と思ったが、 39640 よく考えたら bash-3.2 なのでそもそも切られている。 39641 39642 振る舞いを見るとちょうど "echo \改行" の状態の時にのみ発生する様である。 39643 続きを記述するとそのメッセージは発生しなくなる。更にカーソル移動では発生しない。 39644 ble_debug=1 で見ても文法構造的に何か偏という事はない気がする。 39645 39646 ble/syntax/parse &>/dev/null してもメッセージは表示されたので parse は関係ない。 39647 ble/textarea#update-text-buffer &>/dev/null で何もでなくなったのでこの中である。 39648 ble/highlight/layer/update "$text" の中である。 39649 "ble/highlight/layer:$layer/update" "$text" "$player" の中で起こっている。 39650 LEVEL=1 である。syntax だった。 39651 ble/highlight/layer:syntax/update-word-table &>/dev/null の中だった。 39652 ble/highlight/layer:syntax/word/.update-attributes &>/dev/null の中である。 39653 ble/syntax:bash/simple-word/evaluate-path-spec "$wtxt" / "$opts" の中だ。 39654 ble/array#push spec "$s" なんとこれが駄目だ…。type で出力すると以下の通り。 39655 39656 ble/array#push () 39657 { 39658 builtin eval "$1+=(\"\${@:2}\")" 39659 }。 39660 39661 不思議だ。bash-3.2 で色々動かして見るが似たような例が駄目に場合は見当たらない。 39662 以下の様にしてもエラーを出力せずに実行できる。 39663 ff() { b=(); builtin eval '\''b+=("${@:2}")'\''; declare -p b; }; ff 111 222 333 444 555 39664 ff() { local b=1; builtin eval '\''b+=("${@:2}")'\''; declare -p b; }; ff 111 222 333 444 555 39665 うーん。不思議な事に ble/debug/print-variables s が何も出力しない…。 39666 39667 再現性は謎だが少なくとも ble/syntax:bash/simple-word/evaluate-path-spec $'\\\n' を実行すれば再現する。 39668 $ ble/array#push spec $'\\\n' としても再現性はない。 39669 39670 うーん。ble-detach した状態でも再現はする。 39671 39672 [原因解明] 39673 39674 仕方がないので ble/syntax:bash/simple-word/evaluate-path-spec を少しずつ縮めて行った結果、 39675 以下の形にまで縮小する事ができた。B と C の間でエラーになる。 39676 どうも bash-3.2 eval は前に評価した時の途中状態を残して構文解析するらしい? 39677 然し、コマンドの実行に関しては前回の途中状態からではなくて、 39678 今回読み取られた新しい単語をコマンドとして読み取る様である。 39679 39680 function debug1 { 39681 echo A 39682 builtin eval $': \\\n' 39683 echo B 39684 builtin eval 'B=()' 39685 echo C 39686 } 39687 39688 他の bash はどうだろうか。ファイルに問題のスクリプトを記述して試してみる。 39689 builtin eval $': \\\n' 39690 builtin eval 'B=()' 39691 だと再現しない。 39692 builtin eval $': \\\n'; builtin eval 'B=()' 39693 で再現する。つまり途中に実行の区切れがあれば eval 状態はクリアされるという事。 39694 これで試すと bash-3.1 及び bash-3.2 で問題になる。bash-3.0 はOK 39695 39696 [解決方法] 39697 39698 これに対してどの様に対処したら良いだろうか。 39699 変な物を eval した後は eval -- ':' とかやっておけば良いのだろうか。 39700 39701 * edit: exec:exec の枠組みは削除する事にする [#D1131] 39702 #D1130 の対応が面倒になってしまう為。 39703 更に全くテストしていないので他にも様々な問題が在るだろう。単に削除する。 39704 39705 * main: BUG ble.sh セッションで source ble.sh --attach=none すると固まる [#D1130] 39706 39707 [症状] 39708 ble.sh をロードした状態で source ble.sh --attach をすると固まってしまう。 39709 一方で source ble.sh --attach=attach としても固まらない。この違いは何だろうか。 39710 どうも調べてみると単に --attach とすると 39711 --attach=none という意味になり、そうすると固まる様である。 39712 --attach=none で再現する事を確認した。--noattach でも再現するのだろう。 39713 39714 もしかしてこれは source ~/.bashrc で問題になるのではないだろうか。 39715 と思ったが、もし --noattach を指定していたとしても、 39716 bashrc の末尾で ble-attach を呼び出している筈だから大丈夫の筈なのである。 39717 39718 試しに ble/base/unload-for-reload を呼び出してみるとその場で固まった。 39719 ble-detach/impl を実行してみてもやはり固まった。何が悪いのだろうか。 39720 どうも固まると言っても C-d によるログアウトはできる様である。 39721 39722 [原因解明] 39723 39724 C-f や C-g に ble.sh の枠組みでログアウトを登録しても何も起こらなかった。 39725 つまり C-d によるログアウトを支配しているのは bash の枠組みの方である気がする。 39726 実際に bind -p を出力したところ bind は復元されている様子であった。 39727 では標準出力等が繋がっている先がおかしな事になっているという事だろうか。 39728 39729 la /proc/self/fd を実行してみたところ 0 と 2 は普通だが 1 は変な所に繋がっている。 39730 と思ったが、これは元からそうである様である。普通に実行しても pipe:[...] になっている。 39731 普通に ble-detach してその上で実行してもやはり pipe:[...] になっている。 39732 なので接続先がおかしくなっているとかそういう事ではないのだろうという気がする。 39733 39734 * 2019-07-14 うーん。そもそもキー入力を受信しているのかどうかから調べる事にする。 39735 どうもキー入力を受信してはいない様である。次に bind の状態を調べてみたい。 39736 うーん。bind は通常の bash になっている気がする。 39737 39738 その直後に PROMPT_COMMAND 経由で hook が実行されているのだろうか…。 39739 試しに PROMPT_COMMAND= を付けてみてもやはり反応がなくなる問題は継続している。 39740 うーん。ble-attach を直後に実行しておけば操作できなくなる事はない。 39741 因みに ble-attach の直後の builtin bind -p は何も出力されない…。 39742 何が起こっているのだろうか。と思ったが ble-attach の直後は出力は抑制されるのだった。 39743 ファイルに書き出してみた所 builtin bind -p によって期待通りに、 39744 何にも束縛されていない結果が出力される事を確かめた。 39745 39746 うーん。source out/ble.sh --noattach の直後に stty sane をしても効果はなかった。 39747 というかそもそも stty sane を実行したとしても epilogue が走るのではあるまいか。。 39748 epilogue がどうなっているのかについて確かめて置きたい。 39749 39750 成る程…分かった気がする。detach された時には 39751 ble-edit/exec:gexec/.end で本来チェックに引っ掛かって、 39752 bind/tail が呼び出されないという仕組みになっている筈だが、 39753 ble-reload をした場合にはそれがチェックされないという事の様だ。 39754 39755 [修正] 39756 39757 問題の箇所を修正したら完全に固まるという事はなくなった。 39758 然し依然として状態はおかしい。stty sane は実行して置かなければならないし、 39759 更に PS1 などが消滅してしまっている。どうやらコマンドを実行中は 39760 PS1 は消えていないので、その後で消滅しているという事の様である。 39761 39762 うーん。調べてみると ble-detach/impl の後に PS1 の類が復元されている様である。 39763 これはどの様に対処したら良いだろうか。_ble_attached の状態で unload が起こったら…。 39764 detach のタイミングを遅延させて後で detach するという事にするか? 39765 然し、その場で unload しないと変な事になってしまう…。 39766 更に、attach が始まってしまう。或いは別の手として、 39767 _ble_edit_detach_flag == reload になっていたら 39768 その場で強制的に ble-attach してしまうという可能性? 39769 39770 と思ったが既に PS1 等が破壊されている状態で 39771 ble-attach すると余計に変な事になってしまう。 39772 39773 結局、そのまま detach する事は許して、 39774 然し、状態をちゃんと復元するという事にした。 39775 通常の detach の場合には epilogue の外で detach/impl するから問題なかったのが、 39776 今回の場合は prologue-epilogue の中で detach/impl して、 39777 その後で epilogue が実行されて内部状態に入ってしまうのが駄目だった。 39778 従って再び prologue を呼び出して誤魔化す事にした。 39779 面倒なので exec:gexec の枠組みの方の prologue を呼び出してしまう事にする。 39780 39781 * というか exec:exec はちゃんとメンテナンスされているのだろうか…。 39782 39783 うーん。一応 ble-edit/attach/.detach という関数があって、 39784 それでちゃんと処理をするという事になっているが、 39785 reload の時にはそれが後で覆されてしまう。 39786 しかし、ble-edit が保持している _ble_edit_attached 変数に記録されてしまっているので、 39787 再度この関数を呼び出しても意味はない。 39788 その様な事を考えると、実際汚いが prologue を呼び出して誤魔化すしかないのである。 39789 39790 時に、ecec:gexec の prologue でなければならない。 39791 exec:exec は PS1, IGNOREEOF は local で被覆されていると仮定して 39792 復元処理をスキップしている為である。 39793 と思ったが restore-PS1 の枠組み自体が調整済みかそうでないかを記録しているのでは。 39794 exec:exec を利用している時にはそもそも adjust-PS1 を呼び出していないので、 39795 この時に破壊されてしまう気がする…と思ったが、よく考えたら exec:exec の場合には 39796 そもそも PS1= にしていないから問題にならないのであるという事か? 39797 否、exec:exec であっても起動時に adjust している。 39798 reload 時に restore して (しかし local PS1 に対して restore してしまう) 39799 その後で exec:exec/epilogue では adjust されない為に、 39800 改めて restore を実行したとしても復元されないという事になる。 39801 39802 exec:exec に対する対応は複雑になってしまう。 39803 うーん。というか exec:exec はメンテナンスされていないし、 39804 今後使う事があるとも思われないのでこの際削除してしまって良い気がする。 39805 削除する事にした。 39806 39807 * history: BUG #D1126 について対応したと思っていたら駄目だ [#D1129] 39808 39809 % ble-reload した直後に C-d で終了すると履歴が書き込まれない。 39810 % 何かコマンドを実行した後だと書き込まれる。 39811 % 但し、":" の様な単純なコマンドだと書き込まれなかった。 39812 % "echo" でも駄目だった。どういう事なんだろう…。 39813 % また調べ直す必要がある。 39814 % 39815 % 終了するのに exit を実行した場合には問題は再現しない。 39816 % やはり C-d を実行すると行けないのだろうか。 39817 % というかそもそもちゃんと C-d を受信できているのだろうか。 39818 % 実は Bash の枠組みの側で C-d が受信されている可能性はあるだろうか。 39819 % そして Bash の機能としてログアウトが実行されている。 39820 % 39821 % 調べてみると何と ble/history/TRAPEXIT は実行されている。 39822 % つまり、問題は何かが呼び出されていないとかそういう事ではなくて、 39823 % ble.sh の中での skip の管理の方であると思われる。 39824 % 39825 % 気づいた事は、実は履歴の項目数が上限に達しているという事。 39826 % 更に history -a で全ての履歴が書き出されてしまっているという事。 39827 % wskip なのに何故だろう…。うーん。結局履歴が増殖するのも分からないし、 39828 % 更に、あー。何だか分かった気がする。履歴が初期化されるタイミングが色々なんだ。 39829 39830 問題を切り分ける必要がある。今発生している問題は。 39831 1. ble-reload をするとコマンドが記録されない。 39832 2. ble-reload をした後にコマンドを実行して終了すると 39833 履歴が倍加してしまうという減少が発生していた。 39834 39835 取り敢えず 2. が今も再現するのかどうかについて確認する。 39836 再現した。bash RET ble-reload RET echo RET C-d で再現する。 39837 39838 取り敢えず 1. について調べる事にする。 39839 どうも ble/builtin/history/.check-uncontrolled-change が悪さをしている様子である。 39840 ここでは一体どういう判断をしていただろうか。 39841 max!=_ble_builtin_history_prevmax だった時に 39842 _ble_builtin_history_wskip を更新している。 39843 というか _ble_builtin_history_prevmax や 39844 _ble_builtin_history_wskip がクリアされているのがいけないんだ。 39845 ちゃんと初期化されない様にしたら治った。 39846 39847 2. の問題も一緒に治ってしまった。考えてみれば当たり前の気がする。 39848 そもそも reload さえしなければ変な事は起こっていなかったのでこれは気にしない事にする。 39849 39850 * [棄却] decode: BUG bind -sS が効いていない気がする [#D1128] 39851 →確認してみた所、わざわざ ble.sh の設定を解除してから 39852 出力する様になっていた。つまりこれは意図的な動作である。 39853 よく見ると -pP 等の場合にも復元する様になっている。 39854 確かに実行してみると復元した後の状態が出力されている様である。 39855 39856 2019-07-11 39857 39858 * main: --prompt で attach するとプロンプト表示までに時間がかかる気がする [#D1127] 39859 と思ったが今試してみると再現しない。というより、 39860 padparadscha の bashrc を変更したら治ってしまった気もする。 39861 39862 うーん。今 Cygwin で試してみると再現する。 39863 Cygwin の上と Linux の上で振る舞いが違うという事なのだろうか。 39864 一応 cygwin は bash 4.4.12 で linux は bash 4.4.23 である。 39865 linux 上の bash 4.3.48 でも再現はしない。4.2.53 でも再現しない。 39866 Cygwin の上でどのタイミングでプロンプトが表示されるのか調べる事にする。 39867 39868 どうやら vi.sh の初期化がプロンプトの初期化よりも先に実施されている? 39869 というより ble-attach よりも先に実行されている様である。 39870 分かった。inputrc の読み込みのために初期化が実行されている。 39871 つまり inputrc がある環境では vi.sh 等の初期化が先に走ってしまうという事。 39872 後気付いた事だが、通常の bash の場合には bashrc で set -o 等をした後に 39873 inputrc が読み込まれるのではないだろうか。つまり、 39874 ble.sh をロードした時点では未だ inputrc を読み込んでは行けないのではないか。 39875 39876 inputrc の初期化タイミングについて調べる必要がある。 39877 39878 実際に調べてみると inputrc は bashrc の中で set -o vi とした後に 39879 読み込まれている様である。set -o vi より前に bind '' を実行すると 39880 その時点で読み込まれる様になる様である。 39881 何と bind 'set editing-mode vi' とした場合には、 39882 vi mode に変更するよりも前に inputrc が読み込まれてしまう様である。 39883 39884 これについて対応する為には ble.sh での 39885 inputrc の読み込みタイミングを考える必要がある。 39886 - 'bind' を呼び出した時に inputrc の初期化を実行する。 39887 - 'bind' が一度も呼び出されなかった時には attach の時点で inputrc の初期化を実行する。 39888 39889 修正したのに未だ駄目だ…。と思ったら分かった。blerc の中で bind を実行している。 39890 その瞬間に inputrc を読み込んでいるんだ。 39891 39892 % 実は、bind を呼び出した瞬間には inputrc は読み込まなくても良いのではないか。 39893 % 特に set* を実行している場合には inputrc を遅延させても良い気がする…。 39894 % と思ったがやはり駄目だ。inputrc を読み込んでから、その inputrc の設定を 39895 % 上書きする様に振る舞う必要がある。という事は inputrc を先に読み込んで置く必要がある。 39896 39897 これは取り敢えず対応完了と考えて良い事にする。 39898 39899 * history: ble-reload するとそれ以前の履歴が bash_history に書き込まれない [#D1126] 39900 これは ble/builtin/history/.initialize がもう一度呼び出される為である。 39901 ここで _ble_builtin_history_wskip が reload した瞬間の値に書き換えられてしまう。 39902 39903 a _ble_builtin_history_initialized が既に設定されている時にはクリアしない様にする? 39904 39905 と思ったが問題はそれだけではない。例えば途中まで素の bash で操作していて、 39906 途中から ble.sh に切り替えたとする。するとやはり ble.sh をロードする以前の 39907 履歴の内容が bash_history に書き込まれないという事になってしまう。 39908 従って、ble.sh をロードした瞬間に残っているデータに関しては、 39909 その時点で何処かに書き出して置く必要があるのである。 39910 39911 既にその仕組は整っている。fetch である。 39912 39913 b うーん。histapp=$_ble_base_run/$$.history.app に history -a してしまえば良い? 39914 39915 と思ったが本当に大丈夫だろうか。例えば history -a && history -c && history -r 39916 を実行しているという場合には history -r した内容が 39917 history -a で書き出されてしまうのではあるまいか。 39918 39919 今試してみると history -cr; history -r した後で 39920 history -a x.txt で全ての履歴が書き出されてしまっている。 39921 と思ってもう一度試してみたがこれは再現しない。どういう事だろう。 39922 よく分からないが幻だったという事にする。 39923 39924 取り敢えず他で history -r だとかしていたとしても 39925 履歴が倍化してしまうなどの現象は起こらないのではないかと予想する。 39926 然し、念の為対応した後に変な事が起こらないか確認する事にする。 39927 39928 - 実装中に気になった事。/dev/stdin, /dev/stdout 等は POSIX にないのだろうか。 39929 http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap10.html 39930 を見ると /dev/null 及び /dev/tty しか定義されていない。 39931 他に /dev/console という目慣れない物がある。これはよく分からない。 39932 システムのエラーメッセージを出力する端末に繋がっている? 39933 39934 - うーん。builtin history -a で大丈夫なのだろうか。 39935 一回 load した後だと bash の中で記録している index が 39936 色々と狂ってしまっているのではないか。 39937 その様に考えると a と b の対策の両方をしておくのが懸命と思われる。 39938 39939 * history: ble-detach してそれから ble-attach すると [#D1125] 39940 bash: kill: (9952) - そのようなプロセスはありません 39941 と言った様なメッセージが表示される。何処の kill かを先ず特定する必要がある。 39942 →これは最近追加した history の bgpid の kill であった。 39943 前回使用した background-worker の情報が残っていて、 39944 それを kill しようとしているのである。 39945 39946 何故 kill するのかというと、clear-background で再度 39947 background 処理がやり直しになった時に古い bgworker によって 39948 ファイルが上書きされると困るからであった。 39949 従ってファイルが完成した時点で bgpid をクリアしてしまえば良いのである。 39950 ファイルが完成した時点で bgworker が再びファイルを上書きしてしまうという心配はない。 39951 39952 2019-07-10 39953 39954 * 2019-07-02 [不要] 現在 bashrc を実行中かどうかを判定する方法? [#D1124] 39955 39956 以前 bashrc の中にいるかどうかを判定できたら良いという話があった。 39957 39958 実は以下の条件で bashrc の中にいるかどうかを判定できるのではないだろうか。 39959 [[ $(builtin history -s -- echo; HISTTIMEFORMAT=X builtin history 1) == *'??'* ]] 39960 と思ったがこの方法が使えるのは bash-4.3 以降であった。 39961 というよりも寧ろ HISTTIMEFORMAT が動かなくなってしまうのは bash-4.3 以降のバグだろうと思われる。 39962 何れにしても実現する為にはもっと別の方法を模索する必要がある。 39963 39964 何処で bashrc の中にいるかどうかの判定ができたら良いという話だったろうか。 39965 39966 * 見つかった。#D0737 である。しかし、読んでみると結局 trap -- RETURN は、 39967 bashrc の末尾では呼び出されないとの事で、 39968 bashrc の中にいるかどうかの判定ができても意味がないという結論になっていた。 39969 * 或いは ble.pp のスタートアップの判断の時に何か使えるかもしれない。 39970 と思ったがやはり特に使えそうな物はない様な気もした。 39971 もし使えるとしたら $ source ble.sh した時はその場で attach して、 39972 bashrc の中で source ble.sh した時には manual attach という可能性があったが、 39973 どうせ manual attach をユーザに書かせるのであれば 39974 明示的に noattach を指定させた方が混乱がない。 39975 更にもし PROMPT_COMMAND を使うのであれば実はわざわざ場合分けする必要もなかった。 39976 というより今確認したら既に attach=prompt がデフォルトになっていたので、 39977 bashrc の中で単に source ble.sh を記述しただけでも 39978 PROMPT_COMMAND を上書きしない限りは動くには動く。 39979 * 対話シェル以外で起動した時に警告を発するかどうかを 39980 bashrc の中にいるかどうかで切り替えていた。 39981 然し、そもそも対話シェル以外の時には履歴が無効になっているので、 39982 上記で挙げた様な方法は使えないのであった。 39983 39984 というか今や noattach を指定しなくても prompt で取り敢えず設定しておいて、 39985 もし末尾で manual attach されなかったら PROMPT_COMMAND 経由で attach を試みるというので良いのでは。 39986 実際に試してみるとそれで動作している気がするのでOK 39987 39988 もしかすると知られた方法があるかもしれないと思って検索したが見つからない。 39989 というかどのようなキーワードで検索したら良いのかがよく分からない。 39990 39991 * history: vi.sh は _ble_history の上で動作する事を前提としている様に見える [#D1123] 39992 然し、実際には read 等を用いた時に _ble_history 以外の上で動作する。 39993 ちゃんと _ble_edit_history_prefix を参照して動作する様に書き換える必要があるのではないか。 39994 39995 或いは read で動作する時には local で _ble_history を被覆していたりするのだろうか…。 39996 と思ったが履歴を読み込んだりする時にやはり問題に為る気がする。 39997 →確認してみたが実は _ble_history_ind を参照しているだけだったのでそんなに問題ではない。 39998 これは全て get-index に置き換えて実装する事にした。 39999 40000 * done: それより read での新しい編集モードに入る時に初期化するべき変数の一覧など。 40001 うーん。history prefix が変われば以下の様な変数は待避したりしなければならないのでは。。 40002 _ble_keymap_vi_mark_local=() 40003 _ble_keymap_vi_mark_global=() 40004 _ble_keymap_vi_mark_history=() 40005 40006 以下の配列を用意してここに textarea 固有のデータを登録させる事にした。 40007 _ble_textarea_local_VARNAMES 40008 _ble_textarea_local_ARRNAMES 40009 40010 適当にその辺りにある変数も登録しておく事にした。 40011 或いは、全ての textarea で退避する変数を一つの配列に入れようかとも思ったが、 40012 例えば ble/syntax や ble/textmap は独立して使う事もあるかもしれないので、 40013 やはり幾つかの配列に分けて置くというのは有効である。 40014 undo だけは _ble_textarea_local_VARNAMES に登録する事にした。 40015 40016 2019-07-09 40017 40018 * history.mlfix: Bash-3.* でエラーメッセージが出る [#D1122] 40019 bash-3 系列では ble/util/idle を使えないのだった。 40020 必要になった時にロードする様に変更した。 40021 40022 * history (resolve-multiline): 開始時に引っかかる [#D1121] 40023 どうも引っ掛かると思ったら .search-history-light だとか、 40024 或いは magic-space だとかが history -p を呼び出していて、 40025 その経由で resolve-multiline init が実行される様だ。 40026 仕方がないので history -p に関しては resolve-multiline を待たない事にした。 40027 一応現実的な速度で動いている様な気がする。 40028 40029 他には特に問題は起こっていない気がする。 40030 40031 * history: 複数行モードの履歴展開 (reported by cmplstofB) [#D1120] 40032 https://github.com/akinomyoga/ble.sh/issues/26 40033 40034 これは前から問題があるなあと常々思っていて放置していたものである。 40035 既知の問題と書いてはいたが memo.txt には明記はしていなかった様に思う。 40036 40037 履歴展開を自前で再実装するという様な愚は犯したくない。 40038 従ってできるだけ bash の枠組みの中で解決したい。 40039 目的は二つ。複数行コマンドの履歴をそのままの形で保持する。 40040 それから履歴展開も正しく実行される様に工夫する。 40041 40042 履歴展開が正しく実行される様にする為には 40043 history には複数行コマンドを登録するという事は必須である。 40044 そして bash_history に登録された複数行に亘るコマンドを 40045 ちゃんと分断せずに読み取らせる方法は存在していない事から、 40046 bash_history への記録を行う場合には eval -- $'' の形式に変換する必要がある。 40047 history に複数行コマンドを登録する為には自前で history を再構築しなければならない。 40048 この再構築に一番時間がかかると予想される。 40049 40050 | 試しに history -s -- '' の羅列を出力させて、 40051 | 更にそれを source するスクリプトを書いてみた。 40052 | chatoyancy の上では 5000 行を読み取るのに 0.033s であったが、 40053 | padparadscha では 47k 項目を読み取るのに 1.895s かかってしまう。 40054 | どのタイミングで再構築するのかによるが 1.895s は時間がかかり過ぎである。 40055 | 40056 | history -r でまとめて読み取る様にしたらどうなるだろうか。 40057 | chatoyancy 上で 0.012s にまで短くなった。 40058 | 40059 | * history -r でまとめて読み取るにしても例えばまとまりが単一行の場合には 40060 | history -r に置き換えて却って遅くなるのではないかと思われる。 40061 | 次に何個のファイルであれば history -r が history -s * N に勝つのか調べる。 40062 | 計測結果は以下の通り 40063 | 40064 | | 9.30 usec/eval: _read_r 1 (x10000) 40065 | | 26.20 usec/eval: _read_s 1 (x5000) 40066 | | 9.20 usec/eval: _read_r 2 (x10000) 40067 | | 31.20 usec/eval: _read_s 2 (x5000) 40068 | | 10.20 usec/eval: _read_r 5 (x10000) 40069 | | 45.50 usec/eval: _read_s 5 (x2000) 40070 | | 10.90 usec/eval: _read_r 10 (x10000) 40071 | | 69.00 usec/eval: _read_s 10 (x2000) 40072 | | 12.60 usec/eval: _read_r 20 (x10000) 40073 | | 114.00 usec/eval: _read_s 20 (x1000) 40074 | | 21.20 usec/eval: _read_r 50 (x5000) 40075 | | 257.00 usec/eval: _read_s 50 (x500) 40076 | | 32.20 usec/eval: _read_r 100 (x5000) 40077 | | 489.00 usec/eval: _read_s 100 (x500) 40078 | | 40079 | | 何というか、始めから -r が勝っている気がする。 40080 | | source の分が抜けているからであろう。 40081 | | source の分を一致させて計測してみたがやはり _read_r の方が高速だ…。 40082 | | 30.60 usec/eval: _read_r 1 (x5000) 40083 | | 35.00 usec/eval: _read_s 1 (x5000) 40084 | | 31.20 usec/eval: _read_r 2 (x5000) 40085 | | 41.40 usec/eval: _read_s 2 (x5000) 40086 | | 31.20 usec/eval: _read_r 5 (x5000) 40087 | | 60.50 usec/eval: _read_s 5 (x2000) 40088 | | 32.20 usec/eval: _read_r 10 (x5000) 40089 | | 89.50 usec/eval: _read_s 10 (x2000) 40090 | | 34.60 usec/eval: _read_r 20 (x5000) 40091 | | 153.00 usec/eval: _read_s 20 (x1000) 40092 | | 44.00 usec/eval: _read_r 50 (x5000) 40093 | | 331.00 usec/eval: _read_s 50 (x500) 40094 | | 55.50 usec/eval: _read_r 100 (x2000) 40095 | | 625.00 usec/eval: _read_s 100 (x200) 40096 | | 40097 | | 然し、よく考えてみたら _read_r の方はファイル作成について考えていなかった。 40098 | | つまり here string を使っているとその場でファイルを作成・削除する筈なのだ。 40099 | | 59.00 usec/eval: _read_r 1 (x2000) 40100 | | 34.60 usec/eval: _read_s 1 (x5000) 40101 | | 62.00 usec/eval: _read_r 2 (x2000) 40102 | | 41.20 usec/eval: _read_s 2 (x5000) 40103 | | 70.00 usec/eval: _read_r 5 (x2000) 40104 | | 60.00 usec/eval: _read_s 5 (x2000) 40105 | | 82.50 usec/eval: _read_r 10 (x2000) 40106 | | 89.50 usec/eval: _read_s 10 (x2000) 40107 | | 105.00 usec/eval: _read_r 20 (x1000) 40108 | | 155.00 usec/eval: _read_s 20 (x1000) 40109 | | 176.00 usec/eval: _read_r 50 (x1000) 40110 | | 331.00 usec/eval: _read_s 50 (x500) 40111 | | 293.00 usec/eval: _read_r 100 (x500) 40112 | | 625.00 usec/eval: _read_s 100 (x200) 40113 | | 40114 | | 漸く単一行では history -s の方が早いという結果になった。 40115 | | N=1-10 でもう少し詳しく見てみる事にする。 40116 | | 62.50 usec/eval: _read_r 2 (x2000) 40117 | | 41.40 usec/eval: _read_s 2 (x5000) 40118 | | 65.00 usec/eval: _read_r 3 (x2000) 40119 | | 47.00 usec/eval: _read_s 3 (x2000) 40120 | | 67.00 usec/eval: _read_r 4 (x2000) 40121 | | 54.50 usec/eval: _read_s 4 (x2000) 40122 | | 70.00 usec/eval: _read_r 5 (x2000) 40123 | | 60.50 usec/eval: _read_s 5 (x2000) 40124 | | 72.00 usec/eval: _read_r 6 (x2000) 40125 | | 66.00 usec/eval: _read_s 6 (x2000) 40126 | | 75.50 usec/eval: _read_r 7 (x2000) 40127 | | 71.50 usec/eval: _read_s 7 (x2000) 40128 | | 77.50 usec/eval: _read_r 8 (x2000) 40129 | | 82.00 usec/eval: _read_s 8 (x2000) 40130 | | 79.50 usec/eval: _read_r 9 (x2000) 40131 | | 83.50 usec/eval: _read_s 9 (x2000) 40132 | | 81.00 usec/eval: _read_r 10 (x2000) 40133 | | 89.50 usec/eval: _read_s 10 (x2000) 40134 | | 40135 | | N=7,8辺りが怪しい? 何回か測ったがやはり N=7,8 が境目の様である。 40136 | 40137 | history -r にまとめる事の最適化を行って、 40138 | しかしそれでも 47k 項目の再構築をするのに padparadscha では 1.250s かかっている。 40139 | 30% ぐらいは高速化したがそれでも高速とは言い難いのである。 40140 | 40141 | a すると次に試みるのは history の再構築自体を分断して少しずつ実行するという事である。 40142 | うーん。何というか段々と複雑になって行く…。本当に他に方法はないのだろうか。 40143 | 或いは、自前で履歴展開を実装するという方向性に行くのだろうか…。 40144 | 自前で履歴展開を実装するという方向性になると 40145 | その細かな文法 (クォートの負い方) 等にも気を配らなければならない。 40146 | Bash の振る舞いを完全に再現する必要があるのではないだろうか。 40147 | それは面倒だし無為な気がする。 40148 | 40149 | やはり idle 中に history が実行されないという前提で、 40150 | history の再構築を実施するしかないのだろうか。。 40151 | その為には先ず履歴に関連するコードを整理して置きたい。 40152 | 40153 | history/initialize で history の再構築まで実施してしまうのが良いだろうか。 40154 | と思ったが独立な処理だし history/initialize を呼び出す処理では必ずしも 40155 | history 複数行再構築が必要とは限らないし、また history 複数行再構築が 40156 | 必要な文脈では必ずしも _ble_history 初期化を必要とはしない。 40157 | 従って、それぞれ独立に処理すれば良いという気がするのである。 40158 | 40159 | 他に気になるのは history -r で読み取った時に、 40160 | 追加業だけでなく全ての行に関して再度 history 複数行再構築が 40161 | 全体に対して必要になってしまうのではないかという事。 40162 | うーん。history -r で読み取るという処理自体を止める必要があるだろうか。 40163 | history -r で読み取るのではなくて source する方式にする必要がある。 40164 | 然し、それだと ' について追跡をする必要が出てくるなど、 40165 | やはり処理が遅くなってしまう原因である。 40166 | 40167 | 然し、完全な対応をする為には避けて通れない処理であるし、 40168 | まあ、仕方がないのかなという気はする。 40169 | 40170 | b 実は複数の一時ファイルを作ってしまう事を許せばもっと高速になるのでは。 40171 | 処理が遅くなるのは '...' の対応を取る処理を bash が行うからなのではないかと仮定。 40172 | だとすれば始めからファイルに書き出してしまえば別に遅くはならないのではないか。 40173 | 40174 | うーん。これは爆速である…。chatoyancy で 2ms になった。 40175 | padparadscha でも 47k 項目で 79ms になった。 40176 | これは十分な速度である。但し、その前処理の awk で1秒近くかかっている。 40177 40178 結局 b の方法で history の書き換えを実行する事にした。 40179 然し、それでも前準備の awk の処理に時間がかかるという事は否めない。 40180 history -r でファイルから読み取る度に全て再構築するというのは現実的でない。 40181 40182 うーん。history -r で読み取るのはやめて全部自前で読み取る様にするべきなんだろうか。 40183 というか builtin history -r を実行している場所を置き換えてしまえば良いのである。 40184 40185 * done: Bash に history に書き込ませない様に修正する。 40186 これは EXIT で history -a /dev/null とかやっておけば良いだろうか。 40187 もし EXIT が正しく呼び出されなかった暁には Bash が history を書き込むという仕組み。 40188 というか history -a tmpfile; < tmpfile awk >> histfile とすれば良い気がする。 40189 うーん。然し、そうとなると histappend に依存した振る舞いにしなければならないのでは…。 40190 histappend が設定されている時とされていない時で実装を分ける様にする。 40191 40192 後、EXIT trap に既に ble/base/unload が住んでいる。 40193 ble/base/unload の中で histfile に書き込むのは変な気がする 40194 (例えば ble-reload や ble-update でも呼ばれる物である) ので、 40195 やはり別に EXIT trap のハンドラを作って、 40196 其処から EXIT trap を実行する様にするのが良いだろう。 40197 40198 というか実は EXIT で ble/builtin/history -aw を呼び出せば良いだけだった。 40199 これを実行してしまえば bash が自前で書き込むという事もないだろう。 40200 また history -w は中身をちゃんとクリアしてくれるので自前でクリアする必要もない。 40201 40202 取り敢えず動作確認だけはしておく。 40203 →OKちゃんと重複なく書き込まれている事も確認した。 40204 40205 * done: 起動時の history 複数行書き換えを実装する。 40206 書き換え中は history を編集させない様にする必要がある。 40207 実は ble/history/load と同じなので clear-background-load で一緒に補正すれば良い気がする。 40208 取り敢えず ble-dev で試していた物を持ってくる事にする。 40209 40210 取り敢えず非同期実行を実装した。 40211 本当に動くのかどうか怪しいが試してみる事にする。 40212 そもそも起動していない様だ…。と思ったがこれは違った。 40213 単に clear-background が走っていただけだった。 40214 タイミングが分からないので出力してみる事にする。 40215 どうもちゃんと動いている様である。 40216 但し、一瞬で処理が終了してしまうので非同期がちゃんとなっているかは不明。 40217 何れにしても既に実装してある ble/history/load を参考にしたのでそんなに間違ってはいないだろう。 40218 40219 * ok: bash-3.0 に関しては history -s が使い物にならないので、 40220 複数行の履歴項目を history に入れる事はそもそも不可能である。 40221 従って bash-3.0 に関しては履歴展開は諦める物とする。 40222 40223 * done: bash history に登録する箇所では複数行エスケープはせずに登録する。 40224 但し bash-3.0 では複数行エスケープを実施する。 40225 40226 * done: builtin history -r を実行している場所を置き換えてしまう。 40227 それで良い筈。実装の順番はどうしたら良いだろうか。 40228 というか同時に実装すれば良いのだろうか。 40229 と思ったが一旦どちらかを実装してそれを汎用化する形にした方が見通しは良いだろう。 40230 その時には history -c は外側で実行する様にするべきである。 40231 40232 * done: 履歴項目が読み込まれるまでは (bashrc の外に出るまでは) 40233 待っていた方が良いのではないだろうかと思われる。 40234 或いは、履歴項目が前回から変化していたら全て初期化し直す。 40235 40236 取り敢えず実装した気がする。実際に動かしてみる。 40237 40238 x fixed: 自前で書き込んでいる筈なのにちゃんと改行が \n になっていない…。 40239 少なくとも eval -- $'' で囲まれているので自前の書き込みは実行されている。 40240 と思ったら ble/builtin/history/.write のエスケープが間違っていた。 40241 text という変数の中身を書き換えるべきなのに現在行を書き換えていただけだった。 40242 40243 x fixed: 直したと思ったら今度は末尾に無駄な ' が挿入されている…。 40244 どうやら gawk で /\'/ というのを使うと文字列の末端に一致してしまう様だ。 40245 つまり /'/ としなければならなかった。 40246 或いは gsub(/['\\]/, "\\\\&", text) とするべきだった。後者の方法に修正した。 40247 40248 * history: 履歴に関連するコードの整理 [#D1119] 40249 40250 特に新しいファイル src/history.sh に移動する事で整理を行いたい。 40251 先ず、どの部分を edit.sh から独立させる事ができるかについて考察する必要がある。 40252 40253 ble/builtin/history の部分に関しては大体は大丈夫だが 40254 _ble_edit_history に関連する部分は一緒に移動しなければならないと思われる。 40255 40256 * done: ble-edit/info を呼び出している場所もある。 40257 これに関しても適当な hook を用意すれば問題ないだろうという気がする。 40258 というか bleopt と同様に hook 専用の枠組みを整えても良いのかもしれない。 40259 例えば blehook_ で始まる変数名を予約してしまうなど。。 40260 まあそれに関してはまた別項目として後々で対応する事にすれば良い。 40261 40262 * done: ble-edit/history/initialize に関しては 40263 _ble_edit_history_prefix をチェックする版とチェックしない版に分ける。 40264 40265 * ok: うーん。実は _ble_edit_history_ind はやはり 40266 history の方で管理した方が良いのではないか。 40267 というのも履歴の種類毎に *_history_ind という変数が存在している。 40268 寧ろ _ble_edit_history_ind が変更された時に 40269 その事を通知する様にした方が良いのではないのかという事。 40270 40271 * fixed: うーん。ble/builtin/history/option:d の中で ble-edit/history/goto を呼び出している…。 40272 % →これに関しては _ble_builtin_history_delete_hook の中で実行すれば良いのではないか。 40273 % 基本的に _ble_edit_history_ind に関連する処理と 40274 % _ble_edit_history_prefix に関連する処理は hook の中で処理すれば良いのではないか。 40275 40276 _ble_history_ind はやはり ble/history 側に属しているとして処理する事にした。 40277 この時、どの様に ble-edit/history/goto を処理するべきだろうか。 40278 →結局 _ble_history_ind の補正は呼び出し元で行って、 40279 それとは別に履歴項目の移動に関しては delete hook で処理する事にした。 40280 40281 x fixed: 書き換えていたら初期の _ble_history_ind が 0 になってしまっている気がする。 40282 何故だろう。_ble_history_load_done=1 になった瞬間での値を出力してみたらちゃんと有限の値になっている。 40283 get-index で見張ってみると3回問い合わせがあって初回が 0 になっている…。 40284 →これは ble/history/update-count が正しく動作していなかったのが原因であった。直した。 40285 40286 x fixed: 後、async の途中で history/initialize の要求があって sync load が要求された時に、 40287 loading... のメッセージが表示されない状態になっている。これは表示する様に修正した。 40288 40289 x fixed: どうも background load が動いていない様な気がする。 40290 最初にアクセスしようとした瞬間に読み込まれている様な気がする。 40291 async で呼び出すとどうも 148 で終了してしまっている気がする。 40292 うーん。どうしてだろう。。調べてみると恐らく idle.wait-condition が働いていない? 40293 どうも結局 148 を戻していたのがいけない様だ。148 を返すというのは 40294 ble/util/idle の枠組みに於いては入力があったという事を示している。 40295 従って、直後に再び ble/util/idle が呼ばれるという事を予期している。 40296 然し、実際には呼ばれない、という事によって問題になっている。 40297 では入力がないけれども制御を戻すという事の為の専用の戻り値はあるだろうか。 40298 40299 取り敢えず 147 を返す事にした。148/147 のもっと詳しい考察については別の項目で行う事にする。 40300 40301 2019-07-05 40302 40303 * sabbrev: メニュー絞り込み中に静的略語展開すると [#D1118] 40304 メニュー絞り込み状態が残存してしまう。そして何だか変な状態になる。 40305 と思ったが再現しない。再現した。 40306 40307 "fi " で一旦補完候補を出しておいて其処で \L として SP をすると再現する。 40308 40309 - 不思議な事に \date 等では再現しない。展開後の内容が "less" だと再現しない。 40310 展開後の内容が "| less" だと発生する。"| less -r" でも発生する。 40311 - "echo " の場合にも再現した。 40312 40313 どうも menu-filter の編集範囲を抽出する時に "| less" 等が挿入されると 40314 simple-word ではなくなって、その事により menu-filter の更新が止まってしまう様だ。 40315 本来であれば is-never-word の判定で単語ではないという事になって、 40316 それによって menu 絞り込みがキャンセルされる筈だが、 40317 何故か is-never-word が反応していない。 40318 40319 is-never-word の正規表現を修正した。 40320 最初から非単語文字が存在している場合に対応していなかった。 40321 40322 * sabbrev: 複合コマンド直後で展開されない (reported by cmplstofB) [#D1117] 40323 https://github.com/akinomyoga/ble.sh/issues/25 40324 40325 例えば ble-sabbrev '\L=| less' として、 40326 fi \L \L とすると1つ目の\Lは展開されない。2つ目の\Lは展開される。 40327 [[ ]] \L \L の場合にも同様になる。 40328 40329 調べてみると sabbrev は補完候補の生成を用いて単語範囲を決定している。 40330 エラー単語の場合にはそもそも補完が存在しないので駄目なのである。 40331 % 実際に動かしてみるととちゃんと両方の場合で argument が補完源として動作している。 40332 この argument の補完源はその場で新しく引数を始めるという補完源であった。 40333 つまり、\L 全体を囲むような prefix の補完という訳ではないのである。 40334 40335 代わりに単語として不正な物であっても良いので 40336 何らかの補完 source を生成する様にしたいのである。 40337 具体的に見てみると CMDXE 及び ARGX0 について補完源を生成すれば良い? 40338 40339 取り敢えず実装してみた。動いた。と思ったが少し整理したら動かなくなった。 40340 40341 x fixed: "fi \comm" まで入力して補完を開始すると末尾から補完が開始してしまう。 40342 o "fi \commit" 及び "[[ ]] \commit" は動く様になった。 40343 x fixed: "[[ ]] " の直後で補完候補が生成されない。 40344 調べてみると "[[ ]] " という単語が prefix になってしまっている。 40345 と思ったら単に completion-context/.add に第二引数を渡し忘れていた。 40346 それを修正したら動く様になった。 40347 40348 2019-07-02 40349 40350 * highlight: 何故か空文字列に展開される引数がエラー着色されている [#D1116] 40351 これはファイル名着色が有効になってしまっているからと思われる。 40352 40353 ファイル名が問題なのかと思って調べてみたらそもそもファイル名着色のコードに入っていない? 40354 然し ble_debug=1 で確認すると確かに単語着色で実装されている。 40355 詳しく調べてみると ble/syntax:bash/simple-word/evaluate-path-spec 40356 の時点で失敗しているという事が分かった。 40357 40358 * history: ble-detach 時の ble/builtin/history の振る舞いについて [#D1115] 40359 history -na 等の操作がずれてしまうと困るので detach している状態でも、 40360 ble.sh の実装を用いる事にする。但し、_ble_edit_history 等に対する操作は 40361 detach している時には実行しない様にする必要がある。 40362 40363 * 2019-06-28 history: history -d で現在編集の項目が削除された時 [#D1114] 40364 現在の実装ではどの様に動くだろうか。 40365 編集中の文字列は現在編集の項目がそのまま残る。 40366 この状態で移動を行うと、別の項目の edit として 40367 現在編集中の内容が記録されてしまって、 40368 元々其処にあった項目の内容が見えなくなってしまう。 40369 削除後の index に明示的に移動するべきなのではないか。 40370 40371 然し、そうすると現在編集中の文字列が失われてしまう。 40372 或いは index を最新の履歴項目(未登録)の位置に移動するのが良いか。 40373 と思ったがそうすると最新の履歴項目で編集中の内容があった場合に、 40374 やはりそれが失われてしまう。 40375 40376 そもそも現在の項目を削除するという事なのだから、 40377 現在編集中の文字列が失われるのは仕方のない事なのではないだろうか。 40378 なので現在編集の文字列は捨てて削除後の位置の項目をロードする事にする。 40379 40380 2019-07-01 40381 40382 * history: HISTFILE を削除すると awk が警告メッセージを出す [#D1113] 40383 読み取るべきファイルが存在していない場合には単に無視するべきである。 40384 40385 * history: 履歴に変化がない時 history -r で履歴データが同期されない [#D1112] 40386 これは ble-edit/history/load の問題だった。 40387 40388 * history: 履歴ファイルが存在しない時、警告が出る [#D1111] 40389 これは wc の警告を殺すことにした。 40390 ファイルが存在しない時 wc の結果は空になるが算術式では空は 0 になるので気にしない事にする 40391 40392 * history: PROMPT_COMMAND で history -cr すると履歴が倍化する (reported by cmplstofB) [#D1110] 40393 40394 これは ble-attach した時に内部で初回の PROMPT_COMMAND を評価する時に 40395 history -a && history -c && history -r を実行するとなるという事の様である。 40396 40397 色々実行しても倍加するタイミングが分からないのでもっと詳しく調べてみる。 40398 40399 | ble/textarea#render ble/textarea#redraw ble-attach source ~ 40400 | -rw-------. 1 murase murase 2994 2019-07-01 16:59:01 /home/murase/A.bash 40401 | ble/textarea#render ble-edit/bind/.tail ble-attach source 40402 | -rw-------. 1 murase murase 2994 2019-07-01 16:59:01 /home/murase/A.bash 40403 | ble/textarea#render ble-edit/bind/.tail ble-decode/EPILOGUE ble-decode/.hook 40404 | -rw-------. 1 murase murase 5988 2019-07-01 16:59:15 /home/murase/A.bash 40405 | ble/textarea#render ble-edit/bind/.tail ble-decode/EPILOGUE ble-decode/.hook 40406 | -rw-------. 1 murase murase 5988 2019-07-01 16:59:15 /home/murase/A.bash 40407 40408 どうも最初の epilogue の呼び出しの瞬間になる様である。 40409 うーん。history -a で倍加しているのだろうか。 40410 history -a は wskip を基準にしている。調べてみる。 40411 と思ったら wskip に関しては history 1 の出力と同期している様子である。 40412 40413 | ble/textarea#render ble/textarea#redraw ble-attach source 40414 | # Note: history 1 で何も出力されない 40415 | wskip=0 40416 | -rw-------. 1 murase murase 12010 2019-07-01 17:13:32 /home/murase/A.bash 40417 | -rw-------. 1 murase murase 12010 2019-07-01 17:13:32 /home/murase/A.bash 40418 | ble/textarea#render ble-edit/bind/.tail ble-attach source 40419 | 1088 bash 40420 | wskip=1088 40421 | -rw-------. 1 murase murase 12010 2019-07-01 17:13:32 /home/murase/A.bash 40422 | -rw-------. 1 murase murase 12010 2019-07-01 17:13:32 /home/murase/A.bash 40423 | ble/textarea#render ble-edit/bind/.tail ble-decode/EPILOGUE ble-decode/.hook 40424 | 2176 bash 40425 | wskip=1088 40426 | -rw-------. 1 murase murase 12010 2019-07-01 17:13:32 /home/murase/A.bash 40427 | -rw-------. 1 murase murase 24020 2019-07-01 17:13:35 /home/murase/A.bash 40428 40429 したがってこれは関係ない。先に history のリストの方が倍加している。 40430 という事は読み取りの方が問題になっているのだろうか。 40431 40432 | ble/textarea#render ble/textarea#redraw ble-attach source 40433 | history 1:declare -A _ble_builtin_history_rskip_dict=() 40434 | wskip=0 40435 | -rw-------. 1 murase murase 48051 2019-07-01 17:19:00 /home/murase/A.bash 40436 | -rw-------. 1 murase murase 48051 2019-07-01 17:19:00 /home/murase/A.bash 40437 | ble/textarea#render ble-edit/bind/.tail ble-attach source 40438 | history 1: 4355 bash 40439 | declare -A _ble_builtin_history_rskip_dict=([/home/murase/A.bash]="4355" ) 40440 | wskip=4355 40441 | -rw-------. 1 murase murase 48051 2019-07-01 17:19:00 /home/murase/A.bash 40442 | -rw-------. 1 murase murase 48051 2019-07-01 17:19:00 /home/murase/A.bash 40443 | ble/textarea#render ble-edit/bind/.tail ble-decode/EPILOGUE ble-decode/.hook 40444 | history 1: 8710 bash 40445 | declare -A _ble_builtin_history_rskip_dict=([/home/murase/A.bash]="4355" ) 40446 | wskip=4355 40447 | -rw-------. 1 murase murase 48051 2019-07-01 17:19:00 /home/murase/A.bash 40448 | -rw-------. 1 murase murase 96102 2019-07-01 17:19:01 /home/murase/A.bash 40449 40450 と思って rskip の方を出力してみるがこちらも問題ない。 40451 というかやはり history のリストが倍加している…。 40452 分かった気がする…。bashrc の中で history -r を呼び出すと、X行読み込まれて、 40453 更に最初の bind 呼び出しまでに更にデフォルトの動作として X 行が読み込まれる事になる。 40454 40455 大分特定できた。そもそもの原因は history -r を bashrc の中で呼び出すと、 40456 実際に対話モードに入った時に項目が二倍になってしまっているという事。 40457 うーん。最初に bind を受信した時に項目の数を rskip/wskip に記録するべきなのだろうか。 40458 しかし、そうしたとしても履歴ファイルの倍化が防げるだけであって、 40459 history や _ble_edit_history が二倍になってしまうという問題を防ぐことはできない。 40460 40461 a だとすれば bashrc の中での history に対する操作は全てキャッシュしておいて、 40462 その場では発動しない様にしておくという事が必要になるのだろうか。うーん。 40463 40464 b うーん。或いは bashrc の中で呼び出した ble-attach の場合には最後に history -c を実行してしまう? 40465 それと同時に ble/builtin/history/initialize に関してもデータを消去してしまう。 40466 うーん。対症療法的である…。実際にユーザが意図的に特別な履歴項目を予め読み込んで置きたいという時に問題になる。 40467 40468 c 或いは ble/builtin/history/initialize は具体的に履歴が読み込まれている時にのみ実行して、 40469 そうでない時には初期化せずに放置しておく事にする? と思ったが、それは解決にならない。 40470 結局 history -r よりも後に更に何らかの別の history -r を実行するとずれてしまう。 40471 40472 初回の bind の時に wskip を再設定するという事にするのが良いのかもしれない。 40473 うーん。綺麗な解決方法が見つからない。ble/builtin/history/.initialize が 40474 呼び出された後に Bash による history -r が暗黙で走る、という事が問題になっている。 40475 40476 d それならば history が呼び出される度に履歴項目の数を監視しておいて、 40477 勝手に増えたらそれは何らかの別の枠組みによって履歴項目が増えた物として、 40478 その分だけ wskip を増加させるという事にしてはどうだろうか。 40479 今 wskip が変化するのは read/write/delete の時だけである。 40480 40481 その様に実装するのであれば埒外の builtin history 40482 による履歴項目の変化は全て追跡する必要がある。 40483 40484 2019-06-27 40485 40486 * 2019-06-19 history: clipboard が全く効かなくなっている [#D1109] 40487 これは HISTSIZE を小さな値にすると発生する様子である。 40488 最近の変更が悪い訳ではない様に思う。 40489 emacs mode の時には問題は発生していない? と思ったら 40490 vi mode でも再現しない。うーん。発生条件がわからない。 40491 40492 これは .get-count の計算がずれるからだろうか。 40493 取り敢えず .get-count に関しては修正する事にして、 40494 それから .get-count を修正する事にする。 40495 40496 これは再現しないし、また HISTSIZE の取り扱いについて #D1108 で修正を行ったので、 40497 それにより解決した可能性もある。再度発現した時に対処する事にする。 40498 40499 * 2018-08-29 history: HISTSIZE に達した時の動作? [#D1108] 40500 40501 今気づいたが HISTSIZE に達した時、何が起こるだろうか。 40502 何かがずれるのではないだろうか…。 40503 と思ったが history コマンドを使うのは初期化時と履歴展開だけである。 40504 実は大した影響はないのではないかという気がしてきた…。 40505 40506 また、実は bash-4.3 以降では HIST{FILE,}SIZE に負の値を設定できる様だ。 40507 更に、それ以前から単に空文字列にしておけば無制限なのだそうだ。 40508 40509 →2019-06-19 実際に動作を確認してみた所、 40510 40511 % HISTSIZE に達しても履歴への登録が止まったり、 40512 % 古いものから順に削除されていくなどの動作はしない様だ。 40513 % だとすればそもそもHISTSIZEとは何だったのか…。 40514 % うーん。不思議だ。或いは初期化時の HISTSIZE に意味があるのだろうか。 40515 40516 と思ったら…。実は HISTSIZE に達すると番号を保持したまま 40517 先頭部分が削れていくという事の様だ…。 40518 40519 * fixed: だとすれば今までの history 1 による count の計測なども誤っていた事になる。 40520 うーん。修正するとすれば history に登録されている最初の項目の番号が必要になる。 40521 最初の項目の番号を取得する最も速い方法は何だろうか。 40522 history | head -1 だと 3 fork 必要になる。 40523 history を変数に入れると計算時間がかかる。 40524 と思ったが 13k 項目で 0.017s だった @chatoyancy 40525 それ程には時間はかからない。 40526 しかし history | head -1 の方が 0.007s と速い。 40527 40528 history 1 は4箇所で使用している。 40529 うーん。history | head をする位であれば 40530 history | wc -l で取得した方が速い。 40531 40532 * fixed: HISTSIZE に関連して history -p '!1' も危ないのではないか 40533 40534 先頭が削れた時に _ble_edit_history 等はどうしたら良いのか…。 40535 実は _ble_edit_history と builtin history は内容が異なっても良い? 40536 うーん。微妙である。例えば ble/builtin/history/option:d の実装は 40537 history の番号と _ble_edit_history の番号が一致している事を想定している。 40538 他にも考察が必要な箇所が幾らか見られる。 40539 40540 そもそも _ble_edit_history の内容をどの様にするかの可能性が幾つかある。 40541 40542 a history の番号と同じインデックスに記録する。 40543 40544 x 然し、これだと ble.sh をロードした時から history の offset が有限である場合に、 40545 offset までを空文字列で初期化しなければならない。 40546 40547 b history の内容と同期する。つまり HISTSIZE に達して先頭が削れた場合、 40548 _ble_edit_history も一緒に shift を実行する様にする。 40549 この実装の為には、現在の _ble_edit_history の先頭の項目の 40550 history における対応する番号を一緒に記録しておく必要がある。 40551 40552 x HISTSIZE に達すると毎回 shift が起こって効率が悪い。 40553 hook も毎回呼ばれる事になる。 40554 40555 そもそも大量にメモリを使用しているし、 40556 履歴によって多少メモリを追加で食らっても問題ない気がする。 40557 なので HISTSIZE に構わず現在までの履歴を全て記録しても良いのでは。 40558 40559 c history とは独立に _ble_edit_history の開始番号を記録する。 40560 40561 x 然し、これだと history -r で HISTSIZE よりも多い行数を読み取った時に、 40562 その上で読み取った行数の一部だけが _ble_edit_history に追記される。 40563 この時、_ble_edit_history に記録される項目の番号は連続でなくなる。 40564 つまりずれが生じてしまう。 40565 40566 d 或いは、末端からの行数で対応関係を取る事にする。 40567 つまり、history に於ける末端から N 番目の項目は 40568 _ble_edit_history に於ける末端から N 番目の要素と解釈する。 40569 この様にしておけば少なくとも history に現在ある項目に関しては、 40570 _ble_edit_history に於ける項目と正しく対応が取れる筈である。 40571 40572 取り敢えず d の方策で問題なく実装できるかについて確認する。 40573 40574 - option:d に関しては history の offset/count を取得して、 40575 削除範囲を限定する。そしてその後で対応する 40576 _ble_edit_history を削除する事にすれば良い。 40577 40578 うーん。取り敢えず ble/builtin/history に関しては対応した気がする。 40579 他に対応するべき箇所はあるだろうか。。。 40580 ble-edit/history/load は特に対応を取っている訳ではないので関係ない。 40581 40582 * 2016-07-07 history: HISTCONTROL=erasedups の時 ble-edit/history/add が遅いかもしれない [#D1107] 40583 40584 重複する項目がないかぎりはそんなに遅くないのではないかと思われる。 40585 何れにしても bash 配列において何が遅くて何が速いのかについて計測する必要がある。 40586 filter 部分の操作とそれから truncate の部分について。 40587 →benchmark-array.sh で filter を実装して試してみたが、 40588 実装の仕方でそんなに速度が変化するということはなかった。 40589 もっと巨大な配列の場合などでしか効かないという事だろうか。 40590 →しかし何れにしても実測してみたところによると 40591 重複する項目がある時はかなり重くなるという事が予想される。 40592 40593 というか unset して再度 arr=("${arr[@]}") したら速い気がする。 40594 →その方針で再実装した。遅い場合には 0.800 程度かかるのが 40595 0.120 程度に抑えられる事を確認した。もしかすると、 40596 項目数がもっとずっと大きい場合にはそれでも問題になるかもしれないが、 40597 従来の実装で遅くなるよりは格段に増しになっている筈である。 40598 40599 * 2019-02-07 history: history -nr [filename] に関しては履歴を idle で再初期化する? [#D1106] 40600 40601 特に追加項目の数が大量にある場合には background で初期化しても良いのかもしれない。 40602 これは bash 4.0 以降に於いて ble-edit/reset-history を呼び出せば良い。 40603 40604 では追加項目の数が何個以上の時に background で初期化を実行するべきか。 40605 % 取り敢えず delta>=_ble_edit_history_count/2 で判定する事にした。 40606 やはり delta>=10000 で判定する事にした。 40607 40608 * 2019-06-18 history: ble/builtin/history -r に時間がかかる [#D1105] 40609 40610 調べてみると eval に時間がかかっている。 40611 やはり mapfile 等を用いてロードし直した方が早いという事か。 40612 5000項目ロードするのに20秒かかっている。 40613 1秒で250項目である。0.1秒で25項目である。 40614 うーん。 40615 40616 結局、既存の ble-edit/history/load を拡張して、 40617 追加の項目を初期化できる様に変更した。 40618 動いている。 40619 40620 * 2019-06-19 history: ble/keymap:vi/mark/history-delete.hook の動作テスト [#D1104] 40621 一応動いている様な気がする。 40622 40623 x ずれが見られた…。試しに以下を実行してみると 40624 declare -a fire=([5]="B" [6]="C") となるべき所が 40625 declare -a fire=([0]="B" [1]="C") となってしまう。 40626 40627 $ fire[7]=1 40628 $ fire[9]=A 40629 $ fire[10]=B 40630 $ fire[11]=C 40631 $ declare -p fire 40632 $ ble/builtin/history/array#delete-hindex fire 5-10 40633 $ declare -p fire 40634 40635 調べてみた所 local shift=0 を宣言するのを忘れて shift を使っていた。 40636 前回の shift の値が使われていたという事だった。直した。 40637 取り敢えず一番最初にずれを見つけた例でも試して直っている事を確かめた。 40638 40639 まあ、これに関しては動いていると見做して良いという事にする。 40640 40641 2019-06-19 40642 40643 * 2019-02-07 history コマンドで出力される内容と、 [#D1103] 40644 ble.sh で管理している内容がずれてしまうという問題はある。 40645 ただ、それは現実的な問題になるだろうか。 40646 履歴展開を確認する場合には何れにしても history を使って番号を取得する。 40647 従って、内部の番号を参照する事になるはずである。 40648 40649 一方で history -d や history -r 等の操作を実行した時に、 40650 どの様に ble.sh の方を更新するのかという問題はある。 40651 通常の bash では確かにコマンドライン編集時に辿れる履歴も一緒に変更されている。 40652 40653 history の変更に際して何を修正するべきか。 40654 40655 * done: vi.sh において履歴項目ごとに記録している内容 40656 40657 | history に変化が現れた時の hook という物があった筈である。 40658 | それは何で何処から参照されていたか。 40659 | _ble_edit_history_onleave という配列がある。 40660 | これは onleave.fire で参照されている。 40661 | 去る直前に何らかの状態を記録するのに使われている。 40662 | 新しい行き先の情報は参照していない様である。 40663 | これを使っているのは ble/keymap:vi/mark/history-onleave.hook だけである。 40664 | そして ble/keymap:vi/mark/update-mark-history を呼び出している。 40665 | 特に _ble_keymap_vi_mark_history と _ble_keymap_vi_mark_global の中身を更新する必要がある様に思う。 40666 | その他の箇所で hindex を使用している箇所はあるだろうか。 40667 | history/get-index で検索すると他には ble/widget/vi-command/search.impl で使っているが、 40668 | これは移動したかどうかなどを判定する為に使っているだけで履歴に関する情報を記録するのには使っていない。 40669 40670 - _ble_keymap_vi_mark_history 40671 - _ble_keymap_vi_mark_global 40672 40673 _ble_keymap_vi_mark_global に関しては探索する必要があるので、 40674 やはり hook は削除範囲で指定する様にしたい。 40675 →ble/keymap:vi/mark/history-delete.hook に実装した。 40676 動作テストは一度も行っていない。適当な実装なのでテストは是非に行うべきである。 40677 40678 * done: edit.sh 40679 40680 以下の配列に対して作用すれば良さそう。 40681 - _ble_edit_history=() 40682 - _ble_edit_history_edit=() 40683 - _ble_edit_history_dirt=() 40684 - _ble_edit_undo_history=() 40685 最初の3つに関しては履歴をロードしている時にのみ更新する。 40686 最後の物に関しては履歴をロードしているかどうかに拘らず更新する。 40687 40688 _ble_edit_history 及び _ble_edit_history_edit に関しては対応しているが 40689 _ble_edit_history_dirt に関しては対応していない。 40690 40691 * ok: core-complete.sh 40692 40693 他に history/get-index を参照しているのは core-complete.sh だけである。 40694 dabbrev で履歴を遡るために使用している。 40695 履歴を遡っている最中に history によって履歴が書き換わる事はない筈なので、 40696 これについては気にしなくても良いだろう。 40697 40698 | history の操作としてどの様な物があるだろうか。 40699 | 40700 | * history -c は中身をクリアする 40701 | * history -d は項目を削除する 40702 | * history -n [filename] は追加行を読み込む 40703 | * history -r [filename] は履歴ファイルを読み込み直す 40704 | * history -aw [filename] は履歴データには変化なし 40705 | * history -p args... は一部の bash のバージョンで補正が必要 40706 | * history -s args... は項目を追加する 40707 | 40708 | 結構対応は面倒そうである。 40709 40710 * done: 2017-12-03 の項目も対応する必要がある 40711 * 2016-07-07/3 についても確認が必要 40712 40713 [実装] 40714 40715 * clear.hook も追加した。 40716 * 取り敢えず実装した様な気がする。 40717 40718 * 2017-12-03 keymap/vi (mark): BUG erasedup 等のときに履歴番号がずれるのではないか? [#D1102] 40719 40720 これは ble-edit/history/add/.command-history 辺りで callback 40721 を呼び出す様にするなどの方法にしなければならない。 40722 40723 ble/keymap:vi/mark/update-mark-history の仕様を観察すれば、 40724 erasedups 等に際してどの様に更新すれば良いかが分かる筈…。 40725 _ble_keymap_vi_mark_history の index をずらす。 40726 それから _ble_keymap_vi_mark_hindex を書き換える。 40727 -1 にでもすればよいか。 40728 40729 2019-06-18 40730 40731 * 2015-08-11 history コマンドで操作を実行したときにそれが ble の履歴情報に反映されない [#D1101] 40732 history コマンド自体を上書きするなどするとまたややこしいことになるので、 40733 ble-history 等のコマンドを用意してそちらを使ってもらうようにした方がよい。 40734 40735 或いは、もっと interactive に history 操作を実行できるようにしたい所である。 40736 →これは新しい項目で立てる事にする。 40737 40738 builtin history を置き換える。取り敢えず実装した様な気がする。 40739 動作確認はしていない。→うーん。history -r を実行すると時間がとてもかかる。 40740 40741 * 2019-06-11 history: ble/builtin/history/option:n の Bash 3.0 対策 [#D1100] 40742 そもそも history -r を用いると history -n の位置が変わってしまって変な事になる。 40743 history -r を使わずに履歴項目を何とかする方法はあるだろうか。。ない気がする。 40744 では history -n を使っても変な事が起こらない様にする方法? 40745 うーん。history -n を完全に自前で実装するというぐらいしか思い浮かばない。 40746 40747 或いは history -r $histfile 等として history -n の開始位置を再設定できないか。 40748 サブシェルに閉じ込めて history -r "$tmp" とすると本体には反映されない。 40749 history -r とすると大量の行が追加されてしまうのでそれらを削除しなければならない。 40750 history -d は一つずつ削除しなければならないので大変である。 40751 history -cr とすると再度全体に対する初期化を実行しなければならないので遅い。 40752 40753 a 或いは bleopt_history_share が設定されている時には history -n で読み取って、 40754 設定されていない時には history -r で読み取るという様にするか。 40755 しかし、そうすると bleopt_history_share が設定されていない状態から 40756 設定されている状態に変化した時に history -n で大量の行が追加されるという事になる。 40757 或いは bleopt_history_share の設定が変更される時に検出して 40758 bash 3.0 の時には再初期化を実行する事にするか。 40759 40760 というよりそもそも何故 Bash 3.0 では history -s が使えないのだったか。 40761 記録を探してみると #D0233 に議論が残っている。 40762 history -s をしても一番上の項目が入れ替わるだけなのだという。うーん。 40763 40764 改めて幾つか試してみる事にする。 40765 一つの bind -x の中で複数回 history -s をしてもやはり駄目だった。 40766 一番最後に実行した内容が登録されるだけだった。 40767 というかそもそも普通にコマンドを実行していても history -s は 40768 一番上にある履歴項目を置き換えるという動作しかしない様である…。 40769 40770 b やはり history -n の実装を置き換えるしかないのだろうか。 40771 history -n の実装を置き換える為に何が必要だろうか。 40772 先ず、次の読み取り位置を記録して置かなければならない。 40773 一番最初は初期化時の history count で良い。 40774 history -n を実行する度に行数を調べる。 40775 history -a を実行する度にインクリメントする。 40776 40777 要するに history -anrw を完全に ble.sh の物で 40778 置き換えてしまうという算段である。 40779 40780 * というより Bash 3.0 でなかったとしても、 40781 history -n の結果が history -r の影響を受けて変化するのは望ましくない。 40782 やはり Bash 3.0 かどうかに関係なく全て自分で処理してしまうという手の方が良いだろうか。 40783 つまり前回の history -n の際の行数を覚えておく。 40784 しかしどうやって記録するのだろうか。wc で数えるのだろうか。 40785 更に読み取る時には tail awk を用いて読み取る事になる。 40786 まあ、そういう実装でも良いのかもしれない。どうせ awk を起動するのだから 40787 余分に幾つかのプロセスを走らせてもそんなに大変ではないだろう。 40788 40789 もしくは awk で全て処理してしまうというのも手である。 40790 数を数えるという所から追加の行を配列に登録する所まで。 40791 40792 ? 一番最初のカウントはどうするのだろうか。 40793 もし bashrc でロードしているのであれば 40794 その時の bash_history の行数で問題ない。 40795 然しもし ble-attach によって後でアタッチしたのであれば、 40796 最後に読み取った位置というのは非自明である。 40797 40798 というより history を上書きするのは 40799 ble-attach ではなくて ble.sh をロードした瞬間である。 40800 ロードした瞬間に history -n で読み取ってしまうというのが手の様な気がする。 40801 40802 サブシェルで history -n で読み取られた内容をファイルに書き出して置く等。 40803 次に読み取る時には先に書き出して置いた内容を読み出して、 40804 その後で新しく追加された行を読み取る様にする。 40805 40806 連想配列の算術式に於ける展開について確認→OK 40807 $ tip='1]+a[1' 40808 $ declare -A arr=() 40809 $ arr[$tip]=12345 40810 $ arr[1]=10 a[1]=10 40811 $ echo $((arr[$tip])) 40812 20 40813 $ echo $((arr[\$tip])) 40814 12345 40815 40816 [実装] 40817 40818 * done: _ble_builtin_history_wskip 40819 ble.sh をロードした時に初期化するべき。 40820 その瞬間の histfile の行数にするか、 40821 或いはその瞬間の history 1 で得られる履歴項目の数か。 40822 これはその瞬間の histfile の行数と history 1 で得られる履歴項目の数 (0 より大きい時) で、 40823 より小さい方を採用するのが良い様に思われる。 40824 40825 * done: _ble_builtin_history_rskip[histfile] 40826 これも ble.sh をロードした時に初期化するべきである。 40827 これは $_ble_builtin_history_wskip と同じ行数で良い気がする。 40828 40829 うーん。ユーザが HISTFILE を設定し直す可能性もあるので、 40830 ble.sh をロードした時というよりは最初に ble-attach を実行した時だろうか。 40831 或いは、最初に ble/builtin/history にアクセスした時に初期化を実行するというのが良いだろうか。 40832 うーん。ble/builtin/history で最初に history 1 が有限の値を返した時にするか。 40833 これにするべき気がする。 40834 40835 * done: _ble_builtin_history_wskip 40836 履歴を削除したり erasedups で履歴項目が消滅したりした時に修正する必要がある。 40837 erasedups で項目が変更される場合については対応した。 40838 履歴を削除する場合に関しては。。これは history -d だけだろうか。 40839 history/option:d を実装した。history/option:c に於いても 40840 _ble_builtin_history_wskip=0 を実行するべきではないか。 40841 40842 現在の実装では _ble_builtin_history_wskip は項目が減った分だけ減らすという実装になっているが、 40843 本当にそれで良いのだろうか。 40844 wskip の位置が削除末端以降である場合にはそれで良いが、 40845 wskip の位置が削除開始位置以前にある場合には変化しない。 40846 また wskip の位置が削除範囲の内部にある場合には削除開始位置に移動する。 40847 →history/option:d と erasedups の処理でちゃんと wskip を処理する様に修正した。 40848 40849 x fixed: 依然として Bash 3.0 で .bash_history に追加された内容が重複して読み取られてしまう問題は残っている。 40850 うーん。試してみると Bash 4.4 でも同様に発生している。option:n で wskip をずらすのに失敗しているのか? 40851 そもそもちゃんとずらしていなかった。というより読み込んだ時に wskip を何処に設定するのかが非自明である。 40852 取り敢えず未書き込みの内容を histapp というファイルに記録しておいて、 40853 後の本当の write の際に書き込むことにした。 40854 →どうもちゃんと動いている気がする。 40855 40856 2019-06-10 40857 40858 * 2019-05-27 edit: .bash_history と常に同期する設定を ble.sh で提供しても良いのではないか [#D1099] 40859 40860 新しく追加された行を毎回読み込む様にする。 40861 40862 a 具体的には巷にある設定と同様にして history -r すれば良いのではないか。 40863 とも思ったが少し微妙かもしれない。巷にある設定だと history -c してから history -r している様な…。 40864 それだと ble.sh を実行している場合には毎回履歴を初期化しなければならなくなって面倒である。 40865 もっとコストの低い方法を考えても良いのではないかという気がする。 40866 40867 b 或いは、コマンドを実行する前に新しい項目が追加されていないかチェックする、という具合で良いのでは。 40868 新しい項目が追加されていたら追加分を履歴に反映させる様にする。 40869 40870 コマンドを実行する前というよりは newline を入れる度にという様にする方が良いかもしれない。 40871 或いはユーザ入力がある度に? もしくは履歴を参照しようとする度に? 40872 履歴を参照しようとする度にというのが最も妥当な更新のタイミングである。 40873 40874 ble.sh 独自の履歴ファイルを作ってしまうというのが一つの手の気がする。 40875 コマンドを実行する度にそのファイルに追記する。 40876 新しい履歴がある事をどのように他の bash に伝達するか。 40877 40878 a 一つの手は全ての Bash インスタンスに対して *.history_add.txt 的なファイルを用意して、 40879 或る Bash がコマンドを実行する時に *.history_add.txt に履歴を書き込むという物。 40880 b 或いは履歴ファイルの長さを覚えておいて増えた分を追加するという物。 40881 これを実行する為には mapfile -s などで読み飛ばす必要がある。 40882 mapfile のない古い Bash の場合には tail 等を使って切り出す必要がある。 40883 もしくは全て読みだした後で切り取るか…。 40884 何れにしても履歴が長大になってくると結局時間がかかってしまう気がする。 40885 c というか history -a, history -n で良いのでは? 40886 これだとうまく動かない等あるのだろうか。 40887 40888 history -a を実行するとちゃんと記録されている気がする。 40889 ちゃんと行数も増えている。次に history -n を調べる。 40890 うーん。hist_uniq.sh を実行した後で bash_history が縮まっている場合には読み込んでくれない。 40891 つまり Bash は前回の history の行番号を覚えているという事なのだろう。 40892 再度他の bash で history -a してから history -n すると読み込まれたので、 40893 前回の bash_history の長さというのは実際に読み込みが発生しなくても更新される。 40894 また bash_history が短くなっていたとしても現在の履歴が短くなるという事はない。 40895 40896 history -na の順番と動作についても確認する必要がある。 40897 どちらを先に実行したとしても Bash の実装が単純だと変な事になる気がする。 40898 40899 | * 例えば先に -n で新しい項目を読み込んでそれから -a で書き込むと、 40900 | どの範囲のコマンドが bash_history に書き込まれるのだろうか。 40901 | -n を実行すると新しく追加された行が history の末尾に読み込まれる。 40902 | うーん。色々試した所、以下の様な事が分かった。 40903 | 40904 | (1) Bash は最後に書き込みをしてから何個のコマンドを実行したかを記録している。 40905 | (2) history -n で読み取るのは最後に読み取った時の行数以降の行である。 40906 | この時に (1) で記録している情報の更新は行わない。 40907 | 40908 | これによって何が起こるかというと、 40909 | A個コマンドを実行した後に、history -n で N 個新しい履歴が読み取って、 40910 | 次に history -a する時と、history -n で読み取ったN個の項目と、 40911 | (A-N)個の自分で実行したコマンドが記録される事になる。 40912 | つまり、N個の自分で実行したコマンドが履歴に記録されずに終わる。 40913 | 40914 | * 或いは先に history -a して置いてそれから history -n で読み込むと何が起こるか。 40915 | →これは特に何も起こらなかった。つまり history -n では何も読み取られない。 40916 | →然し history -a する前に他の Bash プロセスから履歴項目が追加されている時には 40917 | また変な事が起こった。つまり、history -n で自分の追加したコマンドが重複して読み取られている。 40918 | つまり history -a で書き出す時に history -n の開始点がA個ずらされるという事の様に思われる。 40919 | 40920 | * Bash の動作は以下の様になっている? 40921 | 40922 | | var number_of_new_commands; 40923 | | var history_next_index; 40924 | | history -a 40925 | | history[-number_of_new_commands..$] を HISTFILE に書き出す。 40926 | | history_next_index += number_of_new_commands 40927 | | number_of_new_commands = 0; 40928 | | history -n 40929 | | HISTFILE[history_next_index..$] を history に読み出す。 40930 | | history_next_index += count; 40931 | 40932 | 書き換えると以下に等価である。 40933 | | var history_write_index; 40934 | | var history_read_index; 40935 | | history -a 40936 | | history[history_write_index..$] を HISTFILE に書き出す。 40937 | | history_read_index += count 40938 | | history_write_index = += count 40939 | | history -n 40940 | | HISTFILE[history_read_index..$] を history に読み出す。 40941 | | history_read_index += count 40942 | | history_write_index = += count 40943 | 40944 | 常に同じだけずれるのだとすれば。。 40945 | 実は最初の history と HISTFILE の差だけ記録しておけば良い事になる? 40946 | と思ったが、少なくともどちらかの変数は記録して置かなければならなくて、 40947 | それに加えて差を記録するという事になるので結局2つの変数を使う。余り意味ない。 40948 | 40949 | * 因みに history -an としたらどうなるのかと思って試してみたら、 40950 | history -anrw は何れか一つしか同時に使用できないというエラーメッセージになる。 40951 40952 動作に関しては #M0013 にまとめた。 40953 この動作を踏まえて history -a, history -n を上手に使って同期を実行する事は可能だろうか。 40954 40955 a 例えば必ず history -s の直前に history -n を実行する様にしたらどうだろう。 40956 そしてその直後に history -a を実行する。 40957 未書き込みのコマンドが存在しない状態で history -n を実行した場合には特に何も問題は起こらない。 40958 その上で history -s を実行して history -a を実行すると history -s した内容が書き込まれる。 40959 それで良い様な気がする。 40960 40961 また新しい履歴項目を追加する訳ではないが、 40962 新しい履歴項目が書かれていないかチェックする為には単に history -n とすれば良い。 40963 40964 * 次に HISTCONTROL に変な値が設定されていた時に history -n がどの様に動作するのかという事である。 40965 HISTOCONTROL=erasedups が設定されている時にコマンド command を実行すると、 40966 その時点で履歴の中に含まれている command が全て削除される。 40967 その他の重複するコマンドに関してはそのままである。 40968 history -n で読み取った場合は過去の一致するコマンドは削除されない、という事が分かった。 40969 単に追記されるだけである。という事であれば割合対応は簡単なのだろうという気がする。 40970 40971 * 他にチェックしなければならない項目として 40972 history -r 他ファイル を実行した後の history -n がどうなるかである。 40973 →うーん。履歴項目が倍化してしまっている…。 40974 つまり history -r を用いて履歴項目を増やす作戦は実は駄目。 40975 その後の history -n で駄目な事になってしまう。 40976 40977 history -r は Bash 3.0 で history -s が使えないのを補うのに使っている。 40978 その他の方法で history -s に相当する機能を実装するか、 40979 或いは history -n 以外の方法で新しい行を読み取る様にする必要がある。 40980 40981 うーん。Bash 3.0 では別の方法で history -n を実現する様にするか…。 40982 しかし、別の方法で実現するにしても history に関連する全てのコマンドを上書きしないと 40983 history -n で読み取り始める位置を特定する事ができない。 40984 うーん。結局毎回読み取る事になるのではないか…。 40985 →Bash 3.0 の時には history -n; histrory -a 戦略ではなくて、 40986 echo command >> "$histfile"; history -cr "$histfile" 戦略で行く事にする。 40987 と思ったがそうすると erasedups 等の設定で変更された履歴が全て消滅するので、 40988 結局改めて全ての履歴を読み出す事になってしまうのではないか。 40989 そしてそれは Bash 3.0 ではとても重いので避けたい操作である。 40990 40991 取り敢えずは c (history -na) を用いて実装する事にする。 40992 その他のタイミングでの同期に関しては別の項目で改めて実装する事にする。 40993 と思ったが早速実装が汚くなってしまう気がする…。 40994 40995 更に HISTINDEX_NEXT という物もあってこれも処理しなければならないのでは…。 40996 と思ったが、これに関しては history -n で項目が増えるだけである事を考えれば気にしなくても良い。 40997 40998 取り敢えずの所は Bash-3.0 の事は無視した実装で区切りをつける事にした。 40999 一応動いてはいる様である。しかし、やはり同期のタイミングが 41000 新しい行に移った時というのが分かりにくい。 41001 41002 2019-06-09 41003 41004 * 2019-06-07 progcomp: どうも bash は \= は COMP_WORDBREAKS の対象ではない様である [#D1098] 41005 確かにその様に動作するのが自然に思われる。 41006 41007 * 更に、これが意味する所は挿入時に COMP_WORDBREAKS 41008 に含まれる文字もエスケープする必要があるという事でもある。 41009 41010 現在の実装はどうなっているか。完全にクォート等を除去した上で処理している。 41011 処理を行っているのは以下の部分である。 41012 ble/complete/source:argument/.compvar-generate-subwords 41013 ble/complete/source:argument/.compvar-perform-wordbreaks 41014 41015 クォートをせずに裸で存在している COMP_WORBREAKS だけについて 41016 分割をするようにするにはどうしたら良いか。 41017 というより既に存在している関数でその様な物はあるだろうか。 41018 41019 うーん。評価まで一気にしてしまう実装ならば evaluate-path-spec に存在している。 41020 実のところ評価まで実行してしまっても問題ないのではないかという気もする。 41021 と思ったが各部分について評価を実行したいという事と noglob という事には注意する。 41022 notilde に関してはどの様に伝達すれば良いだろうか。 41023 41024 実際に実装を初めてみるとどうしたら良いのか分からなくなる。 41025 41026 * 先ず初めにパス名展開は起こすのか起こさないのかという事である。 41027 元の実装の場合にはパス名展開を起こした後に分割を行っていた。 41028 しかし元の単語の状態で分割を行うとすればパス名展開を起こす訳には行かない。 41029 41030 →これに関しては元の単語が単語分割の対象になっていればパス名展開を起こし、 41031 元の単語が単語片に分割されていればパス名展開は起こさないという方針にする。 41032 41033 或いは一番最後の単語片に関してだけパス名展開を実行する事にするか? 41034 41035 * 次の問題は補完開始点の対応をどの様に取るのかという事である。 41036 41037 古い実装に依ると補完開始点までの文字列を展開した結果から、 41038 新しい位置の補完開始点を算出するという事をしている。 41039 しかし、パス名展開が絡んでくるとこの方法で正確に対応を取る事ができるのかは怪しい。 41040 つまり、従来の方法でも既に問題はあったという事になる。 41041 41042 新しい実装ではどの様に実装するのが良いだろうか。 41043 取り敢えず一から考えてみる事にすると…。 41044 41045 そもそもパス名展開が起こるとしてもカーソルよりも後の位置に依存してはならない。 41046 という事を考えればパス名展開を考えるにしてもカーソルよりも後の位置は展開に関与してはならない。 41047 41048 1. カーソルが単語内部に存在している場合には、 41049 先ず初めにカーソルよりも左の部分と右の部分に分ける。 41050 これを left と right とする事にする。 41051 2. left と right のそれぞれについて COMP_WORDBREAKS を適用する。 41052 left が単語分割された時はそれぞれの単語片に対して eval-noglob を適用する。 41053 left が単一の単語片の時には eval を適用する。 41054 right に関してはそれぞれ eval-noglob を適用する。 41055 left と right を結合する。left の最後の単語片と right の最初の単語片は結合する。 41056 3. カーソル位置に関しては left/right を結合する時に、 41057 どの単語片のどの位置に対応するかが計算できる。 41058 4. 更に登録する際に quote があるとその分のカーソル位置補正が入る事に注意する。 41059 41060 何だか汚い実装だが仕方がない事だろうか。 41061 全体を作り直すという事も考えたが、 41062 処理として汚いかどうかではなく一つ一つの関数の機能として、 41063 分かりやすいかどうかが優先されるべきである。 41064 41065 * menu_complete: C-g でキャンセルすると何故か展開が実行されてしまう [#D1097] 41066 因みに確定をした時にはちゃんと前の展開が保持される。 41067 41068 更にエスケープ等も消えてしまう。 41069 調べてみると ble/complete/menu-complete.class/onselect で 41070 local insert=$_ble_complete_menu_common_part としているのが原因である。 41071 ここは menu_common_part ではなくて元々の文字列を指定するべきなのでは。 41072 41073 _ble_complete_menu0_comp を見たら良いだろうか? 41074 と思ったがこれは候補を一番始めに表示した時の値が入っていて、 41075 その後の補完や入力に依る絞り込みの状態を判定していない。 41076 _ble_complete_menu_comp を観察してみるとそれらしい値が入っている気がする。 41077 41078 menu_common_part に代入している部分を遡ってみると何れも COMPV を代入している。 41079 従って COMPV の代わりに COMPS を使う様にすれば良い筈である。 41080 そしてそれは ${_ble_complete_menu_comp[2]} に入っている気がする。 41081 41082 と思ったが本来 menu_complete を開始する時に元々の文字列を記録しているべきなのではないか。 41083 と思って調べてみると _ble_complete_menu_original にちゃんと記録してある。 41084 これを使うべきなのである。と思ったが menu-complete.class は必ずしも 41085 menu_complete の中からだけ呼び出されるとは限らない様だ…。 41086 41087 * 2015-06-28 color: --prefix=filename の filename 部分 (ref #D0839, #D0840, #D1095) [#D1096] 41088 単語に対して部分的な着色をする場合、現在の単語毎の着色ではない方法を考えるべき。 41089 → #D1095 で完全に対応した。 41090 41091 * 2019-04-21 syntax: ファイル名の着色でディレクトリ部分の着色を別にする事が可能なのではないか [#D1095] 41092 特に simple-word に於いて / で区切られる場合について 41093 各 pathspec に対しての展開を既に実装していた気がする。 41094 これを利用すればディレクトリ部分を切り離して着色する事が可能なのではないか。 41095 41096 また単語の途中で着色を変更する枠組みも既に用意してあった筈。 41097 41098 * 確か = または : の後だけファイル名着色する時に使っていた。 41099 と思ったら = または : の後にある単語の着色は有効になっていない…。 41100 これは 2015-06-28 から todo にずっと残っている項目である。 41101 41102 取り敢えず着色を行っている箇所を調べる事にする。 41103 実装は ble/highlight/layer:syntax/word/.update-attributes/.proc で行われている。 41104 単語着色の中でもファイル名の着色は特に ble/syntax/highlight/filetype を呼び出した後に行われている。 41105 41106 * fixed: ble/syntax:bash/simple-word/evaluate-path-spec の実装を確認する。 41107 glob がある時に failglob で全然駄目になる様な気がする…。 41108 取り敢えず修正してみる事にする。 41109 試してみたところやはり駄目だった。修正が必要である。 41110 修正した。動いている気がする。OK 41111 41112 * done: 一応単語の中に = や : が存在する時にはそれ以降をファイル名と解釈する様にした。 41113 41114 x resolved: しかしこれだとチルダ展開が起こらない文脈でもチルダ展開を前提とした着色になってしまいややこしい。 41115 →途中からの着色の場合 ATTR_TILDE が設定されていなければチルダ展開を抑制する事にした。 41116 41117 x fixed: 何故かチルダ展開を抑制しているのにチルダが着色される。 41118 というか echo '~' としてもチルダ展開が内部で実行されている気がする…。 41119 調べてみると filetype の中で明示的に ~ を処理している様だ。 41120 これは恐らく昔展開を実行する前のコードなので今は消して良いだろうと思われる。 41121 念の為呼び出し元を一つずつ確認していく事にする。 41122 41123 - core-complete.sh からの呼び出しでは CAND を渡している。 41124 CAND にはファイル名が入っていると考えている。 41125 チルダに置換して短縮した名前は INSERT の方に入っている筈である。 41126 - 他に core-syntax.sh ble/syntax/highlight/getg-from-filename 41127 からの呼び出しがある。これはやはり core-complete.sh から CAND 41128 を渡して処理する物である。 41129 - 他は現在の実装部分だけである。 41130 41131 x fixed: a= の形式の補完でディレクトリ名の後に / が挿入されないのは不便だ 41132 →うーん。原因が分かった。cand/yield file で a= の部分も一緒に渡すので、 41133 tail 設定のためのファイル名・ディレクトリ名判定が働かないのである。 41134 いや、yield というより最後の complete の時の処理である。 41135 これに関しては取り敢えず新しい action:file_rhs を追加して実装する事にした。 41136 41137 x filename/aaaa とした時に filename/ までが着色されてしまう。 41138 ファイル名はディレクトリとして取り扱えないのでこれは不自然。 41139 前置部分の着色をする時にはディレクトリかどうかのチェックを実行する事にした。 41140 41141 2019-06-05 41142 41143 * complete: = が含まれるファイル名について補完すると = より前の部分が重複する [#D1094] 41144 41145 例えば hello= という状態で補完しようとすると hellohello=... という 41146 候補が生成されてしまう。complete -r とすると治るので、 41147 これは bash-completion を呼び出す時の問題である。 41148 41149 | function ble/complete/minimal1 { 41150 | ble/debug/print-variables COMP_LINE COMP_POINT COMP_CWORD COMP_TYPE COMP_KEY COMP_WORDS >>/dev/pts/14 41151 | _minimal "$@" 41152 | ble/debug/print-variables COMPREPLY >>/dev/pts/14 41153 | } 41154 | complete -F ble/complete/minimal1 echo 41155 41156 先ずは bash のプログラム補完で呼び出した時の結果。 41157 41158 COMP_LINE='echo b=' COMP_POINT='7' COMP_CWORD='2' COMP_TYPE='9' COMP_KEY='9' COMP_WORDS=('echo' 'b' '=') 41159 COMPREPLY=('b=hello1' 'b=hello2' 'b=hello3' 'b=hello4' 'b=hello5' 'b=hello6' 'b=hello7' 'b=hello8' 'b=hello9') 41160 41161 ble.sh の枠組みで呼び出した時にはどうなるかというと。 41162 41163 COMP_LINE='echo b=' COMP_POINT='7' COMP_CWORD='2' COMP_TYPE='9' COMP_KEY='9' COMP_WORDS=('echo' 'b' '=') 41164 COMPREPLY=('b=hello1' 'b=hello2' 'b=hello3' 'b=hello4' 'b=hello5' 'b=hello6' 'b=hello7' 'b=hello8' 'b=hello9') 41165 41166 うーん。全く同じ結果になっている。という事は COMPREPLY を読み出して処理する側に問題がある。 41167 うーん。その後の処理でもやはり b=hello1 的な候補がちゃんと生成されている。 41168 これは挿入時の問題である様に思われる。 41169 41170 調べてみると progcomp_prefix が 41171 ble/complete/source:argument/.compvar-initialize で設定されている。 41172 41173 これに対して bash はどの様に動くのだろうか…。 41174 と思ったら変な動き方をしている。b=b\=hello という具合に補完されている。 41175 つまりどういう事かというと bash-completion の動作の方がおかしい。 41176 一方で = に対して b=hello という候補を生成している時に、 41177 ble.sh は = を b=hello に置き換える様に動作するが、 41178 bash は = の続きに "b=hello" を追記する様に動作している気がする。 41179 これに対する対策は必要になるだろうか、というか bash の振る舞いがどういう事なのか確認したい。 41180 例えば生成した候補が = で始まる場合にも = が重複して挿入されるのだろうか。。 41181 うーん。どうやら = が重複して挿入される様子である。 41182 41183 うーん。COMP_CWORD 及び COMP_WORDS を確認する限りは生成候補は '=' の補完に使われる様に見える。 41184 然し、実際には = の更に次に新しい単語があるとして補完が実行されている気がする。 41185 うーん。bash-5.0 も bash-3.2 も同様の動作である。 41186 41187 * done: 試していて気付いたが bash は連続する : や = を繋いで一つの単語としている。 41188 ble.sh では : や = を 1 文字ずつ全部分解して取り扱っている。 41189 ble.sh でも : や = を繋げて一つの単語片として取り扱う事にした。 41190 41191 取り敢えず bash-completion が動く様にするかどうかについては置いておく事にして、 41192 = や : がある場合にはその直後から補完を開始する様にする事にする。 41193 その為に空の単語片を登録する事にして、更にカーソルを偶数番目の単語片に属させる事とした。 41194 41195 以下にテストに用いた補完設定を残す。 41196 41197 | function ble/complete/minimal1 { 41198 | ble/debug/print-variables COMP_LINE COMP_POINT COMP_CWORD COMP_TYPE COMP_KEY COMP_WORDS >>/dev/pts/14 41199 | COMPREPLY=('b=world') 41200 | } 41201 | complete -F ble/complete/minimal1 echo 41202 41203 2019-05-28 41204 41205 * bash-3.0 で ^V^V^V^? を入力すると stackdump が出る [#D1093] 41206 bash-3.1 以降では再現しない。 41207 41208 stackdump: X1 0 <= beg:1 <= end:2 <= iN:1, beg:1 <= end0:1 (shift=1 text=) 41209 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:9125 (ble/syntax/parse) 41210 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:4 (ble-edit/content/update-syntax) 41211 @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:3954 (ble/highlight/layer:syntax/update) 41212 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:5 (ble/highlight/layer/update) 41213 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:9855 (ble/textarea#update-text-buffer) 41214 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:7295 (ble/textarea#render) 41215 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:3705 (ble-edit/bind/.tail) 41216 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:58 (ble-decode/EPILOGUE) 41217 @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (ble-decode/.hook) 41218 41219 どうやら文字列の長さが 1 になってしまっている様子である。 41220 本来期待するのは ^V^? という内容である。うーん。 41221 $ ble/util/c2s 127; v=^V$ret; echo "${#v}" 41222 の結果はちゃんと 2 になっているので本質的に対応が難しいという訳ではなさそう。 41223 quoted insert について調べる。 41224 41225 どうも edit.sh ble-edit/content/update-syntax で ble/syntax/parse を呼び出す時に、 41226 末尾にある ^? が消滅してしまうという問題が発生している様である。 41227 41228 $ bash-3.0 41229 $ function f1 { a=$'\177'; b=a$a; f2 "$b"; }; function f2 { echo "${#1}"; }; f1 41230 1 41231 $ bash-3.1 41232 $ function f1 { a=$'\177'; b=a$a; f2 "$b"; }; function f2 { echo "${#1}"; }; f1 41233 2 41234 41235 うーん。つまり bash-3.0 では全般に引数として ^? で終わる物を渡す事ができないという事になる。 41236 workaround について試してみたが、"$b""" としても"""$b""" としても駄目であった。 41237 $b と裸で引数に渡してみたら大丈夫だったが、これだと空白類やグロブ文字を含んでいる時に駄目である。 41238 41239 a 代替手段として ^? を入力したい場合には 41240 bash 3.0 では別の Unicode 文字を入れるという手もあるかもしれない。 41241 実行する時にだけ ^? に置換して実行を行う。 41242 うーん。可也汚い方法ではあるが動かない事はないのではという気がする。 41243 面倒なのは文字幅や表示を ^? に変換するという処理が必要な事。 41244 41245 x 然し、そうしたとしても bash_history に記録されている ^? もある。 41246 これも全て変換するとするととても面倒である。 41247 x また、入力文字列以外のあらゆるユーティリティ関数についても 41248 ^? に対する処理に問題があるという事になり、 41249 これは入力された文字列の表現を変更してもどうにもならない。 41250 x 代替文字に対して s2c を実行した時の振る舞いも変更しなければならない。 41251 41252 b 或いは bash-3.0 では単に ^? の入力を無効にするか。 41253 元々 ^@ は入力できないのだからそれと似たような意味の 41254 ^? も入力できなくて仕方がないのではないか。 41255 41256 中途半端な対応をしても仕方がない気がする。 41257 一応単純な対策として b を採用する事にする。。 41258 41259 2019-05-27 41260 41261 * 2019-05-24 edit: 実は rlvar bind-tty-special-chars で C-u C-v C-w の bind の振る舞いが変わる? [#D1092] 41262 http://lists.gnu.org/archive/html/bug-bash/2019-05/msg00069.html 41263 41264 →これに対する workaround は既に @decode.bind.uvw で実行している。 41265 既にこの rlvar の設定がどうなっていたとしても動作する様になっているので、 41266 わざわざ現在の workaround を bind-tty-special-chars の設定に置き換える必要はない。 41267 然し、この rlvar の動作については確認しておく必要がある。 41268 41269 一応 rlvar bind-tty-special-chars の設定を変更した時の振る舞いについて調べて、 41270 (設定を変更した時にこの workaround が不要になるのかどうか、 41271 また設定を変更した時の現在の workaround が動作しなくなったりしないか) 41272 それで問題がなければ注記として残してこの項目は解決した事にすれば良い。 41273 41274 | うーん。今確認すると manual attach にしてもしなくても uvw の対策無しで動いて見える。 41275 | % uvw の中で builtin bind -X | grep '[UVW?]' を実行してみると bind されていない。 41276 | % 対策を施した直後でも bind されていない。これはどういう事か。 41277 | % 実は UVW? では捕まえられない?→ grep 'C-[uvw?]' にしたらちゃんと取れた。 41278 | % 何れの場合でも少なくとも表面上は取れている。 41279 | 41280 | bind 'set bind-tty-special-chars on' にしても off にしても bind の変化はない。 41281 | どうも bind-tty-special-chars が追加されたのは bash-3.1 の様である。 41282 | 然し bash 3.0 で試しても特に問題が発生している様子は見られない。 41283 | 41284 | #D0003 を確認すると別の関数に配置した時点で問題が発生しなくなったという様に書かれている。 41285 | つまり現在の実装では実は問題になっていない、という事なのだろうか。 41286 | しかし #D0329 を確認してみると問題が発生していた様である。 41287 | Bash 4.3 で再現した。Bash 4.4 でも再現した。 41288 | 41289 | builtin bind -X は一度 bind されると xmap に情報が残ってしまうので確認には使えなかった。 41290 | 実際には bind -p を使って確認する必要があったのである。 41291 41292 試してみたところ set bind-tty-special-chars on の時には ^U ^V ^W ^? の上書きが必要になった。 41293 つまり self-insert が勝手に設定されている。 41294 set bind-tty-special-chars off の時には特に必要ない様である。 41295 何れにしてもこの設定の変更によって何か問題が起こることはないようだ。 41296 41297 * 2019-05-09 edit: source ble.sh (--attach=prompt) だと source に使ったコマンドの履歴が残らない? [#D1091] 41298 というかコマンド履歴が一切無効化されている気がする? 41299 41300 うーん。そのセッションのコマンド履歴は全て消える。 41301 --attach=none にして ble-attach しても再現する。 41302 --attach=none にしてそのまま抜ければ記録される。 41303 41304 bashrc からロードしてその上で ble-reload しても大丈夫。 41305 41306 attach 処理の中のどの時点で問題が発生する様になっているのか特定して、 41307 それで原因を探し当てるのが最初にするべきことの様に思われる。 41308 41309 * 試しに ble-edit/reset-history の中の ble/util/idle.push 'ble-edit/history/load async' 41310 という部分を無効化してみたが変化はなかった。やはりコマンド履歴に記録されない。 41311 * 以前 HISTSIZE 関連で変な workaround を実行していた様な気がしたので調べてみたが、 41312 今回の場合には関係なさそうである。該当コードは ble-edit/history/load/.background-initialize 41313 でありコメントに色々と書かれている (#D0702, #D0732) が結局、様々の問題の為に 41314 サブシェルで履歴項目の処理を行う事にして HISTSIZE は弄らない方針に変更されたのであった。 41315 * そもそも履歴に登録されているのだろうか。という事を調べる必要がある。 41316 色々 history | tail を実行してみるとこの時点で振る舞いがおかしいという事が分かった。 41317 履歴項目が消滅している気がする…。 41318 41319 | $ bash --norc 41320 | $ source out/ble.sh --attach=none 41321 | $ history | tail 41322 | 14370 screen -ls 41323 | 14371 screen -dr 41324 | 14372 bind -v 41325 | 14373 echo hello1234 41326 | 14374 echo world4321 41327 | 14375 history | tail 41328 | 14376 echo test1234 41329 | 14377 history | tail 41330 | 14378 source out/ble.sh --attach=none 41331 | 14379 history | tail 41332 | $ echo 1234 41333 | $ echo 4321 41334 | $ echo 1111 41335 | $ history | tail 41336 | 14374 echo world4321 41337 | 14375 history | tail 41338 | 14376 echo test1234 41339 | 14377 history | tail 41340 | 14378 source out/ble.sh --attach=none 41341 | 14379 history | tail 41342 | 14380 echo 1234 41343 | 14381 echo 4321 41344 | 14382 echo 1111 41345 | 14383 history | tail 41346 | $ ble-attach 41347 | $ history | tail 41348 | 14373 echo hello1234 41349 | 14374 echo world4321 41350 | 14375 history | tail 41351 | 14376 echo test1234 41352 | 14377 history | tail 41353 | 14378 source out/ble.sh --attach=none 41354 | 14379 history | tail 41355 | 14380 echo 1234 41356 | 14381 echo 4321 41357 | 14382 echo 1111 41358 | $ echo 9999 41359 | $ history | tail 41360 | 14365 bind -x '"\C-@": "echo abc"' 41361 | 14366 command 41362 | 14367 screen -ls 41363 | 14368 screen -dr 41364 | 14369 screen -dr 41365 | 14370 screen -ls 41366 | 14371 screen -dr 41367 | 14372 bind -v 41368 | 14373 echo 9999 41369 | 14374 history | tail 41370 41371 この時点で 14372 番目まで履歴が削れてしまっている。 41372 特に 14373--14377 は bash_history から読み取った物の筈である。 41373 これ以降に実行したコマンドは普通に登録される様である。 41374 41375 うーん。history -s -- "$cmd" をコメントアウトしたら余計に酷い事になった。 41376 どんどん履歴が削れてなくなっていく…。 41377 前に似たような事があった。と思って調べると bash-3.1 以下の時の 41378 ble/edit/hist_expanded/.core で対策が書かれている。 41379 試しに bash 3.1 以降での処理をサブシェルにしてみた所、 41380 問題は起こらなくなった。履歴もちゃんと記録されている。 41381 つまり Bash-4.4 でも Bash 3.0 と同様の問題が起こるという事。 41382 41383 % Bash 5.0 では再現するだろうか。と思って試したら再現しない。 41384 % というか Bash 4.4 でも再現しなくなった。 41385 % 何か特別な履歴項目の数などがあるのだろうか。。 41386 % screen の記録を探ると以下の .bash_history の内容で再現していた筈。 41387 % 41388 % $ tail ~/.bash_history ble.sh master (2e6f44c) 41389 % screen -dr 41390 % screen -dr 41391 % screen -ls 41392 % screen -dr 41393 % bind -v 41394 % echo hello1234 41395 % echo world4321 41396 % history | tail 41397 % echo test1234 41398 % history | tail 41399 % 41400 % .bash_history の内容を削って再度試してみる事にする。 41401 % うーん。再現しない。と思ったら history の内容が追記されて増えていた。 41402 % また減らして調べる必要がある。減らしてみたら再現した。 41403 % 41404 % うーん。複数の要素が絡み合っているので再現するかどうか判定する為には 41405 % 一時的に history -s を無効にしておかなければならない。 41406 % というか寧ろ history 1 を繰り返し実行しても変化しないという事こそが 41407 % 再現しているという事の証拠になっているのでは? とも思ったがよく分からない。 41408 41409 Bash-3.1 -- 5.0 の全てで再現する事を確認した。 41410 結局 Bash 3.0 で使っていたのと同じ workaround で 41411 問題が解決できる事が分かったのでそれを使う事にする。 41412 41413 うーん。履歴項目が消滅する問題については解決されたが、 41414 履歴が保存されないという問題に関しては未だ残っている。 41415 というより、今迄問題なかったのが新しく問題になっている気がする。 41416 改めて調べる。history -r を使って履歴項目を追加したのは 41417 Bash 3.0 が history -s を持っていない (or 動かない) 為であろう。 41418 history -s -- "$cmd" をしている箇所でも Bash 3.0 は特別扱いしている。 41419 41420 今回の workaround でも Bash 3.0 以外では history -s で項目を追加する事にした。 41421 Bash 3.0 に関しては history -r してもどうせ自分で histfile に記入するので問題にならない。 41422 実際に動かしてみた。問題なく動いている。OK 41423 41424 2019-05-09 41425 41426 * main: bashrc から起動すると read が使えたり使えなかったりする [#D1090] 41427 具体的には vbell を表示するタイミングで read が終了してしまう。 41428 41429 - bashrc から起動すると --attach=prompt, none に関係なく駄目。 41430 - bash --norc で起動してから source すると大丈夫。 41431 --attach=prompt, --attach=none に関係なく大丈夫。 41432 - ble-reload を実行すると治る。 41433 41434 調べてみると ble/util/visible-bell の内部で死んでいる。 41435 うーん。再現性が分かった。一度でも外側で vbell を呼び出していれば問題は起こらない。 41436 41437 うーん。failglob っぽい。どうもサブシェルの中だと failglob を eval で防げない様だ…。 41438 サブシェルの中では shopt -u failglob してしまう事にする。 41439 41440 * edit: うーん。リサイズした後のカーソルの位置がおかしい [#D1089] 41441 ちゃんとテストしておくべきだった。何度も似たような修正を繰り返している…。 41442 41443 所で read の方の TRAPWINCH は大丈夫だったのか。 41444 確認すると大丈夫の様な気がする。所で vim mode の時の read はどういう振る舞いをするのだったか。 41445 41446 * edit: 後気付いたのはプロンプトの途中で改行が起こっている時に座標計算が正しくない [#D1088] 41447 これについても本来対応しているつもりだったが何かを間違えているのだろう。 41448 座標計算がどの様にされているか確認する。 41449 41450 うーん。COLUMNS が 20 であるのにも関わらず x が 30 になっている…。 41451 分かった…。結果がキャッシュされていた。座標計算をする時には COLUMNS の幅も影響するので、 41452 それも一緒に比較するべきだった。 41453 41454 うーん。考えた末に COLUMNS を version の一部に含めれば良いだけだと気付いた。修正する。 41455 と思ったが効果はなかった。チェックが二段階になっている。先ず version が同じだったらスキップする。 41456 更に expanded の値が同じだったらスキップする。 41457 41458 これを修正したら色々と他にも直った。今まではリサイズした後の rps1 の位置が 41459 なにかコマンドを実行するまでおかしかったのがちゃんと再計算される様になった。 41460 41461 * edit: read -e でベルを鳴らした後に C-c で終わると [#D1087] 41462 ref #D1000 41463 41464 沢山のジョブ終了通知が現れる。というより C-c でなくても終了すると現れる。 41465 そもそも普通の状態ではベルをどの様に抑制していたのだったか。 41466 41467 うーん。結局 ( ... & ) の形にすれば大丈夫と思っていたのが、 41468 $() の中で更にそれを実行すると駄目になってしまうという事か。 41469 read の $() の中でジョブ管理を無効にしたらどうなるか。 41470 と思って確認したら既に無効にする行が書かれていた。set +m である。 41471 41472 % うーん。read は寧ろ bell が発生すると終了する様になってしまっている。 41473 % 0.4.0-devel1+ab8dad2 である。一方で動いている version は… 41474 % 0.4.0-devel1+ab8dad2 である。変だ。書き換えたのは WINCH だけである…。 41475 % もしかすると BLE_VERSION の抽出を間違えたのかもしれない。 41476 % 0.4.0-devel1+b52da28 41477 % 0.4.0-devel1+799f6d3 41478 % 0.4.0-devel1+467b7a4 41479 % 41480 % 直前までやはりちゃんと動いていた。新しく起動すると駄目になるのだろうか。 41481 % →何と新しく起動した ble-0.3.0 でも動かなくなっている。 41482 % という事は何か設定項目の変更が関係しているという事だろうか。 41483 % うーん。ble-dev で checkout して source すると変な事は起こらない。 41484 % キャッシュが破壊されているという事なのだろうか。。 41485 % 41486 % うーん。bash --norc してから source ble.sh しても動いている。 41487 % つまり、attach 戦略が行けないという事なのだろうか…。 41488 % どうも --attach=prompt で attach すると駄目という事の様だ。 41489 % 何故だろうか。 41490 41491 まとめると。症状は bashrc から --attach=prompt で ble.sh に入ると 41492 read -e をした時に visible-bell を実行しようとした時点で終了してしまう。 41493 % 取り敢えずこの問題は別の問題であるので manual attach を使って 41494 % 先に簡単そうな問題の方を片付ける事にする。 41495 と思ったら駄目だった。普通に ble-attach で attach しても駄目になった。。 41496 再現性がよく分からない。不安定である。 41497 41498 何れにしても source ble.sh した場合には問題が発生しないので、 41499 それで試してみると set -m でも +m でも関係なくメッセージは表示される。 41500 もう面倒なので visible-bell のタスクに関しては個別に判定して表示しない、 41501 という様にしてしまう事にする。 41502 41503 % その様に書き換えたが全く検出できていない。何故? 41504 % →実は ble.sh/out/ble.sh ではなくて ble-dev のをロードして試していた。 41505 % ちゃんと正しいのをロードして試したら検出できている。 41506 41507 * reject: うーん。というか実は disown してしまえば良いのでは? 41508 と思ったが前回検討した時に disown は試した様な気もする。 41509 と思って調べると #D1000 に記録があって今回の問題と同じ問題について議論していた。 41510 何故解決されていないのかと思って見ると、長いメッセージを短くしただけで満足していた。 41511 完全に表示されなくするのは諦めていたのである。 41512 41513 % うーん。disown してみたら表示はされない様になった。 41514 % 実は visible-bell の側で特別の判定をする必要はなくなった。 41515 と思ったらジョブ名の判定方法が誤っていて全てのジョブを表示しなくなっていただけだった。 41516 改めて試してみたら disown はまるで効果がないようだと分かったので使わない事にする。 41517 41518 * resolved: 然し、別の問題として入力を完了しても visible-bell の 41519 子プロセスが終了するまではプロンプトが戻るまで待たされる。 41520 これは disown してもしなくても再現する。うーん。 41521 41522 % この遅延時間をなくすにはどうしたら良いのか。 41523 % 子プロセスの pid を記録しておいて一気に kill するのか。 41524 % 然し、それだと子プロセスの pid と同じ pid の新しい関係ない 41525 % プロセスを殺してしまうかもしれない。 41526 % 41527 % kill に負の PID を指定すればまとめて消してくれるのではなかったかと思って調べたが、 41528 % これは PGID を同じくする物を全て殺すようだ。そしてサブシェルを同期的に動かしている内は 41529 % 親と同じ PGID になっているので使えない。もし使えたとしても、 41530 % 41531 % 或いは調べると ps を使って自分で子プロセスを列挙して kill するという手があった。 41532 % ps は posix のコマンドではない気がする。と思ったらあった…。 41533 % 41534 % ps -o ppid,pid 等として探し出せば良いのだろうか。。 41535 % 41536 % 調べると ppid が 1 になっているプロセスたちがいる。これらを殺せば良いという事だろうか。 41537 % と思ったが、それだと別の disown になっているプロセスたちを殺してしまうのではないか。 41538 % さて確認してみた所 disown していなくてもサブシェルから & で立ち上げたプロセスの親は 1 41539 % になっている。そして新しい PGID を形成しているという事も分かった。 41540 % これはなぜかというと ( ... & ) で起動している為に外側の () が先に消滅するからである。 41541 % という事を考えると、うーん。検出方法が分からない。( ... & ) をやめるのは面倒である。 41542 % 41543 % ? yes: というか、これは本当に visible-bell 関係の遅延なのだろうか。 41544 % →確認してみた所 vbell がない時にはちゃんと一瞬で read が終了している。 41545 % 41546 % ? というか kill を実行したとしても SIGTERM だと sleep しているので届かないのでは。 41547 % SIGKILL する必要があるのでは。色々問題が在る。 41548 % 41549 % ? no: 実は普通にログアウトする時にもそういう遅延があるのではないか? 41550 % 試してみたらログアウトする時には遅延はなかった。 41551 % 41552 % どういう構造になっているのか。 41553 % 41554 % result=$(sleep 10 & echo hello) でブロックされてしまうという事を確認した。 41555 % それで検索してみると似たような質問が見つかった。 41556 % https://stackoverflow.com/questions/16874043/bash-command-substitution-forcing-process-to-foreground 41557 % うーん。成る程… $() は標準出力が消えるのを待っていて、 41558 % sleep 10 が標準出力を保持し続けるのが悪いという事。 41559 41560 標準出力を $() が待ち続けるのが悪いということが分かった。visible-bell は 41561 全て >&2 に対して実行しているので 1 は閉じてしまって問題ない。 41562 41563 2019-05-06 41564 41565 * 2019-04-21 decode: key code の更新が実行されていない。うーん [#D1086] 41566 これは単にバグのあったバージョンを使っていた所為かもしれないと思ったが、 41567 修正直後のバージョンを使っている様だった。うーん。 41568 今後は強制的に全て更新する様に調整した方が良いのかもしれない。 41569 あるいは、init-cmap で全て更新する様に調整する。 41570 一応 touch vi.sh emacs.sh init-cmap.sh としたら動く様になった。 41571 41572 やはり問題が発生する。更新のタイミングが悪いのかと思って 41573 $_ble_edit_cache の中のファイルと init-cmap.sh のタイムスタンプを確認する。 41574 ちゃんと正しい順序で更新されている様に見える。 41575 という事は問題になっているのは keyname2code の変換をしている関数の 41576 キャッシュが残っている等の事なのだろうか。 41577 41578 うーん。分かった。配列を初期化する時にちゃんと空にしておかなければならなかったのだ。 41579 41580 * edit: ウィンドウをリサイズした時に info が消えたままになる [#D1085] 41581 41582 2019-05-04 41583 41584 * decode: mouse が有効になっていると大量のシーケンスが送られてくる [#D1084] 41585 完全に対応はしなくても少なくともデコードはしなければならない。 41586 そもそも mouse を keyseq の一員と見做して処理して良いのだろうか。 41587 例えば C-x まで入力してその瞬間にマウスに触ってしまって mouse move が起きた時に、 41588 シーケンスがなかった事になって良いのだろうか。 41589 41590 一方で、シーケンスの途中として使いたいという場合も実はあるのではないか。 41591 例えば vim の normal mode で y としてそれからマウスで行き先の位置をクリックして、 41592 其処までをコピーするという動作として取り扱っても良いのではないだろうか。など。 41593 然し、何だか分かりにくい。やはりそういう変なのはやめた方が良いのでは。 41594 41595 一方で、keyseq を入力している途中でマウス等により編集位置が変化した時、 41596 果たして keyseq は有効のまま続きを入力できても良いのかというのも分からない。 41597 うーん。まあ続きが入力できても良い気もする。 41598 或いは、入力途中の keyseq は消去してしまっても良い気もする。 41599 41600 うーん。望ましい動作は、 41601 (1) マウスの移動に際しては keyseq と独立に処理する。 41602 (2) マウスの押下や解放や選択やドラッグに関しては、 41603 既存の keyseq を消去して処理する。という事。 41604 41605 ? yes: 一般のアプリケーションでも上が望ましい動作だろうか。 41606 然し、本当にそうだろうか。現状ではマウスを使って操作するという状況が分からない。 41607 まあ、編集位置の移動や選択ぐらいである。本当にマウスを使って効果があるのは、 41608 もっと GUI っぽいアプリケーションなどを作成した時なのではないだろうか。 41609 例えば life game を実装したとする。クリックした位置に新しく点を打ったり、 41610 ドラッグした範囲を乱数で初期化したりなどができると面白いと感じる。 41611 そういう状況に於いての望ましい動作はラインエディタとしての望ましい動作と同じだろうか。 41612 マウスの移動に関して独立に処理するのもそうだろうと思うし、 41613 また、マウスの押下や解放があった場合にそれまでの keyseq を棄却するというのも良い気がする。 41614 →結論: つまり、その他の一般の用途であっても上記の様な動作で良いという様に思われる。 41615 41616 それを踏まえて考えるとやはり mouse という単純なキーではなくて、 41617 mouse mouse_up(m) mouse_drag(32) mouse_select(t) mouse_move(35) wheel(64) 41618 ぐらいの区別はあって欲しいように思われるのである。 41619 41620 取り敢えずドラッグ・移動に関しては独立に処理する事にした。 41621 うーん。(2) の既存の keyseq の消去に関しては対応していないが、 41622 まあ、mouse up/down/select/wheel ぐらいはそんなに沢山送られてくる物でもないので気にしない。 41623 後は具体的にこれを利用したものを書く機会があった時に、 41624 その需要に合わせて調整すれば良い。 41625 41626 2019-05-02 41627 41628 * decode: S8C1T かつ DECCKM の時のキーシーケンスに対応 [#D1083] 41629 contra の fuzzing で生じた状態でキー入力ができなくなったので。 41630 確かに CSI シーケンスの時は C1 を解釈していたが、 41631 個別に登録しているシーケンスに関しては 8bit C1 を解釈していなかった。 41632 ちゃんと 8bit 表現も一緒に登録する様に修正した。 41633 41634 2019-05-01 41635 41636 * syntax: 何と、fi の直後のコマンドは改行を隔ててもエラーのまま… [#D1082] 41637 CTX_CMDXE がずっと生きている様だ。 41638 試してみると ble-0.2 でも再現している。 41639 つまり、ずっとバグがありながら気づいていなかったという事になる。 41640 ble-0.1 では再現しない。ble-0.3 では当然再現する。 41641 実は CTX_CMDXE に対応した瞬間からずっとバグが残っていたという事なのか? 41642 取り敢えず修正した。すぐに問題の箇所は見つかった。 41643 また他の文脈値に関しては大丈夫そうに思われる。 41644 41645 * main: ble-update で更新の必要がなかった時の終了ステータス (suggested by cmplstofB) [#D1081] 41646 41647 https://twitter.com/cmplstofB/status/1123552437963329537 41648 > @akinomyoga こんばんわ。PRする程でもない提案なので,Twitterで失礼します。 41649 > bleshのble-updateコマンドは何も更新が無い時に終了値1で〝失敗〟しますが, 41650 > 個人的にこの挙動に違和感を覚えます。例えばdnfコマンドは,`dnf upgrade`と 41651 > 実行したときにパッケージの更新が無くても失敗しません。 41652 41653 確かに dnf も git pull も更新の必要がなかった時には成功する。 41654 そして ble-update が明示的に失敗するのは repository が見つからなかった場合や 41655 その他、失敗しないと想定している操作が失敗した時のみである。 41656 なので、更新の必要がなかった場合には成功する事にする。 41657 41658 * complete: cygwin で存在しないコマンド名を打つと遅い [#D1080] 41659 以前何か修正した筈なのに何故なのかと思って調べたら異なる原因だった。 41660 Cygwin では compgen -c -- '' 自体が物凄く遅い。2.6s かかっている。 41661 遅い計算機ではもっと遅くなるだろう。更に曖昧補完の場合には、 41662 no_empty_command_completion による予防もすり抜けてしまう。 41663 41664 先ず、no_empty_command_completion を設定する事にして、 41665 更に no_empty_command_completion がなくても遅くならない様に修正する事にした。 41666 41667 2019-04-29 41668 41669 * main: うーん。ble-update したら駄目な事になった [#D1079] 41670 (#D1077 に対する修正) 41671 41672 keymap=auto のロードに失敗する。 41673 誤った代入ですというエラーメッセージが先ず表示される。 41674 41675 取り敢えず keymap.emacs を削除して実行すると問題が発生する事は確認した。 41676 41677 * done: 先ず "safe" keymap を使います、というエラーメッセージが表示を乱している。 41678 取り敢えずエラーメッセージが表示されても表示が乱れない様に修正した。 41679 41680 と思ったが端末の画面の一番下の行にいる時に正しく領域を確保する事ができていない。 41681 本来は高さを設定する時に LF で領域を増やさなければならないのではないか。 41682 と思って調べたがこれは ble/util/buffer の flush の都合だった。直した。 41683 41684 * それから何故失敗するのかについても調べる必要がある。 41685 _ble_decode_keymap_list に vi_imap が登録されていないという事の様に見える。 41686 何と $_ble_decode_keymap_list を確認してみると :vi_digraph だけしか登録されていない…。 41687 41688 * bash-5.0 で reload を 2 回実行すると以下の様なエラーメッセージが出る [#D1078] 41689 41690 $ source out/ble.sh 41691 readline: "\C-\\\": self-insert: no closing `"' in key binding 41692 readline: "\C-\": self-insert: no closing `"' in key binding 41693 41694 Bash-4.4 では再現していない。確認すると 41695 /tmp/blesh/1000/16071.bind.save の中身が変になっている。 41696 内容を生成しているのは ble/decode/attach/.generate-source-to-unbind-default/.process である。 41697 食わせるデータを出しているのは ble/decode/attach/.generate-source-to-unbind-default (#2) である。 41698 #2 に対して介入してどの様なデータが出力されているかを調べる事にする。 41699 41700 うーん。何と Bash-5.0 の bind -p 時点で何故か "\C-\\\" や "\C-\" という内容を出力している。。 41701 うーん。bind '"\C-\\": set-mark' を試してみた所、"\C-\\\" は再現した。 41702 "\C-\" がどうやって現れるのかについては分からない。まあ、何れにしても bash-5.0 が悪いのだ。 41703 更に言うと何故 self-insert なのかも不明である…。と思ったがこれは恐らく vi mode だからだろう。 41704 vi mode で実行したら再現した。 41705 41706 $ bash-5.0 --norc 41707 $ bind -p | grep '"\\C-\\' 41708 $ bind '"\C-\\": self-insert' 41709 $ bind -p | grep '"\\C-\\' 41710 "\C-\\\": self-insert 41711 41712 $ bash-5.0 --norc 41713 $ set -o vi 41714 $ bind -p | grep '"\\C-\\' 41715 "\C-\\": self-insert 41716 $ bind '"\C-\\": self-insert' 41717 $ bind -p | grep '"\\C-\\' 41718 "\C-\\\": self-insert 41719 "\C-\": self-insert 41720 41721 $ bash-4.4 --norc 41722 $ bind -p | grep '"\\C-\\' 41723 $ bind '"\C-\\": self-insert' 41724 $ bind -p | grep '"\\C-\\' 41725 "\C-\\": self-insert 41726 41727 $ bash-4.4 --norc 41728 $ set -o vi 41729 $ bind -p | grep '"\\C-\\' 41730 "\C-\\": self-insert 41731 $ bind '"\C-\\": self-insert' 41732 $ bind -p | grep '"\\C-\\' 41733 "\C-\\": self-insert 41734 41735 一応 ble.sh 側で対策はしておく事にする。修正した。エラーメッセージは出なくなった。 41736 41737 * decode: うーん reload した後に無限ループになって落ちるバグがある [#D1077] 41738 以前に起こった時には偶にしか起こらないと思っていたが2回目である。 41739 しかし、そう思って実行してみると再現しない。 41740 過去の特定のバージョンから最新のにアップデートした時になるという可能性もある。。 41741 41742 また再現した。今度は --attach=prompt にしていたがそれで固まった。 41743 うーん。よく分からない。やはり再度試しても再現しない。 41744 やはり古い ble.sh をロードした状態で reload すると死ぬのだろうか。 41745 41746 % うーん。再現した。ble-0.3 をロードしてから実行すると無限ループになる。 41747 % これは修正しておいた方が良い気がする。もう手遅れかもしれないが。 41748 % 無限ループになるのだからどの時点で無限ループになるのかは調べられる。 41749 % 少なくとも1文字入力した後で無限ループになっている。.hook から迫る事にする。 41750 % と思って改めて ble-0.3 をロードしてから新しい ble をロードしたが再現しない…。 41751 41752 少なくとも分かった事は一定時間経たないと再現しないとかそういう事はなくて、 41753 source ble-0.3 してから source ble してもちゃんと再現する事があるという事。 41754 41755 再現する迄は .hook に文字列を埋め込んで処理するか…。 41756 41757 * あー。再現した。EPILOGUE の中で発生している。 41758 * 再現する条件が分かった気がする。補完を使って入力して、 41759 その直後に source を実行すると無限ループになる。 41760 また、古い ble-0.3 の中で新しい ble を source した時に発生する。 41761 * 更に、ble/util/idle.do の中で発生している。 41762 タスクが無限に繰り返されているのかと思ったが、 41763 そうではなくて ble/complete/auto-complete.idle が制御を返さない。 41764 41765 うーん。不思議な事に ble/complete/auto-complete/.check-history の中から、 41766 ble/complete/auto-complete.idle が改めて呼び出されている様子である。 41767 しかも idle を経由した呼び出しではなくて。 41768 然し、検索しても auto-complete.idle を呼び出している箇所は他にはない。 41769 41770 何かメモリでも破壊しているという事なのか? 41771 うーん。bash-5.0 でも再現する。 41772 41773 更に遡っていくと ble-decode-key があった。これだ…。 41774 この中で更に idle.do が呼び出されるという事なのだろう。 41775 と思ったが、それも何だかおかしい。idle.do に入ったのだったら 41776 idle.do からメッセージが来るのではないのか。 41777 41778 うーん。ble-decode-key auto_complete_enter が問題なのは分かったが。 41779 古い ble-0.3 からのときだけ問題になるのは何故だろうと思って、 41780 unkbd してみたが特に keycode がずれているとかそういう原因ではない様だ。 41781 41782 と思ったら分かった。ble/widget/auto-complete-enter という関数の中で 41783 ble/complete/auto-complete.impl sync が呼び出されている。。 41784 そして無限ループになっているのだった。 41785 しかし ble/widget/auto-complete-enter は auto_complete keymap 41786 では存在しない筈では? 41787 実際に ble/widget/auto_complete/notify-enter が登録されている筈である。 41788 古い ble-0.3 の方では nop が呼び出されている。 41789 41790 どうやら keycode の変化によって一回 cancel-default に行って、 41791 更にその後で auto-complete-enter が呼び出されているという事の様である。 41792 keycode が 114158 から 114159 に変化している。 41793 auto_complete keymap を再初期化する様にしなければならないのであった。 41794 最初期化を促す為にはどのようにすれば良かったか。reload のコードを辿る。 41795 41796 ble-edit/bind/clear-keymap-definition-loader が怪しい。 41797 見てみると此処で unset -f ble-edit/bind/load-keymap-definition:* というのを実行している。 41798 うーん。keymap の読み込みの手順が何だか分からなくなった。 41799 ble-decode/keymap:auto_complete/define という関数だけ用意しておけば自動で読み込まれるのは何故か。 41800 →ble-decode/keymap/load という関数でこの関数名を探索して読み込んでいた。 41801 しかし、此処を見て分かる事は、ble-decode/keymap/is-keymap "$1" で始めに判定していて、 41802 ここで keymap が存在していると判定されると再読込がされないという事である。 41803 41804 うーん。何故これをそのままにして放置したのだったか。 41805 ユーザの設定を保持する為だった様な気がする。 41806 しかし、ユーザの設定を保持する理由もよく分からない。 41807 reload の際に結局 blerc を読み込むのではなかったか。 41808 という事を考えると、やはり一旦消去してしまうのが良い。 41809 41810 [修正] 41811 41812 _ble_decode_kmaps に登録されている keymap を全て削除する事にした。 41813 と思ったら全然駄目だ。_ble_decode_kmaps に登録されていない…。 41814 仕方がないので _ble_decode_*_kmap_ という名前の変数名を全て探して削除する事にした。 41815 また、色々と keymap 関連の関数を整理する事にした。 41816 41817 もっと大幅に整理しても良いかもしれないとも思ったが面倒なので止めておく。 41818 41819 * 実は attach=prompt ならば普通に source からでも bashrc からでも使えるのでは [#D1076] 41820 実際に試してみると何事もなく実行することができた。 41821 うーん。何も引数を指定しなかった時には --attach=prompt を使う事にしよう。 41822 41823 * 2019-04-21 [無関係] contra: stty? contra ./impl3 を実行した直後の状態が変である [#D1075] 41824 rm を実行しようとするとファイルのクローズに失敗しましたと表示されて終わる。 41825 cat を実行している途中に失敗する。ble.sh ではなくて bash --norc の中から 41826 ./impl3 を実行して抜けた場合には変な状態にはならない。 41827 一旦 bash --norc を実行して抜ければ元の状態に戻る。 41828 stty -a で出力される内容には変化はない。 41829 41830 →./impl3 がこれは fcntl(STDIN_FILENO, F_SETFL, flags) で O_NONBLOCK 41831 を立てたまま終了していたのが悪かった。終了する時に元に戻す様にした。 41832 然し、こういった状態をコマンドから操作する事は可能なのだろうか。 41833 41834 2019-04-19 41835 41836 * edit: プロンプト評価時の $? の値 [#D1074] 41837 41838 https://qiita.com/kxn4t/items/bd85397914a22e69cefd 41839 この記事を見て思ったのだが PS1 の中に含まれているコマンド置換から見ると、 41840 直前に実行したコマンドの終了ステータスを $? を参照する事ができる。 41841 そして実際にプロンプトの表示を切り替える為にその値を参照するというのは需要がある。 41842 41843 https://superuser.com/questions/301353/escape-non-printing-characters-in-a-function-for-a-bash-prompt 41844 更に Bash は \[ \] を ^A ^B に変換して処理を実行するそうだ…。知らなかった…。 41845 ble.sh の内部では \e[99s \e[99u に変換して処理を実行している。 41846 まあ、結局似たような事をしているという事に違いはない。 41847 ^A ^B に変換して処理をする様に変更する必要があるが、まあ大した変更ではないのである。 41848 41849 両方共実装してみた。テストの為に上記 Qiita の記事に書かれている物を設定してみる事にする。 41850 まあ、ちゃんと動いている。但し、上の記事では add_line というので変な改行を出力している様にしているので、 41851 それによって vim-mode の表示が乱れてしまっているが、まあそれは気にしなくて良い。 41852 うーん。頬の罰印の表示に使われている文字の文字幅の計算が誤っている。 41853 west east emacs 等を試してみると何れの場合でも c2w は 2 になっている。 41854 一方で、screen 等の表示は 1 で処理している様に見える。 41855 screen が一方的に悪いという事だろうか。うーん。Qiita 記事を見ると半角で表示されている様子である。 41856 つまり、これは c2w の幅テーブルが誤っているという事を意味する。 41857 問題の文字は U+2716 の様である。そして ble/util/c2w/.determine-unambiguous によると ambiguous になっている。 41858 ble/util/is-emoji によると emoji と判定されている…。bleopt emoji_width= としたら良いのかもしれない。 41859 まあ、これは設定の問題である様な気がしてきたので気にしない事にする。 41860 41861 2019-04-15 41862 41863 * decode: RLogin で delete が何故か効かない問題 [#D1073] 41864 delete を一回押しても無視される。他の文字を続けて入力するとそのまま素通りする。 41865 delete を2,3回押すと unbound keyseq のエラーが発生する。 41866 因みに別の Function Keys については特に問題も発生していない気がする。 41867 全く受信されないという訳でもなく、何が起こっているのかよく分からない。 41868 実際に受け取っているバイト・デコードされた結果などを観察してみる必要がある。 41869 41870 dyna の上で実行してみると今度は insert が効かない。 41871 これは全く効かない。連続で押しても何のエラーも発生しないし、 41872 続いて他の入力をしても何事もなく操作する事ができる。 41873 これは RLogin の側の設定だろうか。設定を探したが何も見つからない。 41874 41875 受信しているバイト列について確認を行う。 41876 どうもちゃんと受信できている気がする。 41877 デコード結果についても確認する。insert の decode に失敗している様だ。 41878 ESC [ 2 ~ は unrecognized csi sequence という事になっている。何故だろうか。 41879 ble-bind -P | grep csi とするとちゃんと insert で 2~ に登録されている。 41880 他の home end prior next delete も同様である。それなのに insert だけ動かない。 41881 41882 うーん。変だ。ent に何も入って来ないのである。 41883 _ble_decode_cmap__... の配列を見ると変な物しか登録されていない。 41884 という事は何を意味するのかというと、CSI ... ~ は一つも登録されていないという事。 41885 うーん。もしかして別の所に登録されていただろうか。 41886 と思ったら insert が登録されているのは _ble_decode_csimap_tilde の方であった。 41887 41888 うーん。ちゃんと hit している気がする…。と思ったら…。 41889 もしかして insert の kcode と error の kcode が衝突している? 41890 つまり、正しくキャッシュがクリアされていなかった事が問題なのである。 41891 41892 - reject: というかキャッシュをクリアする為の関数を作っても良いのかもしれない。 41893 とも思ったがこれは全て ble.sh の内部実装の欠陥による物なので、 41894 ユーザにそれを実行してもらう為に作るというよりはデバグの為に作るべきである。 41895 という事を考えると、自分で使うのに必要でなければわざわざこれを作る必要はない。 41896 41897 2019-04-04 41898 41899 * complete: menu-filter の途中で確定して実行すると自動補完前の状態に戻ってしまう [#D1072] 41900 これは一体何が起こっているのか…。恐らく layer が変な事をしている…。 41901 試しに layer:menu_filter を除外してみたら変な事を起こらなくなった。 41902 41903 2019-04-02 41904 41905 * [考察] main: bash-it との組み合わせについて考える [#D1071] 41906 41907 https://github.com/Bash-it/bash-it/issues/894 に投稿してみたが、 41908 投稿直後に一人反応した以外は何も反応はない。 41909 というか 340 も Watch していてそもそもサイトに訪れたのが1人である。 41910 余りアクティブなので結局皆見ていないという事なのかもしれない。 41911 しかし、メンテナーらしき nwinkler という人ぐらいは見てくれても良さそうだが。 41912 土日だから見ていないという事なのかもしれない。 41913 GitHub ユーザには土日にしか対応しない人と平日にしか対応しない人の二種類の人がいる。 41914 41915 bash-it の初期化内容を idle.do で実行できる様にするのが良いのではないだろうか。 41916 或いは bash_it.sh を書き換える様に pull request を出すというのでも良い。 41917 しかし、下手に bash-it を刺激すると、ble.sh が bash-it の付属物であるかの様に広まったりしないだろうか。 41918 つまり、ble.sh を入れる為には取り敢えず bash-it を入れよう、という具合になってしまうという事。 41919 うーん。それは微妙な気がするが、まあ、すぐにそういう事になるとも思えないので気にしなくて良い。 41920 41921 bash-it のコードを観察してみたが、余り質の良いものではない。 41922 沢山の人がコミットしているからなのかと思いきや、 41923 コアとなる部分のコードも微妙である。 41924 そもそも何故 local を使わない? と思われる箇所が沢山ある。 41925 というか local で宣言した物を他の関数から参照できるという事を知らない? 41926 或いは知ってはいるがそれは bash のデザインが悪いからと言う様に考えていて、 41927 積極的には使用しないよという方針なのかもしれない。 41928 41929 * 2019-03-12 Traffic を見ると GitHub 経由でやって来る人が結構いる。 41930 それから検索経由でやって来る人も結構いる。 41931 これはつまり、GitHub 経由でやってきて、その後で名前を覚えてくれて、 41932 それから検索を使って到達してくれるという事なのだろうという気がする。 41933 41934 では GitHub 経由というのは具体的に何だろうか。 41935 この bash-it に書いたコメントなのだろうか。 41936 しかし、これは閉じられた Issue なので余り見る人が多くいるとも思われない。 41937 或いは、自分の Profile を見て一番上にあるからと思って見に来るのだろうか。 41938 何だかそれが一番多いということの様に思われてきた。 41939 41940 * [考察] main: oh-my-bash との相性についても調べておく [#D1070] 41941 41942 | oh-my-bash は勝手に .bashrc を丸ごと変えてしまう。 41943 | bash-it にしろ oh-my-bash にしろ、 41944 | これらはツールというよりは .bashrc を丸ごと提供する「設定」である。 41945 | さて oh-my-bash の中についても確認したが、 41946 | これも PS1 と completion と alias を設定するぐらいで大した設定ではない。 41947 | 41948 | ble.sh との相性も別に問題はなさそうな気がする。が、念の為両方ロードしてみる。 41949 | ちゃんと動いている。但し、bash-it 程ではないがやはり遅い気がする。 41950 | やはり git コマンドを呼び出すのは遅いという事なのである。 41951 | 直接 .git の構造を探索して現在のブランチ名を取り出すぐらいしないと駄目である。 41952 | うーん。後、意味不明な alias が大量に定義されている…。 41953 | 一文字の alias は勝手に定義しないで欲しいものである。 41954 41955 問題なし 41956 41957 * [自然解消] 2015-03-01 ble-edit: 対応する物がない readline 関数 [#D1069] 41958 41959 - done: history-expand-line magic-space 41960 - done: delete-horizontal-space 41961 - done: history-search-forward/backward 41962 - done: yank-nth-arg yank-last-arg insert-last-argument 41963 - done: shell-expand-line alias-expand-line 41964 - done: tilde-expand history-and-alias-expand-line 41965 - done: edit-and-execute-command 41966 - done: transpose-words upcase-word downcase-word capitalize-word 41967 - done: kill-whole-line 41968 - done: complete関連 41969 - done: redo, undo 41970 - done: yank-pop これはkill-ringを正しく実装する必要がある 41971 - done: digit-argument universal-argument 入力しやすい様に? 41972 41973 * [自然解消] 2013-06-01以前 デフォルトで bind されている readline 関数の一覧をチェック [#D1068] 41974 41975 * [自然解消] 2013-06-05 bashfc [#D1067] 41976 ref #D1050 41977 41978 * [解消] 2019-03-21 emacs: readline 関数を少しずつ実装して行く事にする [#D1066] 41979 ref #D1059 取り敢えず全て実装した気がする。 41980 41981 * 2018-08-19 highlight: シェル変数 auto_resume? [#D1065] 41982 一語の単純コマンドでありかつジョブの名前に一致する場合にジョブ名と解釈する。 41983 41984 | 先ず初めに一語の単純コマンドとはどういう条件であるかを調べる必要がある。 41985 | value=less; $value でも成立するのだろうか。 41986 | →成立した…。更に "echo; $value" とやってもちゃんと実行される。うーん。 41987 | "一語から成る" というのは難しい条件であるが、 41988 | 何も考えずに単体のコマンドとして着色しても良いのかもしれない。 41989 | 41990 | うーん。よく分からない。$value だとできるが \less や 'less' だとできない。 41991 | "$value" 等もできない。\ や "' が含まれていると駄目という事なのか。 41992 | 何と $(echo less) でもできる。$(echo "less") でもできる…。 41993 | `echo less` はできない。 41994 | うーん。ble.sh では \"'` が含まれていなければ OK という事にしようか…。 41995 | 41996 | 調べてみると alias の方が優先される。function よりはこちらの方が優先される。 41997 41998 ble.sh の仕様としては (1) 一語のコマンドかどうかの判定は諦める。 41999 (2) 単純コマンドかどうかは展開前に \'"` 等の文字が含まれていない事とする。 42000 (3) alias が優先されその次にジョブ名と解釈できるかどうかを判定する。 42001 42002 * blerc: 設定に関する質問が来たので取り敢えず blerc に記述する事にした [#D1064] 42003 https://github.com/akinomyoga/ble.sh/issues/23 42004 42005 * 2019-04-02 decode: ble/builtin/bind/rlfunc2widget が遅い [#D1063] 42006 呼び出し回数がそんなになければ良いが inputrc に沢山の項目が書かれていると、 42007 その項目の数だけ awk を fork しなければならない。 42008 特に Cygwin で重くなってしまうのである。実際に Cygwin 上で確認すると重い…。 42009 awk を使わない実装に切り替える事にした。実際に試してみたがそんなに改善していない。 42010 うーん。元々遅かったという事なのかもしれない。 42011 少なくとも多少は早くなったと思うので気にしない事にする。 42012 42013 * decode: 起動時に error_cseq_vbell で変なエラーメッセージが出る様になった… [#D1062] 42014 と思ったらこれは inputrc の decode で発生している様だ。 42015 成る程、decode で visible-bell が表示されては困る。 42016 42017 (1) 先ず始めに ble/builtin/bind/.decode-chars の中で 42018 エラーが発生しても無視する様にする。 42019 (2) 更に ble/decode/read-inputrc を実行する前に 42020 cmap を初期化する必要がある。 42021 ble-decode-bind/cmap/initialize で初期化を実行している。 42022 これは ble-decode/initialize から呼び出されている。 42023 ble-decode/initialize は ble.pp の中から呼び出されている。 42024 42025 2019-04-01 42026 42027 * [解消] 2018-02-12 emacs: kill-ring [#D1061] 42028 ref #D1059 42029 42030 M-y にも対応したい。C-y の引数に対応する。 42031 然し、今の所は vim-mode 対応の方を優先させるので、これは後回しにする。 42032 42033 * [解消] 2017-12-04 keymap/emacs: 引き数: ble/widget/yank [#D1060] 42034 ref #D1059 42035 42036 引き数の解釈がよく分からない。 42037 1 以外の引き数を指定すると rotate するのだろうか。 42038 どうもその様に思われる。 42039 しかし、現在の枠組みではそもそも kill_ring に対応していない。 42040 従って、急には対応できない。取り敢えずの所は clear-arg しておく。 42041 42042 * emacs: yank-pop [#D1059] 42043 42044 これは kill-ring の実装等も同時に考えなければならない。 42045 現在の変数は _ble_edit_kill_ring にある。 42046 及び _ble_edit_kill_type にある。 42047 42048 取り敢えずこれを配列にする所から始める。 42049 直接触っている箇所について確認する。 42050 42051 * 先ずは vi.sh 以外の場所について。登録している箇所が殆どであって、 42052 それらは push-kill-ring という名前の関数経由で設定する事にした。 42053 参照している箇所は yank のみである。 42054 42055 * vi.sh はたくさん使っているが、 42056 これらは今まで通りに一番上の項目だけ使う様にすれば良い気がする。 42057 つまり、特に処置は必要ない。 42058 一応、emacs モードとの互換性も考えて登録する時には 42059 push-kill-ring を使って登録して、ring を参照できる様にする。 42060 42061 取り敢えずコードは整理した。 42062 登録は push-kill-ring から行っている。 42063 使用は yank から行っている。これらの二箇所さえ修正すればOKなのでは? 42064 但し、yank が一体どの様に振る舞うのかによって実装の仕方が変わるかもしれない。 42065 先に振る舞いについて確認しておきたい。 42066 42067 うーん。yank で引数を指定すると回転するのかと思ったがそうでもない様だ。 42068 f1 v kill-ring RET で kill ring の内容を確認する事ができるが、 42069 やはりいちばん最近に追加した物が一番上にあるままであった。 42070 42071 引数1を指定すると位置は変わらない。 42072 引数0を指定すると一つ次の内容に移動する。 42073 引数2を指定すると一つ前の内容に移動する。 42074 次の内容が存在しない時には cyclic に移動する。 42075 新しい内容を kill すると先頭に戻る。 42076 42077 こんな振る舞いで良いのだろうか。 42078 というか、項目の最大数を設定しなくても大丈夫だろうか。 42079 後、bash の振る舞いも emacs と同じと思って良いのだろうか。 42080 と思ったら bash は全然 ring になっていない気がする。うーん。 42081 あー。これは。。yank-pop を使った時にのみ ring にアクセスできる。 42082 然も、yank-pop は引数を認識していない様子である。 42083 42084 a ううーん。yank 直後も何か特別な keymap にいるという事にしようか。 42085 42086 b 或いは LASTWIDGET を用いて処理しようか。正直な所 LASTWIDGET は余り働いていない。 42087 引数を追加する widget や auto-complete 等が間に勝手に入っても良いからである。 42088 然し、そうは言っても C-w を連続で使用した時の積算や 42089 up down による移動の列の保持など、そういう操作で使いたい気もする。 42090 42091 うーん。auto-complete やら引数 widget で "LASTWIDGET に影響しない" 42092 という事を明示する様にしてやれば良いのだろうか。。。これは実は可能である。 42093 _ble_decode_widget_last=$LASTWIDGET という具合に上書きしてしまえば良い。 42094 →その為の関数 ble/decode/widget/skip-lastwidget を新しく定義した。 42095 取り敢えず redispatch と引数追加が起こる時にはこれを呼び出す事にした。 42096 実際に auto-complete を起こしてみて調べてみる。 42097 nop が走っている。これは auto_complete_enter によって引き起こされている。 42098 auto_complete_enter では auto_complete/notify-enter というのを呼び出す事にした。 42099 その中で skip-lastwidget を実行する事にする。 42100 42101 然し、LASTWIDGET を用いて処理するにしても 42102 置換がどんどん起こっていく時の置換範囲というのは分かりやすい方が良い。 42103 そう思うとやはり特別の keymap を作成した方が良いのではという気になる。 42104 実は yank の直後の yank-pop をした時点で keymap に入るのが良いのでは。 42105 42106 ? 所でいきなり yank-pop を実行した時の bash の振る舞いは何だろうか。 42107 調べてみた所 bell が鳴るだけなのであった。 42108 42109 取り敢えず実装してみた。 42110 42111 x fixed: 置き換え範囲が変である。yank でちゃんと設定できていない? 42112 確認した所 mark の設定に失敗していた。修正した。 42113 42114 x fixed: push-kill-ring を未だ真面目に実装していなかった。 42115 取り敢えず実装した。未だ動作は未確認である。 42116 ちゃんと動いている様に思われる。 42117 42118 これで対応は終わっただろうか、と思ったが yank の引数の動作を確認していない。 42119 確認した。まあ、動いている様に思う。OK 42120 42121 * [自然解消] 2017-09-23 ble-edit: yank-last-arg [#D1058] 42122 42123 | 続けて入力するとどんどん遡っていく。 42124 | どの位置から置き換えを行うかは mark に記録されている様子だ。 42125 | また、前回実行された関数が yank-last-arg だった時にのみ遡る。 42126 | 42127 | 前回実行されたコマンドを記録する仕組みを整える必要がある。 42128 | 難しい点は marked/nomarked をどの様に取り扱うかである。 42129 | そう考えると呼び出し元 (ble-decode) で記録するのは難しいかもしれない。 42130 | かと言って呼び出される側 (ble-edit) の各 widget で記録するのも面倒である。 42131 | 42132 | うーん。取り敢えず ble-decode の側で最後に呼び出したコマンド文字列を記録するぐらいはできるし、 42133 | その程度の機能ぐらいはあってしかるべきと思うので実装する。 42134 | marked/nomarked などの無駄な文字列は、記録した文字列を使用する側で何とかする仕組みにすれば良い。 42135 42136 これは #D1051 で実装された。 42137 42138 * edit: universal-argument [#D1057] 42139 42140 これの実装は面倒である。 42141 C-u が入った状態は + で始まるという事にしようか。 42142 42143 うーん。arg=+ の時は M-C-u が入った状態とする。 42144 この時点で何か数字を入れると通常の状態になる。 42145 更にここで M-C-u を押すと +数字 という状態になる。 42146 この状態の時には M-C-u から抜けた状態になっていると考える。 42147 42148 実装してみた。動いている様に見える。これで良いという事にする。 42149 42150 * edit: skip-csi-sequence は ble.sh では bleopt の [#D1056] 42151 decode_error_char_discard か decode_error_kseq_discard 42152 に対応していると思ったが、調べてみると前者は誤ったバイト列の時で、 42153 後者は誤ったキーの列の時であった。 42154 42155 これは入り組みそうなので別の項目として処理する事にする。 42156 csistat で IGNORE を返す様にすれば良い気がする。 42157 csi/consume の側では、登録されている cseq が存在しているかもしれないので、 42158 その場ではエラーになるかどうか判定する事ができない。 42159 一方で、ここで IGNORE を返してしまうと正しく認識できた上で IGNORE として 42160 返る CSI シーケンスとの区別がつかなくなる。 42161 42162 結局 IGNORE (__ignore__) ではなく ERROR (__error__) というキーを新規作成する事にした。 42163 登録されている cseq の探索コードとの両方を統合する箇所でエラーを判定して、 42164 その上で vbell, abell の処理をすれば良いだろう。 42165 というか discard に関してもここで判定した方が見通しが良いのではないだろうか。 42166 42167 取り敢えず bleopt decode_error_cseq_{abell,vbell,discard} を追加した。 42168 42169 * edit: transpose-words [#D1055] 42170 42171 単語の切り出しがどの様に起こるのかについて調べる。 42172 調べてみると bash と emacs で振る舞いが異なる。 42173 というか bash の振る舞いは物凄く分かりにくい。 42174 emacs の振る舞いに倣う事にする。 42175 42176 echo hello_world 42177 42178 echo hello world this is a pen 42179 echo+hello*world-this=is@a:pen 42180 42181 1. 単語の先頭にいる時はその前の単語を移動 42182 2. 単語の二文字目以降にいる時は後の単語と交換 42183 3. 引数を指定した時は後のN単語を一まとまりと見て 42184 交換する。つまり word1+(word2-word3-word4) 42185 を (word2-word3-word4)+word1 にするという具合。 42186 42187 開始点は locate-backward で b を拾えば良い。 42188 42189 echo+hello*world-this=is@a:pen 42190 echo+hello*world-this=is@a:pen 42191 echo+hello*world-this=is@a:pen 42192 42193 4. 引数0を指定した時は mark の位置の単語と、 42194 現在位置の単語を交換する。 42195 交換する単語は何れも前方に検索する。 42196 skip-forward, skip-backward して特定する。 42197 42198 5. 負の引数を指定した時には 42199 1.2. と同様に移動単語を決定し、 42200 そして更に負の方向に単語を探索する。 42201 42202 取り敢えず実装してみた。動いている。良しとする。 42203 42204 * tty-status は呼び出しても何も起こらない気がする。 42205 stty raw として見て tty-status を呼び出しても状態が治るとか、 42206 現在の状態が変である事を示す表示が出るとかそういう事はない様だ。 42207 もちろん、元の振る舞い (C-t) も上書きしているので起こらない。 42208 bash-5.0 の man を見ても何も説明はない。 42209 これはよく分からないので無視する方向で行く。 42210 42211 * edit: shell-expand-line [#D1054] 42212 42213 * これの実装をする為には、先ずどの様な展開が実行されるのかを調べる必要がある。 42214 エイリアスの展開は実行される。チルダ展開は実行されない。 42215 パス名展開は実行されない。コマンド置換は実行される。 42216 パラメータ展開は実行される。算術式展開は実行される。 42217 何とクォート除去も実行されてしまう…。プロセス置換すら実行されてしまう…。 42218 42219 - 履歴展開 42220 - コマンド置換・パラメータ展開・算術式展開 42221 - プロセス置換 42222 - エイリアス展開 42223 - クォート除去 42224 - 単語分割 42225 x チルダ展開・パス名展開 42226 42227 因みにコマンド置換・クォート除去の後にエイリアス展開が起こるという事はない。 42228 コマンド置換の後にクォート除去が起こるという事もない。 42229 つまり、複数の展開が一気に起こるという事はないのである。 42230 42231 然し、履歴展開によって現れた内容に対してコマンド置換は適用される様である…。 42232 というかそのコマンド置換でエラーが生じたところ bash が落ちる。 42233 と思ったが勘違いか? 再度試したら落ちなかった。 42234 42235 * カーソルの位置は末尾に移動する? と思ったら、dirty range の前に居る場合は dirty range 直前に、 42236 dirty range の中にいる場合は dirty 末尾に、dirty range の後に居る場合は 42237 文字列の末尾に移動するという事になっている様だ。 42238 42239 これは既に実装しているエイリアス展開の実装を参考にして実装するのが良さそう。 42240 但し、どうせ展開されるので nest の中の実行はしなくても良い。 42241 42242 というか今の実装では .replace-range を使っているので自動的にカーソルが計算される。 42243 寧ろ、.replace-range に任せる方が良いのではないかという気がする。 42244 唯、振る舞いの違いは .replace-range だと置換範囲の末尾ではなくて、 42245 できるだけカーソルが移動しない様になっているという事である。 42246 →.replace-range のカーソル移動の仕様に関しては特に意味がなかった様な気がするので、 42247 振る舞いを変更してしまう事にする。mark, ind が変更に巻き込まれる時、 42248 mark は 変更範囲の先頭に、ind は変更範囲の末尾に移動する。 42249 * .replace-range を使っている箇所を一応確認する。 42250 大抵は _ble_edit_ind を設定している。 42251 多くは operator の中で使われているが、operator の場合は 42252 呼び出し元で位置を設定するはずなので気にしていないのだろう。 42253 他に変更範囲外の時には曖昧なく移動が起こるという事を仮定している 42254 様に思われる箇所はあった。確かにこれは妥当な仮定である。 42255 そしてこれは新しい振る舞いでも保たれる。 42256 .replace-range の振る舞いは変更する事にした。 42257 42258 というかそれぞれの単語について展開を実行すれば良いのでは? 42259 42260 * うーん。どの様にしたら展開対象の単語の文脈を網羅する事ができるだろうか。 42261 単語を閉じる時に検査など行っていなかっただろうか。 42262 42263 ble/syntax:bash/ctx-command/check-word-end を確認したがチェックはない。 42264 ble/syntax:bash/ctx-command/.check-word-begin にコードがあった。 42265 _ble_syntax_bash_command_BeginCtx というテーブルを使って単語の wtype に変換している。 42266 確認できる物は以下の通りである。 42267 42268 CTX_CMDI 42269 CTX_ARGI CTX_ARGEI CTX_ARGVI 42270 CTX_FARGI1 CTX_FARGI2 CTX_FARGI3 42271 CTX_TARGI1 CTX_TARGI2 42272 CTX_CARGI1 CTX_CARGI2 42273 42274 然し、実際に確認できる物はこれよりも少ない。実は、もっと後で更に変換をしている気がする。 42275 と思ったが実装をよく見るとテーブルで変換した後の値を wtype にしているのではなくて、 42276 その前の文脈値を wtype にしている様だ。 42277 と思ったらちゃんとコメントに説明が書かれている _ble_syntax_bash_command_EndWtype で 42278 更に最後に変換が行われるという事が述べられている。このテーブルによると以下の値が確認できる。 42279 42280 CTX_CMDI 42281 CTX_ARGI CTX_ARGVI CTX_ARGEI 42282 CTX_CARGI2 CTX_FARGI2 42283 42284 CARGI2 FARGI2 は in というキーワードなので展開の対象ではない。 42285 他に試していると CTX_VALI という物も確認することができる。 42286 うーん。ctx.def を観察する CTX_CONDI は対象である。 42287 RDRI というのもあるがこれは展開の対象ではない。 42288 42289 * fixed: うーん。eval-noglob としているのにパス名展開が実行されている…。 42290 と思ったら、eval-noglob では変数代入の右辺にする事で 42291 パス名展開を免れていたのであった。 42292 今は単純単語以外も許すために、 42293 配列代入で単語を展開しているのでパス名展開が有効になってしまっている。修正した。 42294 42295 チルダ展開についても一緒に実装する事にする。 42296 チルダ展開についても alias-expand-line と同様に tree-enumerate で実行しようと考えたが、 42297 よく考えてみるとチルダ展開は tree に登録していない。 42298 というか内部構造がなくて単に syntax の解析の時点で特定できているから、 42299 _ble_syntax_attr だけ確認して置換すればよいのではないか。 42300 簡単に実装してみた。動かしてみる。動いている気がする。良しとする。 42301 42302 2019-03-31 42303 42304 * emacs: history-nsearch-{for,back}ward-again [#D1053] 42305 again の実装は簡単である。と思ったが nsearch 自体の振る舞いが変だ。 42306 42307 x fixed: 検索文字列として有限の物を入力していても `' not found というメッセージが出る。 42308 これは一番端に達した時に needle をロードしていなかったのが原因。 42309 何れにしても local needle=$_ble_edit_nsearch_needle を実行する様にした。 42310 42311 x fixed: 同じ履歴内容の物に一致すると範囲着色が為されない? 42312 調べてみるとちゃんと mark_active 及び mark ind は設定されている。 42313 それなのに描画している時に着色が適用されないという状態。 42314 これは一体何が起こっているのだろうか…。 42315 42316 reset-and-check-dirty で変更が起こらないとちゃんと着色されないという事なのか。 42317 うーん。ble/textarea#render まで行ったが 42318 其処でもちゃんと mark_active mark ind は設定されている。 42319 それなのに着色される時とされない時がある。 42320 42321 x fixed: というより、そもそも何故か2回ずつ render が呼び出されている。 42322 これはどういう事だろうか。何故2回呼び出す必要がある。 42323 設計上は1回呼び出すだけの筈なのではないのか…。 42324 不思議だ…。.hook が2回呼び出されているのか? 42325 DEL は一文字で受信できる筈だし、もしそうだとしても状態が変化しない筈なので 42326 textarea#render が2回実行される事はない筈なのである…。 42327 42328 調べるとどうも EPILOGUE は 1回しか呼び出されていない。 42329 ble/bind/.tail の中で複数回 textarea#render が呼び出されている。 42330 中を確認すると idle.do を実行した後にもう一度 textarea#render を呼び出している。 42331 つまり、2回 textarea#render が呼び出される所までは良い。 42332 42333 問題は何故何も操作をしていない筈なのに dirty が立つのかという事。 42334 あー。これは caret_state がちゃんと初期化されない制御パスがある…。 42335 直した c7599a2 42336 42337 さてそれでも着色が為されない場合というのが存在している。 42338 もしかすると layer 側の問題だろうか…。 42339 うーん。layer:region/update を観察する。selection の取得まではできている。 42340 42341 あー。分かった。変更点がなかった場合に PREV_BUFF を更新する必要があったのだった。 42342 直した 23796bc 42343 42344 x fixed: 更に途中で何故か操作不能になるという現象も発生していたはず…。 42345 今再度試してみたらやはり再現する。これは何だろう。 42346 一度 C-r してから C-s で端まで到達すると上にも下にも動けなくなる。 42347 42348 検索範囲が狭められている…。 42349 これはどうも start の初期化の問題の様である。 42350 直した 3b2237e 動くようになった。 42351 42352 * emacs: menu-complete-backward [#D1052] 42353 これは簡単である。 42354 42355 * emacs: insert-last-argument [#D1051] 42356 42357 取り敢えず実装してみたは良いが Bash のマニュアルを見ると 42358 yank-nth-arg だとか yank-last-arg だとかがあって、 42359 引数に対する取り扱いが全く異なる。 42360 更に、挿入内容は !n や !$ を使って展開されるという話。 42361 42362 うーん。再実装の必要の予感…。と思ったが、 42363 editted entry からという事を考えると、 42364 やはり自分で履歴項目を取り出して処理する必要があるのではないだろうか。 42365 うーん。サブシェル内で評価する。 42366 builtin history -s -- "$cmd" で登録してから !!:$ 等で単語を切り出す。 42367 42368 以下は再実装前の実装。 42369 42370 | ## @var _ble_edit_lastarg_index 42371 | ## 最後に挿入した最終引数の履歴番号です。 42372 | ## @var _ble_edit_lastarg_arg 42373 | ## 最後に挿入した時の編集関数の引数です。 42374 | ## 次に編集関数を引数無しで呼び出した時の 42375 | ## 既定の方向を決定するのに使われます。 42376 | _ble_edit_lastarg_index= 42377 | _ble_edit_lastarg_arg= 42378 | function ble/widget/insert-last-argument { 42379 | local arg; ble-edit/content/get-arg '' 42380 | 42381 | # current position 42382 | local beg=$_ble_edit_ind end=$_ble_edit_ind index= 42383 | if [[ ${LASTWIDGET%%' '*} == ble/widget/insert-last-argument && $_ble_edit_lastarg_index ]]; then 42384 | beg=$_ble_edit_mark 42385 | index=$_ble_edit_lastarg_index 42386 | [[ $arg ]] || ((arg=_ble_edit_lastarg_arg>=0?1:-1)) 42387 | else 42388 | ble-edit/history/get-index 42389 | [[ $arg ]] || arg=1 42390 | fi 42391 | 42392 | # next position 42393 | local index2=$((index-arg)) 42394 | if ((arg<0)); then 42395 | local count; ble-edit/history/get-count 42396 | ((index2>=count&&(index2=count-1))) 42397 | else 42398 | ((index2<0&&(index2=0))) 42399 | fi 42400 | if ((index==index2)); then 42401 | ble/widget/.bell 42402 | _ble_edit_lastarg_index=$index2 42403 | _ble_edit_lastarg_arg=$arg 42404 | return 1 42405 | fi 42406 | 42407 | while :; do 42408 | local entry; ble-edit/history/get-editted-entry "$index2" 42409 | local wordbreaks; ble/complete/get-wordbreaks 42410 | local rex='([^'$wordbreaks']+)['$wordbreaks']*$' 42411 | if [[ $entry =~ $rex ]]; then 42412 | local rematch1=${BASH_REMATCH[1]} 42413 | ble-edit/content/replace "$beg" "$end" "$rematch1" 42414 | ((_ble_edit_mark=beg,_ble_edit_ind=beg+${#remtach1})) 42415 | _ble_edit_mark_active=menu_complete 42416 | break 42417 | elif ((arg<0)); then 42418 | ((++index2>=count)) && break 42419 | else 42420 | ((--index2<0)) && break 42421 | fi 42422 | done 42423 | _ble_edit_lastarg_index=$index2 42424 | _ble_edit_lastarg_arg=$arg 42425 | } 42426 42427 * emacs: edit-and-execute-command [#D1050] 42428 42429 以前以下に書いた https://ja.stackoverflow.com/questions/8808 の実装は参考になるだろうか。 42430 結局エディタで編集した結果を accept-line と同様に実行すれば良いのである。 42431 42432 エディタの中に記述した履歴展開はちゃんと展開されるのだろうか。 42433 どうやら履歴展開は無効になっている様だ。 42434 42435 うーん。まあ動いている気がする。 42436 42437 ? ok: bash の edit-and-execute の場合 LINENO が増えない 42438 bash の振る舞いは変である。ble.sh では LINENO はちゃんと増える事にする。 42439 それどころか bash では CMD も増えない…。ble.sh では増える事にする。 42440 42441 ? ok: gexec/.begin, prologue, epilogue, end 等は呼び出さなくて良いのか。 42442 うーん。$_ だとか $? だとか $BASH_REMATCH を保存するかどうかも関係してくる。 42443 面倒なので呼び出さなくても良いという事にする。 42444 エディタコマンドであればそれぞれに勝手に stty してくれるだろう。 42445 42446 * 何故か menu-complete に入って C-g すると入力済み部分が消える様になっている… [#D1049] 42447 これは修正した。 42448 42449 * complete: dynamic-complete-history とは何だろう [#D1048] 42450 42451 実際に実行してみた所、履歴の中から単語を切り出して、 42452 更にその単語を候補として利用する物の様である。 42453 42454 しかも適当に試してみるとちゃんと引用符も認識している様な…。 42455 これは対応が難しい。 42456 42457 というか以前にも考察した様な気がする。 42458 dynamic-complete-history は memo.txt を検索しても当たらない。 42459 → #D0820 に議論が残っていた。dabbrev-expand の振る舞いについてだった。 42460 恐らく dabbrev-expand は dynamic-complete-history の menu-complete 版だ。 42461 逆に言えば、dabbrev-expand の実装を調べれば良い? 42462 議論によると COMP_WORDBREAKS によって区切っている。 42463 42464 dabbrev-expand の実装を調べようとしたらこれは incremental である。 42465 どの様に判定しているかだけ確認して実装し直す事にする。 42466 dabbrev で条件判定に使う正規表現などを構築しているのは以下。 42467 42468 local ret; ble/string#escape-for-extended-regex "$original" 42469 local needle='(^|['$wordbreaks'])'$ret 42470 42471 まあ sed 辺りで実装する事にする。というか grep -o が良い。 42472 HISTTIMEFORMAT= builtin history | ble/bin/grep -o "$needle" という具合にする。 42473 実装した。一応動いてはいる。 42474 42475 * 2019-03-28 complete (insert_braces): 遡って書き換わる場合に対応できているか謎 [#D1047] 42476 特にちゃんと前方が置き換わらない様に全候補が調整されているかどうかで振る舞いが変わる。 42477 やはり common-prefix を真面目に求めてから処理する方が良いのかもしれない。 42478 42479 うーん。或いは完全に置き換えてしまうのでも良いのかもしれない… 42480 と思ったが何故それをしないのかというと候補を生成した時点で、 42481 その引用符を前提とした挿入文字列を構築してしまっているからである。 42482 それを braces に変換する為には結局その様な操作が必要になる。 42483 42484 然し、common-prefix を真面目に求めたとしても、 42485 単語の途中で quote の種類が変わる様な場合もある訳だし、 42486 考えれば考える程難しい気がしてきた。 42487 うーん。common-prefix よりも後は CAND から再度クォートして復元するという手もある。 42488 それが候補生成の時に意図した事なのかどうかは分からないが、 42489 まあブレース展開として挿入するという場合には妥協しても良い気がする。 42490 何れにしても CAND は絞り込みなどに使うので物凄く離れた物にはなり得ない。 42491 42492 2019-03-31 determine-common-prefix の実装を確認すると色々微妙である。 42493 曖昧補完の時には色々と複雑な処理をするが、 42494 これはブレース展開による挿入にそぐうだろうか。 42495 そもそも曖昧補完に対してブレース展開による挿入を起こして良いのだろうか。 42496 まあ、候補を確認した上で挿入を起こすというのは考えうる。 42497 42498 然し、曖昧補完の時の determine-common-prefix が返す値は 42499 common-prefix ではなくて common subsequence になっている。 42500 つまりブレース展開を実行する時の前方部分としては使えない事になる。 42501 42502 ではこれとは別に実装すれば良いだろうか。 42503 共通部分を特定して共通部分以降をブレース展開に変換する。 42504 然し、共通部分以降が特定のクォート方法だけで表現されているとは限らない。 42505 今の awk の実装では '...' か $'...' か "..." $"..." しか対応していない。 42506 42507 1 うーん。結局全ての候補が COMPS を共有していれば OK 42508 42509 2 そうでなければ COMPS を遡って書き換える事にする。 42510 特に中途半端に遡っても quote の状態が分からないので、 42511 諦めて全部遡る事にする。 42512 42513 と思ったが、determine-common-prefix の partial comps では何をしていただろうか。 42514 これは ble/complete/candidates/determine-common-prefix/.apply-partial-comps で実装される。 42515 最長一致部分と COMPS を比較する事によって比較を行っている。 42516 42517 うーん。ble/complete/candidates/determine-common-prefix/.apply-partial-comps 42518 を使えるだろうかと思ったが微妙な気がしてきた。 42519 何れにしても遡って書き換えが起こる場合には INSERT ではなくて 42520 CAND の方から再度クォートも含めて再構築する必要があるのではないだろうか。 42521 42522 何だか実装が汚くなった気がするが、まあ動いている。 42523 42524 面倒なので determine-common-prefix に関しても awk で実装する? 42525 →これは駄目。ble/syntax:bash/simple-word を使いたいので。 42526 42527 * 2019-03-28 complete (insert_braces): 末尾で close-quotation するとやはり空の引用符ができてしまう [#D1046] 42528 42529 これは最後に空文字列を除去する所で close-quotation の処理をする事にした。 42530 close-quotation の時に文字列が空ならば始まりの引用符を除去する。 42531 42532 * 2019-03-28 complete (insert_braces): 引用符を閉じてすぐ開くというのを除去したい [#D1045] 42533 42534 これに対応する為にはどの様にしたら良いだろうか。 42535 42536 | a 現在の候補がクォートを必要としているのかしていないのかについての情報を別の方法で保持する 42537 | 特に現在の候補の右側と左側でクォートの状態が異なりうるという事は注意しておくべきである。 42538 | 例えば {a..z}'xx という時には左側は quote が要るけれども右側は要らない。 42539 | 42540 | b 現在の候補の内容に基づいて引用符の中にいるかいないかを自動的に判定する。 42541 | これは曖昧性はないだろうか。現在の実装だと引用符の外にいる状態というのは 42542 | {...} となっている場合しかない気がする。 42543 | と思ったが、実際に本当の文字列が {} を含んでいる場合には、 42544 | それがそのままになっていると駄目である。 42545 | 42546 | c うーん。実は最初に候補を register する時点で quote してしまう? 42547 | と思ったがそれはそれで取扱が難しい。range detection だとか 42548 | 共通部分括り出しの時のクォート除外の処理が増えてしまう。 42549 | 42550 | やはりよく分からなくなった。現在の処理の手順はどうなっているだろうか。 42551 | 一番最初に登録する時にはクォートの中の状態という事になっている。 42552 | その後で reduce する時にクォートの中の状態と外の状態が混ざり合う事になる。 42553 | 42554 | その文字列を観察した時にクォートの中か外化というのを判定するにはどうしたら良いだろうか。 42555 | 例えば、逆に必ずクォートの中にいる状態にとして記録する事にして、 42556 | 端に引用符があればそれを除去する事によってクォートを外せる事にする、等。 42557 | 然し、端に引用符があったとしてもそれがエスケープされた物なのか、 42558 | そうでないのかについては連続する \ を数えなければならない。 42559 42560 うーん。上で提示した手法たちは考えが甘い。 42561 状況が整理できてきたので改めて手法について具体的に考える。 42562 42563 | a 現在の候補が引用符の中にあるのかないのかの情報を 42564 | 本体の文字列とは別に記録する事にする。 42565 | 因みに引用符の中にあるのかないのかは右端と左端で独立である。 42566 | 42567 | x '{a..z}' という文字列と {a..z} というブレース展開は 42568 | 両方共本体の文字列で {a..z} として記録されてしまう。 42569 | 共通部分の括り出しで両者は結合されてしまう。 42570 | かと言って共通部分の括り出しの処理で引用符の状態まで含める様にするのは 42571 | 実装が複雑になってしまう。 42572 | 42573 | b 現在の候補が引用符の中にあるのかないのかを自動判定する。 42574 | 42575 | x これは a と同様の問題がある。 42576 | というより区別できない事例があるので余計に深刻である。 42577 | 42578 | c 最初に登録する時に引用符の中に入れてしまう。 42579 | つまり常に引用符の外側にいる状態で比較などを行う。 42580 | 42581 | x これも共通部分の括りだしを行う時に何だか面倒な事になる気がする。 42582 | うーん。或いは、単純な引用符の場合には問題にならないのだろうか。 42583 | 42584 | 然し、現状で既に引用符を外す場所などで 42585 | to_atoms が変な振る舞いをしないかどうか危ない。 42586 | というか、引用符の中にある {} で問題が発生する気がする…。 42587 | 42588 | d 記録する時は全て引用符の中にいる様にする (つまり今と同じ) 42589 | 結合する時に端に引用符があればそれを対消滅させる。 42590 | 42591 | x この方法の問題はエスケープが絡んできた時に、 42592 | 右端の引用符が対消滅できる物かそうでないか判定する為に、 42593 | エスケープも考慮に入れなければならないという事。 42594 | 42595 | x 引用符の種類によって実装を行わなければならない 42596 42597 問題の切り分けを行う。 42598 42599 問題は (1) どの様に表現するのかという事と、 42600 (2) 引用符が本質的に除去可能かどうか別に記録する 42601 必要があるのかどうかという事である。 42602 42603 - (1) に関しては A 全て引用符の外側と仮定した表現とするか、 42604 B 全て引用符の内側と仮定した表現とするか、 42605 或いは C 引用符の外側でも内側でも良いので最短となる様にするかの選択肢がある。 42606 42607 - (2) に関しては C の時は確実に必要である。 42608 A は一致の処理が面倒になる。というか B でも to_atoms に修正が必要。 42609 然し、to_atoms がちゃんと動作する為には 42610 "クォートの外のパターン" を限る必要があるのでは。 42611 '{' '}' 及び ',' と '{a..z}' である。 42612 然し、そうなると下手に空文字列を消去できない。 42613 42614 うーん。最後の最後に空文字列を除去するのが自然に思われて来た…。 42615 →その様に実装した。 42616 42617 * done: 更に引用符がある時の {...} を atom として取り扱う様に修正した。 42618 42619 * 2019-03-28 complete (insert_braces): range detection のコードはもっとまともな物に書き換えたい [#D1044] 42620 例えば a b c 1 2 3 を {{a..c},{1..3}} 等に縮約するなどできると嬉しい。 42621 これは配列の要素を部分的に書き換える等の方法で実装する事ができるだろうか。 42622 始めの要素に対して負の方向と正の方向に拡張する形で探索するなど。 42623 問題は zpadding に合致する物を探すという事だが、 42624 これは実装し始めれば丁度その実装に合った方法が自ずと分かるだろう。 42625 42626 a 取り敢えず [{type, begin, end}, ...] の形式のデータを 42627 一個候補が現れる度に更新するという方法で実装しかけたが、 42628 これだと、例えば a,b,c,c,d,e (順不同) の時に、 42629 {{a..e},c} ではなく {{a..c},{c..e}} 等になってしまう可能性がある。 42630 できるだけ長い列を取り出すのが自然に思われる。 42631 従って、この実装方針は諦める事にした。 42632 実装途中のコードを以下に残しておく。 42633 42634 function range_extend(type, value, width, _, irange) { 42635 for (irange = 0; irange < nrange; irange++) { 42636 if (range[irange, "t"] != type) continue; 42637 if (width != "" && range[irange, "w"] != width) continue; 42638 if (value == range[irange, "b"] - 1) { 42639 range[irange, "b"]--; 42640 for (jrange = irange + 1; jrange < nrange; jrange++) { 42641 if (range[jrange, "t"] != type) continue; 42642 if (width != "" && range[jrange, "w"] != width) continue; 42643 if (value == range[jrange, "e"] + 1) { 42644 range[jrange, "t"] = ""; 42645 range[irange, "b"] = range[jrange, "b"]; 42646 } 42647 } 42648 return 1; 42649 } else if (value == range[irange, "e"] + 1) { 42650 range[irange, "e"]++; 42651 for (jrange = irange + 1; jrange < nrange; jrange++) { 42652 if (range[jrange, "t"] != type) continue; 42653 if (width != "" && range[jrange, "w"] != width) continue; 42654 if (value == range[jrange, "b"] - 1) { 42655 range[jrange, "t"] = ""; 42656 range[irange, "e"] = range[jrange, "e"]; 42657 } 42658 } 42659 return 1; 42660 } 42661 } 42662 return 0; 42663 } 42664 42665 function range_register_alpha(ialpha, _, irange) { 42666 if (range_extend("A", ialpha, "")) return; 42667 42668 range[nrange, "t"] = "A"; 42669 range[nrange, "b"] = ialpha; 42670 range[nrange, "e"] = ialpha; 42671 nrange++; 42672 } 42673 function range_register_number(value, _, irange) { 42674 width = length(value); 42675 value = 0 + value; 42676 42677 if (range_extend("N", value, "")) return; 42678 if (range_extend("Z", value, width)) return; 42679 42680 range[nrange, "t"] = "N"; 42681 range[nrange, "b"] = value; 42682 range[nrange, "e"] = value; 42683 nrange++; 42684 } 42685 function range_register_znumber(value, _, irange) { 42686 width = length(value); 42687 value = 0 + value; 42688 42689 if (range_extend("Z", value, "")) return; 42690 if (range_extend("N", value, width)) return; 42691 42692 range[nrange, "t"] = "N"; 42693 range[nrange, "b"] = value; 42694 range[nrange, "e"] = value; 42695 nrange++; 42696 } 42697 function simple_range(arr, len, _, iother, i, alpha, value, beg, end) { 42698 alpha = "abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 42699 iother = 0; 42700 for (i = 0; i < len; i++) { 42701 value = arr[i]; 42702 if (value ~ /^(0|-?[1-9][0-9]*)$/) { 42703 range_register_number(value); 42704 } else if (value ~ /^(0+|-?0+[1-9][0-9]*)$/) { 42705 range_register_znumber(value); 42706 } else if (value ~ /^[a-zA-Z]$/) { 42707 r = index(alpha, value); 42708 range_register_alpha(r); 42709 } else { 42710 other[iother++] = value; 42711 } 42712 } 42713 42714 len = 0; 42715 42716 for (i = 0; i < nrange; i++) { 42717 if (range[i, "t"] == "A") { 42718 beg = substr(alpha, range[i, "b"], 1); 42719 end = substr(alpha, range[i, "e"], 1); 42720 value = del_close "{" beg ".." end "}" del_open; 42721 } else if (range[i, "t"] == "N") { 42722 beg = range[i, "b"]; 42723 end = range[i, "e"]; 42724 } else if (range[i, "t"] == "Z") { 42725 beg = zpad(range[i, "b"], range[i, "w"]); 42726 end = zpad(range[i, "e"], range[i, "w"]); 42727 } else continue; 42728 arr[len++] = del_close "{" beg ".." end "}" del_open; 42729 } 42730 42731 for (i = 0; i < iother; i++) arr[len++] = other[i]; 42732 42733 return len; 42734 } 42735 42736 b また別の方針で実装してみる事にする。 42737 実装した。動いている気がする。前のコードは削除する。 42738 42739 2019-03-28 42740 42741 * complete: complete-into-braces に対応する [#D1043] 42742 42743 候補をどの様に braces に変換するのかという事が重要になる。 42744 後、上限の文字数という物を決めておかないと大変な事になる気がする。 42745 42746 | braces にする為には…。実は色々なやり方が考えられるとは思うが、 42747 | 取り敢えず前方から一致させるとどうなるだろうか。 42748 | 42749 | bash がどの様に振る舞うかについて一応確認しておく。 42750 | $ touch hello{a..c}{1..3}.txt 42751 | $ echo hello{a{1.txt,2.txt,3.txt},b{1.txt,2.txt,3.txt},c{1.txt,2.txt,3.txt}} 42752 | 42753 | 成る程。つまり、前方の一致だけしかまとめてくれない。 42754 | ではそうだとしても {a..z} の様な形式にまとめてくれたりするだろうか。 42755 | $ touch world{1..10} 42756 | $ echo world{1{,0},2,3,4,5,6,7,8,9} 42757 | $ touch check{1..9} 42758 | $ echo check{1,2,3,4,5,6,7,8,9} 42759 | この結果を見ると a..z の形式には対応していない様子である。 42760 | 全て , によってまとめられてしまう。 42761 | 42762 | 取り敢えず最短にするなどの事は考えずに挿入すれば良いだろうか。 42763 | 取り敢えずクォートは勝手に外す事にする。 42764 | 42765 | 処理は bash でやるよりも awk 等に投げてしまった方が楽そうである。 42766 | 42767 | - 実装としては漸化式的に考えれば良い。 42768 | 今までに確定した部分と、確定していない部分。 42769 | 一つ前の文字列と較べてどこまで一致しているかで処理が変わる。 42770 | 42771 | - POSIX awk はちゃんと SUBSEP に対応していて、 42772 | 多次元配列 arr[a, b] がちゃんと使える。 42773 | ちゃんと各要素の長さを別に管理すればちゃんと使える。 42774 | 42775 | - いざ {} を閉じる時に末尾からの brace expansion 取り込みを実行すると良い。 42776 | そして最後に {a..z} 等の様なパターンに一致しないかというのをチェックする。 42777 | 42778 | - 複数の箇所に brace 展開が現れない限りは、 42779 | 最後に残る物は '^[0-9]+$' か '^[a-z]$' の時だけ {a..z} にまとめられないか 42780 | チェックするだけで十分の筈である。 42781 | 42782 | うーん。この様に実装すれば bash の braces にまとめる機能よりも強力に 42783 | すっきりと brace expansion にまとめる事ができる。凄い。 42784 | 42785 | 取り敢えず、始めは欲張らずに先頭からの一致について実装を試みるのが良い。 42786 | うーん。クォートとかはどうしたら良いのだろうか。 42787 | これも多分どうにかなるので取り敢えずは実装する事にする。 42788 | 42789 | →いろいろバグを出したが取り敢えず動いている様な気がする。 42790 | また後で実装を確認してみる事にする。 42791 42792 一度実装してみて何となく分かったので再度上の議論を整理する。 42793 42794 * done: 改行を含む候補に対応する為には環境変数を使うしかないだろうか。 42795 と思ったが環境変数のサイズこそ制限があるはずである。 42796 大量のデータを環境を経由して渡すのは非現実的である。 42797 42798 他の方法としては \0 で区切って渡すという物だが、 42799 RS = "" の時の振る舞いは POSIX で "空行" で record を区切るという物の様である。 42800 一方で RS = "\0" は gawk は認識するが可搬ではない。 42801 従ってこの方法も取りづらい。 42802 42803 或いは ASCII か Unicode の特別な文字を使って分離するという手もある。 42804 特に制御文字で (^0 以外の) 誰も使いそうにない物を使う。 42805 意味的には FS などを使いたくなるが誰かが使いそうな気もする。 42806 伝送制御 DLE 等は誰も使いそうにない気がする。 42807 DEL だとかは意味的には NUL に近いので使いたくなる気もするが、 42808 こういった有名な物はやはり誰かが使いそうな気がするので避けたい。 42809 42810 完全な答えではないが DLE を使うのが一つの手である。 42811 C1 の文字を使うてもあるとも思ったが、 42812 本当に文字コードに依存しないのかどうか怪しいので止めておく。 42813 うーん。しかし C0 文字というのは実は Ctrl-X に対応しているので、 42814 制御文字としては使われなくてもキーボード操作として使われる事はあるのではないだろうか。 42815 やはり ^@ を使って分割したい気がする。 42816 42817 或いは初期化時に備え付けの awk の特性を調べておくというのも手かもしれない。 42818 或いは起動が遅くなるのは嫌なので一番最初の実行時で良い。 42819 2回目以降の呼び出しではキャッシュした内容を使用する。 42820 % と思って gawk で試してみたが RS = "\0" を認識していない…。 42821 % stackoverflow の記事に騙された…? 42822 % https://stackoverflow.com/questions/9170119/could-sed-or-awk-use-nul-character-as-record-separator 42823 % の最初の回答の最初のコメントによると確かにそう書かれている様に見える。 42824 % https://www.gnu.org/software/gawk/manual/html_node/gawk-split-records.html#gawk-split-records 42825 % にもその様に書かれている。 42826 あー。<<< $'a\0b' だと bash の側で \0 以降を消去してしまうのであった…。 42827 printf 'a\0b\0c' で流し込んだら実行できた。OK。 42828 gawk ではなくて awk の名前で起動してもちゃんと認識している。 42829 42830 一応対応した。動いている。 42831 42832 * done: 先ず候補は sort -n 的な方法で sort して置きたい。 42833 そうしないと {1..10} の様な場合に対応する事ができない。 42834 sort を呼び出すにしても改行区切りでないと辛いのでは。 42835 42836 調べてみると sort には -z オプションがある。NUL で区切れる。 42837 と思って POSIX に行くと -z は廃止されたと書かれている。駄目だ。 42838 42839 或いは落ち着いて考えてみると {1..10} の様な場合については、 42840 順番が変わっても (どうせ sort という作戦を取ろうとしていたのだし) 42841 良いので連番になっているかどうかをチェックする、というので良い気がする。 42842 42843 * done: クォート等に関しては現在の実装の to_atoms を場合に応じて 42844 適切に選択する事で対応できる気がする。 42845 というかそもそも引用符は外さないとブレース展開を有効にできない。 42846 或いは、ブレース展開の周辺だけ引用符を外すという手もあるのかもしれない。 42847 何れにしても文脈に応じた to_atoms と出力を実施したい。 42848 42849 to_atoms だけではなくて quote を閉じたり開いたりするのも実行しなければならない…。 42850 取り敢えずそれも実装した。本当にこれで良いのだろうか…。 42851 うーん。前方まで置き換わる場合など考えると不完全な気がする…。 42852 42853 無駄に沢山の引用符が挿入されてしまうなど課題は残っている気がするが、 42854 それはまた別の項目を立てて考察するのが良い気がする。 42855 42856 また現状の振る舞いが変なので修正をしなければならない。 42857 42858 x fixed: どうも rfrag[-1] がクリアされていないのが問題の様である。 42859 というかそもそも rfrag[-1] を使うという事自体が変である。 42860 →修正した。前よりもすっきりしたコードになった。 42861 42862 x fixed: {1..10} の様な物に対応したと思ったが、 42863 その前に前方括り出しで 1{,0} 2 3 4 ... に変換されてしまうので、 42864 {1..10} にはならないという事が分かってしまった。 42865 42866 | これはどの様に対処すれば良いだろうか。例えば、 42867 | 数字の連続に関しては atom として取り扱う等? 42868 | そうしても問題ないだろうか。例えば 120 110 150 を 42869 | 1{2,1,5}0 ではなくて {120,110,150} にするという事。 42870 | うーん。数字の連続は atom にした方が分かりやすそうだ。 42871 | とも思ったが、これが物凄く沢山数字が並んでいて末尾の数字だけ違う等だと大変。 42872 | 然し、二桁以上の数字の場合には必ずこの様に分解される事は必定。 42873 42874 従って、やはり数値は atom として取り扱うべきなのである。 42875 42876 数値を atom にしても動かない。 42877 前の番号が w1 の時 w10 が来たとすると w1 まで一致しているので、 42878 0 以降を atom で分解する様にしようとしている。 42879 うーん。これは get_matching_depth を修正する必要がある。 42880 42881 修正した。適当に修正したら何だか完全に動く様になった気がする。 42882 これで気にしない事にする。 42883 42884 2019-03-25 42885 42886 * main: 今や inputrc を勝手に読み込んでも良いのではないか [#D1042] 42887 42888 後、inputrc を読み込まない様にする設定も欲しい。 42889 然し、bleopt を呼び出すのは blerc の中か ble.sh を source した後である。 42890 然し、その時には既に inputrc は読み込まれている。 42891 42892 * fixed: うーん。所で .inputrc の中で set editing-mode vi 等とした時に、 42893 ちゃんと keymap が正しいものに選択されるのだろうか。 42894 opt_keymap に使われる既定の文字列は空文字列にしている。 42895 という事を考えたが辿ってみると、ちゃんと空の時には、 42896 ble-decode/DEFAULT_KEYMAP → bleopt/get:default_keymap 42897 という経由で正しい物が選択される様になっている。 42898 但し、 ble-decode/DEFAULT_KEYMAP は edit.sh 側で上書きされた物でなければならない。 42899 42900 うーん。decode.sh の ble-decode/DEFAULT_KEYMAP の時点で 42901 ちゃんと切り替わる様になっているべきなのではないか。 42902 →最初からその様になるように実装し直した。 42903 42904 * ok: 後、read-inputrc の中で呼び出している bind は…。 42905 勝手に二重に起動されていたりはしないだろうか。 42906 →大丈夫。ble/builtin/bind/.process しか呼び出していない。 42907 そして ble/builtin/bind/.process が呼び出しているのは 42908 オプションを指定した時の builtin bind だけである。 42909 42910 * fixed: 万が一 - で始まる内容が inputrc の中に含まれていたとしても、 42911 それをオプションとしてではなく束縛の設定として解釈させるために、 42912 -- をつける必要があるのではないか→つけた。動く事を確認した。 42913 42914 inputrc を読み込まない為の設定として 42915 ble.pp に --noinputrc というオプションを追加した。 42916 これを指定していない限りは .inputrc を読みに行く事にする。 42917 42918 * done: bleopt_internal_suppress_bash_output に対応する機能も 42919 引数から指定できる様にするべきなのでは。 42920 というかそもそも bleopt_internal_suppress_bash_output= は動作するのだろうか。 42921 今試してみた所、一応ちゃんと動いてはいる様である。 42922 オプションの名前を考える事にする。 42923 42924 --debug-enable-bash-output 42925 --debug-keep-bash-stdout 42926 --debug-keep-bash-output 42927 --debug-no-interrupt-bash-output 42928 --debug-free-bash-output 42929 --debug-full-bash-output 42930 42931 うーん。keep が良い気がする。debug という prefix は必要だろうか。 42932 まあ、debug 用の機能という事が分かる様に debug はつけるべきである。 42933 或いは debug が動詞だと考えるのであれば、 42934 42935 --debug-bash-output 42936 42937 でも良いのではないだろうか。うーん。これが良い気がする。 42938 42939 * done: --help にも対応するべきなのでは 42940 うーん。引数を解析するのは実は全ての初期化を終わった後である。 42941 然し、--help や --version を表示する為だけに全部ロードするというのは変である。 42942 その様に考えると最初に引数の解析は終わらせて置くべきなのだろうか。 42943 42944 因みに version を解析する箇所は check-environment の後である。 42945 version だけは一番最初に初期化してしまっても良い気がする。 42946 42947 うーん。--help や --version は実はシェルに依存せずに動作して欲しいのではないだろうか。 42948 その様に考えると、実は引数の解析は sh 準拠で実装しなければならないという事になるだろうか。 42949 42950 対応した。簡単な対応なので --rcfile --help 等の指定があっても反応してしまうが、 42951 面倒なので妥協する事にしようと思う。sh で解析するのは面倒である。 42952 42953 * emacs: insert-comment に対応する [#D1041] 42954 42955 x fixed: 実行している途中で落ちると思ったら 42956 redispatch の実装を誤っていて無限ループになっていた。 42957 decompose-meta で修正した物に置き換えている積もりが、 42958 元と同じキーシーケンスを食わせていた為であった。修正した。 42959 42960 対応した。動いている様に見える。 42961 元の bash では先頭にしか # を入れないが、 42962 ble.sh の実装では各行に挿入する事にした。 42963 42964 * emacs: character-search{,-backward} に対応する [#D1040] 42965 42966 これは文字を一つ受け取って実施する所も含めて vi の f と同様の機能である。 42967 但し、key を受け取るのではなくて本当に char を受け取る。 42968 つまり、quoted-insert と同様という事である。 42969 42970 delete-forward-char-or-list も実装が簡単だったので一緒に実装した。 42971 42972 2019-03-24 42973 42974 * emacs: readline-dump-{functions,macros,variables} に対応する [#D1039] 42975 これはとても簡単だった。本来は ble-bind の設定を出力するべきなのではないか、 42976 と思わないでもないが面倒なのでこれで良い。 42977 42978 もし実装するとしたら dump-macros については 42979 ble-bind -P | grep 'ble-bind -m [^ ]+ -s ' 等として出力するしかない。 42980 また dump-functions の様な逆引き機能を提供するのは難しい。 42981 真面目にやろうと思うと全ての widget について keymap を検索しなければならないので非効率的である。 42982 dump-variables はそのまま readline の変数を出力してしまえば問題ない。 42983 何れにしても余り必要性を感じないので現段階では ble-bind 版は提供しない事にする。 42984 42985 * edit: re-read-init-file に対応する [#D1038] 42986 既に decode.sh で ble/decode/read-inputrc を実装しているから簡単だと思ったが、 42987 よく考えたら本当にそうだろうか。 42988 set keymap に応じて現在の keymap を切り替える必要があるのではあるまいか。 42989 これは以前 ble/decode/read-inputrc を実装した時の手落ちである。 42990 42991 [調査] 42992 42993 opt_keymap が空の時には set keymap で指定した所から読み出す必要がある。 42994 うーん。本当だろうか。実はこれが有効なのは inputrc の中だけだったりはしないだろうか。 42995 振る舞いを調べなければならない。 42996 42997 | 実際に set keymap をすると完全に keymap が切り替わってしまう。 42998 | うーん。これはどの様に処理したら良いのだろうか。 42999 | 要するに bind の呼び出しを跨いで "現在の keymap" という物が存在するという事になる。 43000 | これはグローバル変数にでも記録しておくしかないだろうか。 43001 | 然し、グローバル変数に記録した "現在の keymap" というのをクリアするタイミングというのは何か。 43002 | 例えば bash の場合にはコマンドを実行する度に keymap はリセットされる様である。 43003 | 然し、コマンドが実行されない限りはリセットされずに保持されている。 43004 | 本当だろうか。と思ったが、コマンドが実行されてもリセットされずに保持されている。 43005 | そして bind の適用対象は相変わらず set keymap で指定した keymap になっている。 43006 | 43007 | - done: $include を跨いでも持続するのかどうか → yes 43008 | - done: bind -f を跨いでも持続するのかどうか → yes 43009 | D1038.test1.* を用いて調べた。結果は 43010 | $ source D1038.test1.0.sh 43011 | # keymap emacs 43012 | "A": "from 0.sh" 43013 | # keymap vi-insert 43014 | "B": "from 1.inputrc" 43015 | # keymap vi-command 43016 | "C": "from 2.inputrc" 43017 | "D": "from 1.inputrc" 43018 | "E": "from 0.sh" 43019 | set keymap vi 43020 | 43021 | 内部で設定した keymap が外側にも残っているという事が分かる。 43022 | つまり $include を使っても bind -f を使っても設定は持続する。 43023 | 43024 | - 因みに bind -f はそれを記述しているソースファイルからの相対パスではなく 43025 | 現在のディレクトリからの相対パスとして解釈される。 43026 | 一方で $include に関しては、それを記述している inputrc ファイルからの相対パスで行ける。 43027 | と思ったら勘違いだった。現在のディレクトリからの相対パスでなければならない。 43028 | ファイルが見つからなかった場合には何もエラーメッセージがなく失敗する。 43029 | 43030 | - done: re-read-init-file (inputrc) を跨いでも持続するのか 43031 | →抜ける時に既定の物になる(入る前の状態に復元する訳ではなく editing mode に固有の keymap に矯正される) 43032 | 43033 | これはどの様に調べれば良いか。C-xC-r で re-read-init-file を呼び出す事ができる。 43034 | INPUTRC=D1038.test1.1.inputrc 43035 | \C-x\C-r 43036 | という具合にすれば良いだろうか。 43037 | うーん。 D1038.test1.0.sh の中身で bind -f の行の部分だけ 43038 | INPUTRC=D1038.test1.1.inputrc 43039 | \C-x\C-r 43040 | に置き換えて実行すれば良い気がする。 43041 | うーん。そもそも C-xC-r で読み込まれていない気がする。 43042 | 43043 | 実際に試してみると re-read-init-file の中で設定した keymap は見えない様である。 43044 | というか re-read-init-file を実行すると keymap はリセットされる様子である。 43045 | また、re-read-init-file の中では外側で設定されていた keymap は見えるのだろうか。 43046 | 確認してみた所外側で設定されていた keymap が保持されている様である。 43047 43048 まとめ 43049 43050 * set keymap をすると本当に編集に用いている keymap が切り替わる。 43051 当然 bind の既定の対象も切り替わる。 43052 * コマンド実行を跨いでもその効果は持続している。 43053 * bind -f や $include の中で行った切り替えも外側に影響を与える。 43054 * 外側の設定は re-read-init-file の中で見えるが、 43055 re-read-init-file が終わる時に既定の keymap に強制的に戻る。 43056 * bind -f filename 及び $include filename は現在のディレクトリからの相対パスである。 43057 これらのコマンドを記述しているスクリプト・初期化ファイルからの相対パスではない。 43058 (ble.sh ではファイルからの相対パスに対応しているが余計な機能だったかもしれない) 43059 43060 [実装] 43061 43062 * fixed: うーん。何と現在の editing mode と関係なく keymap を切り替える事ができて、 43063 しかも切り替えるとその editing mode でコマンドラインが編集できるという状況である。 43064 これは微妙である。ble.sh が動かなくなってしまう原因なので、修正する必要がある。 43065 因みに set -o emacs もしくは bind 'set editing-mode emacs' を明示的に呼び出せば、 43066 既定の keymap に自動的に戻る様子である。つまり、ble-decode/attach する直前に 43067 set -o emacs もしくは set -o vi を呼び出せば良いという事になる。 43068 43069 * fixed: うーん。ユーザのコマンドによって keymap が勝手に切り替えられてしまうという事はあるだろうか。 43070 そういう事があった場合でも ble.sh は動作を停止してしまう事になる。 43071 その様な場合への対策として、やはりコマンドを実行した後に keymap を復元する必要がある。 43072 実際に試してみた所、確かに一時的に変な状態になってしまうが RET を押すと治る。 43073 恐らくコマンドを一つ実行すれば元の keymap になって動作が戻るという事なのだろう。 43074 43075 * done: 現在の bind の対象の keymap を _ble_builtin_bind_keymap に保持する事にした 43076 43077 * ok: bind -f 及び $include は現在のパスからの相対パスを優先させる? 43078 うーん。普通に考えたらファイルパスからの相対パスを優先させる方が自然である。 43079 なので、bash の振る舞いと変わってしまう所ではあるが現在の振る舞いを保持する事にする。 43080 43081 まあ、これで多分大丈夫だろうという気がする。動作チェックは面倒なのでしない。 43082 試しに source D1038.test1.0.sh を実行してみた所、ちゃんと動いていた。 43083 但し、bind -s は代わりに ble-bind -P | grep ' -s ' としなければならない。 43084 re-read-init-file についても動作確認してみた。 43085 43086 * fixed: ble-bind のエラーメッセージに ble edit function という語句が含まれている 43087 * fixed: bind 'set editing-mode' の時に keymap はクリアするべきではないのか。 43088 43089 * edit: kill-while-line に対応する物があったのではないかと思ったが [#D1037] 43090 そういう物は実装されていない様だった。kill-forward-line (C-k) 及び 43091 kill-backward-line (C-u) に倣って実装しようと思ったが、 43092 それぞれ logical/graphical の二種類があって、 43093 更に引数の有り無しで改行も一緒に消すかどうかの動作まで切り替わる様で、 43094 何だか複雑だったので最初から実装し直す事にした。 43095 最初から実装し直したらすっきりとした実装になった。 43096 43097 * menu-complete: 現在 "表示" されているメニュー項目から候補を生成している? [#D1036] 43098 ble/complete/menu/generate-candidates-from-menu の実装を見て思った。 43099 menu-filter した後の menu_items ではなくて、 43100 更にその後に表示を行っている menu_icons から読み取っている気がする。 43101 43102 * global: builtin echo を関数に置き換えるというのはどうだろうか [#D1035] 43103 43104 実際に benchmark-201903-builtin-echo.sh というスクリプトで試してみる。 43105 7.37 usec/eval: echo.normal (x10000) (echo) 43106 7.70 usec/eval: echo.builtin (x10000) (builtin echo) 43107 10.97 usec/eval: echo.function1 (x10000) (関数内で builtin echo) 43108 12.37 usec/eval: echo.function2 (x10000) (printf %s\n による実装) 43109 43110 まあ、誤差の範囲内である。 43111 ふと思って &>/dev/null の繋ぎ変えを削除して実行してみる。 43112 43113 3.22 usec/eval: echo.normal (x20000) 43114 3.63 usec/eval: echo.builtin (x20000) 43115 6.75 usec/eval: echo.function1 (x10000) ble/builtin/echo1 43116 7.67 usec/eval: echo.function2 (x10000) ble/builtin/echo2 43117 43118 うーん。実は二倍ぐらいの時間がかかっているという事か。 43119 echo の呼び出しと、関数呼び出しと、&>/dev/null の時間は大体同じぐらいという事。 43120 然し、ユーザで echo を置き換えてやろうという事を考える人は本当にいるだろうか。 43121 例えば、echo の振る舞いを標準化してやろうとして echo を置き換えたいという人はいるかもしれない。 43122 43123 6.35 usec/eval: echo.functionS (x10000) ble/print 43124 6.29 usec/eval: echo.functiont (x10000) ble/p 43125 43126 うーん。やはり関数名は短い方が高速に動作する様子である。 43127 43128 a ble/print 的な関数を作ってしまっても良いのかもしれない。 43129 43130 b ble/p でも良い? 然し汚い感じがする。 43131 というか其処まで速度を気にする必要はない筈である。 43132 43133 c ble/builtin/echo という事にしようか。 43134 しかし ble/builtin/* は builtin を置き換える関数の為の名前だった気がする。 43135 従って、やはり別の名前の方が良いのではないか。 43136 本当に builtin の関数を呼び出したければ builtin echo とする。とそういう物。 43137 43138 d ble/bin/echo は大丈夫だろうか。 43139 ble/bin は command として実行する為に置き換えられてしまうのではないか。 43140 と思って調べてみたが、別に明示的に指定しない限りは特に置き換えは起こらない様である。 43141 考えてみれば当たり前である。わざわざ呼び出される度に検査する訳ではないので、 43142 勝手な置き換えは起こらない。 43143 43144 問題は ble/bin/echo だと command 版が呼び出される様に錯覚してしまう事である。 43145 うーん。やはりコマンド版が呼び出されると勘違いしそうなので良くない。 43146 43147 e 或いは ble/util/print でやはり良いのでは。。ble/util/p とか。 43148 と思ったが -n に対する処理を考えるとやはり echo が良い。 43149 43150 f そう思うと ble/util/echo という手もある。 43151 43152 うーん。考えるのが面倒になったので、取り敢えず ble/bin/echo という事にする。 43153 43154 * vbell: menu complete でページを移動している時に [#D1034] 43155 ページ番号が短くなった時に前の表示を消しきれていない。 43156 43157 うーん。persistent だったとしても前の表示を消して良い筈。 43158 と思ったが、persistent の時にはすぐに終了してしまう? 43159 そして終了してしまうともう表示されていないのではないかと判定されてしまう。 43160 workerfile を空にせずに終了すれば良いのではないか。 43161 そうすれば未だ表示されている内容があるという事の意思表示になる。 43162 43163 問題になっていたのは worker が生きているのにも拘わらず、 43164 workerfile の中身が空になって、他の worker の為に同じ 43165 workerfile が使われてしまうという事だった。 43166 従って、worker だけが生き続けて workerfile が有限の内容を持ったまま残るというのは問題ないのでは。 43167 43168 x と思ったのだが、よく考えたらそうでもない。これだとその workerfile はずっと残り続けてしまう。 43169 うーん。worker が終了したらやはり消去するべきなのである。 43170 43171 * 所で worker が予期せず終了して workerfile をクリアしなかったらどうなるのだろうか。 43172 その様な場合にも workerfile が残り続けてしまうが、 43173 そういった事故はそんなには起こらない筈なので多少残っていても問題はない。 43174 43175 結局、思っていたよりも様々な状態があるという事。 43176 43177 - 次の表示が始まっていて既に表示は消えている状態 43178 これは ftime と有限サイズ workerfile のタイムスタンプを比較して判定できる。 43179 - 未だ表示されていてそして worker も生きているという状態 43180 これは workerfile が有限の大きさを持っている事によって判定できる。 43181 - 表示が消されていて worker も消えているという状態 43182 これは workerfile が空になっている事で確認する事ができる。 43183 43184 if [[ -s $workerfile && $workerfile -ot $ftime ]]; then 43185 # worker は生きているが、既に消去済み 43186 elif [[ -s $workerfile ]]; then 43187 # worker は生きていて、表示も消されていない。 43188 else 43189 # worker は死んでいる。workerfile は再利用可能。 43190 fi 43191 43192 これに加えて表示は未だされているが worker は死んでいるという状態がある。。 43193 これはどう判定したら良いのだろうか…。 43194 実は単純にダミーの workerfile を作れば良いという事になるだろうか。 43195 "死んでいて動いていない worker" の workerfile として *.Z というのを作る。 43196 これは .erase-previous-visible-bell の判定に入るのでこれで動く筈。 43197 43198 動作確認した。ちゃんと動く様になっている。 43199 43200 * menu: 取り敢えず menu 選択機能だけは実装する [#D1033] 43201 43202 * done: iloop をもっと別の名前にする 43203 →これは主に menu#construct の中だけで使われている。menu_iloop にした。 43204 更に complete 中に使う判定ではなくて menu 専用の判定に切り替えた。 43205 43206 * linewise に項目番号を表示する機能をつけても良いのではないか 43207 或いは > だとかそういう装飾を設定できる様な自由度があって良いと思う。 43208 43209 考えてみたがどういう自由度を持たせるのかというのは難しい。 43210 項目番号だけしか提供しないのであればそれで良いのかもしれないが、 43211 例えば複数選択時に選択されているかどうかの表示を含めるとか、 43212 或いは何かの文字を表示するとか、番号に応じて色を変えるだとか、 43213 或いは番号を二種類表示するとかそういう事があったらどうするのだろう。 43214 43215 例えば PS1 の様に \? という形式で指定できる様にするとしても、 43216 フォーマットをどの様に指定するかが問題である。 43217 printf の様に %d 等の形式にするとすると、 43218 フィールドの順序と数は固定しなければならなくなってしまう。 43219 然し、現実的な事を考えれば複数選択時には別の枠組みで表示するべきだし 43220 (ユーザの設定によって表示されたりされなかったりというのは不便である)、 43221 番号の他に表示するべき項目などはあるだろうか。 43222 43223 その様に考えるとやはり printf と %d を用いた形式で 43224 指定できる様にするのが現実的な感じがする。 43225 問題はどの様に外部から指定するのかという事。 43226 bleopt で指定する仕組みにすると (一時的な変数だとしても) 43227 何だか global な設定を指定している様な感じがして変である。 43228 或いは menu_style 変数に引数を指定できる様にするか。 43229 うーん。やはり bleopt で指定できる様にするのが良い気がしてきた。 43230 43231 変数名はどの様な物が良いだろうか。 43232 bleopt menu_linewise_number_format 43233 bleopt menu_linewise_ps 43234 bleopt menu_linewise_fmt 43235 bleopt menu_linewise_bullet_format 43236 bleopt menu_linewise_prefix 43237 長いのも何だか面倒なので最後のにしようか。 43238 然し、prefix は乱用しすぎて何だかわからない。 43239 43240 * reject: 或いは bleopt menu_linewise_format='%d %s'等にして、 43241 番号と項目の両方を指定させてしまうという手もあるかもしれない。 43242 43243 x うーん。幅がずれたりするのを調整するのが面倒である。 43244 しかし、幅という事で言えば %3d 等とした時点で 43245 予想外の数の候補が来た時には何れにしてもずれる事になる。 43246 ? 後は、%s に何を指定するのかという事もある。 43247 %s に指定するのは SGR も含めた文字列だろうか。 43248 だとすると printf を適用するのは SGR の処理の後である。 43249 従って番号の着色は指定する事ができない。 43250 x というか項目の選択範囲の計算がこれだとできないから駄目。 43251 43252 まあ、取り敢えず最後の物を使うことにする。 43253 取り敢えず実装してみた。動いている。 43254 43255 実装はしてみたが何の役に立つのかよく分からなくなってきた。 43256 もっと高機能になってから具体的な用途を持って使わないとインターフェイスが定まらない。 43257 これ以上編集するとごちゃごちゃしそうなので取り敢えず commit する事にする。 43258 43259 そもそも現在の menu#start という関数は適切なのだろうか。 43260 menu_style は決め打ちだし、menu.class も決め打ちである。 43261 そして、引数に与えた文字列を選択できるだけという物である。 43262 また、気になるのはこれを widget の中で使う分には良いが、 43263 通常のコマンドとして実行してしまうと、 43264 すぐに終了して読み取り待機状態になるので表示が乱れてしまうという事。 43265 43266 うーん。vi_cmap と同様に新しいプロンプトを出して処理するとか、 43267 そういう事が必要になるのではないか等。 43268 然し、現状では使い道がないのでサンプル実装として menu#start を置いて置く事にする。 43269 これに依存したコードは未だ書かない様に注意する必要がある。 43270 43271 * menu: \commit での menu の項目の着色が消えている? [#D1032] 43272 調べてみると comp_type が空になっていて着色が無効になっていた。何故だろうか。 43273 →これは sabbrev では comp_type が空のままだからであった。 43274 readline variables の読み取りを sabbrev でも行う様にした。 43275 43276 更に選択するとやはり着色が無効になっていた。 43277 これも選択の度に comp_type が空になっているのが原因であった。 43278 comp_type を初期化する様に修正した。 43279 43280 readline variables の読み取りの箇所は comp_type を宣言した所であるべきでは。 43281 と思ったが別に現状で良い気がしてきた。menu から読み取る場合には 43282 結局以前使った comp_type を復元するのだから、 43283 実際に候補を生成する場所で comp_type を作れば良いのである。 43284 その様に考えると現在の場所で問題ない様に思われる。 43285 43286 * menu: desc の説明が取得できなくなっている… [#D1031] 43287 これは local desc としてしまっていたのが問題だった。直した。 43288 43289 * decode: charlog/keylog に関して再考 [#D1030] 43290 43291 うーん。menu_complete/exit-default 等は redispatch でなくても本当に良いのか。 43292 改めて考えてみる事にする。入れ子の呼び出しの場合には keylog は記録されない。 43293 43294 x fixed: また、ble-decode-char の _ble_decode_keylog_chars に登録する場所で 43295 43296 | _ble_decode_keylog_depth のチェックが本当に効いているのかというと怪しい。 43297 | というのも ble-decode-char は入れ子の呼び出しの場合には、 43298 | 実際の実行を呼び出し元に任せてすぐに抜けるからである。 43299 | つまり、常に一番外側でしか char を処理しないので、 43300 | _ble_decode_keylog_depth は常に 0 になっている。 43301 | 従って、入れ子の呼び出しによって再度 ble-decode-char を処理する、 43302 | というような場合にも全て処理した文字が登録されてしまう事になる。 43303 | 43304 | これを正しく処理する為にはどの様にしたら良いだろうか。 43305 | 例えば ble-decode-char を呼び出す際に charlog に記録されている内容を pop するなど? 43306 | どういう箇所で ble-decode-char が呼び出されているだろうか。確認する。 43307 | - マクロ再生の箇所2箇所 (vi, emacs) 43308 | - ble/builtin/read のループ 43309 | 43310 | うーん。逆にこの箇所に於いて charlog の suppress を明示的に指定すれば、 43311 | 他は全て charlog に記録されてしまっても問題ないのでは。。 43312 | と思ったが、此処で明示的に suppress を指定したとしても、 43313 | 結局処理が遅延されるのであれば suppress が効果を発揮しない。 43314 | (char buffer に登録する時に suppress の情報も一緒に記録する、 43315 | というようにするのは無駄に処理が複雑になるので余り考えたくない。) 43316 | 43317 | 逆に再生中は記録状態にはないと考えて、 43318 | そのまま記録させてしまうというのでも良いのかもしれない。 43319 | 或いは、再生に用いた文字を pop して、 43320 | 再生内容で置き換えるという様に考える。 43321 | そちらの方が現実的の様な気がしてきた。 43322 | 43323 | と思ったが本当だろうか。やはり "再生" という処理をしたというのは 43324 | 記録に残っても良いのではないかという気もする。うーん。 43325 | 43326 | うーん。何故こんなにも複雑になってしまうのか。 43327 | 本来はもっと簡単な事ではないのか。 43328 | 例えば、ユーザから入力された文字については記録するけれども、 43329 | マクロ再生などによって入ってきた文字については記録しないという具合に。 43330 | 問題は何処にあるのかというと。処理の順番にある。 43331 | 処理の遅延を考えないのだとしたら、 43332 | 普通にユーザから入力された文字を受け取った時点で記録すれば良い。 43333 | マクロ再生などの場合には記録せずに処理を行えば良い。 43334 | 然し、処理を遅延させている場合には、単に記録すれば良い訳ではない。 43335 | 例えばマクロの記録をしている時には、 43336 | マクロの終了が呼び出された段階での charlog の内容を見ると問題になる。 43337 | charlog には未だ処理されていないが既に受信した文字などが全て入っているからである。 43338 | 従って、charlog には実際に処理した文字を追加するという様にしなければならない。 43339 | 43340 | うーん。現在エラー文字に関しては特別のフラグを立てて処理している。 43341 | 結局、同様に特別なフラグを立てて charlog に入れないという様にするのが良さそうである。 43342 | depth のチェックは意味をなしていないので削除する。 43343 43344 結局 buffering を行う ble-decode-char に於いて 43345 自動的に charlog に登録するかしないかを判定するのは困難であるという結論。 43346 従って、ble-decode-char に文字を渡す時点で、 43347 文字にフラグを設定して charlog に登録しない事を明示する事にした。 43348 43349 改めて exit-default における redispatch について考える。 43350 43351 * resolved: charlog に関してはこれで多分問題ないと思われる。本当か。 43352 43353 | 具体的に動作を考えてみる。 43354 | 43355 | 1. exit-default が呼ばれる 43356 | 2. ble-decode-key で改めてキーが処理される 43357 | 然し、charlog は通過しないので勝手に新しい文字が増える事はない。 43358 | 3a. (2) の結果として例えば普通のコマンドが選択されたとする。 43359 | この場合にはやはり charlog に対しては何も起こらない。 43360 | また、この呼出は入れ子の呼び出しになっている為、 43361 | _ble_decode_keylog_depth が多い。従って charlog のクリアも起こらない。 43362 | 3b. (2) の結果として end-keyboard-macro が呼び出されたとする。 43363 | この場合には charlog#pop が呼び出されて 43364 | 元々の exit-default 呼び出しに要した文字の列が削除される。 43365 | 43366 | うーん。この動作は本当に大丈夫なのだろうか。 43367 | 考えてみれば end-keyboard-macro が複数回呼び出される様な事があると、 43368 | charlog#pop が複数回呼び出されて変な事になる気がする。 43369 | 従って、charlog#pop に相当する操作は配列を得た後で行うべきなのでは。 43370 | もしくは charlog#end-without-current-call 的な物。 43371 | charlog#end-exclusive という名前にする。 43372 | 43373 | と思ってよく考えてみたらどうせ #pop した後に #end して 43374 | 中身は空になるので複数回呼び出しても余り問題はなかった気もする。 43375 | 然し、設計としてはこちらの方が自然なのでそれで良い。 43376 | 43377 | 4. ble-decode-key が終わったら exit-default に戻る。 43378 | そして exit-default を抜けると keylog_chars_count がクリアされる。 43379 43380 charlog#pop & charlog#end ではなくて、 43381 charlog#end-exclusive という関数で取り出した後に削る事にした。 43382 これで良い気がする。 43383 43384 うーん。よく考えたら駄目な気がして来た。 43385 というのも、再生した時には exit-default までを実行したいはずなのでは。 43386 然し、現在の記録方法だと exit-default も exclude されてしまう。 43387 とは言っても、一方だけを exclude するのは不可能である。 43388 うーん。入れ子の呼び出しの時には exclude しないという事にするか。 43389 →charlog#end-exclusive-depth1 というのを実装した。 43390 43391 * resolved: keylog に関しては真面目に考え直す。現状使っていないとは言え。 43392 43393 | 例えば次の様に動作をする事にする。 43394 | 43395 | 1. exit-default を呼び出す (KEY が記録される) 43396 | 2. 中で ble-decode-key を呼び出す。 43397 | この時 _ble_decode_keylog_depth の効果により、 43398 | KEY が重複して記録されるという事はない。 43399 | 3a. これで呼び出されるのが通常コマンドの時は何も問題はない。 43400 | 3b. もし呼び出されるのが keylog#end を利用する物だったら。 43401 | keylog#pop & keylog#end をしてそれまでの記録を取得する。 43402 | この時 ${#KEYS[*]} は本当に正しいのだろうか。これはとても怪しい。 43403 | うーん。_ble_decode_keylog_chars_count と同様に処理するべきなのでは。 43404 | →_ble_decode_keylog_keys_count を導入した。 43405 | 4. ble-decode-key, exit-default を抜けると終わる。問題はない。 43406 | 43407 | keylog を用いてマクロを実装するとしたら、 43408 | charlog#end-exclusive-depth1 と同様の事をしなければならない。 43409 | 因みに vi.sh の qx...q の側でも迷い込んだ q は無視する様に既になっていた。 43410 43411 _ble_decode_keylog_keys_count を導入した。 43412 今後 keylog によるマクロを実装する場合には、 43413 charlog#end-exclusive-depth1 と同様に処理する。 43414 43415 他にも keylog に干渉するパターンがある。decompose-meta の類である。 43416 この場合には既に入力されたと思っているデータを書き換える目的がある。 43417 従って、redispatch の様な操作が必要になるのである。 43418 43419 * ok: auto-complete は本当に redispatch が必要なのか。 43420 43421 | これは勝手に起動した auto-complete を終了する為のキーとして記録が行われて、 43422 | 更にその時点で _ble_decode_keylog_keys_count がクリアされてしまうのが問題。 43423 | 43424 | 然し、それだと charlog の方もちゃんと対策が必要なのではないか。 43425 | と思ったが、よく考えたら depth=0 としている事によってそれを免れていたのだった。 43426 | なので、現状ではちゃんと期待通りに動いているのである。 43427 43428 →つまり必要であるという結論になる。 43429 43430 * 然し、そうすると menu-complete 等の exit-default の場合にも必要ではないかと思われてくる。 43431 これもまた抜けるのに使ったキーが其処で記録されて中途半端に記録が終了してしまう。 43432 然し、だからと言って redispatch するとその記録自体が exclusive-depth1 で消えてしまい、 43433 再生した時には exit-default の exit 部分自体も実行されずに終わるという事になる。 43434 だからといって exit-default -> end-keyboard-macro を検出できるかは謎である。 43435 直ぐに呼び出される場合には良いが、end-keyboard-macro を呼び出すための 43436 1文字目だけが exit-default で処理されたとすると、 43437 実際に再生を行った時に 1 文字目だけが中途半端に入力された状態で 43438 43439 再生が終了するという事になる。その様な事になるぐらいであれば、 43440 そもそも exit-default も呼び出さないか、或いは end-keyboard-macro まで呼び出す。 43441 end-keyboard-macro まで呼び出すかどうかを判定するのは難しい。 43442 というかそもそも end-keyboard-macro を呼び出す為に使ったシーケンスなのであれば、 43443 exit-default の exit を起こすのが目的ではなかったと思われて、 43444 その場合には exit-default が再生で呼び出されなくても良いのではないか…。 43445 43446 うーん。面倒なので menu-complete の exit-default の場合にも redispatch で処理する事にする。 43447 43448 * では ble/widget/auto_complete/accept-line 等の ble-decode-key 13 はどうするのか。 43449 これも redispatch で処理するべきなのだろうか。 43450 原理的には 13 が end-keyboard-macro を呼び出すキーシーケンスの最初の文字になっている可能性はある。 43451 然し、一方で accept-line を呼び出すのに別のキーを使った可能性もあって、 43452 その場合には 13 に redispatch してしまうとそもそも accept-line が再現されなくなる可能性もある。 43453 うーん。これに関しては accept-line を呼び出すのに使ったキーが消滅するのは嫌なので、 43454 redispatch は実行しない事にする。 43455 43456 2019-03-23 43457 43458 * complete: menu の枠組みの分離 [#D1029] 43459 実は menu の枠組みは他に流用できるのではないだろうか。 43460 補完とは切り離して利用できる様になると便利である。 43461 43462 うーん。menu の表示部分と補完の処理部分の分離を試みる。 43463 43464 * done: desc の説明取得部分は未だ分離できていない 43465 43466 * done: 現在 menu_onselect だとか menu_item_renderer だとかで 43467 外部から振る舞いを変更できる様にしているが、 43468 どんどんと外部からの振る舞いが追加されていくと辛い。 43469 menu_class menu_param という二つの変数で制御できないだろうか。 43470 43471 menu_class=ble/complete/menu-complete 43472 menu_param=object-id 43473 43474 として置いて 43475 43476 menu_param=$menu_param "$menu_class"/render-item 43477 43478 の様にして呼び出してもらう事にする。 43479 43480 * self-insert をどの様に取り扱うか。 43481 これは二種類の keymap を用意しても良いのではないかという気がする。 43482 特に積極的に filtering を行うモードの場合には、 43483 自由に keymap を弄り回したい気がするので。 43484 43485 というか現在の menu_complete keymap はそのままにして、 43486 menu keymap としてその様な物を提供すれば良い気がしてきた。 43487 43488 * accept だとか exit だとか cancel についても callback にする? 43489 これは具体的に menu の機能を利用する機能が出てきたら考える。 43490 43491 * emacs: kbd-macro に対応する [#D1028] 43492 43493 [実装案] 43494 43495 既に vi の側で類似の機能を提供しているのだから何も考えずにそれを実装すれば良いのでは。 43496 vi での実装は ble/widget/vi_nmap/record-register にある。 43497 _ble_decode_key__hook="ble/widget/vi_nmap/record-register.hook" を設定して、 43498 ble/widget/vi_nmap/record-register.hook で記録先のレジスタの番号を取得すると、 43499 其処から記録を開始する。結局、実際に行っている処理は以下の通りである。 43500 43501 | _ble_keymap_vi_reg_record=$reg 43502 | _ble_keymap_vi_reg_record_char=$ret 43503 | ble-decode/keylog/start 43504 | ble/keymap:vi/update-mode-name 43505 | return 0 43506 43507 - さて何処に実装するのが良いのか。 43508 どんどんと emacs モードではなくて本体の edit.sh の方に機能を実装している気がするが、 43509 それで良いのだろうか。考えるに readline の機能は両方で使う可能性があるので、 43510 edit.sh に記録したいという気分である。一方で、emacs.sh に定義しておいて、 43511 vi 側から使いたい時には autoload で呼び出すという考えもある。 43512 43513 うーん。所でマクロに関しては vi 側では qx...q があるので、 43514 その機能との混線を避ける事を考えれば vi 側では実行できない様にするべきなのでは。 43515 その様に考えるとやはり emacs.sh に実装したほうが良い気がする。 43516 43517 一方で、そもそも混線しない様に設計するべきなのではないかという話もある。 43518 うーん。取り敢えず edit.sh に実装する事にする。 43519 43520 - 記録の形態はキーの列で行う事にする。 43521 bash の振る舞いを見ると (print-last-kbd-macro で出力すると) 43522 文字単位で記録されている様に見える。 43523 然し、特殊キーなどを端末依存で記録するのも嫌なので、 43524 ble.sh の実装では、キーの列として記録して、 43525 print を求められた時には vi の記録と同様に内部形式で文字列に戻す事にする。 43526 43527 - うーん。やはり文字列に変換して表示するのは分かりにくいだけで意味がないので、 43528 unkbd で戻した結果を表示することにするのが良い 43529 43530 - [棄却] ble-decode-key abort/buffering 機能? 43531 43532 然しキーの列として処理させようとして気づいたが、 43533 現在の枠組みでは byte または char に対して abort は効くが、 43534 key に対する abort は効かない。前回対応した時には char を buffering する様にしたが、 43535 文字に関しては buffering する様にはしていないのである。 43536 key についても同様に buffering する様にする必要があるだろうか。 43537 43538 ? 然し、そうすると実は char に対する buffering は必要なかったのではないかとも 43539 思われてしまう。何故ならば char->key の処理は byte->char にも増して軽い気がするからである。 43540 まあ、実際にどうかは分からない。色々なシーケンスの検査をするので、 43541 実は char->key の方が重いような気もする。 43542 そのまま通過する char も多いと言いつつ、それは byte->char の時にも同様である。 43543 実測してみれば良い。 43544 43545 ? 次に気になるのは _ble_decode_char_hook だとか、 43546 _ble_decode_key_hook の処理の順序が乱れないのか、という事である。 43547 例えば或る widget が _ble_decode_char_hook を要求したとして、 43548 実は既に後続の文字が ble-decode-key に全部吸収されている場合、 43549 _ble_decode_char_hook を通過せずに全部キー入力になってしまっている。 43550 43551 従って、ble-decode-key の側で完全に処理しきらないまま 43552 ble-decode-char に戻してしまうと処理の順序が変わってしまう事になる。 43553 43554 しかし本当にそうだろうか…。実はユーザからの入力が来た場合には、 43555 ble-decode-char が中断して ble-decode-key も中断して、 43556 という具合になって中途半端な事は起こらない、という事になったりはしないか。 43557 真面目に考えてみる。ユーザからの入力が大量に来るとする。 43558 ble-decode-char に文字が大量に現れる。 43559 ble-decode-key は key が来る度に真面目に処理をする。 43560 処理の途中で追加のユーザの入力が現れるとする。 43561 この時 ble-decode-key は制御を戻す。 43562 ble-decode-char も制御を戻す。 43563 ble-decode/.hook に於いて abort のチェックが行われる。 43564 abort があれば処理中の ble-decode-char/key の列は廃棄される。 43565 もし abort でなければ ble-decode-char の待ち行列に追加される。 43566 さて、処理は続きから実行される事になる。 43567 ble-decode-char に入り、もしこの時点で hook が定義されていればそれを実行する。 43568 そうでなければ ble-decode-key に入る。 43569 うーん。ble-decode-key の中で無駄に buffering していない限りは大丈夫の気がする。 43570 43571 →実際に vi の実装で試してみたら問題になっている。駄目だ。 43572 vi は keylog ではなくて char レベルの記録 charlog に実装を切り替えた。 43573 従って emacs でも charlog にしないという手はないだろう。 43574 43575 [実装] 43576 43577 * done: 引数に対する仕様を確認する 43578 →再生時には繰り返し回数になる。記録時には何も意味しないだろう。対応した。 43579 43580 * done: keylog が混線しないように現在の処理にタグを付けるなどする。 43581 →これは対策した。 43582 43583 x fixed: 何故か再生がその場では成されない。 43584 一番外側の ble-decode-char ではないからだろう。 43585 これは ble-decode-char のループを修正した。 43586 43587 x fixed: vi のマクロ再生時に必ず bell が鳴る。 43588 記録されている内容を見ると別に何か変な物が混入している訳でもない。 43589 →実は register#play の戻り値は意味があって、 43590 マクロの再生ができなかった時に失敗を返すのだった。 43591 43592 では ble-decode-char が失敗を返しているのは何故だろうという話になるが、 43593 これは調べてみた所、入れ子の ble-decode-char はその場で登録するだけで、 43594 処理は外側の ble-decode-char に任せるからなのであった。 43595 43596 * fixed: emacs の mode name に現在記録中である事を表す記号を表示する。 43597 →これは対応したはずだが何故か動いていない。 43598 これは footprint で変更がなければ更新しない様になっていたのが原因だった。直した。 43599 43600 * edit: vi_cmap に於いて rps1 が表示されている [#D1027] 43601 read -e の時には抑制していた筈である。と思ったら抑制していなかった。 43602 read -e でも rps1 が表示されている。うーん。これはこのままで良いのだろうか…。 43603 read -e に関してはユーザ側で適当に rps1 を設定してもらえば良い話である。 43604 一方で、vi_cmap についてはやはり抑制した方が良い様な気がするが…。 43605 43606 どの様に抑制するのが正しいのだろうか。 43607 例えば _ble_textarea_panel==0 の時にだけ表示する等? 43608 read に関して言えば元々 _ble_textarea_panel==0 で起動するのでこれだと消えない。 43609 一方で編集関数の中などから使った時には 1 で起動するので表示されない。 43610 ユーザが普通に使った時はユーザが自由に設定できて良い筈なので残しておいて良い気がして来た。 43611 従って、_ble_textarea_panel==0 の時だけ rps1 を処理する事にした。 43612 43613 * vi: q によるマクロの記録で、quoted-insert 等が正しく記録されない [#D1026] 43614 実は quoted-insert 等 char hook を用いている機能は 43615 すり抜けているのではないか…。試してみる。 43616 →うわー。すり抜けている…。これは設計を考え直す必要がある。。。 43617 本来実行するべきは keylog ではなくて charlog なのではあるまいか。。 43618 43619 * 取り敢えず ble/decode/charlog を実装する事にした。 43620 ble-decode/keylog をそのままコピーすれば良いだろう。 43621 と思ったのだが、微妙である。 43622 ble-decode/keylog/pop に対応する機能の実現方法が分からない。 43623 或いは、ble/decode/charlog を使う側で適当に処理すれば良いのだろうか。 43624 然し、widget は自分を呼び出すのに使った char をどの様に検出すれば良いのだろうか。 43625 43626 a widget を呼び出す度にクリアする char の buffer を用意する 43627 もしくは char の count を用意する。 43628 うーん。ble-decode/charlog の記録をすると同時に count すれば良い気がする。 43629 43630 b reject: KEYS に倣って CHARS の様な配列を用いて、 43631 その widget が呼び出されるに至った文字の列を提供する。 43632 これはそもそも有用なのか分からないし、実装が複雑そうだし重そう。 43633 43634 c reject: keymap の __before_widget__, __after_widget__ 辺りで文字数を計る。 43635 うーん。これは実装として汚いし重そうである。 43636 43637 然し、そんなに大げさなことをする必要があるのだろうか。 43638 もっと綺麗な解決方法はあったりしないのだろうか。 43639 43640 - 因みに keylog/pop は既に vi の2箇所で使われている。一つは record-register であるが、 43641 もう一つは vi-command の decompose-meta (これは __default__ で処理される) に於いて、 43642 ble-decode-key を改めて再発行する時に分解前の記録を抹消する為に用いている。 43643 実は、これに関しては keylog 機能を削除すれば気にしなくて良くなるのではないか…。 43644 従って、keylog/pop に関しては record-register だけから用いられると考えて良い。 43645 43646 d reject: 或いは charlog/end に至る文字の列を予め登録しておいて、 43647 それが来たら hook を呼び出させるという手もあるかもしれない。 43648 然し、それはそれで C-x ) 等の場合を考えると複数の文字の列の場合を考えなければならないし、 43649 また別のキー列の部分に現れる C-x ) に反応されても困るとか色々問題がある。 43650 43651 うーん。良い案が思い浮かばないので charlog と一緒に count する作戦 (a) で行く事にする。 43652 43653 * さて。文字ベースでの記録に変更した事によって 0 をどうやって記録するのかが問題になる。 43654 0 は結局、必ず C-@ に変換されると思ってよいのだろうか…。 43655 と思ったが、よく考えたら _ble_decode_char__hook 経由の場合には、 43656 変換されずに 0 として出力される事になる。 43657 従って、やはり 0 は 0 として記録しなければならない。 43658 例えば整数値の列として記録したら良いのだろうか。 43659 然し乍ら、register は元々文字列である。 43660 更に編集文字列中の部分文字列をそのまま貼り付けたいという需要もある。 43661 編集文字列中には ble.sh では C-@ は存在できないが、 43662 然しキーボードの操作としては C-@ があっても良いのである。 43663 従って C-@ もちゃんと記録できる様にしたい。 43664 43665 うーん。C-@ だけ別の文字に変換して記録するのか…。 43666 うーん。既に isolated ESC は U+07FF という未割り当て文字に対応させている。 43667 その事を思えば、実は C-@ を U+07FE 辺りに適当に割り当てても大丈夫なのではないか? 43668 43669 その様に実装した。:reg で表示した時に C-@ だけ何だか変な表示になってしまうが、 43670 まあ仕方のない事である。少なくとも今までの keylog による記録よりは綺麗である。 43671 様々な自動的に発動されるキーだとか修飾キーだとかが綺麗になっている。 43672 端末依存の表記になってしまっている部分はあるかもしれないが、 43673 差異(というかコンフリクト)はそんなにないだろうし、 43674 まあこちらの方が実際に受け取った文字の列なので見やすい。 43675 43676 * isearch: どうも編集前の文字列に対して一致している気がする [#D1025] 43677 と思ったがそうでもないようだ。 43678 と思ったら履歴を移動した先で削除を行って、 43679 その場で検索を開始するとその場で一致している気がする。 43680 43681 うーん。現在の項目で何故一致する事ができるのか…。 43682 43683 分かった append になっていると現在の項目から next-history.fib が始まる。 43684 そして現在の項目は未だ edit に格納されていない。 43685 43686 2019-03-22 43687 43688 * edit: alias-expand-line 実装 [#D1024] 43689 43690 これを実装するにはどうしたら良いだろうか。 43691 知る限りをこれを実行する様な機能は bash では提供されていない。 43692 43693 a 従って自前で実装するなどしなければならない。 43694 43695 b 或いは readline に食わせて処理させる事など可能だろうか。 43696 例えば DA2 応答等を無理やり返答させて、続きを処理させるなど。 43697 つまり一旦抜けてから次の端末からの送信メッセージで 43698 alias-expand-line を実行させて、 43699 更にその次の文字を受信した時に続きの処理を実行する事にする。 43700 然し、端末が必ずしも応答を返してくれるとは限らない。 43701 43702 やはり汚い事を実行するよりは自前で実装するのが良い気がする。 43703 環境に依存せず動くので安心である。 43704 43705 自前実装する事にする。ble_debug=1 で観察した限りだと、 43706 コマンド名に相当する部分は必ず CMDI の単語になっている。 43707 キーワードや組み込みコマンド等の区別はない。 43708 どうも [[ ですら CMDI という事になっている。 43709 と、ここで alias '[[' を定義したら ble.sh が動かなくなるという問題…。直した #D1023 43710 43711 CMDI なる全ての単語について alias を確認すれば良いという事だろうか。 43712 結局 tree-enumerate を用いて実装する事にした。 43713 何故ならば直接 _ble_syntax_tree を弄ろうかとも思ったが、 43714 そうすると _ble_syntax_tree の仕様変更があった時に問題になる。 43715 43716 実際に回してみるとちゃんと動く。内部に単語がある場合には alias 展開は試さなくて良いだろう。 43717 alias があるかどうかの確認は cmdtype で実装している筈。 43718 と思ったが cmdtype で確認しているのは type -t を用いて alias かどうかを確認しているだけだった。 43719 alias の展開を実行しているのは ble/syntax:bash/ctx-command/check-word-end であった。 43720 展開している部分を ble/util/expand-alias として分離する。 43721 43722 動いている。実装してみれば意外と呆気ない物である。 43723 43724 * edit: alias '[['=hello とすると [[ と入力した時点でエラーメッセージが大量に出る [#D1023] 43725 と思ったら、どうやら ble.sh の処理に使っている [[ が全て hello に置換されている様だ。 43726 これは凶悪である。unset -f をやっているのと同じ箇所で unalias も実行しておくべきであろう。 43727 43728 * 2013-06-04 説明書に注意点を書く [#D1022] 43729 + 問題点: 既存の bind を上書きする事 43730 + 問題点: 既存の trap を上書きする事 43731 →これらは説明書にその様に書いておけば問題ない 43732 43733 * edit: {kill,copy,delete}-region-or の引数に [#D1021] 43734 {kill,copy,delete}- を付加して実行するのは分かりにくいのでやめる 43735 43736 * 2017-12-04 emacs: 引き数: 単語関連 [#D1020] 43737 43738 todo: ble/widget/単語関連 43739 現状では取り敢えず clear-arg する。後で仕様の確定も含めて対応する。 43740 43741 2019-03-21 capitalize-word の類の実装と同時に実装する事にした。 43742 負の引数を与えた時の振る舞いはどうするのか…→適当に実装した。 43743 負の引数を与えた時の振る舞いの確認を行う。 43744 forward/backward-word は動いている。 43745 kill-forward-word も動いている。まあ問題ないだろう。 43746 delete-forward-word も動いている。 43747 43748 x fixed: どうも forward-word が変である。 43749 恐らく一番最後に修正した skip-forward,backward が問題なのではないか。 43750 43751 * emacs: rlfunc capitalize-word, downcase-word, upcase-word [#D1019] 43752 対応した。一緒に単語関係の widget の実装を整理した。 43753 43754 2019-03-21 43755 43756 * decode: rosaterm で起動すると "no previous search" というメッセージが表示される [#D1018] 43757 何か変な物を受信している? 43758 43759 調べると vi mode の search.impl で n または N の時に表示される。 43760 もしくは / ? # * でも表示される事がある? 43761 何れにしても最初に何か変な物を受信しているのが原因である事には違いない。 43762 うーん。やはり ble-decode/.hook 経由で呼び出されている。 43763 43764 うーん。調べてみるとなんと rosaterm は CPR を "CSI Pn ; Pn n" で返す様だ。 43765 むう。因みに n は private sequence という訳でもない。というか DSR である。 43766 これは仕方がないので対策する事にした。 43767 43768 * emacs: rlfunc forward-byte, backward-byte [#D1017] 43769 43770 これらはどの様に振る舞うべきなのか。 43771 中途半端な位置に移動してしまって良いのだろうか…。 43772 類似の例として vim mode の nth-byte という物がある。 43773 これは文字内部には移動しない様に実装している。 43774 二分法によって適切な文字境界に移動する。 43775 逆に言えば forward-byte 及び backward-byte は、 43776 引数を指定した時にそのバイトまで移動するという様に実装できないだろうか。 43777 43778 取り敢えず振る舞いに関する提案はさておき、 43779 readline で具体的にどの様に動くかについては確認しておいて良い気がする。 43780 →実際に以下の様にして日本語を入力してカーソルを移動して入力してみた所、表示が乱れた。 43781 $ bind '"\C-f": forward-byte' 43782 $ bind '"\C-b": backward-byte' 43783 つまり、readline の振る舞いとしては変な位置にカーソルを移動するという事になる。 43784 43785 ble.sh の振る舞いとしてはどの様にしたら良いだろうか。 43786 中途半端な位置に移動した場合には次の文字境界まで移動するという事にしたい。 43787 然し、どの様にして文字境界を判定したら良いだろうか。 43788 一つの方法は vim mode の nth-byte と同じ様に二分法で位置を決定する。 43789 他にあるだろうか。1文字ずつ移動してバイト数を超えたら終わる? 43790 43791 取り敢えず実装した。動作確認した。まあ、大丈夫だろう。 43792 43793 * rps1: checkwinsize の時に rprompt が再描画されていない気がする [#D1016] 43794 と思って落ち着いて調べてみた所、再描画はされているけれども、 43795 元々あった内容の消去ができていない、という事の様である。 43796 サイズが変わったら el2 を使って全て消してしまうほうが良いのかもしれない。 43797 と思ったらページ内容を消去するのは ED (\e[J) であった。 43798 _ble_term_ed を定義して再描画時にそれを出力する様にした。直った。OK 43799 43800 * complete: ブレース展開の中ではファイル名の直後に ' ' ではなくて ',' を入れたい [#D1015] 43801 もしくは何も入れない。 43802 取り敢えず , を入れる事にした。これは簡単に実装できた。 43803 43804 * complete: 曖昧補完であっても既存の部分が一致している場合には置換しなくて良いのでは [#D1014] 43805 例えば chat 上で ~/.in に対する補完で再現している。 43806 inputrc がなかったので別のファイルに曖昧一致しているが、 43807 その時に ~/ が /home/murase/ に無駄に置換されてしまっている。 43808 うーん。これは変だ。補完候補生成の段階で /home/murase は ~ に置き換えられる筈なのである。 43809 43810 調べてみて分かった。"既存の部分" は "/home/murase/.in" なので、 43811 "/home/murase" の部分だけが一致していても仕方がないのであった。 43812 43813 a 候補生成側での COMPS への置き換えをもっと細かく実行する案 43814 43815 ではディレクトリ毎に一致しているかどうか確かめれば良いのか、というと、 43816 COMPV のディレクトリの区切りが COMPS のどの部分に対応するかは非自明なのであった。 43817 かと言って COMPS を適当に切断しながら評価していくというのも大変である。 43818 43819 % うーん。理由は分からないが候補生成側で共通部分に対する置換を実行する事にする。 43820 % 問題は先頭一致部分をどの様に修正するのかということである。 43821 43822 うーん。曖昧補完の時には実は COMPV は信用できない。 43823 何故ならば候補生成時に COMPV を書き換えて短くする等している為である。 43824 ファイル名の場合には自前で処理する為に COMPV の書き換えを実行していないが、 43825 一般の枠組みとして考えるとやはり共通部分を決めてから 43826 COMPS に一部戻すなどの事が必要なのではないか。 43827 しかしどの様にして戻すのかというのは難しい問題である。 43828 例えば、不一致部分が特殊文字を含まず裸であれば、 43829 COMPS の末尾からその文字数分だけ削って、 43830 共通部分を置き換えるという様にすれば良い。 43831 43832 然し、ファイル名の処理の時にだけ / 区切りで一致部分を探すというのも現在の枠組みでは面倒だ。 43833 現在は COMPS への置き換えは quote-insert を通じて行っているが、 43834 この quote-insert は全ての source から共通して使われる関数である。 43835 或いは、あらゆる場合について / または : または = による区切りで共通部分を確認するとしても良いのかもしれない。 43836 然し、これを全ての候補に対して実行していると処理時間が長くなってしまう。 43837 その様に考えると、実は置換を実行する側で共通部分の評価結果が同じであれば、 43838 COMPS に置き換えてしまうというのを実装しても良いのかもしれない。 43839 43840 b 曖昧補完の共通部分決定の後で COMPS への置き換えを考える案 43841 43842 曖昧補完の挿入の側で共通部分を勝手に抽出しても良いのだろうか。 43843 というかそもそも何故補完候補生成側で共通部分を置換していたのだったか。 43844 或いは、特別なキーワード等の場合の為にその様にしていたのかもしれない。 43845 とも思ったが特別なキーワードであったならばそもそも 43846 展開後の内容で補完候補を生成するべきではない。 43847 43848 確認してみると実は曖昧補完の場合には 43849 既に COMPS を参照して共通部分の決定を実行している。 43850 従って、COMPS を共通部分決定の際に参照する事を避ける理由は実はない気がする。 43851 43852 共通部分を置き換える事が可能である条件は何だろう。 43853 先ず始めに置き換える部分は、COMPS の方も common の方も simple-word でなければならない。 43854 クォートを閉じれば simple にできる等ではなくて、何もしなくても完全でなければならない。 43855 そうしないと文脈が変化してしまうからである。或いは、common の方さえ simple であれば、 43856 COMPS の方のクォートを閉じれば良い気もするが分からない。 43857 43858 更に共通部分をどの様に判定するのかの方法についてもどの様にするのが良いか考えたい。 43859 結局 COMPS の方も common の方も展開が必要になるという事なのだとすれば。 43860 うーん。:/= 区切りで評価するというのを実装するのが良いのだろうか。 43861 43862 うーん。まあ取り敢えず実装してみた。一応動いてはいる。 43863 43864 さて、動いてはいるが、メニュー補完の中に入ると結局補完前の状態になってしまう。 43865 然し、全ての候補について置き換えを実行するとなるとやはり処理時間が気になる。 43866 うーん。或いは、挿入時に挿入内容を書き換える仕組みがあっても良いのではないか、 43867 とおも思ったが挿入時に書き換える仕組みになっていると共通部分探索の意味がなくなってしまうのでは。 43868 やはり候補を生成する時に挿入内容は確定させて置かなければならない気がする。 43869 43870 まあ、面倒なのでメニュー補完の場合にはそのメニューが提供する内容に 43871 置換してしまって仕方がないという事にする。 43872 43873 * 2019-02-10 decode: 組み込みコマンド bind 上書き実装で未対応の事柄 [#D1013] 43874 43875 * reject: ble-bind -s で bell が呼ばれた時にマクロ実行を中断する? 43876 bind -s の場合にはその様な実装になっているが 43877 ble.sh では取り敢えずはその振る舞いは実装しない事にした。 43878 43879 2019-03-20 ユーザによる中断の要求に対しては #D0998 で実装された 43880 decode_abort_char で中断できる様になった。 43881 ble-bind -s の場合には ble-decode-char を用いてマクロを実行しているので、 43882 特に意識しなくても中断を実行する事ができるのである。 43883 43884 一方でマクロの文字列の中に含まれている C-g 等の文字に関しては 43885 マクロを中断する機能はない。というか、それがマクロを中断する能力を 43886 持っていて良いのかという疑問も残る。 43887 % 然し、decode_abort_char がその機能を持っている限りはやはり、 43888 % decode_abort_char がマクロを中断する機能を持ってしまう。 43889 % と思ったが調べてみると decode_abort_char は .hook で受信した時のみ 43890 % 検査される様なのでこれに関しては問題ない。 43891 43892 →この実装ではマクロ中に含まれている C-g (bell) も 43893 C-\ (decode_abort_char) も特別な処理を実行しない、 43894 という実装で良い事にする。 43895 43896 * done: 現状では bind -lpsPSX は元の readline の情報を出力している。 43897 ble.sh における情報を出力するように修正しても良いのかもしれない。 43898 ble.sh の bind は元の bind の振る舞いを変更しないままそれに対して介入して 43899 ble.sh の設定に反映させるというのが目的である。 43900 bind 自体の振る舞いを ble.sh に変更するのが目的ではなかった。 43901 更に ble.sh の設定を確認したいのであれば ble-bind 経由で調べれば良い。 43902 その様に考えれば bind -lpsPSX で ble.sh の設定を出力する事に意義はない。 43903 43904 と思ったが、attach している間は bind -lpsPSX の内容は滅茶苦茶な内容になっている。 43905 なのでそのまま出力しても仕方のない状態になっている。 43906 43907 a その事を思えば ble-bind の内容を bind 風に整形した内容を出力するべきなのではあるまいか。 43908 b 或いは、サブシェルの中で binding を復元して出力しても良いのかもしれないが…。 43909 43910 ここは b の方針で修正する事にした。bind 風の出力をしても再利用できないので仕方がないし、 43911 かと言って ble.sh の内部で使用している binding を出力してもやはり仕方がない。修正した。 43912 43913 * done: bind -q function には対応していない 43914 これに関しても元の bind の設定を出力させれば良いのではないか。 43915 bind -psPSX と同様に元の状態を復元してから呼び出す事にした。 43916 43917 -q function がある度にちゃんと出力する様にした。 43918 元の builtin bind の場合には最後に指定した -q function しか処理しない。 43919 43920 * done: bind -u function には対応していない 43921 →実装した。これは ble.sh の bindings を変更する様にする。 43922 実際に試してみた。動いている様に見える。 43923 43924 * done: bind -f filename には対応していない。 43925 $if 等のディレクティブ以外は既に対応している機能を用いれば良い。 43926 ディレクティブに関しては何とかして実装する必要がある気がする。 43927 或いは bash のコマンドに置換して後で全体を eval するというのでも良いかもしれない。 43928 43929 更に言うと .inputrc についても本当は読み取ると良いのかもしれない。 43930 43931 うーん。bash と readline version の対応が分からない。 43932 外部 readline を利用している場合には対応していないが、 43933 ldd で何とか分かるかもしれない。しかし major version しか分からない可能性もある。 43934 組み込まれている readline に関しては以下の日付から推測する事ができる。 43935 https://ftp.gnu.org/gnu/bash/ 43936 https://ftp.gnu.org/gnu/readline/ 43937 43938 Bash 3.0 - Readline 5.0 43939 Bash 3.1 - Readline 5.1 43940 Bash 3.2 - Readline 5.2 43941 Bash 4.0 - Readline 6.0 43942 Bash 4.1 - Readline 6.1 43943 Bash 4.2 - Readline 6.2 43944 Bash 4.3 - Readline 6.3 43945 Bash 4.4 - Readline 7.0 43946 Bash 5.0 - Readline 8.0 43947 43948 取り敢えず対応した。動作確認をする。 43949 43950 - 取り敢えず動作テストした。動いている気がする。 43951 - $if $endif $include は動く事を確認した。 43952 - 後は $if の条件がちゃんと動いているかである。 43953 application, mode, term, version, rlvars の何れも動作確認した。 43954 43955 2019-03-20 43956 43957 * vi_imap 及び vi_nmap に於ける rlfunc <--> widget 対応表の記入 [#D1012] 43958 vi_imap に関しては多少埋めた。完全ではない。 55cfa22 43959 vi_nmap に関しても編集する。 43960 43961 * done: vi_nmap に関連して単語関連の操作が沢山あって違いが分からない。 43962 43963 vi-next-word vi-end-word vi-prev-word 43964 vi-fword vi-eword vi-bword 43965 vi-fWord vi-eWord vi-bWord 43966 vi-forward-word - vi-backward-word 43967 vi-forward-bigword vi-end-bigword vi-backward-bigword 43968 43969 どうやら vi-next-word/vi-end-word/vi-prev-word は入力された文字に応じて 43970 動作を変更する物になっているという気がする。 43971 試しに eword eWord を e, E に設定してみたが両方共 E の動きしかしない気がする。 43972 end-word 及び end-bigword はちゃんと期待通りに動いている気がする。 43973 但し end-word は大文字か小文字かで動作を変える。end-bigword は変わらない。 43974 うーん。謎である。よく分からないが、取り敢えず憶測で割り当てる事にする。 43975 43976 もう少し真面目に調べてみる。 43977 先ず bigword は実は bWord eWord fWord に等価である。 43978 同様に backward-word は bword で、end-word は eword で、 43979 forward-word は fword である。なので現在の方針は正しい。 43980 更に気になるのは vi-next-word, vi-end-word, vi-prev-word である。 43981 実際に vi-prev-word の実装を見てみると、 43982 現在の ble.sh の実装と同じ様に文字が大文字かどうかで判定して 43983 bword, bWord に分岐している。 43984 43985 | int rl_vi_prev_word (int count, int key) { 43986 | if (count < 0) 43987 | return (rl_vi_next_word (-count, key)); 43988 | if (rl_point == 0) { 43989 | rl_ding (); 43990 | return (0); 43991 | } 43992 | if (_rl_uppercase_p (key)) 43993 | rl_vi_bWord (count, key); 43994 | else 43995 | rl_vi_bword (count, key); 43996 | return (0); 43997 | } 43998 43999 * vi_nmap において以下の物は .dispatch を作る必要がある。 44000 done: vi-search (/ or ?) 44001 done: vi-search-again (N or n) 44002 done: vi-subst (S or s) 44003 done: 更に operator 達も d D y Y c C は動作が区別されている気がする。 44004 44005 未だまだ不完全の気がするが細かく対応し始めると 44006 widget を色々と新しく作る必要が出てくる。 44007 emacs でもちゃんと対応しきれていない。 44008 これはこの項目の中でするべき事ではなくて、 44009 個別の機能について考察するべきである。という訳でこの辺りで止めておく事にする。 44010 44011 * 2019-02-05 char_width_mode=auto? [#D1011] 44012 44013 既に起動時に DA2 要求と応答の読み取りを実施している。 44014 序でにカーソル位置を用いて文字幅の判定を実行してよいのではないだろうか。 44015 44016 実装した。まあ、動いているのではないだろうか。 44017 44018 - done: 幅が 1 または 2 以外の時には失敗しているので既定の幅を用いる。 44019 →幅が1以外の時は全て 2 という事にする事にした。 44020 幅が1以外の時には常に折り返しの可能性があるので。 44021 44022 - done: check において変更を検出する。変更時に更新を行う。 44023 画面の左上か右下を用いる。画面の左上で RI を使うのが良いのでは。 44024 画面の右上で実行する事にした。 44025 44026 x fixed: s-A-f3 という謎の文字が受信される様になった。 44027 然し、文字幅判定自体はちゃんと動いている。 44028 % 調べてみると CSI >83;40301;0 c という謎のシーケンスが送られて来ている。 44029 % これは何だろう…。と思ったが、これは DA2 応答なので関係ない。 44030 →分かった。CPR の処理をした後に return をしていなかった。直した。 44031 44032 x fixed: bleopt char_width_mode=auto を実行するとカーソル位置がずれる。 44033 これは RI を実行しない様にする事で対処する事にした。 44034 44035 2019-03-19 44036 44037 * vbell: 長いメッセージを表示した直後に短いメッセージを表示すると消去時に文字列が残る [#D1010] 44038 更に、短いメッセージが長いメッセージの上に表示されて内容が混ざる。 44039 新しいメッセージを表示する時に前のメッセージを消去する必要がある。 44040 44041 現在はファイルの時刻に基づいた判定になっているが、 44042 メッセージ毎のファイルを使用する事にして、 44043 ファイルが空かどうかで判定できる様にするのが良い気がする。 44044 有限の内容のファイルが残っている場合には削除をその場で実行する。 44045 有限の内容のファイルには横幅を記録しておくなどすれば良い。 44046 44047 と思ったが一種類のファイルでは管理できない気がしてきた。 44048 状態が三種類ある。現在表示中・削除済みだがworkerは動いている・削除済み。 44049 或いは worker の生死と表示の有無があるのである。 44050 ファイルに有限の内容があるかどうかだと、 44051 worker が未だ生きているかどうかを判定する事ができない。 44052 44053 a 或いは vbell を実行した回数だけファイルを作成してしまうという手もあるのかもしれないが、 44054 それだとファイルが無限に増えていくので定期的に適度に削除しなければならない。 44055 然し、削除するにしても現在使用しているファイルを削除する訳には行かないので、 44056 一つ一つファイルスタンプを確認するとか、或いは定期的に何処までファイルが消えているかを 44057 確認して記録しておく必要がある。 44058 44059 b その様に考えると rm 等使ってファイルを削除する等しても良いのではないかとも思われる。 44060 44061 c 或いは $! を使って fork した worker を記録しておいて、それに対してシグナルを発する? 44062 と思ったが変にジョブ管理に登録されても嫌だし、それについて調べるのも面倒なので、 44063 ファイルを使って何とかする方法を模索したい。 44064 44065 d ファイルの状態を使って何とかできないだろうか。 44066 現在は -s を使っている。ファイルを削除する為には外部コマンドを呼ぶしかない。 44067 -s 以外に何かシェルの組み込み機能だけで読み書きのできる属性はあるだろうか。 44068 -xwr に関しては読み取りはできるが変更はできない。 44069 umask を使えば最初に作成する時の属性の変更はできなくはない。 44070 44071 e reject: [[ -N $file ]] を使う案。 44072 44073 help test を見ていたら面白い機能が実装されている。使えないだろうか。 44074 -N で最後にアクセスしてから新しくなったかどうかを確認することができるようだ。 44075 と思ったら実はこの機能は bash-3.0 の時から既に存在している様である。 44076 然し、最後に読み込まれてから新しくなったかどうかというのの、 44077 最後に読み込まれてからというのはどのタイミングの事だろう。 44078 Bash が読み込んでからという事なのだろうか。 44079 或いはどのプロセスでも良いから読み込んでからという事なのだろうか。 44080 また -s や -N によってアクセスした場合には最後に読み込んだという事になるのだろうか。 44081 44082 - 他のプロセスが読み込んでも最後に読み込んだと見なされる。 44083 - [[ -s $file ]] でアクセスしても最後に読み込んだとは見做されない。 44084 44085 これはどうもファイルシステムに記録されている情報を使っている気がする。 44086 そして mtime と atime をそのシステムがどの様に更新するかに依存している。 44087 従って、この機能に依存して状態を管理するというのには不安が残る。 44088 44089 f 各表示について2つずつファイルを作るのではなくて、 44090 一つは時刻か何かの制御に使って、残りを各 worker が active かどうかの管理に使う。 44091 というようにするのはどうだろうか。 44092 44093 先ず始めに、vbell を表示する時には必ず "前回の表示" を削除する様にする。 44094 2回よりも前に表示した内容は既に削除している筈なので気にしなくて良い。 44095 44096 既に削除したかどうかはファイルの内容の有無で管理する事にする。 44097 もしくは最後に表示した時刻を .time ファイルに記録しておいて、 44098 .time よりも古いものは全て削除済みなのだと解釈する事にする。 44099 44100 worker が削除した時に本体の側に削除の必要がないことを伝達するにはどうすれば良いか。 44101 これも .time ファイルを触るという事にすれば良いのではないだろうか。 44102 44103 具体的な手順について考える。 44104 .time より新しい .N ファイルがあったら前回の内容を削除する。 44105 .time を触る。新しい .N ファイルを触る。 44106 44107 うーん。やはり worker が生きているかどうかは .N に有限の内容があるかどうかで保持し、 44108 表示を削除済みかどうかに関しては .time で管理するというのはどうだろうか。 44109 44110 うーん。f で実装してみたが何回か実行してみると表示が残ってしまう事が結構ある。 44111 何が起こっているのだろう。workerfile と reference の読み書きについて 44112 動作確認する必要がある気がする。 44113 44114 確認してみると多くの vbell が錯綜している時、 44115 何故か途中で .time を触っていないのにも拘わらず 44116 .3 が .time よりも新しくない、という事になっている。 44117 うーん。create してから deprecated1 する迄間に何もない、というのはどういう事か。 44118 44119 何回か試して分かった。同じタイムスタンプになっているのである。 44120 これはファイルシステムの時間分解能の問題である。 44121 同じタイムスタンプの時には未だ deprecated になっていないという解釈にする事にした。 44122 色々試してみたがちゃんと動いている様に見える。 44123 44124 * [自然解消] 2015-11-21 vbell の色 [#D1009] 44125 44126 * [自然解消] 2016-06-20 ble-edit/exec:exec/process コマンド実行時に一時的に .ble-line-info を消す [#D1008] 44127 その他にも ble-line-info の使い方について全体的に見直しを行うと良い。 44128 44129 * complete: rlvar mark-symlinked-directories, match-hidden-files 等の対応 [#D1007] 44130 44131 * done: comp_type が段々と複雑になって来た。 44132 opts の様に名前で指定できる様にするべきではないか。 44133 44134 x ok: しかし、比較速度の問題もある。 44135 - 確認してみた所、候補ループの中では使われていない。 44136 - 唯一使われているとすれば、メニュー表示の一致範囲の決定であるが、 44137 - 元々この部分は時間がかかる処理なので comp_type の検索時間はそれ程効かない筈である。 44138 - また、ループの外で判定結果を変数に入れてしまっても良い。 44139 と思ったが別にループがあるという訳でもなかった。 44140 →比較速度に関しては気にしなくて良いだろう。 44141 44142 * done: 実装 44143 mark-symlinked-directories には対応した。 44144 match-hidden-files にも対応した。 44145 両者とも実際に動かして確かめてみた。 44146 44147 * done: 動作チェック 44148 match-hidden-files に関しては絞り込みによって 44149 . が入力されても新しく生成されないというのが難点だが、 44150 まあ絞り込みと考えれば変な動作でもない。 44151 C-g によってキャンセルして改めて補完を実行すれば 44152 hidden-files もちゃんと生成される様になったのでOK 44153 44154 * done: menu-complete-display-prefix にも対応した。 44155 44156 * done: colored-* 44157 set colored-completion-prefix off 44158 set colored-stats off 44159 44160 以上の物に関しては既に機能としては ble.sh で既定で有効になっているが、 44161 rl の既定では off になっているのでこの変数に対応するとしたら、 44162 ユーザに自分で設定を有効にしてもらう必要がある。 44163 もしくは勝手に ble.sh の側で有効にしてしまうという手も考えられるが…。 44164 結局対応してしまう事にした。 44165 a うーん。勝手に設定を on にする事にする。 44166 但し、遅延ロードで設定を on にすると bashrc で制御できないので、 44167 遅延ロードでない所で勝手に設定を on にする事にする。 44168 この振る舞いに関しては何処か説明書に書くと良いのかもしれない。 44169 b と思ったが off にする機能を残しておく必要はあるのだろうか。 44170 その様に考えると一応 on/off する仕組みを残して置きつつ、 44171 やはり強制的に on にするというのの方が良い気がしてきた。 44172 実は他にも沢山の設定項目が rlvar にはあって、 44173 それらを全て on にするというのは非現実的な感じがする。 44174 44175 2019-03-18 44176 44177 * 2019-03-12 complete: source:sabbrev の候補表示に \ を入れたい [#D1006] 44178 44179 menu の表示に使われる文字列と、絞り込みに使われる文字列を別々にしても良いのでは。 44180 という様に最初は考えたが、よく考えると menu の表示に使われる文字列を用いて、 44181 絞り込みやどのように絞り込まれたかの表示が為されるので、 44182 結局、絞り込みに使われる文字列で menu 表示が行われる事になる。 44183 44184 然し、ファイル名候補の場合に末尾に * 等を追加するだとか、 44185 そういう可能性もあるから、prefix 及び suffix を取得する 44186 というのがあっても良いのかもしれない。 44187 そしてそれは getg と同時に行われるのが良い。 44188 44189 * done: action:sabbrev の場合には其処で prefix を設定する。 44190 と思って途中まで実装してみたが、よく考えてみると、 44191 別に sabbrev は必ずしも \keyword の形をしている訳ではない。 44192 或いは各文字に対応する文字列がどれかを指定して eval する事は現実的だろうか。 44193 うーん。もしその様にしたとしてもどうやって construct-single-entry に伝達するのか。 44194 うーん。変数 show の内容を弄るという事になるのだろうか。 44195 そして変数の内容を弄った時には一致部分の着色は無効にしてしまうという事。 44196 44197 show の内容を弄ってもらうという事にした。 44198 show の内容が元々の内容と同じであればその時に限り着色を実行する。 44199 44200 * ok: まあ、その様にするのが自然の気がする。show という変数名は変更しても良い気がする。 44201 然し、元々の complete の実装で cand_show などだった事を考えれば、 44202 まあ、show のままでも良いような気がする。或いは別の変数名で良さそうな物はあるだろうか。 44203 →取り敢えず show のままで良いという事にした。 44204 44205 * done: また visible-stats が有効の時に * や / を末尾に付加する機能があって良い気がする。 44206 毎回 visible-stats を問い合わせるのは大変なので、これは comp_type 等に入れると良いのだろうか。 44207 さて、此処で問題になるのは prefix, suffix に着色をするかしないかという事である。 44208 それが付加的なマークであると考えるのであれば着色しない。 44209 それが候補自体の見た目を整える為の物であれば着色する。 44210 まあ、見た目を整える為に prefix/suffix を使うというのは変な気がするので着色はしない事にする。 44211 44212 * done: うーん。もし show の内容と filter_target の内容が一致していなかったとしても、 44213 show の内容に filter_target が部分文字列として含まれている場合には、 44214 その部分を対象として着色すれば良い気がする→その様に実装した。 44215 44216 * done: getg という関数名は最早そぐわない。色々な機能を持っているからである。 44217 どの様な関数名が良いだろうか。menu item の見た目の調整である。 44218 うーん。decorate-menu-item とか。adjust-menu-item とか。 44219 get-menu-item でも良いのかもしれない。と思ったが、 44220 何もしなければ既定の表示がされるという事で必須ではないので get-menu-item は変。 44221 adjust-menu-item かもしくは setup-menu-item か。 44222 menu-item というより entry なのかもしれないとも思いつつ、 44223 menu_items という配列も使っているからやはり menu-item でも良いかもしれない。 44224 initialize-menu-item が良いかもしれない。或いは initialize-menu-entry か、 44225 initialize-menu-item-rendering だとか。うーん。init-menu-item が良い気がする。 44226 置換した。 44227 44228 * done: 序でなので mark-directories にも対応する事にする。対応した。 44229 44230 * mark-symlinked-directories や match-hidden-files にもこの際対応するべきなのではないか。 44231 と思ったが、そもそも sabbrev の為に修正を始めたのであって、色々手を出しすぎると収集が付かないので、 44232 取り敢えずここまでで commit してしまう事にする。別項目として立てる事にする。 44233 44234 * 2019-03-13 rps1 の高さを PS1 と同じだけ確保しても良いのではないかという説 [#D1005] 44235 複数行の PS1 にしている人は rps1 も複数行にできる様にする。 44236 44237 一方で、rps1 の方が PS1 よりも行数が多いというのは微妙なので止める。 44238 例えば、出力と被らない様にする為には rps1 の 2 行目以降を消去するか、 44239 コマンドの出力を rps1 の最終行の次の行からにするか、 44240 或いは、rps1 とコマンドの出力が被ってしまっても気にしないか。 44241 とそういう選択肢しかない。 44242 44243 これは PS1 の高さが確定してから、その高さを用いて rps1 を初期化する様にする。 44244 44245 x fixed: さて複数行の rps1 を許す様にして rps1 を削除するコードを書いてから、 44246 実際に rps1 を表示してみると一行になってしまっている。 44247 と思ったら prompt/.initialize で trace を呼び出す時に明示的に LINES=1 44248 を実行してしまっていた。そして、confine を指定していない PS1 の方については 44249 問題が発現していなかったというだけであった。 44250 44251 x fixed: うーん。表示されるようになったが座標計算が誤っている。 44252 rps1 を表示してから y 座標を更新できていない気がする。 44253 座標計算も誤っていたし、更に PS1 の描画位置も誤っていた。修正した。 44254 44255 * 2019-03-13 rps1: rps1_transient の時 _ble_term_el で最後の文字以降を全て消去しても良いのではないか [#D1004] 44256 実際に zsh の場合にはその様にしている様に見える。 44257 44258 ただ複数行の時に各行に対して全て実行するというのは面倒である。 44259 或いは、一行目の時だけ改行の右側を空白で fill するという手もあると思ったが、 44260 2行目以降の改行が1行目に移動した時に問題が発生するので、 44261 それはやはり難しいのである。 44262 44263 全ての改行位置を手早く取得する手法はあるだろうか。 44264 と思ったが、よく考えてみれば $'\n' を単に検索すれば良いのだった。 44265 その他に折り返しの場合もあるが、折返しは一番右側で起こると決まっているので、 44266 殊更に削除するべき空白などがあったりはしない。 44267 44268 うーん。これについて試しに実装してみる事にするか…。 44269 rps1 を消去する時にどの場所で消去するのだろうか。 44270 44271 1 先ず始めに幾何を更新する前に消去する。 44272 2 次に編集文字列の改行の位置より右側を削除する。 44273 44274 2回削除しているので無駄の様な気もするが両方必要の様な気もする。 44275 というのも 1 がないと複数行プロンプトで複数行の rps1 に対応している時に 44276 rps1 が削除されないという事態になる。一方で 2 がないと空白が行末まで続いた状態になっていて 44277 コピー&ペーストする時に邪魔になってしまう。従って、この二種類の消去が必要になるのである。 44278 44279 取り敢えず実装した。最後の行末も消す必要があった。修正した。 44280 44281 * 2019-03-13 rps1: not rps1_transient でコマンドを入力してから次の行に進む時 [#D1003] 44282 rps1 が消去される。寧ろ transient の時は空白で埋められている。 44283 →これは条件式を誤っていた。修正した。 44284 44285 また、何も入力せずに次の行に行く時の再描画についても修正した。 44286 次にユーザの入力が途切れるまで buffer.flush が実行されないので、 44287 明示的に buffer.flush を呼び出す事にした。 44288 44289 * 2019-03-12 complete: completion-ignore-case の時に comp_type=i を設定しているが実際に使っていない [#D1002] 44290 うーん。各 source で本当に正しく実行できているかどうかは分からないが、 44291 そして compgen がいい感じに候補を生成してくれるのか分からないが、 44292 取り敢えず見て簡単に分かる所は更新した。簡単に実行して確かめてみる事にする。 44293 44294 一意確定すれば動いている様な気がするが複数の候補がある時に全く補完できない。 44295 これは count-match-chars の実装が必要である。更に、common_part を求める時に、 44296 case の違いを許す様にして求める必要がある。 44297 44298 色々工夫してみたは良いが、実は nocasematch というオプションが bash-3.1 以降には存在する様だ。 44299 44300 * done: というより常に nocasematch は off にして置かないと別の場所で問題になるのではないか。 44301 実際に shopt -s nocasematch にすると IF true; THEN echo hello; FI が文法的に正しくなってしまう。 44302 実際に試してみるとそのように解釈されてしまっていて、しかも実行するとやはりエラーになる。 44303 うーん。面倒なのでこれはやはり全体の設定で解除しておくべきである。 44304 44305 取り敢えず動かしてみる。 44306 44307 x fixed: 前方部分を置き換えるために確定部分の挿入が起こらない。 44308 そもそも前方部分の置き換えに関しては曖昧補完の時にしか起こしていなかった。 44309 これを ignore case による補完の時にも起こる様に修正した。 44310 44311 - 実は既に実装した部分に関しても nocasematch を使ったほうが高速化できるなどあるだろうか。 44312 問題は一致の init と finalize を作ったとして、 44313 その途中で nocasematch が別の操作に対して悪影響を与えないのかという事である。 44314 また、どうせ bash-3.0 では nocasematch に依らずに実装する必要があるので、 44315 わざわざ無駄にスイッチを作るというのは面倒である。 44316 44317 determine-common-prefix でスイッチしてでも nocasematch を実施したのは、 44318 毎回 tolower を実行するのはコストが高いだろうと判断するからである。 44319 a 然し、そうは言っても [][] でパターンを生成するというのも、 44320 少しずつ短くしていかなければならないので毎回パターンを生成しなければならない。 44321 b もしくは構築時に長さを配列に記録して少しずつ短くするという手もある。 44322 c もしくはアルファベット以外の文字 x の場合にはダミーで [xx] というのを生成して、 44323 4文字ずつ切り出してパターンとして利用するという手もある。 44324 44325 うーん。余り実装する意味はない様な気もするが、 44326 一方で bash-3.0 ではやはりこういう風に処理した方が速い気もする。 44327 一方で、余り実装手法を複雑にすると後でよく分からなくなる。 44328 44329 2019-03-12 44330 44331 * syntax: "for a in 1; do done" が文法エラーになっていない [#D1001] 44332 現在の実装では do の後に任意のコマンドが来ても良い事になっている筈。 44333 然し、来ては行けないコマンドという物を指定する事はできない。 44334 それでもよく考えてみれば } や done 等の時には来ても良いコマンドを指定する事ができたのだから、 44335 それと同じ様に処理すれば良いのではないだろうか。} や done は CTX_CMDXE という文脈を生成する。 44336 一方で do は CTX_CMDX1 という文脈を生成する。 44337 CTX_CMDX1 になるのは他にも if while until then elif else { 等がある。 44338 44339 他に case esac で esac を読み取る直前に CTX_CMDX1 を設定している箇所があったが、 44340 ここは別に CTX_CMDX で良いきがするのでこれはその様にした。 44341 この上で、CTX_CMDX1 の次には then elif else } done esac fi 等は消えてゃ行けないという制限をかけたい。 44342 CTX_CMDXE の特別の判定をしている箇所を探す。 44343 44344 結局 'for' 等を処理している ctx-word-end に於いてやはり判定をしているのだった。 44345 実は wtype にその文脈に入った時の ctx が入っている。 44346 CTX_CMDXE に関しては _ble_syntax_bash_command_Expect による判定が使われていた。 44347 同じ箇所に手動での判定を書き加えることにした。動いている。 44348 44349 * read -e で C-d を入力してから確定すると vbell のジョブメッセージが出る [#D1000] 44350 44351 a set +m を用いてジョブ管理の状態を変更しても効果はなかった。 44352 ジョブを発動する瞬間に set +m でなければならないという事だろうか。 44353 b と思って set +m と set -m で囲んでみても効果がなかった。理由はよく分からない。 44354 或いはコマンドが終わった瞬間にジョブ管理が有効になっていると検出してしまうという事だろうか。 44355 c そう思って set +m にずっとしたままで実行してみても変わらない。 44356 44357 もしかすると bind -x の中で実行している限りは状態が復元されてしまうという事なのかもしれない。 44358 というか、普通の visible-bell の時には検出できないのが何故 read -e の時にだけ検出できるのだろうか。 44359 うーん。よく分からないけれども。まあ余りきにしない事にする。 44360 44361 visible-bell のサブシェルのコマンドは 44362 直接コマンドの羅列を記述していて長いので関数にする事にした。 44363 これで何か変なメッセージが表示されるとしても短くて済む。 44364 44365 * edit: read -e 実は ble-0.2 の時点では変なメッセージなしに vbell が表示できていた。 44366 と思ったら気の所為だった。単に bleopt edit_vbell が off になっていただけなのだった。 44367 44368 * read -e で謎の改行が入る [#D0999] 44369 これは第二の panel を使って入力をしているからである。 44370 その時に第一の panel の高さをクリアし忘れている。直した。 44371 44372 * 2018-08-22 vi: マクロ再生の中断? [#D0998] 44373 ユーザから入力があったら中断する機能。 44374 すぐに中断するのではなくて時間を計測しても良い。 44375 44376 Note: 現在はマクロの中で更にマクロが再生されるのは検知して阻止している筈。 44377 従って、中断できる様にする対象は履歴の検索等の元から時間がかかる処理である。 44378 44379 2019-03-12 思うにこれは大量の入力をしてしまった時にも同様である。 44380 従って、vi マクロの側で処理するのではなくて、 44381 vi マクロの側は "大量の入力" として再生を decode 側に一任する。 44382 そして decode 側は "char" の列を何処かに記録して実行を行う。 44383 もし入力が現れた時にはそれを読んで例えば ^\ だったら記録されている列を削除する。 44384 44385 * 再帰的に ble-decode-char を呼び出した場合には、 44386 記録されている列の "前" に新しい文字が挿入されるという事に注意する。 44387 また、普通にユーザの入力として ble-decode-char を呼び出した場合には、 44388 "後" に新しい文字が挿入されるという事にも注意する。 44389 44390 では中途半端な位置に挿入される事が期待される場合はあるだろうか。 44391 うーん。今実行中の部分が原因で呼び出される場合には必ず "前" である。 44392 何故なら今実行中の文字の直後に処理されて欲しいから。 44393 ユーザからの入力の場合には必ず "後" である。 44394 現在処理中の物を全て処理した後に実行して欲しいから。 44395 しかし、それ以外の要因で char が追加されるという事があるだろうか。 44396 恐らくないと考えて良い。 44397 44398 * 今似たような仕組みは ble-decode/.hook に存在している。 44399 これは byte を受け取る部分の側の仕組みである…。 44400 char を受け取る部分の側の仕組みで似たような事をしたい。 44401 しかし byte を受け取る部分との整合性も考えたい。 44402 44403 * 実は ble-decode-key も直接呼び出されたりしているが、 44404 これに関してはまあ中断機能は及ばなくても良いだろう。 44405 後で簡単に拡張して対応できるし、 44406 現時点では ble-decode-key ベースのマクロ再生は存在していないので。 44407 もしかすると emacs モードでのマクロは key ベースになるかもしれないが、 44408 然し、マクロをプリントする機能などの事を考えると、 44409 やはり char ベースのマクロになるのではないかという気がする。 44410 44411 [実装案] 44412 44413 bytes = [ユーザからの入力の列] = _ble_decode_input_buffer 44414 chars = [デコーダからの入力の列] 44415 44416 うーん。bytes は chars に末尾から追加する。 44417 それ以外の ble-decode-char は chars に前に追加する。 44418 bytes に C-\ が入ってきたら全て消去する。 44419 44420 chars を実行している途中に has-input 状態になったら、 44421 今まで実行した chars の部分を消去して中断して抜ける。 44422 其処で bytes の末尾に byte が追加されるのである。 44423 そして bytes から ble-decode-char が呼び出されるが、 44424 その時の文字は chars の末尾に追加されて、 44425 ble-decode-char は溜まっている char からまた 44426 処理を再開するという流れになる。 44427 44428 % - 前に追加するか後に追加するかは 44429 % ble-decode-char の中から ble-decode-char 44430 % を呼び出しているかどうかで判定する。 44431 % 44432 % - 因みにユーザがコマンドから呼び出す ble-decode-char は…。 44433 % ble-decode-char の外側から呼び出される筈なので、 44434 % 溜まっている chars よりも先に実行されてしまう気がする。 44435 % 一方で、コマンドの全て処理が終わってからの様な気もするので、 44436 % そういう意味では前も先もないのかもしれない。 44437 % これは確認する必要がある。 44438 % 44439 % - 後、前に挿入する、という事だが、 44440 % 一つの処理の間に複数の ble-decode-char が呼び出される場合、 44441 % 順序が反転して記録されてしまうのではないだろうか。 44442 % この辺りは工夫して buffer の管理を行えば回避できる気がする。 44443 % 例えば実行中は buffer は空にして置いて、 44444 % 去る時に未処理の文字たちを buffer の末尾に追加する。など。 44445 % 実は、その様にすれば前だとか後だとか気にせずに、 44446 % 常に後ろに追加するだけで良くなるのではないか。 44447 44448 - done: ble/builtin/bind/.decode-chars の処理に関しては、 44449 ユーザからの入力があっても失敗しない様にする。 44450 もしくは 148 を返したら失敗と判定する事にする。 44451 多分、ユーザからの入力があっても中断しない様にするのが適切。 44452 44453 - done: ble-decode-char で処理中は一旦ローカルの配列に移動する。 44454 但し、ローカルの配列に未だ中身があるという事をどうにかして、 44455 has-input で検出しなければならない。 44456 44457 | 特に入れ子になって実行している時でも大丈夫だろうか。 44458 | 或いは入れ子になって実行している時には必ず push しかしない、 44459 | という様にするという手もある。 44460 | そうすれば入れ子で実行しているという事はないのだから、 44461 | そして実行しているとすれば必ずその関数の中から呼び出されているので、 44462 | ローカル変数は見えているという事になる。 44463 | 従って、has-input でそのローカル変数を参照すれば良い。 44464 | 44465 | と思ったが、本当にそれで大丈夫だろうか。 44466 | 44467 | ble-decode-char 自体はどの様に入れ子で処理しているか検出するのか。 44468 | やはりローカル変数で確認するという事になるのか。 44469 | そして ble-decode-char 自体が入れ子で処理している時に、 44470 | どの様にして引数を追加したら良いのだろうか。 44471 | ble-decode-char が呼び出されてユーザからの入力はないけれども、 44472 | ble-decode-char で未だ残りの文字が存在するという状況で、 44473 | その場で push して抜けるべきなのか、 44474 | それともその場で処理を続行するべきなのか。 44475 | 44476 | a 当初の計画ではその場で処理を続行するという物だった。 44477 | そして、ユーザからの入力があったら push して抜けるという物。 44478 | ユーザからの入力は一番上まで抜けなければならないから大丈夫。 44479 | しかし、よく考えてみるとユーザからの入力は50回に1回しか確認しない。 44480 | 44481 | b 従って入れ子の ble-decode-char の場合には必ず失敗して、 44482 | push してから上に抜けていくという状況になる。 44483 | そして呼び出し元では毎回 _ble_decode_char_buffer に 44484 | 何か新しい処理が書き込まれていないか確認しなければならない。 44485 44486 入れ子で ble-decode-char を呼び出した時は制御を戻し、 44487 外側で実行してもらう事にする。 44488 ble-decode-char で ble_decode_char_rest という変数を提供し、 44489 残りの文字数を分かるようにして、has-input ではそれを参照する事にした。 44490 44491 - ok: ble-decode-char を呼び出す時は必ずしも 44492 その場で実行されるとは限らない事を確認する。 44493 特に ble-decode-char の後に処理が走っている場合には気を付ける。 44494 44495 - done: ble-decode/.hook 経由で呼び出される encoding の 44496 ble-decode-char はどの様に処理すれば良いのか。 44497 ユーザからの入力があったからと言って中断していると、 44498 後続の処理が実行されてしまう。 44499 特に erase-progress が実行されてしまう。 44500 44501 うーん。或いは実は寧ろそちらの方が良いのではないか。 44502 と思ったが、これが走っている時は必ず 44503 has-input が true になるので直ぐに終了してしまう。 44504 つまり、直ぐに末尾まで行って、その後で 44505 erase-progress が実行される。 44506 44507 試しに実行してみたらやはりそうなった。 44508 decode だけを実施して最後まで行ってしまう。 44509 因みに動作自体はちゃんとしている。 44510 うーん。progress を ble-decode-char の側でも 44511 実行するべきなのかもしれない。表示する様にした。 44512 44513 - done: うーん。builtin/read/.loop の処理に関しては、 44514 その場で最後まで処理し切るという様にしないと困る気がする。 44515 と思ったが、abort する事ができる様にする為には、 44516 やはりループを書き直す必要があるのではないだろうか。。 44517 44518 何だか面倒なので試しに一回実行してみる事にした。 44519 すると実は一応動いている様な気がする。 44520 erase-progress だけは実行しておく事にした。 44521 44522 然し、やはり has-input-for-char の動作は切り替えなければならない。 44523 取り敢えず _ble_decode_input_count は見えない様にマスクしておく事にする。 44524 ble/encoding:.../is-intermediate に関しては気にしない事にする。 44525 中途半端な状態でユーザが read を呼び出す様な事をすることはないとの仮定。 44526 44527 さて、次に必要なのは C-\ (28) を受け取った時に中断する機能である。 44528 うーん。何れにしても is-stdin-ready の時には処理が一時中断される事を思えば、 44529 実は入り口の ble-decode/.hook で全て消去してしまえば良いのである。 44530 44531 2019-03-11 44532 44533 * 2013-06-01 以前 vbell [#D0997] 44534 + スタイルを指定できる様にする 44535 + 位置を指定できる様にする 44536 44537 設定 "bleopt vbell_align" を追加した。 44538 描画設定として vbell, vbell_flash, vbell_erase を追加した。 44539 44540 * vi: imap に於ける undo がちゃんと記録されていないのでは [#D0996] 44541 特に補完のタイミングにおける記録もない。 44542 やっぱり undo/add が呼び出されていない。 44543 44544 実装を見ると ble/widget/vi_imap/__before_widget__ 経由で、 44545 white でないコマンドを実行する直前に 44546 ble/keymap:vi/mark/end-edit-area が実行されて、 44547 そのタイミングで undo/add が呼び出される筈の気がするが…。 44548 44549 と思ったが、実は DEL などは white と認識されている? 44550 うーん。vim の動作を調べると実は vim の場合は undo は 44551 挿入モード単位で行われている様だ。つまり、 44552 現在の様な記録方法で問題ないのである。 44553 44554 しかし、やはりこれは分かりにくい。というか不便だ。 44555 オプションでもっと細かく undo を記録するモードをつけるか。 44556 その場合にはどの様に判定するのか。 44557 別に判定など考えずに undo を沢山呼び出せば良い様な気もする。 44558 44559 - done: ble/util/invoke-hook _ble_complete_insert_hook は 44560 実際に挿入を行った後に呼び出す様に変更した。 44561 実装を見てみるとどちらで行っても良い様な実装になっていたので。 44562 44563 - done: bleopt keymap_vi_imap_undo=more の時に細かく記録する事にした。 44564 新しく magic-space やら delete-backward-char やらの拡張を作るのが面倒になったので、 44565 結局 edit.sh の方の widget 本体を弄ってしまった。まあ、仕方がない。 44566 というか keymap 毎に widget の名前が微妙に違うというのも分かりにくいのでこれで良い気もする。 44567 44568 * menu-complete: C-g でキャンセルできる様にしたい [#D0995] 44569 C-g は bell だったが。bell に何か hook する事は可能だろうか。 44570 拙速かもしれないが C-g でキャンセルする事ができる様にした。 44571 44572 然し、layer:manu_filter による着色が解除されない。 44573 これに関しては明示的に invalidate するか dirty-range とするかする必要がある? 44574 取り敢えず invalidate してしまっているが、まあ面倒なので良いかという具合である。 44575 本当は caret_state に自由に外から追加できる様にするべきなのかもしれない。 44576 44577 * 2019-02-28 complete: sabbrev に登録されている単語の補完もあっても良い気がする [#D0994] 44578 実装してみたがメニュー補完に於ける置換範囲が変である。 44579 先頭の \ が抜けている所為で二重に \ が挿入されてしまうのである。 44580 これは sabbrev の候補のみを生成した時でも再現する。 44581 44582 うーん。成る程。初めから \ が除外された状態で補完が開始している気がする。 44583 というか。reconstruct-incomplete-word に於いて末尾の \ を除去するべきなのではないか。 44584 つまり reconstruct-incomplete-word による COMPV の構築に失敗して、 44585 fallback の位置で補完が開始しているという事になる。 44586 44587 reconstruct-incomplete-word で \\ に対応する事にした。 44588 然し、いろいろ考えると対応していない物は沢山ある。 44589 "a\ で終わっている様な場合や "a${para で終わっている様な場合。 44590 まあ、それらは気になった時に実装していくというので良い気がする。 44591 44592 * edit: bleopt rps1_transient 対応 [#D0993] 44593 非空文字列が設定されている時、右プロンプトを次の行に行く前に消す。 44594 44595 * util (ble/util/openat): 入れ子の bash-3.1 で C-d を受信できない [#D0992] 44596 ref #D0857 44597 44598 これは前に修正した物ではなかったか。 44599 実際に調べてみると子プロセスが起動していない。 44600 また再現するかどうかを見ると 3.0 3.1 3.2 の中で 3.1 を起動した時に起こる。 44601 前の時と全く同じ症状に見える。しかし、前の対策は有効である。 44602 exec を2つに分けて実行してみても駄目だった。 44603 44604 うーん。子プロセスが起動していないというのは前にはなかった気がする。 44605 子プロセスを起動する部分を見たが特にエラーメッセージが出ている訳でもない。 44606 調べるとどうも起動した瞬間は起動している様である。 44607 その後で read に失敗して while ループを抜けている。 44608 44609 openat でその pipe を開かない場合には失敗して終了する事はない様子である。 44610 つまり pipe を開くと read に失敗する。 44611 また openat_base をずらすと失敗して終了する事はない。 44612 44613 * edit: RET を連打するとプロンプトの表示前に行頭にカーソルが滞在している [#D0991] 44614 これは何故だろうと思っていたが、よく考えたら has-input の時には、 44615 プロンプトを再描画せずに通過するのであった。 44616 そして次の RET が来て .insert-line した時に漸く新しい行が描画される。 44617 44618 それなら新しい行を挿入した時点で textarea#render してしまえば良い。 44619 と思って render しようとしたら変な事になる。 44620 というのも新しい行を挿入した時点では新しい行の状態を指定していないので。 44621 従って、新しい行の状態を指定した上で再描画しないと行けない。 44622 特に ble/widget/* のレベルで再描画を指定するほうが良さそう。その様にした。 44623 44624 x ble/util/joblist.bflush を呼び出しているが、 44625 keep-info の時にこれを呼び出すと info が消えてしまう。 44626 これについても対策した。 44627 44628 2019-03-10 44629 44630 * menu-complete: 頁管理の枠組みを統一したい [#D0990] 44631 統一した。 44632 44633 * util: bash-4.0 未満では物凄く遅くなるので曖昧補完は無効にしたい [#D0989] 44634 と思ったがこれは実は ble/util/array-assign が原因だったのかもしれない。 44635 また後で詳しく何が原因だったのか調べる必要がある。 44636 44637 後、ble/util/array-assign は本当に高速なのか。 44638 後 ble/util/mapfile も遅そうである。 44639 というか split-lines が遅いのでは。 44640 図ってみたら確かに50倍ぐらい遅い。 44641 split-lines は while read で実装し直す事にした。 44642 44643 それ以外でそんなに bash-3.2 と bash-4.0 に差があるとは思えないので、 44644 取り敢えず様子見して固まらない限りは気にしない事にする。 44645 44646 * bash-3.1 以下で bleopt_rps1 が動いていない [#D0988] 44647 44648 これは何だろう。全く動かないというのは不思議な事である。 44649 途中でクラッシュしているという訳でもないのだと思うが。 44650 trace の問題だとしたらもっと他の場所でも影響が出ているはずである。 44651 44652 調べてみると何と measure-bbox の結果が変な事になっている。幅0という事に。 44653 しかも何故 bash-3.2 で動いて bash-3.1 で動かないのか。という事。 44654 他の実際の出力結果などはちゃんと動いている様に見える。 44655 最終的な位置に関してもちゃんと動いている。 44656 44657 と思ったらこれも算術式のバグだった。 44658 bash-3.1 では三項条件式を全てカッコで囲まなければならないのだった。 44659 これを直したら呆気なく動く様になった。 44660 44661 * bash-4.0 未満では menu-filter.idle に対応していないので、 [#D0987] 44662 layer:menu_filter は登録しない事にする。 44663 変な着色が実行されてよく分からない事になっている。 44664 44665 * bash-3.2 以下で 関数名補完が変だ。というか絞り込みが働かないので [#D0986] 44666 menu 候補がいつまで経っても最初と同じ状態で駄目だ。 44667 これは menu-filter が働いていない時には menu-filter を手動で呼び出す様にした。 44668 44669 * bash-3.2 以下で sabbrev が動いていない [#D0985] 44670 正規表現? と思ったがそもそも core-complete.sh が読み込まれていない。 44671 ble/complete/sabbrev/expand を autoload に追加しておく事にした。 44672 また、物凄く遅いが一応動いている様子である。 44673 44674 然し、この遅さは何だろう。滅茶苦茶遅い…。 44675 もしかすると全ページを構築している? 44676 と思ったが次のページに行こうとするとやはり時間がかかるので、 44677 恐らく本当に動作が遅いという事なのだろう…。 44678 44679 調べたら ble/util/assign-array に滅茶苦茶時間がかかっていた。 44680 変な split-lines のルーチンよりも while builtin read -r line の方が速いのだった。 44681 2m22s から 0.05s にまで短くなった。約 1000 行のファイルである。 44682 44683 * ble/util/msleep の usleep を使う実装に於いて警告が表示されている [#D0984] 44684 deprecated だそうだ。取り敢えず &>/dev/null で警告を殺す。 44685 44686 * bash-4.1 未満で visible-bell? もしくは menu-complete の頁描画がずれる [#D0983] 44687 そもそも1頁に表示されている項目の数が怪しい。 44688 ble-edit/info/.initialize-size の計算結果を見てみると、 44689 44690 $ echo "$COLUMNS x $LINES / $cols x $lines" >>/dev/pts/4 44691 bash-4.4: 179 x 68 / 179 x 66 44692 bash-4.1: 179 x 68 / 179 x 67 44693 44694 となっていて、この時点で計算が怪しい。 44695 ble/canvas/panel/layout/.get-available-height の中でどうなっているか確認。 44696 44697 bash-4.4 44698 declare -a mins=([0]="1" [1]="0" [2]="1") 44699 declare -a maxs=([0]="1" [1]="0" [2]="66") 44700 declare -a heights=([0]="1" [1]="0" [2]="66") 44701 44702 bash-4.1 44703 declare -a mins='([0]="1" [1]="0" [2]="1")' 44704 declare -a maxs='([0]="1" [1]="0" [2]="67")' 44705 declare -a heights='([0]="1" [1]="0" [2]="67")' 44706 44707 うーん。ble/canvas/panel/layout/.extract-heights が悪いのかとも思ったが、 44708 ble/canvas/panel/layout/.determine-heights が怪しい気がしてきた。 44709 44710 bash-4.4 44711 declare -- lines="67" 44712 declare -a mins=([0]="1" [1]="0" [2]="1") 44713 declare -a maxs=([0]="1" [1]="0" [2]="68") 44714 declare -a heights=([0]="1" [1]="0" [2]="66") 44715 lines=67 mins=(1 0 1) maxs=(1 0 68) heights=() max=69 min=2 44716 heights=(1 0 66) 44717 44718 bash-4.1 44719 declare -- lines="67" 44720 declare -a mins='([0]="1" [1]="0" [2]="1")' 44721 declare -a maxs='([0]="1" [1]="0" [2]="67")' 44722 declare -a heights='([0]="1" [1]="0" [2]="67")' 44723 lines=67 mins=(1 0 1) maxs=(1 0 67) heights=() max=68 min=2 44724 lines=67 mins=(1 0 1) maxs=(1 0 68) heights=() max=69 min=2 44725 heights=(1 0 67) 44726 44727 やはり変だ。入力が同じなのに結果が異なる。 44728 これは算術式のバグを踏んでいた。 44729 条件分岐の中に配列要素の参照があると常に処理されてしまう。 44730 44731 * rosaterm で screen -dr を isearch する時に座標計算がずれている [#D0982] 44732 これは rps1 と関係している様子である。xenl の問題だろうか。 44733 これは xenl が入っていない時には更に cols-- する様にすれば良い。 44734 44735 * menu-complete (desc-raw): 頁生成が遅い [#D0981] 44736 trace で nooverflow を指定していても文字列の末尾までスキャンしている気がする。 44737 更に言うと、ellipsis を付加する処理を何度でも実行してしまっている。 44738 特に ellipsis は余り頻繁に起こらないと思って遅い実装になっているが、 44739 今の実装だと ellipsis は全角文字の数だけ起こるのでとても非効率的である。 44740 44741 trace は制御シーケンスを解釈するので一旦範囲外に行っても、 44742 また戻ってきて範囲内に文字列を出力する可能性がある。 44743 その為に文字列の末尾まで全てスキャンしているのであった。 44744 44745 新しく ble/canvas/trace に truncate と confine の二種類を実装した。 44746 confine が今まで通り範囲外に行きそうになっても全て処理するもの。 44747 truncate は範囲外に行ったら其処で処理を終了するもの。 44748 44749 * menu-complete: ページ番号を visible-bell で表示するのはどうだろうか [#D0980] 44750 44751 * util: unicode 文字を使って出力を行うことの是非について [#D0979] 44752 44753 現在 progress の表示及び trace.draw の ellipsis の表示に Unicode 文字を使用している。 44754 然し、output-encoding が unicode とかそういう環境でなければそれは面倒な事になるのでは。 44755 古い端末だと文字化けしてしまって変な見た目になってしまうかもしれない。 44756 その様に思うと * や ... を用いた代替を用意して置いた方が良いのではないだろうか。 44757 44758 これは bleopt で設定しても良い気がする。 44759 オプション名は何にするのか。 44760 例えば output_encoding として置いて、 44761 output_encoding に Unicode 文字が使える場合にはそれを使う等。 44762 しかし、output_encoding は実のところ LC_CTYPE で制御されている。 44763 そういう風に考えれば、bleopt で指定しなくても LC_CTYPE を見て *.UTF-8 ならば 44764 unicode 文字を使うという風にして良いのではないかという気がする。 44765 44766 →LC_CTYPEを使って ble/util/is-unicode-output を判定して、 44767 それを使って出力に使う文字を切り替える様に実装を変更した。 44768 44769 その他の序での変更。 44770 44771 - (ble-edit/info/show): rename ansi -> esc 44772 - (ble-edit/info/show): esc (現在の端末の解釈) に対応 44773 - (ble/canvas/trace): 関数追加 44774 - test/check-trace.sh: lib/test-canvas.sh にマージ 44775 - canvas: rename ble/canvas/rmoveto.draw -> ble/canvas/put-move.draw 44776 - canvas: rename ble/canvas/rmoveto-x.draw -> ble/canvas/put-move-x.draw 44777 - canvas: rename ble/canvas/rmoveto-y.draw -> ble/canvas/put-move-y.draw 44778 - ble/canvas/trace.draw: opts=terminfo に対応 44779 44780 * 2018-03-14 info: progress の表示 [#D0978] 44781 44782 history の background loading で一時 progress の表示をしていたが、 44783 その後に効率的な実装方法が分かった為に結局現在は使われていない。 44784 44785 しかし、その時に残っていた課題が幾つかある。 44786 44787 * info で progress を表示するための専用の仕組みを作る? 44788 44789 一つは info で表示する事自体に 40ms 程度時間がかかっていた事である。 44790 これは progress を表示する事自体によって処理時間が長くなるという事を意味する。 44791 また info の表示を行う為に配列を使用しているので、 44792 外側のループで巨大配列を触っている時に、これも速度低下の原因となる。 44793 44794 2019-03-10 何の為に info で progress を表示する専用の仕組みを作るのか分からなくなった。 44795 また、実際に progress bar を isearch の検索進捗状況の表示に使ってみたが、 44796 "固定文字列部分 プログレスバー 状態表示" の様になっているので、 44797 info で表示する為の専用の枠組みを作っても面倒なだけの様に思われる。 44798 それよりは各自でプログレスバーを生成した方が良い気がする。 44799 44800 * ok: screen の文字幅判定のコードをチェックする。 44801 44802 % また Unicode Block Characters を使って作成した progress bar で、 44803 % 文字幅の計算がずれてしまう。これは screen 上で Unicode Block Characters が幅2 なのに、 44804 % Poderosa 及び ble.sh で幅1で扱われているのが原因である。 44805 % 使用している screen は cjkwidth emacs で動作しているのに変である。 44806 44807 これは確かめてみた所、そもそも padparadscha 上ではオリジナルの screen-4.1.0 を用いていた。 44808 改造した screen は screen-4.3.1 である。 44809 改造した repository を探してみたが padparadscha 上にはなくて magnate 上にあった。 44810 GitHub に登録することにした。 44811 また、git pull してみると 4.* 系列は既に 4.6.2 まで出ている様である。 44812 既存の改造を 4.6.2 に付け替える事にした。 44813 44814 - Cygwin でコンパイルできない問題に関しては screen-v4 では直されていた。 44815 master の方では治っていない (依然として ut_div を用いている)。 44816 - SGR mouse (DECSET 1006) は 4.6.2 で対応した様である。 44817 - 結局、4.6.2 に対する改造は `cjkwidth emacs` のみである。 44818 - 他に Makefile.in の微妙な修正が含まれる。 44819 44820 新しくした screen で試してみた所、ちゃんと文字幅 1 で計算されている様である。 44821 44822 * complete (style:desc-raw): 範囲に入り切らない場合に末尾に … を表示する [#D0977] 44823 序に style:desc でも頁描画をキャッシュする事にした。 44824 44825 * [自然解消] 2015-11-21 bug: 複数行編集でカーソルが一番上にない場合 vbell で編集内容が消される [#D0976] 44826 44827 これは既に #D0878 で解決している。 44828 44829 元々 vbell を実装した時は複数行になる事を想定していなかった (複数行にできなかった)。 44830 現在は複数行に対応したので特別の配慮が必要である。 44831 (ble-edit.sh から値を引っ張ってくる必要があるので interface を決めておく必要はあるが。) 44832 44833 * menu-filter: 着色を改良 [#D0975] 44834 然し、使ってみると menu-filter の範囲の着色は分かりやすいのか分かりにくいのか謎。 44835 更に、何処が入力の開始点なのかも分からない。 44836 44837 x 空文字列から補完を開始した時は、 44838 menu からの補完を行ってもそれを DEL で戻って修正できるが、 44839 有限の長さの文字列から補完を開始した問は、menu からの補完を行うと、 44840 補完した部分より前を修正すると menu-filter が終了してしまう。 44841 これは何が起こってるのだろうか。 44842 44843 成る程。分かった。menu-source での更新は行われていない。 44844 というか、R を入力した時点で README まで確定しているから、 44845 メニューが一番始めに表示されたタイミングが README まで入力した状態だった。 44846 従って、其処から絞り込みが開始するというのは自然である。 44847 これは寧ろ着色の問題である。 44848 44849 * menu-filter: 何故か関数名補完で一致する候補が消えても候補が menu-filter で消滅せずに残る [#D0974] 44850 うーん。これはあれだろうか。simple-word でなくなった時にそのままにしているのが悪いのか。 44851 simple-word でない時には着色だけ解除するという手もあるのかもしれない。 44852 或いは、そもそも simple-word でない時には menu-filter を使う気がないと判断するべき? 44853 44854 うーん。或いは。"simple-word ではあり得ない" という判定を作るのが良いのではないか。 44855 →その様に実装した。ble/syntax:bash/simple-word/is-never-word と言う関数名にした。 44856 44857 * 2013-06-01 以前 vbell: メッセージが長い場合に適度に長さを制限する [#D0973] 44858 44859 trace を拡張して construct-text と同様の機能を持たせるか。 44860 或いは construct-text を trace に統合してしまうか。 44861 然し、現状で construct-text はそれなりに高速である。 44862 なので、trace に統合すると遅くなってしまう。 44863 ble-edit/info/.construct-text は ble/canvas/trace-text に改名する事にした。 44864 44865 取り敢えず trace-text を利用する事にする。 44866 44867 * menu-complete: menu-filter の後に menu-complete に突入する際に menu_style が保持されない [#D0972] 44868 これはメニューから候補を読み取る際に _ble_complete_menu_style から 44869 bleopt_complete_menu_style を local 復元するという様にする事にした。 44870 44871 * menu-filter: コマンドを実行した時に着色が解除されない [#D0971] 44872 これは region の時と同じ様に _ble_complete_menu_active を解除すれば良いだろう。 44873 と思って試してみたら駄目だった。caret_state に反映されないので、 44874 _ble_complete_menu_active の変化を検出できていないのである。 44875 invalidate するか。或いは _ble_textarea_version なる変数を導入するか。導入した。 44876 ble/textarea#invalidate を拡張する事にした。 44877 44878 * edit: rps1 を設定していると vi : 等によるサブコマンドラインの表示位置がずれる [#D0970] 44879 render_opts を空にしても同じ問題が生じているので、出力部分の問題である。 44880 実際に rps1 を put している所をコメントアウトしたら直った。 44881 と思ったら _ble_textarea_panel を _ble_text_area_panel と typo していた。修正した。 44882 44883 * 2019-03-04 complete: menu-filter の編集領域を着色する案 [#D0969] 44884 44885 編集領域 (get-active-range) を layer:region を用いて着色するのは微妙そうだ。 44886 auto-complete と同時に使いたい事もあって、layer:region は 44887 auto-complete で一時挿入された部分の着色にも用いられる為である。 44888 44889 a reject: 実際に試しで実装してみたが region を使って着色するのは色々と微妙である。 44890 menu-filter は新しい keymap を導入するわけではないので、 44891 self-insert などがそのまま実行される。そうすると region が置換されて消滅してしまう。 44892 auto-complete や menu-complete や search の時に問題がなかったのは、 44893 特別に keymap を用意しているので self-insert などが region に作用しなかったからである。 44894 44895 更に当然の事であるが auto-complete が走っている間はそちらを優先しているので着色されない。 44896 44897 b reject: うーん。別の layer を使って着色を変更する事は可能だろうか。 44898 例えば overwrite_mode 及び disabled に関して。 44899 然し、着色順序が異なる。syntax の上で region の下に着色を行いたい。 44900 overwrite_mode は region と排他的なので、移動は可能かもしれないが、 44901 overwrite_mode 自体が self-insert の振る舞いを変更するのでこれは変えられない。 44902 44903 c 振る舞いは変えないけれども表示だけ変わるというような新しい layer が必要である。 44904 更に状態を制御する変数として、caret_state のチェックに menu-filter が有効になっているかどうかも含める必要がある。 44905 _ble_complete_menu_* 変数の状態は caret_state として記録しなくても大丈夫だと思われる。 44906 というのもこれらが更新されるのは何れにしても _ble_edit_str か _ble_edit_ind が変更される時だからである。 44907 44908 d 或いは disabled を逆に利用して編集領域以外を灰色で被せるなど? 44909 然し、その場合には overwrite_mode や region 等も同じ色で被せてしまう事になるので微妙である。 44910 44911 やはりもし実現するとしたら新しい layer を作るのが現実的に思われる。 44912 現状では余り活性化しない layer が増えてもそんなに重さには影響しないはずである。 44913 更に、blink-matching-paren などの機能も考えると結局 layer は増やす事になる気がする。 44914 44915 x fixed: menu-filter に入る時に何故か menu がクリアされてしまう様になっている。何故 44916 と思ったら、これは menu-filter.idle が menu-filter が失敗した時にメニューを削除するのだった。 44917 つまり、今回の変更で menu-filter の戻り値を変更したのが原因である。直した。 44918 44919 * 2019-02-15 ble.sh で [ble: EOF] としている内容は zsh では PROMPT_EOL_MARK で設定できるそうだ [#D0968] 44920 https://qiita.com/2357gi/items/6d530820402ae776ca66 44921 44922 ble.sh でもユーザが設定できる様にする? しかし、毎回座標計算するのは面倒である。 44923 というより現在の位置が分からなければ tab 等の座標計算ができないのではあるまいか。 44924 結局、現在位置を CPR で尋ねるという事をしなければならなくはないか…。 44925 44926 事前に計算しておく事にするか? その場合には tab 等の文字が含まれていた場合に困る。 44927 と思ったが、tab の場合はスペースに変換するので問題ない。 44928 垂直タブやカーソル移動等が含まれる場合はサポート外とすれば良い。 44929 44930 2019-03-09 これは trace.draw で nooverflow を実装したので 44931 一行に収まる様にして簡単に実装できる筈。 44932 44933 →実際に現在の ble.sh の実装を確認してみたところ、 44934 実は EOL_MARK の大きさに関係なく動くような実装になっていた。 44935 % というか eol mark の途中で折返し改行が入った場合はどういう動作になるのか…。 44936 % 何だかよく分からなくなったがまあ動いているから良いのだろう。 44937 これは大丈夫。何れにしても次の行に行くという事。 44938 それからもし行頭に居た時には [ble: EOL] を削除するという事。 44939 正しく削除する為には eol mark はその行に収まっていなければならない。 44940 44941 * [棄却] bleopt: openat_base -> internal_openat_base [#D0967] 44942 internal をつけるかどうかはユーザが触る可能性があるかないかである。 44943 特別な fd を使う時に触ってもらうかもしれないので internal_ は取り敢えず付けない事にする。 44944 (とは言いつつユーザがこのオプションに気づいてこれを活用する様になる事があるかは不明だが。) 44945 44946 * menu_complete: support prior, next, home, end [#D0966] 44947 44948 2019-03-09 44949 44950 * 2019-03-03 complete: desc の着色に対応する? [#D0965] 44951 44952 これは trace を弄る必要がある。trace は多分、範囲の指定に対応していない。 44953 一応見てみると LINES 及び COLULMNS を読み取って使っているが…。 44954 行末の処理などが折り返し全体になっていたり、 44955 実際に改行を挿入してしまったりなどしているのではないかと思う。 44956 これは .construct-text と同様に nonewline 等に対応する必要がある。 44957 44958 しかし、そもそも色のついた desc を生成する物がないので、 44959 実装する意義は今のところない。 44960 44961 2019-03-09 #D0964 に於いて範囲をはみ出ない様な trace を実装した。 44962 なので実は実装しようと思えば簡単に実装する事ができる。 44963 →実際に .construct-text を置き換えてみたところ普通に動作している…。 44964 計算時間に関しても特に無駄にかかっているという様な印象はない。 44965 というか寧ろ高速だったりする事はあるかしらん。 44966 44967 * trace.draw と .construct-text の速度に関して 44968 44969 % 実際に計ってみると .construct-text よりも trace.draw の方が速い… 44970 勘違いだった測定する順序を間違えていた。逆だった。 44971 44972 fa2a874 の上に居る時に .blerc (akinomyoga.dotfiles) の sabbrev \commit の表示で試した。 44973 for entry in "${measure[@]}"; do のループの実行時間を計測する。 44974 .construct-text による計算時間は: 44975 44976 real 0m0.027s 1ページ目 44977 real 0m0.248s 最後の頁 44978 real 0m0.074s 最後から2番目の頁 44979 44980 trace.draw による計算時間は: 44981 44982 real 0m0.048s 1ページ目 44983 real 0m0.739s 最後の頁 44984 real 0m0.115s 最後から2番目の頁 44985 44986 うーん。これを見た感じだと特に日本語の文字が連続している場合には 3 倍ぐらい時間がかかっている。 44987 やっぱり配列に大量に触ると遅いという事になるのだろうか。 44988 44989 うーん。DRAW_BUFF を配列ではなく普通の変数にして見たが計算時間は全く変わらない。 44990 宣言部分を local DRAW_BUFF= に変えてみてもやはり速度は変わらない。 44991 というか本当に DRAW_BUFF は配列にする事によって速度が向上しているのだろうか。怪しい。 44992 JavaScript の場合には配列に入れておいて後で連結したほうが速かったが 44993 bash の場合はどうなんだろう。実際に計測してみる事にする。 44994 44995 $ bash-5.0 benchmark-strbuff.sh 44996 4485.78 usec/eval: concat.str (x50) 44997 4493.09 usec/eval: concat.ret (x50) 44998 2177.40 usec/eval: concat.arr (x50) 44999 45000 うーん。実際に計ってみると配列を連結したほうが速い様だ。 45001 45002 5745.09 usec/eval: concatB.str (x20) 45003 5899.53 usec/eval: concatB.ret (x20) 45004 3574.55 usec/eval: concatB.arr (x50) 45005 45006 途中で別の配列も一緒に触る様にしてもやはり配列の連結の方が速い。 45007 複数の配列を触って遅くなるのは物凄く長い配列の場合だけだろうか。 45008 Bash の version 毎に違いがないかも確かめたが違いはない様子である。 45009 45010 まあ速度的には微々たる物の気がするので気にしない事にする。 45011 45012 * 着色した場合の速度はどうだろうか。と思って調べたが 45013 30ms 程度の遅延が一様にかかる様である。まあ気にしなくて良い。 45014 45015 * 切り替えられる様にした。desc-raw とした時に trace を用いる事にした。 45016 45017 * 2019-03-08 canvas: ble/canvas/trace を大幅に書き換えようと思う [#D0964] 45018 45019 complete: desc で色のついた説明を表示できる様にする事に関連して。 45020 45021 1. 特に先ず初めに範囲内に収まらない場合に出力しない様に修正する。 45022 2. 改行などで移動している部分を相対位置の移動でもできるオプションを実装する。 45023 45024 実装した。これで Window 的な物を実装する事はできる様になったのではないかという気がする。 45025 overlay が簡単に実現できる様になったかどうかについては微妙な所ではある。 45026 overlay は textarea/info の上でに overlay する事を考えれば、 45027 textarea/info それぞれに対して再描画等の処理が必要になる。 45028 それぞれに対して指定された範囲を再描画する関数を実装するか。 45029 45030 * reject: 背景色を設定する場合を考えると。 45031 また改行を実行する際に現在位置の右をスペースで埋めるオプションは必要になるだろうか。 45032 と思ったが、\r を実行してから改行を実施する場合もあるし、難しい問題である。 45033 先にスペースで埋めてから描画するという具合にするしかないのではないか。 45034 45035 % Note: ble/textmap#update に於いては、 45036 % #D0959 での考察により terminfo に ech がある場合にはそれを使い、 45037 % もしなければ半角空白で埋めるという事をする事にした。 45038 % 45039 % erase-eol (ech で消去する) fill-eol (半角空白で埋める) などの 45040 % オプションを用意しても良いのかもしれない。 45041 % と思ったが \r を実行してから改行を実行する場合も考えると対応は難しい。 45042 45043 やはり何か枠の中に描画する際には始めに 45044 呼び出し元でその枠の中身を消去しておいてもらう必要がある。 45045 45046 * done: RPROMPT の表示にも使うことができるかもしれない → #D0959 実装した 45047 45048 * done: trace 中に最大で何処まで右に行ったかを記録したい。 45049 45050 opts=measure-bbox として実装する事にした。 45051 これの実装は面倒そうだと思ったが意外と簡単だった。 45052 殆ど全ての動作は直線的に行われ、 45053 直線でないのは折返し操作が入る時だけなのであった。 45054 折返し操作が入る場合には 0-cols を範囲に含めれば良い。 45055 他の操作に関しては操作が終わってからの位置を見るだけで良い。 45056 45057 →これを用いて rps1 の表示位置を決定する事にした。 45058 45059 x fixed: と思ったら日本語を含む時に座標計算がずれている…。 45060 これは先日 trace を修正した時のバグだった。直した。直った。 45061 45062 まあ、こんな物である。また本格的に Window System でも作る時に手を入れる 45063 必要が出てくるかもしれないが今はこれ以上の拡張は行わない事にする。 45064 45065 * [自然解消] 2013-06-05 RPS1 [#D0963] 45066 zsh で試してみた所、そもそも RPS1 に改行を含めると RPS1 自体表示されない事が分かった。 45067 改行は含まれていないと仮定して表示してしまっても良いのかも知れない(2015-03-04)。 45068 45069 2019-03-09 #D0959 で "bleopt rps1=" として実装した。 45070 45071 * [自然解消] 2015-02-21 zsh にある機能で気になる物 [#D0962] 45072 45073 menu 補完と言った物もあるようだ。 45074 選択肢の説明の表示もできる。 45075 考えつきそうな機能は一通り揃っているという事か。 45076 45077 2018-09-23 メニュー補完は既に対応した。 45078 選択肢の説明は表示していない。 45079 menu_style で選択肢の説明を表示するモードも提供して良いかもしれない。 45080 45081 2019-03-09 選択肢の説明に関しては #D0946 で対応した。 45082 45083 * 2019-03-05 complete: "ble/complete/" の状態から menu-complete に入る事ができない [#D0961] 45084 これは後で調べる必要がある。 45085 45086 調べてみると $_ble_complete_menu_active の値が auto になっているのが原因だった。 45087 では何故 _ble_complete_menu_active=auto の時には menu-complete に入らないのか。 45088 と思ったら、これは敢えてその様にしているのだった。二回 complete を押して漸く 45089 menu_complete に入れる様にというそういう配慮だった。 45090 しかし、今 auto-complete の所為で LASTWIDGET が変化しているので、 45091 LASTWIDGET による判定に頼る事ができない。 45092 45093 よく考えてみたら今では footprint による判定を実行しているので、 45094 わざわざ _ble_complete_menu_active=auto 等の様な仕組みは用意しなくて良いのだった。 45095 45096 実際に削除してみたら動作が変である。filter で一意確定になった状態で 45097 complete を実行しようとしても enter_menu になってしまう。 45098 うーん。filter で一意確定になる所までは良い。 45099 問題はその一意確定が唯の prefix として生成された物であって、 45100 実際には完全な候補ではないという事である。 45101 なので候補を再生成しなければならないが、 45102 現在 menu から候補を読み取る機能を実装してしまった為に、 45103 再生成が行われなくなったというのが問題点である。 45104 45105 * complete: ~/ble 等と ~/ に続けて存在しないファイル名を入力すると物凄く処理に時間がかかる [#D0960] 45106 途中の処理中断が働いていないという事が考えられる。 45107 45108 ble/complete/source:file/.construct-ambiguous-pathname-pattern が緩すぎて、 45109 /home/murase/ble に対して m (substr 一致) で /*/*/* が生成されていた。 45110 もっと厳しく判定する事にした。速くなった。 45111 45112 * edit: bleopt rps1 に対応 (RPROMPT (RPS1) 実装) [#D0959] 45113 45114 | ble/canvas/trace.draw の書き換えに 45115 | 類似の書換として、textarea の改行を入れる時に 45116 | 右側に表示されている内容を消すというのがあった。 45117 | これが RPROMPT の実装の際に問題になっている。 45118 | これを何か別の物に置き換えるという事は可能だろうか。 45119 | 例えば RPROMPT が設定されている時には、 45120 | textarea の幅が狭くなった状態になっている。 45121 45122 結局 RPS1 に対応してみる事にした。 45123 45124 a その時に右側を消すには文字数を指定した消去を使うことができる。ECH である。 45125 と思って infocmp を見てみたが ECH なる項目はない。 45126 b DCH と ICH の組み合わせで実装するしかない。 45127 然し DCH で全角文字がある場合にはどうなるのだろう。 45128 と思って実際に試してみた所 Poderosa でエラーが発生した。 45129 なのでこれを使う事はできない。 45130 c 実は此処は単に空白文字を出力するだけで良いのではないか。 45131 45132 取り敢えず実装した。RPROMPT がある時には opts に 45133 relative を入れて実行すれば良いのではないか。 45134 実は、常に relative を入れても良いのかも知れない。 45135 45136 実装した。 45137 45138 x fixed: 何故か表示されないと思っていたら結果が記録されていなかった 45139 x fixed: PS1 を上書きしていると思ったら local ret するべきだった 45140 x fixed: 表示位置がずれている。一番右ではなく余白ができている。 45141 これは cols を rps1 を除いた長さに修正したことを忘れていた事による物だった。 45142 45143 動いている気がする。 45144 45145 * done: RPS1 は bleopt_edit_rps1 に変更する。 45146 →結局 bleopt_rps1 という名前にする事にした。変更した。 45147 45148 * done: 次に文字を入力しても消去されない様にする必要がある。 45149 というより文字を入力した時に何処で消去が起こっているか調べる必要がある。 45150 45151 * ble/textarea#render/.show-scroll-at-first-line 45152 先ず line... というのを表示する所で _ble_term_el を出力している。 45153 ここは rps1 が有効の時は relative にする。 45154 45155 取り敢えず上は render_opts を参照して消去を行う様に修正した。 45156 然し、他に _ble_term_el を出力している箇所はない…。 45157 という事となるとやはり ble/canvas/trace.draw が末尾に el を出しているのだろうか。 45158 もしくは ble/textarea#slice-text-buffer の辺りか…。 45159 見つけた。ble/canvas/panel#clear-after.draw を呼び出している所である。 45160 45161 動かしているが座標計算が誤っている。 45162 と思ったら ble/canvas/panel#goto.draw を呼び出すべきところを、 45163 ble/canvas/goto.draw を呼び出していた。直した。 45164 45165 * done: _ble_term_ech 対応 45166 現在は空白を大量に出力するので効率が悪い。既存の端末の ech 対応状況を調べて、 45167 もし多くの端末で対応されているようであれば ech を用いた実装も準備する。 45168 dch と ich を用いた実装は poderosa が全角文字で火を吹くので駄目。 45169 45170 RLogin 及び xterm は対応している。screen, mintty も対応している。 45171 Poderosa (myoga) は何故か引数の解釈が一つずれている? 45172 うーん。やはり ech は terminfo の中でも余りない為に動作が怪しい。 45173 terminfo に登録されていても使わない方が安心なのでは。 45174 しかし xterm に登録されている…。 45175 xterm を名乗りながらバグが有るのはその端末の責任である。 45176 なので、ble.sh の知ったことではない。寧ろバグの洗い出しになるだろう。 45177 45178 Poderosa での ICH/DCH/ECH の実装について。 45179 % 例えば Poderosa-4.35b では (1) 引数の解釈がおかしい (1 少なく解釈される)。 45180 % (2) ECH で全角文字の途中まで消去すると変な文字が表示される。 45181 % (3) DCH で全角文字の途中まで消去しようとするとエラーメッセージが出る。 45182 実際にソースコードを見てみたところ自分の実装がおかしかっただけの気がしてきた。 45183 Poderosa で xterm の場合で動作確認したところ、 45184 DCH に関しては中途半端な文字が残ってしまうが、他の動作は普通だった。 45185 45186 取り敢えず Poderosa の DCH を直した。ECH はどうも変な振る舞いは起こっていない。 45187 全角文字の途中までの消去でもちゃんとスペースになっている気がする。 45188 引数の解釈も問題ない気がする。修正した。後で更新する事にする。 45189 45190 以下の項目はこれで実装完了とする。 45191 45192 | + 2015-11-21 RPS1 45193 45194 2019-03-07 45195 45196 * complete: menu の頁 [#D0958] 45197 45198 現在の実装だと画面に収まる範囲でしか選択できない。 45199 commit id 等の場合には入力による絞り込みは難しいので、 45200 やはりどの項目も menu からアクセスできる様にしたい。 45201 そう考えると menu の頁に対応するのが良い気がする。 45202 その為には現在表示している項目の範囲を記録するという事、 45203 それから前に表示した頁の先頭位置を記録するという事。 45204 S-TAB で戻った時には計算が重くなるが、全頁について計算する。 45205 45206 うーん。取り敢えず desc の場合にはページと項目番号の対応が自明なので、 45207 desc の場合にだけ対応してしまうというのも一つの手である。 45208 45209 現状の実装について観察する。どうも construct-text が lines をはみ出ない様になっている為に、 45210 途中で内容が切れていても収まっていると判定されている…? それによって中途半端の項目が表示されている。 45211 更に中途半端の項目はメニュー選択で着色されたりされなかったりして振る舞いが一定していない気もする。 45212 今の所再現する条件については分かっていない。 45213 45214 * done: 現在の表示の高さは最後の行に改行を出力する事前提で一行少なめになっている。 45215 末尾の改行を無駄に出力しない様にする事に出最後の行まで使い切る様に修正する。 45216 45217 * fixed: 中途半端に表示されている項目は表示しない様に修正する。 45218 然し、中途半端になったかどうかについてどうやって判定すれば良いのだろうか。 45219 うーん。.construct-text の実装を調べるとまあ分からない。 45220 一番最後の位置に移動していれば丁度ぴったり収まったかはみ出たかのどちらかである。 45221 然し、やはりちゃんと収まったかどうかについて判定できる方が良い。 45222 45223 はみ出たときにはそれを検知する様にするべきである。 45224 →はみ出た時には .construct-text は失敗する様にした。 45225 また同様に construct-single-entry についても失敗する様にした。 45226 45227 戻り値を用いてはみ出た項目については出力しない様に修正した。 45228 但し、一番初めの候補の時点ではみ出てしまう場合にははみ出ても表示する。 45229 45230 どの様に頁を変更・表示するのかについて考える。 45231 ble/widget/menu_complete/forward を観察すると 45232 _ble_complete_menu_selected が現在の頁の中の選択位置で、 45233 ${#_ble_complete_menu_items[@]} が現在の頁の中の項目の数である。 45234 これに加えて ${#_ble_complete_menu_pack[@]} も考慮に入れて再描画などして実行すると良いのではないか。 45235 45236 * done: 先ず初めに menu/show に於いて開始位置を指定して表示できる様にする。 45237 _ble_complete_menu_offset という変数を用意して其処に offset を記録する事にした。 45238 45239 * done: 実装した。動いている。 45240 45241 但し頁切替時の offset の計算方法が適当である。 45242 45243 a 或いは construct に統合しても良いのかもしれないとも思う。 45244 適当な場所から描画を始めて二分法的に開始位置を特定する。 45245 45246 もし頁切替時の offset の計算を construct に統合するのだとすれば。 45247 その際には opts として offset=NUMBER ではなくて、 45248 bottom=NUMBER もしくは end=NUMBER 等を指定できる様にする? 45249 或いは scroll-up=NUMBER もしくは scroll-down=NUMBER でも良い。 45250 と思ったが、scroll-up/down の up/down は紙の話か枠の話かで分かりにくい。 45251 scroll=NUMBER にして現在の表示範囲と較べて自動で判定してもらうという手もある…。 45252 45253 b 或いは全て計算を実行しきってしまうか。と思ったが、計算に時間が掛かるし、 45254 更に大抵の場合にはスクロールもしないで終了するので意味がない。 45255 45256 やはり適当に計算を実行するしか無い気がする。 45257 45258 c 或いは、一度表示した頁に関してはその情報を記録しておくという手がある。 45259 但し info の高さなどが変更になった場合にはその情報をクリアしなければならない。 45260 また遡った時には頁情報を利用することができないので、 45261 やはり中途半端な実装になってしまう。 45262 45263 適当な見積もりで何とか誤魔化すしかないだろうか。 45264 45265 d 或いは逆方向に rendering する事は可能なのだろうか。 45266 そちらの方が現実的な気がしてきた…。と思ったが、 45267 やはり逆方向に rendering しても元と完全に一致するかは分からないし、 45268 中途半端に実装しても非直観的な振る舞いになってしまう。 45269 45270 二分法で当たりをつけるにしても最初の範囲はどの様に決定したら良いか。 45271 一番最初からにすると候補が増大した時に大変な事になる。 45272 1項目あたりの長さを見積もってそれで適当に予測を立てるしかないのだろうか。 45273 1項目あたりの長さに関しては bleopt_complete_menu_align で最大値が分かる。 45274 しかし実際にはもっと短いファイル名の場合などがあるのでもっと小さくなりうる。 45275 或いは最低の align という物を定めてしまっても良いのかもしれない。 45276 45277 e うーん。やはりどうしても実装が汚くなってしまう。 45278 もし bash ではなくて十分に速度の出る言語だったらどの様に実装しただろうか。 45279 普通に考えて一番初めに全て計算しきってしまうだろう。 45280 45281 或いは、その時に request した部分までを計算して、 45282 既に計算し終わった部分に関しては何処かに記録しておいて、 45283 未だ計算し終わっていない部分が必要になったらその時に計算を実行する。 45284 45285 うーん。まあこの方法が一番まともな気がする。 45286 変に速度を気にしておかしな実装にするよりはずっと良い。 45287 問題は info の幅が変更になった時に再度計算し直しになるという事だが 45288 これは速い言語で実装する時にもそうなる筈なのだから気にしなくて良い。 45289 45290 取り敢えず各項目が表示される頁は固定という事にしてしまう。 45291 そうしないと頁を跨る項目などが現れて面倒な事になるからである。 45292 また、offset=NUMBER の指定ではなくてどの項目を表示するかの指定を 45293 scroll=NUMBER で指定する様にする事にする。 45294 実装が複雑になりそうなので一旦 commit を作ってしまう事にする。 45295 45296 * style:align に関して配置を計算しようとしたが厄介である。 45297 先ず始めに幅をどの様に決めるか。これは実際の項目の幅を全部見ていかなければ分からない。 45298 そして幅というのはページごとに計算するべきである。 45299 という事を考えればページごとに配置を計算していかなければならないという事になる。 45300 45301 なのでループする時にも実際に途中まで計測を実行して頁配置を実際にして、 45302 そしてはみ出たところからまた項目の計測を行って頁配置を実際にして、 45303 というのを繰り返して計算を実行しなければならない。 45304 うーん。1から計算し直さなければならないのだろうか…。 45305 或いは計測した情報だけから何か有意に計算する事が可能だろうか。うーん。 45306 incremental に実際に取る幅を計算していく事ができるだろうか。 45307 取り敢えず考えてみる事にする。 45308 45309 1. 仮定として全角文字は含まれないという事にする。 45310 つまり単語の任意の箇所で改行が実行できるという様に仮定する。 45311 2. max_wcell は cell の幅の最大値である。 45312 3. wcell は現在までの項目から決めた cell 幅という事にする。 45313 ncell は現在までの cell の数という事にする。 45314 45315 wcell を大きくしなければならないという事が分かった時にどの様に更新するのかという事。 45316 先ず wcell->wcell+delta とする時に、一行に収まる cell の数が減少する。 45317 逆に増えるという事はありえない。これによって ncell_max が減少する。 45318 また一旦 wcell が max_wcell に達すると、それ以上に wcell が増大する事はなくなる。 45319 また align-nowrap に関しては、wrap が起こる様な場合というのは、 45320 必ず wcell が max_wcell に達した後になるので、これも wcell は固定されていると思って良い。 45321 45322 まずはじめはキャッシュの形式などを考えることなく愚直に最後まで実装する事を考える。 45323 その後で途中で中断・再開する為に必要なデータの形式について考える事にする。 45324 というか正しく実装すれば実は一つのループで実装できてしまうのではないかとすら思われる。 45325 45326 取り敢えず配置の見積もりの部分までは書いてみたが…。うーん。本当にこれで大丈夫なのだろうか。 45327 正確に測量できているだろうか。予想外の事によってやはり収まらないみたいな事はないのか。 45328 と思ったが、実際にそういう可能性がある。というのも、全角文字の途中で改行が起こって収まらない可能性があるから。 45329 その様に考えると頁を一つ処理する度に、一旦ループを抜けて実際の配置の構築を実施しなければならない筈である。 45330 一応、wcell <= max_wcell の時には途中で改行が入るなどの事はないと思われるが、 45331 実のところ場合分けしても仕方がないので前提として改行が入る可能性を考えてページごとにレンダリングを試す事にする。 45332 頁に収まらない項目に関しては計測が重複してしまう様な気もがするがそれは仕方がない。 45333 というかその部分をキャッシュすることにすれば良いという気もする。 45334 45335 頁内容の構築の部分は今までのコードを流用すれば大丈夫のはずである。 45336 取り敢えず動作テストだけ実施してしまう事にする。 45337 45338 x fixed: フリーズする→これはどうにかして直した。 45339 x fixed: 一列になってしまう→ncell の初期化をしていなかった。 45340 x fixed: TAB を連続で押すとフリーズする→これは check-cancel 45341 で終了したのに成功したとして処理していたのが悪かった。 45342 x fixed: 何故かもっと表示できるはずなのに余り表示されない。 45343 これは cols%wcell の余白に収まる候補が改行されないのが原因であった。 45344 余白に収まる場合には改行しないという事を考慮に入れた実装にしたい。 45345 45346 まあ、取り敢えず style:align の頁は実装した。 45347 45348 * style:dense は style:align よりは簡単だろう。 45349 というのも途中で wcell が幅を変えるだとか変則的な事は起こらないので。 45350 実装した。動いている。取り敢えずこれで良い気がする。 45351 45352 * style:desc はもっと簡単である。 45353 動作確認する。動いている。OK 45354 45355 最早 offset がどうのというコードは要らなくなったので削除する。 45356 45357 2019-03-04 45358 45359 * complete: menu-filter が有効の時は auto-complete を無効にする? [#D0957] 45360 <kbd>C-g</kbd> で menu-filter をキャンセルする (menu を消す)? 45361 45362 うーん。実際に試してみたけれども微妙な気がしてきた。 45363 編集領域の途中にカーソルがある時に勝手に auto-complete を挿入されると 45364 混乱の元になってしまうので抑制するというのは正しい気がする。 45365 45366 然し、更に編集領域の末尾にカーソルがある時に 45367 auto-complete を抑制する事が果たして自然なのかは分からない。 45368 45369 % というか、編集領域が "" の時に auto-complete を許していると、 45370 % その後の文字入力に対して編集領域が変化した時に auto-complete に食われてしまって 45371 % menu-filter が働かないのではないかという気がする。 45372 % →と思って実装を調べてみたら auto-complete の時には 45373 % menu-filter 側で特別の対策をしていて auto-complete 45374 % で挿入された部分をちゃんと取り除いてから処理している。 45375 45376 うーん。こうなっているとすると、menu-filter の active range を 45377 layer:region (_ble_edit_mark_active) を用いて着色するという作戦は微妙? 45378 →これは独立した項目として議論する事にする。 45379 45380 * complete: menu-complete に入る条件がやはり何かずれている [#D0956] 45381 45382 三回目の TAB で漸く menu-complete に入るという状態になっている。 45383 45384 echo pr [TAB] echo pro [TAB] echo pro [TAB] echo prog 45385 45386 本当はこの様な時には2回目のTABで menu-complete に入って欲しい。 45387 具体的にどの様になっているかを調べてみるのが良い。 45388 特に footprint がどの様な状態になっているのかが一番怪しいので調べる。 45389 45390 どうやら記録されている footprint の _ble_edit_mark の位置が異なるのが原因である。 45391 というか _ble_edit_mark の位置は auto-complete に依って書き換えられるのだから、 45392 異なっていても仕方がない。なので、_ble_edit_mark は footprint に含めない。 45393 もしくは _ble_edit_mark_active が設定されている時にだけ footprint に含める。 45394 45395 直した。その他の場面でも前よりも違和感のない動作になった様な気がする。 45396 45397 2019-03-03 45398 45399 * VARNAMES でブレース展開を使うのは良くない。refactoring の置換で変な事になる [#D0955] 45400 具体的には edit.sh の _ble_dirty_... など。手で展開した。 45401 45402 * info: ble-edit/info/.construct-content raw は分かりにくい [#D0954] 45403 結局中で trace するので、raw ではなくて ANSI sequence である。 45404 これは ansi だとか esc だとかにするべきなのでは。esc が良い。 45405 幸いに raw という単語は他に殆ど使っていない様なので一括で置換できそう。 45406 45407 * complete: desc を表示する為の単語候補は既定にしても良いのでは。。 [#D0953] 45408 対応した。 45409 45410 * complete: menu-filter した後の menu-complete を確定すると / が付加される [#D0952] 45411 これは起こったり起こらなかったりする。LICENSE.md で起こる。 45412 うーん。必ず起こっている気がしてきた…。何故だろう…。 45413 45414 また動作を調べてみる事にする。 45415 これは _ble_complete_menu_items (表示候補) からデータを取り出さなければならないところを、 45416 _ble_complete_menu_pack (全候補) からデータを取り出していたのが行けなかった。 45417 番号が全く異なるので別の候補 (ディレクトリ) を取り出して処理していた。 45418 今まで問題にならなかったのは menu-filter をした後に menu-complete に入る事がなかったので 45419 両者の番号が一致していたという所にある。 45420 45421 これはちゃんと _ble_complete_menu_items からデータを取り出す様にしたら直った。 45422 45423 * complete: menu-filter した後に TAB で menu-complete に入ろうとしても入れない [#D0951] 45424 どうも新しい補完が発動している様な気がするが…。 45425 しかし、menu-filter はクリアされていない様子である。 45426 45427 これは ble/widget/complete の中で enter_menu になる条件の所を調べる必要がある。 45428 うーん。自動補完が関係している様な気もしている。 45429 45430 具体的に再現する例は Makefile make_command.sh というファイルが存在して、 45431 その時に "echo @" で補完を開始して "echo ak" まで絞り込んだ時に、 45432 メニュー補完に入る事ができない。 45433 45434 具体的に見てみる事にする。 45435 45436 連続で素早く TAB を入力するとメニュー補完に入る事ができる。 45437 auto-complete が LASTWIDGET を書き換えてしまっているという事だろうか。 45438 調べるとたしかに書き換えてしまっている。 45439 しかし、別経路でメニュー補完に入るのもある。 45440 _ble_edit_str と _ble_complete_menu_str が一致している時である。 45441 今までは大体こちらの別経路の方でメニュー補完に入っていた様に思われる。 45442 今回これが効かなくなってしまったのは _ble_complete_menu_str の更新が変わったからである。 45443 今までだと _ble_complete_menu_str は最後に complete を実行した時の編集文字列だった。 45444 然し、現在では complete を実行したとしても必ずしも _ble_complete_menu_str は更新されない。 45445 従って、ここでの判定に _ble_complete_menu_str は使えない。 45446 45447 というか _ble_complete_menu_str は元々 filtering の初期状態を残しておく為の物だった。 45448 45449 a なので、この用途の為にはまた別の変数を用意するのが良い気がする。 45450 うーん。然し変数名はどうした物か。 45451 というか str,beg,end は何れも active-range の為の物なので menu を始めに表示した時の物である。 45452 str の名称を変えるのだとしたらそれに応じて beg,end も変えなくては変である。 45453 従って、str,beg,end の変数名は変えない事にして、 45454 最後に TAB で complete を呼び出した時の内容は別の変数名 str2 などに格納するのか。 45455 45456 b 或いは LASTWIDGET が正しく動く様にするという手も考えられる。 45457 というか ble-decode-key を使っているのだから、LASTWIDGET が設定されても良いのでは? 45458 と思ったが cancel-default も LASTWIDGET を設定するし、 45459 ble-decode-key から呼び出された complete も LASTWIDGET を設定するし、 45460 という事になるので難しいし、今の振る舞いが変であると言うこともできない。 45461 45462 c やはり変数に記録する方法が良いのだろうか。 45463 後、カーソル位置についても確認した方が良い気がする。 45464 45465 うーん。ble/textarea#render の更新でチェックしている _ble_textarea_caret_state 45466 と似たような情報を調べたほうが良いだろうか。つまり、カーソル移動等があった後は、 45467 いきなりメニュー補完に入るのではなくて、一回は通常の補完を試みる。 45468 45469 というか menu-filter の途中で auto-complete が起こるのは微妙である。 45470 うーん。menu-filter の途中では auto-complete が起こらない様にするか…。 45471 その様にした方が振る舞いとしてすっきりする気がする。 45472 また、auto-complete がなければ get-active-range の着色も region layer からできる。 45473 45474 →結局 footprint という変数名にして _ble_edit_{ind,mark,mark_active,overwrite_mode,str} を記録する事にした。 45475 45476 45477 * complete: REPLACE の時の auto-complete と上書きされる文字の着色について [#D0950] 45478 auto-complete で一時的に挿入される内容が上書き対象として着色されてしまっている。 45479 45480 これは以下の順序が問題である。 45481 _ble_highlight_layer__list=(plain syntax region overwrite_mode disabled) 45482 然し、この順番になっているのには理由があるのではあるまいか。 45483 例えば region で囲まれている時に overwrite だったら…。 45484 囲まれている時の self-insert は囲まれている部分を削除するのであって、overwrite は無効になる筈である。 45485 したがって、そもそも overwrite_mode は mark_active の時には着色しない? 45486 45487 然し、mark_active= は色々な場合がある。単なる選択の場合から矩形選択だとか、云々。 45488 45489 1 ... これは通常の選択 (選択範囲を置換) 45490 S ... これは shift による移動中 (選択範囲を置換) 45491 search ... これは検索中 (選択範囲を置換) 45492 menu_complete ... (範囲を削除した上で上書き) 45493 auto_complete ... (範囲を削除した上で上書き) 45494 vi_c?surround ... (入力待ちなので self-insert が起こる事はない筈) 45495 vi_{char,line,block}+? ... 45496 これは xmap の時には self-insert は起こらない。 45497 選択モードの時には選択範囲を置換する。というか、 45498 選択モードから抜けた時に REPLACE になる事はあるのだろうか。 45499 vi_search ... これは normal mode なので挿入は起こらない 45500 vi_filter ... これはコマンドを入力している間の話なので関係ない。 45501 45502 この様に眺めてみると、実は overwrite_mode の着色は、 45503 menu_complete/auto_complete の時を除けば mark_active なら無効にして良い気がする。 45504 実際に動かしてみた。まあ、大丈夫である。 45505 45506 menu_complete/auto_complete に関しては妥協する。 45507 将来的にオーバーレイかそれに類いする方法を実装した時には、 45508 auto_complete は region ではない方法で実装される様になるので、気にしなくて良い。 45509 menu_complete に関しては実際に挿入する事になりそうだが、 45510 その時に self-insert をした時に何処が上書きされるのか、を表示するのは結局面倒である。 45511 45512 或いは、mark_active の種類毎に削除した上での overwrite かどうかを取得して、 45513 削除した上での overwrite だったら範囲の末尾で着色をするという事もできるのかもしれない…。 45514 然し、実装として汚くなるので妥協してそういう実装にはしない事にする。 45515 45516 x ok: vi_nmap (`!!`): キャンセル時に vi_filter の色が残る。と思ったが勘違いだった。 45517 C-g ではキャンセルできないのだった。 45518 45519 x fixed: xmap r での上書きの着色が見えなくなった。今までは上書きになるという事を示すべく、 45520 カーソル位置で色が水色になっていたが、それがなくなった。 45521 しかし、それはこのままでも良いような気がしてきた。 45522 というのも $ で行末に行っている時には結局水色にならないからである。 45523 45524 _ble_edit_overwrite_mode=R の時には選択範囲の着色を変えるのが良いのではないかと思ったが、 45525 そうすると、vi_{char,line,block}+? のそれぞれに対してコピーを作成する必要があって不毛である。 45526 と思ったが、mark:vi_{char,line,block}/get-face の中で _ble_edit_overwrite_mode を参照すれば良いだけ? 45527 →その様に実装する事にした。動いている。 45528 45529 * 2018-08-26 complete: 候補一覧にて曖昧一致に関しても一致部分を太字にすると便利ではないか? [#D0949] 45530 45531 % これは処理が重くなるので取り敢えずは実装しない。 45532 % 45533 % うーん。awk による実装に切り替えたら現実的な速度で実装できるかもしれない。 45534 % awk による実装で問題になるのは getg を先に全項目に対して呼び出して置かなければならないという事。 45535 % シェルの実装だと画面の大きさに達したらそこまでで良かったが、awk の実装だとそういう訳には行かない。 45536 % と思ったが、まあ、文字数で数えて上限を設定すればそう問題でもない。 45537 % 45538 % 2019-02-08 更に配列を awk に渡すなどの際に色々面倒な事がある気がする。 45539 % とにかく実装が汚くなってしまう。何か簡単に一発で着色できる方法の様な物はないだろうか。 45540 % 或いは、部分一致だけ awk で処理して着色部分に関しては ble.sh 側で行うという手も考えられる。 45541 % 何れにしても bash が遅いのが問題なのである。 45542 % 45543 % 2018-09-05 ブレース展開の comps_ibrace による固定部分の処理には注意する。 45544 45545 →これは結局 #D0948 の一環で実装した。awk 等は使わず結局 bash だけで実装する事になった。 45546 そもそも曖昧補完で沢山一致するという事が余り考えられないので速度は取り敢えず気にしない。 45547 45548 * complete: menu-filter に於いて、候補がなくなった時の曖昧一致は [#D0948] 45549 45550 1. 部分一致 45551 2. 先頭1文字と部分列一致 45552 3. 部分列一致 45553 45554 の優先順位で試す事にしたい。というより普通の補完の時にも 45555 その様にして良いのかもしれない。但し、コマンド補完などの場合には 45556 大量の候補が生成されて処理に時間がかかってしまうので、 45557 部分列一致は無効にするなどの事はして良いのではないかと思う。 45558 45559 menu-filter に関しては実装した。然し、通常の補完については実装していない。 45560 45561 →取り敢えず簡単に実装してみたが、未だ候補生成部分を弄っていないので 45562 部分列一致に関しては不完全である。 45563 45564 * done: 曖昧一致の種類が分かる様にする。comp_type を弄る。 45565 一応一通り書いた様な気がする。 45566 候補生成部分に関しても実装した。 45567 45568 * fixed: source:glob の実装が怪しい。 45569 pattern* による補完が可能かどうかチェックする。 45570 これは今までの実装では動かなかったが修正して動く様になった。 45571 45572 動作テストをしてみる。 45573 45574 x ok: 何故だか menu-filter を実行した後に ble/widget/complete を呼び出しても、 45575 その場で補完が起こってしまって enter_menu にならない気がする。 45576 と思ったが、その動作で正しいのだった。 45577 もしかすると保管によって挿入できるかもしれないとして、 45578 メニューに入らずに TAB を押したいという事があるかもしれない為である。 45579 二回 TAB を押した時に限ってメニュー補完に入るのである。 45580 45581 o 取り敢えず substr も subseq も動いている気がするので OK 45582 45583 * done: 実装を整理する。つまり、menu-filter と最初の生成のルーチンを共通化する。 45584 45585 * done: 曖昧一致によって menu 項目着色のルーチンを変更する 45586 45587 現在の実装を確認してみると先頭一致の場合には途中で色を切り替えて、 45588 曖昧一致の時には全体をそのまま描画する様になっている。 45589 .construct-text を途中で呼び出しつつ処理している。 45590 45591 どの様な実装にするのが良いだろうか。 45592 例えば、trace を呼び出してしまって計測するという手は? 45593 →その方法だと埋め込まれた制御シーケンスの切り出しなどが手間である。 45594 やはり .construct-text を自分で呼び出していく方が高速に動作する筈である。 45595 45596 さて、どの様に実装するのが良いだろうか。 45597 例えば filter:substr/get-matches という形で配列に一致部分を格納する? 45598 或いは filter:substr/construct という関数で、自前で描画してもらう事にする? 45599 前者の実装の方が良い気がする。前者の方法で取り敢えず実装してみる事にする。 45600 45601 - ble-complete/candidates/filter:hsubseq/match は何となく実装したが今ひとつ自信がない。 45602 →テストした。少し直した。 45603 - 更にこれを使って着色するコードを書いた。動いている。 45604 - substr の時の動作が変だったが直した。 45605 45606 x fixed: 部分列一致を通常の補完でも実装したつもりなのに動いていない。 45607 progcomp が悪いのだろうか。然し、空の文字列の時にはちゃんと補完候補が現れている…。 45608 これは調べてみると progcomp の問題ではなくて、 45609 generate-with-filter の関数の戻り値の問題だった。曖昧補完が全く起動しなくなっていた。 45610 45611 x fixed: 今度は補完した時に表示される筈の候補が一瞬しか表示されなくなってしまった。 45612 挿入が起こると消滅してしまう様子である。今までは動いていた。 45613 45614 調べると候補一覧は if [[ $insert_flags == *m* ]]; then の中で表示している。 45615 実際に中にある menu/show を省略すると一瞬表示されていた物は全く表示されなくなった。 45616 問題は、誰かが表示を消しているという事である。 45617 45618 うーん。不思議だ。ちゃんと menu/show は呼び出されている気がする。 45619 % しかも、一瞬だけ表示されていたと思ったものが全く表示されなくなってしまった。 45620 % と思ったらこれは勘違いだった。make できていなかっただけだった。 45621 45622 うーん。誰が表示を消しているのだろうか…。ble-edit/info からも調べてみる事にする。 45623 何と調べてみると、menu-filter の中の get-active-range の中で menu/clear が呼び出されている…。何故? 45624 45625 どうやら auto-complete で挿入されている内容がメニュー構築時に記録されて、 45626 その後で挿入が起こるとその内容が消えてしまった様に見える為に menu-filter 状態が解除されたと見なされている。 45627 今まで動いていたのは挿入が起こった場合には候補生成・メニュー構築を再実行していた為に、 45628 挿入後の内容で再度 menu-filter が初期化されるからである。 45629 現在ではメニューが残っている場合には、それを用いて menu-filter 状態を更新している為に、 45630 挿入で消えたものや吸収した文字列にずれが生じた事に対応できていない…。 45631 45632 a menu/show で記録する時に auto-complete で一時的に挿入されている物を削除する。 45633 この作戦は使えない。というのも auto-complete がなくても挿入時に吸収される場合もあるからである。 45634 というかそもそも auto-complete で一時的に挿入されている物が記録されてしまうのも謎である。 45635 complete を実行している間は auto_complete keymap から抜けているので、 45636 auto-complete によって挿入されている文字列は _ble_edit_str には残っていないのでは…。変だ。 45637 何れにしてもこの方法だと駄目なのでもっと良い方法を考える。なので気にしない。 45638 45639 b 挿入が起こった時には、挿入開始点はそのままにして、 45640 その後の状態を menu/show で記録するという様にすればよいのでは…。 45641 つまり、menu 項目を用いて補完して挿入された場合には、 45642 その場合専用の情報更新をすれば良い。 45643 45644 うーん。よく分からない記録する部分を弄ろうとしたら全く通過しない。 45645 しかも考えてみたら menu から拾った候補でない時にも同じ現象が起こっている。 45646 先ずは、普通の時に動作する様に修正しなければならない。 45647 記録しているのは beg=$COMP1 end=$COMP2 …ああ、これだ。最近書き換えた…。 45648 これは修正した。そうしたら以前のとおりに動く様になった。 45649 45650 しかし menu から拾った候補の場合には未だ問題が残っている。 45651 文字列を吸収した場合に対応できていない。 45652 →これは menu/show で、menu から候補を拾った時の特別な更新を追加して対応した。動いている。 45653 45654 * complete: menu-filter で曖昧になった時に complete で補完すると [#D0947] 45655 comp_type に a が含まれない事になって、挿入結果にごみが残ってしまう。 45656 と思って修正してみたが症状は変わらない…。うーん。 45657 実際に調べてみると COMP1 と COMP2 が正しく設定されていない。 45658 というか COMP2 が正しく設定されていないのである。 45659 COMP2 が filter 前の状態になっている…。 45660 45661 x fixed: これについては修正したが、今度はちゃんと補完できなくなった。 45662 実装を見てみると "既存部分を置換し、一意確定でない場合は挿入しない" という事になっている。 45663 その様にする理由は何だったろうか。文法構造を破壊してしまう可能性があるからだったろうか。 45664 どうも 41b8cbb の様である。調べると #D0897 である。 45665 #D0897 は既存の部分を置換する様にした一番最初の実装なので、大した意味はない様である。 45666 成る程。理由が分かった。既存の部分を置換してしまうと、 45667 共通部分が既存の部分の一部にしか一致していない場合に、 45668 既存部分の持っていた情報が失われてしまうという問題がある。 45669 45670 これに正しく対応する為には、共通部分が完全に曖昧一致する場合は、 45671 既存部分の置換を起こしても良い事にする。しかし、それでも不完全である。 45672 もっとちゃんと言うと "共通部分の評価結果が含む既存部分を吸収する形で挿入する" というのが正しい。 45673 45674 然し、もっとよく考えてみると曖昧一致の場合と、 45675 完全に置換する場合の二種類がある。 45676 完全に置換する場合には勝手に内容を書き換えてしまっては行けないので、 45677 今まで通りに一意確定の時以外には挿入を実行しないという事にする。 45678 曖昧一致の場合にはその様に置換する。 45679 しかし曖昧一致の種類に応じた処理が必要なのではないか…。 45680 45681 * ble-complete/candidates/determine-common-prefix の comp_type の部分を真面目に実装する必要がある。 45682 ble/widget/complete の部分も真面目に実装する必要がある? 45683 或いは determine-common-prefix でちゃんと実装すれば実は気にしなくても大丈夫? 45684 45685 取り敢えず実装する。determine-common-prefix において、eval する所までは良い。 45686 完全一致ではなくて部分一致の時はどの様に実装すれば良いのか。 45687 45688 1 例えば部分列 (m) で考える事にする。 45689 この時は $common* が m に一致すれば良い。 45690 つまり $common == *m* か或いは、 45691 $common == *${m::some} という事になる。 45692 うーん。2つ目の条件は…。common-suffix-prefix という関数があったのでそれを使う事にした。 45693 45694 2 部分列 (a) の時にはどうしたら良いだろうか。 45695 何文字目まで一致したのかという事を知らなければならない。 45696 正規表現を工夫する事を考えたが、よく考えたら正規表現にする意味がない。 45697 正規表現にするのは大量の候補を処理する時に高速だからである。 45698 しかし今回の場合は一回限りの判定なので正規表現を構築していたら却って遅い。 45699 自分で1文字ずつ処理するのが速い。 45700 45701 取り敢えず実装した。動いている。 45702 ble/widget/complete の部分では特に処理をする必要はなかった。 45703 45704 2019-03-02 45705 45706 * ble-sabbrev -m に於いて COMPREPLY で結果を戻す様にしているが [#D0946] 45707 この方法だと自由度に欠けるのではないか。 45708 それよりは yield を使って生成する等の方法を取った方が良いのかもしれない。 45709 或いは、自分で desc を追加する方法を提供するなど? 45710 45711 というかそもそも現在の補完の仕組みでは各項目に対する desc を設定する事ができない。 45712 desc を記録するフィールドがそもそも無いからである。 45713 なので、これに対応するのは、少なくとも、補完において各項目の desc を表示できる様にしてからである。 45714 desc の表示はどの様に実装したら良いのだろうか。特に候補の幅と desc の幅をどう決めるのかという事。 45715 desc を一緒に表示するという事になると候補の数は最初に確定してしまうので、 45716 その中で最長の候補の長さを候補の表示に割り当てて、残りの幅を desc の表示に割り当てる事にすれば良さそう。 45717 desc に関しては入り切らない部分は其処で切るという事にする。 45718 45719 * 取り敢えず COMPREPLY でも ble-complete/cand/yield でも 45720 どちらでも候補を生成する事ができる様にする事にした。 45721 45722 * 生成する事が可能になった。 45723 更に、.blerc に blerc/sabbrev-git-commit として実装してみたが頗る便利である。 45724 45725 * ble-sabbrev -m '\date'='ble/util/assign COMPREPLY "date +%F"' 45726 これは便利な感じがする。 45727 45728 * complete: description の表示に対応する [#D0945] 45729 45730 description を表示する時には各行に候補を表示する事にして、 45731 一番長い候補に合わせて候補の表示幅を決める。 45732 残りの部分を説明の表示に使う事にする。 45733 45734 対応する為には先ず説明の情報を格納する方法について考える必要がある。 45735 当初の考えでは source または action 毎に DATA に必要な情報を格納してもらって、 45736 必要になった時に説明を生成するというものだった。 45737 説明の生成には時間がかかるかもしれないので、できるだけ説明の生成を遅延させるという事。 45738 もし説明の生成に必要な情報が候補生成時にしか得られないのだとしたら、 45739 そのまま説明のデータを DATA に格納してしまっても良いのである。 45740 45741 DATA に必要な情報を格納するという方式にして置けば 45742 ble-complete/cand/yield をそのまま使う事ができる。 45743 action に対応した形式で必要な情報を DATA に格納する。 45744 45745 先ずは desc がある時の配置・描画のコードを書く事にする。 45746 はみ出る候補や説明については切る事にする。 45747 調べてみると .construct-text は初めからそうなる様に実装されていた。 45748 更に、.construct-text は改行やタブは ^J や ^I としてくれる。 45749 なので候補が変に切られたり表示が滅茶苦茶になったりという事はない筈。 45750 45751 cols 及び lines を弄る事によって幅を制限すれば良い。 45752 45753 取り敢えず実装してみた所、表示はできている気がする。 45754 もの凄く長い物が含まれている場合等でも大丈夫か確認する。 45755 45756 x fixed: 駄目である。と思ったら隔てる空白の分の x 座標移動を入れていなかった。入れた。 45757 45758 x fixed: しかしそれでも未だ何かずれている。うーん。put-atomic で文字を出力してしまっている気がする。 45759 それも put-simple で切れた後にそれが起こっている。 45760 行末または範囲外に行ったらその時点で処理を中断する必要があるのでは。 45761 45762 % また、丁度ぴったりの時にも put-atomic が起こらない様にする必要がある。 45763 % と思ったらちゃんと w による幅で収まるかどうかを判定している。 45764 % これは put-atomic の想定として "未だ範囲内にいる" と思っているのが行けない。 45765 % なので、これについては呼び出し元で処理する事にして put-atomic 側では何もしなくて良い。 45766 45767 これについても修正した。 45768 45769 x fixed: 後、丁度ぴったり末尾に収まった時に put-atomic が改行を出力してしまう気がする。 45770 put-simple の方も put-nl-if-eol というのを出力する様になっている。 45771 もしこれが発動してしまうと幅を計算するのに使う事ができなくなる。 45772 勝手に開業しない種類の construct-text が必要になるのではないか。 45773 これは construct-text の第二引数に opts でも受け取って処理することにすれば良いか。 45774 45775 自動改行が起こらないオプションという事にする。 45776 これについても慎重に考えてみたが恐らく問題は起こらないという判断。 45777 45778 x fixed: 改行などの特殊文字に色がついていない。 45779 これは .construct-text の呼び出し元で sgr1 sgr0 を用意しておく必要があった。対応した。 45780 45781 x fixed: 座標計算が誤っている。直した。 45782 45783 * done: また幾つかの action について get-desc を実装した。 45784 45785 * done: メニューの形式を最初にメニューを表示した時点の物に固定する様にした。 45786 45787 * vi_map N でコマンドが見つかりませんという表示が出る [#D0944] 45788 これは ble-edit/isearch/backward-search-history-blockwise に 45789 opts として progress をつけて呼び出しているのにも拘わらず、 45790 isearch_progress_callback を指定していないのが原因であった。 45791 ではそもそも何故 progress を付けたのだったか。 45792 そして、isearch_progress_callback は何故設定していないのか。 45793 既定値を使用する意図だったのかそもそも progress は表示しないつもりだったのか。 45794 実際に vi.sh を観察すると isearch_progress_callback は影も形もない。 45795 取り敢えず isearch で使っているのと同じ callback を用いる事にした。 45796 45797 2019-02-28 45798 45799 * bash: 何と色々試している内に変な事を発見してしまった [#D0943] 45800 45801 $ bash --norc 45802 $ shopt -s failglob 45803 $ a='\' 45804 $ echo $a'*' 45805 45806 これで failglob が発動する。\* に一致するファイルは存在しませんという話。 45807 試しに bash-3.0 -- 5.0 まで調べてみるが全て同じ動作だった。 45808 うーん。まあ、変数に入った物は全て "" で囲むというルールを徹底していれば問題は起こらない。 45809 45810 更に、これは決してファイルに一致しない様である。 45811 '\*' という名前のファイルにも一致しないし、'*' という名前のファイルにも一致しなかった。不思議だ。 45812 45813 単語中の "" で囲まなければならないパラメータ展開は、 45814 展開後の結果に以下を含む物の時。 45815 45816 1. (単語分割抑制) IFS に含まれる文字 45817 2. (パス名展開抑制) グロブ文字 *?[@! 45818 3. (パス名展開抑制) '\' 45819 これは a='\'; $a'*' 等に於いて * がパターンと見做されてしまう為。 45820 45821 * ble-sabbrev でコマンド・関数を実行する機能? [#D0942] 45822 この記事を見て思った。https://qiita.com/kazuooooo/items/92bf3146cafeb8fd8673 45823 例えば \branch として展開を実行すると git のブランチ名の中から選択できる、など。 45824 これは peco だとか fzf だとかを呼び出さなくても menu-complete を呼び出しても良い。 45825 45826 取り敢えず実装してみたが振る舞いが変である。 45827 45828 x resolved: 先ず始めにメニューの最初の項目を選択した時点で選択されている文字列が表示されていない。 45829 最初の enter で何が起こっているのか調べる必要がある。 45830 45831 ble-complete/menu-complete/enter の中の 45832 "ble-complete/menu-complete/select 0" という行が問題の行の筈である。 45833 中を辿る。(ble-edit/content/replace "$_ble_complete_menu_beg" "$_ble_edit_ind" "$value") 45834 という関数の呼び出しに関しては問題ない様である。ちゃんと 5-7 を最初の候補に置換している。 45835 という事は描画の問題なのだろうか…。或いはその後で _ble_edit_str が書き換えられてしまっている? 45836 45837 →分かった。magic-space では sabbrev/expand の直後に空白が挿入されるのだ。 45838 148 を返した時には空白挿入をキャンセルするという様に修正する必要がある。 45839 直した動く様になった。 45840 45841 x resolved: 更にメニューから選択をしてそれから確定すると元々在った文字列が削除されない。 45842 うーん。どうも yield した時点で追記されている気がする…。COMPV が空白のままなので、 45843 既存の内容が空白に相当すると勘違いされてそのまま挿入されているのである。 45844 45845 a これが起こらない様に action 等を弄る事にしようか。 45846 b 或いは COMPS も COMPV に対応して空白にしてしまえば良いという事なのか。 45847 c または先に key に相当する部分は削除してしまう事にするか。 45848 削除してしまうとキャンセルする事ができなくなる。 45849 というか COMPS= とした場合にもキャンセルする事ができなくなる。 45850 d 実装を観察していて思ったが COMPV を評価するのに失敗した時でも 45851 ble-complete/action/util/quote-insert で $CAND == ""* ならば、 45852 既存の内容を残したままの挿入になってしまっている。 45853 この部分を修正すれば良い。 45854 45855 結局 d で修正する事にした。これで挿入される文字列に関しては大丈夫になった。 45856 45857 x resolved: やはりいきなり menu-complete に入るのは微妙である。 45858 先ずは menu を表示しておいてそれから menu-filter に任せるというのが適切である。 45859 これは単純に enter しないだけで大丈夫だろうか。 45860 →メニューを表示するだけという事にした。 45861 45862 x ok: 絞り込みの際に候補がなくなったら曖昧一致させたい気がする。 45863 menu-filter ではどの様に処理していただろうか。 45864 うーん。実装を見ると曖昧一致が有効になる筈である。何故有効にならないのか。 45865 と思ったが、曖昧一致は曖昧一致でも先頭が一致していなければならないのだった。 45866 この辺りは変更しても良いのではないかという気がする。 45867 →これは独立した項目で処理する事にする。 45868 45869 - done: 最後に機能の名称は ble-sabbrev -c で良いのだろうか。 45870 ble-sabbrev -m 等の方が分かりやすいのではないだろうか。 45871 メニューを表示するという意味において。 45872 寧ろ -c は直接編集コマンドを実行するという機能を将来的に実装した方が良いかも。 45873 という訳で -m に変更する事にする。 45874 45875 2019-02-27 45876 45877 * syntax: 何と eval の引数として a=() の形式が許される様である [#D0941] 45878 eval a=(1) b=(2) c=(3) や eval declare a=(1 2 3) が動く。 45879 解析の方法を変えなければならないのではないか。 45880 或いは declare 等と同じ様に解析すれば良いのだろうか。 45881 しかしその場合には変数名の補完が起こらない様にする必要がある。 45882 45883 うーん core-syntax-ctx.def の ARGVX ARGVI ARGVR 辺りを複製して 45884 eval 専用の ARGEX ARGEI ARGER 的な物を導入するのが早いだろうか。 45885 45886 * ok: 補完はどの様に起こすのが良いのだろうか。 45887 これは通常のコマンドと同様に補完させるのが良い気がする。 45888 しかし、コマンドと同じ文脈にしてしまうと今度はコマンドとしての着色が発生して、 45889 コマンドが見つからない時にエラー着色になってしまう。 45890 コマンドが見つからない場合にはエラー着色ではなくて何も着色しない、 45891 というようにする必要がある。また、引数の着色はどの様にするのが良いだろうか。 45892 コマンドの抽出…うーん。 45893 45894 よく考えたら declare と同様に適当な着色のままで良い気がしてきた。 45895 取り敢えずは特別な着色は考えずに現状の着色で行く事にした。 45896 45897 * ok: 所で eval はキーワードではなくてコマンドである。 45898 通常のコマンドではあるが文法解釈を変えるというのは自然に実装できるだろうか。 45899 等と考えたが、改めて考えてみれば declare や typeset なども同様である。 45900 declare や typeset 等と同様に取り扱えば問題ない。 45901 そして declare や typeset に関してはやはり 'for' 等と同様の場所で処理していた。 45902 ここに eval を追加すれば良いのである。 45903 45904 取り敢えず対応した。動いている。 45905 45906 * complete: PROMPT_COMMAND に追記が在った時の対策 [#D0940] 45907 bash-it 等の場合には PROMPT_COMMAND に ';' で区切ってコマンドを追加してくる。 45908 また、別の枠組みで PROMPT_COMMAND を管理している事もある。 45909 その様な時には attach-from-PROMPT_COMMAND は呼び出されるけれども、 45910 PROMPT_COMMAND は別の文字列になっているという事が考えられる。 45911 45912 その様な時には attach-from-PROMPT_COMMAND の中から PROMPT_COMMAND を 45913 書き換えると後に設定された PROMPT_COMMAND が削除されてしまって問題である。 45914 従って、後で設定された PROMPT_COMMAND はそのままにして置いて、 45915 attach-from-PROMPT_COMMAND の処理を二回目以降はスキップする、 45916 などと言った処理が必要になる。その様に実装した。 45917 45918 * complete: C-x $ などで変数名候補が出ている状態で、 [#D0939] 45919 多少入力して menu-filter が働いて一意になったという時に 45920 TAB を押すと通常の補完が走って候補が消滅してしまう。 45921 menu に候補が表示されている時には TAB (complete) で、 45922 表示されている候補を使う様に修正するべきなのではないか。 45923 45924 実はこの振る舞いは今までにも気になっていた物である。 45925 一回、メニューが表示されている時にはメニューの内容で補完する様に変更してみる事にする。 45926 変更してみた。動いている。何か見落としがあるような気がしないでもないが暫く使ってみる。 45927 45928 x resolved: この状態で補完が起こると menu 項目が全てクリアされてしまうので、 45929 DEL をしても最後に補完で挿入した内容よりも前に戻る事ができない。 45930 これは、現在は menu から抽出した候補を用いているという情報を何処かに記録して、 45931 その場合には menu の情報の再設定は行わないという様に工夫する必要がある。 45932 45933 menu の情報の記録は何処で行われているのだったか。 45934 どうも menu-filter の場合には ble-complete/menu/show filter を呼び出している。 45935 filter を指定して呼び出す事により menu の情報が消滅するのを避けているのである。 45936 →これも適当にやったら動いた。 45937 45938 - ok: 然し、今までの補完だって続きを補完しようとしたら menu-filter 45939 で戻る為の情報は記録されないのではなかったか。 45940 と思ったが、今回の対応によってそのような場合でもちゃんと menu-filter 45941 で戻る事ができるようになったのではあるまいか…。 45942 うーん。やはりその様になっている気がする。 45943 45944 2019-02-26 45945 45946 * main: --attach=prompt (bashrc) で reload すると PS1 が消滅する [#D0938] 45947 うーん。PROMPT_COMMAND の評価をする時に PS1 を復元していないから? 45948 と思ったが復元はしている筈なのである。これは後で調べる。 45949 45950 改めて reload が起こる手順について確認する。 45951 うーん。source ble.sh するとその場で unload が実施される。 45952 この時点で PS1 などは復元されるのではないのかと思う。 45953 そして復元など一頻りした後に bashrc で PS1 が設定されて、 45954 その後に PROMPT_COMMAND が呼び出された時に PS1 が ble.sh 側に待避される。 45955 45956 この何処かの段階で PS1 が失われるという事になる。 45957 うーん。調べてみると ble-attach の瞬間までは問題ない様である。 45958 ble-attach すると PS1= になるが、これは期待している動作である。 45959 45960 →分かった。PROMPT_COMMAND が実行されているのは 45961 何と、ble.sh の枠組みの中なのであった。 45962 うーん。中にいる時には attach するとかしないとか。 45963 どの様にするのが良いだろうか。中で attach するが、 45964 PS1 等は弄らない様にするという動作にするのか…。 45965 45966 うーん。結局 ble-detach を実行する時にも、 45967 ble-detach/impl を exec:gexec/.end から呼び出して、 45968 その後で再描画をして終了するという事になっている。 45969 という事を考えると、一旦 detach を完全に実行してから、 45970 その後の prompt の表示の際に attach するという様にするべきなのではあるまいか。 45971 45972 うーん。駄目だ変な状態になる。そもそも detach された状態になっていない様な気が…。 45973 うーん。改めて調べてみると .check-detach 経由で detach した時には 45974 .check-detach が return 0 をして、それにより term/enter, bind/.tail 等の操作がスキップされる。 45975 unload の時にもその様に操作しなければならないのではないだろうか。。 45976 と思ったがその場で ble-attach するという場合には _ble_edit_detach_flag を設定すると都合が悪い。 45977 と思って ble-attach の実装を見てみると、ble-attach の実装では _ble_edit_detach_flag 45978 をちゃんとクリアする様になっていた。気にしなくて大丈夫そうだ。 45979 45980 [実装] 45981 45982 % % a _ble_attached で _ble_term_state == external で 45983 % % unload を実行するのは .check-detach 経由でという事にする。 45984 % % と思ったが ble-attach と ble-detach が相殺して結局何も起こらないという状況になってしまっては厄介だ。 45985 % % やはり unload はその場で実行しなければならないという事になる。 45986 % % unload が起こったという事だけ通知して .check-detach に return 0 させるという事にすれば良い。 45987 % 45988 % unload はするけれども detached を _ble_edit_detach_flag に設定する事にした。 45989 % しかしそれでも期待通りに動いていない。どういう事だろうか。 45990 % 調べてみるとそもそも .check-detach で _ble_edit_detach_flag の分岐に入っていない気がする。 45991 % 変数名を間違えているだろうか。と思ったら分かった。 45992 % ble.sh を初期化している時に _ble_edit_detach_flag= が設定されてしまうのである。 45993 % 45994 % さて、動く様にはなったがプロンプトが空文字列で更に、 45995 % 次にコマンドを実行する時まで PROMPT_COMMAND が呼び出されないという状況である。 45996 % うーん。つまりこの方針は使えないという事になる。別の方針を考える必要がある。 45997 45998 b 別の方法は PROMPT_COMMAND が内部で実行されているという事を検出して、 45999 その場合には PS1 の取り扱いを特別にするという物である。 46000 しかし、特別にしなければならないのはそれだけだろうか。 46001 46002 うーん。というか、そもそも実行中の関数を書き換えてしまった場合に 46003 一体どういう事が起こるのかというのも気になる事ではある。 46004 まあ、多分、ちゃんとやっているという事にして、 46005 これは実際に問題が発生した時に気にする事にすれば良い。 46006 46007 c 或いは --attach=prompt であっても、 46008 内部から reload した時にはその場で attach するという様にするべきか。 46009 うーん。一応 PROMPT_COMMAND 経由で実行するという事になっているのだから、 46010 特に問題がない限りは PROMPT_COMMAND 経由で実行した方が良い気がする。 46011 46012 d ble-edit/{adjust,restore}-PS1 46013 ble-attach の実装をよく見てみるとこの様な関数を経由して PS1 を待避している。 46014 もっと言うとちゃんと現在の状態が待避した状態かそうでないかを管理している。 46015 もしかするとこれを用いて PROMPT_COMMAND を呼び出せば解決する問題ではないのか。 46016 改めて考えてみる。 46017 46018 通常は adjust 状態にある。 46019 reload をユーザが呼び出すとどうなるかというと、 46020 restore 状態で呼び出す事になる。 46021 a この時 ble-attach が即座に行われれば、 46022 adjust 状態になり正しく PS1 が記録される。 46023 b もし --attach=prompt の場合だと、 46024 PS1 は restore 状態のまま描画ルーチンに入る。 46025 1 そこで restore-PS1 が呼び出されるが何も変化は行わず、 46026 2 次に PROMPT_COMMAND が呼ばれて中で ble-attach を実行した時に adjust 状態になる。 46027 3 次に adjust-PS1 が呼び出される時には何も変化がない。 46028 これでちゃんと動くはずである。 46029 46030 結局 d の方法で呆気なく動くようになった。 46031 46032 2019-02-25 46033 46034 * 2019-02-15 bash-4.4 で reload を実行すると \ が入力できなくなる [#D0937] 46035 というより ble-detach, ble-attach しただけでも入力できない。 46036 うーん。初回はうまく行っているのに2回目以降で失敗するというのが分からない。 46037 ble-attach を観察してみると ble-decode/attach ble-decode/bind から、 46038 /home/murase/.mwg/src/ble/out/cache.d/1000/ble-decode-bind.40419.UTF-8.bind を 46039 source していて、このファイルの中身は特に変な事はない。 46040 46041 エラーメッセージはコマンドのキーマップが存在しません、という事なので…。 46042 うーん。これは bash のソースを見ながら調べなければならないのだろうか。 46043 46044 * set -o vi をせずに emacs モードで実行しても同様になる。 46045 つまり編集モード固有の問題ではない。 46046 * ble-detach/impl; _ble_attached=; ble-attach でも再現する。 46047 * ble-decode/detach; ble-decode/attach でも再現する 46048 * ble-decode/unbind; ble-decode/bind では再現しない 46049 * ble-decode/unbind; source $_ble_base_run/$$.bind.save; ble-decode/bind でも再現しない。 46050 * どうも builtin eval -- "$(ble-decode-bind/.generate-source-to-unbind-default)" を実行すると駄目の様だ。 46051 eval しているスクリプトを覗いてみる。怪しい項目として以下の様な物が見つかる。 46052 46053 builtin bind -r '\\": ' 46054 builtin bind -r '\C-x\C-\\": ' 46055 builtin bind -r '\C-x\\": ' 46056 builtin bind -r '\C-\\": ' 46057 46058 そもそもこの様な物が現れる原因は何だろうか。 46059 うーん。generate-source-to-unbind-default を覗くと bind -X の結果の処理が怪しい。 46060 特に2回目の attach で問題になるという事からこれが原因である事は明らかである。 46061 46062 →うーん。あっさりと直ってしまった。結局 "..." を抜き出す部分のエスケープの取り扱いを誤った所為で、 46063 "..." の範囲の切り出しに失敗して、結果として変な bind -r が呼び出されていたのが悪かった。 46064 これにより変な keymap entry が構築されてよく分からない事になっていたのである。 46065 46066 * 2017-11-22 syntax: 実は予約語も alias にできてしまう… [#D0936] 46067 46068 $ alias end=fi 46069 $ if true; then if true; then echo; end end 46070 46071 現状ではエラーとして検出してしまう。 46072 更に以下の様なこともできる。 46073 46074 $ alias var=declare 46075 $ var arr=(echo 1 2 3) 46076 46077 うーん。指定の単語が alias だった時は、 46078 毎回 alias を resolve するのだろうか。 46079 然し、alias の展開結果が複数の単語を含む場合に至っては、 46080 完全に追跡する事は不可能である。 46081 従って、alias までは考慮に入れなくて良いのではという気がする。 46082 寧ろ、中途半端に対応するよりは全然対応しない方が良いかもしれない。 46083 46084 或いは単一の単語の時にだけ展開するという手もあるし、 46085 または最初の単語についてのみ alias の展開を実行するという手もある。 46086 46087 $ alias begin='{' 46088 $ for ((i=1;i<=2;i++)) { echo hello; } 46089 $ for ((i=1;i<=2;i++)) begin echo hello; } 46090 bash: 予期しないトークン `begin' 周辺に構文エラーがあります 46091 $ for ((i=1;i<=2;i++)); begin echo hello; } 46092 46093 for (()) の直後などの文脈では alias の展開は起こらない様だ。 46094 46095 * 2019-02-25 関数定義 function キーワードも alias にできるのか? 46096 46097 $ alias defun=function 46098 $ defun hello () { echo hello; } 46099 46100 関数の定義も alias にする事ができる。 46101 46102 * 2019-02-25 所で alias の展開を実行するコードは既にあったろうか。 46103 使っているとすれば ble/util/type 等の周りである。 46104 うーん。別に alias の展開を実行している訳ではないのである。 46105 alias だったら alias 色に着色するという事と、 46106 quote されていたら alias ではない type の評価を実行するという事。 46107 alias の中身が何であるかについては調べていない。 46108 では、実際に調べるとしたらどの様にすれば良いのだろうか。 46109 46110 alias name とすると alias name='...' と表示される。 46111 ' は '\'' に置換されて出力される。もしこの方法を使うのだとしたら、 46112 alias ...= の部分だけを別のものに置き換えて eval すれば良い。 46113 46114 type name とすると日本語で表示されてしまう。 46115 LANG=C type name とすると name is aliased to `...' と表示される。 46116 alias の文字列の中に ' が含まれている場合でもそのまま出力される。 46117 type --help によって使えそうなオプションがないか見たがなさそうである。 46118 46119 * 何と alias 名として hello:world だとか A+B だとか指定できる様だ。 46120 ; や \ 等の文字を含める事はできなかった。当然 = も含められない筈である。 46121 46122 * util: sleep coreutils check [#D0935] 46123 bash-3 以下で sleepenh もなく usleep もない時 /bin/sleep が使われるが、 46124 その sleep が整数しか対応していない時にはエラーが出てしまう事になる。 46125 適当に整数に調整してから呼び出す様にする必要がある。 46126 46127 結局これも #D0934 と一緒に実装する事にした。 46128 46129 * 2019-02-22 util: sleep で </dev/zero を使う可能性について [#D0934] 46130 Qiita についたコメントから。 46131 46132 Note: 遅延は他の方法と較べても最も良い。 46133 Note: /dev/zero から読み取っている間 CPU は 100% になる。 46134 Note: /dev/zero は POSIX にはない。存在を確認してから使うというので良い気がする。 46135 Note: zsh の場合には </dev/zero を実行するとメモリを大量に食らってクラッシュする。 46136 46137 とにかく cygwin の場合には現状では変な子プロセスが必要になっているので、 46138 read -t 0.001 </dev/zero の方式と sleep を組み合わせて使う様に変更したい。 46139 46140 実は bash 5.0 以上では遅延を計測する事によって 46141 更に高精度の sleep を作る事ができるのではないか。 46142 46143 うーん。やはり /dev/zero は CPU 100% になってしまうのが問題である。 46144 1秒以上の遅延がある場合に sleep を併用する事にしても、 46145 例えば bleopt idle_interval の既定の設定だとずっと CPU 100% になってしまう。 46146 →実際に試してみると task がない場合には idle.do 自体が終了するので、 46147 ずっと CPU 100% という事にはならない様に思われる。 46148 しかし、将来的に screen saver 等の仕組みを整えようと思うと、 46149 やはり CPU 100% になってしまうというのは良くない。 46150 やはり /dev/zero は使わない方針で実装するのか…。 46151 もし使うのだとしたらとても短い時間の遅延にだけ使うという事になるのだろうという気がする。 46152 46153 そしてその為には様々な sleep の種類について遅延を計測するという事が必要になる。 46154 遅延の計測に関しては init の時に実行する事にして、毎回計測しなくて済む様にしても良い。 46155 ble.sh でもアップデートするタイミングで再計測するという事にすれば良い。 46156 また、計測自体は idle の中で実行するということにすれば良い。 46157 最初の計測の時に使う idle は遅延なしを仮定した sleep を用いる事にすれば良い。 46158 46159 しかし、できるだけビジーウェイト (/dev/zero) を使わない方針にするとすると。 46160 他にどの様な短い遅延の sleep の方法が Cygwin で利用できるだろうか。 46161 うーん。udp は結構遅延が短いが余り長い時間接続していると udp の timeout が起こりそうで、 46162 長時間の sleep には使用できない。今の実装はそれに対応する為に複合型になっていると思われる。 46163 しかし、1秒以上の時間になるという事なのであれば、普通に sleep を呼び出しても問題ないのでは?? 46164 46165 集中力が切れている。何をするべきか決めてさっさと実装する事にする。 46166 或いは実装しない事に決定するか。実装しないという選択肢はない様な気がする。 46167 結局 sleep の性能を計測するより他はない。 46168 初回の sleep の実行の際に計測を実施するというので問題ないだろうか。 46169 しかし計測には結構時間がかかるので、初回の sleep というよりは、 46170 idle.do の中で実行するべきなのかもしれない。 46171 初期化前は遅延は 0 として計算する。 46172 46173 一度に全ての補正を実装するのではなくて、一つずつ実装する事にする。 46174 また、計算自体にかかる時間も考慮に入れるべきなのではあるまいか。 46175 46176 [実装] 46177 46178 * done: msleep として実装する案 46179 46180 うーん。まずはじめに sleep ではなくて msleep を実装するべきなのではないかという気がしてきた。 46181 実際に使用している箇所を調べてみると固定の値を用いているか、 46182 そうでなければ msec から sec への変換を実施している。 46183 どうせ呼び出し元で毎回 msec から sec へ変換するのであれば、 46184 msleep の側で変換をする様にした方が遅延などの補正も実行しやすい。 46185 46186 取り敢えず少なくとも msleep を実装する事にする。 46187 元から少数に対応している sleep を使用する際には、 46188 実はもしかすると msleep よりも sleep の方が都合が良いかもしれないが、 46189 結局遅延の補正を実施するのだとしたら msleep の方が良いのではないか。 46190 46191 * ok: 遅延自体の計算と小数への変換にかかる時間に関して。 46192 これは計測してみない事には分からない。 46193 これは cygwin で測ってみると 70usec 程度なので、 46194 msec オーダーの sleep の際には無視できる。 46195 _ble_measure_base=0 にしても 86usec 程度である。 46196 まあ delay は少なめに見積もるのが良い気がするので 46197 _ble_measure_base ありで良い気がする。 46198 46199 * sleep が coreutils なのかのチェックもあった方が良いのでは。 46200 coreutils でない場合には小数の sleep は切り上げにするしかないのだろうか。 46201 1s 未満の場合には切り上げで、それ以上の場合は切り捨てで良いだろう。 46202 46203 →これは別項目を立てる事にする。 46204 46205 何だか収集がつかなくなってきた気がする。 46206 何も考えずに実装すると言いつつ色々考えてしまっている。 46207 46208 * done: benchmark.sh を読み込む様に修正する必要がある。 46209 benchmark.sh は zsh でも動く様に設計してある。 46210 46211 * ok: Cygwin で複数の方法を組み合わせるとしたらどの方法が良いか。 46212 46213 | 遅延を修正する事ができるのだとしたら sleep を用いてしまって良いのではという気がする。 46214 | 流石に遅延が 1s に達する事は殆どないだろうという前提で。 46215 | 1s 以上については sleep を用いる事にして、 46216 | それより小さい物に関しては udp を用いる事にする。 46217 | 更に短いスケールでは /dev/zero を用いるのだ、 46218 | という事を考えては見たがよく考えてみると遅延を修正することができるのであれば、 46219 | /dev/zero に頼らなくても udp だけで事足りるのではあるまいか。 46220 | 46221 | 結局 /dev/zero を使う意義はやはり余りないだろうという事で、 46222 | 以下の /dev/zero を用いた実装は使わない事になった。 46223 | 46224 | if [[ $BASH_VERSION && -c /dev/zero ]]; then 46225 | function ble/util/sleep { 46226 | local sec=${1%%.*} msec=0 46227 | if [[ $1 == *.* ]]; then 46228 | msec=${1#*.}000; msec=${msec::3} 46229 | fi 46230 | local ext=0 46231 | if ((10#$msec)); then 46232 | builtin read -t "0.$msec" s < /dev/zero; ext=$? 46233 | fi 46234 | if ((sec)); then 46235 | ble/bin/sleep "$sec"; ext=$? 46236 | fi 46237 | return "$ext" 46238 | } 46239 | fi 46240 46241 →read -t 0.001 udp と /bin/sleep を組み合わせる事にした 46242 46243 * done: Cygwin で複数の方法を組み合わせる時に遅延に対する修正はどの様に行うのか 46244 46245 まず、かかる時間に応じてどの様に分けるのかの遅延 (delay0) が存在する。 46246 そして ble/bin/sleep を起動するのにかかる時間 (delay2)、 46247 それから read -t 0.001 udp を呼び出すのにかかる時間 (delay1) が存在する。 46248 46249 問題はどの長さの時に ble/bin/sleep を呼び出して、 46250 どの長さの時に呼び出さないのかという事である。 46251 ble/bin/sleep は必ず秒単位でしか呼び出さないという事にする。 46252 更に簡単の為に read -t 0.001 udp は必ず呼び出す事にする。 46253 46254 ble/bin/sleep を呼び出す事にすると、 46255 必ず遅延として delay0+delay1+delay2 はかかる事になる。 46256 従って、delay0+delay1+delay2 より短い時には ble/bin/sleep は使わない。 46257 また、delay0+delay1+1秒より短い時にも ble/bin/sleep を使う理由がよく分からない。 46258 うーん。必ず delay0+delay1 は支払うのだとしたらば、 46259 delay0+delay1 を引き算した上で、残りが1秒+delay1 以上あるならば ble/bin/sleep を呼び出して、 46260 それより短いのであれば全て read -t に押し付けるという方法で行くのが良さそうである。 46261 46262 その様に実装する事にする。特に delay0+delay1 はくっつけて考える事にする。 46263 取り敢えず実装して delay の計算部分も実装した。 46264 46265 [まとめ] 46266 46267 * sleep 自体にかかる時間を見積もって較正する機能を実装した 46268 * 較正のための計算が複雑になるので ble/util/msleep として実装することにした 46269 * 較正する機能を実装したので CPU 100% になる /dev/zero を敢えて使う必要はない 46270 * 従来の ble/util/sleep は便利かもしれないので ble/util/msleep を呼び出して実現する 46271 * Cygwin ではサブシェルのパイプではなく /bin/sleep で長時間 sleep を実装する事にした 46272 46273 2019-02-15 46274 46275 * bleopt: ble.sh reload 時に failglob でエラーが出る (reported by cmplstofB) [#D0933] 46276 https://github.com/akinomyoga/ble.sh/issues/22 46277 46278 ble-update の時にエラーメッセージが表示されるという話。再現した。 46279 普通に source ble.sh で reload した時にも再現する。 46280 どうも bleopt 関係である事は間違いない気がしているが、 46281 どのタイミングでエラーメッセージが現れているのかを調べる。 46282 46283 と思っていたら調べる前に分かってしまった。 46284 これは : ${hello:=...} のイディオムが火を吹いている。 46285 さて : "${hello:=...}" とする事もできるが…。 46286 そうすると ... の部分がクォートされている場合にはどうするか。 46287 46288 試しに "${hello:-$'\e[91mhello\e[m'}" というのを試してみた所、 46289 bash-3.0 で変な事になる。bash-3.1 以降では大丈夫。 46290 うーん。念の為 shopt -u extquote でも試してみる。 46291 →変化はない。extquote はこの場合には関係ないのだった。 46292 46293 うーん。 46294 46295 a bleopt に新しいオプションか指定方法を追加するか…。 46296 46297 * もしその様にするとしたらどの様な形式が良いだろうか。 46298 空文字列を上書きする場合と、未設定変数を上書きする場合の二種類がある事に注意する。 46299 46300 bleopt var::[default] 46301 bleopt var:[default] 46302 46303 微妙。そもそも分かりやすいのかという話。 46304 更に default 値に [] が含まれる可能性もあるので、 46305 括弧の様な対応があるような物は余り使わない方が良いのでは。 46306 46307 bleopt var:-default 46308 bleopt var-default 46309 bleopt var:~default 46310 bleopt var~default 46311 bleopt var:+default 46312 bleopt var+default 46313 bleopt var:?=default 46314 bleopt var?=default 46315 bleopt var:||=default 46316 bleopt var||=default 46317 bleopt var||=default 46318 bleopt var|=default 46319 46320 うーん。まあ、最後の物が一番良い様な気はする。 46321 然し、どちらが || でどちらが | なのかは分かりにくい。 46322 46323 bleopt var:|=default 46324 bleopt var|=default 46325 46326 こう? しかし、これだと普通の var:=value var=value 46327 の区別と混同しそうな気もする。 46328 46329 * 後もう一つの問題は bleopt 関数の定義より前に 46330 bleopt 変数の宣言を置く事ができないという事である。 46331 46332 →実は最初の bleopt 変数の宣言は util.sh の中であり、 46333 更に bleopt 関数は他の関数に一切依存していないので、 46334 util.sh の先頭に持ってきても問題ない。 46335 46336 b 或いはできるだけ : "${}" を使う事にするが、 46337 右辺に特別な値を入れたい時には何か別の方法を使うか、 46338 一次変数に規定値でも入れてから : "${}" を使う。 46339 46340 c 手動で [[ ${var+set} ]] || var=... とするか。 46341 46342 d bleopt とは独立に : ${var=value} を実行する関数を定義する? 46343 46344 うーん。こちらの方が良い気がしてきた。 46345 或いは、bleopt専用の変数定義関数を作成するか。 46346 46347 現状の候補は b または c である。うーん。 46348 d と a を折衷して bleopt を util.sh の先頭に持ってきて、 46349 bleopt/declare という関数を作成する事にした。 46350 46351 2019-02-13 46352 46353 * M-\ が現在より右側にしか作用していない [#D0932] 46354 46355 後、誰かが timeout か何かで止めている。screen? 46356 →screen を抜けて試してみたら問題なかったので screen が問題である。 46357 maptimeout は設定しているはずなので、それとは別の何かがあるのだろう。 46358 しかし不思議なのは emacs の中ではその様な事はないという事。 46359 やはり ble.sh の方で何か問題があるのだろうか…。後で確認する。 46360 46361 →と思って再度試してみた所特に問題はなくなった。 46362 もしかすると今回のバグの所為で何らかの条件で 46363 問題が発生したりしなかったりしたのかもしれない。 46364 取り敢えず気にしないことにする。 46365 46366 * syntax: ブレース展開は [[ $- == *B* ]] の時だけ有効にする [#D0931] 46367 これは実は ble-syntax:bash/check-brace-expansion の最初の条件を弄るだけなのでは。 46368 後で試して動作を確認してみる事にする。 46369 46370 →試しにその様に実装してみた所、エラー着色になってしまった。 46371 改めて実装を読んでみると実は {fd}> 等のリダイレクトの読み取りとの兼ね合いもあるので単純ではない。 46372 というか幸いにして brace expansion が効かない文脈という物もあって、 46373 そういう文脈に対する処理も既に書かれていたので [[ $- != *B* ]] の時も 46374 brace expansion が効かない文脈に含めればよいのだった。 46375 まあ、動いている。気にしなくて良さそう。 46376 46377 * set -e で ble.sh をロードしようとすると終了する。他 set -xv 対策 [#D0930] 46378 46379 しかし、対話シェルで set -e にしているとタイプミスしただけで終了してしまう。 46380 本当にそんな設定で良いのかというのは疑問であるが、一応 ble.sh がロードできる様にして置きたい。 46381 特に、set -e を解除する迄生き長らえれば問題ない。 46382 実際に試してみると ble/base/adjust-bash-options を呼び出す所までは到達している様子である。 46383 結局、ble/base/adjust-bash-options を多少いじっただけで動く様になってしまった。 46384 本当にこれで大丈夫なのか…。 46385 46386 [set -x について] 46387 46388 他にも確認しておくべきオプションはないだろうか。 46389 set -x は物凄く沢山のデータを出力する。これは封じるべきだろうか。 46390 例えば以前の cmplstofB さんの報告では set -x による出力が提供された。 46391 しかし、実のところ余り役には立たない感じだった様にも思う。まあ、これは封じる事にする。 46392 46393 * ok: 3>&2 大丈夫? 46394 46395 実装している途中で { } 3>&2 などを用いた。 46396 此処で何だかよく分からなくなった。bash はどうやってこれを処理しているのだろう。 46397 一つのプロセスの中で複数の fd の体系を保持するのは困難である。 46398 或いは、fd の体系は実は単に模倣しているだけで、 46399 他のプロセスに exec する直前にだけ調整しているという事だったりするのか。 46400 丁度環境変数の処理と同じ様に。 46401 46402 3>&2 としても外側で作った 3 が削除されない事を確認する為に実験する事にする。 46403 46404 $ exec 3>p.txt 46405 $ echo hello >&3 46406 $ { echo true world; } 3>&2 46407 $ echo world >&3 46408 46409 うーん。平気みたいだ。では中から見るとどういう事になっているのか。 46410 46411 $ { ls -la /proc/self/fd; } 3>&2 46412 lrwx------ 1 murase murase 64 2019-02-13 21:44:57 3 -> /dev/pts/6 46413 $ { ls -la /proc/self/fd; } 46414 l-wx------ 1 murase murase 64 2019-02-13 21:45:19 3 -> /home/murase/prog/ble/p.txt 46415 46416 他に変化はない…。つまり、何処か別の場所に fd を保存しているという訳でもない? 46417 もしかしてサブシェルになっているという事なのか…。 46418 46419 $ echo +$a 46420 + 46421 $ { a=12345; } 3>&1 46422 $ echo +$a 46423 +12345 46424 46425 否、ちゃんと同じシェルの中にいる。ではもしかして繋ぎ直したりしているのか? 46426 名前付きパイプで確かめてみる事にする。 46427 46428 % mkfifo p.pipe 46429 % sed 's/^/[/;s/$/]/' p.pipe 46430 46431 $ exec 3>p.pipe 46432 $ echo hello >&3 46433 $ echo world >&3 46434 $ { echo hello; } 3>&1 46435 hello 46436 $ echo running >&3 46437 $ exec 3>&- 46438 46439 ちゃんと期待通りに動作する。途中で接続が切れる等の事は起こっていない。 46440 途中で別プロセスを起動 { ls -la /proc/self/fd; } 3>&2 してみても問題はなかった。 46441 うーん。中でどうやっているのかは謎だが気にしなくても良いのかもしれない。 46442 46443 気にしない事にした。 46444 46445 * ok: 所で着色が間違っている事に気づいてしまった 46446 { echo; } 3>&1 とすると 3 が赤いままである。 46447 多分、これは始め 3 が単語であると認識されてエラー着色されて、 46448 その後で単語が削除された後に色が残ってしまっているという物である。 46449 以前の配列の場合と同じである。これは以前の配列の着色の問題の項目に追記する事にする。 46450 46451 [set -v について] 46452 46453 set -v に関しては起動してから -v とした時には特に問題は起こらないが、 46454 起動する時から -v を指定していた場合にはずっと出力がされる。 46455 46456 もしかして起動時に指定した -v は取り消す事ができないのだろうか。 46457 然し、実際に試してみた所、そんな事はないようである。 46458 更に、-v の時に定義した関数を呼び出すと verbose に出力されるのかと思いきや、 46459 そういう様子でもないらしい。一体何が起こっているのだろうか。 46460 もしかすると [[ -o verbose ]] では検出できないという事なのだろうか。 46461 →ちゃんと検出する事ができている。うーん。 46462 46463 うーん。検出できるできない関係なく変である。 46464 set +v と明示的に入力して実行しているのにその効果が現れない、という事なのだから。 46465 46466 source ble.sh の周りだけを set -v ... set +v で囲んだ場合でも変な事は起こらない。 46467 bash -v で起動するが set +v を source ble.sh の直前で実行した場合も大丈夫。 46468 set +v ... set -v で source.ble.sh を囲んだ場合は再現する。bash -v をしなくても再現した。 46469 実は prompt_command 及び bind -x の中での set -v はリセットされるという事なのか? 46470 prompt_command で attach しても bashrc の末尾で手動 attach しても再現する。 46471 と思ったら手動 attach の直前で set -v した場合には特に問題は起こらない様だ。 46472 46473 ? ok: つまり、プロンプトを表示する瞬間に set -v だと、 46474 それ以降はどんなに bind -x の中で set +v をしても解除されない、という事なのか。 46475 どうも bind -x の中で set +v をすると一時的に +v になるが、 46476 bind -x を抜けた時には既に set -v になってしまっている様子である…。 46477 というのも {adjust,restore}-bash-options の処理を追跡してみた所、 46478 以下の様な具合になっていたからである。 46479 46480 adjust: v->n 46481 restore: n->v 46482 adjust: v->n 46483 restore: v->v # ←最後に観測した時は n だった筈なのに勝手に v になっている 46484 adjust: v->n 46485 restore: v->v # ← 46486 adjust: v->n 46487 restore: v->v # ← 46488 adjust: v->n 46489 46490 他に ble.sh の中で set -v だとか set +v だとか set -o verbose だとか 46491 そういった物を触っている箇所はない。なので bash が勝手に状態を戻しているというより他はない。 46492 46493 ? ok: 更に言うと、bash の出力を抑制している筈なのに抑制できていないのは何故? 46494 何か特別の fd を使って出力しているという事なのだろうか…。 46495 或いは、表示する瞬間だけ内容が漏れているという事なのか。 46496 stdout.on,off はどのタイミングで行われるのだったか。 46497 実は、ble-decode/.hook の中の PROLOGUE EPILOGUE の中で on, off が行われるのだった。 46498 従って、ble.sh の機能が働いている間は殆ど stdout は on の状態になっている。 46499 46500 なので抑制しているのに色々と出力されているというのは特に普通の事である。 46501 46502 どのタイミングで set -v の状態が戻っているのか確認する為に、 46503 念の為 PROLOGUE と EPILOGUE で張って見る事にする。 46504 というか、張るべきなのは厳密には head と tail である。 46505 やはり、tail で +v だったとしても次の head の時には -v に戻っている…。 46506 これは何処で対策するべきだろうか。というか、ble-decode/.hook の先頭で set +v としても良い気がしてきた…。 46507 というのも ble-decode/.hook が呼び出される時点で adjust された状態の筈だから…。 46508 46509 取り敢えず ble-decode/.hook で set +v を実行してみる様にしてみたら問題は発生しなくなった。 46510 この振る舞いについて何処かに記録しておくべきだろうか。記録する事にした。記録した。 46511 46512 動作確認してみる。動いている。大丈夫。 46513 46514 * [整理] 2013-06-10 ble-bind 以下の同値なキーに対する処理? [#D0929] 46515 ref #M0012, #D0752 46516 46517 | + DEL を BS にマップする 46518 | + C-_ を C-BS にマップする 46519 | + C-m を RET にマップする 46520 | + C-i を TAB にマップする 46521 | + M-大文字 を M-S-小文字 にマップする? → これは CapsLock に依存するので止めておく 46522 | + DEL の bind している物を BS から bind する。 46523 | + C-_ の bind している物を C-BS から bind する。 46524 46525 これは #D0752 で再考された。以下のものはキーマップ上で交換可能であるように注意深く束縛された。 46526 しかし、一方で自動的に変換してどれかだけ束縛すれば良い様に実装することも考えて良いかもしれない。 46527 46528 - DEL C-? 46529 - BS C-h 46530 - NUL C-@ C-SP 46531 - RET C-m 46532 - TAB C-i 46533 - C-_ C-DEL C-BS 46534 46535 * [整理] 2017-11-29 syntax: http://lists.gnu.org/archive/html/bug-bash/2017-11/msg00002.html [#D0928] 46536 46537 "$(case *) ;; esac)" の問題が報告されて Chet が調べると言っている。 46538 もしかしてこれは将来的に修正されるのかもしれない。 46539 →2019-02-13 bash-5.0 で試してみたが全然直っていない。当面は直らないのだろう。 46540 46541 * [整理] 2017-11-29 syntax: function @() { ...; } [#D0927] 46542 https://stackoverflow.com/questions/43117707/bashs-strange-behavior-on-a-function-named/ 46543 http://lists.gnu.org/archive/html/bug-bash/2017-03/msg00220.html 46544 これで関数を定義しても関数は定義されない。 46545 46546 * [整理] 2018-03-18 アニメーション gif を作る [#D0926] 46547 ref #M0004 46548 46549 - 画面の幅や文字の大きさなどを調整しておく。 46550 46551 mintty を使って撮影することにした。 46552 文字の幅は 56 にする。文字の大きさは 14 ぐらいで良かろう。 46553 46554 うーん。本当はもっと文字を大きくして PS1 46555 も簡単なものにするべきかもしれない。 46556 というか '\s-\v\$ ' にするべきの気がして来た。 46557 そうすれば bash で動かしているという事が分かる。 46558 46559 - 現在のキー入力を表示する機能を搭載する? 46560 →これはやはり何らかのソフトウェアを使うのが現実的だろう。 46561 46562 - done: 黒背景の時の着色の調整を行う。 46563 コメント・disable の着色が暗い。 46564 算術式の色が暗い。 46565 46566 3 どの様な順で操作をするのかまとめておく。 46567 46568 元々の動画ではどの様にしていたかと言うと…。 46569 46570 - echo hello world 46571 - printf hello 46572 - [[ a == b ]] 46573 - echo "hello $(echo bash $(echo world))" 46574 - # history search 46575 - echo 'select, copy and paste' 46576 - echo insert mode 46577 - echo lib/core-complete.sh ble-decode.sh make_command.sh 46578 - echo histexpand 46579 - cat <<EOF 46580 this is the $(echo multiline mode). 46581 EOF 46582 46583 これにインストールの様子も加えると良いだろう。 46584 46585 - git clone git@github.com:akinomyoga/ble.sh.git 46586 cd !$:t:r 46587 make 46588 make install 46589 46590 然し、それとは別に現在出ているエラーを修正する必要がある。 46591 set -o vi した直後に出るのは何だろう? 46592 46593 * [整理] 2018-05-24 bash-5.0 alpha が告知された [#D0925] 46594 46595 気になる事を幾つか。 46596 46597 - EPOCHSECONDS, EPOCHREALTIME ... これは sleep に応用できる可能性がある。 46598 と思ったが何れも単位は秒の様である。 46599 と思って EPOCHSECONDS と EPOCHREALTIME の違いを調べてみた所、 46600 EPOCHREALTIME は小数で結果が返ってくるのだった。 46601 46602 - 今まで ++var++ という算術式が許されていた様だ。 46603 46604 - 複数行履歴がちゃんと記録されるようになるらしい。 46605 従って eval -- $'...' という workaround はしなくてもよくなるかもしれない。 46606 46607 →試してみたが何がどう変わったのかよく分からない。 46608 全然複数行履歴として記録されていない気がする。 46609 この情報は気にしない事にする。 46610 46611 - %q は未だバグが残っていた様だ。 46612 46613 - 自分の報告・修正した項目も含まれている: 46614 46615 1. q. t. oooo. xxxx. ggggg. 46616 一つ抜けている気がしたが、よく考えたらそれは 46617 4.4 以降に埋め込まれて 5.0 前に直されたバグだった。 46618 46619 - (4. a. vi-mode n, N) 正規表現ではなくてグロブパターンらしい。 46620 46621 - (4. d. C-v) 負の引数 -N を指定すると、次の N 文字をそのまま挿入するらしい。 46622 46623 * [整理] bash 4.0-4.4 で f() { declare -a x; declare -A x; }; f で segfault という報告がある [#D0924] 46624 46625 知らなかった。これは危険である。 46626 http://lists.gnu.org/archive/html/bug-bash/2019-02/msg00047.html 46627 46628 試してみると unset x; declare -A x とすれば大丈夫の様だ。 46629 declare -a A; f() { local -A A; }; f の場合も大丈夫の様だ。 46630 まあ、同じ関数内で配列として使っていた物を後になって連想配列にするという事も余りなかろう。 46631 46632 というより。こういう情報を ToDo にどんどん入れているが、 46633 これらは ToDo ではなくて Memo か情報か、そういった物である。 46634 これを機に整理したら良いのではないだろうか。 46635 46636 * 2017-02-27 PS1='$(echo "hello")' [#D0923] 46637 46638 現在の実装では " で囲んでも大丈夫な様に一頻りエスケープしてから 46639 builtin eval "ps1esc=\"$ps1esc\"" を実行している。 46640 しかし、この実装だと $() の中にある " も全てエスケープされてしまう。 46641 46642 これに対応するのは面倒である。 46643 正しく実装する為には $() の中と ${} の中を読み飛ばして無駄にエスケープしない様にする必要がある。 46644 それこそ構文解析をして $() や "" <() ${} の入れ子を追跡しなければならない。 46645 実は入れ子の追跡だけならば () と "" だけ追えば良いのではないか? 46646 しかし case esac があるとまた厄介になる…が、それに関してはシェル自体も対応していなかったりする。 46647 @() や +() 等に関しては必ずバランスする事が保証されているのでこれも一緒くたに追跡すれば良い。 46648 問題は quote されている () "" であるがそれらは… \? '...' `...` を飛ばすという対応で良いのではないか。 46649 と思ったが文脈によっては ' は quote にならなかったりする。文字列の中では quote にならないし、 46650 また $(('aa)) だとどうだろう。と思ったが、そもそもこれは算術式のエラーになる。 46651 実際に試してみた所、更にシェルの文法としてもエラーになる様子だ。つまり、切り出しはやはり '...' の組で行っている。 46652 46653 うーん。因みに Bash はコマンド置換の中の \w 等についてもちゃんと展開してくれる。 46654 46655 2017-11-12 改めて Bash の振る舞いについて調べる。 46656 46657 | 先ず \w が展開された結果として $(...) が現れても 46658 | それはコマンド置換の対象ではない。 46659 | 46660 | ~$ mkdir '$(echo "hello")' 46661 | ~$ cd !$ 46662 | $(echo "hello")$ 46663 | 46664 | この状態で PS1 を設定してみる。と、エラーになった。 46665 | $(echo "hello")$ PS1='$(echo \w)' 46666 | bash: command substitution: 行 41: 予期しないトークン `(' 周辺に構文エラーがあります 46667 | bash: command substitution: 行 41: `echo ~/t/\$(echo \"hello\"))' 46668 | bash: command substitution: 行 1: 予期しないトークン `(' 周辺に構文エラーがあります 46669 | bash: command substitution: 行 1: `echo ~/t/\$(echo \"hello\")' 46670 | 46671 | うーん。どうやら Bash の実装では \w 等を展開した結果に $" が含まれている場合は 46672 | エスケープ付きに一回置き換える様だ。 46673 | 因みに ~ もエスケープされないので \w にしていても上記の PS1 では /home/... になってしまう。 46674 | 46675 | /home/..../tmkdir '\\\\'; cd '\\\\' 46676 | /home/..../t/\\\\ 46677 | 46678 | どうやら、\ もちゃんとエスケープ付きに置換されている。 46679 | 因みに \w と違って \\ は単一の \ に置換されるようだ。 46680 | 従って、次の評価の時に数が半減してしまう。 46681 | 46682 | /home/....t/\\\\PS1='$(echo \\\\)\$ ' 46683 | \$ 46684 46685 恐らくこういう実装になっている。 46686 46687 1 最初に \w などの特別な指定を全て置換する。 46688 46689 この時置換結果に $"\` が含まれている場合にはエスケープする。 46690 これは丁度 "" 引用符の中でエスケープが必要なものに合致する。 46691 (! はエスケープの対象ではない。) 46692 46693 また \\ は \ になる。 46694 \" は \" のままの様だ。これは PS1='$(echo \\\"hello\\\") ' 46695 とするとプロンプトが \hello\ になる事で確かめられる。 46696 46697 2 次に文字列を評価する。コマンド置換やパラメータ展開を処理する。 46698 46699 それも恰も "" で囲まれた環境であるかの様に展開を処理する。 46700 しかし " は引用符の終わりという意味を失って単なる文字になる。 46701 この部分が一筋縄では行かない難しい点である。 46702 46703 " が引用符の終わりという意味を失いつつ、 46704 それでいてパラメータ展開やコマンド置換が有効な文脈は思い浮かばない。 46705 46706 | a そう言えばヒアドキュメントはどうだろう。 46707 | 46708 | o ヒアドキュメントは行末の空白は消えない。空白類はちゃんと保持される。 46709 | o 最後に改行は付加される。 46710 | x \" は \" のまま。これは問題である。 46711 | o \$ は $ になる。\\ は \ になる。 46712 | 46713 | うーん。しかし、厳密に bash と同じ振る舞いでなければならない訳ではない。 46714 | 例えば step 1 の段階で \" を " に縮め、 46715 | また置換結果の " をエスケープしないというのも可能である。 46716 | 46717 | この時 PS1='\\" ' の結果が Bash と異なることになるが仕方がない。 46718 | Bash は \" にし、更にその後の評価で " になる。 46719 | 一方で、此処で提案した実装では初めに \" になる所までは同じだが、その後で \" のままになる。 46720 | PS1='\\\" ' の場合はどうだろうか。Bash は \\" にし 更に \" になる。 46721 | 此処で提案した方法だと初めに \" になり次のステップでも \" に留まる。 46722 | この時は (中の処理は異なるが) 結果は一致して見える。 46723 | 46724 | % 更に言うと Bash の実装に従う必要も全然ないかもしれない。 46725 | % 例えば、\w 等の置換結果は当たり障りの無い 46726 | % 特殊 Unicode 文字 (私用領域など) に変換しておいて、 46727 | % 最後に代入するという手法も考えられる。 46728 | % この様にすれば変なディレクトリに入った時に Bash の文法とかち合うこともない。 46729 | % 但し、これだと例えば \w のパスを加工して表示するという様な処理が期待通りに動かない。 46730 | % 直観的でないのでやはりこの方法は避けた方が良い様に思われる。 46731 | 46732 | x そういう意味で言えば Bash の振る舞いはコマンド置換の中で \w を使う場合でも 46733 | 取り敢えず "" で囲んでおけば問題は起こらないので、PS1 を正しく設計すれば大丈夫である。 46734 | 一方で、此処で提案したような「" はエスケープしない」という実装だと、 46735 | 二重引用符を含むような名前のディレクトリにいる時、"\w" の様に二重引用符で囲んでも駄目、 46736 | ということになり問題が生じる。どんなディレクトリ名でも大丈夫にしようと思うと、 46737 | ヒアドキュメントを更に内部で使用しなければならず、非現実的である。 46738 | 46739 | そう考えるとやはりヒアドキュメントに頼らない方が良い気がする。 46740 | というかヒアドキュメント自体が悪いのではなくて、 46741 | ヒアドキュメントで \" が " にならないという仕様がたまたま今回の場合に合わないだけである。 46742 | 46743 | b 他に文脈はあるだろうか。ない気がする。 46744 | 46745 | c やはり正確に処理する為には地の文にある " だけを全て正確に \" に置き換えるしかない。 46746 | そしてその為には $() ${} "" の入れ子の勘定が必要である。\? '...' `...` はスキップする。 46747 | うーん。場合によっては ble-syntax を呼び出した方が賢明かもしれない。 46748 46749 2019-02-12 c の実装を試してみる事にする。 46750 現在の実装を確認する事にする。1. の振る舞いについては現時点で既にその様になっているようだ。 46751 地の文の \" は " になる。また " は " のままである。 46752 それ以外のコマンド置換等の中の \" はその文脈で評価される。 46753 46754 取り敢えず $(...) ${...} "..." の入れ子の対応は考える事にする。 46755 ${...} の中にある \" は " になる。これはそのまま放置で良い。 46756 ${...} の中にある生の " はエラーである。これはエスケープする。 46757 と思ったが、そういう事ではなかった。${...} の中では "..." が有効なのである。 46758 46759 取り敢えず指の動く儘に実装してみた。色々動かしてみたが結構いい感じに動いている様子だ。 46760 何より不完全な状態で終わっている時の補完がちゃんと動いていて良い。 46761 具体的な例で試してみる事にする。 46762 46763 o PS1='$(echo "hello")\$ ' 46764 o 以下の物は bash と全く同じプロンプト・エラーメッセージになったのでOK 46765 $ mkdir '$(echo "hello")' 46766 $ cd !$ 46767 $ PS1='$(echo \w)' 46768 $ cd ..; mkdir '\\\\'; cd '\\\\' 46769 o PS1='$(echo \)\$ ' → ')$ ' 46770 o PS1='$(echo \\)\$ ' → ')$ ' 46771 o PS1='$(echo \\\)\$ ' → '\$ ' 46772 o PS1='$(echo \\\\)\$ ' → '\$ ' 46773 o PS1='$(echo \\\\\)\$ ' → '\)$ ' 46774 o PS1='$(echo \\\\\\)\$ ' → '\)$ ' 46775 o PS1='$(echo \\\\\\\)\$ ' → '\\$ ' 46776 o PS1='$(echo \\\\\\\\)\$ ' → '\\$ ' 46777 o PS1='$(echo \\\"hello\\\") ' → '\hello\ ' 46778 o PS1='" ' → '" ' 46779 o PS1='\" ' → '" ' 46780 o PS1='\\" ' → '" ' 46781 o PS1='\\\" ' → '\" ' 46782 o PS1='\\\\" ' → '\" ' 46783 o PS1='\\\\\" ' → '\" ' 46784 o PS1='\\\\\\" ' → '\" ' 46785 o PS1='\\\\\\\" ' → '\\" ' 46786 46787 何も問題なく完璧に一致している。良かった。 46788 46789 2019-02-11 46790 46791 * bash-dev で complete が識別式の関数名しか受け付けなくなった [#D0922] 46792 これは本当に意図した動作なのだろうか。 46793 と思ったら普通にバグである。これは流石に気づいて直しているだろう…。 46794 →これは 439b8c2 で直った。 46795 46796 * 2018-07-19 bugbash: lib/readline/bind.c:397: [#D0921] 46797 46798 ref #D0699 46799 46800 | 以下の ic = UNMETA (ic); の行は if (map ...) の内側であるべきなのではないか。 46801 | 46802 | if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) 46803 | { 46804 | ic = UNMETA (ic); 46805 | if (map[ESC].type == ISKMAP) 46806 | { 46807 | prevmap = map; 46808 | map = FUNCTION_TO_KEYMAP (map, ESC); 46809 | } 46810 | } 46811 | 46812 | 然しこれは bind -m emacs-meta ... とした時の為にそうなっているとも考えられる。 46813 46814 これは別の直し方をした。報告した。 46815 https://lists.gnu.org/archive/html/bug-bash/2019-02/msg00036.html 46816 46817 * 2018-08-18 bugbash: #D0727 の報告をするか? [#D0920] 46818 一応 bash devel branch に対する修正の案も作ってある。 46819 46820 検索してみたら似たような提案が行われた形跡があるが Chet は無視した。 46821 http://lists.gnu.org/archive/html/bug-bash/2014-06/msg00053.html 46822 46823 報告した。 46824 https://lists.gnu.org/archive/html/bug-bash/2019-02/msg00035.html 46825 46826 * keymap: `C-x C-g` や `C-M-g` にも cancel, bell を設定する? [#D0919] 46827 実は C-g は keymap によって様々な物が bind されている。 46828 46829 2019-02-10 46830 46831 * builtin bind --help を実行すると標準出力が変になる… [#D0918] 46832 これは最近の実装が問題になっているのだろうか…。 46833 しかし builtin で問題になっているから別の問題かもしれない。 46834 ble-0.2 と ble-0.1 でも試してみる事にする。 46835 うーん。ble-0.1 でも再現する。 46836 46837 ble-detach してから ble-attach すると直る。 46838 46839 コマンドラインに内容が消されてしまうという事は、 46840 bleopt_internal_suppress_bash_output の関係だろう。 46841 と思って観察したが suppress_bash_output は最初のロード時に 46842 初期化するだけであって detach/attach に関係するとは思われない。 46843 46844 set -o emacs で editing mode を変更すると 46845 ble-decode/{detach,attach} が呼び出されるはずである。 46846 と思って確認してみた所、set -o emacs では治らない。 46847 明示的に ble-detach して ble-attach すると確かに直る。 46848 46849 また一度 ble-detach して ble-attach すると 46850 次に builtin bind --help しても問題は発生しない。 46851 stty の問題でもなさそうな気がする。 46852 念の為 stty -a を調べてみる事にする。 46853 discard が undef から ^O になっている。 46854 うーん。然し色々調べてみたがこれはやはり関係ない気がする。 46855 46856 うーん。_ble_attached=; ble-detach/impl; stty sane; ble-attach 46857 というのを一気に実行したとしても症状は治らない。 46858 ble-detach して ble-attach すると直るのは何故だろう。 46859 46860 また builtin bind --help が実装された bash-4.4 以降で起こる様になっている。 46861 46862 ble/util/assign hello 'builtin bind --help' としても症状は発生する。 46863 (builtin bind --help) の様にすると症状は発生しない。 46864 うーん。bash の状態がおかしくなっている? 46865 bind の実装はどうなっているだろうか。うーん。分からない。 46866 これを見ると他の組み込みコマンドの時にも同様の問題が発生しても良い様に見える。 46867 或いはこの仕組を使って --help を表示しているコマンドは少ないという事なのか。 46868 何れにしても最新版の bash-dev で試してみる事にする。 46869 46870 % bind.def の実装は変わっていない。complete.def と比べると、 46871 % bind の方は help を表示した後に未だ何か動作をしている。 46872 % 46873 % | begin_unwind_frame ("bind_builtin"); 46874 % | builtin_usage (); 46875 % | do { return_code = EX_USAGE; goto bind_exit; } while (0); 46876 % | bind_exit: 46877 % | if (saved_keymap) 46878 % | rl_set_keymap (saved_keymap); 46879 % | 46880 % | run_unwind_frame ("bind_builtin"); 46881 % | 46882 % | return (sh_chkwrite (return_code)); 46883 % 46884 % この時点で saved_keymap は NULL なので rl_set_keymap は実行されない。 46885 % run_unwind_frame は何をするのか…。どうも begin_unwind_frame と対になっている。 46886 % 46887 % 調べてみると sh_chkwrite を CASE_HELPOPT の後に呼び出しているのは bind のみである。 46888 % 他の builtin では直接に戻り値を返している。では sh_chkwrite とは何か。 46889 % 46890 % | // builtins/common.c 46891 % | int sh_chkwrite (int s) { 46892 % | QUIT; 46893 % | fflush (stdout); 46894 % | QUIT; 46895 % | if (ferror (stdout)) 46896 % | { 46897 % | sh_wrerror (); 46898 % | fpurge (stdout); 46899 % | clearerr (stdout); 46900 % | return (EXECUTION_FAILURE); 46901 % | } 46902 % | return (s); 46903 % | } 46904 % | 46905 % | // quit.h 46906 % | #define QUIT \ 46907 % | do { \ 46908 % | if (terminating_signal) termsig_handler (terminating_signal); \ 46909 % | if (interrupt_state) throw_to_top_level (); \ 46910 % | } while (0) 46911 % 46912 % うーん。これで振る舞いが変わる物とは思われない…。 46913 % 取り敢えず bash-dev で再現するかどうか試してから弄ってみる。 46914 % →bash-dev でも再現する。 46915 % sh_chkwrite を呼び出さない様にしても再現する。 46916 % 46917 % というか、以下の部分が極めて怪しい。 46918 % 成る程、unwind_protect とはそういう使い方をする物なのか…。 46919 % 46920 % | unwind_protect_var (rl_outstream); 46921 % | rl_outstream = stdout; 46922 % 46923 % うーん。調べてみたがそもそも CASE_HELPOPT を通過していない。。 46924 % うーん。実は --help は CASE_HELPOPT ではなかった…。 46925 % これは変な引数などを指定した時に出るエラーだったのである。 46926 % そして、その場合には特に変な現象には悩まされていない。 46927 46928 改めて。試してみると begin_unwind_frame を呼び出しているのに、 46929 run_unwind_frame が呼び出されない、という事になっている様子である。 46930 と思ったら…。CASE_HELPOPT はよく見たらラベルじゃなくて文だった…。 46931 46932 CASE_HELPOPT の中を覗いたら return (EX_USAGE) している。 46933 これが犯人である。直した。 46934 46935 * [自然解消] 2013-06-10 ble-bind キーボードマクロの定義に対応 [#D0917] 46936 ref #D0915 46937 46938 % 2017-09-10 ble-decode.sh: キーボードマクロのためには _ble_decode_key__hook と似ているが、 46939 % 46940 % 1. 一回限りではなくて恒久的に処理する 46941 % 2. 既定の処理も行う 46942 % 3. 複数の物を登録して管理できる 46943 % 46944 % ような仕組みを取り付ける必要がある (3. に関しては不要かもしれない)。 46945 % ↑2019-02-10 これは C-x ( .. C-x ) C-x e によるマクロの考察では? 46946 46947 * [自然解消] 2015-03-01 ble-edit: bind 模倣? [#D0916] 46948 ref #D0915 46949 46950 bind -x や bind の機能を実装し、 46951 更に bind 関数を上書きしてその動作を模倣するという事? 46952 46953 * 2015-02-23 bind の上書き [#D0915] 46954 46955 未だ時期尚早である。先ず、readline の function を一通り実装しなければならない (expand 系が大変)。 46956 また、bind にある様々なオプションとそれらを組み合わせて使った時の振る舞いについて整理しなければならない。 46957 46958 一応将来的な実装の為に、既存の bind の呼出に一通り builtin をつけた。 46959 46960 * 2018-08-19 bind '"":""' の形式の振る舞いについて調べた。 46961 特に後半の文字列がどのように解釈されるか。 46962 46963 - \C-? は解釈される。\C- の直後に日本語の文字があると1バイト目だけ切り取られて解釈される。 46964 - \C-@ があるとその場所でマクロが途切れる。 46965 - \ooo は解釈される。3文字まで。 46966 - \a \b \e \f \n \r \t \v は解釈される。 46967 \a はマクロ実行を途中で停止する効果がある。 46968 - \xhh は解釈される。2文字まで。1文字でも良い。 46969 直後に16進数がなくて \x 単体の場合には単に x となる。 46970 - \ の直後にそれ以外の文字が来る時は無視される。 46971 46972 - \C-\M- の両方が指定された場合には \e\C- という解釈になる。 46973 - \M-\C- とするとちゃんと Control-Meta 修飾になる。 46974 - \M-\C-\C- 等の様に3つ以上指定しようとしてもできない。 46975 \M-\C-\ までで一まとまりと解釈される。 46976 - \C-\M- の次に来るのは一文字だけである。 46977 其処に \a や \x43 等があっても先頭の \ だけ取られる。 46978 46979 恐らく前半も同様に解釈されるのだろう。 46980 此処で難しいのは前半をキーの列に解釈し直すべきなのか、 46981 或いは、ble-decode-char の処理で一つの長いキーと思って解釈するのかという事である。 46982 できれば前半をキーの列に解釈し直したい。 46983 ble-bind を使って普通に bind した物と競合すると良くないので。 46984 46985 * 2018-08-19 一つの bind '...' の中で複数の束縛を改行区切りで書けるか? 46986 試してみた所、書けない。 46987 どうも "([^\"]|\\.)*":".*" の形式で読み取っている様な気がする。 46988 と思ったが、そうでも無いようだ。謎の動作をする。 46989 46990 2019-02-10 これについて実装する必要がある。 46991 特にユーザの指定した -x には対応していきたい物である。 46992 46993 | うーん。取り敢えず前半部分と後半部分をどうやって分離するのか。 46994 | 試しに bind -x 'TAB: echo hello' とやるとエラーになる。 46995 | 最初の非空白文字が " ではありませんと言っている。 46996 | 一方で bind 'TAB:"echo helllo"' はちゃんと動く。 46997 | どうも bind と bind -x で解析器が異なる? 46998 | マニュアルによると他に Control-* とか Meta-* とか Rubout とかが存在している。 46999 | keyname の一覧は何処にあるのだろうか…。 47000 | うーん。結局 readline のソースコードに埋め込まれていた。 47001 | lib/readline/bind.c:2230: name_key_alist にある。 47002 | 47003 | { "DEL", 0x7f }, 47004 | { "ESC", '\033' }, 47005 | { "Escape", '\033' }, 47006 | { "LFD", '\n' }, 47007 | { "Newline", '\n' }, 47008 | { "RET", '\r' }, 47009 | { "Return", '\r' }, 47010 | { "Rubout", 0x7f }, 47011 | { "SPC", ' ' }, 47012 | { "Space", ' ' }, 47013 | { "Tab", 0x09 }, 47014 | 47015 | 大文字小文字は多分区別しないのだという気がする。 47016 | →bind 'rUBouT:"echo hello"' でも動いたので大文字小文字は関係ない。 47017 | 他に以下の物が埋め込まれている。 47018 | 47019 | const char * const _rl_possible_control_prefixes[] = { 47020 | "Control-", "C-", "CTRL-", (const char *)NULL 47021 | }; 47022 | const char * const _rl_possible_meta_prefixes[] = { 47023 | "Meta", "M-", (const char *)NULL 47024 | }; 47025 | 47026 | うーん。Meta の後に hyphen がないのは何故だろう…。 47027 | 47028 | bind '"\C-t""C-t":"echo world"' は前半の引用符の内容しか理解しない。 47029 | bind '"\C-t\"\"\C-t":"echo world"' はちゃんと全体の中身を理解している。 47030 | bind '"\C-t:\C-t":"echo world2"' はちゃんと二番目の : までを前半としている。 47031 | bind '"\C-t:\C-t"' とすると実は binding が削除される。 47032 47033 まとめると以下の様になる。 47034 - /^("([^\"]|\.)*"|[^:])*/ で前半を読み取る 47035 - 最初の非空白文字が " の時、keyseq と見做して "..." の中身を解釈する 47036 二個目以降の "..." は解釈されない。 47037 - それ以外の時、keyname に従って解釈する。 47038 複数の単語から成る時無視される。 47039 不明な keyname の場合には一文字目が使われる。 47040 - 続きに : が存在していれば key bindings を作る。 47041 もし続きに : がなければ key binding を削除する。 47042 と思いきやよく分からない状態になる。何もしないという動作に binding されている気がする。 47043 47044 bind '"\C-t" "\C-t": "echo hello"' としたら "\C-t": "\C-t\":" という事になった…。 47045 更に bind 'a "bull"' としたら "a": "bull" という事になった。 47046 つまり空白区切りという事なのである。 47047 47048 * bind のオプション解析に関して 47049 47050 何故か bind '"a": "bull1"' -m vi を実行すると m も v も動かなくなる。 47051 別のキーバインディングとして解釈されているのだろうか。 47052 bind '"a": "bull1"' m:self-insert v:self-insert とするとちゃんと動く様になる。 47053 bind '"a": "bull1"' -m:self-insert でも動く様になる。 47054 47055 つまり、一度 -m 以外のオプションが現れると、それ以降は binding と見なされるという事? 47056 -x spec を与えた後に spec2 を与えた場合には spec2 は -x なしで解釈される様だ。 47057 47058 bind -x '"a": echo hello' '"b": echo world' → -x a および b 47059 bind -x '"a": echo hello' -x '"b": echo world' → -x a および -x b 47060 bind '"a": echo hello' -x '"b": echo world' → a および -x および b 47061 47062 つまり、一度オプション以外の引数を読み込んだ場合は、それ以降は通常の引数と見なされるという事。 47063 この振る舞いは bash-5.0 以降でも同様なのだろうか…。 47064 何と bash-5.0 で確認してみた所、最後に指定した物しか有効になっていない…。 47065 bash-5.0$ bind -x '"a": echo hello' '"b": echo world' → -x a および b 47066 bash-5.0$ bind -x '"a": echo hello' -x '"b": echo world' → -x b のみ 47067 bash-5.0$ bind '"a": echo hello' -x '"b": echo world' → (a: 成功) および (-x: エラー) および (b: 成功) 47068 47069 うーん。どのバージョンの bind を基準にするべきだろうか。 47070 できるだけユーザの意図を汲む様な実装にする事にする。 47071 その様に考えれば、一度通常引数が現れたら引数は解釈しないという振る舞いは変だし、 47072 振る舞いが引数を指定する順序に欲しくない (上書きする場合を除いて) というのもある。 47073 47074 まとめる。 47075 47076 - bind の引数解析は最初に -* のオプションを解析して、 47077 - で始まらない引数が現れた時点でそれ以降を全て readline コマンドと見なす。 47078 - bash-5.0 では -x に関しては最後に指定したものだけが有効である。 47079 普通の readline コマンドとしてのバインディングは全て有効である。 47080 - bash-5.0 では二番目の単語が存在しない keyname:command に対してエラーが出る。 47081 - -m keymap はそれ以降の引数に対してのみ影響を与える。 47082 (bind -m vi -x '"a": echo hello' -m emacs -x '"b": echo world' で試した) 47083 47084 [実装] 47085 47086 * done: オプション解析の流れは実装した (.readarg) 47087 * done: keyseq:command の分離も実装した (.readarg/decompose-pair) 47088 * done: keyname の解釈も実装した (.readarg/parse-keyname) 47089 * done: keyseq の解釈 (.readarg/parse-keyseq) 47090 * done: 文字列からキー列への変換 (.readarg/decode-chars) 47091 47092 現在の ble-decode-char の状態を破壊せずに、 47093 ble-decode-char の機能を用いて実装したい。 47094 47095 以下の変数を被覆すればよいだろうか。 47096 _ble_decode_csi_mode=0 47097 _ble_decode_csi_args= 47098 _ble_decode_char2_seq= 47099 _ble_decode_char2_reach= 47100 _ble_decode_char2_modifier= 47101 _ble_decode_char2_modkcode= 47102 47103 以下の変数も一時的にクリアしておく事にする 47104 _ble_decode_char__hook 47105 47106 ble-decode-key 側の処理抑制も必要である。 47107 #%if debug_keylogger 47108 _ble_keylogger_enabled 47109 #%end 47110 _ble_decode_keylog_enabled 47111 47112 これを用いて設定を行う。 47113 _ble_decode_key__hook 47114 47115 * done: bind の実行 47116 47117 ? bind -x の右辺を "" で囲んだ時、\C-* 等の特殊なシーケンスは解釈されるのか。 47118 47119 $ bind -x '"\C-t": "od -t d1 <<< \C-t"' 47120 0000000 67 45 116 10 47121 47122 これは C-t という文字列である 47123 47124 $ bind -x '"\C-t": "echo \"hello\""' 47125 "hello" 47126 47127 echo "hello" ではなく echo \"hello\" が実行されている 47128 つまりただ単に周りの "" を削除しているだけに過ぎない。 47129 また、'"echo hello' の様に片方だけ quote されている場合にはエラーになった。 47130 更に '"echo hello\"' としえもエラーになる。 47131 '"echo ""hello"' とすると 'echo ' が実行される事になる。 47132 47133 ? ok: vi-move とは何かと思ってソースコードを見に行ったら vi, vi-command と等価だった。 47134 内部的な名前は vi_movement_keymap なのであった。 47135 47136 取り敢えず実装は完了した。ちゃんと動くかどうかについては調べていない。 47137 47138 [議論] 47139 47140 * done: ble-bind -P での出力内容 47141 .ble-decode-key は ble-bind -s として表示する。 47142 47143 * done: というか ble-bind -s に対応する。 47144 47145 * done: ble-bind -s を説明書に追記する。 47146 47147 * ok: 結局 keymap:*/define を autoload で定義する事にしたのである。 47148 今までの色々の処理を整理する事は可能だろうか。 47149 ただ、自分で新しい基底 keymap を定義する人が居た場合に備えて 47150 残しておいても良いのかもしれない。 47151 47152 うーん。考えるのが面倒なので今後問題になった時に処理するという事で良い。 47153 47154 * done: bind -r に対応していない 47155 対応した。 47156 47157 * reject: \a でマクロを止める機能? 47158 47159 \a というよりは bell である。 47160 しかし、その他の様々な機能との兼ね合いもあるので。 47161 decode.sh 側で一律に停止する様な仕組みにはし辛いのではないか。 47162 うーん。考えるのが面倒なのでこの機能は取り敢えず実装しない事にする。 47163 47164 * done: ble/builtin/* 47165 47166 モジュールの名前の下に直接組み込みコマンドの名前を置くと分かりにくい。 47167 例えば ble-edit/read というのは ble/edit における何らかの read とも見える。 47168 もっと分かりやすいように組込コマンドを上書きする意図のコマンドは、 47169 ble/builtin/* 以下に定義する事にした。 47170 47171 既に存在していた上書きする関数は read と exit のみであった。修正した。 47172 47173 * 対応表を実装する必要がある 47174 これは keymap 毎に解決する必要があるのではないだろうか。 47175 疑問点は vi モードの readline 関数をどの様に emacs に翻訳するのかという事。 47176 うーん。そのまま束縛すると何か変な事が起こらないだろうか…。 47177 また、vi.sh に定義されている widget を参照できるのかという問題もある。 47178 47179 その様に考えると適切でない readline 関数は reject するというので良い気がする。 47180 47181 うーん。テキストファイルに対応表を書く? 47182 取り敢えず emacs モードで対応した。 47183 vi_imap 及び vi_nmap に関しては後で対応する事にする。 47184 47185 [動作テスト] 47186 47187 * ok: ble-bind -s 及び対応する ble-bind -P は確認した。 47188 * ok: bind '"A": "echo hello"' は確認した。 47189 * fixed: bind -x '"A": "echo hello"' を実行したら変なエラーが出た。 47190 何故か readline function を探している…。 47191 引数の解析部分に誤りがあった。直した。 47192 * fixed: bind -x でプロンプトを消してそれからまた再表示するべきなのでは。 47193 bash の振る舞いに準じた動きをするべきである。 47194 現在はプロンプトを消す事もしないし、再表示もしない。 47195 確認してみる事にする。 47196 47197 bind -c の方は .insert-newline を用いて消している。 47198 真似して .hide-current-line を作って見た。 47199 それを使って一時的に消してみる。 47200 47201 2019-02-09 47202 47203 * bash-it でまた誰かが書き込んでいる [#D0914] 47204 https://github.com/Bash-it/bash-it/issues/894 47205 47206 やはり需要があるという事なのだろう。 47207 47208 - ble-0.3 を出す事にする。 47209 これまでの変更を Release 時にまとめる事にする? 47210 然し、長大になるし時間が掛かるし誰が読むわけでもなさそうなので、 47211 今回は見送る事にする。何れにしてもこの memo.txt には残っている訳だから。 47212 或いは、そのまま日本語で出してしまっても良いのではないだろうか。 47213 47214 ble-0.2 changes 47215 - vi (xmap `aw`/`iw`): Extend backward to include the current entire word 47216 - util (`ble/util/openat`): Add workaround a Bash 3.2 bug that causes problems with <kbd>C-d</kbd> in nested shells 47217 - edit (`ble/textarea#render`): Fix a bug of wrong scroll/cursor position after entire redraw 47218 - main: Fix a `"$_ble_base"` determination bug on `source ble.sh` for local ble.sh 47219 - global: Fix a leak variable 47220 47221 ble-0.1 changes 47222 - util (`ble/util/openat`): Add workaround a Bash 3.2 bug that causes problems with <kbd>C-d</kbd> in nested shells 47223 - main: Fix a `"$_ble_base"` determination bug on `source ble.sh` for local ble.sh 47224 47225 取り敢えず bump して archive を作る。ダウンロードする。 47226 というか ble-0.3 についても作成してダウンロードする。 47227 ble-0.1 release を更新する。タグを push しなければならない。 47228 47229 - bash-it をダウンロードしてどうなっているか確認する。 47230 47231 ダウンロードしてみたら 40MB もある。重い。 47232 そんなに沢山のデータがあるという事があるのだろうか…。 47233 うーん。working tree は軽い。履歴に変な物が入っている? 47234 47235 install.sh の中を覗いたが複雑なので読む気がしない。 47236 試しに実行してみる事にしようか…。実行してみた。 47237 現在の bashrc の末尾に追加するというのにしてみた。 47238 本当に末尾に追加するだけの様である。 47239 ちゃんとシンボリックリンクになっている事を認識して、 47240 中身を .bashrc.bak として保存して、 47241 更にシンボリックリンクの示す先を書き換えてくれた。 47242 47243 末尾に追加された内容は基本的に以下に等価である。 47244 というか、これらは本当に "export" する必要があるのだろうか…。 47245 47246 if [[ $- == *i* ]]; then 47247 export BASH_IT="/home/murase/prog/ext/github/bash-it" 47248 export BASH_IT_THEME='bobby' 47249 export GIT_HOSTING='git@github.com:akinomyoga/bash-it.git' 47250 unset MAILCHECK # Don't check mail when opening terminal. 47251 export IRC_CLIENT='irssi' 47252 export TODO="t" # todo.txt-cli 47253 export SCM_CHECK=true 47254 #export SHORT_HOSTNAME=$(hostname -s) 47255 #export SHORT_USER=${USER:0:8} 47256 #export SHORT_TERM_LINE=true 47257 #export VCPROMPT_EXECUTABLE=~/.vcprompt/bin/vcprompt 47258 # export BASH_IT_AUTOMATIC_RELOAD_AFTER_CONFIG_CHANGE=1 47259 # export BASH_IT_RELOAD_LEGACY=1 47260 source "$BASH_IT"/bash_it.sh 47261 fi 47262 47263 見てみると勝手にプロンプトを書き換えて screen に何か表示する等、 47264 色々と勝手な設定を行ってくる様である。 47265 自分で色々設定している人に取ってみれば結構厄介であろう。 47266 47267 取り敢えず試しに実行してみることにする。遅い。滅茶苦茶遅い…。 47268 ble.sh の機能とかちあって居るのかもしれないと思って、 47269 ble.sh を attach せずに使ってみたがやはり遅い。 47270 また ble.sh を使っていてもちゃんとプロンプトは表示されている様子だ。 47271 うーん。やはり信じられない遅さだ…。 47272 47273 更に、green だとか purple だとか reset_color だとか、 47274 普通の変数名を思い切り汚染している…。調べてみると 47275 それでも PS1 で使うものだけしか汚染していない様だ。 47276 無節操に汚染しているという訳でもない。 47277 47278 まあ、取り敢えず動くのだという事は分かったのでOK。 47279 47280 * ble.sh を bash-it に組み込むとしたらどの様になるだろうか。 47281 或いは bash-it は alias しか許さないのだろうか…。 47282 47283 うーん。bash_it.sh の中を覗くと enabled aliases 等は 47284 割と最初の方で source されている。 47285 theme 等の初期化はそれよりも後にある。 47286 PS1 が設定されるのは恐らく theme の中なのでこれでは駄目だ。 47287 もし ble.sh と組み合わせるのだとしたらば、 47288 bash_it.sh の中を弄らなければならない。 47289 47290 或いは、ble.sh の側でプラグインマネージャ的機能を実装して、 47291 bash_it.sh の中で実行している内容を非同期に実行する様にもできるかもしれない。 47292 何れにしても bash-it に普通に Pull request として 47293 ble.sh の機能を提供するのは難しそうである。書き換えが必要である。 47294 47295 * 因みに bash-it のロード時間は 0.744s である。 47296 ble.sh のロード時間は 0.218s で、attach には 0.437s かかる。 47297 bash-it よりは軽いが、そんなに軽いとも言い難い。 47298 環境によっては結構時間が掛かるのではないかという気がする。 47299 まあ初期化時間に関してはどうしようもない。 47300 47301 - 説明書の英語版を作るべきだろうか。それは後回しで良い。 47302 別項目として立てる事にした。 47303 47304 * manual: 以下の関数についても説明書に記述して --help に対応しても良いかもしれない [#D0913] 47305 - done: [public] ble-import, ble-assert, ble-autoload, ble-stackdump 1209ac6 47306 - renamed: [private] ble-color-ansi2g 47307 - renamed: [private] ble-color-face2{g,sgr} 47308 - renamed: [private] ble-color-g2sgr 47309 - renamed: [private] ble-color-gspec2{g,sgr} 47310 - renamed: [private] ble-color-iface2{g,sgr} 47311 - renamed: [private] ble-color-sgrspec2g 47312 - reject: [private] ble-decode-{byte,char,key} 47313 - reject: [private] ble-decode-{kbd,unkbd} 47314 47315 オプション --help の対応は果てしなく面倒くさい。 47316 というか引数の解析が必要なかった物全てに引数の解析を実装しなければならないのが駄目。 47317 というより、その為に archive/getopt.sh があったのではなかったか。 47318 そして archive/getopt.sh は大変に重かったという事と 47319 使い方が分かりにくかったという事で archive されたのだった。 47320 47321 うーん。引数の解析を実施すると速度が低下するので、 47322 特に ble-assert や ble-stackdump 等では実行したくない。 47323 結局、引数の解析を行わない内部用の ble/util/{import,assert,autoload,stackdump} と、 47324 ユーザに公開する --help 付きの ble-{import,assert,autoload,stackdump} を提供する事にした。 47325 47326 ble-color-*2* に関しては、そもそも公開する理由がない。改名する事にする。 47327 以下の様なスクリプトを書いて一括で変換した。 47328 47329 | #!/bin/bash 47330 | 47331 | function refactor-color-functions { 47332 | local funcs slash fun 47333 | funcs=( 47334 | ble-color-ansi2g 47335 | ble-color-face2{g,sgr} 47336 | ble-color-g2sgr 47337 | ble-color-gspec2{g,sgr} 47338 | ble-color-iface2{g,sgr} 47339 | ble-color-sgrspec2g) 47340 | slash=/ 47341 | for fun in "${funcs[@]}"; do 47342 | refact -b "$fun" "${fun//-/$slash}" 47343 | done 47344 | } 47345 | 47346 | refactor-color-functions 47347 47348 序にその他の ble-color/* 関数も改名する。 47349 47350 | #!/bin/bash 47351 | 47352 | function refactor-color-functions { 47353 | local funcs slash fun 47354 | funcs=( 47355 | ble-color/.name2color 47356 | ble-color/.color2sgr-impl 47357 | ble-color/.color2sgrfg 47358 | ble-color/.color2sgrbg) 47359 | slash=/ 47360 | for fun in "${funcs[@]}"; do 47361 | refact -b "$fun" "ble/color/${fun#ble-color/}" 47362 | done 47363 | } 47364 | 47365 | refactor-color-functions 47366 47367 ble-decode-byte に関しては誰も参照していない。 47368 ble-decode-key に関しては様々な所から内部使用が見られる。 47369 ble-decode-char に関しても微妙に内部使用が見られる。 47370 これらの関数名をどうするかは微妙である。 47371 元々 "decode byte,key,char" という意味なので、 47372 もし真面目に変えるとしたら ble/decode/decode-{byte,key,char} になる。 47373 然し長いので気になる。一方で ble/decode/char というのも何か変な気がする。 47374 或いは、現状のままで --help に対応しないという方向性も考えられる。 47375 というか何故 --help に対応しなければならないのか…。 47376 47377 ble-decode-kbd や ble-decode-unkbd も似たような物である。 47378 面倒になったのでこれらの関数については、 47379 これまで通り内部の関数として、但し関数名は今の儘で変えないという事にする。 47380 47381 * ble-sabbrev: 定義の表示において key に含まれる特殊文字がそのまま出力される [#D0912] 47382 これは ble-complete/sabbrev/list の定義を見直した。 47383 47384 2019-02-08 47385 47386 * global: ユーザ関数に --help を実装する (suggested by cmplstofB) [#D0911] 47387 47388 正直面倒くさい。沢山ある割に大した複雑な使用方法も存在しない。 47389 ble-bind がほぼ唯一の指定が面倒な関数である。 47390 他に ble-color-setface 辺りは説明を実装しても良さそう。 47391 取り敢えず適当に説明を追加した。 47392 47393 - ble-bind 対応済み 47394 - ble-update 47395 - ble-sabbrev 47396 - ble-attach, ble-detach 47397 - ble-color-show, ble-color-defface, ble-color-setface 47398 47399 * BUG main: /bin/sh が dash/ash の環境で ble-update が動作しない (reported by cmplstofB) [#D0910] 47400 _ble_base_repository='...' を生成するコマンドが bash の機能に依存していたのが原因であった。 47401 パラメータ展開の ${var//before/after} は POSIX には規定されていない。 47402 結局 bash を明示的に呼び出す事にした。 47403 47404 * main: support BLE_VERSION and BLE_VERSINFO (suggested by cmplstofB) [#D0909] 47405 変数名は最近は全て _ble_* に統一してきたが素直に BLE_* を使う事にした。 47406 今後は BLE_* はユーザに公開する変数に使う事にする。 47407 core-syntax.sh で使っている BLE_ATTR_* 及び BLE_CTX_* は後で改名する → 改名した 1fbcd8b 47408 47409 2019-02-07 47410 47411 * BUG complete: チルダ展開における補完で大量のエラーメッセージが出る (reported by cmplstofB) [#D0908] 47412 47413 以下のエラーメッセージが出る。単に action:tilde の実装がないだけだった。直した。 47414 -bash: ble-complete/action:tilde/initialize: そのようなファイルやディレクトリはありません 47415 47416 * 2018-08-28 complete: bash-completion の幾つかの関数を上書きもしくは乗っ取り? [#D0907] 47417 [棄却: ただし、ble.sh 側で bash-completion に習って tilde 展開の補完に対応] 47418 47419 bash-completion の _minimal などは ble 側で乗っ取っても良い様に思う。 47420 より良いサポートをする事ができるはずなので。 47421 例えば --prefix=... などに於いて。 47422 実は単にキャンセルすれば ble の既定の filedir 及び =... :... が動く。 47423 47424 →と思ったが --prefix=... に関しては COMP_WORDBREAKS に対応した今、 47425 実は余り気にしなくても自動的に対応される…。 47426 その他に乗っ取って利点などはあるだろうか…。 47427 もし利点があるようだったら実装するというので良い気がする。 47428 47429 * 調べると bash-completion _filedir はチルダ展開にも対応している。 47430 bash-completion の方が実は上なのではないか…。 47431 →ble.sh の source:file, source:dir でも対応した 47432 47433 _tilde: COMPV =~ ^~[^/]+$ ならばユーザ名を生成 47434 compgen -P '~' -u -- "${COMPV#\~}" 47435 47436 _filedir 47437 先ず _tilde を試みる or 47438 第一引数が -d ならディレクトリ名を生成 or 47439 第一引数がそれ以外なら、それを拡張子と解釈してファイル名を生成 or 47440 ファイル名を生成 47441 47442 →取り敢えず tilde には対応した。 47443 47444 [=:] に関しては完全には対応していないが、 47445 /C:foo --opt=foo opt=foo 等の形式には対応している。 47446 一方で opt=foo:bar の形式には対応していない。 47447 まあ、面倒だし、本当にそういう機会があるのかも分からないので取り敢えず放置する。 47448 もし対応するのだとしたら完全に [=:] で単語を分割して対応する方が良い。 47449 47450 よく考えたら。クォートされている場合には発動してはならないのでは。。 47451 と思ったが COMPS でパターンマッチングしているのでクォートされている事はない筈。OK 47452 47453 うーん色々考えたが。現状で _minimal に問題点があるという訳でもないので、 47454 取り敢えず乗っ取るのはわざわざする程の事でもないという事で棄却する。 47455 47456 2019-02-05 47457 47458 * 改めて leak variables のチェックを行う [#D0906] 47459 ref #M0002 47460 何処かで len, ret, flags という変数が漏れている。 47461 47462 - fixed: ble-syntax:bash/ctx-heredoc-word/remove-quotes rex 47463 - fixed: ble-bind flags 47464 - fixed: ble-complete/auto-complete/.search-history-light len 47465 - fixed: ble-complete/menu/show info_data menu_items 47466 47467 | ret は手強い。調べてみると ble-attach で既に出ている。 47468 | 更に遡ると ble-edit/bind/.tail で出ている。 47469 | →ble-edit/info/reveal 47470 | →ble-edit/info/.render-content 47471 | →ble/canvas/panel#reallocate-height.draw 47472 | →ble/canvas/panel/layout/.determine-heights 47473 47474 - fixed: ble/canvas/panel/layout/.determine-heights ret 47475 47476 * 2018-04-12 [棄却] ble-bind -xf で cd を実行することについて [#D0905] 47477 47478 プロンプトに現在のディレクトリを表示している場合、 47479 cd で移動した後にプロンプトを再計算したい。 47480 その時は ble-bind -xf 'C-@' 'cd ..; _ble_edit_prompt=; ble/textarea#invalidate' 等のようにすれば良い。 47481 しかし面倒なので ble-edit/prompt#invalidate の様なものを用意しても良いのではないかという気がする。 47482 同時に ble-edit/prompt/* 系統の関数名についても考え直したい。 47483 - というより単に ble/edit/prompt/* で良いのかもしれないが。 47484 - 或いは ble/textarea/prompt/* の方が良いかもしれない。 47485 →と思ったが確認してみると疎結合なのでやはり textarea の下には置かない。 47486 - 或いは ble/prompt/* という可能性もある。 47487 然し、そうすると ble-edit.sh の中に沢山の名前空間が出来て始末が悪い。 47488 47489 現状では ble-edit.sh の中にあるのは以下の通り。 47490 他に ble-decode 及び ble-bind に対する設定関数がある。 47491 47492 - ble-edit 47493 - ble/textarea 47494 - ble/util/c2w 系統 47495 - ble/widget 47496 47497 この現状を考えると ble/edit/prompt が妥当であろうという気がする。 47498 或いは prompt 計算自体を ble-form.sh に移動して、 47499 ble/form/prompt にしても良いかもしれない。 47500 しかし、prompt は form/control というよりは 47501 寧ろ graphics 的な実装方法なのでやはり ble-form.sh に入れるのも微妙か。 47502 少なくとも現状では textarea に付属して ble-edit にあった方が良い。 47503 47504 よく考えたら ble-bind -cf で実行すれば良いだけなのでは…。 47505 47506 * bash-5.0 の localvar_unset [#D0904] 47507 localvar_unset が on の時には upvar などで使っている unlocal 機能が使えない。 47508 対策をしなければならない。 47509 47510 * 2018-09-13 progcomp: scp の補完の動作が変である [#D0903] 47511 47512 scp ... chat:... の入力時にタイミングによって文字入力ができなかったりする。 47513 これは一体どういう事なのだろう…。プログラム補完が入力を奪っている? 47514 47515 % 今試すと再現しない。特定のホストだけで発生するという事なのだろうか。 47516 % うーん。一応標準入力を /dev/null に繋いで勝手に標準入力を食わない様に変更する。 47517 % もしユーザから入力を受け取るのであればその補完関数・コマンドが明示的に /dev/tty に繋ぐべきである。 47518 47519 と思ったが、ユーザから入力を求めて補完候補を絞る機能があっても良い様な気がしてきた。 47520 そのような発想で補完関数を設計する人は沢山いるだろうと考えられる。 47521 やはり、標準入力を勝手に封じるのは問題の様に思われてきた。取り敢えず保留という事にする。 47522 47523 →これが再現しなくなっていたのは実は別のバグで scp の補完関数 _scp に 47524 *:* の形式の引数が渡っていなかったからではないかと思われてきた。 47525 今修正が入っているので、再度確認してみて良い気がしてきた。 47526 47527 今実行してみたら scp による補完が動く様になった…が、 47528 何故か既存のホスト名の部分まで置き換えてしまう様に補完された…。 47529 更に、文字入力が吸収されてしまうという現象が再現した。 47530 47531 2つの問題がある。 47532 47533 * 先ず、ble.sh 上で補完するとホスト名が消失するが、 47534 bash 上で補完するとホスト名はちゃんと残っているという事。 47535 これは ble.sh の側での結果の解釈が誤っているという事である。 47536 或いは何かの機能を忘れている。prefix をつけるなどの。 47537 47538 うーん。取り敢えず観察する。 47539 47540 ble.sh 上で動かした時。 47541 | declare -- COMP_CWORD="1" 47542 | declare -- COMP_KEY="67108969" 47543 | declare -- COMP_LINE="scp chat:mirr" 47544 | declare -- COMP_POINT="13" 47545 | declare -- COMP_PREFIX="" 47546 | declare -- COMP_TYPE="9" 47547 | declare -- COMP_WORDBREAKS=" 47548 | \"'><=;|&(:" 47549 | declare -a COMP_WORDS=([0]="scp" [1]="chat:mirr") 47550 | declare -a COMPREPLY=([0]="mirror/") 47551 特に _scp 呼び出し前後で COMP_@ の変数の中身が書き換えられているという事もない。 47552 47553 bash 上で動かした時。 47554 | declare -- COMP_CWORD="3" 47555 | declare -- COMP_KEY="9" 47556 | declare -- COMP_LINE="scp chat:mirr" 47557 | declare -- COMP_POINT="13" 47558 | declare -- COMP_TYPE="9" 47559 | declare -- COMP_WORDBREAKS=" 47560 | \"'><=;|&(:" 47561 | declare -a COMP_WORDS=([0]="scp" [1]="chat" [2]=":" [3]="mirr") 47562 | declare -a COMPREPLY=([0]="mirror/") 47563 うーん。分かってしまった。ble.sh が COMP_WORDBREAKS に対応していないのが原因だった。 47564 47565 うーん。COMP_WORDBREAKS の中でもシェルの特殊文字でない物に関しては、 47566 ble.sh の側で分割を実行しても良い気がする。 47567 47568 - ok: ただし、これは ble.sh の補完の枠組みでは適用したくない。 47569 ble.sh の補完の枠組みの側では COMP_* は利用していただろうか…。 47570 →確認してみた所 COMP_* を初期化しているのは ble-complete/source:argument/.progcomp-helper-vars 47571 であり、この関数を使っているのは complete -F または -C に指定した関数・コマンドを呼び出す時だけだった。 47572 従って、ble.sh 独自の補完の枠組みでは使用されていない。 47573 47574 .progcomp-helper-vars の実装を変更する事にする。 47575 47576 - done: 先ず COMP_WORDBREAKS からシェルの特殊文字を除去する。 47577 特殊文字は util.sh から拾ってくる。 47578 - done: 次に単語を分割するという事。これも動いている 47579 - done: 分割した単語を用いて COMP_@ を構築する 47580 47581 * done: wordbreaks するのは simple-word/eval してからであるべきでは。 47582 そうしないと ${hello:=world} 的な物に対して途中で分断されてしまう。 47583 これは文法的にも変である。 47584 47585 うーん。先に eval してそれから wordbreaks する事にする。 47586 →大きく書き換えてしまったが対応した。 47587 47588 * done: 更にまた整理を行った。 47589 47590 * done: さて、これで補完関数は正しく動く様になった気がするが、 47591 生成された補完候補は単語の一部に対する候補なので、 47592 その事を ble.sh 側に正しく伝えないと、 47593 単語全体がその候補に置き換えられてしまって問題になる。 47594 47595 これはどの様に調整すれば良いだろうか。 47596 point が単語片の中にある場合には、 47597 その単語の eval した結果を保持しておいて、 47598 それを COMPREPLY に付加するなどの工夫が必要である。 47599 47600 或いは COMPREPLY を読み取る時に付加するというのでも良い。 47601 progcomp_prefix 的な変数に prefix を保存しておけば良いだろうか。 47602 或いは COMP_CWORD0 的な変数に最初の単語片の位置を記録しておけば良い。 47603 47604 と思ったら compgen 関数を通して実行されるのであった。 47605 この時、中で設定したシェル変数を外から参照できるのだったか。 47606 試しにやってみたらできた。なのでこれで良いだろう。 47607 結局 progcomp_prefix という変数に、 47608 現在の単語の現在位置よりも前の単語片を追記していく方法にした。 47609 後で progcomp_prefix を候補生成時に付加する。 47610 47611 動かしてみるとまだ問題が残っている。 47612 47613 x ok: ディレクトリ名を保管した後にスペースが挿入されてしまう。 47614 補完関数はディレクトリ名の補完で / を挿入している。 47615 一方で ble.sh が候補を単語と解釈して、更にスペースを挿入してしまう。 47616 47617 % nospace 的な compopt は設定されていないのだろうか。 47618 % うーん。確認してみたが _scp からはその様な物は指定されていない様子…。 47619 % 47620 % →不思議な事に普通の Bash で _scp を実行するとちゃんとスペースが挿入されずに補完されるが、 47621 % _scp_hook を通して実行するとスペースが挿入されてしまう。この振る舞いの違いは何か。 47622 % 47623 % うーん。調べてみると _ssh_options の中で compopt -o nospace が呼び出されているはず…。 47624 % 或いは compgen の中からだと unset -f compopt されてしまうのだろうか。 47625 % と思ってよく見てみると _scp は _ssh_options は呼び出していなかった。 47626 % 然し、何れにしても _scp の中で compopt +o nospace を呼び出しているのよりも 47627 % 前の何処かで compopt -o nospace を呼び出していると考えるのが自然である。 47628 % 47629 % 何と complete -F _scp_hook scp としてから complete -F _scp scp としても 47630 % 余分なスペースが入る様になってしまう…。 47631 47632 と思ったら実は単に complete -o nospace -F _scp scp という事だった…。 47633 つまり、ble.sh の側では complete -p の結果に含まれる -o ... を正しく読み取れていない? 47634 47635 と思って改めて実行してみたらちゃんと動く…。 47636 実はテストのために実行していた complete -F _scp_hook scp 47637 が設定を破壊していたというだけの話だった。 47638 47639 x fixed: compopt 内部で呼び出している builtin compopt は必ず失敗している。 47640 "補完機能は現在実行されていません" というエラーメッセージが出ている。 47641 Bash 4.1--5.0 の何れでも同様の動作の様なので呼び出さない事にした。 47642 47643 * resolved: 次に、scp の引数に対して入力をすると 47644 入力した文字列が消滅してしまうという問題について。 47645 これは ble.sh 上で Linux 上でも Cygwin 上でも再現する事を確認した。 47646 47647 特に自動補完が有効になっている時に再現する様な気がする。 47648 うーん。自動補完が有効になっていてもなっていなくても、 47649 勝手に標準入出力が壊れるのは問題である。 47650 従って、勝手に補完関数の標準入力は塞ぐ事にする。 47651 →標準入力を /dev/null に繋いで実行する様にしたら問題は起こらなくなった。 47652 47653 実際に補完関数が標準入力を必要とする事があるのかどうか分からないが、 47654 特に自動補完の事を考えたりすると標準入力を必要とする補完関数は変だ。 47655 という訳なので、補完関数は標準入力を使えないという事にする。 47656 敢えて標準入力を使いたければ自動補完でない事を確認して /dev/tty に繋いでもらう。 47657 47658 2019-02-03 47659 47660 * 2019-01-27 complete: 前の単語に対してパス名展開を実行する編集関数? [#D0902] 47661 M-g (glob-complete-word) 47662 C-x * (glob-expand-word) 47663 C-x g (glob-list-expansion) 47664 47665 どの様に現在の枠組みを修正するか。 47666 COMPV を配列にするか、展開前の値にするか。 47667 展開前の値にするのが良い気がする。 47668 comp_type に R を指定した時には展開前の値にする。 47669 47670 * [ok] complete: insert_all で comps_flags をクリアしなければならないのでは [#D0901] 47671 と思ったがそうでもないような気もする…。後で実際に試してみる。 47672 そもそも候補の生成時点でその状態を前提としてクォートしている筈である。 47673 47674 →試してみるとちゃんと動いている。${a} 等の補完もちゃんと動いている。 47675 47676 * util: それよりも何処かで leak variable が存在している… [#D0900] 47677 勝手にシェル変数 a の中身が ! に書き換わる 47678 これは util.sh の中のエスケープ関連の関数だった→修正した 47679 47680 * 2019-01-27 M-* (コマンドライン上でパス名展開を実施) などに対応する [#D0899] 47681 →改めて確認してみた所 M-* はパス名展開ではなくて 47682 補完候補を全て挿入という機能であった。 47683 47684 うーん。確かに全て挿入される。また、クォートを閉じるだとか、 47685 ファイル名・ディレクトリ名に対してスペース・スラッシュを挿入するだとか、 47686 そういう機能はなくて、単にスペース区切りで全て連結している様に見える。 47687 47688 試しに 'a/b の状態で展開を試みたらクォートは除去されて a/b* a/b* a/b* という 47689 内容が挿入される事となった。うーん。ここはやはりちゃんと全て complete を 47690 呼び出す様にしようか…。 47691 47692 実装した。動いているので気にしない事にする。 47693 47694 * progcomp: -o nosort noquote plusdirs などに対応する [#D0898] 47695 filenames の対応も不完全に見える。 47696 dirnames の対応についても再度確認したほうが良さそう。 47697 47698 * nosort の時には uniq は実行するべきかどうか。 47699 問題は一意確定なのに確定しない場合があるという事なので、 47700 uniq で十分なのではないかとの説。 47701 でも結局 uniq で外部コマンドを読み込むのだとしたら awk で処理した方が良いかも。 47702 →awk で実装する事にした。 47703 * plusdirs ... 対応した 47704 * bashdefault, default に関しては、 47705 何も候補が生成されなかった時の振る舞いだが、 47706 bash ではこれらが指定されなかったとしてもファイル名候補を生成する。 47707 * filenames ... これは確認したが quote はデフォルトで実行される。 47708 また末尾の空白やスラッシュも現状の実装でちゃんとなる筈。 47709 バグがなければ。 47710 * dirnames ... これは対応している。 47711 * noquote については。action:progcomp/initialize を見る必要がある。 47712 quote は initialize で実行されている筈だから。 47713 調べた。plain/initialize は結局 quote しかしていない様なので、 47714 ble-complete/action/util/quote-insert という関数に分離する事にした。 47715 その上で noquote が指定されている場合には quote を実行しない様にした。 47716 47717 * progcomp: 現在入力済みの文字列に合致しない物を生成しても全部棄却される [#D0897] 47718 ref #D0895 47719 47720 以下での議論に関連して。 47721 https://lists.gnu.org/archive/html/help-bash/2019-01/msg00006.html 47722 47723 元の Bash の実装ではOK。ただし、変な事が起こるので 47724 bind 'set show-all-if-ambiguous on' にしないと使い物にならない。 47725 更にそうしたとしても実際に補完されるのは一意確定の時のみである。 47726 47727 現在の実装では、通常時 (ambiguous でない時) は 47728 ble-complete/source:argument/.progcomp の中の 47729 ble/util/assign-array arr 'ble/bin/sed ...' の部分で $COMPV を接頭辞とするフィルタをしている。 47730 曖昧補完時は上と同じ箇所で compv の最初の文字によるフィルタをした上で、更に、 47731 ble-complete/source:{command,argument} の ble-complete/candidates/.filter-by-regex によって 47732 曖昧補完に合致する様にフィルタリングを実施している。 47733 47734 もしもっと自由な補完候補を生成したいのであれば、 47735 これらのフィルタリングを実施しない様なオプションを追加するなどする必要がある? 47736 その時には曖昧補完時には影響が出ないようにして、 47737 曖昧補完時に影響が出る様にする必要がある。 47738 47739 ? というかそもそも何故 sed でフィルタする必要があったのだったか。 47740 どの様な状況でフィルタする必要があったのかについて改めて調べる必要がある。 47741 何処かに記録は残っていないだろうか。 47742 47743 補完についての初めの議論は #D0181 である。 47744 うーん。ここではフィルタリングについては述べられていない。 47745 しかし、一番最初の実装からその様な実装になっていた気もする。 47746 覚えていないので寧ろ blame で遡った方が良いのかもしれない。 47747 47748 blame で遡ると以下が見つかった。 47749 47750 | $ git blame -C -M 4df15e1e~ -- complete.sh 47751 | 1929132b (Koichi Murase 2015-11-24 04:05:14 +0900 387,397) 47752 | # * 一旦 compgen だけで ble/util/assign するのは、compgen をサブシェルではなく元のシェルで評価する為である。 47753 | # 補完関数が遅延読込になっている場合などに、読み込まれた補完関数が次回から使える様にする為に必要である。 47754 | # * "$COMPV" で始まる単語だけを候補として列挙する為に sed /^$rex_compv/ でフィルタする。 47755 | # compgen に -- "$COMPV" を渡しても何故か思うようにフィルタしてくれない為である。 47756 | # (compgen -W "$(compgen ...)" -- "$COMPV" の様にしないと駄目なのか?) 47757 | # * sed で末端の [[:space:]]+ を除去する。 47758 | # git の補完関数など勝手に末尾に space をつける物が存在する為である。 47759 | # 単語の後にスペースを挿入する事を意図していると思われるが、 47760 | # 通常 compgen (例: compgen -f) で生成される候補に含まれるスペースは、挿入時のエスケープ対象である。 47761 | # →これだとスペースで終わるファイル名を挿入できない…。 47762 | # * arr=($(...)) としないのは IFS=$'\n' の影響を $(...) の中に持ち込まないためである。 47763 47764 というかこの sed に関する説明は今も残っている…。 47765 何れにしても 1929132b (2015-11-24) が怪しい。 47766 調べてみると 1929132b~ で既に sed の呼び出しは存在していない。 47767 2015-11-24 付近のログを調べてみる事にする。 47768 47769 うーん。取り敢えず #D0245 の気がするが、特に sed によるフィルタリングについては書かれていない。 47770 ただ、#D0245 は progcomp の対応であるので、変な補完設定が勝手に変な候補を生成した際に、 47771 それをフィルタする必要があったという事なのだろうと思われる。 47772 47773 というかもしかして補完関数を呼び出す時の呼び出し方が間違っていた (or 間違っている)? 47774 と思って調べてみる。1929132b の時点ではちゃんと "$comp_func" "$cmd" "$cur" "$prev" と呼び出している。 47775 一方で、その前の段階 cdd38598 (2015-11-23 23:58:01 これが #D0245 のメインのコミットと思われる) では、 47776 以下の様な実装になっていて -F で指定した関数の引数に単語などを渡していない。 47777 47778 | function ble-complete/source/argument/.compgen-helper-func { 47779 | local -a COMP_WORDS 47780 | local COMP_LINE COMP_POINT COMP_CWORD COMP_TYPE COMP_KEY 47781 | ble-complete/source/argument/.compgen-helper-vars 47782 | [[ $comp_func ]] && eval "$comp_func" 47783 | } 47784 47785 何だか単にこれが問題だったというだけの気がする。 47786 47787 * done: 取り敢えず試しに既定では "$COMPV" によるフィルタリングを実行し、 47788 もしそれで候補が一つもなくなる様だったら生成された候補を全て使用するという様に変える。 47789 47790 →取り敢えずその様にしてみたら動いた。 47791 クォートされてしまってパス名展開にならない的な事も起こっていない。 47792 よく考えてみれば ble.sh の progcomp は展開後の生の文字列を渡す事にしているので問題ないのである。 47793 47794 % 逆に言えば b\*sh としても b*sh に変換されてパス名展開の処理を補完関数が実行すると 47795 % それが有効になるという事でもあるのだが。 47796 % →と思って試してみた所、有効にはならなかった。 47797 % うーん。そういう物だったか。調べてみると ${comp_words[comp_cword]} から直接取り出していて、 47798 % 更に comp_words は extract-command を用いて生成している。 47799 % extract-command は無駄な展開などしないので、 47800 % 補完関数に渡されるのは実際にコマンドライン上にある文字列である) 47801 47802 x fixed: さて、動くには良いが既に存在している文字列が削れてなくなってしまう。 47803 更に、その状態で再度補完をやり直すと候補がまた沢山になってしまう。 47804 この辺りは対策をしていた様な気がするが何故動かないのか。 47805 曖昧補完の時にだけ対策が実行されるのだったか。調べる必要がある。 47806 47807 調べると一致しない場合には insert_flags=r というフラグを立てている。 47808 しかし、実際にはこのフラグを使用している箇所はない。 47809 挿入・置換を実施するところで insert_flags == *r* の時で、 47810 かつ一意確定でない時には置換を実施しない様に書き換えた。 47811 47812 * ok: 速度は気になる。今回の変更では assign の呼び出し回数が増えた。 47813 しかし fork の数は減っている様にも思う。 47814 これが実際の処理にどの様に影響を与えるであろうか。 47815 47816 実際に以前のコード (1回の assign) と較べてみると、 47817 以前は 0.020 だったのが今回は 0.028 になっている。 47818 と思ったが、よく考えたら以前のコードは候補が絞れなかった時に候補が生成されないので比較対象として適切でない。 47819 同等の機能を持って、しかし1回の assign で実行する場合と比較しなければならない。 47820 というか、それには b*sh ではなくて g などで調べた方が良いのではないか。 47821 47822 何かちゃんと動作しない。と思ったら .bashrc に書いている補完関数の方の問題だった。 47823 計ってみると以前のコードが 0.019 で今回のコードが 0.018 と言った様な具合で、 47824 新しいコードの方が若干高速である。とは言いつつ、何度か呼び出すと微妙に時間が反転することもある。 47825 →これで良いという事になった 47826 47827 * ok: 実はデフォルトでフィルタしない動作で良い気がしてきた。 47828 compopt でなにか指定した時にだけフィルタリングを実行するなど。 47829 →compopt に独自の filter_by_prefix を追加する事にした 47830 47831 この独自設定については何処か説明書に書く必要はあるだろうか。 47832 というかそもそも補完において、bash のプログラム補完が使えるという事を 47833 説明書に書いていない。うーん。面倒である。 47834 これは memo.txt の先頭に書いておく事にした。 47835 序に古い設定変数一覧は消す事にした。 47836 47837 x fixed: 実際にフィルタリングなしで動かしてみると動作が変である。 47838 やはり filtering しないと駄目である。 47839 と思ったが変だ。うーん。実際にやってみると大量のファイル名を出力している。 47840 何故だろう…。そして、普通に ble.sh 以外から touch の補完を実行すると正しい候補だけを出力している。 47841 うーん。ble.sh による補完関数の呼び出し方が未だ間違っているという事なのか。 47842 47843 詳しく呼び出しの状態を調べてみる事にする。 47844 先ず疑ったのは関数を呼び出す時の引数だったが、 47845 これについては具体的に出力してみた所、問題なかった。 47846 次に調べるのは declare -p ${!COMP*} である。 47847 →COMP_POINT が間違っている…。 47848 COMP_POINT は補完開始点ではなくて現在のカーソルの位置の様である。 47849 しかしこれだけで変わる物だろうか…。 47850 何れにしてもこれは問題なので修正する事にする。 47851 うーん。comp_point はちゃんと正しい値である。 47852 47853 分かった。バグだった。修正した。 47854 47855 2019-01-27 47856 47857 * [棄却] 2019-01-21 complete: 曖昧補完時にパス名展開を考慮に入れると良いのではないか? [#D0896] 47858 47859 https://lists.gnu.org/archive/html/help-bash/2019-01/msg00003.html 47860 https://lists.gnu.org/archive/html/help-bash/2019-01/msg00006.html 47861 47862 | 現在の実装ではパス名展開で一致した物の内で一番最初の物を選択し、 47863 | 更にその続きに来るかも知れない文字を探すという動作になっている。 47864 | 改めて考えるとその動作の方が自然な気がする。 47865 | 47866 | またコマンド名をパス名展開で検索するという考え方は変だ。 47867 | そもそもの話としてコマンド名にパス名展開を含んでそのまま実行しても実行されない。 47868 | 然し、よく考えてみればそもそも補完はそういうものである。 47869 | そのままでは実行できないけれども文字列を補完する事によって実行できる様にする。 47870 | その様に考えてみれば候補が他に存在しないという時に限って、 47871 | コマンド一覧をパス名展開で表示するというのは一つの手である様な気がする。 47872 | 47873 | というよりそういう細かい動作はユーザに complete -I で実装してもらう事にして、 47874 | ble.sh の側では何も関知しないという手もある。しかし、ble.sh の補完の仕組みは 47875 | 丁寧に作りすぎている所為で、グロブパターンが存在するとそれをクォートしてしまう。 47876 | そうすると期待通りに展開が為されないのではないかとも思われる。 47877 | 何れにしてもこれについて考えるのは complete -I を実装してからという気がする。 47878 47879 先ず、引数の補完の場合には: 47880 パス名展開は複数のファイルに一致する事を意図しているはずなので、 47881 勝手にその内のどれかに展開してしまうのは変である。 47882 コマンド名の補完の場合には: 47883 どれか一つに一致するのが自然なので対応しても良いが、 47884 実のところ、本来は b*sh などではコマンドを実行できないので、変な気もする。 47885 これはユーザ側のプログラム補完 complete -I で個別に対応してもらえれば十分である。 47886 47887 * 2018-07-28 complete: bash-5.0 の complete -I に対応する [#D0895] 47888 47889 これは要するにコマンド名の候補の生成に使うと考えたら良いだろうか。 47890 他の入力画面でも同じ補完を使うのはやはり変なので、 47891 コマンド名の補完候補の生成に限って使うというのが良さそう。 47892 47893 取り敢えず ble-complete/source:argument/.progcomp を改造して、 47894 -I の時に対応できるようにしたい。→取り敢えず 47895 .progcomp initial として呼び出せば -I で complete -p する様に修正した。 47896 47897 ble-complete/source:argument/.generate-user-defined-completion も改造するか。 47898 実は最初の単語にカーソルがある場合には動作を切り替えるという様にもできるし、 47899 或いはオプションとして initial が設定されていたら動作を切り替えるという様にもできる。 47900 ここではオプションとして initial が設定されていたらという方法にする。 47901 というのも sudo command 等の場合には文法的には command が引数であっても、 47902 ユーザの手動の設定でコマンド名としての補完を要求することがあるかもしれないからである。 47903 47904 ble-complete/source:command に ble-complete/source:argument 47905 に書かれている物と同じ物を書いてみる。実はこれで対応は完了なのではあるまいか。 47906 47907 実際に動かしてみると動かない。候補が生成されていない。 47908 と思ったが、実は当然である。何しろ complete -I を指定していないのだから。 47909 試しに何か適当な物を指定してみる事にする。 47910 →opts "initial" を渡すのに失敗していた。動く様になった。 47911 しかし、今度は source:command で生成された候補が全部棄却されている。 47912 →調べてみると source:command の外側で棄却されているのではなくて中で棄却されている。 47913 更に観察してみると ambiguous の時には ble-complete/candidates/.filter-by-regex の時点で棄却されている。 47914 また、ambiguous でない場合にはもっと上流で棄却されている気がする。 47915 調べるとどうも ble-complete/source:argument/.progcomp の中の 47916 ble/util/assign-array arr 'ble/bin/sed ...' でフィルタしているのだった。 47917 47918 うーん。これはそういう仕様である。何故その様になっているのかと言うと、 47919 compgen が時々 prefix に関係ない物まで全て列挙してしまうからであった気がする。 47920 しかし、その様な場合にはどの様に対処すれば良いのだろうか…。 47921 うーん。こういう場合については取り敢えず対応しないことにする。 47922 47923 別の項目として立てておく事にする。 47924 47925 2019-01-22 47926 47927 * 実は declare -i した変数 var の var+= の右辺でも算術式展開が起こる様だ [#D0894] 47928 47929 しかも算術式評価で解析する量が減るので var+= が一番早いという結果も出ている? 47930 https://lists.gnu.org/archive/html/help-bash/2018-12/msg00092.html 47931 47932 これは算術式の記事を更新しておく必要がある→更新した。下書きに入れてある。 47933 https://qiita.com/akinomyoga/items/2dd3f341cf15dd9c330b 47934 https://qiita.com/akinomyoga/items/9c9d6cfeb02f186f9185 47935 そんなに際どい事は書かれていなかったので多少例を追加するだけで済んだ。 47936 47937 これに関連して ble.sh を修正する必要はあるだろうか。 47938 現在の ble.sh の実装だと declare -i や local -i は基本的に使わない様にしている。 47939 メーリングリストの計測結果を見ると、もしかすると declare -i や local -i 47940 にした方が動作が高速になるかもしれないが。。 47941 うーん。然し、-i になっていると代入する度に算術式評価が入るので、 47942 単純な値の代入が起こる限りはやはり -i をつけない方が速い様な気もする。 47943 実のところ、一長一短である。面倒なので -i をつけない方針で統一する方が楽なのではないか。 47944 因みに、現在の実装では主に引数を受け取る時に -i を結構使用している。 47945 47946 色々考えるのが面倒になったので出来るだけ local -i は使わない様に変更する事にした。 47947 declare -i 及び local -i を使わない理由を以下に挙げる事にする。 47948 47949 1 local -i を使ったり使わなかったりすると呼び出し元で算術式展開をしたりしなかったりする。 47950 そうすると確認する時に算術式展開をするべきかしないべきか判断しなければならない。 47951 2 逆にできるだけ local -i を使う様にすると良いと考えるかも知れないが、そうすると 47952 今度は整数引数なのかそうでないのかの仕様がだんだんとよく分からなくなってくる。 47953 また、算術式展開をわざわざ呼び出すまでもない整数引数を受け取る関数についても 47954 local -i で引数を受け取る事になる逆に処理の効率が悪くなってしまう。 47955 3 そもそも算術式展開がその場で必要になる機会の方が少なくて、 47956 そしてその様なときには呼び出し元がそれを知っているはずなので、 47957 呼び出し元でちゃんと算術式展開を実行する様にするべきなのである。 47958 47959 2019-01-21 47960 47961 * 実は unset 変数名 とした時にその変数がなくて関数があると関数が消える [#D0893] 47962 47963 例えば: 47964 $ function hello() { echo world; } 47965 $ hello=1234321 47966 $ unset hello # 変数が消える 47967 $ unset hello # 関数が消える 47968 47969 unset -v を使う様にすれば関数が消えてしまう事はない。 47970 ble.sh の中の unset (-f なし) を全て unset -v にする。 47971 47972 2019-01-20 47973 47974 * 2018-09-23 manual: 説明書について書き始める [#D0892] 47975 47976 書き始めると仕様で微妙なところが浮き上がってくるのでその都度修正する事にする。 47977 47978 - done: vi でも M- 系列を bind するオプションがあっても良いのでは。 47979 しかしキャッシュしていると反映されなくなってしまう。 47980 また、keymap vi の初期化の前にそのオプションは指定しなければならない。 47981 或いは、キーマップの継承などがあれば簡単なのかもしれない。 47982 しかし、これ単体の為に継承を新しく実装する程でも無い。 47983 或いは M- 系列を元から bind してしまう…? 47984 47985 | うーん。現在のデフォルトの Meta/ESC の設定は何だったろうか。 47986 | bleopt_decode_isolated_esc=auto になっていて、 47987 | この時 ble-decode/uses-isolated-esc は vi モードで return 0 である。 47988 | 一方で、uses-isolated-esc の呼び出し元を確認すると、 47989 | 孤立ESCを受け取った時にそれを ESC として処理するかどうかの判定に使っている。 47990 | 現在の設定では孤立ESCは ESC として扱う振る舞いになる。 47991 | 47992 | ここで問題になるのは timeout の長い処理系を使っている人について、 47993 | ESC を入力してから次のキーを入力するまでの時間が短いと Meta になってしまうという事である。 47994 | また、Meta を押しながらキーを入力する事で確実にノーマルモードで実行する様にする、 47995 | という癖にして使っている人も世の中にはいるかもしれない。 47996 | その様に考えると M- 系列を初めから bind しておくというのは憚られる。 47997 | 47998 | 現在の実装では M- 系列が bind されていないので、timeout して孤立ESCが次の文字とくっついたとしても 47999 | 最終的には分解されてちゃんと単体の ESC として処理される。従って問題が発生していないのである。 48000 48001 単に M- 関連を bind する為の関数を提供すれば良いだけの気がしてきた。 48002 ble-decode/keymap:vi_imap/define-meta-bindings という関数を用意する事にした。 48003 blerc に記述する。 48004 48005 - done: vi_[nox]map C-end vi-command/last-line は vim の説明に依ると inclusive である筈。 48006 実際に試してみようとすると C-end が認識できないので入力できない。 48007 しかし、vimindex によると G と C-end は同じと書かれているにも拘わらず、 48008 実際に vim motion の頁を見ると G と C-end は異なるように書かれている。 48009 G は linewise であり C-end は inclusive であると書かれている。 48010 48011 実装し直す事にする。実装した。簡単に動かしてみた所、動いているので後は気にしないことにする。 48012 C-home に関しても現在の実装では jump になっているが vimindex によると、 48013 (H と殆ど動作として同じであっても) jump ではない用なので実装し直した。 48014 48015 - done: M-m 及び S-M-m の実装が単なる beginning-of-line になっている f77f1aa 48016 48017 - done: vi_nmap: z z, z b, z -, z . の実装は不完全である (ref #D0886) 48018 48019 取り敢えず今までの所で浮き上がってきた仕様の微妙な所は修正した。 48020 この項目についてはどの様にしようか。長くなって来たので Done に送りたい。 48021 他に残っているのは Emacs 編集モードの説明のみである。これは独立した項目にする。 48022 48023 * update: .tar.xz から落とした場合でも ble-update を使える様にする [#D0891] 48024 しかし、これは次の 0.3 のリリースまでは実際には有効にはならないが。 48025 48026 後、.tar.xz の時にはコンパイルに使用したディレクトリを記録しない様にするべきでは。 48027 偶々同じ名前のディレクトリ (例えば ble.sh の異なるバージョンなど) が存在した時に変な事になる。 48028 48029 % 或いは .tar.xz の時には、何か特別のファイルを添付してそれで判別するか。 48030 % 例えば $_ble_base/ble-release-version.txt などのファイル。 48031 % → $_ble_base/ble-release というファイルを置く事にした。 48032 48033 と思ったがやはり微妙な気がする…。余分なファイルができてしまうという事が先ず気になる。 48034 別に余分なファイルを作らなくても原理的には可能な機能である。 48035 次に、コンパイルしたディレクトリの記録を残しておく理由がない。 48036 その様に考えると、コンパイルしたディレクトリの記録の部分に特別な値を設定しておく方が自然である。 48037 48038 - done: reload した時に再度設定を適用する為には README は更新しておかなけけばならない。 48039 - done: _ble_base_repository=release:branch の形式で特別な値を埋め込む事にした。 48040 48041 実際にテストしてみた所ちゃんと動く様子なのでこれで良しという事にする。 48042 因みにこれを実行すると clone のカウントが増える。 48043 2019-01-20 に一回テストを実行したので clone の回数が一回増えているはず。 48044 取り敢えずこれで完了しているはず。。 48045 48046 * fixed: うーん。ble-update のテストをしていたら何故か _ble_base の決定がおかしい… [#D0890] 48047 と思ったら source ble.sh の様にディレクトリを指定せずに読み込むと駄目の様だ…。 48048 これについては修正した。 48049 48050 * 2018-09-28 isearch: 空文字列で検索を開始すると前回の文字列で検索する様にする可能性? [#D0889] 48051 48052 これは bash の既定が空文字列による検索なので微妙かもしれない。 48053 然し、よく考えてみると既に確定時の振る舞いが異なるのだし、 48054 やはり emacs の振る舞いの方が自然に思われるので、 48055 これは実装しても良いのではないかという気がする。 48056 →実装した。意外と簡単だった。本当にちゃんと動いているかは自信がないが。 48057 取り敢えず暫く使ってみてから考えれば良いだろう。 48058 48059 記録するのは検索を実行したタイミングではなくて 48060 実際に一致したタイミングであるべきなのでは。 48061 48062 2019-01-19 48063 48064 * complete: 複数行モードにおけるメニュー補完で描画位置がずれている気がする [#D0888] 48065 と思ったら複数行どころか常に描画位置がずれるようになってしまっている。 48066 一箇所直したら治った。これは #D0880 で埋め込んだバグであった。 48067 48068 2019-01-16 48069 48070 * bleopt: 内部の設定変数に internal_ を冠する事にした [#D0887] 48071 48072 - suppress_bash_output -> internal_suppress_bash_output 48073 - ignoreeof_message -> internal_ignoreeof_trap 48074 - exec_type -> internal_exec_type 48075 - stackdump_enabled -> internal_stackdump_enabled 48076 48077 2019-01-14 48078 48079 * vi_nmap: スクロール [#D0886] 48080 48081 * C-d C-u C-e C-y について対応し始めたら何だか分からなくなってきた。 48082 現在の実装だと論理行と表示行の取り扱いが混ざり合っている。 48083 48084 ble.sh のスクロールは表示行についてのスクロールである。 48085 更に、プロンプトの高さの分だけ全体の高さは引き算して考える必要がある。 48086 では vim の C-d, C-u は表示行なのだろうか、それとも論理行なのだろうか。 48087 更に C-e や C-y は表示行なのか論理行なのか。 48088 48089 どうも調べてみると C-d 及び C-u は論理行の移動の様である。 48090 そして移動した分だけスクロールするという仕組みになっている様子である。 48091 何と、C-e や C-y についても論理行のようである。 48092 つまり、画面に表示されている先頭行を追加・削除するという形。 48093 カーソルはできるだけ移動しないが、画面に入り切らない時には内側に入れる。 48094 48095 x fixed: ble/textmap を使って実装してみたがどうも動作が変である。 48096 もしかすると scroll 値の意味を勘違いしている。 48097 例えば scroll=15 なのに何故か表示は 17 行目からになっている。 48098 ble/textarea#render/.show-scroll-at-first-line の実装を観察すると、 48099 確かに scroll+2 を現在の行番号として表示している。その心は何だろうか。 48100 48101 また、.determine-scroll の説明を読むと scroll とはスクロール量である。 48102 つまり、最初に表示されている行の番号という訳ではない。 48103 例えば、scroll=1 の場合を考える。この時、1行目は行番号に置き換えられて、 48104 2行目が欠損する形で3行目(y=2)からの表示となる。 48105 48106 max_scroll の値も再考する必要がある。 48107 nline あって枠が height なのだとすれば nline-height だけ欠損すれば全体を表示できる。 48108 従って、max_scroll = nline-height = _ble_textmap_endy + 1 - height である。 48109 それから ay by の値も修正した。y<ay の時の y=ay が誤って x=ay になっているのも修正した。 48110 まあ、何やら動く様になったので良しと言う事にする。 48111 48112 * ページのスクロールについても実装することにする。 48113 基本的には現在見えている一番下の行に移動するという事。 48114 引数を指定するとそれを繰り返し実行したのと同じ位置に移動する。 48115 つまり、移動後は上から2行目に表示されるので、表示高さを vheight として 48116 (ARG-1)*(vheight-2) だけ下に移動した位置に移動する。 48117 48118 C-b の場合には scroll が 1 以上の時にだけ動作し、 48119 現在表示されている画面の一番上から2行目の行が画面の一番下に来る様に移動する。 48120 カーソル位置は以前表示されていた内容の1行目の非空白行頭である。 48121 (ARG-1)*(vheight-2) だけ上に移動する。 48122 48123 頁のスクロールについても実装した。動いている気がする。 48124 48125 * zz 辺りを実装する。 48126 引数を指定すると移動先の行番号となる。 48127 行は論理行であり、更に相対位置関係で列の位置が決まる。 48128 実装した。動いている。 48129 48130 2019-01-13 48131 48132 * [自然解消] 2015-03-06 整理 [#D0885] 48133 48134 | - 着色の古いコード 48135 | これに関しては現在の複雑な実装と昔の簡単な実装の間の着地点を見つけたい。 48136 48137 これも古い実装についてなので忘れる事にする。 48138 48139 * [自然解消] 2015-02-24 ble-syntax-highlight+* の代替機能の実装と廃止 [#D0884] 48140 これは既に消滅している気がする。 48141 48142 * [自然解消] 2015-02-23 complete: TAB を打たなくても補完候補がある場合は薄く表示する? [#D0883] 48143 48144 | 重くなるといけないので read -t 0 で確認しつつ処理を行うのが良い。 48145 | 48146 | 実際に未だ入力されていない物を上に重ねて表示する場合、また新しい枠組が必要になる気がする。 48147 | 48148 | a 一つの簡単な方法は「編集文字列を本当に書き換えてしまう」方法である。 48149 | しかし編集文字列を書き換えている状態で別のコマンドが起動されるなどすると 48150 | 編集文字列内容に齟齬が生じて面倒な事になる。それを防ぐ為に新しいコマンドが来るたびに 48151 | 編集文字列の内容を復元するようにトラップをしかけるのも綺麗でない。 48152 | その他の理由でトラップをしかけたくなった時などに結局齟齬が生じる可能性が残る。 48153 | 48154 | この方法は現実的でない。 48155 | 48156 | b もう一つの方法は上に重ねる事のできる「レイヤー」の概念を導入する方法である。 48157 | 48158 | レイヤーを導入する場合、描画ルーチンが面倒な事になる。 48159 | 48160 | b.1 既存の描画ルーチンを活かす方向で行くと、 48161 | 一旦一番下のレイヤーを描画した後でその上にあるレイヤーの描画をつづけて行えばよい。 48162 | しかしこれだとちらつきが気になる。 48163 | 48164 | b.2 もう一つの方法は描画を完全に座標指定で行う事にして、 48165 | あるレイヤーを描画する際にはマスクを考慮して描画できる様にする。 48166 | 48167 | うーん。わざわざ座標指定で描画を行える様にしなくても、 48168 | 既存の描画関数の内部を適当に書き換えるだけで行けそうな気もしないでもない。 48169 | 要するにマスクされた領域の上にある文字については、文字を出力する代わりに 48170 | 位置だけを更新して、最初にマスクされていない領域の文字を書き込もうとした瞬間に、 48171 | その位置へ移動するシーケンスを生成する様にしたらよい。 48172 | 48173 | ただこの時に問題なのはどの様にしてマスクされた領域を表現するかである。 48174 | 領域の上に複雑にレイヤーが存在している場合、領域に沢山の矩形の穴が空いた状態になる。 48175 | この様なマスクがある場合マスクの上にあるかどうかの判定は物凄く重い計算になる。 48176 | 48177 | やはり描画可能領域は矩形に制限して、上に重なっている別のレイヤーに関しては 48178 | 上から重ねて描画してしまうという手を取った方法の方が良いのではないかという気がする。 48179 | 48180 | 48181 | b.3 或いは内部に完全に画面のバッファを保存してしまうという手もある。 48182 | そして最後に更新された部分だけ反映させるという方法である。 48183 | 48184 | o この方法だとサブウィンドウを作成したりする事ができて汎用性が高い。 48185 | 何れはこの方法を採らなければならなくなるのではと言う気がする。 48186 | 48187 | x 特に各座標位置について描画属性などを保存する事になるだろう。 48188 | しかしメモリを食うのではないかなどの懸念も残る。 48189 | 48190 | x また描画用のシーケンスの生成にも処理時間が掛かりそうな気がする。 48191 | 何しろ記録した配列の要素をスキャンしてシーケンスを構築していかなければならないからである。 48192 | 或いは現在の編集文字列の記録と同様に配列に描画シーケンスも含めて記録しておいて、 48193 | 其処から特定の範囲の要素だけ単純に join して出力できるようにするか。 48194 48195 2019-01-13 これは auto-complete として既に実装されている。 48196 この考察にはウィンドウシステム的な物の実現の可能性など 48197 示唆に富むものもあるが似たようなことは既に他の項目でも述べられているので Done に移動する事にする。 48198 48199 * 2017-09-25 複数行編集スクロール: info の高さとの兼ね合い [#D0882] 48200 48201 | 先ず info の高さを制限するようにしなければならない。 48202 | 現状では高さを計測する仕組みはあったが制限する仕組みはなかった気がする。 48203 | つまり高さを計測しながらもし予め指定した高さを超えるようであれば 48204 | そこで切るようにしなければならない。 48205 | 48206 | その後で info の高さを全体の高さの半分になるように制限する。 48207 | 編集パネルの高さはその時点での info の高さを引き算した値で決定する。 48208 | もし編集パネルの高さが 2 行未満しか取れない場合には info を削る。 48209 | 48210 | (そもそも端末の高さ LINES が 2 未満しかないような環境は無視する。) 48211 | 48212 | →第2のプロンプトも出すようにしたので、それも意識して修正しなければならない。 48213 48214 これは #D0878 で実装された。 48215 48216 * 2018-02-12 スクロール位置を変更する仕組み? [#D0881] 48217 48218 現在の仕組みではスクロールはカーソル位置が表示範囲外になった時に自動的に行われる。 48219 明示的にスクロール位置を変更する仕組みを追加したい。 48220 どれだけスクロールするかのデルタを記録する方法だと絶対位置に移動するのが辛い。 48221 やはり現在スクロール量を直接編集できるようにしたい。 48222 その為には現在の描画におけるスクロール量と、 48223 内部の論理的なスクロール量の二つの変数を用意する必要がある。 48224 48225 * 2018-08-30 complete: bug, menu-complete 中にコマンドラインの高さが変わると座標計算がずれる [#D0880] 48226 48227 これは改めて試してみた所、端末の高さが足りている場合には問題は起こらない様である。 48228 (しかし、本当だろうか…問題が起こっていた時も高さが足りていた様な気がするが…) 48229 48230 | 問題が起こるのは端末の高さが足りない時である。 48231 | つまり、コマンドラインの高さが増えた時に、 48232 | 本来それに応じて info の高さを減少させなければならない。 48233 | この問題は実は全般に存在する。例えば、画面一杯に編集している時に 48234 | cmap (panel 1) で複数行の内容を入力したらどうなるのかなど。 48235 | 結局、本体 (panel 0) を削る事が自然な状況も存在するという事である。 48236 | そして、本体を削った時にどの様に再描画を行うのかという問題がある。 48237 | 個別に対応していると汚くなり管理できない。 48238 | 48239 | 一般的な仕組みとして整えるとしたら、どの様に対応すれば良いだろうか。 48240 | 48241 | a 一つの方法はアクティブ・非アクティブの panel という概念を作り、 48242 | アクティブな物は非アクティブな物から高さを一時的に奪う事ができ、 48243 | また、新しくアクティブになった時に改めて高さを回復する様にする。 48244 | 48245 | これを実装するには改めてアクティブになった瞬間に、 48246 | 再描画を呼び出す事ができなければならない。 48247 | もしくは内容を別の方法で記録しておく様にすれば良い。 48248 | 48249 | x 問題点は、二つの物を同時に表示したい時に、 48250 | 必ずどちらか一方 (最終的にアクティブでない方) は画面に入り切らないことである。 48251 | やはり一時的なサイズの変更ではなくて、本当にサイズを変更する仕組みが必要である。 48252 | 48253 | b 或いは、高さが変更された時に再描画する様なコールバックを呼び出す様にする。 48254 | この場合、高さを何処から奪い取るかの仕組みをどのように整えるかは難しい。 48255 | 48256 | 例えば min-height をそれぞれの panel に設定できる様にする。 48257 | 余裕の多いところから均等に高さを確保する様にする、という事にするのはどうか。 48258 48259 これらは #D0878 で枠組みを整えた。しかし、それでも未だ問題が起こる。 48260 48261 menu-complete を初期化した時に各項目の位置などを記録して、 48262 選択肢を変更した時にその位置だけ再描画する様にしている。 48263 しかし info の高さが変化して短くなると、選択肢が画面外に消える。 48264 その時に無理やりその位置だけ再描画という処理をすると座標計算がずれると思われる。 48265 従って、その位置だけ再描画する際に、現在の info の高さを確認して 48266 中に収まっている時に限って再描画を実行する様に変更するした。 48267 48268 * 2018-12-02 座標計算を修正したと思ったが依然として長い日本語名のファイルに対して治っていない? [#D0879] 48269 48270 | これは画面に収まりきらないぐらい沢山の項目がある場合に起こる。 48271 | しかし、それでも起こる場合と起こらない場合があるのは何が違うのだろうか。 48272 | 48273 | ASCIIだけで構成されたファイル名の場合には長いファイル名があっても問題は発生しない様だ。 48274 | 48275 | うーん。どうも一部のファイルの座標計算がずれているという事の様な気もしてきた。 48276 | 変な文字が含まれていると次の行に行くが、その時、続きに収まるファイル名を表示するか。 48277 | 現在は表示されている気がする…と思ったが、元からそういう仕様だったような気もしてきた。 48278 | 48279 | と思って試してみると改行を含むようなファイル名の時に確実に失敗する様である。 48280 | やはり改行を含んでいてもASCIIだけで構成されているファイル名の場合には問題は発生しない。 48281 | 日本語のファイル名を自分で作って試してみても再現しない。不思議な事である。 48282 | 空白類をたくさん含むファイル名を作って意図的にファイル名が長くなるような物を作成しても 48283 | 問題なく表示される (というか、menu で表示されるファイル名はエスケープの対象ではなかった)。 48284 | 48285 | 今試してみた所再現しなくなっていた…。もしかすると Poderosa の方のバグだという可能性もあるのだろうか。。 48286 | 或いは、ウィンドウサイズを変更した直後にだけ起こっているのかもしれない。 48287 48288 どうも再現しない様だ。ウィンドウサイズを変更した後などには再現するがそれは一時的な物である。 48289 また、確実に再現する状況を作り出してからこれについては考える事にする。 48290 48291 後は、曖昧文字幅の文字を表示した後に一文字ずれる。 48292 これは持っている文字幅の辞書との不一致による物だろう。という事で気にしなくても良い。 48293 48294 2019-01-13 #D0878 で info / textarea の高さの融通の仕組みを整えた。 48295 多分、似たような描画のずれの問題が合ったとしてもそれで治っている気がする。 48296 もし依然として解決していないとしても現状では症状がよく分からないので再発した時に考える事にする。 48297 48298 * textarea: 描画の高さ関連の項目がたくさんあるので解決する事にする [#D0878] 48299 48300 先ずは高さを指定して再描画する機能を実装するのが良さそうである。 48301 48302 - 高さが低くなる時 48303 info に関しては単に高さを削るだけで良いのではないか。 48304 編集文字列に関しても実は高さを削るだけで良い様な気がして来た…。 48305 と思ったが高さが収まっている状態から高さに収まらない状態に移行した時は、 48306 最初の行に現在の行番号を表示するのではなかったか。 48307 試してみるとスクロール位置が変わらない限りは最初の行は最初の行である。 48308 つまり、収まっている状態から収まらない状態に移行する場合は、 48309 スクロール位置を変更しない限りはやはり末尾を削るだけで良い。 48310 48311 - 高さが高くなる時 48312 info に関してはどういう理由で設定されたかが色々なので、 48313 高くしても内容の再描画はしなくて良い気がする。 48314 というより高くなる機会があるのかもよく分からない。 48315 編集文字列に関しては再描画の必要がある。 48316 48317 後試していて気づいたが、既に色々と問題がある。 48318 48319 x fixed: 複数行編集モードのときに C-l をするとカーソル位置が先頭行に移動してしまう。 48320 列の位置は正しい。これは何故だろう。 48321 →これは改めて ble.sh を立ち上げてみたら再現しなくなった。 48322 一度スクロール状態になってから戻ると駄目なのかとも思ったがそうでもない様だ。何だったのだろう。 48323 →再現した。スクロール状態で一度 C-l を実行するとなるという事? 48324 調べてみるとスクロールを解除したのにスクロール状態になっていて、 48325 48326 スクロール状態の時のカーソル位置の計算を確認したら間違っていた。 48327 二重に高さの位置を更新していた。これは修正した。再現しなくなった。 48328 48329 x resolved: 複数行スクロールの時に bell で文字列が表示されるとプロンプトが消されてしまう。 48330 プロンプトの位置と bell の位置が被っている時にはプロンプトを再描画するべきではないか。 48331 恐らくこれは高さの計算を正しく実行する様にすれば解消できるはず。 48332 48333 →実装し終わってから試してみた所、問題は発生しなくなっていた。 48334 48335 うーん。どの様なモデルにするのが正しいのか。 48336 各パネルにどの様な機能を要求するのかというのを考える事にする。 48337 48338 - 先ず再描画・更新描画の機能。 48339 48340 - 高さ変更の通知とそれに伴う再描画の機能。 48341 これは内部の構成要素の配置も含むはず。 48342 48343 これが呼び出されるのは他のパネルに高さを奪われた時以外に、 48344 端末の高さが変更された場合なども含まれる。 48345 ただし、現時点では端末の高さの変更には対応しない。 48346 48347 - スクロール及び配置の計算は実は内側の枠組みではなくて 48348 外側の枠組みで提供するべきことのような気がしてきた。 48349 うーん。スクロールはやはり内部で管理するべき。 48350 外部には min-height 及び desired-height 的な物を公開する。 48351 48352 もしくは span-h にしてできるだけ伸ばす設定にして、 48353 しかしながら実際の表示の高さは自由に設定できるようにするか。 48354 しかしそうすると何が何だかよく分からないのでこれはやめる。 48355 やはり外部に公開された情報を用いて高さを調整するのが良い。 48356 48357 更に info と textarea の高さのバランスも考えたい。 48358 両方が高さを過剰に持っている場合には等分配か、 48359 或いは一定の比率で分配する様にしたい。 48360 うーん。やはり min-height 及び desired-height 48361 だけから取り敢えず実装してみる事にしようか。 48362 48363 取り敢えず min-height 及び desired-height を問い合わせる仕組みを作る事にする。 48364 色々実装してみた。未だ途中の積もりだったが取り敢えず何となく動いている様な気がする。 48365 48366 x ok: info による reallocate-heights によって編集文字列側の再描画が必要になる事があるはず。 48367 48368 所で端末のサイズが変わった時には TRAPWINCH で textarea#redraw が呼び出されている。 48369 そして textarea#redraw の中では textarea#invalidate が呼び出されている。 48370 うーん。info によって高さが変わるのだとしたら通知が高さ変更の通知があっても良いのではないか。 48371 48372 まあ、何かわからないけれども動いている気がする。 48373 試してみたら info が縮んで再び編集文字列にスクロールが不要になった時、 48374 次の入力が来るまでは再描画が実施されない…という事が分かった。 48375 48376 % 何故かと言うと info を消去しているのが ble/util/idle からなので、再描画がされていない…。 48377 % →調べてみると ble/util/idle.do && ble/textarea#render の様に実行されるので、 48378 % idle の中で on-height-change が起こったとしてもちゃんと invalidate で再描画される。 48379 % これは関係ないし、気にしなくて良い。 48380 48381 →実際にやってみると全く動作していなかった。今まで動いていた様に見えたのはたまたま 48382 編集文字列の内容に変更などが合ったために再描画されていただけだった。 48383 48384 x fixed: 描画が乱れる問題 48385 48386 % ちゃんと invalidate が呼び出される様にしてみた所、カーソル位置の計算が乱れる様になってしまった。 48387 % 何故だろう。単に invalidated を変更するだけでこうも違いが出る理由がよく分からない…。 48388 % 48389 % うーん。発生したりしなかったりで謎である。というか一回を除いて毎回発生している。 48390 % やはり invalidated を設定しない場合には表示の乱れは起きない。 48391 % うーん。分からないけれども info pane が一行はみ出ている気がする…。 48392 % それを直しても表示の乱れは治らない。 48393 % 48394 % やっぱり何か変な事が起こっている。というか textarea#render の方の問題の気がしてきた…。 48395 48396 →これは全体更新の時に scroll が変化した時に _ble_textarea_scroll 48397 に新しい値を設定し忘れているという textarea#render 側のバグであった。修正した。 48398 48399 2019-01-12 48400 48401 * 2018-10-08 vim: u で戻った時のカーソル位置 [#D0877] 48402 48403 現在の実装では check-dirty と同じ方法を使って切り出しているが、 48404 これだと同じ内容が繰り返されているのを削除した場合にどの部分が削除されたのかを特定できない。 48405 結果として u で戻った時に元の場所ではなくて繰り返し部分の一番最後に移動してしまう。 48406 48407 カーソル位置も一緒に記録して (或いは既に記録していただろうか) 48408 その付近で変更があったと解釈して範囲を特定する事は可能だろうか。 48409 48410 これは vim というよりは edit.sh の ble-edit/undo/.load の実装に関係している。 48411 実際の所、記録を行った時のカーソル位置は一緒に記録されている。 48412 問題は、戻る時に記録を行った時のカーソル位置ではなくて 48413 変更範囲の先頭または末尾にカーソルを移動する時に誤った位置になってしまう事にある。 48414 48415 具体的な例を考える事にする。 48416 48417 例えば "echo abcabc@abcabc world" において 3x とした時にどの位置に戻るのかという事である。 48418 実際に ble.sh で試してみると "echo abcabcabcabc@ world" という状態になる。 48419 ここで元々の index の位置は記録していたはずである。 48420 削除した時に、"echo abcabc@abc world" になっている筈である。 48421 48422 うーん。問題は簡単ではない気がしてきた。 48423 記録されているのは飽くまでその状態に初めてなった時にどの位置にカーソルが居たかである。 48424 従って、変更直前にどの位置にカーソルがいたかは記録されていない。 48425 寧ろ、変更直後のカーソル位置が記録されている。 48426 48427 a なので次に記録されている entry の index から変更位置を探る必要がある。 48428 48429 b しかし、もっとよく分からないのは一気に複数の変更だけ戻した時にどのように振る舞うべきかである。 48430 各ステップの diff を追跡するべきなのだろうか。 48431 もし厳密にやろうとするとそういう事になるはずである。うーん。 48432 48433 c 或いは、戻す直前のカーソル位置に一番近い位置になるように common-prefix/suffix を切るという手。 48434 48435 試しに現在位置と記録位置を境界として、それらより前の部分の先頭一致と、 48436 それらより後の部分の末尾一致を分離してから、改めて先頭一致と末尾一致を取り出す様にしてみた。 48437 しかし、記録位置は最初にその状態になってからの一致だったので、変な位置になってしまう。 48438 48439 ble/string#common-prefix "${_ble_edit_str::_ble_edit_ind}" "${str::ind}"; local p1=${#ret} 48440 ble/string#common-suffix "${_ble_edit_str:_ble_edit_ind}" "${str:ind}"; local s1=${#ret} 48441 local substr1=${_ble_edit_str:p1:${#_ble_edit_str}-p1-s1} 48442 local substr2=${str:p1:${#str}-p1-s1} 48443 ble/string#common-prefix "$substr1" "$substr2"; local p2=${#ret} 48444 ble/string#common-suffix "${substr1:p2}" "${substr2:p2}"; local s2=${#ret} 48445 local beg=$((p1+p2)) end0=$((${#_ble_edit_str}-s1-s2)) end=$((${#str}-s1-s2)) 48446 ble-edit/content/replace "$beg" "$end0" "${str:beg:end-beg}" 48447 48448 記録位置を使わない様に実装し直してみる事にする。 48449 これは結構いい感じに動いている様な気がする。 48450 追記された時のカーソル位置は末端の方が嬉しいのでその様に修正した。 48451 48452 ble/string#common-suffix "${_ble_edit_str:_ble_edit_ind}" "$str"; local s1=${#ret} 48453 ble/string#common-prefix "${_ble_edit_str::_ble_edit_ind}" "${str::${#str}-s1}"; local p1=${#ret} 48454 local substr1=${_ble_edit_str:p1:${#_ble_edit_str}-p1-s1} 48455 local substr2=${str:p1:${#str}-p1-s1} 48456 ble/string#common-suffix "$substr1" "$substr2"; local s2=${#ret} 48457 ble/string#common-prefix "${substr1::${#substr1}-s2}" "${substr2::${#substr2}-s2}"; local p2=${#ret} 48458 local beg=$((p1+p2)) end0=$((${#_ble_edit_str}-s1-s2)) end=$((${#str}-s1-s2)) 48459 ble-edit/content/replace "$beg" "$end0" "${str:beg:end-beg}" 48460 48461 更にコードを整理する。 48462 48463 2019-01-11 48464 48465 * 2019-01-09 確認: set -o posix で ble-detach, ble-attach しても動くのだろうか [#D0876] 48466 →確認した所 ble-attach の冒頭で adjust を実行しているので問題ないはずである。 48467 これについては後で確認することにする。 48468 48469 * reload: ユーザ設定の保持 [#D0875] 48470 48471 * ok: bleopt 変数に関しては問題ない。 48472 48473 * done: 構文着色の設定 48474 ble-color-defface は既に定義されている face の設定は上書きしない。 48475 つまり defface の引数は既定値として解釈する。 48476 48477 * done: ble-sabbrev の設定 48478 48479 * reject: ble-bind に関してはどうしようもない。 48480 そもそも編集関数も更新の対象なので全く更新しないという訳にも行かない。 48481 48482 * done: blerc を再度読み込む等の方法を取らなければならない気がする。 48483 →特に rcfile が指定されない場合は前回使った rcfile を使う様にする。 48484 また rcfile の規定値として ~/.blerc を読み込む事にした。 48485 48486 結局 blerc を自動で読み込む様にしたので、 48487 ユーザ設定の保持についてはそれほど気にしなくても良いような気がする。 48488 48489 * 2019-01-01 アップデート機能? [#D0874] 48490 48491 現在アップデートは git pull して make して make install する、 48492 という様に実行する必要がある。git の事などよく分かっていない人にはこれは難しい。 48493 ビルドしたディレクトリ及び使った INSDIR を覚えておく 48494 (INSDIR は単に _ble_base から算出すれば良い様な気がする)。 48495 - もしビルドしたディレクトリが存在していなければ新しく git clone する。 48496 - git や make や gawk が入っていない場合にはアップデートできない。 48497 48498 或いは自動アップデート機能すらあっても良いのかもしれない。 48499 idle に登録しておいて勝手に background で実行するという事。 48500 48501 取り敢えず ble-update というコマンドを作成してみた。 48502 動いてはいる。しかし、ble-update としても現在のセッションがアップデートされる訳ではなくて、 48503 次に実行した時に反映されるだけである。これは分かりにくい。 48504 やはり複数回 source する事ができるようにするべきだろうか。 48505 48506 [ble.sh の reload に関する議論] 48507 48508 | * 自動リロード: アップデート前のバージョンに対する依存性 48509 | 48510 | | その時、関数内からソースする時はグローバルな連想配列を新しく宣言する事ができない。 48511 | | 元々グローバルな連想配列が存在していれば良いが、 48512 | | 連想配列のそれぞれについて元から存在しているかどうかは、 48513 | | update 前の ble.sh のバージョンにも依存するので臨機応変に対応するのは難しい。 48514 | | 結局 ble.sh を完全に unload してそれから reload するという様な方法を取るようにしないと、 48515 | | バージョン間の差異や相性などに対応することができなくなる。 48516 | 48517 | 完全に unload してそれから reload するという様にする。 48518 | 48519 | * 自動リロード: ユーザ設定の継承 48520 | 48521 | | 一方で、ble-bind や ble-sabbrev や ble-color-setface などの設定はどうなるのか。 48522 | | ble.sh を reload すると完全にクリアされてしまうのだろうか。 48523 | | 内部形式が変更される可能性なども考えると完全にクリアされる仕様にするしかないのか。 48524 | | しかし ble-update しただけで設定が消滅してしまうというのも悲しいことである。 48525 | 48526 | その様に考えれば幾つかの設定項目に関しては、内部形式のバージョンを定義し、 48527 | 内部形式の更新があればそれに応じて設定を書き換えるという仕組みが必要になる。 48528 | 48529 | 因みにリロードに関する議論は以前にもあったが棄却されている (#D0685) 48530 | 其処での考察では Bash 3.0 の C-d 受信用の子プロセスの削除、 48531 | 及び、stdout/on stdout/off などの状態についての考察があった。 48532 | 更に、ble.sh が特別の用途で使っている fd についても閉じる様にした方が良いのではないか。 48533 | 48534 | * openat を用いて開いた fd は抜ける時に全て閉じるようにする。 48535 | openat の内部で実際に開いた fd の番号を記録しておくことにする。 48536 | また exec による新しい fd は全て openat 経由で開く事にした。 48537 | これにより fd が重複したりするのを防ぐ。 48538 | 48539 | x openat でユーザが開いた物を勝手に閉じたら都合が悪いのではないか。 48540 | ユーザが開いた物ではなくても、update 時に保持しておきたい fd はないのか。 48541 | これは openat の呼び出し元を一つ一つ確認する必要がある。 48542 | 初期化時に開くような種類の物であれば問題はない。 48543 | 48544 | * Bash 3 の C-d 受信のためのプロセスは openat で開かれた fd 経由で通信している。 48545 | 試しに該当する fd を exec 32>&- として閉じてみたら受信のためのプロセスは終了した。 48546 | つまり、上記の openat に対する処置で自動的にこちらもちゃんと unload される事になる。 48547 | 48548 | * stdout/{on,off} の状態や端末の状態に関しては 48549 | 48550 | | ble-detach した上でリロードすれば良い。 48551 | | 但し、ble-detach は detach の予約をするだけなので… 48552 | | 具体的にはどの関数であろうか。 48553 | | .check-detach まで呼び出してしまわなければならないのか。 48554 | | うーん。或いは…ble-detach を実行して、更にその後で…。 48555 | | たぶん、.check-detach でリロードを実行する機能を追加すれば良い。 48556 | | 48557 | | リロードが起こる状況には二種類ある。 48558 | | 手で source ble.sh を実行した時。 48559 | | それから ble-update を実行した時。 48560 | | 更にそれぞれ ble attach 中かそうでないかという状態が存在する。 48561 | | 48562 | | attach 中は、その場で ble.sh を source するのは難しいのではないか。 48563 | | source するべき ble.sh の位置を覚えておいて、 48564 | | それを .check-detach の中で source するようにするか。 48565 | | 48566 | | detach している時は、その場で ble.sh を source してしまった良いものだろうか。 48567 | | ble.sh のロード時に既に ble.sh がロードされて detach 状態である事を検出して、 48568 | | その時に、色々の後始末をする処理を実行する様にすれば良い。 48569 | 48570 | 整理すると。 48571 | 48572 | source ble.sh をした時点で ble.sh の冒頭で、 48573 | 既に ble.sh がロードされている事を検出して、 48574 | 48575 | a attach している場合には .check-detach でリロードする予約をして取り敢えず抜ける。 48576 | .check-detach の中では ble.sh のアンロード処理を実行して、 48577 | その上で改めて ble.sh を呼び出す事にする。 48578 | b detach している場合には、中でアンロード処理を実行して 48579 | ble.sh の続きを実行すれば良い。 48580 | 48581 | 何れの場合でも「アンロード処理」を実装すれば使い回せる。 48582 | 48583 | * trap '...' EXIT で実行されるべき操作はしなくてよいのか? 48584 | ble/term/TRAPEXIT の中では stty の調整、一時ファイルの削除など、色々やっている。 48585 | これは呼び出しておいた方が良い様な気がする。 48586 | 48587 | 更に言うと ble/term/TRAPEXIT の中を見ると _ble_base_run の処理もここでやっている。 48588 | これは unload という関数でも用意してそれを EXIT に登録するべきなのではあるまいか。 48589 48590 [まとめ] 48591 48592 - 完全に unload してから ble.sh を再度読み込むことにする。 48593 - ユーザ設定の継承は改めて行う必要がある 48594 (特に ble-bind に関しては議論が必要である)。 48595 - unload で必要なのは特に detach することと openat で開いた物を閉じること。 48596 既存の ble/term/TRAPEXIT の関数を実行すること。 48597 - %%detach は .check-detach 経由で実行する必要がある。%%→これは棄却 48598 48599 [実装] 48600 48601 * done: ble/term/TRAPEXIT の処理を ble/base/unload 関数に移行する。 48602 * done: ble/base/unload にその他のアンロード処理を実装する。 48603 特にopenat で開いた fd を閉じる 48604 48605 * reject: .check-detach に reload 機能を追加する 48606 48607 試しに強制的に呼び出してみた所、遅延ロード関数が全部駄目になっている…。 48608 うーん。何が起こっているかと言うと…遅延ロード様に関数が上書きされて、 48609 遅延ロード用関数はファイルを読み込もうとするが、 48610 遅延ファイルは既に実行されたと思ってスキップするという事だろうか…。 48611 48612 % 取り敢えず autoload において既に関数が存在している場合には何もしないようにした。 48613 % しかし、それでも色々の物が動いていない。 48614 % →autoload はやはり関数を上書きするべきである。 48615 % 問題は autoload ではなくて ble-import の読み込み済みの 48616 % ファイルのキャッシュが残っていた事にあった。 48617 48618 先ず構文着色が動いていない。予測補完も動いていない。うーん。 48619 取り敢えずこれらについては後で対処する事にすれば良さそうである。 48620 48621 x done: .check-detach 経由の reload は実行順序が保たれず問題が起こる 48622 48623 うーん。.check-detach 経由で unload する様にすると 48624 source ble.sh 前後の処理との順番が入れ替わってしまう為に変な事になる。 48625 やはりその場で detach/unload/source して何事もなかったかの様に継続できないだろうか。 48626 その様にしてみたら ble.sh attach 直後に epilogue が実行されて 48627 PS1 やその他の端末の状態がおかしくなってしまった。 48628 48629 というか ble-detach; ble-attach した時にも同様の問題が起こるのではないか? 48630 →試してみたら再現した。従って、それも考えてちゃんと実装する必要がある。 48631 (しかし何故再現するのか今ひとつよく分からない。ble-detach を実行しても 48632 その場では detach されなかったはずである…。) 48633 うーん。実装を確認したら _ble_attached の値でガードしているが、 48634 ble-detach がその場で処理を実行しないために色々変な事になっている。 48635 _ble_attached の値は ble-detach の中ではなくて .check-detach の方で設定するべきである。 48636 48637 a 一つの方法は eval-epilogue を抑制する機能をつけること。 48638 しかしどの様な条件で抑制するのだろうか。 48639 source ble.sh して ble-attach した時? 何だかよく分からない。 48640 b 或いは PS1 の設定のinternal/externalの状態を記録して退避を行うという事。 48641 というのも eval-epilogue を観察すると、その他の物については 48642 既に internal/external の記録をしているか二重に実行しても問題ないものばかりの気がするからである。 48643 48644 * done: PS1 の二重退避は解決した。 48645 * done: ble-detach/ble-attach の _ble_attached= の管理はどうするか。 48646 48647 やはり ble-detach; ble-attach の実行は自然になって欲しい。 48648 すると ble-detach で flag は設定したけれど未だ実際には detach していない、 48649 という様な状態の時には ble-attach は単に flag を削除するだけにするという手がある。 48650 →その様に実装したら実際に良さそうである。動いている。 48651 48652 * done: 直接 source ble.sh できる様にする。 48653 * done: ble-update で最後に source する様にする。 48654 48655 [現状の問題点] 48656 48657 | * 構文着色が無効になっている 48658 | 48659 | 調べてみると ble-color/faces/initialize が呼び出されていない。 48660 | というかそもそも構文着色の処理が呼び出されていない様な。 48661 | 試しに source $_ble_base/lib/core-syntax.sh を実行してみたら着色が有効になった。 48662 | これはつまり単に core-syntax が呼び出されていないのが原因だった。 48663 | 48664 | しかし、補完や help を実行しても core-syntax.sh が呼び出されないのは何故だろう…。 48665 | と思ったが、よく考えたらこれは autoload で上書きを防ぐようにしたのが問題である。 48666 | そもそも reload したのだから上書きするべきなのではないだろうか。。 48667 | 48668 | * ble_debug=1 として見たが何も表示されない…何事だろう。 48669 48670 * done: ble-import を修正したら呆気なく動く様になった。 48671 48672 * done: ble-edit/bind/load-keymap-definition:$defmap も unload 時に clear する事にした。 48673 48674 未だユーザ設定の保持については実装していないが、また複雑になりそうなので、 48675 取り敢えずは commit して確定する事にする。 48676 48677 2019-01-08 48678 48679 * 2019-01-04 "bash -i -c command" などとして起動した時に、コマンドの実行結果が出力されない [#D0873] 48680 48681 そもそもコマンドを実行するのに -i を指定する必要があるのかという問題もあるが、 48682 その様な事が可能である (例えば interactive session の起動時間を測る目的などで) 48683 という事なので考察しておく必要はあるように思う。 48684 48685 実行結果が出力されないのは bashrc を呼び出して以降プロンプトが表示されるまで 48686 の間にコマンドが実行されるからである。ble.sh の場合にはその間は出力を抑制する 48687 為にコマンドの出力結果は表示されない。 48688 48689 [実装方法] 48690 48691 もし bash -i -c command とした時にそのまま終了せずに対話状態になるのであれば、 48692 始めのコマンドの実行時またはユーザ入力時に抑制された内容を調べて 48693 それを標準出力へ流すことも可能だが、実際にはそのまま終了してしまうのでその機会はない。 48694 48695 代わりに bash -i -c command の形式で起動されたことを検出して、 48696 その場合には ble.sh をロードしない様にすることは可能なのだろうか。 48697 例えば bash の環境変数またはシェル変数に引数が入っていればそれを解析できるだろうか。 48698 試しに実行してみた所、以下のように BASH_EXECUTION_STRING なる変数が設定されている事が判明した。 48699 48700 $ bash -i -c 'set | grep fasdf >/dev/tty' 48701 BASH_EXECUTION_STRING='set | grep fasdf >/dev/tty' 48702 48703 この変数は通常の起動の仕方をした時にはそもそも存在していないようだ。 48704 この変数 BASH_EXECUTION_STRING が導入されたのは Bash 3.0 の様なので問題ない。 48705 48706 [実装] 48707 48708 BASH_EXECUTION_STRING が設定されている時は ble.sh をそのまま抜ける事にした。 48709 48710 * 2018-09-26 実は set -o posix に対する制限は外せる気がする [#D0872] 48711 但し、posix に対しても ble を実行するべきなのかという問題はある。 48712 起動時にはチェックするけれども、 48713 実行中に変更された場合には対応するという方針でも良い気がする。 48714 48715 % _ble_edit_bind_force_draw=1 も考慮に入れる必要がある。 48716 % →これは廃止したので気にしなくて良い。 48717 % 追記: 一応 #D0324 に導入の経緯の議論があった 48718 48719 2019-01-08 調べてみると set -o posix を実行すると 48720 POSIXLY_CORRECT に y が入るし、 48721 POSIXLY_CORRECT が設定されていると [[ -o posix ]] が有効になるようだ。 48722 つまり変数 POSIXLY_CORRECT だけ観察していれば対応できた事になるのではないか。 48723 つまり現在の実装で殆ど対応できているような気がする。 48724 48725 問題は adjust-POSIXLY_CORRECT のタイミング? 48726 最後に restore して ble.sh を抜けて、 48727 いざ attach する時に adjust-POSIXLY_CORRECT を実行するべきではなかろうか。 48728 48729 {adjust,restore}-POSIXLY_CORRECT を連続して実行したりしても大丈夫な設計になっていただろうか。 48730 見た感じだとなっていない気がする…。呼び出し元を観察すると必ずペアになっているので、 48731 単にそのような状況を想定していなかったのだろう。しかし、何かトラブルなどがあったりすると、 48732 ペアにならなかったりするので本当はちゃんと現在の状態 (adjusted/restored) を記録する必要がある。 48733 48734 * POSIXLY_CORRECT=y でコマンドを実行すると unset : でエラーメッセージが出る [#D0871] 48735 このエラーメッセージは殺しても良いのではないか。 48736 というよりエラーメッセージが出ないようにしたのではなかったか。 48737 48738 ref #D0722 48739 48740 2019-01-01 48741 48742 * 2018-10-03 complete: "type" の補完指定が効いていない [#D0870] 48743 ref #D0714 #M0009 48744 48745 調べると complete -c type になっている。 48746 調べたら compv_quoted で '' の中に名前を指定すると駄目の様だ。 48747 これについては一度確認したような気がするが、その時はどのような結論になったのだったか。 48748 48749 #M0009 に記録が残っている。-A command,directory,file は駄目だそうだ。 48750 これは command,directory,file が補完に含まれる時にはクォートしないという方法を取る事にした。 48751 他の種類の補完候補が含まれている場合やチルダが含まれている時に問題になるかもしれないが仕方がない。 48752 48753 * [自然解消] vi: operator d の特殊ルールは v で適用されるのか? [#D0869] 48754 48755 % 少し動かしたら適用されている様な…。後で確認する必要がある。 48756 48757 2018-12-26 operator d の特殊ルールとは何だったか。。 48758 うーん。これは ble/keymap:vi/operator:d の charwise の箇所で 48759 実行されている処理のことのはずである。 48760 48761 * o_v で適用されるか 48762 48763 % 試しに動かしてみる。 48764 % | AAAAAAAA$ 48765 % | echo$ 48766 % | world $ 48767 % | BBBBBBBB$ 48768 % 48769 % vim, blesh: e の位置で d2e とすると2行消える。 48770 % vim: e の位置で dv2e とすると echo\nworl が削除される。 48771 % blesh: e の位置で dv2e とすると echo\nworld が削除される。 48772 % つまり、operator d の特殊ルールは適用されなくなるが、 48773 % そもそも v の時の適用範囲が誤っている…。 48774 % 48775 % % これは実は xmap のルーチンを流用して来た方が正しいのかもしれない…。 48776 % % と思って xmap の時の処理を確認したら 48777 % % 処理は ble/widget/vi-command/operator で行われていて、 48778 % % 寧ろ処理の範囲は縮小されるのではなくて拡張されていた…。逆である。 48779 % % なので xmap は恐らく o_v の動作には関係ない。 48780 % 48781 % 寧ろ :help o_v の方に説明が書かれているかもしれない。 48782 % o_v の説明を読むと exclusive/inclusive を切り替えると書かれている…。 48783 48784 o_v に関しては別に実装する事にした。 48785 inclusive/exclusive の切り替えもちゃんと実装したら動作は一致する様になった。 48786 48787 * v (xmap/smap) で適用されるか 48788 48789 | AAAAAAAA$ 48790 | echo$ 48791 | world $ 48792 | BBBBBBBB$ 48793 48794 以上の e の位置で vjd とすると、vim でも ble.sh でも空白4つを残して他は消えた。 48795 どのような振る舞いになっているか考えるのは面倒だがちゃんと動いている。 48796 恐らく規則によって先頭の space 類は残したまま行指向になるのだろう。 48797 何れにしても既に一致した振る舞いになっているので気にしない事にする。 48798 48799 * vi (omap `v`): dd や yy 等の場合にも omap v/V/C-v を適用する [#D0868] 48800 48801 dd や yy などの時にも間に v や V 等挟んでも良いのだろうか。 48802 48803 vim で試してみると dvd は行頭までの削除になって、 48804 dC-vd は現在位置から行頭までの削除 (inclusive) になる。 48805 dVd は同じ振る舞いである。 48806 しかし ble.sh では dvd 等と別の物が間に挟まっているとエラーになる。 48807 48808 実装した。テストした。動いている。OK 48809 48810 * vi (omap `v`): charwise の inclusive/exclusive を toggle する [#D0867] 48811 48812 :help o_v によると元から charwise の時には 48813 inclusive/exclusive を切り替えるとの事。 48814 48815 | さて問題は ble.sh の実装では全て exclusive と想定して 48816 | 実装しているという事である。 48817 | 従って、現在 inclusive なのか exclusive なのか、 48818 | 呼び出された側からは判定する事ができない。 48819 | 或いは、常に exclusive だと思って置けば良いのだろうか。 48820 | 改行が絡んでいる時にはどうしたら良いのだろうか…。 48821 | 48822 | 更に、inclusive/exclusive というのも opfunc 内に 48823 | 記録しなければならないという事になる。 48824 | 48825 | うーん。ble.sh における inclusive/exclusive に関する考察が 48826 | 何処かにあったような気がするがすぐには見つからない。 48827 | 取り敢えず #D0437 に多少の議論があるが、 48828 | もっと後に何か考察したような気がする。 48829 | 48830 | 改めて inclusive/exclusive について考える事にする。 48831 | exclusive-range.impl が charwise で呼び出される時の問題である。 48832 | というか exclusive-range.impl は元々 charwise で呼び出されるのであった。 48833 | 48834 | inclusive の物は数が限られているので inclusive である物を列挙する事にする。 48835 | $ (行末) g$ (表示上の行末) g_ (最後の非空白文字) fx tx (検索) 48836 | e E ge gE (単語末尾) % (括弧やコメント等の検索) 48837 | 取り敢えず https://vim-jp.org/vimdoc-ja/motion.html に載っているのはこれだけである。 48838 | 48839 | 一方で exclusive-linewise の判定ではどのようにしているのか。 48840 | exclusive-linewise は exclusive の時にだけ有効になる筈なのではないか。 48841 | どのように判定しているのか。exclusive-linewise で検索すると、 48842 | #D0565 で exclusive-linewise が実装されていて、 48843 | その記述によると exclusive は exclusive-goto.impl -> exclusive-range.impl と呼び出され、 48844 | inclusive は inclusive-goto.impl -> exclusive-range.impl と呼びされるので、 48845 | exclusive-linewise は exclusive-goto.impl で実装すれば良いとのこと。 48846 | 実際に確認してみるとその様になっている。 48847 | 48848 | とすれば…inclusive-goto.impl で書き換えれば良いという事になる。 48849 | 本当だろうか。一応上記の inclusive なコマンドがどの様に実装されているかを確認していく。 48850 | - $ 及び g$ と g_ ... 確かに inclusive-goto.impl を呼び出している。 48851 | - fx 及び tx に関しても確かに inclusive-goto.impl を呼び出している。 48852 | - e E ge gE についても inclusive-goto.impl を呼び出している。 48853 | - % (search-matchpair-or) も inclusive-goto.impl を呼び出している。 48854 48855 結論: ble.sh の実装では exclusive な motion は、 48856 exclusive-goto.impl -> exclusive-range.impl で呼び出される。 48857 inclusive な motion は 48858 inclusive-goto.impl -> exclusive-range.impl で呼び出される。 48859 従って exclusive/inclusive 毎の操作は 48860 exclusive/inclusive-goto.impl で実装する事になる。 48861 現に exclusive-linewise の機能は exclusive-goto.impl の中で実装されている。 48862 48863 これについては #M0011 に記録を残して置く事にする。 48864 48865 | v に対して opfunc 内で偶奇性を保持する様に修正すれば toggle はできる。 48866 | さて、問題は修正をどの場所で行うのかという事になる。 48867 | inclusive の時にも exclusive の時にも修正を行う必要がある。 48868 | そして exclusive-range.impl の呼び出し元は実は 48869 | exclusive/inclusive-goto.impl だけではなくて沢山ある。 48870 | うーん。実は exclusive-range.impl 側で処理した方が良いのではないか。 48871 | inclusive の時だけは元々 inclusive な motion であるという情報を 48872 | exclusive-range.impl に何らかの方法で伝達する必要がある。 48873 | 48874 | うーん。第5引数に nobell を受け取っているがこれを opts に変更できないだろうか。 48875 | 使用箇所を確認してみると2箇所でしか nobell は指定していない。 48876 | そしてそれは exclusive-goto.impl 及び inclusive-goto.impl である。 48877 | これらを検索するとこれは呼び出し時に確定している様子である。 48878 | 従って、nobell を指定する様に変更してしまって良いだろう。 48879 | →opts に変更する事にした。 48880 48881 結論: exclusive-range.impl の第5引数を nobell から opts に拡張する事にする。 48882 これを通して exclusive-range.impl に inclusive を伝達する事にする。 48883 48884 * vim における exclusive/inclusive の動作について確認する。 48885 Fh で後退した場合に起点 (終端点) は inclusive に変換されるのか。 48886 実際に vim で試してみた所 g~Fh では起点は作用対象にならない (exclusive) だが、 48887 g~vFh とすると起点も作用対象になった (inclusive)。 48888 つまり、exclusive/inclusive の別は行き先に対して実行されるのではなくて、 48889 飽くまで範囲の終端点に対して実行されるのである。 48890 48891 [実装] 48892 48893 - done: v に対して偶奇を保持する様に修正 48894 - done: exclusive-range.impl の第5引数に opts を受け取る様に修正 48895 - done: exclusive-range.impl に於いて vi_char1 の時は exclusive/inclusive を反転する 48896 48897 [動作確認] 48898 48899 x fixed: vim の動作を調べてみた所…toggle すると書いてあったが、 48900 v を押す度に反転するという訳ではなくて、 48901 v を一回でも押したら反転したものになって、それ以降は変わらない様だ。 48902 つまり vi_char の偶奇性を判定する必要は全くなかった。 48903 偶奇のコードは削除する事にした。 48904 48905 o linewise の時の動作は正しいか。例えば g~vj でどう振る舞うべきか。 48906 vim でどう動くか試してみる。→ exclusive である。g~vvj としても同じ。 48907 ble.sh の現在の実装での振る舞いもちゃんと一致している。OK 48908 48909 * vi (omap `v`): linewise-range.impl の時も charwise/blockwise に変換する [#D0866] 48910 48911 g?j などは linewise-range で呼び出されるが、 48912 その時でも exclusive charwise に変換するとの事。 48913 48914 こちらの方が対処が簡単そうなので先に処理する事にする。 48915 48916 実装を調べてみるとよく分からない事が出てくる。 48917 linewise-range で charwise/blockwise とする時、 48918 終点と始点はどの様にしたら良いのだろうか。 48919 例えば現在の処理の通りに行頭と行末にしてしまうと、 48920 結局 linewise と同じになってしまう。 48921 しかし実際に vim でやってみると j の時には、 48922 その移動先までという事になっている。 48923 また vim + でやってみると行頭までという事の様だ。 48924 もっとちゃんと調べると非空白行頭になっている。 48925 48926 * ok: もう一つ気付いたのは C-v の時、 48927 開始位置を inclusive に含むという事である。 48928 しかし、これは実のところ普通の xmap の振る舞いと同じではある。 48929 調べてみると extract-block がちゃんと inclusive に右端を拡張する様になっている 48930 様子なのでこれについては気にしなくても良い。 48931 最後に実装が終わってから期待した動作になっているかを確認すれば良い。 48932 48933 現在の実装ではオペレータがある時には、 48934 どの行移動についても同じ様に処理してしまっているが、 48935 実際の所は移動のそれぞれについてオペレータの動作も異なるという事。 48936 48937 どの様に実装するのが正しいのだろうか。 48938 行き先を決定してから call-operator-linewise に渡すのが良いのか。 48939 これは linewise-range.impl を利用している複数の機能について調べて 48940 最も都合の良い方法を選択する必要がある。 48941 48942 a 一つの方法は relative-line.impl の側で flag を見て、 48943 もし char/block だった場合にはそちら側で処理してしまうという方法である。 48944 b もう一つの方法は何れにしても relative-line.impl の側で 48945 位置を決定してから linewise-range.impl を呼び出すという物である。 48946 c 或いは、linewise-range.impl の中から 48947 relative-line.impl を呼び出して位置を決めるという手もある。 48948 d というか relative-line.impl の位置を決定するコードだけ分離すれば良い。 48949 48950 取り敢えず d の方法が良い様な気がする。 48951 実際にこの方法を取らないとしてもコードの整理として、 48952 relative-line.impl の行き先を決定する関数はあって良い気がする。 48953 48954 [実装] 48955 48956 1 done: relative-line.impl の行き先を決定する関数の抽出 48957 と思ったが微妙である。relative-line の場合には、 48958 移動先の行がない場合 (最終行または第1行を超えて移動しようとする時) には、 48959 はみ出た行数の分だけ履歴行を移動する。はみ出た行数の計算を 48960 行き先を決定する関数の内部で実行している。 48961 初めに行数を数えてから行き先の計算を実行する様に変更したい。 48962 →取り敢えず実装した 48963 2 done: linewise-range.impl の実装 48964 relative-line.impl ではなくて先の項目で作成した 48965 get-index-of-relative-line という関数を使う様に修正した。 48966 更に charwise/blockwise の時の範囲の計算も適切に実装した。 48967 48968 [動作確認] 48969 48970 x fixed: jk などの relative-line.impl の動作がおかしくなっていないか。 48971 →見事に動かなくなっている。確認する必要がある。 48972 一箇所直した。j は動く様になった。しかし k が動かない。 48973 →もう一箇所直した。取り敢えずちゃんと動いている。 48974 48975 x fixed: guvj 等が動作するか。 48976 動かない…次の行頭までになっている。 48977 →これも簡単なミスだった。修正した。 48978 48979 o C-v の時右端が inclusive になっているか。 48980 これはちゃんと動いた。 48981 48982 48983 2018-12-31 48984 48985 * 2018-10-08 vi (omap v): o_v o_V に対応する? [#D0865] 48986 オペレータの振る舞いに影響を与える。 48987 詳しくは help o_v と help o_V を参照すれば良い。 48988 オペレータ d の charwise の時の特別な振る舞いも無効化する。 48989 48990 実際に試してみて分かった振る舞いについて以下にまとめる。 48991 - omap C-v も効いている。 48992 - omap v, V, C-v を実行しても表示は変わらない。 48993 48994 [実装方針に対する考察] 48995 48996 現在の状態をどのように保持するのが良いのかという考察。 48997 48998 | どの様に実装するのか。 48999 | ble/keymap:vi/operator を見る。omap の時にはそもそも operator は呼び出されない。 49000 | nmap で operator が呼び出されると opfunc が設定されて、 49001 | それを元にして移動などが起こった時に実際の動作に入るのである。 49002 | そして、コメントを見ると恐らく opfunc と同等の変数として新しく opmark をつける予定だった。 49003 | 49004 | 他の実装方法はないのだろうか。というのも opfunc や oparg と同様に実装すると、 49005 | また新しく変数を追加する事になってしまい、管理がまた大変になりそうだからである。 49006 | 49007 | a opfunc に付加する形にするのは難しい。というのも opfunc は二文字以上も可能にしているから。 49008 | 一応 opfunc に使える文字の種類を限定して : で区切って付加情報も記録できる様にする事も可能かもしれないが、 49009 | それはそれで大変である。 49010 | b では oparg に記録する事は可能だろうか。 49011 | oparg はそのまま _ble_edit_arg をコピーする事によって値が設定されている。 49012 | また、記録していた物を再生する時には ARG がそのまま _ble_keymap_vi_optarg に設定されている。 49013 | やはり面倒そうな気がする。もし oparg に記録するとしても ARG に情報を伝達すると、 49014 | ARG を整数として扱っている数々の関数で問題が起こる事になる。 49015 | 何れにしても ARG FLAG REG に新しい変数を追加するか、 49016 | 或いは ARG FLAG REG とは別に local _ble_keymap_vi_opmark なる変数を用意して、 49017 | それを経由して値を伝達するという事になる気がする。 49018 | c 新しく変数を作成するとしたら oparg と並列になる様に変数を作成すれば良い様な気がする。 49019 | しかし、その時に ARG FLAG REG の3変数に更に新しい変数を追加する事になるのだろうか。。 49020 | 或いはグローバルの変数を経由して operator を呼び出せば良いのだろうか。 49021 | グローバルの変数を経由して呼び出す場合には入れ子で operator を呼び出した時にどうなるのか。 49022 | (というかそもそも入れ子で operator を呼び出すという事があるのかどうかも分からないが…) 49023 | 49024 | うーん。色々考えてみると実は opfunc/FLAG の中に情報を格納する方針の方が良い様な気がしてきた。 49025 | opfunc 及び FLAG はどの様に使われているだろうか。 49026 | 使用方法を調べてみると FLAG は上に伝達する時にしか使われていない気がする。 49027 49028 結論: 取り敢えず opfunc 及び FLAG を拡張する方向で考えてみる事にする。 49029 49030 opfunc/FLAG を拡張するという方針で問題がないかの考察。 49031 49032 | done: FLAG を渡されている関数は以下の通りである。 49033 | 49034 | - ble/keymap:vi/text-object.impl "$ARG" "$FLAG" "$REG" "$type" 49035 | これは辿っていくと (flag が使用される場合には) 何れも以下の何れかに帰着する。 49036 | -> ble/widget/vi-command/exclusive-range.impl "$beg" "$end" "$flag" "$reg" 49037 | -> ble/widget/vi-command/linewise-range.impl "$beg" "$end" "$flag" "$reg" goto_bol 49038 | - ble/widget/vi-command/backward-word-end.impl "$ARG" "$FLAG" "$REG" "$_ble_keymap_vi_REX_WORD" 49039 | -> ble/widget/vi-command/inclusive-goto.impl "$index" "$flag" "$reg" 49040 | - ble/widget/vi-command/backward-word.impl "$ARG" "$FLAG" "$REG" $'[^ \t\n]+' 49041 | -> ble/widget/vi-command/exclusive-goto.impl "$index" "$flag" "$reg" 49042 | - ble/widget/vi-command/forward-word-end.impl "$ARG" "$FLAG" "$REG" "$_ble_keymap_vi_REX_WORD" 49043 | -> ble/widget/vi-command/inclusive-goto.impl "$index" "$flag" "$reg" 49044 | - ble/widget/vi-command/forward-word.impl "$ARG" "$FLAG" "$REG" $'[^ \t\n]+' 49045 | -> ble/widget/vi-command/inclusive-goto.impl "$index" "$flag" "$reg" 49046 | -> ble/widget/vi-command/exclusive-goto.impl "$index" "$flag" "$reg" 49047 | - ble/widget/vi-command/goto-mark.impl "$index" "$FLAG" "$REG" "$opts" 49048 | -> ble/widget/vi-command/linewise-goto.impl "$index" "$flag" "$reg" 49049 | -> ble/widget/vi-command/exclusive-goto.impl "$index" "$flag" "$reg" 1 49050 | - ble/widget/vi-command/graphical-relative-line.impl "$ARG" "$FLAG" "$REG" 49051 | -> ble/widget/vi-command/exclusive-goto.impl "$index" "$flag" "$reg" 49052 | - ble/widget/vi-command/relative-first-non-space.impl 0 "$FLAG" "$REG" charwise 49053 | -> ble/widget/vi-command/exclusive-goto.impl "$nolx" "$flag" "$reg" 1 49054 | -> ble/widget/vi-command/linewise-goto.impl "$nolx" "$flag" "$reg" require_multiline:bolx="$bolx":nolx="$nolx" 49055 | - ble/widget/vi-command/relative-line.impl $((-ARG)) "$FLAG" "$REG" history 49056 | -> ble/widget/vi-command/linewise-goto.impl "$_ble_edit_ind:$offset" "$flag" "$reg" preserve_column:require_multiline 49057 | 49058 | 結局諸々の関数の呼び出しは以下の関数に帰着するようにである。 49059 | 49060 | - ble/widget/vi-command/exclusive-goto.impl "$beg" "$FLAG" "$REG" 1 49061 | -> ble/widget/vi-command/linewise-goto.impl "$index" "$flag" "$reg" 49062 | -> ble/widget/vi-command/exclusive-range.impl "$_ble_edit_ind" "$index" "$flag" "$reg" "$nobell" 49063 | - ble/widget/vi-command/inclusive-goto.impl "$index" "$FLAG" "$REG" 1 49064 | -> ble/widget/vi-command/exclusive-range.impl "$_ble_edit_ind" "$index" "$flag" "$reg" "$nobell" 49065 | - ble/widget/vi-command/linewise-goto.impl 0:$((iline-1)) "$FLAG" "$REG" 49066 | -> ble/widget/vi-command/linewise-range.impl "$_ble_edit_ind" "$@" 49067 | 49068 | 更に以下の関数に委譲されている。 49069 | 49070 | - ble/widget/vi-command/linewise-range.impl 49071 | 49072 | | ((end<${#_ble_edit_str}&&end++)) 49073 | | if ! ble/is-function ble/keymap:vi/operator:"$flag"; then 49074 | | ble/widget/vi-command/bell 49075 | | return 1 49076 | | fi 49077 | | 49078 | | # オペレータ呼び出し 49079 | | ble/keymap:vi/call-operator "$flag" "$beg" "$end" line '' "$reg"; local ext=$? 49080 | | if ((ext)); then 49081 | | ((ext==148)) && return 148 49082 | | ble/widget/vi-command/bell 49083 | | return "$ext" 49084 | | fi 49085 | 49086 | 主に以上の箇所 $flag で使用されている。 49087 | 先ず初めに operator:$flag に関しては修正が必要である。 49088 | 後ろの方で $flag == [cd] という判定があるこれも修正が必要である。 49089 | 更に良く考えてみるとこの関数は linewise の関数なので、 49090 | flag に charwise や blockwise が設定されていたとしても 49091 | linewise として処理を実行しなければならないのではないか。 49092 | 49093 | call-operator の実装について確認しておく事にする。 49094 | call-operator の実装では第一引数をそのまま vi/operator:$1 の様に呼び出すのに使っている。 49095 | つまり、何れにしても operator 名で呼び出さなければならないのである。 49096 | また、linewise-range から call-operator-linewise を呼び出すのではなくて、 49097 | 直接に call-operator を呼び出しているのは、呼び出し元で行指向にする処理をしているからである。 49098 | 49099 | 従ってこの部分は単に演算子名にすれば良いのである。 49100 | 49101 | - ble/widget/vi-command/exclusive-range.impl 49102 | これは以下の箇所で使われているのみである。 49103 | 49104 | | ble/keymap:vi/call-operator-charwise "$flag" "$src" "$dst" '' "$reg"; local ext=$? 49105 | 49106 | さて今から実行しようとしている事は何かというと、 49107 | この call-operator-charwise を現在記録されている矩形の種類に置き換えるという事である。 49108 | 49109 | ok: その他の FLAG の気になる使い方をしている箇所は以下の通りである。 49110 | 49111 | - ./keymap/vi.sh:2381: if [[ $FLAG ]]; then 49112 | - ./keymap/vi.sh:2576: if [[ $FLAG || $_ble_decode_keymap == vi_[xs]map ]]; then 49113 | - ./keymap/vi.sh:2601: if [[ $FLAG || $_ble_decode_keymap == vi_[xs]map ]]; then 49114 | - ./keymap/vi.sh:3380: [[ $FLAG ]] || ble/keymap:vi/mark/set-jump # `` 49115 | - ./keymap/vi.sh:3386: [[ $FLAG ]] || ble/keymap:vi/mark/set-jump # `` 49116 | - ./keymap/vi.sh:3393: if [[ $FLAG ]]; then 49117 | - ./keymap/vi.sh:3418: if [[ $FLAG ]]; then 49118 | - ./keymap/vi.sh:3444: [[ $FLAG ]] || ble/keymap:vi/mark/set-jump # `` 49119 | - ./keymap/vi.sh:3765: [[ $FLAG ]] || ble/keymap:vi/mark/set-jump # `` 49120 | - ./keymap/vi.sh:4764: if [[ $FLAG || $_ble_decode_keymap == vi_[xs]map ]]; then 49121 | - ./keymap/vi.sh:4777: if [[ $FLAG ]]; then 49122 | - ./keymap/vi.sh:5833: if [[ $FLAG ]]; then 49123 | - ./keymap/vi.sh:5893: if [[ $FLAG ]]; then 49124 | - ./keymap/vi.sh:6013: if [[ $FLAG ]]; then 49125 | - ./keymap/vi.sh:6096: if [[ $FLAG ]]; then 49126 | - ./keymap/vi.sh:6518: if [[ $FLAG ]]; then 49127 | これらは基本的に FLAG に opname が指定されているかどうかだけを確認している。 49128 | opfunc を拡張するとしても既に何か設定されている時にのみ ~wise を付加するのだから関係ない。 49129 | 問題は具体的に値を使って何かを実行する時だけのはずである。なのでこれらは気にしなくて良い。 49130 | 49131 | - ./lib/vim-surround.sh:690: local WIDGET=ble/widget/vim-surround.sh/nmap/csurround.repeat ARG=$arg FLAG= REG=$reg 49132 | これは FLAG を空にするという動作であって、 49133 | ~wise は FLAG が非空の時にのみ意味があるのでこれで良いのである。 49134 | 49135 | - ./keymap/vi.sh:649: FLAG=$_ble_keymap_vi_opfunc 49136 | - ./keymap/vi.sh:3399: _ble_keymap_vi_opfunc=$FLAG 49137 | - ./keymap/vi.sh:3419: _ble_keymap_vi_opfunc=$FLAG 49138 | - ./keymap/vi.sh:3724: _ble_keymap_vi_opfunc=$FLAG 49139 | opfunc と FLAG は一致する扱いとすればこれで良い。 49140 | 49141 | - ./keymap/vi.sh:2469: local -a repeat; repeat=("$KEYMAP" "${KEYS[*]-}" "$WIDGET" "$ARG" "$FLAG" "$REG" '') 49142 | つまり 4 番目の要素に FLAG が格納される。調べてみるとこれが実際に使われるのは 49143 | ./keymap/vi.sh:2531: _ble_keymap_vi_opfunc=${_ble_keymap_vi_repeat[4]} 49144 | という箇所のみであり、これも opfunc と FLAG が一致しているという前提の下で気にしなくて良い。 49145 | 49146 | 2018-12-31 少し時間を置いたら分からなくなった。今の状況を整理する事にする。結局、 49147 | 1. FLAG が空文字列かどうかを判定している箇所は、FLAG の内容の形式が変更されても問題はない 49148 | 2. FLAG の内容を記録している部分についても、FLAG の内容の形式には関係ないので問題ない 49149 | 記録時に FLAG の内容によって動作が変わるなどのことはしていないので問題ない。 49150 | また、記録される内容も v だったか V だったか C-v だったかまで一緒に記録するのが自然に思われる。 49151 | 実際の vim の振る舞いがどちらなのかは確認していないけれども。 49152 | しかし v/V/C-v を忘れて再生されるというのは不自然なので当然 vim でもその状態を記録しているはずである。 49153 | 3. その様に考えると実際に問題になるのは FLAG の中身を覗いているコードのみである。 49154 | それについては未だ確認していない関数のリストがあるので一つずつ確認していく事にする。 49155 49156 結論: 使用箇所で修正が必要なのは以下の二つの関数である。 49157 49158 - ble/widget/vi-command/linewise-range.impl 49159 - ble/widget/vi-command/exclusive-range.impl 49160 49161 $flag を operator 名とそれに付属するオプションに分離する。 49162 linewise-range ではオプション部分を無視して operator 名だけ使用するようにすれば良い。 49163 exclusive-range においてはオプションによって呼び出す charwise/linewise/blockwise を変更すれば良い。 49164 49165 opfunc/FLAG の形式を決定する必要がある。 49166 49167 | どの様な物が良いだろうか。既存の opfunc 名と被らない様にしたい。 49168 | そもそも opfunc は operator:opfunc の形式で呼び出すのだから、 49169 | ":" 区切りにするのが自然な気がする。 49170 | wiki の operator 設計の箇所ではどの様に書いただろうか。 49171 | 特に MyOperator を構成する文字列に対する制限は書かれていない。 49172 | 一応 MyOperator.record という関数を使っているので、 49173 | "." を含む事を可能にするのは不味いだろうというぐらいである。 49174 | 恐らく識別子として使える名前に制限しているつもりの気がする。 49175 | と思ったら既に surround-extract-region というのがある…。 49176 | まあ、然しそんなところだろう。 49177 | ":" を使うという事はない気がする。 49178 49179 結論: /Operator(:options)?/ の形式という事にする。 49180 また Operator には ":" や "." を含んではいけない事にする。 49181 49182 [実装] 49183 49184 1 done: o_v o_V o_C-v の実装 49185 2 done: 使用箇所の修正 49186 49187 取り敢えず動いている気がする。 49188 後は面倒なので不具合報告が出てきた時に対応する事にする。 49189 49190 2018-12-30 49191 49192 * color (ble-color-setface): "face:..." による設定が正しく設定されない (reported by cmplstofB) [#D0864] 49193 https://github.com/akinomyoga/ble.sh/issues/20 49194 49195 これは調べてみたところ ble-color-face2g 及び ble-color-iface2g の使い方を間違えていた。 49196 これは直した。 49197 49198 * fixed: しかし、face2g/iface2g の呼び出しに失敗するだけで、 49199 後に沢山のエラーメッセージが出てくるのはこれはこれで別のバグである。 49200 調べてみると、単語着色に於いて g 値が空文字列になった時に、 49201 _ble_syntax_tree に記録されている項目がずれてしまう問題があった。 49202 そもそも _ble_syntax_tree に記録される項目は空白区切りの単語列なので、 49203 空の単語が記録されない様に注意する必要があった。これも直した。 49204 49205 * ok: では何故 "echo" 等の時は問題にならないのに "[" の時は問題になるのか。 49206 更に bash のエラーメッセージに於いて "-" というのがコマンド名の如くに表示されているのは何か。 49207 cmplstofB さんのログによると tree-enumerate の中で起こっている様に見えるが解せない。 49208 % と思ったら分かった。tchild= だとか tprev= の右辺は算術式で計算されていて、 49209 % 算術式の中身に "[" が単体で存在していると問題になるのだ。 49210 % "echo" 等が単体で存在している場合にはそれは変数名と解釈されるので問題が起こらない。 49211 % と思ったがそれも不思議な話である。コマンド名は _ble_syntax_tree の内部に記録しない。 49212 更に表示されているエラーメッセージを見る限りは問題になっている要素の内容は "-" である。 49213 ずれてダミーで設定している "-" の値が算術式に渡されているのが原因である。 49214 49215 もしかして echo と [ で着色の仕組みが異なる? と思ったが、 49216 最終的に echo も [ もちゃんと同じ色で着色されているので、 49217 やはり着色の過程は同じになっているような気がする。 49218 何が echo と [ の違いを生んでいるのだろう。 49219 49220 →ble_debug=1 で dump して -/wattr を表示する様にした所、 49221 実は echo の時には一つの単語であるが、 49222 "[" の時には普通のコマンドとしての単語の中に 49223 word="none":0-1 という単語が設定されているという事が分かった。 49224 そしてこれは glob の [...] の検知の為に設置されている物の筈である。 49225 49226 つまり、特に何か問題があって "[" の時にだけ問題が発現したというよりは、 49227 同じ位置でネストされた word がある時にだけ発現するという、 49228 元々発現しにくい問題がたまたま "[" の時にようやく発現したという事である。 49229 なので、この動作の違いについては気にしなくても良いのである。 49230 49231 2018-12-17 49232 49233 * syntax (filename_ls_colors): 実は coreutils ls は二重拡張子にも対応している [#D0863] 49234 49235 * done: 二重拡張子には対応した。 49236 49237 * ok: 拡張子以外のパターンには対応していない様である。 49238 49239 * done: できるだけ長い拡張子から順番に試すという様に実装する必要がある? 49240 % →coreutils ls で試してみると長い拡張子から順番に試すのではなくて、 49241 % LS_COLORS に登録されている物の内、一番始めにあるものが優先される。 49242 % と思ったら勘違いだった。coreutils ls でも最初にあるものではなくて、 49243 % 長いものの方が優先される様に見える。 49244 →これには対応した。 49245 49246 * done: もう一つ確認しておきたいのは . から始まるファイルである。 49247 → . から始まるファイルも拡張子として取り扱われている。 49248 →対応した。 49249 49250 * 2016-07-20 ファイル名の色付けに LS_COLORS を参照する? [#D0862] 49251 https://github.com/trapd00r/zsh-syntax-highlighting-filetypes 49252 49253 ble.sh の枠組で使用する為には ble-color.sh/gflags に変換しなければならない。 49254 しかし、実際に使っている terminal と sequence が異なる場合に齟齬が生じる。 49255 従って直接 LS_COLORS を用いるよりは、bleopt_filename_ls_colors 的な変数に指定して貰う事にする。 49256 そのまま LS_COLORS を使用したい場合は bleopt_filename_ls_colors=$LS_COLORS などとする。 49257 展開を実行するようにする。 49258 49259 2018-12-16 https://github.com/akinomyoga/ble.sh/issues/19 に関連して。 49260 意味は例えば http://www.bigsoft.co.uk/blog/2008/04/11/configuring-ls_colors に書かれている。 49261 49262 | no NORMAL, NORM Global default, although everything should be something 49263 | fi FILE Normal file 49264 | di DIR Directory 49265 | ln SYMLINK, LINK, LNK Symbolic link. If you set this to ‘target’ instead of a numerical value, the color is as for the file pointed to. 49266 | pi FIFO, PIPE Named pipe 49267 | do DOOR Door 49268 | bd BLOCK, BLK Block device 49269 | cd CHAR, CHR Character device 49270 | or ORPHAN Symbolic link pointing to a non-existent file 49271 | so SOCK Socket 49272 | su SETUID File that is setuid (u+s) 49273 | sg SETGID File that is setgid (g+s) 49274 | tw STICKY_OTHER_WRITABLE Directory that is sticky and other-writable (+t,o+w) 49275 | ow OTHER_WRITABLE Directory that is other-writable (o+w) and not sticky 49276 | st STICKY Directory with the sticky bit set (+t) and not other-writable 49277 | ex EXEC Executable file (i.e. has ‘x’ set in permissions) 49278 | mi MISSING Non-existent file pointed to by a symbolic link (visible when you type ls -l) 49279 | lc LEFTCODE, LEFT Opening terminal code 49280 | rc RIGHTCODE, RIGHT Closing terminal code 49281 | ec ENDCODE, END Non-filename text 49282 | *.extension Every file using this extension e.g. *.jpg 49283 | 49284 | mh MULTIHARDLINK for "Regular file[s] with more than one link" 49285 | ca CAPABILITY for "File with capability." 49286 | rs ???? "Reset to ordinary colors" 49287 49288 取り敢えず *.extension に関しては対応した。 49289 49290 * ok: うーん。LS_COLORS の具体的な振る舞いが分からない。 49291 49292 | ? 複数の項目が当てはまる場合には属性は合成されるのか、 49293 | それともどれか一つだけが選択されるのか。 49294 | 49295 | 面倒なので coreutils を覗いてみる事にする。 49296 | 丁度 ~/local/build/coreutils-8.28 があったのでそれを見る。 49297 | 恐らく src/ls.c:4677: get_color_indicator (const struct fileinfo *f, bool symlink_target) である。 49298 | これを見る限りは、通常ファイルについて setuid, setgid, exec, multihardlink を順に試している。 49299 | またディレクトリについて other-writable/sticky を試している。 49300 49301 順番に試して先に一致した着色を採用する様である。 49302 拡張子については通常ファイルの時 49303 (setuid, setgid, exec, multihardlink の何れも適用されない時) に適用される。 49304 49305 * done: 更にファイルの種類について増やす? 49306 49307 | - do これはSolaris限定らしい 49308 | - or mi or については対応可能である。 49309 | - su sg st Bash から setuid 及び setgid を判定する方法はあったか → -u -g -k だった。 49310 | - tw ow Bash から other writable を判定する方法は無い気がする。 49311 | - lc rc ec これらは ble.sh では登場しないのではないか。 49312 49313 これに関しては or su sg st について対応した。 49314 tw ow do については対応できない。 49315 lc rc ec は ble.sh では使わない。 49316 mi については着色はしない。 49317 49318 * done: menu-complete で使う着色も core-syntax.sh の関数を呼び出して決める事にする。 49319 これは ble-syntax/highlight/getg-from-filename という関数で対応することにした。 49320 49321 新しい機能名は以下の通り 49322 - bleopt:filename_ls_colors 49323 - face:filename_ls_colors 49324 - face:filename_orphan 49325 - face:filename_setuid 49326 - face:filename_setgid 49327 - face:filename_directory_sticky 49328 49329 取り敢えず動作テストした。 49330 o 拡張子の着色 49331 o setuid setgid sticky orphan の着色の確認 49332 これは色を調整した。 49333 o menu-complete における着色 49334 49335 2018-12-16 49336 49337 * color (ble/color/read-sgrspec): 色番号の対応が不完全なのでは [#D0861] 49338 #D0860 を取り敢えず実装したが色番号について考慮していなかった。 49339 49340 端末の設定に基づいて読み取るのだから 49341 (1) 最初の 8 色もしくは 16 色に関しては 49342 _ble_term_sgr_{af,ab} を参照するようにする。 49343 (2) 88 色の場合には index color の翻訳を実行する 49344 49345 | (1) に関してはどのように実装するのが良いだろうか。 49346 | _ble_term_sgr_af が単一の番号であれば、 49347 | その逆写像を作成すれば良いのではないだろうか。 49348 | →どうもちゃんと単一の番号になっている気がする。 49349 | と思ったが init-term.sh の実装を見る限りはそうとも限らない。 49350 | 単一の番号の時のみに限り解釈する事にした。 49351 | 49352 | 世の中には 1; や 5; との組み合わせで highlight color を表現する場合もあるが、 49353 | それらについては面倒なので対応しない事にする。 49354 49355 →(1) については _ble_term_sgr_term2ansi という配列を使って、 49356 SGR値を読み取り時に ANSI の値に置き換えて解釈する事にした。 49357 49358 | (2) に関しては数式を確認する必要がある。#D0824 の記録を見ると、 49359 | 49360 | 16-79 4x4x4 0,58*v+81 49361 | 80-87 gray 46+25*v 49362 | 49363 | となっている。6x6x6 に関してはどうだったろうか。 49364 | 0-255 は 5 等分にする事ができるので、等間隔なのだろう。 49365 | 49366 | 0.58*v+81 とはどういう事か。0, 81, 139, 197, 255 と考えると 5 段階になってしまう。 49367 | 或いは一番暗かったとしても 81 という事になるのだろうか。 49368 | うーん。6level->4level の変換は R=(R*3+2)/5 という数式で行っている。 49369 | もっと単純に考えて R=(R*5+o)/3 とすれば良いのだろうか。 49370 | というか4値を6値に割り当てるだけなので実際の明るさなどはどうでも良くて、 49371 | できるだけ区別が残る様にするのが正しいのであろう。 49372 | その様に考えると元の値は関係なく変換するのが良い。 49373 | 適当に試して対称的になる o=1 を採用する事にした。 49374 | 49375 | 232-255 = 23段階 であるが実際には一番明るい色と暗い色が含まれていないので 25 段階である。 49376 | 同様に 80-87 は 7 段階の様に思われるが、実際には一番明るい色と暗い色が含まれていないので 9 段階である。 49377 | 結局、以下の関数のセットとして作成する事にした。 49378 | - ble/color/convert-color88-to-color256 49379 | - ble/color/convert-color256-to-color88 49380 49381 →(2) 88色時の index color の翻訳にも対応した。 49382 49383 * ble-color-setface で様々な形式に対応する (requested by cmplstofB) [#D0860] 49384 https://github.com/akinomyoga/ble.sh/issues/19 49385 当初は SGR の引数による指定の要望だった。様々な形式に対応する形で実装した。 49386 49387 2018-12-14 49388 49389 * サブシェル (...) 内で command-help が効かない (reported by cmplstofB) [#D0859] 49390 https://github.com/akinomyoga/ble.sh/issues/18 49391 49392 どうやら調べてみると extract-command に失敗している様である。 49393 extract-command の中を覗いてみるとちゃんと抽出できている様である。 49394 と思ったら、抽出できているのにも関わらず return 1 になる様になっていた。直した。 49395 これは前に extract-command を修正した時 #D0799 の修正忘れであろう。 49396 49397 2018-12-02 49398 49399 * 最近思っていたが menu-complete において日本語の文字が含まれていると座標がずれる [#D0858] 49400 49401 実際に試してみるとやはりずれている。どうも日本語の文字が半角の幅で計算されている様である。 49402 幅の計算を実行している部分を確認する必要がある。 49403 49404 うーん。関係するのは ble-complete/menu/construct-single-entry の中の、 49405 ble-edit/info/.construct-text を呼び出している部分である。 49406 もしかすると Cygwin 上だと変な事になるという事なのかもしれない。 49407 locale 関係が理由で。padparadscha の上で再現するかどうかを確かめてみる事にする。 49408 →試してみた所 padparadscha の上でも再現する。つまり locale の問題ではないはず。 49409 49410 construct-text の呼び出し前後での様子を出力させてみる事にする。 49411 結果、見事に単に文字数が計上されているという事が判明した。 49412 おかしい。construct-text が壊れているのだとすれば 49413 今までの info も壊れていたのではないか。 49414 或いは LC_COLLATE が効いていない? 49415 LC_ALL が設定されているとそういう事もあるかもしれない。 49416 49417 * fixed: construct-text の方を観察してバグを見つけてしまった。 49418 存在しない変数 tail を参照している。 49419 tail は基本的に空文字列である事を考えれば 49420 必ず「特殊文字が存在しない」と判定されて文字数だけのカウントになってしまう。 49421 これで起こっている現象を説明する事ができる。 49422 * done: 序に LC_ALL 対策も実施する事にする。LC_ALL= と内部で設定する。 49423 意図的に ble.sh の動作を変更する為に LC_ALL を変更するという事は考えにくいのでこれで問題ない。 49424 49425 動作確認もした。ちゃんと動作する様になった。OK 49426 49427 2018-10-18 49428 49429 * 2018-10-06 edit (reported by Kikurage): Bash-3.2 で C-d で exit できない [#D0857] 49430 https://github.com/akinomyoga/ble.sh/issues/15 49431 49432 更に、試行して以降全てのキー操作に対して "ジョブがあるので exit できない" の旨が表示される。 49433 これは C-d の受信に関係していると思われる。 49434 また、これより後に stty 等のジョブが途中状態で停止した状態になって残るのも確認された。 49435 しかも、入れ子のシェルでのみ発生するという現象である。謎。 49436 49437 更に言うと PS1 の中身が消失してしまうというのまである。 49438 これが起こるのは無理矢理抜けた後のシェルでの様である。 49439 49440 % 調べてみると何故か C-d は TRAPUSR1 経由で受信している訳ではない様だ。 49441 % 勘違いだった。デバグ用に弄っているのは devel だったのに 49442 % 0.2-master でテストを実行していた。 49443 49444 調べてみると実は毎回 "Use "exit" to leave the shell." 49445 というメッセージを受け取っている。 49446 つまり、Bash 3.2 が毎回そのメッセージを送信しているという事? 49447 うーん。不思議だ。 49448 49449 * checked: 再現する状況について再度詳しく調べてみる。 49450 Bash 3.0 では再現しない。Bash 3.1 では再現する。 49451 Bash 4.0 では再現しない。つまり、Bash 3.1 と 3.2 だけで再現する様子だ。 49452 49453 * checked: どのタイミングでこの問題が発生する様になったか 49454 49455 % また、今までは動いていたのだろうか。ble-0.1 では問題なく動いている。 49456 % という事は何処かのタイミングで問題が発生する様になった様だ。 49457 49458 - 32037b9 (support-vi-mode merge) 再現する 49459 - f15f8c5 再現する 49460 - 97923a9 再現する 49461 49462 と思ったら ble-0.1 でも再現する様だ…。 49463 つまり、これは何らかのミスで対応が壊れたのではなくて、 49464 特別に対策を考えなければならないケースの気がする。 49465 49466 * もっと単純化した状況で再現できないだろうか。 49467 49468 C-d で 'Use "exit" to leave the shell' が表示される。 49469 これは IGNOREEOF を設定している時には出るのである。 49470 この次に USR1 というシグナルを受け取る。 49471 そこで C-d に対応した処理が実行される。 49472 ジョブが存在しているので exit 等の処理は行われない。 49473 49474 結局何が特別なのかが分からない。 49475 USR1 というトラップを実行するという事が鍵なのだろうか。 49476 うーん。適当に単純化した bashrc でやっても再現しない。 49477 49478 というよりそもそも単純化すれば治るという物とも限らない。 49479 単純化すれば発生の条件が分かって対策方法が分かるかもしれないという事。 49480 49481 * suspend 状態になっている stty を殺すと 49482 キーを押す度にジョブが表示される問題は止まる様である。 49483 49484 * 後の気になる点は、何故 Done となったジョブが毎回表示され続けるのかという事である。 49485 49486 改めて。どうして Bash が毎回メッセージを発するのか。 49487 うーん。少しずつ機能を少なくして行って試すという事をしなければならないのか。 49488 ble-attach を分解して行って機能を少なくして試すという作戦。 49489 終了できなくなるかもしれないがそれは kill で…。 49490 或いは ble-decode/.hook を乗っ取る。 49491 うーん。とりあえずは ble-decode/.hook を乗っ取った状態で C-d を押して再現するのかという事。 49492 D0728.bashrc で似たような事をしているから参考になるかもしれない。 49493 49494 * というか入れ子で起動した時にのみ変な事になるというのはどういう仕組なのか。 49495 49496 | 状態が継承されるとしたら環境変数または stty による設定である。 49497 | しかし、入れ子元が Bash 4.0-4.4, 5.0 だと発生しないというのも妙である。 49498 | 環境変数や stty は Bash の version に関係あるとは思われないのだが。 49499 | 何れにしても、もしも原因の設定を特定できれば修正できる可能性もある。 49500 | 49501 | ? reject: 取り敢えず起動した瞬間の環境変数と stty を出力する事にする。 49502 | うーん。違いは MODULEPATH と NLSPATH と SHLVL のみである。 49503 | stty については diff で引っかからなかったので違いはないのだろう。 49504 | そして、macOS でも再現している事を考えるとこれらは関係ない。 49505 | 49506 | { 49507 | stty -a 49508 | export 49509 | } > debug-C-d.$SHLVL.txt 49510 | 49511 | ? reject: 標準出力・標準入力が何処に繋がっているかも関係あるかもしれない。 49512 | 49513 | { 49514 | ls -la /proc/self/fd/{0,3,2} 49515 | } 3>&1 > debug-C-d.$SHLVL.txt 49516 | 49517 | これで確かめてみたが変化はない。 49518 | 49519 | ? 或いは fork の時に特別な処理をしている可能性? 49520 | バイナリが同じだったら exec を省略するなど。 49521 | 然し、3.1 から 3.2 に入った時でも再現する事からそれはない。 49522 | 49523 | 後、bash-3.2 bash-4.4 bash-3.2 と起動した時にはどうなるのだろうか。 49524 | →うーん。今度は C-d を全く受信できなくなってしまった。 49525 | stty を調べてみると -echoe という状態になっている。 49526 | stty echoe としたら戻った、それでも関係なく受信できない。 49527 | C-d を押すとまた stty -echoe に戻ってしまう。 49528 | この辺りに何らかの鍵があるのかもしれない。 49529 | 49530 | ? reject: うーん。一回コマンドを実行すると直るという事を思うと、 49531 | やはり stty の状態がおかしくなっている事による問題とも捉えられる。 49532 | 試しに stty を実行しないとどうなるのか確かめてみるのも一つの手である。 49533 | →試しに ble/bin/stty() { :; } を実行して stty が呼び出されない様にしたが、 49534 | 再現されるし、またコマンドを実行すると直る。うーん。何故だろう。 49535 | 49536 | これは不思議である。何をきっかけとして直るのだろうか。 49537 | 絶対に何か直るきっかけが存在しなければならない。 49538 | stty 以外で何があるのだろうか…。 49539 | 49540 | ble/term/enter, ble/term/leave を丸ごと消したがそれでもコマンド実行で直る。 49541 | だとすると ble-edit/bind/stdout.on, ble-edit/bind/stdout.off が鍵なのだろうか。 49542 | 然し、不思議な事に M-z を押しても直らない…と思ったが、 49543 | vi mode では M-z は束縛していないのだった。C-z で直った。 49544 | という事はやはり確実にコマンド実行が関係している。 49545 | 49546 | 試しにいい加減な widget を使って実験してみるのも良いかもしれない。 49547 | 試してみたところ stdout.on, stdout.off では直らない様である。 49548 | 続けて色々 widget を試す。少なくとも .begin/.end を実行すれば直る。 49549 | そのどれが効いているのだろうか。絞り込んでいくと term/enter, leave で直る。 49550 | 49551 | - 色々試していて気づいた。これは親 bash が TRAPUSR1 を捕まえている。 49552 | つまり、コマンド実行中は TRAPUSR1 を解除する様にしなければならない。 49553 | →うーん。TRAPUSR1 を解除して実行したら USR1 を受け取って 49554 | セッションごと全て落ちてしまった。うーん。 49555 | 更に残された subshell が無限に Use "exit" to leave the shell のメッセージを受け取っている。 49556 | これも謎である。何故 pipe を通じて無限にデータが送られて来るのか…。 49557 | 49558 | 代わりに '' で無視する様にして見た所、反応しなくなってしまった。 49559 | うーん。実は親の subshell が受信しているという事か…。 49560 | そして親に TRAPUSR1 を送っているという事…。 49561 49562 仕組みは分かった。C-d を受信すると親 Bash 3.2 の側で 49563 Use "exit" to leave the shell のメッセージが表示され、 49564 子 Bash 3.2 の側には何も通知が行かない。 49565 本当は Bash 3.2 に C-d を送信したい所であるが、どうしようもない。 49566 stty の設定を確認してみるが矢張りどうしたら良いか分からない。 49567 49568 問題は2つある。 49569 49570 1 メッセージが大量に出るという事。 49571 % stty を実行して直るのはこちらだけである。 49572 49573 →これに関しては単に $_ble_term_state == internal の時にだけ 49574 反応する様にすれば良い。取り敢えず抑制できる事は確認した。 49575 49576 2 % 子Bash (というより子プロセス全て) に C-d を伝達する事ができない。 49577 % エラーメッセージを抑制したとしてもこれに対処する事はできない気がする。 49578 % 49579 % と思って試しに子プロセスに全然 C-d が行かない事を立証しようとしたが、 49580 % cat に対して C-d を実行したらちゃんと受信できるという事が分かった…。 49581 % stty の状態によって Bash が C-d を奪うかそうでないかが決まるという事だろうか。 49582 % そして親 Bash 3.2 が子を起動する時には stty をちゃんと設定するが、 49583 % 子 Bash の側で ble.sh をロードして stty を調整すると、 49584 % その所為で親 Bash 側での処理が再度有効になってしまうという仕組みである。 49585 % 49586 % というか Bash 3.2 から Bash 4.0 を呼び出した時に C-d が動いていた様に見えたのは何だったのか。 49587 % →うーん。動いている。という事は何らかの条件を満たせばちゃんと子に伝達される。うーん? 49588 % うーん。やはり 4.0 ではちゃんと C-d を受信する事ができている。 49589 % C-d を入力した後でも同様である。両方共 eof は ^D になっている。 49590 49591 これに関しては Bash 3.2 以外の子孫に対しては 49592 途中に Bash 3.2 が含まれていたとしてもちゃんと C-d を伝達できている。 49593 ただただ子 Bash 3.2 で ble.sh をロードした時にのみ親 Bash 3.2 が引っ掛かる。 49594 49595 * うーん。現在の標準入力に対して好きな文字を流し込むという事はできないのか…。 49596 擬似端末のマスター側が必要である。そしてそれは普通見えない…。 49597 或いは子Bash側から C-d が欲しいという事を上に伝達する。 49598 49599 * internal の状態における stty について Bash 3.2 と 4.0 で確認したい。 49600 →stty -a を両者で実行してみたが違いはない様に見える。 49601 49602 ? reject: 何故 stty の設定で eof が ^D のままになっているのだろう。 49603 49604 | これを undef にしたら解決したりしないのだろうか。 49605 | というか何故元々 C-d を IGNOREEOF で受信せざるを得なかったのかの議論を遡る必要がある。 49606 | 議論を遡ってみると #D0141 という物があるが、 49607 | ここでは stty で設定を変更する事に関しては議論されていない。 49608 | 試しに stty で eof を undef に設定してみることにした。しかし変化はない。 49609 | 更に bash-3.2 用の特別の処置を解除してみたが、 49610 | そうすると単純に入れ子かどうかに関わらず C-d が全く効かなくなった。 49611 | 従って stty で eof を解除するかどうかは全く効かない。 49612 | ソースコードを元の状態に戻す。 49613 49614 結論 stty で eof ^D を変更しても何も効果はない。従って動かさない方向で行く。 49615 49616 ? 目下の謎は、何故 Bash 4.0 がぶら下がっている時には親 Bash 3.2 が反応しないのに、 49617 Bash 3.2 がぶら下がっている時には親 Bash 3.2 が反応するのかという事である。 49618 というか、本当にその様な構造になっているのだろうか。 49619 49620 - Bash 3.2 -> 4.0 は C-d が使える。 49621 - Bash 3.2 -> 4.0 -> 3.2 だと C-d が使えない。 49622 - Bash 3.2 -> 4.0 -> 3.2 -> 4.0 では C-d が使える。 49623 - Bash 3.2 -> 3.2 だと親 Bash 3.2 で Use "exit" を検知している。 49624 - Bash 3.2 -> 4.0 -> 3.2 だと親 Bash 3.2 では検知できていない。 49625 子 Bash 3.2 でも検知できていない。うーん。間の 4.0 に吸い込まれているのだろうか…。 49626 - Bash 3.2 -> 3.2 -> 3.2 の時には最初の Bash 3.2 が検知している。 49627 49628 うーん。norc だと読み取る事はできるのだろうか。 49629 - 3.2(ble) ** 3 -> 3.2(norc) でちゃんと C-d を読み取れている。 49630 - 3.2(ble) -> 3.2(ble/nostty) 49631 もしかすると stty を何も実行しなければ受信できるのかもしれない、 49632 と思ったがやはり受信はできない様だ。 49633 この時もやはり親 Bash が代わりに受信をしている。 49634 - 3.2(norc) -> bindx 内から 3.2(norc) 49635 stty sane を実行しないと何も表示されないが、 49636 stty sane さえ実行してしまえば特に問題なくコマンド実行できる。 49637 C-d もちゃんと動作している。 49638 49639 やはり標準エラー出力をリダイレクトしているか 49640 していないかにも関わってくるのだろうか。 49641 49642 結局何がどうなっているのかはよく分からない。 49643 Bash 3.2 だけのチェインになっている時には最初の 3.2 が検知する。 49644 途中に Bash 3.2 以外が含まれていると誰も検知していない様に思われる。 49645 どの様なチェインになっていたとしても Bash 4.0 など他のプログラムは 49646 C-d を読み取れる。Bash 3.2 も ble.sh をロードしていない限りは読み取れる。 49647 Use "exit" 云々のメッセージも子 Bash 3.2 から発している気がする。 49648 49649 現在分かる範囲での対策方法として何があるだろうか 49650 49651 a reject: 一つの解決方法は子 Bash 3.2 を起動した時に親 Bash 3.2 に通知をして、 49652 親 Bash 3.2 が検知した時に今一番下にいる Bash 3.2 に対して通知を転送する方法である。 49653 しかし、この方法だと複数の Bash 3.2 の子供がいる場合 (というのが可能化は知らないが) 49654 にどう対応するのかは非自明だし、子 Bash のリストをどの様に管理するのか、 49655 管理に不整合が起こった場合にどの様に処理するのかなどを考察しなければならない。 49656 49657 また、Bash 3.2 -> Bash 4.0 -> Bash 3.2 の場合にはそもそも誰も検出できないので、 49658 この方法は完全な解決になっているとは言い難い。 49659 例えば Bash 3.2 -> screen -> Bash 3.2 としたら何が起こるのだろうか。 49660 或いは、screen の場合には擬似端末とセッションを作るので実は問題にならないのかもしれない。 49661 49662 何れにしてもこの方法は不完全であるし微妙。 49663 49664 b もう一つの解決方法は具体的に何が C-d の受信を妨げているのかを特定するという事。 49665 これは実際に調べてみないとどの様な事になるか分からない。 49666 49667 取り敢えず bind -x '"\C-d": hello' は Bash 3.2 で動くのだったろうか。 49668 Bash 3.2 with ble.sh の中から Bash 3.2 with test2.bashrc で起動して試す。 49669 試してみると実は有限の文字列が設定されている時には C-d は効くのだった。 49670 更に、文字列が空の時には問答無用で Use "exit" の様だ。 49671 但し、ちゃんと子 Bash の側で Use "exit" が表示されている様に思われる。 49672 つまり、子 Bash から検出可能なのではないか。 49673 49674 どの様な設定を行う事によって Use "exit" が使えなくなって 49675 親 Bash 3.2 によって処理されるという事態になるのか確認が必要である。 49676 取り敢えず ble.sh を単に load するだけでは問題は起こっていない。 49677 attach すると問題が起こる。 49678 49679 * attach した場合でも以前の実験により、 49680 stty を封じていても受信できなくなるという事は分かっているので、 49681 特に stty の設定の変化が悪いという訳でもないと考えられる。 49682 * 取り敢えず bind だけ実行してみるというのも手である。 49683 49684 % ble-attach から始めてどんどん絞り込んで行って 49685 % 49686 % | function ble-decode/.hook { 49687 % | ble-decode/PROLOGUE 49688 % | local byte 49689 % | for byte; do 49690 % | case $byte in 49691 % | (20) echo C-t; exit ;; 49692 % | (4) echo C-d ;; 49693 % | (*) echo $byte;; 49694 % | esac 49695 % | done 49696 % | ble-decode/EPILOGUE 49697 % | } 49698 % | source $_ble_base_cache/ble-decode-bind.$_ble_bash.UTF-8.bind 49699 % 49700 % という所まで絞り込めた。 49701 % この PROLOGUE または EPILOGUE が悪さをしている様である。 49702 % どうも ble-edit/bind/stdout.off を実行した状態だと駄目の様だ。 49703 % この時親 Bash 3.2 で検知される様になる。 49704 % ble-edit/bind/stdout.on の後には大丈夫になる。 49705 % 49706 % % - reject: うーん。もしかして openat で変なファイルを開いている可能性? 49707 % % 確かめてみたがちゃんと自プロセスのファイルを開いている気がする。 49708 % % - reject: 或いは同じ fd で開いているから何か変な干渉が起こっているのだろうか。 49709 % % % →_ble_util_openat_nextfd=33 としてみて起動して、 49710 % % % fd を親 Bash 3.2 とずらす様にして試してみた。それでも駄目 49711 % % bleopt_openat_base=33 としなければちゃんと fd がずれていなかった。 49712 % % しかしそれをして fd がずれている事を確かめても C-d は受信できなかった。 49713 % % - 試しにぜんぜん違うファイルにリダイレクトするのを試してみる。 49714 % % exec 1>>$_ble_edit_io_fname1 2>test.stderr 49715 % % これだとちゃんと受信する事ができている。 49716 % % - 次に別の名前付きパイプを使って見る事にする。 49717 % % 何と自分で新しく作成した名前付きパイプを使うと受信できている…。 49718 % % 違いは何だろうか。 49719 % % 49720 % % % しかし中を覗くと受信している内容は滅茶苦茶になっている。 49721 % % % 文字が色々抜け落ちたりしている。これはどのタイミングで起こるのだろうか。 49722 % % % →滅茶苦茶になっているのは一つのパイプに複数のプログラムがぶらさがっていたからだった。 49723 % % 49724 % % うーん。よく分からない…。 49725 % % pipe に繋がっている先のプログラムで行っている処理が関係しているのだろうか。 49726 % % と思ったが、そもそも処理を一度も実行しない内から問題は始まっている。 49727 % % diwown しているのが問題の元なのかと思いきや、正しく動いている方でも disown はしている。 49728 % % 49729 % % うーん。取り敢えず bashrc の方で C-d を捕まえられる様になるかどうかを確かめる為に、 49730 % % →幾らか修正した所 C-d を捕まえられる様になってしまった。 49731 % % パイプを tmpfs の上に置いていると問題になるのだろうか。 49732 % % と思ったが、ble-0.1 でも問題が同様に発生している事からそれは関係ない。 49733 % % では openat を実行する場所が問題なのだろうか。 49734 % % 例えば source したファイルの中でやると駄目など。 49735 % % 或いは、ファイルディスクリプタがやはり問題になっているのだろうか。 49736 % % 今回は 35 番でやっているが、ble.sh によって設置されるのは 32 か 33 である。 49737 49738 どうも動かなくなったのは単に _ble_term_state=internal が足りていなかったのが行けなかったようだ。 49739 遡ると PROLOGUE/EPILOGUE でも動作する様になった。 49740 更に ble-attach の中を分解してコメントアウトするなどしたがどうも動く様である。 49741 処理を関数の中に入れても動く。というか、ble-attach を直接呼び出しても動いた。 49742 49743 結局 bleopt_openat_base=33 があるかないかで動くか動かないかが変わる様だ。 49744 使われていない番号でないと動かない。しかし openat でちゃんと上書きされる筈であるし、 49745 親プロセスの fd には影響はないはずである。試しに明示的に fd を閉じて見ることにする。 49746 動くようになった。うーん。 49747 49748 調べてみると以下の様なバグ修正がある。恐らくこれであろう。 49749 49750 > ------------------------------------------------------------------------------ 49751 > This document details the changes between this version, bash-4.0-alpha, 49752 > and the previous version, bash-3.2-release. 49753 > 49754 > 1. Changes to Bash 49755 > 49756 > (中略) 49757 > 49758 > ee. Fixed a bug that caused bash to close file descriptors greater than 10 49759 > when they were used in redirections. 49760 49761 * 2018-10-06 [棄却] edit: ble-0.1 系列でコマンド実行の度に "一致しません: ?" のメッセージが表示される [#D0856] 49762 これは failglob が原因だった。これには改めて対応はしない。 49763 49764 2018-10-09 49765 49766 * 2018-10-06 vi (reported by cmplstofB): ビジュアルモードにおけるテキストオブジェクトの単語の振る舞い [#D0855] 49767 https://github.com/akinomyoga/ble.sh/issues/16 49768 49769 % 調べてみると色々の異なる振る舞いをしている。 49770 % そもそもどういう振る舞いだと考えたのかがまず分からない。 49771 % 過去の議論を遡ることにする。 49772 % 余り情報は残っていない #D0443 に多少残っている。 49773 % やはり他に残ってはいない様だ。 49774 % 49775 % 改めて。以下は aw の振る舞いである。 49776 % 49777 % > - カーソル位置が空白の場合にはそれに続く単語の末端までを範囲とし、 49778 % > この時単語に皇族の空白は含まれない。引数が複数ある場合についても同様である。 49779 % > 一番最後の単語に後続の空白は含まれない。先頭の空白には改行が含まれていても良い。 49780 % 49781 % これに関しては特に問題は無いように見える。現にテストケースでも問題は起こっていない。 49782 % - done: 但し、改行が含まれている場合というのをテストケースに加える事にする。 49783 % 49784 % > - 一方で、カーソルの位置が単語の内部にある場合には、 49785 % > 一番最後の単語に後続の空白は含まれる。 49786 % > また後続の単語に改行は含まれない。 49787 % 49788 % - done: これは明らかに不完全である。後続の空白がない場合は前の空白を取り込む。 49789 % これは対応した。一つのテスト項目しか減少しなかった。 49790 % 49791 % - また複数の単語を取る時、必ずしも空白で分かたれていなければならない訳ではない。 49792 % 異なる種類の単語であれば問題ない。 49793 % しかしながらこれを正規表現で判定するにはどうしたら良いだろう。 49794 % 空白を入れなくて良い事にすると本来単語区切りでない所で単語が区切れて一致するという事が起こりうる。 49795 % 49796 % うーん。作り直す事にした。改めて個別の動作について確認する。 49797 % 49798 % 49799 % うーん。改行が絡んでいる時の振る舞いが全く分からない。 49800 % 因みに exclusive-range.impl では勝手に位置をずらすなどの事はしていない様である。 49801 % 49802 % - $'@:echo\n@\nhello\n\nworld\n' iw $'@:echo\n@<>\nhello\n\nworld\n' 49803 % - $'@:echo\n@\nhello\n\nworld\n' aw $'@:echo\n@<\nhello\n>\nworld\n' 49804 % - $'@:echo\n@\nhello\n\nworld\n' 2iw $'@:echo\n@<\nhello\n>\nworld\n' 49805 % - $'@:echo\n@\nhello\n\nworld\n' 2aw $'@:echo\n@<\nhello\n\nworld>\n' 49806 % 49807 % 現状ではこの様になっている。 49808 % ここで疑問なのは「範囲の末端の改行」は範囲から除かれるという動作。 49809 % この動作は元の text-object/word.impl の時から存在していた。 49810 % 49811 % 先ず初めに iw から考える事にする。iw の時点でよく分からない動作をする。 49812 % そう考えると iw は <\n> を最初囲んでから <> に縮まった物と思われる。 49813 % 一方で 2iw はどうだろうか。<\nhello\n> を囲んだのだとすれば 49814 % <\nhello> に縮まるべきであるが vim では縮まっていない。 49815 % 49816 % 再度試してみる事にする。やはり <\nhello\n> が削除される。 49817 % もしかすると <\nhello\n\n> まで囲んでから <\nhello\n> に縮んでいるのかもしれない。 49818 % と思って \n\n\n に対して試して見たがそうでも無い様だ。 49819 % うーん。しかも引数を増やす毎に一つずつ取り込む改行が増える。 49820 % 実は末尾に改行を除くという操作は元からしていなくて、 49821 % 最初の iw で <> が初めから選択されているという事なのだろうか。 49822 % しかし、空の選択範囲という物が選択されるというのも設計として変である。 49823 % 或いは、末尾の \n が除去される状況と除去されない状況というのが存在するのか。 49824 % もう一つ試しておくべき事は、末尾の改行が存在しない時である。 49825 % 後更に一つ引数を増やしたらどうなるか…あれ次の単語まで取ってしまう。 49826 % 49827 % - $'@:echo\n@\nhello\nworld\n' 1iw $'@:echo\n@<>\nhello\nworld\n' 49828 % - $'@:echo\n@\nhello\nworld\n' 2iw $'@:echo\n@<\nhello\n>world\n' 49829 % - $'@:echo\n@\nhello\nworld\n' 3iw $'@:echo\n@<\nhello\nworld\n>' 49830 % - $'@:echo\n@\nhello\n\nworld\n' 1iw $'@:echo\n@<>\nhello\n\nworld\n' 49831 % - $'@:echo\n@\nhello\n\nworld\n' 2iw $'@:echo\n@<\nhello\n>\nworld\n' 49832 % - $'@:echo\n@\nhello\n\nworld\n' 3iw $'@:echo\n@<\nhello\n\n>world\n' 49833 % - $'@:echo\n@\nhello\n\nworld\n' 4iw $'@:echo\n@<\nhello\n\nworld\n>' 49834 % - $'@:echo\n@\nhello\n\n\nworld\n' 1iw $'@:echo\n@<>\nhello\n\n\nworld\n' 49835 % - $'@:echo\n@\nhello\n\n\nworld\n' 2iw $'@:echo\n@<\nhello\n>\n\nworld\n' 49836 % - $'@:echo\n@\nhello\n\n\nworld\n' 3iw $'@:echo\n@<\nhello\n\n>\nworld\n' 49837 % - $'@:echo\n@\nhello\n\n\nworld\n' 4iw $'@:echo\n@<\nhello\n\n\nworld\n>' 49838 % - $'@:echo\n@\nhello\n\n\n\nworld\n' 1iw $'@:echo\n@<>\nhello\n\n\n\nworld\n' 49839 % - $'@:echo\n@\nhello\n\n\n\nworld\n' 2iw $'@:echo\n@<\nhello\n>\n\n\nworld\n' 49840 % - $'@:echo\n@\nhello\n\n\n\nworld\n' 3iw $'@:echo\n@<\nhello\n\n>\n\nworld\n' 49841 % - $'@:echo\n@\nhello\n\n\n\nworld\n' 4iw $'@:echo\n@<\nhello\n\n\n\n>world\n' 49842 % - $'@:echo\n@\nhello\n\n\n\nworld\n' 5iw $'@:echo\n@<\nhello\n\n\n\nworld\n>' 49843 % - $'@:echo\n@\nhello\n\n\n\n\nworld\n' 1iw $'@:echo\n@<>\nhello\n\n\n\n\nworld\n' 49844 % - $'@:echo\n@\nhello\n\n\n\n\nworld\n' 2iw $'@:echo\n@<\nhello\n>\n\n\n\nworld\n' 49845 % - $'@:echo\n@\nhello\n\n\n\n\nworld\n' 3iw $'@:echo\n@<\nhello\n\n>\n\n\nworld\n' 49846 % - $'@:echo\n@\nhello\n\n\n\n\nworld\n' 4iw $'@:echo\n@<\nhello\n\n\n\n>\nworld\n' 49847 % - $'@:echo\n@\nhello\n\n\n\n\nworld\n' 5iw $'@:echo\n@<\nhello\n\n\n\nworld\n>' 49848 % 49849 % \n x 1: echo\n@(1)\nhello\n(2)world\n(3) 49850 % \n x 2: echo\n@(1)\nhello\n(2)\n(3)world\n(4) 49851 % \n x 3: echo\n@(1)\nhello\n(2)\n(3)\nworld\n(4) 49852 % \n x 4: echo\n@(1)\nhello\n(2)\n(3)\n\n(4)world\n(5) 49853 % \n x 5: echo\n@(1)\nhello\n(2)\n(3)\n\n(4)\nworld\n(5) 49854 % 49855 % - $'@:echo\n@\nhello\n\n\n\n\nworld\n' 1aw $'@:echo\n@<\nhello\n>\n\n\n\nworld\n' 49856 % - $'@:echo\n@\nhello\n\n\n\n\nworld\n' 2aw $'@:echo\n@<\nhello\n\n\n>\n\nworld\n' 49857 % - $'@:echo\n@\nhello\n\n\n\n\nworld\n' 3aw $'@:echo\n@<\nhello\n\n\n\n\n>world\n' 49858 49859 * done: vim のソースコードを読んで知ったが 49860 後続空白がなかったとしても行頭空白は含めないらしい。 49861 49862 * done: 結局 vim のソースコードを読むことにした。 49863 読んでいても良く分からなくなるので分かった事をここに書きながら読むことにした。 49864 49865 先ず初めに、omap もしくは xmap で一文字しか選択されていない場合には、 49866 49867 inc は次の文字に移動する。行の最後の文字にいる時には行末の NUL に移動する。 49868 行末の NUL で再度 inc を実行すると次の行の行頭に行く。 49869 incl は行末の文字から次の行に跳ぶ。 49870 行末の NUL は ble.sh での \n と考えて良いだろう。 49871 inc は \n に止まるが incl は \n に止まらずに次の行の行頭に行く。 49872 49873 back_in_line は同じ文字カテゴリの文字が続く限り行内で後ろに戻る。 49874 これは現在の ble.sh でやっているのと同じ動作になっているので大丈夫。 49875 49876 if ((cls() == 0) == include) 49877 if (end_word(1L, bigword, TRUE, TRUE) == FAIL) 49878 return FAIL; 49879 else { 49880 fwd_word(1L, bigword, TRUE); 49881 以下略 49882 } 49883 ここでやっているのは、 49884 iw で最初空白だったらその空白を拡張する。 49885 iw で最初空白以外だったらその単語の末尾まで拡張する。 49886 aw で最初空白だったら次の単語の末尾まで拡張する。 49887 aw で最初空白以外だったら次の単語の末尾まで拡張する。 49888 という事。丁度反転しているから xor で振る舞いを切り替えている…。 49889 更に include_white は aw でかつ最初非空白だった時に設定される。 49890 49891 2個目以降の単語は取り扱いが異なる。と思ったが、 49892 if (include != (cls() == 0)) { 49893 if (fwd_word(1L, bigword, TRUE) == FAIL && count > 1) 49894 return FAIL; 49895 if (oneleft() == FAIL) 49896 inclusive = FALSE; 49897 } else { 49898 if (end_word(1L, bigword, TRUE, TRUE) == FAIL) 49899 return FAIL; 49900 } 49901 これは最初と条件判断の真偽が逆になっているだけでやっている事は同じに見える。 49902 比べてみると最初の単語の切り出しでは 49903 if (curwin->w_cursor.col == 0) 49904 decl(&curwin->w_cursor); 49905 としているが、while の中ではこれを実行していない。 49906 つまり count が 2 以上だった時、 49907 もしくは xmap でかつ ind != mark だった時は、 49908 末尾の改行の削除は行われないということの様だ。 49909 49910 if (include_white && (cls() != 0 49911 || (curwin->w_cursor.col == 0 && !inclusive))) 49912 これは「aw で最初非空白で、(現在地が非空白 または (行頭かつ !inclusive))」 49913 という条件である。!inclusive という事は行頭の文字は含まれない、 49914 つまり行末までの範囲という事である。 49915 49916 | うーん。現在地が非空白、という事については ble.sh で対応しているので大丈夫。 49917 | しかし、行頭かつ !inclusive というのはどういう事か。 49918 | これだと行末に空白が並んでいる場合でも exclusive ならば、 49919 | 前方に空白を取り込みに行くという事の様に思われる。 49920 | うーん。inclusive = FALSE は最後の単語の探索で行頭に居た時に起こる様である。 49921 | しかし、試してみたがこれによってどういう振る舞いの違いが出ているのか分からない。 49922 | というか、単に vim の範囲表現の処理のような気がしてきた。 49923 | 実際に試してみてもこれによってどういう振る舞いの変化が起こっているのか分からない。 49924 | →よく分からないのでこれは無視する事にする。 49925 49926 というか先に fwd_word を見ておくべき気がする。 49927 fwd_word を見ると空行 (col 0 に NUL がある) で止まると書いてある。 49928 また一番始めに空白があると空白を一つの単語として数えそうな気がする…。 49929 初めに空行にカーソルがあった場合に fwd_word を実行するとどうなるか。 49930 \n@\n\n ここで cls == 0 となる。そして次に進むと 49931 \n\n@\n という状態になる。ここで空白の読み飛ばしに入るが、 49932 実はその瞬間に終了するはずである。つまり1文字しか進まないはず。 49933 また、初めに単語にカーソルがあった場合に fwd_word を実行するとどうなるか。 49934 \n@hello\n\n となっている。ここで \nhello@\n\n まで進む。 49935 空白を読み飛ばすと \nhello\n@\n という事になる。 49936 49937 これによって先の偶奇を説明する事ができるだろうか。 49938 恐らく、末尾の改行の除去を行う前は以下の様な動きになっている。 49939 49940 | \n x 1: echo\n@\n(1)hello\n(2)world\n(3) 49941 | \n x 2: echo\n@\n(1)hello\n(2)\n(3)world\n(4) 49942 | \n x 3: echo\n@\n(1)hello\n(2)\n(3)\nworld\n(4★) 49943 | \n x 4: echo\n@\n(1)hello\n(2)\n(3)\n\n(4★)world\n(5) 49944 | \n x 5: echo\n@\n(1)hello\n(2)\n(3)\n\n(4★)\nworld\n(5★) 49945 49946 | \n x 5: echo\n◎①\nhello\n②\n③\n\n④\nworld\n⑤ZZZZZ 49947 | \n x 10: echo\n◎①\nhello\n②\n③\n\n④\n\n⑤\n\n⑥\n\n⑦world\n⑧ZZZZZ 49948 49949 ★を付した箇所が理解できない振る舞いをしている部分である。 49950 49951 調べてみると diw を使っている時は fwd_word ではなくて end_word の気がする。 49952 end_word の中を覗くと、取り敢えず一文字は必ず進む。 49953 非空白文字の時は文字の種類が変わるまで進む。 49954 空白文字の時は空白が続くまで進むけれど空行に入ったらその位置で止まる。 49955 空行で止まった時以外は一文字戻る (これは inclusive 範囲なので)。 49956 49957 この動作に従うと (3) は正しい気がする。(4) 以降はやはり理解できない。 49958 と思ったが、よく見ると end_word を呼び出す前に取り敢えず一文字移動している。 49959 しかも incl である。この時何が起こるのだろうか。 49960 49961 hello\n@\n\n\n の時には incl で 49962 hello\n\n@\n\n という状態になる。ここで更に end_word を呼び出すと、 49963 hello\n\n\n@\n という状態になる。そう考えると (3) は二行進むはずである。 49964 しかし、何故か一行しか進まない。うーん。 49965 あー。何か分かった気がする。恐らく text object の中では以下の様になっている。 49966 49967 | \n x 10: echo\n◎\n①hello②\n\n③\n\n④\n\n⑤\n\n⑥\n\n⑦world\n⑧ZZZZZ 49968 49969 これがその後の補正に依って範囲が変更されている。 49970 49971 * done: 取り敢えず vim の真似をして多少修正する。 49972 49973 色々バグが出て動かない。 49974 49975 test(xmap text object (word)/A7/iw): keys = (d i w) 49976 initial = "echo^J@^Jhello^J^Jworld^J" 49977 expected = "echo^J@^Jhello^J^Jworld^J" 49978 result = "ech@o^Jhello^J^Jworld^J" 49979 49980 色々試してみると、二行ずつ進むという動作が再現しない。 49981 vim の側では daw も diw も十分大きな引数に対して 49982 2行ずつ進む様であるが、vim のソースコードを読んでも1行ずつしか進まない気がするし、 49983 それを参考にして実装した ble.sh も当然1行ずつしか進まない。 49984 49985 如何なる仕組みによって二行ずつ進んでいるのだろうか。 49986 改めて vim のソースコードを見てみる必要がある。 49987 取り敢えず十分大きな count に対して思っているのと違う動作をしているので、 49988 その部分について観察してみる事にする。 49989 49990 | while (count > 0) { 49991 | inclusive = TRUE; 49992 | if (VIsual_active && LT_POS(curwin->w_cursor, VIsual)) { 49993 | 今は xmap では試していないので此処には入ってこない筈である。 49994 | } else { 49995 | ここで一文字進む。つまり、\n の直前にいたとすると次の行頭に移動する事になる。 49996 | 或いは空行以外の場合にはカーソルが行末にいたとすると一番最後の文字の直前にいる筈だが、 49997 | この場合でも incl を使うと二文字進んで次の行頭に移動する事になる。 49998 | これは、常に exclusive end で管理している ble.sh 的には、 49999 | 行末にいる時には行頭に移動するという事と考えて良い。 50000 | 行末以外にいる時には特に何もしなくて良い。 50001 | if (incl(&curwin->w_cursor) == -1) 50002 | return FAIL; 50003 | 50004 | include は aw か iw の違いである。 50005 | cls() は現在位置の文字の種類で 0 はスペースである事を表す。 50006 | 改行ばかりが並んでいる時にはこれは常に TRUE になる。 50007 | つまり aw の時にはこの if 文の true-clause に入り、 50008 | iw の時にはこの if 文の false-clause に入る。 50009 | if (include != (cls() == 0)) 50010 | { 50011 | 次に fwd_word について考える。 50012 | ここに入るのは aw で非空白文字の上に載っていた時と、 50013 | iw で空白文字の上に載っていた場合である。 50014 | 50015 | if (fwd_word(1L, bigword, TRUE) == FAIL && count > 1) 50016 | return FAIL; 50017 | | fwd_word = { 50018 | | sclass = cls(); 50019 | | last_line = (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count); 50020 | | i = inc_cursor(); 50021 | | if (i == -1 || (i >= 1 && last_line)) return FAIL; 編集文字列の末端 (NUL) だったら失敗 50022 | | if (i >= 1) return OK; 次の行に進んだら成功。 50023 | | 取り敢えず一文字進んで見る。 50024 | | 50025 | | if (sclass != 0) { 50026 | | while (cls() == sclass) 50027 | | { 50028 | | i = inc_cursor(); 50029 | | if (i == -1 || (i >= 1)) 50030 | | return OK; 50031 | | } 50032 | | } 50033 | | もし w だったら w+ だけ読み取る。途中で次の行に進んだら成功。 50034 | | もしくは文字列終端に進んだら成功。これは /w+($|\n)/ という事。 50035 | | それ以外の w+ は次に進む。 50036 | | 50037 | | while (cls() == 0) { 50038 | | if (curwin->w_cursor.col == 0 && *ml_get_curline() == NUL) 50039 | | break; 50040 | | この条件が満たされる事はない気がする。 50041 | | fwd_word を呼び出す前に incl しているのでファイルが空でない限りは 50042 | | 必ず文字の上にカーソルがいる状態で fwd_word が呼び出される。 50043 | | その状態で inc すると必ず col は 1 以上になる。 50044 | | col が 0 になるのは最終行以外で NUL を指している時に次の行に移動した時である。 50045 | | 或いは最初から 0 でしかも最終行にいてそれが空行である時である。 50046 | | 50047 | | i = inc_cursor(); 50048 | | if (i == -1 || i >= 1) 50049 | | return OK; 50050 | | } 50051 | | ここは [bn]* を読んでいるが途中で $|\n を読んだら終了。 50052 | | うーん。初めが空白だったとしたら、/b(b*n|b*$)/ = /b+(n|$)/ 50053 | | 初めが改行だったとしたら /n(b+n|b*$)/ = /nb*(bn|$)/ 50054 | | 初めが w だったとしたら /w+b*(n|$)/ という事になる。 50055 | | 50056 | | 修正: i>=1 は i==2 も含む。i==1 は改行を通った場合だが、 50057 | | i==2 は改行の直前に達した時である。改行を通った場合は行頭で戻り exclusive になる。 50058 | | 改行の直前に達した場合には行末で戻り、更に oneleft() して inclusive になる。 50059 | | } 50060 | 50061 | % aw で非空白文字の上に載っていた場合には、 50062 | % /w+($|n)|w+b*(n|$)/ を読み取る。つまり /w+b*(n|$)/ である。 50063 | % iw で空白文字の上に載っていた場合には、 50064 | % /b+(n|$)|nb*(bn|$)/ である。 50065 | % = /b+n|b+$|nb+n|nb*$/ = /n?b+n|[bn]b*$/ うーん。微妙。元のままの方が良い。 50066 | 修正: n を読み取ったら即座に終了である。もしくは改行直前に達したら終わる。 50067 | つまり iw は /b+|n/ である。実際に vim で動作を確認してみる事にする。 50068 | aw に関してはどうだろうか。w+を読み取った後に改行に達したらやはり即終了である。 50069 | 改行は読み取りの範囲内に含まれない。つまり /w+b*/ である。 50070 | check $'@:@ \necho' 'c i w' $'@:@\necho' 50071 | check $'@:@\n echo' 'c i w' $'@:@\n echo' 50072 | 50073 | if (oneleft() == FAIL) 50074 | inclusive = FALSE; 50075 | この部分は単に exclusive の解釈から inclusive の解釈になる様に修正しているだけ。 50076 | ble.sh では常に exclusive で処理しているから関係ない。 50077 | } 50078 | else 50079 | { 50080 | 先に iw の時を考える。特に end_word を引数 count = 1 で呼び出している。 50081 | stop = TRUE で empty = TRUE である。 50082 | if (end_word(1L, bigword, TRUE, TRUE) == FAIL) 50083 | return FAIL; 50084 | この時 end_word の中は以下の様な処理になる。 50085 | | []() { 50086 | | sclass = cls(); 50087 | | if (inc_cursor() == -1) return FAIL; 50088 | | ここで取り敢えず一文字進んで見る。 50089 | | @\n\n の状態から \n@\n という状態になっていたはずなので、 50090 | | 更に一文字進んで \n\n@ という状態になると考えて良い。 50091 | | 50092 | | if (cls() == sclass && sclass != 0) { 50093 | | if (skip_chars(sclass, FORWARD)) 50094 | | return FAIL; 50095 | | } else if (sclass == 0) { 50096 | | while (cls() == 0) { 50097 | | if (curwin->w_cursor.col == 0 && LINEEMPTY(curwin->w_cursor.lnum)) 50098 | | return OK; 50099 | | 空行に入ったら一つ単語を見つけたと考えて end_word を抜ける。 50100 | | 50101 | | if (inc_cursor() == -1) /* hit end of file, stop here */ 50102 | | return FAIL; 50103 | | } 50104 | | 50105 | | if (skip_chars(cls(), FORWARD)) 50106 | | return FAIL; 50107 | | } 50108 | | dec_cursor(); /* overshot - one char backward */ 50109 | | 50110 | | } 50111 | | うーん。end_word(1, bigword, t, t) を正規表現で表すとどの様になるだろうか。 50112 | | /ww+|[bn]+?(空行|w+)|w/ こんな感じである。要するに /w+|(b+n?)+w+|n/。 50113 | | 否、何か違う気がする。/w+|(n|b(b*n))(b+n)*((?=n)|b*w+)/ 50114 | | /w+|(b*n)(b+n)*((?=n)|b*w+)/ ←これで考えるのが良い気がする。 50115 | 50116 | aw に対しては空白に対して end_word が呼び出されるので、 50117 | /(b*n)(b+n)*((?=n)|b*w+)/ である。 50118 | 実のところ (?=n) の位置で n が現れる場合には、 50119 | 必ず其処で正規表現の一致が止まる (他の一致の仕方はできない) し、 50120 | それ以外の文字の時には必ず b*w+ か b+n かに当たるので、 50121 | (?=n) の要請は結局ここに文字列末端が来ないという事の要請である。 50122 | /(b*n)(b+n)*(b*w+)?/ で一致させてもし末端まで達していたら、 50123 | 最後が非空白文字である事を確認すれば良い。 50124 | 50125 | 訂正を入れる。b+w+ の場合が抜けている。 50126 | /(b*n)(b+n)*((?=n)|b*w+)|b+w+/ 50127 | = /(b*n)(b+n)*(?=n)|(b*n)(b+n)*(b*w+)|b+w+/ 50128 | = /(b*n)(b+n)*(?!$)|(b*n(b+n)*b*|b+)w+/ 50129 | 50130 | 更に訂正。b+$ の場合も抜けているのではないか。 50131 | と思ったが、これは常に失敗なので考えなくて良い? 50132 | しかし、これも考えた方が正規表現が単純になって見通しが良い。 50133 | 結局、後の確認ではねられる所ではあるが。 50134 | /(b*n(b+n)*b*|b+)(w+|(?!$))/ 50135 | 50136 | iw に対しては非空白に対して end_word が呼び出されるので、 50137 | /w+/ が使われる物と考えて良い。 50138 | } 50139 | } 50140 | --count; 50141 | } 50142 | 50143 | 整理すると以下の様な事になる。 50144 | 先ず初めに \n が次にあればそれを取り込む。 50145 | 次に以下の場合分けで読み取る。つまり、 50146 | 50147 | - iw に対しては非空白に対して /w+/ を読み取る。 50148 | - iw で空白文字の上に載っていた場合には 50149 | % /b+(n|$)|nb*(bn|$)/ を読み取る。 50150 | /b+|n/ を読み取る。 50151 | - aw で非空白文字の上に載っていた場合には、 50152 | % /w+b*n?/ を読み取る 50153 | /w+b*/ を読み取る。 50154 | - aw に対しては空白に対して 50155 | % /(b*n)(b+n)*(b*w+)?/ で一致させて、 50156 | % /(b*n(b+n)*b*|b+)w+|(b*n(b+n)*b*|b+)(?!$)/ で一致させて 50157 | /(b*n(b+n)*b*|b+)(w+|(?!$))/ で一致させて 50158 | もし末端まで達して最後が空白文字だったら失敗 50159 50160 まとめると 50161 先ず初めに \n が次にあればそれを読み飛ばす。 50162 % iw に対しては /w+|b+n?|nb*(bn)?/ で一致させる。 50163 iw に対しては /w+|b+|n/ で一致させる。 50164 % aw に対しては /w+b*n?|((b*n)(b+n)*b*|b+)(w+)?/ で一致させて、 50165 aw に対しては /w+b*|((b*n)(b+n)*b*|b+)(w+)?/ で一致させて、 50166 末端まで達して最初と最後が空白文字だったら失敗。 50167 50168 * reject: aw の条件に関してはもっとましな判定方法は無いだろうか。 50169 うーん。難しい。(?=n) さえ正規表現にあれば簡単だったという事。 50170 これは諦める事にした。 50171 50172 * ok: 一方で一番最初の単語の読み取りは全く同じでも良いのだろうか。 50173 fwd_word 及び end_word の中身は同じである。 50174 然し、その前に改行を取り込む等の事はしない。 50175 また、fwd_word の後で小細工をする。 50176 50177 x fixed: end_words は改行を取り込む事について 50178 50179 うーん。動かしてみるが思う様に行かない。 50180 exclusive/inclusive による振る舞いの変化だろうか。 50181 先に書いたコードによると、行末の非空白文字で終わった時に 50182 exclusive になるとか書いてあるけれど、これはちょっと意味が分からない。 50183 実際に読んでもその様になっている様には思われない。 50184 それよりは寧ろ、特定の条件で行頭に来た時に exclusive になっていて、 50185 その時には改行は含まないのであるという実装になっている。 50186 50187 実は end_word 等で二重改行の中で終わっていたが、 50188 実は end_word の時は inclusive に二重改行も範囲に取り込むべきなのではないか。 50189 →調べてみたところ二重改行に対しては inclusive である事を考慮した dec が行われていない。 50190 つまり、end_word で二重改行に会った時には二重改行の末尾まで取り込むという動作である。 50191 50192 これはどの様に正規表現を修正するだろうか。 50193 (?=n) だと思っていたのが n になると考えれば良い。 50194 aw で空白にいる時に 50195 /(b*n)(b+n)*(n|b*w+)|b+w+/ に一致する。 50196 % = /(b*n)(b+n)n|((b*n)(b+n)*b*|b+)w+/ 50197 % = /(b*n)(b+n)n|((b|n|b+n)(b+n)*b*)w+/ 50198 % = /(b*n)(b+n)n|(n(b+n)*b*|b(b*n(b+n)*)?b*)w+/ 50199 = /b+w+|b*n(b+n)*(n|b*w+)/ 50200 iw で非空白にいる時に /w+/ 50201 特に iw を考えている分には二重改行の類は考えなくて良さそう。 50202 そうすると aw の正規表現を修正する。 50203 % aw で非空白文字にいる時には /w+b*n?/ であったので、 50204 % /w+b*n?|b+w+|b*n(b+n)*(n|b*w+)/ という事になる。 50205 aw で非空白文字にいる時には /w+b*/ であったので、 50206 /w+b*|b+w+|b*n(b+n)*(n|b*w+)/ という事になる。 50207 50208 x fixed: operator:d の特殊ルールに対応 50209 50210 まだうまく行かない。 50211 50212 initial = echo^J@^Jhello^J^Jworld^J" -> daw 50213 expected = echo^J<^Jhello^J>^Jworld^J" 50214 result = echo^J<^Jhello>^J^Jworld^J" 50215 50216 どの様に動作するのかについて考える事にする。 50217 一番始めに前方に拡張が試みられるがこれは成功しない。 50218 改行は拡張に含まれない為である。 50219 次に一致が試みられる。改行から一致が始まる。 50220 正規表現的には hello の末端まで一致する。 50221 end_words の振る舞い的にもその様になっている筈である。 50222 dec されて o の直前にカーソルが行くので、 50223 結局囲まれる領域は hello までになるべきである。 50224 50225 何故範囲が拡張されているのだろうか。 50226 これは exclusive linewise などなのだろうか。 50227 調べてみると exclusive linewise が実行されているのは、 50228 exclusive-goto.impl の様である。 50229 txtobj では exclusive-range.impl を直接呼び出しているので補正は効かない。 50230 しかし、exclusive-goto.impl の実装を確認してみると、 50231 補正が発生するのは行頭に exclusive で移動した時の話で、 50232 行末に inclusive で移動した時には発動しないので今回の事には関係ないのでは。 50233 50234 改めて vim の実装と動作について考えてみる事にする。 50235 daw なので include == true である。 50236 cls() == 0 である。従って、end_word が呼び出される。 50237 辿ると結局実行されるのは以下の3行の様な気がする。 50238 inc_cursor(); 50239 skip_chars(cls(), FORWARD) 50240 dec_cursor(); 50241 skip_chars は異なるクラスになるまで移動する。 50242 つまり、hello の後の \n の位置で止まる。 50243 その後で dec_cursor を実行するので、 50244 hello の o の直前にカーソルが移動する。 50245 では end_word を抜けた後はどうなるだろうか。 50246 うーん。そのまま inclusive = TRUE を設定して抜けてしまう気がする。 50247 50248 うーん。行が変わって行末に行く時には inclusive から 50249 linewise になるとかあるんだろうか。 50250 うーん。やはり vim の help を見ても inclusive の時に範囲を拡張する等の話は載っていない。 50251 50252 vim のソースコードをいじって途中状態を出力させて見る事にした。 50253 すると current_word を抜ける時点ではやはり次の行の行末になっている。 50254 これはもしかすると d の方の働きによって行が削除されているという事なのだろうか。 50255 うーわ。これは d だった。https://vim-jp.org/vimdoc-ja/change.html#d 50256 50257 > コマンド "d{motion}" に関する例外: 移動が行単位でなく、移動の開始点と終了点が 50258 > 同じ行になく、移動の開始点の前に空白しかなく終了点の後に空行以外がない場合に 50259 > は、削除は行単位となる。このときユーザーは空白のみの行が残ると期待するかもしれ 50260 > ないが、共に削除される。削除を文字単位に強制したい場合は o_v を使うこと。 50261 50262 例によってよく分からない日本語であるが…。試してみる。 50263 終了点の後に空行以外がない場合、というのはどういう状況か。 50264 取り敢えず、終了点の次の行が空行以外であっても行毎削除される様である。 50265 また、終了点以降に空白しか無い場合も全部削除される様である。 50266 50267 更に判明してしまった事は o_v なる機能が存在するという事である。 50268 これは新しい項目で処理する事にする。 50269 50270 x fixed: inclusive = FALSE の時、前の \n は範囲に含まれない様だ 50271 50272 未だうまくいかない。今度は \n が沢山ある時の勘定が変だ 50273 うーん。もしかすると d の特殊ルールは空行に対しては効果がない? 50274 と思ったが確かめてみると d3j とやるとやはり空行であっても 50275 ちゃんと行単位に変換されて一行余分に削除されるという事が分かった。 50276 50277 ではやはり txtobj の段階で一つ少ない位置に一致するべきなのだろうか。 50278 vim に内部の状態を出力させてみると、ちゃんと同じ位置に止まっている様である。 50279 しかし、よく見てみると hello 直後の時と空行の時とで inclusive の状態が異なる。 50280 50281 うーん。exclusive の時には一つ前の行末に移動する事にすれば良いのか。 50282 しかし、そうすると別の operator での動作が変わってしまう。 50283 少し ciw で試してみる事にする。ciw の方では変な範囲の拡張縮小は起こらないはず。 50284 50285 ciw echo\n@①\nhello②\n③\n\n④\n\n⑤\n\n⑥\n\n⑦\nworld⑧\nZ 50286 diw echo\n@①\nhello\n②\n③\n\n④\n\n⑤\n\n⑥\n\n⑦world\n⑧Z 50287 50288 と思って調べてみたところ、ciw の場合には ③ は一つ手前に置かれる様である。 50289 というか2行しか下に移動していない。どうしてだろう。 50290 更に diw と比べてみるとちゃんと全て一行ずつ下に移動しているのが分かる。 50291 ciw 基準で実装した方が良いという事か。 50292 50293 しかし、この ciw の振る舞いが正しいとすると vim で調べた結果は何だったのか。 50294 ③ に対しては確かに3行下に移動していた様に思われた。 50295 先ず初めに 3ciw と 3diw で current_word は同じ結果を返している事を確かめる。 50296 OK これは大丈夫。しかし、実際の動作の次の行の行頭に exclusive で位置している。 50297 うーん。次に 1ciw から 8ciw まで試してみる事にする。 50298 1ciw 3:0 -> 3:0(inclusive) 結果 3:0 50299 2ciw 3:0 -> 4:4(inclusive) 結果 4:5 50300 3ciw 3:0 -> 6:0(exclusive) 結果 5:0 50301 4ciw 3:0 -> 8:0(exclusive) 結果 7:0 50302 5ciw 3:0 -> 10:0(exclusive) 結果 9:0 50303 6ciw 3:0 -> 12:0(exclusive) 結果 11:0 50304 7ciw 3:0 -> 14:0(exclusive) 結果 13:0 50305 8ciw 3:0 -> 14:4(inclusive) 結果 14:5 50306 50307 つまり、行頭 exclusive は実際には前の行の末尾として取り扱われるのだと解釈するべき。 50308 その様に修正する事にする。しかし、どの様に行頭 exclusive を判定するのか? 50309 と思ったが、実は行頭にいる時は常に行頭 exclusive と思って良いのだろうか。 50310 しかし、二重改行などを考えると inclusive という事も考えられる。 50311 うーん。改めて inclusive exclusive の条件を確認する必要がある。 50312 50313 exclusive になるのは、fwd_word で行頭に移動した時である。 50314 50315 x fixed: 今度は {N}aw がちゃんと動いていない。 50316 うーん。1caw で試すと問題ないが、 50317 2caw で試すと余分に一行削除してしまっている。 50318 50319 これは一体どの様な動作に依る物だろうか。 50320 特に3行ずつ範囲が拡大してしまっている。 50321 実装を調べてみる事にする。先ず \n を読み取る。 50322 その後で正規表現の b*n(b+n)*(n|w+) に一致している気がする。 50323 これは end_word 由来の一致である。 50324 end_word では二重改行に一致した時にその末端に一致するとした。 50325 しかし、改めて振る舞いを見てみると怪しい。 50326 改めて end_word を確認する必要があるのではないか。 50327 50328 vim の振る舞いを確認する。先ず初めに incl が呼び出される。 50329 この時 cursor は行頭にあって、incl によって次の行の行頭に移動する。 50330 aw の時 include == TRUE であり、cls() == 0 も TRUE である。 50331 従って、end_word の方に入っていく事になる。end_word の中では以下の様に処理が進む。 50332 sclass = cls(); // [ @\n@\n\n, sclass = 0 ] 50333 inc_cursor(); // [ @\n\n@\n, sclass = 0 ] 50334 if (cls() == sclass && sclass != 0) この条件は満たされない。 50335 if (!stop || sclass == 0) この条件は満たされる。 50336 while (cls() == 0) { // [@\n\n@\n] OK 50337 if (empty && curwin->w_cursor.col == 0 50338 && LINEEMPTY(curwin->w_cursor.lnum)) この条件はいきなり満たされる。 50339 goto finished; これが実行される 50340 if (inc_cursor() == -1) return FAIL; 50341 } 50342 finished: 50343 stop = FALSE; 50344 } 50345 return OK; 50346 つまり最初カーソルがあった状態から2行進んだ状態で end_word を出ていく。 50347 この時呼び出し元では行頭にカーソルがあるけれども inclusive という取り扱いである。 50348 50349 うーん。問題点は何かというと。この状態で次の単語を探しに行くと 50350 一文字進んでそれからまた一文字進む。2文字しか進まないという事である。 50351 一方で、この状態で最後の一致だとすると、inclusive として 50352 次の文字が含まれた状態になる。 50353 50354 つまり $'\n' が次に居たら取り込むという動作をしているが、 50355 実はこれは inclusive か exclusive かで切り替えるべきなのではないか。 50356 此処で改めて考え直す事にする。 50357 ble.sh の実装では常に end は exclusive で保持する様にしたい。 50358 50359 現在の実装ではどの時に exclusive でどの時に inclusive だったろうか。 50360 Vim では基本的には大体 inclusive なのである。 50361 特に現在の実装で inclusive なのか exclusive なのか気にしているのは改行で終わっている時である。 50362 iw に於いて空白に一致してその最後が改行であった時、exclusive になる。 50363 aw に於いて単語+空白に一致した時にも exclusive になる。 50364 これらの時、特に最初の一致と最後の一致だった時には最後の改行の前に移動する。 50365 これらの場合には既に exclusive としての処理を想定しているので、 50366 特に新しい処置は必要ない。 50367 50368 問題になるのは aw に於いて空白から始まる場合に最後に改行だったという状況。 50369 これが現在の end_word による一致の状況である。 50370 この時には二重改行に出会うと1つ目の改行の直後で inclusive で抜ける。 50371 つまり、exclusive で表すならば end は2つ目の改行の直後である。 50372 50373 さて、何が解釈に違いを与えるかというと、 50374 incl(&curwin->w_cursor); が結局何をした事になるのか、という事である。 50375 これは inclusive だった現在位置を exclusive の現在位置にする物と解釈していた。 50376 通常文字の上にいる時には常に inclusive であり、 50377 また incl によって exclusive な末端を得られた。 50378 また、exclusive に改行の直前にいる時には incl はその改行を範囲内に取り込むという事を意味する。 50379 一方で inclusive な改行の直前にいる時には incl は単に exclusive に変換しただけという事になる。 50380 50381 ble.sh の実装では exclusive に改行の直前にいる時には現在の実装で問題はない。 50382 一方で、inclusive な改行 (つまり end_word の二重改行) の直後にいる時には 50383 「次の行に行く」という動作はしないという様にしなければならない。 50384 元の Vim では依然として二重改行の直前にカーソルがあって、 50385 incl を経て始めてカーソルが exclusive な状態になるからである。 50386 この時対象の範囲は変化しない (元から含まれているべき改行が含まれただけ)。 50387 さて、では inclusive な改行はどの様に判定したら良いだろうか。 50388 iw の時には 空白は空白だけで読み取るので、最初が空白の時にしか最後に改行が来る事はない。 50389 しかし最初が空白の時には fwd_word が使用されるので end_word は使われない。 50390 必ず exclusive な改行が来る事になる。 50391 aw の時には最初が非空白の時には fwd_word が用いられて exclusive な改行が来る。 50392 最初が空白で最後が改行の時に end_word になって二重改行の後に現在位置が移動する。 50393 しかし vim 的にはこの時カーソルは二重改行の間に置かれて inclusive な改行の状態になる。 50394 さて、判定は rematch == ["$ifs"]*$'\n' で問題ないだろうか。 50395 特に rematch == $'\n' になる事はないだろうか。 50396 今回の状況は、必ず二重改行に一致した時なので rematch は二文字以上ある筈である。 50397 50398 % 然し、そもそも初めから二重改行を取り込まないという様にする可能性はあるだろうか。 50399 % その様な実装の時にはどの様に動作するべきだろうか。 50400 % 先ず直前の inclusive/exclusive の状態を記録する様にする。 50401 % 最後に inclusive か exclusive の状態かを見て範囲の調整を行う。 50402 % 途中の処理では実は inclusive か exclusive かは使わない。 50403 % →面倒になったのでこの可能性に関しては検討しない事にする。 50404 50405 うーん。修正したが殆ど変わらない。最後の 6caw と 6daw だけ一致する様になった。 50406 途中は常に1個余分に削除されてしまっている。 50407 改めて動作について考える必要がある。2caw について例えば考える。 50408 initial echo\n@\nhello\n\n\n\n\n\n\n\n\n\nworld\nZ 50409 expected echo\n[\nhello\n\n]\n\n\n\n\n\n\n\nworld\nZ 50410 result echo\n[\nhello\n\n\n]\n\n\n\n\n\n\nworld\nZ 50411 @ が最初のカーソル位置で [] が caw による削除範囲である。 50412 カーソルの動きについて考える。一番最初に \nhello が読み取られる。 50413 次に \n が取り込まれる。そして正規表現によって \n\n が取り込まれる。 50414 (この時の vim の動作は \n\n の1つ目の改行だけ取り込んで、inclusive の状態になる) 50415 50416 うーん。operator d の特殊ルールが適用される条件に 50417 inclusive がどうのというのもあるのだろうか。 50418 調べてみる必要がある。と思ったが、現在の対象は c である。関係ない。 50419 うーん。改めて vim でどの様になっているか確認する必要がある。 50420 vim では current_word は 50421 1caw echo\n[\nhell]o\n\n\n\n\n\n\n\n\n\nworld\nZ (inclusive) 50422 2caw echo\n[\nhello\n\n]\n\n\n\n\n\n\n\nworld\nZ (inclusive) 50423 を返している。ここで不思議なのは inclusive により 50424 hello の o は作用範囲になっているのに、 50425 inclusive により次の改行は inclusive になっていないという事である。 50426 50427 つまり inclusive の時には2つ目の改行は作用対象には入っていないという事? 50428 然し、そうするとやはり二重改行は取り込まないという様にするべきだったのだろうか。 50429 →その様に直したら呆気なくテストを通る様になってしまった。 50430 50431 * done: ble-0.2 に対しては簡単な修正を行うだけに留める事にする。 50432 →これについては取り敢えず修正はした。未だ commit は作っていない。 50433 未だ時間がかかりそうなので先にこれについて commit してしまう事にする。 50434 50435 * ok: 前方の空白を取り込む処理については inclusive/exclusive 50436 は考えなくて良いのだろうか。 50437 50438 % 改めて vim の処理について読んで見る事にする。 50439 % 前方の空白を取り込む条件は以下の通りである。 50440 % if (include_white && (cls() != 0 50441 % || (curwin->w_cursor.col == 0 && !inclusive))) 50442 % include_white は include かつ fwd_word が使われた時に設定される。 50443 % つまり、aw で最初の最初にカーソルが非空白位置にあった時に設定される。 50444 % 次に cls() は現在位置が非空白の時。この時常に inclusive なので、 50445 % 範囲の一番最後の文字が非空白の時を意味する。 50446 % 次に col == 0 && !inclusive は、改行直後でかつ exclusive の時。 50447 % 実は ble.sh では最後が exclusive の改行の時には、 50448 % 後で修正される事を見越して既に範囲を前の行末にまで狭めてしまう。 50449 % しかし、此処での問題は前の行末に非空白文字が存在するとは限らないという事である。 50450 % やはり flags に X を追加する等するべきだろうか。 50451 % 50452 % その前に vim の動作について確認する事にする。 50453 % 果たしてどの様な時に前方の空白取り込みが起こるのか。 50454 % % 特に、exclusive 改行直後に一致した時に、 50455 % % 直前に空行がある可能性はあるのだろうか。 50456 % % 例えば iw では決して二重改行に一致する事はない。 50457 % % aw では exclusive な改行になるのは非空白文字に始まって改行に終わる時であるが、 50458 % % その時二重改行に一致する事は決してない。 50459 % 然し、よく考えてみたら col == 0 && exclusive の時には、 50460 % 直前にどの様な文字があったとしても前方の空白取り込みが発生する。 50461 % つまり、直前が改行以外であったとしても、空白であれば前方の空白取り込みが発生する。 50462 % 再度振る舞いについて考える必要がある。 50463 % iw の時はそもそも前方の空白取り込みは発生しないので気にしなくて良い。 50464 % aw の時に exclusive になるのは非空白に始まって改行に一致する場合である。 50465 % つまり /w+b*n/ に一致する時である。vim の実装を見る限りでは 50466 % この場合にも前方の空白取り込みが発生する気がする。確かめる必要がある。 50467 % 50468 % うーん。試してみたが空白取り込みは発生していない様に思われる。 50469 % 実際に vim の current_word の中の様子を見るが取り込みは発生していない。 50470 % というかそもそも /w+b*/ には一致しているけれども /w+b*n?/ には一致していない。 50471 % この /w+b*n/ の出処は何処だったろうか。fwd_word の実装の観察である。 50472 % 再度確認してみる事にする。うーん。処理を大きく読み間違えていた様だ。 50473 % 正規表現はかなり簡単化する。修正した。 50474 % 既存のテストはこれに対して変化しなかった。新しいチェックも通る。 50475 % 安心ではあるが一方で既存のテストは穴だらけという事の証拠でもある…。 50476 % 50477 % 改めて考察してみる事にする。col == 0 && exclusive の時の 50478 % 改行の直前の文字として何が考えられるか。 50479 % iw で exclusive になるのは単一の改行を読み取った時である。 50480 % この時直前の文字が空白であるかどうかは分からない。 50481 % 例えば \n@\n という状態で iw を実行すると次の行に移動する。 50482 % この時、前方に空白を取りに行く。しかし、前方に空白は存在しない。 50483 % 或いは、xmap で \nhello@\n という状態で iw を実行するとどうなるのか。 50484 % (この初期状態を作るには $vlol とすれば良い。) 50485 % 試してみた所、hell[o] という選択状態になった。微妙…。 50486 % 現在位置が NUL である為、前方への拡張は行われず 50487 % 単に改行が一個読み取られるが一つ戻って結局幅 0 になる、 50488 % かと思いきや eol fix によって一つ戻る。 50489 % これは実は現在の ble.sh の実装もちゃんとそうなりそうな実装になっている。 50490 % 然し、実際に試してみた所違う振る舞いをする。テスト項目に加える。 50491 % 50492 % 色々考え合わせるとやはり col == 0 && exclusive の時の直前の文字は 50493 % 非空白文字であると仮定するのは難しい様に思われる。 50494 % ちゃんとチェックする様にする。 50495 % 50496 % 修正した。今までのテストで失敗する様になった物はない。 50497 % 新しいテストを追加するべきだろうか。 50498 % 特にこの振る舞いに依存する様な状況は何が考えられるだろうか。 50499 % つまり aw で exclusive になっているがその改行の直前が空白文字という状況である。 50500 % aw で exclusive になるのは非空白で始まって改行で終わる状況で、 50501 % しかしその様な事は起こりえない? 50502 % おかしい。何か変だ。fwd_word で exclusive が起こる。 50503 % fwd_word は include != (cls()==0) の時に呼び出されるので、 50504 % aw の時には非空白の時に使われる。うーん。 50505 % 実は aw の時には改行は読み取られないので exclusive になる事は有り得ない? 50506 50507 前方の空白を取り込む条件は、 50508 1. include_white ... aw でありかつ最初の位置が空白文字だった時、かつ 50509 2a. 範囲の最後の文字が非空白文字だった時 50510 2b. 最後の位置が行頭でありかつ exclusive だった時 50511 50512 ここで 2b の条件は絶対に満たされない様に思われる。 50513 先ず、include_white を判定している時点で aw である。 50514 aw の時 exclusive になるのは fwd_word を呼び出した後 (しかも成功) である。 50515 fwd_word を呼び出す前は必ず非空白文字になっている筈。 50516 fwd_word で行頭になるのはどういう状況かというと、fwd_word の中を見ていくと、 50517 50518 | 先ず count = 1, eol = TRUE である。最初のループで count == 0 になる。2回目以降のループはない。 50519 | sclass = cls(); // sclass には非空白文字のクラスが設定される 50520 | last_line = (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) 最終行の時1 50521 | i = inc_cursor(); // 非空白文字なので必ず成功する。改行の直前であれば 2 それ以外なら 0 50522 | if (i == -1 || (i >= 1 && last_line)) // これが満たされる時は FAIL が返されて、そもそも exclusive にならない。 50523 | return FAIL; 50524 | if (i >= 1 && eol && count == 0) // ここに入る可能性はある。 50525 | // つまり改行の直前にいた時 @a\n → a@\n という形になる。 50526 | // しかし fwd_word 呼び出しの後の oneleft が成功するので exclusive にはならない。 50527 | return OK; 50528 | 50529 | if (sclass != 0) // 非空白なのでこの中には入っていく 50530 | while (cls() == sclass) // w+ を読み取る。 50531 | { 50532 | i = inc_cursor(); // 改行に接したら 2 が返される。それ以外ならば 0 である。 50533 | if (i == -1 || (i >= 1 && eol && count == 0)) 50534 | return OK; // ここに来るのはファイル末端か www@\n という状況である。 50535 | // 必ず w があるので oneleft が成功して exclusive にはならない。 50536 | } 50537 | 50538 | while (cls() == 0) // 改行以外の空白に当たった時にここに入る。 50539 | { 50540 | if (curwin->w_cursor.col == 0 && *ml_get_curline() == NUL) 50541 | break; // 空行の時、という事だが w+b+の後なので此処には入らない。 50542 | 50543 | i = inc_cursor(); 50544 | if (i == -1 || (i >= 1 && eol && count == 0)) 50545 | return OK; // ファイル末端化 w+b+@\n に当たった時には必ずここに入る。 50546 | // この時も必ず oneleft() が成功するはず。 50547 | } 50548 | ここまで来るのは cls() != 0 になった時である。 50549 | つまり、また別の単語が始まった時である。 50550 | ここで抜けるとやはり必ず oneleft() が成功するはずである。 50551 50552 やはり fwd_word で行頭で抜けて oneleft() が失敗して exclusive になるという事は有り得ない気がする。 50553 50554 或いは oneleft はまた別の実装になっているのだろうか。 50555 何と、確認してみた所 virtual_active() の時には oneleft は getviscol() つまり、 50556 見た目の列で左に行くか行かないかが決まる様である。つまり、 50557 行の途中であっても exclusive になったりならなかったりする。 50558 これだと色々動作的に困る気がするのだが大丈夫なのだろうか… 50559 と思ったが実はそんなに問題にはならないのかもしれない。 50560 oneleft() する事と exclusive にする事は大体同じ動作だからである。 50561 何れにしても virtual_active() が成立していない時には oneleft は単に col を見ているだけである。 50562 50563 結論: virtual_active() における oneleft() の動作を考えなければ、 50564 aw に於いて exclusive の状態になる事は有り得ない。 50565 従って、exclusive の判定は aw ではしなくて良いし、 50566 前方拡張についても exclusive の判定は省略可能である。 50567 50568 x fixed: xmap について漸くテストを開始する。 50569 と思ったら早速振る舞いが変だ。 50570 viw が ciw と異なる範囲を選択している。 50571 vim の方では同じ範囲になる。 50572 50573 うーん。調べてみると行末でなければ index++ するという振る舞いになっている。 50574 この振る舞いの根拠は一体何だったのだろうか。 50575 一応 vim の実装の方でも特殊な事をしていないかを確認する事にする。 50576 50577 if (VIsual_active && *p_sel == 'e' && LT_POS(VIsual, curwin->w_cursor)) 50578 dec_cursor(); 50579 50580 うーん。寧ろ条件に依ってカーソルの位置を後退している。 50581 しかしこれは exclusive の位置から inclusive の位置に変換する為に行っている事。 50582 他には、事前の操作で visual モードの時に特別なことをするという処理は見当たらない。 50583 それよりも事後で何かしている。 50584 50585 if (VIsual_active) { 50586 if (*p_sel == 'e' && inclusive && LTOREQ_POS(VIsual, curwin->w_cursor)) 50587 inc_cursor(); 50588 if (VIsual_mode == 'V') 50589 { 50590 VIsual_mode = 'v'; 50591 redraw_cmdline = TRUE; /* show mode later */ 50592 } 50593 } 50594 50595 選択が exclusive の場合には inc_cursor している。 50596 しかしビジュアルモードの選択が exclusive というのはどういう状況だろうか。 50597 少なくとも現在の ble.sh では対応していない機能である。 50598 他に行ビジュアルモードだったら文字ビジュアルモードに変更して再描画する。 50599 50600 実はビジュアルモードに対して特別な事をする必要はないのではないかという気がする。 50601 余分な処理を除去したら全て動く様になった。 50602 50603 x fixed: 次に vhiw と vhaw のテストを試してみたら全滅だった。全然駄目。 50604 これはまた vim の振る舞いについて研究が必要になる。 50605 50606 後退時は幾分簡単で以下のコードが繰り返し適用されるだけである。 50607 ここより前の部分にも幾らかコードがあったが、何れも条件を満たさないので実行されない。 50608 50609 | if (VIsual_active && LT_POS(curwin->w_cursor, VIsual)) 50610 | { 50611 | if (decl(&curwin->w_cursor) == -1) 50612 | return FAIL; 50613 | 先ずは現在位置を後退する。行頭にある場合には前の行の最後の文字に移動する。 50614 | 前の行が空行だったらそのまま前の行の行末。 50615 | それ以外の場合には一文字左に移動する。 50616 | 50617 | if (include != (cls() != 0)) 50618 | { 50619 | iw (include == false) で非空白文字 (cls()!=0) にいる時。 50620 | もしくは aw で空白文字にいる時。 50621 | 50622 | if (bck_word(1L, bigword, TRUE) == FAIL) 50623 | return FAIL; 50624 | 50625 | | bck_word = [] { 50626 | | sclass = cls(); 50627 | | if (dec_cursor() == -1) return FAIL; // 一文字戻る。戻れなければ失敗(※1) 50628 | | if (sclass == cls() || sclass == 0) { 50629 | | 最初の文字が w の場合と b と n (空行の時のみ) の場合がある。 50630 | | この時点で /@.[wbn]$/ という状態である。 50631 | | while (cls() == 0) { 50632 | | 最初が b または n ならば空白類は読み飛ばしたい。 50633 | | 現在位置が空行ならば直ぐに止まる。 50634 | | n@n[bn]$ という状況だと即停止してしまう。 50635 | | n@nb*$ という状況や nnb*n$ という状況など。 50636 | | 正規表現で表せば b*n(b+n)*b*n?$ という事になるだろうか。 50637 | | if (curwin->w_cursor.col == 0 50638 | | && LINEEMPTY(curwin->w_cursor.lnum)) 50639 | | goto finished; 50640 | | if (dec_cursor() == -1) /* hit start of file, stop here */ 50641 | | return OK; 50642 | | もしファイルの先頭に達したらOK 50643 | | つまりこれは /^b*n(b+n)*b*n?$/ というのに一致する状況。 50644 | | } 50645 | | 50646 | | if (skip_chars(cls(), BACKWARD)) 50647 | | return OK; 50648 | | 最初が w の時には ww$ ならば skip_chars がそのまま実行されて 50649 | | うーん。何か変な位置で停止する気がする。と思ったけれども、 50650 | | if (skip_chars()) が 0 以外を返すのは失敗した時だから良い。 50651 | | 要するに /w+$/ を読み取った場合という事になる。 50652 | | 最初が b または n の時には /w*b*n(b+n)*b*n?$/ に一致する。 50653 | | 但し、/^b*n(b+n)*b*$/ の時は既に一致しているし、 50654 | | /n@n(b+n)*b*$/ の時は既に終了している筈なので、 50655 | | 此処に入ってくるのは /w+b*n(b+n)*b*n?$/ である筈。 50656 | | } 50657 | | 上の条件文の中から来た場合は /@.w{2,}|@.w+b*n(b+n)*b*n?$/ である。 50658 | | 条件文に入らないのは @Ww$ や @bw$ や @nw$ の時である。 50659 | | つまり、/@.w+(b*n(b+n)*b*n?)?$/ という事の様に思う。 50660 | | 50661 | | inc_cursor(); /* overshot - forward one */ 50662 | | ここで /w+(b*n(b+n)*b*n?)?$/ に一致する様になる。 50663 | | finished: 50664 | | return OK; 50665 | | } 50666 | 50667 | 合わせると /^b*n(b+n)*b*n?$|w+(b*n(b+n)*b*n?)?$|(?<n)b*n(b+n)*b*n?$/ である。 50668 | 二重改行の条件は潰せないだろうか。/b*n(b+n)*b*n?/ の直前に来るのは、 50669 | 可能性としては ^nw の何れかである。b があれば一致するので。 50670 | また先に w+* を判定しておけば w が来る事もない。 50671 | 二重改行以外の n の場合もちゃんと b*n 側に含まれる筈である。 50672 | 従って ^ または二重改行にちゃんとなる。 50673 | /w+$|w*b*n(b+n)*b*n?$/ これで判定すれば良い。 50674 | 50675 | 特に iw で非空白文字にいる時は /w+$/ であり、 50676 | aw で空白文字にいる時は /w*b*n(b+n)*b*n?$/ である。 50677 | 50678 | 所で※1の部分を見ると vim は 'he@llo' に対して vhiw とするとエラーになる。 50679 | 'hel@lo' に対して vhiw はエラーにならないのに。 50680 | これは本当に意図した振る舞いなのだろうか。 50681 | 50682 | } else { 50683 | if (bckend_word(1L, bigword, TRUE) == FAIL) 50684 | return FAIL; 50685 | | bckend_word = [] { 50686 | | sclass = cls(); // /.$/ 50687 | | if ((i = dec_cursor()) == -1) 50688 | | return FAIL; // /^.$/ だったら失敗 50689 | | if (i == 1) // /\n.$/ だったら成功 50690 | | return OK; 50691 | | 50692 | | if (sclass != 0) { // /.w$/ の時 50693 | | while (cls() == sclass) 50694 | | if ((i = dec_cursor()) == -1 || (eol && i == 1)) 50695 | | return OK; /(^|\n)w+$/ だったら成功 50696 | | /.w+$/ という状態 50697 | | } 50698 | | この時点で /.w+$|.[bn]$/ という状態である。/.(w+|[bn])$/ とまとめる。 50699 | | 50700 | | while (cls() == 0) { 50701 | | if (curwin->w_cursor.col == 0 && LINEEMPTY(curwin->w_cursor.lnum)) 50702 | | break; 現在位置が二重改行ならば終了 50703 | | if ((i = dec_cursor()) == -1 || (eol && i == 1)) 50704 | | return OK; 一つ前に ^ または n があればそれを読んで終了 50705 | | } 50706 | | % この部分は、最初に n があったならば二重改行の判定をして、 50707 | | % それ以降にはそもそも n を呼んだ時点で終了するので、 50708 | | % 二重改行が現れる事はないはずである。 50709 | | % つまり、/n@n(w+|[bn])$/ ならばそこで抜ける。 50710 | | % それ以外ならば /(^|n)b+[bn](w+|[bn])$/ で終了。という具合。 50711 | | % 途中で空白以外になったらやはり終了。 50712 | | % つまり /wb+[bn](w+|[bn])$/ の様な物。 50713 | | 実はこの部分で最初に n がある事はない。 50714 | | 改行 n が途中で現れたとしてもそれを読んで抜ける。 50715 | | 従って、この部分を抜けた後は /wb*(w+|[bn])$/ である。 50716 | | 50717 | | % まとめると、/w(w+|[bn])$/ だったらそのまま。 50718 | | % /nn(w+|[bn])$/ だったら1文字進める。 50719 | | % /b+[bn](w+|[bn])$/ で読めるだけ読んでおけば良い。 50720 | | % 直前が wn だった場合には余分に1文字後退する。 50721 | | % 直前が ^ だったらそのまま。直前が b である事はない。 50722 | | 50723 | | うーん。結局 break しても return OK しても直後に 50724 | | return OK があるから違いはないのである。 50725 | | その様に考えればこのループが終わるのは 50726 | | 改行を飛び越えた後か、飛び越えた文字が空白以外か、 50727 | | 編集文字列の先頭に達したかという事であるか、 50728 | | という事であるから /(^|[wn])b*(w+|[bn])$/ である。 50729 | | 50730 | | return OK; 50731 | | } 50732 | 50733 | (void)incl(&curwin->w_cursor); 50734 | 50735 | これによりどうなるか。 50736 | 50737 | 1. /(^|n).$/ の時には /.$/ になる。 (vim 実装では ^.$ は失敗なのだがこれは多分ミス) 50738 | →と思ったが /^.$/ の場合には /$/ になってしまうのでは。つまり、動かない。 50739 | 従って /.$/ の時には失敗で /\n.$/ の時には /.$/ に一致する。 50740 | しかしながら結局後で失敗した時には先頭位置に移動するのでやはり /.$/ になると言って良い。 50741 | 50742 | 2. /(^|n)w+$/ の時には /w+$/ になる。 50743 | 50744 | % 3. /n@n(w+|[bn])$/ の時には /(w+|[bn])$/ になる。 50745 | % →と思ったが /w+$/ の時には n が来た時点で抜ける筈なので、 50746 | % 実際に実現するのは /n@n[bn]$/ のパターンのみである。 50747 | % 更に /n.$/ のパターンは既に /.$/ という取り扱いになるという事を考えると、 50748 | % /n@n[bn]$/ の場合もここまで進む前に抜けてしまうはずである。 50749 | % 従って、このパターンは実際にはテキストオブジェクトでは起こらない。 50750 | % 4. /^bb*[bn](w+|[bn])$/ の時には最初の b が削られて /b*[bn](w+|[bn])$/ になる。 50751 | % 更に incl なので bn という状況になっている場合には二文字進むなどもある。 50752 | % →これは上記と同様の議論によって、実際には /bb*b(w+|[bn])$/ しか実現しない。 50753 | % /[wn]b+[bn](w+|[bn])$/ に対しては /b+[bn](w+|[bn])$/ となる。 50754 | 50755 | 3. /(^|[wn])b*(w+|[bn])$/ で抜けた時には、 50756 | incl によってどうなるか。場合分けが必要である。 50757 | 50758 | | a /^(w+|[bn])$/ 50759 | | % 実は /^[bn]$/ だったら既に失敗している筈なので、 50760 | | % /^w{2,}$/ しか実現されない。この時には incl によって /w@w+$/ になる。 50761 | | % 然し、本当にその様な動作になるだろうか…。うーん。 50762 | | % 実は dec_cursor() == -1 になった時というのは ^ を読み飛ばして、 50763 | | % 負のインデックスになっているという事なのかもしれない。 50764 | | % →うーん。確認してみたが (0,0) の位置にいる場合には、 50765 | | % 其処から動かずに dec_cursor() == -1 になっている。 50766 | | % つまり、次の decl によって一文字進んでしまう気がする。 50767 | | % 50768 | | % 然し、その様な実装になっているという事が今一理解できない。 50769 | | % 実際に実行して試してみる事にする。何と再現した…。 50770 | | % check 'echo@ hello' 'v h a w S a' 'e@<cho >hello' → これは vi_test.sh に追記した。 50771 | | 50772 | | 結局 /^w{2,}$/ ならば /w@w+$/ の位置になる。 50773 | | 50774 | | b /^b+(w+|[bn])$/ 50775 | | 50776 | | % 特に /^bn$/ の場合には2文字進む気がする。 50777 | | % そして最初と同じ位置になる。 50778 | | % これは本当にそうだろうか。試してみる事にする。 50779 | | % うーん。bn@ で aw を実行するとエラーに為る。 50780 | | % と思ったが、ここで試すべきは iw ではないだろうか。 50781 | | % うーん。bn@ で iw に対してもエラーになる。 50782 | | % /^bbn$/ の時には iw で /b@bn$/ になる。 50783 | | % 50784 | | % →うーん。改行の直前の場合には少し異なる動作をする。 50785 | | % /^bn$/ の時には最初の decl で /^@bn$/ という状態になる。 50786 | | % 50787 | | % もう少し真面目に考える必要がある。 50788 | | % 二重改行の場合には /^n@n$/ という形になって、 50789 | | % iw を実行した時に bckend_word に入るが、 50790 | | % /^n@n$/ から /^@nn$/ になってしかし改行を越えたという事で 50791 | | % 其処で終了して直後の incl で /^@n$/ という形になる。 50792 | | % /^@n$/ の場合には戻ろうとした時に失敗して、結局失敗する。 50793 | | % それ以外の場合には必ず n 以外の位置にカーソルがあるはず。 50794 | | % つまり /[wb]$/ という事になる。 50795 | | 50796 | | その様に考えると $ の直前の構造として考えられるのは、 50797 | | /(^|n)n$/ か /[wb]$/ かのどちらかしかない。 50798 | | 従って、/^bn$/ や /^bbn$/ の状態が達成される事はない。 50799 | | 50800 | | 更に言うと /(^|n)n$/ の構造になっている場合には、 50801 | | その前の段階で失敗か成功をするので、ここまで来る事はありえない。 50802 | | /n$/ つまり、n が $ の直前に来る場合については想定しなくて良い。 50803 | | 50804 | | この場合には /^b{2,}$/ または /^b+w+$/ が実現される。 50805 | | 何れの場合でも最初の b は incl によって除外される。 50806 | | 50807 | | % c /[wn](w+|[bn])$/ 50808 | | % これは先の議論によって /[wn](w+|b)$/ という状態しか実現しない。 50809 | | % w+ の場合には w+ で w は読み切る筈なので /^w{2,}$/ だが、 50810 | | % これは別の場合に含まれる。或いは /nw+$/ である。 50811 | | % その場合には /w+$/ にまで縮小して終わる。 50812 | | % /wb$/ の場合には 50813 | | % 50814 | | % d /[wn]b+(w+|[bn])$/ 50815 | | % これも先の議論によって /[wn]b+(w+|b)$/ という状態しか実現しない。 50816 | | % 50817 | | % これは別の場合分けをした方が良い気がしてきた。 50818 | | 50819 | | e /[wn]w+/ 50820 | | % /w{2,}$/ これは /w@w+$/ となるが、そもそも此処に来るのはどの様な場合か。 50821 | | % /bw{2,}$/ という場合には b を読んで次の場合に入る筈だ。 50822 | | % /nw{2,}$/ という場合には /nw+/ という場合になる。 50823 | | % 途中で ^ に当たる場合は既に処理している。 50824 | | 50825 | | 従って、此処に入るのは /nw+$/ というパターンしか存在しない。 50826 | | その場合には /n@w+$/ になる。 50827 | | 50828 | | f /[wn]b+w+/ 50829 | | 此処に入るのは、うーん。これは普通に実現しそうである。 50830 | | この場合には最終的に /[wn]@b+w+$/ という事になる。 50831 | | 50832 | | g /[wn]b+/ 50833 | | これも普通に実現しそうである。/[wn]@b+$/ という事になる。 50834 | 50835 | 以上をまとめると /^w{2,}$/ ならば /w@w+$/ の位置になる。 50836 | /^b{2,}$/ または /^b+w+$/ の時には /^b@(b+|w+)$/ となる。 50837 | /nw+$/ の時は /n@w+$/ になる。 50838 | /[wn]b+w+/ 及び /[wn]b+/ の場合にはやはり一文字飛ばす。 50839 | 50840 | 最後が w の時とそれ以外の時で分けて考える事にする。 50841 | 50842 | a aw非空白の場合: /^w{2,}$/ または /^b+w+$/ または /nw+$/ または /[wn]b+w+$/ で、 50843 | 何れの場合でも 1 文字進める。 50844 | まとめると、/(^w|n|(^|[wn])b+)w+$/ で、何れの場合でも1文字進める。 50845 | 1.2. の時も考え合わせると /^w$/ の時には一回失敗となって先頭に置かれる。 50846 | /nw$/ の場合には /n@w$/ になる。/(^|n)w+$/ の場合には一文字進む。 50847 | 50848 | 従って、/(^|n|(^|[wn])b+)w+$/ で、一致長さが2文字以上の時に1文字進む。 50849 | もう少し変形できないだろうか。 50850 | /(^|n)w+$|(^|[wn])b+w+$/ 50851 | うーん。微妙 (^|[wn]) を共通化するのは分かりにくくなる。 50852 | 50853 | b iw空白の場合: 最後が n の場合は此処には入らない。最後が b の場合は、 50854 | /^b{2,}$/ または /[wn]b+/ の場合で、これは1文字進む。 50855 | 1.2. も考えると /(^|n)b$/ の時には、/nb$/ なら1文字進んで、 50856 | /^b$/ は一回失敗して先頭に行く。/(^|n)n$/ の時には、/n$/ に一致する。 50857 | 50858 | 従って、/(^|[wn])b+$/ の時、一致長さが2文字以上の時に1文字進む。 50859 | 50860 | これらを "1文字進む" という特別動作を行わないで済むように変換できるだろうか。 50861 | 50862 | a aw非空白: 先ず /w+$|b+w+$/ に一致させる。直前に ^ がなければ、 50863 | 直前には wbn の何れかが存在するはずである。w+ の場合には直前は b か n である。 50864 | その場合は結局 1文字進めるという動作は /w+$/ に一致するのと同じ事である。 50865 | b+w+ の場合には直前は wn の何れかである。これの場合も結局1文字進めるという動作は 50866 | /b+w+$/ に一致させるのと同じ動作である。直前が ^ である時は、 50867 | /^b*w+$/ に一致させる事になるが、この時は1文字進める必要が出てくる。 50868 | 50869 | 従って /b*w+$/ に一致させて、その後で「先頭まで一致してかつ2文字以上一致している時に1文字進める」 50870 | 50871 | b iw空白: /b+$/ に一致させて、その後で「先頭まで一致してかつ2文字以上一致している時に1文字進める」 50872 | 50873 | # さて、暫く時間が空いたので何を考えていたのか分からなくなってしまった。 50874 | # 覚えているのは xmap で後退する時の読み取り規則を正規表現で表そうという事である。 50875 | # 呼び出される関数が最初のカーソル位置の空白・非空白で切り替わる。 50876 | # (1) 一方は iw で非空白文字にいる時または aw で空白文字にいる時である。 50877 | # (2) 他方は aw で非空白文字にいる時または iw で空白文字にいる時である。 50878 | # vim の振る舞いには怪しい点が幾つかあるのでそれを都合よく修正して解釈する事にする。 50879 | # (2) に関しては取り敢えず前の単語の末端を見つけてから一つ文字を戻すという作戦である。 50880 | } 50881 | } 50882 50883 iw ならば /(w+|b+)?$/ に一致させる。一致部分が /^bb/ に一致するならば一文字進める。 50884 aw ならば /(b*w+|w*b*n(b+n)*b*n?)$/ に一致させる。一致部分が /.w$/ に一致するならば一文字進める。 50885 50886 本当にこれで良いのだろうか…。直前の decl に対してどの様に動作するだろうか。 50887 特に直前に行頭にいた時には /.n$/ という状態になって一致が始まるのではないか。 50888 それは即ち改行(空行以外)があった時のみ1文字戻ると解釈される。うーん。 50889 取り敢えず実装してみる事にする。 50890 50891 うーん。aw空白で始まった時の w+b+ が条件に含まれていない。 50892 現状の実装だと必ず改行が含まれなければならない事になっている。 50893 改めて bck_word を調べなければならない。 50894 50895 | bck_word = [] { 50896 | sclass = cls(); 50897 | if (dec_cursor() == -1) return FAIL; /^.n?$/ の時は失敗 50898 | この時点で /..n?$/ という状態になっている。 50899 | if (sclass == cls() || sclass == 0) { 50900 | ここでは /(ww|.[bn])n?+$/ という状態になっている。 50901 | while (cls() == 0) { 50902 | % ここに入ってくるのは /[bn][bn]n?+$/ の時のみ。 50903 | % 現在位置が空行ならばすぐに止まる。つまり /n@[bn][bn]n?+$/ で止まる。 50904 | % これに従うと最大で nnn を読み取れる様になっている気がするが…。 50905 | % うーん。n?+ が読み取られるのは n の直前に n 以外がある時のはずである。 50906 | % つまり n?+ というよりは ((?<!n)n)? である。これは N と書く事にして後で考える。 50907 | 50908 | ここに入ってくるのは /[bn][bn]N$/ の時のみである。 50909 | 50910 | if (curwin->w_cursor.col == 0 50911 | && LINEEMPTY(curwin->w_cursor.lnum)) 50912 | goto finished; 50913 | if (dec_cursor() == -1) /* hit start of file, stop here */ 50914 | return OK; 50915 | } 50916 | 50917 | 現在位置が空行ならばすぐ止まる。/n@n[bn]N$/ だと止まる。 50918 | それ以外ならば二重改行が現れる迄は [bn]* を読み取る。 50919 | 要するに /(ww|b*(n(b+n)*b*)?[bn])N$/ という事である。 50920 | 50921 | 途中で二重改行または編集文字列の先頭に達した場合は既に抜けている。 50922 | つまり、ここまで到達するのは w に出会った時である。 50923 | if (skip_chars(cls(), BACKWARD)) 50924 | return OK; 50925 | 50926 | もし w+ を読み取っている途中で文字列の先頭に到達した場合には、 50927 | その場で抜ける。w 以外の文字に到達した場合には下に流れる。 50928 | 最終的に w の先頭に移動してそれから抜ける事になる。 50929 | } 50930 | そもそも上の if 文に入らなかった場合も此処に来る。 50931 | それは /[bn]wN$/ 等である。 50932 | inc_cursor(); /* overshot - forward one */ 50933 | finished: 50934 | return OK; 50935 | } 50936 50937 まとめると、/(w+|w*b*(n(b+n)*b*)?[bn])N$/ ただし N = ((?<!n)n)? という事。 50938 ここに入るのは N を読み取った直後に iw非空白 または aw 空白にいる時である。 50939 50940 a iw非空白: /w+N$/ 50941 b aw空白: /w*b*(n(b+n)*b*)?[bn]N$/ 50942 50943 これに従って再度正規表現を修正する。iw の方は修正は不要である。 50944 aw の方は [bn]N は /bN|nN/ = /bn?|n/ と書き換えられる。 50945 50946 因みに、vim の変な振る舞いについてまとめておく事にする。 50947 50948 | 'hell@o' vhaw 'h[ello]' 50949 | ' @ ' vhiw ' [ ]' 50950 | 'ab@c' vhiw '[abc]' + bell 50951 | 'ab@c' vhaw '[abc]' + bell 50952 | ' @ ' vhiw '[abc]' + bell 50953 | ' @ ' vhaw '[abc]' + bell 50954 50955 * ok: 所で xmap の時には末端に文字を移動する事ができるという事に注意しなければならないのでは…。 50956 これまで調べた vim の振る舞いも末端に文字が存在しないという事を仮定してはいなかったか。 50957 これに関してはテストを追加した。 50958 50959 余り深追いしたくないが実際に試してみると違いがある。 50960 50961 test(txtobj word xmap/Bn/viw): keys = (v $ o $ i w c) 50962 initial = "0:echo hello^Jecho world" 50963 expected = "9:echo hell^Jecho world" 50964 result = "9:echo hellecho world" 50965 50966 行末までのはずが次の改行まで削除されてしまっている。 50967 operator:c により範囲が拡張されているのかと考えたが、 50968 実際に試してみるとそうでも無い様である。 50969 operator:c に範囲が渡された時点で次の行末までになっている。 50970 50971 というより、iw で範囲選択している段階ではちゃんと行末までになっていた気がする。 50972 これは iw の問題ではない…と思ったが、そもそものテストケースは正しいのだろうか。 50973 と思って試してみたらテストケースの方が誤っていた。 50974 50975 2018-10-06 50976 50977 * syntax (reported by cmplstofB): コメント上の単語が何故か除去されない [#D0854] 50978 https://github.com/akinomyoga/ble.sh/issues/17 50979 50980 調べてみると悪いのは 854c3b4 のようである。 50981 少なくともここで発現する様になった。 50982 しかし、ここでは単語に関する着色は何もしていない。 50983 うーん。もっと前にやった変更がここで発現する様になっただけの可能性もある。 50984 50985 うーん。ble-highlight-layer:syntax/update-word-table 冒頭には 50986 「単語の削除に関しては後で考える」と書かれている。 50987 50988 うーん。改めて 854c3b4 を見てみる。 50989 .apply-attributes で着色を削除する d の判定が増えている。 50990 もしやと思って呼び出し元を調べてみた所、 50991 '' で呼び出して削除しようとしているところがあった。直した。 50992 50993 * color: workaround Bash 3.0 算術式で <() がプロセス置換に勘違いされる [#D0853] 50994 検索してみたが他の箇所では <() という構造は現れていない様だ。 50995 50996 2018-10-01 50997 50998 * 2018-09-23 manual: 説明書について書き始める (2) complete 等 [#D0852] 50999 51000 - done: auto-complete: C-j が誤って insert になっていた 01476a7 51001 51002 - done: dabbrev: RET, C-m は確定で、C-RET, C-j で実行にした方が良いのでは 01476a7 51003 51004 - done: edit: M-S-f, M-S-b を束縛するべきところ M-C-f, M-C-b を束縛している箇所があった c68e7d7 51005 51006 - done: complete: auto_complete の M- 事情はどうなっているのか? edd481c 51007 bleopt decode_isolated_esc=auto だと M- が吸収されてしまう。 51008 結局 decode_isolated_esc=auto で default_keymap もチェックする事にした。 51009 51010 - done: isearch/exit-delete-forward-char は実態を反映していないのでは db28f74 51011 →これは元々 emacs の動作に合わせる為だった気がする。 51012 emacs では検索して C-d とするとその位置の文字が削除される。 51013 検索して一致した部分が削除される訳ではないのである。 51014 改めて試してみると確かにそうだった。 51015 51016 Bash の振る舞いはどうであっただろうか。 51017 Bash はもっと原始的な振る舞いしかしない。 51018 常にカーソルは一致範囲の先頭であり、 51019 また、C-d とするとその位置の文字が削除される。 51020 51021 一方で、現在の ble.sh の実装ではその他の様々の操作も全て 51022 一致した範囲に作用する様になっている。つまり、 51023 C-d だけ別の振る舞いをするというのも不自然である。 51024 従って、今の振る舞いのままで良いが、 51025 exit-delete-forward-char は Bash/Emacs 互換の動作として、 51026 既定では束縛しない様にする。 51027 51028 - done: auto_complete 及び menu_filter の有効無効も切り替えられた方が良いのでは 4425d12 51029 51030 - done: bleopt complete_stdin_frequency は改名したい 51031 これに対応する為にはうーん。 51032 complete_stdin_frequency に bind した時に警告を発生する様にしたい。 51033 後、どの様な変数名が適当であろうか。 51034 complete_stdin_check_interval 51035 complete_polling_cycle が良さそうだ。知っていれば何かすぐに分かる。 51036 古い変数名に対するチェックも行った。 51037 51038 * refactor: 関数名を整理する [#D0851] 51039 51040 特に / を含まない ble から始まる関数は 51041 ユーザに公開する関数のみに留める事にする。 51042 元々は他のファイルに公開する関数のみに留めようと考えていたが、 51043 そんなに疎結合ではなかったので限界がある。 51044 51045 * 文字符号化方式関連では以下の関数が存在している。 51046 - ble-decode-byte+* 51047 - ble-text-b2c+* 51048 - ble-text-c2b+* 51049 - ble-text-c2bc+* 51050 51051 以下の様に改名したい。 51052 - ble/encoding:*/decode 51053 - ble/encoding:*/b2c 51054 - ble/encoding:*/c2b 51055 - ble/encoding:*/c2bc 51056 51057 改名した。 51058 51059 * attach/detach 関連は特に初期の公開のポリシーに従っていた為に 51060 ble-edit-attach や ble-decode-attach 等が存在している。 51061 これらは ble-edit/attach や ble-decode/attach に変更する。 51062 然し、ble-edit/attach については既に存在している。使い分けは何だろうか。 51063 51064 - ble-edit/attach -> ble-edit/attach/.attach # PS1 IFS IGNOREEOF LINENO 等の調整 51065 - ble-edit/detach -> ble-edit/attach/.detach # 同上 51066 - ble-edit-attach -> ble-edit/attach # 上 + カーソル位置原点 51067 - ble-edit-finalize -> ble-edit/detach # 上 + ごみの削除 51068 - ble-edit-initialize -> ble-edit/initialize # プロンプト用定数の初期化 51069 51070 ble-decode 関連は特に衝突も無い様だ。 51071 51072 - ble-decode-attach -> ble-decode/attach 51073 - ble-decode-finalize -> ble-decode/detach 51074 51075 改名した。 51076 51077 * ble-decode-key 及び ble-decode-char はあるのに 51078 ble-decode-byte は存在しない。一応ユーザに提供するという名目で公開する事にしても良い。 51079 51080 # 然し、実は bind 'kseq: "string"' に対応する時に使う事になる様な気がしている。 51081 51082 2018-09-29 51083 51084 * 2018-09-23 manual: 説明書について書き始める (1) decode [#D0850] 51085 51086 - core: bleopt に設定名を指定子て設定内容を表示させる時、設定名の存在を確認する 725d09c 51087 - decode (ble-bind): オプション `-cf` 及び `-xf` をそれぞれ `-c` 及び `-x` に変更 f7f1ec8 51088 - decode (ble-bind): オプション `-d` に於いて `-c` 及び `-x` の引用符が二重になっている問題の修正 f7f1ec8 51089 - decode: 組み込みコマンド bind を上書きして引数をチェックする f7f1ec8 51090 - decode (ble-bind): オプション `--list-widgets` 64ad962 51091 - decode (ble-bind): オプション `[-m keymap]... -P|--print|-D|--dump` 64ad962 51092 - decode (cmap/default): rxvt の <kbd>(C-)?(S-)?(up|down|right|left)</kbd> 及び <kbd>S-(f11..f20|home|end|insert|delete|prior|next)</kbd> に対応 dc013ad 51093 - decode (cmap/default): <kbd>kpspace</kbd> は <kbd>SP</kbd> として受信する dc013ad 51094 - decode (csi/.decode): <kbd>kp5</kbd> を <kbd>CSI 1 ; <i>mod</i> u</kbd> で送る端末に対する対策 dc013ad 51095 - decode: `bleopt decode_isolated_esc=auto` 設定を追加 9b20b45 51096 51097 * decode: バッチで挿入を実行するという事を考えたが、微妙な点が様々ある [#D0849] 51098 51099 - 元々のアイディアは emacs もしくは vi_ins において、 51100 ble-bind -f __batch_chars__ ... 的な設定を追加して、 51101 __batch_chars__ が存在すればそれを呼び出して挿入を行うという物である。 51102 - overwrite_mode や選択領域がある場合などには 125 を返して、 51103 そうしたら通常通り1バイトずつ処理するモードに入る。 51104 51105 % 微妙な点は以下の通り。 51106 % 51107 % x ASCII の GL 図形文字の範囲を特殊な文字に使用する文字コードで駄目。 51108 % 例えば iso-2022 は GL 図形文字を色々に変更することができる。 51109 % またマルチバイト文字の二バイト目以降として 51110 % GL 図形文字を使っている文字コードがあっても不思議ではない。 51111 % →これに関しては先に文字コードの復号だけ行ってから実際の挿入処理を行うという手もある。 51112 % 51113 % x 文字に ble-bind して使う人がいると入力や通信の速度で振る舞いが変わる事になり駄目。 51114 % 例えば特定の文字に (文字挿入+何かの操作) を割り当てるなどの事が考えられる。 51115 % magic-space の様に。 51116 % 51117 % これに対して対応するにはどうすれば良いか。 51118 % 毎回 keymap の binding を検査するのも大変である。 51119 % 51120 % x 更に何らかのキーシーケンスやキー列の後半で通常文字を使う事もある。 51121 % その通常文字と区別する事はできるのだろうか。 51122 % →これはキーシーケンスが途中状態でないかどうかだけ見ればOK? 51123 51124 実は __defchar__ を呼び出すところでキャッシュすれば良いだけなのかもしれない。 51125 51126 x 但し、それだと通常文字ばかり大量に入力した時に progress が更新されなくなる。 51127 特に overwrite mode に入っているとき等は結局1文字ずつ処理する事になるので、 51128 とても遅い事になってしまう。 51129 51130 →これは上限を 50 文字にするなどすれば良い。 51131 これで高速化が阻まれたとしても精々 2% 遅くなるだけなので問題ない。 51132 51133 - キャッシュされた文字があるかどうかを key を受け取った時に 51134 最初に調べなければならない。 51135 51136 x 次の入力がある時のみにキャッシュは行う。 51137 次の入力によってすぐにまた制御が戻ってくるはずだからである。 51138 しかし本当だろうか。入力バイトがあったからと言って、 51139 エンコーディングでマルチバイト文字が完成するとは限らないし、 51140 キーシーケンス復号でキーが完全になるとは限らない。 51141 51142 →と思ったが、よく考えてみたら既に has-input では、 51143 不完全な文字符号化やキーシーケンスの時には 51144 続きがすぐに来るという事を期待している。 51145 51146 x __defchar__ の処理中に keymap が変わったり、 51147 __batch_char__ の binding が変わったりする場合はどうなのか。 51148 また _ble_decode_key__hook が設定される場合も考えうる。 51149 51150 →その様な変な動作をする場合にはそもそも __batch_char__ 51151 を設定していないはずなので、大丈夫。 51152 一応説明書にその様に記述しておけば良い。 51153 51154 - ok: bracketed paste mode はどうか。 51155 bracketed-paste-mode の時には _ble_decode_key__hook 経由でキャッシュされる。 51156 何れにしても _ble_decode_key__hook よりも後でキャッシュは実行するはずなので、 51157 bracketed paste mode に影響はないだろう。 51158 bracketed paste mode の間は _ble_decode_key__hook より後ろに来ることは無いので、 51159 bracketed paste mode に対して変な影響を与える事もない。 51160 また bracketed paste mode に突入するのは paste_begin を受信した時で、 51161 その時にはちゃんと後ろまで行ってキャッシュされた文字たちが実行されるので大丈夫。 51162 51163 - 何処でキャッシュを実行するべきだろうか。 51164 最初はキーを受け取った直後でチェックを行って入力がなければ実行という事にしようと思ったが、 51165 それだと1文字ずつしかキャッシュされずに毎回実行される事になってしまう。 51166 しかし、だからと言って通常文字の場合にはキャッシュに追記する、 51167 という振る舞いにしてしまうと通常文字に対して bind がある場合に駄目。 51168 やはりキャッシュへの追記は __defchar__ で実行するべき気がする。 51169 51170 或いは、キャッシュの実行は実際にコマンドが実行される直前、という事にする。 51171 それだと不完全なキーシーケンスで終わった時に、キャッシュが実行されない。 51172 という事を考えたが、ble-decode-key の一番最後で has-input を確認して、 51173 もし次の入力がなかったら実行するという事で良い気がする。 51174 51175 これは少々実験的な実装になると思うので、 51176 bind レベルのキャッシュとは別で取り扱う事にして、一旦 commit する事にする。 51177 51178 - vi_imap においては self-insert を記録している。 51179 これをどの様に取り扱うべきかはまた考える必要がある。 51180 例えば __batch_char__ についても記録して良いが、 51181 125 を返した場合にはどうするのか、など。 51182 51183 と思ったが 125 を返さずに、内部でループで回して処理すれば良い気がしてきた。 51184 外で progress を表示するなどの事はできなくなるが、 51185 今は progress を batch に対して表示する事は諦めたので、 51186 そもそも 125 を返すことができる必要はない。 51187 51188 実装した。動いている様な気がする。 51189 1000文字 8.5s ぐらいだったのが 3.5s ぐらいにまで高速化した。 51190 chatoyancy で試したら元から 1000 文字 1.5s ぐらいで、 51191 1s ぐらいにしか変化しなかった。chatoyancy は滅茶苦茶速い。 51192 51193 * 2018-09-25 decode: 実は ble-decode/.hook で is-stdin-ready をチェックして [#D0848] 51194 バイト列を中でキャッシュする様にすれば高速化できるのではないだろうか。 51195 特に PROLOGUE と EPILOGUE の呼び出しを省略する事ができる。 51196 また、大量のバイト列を受け取った状態でプログレスバーを表示する事も可能である。 51197 51198 この時 ble-decode/has-input はまた修正が必要になる事に注意する。 51199 特にキャッシュしたバイトを処理している途中状態でどう対応するか。 51200 一番最後のバイトを処理している時はもう入力がないと判定する必要がある。 51201 51202 更に言うと今までの has-input も不完全だったのではないか。 51203 ble-decode/.hook で二つ以上の引数を受け取った時、 51204 一番最後以外のバイトを処理している時には、 51205 ちゃんと has-input が成功する様になっていただろうか。 51206 今確認した所そうはなっていない。 51207 51208 2018-09-29 本当に実際に高速化するのかどうかは未知数である。 51209 試しにキャッシュしてみて実測してみることにする。 51210 時計を見ながら手動で計測した所、キャッシュしないと 10 秒程度だったのが、 51211 キャッシュすると 8 秒程度になった。微妙に速くはなったが、 51212 やはり実際に入ってきた文字を処理している時間の方が長いのであった。 51213 51214 ところで PROLOGUE と EPILOGUE を各文字毎に呼び出さないと起こる不都合などはあっただろうか。 51215 改めてそれぞれ何をしているかを確認する事にする。問題なさそうである。 51216 51217 処理が続行している間は進行状況を表示する事にする。 51218 - 但し、default の時にのみ。これの判定は [[ $_ble_edit_info_scene == default ]] で良い? 51219 他には show という状態しか無いようなので多分良いのだろう。 51220 - どの頻度で進行状況を表示するのが良いだろう。 51221 一秒に 2 回程度であろうか。だとすると 1000 件処理するのに約 10 秒として、 51222 100件処理するのに 1 秒で、50件毎に表示すれば良い気がする。 51223 (但し、これは遅いホストでの話しなので実際にはもう少し頻度が高くなるだろうがそんな物であろう。 51224 進行状況の表示によるオーバーヘッドであるがそんなには高くないと信じたい) 51225 - 実は vim-mode だから遅いというのはあるのかもしれない。 51226 と思って測ってみたが殆ど変わらなかった。 51227 51228 bracketed paste を自動的に設定しようかとも思ったが、 51229 それだと本当に vim の操作としてアルファベットを入力しているのと区別がつかない。 51230 そのような事をする人がいるとは思い難いが、しかし勝手に振る舞いが変わるのは良くない。 51231 51232 2018-09-27 51233 51234 * isearch: 空文字列で検索した時 stack による巻き戻しが無効になっている。何故? [#D0847] 51235 51236 | % どうもこれは "空文字列の時に" 起こるのではなくて、 51237 | % C-r で当たった履歴項目の一つ前の項目に一致する時に起こることである。 51238 | % つまり、C-r で当たった時に "次の検索位置" が現在の履歴項目の一つ前に設定されている為に、 51239 | % そのまた次の検索で向きを変更した時に、 51240 | % 現在の履歴項目の一つ後から検索を始めなければならないのに 51241 | % 現在の履歴項目の一つ前から検索を始めてしまっているのが問題なのである。 51242 | % 改めて現在の実装がどの様な記録の仕方をしているのかについて確認する事にする。 51243 | 51244 | →否、全然違った。原因はそうではなかった。やはり空文字列の時に起こることである。 51245 | 有限の文字列の時には検索の向きを変更すると、カーソルの位置の都合から、 51246 | 一回同じ単語に一致するけれどもカーソルの位置だけ変化するという事が起こる。 51247 | 51248 | これをどの様に正しく実装したら良いだろうか。 51249 | 現在の実装ではとにかく移動する時には必ず記録する様にしている。 51250 | これは DEL を押した数と戻った回数の整合性という観点から望ましい。 51251 | そして、記録する時には追加するか或いは消去するという処理になっている。 51252 | 既に同じ一致がトップにあれば消去し、それ以外は追加する。 51253 | 然し、本来は「同じ一致がトップにあれば」というよりは、 51254 | 次にどちらの方向へ進むかを考慮に入れて実行したい。 51255 | 51256 | 或いは、空文字列の時でも一回は同じ位置で一致する 51257 | という様にした方が一貫性がある様にも思う。 51258 | うーん、前回の検索方向というのを覚えておいて、 51259 | 検索方向が前回と同じであればそのまま検索して、 51260 | 検索方向が前回と異なれば一回は転回処理を実行する、 51261 | というようにしたい。 51262 | 51263 | その様に実装した。 51264 | 51265 | x 動かしてみたら全く動かない。 51266 | 改めて考察してみるとこの修正では全然駄目である。 51267 | しかし段々と何がどうなっているのか分からなくなってきた。整理する。 51268 | 51269 | 先ず、_ble_edit_isearch_arr の記録の仕方。 51270 | これは新しい一致が見つかった時に、 51271 | 今までの一致の位置・検索文字列と、現在の検索方向を格納する。 51272 | 検索方向だけ新しい物を格納しているのが良いのかは分からないが 51273 | 取り敢えず其処は今回の問題ではない。 51274 | 51275 | ABCD と一致した時、ABC は _ble_edit_isearch_arr の中にあり、 51276 | D はグローバル変数 _ble_edit_isearch_* に記録されている。 51277 | 検索方向の転回をここで実行すると D に対する転回となる。 51278 | 51279 | % % さて、この状態で再びその方向に検索を実行するとどうなるか。 51280 | % % 新しく C に一致するだろう。そうすると配列の末尾にある C と対消滅する。 51281 | % % これは現在の実装でちゃんと動く。 51282 | % % 51283 | % % しかしそうすると逆に今までの実装で何故ちゃんと動いていたのかが不思議である。 51284 | % % 今までの実装で何が起こっていたかを考える ABC|D の状態で転回を実行する。 51285 | % % そうすると再び D に一致する。この場合 ABCD|D という事になる。 51286 | % % この後で再度検索すると C に一致する。この時元々の状態の D が 51287 | % % 配列に push されて対消滅して ABC|C という状態になる。 51288 | % 51289 | % という事はやはり現在の実装で動くというのは勘違いだ。 51290 | % ABC|D の状態で転回を実行すると ABC|D のままである。 51291 | % この状態で元に戻ろうとすると C が一致する。 51292 | % この時に現在の状態の D が push されて、ABCD|C という状態になる。 51293 | % これだと永久に対消滅は起こらない。 51294 | % 51295 | % a 一つの方法は上から配列の二番目の状態を調べるという物である。 51296 | % でもそうすると A|B という状態で転回して元に戻ろうとすると、 51297 | % AB|A という状態になって…この場合はちゃんとうまく行く。 51298 | 51299 | やはり何か違う。ABCD と入力する。この時点で ABC|D となっている。 51300 | 転回した時再び D になる。その時 _ble_edit_isearch_arr は弄らないので ABC|D のまま。 51301 | この次に検索を実行すると C に一致する ABC|D の状態で C を push しようとするので、 51302 | C は対消滅する。この時 D は記録されない。結果として AB|C という状態になる。 51303 | (別に「対消滅」する訳ではなくて pop されるというのが正しい表現である)。 51304 | 51305 | 今までに動いていたのは何故だろうか。 51306 | ABCD と入力すると ABC|D になる。ここで転回すると D が push されようとする。 51307 | % C != D なので ABCD|D という状態になる。次に検索を実行すると C に一致する。 51308 | と思ってよく見たら index と beg:end:needle が同じならば dir に依らずに 51309 | push が省略される様だ。つまり、ABC|D という状態になる。従って、次に C が来ると、 51310 | ちゃんと消滅が起こって AB|C という状態になる。 51311 | 51312 | そうすると今度は何故今まで空文字列で動かなかったのか、という事になる。 51313 | ABC|D と入力する。転回すると C に一致する。そうすると AB|C という状態になるはずである。 51314 | これは確認しておく必要がある。どうも C に一致していない様だ。 51315 | →分かった。$beg:$end が一致していない。何故か -1:-1 になっている。 51316 | もしくは -1:-1 になる方が正しくて 3:3 や 4:4 になっているのが間違っているのだろうか。 51317 | 呼び出し元を観察すると beg==end の時には両方 -1 にする様に明示的に書いている。 51318 | では何故 3:3 や 4:4 の様な物が可能なのであろうか。 51319 | と思ったら push する時には obeg==oend のチェックをしていないのだった。 51320 | →あっさり直ってしまった。と思ったが、実際にそうしてみると、 51321 | 今度はキャンセル時に状態を復元する時に _ble_edit_ind, _ble_edit_mark が復元できずに失敗する。 51322 | 51323 | # 所で、この復元のコードは誤っている様な気がする。検索の方向によって 51324 | # beg と end と _ble_edit_ind と _ble_edit_mark の対応は切り替わらなければならない。 51325 | # これは別項目で後で修正する事にする。 51326 | 51327 | やはり -1:-1 を記録するのではなくて実際の位置を記録するべきなのだろうか。 51328 | 51329 | ? 逆に何故 beg==end の時に beg=end=-1 としたのかの方が謎である。 51330 | blame したら分かるだろうか。探すとこれは最初からそうだった様だ。 51331 | https://github.com/akinomyoga/ble.sh/commit/d10d5364e812d302f8c36d0b8a8729bb00761ec9 51332 | しかも 3 年前のコードで git 上にある中ではかなり最初の方の実装である。 51333 | この時の議論は残っているだろうか。2015-11-29 である。しかし memo.txt を見ると何も言及がない。 51334 | 昔はそのまま実装できると思ったものはそのまま実装していた様だ。 51335 | commit message を見ると一致範囲も記録するとしか書いていない。 51336 | % 特に考察した形跡もないので、試しに -1 に設定するのをやめて見る事にする。 51337 | % 恐らく範囲がない == 一致していないという事と当時は解釈したのだろう。 51338 | 51339 | →これは実際に beg=end=-1 にしないでやってみたところ、 51340 | 空文字列の場合には各履歴項目に一回しか一致しないという条件により、 51341 | backward search では履歴行の末端に一致して、 51342 | forward search では履歴行の先端に一致する。 51343 | これにより forward search にしても同じ状態にならないので復元できないという事の様だ。 51344 | 51345 | うーん。現在の振る舞いのままの方が良いのかもしれない…。 51346 | もし戻りたければ DEL を入力すれば良いだけなのである。 51347 51348 やはり従来の振る舞いで適切という結論である。 51349 空文字列で検索している時は一致の振る舞いが多少異なる。 51350 各行で一回ずつしか一致しない様に制限をしている。 51351 backward search の場合には編集文字列の末端に一致する。 51352 forward search の場合には編集文字列の先頭に一致する。 51353 通常の C-s と戻る C-s の振る舞いの一貫性を保つには、 51354 そして C-s が本質的にはカーソルの移動と考えるならば、 51355 行きと戻りは異なる経路として記録するべきである。 51356 51357 * done: 所で、修正する途中で気づいた事だが、 51358 51359 _ble_edit_bind_force_draw=1 51360 51361 という物があった。これは例えユーザー入力があったとしても、 51362 行の再描画を強制するという要求である。 51363 実は、これは dabbrev 及び nsearch でも設定する必要がある。 51364 51365 と思ったが、これは本当に効果があるのだろうか。 51366 これは実際に抜けた時に実行される物の筈である。 51367 という事は #resume を実行している間は実行されないのではないか。 51368 それよりはすぐに redraw を実行してしまった方が良いのではないか。 51369 51370 その様に書き換えた。また、そうなるとそもそもこの 51371 _ble_edit_bind_force_draw=1 は必要なのか疑問である。 51372 何処で使われているか確認して不要そうだったら削除する。 51373 51374 →今確認したところ誰も使っていない。削除する。 51375 51376 追記: 一応 #D0324 に導入の経緯の議論があった。後で確認しても良い。 51377 51378 * fixed: ble/widget/isearch/cancel: _ble_edit_ind と _ble_edit_mark の対応が違う 51379 これは別に記録しなければならないのではないか。 51380 というのも最初の _ble_edit_ind と _ble_edit_mark の状態は、 51381 検索前の状態なので検索の方向などから判定する事は不可能である。 51382 51383 先ず ble-edit/isearch/prev の実装を確認すると、 51384 ble-edit/isearch/prev は…うーん。一番最初の状態には戻らない。 51385 実際にやってみると必ずカーソルが後ろになってしまう。 51386 .set-region で設定を行う為である。 51387 51388 最初の状態だけは beg:end ではなくて ind:mark を 51389 記録する様にするという手もある。 51390 と思ったら既に _ble_edit_isearch_save という変数に記録してあった。 51391 _ble_edit_isearch_save は C-s で移動して確定した時に、 51392 ちゃんと領域を拡張できているようにする為に導入した物で、 51393 exit する時にそれに応じて調整する様にしていた。 51394 cancel も内部で exit を呼ぶようにしていたが、 51395 よく考えてみたら cancel の時は領域を拡張するのではなくて、 51396 本当に元の状態に戻すという事なので操作が異なる。 51397 51398 * done: ここで一つの可能性が出てくる。 51399 forward search の場合にも編集文字列の末端に 51400 一致する様に変更しても良いのではないか。 51401 例えば history-prev/next については上に移動しても下に移動しても 51402 カーソルの位置は文字列の末端に移動する。 51403 51404 確認して置かなければならないのは空文字列の時の 51405 行内一致はどうなっているのかという事。 51406 不思議だ。コードを確認してみたが、空文字列に対する対策は特に実行されていない気がする。 51407 51408 実は isearch/search は一箇所でしか呼び出されていない。 51409 .next-history.fib からは呼び出されていない様だ。 51410 改めて確認したところ .next-history.fib の中では直接パラメータ展開を使って切り出している。 51411 従って、最初の一致と二回目以降の一致は元から処理の仕方が異なるのであった。 51412 forward search で一致するのを末尾に変更する為には、 51413 .next-history.fib の中で [[ ! $needle ]] の時だけ特別扱いすれば良い。 51414 51415 実装の方法はともかくとして、何故行内で何度も一致しないのかの謎は解けていない。 51416 ここは少し出力してみる事にする。 51417 →なんと、isearch/search に対して空文字列で検索を実行すると何にも一致しない。 51418 何故かというと isearch/search は ${target#*"$needle"} と ${target%"$needle"*} 51419 を用いているので空文字列を使うと最小一致は幅0なので、何にも一致しなかった場合と区別が付かない。 51420 正規表現を用いている方は、逆側から最大一致を実行している筈なので微妙である。 51421 しかし正規表現の方はそもそもどのように一致の長さを事前に検知するのかは非自明である。 51422 51423 うーん。isearch/search の設計としては空文字列を指定した場合にも一致する様にしたい。 51424 但し、現在地に一致するのではなくて、次の位置に一致する様にする。 51425 修正した。 51426 51427 * reject: 因みに逆方向に検索を実行するときに常に配列の末尾を取り出して 51428 巻き戻しの検索になっていたら単にそれを復元するという実装にする事も可能である。 51429 しかし、その時には needle が一致している事などを確認する必要がある。 51430 逆に言えば needle が一致しているかどうかだけ見れば、 51431 そのまま取り出して再利用してよいかどうかが分かるのではないか。 51432 51433 もう考えるのも面倒なのでこれはやらなくても良い。現状の動作で十分動いている。 51434 51435 * fixed: 現状では検索方向の転回に必ず一操作を要しているが、 51436 C-s, C-r の本質がカーソル移動だと思うのであれば、 51437 やはり空文字列に対しては転回に対して一回使わない方が自然なのではないか。 51438 51439 ここで bash の振る舞いを調べる事にする。 51440 先ず bash は空文字列で検索を開始する事はできない。 51441 更に有限の文字列で検索を実行するとしても転回に1回は使わない。 51442 今までの動作は Emacs の振る舞いを真似た物だったが Emacs では空文字列での検索はできない。 51443 空文字列で検索しようとすると前回の検索が使用される。 51444 その様に考えると、やはり転回に対して使わない方が自然である。 51445 51446 以下の断片は転回に必ず (空文字列であっても) 1回要する時のコード断片で、 51447 元々 ble-edit/isearch/.next.fib にあったものであるが、 51448 削除する事にした。 51449 51450 | local old_dir=$_ble_edit_isearch_dir 51451 | 51452 | 中略 51453 | 51454 | # 向きを転回する時はカーソルの位置を移動するだけ 51455 | if [[ $_ble_edit_isearch_dir != "$old_dir" ]]; then 51456 | if [[ $_ble_edit_mark_active ]]; then 51457 | local tmp 51458 | ((tmp=_ble_edit_ind, 51459 | _ble_edit_ind=_ble_edit_mark, 51460 | _ble_edit_mark=tmp)) 51461 | ble/textarea#redraw 51462 | fi 51463 | ble-edit/isearch/.show-status.fib 51464 | return 51465 | fi 51466 51467 * complete: dabbrev も fiberchain で再実装する [#D0846] 51468 51469 % と思ったが、そんなに面倒ではないかもしれない。 51470 % と思ったが、やはり色々面倒な事になってしまった。 51471 51472 dabbrev でも無駄に start を記録していたがこれは実際使われていないので廃止する。 51473 代わりに最後に一致した位置 match を記録しようとしたが、 51474 実は常に最後の検索位置 index と一致している様な気がする。 51475 というのも履歴の一番最初に行ったらまた履歴の最後まで戻るためである。 51476 51477 * done: うーん。何だかよく分からなくなった。 51478 dabbrev-expand の時は見つからなければまた最初に戻る。 51479 つまり、cyclic に検索するという事になる。 51480 外側から指定しようと思ったが、 51481 よく考えると元の検索器の方にその機能を追加した方が自然である。 51482 cyclic というオプションで指定できる様にした。 51483 51484 % これで履歴内に検索対象が全くない場合に限り検索が失敗する様になる。 51485 % つまり、再一致を dabbrev 側で再試行する必要はなくなった。 51486 51487 * done: と思ったら微妙なことが判明した。dabbrev は単に一致したらではなくて、 51488 現在一致している内容と異なる内容だったら、という追加条件がある。 51489 これを拡張正規表現で表現するのは困難である。 51490 一応できなくはないが、現状の様に外側で複数回一致させる方が自然の様に思われる。 51491 さて、それに当たっては start を固定したままで 51492 backward-search-history を複数回呼び出せば良い。 51493 折り返して再度元の場所に戻ってきたら必ず backward-search-history が失敗するので、 51494 無限ループになるという事はない。 51495 51496 取り敢えずその様に実装し直した。微妙な間違いなども見つけた。 51497 動作確認はしていないが後でまた確認すれば良いだろう。 51498 51499 取り敢えず細かい調整をして実装した。 51500 試しに動かしてみる事にする。 51501 51502 * done: dabbrev で何故か cyclic にならずに終了してしまう。 51503 51504 単に一個しか一致する物がないので、exclusive に検索している為に一致しないのか? 51505 という事を思ったが、二個一致する物に対しても cyclic にならずに終了してしまう。 51506 cyclic の条件判定のところを観察してみる事にする。 51507 →単に $1 を $opts に格納していなかっただけだった。 51508 これを直したら2個一致する時にはちゃんと cyclic になる様になった。 51509 51510 | * しかし、自分以外に1個しか一致がない時にはやはり抜けてしまう。 51511 | 51512 | 変である。よく考えてみたら自分自身にも一致して良いのではないか? 51513 | と思ったが、自分は履歴に登録されていないという事を考えれば一致しないのは当然である。 51514 | 因みに、現在の実装だともし現在地が過去の履歴であれば自分自身に一致する事になる。 51515 | その辺りの一貫性をどのように確保するのかも課題の一つである。 51516 | 51517 | 仕様: 自分自身には一致しない 51518 | 仕様: 自分以外に1つしか一致がない場合は、巡回して戻ってきたらそれに一致する 51519 | 51520 | →現在地が過去の履歴にある時には _ble_edit_history_edit には 51521 | 最新の未実行のコマンドが登録されるので、${#_ble_edit_history_edit[@]}-1 番目の要素 51522 | (これは ble-edit/history/get-count (-1 しない) 番目の要素に同じ) 51523 | も検索する様にすれば問題ない。実際にその様になっている。 51524 | 51525 | →また自分自身に一致しない様にするために predicate 内部で 51526 | index もチェックする事にした。 51527 | 51528 | * 自分自身に一致する様に start を 1 ずらして定義してみる事にした。 51529 | するとずっとループして検索が停止しなくなってしまった。 51530 | "現在の内容と厳密一致する時にはスキップする" という機能の所為である。 51531 | これは次の項目の "遅い問題" と一緒に解決できる。 51532 | つまり関数を使って一致判定を実行するということである。 51533 | 51534 | * hello の様な頻出の単語で検索すると速度が著しく低下する。 51535 | 厳密に一致する単語に何度も引っかかってしまって、 51536 | その度に blockwise で 1000 件走るからである。 51537 | 本来は一回スキャンすれば良いはずなのにである。 51538 | これは関数を外から指定して判定する事ができるようにするべきなのではないか。 51539 | 51540 | →関数にしてみたが微妙に遅くなった。eval してくれる cond 的な物の方が良いのでは。 51541 | 51542 | * 一番初めのpos 初期化: 末端? 51543 51544 取り敢えず関数を渡して検索するのを実装したので 51545 一つ一つについて動作を確認する事にする。 51546 その前に様々の問題が発生したのでそれを修正して行く。 51547 51548 | x fixed: 先ず全く一致しなくなってしまった。これは直した。 51549 | backward-search-history 側で predicate オプションを認識していなかった。 51550 | 51551 | x fixed: 一度一致しても blockwise search の途中で dabbrev_pos=0 に再設定されてしまうという問題がある。 51552 | 51553 | % →これについては直した。外側で dabbrev_pos=0 に設定して、 51554 | % 中では一致した場合を除いては勝手に弄らない様にする… 51555 | % と思ったが駄目だ。そうすると一度 dabbrev_pos を設定すると、 51556 | % それ以降の検索に影響を与えてしまう。 51557 | 51558 | →search-in-history-entry では dabbrev_pos は設定しない事にして、 51559 | dabbrev_match_pos に返すだけに留める事にした。 51560 | 外部で dabbrev_match_pos を dabbrev_pos に適用すれば良い。 51561 | 51562 | x fixed: 同じものに何度も一致している 51563 | 51564 | % →これは blockwise search だからである。 51565 | % 一番最後に一致した物についての結果しか得られない… 51566 | % と思ったが、よく考えたら blockwise search の場合は 51567 | % 一番最後に一致した物を採用するのだから問題ない気がする。 51568 | 51569 | これは別の物に一致していたが、毎回 dabbrev_match を代入してから判定していたため、 51570 | 一致していない物の dabbrev_match で上書きされてしまっていたという事だった。 51571 | 一致した時にのみ dabbrev_match に書き込むように変更する事で解決した。 51572 | 51573 | x fixed: 何故かタスクがどんどん増えていく 51574 | 検索の最中に更に次の検索を要求すると発生する様だ。 51575 | どんどんタスクが増えていく時は同じ履歴項目の間を振動している。 51576 | 51577 | →これは fib_suspend をクリアし忘れていたのが原因だった。 51578 | その為に折角一致しても fib_suspend したと判定されてすぐに停止するのだった。 51579 | 更に、検索を再開しても何度も同じ検索を実行していた事になる。 51580 | 51581 | x fixed: 同様の問題が isearch, nsearch でもないか確認する必要がある。 51582 | →確認してみた所両方共大丈夫だったが、それぞれ別の書き方をしている。 51583 | 分かりにくいので fib_suspend を確認して読み取ったらすぐに空文字列を設定する様に変更した。 51584 | 51585 | と思って nsearch で実験してみたら駄目だった。 51586 | fib_suspend を確認する前に関数を抜けている箇所がある? 51587 | →何処で抜けているか分かった。 51588 | 新しいコードの方が正しくて、今までのコードの方が間違っていた。 51589 | 今までのコードの方で再現して、新しいコードの方では再現しないという事が分かった。 51590 | 51591 | isearch の方では問題は起こらない様である。 51592 | 51593 | x fixed: 実は nsearch で C-s で戻り切るとその後の検索が変である。 51594 | これは C-x C-p して C-s するだけで再現する。 51595 | fiberchain の側の問題ではないようだ。 51596 | 51597 | 試してみると途中で index=-1 になってしまっている様だ。 51598 | backward-search から戻った時の index の値が怪しい。 51599 | うーん。これは forward-search で失敗した時に index 51600 | が一番最後にいると思っているのがいけない。 51601 | 実際には空文字列が設定されるのである。 51602 | 51603 | ちゃんと backward-search の戻り値に応じて 51604 | _ble_edit_nsearch_index を更新する様に修正した。直った。 51605 51606 取り敢えず見つかった問題は解決したので 51607 改めて元々の問題が解決されているかについて確認していく。 51608 51609 * fixed: 自分以外に1個しか一致がない場合に抜けてしまう問題について。 51610 これは単に既に一致している場合には bell を鳴らすだけで 51611 動かさないという様にすれば良い。 51612 51613 * ok: 自分自身を飛ばす 51614 これは今まで試したところだとちゃんと動作している様に思われる。 51615 と思ったが、よく考えたら今までは最新の履歴項目で編集していたので分からないだけかもしれない。 51616 →古い履歴項目を書き換えて ring とやって ringo, 周回, ringing の順に一致して 51617 ちゃんと自分を飛ばしてまた ringo に一致するという事を確認した。 51618 51619 * ok: 無限検索ループになることについて 51620 これは構造上今回の実装では起こりえないし、今までにも起こっていない。 51621 つまり backward-search-history-blockwise の cycle 判定がちゃんと動いているということ。 51622 51623 * ok: 一番初めのpos 初期化: 末端? 51624 →これについては今までのところ問題は発生していない。 51625 51626 * ok: 検索速度が遅いことについて 51627 51628 頻出単語に対する検索の遅さは著しく改善したが、 51629 各行に対して関数を呼び出す為に全体に遅くなってしまった。 51630 試しに eval を用いる方法についても実装してみる事にする。 51631 51632 うーん。何故か常に一致する感じになってしまっている。何故だろう。 51633 条件式を間違えていた。修正した。 51634 51635 然し、predicate よりも余計に遅くなった。 51636 変数代入に続けて eval を書くのはもしかして遅いのかもしれない。 51637 時間を計測してみることにする。 51638 51639 | a for ((j=i-block;++j<=i;)); do 51640 | LINE=${_ble_edit_history_edit[j]} INDEX=$j eval "$needle" && index=$j 51641 | done 51642 | 51643 | これは 1000 件で 0.156 秒程度である。 51644 | b local LINE INDEX 51645 | for ((j=i-block;++j<=i;)); do 51646 | LINE=${_ble_edit_history_edit[j]} INDEX=$j eval "$needle" && index=$j 51647 | done 51648 | これは 0.154 秒程度である。 51649 | 51650 | c eval "function ble-edit/isearch/.search-block.proc { 51651 | local LINE INDEX 51652 | for ((j=i-block;++j<=i;)); do 51653 | LINE=\${_ble_edit_history_edit[j]} INDEX=\$j 51654 | { $needle; } && index=\$j 51655 | done; }" 51656 | ble-edit/isearch/.search-block.proc 51657 | これは 0.086 秒程度である。多少速くなった。 51658 | しかし、今までと較べるとやはり遅い様な気がする。 51659 51660 うーん。取り敢えず c を選ぶという事にしても遅い。 51661 と思っていたら、どうも ring は string に引っかかるので、 51662 頻繁に関数呼び出しの方を実行しているという事の様に思われる。 51663 と思ったが本当だろうか。直前に区切り文字がない限りは反応しない筈だ。 51664 その様に思うとやはり不思議だ。単に正規表現が重いという事なのだろうか。 51665 51666 | needle に以下の様に 1 行目を追加したところ 0.045s にまで短くなった。 51667 | 因みに1つ目の条件コマンドと2つ目の条件コマンドを結合すると 0.046s である。 51668 | 殆ど違いはない。つまり、ちゃんと遅延評価にはなっている様である。 51669 | 51670 | [[ $LINE == *"$_ble_complete_dabbrev_original"* ]] && 51671 | [[ $LINE =~ $_ble_complete_dabbrev_regex1 ]] && 51672 | ble-complete/dabbrev/search-in-history-entry "$LINE" "$INDEX" 51673 | 51674 | 実は glob で全部実装した方がもっと速いのかもしれない。 51675 | 一時的に wordbreaks を復活させる事にする。 51676 | もしくは glob escape すれば良いのかもしれないが…。 51677 | 以下の様に glob だけで実装してみたところ一定しなくなった。 51678 | それでも 0.140 程度なので却って遅くなった。 51679 | 51680 | [[ $LINE == "$_ble_complete_dabbrev_original"* || 51681 | $LINE == *["$_ble_complete_dabbrev_wordbreaks"]"$_ble_complete_dabbrev_original"* ]] && 51682 | ble-complete/dabbrev/search-in-history-entry "$LINE" "$INDEX" 51683 | 51684 | 変数名が長いのが気になると思って local dabbrev_{original,wordbreaks} 51685 | に入れてみたが速度としては変わらない様だ。 51686 51687 結局、local dabbrev_original による枝刈りと 51688 local dabbrev_regex1 による判定で実装する事にした。0.044s 51689 まあ許せる速さではある。 51690 51691 * done: cycle した時には bell を鳴らしたい 51692 51693 * done: うーん。気づいたが show-status の中で ntask を参照している。 51694 然し、show-status を #resume の外で呼び出している様な気がする。 51695 これは isearch/nsearch を改めて調べて修正する必要がある。 51696 51697 調べてみたところ nsearch は問題なかった。 51698 isearch ではそもそも #resume の中から呼び出され時にしか ntask を確認していない。 51699 #resume の外で .draw-line を呼び出した時にも fib_ntask を使って描画する事にした。 51700 それに伴って呼び出し元をたどって修正した。 51701 関数名の整理も行った。 51702 51703 2018-09-26 51704 51705 * 2015-12-23 isearch: C-r C-s で mark が破壊されてしまう [#D0845] 51706 (現状の実装だと、範囲選択に C-r C-s を使う事ができない。) 51707 51708 例えば mark が設定されている場合は現在の履歴項目の中で、 51709 mark を解除せずに検索を行うなどの様にすると良い。 51710 51711 履歴項目を移動した場合には解除するというので良い。 51712 (また戻ってきた場合には復元する。) 51713 51714 % 問題になるのは着色である。layer を追加するか、 51715 % 選択範囲の表示に使っている layer を拡張するかする必要がある。 51716 →抜けた時に復元すれば良いという事にした。 51717 選択範囲と一致範囲の両方を表示するのも見にくいし、 51718 また選択範囲だけしか表示しないというのも分かりにくい。 51719 なので、検索中は一致範囲だけ表示するというので問題ない気がする。 51720 51721 実装した。動くことを確認した。OK 51722 51723 * edit: ble/widget/accept-single-line-or/accepts は別の名前を割り当てる [#D0844] 51724 現在の名前だと ble-bind -L に表示されてしまう。直した。 51725 51726 * edit: history-search [#D0843] 51727 51728 dabbrev-expand でもそうだが、履歴の検索は遅い。 51729 連打したりすると応答がなくなる可能性がある。 51730 かと言って単に has-input で停止していると入力が消滅した様に見える。 51731 特定の回数連打した時に期待した位置に行かないなどの事が起こる。 51732 そうすると isearch の様に fiber を組み合わせて実装する事になる。 51733 51734 思うに fiber を沢山重ねて実行する統一的な枠組みを作っても良いのではないか。 51735 51736 * fixed: progress は _ble_edit_isearch_* に依存している。 51737 更に検索が完了したら毎回 clear する必要がある。 51738 51739 これはどの様に実装するのが正しいだろうか。 51740 現状の実装では forward/backward-search-history が 51741 ble-edit/isearch/.draw-line-with-progress "$i" を呼び出す形になっている。 51742 51743 % 取り敢えずこの関数の内容を確認してみた所、 51744 % 特に isearch 特有の表示はしていない。 51745 % なので、この関数自体を任意の場合に使える様に拡張するのが良い。 51746 % 51747 % _ble_edit_isearch_str は needle で置き換えられる筈である。 51748 % .draw-line-with-progress の呼び出し元を確認する。 51749 % - backward-search-history-blockwise 及び forward-search-history は大丈夫。 51750 % - .draw-line は様々な場所から呼び出されている。 51751 % これは needle が定義されていない文脈からも呼び出される。 51752 % .draw-line の中で needle を定義する事にすれば良い。 51753 51754 と思ったが、やはり微妙に思われてきた。 51755 現在位置も表示しているが、nsearch の場合には現在位置は移動しない。 51756 やはり外部から表示内容を設定する事ができるようにするのが良さそうである。 51757 →外部から isearch_progress_callback を指定する事にした。 51758 今まで無意味に isearch_ntask に依存していたのを置き換える形である。 51759 51760 * done: 実は記録されている現在位置と次に検索開始する位置は異なる。 51761 51762 | 現在は _ble_edit_nsearch_start を最初に検索を開始した位置 (nsearch に入った時の位置) として、 51763 | また _ble_edit_nsreach_index を次に検索を開始する位置兼最後に一致した位置としている。 51764 | しかし、一番最後に一致に失敗した時は index の位置はどうしたら良いか分からない。 51765 | 一回一致に失敗したのだから次に検索を開始する位置は履歴の一番端であるべきだが、 51766 | 一方で最後に一致した位置は動いて欲しくない。 51767 | 51768 | isearch の場合には index は記録していなくて、全て history/get-index に依っていた。 51769 | つまり、最後に一致した位置となっている。 51770 | その為、一致しなかった時にはキーを連打した回数だけ、 51771 | 最後に一致した位置から履歴の橋までを繰り返し検索する事になる。 51772 | isearch の場合にはキーを入力する度に検索の条件が変わるため、 51773 | 繰り返し検索を実行する事に意味があった。 51774 | 51775 | しかし、nsearch の場合には前に行くか後ろに行くかの二種類しかないので、 51776 | 毎回検索の条件は同じである。従って繰り返し検索を実行するというのは不自然である。 51777 | やはり最後に一致した位置と次に検索するべき位置というのは別に管理するのが良いのではないか。 51778 | 51779 | また、現在の実装では start はどの様に使われているだろうか。 51780 | 新しい nsearch の実装では start は nsearch に入った時の位置としている。 51781 | しかし、どうも isearch の場合には start は現在処理しているキー入力に対する検索の開始位置の様である。 51782 | そういう意味で言えば、実は start を最後に一致していた位置として、 51783 | index を次に検索するべき位置と考えるのが良いのかもしれない。 51784 | 或いは、そもそも start を記録する意味はないのかもしれない。 51785 | 現に isearch の実装では start は記録していない。 51786 | suspend の時に suspend データに記録しているだけである。 51787 51788 以下の様に実装する事にする。 51789 - _ble_edit_nsearch_start は廃止する。 51790 start は各入力に対して最初にどの位置に居たかを記録する事にする。 51791 各入力に対して使用するだけなので、これは fib_suspend に記録する。 51792 - _ble_edit_nsearch_index は最後に検索した位置を格納する事にする。 51793 - _ble_edit_nsearch_match に最後に一致した位置 51794 (現在表示している行内容がどの位置に対応しているか) を入れる事にする。 51795 51796 変更した。動いている。 51797 51798 * fixed: nsearch を抜けた後に検索状況の表示が残ってしまう。 51799 isearch は ble-edit/isearch/.erase-line を呼び出していた。 51800 これは中で ble-edit/info/default を呼び出している。 51801 同様に nsearch でも ble-edit/nsearch/erase-status という関数を作る事にする。 51802 51803 * fixed: C-r して C-s して最初の状態にまで戻った時、 51804 囲まれていない。これは最初に nsearch を開始した時に 51805 _ble_edit_mark を調整していない為である。 51806 _ble_edit_mark を保持する理由もないので _ble_edit_mark を変更する事にする。 51807 51808 と思ったが、よく考えたら non-incremental-history-search で 51809 ユーザに入力してもらった時には現在の行で一致があるとは限らない。 51810 C-s で戻る事ができるのは実際の一致に対応する ${_ble_edit_nsearch_stack[1]} 51811 以降というように制限するのが良さそうである。直した。 51812 51813 * fixed: 実は C-r を連打すると fib_suspend した内容が消滅している? 51814 確認してみた所、別に C-r によって fiberchain の最後の項目が 51815 キャンセルされているという事ではないようだ。 51816 51817 もしくは正しく検索状態を復元できていない? 51818 確認してみた所、何と、index= になっている。 51819 つまり、fib_suspend で start も記録する様に変更したのとは別に、 51820 元からちゃんと resume できていなかったという事になる。 51821 然し、何故 index= になっているのだろう…。 51822 →恐らく isearch/{for,back}ward-history-search の仕様であろう。 51823 と思ったが、改めて説明を呼んでも 148 を返した時にはちゃんと index を返す筈である。 51824 isearch/{for,back}ward-history-search の側のバグであろうか。 51825 51826 試してみたら実は今までの isearch の振る舞いも変だった様だ。 51827 直した方で試すと C-r を連打した回数だけちゃんと記録されている様だ。 51828 C-g で溜まっていたものを全てキャンセルする様になっている。 51829 51830 * done: 未処理の入力がある時、cancel でそれらをクリアする。 51831 51832 * done: defface で region_search を追加 51833 51834 * changed: `ble/widget/isearch/accept-line` 51835 51836 今までは何故か exit-default を実行していたが、 51837 これだと accept-line に束縛しているキーによって振る舞いが変わってしまう。 51838 % 明示的に accept-single-line-or-newline を呼び出す事にした。 51839 % もしくは isearch/accept-{line,single-line-or-newline} を作るべきかもしれない。 51840 % autoload し忘れていたのを追加した。 51841 調べてみると vi_imap などでは特殊な関数を呼び出す必要がある。 51842 やはり `RET` を実行する様に変更する事にした。 51843 51844 取り敢えずこの時点で commit を作成する事にする。 51845 51846 * done: key binding として up down を使った物も用意する。 51847 51848 * done: 後で mark の種類の名称を変更する事にする。 51849 mark:search -> mark:vi_search mark:nsearch -> mark:search 51850 これに併せて char block line についても変更したい。 51851 51852 mark_active を辿れば良いと思う。 51853 - mark_type についても確認する必要がある。 51854 一応一通り見た。 51855 - _ble_keymap_vi_search_activate も辿る。 51856 これも一通り見た。 51857 - _ble_keymap_vi_xmap_prev_visual も調べる。 51858 これは単に mark_active を記録・復元しているだけの様だ。 51859 51860 見逃しがないか不安である。改めて mark_active を見る。追加で以下も変更する。 51861 51862 - _ble_keymap_vi_xmap_prev_edit 51863 - ble/widget/vi-command/visual-mode.impl 51864 - ble/widget/vi_xmap/switch-visual-mode.impl 51865 - ble/keymap:vi/xmap/switch-type も確認した。 51866 51867 - ble/keymap:vi/call-operator 及び operator の context は変更しなくて良い。 51868 51869 まあ、取り敢えず試しにやってみて動けばよいだろう。 51870 表示は OK C-v による操作も確認した。まあ、問題なかろう。 51871 51872 * done: isearch も fiberchain で実装し直す 51873 直した。fiberchain で fiber に引数を指定できる様に拡張した。 51874 一応動いている。 51875 51876 また isearch で region を復元するのもこれを機に実装するのが良い。 51877 →これは #D0845 で実装した。 51878 51879 * done: non-incremental-* も実装する。 51880 これには emacs 側でも vi_cmap 的な枠組みが必要になる。 51881 read を直接使おうかとも思ったが、実は今の read の仕組みだと C-c に反応してしまう。 51882 同じプロセス内で実行できないだろうか。或いは、今の read の仕組みで実は問題ないだろうか。 51883 うーん。よく考えてみると問題ないのではないだろうか。 51884 今の read の仕組みでも C-c を受け付けて自分で処理している気がする。 51885 51886 面倒になった。何も考えずに read で良い様な気がしてきた。 51887 わざわざ vi_cmap を使わなくても良いという気分である。 51888 51889 2018-09-24 51890 51891 * complete: よく考えたら ble-sabbrev はエクスポートするべきなのでは [#D0842] 51892 https://github.com/akinomyoga/ble.sh/issues/5 で cmplstofB さんの質問で、 51893 ble-sabbrev は _ble_complete_load_hook で設定するのかという問いに対して。 51894 修正した。然し、何れにしても遅延ロードを有効にする為にはやはり load hook の中で実行する方が望ましい。 51895 51896 後で core-syntax.sh `ble-syntax:bash/is-complete` も autoload されていない事に気づいた。 51897 これも autoload する様に変更しておく。 51898 51899 * complete: "echo dist/ble1423@" に対して曖昧補完が効かない [#D0841] 51900 "cd dist; echo ble1423@" は効く。 51901 51902 調べてみると generate の所ではちゃんと曖昧補完に入っている様である。 51903 但し、source:argument に入っている。source:argument が悪い気がして来た。 51904 動作を見てみると source:argument は "d" で始まる候補を列挙して成功している。 51905 つまり、d*/b* による候補が列挙されていない。 51906 曖昧補完の時にはこれで諦めてはならないはずなのである。 51907 しかし、だからと言って曖昧補完の時には常に source:file を実行するというのも変である。 51908 本来はフィルタした後に候補が全てなくなったら、source:file による曖昧補完を試みる、 51909 という形でなければならない。 51910 51911 中でフィルタをかける事にした。 51912 フィルタをかけた上で候補の数が増えていなかったら 51913 source:file または source:dir を使う。 51914 51915 * [自然解消] 2015-06-28 color: PATH=filename の filename の部分 (ref #D0839) [#D0840] 51916 51917 * highlight: wtype==CTX_VALI (a=(1@)) 及び wtype==ATTR_VAR (v=1@) の着色? [#D0839] 51918 51919 core-syntax.sh: ble-highlight-layer:syntax/word/.update-attributes/.proc では 51920 wtype が CTX_CMDI, CTX_ARGI, CTX_RDRF, CTX_RDRS の時にのみ単語着色している。 51921 CTX_VALI または ATTR_VAR の時は変数名や []= の部分を除いて着色する必要がある。 51922 その為には先ず範囲を切り出さなければならない。 51923 51924 []= の形式の時に = の位置を特定するコードは、completion-context にあったはず。 51925 整理して ble-syntax:bash/find-{end-of-array-index,rhs} という関数にした。 51926 更にそれを利用して右辺の位置を特定して着色する様にした。 51927 単語の描画属性 (wattr) についても今までの単純な物から、 51928 単語内で色分けできる様に m(len:attr)+ の形式に対応した。 51929 51930 * highlight (reported by cmplstofB): 単語着色で配列の指示初期化子が failglob 判定されている [#D0838] 51931 https://github.com/akinomyoga/ble.sh/issues/13 51932 ble-highlight-layer:syntax/word/.update-attributes/.proc を直した。 51933 対応していない wtype については無視する事にした。 51934 51935 2018-09-23 自然解消 51936 51937 * [自然解消] 2016-06-22 timer の実現方法について [#D0837] 51938 51939 一つの方法は read -t 0.1 < 何処か などという風にすることである。 51940 しかしこの方法は一定時間の sleep を行うだけで定期的な処理を実行する timer にはならない。 51941 処理自体に時間が掛かっていると遅延が生じてしまう。 51942 51943 もう一つの方法は別のプロセスを起動してそのプロセスでひたすら時を刻みながら 51944 自プロセスに対して通知を行うという方法である。 51945 通知を行う方法は色々考えられる。シグナル、mkfifo、mkdir など。 51946 51947 a シグナルには余り頼りたくない。思いがけずクラッシュしそうな気がするからである。 51948 シグナルハンドラの起動中にシグナルハンドラが呼び出されるとクラッシュするので、 51949 シグナルハンドラの内部ではカウンタをインクリメントをするだけにする。 51950 しかしその様にしたとしても何らかの遅延により 51951 シグナルハンドラが二重に呼び出される可能性は排除できない。 51952 また、別の問題点としてタイマーの開始・終了を制御する方法がないという事がある。 51953 →まあ、単純に生成したサブシェルを kill すれば良いだけとも言える。 51954 51955 $ trap -- '((ble_timer_count++))' USR2 51956 $ (while xsleep 0.1; do kill -USR2 $$; done) & disown 51957 51958 →実際にやってみたが思う様に動いていない様に見える。 51959 どうも親プロセスでキーボード入力をした回数だけしか発生していない様な…。 51960 というわけでそもそもこの方法は使えないという事なのかも知れない。 51961 51962 b mkfifo による方法に関しては…。これは処理する側で遅延が発生すると、 51963 延々とパイプにデータが流し込まれメモリに悪そうだという問題がある。 51964 しかしバッファが一杯になったら都合良く停止するだろうか (バッファのサイズによる)。 51965 51966 →或る程度呼び出したら停止した。と思ったらそんな事は無かった。 51967 というか 1 秒間に 10 文字程度ではすぐには buffer は一杯にならない。 51968 51969 $ exec 3< <(trap -- '' INT QUIT; while echo -n t; do sleep 0.1; done) 51970 $ while read -t 0 <&3; do IFS= read -r -d '' -n 1 byte <&3; ((count++)); done; echo $count 51971 51972 所で timer を停止したい場合にはどうしたら良いのか…。プロセス番号を取得するには? 51973 と思ったらプロセス置換の場合でもちゃんと $! にプロセス置換のプロセス番号が入っていた。 51974 なので $! さえ何処かに記録しておけば問題ない。 51975 51976 更に実際に動かしてみると安定して動いている様に見える。 51977 51978 c もし自プロセス内で閉じた方法があればそれが一番良い。 51979 例えばミリ秒単位で時刻を計測することができれば経過時間に応じて 51980 sleep 量を調整する事ができる。 51981 51982 printf -v '%(%s)T' を用いる方法だと秒より下の単位は取得できない。 51983 GNU coreutils の date はその様な機能 (%N) も持っている様だが、拡張に過ぎない。 51984 51985 あった。procfs をマウントしていれば (そして現在のシステムでは殆どそうだろう) 51986 cat /proc/uptime でシステムを起動してからの時間を見ることができる。 51987 と思ったが linux, cygwin には /proc/uptime があるが、mac os x ではそもそも /proc がない様だ。 51988 FreeBSD でも /proc はあるが、BSD にはなかったからの様だ。他に HP-UX もない。 51989 Solaris には /proc はあるが /proc/uptime は無い様な雰囲気である (確認できていない)。 51990 51991 また /proc/uptime を呼び出す overhead が如何程の物かという問題もある。 51992 →0.05ms であった。本当に計測できているのだろうか?? 51993 関数に入れて見たが計測できている様だ。という訳で overhead はない物として良い。 51994 51995 * [自然解消] 2016-06-19 complete 補完候補一覧表示: [#D0836] 51996 やはり現在までに入力した部分と、 51997 未だ入力されていない補間文字列の部分を色分けして表示した方が良い。 51998 特に入力文字列が長い場合に見にくい。 51999 52000 * [自然解消] 2016-06-19 complete 補完候補一覧表示: [#D0835] 52001 また、候補が長い場合や入力が面倒な場合 (例えば日本語の場合) があるので、 52002 矢印キーなどで選択できる様にした方が良い。 52003 52004 * [自然解消] 2016-06-19 timer/非同期実行機能: [#D0834] 52005 history 検索やゲーム的機能 (demo 用) の実装のためには、 52006 やはり timer の様なイベントを発生させる仕組みを整えた方が良い様な気がする。 52007 52008 →しかし無駄に複雑にしたり需要に合わない様な形に実装しても仕方がないので、 52009 取り敢えずは history の検索に於いて非同期に処理を行う方法を実装して、 52010 その後でその実装を参考にして仕組みを整える方が賢明である様に思われる。 52011 あるいは、history を非同期に検索できる様にしたとしても 52012 途中で面倒になって統一的な実装にしたくなるかも知れないが、 52013 そうだとしても history を目的として最小限の統一的実装にするという方向でよい。 52014 52015 非同期の実行の仕組みとしては、 52016 52017 1. 先ず処理を中断できる様な方法で実装するという事、 52018 2. それからユーザからの入力があった場合にそれを検知できるという事。 52019 52020 これらだけあれば基本的に十分である。 52021 ユーザからの入力は bash-4.0 以降であれば read -t 0 で確認できる。 52022 なので、基本的には処理の方を細切れにできれば何も問題は生じない筈である。 52023 一応ユーザからの入力を受ける時に bash が勝手に色々操作をするので、 52024 それの対策として色々出力を繋ぎ変えたり表示を更新した理などの処理はあるが、 52025 それらは別に大したことはない。context switching か何かの一部だと思えば良い。 52026 52027 * [自然解消] 2016-04-06 補完候補表示で既に入力が完了しているディレクトリ部分についてはそれを表示しない様にする [#D0833] 52028 表示されている候補がファイル名とは限らないが、補間されている候補の種類に依らず省略して良いと思う。 52029 そちらの方が自然である。もしファイル名でないとしても似たような入れ子構造に対応している可能性が高いので。 52030 52031 →でも、前に何か対応したような気がするが…、と思って改めて確かめてみたら、 52032 ちゃんと ../../ の様な面倒な物は省略されて表示されている様な気がする。 52033 では何故先程は ../../ の様な文字列が大量に表示されていたのだろうか…。 52034 52035 →いや、cd コマンドの候補 (プログラム補間候補) がそうはなっていない様である。 52036 前に同様の事を議論したような気がするのでログを漁ってみる事にする。 52037 52038 2018-09-23 これは基本的にプログラム補完 (bash-completion) が悪い。 52039 余り黄にしても仕方がないので取り敢えず保留という事にする。 52040 52041 * [自然解消] 2015-11-21 同じ場所で complete (TAB) を連続で呼び出した時にカウントを行うべき [#D0832] 52042 + peco や sentaku など (?) の外部コマンドを起動する時の基準に使用できる。 52043 52044 2018-09-23 これは結局 core-complete.sh 自身で絞り込みを提供するので余り必要なくなった。 52045 また既に同じ場所で連続で呼び出したかどうかは LASTWIDGET 経由で判定できる様になっている。 52046 回数まではカウントしていないが、widget の側で数える様にする事は容易である。 52047 52048 * [自然解消] 2015-11-21 vi bind (これは bind -p で調べれば大丈夫の筈?) [#D0831] 52049 52050 →bind -p して見たがどうも vi には vi の完全に異なるコマンド体系がある様である。 52051 単純な移動コマンドぐらいならば対応できるが、それ以外の物についてはどの様な操作なのか 52052 よく理解していないので憶測で実装するのは難しい。 52053 52054 2018-09-23 これは既に support-vi-mode で実装済みである。 52055 52056 * [自然解消] 2015-11-18 PROMPT_COMMAND を一番外側の環境で実行する様に変更する [#D0830] 52057 52058 現在は .ble-line-prompt/update の中で直接実行している。 52059 52060 また、stty 等を正しく設定して呼び出すようにする? 52061 52062 参考の為: 現在 ble-bind -cf による登録では、 52063 function .ble-edit.bind.command を通して .ble-edit.accept-line.add 52064 でコマンドを登録し一番最後に外側でコマンドを実行する。 52065 このコマンドによる出力はプロンプトの次の行に表示される。 52066 またコマンド終了後には改めてプロンプトが表示される。 52067 52068 一方で ble-bind -xf proc に関してはそもそも未実装の状態になっていた。 52069 このコマンドではプロンプトの次の行に行ったり、プロンプトを消したり、 52070 或いはプロンプトを再描画したりなどと言った事は不要である。 52071 (勝手な出力をしないという前提・表示が乱れた場合 proc の方が悪いという事にする) 52072 52073 2018-09-23 これは既にその様な実装になっている。 52074 stty の設定は行っていないが、上記の議論の通り、 52075 変な表示になったりしても前提を崩す様な処理を行う方が悪いのだという事にする。 52076 つまり、現状の通り stty などによる調整は行わないで良い。 52077 52078 * [自然解消] 2015-02-27 complete: 文脈判定を強化する。他にも色々な箇所で補完を実行する [#D0829] 52079 52080 2018-09-23 これは曖昧な項目であるが少なくとも当時よりは大幅に増強された。 52081 52082 * [自然解消] 2013-06-01 以前 compgen, history コマンドを関数内から自由に利用する事が出来るか [#D0828] 52083 → できる (2018-09-23) 52084 52085 2018-09-23 52086 52087 * auto-complete: 構文エラーが自動補完により解決される時 <kbd>RET</kbd> でコマンド実行が抑止されない [#D0827] 52088 52089 * isearch: C-d で現在の選択範囲を削除する様に変更。また C-m (RET) で確定した時は選択範囲を解除 [#D0826] 52090 52091 * complete (suggestion by cmplstofB): vi_imap に於いて C-] から sabbrev-expand に束縛 [#D0825] 52092 https://github.com/akinomyoga/ble.sh/issues/5 52093 52094 * 2015-03-04 減色 (88colors の時の palette について) [#D0824] 52095 16-79 4x4x4 0,58*v+81 52096 80-87 gray 46+25*v 52097 52098 * term: term.sh の local j=$((k-i1+j1)) の k は i の誤りである [#D0823] 52099 序でに端末が256色対応していない場合の減色処理についても追加する。 52100 52101 * edit: 検索中や auto_complete にて C-RET ですぐに実行という意味にしたい [#D0822] 52102 52103 序でに isearch/accept → isearch/accept-and-execute にしようと思ったが、 52104 検索を終了して実行しない物は既に isearch/exit という名前が与えられている様なので、 52105 isearch/accept のままにする事にした。そうすると、今度は auto_complete/accept-and-execute 52106 の方を auto_complete/accept にして、auto_complete/accept を別の単語にしたくなる。 52107 accept の代わりに "確定する" という様な意味の単語があれば良いが、 52108 検索してみると determine, decide などが出てくる。これらは意味が違う。 52109 他に settle や fix 等があるが前者は余りニュアンスが分からない。 52110 後者は色々意味がありすぎて auto_complete/fix などとしても伝わらない気がする。 52111 もっとよく使われる単語で良さそうな物はないだろうか。 52112 insert にしようか。insert が良さそうだ。編集関数名の変更の一覧を作成しておく。 52113 52114 - menu_complete/accept → menu_complete/exit 52115 - auto_complete/accept → auto_complete/insert 52116 - auto_complete/accept-on-end → auto_complete/insert-on-end 52117 - auto_complete/accept-word → auto_complete/insert-word 52118 - auto_complete/accept-and-execute → auto_complete/accept-line 52119 - isearch/accept → isearch/accept-line 52120 52121 2018-09-22 52122 52123 * term (reported by cmplstofB): libvte 系列のターミナルで SGR(>4) が画面に表示されてしまう [#D0821] 52124 これは bleopt term_modifyOtherKeys_{in,ex}ternal=auto に対応し、 52125 端末の DA2 応答を見て libvte では SGR(>4) を既定では送らない様にする事にした。 52126 libvte をちゃんと区別する方法はない様であるが、DA2R の最初の数字が 1 の物は 52127 vt220 か libvte 及び Windows のマイナーな端末しかない様なので、 52128 これらが SGR(>4) に対応しているとは思われないので問題ないだろう。 52129 52130 * 2018-09-10 complete: 略語展開 [#D0820] 52131 52132 動的略語展開に対応するにしても zsh-abbbreviations に対応するにしても、 52133 補完文脈を外から指定できる様にする仕組みが必要になる。 52134 52135 現在の仕組みは ble-syntax:bash/completion-context/generate に固定になっている。 52136 この部分を別の補完文脈生成に差し替える事ができる様にする仕組みが欲しい。 52137 52138 ble-complete/candidates/get-contexts の中で呼び出している。 52139 これを ble-complete/context:$context/generate 的な物に置き換えられたら良い。 52140 というか補完文脈を生成する物にどのような名前をつけたら良いであろう。 52141 52142 % 補完文脈を生成するものも context (文脈) と呼ぶのだと混乱の元である。 52143 % 52144 % 因みに現在は ble-complete/source:SOURCE と ble-complete/action:ACTION がある。 52145 % 今 context と読んでいるのは位置と source の組である。 52146 % 最近 context 配列を contexts に変更したがこれは失敗したかもしれない。 52147 % 実は context == sources だったのかもしれない。 52148 % pick-nearest-context なども pick-nearest-source であるべきだったかもしれない。 52149 % 52150 % うーん。今となっては面倒なので context を生成する機構は switch という事にする。 52151 52152 2018-09-20 元気があったので今まで context ctx と呼んでいた物は全て source src に改名した。 52153 source を生成していた物が今後は context になる。 52154 52155 改めて思うことは、実は静的略語展開にしても動的略語展開にしても、 52156 実は complete の枠組みとは処理の仕方が異なるので、 52157 また独立に実装する必要があるのではないかという事。 52158 もしそうだとするならば context:??? を用意して実装するというのは変な気がする。 52159 52160 * 寧ろ context:??? を用意して実装するのは個別の補完の種類を指定した補完なのではないか。 52161 取り敢えず実装仕掛けてしまったので個別の補完の種類を指定した補完に対応する事にする。 52162 取り敢えず実装して emacs モードでテストした。動いている。 52163 52164 | 問題は vim mode でどの様に実装するべきかである。 52165 | M-/ 等には bind したくない。すると C-x / 等だけに bind する事になり、 52166 | 最初から menu-complete を試みる事になる。本当にそれで良いのだろうか。 52167 | 52168 | * vim での振る舞いについて確認しておく事にする。 52169 | vim の振る舞いは何だかよく分からない。取り敢えず C-x C-v とするとメニュー補完に入る様だ。 52170 | その意味では menu-complete に入るという振る舞いは良い。 52171 | しかし、その後で C-v を再び押すとどんどん次の候補に移動する様である。 52172 | という事は、menu-complete でも例えば C-x / で始まった時には、 52173 | / を連続で押す事によって次の候補に移動するという事をしても良いのではないか。 52174 | * と思って bash の振る舞いを再度確認したら、 52175 | これはメニュー補完ではなくて、単にメニューを表示するだけだった。 52176 | C-x $ に続けて連続して $ を入力しても、普通に $ が入力されるだけで、 52177 | 別にメニュー補完に突入する等の事はないようだ。 52178 | 52179 | まとめると 52180 | - vim では C-x C-v とするとメニュー補完に入り、続けて C-v を押すとメニュー内の選択をできる。 52181 | - bash では C-x / などとすると単にメニューを表示するだけでメニュー補完に入るという事はない。 52182 52183 これを踏まえて以下の様に実装する事にする。 52184 52185 - emacs モードでは bash と同様の動作とする。つまりメニューを表示する。 52186 - vim モードでは menu-complete に入る。但し、同じキーを続けて打つ事による選択には対応しない? 52187 52188 まあ、取り敢えずこれで完了という事にする。 52189 52190 * 次に静的略語展開について考える。 52191 静的略語展開は補完候補の生成などは実は行わない。 52192 単に文脈を見て完全一致したら置換を実行するだけである。 52193 magic-space を改造する必要がある。 52194 52195 先に静的略語展開に対応する事にした。 52196 52197 * 動的略語展開は command argument word など? 52198 或いは、extract-command で取得できる範囲? 52199 それを入力済みの文字列として履歴から合致する単語を探し出す。 52200 52201 しかし、履歴に含まれる単語を厳密に切り出すと時間がかかる。 52202 事前にバックグラウンドで単語の分割を実行したとしてもメモリを食う。 52203 更に、入れ子になっている場合なども考えていくと処理は単純ではない。 52204 52205 Bash の振る舞いはどうなっているのだろうか? 52206 52207 | 調べてみると例えば 'f に対して dabbrev-expand すると、 52208 | 過去の f で始まる単語に一致する。過去の "'f" で始まる単語には一致しない。 52209 | * 更に実際に挿入される文字列はちゃんと閉じ ' も付加される。 52210 | →これは core-complete の action:word/complete 辺りで行っているのと同様の事をすれば良い。 52211 | * また、過去の 'hello f*** world' 的な引用符の中の単語にも一致しない。 52212 | →これは単純なシェル特殊文字による分割ではなくて入れ子構造も考慮した探索になっている事を表す。 52213 | 52214 | うーん。これをちゃんと対応するのは難しい。 52215 | しかし、引用符の中を考えなくて良いのであれば或いは簡単かもしれない。 52216 | 52217 | 引用符をスキップして一致した物を見つければ良いのでは。 52218 | あと空白とシェルの分割文字 ><;|&(。 52219 | * また = と : については特別扱いするべきか。 52220 | 調べてみた所 : も = も特別扱いはされていない様だ。 52221 | : または = で区切られた補完候補も生成されないし、 52222 | また : または = が含まれていても全体として一つの補完候補となっている。 52223 | * 単に '' の部分だけ除去するだけでは駄目の様だ。 52224 | つまり、'bbbb'aaaa が履歴にある時 aaaa は候補にはならない。 52225 | * コマンド置換の中にある単語も候補にはならない。 52226 | * 引用符の中での dabbrev はできるが、クォートがある場合には dabbrev はできない。 52227 | つまり 'f からは dabbrev できるが、\f からは dabrrev できない。 52228 | もしかすると COMP_WORDBREAKS 以降の文字列に対して dabbrev しているだけなのかもしれない。 52229 | →なんとそれだった。\ を COMP_WORDBREAKS に入れたら \f から dabbrev できるようになった。 52230 | 52231 | つまり、以下の様な実装になる。 52232 | 1 COMP_WORDBREAKS 以降の文字列を入力済み部分とする 52233 | 2 入力済み部分に一致する単語を履歴の中から探し出す。 52234 | 単語がどう切り出されているのかは不明 52235 52236 ble でどの様な仕様にするかは色々考えられる。 52237 52238 | a COMP_WORDBREAKS で区切って最後の単語に対して履歴から検索を行う。 52239 | 52240 | b 文法構造に従った単語で履歴から検索を行う。 52241 | 文法構造を解析しているので単語を抽出する事は容易である。 52242 | しかし、履歴の方については文法構造に従った抽出は困難である。 52243 | 52244 | 52245 | ? 展開した結果の文字列を履歴から検索するのか 52246 | 展開前の文字列について履歴から検索するのか。 52247 | これは、履歴を一つ一つ展開するのが困難であるし、 52248 | 展開語が一致する様に展開前に対する正規表現を構築するのも不可能であるから、 52249 | 整合性を考えるならば展開前の文字列について履歴から検索するのが妥当である。 52250 | 52251 | ? Bash では履歴の中の引用符に含まれる文字列などには一致しなかった。 52252 | これを正しく実装するのは ble では難しい。 52253 | 正規表現で単語を切り出しながら一致させる事も可能であるが、 52254 | そうすると少し複雑な単語が含まれているだけで、 52255 | それ以降の単語について一致させる事ができなくなる。 52256 | 52257 | 改めて Bash で試してみると、例えば $ から dabbrev-expand すると、 52258 | ちゃんとコマンド置換の単語も抜き出す事ができているという事から、 52259 | やはりトップレベルの単語について全て記録している、 52260 | もしくは一致させる時にちゃんと解析をしているという事になる。 52261 | 52262 | これを ble で実現する為には、 52263 | 内部的に文法構造の解析を実行するか、 52264 | 或いは、簡易な方法で読み飛ばすか、 52265 | という事をしながら履歴を検索していかなければならない。 52266 | 因みに Bash は簡易な方法で読み飛ばしているのではないかという気がする。 52267 | 元々の解析自体が簡易な方法で読み飛ばしてから、 52268 | 中の構造をまた解析し直すという解析方法を取っているように思うので。 52269 | 簡易な方法で読み飛ばすとしたらどの様にすれば良いのか。 52270 | ${} と () をカウントすれば良いだろうか。 52271 | それと " についてもちゃんと開く・閉じるを調べる必要がある。 52272 | 再帰下降で解析すればそんなには難しくないのだろうという気がする。 52273 | 但し Bash で実装するのには重い気がする。 52274 52275 Bash の動作 52276 52277 COMP_WORDBREAKS で区切った単語を現在位置から切り出し、 52278 文法構造に従ったトップレベルの単語を履歴から検索する。 52279 単語のクォート除去などは行わない状態で検索を行う。 52280 52281 方針1 52282 52283 文法構造に従った単語を現在位置から切り出し、 52284 文法構造に従った単語を履歴から検索する。 52285 これは事前に単語の一覧を作っておくか、 52286 その場で解析を実行しなければならない。 52287 52288 方針2 52289 52290 COMP_WORDBREAKS で区切った単語を現在位置から切り出し、 52291 COMP_WORDBREAKS 区切りで単語を履歴から検索する。 52292 52293 実用性という観点から考えると、例えば $(...) 52294 という様な単語を切り出すという事があるのかという疑問がある。 52295 それよりは細かい単語を補完させる場合の方が多いのではないかと思う。 52296 その様に考えると COMP_WORDBREAKS で区切った物を履歴から検索する方が自然に思われる。 52297 52298 取り敢えず方針2で実装する事にする。 52299 52300 * complete: メニューが表示されている状態で C-x ~ 等を実行すると [#D0819] 52301 その時にメニューに表示されている内容でメニューに入ってしまう。 52302 context= が指定されている時にはメニューに入るべきではないのではないか。 52303 →取り敢えずその様に実装した。この仕様は微妙かもしれないが暫く試してみる事にする。 52304 52305 * 2018-09-15 [保留] complete: 補完で stackdump が出た。恐らく補完のバグである [#D0818] 52306 52307 TAB RET を連続で打った。しかし、本当にそれが原因かは分からない。 52308 寧ろ menu-filter や auto-complete の方が問題である可能性もある。 52309 備考: magnate で発生した。直前に cd で [ble: EOF] が表示される問題が再現している。 52310 52311 | [murase@magnate2016 0 bin]$ cd 52312 | [murase@magnate2016 0 ~]$ c[ble: EOF] 52313 | [murase@magnate2016 0 ~]$ cd bin/l 52314 | [murase@magnate2016 0 bin]$ stackdump: X1 0 <= beg:0 <= end:1 <= iN:1, beg:0 <= end0:-1 (shift=2 text=l) 52315 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:6 (ble-syntax/parse) 52316 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:4 (ble-edit/content/update-syntax) 52317 | @ /home/murase/.mwg/src/ble.sh/out/lib/core-syntax.sh:14 (ble-highlight-layer:syntax/update) 52318 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:5 (ble-highlight-layer/update) 52319 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:40 (ble/textarea#update-text-buffer) 52320 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:3 (ble/textarea#render) 52321 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:2 (ble/widget/.insert-newline) 52322 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:34 (ble/widget/.newline) 52323 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:0 (ble/widget/accept-line) 52324 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:21 (ble-decode/widget/.call-keyseq) 52325 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:42 (ble-decode-key) 52326 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:43 (ble-decode-char/.send-modified-key) 52327 | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:50 (ble-decode-char) 52328 52329 padparadscha 上で試しても再現しない。 52330 上を観察すると beg, end は正しい値になっているが 52331 end0 が設定されていないという状況の様だ。謎である。 52332 また、これは今までによく発生していた mark と ind のエラーではなくて、 52333 ble-syntax/parse の中で起こっている更新範囲のエラーである。 52334 特に ble-syntax/parse から利用する end0 に触っている箇所は限られているはずである。 52335 52336 * 辿って行くと、ble/dirty-range#update を信頼するならば、 52337 ble-edit/content/.update-dirty-range の呼び出し元が怪しい。 52338 これの呼び出し元は三箇所で以下の通り 52339 - ble-edit/content/replace 52340 - ble-edit/content/reset 52341 - ble-edit/content/reset-and-check-dirty 52342 reset の場合には内部で文字列長を取得しているので end0 が負になる事はありえない。 52343 reset-and-check-dirty に関しても ble/string#common-suffix が渡した文字列よりも長い 52344 誤った結果を返さない限りは end0 が負になる事はない。 52345 従って、ble-edit/content/replace の呼び出し元を調べれば良いはずである。 52346 core-complete.sh の中での ble-edit/content/replace の呼び出し元は以下の通り。 52347 - ble-complete/menu-complete/select 52348 ここは end として _ble_edit_ind を渡している。 52349 _ble_edit_ind が負になっていたらもっと色々なエラーが出ている筈であるし、 52350 また今回の操作には menu-complete は関係ないのでこれは大丈夫だろう。 52351 52352 - ble-complete/auto-complete/.check-history 52353 - ble-complete/auto-complete/.check-context 52354 ここでも _ble_edit_ind を渡している。 52355 - ble/widget/auto_complete/cancel 52356 - ble/widget/auto_complete/accept 52357 これらは _ble_edit_mark の方を渡している。 52358 - ble/widget/auto_complete/self-insert 52359 - ble/widget/auto_complete/accept-word 52360 _ble_edit_ind を渡している。 52361 うーん。何れも問題がないように思われる。 52362 52363 * ble/dirty-range#update の実装を確認する。 52364 どうもこれを読むと beg>=0 で end<0, end0<0 という状況も想定している様である。 52365 end<0, end0<0 は恐らく末端までという意味であろう。 52366 しかし、今回は beg>=0 ならば end>=0 かつ end0>=0 と仮定する。 52367 この時 end0 が元にない値になるのは、 52368 delta=endA-endB0 が負の時でこの時 end0=endA0-delta とされる。 52369 しかし、これは end0 を増加させるのであって、end0 が負になることの説明にはならない。 52370 因みに、例えば以下のような形の変更である。処理としても正しい。 52371 52372 0---bA-----------eA0---e0---$ 52373 | | / : / 52374 | | / : / 52375 0---bA---bB---eA---eB0---$ 52376 | : | / / 52377 | : | / / 52378 0---bA---bB------eB---$ 52379 52380 * core-complete.sh 内部で _ble_edit_mark に値を設定している箇所を確認する。 52381 何れも _ble_edit_ind に正の値を渡しているか、或いは直接正の値を代入している様に見える。 52382 _ble_edit_ind に関しては insert_beg または _ble_complete_ac_comp1, _ble_complete_menu_beg が負の値だと 52383 もしかすると負の値になってしまうかもしれない。 52384 insert_beg は _ble_complete_menu_beg または _ble_complete_ac_comp1 から値を持ってきている。 52385 それ以外の場所は自明に正の値になっているはずである。 52386 _ble_complete_menu_beg は COMP1 から値を取ってきている。 52387 _ble_complete_menu_comp1 も COMP1 から値を取ってきている。 52388 COMP1 は補完文脈から直接値を取得している。 52389 52390 補完文脈でバグにより負の値が生成される事があるのだろうか。 52391 取り敢えず ble-syntax/completion-context/.add に 52392 ble-assert を設置して様子を見る事にする。 52393 また、エラーが発生した時の修正で end0 も値を設定する様にした。 52394 後はまた様子見をする事にする。 52395 52396 * [保留] 2018-09-11 complete: 止まってしまう問題。端末の問題なのか ble.sh の問題なのか切り分けが必要 [#D0817] 52397 と思ったが最新版では再現しない。何だったのだろうか。 52398 52399 - これはやはり今でも起こる様である。 52400 - 先ず今までに screen の中で起こった事はない。 52401 rosaterm に関して起こった。 52402 - Cygwin だけでなく Linux (padparadscha) の上でも起こる。 52403 - 別の端末から bash を殺すと再度動く様になることから、 52404 端末の表示がおかしくなっているという事ではない。 52405 - コマンドの実行直後に起こる事もある 52406 実はかなりの頻度で起こっている。 52407 52408 2018-09-19 今試すとやはり動かない。何らかの発生条件があるのだろうか。 52409 52410 2018-09-19 52411 52412 * edit: コマンド実行が伴わないとき、ちらつき防止の為 insert-newline で info を消去しない [#D0816] 52413 空のコマンドに対しても毎回 info を隠したり表したりするのは 52414 非効率でありちらつきの原因である。 52415 52416 序でに、コマンド実行時に現在のカーソル位置より下に表示されている 52417 端末の内容を上書きする様に変更した。 52418 52419 * 2018-09-12 face が見つかりませんでしたのエラーメッセージは [#D0815] 52420 info か或いは新しい行に表示するべきではないか。 52421 52422 試しに internal の時には .SHELL_COMMAND を呼び出すようにしてみたが、 52423 表示が乱れるし何だかよくわからない振る舞いをする。 52424 調べてみると実際に setface が呼び出されるのは最初の render の最中であり、 52425 その render は exec が設定されていない時に ble-decode/.hook 内部から呼び出される 52426 bind/.tail からなのであった。従って、ここで .SHELL_COMMAND を呼び出すと、 52427 以下の様にして問題が発生する様である。 52428 52429 1 .SHELL_COMMAND 自体が今までの編集文字列を disabled にして 52430 明示的に textarea#render を呼び出すので、render の中で render を呼び出す形になる。 52431 2 exec が設定されているかどうかを確認した後なので、 52432 .SHELL_COMMAND を呼び出しても実際にそのコマンドが呼び出される事になるのは 52433 更に次のユーザ入力のあとになる。 52434 52435 ここで望ましい振る舞いは何だろう。 52436 52437 望ましいのは現在入力中の文字列は灰色に再描画して、 52438 その上で直後に表示を行うという事。 52439 .SHELL_COMMAND を呼び出すのは様々な端末の設定を復元してから実行したい場合である。 52440 また、関数の中ではなく一番外のスコープで実行したいという時である。 52441 今回は単に echo するだけなので .SHELL_COMMAND 経由で呼び出す必要はない。 52442 52443 なのでその場で .insert-line してから実行してしまえば良い気がする。 52444 但し、着色の初期化が終わってからでないと描画に支障を来すかもしれないので、 52445 初期化中に発生したエラーは初期化が終わってから一括で表示する事にする。 52446 52447 - C-x C-v で表示するバージョン表示も同様にして表示すれば良い。 52448 特に、何かを echo するだけの .SHOW_MESSAGE 的な物を作れば良い気がする。 52449 →ble/widget/print という編集関数を用意した。 52450 - 他の箇所も全て ble/widget/print を呼び出す様に変更する、と思ったら、 52451 echo して序でに jobs も実行するという物があった。 52452 つまりコマンドの実行もできた方が良い。 52453 結局 ble/widget/internal-command という関数を用意する事にした。 52454 - command-help に関しても序でに "外の環境でコマンドをその場で実行する" ものとして 52455 ble/widget/external-command を実装してそれを使って表示する様に変更した。 52456 - 分かりやすさの為、.SHELL_COMMAND は ble/widget/execute-command という編集関数を用意して、 52457 その編集関数をそのまま呼び出すことによって実装する様に変更した。 52458 52459 * ble-edit/read は ble/util/strftime で timeout を計っているが [#D0814] 52460 EPOCHREALTIME 等、他にももっと良い計測方法が在るのではないだろうか。 52461 idle で使用している物を流用できれば流用したい。 52462 特に idle で使用している物を汎用的な物に書き換えるなどすると良さそう。 52463 初期化と取得に分けて時間間隔を計ることができるようにする。 52464 52465 * decode: ユーザが勝手に先に keymap にキーを追加していると [#D0813] 52466 ble-decode/keymap/load が呼び出されずに、既定の設定が呼び出されない可能性がある。 52467 52468 a 元々存在していない keymap は受け付けるべきではないのではないか。 52469 現在の実装はどうなっているだろうか。様々の keymap について明示的に定義していただろうか。 52470 52471 b 或いは、既に keymap が存在している場合には bind 時に define を呼び出す様にするか。 52472 しかし、それだと keymap:$keymap/define も遅延ロードされる時にやはり駄目。 52473 52474 やはり a の方針で行く事にする。 52475 取り敢えず ble-decode/keymap/load を bind 時に実行して、 52476 失敗したらエラーという事で良いのではないかと思ったが、 52477 よく考えたら ble-decode/keymap/load は内部で bind を呼び出すので無限ループになってしまう。 52478 52479 * complete (request by cmplstofB): 補完関係の設定をする為に補完に load hook を追加した [#D0812] 52480 52481 * complete (request by cmplstofB): ble/widget/auto_complete/accept-and-execute [#D0811] 52482 名称をどうするか悩んだが結局 accept-and-execute にした。 52483 accept-and-accept だとよく分からないし、 52484 accept-and-accept-line も似たような物である。 52485 単に accept-line とすると accept-word との対比から勘違いする。 52486 結局 accept-and-execute という事にした。後でまた変更するかもしれない。 52487 52488 52489 2018-09-18 52490 52491 * 2018-09-15 complete: "for a in @" と "do @" の補完で空の補完源が指定されている様だ [#D0810] 52492 エラーメッセージが出る。と思ったら 52493 ble-syntax/completion-context/.check-prefix/ctx:next-identifier 内部の変数名の typo だった。直した。 52494 52495 * 2018-09-13 edit: TRAPWINCH による再描画条件 (TERM=rosaterm において cd した時の表示が変だ) [#D0809] 52496 何故か [ble: EOF] が表示されてから改行が実行されるという事が起こっている。 52497 今試すと再現しない。magnate からだけ再現するという可能性もある。 52498 →試してみた所 magnate では再現する。 52499 52500 | うーん。もしかするとこれは Bash が cd の変更による 52501 | プロンプト再表示に対応しているという事なのだろうか。 52502 | つまり、余分に表示されているプロンプトは Bash によるものの可能性。 52503 | しかし、screen の中では発生しないというのは不思議な事である。 52504 | 52505 | また builtin cd の呼び出しでは再現しない。 52506 | cd を複数回中で呼び出してもプロンプトの余分な表示は一回だけ起こる。 52507 | 調べるに当たって複数の方向性が在る。 52508 | 一つは ble.sh のどのタイミングでプロンプトの余分な再描画が行われているのか。 52509 | そしてもう一つは mwg_cdhist の中のどの行が問題を引き起こしているのか。 52510 | 52511 | * どうも mwg_cdhist.push "$PWD" &>/dev/null が問題を引き起こしている。 52512 | しかも、何故か &>/dev/null がある時に限って問題が起こる。 52513 | 段々と絞れてきた。 52514 | 52515 | $ f1() { (echo 1); }; f1 &>/dev/null 52516 | 52517 | だと再現するが、 52518 | 52519 | $ f1() (echo 1); f1 &>/dev/null 52520 | 52521 | だと再現しない。何が原因なのかは不明である。 52522 | 52523 | * うーん。過去の ble.sh の version に遡ってみる。 52524 | どうも b232a88 からの様である。 52525 | 調べると bleopt_term_modifyOtherKeys_external= だとならなくて 52526 | bleopt_term_modifyOtherKeys_external=1 だとなる。 52527 | というより bleopt_term_modifyOtherKeys_external が非空白だとなる。 52528 | この振る舞いは最新版でも再現した。 52529 52530 * f1() { (echo 1); }; f1 &>/dev/null で発生するが 52531 f1() (echo 1); f1 &>/dev/null では発生しない。 52532 * bleopt_term_modifyOtherKeys_external に非空白の値が設定されているとなる。 52533 つまりコマンド実行直前に CSI > 4 m が送信されるかされないかの違いである。 52534 52535 うーん。何故上記の組み合わせで起こるのかは謎であるがこれは Poderosa のバグ、だろうか? 52536 52537 もう少し試してみた。先ずプロンプトに + を追加して様子を見てみる。 52538 そうすると余分に表示されるプロンプトに関しても + が付加されている。 52539 更にプロンプトの計算回数も + の前に付加してみると、 52540 余分に表示されているプロンプトは確かに一つの独立した描画によって為されている様である。 52541 52542 分かった気がする。どうやら Poderosa が modifyOtherKeys を受け取った時に画面の下端に 52543 不明なシーケンスを受け取った旨を表示するがその瞬間だけ画面サイズが変化する。 52544 その通知を ble.sh が受け取って再描画を実施しているという事の気がする。 52545 調べてみると screen の中に居る時には CSI > 4 m は Poderosa に到達していない様だ。 52546 52547 更に &>/dev/null の有無で変化するのは TRAPWINCH からの出力が何処へ行くかの問題の様に思われる。 52548 これは TRAPWINCH に於いて現在プロンプトを表示している状態かどうかを検査すれば良い。 52549 52550 プロンプトの表示・非表示は何処で設定されているだろうか。 52551 コマンド実行は gexec/.begin 及び gexec/.end で囲まれて実行される。 52552 これは gexec/.setup で設定されたフックによって実行される。 52553 gexec/.setup は gexec/process から呼び出され、 52554 これは ble-decode/EPILOGUE で呼び出される。 52555 ble-decode/EPILOGUE は ble-decode/.hook の最後に呼び出される。 52556 うーん。この decode の枠組自体はより一般の物なので 52557 ここではプロンプトの処理はしていない。 52558 52559 * internal/external の状態について確認 52560 だとすると寧ろコマンドを最初に登録している箇所での制御である。 52561 それは ble/widget/.SHELL_COMMAND などである。他にも沢山ある。 52562 ble/widget/.insert-newline を呼び出している箇所と考えれば良さそうである。 52563 52564 - ble/widget/.newline 52565 - ble/widget/discard-line 52566 - ble/widget/accept-line 52567 - ble/widget/read/accept 52568 これはパネル 1 の上で実行されている。 52569 しかもサブシェルの中で実行されているので、 52570 ここでの状態は外には反映されない。 52571 この中で TRAPWINCH を捕まえると何が起こるだろうか。 52572 というか中で TRAPWINCH が実行されるという事があるのだろうか。 52573 恐らく中では TRAPWINCH は実行されない様に思うが、 52574 52575 もし中で実行されるとすると .insert-newline が実行されると何が起こるか。 52576 52577 というか、そもそも .insert-newline は何を実行するのだったか。 52578 先ず、現在の状態で (未だ描画していなかった部分を) 描画を実施する。 52579 ble-info は仕舞う。textarea の末端へ行き、次の行に移動する。 52580 ジョブがあれば出力する。 52581 ble/textarea#invalidate を実行する。 52582 (実は単に _ble_textarea_invalidated=1 を設定するだけ) 52583 52584 その様に考えれば read の中で .insert-line が実行されて、 52585 プロンプトの類が表示されない状態になっている時、 52586 TRAPWINCH を呼び出されると何が起こるかというと、 52587 read の入力のプロンプトが再度表示されるという事になる。 52588 これは不都合である…。 52589 52590 * 判別方法 52591 52592 | a うーん。単に $_ble_term_state を見て external だったら再描画せず、 52593 | internal だったら再描画するというので良い様な気もする。 52594 | 52595 | この方法で確認して置かなければならないのは external になるのは、 52596 | 本当にコマンド実行のタイミングだけだったのかという事である。 52597 | この状態は ble/term/enter, leave を呼び出した時に変更される。 52598 | ble/term/enter の呼び出し元を調べる。 52599 | というより ble/term/leave の方を調べた方が良い。 52600 | 52601 | - ble/term/finalize 52602 | - ble/term/TRAPEXIT これは bash を終了する時である 52603 | - ble-edit/exec:exec 52604 | - ble-edit/exec:gexec/.begin 52605 | - ble-edit/read/.impl 52606 | これは external で read を呼び出した時に 52607 | 読み取り処理の途中だけ一時的に internal 52608 | になっていたのを元に戻すのに使っている。 52609 | 実は、これはサブシェルの中で実行するべきなのでは、 52610 | と思ったが、微妙である。サブシェルの中でクラッシュすると 52611 | 変な端末状態のままになってしまう。 52612 | 余り面倒な事は考えたくないので現在のままにしておく。 52613 | 52614 | うーん。そもそもこの read は internal の時にちゃんと動くのか謎だ…。 52615 | ちゃんと落ち着いて考える必要がある。 52616 | 52617 | - ble/widget/command-help.impl 52618 | これはまあ外部コマンドと同様である。 52619 | 実際に invalidate を呼び出している。 52620 | 52621 | b 或いは、当初の案で行くとどうすれば良いかと言うと… 52622 | _ble_textarea_invalidated=1 が設定されている場合には、 52623 | 何れ再描画される事が意図されているのでわざわざ再描画はその時点ではしないと判断できる。 52624 | しかし、本当にそれで良いのだろうか。それだと次のキーが入力されるまで再描画されない事になる。 52625 | それでも _ble_textarea_invalidated=1 で放置されて何も表示していないという事は、 52626 | 直後に未処理の入力があるか或いはコマンド実行中か、或いは関数の中にいて、 52627 | ble-decode/.hook の最後で再描画が為されるのを待っている状態という事になるから、 52628 | やはり再描画はその場ではしなくても良いという事になる気がする。 52629 | 52630 | 一方で、 _ble_textarea_invalidated= の状態で TRAPWINCH を受け取った場合にはどうだろうか。 52631 | もしかすると行全体の invalidate が起こっていないだけで、実は処理の途中で 52632 | ble-decode/.hook の最後で再描画されるのを待っている状態かもしれないし、 52633 | 或いは、アイドル状態でユーザの入力が為されるのを待っている状態かもしれない。 52634 | ユーザの入力を待っている状態であれば即座に TRAPWINCH を処理しないと不都合である。 52635 | 52636 | そう考えると実は _ble_textarea_invalidate だけを見るのではなくて、 52637 | dirty の方も確認するというのは手かもしれないと思われる。 52638 | dirty が残っていたら _ble_textarea_invalidated=1 を設定して終了する。 52639 | そう思って確認したが ble/textarea#render に於いて部分描画の必要性を判定する部分は単純ではなかった。 52640 | 結局、色々 highlight layer や syntax 等を処理した上で umin:umax を求めてそれを元に判断している。 52641 | なのでやはり _ble_textarea_invalidate を確認するだけで良い様に思われる。 52642 52643 折衷案で行く。 52644 52645 - _ble_textarea_invalidated に非空文字列が設定されている場合には、 52646 その直後の然るべきタイミングで再描画が行われるという事を期待して再描画はしない。 52647 - read 以外に関しては上記の方法で十分である。 52648 read に関しては、そもそも現在の実装に問題がないのかも含めて判断する必要がある。 52649 必要があれば _ble_term_state で external かどうかも判定の考慮に入れる。 52650 或いは、(read の実装がそれに合っていれば) それとは関係なく external で判定しても良いかもしれない。 52651 52652 * read を internal で呼び出した時の動作について確認を行う。 52653 処理は result=$(ble-edit/read/.loop) というサブシェルの中で行っている。 52654 ble-edit/read/.setup-textarea でパネル 1 に表示を行う。 52655 パネル 1 に表示を行うのはパネル 0 の表示を保持したまま入力を行う為であったと思われる。 52656 もしパネル 0 の表示を read する度に消して良いのだとしたらパネル 0 にそのまま表示しても良かった様に思われる。 52657 その後設定を行って文字を1文字ずつ読み取る。_ble_edit_read_accept に非空文字列が設定されたら終了する。 52658 特にループが終わった時に表示を調整するなどはしていない。 52659 つまり、_ble_edit_read_accept を設定する側で表示の調整を行っている。 52660 実際にやっているのは ble/widget/read/accept と ble/widget/read/cancel である。 52661 52662 ? ok: 特にキャンセルに関して言うと、実は何もしていない。 52663 うーん。external で使っている限りでは特に問題は起こっていない様に見える。何故だろうか。 52664 →と思ったが、よく見たら cancel の中で accept を呼んでいて、 52665 その accept が .insert-newline を実行しているのだった。 52666 52667 さて、ここでの問題は、internal で read をした時にどうなるかという事である。 52668 52669 $ function ble/widget/test1 { local REPLY; read -ep 'hello$ '; }; ble-bind -f C-t test1 52670 52671 これで実際に実行してみた所、表示の計算がずれることになった。 52672 さて、では逆にどの様な表示が望ましいだろうか。 52673 52674 a 一つの方法は一旦今まで表示していた textarea を disabled で再描画して、 52675 それから read で何かを読み取って、その後で再度新しい行に行を完全に描画し直す。 52676 b vi_cmap と同様に panel 1 に表示して、入力が完了したら入力に使ったパネルは消去する。 52677 これは何を入力したかを後で確認できなくなるという問題が残る。 52678 しかし、そもそも ble-bind で処理する時点で残る事を期待するのも変である。 52679 c 或いは一旦 textarea を消去してそこに read による入力を実行する。 52680 入力が完了したら新しい行に移動して、元々の編集文字列を再描画する。 52681 これは実質 a と殆ど同じで、元の内容を消去するか残すかの違いしかない。 52682 52683 | ところで bash はそもそもどの様に振る舞うのか。 52684 | bash-4.3 で試したら変な事になった。 52685 | 先ず、read を起動した瞬間に元のプロンプト・編集文字列は一旦消去する。 52686 | 確定すると次の行に移動するが read の行がもう一つ重複して表示されてしまう。 52687 | その後で本来のプロンプトが改めて描画されたりされなかったりするが、 52688 | 元の編集文字列の内容は消えてなくなっている。 52689 | 52690 | 更に bash-5.0 ではもっと変な振る舞いになっている。 52691 | 先ず、元のプロンプト(a)・編集文字列(b)は一旦消去する。 52692 | 新しい read のプロンプト(c)を表示して入力を受け付ける。 52693 | 確定すると次の行に移動して、プロンプトは read に使った(c)のままで(b)が表示されるが、 52694 | 更にその場で(b)がコマンドとして実行されてしまう。 52695 | その後で新しいプロンプトと空の編集文字列が表示される。 52696 | もしかすると bash-4.3 の振る舞いもこれと同じことだったのかもしれないが再度確認するのは面倒だ。 52697 52698 結局、bash 自体が変な振る舞いをするという事が分かったので、 52699 これに関しては ble.sh の側で自由に適切と思う動作を選択する事にする。 52700 特に上記の b の方向で実装する事にする。 52701 52702 これは実装した。 52703 52704 次に TRAPWINCH を修正する。 52705 read については独自に trap WINCH するのが良いのではないか。 52706 確認のためにサブシェルの中で trap がどうなっているのか確認する。 52707 サブシェル内部で "trap" とやると WINCH も出る。継承されている? 52708 実際に発動するのか分からないので確認してみる事にする。 52709 52710 調べてみた所、やはり親の側で発動している様である。 52711 では内部で改めて trap を実行した場合にちゃんと内部で発動する様になるのだろうか。 52712 ちゃんと呼び出されている。しかし再描画させようとしたら式に誤りがあるというエラーが発生した。後で見る。 52713 これは IFS の問題だった。TRAPWINCH の中で IFS を設定するようにしたら直った。 52714 52715 取り敢えず動いている様子なので一旦コミットする→直った事を確認した。 52716 52717 2018-09-15 52718 52719 * mshex: mwg_cdhist が failglob で動かなくなる [#D0808] 52720 これは後で確認する。そんなに難しい事ではないだろう。 52721 何箇所か修正したが本当にこれで全部なのかは分からない。 52722 取り敢えず問題は起こらなくなったが、mwg.dict の実装を再度確認する。 52723 再確認した。また古いコードを大幅にレファクタリングした。 52724 52725 * bash-3.0: 補完できない時に ble-complete/source/: No such file or directory のメッセージが出る [#D0807] 52726 % これはまた bash-3.0 配列のバグ回避に失敗している気がする。 52727 これは単に ble/array#push の bash-3.0 向けの実装に問題があった。 52728 push する要素が一つもない場合にから文字列を追加する様になっていた。 52729 これを修正したら直った。 52730 52731 * [棄却] base: --noattach を忘れた時に PS1 が元に戻る問題の対策 [#D0806] 52732 これは元々使い方を誤っているのが問題なのだが、 52733 多少変な使い方をしても変なことが起こらないようにはしたい。 52734 52735 と思ったが最初のキーを受け付ける迄には PS1 は表示しなければならない。 52736 つまり最初のキーを受け付けるよりは前に PS1 を読み取って、 52737 しかし bashrc の末尾で PS1 を更新するという様にしなければならない。 52738 しかし、そもそも ble-attach した瞬間に既にプロンプトを表示するので、 52739 PS1 が設定されたのを検出できたとしても 52740 最初の一回は必ず設定前のプロンプトになってしまう。 52741 やはり遅延初期化をし忘れた場合に PS1 を正しく実行する様にするのは難しい。 52742 52743 2018-09-13 52744 52745 * edit: read/exit の振る舞いが破壊されていた [#D0805] 52746 52747 mshex: mwg_cdhist が何故かフリーズする。 52748 これは謎である。今までは起こっていなかった。 52749 ble.sh との相互作用で何か変な事が起こっているのだろうか。 52750 →ble.sh をロードせずに実行するとフリーズするという事はない。 52751 何が悪いのだろうか。例えば、fd がバッティングしている可能性など? 52752 52753 これはあらゆる所で問題をおこしている。 52754 早く修正しなければならない。 52755 どうも C-@ しか受信できない状態になっている様だ。 52756 52757 →分かった。read が全く働いていない。引数を渡し忘れている。 52758 52759 * bash-3.0: ble-detach 後に stty sane を実行しろというメッセージが出る事に関して [#D0804] 52760 52761 * ok: bash-3.0 では stty sane がコマンドラインに入らない。 52762 →そもそも READLINE_LINE は bash-4.0 からの機能なのでコマンドラインに入らないのは問題ない。 52763 52764 一方で bash-4.3 では stty sane を実行しなくても特に問題は発生せず、 52765 しかし、前者に関しては謎である。見た感じ .check-detach で READLINE_LINE に 52766 stty sane を設定して、そのまま return 0 している。return 0 した時には、 52767 gexec/.end で bind/.tail を実行せずにそのまま終了する。 52768 従って、READLINE_LINE に stty sane が入っているはずである。 52769 52770 と思って確かめてみた所実はちゃんと READLINE_LINE には stty sane が代入されているが、 52771 それが表示されていないということの様だ。何故表示されていないのだろう。。 52772 52773 | | 何かこれに関して議論があったはずと思って調べた。 52774 | | #D0436 によると PS1 のずれを補正する為の茶番だそうだ。 52775 | | つまり、bash は以前の PS1 のまま表示しようとするので、 52776 | | 結果として空の PS1 になるのであるが、 52777 | | ble.sh が代わりにそれを表示して誤魔化している。 52778 | | しかし、それだと不都合が生じるので適当に何かコマンドを実行する必要があった。 52779 | | その為に stty sane を実行するのだという。 52780 | | いっぽうで、改めて試してみるとやはり stty sane を実行しないと問題になるようだ。 52781 | 52782 | ^L を入力して (別の理由によってそれが直接入力されて) 実行すると、 52783 | その後で stty の状態が変になっているという事が露呈する。 52784 | 52785 | しかし、現状では描画がずれて stty sane が表示されない。何故だろう。 52786 | READLINE_POINT=9 から 0 に変更しても同様だった。 52787 | 不思議なのは home を押すと内部的にはちゃんと home に行っている様なのに 52788 | 表示上はカーソルの位置が全く変わらない事である。 52789 | 52790 | 実は PS1 をクリアせずに保持するという手もあるのかもしれない。 52791 | 毎回何か変な内容が出力されるのを握りつぶす事になるが、… 52792 | と思ったが PS1 に含まれるコマンド実行などが余分に実行されるという問題がある。 52793 | 特にコマンド置換を用いていると余分に fork が発生して、 52794 | 特に Cygwin では遅延が二倍になって余り嬉しくない。 52795 | 52796 | やはり現状で何が起こっているのかについて調べる必要がある。 52797 | うーん。やはり不思議としかいいようがない。 52798 | そもそも再描画しないのだと仮定しても、カーソル位置が動かないのはおかしい。 52799 | うーん。普通に bind -x で echo hello 等とした場合には再描画が実行される。 52800 | ちゃんと全体が再描画されてカーソル位置の調整も行われる。 52801 | 52802 | うーん。どうやら bash は stty の状態に応じて 52803 | プロンプトの出力をする・しないが切り替わるのだという事を思い出した。 52804 52805 結局何が起こっているのかというと以下の事が起こっている。 52806 52807 - 恐らく Bash は前回の stty の状態に依存して、 52808 プロンプトなどの類を表示するかしないかを切り替えている。 52809 ble-detach の直後にはプロンプトも編集文字列も表示されない。 52810 - DEL でカーソル位置が動かなかったのは stty が中途半端な状態で、 52811 erase=^? の設定が欠けていたためにそもそも back の役割を持っていなかった為に、 52812 実際に文字の削除も行われていない状態だった。 52813 - 普通に文字を入力すると入力できている様に思われたのは、 52814 単に入力文字がエコーされているだけの様である。 52815 52816 調べると bash-4.0 -- 4.4 で一貫してこの事が起こっている様だったので、 52817 READLINE_LINE に関してもそのまま ble.sh 側で描画する事にした。 52818 bash-5.0 でも同様の振る舞いである。更に過去の ble の version ではどうであったか。 52819 ble-0.1 でも ble-0.2 でも再現した。全てに適用する事にする。 52820 52821 * bash-3.0: ble-detach した後で " が効かない [#D0803] 52822 Bash 4.3 ではこの問題は発生していない。 52823 代わりに bash 4.3 で試すと ^L が効かなくなっている。 52824 Bash 3.0 でも ^L は効かない。 52825 52826 Bash 3.0 で bind -p してみると "\"" に対してはちゃんと bind できている気がする。 52827 他に C-? が色々 self-insert になってしまっている。 52828 ^A-^C ^E-^G ^K ^L ^N-^Q ^X ^Z ^\ ^] ^^ である。 52829 52830 "\C-a": self-insert 52831 中略 52832 "\C-^": self-insert 52833 52834 unbind が一体どうなっているか確認する必要がある。 52835 調べたら unbind ではなくて $$.bind.save だった。 52836 52837 % * 中は完全に空である。何故か? 52838 % 52839 % 普通に起動して attach せずに 52840 % bind -sp | ble-decode-bind/.generate-source-to-unbind-default/.process を実行してみた所、 52841 % ちゃんと内容が出力されている。ということは bashrc の中で bind -sp すると何も出力されないという事か。 52842 % と思って再度実行してみるとちゃんと bind.save は有限のサイズになっている。 52843 % 更に bind.save をソースしている途中でエラーになって、跡で確認すると bind.save が空になっている。 52844 % と思ったら単に ble-decode-detach で読み取ったものをクリアしているだけだった。 52845 52846 * bind.save を読み込んでいる時に出るエラーは何か。 52847 ble-attach している状態で bind.save の中を確認する必要がある。 52848 52849 % * ok: 確認すると何と ^A-^^ の問題のキーは確かに bind '"\C-a": self-insert' 等となっている。 52850 % 取り敢えず '"\C-a": self-insert' の原因だけ探る。改めて bind -sp してみる。 52851 % 不思議な事に ble-decode-bind/.generate-source-to-unbind-default の中で実行した。 52852 % bind -sp は self-insert になっている。 52853 % 52854 % --attach=prompt が悪いのかと思って --noattach に直したが同じである。 52855 % 52856 % 何と bashrc の中で bind -sp を評価したら "C-a": self-insert になっている…。 52857 % これは実は Bash 4.3 でも同じである。対策する必要がある。 52858 % 52859 % 更に調べてみると bashrc の中でも source ble.sh する前と後で 52860 % bind -sp の内容が変化するのであった。どうも調べていくと rcfile の前後で変わっている。 52861 % .blerc を見ると set -o vi をしていた。つまり ^A-^^ のキーは set -o vi 52862 % の時には元から bind されていないという事だろうか。その様だ。 52863 % 従って、これは問題ない動作なのであった。 52864 52865 再び元に戻って $$.bind.save について調べる。 52866 52867 うーん。どうも bind -p で "\"": self-insert が有効になっている様に見えるのに実際は無効である。 52868 試しに改めて bind '"\"": self-insert' を実行しても駄目だった。 52869 また bind '"\x22": self-insert' や bind '"\042": self-insert' を実行しても駄目だった。 52870 double quotation が stty で何か特殊文字になっているという事もない。 52871 52872 bash-3.0 --norc で起動して bind -r '"' して bind '"\"": self-insert' を実行した場合はちゃんと動く。 52873 途中で bind -x '"\"": ...' して bind -r '"' しても大丈夫。 52874 52875 更に ble-detach してから ble-attach して " を入力して数秒すると SIGSEGV する。 52876 もしかしてこれは既知の問題だったりするだろうか…。 52877 52878 やはりどの様にしたら再現するかについて調べる事にする。 52879 これは純粋に bind の問題であろうという気がする。 52880 なので取り敢えず bind と unbind について調べる。 52881 52882 ble-decode-bind.30022.UTF-8.bind -> 30022.bind 52883 ble-decode-bind.30022.UTF-8.unbind -> 30022.unbind 52884 $_ble_base_run/$$.bind.save -> 30022.restore 52885 52886 これを source して見たところ再現した。 52887 source 30022.bind; source 30022.unbind; source 30022.restore 52888 更に、unbind/restore だけでも再現する。 52889 source 30022.unbind; source 30022.restore 52890 restore だけでは再現しない。 52891 source 30022.restore 52892 52893 unbind を少しずつ削ってみると怪しいものが見つかった。 52894 他に可能性として関係がありそうな物も含めると、以下の二つ。 52895 52896 builtin bind -r '"\e"' 52897 builtin bind -r '\"' 52898 52899 後者についてはエスケープがあっても問題ないのだろうか。 52900 →実際に確かめてみるとエスケープがあっても期待の通りに束縛が削除される様だ。 52901 前者についてはそもそも -r '\e' はあるのだろうか。 52902 →確認してみた所 \e? はあるが \e がない。 52903 bind.sh を確認した所、明らかなミスであった。直した。 52904 52905 ble-detach した後でも " がちゃんと入力できる様になった。 52906 また ble-detach して ble-attach した後に "" を入力しても落ちなくなった。 52907 52908 2018-09-12 52909 52910 * "bash: read: 0.0-9: 無効なタイムアウト指定です" @ Cygwin [#D0802] 52911 これは何処かにバグがある。しかし再現しない。 52912 read -t ? を呼び出しているのは ble/util/sleep しかない。 52913 ble/util/sleep を呼び出している所を探すと、実はそんなにない。 52914 52915 - ble/util/sleep 遅延初期化後の改めての sleep 52916 - vbell の消去までの時間 52917 - ble/util/idle/.sleep しかしここでは引数は算術式を使って構築しているので 52918 0-9 の様な変な値が混入する事はありえない。 52919 52920 そうすると消去法で vbell が怪しいという事になる。 52921 しかし vbell も改めて確認した所算術式経由なのでやはり変な値が紛れ込む余地はない。 52922 改めて考えると ble/util/idle/.sleep で 0 を前置している。 52923 だとすれば負の値を ble/util/idle/.sleep に渡すと 0-9 の様になっても不思議ではない。 52924 負の値を ble/util/idle/.sleep に渡した場合には sleep せずに抜けるのが良い。修正した。 52925 52926 * edit: 履歴展開が前の置換指示子に依存した動きをするということ [#D0801] 52927 https://github.com/akinomyoga/ble.sh/issues/10 52928 52929 調べてみると置換指示子さえ使わなければ問題はなさそうだ。 52930 ble.sh 内部で置換指示子を使用する時はサブシェルで実行する必要がある。 52931 しかし、現状では履歴展開は内部使用するが置換指示子は使用していないので大丈夫。 52932 一方で、Bash 3.0 で履歴展開をサブシェルの中で実行していることにより、 52933 置換指示子が記録されないという問題がある。これは実際に起こることを確認した。 52934 52935 | 該当する部分のコメントに依ると #D0233 で議論されているそうだ。 52936 | #D0233 によると history -p を実行する度に 2 つずつ履歴項目が消滅するという事になっているが、 52937 | 調べて見た限りでは履歴項目が減少しているという事はない。 52938 | 逆に history -r で読み取る事により履歴項目の数が矢鱈増えている。 52939 | 具体的にどのような状況で履歴項目が減少してどのような状況で履歴項目が登録されるのか調べる必要がある。 52940 | 52941 | 今試してみると問題なく動いている様な気がする。不思議だ。 52942 | もしかすると history -s で履歴行を追加している時のみの問題だったのかもしれない。 52943 | と思ったがやはり不思議だ。history -p する度に履歴行が減少するというのは確かに観測していた筈。 52944 | bash --norc の上で試してみる。 history -p だと何も起こらない。history -p '' だと減少する。 52945 | history -p -- '!!' でも減少する。bind -x 経由でも再現するか調べる。 52946 | 52947 | bind -x '"\C-t": history -p -- ""; history | tail -1' 52948 | 52949 | やはり減少する様だ。すると、何故 ble.sh の枠組みから呼び出した history -p で減少しないのかは不思議である。 52950 | 試してみるとやはり減少はしていない。標準入力(もしくは tty)に繋がっている時だけの問題という可能性はあるか? 52951 | 改めて bash-3.0 --norc の bind -x 内で振る舞いを調べる。 52952 | 52953 | - 関数内で呼び出しても履歴項目が減少する (bind -x '"\C-t": f001') 52954 | function f001 { history -p -- '!!'; history | tail -1; } 52955 | - 仮想端末につなげても同様に減少する (bind -x '"\C-t": f001 >>/dev/pts/16') 52956 | - ファイルに出力してもやはり減少する (bind -x '"\C-t": f001 >>B.txt'; cat B.txt) 52957 | - 標準エラー出力を捨てても減少する (bind -x '"\C-t": f001 >>B.txt 2>/dev/null'; cat B.txt) 52958 | 52959 | - NOBLE で ble.sh だけ読み込まずに mshex だけ読み込んだ状態でも減少は再現する 52960 | - set -o vi しても再現する 52961 | - HISTFILE=A.txt bash-3.0 --rcfile ../ble-dev/out/ble.sh で試してみる。 52962 | ble-detach してから実行してみる。やはり減少は再現する 52963 | - ble.sh の側で -o vi と -o emacs を観察すると両方共減少しない。 52964 | - 別に history コマンドを変な関数で上書きしているという事もない。 52965 | 52966 | - 問題の関数 ble/edit/hist_expanded/.core を bind -x から直接呼び出すと減少が再現する。 52967 | - ble-edit/hist_expanded.update を呼び出しても再現する。 52968 | bind -x '"\C-t": eval "ble-edit/hist_expanded.update aiueo"' としても再現する。 52969 | bind -x '"\C-t": ! ble-edit/hist_expanded.update aiueo' としても再現する。 52970 | - 再び attach してみたら再現する様になった。不思議だ。 52971 | 52972 | - 再度起動し直して、ble-detach して ble-attach する。再現する。 52973 | ble-detach; ble-attach だと再現しない。 52974 | ble-detach を実行してから (stty sane を実行せずに) ble-attach を時刻すると再現する。 52975 | ble-detach; history -p -- ''; ble-attach しても再現しない。 52976 | set -o vi によって切り替えを実行しても再現しない。 52977 | bash --norc で起動してその後で source ble.sh すると減少が再現する。 52978 52979 [現象] 52980 52981 - bash-3.0 では history -p -- '' を実行すると履歴項目が一つ減少した上で展開が実行される 52982 - history -p だけでは減少は起こらない。 52983 - ble.sh を rcfile として読み込んでその中で attach した場合には減少は起こらない。 52984 途中で detach & attach を一つの bind -x 呼び出しの中で完結して実行しても減少は起こらない。 52985 逆に後で attach したり、1回 detach してから別のコマンドとして attach を実行すると、 52986 history -p -- '' で履歴項目が減少するようになる。 52987 52988 [実装] 52989 52990 更によく考えてみると、もし減少する状況だったとしても、 52991 どの様に元の情報を復元したら良いのかは非自明である。 52992 というのも history -p -- '!!' は、減少してから一番最後の項目を取り出すので、 52993 減少した項目は取得できないためである。正しく実行する為には、 52994 HISTTIMEFORMAT= として history | tail -1 を実行して、 52995 その先頭から番号を取り除くという事をしなければならない。 52996 52997 更に、その時に減少するモードになっているのか減少しないモードになっているのかを判定しなければならない。 52998 実装できなくはないが大変に面倒である。検証も面倒である。と思ったが結局実装した。 52999 53000 2018-09-11 53001 53002 * syntax (report by cmplstofB): 履歴展開の置換指示子の切り取りが正確でない [#D0800] 53003 https://github.com/akinomyoga/ble.sh/issues/10 53004 53005 先ず gGa は指示子というよりは指示子に対する接頭辞として働くこと。 53006 また s?..?..? の形式に対応していないという事。 53007 これは実際に対応してみたらそれほど複雑ではなかった。 53008 指示子は元々別に読み取っていたということと、1つの関数の2箇所でしか使っていなかった。 53009 53010 * edit (report by cmplstofB): command-help の切り出しが変ということ [#D0799] 53011 https://github.com/akinomyoga/ble.sh/issues/10 53012 53013 これは確認したら extract-command の振る舞いがおかしい。 53014 実装の中で何が起こっているのか調べようとしたら、 53015 その前に unset の使い方がおかしいという事に気づいた。 53016 これは unset で現在のスコープで定義された変数も削除できると思っていた時期のコードである。 53017 修正した。現在のスコープの変数を削除する関数の名前は何が良いか悩んだが、 53018 他に良いものが思い浮かばなかったので unlocal という事にした。 53019 53020 2018-09-09 53021 53022 * complete: auto_complete keymap で C-x C-x DEL すると stackdump が発生する [#D0798] 53023 53024 カーソル位置の計算が誤っている。これは auto_complete から抜ける時の mark の更新の問題の気がする。 53025 確認したらこれは簡単だった。他にもないか確認したが、他の場所は大丈夫のようだ。 53026 動作確認する。もう起こらなくなった。大丈夫。 53027 53028 * vi: [棄却: 意図的な振る舞い] C-x ? のシーケンスに対する処理が怪しい [#D0797] 53029 53030 例えば C-x C-s を入力すると ^X が挿入されてから C-s による検索が始まる。 53031 初めは何らかの仕様に基づく動作だったかと思ったが調べてみるとよく分からない。 53032 例えば C-] は何にも束縛していないが、これを入力すると普通にエラーメッセージが出る。 53033 また C-x C-x C-x A としても ^X は一個しか挿入されない。 53034 これは内部で何が起こっているのかを詳しく調べる必要がある。 53035 53036 因みに modifyOtherKeys を使っていても同様の現象が起こるので、 53037 C-x キーの readline からの受け取りの部分では問題は起こっていないと予想される。 53038 53039 調べてみると ble/widget/vi_imap/__default__ において明示的にそのような実装になっている。 53040 そうすると疑問が二つある。 53041 53042 * 何故 C-] はそのまま挿入されないのか。 53043 他に C-^ もある。C-[ C-\ C-_ C-? に関しては既に束縛しているのでそちらが呼び出される。 53044 調べてみると C-] と C-^ では __default__ に入ってこない様だ。 53045 改めて ble-bind -d を監査室してみた所 C-] と C-^ は実は既に bell に束縛していた。 53046 従って、これらによって何も挿入されないのは自然なのであった。 53047 53048 一方で、元々の vim ではどうだろうか。^_ はそのまま挿入される。 53049 ^F もそのまま挿入される。また ^\ に関しては二文字めを待って挿入される。 53050 一方で C-^ や C-] に関しては何も反応しない。 53051 53052 ^X は実は補完に割り当てられている様だ。 53053 更に言うと2文字目に (C-x ? の組み合わせの割当がない) 何を入力しても吸収される。 53054 あと C-s は vim-surround が入っているのであった。 53055 53056 * 何故 C-x を複数入力しても一つしか挿入されないのか。 53057 →これは簡単だった。よく考えたら C-x C-x の組み合わせで exchange-point-and-mark なのだった。 53058 53059 * 2018-09-02 [棄却: これは Bash のバグ] edit: history -p '!!hello' の実行結果が異なる [#D0796] 53060 53061 | % 元々の Bash で (直前のコマンド)hello になるところが、(現在のコマンド)hello になる。 53062 | % というか試すと history -p '!!' の時点で自分自身に展開されてしまって使えない。 53063 | % これは余り気にしなくても良さそうだが、一応そういう問題があるという事を記録しておく。 53064 | % これに対応する為には、登録前のコマンドの配列に記録しておいて、 53065 | % コマンドが実行される度にその配列に記録してあったコマンドを登録し、 53066 | % 最後に未だ残っているコマンド (何らかの拍子に抜けてしまったもの) を最後まで登録する。 53067 | % という様にすれば今まで通りにちゃんと履歴に登録されることが保証される。 53068 | 53069 | しかしやはり変だ。history | tail を実行すると自分自身も既に登録されている。 53070 | これは Bash でも ble.sh でも同様である。しかし、それなのに、 53071 | history -p における !! は Bash では最後から二番目を指しているのに対して、 53072 | ble.sh では最後を指しているという事になっている。 53073 | 53074 | これは Bash のコマンドを実行している途中では 53075 | history は何か特別な状態になっているという事だろうか。 53076 | 53077 | bash --norc で色々試してみると変な挙動に出会う。うーん。 53078 | どうも history -p '!!' 等をコマンド実行に於いて呼び出すと、 53079 | 現在の項目が削除される様である。 53080 | 53081 | | $ function f1 { history | tail -1; history -p '!! @'; } 53082 | | $ f1;f1;f1;f1;f1;f1;f1;f1 53083 | | 41119 f1;f1;f1;f1;f1;f1;f1;f1 53084 | | history | tail -2 @ 53085 | | 41118 history | tail -2 53086 | | : hello world @ 53087 | | 41117 : hello world 53088 | | history | tail -1 @ 53089 | | 41116 history | tail -1 53090 | | : hello world @ 53091 | | 41115 : hello world 53092 | | history | tail -1 @ 53093 | | 41114 history | tail -1 53094 | | : hello world @ 53095 | | 41113 : hello world 53096 | | function f1 { history | tail -1; history -p '!! @'; } @ 53097 | | 41112 function f1 { history | tail -1; history -p '!! @'; } 53098 | | : hello world @ 53099 | 53100 | うーん。 53101 | 53102 | | $ function f2 { history | tail -1; history -p '!-2 @'; } 53103 | | $ for f2 in {1..10}; do f2; done 53104 | | 41114 for f2 in {1..10}; do f2; done 53105 | | bash --version @ 53106 | | 41113 function f2 { history | tail -1; history -p '!-2 @'; } 53107 | | : hello world @ 53108 | | 41112 bash --version 53109 | | echo hello @ 53110 | | 41111 : hello world 53111 | | history | tail -1; history -p '!! @' @ 53112 | | 41110 echo hello 53113 | | ble-bind -d | grep C-x @ 53114 | | 41109 history | tail -1; history -p '!! @' 53115 | | ble-bind -d | less @ 53116 | | 41108 ble-bind -d | grep C-x 53117 | | ble-bind -d | grep C-x @ 53118 | | 41107 ble-bind -d | less 53119 | | set -o vi @ 53120 | | 41106 ble-bind -d | grep C-x 53121 | | set -o emacs @ 53122 | | 41105 set -o vi 53123 | | ble-bind -d | grep M-C-m @ 53124 | 53125 | やはり履歴をどんどん削っている。 53126 | 53127 | この事から分かるのは bash-3.0 以下でのバグだと思われた 53128 | history -p によって履歴行が消えてなくなる仕様は (#D0233)、 53129 | 実は単にこの動作が (コマンド実行時だけでなく) bind -x 53130 | の関数実行時にも適用されていたという事の様だ。 53131 | 53132 | これは Bash の振る舞いが悪いという事にして深追いはしない事にする。 53133 53134 [まとめ] 53135 53136 Bash ではコマンド実行中に history -p を呼び出すと履歴項目を一つ削ってから展開を行う。 53137 さらに history -p を複数回呼び出すと呼び出した回数だけ履歴項目が減少する。 53138 53139 これは bash-4.3, 4.4, 5.0 (devel) で再現する。3.0 でも再現した。 53140 途中の version は試していないが何れでも再現するのだろう。 53141 53142 * decode: ble-bind -d が動かなくなっている [#D0795] 53143 割と最近の問題の様である。 53144 →調べてみたら割と最近の問題、という訳ではなくて failglob が原因だった。 53145 53146 * 2018-09-02 isearch: 文字を入力せずに C-r を連打して遡った後に C-h で戻った時の選択範囲 [#D0794] 53147 何故か編集文字列全体が選択されている。 53148 何か文字を入力して処理している場合には何も起こっていない。 53149 ble-edit/isearch/search の空文字列に対する振る舞いが原因かもしれない。 53150 53151 C-h で戻った時には ble-edit/isearch/prev にて、単に記録していた状態に戻っているだけである。 53152 記録されていた情報を確認してみると、記録していた時点で先頭から末尾までの範囲が設定されている。 53153 実際に配列に記録している箇所へ行く。ble-edit/isearch/.push-isearch-array である。 53154 ここで push する内容を観察すると先頭から末尾になっている。 53155 そしてその値は _ble_edit_ind と _ble_edit_mark から計算している。 53156 _ble_edit_ind と _ble_edit_mark は ble-edit/isearch/.set-region で設定されている。 53157 但し、長さが 0 の場合には何も設定されない。 53158 というか、長さが 0 の時にはそもそも beg:end は -1:-1 の様である。 53159 更に _ble_edit_mark_active は設定されない。 53160 53161 ble-edit/isearch/.push-isearch-array で push する時に、 53162 _ble_edit_mark_active を確認して、範囲が有効になっていなければ 53163 oend は obeg と同じ位置にする事にした。 53164 53165 * 2018-09-05 complete (progcomp): 一応補完開始点に単語の切れ目を入れる [#D0793] 53166 53167 % よく考えてみたら --prefix=... の場合には単語が切れてしまうと不都合である。 53168 % 元々 check-here が起こった時に変な補完になるのが問題だったのだが、 53169 % check-here が起動する時点で不備があるということなので、 53170 % そこで変な事が起こっても気にしない事にする。 53171 % 53172 % と思ったが、本当に大丈夫だろうか。例えば --prefix= の途中で補完が起こった場合には… 53173 % 実は progcomp では必ず単語の先頭で補完が始まるはずなので --prefix= の途中で補完が起こる可能性はない。 53174 % 従って、そのような場合に単語が切れて困るという事はない。 53175 53176 やはり補完開始点 (progcomp を呼び出した argument) で切るのが良さそうに思われる。 53177 53178 問題は単語の切れ目を入れる時に ble-syntax:bash/extract-command 側で実行するか、 53179 それとも complete の側で実行するのかという事である。 53180 53181 % ble-syntax:bash/extract-command の側でのデフォルトを変えるのはない。 53182 % 新しくオプションを受け付ける様にするという手もある。 53183 % しかし考えて見るに、本当にその様な事ができるだろうか。 53184 % 例えば simple-word ではない場合には中途半端な位置で切っても仕方がない。 53185 % なので complete の側で修正は行っても良いのではないかと思う。 53186 % また、complete の内部でそう何度も呼び出す処理ではないので多少遅くても問題ない。 53187 53188 と思ったが、よく考えてみたら現在の complete の実装で既に 53189 .progcomp-helper-vars 関数の中で再度コマンドラインを構築し直している。 53190 従って、ここで単語の切れ目を導入するのが自然である。 53191 わざわざ extract-command 側を修正する可能性について考察する必要はなかった。 53192 53193 ? 今実装を見て思ったのだが、本当に comp_point の実装は正しいのだろうか。 53194 元のコマンドラインの中での位置だったりはしないだろうか。 53195 と思ったが、元のコマンドラインの中での位置だった場合には、 53196 わざわざ comp_point に値を格納する必要はないから、 53197 やはり comp_line は再構築したコマンドラインであり、 53198 comp_point はその中での位置なのだろうという気がする。確認する。 53199 →確認した。大丈夫 comp_line は現在のコマンドから再構築した仮想的な文字列であり、 53200 また comp_point はその中での位置であり、単語は必ず ' ' で区切られる。 53201 →これは大丈夫。 53202 53203 * しかし実は補完開始点は comp_point とは関係ないのであった。 53204 今、comp_point に入っているのは補完開始点の位置ではなくて、 53205 現在のカーソルの位置である。 53206 53207 しかし、現在のカーソルの位置も重要な情報であるからこれの代わりに補完開始点を extract-command に渡す訳には行かない。 53208 或いは extract-command を二回呼び出すのも無駄だし、その二つの呼び出し結果の間に不整合があったらまた厄介である。 53209 考えてみれば extract-command が単語をそのまま切り出しているのだとすれば、補完開始点とカーソル位置の距離は保たれる筈である。 53210 その過程から comp_point-(COMP2-COMP1) が補完開始点と考えて良い。 53211 53212 実装してみて思ったが、COMP_LINE COMP_POINT COMP_WORDS COMP_CWORD だけの問題ではないのでは。 53213 ble 自体の補完機能を使う場合には comp_line comp_point comp_words comp_cword を参照する筈である。 53214 そう考えると comp_line comp_point comp_words comp_cword の方も修正するべきなのでは。 53215 と思ったが、まあ、COMP2-COMP1 を使って自分で補完開始点をチェックすれば良いという事なのかもしれない。 53216 然しながら、それだと毎回ちゃんと単語の先頭に補完開始点があるかどうかを調べなければならず不便である。 53217 やはり適当に単語を分割するべき様な気がする。 53218 53219 →やはり extract-command の直後で単語の分割は実施する事にする。 53220 特に、その様な変な事は基本的に起こらないはずなので、 53221 先に最初に単語の途中に補完開始点があるかどうか確認し、 53222 単語の途中に補完開始点がある時にだけ分割の処理を実行する事にした。 53223 53224 * complete: やはり予測候補の色が分かりにくいので背景色を設定する事にする [#D0792] 53225 背景色を薄灰色にしている人は恐らくそんなにいないだろう。 53226 53227 他の案として (昔の Windows のツールチップの様に) 薄黄色にしてみたが 53228 やはり何か陳腐な感じがするのでやはり敢えて無彩色で行くのが良いだろう。 53229 53230 * 2018-09-05 highlight (layer:region): 改行直後の色が違う [#D0791] 53231 53232 | ble-highlight-layer:region/getg で face2g region で決め打ちにしている。 53233 | ここは mark:MARK/getg を呼び出す様に変更する必要がある。 53234 | 53235 | うーん。実際に用意しているのは mark:MARK/get-sgr である。 53236 | sgr と g のどちらの方が primitive なのであろうか。 53237 | face → g → sgr という変換はできる。然し sgr → g はできない。 53238 | 従って、多少面倒ではあるが getg という関数を用意して、 53239 | 更に、其処から sgr に変換するという様にした方が良いのかもしれない。 53240 | 53241 | 因みに実装を確認してみた所、何れの get-sgr も face2sgr を呼び出していた。 53242 | また ble-color-face2g を呼び出してから ble-color-g2sgr を呼び出すよりも、 53243 | ble-color-face2sgr を直接呼び出した方が速い。 53244 | その様に考えると get-g と get-sgr の両方を貞経した方が高速である。 53245 | しかし、それだと実装が煩雑になる。 53246 | 或いは get-face という関数を呼び出すという手もある。 53247 | 53248 | しかし、今度は逆に動的に着色を生成する等の事が難しくなる。 53249 | 動的に着色を生成するという可能性はあるのだろうか。 53250 | 例えば、括弧を異なる色で着色する場合には動的に色を生成するのかもしれない。 53251 | 或いは複数の選択箇所を異なる色で着色する場合など。 53252 | しかし、改めて考えてみれば現在の実装では範囲は全て同一の色で着色する事を想定している。 53253 | その時に動的に色を生成する理由はない様に思われる。 53254 | 53255 | 将来的に色々な色に着色できるように拡張する可能性はあるが、 53256 | それはその時に対処すれば良い事である。 53257 | 更に言うならば、現在の実装は同一着色である事を前提とした最適化がされている気がする。 53258 | その事から、将来的にも異なる色で着色する様になる可能性は低い気がする。 53259 53260 mark:MARK/get-face という関数で実装し直す事に決定した。 53261 53262 * complete: 候補一覧にて入力済み範囲の着色がされない [#D0790] 53263 一時は動いていた筈なのに、今は効かない。 53264 少なくとも絞り込みを実行すると動かなくなる。 53265 53266 絞り込みが実行されていない時にも一瞬だけ着色されて、 53267 その後で着色が外れる。絞り込みが発生しない筈なのに 53268 何故か絞り込みが発生している気もする。 53269 53270 1 先ず、絞り込みが実行されている時に menu_common_part が空になっている。 53271 menu_common_part は menu/show 内で宣言されて、 53272 menu/initialize 内で初期化される。 53273 menu/initialize では COMPV の値をそのまま menu_common_part に設定している様だ。 53274 確認してみると menu-filter の呼び出し元では COMPV はちゃんと設定されている。 53275 menu/initialize の呼び出し直後にもちゃんと COMPV は設定されている。 53276 と思って確認してみた所、menu/initialize の中では insert 変数も参照していた。 53277 53278 この insert という変数は何のための物だったろうか。少し観察したが見当が付かない。 53279 blame で確認すると 2018-08-27 04:52:33 29d8ef54 である。これは 53280 29d8ef5 - (13 days ago) complete: highlight candidates in menu である。 53281 つまり一番初めの実装からその様になっている。 53282 これは menu-filter の実装よりも前である。更に言うと menu-complete よりも前である。 53283 今調べると menu/show を呼び出しているのは元々の complete と、menu-filter の二つだけである。 53284 insert を使う事に意味に関しては ble/widget/complete だけ観察すれば良い。 53285 恐らく complete によって挿入が起こった後の着色範囲を指定する物である。 53286 53287 complete の内部では3箇所から menu/show が呼び出されている。 53288 それぞれについてどの範囲を着色すれば良いかについて確認する。 53289 opts に enter_menu が含まれている場合には、そのまま menu-complete に突入する。 53290 この時には共通一致部分が仮にあったとしてもそれを挿入せずにメニューが開始するので 53291 本来は insert を使うべきではない。現状の実装では恐らく enter_menu になるのは 53292 共通一致部分がない場合に当たるので問題が起きていなかったという事なのだろう。 53293 show_menu が含まれている場合にはそのまま表示して終わりである。 53294 最後の所は menu_common_part を insert から再構築する必要がある。 53295 結局観察した所 menu_common_part を insert から再構築する必要があるのは一箇所だけの様だ。 53296 その部分を menu/show の呼び出し元に移動する事にした。 53297 つまり、menu/show の呼び出し元で予め menu_common_part を設定する様にする。 53298 53299 2 次に filter-incrementally で候補表示が二回行われている様に思われることについて。 53300 complete の直後では filter-incrementally はスキップされる筈なのだが何故だろう。 53301 調べてみた所、なんと候補一覧を表示した時の _ble_complete_menu_filter は make_c であった。 53302 これを実際にメニューを構築した時の入力内容を使う様に修正した。 53303 53304 しかし、そうすると今度は曖昧補完で確定が進んだ時に着色が起こらない様である。 53305 →これは単に曖昧補完であったとしても COMPV から insert 評価値に変更するだけで良かった。 53306 また改めて確認してみた所 construct-single-entry においては、 53307 曖昧補完かどうかに拘らず menu_common_part が接頭一致したら強調する様になっていたので、 53308 特にこれに対して修正する必要はなかった。 53309 53310 実はこの修正により menu/initialize という関数の意味がなくなった。 53311 (更に言うとそもそも一箇所からしか呼び出されていないのであった。) 53312 削除する事にした。 53313 53314 2018-09-08 53315 53316 * edit: コマンド exit を上書き。ジョブが残っている場合はユーザに尋ねる [#D0789] 53317 cf https://github.com/akinomyoga/ble.sh/issues/8 53318 53319 →サブシェルで exit を実行しても確認が走ってしまう。これはチェックを入れる。 53320 53321 * syntax (bug): Bash-4.1 以下で関数定義の構文解析ができない [#D0788] 53322 ble_debug で調べると途中で CTX_UNSPECIFIED になっている。 53323 nest を閉じることができなくて全体がエラーになっている。 53324 53325 | bash-4.2$ f1() { echo hello; } 53326 | _ble_syntax_attr/tree/nest/stat? 53327 | 2 aw 000 'f' | stat=(CTX_CMDX w=- n=- t=-:-) 53328 | | aw 001 '1' + word=ATTR_FUNCDEF:0-2 53329 | 12 a 002 '(' 53330 | | a 003 ')' 53331 | 26 a 004 ' ' stat=(CTX_CMDXC w=- n=- t=$2:-) 53332 | 18 a 005 '{' ++ word=CTX_CMDI:@1>5-6>@5 word="none":5-6 nest=(CTX_CMDI w=CTX_CMDXC:5- n=- t=-:$2) stat=(CTX_CMDXC w=- n=- t=$2:-) 53333 | 17*a 006 ' ' stat=(CTX_CMDX1 w=- n=- t=$6:-) 53334 | 2*aw 007 'e' | stat=(CTX_CMDX1 w=- n=- t=$6:-) 53335 | |*aw 008 'c' | 53336 | |*aw 009 'h' | 53337 | |*aw 010 'o' + word=CTX_CMDI:@5>7-11 53338 | 3*a 011 ' ' 53339 | 4*a 012 'h' | stat=(CTX_ARGX w=- n=- t=$11:-) 53340 | |*a 013 'e' | 53341 | |*a 014 'l' | 53342 | |*a 015 'l' | 53343 | |*a 016 'o' + word=CTX_ARGI:@10>12-17 53344 | 12*a 017 ';' stat=(CTX_ARGX w=- n=- t=$17:-) 53345 | 1*a 018 ' ' stat=(CTX_CMDX w=- n=- t=$17:-) 53346 | 19*a 019 '}' + word=CTX_CMDI:@16>19-20 stat=(CTX_CMDX w=- n=- t=$17:-) 53347 | | s 020 ^@ stat=(CTX_CMDXE w=- n=- t=$20:-) 53348 | 53349 | 53350 | bash-4.1$ f1() { echo hello; } 53351 | _ble_syntax_attr/tree/nest/stat? 53352 | 2 aw 000 'f' | stat=(CTX_CMDX w=- n=- t=-:-) 53353 | | aw 001 '1' + word=ATTR_FUNCDEF:0-2 53354 | 12 a 002 '(' 53355 | | a 003 ')' 53356 | 26 a 004 ' ' stat=(CTX_CMDXC w=- n=- t=$2:-) 53357 | 6 a 005 '{' + word="none":5-6 nest=(CTX_UNSPECIFIED w=CTX_CMDXC:5- n=- t=-:$2) stat=(CTX_CMDXC w=- n=- t=$2:-) 53358 | |*a 006 ' ' stat=(CTX_UNSPECIFIED w=CTX_CMDXC:5- n=- t=$6:$2) 53359 | |*a 007 'e' 53360 | |*a 008 'c' 53361 | |*a 009 'h' 53362 | |*a 010 'o' 53363 | |*a 011 ' ' 53364 | |*a 012 'h' 53365 | |*a 013 'e' 53366 | |*a 014 'l' 53367 | |*a 015 'l' 53368 | |*a 016 'o' 53369 | |*a 017 ';' 53370 | |*a 018 ' ' 53371 | |*a 019 '}' 53372 | | s 020 ^@ stat=(CTX_UNSPECIFIED w=CTX_CMDXC:5- n=- t=$6:$2) 53373 53374 core-syntax.sh を 40100 または 40200 で探してみても関係ありそうな分岐をしている箇所はない。 53375 一つずつ見ていく事にする。直前の文脈は CTX_CMDXC である。これの処理は 53376 ble-syntax:bash/ctx-command で行っている。.check-word-begin までは問題ないようだ。 53377 取り敢えず現在の ctx である CTX_CMDXC を wtype に設定して単語が始まる。 53378 次の check-variable-assingment は CTX_CMDXC ではスキップされる筈である。 53379 ${_ble_syntax_bash_chars[CTX_ARGI]} の内容にも違いは見られない。 53380 うーん。どうやらブレース展開に入りかけてすぐ出るというのが正しい動作だが、 53381 53382 そのブレース展開に入る nest で失敗している様子である。 53383 ブレース展開に入る所を調べる。nest の前後を見ると、何と push 直前の ctx が 0 になっている。 53384 ctx を最後に書き換えているのは同じく check-brace-expansion の中の真ん中あたりにある。 53385 _ble_syntax_bash_command_IsAssign という配列を参照している箇所である。 53386 _ble_syntax_bash_command_IsAssign の中身を確認してみたが何も変化はない。 53387 ctx は 2 → 0 に変化してしまっているがそもそも _ble_syntax_bash_command_IsAssign には 2 は登録されていない。 53388 53389 これは bash 算術式のバグだろうか。 53390 何とこれは既知のバグであった。このバグの存在を忘れていた。 53391 最近書いたコードにもこういう物が含まれている可能性はある。 53392 他にも似たような物がないか core-syntax.sh の内部は調べた。一箇所直した。 53393 vi.sh と ble-edit.sh の中も調べたが特に怪しいものはない。 53394 ble-canvas.sh と ble-color.sh の中も調べた。ble-decode.sh の中も調べた。 53395 53396 2018-09-07 53397 53398 * 2015-12-12 IGNOREEOF に対応 (現在 bash-4.0 未満では勝手な値を設定しているので [#D0787] 53399 cf https://github.com/akinomyoga/ble.sh/issues/8 53400 これはコマンド実行の瞬間だけに復元する様にする必要がある。 53401 PS1 と同様の取り扱いで良いと思われる。) 53402 53403 * edit (request from cmplstofB): ジョブがある時の終了コマンド (C-d) [#D0786] 53404 cf https://github.com/akinomyoga/ble.sh/issues/8 53405 bleopt allow_exit_with_jobs=1 として対応した。 53406 53407 * complete: CentOS 7 で LC_ALL=C.UTF-8 に対してエラーが出る [#D0785] 53408 53409 * complete: 起動時に暫くとまる [#D0784] 53410 53411 調べると auto-complete.idle が止めている。 53412 更に入っていくと ble-edit/isearch/backward-search-history-blockwise が止めている。 53413 ちゃんと stop_check は設定されているのでユーザから入力されれば止まるはずだ。 53414 と思ったら、それ以前の段階で履歴がロードされるのを待っていたのだった…。 53415 53416 履歴がロードされるまでは history heavy は呼び出さない様にする事にした。 53417 53418 * complete (reported by cmplstofB): failglob の時、コマンドの補完候補に * が含まれてしまう [#D0783] 53419 https://github.com/akinomyoga/ble.sh/issues/7 53420 53421 * ble/util/assign 入れ子対策? [#D0782] 53422 53423 2018-09-07 53424 53425 * complete (reported by cmplstofB): workaround: プログラム補完関数が failglob を踏むとシェルが終了する [#D0781] 53426 https://github.com/akinomyoga/ble.sh/issues/6 修正した。 53427 53428 2018-09-05 53429 53430 * auto-complete: 実は元から灰色の文字がデフォルトのターミナルが存在する [#D0780] 53431 53432 * color (reported by cmplstofB): ble-color-setface がエラーを起こす [#D0779] 53433 https://github.com/akinomyoga/ble.sh/issues/6 53434 53435 調べた所 ble-color-defface / ble-color-setface の順序が効いている。 53436 恐らく defface 自体を遅延させている為に、順序が入れ替わって、 53437 結局 ble-color-defface / ble-color-setface の評価順を逆転した意味がなくなっていた。 53438 53439 確認の為に、defface 及び setface を出力してみることにする。 53440 やはり順序が反転している。_ble_color_complete_{defface,setface}_hook の2種類を作る事にした。 53441 これで大丈夫のはず。 53442 53443 * mwg_pp.awk: PHONY targets for dependencies [#D0778] 53444 調べたら既にその機能はついていた。単に Makefile に書き忘れていただけである。 53445 53446 * complete (progcomp): 実は simple-word/eval は eval "set_return $1" で行けるのでは [#D0777] 53447 しかし本当に複数単語に展開してしまうと大量の単語が現れた時に処理が遅くなる。 53448 やはり現状の様に最初の単語だけ取得するというので良い気がする。 53449 何れにしても、現状の実装でも結局配列に全要素を入れているので大差はないかもしれないが。 53450 53451 現在の実装が =~... になっているのには理由があったのだろうか。 53452 ログを漁ってみたが特に記録はされていない。 53453 53454 * complete: bug: 自動補完が起動しなくなっている [#D0776] 53455 これは宣言していない変数 ext を参照しているのが問題であった。 53456 53457 * complete: bug: 曖昧補完で補完を実行しようとすると入力した物が削除されて空になる [#D0775] 53458 →これは determine-common-prefix で local ret を宣言していたのがいけなかった。直した。 53459 53460 * complete: ブレース展開の中での補完 [#D0774] 53461 53462 * done: 先ず初めにブレース展開を解析するコードが必要である。 53463 53464 | 更にブレース展開以前を書き換えるといけないので、 53465 | "書き換えてはならない範囲" というのを complete 側に実装する必要もある。 53466 | 自動補完でもそれを考慮に入れなければならない。 53467 | 直前のパラメータ展開はブレース展開より後にあると保証できるので大丈夫。 53468 | 53469 | 後、ブレース展開の中では nest に入っているので、 53470 | 元の単語を抽出するにはブレース展開を抜ける必要がある。 53471 | 然し、どうせ nest に入っている構造を遡るのだから、 53472 | 53473 | その際に一緒にブレース展開の最初の候補を抽出してはどうか 53474 | …と考えたが問題が幾つかある。 53475 | 先ず初めに現在の枠組みでは初めに補完文脈を生成してから 53476 | それを補完器に渡している。補完文脈には開始点と種類の情報しかない。 53477 | オプションとして何か指定できるように拡張するとしても面倒である。 53478 | 更に、将来的にはユーザによる補完の起動なども実装したい。 53479 | やはりその際には開始点と種類だけから起動できる様になっているのが望ましい。 53480 | その様に考えると、やはり別々にブレース展開を解析する方が良いと判断する。 53481 | 53482 | * ブレース展開の解析は simple-word と似た様な形で、 53483 | しかし、{,} を特別に処理してやれば良い。 53484 | rex_letter を {,} とそれ以外に分割して、 53485 | extract-parameter-expansion と同様に処理すれば良い。 53486 | 実装したが動作テストはしていない。 53487 | 53488 | * ブレース展開に符号を入れられるという事が分かったので対応した。 53489 53490 ブレース展開と引用符を閉じる関数を作った。 53491 更に、ブレース展開を実行した時の最後の単語を取得し、 53492 ブレース展開の構造を壊さないで変更できる word の最初の位置として simple_ibrace を返す様にした。 53493 閉じた引用符の種類は今までの close_type の代わりに simple_flags という変数を用いて返す。 53494 53495 * done: 次に、simple_ibrace を用いて、変更してはならない範囲を保持したまま置換が行われる様に変更する。 53496 その為には reconstruct-incomplete-word (旧 close-open-word) を呼び出している箇所で一つずつ問題がないか確認する。 53497 53498 1 ble-complete/source:argument/.progcomp-helper-vars 53499 これはプログラム補完から見える単語を復元する為に使用する。 53500 一番最後の単語だけここで取得される事になるが、まあ、今までと大差ないだろう。 53501 (今まではブレース展開が処理されないままにプログラム補完に渡されていたと思う) 53502 53503 もし気になるようであればプログラム補完に渡す時には複数単語にちゃんと展開するという可能性もある。 53504 53505 …今気づいたのだが、実は eval は eval "myfunc $1" で行けるのではないか…。→ #D0777 53506 もしそうだとすれば simple_flags を見ればブレース展開による全ての単語を取得する事もできる。 53507 53508 % と思ったが、うーん。単に eval を実行するとパス名展開まで実行されてしまう。noglob で評価するべきか。 53509 % 改めて考えてみると実は現段階で既にパス名展開は実行している (最初の単語を選択している)。 53510 % そう考えるとやはりパス名展開まで実行しても誤りではないのではないか。 53511 % 53512 % 所で、よく考えてみると文脈によって展開のされ方は違う筈である。 53513 % 例えば変数代入の場合にはパス名展開は実施されない。ブレース展開も実施されない。 53514 % と思ったが、特にこの関数で呼び出しているのは引数の場合だけだから、 53515 % やはりパス名展開は実行されてよいのである。 53516 53517 パス名展開は寧ろされている方が自然である。 53518 53519 2 ble-complete/candidates/.pick-nearest-context 53520 次は候補の生成部分である。ここでは取り敢えず simple_ibrace を comps_ibrace としてそのまま返す。 53521 呼び出し元は ble-complete/candidates/generate である。 53522 53523 % 未だ此処では個々の候補は生成していないので comps_ibrace によるフィルタリングはできない。 53524 % と思ったが、よく見たらフィルタリングをしているのはこの箇所だった。 53525 53526 しかし実は comps_rex_ambiguous はこの時点で設定できる… 53527 53528 うーん。フィルタリングをしようと思ったが、実は ibrace だけだと不都合である。 53529 というのも ${word::ibrace} の評価結果を使わないと評価結果によるフィルタリングはできないが、 53530 ${word::ibrace} の評価結果を得る為には結局またブレース展開を閉じるなどの処置が必要になる。 53531 同じ処理を繰り返し実行する事になってしまって効率が悪いので、ibrace の他にも情報を返したい。 53532 実は、単に ibrace と一緒に reconstruct-incomplete-word の戻り値の中での index も返せば良いのでは。 53533 53534 ? reject: 曖昧一致は ibrace>0 で禁止するという手もあるのだろうか。 53535 しかし、うーん。やはりブレース展開よりも後の場所で曖昧一致させられる方が自然である。 53536 53537 3 ble-complete/candidates/determine-common-prefix 53538 ここは common part が曖昧一致するかどうかっを調べている。 53539 comps_ibrace が設定されている場合には、 53540 既にここに入る時点で候補は全て comps_fixed_part を保存する様になっている筈なので、 53541 曖昧一致だけ確かめれば、ちゃんと comps_fixed_part は保持したままになっている筈である。 53542 ここは気にしなくても良い。 53543 53544 4 ble-complete/menu/initialize 53545 うーん。これは何だろう。 53546 これは ble-complete/menu/show の頭で呼び出されている関数である。 53547 他の場所からは呼び出されていない。menu_common_part を初期化するのに使っている。 53548 これはまあ、問題ないだろう。単に太字にするだけなのである。 53549 53550 ambiguous の場合にはまた曖昧一致部分がちゃんと fixed_part になる様に調整が必要であるが、 53551 現状では ambiguous の場合に入力部分を太字にするのには未対応である。 53552 ambiguous で対応する場合に注意する様にすれば良い。 53553 53554 5 ble-complete/menu/filter-incrementally 53555 うーん。まあ、これは絞り込みをかけているだけだから問題ない気がする、 53556 と思ったが {aaa,bb の状態で補完候補を出して、その後で {aaa,bbb,b と入力した時に、 53557 そのまま候補一覧を表示したままにしておくとメニュー補完において {aaa,bbb, 53558 の部分を置き換えて bbb, が失われてしまう。従って、 53559 ibrace が元々の ibrace から移動した場合には候補一覧をキャンセルするなどの対処が必要である。 53560 53561 これは実は get-active-range の中で判定するべきことなのかもしれない。 53562 53563 6 ble/widget/auto_complete/self-insert 53564 self-insert で {,} の何れかの文字を挿入する時、 53565 特に曖昧一致や前方に置換がある時については、 53566 ブレース展開の状況が変わるかもしれないので、auto_complete をクリアする。 53567 一方で、_ble_complete_ac_type が [ch] の時は、 53568 {,} が入力されてもブレース展開の状況は変わらないか、 53569 或いはそれも見越して一致する場合にしか auto_comoplete 内での self-insert は怒らないので、 53570 現状のままの実装で問題ない。 53571 53572 * done: menu-complete の時にブレース展開の構造の部分まで反転して置換対象であるかの様に表示されるのは妙である。 53573 従って、_ble_edit_mark を移動したいところだが、他の場所に影響は出ないだろうか。 53574 特に _ble_edit_mark を参照して処理をしていたりしないだろうか。 53575 53576 ble-complete/menu-complete/select と menu_complete/accept で参照している。 53577 menu-complete に於いて _ble_edit_mark を設定しているのは menu/enter のみである。 53578 ここでは _ble_complete_menu_beg の値がそのまま beg に入り、それから _ble_edit_mark に入っている。 53579 従って、上記で _ble_edit_mark を参照している所は実は _ble_complete_menu_beg に置き換えれば良い。 53580 53581 * done: 実際に動かしてみるとどうも変な振る舞いをする。 53582 例えば echo {a,m} に対して m が挿入される。 53583 と思ったら、実は completion-context で変な物が生成されている気がする。 53584 53585 調べてみると check-here による補完文脈が生成されていて、 53586 しかしその後の progcomp での単語切り出して m が既に入力されている者とされ、 53587 結果として m が候補として生成される。ところが check-here なので m が重複して挿入される。 53588 53589 実は progcomp 側でも check-here などで生成された場合に対する対策として、 53590 補完開始点で無理矢理単語を分割するべきなのではないか、とも思う。→ #D0793 53591 53592 * done: {,} もエスケープするべきなのではないか。今確認した所、{} はエスケープしている。 53593 , はエスケープしていない。ブレース展開がある場合には , もエスケープする。 53594 それ以外の場合には特に , はエスケープしない、という方針で良い気がする。 53595 53596 2018-09-03 53597 53598 * 2017-11-26 complete: 変数代入の時は右辺でファイル名補完をするが、 [#D0773] 53599 実は arr[$(...)]= の様な複雑な場合に右辺を正しく切り出せていない。 53600 53601 2018-08-26 この時直前の stat に記録される文脈は、 53602 arr[...@]= の位置にある CTX_EXPR である。 53603 これは CTX_EXPR 側で対処するべき事の気がする。 53604 例えば tail == ']=' かつ、nest type が a[ の時に、 53605 変数の右辺の補完を開始する。 53606 53607 実際に実装してみたが微妙である。 53608 arr[@] (@: stat の位置) に対しては = を挿入させる事はできる。 53609 arr[@]= に対してはファイル名補完を開始させる事はできる。 53610 arr[1]=@hello に対しては正しくファイル名補完を起動する事ができない。 53611 この時 @ に設置されるのは VRHS であるが、一番最初の VRHS を検出する手段がないからである。 53612 更に、arr[1]+ に於いて arr[1]+= としたいが、 53613 実際には、arr[1]@+ で @ に stat が設置され文脈は CTX_VRHS となっている。 53614 53615 要するに、問題は CTX_VRHS において右辺の開始位置を検出する事ができないという事である。 53616 ところで、CTX_ARGI などの場合には word の始まりが単語の始まりという事で判定できた。 53617 CTX_VRHS は単語の始まりは変数名の始まりという事が難しい。 53618 arr[]=... の形式の場合には [] の部分を読み飛ばして開始点を決定する事ができれば良い。 53619 53620 * done: うーん。解析の構造を見ると、先ず初めに単語の先頭以降にある最初の nest (1) を探す。 53621 更に、それ以降の stat を調べて最初に nlen が (1) より前 (もしくは -1) を指す様になった所が、 53622 最初の CTX_VRHS である。もしくは、最後の nlen が (1) 以降を指す stat が閉じる ] の直前になる。 53623 53624 * done: a[1]+ の状態ではどうなっているか。うーん。+ の直前に VRHS が設置される。 53625 やはり最後の "nlen が (1) 以降を指す stat" から "]" の後に何があるかで判定する方が良い。 53626 53627 * done: a=([1]=a の場合には CTX_VRHS の代わりに CTX_VALR である。 53628 これについては rex='^(\[)'; [[ $word =~ $rex ]] の時だけ 53629 53630 * 2017-03-01 complete: "function fun [" で補完を実行すると '[[' ではなくて '[\[' になってしまう [#D0772] 53631 これを解決するためには complete.sh の source の wordlist で、 53632 エスケープをオフにするオプションを用意する必要がある。 53633 53634 ble-complete/action/plain/initialize で行われている escape-specialchars が原因だ。 53635 action として word を使用している為にそのままその機能を継承している様だ。 53636 新しい専用の action を定義するか或いは wordlist にオプションを指定できる様にするかすると良い。 53637 53638 * complete: bug, 一意確定した直後に更に新しい補完を始めようとすると menu-complete が始まる [#D0771] 53639 53640 2018-09-02 53641 53642 * 2018-07-28 complete 再考 [#D0770] 53643 53644 元々の問題提起は以下から。 53645 53646 | * 2016-07-15 complete: そもそも現在の実装は妥当なのだろうか。 53647 | 全ての候補に一つずつ候補の文字列・挿入文字列・説明 etc を計算して登録しているが、 53648 | これらは最低限の情報に留めておき表示する必要が生じた時に改めて計算すればよいだけなのではないか。 53649 | つまり、source 番号と一緒に登録しておけば全部計算できるような気がする。 53650 | 53651 | 一つ気になるのが INSERT を事前に計算しておく必要があるのかどうかと言う事である。 53652 | 現状の実装では共通一致部分を算出するのに INSERT を使用している。 53653 | - source の種類によって一致対象の文字列が同じでもエスケープの仕方が異なる事が考えられ、 53654 | その場合にはエスケープも含めて共通一致部分までしか確定できないはずだからである。 53655 | 例えば変数名 $variable 及びファイル名 variable の両方に一致して $var まで入力しかけた時、 53656 | 一致候補の文字列が同じ variable であっても前者による補完は $variable だし、 53657 | 後者による補完は $var\variable になる筈である。 53658 | しかし、この措置によって処理が複雑化している気がする。 53659 | その様な状況が本当に発生するのかどうかも含めて再度考え直しても良いのではないか。 53660 | 例えば上記の例で言えば、実際には $variable の補完の方が優先される。 53661 | その点から始まる補完 (ファイル名 variable) は他に候補がない場合に限られるからである。 53662 53663 完全に再実装するのは二度手間なので、現状の実装を改善する方向で行く。 53664 途中で必要があれば需要に応じて構造を変更する事にする。 53665 →結局 complete の構造は元々の構造を保持したまま発展させたので 53666 大きく再設計するという事はなかった。この項目はそのままログに送る。 53667 53668 * その為には現在の実装がどの様な構造になっているかについて調べる必要がある。 53669 53670 1. source 一覧生成 53671 先ず初めに ble-syntax/completion-context を呼び出して 53672 補完開始点と使用する補完生成器の一覧を生成する。 53673 53674 2. 候補生成 53675 次に各 source に対して候補を生成する。 53676 各 source は ble-complete/source/NAME 関数として実装され、 53677 COMP1 COMP2 COMPS COMPV を受け取る。 53678 生成する候補は生成時点で既に escape などの処理を終わらせる。 53679 53680 3. 候補の絞り込みを行う 53681 結局現在の実装では一番近い開始点からのものしか用いていない。 53682 また、その様にしないと候補表示が分かりにくいというのもある。 53683 ここは、一番近い開始点からの補完しか行わないと仮定して良いのではないか。 53684 その様にすれば処理も幾分楽になる。 53685 53686 もし後々になって複数開始点からの補完をしたくなったら、 53687 その時になってから考える事にすれば良い。 53688 53689 4. 確定の場合には続きを入力する為に、 53690 補完文字列に対応して、末尾に / または ' ' を追記する。 53691 53692 5. 置換を実施する。 53693 53694 * ok: 候補の表現は適切か。 53695 53696 | 現在の所、生成した候補は以下の配列に格納される。 53697 | 複数の配列に格納するのは候補数が沢山ある場合に効率が悪くなるので統合したい。 53698 | 53699 | cand_cand[icand]="$CAND" # 候補名文字列 (直接) 53700 | cand_prop[icand]="$ACTION $COMP1 $COMP2" # 置換操作と範囲 53701 | cand_word[icand]="$INSERT" # 挿入文字列 (escaped) 53702 | cand_show[icand]="$SHOW" # 表示文字列 53703 | cand_data[icand]="$DATA" # 現在使用されていない 53704 | 53705 | - 先ず初めに COMP1-COMP2 は共通である。 53706 | もしくは source 毎に確定である。 53707 | なので、これは source 名などに置き換える事ができる筈である。 53708 | - DATA に関しては現在は使われていない様である。 53709 | - INSERT は共通部分の一致を試す為に結局使用するので、 53710 | 候補生成時点で出力して良い。 53711 | また、source しか知りえない方法で escape したいという事もあるかもしれない。 53712 | と思ったが、fignore などを考えるとやはり後で escape を実施しても良いのかもしれない。 53713 | 53714 | - SHOW は結局現状の実装では CAND に等価である。 53715 | 将来的に syntax highlight 等も非同期で行う様になると SHOW は使用する事になるかもしれない。 53716 | 何れにしてもこれは遅延で計算すれば良い事の様に思われる。source は遅延に対応する。 53717 | 特に source が返還を貞経しなければ CAND をそのまま表示すれば良い。 53718 | - または表示時の文字列に限らず、例えば候補の説明を表示するという事も考えられるが、 53719 | それらについても遅延で計算すれば良い。 53720 | 53721 | 或いは別の案として以下の様な記録方法を取るという事も考えられるが…。 53722 | 53723 | cand_cand[i]="$ACTION:${#CAND}:${#INSERT}:${#SHOW} $CAND$INSERT$SHOW$DATA" 53724 | 53725 | やはり処理が複雑になる為にそんなに速くなさそうである。 53726 | これは具体的に実測する等して比較するしかない。 53727 53728 紆余曲折を経て現在では cand_cand, cand_word, cand_pack の三つの配列で取り扱っている。 53729 速度的には問題があるかもしれないが現在のところはこれが現実的である様に思われる。 53730 53731 * ok: escape の処理を何処で行うか [→現状の儘で良い] 53732 53733 これは枠組みとして考えれば候補生成とは別に行うという事も考えられる。 53734 しかし、落ち着いて考えれば文法要素も含めて補完を実施したい時もあるだろうから、 53735 外側で一律に escape をするという仕組みになっていると都合が悪い。 53736 候補生成側で直接 escape した物を生成することにして、 53737 適宜こちらで用意した escape 関数を呼び出してもらうか、 53738 或いは、候補生成時に escape の種類についての値も出力とするという手がある。 53739 これは現状通りにこちらで用意した escape 関数を呼び出してもらう事にするのが良さそうだ。 53740 53741 特殊な escape をしたい場合などには各 source で個別に適切な関数を呼び出す様にする。 53742 53743 以下については既に対応されていた。 53744 53745 | * 2017-03-01 complete: 既に入力された部分を修正する様な形での補完があっても良いのではないだろうか。 53746 53747 * auto-complete: 入力している時に時々固まる。history auto-complete が怪しい [#D0769] 53748 本当に history auto-complete が原因なのかは未だ確認していない。 53749 後で調べる事にする。 53750 →これは単に ble-edit/isearch/.read-search-options のミスだった。 53751 結果を返す為の変数を local にしていた所為で stop_check 等が無効になっていた。 53752 53753 * 2018-08-29 complete: "$hello" などでも補完できる様にする [#D0768] 53754 53755 これは simple-word の拡張が必要になる。 53756 また simple-word を使用している各箇所の動作についても確認する必要がある。 53757 53758 - simple-word の拡張自体はそんなに難しくなさそうだ。 53759 然し、これを使っている場所で不都合が起こっては困る。 53760 使っている箇所について調べる事にする。 53761 53762 | - ble-edit.sh command-help でコマンド名を抽出するのに使っている。 53763 | 直後に command=$literal を用いて展開を実行しているから、 53764 | これは "$hello" の様な物があったとしても問題ない。 53765 | 一方で、直接 command=$literal の様な事をしても問題ないのだろうか…。 53766 | 53767 | 調べてみるとコマンド名であってもパス名展開は有効だし、 53768 | また、パラメータ展開の変数名とローカル変数の変数名が被る可能性もある。 53769 | 従って、eval を用いて評価したほうが良い。 53770 | 53771 | - core-syntax.sh: ble-syntax/completion-context/.check-prefix/ctx:next-command 53772 | ここで is-simple を使っている。これはコマンド名として補完の対象となりうるかを判定する為に使っている。 53773 | 所で、ここは is-simple で良いのか…確認してみると next-argument の方では 53774 | is-simple-or-open-simple を使っている。ここは修正する事にした。 53775 | - core-syntax.sh: ble-syntax/completion-context/.check-prefix/ctx:redirection 53776 | - core-syntax.sh: ble-syntax/completion-context/.check-prefix/ctx:rhs 53777 | ここでも is-simple を使っていたが、is-simple-or-open-simple に書き換えた。 53778 | - core-syntax.sh: ble-syntax/completion-context/.check-prefix/ctx:next-argument 53779 | - core-syntax.sh: ble-syntax/completion-context/.check-prefix/ctx:quote/.check-container-word 53780 | これらは is-simple-or-open-simple を使っているが "$hello" に対応しても問題はないだろう。 53781 | 53782 | - core-syntax.sh: ble-highlight-layer:syntax/word/.update-attributes/.proc 53783 | これは is-simple のままで問題ない。着色なので閉じていない単語については処理しなくて良いので。 53784 | また、"$hello" に対応しても大丈夫。 53785 | 53786 | - core-complete.sh: これは "$hello" に対応しても問題ない。 53787 | 特に全て close-open-type & eval を介しての使用である。 53788 53789 特に使用箇所での使用方法に対して不都合が起こるという事はなさそうである。 53790 53791 - done: simple-word/eval で変数名を抽出する時にちゃんと "$hello" も抽出する必要がある。 53792 特に ble-syntax:bash/simple-word/extract-parameter-names である。 53793 →対応した。動作確認した。is-simple も確認した。 53794 53795 - パラメータ展開で終わっている時には挿入時に ${param} または $param\ 53796 の様に書き換える必要がある。つまり、引用符の中でもこれを実行するという事。 53797 一方で ' や $' の中に現れるパラメーて展開と同様の文字列は、 53798 実際にはパラメータ展開ではないので書き換える必要はない。 53799 53800 x hello=mem; echo "$hello@ に対して o が挿入される筈なのに動かない。 53801 menu 補完に入れば期待通りに動くが、通常の補完で "${hello}o までは入力できる筈である。 53802 調べてみると cand_word までは "${hello}o になっているが、 53803 53804 % determine-common-prefix で何故か "$hello になっている。 53805 % 実装を調べると、これは ambiguous の時に起こる様である。 53806 % と思って調べたが特に ambiguous に誤ってなっているという事もない。 53807 53808 改めて確認してみると ambiguous でない場合でも、 53809 遡って書き換わる時でかつ一意確定でない時には書き換えが起こらない様だ。 53810 元々この様にしていた理由は、遡って書き換わる事によって変な書換になって、 53811 続きの補完ができなくなってしまう事を懸念しての事だった。 53812 そうであるならば、共通部分が変な書き換え (non simple-word) になっていなければ大丈夫という事である。 53813 新しく simple-word かどうか判定して、simple-word の時は書き換えを実行する事にした。 53814 53815 * complete: auto_complete keymap における M-f C-f 等の対応 [#D0767] 53816 53817 * auto-complete: 履歴からの検索 [#D0766] 53818 53819 [実装方法] 53820 53821 | a 試してみると下手に tac 等を使うよりは以下の様に awk を使うのが速い。 53822 | time HISTTIMEFORMAT= history | awk '/aaa/ {a=$1} END{print a;}' 53823 | しかしそれでも 0.226s 程度かかっていて遅い。 53824 | 更に incremental に遡っていく度に同じ位時間がかかるという事である。 53825 | 53826 | また、これだと文字を入力する度に他のプロセスを起動する事になるので避けたい。 53827 | 53828 | b これは bash 自身を使って遡るのとどちらが良いであろうか。 53829 | bash 自身を使う場合は検索の途中状態を表示する事も可能である。 53830 | しかし自動補完によって background で実行している物の経過を表示するのは正直うるさい。 53831 | 53832 | 問題は bash 自身を使って遡る時に結局一致が見つからない場合である。 53833 | その場合にはさっさと局所的な補完が起動して欲しいが、 53834 | bash 自身を使って遡るとすると大分待ってからでないと通常の補完に入らない。 53835 | 53836 | c 実は履歴展開を使って何とかならないだろうか。 53837 | と思ったが、スペースなどが入った時にちゃんと検索してくれるのだろうか。 53838 | 53839 | 試しに history -p で試してみると ' ' が含まれていると、 53840 | その直前までしか展開してくれない。 53841 | スペースをクォートしたとしても '\' の1文字が検索対象として追加されるだけである。 53842 | COMP_WORDBREAKS 的な設定も見つからない。 53843 | 試しに COMP_WORDBREAKS= history -p として見たがやはり影響は受けない。 53844 | 53845 | d 或いは bash 自身を使って遡るが遡る件数を制限する。 53846 | 既定で 1000 件にして、ユーザの設定で変更できる様にする。 53847 | 因みに bash の既定は 500 である。随分と小さい。 53848 | 検索すると CentOS は独自に上書きしていて 1000 だそうだ。 53849 | 他に 2000 にしている人と 10000 にしている人がいる。 53850 | 53851 | e 実は先に通常の補完候補で一旦自動補完してから、 53852 | 裏でゆっくり検索して見つかった時にすり変えれば良いのではないか。 53853 | 更に一つの単語で構成されている時には history -p '!string' を用いれば良い。 53854 | 複数の単語で構成されている時にも初めに最初の単語を使って 53855 | history -p '!string' として存在が確認できる時にのみ実行すれば良い。 53856 53857 e の方法で実装する事にする。 53858 53859 [実装1: history -p による検索] 53860 53861 具体的な実装に入る。 53862 履歴展開の !string の形式で string の終わりになる文字は何だろうか。 53863 調べてみると <>;&|$IFS() の様である。これは COMP_WORDBREAKS の既定値から "'= を覗いた物である。 53864 また ! の直後に来るとイベント支持子として解釈されて駄目な文字列というのも存在する様だ。 53865 53866 先ず '!' 単体だと自分自身に展開されてしまう。 53867 少なくとも一文字はないと行けない。 53868 しかし、これは逆に !string の string が空の場合の振る舞いとして自然な気がする。 53869 また、コマンドの最初の文字が 0-9 の場合にも駄目。! # ? の場合も駄目。 53870 更に試してみると最初の文字が - の場合にも駄目である。 53871 53872 実は !?...? の形式の場合には途中に ? が含まれていなければそれ以外の文字も含む形で検索する事ができる様だ。 53873 取り敢えず、history -p を使った高速な実装は終わった。動いている。 53874 53875 しかし、やはり一致したりしなかったりするので微妙である。 53876 53877 [実装2: 配列の探索] 53878 53879 ちゃんとした検索を実装するには history-edit/isearch/search を拡張する必要がある。 53880 或いは正規表現を構築して ^ を付加して既存の regex で検索するという手もある。 53881 しかし、やはり速度を考えると glob で一致させる方が速いだろう。 53882 53883 * しかし改めて考えてみると途中でファイル名に補完されたのに、 53884 その後で暫くしてよく分からない別の場所で実行されたかもしれないコマンドに置き換わるのも妙である。 53885 53886 * C-r による検索で色々試すと、実はそんなに検索に時間はかからない様である。 53887 53888 何れにしても取り敢えず実装してみる事にする。 53889 途中で中断したとしても検索状態を記録しておいてまた後で続きから検索できる様にすると良いだろう。 53890 53891 実際に試してみると十分速い様に思われるので既定で先に history を見てから通常の自動補完を行う事にした。 53892 53893 2018-09-01 53894 53895 * menu-complete: やはり重い気がする。表示までに時間がかかる [#D0765] 53896 後でどの部分が遅いか確認する。 53897 53898 やはり ble/function#try ble-complete/menu/style:"$menu_style"/construct 53899 に 0.660 程度かかっている。 53900 53901 x resolved: しかも計測してみて分かったが何故か無駄に2回も呼び出されている。 53902 自動補完では呼び出されていない。スタックを出力させてみた所、 53903 一回目は ble/widget/complete でありこれは想定していた物であるが、 53904 二回目は filter-incrementally だった。これは想定していない。 53905 一文字も入力していなければ最初に呼び出した時と結果は変わらないはずで、 53906 再度わざわざ実行する必要はないはずだ。 53907 filter-incrementally は以下のコマンドによって重複した計算を省略しているはずだが、 53908 53909 [[ $input == "$_ble_complete_menu_filter" ]] && return 0 53910 53911 どうやらこれが正しく動作していない。_ble_complete_menu_filter の初期値はどうなっていたか。 53912 うーん。調べてみると input には e が入っていて、_ble_complete_menu_filter には '' が入っている。 53913 つまり input は補完開始店から切り出していて、filter の初期値は新しく入力した文字列だと思っている。 53914 改めて _ble_complete_menu_filter の使い方について確認してみる。 53915 →_ble_complete_menu_filter の使用箇所を確認したら実はここだけだった。 53916 これは _ble_complete_menu_filter の初期値を COMP1-COMP2 の文字列にしたら直った。 53917 53918 [計測] 53919 53920 | さて、getg がどれだけ遅くしているのかを確認する。 53921 | getg を呼び出さない様に変更してみた所 0.533 になっている。 53922 | getg は実はそんなに時間を食っている訳ではない。 53923 | 今は特に重い getg (内部で ble/util/type を呼び出し) を使っていて、それでも 0.100s である。 53924 | 別の場所が遅いという事である。 53925 | 53926 | ble-color-g2sgr の呼び出しを削除してみた所 0.338 にまで減少した。 53927 | 先ずここがかなり食っているという事になる。0.200s である。 53928 | というか、ble-color-g2sgr はキャッシュしているのではなかったのか。 53929 | 53930 | ble-edit/info/.construct-text の代わりに 53931 | ble-edit/info/.put-simple "$((${#show}-alen))" "${show:alen}" 53932 | ble-edit/info/.put-nl-if-eol を使ってみたところ、 53933 | 0.090s 程度は高速化した。更に何もしないように変更すると 0.040 程度短くなった。 53934 | うーん。実は正規表現で print+ を呼び出すのは微妙に遅いという事なのかもしれないが、 53935 | しかしそれでもそんなに重い処理ということではない様だ。 53936 | 53937 | 一つ上の階層で、construct-single-entry 自体を空の物に置き換えるとどうなるか。 53938 | 調べてみると、0.097 にまで短くなった。つまり、construct-single-entry が悪いのである。 53939 | 改めて少しずつ調べる。unpack は 0.070s 程度はある様である。 53940 | 改めて各部分について再計測する。 53941 53942 construct 0.650 の内訳 計測2 53943 - construct-single-entry 0.550s 0.389s 488 53944 - unpack 0.070s 0.040s 99 53945 - getg 0.110s 0.119s 139 53946 - g2sgr 0.210s 0.063s 258 53947 - construct-text 0.140s 0.142s 321 53948 - 正規表現 print+? 0.090s 53949 - 内容の構築 0.040s 53950 - 結果の処理 0.020s 0.025s 463 53951 Note: construct-single-entry がちゃんとした結果を返した時に、 53952 それを外部で処理する時に増える時間である。 53953 - 外側の処理 53954 53955 [高速化] 53956 53957 取り敢えず unpack がそんなに時間がかかるというのは問題なので確認する。 53958 将来的には全てのデータをこの unpack の方式に変更したいので、 53959 これについてちゃんとした速さを確認しておく必要がある。 53960 ble/string#split (空要素やglobに対する対策あり) の代わりに単純な配列代入に置き換えてみた所、 53961 0.030s 程度短縮した。つまり 0.040s ぐらいになったはずである。 53962 53963 次に g2sgr について確認する事にする。 53964 upvar によって結果を返すのをやめてみたが 0.040s 程度しか短縮しない。 53965 キャッシュが働いていない可能性があると思ったがそうでもない。 53966 何故こんなにも遅いのだろうか。空の関数に差し替えてみると 0.050s 程度更に縮まった。 53967 つまり配列アクセスだけで 0.050s 程度も損しているという事になる。 53968 更に、未だ 0.110 程度の時間が残っている。おかしい。 53969 と思って、呼び出しを削除してみたら 0.030s 程度しか変化しない。 53970 先程の計測は誤りだったのだろうか。 53971 再度計測し直す事にする (計測2)。どうも upvar をやめただけで 0.140s 縮んでいる? 53972 0.040s しか縮まなかったというのは勘違いだったのであろう。 53973 53974 全般に upvar は使わない様に書き換える事にした。書き換えた。 53975 53976 しかし、依然として全般に遅い事は変わらない。print+ の高速化を試みる。 53977 うーん。難しい。まずは試しに正規表現一致を外で行う様にしてみたが 0.028s 縮んだだけだ (0.460)。 53978 正規表現の代わりに glob を使う様にしてみたが対して速度に変化はない (0.449s)。 53979 最初に予期しない文字が含まれていなければ簡単に処理する様にしてみたが、 53980 するとそれだけで 0.032s も早くなる (0.417s)。これで construct-text は最初の半分の時間になった。 53981 53982 所で g2sgr の配列アクセスに時間がかかるのは気になるので、 53983 試しに _ble_color_g2sgr__table を local で宣言してみるとどうなるか確認する。 53984 →これは殆ど変わらない。寧ろ毎回 g2sgr を一回計算し直すので 0.005 程度遅くなる。 53985 53986 うーん。g2sgr のキャッシュを先にみて関数呼び出しを省略したらそれだけで 53987 0.417 → 0.384 に早くなった。0.033s の高速化である。 53988 しかも、試してみた所、実は関数呼び出しを省略しなくても、 53989 キャッシュする関数と実際に計算を実行する関数を分けたら、 53990 それだけでも 0.018s の高速化になるという事が分かった。 53991 つまり、実際に実行する処理が同じでも実行する関数の長さに依存して 53992 関数呼び出しの実行時間が変化するという事だろうか。 53993 53994 更に g2sgr 周りの呼び出し方を変えたら早くなるかと思ったら遅くなった (0.382 → 0.386) ので戻す。 53995 何か計測方法に不備があった可能性もあるが、何れにしても殆ど変わらない。元のままで良い。 53996 53997 次に getg について。特に変数名の列挙の時に時間がかかっている。 53998 ble-color-face2g syntax_varname を毎回呼び出すのをやめたらどうだろうか。 53999 0.709 → 0.694 に減少した。大した変化ではない。 54000 また、変数名を勝手にキャッシュするのではなくて、 54001 ble-color-face2g で使っている変数を参照する様に変更した所、0.696 になった。 54002 殆ど変わらないが、着色をユーザが変更した時に追跡できるようにする事を考えると、 54003 その配列を参照するのが良い。しかし、何れにしても微妙な違いしか無いという事が分かったので、 54004 これについては元の通り ble-color-face2g を呼び出す様にする方が良い。 54005 54006 うーん。これ以上は微妙。改めて試してみると古い実装は高速だった。 54007 或いは、一定以上の項目数の場合には awk 等を使った高速な実装に切り替えるという事も必要なのかもしれない。 54008 それはまた問題になってから考える事にすれば良い。 54009 54010 * complete: / を含む関数名の補完で途中でメニュー補完が起動してしまう [#D0764] 54011 新しく挿入文字列が合った場合にはメニュー補完は起動するべきではないのではないか? 54012 と思ったが、今回の問題はそうではないようだ。挿入できる時でも挿入する前にメニュー補完に入っている。 54013 54014 何故メニュー補完が開始してしまうのかと言うと、 54015 連続で二回同じコマンドが呼び出されるという場合に該当するからである。 54016 関数名の補完の場合は / の区切り毎に補完を実施することにしているが、 54017 連続で二回同じ補完コマンドを呼び出した時にメニュー補完に入るのは、 54018 一回の補完で必ず挿入できるところまで全て挿入するという前提があるからである。 54019 54020 その前提が必ずしも成立しないとすると、どの様にメニュー補完に入るのを判定したら良いだろう。 54021 或いは、既に表示した時点で新しく…うーん 54022 54023 * ble/util/assign: 第2引数をコマンドとして第3引数以降を引数にしたら良いのではないか [#D0763] 54024 現在の実装では第2引数以降を全て eval に渡しているが、 54025 現状使用されている箇所を確認すると全て第2引数にしか指定していない。 54026 寧ろ、パラメータを渡す為にわざわざ一時変数を介するなど面倒な箇所 (ble/util/type) がある。 54027 パラメータを渡す事ができる様にする事は便利であるはずなのでその様に実装を変更すると良い。 54028 54029 よく見たら term.sh の中で呼び出している ble/util/assign はおかしい。直した。 54030 また第2引数(コマンド)がクォートされていないものは全てクォートする事にした。 54031 ble/util/assign 及び ble/util/assign-array の両方を $2 のみ評価する様に修正した。 54032 ble/util/type の実装はこの新しい機能を使うものに切り替えた。問題なく動いている様だ。 54033 54034 * 2018-08-26 complete: 候補一覧でコマンド・ディレクトリ名や変数名の着色 [#D0762] 54035 54036 対応してみたが何故かキーワードが赤く着色されてしまう。何故か。 54037 確認してみた所、ble-syntax/highlight/cmdtype はキーワードに対しては呼び出さないので、 54038 もし仮に keyword が返された時には、ジョブ名かその他の特別な状況である。 54039 54040 仕方がないので ble-syntax/highlight/cmdtype1 を直接呼び出してみる事にする。 54041 そもそもメニューの表示においては同じコマンド名が複数現れるとは考えにくいので、 54042 余りキャッシュの効果もないだろうと予想する。 54043 54044 因みに type -t commands... で一括で結果を取得するという事も考えたが、 54045 どうやら type -t commands... だとエラーのあるコマンドについては何も出力しないので、 54046 結局どの行がどのコマンドに対応するのかが分からない。 54047 一番最初に生成される候補の時点でちゃんと全て存在する物であるならば問題はない。 54048 一方で type commands... だと関数定義まで出力してしまうし、 54049 type -p commands... だとファイルとしてのコマンドについてしか出力を行わない。 54050 54051 2018-08-31 54052 54053 * complete: vi_cmap での自動補完・絞り込みなどはどうなっているのか [#D0761] 54054 54055 そもそも補完は定義されていただろうか。 54056 確認してみると vi_cmap ではそもそも補完は bind されていなかった。 54057 しかしコマンドを入力する場合などを考えると補完があった方が便利である。 54058 54059 コマンド以外の物を入力する場合でも、 54060 文脈値に対応していなければそもそも補完文脈が生成されないだけなので、 54061 特に問題は起こらない様に思われる。 54062 54063 そもそも現状では TAB を入力すると何が起こるのか? 54064 →TAB が入力されるという事はなくて C-i になるので unbound keyseq になる。 54065 54066 単に有効にしてみると何が起こるか。 54067 →(恐らく) check-here でファイル名による補完が起動する。 54068 →もう一つの問題は 入力欄を panel 2 に表示している為に、 54069 候補一覧が表示・非表示される度に表示位置が変更されて見にくいという事である。 54070 54071 実際に補完文脈を生成している部分を観察してみたが、 54072 "認識できない文脈の時に file を文脈として生成する" 等の機能はない様に見える。 54073 うーん。調べると確かに argument が生成されている。更に variable 等も生成されている。 54074 % .check-here で生成される事があれば、.check-prefix で生成される事もある。 54075 % →確認したら .check-prefix で生成されていたのは普通の文脈に戻った時だけだった。 54076 .check-here で argument が文脈として生成されている。 54077 ctx を確認してみると 0 (CTX_UNSPECIFIED) である。 54078 文脈値が重複している物がないか確認したがない。 54079 という事はどれかの文脈値の名前を間違えているか? 54080 分かった CTX_FARGX3 と書くべき所が FARGX3 になっていた。直した。 54081 54082 * vi: !! をキャンセルしても _ble_edit_mark_active が元に戻らない [#D0760] 54083 これは最初単に _ble_edit_mark_active= を設定する位置の問題かと思ったがそうではなかった。 54084 元々のコマンドラインの内容に対して着色を行っているのであるから、 54085 vi_cmap を抜けた時の自動的な復元の対象とはならない。 54086 vi_cmap に _ble_keymap_vi_cmap_cancel_hook 変数を追加する事にした。 54087 修正した。ちゃんと元に戻る事を確認した。 54088 54089 * decode: xterm で modifyOtherKeys とすると C-back で DEL を送り back で BS を送る [#D0759] 54090 試してみると modifyOtherKeys に関係なくその動作の様である。 54091 これらの端末ごとの動作に関しては何処かにまとめて置くと良いだろう。 54092 #M0010 にまとめる事にした。 54093 54094 2018-08-30 54095 54096 * decode: xterm で _ を入力しようとすると S-_ がありませんと言われる [#D0758] 54097 現在はアルファベットしか処理していないが、 54098 実はキーボートに表示される可能性のある全てのキーについて S- は処理するべきなのでは。 54099 更によく考えるとヨーロッパの国では変な文字がキーボードに表示されている事もある。 54100 その様な状況を考えれば S-通常文字 については常に S- は外すべきなのではないだろうか。 54101 54102 * menu-complete: vi マクロ・繰り返しにおける対応 [#D0757] 54103 54104 % これは対応し始めると大変な気がするので 54105 % menu-complete が実行された場合には imap-repeat は無効化する事にする。 54106 54107 と思ったが選択過程は無視してどう置換されたかだけで記録すれば良い様な気もする。 54108 置換に失敗した時にそのまま処理を続行しても良いのかどうかは謎であるが、 54109 少なくとも現在の complete の実装はその様になっている。 54110 54111 これは ble/widget/menu_complete/accept において、 54112 一旦内容を元の状態に戻して、それから ble-complete/insert 54113 を用いて展開すれば良い様な気がする。 54114 序に menu_complete/accept に於いて action/complete も調整する事にした。 54115 但し insert の書き換えには対応していない。 54116 54117 テストする。imap-repeat も . も動いている様に思う。 54118 54119 * ok: マクロに関してはどうしようもない。 54120 54121 % tab 等による選択もマクロとして記録されてしまうが、 54122 % それをそのまま再生した時に本当にちゃんとできるのかは謎である。 54123 % だからと言って別の操作を勝手に実現する様にするのも変である。 54124 % というかマクロはキーシーケンスとして記録されるのだから、 54125 % 何れにしても変更の余地はない。 54126 % 54127 % そもそも auto-complete の時に特別な処置が必要だったのは、 54128 % auto-complete が実際のキー操作を伴わずに勝手に起動して、 54129 % その後のユーザ操作の結果に影響を与えるからであった。 54130 % menu-complete に関してはユーザの操作で閉じている。 54131 % menu-filter に関しては基本的には表示情報が更新されるだけで、 54132 % ユーザ操作の編集結果に対する影響はないので特に考えなくても良さそうである。 54133 54134 マクロに関しては特別に対応する必要はない 54135 54136 * done: 実は action:action/complete は以下の変数を提供する事になっている 54137 54138 COMP1 COMP2 COMPS COMPV comp_type comps_flags 54139 54140 これらは別の変数に記録しておく必要がある。 54141 更に insert 自体の書き換えが起こる可能性もあるし、 54142 insert_flags の書き換えも起こりうる。 54143 何れにも一応対応した。 54144 54145 x fixed: bug そもそも complete 自体が正しく動いていない気がする 54146 どの様に記録されているかを確認する必要がある。 54147 54148 - done: insert.hook を調べてみた所、そもそも実際に挿入が行われていないのに 54149 insert.hook が呼び出されている。スキップするべきなのではないか→修正した。 54150 54151 分かった事は auto_complete で self-insert を取っているので、 54152 その間に入力された内容が記録されていないという事であった。 54153 54154 a うーん。auto_complete self-insert から vi_imap に push するのは変だ。 54155 b __before_widget__ を呼び出すのも変な事が起こりそうだ。 54156 c 新しい hook を定義する程でもない様な気がする。 54157 d そうすると insert_hook を流用して通知する事になるだろうか。 54158 54159 取り敢えず d の方針で実装する事にする。 54160 修正した。これで取り敢えず auto_complete が混ざった補完の繰り返しは動く様になった。 54161 54162 o menu-complete も menu-filter も問題を起こさず繰り返しできている様に見える。 54163 54164 * decode: modifyOtherKeys が全然駄目 [#D0756] 54165 54166 mintty や xterm で試してみる。 54167 54168 x fixed: 調べてみると ESC [ key ; mod u は送られてきているが、ちゃんとデコードできていない? 54169 と思ったら変数名を間違えていた。 54170 54171 x fixed: 何故か S-A 等はちゃんと入力できる。 54172 CapsLock の状態で S-a を入力すると、今度は何故か M-a と認識されてしまう。 54173 →これもバグだった。mods で modify するべき所を kcode で modify していた。 54174 54175 - done: S-a や S-A に対してはどの様に対処すれば良いだろうか。 54176 54177 どうやら mintty の場合には S-(Shift済み文字) を送ってくる様だ。 54178 C-S-a 等の場合にも C-S-A を送ってくる。 54179 うーん。どうやって検出するのが良いだろうか。 54180 54181 先ず Shift 以外の修飾がない場合には通常の文字入力と解釈したいので、 54182 単に S- を外す様にすれば良い。 54183 次に Shift 以外の修飾がある場合には実際に押されたキーを使いたいので、 54184 寧ろ文字の方を小文字に変換する様にしたい。 54185 54186 後で xterm も試してみた所、同様の動作だった。 54187 54188 x fixed: ログアウトした時に変な状態? 54189 やはり external の既定値は 0 にするべき。少なくとも 1 が望ましい。 54190 取り敢えず 1 にする事にする。1 にしておいたら抜けても大丈夫だった。 54191 54192 o ok: 普通の入力はできる様になった。mintty で S-RET はできる。 54193 C-TAB は何も送信されて来ない(?)がこれは仕方がない。 54194 xterm で試してみた所、xterm では C-TAB が送られてくる。S-RET も効く。 54195 54196 x resolved: うーん。mintty は Alt で普通に A- 修飾をしてくる。 54197 ここは M- 修飾という事に読み替えるか…。 54198 うーん。そもそも 2 を A- として 54199 0x20 を M- にするのは独自の仕様である。 54200 54201 うーん? 他の端末だとどうか? 54202 xterm を試してみた所やはり Alt で修飾 2 である。 54203 ここは 0x20 を A- にして一般的な 2 は M- 修飾にする。 54204 54205 2018-08-29 54206 54207 * complete: echo ~/m@ から補完を実行すると COMP_PREFIX が効いていない [#D0755] 54208 全ての候補に余分に /home/murase/ がついている。 54209 54210 - 今までの ble.sh ではちゃんと動いていた様子である。 54211 これはまた bash-completion だろうか。 54212 - また echo ~/@ から補完を実行した時にはちゃんと COMP_PREFIX は効いていて、 54213 候補たちには余分なパス /home/murase/ は付加されない状態で表示てきている。 54214 - ble-syntax:bash/simple-word/eval '~/m' をしてみると、 54215 ちゃんと /home/murase/m に展開されている。 54216 従って COMPV の不整合ではないと思われる。 54217 54218 また後で詳しく調べる事にする。 54219 54220 - 調べるとどうも action:plain/initialize の直後ではちゃんと ~/m* の形の候補になっている様だ。 54221 - 確認してみると先頭を削っているのは action:action/initialize ではなかった。 54222 そもそも menu で表示しているのは INSERT ではない。 54223 menu/style:style/construct の中で PREFIX_LEN を参照してその分だけ削っている。 54224 つまり PREFIX_LEN または COMP_PREFIX の計算が間違っている。 54225 実際に COMP_PREFIX は全く設定されていない様だ。 54226 - yield の呼び出し元を調べると progcomp である。 54227 compopt で filenames が指定されていないという事だろうか。 54228 と思ったらちゃんと指定されている。 54229 - 分かった。単に自分の作ったバグである。 54230 "COMPV に / が含まれている時に COMP_PREFIX を設定する" ところが、 54231 "COMPV が / で終わる時" に誤ってなっていた。直した。 54232 54233 * complete: [refactor] $ACTION は ble-complete/action/ は含まない様に変更する [#D0754] 54234 54235 また ble-complete/action/ から ble-complete/action: に変更する。 54236 元々 ble-complete/action/ の形にしていたのは 54237 "外からカスタマイズする時に action というディレクトリにファイルを置けば使える" 54238 という様にできたらいいなと思っての事だったが、具体的な計画はないし 54239 そもそも結局 $path/complete/action/foo の形で検索しなければならないのだから、 54240 関数名を ble-complete/action/ の形式にしておいても余り利点はない。 54241 54242 同様に ble-complete/source/foo も ble-complete/source:foo に変更する事にした。 54243 54244 * decode: [refactor] _ble_decode_key__kmap -> _ble_decode_keymap [#D0753] 54245 54246 * decode: modifyOtherKeys の振る舞いについて [#D0752] 54247 54248 調べると xterm では $'\e[>4;1m' 等を送ると有効になると書いてある。この情報は本当か? 54249 https://unix.stackexchange.com/questions/165104/does-gnome-terminal-have-an-equivalent-for-xterms-modifyotherkeys 54250 54251 更に C-tab を使う為には modifyOtherKeys を 2 にしなければならないが、 54252 これを設定すると Ctrl+space が C-@ ではなくて C-SP になるなど色々面倒な事になる。 54253 どの設定でも動く様にする為には C-@ と同時に C-SP 等にも束縛して置かなければならない。 54254 これらは実際の xterm で試す必要があるだろう。 54255 54256 なんと xterm.el にもその様な設定が含まれている。 54257 https://emacsformacosx.com/emacs-bzr/trunk/lisp/term/xterm.el 54258 これを読む限りでは \e[>4m で解除で \e[>4;1m で有効化の様である。 54259 実は \e[>4;2m とすれば C-TAB もできるようになるという事ではあるまいか。 54260 54261 検索してみると mlterm は "CSI > 4 ; 2 m" に対応している。 54262 https://sourceforge.net/p/mlterm/feature-requests/16/ 54263 しかも "ESC[<unicode>;<mod>u" の形式を使っている…。 54264 54265 うーん。'\e[>4;1m\e[>4;2m\e[m' でも送っておけば良いだろうか。 54266 現在の所、端末がこれらの設定に対応しているかどうか調べるのは難しい。 54267 解除に関しては、ユーザが敢えて設定している事もあるかもしれないので、 54268 \e[>4m は送らないで置く…と思ったが、\e[>4;2m で放置しておくと、 54269 C-SP が他のソフトウェアで効きませんという事になるかもしれないので難しい。 54270 bleopt で設定できる様にするべきである。 54271 54272 以下のページによると mintty は C-TAB で \e[1;5I を S-C-TAB で \e[1;6I を送ってくるそうだ。 54273 https://tmsanrinsha.net/post/2012/07/%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E3%81%A7ctrltab%E3%81%A8%E3%81%8B%E3%82%92%E4%BD%BF%E3%81%86/ 54274 cmap/default.sh を参照してみるとこれらは kptab に割り当てられている… (つまり C-kptab, S-C-kptab)。 54275 54276 [修正] 54277 54278 - done: 先ず初めに synonym となるキーに関して確認を行う。 54279 54280 - done: C-@ と一緒に C-SP も登録する事にした。ただそもそも一箇所しかなかった。念の為 NUL も登録した 54281 - done: C-m と一緒に RET も登録する事にした。一箇所だけ欠けている所があった 54282 - done: C-i と一緒に TAB も登録する事にした。一箇所 S-TAB だけの所があったので C-S-i も登録した 54283 - done: C-?, C-h と一緒に DEL, BS も登録する。これは結構修正した。主に C-h と DEL しか登録されていなかった 54284 - done: C-_ と一緒に C-DEL, C-BS も登録する。これは一箇所 C-_ だけの所があった。他に C-BS は一つもなかった 54285 54286 - done: 次に CSI u に対応する。 54287 54288 - done: kp~ は区別しても役に立たないので 54289 ユーザが特に区別したいというのでなければ既存の物と同じにする。 54290 54291 - done: '\e[>4;1m\e[>4;2m\e[m' を送ることにする。 54292 結局状態を管理する事にした。 54293 ble.sh の外でどの設定にするかは bleopt_term_modifyOtherKeys_external で設定する。 54294 54295 * complete: 絞り込み [#D0751] 54296 54297 初め fish の様に入力欄を候補一覧の上に表示する事を考えたが管理が面倒だ。 54298 更に言うとコマンドラインと別に表示する意味があるのかわからない。 54299 それよりはコマンドラインの中に入力して、 54300 入力しながら直ぐに候補一覧を更新するという様にした方が懸命である。 54301 54302 % その時にどの様に処置をするのが良いだろうか。 54303 % 54304 % a 一つの方法は keymap:complete を定義するという事 54305 % この keymap の中で self-insert や delete-backward-char があった場合には、 54306 % 候補一覧をその場で更新するという仕組みにする。 54307 % 54308 % 少々問題がある。auto-complete が更に起動している場合、 54309 % self-insert は auto-complete が食ってしまう。 54310 % これに対して正しく対処するためには、 54311 % auto-complete 側が complete の情報を利用する様に書き換えると良い。 54312 % 54313 % b 或いは寧ろ auto-complete が候補一覧を出すというのでも良い。 54314 % 54315 % 取り敢えず auto-complete に候補一覧を出させてみる事にする… 54316 % と思ったが、候補の更新は background で実行したい。 54317 % もし background で候補を更新するのだとしたら、 54318 % 実は候補一覧が表示されている時に限り、 54319 % すぐ様、候補の絞り込みの処理を実行すれば良いのではないか… 54320 % 54321 % c auto-complete.idle に処理させる。 54322 54323 うーん改めて望ましい動作について整理する必要がある。 54324 54325 * done: [準備] ところで候補一覧を計算している途中に次の入力が来たときには処理を中止する。 54326 中止したとしても候補一覧を無効にしたくはないので、 54327 処理を中止した場合には _ble_complete_menu_* に変化がない様にしたい。 54328 つまり、処理が完了したらその時に _ble_complete_menu_* を更新する様に変更する。 54329 54330 * ok: 絞り込みによって候補がなくなった場合に曖昧一致に切り替える時 54331 54332 | 先ず初めに補完候補一覧を出したとする。それに続けて文字を入力したとする。 54333 | すると段々と候補が少なくなってもし変な文字列を入れると最終的には候補は全てなくなる。 54334 | この時に改めて曖昧一致などを試みるべきだろうか。 54335 | しかし、そうだとすると一番最初の候補生成のところからやり直すべきなのではないか。 54336 | 更にいうと、候補生成は開始点を遡って候補生成を試して、 54337 | 一つも候補が見つからなかった時に限り曖昧一致の候補を生成する様になっている。 54338 | もし絞り込みで候補が尽きた時にも同様の動作をするとすれば、 54339 | 結局絞り込みの開始点が勝手にずれるという事になり混乱の元である。 54340 | 54341 | 更に delete-backward-char 等でカーソル位置を元に戻した時に、 54342 | a 元の候補一覧に戻すようにしない、というのは不便である。 54343 | b 一つの方法は元の候補集合をカーソル位置毎に覚えておく方法である。これは非現実的な気がする。 54344 | c そもそも候補集合を変更しない様にするというのが現実的な気がする。 54345 | つまり、ユーザが明示的に TAB (complete) を呼び出さない限りは候補集合は変更しない。 54346 54347 結論: 候補が絞られてなくなった時、候補集合を自動的に曖昧一致で再生成するか? 54348 →しない。既に持っている候補集合に対してのみ曖昧一致を試みる。 54349 もしちゃんとした曖昧一致を実行させたいのであれば、 54350 ユーザがもう一度明示的に complete を押すようにするべきである。 54351 54352 * done: どの様な操作があった時に候補絞り込みを継続(中断)するのか。 54353 54354 | 例えばスペースを挿入する事によって単語が切れた時。 54355 | これは例えば補完開始点と終了点を記録しておいて、 54356 | 補完開始点からカーソル位置の間までが simple-word (close 可能) であるかどうかの判定で良い。 54357 | 54358 | 或いは、一旦スペースを挿入して backward-delete-char 54359 | で戻った時にまた再開するかどうかも微妙な問題である。 54360 | 一回スペースを挿入したのにまた戻ってきたら再開するというのも妙な話である。 54361 | 然し一方で、誤って挿入してしまったとしてもまた元に戻る事ができるというのも便利である。 54362 | 54363 | また一回カーソルで移動してからまた元の位置に戻ってきた時の動作はどうか。 54364 | 一回離れてまた戻ってきた時にまた動き出すというのも変な話である。 54365 | しかしながら一方で、絞り込みの途中で前後に移動したいという需要はあるかもしれない。 54366 54367 以上を総合すると次の様な実装にするのが良いのではないだろうか。 54368 54369 1 最初の候補一覧表示の際に、以下を記録して置く。また "絞り込み" がアクティブの状態にする。 54370 補完開始点 beg, 補完点 end, 前の文字列 left=${str::end}, 後の文字列 right=${str:end} 54371 54372 実装: 実はこれは現在の実装で既に記録している物に一致している? 54373 しかし _ble_complete_menu_state はもしかすると廃止するかもしれないし、 54374 直接文字列を格納している訳ではないので分かりにくい。 54375 取り敢えずの実装として _ble_complete_menu_str を記録する事にする。 54376 54377 2 idle の処理に於いて絞り込みがアクティブである時、 54378 1 カーソル位置のチェックとして次を行う。 54379 [[ ${str::ind} == "$left"* && ${str:ind} == *"$right" ]] 54380 が満たされていなければ、絞り込みから外れたと見做し、 54381 絞り込みを非アクティブにして終了する。 54382 2 ${str:beg:${#str}-${#right}} が simple-word でなければ 54383 やはり絞り込みを非アクティブにして終了する。 54384 54385 注意: この時、もし auto-complete が有効であるならば、 54386 一時的に挿入されている文字列に反応しても困るので、 54387 str1=${str::ind}${str:mark} を対象にして上記の判定を実行する事にする。 54388 54389 更に、isearch など他のモードになった時に勝手に候補絞り込みが走られても困るので、 54390 keymap が emacs, vi_imap 及び、特別に対策した auto_complete の時のみ処理する。 54391 それ以外の場合には絞り込みを非アクティブにして終了する。 54392 54393 実装: これはそのまま実装する。 54394 54395 絞り込みの非アクティブ化は idle で実行するため、 54396 一瞬で絞り込みの条件を破壊し回復しても絞り込みの続きができる。 54397 これは仕方がないので気にしない事にする。 54398 54399 取り敢えず実装してみた。動いている。 54400 54401 * done: この絞り込みがアクティブかどうかの条件を menu-complete に入るかどうかの判定に使える。 54402 現在は $_ble_edit_ind:$_ble_edit_str しか見ていないので、 54403 編集してから同じ状態にして其処で complete を実行した場合でも、 54404 menu-complete に入ってしまう。やはり試してみると不自然な動作に思われるので、 54405 絞り込みがアクティブかどうかを考慮に入れるのが良い様に思われる。 54406 54407 * done: 絞り込みが行われた状態でメニュー補完に移る条件は? 54408 54409 現在の実装だと complete を連続で押すか、 54410 最後に候補一覧が更新された時と同じ状態で complete が呼び出されると、 54411 メニュー補完に突入する。 54412 54413 連続で complete を呼び出した時にメニュー補完に入るのは良い。 54414 最後に候補一覧が更新された時と同じ状態という条件はそのままだと問題になるかもしれない。 54415 絞り込みが行われた時に一緒に _ble_complete_menu_state も記録していると、 54416 絞り込みの途中で共通部分の complete を実行しようと思っても必ず menu-complete に入ってしまう。 54417 54418 - done: これは _ble_complete_menu_active を用いて判定する事にした。実装した。 54419 54420 - done: menu-complete では _ble_complete_menu_active はそのまま保持する事にした。 54421 menu_complete を抜ける時に cancel ならば続きからに絞り込みできる様にする。 54422 accept ならばその時に _ble_complete_menu_active を無効にする。 54423 他に menu_complete から抜ける箇所はないので、 54424 _ble_complete_menu_active が残存して問題が起こる事はないだろう。 54425 54426 * done: _ble_complete_menu_state はもし不要になっていたら削除する 54427 確認したらもう既に使われていないので削除する。 54428 54429 * done: 絞り込まれた状態でメニュー補完に入っても問題は起こらないか。 54430 普通に動いている様だが、そもそもどの様な懸念があったろうか。 54431 54432 | 試していたら駄目だった。beg と end が恐らくずれている為に問題が生じている。 54433 | メニュー補完で確定した後に挿入する位置が間違っている。 54434 | beg と end がどう使われているかを再度確認する必要がある。 54435 | 1 先ず、menu-complete の範囲の切り出しに使用されている。 54436 | 2 また、menu-filter の有効期限判定の為にも使われている。 54437 | 前者では最新の状態に対応する範囲を使う必要がある。 54438 | 後者では一番最初の状態に対応する範囲を使う必要がある。 54439 | つまりそれぞれ記録する必要がある。 54440 | 54441 | menu-complete の範囲の切り出しに使うのは、 54442 | menu-filter によって計算された範囲という事にしようと考えたが、 54443 | よく考えてみたらビジーだと menu-filter は実行されない。 54444 | 従って、menu-complete の側で独自に menu の有効期限を更新する必要がある。 54445 | 特に毎回更新を行うのだとしたら、わざわざ最新の beg と end を記録する必要はない。 54446 | 一方で、最新の beg と end を計算する仕組みを共通化するという観点から考えると、 54447 | 最新の beg と end をグローバル変数に記録する仕組みになっていてもおかしくはない。 54448 | 54449 | 取り敢えずは最新の beg と end を計算するコードを書いてみてから比較して判断する。 54450 | やはりその場で毎回範囲を計算しなければならない。 54451 | get-active-range という関数を作って編集範囲を取得する共通コードを括りだした。 54452 54453 menu-complete にしろ menu-filter にしろ、 54454 取り敢えず最初の beg end str と現在の str ind を較べる事により、 54455 候補一覧がアクティブであるかどうかを確認し、 54456 その後で現在の範囲を用いて処理を行う。 54457 現在の範囲を取得する関数として共通の実装にする事にした。 54458 54459 * done: _ble_complete_menu_beg をチェックしてメニュの有効無効を判定している箇所は 54460 _ble_complete_menu_active に変えても問題ないか確認した上で変更する。 54461 そのすぐ下で既に _ble_complete_menu_active のチェックを行っていたので、 54462 単に判定を削除するだけで対処した。 54463 54464 ble-complete/menu/clear に関しては _ble_complete_menu_beg による判定が残っているが、 54465 そもそもこの ble-complete/menu/clear の処理は必要だったのだろうか。 54466 単に menu_active を無効にして ble-edit/info/clear するだけで良い様な気もする。 54467 54468 * done: そもそも何故 ble-complete/menu/clear という関数を作ったのだったか。 54469 現状では実質、メニュー補完で確定をした時に画面を消去するのにしか使っていない。 54470 メニュー補完で確定した後にまたメニュー補完が始まると嫌なので 54471 _ble_complete_menu_beg をクリアしたが、 54472 _ble_complete_menu_beg だけクリアするのも変ということで全て消したのであろう。 54473 →_ble_complete_menu_active= だけ実行する様に変更する。 54474 54475 * done: 一意確定の時に ACTION/complete を呼び出す前に menu/clear している 54476 元々は ACTION/complete の中で候補一覧を表示するために先に clear をしていたが、 54477 現在は新しく候補一覧を出す時には ACTION/complete の中で要求を出して 54478 外側で改めて候補一覧の生成を実行する様に変更した。 54479 今となっては ACTION/complete の中で menu/clear を実施する必要がない様に思われる。 54480 →この呼出は削除する事にする。 54481 54482 x resolved: メニュー補完で確定した後も絞り込みが有効になっている。 54483 →メニュー補完ではなくて自動補完の方だった。 54484 - checked: 通常の補完確定でもメニューは無効化される。 54485 - checked: メニュー補完の確定でも無効化される。 54486 - checked: 自動補完の確定でも今回無効化されるようにした。 54487 何れの場合でも補完が確定すれば候補一覧を消すという方向で統一した。 54488 前よりも見通しが良くなった気がする。 54489 54490 * done: よく考えたら現在の枠組みでどうやって候補再生成を実行するのか 54491 54492 | 必ず menu-complete に突入してしまう。 54493 | 直ぐに menu-complete したいという時もあるのでどうするか。 54494 | うーん。やはりアクティブでかつ元と同じ状態という事にするか。 54495 | 54496 | 望むらくは有限の共通一致部分が新しく挿入すれば補完し、 54497 | それ以外の場合にはメニュー補完に移動する。 54498 | という事を考えたが、目で見て瞬時に判断するのは難しいので、 54499 | 結局は一回は共通一致部分の挿入を確かめる事にするのが良い。 54500 | 一方で、折角絞り込んでも候補の再生成を行うと異なる物が表示される可能性もある。 54501 | どちらの方が良いのか。或いは別のキーで直接メニュー補完に入れる様にする。 54502 | 54503 | - 直接メニュー補完に入った時には元の状態と同じでなくても良いが、 54504 | 依然としてアクティブである事を確かめる。失敗したらベル? 54505 | - complete からメニュー補完に入る時は元の状態と一致する事も追加要件とする。 54506 54507 complete の先頭で menu-complete/enter する時に、 54508 _ble_edit_str の一致をチェックするだけで良さそうだったのでそうした。 54509 以前は _ble_edit_ind の一致も確かめていたが、 54510 それは _ble_complete_menu_active=1 の時には一致している筈なので省略できる。 54511 また、明示的に ble/widget/menu-complete を呼び出した時は、 54512 別の経路で ble-complete/menu-complete/enter が呼び出されるが、 54513 その時はチェックなどせずに強制的に実行されるので気にしなくて良かった。 54514 単にその位置で menu-complete に入らなかった時に bell を鳴らす様にだけ変更した。 54515 54516 * done: 絞り込み処理の途中でユーザが入力した時に中断しても問題は起こらないか。 54517 これは実際にテストの途中にやっていて起こっている様だったが、特に問題になってはいない。 54518 と思ったら _ble_complete_menu_filter による判定を間違っていた。 54519 _ble_complete_menu_filter_str を参照していた。直した。 54520 構造を改めて見たが問題にはならなそうだ。 54521 最後に表示する時に _ble_complete_menu_filter= を更新しているので。 54522 54523 * ok: 変数を整理する 54524 変数を配列にまとめるなどしたら綺麗にならないだろうか。 54525 観察してみたがまあ特に問題はないだろう。 54526 _ble_complete_menu_filter だけは表現を変更する事にした。 54527 54528 * ok: 変数名 _ble_complete_menu_... の refactor 54529 54530 * done: info が途中で別の操作によって上書きされる可能性が常にあるのでは。 54531 これは menu-complete に突入する時にも既に同じ問題がある。 54532 修正する必要がある。 54533 →menu-complete については修正した。 54534 menu-filter に関しては毎回完全に再描画するので 54535 info が上書きされていても大丈夫である。 54536 54537 * done: 現在絞り込みの状態である事が分かる様なサインはないのか? 54538 未だ絞り込みが有効であると思って何か入力しても反応しないというのは悲しい。 54539 或いは絞り込みが無効になったら候補を消してしまう? 54540 54541 取り敢えずその様に修正した。 54542 もしやはり候補一覧は表示したままが良いという場合には、 54543 get-active-range と ble-complete/menu-filter.idle で呼び出している 54544 ble-complete/menu/clear を別の物に置き換えると良い。 54545 例えば灰色一色の候補一覧を表示するなど…。 54546 54547 x resolved: メニューが消えるタイミングが変である… 54548 echo b@ で候補を出してその後でスペースを挿入すると、 54549 その直後にメニューが無効化されて消えて欲しいのに、 54550 実際には更に次の操作を行った時に始めて消える。 54551 →これは調べたら単に buffer に溜まっていただけだった。 54552 immediate-clear を使う様にしたら直った。 54553 54554 2018-08-28 54555 54556 * edit: refactor function names "_ble_edit_str.*" -> "ble-edit/content/*" [#D0750] 54557 54558 * 他にも全般に関数名を見直す。 54559 - _ble_* で始まる関数名 54560 - ble-edit/prompt/update 周りの関数名で非公開の物に . をつける 54561 - ble-edit/prompt/update/backslash:* -> ble-edit/prompt/backslash:* 54562 - ble-edit/prompt/update/append -> ble-edit/prompt/print 54563 - _ble_util_array_prototype -> _ble_array_prototype 54564 - _ble_util_array_prototype.reserve -> ble/array#reserve-prototype 54565 - _ble_util_string_prototype -> _ble_string_prototype 54566 - _ble_util_string_prototype.reserve -> ble/string#reserve-prototype 54567 54568 * declare -F で眺めて気になる物を直す。 54569 54570 refact -F ble/adjust-bash-options ble/base/adjust-bash-options 54571 refact -F ble/restore-bash-options ble/base/restore-bash-options 54572 refact -F ble/workaround-POSIXLY_CORRECT ble/base/workaround-POSIXLY_CORRECT 54573 refact -F ble/unset-POSIXLY_CORRECT ble/base/unset-POSIXLY_CORRECT 54574 refact -F ble/adjust-POSIXLY_CORRECT ble/base/adjust-POSIXLY_CORRECT 54575 refact -F ble/restore-POSIXLY_CORRECT ble/base/restore-POSIXLY_CORRECT 54576 54577 * 2018-07-30 complete: menu-completion [#D0749] 54578 54579 曖昧一致の時には自動的に開始しても良いかもしれない。 54580 或いは、その様にすると動作が予期できなくて却って邪魔かもしれない。 54581 54582 その前に他のシェルでどの様なインターフェイスにしているのかを確認する必要がある。 54583 下手に実装して非直感的で使いにくい物にしてしまっても仕方がない。 54584 54585 - done: menu-completion の前に候補の表示の仕組みを整える必要がある。 54586 各候補を表示している座標が必要である → #D0746 54587 - done: mark_active の実装 54588 - done: C-m, RET で確定 54589 - done: tab の場合は一番最後に行ったら最初に行く。 54590 S-TAB なら一番最初に行ったら最後に行く。 54591 - done: 次の行・前の行に行く機能 54592 - self-insert で絞り込み 54593 本当に self-insert で絞り込みというので分かりやすいか。 54594 続けて入力を開始したら確定して続きへの入力にしたい。 54595 54596 それよりは、auto-complete の側で、 54597 候補一覧が既に表示されている時には、 54598 候補一覧の内容を更新するという形にしたほうが良いのではないか。 54599 54600 o 入力領域を新しく用意しなくて済むので便利である。 54601 - 但し、その場合には、更新の途中で中止した時の為に、 54602 直接は _ble_complete_menu_list を書き換えずに、 54603 処理が完了した時に限り _ble_complete_menu_list を書き換えるのが良い。 54604 - また has-input の確認の間隔は短めに設定するのが良いだろう。 54605 54606 →これは別項目を立てる事にする。 54607 54608 - done: menu-complete on/off option 54609 bleopt_complete_menu_complete を追加した。 54610 54611 x resolved: auto-complete が途中で起動するとキャンセルされてしまう。 54612 どの様にして直前が complete であったという事を判定すれば良いのかが問題である。 54613 __before_widget__ で毎回 complete をチェックするのは不毛である。 54614 或いは _ble_edit_arg に何かマーカを設定するか? 54615 と思ったが、それだと他の処理に支障を来す。 54616 54617 LASTWIDGET として自動で起動された物が設定されているのが行けないのか? 54618 と思ったが、実際に exit-default を介して widget が実行されている。 54619 54620 うーん。もう面倒なので menu を表示した瞬間の _ble_edit_ind と 54621 _ble_edit_str を記録しておいて、それらが一致したら 54622 メニュー補完に入るという事にしてしまう。 54623 54624 x resolved: また、現在の気になる振る舞いとして高速に tab を二回押すと 54625 menu-completion が起動しないという事がある。 54626 これは一回目の tab による complete が中止されて、 54627 最後まで行かない為に menu が表示されず、 54628 結果として二回目の tab によって menu-complete が開始しないという事にある。 54629 54630 現在は menu-complete の開始条件を menu が現在の ind:str の状態で記録されていたら、 54631 という事にしているが、LASTWIDGET もチェックして同じ物が連続で呼び出されていたら、 54632 問答無用で menu-complete に入る様にするべきだろうか。。 54633 54634 →と思ってその様にして見た所、complete を二回叩いたら何も表示されず変な状態になる。 54635 どうやら menu-complete/enter は既に計算済みの _ble_complete_menu_list を使用するので、 54636 新しく起動する為にはこちらの手許で候補生成を実施しなければならない。。 54637 更に menu-show も実施しなければならない。 54638 54639 →opts に enter_menu を追加して opts=show_menu と同様の処理の仕方をする事にした。 54640 54641 2018-08-27 54642 54643 * mshex: <del>base (--attach=prompt):</del> screen の中からだと効くが外だと効かない [#D0748] 54644 ble-attach さえ実行すれば読み込まれるのでロードに失敗しているという事ではない。 54645 →これは mshex の側の問題であった。 54646 54647 2018-08-26 54648 54649 * complete: compopt -o filenames に対応する [#D0747] 54650 echo dir/ から補完すると dir/ の部分が省略されない。 54651 これは何故かというと bash-comopletions の _minimal が呼び出される為。 54652 更に、action/file で定義されている候補着色などの機能も効かなくなっている。 54653 54654 →これは action/progcomp の DATA として $comp_opts を記録して、 54655 action/progcomp で場合分けして処理する事にした。 54656 54657 (今までは comp_opts に応じて action/argument{,-nospace} を切り替えていたが、 54658 その方針だと comp_opts の種類の累乗で action が必要になり始末が悪いので、 54659 一つの action で実装する事にした) 54660 54661 * 2018-08-05: complete: 候補一覧の配置と着色 [#D0746] 54662 54663 候補の表示についてはもう少し考える必要がある。 54664 元々は候補源の側で表示の仕方を制御できる様にしようと考えていたが、 54665 よく考えてみれば色々と微妙な問題が存在する。 54666 54667 - 候補に ^M や [m 等の特殊文字が含まれる場合に、 54668 これを着色やレイアウトの為のエスケープシーケンスとどう区別するのか。 54669 特に、エスケープシーケンスを含む事を可能にするのだとしたら、 54670 呼び出し元でわざわざ候補に含まれるエスケープ文字に対して 54671 表示文字列に変換しなければならない。 54672 54673 - 更に、上位の枠組みで着色を変更したい需要がある。 54674 例えば既に入力済みの部分と一致している部分を太字にするなど。 54675 54676 候補源側で着色するという手もあるが、各候補源で着色を別々に実装するのは 54677 不毛だし面倒だし分かりにくいし、表示の統一性を保ちにくい。 54678 また、絞り込みなどのインクリメンタルな処理を行う際に、 54679 毎回候補源を呼び出すというのも効率が悪い。 54680 54681 また、上位の枠組みによる着色が、 54682 候補源側による着色と被るとそれはそれで分かりにくい。 54683 54684 一つの案は候補源は候補の色 (bg,fg) のみを指定し、 54685 上位の枠組みで入力済みの部分を太字にして、 54686 menu_completion で選択している物は反転して、 54687 等の様に直交するような着色を実行する。 54688 54689 1 入力済みの部分を着色するという事 54690 54691 2 各候補の表示位置を計算するという事 54692 54693 3 候補が行を跨がない様にするという事 54694 54695 特に幅が現在の幅より小さい場合には次の行に送る。 54696 現在の幅より大きい場合にはどうせ入らないので、 54697 続きに表示してしまう事にする。 54698 54699 方針としてはまず最初に各候補の幅について計算するのが良い。 54700 タブなどは ^I で表示する事にするので、文字幅は固定である。 54701 但し、折返しが起こる時にはその行で一番最後の文字の 54702 文字幅が影響してくるので注意する。 54703 これは行数分だけ幅に余裕を持って考えれば良いだろうか。 54704 と思ったが、行数が文字幅を超える場合は、それでも問題になる。 54705 1行に収まりきらない候補については必ず末端に表示する事にするか。 54706 54707 或いは行を跨ぐのは諦めるという手もなくはない。 54708 54709 これを達成する為に、info text を改造した様な物を考える。 54710 54711 * 行を跨ぐ場合には、そのまま文字列を出力するとずれる。 54712 再描画の時に再度計算し直すか、 54713 或いは最初に計算した時に esc を記録するか。 54714 再描画の際には esc が変化するので、 54715 記録しておいても仕方がないかもしれない。 54716 54717 % 或いは、反転させるだけならば、反転の SGR で全体を囲むだけ? 54718 % と思ったが太字解除等のシーケンスに対応していない端末では、 54719 % 太字解除に SGR(0) を使ってしまうので単に全体を囲むだけでは駄目である。 54720 % 実際、現在の仕組みを調べてみた所、毎回 SGR(0) でクリアしている。 54721 54722 やはり毎回全体を構築する事になるのだから、 54723 esc の状態で記録しておく事に意味があるかどうかは分からない。 54724 或いは、ble/textmap の様に文字の部分と SGR の部分を分離して記録する手もあるかもしれないが、 54725 それは面倒だし処理の量も増えるので好ましくない。 54726 54727 * 複数の配置モードを実装するというのも手である。 54728 その様に考えれば、最初は一番簡単な実装方法で良い。 54729 54730 [実装] 54731 54732 * done: 取り敢えず着色などを考えずに実装する。 54733 また行に収まらない時の改行なども考えずに実装する。 54734 54735 実装した。bleopt_complete_menu_style を用いて配置方法を選択できる様にした。 54736 今まで通りの何も気にせずに続けて表示する物は dense とした。 54737 行に収まらない時の改行の処理についても実装した dense-nowrap とした。 54738 更に、align, align-nowrap という名前で綺麗に整列するのも実装した。 54739 align{,-nowrap} では bleopt_complete_menu_align を用いて、 54740 整列する時の最大幅について設定できる様にした。既定値は 20 54741 54742 * done: 着色を行う。 54743 COMP_PREFIX 等によって削られている場合に対して対策が必要である。 54744 54745 というか寧ろ cand_show には COMP_PREFIX を入れておいて、 54746 cand_cand の中身と合わせて生成したほうが良いのではないか? 54747 と思ったが、cand_show と cand_cand の両方を参照するのは効率が悪くなる。 54748 54749 cand_show の形式を変更する事にする。 54750 cand_show="${#COMP_PREFIX}:$CAND" に変更する。 54751 形式は変更した。 54752 54753 取り敢えず入力済みの部分を太字にするのを実装したが問題が残る。 54754 54755 1 done: 補完を実行する直前の入力部分が着色されているが、 54756 補完実行後の入力部分 (つまり候補の共通部分) に対して着色するべきではないか。 54757 これについては対応した。 54758 54759 2 done: 制御文字が含まれていた場合 ble-edit/info/.construct-text 54760 は _ble_term_rev _ble_term_sgr0 を用いてそれを囲んでいる。 54761 それによって太字などの描画属性が消えてしまう。 54762 54763 * done: 使用する sgr 及び特殊文字に使用する sgr を外から指定できる様にする。 54764 54765 一つの手は .construct-text は弄らずに 54766 _ble_term_rev _ble_term_sgr0 を local で上書きする事だが汚い。 54767 代わりに ble-edit/info.construct-text の機能として、 54768 別の変数を使って特殊文字とそれ以外の描画属性を外から指定できる様にする。 54769 54770 その上で何が必要になるだろうか。 54771 先ず、候補に SGR が設定されている場合について考える。 54772 54773 * done: 候補ごとに適切な sgr を取得する方法を決める。 54774 (現在は未だ色を設定できる様にはしていないがその内に実装の予定である。 54775 但し実装の方法は複数考えられる。ACTION 経由で取得できる様にした方が良い気がする) 54776 54777 →結局これは ACTION 経由で取得できるようにする事にした。 54778 54779 cand_show の形式も拡張して ACTION や DATA 等の全ての情報を格納する事にした。 54780 結局 cand_show, cand_prop, cand_data の三つの配列を統合し、 54781 cand_pack という名前の配列とする事にした。 54782 その上で cand_pack の要素を展開する関数として ble-complete/cand/unpack を用意し、 54783 それを呼び出した上で "$ACTION/getg" を呼び出す事にした。 54784 54785 * done: ファイル名に関してはディレクトリかそうでないかで色分けする事にする。 54786 結局 syntax 定義されているファイルの種類の全てに対応する事にした。 54787 54788 以下はこの項目によって解消した 54789 54790 | * 2013-06-06 complete: 候補一覧の整列 54791 54792 * history: ロード中に up などで履歴を参照すると履歴の初期化に失敗する [#D0745] 54793 空の履歴になってしまう。 54794 54795 これは async の処理の途中で sync を呼び出した時に、 54796 条件が満たされて初めて呼び出されると期待している場所に、 54797 条件が満たされていないのに突入してしまうのが原因であった。 54798 54799 2018-08-25 54800 54801 * complete: ファイル a=b について a= で補完すると a=a=b になる [#D0744] 54802 54803 #0742 で直したと思っていたが直っていない。 54804 →変更漏れがあったので直した。 54805 更に、argument 以外の時には、= に対する処置を core-complete.sh 側で実行していないので、 54806 argument 以外の時に限って core-syntax.sh 側で = または : 以降の補完文脈を生成する事にした。 54807 54808 * complete: bug: 曖昧補完での置換で元々あった文字列が削除されていない [#D0743] 54809 ble-complete/insert の呼び出しまでは問題ない様だ。 54810 54811 調べてみると insert_beg の値が滅茶苦茶になっている… 54812 と思ったら算術式として計算するべき所で、 54813 文字列としての追記が行われていた。 54814 54815 * complete: bug: 変数 var にディレクトリ名が入っている時 echo ${var} で補完すると [#D0742] 54816 変数の中身が余分に挿入される。 54817 54818 調べてみると何とそもそも補完文脈の時点で 54819 補完開始点が ${var} の直後になっている。 54820 54821 hello=cmap 54822 echo ${hello}@ 54823 54824 に対して "argument 13" という補完文脈が生成されている。 54825 不思議なのはその後でちゃんと $hello に入っている cmap で確定している事である。 54826 54827 調べてみると、どうも source/argument は内部で独自に ble-syntax:bash/extract-command 54828 を呼び出していて、${hello} を抽出している様である。 54829 つまり、argument 候補文脈を生成する時にはちゃんと正しく開始点を決定できなければ、 54830 誤った候補が生成されてしまうという事を意味する。 54831 54832 然し…現在の completion-context の next-argument を観察すると… 54833 例えば引数が ...= の形式をしている時に ...= の部分を削除して 54834 引数として argument を生成する等している。 54835 実際に、 54836 54837 touch a=b 54838 echo a=@ 54839 54840 で補完を実行した所 a=a=b という具合に重複して補完される事を確認した。 54841 うーん。実は ...= の右辺に関しては argument 54842 で処理するべきではないのかもしれない。 54843 もしくは文脈の生成側で勝手に ...= などを切り出すべきではないのか。うーん。 54844 54845 * 取り敢えず少なくとも解決しなければならない事は、 54846 ${hello} に対して補完開始点が正しく検出できない事。 54847 $hello に対しては正しく検出できている。 54848 54849 どうも ${hello} の時は ble-syntax/completion-context/.check-prefix/ctx:next-argument 54850 が呼び出されていない様である。check-here を介して候補が生成されているのではないか。 54851 調べてみると CTX_PARAM を介して check-prefix を起動しようとしている。 54852 直前の ${hello@} における文脈を拾っている。 54853 うーん。これは外側の文脈を用いて補完を起動するべきなのではないか? 54854 と思ったが、パラメータ展開を閉じていない場合には 54855 やはり CTX_PARAM によって補完するべきである。 54856 54857 % うーん。現在位置と同じ nest か、より上の nest になるまで遡るべきなのではないか。 54858 % どの様に判定したら良いか。同じかどうかの判定は簡単である。 54859 % より上の nest であるかどうかはどう判定するか。 54860 % 54861 % extract-command におけるスキップを見れば良いのかもしれない…。 54862 % と思ったが extract-command は tree-enumerate を使っていた。 54863 54864 うーん。そもそもの考えとしては、直前の文脈を参照すれば、 54865 現在の文脈が何であるかが分かるはず、という話だった。 54866 その時に直前の文脈から現在の位置に至るまでの間に含まれる文字列も検索するのであった。 54867 この考え方に従えば CTX_PARAM 文脈に対する処理として実装し、 54868 '}' があれば一つ上の文脈を用いて補完を実行し、 54869 それ以外の時にはパラメータ展開の中身としての補完を実行する、 54870 という具合に実装するべきなのである。 54871 54872 実装した。動くようになった。 54873 54874 * 序に数式中で変数名を補完する様に修正した。 54875 54876 * 候補源 argument が中途半端な場所から始まった時に問題が起こる事に関しては、 54877 そもそも中途半端な場所から始まった時には argument は使うべきではないと判断する。 54878 プログラム補完が定義されている場合でも、--prefix=... の形式の ... の部分を 54879 通常の補完候補と同じ様に補完させてよいのかは非自明である。 54880 54881 更に、補完文脈を生成する際に = や : の位置以降の物を生成するのは都合が悪いのでは。 54882 というのもプログラム補完の側で = 以降や : 以降の候補の生成に対応している可能性がある。 54883 従って、補完文脈の側では = や : 以降の補完文脈は生成せず、 54884 候補源の側で適当に = や : 以降を用いて生成する様にするのが良い。 54885 54886 丁度関連する議論として #D0718 があって、 54887 = や : 以降の方を優先させる事について書いていたが、それについては撤回する事にする。 54888 54889 実際に見てみた所、単に completion-context/.check-prefix/ctx:inside-argument 54890 の中で生成している : または = から始まる補完文脈を削除すれば良いだけの様に思われる。 54891 削除した。 54892 54893 * 2016-07-15 complete: "" の中にある $variable で確定した時は空白は挿入しないようにしたい [#D0741] 54894 また ${... の中で variable で確定した場合は '}' を挿入するようにしたい。 54895 もしくは } が既に存在している場合にはその次の文字へカーソルを進めたい。 54896 54897 % つまり、何を挿入するかは候補側が決めるというよりは実のところ 54898 % 候補生成箇所の文脈に依存するという事である。 54899 % variable:= などを導入して候補生成箇所の文脈を伝える様にはした。 54900 % しかしこの方法だと無駄に複雑になる気がする。 54901 % 補完の枠組自体を再考する必要がある。 54902 54903 2018-08-25 "" の外にあったとしても $variable で確定した問は空白は挿入しない事にした。 54904 ${... の補完の場合には } を挿入する事にした。 54905 既に存在している物をスキップする機能は既に上の枠組みで実装している。 54906 結局現在の枠組みで実装する事にした。 54907 54908 2018-08-23 54909 54910 * 2018-08-05 complete: パラメータ展開で厳密一致で一意確定の時にはそもそも候補の生成を行わない? [#D0740] 54911 曖昧一致も許さない様にする。 54912 そうすれば別のコマンドが生成できる。 54913 54914 実際にやってみたら動かない、と思って調べたら候補生成を停止すると、 54915 今度は曖昧一致を試みるので、結局候補が生成されてしまうという事だった。 54916 曖昧一致の優先順位を変更する事にした。これまでの曖昧一致の順位に余り深い意味はなかった。 54917 今までは先頭一致または曖昧一致で一番近いものを使っていたが、 54918 先頭一致 (で一番近いもの) がなかった時に限り曖昧一致で一番近いものを使うように変更した。 54919 54920 * complete: git の補完が効かない [#D0739] 54921 54922 % 例えば git com まで入力した状態で補完を実行する場合で考える。 54923 % ちゃんと補完関数は呼ばれている。 54924 % 試してみると __get_cword_at_cursor_by_ref で cur=com になるべき所 cur=' com' になっている様だ。 54925 % 以下を実行してみると分かる。 54926 % 54927 % COMP_LINE="git com" COMP_POINT=7 COMP_CWORD=1 COMP_TYPE=9 COMP_KEY=9 54928 % __get_cword_at_cursor_by_ref "" words cword cur; declare -p words cword cur 54929 % 54930 % % これは git の bash completion のバグだろうか。 54931 % 54932 % COMP_* を何も弄らないと cur="'com'" になっている。 54933 % 中途半端に弄ったせいで cur=' com' になったのかもしれない。 54934 % 54935 % COMP_WORDS=(git com) COMP_LINE="git com" COMP_POINT=7 COMP_CWORD=1 COMP_TYPE=9 COMP_KEY=9 54936 % 54937 % で実行してみた所、ちゃんと実行する事ができている。 54938 54939 つまり git completion はクォートしていると動かないという事になる。 54940 これはクォートが要らない場合にはクォートしない様に修正すれば良い。 54941 54942 * complete: 引用符の中にいる時 addtail で閉じる引用符を入れる [#D0738] 54943 参照: #D0717 54944 54945 * ble.pp: bashrc の末尾で自動的に ble-attach するようにできるのではないか [#D0737] 54946 54947 % 実は trap -- '' RETURN を使えば bashrc 末尾でわざわざ 54948 % attach を実行する必要がなくなるのでは。 54949 % 54950 % x しかし自動的に検出する為には、bashrc の中にいるという事を検出しなければならない。 54951 % BASH_SOURCE を参照する方法だと --rcfile を使って bashrc を指定した時に使えない。 54952 % x history が初期化されているかどうか確認する方法だと、 54953 % bashrc の内部で history -n したりしている場合に失敗する。 54954 % x BASH_ARGC 及び BASH_ARGV を使うとどうなるか。 54955 % うーん。普通の source との区別が付かない。 54956 % 54957 % 実のところ --noattach の代わりのオプションを作るというのが現実的かもしれない。 54958 % 54959 % source /path/to/ble.sh --auto-attach --rcfile ~/.blerc 54960 % 54961 % 等の様な感じにする。もしくは 54962 % 54963 % if source /path/to/ble.sh --auto-attach; then 54964 % # ble configuration 54965 % fi 54966 % 54967 % 実際に bashrc の中に trap RETURN を記述して試してみたが、 54968 % bashrc の末端で trap RETURN は呼び出されない様だ。 54969 % trap DEBUG だと全ての行で実行されるので最後を判定できない。 54970 54971 trap RETURN を使う方法では実現は不可能。 54972 54973 或いは別の方法としてシェルの起動に使われた bashrc のファイル名が分かれば良いが、 54974 BASH_ENV には何も設定されていなかった。というかファイル名が分かったとしても、 54975 "最後に実行した行" を検知できなければ意味がない。。 54976 →と思ったが、別に bashrc かどうかとかは関係なくて、 54977 ble.sh がロードされた時の呼び出しスタックで一番浅い所を抜ける時に 54978 ble-attach を実行する様にすれば良い。 54979 54980 % 実はそのファイルの行数をカウント wc でカウントしておいて、 54981 % 一番最後の行を実行した時を DEBUG で検出すれば良いのかもしれない。 54982 % 54983 % 試してみた所 RETURN はやはり全然呼ばれない。 54984 % DEBUG は各行を実行する時に (前か後かは後で確認) 呼び出される。 54985 % 一番最後に実行される行 (LINENO) は一番最後の行番号である。 54986 % 54987 % - 但し、空行やコメントは実行されない。 54988 % - 一番最後の行の最後のコマンドが \ で分断されている場合は、 54989 % そのコマンドの先頭行が一番最後に実行される行である。 54990 % (一番最後の行ではなくて一番最後のコマンド) 54991 % - 一行に複数のコマンドが含まれている場合は、 54992 % それぞれのコマンドに対して実行される。 54993 % - どうも、やはりコマンドを実行する直前に実行される様であるので、 54994 % 一番最後のコマンドの最後に、というのは難しい。 54995 54996 trap DEBUG は、コマンドを実行する前に呼び出されるので使えない。 54997 54998 PROMPT_COMMAND を使えば良いのではないか…。 54999 しかしこれは多くの distro で変な物が設定される。 55000 マニュアルに記すとしても角の方に機能を乗せるに届けておくべき。 55001 少し試して見た限りでは実現できそうな気がする。 55002 実際に簡単に実装して動けば細かいところまで対応する事にする。 55003 55004 試して見た限りでは良好に動作しているが、 55005 何故か知らないが起動直後にジョブが走っている…。 55006 以下の様なメッセージが表示される。 55007 [1] 終了 '/usr/bin/stty' "$@" 55008 [2] 終了 tty 2> /dev/null 55009 55010 しかも初回のコマンド実行時だけである。 55011 手で local tmp; ble/util/assign tmp 'date' など実行しても現れない。 55012 取り敢えず ble/util/joblist.flush しておく事にした。 55013 55014 ところで、そもそも何故 source ble.sh を bashrc の上の方に書くのだったか? 55015 一番下で source ble.sh をすれば良いのではないか? 55016 元々は bind を上書きするつもりだったが、実のところ今は未対応である。 55017 まあ、余り考えない事にする。 55018 55019 2018-08-22 55020 55021 * 2018-08-05 complete: 補完後の文字列が実は index 以降に続いている時は、 [#D0736] 55022 それを吸収する形で補完を実行する。 55023 55024 | ただし、意図しない吸収を防ぐために INSERT が index 以降に 55025 | 全て揃っている場合にのみ吸収する。つまり部分的に INSERT の 55026 | 前半部分が続きにあるだけの時には吸収は行わないようにする。 55027 | 55028 | うーん。emacs の auto-complete の振る舞いを見ると、 55029 | もう少し柔軟にしても良いかもしれない…と思ったが、 55030 | 本当に auto-complete が柔軟に動いているのかどうかは確かめる必要がある。 55031 55032 これは結局 #D0735 の対応と同時に実装した。 55033 カーソルの右の文字列が、挿入文字列の先頭と一致する場合、 55034 また、挿入文字列の末端と一致する場合に吸収を行う。 55035 SUFFIX (addtail で追記した部分) と INSERT を別々に取り扱い、 55036 それぞれ吸収を行う様にした。 55037 55038 * 2018-08-17 auto-complete: vim-mode の繰り返しやマクロとの相互作用 [#D0735] 55039 ref `#D0724` 55040 55041 所で… vim-mode の繰り返しの設定だとかマクロだとかとの関係はどうなっているのか…。 55042 特に自動補完候補の表示だけで繰り返しが無効化されては困るし、 55043 また、実際に候補を確定した際に繰り返しが無効化されるのも余り良くない。 55044 マクロに関しては「候補を確定する」という操作が記録されると、 55045 自動再生の時には自動補完候補が生成されていないのでこれもまた変な事になる。 55046 この辺りは丁寧に考察する必要がある。 55047 55048 * 先ず初めに vim-mode の insert の繰り返しについて調べる。 55049 55050 | これは irepeat もしくは imap-repeat という枠組みで記録され再生される。 55051 | ble/widget/vi_imap/__before_widget__ を通じて記録が行われる。 55052 | つまり、実際に処理が実行される前に記録が実施される。 55053 | white list に登録されていないコマンドが実行された時、 55054 | 繰り返しは無効化される。 55055 | 55056 | さて、現状の auto-complete ではどの様な振る舞いになっているか。 55057 | 先ず初めに auto-complete はコマンド実行を介さずに勝手に導入される。 55058 | つまり、繰り返しはキャンセルされないが、補完した文字列が欠ける事になる。 55059 | 実際に試してみた所確かにそうなる事を確認した。 55060 | 55061 | 此処で改めて white list を調べる。 55062 | 補完によって実行される置換・挿入を 55063 | white list に登録されているコマンドの組み合わせで実行できるか。 55064 | 確認してみると delete-backward-char が存在しているので普通にできる。 55065 | 所で、記録されているのはキーと WIDGET のみなので、引数などは記録できない。 55066 | 或いは、引数の設定自体も登録してしまうという手もある… 55067 | 55068 | と思ったら引数を設定する widget は emacs.sh にしか含まれていなかった。 55069 | ble/widget/emacs/append-arg である。或いは complete 専用の widget を作るという手もある。 55070 | KEYS に削除する文字数を指定して、引数に挿入する文字列を指定するなど。 55071 | というか、KEYS に指定しなくても引数1と引数2に指定すれば良いのでは。。 55072 55073 もし実装するとしたら 55074 55075 1. auto-complete 側で挿入時に呼び出す hook を提供する 55076 2. vi_imap 側で hook を登録する。 55077 面倒なので hook を外したり入れたりは省略。 55078 取り敢えずの実装では vi.sh ロード時に入れてそのままにする。 55079 (或いは keymap initialize/finalize 的な所で実行しても良いが…) 55080 55081 うーん。確定する時に文字列をどの様に置換したかという情報を使うか。 55082 「現在位置以前に置換前の文字列がある時に限り置換後の文字列に置換する」という widget にする。 55083 この widget は complete を vi_imap で実行した時の再生動作としても使う事ができる。 55084 55085 * というかよく考えたら通常の complete でも vim-mode 55086 の繰り返しに支障を来すのではないか。 55087 現状の動作では、補完が途中で行われた場合には繰り返しがキャンセルされる。 55088 55089 | これに関してはどの様に処理すれば良いか微妙である。 55090 | white list に登録すると結果として irepeat 配列に登録されてしまうので、 55091 | 後で削除・上書きするか或いは complete を無効にするか、うーん。 55092 | それとも complete 自体をそのまま繰り返してしまうという手も考えられる。 55093 | 55094 | 一番無難なのは "置換前と置換後を記録しておいて一致する時だけ置換する" 55095 | という前項の案で出てきた widget に上書きするという物である。 55096 | もし complete が実行できない場合には complete は削除する。 55097 55098 1. widget "vi_imap/complete" を定義して、white list に登録する。 55099 この widget では内部で irepeat に対する操作の上書きを実行する。 55100 2. complete 側で実際の補完の実行に対して hook できる様にする。 55101 3. widget を呼び出す際に hook を一時的に設定してから呼び出す様にする。 55102 55103 うーん。どの様な情報を記録してどう置換するのが良いかわからなくなった。 55104 特にカーソルの右側に挿入文字列に一致する内容が存在する時の取り扱い。 55105 元の文字列が action/complete においてどの様な修正を許容するかの問題でもある。 55106 単に末尾に文字列を追記するという事を仮定しても良いのだろうか。 55107 或いは、そのような仮定に依存せずに実装する事ができればそれが一番良い。 55108 55109 問題は前方に hoge.txt があって、挿入文字列が "hoge.txt " だった時に、 55110 "hoge.txt" を吸収するかどうかという事にある。実際の所、吸収して欲しい。 55111 しかし addtail で末尾に文字列を追加する可能性を考えると、 55112 吸収の判定は "末尾一致" ではなくて "途中一致" になる。 55113 途中一致で給してしまっても問題ないだろうか…。 55114 55115 吸収の処理を明確にしておく必要がある。 55116 55117 | * 先ず空白類で区切られている物を吸収して欲しくはない。 55118 | 例えば挿入文字列が "a\ b\ c.txt" だった時に、 55119 | "a@ c.txt" で補完を実行した時に、 55120 | "a\ b\ c.txt@" という様に補完するのは不自然である。 55121 | 元々存在したクォートされていないスペースが、 55122 | クォートされたスペースに変換されてしまっている。 55123 | 55124 | 一般化すればクォートされていない物をクォートするのは禁止したい。 55125 | これを実現するためには挿入文字列に含まれる "正しい区切り目" 55126 | の単位で一致するかどうかを判定しなければならない。 55127 | しかし、これは実装が煩雑になるしユーザから見て分かりやすいか微妙である。 55128 | 55129 | 取り敢えず現状の実装では吸収可能範囲は最初の空白までと定める事にする。 55130 | 55131 | * 次に部分一致を吸収するかどうかという事である。 55132 | 55133 | 更に吸収すると仮定した時にどの様にそれを判定するかという事。 55134 | 例えば "hoge.txt " が挿入文字列で、前方に "@ogewaa" があったとして、 55135 | これを補完する事によって "hoge.txt@waa" になるという事。 55136 | やはりどうも不自然な様に思われる…。 55137 | 55138 | やはり先頭一致か末尾一致に限定したい気がするし、 55139 | そちらの方が一致範囲を決定するのが楽である。 55140 | うーん。INSERT と SUFFIX を区別するのが自然な気がしてきた。 55141 | 55142 | 更に INSERT の吸収と SUFFIX の吸収を別々に実装する。 55143 55144 結局吸収まで実装した。 55145 55146 * . による繰り返しの場合には irepeat をコピーする事によって実現されているので、 55147 irepeat の方さえ正しく登録する様にすれば問題は起こらない。 55148 55149 取り敢えず実装方針については固まった気がするので一つずつ実装していけば良い。 55150 実装したので動作確認を行う。 55151 55152 - 取り敢えず complete と auto-complete のそれぞれについて 55153 3i<C-[> でちゃんと繰り返される事を確認した。 55154 - . での繰り返しはどうか→ちゃんと動いている。 55155 55156 * 2018-08-17 auto-complete: キーボードマクロによる再生の対応 [#D0734] 55157 ref `#D0724` 55158 55159 qによるマクロでの自動補完のサポート? 55160 q によるマクロの場合には、これはキー操作のマクロであると考えれば、 55161 特に特別な操作は必要ない様に思われる。 55162 55163 | と思ったが、S-RET が間髪入れずに入力されると厄介な事になる。 55164 | 実際には delay があってから auto_complete keymap に入って、 55165 | その時点で S-RET をユーザが押した場合であっても 55166 | 再生時には delay や idle は実行されないので、 55167 | 元々の keymap において S-RET が再生されてしまう。 55168 | 55169 | vi_imap では既定では S-RET には何もないので単にエラーになる。 55170 | (#D0733 の修正後に) 実際にその様に振る舞う事を確認した。 55171 | ユーザが何か S-RET に割り当てている時には尚も変な事が起こる可能性がある。 55172 | 55173 | これに対してどの様な方針を考える事ができるか。 55174 | 55175 | a 特に対処は行わず単にキーボード操作を再生する。 55176 | 間髪を入れずに補完確定に使用した S-RET が再生される事により、 55177 | 補完が実施されなかったり別の操作が実行されたりする事については関知しない。 55178 | 55179 | b キーを入力した時の keymap の状態も一緒に記録する。 55180 | しかしこれはキーボードマクロを文字列で記録している事と相性が悪い。 55181 | これは駄目。 55182 | 55183 | c 推測補完 keymap に入る時にそれに対応するキーを仮想的に押す。 55184 | 特別なキーを用意しておいて ble-decode-key で特別なキーを押した事にする。 55185 | 55186 | 或いは、keymap に入るのに ble-decode-key を介して実行する事も考えたが微妙。 55187 | 推測補完は実際に補完候補が生成されるかどうか分からないので、 55188 | 最終的に keymap に入った時にのみ key を登録したい。 55189 | すると必然的にどの様な補完候補によって keymap に入るのかの情報が確定した状態で keymap に入る事になる。 55190 | 既に確定した情報を元に keymap に入る様な widget で処理する事になる。 55191 | しかしそれだと再生の時に困る。再生の時には自分で候補を見つける様な widget として振る舞いを変えなければならない。 55192 | 55193 | その様に思うのであれば実際に ble-decode-key は実行せずに、 55194 | keylogger に外部から手でキーを加えるという様にするしかない。 55195 | これは次の d に比べると不自然な実装になるので駄目。 55196 | 55197 | d 実は auto_complete keymap にいる時には何もしない様な ble-decode-key を実行すれば良いのでは。 55198 | 55199 | 例えば auto_complete という名前のキーを定義して、 55200 | keymap:vi_imap から auto_complete キーが押されたら、 55201 | 推測候補を生成して更に keymap に入る。 55202 | keymap:auto_complete で key:auto_complete が押されたら何もしない。 55203 | という動作にすれば良い。 55204 55205 ここは d の方針で実装するというので良いだろう。 55206 55207 * 特殊キーの名前は考慮の余地はある。 55208 55209 | 無節操に機能毎にキーを定義するのは憚られるので、 55210 | 何か名前空間の様な命名規則を使いたい気がする。 55211 | 55212 | complete に所属するので寧ろ complete_autocomplete だとか、 55213 | complete_suggest だとか complete_autosuggest 55214 | complete_auto など。或いは、comp_auto comp_suggest など。 55215 | 55216 | 或いは ac という名前を認めてしまえば、 55217 | ac_enter だとか ac_suggest だとかでも良い。 55218 | →今の所 ac は complete_ac_delay だけに使っている。 55219 | 行く行くはもっと分かりやすい物に変更したい。 55220 | 従って避けたい。 55221 | 55222 | - complete_auto 55223 | - complete_suggest 55224 | - complete_auto_enter 55225 | - complete_ac_enter 55226 | - comp_auto 55227 | - comp_suggest 55228 | - comp_autosuggest 55229 | 55230 | うーん。メニュー補完なども考えると、以下の辺りだろうか。 55231 | 55232 | - complete_menu_enter 55233 | complete_auto_enter 55234 | - complete_ac_enter 55235 | complete_mc_enter 55236 | - comp_menu_enter 55237 | comp_auto_enter 55238 | - comp_ac_enter 55239 | comp_mc_enter 55240 | 55241 | 一方で、既に keymap の名称は auto_complete にしている。 55242 | menu 補完については menu_complete とするだろう。 55243 | そう考えると auto_complete_enter 等だろうか。 55244 55245 auto_complete_enter にする事にする。 55246 55247 - done: auto_complete_enter の定義 55248 実は明示的に定義しなくても自動的に ble-bind したら kcode が生成される気がする。 55249 何れにしても core-complete.sh 側で kcode を知っておく必要があるので、 55250 generate-keycode (.gen-keycode から改名した) は呼び出し置けば良い。 55251 55252 - ok: _ble_decode_keylog_depth について 55253 自動補完から ble-decode-key を呼び出した時に 55254 _ble_decode_keylog_depth による判定はどうなっているか、と思ったが、 55255 よく考えたら自動補完は idle.do から起動されるので 55256 _ble_decode_keylog_depth=0 になっている筈で、 55257 普通に ble-decode-key を呼び出せば記録される様に思われる。 55258 55259 - done: ble-decode-key による記録 55260 55261 - done: sync モードの定義。 55262 ble-complete/auto-complete.impl sync 55263 55264 複数の手段が考えられる。 55265 55266 | a comp_type 等に新しい文字を入れる。 55267 | [[ $comp_type != *s* ]] && ble-decode/has_input && return 148 等の様に書き換える。 55268 | もしくは、頻繁にグロブを呼び出すコストを考えたらループの外側で判定を行って、 55269 | 何らかの文字列変数に入れて [[ $opt_async ]] && ... とする。 55270 | 55271 | b opt_async の様な感じの変数を定義する。 55272 | 実のところこちらの方が分かりやすいかもしれない。 55273 | これまでの comp_type も実はこれにした方が良いのではないかとも思うぐらい。 55274 | 55275 | 何故、comp_type に含まれている物を opt_* にしなかったのかについて再度考える。 55276 | 先ず初めに comp_type に含まれる文字は、親の complete で決まるのではなくて、 55277 | 呼び出した先の関数で決まる物であるという事。 55278 | 従って、呼び出し元で local だけ沢山して、 55279 | 呼び出された先の関数で値を設定するというのは分かりにくい。 55280 | 更に comp_type は補完関数からも参照される事を意識していた。 55281 | やはり同様に補完関数から参照される変数が多いのは分かりにくい。 55282 | つまり、comp_type 等に含まれるフラグたちは外部の枠組みから参照される物であり、 55283 | インターフェイスを小さくする為にフラグ変数で取り扱ったのであった。 55284 55285 やはり a の方法で実装する事にした。実装した。 55286 55287 - ok: よく考えると本当に中断しなくて良いのだろうか。 55288 例えばマクロ実行中に C-g を押して中断したくなったとする。 55289 その時に候補生成が中断しないと時間がかかってしまう。 55290 55291 % また入力時にゆっくり入力した時などに、 55292 % 1文字入力する毎に auto_complete_enter が記録されるとすると、 55293 % 実際に入力したときには候補が生成される前に中断されていたとしても、 55294 % マクロ再生時には候補を最後まで生成してから実行する事になるのではないか。 55295 % と思ったが、よく考えると auto_complete_enter は候補が最後まで生成されてからしか記録されないし、 55296 % また続きのキー入力がマクロ上にあったとしても ble-decode/has-input では判定できない。 55297 55298 特に気になったのは最終的に棄却された自動補完であっても、 55299 マクロ再生時に再現してしまうのは無意味ではないのかという事だったが、 55300 これは余り気にしても仕方がない事の様に思う。 55301 55302 唯一残る問題はマクロ再生を中断できないという事だが、 55303 考えてみればマクロ再生は元から中断できない。 55304 この部分を気にするのであればマクロ再生の仕組み自体を考え直す必要がある。 55305 55306 またマクロ再生を中断する仕組みさえ整えば候補生成は中断する程には遅くない気がする。 55307 中断しないという現在の実装で良いという事にする。 55308 55309 実際に動作確認する。 55310 55311 - 動いている。特に問題もない気がする。 55312 55313 2018-08-19 55314 55315 * vi-mode: 今気づいたのだが @x による再生がうまく行っていない [#D0733] 55316 特殊キーがそのまま文字列として挿入されてしまっている…。 55317 55318 調べてみると再生を行っているのは ble/keymap:vi/register#play で、 55319 其処ではちゃんと ble-decode-char を呼び出している。 55320 問題は CSI (M-^[) が単なる文字として通過してしまっているらしいという事。 55321 55322 ble-decode-char/csi/consume はちゃんと 155 を認識している様だ。 55323 ble-decode-char/.getent の振る舞いを見ていると、 55324 "M-^[27;1;1114154" まではシーケンスの続きがあるとしているが、 55325 "~" が来た時点で ent= になって、シーケンスが不正であるという結果になっている。 55326 55327 ? ok: 所で 1114154 というのは正しいのだろうか。 55328 printf '%x\n' してみると 11002a になっている。 55329 110000 は Unicode の最大値であり、これ以降に特殊キーを割り当てたはずなのでこれは正しい。 55330 55331 "~" の処理が怪しい。調べるとこれを担当しているのは 55332 ble-decode-char/csi/.decode である。 55333 55334 x ok: と、ここで ble_decode_MaskChar でマスクしている事に気づいてしまった。 55335 55336 % これは後でマスクしない様に修正する必要がある。 55337 % vim-mode の register#play で特殊キーが再生される事があるという注記付きで。 55338 % しかしそうだとしても ent= になってしまう事の説明が付かない。 55339 % もう少し調べる事にする。 55340 55341 改めて調べてみた所 ble_decode_MaskChar は特殊キーも入っている事が分かった。 55342 この名前は紛らわしいので変えるべきかもしれない。 55343 55344 ble-decode-char/csi/.decode で $_ble_decode_csi_args を出録してみたら、 55345 _ble_decode_csi_args がクリアされていないという事が分かってしまった。 55346 修正する。 55347 55348 * 何故か履歴項目の数が倍増している… [#D0732] 55349 55350 調べてみるとやはり 5c0333e が悪い様である。 55351 観察してみたがそんなに変更はしていない。 55352 HISTSIZE を二回変更すると二倍になるという事なのだろうか。 55353 また調べてみる事にする。 55354 55355 どうも現状の bashrc を使って調べると 5c0333e の変更を 55356 戻しても戻さなくても二倍になるのが再現する様である。 55357 更に、現在の ble.sh を直接 rcfile にすると二倍にならない。 55358 bashrc の中の記述との関連を調べる必要がある。 55359 55360 1. どうも histappend が設定されていると2倍になる 55361 2. histappend が設定されていないと HISTFILE に丸ごと書き込まれる 55362 55363 結局以下の設定だけで倍加する事が分かった。 55364 shopt -s histappend がない時には、 55365 起動時には二倍にはならないが最終的に二倍になる。 55366 55367 | HISTFILE=A.txt 55368 | HISTSIZE=100000 55369 | HISTFILESIZE=100000 55370 | shopt -s histappend 55371 | builtin history -n 55372 55373 55374 * 何故二重にロードされるのか。 55375 bashrc 内部で history -n を二回実行したとしても三倍になるなどの事はない。 55376 つまり、bashrc の中ではちゃんと新しく追加された項目を理解している。 55377 55378 * 不思議なのは何故昔の設定では二倍にならなかったのかという事。 55379 55380 | →改めて試してみた所、昔の設定でも再現する様だ。 55381 | と思ったが、間違えて問題が発生し初めた直後の commit で試していた。 55382 | 55383 | そう思って古いもので改めて試してみたが、 55384 | やはり履歴が二倍になる問題は依然として存在する。 55385 | shopt -s histappend の有無による動作も同じだ。 55386 | 55387 | 次に ble-0.1 でも試してみる事にする。 55388 | ble-0.1 では問題は発生していない。 55389 | ble-0.2 では問題は発生している…と思ったが、 55390 | 0.2 は問題の commit よりも後に分岐したのだから当然である。 55391 | 55392 | 問題の commit の前でも再現した事から、もっと遡る必要がある。 55393 | 55394 | b6815e0 問題なし (master: support-vi-mode マージ前) 55395 | 32037b9 問題あり (master: support-vi-mode マージ直後) 55396 | 25db43e 問題なし (support-vi-mode: 最後の master からのマージ) 55397 | c521012 問題なし (support-vi-mode: 最後の他からのマージ) 55398 | f894ca5 問題なし (support-vi-mode: 二分法) 55399 | c0c7f13 問題あり (support-vi-mode: 二分法) 55400 | 68b1ed5 問題なし (support-vi-mode: 二分法) 55401 | 48bee3c 問題なし (support-vi-mode: 二分法) 55402 | f0fcb54 問題なし (support-vi-mode: background load of history 直前) 55403 | 467dfbd 問題なし (support-vi-mode: background load of history 直後) 55404 | 55405 | これだった。これは結構大きな変更だったはず。。 55406 | うーん。しかし、本質的には (ユーザからの入力がない内は) 違いがない筈だと思ったが…。 55407 | 調べてみる事にする。 55408 | 55409 | と思ったらこれより前の version では 55410 | bleopt_history_lazyload に空文字列以外が設定されている時に、 55411 | history の load を遅延するから、bashrc の中では history を初期化していないのだった。 55412 | 55413 | 明示的に bleopt_history_lazyload= を指定して先に history を初期化させてみた所、 55414 | 実は bashrc の中から history を初期化しても問題は発生していないという事が分かった。 55415 | 何が鍵なのだろう…。 55416 | 55417 | 改めてまた確認してみた所、実は古い version ではサブシェルの中で history -n を実行していた。 55418 | 本体の方では history -n は実行していないのであった。 55419 55420 結論: 問題が発生し始めたのは idle を利用して history を load する様に変更してから。 55421 idle を利用する様にする前はサブシェルの中で history -n を実行していたので影響がなかった。 55422 55423 * さて、ここで考えるべきはサブシェルの中で history -n を実行する様に変更するか、 55424 或いは、親側で history -n を実行しながらも問題が発生しない方法を探すか。 55425 どちらにするのが良いのかという事である。 55426 55427 取り敢えず時間を計測する。10万項目を読み取るのに 0.100 秒かかっている。 55428 55429 というか落ち着いて考えてみれば今まで倍加していたという事は、 55430 今までだって二重に履歴を読み込んでいたのである。 55431 今、親シェルとサブシェルで別々に履歴を読み込み様にしても遅くなる事はない。 55432 当初想定していた速さにはならないが、面倒なので遅くても良いからサブシェルで読み取る事にする。 55433 55434 2018-08-18 55435 55436 * 2018-08-15 idle: ble/util/idle でバックグラウンドジョブ待ち機能を実装 [#D0731] 55437 history の初期化中に別の task が実行できる様になるはず。 55438 pid を指定してそのプロセスが生きているかどうかで判断する。 55439 もしくはファイル名を指定してそのファイルが存在するかどうかで判断する。 55440 55441 実はこれは既存の history のコードを流用すれば簡単に実装できるのではないか。。 55442 55443 以下の関数を追加した。 55444 - ble/util/idle.wait-filename filename 55445 - ble/util/idle.wait-file-content filename 55446 - ble/util/idle.wait-process pid 55447 - ble/util/idle.wait-condition command 55448 55449 idle.do についても整理した。 55450 55451 * auto-complete: bug bash-4.1 以下で auto_complete keymap に入ると、 [#D0730] 55452 何を押しても unbound keyseq の状態になる。 55453 isearch では問題になっていないので何か使い方が違っているという事だろうか…。 55454 auto_complete という名前の keymap が問題を引き起こしている? 55455 :isearch を含む関数は ble-decode/keymap:isearch/define しかない。 55456 これに同等な物は auto_complete に対しても定義している。 55457 55458 そうすると何処に違いがあるのだろう…。 55459 そもそも何故 __defchar__ や __default__ が呼び出されないのか…。 55460 調べてみると _ble_decode_auto_complete_kmap_ にちゃんと登録されていない。 55461 先ず何故か exit-default が 9 番に登録されている。 55462 次に self-insert が何処にも定義されていない。 55463 正常に動作している時には 5 項目登録されているが bash-4.1 以下では 4 項目しか無い。 55464 恐らく __defchar__ や __default__ が 9 になっていて、 55465 先に __defchar__ で登録した物が __default__ によって上書きして 4 項目になったのだ。 55466 55467 では、何故 __defchar__ や __default__ が 9 になってしまうのか。 55468 また isearch は何故平気なのか。 55469 55470 どうやら ble-decode-kbd/.get-keycode の連想配列を使わない実装が問題である様だ。 55471 後、何故か fallback implementation を使う条件判定が恒偽式になっていたので修正した。 55472 直した。寧ろ今まで何故動いていたのかが不思議であるが…。 55473 55474 * idle: 矢印キーを押しても is-stdin-ready 判定が偽になって idle.do が止まらない [#D0729] 55475 一体何が起こっているのか。ble-decode が保持しているキーが残っているという事なのか。 55476 調べてみると、別に ble-decode がキーを保持しているという訳では無いようだ。 55477 55478 これは恐らく bash の readline が保持しているのだろう。 55479 矢印キーに一致するかもしれないシーケンスは Bash が最後まで読み取ってから 55480 bind で登録された関数を呼び出しているのだろう。 55481 従って、bind で矢印キーを構成するバイトを処理している時は、 55482 既に stdin が空になっているので標準入力に何もないと判定されるのである。 55483 55484 decode の状態を見てキーシーケンスの途中でないかどうかチェックできる様にする必要がある。 55485 55486 % 特に非 ASCII 文字がキーシーケンスを構成する事はないと考えれば、 55487 % ble-decode-char の途中状態だけ確認すれば十分である。 55488 55489 観察した雰囲気では未確定の文字は (CSI であれ登録された物であれ) 55490 _ble_decode_char2_seq に溜められる様である。 55491 つまり、_ble_decode_char2_seq を見れば判定できる気がする。 55492 55493 と思ったが、うーん? どうも ble-decode-byte の方でも 55494 ESC と M- の区別をする為の仕組みが状態を保持している様子である。 55495 _ble_decode_byte__utf_8__code これだろうか…。 55496 調べると _ble_decode_byte__utf_8__mode の方が良い。 55497 _ble_decode_byte__utf_8__code の方は使用しなくなった文字が残留する様だ。 55498 さて、_ble_decode_byte__utf_8__mode は現在の input_encoding に依存している。 55499 従って input_encoding に対する要件を増やして現在の状態を取得できる様にする必要がある。 55500 55501 % よく考えたら ble-decode-key についても判定しなければならない。 55502 と思ったが、これについては途中状態であっても、 55503 ユーザからの入力を待っている状態なので、アイドルの内に入る。 55504 特に、ユーザが入力した時に一塊になって送信されてくる、 55505 文字やキーのデコードについてのみ途中状態になっているかどうかを判定すればよいのである。 55506 55507 * auto-complete: 既にカーソルの右に内容が入力されている時にわざわざ表示しない? [#D0728] 55508 55509 と思ったが、カーソルの右が第一候補に厳密に一致している場合にだけ自動補完を無効にしても、 55510 カーソルの右が第二候補以降に厳密一致している場合には対応できないし、 55511 或いは、"何れかの候補に厳密一致している場合には自動補完しない" という事にしても、 55512 本当に補完したい時に候補が出てくれず困るという事も考えられる。 55513 55514 思うに、オーバーレイではなくて挿入して表示してしまっているから振動してうるさいのである。 55515 後、振動してうるさいという事を考えるのであれば、 55516 やはりカーソルの右が厳密に一致している場合に限り自動補完を無効にするというので良い気がする。 55517 55518 * bugbash: POSIXLY_CORRECT に触るだけで bind -x C-i が無効になる謎 [#D0727] 55519 ref #D0726 55520 55521 Bash-4.2 -- 5.0 で ble.sh の中で再現する。 55522 unset POSIXLY_CORRECT をすると起こる。 55523 bash --norc においては未だ再現はできていない。 55524 55525 * bind -x '"\x89": ...' と bind -x '"\x9": ...' を同時に設定しても何も起こらない。 55526 55527 * cache.d/$UID/ble-decode-bind.40419.UTF-8.bind をコピーして来て、 55528 末尾に以下の関数を追加して、bash --norc から source しても再現しない。 55529 55530 function ble-decode/.hook { 55531 echo ble-decode/.hook: $1 55532 if (($1==4)); then 55533 # C-d で終了する 55534 echo exit 55535 exit 55536 elif (($1==20)); then 55537 # C-t で unset POSIXLY_CORRECT を実行する 55538 local POSIXLY_CORRECT=y 55539 unset -f echo 55540 unset POSIXLY_CORRECT 55541 fi 55542 } 55543 55544 もしかすると stty と相互作用している可能性もある。 55545 更に stty/enter やら uvw やら加えてみたが再現しない。 55546 55547 * ble.sh 本体の ble-decode/.hook を上記の様に書き換えてみた所再現した。 55548 結局以下のコードにまで縮小する事ができた。 55549 D0726.bind.source1 は bind -r が並んでいるファイルで、 55550 D0726.bind.source2 は bind -x が並んでいるファイルである。 55551 55552 | function ble-decode/.hook { 55553 | echo ble-decode/.hook: $1 55554 | if (($1==4)); then 55555 | echo exit 55556 | exit 55557 | elif (($1==20)); then 55558 | local POSIXLY_CORRECT=y 55559 | unset -f echo 55560 | unset POSIXLY_CORRECT 55561 | fi 55562 | } 55563 | source D0726.bind.source1 55564 | source D0726.bind.source2 55565 55566 更にこれを元に再現する rcfile を作成する。 55567 其処からどんどん縮めていくと結局上のコードに加えて 55568 以下の二つのコマンドさえあれば再現する様だ。 55569 55570 | set -o vi 55571 | shopt -s no_empty_cmd_completion 55572 55573 更に縮めると結局以下のコマンドで再現した。 55574 どうやら set -o vi だけでしか起こらない様だ。 55575 55576 set -o vi 55577 bind -x '"\C-t": unset POSIXLY_CORRECT' 55578 bind -x '"\C-i": echo C-i is pressed' 55579 55580 * 試してみると bind -x でなくても生じるようだ。 55581 55582 $ bash --norc 55583 $ set -o vi; bind '"\C-i": "echo hello"' 55584 $ echo hello # <---- echo hello is inserted by typing C-i 55585 hello 55586 $ declare -p POSIXLY_CORRECT; unset POSIXLY_CORRECT 55587 bash: declare: POSIXLY_CORRECT: 見つかりません 55588 $ 55589 Display all 4915 possibilities? (y or n) 55590 $ 55591 55592 * 取り敢えずバグ報告を書いてみる。 55593 55594 % Subject: Why `unset POSIXLY_CORRECT' unbinds the key `\C-i' in the `vi-insert' keymap? 55595 % Subject: [PATCH] Fix the bug that `unset POSIXLY_CORRECT' unbinds the key `\C-i' in vi-insert keymap. 55596 % 55597 % Here I show a reduced case. With the following settings: 55598 % 55599 % $ bash --norc 55600 % $ set -o vi 55601 % $ bind '"\C-i": "echo hello"' 55602 % $ bind -s 55603 % "\C-i": "echo hello" 55604 % 55605 % the string "echo hello" can be inserted by typing TAB. 55606 % 55607 % $ echo hello 55608 % hello 55609 % 55610 % However, after "unset POSIXLY_CORRECT" is executed, TAB loses its custom binding. 55611 % Then the readline function `complete', the readline default, is invoked by TAB. 55612 % 55613 % $ unset POSIXLY_CORRECT 55614 % $ 55615 % Display all 4915 possibilities? (y or n) <----- Here I typed TAB twice 55616 % $ bind -s <----- Now nothing is output 55617 % $ 55618 % 55619 % This behavior is reproduced in all the versions of Bash, that I tried, from 3.0 to the devel branch. 55620 % The behavior can also be reproduced by `f1() { local POSIXLY_CORRECT; }; f1' instead of `unset POSIXLY_CORRECT'. 55621 % The behavior is not changed regardless of whether the shell variable `POSIXLY_CORRECT' is initially set or not. 55622 % The behavior is only reproduced for `\C-i' (TAB) but not for other key sequences. 55623 55624 結局、バグというよりは仕様と諦めるしかない感じだという事が分かったので報告はしない。 55625 55626 * bash の中に入る。 55627 55628 unset POSIXLY_CORRECT は 55629 unset_builtin を呼び出す。 55630 更に unbind_variable が呼び出されて、 55631 makunbound が呼び出される。 55632 更に stupidly_hack_special_variables の中から 55633 sv_strict_posix が呼び出される。 55634 posix_readline_initialize (posixly_correct = 0); 55635 55636 何と明示的に C-i が上書きされている…。 55637 55638 /* Change the readline VI-mode keymaps into or out of Posix.2 compliance. 55639 Called when the shell is put into or out of `posix' mode. */ 55640 void 55641 posix_readline_initialize (on_or_off) 55642 int on_or_off; 55643 { 55644 if (on_or_off) 55645 rl_variable_bind ("comment-begin", "#"); 55646 #if defined (VI_MODE) 55647 rl_bind_key_in_map (CTRL ('I'), on_or_off ? rl_insert : rl_complete, vi_insertion_keymap); 55648 #endif 55649 } 55650 55651 うーん。これは微妙だ。 55652 つまり、POSIXLY_CORRECT は一時的に有効にしようとしても 55653 それに応じてシェルの設定を書き換えてしまうので後遺症が残る。 55654 「一時的に有効にして元に戻したら上書きした設定も元に戻る」 55655 という様にするのはこの様な実装では難しい。 55656 55657 % これは諦めるしかなさそうだ。 55658 % また、これを見る限りは、ユーザが一時的に POSIXLY_CORRECT を弄った場合でも 55659 % binding が失われてしまうので、それに対する対策をしなければならない。 55660 55661 或いは…元々刺さっているのが rl_insert の時には rl_complete にし、 55662 元々束縛しているのが rl_complete の時には rl_insert にする、 55663 というように条件判断を加える事はできないだろうか。 55664 つまり、デフォルトの束縛の時のみに切り替える様にする。 55665 55666 * bash を直してみた。 55667 55668 動作確認。基底の束縛ではちゃんと切り替わっている。 55669 ユーザの設定した束縛はちゃんと保持されている。 55670 55671 $ bash-dev --norc 55672 $ set -o vi 55673 $ bind -ps | grep C-i 55674 "\C-i": complete 55675 $ POSIXLY_CORRECT= 55676 $ bind -ps | grep C-i 55677 "\C-i": self-insert 55678 $ unset POSIXLY_CORRECT 55679 $ bind -ps | grep C-i 55680 "\C-i": complete 55681 $ bind '"\C-i": "echo hello"' 55682 $ echo hello 55683 hello 55684 $ bind -ps | grep C-i 55685 "\C-i": "echo hello" 55686 $ POSIXLY_CORRECT= 55687 $ bind -ps | grep C-i 55688 "\C-i": "echo hello" 55689 $ unset POSIXLY_CORRECT 55690 $ bind -ps | grep C-i 55691 "\C-i": "echo hello" 55692 55693 * 現状では ble.sh の対策は不完全だという事が分かったので修正を行う。 55694 55695 55696 2018-08-17 55697 55698 * decode: 何故かコマンド実行後に vim-mode において TAB が効かなくなる [#D0726] 55699 初め complete の問題かと思ったがそうでも無いようだ。後で対処する。 55700 55701 [原因] 55702 55703 | どうも調べてみた所、少しでも POSIXLY_CORRECT に触ると問題が発生する。 55704 | 先ず初めに関数内で unset POSIXLY_CORRECT すると駄目。 55705 | 関数内で local POSIXLY_CORRECT しても駄目。 55706 | 関数内で local POSIXLY_CORRECT してから unset POSIXLY_CORRECT しても駄目。 55707 | Bash-4.2 -- 5.0 まで同様に問題が再現する。 55708 | (Bash-4.1 以下は別の問題によって確認する事ができなかった。これは後で) 55709 | 55710 | さて、表面上は POSIXLY_CORRECT が定義されていなければ 55711 | 何も問題は起こらない様に見える。 55712 | 55713 | もう少し調べる。 55714 | ble.sh (bashrc 時に評価) に直接 unset POSIXLY_CORRECT を書いても問題は生じない。 55715 | ble.sh (bashrc 時に評価) で関数内から unset POSIXLY_CORRECT としても問題は生じない。 55716 | ble.sh (bashrc 時に評価) で関数内から local POSIXLY_CORRECT=y; unset POSIXLY_CORRECT としても問題は生じない。 55717 | ble-attach の直後に関数内から local POSIXLY_CORRECT=y; unset POSIXLY_CORRECT とすると再現する。 55718 | ble-attach の直後に直接 unset POSIXLY_CORRECT とすると再現する。 55719 | ble-attach の直前に unset POSIXLY_CORRECT としても再現しない。 55720 | ble-decode-attach; ble-decode-detach すると回復するという事が分かった。 55721 | 55722 | どうも POSIXLY_CORRECT を少しでも触ると bind -x \t が壊れる様である。 55723 55724 これは明らかに bash のバグである。しかも未だ修正されていない。 55725 55726 [対策] 55727 55728 取り敢えず unset POSIXLY_CORRECT の直後に再度 bind する事にすれば一応回避できる様だ。直した。 55729 55730 [報告] 55731 55732 Bash に報告する為にもう少し調べる事にする。 55733 先ず初めに bash --norc で再現させられるか。 55734 55735 $ bind -x '"\C-i": echo C-i is pressed' 55736 $ unset POSIXLY_CORRECT 55737 $ function f1 { local POSIXLY_CORRECT=y; unset -f echo; unset POSIXLY_CORRECT; } 55738 $ bind -x '"\C-t": f1' 55739 55740 うーん。再現しない。ちゃんと bind は有効である。 55741 上記の様に直接 unset POSIXLY_CORRECT としても、 55742 bind -x の内部から unset POSIXLY_CORRECT としても問題は再現しない。 55743 55744 * bind -x '"\t": ...' でも '"<生のtab>": ...' でも問題は発生しない。 55745 55746 * bind -x の中から直接 unset POSIXLY_CORRECT したらどうなるか? 55747 55748 $ bind -x '"\C-t": unset POSIXLY_CORRECT' 55749 55750 これで C-t を押してみたが、それでもちゃんと C-i は無効になっていない。 55751 stty 等の兼ね合いもあるのだろうか…。しかし、そうだとすると bind で直るのも変な気がする。 55752 55753 うーん。謎だ。 55754 55755 * 他に気になるのは、問題が起こっているのは本当に C-i だけなのだろうか。という事。 55756 調べてみた所取り敢えず日本語は入力できる様に見える。他に C0 制御文字も C-i 以外は全部大丈夫だった。 55757 55758 * core: ble/util/isfunction func && func ... を関数にできるのでは [#D0725] 55759 55760 ble/util/calliffunc 的な名前の関数で。 55761 これだと繋がっていて単語の切れ目が分からない。 55762 ble/util/call-if-func 55763 ble/util/call-iffunc 55764 ble/util/callif-func 55765 ble/util/callIfFunc 55766 ble/util/call-if-function 55767 ble/util/call-if-fun 55768 もっと良い動詞はないだろうか。存在する時だけ呼び出すという事が分かる様な。 55769 ble/util/try-call-function 55770 ble/util/try-function 55771 ble/util/try-fun 55772 ble/util/function#try 55773 ble/function#try 55774 ble/fun#try 55775 ble/function#callif 55776 ble/function#call-if 55777 ble/function#checked-call 55778 ble/function#check 55779 55780 * 2013-06-06 complete: 入力する側から候補を表示? [#D0724] 55781 55782 2018-08-17 取り敢えず履歴からの autosuggestions ではなくて、 55783 現在の位置で補完を実行した時の候補を表示する事にした。 55784 55785 | 実装しなければならないもの。 55786 | 55787 | 1 候補を生成する部分を既存の ble/widget/complete から分離。 55788 | 取り敢えず関数を分けた。 55789 | 55790 | * reject: 曖昧一致を無効にする必要がある。 55791 | →これについては、曖昧一致になっていても候補を表示する事にした。 55792 | 55793 | 2 complete 途中状態の keymap 55794 | これは実装した。region 着色の設定も行った。 55795 55796 取り敢えず実装した。 55797 55798 x fixed: 何故か完全一致しているのに候補が表示される… 55799 完全一致時を条件判断から抜いたら次の else に入っていた…。直した。 55800 x fixed: 候補が表示されると入力ができない? 55801 return の位置を間違えていた…。直した。 55802 x fixed: 毎回候補が再表示される? 55803 _ble_complete_ac_ins や _ble_complete_ac_word の取扱を調整した。 55804 x fixed: accept した時に _ble_edit_{ind,mark} が範囲外になる。 55805 ちゃんと調整するのを忘れていた。直した。 55806 55807 * done: addtail 迄実行するべき。 55808 55809 * done: 関数名の縮約を起こさない様にするべき。 55810 bleopt_complete_contract_function_names 変数を追加した。 55811 →実際にやってみた所、動作として微妙。 55812 やはり / 毎に候補を生成した方が使いやすいのではないか…。 55813 分からないが取り敢えず今の状態で使ってみる事にする。 55814 55815 * done: 後気づいた事は曖昧一致の時には候補は縮約するべきでない気がする。 55816 対応した。 55817 55818 * done: auto suggestion の場合 check-here による候補生成はしない方が良いのではないか。 55819 現在 generate では check-here と chek-prefix の両方で生成を行っている。 55820 generate を contexts 生成部分と、実際に generate する部分に分けるべきなのではないか。 55821 55822 これは以下の二つの関数を新しく作成して、 55823 呼び出し元でほしい文脈の種類に応じて呼び分ける事にした。 55824 ble-complete/candidates/get-contexts 55825 ble-complete/candidates/get-prefix-contexts 55826 55827 * done: completion-context 関数の関数名を 55828 ble-syntax/completion-context/generate に変更した。 55829 55830 * 2013-06-06 [自然解消] ble-line-info の描画のタイミングを ble-edit-draw.update と同じ時にする? [#D0723] 55831 それ以外の時に描画したければ、必要に応じてその場で明示的に描画させる。 55832 55833 2018-08-17 これは古い項目である。 55834 現在ではその様な実装になっている筈。いつか自然解消した。 55835 55836 2018-08-15 55837 55838 * 2018-08-13 どうやら POSIXLY_CORRECT を使えば unset 上書きを防御できる様だ [#D0722] 55839 https://stackoverflow.com/questions/35916983/how-can-you-use-pure-unset-shell-builtin-can-you-write-shell-scripts-that-are-i 55840 55841 試してみた所 POSIXLY_CORRECT=1 unset -f ... を使って unset 関数を削除できる。 55842 但し、POSIXLY_CORRECT=1 自体が POSIX 通りに環境に残り続ける所まで振る舞いとして一致している。 55843 なので明示的に unset POSIXLY_CORRECT をする必要がある。 55844 55845 また、POSIXLY_CORRECT が設定されていると、ble.sh が動かなくなるので、 55846 元から POSIXLY_CORRECT をキャンセルする様にする必要はあった。 55847 POSIXLY_CORRECT も IFS 等と同様に記録する必要がある。 55848 特に unset/set 状態も記録する必要がある。 55849 55850 * complete: 自動補完2 ble/util/idle 拡張 [#D0721] 55851 55852 現在の idle の枠組みを拡張する必要がある。 55853 現在の枠組みだと各タスクについて処理が終わるか 55854 ユーザの入力によって中断されたかの二通りしかない。 55855 ユーザの入力によって中断された場合には即座に 55856 idle 処理自体を中断している。 55857 55858 今何が必要だろうか。 55859 55860 * done: ring の様な物は欲しい。 55861 55862 優先順位は配列 _ble_util_idle_task に登録する番号の範囲で実現する事にした。 55863 現在の仕組みでは配列の添字の番号の若い方から順に調べて行って実行している。 55864 従って、優先順位が低い物を後ろに配置しておけばそれは自然に他の処理が全て終わってから実行される事になる。 55865 今後、処理を実行している途中でも task を中断して他のプログラムが動く様にする場合でも、 55866 添字の番号について条件判定などする様にすれば簡単に対応する事ができるはずである。 55867 配列を複数作るよりもずっとすっきりした実装になるのでこれを採用する。 55868 55869 * done: 定期的に task を中断する機能? 55870 55871 | 今までの処理では最優先の task しかなかった。 55872 | 従って、そのタスクが終わる迄制御を専有しても自然だった。 55873 | 今は優先度の高い ring にタスクが投入されたらそちらを先に実行する様にしたい。 55874 | 従って、定期的に task を中断して優先度の高い物がないかどうか確認したい。 55875 | 55876 | と思ったが、よく考えたら task を実行している途中に 55877 | 優先度の高い task が勝手に追加されるという事は考えにくい。 55878 | その様に考えると、実は ring を複数作るだけで、 55879 | 後は各 ring の task を回し続ければ良いのでは。 55880 55881 これは今の所は必要にならないので実装しない。 55882 というか実は ble_util_idle_status に R を設定して 55883 return すれば良いだけかもしれない。 55884 その機能だけ実装した (ble/util/idle.continue) 55885 55886 * done: sleep の実装が欲しい。 55887 55888 [機能の議論] 55889 55890 sleep 時間の記録方法と時刻の設定方法。 55891 55892 | 1 時刻の計測方法 55893 | 先ず時刻で測るのか、時間で測るのか。 55894 | 55895 | 時刻で測るとすると保証できるのは date であり秒単位である。 55896 | GNU coreutils の date だとミリ秒までは少なくとも分かる。 55897 | Linux だと /proc/uptime の最初の列により 10 ミリ秒まで分かる。 55898 | 55899 | 調べると /proc/driver/rtc という物もあるようだ。 55900 | https://stackoverflow.com/questions/5242296/how-can-i-get-system-time-from-a-proc-file 55901 | と思ったが、実際に見てみると全然 microseconds の情報はない。秒までしか分からない。 55902 | 55903 | 仕方がないので遅延も考慮に入れて ble/util/sleep に指定した時間の和で実装し、 55904 | 定期的に /proc/uptime 等を参照して較正するという方法を用いる事にする。 55905 | 特に較正は後回しで良い。 55906 | 55907 | 2 sleep の指定方法。 55908 | ble/util/idle.set-sleep を呼び出してそのまま return する? 55909 | return はしなくても良いかもしれない。 55910 | 特別な終了ステータスを使う事も考えたが、 55911 | 結局 sleep 時間を別に指定しなければならない訳で、 55912 | そうしたら、sleep 時間が設定されているという事だけで、 55913 | 終了ステータスを見なくても sleep が要求されているという事が分かるから。 55914 | 55915 | sleep を指定したとして、それをどの様に記録するか。 55916 | 55917 | a 例えば _ble_util_idle_task の配列に入れる文字列を 55918 | "数字:何とか" 55919 | の形にする等すれば良いだろうか。そうすると、現在走っている物についても、 55920 | 区別が付くように "R:command" という形式に変更する必要がある。 55921 | 55922 | 現在の実装では _ble_util_idle_task 配列は完全に隠蔽しているので、 55923 | 変更は局所的で済む。 55924 | 55925 | b その他の方法としては別の配列に状態を記録するという物もある。 55926 | 然し、これは管理が面倒であるし、bash 配列の効率が悪い使い方になっている。 55927 | 55928 | c 或いは、状態毎に配列を作成するという手もある。 55929 | 55930 | 実行しているタスクが増加して来た場合には、 55931 | 効率の問題から、状態毎に配列を作成するのが良さそうであるが、 55932 | 今の所は一つの配列で管理した方が楽である様な気がする。 55933 | 特に、状態毎に配列を分けるという様にすると、 55934 | 配列を移動したりなどの面倒な処理を実装する必要がある。 55935 | 55936 | つまり、取り敢えずは a の方式で良いのではないだろうか。 55937 55938 [実装方法の議論] 55939 55940 取り敢えず最初に sleep を実装する事にする。 55941 55942 | どの様にしたら良いのかで一番難しいのが時刻の分解能が低い時にどのように調整を行うかである。 55943 | 特に自分自身が呼び出す sleep の時間の積算によって時間が多少測る事ができるので、 55944 | それを使って待ち時間を計測しつつも、それだと遅延が起こるので 55945 | 分解能の低い時計によって修正を行って時間を測る。 55946 | 55947 | と言っても分解能の低い時計でどの様に修正する事ができるだろうか。 55948 | 55949 | a 例えば一つの方法としては基本の時計として sleep の積算を使用して、 55950 | 同時に低分解能の時計を用いて遅延が検出できたらその分時計を進めるという方法である。 55951 | この方法の問題は sleep を設定した直後に遅延が検出されて時計の針が進められると、 55952 | sleep の時間が縮まってしまう事にある。 55953 | 55954 | b その様に考えると各 sleep について遅延を検出したら時計の針を進める、 55955 | というようにした方が良いのではないだろうか。 55956 | では各 sleep について計測するにはどの様にしたら良いか。 55957 | 先ず、sleep を呼び出してからの ble/util/sleep の積算がある。 55958 | 55959 | 要するに秒 (低い方の解像度) が2回以上変化した後は、 55960 | 低解像度の時計によるチェックを行うという事? 55961 | 55962 | うーん。sleep 時間の表現をどの様にすれば良いのか。 55963 | 一つの方法は S<終了時刻ミリ秒> だったが、 55964 | これだと厳密に測るのが難しい。 55965 | 55966 | もう一つの方法は S<終了時刻(sleep累積)> だったが、 55967 | これだと sleep 累積の較正時に跳びが生じてしまう問題がある。 55968 | 55969 | うーん。sleep 時間の長さに応じて種類を変える? 55970 | 1秒以上の sleep の場合には較正を受ける事にして、 55971 | 1秒未満の sleep の場合には較正を受けない事にする。 55972 | 較正を受ける sleep に関しては S<絶対時刻> にして、 55973 | 較正を受けない sleep に関しては s<sleep累積> にする。 55974 | 55975 | sleep 累積に関してはその idle ループの初回には 55976 | 何らかの仮定を置かなければならないので、 55977 | 実際に秒の目盛りが変わった瞬間にその仮定をシフトできる仕組みを整えると良い。 55978 | 55979 | 例えば最初に initial_offset=0.5 で始めて、 55980 | そこから accumulated_sleep を累積する。 55981 | 最初に秒が切り替わった時に shift = 1.0 - accumulated_sleep だけ "シフト" を実行する。 55982 | "シフト" 後には全ての <終了時刻> は shift だけ加算して考える。 55983 | また sleep を登録する時には shift だけ引き算して登録する。 55984 | 55985 | 55986 | - sleep 累積のカウンタを作る。 55987 | これは一つの idle.do 呼び出しに対して毎回独立にカウントする。 55988 | (idle.do と idle.do の間の時間間隔が分からないので) 55989 | つまり、毎回リセットする。 55990 | 55991 | - sleep 累積カウンタを参照して秒以下を拡張した時計を作る。 55992 | 前回の秒切り替わり時の sleep 累積カウンタを記録する。 55993 | 実はここで shift を入れてしまっても良いのでは。 55994 | 55995 | - sleep 累積カウンタをできるだけ正確に測る為に、 55996 | 平均の sleep 一回辺りの遅延時間も計測する? 55997 | 然し、実際の処理時間の分布はどうなっているだろう。 55998 | 重い処理が一回走ると過剰評価になるなどの事だと困る。 55999 | 結局難しいのではないか…。 56000 56001 [実装] 56002 56003 * 初めから二種類の sleep を区別する事にした。 56004 実際の時計に基づく sleep と、アイドル時間に基づく sleep。 56005 56006 前者の sleep に関しては、以下の様な状況に於いて 56007 実質的に sleep 時間が短くなり実行されない事があることに注意する。 56008 56009 - 実際の時計に基づく sleep は高精度の時計が利用できない時がある。 56010 その場合にはアイドル時間を用いて秒単位以下をできるだけ再現しようとするが、 56011 ずれがあるので時計自体の値が元々の精度以下で跳んだりする事がある。 56012 56013 - 重い処理が走るなどして時間が経過した時。 56014 56015 後者の sleep に関しては、アイドル状態にならなければ幾らでも実行の遅延が長くなる可能性があるが、 56016 必ず或る一定以上の sleep を入れる事が望ましい場合に使う。 56017 56018 * アイドル時間については ble/util/sleep 56019 * 実際の時計についてはできるだけ軽量な方法でシステムから取得する。 56020 精度が足りない場合はアイドル時間を併用する。 56021 軽量な手段がない場合にはアイドル時間で代用する。 56022 56023 Note: 因みに ble/util/sleep は 4.0 以上で read -t 0.1 (例) を使う。 56024 ble/util/idle の実現に使う polling (read -t 0) も 4.0 なので、 56025 今回の場合には常に ble/util/sleep は軽量な方法で実装されていると考えて良い。 56026 56027 取り敢えず実装した。 56028 56029 [動作確認] 56030 56031 時計を動かすサンプルで確認した。 56032 初め動かなかったが幾つか修正したら動く様になった。 56033 56034 * done: 割り込み待ち状態というのも欲しい。 56035 56036 | 例えば補完が終了した状態になったとすると、 56037 | 暫くは処理をしなくても良いが、 56038 | sleep で定期的にチェックするのも変である。 56039 | 何かのイベントが起こったら再びチェックするという様にしたい。 56040 | 56041 | と思ったが、取り敢えずの所は毎回 idle で順番が回ってきた時に 56042 | チェックして未だだったらスキップするというので良い様な気もする。 56043 | 本当だろうか。例えば同じリングに A, B, C が登録されているとして、 56044 | 56045 | 1. A を呼び出して条件が満たされていないのでスキップ 56046 | 2. B の処理を暫くしてその後で待機状態になる 56047 | 3. C を呼び出すが条件が満たされていないのでスキップ 56048 | 56049 | と処理をした時に、B の処理をしている間に A 条件が満たされているかもしれない。 56050 | 従って、再び A, B, C とループを回したい。 56051 | かと言って無限ループにすると高頻度で割り込みをチェックする事になり非効率的だ。 56052 | 56053 | うーん。結局 sleep で定期的にチェックするという実装になるだろうか。 56054 56055 →これは sleep で処理する。 56056 次のユーザ入力が来るまでは絶対に再起動しないと分かっている場合には、 56057 sleep 0.010 の様な物が無限に続くのは効率が悪いので、 56058 そういう状態を作成するのが良いのではないか。 56059 56060 例えば "I:command" の様にする。 56061 56062 これは実装した。動作未確認。 56063 56064 * 他にサブシェルをバックグラウンドで実行している間待つ、 56065 という実装を考えても良いが今の所は後回し。 56066 56067 これを実装すれば history の subshell を実行している間に、 56068 core-complete ロード等の処理を継続することができるはず。 56069 56070 2018-08-13 56071 56072 * complete: 自動補完1 LASTWIDGET [#D0720] 56073 56074 取り敢えず LASTWIDGET は実装する事にする。 56075 56076 | LASTWIDGET の実装方法とし複数を考える事ができる。 56077 | 基本的には一番最後に呼び出された ble/widget/* であるが、 56078 | "呼び出す" というのはどういう事かというのが問題になる。 56079 | 56080 | 1 例えば、或る ble/widget/* の中で別の ble/widget/ を呼び出した時にはどうするのか。 56081 | 次回の widget において、呼び出し元の widget を LASTWIDGET とするのか、 56082 | それとも一番内側で呼び出した widget を LASTWIDGET とするのか。 56083 | 56084 | 2 またマクロによって呼び出した ble/widget の場合にはどうするのか。 56085 | マクロ実行後に LASTWIDGET をどの様に設定するのか。 56086 | 例えば、マクロ内部で一番最後に呼び出した widget を LASTWIDGET にするのか、 56087 | それとも、マクロの呼び出し自体を LASTWIDGET とするのか。 56088 | 56089 | 3 マクロ実行に関しては、更に別の観点からも LASTWIDGET をどうするかがある。 56090 | マクロ内部で呼び出される widget から見える LASTWIDGET は何なのか。 56091 | マクロ実行の開始直前の widget なのか、 56092 | それともマクロ内部で直前に呼び出された widget なのか。 56093 | 56094 | これを考えるためにはどのような用途で LASTWIDGET が必要になるのかという事を考えれば良い。 56095 | 56096 | 1 一番よくありそうなのは行移動の場合である。 56097 | 連続する下カーソルによる移動の時には移動を開始した時の列の位置が保持される。 56098 | 途中で短い行があって列が左に移動したとしても、再び長い行に移動した場合には、 56099 | 元々の列の位置を回復する。 56100 | 56101 | これを実装するためには「連続する行移動」を判定する必要があって、 56102 | そのために LASTWIDGET を参照する。 56103 | 56104 | 2 今回必要になるのは auto complete をどの様に起動するかである。 56105 | 直前が文字入力の時または明示的な要求がある時に限って auto complete を起動したい。 56106 | カーソル移動などをした先で毎回 auto complete が起動していたのではうるさい。 56107 | 56108 | 思うにこれらの用途であれば ble/widget/ の内部で 56109 | 正式に (実装の間借りなどではなく) コマンドとして widget が呼び出されたのであれば、 56110 | それを LASTWIDGET に設定して良いという気がした。 56111 | 例えばマクロの場合には中で呼び出される一つ一つのコマンドに対して全て LASTWIDGET が更新される。 56112 | 或いはユーザに依る widget の実装が複数の既存の widget を呼び出す事によって実装されるならば、 56113 | その呼び出された個々の widget において LASTWIDGET が更新されるという様にする。 56114 | 56115 | これだと auto complete がマクロの実行直後に起動されて妙な気もするが、 56116 | しかし一概に auto complete が起動されない方が自然とも決めがたい。 56117 | LASTWIDGET の種類に複数あったり条件によって振る舞いが変わったりするようなのだと、 56118 | 何だかよくわからない事になってしまうので、ここでは明快さを取って、 56119 | 内部で呼び出される場合にもちゃんと LASTWIDGET を更新するという実装にする。 56120 56121 [仕様] 56122 56123 - マクロ内部で呼び出されたコマンドによっても LASTWIDGET は設定される。 56124 - widget から ble-decode の手続きによって呼び出されたコマンドによっても、 56125 LASTWIDGET は設定される。 56126 56127 Emacs でどのような振る舞いになっているかについても改めて確認しておく。 56128 - this-command, last-command, real-last-command がある。 56129 - (call-interactively ...) で呼び出せば last-command が更新される 56130 …というような事だったと思う。 56131 56132 [現状の実装] 56133 56134 現状の実装についても確認しておく。 56135 特に WIDGET= を含む関数について確認すれば良いだろう。 56136 56137 | ble-decode には以下の三つの関数が存在している。 56138 | - ok: ble-decode-key/.invoke-command 56139 | - ok: ble-decode-key/.call-widget 56140 | - ok: ble-decode/invoke-widget -> ble-decode/widget/call-interactively 56141 | 56142 | うーん。これらの関数の使い分けについて考える。 56143 | ble-decode/invoke-widget は vi.sh から使われている。 56144 | 特に bracketed-paste の実装から使われている。 56145 | ble-decode-key/.invoke-command は内部から使われている。 56146 | キーシーケンスが完成した時にそれに対応するコマンドの呼び出しに使われる。 56147 | ble-decode-key/.call-widget は内部から使われている。 56148 | _ble_decode_{key,char}__hook 経由の呼び出しで使われる。 56149 | 56150 | | ble-decode-key/.invoke-command | DB | 56151 | | ble-decode-key/.call-widget | DB | 56152 | | ble-decode/widget/invoke | B | 56153 | 56154 | - D: keylog depth の更新を行う。内部では keylog は実行されない。 56155 | invoke-widget において depth の更新がないのは、 56156 | invoke-widget はそもそも widget の中から呼び出される事を想定しているので、 56157 | 既に keylog depth は設定されている筈だから、わざわざ更新しなくても良いという事である。 56158 | 56159 | - B: __{before,after}_widget__ の呼び出しも行う。 56160 | これは keymap 特有の設定である。 56161 | 何故 ble-decode/widget/invoke で必要なのかは不明。 56162 | 56163 | 取り敢えず整理した。関数名も多少変えた。 56164 | ble-decode/invoke-widget は ble-decode/widget/call-interactively に改名して、 56165 | 他に hook を実行しない物として ble-decode/widget/call を追加した。 56166 | 56167 | ble-edit 56168 | - done: ble/widget/quoted-insert.hook 56169 | WIDGET を self-insert に上書きして self-insert に委譲している…。 56170 | 始末が悪いので ble-decode 側の関数を経由して呼び出す様にした方が良いか? 56171 | これについては後で考察する事にする。 56172 | →やはり self-insert は内部で WIDGET を触っていないので、 56173 | わざわざここで self-insert を WIDGET に設定する意味がない。単に削除した。 56174 | - done: ble/widget/bracketed-paste.proc 56175 | 同様。これは処理を軽くする為に一回設定すれば OK な様にしている。 56176 | 実は self-insert の方を改良して複数の文字を処理できる様にしても良いのでは。 56177 | という気もする。と思ったが、下手に実装を変えるのも面倒そうだ。 56178 | というか、そもそも self-insert を呼び出すのに WIDGET を設定している理由は何だったのか…。 56179 | 56180 | これらの関数の中では WIDGET は参照されていない様に見える。 56181 | 何らかの hook が呼び出されるという事もないので、 56182 | 別の関数から参照される可能性もない。 56183 | 何故 WIDGET が設定されているのだろうか。 56184 | これは vi.sh における同等の処理との対称性から無駄に設定されているだけだろうか。 56185 | 56186 | →これも self-insert を呼び出しているだけなので WIDGET を設定する必要はない。 56187 | 56188 | keymap/emacs.sh 56189 | - ble/widget/emacs/bracketed-paste.proc 56190 | これは上記と同様である。 56191 | safe map の物と何が違うのかと思ったら、どうも update-mode-name を実行するという事の様だ。 56192 | 他には特に機能はない。 56193 | 56194 | * fixed: 何と emacs の bracketed-paste mode で二重に挿入するバグだった。 56195 | 結局 ble-edit.sh の brackated-paste.proc を呼び出すのであるから 56196 | 此処で self-insert を呼び出す必要は最早ないのであった。 56197 | 従って、そもそも WIDGET に此処で触る必要もなかった。 56198 | 修正して別のコミットにした。後で 0.2 にも適用する。 56199 | 56200 | keymap/vi.sh 56201 | - done: ble/keymap:vi/imap-repeat/process 56202 | これはまあマクロの呼び出しと思って良い。 56203 | invoke-widget か何かを経由して呼び出す様に変更したい。 56204 | 速度が気になるかもしれないが後で考える。 56205 | これは ble-decode/widget/call を用いて実装する事にした。 56206 | 56207 | x fixed: 動作確認をする。と思ったら ble/widget/ble/widget が呼び出されてしまう。 56208 | 仕様を変更する事にした。今までは内部で ble/widget/ を付加していたが付加しない。 56209 | ble-decode/widget/call{,-interactively} ではフルの関数名を受け取る事にする。 56210 | 56211 | o 取り敢えず動作するという事を確認した。 56212 | 56213 | - ok: ble/keymap:vi/imap/invoke-widget 56214 | これは何だろう…。 56215 | これはどうやら bracketed-paste から呼び出す為に使用している。 56216 | ble/keymap:vi/imap-repeat/push を呼び出す invoke-widget である。 56217 | 一方で、quoted-insert などからも使えそうに見えるが使っていない。 56218 | - done: ble/widget/vi_imap/quoted-insert.hook 56219 | - done: ble/widget/vi_imap/bracketed-paste.proc 56220 | これらは上記の通り ble/keymap:vi/imap/invoke-widget 経由で実装できそう。 56221 | 後で確認をして実装を切り替える。 56222 | →bracketed-paste.proc に対してはは速度低下を防ぐために 56223 | invoke-widget-charwise という関数を追加した。 56224 | 56225 | - done: ble/keymap:vi/repeat/invoke 56226 | コマンド . による繰り返し。これは大分特殊だ…。 56227 | 一番最後に ble-decode/invoke... 経由で呼び出せる様にできるかもしれない。 56228 | うーん。個別に LASTWIDGET を設定するか、ble-decode の関数を呼び出して設定するか微妙。後で考える。 56229 | 56230 | 中で KEYMAP 等の変更がある。ble-decode/widget/call を使うと現在の keymap が使用されてしまうので、 56231 | 結局自分で全部設定した方が良さそうである。自分で LASTWIDGET の設定を行う事にした。 56232 | 56233 | - ok: ble/keymap:vi/commandline/__before_command__ 56234 | これは cmap でキャンセルをするために WIDGET= としている。考えなくて良い。 56235 | 56236 | * done: これは ble-decode 側でキャンセルする為の関数を用意した方が良いのではないか。 56237 | そんなに重い処理でもないので関数化して良いだろう。 56238 | また、ble-decode 側で処理をキャンセルするという仕組みを明示的に提供するべき。 56239 | 後々の変更で WIDGET= をキャンセルと見做すという仕様が曖昧になると行けないので。 56240 | 56241 | また Wiki で WIDGET= でキャンセルできるという事を言及していたかもしれないと思ったが、 56242 | 確認してみた所 WIDGET の設定に関しては元から言及が無い様である。OK 56243 | 56244 | というか改めて調べてみた所 ble-decode 側では特にキャンセルについては意識していなくて、 56245 | vi.sh の側で勝手にハックしているだけという様な気がする。 56246 | また、vi.sh 側で実行しているのはキャンセルというよりは、寧ろ処理が完了しましたという事の気がする。 56247 | 現状の実装では __after_command__ が呼び出されていて、それは "キャンセル" にそぐわないのではないかと思ったが、 56248 | 実際にやっている事は、処理を行ってからキャンセルという様な事なので、 56249 | これは実質処理が完了しましたという事であって、キャンセルではないので、 56250 | 寧ろ __after_command__ を呼び出すという動作で正しいのである。 56251 | 56252 | 新しい関数 ble-decode/widget/suppress-widget を定義した。 56253 | 56254 | * done: ble/keymap:vi/commandline/__before_command__ は 56255 | ble/keymap:vi/commandline/before-command.hook に改名した。 56256 | 伴って ble/lib/vim-surround.sh/async-read-tagname/.before-command.hook も改名した。 56257 | 56258 | * done: __before_command__ を __before_widget__ に解明する可能性? 56259 | 56260 | これは過去にも議論があった筈である。その時の結論は何だったか。 56261 | 特に __before_command__ に関しては、言及はあるもののちゃんと議論はしていない様だ。 56262 | 議論していたのは WIDGET と同様に BEFORE_WIDGET や AFTER_WIDGET も定義するかどうか。 56263 | これは元々定義していなかったので、それまで通り定義しないという事になった。 56264 | (必要になった時に定義すれば良い) 56265 | 56266 | 特に __before_command__ 等の名前にしておく理由もない様なのでこの際変更する事にする。 56267 | 56268 | * done: rename ble-decode/invoke-widget to ble-decode/widget/invoke 56269 | 実は ble/keymap:vi/imap/invoke-widget 等との対称性もあったようだが気にしない。 56270 | 56271 | lib/vim-surround.sh 56272 | - ok: ble/lib/vim-surround.sh/async-read-tagname/.before-command 56273 | これは上記 commandline/__before_command__ と同じ。気にしなくて良い。 56274 | →これは結局 commandline/__before_command__ (commandline/before-command.hook) と同様に、 56275 | ble-decode/widget/suppress-widget を呼び出す事にした。 56276 | 56277 | * ok: 関数名は変えても良いかもしれない。 56278 | →改めて確認した所、先の __beore_command__ の場合には直接 keymap に登録していたが、 56279 | 今回の .before-command に関しては _ble_keymap_vi_cmap_before_command 経由で呼び出される関数なので、 56280 | その儘の関数名で良かったのであった。 56281 | 56282 | - ok: ble/widget/vim-surround.sh/nmap/csurround.record 56283 | これは ble/keymap:vi/repeat/record で記録される内容を弄る為に使用している。 56284 | これも気にしなくて良いだろう。 56285 | 56286 | * ok: 本当は ble/keymap:vi/repeat/record 側から特別に設定する手段を与えるべきなのかもしれない。 56287 | 或いは ble/keymap:vi/repeat/record で設定された内容を後で上書きするべき? 56288 | 56289 | 調べてみると ble/keymap:vi/repeat/record は内部で 56290 | ble/keymap:vi/repeat/record-normal を呼び出していて、 56291 | その中で repeat 配列の 2 番目の要素に WIDGET が設定される。 56292 | 56293 | | そして repeat は、vi_imap の時には _ble_keymap_vi_repeat_insert に、 56294 | | それ以外の時には _ble_keymap_vi_repeat に代入される。 56295 | | ble/widget/vim-surround.sh/nmap/csurround.record の中では 56296 | | vi_imap ではないという前提の元で、ble/keymap:vi/repeat/record が呼び出された後に、 56297 | | _ble_keymap_vi_repeat を修飾している。しかし、 56298 | | 56299 | | _ble_keymap_vi_mark_suppress_edit が設定されている時等に勝手に書き換えてしまうとまずいのでは? 56300 | | 調べてみると _ble_keymap_vi_mark_suppress_edit=1 が設定されるのは 56301 | | ble/keymap:vi/call-operator や ble/widget/vi_xmap/paste.impl において、 56302 | | 外側で record を実行したい時に内部で record されると困るという場合に使っている。 56303 | | つまり、内部で変な repeat 情報を記録したとしても結局外側で上書きされてしまうという事。 56304 | | その様に考えると実は record の内部で suppress している意味は実はないのではないか…とも思うが。 56305 | | 唯、keymap が途中で変化した場合などには上書きが保証されない…。うーん。どうなっているのか。 56306 | | うーん。良くわからないが実装の綺麗さを考えると csurround の側でもちゃんと、 56307 | | record の実装と整合する様にしておくべきの気がする。 56308 | 56309 | 一応 ble/widget/vim-surround.sh/nmap/csurround.record に条件は付加した。 56310 | 一方で後で WIDGET を修飾する様に修正すれば良いというのはやめる事にした。 56311 | record が参照する為に WIDGET を設定するというのは、 56312 | 実の所 record のインターフェイスの問題であって、 56313 | ble-decode の仕様とは切り離して考えても差し支えないだろうという事と、 56314 | WIDGET が何番目に格納されるのか、というのを外側の枠組みが意識するのはよくないという事。 56315 56316 2018-08-06 56317 56318 * 2018-08-05 complete: ble-complete/util/escape-specialchars を refactor [#D0719] 56319 56320 * 2018-08-05 complete: 実は completion-context の方で既に --prefix= 等に対応していた… [#D0718] 56321 56322 まあそれはそれで良い様な気がする。 56323 56324 1. completion-context 側で生成した = 以降が一番優先度が高くて、 56325 2. それで候補が無ければ単語全体に対する補完候補が生成されて、 56326 3. それでも候補がなければ = または : 以降に対する補完候補が生成される。 56327 56328 もし completion-context の方の条件に引っかかれば実質 1.2. の優先順位であり、 56329 そうでなければ 2.3. の優先順位ということで良いのではないだろうか。 56330 56331 但し、似たような処理がある事をソースコード内に注記しておくと良いだろう。 56332 56333 * 2018-08-05 complete: 引用符内のエスケープなどを適切に処理する [#D0717] 56334 56335 % shopt -s complete_fullquote に対応する 56336 % →shopt -s complete_fullquote はそういう機能ではなかった。 56337 % シェルの特殊文字を補完時に適切にクォートするそうである。 56338 % 少し試してみた所、結局何が変わるのか良く分からなかった。 56339 % 何れにしてもクォートするべき物というのは明らかのはずで、 56340 % 現在の実装ではちゃんとやっている筈なので気にしない。 56341 56342 - done: initialize: 引用符内のエスケープ 56343 - ok: initialize: COMPS が保持されない時のエスケープ 56344 これは元からちゃんとなっていた。 56345 56346 - done: ble/string#escape-for-bash-escape-string 56347 取り敢えず次の物を置換する事にする: \a \b \e \f \n \r \t \v \\ \' 56348 56349 - done: ble/string#escape-for-bash-* についてテストを行う。 56350 56351 - ok: bash-4.4 の ${var@E} を使えるかどうか確かめる。 56352 特に改行やタブなどが変換されるのかどうか。 56353 →どうやら ${var@E} は逆方向の変換の様だ。 56354 元々変数の中に入っている \r\n\t などのエスケープシーケンスを 56355 decode して本物の改行やタブに変換する。これは使えない。 56356 56357 x done: そもそも echo 'a で補完を実行すると 7 文字目から argument が開始する。 56358 これが為に結局引用符を閉じて補完するという動作にならない。 56359 これは core-syntax.sh の方が悪い。調べる必要がある。 56360 56361 x fixed: これは ble-syntax/completion-context 側で 56362 ble-syntax:bash/simple-word/is-simple によるチェックを行っていた為であった。 56363 ble-syntax:bash/simple-word/is-simple-or-open-simple という関数を追加してそれで判定する事にした。 56364 56365 x fixed: しかし 'a を判定させても真にならない。 56366 と思ったら、正規表現を誤っていた。'a よりも前に "1 つ異常" の element を要求していた。 56367 "0個異常" でなければならないはずだ。直した。 56368 56369 - todo: initialize の動作チェック。正しくエスケープされるだろうか。 56370 56371 x fixed: 動かない。と思ったら、ble-syntax:bash/simple-word/close-open-word にもバグがあった。 56372 close_type の判定のために不完全引用符を切り出す所を誤っていた。 56373 不完全引用符の内側にもキャプチャがあるのだから、 56374 不完全引用符のキャプチャが一番最後のキャプチャである事は保証できないのである。 56375 別の方法を用いる事にした。これは直った。 56376 56377 o 取り敢えず 'a や "a や $'a や $"a は動く。 56378 56379 x fixed: また、"\" から補完をしようとしても正しく補完できない。 56380 これは bash-completion とは関係の無い問題の様である。 56381 56382 というか補完が起こらない。と思ったらそもそも completion-context が生成されていない。 56383 構文木を調べてみると先ず、単語が全然設置されていない。 56384 というか nest を作成している。nest を作成している為に単語が設置されていないという事…。 56385 double quote の中にいる時には一旦外に出て単語を調べるという処理を実装する必要がある。 56386 →実装した。実行できている。 56387 56388 x resolved: "\"" から連続で補完しようとすると変な補完のシーケンスが生成される。 56389 これも上を修正したら直った。bash-completion が入っていても問題ないようだ。 56390 56391 x fixed: 完全一致している状態で補完を呼び出すと何故か quote が全て解除される。 56392 56393 候補を見るとちゃんと cand_cand[0]='a b c' で cand_word[0]="'a b c" になっている。 56394 では何故 quote が全て剥がされてしまうのだろうか。 56395 →これは opt_ambiguous の時に「共通部分 common が元々の文字列に曖昧一致しない場合に、 56396 補完を起こさない」という所で COMPS を設定するべき所で COMPV を設定しているのが行けなかった。 56397 修正した。ちゃんと動くようになった。 56398 56399 x resolved: quote 内部で空白を置いた後で (空白を含むファイル名の) 補完を実行しても補完されない。 56400 56401 これは上の項目を修正したら自然に直った。然し、未だ次の項目の問題が残っている。 56402 次の項目について修正した後で、それでも問題なく動くかどうかを確かめる事にする。 56403 →サイド試した所動いている。問題ない。 56404 56405 x fixed: 「'a b c」で補完を開始すると何故か最初のファイル名の補完で候補が全く生成されない。 56406 次の曖昧一致用の候補生成によって初めて候補が生成されている。 56407 これは要するに pathname-expansion が壊れている。後で確認する。 56408 56409 これはどうやら 'a b c*' で nullglob で候補生成すると、 56410 'a' と 'b' と null という候補が生成されてしまうという事の様である。 56411 そして 'a' も 'b' もファイルとして存在していないので、 56412 その直後の yield-candidate の直前のチェックではねられて消える。 56413 スペースもエスケープする必要がある様である。 56414 56415 因みに以下を試してみた所、一致した。つまり、変数に入れたパターンの場合は、 56416 空白に対する \ によるクォートはちゃんと除去されるという事である。 56417 56418 $ globpat1='a\ b\ c' 56419 $ [[ 'a b c' == $globpat1 ]] 56420 56421 と思って 'a\ b\ c*' で一致させてみた所、 56422 今度は 'a\' と 'b\' という二つの要素が生成されただけだった。 56423 IFS= にして実行してみる事にする。直った。 56424 56425 x fixed: addtail で追加された空白の後ろにカーソルが行って欲しいがそうならない。 56426 →これは簡単なミスだった。修正した。 56427 56428 x fixed: $' から補完を始めると何故か '$' から始まる候補が列挙される。 56429 →これは bash-completion の貞経している関数が悪いのだという事になった。 56430 bash-completion を混乱させない為には展開した後の文字列を使って構築したコマンドラインを与える必要がある? 56431 56432 少なくとも bash-completion を使わない場合 (complete -r で全削除) には問題は発生していない。 56433 これは COMP_LINE COMP_WORDS を設定する時に、再構築する事にした。 56434 特に、クォートを除去した後に '' でクォートし直す事にした。 56435 ただし、コマンド名は compgen が壊れている事による問題が起こると嫌なので、 56436 クォートしない事にした (#M0009)。bash-completion では実際に問題は起こらないようだったが。 56437 56438 以下の項目はこれによって解消した。 56439 56440 | * 2015-02-27 complete: 引用符の中で補完を実行する方法? 56441 | 56442 | 引用符の途中でも正規な単語として認識できる様にする。 56443 | 引用符の中であるという情報が必要。 56444 56445 2018-08-05 56446 56447 * complete: いつの間にかに共通部分が保持されなくなっている [#D0716] 56448 56449 例えば echo $HOME で tab を押すと /home/murase に置換されてしまう。 56450 56451 * complete: --prefix= などの続きの補完 [#D0715] 56452 56453 * complete: コマンド名補完ができなくなっている [#D0714] 56454 56455 何と compgen は普通は quote を外すが、 56456 command 名の候補生成の時だけは quote を外さない様だ。 56457 56458 具体的にそれぞれの候補生成で確認する必要がある。 56459 56460 | 以下は quote を外してくれる。 56461 | 56462 | - function: 全 bash version OK 56463 | - variable: 全 bash version OK 56464 | - arrayvar: 全 bash version OK 56465 | 56466 | 以下は quote を外してくれない。 56467 | 56468 | - command: 全 bash version 駄目 56469 | 56470 | 以下は状況によって quote を外してくれたりくれなかったりする。 56471 | 何らかの設定が関係しているのだろうか。 56472 | 56473 | - directory: bash-3.0 - 4.2 で OK 56474 | 56475 | bash-4.3, 4.4, 5.0 で、bash -c から呼び出すと、外してくれない。 56476 | bash-4.3, 4.4, 5.0 で、bash --norc から呼び出すと、外してくれない。 56477 | ble を load せずに mshex だけだと外してくれない。 56478 | ble を load していると外してくれる。 56479 | 56480 | 何の違いであろうか。何故 ble をロードすると動作が変わるのだろうか。 56481 | shopt の出力は全く変わっていない。もう少し調べてみる事にする。 56482 | bind -v の出力を観察すると editing-mode が先ず異なる。 56483 | editing-mode を合わせて見たが別に変化は見られない。 56484 | keyseq-timeout も合わせてみたが変化は見られない。 56485 | stty の状態で変わるという事がありうるのか? 56486 | 56487 | - file: bash-3.0, 3.1, 3.2, 4.2, 4.3, 4.4, dev で OK 56488 | 56489 | 4.0-4.1 で bash --norc から呼び出すと外してくれない。 56490 | これは ble をロードしていてもやはり外してくれない。 56491 | bash-3.2 及び 4.2 以降では何も問題は起こっていない。 56492 56493 56494 [まとめ] これは memo にも転記する: #M0009 56495 56496 compgen -A command クォート不可 56497 compgen -A directory クォート不可 (Bash-4.3 以降でクォート除去されない※1) 56498 compgen -A file クォート不可 (Bash-4.0, 4.1 でクォート除去されない※2) 56499 compgen -A function クォート可 56500 compgen -A variable クォート可 56501 compgen -A arrayvar クォート可 56502 56503 ※1 バグと思われる。ble をロードしていると何故かクォート除去されている。 56504 然し、--norc や ble ロードなしで実行するとクォート除去されない。 56505 クォート除去が実行されなくなってしまう条件が分からないのでこれは使わない。 56506 56507 ※2 バグと思われる。 56508 56509 * 2018-07-28 complete: 例えば ble-complete/ まで一意確定でコマンド名補完した時に、 [#D0713] 56510 続きの候補も同時に表示した方が便利である。 56511 56512 現在の実装ではもう一度 tab を押して補完を促さないと表示されない。 56513 これは候補をまとめる仕組みと一意確定の仕組みに修正を加えなければならない。 56514 56515 * 2018-07-28 complete: compgen に渡す文字列はクォートしなければならない [#D0712] 56516 56517 | →これは本当だろうか。今試してみたところ、\ でクォートしていても動くが、 56518 | クォートしていなくても動く。少なくともチルダ展開は実行しない。 56519 | 56520 | '' の除去は発生する。"" の除去も発生する。 56521 | パラメータ展開は実行しない。 56522 | 閉じていない ' や閉じていない " でも除去される。 56523 | 56524 | 後 compgen の引数が空白を含む場合等にどうなるのかについても確認する。 56525 | →大丈夫。勝手に単語分割されることはない。 56526 56527 - '' や "" の除去は実行される。閉じていない場合でも実行される。 56528 - パラメータ展開は実行されない。 56529 - 単語分割は実行されない。 56530 56531 以上の事から考えると '' でクォートしておけば良い気がする。 56532 56533 * complete: cd [#D0711] 56534 56535 既定だと cd の補完は bash-completion による補完になっていて、機能が劣る。 56536 ble のプログラム補完 ble/cmdinfo/complete:$command_name に対応して、 56537 それを利用して cd 用の補完を実装する事にした。 56538 56539 * 2018-07-28 complete: 既存部分の置き換えは一意確定以外の時は起こさない様にする [#D0710] 56540 56541 未だ候補が確定していないのに共通部分で置き換えを行うと、 56542 今までに生成していた候補が再現されなくなる可能性があるので。 56543 56544 また、途中で補完をやはりやめようという時に面倒である。 56545 補完のキャンセルの仕組みについては後で対応する予定ではあるが、 56546 キャンセルに対応したとしてもやはり動作として不自然である。 56547 56548 →これは取り敢えず文字数が少なくなる様な置換だけ行わない様にした。 56549 それで問題が起こる様であればまた再考する。 56550 56551 * 2018-07-28 complete (ble-complete/source/command/gen): compgen の使用の是非について再確認 [#D0709] 56552 56553 - done: compgen -A directory と pathname-expansino の両方の実装がある理由は? 56554 compgen だと -- の先の単語の quote がよく分からないという事。 56555 一方で pathname-expansion の方を使わない理由もあった筈。 56556 これについてはコミットを遡れば良い。 56557 56558 これはどうも nocaseglob と関係している様である #D0633 56559 nocaseglob の時、大文字小文字を区別しない候補の生成を行う。 56560 56561 調べると bash には大文字・小文字に関して色々のオプションがある様である。 56562 56563 - compgen は rl の設定に左右される。bind "set completion-ignore-case on" 56564 [autocomplete - getting case insensitive completions with compgen in bash - Unix & Linux Stack Exchange](https://unix.stackexchange.com/questions/204848/getting-case-insensitive-completions-with-compgen-in-bash) 56565 % 然し、今 bind -v してもその様な rl 変数はない… 56566 % と思ったら bind -v の出力は別にソートされている訳でも、同じカテゴリで並んでいる訳でもなかった。 56567 - [[ == ]] や case は shopt -s nocasematch に依存する。 56568 - パス名展開は shopt -s nocaseglob に依存する。 56569 56570 ble-complete では bind -v の値に従って候補生成する事にした。 56571 glob を用いる時には一時的に shopt -q nocaseglob を変更する。 56572 正規表現を用いてフィルターする時には i がある時には各文字を [aA] 等の様にする。 56573 56574 以下の項目についてはこれで完了した。 56575 56576 | * 2017-11-26 complete: nocaseglob 的な補完に対応する? 56577 | 56578 | つまり、大文字小文字が違うファイルに一致した場合は、 56579 | 前方の文字列を書き換えてしまう。 56580 56581 * 2018-07-30 complete: 曖昧一致がサブディレクトリのファイルに効かない [#D0708] 56582 56583 これは何故かと言うと曖昧一致の候補生成を最初の文字だけで行っているからである。 56584 サブディレクトリのファイルは生成されない。 56585 これを正しく実行する為には COMPV 内部の / について一つずつ遡って、 56586 初めて存在するディレクトリに当たった箇所から候補生成を行う必要がある。 56587 56588 また存在しないディレクトリ名に関しては、 56589 /a*/b* 等の様にして生成した候補に対して曖昧一致を試みるべきなのかもしれない。 56590 % その場合には .* ではなくて [^/]* で一致させる必要がある。 56591 % と思ったけれど、よく考えたらその場合には / の数は保存しているので、 56592 % [^/] としなくても、[^/] に一致せざるを得ないので問題ない。 56593 56594 色々考えると実は source 側で処理するほうが懸命なのかもしれない。 56595 56596 実装した。これにより以下の古い項目についても自然解消した。 56597 56598 | * 2015-02-21 zsh の機能: /a/b/c 等に対してディレクトリ名の補間も行う 56599 | でも、これはやった後で一意に補完できない事が分かった場合が悲しい。 56600 | TAB を打つ回数が多少減るだけで何が嬉しいのか分からない。 56601 | しかしながら、曖昧一致による補完機能はあった方が便利な気がする。 56602 | ただ、候補を表示するに留め、無断で補完する事はやめる。 56603 56604 2018-07-30 56605 56606 * complete: ファイル名の曖昧一致? [#D0707] 56607 56608 候補が一つも生成されなかった時に曖昧一致を行う。 56609 然し一つも生成されなかったときというのをどの時点で判定するのか。 56610 56611 a 全ての補完開始点について一つも生成されなかった時 56612 b その開始点に於いて一つも生成されなかった時 56613 c その source に於いて一つも生成されなかった時 56614 56615 b に対して実行するのが妥当な様に思われる。 56616 然し、その為には source 側で実行するのは面倒である。 56617 以下の方法を考える事ができる。 56618 56619 a source 側は全くフィルタリングをせずに候補を提供する。 56620 もしくは、曖昧一致する物も含めて全て列挙する。 56621 ble/widget/complete 側でフィルタリングを実行する。 56622 56623 この方法はとても遅くなる気がする。 56624 特にコマンド名については毎回大量に生成する事になる。 56625 56626 最初の文字を固定するとしても、多いのではないか。 56627 実際に確かめてみると b で始まるコマンドが最多で 1500 (ble 含む)。 56628 p で始まるコマンドが 1371 で次に多い。 56629 56630 b 或いは source に対して引数を指定できるようにして、 56631 最初の source 呼び出しでは無引数で行い、 56632 全ての source で候補が一つも生成されなかった場合には、 56633 曖昧一致を許すという意味の引数を指定して再度 source を呼び出す。 56634 56635 c もうひとつの方法は source は何も修正せず、呼び出し側で工夫する。 56636 最初の source 呼び出しは通常通り行う。 56637 候補が一つも生成されなかった場合は、 56638 最初の一文字だけ与えて source を呼び出し、呼び出し元でフィルタを行う。 56639 56640 これは c の方法が良いだろう。 56641 56642 コマンド名についての曖昧一致はどの様にしたら良いか微妙である。 56643 コマンド名は大量に生成されるはずなのでそれをスクリプトでフィルタすると時間がかかる。 56644 sed でフィルタすれば良いだろうか。曖昧一致とは言っても、最初の文字だけは一致する様にするか。 56645 56646 ? 曖昧一致に関しては正規表現を使うか。超線形になったらどうしようと思ったが、 56647 56648 | よく考えれば使うのは DFA の範囲内なので問題にはならないだろう。 56649 | 逆に glob を使った場合にちゃんと超線形を避けられるのかは気になる。 56650 | [[ a{30回} =~ (*a){n回}z ]] を試したら: 56651 | 56652 | n = 2 time 0.000s 56653 | n = 3 time 0.001s 56654 | n = 4 time 0.005s 56655 | n = 5 time 0.024s 56656 | n = 6 time 0.097s 56657 | n = 7 time 0.325s 56658 | n = 8 time 0.935s 56659 | n = 9 time 2.338s 56660 | n = 10 time 5.128s 56661 | 56662 | 明らかに超線形になってしまっている。因みに sed ではちゃんと線形になっているだろうか。 56663 | 56664 | n = 15 time 0.005s 56665 | n = 20 time 0.005s 56666 | n = 25 time 0.005s 56667 | n = 30 time 0.005s 56668 | 56669 | 大丈夫である。序に zsh, ksh の glob も確認する。 56670 | 56671 | $ time zsh -c '[[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa == *a*a*a*a*a*a*a*a*a*az ]]' 56672 | $ time ksh -c '[[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa == *a*a*a*a*a*a*a*a*a*az ]]' 56673 | 56674 | zsh n = 10 time 5.749s 56675 | ksh n = 10 time 5.605s 56676 | 56677 | bash の glob と殆ど変わらない。同じルーチンを使っているという事なのだろうか。 56678 | また正規表現を試してみる事にする。これはシステムの正規表現が内部的に使用される。 56679 | 56680 | $ time [[ xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =~ .*a.*a.*a.*a.*a.*a.*a.*a.*a.*a.*z ]] 56681 | n = 10 time 0.000s 56682 | 56683 | 問題はない。キャプチャが合っても大丈夫だろうか。 56684 | 56685 | $ time [[ xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =~ (.*)a(.*)a(.*)a(.*)a(.*)a(.*)a(.*)a(.*)a(.*)a(.*)a(.*)z ]] 56686 | n = 10 time 0.000s 56687 | 56688 | 大丈夫のようだ。 56689 56690 結論: glob は超線形になるので危ない。正規表現ならば Bash の物でも sed の物でも問題ない。 56691 56692 取り敢えず実装した。 56693 時間がかかるかもしれないが、取り敢えずは Bash の正規表現を使って標準入力を確認しながら処理する。 56694 また、生成した候補を後から制限する方法にしたので、 56695 必然的に cand_{prop,cand,word,show} を並列で操作する事になるので遅い。 56696 然し、これは後で問題になってから配列を統合する等の処置によって改善するべきである。 56697 ここでは複雑な事をして改善する等の方策は取らない。 56698 56699 x 実装して気づいた事は、曖昧一致による確定は色々難しいという事。 56700 直ぐに一意確定すれば問題ないが、複数の候補がある時に、 56701 単純に共通部分で補完を行ってしまうと、既に入力した部分が消えてしまう。 56702 56703 然し、だからといって曖昧一致の時には遡る様な確定は行わないのだとすると、 56704 hello 及び hello~ がある時に hll から補完を開始した時に、 56705 結局何も補完できないという事になってしまう。 56706 56707 % 曖昧一致の時は曖昧一致の時で共通部分を計算する必要がある。 56708 % しかしどの様なアルゴリズムで共通部分を計算したら良いだろうか。 56709 % LCS というアルゴリズムがあったはず。 56710 % 単純に LCS を求めると元々入力した文字列を含まない可能性もあるので、 56711 % 先に元々入力した文字列との関係を調べてから、 56712 % その間隙に対してそれぞれ LCS を求める様にするのが良い。 56713 % 56714 % x 問題点がある。求められた LCS に対するエスケープをどうするのか。 56715 % 特に複数の種類のエスケープが混ざっている場合に、 56716 % どのエスケープをすれば良いのかが分からない。 56717 % 56718 % 逆にエスケープ後の文字列に対して LCS を求めるのはもっと問題になる。 56719 % エスケープは複数の文字の組み合わせで意味があるのであって、 56720 % 部分列を取ってしまうと意図しない意味を持つようになってしまうので使えない。 56721 % エスケープの組み合わせが分断されない様に LCS を求めるとしても、 56722 % 複数の種類のエスケープが混ざっていた場合にはやはりよく分からない事になる。 56723 56724 余り複雑な処理にしても非直観的な物になってしまうので、 56725 ここでは単純に求めた共通部分が COMPV に曖昧一致していれば補完を実行するし、 56726 一致していなければ何もしないという様にするのが良さそうである。 56727 56728 * 何れにしても曖昧一致では確定できない時の為に、 56729 menu-completion の様な機能は必須である。 56730 これは後でまとめて対応する。 56731 56732 2018-07-29 56733 56734 * complete: 関数名の補完で / 以前を共有する物が複数ある場合には [#D0706] 56735 / までを補完候補として、/... と表示する様にする。 56736 ble-complete/source/command/gen を変更する。 56737 awk で実装すれば良い。bleopt を追加しても良い。 56738 56739 実装し始めて思ったのだが、どういう振る舞いにするのかが不明瞭である。 56740 a/b/ まで入力している時に a/b/1 a/b/2 があったとして、 56741 その時に a/ という候補が生成されるのでは困る。 56742 56743 1. 先ず初めに共通部分までは必ず補完する事にする。 56744 2. 共通部分以降の部分について a/ 以降が単一しかない場合には、 56745 最後まで確定する。それ以外の場合については、a/ を生成する。 56746 56747 →最後までというよりは、単一しか無いディレクトリ階層まで 56748 一気に補完できるようにした方が良い。 56749 56750 これを動的にできるだけ 1pass で実装する事は可能だろうか。 56751 56752 % 例えば、状態として以下の様な物を考える。 56753 % 56754 % 共通部分 a/b/c 56755 % 候補 '' '/1' '/2' '/3' '/d/e' 56756 % 56757 % 此処で b が来たらどうするかというと 56758 % 56759 % 共通部分 '' 56760 % 候補 'b' 'a/b/c' 56761 % 56762 % となる。うーん。此処で a/b/c/4 が来たら単に追加するだけである。 56763 % ここで a/b/c/d/1 が来たら '/d/e' を '/d/' に短縮しなければならない。 56764 % これをどの様に実装するかは難しい所である。 56765 % 既に生成されている候補の一つ一つと比較しなければならないのだろうか。 56766 % それだと最悪 O(N^2) になってしまう。 56767 % ソートしておいて二分法で探索するという手もあるが、実装が大変に面倒になる。 56768 % 挿入できる様にする為には awk で二分木も構築しなければならない。 56769 56770 よく考えてみれば初めから入力をソートして置けば、 56771 もっと簡単に実装できるのではないだろうか。 56772 / で区切られた名前を単位とする、階層が二つしか無いパトリシア木の構築と思えば良い。 56773 56774 - reject: 共通部分は a/b/c の様にスラッシュの手前までの方が良い。 56775 a/b/c という関数と a/b/c/d ... という関数があった場合に、 56776 a/b/c まで入力した時に、 a/b/c と a/b/c/ が候補になるのは悲しい。 56777 a/b/c が共通部分になっていれば、a/b/c 及び a/b/c/d... 56778 が候補になってくれると思う。実装によると思うが。 56779 56780 と思ったがこの方法にしていると、a/b/c/1 a/b/c/2 という候補に対して、 56781 スラッシュの手前またはスラッシュの直後の両方を可能にした方が良いのでは。 56782 56783 これを考えると難しくなるので a/b/c と a/b/c/ を候補にする事にした。 56784 これだと a/b/c まで入力されているのだという情報も使わないとならない。 56785 動作として色々と不自然になる気がするので取り敢えず実際に気になるまで考えない事にする。 56786 56787 - resolved: a/b/c と a/b/c/d に対して a/b/c を候補として生成した時に、 56788 一意確定してしまったらどうするのか。 56789 実は一意確定しない様にする事も必要なのではないだろうか。 56790 56791 或いは、候補を表示する時にだけ / 以降が色々ある場合には表示を省略する、とするか。 56792 そちらのほうが良いのかもしれない。 56793 特にディレクトリ名と関数名で / 以前の部分を共有している場合なども考えられるので。 56794 56795 これについては a/b/c と a/b/c/ の両方を候補として生成する事にした。 56796 56797 x resolved: 実際に動作確認してみると全くフィルタできていない。何故だろうか。 56798 と思ったら、既存文字列に / が含まれていない場合は compgen -c の方から関数名が列挙されるのであった。 56799 compgen -c 及び compgen -A function の両方の出力に対して実行する事にした。 56800 56801 x resolved: 何故か ble-c まで入力して補完しようとすると ble-complete が候補として列挙されない。 56802 →最後に END で残っている物を出力するのを忘れていた。 56803 取り敢えずの所動いているような気がする。 56804 56805 * complete: 前の候補を覚えておいてそれに対する絞り込みにした方が速い可能性 [#D0705] 56806 56807 →これは各 source でキャッシュするべきである。 56808 56809 同じ補完の続きの場合には、毎回補完候補を列挙するのではなくて、 56810 前に生成した候補を覚えておいてそれに対する絞り込みをかけた方が速い可能性。 56811 しかし、同じ補完の続きかどうかを判定する必要があるし、 56812 最初の補完で大量の補完候補が存在する場合には、 56813 スクリプトで絞り込みをかけるよりも、最初から生成し直した方が速い。 56814 56815 現状では、毎回候補を生成した方が速いと判断する。 56816 もし候補生成自体が遅い種類の source の場合には source の側で記録したほうが良い。 56817 どの様な状況で候補を再利用できるのかを的確に知っているのは source だけのはずなので。 56818 56819 2018-07-28 56820 56821 * complete: source の時点で一番近い開始点にフィルターする [#D0704] 56822 56823 取り敢えず手始めに開始点はできるだけ後ろの物しか用いない様に変更する。 56824 開始点を一番近い物だけにした場合、初めから一番近い source だけで候補生成をすれば良い。 56825 56826 - done: ちょっと面倒なのは、一番近い source で候補が一つも生成されなかった場合、 56827 次に近い source 候補を使う必要があるという事。 56828 これには対応した。 56829 56830 [動作確認] 56831 56832 x fixed: 候補が複数あっても最後の物で確定してしまう? 56833 共通部分の算出がちゃんと動いていないという事だろう。 56834 二番目以降の要素について列挙するのは "${arr[@]:1}" であった。修正した。 56835 56836 使った見た感じ他は問題は発生していない。 56837 56838 [動作変更点] 56839 56840 - 変更に伴って、shopt -s force_ignore は補完候補生成より前の状態を参照する様に変更した。 56841 - また、パターンの一致に関しては、挿入文字列 (INSERT) ではなくて候補文字列 (CAND) に対して適用する様に変更した。 56842 56843 * 2017-03-18 complete: .exe が候補から消去されている場合、.e の入力仕掛けの状態での補完ができない [#D0703] 56844 56845 現状の実装がどうなっているか確認する。やはり compgen を使っている。 56846 実際に以下を実行してみると補完候補として sort だけが生成される。 56847 $ compgen -c -- sort.e | sort -u 56848 56849 % 補完候補が単一の場合はそれに確定して 56850 % ble-complete/action/command/complete が呼び出されて、更に 56851 % ble-complete/action/util/complete.addtail が呼び出される。 56852 % 其処で INSERT に ' ' や '/' などの内容が追記される。 56853 % 56854 % うーん。その部分より前の編集部分の最小化という所に問題点がある様な気がする。 56855 % 先ず、編集文字列 text (= _ble_edit_str) の内容を見て編集部分を最小化している。 56856 % 挿入文字列の quote や編集文字列の置換などが考慮に入っていないのではないか。 56857 % 更に、この部分では補完によって単語が伸びる場合しか考慮に入っていない? 56858 % と思ったら遡って書き換わる場合についてもちゃんと対応はしている様であった。 56859 % うーん。観察してみるとちゃんと長さが縮まる場合にも対応している気がする。 56860 56861 確認してみた所、そもそも共通部分を計算する以前から、 56862 sort.e や sort.ex などの不完全な候補が生成されているという事が分かった。 56863 調べてみると ble-complete/source/command の中で呼びされている 56864 56865 ble-complete/yield-candidate "$cand" ble-complete/action/command 56866 56867 の中で sort が sort.e に化けているという事が分かった。 56868 更に中で呼びされている ble-complete/action/command/initialize の中が怪しい。 56869 これは ble-complete/action/plain/initialize を呼び出している。 56870 ここでは既存の内容と一致する部分を置き換えない様にする為に、 56871 INSERT=$COMPS${CAND:${#COMPV}} 的な事をしている。これが行けない。 56872 56873 ble-complete/action/plain/initialize は遡って書き換わる場合にも 56874 対応できる様に修正するべきである。 56875 場合分けで既存の内容に対する追記の場合と、 56876 書き換えが起こる場合に分けて処理する事にした。 56877 56878 2018-07-24 56879 56880 * edit/history: bashrc の謎の遅延に関して [#D0702] 56881 56882 #D0701 後半に関して再度整理し直す。 56883 56884 色々調べて分かったこと。 56885 56886 - bashrc 中で shopt -s histappend の状態で history -n をすると、 56887 bashrc を抜けた後に謎の遅延がある。 56888 - 当初 Cygwin だけかと思っていたら GNU/Linux でも同様の遅延が生じる。 56889 特に padparadscha ではかなり長い遅延が発生する。 56890 - Bash 3.0 では遅延はない。Bash 3.1 - 5.0a の全てで遅延がある。 56891 - 履歴項目の数から HISTSIZE, HISTFILESIZE の半分を引いた数に比例した遅延である。 56892 56893 - history -n をする瞬間だけ shopt -u histappend すると遅延はなくなるが、 56894 histappend の効果が失われる。 56895 shopt -u histappend; history -n; shopt -s histappend 56896 56897 以下の様にしても遅延はないが histappend の効果はない。 56898 shopt -u histappend; history -n 56899 shopt -s histappend; history -n 56900 56901 以下の様にすると遅延があって histappend の効果がある。 56902 shopt -s histappend; history -n 56903 shopt -u histappend; history -n; shopt -s histappend 56904 56905 再現するには以下のような bashrc を用意する。 56906 参照: memo/D0703.bashrc 56907 56908 | # bashrc-test 56909 | 56910 | function measure1 { 56911 | time1=($(date +'%s %N')) 56912 | } 56913 | function measure2 { 56914 | local -a time2=($(date +'%s %N')) 56915 | local sec=$((time2[0]-time1[0])) 56916 | local usec=$((sec*1000000+10#${time2[1]}/1000-10#${time1[1]}/1000)) 56917 | echo "${usec} us" >/dev/tty 56918 | } 56919 | 56920 | export HISTFILE=A.txt 56921 | export HISTSIZE=100000 56922 | export HISTFILESIZE=100000 56923 | shopt -s histappend 56924 | history -n 56925 | measure1 56926 | PS1='$(measure2)'$PS1 56927 56928 $ printf 'echo hello %d world.\n' {1..100000} > A.txt 56929 $ bash --rcfile bashrc-test 56930 56931 解決の為には 56932 56933 a 遅延が生じず histappend も有効にできる様な何らかの方法を見つけるか 56934 b サブシェルで history -n を実行するか 56935 c キーが入力された後に履歴を読み込むか 56936 d 履歴の仕組み自体を Bash の履歴とは独立な物かラップした物にするか 56937 56938 実は一時的に HISTSIZE を増大させれば問題ないのでは? → 遅延がなくなった。 56939 56940 * 2018-05-22 もしかすると cygwin で遅延ロードがちゃんと働いていない可能性がある [#D0701] 56941 56942 使った感触でそう思っただけなので具体的に確認する必要がある。 56943 56944 * done: 調べてみた所遅延ロード自体はちゃんと動いている。 56945 但し、履歴項目の読み込み (mapfile) に時間がかかっている様に思われる。 56946 有効になっている ble/util/mapfile の実装について確認した所 mapfile -t になっている。 56947 10万項目を読み取るのに 3.050 秒かかっている。 56948 56949 Linux で3.7万項目の ble/util/mapfile の読み込みに 47ms しかかかっていない事と較べると、 56950 Cygwin では mapfile が20倍ぐらい遅いという事になる。 56951 もしかすると昔ながらの source の方が速いという事もあるかもしれない。 56952 56953 1. mapfile 3.055 sec 56954 2. 配列のコピー 0.522 sec 56955 3. source 0.620 sec 56956 56957 取り敢えず Cygwin に限って _ble_edit_history は source で定義して、 56958 _ble_edit_history_edit は _ble_edit_history をコピーする事にした。 56959 56960 * 後もう一つ。.background-initialize 待機中に一度 148 で抜けると 56961 .background-initialize が終わるまで最後まで実行してしまう様である。 56962 然し、不思議である…。何処で時間を食っているのかが分からない。 56963 分かったこと。148 で抜ける → .background-initialize が終わるまで戻ってこない。 56964 .background-iniailize が終わると ble-edit/history/load async が再び呼び出される。 56965 56966 何が起こっているのだろう。 56967 56968 | 色々調べてみた所、どうやら問題は .bashrc が終わった直後から、 56969 | 最初に入力が来るまでの間にあるようである。 56970 | ble-attach → ble-edit/bind/.tail → ble/util/idle.do の中でジョブが投げられると、 56971 | 必ず 0.8-1.2 sec 程の遅延が生じる。ジョブを投げないと遅延はない。 56972 | ジョブが物凄く時間がかかる者であったとしても遅延は 0.8-1.2 sec のままである。 56973 | 56974 | 然し、不思議なのは小数 sleep のための background プロセスに関しては遅延が生じていないという事である。 56975 | 56976 | % →どうやら var=$(command & echo $!) で起動すると駄目の様だ。 56977 | % 代わりに ble/util/assign var 'command & echo $!; disown' 2>/dev/null で起動してみると遅延はない様だ。 56978 | % Linux でも試してみたが、Linux では違いはない様に見える。 56979 | % →やはり ble/util/assign var を用いたとしても遅延は存在する。 56980 | 56981 | 簡単な bashrc を作って実験してみる事にする。 56982 | - 簡単な bashrc を使っている限りに於いては、 56983 | 丁寧に </dev/null &>/dev/null にすると、 56984 | ちゃんと遅延無しで動く様になる。 56985 | - bind -x しても遅延はない。 56986 | - ble-edit/bind/stdout.off の効果でも無いようだ。 56987 | - 関数を入れ子にしても再現しない。 56988 | 56989 | 色々試した結果、犯人は fork ではなくて、それよりも前にある history -n だと分かった。 56990 | history -n を bashrc の中で使うだけで遅延が生じる様になる。 56991 | 然し、history -n だけでは再現しない様だ。 56992 | - 更に調べてみると source bashrc_common.sh; history -n で遅延が出る。 56993 | どちらか一方でも欠けていれば遅延は生じない。 56994 | - is-stdin-ready も関係しているのではないかと当初疑っていたが関係ない。 56995 56996 結局、以下が bashrc に含まれていると遅延が生じるという事が分かった。 56997 どれか一つだけでも欠けていると再現しない。 56998 また順番を変更しても (特に history -n を shopt -s histappend より先にすると) 遅延しない。 56999 57000 export HISTSIZE=100000 57001 export HISTFILESIZE=100000 57002 shopt -s histappend 57003 history -n 57004 57005 a shopt -s histappend の時は一瞬だけ shopt -u histappend にして history -n を実行する? 57006 57007 順番を変更した時に正しく histappend が適用されるかどうかについては確認が必要である。 57008 →順番を変更してみたところ histappend が有効にならないという事が分かった。 57009 つまり、history -n する瞬間だけ shopt -u histappend にしても、HISTFILE に全体が書き込まれる。 57010 shopt -s histappend にしたまま history -n すると期待通りに実行したコマンドだけが追記される。 57011 57012 つまり shopt -s histappend が有効になっている時に history -n しないと駄目という事。 57013 この方法は使えない。 57014 57015 b 或いは、Cygwin に於いては history -n 57016 をサブシェル内で実行するという手もあるかもしれない。 57017 実際にサブシェル内で history -n を実行する様にしたら遅延を改善する事ができた。 57018 57019 - history -n をサブシェルで実行するという事は二回ファイルを読み込むことになって問題だが、 57020 history -n 自体はそんなに時間のかかる処理ではない (71ms/10万項目) ので速度的な問題は生じないだろう。 57021 57022 x 問題になるとすれば二回に分けてファイルを読む途中でファイル内容が変更された時に、 57023 データの内容に不整合が生じてしまう可能性がある事である。 57024 57025 history の仕組み自体を大幅に変更した上で再考しても良いかもしれないが、 57026 現段階では不整合を防ぐために遅延を甘受して一回で読み取る事にする。 57027 57028 | また、この問題が実は Linux でも発生している事も確認しておいた方が良いかもしれない。 57029 | →Linux でも再現した。というかより遅延時間が長い @ padparadscha 57030 | 4万行の時は殆ど遅延がなくて10万行に達すると遅延が生じる事から、 57031 | もしかすると HISTSIZE, HISTFILESIZE の上限に達する時特有の遅延なのかもしれない。 57032 | 57033 | 試しに幾らか余裕をもたせて実行してみる事にする。 57034 | 余裕を持たせても遅延が長いのは変わらない様だ。 57035 | 50000 まで減らすと遅延がなくなる。70000 だと遅延がある。 57036 | 色々調べると 50000 を超えた辺りから急激に遅くなる。 57037 | (と思っても増え具合は線形のようではある。) 57038 | 57039 | 50000 63642 us 57040 | 51000 308568 us 57041 | 52000 554410 us 57042 | 53000 802508 us 57043 | 54000 1046543 us 57044 | 55000 1290507 us 57045 | 57046 | HIST{,FILE}SIZE を 200000 に増やしたらまた速くなった。 57047 | 57048 | 55000 30085 us (with HISTSIZE=200000 HISTFILESIZE=200000) 57049 | 57050 | つまり、この遅延は HISTSIZE/2, HISTFILESIZE/2 より超過すると発生する。 57051 | 本当に、"半分" なのだろうか。また試す。やはり "半分" が閾値になっている様だ。 57052 | 57053 | 100000 123337 us (with 200000) 57054 | 101000 1106749 us (with 200000) 57055 57056 この遅延は Linux でも生じる。特に padparadscha では遅延が著しい。 57057 HISTSIZE, HISTFILESIZE の丁度半分よりも超過した項目の数に比例して時間がかかる。 57058 57059 2018-07-19 57060 57061 * ble-decode: ble-text.s2c 廃止 [#D0700] 57062 57063 * 2018-07-10 LANG=C とすると c2s がおかしくなる [#D0699] 57064 57065 一度キャッシュされるとそのままになってしまう。 57066 57067 うーん。どうしたら良いのか謎である。 57068 LANG が途中で切り替わると Bash の文字のカウントなどが全て変化する。 57069 その様に考えると LANG=C の時には UTF-8 表現であっても保持するべきではないのでは。 57070 つまり '?' などの文字に変換するべきではないのか。 57071 57072 すると LANG に応じて変換先の文字を変更することになるので、 57073 LANG が変わったら c2s のテーブルをクリアするなどの処置が必要になる。 57074 57075 うーん。c2s は output charset に応じて変更するべきである。 57076 input_encoding の設定項目はあるが、output_encoding の設定項目はない。 57077 というか、output_encoding の設定項目の代わりに LC_CTYPE を用いているのだろう。 57078 その様に考えると c2s で変換に失敗する場合には、 57079 文字の幅に応じて ? や ?? になるべきなのでは? 57080 と思ったが c2s が使われる箇所を考えると微妙である。 57081 描画の瞬間にその文字になるのではなくて、 57082 既に文字列として保持している時点でその文字になっている。 57083 57084 _ble_edit_str に何か物が入っている時に LC_CTYPE が変化するとよく 57085 分からないことになるが、LC_CTYPE が変わるのはコマンド実行時と考えれば、 57086 基本的に _ble_edit_str が空の時に LC_CTYPE が変化すると考えて良い。 57087 そう考えれば _ble_edit_str に壊れた文字が含まれる事はないし、 57088 また、座標計算などのキャッシュされたデータに齟齬が生じる事もない。 57089 と思ったが履歴項目が変なことになるのではないか。 57090 壊れた文字が含まれる事になる (但し、座標計算などがおかしくなる事はない)。 57091 然し、これは ble.sh を使っていなくても起こる問題であるので気にしない。 57092 57093 そう考えると新しく入力される文字についてだけ適切に処理できれば良い。 57094 57095 % 例えば LC_CTYPE=C 等になったとすると、どんなに頑張っても文字として保持不可能である。 57096 % 従って ? 等の文字に変換するしかない。? はシェルとして特別な文字なので、 57097 % 別の文字にしたい。もしくは \u???? の形式の文字列にする。 57098 % うーん。調べてみると、やはり c2s は様々なところで使用されていて、 57099 % 必ず一文字の結果を返すという事前提の実装になっている。 57100 57101 ここで問題にしているのは c2s の結果が表現不可能な文字の時にどのように取り扱うかである。 57102 57103 a "?" という文字にする。 57104 これはシェルの特殊文字なので誤って取り返しの付かない事をしてしまう可能性がある。 57105 例えば rm -rf ???? などとして大切なファイルを消してしまうかもしれない。 57106 これは危険である。 57107 57108 b エラーにする。そもそも文字を入力できない事にする。 57109 57110 そもそも文字を入力できなくすれば、文字を入力する箇所の 57111 c2s だけに影響が留まるという算段である。 57112 しかし履歴項目などに含まれている文字を消去する事はできない。 57113 と思ったが履歴項目に含まれている文字は別の文字として解釈されるので問題ない。 57114 57115 c "\u????" という文字列に変換する。 57116 57117 この方法だと情報劣化はない様な気がするが。 57118 実際にこの様にしたところで printf の引数に用いる時ぐらいしか意味がない。 57119 57120 また、現在の c2s の使用例を調べてみるとやはり一つの code に対して 57121 一文字しか返さない事を前提としている様な気がする。 57122 と思ったが、そもそも c2s を用いた時に現在の LC_CTYPE で表現不可能な code 57123 を指定する可能性がある箇所というのは限られているのではないかとも思われる。 57124 57125 d "_" 等の文字にする。これは "_" と違ってシェルとして特別な意味は持たないので安心である。 57126 また "-=" はオプションなどで使用するし、"/" はパス区切りに用いる。 57127 残るのは "%@+:.," 位だが、やはり "_" が最も良さそうに思われる。 57128 現にファイルをダウンロードする時などによく使われる置換である。 57129 57130 ble/util/c2s の使用箇所についてまとめる。 57131 調べた範囲では ble/util/c2s の終了ステータスは使用されていない。 57132 57133 - done: ble-decode.sh 57134 - ble-decode-kbd/.get-keyname 57135 input_encoding によって現在の LC_CTYPE で表現できない Unicode が入ってきうる★ -> ok 57136 - ble-decode-char/csi/print 57137 これは ble-bind -d の時に出力する内容★ -> ok 57138 - ble-decode-char/csi/consume 57139 - ble-decode-bind/c2dqs 57140 これは ASCII の範囲内であることが保証されている文脈 57141 - done: ble-edit.sh 57142 - ble/textarea#adjust-for-bash-bind 57143 これは現在位置の左にある文字の文字幅を計算するのに使う。 57144 現在位置の左にある文字は LC_CTYPE で切り出されるので、 57145 そこから s2c で得られた文字コードは必ず c2s で元の文字に戻せるはずである。 57146 よってこれに関しては表現不可能な文字になる可能性は考えなくて良い。 57147 - ble/widget/self-insert [self-insert] 57148 これは input_encoding を通して生成された unicode を文字列に変換するもの。 57149 LC_CTYPE で表現できない Unicode が入ってくる可能性を考慮に入れるべき。★ -> done 57150 - ble-edit/history/string#create-unicode-progress-bar 57151 これはプログレスバーを表示するのに使っている。★ -> done 57152 - ble-edit/isearch/self-insert.fib 57153 - ble-edit/isearch/history-self-insert.fib 57154 これは検索文字列を入力するもの。input_encoding 経由★ -> \uXXXX の形式でも ok 57155 - done: keymap/emacs.sh 57156 - ble/widget/emacs/append-arg 57157 これは bind した文字しか来ない筈だが…。★ -> won't support 57158 ここで得られた文字は _ble_edit_arg に追記されるが、 57159 そもそも参照する時に 0-9 や - のみしか使っていないので、 57160 それ以外の文字の取扱は正しい encoding だろうと文字化けだろうと変わらない。 57161 寧ろ、数字や - 以外の文字が来るとエラーメッセージが表示される気がする。 57162 - done: keymap/vi.sh 57163 - ble/keymap:vi/register#dump -> ok 57164 これは登録したレジスターの数字しか来ないはず。つまり ASCII だけのはず。 57165 と思ったが見てみると普通の文字にも割り当てられる様になっている気がする。 57166 しかし、これは何れにしてもユーザに対して表示する内容の生成であるので、 57167 \u???? の様な表示になっていても問題ない…というより寧ろ好ましい。 57168 - ble/widget/vi-command/append-arg 57169 input_encoding★ -> won't support 57170 これはそもそも数字以外が来ると assert で引っかかるはずである。 57171 また assert を通過しても結局 _ble_edit_arg に登録されるだけなので、 57172 問題が起こるとしても編集コマンドに対する引数が理解できないという物に留まる。 57173 - ble/widget/vi_nmap/record-register 57174 keylog で記録されたキー列を文字列にして記録する。 57175 input_encoding によった unicode★ -> done 57176 これについては CSI 27;1;code ~ 形式で記録する事にした。 57177 - ble/widget/vi_nmap/record-register.hook -> ok 57178 register名に使用している。input_encoding によった unicode の気がする。 57179 これはステータスに表示する "REC @?" の文字列を生成する箇所なので、 57180 変な文字になっても実害はない。 57181 寧ろユーザにわかりやすい様に \u???? の形式が望ましい。 57182 - ble/widget/vi-command/search-char.impl/core★ -> ok [self-insert] 57183 これは検索文字列に新しく追加する文字の生成である。 57184 input_encoding で変換されて得られたコードが来る。 57185 際どい所だが self-insert と同じ取扱で良い。現状ではそのまま。 57186 - ble/keymap:vi/text-object.hook★ -> won't support 57187 これは text object の二文字目の入力である。 57188 iw aw a[ などに於ける二文字目であり、普通は ASCII の範囲である。 57189 もし独自に拡張して Unicode 文字を受け取る様にしたとしても、 57190 現在の LC_CTYPE で表現できない様な文字に関してまで正しく動作する必要はない。 57191 従って、これは \u???? のままで良い。 57192 - ble/keymap:vi/.check-text-object★ -> ok 57193 これは text object の形式を確認する為の物。 57194 一文字目が i または a である事を確認する。 57195 それ以外の場合には常に false になるので、どの様に変換されても問題ない。 57196 - ble/widget/vi_xmap/visual-replace-char.hook★ -> ok [self-insert] 57197 これは範囲置換で埋めるのに使う文字を取得するのに使っている。 57198 self-insert と一貫していれば良い。 57199 幅の計算も code から計算した物を用いているがそれで良い。 57200 self-insert でその様にしているから。 57201 - lib/vim-surround.sh 57202 - ble/widget/vim-surround.sh/omap★ -> won't support 57203 これは二文字のオペレータの二文字目を取得するのに使う。 57204 オペレータ名に非ASCIIは恐らく使わないし、 57205 使うとしても LC_CTYPE でサポートされない文字の時にはその機能は使えなくて良い。 57206 - ble/lib/vim-surround.sh/get-char-from-key★ -> ok [self-insert] 57207 これは ble/lib/vim-surround.sh/async-inputtarget.hook から使われていて、 57208 更に async-inputtarget を使用して遅延して処理される全ての処理で使われている。 57209 つまり vim-surround で続きの文字を待っている時には必ずこれが使われる。 57210 これはどの様に処理したら良いだろう。 57211 操作を選択する文字という観点で言えばどうせそもそも使われないので 57212 \u???? のままでも良い気がする。しかし、囲むのに使う文字を入力する場合には、 57213 これは self-insert と一貫していて欲しい。 57214 取り敢えず self-insert と一貫した設計にするという事にする。 57215 57216 57217 使用箇所を調べてみて考えた事は、変換先の文字が存在しない場合には、 57218 一律で変換後の文字を定めるのではなくて、それぞれの場合で適切な処理をしなければならないという事。 57219 例えば、"?" や "_" に変換してしまうと vim-mode で意図しないレジスタが使用されることになったりする。 57220 また、場所ごとに適切なロケールを使用して ble/util/c2s を呼び出すというのも必要かもしれない。 57221 入力を処理する時には LC_CTYPE=C.UTF-8 にして行うなど? 57222 但し、実行するコマンド文字列に含まれる物に関してはやはり環境の LC_CTYPE を使用するべきである。 57223 57224 - done: (ble-edit) self-insert は複数文字に変換されても大丈夫な様に修正した。 57225 - ok: self-insert insert-mode の時の複数文字の時の振る舞いは正しいのか? 57226 →確かめてみた所、特に問題はないようだ。 57227 57228 - done: ble-decode.sh に含まれる c2s に関してはどの様に取り扱えば良いのか微妙である。 57229 57230 | テーブル k2c 及び c2k に含まれる文字列の文字コードをどの様に変換すれば良いのだろうか。 57231 | 登録した瞬間の文字コードによる文字列を用いるのだろうか。 57232 | 一文字の文字の場合には c2s を用いる様にしたら良い。 57233 | 特殊キーの場合には…c2k と k2c を同時に登録していれば、 57234 | c2k に見つからなかった時点で単一の文字と確定するが… 57235 | 57236 | 或いは、これについても文字コードが変化した瞬間に 57237 | 登録されている文字列の文字コード変換を実行するか。 57238 | 文字コードの変換を実行するのは始末が悪い気がする。 57239 | また文字コードの変更を検出するのも面倒である。 57240 | 57241 | 調べてみたところ k2c を設定した時 c2k も一緒に設定されている。 57242 | また k2c が設定されるのは特殊キーとしてのみであり、 57243 | 普通のキーについてわざわざ k2c が設定される事はない。 57244 | つまり、c2k が見つからないという事は特殊キーとしてそもそも登録されていないキーという事であり、 57245 | 通常の文字ということである。というか、if の条件式を見ると明示的にその様になっていた。 57246 | その場合にはキャッシュしない様にして ble/util/c2s を必ず呼び出すことにすれば良い。 57247 | そもそも ble/util/c2s がキャッシュしているのだし、 57248 | また c2k が使用されるのは ble-bind -d の時やエラーメッセージの時など限られているのだから、 57249 | 速度についてはそれ程気にしなくても大丈夫のはずである。 57250 57251 ble-decode-kbd/.get-keyname は ble/util/c2s の locale 毎の切り替えに一任して、特に何もしないこととした。 57252 但し、今までキャッシュする様にしていたのをキャッシュせずに c2s のキャッシュから読み取る事にした。 57253 ble-decode-char/csi/print についても同様。 57254 他の ble-decode.sh 内の仕様は全て ASCII の範囲内の文字に対する使用であるので、 57255 対応する文字が存在しないという事はないものとして扱う。 57256 57257 - done: ble/util/s2c のキャッシュも問題になるのではないか。 57258 特にこれこそ LC_CTYPE の影響を受けて変化する物のはずである。 57259 bash-4.0 でキャッシュを行っている。 57260 これについてもキャッシュをクリアする事にした。 57261 57262 * bug: LANG=C bash で起動すると動かなくなる [#D0698] 57263 57264 | bind が壊れている様子である。 57265 | 57266 | - ble-bind -D や ble-bind -d を見ても異常はない。 57267 | - .cache/blesh/*.bind の周りを見ても異常はない。 57268 | - padparadscha では bash-3.0 から bash-dev まで再現するが、 57269 | chatoyancy では再現しない。 57270 | - bind -X を見て気づいたが変な値に bind されている。 57271 | 例えば bind -x '"\C-@": ble-decode/.hook 128' などである。 57272 57273 これは以下の通り bash のバグに起因するものであると判明した。 57274 57275 - LANG=C bash --norc で起動して 57276 bind -x '"\C-a": echo C-a' 57277 bind -x '"\201": echo 201' 57278 としてから C-a を入力すると 201 が表示される。 57279 bash-3.0 から bash-dev まで再現する。 57280 57281 bind -x '"\201": echo 201' だけだと、 57282 bind -X の表示は '"\C-a": echo 201' となるが有効にはならない。 57283 恐らく通常の key binding に関しては問題は起こっていないが、 57284 内部のコマンド文字列を保持している cmd_xmap に登録する時に問題が起こっている。 57285 57286 - chatoyancy ではならない。Cygwin, padparadscha 32bit ではなる。 57287 32 bit 環境だとなると予想される。 57288 57289 - LANG はそのままに LC_CTYPE=C とだけしても再現する。 57290 - 普通に起動してから LC_CTYPE=C にして、 57291 その後で bind しても再現しない。 57292 bash を起動した瞬間の LC_CTYPE が効くようだ。 57293 cmd_xmap の構築時の問題だろうか。 57294 57295 Work around として、この問題が発生している時には 57296 bind -x で 80-FF に bind しないという手がある。 57297 もしくは別の文字を通して迂回する。 57298 57299 取り敢えず bind の順番を変更して全然動かないという状態にはならない様にした。 57300 57301 % [80-FF を迂回して読み取る方法を考える] 57302 % 57303 % a 何れかの文字を犠牲にするしかない。 57304 % 0-127 の中で遅延が起こっても 57305 % 問題がなさそうな文字はどれだろうか。 57306 % うーん。そんな文字は存在しない気がする。 57307 % 制御文字も \C-@ - \C-_ として使われている。 57308 % 57309 % と思ったが ESC に関しては遅延が起こっても問題ないのでは。 57310 % 57311 % b 或いは、何らかの方法を用いて 80-FF に 57312 % bind -x する事ができるだろうか。 57313 % Bash のソースコードを見たら分かるかもしれない。 57314 % 57315 % \C-x\C-r の re-read-init-file を呼び出してみたが 57316 % 正しく bind できない事に変わりはない。 57317 % LANG や LC_ALL を設定して実行してみても変化はない。 57318 % 57319 % [bash debug] 57320 % 57321 % 取り敢えず怪しいのは cmd_xmap の構築時である。 57322 % 他に怪しいのは bind_keyseq_to_unix_command 内で kseq が化けてしまっているという可能性。 57323 % 57324 % bashline.c:4312: rl_generic_bind (ISMACR, kseq, value, cmd_xmap); の直前で、 57325 % kseq を print してみる。bind -x '"\201": echo 201' に対して "\\201" という文字列だった。 57326 % この時点では変換前ということなのだろう。 57327 % 57328 % FILE* file = fopen("/home/murase/b1.txt", "wb"); 57329 % fprintf(file, "kseq='%s'\n", kseq); 57330 % fclose(file); 57331 % 57332 % bind.c:378: rl_generic_bind の実装の中の rl_translate_keyseq 57333 % の呼び出しの直後でどの様に翻訳されているかを確認する。 57334 % この時点ではちゃんと "\201" という文字列になっていた。翻訳は大丈夫。 57335 % 57336 % FILE* file = fopen("/home/murase/b2.txt", "wb"); 57337 % fprintf(file, "kseq='%.*s'\n", keys_len, keys); 57338 % fclose(file); 57339 % 57340 % bind.c:397: if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) 57341 % という怪しい分岐がある。ここで meta を削除している。これなのではないか。 57342 % これの前後で ic がどう変化するのかを調べてみる事にする。 57343 % 結果として、ここで \201 が \001 (C-a) に変換されている事が判明した。 57344 % 57345 % FILE* file = fopen("/home/murase/b3.txt", "wb"); 57346 % fprintf(file, "ic='%c' (%d)\n", ic, ic); 57347 % 中略 57348 % fprintf(file, "ic='%c' (%d)\n", ic, ic); 57349 % fclose(file); 57350 % 57351 % _rl_convert_meta_chars_to_ascii というオプションが怪しい。 57352 % bind -v してみると set convert-meta on という行がある。 57353 % 調べてみると、問題が発生する状況では on になっていて 57354 % 問題が発生しない状況では off になっているという事が分かった。 57355 % つまり、この変数を変更すればちゃんと bind できるのではなかろうか。 57356 % 57357 % 取り敢えず set convert-meta off にして試してみる事にする。 57358 % 調べてみると set convert-meta on の時には、 57359 % 入力された 128-255 の文字は全て Meta + 0-127 と解釈される様だ。 57360 % なので bind の瞬間だけ set convert-meta off にしておいて、 57361 % bind が終わったら元に戻すようにしたい。 57362 57363 結局 bash のバグというよりは rl 変数の convert-meta の仕様(?)という事が分かった。 57364 仕様だとしても bind -x '"\201": echo 201' が動かないばかりか、 57365 既存の別の keymap を上書きしてしまうという動作は変なのではないかという気がするが…。 57366 57367 bind する時だけ一時的に convert-meta off にする様にして修正した。 57368 と思ったがそれで日本語を入力するとメモリを大量に使って死んでしまう。 57369 ble.sh をロードしている間は convert-meta は off にしておくべきだろうか。 57370 detach する時に元に戻す。 57371 57372 2018-05-24 57373 57374 * 2018-03-19 bash-bug: bash-4.4, dev で以下を実行するとエラーメッセージが出る。 [#D0697] 57375 57376 →これは修正報告した。 57377 https://lists.gnu.org/archive/html/bug-bash/2018-05/msg00020.html 57378 57379 2018-08-05 Note 57380 これは keymap 切替時に出てくる謎のエラーメッセージにより判明した (#D0692)。 57381 これは bash 側の問題であるし、実害も余りないので対処しない。 57382 57383 $ function A { bind -x '"\C-t":A'; } 57384 $ A 57385 <C-t><C-t>... 57386 57387 これは微妙な操作なのでそのまま報告しても無視されるかもしれない。 57388 これについても原因を解明してから対処したいものである。 57389 57390 そもそも bind -x を実行している箇所は何処だろう。 57391 bash_execute_unix_command で実行している。 57392 うーん。これを解決するには 57393 57394 a bash_execute_unix_command において 57395 実行するコマンドの文字列を予めコピーしておく。 57396 b builtins/evalstring.c: parse_string() において 57397 一つずつコマンドを実行するのではなくて、 57398 まとめて読み取って実行するモードを付け加える。 57399 57400 然し、その為には yyparse を弄るなどしなければならず大変? 57401 57402 論点 57403 57404 - 微妙な操作であるがこれは reduced test case だから。 57405 自分はもっと複雑な処理で実際に必要と判断している。 57406 - コマンドを 57407 - 攻撃の対象になる可能性がある。 57408 - 少なくとも、現在実行中のものに bind しても大丈夫にするか、 57409 現在実行中かどうかを検出して実行中ならばエラーを吐くなどする必要がある。 57410 自分は使っているので大丈夫なようにする方を望む。 57411 また大丈夫なようにするのは比較的簡単で、 57412 cmd をコピーすれば良い。 57413 57414 コストが大きいように感じるかもしれないが、 57415 どうせ evalstring で command を parse するなどするので、 57416 元々のコストが大きいので気にしなくても良い。 57417 また、キーボード入力の解釈にそんなに性能は不要のはず。 57418 57419 * 2018-05-22 どうも history search で見つからない場合に無限ループになる様だ。 [#D0696] 57420 57421 →無限ループではなく処理に時間がかかっているだけだった。 57422 問題は .bash_history に 55KiB の履歴行が魂友していた事にある。 57423 何故その様な行が入っていたのかのはっきりした理由は分からないが、 57424 それは再度発生した時に確認することにする。 57425 57426 これは大層困ったバグである。直ちに修正する必要がある。 57427 先ずは何処か適当な場所で何か出力する様にする。 57428 先ずは ble-edit/isearch/next-history/forward-search-history.impl に仕掛けてみたが通過しない。 57429 謎だ。ちゃんと反映されているのだろうか。 57430 と思ったら backward search の時には特別に blockwise search を使うのだった。 57431 57432 どうも原因は isearch/process の外で起こっている様だ。謎だ。 57433 一致が起こって検索が完了した後に無限ループになっている。描画関係だろうか。 57434 もっと外側で調べなければならない。 57435 57436 ble-decode/PROLOGUE, ble-decode/EPILOGUE を確かめてみたがそれでも動かない。 57437 更に外側で起こっている? というか idle ループが問題になっているのでは? 57438 と思ったが、改めてよく見ると EPILOGUE の最後の最後で止まっている様だ。 57439 ble-edit/bind/.tail である。 57440 更に ble/textarea#render の中で起こっている。 57441 その中の ble/textmap#update で起こっている。 57442 何と分かったことは、bash_history の中に意味不明に長いコマンドが登録されている事だった。 57443 55 KiB ある行が二つ登録されている。実際にこのような長いコマンドを入力した記憶はない。 57444 57445 だとすれば何らかの問題によって、このように長い偽コマンドが登録された事になる。 57446 普通の bash ではそのような事が起こるとは思えないし、 57447 やはりこれは ble.sh の問題のような気がする。 57448 うーん。(history -p -- 'echo *') も ble/uti/assign aaa 'echo *' も異常はない。 57449 前後に echo * を展開したらしきものもあったので、 57450 これは何か特殊な操作を実行した時のテストで生成された結果だったのだろうか。 57451 うーん。何れにしても、ble.sh 自体に無限ループがある訳ではないようだし、 57452 その様な変な履歴項目が生成される確率も低い (もしくは一時的なものだったかもしれない) ようなので、 57453 この問題についてはこれ以上考えなくて良いものと判断する。 57454 57455 2018-03-19 57456 57457 * bash-bug: bash-dev で ble.sh をロードするとクラッシュする [#D0695] 57458 57459 取り敢えず何処でクラッシュするのかだけは特定しておきたい。 57460 どんどん絞っていくと以下を実行しただけでクラッシュする。 57461 ~/.bashrc の先頭に書いても其処でクラッシュするので ble.sh の影響ではない。 57462 57463 bind -r '\C-j' 57464 bind -r '\C-m' 57465 57466 gdb で実行して bt で backtrace を見ると 57467 rl_generic_bind でクラッシュしている。 57468 bash-dev で見てみると lib/readline/bind.c で実装されている。 57469 どうやらクラッシュは、最後の方の 57470 57471 lib/readline/bind.c:460: (FUNCTION_TO_KEYMAP(prevmap, prevkey) == rl_binding_keymap) && 57472 57473 で起こっている。FUNCTION_TO_KEYMAP は (Keymap) prevmap[prevkey].function に変換される。 57474 prevmap 及び prevkey を出力してみると prevkey が滅茶苦茶な負の値になっている。 57475 57476 →これは報告した https://lists.gnu.org/archive/html/bug-bash/2018-03/msg00155.html 57477 57478 2018-03-18 57479 57480 * bug: [再現せず] bleopt_suppress_bash_output= で、入力された文字が表示されない [#D0694] 57481 これは initialize の -echo を消したら直ったが、 57482 何故これで直るのかが分からない。 57483 後で調べる必要がある。 57484 57485 これは chatoyancy での振る舞いである。 57486 これは padparadscha では再現しない。 57487 bash-4.4 でも再現しない。 57488 再度 chatoyancy で試してみたが再現しない。 57489 57490 * bug: bleopt_suppress_bash_output= で、一文字表示位置がずれる [#D0693] 57491 57492 | 元々、Bash が文字を出力する事を見越して一文字戻した位置にしているが、 57493 | その文字が実際には出力されていない、という事のような気がする。 57494 | 57495 | 因みに bash-3.2 以下ではずれは発生していない。 57496 | →これはそもそも adjust を使用していないからだった。 57497 | adjust を使用するのは READLINE_LINE に文字列を設定して置かないと、 57498 | C-d を検出する事ができなかったからである。 57499 | しかし bash-3.2 ではそもそもそれも出来ないので adjust はしない。 57500 | 57501 | bash-4.0 以上では READLINE_LINE に文字を設定して C-d で exit しない様にしつつ、 57502 | READLINE_LINE の描画が行われる事を前提として調整を行う。 57503 | しかし、いつの間にかに READLINE_LINE の内容が描画されない様になっていた。 57504 | 昔は確かに描画されていて問題になっていたので、これでちゃんと調整できていたはずだ。 57505 | 57506 | stty などの何らかの設定の影響を受けて描画されたりされなかったりするのかもしれない。 57507 | →どうやら stty -echo の状態だと何も出力されないという事の様だ。 57508 57509 結論: stty -echo にすると Bash は何も出力しなくなるので、 57510 READLINE_LINE に有限の長さの文字列が入っていても問題は起こらない。 57511 57512 2018-03-18 57513 57514 * bash-bug: chat で "set -o vi/emacs" すると直後にエラーメッセージが出る [#D0692] 57515 →これは結局 bash-4.4 のバグの様に思われる。 57516 set -o vi/emacs でエラーメッセージが表示されるだけで実害はないので対応はしない。 57517 57518 エラーメッセージは stdout.off の間に起こっている様である。 57519 57520 stdout.off stdout.on の呼び出しを観察してみると on が連続で二回呼び出されている箇所がある。 57521 (単に、これは stdout.off が呼び出される前にエラーで中断したという事かもしれないが。) 57522 57523 うーん。エラーメッセージは前回の off とその直後の on の間に起こっている筈である。 57524 先ず stdout.off に関しては 57525 ble-edit/exec:gexec/.end -> ble-edit/bind/.tail -> stdout.off と呼び出されている。 57526 ble-edit/bind/.tail は stdout.off を最後に呼び出しているので、 57527 ここでエラーメッセージが出る事はない。 57528 ble-edit/exec:gexec/.end についても ble-edit/bind/.tail を最後に呼び出している。 57529 そうすると $_ble_decode_bind_hook に設定されている値が怪しい。 57530 57531 うーん。エラーメッセージが出た可能性のある時の _ble_decode_bind_hook の値は 57532 以下の通りである。特に怪しい所はないし gexec/.end は実際に呼び出されているし、 57533 gexec/.end より後に実行されている物も存在しない。 57534 57535 | ble-edit/exec:gexec/.begin 57536 | builtin eval -- 'ble-edit/exec:gexec/.eval-prologue '\''set -o vi'\'' "$_ble_edit_exec_lastarg" 57537 | set -o vi 57538 | ble-edit/exec:gexec/.save-last-arg' 57539 | ble-edit/exec:gexec/.eval-epilogue 57540 | trap - INT DEBUG 57541 | ble-edit/exec:gexec/.end 57542 57543 という事は、 stdout.off の直後ではなくて、stdout.on の直前が怪しいという事になる。 57544 呼び出しの順序は ble-decode/.hook → ble-decode/PROLOGUE → ble-edit/bind/.head → ble-edit/bind/stdout.on 57545 の様になっている。chat では特に $bleopt_suppress_bash_output を弄っていないので、 57546 この時には ble-edit/bind/.head は単に stdout.on を呼び出すだけである。 57547 ble-decode/PROLOGUE を見てみると .head より後に何か呼び出している。と思ったが、 57548 エラーメッセージが出てくるのは直後ではなくて直前のはずなので、 57549 .head より後に呼び出している物に関しては気にしなくても良い。 57550 そうすると ble-decode/.hook が悪いという事になるが、 57551 IFS を設定している以外には PROLOGUE より前には何も実行していない。 57552 57553 こうなってくると次に怪しいのは bind の中身である。 57554 更に気付いた事は、これは chat に特有というよりは bash-4.4 に特有の様である。 57555 padparadscha の bash-4.4 でも再現した。 57556 何れにしても調査を続ける事にする。 57557 うーん。bind -spX の出力は stdout.on, off で見張っても変化していない。 57558 57559 - detach/attach の前後で出力してみようと思ったが…。 57560 これらは gexec の実行過程に組み込まれているので、 57561 タイミング的には set -o emacs/vi したのと同じ時に実行されている。 57562 なので、エラーメッセージがこの時に表示されるという事は元々ない。 57563 57564 - 或いは、bleopt_suppress_bash_output= として見たら状況は変わるか? 57565 57566 そうすると今度はまともに動かない…。何故だろう。 57567 -echo を指定したせいだろうか→その様だ。 57568 うーん。bleopt_suppress_bash_output と stty で何が関係しているのだろう? 57569 これについては後で調べる必要がある。 57570 取り敢えず調査の為に -echo は外しておく事にする。 57571 後、座標の位置が一文字ずれている…。 57572 Bash によって出力されると予想される物が出力されていないという事の気がする。 57573 57574 何れにしても bleopt_suppress_bash_output= でも再現した。 57575 (この場合には画面に直接エラーメッセージが出力される事になる)。 57576 57577 - もしかすると set -o emacs; set -o vi としただけでもエラーメッセージが出るかもしれない。 57578 と思ったが何も起こらなかった。やはり binding を弄るとなるという事なのか? 57579 57580 - 或いは、set -o emacs は全然関係なくて単に ble-decode-detach 及び ble-decode-attach 57581 だけでもエラーメッセージが発生するのかもしれない→再現した…。 57582 更に、ble-decode/unbind; ble-decode/bind でも再現するか→再現する。 57583 これらの関数は基本的に source しているだけである。 57584 % と思ったら source しているファイルを cat してくっつけて、それを source すると再現しない。 57585 % % source *.unbind; source *.bind をしても再現しない。 57586 % % 関数の中では他に特別な事をしている様には見えない。 57587 % % という事は関数内から source すると駄目なのか。 57588 % % →やはり再現した。 57589 →source b.sh (b.sh は unbind と bind をくっつけたファイル) でも再現した。 57590 57591 - 次に b.sh を編集して試す。先ず初めに bash-4.3 と bash-4.4 の違いと言えば 57592 ^X を明示的に bind しているかどうかである。 57593 ^X を含まない b.sh を作ってみるとエラーメッセージは再現しなかった。 57594 ^X を含む行だけの b.sh を作ってみてもエラーメッセージは再現しない。 57595 改めて両方を含むファイルを source するとちゃんと再現する。うーん。 57596 57597 何と、中身を sort してみたら再現しなくなった。 57598 また、ble-decode/bind だけでも再現する。 57599 どんどん小さくしていくと、最終的に以下の一行を含むスクリプトで既に再現する。 57600 57601 bind -x '"\C-m":ble-decode/.hook 13; builtin eval "$_ble_decode_bind_hook"' 57602 57603 source せずに直接実行しても再現するという事を確認した。 57604 更に、これは C-j を使って実行している時には再現しない。 57605 57606 - つまり、bind -x において現在実行しているキーマップに 57607 -x を指定するとエラーになるという事だろうか。 57608 と思って bash --norc で以下を試してみた所、再現する。 57609 57610 $ function A { bind -x '"\C-t":A'; } 57611 $ A 57612 <C-t><C-t>... 57613 57614 これは明らかに bash-4.4 のバグである。 57615 bash-dev でも確認してみたが未だ治っていない。 57616 そして、これは ble.sh 側では何ともならない…というか頑張れば何とかなる可能性もあるが、 57617 現在の方法を滅茶苦茶に変更しなければならない気がするので非現実的である。 57618 57619 これは保留という事にする。 57620 57621 というか bash-dev で ble.sh をロードするとクラッシュする…。 57622 57623 * bug: "set -o emacs" もしくは "set -o vi" で切り替えた直後に stty が変 [#D0691] 57624 57625 何度か繰り返しても同じ様である。つまり初回だけなる等の事ではない。 57626 うーん。調べてみると、ble/term/finalize して ble/term/initialize している筈である。 57627 57628 →どうも ble/term/stty/initialize と ble/term/stty/enter で微妙に違いがある。 57629 前者の stty に -echo が指定されていない。今回は、新しく指定する事にした。 57630 ちゃんと動くか確かめる。 57631 57632 - ok: set -o vi 及び set -o emacs で動作する。 57633 - ok: source ble.sh で動く。 57634 - ok: bashrc からの読込でも動く。 57635 - ok: ble-detach & ble-attach でも動く。 57636 57637 * bug: mintty (横幅 56) で起動すると unbound keyseq ... 等の表示が欠ける [#D0690] 57638 57639 ble/term/visible-bell を手動で呼び出しても中途半端な所で欠けて表示される。 57640 調べてみた所、何と横幅を取得する所で行数を使っていた。 57641 57642 mintty で起動したらなったと書いたが、 57643 実際には縦の行数が少ない環境で実行するとなるバグだった。 57644 57645 * bug: insert mode で C-c にしても disabled の着色にならない。何か変だ [#D0689] 57646 57647 これは overwrite_mode レイヤーがキャッシュした着色を更新せずに使っていたのが悪い。 57648 overwrite_mode ではカーソル位置も文字列内容も変更がなかった時に、 57649 キャッシュした内容をそのまま使う様になっている。 57650 しかし、実際にはその他の要因 (_ble_edit_line_disabled など) で着色が変わるので、 57651 本来は毎回着色を変更するべきなのである。 57652 57653 しかし、それを言い出すと様々な箇所でキャッシュを使えるかどうかが微妙になって来る。 57654 _ble_highlight_layer__list=(plain syntax region disabled overwrite_mode) 57655 この設定の下で、より後に来る layer は前の layer の 57656 PREV_UMIN..PREV_UMAX について更新しなければならない。 57657 57658 というか、実は他にも表示が崩れるケースが有る。 57659 region 変化を overwrite_mode で検出していないので、 57660 $ echo hello world で overwrite-mode で "hello worl" の範囲を選択して home を押すと、 57661 "echo " だけが反転されるべきだが、"hello world" の選択着色が残ってしまう。 57662 57663 →実は、これは DMIN ではなくて PREV_UMIN を見て判定すれば良いだけなのでは。 57664 実際に変更があったかどうかは PREV_UMIN..PREV_UMAX を見れば分かる。 57665 なので、これだけ見て更新があったかどうかを判定すれば良いのだ。 57666 →実装した。動いている。 57667 57668 それとは別に disabled したのに overwrite_mode のカーソル位置が残るのは変なので、 57669 disabled は overwrite_mode レイヤーよりも後に持ってきたほうが良さそうだ。 57670 57671 * bug: PS1 で \v が空文字列である [#D0688] 57672 57673 後、\s にハイフンがない? と思ったら、これは ssh からのログインシェルだと 57674 -bash になるというだけの事の様だ。これは大丈夫。 57675 →これは単純なミスだった。直した。 57676 57677 * bug: bash-3.2 以下で _ble_syntax_attr: bad array subscript のエラーが出る [#D0687] 57678 57679 これは空文字列で確定をした時だけに起こる。 57680 調べてみると構文的に完結しているかどうかを判定する関数が悪かった。 57681 bash-3 では ((iN>0&&_ble_syntax_attr[iN-1])) だと iN=0 の時にエラーになってしまう。 57682 これは直した。 57683 57684 2018-03-15 57685 57686 * 単語着色の問題 (2017-11-26 reported by cmplstofB) [#D0686] 57687 57688 これについては項目が既にあるかと思ったが今探してみた所なかった。 57689 恐らく以下の項目が実装途中で放棄されているので、 57690 これに関連して起こっている物と解釈されて放置されていたのだろう。 57691 57692 | * 2015-08-16 入れ子構造を考慮に入れた効率的な単語着色 57693 57694 この単語着色の適用範囲の問題は以下の手順で再現する。 57695 57696 | $ touch abcdef 57697 | $ echo abc def ghi jkl 57698 | この状態で abc と def の間の空白を削除する。 57699 57700 さて、この時一体どの様な処理が走っているのかという事を確かめる。 57701 先ず、連結した瞬間に更新される単語は連結された単語だけであった。 57702 これは妥当である。 57703 57704 単語の着色を調べるとちゃんと範囲内に着色している。 57705 問題が起こるとすれば sgr を設定する箇所だと考えていたが、 57706 どうやら単語の着色を行う部分では単に属性値を配列に設定しているだけで、 57707 sgr を生成して出力する為の文字列を生成している箇所は別のところにある様だ。 57708 57709 highlight-layer:syntax で使用している buffer は、 57710 _ble_highlight_layer_syntax_buff であり、この配列に設定を行っているのは 57711 ble-highlight-layer:syntax/update である。 57712 確認してみると ble-highlight-layer:syntax/update で設定を行っている範囲が、 57713 umax の一つ手前までになっている。sgr を弄っているのだから、 57714 その次も更新しなければならないはずである。 57715 (描画範囲外なので更新しなくても良い様に思われたが、実際には後で再描画するかもしれないし、 57716 或いは更に上の layer で範囲が拡大される可能性もあったのである)。 57717 57718 修正した。 57719 57720 * 古い ToDo 項目の整理 [#D0685] 57721 57722 以下の物は対応済み、または、自然解消したものである。 57723 57724 | 2015-12-03 57725 | 57726 | * undo, redo 57727 | 57728 | * 色コード ble-color-gspec-list 57729 | → ble-color-show 57730 | 57731 | * bash-3 で C-d を捕獲する為のメッセージについて 57732 | 57733 | ignoreeof-messages.txt に入れてそれを grep -F で検索する様にした。 57734 | しかしながら ignoreeof-messages.txt の中身を読み込んでしまった方が速いかもしれない。 57735 | 57736 | 2015-12-01 57737 | 57738 | * vi bind 57739 | 57740 | 2015-11-18 57741 | 57742 | * complete: 存在しない変数名で補完しようとすると \ が挿入される。 57743 | ここは何も実行しないで欲しい所である。 57744 | 57745 | 2015-08-14 57746 | 57747 | * 高速化: $(type -t), $(printf), $(jobs) をファイル書き出し・read読み出しに変更する 57748 | 57749 | $() を read で実行する為の関数 ble/util/assign を作成した。 57750 | cygwin 環境で特に遅くなる原因と思われる部分についてはこれに置き換えた。 57751 | 57752 | 2015-06-28 57753 | 57754 | * complete: 沢山の補完候補が存在する時に表示する内容を絞る 57755 | 57756 | 2015-03-01 57757 | 57758 | * ble-edit: ble-bind -xf 対応 57759 | 57760 | 2013-06-01 以前 57761 | 57762 | * ble-decode 57763 | + ble-bind: -x オプションに対する対応: BLE_LINE, BLE_POINT, 再描画 57764 57765 以下のリロード可能にする機能については、 57766 動機である complete.sh の不整合が遅延ロード対応によって解消されたので、 57767 そもそも実装する意義を失った。今後も強い需要が出てくるとは考えにくいので削除する。 57768 57769 | 2017-09-25 57770 | 57771 | * ble.sh リロード機能? 57772 | 57773 | complete.sh の不整合で度々に問題になるのでリロード機能ぐらいはあっても良いのでは。 57774 | また complete.sh はそれ自身として対策は考えたほうが良い気はする。 57775 | 例えばバージョンごとにディレクトリを作成してその中で管理するなど。 57776 | 57777 | 以前 declare -ir だったものを全て消した。 57778 | 実はリロードできるのではないか。 57779 | 但し注意するべき点はいくつかある。 57780 | 57781 | 先ず bind を再度実行すると変なことになると思われる。 57782 | これについては何らかの変数で現在 bind 中かどうかを判定していたはず。 57783 | 現在の状態に関する類似のものは色々あるが、これらについては上書きしないようにする必要がある。 57784 | 57785 | また bash-3.0 の C-d 対策に使用する子プロセスや、 57786 | stdout/on, off の状態などにも気をつける必要がある。 57787 57788 * 2017-10-22 edit: RET 文法に基づく改行挿入 [#D0684] 57789 57790 shopt -q cmdhist &>/dev/null を参照してこれを有効・無効にするのが良い。 57791 57792 - if .. fi, do .. done, { .. } の対応を取ることを考えていたが、 57793 よく考えてみると、実は、数を数えてバランスしているかを確かめれば良いのでは? 57794 後は case esac がある。これらは絶対に対になっているはずである。 57795 if があれば必ず fi が来る。case があれば必ず esac が来る。他の終わり方はない。 57796 57797 - for/until/while/select などは do .. done, { .. } で必ず囲まれるので 57798 本体の中身がバランスしているかどうかは上記の方法で終わっている。 57799 57800 然し、for/until/while/select が孤立して存在している場合もチェックしなければならない。 57801 これも for/while/until/select の数と do/{ の数を数え上げればいい気がする。 57802 57803 どうやって数えるのが良いだろうか。毎回 tree-enumerate したり、 57804 for in "${_ble_syntax_attr[@]}" するのは遅そうな気がする。 57805 例えば _ble_syntax_attr に特別な属性を指定しておいて、 57806 IFS= concat="::${_ble_syntax_attr[*]/%/::}" として、 57807 後は $concat に対する処理で何とか各属性の数を抽出できないだろうか。 57808 57809 pat=:$ATTR_KEYWORD_B: a=${concat//$pat}; bcount=$(((${#concat}-${#a})/${#pat})) 57810 pat=:$ATTR_KEYWORD_L: a=${concat//$pat}; lcount=$(((${#concat}-${#a})/${#pat})) 57811 pat=:$ATTR_KEYWORD_R: a=${concat//$pat}; rcount=$(((${#concat}-${#a})/${#pat})) 57812 57813 実際にループで回すのとどちらの方が速いかである。 57814 57815 - また、文脈値によっては未だ終了してはならない物が決まっているのでそれを見る。 57816 例えば function aaa() の直後などもこれに含まれる。 57817 57818 - nest の状態も見る。 57819 - ヒアドキュメントの待ちキーワードも確認する 57820 57821 その他のエラーについては、"続きが必要" という種類のものではないので、 57822 RET を以て改行を挿入して続きを入力するという機能にする必要はない。 57823 57824 [実装] 57825 57826 取り敢えず一番簡単な物から実装していく事にする。 57827 57828 nest の状態を見るのが良い。 57829 ble-syntax/parse の最後で nest のチェックをしているので、 57830 それと同等のチェックを行う様にすれば良い。 57831 57832 というかその前にチェックを行う関数を何処に定義するのか決めなければならない。 57833 実際の実装は ble-syntax の内部実装に関わって来るので、 57834 これは syntax 側で実装するようにするのが良い。 57835 57836 - done: nest が設定されていない事を確かめる 57837 - done: ヒアドキュメントの予約がない事を確かめる 57838 - done: 最後の文字にエラーが設定されていない事を確かめる 57839 - done: 最後の解析再開点の文脈がその場で終わっても良い様なものか。 57840 57841 % if..fi, do..done, {..}, case..esac については数が一致している事を確認すれば良い。 57842 % if..then, elif..then, for/until/while/select..do/{ に関してはどの様にチェックすれば良いか。 57843 % 特に { に関しては孤立して現れた { なのか、構文の一部としての { なのか区別が付かない。 57844 % 57845 % うーん。特に { の場合には for/select の直後のコマンドが { であるべきである。 57846 % (調べてみた所 while/until の場合は {..} ではなくて必ず do..done の様だ)。 57847 % そしてこの時、文脈値が特別な値になっているのではあるまいか。 57848 % と思ったが ; の後に {..} が来るパターンには対応していない。 57849 % というか現在の実装だと ; の直後に何もコマンドがない場合でもエラーにならない。 57850 % 57851 % ; の直後に { または do を要求する文脈というのを追加しても良いのではないだろうか。 57852 % 57853 % →これらに関しては、do..done ではなく while..done の組にする事にしたので、 57854 % 改めて考察し直すことになった。 57855 57856 [どのように対を判定するかの議論] 57857 57858 a そもそも対になっているものをどのように判定するのが良いだろうか。 57859 一つの方法は、上で提案された様に対になるものについて特別な attr 57860 (ここでは begin と end とする) を設定して、 57861 最終的にその数があっているかを確認する物である。 57862 57863 この方法だと数が一致しているだけで順番が滅茶苦茶な場合でも accept してしまう。 57864 57865 # 或いは、_ble_edit_attr に現れる順番も含めて検査するという手もある。 57866 57867 b もう一つの方法は nparam によって現在どのような構文の中にいるかを記録するもの。 57868 57869 % この方法だとインデントの実装が楽になる。 57870 % というか、最終的にインデントを実装しようとしたら、 57871 % 結局この様な方法に頼らざるを得ないのではないか? 57872 % 57873 % と思ったが a の方法を採用していたとしてもインデントは処理できる気がする。 57874 % 現在の入れ子の開始点から現在位置までの間に何個の begin と end 57875 % があるかを数えれば良いだけである。 57876 57877 x この方法だと解析をやり直す範囲が増大する。 57878 57879 - ちゃんと構文が閉じているかの判定にかかる処理量が減少する。 57880 と思ったが、構文が閉じていることの判定は RET を押した時ぐらいにしか行わないので、 57881 この点において効率化しても仕方がない。 57882 57883 つまり、構文が閉じているかどうかを判定する頻度は少ないのだから、 57884 できるだけ解析時の処理量は少なくして、実際に判定が要求された時に、 57885 判定が可能になるような最低限の情報を埋め込むというのが望ましい。 57886 57887 その様に考えるとこの方法は若干処理が複雑になるので避けたい。 57888 57889 やはり基本的には当初の考えの通り、a の方針で実装する事にする。 57890 従って、やはり while/until/for/select の直後に文を要求する。 57891 57892 [どの予約語の間で対にするべきかの議論] 57893 57894 a while, until に関しては…現在の実装ではすぐに通常の CTX_CMDX1 に移行する。 57895 従って、2つ目のコマンドに対して do を要求するというのを実装するのは、 57896 文脈値で処理するのは難しいように思われる。 57897 これにこそ nparam を使うという考え方がある。 57898 次に do が現れるまでを範囲とする。 57899 57900 b 然し… while .. do .. done / until .. do .. done という構成を考えると…。 57901 寧ろ、while..done, until..done で対応を取ったほうが良い様な気もする。 57902 同様に for..done と select..done で対応を取る。 57903 そして for .. { .. } と select .. { .. } を例外として特別に処理する方が良い。 57904 for .. { の時は "{" には begin を設定しないという様にするのはどうだろうか。 57905 for/select については直前まで特別な文脈値で処理するので、 57906 "{" に対して特別な取り扱いを行う事は比較的簡単のはずである。 57907 57908 [for/select 直後の文脈の調整] 57909 57910 | 特に for/select が終わった後の ; の直後として do または { だけを許す文脈値を作れば良い。 57911 | その文脈値の時には { に begin 属性をつけない様にする。 57912 | と思ったら既に CTX_CMDXD という文脈値がある。これだろうか。 57913 | と思ったが、この文脈値は他に ";" も許す文脈であった。 57914 | つまり、今必要なのでは CTX_CMDXD の ";" を許さない版である。 57915 | 57916 | % うーん。或いは、CTX_CMDXD で "; do" まで一気に読み取ってしまうという手もあるのかも。 57917 | % →いや、これは微妙である。何故なら途中にコメントが入る事もあるし、 57918 | % また改行が複数入る可能性もある。 57919 | 57920 | 現在の for 及び CTX_CMDXD の実装が色々変だ。 57921 | 57922 | - 先ず初めに CTX_CMDXD の直後に ; が来ることが許されている。この時 CTX_CMDX に切り替わる。 57923 | - for a in 1 2 3 ; の直後で CTX_CMDXD の状態になっている。 57924 | つまり、この時更に ; を重ねてから do を書いても構文エラーにならない。 57925 | しかし、実際にはこれは構文エラーである。 57926 | - for (()) を出た瞬間の文脈は CTX_CMDXD だが、; が来ると CTX_CMDX に切り替わる。 57927 | つまり for (()) echo は構文エラーを検知できるが、 57928 | for (()); echo は構文エラーを検知できない。 57929 | 57930 | 以下の様に実装を変更したい。 57931 | 57932 | - CTX_CMDXD の直後に ";" が来ることは許さない。改行は OK 57933 | - for a in 1 2 3 ; の直後は CTX_CMDXD のままで良い。 57934 | select に関しても同様の処理で問題ない 57935 | (というか select も FARGX3 を使うので特別に気にしなくて良い)。 57936 | - for (()) の直後は特別な文脈にする。 57937 | ";" または "改行" などが来て初めて CTX_CMDXD に移行する。 57938 | 57939 | さて、現状の実装で CTX_CMDXD の直後に ";" が来ることを許容しているのはどの部分だろうか。 57940 | 少なくとも、CTX_CMDX は ";" を許容しないので CTX_CMDXD について特別の判定をしている筈である…。 57941 | 見つけた。以下の行である。 57942 | 57943 | _ble_syntax_bash_command_Opt[CTX_CMDXD]=1 57944 | 57945 | この行を削除しても問題ないだろうか。 57946 | 先ず _ble_syntax_bash_command_Opt は一箇所でしか使われていない。 57947 | 次に、これは delimiters が来た時に使われている (改行が来た時には使われていない)。 57948 | →この行は削除してしまって問題ないだろう。 57949 | 57950 | 次に for (()) の直後に来るべき文脈について考える。 57951 | これについては実のところ CTX_CMDXD の複製で問題ない様な気がする。 57952 | 取り敢えず現状の CTX_CMDXD を複製した。 57953 | 57954 | - done: あと調整しなければならないのは、 57955 | ";" が来た時に CTX_CMDXD0 から CTX_CMDX になるのではなく、 57956 | CTX_CMDXD になるという事。対応した。';' が来た時に FARGX3 と同様に処理すれば良い。 57957 | 57958 | - done: 改行が来た後に CTX_CMDXD0 から CTX_CMDXD に移行するという事。 57959 | これも同様に改行が来た時に FARGX3 と同様に処理すれば良い。 57960 | 57961 | x done: 試してみると for a ; の直後の文脈が CTX_CMDX になっている。これについても処理する。 57962 57963 [対にする処理の実装] 57964 57965 既に決定した様に _ble_syntax_attr を用いて判定する。 57966 57967 - done: 新しく文脈値(属性)を用意する。 57968 57969 - ATTR_CMD_KEYWORD → ATTR_KEYWORD 57970 - new ATTR_KEYWORD_{BEGIN,END,MID} 57971 ATTR_KEYWORD_MID は後でインデントを実装する際に使用する。 57972 57973 - done: 次に各キーワードに ATTR_KEYWORD_{BEGIN,END,MID} を割り当てる。 57974 正しく実装できている事を以下のコードで着色して確かめた。 57975 57976 | ble-color-defface command_keywordB fg=blue,bg=225 57977 | ble-color-defface command_keywordE fg=blue,bg=192 57978 | ble-color-defface command_keywordM fg=blue,bg=195 57979 | _ble_syntax_attr2iface.define ATTR_KEYWORD_BEGIN command_keywordB 57980 | _ble_syntax_attr2iface.define ATTR_KEYWORD_END command_keywordE 57981 | _ble_syntax_attr2iface.define ATTR_KEYWORD_MID command_keywordM 57982 57983 後は、_ble_syntax_attr で該当項目の数を数えれば良い→実装した。 57984 57985 以下の項目は自然解消したと考える。 57986 当初はエラー着色がある場合には常に実行しないという案もあったが、 57987 ただ単に ble.sh の構文解析の不足によってエラー着色が起こる場合もあるし、 57988 構文エラー以外の理由でエラー着色がある場合も考えられるので、 57989 取り敢えずの所は明らかに構文が閉じていないなどの時にだけ改行挿入する事にする。 57990 57991 | 2015-08-20 57992 | 57993 | * エラーがある時にはコマンドを実行できない様にする 57994 | 57995 | 一番明らかな物は一番初めのコマンドが見付からない場合である。 57996 | また、文法構造にエラーがある場合も含まれる。 57997 | 文法構造にエラーがある場合は ATTR_ERR が指定されている筈である。 57998 | 然し乍らそれ以外にはエラーを得る情報が無いとも言える。 57999 | エラーがある時のコマンド実行について考える前に、 58000 | 先ずはエラーの処理について再考しておいた方が良いような気がする。 58001 | 58002 | 2013-06-01 以前 58003 | 58004 | * 問題点 58005 | + コマンドが完結していない状態で accept-line すると 58006 | 既定の動作では続きを入力する事が出来るが、 58007 | eval をすると単にエラーになってしまう。 58008 | 58009 | →これは寧ろこの様な動作の方が分かりやすいかも知れない。 58010 | 取り敢えずそういう仕様と言う事にする。 58011 58012 2018-03-14 58013 58014 * 2017-09-23 emacs mode でも複数行のときにはそれが分かるような表示を行いたい [#D0683] 58015 58016 これを実際に実装するためには _ble_edit_str に変更がある全ての箇所で、 58017 複数行モードになったか、或いは逆に単一行モードになったかをチェックする必要がある。 58018 とは言っても _ble_edit_str を変更する箇所はそんなに多くないはずである。 58019 58020 それとは別に現在の引数の状態も表示したい。 58021 これには _ble_edit_arg が変更された箇所でも変更を行う必要がある。 58022 58023 表示は keymap/vi の時と同じ様に ble-edit/info/default raw "..." で実行すれば良い。 58024 58025 a さて、問題は具体的に一つ一つの widget について 58026 モード表示の変更の可能性がある操作の直後に更新をチェックするか、 58027 58028 b 或いは、__after_command__ にチェックのコードを挿入してしまうか。 58029 実は、既に __after_command__ で undo のチェックをしているのではないか? 58030 と思って確かめてみた所、それは __before_command__ の方だった。 58031 しかし、どうせ __before_command__ に設定しているのだから、 58032 __after_command__ に処理を追加しても良い様な気もする。 58033 何より沢山一度に入力した場合には描画を省略するなどして処理を軽くするのだから、 58034 __after_command__ 程度なら実行しても良い気がする。 58035 (と思ったが、貼り付けなどで大量に入力した時の待ち時間が長くなる気がする。) 58036 58037 取り敢えず __after_command__ で対応する事にした。 58038 58039 実装した。然し、quoted-insert を用いると実行されない。 58040 quoted-insert は _ble_decode_char__hook を使って実装されているからである。 58041 _ble_decode_char__hook は .call-widget を呼び出し、 58042 .call-widget は直接 eval するのみである。 58043 58044 a 一つの可能性は .call-widget を改造して __before_command__ 58045 及び __after_command__ を実行する様にする事である。 58046 実のところ hook を利用して実行する頻度は低いので効率的な面では問題はない。 58047 58048 次の問題は、既存のコードの動作に対する影響である。 58049 実のところ、.call-widget を呼び出しているのは、 58050 _ble_decode_char__hook と _ble_decode_key__hook の二つだけである。 58051 従って、そんなに影響範囲は大きくない。 58052 58053 しかし __before_command__ は undo を設定するのに使われている。 58054 また keymap/vi ではもっと複雑な事をするのに使われているのではなかったか。 58055 これらについて確認する必要がある。 58056 58057 - vi-imap/quoted-insert に関しては、寧ろ quoted-insert.hook で 58058 __before_command__ の真似事をしているので、 58059 .call-widget で __before_command__ を呼び出した方が良い。 58060 そうすれば self-insert を直接指定する事ができる気がする。 58061 58062 - 然し ble/keymap:vi/commandline/__before_command__ に関しては、 58063 特別なキーの組み合わせで処理をすりかえるのに使っている。 58064 これは _ble_decode_char__hook (quoted-insert) の時には素通りして欲しい。 58065 つまり、__before_command__ を使って key binding を動的に判定するのに使っているので、 58066 quoted-insert の様な key bindings を無視して文字を受け取りたい場合と相性が悪い。 58067 58068 これについては _ble_decode_key__hook 経由で呼び出している時には、 58069 無視するなどの対策を行うこともできるが、どうだろうか。直観的と言えるか。 58070 58071 - 更に ble/widget/bracketed-paste でも __hook が使用されている。 58072 vi_imap/bracketed-paste では最終的に実行する時に、 58073 一つ一つ imap-repeat/push を実行している。 58074 実は、__before_command__ が有効であれば一つずつ実行する必要がなかった可能性がある。 58075 但し、その時には paste の終端シーケンスを見つけたら、 58076 その終端シーケンスに対応するバイト数だけ imap-repeat/pop を実行しなければならなくなる。 58077 どちらの実装のほうが綺麗かというのはよく分からない。 58078 58079 b 結局、.call-widget で __before_command__/__after_command__ を呼び出す様にすると、 58080 色々と面倒な事が起こりそうな雰囲気である。 58081 58082 keymap/vi の quoted-insert でやった様に、 58083 emacs 専用の quoted-insert を用意して処理したほうが良さそうである。 58084 後、bracketed-paste に介入する。 58085 58086 今回は b の方針で実装した。 58087 58088 * 2018-02-23 起動時間: ble-edit, ble-syntax の読み込み遅延の可能性 [#D0682] 58089 58090 これで、現在時間がかかる要因になっているのは恐らく ble.sh 本体のロード時間だけである。 58091 ble.sh 本体のロード時間を短縮するには ble.sh 自体を短くするしかない気がする。 58092 実際にそれを確かめる為に計測を行ってみる。 58093 source ble.sh にかかる時間と、ble.sh の中身全体を time { } で囲んだ時の時間から、 58094 ble.sh の構文解析にかかる時間と、ble.sh の実行にかかる時間を別々に評価できる。 58095 58096 ble.sh 読み取りと実行 real 0m0.245s 58097 \_読み取り 残り \_0m0.162s 58098 \_実行 real \_0m0.083s 58099 \_prologue real \_0m0.014s 58100 \_ble-core.sh real \_0m0.008s 1653L 49647B 58101 \_ble-decode.sh real \_0m0.013s 1924L 60832B 58102 \_ble-color.sh real \_0m0.002s 779L 26038B 58103 \_ble-edit.sh real \_0m0.016s 6983L 223652B *一部だけでも遅延可能か?* 58104 \_ble-form.sh real \_0m0.001s 147L 4384B 58105 \_ble-syntax.sh real \_0m0.013s 5082L 178816B *遅延可能か?* 58106 \_ble-initialize real \_0m0.010s 58107 \_その他 残り \_0m0.006s 58108 58109 やはり ble.sh の読み取りに時間がかかっている。 58110 また行数・バイト数の内訳で見ると ble-edit が一番重くて、 58111 次に ble-syntax.sh が重い。ble-edit の編集関数部分と、 58112 ble-syntax については遅延する事も可能な様に思われる。 58113 58114 2018-02-28 ble-syntax に関しては #D0680 で遅延読み込みに変更した。動作している。 58115 全体の読み取り時間は 0m0.185s にまで短くなった。実行は 0.070s である。 58116 単に ble-syntax.sh の部分が 0.013s から 0.001s になったのを反映している。 58117 結局読み取り時間は 0.115s になったと考えて良い。 58118 因みに、遅延評価に基づく core-syntax.sh の ble-import は 0.067s かかっている。 58119 58120 またコメントなどを除去したインストール版を使うと 58121 ble.sh のロード時間は 0m0.149s にまで短くなった。 58122 ble-attach の時間は (vi.sh の読み込みも含めて) 0.354s もかかっているが、 58123 実際の所、プロンプトの表示までにかかる時間は 0.036s である。 58124 インストール版を使うと ble-attach は 0.336s になるが、 58125 プロンプトの表示までにかかる時間は 0.036s で変わらない。 58126 58127 何れにしても現在の実装 (インストール版) では 58128 プロンプト表示までに合計で 0.185s かかる事になる。 58129 58130 ble-edit の遅延読み込みに関しては。 58131 前半の textarea の部分まではすぐに使うので遅延できない。 58132 widget 群に関しては遅延しても良いがそれほど効果を期待できるかは分からない。 58133 一部の使用頻度の低そうな widget に関しては遅延しても良いかもしれないが、 58134 ロードに失敗して何も出来なくなったりするのも嫌なので、やはり含めて置いた方が良いような気もする。 58135 実のところ、最近のコンピュータは十分速いので現状でもロードに 0.030s しかかからない様である。 58136 そういう事であれば、苦労して高速化する必要もないのではという気もする。 58137 58138 それとは独立に ble-edit.sh の中を整理したい気もする。 58139 58140 2018-03-14 高速化する為には ble-edit.sh を何千行と減らさなければならない。 58141 しかし、現状では雑多な機能が詰め込まれていて遅延読み込みにするのも面倒そうである。 58142 実のところ新しい計算機ではそんなに重くないということなどから、 58143 取り敢えずは ble-edit.sh のち円読み込みには対応しない事にする。 58144 ble-edit.sh の中の整理に関しては、遅延読み込みとは関係なく少しずつ薦めていきたい。 58145 58146 * 2016-09-11 やはり履歴のロード時間が気になる [#D0681] 58147 58148 | time test1=$(ble-edit/history/.generate-source-to-load-history) 58149 | real 0m3.211s 58150 | user 0m3.661s 58151 | sys 0m0.535s 58152 | 58153 | time eval -- "$test1" 58154 | real 0m2.472s 58155 | user 0m2.383s 58156 | sys 0m0.080s 58157 | 58158 | time _ble_edit_history_edit=("${_ble_edit_history[@]}") 58159 | real 0m1.552s 58160 | user 0m1.526s 58161 | sys 0m0.022s 58162 58163 generate-source-to-load-history が思いの外遅い。 58164 58165 time history | cat >/dev/null 58166 real 0m0.321s 58167 user 0m0.134s 58168 sys 0m0.433s 58169 58170 history 列挙自体はそんなに時間はかからない様だ。 58171 time command awk ... 2>|~/a.txt 58172 3.08user 0.02system 0:03.13elapsed 99%CPU (0avgtext+0avgdata 3096maxresident)k 58173 0inputs+0outputs (0major+281minor)pagefaults 0swaps 58174 58175 何か変な表示になったが…。 58176 何故かは分からないが /bin/time が呼び出されている様だ。 58177 どうやら hoge | time ... とすると time は /bin/time になる様だ。知らなかった…。 58178 何れにしても awk における処理自体が 3 秒かかっているという事が分かった。 58179 と、ここで使っている awk の version が古いという事に気づいた。最新版に更新する。 58180 序に CFLAGS='-O3 -march=native' でコンパイルしてみる。2.5s になった。 58181 調子に載って icc でも試してみたら 2.6s になった。 58182 オプションは -fast にしたらリンク関係で失敗したので、-O3 -march=native にした。 58183 padparadscha の動作が重いようなと思って再起動したら 0.677s にまで短くなった。 58184 Server というのは長時間起動していると遅くなるものなのか…。 58185 或いは、kernel のアップデートをする度に何らかの thunk が登録されて動作を置き換えているとかそういう事なのかもしれない。 58186 という訳でずっと起動しながらアップデートを続けていくとどんどん重くなっていくとかそういう事だったりするのだろうか。 58187 58188 a 或いは history を配列上に展開するということをしないほうが良いのだろうか。 58189 つまり ble/util/assign result history ... を用いて各行毎に値を取り出す様にする。 58190 これは ble/util/assign と配列を辿る速度の差がどれくらいあるかに依存する。 58191 と思ったが、そもそも history を探してみたが特定の番号の項目だけを抽出する方法がない。 58192 ということは sed などを起動して目的の行だけを抽出する必要があって、 58193 アクセス速度はシステムの fork の速度によって律速される。 58194 つまりとても遅いので使いものにならない。 58195 58196 b 或いは、必要になった部分だけを少しずつロードするという手もあるかもしれない。 58197 しかし、そうすると例えば検索で存在しない文字列を入力したりすると、 58198 何度もロードし直す事になり、余計に時間が掛かる様になる。 58199 実装が面倒な割に対して効果も得られなそうだ。 58200 58201 c それとも初めに history の内容を何処か別のファイルに変換してすぐ source できるようにしておいて、 58202 違いのある部分についてだけ更新を実行するという手もあるかもしれない。 58203 しかし、必ずしもファイルが後尾に追記されるだけとは限らないし、 58204 それに対処するために diff などを呼び出し始めると余計に時間が掛かる事になる。 58205 或いは、history コマンドとは完全に独立に履歴を管理して、 58206 自分の管理している履歴から bash_history を生成して、 58207 bash の開始時にはその自分の管理している history を読みこませるという手もある。 58208 58209 というかこれに関しては既に色々と議論している筈だ。 58210 → 2016-07-15 #D0346 に記録が残っている。そちらの方が詳しいはず。 58211 58212 2017-11-11 実は ~/.bash_history を直接読んでしまった方が速い可能性? 58213 具体的にどれぐらいの時間差があるのかについて調べる。 58214 58215 $ time mapfile -t array1 < ~/.bash_history 58216 58217 real 0m0.049s 58218 user 0m0.038s 58219 sys 0m0.011s 58220 $ len=${#array1[*]}; echo len=$len; rex='^eval -- \$'\''([^\'\'']|\\.)*'\''$' 58221 len=34093 58222 58223 | $ time for ((i=0;i<len;i++)); do [[ ${array1[i]} =~ $rex ]] && echo yes; done 58224 | real 0m2.205s 58225 | user 0m2.197s 58226 | sys 0m0.005s 58227 | 58228 | 高速化を試みる。 58229 | 58230 | $ time for ((i=0;i<len;i++)); do [[ ${array1[i]::4} == eval && ${array1[i]} =~ $rex ]] && echo yes; done 58231 | real 0m1.004s 58232 | user 0m1.002s 58233 | sys 0m0.001s 58234 | 58235 | $ time for ((i=0;i<len;i++)); do [[ ${array1[i]} == 'eval -- $'* && ${array1[i]} =~ $rex ]] && echo -n yes; done 58236 | real 0m0.925s 58237 | user 0m0.923s 58238 | sys 0m0.001s 58239 | 58240 | 判定を分けて見る。少し速くなる。25ms 58241 | $ function check1 { [[ ${array1[i]} =~ $rex ]] && echo -n yes; } 58242 | $ time for ((i=0;i<len;i++)); do [[ ${array1[i]} == 'eval -- $'* ]] && check1; done 58243 | real 0m0.900s 58244 | user 0m0.897s 58245 | sys 0m0.002s 58246 | 58247 | もっと判定を短くしてみる。クォートはない方が速い (11ms) 58248 | $ time for ((i=0;i<len;i++)); do [[ ${array1[i]} == 'eval'* ]] && check1; done 58249 | 58250 | 'eval'* eval* 58251 | real 0m0.877s 0m0.866s 58252 | user 0m0.876s 0m0.865s 58253 | sys 0m0.000s 0m0.001s 58254 | 58255 | ${array1[i]::4} とすると遅いようだ (114ms) 58256 | $ time for ((i=0;i<len;i++)); do [[ ${array1[i]::4} == eval ]] && check1; done 58257 | 58258 | real 0m0.980s 58259 | user 0m0.973s 58260 | sys 0m0.005s 58261 | 58262 | 判定で空白まで含めると遅くなる。逆に短くすると速くなる。 58263 | しかし短くしすぎると偽陽性が多くなるので遅くなる。まあ eval が妥当な所だろう。 58264 | $ time for ((i=0;i<len;i++)); do [[ ${array1[i]} == eval\ * ]] && check1; done 58265 | 58266 | eval\ * eva* ev* e* 58267 | real 0m0.873s 0m0.859s 0m0.856s 0m1.101s 58268 | user 0m0.872s 0m0.857s 0m0.846s 0m1.099s 58269 | sys 0m0.000s 0m0.001s 0m0.008s 0m0.001s 58270 | 58271 | for in でループを回す様にしたが寧ろ遅くなった。 58272 | $ i=0; time for data in "${array1[@]}"; do [[ $data == eva* ]] && check1; let i++; done 58273 | 58274 | let i++ ((i++)) 58275 | real 0m1.320s 0m1.161s 58276 | user 0m1.306s 0m1.154s 58277 | sys 0m0.012s 0m0.005s 58278 | 58279 | 配列の中身を修正するようにしても特に速度低下は見られない 58280 | $ function check1 { [[ ${array1[i]} =~ $rex ]] && array1[i]=${array1[i]:8}; } 58281 | $ time for ((i=0;i<len;i++)); do [[ ${array1[i]} == eval* ]] && check1; done 58282 | 58283 | real 0m0.853s 58284 | user 0m0.852s 58285 | sys 0m0.000s 58286 | 58287 | 実際に目的の補正を実施してみる。 58288 | $ time mapfile -t array1 < /tmp/hello.txt 58289 | 58290 | real 0m0.056s 58291 | user 0m0.048s 58292 | sys 0m0.008s 58293 | 58294 | $ function check1 { [[ ${array1[i]} =~ $rex ]] && eval "array1[i]=${array1[i]:8}"; } 58295 | $ time for ((i=0;i<len;i++)); do [[ ${array1[i]} == eval* ]] && check1; done 58296 | real 0m0.864s 58297 | user 0m0.863s 58298 | sys 0m0.000s 58299 58300 58301 或いは、~/.bash_history でなくて history を何処かに出力するというのでも良い。 58302 $ time history | sed 's/[[:space:]]*[0-9]\{1,\}[[:space:]]*//' > /tmp/hello.txt 58303 58304 real 0m0.146s 58305 user 0m0.167s 58306 sys 0m0.049s 58307 58308 もしこれをする位であれば、現状の方法で eval をする代わりに mapfile で読み出せる様にした方が良い? 58309 と思ったが、改行を含む場合に何ともできないのでやはり駄目だ。 58310 しかし、配列の複製よりも mapfile の方が速い様だ…。 58311 58312 $ time array2=("${array1[@]}") 58313 58314 real 0m0.590s 58315 user 0m0.577s 58316 sys 0m0.012s 58317 58318 現在の読み取りの枠組みでどれだけ時間がかかっているのかについても確認しておく。 58319 58320 $ time ble-edit/history/load 58321 58322 real 0m2.320s 58323 user 0m2.453s 58324 sys 0m0.228s 58325 58326 うーん。mapfile による実装を合計すると大体同程度なのでは。 58327 58328 history > tmp 146ms 58329 mapfile 56ms 58330 複数行補正 864ms + α 58331 配列コピー 590ms 58332 -------------------- 58333 合計 1656ms (71% of 2320) 58334 58335 計算してみると多少短くなっているが、そんなに変わらない。 58336 しかし、この新しい方法の利点は何かというと、 58337 一番処理に時間のかかる部分がループになっているので、 58338 処理を分割して少しずつ裏で更新を行うことができる点にある。 58339 58340 さて。この方法の問題点は shopt -s lithist の時に、 58341 改行を含むコマンドが分割されてしまうという事にある。 58342 改行を含む場合には eval -- の形に変換するなどの工夫が必要になる。 58343 しかし其処まで行くと、awk でできるだけ処理してからという事もできる。 58344 58345 2018-03-12 本格的にこの方針での実装について考える。 58346 先ず初めにファイルに出力する。 58347 58348 複数行に亘る history entry が登録されている場合の為に、 58349 awk または sed で処理する必要がある。 58350 実際に両方で実装してみた所、awk の方が微妙に速かった。 58351 58352 history | awk ... 0m0.574s for 37002 entries 58353 history | sed ... 0m0.634s for 37002 entries 58354 58355 | # 0m0.634s for 37002 entries 58356 | time builtin history | ble/bin/sed ' 58357 | s/^ *[0-9]\{1,\}\*\{0,1\} \{1,\}__ble_ext__)// 58358 | s/^ *[0-9]\{1,\}\*\{0,1\} \{1,\}??// 58359 | tF 58360 | ${H;s/.*//;bF;} 58361 | H;d 58362 | :F 58363 | x;s/^\n// 58364 | /\n/ { 58365 | s/['\''\\]/&/g 58366 | s/\n/\\n/g 58367 | s/.*/eval -- $'\''&'\''/ 58368 | } 58369 | p 58370 | ${s/.*//;x;/./{x;bF;};x} 58371 | d 58372 | ' > "$tmpfile" 58373 58374 awk 版を採用する事にする。 58375 さて、この操作は時間がかかるので background で実行する? 58376 sleep ring だとかを実装すると良いかもしれない。 58377 うーん。取り敢えずは sleep ring だとかは考えずに 58378 同期的に待機して処理を行うことにする。 58379 少しユーザを待たせることになるが、対策は後で行えば良い。 58380 58381 次に実行するのは mapfile である。 58382 配列を走査して複数行コマンドを修正するのも実装した。 58383 _ble_edit_history_edit については、 58384 配列の複製は時間がかかるので、これも mapfile で処理することにする。 58385 但し、配列は走査せずに _ble_edit_history で修正を行った要素の番号を記録する方法を取る事にした。 58386 そうすると 11ms で書き換えは終わった。 58387 58388 | progress の表示 58389 | 58390 | 配列を走査している間は progress を info に表示する様にした。 58391 | progress を Unicode の文字を使用して描画するとずれる。 58392 | 調べてみると blesh 及び Poderosa は幅 1 と認識しているが、 58393 | screen が幅 2 と認識している様だ。 58394 | 使っている screen は ~/local/bin/screen である。 58395 | cjkwidth emacs は .screenrc に書かれている。 58396 | もしかすると cjkwidth のコードが誤っているという可能性もある。 58397 | 58398 | ずれは \r を最後に出力すれば収まる。 58399 | 但し、これで問題が発生しないのは端末の幅が十分にある時のみである。 58400 | 58401 | todo: screen の cjkwidth emacs のコードを確認する? 58402 | todo: progress を表示するより効率的な枠組みを作成する? 58403 58404 →これに関しては新しく独立した項目を立てる事にした。 58405 58406 2018-03-13 実は awk で書き換えが必要な index を調べておけば、_ble_edit_history も 11ms で終わるのでは? 58407 58408 | これを実現する為には awk で別のファイルに書き出せる様にしなければならない。 58409 | もしくは /dev/stderr に書き出す? /dev/stderr は GNU awk では特別扱いの対象である。 58410 | POSIX awk では /dev/stderr が存在する事が保証されているだろうか。 58411 | 58412 | 調べてみると保証されていない様だ。そして実際に AIX には /dev/std??? は存在しない。 58413 | https://unix.stackexchange.com/questions/338667/unix-systems-without-dev-stdin-dev-stdout-and-dev-stderr 58414 | 58415 | POSIX awk のページを見てみると、少なくとも redirection には対応しているので、 58416 | これを使ってファイルを保存すれば良い。 58417 58418 実装した。両配列について 22ms で書き換えが完了する。 58419 58420 0m0.523s history | awk > tmpfile 58421 0m0.049s mapfile -t _ble_edit_history 58422 0m0.047s mapfile -t _ble_edit_history_edit 58423 0m0.022s 複数行コマンド履歴の補正 (107項目) 58424 58425 これで合計 641ms になった。 58426 58427 結局、走査するループがなくなったので progress は使われなくなった。 58428 以下に progress を表示するのに使っていたスクリプトの断片を残しておく。 58429 58430 local ret 58431 ble-edit/history/string#create-unicode-progress-bar "$i" "$len" 6 58432 local bar=$ret 58433 ble-edit/info/immediate-show raw $'processing multiline history [\e[38;5;63m'"$bar"$'\e[m]\r' 58434 58435 2018-03-14 次に修正するべき事は、history | awk > tmpfile の高速化である。 58436 58437 history -n に 37ms かかっている。 58438 その後の history | awk 本体が 481ms である。 58439 因みに history | awk '{print}' > tmpfile だと 188ms なので、 58440 具体的に awk で実行している処理によって 300ms 程度時間を消費している事になる。 58441 これについては短縮のしようがない様に思われるので、background process を作成する。 58442 58443 実装した。動く様になった。と思ったら、実行した background process がジョブに登録されている。うーん。 58444 % これは subshell の中で shopt -u huponexit で & echo $! を呼び出す様にして、 58445 % それを ble/util/assign から読み取る様にした。 58446 と思ったが ble/util/assign で subshell を作るぐらいなら、単に result=$(...) を使えば良い。 58447 58448 これで background で素早くロードすることが可能になった。気にならない。 58449 58450 これを以て履歴ロードの高速化は解決したものと考える事にする。 58451 以下の項目は自然解消した。 58452 58453 | 2016-07-07 58454 | 58455 | * _ble_edit_history, _ble_edit_history_edit 初期化高速化について 58456 | 58457 | これについての詳細な議論は 2016-07-15 #D0346 に残す。ここでは概要について述べる。 58458 | 58459 | 時間計測すると 40% が generate-source-to-load-history (awk) であり、 58460 | 40% が eval -- '_ble_edit_history=(...)' であり残りの 20% が 58461 | _ble_edit_history_edit=("${_ble_edit_history[@]}") である。 58462 | どのステージでも高速化の効果が同程度にあると見て良い。 58463 | 58464 | 現在現実的な手法として残っているのは以下である。 58465 | - _ble_edit_history_edit clone 遅延 58466 | - generate-source の非同期実行 58467 | 58468 | 記述の汚さの割に大幅な高速化が見込める訳ではないので現在は採用していない。 58469 | 今後高速化で問題になる様なことがあれば上記の項目・その他について考える。 58470 58471 2018-02-27 58472 58473 * 2018-02-23 idle: ble-syntax.sh の遅延読み込み [#D0680] 58474 58475 ble-syntax は比較的重いモジュールなので遅延読み込みにできるならばそうしたい。 58476 ble-syntax は外から利用している関数が少ない (疎結合) なので分離可能と判断した。 58477 58478 [API確認] 58479 58480 ble/util/idle の仕組みを整えたので改めて考え直す。 58481 先ず公開インターフェイスの小さそうな ble-syntax について考える。 58482 ble-syntax.sh で定義されている関数について調べると、以下の様な物がある。 58483 58484 - ble-syntax/* 58485 - ble-syntax:* 58486 - ble-highlight-layer:syntax/* 58487 - _ble_syntax_attr2iface.define 58488 58489 これらの内他のファイルから呼び出される関数は以下の通り: 58490 58491 - ble-syntax/completion-context 58492 - ble-syntax/parse 58493 - ble-syntax:bash/extract-command 58494 - ble-syntax:bash/simple-word/eval 58495 - ble-syntax:bash/simple-word/is-simple 58496 - ble-highlight-layer:syntax/update 58497 - ble-highlight-layer:syntax/getg 58498 58499 ble-syntax/parse, ble-syntax/completion-context 以外に関しては 58500 complete.sh もしくは command-help から呼び出される物であり、 58501 半ば ble-syntax/parse が終わっている事が前提になっている物である。 58502 従って、ble-syntax/parse 及び ble-syntax/completion-context についてだけ 58503 autoload に登録しておけば良い様な気もするが、実際に誤って使う事もあるかもしれないので、 58504 これらの関数についても ble-autoload しておいた方が無難であろう。 58505 58506 他に ble-syntax.sh で定義されている変数を参照している箇所は。 58507 58508 - _ble_syntax_VARNAMES (ble-edit.sh) 58509 - _ble_syntax_ARRNAMES (ble-edit.sh) 58510 - _ble_syntax_lang (ble-edit.sh) 58511 - _ble_syntax_bash_simple_rex_element (complete.sh) 58512 - _ble_syntax_lang (vi.sh) 58513 58514 ble-edit.sh で参照している変数は何れも単に最初に設定すれば済む話である。 58515 vi.sh で参照している変数もこれは最初に設定するので問題ない。 58516 complete.sh で参照している部分に関しては…これは ble/widget/complete 58517 の呼び出し時に ble-import syntax.sh するしかない。 58518 58519 [実装方法] 58520 58521 さて、問題は ble-syntax/parse を如何に遅延するかという事である。 58522 58523 | a 一つの案は text が空の場合には ble-syntax/parse は呼び出さないという物である。 58524 | 58525 | x しかし、それだと有限の長さの文字列から ble-syntax/parse になった時の更新が為されない。 58526 | 58527 | x ok: 更に、初回の ble-syntax/parse の呼び出しで設定されるべき初期値が変な値になるのではないか? 58528 | と思ったが、よく考えたら ble-syntax/parse では、解析開始点が文字列先頭の時には既定の設定を用いるのだった。 58529 | 従ってこれについては問題はない。 58530 | 58531 | b 或いは、syntax.sh を読み込むまではダミーの ble-syntax/parse を置いておいて、 58532 | このダミーの ble-syntax/parse では何も実行しないなど? 58533 | そういう意味で言うと ble-highlight-layer:syntax/update 及び getg についても 58534 | それに合わせた実装にしなければならない。 58535 58536 (結局最終的に b に近い実装になった) 58537 58538 ble-edit の実装を観察してみると ble-syntax/parse は _ble_edit_str.update-syntax から呼び出している。 58539 他からは呼び出していない。なので、弄るとすればここを弄れば良いだろう。 58540 扨、観察してみると実は変更範囲がない時には ble-syntax/parse は呼び出されない。 58541 つまり、ble-syntax/parse に関してはそのまま ble-autoload しても良さそうに思われる。 58542 がしかし…入力したそばから何か入力した場合には、取り敢えず無着色でも良いから呼び出すという態度も考えられる。 58543 この辺りはどちらでも良い様な気もする。 58544 58545 というか ble-syntax/parse を呼び出さないと何が起こるのだろうか…。試してみる価値はある。 58546 →試してみた所、何事もなく動いている。着色がされず補完ができないというだけである。 58547 58548 次に、ble-highlight-layer についても考えてみる。実は既定で region 等は読み込まれるので、 58549 これらについての着色はすぐに有効になるのが自然である。 58550 問題は syntax をどの段階で処理するのか…という事である。 58551 うーん。これについては適当なダミーの ble-highlight-layer を最初に定義すれば良い気がする。 58552 ダミーの ble-highlight-layer は選択範囲がない場合の region と同じように動作すれば良い。 58553 58554 [実装] 58555 58556 どうやら技術的に可能の様に思われるので ble-syntax.sh の分離を実行する事にする。 58557 58558 →実装した。動いている。ロード中に補完まで呼び出した場合でも動作する。 58559 58560 x 但し、ロード中に一頻り何か入力して、その後アイドルになって syntax がロードされたとしても、 58561 その場では着色されず、次に何らかの操作があった時に初めて着色される。 58562 idle の後には textarea#render を折角実行しているのだから、 58563 core-syntax.sh がロードされた瞬間に全体を invalidate すれば良さそう。 58564 58565 a ×: 文字列全体を reset すれば良いのではないかと思ったが、 58566 textarea#render は賢い作りになっていて、文字列の内容が同じならば反応しないようだ。 58567 58568 b 結局 ble/textarea#invalidate を呼び出すしか無さそうだ。 58569 しかしプロンプトの計算も個別にキャッシュされているのでそんなには重くはなさそうだ。 58570 単に全体を再描画するシーケンスを出力するというだけである。 58571 58572 OK ble-syntax.sh の末尾で ble/textarea#invalidate を実行するようにしたら大丈夫。 58573 58574 o bash-4.0 でも動作するか。 58575 o bash-4.1 でも動作するか。 58576 o bash-4.4 でも動作するか。 58577 o bash-3.2 でも動作するか。 58578 o bash-3.1 でも動作するか。 58579 o bash-3.0 でも動作するか。 58580 58581 何れの version でも問題なく動作している。 58582 58583 * 2017-11-25 complete: 更新する度に complete.sh の不整合が問題になっている [#D0679] 58584 58585 % やはり、遅延読み込みはやめた方が良いのでは。 58586 % 然し、それを言い出すと今後対応する予定である 58587 % cmdinfo の類についても遅延読み込みできなくなる。 58588 % もしくは、安定した API の下での実装という事になる。 58589 % 58590 % 或いは別の方法として ble.sh の細かい version 毎に 58591 % complete.sh をインストールするという手もある。 58592 % version の管理は面倒なので ble.sh の日付をそのまま使っても良い。 58593 % 或いは、起動時にファイル一式を何処かにコピーする。 58594 58595 →これは idle になった時に遅延読み込みするという方法が良い。 58596 history の load 高速化も含めてその仕組みを作りたいので、 58597 その時に実装する様にする。 58598 58599 * idle 時に何かを実行する為の枠組みを整える [#D0678] 58600 58601 以下の箇所で待ちを行う必要がある。 58602 58603 - ble-attach 58604 - eval "$_ble_decode_bind_hook" 周辺 58605 58606 read -t 0 (というか ble/util/is-stdin-ready) を実行して何も来ていなければ idle 処理を実行する。 58607 idle 処理の内部では ble/util/is-stdin-ready を定期的に実行して 58608 何か文字が来たら即時中断できる様に実装する。 58609 更に続きの処理を実行できる様に中断時に状態を記録する。 58610 58611 | - _ble_decode_bind_hook 周りに関しては多少考察が必要になる。 58612 | 現在の実装では _ble_decode_bind_hook は専ら exec:gexec で使用される。 58613 | というか、他の場所で値が設定される事はない。 58614 | 58615 | もう少し詳しく見る事にする。 58616 | 58617 | | 先ず初めに ble-edit/exec:gexec/.setup の中で設定される。 58618 | | 設定内容は以下を含む。 58619 | | - ble-edit/exec:gexec/.begin 58620 | | - コマンドの個数だけ以下を繰り返し実行: 58621 | | - ble-edit/exec:gexec/.eval-prologue ... 58622 | | - コマンド実行 58623 | | - ble-edit/exec:gexec/.save-last-arg 58624 | | - ble-edit/exec:gexec/.eval-epilogue 58625 | | - trap - INT DEBUG 58626 | | - ble-edit/exec:gexec/.end 58627 | | 58628 | | 次に $_ble_decode_bind_hook 経由で実行が実際に行われる。 58629 | | 一番最初に呼び出される ble-edit/exec:gexec/.begin の中で 58630 | | $_ble_decode_bind_hook はクリアされる。 58631 | | 58632 | | 最終的にコマンドが実行された後に、 58633 | | ble-edit/exec:gexec/.end が呼び出される。 58634 | | 内部で以下の関数が呼び出される。 58635 | | ble/term/enter 58636 | | ble-edit/bind/.tail 58637 | 58638 | この様に考えてみると、実のところ特別に新しく hook を用意するのではなくて、 58639 | 単に ble-edit/bind/.tail 辺りで idle 処理を実行すれば良い様な気もする。 58640 | 58641 | 因みに ble/term/enter は "ble/term/leave → コマンド実行 → ble/term/enter" 58642 | の流れを構成する物であって、ble.sh による処理はこの外側で実行するべきものの様に思われるので、 58643 | ble/term/enter の中で処理するなどの可能性は最初から除外して良い。 58644 | 58645 | さて。ble-edit/bind/.tail の中では info/reveal して textarea#render して stdout.off している。 58646 | アイドル時には textarea#render の後で ble/util/buffer.flush >&2 してから入れば良い。 58647 | stdout.off はそれよりも後で最後に実行すれば良い。 58648 | 58649 | - ble-edit/bind/.tail がどの状況で呼び出されるのかについて確認しておく必要がある。 58650 | →これは基本的に ble-decode/EPILOGUE で実行される。 58651 | コマンドの実行予定がある場合には ble-edit/exec:$bleopt_exec_type/process を呼び出した時に、 58652 | 内部で ble-edit/bind/.tail が予約されるので、そのまま抜ける。 58653 | コマンドの実行と共に $_ble_decode_bind_hook の内部で最終的に ble-edit/bind/.tail が呼び出される。 58654 | 58655 | ble-edit/bind/.tail-without-draw については、忙しい時に呼び出される物なので、 58656 | アイドル処理を行うかどうかについては確認しなくて良い。 58657 58658 これらの様子を総合すると、ble-edit/bind/.tail の textarea#render の直後で 58659 アイドル処理を実行する様にすれば良い。 58660 58661 ble-attach の最後の部分でも ble-edit/bind/.tail を呼び出す事にした。 58662 58663 o ok: 取り敢えず以下の様なダミーの処理が違和感なく動いている事を確認した。 58664 どうも 0.05 程度の遅延が違和感の無いぎりぎりの様に思われる。 58665 58666 | function ble-edit/test/count-up { 58667 | while ! ble/util/is-stdin-ready; do 58668 | ble-edit/info/show text $((_ble_test_count++)) 58669 | ble/textarea#focus 58670 | ble/util/buffer.flush >&2 58671 | ble/util/sleep 0.05 58672 | done 58673 | return 148 58674 | } 58675 | ble-edit/idle/push ble-edit/test/count-up 58676 58677 o ok: 試しに以下の様にして見たところ、ちゃんと ble-attach 時に既に入力がある場合には、 58678 それらの入力を処理してから履歴のロードが始まるという事を確認した。 58679 つまり ble-attach (from bashrc) でも ble/util/is-stdin-ready が正しく認識できている。 58680 58681 | ble/util/isfunction ble-edit/idle/push && 58682 | ble-edit/idle/push ble-edit/history/load 58683 58684 序で complete.sh の遅延ロードに対応した。動いている。 58685 58686 * 2017-11-03 vi-mode (extract-block): [Optimize] 現在の実装では毎回フルに矩形を計算している [#D0677] 58687 58688 しかし、一部のコマンドでは一部の情報しか必要としないものも多い。 58689 例えば xmap I, xmap A では sub_ranges[0] と sub_x1, sub_x2 しか使用しない。 58690 また xmap O では sub_ranges[0] と sub_ranges[最後] しか使わない。 58691 extract-block に途中の行について取得しないオプションがあっても良い気がする。 58692 58693 2018-02-23 58694 58695 * bash-3.0: コマンドの着色が常にエラーになっている [#D0676] 58696 これは ble-highlight-layer:syntax/word/.update-attributes/.proc の中に 58697 local var=() の形式の変数代入があったのが原因だった。直した。 58698 58699 * 起動時間: プロンプト表示までの時間の短縮 [#D0675] 58700 58701 起動時間がどんどん肥大化していく。起動時間を短縮する事はできないだろうか。 58702 58703 - 例えば、一番最初にプロンプトだけは表示してしまうなど。 58704 58705 1 プロンプトを表示する 58706 この為には ble-form.sh 及び ble-edit.sh の描画関連は読み込んでいる必要がある。 58707 更に着色関連で ble-color も読み込んでいる必要があるかもしれない。 58708 58709 2 次に ble-decode-bind の設定を行う 58710 これを実行しないとキーボード入力を受けても反応する事ができない。 58711 ただ、多少遅れて処理を行っても問題ない様な気もする。 58712 58713 現状の実装では ble-decode-bind を実行した時点で 58714 __attach__ 等の処理も実行する必要がある。 58715 58716 実は現在の実装では先に 2 を実行してから 1 を実行している。 58717 これを逆にするだけでも体感が異なるのではないかという気がする。 58718 取り敢えずそのようにした。 58719 58720 - 更に、keymap の初期化も遅らせる事ができるのではないだろうか。と思ったが難しいかもしれない。 58721 というか現状で一番時間を食っているのは vi.sh の読み込みのような気もする。 58722 vi.sh の読み込みを遅延させるとすると… 58723 vi.sh 側でキーマップ初期化時に呼び出すべき hook を提供するという手もある。 58724 しかし、そうしたとしても結局、実際にコマンドを入力できる様になるまでの時間は変わらないので、 58725 あまり意味が無いのではないかという気もする。うーん。 58726 58727 実際に実装してみた。bashrc の中で ble-bind を実行するとその場で読み込んでしまうので、 58728 それぞれの keymap に load_hook を用意してそれに登録してもらう事にした。 58729 実際にやってみると遅延してロードする様になった。 58730 やはり体感としてはできるだけ早くプロンプトを出した方が安心できる気がする。 58731 58732 2018-02-22 58733 58734 * vi-mode: BUG 行指向の貼り付けが動かなくなっている [#D0674] 58735 調べるとそもそも記録された時点で charwise になっている。何故だろうか。 58736 更に Vy としても charwise になっている。全然駄目だ。 58737 →直した。と思ったが何故これで全部直ったのかは謎である…。 58738 何らかの勘違いもあったかもしれない。現状では動いているので良しとする。 58739 58740 直前の問題の Y や yy でカーソルが動く問題も 58741 これが関係しているかと思ったが関係なかった。 58742 58743 x fixed: :reg において既定のレジスタ "" が表示されていない。直した。 58744 58745 * 2018-02-21 vi-mode: Y で行頭には動かないのが正しい動作 [#D0673] 58746 というか yy でも動かないのが正しい動作。 58747 試してみると g~~ では動く。という事は y の時だけ特別扱いという事か。 58748 もしくは、何も編集が起こらなければカーソル位置は動かさないということなのか。 58749 しかしだとすると charwise の y の時に動くという事の説明が付かない。 58750 やはり linewise y だけ特別にカーソルを移動しないという振る舞いなのだろう。 58751 58752 - done: という訳で operator:y の line の箇所を変更する。 58753 58754 - done: また、operator:d の実装を operator:y の実装に頼っているのは 58755 operator:y 独自の動作を実装するのに不都合であるから、 58756 operator:d はそれ自体で完結する様に実装し直した。 58757 58758 * vi-mode: support smap [#D0672] 58759 58760 | 2017-09-17 58761 | 58762 | * cmplstofB: ビジュアルモード・選択モード? 58763 | 58764 | * 選択モードは範囲に対する挿入モードのような気がする。 58765 | 選択モードは取り敢えず対応しないことにする。 58766 58767 * 選択モードは範囲に対する挿入モードのような気がする。 58768 選択モードは取り敢えず対応しないことにする。 58769 58770 - done: 選択モードにもビジュアルモードと同様に3種類のモードが存在する。 58771 vi_xmap と似た別の keymap (vi_smap) を作成すれば実は直ぐに対応が完了してしまうのではないか。 58772 58773 - done: 選択モードではテキストオブジェクトは呼び出されないと考えて良い。 58774 しかし、やはり後になって呼び出したくなったりすると行けないので取り敢えず xmap と同じ動作で対応する事にする。 58775 58776 - done: Select-mode: この説明によるとシフトを押さずに移動コマンドを実行すると 58777 選択モードを抜けるという事になっているが実際にやってみるとそんな事はない。 58778 と思ったが、これはどうやら keymodel 変数の値によって振る舞いが変化する様だ。 58779 58780 - done: 後は通常の文字及び C-m を入力した時に operator c に続いて何か入力したのと同じ状態にする。 58781 58782 x fixed: C-g で切り替えた時にモード表示が更新されない。修正した。 58783 58784 x fixed: 文字を入力した時に無限ループになる。そして segfault した。 58785 これは operator が vi_smap を認識していないのが原因だった。 58786 58787 - done: 何か入力した時の . で記録される内容はどうするか。 58788 普通に operator c が指定された場合にはどの様な振る舞いだったか? 58789 58790 因みに現在の実装で試しに実行してみた所 a が重複して再生されている。 58791 実は ble-decode-key で呼び出さずに直接 self-insert して良いのかもしれない。 58792 58793 - done: vi-command/operator で .save-visual-state するべきだろうか。 58794 vim で試してみると実際に記録している様だ。復元時はビジュアルモードになる。 58795 現在の ble.sh の実装でもその様に動いている。 58796 58797 x fixed: C-v で矩形ビジュアルではなくて矩形選択に移行している。直した。 58798 58799 以下の機能には対応しない 58800 58801 - gV という機能の説明が謎である。 58802 - keymodel=startsel の時に "S-移動コマンド" で選択モードに移行する機能 58803 58804 * ble-edit: ble/widget/.goto-char 廃止 [#D0671] 58805 58806 #D0407 に多少記録が残っている。 58807 現在ではこの関数は単に _ble_edit_ind を設定するだけで何もしていない。 58808 _ble_edit_mark に対する代入との非対称性が気になるので、この関数は廃止する事にする。 58809 58810 また、現時点でも幾つかの箇所で _ble_edit_ind を直接変更している物がある。 58811 もし仮に将来的に再度 _ble_edit_ind の設定を検出しなければならない状況になったとしても、 58812 改めてこれらの箇所について一つ一つ必要かどうかを判定する必要が出てくるだろうし、 58813 また同時に _ble_edit_mark の検出にも気を配らなければならない。 58814 58815 * vi-mode (xmap txtobj quote): xmap での振る舞いに対応 [#D0670] 58816 58817 振る舞いについて調べる必要がある。 58818 58819 | 先ず初めに行を跨ぐことはない。既に行を跨いでいる場合には i" も a" もベルになる。 58820 | また、行頭から数えて奇数番目の " から偶数番目の " を一つの <quote> として捉えている様だ。 58821 | 58822 | 先ず i" の前方拡張について調べる。つまりマーク < 現在位置の時の振る舞い。 58823 | 58824 | % 先ずマークと現在位置の間に <quote> 境界がない場合について。 58825 | % 現在位置が quote の外側にいる場合には次の <quote> の内部を選択する。 58826 | % 現在位置が quote の内側にいる場合には現在の <quote> の内部を選択する。 58827 | % 但し、既に内部を選択している場合には <quote> の外側を選択する様に拡張する。 58828 | % 58829 | % 端点が <quote> 境界を跨いでいる場合にはその端点は動かさない様だ。 58830 | % % - 現在位置が <quote> の外側にいる場合には次の <quote> の内部の終点に行く。 58831 | % % - 現在位置が <quote> の内側にいる場合には現在の <quote> の内部の終点に行く。 58832 | % % - 既に <quote> の内部終点にいる場合には動かない。 58833 | % % 但し引数として 2 以上を指定すると外部終点に移動する。 58834 | % % どんなに大きな引数を指定しても単に現在の <quote> の外部終点に移動するだけである。 58835 | % 58836 | % % <quote> の内部にいる場合にはその <quote> の内部終点に移動する。 58837 | % % 引数として 2 以上を指定すると外部終点に移動する。 58838 | % % 3 以上の引数を指定しても 2 を指定した時の振る舞いと変わらない。 58839 | % 58840 | % 現在位置以降にある <quote> の内部終点まで範囲を拡張する。 58841 | % もし現在位置以降に閉じた <quote> がなければ孤立 " の手前まで拡張する。 58842 | % もし孤立 " もなければベル。 58843 | % 引数が 1 以下の時、その <quote> の内部終点に移動する。 58844 | % 引数が 2 以上の時、1 文字拡張して " を範囲に含める。 58845 | % 58846 | % 丁度現在位置に " がある場合…。 58847 | % この場合は <quote> 関係なく、現在位置の次の文字から "..." ペアを見つけて 58848 | % それを <quote> と考える。後は、上と同じ振る舞いをする。 58849 | % 58850 | % 端点が " の上にある時、これは "<quote> 境界を跨いでいる時" と同じだ。 58851 | 58852 | 先ず丁度現在位置に " がある場合、 58853 | その次の位置以降から "..." ペアを見つけて終端の " の位置を A とする。 58854 | 一つしか " がない場合には、その " の位置を A とする。 58855 | それ以外の場合、 58856 | 現在位置の次の位置以降から <quote> の終端になる " を見つけて、その位置を A とする。 58857 | その様な " が見つからない場合にはベルを鳴らして中止。 58858 | 更に、マークの一つ前から現在位置の範囲に " が含まれない場合、B = 1 を設定する。 58859 | 58860 | a" の場合、 58861 | A の位置に移動する。続いて空白がある場合にはそれも取り込む。 58862 | B == 1 ならば、マークを A よりひとつ前の " の直前まで移動し、その前に空白があればそれも取り込む。 58863 | 引数が 2 以上の時、 58864 | A の位置に移動する。B == 1 ならば、マークを A より一つ前の " の直前まで移動する。 58865 | 引数が 1 以下の時、 58866 | A の手前に移動する。B == 1 ならば、マークを A より一つ前の " の直後まで移動する。 58867 | 58868 | i" で、マークと現在位置が同じ位置にある場合には明らかに振る舞いが変化する。 58869 | 58870 | % <quote> 内部にいる時にはその <quote> を A とする。 58871 | % <quote> 外部にいる時は、 58872 | % 先ず backward に " を探して見つからなければ forward に " を探す。 58873 | % もし見つかったら、次にそれより後にもう一つ " を見つける。 58874 | % このペアを A とする。もし見つからなければベルを鳴らして中止する。 58875 | 58876 | 先ず [行頭, ind+1) から最後の " を探す。見つからなければ forward に " を探す。 58877 | もし見つかったら、次にそれより後にもう一つ " を見つける。 58878 | このペアを A とする。もし見つからなければベルを鳴らして中止する。 58879 | 58880 | a" の場合、範囲A全体とその周りの空白を選択する。 58881 | 引数が 1 以下の時は範囲 A の内部を選択する。 58882 | 引数が 2 以上の時は範囲 A 全体を選択する。 58883 | 58884 | i" で、現在位置がマークより前にいる時も調べる必要がある。 58885 | 58886 | % 現在位置に " がある場合、それより前の <quote> 開始点を A とする。 58887 | % 実は現在位置に " があるかどうかは関係ない様だ。 58888 | 58889 | 現在位置より前の <quote> 開始点を A とする。 58890 | 見つからない場合にはベルを鳴らして中止する。 58891 | [現在位置, マーク + 2) の範囲に " がなければ B = 1 を設定する。 58892 | 58893 | a" の時は、A直前まで移動して更に空白を取り込む。 58894 | B == 1 ならばマークを対応する " の直後まで移動し、空白があれば取り込む。 58895 | 引数が 2 以上の時は A の位置まで移動する。 58896 | B == 1 ならばマークを対応する " の直後まで移動する。 58897 | 引数が 1 以下の時は A の直後まで移動する。 58898 | B == 1 ならばマークを対応する " の直前まで移動する。 58899 | 58900 | % a" についても同様に三通り調べる必要がある。 58901 | % どうも a" の場合は引数を指定しても効果は無いようだ。 58902 | % そして i" の時と違って <quote> の外側に隣接する空白も取り込む様だ。 58903 58904 現在の選択範囲が複数行に亘っている場合には throw (ベルを鳴らして中止) する。 58905 以降は行内での拡張を考える。 58906 行頭から偶数番目の " を 右" とし、右" の一つ前にある " を左" として区別する。 58907 行頭を beg とし、行末を end とする。現在位置を ind とし、支点を mark とする。 58908 選択範囲は [min(ind,mark), max(ind,mark)+1) になる。 58909 58910 a" の時 mode = a, i" で引数が 2 以上のとき mode = q, それ以外の時 mode = i とする。 58911 mode = i は " を含まないような範囲である。もし "" 等の様に中身がない場合は q と同じ様にする。 58912 mode = q は丁度 " を含むような範囲である。 58913 mode = a は mode = q から更に右側の空白も取り込むように拡張を行う (左側の空白は取り込まない)。 58914 58915 mark == ind の時、 58916 A1 = [beg, ind+1) にある最後の " || [ind+1, end) にある最初の " || throw 58917 A2 = [A1+1, end) にある最初の " の終端位置 || throw 58918 mode に応じて [A1, A2] を囲む。 58919 mark < ind の時、 58920 ind の位置に " がある時 58921 A = [ind+1, end) にある最初の " 58922 A = [A+1, end) にある最初の " || A 58923 それ以外の時 58924 A = [ind+1, end) にある最初の 右" || throw 58925 B = [mark-1, ind+1) に " が含まれない 58926 ind を mode に応じて終端点 A に移動する。 58927 B = true の時、mode に応じて mark を [beg, A) の最後の " (必ず存在) の位置まで移動する。 58928 ind < mark の時、 58929 A1 = [beg, ind) の最後の 左" || throw 58930 B = [ind, mark+2) に " が見つからない 58931 mode に応じて ind を開始点 A に移動する。 58932 B = true の時、mode に応じて mark を 右" に移動する。 58933 58934 [動作確認] 58935 58936 x fixed: 動作がおかしい。と思ったらどうも surround S の振る舞いが変だ。 58937 囲んでいる範囲の末端にある空白を範囲から外してしまう様になっている。 58938 調べてみると explicit にそういうコードになっている。 58939 これが適用されるか適用されないかの条件があるということだろうか。 58940 ysw の時には確かにその様な動作になっている。 58941 テキストオブジェクト ysaw の場合にもそうなっている。 58942 他は全て linewise な operator かもしくは vS, vgS である。 58943 つまり、末端の空白を範囲から除外するのは ys の時だけである。 58944 直した。 58945 58946 2018-02-21 58947 58948 * vi-mode: vi_test で qx..q マクロについてのテストを追加 [#D0669] 58949 58950 と思ったら動かない…。 58951 58952 何となくテストを追加してみた所 @x によってマクロが実行されない。 58953 手で実行すると正しく実行されるので変だ。 58954 マクロを実行する何らかの条件があっただろうか。 58955 或いは単にバグかもしれない。調べる必要がある。 58956 58957 どうやら register#play 迄は到達している様だが、 58958 再生するべき文字列を取得した時点で空文字列になっている様だ。 58959 :reg で確認してみるとやはり空文字列になっている。 58960 これは再生の問題ではなくて記録の方の問題である。 58961 58962 →どうも ble-decode/keylog/end して入力されたキーを読み取った時点で空の様だ。 58963 結局、原因は分かった。_ble_decode_keylog 配列に対する記録は ble-decode-key で行われているが、 58964 この時 _ble_decode_keylog_depth=0 かどうかを確かめている。 58965 これは実際に入力されたのではなくて二次的に呼び出された ble-decode-key を記録しない為の物である。 58966 テストを実行する為には _ble_decode_keylog_depth=0 を一時的に実行して keylog を有効化しなければならない。 58967 58968 * vi-mode: registers "0 "1 "- について。 [#D0668] 58969 58970 どうも y や d でコピーされた文字列がどのレジスタに登録されるかは複雑の様である。 58971 58972 - 先ず、何れの場合でも register として "" 以外のものが指定された時には設定されない。 58973 - y の場合には "0 に登録される 58974 - d や c の場合には改行が含まれるかまたは % ( ) ` / ? n N { } と組み合わせた時に "1 に登録される 58975 - それ以外の時には "- に登録される 58976 - "2 .. "9 に関しては "1 が設定された時のみにシフトされる。 58977 58978 % ( ) ` / ? n N { } に関しては特別扱いで WIDGET を参照する事にすれば良い。 58979 元々の vim でもこれは vi と互換性を持たせる為の振る舞いであると書かれているので、 58980 少しでも違うコマンドで実行された場合には、特別扱いしないという事で良い気がする。 58981 58982 所で… ( ) というコマンドはあっただろうか…。 58983 →調べてみた所、存在した…。カーソルを N 文先に進める or 戻すという動作の様だ。 58984 更に { と } も同様のコマンドである。 58985 これについては別の項目を立てて対応する事にする。 58986 58987 * vi-mode: マクロで記録される内容に空白が挿入されている。 [#D0667] 58988 58989 これは何処かの連結で変な事が起こっている。やはり連結だった。 58990 58991 動く例: 58992 IFS= eval 'value=${arr[*]}' 58993 IFS= eval 'value="${arr[*]}"' 58994 IFS= eval 'local value="${arr[*]}"' 58995 58996 動かない例: 58997 IFS= eval 'local value=${arr[*]}' 58998 58999 これは罠である…。Memo にも記録しておく事にする。 59000 59001 * 2018-02-18 vi-mode: register 0..9 に対応する [#D0666] 59002 59003 https://qiita.com/nakabonne/items/84d61ae5e89e20de0157 59004 59005 * 2017-10-17 vi-mode: support :reg [#D0665] 59006 59007 内容を escape したい。これは info text と同じ仕組みを使えば良いはず。 59008 →調べてみると info では ble-edit/info/.construct-text で変換している。 59009 そしてこれは座標計算もしている。其処までは必要ない。 59010 代替になるものを実装する必要がある。基本的に .construct-text を簡単化すれば良い。 59011 文字幅を計算しなくて良いので [[:print:]]+ で読み飛ばしてしまっても良い気がする。 59012 59013 取り敢えず実装した。 59014 59015 * complete: 解析再開点の記録抑制により正しく補完できないケースがある [#D0664] 59016 59017 Cygwin 上で何故か g++ の引数が補完されない。 59018 59019 gcc など他のコマンドについてはちゃんと補完される。 59020 complete には何も登録されていない。 59021 候補の表示まではちゃんと動いている。 59022 59023 [原因] 59024 59025 | - どうも he まで入力しているのに a.exe や a.txt などの 59026 | 一致しないファイル名が候補として列挙されている。 59027 | - コマンド名に + が含まれていると駄目の様だ。 59028 | 59029 | そもそも単語切り出しに失敗している。 59030 | he まで入力しているのに COMPS="" になっている。 59031 | 遡ると context の生成の時点で振る舞いがおかしい。 59032 | ble-syntax/completion-context の方を見に行く。 59033 | ble-syntax/completion-context/check-prefix が悪そうだ。 59034 | check-prefix の CTX_ARGX の部分を、echo だと通過するのに g++ だと通過しない。 59035 | 何か変だ。調べてみるとそもそも解析の時点でおかしい。 59036 | echo he だと h の位置に解析再開点が設置されているが、 59037 | g++ he だと h の位置に解析再開点が設置されていない。 59038 | Linux の方では解析再開点はちゃんと設置されれている。 59039 | bash-4.4 で試してもちゃんと設置されている。 59040 | 59041 | うーん。調べてみると parse_suppressNextStat が設定されている。 59042 | コマンド名に + が含まれている場合、後の編集によって変数代入に化ける事があるので、 59043 | その次の解析再開点の設置を抑制するというのが目的である。 59044 | そして現状では parse_suppressNextStat はこの用途のみの為に存在している。 59045 | 導入の事情は #D0318 に書かれている。 59046 | 一時期 time -p の解析 #D0320 でも用いられたが、現在は用いられていない。 59047 | #D0318 を見てわかったのは、var+ となっている時、 59048 | check-variable-assignment では var+ まで読んで parse_suppressNextStat を設置して抜ける。 59049 | 次にコマンドの読み取りで var まで読んで其処に解析再開点を設置しようとするが、 59050 | 其処で parse_suppressNextStat が効いて解析再開点が設置されいないという仕掛けになっている。 59051 | わざわざ var までしか読まないのはそれが extglob +() を構成する + かもしれないからである。 59052 | 59053 | ここで magnate (Cygwin) と padparadscha (Linux) での違いが分かった。 59054 | magnate 上では extglob が設定されていなかったので、実は次のコマンドの読み取りで var+ まで読んでしまう。 59055 | するとそのまた次の解析再開点が抑制されてしまい問題になるのである。 59056 59057 これの解決方法は簡単である。確か parse_suppressNextStat とは別の仕組みで 59058 % 解析再開点の設置を抑制する仕組みを整えた筈である。 59059 parse_suppressNextStat を廃止してそれに統合するのが良い。 59060 59061 [対処] 59062 59063 解析再開点の設置を抑制するのではなくて解析再開点に参照範囲も記録することで、 59064 再開時に dirty-range に応じて再開点を無効かどうか判定できる様にする仕組みだった。 59065 これに使うのは ble-syntax/parse/set-lookahead という関数だった。 59066 この関数は現在位置を基準に何文字先まで先読みしたかという事である。 59067 #D0601 で導入されている。 59068 59069 [実装] set-lookahead を設定する様にした。補完は動いている。 59070 59071 x fixed: しかし、今度は解析がちゃんとできなくなった。 59072 不思議な事に lookahead が設定されていない…。どういう事だろう。 59073 よく考えてみたら lookahead する文字数が足りない。 59074 variable assignment は + の次の文字が = でない時に失敗するのだから、 59075 + の次の文字まで先読みしたという事を記録しなければならない。 59076 59077 動いている。 59078 59079 2018-02-14 59080 59081 * 2017-10-05 vi-mode: 最終行付近で + _ g_ などを呼び出したときの振る舞いが異なる。 [#D0663] 59082 この辺りの振る舞いについては色々調べる価値はある。 59083 59084 - vim では最終行で 2_ を押すとベルが鳴る。移動しない。この動作は同じ。 59085 vim では最後から2行目で 3_ を押すと最終行の行頭に移動する。ベルは鳴らない。 59086 しかし同じことを今の実装で行うと何故かその行の行頭に移動する。これはバグだ。 59087 59088 - + についても調べる。vim は + も同様の振る舞いをする。 59089 そして現在の実装も何故かその行の非空白行頭に移動する。 59090 59091 - 現在の実装では g_ は最終行の行末に移動する。この動作は vim と同じだ。 59092 しかし最終行にいる時 2g_ とすると vim はベルを鳴らして動かないが、 59093 現在の実装ではそのまま現在の行の行末に移動してしまう。 59094 59095 + 及び _ に関しては明らかにバグであった。 59096 指定された量だけ履歴項目内で移動できず、履歴移動にも失敗して、 59097 それでも履歴項目内で少しは動けた時は、nolx を修正して其処に移動する実装の筈だった。 59098 しかし、コードの共通部分を利用するためにこれを first-non-space に置き換えたのが行けなかった。 59099 コードは同じであるがローカル変数 nolx は同じ値ではないのでこれだと正しく動作しないのだった。 59100 59101 g_ に関しては常に成功する実装になっていたので、失敗する条件を追加した。 59102 行移動を要求された (引数 2 以上) のに、1行も移動することができなかった場合にベル。 59103 59104 * undo: 戻った後の位置、進んだ後の位置が不自然 [#D0662] 59105 59106 現状の実装では初めてその状態になった瞬間のカーソル位置に移動している。 59107 しかし、この動作は自然だろうか。redo で進んだ時はそれで良い。 59108 しかし、undo で戻った時には、最後にその状態だった瞬間のカーソル位置に移動するべきなのではないか。 59109 59110 或いは別の実装方法として、履歴移動が起こった時には diff を取って、 59111 一番最初の変更点 (または最後の変更点) にカーソルを移動するという手が考えられる。 59112 vim の実装はこれになっている様な気がする。 59113 59114 この場合には _ble_edit_str.reset-and-check-dirty の中で計算した値を使えば良い。 59115 と思ったが _ble_edit_str/update-dirty-range で記録しているのは描画・構文解析・配置についてだけなので、 59116 現在の undo によって変更された範囲というのは求めがたい。 59117 結局、処理が二重になってしまうかもしれないが呼び出し元で common-prefix / common-suffix を求める事にする。 59118 59119 うーん。コレに関しては様々な考え方がある気がする。 59120 59121 a 初めにその状態になった瞬間のカーソル位置 59122 b 最後にその状態だったカーソル位置 59123 c 変更範囲の開始点 59124 d 変更範囲の終端点 59125 59126 設定項目 bleopt_undo_point として提供する事にした。 59127 59128 * vi-mode: xmap <C-a>, etc. の動作について [#D0661] 59129 59130 - V<C-a> の場合は各行の最初の整数について 1 ずつ増加させる。 59131 v<C-a> の場合にも同様である。<C-v><C-a> の場合も、 59132 矩形を構成する各行の一番最初の整数について増加させる。 59133 59134 - Vg<C-a> の場合は各行の最初の整数について 1, 2, 3, ... ずつ増加させる。 59135 引数を指定した場合には {N}, 2{N}, 3{N}, ... ずつ増加させる。 59136 k個目に見つかった整数は k 倍になるということである。 59137 (k行目の整数が k 倍ということではない。数字がない行についてはスキップする) 59138 59139 - v 及び <C-v> において整数の途中で領域が切れている場合、 59140 領域内に入っている部分だけで解釈される。左端も右端も。 59141 59142 - 098 を 1 増やすと 99 ではなく 099 になる。 59143 099 を 1 増やすと 100 になる。 59144 000 から 1 減らすと -001 になる。 59145 つまり動かす前の 0 padding を覚えているという事になる。 59146 59147 - 範囲内に数字が見つからなかった場合は `[`] は設定されないが . は設定される。 59148 59149 実装の方法としては vi_xmap/visual-replace-char を参考にすれば良い。 59150 また nmap <C-a>, <C-x> についても 0 padding に対応する必要がある。対応した。 59151 59152 x fixed: 一番最初の行しか変換されない。 59153 調べてみると何故か delta が 0 になっている。 59154 何と .repace-range で変数 delta が leak していた。直した。 59155 ちゃんと動くようになった。 59156 59157 o 境界を跨ぐ数字について。右境界・左境界共にOK 59158 o 行内に複数の数字がある時、一番最初の数字だけ。 59159 V, v, C-v で確認。C-v に関しては矩形内で最初の数字。 59160 o 引数がちゃんと使えるということ。 59161 o g<C-a>, 2g<C-a> で等比数列で増加するという事。 59162 o g<C-x> で数字がない行があっても、ちゃんと行番号ではなくて 59163 見つかった数字の数で倍率が決まっているという事。 59164 o 範囲内に数字がない場合 `[`] は設定されないが . は設定される。 59165 o 098 → 099, 099 → 100, 000 → 001, -001 → 000, -000 → 001 59166 o 099 → 098, 100 → 99, 002 → 001, 000 → -001 59167 59168 x ok: undo した時のカーソルの位置が変だ。 59169 59170 % これは xmap r{char} でも同様に変だ。 59171 % xmap c ... ESC で試してみると xmap を解除する瞬間のカーソル位置が変。 59172 % 59173 % 調べると undo 後の位置は記録されていた位置をそのまま再現するだけである。 59174 % 記録は undo/add した瞬間の _ble_edit_ind と _ble_edit_str を記録している。 59175 % 一緒に記録しているので異なる _ble_edit_str の時の _ble_edit_ind が再生されるなどの事は考えにくい。 59176 % 59177 % これはどうも最終的な位置に移動する前に set-previous-edit-area を実行しているのが原因の様な気がする。 59178 % 取り敢えず最終的な位置を調整してから set-previous-edit-area を実行してみる事にする。 59179 % 59180 % 直っていない…と思ったがよく考えたらこの動作で良いのである。 59181 % 何故ならば最後に編集が起こった時のカーソル位置を記録しているのであって、 59182 % その操作を実行する直前の位置を記録しているわけではないのである。 59183 % しかし、これは意図した動作であるとはいえ vim ではどの様に扱っているのか確認する必要がある。 59184 % →vim の場合にはま編集を行う直前にいた位置に戻るようである。 59185 % 一方で C-r で進む場合にはその操作を行う直前の位置に行く。 59186 % つまり、文字列の状態と位置を紐付けている訳ではない。 59187 % 59188 % どうも u で戻った時には戻した編集が起こった位置に移動し、 59189 % C-r で進んだ時には進んだ編集が開始した位置に移動する様だ。 59190 % u で戻った時は戻った後の記録の次の記録の記録点で、 59191 % C-r で進んだ時は進んだ後の記録の記録点と考えれば良いだろうか。 59192 % うーん。然し、その様にすると不整合が生じる可能性がある。 59193 % 或いは、戻った時の diff を取って編集が起こった先頭に移動すれば良いのかもしれない。 59194 % 現に、 _ble_edit_str.reset-and-check-dirty を呼び出しているのであるから、 59195 % その dirty の先頭に移動すれば良いのではないだろうか。或いは末端のほうが自然か。 59196 % vim の振る舞いを見ると変更範囲の先頭に移動している様に見える。 59197 59198 結局、これは undo の問題なので別項目で考えることにする。 59199 59200 * 2018-02-13 bug: ヒアストリングで $ret を指定すると以下のエラーメッセージ [#D0660] 59201 59202 ((: ret: 式の再帰可能レベルを越えました (エラーのあるトークンは "ret") 59203 59204 再現できた。原因は ble-syntax:bash/simple-word/eval-noglob '$ret' である。 59205 →単純なミスであった。要素数を調べるのに誤って中の文字列を展開していた。直した。 59206 59207 念のために他にも同様のミスがないが検索してみたが特にはない様だ。 59208 grc '\(\([^[:space:]]*\$\{[[:alnum:]_]+\[@\]\}' 59209 59210 * vi-mode: g?? は rot13-encode lines だが g~? は backward-search switch case である [#D0659] 59211 59212 - 現在の実装では vi_omap は "operator rot13" に紐付けているが、 59213 g~ g? の様に異なる組み合わせのオペレータを組み合わせた時は元々の motion ? の意味を取り戻す。 59214 - 因みに g~ gu gU gq に対応する omap ~, u, U, q に関しては 59215 元々 motion ではないので vi_omap で認識できる必要はない。 59216 - gw に対応する omap w は単語の意味であって gww の様な重ね方には対応していない。 59217 59218 a operator を二つ重ねた時の振る舞いについて調整が必要である。 59219 59220 b もしくは omap ? を特別な処理に差し替えるという事も考えられる。 59221 つまり opfunc を見て rot13 ならば operator rot13 を実行し、 59222 そうでなければ motion ? を実行する。 59223 59224 今回は b の方法で対処する事にした。 59225 59226 * 2017-11-03 vi-mode (map / ? n N): backward search の一致の仕方が異なる。 [#D0658] 59227 現在の実装では一致範囲が現在の位置以前にある一致の最後のものが当たる。 59228 しかし vim を観察すると、"一致範囲の開始位置" が現在の位置より前にある一致の最後のものが当たる。 59229 59230 また、vim では一致する物がそれ以上ないときに cyclic に一致するが、 59231 ble.sh ではこれについて敢えて対応していない。 59232 59233 - fixed: 2017-11-06 更に試して気付いたのだが、 59234 / や ? で新しい検索を始めるときでも、 59235 現在位置にある単語には一致しない。 59236 現在の ble.sh の実装では以前の一致の上にいる時には現在位置には一致せず、 59237 新しい一致を始めるときには現在位置に一致するようにしているが、 59238 これは全く無意味な処理である気がする…。 59239 59240 これは ble/keymap:vi/search/invoke-search で制御している振る舞いである。 59241 % 単に条件の "|| ! ble/keymap:vi/search/matched" の部分を削除すれば良いだけでは? 59242 % これについては具体的に動作を調べながら修正する。 59243 59244 と思ったら、この部分を削除すると検索開始位置が変な事になる。 59245 初回の検索位置は飽くまで初回の検索位置として処理するが、 59246 その位置を微修正するという方向で対策が必要である。 59247 59248 取り敢えず直った様な気がする。 59249 bleopt_keymap_vi_search_match_current=1 の時、以前の動作に戻る。 59250 59251 さて、然し backward search に関しては振る舞いは未だ異なる。 59252 59253 これは ble-edit/isearch/search 自体の振る舞いを弄らないと行けない。 59254 取り敢えず正規表現を使って "開始位置" が現在の位置より前にある物を探す方法を考える。 59255 これについては先頭の .{数} の部分を調整すれば良い気がする。 59256 →ble-edit/isearch/search に新しい方向 B を用意した。 59257 従来の - と違って開始点が現在位置より前ならば一致する。 59258 59259 新しい方向 B を使って実装してみたが今度は重複して一致する事が可能になってしまった。 59260 つまり、aiai[aiai] に一致している時に n を押すと [aiai]aiai になるべきだが、 59261 現在の実装では ai[aiai]ai になってしまう。 59262 これについては、再一致の時は dir を変更するという様にすれば良い。 59263 直した。動いている。 59264 59265 2018-02-13 59266 59267 * [bug] ble-bind: ble-decode-unkbd があらゆる文字について ESC を返す様になっている [#D0657] 59268 59269 連想配列の添字の $keycode を keycode に変えたのがいけなかった。 59270 というかそもそも何故連想配列になっているのだったか…。 59271 keycode は常に整数なのではないだろうか。 59272 →どうもそのようにしか見えないので _ble_decode_kbd__c2k 59273 を連想配列から通常の配列に変更した。 59274 59275 * オペレータ ! や ys において、作用対象を着色 [#D0656] 59276 59277 オペレータ ! や ys では続けてどの様な操作をするかを決定する為にユーザの入力を待つ。 59278 ユーザの入力を待っている間は、作用対象の文字列範囲を着色するのが良い。 59279 取り敢えず対応した。 59280 59281 - ok: 先ず着色する色は通常の領域選択と異なる色にしたい。 59282 これには対応した。highlight-layer:region において色 (sgr) も一緒に記録する事にした。 59283 59284 x fixed: 矩形ビジュアルモードで S を押して ysurround を呼び出した時、着色されない。 59285 59286 これは call-operator-blockwise を呼び出す時に、 59287 一時的に _ble_edit_mark_active を古い値に戻してから、 59288 呼び出した後で新しい値 (つまり vi_xmap/exit で設定された空文字列) 59289 に書き戻しているのが原因だった。 59290 59291 そもそも call-operator-blockwise の呼び出しで _ble_edit_mark_active を指定する必要があったのは、 59292 矩形領域を決定する為に、現在の選択の方法が block なのか block+ なのかを区別する為である。 59293 この目的の為に新しくローカル変数 ble_keymap_vi_mark_active を導入する事にした。 59294 このローカル変数に _ble_edit_mark_active の古い値を設定してから 59295 call-operator-blockwise を呼び出す。call-operator-blockwise は extract-block 59296 を呼び出す時だけ _ble_edit_mark_active を復元する。 59297 59298 - ok: csurround でも同様に設定したい。 59299 と思って実装を確認したら csurround の作用対象の範囲は csurround.core の中で決定していた。 59300 作用対象の決定部分と実際に挿入内容を決定した後の挿入の部分を二つの関数に分ける必要がある。 59301 59302 と思ったが、二つの関数に分けたとしても text-object を用いて範囲の決定をしている場合は困難が残る。 59303 text-object.impl を用いると演算子の呼び出しにまで到達するが…。 59304 →結局、特別なオペレータを定義して範囲を抽出することにした。 59305 59306 また、途中状態の保持方法を大幅に変更する事にした。 59307 処理を二つに分けた事によって、受け渡ししなければならない変数が増えた。 59308 これらを配列に格納することにしたが、既存の変数 type arg reg del についても同じ配列に記録する事にした。 59309 csurround の処理を (1) type arg reg の設定、(2) del の設定、(3) ins の指定で実行 の三つに分けて定義した。 59310 これらを必要に応じて呼び出す事で実際の処理 (cs や ds や . による繰り返し) を定義する。 59311 59312 2018-02-12 59313 59314 * 2017-09-12 vi-mode: operators [#D0655] 59315 59316 % ydc の他にも色々ある。 59317 % 59318 % http://vim-jp.org/vimdoc-ja/motion.html#operator 59319 % 59320 % ! = > < gq zf g@ 59321 % 59322 % この内 g~ gu gU g? g@ は y と同様に文字列の長さを変えないものである。 59323 % 59324 % また ! = > < gq zf は例え文字列単位の範囲であっても行単位の操作に変換する。 59325 % 従って、処理を行った後の beg 及び end の位置は変更を受けることになる。 59326 % これは operator:* 関数内からいじっても良いということにすれば現在の枠組みで十分対応可能である。 59327 % 何れにしてもそれぞれの機能の動作について調べてから実装する必要はある。 59328 % 59329 % →実際に < > の実装で (type == char のときに) beg を修正することにした。 59330 % ! = gq zf の実装では < > の実装を参考にすれば良い。 59331 59332 > gq, gw #D0652 59333 > ! #D0653 59334 > g@ #D0654 59335 * todo = #tmp0001 59336 59337 * zf は領域の折り畳み。対話シェルでは長いコマンドの編集は推奨されないし、これには対応しない。 59338 * gq の formatexpr, formatprg には未対応。 59339 59340 取り敢えず = 以外は実装したのでこの項目は Done に移動する事にする。 59341 残っている事柄については新しい項目 #tmp0002 を立てる。 59342 59343 * vi-mode: operator g@ の実装 [#D0654] 59344 59345 | 2017-09-12 59346 | * opfunc/g@ はどうやら Vim script のキーボードマクロで使われるようだ。 59347 59348 実際に需要があるかどうかはともかくとして対応することにした。 59349 これは bleopt 変数 keymap_vi_operatorfunc を定義することにした。 59350 この変数に operator:NAME の NAME 部分を指定する。 59351 59352 * vi-mode: operator ! の実装 [#D0653] 59353 59354 `nmap .` による繰り返しの登録については ble/lib/vim-surround.sh/ysurround.repeat/{entry,record} の使い方を参考にする。 59355 vim-surround では 繰り返し時のオペレータの名前を変更する事によって区別することにしていたが、 59356 今回の実装では $_ble_keymap_vi_repeat_invoke が設定されているかどうかで判定する事にした。 59357 59358 * vi-mode: operator gq, gw [#D0652] 59359 59360 取り敢えず、与えられた文字列を変換する関数を書く。 59361 先ずは、文字の幅を考えずに文字数だけで実装する。 59362 59363 | 2017-09-12 59364 | * gq の整形とはどういう整形だろう。調べると gw というのもある。 59365 | http://h-miyako.hatenablog.com/entry/2015/01/31/185620 によると折り返しと関係する? 59366 | 試してみた所 80 桁に収まるように単語の切れ目で折り返しをする。 59367 | 単語は空白区切りであり w による単語とは異なる。 59368 | gw と gq の違いは簡単に試した限りではない。後で help を見る。 59369 | 59370 | - 行は初めに連結される。空行(空白だけの行)は連結されない。 59371 | 59372 | というか面倒なので fold コマンドに流し込めば良いのでは? 59373 | と思ったが fold は行を連結してはくれない。 59374 | やはり自分で書いたほうが良いかもしれない。 59375 59376 動作について 59377 59378 - done: 行指向のオペレータである。 59379 - done: 元々合った空白については保持される。 59380 - done: 行末に来る空白は削除される。 59381 単語と単語の間のタブは保持される。 59382 - done: どうも 80 文字丁度ぴったり収まる場合は行に収まるとは判定されない様だ。 59383 表示文字が 79 列以下になるように整列される。 59384 59385 - done: gw の時は元々カーソルがあった文字に対応する位置に移動する。 59386 gq の時は最終行の非空白行頭に移動する。 59387 - done: 改行直後の空白類は潰れてなくなる。 59388 59389 - done: 最初の行のインデントは継承される。 59390 % 行頭は必ず非空白文字になる→これは違った。 59391 59392 具体的な折り返しの処理は ble-edit/info/.construct-text を参考にすれば良い気がする。 59393 と思ったが、結局大きく異なる実装になった。何れにしても取り敢えず実装した。 59394 動作確認を行う事にする。 59395 59396 x fixed: 段落の末端の改行が欠けてしまっている。 59397 fold の処理で最後の改行が出力されないので、末端に改行を連結するように直した。 59398 59399 x fixed: 元々合った文字列が残ってしまう? 59400 →もう変換できる段落がなくなって、 59401 最後に未変換文字列を連結するところで全体文字列を連結していた。直した。 59402 59403 x resolved: gq 後のカーソル位置がおかしい。 59404 replace-range 後の末端位置を基準に計算する様に修正した。 59405 しかし、それでもやはり駄目だ。というかもしかして find-non-space は行頭でなければならない? 59406 →これは次の項目を直したら直った。 59407 59408 x fixed: 不思議な事に前回の gq の影響が残っていて、 59409 前回の内容が付加されている様に見える。 59410 これは out なる変数がリークしていたのが原因だった。他にも変数 new が漏れていた。 59411 59412 x fixed: 幅が 80 以上になっている。 59413 59414 どうも内部の計算を見てみると空白の幅が考慮に入れられていない様だ。 59415 と思ったら .get-interval の中の iN が変な値で初期化されていた。 59416 直した。と思ったら今度は単語一個ずつ開業されるようになってしまった。 59417 インデントの幅が 210 になっている→ iN の初期化が未だ間違っていた。直した。 59418 59419 x fixed: gq 後のカーソル位置が先頭行の非空白行頭になっている。 59420 と思ったら preserve_point の判定が逆転していた。 59421 59422 x fixed: gw でカーソル位置が保たれない。どうも行頭に行ってしまう。 59423 どうやら、これはオペレータを適用した後のカーソル位置の調整による物の様だ。 59424 調べてみた所、現状ではオペレータの呼び出し元での調整を抑制する方法はない。 59425 59426 新しく _ble_keymap_vi_operator_index というローカル変数を導入する事にした。 59427 調べてみると beg を修正する事によってオペレータ作用後のカーソル位置を 59428 指定しているオペレータは他に operator:indent.impl しかなかった。 59429 影響範囲は小さいので今の内に仕様を変更する事にする。 59430 59431 % 実は beg や end と同様に単純な変数名でも良いのではないだろうか。 59432 % _ble_keymap_vi_operator_index を単に短くすると index になる。 59433 % しかし、これだと何の index か分かりにくい。 59434 % 寧ろ、ind にした方が _ble_edit_ind との対応がついて分かりやすいかもしれない。 59435 % また beg, end と同じく三文字であるという共通点もある。 59436 % 然し、ind にすると、其処に何らかの意味のある情報が格納されている様にも思われる。 59437 % 実際には既定値は空であり、専ら出力専用の変数である。 59438 % やはり混乱の元の様な気がするので取り敢えずは長い変数名という事にする。 59439 % 後で面倒になって来たら短い変数に変える事を考える。 59440 % 但し、その時でも通常の変数と違って出力専用の変数であるという事が分かる名前にする。 59441 59442 _ble_... で始まっているとグローバル変数とも勘違いしやすい。 59443 検索するとローカル変数の場合は ble_... で始めている事が多いようなので、それに倣う。 59444 59445 o 元々合った空白の保持 59446 o インデントの継承 59447 o 行末に来る空白の削除 59448 o 80 桁ではなく 79 桁に収まる様にする。 59449 o 改行直後の空白類は潰れる 59450 59451 * 2018-01-19 誤って PATH に変な値を設定してしまうと動かなくなる。 [#D0651] 59452 59453 呼び出している外部コマンドの一覧を作って、 59454 更にそれらのコマンドをフルパスで呼び出す様に修正する必要がある。 59455 その為には command -p 付きで呼び出すようにするか、 59456 或いは起動時にそれぞれのコマンドのパスを何処かに記録すれば良い。 59457 59458 (実のところ command ... となっている物について修正を行えば良いだけかもしれない) 59459 59460 2018-02-11 59461 59462 * vi-mode: nmap C-a C-x 対応 [#D0650] 59463 59464 [振る舞い] 59465 59466 先ずは振る舞いについて調べる。 59467 59468 現在行が空行の時は何もしない。 59469 現在位置から現在行末までから数字を探し、 59470 その数字から前方・後方へ拡張する。符号 - も拡張する。符号 + は無視する。 59471 引数 (既定値 1) を加算・減算した文字列で置き換える。 59472 変更後のカーソルの位置は最後の数字の一つ前。 59473 59474 `[`] は置き換えた範囲になる。. はそんなに考えなくて良い。 59475 59476 念のため help の記述についても確認しておく。 59477 59478 | CTRL-X Subtract [count] from the number or alphabetic 59479 | character at or after the cursor. {not in Vi} 59480 | CTRL-A Add [count] to the number or alphabetic character at 59481 | or after the cursor. {not in Vi} 59482 59483 特に目新しいことは書かれていない。 59484 59485 [実装] 59486 59487 さて、`[`] 及び . に関連して参照実装として何を選べば良いだろうか。 59488 例えば、ble/widget/vi_nmap/forward-char-toggle-case が replace-range を呼び出している編集関数である。 59489 実装した。動作確認をする。 59490 59491 x fixed: その行の一番最後の数字について変更が行われている。 59492 正規表現において prefix (.*) の部分に数字を許しているのがいけなかった。 59493 これは ([^0-9]*) に書き換えることにする。 59494 59495 x fixed: 負号より前にカーソルが合った時に負号が考慮に入れられていない。 59496 これも正規表現の都合である (.*) によって負号が先に読み取られてしまうので prefix と解釈されている。 59497 59498 o 空行では何も起こらない。行内で現在位置よりも後に数字がない時はベル。 59499 59500 o `[`] は設定されている。. も正しく設定されている。 59501 59502 * 2017-12-03 keymap/emacs: undo/redo に対応する。 [#D0649] 59503 59504 現在はそもそも記録を行っていない。 59505 後、各 widget について対応を行うとすると vi_imap とかち合うので注意が必要である。 59506 特に、今までの機能は全て safe キーマップの機能という事にして、 59507 新しく emacs.sh に実装を追加した方が良いのかもしれない。 59508 59509 emacs mode では何処で undo/add を呼び出すべきだろうか。 59510 変更の発生するすべてのコマンドに一つずつ undo/add を追加するべきだろうか。 59511 59512 vi では ble/keymap:vi/mark/set-previous-edit-area からしか undo/add を呼び出していない。 59513 vi_imap での変更はどの様な過程で検出されるのだろうか。 59514 どうやら _ble_keymap_vi_imap_white_list で指定されたコマンドが実行される時以外は、 59515 ble/keymap:vi/mark/end-edit-area が呼び出され、其処から undo/add が実行される様だ。 59516 59517 従って、emacs mode でも white_list を作って、 59518 其処に登録されていないコマンドが呼び出される時には必ずと undo/add を実行するという事にすれば良いだろうか。 59519 59520 Note: delete-backward-char は取り敢えず undo/add する事にした。 59521 本来の emacs では複数の連続する delete-backward-char がまとめられる。 59522 しかし面倒なので一文字ずつ記録することにしてしまう。 59523 その様に考えるとその他の delete-*-?word などについても undo/add して良い気がする。 59524 という訳で delete-*-?word も white list から除外した。 59525 59526 * 2018-12-04 keymap/vi (nmap u, U, C-r): 引き数に対応する。 [#D0648] 59527 59528 * getindex/getcount の関数名を変更 [#D0647] 59529 59530 refactor getindex, getcount → get-index, get-count 59531 59532 * 2017-12-04 keymap/emacs: 引き数 [#D0646] 59533 59534 - done: ble/widget/insert-string 59535 59536 取り敢えず clear-arg しているが、 59537 本当は繰り返し挿入にした方が良いのではないか。 59538 →繰り返し挿入にすることにした。対応した。 59539 59540 - done: ble/widget/transpose-chars 59541 59542 これはカーソルの左の文字を N 文字右に移動するという効果である。 59543 また引き数を指定しないとき、行末にいるならばその前の二文字を入れ替える。 59544 59545 - done: ble/widget/delete-forward-char 59546 59547 - done: ble/widget/delete-backward-char 59548 59549 2018-02-10 暫く置いてしまったがリリースの機会を逸したので、 59550 またこれから少しずつ編集してきりの良いところでリリースする事にする。 59551 取り敢えず emacs mode における引き数の対応の途中で止まっていた。 59552 59553 - done: kill-backward-logical-line の動作確認を行う。 59554 実際に動かしてみると動かない…と思ったら kill-backward-line なので、 59555 kill-backward-logical-line は実際には呼び出されていなかった。 59556 - ok: 引き数を指定しない場合は行頭までを消す。 59557 - ok: 正の引数 a を指定する場合は a 行前の行の行末まで消す。 59558 - ok: 引数 0 を指定した場合は現在行の行末まで消す。 59559 既に行末にいる時には何もしない (空文字列をコピーする)。 59560 - ok: 負の引数 -a を指定した場合は a 行後の行の行末まで消す。 59561 59562 - done: 次に kill-forward-logical-line の動作確認も行う。 59563 - ok: 引数を指定しない場合は行末まで。 59564 - ok: 正の引数 a を指定した場合は a 行語の行頭まで消す。 59565 - ok: 0 を指定し場合は行頭までを消す。 59566 元から行頭にいる場合には何も変更せず空文字列をコピーする。 59567 - ok: 負の引数 -a を指定した場合は a 行前の行頭まで消す。 59568 59569 - done: kill-forward-logical-line.impl が実装の途中である。 59570 先ず仕様を明確にする必要がある。 59571 現在の実装では正負・↑↓について対称である。 59572 引数として 0 を指定した場合は移動は行わない。 59573 59574 - 履歴項目の移動の実現方法に関して 59575 59576 また別の現在の問題として現在の履歴項目を越えて移動する場合の動作についてである。 59577 forward-logical-line が独立して動作する為には、 59578 一番上から更に移動しようとした時に何行移動しようとしたかを呼び出し元に伝達する必要がある。 59579 或いは、vim-mode での実装を真似して forward-logical-line の内部から履歴項目の移動を呼び出すという手もある。 59580 現在の所、履歴項目の移動についても引数に対応していないので、 59581 これを現状で実装しようと思ったら履歴項目の移動についても対応する必要がある。 59582 何れにしても二種類の実装方法が考えられる。 59583 59584 a 呼び出し元に残っている移動行数について何らかのローカル変数を介して伝達する。 59585 (現在の実装では終了ステータスを用いて移動できたかできなかったかの二値で対応する情報を伝達している。) 59586 b 或いは、別に履歴項目を移動するコマンドを用意しておいて、 59587 移動行数が満たない場合には forward-logical-line.impl の中から、 59588 その履歴項目を移動するコマンドを呼び出す様にする。 59589 実際に履歴項目を伴うか伴わないかについての制御は引数を用いて行う。 59590 59591 - 選択範囲が有効になっている場合には履歴項目の移動は行わない。 59592 59593 取り敢えずは履歴項目の移動以外については実装を行う。 59594 動作確認を行う。 59595 59596 x fixed: 引数を指定した場合は全然動かない。 59597 何故か行末に移動して bell を鳴らす。行数は問題ない。 59598 →これは実際に移動した個数 \n を数える所で、 59599 移動量が正であるかどうかの判定で不等号の向きが誤っていた。 59600 更に、_ble_edit_str ではなく _ble_edit_ind の中を数えていた。直した。 59601 59602 x resolved: 引数を指定しない場合はちゃんと動く。 59603 と思ったら勘違いだった。引数を指定した時と同様に動かなかった。 59604 これは引数を指定した時の動作と同時に修正された。 59605 59606 - ok: 引数 0 を指定した時は、期待通りに何もしない。 59607 59608 - beginning-of-line / end-of-line 59609 これらは beginning-of-graphical-line / end-of-graphical-line に分離した。 59610 動作確認。 59611 59612 - ok: 範囲内の移動であれば 引数を指定しなかった時、0 を指定した時、 59613 正の数を指定した時、負の数を指定した時、何れも動いている。 59614 59615 - ok: 範囲外への移動の場合でも、一番最初の行の行頭、または一番最後の行の行末に移動する。 59616 end であっても正しく行頭に移動するし、home であっても正しく行末に移動した。 59617 これは意識して実装した訳ではなかったが textmap による幾何的な実装で自然にそうなっていた。 59618 59619 - done: self-insert で、"M-- 1 0 a" で bell を出すようにする。 59620 59621 - kill-backward-graphical-line / kill-forward-graphical-line 59622 これも kill-backward-line / kill-forward-line から分離する。 59623 動作確認を行う。 59624 59625 - ok: forward-line に関しては、引数なし、引数 0、引数 1、引数 -1、 59626 引数 2 において正しく動作している。 59627 59628 x done: backward-line に関しては、引数の正負を逆転した方が良いのではないか。 59629 というか、コメントにはその様に書いている。 59630 59631 →コメントに書かれている動作になるように修正した。 59632 負の引数について試した。引数 0 引数 1 引数 2 について試した。 59633 59634 - done: find-graphical-eol の引数に axis を取る様にする。 59635 find-logical-bol に合わせて → 直した。 59636 59637 - forward-graphical-line / backward-graphical-line 59638 これは forward-line / backward-line から分離して統合した。 59639 59640 動作確認を行う。 59641 59642 x fixed: 移動できない。というか履歴項目の移動を行ってしまう。 59643 これは、forward-graphical-line.impl の終了ステータスの問題だろう。 59644 と思ったが、.bell は必ず 0 を返す。ということは原因は他にある? 59645 →よく見たら移動後の 位置を求める時に --prefix=a を指定するのを忘れていた。直した。 59646 59647 x fixed: 履歴項目の移動がそれ以上できなかった時に、 59648 カーソル位置が移動せずに終わってしまう。これは駄目だ。 59649 履歴項目の移動を呼び出す前に履歴項目内で移動を行うべき。 59650 これは forward-logical-line.impl でも同様に修正した。 59651 59652 - ok: forward/backward 両方について、 59653 引数なし、引数 0、引数 1、引数 2、負の引数 59654 について確認した。問題なく動いている。 59655 59656 - accept-and-next 59657 引数で指定した分だけ移動しても良いのではないかと思ったが、 59658 readline の動作を見てみると引数は効果を与えないようなので、取り敢えずそれに倣う。 59659 59660 - forward/backward-line-or-history-next 59661 これについては実装し直す必要がある。 59662 特に埋め込む形で実装する様にする。 59663 行数は logical-line で数えるという事で問題ないだろう。 59664 59665 % また、その後で廃止する事にする。 59666 % history を移動しない形での移動コマンドを提供する可能性もあるが、現在のところは対応しない。 59667 と思ったが、よく考えたらサブのプロンプトなどでは履歴移動を伴わないものが欲しくなる可能性がある。 59668 履歴移動を伴う可能性がある場合には widget の引数で opts を指定してもらうことにする。 59669 59670 →forward-history-line.impl を実装した。動いている。 59671 →forward/backward-line-or-history-next/prev は廃止し、 59672 代わりに通常の forward/backward-line に引数 "history" を指定して登録する。 59673 59674 59675 2017-12-03 59676 59677 * 絵文字の文字幅に対応する [#D0645] 59678 https://github.com/vim-jp/issues/issues/1086 の表を用いる 59679 59680 * 2017-09-17 cmplstofB: undo これは vi-mode の実装が終わってから考える [#D0644] 59681 59682 - xmap I, A で undo は 2 回に分割される。初めの入力と後のコピー。 59683 59684 vi-mode が落ち着いて来たので改めて考える事にする。 59685 これはやはり vi-mode を公開する前に簡単でも良いので対応したい。 59686 先ずは、基本の枠組みだけでも作成する。 59687 59688 先ず初めにこれまでの考察に関してまとめる事にする。 59689 59690 | 2015-03-01 59691 | 59692 | * undo の実装について 59693 | 59694 | どの様な振る舞いにするのがよいかというのが問題である。 59695 | 他の shell でどの様に実装されているかについて確認する。 59696 | 59697 | zsh における undo について 59698 | 59699 | 履歴行に関係なく "表示されている文字列" の redo undo の様に見える。 59700 | つまり、履歴で上へ行ったり下へ行ったりするとそれも含めて undo される。 59701 | これが分かり易いのかどうかは不明。というか分かりにくいと思う。 59702 | また、一旦 accept した後はそれ以前の履歴にはアクセスできない。 59703 | 59704 | bash における undo について 59705 | 59706 | bash で試してみるとコマンド履歴の行毎に編集履歴は記録されている様である。 59707 | また、accept した後でも編集が残っている。 59708 | 但し、accept した編集行については中身が編集前の状態に戻る。 59709 | (つまり、後で実際に実行されたコマンドを確認するには undo しきらなければならない) 59710 | これも分かり易いのかどうかは分からないが、少なくとも zsh よりは良い様にも思う。 59711 | 59712 | とはいいつつも accept-line した後も編集が残っているのは良いのか微妙である。 59713 59714 a 実のところ二重配列は bash にはないのでやはり一つの配列に全部入れたほうが良いかもしれない。 59715 例えば、undo の個数に制限をかけて 1000 個までとする。 59716 この時、1000 * hindex + undo_index 番目の要素に格納するなどする。 59717 59718 しかし、これだと上限に達した時の処理が面倒である。 59719 新しい編集を行う度に shift を実行しなければならない。 59720 1100 まで増やして 1100 に達したら 100 だけ shift するなど 59721 ということにすれば毎回 shift するのは避けられる。 59722 しかし、其処までしてもやはり上限が存在するという事実は変わらない。 59723 59724 b 或いは、現在の履歴項目の undo 履歴だけを配列に格納し、 59725 他の履歴項目に移る時にはシリアライズして別の配列に格納するという様にすれば良い。 59726 59727 実際 keymap/vi.sh の mark で似たような運用方法を取っている。 59728 % 同様に履歴項目を移動する時に保存・復元を行えば良い。 59729 改めて実装を見てみたら、必要になった時に hindex と記録した hindex を比較して、 59730 もし異なっていれば save/load を行うという実装になっていた。 59731 59732 コマンドを実行して erasedup などによって項目が移動する事はあるが、 59733 それに関してはコマンドを実行する度に履歴項目を全てクリアするという様にして対応する? 59734 そもそも _ble_edit_history_edit ですら shift ではなくて全クリアにしている。 59735 従って、undo についても全てクリアするという事で問題ないだろう。 59736 59737 取り敢えず実装してみた。 59738 59739 - vim の動作を調べてみると undo/redo をしても . による repeat は設定されない様だ。 59740 - また、`[`] は変更があった部分の最初の位置に設定される? 59741 59742 意外と簡単に実装できてしまった。 59743 `[`] の枠組みを整備していたお陰でそれに沿って実装できたのが大きい。 59744 59745 `U` に関しては readline "revert-line" と同じ効果になる様にした。 59746 U 自身を記録すると訳が分からなくなるので記録しない。 59747 59748 * 2017-11-29 そう言えば read -e の問題についてここに書いていない [#D0643] 59749 と思ったら上の "制限" に書いていた。少なくとも警告ぐらい出すようにするべきなのでは。 59750 59751 2017-12-02 59752 59753 * 2017-11-29 set -u にすると動かないに違いない [#D0642] 59754 やはり動かない。動かない原因を少しずつ除いていく。 59755 と思ったら、set -u だと arr1=(); arr2=("${arr1[@]}") すらできない。 59756 各配列の要素があるかないかで "${arr[@]}" を切り替えるのは困難である。 59757 仕方がないので、やはり set -u は毎回コマンド実行前に復元・保存する事にする。 59758 59759 * 2017-11-29 README.md に GitHub アカウントを持っていない時の記述方法を書くと良いのではないか [#D0641] 59760 と思ったら元々 GitHub アカウントを持っていない時の記述であった。 59761 59762 * 2017-11-29 update blerc -> bashrc [#D0640] 59763 やはり名称の変更は行わない。中身は更新した。 59764 59765 * 2015-08-14 DECSET 2004 に対応する? (ref http://srad.jp/~doda/journal/506765/) [#D0639] 59766 59767 bash-4.0 未満では read -t 0 がないので貼付などが行われた時に長く待たされる事になる。 59768 DECSET 2004 を用いて貼付を検知するなどの対策が必要。 59769 59770 2017-11-29 @cmplstofB さんからの要望 59771 59772 vi-mode における振る舞いを調べる。 59773 59774 - 置換モードで実行すると上書きされる。 59775 改行は新しい行の挿入。 59776 つまり、一文字ずつ上書きした時と同じ振る舞いである。 59777 59778 - ビジュアルモードで実行すると範囲を削除してから挿入を実行する様だ。 59779 挿入が終わった時にはノーマルモードになっている。c ... ESC だ。 59780 59781 . を実行すると先に貼り付けたのと同じ内容が繰り返される。 59782 59783 % うーん。色々考えると bracketed paste mode として特別に処理するよりは、 59784 % 今まで通りに処理する方が楽かもしれない。 59785 % ただし _ble_keymap_vi_paste 等のフラグを立てて、 59786 % コマンド実行などの操作を抑制する。 59787 % しかし貼り付け内容にキーシーケンスが含まれている場合などはどう扱うのだろう。 59788 % →試してみるとそのまま入力された。つまり、やはりキー入力をとして受け取るのではなくて、 59789 % 文字として受け取るのである。従って、今までと同様の処理では駄目だ。 59790 59791 一方で、\e[201~ はどの様に検出したら良いのだろうか。 59792 文字列として溜めておいて末端が \e[201~ になったら 59793 其処で抜けて挿入操作を開始するという方法が良いのか? 59794 59795 うーん。vi-mode で実装する前に emacs mode で実装した方が良い気がしてきた。 59796 そして、それを参考にしつつも独立に vi の各 mode での bracketed-paste を実装する。 59797 実装した。動いている。改行は CR LF も CR も LF に変換することにした。 59798 59799 次は vi-mode における実装である。 59800 59801 % 今見たら vi-mode で quoted-insert が white list に登録されていない。 59802 % と思ったが、よく見たら手動で登録していた。というより vi_imap/quoted-insert が定義されていた。 59803 59804 - vi_imap/bracketed-paste は実装した。動作を確認する。 59805 何か二回挿入される。これは実装途中だった。直した。 59806 59807 - 次に vi_nmap での実装を行う。これは思うに i ... ESC と同じと考えれば良い。 59808 調べてみると寧ろ a ... ESC の様である。 59809 更に、行頭に位置していた時には i ... ESC になるが、 59810 "." で繰り返す時には常に a ... ESC になる。 59811 ble.sh の実装では a <元々行頭なら行頭に戻る> ... ESC として、 59812 <もともと行頭なら行頭に戻る> は記録しないというようにする。 59813 動くことを確認した。 59814 59815 - vi_xmap も同様に operator c を実行する様に実装する。 59816 v に対しては期待通りに動いている。 59817 59818 しかし、C-v に対しては思ったとおりの動作をしない。v と同じ動作になっている。 59819 更に、V に対しても v と同じ動作になっている。何故だろうか。 59820 一旦、operator c の直後で中断してみることにする? と思ったが、 59821 それより後で複数行に亘って削除するようなコマンドは存在しないので、 59822 operator c を呼び出した時点で誤った結果になっているというのは明らかである。 59823 しかし普通に xmap で c を呼び出してもちゃんと linewise/blockwise になっている。 59824 念のため、bracketed-paste でも operator c の直後で中断してみると、やはりこの時点で失敗している。 59825 linewise/blockwise に切り替えるのは _ble_edit_mark_active を参照している。 59826 と思ったら、_ble_edit_mark_active が ble/widget/bracketed-paste によってクリアされているのだった。 59827 _ble_edit_mark_active を記録する様にした。ちゃんと動いている事を確かめた。 59828 59829 - vi_omap ではエラーになる。 59830 続きの貼り付けないようがコマンドに渡されるということもないので、 59831 単に paste_begin を束縛しないのではなくて、 59832 貼り付け内容を破棄する様に実装する必要がある。 59833 59834 エラーになった後の状態は何か。調べるとノーマルモードに戻っている。 59835 その様に修正した。 59836 59837 - 引数に対する応答を調べる 59838 59839 "x は無視される xmap の場合でも消えた文字列が "x に入っていく事はない。 59840 nmap の時は勿論無視される。 59841 59842 数字の引数がある時には一文字進んだ状態で nmap -> imap になる。 59843 恐らく append-mode に入ってその時点でエラーになるなどするのだろう。 59844 これはもしかすると vim のバグかもしれない。 59845 xmap で数字の引数を指定した時は、完全に無視されて分からない状態になる。 59846 59847 更に気付いたことは実は block-insert は起こらないという事。 59848 面倒なので、そのままにする。現在の実装の方が自然である。 59849 59850 2017-11-29 59851 59852 * 2017-11-27 core: 端末の状態設定・復元とカーソル形状の対応 [#D0638] 59853 59854 先ずそのタイミングについて調べる必要がある。 59855 結局 ble-stty/* と全く同じタイミングで全て調整する事にした。 59856 59857 カーソルに関しては ble/term/cursor-state/* において 59858 hidden 及び 整数値 に対応した。 59859 59860 しかし、実際に動かしてみると微妙である。 59861 overwrite mode 用の highlight-layer が、 59862 カーソルの hidden を解除するので、 59863 その時に既定のカーソルになってしまう。 59864 よく考えてみると overwrite mode であっても、 59865 文字の上にカーソルがない時には予め指定したカーソルの形状にする。 59866 59867 これに対応するためには二種類の方法がある。 59868 59869 a overwrite mode 側でカーソルを表示している時の 59870 カーソルの形状を保持する。 59871 vi.sh からは overwrite mode 時のカーソルの形状を指定する様にする。 59872 つまり、vi.sh とは独立にカーソルの形状をカーソルに紐付ける。 59873 そして表示・非表示に関しては overwrite mode が管理を行う。 59874 59875 よく考えるとこの様な方法にするのだとしたら、 59876 結局 ble-edit のレイヤーでカーソルの形状と表示・非表示を管理するのに等価である。 59877 一応、既定のカーソルの形状の設定として "非表示" というものを許し、 59878 ble-edit のレイヤーで合成した結果を ble/term のレイヤーに適用するなどの事はできるが、 59879 そのようなことをしても余り利点はないように思われる。 59880 59881 b もう一つの方法はカーソルの形状と表示・非表示は別の設定項目にする。 59882 カーソルの表示・非表示に関しては完全に overwrite mode 側に委ねる。 59883 カーソルの形状に関してだけ vi.sh から設定を変更する。 59884 59885 結局 overwrite mode のために非表示機能は予約されているのだから、 59886 カーソルの表示・非表示の設定と形状の設定を統合する意味はない。 59887 もし将来的に必要になったらその時に統合すれば良いだろう。 59888 従って、 b の方法に書き換えることにする。 59889 59890 動かしてみた。動いている。 59891 と思ったが external に移動する時に正しくカーソルが既定の状態に戻されていない気がする。 59892 実際に調べてみると external のカーソル形状に戻す部分は呼び出されている。 59893 →実は制御シーケンスが flush されていないというだけでなのでは? 59894 そうだった。flush するようにしたらちゃんと external のカーソル形状が反映される様になった。 59895 59896 2017-11-27 59897 59898 * syntax: 変数代入の各括弧式とチルダ展開 [#D0637] 59899 59900 #D0636 では角括弧式の中に : が含まれる場合には各括弧式をキャンセルするという実装にした。 59901 しかし、改めて試してみるとそうでも内容だ。 59902 59903 $ echo a=[:~:] はチルダ展開が実行され角括弧式は意味を失う。 59904 $ echo a=[:+:] はチルダ展開は起こらず、角括弧式として解釈される。 59905 $ echo a=[:~mura:] はチルダ展開に失敗し、角括弧式として解釈される。 59906 59907 つまり、実際にチルダ展開が起こったかどうかで、 59908 各括弧式が各括弧式として解釈されたかどうかが決まる。 59909 つまり、角括弧式の中でもチルダ展開は解釈することにして、 59910 チルダ展開であるということが明らかになった時に初めて 59911 角括弧式を解除することにする。 59912 59913 角括弧式の終端はチルダ展開の終端または ":" の位置に置く事にすれば良い。 59914 59915 * 2017-11-24 syntax: 変数代入に於けるチルダ展開 [#D0636] 59916 59917 [bash の振る舞い] 59918 59919 - 変数代入では値の : または = の直後でチルダ展開が始まることが許される。 59920 つまり、a=~:~ では両方のチルダについて展開が起こる。 59921 a=~=~ では後者のチルダについて展開が起こる。 59922 59923 - [追加] 因みに a=(~:~) に関しては最初の ~ しかチルダ展開の対象にはならない。 59924 つまり、:= による区切りが有効になるのは本当に CTX_VRHS の文脈のみの様だ。 59925 59926 - [追加] 気付いてしまったのだが、通常の単語でも = の直後でチルダ展開は有効のようだ。 59927 echo var=~ は展開される。一方で echo var:~ は展開されない。 59928 これについて man bash に何か記述はあったろうか。やはり探してみたが見つからない。 59929 更に、LANG=C man bash で見てみても見つからない。 59930 59931 - [追加] 更にまた振る舞いの違いを見つけてしまった。 59932 : はチルダプレフィックスの終端になるが = はチルダプレフィックスの終端にはならない。 59933 これについては現在の実装で正しく実装することができている。 59934 59935 [どのように実装するべきか] 59936 59937 現在の実装ではチルダ展開が有効かどうかを一つ前の文字を見て決めている。 59938 しかし、やはりひとつ前の文字を読むのは解析再開用ルールの違反である。不整合になる。 59939 例えば a=~:~ にしておいて : を消すと2つ目の ~ がチルダ展開のままになる。 59940 59941 a 例えば変数代入の時には : 区切りで単語を設置する様にする。 59942 そうすれば着色の際にも値についてファイル名の存在確認が取れる。 59943 59944 b 或いは : と = の前後で文脈値を切り替えるなどして、 59945 次の文字に移った時に前が := の何れかであるかどうかの状態を保持する様にしても良いが、 59946 文脈値が無駄に増えるということと、結局補完の際にはまた特別な処置が必要になる。 59947 59948 % ここは迷わず a の方針で考えることにする。 59949 % 但し、注意しなければならないことは、 59950 % この変更により単語が設置されるが、 59951 % これにより既存の補完などの枠組みに問題が生じないかということ。 59952 % 59953 % - extract-command に与える影響はどうだろう 59954 % 59955 % | 先ず、単語はどの様に設置するべきだろうか。 59956 % | 例えば変数代入自体を一つの大きな単語として、 59957 % | その中に入れ子で単語の集合を設置するのか、 59958 % | 或いは、親の文脈で一つの変数代入に対して複数の単語を設置するのか。 59959 % | 59960 % | 文法構造という観点からいうと入れ子にして設置したほうが良い気がする。 59961 % | しかし、補完などの観点からいうと extract-command した時に変な切り出し方をされると嫌だ。 59962 % | と思ったが、既にリダイレクト (ctx-redirect) や配列 (ctx-values) などの場合には内部に入れ子構造を作っているのだから、 59963 % | extract-command で問題になったりしそうなものである。これについては現在の振る舞いを確認する。 59964 % | →どうも調べてみると現状の extract-command だと、 59965 % | リダイレクトや配列の代入の中では親のコマンドを正しく抽出できていないという事が分かった。 59966 % | 従って、extract-command を改修して入れ子になっていても大丈夫な様にする必要がある。 59967 % | そしてその様に改修した暁には変数代入に関しても入れ子にして問題ないだろう。 59968 % 59969 % 従って extract-command 関係については以下の様に対応すれば良い。 59970 % 59971 % 1 extract-command を改修して一番最初にコマンド単語 (CTX_ARGI) のあった階層で抽出する様にする。 59972 % これにより echo hello; arr=(hello @world) など (@ はカーソル位置を表す) に対して 59973 % echo hello が抽出される様にする。同様に echo world > te@st に対して echo world が抽出される様にする。 59974 % 59975 % 2 extract-command のコマンド単語抽出の方法について再確認を行う。 59976 % コマンドの引数単語は常に CTX_ARGVI または CTX_ARGI と決まっていただろうか? 59977 % またコマンド単語は常に CTX_CMDI と決まっていただろうか? 59978 % 59979 % 3 その上で変数代入に関しては、それ自体を一つの単語とすると同時に、 59980 % 内部に入れ子で単語を導入する様にする。 59981 % 59982 % 4 実は declare var=hello の右辺でも同様にチルダ展開が有効になるはずである。 59983 % これについても同様に内部に入れ子で単語の構造を導入する事にする。 59984 % 59985 % 1, 2 に関しては #D0635 で取り扱う事にした。 59986 % 59987 % - もう一つの懸念事項は既存の補完で変数代入の右辺について何かあっただろうか。 59988 % 59989 % % これに関してはまた確認する必要がある。実の所、現状では何も補完できていないので、 59990 % % 何か実装しようとしていたとしても表面上は破壊する事にはならないだろうが。 59991 % % 念のために確認しておく事にする。 59992 % % →調べてみると ctx==CTX_VRHS で file を設置している。 59993 % 59994 % 実際に補完してみたら補完された。動いている。 59995 % completion-context で ctx が CTX_VRHS の時に file を設置している。 59996 % 59997 % 補完開始点はその CTX_VRHS の先頭になっている。 59998 % つまり、CTX_VRHS で複数回数で解析を行っている場合補完が働かなくなる。 59999 % 実際に var='w'or@ において補完を実行しようとしても補完できなかった。 60000 % これは独立した項目で処理する事にする。#D0627 60001 % 60002 % 何れにしてもこの補完が動く様にする為には文字列を開始する必要がある。 60003 % 60004 % うーん。ここで通常コマンドの引数でも = の直後でチルダ展開が有効になるという事を発見した。 60005 % という事は、上記の方法を取っている限りは全ての単語について入れ子構造を導入しなければならない。 60006 % その様に実装すると余計に複雑になる。この方法はやはり駄目である。 60007 60008 c =~ や :~ の連なりを見てチルダ展開を実行する様にすれば良い。 60009 これならば問題は起こらないはず。 60010 60011 どうもまた色々試すと思っていたよりも複雑の様だ。 60012 先ず、echo a=~:~ とすると両方共展開される。 60013 また echo ~:~ だと前者しか展開されない。 60014 echo a+b=~:~ だと展開されない。 60015 echo a=~:b=~ だと前者しか展開されない。 60016 echo a=b:~ だと展開される。 60017 echo a+=~ だと展開され、echo a-=~ だと展開されない。 60018 a=b=~ は展開されない。 60019 echo a[$((1+2*3))$(echo 1)]=~:~ などでも有効になる。 60020 60021 以下の様な規則になっていると思われる。 60022 先ず初めに通常の単語であっても変数代入と同様に解釈される。 60023 変数代入の右辺の初め、または、途中の : の直後ではチルダ展開が有効になる。 60024 60025 これに対応するためには通常の単語であっても変数代入と同様の解析を行う必要がある。 60026 60027 - どうも対応が微妙になってきた。そもそも配列代入の解析は正しく出来ていたのだったか? 60028 怪しい振る舞いをしていたので調べてみたが、それは解析の問題ではなかった #tmp0003 60029 60030 [実装1] 60031 60032 改めて考え直す必要がある。 60033 取り敢えず変数代入に関しては正しく動く様に実装できたと思う。 60034 通常の単語については以下の対策が必要である。 60035 結局通常の単語に関しても変数代入の形式の読み取りを実施しなければならない。 60036 60037 - v= の形式の時 CTX_VRHS 的な別の文脈に移動する。 60038 これは取り敢えず CTX_ARGI のクローンとして実装すれば良い。 60039 例えば CTX_ARGIR という名前にする。 60040 60041 - a[...]= の形式の時、通常の単語の場合には [] の中身は CTX_BRAX で読み取る。 60042 CTX_BRAX を抜ける時に ntype を見て 'a[' ならば、 60043 続きが ]= であることを確かめて CTX_ARGIR に移行する様にしかける。 60044 移行した時には変数代入の時と同様に tilde-expansion のチェックをその場で行う。 60045 60046 取り敢えず、ARGVI, ARGI, FARGI3, CARGI1 それぞれについて 60047 変数代入の右辺になった時の文脈値を定義した。実装した。 60048 通常の引数について動作のテストを行う。 60049 60050 x fixed: stackdump が出る。これは _ble_syntax_bash_command_isARGI が整数値のはずなのに、 60051 文字列として扱おうと考えて "a" などの値を入れたのが悪かった。 60052 結局文字列の値は使わないことになったので "a" から "1" に戻した。 60053 60054 x fixed: echo a[i]=1 において CTX_BRAX から抜けた時の着色が変だ。 60055 等号は ATTR_GLOB で塗らない。直した。 60056 60057 x fixed: 変数代入の後に ctx=CTX_UNSPECIFIED になっている。 60058 単語の形成にも失敗している。直した。 60059 60060 x fixed: declare var=value の value の着色が変だ。 60061 これは上の項目と同じ原因だった。直った。 60062 60063 x fixed: declare var=value の後の文脈がコマンドを受ける文脈になっている。 60064 CTX_ARGVX に戻るべき。これは _ble_syntax_bash_command_EndCtx[CTX_ARGVIR] の値を誤っていただけだった。 60065 CTX_VRHS の設定をコピーしただけになっていた。直した。 60066 60067 o ok: チルダ展開が有効でないはずのものはちゃんとチルダ展開以外になっている。 60068 o ok: declare arr[123]=~:~ なども期待通りに動いている。 60069 60070 x wontfix: 実は echo a[]=~ もチルダ展開として有効である。 60071 しかし、現在の実装では [ の直後の ] は "]" を閉じる力がない。 60072 60073 改めて試すと echo a[]b]=~ はチルダ展開が有効にならない。 60074 つまり、チルダ展開としては "a[]"b]=~ の形式であると見做し、チルダ展開は起こらない。 60075 一方で 'ab=~' という名前のファイルに一致するのでパス名展開としては echo a["]b"]=~ と解釈している。 60076 これについては blesh は パス名展開の方が正しく着色されるようにする。 60077 60078 o ok: for var in args... や case arg in の arg の部分でもちゃんと動いている。 60079 60080 [実装2] 60081 60082 未だ残っている。ctx-values や ctx-conditions でもチルダ展開は有効である。 60083 ctx-values については対応した。ctx-conditions にも対応した。 60084 60085 * 変数代入形式の単語の右辺でブレース展開を使うと、チルダ展開は無効になる。 60086 % echo a=~:{a,b}:~ とするとチルダ展開は有効にならない。 60087 % ブレース展開があると駄目なのだろうか。 60088 % 規則がよく分からないのでこれは保留にする。 60089 と思ったが後で対応するのも面倒なので分かる範囲で対応することにした。 60090 60091 2017-11-26 60092 60093 * 2017-11-24 syntax: extract-command の実装を再確認する [#D0635] 60094 60095 これは元々 #D0636 の方法 b を整備する時に 60096 extract-command の実装を確認した時に気がついた extract-command 自体の問題。 60097 結局方法 b は棄却されたので、独立させてここで実装する事にする。 60098 60099 | 1 extract-command を改修して一番最初にコマンド単語 (CTX_CMDI) のあった階層で抽出する様にする。 60100 | これにより echo hello; arr=(hello @world) など (@ はカーソル位置を表す) に対して 60101 | echo hello が抽出される様にする。同様に echo world > te@st に対して echo world が抽出される様にする。 60102 | 60103 | 2 extract-command のコマンド単語抽出の方法について再確認を行う。 60104 | コマンドの引数単語は常に CTX_ARGVI または CTX_ARGI と決まっていただろうか? 60105 | またコマンド単語は常に CTX_CMDI と決まっていただろうか? 60106 60107 2 に関しては ble_debug を見て試した限りでは問題ない様に見える。 60108 1 に関しては現在の実装を改めて見ないと分からない。 60109 実装を改めて読む。そもそも tree-enumerate は一体どのような実装になっていたのだったか。 60110 60111 | 先ず初めに tree-enumerate/.initialize を見る。 60112 | 出力する変数は tree と i と nofs である。 60113 | 恐らく .initialize では未だ閉じていない入れ子を末端位置で仮に閉じた時に、 60114 | _ble_syntax_tree[iN-1] がどの様な値になるかを計算している。 60115 | - _ble_syntax_tree[i-1] は境界 #i で終わる範囲の情報を格納することに注意する。 60116 | - 範囲は二種類ある。word と nest である。 60117 | - word は word を直接子に持つことはない。 60118 | - inest は範囲の開始点であり、_ble_syntax_nest[inest] に範囲の開始情報が格納されている。 60119 | 60120 | 次に tree-enumerate/.impl を見る。 60121 | - 同じ位置で複数の階層の範囲が終端するとき、 60122 | それらの情報は連結されて _ble_syntax_tree[i-1] に格納される。 60123 | 外側の範囲の情報の方が左側に格納される。 60124 | - tclen tplen を用いてこれらの範囲情報は互いに参照する。 60125 | - 他の位置から参照されるときは必ず一番外側の情報を参照する。 60126 | 同じ位置から参照されるときに限り一つ右の情報を参照する。 60127 | この関数は同じ階層に位置する兄弟を末尾から列挙して指定した関数を呼び出す。 60128 | 範囲の情報は wtype wbegin tprev tchild nofs を用いて渡される。 60129 60130 結局 tree-enumerate は一番外側の階層の範囲を列挙し、 60131 tree-enumerate-children は現在の範囲の中に下の階層があれば、 60132 その階層について範囲を列挙するということをする理解は正しい。 60133 使える変数は wtype wbegin tprev tchild nofs であり、 60134 通常用途であれば直接ユーザが使用するのは wtype wbegin である。 60135 tree-enumerate-break は強制的に tprev=-1 にする事で 60136 兄要素がないことにし、そこで兄弟の列挙を停止させる。 60137 60138 ble-syntax:bash/extract-command/.scan では、 60139 現在位置が含まれる一番下の階層の単語を探している。 60140 先ず初めに現在以前で始まる範囲まで見送る。 60141 範囲が現在位置よりも左まで行ったら中断する。 60142 現在位置を含む範囲を見つけたらその中に潜るというのを繰り返す。 60143 60144 その階層に単語 (wtype/ntype が整数値の範囲) が含まれる場合には isword を設定する。 60145 isword は、一つ上の階層で construct を呼び出して貰うためのマーカである。 60146 この isword は一番最初に見つかった単語である。 60147 つまり、現在位置以前に始まる一番最後の単語の wtype になる。 60148 そうは言っても誰も使っていない様である。 60149 isword は分かりにくいので extract_has_word に変数名を変更した。 60150 60151 うーん。結局 iscommand=1 (改め extract_command_found=1) の位置を変更するだけで良い気がする。 60152 試してみる。動いている。OK 60153 60154 ? fixed: _ble_syntax_tree の構造を見ていて気付いたが、 60155 よく考えると _ble_syntax_tree であっても、wtype に任意の文字列が入りうるから、 60156 node=(${_ble_syntax_tree[i]}) とすると failglob で不味いのでは? 60157 60158 と思ったが、ntype としてグロブパターンになる物がなければ大丈夫のはず。 60159 これは nest-push を全て確認すれば分かる。a[ や v[ など怪しい物もあるが、 60160 現状ではグロブパターンになる様なものは含まれていない。 60161 将来的なことを考えると本当はグロブパターンが含まれることも 60162 想定して修正した方が良いのかもしれないが。 60163 60164 現状では問題ないが、やはり後々のためにちゃんと安全な方法で split する事にする。直した。 60165 60166 * edit: history 初期化で先頭行に行く (reported by cmplstofB) [#D0634] 60167 60168 > 起動直後に履歴を遡る (というより ^P を押下する) と一番始めの履歴にまで戻ってしまいます。 60169 60170 送ってもらったログを見て分かった。 60171 failglob の為に history_line=($history_line) を 60172 ${history_line%%[$IFS]*} に変更したのが原因だった。 60173 どうやら history で出力される履歴番号は printf %5d で出力されている為に、 60174 履歴項目の数が 5 桁より小さい時には先頭にスペースが入るのだ。 60175 60176 * complete: failglob 時の問題 (3) (reported by cmplstofB) [#D0633] 60177 60178 > コマンドに glob が含まれている場合などはいいのですが, 60179 > 存在しないパスを補完しようとすると不具合が発生します。 60180 60181 うわ。未だ残っている…。うーん。 60182 候補生成にパス名展開を使っているのが悪い。 60183 試しにエラーメッセージを殺す方向で試してみたが、 60184 すると今度は ble.sh の処理自体が其処で死ぬ。 60185 60186 % 先に対応したパス名展開では死んでいなかったが何故だろう。 60187 % 見てみると eval している。試してみると eval だと大丈夫のようだ。 60188 % 関数を作る。ble/util/eval-pathname-expansion 60189 % 一応パス名展開をしているところはこれに置き換えた。 60190 % エラーメッセージは出ていない。 60191 結局この実装は以降の修正により使わない事になった。 60192 60193 x fixed: 後、shopt -s nocaseglob も現在の実装だと不味い。 60194 パス名展開で候補を生成しているので、 60195 a.txt に対して A@ で補完を実行すると A.txt になってしまう。 60196 60197 そもそも何故 compgen -A file -- ... を使わずに、 60198 "$COMPV"* を使っていたのだったか。 60199 先ず初めに compgen は fork またはファイルへの読み書きをしないと結果を取得できないので遅い。 60200 次に、何故か prefix を認識してくれないことが過去にあったから。 60201 今試してみるとちゃんと動いている様に見えるが、実のところ良くわからない。 60202 更にディレクトリ名を / を付きで生成するのも楽である。 60203 60204 今 nocaseglob に合わせて、既に存在している文字列を 60205 書き換えてしまうという手も考えられるが、quote がある場合など諸々を考えると面倒だ。 60206 後でまとめて対応する様にした方が良い気がする。 60207 この大文字小文字の違う候補でも補完できるようにするのは独立した項目にする。 60208 60209 今は compgen で候補を生成する事にする。 60210 60211 x fixed: 起動時に一時ファイルを消すところでもパス名展開を使っている。 60212 これも対処しないとそもそも ble.sh のロードに失敗する筈。 60213 60214 これは起動時の処理なので ble/util/* などの高等な機能は使えない。 60215 従って、shopt -u failglob して処理する事にする。 60216 60217 * 変数が漏れている。ret が定義されている [#D0632] 60218 60219 1 先ず emacs mode でも定義される。 60220 2 ble-syntax/parse で local ret としてみても変わらない。 60221 3 ble/textarea#render で local ret としてみても変わらない。 60222 60223 逆に外側から絞っていく事にする。 60224 4 ble-decode/.hook で local ret としたらさすがに大丈夫だ。 60225 5 ble-decode/PROLOGUE, EPILOGUE は関係ないようだ。 60226 6 ble-decode-key で local ret としたら大丈夫だ。 60227 7 eval -- "$WIDGET" の前後で ret が設定される様だ。 60228 ret の値が破壊される時の WIDGET を出力させると以下の様になった。 60229 ret=0:WIDGET=ble/widget/vi_imap/accept-single-line-or vi_imap/newline 60230 60231 どうも複数存在する様である。一つは _ble_edit_str/update-dirty-range から。 60232 見つけた。以下で漏れている。 60233 60234 ble/keymap:vi/mark/set-global-mark 60235 ble/keymap:vi/mark/set-local-mark 60236 60237 直したら取り敢えず ret の値は保持される様になった。 60238 実は他の箇所でも漏れがあったような気がしたが、今の所は再現していない。 60239 60240 x 更に、一回 normal-mode に入ってそれから insert-mode に入ると ret が消える。 60241 これも ret が漏れている証拠である。どうも normal-mode に入る瞬間に駄目の様だ。 60242 と思ったが当たらない。どうも実行直前に insert-mode に入っていて、 60243 insert-mode の実装で ret を宣言するのを忘れていたということのようだ。 60244 60245 さて、これは直したと思ったが、未だ直っていない。 60246 insert-mode で local ret したが反応しない。と思ったら xmap/insert-mode を見ていた。 60247 そう思って nmap/insert-mode で local ret をして見たがそれでも直らない。 60248 vi_imap/normal-mode-without-insert-leave の方でも修正したがそれでも駄目。 60249 もう一度外側から絞っていくしかないのだろうか。もう一度 ble-decode にしかける。 60250 60251 | local ret=trap1 60252 | builtin eval -- "$WIDGET"; local exit=$? 60253 | [[ $ret == trap1 ]] || echo "ret=$ret:WIDGET=$WIDGET" >> a.txt 60254 | 60255 | 結果 60256 | ret=<U+009C>:WIDGET=ble/widget/vi_imap/normal-mode-without-insert-leave 60257 | ret=<U+009C>:WIDGET=ble/widget/vi_nmap/insert-mode 60258 60259 うーん。何と両方で ret が書き換わっている。道理で片方だけ書き換えても反応しない訳だ。 60260 というかよく考えたら local -r ret すれば犯人が分かるのでは? 60261 と一瞬思ったが駄目だ。local -r ret すると新しいローカル変数の定義も禁止されてしまう。 60262 60263 normal-mode-without-insert-leave に潜る。ble/keymap:vi/update-mode-name が駄目だ。 60264 中を覗いてみると呼び出している関数は ble-edit/info/default しかない。やはりそうだ。 60265 辿っていくと ble-edit/draw/trace.impl にまですぐに行く。見つけた。 60266 60267 改めて ble-edit.sh についても ret のリークがないか調べる必要がある気がしてきた。 60268 他に 2 箇所同様の ret のリークを見つけた。直した。 60269 心配になったので ble-syntax.sh と ble-decode.sh も確認する。問題は見つからなかった。 60270 ble-color.sh も確かめた。一つ上の階層で local ret している例を見つけたが、 60271 実際の処理内容を見ると不自然なので local ret は中に移動した。 60272 (ble-highlight-layer:plain/update / ble-highlight-layer:plain/update/.getch) 60273 60274 x done: keymap/vi.sh の実装について一通り ret の使用を見てみたら、 60275 かなり local ret を忘れている箇所が見つかった。見つかった物は直した。 60276 60277 * また最初の調査で "emacs mode でも定義される" と書いたが、 60278 これは _ble_edit_dirty_observer に登録した 60279 ble/keymap:vi/mark/shift-by-dirty-range がそのまま動いていて、 60280 更にこれの中で ret が上書きされていたのが行けなかったようである。 60281 これについては emacs mode に入る時には _ble_edit_dirty_observer 60282 から消去する等の対策が必要な気がする。 60283 60284 2017-11-25 60285 60286 * 2017-11-23 complete: bug 補完で謎の現象が起こっている。空白が補完される [#D0631] 60287 というか echo [a でも同様に空白が補完される。 60288 echo $(echo > ) の > の後で実行しても同様である。 60289 更に echo $(echo) の後でも空白が補完される。 60290 どうやら同じ点で nest-pop が 2 回起こっているとなっている気がする。 60291 60292 % どうもこれは昔からあった振る舞いの気がする。後で対応する事にする。 60293 60294 というか "echo @" でも空白が挿入される。 60295 この振る舞いは今までなかったはずだ。 60296 今までは、候補一覧が表示されたはず。 60297 つまり、これは最近埋め込んだバグである。 60298 60299 調べてみると空文字列の候補が生成されている。 60300 どうも compgen で一つも候補が生成されなかった時に、 60301 ヒアストリングで <<< "$compgen" とした時に空候補が作られる様だ。 60302 60303 - そもそも compgen が空の時には候補生成の処理はしなくても良いのだから先に抜ける様に変更した。 60304 - 更に、compgen に内容が含まれていたとしても空行がある場合には、それを除く様に変更した。 60305 - ble/util/assign-array も調整した。 60306 60307 * highlight: failglob でエラーメッセージが出る (reported by cmplstofB) [#D0630] 60308 60309 > コマンドラインで $ l* と入力すると bash: 一致しません: l* という 60310 > エラーメッセージらしい表示が入力位置の右隣に発生し,続く入力が妨げられます。 60311 60312 直した。パス名展開を試みている箇所では同様のことが起こりうる。 60313 60314 x fixed: あと、ble/string#split も火を吹いていた。諦めて set -f する事にした。 60315 60316 x fixed: また、失敗するコマンドを一度実行するとそれ以降どのキーを入力してもエラーメッセージが出る様になる。 60317 しかも、C-c などの操作が効かなくなる? DEL も効かない。何故? decode の問題だろうか。 60318 先ず初めにどのタイミングでエラーが発生しているのかを確認しなければならない。 60319 これは getcount を実行する時に count=($(history 1)) に相当することを実行していたのが悪かった。 60320 60321 調べてみると類似の物は広範囲に亘って存在する。全て修正しなければならない。 60322 grc '=\(\$' で検索して当たるものを全般に調べる必要がある。 60323 特に ble-syntax.sh における _ble_syntax_stat の類を ble/string#split で分割する必要がある。 60324 というのも、nparam にはヒアドキュメントの終端が入り * が含まれうるから。 60325 _ble_syntax_nest も同様である。 60326 60327 大変なので ble/string#split-words 関数を追加した。 60328 60329 - done: あと、パス名展開に失敗したらその単語をエラー着色するようにする。 60330 60331 * keymap/vi (cmap): C-d で終了してしまうバグ (reported by cmplstofB) [#D0629] 60332 60333 > たとえコマンドラインに文字があっても終了してしまいます。 60334 60335 直した。 60336 60337 2017-11-24 60338 60339 * complete: 更に key=key とした後に echo $key""@ も補完できない [#D0628] 60340 60341 そのまま echo key@ だと勿論補完できる。 60342 調べてみると is-simple は true を返し、更に eval も期待した値 key になっている。 60343 一体何が問題で補完に失敗しているのだろうか。 60344 60345 うーん。何と別のファイル名だと再現しない。 60346 しかも更に変数名を変えたら動く。 60347 $ var=key 60348 $ echo $var""@ 60349 60350 途中の様子を調べてみたら…何と $key"" が 67108969 という値に展開されていた。 60351 成る程、ローカル変数の変数名と被っているために変数の中身がすり変わっている。 60352 60353 [cf memo/D0628.extract-global-values.sh] 60354 60355 | x [困難] これに対処するのは困難である。外部文脈で評価するしかないが、 60356 | 評価の度に外部文脈にまで移動するのは難しい。 60357 | 処理を完全にファイバーにして処理しなければならないが、それは滅茶苦茶である。 60358 | 60359 | a [不可能] 或いは declare -g key などとすれば外部変数にアクセスする事ができるか? 60360 | これは具体的に試してみないと分からない。試してみた所、 60361 | declare -g key を用いるとグローバルでの変数の値を変更できるだけであって、 60362 | グローバルでの変数の値を読み出すことができる訳ではないようだ。 60363 | 60364 | さて、グローバルでの変数の値を設定することができるのだから、 60365 | 何処かにその値を読み出す方法があるかもしれないと思って検索してみる。 60366 | しかし、サブシェルの概念を知らずに変数の値が設定できないと相談している人や、 60367 | 関数内で変数宣言のコマンド (local declare readonly typeset) を用いた時に、 60368 | 自動的に関数内の局所変数になるということを知らないで記事を書いている人が当たったりで、 60369 | "ローカル変数を定義している時にグローバルの値を読み出す方法" についての記事は簡単には見つけられそうにない。 60370 | 60371 | b [不可能] よく考えてみたら declare -p -g var とすれば見る事ができる筈だ。 60372 | しかし $var でアクセスできる様になる訳ではないという事に注意する。 60373 | declare -p -g var 等して得られた結果から、 60374 | 先頭の declare 云々の部分を消して local を付加し、 60375 | それから eval すればローカルに値を丸っと持って来ることができる。 60376 | 60377 | - 所で declare -p にはバグがあって改行について再現できない、 60378 | と思ったがよく考えたらバグは bash-3.0 の話であり、 60379 | 一方で declare の -g オプションは bash-4.2 以降なので、 60380 | これについては気にしなくても良い。 60381 | 60382 | - この時にその文脈での変数名を上書きしない様に注意する必要がある。 60383 | 変数名は全て _ble_* という名前にすれば良い。 60384 | 60385 | 何と実際に試してみた所できないという事が判明した。 60386 | declare -g に -p オプションを指定すると -g は無効になる。 60387 | "declare -g" で現在定義されているグローバル変数を全て出力できるのではないかとも思ったが、 60388 | 実際に試してみるとローカル変数も含めて全変数について、現在での文脈の値が出力されるだけだった。 60389 | 結局グローバルでの値は分からない。 60390 | 60391 | c [不可能] 既に設定されているローカル変数を全て unset すれば 60392 | グローバル変数に到達することができるはずだが、 60393 | 先ず、何回 unset したら良いかわからない。一番最後に定義されていた変数は分かるが、 60394 | それが果たしてグローバル変数なのか、それともローカル変数なのか判別できない。 60395 | declare -g var としても変数が "定義" される訳ではないので多分駄目だ。 60396 | 更に、unset した後でまた元の状態に復元する方法が存在しない。 60397 | 60398 | d [不可能] 或いはシグナルを用いてシグナルハンドラから出力させるという手もある。 60399 | これは遅そうだが仕方がない。実際に試してみた所駄目だった。 60400 | 先ず呼び出しの順序はちゃんと保たれている。 60401 | しかしながら、ローカル変数はそのままにして呼び出される様で、 60402 | シグナルハンドラの中からでもローカル変数の値しか見えない。 60403 | 60404 | e 或いは bind の一番外側で毎回全てのグローバル変数を何処かに記録するという手もある。 60405 | しかし、これは明らかに滅茶苦茶遅い。特に _ble_* の類を除外する方法がない。 60406 | 60407 | f もしくは、全てのローカル変数の名前を _ble_* に変えるという手もある。 60408 | その様にすれば _ble_* という変数名を参照しない限りは 60409 | グローバル変数の値を (何もせずに) 参照できるということが保証できる。 60410 | 更に、この方法は declare -g などと違ってどの bash の version でも使える。 60411 | 60412 | 然し、これはこれで変更コストが大きいし、またコードも読みにくく・書きにくくなる。 60413 | 60414 | g c の方法に於いてサブシェルに潜れば unset でグローバル変数を掘り出しても、 60415 | 外側では影響が出ない様にする事ができるのではないか。 60416 | unset を繰り返し実施して一番最後に定義されていた変数の値を取れば良い。 60417 | この方法でグローバル変数が定義されていればそれを取得できるという事が分かった。 60418 | 60419 | v 実際に複数階層の場合でも各階層での値を逐次的に取得できることが分かった。 60420 | 60421 | x ok: 途中にローカル変数があった場合は? 60422 | 60423 | | 思ったのだが途中で -r のローカル変数があった時に unset できるのだろうか。 60424 | | →試してみたところ駄目だった。できない。 60425 | | これに関しては -r なローカル変数を設置しないという今までの方針を用いている限りは問題ない。 60426 | | complete の処理の途中でユーザ関数を通過することはないので問題にはならない。 60427 | | ただ、中で補完などを呼び出すような widget を書くときには readonly にしない様に注意するしかない。 60428 | 60429 | グローバル変数にアクセスするには途中のローカル変数に readonly を指定してはならない。 60430 | 60431 | というか試していて分かったことだが local -r 宣言してしまうと、 60432 | 更に呼び出した先の関数でその変数を local 宣言することができなくなってしまう。 60433 | 実際に検索してみるとそれをやっている箇所が ble-syntax.sh に二箇所見つかった。これは消す。 60434 | 60435 | x solved: 問題点はグローバル変数が定義されていなかった時に、 60436 | 一番最初に定義されたローカル変数の値を拾ってきてしまうという事である。 60437 | 60438 | a その変数がグローバル変数かどうかを判定するには、 60439 | declare -g var=xxx を実行して値が変化するかどうかを見れば良いが、 60440 | もしそれがグローバル変数ではなかった場合にグローバル変数の値を破壊してしまう。 60441 | 破壊が起こらない様にする為にはサブシェルの中で値が変化するかどうか見れば良いが fork が増える。 60442 | 60443 | 一応、以下の方法を用いれば余分な fork は一回に抑えることができる。 60444 | 先ず初めに unset を繰り返す事で何階層の変数が定義されているかを調べ、 60445 | その後で改めて初めから unset を実行して一番最後の階層に移動し、 60446 | そこで declare -g var=xxx に応答するかどうかでそれがグローバル変数かどうか判定する。 60447 | 60448 | b 或いは declare -g var だけ実行すればそこに変数が存在することが保証されたりしないだろうか。 60449 | 或いは declare -g -r var などとすれば readonly な物をグローバル変数と解釈できる。 60450 | 60451 | ここは b で実装してみた。動いている。 60452 | 60453 | c 但し、declare -g は bash-4.2 以降でないと使えないので、 60454 | bash-4.2 未満では [[ ${var+set} ]] による実装に切り替える。 60455 | しかし、これだとやはりグローバル変数に到達できない場合があり問題だ。 60456 | 60457 | 或いは、__ble_MaxLoop=20 迄回してしまうというのも手である。 60458 | fork に比べれば大した処理量ではない。また、別目的にこの関数を使うとしても、 60459 | bash-4.2 未満の話なのでパフォーマンスは余り気にしない事にする。 60460 | その様に修正した。動いている。 60461 | 60462 | 唯、bash-4.0 未満 ${!varname+set} が期待通りの動作をしていない気がする? 60463 | しかし普通に bash-3.2 -c 'var=hello; [[ ${!var+set} ]]' とすると動いて見える。 60464 | まあ、調べるのも面倒なので、少なくともグローバル変数がある場合には 60465 | 正しい値を取得できているので良しとする。 60466 | 60467 | x ok: 途中に宣言だけの変数があった場合 (local var) は? 60468 | 60469 | [[ ${var+set} ]] とすると変数が存在することになっている? 60470 | と思ったが、それも2回だけで 2 回 unset すると変数は存在しないことになる。 60471 | ところが、無視して unset を続けて行くと最終的にグローバル変数に到達することはできる。 60472 | 60473 | まあ、取り敢えず動いているので気にしない事にする。 60474 | 60475 | x ok: もう一つの面倒なことは、サブシェルで実行するので、 60476 | 実行結果を返すために標準入出力を用いなければならないという事である。 60477 | といってもこれは面倒なだけで fork をするよりはコストも小さいし問題にはならない。 60478 60479 結局 g の方法でテスト実装して動くようなものができたのでそれを使う事にする。 60480 ble/util/print-global-definitions という関数を定義した。 60481 60482 次に simple-word から変数名を抽出する。テストした。 60483 それから変数名が一つ以上ある時に print-global-definitions を呼んで eval する。 60484 幾らか修正したら、問題なく動いている。 60485 60486 些細な事のために大分実装が複雑になったが仕方がない。 60487 60488 * complete: ファイル world があるとき var='w'o@ (@ はカーソル位置) で補完できない [#D0627] 60489 60490 これは completion-context の CTX_VRHS において、 60491 CTX_VRHS が最後に設置された位置を補完開始点としているからである。 60492 上記の例で言えば o を起点に補完を実行しようとしてしまう。 60493 ここでは wbeg から変数名をスキップして補完を実行するべきである。 60494 60495 この修正により以下の項目も解決した。 60496 60497 | 2017-11-06 60498 | 60499 | * complete: リダイレクトのファイル名に @ が含まれているとき @ 以降で補完できない。 60500 60501 * syntax: チルダ展開 [#D0626] 60502 60503 チルダ展開が起こる文脈は? 60504 ctx-command ctx-values では起こる。 60505 ctx-conditions では %%起こらない%% と思ったら起こっている様だ。 60506 ctx-redirect CTX_RDRF/CTX_RDRS/CTX_RDRD では起こる。 60507 60508 extglob や [...] の中では起こらない。 60509 最初のブレース展開の中では起こる。が、これは面倒なので認識しない。 60510 60511 * highlight: リダイレクト先ファイル名が複数語に展開されたらエラー着色 [#D0625] 60512 60513 * highlight: echo <<< {a,b} や echo <<< * ではグロブ展開が起きないのに、 [#D0624] 60514 着色はグロブ展開も含めてファイル名に一致するかどうかが確かめられている。 60515 60516 * 2015-08-15 syntax: CTX_CMDXC, CTX_CMDXF 等に於いて redirect は許可するべきでないのでは? [#D0623] 60517 更に、CTX_CMDXC においては var=... も許可するべきではない。 60518 60519 また CTX_CMDX1 についても直前のコマンドによっては redirect は許可するべきでない? 60520 (while, if, do, then, else, '(', time の直後では redirect も可能な様だ。) 60521 60522 2017-11-24 改めて一通り動作を確認する事にする。 60523 60524 | CTX_CMDX1 について調べた所、他に && などの直後が CTX_CMDX1 のようだが、これについても redirect は可能である。 60525 | 結局、現状のコードでは CTX_CMDX1 の場合はいつでも redirect は可能に思われる。 60526 | 60527 | CTX_CMDXF は CTX_FARGX1 に改名した。CTX_FARGX1 では redirect はできない。 60528 | CTX_FARGX2 でも redirect はできない。これらは大丈夫。 60529 | しかし、CTX_FARGX2 から CTX_ARGI に変換しているが、 60530 | bash は for a in aaa bbb > redirect; の形式を許していない。★これは修正が必要 60531 | 60532 | CTX_CMDXE は fi fi などの文脈であるが、 60533 | この直後に > redirect がある事はいつでも許される。 60534 | また redirect の後は CTX_ARGX0 になるという振る舞いも正しい。 60535 | 60536 | CTX_CMDXC は関数定義の始まる前の文脈であるが、ここでは redirect は使えない。 60537 | この振る舞いについても ble.sh で試したところ正しい。 60538 | 60539 | CTX_CMDXD は for ((;;)) 直後の文脈である。 60540 | これも現状の ble.sh の振る舞い通り redirect は使えない。 60541 60542 結局 for a in の後の引数の列でリダイレクトを使えないという事に対応すれば良い。 60543 対応した。新しい文脈値 CTX_FARGX3, CTX_FARGI3 を追加した。 60544 60545 2017-11-23 60546 60547 * 2017-11-21 syntax: ブレース展開? [#D0622] 60548 60549 | 少し試してみたが、ブレース展開が起こる条件が謎。 60550 | echo ${aaaa:-{a,b}{c,d}} # 起こらない 60551 | echo ${aaaa:-{a,b}{c,d} # 起こらない 60552 | echo ${aaaa:-a,b}{c,d} # 起こる a,bc a,bd 60553 | echo ${aaaa:-{a,b}}{c,d} # 起こる {a,b}c {a,b}d 60554 | echo ${aaaa:-a,b}}{c,d} # 起こる a,b}c a,b}d 60555 | 60556 | bbbb=1234; echo ${bbbb:-{a,b}{c,d}} → 1234{c,d}} となるので、 60557 | ${} は特に {} の入れ子の回数を数えるという事はしていない。 60558 60559 うーん。仮説は以下の通り。 60560 1 先ず初めにブレース展開を試行する為に {,} を抽出する。 60561 ${} が現れたら {} の入れ子を数えつつスキップする。 60562 ブレース展開が見つかったら展開する。 60563 2 展開後の単語について ${} 等の展開を行う。 60564 この時は ${} の中の {} の入れ子は数えず、 60565 "}" が現れた時点で即座にパラメータ展開が閉じるとする。 60566 60567 この 1 と 2 の間の ${} の終端点の抽出の違いに依って 60568 変な振る舞いが生まれていると思われる。 60569 これは bash がおかしいので多少の着色の違いは無視する。 60570 基本的に ${} の抽出に従い (つまり {} の入れ子は考えない)、 60571 仮にブレース展開が {} の入れ子で無効化されていたとしても、 60572 気にせずに着色を実施する。 60573 60574 ブレース展開の着色に対応するのであれば、 60575 {aa..bb} や {aa..bb..cc} や {aa,bb} 等の途中の区切りについても着色したい。 60576 CTX_BRAX と同様に delimiters が来たら抜ける。 60577 60578 | a 初めは .. が来るか , が来るか分からない状態として解析し、 60579 | 何か複雑な構成が来たら , だけを受け付ける状態に移る? 60580 | 60581 | b と思ったが .. が許されるのは内部に構造がない時のみなので、 60582 | "{" を nest-push する時点で .. の形式かどうかを判定する事ができる気がする。 60583 | 正規表現 (([0-9]+)\.\.([0-9]+)|[a-zA-Z]\.\.[a-zA-Z])(\.\.[0-9]+)?\} で読み取れる所まで読み取り、 60584 | 一番最後まで読み切れたら {aa..bb} の着色を行う。 60585 | もし途中で一致しないと分かったら、その時点で , を受け付けるブレース展開の文脈に push する。 60586 | 60587 | c b の方法だと先読みのために何処まで読んだかを調べなければならないので、もっと単純化する。 60588 | "{" が来たらそこから前方に [0-9a-zA-Z.]*\}? を読み取る。 60589 | もし \} まで読み切ったら、中身が b の形式になっていれば {a..b} として着色し、 60590 | そうでなければブレース展開ではなく通常の文字列として読み取る。 60591 | 途中までしか読み取れなかった場合には "{" で nest-push して 60592 | {,} 形式のブレース展開の文脈に入る事にする。 60593 60594 ここでは c の方法を用いることにする。 60595 60596 ブレース展開の文脈でも角括弧式やグロブパターンは有効である。 60597 ブレース展開から角括弧式を呼び出した時には 60598 角括弧式は通常のコマンドの終端に加えて ,} でも終端する様に注意する。 60599 60600 取り敢えずブレース展開に対応する事にする。 60601 60602 [実装] 60603 60604 1 done: 先ず初めに _ble_syntax_bashc[CTX_ARGI] を修正する。 60605 "{" を追加した。 60606 60607 2 done: 影響範囲を確かめる。 60608 ${_ble_syntax_bashc[CTX_ARGI]} を参照しているのは、 60609 ctx-command, ctx-values, ctx-conditions, ctx-redirect である。 60610 更に ctx-bracket-expression でも使用している。 60611 60612 - ctx-values ではブレース展開は有効である。 60613 - ctx-conditions ではブレース展開は無効である。 60614 - ctx-redirect ではどうだろうか。試してみると文脈によって振る舞いが異なる。 60615 - CTX_RDRF で使うと曖昧だと言われてエラーになる。 60616 - %%CTX_RDRH で使うとブレース展開は完全に不活性の様だ。%% 60617 →そもそも CTX_RDRH は ctx-redirect の対象ではなかった。 60618 - CTX_RDRS で使った場合も不活性の様だ。 60619 - CTX_RDRD これは fd を受け取る形式のリダイレクトである。 60620 曖昧なリダイレクトだと言われてエラーになる。 60621 60622 つまり、少なくとも CTX_RDRF, CTX_RDRD ではブレースを認識し、 60623 そして、エラー着色を設置する必要がある。と思ったが、 60624 不完全なブレース展開の場合には入る時に確実なエラー着色を実行できない気がする。 60625 と思ったが、これは "}" が現れてブレース展開が閉じる時にエラー着色すれば良い。 60626 そして途中の "{" や "," は不活性という事にする。 60627 60628 3 done: 取り敢えず ctx-command で使う為に check-brace-expansion を実装する 60629 実装した。動いている。 60630 60631 4 done: 次に文脈毎に対応していく事にする。 60632 60633 - ctx-values ではそのまま対応すれば良い。 60634 60635 - ctx-conditions では着色しないし nest-push もしないという様にすれば良い。 60636 (或いは、そもそも ctx-conditions の通常文字集合から "{" を除けば良いのだが、 60637 新しい文字集合を定義するのも面倒なのでそのままにしておく。) 60638 60639 - これは CTX_RDRS %%及び CTX_RDRH%% でも同様に取り扱えば良い。 60640 また CTX_RDRD 及び CTX_RDRF では一応読み取るがエラーにする。 60641 と思ったが > {1..1} 等の様に 1 個しか値が生成されない時はエラーにはならない様だ。 60642 うーん。これは展開の結果としてのエラーであって構文エラーではないので、 60643 余り気にせずそのまま解析してしまえば良い? 60644 唯、> {1..3} の様な場合はやはり明らかにエラーになることが分かっているので、 60645 この解析の時点でエラーにしてしまって良い気がする。エラーにする事にした。 60646 60647 特に nest-push した時には最終的に , なしで終わってブレース展開として有効にならない事もある。 60648 その様なことを考えると nest-pop した場合にはわざわざエラーの着色はしなくても良い? 60649 →これは次の項目で対処する様に "," の前後で文脈値を変えることにしたので、 60650 実は "," なしで終わったかどうかは判定可能である。 60651 というか、"," より後でしか "}" で終わる事ができない。 60652 取り敢えず現状では "}" で抜ける時にエラーを設定する事にする。 60653 60654 5 done: 実は echo {aaa},bbb} は {"aaa}","bbb"} と解釈される様だ。 60655 初めの "," が現れるまでは "}" は有効でない。対応した。 60656 60657 6 done: ctx-brace-expansion の入れ子について。対応した。 60658 60659 7 done: CTX_PATN や CTX_BRAX との入れ子の関係について考える必要がある。 60660 60661 | CTX_PATN 及び CTX_BRAX の失効の関係についてまとめる。 60662 | 60663 | CTX_VRHS -> CTX_BRAX 不活性, CTX_PATN 不活性, CTX_BRACE? 失効 60664 | CTX_RDRS -> CTX_BRAX 不活性, CTX_PATN 不活性, CTX_BRACE? 失効 60665 | CTX_BRAX -> CTX_BRAX 不活性, CTX_PATN 不活性, CTX_BRACE? 有効 60666 | CTX_CONDI -> CTX_BRAX 有効, CTX_PATN 有効, CTX_BRACE? 失効 60667 | CTX_RDRF -> CTX_BRAX 有効, CTX_PATN 有効, CTX_BRACE? 不活性 60668 | CTX_RDRD -> 同上 60669 | 60670 | 伝播は CTX_BRAX, CTX_PATN, CTX_BRACE の間で行えば良い。 60671 | と思ったが、そもそも CTX_BRAX 及び CTX_PATN の内部での 60672 | ブレース展開を許可するのかは謎である。 60673 | 60674 | | うーん。取り敢えず CTX_PATN の下からは好きに CTX_BRACE に入れる様にする? 60675 | | と思ったが、CTX_PATN の呼び出し元として何が考えられるか。。 60676 | | うーん。現状では glob pattern が有効な ctx-command 系統の文脈に限っている。 60677 | | 従って、CTX_PATN の呼び出し元が何であれ CTX_BRACE に入って問題はない。 60678 | | 60679 | | 一方で、今後 ${var#pattern} に対応したことを考えると事情は複雑になる。 60680 | | この場合はブレース展開は無効にしなければならない。 60681 | | 一つの方法は、${var#pattern} における extglob 及び 角括弧式 60682 | | は別の文脈値を使って解析するという物である。 60683 | | ${var#pattern} の場合には CTX_VRHS CTX_RDRS 等の不活性処理が不要である。 60684 | | 一方で CTX_BRAX による不活性処理は必要である。うーん。然し…。 60685 | | 60686 | | そもそも CTX_PATN を抜ける条件である "}" をどの様に伝播するつもりだったか。 60687 | | もし CTX_PATN を抜ける条件として "}" が有効かどうかを確かめる手段を与えるのだとしたら、 60688 | | この 「"}" で終わるかどうか」を以てブレース展開が有効かどうかを判定できるはず。 60689 | | その様に考えれば、将来的に ${var#pattern} に CTX_PATN が対応するかどうかに依らず、 60690 | | 現状として CTX_PATN から CTX_BRACE に入るのを有効にして良い気がする。 60691 | 60692 | 現状では CTX_PATN からブレース展開はいつでも呼び出せることにする。 60693 | 60694 | 1 先ずブレース展開に入るときを考える。 60695 | 60696 | CTX_PATN/CTX_BRAX が不活性の時、その原因は CTX_VRHS/CTX_RDRS/CTX_BRAX のどれかである。 60697 | 原因が CTX_VRHS/CTX_RDRS のときブレース展開は不活性にする。 60698 | 原因が CTX_BRAX のときブレース展開は通常通りに処理する。 60699 | CTX_PATN/CTX_BRAX が有効のときは、何も考えずにブレース展開を有効にすれば良い? 60700 | 60701 | 但し、CTX_BRAX の親 nctx が CTX_CONDI の時にはブレース展開はやはり無効にする。 60702 | CTX_PATN の親 nctx についてもチェックできるが、CTX_PATN は幾らでも入れ子にできるので、 60703 | 入れ子の階層によってブレース展開が有効になったり無効になったりするのは分かりにくい。 60704 | 仕方がないので、[[ @() ]] の中ではブレース展開は有効になるように解析する。 60705 | 60706 | 2 次に CTX_PATN に入る時を考える。CTX_BRAX も同様にできそう。 60707 | 60708 | 特に CTX_BRACE(不活性) から CTX_PATN に入る時はどうするべきか。 60709 | 不活性要因は CTX_RDRF, CTX_RDRD だが、両者とも基本的には CTX_PATN, CTX_BRAX は有効である。 60710 | 従って、CTX_BRACE(不活性) から CTX_PATN に入る時はそのまま CTX_PATN に入れば良い。 60711 | CTX_BRAX に入る時も同様である。一方で、CTX_VRHS, CTX_RDRS によって CTX_BRACE が無効化されている時は、 60712 | そもそも CTX_BRACE? の文脈に突入しないので考慮しなくて良い。 60713 | 60714 | 問題は CTX_BRAX -> CTX_BRACE(有効) -> CTX_PATN/CTX_BRAX となる時だが… 60715 | CTX_BRACE になっている時点で外側の CTX_BRAX は分断されるので、 60716 | bracket expression として有効なのかも分からない。 60717 | 従って、内部で CTX_PATN や CTX_BRAX が有効でも良いのではないかという気がする。 60718 | 60719 | つまり、これに関しては何も考慮しなくて良い。という事にする。 60720 | 60721 | 表にする。 60722 | 60723 | CTX_VRHS -> ... -> CTX_PATN(不活性) -> ブレース展開 x 60724 | CTX_VRHS -> ... -> CTX_BRAX(不活性) -> ブレース展開 x 60725 | CTX_RDRS -> ... -> CTX_PATN(不活性) -> ブレース展開 x 60726 | CTX_RDRS -> ... -> CTX_BRAX(不活性) -> ブレース展開 x 60727 | CTX_CONDI -> CTX_BRAX(有効) -> ブレース展開 x 60728 | CTX_BRAX -> ... -> CTX_PATN(不活性) -> ブレース展開 o 60729 | CTX_BRAX(有効) -> ブレース展開 o 60730 | CTX_PATN(有効) -> ブレース展開 o 60731 60732 60733 CTX_PATN/CTX_BRAX の入れ子に関して表にしてみたが分かりにくい。 60734 やはり日本語でまとめる事にする。 60735 60736 以下のとき、ブレース展開は無効となり通常文字列として読み取られる。 60737 - CTX_CONDI/CTX_VRHS/CTX_RDRS からブレース展開を試みるとき 60738 - CTX_VRHS/CTX_RDRS によって不活性化した CTX_PATN/CTX_BRAX からブレース展開を試みるとき 60739 - CTX_CONDI の直下にある CTX_BRAX(有効) からブレース展開を試みるとき 60740 以下のとき、ブレース展開は不活性となりブレース展開として有効になったときエラーを設置する。 60741 - CTX_RDRF/CTX_RDRD からブレース展開を試みるとき 60742 - 不活性の CTX_BRACE1/CTX_BRACE2 から入れ子のブレース展開を試みるとき 60743 その他のとき、ブレース展開は有効になる。但し、bash と違い以下の場合を含む 60744 - CTX_BRAX によって不活性化した CTX_PATN からブレース展開を試みるとき 60745 CTX_BRACE1/CTX_BRACE2 から CTX_PATN/CTX_BRAX に入る時は特別な処理は何も必要ない。 60746 60747 * syntax: "{fd}>" 形式のリダイレクトで先読みに問題が生じる可能性? [無問題] [#D0621] 60748 60749 echo {f,d}> a.txt を echo {fd}> a.txt に書き換えるとどうなるのか。 60750 うーん。実はこれは問題にならない。何故なら、 60751 {f,d} の場合には {f,d} まで一気に読み取るので、 60752 "," が消えると必ず解析再開点は "{" になる。 60753 60754 問題はリダイレクトとして有効な形になった瞬間に、 60755 解析再開点が "{" 以前になることが保証されるかである。 60756 もう少し落ち着いて考える。リダイレクトとして有効な形でないとき、 60757 ある点でそれがリダイレクトとして有効でないという事が判明する点がある。 60758 上記の例で言えば "," の位置である。これより前の位置ではリダイレクトとして有効である。 60759 この時、 "{" から "," の直前の位置までの解析が 1 回で済んでいれば問題ない。 60760 そして実際にその様になっているかどうかについては…。 60761 現状では /\{[0-9a-zA-Z]+|[0-9]+/ の連なりは一気に読み取るので途中に解析再開点が設置されることはない。 60762 60763 ブレース展開に新しく対応する際にも \{[0-9a-zA-Z]+ については 60764 一気に読み取るという事を変更しない様にすれば大丈夫のはず。 60765 例えば、その文脈でブレース展開が有効でなかったとしても、 60766 "{" 単体で読み取るということはせずに後ろに続く alnum も一緒に読み取るようにする注意が必要である。 60767 60768 * syntax: for ((i=0;i<10;i++)) { echo; } が構文エラーになってしまっている。 [#D0620] 60769 ble_debug=1 で見ると (()) の直後は ARGX0 になっている。 60770 うーん。is_command_form_for=1 の設定がうまく伝播していないのが原因だろうか。 60771 調べてみると is_command_form_for=1 は設定されているが、 60772 実際に ble-syntax:bash/ctx-command/.check-delimiter-or-redirect に到達する事には消えている。 60773 関数の呼び出しのされかたについて勘違いをしているだろうか。 60774 60775 と思ったら ble-syntax:bash/ctx-command の先頭で 60776 local is_command_form_for= が実行されている。これが原因だ。これを削除する。 60777 しかし、そうすると野に is_command_form_for という変数があった時に誤動作する。 60778 変数名は _ble_syntax_bash_is_command_form_for 等に変えるのが良いだろう。 60779 60780 * syntax: [[ ]] の中で <>();|& の文字を使った場合は構文エラーにするべき [棄却] [#D0619] 60781 60782 但し、 "<" ">" "(" ")" "||" "&&" 等の特別な単語の時にだけエラーでなくなる。 60783 と思ったが、改めて調べてみると "<" ">" "(" ")" "&&" は何れも単語を構成していない。 60784 Bash でエラーが出ている様に見えたのは、 60785 各演算子の使い方が誤っていたからである。 60786 60787 だとするとそもそもこの項目を立てた時に実装していた 60788 CTX_BRAX の方で不整合が生じているかもしれないので確認する必要がある。 60789 特に [aa&& でちゃんと && 演算子の手前で CTX_BRAX から抜けるだろうか。 60790 →これは特に対策もしていないので抜けるはずである。実際に確かめてもそうなっている。 60791 特に問題にはならなそうである。 60792 60793 * 条件コマンドの比較の右辺で怪しいところが幾つかある [#D0618] 60794 60795 $ grc '== \$[^'\'']' 60796 修正した。色々バグっていた気がする。 60797 60798 * 2017-11-14 syntax: 後 !; は履歴展開ではないはずなのに履歴展開と解釈されている[保留] [#D0617] 60799 と思ったが、文脈によって履歴展開だったりそうでなかったりしている気がする。 60800 どうも履歴展開と解釈されてはいるが、必ず展開に失敗する? 60801 60802 これは気にしなくても良いという事にする。 60803 60804 * syntax: *? 等の文字は extglob の時にしか着色されない [#D0616] 60805 60806 | また ble-syntax:bash/.update-_ble_syntax_bashc が extglob の変更に際して呼び出されていない。 60807 | →これは #D0615 で取り扱う。 60808 60809 これは取り敢えず現在取り掛かっていることが終わってから対処する。 60810 60811 多分、これは単に _ble_syntax_bashc で [ の他に * や ? も含める様にすれば良い。 60812 変更した。動いている。多分大丈夫だろう。 60813 60814 * syntax: shopt -u extglob にしても _ble_syntax_bashc が更新されない [#D0615] 60815 60816 これは _ble_syntax_bashc の変更条件は histc12 及び shopt -q extglob で決まるのに、 60817 ble-syntax:bash/cclass/update の呼び出し元で勝手に histc12 だけで呼び出しを判定している為である。 60818 無条件に ble-syntax:bash/cclass/update を呼び出す様にすれば良い。 60819 60820 更に ble-syntax:bash/.update-rex_simple_word も、 60821 ble-syntax:bash/cclass/update の内部で更新が実行された時に限り呼び出す様にする。 60822 60823 * syntax: hist1, hist2, hist12 等の変数は bash 固有である [#D0614] 60824 60825 これはローカル変数として管理するのではなく、 60826 グローバル変数として _ble_syntax_bash_* にした方が良い。 60827 現在は bash 決め打ちで initialize-vars の前に、 60828 local "${_ble_syntax_bash_vars[@]}" しているが、 60829 別の言語を用いる際に動かない。 60830 60831 もしくは、言語に依存したローカル変数を定義できる仕組みを提供する。 60832 本来はローカル変数を定義できる仕組みにするのが良い気がするが、 60833 設計がより複雑になる割にそんなに必要性があるか分からない。 60834 60835 解析をしている途中に更に別の解析を開始する等の事をしない限りは 60836 グローバル変数にしていても特に問題にならない気がする。 60837 60838 →取り敢えず直した。_ble_syntax_bash_hist12 というグローバル変数に入れる事にした。 60839 hist1, hist2 は実際に使うときに _ble_syntax_bash_hist12 の部分文字列として得る。 60840 また histstop についても _ble_syntax_bash_histstop という変数にした。 60841 ローカル変数は廃止した。 60842 60843 2017-11-22 60844 60845 * syntax: 変数代入に於ける pattern で入れ子 @(@()) の内側が不活性になっていない [#D0613] 60846 60847 これは var=@(aa|[bracket]) の [] も同様である。 60848 60849 これは ble-syntax:bash/check-glob で 60850 ((ctx==CTX_PATN)) の分岐以下で attr を補正しているところを参考にすれば良い。 60851 というかこの部分をより前方に持ってくれば済む話なのでは? 60852 60853 - ctx=$attr という ntype は検索しにくいので ctx:$attr などに変える。 60854 - また ctx:$attr ではなく ctx:$ctx にする。 60855 - CTX_PATN を nest-push している箇所で ntype を確定させる。 60856 60857 これは #D0612 の対応に際して統合的に対応した。 60858 60859 * 2017-09-06 ble-syntax: echo ${a#[!0-9]} は履歴展開ではない [#D0612] 60860 どうやら "echo [!1 " と入力しても展開されない。[ の中は (対応する ] がなくても) 履歴展開は無効ということ。 60861 60862 実は、もう少し試してみた所、以下は何れも履歴展開となった。 60863 60864 $ echo [a!a 60865 $ echo [a!a] 60866 $ echo [[!a 60867 60868 1 つまり、[! の組み合わせで始まる range expression だけ特別扱いする。 60869 2 range expression の中で [! の組み合わせは特に特別な意味は持たない。 60870 60871 ということ。しかし、それでも [! が特別な意味を持つかどうかの判定の為に、 60872 結局、現在 range-expression の中にいるかどうかの判定は必要になる。 60873 60874 これに対応するには、やはり新しい文脈に対応するのが良い様な気がする。 60875 思うに $(()) と類似の文脈にするのが良いだろうか。 60876 というより $(()) と違って入れ子も考えなくて良いし、より簡単な気がする。 60877 或いは case のパターンの中と同様の文脈と考えても良いかも。 60878 但し空白・delimiterは来ない。これは丁度 ctx-command の check-word-end/is-delimiter で良い気がする。 60879 と思ったが、これは呼び出し元の文脈に依存する。例えば ${a#[a ]} などの場合には 60880 其処で bracket expression が終わったりはしない。これは ntype か何かで記録する事にする。 60881 60882 うーん。然し、条件コマンドとの区別がややこしい。 60883 或いは条件コマンドをチェックして、それから [ をチェックする様にすれば良い気もする。 60884 例えば [[ の直後に文字列末端または delimiter が来る時には条件コマンドとし、 60885 それ以外の時には nest-push する。 60886 60887 nest-pop が同じ点で起こっても良いのだったか。これは確かめる必要がある。 60888 nest-pop は tree-append により情報を登録している。 60889 tree-append は word の登録にも使う。つまり同じ位置で複数の tree-append が来ても良い様にできている筈だ。 60890 問題は tree-append を複数回出来るとしても nest-pop が同じ位置で 60891 一回しか呼び出されない的な仮定がないとは言い切れないことである。 60892 60893 角括弧式の中で何が有効なのかについて調べる。 60894 60895 $ echo [@(a|\*)] 60896 * @ a 60897 60898 これを見ると角括弧式の中では extglob も含めて意味を失う様である。 60899 但し、quote は意味を失わない。 60900 60901 [実装1] ctx-command での実装 60902 60903 先に ctx-command から入った場合について実装することにする。 60904 取り敢えず nest-push について実装する。 60905 60906 何が何だか分からなくなってきたので取り敢えず 60907 ntype は気にせずに ctx-command から入った時の終端方法で実装して動作確認する。 60908 その後で様々な場合に対応する事にする。 60909 60910 x fixed: 空白や文字列末端で終端していない。 60911 check-word-end の is-delimiter が効いていないのではないか。 60912 実装仕掛けの ntype チェックで引っかかっていた。 60913 60914 x fixed: stackdump が出る。 60915 これは check-word-end で nest-pop した時に、 60916 更に外側の check-word-end を呼び出さなければならないのを抜かしたのが行けない。 60917 nest-pop が二重に起こる場合も含めて動いているように見える。 60918 ただ、この方法が設計上良いのかどうかは分からないが、取り敢えず。 60919 60920 x fixed: [!a*] などで * がエラーになっている。 60921 これは glob の入れ子を許可する様にすれば良い。 60922 直した。echo [a*] や echo [!a] は OK。 60923 取り敢えず echo [![!a] も期待通りに解析されている。 60924 echo [!a@(aaa|bbb)] は着色が変な事になっているが、 60925 これについてはまた後で実装しなおせば良い。 60926 60927 [実装2] 呼び出し元文脈に依存した振る舞い 60928 60929 次に角括弧式を抜ける位置をどの様に特定するかについて考える。 60930 現在の実装では常に ctx-command から呼び出されたと思って角括弧式を抜けている。 60931 しかし、実際には角括弧式に入った時の文脈によって色々である。 60932 60933 % * ntype はどうするのが良いか。 60934 % 60935 % nest-push "$CTX_BRAX" する時の ntype はどうしたら良いか。 60936 % 60937 % - "]" が現れる前に中断される時にどのタイミングで中断するかを見るためには、 60938 % やはり呼び出し元の ctx が必要になる。 60939 % - また内部で CTX_PATN を実行する時には不活性にしなければならない。 60940 % 60941 % 従ってやはり ctx=$ctx を ntype にして伝播させるのが良いだろう。 60942 % もう一つの方法は type=command だとか type=vrhs だとかであるが、 60943 % これは CTX_PATN 等との兼ね合いを考えると面倒である。 60944 % 60945 % よく考えてみると、CTX_PATN と混ざってくるとより面倒な事になる…。 60946 % CTX_PATN の場合は不活性にするかどうかは一番最初の呼び出し元が CTX_VRHS かどうかで決まる。 60947 % 或いは、途中で CTX_BRAX になってその中で CTX_PATN を呼び出した時にも不活性になる。 60948 % 一方で、CTX_BRAX の読み取り方の制御はどの様に行われるかというと、 60949 % 一番最初の呼び出しにおける文脈に依存する。 60950 % しかし、CTX_PATN と同様に不活性になった時の色にも注意しなければならない。 60951 % 60952 % 現在の実装では突入時の文脈を指定する事にしているが、 60953 % この方法で問題ないだろうか。 60954 % 60955 % - [] の中で更に [ や @(...) や * がある時にはどうするのか? 60956 % [ は無視する。@(...) は着色せずに読み取りを実行する。 60957 % * や ? は *() や ?() になっているかもしれないので、読み取る。 60958 % 60959 % うーん。実は一つ上の階層の ctx を考慮して CTX_BRAX の終端を判定すれば良いのではないだろうか。 60960 % そして、それとは独立に着色のために ctx= を用いるのが良いのではないだろうか。 60961 60962 当初の考えでは入った時の文脈の種類に応じて ntype を設定して、 60963 ntype に応じて CTX_BRAX の中で処理を切り替えるという事を考えていた。 60964 しかし ntype は CTX_VRHS CTX_BRAX の下に入れ子になっている時に、 60965 着色を無効化する為に用いたいので、別の方法を考える。 60966 60967 | 別の方法と言っても入った時の文脈を nest 情報から抽出するという事である。 60968 | ※実のところこの nest 情報は入った時の文脈というよりは、 60969 | 抜ける時の文脈といった方が正確である点には注意する。 60970 | 入った時の文脈を取得する関数として ble-syntax/parse/nest-ctx を作った。 60971 | 今までこれがなかったのは不思議であるが、便利そう。 60972 | 60973 | これを使って文脈を取得し、特別な文脈以外では ctx-command 由来として処理する。 60974 | さて、どのような文脈で CTX_BRAX が nest-push されるだろうか。列挙する。 60975 | 現在 CTX_BRAX を nest-push しているのは check-glob のみであり、 60976 | この check-glob を呼び出している箇所は以下の通り。 60977 | 60978 | - ble-syntax:bash/ctx-command (色々) 60979 | - ble-syntax:bash/ctx-values (CTX_VALI) 60980 | - ble-syntax:bash/ctx-redirect (CTX_RDR[FDS]) 60981 | - ble-syntax:bash/ctx-conditions (CTX_CONDI) 60982 | - ble-syntax:bash/ctx-globpat (CTX_PATN) 60983 | - ble-syntax:bash/ctx-bracket-expression (CTX_BRAX) 60984 | 60985 | この内、ctx-command ctx-redirect は同様に扱って問題ない。 60986 | 残っているのは全て単一の文脈値なので直接比較して問題ない気がする。 60987 | 一つずつ見ていく事にする。 60988 | 60989 | - CTX_VALI の場合は、実は ctx-command と殆ど同じ扱いで良い気がする。 60990 | 但し、")" が来たら終わる。でも ")" が来たら終わるのは ctx-command でも同じ。 60991 | - CTX_CONDI の場合は、 60992 | 60993 | % ctx-command と似ているが少し処理を変える必要がある。 60994 | % 空白を除く delimiter つまり ()<>;|& が単語に含まれることが許されている。 60995 | % これらは例えば "()<>;|&" を chars から除いて処理すれば良いのだろうか。 60996 | % 念のため確認する。[...] の中に delimiter の文字が現れても良いのだろうか 60997 | % →と思って試したら構文エラーになる。というか [...] の中でなくてもエラーになる。 60998 | 60999 | 改めて考え直す。先ず "()<>;|&" を含む単語で許されているのは、少数の物のみであり、 61000 | 更にそれらに "[" が含まれる事はない。従って、()<>;|& が現れた時点で [...] を抜けて良い。 61001 | 外側で自動的にエラーが設定されるだろう。また、空白類が来た時も [...] を抜ける。 61002 | 結局、CTX_VALI と同様に ctx-command と同じ処理をすれば良い。 61003 | - CTX_BRAX から check-glob を呼び出した時は nest-push が起こらない。 61004 | つまり nctx が CTX_BRAX になる事はない。 61005 | - 結局特別な取り扱いをする必要があるのは CTX_PATN だけの様だ。 61006 | CTX_PATN では < や > が単体で現れる事が許される。 61007 | これは [] の中でも同様なのだろうか。どうも許される様だ。 61008 | 61009 | さて、@([a|b]) はどの様に解釈されるのか? 61010 | →調べてみると @(["a|b"]) と解釈されている様だ。 61011 | @([a b]) は @(["a b"]) と解釈されている。 61012 | 61013 | @([a()b]) は @(["a()b"]) と解釈されている。 61014 | @(a|[) はどうも構文解析はうまくいくがパス名展開は失敗している。 61015 | 何れにしても ")" が現れた所で終わるという解釈で良さそうだ。 61016 | うーん。つまり、[...] の中でも () の入れ子を追跡しなければならないという事。 61017 | (後のパス名展開で失敗するかもしれないとしても、構文解析上はそうなっている気がする。) 61018 61019 まとめる。CTX_BRAX による読み取りの判定は nctx を用いて行う。 61020 - nctx を取得するためのシェル関数 ble-syntax/parse/nest-ctx を追加した 61021 - nctx が CTX_PATN の時以外は、ctx-command から呼び出したと考えたと時と同様の処理で良い。 61022 - nctx が CTX_PATN の時は、) が来たら終わる。 61023 ( が来たら nest-push して入れ子を数える。 61024 その他の文字 (|<>*?@+!) は単に [...] に含まれる事が許される。 61025 61026 x fixed: echo @([a|b]) で | の着色がエラーになっている。 61027 これは特別に追加する必要があった。 61028 他の文字 (*?!+@) は check-glob で着色される 61029 (extglob ならピンク、extglob でなければ黒) ので必要ない。 61030 61031 [実装3] CTX_PATN と CTX_BRAX の入れ子について再確認 61032 61033 | * CTX_BRAX の中で CTX_PATN になって更に "[" に出会った時にはどうするのか。 61034 | 調べてみると、"[" を bracket expression と認識している様子だ。 61035 | 61036 | echo [@(aaa|[!a])] は履歴展開が無効だが、 61037 | echo [@(aaa|[a!a])] は履歴展開が有効になる。 61038 | つまり [! の組を認識している。 61039 | と思ったが、実は echo [[!a]] も履歴展開は無効だし、 61040 | echo [![!a]] も履歴展開は無効のようだ。 61041 | 一方で echo [[!a や echo [!a は履歴展開が有効になる。 61042 | つまり bracket expression が閉じていれば [! の組の履歴展開は無効で、 61043 | bracket expression が開いていれば [! の組でも履歴展開は有効になる。 61044 | 61045 | 従って、CTX_BRAX であっても [! は認識するべきである。 61046 | 但し、CTX_BRAX の時には nest-push はしないという事にする。 61047 | 61048 | * echo [![!a]] はどのように組まれるか? 61049 | 実際にファイル名に一致させて試すと 61050 | echo [!"[!a"]"]" と解釈される様である。 61051 | つまり、[!...] の入れ子は考慮に入れられないが、 61052 | "[!" の組で履歴展開にならないということだけは処理される。 61053 | 61054 | * やはり [@(...)] の中で更に [...] があった時の解釈が分からない。 61055 | ファイル名に一致させてみると echo [@([aaa])] は、 61056 | echo ["@([aaa"]")]" というパターンになっている様である。 61057 | これは実際の解析のまとまりとはばらばらの様に思われる。 61058 | うーん。つまり最初の切り出しは ["@([aaa])"] となるが、 61059 | 実際の解釈では ["@([aaa"]")]" となるという事である。 61060 | これは ble.sh の解析の枠組みでは直接取り扱えない。 61061 | つまり着色は ["@([aaa"])] のまとまりで行いつつも 61062 | 残った ")]" の部分についてのエラーは 61063 | ["@([aaa])"] の構造があるとして抑制しなければならない。 61064 61065 - [...] の入れ子は考慮に入れられない。 61066 つまり "[" の登場に拘らず "]" の登場ですぐに閉じる。 61067 - [...] の中でも [! の組は履歴展開の ! とは認識されない。 61068 つまり、入れ子の勘定には入れないが、"[!" の組は認識している。 61069 - [...] の中でも extglob @(...) のまとまりは有効である。 61070 但し、元の意味は失う。つまり、解析にだけ考慮される。 61071 - [...] の中で @(...) があって、更に中に [...] があった時の解釈は厄介である。 61072 例えば [@([abc])] の場合には、 61073 構文構造としては [@([abc])] のまとまりで切り出されるが、 61074 最終的なパス名展開の適用に際しては [@([abc] のまとまりで切り出されてしまう。 61075 これについては構文構造を優先して着色する事にする。 61076 61077 この辺りの振る舞いについては現在の実装で問題ないはずである。 61078 問題は @([(...)]) の場合に () の入れ子を処理する必要がある事である。 61079 check-glob を弄って ctx==CTX_BRAX の時も入れ子を数える様にする。 61080 取り敢えず色はさておき、構文構造は正しく解析できる様にする。 61081 取り敢えず対応した。 61082 61083 [実装4] 入れ子になっている時の色の伝播に関して。 61084 61085 % 改めて CTX_PATN が関わってくる場合を考える。 61086 % CTX_PATN の中で更に [...] がある場合には、 61087 % [... の不完全終端は CTX_PATN の終端と同じにする。 61088 % 一方で、着色に関しては CTX_PATN と同じ色にすれば良い。 61089 % 但し、CTX_PATN の nest の時には別の色にしなければならない。 61090 61091 | 変数代入の右辺でどうなっているか。 61092 | 61093 | $ echo=[a] # → パス名展開は起こらない。 61094 | $ echo=[!a] # → 履歴展開されない。パス名展開も起こらない 61095 | $ echo=[a!a] # → 履歴展開される。パス名展開も起こらない 61096 | 61097 | つまり、解析としては [!...] を拾っているが、 61098 | パス名展開は起こらないと考えて良い。 61099 | 現状の @(...) と同様に nest-push して解釈はするが、 61100 | 着色はしないというように処理すれば良い。 61101 61102 変数展開の下の glob パターンは、全て解析はするが着色は無効化する。 61103 61104 うーん。特に色を無効化させるのであれば、 61105 色を外側から伝播させれば良い様な気がする。 61106 61107 CTX_VRHS から下はどう頑張っても全て無効化 61108 同様に CTX_BRAX から下はどう頑張っても全て無効化。 61109 それ以外の時には nest の括弧は無色。それ以外は着色。 61110 61111 さて、現在 ntype=nest は他の用途で使われているだろうか。 61112 どうも、ここで色を決定することにしか使われていない様だ。 61113 61114 ntype の意味を次の様に定める。 61115 1 ntype='nest' の時はその括弧及び内側の | は特別な色をつけない事を意味する。 61116 更に内側の [...] や @(...) は有効になる。 61117 2 ntype='ctx=...' の時はその括弧及び内側の | はその ... で着色する事を意味する。 61118 更に内側の [...] や @(...) に対してもその塗り潰しは継承する。 61119 61120 取り敢えず実装した。 61121 61122 * supported: here string でも glob/bracket は無効化されるべき。 61123 61124 [実装5] 後は新しく生じた不整合を解決する。 61125 61126 x fixed: [[ が無効になっている。 61127 61128 これはどの様に対応するべきか。 61129 先ず初めに [ の直後に [ がある場合はそれも一緒に読み取ってしまう? 61130 しかしそうすると今度は [[! の場合に其処まで読み取らなければならない。 61131 61132 というかそもそも現状はどの様な状態なのだろうか。 61133 '[[' の部分を見ると i=$wbeg ble-syntax/parse/nest-push している。 61134 これはつまり単語の開始点が現在の解析 step の開始点以降である事を前提としている。 61135 現在の実装だとその仮定が崩れてしまっている。 61136 61137 正しく実装し直す為には、nest-push の点をずらすか、 61138 或いは [[ の連なりは一度に解析できる様に修正するか。 61139 取り敢えず [[ の連なりは一度に解析する様に修正する。 61140 これは直した。 61141 61142 x fixed: simple word で [] が許されなくなっている。 61143 これは _ble_syntax_bashc_simple に "[" が混入していたのがいけなかった。 61144 _ble_syntax_bashc_simple を _ble_syntax_bashc[CTX_ARGI] と独立に生成する様にした。 61145 61146 * syntax: プロセス置換が @(<(echo)) で認識されていない。 [#D0611] 61147 角括弧式対応の途中で気付いた。 61148 これは元からあった問題である。修正した。 61149 61150 * edit (command-help): quote されていると駄目 [#D0610] 61151 61152 * edit (command-help): function, until が引っかからない。 [#D0609] 61153 61154 * 2017-11-14 complete: コマンドの補完候補に出てくる functions とは何だろう [#D0608] 61155 実際には見つからないし実行できない 61156 61157 →これはどうもディレクトリ functions が一致している様だ。 61158 所で、functions まで入力して TAB を押しても functions という候補が二重に出ている所為で補完できない。 61159 他のディレクトリ名についても同様の様である。 61160 61161 重複を除く様にしてみたがそれでも 2 つ出て来る。 61162 異なる source から複数現れているのだろうか。 61163 と思って調べてみた所、ble-complete/source/command から 2 つ現れている。 61164 ble-complete/source-command では sort -u する様にしたはずなのにおかしい。 61165 と思ったら、ble-complete/source/dir が明示的に呼び出されている。 61166 61167 しかし、そうだとしても不思議だ。shopt -s autocd は有効になっていないので、 61168 前者からは候補が出てこない筈である。 61169 61170 うーん。と思ったら、どうも compgen -c -- foo で 61171 foo がディレクトリ名に厳密に一致している場合、 61172 foo も補完候補として表示されてしまうのだという事が分かった。 61173 これはどの様にしたら良いか。 61174 61175 また、実際に補完候補が確定した時の振る舞いについても考える必要がある。 61176 例えば、確定された単語がディレクトリ名だったら / を後置する様にするなど…。 61177 しかし、コマンド名とディレクトリ名が被る場合はどうするのか謎である。 61178 mkdir grep として調べてみると、どうやら実行する時にはコマンド名の方が優先される様だ。 61179 61180 a 一つの方法はディレクトリ名としての候補の場合には予め / を後置する様にする。 61181 確定した単語が / で終わりかつ実在するディレクトリ名だった時には、 61182 そのまま確定する。それ以外の時には空白を空ける。 61183 61184 これだと / で終わる名前のシェル関数とディレクトリ名が同じ時に、 61185 本来はシェル関数の方が呼び出されるはずなのにディレクトリ名として解釈されて、 61186 空白が後ろに付加されない。しかし、まあ妥当な振る舞いの範疇だろう。 61187 61188 - 同様に autocd によって列挙されるディレクトリ名の場合にも / を後置する。 61189 その様にしないと既存のコマンド名とディレクトリ名が被っていた時に、 61190 ディレクトリに移動しようとしてもコマンドを実行してしまうからである。 61191 61192 適当に実装した。 61193 61194 - 実は shopt -s autocd かどうかには依らずに、ディレクトリ名は foo*/ で生成すれば良い。 61195 - foo というディレクトリがある時に compgen -c -- foo で foo が列挙されてしまう問題については、 61196 workaround として "cand がディレクトリ名であって該当するコマンドが見つからないとき、 61197 その候補を除去する" という処置を取ることにした。 61198 61199 * syntax: declare, local, の類が予約語の色になっている。 [#D0607] 61200 修正した。と思ったら、今度は declare の上での変数名の補完が効かなくなっている。 61201 ble_debug=1 で見てみると declare の直後の文脈が通常のものに戻っている。 61202 と思ったら、is_keyword でない時には後で ctx=ARGX に上書きされて、 61203 通常の引数のための処理が行われている。 61204 61205 * complete: echo echo などのように二重に候補が出るのは何故か。 [#D0606] 61206 61207 これは compgen -c -- echo の時点で再現する。 61208 どうも組み込みコマンドの echo と通常コマンドの echo が両方一致している? 61209 しかし、grep の場合も同様に二つ表示される。と思ったが、これの場合は alias だ。 61210 61211 取り敢えず sort -u を呼び出すことにしたが、 61212 実は compgen に重複を発生させないオプションが合ったりするかもしれない。 61213 と思って man bash を見るがやはり complete と共通のオプション以外はない。 61214 そして complete には重複を除くなどのオプションはない。 61215 結局自前で sort -u を呼び出すようにしなければならない。 61216 61217 2017-11-21 61218 61219 * 2017-11-11 complete: time の次に来るコマンド名で補完ができない。 [#D0605] 61220 これは恐らく文脈値を増やしたのにそれを追加していないのがいけない。 61221 61222 これは調べてみた所、time -p command まで一度に解析する様にしているのが原因である。 61223 コマンド名の先頭に stat (ctx) が設置されていないのが原因である。 61224 現在の補完の枠組みでは ctx を使っているので、これでは補完候補を生成できない。 61225 61226 或いは、コマンドの候補を生成する時には先頭が "time [-p]" になっていれば、 61227 その部分は削って候補生成を行うという様にも出来るが、 61228 それは実装として汚い気がする。やはり新しく文脈値を導入するほうが良さそうだ。 61229 61230 →これは #D0604 の対応と共に実装した。 61231 61232 * 2017-11-14 syntax: time -p -- echo hello (bash-4.2 以降) [#D0604] 61233 61234 実は time -p -- echo hello とできる。 61235 time -- echo hello はできない。 61236 調べてみると、これは bash-4.2 以降の以降である。 61237 bash CHANGES にもちゃんと書かれていた (bash-4.2-alpha/3.r)。 61238 61239 これに関しては途中に解析再開点を設置する様にしたいので、 61240 やはり文脈値を拡張して対応することにしたい。 61241 文脈値の拡張に関しては CTX_CARGX1 などを参考にするのが良い気がする。 61242 in 等の代わりに -p が特別な意味を持つようにする。 61243 61244 取り敢えず CTX_CARG{X,I}{1,2} を複製する形で CTX_TARG* を作った。 61245 然し、実際の処理はもっと異なる形になるような気がする。 61246 一つずつ CTX_TARGX1 から順に対応していく事にする。 61247 61248 少し対応した所で整理した。と思ったら完成していた。 61249 取り敢えず動いている。 61250 61251 * 2017-09-05 syntax: function hello (()) は bash-3.0 では構文エラー。 [#D0603] 61252 →どうも調べてみた所 bash-4.1 まで使えなかった様だ。bash-4.2 以降で使える。 61253 61254 * 2017-09-05 syntax: function hello (()) としておいて function hello () (()) にすると解析が誤っている。 [#D0602] 61255 これは新しく導入した set-lookahead 2 で簡単に直った。 61256 61257 * 2017-11-14 syntax: echo $(echo > ) において $() が閉じていないとなっている。 [#D0601] 61258 61259 元々 > の次に ) が来た時点で構文エラーなのだから、 61260 ")" がどう取り扱われようと勝手なのかもしれないが、 61261 61262 - やはり直観としてはエラーは > の手前で止まってほしいし、 61263 61264 - 例えば、長いコマンドの最初の方の $() の中にリダイレクトを追加する時、 61265 一瞬この様な状態になったことで部分更新が働かなくなるのも嫌である。 61266 61267 従って、> において ) が現れたらその手前で nest-pop 61268 をするという訳には行かないだろうか。 61269 61270 nest-pop/tree-append の都合で 1 文字以上進んでからしか pop できないと思ったが、 61271 よく考えてみれば、check-word-end 辺りで確認を行って、 61272 次に delimiter が来ていればエラーを設置すると共に、nest-pop すれば良い。 61273 61274 と思ったが、調べてみると実際にその様な実装になっている。 61275 何故だろう…と思ったら、そもそも単語が始まっていない時には nest-pop は実行されない様だ。 61276 61277 a それなら、単語を構成する文字が見つからない場合には初めから nest-push しなければ良い、 61278 と考えたが、駄目だ。先読みしてしまうと部分更新の時に破綻してしまう。 61279 先読みした分だけ呼び出し元で単語の設置などしてしまうと、 61280 結局新しい文脈を使って解析している意味がない…というか、 61281 プロセス置換などの構成を使っている時に対応がどんどん面倒になってくる。 61282 61283 b 或いは、次の一文字だけなら読むことを許されているのだから、 61284 次の一文字が許される文字だったならば nest-push する。 61285 そして、CTX_RDRF 等の文脈において失敗したならば、 61286 61287 と思ったが、次の一文字だけを見るのだと [<>] がいる時に、 61288 それがプロセス置換 [<>](...) の一部かもしれないので、 61289 受け入れざるを得ない。従って、[<>] の時は nest-push する。 61290 61291 さて。nest-push するところを修正したらすぐに大丈夫になった。何故? 61292 よく見てみるとリダイレクトの後に続く空白類は既に 61293 redirection の始まりの記号の一部として読み取っていた。 61294 従って、直ぐに単語が始まる状態になっていたのだった。 61295 なので単語に突入しないという状態にはならない。 61296 61297 [プロセス置換の先読み問題] 61298 61299 例外はプロセス置換の時である。 61300 将来的にプロセス置換を構成するかもしれない < が単体で入力された状態の時、 61301 一体どのように解釈されるべきか。 61302 61303 というか ble-syntax:bash/ctx-redirect/check-word-end で2文字以上先を参照しているが良いのだろうか。 61304 % うーん。どうやら > A<(B から A<B に化ける時には、直前の再開点は < であり…と思ったが、駄目だ。 61305 やはり問題になる気がする 61306 →現実に問題になることを確認した。 61307 先ず echo >A<(echo) の状態にしておいて ( と ) を削除すると、 61308 echo >A<echo において、"<" の位置でエラーという事になる。 61309 一方で、普通に echo >A<echo とすると構文エラーにはならない 61310 (但し、echo というファイルは見つからないというエラーにはなる)。 61311 61312 これはどの様に処理するべきか。 61313 61314 a 一つの方法は先読みの文字数を 2 文字にするということ。 61315 61316 広範な変更が必要になりそう。 61317 また、解析再開が非効率になるのが気になる。 61318 実際どの程度非効率になるのだろうか。 61319 61320 それに解決策としては余り綺麗でない気がする。 61321 例えば、今後 3 文字先読みが必要になったら、 61322 全体で 3 文字の先読みを許容するようにするのか? 際限がない。 61323 61324 b 或いは、先読みをした時にはその文字数を記録する。 61325 61326 % 因みに、読み取りの終端位置を決めるのに、 61327 % 例えば [[:alnum:]]+ 的なことをするので、 61328 % 実質必ず 1 文字以上先読みはしているような物である。 61329 % ただ、物によっては $(( など、それ以上一度に読み取らないというものもある。 61330 61331 この方法が良い様な気がする。 61332 但し、stat に新しい要素を追加する事になる。 61333 stat に要素を追加する時の方法について確認する必要がある。 61334 61335 また、今回の問題の解決に実際に使わないとしても、 61336 今までの実装を考えると先読みの文字数を指定できる様にすると大分楽になる気がする。 61337 実のところ、今までの方法では "先読みをした場合には、先読みされた部分まで一気に解析する" 61338 または "先読みした時にはそこには解析再開点は設置しない" という方法を取っていたので、 61339 実のところ解析の効率が落ちるということもない気がする。 61340 61341 c もう一つの方法は "曖昧な状態" を表す文脈を用意するということ。 61342 61343 しかし、これは <( の直前に現れる可能性のある文脈値全てについて、 61344 その種類が倍化するので始末が悪い気がする。 61345 或いは、別の変数を使って曖昧な状態を表現するとしても、 61346 それは結局 b と等価になるのではないだろうか。 61347 寧ろ、b よりも間接的なので分かりにくい。 61348 61349 d 実のところ解析再開点を設置しないという対策だけで良いのではないかという気もしてきた。 61350 61351 問題点は何かというと、現在の補完の枠組みでは解析再開点を用いて補完候補生成方法を決定しているので、 61352 解析再開点を省略するとそこから始まる単語について補完候補の生成を行うことができない事にある。 61353 61354 現在の補完の枠組みは、解析再開点を用いるのではなく単語などの情報を用いるように変更するべきの気がする。 61355 と思ったが、結局単語の詳細な情報はその単語の読み取りを開始した時の文脈値に依存する。 61356 結局、解析再開点の情報も必要になるのではないか。 61357 61358 或いは、"無効化した解析再開点" の様なものを用意して、 61359 そこにおける文脈値だけを記録するという手もある。 61360 61361 やはり先読みの文字数を設定できるようにした方が柔軟な気がしてきた。 61362 また、解析再開点を設置しない方法だと、先読み位置以降・次の再開点以前の範囲で変更があった場合に、 61363 本来必要のない再解析をすることになる。更に先読みが続くと解析再開点が連続で設置されないという事になる。 61364 61365 やはり先読みの文字数を記録する b の方針で考える。 61366 比較的大きな書き換えになるし、ちゃんとできるか分からないので取り敢えず commit を切る。 61367 61368 [書き換え] 61369 61370 1 解析変数の追加 61371 61372 前回 nparam を書き換えた時と同様に行えば良い。 61373 注意点としては nparam は空文字列になりうるので、 61374 _ble_syntax_stat に格納する際には空文字列は none に置き換えるか、 61375 或いは nparam の前に新しい変数を挿入するかである。 61376 61377 新しい変数を導入する度に nparam の位置が変わるのは始末が悪いので、 61378 空の nparam は none に置き換える事にする。 61379 これは _ble_syntax_stat に格納・から読み出すところで弄れば良い。 61380 と思ったら初めからそのような実装になっていたので問題ない。 61381 61382 nparam の次の解析変数として lookahead を追加する。 61383 調べてみたが新しい解析変数の追加はそれほど大変ではないようだ。 61384 初期化と保存と ble_debug による出力に対応すれば良い。 61385 61386 2 次に lookahead を見て解析再開点を決定する様にする必要がある。 61387 61388 現在の実装では parse の以下の部分で決定している。 61389 61390 | # 解析予定範囲の更新 61391 | local i1 i2 j2 flagSeekStat=0 61392 | ((i1=_ble_syntax_dbeg,i1>=end0&&(i1+=shift), 61393 | i2=_ble_syntax_dend,i2>=end0&&(i2+=shift), 61394 | (i1<0||beg<i1)&&(i1=beg,flagSeekStat=1), 61395 | (i2<0||i2<end)&&(i2=end), 61396 | (i2>iN)&&(i2=iN), 61397 | j2=i2-shift)) 61398 | if ((flagSeekStat)); then 61399 | # beg より前の最後の stat の位置まで戻る 61400 | while ((i1>0)) && ! [[ ${_ble_syntax_stat[--i1]} ]]; do :;done 61401 | fi 61402 61403 先ず flagSeekStat とは何だろう。 61404 というか何故 i1 end0 _ble_syntax_dbeg, _ble_syntax_dend など色々あるのか。 61405 コメントに書かれていた。_ble_syntax_d* は前回の解析でやり残した部分を記録する。 61406 先ず初めに i1..i2 に前回の解析でやり残した範囲を読み込む。 61407 その後で今回の文字列の編集範囲を用いて i1..i2 を更新する。 61408 flagSeekStat は、今回の文字列の編集範囲によって解析を開始することを示す。 61409 flagSeekStat が立っていないとき、前回の解析中断位置から再開するが、 61410 必ず stat が設定されている位置で中断される (予定) なので、わざわざ解析再開点を探す必要がない。 61411 61412 lookahead によるマージンを取るのは flagSeekStat の中で判定すれば良い。 61413 実装した。取り敢えず既存の解析再開の仕組みは動いている様に見える。 61414 61415 3 後は、折に触れて lookadhead を更新すれば良い。 61416 61417 lookahead の更新はただ代入するのではなくて、 61418 前の値よりも大きい時に更新するという様にする。 61419 61420 そうすれば一回の解析の間に複数箇所で先読みをした時に対応できる。 61421 元々2文字以上の先読みを実行する箇所は少ないのだから、 61422 このぐらいのチェックで遅くなるということは考えにくい。 61423 従って、速度については気にしなくて良い。 61424 61425 と思ったが、実のところ一回 lookahead を設定した後に、 61426 解析位置が進んだ場合にはどうするのだろう。 61427 その場合には lookahead を再び clear しなければならない。 61428 改めて lookahead の方法について考える。 61429 61430 a 一つの方法は必ず解析の最後で lookahead を設定するという事である。 61431 その様にすれば lookahead の位置がずれる事はない。 61432 しかし、問題点は check-process-subst 等で一致するかどうか参照しているが 61433 引っかからなかったという時に lookahead をどう設定するのかということである。 61434 或いは、引っかからなかった時には lookahead は設定しなくても大丈夫だろうか。 61435 61436 実のところ 2 文字ならば lookahead は設定しなくても大丈夫である。 61437 何故なら 1 回の解析で少なくとも 1 文字は進み、 61438 更に少なくとも 1 文字の先読みが存在するので、 61439 もし失敗して別の方法で進む場合には 2 文字まで先読みして大丈夫である。 61440 61441 では任意の文字数先読みすることは可能なのだろうか。 61442 61443 % もしかするとそもそも先読みがなかったことにできるという可能性もある。 61444 % 例えば <() について考える。今 <a 等の様になっていたとする。 61445 % この時一致は失敗して < 単体に後で引っかかる。 61446 % ここで先読みがなかったことにするとどうなるだろう。 61447 % "<(a" の様に "(" を挿入したとする。実際のところ a まで見て一致しないと判定したのに、 61448 % 解析再開の際には "<" の部分に変更がないからという理由で、 61449 % 前回の解析結果が採用されて、今回も一致しないという様になってしまう。 61450 % この例の時には、実際には > が読み取られてその次の文字まで先読みになるので問題にはなっていなかったが、 61451 % 3 文字以上に渡る先読みの場合にはやはり問題が発生する。 61452 61453 一致に失敗したとしても先読みして動作を変更したのであれば、 61454 それを記録しておかないと後で不整合が起こってしまう。 61455 61456 x 先読みの長さに関する制限もある。 61457 61458 前回の解析ステップで先読みした長さを、 61459 次の解析ステップでは必ず全て取り尽くさなければならない。 61460 61461 何故なら、解析再開点の決定では文字列変更範囲より前の再開点で、 61462 一番最初に見つかったものを採用するからである。 61463 もし前回の解析ステップの先読みを取り尽くさないと以下のような場合に問題になる。 61464 61465 aaaaaaXa 文字列と編集位置 61466 +------- 解析再開点1 + 先読み 61467 +--- 解析再開点2 + 先読み 61468 61469 X の位置で編集が起こった時、本来であれば解析再開点1 から解析を再開しなければならないが、 61470 実際には最初に見つかった解析再開点2 から解析が再開されてしまうことになる。 61471 61472 b もう一つの方法は、現在は lookahead を "何文字先か" で管理しているが、 61473 実際の解析の過程では "先読みした最後の位置の index" を管理する様にする。 61474 _ble_syntax_stat に記録する時に何文字先かの情報に書き換える。 61475 61476 | すると shift の対象になるのではないかとも考えたが、shift はしなくてよい。 61477 | % というかむしろ shift するべきではないと思われる。 61478 | lookahead を設定するのは再開点と先読み点の間で変更があった場合に、 61479 | 解析再実行範囲を再開点まで拡張するために用いられる。 61480 | もし文字列変更範囲が再開点よりも前にある時には shift は必要ない。 61481 | 文字列変更範囲が先読み点よりも後にある時にはやはり shift は必要ない。 61482 | 文字列変更範囲が被っているとき、 61483 | 再開点が文字列変更範囲に含まれる場合にはそもそもその再開点は消滅するので気にしなくて良い。 61484 | 再開点と先読み点の間で文字列変更範囲が始まっている場合には shift してもしなくても、 61485 | その再開点は使えないということが計算して分かる。 61486 | なので、shift の機会があるとしても shift してもしなくても何も変わらない。 61487 61488 [結論] shift の必要はない。 61489 61490 % 或いは、寧ろ "何文字先まで見たか" を記録する為だけに "先読み点" を計算していたのであって、 61491 % 飽くまで "何文字先か" という情報なのだと思えば自然かもしれない。 61492 % と思ったがこの考え方はやはり安易な気がする。 61493 61494 この方法を用いれば a の所に書いた先読みの長さに関する制限も自然に解消できる。 61495 こちらの方法を用いるべきである。 61496 61497 2' 改めて b の方法に従って lookahead を書き換えることにする。 61498 変数名はどの様にするべきか。lookahead を文字数として、 61499 ilook を lookahead の位置ということにしようか。 61500 書き換えた。まあ問題なく動いている。 61501 61502 3' 取り敢えず問題になっていた部分について設定を行う。 61503 61504 % と思ったら…再現しない。現在は問題なく解析できている。 61505 再現した。スペースがあるかないかで変わる様だ。 61506 "echo > A<(echo)" から "echo > A<echo" に書き換えるとなる。 61507 61508 これの原因は何だったかというと "> A<(echo)" となっている時に、 61509 解析再開点が < の位置に設置されリダイレクト先の続きを読む設定になっている。 61510 ここで、<( となっている時には問題がないが < に書き換わると、 61511 ここはリダイレクト先の続きを読むのではなくて、 61512 新しい別のリダイレクトとして読まなければならない。 61513 つまり、この解析再開点が誤っている。 61514 何故このような事になったかというと、そもそもこの解析再開点を設置した時に先読みして 61515 "<(" まで見てリダイレクト先の続きを読むとした為である。 61516 つまり "(" が消滅する様な場合には、この解析再開点は無効化されなければならない。 61517 61518 さて set-lookahead で先読みしたことを設定してみる。 61519 正しく先読み情報が記録されている。 61520 そして上記の編集の後でも正しく文法が解析されていることを確認した。取り敢えず OK 61521 61522 4' その他のプロセス置換の部分についても確かめる。 61523 61524 % と思ったが、よく考えたらプロセス置換に限らず 61525 % $(( や $( でも問題になるのではないだろうか…。 61526 % しかし、これらについて問題になるのではないかという事は今まで意識したことがない。何故か。 61527 % 61528 % 例えば $(( について考える。一致した時には $(( の末端まで移動するので問題は起こらない。 61529 % 一致しなかった場合には、3 文字目まで見たときは代わりに $( の方に一致するはずである。 61530 % この時、3 文字目も先読みしたことになるので問題ない。 61531 % 2文字目まで見て一致しないという事が分かったとき、必ず後で 1 文字は解析が進むので、 61532 % やはり 2 文字目の先読みの範囲に自動的になるので問題ない。 61533 61534 $( や $(( で問題にならなかったのには、ちゃんと理由がある。 61535 $(( は 3 文字目まで見て失敗した時は必ず $( に一致するので OK。 61536 先読み2文字以下の構造については、そこで採用されなかったとしても必ず1文字進んで、 61537 その先読みで2文字は必ず進むので、気にしなくても良い。 61538 61539 - その他、同様に check-word-end で参照している部分については、 61540 共通の関数 check-word-end/is-delimiter を用意してそれを使う事にした。 61541 61542 - また、starts-with-delimter という関数も用意する事にした。 61543 これは実際に読み取りを行うよりも前の位置で呼び出すので、 61544 恐らく先読みの設定はしなくても大丈夫。 61545 先読みが当たればそれに対応する分だけ解析が進むし、 61546 先読みが外れるとしても1文字少ない部分列で解析が進むので、 61547 先読みの文字数に問題は起こらない。 61548 61549 - 最後に starts-with-delimiter-or-redirect については、 61550 'time' 予約語に対して使っている箇所と、 61551 ctx-command の冒頭で使っている箇所がある。 61552 61553 ctx-command の冒頭で使っているところでは、 61554 最終的に対応する redirect または delimiter を読み取るので問題ない。 61555 'time' 予約語に関してはまた実装を見直す予定なので、 61556 ここでは未だ余り真面目に考えなくても良い。 61557 実のところ、駄目な気がする…というか check-word-end/is-delimiter を使うべきでは? 61558 →starts-with-delimiter-or-redirect ではなく check-word-end/is-delimiter を使う事にした。 61559 61560 取り敢えずよしとする。 61561 61562 * memo.txt: D0535 が重複している。D0587 も重複している。 [#D0600] 61563 61564 以下を使って調べたところ重複は他にはない。 61565 $ grep -ao '\[#D....\]' memo.txt | sort | uniq -cd 61566 61567 跳びもない 61568 $ grep -ao '\[#D....\]' memo.txt | wc 61569 599 61570 61571 番号が付いていない項目もない 61572 $ grep -Ea '^ \* (.*\[#D....\]$)?' memo.txt 61573 61574 61575 どの様にしたら自動的にずらす事ができるだろうか。 61576 D05\(3[5-9]|[4-9].\) → D05\,(1+ \1) 61577 61578 うーん。 61579 D05\(3[5-9]|[4-9].\) → D05\,(+ \1 (if (<= \1 87) 1 2)) 61580 D05\(3[5-9]|[4-9].\) → D05\,(let ((num (string-to-number \1))) (+ num (if (<= num 87) 1 2))) 61581 61582 修正した。多分、大丈夫。 61583 61584 * syntax: $(()) が常にエラーの着色になってしまっている。何故か。 [#D0599] 61585 61586 [状況] 61587 61588 調べてみると nest-push した時に中で ARGX になっている。 61589 $() も赤くなってしまっている。"$(echo)" も最初の " が赤くなっている。 61590 61591 これは明らかに、#D0597 の書き換えによって単語内部を解析する時の 61592 wtype を変更したのが原因である。しかしどの部分でエラーになっているのだろう。 61593 調べてみるとエラー着色は構文解析の時点で設定されている。 61594 特に nest-push が発生した時に限り起こっている様に思われる。 61595 61596 [原因] 61597 61598 もう少し調べてみる。先ず初めに $(( が来ると check-dollar に入る。 61599 ここで attr には CTX_PARAM が設定される。そして nest-push をしてそのまま抜ける。 61600 抜けると ble-syntax:bash/ctx-command に戻る。 61601 flagComsume=1 が設定されるので、後でその分岐に入る。 61602 エラーが設定される条件は2パターンある。 61603 61604 - 1つは _ble_syntax_bash_command_expect[wtype] に設定されている wtype であること。 61605 これは違う。この配列に登録されているのは CMDXE などだけである。 61606 61607 - もう一つは unexpectedWbegin が設定されていること。 61608 しかし、こちらだと考えると変だ。 61609 61610 例えば " の場合は "a" の様に単純な場合にはエラーにはならない。 61611 一方で "$(echo)" だとエラーになる。unexpectedWbegin は其処にある文字で判定するので、 61612 " の後に何が来るかに依存しないはずである。 61613 61614 エラーになるかならないかを分けているのはやはり nest-push したかしないかである。 61615 nest-push では unexpectedWbegin は書き換えない。wtype は書き換える。 61616 という事を考えると、やはり wtype が書き換わる nest-push が怪しい。 61617 nest-push で wtype は -1 になる。しかし _ble_syntax_bash_command_expect に -1 はない。 61618 配列に -1 を指定すればエラーになる。と思ったが、よく考えたら負の添字を渡すと、 61619 一番最後の要素の値が取れるのではなかったか。実際に試してみるとそうだった。 61620 61621 [修正1] 61622 61623 ${_ble_syntax_bash_command_expect[wtype]} の確認をする前に 61624 wtype が 0 以上である事を確認する様にした。直った。 61625 61626 test/benchmark/benchmark-201711-arithmetic.sh 61627 所で、0 以上である事を調べてから条件コマンドで中身を確認する時に、 61628 算術式コマンドと条件コマンドに分割した方が速いのか、 61629 或いは、単一の条件コマンドのした方が速いのかについて調べた。 61630 このケースの場合にはどちらが速いとも言えないが 61631 基本的に算術式で評価できるものは算術式で評価した方が速い様だ。 61632 61633 [修正2] 61634 61635 直ったと思ったら、今度は本来の目的の fi $(echo) をエラーにするという機能が駄目になった。 61636 nest-push しているので wtype が変わってしまい、エラーを設置する機会が失われている。 61637 また、今まで動いていた様に見えたのも nest-push して wtype=-1 になった事で、 61638 誤った条件判定によりエラーが設定されていただけの事であった。 61639 61640 nest-push があった場合には nest-push する前の wtype が必要になる。 61641 これは実は初めの wtype を覚えて置くだけで良いのかもしれない。 61642 61643 2017-11-15 61644 61645 * edit: echo !( !a ) で !a の直後で magic-space しても展開されない。 [保留] [#D0598] 61646 61647 現在の実装ではカーソル位置よりも前の部分に対して展開を試みる。 61648 しかし、どうやら "echo !( !a" だと構文エラーか何かで失敗する様だ。 61649 最後の位置までカーソルを持っていかないと展開されない。 61650 61651 元々の bash の実装ではどうなっていただろうか。 61652 echo !( !a の状態で SP をすると event not found のエラーになる。 61653 そして space も入力できない。これは不便だ。 61654 61655 また、!( !a ) の状態ならば magic-space すれば展開される。 61656 カーソル位置もちゃんとなっている。 61657 61658 echo !( !a) !a の状態で初めの !a の直後に magic-space を入れようとすると、 61659 履歴展開は両方共実行される。実行後のカーソルの位置は最後から四文字目。 61660 これは展開で挿入された文字列の中途なところである。 61661 つまり、実際に展開で挿入された文字列の位置ではなくて、 61662 展開前の最後尾からの位置を覚えておいて、展開後に覚えておいた最後尾からの位置に移動するだけの様だ。 61663 しかも、展開した後に空白を挿入するせいで、変なところに空白が挿入されている。 61664 Bash の magic-space の実装は微妙である。 61665 61666 その様に考えると現在の実装の方が妥当に思われる。 61667 因みに、全体に対して展開を実行して、 61668 それでいて、展開後の現在位置に対応する箇所を特定する方法はあるだろうか。 61669 うーん。難しい気がする。ならばわざわざ実装する必要もないのではないだろうか。 61670 61671 2017-11-15 61672 61673 * syntax: 以下はエラーにするべき。 [#D0597] 61674 if true; then true; fi <(echo) 61675 61676 おかしい。fi echo はちゃんと赤く着色されているが、どの時点で着色されているのか謎だ。 61677 調べてみると単語を読み取る時には赤くなっていない。 61678 これは考えてみれば単語が終わるまでは、fi の後に fi done などが来るかもしれないので、 61679 この時点では未だ構文エラーかどうか分からないので、妥当な処理である。 61680 しかし、実際に赤くなっているのは誰が管理しているのだろうか。 61681 61682 更に気付くことは fi echo$(echo) とすると赤くならないという事である。 61683 fi $(echo) も赤くならない。これは問題である。 61684 61685 これはプロセス置換に限った話ではなくて全般的な問題の様に思われる。 61686 さて、そもそも現在の着色は何処で行われているのかを特定する必要がある。 61687 どうも、文法的に着色されている訳ではなくて、後付で着色されている様だ。 61688 61689 うーん。実は CTX_CMDXE 及び CTX_CMDXD では取り敢えずエラーを設定して、 61690 word が終わる箇所でもし許容できるコマンド名になっていたら attr を設定する 61691 という方式で良いのではないだろうか。許容できるコマンド名は単純なので必ず同じステップ内のはずである。 61692 CTX_CMDXE CTX_CMDXD 以外にもあるかもしれない。 61693 これについては、後付で着色しているコードを観察すれば良い。 61694 所で、未だ後付で着色している部分の特定には至っていない。 61695 61696 →多分分かった。ble-highlight-layer:syntax/word/.update-attributes/.proc 61697 CTX_CMDXE 及び CTX_CMDXD では wtype に ATTR_ERR を設定しているのだ。 61698 そして wtype が ATTR_ERR ならば赤く色を付けるという様にしている。 61699 然しながら、この判定をしているのは $wtxt =~ $_ble_syntax_rex_simple_word の中なので、 61700 $(echo) などを含む単語についてはエラーの着色が起こらないのである。 61701 →では wtype に ATTR_ERR を設定しているのは何処だろう。 61702 ble-syntax:bash/ctx-command/check-word-end の中で 61703 _ble_syntax_bash_command_expect を参照している。 61704 この配列に正規表現が登録されている問、この正規表現に一致しない物について 61705 wtype=ATTR_ERR を設定している。 61706 61707 逆に言えば、この配列に登録されている様な文脈の場合には属性値を取り敢えず ATTR_ERR にしておいて、 61708 正しいと分かった時に改めて、期待される属性値を代入するという具合にするのが良い気がする。 61709 更によく見ると CTX_CMDXE CTX_CMDXC CTX_CMDXD で許容されるコマンドは何れもキーワードなので、 61710 改めて期待される属性値を代入しなくても正しい値で上書きされる様に見える。つまり、気にしなくて良い。 61711 61712 % と思ったが、属性値を ATTR_ERR にしようと思っても、 61713 % 実は属性値は ctx の値をコピーして設定する事になっているので、 61714 % 自由に設定できるようなものではない。 61715 % 特に単語の開始境界の位置で設定できる物という訳ではない。 61716 と思ったが、ctx の値をコピーして設定する所で wtype も参照して設定する事にした。動いている。 61717 61718 ところで、わざわざ wtype を設定して highlight で色を付けて貰うこともないのではないかとも思ったが、 61719 'echo' 等の様にして囲んだ場合には現状の方法だと対応しきれないので、 61720 やはり wtype によるエラー着色は必要である。そのままにする。 61721 61722 しかし、それでも未だ if true; then true; fi <(echo) はエラー着色が見えない。 61723 やはり全体をエラーの色で塗り潰したい物である。 61724 →単語を構成する要素は全て先頭にエラー色を上書きする事にした。動いている。 61725 多分問題も生じないであろう。 61726 61727 さて、改めて今まで調べて問題だったものについて確認する。何れも着色されている。OK 61728 正しい場合にはエラーの色は残っていない。OK 61729 61730 * resolved: 因みに、[[ echo ]] echo や (( echo )) echo に関しては 61731 構文的に誤っているということがすぐに分かるのにも拘らず、 61732 エラーの着色が為されていない。これも何故だろう…。 61733 _ble_syntax_attr にはちゃんと CTX_ARGI が設定されている。 61734 CTX_ARGX0 なのに ble-syntax:bash/ctx-command/.check-word-begin がちゃんと返していないのが悪い。 61735 しかしちゃんと返しているとしか思えない。と思って、呼び出し元を見たら、 61736 何故か unexpectedWbegin に値を設定するはずの所が壊れていた。 61737 どうやら色々試している内にここを壊してしまっていた様だ。 61738 これについては直った。 61739 61740 * fixed: 後、echo とした時、普通は後付の色で上書きされるために見えないが、 61741 その下にはコマンドの色がついているはずなのに黒である。これはどういう事か。 61742 _ble_syntax_attr[i]=ctx によって現在の ctx を代入している様にみえる。 61743 というか ble_debug の一番左の列に表示しているのが attr だった。 61744 これによるとちゃんと CTX_CMDI が設定されている。 61745 だとすれば、attr から色に変換する所で誤っているのか。 61746 別に bashrc で syntax_command の色設定を上書きしている訳でもない。 61747 何と色指定を誤っていた。元々 red となっていたのを brown に書き換えたのだったが、 61748 正しくは fg=red であるべきで、それを fg=brown に書き換えるべきだった。直した。 61749 61750 2017-11-14 61751 61752 * syntax: [[ a == b ]] などが誤って構文エラーになっている。 [#D0596] 61753 これはごくごく最近発生した問題のはずである。 61754 61755 直した。序に、[[ と ]] は今まで予約語色にしていたが、 61756 構文レベルで ATTR_DEL にする事にした。 61757 (今までは構文レベルで [[ を ATTR_DEL にしていたが、 61758 その後の単語の着色で予約語色になっていた。 61759 ]] はそれを見越して構文解析の時点で予約語色にしていた) 61760 61761 * syntax: - で始まる名前のコマンド・関数だと正しく着色されない。 [#D0595] 61762 これは type がコマンド名をオプションと勘違いしている為である。 61763 type を呼び出す時に -- を前置すれば良い。 61764 61765 * syntax: time の後に何もなくても文法的には正しい。 [#D0594] 61766 time -p の後に何もなくても文法的には正しい。 61767 61768 実は ! / time の直後は特殊な文脈になっている様だ。 61769 61770 以下はリダイレクトの文法の詳細について調べている時 (#D0591) に分かったこと。 61771 61772 | 実は ! 単体でも OK 61773 | while !; do break; done 61774 | これは直したのに直っていないと思ったら、 61775 | そもそもリダイレクトに関係ないので修正とは関係なかった。 61776 | 独立に修正する必要がある。 61777 | 61778 | 所が調べてみると ! ; echo これは文法エラーになる。不思議だ。 61779 61780 調べてみるとまたよく分からない規則がある様だ。 61781 61782 $ ! ; # OK 61783 $ time ; # OK 61784 $ ! ; echo # Error 何故? 61785 $ time ; echo # Error 何故? 61786 $ while ! ; do break; done # OK 61787 $ while time; do break; done # OK 61788 $ while false; do ! ; done # OK 61789 $ while false; do time ; done # OK 61790 61791 どうやら !, time 直後の ; の後は CTX_CMDXE になっている様だ。 61792 61793 2021-02-18 Note (#D1477): bash 4.4 で振る舞いが変更された。 61794 4.4 以降では time ; や ! ; の後は通常のコマンドも来る事ができる。 61795 61796 もう少し調べる。 61797 61798 $ time & # Error 61799 $ time && echo # Error (&& が来た時点で既にエラー) 61800 $ time || echo # Error 61801 $ time | echo # Error 61802 $ time |& echo # Error 61803 $ case a in (a) time ;; esac # Error 61804 $ case a in (a) time ;& esac # Error 61805 $ case a in (a) time ;;& esac # Error 61806 61807 つまり ; 以外が来るともう駄目ということである。 61808 さて、; 以外については現状の振る舞いと一致しているので、 61809 ; が来た時だけ特別扱いをすれば良い。 61810 61811 ! と time の後は、現在の枠組みでは文脈値として CTX_CMDX1 になっている。 61812 これは例えば else の時も同じである。試してみる。 61813 61814 $ if true; then true; else ; fi # Error 61815 $ if true; then true; time ; fi # OK 61816 $ if true; then true; ! ; fi # OK 61817 61818 やはり明確に !, time の直後だけ文脈が異なる。 61819 そして、! と time の直後はやはり類似の文脈の様だ。 61820 61821 % と思ったが、! に関しては寧ろ else と同じ? 61822 % 勘違いだった。構文エラーではなくて単に ! が実行されて終了ステータスが 1 になっただけだった。 61823 61824 取り敢えず CMD_CMDX1 を複製することにする。複製した。 61825 time ; 及び ! ; に対応した。 61826 次に行末での処理に対応する。改行のある時と、最後(文字列末端)のチェックを直す。 61827 多分、これで対応できた。 61828 61829 * syntax: 以下で ")" の位置で誤って構文エラーが報告されている。 [#D0593] 61830 61831 echo $({ time echo helo; }) 61832 echo $(while true; do break; done) 61833 61834 CTX_CMDXD の後にコマンドがなくて終了しても OK にする。 61835 61836 * syntax: 予約語と変数代入・リダイレクトの順番に関する修正 [#D0592] 61837 61838 というか time や ! 周りの文法が分からなくなってきた。試してみる。 61839 61840 * ok: 何と、以下の何れも文法的に正しい。 61841 今まで深く考えていなかった実装でそんなに間違っていはいなかった様だ。 61842 61843 $ time ! echo hello 61844 $ ! time echo hello 61845 $ ! time ! echo hello 61846 $ time time echo # 一個しか time を指定しなかったときと同じ 61847 $ ! ! echo 61848 $ ! ! ! echo # ちゃんと数に意味があって奇数個・偶数個で振る舞いが変わる 61849 61850 * fixed: 以下は time はコマンドとして実行される。! はコマンドが見つかりませんと出る。 61851 61852 $ > a.txt time echo 61853 $ > a.txt time -p echo 61854 $ a=b time echo 61855 $ > a.txt ! echo 61856 $ a=b ! echo 61857 61858 % これについては !, time は CTX_CMDXV 以外で有効ということにすれば良い。 61859 % 61860 % そう言えば他の特殊文脈での振る舞いはどうなのだろう。確かめる。 61861 % CTX_CMDXC の場合は time があると駄目である。! も駄目である。 61862 % CTX_CMDXE の場合は如何にもだめそうだが…一応試すと time も ! も駄目だった。 61863 % CTX_CMDXD の場合も試すと time も ! も駄目だった。 61864 % これらは元々エラーなので特別の対策はいらないだろう。 61865 % 特に ! や time を下手にコマンドとして取り扱うと、 61866 % それ以降に復号コマンドなどがある時に振る舞いがおかしくなるので、 61867 % これはそのまま通過するということで良い気がする。 61868 % 61869 % さて、どの様に対応したら良いだろうか。 61870 % 実際に '!', 'time' 等の判定をしているところを見ると、 61871 % ctx は既に CTX_CMDI になっているので元々の文脈値が分からない。 61872 % ここで、元々の文脈値を過去に遡って確認することは許されていただろうか。 61873 % 少なくとも直接に stat/attr 配列を参照して確認することは許されていない。 61874 % 部分更新の際にこれらの情報は書き換わってしまうからである。 61875 % | 或いは、必ず1回の step で '!' や 'time' の終端に達すると考えれば、 61876 % | 実は '!' や 'time' 以降の状態を参照しても良い気もするが、 61877 % | 原則を破ると汚くなってなんだかよく分からないので、できるだけこれはしない。 61878 % 61879 % では word の情報としてこれらは記録されていただろうか。うーん。 61880 % どうも wtype として記録されている気がする。 61881 % 調べてみると CTX_CMDX[CDE] に関しては実は既に wtype にそれが設定されていた。 61882 % しかし、それ以外の場合については wtype は word の中を解析する ctx (つまり CTX_CMDI) に統一されている。 61883 % これには意味はあっただろうか。取り敢えず一旦 wtype になったものが ctx になることはないだろう。 61884 % なので wtype で CTX_CMDI に特別な意味を持たせているものについてチェックすれば良い。 61885 % ble-syntax.sh で登場する CTX_CMDI について wtype に関係するものは以下の二箇所で出て来る。 61886 % 61887 % ble-syntax:bash/extract-command/.construct-proc 61888 % ble-highlight-layer:syntax/word/.update-attributes/.proc 61889 % 61890 % これらは何れも tree-enumerate の過程で呼び出される proc である。 61891 % という事は最終的に登録される wtype だけしか効かない筈である。 61892 % 途中で CTX_CMDXV などになっていても大丈夫のはず。 61893 61894 というか、今気づいたのだが、そもそも 61895 61896 $ a=b function hello [[ a ]] 61897 $ > a.txt function hello [[ a ]] 61898 61899 等は何れも function をコマンド名扱いしている。 61900 他のキーワードのチェックに現れるコマンドを全て確認したが、 61901 何れもコマンド扱いされるようになる様だ。 61902 61903 a うーん。新しい文脈値 CTX_CMDIV 的なものを導入する可能性も考えたが、 61904 其処まですることもない様な気がする。何より違いというのはここにしかない。 61905 61906 b したがって、CTX_CMDXC 等と同様に wtype に記録するのが良い気がする。 61907 61908 c というかそもそも解析中の wtype を参照する箇所は他にあるのだろうか。 61909 探してみた所見つからない。という事は、実は開始時の wtype をそのまま指定して、 61910 それから word-pop する直前で調整すれば良いだけなのではないだろうか。 61911 61912 word-push では単に wtype 変数に値を指定するだけなので気にしなくて良い。 61913 実際に tree に登録されるのは word-pop の時である。 61914 そして、既にそのことを意識して途中で wtype を書き換えるという事は行っている。 61915 但し、その wtype の書き換えの際には実際には元の wtype は参照していなくて、 61916 ctx に基いて新しい wtype を設定しているだけである。つまり、wtype は使われていない 61917 61918 うーん。念のため、以前実装した時にどうしてこの様にしたかを確認する。 61919 関係がありそうなのは #D0393 #D0382 #D0378 #D0372 #D0371 だが、 61920 何れにおいても現在の実装については議論されていない。 61921 _ble_syntax_bash_command_bwtype を弄っている commit を見てみると、以下の通り。 61922 61923 70e1e49d 2017-03-05 19:07:58 → これは #D0382 だろう。 61924 fdbfb399 2017-03-01 11:40:26 → これは #D0372 なのだろう。 61925 61926 結局そんなに分からない。恐らく元々 wtype=ctx としていたのを破壊しない様に修正した結果、 61927 現在のような形になったというだけで、これに対した意味は無いだろうと思われる。 61928 61929 [実装] 61930 61931 wtype には octx を設定する様にする事にした。 61932 check-word-end で _ble_syntax_bash_command_ewtype を使って変換してから word-pop する。 61933 取り敢えず分かっている範囲での動作に破壊が生じないことは確認する。 61934 61935 wtype が CTX_CMDXV だった時には予約語は解釈しない様にする。 61936 直してみたらエラーになった。うーん → 修正した。 61937 61938 * 変数代入とリダイレクトの後は予約語を解釈しないように変更したが、 61939 相変わらず予約語の色で着色されている。 61940 これはコマンドとしてマークされた予約語には現在予約語の色をつけている為である。 61941 しかし、思うに予約語はそもそもコマンドとしてマークする必要はないのではないか。 61942 61943 (ところで初めは以下のように書いていたが、実は予約語全般に当て嵌る話だった) 61944 61945 | 所で、現在の実装では '!' は何も着色していないが、 61946 | type -t '!' とすると keyword と出るので keyword 色にするべきでは。 61947 | もしくは、[[ 等と同様に太字にするか。性質を考えると time と同じにしたい。つまり青字。 61948 61949 コマンドとしてのマークをしないという事にした時にどの様な影響が出るかについて考える。 61950 先ず初めに extract-command が正しく働かなくなる。予約語の為の word type を用意するべきだろうか。 61951 61952 或いは、別の方法でコマンド着色の際に判定を行う。 61953 例えば、初めから attr に予約語の色が設定されている時には改めて着色は行わないなど。 61954 こちらの方が現実的な気がする。 61955 61956 さて、では予約語に対応する語がコマンドとして呼び出される時は、 61957 実際にはどのようにして色を決めれば良いのだろう。 61958 例えば type -tP time などとすればコマンドがあるかどうか分かる様だ。 61959 しかし、a=b time は関数でも良いようだ。なので、関数があるかどうかも調べなければならない。 61960 61961 そう言えば 'time' 等として呼び出す場合にも同じことが当てはまる。 61962 現在の実装では 'time' なども予約語として取り扱われて青くなったのだったろうか… 61963 と思ったら、'time' とした場合には正しく解決できている。これを参考にする必要がある。 61964 →これは ble-syntax/highlight/cmdtype2 の $type == $ATTR_CMD_KEYWORD 分岐で処理されていた。 61965 61966 [実装] 61967 61968 a 予約語の時は語の先頭の attr を書き換えれば良い…と思ったが、 61969 よく考えたら check-word-end に至った時点で既に先頭の attr は設定されている。 61970 この値を書き換える為には [[ で行っている様に、 61971 61972 ble-syntax/parse/touch-updated-attr "$wbeg" 61973 ((_ble_syntax_attr[wbeg]=ATTR_DEL)) 61974 61975 という様な事を明示する必要がある。 61976 61977 これだと解析の効率が下がるのではないかとも思ったが、 61978 よくよく考えてみるとそもそも予約語の様な単純な単語の場合には、 61979 必ず 1 回で解析が終了するので、これで効率が下がることはない。 61980 寧ろ、ble-syntax/parse/touch-updated-attr "$wbeg" をわざわざ呼び出す必要も、 61981 本当は無いのかもしれない。ただ、これはルールとして呼び出すようにしておく。 61982 61983 b wtype に記録された情報を用いる。 61984 61985 そう考えると寧ろ check-word-end の支配下にある 61986 word-pop で登録される情報を弄る方が良い気もしてくる。 61987 然し、改めて実装を見てみると word-pop を使うとしても 61988 現在のコードの流れでは word-cancel を実行してから、 61989 再度 word-pop をしなければならないという面倒なことになっている。 61990 61991 word-cancel はそれなりに面倒なことをしている。 61992 もしこの wtype を用いる方法を採用するとすれば、 61993 処理の流れを変えて word-cancel をしなくて済む様にしたい。 61994 61995 どちらの方が良いだろうか。 61996 61997 | extract-command の観点から考えてみる。 61998 | 61999 | | しかし、そうするとこれは extract-command に影響が出てくる。 62000 | | (所で、extract-command を使っている command-help の方はどうなのだろう。 62001 | | 例えば a=b function となっていた時、command-help の中からは 62002 | | それが予約語の function なのか、コマンドの function なのか判定ができない。 62003 | | command-help にも配慮した設計にするべきなのではないだろうか。 62004 | | と思ったが、(attr を用いる方法か wtype を用いる方法か) 何れの方法を用いたとしても、 62005 | | 現状の枠組みでは command-help に情報を伝えるのは難しい。 62006 | | 或いは、extract-command において単語開始位置の情報まで全て返すようにすれば、 62007 | | 後は attr/wtype に拘らず command-help 側で好きに調べることができる。 62008 | | もし wtype になっていれば extract-command を返す時に、 62009 | | 先頭の単語の種類も一緒に別の変数かなにかで返すことができる。 62010 | | しかし、現状の実装ではそれが予約語かそれ以外かの二択なので、 62011 | | わざわざ変数にして返す意味があるのかという疑問も生じる。 62012 | | 62013 | | 更に、よく考えてみると command-help だけでなく、 62014 | | complete を行う時にもそれがコマンドかどうかによって振る舞いは変えるべきなのではないか。 62015 | | と思ったが、complete の場合にはそもそも予約語に対して引数はないので、 62016 | | complete が呼ばれることもない気がする…いや、for 等の場合には complete が呼ばれる。 62017 | | もし complete で関数が登録されていればやはり extract-command を呼び出すのが良いだろう。 62018 | | しかし、この時には bash の補完関数の仕組みではそれが予約語かコマンドか判定する仕組みがないので、 62019 | | 結局、そのような情報を提供する意味がない。 62020 | 62021 | - command-help で表示するヘルプを選択するときには、何らかの方法で予約語かそうでないかを区別したい。 62022 | - Bash の補完関数の枠組みを模倣するときは予約語かそうでないかの区別はない。 62023 | 62024 | highlight の観点から改めて見てみる。 62025 | 62026 | wtype 及び attr は何れも簡単にアクセスできる物だろうか。 62027 | そもそも highlight は wtype を参照して着色する方法を選択している。 62028 | その場所は ble-highlight-layer:syntax/word/.update-attributes/.proc である。 62029 | 一応、この箇所で _ble_syntax_attr[wbeg] を参照すれば良いが、 62030 | やはり綺麗なのは別の wtype にする事の気がする。 62031 | 62032 | 改めて wtype CTX_CMDI を明示的に調べている部分を探す。 62033 | これは先程調べたものである。extract-command と highlight 以外では使っていない。 62034 | extract-command の wtype == CTX_CMDI を新しく追加した wtype にも対応するという風にするだけで良い。 62035 | 62036 | さて、wtype を追加するとしたらどの様な値にするべきだろうか。 62037 | a 一つの方法は新しい文脈値を作るというものだが、 62038 | 実のところ解析に関与していない文脈地は作りたくない。 62039 | b 或いは、既存の文脈値を流用する。しかし予約語に向きそうなものはない。 62040 | 一応 CTX_CMDXE や CTX_CMDXD は予約語しか次に受け付けないが、 62041 | これらは既に来る予約語名までの空白の色に同時になっている気がする。駄目。 62042 | c 或いは、ATTR_CMD_KEYWORD を用いる。 62043 | 現在の実装では ATTR_CMD_KEYWORD は CTX_* と重複しないようになっているので問題はないはず。 62044 | もし wtype の方法にするとしたら ATTR_CMD_KEYWORD を用いる。 62045 | 62046 | function の最後の文字のエラーの着色が透過するためには、 62047 | 予約語の時には敢えて単語の種類による着色を行わないという様にすれば良い気がするが、 62048 | その為には結局最初から _ble_syntax_attr を書き換えて置かなければならない。 62049 | 62050 | 或いは、function のエラー着色を今まで通りに上書きしても良いとしても、 62051 | 予約語について上から予約語色で塗るというのは、 62052 | わざわざ highlight の phase で実行しなくて良い気がする。 62053 | 色の管理が面倒になるので、寧ろ文法解釈の時点で分かる色・属性はそこで設定した方が良い。 62054 62055 [結論] _ble_syntax_attr[wbeg] を書き換える。 62056 62057 - wtype を用いて判定すると予約語の時に改めて着色する必要がある。 62058 予約語の色は構文解析の時点で分かっているので、改めて着色の判定をするのは無駄である。 62059 また孤立 function のエラーなど構文解析でのエラー着色が上書きされてしまう問題があった。 62060 これを解決する良い機会でもある。 62061 62062 - _ble_syntax_attr[wbeg] を書き換えると、一見、解析の効率が悪くなる様にも思われるが、 62063 実際には予約語は単純なので wbeg の位置は同じ解析ステップの範囲のはずなので気にしなくて良い。 62064 62065 この修正により以下の古い項目は解消した。 62066 62067 | 2015-08-15 62068 | 62069 | * ble-syntax.sh: `function' と入力した時に最後の n の部分にエラーを設定するが、 62070 | command 名としての着色の際に上書きされてしまっている。 62071 62072 * 2017-11-10 syntax: > a.txt ; echo が文法エラーとされているが、これは文法エラーではない。 [#D0591] 62073 62074 * fixed: 以下は本来文法的に正しい 62075 > a.txt; echo 62076 62077 他にも試してみると色々新しいことが分かった。 62078 以下は何れも文法的に正しい。 62079 62080 * fixed: 以下は本来文法的に正しい 62081 while > a.txt; do break; done 62082 →これは色々試してみた所、 62083 リダイレクトを挟むと CTX_CMDXV になるとすれば良さそうだ。 62084 リダイレクトの後に変数代入があってもいいし、 62085 変数代入と変数代入の間にリダイレクトがあっても良い。 62086 62087 以下は本来文法的に正しくない。 62088 62089 * fixed: 関数の本体の直前 62090 function hello () > a.txt ((a+=b)) # 駄目 62091 function hello () ((a+=b)) > a.txt # 備考: これは正しい 62092 →これは CTX_CMDXC ではリダイレクトは駄目ということにすれば良い 62093 62094 * fixed: fi などの直後にリダイレクトを挟んで fi などが来るとき 62095 if true; then if true; then echo hello; fi > a.txt fi # 駄目 62096 if true; then if true; then echo hello; fi fi # 備考: これは正しい 62097 →これは CTX_CMDXE でリダイレクトを挟むと CTX_ARGX0 になるとすれば良い。 62098 62099 2017-11-12 62100 62101 * encoding: input_encoding を切り替えた時ごみが残るのでは。 [#D0590] 62102 detach の時にもこれは処理するべき。 62103 ごみは flush するのかそれともそのまま消去するのか。 62104 ble-decode/unbind で消去してしまうのが良い気がする。 62105 62106 * encoding: この辺りで __ENCODING__ という部分を整理する。 [#D0589] 62107 62108 調べてみるともう2箇所しか残っていない。 62109 一箇所は ble-color.sh の ble-highlight-layer:plain/update/.getch で、 62110 これは C1 文字を M-^? の形の表示に変える為のものである。 62111 これは ble/util/s2c でコードに変換してから判定することにした。 62112 多少重くなるかもしれないが仕方がない。 62113 62114 ble/util/s2c は必ず Unicode の値になるのだろうか。 62115 現在の実装を調べてみると結局 builtin printf %d "'あ" を使っている。 62116 これは実際に試してみた所、eucJP でも 12354 という値を出力したので、 62117 最終的に Unicode に変換してから出力するようである。 62118 62119 | 疑問: ble/util/s2c の実装は本当に Unicode 値を得られているのだろうか? 62120 | [cf memo/D0589/D0589.test-printf-s2c.sh] 62121 | 62122 | eucJP で試す。_ble_bash>=40100 の実装は OK 62123 | builtin printf %d "'あ" はちゃんと unicode の値を返す。 62124 | 他の実装も結局同様に builtin printf を使っているので大丈夫のはずだ。 62125 62126 もう一つの __ENCODING__ は ble-edit/draw/trace に残っている。 62127 現在では LC_ALL=C ではなく LC_COLLATE=C にしているので、 62128 問題は起こりそうにないが念のため実験する。 62129 試してみた所 glob でも正規表現でも、 62130 ちゃんと LC_CTYPE に従った文字の単位で切って、 62131 その後で LC_COLLATE=C に従った比較になっている様だ。 62132 問題になることは無さそうに思う。 62133 [cf memo/D0589/D0589.test-lc_collate.sh] 62134 62135 ただ、比較をする上で直接 ST を正規表現に埋め込んでいた。 62136 これはソースコード上 UTF-8 で符号化されて埋め込まれている。 62137 UTF-8 でない環境で source ble.sh した時に問題になると思われるので、 62138 ble/util/c2s 156 で文字を取得するように変更する。 62139 62140 | 唯、気になるのは ST に対応する文字が存在しない環境で、 62141 | ble/util/c2s (もしくは printf -v var '\uXXXX') がどの様な結果を齎すかである。 62142 | [cf memo/D0589/D0589.test-printf-uXXXX.sh] 62143 | 62144 | 例えば空欄になるのか、或いは変な文字がそこに入るのか、変数に代入が行われないのか。 62145 | 手許の環境では ST のある文字コードしかないので取り敢えず別の文字を使う。 62146 | ここは周回積分記号 ∮ を用いることにする。U+222E である。 62147 | iconv -f UTF-8 -t EUC-JP <<< ∮dx とすると以下のエラーになる。 62148 | 62149 | iconv: illegal input sequence at position 0 62150 | 62151 | 従って、これは EUC-JP に対応するもののない文字である。 62152 | さて、実際に printf '\u222E' を試してみると 62153 | 何と '\u222E' という文字列がそのまま出てきた。 62154 | \u3042 (あ) はちゃんと ja_JP.eucJP でも変換されている。 62155 | と思ったら、実際に使っているのは $'\uXXXX' だった。 62156 | 改めて調べなおすと同じ振る舞いだった。'\u222E' という文字列になる。 62157 | 62158 | 所で、もう一つ気付いたことは $'\uXXXX' は、Bash が parse した時の文字コードで先に文字に変換されている。 62159 | 従って、eval で評価を遅延させる必要がある (これは実際に c2s でやっていることとも一致する)。 62160 62161 →対応する文字が存在しないときは '\uXXXX' の形になるので文字数が 2 文字以上なら失敗と見做せば良い。 62162 62163 % ところで周回積分記号の幅の計算が誤っているがこれはどうしてか。 62164 % どうも幅 1 と思っている様だ。手許の emacs では変なことは起こっていない。 62165 % そして現在の ble.sh は emacs のテーブルを元にしているはずなのだが。 62166 % →と思ったらこれは直したのだった。最新の ble.sh では変なことは起こらない。 62167 % ble.sh を編集しているシェルセッションが古いのがいけなかった。 62168 62169 他に動作に深く関わるもので Unicode の文字 (C0 GL でない文字) が直接埋め込まている箇所はあるだろうか。 62170 実のところ意味を持つのは C1 程度なので、C1 以外を埋め込む意味がないように思われる。 62171 あるとすれば(エラー)メッセージに日本語が含まれる場合だが、 62172 日本語のメッセージを出力する箇所はないはずだし、 62173 もし日本語メッセージが UTF-8 で出力されたとしても大きな問題には至らない筈である。 62174 ST (\u009C) と CSI (\u009B) は検索したが、今回対処したところ以外にはない。 62175 多分、他の文字も存在しない。OK 62176 62177 * ble_debug=1 で表示していた内容が :q で消去されない。 [#D0588] 62178 これは info の仕組みを用いて表示していたので、 62179 :q をする時に消去されるはずなのではないか。 62180 62181 というか、普通どおりに exit しても消去されない。 62182 と思ったが補完候補達は初期されている気がする。うーん。 62183 もしかして高さの計算を誤っている? 62184 62185 と思ったが mode 変更の際に info が変わる時には 62186 ちゃんと正しい高さだけ削除されている。 62187 62188 実装の方を観察してみる。 62189 ble/widget/vi-command:q は ble/widget/exit を呼び出している。 62190 ble/widget/exit は ble-edit/info/hide を呼び出している。 62191 もしかして hide した物が再度描画されてしまっている可能性? 62192 62193 と思ったが、再描画されるようなタイミングはなく exit している気がする。 62194 うーん。途中の出力の様子を見てみると何も出力されていない? 62195 直前の高さを確認してみたが _ble_form_window_height にはちゃんと高さが設定されている。 62196 そして hide の直後には高さが潰れている。 62197 62198 うーん。どうも調べてみると ^O しか出力されていない様だ。 62199 と思ったが、どうやら alias less で確認していたために 62200 エスケープシーケンスが表示されていなかったようだ。 62201 ちゃんと確認したら消去のシーケンスは _ble_util_buffer に入っていることは分かった。 62202 ESC[m^OESC[1B^MESC[8M となっている。SGR() ^O CUD(1) DL(8) である。 62203 では、何故実際に消去されていないのだろうか。 62204 flush を挟んで見る。しかしながら消去できていない…。どういうことだろうか。 62205 あれ、もしかして高さの計算を間違えている? と思ったがそんな事もない。 62206 62207 うーん。おかしい。もしかして render の中で再描画されている? 62208 →そのようだ…。高さが復元している…。 62209 あ…分かった。textarea#render が中で syntax を呼び出して、 62210 syntax は ble_debug=1 の時中で info を呼び出すのだった。 62211 62212 ble/util/hide の方を後にしたら収まった。 62213 62214 * ble_debug=1 で表示される内容の _ble_highlight_layer_disabled_buff [#D0587] 62215 の行が前の行にくっついている。 62216 これは ble/util/assign の実装を変更して行末の改行を除くようにしたのが原因だった。直した。 62217 62218 改めて ble/util/assign の様子を観察してみるとどうも最後の改行が除かれている 62219 前提のコードが多いような気がする。今まで動いていたのはなんだったのか不思議である。 62220 一応動作を統一するために bash-4.0 未満でも最後の改行は除くようにした。 62221 62222 * bind: bleopt input_encoding=C は動かない気がする。 [#D0586] 62223 62224 素直な bind ではちゃんと入力を読み取れないので UTF-8 62225 では文字を 2 byte 表現に一旦変換してから読み取るなどの工夫をしている。 62226 62227 これに正しく対応するためには、C であっても特定のシーケンスについて特別な意味を持たせる必要があるのではないか。 62228 そうすると、例え C であっても C1 の領域の何れかの文字を生贄にするしかない。 62229 因みに vim では right を <80>kr という表現でキーボードマクロに記録する。 62230 これを考えると <80>? を特別な表現に割り当てれば良い気がする。 62231 62232 % とここまで書いて思ったが、実は現在の設計は文字符号化方式の部分と、 62233 % bind の部分が癒着しているのがいけないのではないか。 62234 % つまり、ble-decode/.hook から直接 ble-decode-byte を呼び出しているが 62235 % その手前で特別表現からバイト値に変換する段があっても良いのではないかという事である。 62236 % 62237 % そうすれば bind の文字符号化方式依存の部分は解消するし、 62238 % 場合によっては孤立 ESC を受け取るために使った 62239 % <wait> などの仕組みについてももっと綺麗に解決できるかもしれない。 62240 % 62241 % 取り敢えず、孤立 ESC の細かい取り扱いは抜きにしても、 62242 % 文字符号化部分とバイト受信部分を明確に分離する。 62243 % 特別なバイトを受け取る時に使用するシーケンスとして何を使うか考える必要がある。 62244 % これには UTF-8 で決して使われないバイトを使うのが良い気がする。 62245 % 勿論、完全に文字符号化部分と分離するのであるから、UTF-8 で使われるバイトを用いても良い。 62246 % 然し、多くの場合 UTF-8 で使われることを考えると効率の観点などから考えて、 62247 % やはり UTF-8 では来ない様なバイト値で処理をするのが良い様に思われる。 62248 % 62249 % 先ず初めにどのバイトを用いるのかを決定する。 62250 % UTF-8 で使われないバイトは \xFF \xFE と、 62251 % 更に不正な表現の先頭バイトになる \xC0 と \xC1 である。 62252 % 実は現在の実装では \xC0? (不正な 2 バイト表現) に置き換えているので、 62253 % \xC0 を特別なバイトとして扱う事にすれば bind.sh の変更を最小限にできる。 62254 % 0xC0 を特別なバイトとして採用する事にした。 62255 % 62256 % 後は、0xC0 自身をどう表現するかである。 62257 % 一つの方法は \xC0\xC0 とするものである。或いは \xC0\xC1 とする。 62258 % 混乱を防ぐ為には \xC0\xC0 は避けた方が良い。\xC0\xC1 とすると、 62259 % 仮に \xC1 を受け取りたい時との混乱を避けられないのではないかという懸念があるが、 62260 % 実の所それは例えば C-@ を受け取るのに \xC0\x80 を使う時に \x80 で混乱が置きないかと心配するのと同じである。 62261 % 寧ろ、\xC1 は UTF-8 として不正な値であるので、寧ろ受信される頻度は殆どないと考えて良い。 62262 % ここでは \xC0 は \xC0\xC1 として受け取る事にする。 62263 % \xC0 については特に問題も起きそうにないので一旦 bind '"\xC0": "\xC0\xC1"' と置き直す必要もない。 62264 % というか、その様な置き換えをしてしまうと無限ループになってしまうので駄目だ。 62265 % 所で…現在 "\C-@": "\xC0\x80" 及び "\C-[": "\xC0\x9B" で置き換えているが、 62266 % これらは最終的に \xC0 \x80 として受信される。だとすれば、 62267 % この \xC0 と本来の \xC0 はどの様にして区別するのだろうか。 62268 % 62269 % ここで何故現在のような実装になっているかを思い出す。 62270 % その文字符号化方式で送られてこないような符号に変換する必要があったのだ。 62271 % そして UTF-8 の場合にはたまたまそれぞれのバイトに対する 62272 % 多バイト表現があったので、それを使うことができたのである。 62273 % 62274 % しかし、本当にそうしなければならないのかについて考える。 62275 % 先ず、\xC0 を使って表現すると決めた時点で、 62276 % \xC0 自身を区別して受信する方法が必要になる。 62277 % しかし "\xC0": "\xC0\xC1" などのようにすると無限ループになるし、 62278 % 更に、これだと "\x1B": "\xC0\x9B" なども "\xC0" に突入してしまう。 62279 % "\xC0\xC1" にも同時に bind -x する事にすると単体の 62280 % \xC0 が来た時に timeout を待つことになる。 62281 % 62282 % やはり符号化の "穴" を突くしか無いのだろうか。 62283 % そうすると結局また符号化方式依存になってしまう。 62284 % 62285 % 或いは制御文字は恐らくどの (現実的な) 文字符号化方式でもあるだろうと考えれば 62286 % (そうでなければ C-@ ~ C-_ の表現が普通と異なってしまい大変だ)、 62287 % 制御文字のどれかを特別な文字として組み合わせで受信することができる。 62288 % しかし、これもその制御文字に対する timeout が発生することになる。 62289 % 62290 % 勝手に keymap-timeout を変更すると、それはそれでキーシーケンスが 62291 % 認識されなかったり、途中の timeout によって文字が連なって来た時に混乱が生じたりする。 62292 % なので keymap-timeout はそのままにしておく。すると 300ms の遅延が生じる。 62293 % 結局、既存の文字に割り当てる時と同様に問題になる。 62294 % 特に制御文字は ASCII にないような変な文字に比べて入力する機会が多いし、 62295 % 結果として大きな変化を齎す物もあるから遅延があるのは通常文字に増して問題がある気がする。 62296 62297 結局、Bash のキーボードマクロが反復して適用されることにより、 62298 1対1の対応付を作ることが難しい。従って、遅延などが起きない様にしようと思うと、 62299 文字符号化方式に依存して使われていないコードポイントを使用するしかない。 62300 62301 * しかし、やはりできそうな気がしてくる。本当に不可能なのだろうか。 62302 62303 | 先ず前提として、或る文字を直接受信できないときに、 62304 | bind '"\x1B": "\xC0\x9B"' などの様にして別のシーケンスにして受信できる。 62305 | この時、受信できないバイト "\x1B" は当然代替シーケンスには含まれない。 62306 | 62307 | 問題は以下の様に要約できる。 62308 | 62309 | 1 256 種類のバイトを 254 種類のバイトで符号化する方法を作る。 62310 | 2 この符号に対して再び符号化を適用しても不変である。 62311 | 62312 | 254 種類というのは、直接受信できないバイトが 2 種類存在するという前提である。 62313 | この時 bind -x で受信するためには残りの 254 種類のバイトで行わなければならない。 62314 | 要求 2 は、bind '"\xC0": "\xC0\x9B"' に対して反復して変換が試みられる実情を反映する。 62315 | この条件が満たされないと無限ループに陥る。 62316 | 62317 | この様な符号化は不可能な気がする。 62318 | もう少し真面目に考える。とにかく鍵となるのは直接受信できないバイト 62319 | B1, B2 を表現するために使われるシーケンスを構成するバイトである。 62320 | 特に Encode(B1) の先頭文字を B3 ということにする。 62321 | この時、曖昧でないためには B3 自体も符号化しなければならない。 62322 | 無限ループに陥らない為には B3 は B1-B3 以外の文字で表さなければならない。 62323 | これを繰り返すと最終的に文字がなくなる。よって不可能だ。 62324 | 62325 | これを克服するには少なくとも条件を緩くしなければならない。 62326 | 例えば bind -x '"\xC0\xC0": hoge' 等のようにする。 62327 | \xC0 は単体で受信されることはなくて必ず二文字に増やしてから受信するのだとすれば、 62328 | これで遅延が生じることはないように思われると思ったが… 62329 | 62330 | 1 \xC0 単体で受信した時に次の文字が来ないか待つのでここで timeout 分遅延する 62331 | 2 更に、たまたま本当の入力に \xC0\xC0 の様な並びがあるときに 62332 | それが別のバイトに化けてしまう。 62333 62334 やはり文字符号化方式の穴を使わずに 62335 完全な読み取りを実現することは不可能であると判断する。 62336 62337 (全て Bash の bind で直接受信できないバイトが存在するのが悪いのだが) 62338 62339 * さて、この時 input_encoding=C については全ての文字が意味を持つので、 62340 穴など存在しない様に思われる。何れかのバイトを犠牲にするしかない。 62341 例えば C1 制御文字の何れかを犠牲にするのが一番影響が小さいだろう。 62342 C1 制御文字をコマンドの文字列を構成する文字の一つとして使いたい時は問題だが、 62343 その様なケースは限られているので仕方がない。 62344 62345 一番影響が少ないと思われるのは、元からシーケンスの一部として使われる様な文字である。 62346 例えば ESC がそれだが、これが丁度 Bash では直接受信できない文字である。 62347 次に CSI などがある。他に DCS SOS OSC PM APC 等がある。 62348 DLE (C-p) は実際に使われるので駄目。まあ CSI を使って置くのが妥当であろう。 62349 62350 さて CSI を犠牲にすると言えば、どの様にするのが良いだろう。 62351 実際に 8 bit CSI シーケンスが送られてきた時と干渉しないためには、 62352 これ自身も CSI シーケンスになる様に構成するのが良い。 62353 62354 | a 2文字で表現する案 62355 | 62356 | また CSI は、もし CSI シーケンスを処理するのだとしたら、 62357 | 結局何れにしても 2 文字目以降を待つ必要があるので都合が良い。 62358 | private CSI を使うことにする。特に、端末制御用のシーケンスは 62359 | 逆に端末から送られてくることは無さそうなので、それが良い。 62360 | 下手に使われていない private CSI は端末によっては拡張で対応している可能性がある。 62361 | 62362 | 然し、そのように考えてみると実は private CSI ではなくて ANSI CSI seq の方が良いかもしれない。 62363 | と思ったが CUU, CUD, CUF, CUB などはカーソルキーで使われているし、際どい。 62364 | もしかすると端末によってはその他のキーについても ANSI CSI seq と同じものを使ってくるかもしれない。 62365 | しかしその危険性は private CSI の方が高いような気もする。結局 private/ansi は当てにならないので 62366 | 実際の実装を確認するしか無い様に思われる。vt100 の function key f1-f10 で ESC O ? が使われている。 62367 | ? には P Q R S t u v l w x が使われている。これらは避ける。 62368 | 62369 | しかし、現在では CSI による制御シーケンスは使われず、 62370 | 専ら ESC [ による 7 bit の制御シーケンスが使われる。 62371 | 従って、そんなに気にする必要もないのかもしれない。 62372 | 62373 | b 或いは 2 文字でなくても良い。 62374 | <csi>27;1;2047~ などとしてこれに対して bind -x しまう手もある。 62375 | しかしこの方法で問題が生じないかは疑問である。 62376 | 62377 | と思ったが、bind -x で 2 文字以上に bind できるのは 62378 | bash-4.3 以降なのでこれは駄目である。 62379 | 62380 | c うーん。或いはそもそも CSI シーケンスの形をしていなくても良いのでは。 62381 | CSI シーケンスとして不正なものに割り当てるのが良い。 62382 62383 ここは c を採用する事にした。 62384 62385 * 次に bind を符号化方式依存にするのであるから、 62386 bind.sh の方も符号化方式に依存して切り替える様にするべきなのではないだろうか。 62387 62388 一つの方法は符号化方式毎に generate-binder を設計するというものである。 62389 もう一つの方法は、現在の UTF-8 の generate-binder を元にして、 62390 各符号化方式毎に後付の補正を行うという方法である。 62391 各符号化方式毎の後付の補正にする方が管理が楽であるように思う。 62392 何より新しい符号化方式に対応する時のコストが小さくて済む。 62393 62394 取り敢えず現在の UTF-8 用の bind の整理を行う。 62395 #D0583 で C-x について単純化できないか考えたができなそうだ。 62396 #D0584 で ESC ESC について単純化を考える。これは現在の枠組みでは不要だった。 62397 62398 現在の UTF-8 用の bind で UTF-8 依存なのは以下の物である。 62399 bind の設定に依っては変わるかもしれないが気にしないことにする。 62400 62401 ble-decode/generate-binder/bind-s '"\C-@":"\xC0\x80"' 62402 ble-decode/generate-binder/bind-s '"\e":"\xDF\xBF"' 62403 ble-decode/generate-binder/bind-s '"\e'"$ret"'":"\xC0\x9B'"$ret"'"' 62404 62405 [実装1] ble-decode-attach/ble-decode-detach で符号化方式依存の物にする。 62406 62407 % bind 修正用の関数を定義した。 62408 % ble/encoding:C/rebind 及び ble/encoding:C/unbind である。 62409 % 更にそれに応じて ble-decode-char+C も修正した。 62410 % isolated ESC にも対応している。しかしその前に isolated ESC が UTF-8 でも動作することを確かめたい。 62411 % 62412 % 同時に ble/encoding:UTF-8/rebind 及び ble/encoding:UTF-8/unbind も用意する。 62413 % 62414 % 更にこの rebind, unbind を適切なタイミングで呼び出す様にする必要がある。 62415 62416 と思ったがこの ble/encoding:UTF-8/rebind の時間計測を行うと存外に遅い。 62417 42ms かかっている。bind のキャシュを source するのにかかる時間が 19ms である事を考えると遅い。 62418 やはり encoding 毎の bind キャッシュを考えるべきだろうか。やはりそうする。 62419 62420 取り敢えず対応した。動いている。意外と変なことも起こらず普通に動いている。 62421 所で、やはり UTF-8 の binder を上書きするようにしている為に、source には多少時間がかかる。 62422 元々 18ms だったのが 26ms に増えている。8ms の増加である。 62423 まあ、UTF-8 でない変な文字コードを用いることの代償としてはそんなに大きくないので気にしない。 62424 62425 ところで思ったのだけれど bind のキャッシュを生成するときに 62426 bind.sh のタイムスタンプは見ているが、ble/encoding:C/generate-binder のタイムスタンプは分からない。 62427 新しい符号化方式に対応する時には、このタイムスタンプも確認する必要がある。 62428 これについてはメモに記録することにする。 62429 62430 [実装2] 動的に符号化方式を切り替えるときについて対応する。 62431 62432 新しく ble-decode/bind 及び ble-decode/unbind を作成した。 62433 62434 今回の改修で memo.txt の冒頭にある文字コード対応についての以下の記述は古くなったので更新した。 62435 62436 | ble-decode.sh (function .ble-decode-bind): 62437 | bash-3 で "ESC [" を bind する為に ESC [ を 62438 | utf-8 の非正規な符号 "\xC0\x9B[" に変換している。 62439 | bash-4.3 で "C-@" を bind する為に \C-@ を 62440 | utf-8 の非正規な符号 "\xC0\x80" に変換している。 62441 | 62442 | UTF-8 以外の文字コードを使う場合には 62443 | これらのバイト列を特別に認識する様にするか、 62444 | 別のバイト列を指定する必要がある。 62445 | (これらは bind にハードコードされているが、 62446 | 外部から指定できる様に変更する必要がある。) 62447 62448 * decode: <C-q><C-[> とすると ^[[27;5;91~ が入力される。 [#D0585] 62449 62450 これは単体の ESC を ESC[27;5;91~ に翻訳し、 62451 何かに前置されてやってくる ESC を ESC で受信しているのが原因。 62452 62453 <C-q> の引数として一文字読み取るのに使うためには、 62454 寧ろ単体の ESC を ESC として読み取って、 62455 Meta と解釈されるものを別の文字として受信するべきなのではないか? 62456 62457 しかし、そうすると今度は <C-q><left> の方がより変な入力になってしまう。 62458 現状では ^[[C が入力されるがこれが ^[[27;5;91~[C などになる。 62459 どちらでも期待通りに入力するためには bind/decode の側で工夫しなければならない。 62460 62461 | a 例えば同一の文字として解釈されるが内部的な表現の異なる UTF-8 62462 | (要するに不正な UTF-8 表現) を使って両者を区別する方法。 62463 | しかし、この違いは ble-decode-char まで来た時に吸収されているので、 62464 | 区別することはできない。 62465 | 62466 | 区別しようと思ったら ble-decode-byte:UTF-8 の中を弄るか、 62467 | 或いは、不正な UTF-8 表現に対して ble_decode_Erro フラグを立てて、 62468 | それの有無で ESC の種類を特定するという方法がある。 62469 | しかし、現状では ESC の受信には常に不正表現を使っているので、 62470 | ble_decode_Erro フラグをつけるとすれば常につける事になるので良くない。 62471 | 62472 | b もう一つの方法は、ble/util/is-stdin-ready を修正して、 62473 | ble-decode-byte 及び ble-decode-char で処理中の文字が残っているかどうかで、 62474 | それが孤立 ESC か続きのある ESC かを判定するという方法がある。 62475 | 62476 | こちらの方が良さそうだ。問題点としては何があるだろうか。 62477 | 例えば、キーボードマクロに登録されたものを再生する時は、 62478 | 元々孤立 ESC だったものも Meta になってしまうという問題がある。 62479 | と思ったが、これについては記録する時に ^[[27;5;91~ に変換すれば良い。 62480 | と持ったが、<C-q><C-[> として記録する時にはどうするのだろう…。 62481 | 62482 | c 或いは、孤立 ESC の時には、ESC に続いて 62483 | 無視される文字 <wait> を読ませるという手もある。 62484 | つまり、ESC は取り敢えずは Meta として読ませて置いて、 62485 | Meta が設定されている時に <wait> 文字が来たら、 62486 | それを C-[ として ble-decode-key に伝達する。 62487 | 62488 | 何もない時に <wait> が来たら無視する。 62489 | (これは <C-q><C-[> によって先頭の ESC が横取りされた時などに発生しうる。) 62490 | 62491 | キーボードマクロに登録する時には、<wait> 文字も含めるようにすれば良い。 62492 | p 等でレジスタの中身を表示するとそこに文字があることが見えてしまうが、仕方がない。 62493 | 62494 | さて。問題はどの文字を <wait> として採用するかである。 62495 | a C0 の文字でそういう意味を持ちそうな文字はありそうだが、 62496 | 実のところこれらは C-? としての意味を持つので、他の意味には使えない。 62497 | 例えば C-@ や DEL は元々は通信では無視されるものだったが、今では意味を持つ。 62498 | b C1 の文字についてはどうだろうか。これはキーボードから直接入力することはない。 62499 | (M-C-? で入力できる端末もあるかもしれないが、まあ ESC C-? で送ってもらうべきである) 62500 | しかし、現在の実装ではコピーペーストなどによって、 62501 | 実際に self-insert で編集文字列の一部として入力可能である。 62502 | この動作を破壊するのも難がある。編集文字列の一部になりえないのは C-@ のみであるが、 62503 | これは文字列として入力されることはなく特別な操作に使われる。 62504 | c Unicode の定義されていない文字を用いるというのが無難そうである。 62505 | Unicode の文字を使用すると他の符号化方式に対応した時に問題になるが、 62506 | 他の符号化方式を使うときはその符号化方式で使われていない code point を使うことにすれば良い。 62507 | 62508 | 現状で C0 も GL も <wait> には使えないとなれば 62509 | 結局文字符号化方式によって大きく意味が異なる C1 か GR の領域を使わざるを得ないので、 62510 | このように文字コード毎に特別な文字を確保するということは不可避である。 62511 | 62512 | ただ文字符号化方式が C の時に限れば何処にも特殊な文字を置く場所がないので、 62513 | この問題は不可避である。というかよく考えたら、現状で既に文字符号化方式 C は壊れているのではないか。 62514 | →これは別項目で議論することにする #D0586 62515 | 62516 | https://ja.wikipedia.org/wiki/Unicode%E4%B8%80%E8%A6%A7_0000-0FFF を見ると、 62517 | 未使用は結構あるようだが不使用ではない。つまり、将来的に何か文字が割り当てられるかもしれない。 62518 | 不使用の文字はずっと後ろの方にありそうである。 62519 | 一方で、特別な文字については余り沢山の文字を消費したくない。 62520 | UTF-8 で 2 byte に収まるのは 0-800 の範囲である。7FF が良さそうだ。 62521 | 62522 | d 或いは Unicode の場合には UTF-8 不正表現の内のどれかを特別に wait に割り当てても良い。 62523 | 例えば 0 (NUL) の 2 byte 表現はどうだろうか…と思ったら既に NUL を受信するのにその対処が必要だった。 62524 | 62525 | d 逆も考えうるかもしれない。つまり、孤立でない ESC の時は、その直後に <meta> の文字を挟む様にする。 62526 | (vi-mode の) キーボードマクロで記録する時には常に CSI 27 ~ に M-* も含めてしまう様にする。 62527 | 62528 | e うーん。孤立 ESC かどうかを判定してキーの組み立てに影響を与えるのは ble-decode-char の中である。 62529 | これは文字符号化の復号を行う ble-decode-byte よりも後段になる。 62530 | という事は、ble-decode-byte を貫通して Meta の情報を伝達する仕組みは何れにしても必要である。 62531 | 或いは、実は Meta の時には ble-decode-byte をスキップして直接 ble-decode-char に対して、 62532 | 特殊な文字を送り込むという手管も考えられる。そうすれば、文字符号化方式と直交させることができる。 62533 | その折にはそもそも ESC <meta> などという 2 バイトの組み合わせにする必要はなくて、 62534 | 単に <meta> を ble-decode-char に送りつければ良い。 62535 | 更に、ble-decode-char に渡される文字は既に Unicode になっている筈なので、 62536 | 文字符号化方式毎に <meta> のために使う特別な文字を割り当てなくてもよい。 62537 62538 #D0586 で議論されている方法を用いて、上記の e の方式で行くことにする。 62539 62540 % - 孤立 ESC はそのまま ble-decode-byte に入っていく。 62541 % 文字符号化方式が ESC を特別扱いしなければ、 62542 % これはそのまま ble-decode-char に入っていく。 62543 % ble-decode-char では ESC は即座に key C-[ に変換し、 62544 % キーシーケンスの一部になることは防ぐ。 62545 % 但し _ble_decode_char__hook が設定されている時は ESC として処理する。 62546 % 62547 % - ESC ? として受信した場合は <meta> を ble-decode-char に流し込む。 62548 % 或いは、そもそも meta という文字を定義しなくて 62549 % 単に ble-decode-char/set-meta 的な関数で良い。 62550 % 但し _ble_decode_char__hook が設定されている時は ESC として処理する。 62551 % 62552 % 問題となるのは文字を構成するバイトの途中で ESC が現れた時である。 62553 % その様な文字符号化方式は (少なくとも現実的なものでは) 存在しなそうだが…。 62554 % 62555 % と思ったが、そもそも iso-2022-jp などでは文字コードの制御に ESC を用いるので、 62556 % 孤立 ESC でなかったからと言って処理をスキップすることは不可能である。 62557 % 寧ろ孤立 ESC の時こそ ble-decode-byte をスキップするべきである。 62558 62559 という訳で以下のように手順を修正する。 62560 62561 - 孤立 ESC は文字復号には参加せず ble-decode-char に 62562 <isolated-esc> として入っていく。 62563 _ble_decode_char__hook が設定されているとき、 62564 <isolated-esc> は ESC (^[) に変換してから呼び出す。 62565 それ以外の時はそのまま C-[ になって出ていく。 62566 - 先行 ESC は文字復号に参加する。例えば UTF-8 などの場合には、 62567 そのまま貫通して ble-decode-char に渡る。 62568 62569 vi-mode のキーボードマクロに記録する時は、 62570 isolated-esc をどうにかしなければならない。 62571 62572 | a 或いは再生時に esc を isolated-esc に変換するか。 62573 | 62574 | % と思ったが、それだと通常のキーシーケンスも isolated-esc になってしまう。 62575 | % 通常のキーシーケンスは ESC [ ではなくて CSI で始まる様にするという手もあるが、 62576 | % そうすると今度は ble-bind -c で ESC 云々 として登録された物が処理されない。 62577 | % と思ったが、よく考えたらそれは気にしなくても良い。 62578 | % 結局キーボードマクロに記録されるのは文字ではなくてキーであり、 62579 | % キーは必ず CSI 27 ~ で記録されるので ble-bind -c の設定には関係ない。 62580 | 62581 | キーは CSI 27 ~ で記録するようにすれば問題ない。 62582 | 後、これに対応するためには decode で CSI に対応しなければならない。 62583 | 62584 | b 或いは、全て先行 ESC と解釈して実行してしまっても良い? 62585 | と思ったがやはり不便である。<wait> 的な文字をやはり実装するべきか。 62586 | しかし、その様な物を実装するくらいであれば、 62587 | 初めから <isolated-esc> としてレジスタに記録すれば良いのである。 62588 62589 上記 a の方法を採用する。 62590 vi のキーボードマクロでは全て isolated-esc として ble-decode-char に送る。 62591 また decode は CSI 27 ~ に対応する。 62592 62593 % [孤立 ESC を ESC とし、先行 ESC を <meta> として ble-decode-char に入れる案] 62594 % 62595 % ここまでの案では孤立 ESC は <isolated-esc> として ble-decode-char に入り、 62596 % 先行 ESC についてはそのまま ble-decode-char に入るという話だった。 62597 % しかし逆にするという手もあるのではないか。 62598 % そうすれば vi のキーボードマクロでの実装も自然になる。 62599 % 62600 % この時孤立 ESC はそのまま ESC として ble-decode-char に入り、 62601 % キーシーケンスの一部とはなりえない。 62602 % 一方で、先行 ESC は <meta> として ble-decode-char に入り、 62603 % キーシーケンスの一部になりえる。 62604 % キーシーケンスの一部ではないときは単に C-[ になる。 62605 % 62606 % と思ったが、ユーザが ble-decode-char 27 を呼び出した時に、 62607 % それが孤立 ESC として取り扱われ決して先行 ESC として取り扱われないのは変だ。 62608 % やはり先行 ESC として取り扱う方が自然なのではないのか。 62609 % 或いは、ble-decode-char に同時に複数の引数を指定することがあれば、 62610 % 一番最後の引数の 27 でなければ先行 ESC として取り扱うという手もある。 62611 % x しかしそれだと結局キーボードマクロの孤立 ESC を孤立 ESC として取り扱わせるために特別の処理が必要なので、 62612 % 孤立 ESC の方を <isolated-esc> として取り扱う手法に対する利点がなくなる。 62613 % x また、ble-decode-char を連ねて書く場合とそうでない場合で振る舞いが異なるのも混乱の元である。 62614 62615 →やはり孤立 ESC を <isolated-esc> として取り扱う方が自然である。 62616 62617 [実装1] 孤立 ESC を 0x7FF にする 62618 62619 取り敢えずキーボードマクロの事はさておき、 62620 孤立 ESC の受信方法を変更することにした。 62621 孤立 ESC は U+07FF で表すことにする。ble-decode-char で適切に対応する。 62622 62623 % と思ったら全く入力できなくなっている…。 62624 % bind -s を見てみると登録されているべきものが登録されていない。 62625 % と思ったらテスト用の設定がそのままになっていた。戻した。 62626 62627 今度は C-[ は動くが、M-a や M-i を押した時の動きが変だ。 62628 うーん。今までは動いたはずである。例えば M-c は動いていた。 62629 bind -s の違いは \e を何に翻訳するかが異なるだけである。 62630 bind -X の違いはなかった。だとすると ble-decode の方の問題だろうか。 62631 → keylog で確認してみた所、何と ESC c a が M-a ESC a に翻訳されている。 62632 これは一体どういうことだろう。最後の ESC a は vi_imap/__default__ による物だろう。 62633 だとすると ESC c を処理する時に c が消えてしまっているのが問題だ。 62634 連続してきた文字の処理ができていない? と思ったが矢印などは処理できている。 62635 62636 と思ったら while (($#)) を for char に書き換えたのが駄目だった。 62637 ループの途中で set -- "${rest[@]}" "$@" などとしている為である。 62638 取り敢えず動くということを確認した。 62639 62640 また <C-q><C-[> がちゃんと ^[ の入力になるということを確かめた。 62641 62642 [実装2] 次にキーボードマクロの為 CSI シーケンスを解釈する様にする。 62643 62644 対応した。簡単だった。多分、これで大丈夫。 62645 62646 今まで CSI に対応していなかった理由を探したが特に書かれていなかった。 62647 現在の CSI シーケンス抽出の仕組みを整える前は、 62648 CSI まで全て cmap に登録すると大変になるという理由で対応していなかった。 62649 現在では CSI シーケンスに対応しないという理由はない。 62650 ble-decode-char の中での処理なので UTF-8 を構成するバイトの CSI と干渉するという事もない。 62651 多分、大丈夫である。 62652 62653 [実装3] vi のキーボードマクロに登録する時は CSI を用いるの事。 62654 62655 対応した。同時に C-[ は ESC として記録する。 62656 再生時には ESC は ble_decode_IsolatedESC に変換する。 62657 62658 * bind: ESC ESC for bash-4.1/4.2 は不要なのでは? [#D0584] 62659 62660 これは #D0586 の整理の一環である。 62661 62662 過去に bash-4.1, 4.2 の ESC ESC で問題が生じていた。 62663 これは元々 #D0055 で議論されている。 62664 62665 然し、その後で ESC の方式を切り替えた。 62666 もしかすると、今となってはこの対策も不要になっているのでは? 62667 うーん。これも今は再現しない。 62668 62669 再現することはできなかったが、実際の実装を見てみると、 62670 bind '"\e\e": "..."' に移しているのだから、 62671 現状の ESC の読み取りの方法と同様である。 62672 従って、特別にこの方法を取る必要性はない。 62673 現在の方法を利用している際には有効にならないように修正した。 62674 62675 * bind: C-x の workaround を別の方式に切り替える [却下] [#D0583] 62676 62677 これは #D0586 の整理の一環である。 62678 62679 この辺りで既存の UTF-8 用の binder について整理が必要に思われる。 62680 観察していて気付いたのは、C-x を捕まえる為に使っている方法である。 62681 二文字の組み合わせで捕まえることにしている。しかし、これは本当に必要だろうか。 62682 実は C-@ と同様に別の文字に振り替えれば問題なく捕まえることができたりしないのか。 62683 62684 % 取り敢えず、work around の原因となった問題の再現を試みる。 62685 % bash-4.2 と bash-4.4 と bash-3.1 で確かめる。 62686 % おかしい。何れを用いても再現しない。 62687 % この問題は例えば #D0391 などに記録が残っているがヒントはない。 62688 % もっと遡ると #D0148 #D0122 #D0057 #D0018 #D0017 にある。 62689 % C-x C-b C-b 等と入力してみてもやはり再現しない。 62690 62691 →分かった。vi-mode だと発生しない。emacs mode だと発生する。 62692 bash-4.2 で再現した。bash-3.1 で再現する。bash-3.2 は無限ループになる。 62693 bash-4.0 もクラッシュする。bash-4.1 もクラッシュする。 62694 bash-4.3 は大丈夫。bash-4.4 はコマンドのキーマップがありませんと出る。 62695 まとめると以下のようになる。 62696 62697 version | 症状 62698 --------+-------------------------------------------------- 62699 3.0-3.1 | segfault 62700 3.2 | 無限ループ 62701 4.0-4.2 | segfault 62702 4.3 | 大丈夫 62703 4.4 | "コマンドのキーマップがありません" のエラー 62704 62705 ここで別の方式に切り替える。bind -s '"\C-x": "\xC0\x98"' に変更する。 62706 すると C-x C-x と押しても即座に反映されなくなってしまった。何故だろう。 62707 以前に似た症状があった #D0395 これを確認してみたが、 62708 この時の原因は今回とは関係ないはずである。 62709 62710 以下を実行してみてもやはり遅延は残る。 62711 for ((i=0;i<256;i++)); do ble-decode-bind/c2dqs "$i"; bind -r '\C-x'"$ret"; done 62712 62713 結局遅延を抑える為には C-x? に bind するしかない様だ。 62714 そうするとクラッシュの問題は生じなくなるので気にしなくて良い。 62715 62716 * vi-mode: bug, キーボードマクロで Meta が正しく記録されていない [#D0582] 62717 #D0586 周りの考察をしている時に見つけた。直した。 62718 62719 2017-11-10 62720 62721 * 2017-11-08: vi-mode (nmap K): ページャの表示の問題 (reported by cmplstofB) [#D0581] 62722 62723 * 再描画の実施 62724 62725 | - 再描画を実施するように変更する。 62726 | どのページャも常に altscreen を使用するとは限らないということ。 62727 | 62728 | 但しヘルプを表示する度に新しい行に移動するのは嫌なので、 62729 | 一旦現在表示している内容を消去してからヘルプを呼び出し、 62730 | その後でまた再描画するようにする。 62731 | 62732 | - cmplstofB さんの報告によると: 62733 | 62734 | > 私は Xfce4 Terminal [1] を使っているのですが,この仮想端末は xterm-256color 62735 | > を terminfo として用いており,xterm-256color の terminfo ではきちんと 62736 | > alternate screen は有効になっておりました。 62737 | 62738 | だとすると、複数画面に亘る時に空行になってしまう問題の原因は altscreen off ではない? 62739 | 何故なのかよく分からないが、取り敢えず毎回再描画することにすれば何れにしても解決する気がする。 62740 | 62741 | leave/enter と編集文字列の消去と再描画を実施するようにした。 62742 | しかし、現状の実装だと man に失敗する場合でも 62743 | 編集文字列の消去と再描画を実施するようになっていて気になる。 62744 | 本来であれば man が成功して何か表示できると分かった時点で再描画を実施したいものである。 62745 62746 PAGER を設定できるようにするのであれば、何れにしても完全に対応しなければならない。 62747 従って、ヘルプを表示する前に消去して、ヘルプを表示した後に再描画する。 62748 62749 * stty で leave/enter をちゃんと実施する。 62750 man はキーボード入力を求めるが、これが操作不可能になってしまう。 62751 62752 > これも私の設定の問題ですが,$MANOPT に --all 等の値を設定していると, 62753 > ble.sh と man ページが競合するか何かしてキー入力が受け付けられなくなります。 62754 62755 多分、これはこの leave, enter が原因なのである。 62756 もしかすると違うかもしれない。実装後に確認が必要である。 62757 →実際に leave/enter を呼び出すようにした所直った。 62758 62759 * 日本語 man の内容を正しく取得する方法? 62760 62761 | 問題点は何処にあるかというと $(man ...) もしくは、man > ... として実行すると、 62762 | man の日本語見出しが壊れてしまうということと man の太字などの修飾が消滅してしまうということである。 62763 | なので、現在は成功するかどうかわからない man をいきなり実行する様にしている。 62764 | 62765 | a 一つの方法は、一回 man ... &>/dev/null を実行して成功するかどうか確かめて、 62766 | その上で man を再度実行するというものである。これは二回 man を呼び出すので遅い。 62767 | 62768 | b 或いは PAGER='...' もしくは man -P '...' に cat などを指定して 62769 | 何処かにデータを書き出してしまえば良い。 62770 | しかし POSIX man ではその様な規定はないので、 62771 | これが実際に使えるかどうか分からない。 62772 | 62773 | PAGER 指定が無効な man の為に PAGER=... man > file などとすると、 62774 | また日本語見出しが壊れたり太字などの情報が消えたりする。 62775 | 62776 | c 別の方法として仮想端末を新しく作るという方法はあるかもしれない。 62777 | 62778 | exec 9<>/dev/ptmx で 9 に開く。 62779 | pty=$(tty <&9) でスレーブのファイル名が分かる 62780 | grantpt は chown $UID $pty; chmod 620 $pty とすれば良い。 62781 | unlockpt は分からない。 62782 | 62783 | と思ったが tty <&9 では /dev/ptmx が得られるだけだった。 62784 | slave のファイル名が分からないので開けない。 62785 | 検索してみても shell で同じことを実現しようとしている人は見つからないし、 62786 | また Python でも似たことを挑戦しようとしている質問では、 62787 | ptsname, grantpt, unlockpt の手段がないということで、 62788 | 専用のライブラリ pty を import して使うことを薦められている。 62789 | 62790 | しかし改めて考えてみると run-help 的な枠組みに対応するのだとしたら、 62791 | 何れにしても成功するのか失敗するのかは外側からは分からない。 62792 | 結局、毎回消去してヘルプの表示を試行して再描画するということになる。 62793 | 一応 run-help 的関数が定義されていない場合には、 62794 | 無駄な消去・再描画がないように頑張れるが、構造的に面倒だ。 62795 | 毎回消去・再描画がある方が自然な実装になる。 62796 62797 結局日本語 man の中身を正しく抽出する方法は不明である。 62798 しかし (遅いが) 一応動いているので取り敢えずよしとする。 62799 62800 * run-help 的関数は complete の枠組みと統合するべきか。 62801 62802 | そもそも未だ実装していないが complete の枠組みとして以下のようなものが構想にある。 62803 | 現状では補完関数は専ら組み込みの complete によって設定されるものだけであるが、 62804 | より分かりやすい枠組みとして ble/complete/コマンド名 という関数を通して定義できる様にする。 62805 | 或るコマンドの引数を補完する時は、その関数が定義されていればそれを使う。 62806 | また、"${BLEPATH:-$_ble_base}/complete/コマンド名" が存在すればそれを 62807 | source して定義された関数を使う。 62808 | それでも見つからないときは従来の complete による枠組みを使用する。 62809 | 62810 | 同様に、引数の色つけ関数も考えうる。 62811 | 例えば ble/color/コマンド名 というシェル関数で定義できる様にして、 62812 | "$BLEPATH/color/コマンド名" というファイルも探索する様にするとできる。 62813 | 62814 | しかし、機能毎にファイルを配置するのは大変だし、 62815 | 恐らく実際の設計上はやはり同じファイルで補完も色つけも定義したい。 62816 | その様に考えれば "$BLEPATH/command/コマンド名" 的なファイル名にして、 62817 | 更に、ble/command/complete:mycmd, ble/command/color:mycmd などという関数名にする。 62818 | 62819 | % また、引数の補完ではなくて標準入力 (ヒアドキュメント) の補完といった物も考えうる。 62820 | % →これは新しい関数として定義するというよりは ble/command/complete:mycmd に、 62821 | % 特別な引数を指定して呼び出すというのの方が良いような気もする。 62822 | と思ったが、恐らく complete:mycmd を実装する時には 62823 | そのような滅多に実装しない様なものの為に毎回条件分岐するのも面倒なので、 62824 | ここはやはり独立した関数として提供するべきである。例えば、 62825 | ble/command/complete-stdin:mycmd 62826 | 62827 | 更にリダイレクト先のファイルの補完も同様に処理できる。 62828 | ble/command/complete-redirect:mycmd 62829 | 62830 | この延長で ble/command/help:mycmd というのを入れるのは妥当である。 62831 | 62832 | 所で名前空間 ble/command に関してはもう少し考察の余地がある。 62833 | この名前空間は実際に補助のファイルを配置するディレクトリの名前と合わせたい。 62834 | $BLEPATH/command/mycmd というファイル名があると、 62835 | 其処に実際のコマンドを格納するみたいである。なので、command ではないより良いものが欲しい。 62836 | 例えば terminfo の様に commandinfo もしくは cmdinfo とするのはどうだろうか。 62837 | cmdinfo は省略形なので余り好まれないかもしれないと思ったが、 62838 | 実のところ commandinfo の時点で command-information の略である。 62839 62840 従って cmdinfo で良いような気がしてきた。以下のような感じにする。 62841 62842 ble/cmdinfo/complete:mycmd 62843 ble/cmdinfo/complete-stdin:mycmd 62844 ble/cmdinfo/complete-redirect:mycmd 62845 ble/cmdinfo/color:mycmd 62846 ble/cmdinfo/color-stdin:mycmd 62847 ble/cmdinfo/help:mycmd 62848 ble/cmdinfo/help-stdin:mycmd 62849 62850 結論としては即座には統合しないが、将来的に統合するときのために関数名だけは決めておく。 62851 ble/cmdinfo/help:mycmd という事にする。 62852 62853 * ble/cmdinfo/help:"$cmd" と ble/cmdinfo/help に対応する。 62854 対応した。動作テストはしていない。 62855 62856 * テスト項目 62857 62858 - done: bash builtin 62859 - done: bash keyword 62860 - done: bash [[ 62861 - done: alias resolve 62862 - done: function 62863 62864 * 2017-11-08 command-help: bash 組み込みコマンドの man (suggested by cmplstofB) [#D0580] 62865 62866 > $ # K --> function-for-help test --> man -P 'less $LESS -p ^test' bash 62867 62868 そのままだと動かない。少し工夫が必要である。 62869 62870 man bash | \grep -n '^[[:space:]]*test' | awk '/^([0-9]+)/ {sub(/[^0-9].*/, "");print;exit}' 62871 62872 結局色々試した挙句複雑な実装になった。 62873 ble/widget/command-help/.locate-in-man-bash に実装した。 62874 62875 * vi-mode (cmap): isearch している途中に決定を押すとその内容が実行されてしまう。 [#D0579] 62876 調べると ble/widget/isearch/accept の中で ble/widget/accept-line を呼び出している。 62877 これは駄目。仕方がないので、ble-decode-key "${KEYS[@]}" を呼び出すことにした。 62878 isearch では C-m で確定である。同様に呼び出し元でも C-m が確定であると想定して良い。 62879 だとすれば、そのまま "${KEYS[@]}" を呼び出しておけば問題ないだろう。 62880 62881 * decode: bug 'unset var[index]' が failglob/nullglob で全滅する (reported by cmplstofB) [#D0578] 62882 62883 > あと,もう一つ細かいのですが,failglob を有効にしていると,l* のようなコマンドを入力した場合, 62884 > (決定キーを押下する前に) 「-bash: 一致しません: _ble_decode_keymap_stack[last]」というエラーメッセージが出ます。 62885 62886 failglob は厳しい。浮いている [] があるともう駄目だ。 62887 というか nullglob の時は何もメッセージを出さないので、なおたちが悪い。 62888 62889 unset _ble_decode_keymap_stack[last] が駄目になっていた。 62890 62891 類似のものがないか検索する。 62892 62893 grc 'unset [[:alnum:]_]+\[|^[^][#"'\''`{}()]+\[[^[]' 62894 62895 どうも unset は全て確認したほうが良さそうな感じがしている。 62896 他に ble-bind -f C-[ となっている物が vi.sh の中にある。 62897 これは大丈夫かもしれないが念のため囲むことにする。 62898 62899 更に、この問題は過去の version にも波及する。修正が必要である。 62900 これは一応探してすぐ分かるところは直した。 62901 62902 2017-11-09 62903 62904 * vi-mode (cmap): 履歴に対応 (requested by cmplstofB) [#D0577] 62905 62906 現状の履歴の仕組みはシェルのコマンド履歴 history とくっついている。 62907 これを分離しなければならない。実際の変更はそんなに大変ではないだろう。 62908 ただ、それぞれの変数の役割を特定するのは面倒である。 62909 62910 | 何れにしても一つずつ調べていくしかない。 62911 | 恐らく履歴に関係しているのは _ble_edit_history* という変数のみである。 62912 | この名前の変数は幸いなことに ble-edit.sh において、 62913 | ./ble-edit.sh:4248-4982 に固まって存在している。 62914 | 62915 | 以下の変数はコマンド履歴と関係なく必要な変数である。 62916 | 使われ方も共通で良さそうに思われる。 62917 | 62918 | _ble_edit_history=() 62919 | _ble_edit_history_edit=() 62920 | _ble_edit_history_dirt=() 62921 | _ble_edit_history_ind=0 62922 | 62923 | * 以下の変数と関数もコマンド履歴とは独立に対応するべき気がする。 62924 | 従って、そのまま利用できるようにする。 62925 | 但し、onleave.fire で呼び出された関数で変なことにならない様に注意する。 62926 | これは keymap を見て vi_cmap だったら何もしないという事で対処できそう。 62927 | 62928 | _ble_edit_history_onleave=() 62929 | ble-edit/history/onleave.fire 62930 | 62931 | 62932 | * 以下の変数は危険である。これが空欄の時にはコマンド履歴を呼び出してしまう。 62933 | コマンド履歴ではない時には、これらの変数は空白であってはならない。 62934 | これらが非空白であればコマンド履歴は呼び出されない。 62935 | というか _ble_edit_history_loaded だけ注意していれば良さそうだ。 62936 | 62937 | _ble_edit_history_loaded= 62938 | _ble_edit_history_count= 62939 | ble-edit/history/getindex 62940 | ble-edit/history/getcount 62941 | ble-edit/history/load 62942 | 62943 | * 以下の関数はコマンド履歴に追加を行うので、 62944 | コマンド履歴以外では呼び出してはならない。 62945 | 現在は accept-line の一箇所でしか呼び出していないので 62946 | それ程気にしなくても良いが、名前を変えるなどする必要がある。 62947 | 62948 | ble-edit/history/add 62949 | 62950 | これは ble-edit/history/add-command-history に改名した。 62951 | 単に追加を行う関数として ble-edit/history/add を追加した。 62952 | 62953 | * isearch 関係の関数は殆どコマンド履歴と直交している。 62954 | isearch keymap に入る瞬間の以下の widget で 62955 | ble-edit-/history/load を呼び出しているが、 62956 | これは _ble_edit_history_loaded だけ注意していれば良い。 62957 | 62958 | ble/widget/history-isearch-backward 62959 | ble/widget/history-isearch-forward 62960 | 62961 | うーん。状態変更にどのように対応すれば良いだろうか。 62962 | 62963 | a 初めに考えたのは history に関連する widget それぞれについて、 62964 | cmap/history-* のような新しい widget を作って、 62965 | その中でローカル変数を設定して _ble_edit_history_* をすり変えて、 62966 | その上で各関数を呼び出すという物である。 62967 | 呼び出した後は、変更のあったものについては 62968 | 自前の履歴変数に書き戻すなどする。 62969 | 62970 | しかし widget 毎に一つ一つ用意するのは非効率的である。 62971 | 62972 | b なので @vi_cmap-history などの修飾 widget を作成しても良い。 62973 | 62974 | それでも色々と面倒はある。 62975 | 例えば、isearch は特別の keymap を用いるので、 62976 | cmap で isearch を利用しようと思ったら、 62977 | isearch keymap の clone を作成しなければならない。 62978 | 62979 | - これは色々問題が残る。先ず、似たような履歴を持つ編集モードの 62980 | それぞれについて isearch の clone を作らなければならない。 62981 | - 更に、isearch キーマップを変更しても、それは clone には適用されない。 62982 | 全ての isearch clone たちに対して同様の変更を適用する必要がある。 62983 | これは場合によっては有用かもしれないが、非直感的であるということの方が勝る。 62984 | 62985 | また、一様に状態を復元し・保存しということをすると、 62986 | 毎回全項目について状態を保存しなければならず非効率的である。 62987 | 大体の場合は履歴移動しかしないのだから、履歴番号だけ書き戻せば十分のはずである。 62988 | % と思ったが、history 云々のコマンドからは、元から履歴番号だけしか書き戻さないかも。 62989 | 履歴番号だけしか書き戻さなくて良いかどうかは 62990 | history, isearch の実装の方が知っているはずなのでそちらに任せたい。 62991 | 62992 | c やはり history, isearch 側で代替履歴の存在を 62993 | 認識する様に実装するほうが自然に思われる。 62994 | 62995 | ここは c で行く事にする。先ず初めに _ble_edit_history_prefix という変数を定義する。 62996 | 幾らか実装したが、すり替えによる実装は混乱が大きい。 62997 | 先ず、どの関数がすり変えたことが前提になっていて、 62998 | どの関数が何も考えずに呼び出せるのかが分かりにくい。 62999 | 63000 | 更に、或る関数が、すりかえを実行している関数とすり替えを 63001 | 実行していない関数の両方から呼び出されているとき、 63002 | どの様に処理をするのかが謎である。 63003 | 63004 | a 関数がすり替えを実行する時に local _ble_edit_history_prefix= とする? 63005 | その様にすれば呼び出された関数が重複して復元・記録を行うことはなくなる。 63006 | 63007 | しかし、これは何を意味するかというと使用しない変数も含めて 63008 | 全ての変数を復元・記録するということになる。 63009 | 或いは、どの変数がすり替えられていてどの変数がすり替えられていないかについて 63010 | 一つ一つの関数について決定して、それに基いて注意深く実装するということも 63011 | 原理的には可能だが、これは言語道断の実装である。 63012 | 63013 | b 或いは、二重にすり替えが起こっても大丈夫な様に設計を行う。 63014 | 63015 | すり替えが実際に実施されていたとしても、 63016 | 変数の内容を書き換えたりしていない限りは、 63017 | 元の変数の方にアクセスしている限りにおいては問題はない。 63018 | 63019 | 従って、search-history などの関数において、 63020 | 内部で変数を _ble_edit_history_edit にロードしていても、 63021 | 何も考えずに他の対策済み関数を呼び出して良い。 63022 | 63023 | 関数に対する要請は以下の通りになる。 63024 | 63025 | 1. prefix が設定されている時には本来の変数 (コマンド履歴) にはアクセスしない。 63026 | 2. ローカル変数にロードしてすり替えを行う時には、変数の中身に対する変更はしない。 63027 | 63028 | c 或いは、外部から直接呼び出せる関数に制限をかける。 63029 | その関数を呼び出した時に、全変数をすり変える。 63030 | 外部からも内部からも呼び出す関数については、 63031 | 外部から呼び出すための物と内部から呼び出すものの二つを用意する。 63032 | 63033 | x この方法は重そうだ。 63034 | 調べてみた所、変数のすり替えが必要になりそうな関数は、 63035 | 内部に履歴のループを含む {for,back}ward-search-history 系の関数のみである。 63036 | そして、この関数は 1 回の呼び出しで何度も呼び出されるものではない。 63037 | 寧ろ、恐らく1回しか呼び出されない。 63038 | 従って、全変数を毎回すり替えるとういことをしても速くはならない。寧ろ遅くなる。 63039 | 63040 | 63041 | ここは b の方向で実装することにする。 63042 | 63043 | - すべての関数は prefix の値に応じて適切な変数を参照・設定して動作するようにする。 63044 | - すり替えによる実装はできるだけ避ける。 63045 | - すり替えを実行して効率化を測る関数の場合には、 63046 | その関数自体は履歴情報に対して副作用を持たない。 63047 | また、そこから呼び出す関数も履歴情報に対して副作用を持たない。 63048 | 63049 | この時、実はすり替えをしていたとしても、 63050 | その他の関数を安全に呼び出すことができる。 63051 | また、その関数で直接使う変数のみすり替えれば十分である。 63052 63053 取り敢えず修正した。これで _ble_edit_history_prefix の値に応じて対象の履歴を切り替えられる様になった。 63054 実は未だ vi.sh にも _ble_edit_history* を触るコードがあるが、 63055 これらは全て本体のコマンド履歴を操作するための関数であり、 63056 再利用する予定も (今のところ) ないので、このままで良い。 63057 63058 次に cmap に入る時と出る時に _ble_edit_history_prefix を設定・解除する。 63059 また出る時に履歴項目を追加して最後の位置に移動する。 63060 その様に設定した。動いている様に見える。 63061 但し、未だ keymap に登録を行っていなかった。 63062 63063 * edit: C-r で即座に履歴をロードしようとするが、 [#D0576] 63064 実は、現在の履歴項目に一致が見つからないということが分かってからでも遅くないのでは。 63065 63066 →これの対応は実は簡単だった。既に _ble_edit_history* に直接触るのは 63067 backward-search-history-blockwise, forward-search-history.impl 関数に限られていた。 63068 ここで ble-edit/history/load を呼び出す様にすれば、 63069 isearch に入る時の ble-edit/history/load は必要なくなる。 63070 多分、これで動いているような気がする。 63071 63072 * vi-mode (cmap): bug C-[ でキャンセルできない (reported by cmplstofB) [#D0575] 63073 63074 vi_cmap/define を見てみると登録されている。しかし、実際に実行してみると動かない。不思議だ。 63075 と思って ble-bind -d で見ると bell になっている。 63076 実は、vi_cmap/define の下の方で上書きされていた。修正した。 63077 63078 2017-11-08 63079 63080 * 2017-11-01 vi-mode: キーボードマクロ対応 [#D0574] 63081 63082 | 挿入モード繰り返しの quoted-insert 対応に関連して、 63083 | 繰り返し機能とキーボードマクロの整合性について考察した。 63084 | 結論は両者 (キーボードマクロ vs 挿入モード繰り返し) は独立に実装するべきとなった。 63085 | その時に調べたキーボードマクロの振る舞いと対応方法の可能性に関する議論をここに残す。 63086 63087 さて、矢印キーなどの操作をした時にレジスタにどの様に記録されているのかを調べる。 63088 →どうやら右矢印は <80>kr という文字列に変換される様だ。実際に正しく再生することもできる。 63089 これは端末から渡される文字列とは異なることに注意する。 63090 - つまり、一旦 key から文字の列に逆に戻すという過程が入っている様に思われる。 63091 特に2文字目と3文字目が通常の文字であることから矢印キーを UTF-8 の特別な文字に割り当てていることによって 63092 そのまま文字列にしたら文字化けしているということではなくて、 63093 むしろ明示的に key を文字の列に符号化していると思われる。 63094 - 因みに "xp とすればその中身を直接挿入することができる。 63095 <80>kr という部分を選択して "by して、@b として再生するとちゃんと右矢印として解釈される。 63096 63097 うーん。面倒なので ble.sh では矢印キーはそのまま kcode に対応する UTF-8 で文字列に埋め込んで良い気がする。 63098 但し、その為には c2s で矢印キーに対応する文字を生成できる必要がある。 63099 これは UTF-8 環境ではできることが明らかであるが C などの環境ではできない。 63100 また将来的に別の文字コードに対応するときにも毎回問題になる。 63101 その様に考えると特別なキーシーケンスを与える必要があるのかもしれない。 63102 63103 取り敢えず対応した。 63104 63105 - 通常の文字はそのまま記録 63106 - C-@ C-[ を除く制御文字が対応するキーは制御文字で記録 63107 - その他は "ESC [ 2 7 ; * ; * ~" シーケンスで記録 63108 - @: には対応していない。これは bind -f '@ :' で登録することにする。 63109 - 無限ループを防ぐためにマクロの中でマクロは呼び出せない 63110 63111 * 無限ループの問題について。 63112 実際の vim でやると本当に無限ループになる。 63113 C-c をすると中断することができる。 63114 63115 ble.sh ではどのように実装するか。 63116 stdin を確認してもし何かあればその時点で 63117 マクロの中でマクロ呼出しができなくすれば良い。 63118 stdin を確認できない bash-3.0 未満では、 63119 常にマクロの入れ子呼び出しはできないことにする。 63120 63121 或いは最大の再帰の深さを設定すれば良いのではないか。 63122 →再帰の深さを設定できるようにした。 63123 63124 これで正しく動作するだろうか。 63125 63126 ? checked: 現在は accept-line の直前に記録を完了する様にしている。 63127 他にそのような対策が必要な箇所はあるだろうか。 63128 これは keymap を観察して見れば良い。 63129 簡単に確認したところその様な箇所はない様に思われる。 63130 63131 一つ気になるのは :commandline を実行している間の操作だが、 63132 vim で試してみると、その間の操作も全て記録されている様なので問題ない。 63133 63134 x fixed: 実際のキーボード入力と、再生または再度のやり直しによるキーボード入力が 63135 重複して実行されないように後者が登録されないようにする必要がある。 63136 63137 % vi.sh については ble-decode-* の呼び出しの前に、 63138 % ローカルに _ble_decode_keylog_enabled= を設定する様にした。 63139 % 63140 % 実は他の場所で定義されている widget についても同様に対策する必要があるのではないか。 63141 % 調べてみると ble-edit.sh に同様に ble-decode-key を呼び出している箇所があった。 63142 % この場所でも _ble_decode_keylog_enabled= を設定するようにした。 63143 % 63144 % しかし考えて見るにもっと根本的な対策が必要なのではないか。 63145 % つまり keylog を記録する側で、それがキーボードからの入力なのか、 63146 % 或いは、更なる呼び出しによるものなのかを判定する様にしても良いのではないか。 63147 % 63148 % もう一つ気になるのは、ローカルに _ble_decode_keylog_enabled= を設定した状態で、 63149 % 更に qa でマクロの記録を開始した場合にどうなるのかという事である。 63150 % 結果として、書き込み先のレジスタがすりかわるという事が起こる。 63151 % また、もっと悪いことに q で記録を停止することができなくなってしまう。 63152 % (M-q をもってノーマルモードに戻ると共に記録を停止するなどのことができない。) 63153 % 63154 % % これについては、現在マクロを記録中かどうかは、 63155 % % _ble_decode_keylog_enabled 変数ではなくて、別の変数を用いるというようにすれば良い。 63156 % % それでも未だ問題は残る。例えば end-logging が中で呼び出された場合に、 63157 % % ローカルの _ble_decode_keylog_enabled のみが解除される。 63158 % % 関数を抜けると再び logging が開始してしまう。 63159 63160 ローカルに設定した _ble_decode_keylog_enabled= ではなくて、 63161 もっと別の仕組みによって重複して実行されるコマンドを防ぐ必要がある。 63162 それも ble-decode の内部で完結した方法が良い。 63163 例えば、widget を呼び出す時に、何らかの特別な変数を設定すれば良い。 63164 _ble_decode_keylog_suppress という変数を導入することにした。 63165 また、外部で手で _ble_decode_keylog_enabled= を指定している部分は削除する。 63166 63167 今度の仕組みを使えば上記で述べたような問題点は発生しないだろう。 63168 63169 o 5i12<C-[> としても 12 がたくさん登録されるなどのことはない。 63170 x M-q が C-[ q に分解されてから改めて実行された場合でも、 63171 C-[ q が二重に実行されるということはない…。 63172 63173 % と思ったが、確認してみると <C-[> が登録されている? と思ったら、 63174 % そうではなくて単に M-q がその 27 表現として記録されているだけだった。 63175 % いや。改めて 27 表現を調べてみると <M-q> としてではなくやはり <C-[>q として記録されている。 63176 % 変だ。と思って再度試してみると、ちゃんと期待通りの振る舞いになっている。大丈夫。 63177 % しかし別の問題があることが分かった。これは別項目を立てる。 63178 63179 x fixed: 現在、KEYS に入っているキーの数だけ pop して内容を記録しているがこれは正しくない。 63180 _ble_decode_keylog_suppress が設定されて呼び出された時 KEYS は本来と異なる値になっている。 63181 →これは次の項目と一緒に解決した。 63182 63183 x fixed: M-q などを用いてロギングを中断した場合に <M-q> が全て記録されない。 63184 <M-q> が <C-[>q に分解されて <C-q> の部分だけは記録されてほしいのにも拘らず、である。 63185 その様な場合にはどの様に処理したら良いのだろうか。 63186 これは _ble_decode_keylog_enabled とはまた別の問題である。 63187 63188 % むしろこの場合こそ KEYS を pop するべきなのではないか。 63189 % そして _ble_decode_keylog_suppress=1 の時には pop を行わない様にする。 63190 % 63191 % また、_ble_decode_keylog_suppress= にして記録が行われるようにする… 63192 % と思ったがこの対処は本当に正しいのだろうか。 63193 % 例えば直接ユーザの入力から decompose-meta が呼び出された場合には、 63194 % _ble_decode_keylog_suppress= により記録が実施されるようにすれば良い。 63195 % ところが widget A から ble-decode-key を通して decompose-meta が呼び出された場合には、 63196 % 先ず初めに pop が起こらないというのは良い。 63197 % しかし、次に _ble_decode_keylog_suppress= を解除してしまうと、 63198 % widget A によって生成された仮想的なキー操作が記録されてしまう。駄目だ。 63199 63200 思ったが上記の方法には色々問題がある。 63201 先ず初めに _ble_decode_keylog_suppress=1 の時には pop を行わないと書いたが、 63202 widget の呼び出し中は常に _ble_decode_keylog_suppress=1 なのだから、 63203 _ble_decode_keylog_suppress の値は当てにならない。 63204 思うに _ble_decode_keylog_suppress の値は整数値にして入れ子のレベルを表す様にするべきなのだ。 63205 63206 →_ble_decode_keylog_suppress は _ble_decode_keylog_depth に改名して、 63207 入れ子のレベルを保持することにした。 63208 そして _ble_decode_keylog_suppress == 1 の時にのみ pop を行うことにして、 63209 更に decompose-meta では _ble_decode_keylog_suppress を 1 だけ減ずることにした。 63210 また記録は _ble_decode_keylog_suppress == 0 の時にのみ行う。 63211 63212 ? fixed: レジスタの中に qa...q が含まれている場合にそのレジスタを再生するとどうなるのか。 63213 ... がレジスタ a に記録されるのか、 63214 それとも実際のキーボード入力がユーザからされる訳ではないので a は空文字列になるのか。 63215 更に qb などとして別のレジスタへの記録を実行している途中に @c (中身 qa...q) などとして、 63216 別の記録を開始した時の振る舞いもどうなるのか気になる。a. 前の記録が中断されるのか、 63217 b. その時点で終了するのか、c. 記録が入れ子になるのか。記録が入れ子になるのだとしたら、 63218 内側の記録の内容は c1. 外側の記録にも反映されるのか c2. 外側の記録からは抜けるのか。 63219 63220 →実際に試してみると再生中には q は全て失効しているようだ。 63221 特に qa...q という組があったとしても a... が実行されたのと同じ結果になる。 63222 63223 さて 12qa...q とした時には引数 12 は捨てられるのか、それとも a に渡されるのか。 63224 →試してみると a には引数は渡らない。つまり、q を押しても全く何も起こらないのではなくて、 63225 引数などの消費は行われるという事である。 63226 63227 x fixed: 何故か既定のレジスタにも値がコピーされている。 63228 これは register#set を用いているのが行けない。 63229 63230 そもそも register#set を使う必要はないのではないか。 63231 と思ったが追記の時に何が起こるのかは非自明である。 63232 もしかすると通常の "Ay 等による追記と異なる振る舞いをするかもしれない。 63233 ("Ay の時には既にレジスタに登録されている内容の種類 char, line, block かによって 63234 追記のされ方が異なっていた事に注意する必要がある。) 63235 →確かめる。うーん。何か不思議なことになった。動作を詳細に調べる。 63236 63237 | | - 先ず行指向で A^JB^J という内容にしておく。 63238 | | ここで v{motion}"Ay で文字列を追加すると A^JB^JC^J という内容になる。 63239 | | 更に、qAihello^Cq としてキー操作を追記すると A^JB^JCihello^C^C^J という内容になる。 63240 | | どうやら最後の改行の直前に追記されるようだ。 63241 | | - この後に v{motion}"Ay で追記するとちゃんと ^J の後に追記される。 63242 | | - <C-c> 単体でも ^C^C と記録される様だ。^V は重複しない。 63243 | | ^V 中の ^C も重複する。というか別に追記でない時でも ^C は重複する。 63244 | | これについては別項目で調べることにする。 63245 | | - 行指向でそのまま qAihello^[q としたらどうなるか。 63246 | | →やはり改行直前に挿入される。 63247 | | - 挿入した後のレジスタの性質は変わるか。つまり p が行指向挿入になるか。 63248 | | →なる。行指向のままである。 63249 | 63250 | つまり行指向レジスタに追記する時は改行の直前に挿入される。 63251 | 63252 | | - 矩形の場合には最後の行に追記される。新しい行ではない。 63253 | | - また q で追記した後も矩形挿入のままである。 63254 | 63255 | | - 文字指向の場合はそのまま追記される。文字指向のまま。 63256 | | - 文字指向の時に末端に改行がある時でも、そのまま追記される。文字指向のまま。 63257 | 63258 | - 実は追記の場合には同時に既定のレジスタにも変更後の値が設定される。 63259 63260 まとめると、 63261 63262 - マクロの登録の場合には記録先レジスタの他に "" にも登録されるということはない 63263 但し、例外として、追記の場合には "" にも登録される。 63264 - 行指向のレジスタに追記するとき、最後の改行の直前に挿入される 63265 - 矩形指向のレジスタに追記するとき、最後の行に追記される。 63266 文字範囲を追記したときの様に新しい行に追加される訳ではない。 63267 - 文字指向のレジスタに追記する時は通常と同様に、ただ追記する。 63268 - 何れの場合でも追記先のレジスタの指向を変えることはない。 63269 63270 ? ok: vim では記録中に押された ^C は重複して記録される。何故か? 63271 ble.sh では当然その様にはなっていない。もう少し詳しく調べる。 63272 63273 例えば、i<C-q><C-c><C-[> と操作した時にはどうなるのだろうか。 63274 試してみるとこの場合には ^C は単体で記録されるようである。 63275 ということは無条件に ^C が二重化される訳ではない。 63276 63277 うーん。これはどういう事だろうか。キャンセルとしての C-c 63278 が内部で呼び出さされるともう一度 C-c を実行する等のことが 63279 内部的に実行されているのだろうか。謎である。 63280 63281 これについてはよく分からないので、ble.sh では取り敢えずは ^C は 63282 実際に入力されたとおりに 1 個だけしか記録しない様にする。 63283 63284 * vi-mode: 実は以下で ggvj"ay とすると echo^J^J がレジスタに登録される。 [#D0573] 63285 63286 % | echo$ 63287 % | $ 63288 % | $ 63289 % 63290 % これはどういう事だろうか。一番最後の行で同様に試してみた所、echo^J だった。 63291 % つまり、空行の末端で実行するとそこにある改行まで含むという事になる。 63292 % 最後の行にいる時にはそこに改行がないので含まれない。 63293 % 63294 % | echo$ 63295 % | $ 63296 % | ~ 63297 % 63298 % というかそもそも以下で vjd とすると二行消える。 63299 % つまり、ビジュアルモードに置ける範囲というのは行末の改行も含むという事。 63300 % しかも、今調べると現在の ble.sh 実装でもちゃんとその様になっている。 63301 % 63302 % | echo$ 63303 % | $ 63304 % | hello$ 63305 63306 これは現在の ble.sh の実装でもそうなっているので気にしなくて良い。 63307 63308 2017-11-05 63309 63310 * 2017-11-03 edit: command-help [#D0572] 63311 63312 現在の文脈に従ってコマンド名を抽出して調べる。 63313 実のところ、complete 辺りで似たようなことをしているはずだから、 63314 簡単に実装できるはずである。 63315 63316 ble-syntax.sh の syntax-complete の辺りを見ると 63317 先ず初めにただ単に文脈によって argument だとかを返しているだけである。 63318 complete.sh の方を覗いてみると、 63319 ble-complete/source/argument/.compgen で 63320 ble-syntax:bash/extract-command "$index" を呼び出している。 63321 この関数は変数 comp_cword comp_words comp_line comp_point を設定する。 63322 63323 対応した。--help よりも man の方を優先する様に変更した。 63324 また man の出力をパイプに流すと日本語の見出しが変なことになるので、 63325 man を直接起動することにした。man の標準エラー出力は /dev/null に捨てる。 63326 63327 * vi-mode (nmape * #): 単語の検索に対応するということ [#D0571] 63328 63329 * をおした時カーソルの下に単語 (WORD) があればそれを検索する。 63330 行内の forward に単語があればそれを検索する。 63331 http://vim-jp.org/vimdoc-ja/pattern.html#star には keyword か WORD と書かれているが、 63332 実際にテキストファイルで試してみると word である。WORD ではない。 63333 として、ソースコードのなどの編集を考えると WORD は不便である。 63334 word でなければならない。従って ble.sh では word で対応する。 63335 :help star で確認してみると WORD とは書いていなくて non-blank word と書いている。誤訳か? 63336 63337 | 実のところ bash の正規表現では \<\>\b しか使えず、 63338 | これらの振る舞いを自由に変更することは敵わない。 63339 | 従って、bash の定義する単語にするしかない。 63340 | 63341 | 先ず初めにどの様にして単語を抽出すれば良いか。 63342 | 例えば \<(.\B)*.\> などとすれば内部に単語区切りを含まない単語を抽出できる。 63343 | 現在のカーソルの下にある文字が単語を構成する文字かどうかを判定するにはどうすれば良いか。 63344 | 実は (.\B)*. の様な面倒なことをしなくても判定する方法があるのではないか。 63345 | これには POSIX ERE を調べる必要がある。というか調べたら BRE/ERE には \b, \B, \<, \> はなかった。 63346 | 然し bash の正規表現では確かにこれらの演算子を使うことができる。 63347 | ということは bash の正規表現はどの正規表現なのか? Bash のマニュアルには何も書かれていなかった気がする。 63348 | 63349 | 昔作った表によると \b\B\<\> に対応しているのは GNU grep -G/-E および GNU Emacs, それから Perl 5 である。 63350 | 大分限られている。という事は bash の実装は GNU Regexp もしくは独自エンジンと考えられる。 63351 | 調べてみると lib/sh/shmatch.c から regex を呼び出している。 63352 | 実は POSIX の header regcomp/regexec を呼び出しているだけだった。 63353 | という事は \b\B\<\> に対応しているかどうかは非自明である。環境依存という事になる。 63354 63355 [結論] つまり Bash の正規表現は <regex.h> regcomp/regexec による物で ERE にないものは環境依存。 63356 また [[:alpha:]] などの文字クラスも環境依存・ロケール依存である。 63357 63358 - ok: 因みに今までの実装で \b\B\<\> を使っているとそれは対策を考える必要がある。 63359 と思ったが実際に検索してみると今までは \b\B\<\> は使ってこなかった様だ。問題ない。 63360 63361 | さて、もう少し vim で試してみると /// などには一致しない。 63362 | 確かにこれは \<\> で囲んでも一致しないので除外するべきである。 63363 | その様に考えると vim でも既に w や W で定義される word や WORD 63364 | とは異なる種類の "単語" である (それでも word に近いが)。 63365 | という事は ble.sh でも厳密に対応する必要はない気がする。 63366 | 63367 | 取り敢えず \<[[:alnum:]_]+\> で捕まえるというのはどうだろうか。 63368 | 更にいうと手許の環境で試してみた所 [:alnum:] で平仮名などに一致する一方で、 63369 | \b\B の方も平仮名と英数字の間を単語の内部と判定している。 63370 | \b\B\<\> が一体どのようなものかについて定義はあっただろうか。 63371 | 例えば POSIX awk での定義はどうなっているだろうか。 63372 | 調べてみたら実は POSIX awk でも単語境界演算子は定義されていなかった。駄目だ。 63373 | 63374 | 仕方がないので \b\B\<\> が定義されている別の環境ではどのように実装するのが普通なのか調べる。 63375 | 取り敢えず GNU/Linux の <regex.h> の振る舞いは全て共通と仮定して良い。 63376 | だとすれば恐らく [[:alnum:]_] とそれ以外の境界が単語境界である。 63377 | perlre では \w とそれ以外の境界が単語境界ということになっているが、 63378 | \w の意味については明記されていない。ロケールや設定に依存すると書かれている。 63379 | 例えば /.../a というオプションを指定すると ASCII の [:alnum:]_ に制限されるとも書かれている。 63380 | 因みに ES8 だと 21.2.2.12 で \w は WordCharacters() と書かれている。22.2.2.6.1 を読むと、 63381 | 63382 | WordCharacters() = {c | Canonicalize(c) in [a-zA-Z0-9_]}, 63383 | (Note: 但し Unicode && IgnoreCase のとき以外は [a-zA-Z0-9_] になる) 63384 | 63385 | である様に思われる。Canonicalize は 21.2.2.8.2 で定義されている。 63386 | Unicode && IgnoreCase のときは Unicode データベース CaseFolding.txt に従って変換されるそうだ。 63387 | しかし、これは大文字小文字の変換であるような気がするので、実のところ [a-zA-Z0-9_] なのか? 63388 | 63389 | まとめ 63390 | 63391 | vim の実装は \<\> を使って定義される "単語" である。 63392 | Bash 正規表現について \b\B\<\> に対応していない環境もある。 63393 | 対応している環境の場合には、これらの演算子は 63394 | "単語を構成する文字とそれ以外の文字の境界" として実装されると見て良い。 63395 | 単語を構成する文字は環境依存であるが、 63396 | a [a-zA-Z0-9_] のときと 63397 | b [[:alnum:]_] のときと 63398 | c 更にこれを Unicode に拡張したもののときと、 63399 | d perlre の様に名言を避けているとき 63400 | の4種類がある。GNU/Linux <regex.h> では \<\> は b で対応しているようだ。に対応しているとき、 63401 | 基本的に [[:alnum:]_] で判定できるとしてしまって問題ない気がする。 63402 | 因みに [:alnum:] は POSIX ERE で存在することが保証されている。 63403 63404 [結論] ble.sh では [[:alnum:]_]+ を単語として取り扱うことにする。 63405 これが \<\> の境界の判定条件と合致すると仮定する。 63406 合致しなくて起こる不整合については仕方がないので諦める。 63407 63408 何れにしてもどの様にして対応を行うかを考える必要がある。 63409 63410 | 1 先ず \b\B\<\> が使えない環境から考える。 63411 | 63412 | 先ず初めにカーソルの下の単語の抽出から考える。 63413 | これは実のところ可能である。 63414 | 単に、現在位置の文字が [[:alnum:]_] であれば前後に拡張し、 63415 | それ以外ならば \G[^[:alnum:]_\n]*([[:alnum:]_]+) を捕まえれば良い。 63416 | 但し \G は現在のカーソルの位置。 63417 | 63418 | 検索については厳しい。一応 (^|[^[[:alnum:]_]])my_word([^[[:alnum:]_]]|$) で検索してから、 63419 | 前後の余白を除去すれば一致させることは可能ではあるが、 63420 | これは search の仕組みに手をいれなければならない。しかも汚い。 63421 | なので境界に一致させることには対応しないことにする。 63422 | 63423 | 2 次に \b\B\<\> が使える環境について考える。 63424 | 63425 | 先ず初めにカーソルの下の単語の抽出を行う。これは同様である。 63426 | 63427 | 次に検索について。原理的には単に \<\> で囲めば良い。 63428 | しかし、もし \<\> と [[:alnum:]_] の間に不整合がある場合には、 63429 | これによって全く一致しなくなってしまう可能性もあるので、 63430 | 念のため my_word =~ \<my_word 及び my_word =~ my_word\> を試して、 63431 | それぞれ一致したら付加することにする。 63432 | 実のところ、この様に実装すれば \<\> が使えるかどうかに 63433 | 依存しない実装に出来る気がする。 63434 63435 1. [[:alnum:]_] の連続として単語を抽出する。抽出した単語を my_word とする。 63436 2. my_word =~ ^.{len}\>$ ならば \> を付加する。 63437 3. my_word =~ ^\<.{len}$ ならば \< を付加する。 63438 63439 対応した。動いている。 63440 63441 * vi-mode (nmap :q): 残っている文字列を灰色にする? [#D0570] 63442 63443 * vi-mode (omap): C-c 及び C-[ 等でキャンセルするべきなのでは。 [#D0569] 63444 63445 マニュアルを少し探してみたが該当する記述は見つからない。 63446 vimindex によるとC-c は現在のコマンドをキャンセルと書かれている。 63447 恐らくコレが該当するのだろう。 63448 C-[ 及び <esc> は未使用と書かれている。 63449 63450 * vi-mode: cw cW の特殊な動き (reported by cmplstofB) [#D0568] 63451 63452 | echo hello vim world # 元の文字列 63453 | 63454 | echo hello@ vim world # カーソル位置 63455 | echo hellovim world # cw 63456 | echo hellovim world # 1cw 63457 | echo helloworld #2cw 63458 | 63459 | echo hell@ vim world # カーソル位置 63460 | echo hell vim world # cw 63461 | echo hell vim world # 1cw 63462 | echo hell world # 2cw 63463 | 63464 | echo @ello vim world # カーソル位置 63465 | echo vim world # cw 63466 | echo vim world # 1cw 63467 | echo world # 2cw 63468 | 63469 | echo nihongo日本語にほんご # 元の文字列 63470 | 63471 | echo nihong@日本語にほんご # カーソル位置 63472 | echo nihong日本語にほんご # cw 63473 | echo nihong日本語にほんご # 1cw 63474 | echo nihongにほんご # 2cw 63475 | 63476 | echo @ihongo日本語にほんご # カーソル位置 63477 | echo 日本語にほんご # cw 63478 | echo 日本語にほんご # 1cw 63479 | echo にほんご # 2cw 63480 63481 - 先ず初めに cw と 1cw に違いはない。 63482 - 空白の上にいる時には {N} 個先の w の手前まで。 63483 これは cmplstofB さんの報告通り {N}dw と同じ範囲で良い。 63484 - 単語の文字の上にいるときは {N} 個先の単語終端まで。現在位置を含む。 63485 63486 うーん。もしかして caw の終端点? と一瞬思ったが全然違った。 63487 63488 空行を挟む場合にはどうなるか。 63489 先ず空行または行の最後の空白文字で実行すると、その文字以降を消すだけ。 63490 行の最後の単語の上で cw を実行しても同様に、その文字以降を消すだけ。 63491 行の最後の単語の上で 2cw を実行すると、空行を飛び越えて最初の非空行の最初の単語の末端まで消える。 63492 行の最後の空白の上で 2cw を実行すると、空行が1つ消えるのみである。 63493 63494 x fixed: というか 2dw の時点で vim と ble.sh で振る舞いが異なっている。 63495 →これについては #D0567 で修正した。 63496 63497 x fixed: あと、最終行で最後に空白しか無いときに e を押すと最後の文字に移動して bell がなるが、 63498 vim ではオペレータ付きでこれを実行すると bell はならない。 63499 ble.sh ではオペレータがついていても bell を鳴らしていたので、修正する。 63500 63501 取り敢えず対応した。これから動作確認をする。 63502 取り敢えず提示された編集を実行してみることにする。 63503 63504 * vi-mode: w, dw の動作の違いに関して。 [#D0567] 63505 63506 これは既に Issues #2 にも書いたが、 63507 以下の内容に対して H5|w だと 9 位置に行くが、 63508 H5|dw だと 5678 を削除するという振る舞いについてである。 63509 63510 | 12345678 63511 | 90ab 63512 63513 - 実は :help word-motions に記述があった。 63514 {op}w の時には最後に通過した単語が行末にあった時、 63515 その後の空白は含まれないというものである。 63516 63517 - {op}W に関しては記述がないが、 63518 実際に試してみると {op}w の時と同様に働く。 63519 63520 - "最後の単語" の後に空白があってから改行でも良い。 63521 更にいうと、word-motions には単語の終わりがオペレータの対象の終わりと書いてあるが、 63522 これは間違いで実際には行末までがオペレータの対象の終わりになる。 63523 63524 - "最後の単語" が改行の場合でも成立する。 63525 この時には改行の直後がオペレータの対象の終わりになる。 63526 (但し、その後で exclusive-linewise の規則が適用される。) 63527 63528 * vi-mode: SP DEL は vi_xmap 及びオペレータが設定されている時は改行も数える。 [#D0566] 63529 63530 * dw に引数を与えて試していて気付いたが、 [#D0565] 63531 exclusive-linewise の辺りに書かれている記述の意味が分かった気がする。 63532 これらの記述は移動先自体が変わるという訳ではなくて、 63533 オペレータで処理するときの範囲が変わるという話だったのではないか。 63534 63535 幾つか試してみる。以下 ★◆ を付記したものが 63536 特別な範囲補正が必要になり、ble.sh で再現しないものである。 63537 63538 - 以下で H3|2w とすると cc の 1 文字目に行くが、 63539 H3|2dw とすると " bb" だけが削除され行が連結されるということはない★ 63540 63541 aa bb 63542 cc 63543 63544 - Hdgj とすると1行目が消える。行指向になる◆ 63545 63546 % exclusive-linewise に記述されている結果になっているが、 63547 % 条件を満たしていない気がする。 63548 % これは読み間違えであったということが分かった。日本語訳が悪い。 63549 63550 →"その行" とは移動後の位置の行のことではなくて、 63551 移動初めの位置の行のことである。日本語ではわざわざ "その" とは付けない。 63552 わざわざ付けると "別のものに属する行" の意味になる。 63553 63554 | aa 63555 | bb 63556 63557 - Hldgj とすると1行目の最後の "a" だけが消える★ 63558 これは :help exclusive-linewise の上の段落の記述に合致する動作である。 63559 63560 | aa 63561 | あ 63562 63563 - 3Hdgk とすると2行目が消える。行指向になる◆ 63564 63565 | xxxx 63566 | 1234 63567 | 5678 63568 63569 - 3Hldgk とすると2行目と "5" が消える。1行目に連結はされない。 63570 :help exclusive-linewise の上の段落の記述と一致せず、 63571 特別な動作は何もしていないように見える。 63572 63573 | xxxx 63574 | あ34 63575 | 5678 63576 63577 日本語訳がおかしいのかと思って改めて英語の説明を見る。 63578 しかし英語でもこの動作を正しく言い表しているようには見えない。 63579 むしろ "}" と "d}" が何故異なるのかについて、 63580 より矛盾を孕む動作になっているような気がする。 63581 63582 > If the motion is exclusive and the end of the motion is in column 1, the 63583 > end of the motion is moved to the end of the previous line and the motion 63584 > becomes inclusive. Example: "}" moves to the first line after a paragraph, 63585 > but "d}" will not include that line. 63586 63587 ここまでの振る舞いから実際には以下の様になっていると思われる。 63588 63589 移動コマンドが排他的で、現在の位置より後の列1に移動し、omap のとき、 63590 範囲は移動先の前の行の最後の文字になり inclusive になる。 63591 63592 - 前の行が空行の時にはどうなるのだろうか? 63593 以下で H5d<SP> とすると 1234<LF> が削除される。★ 63594 つまり、前の行の行末までになる。 63595 63596 | 1234 63597 | 63598 | 5678 63599 63600 更に行指向になる。◆ 63601 これはつまり ★の修正と exclusive-linewise★ 63602 の修正が同時に起こりうるということである。 63603 63604 - 2Hdh としても何も起こらない。1 行目に連結はされない。 63605 つまり移動前と移動後の位置が同じときには★は作動しない。 63606 63607 1234 63608 5678 63609 63610 - ◆の動作の説明には非空白行頭と書かれているが、 63611 空白行頭にいた場合には有効ではないのだろうか。 63612 63613 % 以下で Hdgj とすると行指向になる。 63614 % H dgj, H3 dgj, H4 dgj の場合は行指向にならない。 63615 % 2Hdgk は行指向になる。 63616 % 2H dgk, 2H3 dgk, 2H4 dgk は行指向にならない。 63617 % 63618 % | 12341234 63619 % | 5678 63620 % 63621 % 以下で試しても全く同様であった。 63622 % 63623 % | 1234 63624 % | 5678 63625 % 63626 % うーん。不思議だ…と思ったらよく考えると移動先が列1でないと駄目なのだった。 63627 63628 % うーん。"d}" と "d12 " で振る舞いが異なる気がする。 63629 % "d`a" は "d}" と同じ振る舞いである。 63630 % "d}" の場合には移動元が行頭以降・非空白行頭以前のときに行指向になる。 63631 % 別に非空白行頭の直前でなくても良い。(これも日本語訳が悪い。 63632 % "その手前の位置" と書いたら非空白行頭の直前の位置一点を指すのかと思うが、 63633 % 実際にやってみると別に直前でなければならない訳ではない。) 63634 % 63635 % "d12 " の振る舞いは不可解である。 63636 % 63637 % | 1234 63638 % | 567890ab 63639 % | 63640 % 63641 % において "d4 " は "1234" を削除するが、 63642 % "d12 " は "12..0a" までを削除する。b を削除しない。 63643 % 更に言うと :help exclusive-linewise の上下の 1./2. 63644 % のどちらが適用されるかはどう決まるのか…。 63645 63646 これは分かった。<space> はオペレータがある時は文字の数え方が異なる。 63647 :help whichwrap に書かれている。 63648 63649 上記の例で "d}" "d`a" (3Hma してある) "d2gj" は全て同じ振る舞いである。 63650 bol <= src <= nol の時は◆になり nol < src の時は★になる。 63651 と思ったが振る舞いを見ると bol <= src <= nol の時は◆と★の両方が適用されている。 63652 63653 これの修正は何処で行われるべきか。 63654 テキストオブジェクトや inclusive も exclusive-range.impl を呼び出す。 63655 従って、exclusive-goto.impl の中で修正を行うべきの気がする。 63656 63657 2017-11-04 63658 63659 * 2017-08-19 ble-edit: C-x C-x で微妙な遅延が見える。これは stty の問題だろうか? [#D0564] 63660 63661 これは現在大きな問題にはなっていないので優先度は低い。 63662 63663 | ちょっと stty -a の結果を見たり ble-stty/* の実装を見ても分からない。 63664 | そもそも ^X は stty で特別な文字としては扱われていない様に見える。 63665 | もしかすると stty raw などとすると遅延は起こらないのかもしれないが、 63666 | これは時間のある時に試すことにすれば良い。 63667 | 63668 | →screen の maptimeout や readline の 63669 | keyseq-timeout を変更してみたが変わらない。 63670 | screen を抜けても変わらない。ローカルでやると遅延はない。 63671 | 63672 | - どうやら ssh ごしだと遅延があるようだ。 63673 | ssh で timeout で検索すると別の timeout が当たる。C-x や Ctrl-x で検索しても何も出ない。 63674 | 63675 | - よく考えたら実は ssh は関係なくて端末の設定なのではないだろうか。というのも Emacs では遅延はない。 63676 | stty の設定を動いている時と動いていない時で比較したが良くわからない。 63677 | できるだけ似るようにして見たが遅延はそのままである。 63678 | padparadscha ではなく tkynt2 でやってみても同じである。 63679 | ローカルでは screen の中でやっても同じである。 63680 | $ ssh pad bash -i として端末を割り当てずにやってみた所、それでも遅延はある。 63681 | つまりやはり端末の設定ではなくて ssh が怪しいのではないだろうか。 63682 | 63683 | と思ったがそれもおかしい。Emacs はやはり遅延がない。bash が悪いのだろうか? 63684 | ローカルでは bash-4.4 でリモートでは bash-4.3 である。 63685 | 63686 | - リモートで bash-4.4 を動かしてみたら遅延がなくなった。 63687 | つまり bash-4.3 に何らかのバグがあって C-x に遅延が生じているということなのだろう。 63688 63689 bash-4.0, 4.1, 4.2, 4.4 では遅延はない。 63690 bash-4.3 のみで遅延がある。これの対策はしない。 63691 63692 2017-11-03 63693 63694 * vi-mode: refactor [#D0563] 63695 63696 - done: ble/keymap:vi/mark/set-local-mark 96 "$_ble_edit_ind" を実行するコマンドを提供するべき。 63697 例えば ble/keymap:vi/mark/set-jump など。 63698 63699 - done: また、linewise-goto.impl 及び linewise-range.impl は 63700 bolx nolx を用意しなければならないのが分かりにくい。これも修正するべき。 63701 63702 - done: ビジュアルモードの種類 char line block を格納する変数名は type ではなく context に統一する。 63703 63704 * 2017-09-16 vi-mode merge 直前に一括して行うテスト・仕様変更など [#D0562] 63705 63706 * 各コマンドについて再度動作するかどうかについてテストする必要がある。 63707 Wiki に各コマンドの説明を書きつつテストして行くのが良いだろう。 63708 63709 x fixed: ihello world<C-[>. で world 以降しか挿入されない。 63710 これは vi_imap/magic-space によって記録が reset されていた為に起こった物である。 63711 現在は irepeat は実際に行われたコマンドの列で記録されているし、 63712 また xmap I, A なども dirty-range による追跡を行っている。 63713 imap での様々な編集が起こっても問題ないようになっているので、 63714 単に magic-space を登録してそれを white としても問題ないだろう。 63715 63716 vi_imap/magic-space は廃止した。今後は magic-space を直接使ってもらう。 63717 63718 x fixed: a123<C-[>.. において1つ目の . ではちゃんと a で実行されているが、 63719 2つ目の . においては i で実行されている。これは何故か。 63720 record-insert で (vi_nmap/repeat で呼び出されたかどうかに拘らず) 63721 毎回記録しているのが原因である。→修正した。 63722 63723 x fixed: nmap w b e ge において単語の定義が異なる。 63724 これは imap <C-w> や text object iw aw と同様にすれば良さそうだ。 63725 というか、imap <C-w> や text object iw aw についても数字が考慮されていなかった。 63726 63727 x resolved: imap <C-w> でスペースの削除の仕方が異なる気がする。 63728 と思ったら、これは bashrc で設定している関数が問題だった。 63729 63730 x fixed: {N}% がいつも同じ位置に移動する気がする。 63731 →これはどうやら local bolx= nolx= を定義せずに linewise-goto を呼び出したのが行けなかったようだ。 63732 類似の修正を text objects ip ap に対しても行った。 63733 63734 x fixed: `a 'a でオペレータが全く動いていない。 63735 goto-local-mark.impl, goto-global-mark.impl を呼び出す前に clear-arg を実行していたのがいけなかった。 63736 他にも operator の効かない移動コマンドが存在したりするかもしれないので確認する。 63737 63738 x fixed: d_ 及び d1_ が charwise になっている。正しくは linewise である。 63739 63740 ここまでで取り敢えず setup-map で登録されているコマンドについては一通り動作することを確認した。 63741 次に omap nmap xmap に登録されているコマンドについてテストを行う。 63742 63743 x fixed: lib/vim-surround (xmap S): vS が linewise になっているが、 63744 元々の surround.vim ではそうではない。 63745 vS は charwise で vgS の時に linewise になっている。 63746 また VS および VgS の時も linewise だがインデントは行わない? 63747 surround.vim の振る舞いは謎だが、取り敢えず修正した。 63748 63749 x resolved: command-help が常に一番最初のコマンドの help しか出さない? 63750 →調べてみた所、これは元からそういう仕様だったようだ。 63751 これの改良については別項目を立てて処理することにする。 #D0572 63752 63753 x implemented: 実は xmap c, xmap s, xmap C では InsertLeave を設定する様だ。 63754 これの対応は面倒である。 63755 63756 先ず初めに operator:c の中で、 63757 現在の operator の実行が xmap 経由であることを認識しなければならない。 63758 と思ったが、よく考えたら context == block となるのはビジュアルモードだけなので、 63759 この時は常に block-insert-mode.impl を呼び出すようにしてしまえば良い。 63760 63761 block-insert-mode.impl は今まで自身で extract-block を呼び出していたが、 63762 operator:c context=block の時は既に sub_ranges があるので、これを利用したい。 63763 block-insert-mode.impl の呼び出し元で sub_ranges を計算することにした。 63764 63765 operator:c で .insert-mode を呼び出す代わりに block-insert-mode.impl を呼び出す様にする。 63766 vi_xmap/exit が重複して呼び出されることの対策を vi_xmap/exit に追加した。 63767 63768 実装した。動いている。と思ったが、挿入される文字の数が少ない。 63769 63770 operator:c の中で、block-insert-mode は行の長さの変化を見るから、 63771 これを呼び出した後で領域を削除する訳にはいかない。 63772 従って block-insert-mode.impl を呼び出す前に領域を削除しなければならない。 63773 すると、それに応じて sub_ranges の修正が必要になる。 63774 block-insert-mode は sub_ranges[0] しか参照しないので、これを修正すれば十分である。 63775 →修正した。OK 63776 63777 取り敢えず各 keymap で定義されているコマンドは確認した 63778 (imap cmap は面倒だし殆ど emacs-mode と同じなので良いだろう)。 63779 63780 後は各 mark, 各 registers の特殊な振る舞いについて確認すれば良い。 63781 63782 o 先ず registers については、そもそも特殊レジスタには対応していない。 63783 なので確認することは現時点ではない。 63784 63785 o mark `^ (挿入モードを抜けた位置) 63786 o mark `" (最後にその履歴項目から抜けた時の位置) 63787 o mark `. 最後に編集の起こった位置。これは vim のそれと 63788 厳密には振る舞いが異なる可能性もあるが、気にしない。 63789 o mark `[`] これはよく使っているので問題はないはず。 63790 o mark `` これについても既に試したので問題はないはず。 63791 o mark `<`> これも gv で使われているので問題ないはず。 63792 63793 x fixed: xmap ? を押したら rot13 が呼び出される。 63794 xmap: / ? n N これは motion として働くべき。 63795 確認してみると元から登録されている。 63796 単に operator rot13 が上書きされていた。削除した。 63797 63798 x fixed: xmap で / ? n N を実行すると選択範囲がずれるのでは? 63799 →ずれた。これは修正する必要がある。 63800 単に xmap にいる時には選択範囲のハイライトをしないという様にすれば良さそう。 63801 63802 と思ったら、_ble_edit_mark を用いて現在位置が 63803 既に一致したものなのかどうか判定している様だ。 63804 そうすると _ble_edit_mark を設定しておかないと n N で移動ができなくなる。 63805 と思ったが、既に一致したかどうかの判定は ble/keymap:vi/search/invoke-search の中で行っていて、 63806 _ble_edit_mark_active または _ble_keymap_vi_search_activate が search になっているかで判定している。 63807 63808 うーん。invoke-search の中を vi_xmap の時に合わせて書き直そうとしたが難しい。 63809 やはり既に一致したかどうかの情報は必要である。 63810 そしてそれは _ble_edit_mark_active の clone の様な変数を用意すれば良い。 63811 (或いは _ble_edit_mark_active=line+! などのようにどんどん構造を複雑にすることも可能ではあるが、 63812 全体に汚くなるのでやはりそのような方法は駄目だ。) 63813 63814 うーん。取り敢えず _ble_keymap_vi_search_matched という変数を導入してみた。 63815 しかし、この変数が正しくクリアされるかどうかについては自信がない。 63816 63817 - _ble_edit_mark_active は異なるタイミングでもクリアされる。 63818 特に xmap から抜けるときと xmap に入る時。 63819 xmap から抜ける時は実のところ一致状態が残っていても良い。 63820 xmap に入るときも一致状態が残っていても良い。 63821 問題は motion によって解除されるはずのところ解除されないということが起こる場合だが、 63822 恐らく問題はないはずである。 63823 63824 - 他に imap や cmap に移るときに問題になることはあるだろうか。 63825 cmap に移る時には _ble_edit_mark_active はクリアされるが、 63826 _ble_keymap_vi_search_matched はクリアされない。 63827 しかしながら cmap から _ble_keymap_vi_search_matched を参照することはないから問題ない。 63828 更に、また元の nmap に戻ってきたときには _ble_edit_mark_active が復元されて元の状態に戻る。 63829 : を実行している場合には更に adjust-command-mode が呼ばれるので、無事に両方共解除される。 63830 63831 - imap に移る時にはどうだろうか。_ble_edit_mark_active は解除される。 63832 _ble_keymap_vi_search_matched は解除されない。 63833 そのまま挿入の操作をしても _ble_keymap_vi_search_matched は解除されないまま残る。 63834 次に normal-mode に突入するときにも残る。ここで初回から n などを実行すると、 63835 本当は一致していないのに一致しているという様に勘違いして検索が始まる。 63836 63837 この微妙な違いにユーザは気づかないかもしれないが、確かに変な振る舞いになる。 63838 取り敢えず .insert-mode の _ble_edit_mark_active をクリアしているところで、 63839 _ble_keymap_vi_search_matched もクリアすることにする。 63840 取り敢えずこれでよしとする。 63841 63842 さて実際に試してみると駄目だ。動いていない。うーん。 63843 63844 x fixed: これは invoke-search の中で _ble_edit_mark を用いて開始位置を探索していたのが駄目だった。 63845 単に 1 文字進めるというようにすれば良いだろうか。。 63846 或いは再度一致させてしまえば良い→再度一致させる方針で実装した。 63847 63848 x fixed: それでも動かないと思ったら、そもそも _ble_keymap_vi_search_activate を 63849 vi_xmap の時に設定していなかった。従って、_ble_keymap_vi_search_matched も設定されなかったということだった。 63850 _ble_keymap_vi_search_activate を設定するようにした。 63851 63852 x fixed: 所が今度は _ble_keymap_vi_search_activate を設定したら _ble_edit_mark_active が上書きされてしまった。 63853 これは _ble_keymap_vi_search_activate から _ble_edit_mark_active に移す時の keymap の判定が誤っていた。修正した。 63854 63855 x fixed: また詳しく見てみると範囲がずれている。 63856 元々は _ble_edit_mark から読み取って _ble_edit_ind++ していたが、 63857 具体的に再一致させて end を読み取っているときには _ble_edit_ind++ は要らないのだった。直した。 63858 63859 x fixed: / ? n N xmap の時に履歴項目を移動するのはまずいのではないか。 63860 →xmap にいる時には履歴項目の移動はしない様にした。動いている。 63861 63862 取り敢えずはこんなところだろう。 63863 63864 * vi-mode を bash-3.0 でもテストする。 63865 63866 そんなに詳しくテストするつもりはない。 63867 簡単に動かしてみているが、問題はないようだ。 63868 少なくとも全く動かないということはないことは確かだ。 63869 63870 x fixed: ところで矩形挿入の時の `[`] が変だということに気付いた。 63871 修正した。commit-edit-area を追加すれば良いだけだった。 63872 63873 2017-11-02 63874 63875 * vi-mode (operator): ble/keymap:vi/call-operator [#D0561] 63876 63877 オペレータの中で更に編集コマンドを実装する場合に備えて 63878 _ble_keymap_vi_mark_suppress_edit を設定してオペレータを呼び出す。 63879 63880 * vi-mode: ble/widget 実装の注意点 [#D0560] 63881 63882 これらは Wiki に記述することにした。 63883 63884 | vi-mode 用の ble/widget を実装する上での注意点についてまとめる必要がある。 63885 | 63886 | - 先ず __before_command__ の内部で set-previous-edit が発生してはならない。 63887 | set-previous-edit 内部では . で繰り返すために、その編集が起こった原因となる 63888 | コマンドを WIDGET によって特定する。__before_command__ は 63889 | WIDGET 経由で呼び出されないので、誤った復元をしてしまうことになる。 63890 | 63891 | - WIDGET を widget 本体の中で変更してはならない。 63892 | これは同様に . で繰り返すための情報を破壊してしまうことになるからである。 63893 | __before_command__ 内部でコマンドを変更する目的で書き換えることは可能。 63894 | 63895 | - operator の定義方法について 63896 | 63897 | もし . による繰り返しに登録しないときには 63898 | 空の関数 ble/keymap:vi/operator:foo/norepeat を定義する。 63899 | 63900 | 63901 | - `[`] が正しく設定されるために 63902 | 63903 | 編集を伴うコマンドについては、編集後に編集範囲を設定するために 63904 | ble/keymap:vi/mark/set-previous-edit-area 編集開始位置 編集終了位置 を呼び出す。 63905 | 63906 | 複雑な編集について編集範囲が容易に決定できない場合には、 63907 | ble/keymap:vi/mark/set-previous-edit-area を自分で呼び出す代わりに、 63908 | 編集が行われるコード全体を ble/keymap:vi/mark/start-edit-area と 63909 | ble/keymap:vi/mark/end-edit-area で囲めば良い。 63910 | 63911 | | ble/keymap:vi/mark/start-edit-area 63912 | | local _ble_keymap_vi_mark_suppress_edit=1 63913 | | 63914 | | ... # 編集操作 63915 | | 63916 | | unset _ble_keymap_vi_mark_suppress_edit 63917 | | ble/keymap:vi/mark/end-edit-area 63918 | 63919 | mark/{start,end}-edit-area の内側で更に別の編集コマンド (内部で `[`] が設定される) 63920 | を呼び出す場合には、更に _ble_keymap_vi_mark_suppress_edit を設定する必要がある。 63921 | 63922 | | ble/keymap:vi/mark/start-edit-area 63923 | | local _ble_keymap_vi_mark_suppress_edit=1 63924 | | 63925 | | ... # 編集操作 (`[`] の設定を行う widget の呼び出しを含みうる) 63926 | | 63927 | | unset _ble_keymap_vi_mark_suppress_edit 63928 | | ble/keymap:vi/mark/end-edit-area 63929 | 63930 | オペレータについては外側で自動的に編集範囲が検知されるので、 63931 | 自身で {set-previous,end}-edit-area を呼び出す必要はない。 63932 | 但し、編集は起こらないが範囲を設定したい場合 (operator y など) には、 63933 | commit-edit-area 関数を明示的に呼び出す。 63934 | 63935 | - . による繰り返し操作が正しく設定されるようにするために 63936 | 63937 | 基本的には繰り返しの対象になる widget で ble/keymap:vi/repeat/record を呼び出せば良い。 63938 | 繰り返しの対象となるコマンドは2種類ある。 63939 | 一つは編集を伴うコマンドで、もう一つは挿入モードに入るコマンドである。 63940 | 63941 | 1 ble/keymap:vi/mark/{set-previous-edit-area,end-edit-area} を呼び出すときは、 63942 | そこで1単位の編集が完了するということを表すので、 63943 | 大抵、対応して ble/keymap:vi/repeat/record も呼び出すと考えると良い。 63944 | 63945 | 2 ble/widget/vi_nmap/.insert-mode を呼び出した後も、 63946 | 場合に応じて、ble/keymap:vi/repeat/record または ble/keymap:vi/repeat/clear-insert を呼び出す。 63947 | repeat/record はその挿入モード突入に至るコマンドを . で再現したい時に使う。 63948 | repeat/clear-insert は、挿入モードの途中で挿入操作をクリアする時などに使う。 63949 | repeat/clear-insert は実例として imap の <C-o>, 移動操作, コマンド実行などで使われている。 63950 | - 但し operator の中では、外側で自動的に repeat/record が呼び出されるので、これらは自分で呼び出さない。 63951 | 例えば operator:c では .insert-mode を呼び出すが、自身で repeat/record を呼び出すことはしていない。 63952 | operator による非同期読み取りによる継続の場合は、mark/set-previous-edit の時と同様に自分で呼び出す必要がある。 63953 | - repeat/record はその時の keymap を参照するので、vi_nmap/.insert-mode よりも後で呼び出す必要がある。 63954 | 63955 | また、編集を行って更に挿入モードに入るコマンドの場合であっても、 63956 | 1回だけ repeat/record を呼び出せば問題ない。 63957 | その時でもやはり .insert-mode よりも後で repeat/record を呼び出すようにすること。 63958 | 63959 | KEYMAP, KEYS, WIDGET, ARG, FLAG, REG の値は記録され 63960 | 繰り返しの対象となる widget を呼び出すときに再現される。 63961 | 繰り返しの対象となる widget が、それ以外の "状態" に依存して振る舞いが変化し、 63962 | その時選択された振る舞いを繰り返しの際にも再現したい場合には、 63963 | それを明示的に記録・再生する必要がある。 63964 63965 * vi-mode: xmap I A が動かなくなっている…。 [#D0559] 63966 63967 これは修正した。InsertLeave オプションが指定されているかどうかの判定が誤っていた。直した。 63968 63969 という事は、いつからなのか分からないが、ずっと誤っていたのではないかと思われる。 63970 blame で見ると最後の書き換えは 453da8a2 (2017-10-12) である。 63971 調べるとこの時に複数に分かれていた insert-mode を統合したのだった。 63972 63973 さて、更に振る舞いで気になることがある。 63974 挿入を終わった後のカーソルの位置が一つ戻っている。 63975 これは何か? nmap に戻る時にカーソル位置が一つ戻ることに関係するだろうか? 63976 そうだった。その様になっている。これは前からそうだった筈なのだが何故気が付かなかったのか。 63977 何れにしても修正する。どの様に修正するのが良いだろうか。 63978 63979 a 例えば InsertLeave が設定されている時には一つ戻るという操作を行わない? 63980 これは駄目。例えば InsertLeave にカーソル移動を伴わない・編集を伴わない操作が設定されることも考えうる。 63981 その時に、(カーソル移動も編集もないのに) 位置が1つ戻るという操作がキャンセルされるのは変だ。 63982 63983 b InsertLeave の内部でカーソル移動が起こった場合には 1つ戻るという操作を行わない? 63984 これは魅力的だが微妙。もしかすると InsertLeave の中で 63985 明示的に現在位置と同じ位置に移動するという事があるかもしれない。 63986 その様な場合には結局 1 つ戻るという操作が無駄に発生してしまうことになる。 63987 63988 更に言うと InsertLeave の中でのカーソルの移動が、 63989 normal mode に移行する時に 1 つ戻ることを前提としている or それが自然という場合も考えうる。 63990 63991 c 或いは、InsertLeave の中でカーソル移動を行う時は、 63992 normal mode に復帰する際にカーソル位置が 1 つ戻るという事を前提として、 63993 1つ次の文字に設定するということも考えうる。 63994 63995 実のところ c の実装が最も自然に思われる。 63996 63997 * 所で挿入モードに a で入った時と i で入った時で <C-o> 後のカーソル位置が異なる? [#D0558] 63998 と思ったけれど改めて試してみるとそうでもなかった。 63999 64000 * vi-mode: . 実装 (6) 取り敢えず完了 [#D0557] 64001 64002 #D0543 各 widget の戻り値の確定 64003 #D0550 WIDGET/KEYMAP/ARG/FLAG/REG ローカル変数の導入 64004 #D0551 nmap/omap における operator 操作の記録と復元 64005 #D0555 xmap における operator 操作の記録と復元 64006 #D0556 挿入モードの操作の記録 (これの為に imap-repeat も整理した #D0554) 64007 64008 - 3l. とするとそれより前に行われた編集コマンドが実行される。 64009 つまり編集コマンドしか繰り返しの対象とはならない。 64010 64011 どのコマンドが繰り返しの対象になるかについては help を見るのが良いだろう。 64012 help には repeat last change, also yank is repeated 64013 commandline command is not repeated としか書かれていない。 64014 64015 % しかも実際に試してみると yiw は repeat されない様である。 64016 % also yank is repeated とはどういう意味だろう? 64017 64018 * $widget.record 的な関数を定義して、それが使われていたらという話があったが、 64019 operator などの内部で記録を行いたい場合には難しいのでは? 64020 64021 % と思ったが operator の内部では基本的に記録は行わず記録を行うとすれば非同期な読み取りが関わるときだが、 64022 % その場合には改めて hook 関数が呼び出されるのだから、"(hook 関数).widget" という形の関数名にすれば良いのでは? 64023 64024 とも思ったが、直接 hook 関数が _ble_decode_key__kmap に登録されているとは限らない。 64025 例えば、vim-surround.sh の async-inputtarget では async-inputtarget 用の関数が WIDGET の本体になってしまう。 64026 従って、"(WIDGETの本体).record" をそれぞれ定義して動作を制御するというのは難しい。 64027 64028 従って、やはり $widget.record の様な仕組みは余り意味がない。 64029 各自で ble/keymap:vi/repeat/record の代わりに独自の記録関数を定義するのが良い。 64030 その場合には _ble_keymap_vi_repeat{,_irepeat} 配列を必ず設定させるようにする。 64031 64032 [実装] 64033 64034 * 後は一つ一つのコマンドについて確認を行って行くことにする。 64035 64036 - nmap ~ OK 64037 - nmap p P OK 64038 - nmap rx Rx OK 64039 - nmap J gJ OK 64040 - xmap rx Rx OK 64041 - xmap p P OK 64042 - xmap I A OK 64043 - lib/vim-surround: ysiw" OK (surround.vim とは異なるが想定した動き) 64044 - lib/vim-surround: cs"b OK (同上) 64045 64046 どうも実装した後で気付いた事だが、lib/vim-surround.sh の ysiw" に対して 64047 . を実行すると、最後の " の部分に関しては前回のものが使われるのではなくて、 64048 改めて入力を求められる様である。 64049 64050 更に、cs"b などについても入力が求められるが 64051 cs<空><入力したもの> という解釈になる様だ。 64052 これはバグなのではないかと思っている。 64053 64054 * 一段落したら set-previous-edit / end-edit-area と統合できないか考察する。 64055 実装してみた結果、考察するまでもなく、これは全然統合できない。 64056 64057 2017-11-01 64058 64059 * vi-mode: . 実装 (5) 挿入モードの操作の記録 [#D0556] 64060 64061 | - ihello<C-c>. とすると o の前に再度 hello が挿入される 64062 | - ahello<C-c>. とすると末尾に hello が挿入される 64063 | つまりどのような挿入モードによって挿入が起こったかを覚えている。 64064 | - 更に c$123<C-[>. を実行してみるとちゃんと削除してから挿入するまでを一通りの編集として記録している。 64065 | - 挿入モードの途中でカーソルを動かして更に編集を行うと、 64066 | 最後にカーソルを動かしてからの編集が繰り返される。 64067 | 最初に指定した繰り返し回数の引数は忘れられるようだ。 64068 | またこの場合には a で始めたとしても、i と同様の状態になる。 64069 64070 動作を調べる 64071 64072 a<C-w><C-[>... とするとちゃんと単語毎に削除される。 64073 つまり削除された文字数ではなくてちゃんとキーの列で記録されている。 64074 64075 という訳で {count}i の為の記録と同じ枠組みで記録した物を用いる。 64076 と思ったがよく考えると quoted-insert が正しく再生されないのではないか? 64077 試してみた所やはりうまく再生できていない → #D0554 で修正した。 64078 この修正によりキーの列として記録するのではなくて、 64079 実行したコマンドの列として記録することになった。 64080 64081 - done: さて . による繰り返しに対応する為には 64082 先ず初めに imap-repeat を _ble_keymap_vi_irepeat_count の有無に拘らず 64083 常に記録する様に修正する必要がある。 64084 そして white list にないコマンドが来た場合には中身をクリアする。 64085 64086 - done: どうやら ihello<C-o>. とやると hello の挿入が繰り返される訳ではなく、 64087 それより前の操作が繰り返される様だ。試してみると、<C-o> では繰り返しは登録されない。 64088 更に現在の挿入モードが ciw などによって導入されたものの場合にはどうだろうか。 64089 この場合も ciwhello<C-o> とやった時点では ciw は繰り返しに登録されていない。 64090 つまりオペレータが呼び出されたと言ってもその時点では記録されていないのだ。 64091 64092 これを記録する為には、オペレータを呼び出した後に記録を行う時、 64093 _ble_decode_key__kmap == vi_imap の時には、repeat に直接記録するのではなく、 64094 一旦 _ble_keymap_vi_repeat_insert などに記録を行う様にし、 64095 最終的に <C-[> または <C-c> を行う時に実際に記録する様に修正する必要がある。 64096 64097 - done: また <C-o> や途中の non-white な操作の際には、 64098 この内容を ble/widget/insert-mode か何かに書き換えてしまえば良い。 64099 →これは ble/keymap:vi/repeat/clear-insert の中で処理することにする。 64100 64101 - done: 更に .insert-mode を呼び出す各 widget で ble/keymap:vi/repeat/clear-insert を呼び出すようにする。 64102 64103 - ok: また、最終的に <C-[> または <C-c> で抜ける時に、最後の <C-o> 以降の内容が記録される。 64104 これは <C-o> を行う時に reset すれば良い。実の所 <C-o> から insert mode に戻る時に 64105 何れにしても reset されるのでこの点に関しては気にしなくても良い。 64106 64107 | 挿入モードの途中でカーソルを動かしてもOK 64108 | (注意: これは i の引数による繰り返しがキャンセルになる状況である) 64109 64110 これについても対応する。 64111 64112 というか、実際に試してみると、カーソルを動かした瞬間に記録される様だ。 64113 例: iA<C-c>ihello<left><C-o>. とすると . で ihello<C-[> が実行される。 64114 また、その後でカーソルを動かしただけで (挿入を伴わずに) <C-c> or <C-[> を押した場合には、 64115 改めて記録されるということはない様だ。つまり clear-insert では単に repeat_insert を空にして、 64116 record-insert において repeat_insert が空の時には repeat_irepeat 操作が 64117 1 つ以上記録されているときに限って記録を行う様にすれば良い。 64118 64119 実際に <C-o> における clear-insert でも同様に動作するようだ。 64120 つまりそれ以降に操作がなければ最終的には記録されない。 64121 例: iA<C-c>ihello<C-o>.<C-[>. とすると最後の . でも A が入力される。 64122 つまり最後の <C-o>. 以降に何も挿入操作が行われないので、 64123 <C-[> においては何も新しく登録されない。 64124 64125 取り敢えず実装したので今度は動作確認が必要である。 64126 64127 x resolved: ahello<C-c>. で動かしてみた所 . で挿入モードには入るが実際の挿入操作は行われない様だ。 64128 というかノーマルモードに戻るという動作すらしていない。 64129 →これは widget 実行後に vi_imap かどうかの確認をするのに KEYMAP を使っていたのが駄目だった。 64130 現在の keymap は _ble_decode_key__kmap で確認するべき。修正した。 64131 64132 x resolved: ahello<C-c> の後に、何故か . を実行する度に挿入操作が一つずつ減っていき、 64133 最後には誤った添字のエラーメッセージが発生する。 64134 このエラーメッセージは ble/keymap:vi/imap-repeat/pop で出ている。 64135 64136 これは imap-repeat/pop が normal-mode で呼ばれているのが原因? 64137 取り敢えず /normal-mode を手で呼び出している箇所で 64138 imap-repeat に 0:ble/widget/dummy を push する様にする。 64139 64140 o 繰り返し (. に対する引数) はちゃんと動いている。 64141 o 3ahello<C-[> で元々指定した引数 3 も動いている。 64142 o ciwcheck<C-c><別の単語に移動>. もちゃんと動いている。 64143 o a<C-w><C-[>... も動いている。 64144 64145 x resolved: iA<C-c>ihello<left><C-o>. で A が挿入される。 64146 ここは hello が挿入されるべきである。 64147 これは記録を実行するのを忘れていた。修正した。 64148 64149 x resolved: 試していて気付いたのが vim では iA<C-c>i<C-o>. とした後にちゃんと元の挿入モードに戻る。 64150 64151 % normal-mode の呼び出しを分解して無駄なものを除きつつ、 64152 % 有効な部分だけ記述しようと思ったが、存外に複雑である。 64153 % やはり norma-mode の呼び出しはそのままにして、外部から動作を修正する方が良さそうだ。 64154 64155 うーん。これは挿入モードの繰り返しに限らず . 一般の問題の様だ。 64156 実際に繰り返しを行う前に _ble_keymap_vi_single_command を保存して、 64157 更に最終的に vi_nmap に戻るようにして、 64158 その上で _ble_keymap_vi_single_command を復元するという具合に修正した。 64159 64160 o iA<C-c>ihello<C-o>.<C-[>. の動作も OK 64161 64162 * vi-mode: . 実装 (4) xmap における operator 操作の記録と復元 [#D0555] 64163 64164 * done: 次に実装するのは xmap の場合の復元である。 64165 64166 | なんと矩形削除についてもちゃんと再現される。 64167 | 因みに矩形削除では引数は無視されるが、. に引数を指定するとどうなるか。 64168 | 試してみた所、無視された。つまり . の引数は繰り返し回数では決してなくて、 64169 | 以前に実行したコマンドに渡す引数に他ならないのである。 64170 | 64171 | 矩形の大きさは何処で保持されているのだろうか。 64172 | 完全に独立に保持されているのか、それとも gv や 1v と共にしているのか。 64173 | 調べてみた所、先ず gv と 1v は完全に独立になっている。 64174 | gv は <C-c> でも記録されるが 1v に関してはキャンセルすると記録されていない。 64175 | % というか vim で試すと 1v は前回の編集があったときの大きさであって、 64176 | % 前回の矩形範囲ではないような気がする。現在の実装は怪しい。 64177 | % →よく考えたら現在の実装でも 1v は前回の編集が合った時の大きさである。 64178 | 64179 | また gv は開始行と終了行 (追跡) とそれぞれの行での列 (追跡なし) 64180 | を覚えている。つまり、mark で覚えている。というか実際に `< と `> で囲むだけ。 64181 | 一方で 1v は高さと幅だけ覚えている。 64182 64183 .save-visual-state と 1v によるデータの記録が同時に行われるのだとすれば、 64184 単に .restore-visual-state を呼び出して vi_xmap を push すれば良さそうである。 64185 実装してみたが、よく考えると .save-visual-state と 64186 1v によるデータの記録のタイミングは異なる気がする…。 64187 64188 <C-v>jll~<C-v>jjly1v<C-c>. とやってみると両者が独立に記録されていることが分かる。 64189 つまり、先の調査の以下の部分は誤りであったということが分かった。 64190 64191 | % ところで、矩形繰り返しが 1v と独立なのかどうかについて調べるためには、 64192 | % 編集操作を伴わずに 1v の範囲を変更すれば良い。そのようなことは可能か。 64193 | % 調べてみると ble/widget/vi_xmap/.save-visual-state は編集を伴うときにしか呼び出されない。 64194 | % つまり、矩形繰り返しが 1v と別かどうかを調べる方法はない気がする。 64195 | % 逆に言えば .save-visual-state を参考にして操作を繰り返せば良いということになる。 64196 | % (或いは、実際に .restore-visual-state を呼び出して処理するというようにすれば良い)。 64197 | 64198 | →マニュアルの記述に反して y は繰り返し対象ではないようである。 64199 | 1v の場合には y による領域も記録されるから、これを以て繰り返しと 1v の記録が独立かどうか確かめられる。 64200 | 実際に試してみると両者は独立に記録されているということが分かった。 64201 64202 さて。1v の記録 (.save-visual-state) ではどのような変数を用いているか。 64203 _ble_keymap_vi_xmap_prev という変数一つに記録しているようである。 64204 従って、この変数をすり替えて .save-visual-state/.restore-visual-state を呼び出せば良い。 64205 64206 と思ったが、repeat/record が呼び出される頃には既に _ble_edit_ind などの位置は変更されているので、 64207 むしろ独立に .save-visual-state を呼び出すのではなくて、 64208 .save-visual-state によって記録された領域をコピーして来るので良い。 64209 但し、その為には repeat/record を呼び出すときに必ず .save-visual-state が呼び出し済みである必要がある。 64210 これに関しては vi_xmap で編集が起こるときには必ず .save-visual-state が呼び出されるはずだから恐らく大丈夫である。 64211 64212 ところで、一番下の行などで . を実行したことによって、 64213 記録されたのよりも小さな領域に対してしか繰り返し処理を実行できなかった時、 64214 更にそれより後に実行する繰り返しでは領域が狭められるということはあるのか? 64215 →調べてみると初めに記録された領域の大きさを使い続けるようだ。 64216 記録された領域の大きさが改めて設定されることはないようだ。OK 64217 64218 x resolved: xmap 動かない。と思ったら WIDGET の復元に失敗していた。修正した。 64219 64220 * vi-mode (imap): 挿入モードの引数で C-q ? による繰り返しが正しく再生されていない。 [#D0554] 64221 これはキーの記録を keymap のレイヤーで実行している為に、 64222 _ble_decode_key__hook, _ble_decode_char__hook によって 64223 読み取られたキー・文字を取得できていないためである。 64224 64225 一旦は quoted-insert の中で keylog に登録することを考えたが、 64226 よく考えてみると hook をかけるのは key に対してではなく char に対してである。 64227 key に登録するのだと振る舞いが変わってしまう。 64228 64229 a 一つの方法は再生時には quoted-insert は key に対して 64230 hook する様に動作が変わる様にする。 64231 64232 aa 動作の切り替えは例えば、keylog から C-q を pop して 64233 特別な key (例えば s-q) を push する。 64234 s-q に対して key に対して hook する quoted-insert-key 的な widget を登録する。 64235 64236 x これは keymap に対して vi-insert/quoted-insert を登録するだけでは動かないので分かりにくい。 64237 といって vi-isnert/quoted-insert の内部で s-q に bind するのは効率が悪い。 64238 x また、s-q に本当に何かを bind したい時に困る (そのような場合は余りありそうにないが可能性が全くないわけではない)。 64239 64240 ab 再生時に特別なローカル変数を定義して、 64241 その変数が非空白のときには key に対して hook する様に動作を変更する。 64242 64243 b 或いは、keylog として記録するのではなく charlog として記録する。 64244 64245 charlog で記録する場合には、最後の normal-mode を呼び出す発端となったイベント 64246 (C-[ など) が、何文字の char によって引き起こされたのかを調べる方法が必要になる。 64247 これによって最後の C-[ を除去することが可能になる。 64248 64249 ba 一つの方法は最後に記録した時の長さを覚えておいて、 64250 それ以降に増えた部分を今回のイベントを引き起こすのに関与した文字と解釈する。 64251 64252 またこの方法は ble-decode に手を入れる必要がある気がする。 64253 というのも、keymap 経由だとどんなに頑張っても key の情報しか得られないからである。 64254 64255 c もしくは widget の列として記録を行う。 64256 この時には KEYS 及び呼び出す WIDGET の名前の配列として記録する。 64257 quoted-insert は self-insert に変換することで動作する様にする。 64258 64259 この方法の方が自然である。例えば keymap が変更された後でもこれなら同じように動作する。 64260 問題は KEYS と WIDGET だけ保存すれば完全に同じように動作するのかどうかという事である。 64261 うーん。多分動作する? 64262 64263 % しかしよく考えてみると vim の qx ... q @x で "レジスタ" に操作を記録する仕組みとの整合性も考えなければならない。 64264 % そう考えるとむしろ charlog で記録した方が良いのかもしれない。 64265 % 64266 % うーん。というかレジスタに記録する機能は挿入モードに限らず全体に渡って適用される。 64267 % そう考えると、挿入モードの繰り返しとの整合性を考える必要は全く無い。 64268 64269 思うに c の方法が最も綺麗である。 64270 しかしその為には挿入モード繰り返しの記録と再生を完全に再実装する必要がある。 64271 64272 2017-10-31 64273 64274 * vi-mode (xmap): o O [#D0553] 64275 64276 動作を確認する。v, V では o, O に違いはない。 64277 単に mark と ind を交換するだけの様な気がする。 64278 C-v においては o は mark と ind を交換する。 64279 O は同じ行内で右端から左端または左端から右端に移動する。 64280 - 選択領域の幅が1文字しか無いときには動かない。 64281 - 最初の行または最後の行の端に中途半端な全角文字が含まれている場合には 64282 幅が拡張する方向でどんどん大きくなる。例えば 64283 64284 | echo ああああああああああ 64285 | echo aああああああああああ 64286 64287 のような形にしておいて適当なところで C-v で囲んで、 64288 O を連打すると少しずつ幅が拡大していく。 64289 - 末尾拡張の時に o または O を押すと末尾拡張は解除される。 64290 64291 O はどの様に実装するのが良さそうか。 64292 一番簡単な実装方法は矩形領域を実際に切り出して、 64293 mark, ind をそれぞれ行内で丁度反対側の文字になるように移動することである。 64294 64295 % もう少し効率的な実装方法にするとすれば、 64296 % 矩形領域の最初の行と最後の行についてだけ範囲を計算すれば良い。 64297 % しかし、それは似たような処理の再実装になるのでやはり避けたい。 64298 % もし効率化を測るとすれば extract-block にオプションとして、 64299 % 最初の行と最後の行に関する情報だけで良いというものを用意する手があるが、 64300 % 現在の所そんなに遅くて困るということもない気がするので、 64301 % 取り敢えずは直接 extract-block を呼び出すという実装方法で問題ないだろう。 64302 % (或いは、そのようなオプションを簡単に導入できるのだとしたら実装しても良いが) 64303 % 64304 % 取り敢えず extract-block で実装したら動いた。 64305 % そしたら急に面倒になったので効率的な実装は問題になるまでは考えない。 64306 64307 実装した。動いている。 64308 64309 o ちゃんと全角文字があるときに領域が拡大されていく振る舞いも再現している。 64310 64311 x resolved: 末尾拡張のときの振る舞いについて少し異なる。 64312 どうやら末尾拡張を解除した後で、領域を決めて移動先を決定するようだ。 64313 →修正した。 64314 64315 x resolved: 更に O の結果としてカーソルが行末に来ることも許される。 64316 驚くべきことに(?)交換によって mark が行末に来ることも許される。 64317 これは sfill があるかどうかで判定すれば良いだろう。 64318 sfill が 1 以上であれば行末に移動する。 64319 →修正した。試した。期待通り動いている。 64320 64321 _ble_edit_mark が行末に来るということは想定していなかったが、 64322 これによって既に書いた機能について何か問題が生じる可能性はあるか。 64323 つまり、_ble_edit_mark の位置は行末ではないという仮定を行っている箇所があるだろうか。 64324 64325 o 例えば keymap:vi/mark の枠組みで記録される列の位置に関してはどうだろう。 64326 実のところ、これについては復元時に行の長さが変化している可能性も考えて、 64327 位置の調整が行われるので、復元時に nmap として不正な位置にカーソルが来ることはない。 64328 また gv などで復元する場合を考えるとむしろ行末に mark を設定できるべきである。 64329 つまり keymap:vi/mark についてはそもそも行末に置けないという制限はないはずなので、問題ないということ。 64330 64331 o 他に _ble_edit_mark が影響を与えるのは xmap における範囲の決定である。 64332 これについても mark/index を区別せずに実装しているはずなので、 64333 mark が index と同様に行末に来たとしても問題は起こらない筈である。 64334 64335 o 他には vi-mode で _ble_edit_mark が意味を持つことは無い気がする。 64336 64337 まあ、恐らく大丈夫だろう。問題が出てきたらその時に対処する。 64338 64339 * vi-mode: どうやら yiw の振る舞いが異なる [#D0552] 64340 64341 ble.sh では現在 ///日本語 は一つの塊だと考えているが、 64342 vim では "///" と "日本語" の二つに分けて考えているようだ。 64343 vim のマニュアルを見てもこの振る舞いについては書いていない。 64344 非空白文字の連続としか書かれていない。 64345 64346 調べてみると "日本語ひらがなカタカナ" は 64347 "日本語" "ひらがな" "カタカナ" の3つに分割されるようである。 64348 つまり Unicode の Category を見て判定している様である。 64349 これは厳しい気がする。 64350 64351 取り敢えずの簡便な実装としては ASCII の記号と、 64352 それ以外の非空白文字を区別して実装するという事である。 64353 ASCII の記号は [!-/:-@[-`{-~] で表される。対応した。 64354 64355 2017-10-30 64356 64357 * vi-mode: . 実装 (3) 取り敢えずの記録の仕組みと再実行の仕組み [#D0551] 64358 64359 | - diw もちゃんとそのように記録される。 64360 | つまり、ただ単に削除範囲の広さを記録するのではなくて、 64361 | どの様な motion に伴って削除されたかの情報も記録される。 64362 64363 どの様に実装したら良いだろうか。 64364 単にキーシーケンスを覚えるという方法は通用しない。 64365 visual mode で実行したコマンドは visual mode で実行しなければならないし、 64366 normal mode で実行したコマンドは normal mode で実行しなければならない。 64367 挿入モードに入って文字列を入力して抜けたら、挿入モードの種類も含めて再現する必要がある。 64368 64369 うーん。取り敢えず、set-previous-edit が呼び出されるのと 64370 同じタイミングで記録を行うようにする。 64371 64372 | a 一つの一番簡単そうな方法は set-previous-edit が起こった時に、 64373 | それを呼び出したコマンド COMMAND を見るというものである。 64374 | この情報だけでどの程度までコマンドを知ることができるだろうか。 64375 | 64376 | 先ず、diw などの場合には text-object が二文字目を受け取った時に実行される。 64377 | この二文字目は _ble_decode_key__hook を介して呼び出されるため、 64378 | 実は COMMAND 情報を抽出することができない。 64379 | 或いは、ble-decode を修正して hook の場合には、 64380 | hook に設定されていた文字列を指定する方法を提供するようにする。 64381 | 64382 | うーん。実際の vim の実装はどうなっているのだろう。 64383 | vim の場合には非同期に実装する必要はないから、 64384 | 呼び出されたコマンドの中で次の文字も全て処理できる。 64385 | つまり、現在の呼び出しの関数というのは容易に分かる。 64386 | ただし、読み出した文字などは全て記録しておく必要がある。 64387 | 64388 | 個別コマンドについて文字を記録するのは不毛だと考えれば、 64389 | 実のところ入力されたキーの列を記録する方が現実的なのかもしれない。 64390 | とは思ったが、挿入モードの途中でカーソルを動かした時の動作などを考えると、 64391 | やはり単純にキーの列を記録すれば良いというわけでもないように思われる。 64392 | 64393 | やはり set-previous-edit からコマンド内容を調査するという方法で頑張ってみる。 64394 | ble-decode では _ble_decode_key__hook を一旦変数 hook に移してから実行している。 64395 | この hook を BLE_COMMAND, BLE_WIDGET などのような変数に入れて公開することにする。 64396 | そしてこの変数を set-previous-edit は記録するようにする。 64397 | 但し、KEYS やそれまでに用意したローカル変数の様子なども一緒に記録する必要がある。 64398 | KEYS は既定で保存することにして、もし特別に保存する必要があるものがある時には、 64399 | ble/keymap:vi/save-widget/* という関数を用意することにすれば良い。 64400 | set-previous-edit はその関数が存在するかどうかを調べ、 64401 | もし存在すればそれを呼び出すことにすれば良い。 64402 | 64403 | 保存専用の関数名には議論の余地がある。 64404 | ble/widget/vi-command/text-object.hook:save などでも良いかもしれない。 64405 | 64406 | 問題点は実際に set-previous-edit が呼び出されるに至るときには、 64407 | 既に _ble_edit_arg などの変数の値は使用済みとして消去された後であることだ。 64408 | これの解決方法は4通りある。 64409 | 64410 | | a get-arg した瞬間にはまだクリアしないことにして、 64411 | | widget の最後でクリアする関数を呼び出すようにすること。 64412 | | 64413 | | これの問題点は widget の内側で更に別の widget を呼び出しているときに、 64414 | | 引数が残っているがために繰り返し引数が解釈されてしまうことである。 64415 | | 更に内側の widget によって引数が消去されてしまうので、 64416 | | この場合には引数を知ることができなくなってしまう。 64417 | | 64418 | | 内側の widget を実行するときには何らかのフラグを立てるようにして、 64419 | | get-arg によって引数が読み取られないようにするという手もあるが、 64420 | | 複雑になるし、今後の widget 実装をを間違える可能性がある。 64421 | | 64422 | | b 或いは、get-arg する瞬間に引数を別の箇所に退避するという手もある。 64423 | | 64424 | | この方法を使うと widget の内側で別の widget を呼び出しても、 64425 | | 引数が繰り返し使われてしまうという問題点は防げる。 64426 | | しかし、内側の widget で get-arg を呼び出すと 64427 | | そのときに折角退避した引数が上書きされて消えてしまう。 64428 | | 64429 | | つまり、退避はただ1回しか実行しないようにする仕組みが必要である。 64430 | | そのためにフラグを設定するというようにすると、 64431 | | 結局 widget 実装の注意点は a と余り変わらない。 64432 | | 64433 | | 更に、内部で ble-decode-key を呼び出している場合の処理はどうなるか。 64434 | | →その場合は改めて BLE_COMMAND なり何なりが設定されるので、 64435 | | 混乱が起こることはない。 64436 | | 64437 | | c widget の呼び出し元で _ble_edit_arg などの値を退避して記録する 64438 | | という方法もある。しかし、それは ble-decode で退避を行うということを意味する。 64439 | | 一応 .before_command という仕組みはあるが、これは _ble_decode_key__hook に対しては効果がない。 64440 | | 64441 | | 更に、内部で ble-decode-key を呼び出している場合は…これは気にしなくても大丈夫そうだ。 64442 | | 64443 | | d 或いは arg flag reg の3変数を、get-arg 以外の用途で使用することを禁止するという手もある。 64444 | | そうすれば set-previous-edit の中で単に arg flag reg を参照すれば、 64445 | | それが実際に使われる引数の値であると考えて良いことになる。 64446 | | 64447 | | 後で widget を実装するときに誤って別の用途で使用しないように、 64448 | | ARG FLAG REG の様に大文字の変数名に変更するという手もある。 64449 | | しかし、それはそれでうるさい。 64450 | | 64451 | | また関数で受け渡された変数も arg flag reg の名前を継承しているが、 64452 | | これらの変数に関しても同じ名前を使って良いのかどうかということである。 64453 | | 64454 | | - 特に問題になるのは引数を渡すときに、$((-arg)) などのように修正して渡す場合である。 64455 | | このような場合には受け取り側は arg ではない変数名で受け取るように修正しなければならない。 64456 | | あくまでも一番外側の widget を呼び出すときの _ble_edit_arg などなどを記録するためである。 64457 | | 64458 | | - 更に引数を握りつぶして何も渡さないということもある。 64459 | | この場合も実のところ引数を記録する必要はなかったりするのかもしれないが、 64460 | | (或いは、そもそも set-previous-edit が発生しない) 64461 | | やはり念のため元々の引数を復元するようにしたいものである。 64462 | | 64463 | | - うーん。"オペレータの引数" という概念にも arg を使っているが、 64464 | | これは別名にした方が良い気がする。 64465 | | と思ったがオペレータ内部では一般に set-previous-edit は起こらないような気もする。 64466 | | 基本的に自分で set-previous-edit を呼び出すか end-edit (call-operator) で設定される。 64467 | | 従って、call-operator の引数名だけ直せばそれで良い。 64468 | | ところが、call-operator の引数名 arg を修正するのであれば、 64469 | | やはり operator の arg も修正する方が自然である。 64470 | | 64471 | | 色々考え合わせるとやはり get-arg のときだけ大文字にして、 64472 | | それ以外の引数で受け取ったりする引数名は小文字に統一するのが、 64473 | | 書き換えとして最も安全なのではないかと思われる。 64474 | | 枠組みとしても引数が直接透過して見えるので、それが自然である。 64475 | 64476 | d の方針にする。特に arg flag reg は一番最初に取得するときに大文字にする。 64477 | 引数で受け渡しするときには今まで通り小文字のままにする。 64478 | 64479 | b set-previous-edit と独立に各コマンドで . 情報を記録するようにする可能性はあるか。 64480 | 64481 | 単純なコマンドの場合にはそのまま記録する。 64482 | motion の場合には通常は何もしなくても良い。 64483 | omap から motion/txtobj に貼る時には編集が起こる。 64484 | これらに対応するためには motion コマンドにおいて、 64485 | flag が設定されている場合には arg flag reg とそのコマンドを記録するという事になる。 64486 | flag が設定されているにも拘らず失敗して記録されないということはあるだろうか。 64487 | 或いはキーを非同期に読み取る為に 27 を返してそのまま終了するという場合もある。 64488 | 64489 | うーん。motion の場合に問題になるとすれば、 64490 | 或る widget を実装する為に別の widget を呼び出す場合があるということである。 64491 | その場合には呼び出し元の widget を繰り返しとして登録するように工夫しなければならない。 64492 | しかし、基本的には _ble_edit_arg, _ble_keymap_vi_opfunc などを設定しない限りは、 64493 | 編集が発生するということはないから、注意が必要な箇所はすぐ分かる。 64494 | 64495 | あと、問題になるとすれば書き込み専用のレジスタに書き込もうとして失敗した時などの動作である。 64496 | 試してみた所、そのような場合には、やはり . の繰り返しコマンドとしては登録されない。 64497 | 更に、*.impl で実装している場合には、呼び出し元で設定しなければならないので、 64498 | 実際に変更があったかどうかの情報を呼び出し元に通知しなければならない。 64499 | これはに終了ステータスによってよって行うのが自然であるが、 64500 | 終了ステータスに別の意味を持たせている場合があるかもしれず、その場合には使えない。 64501 | また、全般に終了ステータスを確定させるように書き換えが必要になる。面倒だ。 64502 | 64503 | ただ、この . の実装とは独立に終了ステータスを確定させるというのはあった方が安心な気もする。 64504 | → #D0543 64505 | 64506 | うーん。一番外側で情報を記録するようにすると問題になるのは、 64507 | オペレータが中で実際に何をしたか分からないということである。 64508 | もしかすると opfunc として何もしないものが登録されているかもしれない。 64509 | その時にも . の対象とするのだろうか。 64510 | Vim script では opfunc は結局キーの列として登録される。 64511 | だとすると何か意味のある操作をするとすれば :func() のようになる。 64512 | この時 : なので、これは . の繰り返し対象として登録されない気がする。 64513 | 64514 | しかし実際の vim の動作はどうであれ operator が呼び出されれば記録するというのは 64515 | 一つの一貫した動作であるのでそのように動作するのが適切な気もする。 64516 64517 やはり a の方針で行くことにする。 64518 64519 b の方法だと、コマンドが成功したかどうか、 64520 オペレータが処理を実行したかどうか (例えば y は繰り返し対象ではない) 64521 などを一番外側の WIDGET に伝達するのは困難なので、苦しい。 64522 set-previous-edit-area の中か、またはそれと同じ箇所で記録の処理を行う方が現実的と判断する。 64523 64524 [実装計画A] 主に set-previous-edit で記録する 64525 64526 * done (→ #D0550): 取り敢えず現在のコードの整理をした。 64527 ble-decode.sh 側で WIDGET 及び KEYMAP を提供することにした。 64528 また vi.sh において get-arg にて取得されるパラメータは 64529 ARG FLAG REG という名前の変数に格納することにした。 64530 64531 * resolved: set-previous-edit で色々記録を行う。 64532 これは set-previous-edit で行うのではなくその前後で独立に実装することにした。 64533 もし後で統合できそうならば統合するが、初めは独立に実装する。 64534 64535 * done: 再実行するコマンドを取り敢えず何も考えず実装する。 64536 64537 [振る舞い] 64538 64539 振る舞いについて再度実装しながら確認していくことにする。 64540 64541 * done: レジスタの記録 64542 64543 % 先ず "x などのレジスタ指定は記録されるのか。 64544 % または改めて . に対して指定されたレジスタ指定はどのように使われるのか。 64545 % 64546 % 先ず記録時にレジスタが指定されていた場合には 64547 % . による繰り返し時にもそのレジスタが使用される。 64548 % . に対して指定されたレジスタは無視される。 64549 % 記録時にレジスタが指定されていなかった時には、 64550 % もし . に対してレジスタが指定されていたらそれを使う。 64551 % 記録時に既定の "" のレジスタが指定されていた場合には、 64552 % もし . に対してレジスタが指定されていたらそれを使う。 64553 % 64554 % まとめると、記録時に "" 以外のレジスタが指定されていたらそれを使う。 64555 % それ以外のとき、. 実行時にレジスタが指定されていたらそれを使う。 64556 % 64557 % 現在の実装では "" を指定した時はレジスタ指定は削除される。 64558 % 丁度この振る舞いに符合するので都合が良い。そのままにする。 64559 64560 これには勘違いが入っていた。"" であっても指定されればそれが使われた。 64561 なので "" が指定された場合でも _ble_keymap_vi_reg は空欄にせずに 34 を設定することにした。 64562 64563 | またレジスタが指定されていないときに、レジスタを指定して . を呼び出すと、 64564 | それ以降の . の呼び出しでは新しく指定したレジスタが使用される様だ。 64565 | 一度レジスタが指定されれば、それ以降はレジスタが変わることはない。 64566 | それは "" によるレジスタの指定であっても同様である。 64567 | つまり、この点に於いて "" とレジスタを指定しないことはやはり異なる。 64568 64569 記録時にレジスタが指定されていたらそれを使う。 64570 それ以外のとき、. 実行時にレジスタが指定されていたらそれを使い、 64571 . の実行に成功したらそのレジスタを新しく記録する。 64572 64573 * done: 引数の記録 64574 64575 既に、. に対して引数が指定されていた場合にはそれが優先されることを確かめた。 64576 64577 | 3x. とすると 3 文字さらに削除される。 64578 | 3x1. とすると 1 文字さらに削除される。 64579 | つまり、. に引数を指定しない場合は元の引数を使い、 64580 | もし . に引数を指定する場合には代わりにその引数を用いる。 64581 64582 例えば 3d2l の様にした場合には 6 が記録されて、 64583 . に指定された引数で置き換えられるのか、 64584 或いは、3 x 2 と記録されて (. に指定された引数) x 2 の様になるのか。 64585 確かめてみると全体 6 が (. に指定された引数) に変わる様だ。 64586 つまり記録する時には全体の引数で記録すれば良い。 64587 64588 | またもうひとつ気づいたことは、. に引数を指定した場合には、 64589 | 更に後続の . では新しく指定した引数が用いられるということである。 64590 | これは元々引数が記録されていたときでも記録されていなかったときでも同様である。 64591 64592 つまり . に指定した引数は記録する。 64593 64594 * done: フラグの記録は気にしなくて良い 64595 64596 これは後で任意に指定できるものではないので (というか omap でしか指定できないが、 64597 omap には . は存在しないので) 優先順位だとか上書きされるかだとかについて気にする必要はない。 64598 KEYMAP や KEYS についても、WIDGET に紐付いているもののはずだから上書きしない。 64599 64600 * done: . が失敗したときに引数やレジスタを上書きするかどうか 64601 64602 | また . が失敗したときの動作についても確認して置かなければならない。 64603 | →一番下の行で dj をすると失敗する。これを利用して . を失敗させると、 64604 | 引数の上書きは起こらないようである。つまり、引数の上書きは、 64605 | 実際に set-previous-edit-area が呼び出されたときに行えば良い。 64606 | →レジスタについても失敗したときに新しく設定されるかどうか確認する。 64607 | レジスタについても失敗したときには新しく設定されない。 64608 64609 →. を呼び出したときの ARG, REG については成功したときに記録する。 64610 記録されている ARG/REG と区別するために repeat_arg, 64611 repeat_reg というローカル変数に記録することにする。 64612 64613 * KEYMAP の記録に関して: 64614 64615 | % 更に気付いたことだが、呼び出した時の keymap に依存して振る舞いを変えるコマンドが存在して、 64616 | % しかし、呼び出しの途中で ble-decode/keymap/push, pop を実行することがある。 64617 | % この時 set-previous-edit の中から元々の keymap を復元する必要が生じる。 64618 | % これに関しては .invoke-command にて (zle に倣って) KEYMAP なる変数を定義すれば良いのではないか。 64619 | 64620 | - KEYMAP というか _ble_decode_key__kmap によって全く異なる動作になるのは 64621 | vi-command/operator ぐらいである。 64622 | - 他に text objects が xmap で異なる動作をするが、 64623 | これは範囲の変更のみで編集を伴わないので . のために記録されることはない。 64624 | - それ以外については . で繰り返されるとしても _ble_decode_key__kmap 64625 | によって振る舞いが変わって自然なものだけである。 64626 | 64627 | 従って考えるとしたら vi-command/operator の動作を如何に再現するかについて考えれば良い? 64628 | よく考えてみると、widget を呼び出した後に _ble_decode_key__kmap が変更されて、 64629 | その後で vi-command/operator が呼び出された場合、 64630 | vi-command/operator が参照するべきなのは widget 呼び出し時の KEYMAP ではなくて、 64631 | vi-command/operator 呼び出し時の _ble_decode_key__kmap ではないだろうか。 64632 | 但し、そのような場合には WIDGET として記録されるのは vi-command/operator ではなくて、 64633 | 一番最初に呼び出された widget のはずなので記録される KEYMAP について気にしても仕方がない。 64634 | 64635 | ここでの問題は何だったか。KEYMAP を記録したとしてそれをどのように利用して、 64636 | 元々の処理を再実行するかということであった。 64637 | 一つの方法は元々の KEYMAP で記録した keymap に一時的に切り替えて WIDGET を呼び出すというもの。 64638 | しかし、これは keymap の状態遷移がよく分からないことになる。 64639 | 一時的に切り替えたものは元に戻さなければならないが、 64640 | 途中で keymap が更に切り替わったらどうすれば良いのか。 64641 | 64642 | よく考えてみると . を呼び出せるのは nmap からだけである。 64643 | omap/imap/cmap からは呼び出せない。xmap についても確かめてみた所 . は呼び出せない。 64644 | 一方で、編集が起こるのは nmap/omap/xmap/imap のみである。 64645 | nmap で記録されたものに関しては keymap について気にせずに直接呼び出せば良い。 64646 | omap/xmap に関しては変更が起これば自動的に nmap に落ちてくるはずなので 64647 | 一旦 ble-decode/keymap/push してしまえば問題ない。 64648 | また xmap の . に関しては事前に選択範囲を復元するなどの特別な処理が必要になることに注意する。 64649 | imap に関しては完全に特殊なので keymap の復元がどうとかそういうものでもない。 64650 64651 つまり記録した KEYMAP は状態復元に使うというよりは、 64652 repeat を呼び出すときの特別の処理のときに参照するという実装になるだろう。 64653 64654 * 実は y は . の繰り返し対象にはならない [要考察] 64655 64656 つまり set-previous-edit-area で一括して記録するということを想定していたが、 64657 これについては再考しなければならない。 64658 更に vim では 0dh などとして 0 文字削除にしたときでも . で dh を繰り返せる。 64659 一方でこのとき `[ 及び `] は設定されない。 64660 つまり、これは set-previous-edit-area と . の記録は全く別系統であるということの示唆になっている。 64661 やはり、set-previous-edit-area の中で記録を呼び出すというのは使えない。 64662 64663 うーん。それでも set-previous-edit-area を呼び出すのと 64664 同じ箇所で記録するかしないかを判定するという様に設計するのは有効のはずである。 64665 これについては再度 (set-previous-edit-area を多目的に拡張する方向性も含めて) 後で考え直すことにする。 64666 64667 うーん。どの様に対処するべきか。 64668 64669 | a operator で実際に編集が行われたかどうかと、 64670 | edit-area の記録は独立に行う。 64671 | 64672 | この方法の問題点は面倒ということである。 64673 | 特に、edit-area の場合には _ble_edit_str.replace, reset 64674 | における hook を利用して自動的に operator 内の編集を検出できたが、 64675 | 実際に編集を行う操作が operator 内で呼び出されたかどうかは、 64676 | (実際に文字列に変更が行われなかった場合に) 検出できない。 64677 | これを正しく実装するためには operator 内で 64678 | "記録に値する何かを実行した" というフラグなどを明示的に立てる必要がある。 64679 | 64680 | b commit-edit-area による編集範囲の登録と、 64681 | 実際に行われた編集に基づく編集範囲の記録を独立に行い、 64682 | set-previous-edit-area を呼び出すときに両者を合成する? 64683 | 64684 | この方法は問題が色々あるので駄目。 64685 | 64686 | x まず初めに独立に記録を行って後で合成することは不可能である。 64687 | それぞれの編集範囲を構成する各操作の順序の情報が失われてしまうので、 64688 | 後でそれらを合成することは不可能である。 64689 | 64690 | x また、実のところ . で記録するかどうかは、 64691 | 編集が行われたかどうかなのでわざわざ編集範囲まで記録する必要はない。 64692 | 編集範囲の更新をするのは処理の無駄である。 64693 | 64694 | c start-edit-area で編集が行われたかどうかのフラグを下ろしておいて、 64695 | shift-by-dirty-range が呼び出された時にそのフラグを立てる様にする。 64696 | そして end-edit-area においてフラグが立っていれば記録を行う。 64697 | 64698 | x この方法の問題点は 0dh などについて、 64699 | 実際の文字列の変更が発生しなかった時に shift-by-dirty-range が呼び出されず、 64700 | 最終的に記録されないということである。 64701 | vim の動作としては実際の文字列の変更が行われなかったとしても dh が記録される。 64702 | そして何処か別のところに移動して . を押せば dh が実行される。 64703 | 64704 | d 或いは、operator 毎に記録するべきか記録しないべきかの属性を静的に持たせる。 64705 | 64706 | 例えば既定では記録するようにする。 64707 | ble/keymap:vi/operator:foo/norecord などの空関数を定義し、 64708 | その関数が定義されている場合には記録しないというようにする。 64709 | また operator:foo 自身の呼び出しで 0 以外を返した場合も記録しないようにする。 64710 | 64711 | operator 以外に関しては特に指定しない限りは 64712 | start-edit-area と end-edit-area で囲んで変更を検出する。 64713 | というかこれはそんなに気にしなくても良い。現状の set-previous-edit-area も同様に、 64714 | 必要な各箇所で end-edit-area か set-previous-edit-area を明示的に呼び出している。 64715 | それと同様に実装すればよいだけの筈である。 64716 64717 ここは d の方法を採用することにする。 64718 各オペレータ毎に成功した時に記録するかどうかの属性を持たせる。既定では記録する。 64719 →その様に実装することにした。 64720 64721 2017-10-26 64722 64723 * vi-mode: . 実装 (2) WIDGET KEYMAP (decode) 及び ARG FLAG REG (vi-mode arg) の整理・対応 [#D0550] 64724 64725 * done: get-arg, get-arg-reg の出力先の変数名は大文字にする。 64726 get-arg, get-arg-reg を直接呼び出している関数名の変数は大文字にする。 64727 引数として受け取っている arg flag reg は大文字にしない。 64728 64729 直接呼び出し元の arg flag reg を触るような関数は現在存在しないはずなので、これで問題は起こらないはず。 64730 (直接呼び出し元の変数を触るように設計するのは、 64731 特に out パラメータとして使う場合かグローバル変数の場合であるが、 64732 arg flag reg に限って呼び出し元に変更を通知するようなことはないしグローバル変数でもない) 64733 64734 * done: 先ず初めに vi_nmap からのみ呼び出すことを目的とした widget については、 64735 関数名を vi-command/* から vi_nmap/* に変更し、更に flag のチェックは省略する。 64736 * done: 更に get-arg を使っている部分については get-arg-reg を使う様にする。 64737 * done: get-arg は廃止し、get-arg-reg の関数名を get-arg にする。 64738 64739 64740 * done: get-arg を呼び出している箇所を機械的に大文字に変換していく。 64741 これを実行するに当たって良い方法はないだろうか。 64742 Emacs の置換の文字列で特別な記法があれば良いが難しい。 64743 64744 こんな記事を見つけた。\,(...) で replacement に S 式を含めることができるようだ。 64745 https://stackoverflow.com/questions/677021/emacs-regular-expression-replacing-to-change-case 64746 64747 \_<\(arg\|flag\|reg\)\_> -> \,(upcase \1) これで置換を行った 64748 64749 * done: ble-decode: _ble_decode_key__hook から読み取ったコマンドを一旦 64750 BLE_COMMAND 的な変数に入れてから実行する。引数も含めて。 64751 これは _ble_decode_{char,key}__hook についても同様にする。 64752 通常の widget 呼び出しに使っているのも COMMAND から BLE_COMMAND 的なものに改名する。 64753 {BEFORE,AFTER}_COMMAND も同様にする? もし COMMAND -> BLE_WIDGET にするならこれは変えなくても良いかも。 64754 もしくは __before_command__ 自体を __before_widget__ に変更するか。 64755 64756 % また、現在の実装では __before_command__ の内部で 64757 % COMMAND= としてコマンドをキャンセルする手法を用いているが、 64758 % この手法により何らかの問題が生じないかについても考察する必要がある。 64759 % というか、実のところ何も実行されないのだから、BEFORE_COMMAND 内部で set-previous-edit 64760 % が起こるような事態にならなければ大丈夫。むしろ、そのような場合には BLE_COMMAND 64761 % を記録して再実行したとしても動作を再現することはできないので別の問題が生じる。 64762 % →これは恐らく問題ない。OK 64763 64764 そもそも {BEFORE,AFTER}_COMMAND なる変数は定義していないのであった。なので気にしない。 64765 COMMAND に関しては (BLE_COMMAND などではなく) zle に合わせて WIDGET にする事にした。 64766 現在の kmap を zle に倣って KEYMAP に記録することにしたのだから WIDGET も同様に zle に倣うのが良い。 64767 64768 64769 2017-10-25 64770 64771 * 2017-09-16 vi-mode merge 直前に一括して行うテスト・仕様変更など (1) [#D0549] 64772 64773 以下は先に破壊的変更してしまうことにした。 64774 64775 * done: vi_command は vi_nmap に変更する? 64776 * done: vi_insert は vi_imap に変更する? 64777 →widget で vi_nmap と vi-command (vi_nmap, vi_omap, vi_xmap 用) を区別したかったので、 64778 早々に名前を変更することにしてしまった。これは破壊的な変更なので、今度 push する時に説明が必要。 64779 64780 % * vi-insert/@norepeat は @vi-norepeat 辺りに改名する。 64781 % 64782 % C-c の説明は "InsertLeave autocmd が実行されない" である。 64783 % これより @vi-cancel-leave などの方が分かりやすいのでは。 64784 64785 * done: vi-insert/@norepeat は廃止された。従って改名の必要はなくただ消すのみである。 64786 _ble_keymap_vi_imap_white_list に登録されていない widget は全て 64787 __before_command__ で repeat を reset するように変更したためである。 64788 64789 * done: また同時に marked/nomarked も @marked/@nomarked に変更する。 64790 →2017-10-25 これはもう修正した。今は marked/nomarked は obsoleted とし、 64791 @marked/@nomarked に振り替える様にしているが、後に削除する。 64792 64793 * done: vi-insert/@norepeat, marked/nomarked の廃止 64794 64795 2017-10-24 64796 64797 * 2015-11-18 histexpand: shopt -s histverify histreedit 対応 [#D0548] 64798 64799 * support: shopt -s lithist? [#D0547] 64800 64801 % 元々改行を含む履歴項目を登録する機能はあった様である。 64802 % この時の振る舞いについて調べ ble.sh でもこの形式に従って history を登録するべきだろう。 64803 64804 先ず初めに echo hello のような感じのコマンドを複数一度にじっこうしても一つの履歴項目にはならない。 64805 for 等のコマンドが単体行としては不完全な形で実行されると一まとまりに登録される。 64806 この時 history コマンドで見ると改行がそのまま出力されて表示されている。 64807 .bash_history を除いてみると行毎に登録した場合と同様に改行で分かたれて登録されている。 64808 bash を再起動して再度 shopt -s lithist して履歴を遡ってみると 64809 元々一つの履歴項目であったという情報は消えてばらばらの行になってしまっている。 64810 つまり、shopt -s lithist をしたとしても改行を含む履歴項目が bash_history に記録されるわけではない。 64811 64812 従って ble.sh では今までと同様に独自の eval -- 形式で改行を含む履歴項目を記録するということで良い。 64813 cmdhist, lithist のオプションに関しても、ble.sh では複数行の履歴に元から対応するということで振る舞いは変えない。 64814 或いは、文法に従った accept 拒否については cmdhist で振る舞いを変更するという手もある。 64815 64816 2017-10-23 64817 64818 * 時々 kcode と keymap の不整合が起きてキーが効かなくなるのは何故か? [#D0546] 64819 64820 keymap は bash version 依存がある様だ? と思ったら、 64821 default.sh のタイムスタンプで keymap/vi.sh のキャッシュを更新していたのが問題だ。 64822 default.sh から生成されるキャッシュは bash の version によって個別に生成しているので、 64823 そのタイムスタンプで更新する必要がある。 64824 64825 local dump="$_ble_base_cache/cmap+default.$_ble_decode_kbd_ver.$TERM.dump" 64826 64827 と思ったけれど本当だろうか。というか、_ble_decode_kbd_ver 3 と 4 で 64828 kcode は共有されているのだろうか。うーん。見てみたが共有されているはずである。 64829 従って bash version によらずに不整合は起こらないはずなのだが…。 64830 もしかすると過去に default.sh に問題が合ったというだけなのかもしれない。 64831 64832 と思ったらやはり再現する。これは原因を調べて解決する必要がある。 64833 64834 多分原因は分かった。default.sh が初期化される前に vi.sh が読み込まれるとなる。 64835 と思ったら default.sh を先に呼び出しても default.sh の中の最初の ble-bind から 64836 DEFAULT_KEYMAP の解決のために vi.sh が読み込まれてしまう。 64837 そして initialize が二重に呼び出されてしまう。 64838 取り敢えず直した。様子を見る。 64839 64840 2017-10-22 64841 64842 * 2017-09-11 vi-mode: ESC の問題 (reported by cmplstofB) [#D0545] 64843 64844 [原因調査] 64845 64846 | ノーマルモードから挿入モードに移った直後くらいに C-c、C-m 等及び通常のキー入力が「そのようなキーは 64847 | 設定されていない」という警告とともに無視される時がある。 64848 64849 * 可能性1 64850 64851 自分で試していて思ったのは、無意識で clear-screen しようとして C-l を押してしまい、 64852 ノーマルモードに戻ってしまうことがあるということである。 64853 ノーマルモードに戻ると C-c は定義されていないので警告が出る。 64854 また通常のキー入力も何らかのコマンドとして解釈されてエラーになる。 64855 何か入力して oOiIaA などが入るとそれ以降は入力できるようになる (母音なので確率は高い)。 64856 "直後" というのはそういうことなのではないかという疑い。 64857 64858 問題は現在のモードが表示されていないことにあるのではないかという気がする。 64859 モードが切り替わった時に簡単に表示する仕組みにしてみたが、微妙である。 64860 切り替わった瞬間には -- INSERT -- と表示されるが、 64861 補完などによって書き換えられた後は残らない。 64862 64863 ble-edit/info で恒久的に表示する内容 (default) と、 64864 一時的に表示する内容を管理できるようにすると良いのではないだろうか。 64865 結局新しい仕組みを整えることになった。 64866 64867 | * 2017-09-07 vi-mode: 現在のモードや引数の状態を表示する? 64868 | info に表示するか新しく別の status line を追加するか。 64869 | info に追加するというので良い気がする。 64870 64871 実際に C-l を vim で試してみると動かない。 64872 vimindex を調べると insertmode が設定されているときにのみ C-l は normal-mode だそうだ。 64873 Qiita の記事の方を見ると C-l は再描画になっている。 64874 zsh で試してみると C-l は clear-screen である。 64875 従って C-l は clear-screen である方が妥当である。 64876 64877 2017-09-13 追加の報告が来た。 64878 64879 | どうも私の端末の問題でした。Vim で Esc キーを多用するので Esc キーが押下された時 "Meta-" 64880 | に続く文字をなるべく待たないようにしているのですが、その設定を無効にすると発生しなくなり 64881 | ました。厳密な再現条件は未だ不明ですが、一応の解決を見たので取り下げます。 64882 64883 うーん。もしかすると、これは keymap を途中で切り替えた時の話かもしれない。 64884 一回コマンドを処理した時に残っているキーをどの様に処理するのだったか。 64885 というか、最近 ble-decode-key の何処かでミスを埋め込んで更にそれを修正したような気がする。 64886 12f3329 これだ。恐らく現状では直っているのではないかと期待する。 64887 64888 やはり解決していないそうだ。どうも話を見るに寧ろ連続して文字が来たときではなくて、 64889 逆に時間が立ってキーが届いた時の問題のようである。 64890 しかし、それは寧ろ ble.sh としては変なことが起こりにくい状況のはずである。 64891 先の推理では C-M-m などを ESC + C-m に分解して処理するときに一度に ESC と C-m が来るのが問題かと考えたが、 64892 どうもそういう訳でもないようだ。 64893 64894 あー。なんか分かった気がする。vi-mode では M-* を ESC * に分解していない。 64895 つまり ESC が二重になると失敗する。 64896 64897 更に ESC を単体で受け取ったとしてもその場で処理されない。 64898 その場で処理するように ble-decode を改修しようかとも考えたが、 64899 よく考えると、それをやると矢印キーなどを認識できなくなってしまう。 64900 或いは、矢印キーを送るなどした場合には通常は一つのパケットで送るので、 64901 矢印キーの先頭が来ているときにはすでに続きも来ているはずである。 64902 そういう意味では既に次のキーが来ているかいないかで ESC をその場で処理するかどうかを判定するという手もある。 64903 64904 取り敢えず処理するようにした。もう少し様子を見て他に問題の可能性が 64905 なさそうであれば改めて cmplstofB さんに尋ねることにする。 64906 64907 2017-09-17 うーん。やはり駄目だそうだ。 64908 64909 | すいません。まだ発生します。@akinomyoga 様の手元で発生しないということは 64910 | 確実に私の端末側の問題ですので、こちらで対処します。 64911 | どうかお気になさらないでください。 64912 64913 2017-10-12 2文字のコマンドの2文字目に ESC が来る場合、 64914 ble-decode の枠組みでは次の文字をも食らい M-? が 2 文字目に来たとする。 64915 これにより余分に処理されない文字が出てくる。 64916 64917 2017-10-22 どうやら ESC 単体を押した時点で元に戻って欲しいようだ。 64918 64919 * ESC 単体で受け取る方法についての考察 64920 64921 調べると stty time 0 及び tmux set -sg escape-time 0, screen maptimeout 0 など、 64922 通過経路全てで timeout を設定するようにすることができる。 64923 この時、ble.sh でも ESC の次に文字が既に来ているかどうかで単体の ESC かどうかを判定できる。 64924 64925 % と思ったが実際に実装しようとすると問題があるということが分かった。 64926 % 現状では bind によって ESC を単体で受け取ることに成功していない。 64927 % 試しに bind.sh の ESC に関係する work around を bash-4.4 で全て外してみたが、やはり動かない。 64928 % カーソルキーや Function キーだけでなく、個別に ESC h と入力しても駄目である。 64929 % 64930 % と思ったが、bashrc でいきなりロードすることにすれば ESC h だけは動くようだ。 64931 % カーソルキーの類は動かない。ESC [ だけ定義すればカーソルキーの類も動くようになるようだが、 64932 % そうすると ESC 単体ですぐに受信できなくなる。 64933 % 64934 % 結論: bash readline の bind の仕組みを改修しなければどうにもならない 64935 % 元々 bash の bind は色々駄目駄目なので、 64936 % それらの改善も含めて提案してしまえば良い気がする。 64937 64938 カーソルキーの類が動かなかったのは bleopt_decode_isolated_esc=raw 64939 の実装が不完全だったからの気がする。しかし、それを除いても (1B5B に bind しなくても)、 64940 ESC 単体ではすぐに受信できないようだ。と思ったが、事情は複雑である。 64941 CSI decoder の方が止めている可能性が出てきた。 64942 これはやはりキーロガーを導入するしかない。 64943 64944 導入した。しかし、どのタイミングで受信したのかは分からない。 64945 やはり [[ $bleopt_decode_isolated_esc == meta ]] || ble/util/is-stdin-ready 64946 の条件をちゃんとした物にする必要がある。あるいは、もっと手っ取り早く確認する方法? 64947 64948 調べてみると ESC はその場では受け取っていないようだ。 64949 何かが前にいて止めているように思われる。 64950 暫くしてから入力すると同時にキーが来る。 64951 screen で画面を切り替えてから入力すると 64952 bash_execute_unix_command で見つからないという事になってエラーになる。 64953 これは screen が何か噛んでいる気がする。 64954 64955 また ESC を間隔を空けて入力したときには 64956 64957 整理する 64958 64959 screen, esc1BXX=0, ESC (wait) h 64960 → 大丈夫。但し、h を受け取った時に一緒に ESC も受け取る 64961 どうやら screen が勝手に ESC を待つようなので、 64962 取り敢えず screen のない環境でテストするべきである。 64963 64964 esc1BXX=0, ESC (wait) h 64965 → bash_execute_unix_command error 64966 h だけが受信される。 64967 64968 * 0.4 sec 以上間隔を開けると処理されないということについて。 64969 これは変である。再現しない。 64970 64971 * 0.4 sec 以上間隔を空けて ESC を連打しても何も起こらない 64972 これは変である。しかし再現した。 64973 64974 先に screen の外での振る舞いを正すべきである。 64975 というか screen の外で正しくなればあとは maptimeout を 0 にするなどすれば良いはずだ。 64976 64977 再現した…。screen の中でやっていたのが悪かったようだ。 64978 screen の中でやっていると ESC が次の文字とくっついてからしか送られてこない。 64979 従って、単体で送られてくることがなかったのだ。 64980 そして、もし単体で送られてくると bash は解釈できずに駄目。 64981 64982 [修正1] 64983 64984 * 修正: \e? に bind しているときは \e 単体には bind しない。 64985 64986 これをしないと ESC が単体で送られてきたあとに ? が送られてくると、 64987 bash_execute_unix_command のエラーが発生する。 64988 64989 これは 0.4 sec 以上間隔を開けると処理されないというエラーと関係していると思われる。 64990 例えば tmux で escape-time 400 になっていると仮定すると、 64991 0.4 sec 以内であれば h が入力されたときに ESC h の組で送られてくる。 64992 0.4 sec 経過すると先に ESC だけが送られてくる。次に h が送られてくる。 64993 この時点で bash が内部で bash_execute_unix_command エラーを吐いていたのだろう。 64994 (しかし、何故そのエラーが表示されなかったのかというのは不思議である。 64995 と思ったがこのエラーメッセージは bash の標準エラー出力に出されるものだから、 64996 ble-decode ではなくて ble-edit の方から出てきているはずである。 64997 と思って調べたが check-stderr は無条件に visible-bell を呼び出しているので、 64998 やはりエラーメッセージが表示されているはずなのである。) 64999 65000 [確認1] 65001 65002 o さて、ESC を 4 回押さなければ駄目だったのが 2 回で済むようになった。 65003 @cmplstofB さんの手許でも 4 回だったので、恐らくこれで多少なりとも改善はしたはず。 65004 65005 x 但し、間隔を空けて入力するとやはり認識されない。 65006 何回押しても挿入モードのままである。うーん。これは何だろう。 65007 65008 調べてみる。 65009 65010 esc1BXX=1, ESC (wait) ESC (wait) ESC (wait) ESC (wait) h 65011 → bash_execute_unix_command error になる。h だけ受信する。 65012 esc1BXX=1, ESC (wait) ESC h 65013 → bash_execute_unix_command error, ESC h を受信する。 65014 esc1BXX=1, ESC (wait) ESC (wait) h 65015 → bash_execute_unix_command error, h だけ受信する。 65016 65017 esc1BXX=0, ESC (wait) h 65018 → bash_execute_unix_command error, h だけ受信する。 65019 esc1BXX=0, ESC h 65020 → ESC h h を受信する。key は何故かちゃんと C-[ h になる。 65021 これは ESC h の ESC だけが一致して、その後で再度 h を処理しているからである。 65022 65023 うーん。間隔を開けると ESC 単体で受信できないようだ。 65024 65025 ESC を bind -s '"\e": "\xC0\x9B"' で受信するようにしてみたところ動くようになった。 65026 つまり、その場で直ぐに受信することができるようになる。 65027 →試してみた所、実は bash-3.1 - bash-4.4 まで全部これで動く。bash-3.0 は動かない。 65028 65029 うーん。ところで read -n 1 を使えば ESC はその場で受信できるようだ。 65030 →bind の仕方で ESC 単体で受信することができるらしいと分かったので、これは考えない。 65031 65032 [修正2] 65033 65034 * 修正: ESC は bind -s で UTF-8 のエラー表現に移せば良いと分かった。 65035 この時、ちゃんとその場で ESC を受け取ることができるようになる。 65036 65037 試してみる。取り敢えず動く? 65038 65039 * 孤立 ESC はちゃんと C-[ と解釈されているが、 65040 bash-4.3 以上では timeout を待つ様になっている。 65041 調べると bash-4.3 では 'keyseq-timout' というものが追加されたようだ。 65042 何の効果もない。うーん。と思って keyseq-timeout にしてみたら動く様だ。 65043 単位は恐らくミリ秒である。bind 'set keyseq-timeout 1' などとしておけば良い。 65044 65045 * 孤立 C-[ はちゃんと処理されているが、 65046 カーソルキーも誤って孤立キーと判定されている。 65047 これはどうした物だろうか。というか何故? 貼り付けなどは正しく処理できているのに。 65048 65049 実際に試してみると確かに is-stdin-ready ではない様だ。 65050 そして貼り付けを行ったときにはちゃんと is-stdin-ready になっている。 65051 改めて矢印キーについて調べてみる。全ての文字が is-not-ready である。 65052 うーん。どうしたものか…。 65053 65054 これは別のターミナルでやると違うなどということがあるだろうか。 65055 →mintty でやっても同様だった。矢印キーは is not ready で貼り付けは ready 65056 従って、これは Poderosa が悪いのではない。 65057 途中の端末ハンドラが怪しいのではないか。 65058 65059 或いはやはり ESC * も bind するという方向で動いたりしないか? 65060 →試してみたが駄目だった。 65061 65062 screen 越しにやってみても駄目だった。 65063 つまり、やはり端末ハンドラが悪いということを示唆する。 65064 というのも screen は完全にキャッシュしてから送る設定に今はなっている。 65065 ということは、screen と bash の間にある端末ハンドラが悪い。 65066 65067 んー。或いは。read -n 1 してしまうという手もなくはないが…。 65068 →read -n 1 で実装してみたが動かない。というか、何故か順序が変更されている気がする。 65069 | if ((char==27)) && [[ $bleopt_decode_isolated_esc == esc ]]; then 65070 | function ble/util/read-byte-with-timeout { 65071 | local LC_ALL=C 65072 | IFS= read -r -d '' -n 1 -t "$1" byte; local ext=$? 65073 | ble/util/sprintf byte %d "'$byte" 65074 | return "$ext" 65075 | } 65076 | local byte 65077 | if ((_ble_bash>=40000)) && ble/util/read-byte-with-timeout 1; then 65078 | bleopt_decode_isolated_esc=meta ble-decode-char 27 65079 | ble-decode-char "$byte" 65080 | return 65081 | else 65082 | ((char=ble_decode_Ctrl|91)) # C-[ 65083 | fi 65084 | fi 65085 ということは何を意味するかというと特殊キーの場合には既にそれを構成する文字を読み取った後ということ。 65086 そして、現在は ble-decode-char をループか何かで回して処理しているということ。 65087 65088 と思って一回の ble-decode-char 呼び出しで文字の列を処理できるように修正した。 65089 しかし効果はなかった。改めて ble-decode-byte+UTF-8 において出力してみると、 65090 実は ble-decode-byte を呼び出している時点で既に is-stdin-ready は non-ready になっていた。 65091 つまり、bash が内部で "ESC [ D" などの文字の列を既に標準入力から読み取って 65092 中で保持しているので、is-stdin-ready では判定できないということになる。 65093 そしてタイムアウト付きで read しても既に読み取ってしまった文字は読み取れない。 65094 65095 うーん。だとすれば如何にして timeout を検出すれば良いのか…。 65096 基本的に現在の枠組みでは難しいような気がする。 65097 65098 a 全ての可能なキーシーケンスに対して bind して、 65099 一度に受け取ることができるようにする? 65100 65101 しかしこれは以下の点で問題がある。 65102 x 先ず、このキーシーケンスから外れるような入力が合った場合に、 65103 bash_execute_unix_command などのエラーが出るということが既に知られている。 65104 キーシーケンスから外れる全ての可能性について bind -x するとしても、 65105 大量に登録しなければならないので起動が遅くなるし、そもそも bind -x がそんなに信頼できるかも怪しい。 65106 x また、マウスなどの入力を受け付ける場合や、問い合わせの返答を受け取る場合を考えると、 65107 全てのキーシーケンスというのは無限個あることになり、全て登録するのは無理である。 65108 65109 b 或いは bind から read -n 1 ループに入るか。 65110 65111 それでも一番上のコンテキストで実行するためには 65112 ループには bind で入らなければならない。 65113 bind -x 'X: _ble_decode_char=X; eval "$_ble_decode_loop"' 65114 などのようにして、_ble_decode_loop にループを記述すれば良いだろう。 65115 65116 x これの問題点は 1 文字目がカーソルキーなどの場合には、 65117 カーソルキーを構成する 2 バイト目以降は read では決して読み取れないという事である。 65118 何故なら bash が既に読み取ってしまった後になるためである。 65119 65120 c 関数内で read -n 1 ループに入るか。 65121 65122 x この時の問題点は実行の文脈をトップレベルにできないということである。 65123 65124 x 更に、誤って C-c などを連打してそれがループに対して作用してしまった場合、 65125 その瞬間に ble.sh から抜けて元の bash になってしまう。 65126 それだけでも問題であるが、さらに、 65127 この時、其処までに編集した文字列などが失われるなどの実害もある。 65128 65129 d ESC * も bind -s 経由で登録したらうまく行くかもしれない? 65130 65131 もしくは bind '"\e\e": "\xC0\x9B\xC0\x9B"' でも十分かもしれない 65132 65133 方針 d でうまく行くようになった。しかし、こうすると今度は timeout した時に、 65134 esc をそのまま処理するか meta として処理するかの切り替えができなくなる。 65135 或いは逆に C-[ を ESC に戻して処理するという具合にすることは可能か? 65136 65137 元々 C-[ が \e[27:5:91~ として送られてくることはないはず。 65138 だとすれば C-[ を ESC に戻せばよいのではないだろうか。 65139 65140 % と思ったが…よく考えたら C-[ になるのは key の段階なので、 65141 % ble-decode-char の段階で介入できない。 65142 % 65143 % ble-decode-char の段階で介入できるような特別な文字は存在するだろうか? 65144 % うーん。例えば ble-decode-byte+UTF-8 において ESC の 3 バイト表現の場合には特別なフラグを立てるようにするなど? 65145 % しかし ble-decode-byte+UTF-8 は文字デコーダとして独立したものにしたい。 65146 % 65147 % うーん。或いは \e[27;5;91~ は csi を通して処理されるので、 65148 % csi から出てくるキーについても修飾キーになる可能性を検査するように修正するという手もある。 65149 % と思って実装を見たら元々収書キーになるかどうかの判定は csi から出てくる物も含まれていた。 65150 % 65151 % 特別に対処する必要はなかった。 65152 65153 多分解決した。未だ問題がある場合には別項目で立てることにする。 65154 65155 * ble.pp: readlink -f は Linux でしか使えない [#D0544] 65156 65157 2017-10-19 65158 65159 * vi-mode: . 実装 (1) ble/widget の終了ステータス確定 [#D0543] 65160 65161 | Note: __default__, __defchar__ においては要求されたコマンドが成功したかどうか 65162 | (そして . に記録するに値するかどうか) というよりは、 65163 | そのキー入力に対する処理が見つかったかどうかという意味を持つ。 65164 | 見つかったならばその処理自体が無効だったりして失敗したとしても、 65165 | 別のハンドラーを探しに行くという様な動作は変である。 65166 | 或いは __default__ に登録するハンドラーについて、 65167 | それに対応する処理が見つからなかった場合には、単に 1 を返すのではなくて、 65168 | 特別な値を返すというルールにするのが良い。 65169 | むしろその方が自然である。 65170 | 65171 | Bash の終了ステータスの値を参考にするのが良さそうである。 65172 | 65173 | - 127 は一般にコマンドが見つからなかった時に使われる。 65174 | 特にコマンドが見つからなかった時は command_not_found 関数が使われるが、 65175 | これは ble-decode の枠組みにおける __default__ に近い。 65176 | 更に command_not_found 関数もなかった場合に 127 がコマンドの終了ステータスになる。 65177 | これから、__defchar__/__default__ に登録した関数によって、 65178 | KEYS に対応する処理が定義されていない場合には 127 を返すというのは自然な気がする。 65179 | 65180 | と思ったが 127 は丁度 7 bit で表現できる最大の数であることから 65181 | ソースコード中に頻出する数字である。つまり検索しにくい。 65182 | うーん。使われていない 125 を代わりに使うことにしようか。 65183 | 65184 | - 126 はコマンドは見つかったが何らかの理由で実行できなかった場合の値である。 65185 | これは ble-decode ではするべき操作は決まったが、それが正しく実行できないときになる。 65186 | つまり bell を鳴らしたりするような場面である。これは普通に 1 でも返す方が自然だ。 65187 | 65188 | - 125 は使われていない 65189 | 65190 | - 124 はプログラム補完に於いて、 65191 | 補完候補生成を最初からやり直すということを要求するのに使われる。 65192 | 65193 | - 128 以降はシグナルに使われる。 65194 | 65195 | - その他の 12? は特に使われていないようだ 65196 | 65197 | - 148 = 128+20 (SIGTSTP) は C-z による中断時。 65198 | 現在 isearch の fib には 27 を用いているが、根拠は弱い。 65199 | こちらの方が説得力があるかもしれない。 65200 | また 27 は別の目的でも使われるのでなかなか検索しにくいという問題もある。 65201 65202 → __default__, __defchar__ の終了ステータス 125 に対応した。 65203 → 中断・継続のための終了ステータスは 27 から 148 に変更した。 65204 65205 その他の widget についても終了ステータスについて再確認して、 65206 全体に終了ステータスを定義済みになるようにした。 65207 65208 2017-10-17 65209 65210 * 2017-10-14 vi-mode: レジスタ対応 [#D0542] 65211 65212 operator 呼び出しの前後で _ble_edit_kill_{ring,type} 65213 を入れ替える実装にする事にした。 65214 これは単に書き換えて行くだけである。 65215 65216 * done: call-operator-*wise を改修して kill_ring, kill_type を 65217 復元・保存する様にする。 65218 65219 * done: 現在 operator:* は _ble_keymap_vi_operator_delayed 65220 を用いて処理の継続の情報を呼び出し物に伝えているが、 65221 これは終了ステータスによる方法の方が自然なのではないかと思われる。 65222 →終了ステータス 27 によって続きを別のところで処理することを表す事にした。 65223 65224 * done: call-operator-*wise の呼び出し元を修正する。 65225 65226 * done: 以下の関数の呼び出し元の修正 65227 - done: exclusive-goto index flag reg nobell 65228 - done: inclusive-goto index flag reg nobell 65229 - done: exclusive-range p q flag reg nobell 65230 - done: linewise-goto index flag reg opts 65231 - done: linewise-range p q flag reg opts 65232 65233 * done: 以下の関数は直接 kill-range/copy-range を呼び出している。 65234 65235 - done: ble/widget/vi-command/copy-current-line 65236 - done: ble/widget/vi-command/kill-current-line 65237 上記の関数については operator 経由で呼び出す様に変更した。 65238 65239 他にもあると思われる。と思ったら、他は全て operator y/d/c 経由だった。 65240 65241 * done: 後は kill_ring kill_type を直接触っているコード 65242 vi-command/paste.impl vi_xmap/paste.impl がある。 65243 65244 * done: operator:* の終了ステータスを確定させる。 65245 特に 27 を返すことは特別な意味を持つので。 65246 27 を返すもの以外は 0 を返すように修正した。 65247 65248 レジスタへの追記の振る舞い 65249 65250 "大文字によって既存のレジスタへ内容を追加できるそうだ。 65251 しかし v V C-v を混在させるとどうなるのか。 65252 65253 C-v に v を追記したら C-v だった。 65254 ただし、v で追記した分については nfill は設定されていないようである。 65255 65256 今の実装の問題点 65257 65258 * resolved: "x を前置すると実際に変更がなかった場合でも 65259 レジスタに kill_ring kill_type の内容が登録されてしまうのでは? 65260 と思ったが "x を前置したときの内容は事前に "x の内容になっているので、 65261 変更がなかった場合は改めて "x に値を格納しても以前と変わらないので問題ない。 65262 65263 * resolved: 現在は "x を指定したときにはそのレジスタだけに値を設定している。 65264 しかし、vim の動作を確認すると無名レジスタにも同じ値をコピーするようである。 65265 65266 a これに対応するためには、例えば一つの方法は 65267 local _ble_edit_kill_{ring,type} を事前に設定せずにそのまま処理を実行し、 65268 後で _ble_edit_kill_{ring,type} の内容をレジスタにコピーするというもの。 65269 もし追記を指定された場合には、レジスタに追記した後で追記内容を 65270 _ble_edit_kill_{ring,type} に書き戻す。 65271 65272 この方法の問題点は実際に _ble_edit_kill_{ring,type} が変更されたか 65273 どうかを検出しなければならないということである。 65274 もし "x を設定しても何も変更がなかった場合には、 65275 _ble_edit_kill_{ring,type} の内容をレジスタにコピー・追記してはならない。 65276 実際に試してみたが、やはり、例えば "ag~ ではレジスタに変更は起こらない様だ。 65277 65278 またこの方法だと operator から見える _ble_edit_kill_{ring,type} の内容は 65279 無名レジスタのそれであって、ユーザが "a で指定したレジスタの内容ではない。 65280 % (_ble_edit_kill_{ring,type} の内容を変更した時は "a に対する変更であるにも拘らず。 65281 % と思ったが、これは微妙である。何故ならユーザに依る変更は "" と "a の両方に適用されるから) 65282 65283 b もう一つの方法は、取り敢えず local _ble_edit_kill_{ring,type} は事前に設定し、 65284 それをレジスタにコピー・追記した後で、 65285 unset _ble_edit_kill_{ring,type} して本来の kill_ring に値を戻すというものである。 65286 しかし、この場合でも kill_ring に変更があったかどうかを検出する必要がある。 65287 65288 c やはり一番妥当な方法は実際に .copy-range .kill-range する箇所で 65289 コピー・追記などの処理を行うということである。 65290 65291 → c の方針で書き直した。operator:* の呼び出しは結局全て 65292 call-operator 経由で行うことになったので、書き換えは簡単である。 65293 operator 側でもレジスタに触るものは限られている。 65294 65295 Note 65296 65297 * done: omap では "x は使えない。つまりオペレータを入力する前に "x は設定しなければならない。 65298 →nmap と xmap に個別に '"' を登録することにした。 65299 65300 色々書き換えたので動作確認を行う。 65301 65302 * done: レジスタ追記について: (v, V, C-v) x (v, V, C-v) が正しく動作するか。 65303 - v v, v V, v C-v は確認した。 65304 - V V, V v, V C-v も確認した。 65305 - C-v v, C-v C-v, C-v V も確認した。 65306 65307 x resolved: ysiw" の入力途中に bell がなる。動作は正しい。 65308 w まで入力したところでなる。どうも operator:ys で 27 を返すとなるようだ。 65309 →call-operator-* の戻り値をチェックして失敗したら bell を鳴らすようにしていた箇所があった。 65310 27 を返した時には何もせずに退出するべきである。その様に書き換えた。 65311 他にも call-operator-* を呼び出しているが戻り値に対応して適切な処理をしていないところが 65312 幾つか合ったのでそれも直した。 65313 65314 * resolved: これは前からだと思うが行指向の kill_ring を最終行で貼り付けたとき、 65315 余分に改行が挿入されるのは何とかならないのだろうか。 65316 →これは直した。また `[`] で設定される範囲も直した (次の行頭には行かない)。 65317 両変更について確認した。 65318 65319 2017-10-12 65320 65321 * ble-edit: 複数行編集時に .SHELL_COMMAND を実行すると、 [#D0541] 65322 色々と座標計算がずれている。先ず初めに編集中の文字列が残ってしまう。 65323 更に、.SHELL_COMMAND が出力した内容が上書きされて消えてしまう。 65324 65325 座標計算は合っている。みたところちゃんとした場所に移動してから実行しているように見える。 65326 と思ったら分かった。端末の一番下にいるときに起こり、端末の上の方に煎る時には起こらない。 65327 つまり、描画領域の高さの確保がちゃんとできていないことが原因である。 65328 取り敢えず一時的に端末の高さを 0 にするということが必要である。 65329 65330 * vi-mode (visual mode): J gJ [#D0540] 65331 65332 これは試してみた所 block, char かどうかとは関係なく、常に行指向で処理するようだ。 65333 これの対応は簡単だった。 65334 65335 * vi-mode: (insert) で C-c すると表示は (insert) のまま [#D0539] 65336 ノーマルモードに戻っている気がする。 65337 よく分からないので、ble.sh では C-c で 65338 単にノーマルモードに戻ることにする。 65339 65340 * `[ `] は挿入モード中でのカーソル移動でも途切れるが、 [#D0538] 65341 65342 % そのようなものにまで対応していると遅くなると思われるので今は対応しない。 65343 65344 もしかすると white_list に載っていないコマンドで 65345 dirty-range#clear すれば良いだけかもしれないが。 65346 いや、移動した後で何も変更しないということも考えられるから、 65347 end-edit-area, start-edit-area を実行するべきだろうか。 65348 65349 しかし white_list に含まれるかどうかのチェックには時間がかかるのではないかという心配がある。 65350 現在の設定では挿入の引数が設定されていない限りは white_list のチェックは行っていない。 65351 `[`] を設定するためにこれを利用するというのは、常に white_list のチェックを行うという事に等価である。 65352 self-insert は特に頻繁に通過するだろうから、特別に対処するというのは妥当である。 65353 65354 さて、結局 `[`] の挿入モードにおける厳密な振る舞いに対応することによるオーバーヘッドは、 65355 .before_command における white list チェックのオーバーヘッドのことだと考えられると分かった。 65356 現在の実装では特に white list の使用は繰り返しが指定されたときだけにしているが、 65357 実のところ将来的に undo を実装する際には結局同様にチェックしなければならない気がする。 65358 結局、white list のチェックを免れられないのであれば、ここで対応する。 65359 65360 * vi-mode (xmap I): より vim に違い動作 [#D0537] 65361 65362 どうも色々ためすと切り出し位置の決定はそんなに簡単ではないようだ。 65363 現状では行を覚えておいた内容と比較して一番初めに変更の合った点からとしているが、 65364 これはたまたま挿入した文字列が元々合った内容と一致している場合に切り出し内容がずれて問題になる。 65365 vim で詳しく調べてみると、どうやら I が始まって以降の変更範囲を覚えているようである。 65366 どこから開始点よりも前 (前の行での変更も含む) で変更があれば (変更前と変更後が同じだったとしても)、 65367 切り出し位置は開始点になる。もし変更が開始点よりも後にあれば変更はそこからになる。 65368 さて、変更範囲は何処に記録されるだろうか。挿入モードによる `[`] はどうか。 65369 65370 - 試してみた所 C-o から復帰した時点で新しい `[ が始まるようである。 65371 但し何も入力しない場合には最終的に抜けるときに `[ `] は設定されない。 65372 これは通常通りに入るときと少し異なる動作である。 65373 65374 - さて、もし I の InsertLeave が `[ `] を使用しているのだとすれば、 65375 途中で C-o を挟めば以前の編集について忘れてその点からの挿入になるはずである。 65376 →試してみた所 C-o をした瞬間に InsertLeave が消去されてしまう。 65377 因みにこの動作は現在の ble.sh でも同様である。 65378 65379 従って、`[ `] を用いて変更範囲を決定することが可能である。 65380 65381 - と思ったが、vim の動作を調べてみると挿入モードの中であっても 65382 カーソルキーなどを用いて移動したりするとその都度 `[ `] が設定されるようである。 65383 つまり、正しい実装の `[ `] に頼る訳には行かない。 65384 65385 - 更に、現状の実装では挿入開始点の記録に `[ を使用しているがこれも正しくない。 65386 より前に変更があったりすると `[ もずれてしまう。 65387 別の mark を設定する必要がある → これには特別な mark 1 を用意することにした。 65388 65389 - 矩形挿入を開始して以降の "変更" を累積して記録するにはどうすればよいか。 65390 現状の `[ `] はそれに近いが挿入モード開始時に開始点に "変更" を記録してしまうのでこれは微妙に違う。 65391 更に将来的に vim と同じ `[ `] の動作にしたときに、動作が変わってそれも問題になるだろう。 65392 65393 結局矩形挿入モードのときだけ更新する dirty-range をもう一つ用意するしかないのだろうか。 65394 65395 * 2017-10-05 vi-mode (visual): p P [#D0536] 65396 65397 前回 p または P 消したものを覚えていて、それを貼り付けている気がする。 65398 vimindex のページには書いていない。ページが古いのかもしれない。 65399 :help v_P とすると v_p または v_P の説明を見ることができる。 65400 65401 1 help には挿入してから削除すると書かれているがこれは嘘だ。 65402 65403 ABC 65404 ABC 65405 65406 に対して 65407 65408 e 65409 e 65410 65411 を、初めの B 1文字を矩形選択して p すると 65412 65413 AeC 65414 AeBC 65415 65416 という結果になる。これはつまり選択範囲 B を削除してから e を挿入していることを意味する。 65417 カーソルは最初の e 65418 65419 2 文字ビジュアルに矩形を貼り付けるとどうなるか。 65420 65421 12345 65422 67890 65423 xyzwt 65424 65425 abcde 65426 fghij 65427 65428 これについて C-v b → g を v 2 → 9 に対して貼り付けると次のようになる。 65429 65430 1b0 65431 xgyzwt 65432 65433 カーソルは b 65434 これも先に削除してから貼り付けが起こっていることを示唆している。 65435 65436 3 文字ビジュアルに改行を貼り付けるとどうなるか。 65437 65438 ABCDE 65439 FGHIJ 65440 65441 の v C → D に行を貼り付けると以下のようになる。 65442 65443 AB 65444 12345 65445 67890 65446 E 65447 FGHIJ 65448 65449 適当に既存の機能の組み合わせで実装した。 65450 テストする。C-v → C-v は確認した。 65451 上記のケース 1 2 3 は何れも再現した。 65452 65453 4 V を C-v に貼り付ける場合 65454 65455 ABCDE 65456 FGHIJ 65457 65458 の C-v B → G に p で貼り付ける場合。 65459 65460 ACDE 65461 FHIJ 65462 12345 65463 67890 65464 65465 更に P で貼り付ける場合には前に貼り付けられる。 65466 現在の実装だと以下のようになってしまう。 65467 65468 A 65469 12345 65470 67890 65471 CDE 65472 FHIJ 65473 65474 5 v を C-v に貼り付ける場合 65475 65476 A12345CDE 65477 F12345HIJ 65478 65479 文字列 12345 を C-v B → G に貼り付ける場合には、各領域に繰り返し挿入される。 65480 65481 A45 65482 678CDE 65483 FHIJ 65484 65485 貼り付けられる文字列に改行が含まれる場合は、繰り返しは行われない。 65486 65487 これはどう理解したら良いだろう。 65488 貼り付けられる対象が C-v のときには特別な対処が必要ということか。 65489 65490 あとカーソルの位置に関しても確認しておく必要がある。 65491 1 と 2 は合っている。3 はカーソル位置が違うというか…行末に来ている。 65492 通常の行指向の p P は行末に来ていない…と思ったが、 65493 実際に v_p の実装では文字指向の p P を使っているので、この動作は別の問題である。 65494 65495 結局、3x3 のパターンについて個別に paste の仕方を変えて実行することにした。 65496 色々と引数を与えた時の動作などを観察するとこの方法で良かったようだ。 65497 簡単に各場合の動作の確認もした。大丈夫。 65498 65499 2017-10-11 65500 65501 * isearch が動かなくなっている。 [#D0535] 65502 リファクタリングの過程で条件が反転していた。 65503 65504 * complete: complete -p -D が働いていない気がするが… → 124 に対応 [#D0534] 65505 65506 % complete.sh を見ると対応しているように見えるし、 65507 % 過去の記録を見ても動いていた様子がある。 65508 65509 どうも前から動いていなかった疑いがある。 65510 先ず初めに compgen に -D オプションが混入するとエラーになって、 65511 そもそも補完関数も呼び出されない。 65512 65513 さて、無事に補完関数は呼び出されるようになったが、何も候補が生成されていない。 65514 どうやら __load_completion では定義をロードするだけで候補生成は行わない様だ。 65515 一方で、素の bash でやるとちゃんと候補が生成できている。 65516 これが意味するところは素の bash は、もし候補生成がされなかった場合は、 65517 新しく追加された定義を用いて再度候補生成を行うということである。 65518 65519 何と。マニュアルに書かれていた。 65520 -D による補完関数が 124 を返したとき、 65521 再度補完が試みられるのだと。対応した。 65522 65523 * git 補完関数の末尾空白の問題 65524 65525 | * 2015-11-23 プログラム補完: 末尾空白の問題点 65526 | 65527 | 現在 git 補完関数に合わせる形で勝手に末尾の空白を除去している。 65528 | しかしこれで良いのか? これだと空白で終わるファイル名などがあった場合に問題になる。 65529 | (その様なファイル名は滅多にないとは思われるが…。) 65530 65531 % git の補完関数は変なことをする。候補の末尾に空白を付加し compopt -o nospace を指定する。 65532 % ble.sh の complete は末尾の空白をエスケープする仕様になっている。 65533 % これは compgen -A file の空白を含むファイルとの一貫性のためである。 65534 % 従って git の補完関数の場合には sed で末端の [[:space:]]+ を除去する必要がある。 65535 65536 git の時にだけ work around を追加しようと思ったが、 65537 どうやら bash-completion は一般にそのような設計になっている疑いがある。 65538 分からないので取り敢えず現在の仕様を保持することにする。 65539 と思ったが、やはり末端に空白のあるファイル名を補完するときに問題になる。 65540 65541 うーん。やはり git だけ特別扱いすることにする。 65542 65543 そういえば、やはり git は以前問題になったのだから、 65544 以前は complete -D が動いていたという事になる。 65545 恐らく bash の version によって compgen に -D があった時に 65546 エラーになるかどうかが違うということなのだろう。 65547 65548 * しかし、不思議なのは素の bash ではこの問題が発生していないということである。 65549 つまりファイル名の末尾の空白はちゃんとエスケープされるが、 65550 git subcommand の末尾の空白はエスケープされないというようになっている。 65551 65552 もしかして git の補完関数はファイル名を補完しているときには 65553 nospace を指定せずに末尾空白も付加せずに候補を生成するのではないかという説を思いついた。 65554 つまり nospace は末尾空白をエスケープしないというサインになっているのではないかという説である。 65555 しかし試してみると、常に nospace を指定している。 65556 65557 うーん。しかし /usr/share/bash-completion/completions/git に 65558 compopt -o filenames +o nospace という行がある。この行が実行されているときには、 65559 ファイル名末尾の空白がちゃんとエスケープされるようになるということではあるまいか。 65560 そして自前のシェル関数の compopt は実行されないということなのではないだろうか。 65561 65562 そう思って適当なコマンドを作って試してみた所、 65563 ちゃんと自前のシェル関数が呼び出されるということが分かった。 65564 65565 function _alpha { compopt +o nospace; } 65566 function alpha { echo "$@"; } 65567 complete -F _alpha alpha 65568 alpha hello.txt 65569 65570 ということはやはり git の補完では実際には compopt は呼び出されていないのだろう。 65571 やはり素の bash で正しく動作できている理由が不明である。 65572 65573 更に素の bash の補完の振る舞いについても調べてみたが、 65574 65575 function _alpha { compopt -o nospace; local w=${COMP_WORDS[COMP_CWORD]}; for a in hello world 'abc efg'; do [[ $a == "$w"* ]] && COMPREPLY=("$a "); done; } 65576 function _alpha { compopt +o nospace; local w=${COMP_WORDS[COMP_CWORD]}; for a in hello world 'abc efg'; do [[ $a == "$w"* ]] && COMPREPLY=("$a "); done; } 65577 65578 特に -o nospace / +o nospace でエスケープをしたりしなかったりという事はないようだ。 65579 というか、基本的に補完関数によって生成された候補はエスケープしないようである。 65580 65581 ということはスペースを含むファイル名を補完した時にエスケープしているのは誰なのかという謎が生じる。 65582 実のところ、bash は直接 compgen を呼んでいるのではなくて、 65583 内部的な処理の一環としてファイル名を候補に生成しているので、 65584 それがファイル名による候補かどうかを知っていて、 65585 その内部的にしか知り得ない情報を用いてエスケープするかしないかを決めている可能性がある。 65586 65587 % 面倒なのでここまでにして深入りしない事にする。 65588 65589 と思って ble.sh でやってみたらいつの間にかに正しく動くようになっている。 65590 つまり __git* の生成するものについてはエスケープせず、 65591 ファイル名候補の場合にはエスケープする。 65592 どうやら git はサブコマンドしか候補を生成しない様だ。 65593 そして一致するものが見つからない場合には自前でファイル名候補を生成するなどのことはしない。 65594 これによって ble.sh の通常のファイル名候補にフォールバックする。 65595 結果としてファイル名候補の場合には正しくエスケープされるという動作になる。 65596 65597 取り敢えず OK ということにする。 65598 65599 * 2017-10-10 vi-mode (mark): < > ` ' " . などの設定をそれぞれ実装する必要がある。 [#D0533] 65600 65601 - done: [] は直前の変更または yank 範囲 → #D0529 65602 - done: <> は前回のビジュアルモードの選択範囲 → #D0531 で同時に対応 65603 - `' は最後のジャンプ前の位置 65604 65605 ジャンプには以下の種類がある。 65606 - done: 新規ファイル作成 → これは新しい行のロードと解釈して良いだろう 65607 - done: `x 'x / ? n N L H % G (last-line) 65608 - 保留: M ( ) [[ ]] { } :s :tag これらのコマンドはそもそも未対応 → #M0006 に記録 65609 65610 どうやらオペレータによって移動する場合にはジャンプ元の設定は行われない様だ。 65611 65612 - done: " は最後の終了時の位置 65613 これはシェルにおいては履歴項目を移動する直前の位置とするので良いだろう。 65614 しかしどのタイミングで記録するのが良いだろうか。 65615 65616 a 一つの方法は _ble_edit_str.reset を通して呼び出される 65617 update-dirty-range の hook でそれを検出して実行することである。 65618 と思ったが、その呼出のタイミングでは既に元の文字列が失われている可能性がある 65619 (確認してみたら reset のときはそうではないと分かったがこの仮定に依存することは危険である) 65620 ので、もっと他の方法があると良い。 65621 65622 b 或いは、ble-edit 側で history を移動する、もしくは、 65623 新しい行に移動するときの hook というのを用意するという手がある。 65624 65625 - done: . は最後の編集位置 65626 - done: 現在 `[ `] は yank の効果を入れていない。 65627 yank (copy-range もしくは block copy) があった時にも更新するように設定すべき。 65628 実のところコピーをしているのは .copy-range を呼び出している箇所か、 65629 或いは operator:y のみである。他の操作は全ては快適変更を伴うので自動的に登録されている。 65630 対応した。 65631 65632 * vi-mode (visual block): 元から行末にいる時に $ を押しても末尾拡張が表示に反映されない。 [#D0532] 65633 内部的にはちゃんとできているはずだが、描画部に状態変化が伝わらないので、 65634 表示が更新されないのが問題である。これに対応するためには、 65635 末尾拡張も _ble_edit_mark_active を使って表現するしかない? 65636 65637 その場合には従来の _ble_edit_mark_active を参照している箇所も書き換える必要がある。 65638 65639 →その様に修正した。元々使っていた _ble_keymap_vi_xmap_eol_extended という変数は廃止した 65640 ble/widget/vi_xmap/linewise-operator.impl の辺りで保存される矩形の種類についても修正した。 65641 65642 * 2017-10-08 vi-mode (visual): I A [#D0531] 65643 65644 振る舞いを調べる。先ずは I について。 65645 65646 | - 矩形ビジュアルのときだけしか特別な動作はしない。 65647 | 行ビジュアルでもコピーは起こらない。 65648 | 65649 | - 先ず途中でカーソルを中で移動しても大丈夫。 65650 | これは引数による繰り返しとは振る舞いが異なる。 65651 | 更に中で動かすのではなくて一回外に出て戻ってきても OK 65652 | 65653 | - 別の行を弄って戻ってきても大丈夫。 65654 | 行の数が変化すると駄目。行を挿入して削除して合計で変わらなければ OK。 65655 | と思ったが範囲よりも後に行を追加しても大丈夫。 65656 | 65657 | - というか同じ行の前後もいじっても大丈夫? 65658 | 65659 | - 同じ行の前を幅が変わらないように弄るとベルが鳴って行頭に移動する。 65660 | 幅が変わっても何か動く。開始点はずれる前の位置で決まり、終了点は最後に挿入した文字列になる。 65661 | 重要な結果。 65662 | 65663 | | AAABBB -> AAA123BBBaaa -> AAA123BBBaaa 65664 | | AAABBB AAABBB AAA123helBBB 65665 | | AAABBB AAABBB AAA123helBBB 65666 | 65667 | どうやら行内の%%文字数%%幅を数えて増分を計算しているようだ。 65668 | 65669 | - 抜けるときに、挿入文字列の途中にいても大丈夫。但し、外にいると駄目。 65670 | 65671 | - 行の数が変化すると駄目だったが、 65672 | もし行番号だけを見ていてカーソルが同じ番号の行にいれば動くということだと、 65673 | 行の数が変化した分だけカーソルの位置をずらして元々別の行だった所で挿入モードを抜ければ、 65674 | 同様に働くのではないかと考えた。が、試したら動かなかった。 65675 | やはり vim では行は追跡されている気がする (mark の振る舞いを見ると)。 65676 | 65677 | - 途中で改行を入れると動かない。I でも A でも。 65678 | 前に一回動いた(選択領域のかかっている行たちの次の行に新しい内容が挿入されるような動き) 65679 | ような気がしたけれどなんだったのだろう。 65680 | しかし実際にそのような動作が起こる場合があるとしても分かりにくいので取り敢えず実装しない。 65681 | というわけでこの振る舞いに関しては取り敢えずは考えないことにする。 65682 | 65683 | - I に対する引数に依る繰り返しが適用されてから、 65684 | 他の境界に対するコピーが起こる。 65685 65686 この時点での仮説では I は以下のように動く 65687 65688 1 矩形範囲の先頭行の行番号と表示横幅と矩形の左端の位置を記録する。 65689 更にその行自体も覚えておく。 65690 2 挿入モードから抜けるときの処理として次に続くものを登録する。 65691 挿入モードから抜けるときは先に引数による繰り返しを実行する。 65692 これは引数による繰り返しがない場合や、引数に依る繰り返しが無効になった時も含む。 65693 3 カーソルのある行が 1 で記録したものと一緒でなければキャンセル。 65694 カーソルのある行の行番号が 1 で記録したものと一緒でなければキャンセル。 65695 4 表示横幅の変化量を測る。これが正でなければキャンセル。 65696 変化量の分だけ 1 で記録した左端の位置から文字列を切り出す。 65697 5 その時点での続く行の、記録した左位置に 4 の文字列を挿入する。 65698 新しく行が挿入されていたりしても関係なく、 65699 その時点での先頭行からの相対位置で挿入行が決まる。 65700 65701 | 矩形範囲の先頭行を覚えておくのには ble.sh の実装では _ble_edit_mark でも使えば良い? 65702 | ただ挿入モードの操作の途中で _ble_edit_mark が書き換えられることもあるので別に用意するべき 65703 | 65704 | ? 途中で行分割が起こった場合は 1 で記録した行はどうするのか。 65705 | また分割された行に対して挿入が行われたりするのだろうか。 65706 | 65707 | →試すと行頭に紐付いている気がする。また分割された行に対して挿入が行われる。 65708 | うーん。行分割した上で矩形左位置の内容を元と同じにすれば動くが、 65709 | 行分割した上で矩形左位置よりも前の内容が異なると起動しない? 65710 | これは行分割を行わなかった場合と様子が異なる。 65711 | 65712 | うーん。よく分からないのでこれについては無視でも良い気がしてきた。 65713 | 行分割を行わなかった場合と同じ処理にすれば良い。 65714 | 65715 | ? 試すと 以下で C の列で C-v I して、G の後に平仮名を入れて、 65716 | それから抜けると以下のようになる。行の内容を記録しておいて、 65717 | 一番初めに変更のあった位置を検出しているのか? 65718 | 65719 | | ABCDEFGH -> ABCDEFGあH 65720 | | ABCDEFGH ABCDEFGあH 65721 | | ABCDEFGH ABCDEFGあH 65722 | 65723 | うーん。しかし、矩形左位置より前で変更が起こると、 65724 | 矩形左位置からのコピーになる。 65725 | 65726 | - 中途半端に全角文字に被っているとき、 65727 | 全角文字の前で挿入が開始される。 65728 | コピーは矩形範囲内に入った文字列だけ行われる。 65729 | 65730 | 挿入した文字列に含まれる全角文字が、 65731 | 元の矩形の左端に中途半端に被っているときは、 65732 | その全角文字全体がコピーの対象になる。 65733 | コピーの終端がそれに応じて移動するということはない。 65734 | 65735 | 挿入した文字列に含まれる全角文字が、 65736 | 元の矩形の右端に中途半端に被っているときは、 65737 | 何か文字が分解されて変なことになる。 65738 | 65739 | | echo hello world 65740 | | echo hello world 65741 | | echo hello world 65742 | 65743 | | echoあい hello wld 65744 | | echo あ<e3><81>hello world 65745 | | echo あ<e3><81>hello world 65746 | 65747 | コピー先に全角文字が鎮座しているときの振る舞いはどうか。 65748 | →その全角文字の手前に挿入される。 65749 | 全角文字が鎮座していないその他の行については影響はない。 65750 65751 以上のことから手順に以下の変更を加える。 65752 65753 1a 行の内容も記録する 65754 4a 行の内容を比較して一番初めに変更の合った点を求める。 65755 この点が矩形左端より左にあれば矩形左端を切り出しの開始点とする。 65756 もしこの点が矩形左端より右にあればこの点を切り出しの開始点とする。 65757 4b 切り出し範囲に被る全角文字があればその全角文字も取り込む。 65758 5a コピー先に全角文字が鎮座しているときには、 65759 その全角文字の前に挿入する。 65760 タブが鎮座しているときにはタブは空白に変換する。 65761 65762 上の手順の 5a での挿入は p による挿入と同じ気がする。 65763 と思ったが p の場合には全角文字の前に空白を挿入して位置を調整してから 65764 挿入するのであった。つまり、微妙に振る舞いは異なる。 65765 65766 % 実装するとすると先に set-mark を統一的に実装しておく必要がある。 65767 % 1 の開始位置を覚えておくのに使うのは `[ が良いと考えていたが、 65768 % 実は `< の方が適切なのでは? と思ったが I ではそれで良いが A だと駄目なので、 65769 % このままで良い。 65770 65771 - 因みに末尾拡張の状態で A をしてそれから実行するとちゃんとそれぞれの行末に追記される。 65772 空白が挿入されて桁が合わせられるなどのことは起こらない。 65773 - また、挟まれた行で短い行があった場合には (末尾拡張でないとき)、 65774 ちゃんと空白が挿入されて桁が合わせられる。 65775 65776 取り敢えず実装した。取り敢えず動く。 65777 65778 * vi-mode: dd を続けて行うと "bash: index: substring expression < 0" というエラーが出る [#D0530] 65779 これは ble/keymap:vi/mark/end-edit の中の条件式を間違えていた。 65780 65781 * vi-mode (mark): `[ `] [#D0529] 65782 65783 直前の変更範囲または yank 範囲と help には書かれている。動作を調べる。 65784 65785 - 挿入モードの範囲も登録される。 65786 - 実際に何も入力しなかった場合でも登録される 65787 - C-o すると `[ は既に設定されていると分かる。 65788 2回目の C-o でも同じ点のようなので C-o によって挿入モードの範囲が途切れたりはしない。 65789 一方で、`] に関しては C-o する度に新しく設定し直されている気がする。 65790 と思ったが、1回目の2回目の C-o の間に何も入力しなければ `] は最初の C-o と同じになる。 65791 つまり、`] は C-o の度に設定されるのではなくて文字が挿入される度に毎回設定されていると考えるべきだろう。 65792 一方でその実装は効率が悪いように思われるので、ble.sh の実装では C-o の瞬間に実行することにする。 65793 振る舞いが多少異なることになるが、これについては何処かに説明を書いておくことにすれば良い。 65794 65795 取り敢えず operator 呼び出しの箇所と、挿入モードに入る、または出る箇所での `[ `] の設定は書いた。 65796 65797 - done: x s X delete Y S D C p P J gJ r gr でも set する必要がある気がする。要確認 65798 ビジュアルモードの各演算子も同様である。他にもバッファ内容に変更を齎すコマンドは全て対象である。 65799 65800 これは _ble_edit_str/.replace-range 及び _ble_edit_str/.delete-range を全て確認して対応した。 65801 _ble_edit_str.{reset,replace} は直接は触っていない。 65802 実のところ殆どの操作は operator の中で行っているので、変更点はそれほどなかった。 65803 65804 - rx grx に関しては ble/widget/self-insert を介して挿入を行っていたので、 65805 これは気づきにくかった。他に self-insert を介して nmap から変更を行うものはなかった。 65806 - Y S D C の内、ble/widget/vi-command/kill-current-line これも見落としていた。直した。 65807 - x s X delete の類はオペレータを介して操作しているので対策は必要ない。 65808 - p P J gJ は既に直した。 65809 65810 - done: operator で beg の更新はしているが end の更新はしていないという場合があるかも。要確認 65811 65812 というか、そもそも中身を書き換えたりすると end は意味を成さなくなっているのではないだろうか。 65813 65814 a 一つの手は operator を呼び出す前に beg - end を設定してしまうというものである。 65815 この時の問題点は2つある。 65816 65817 x 先ず領域拡張を行って変更した場合に end が beg に落ちてしまうということ。 65818 x もう一つの問題は end が末端ではなく最後の文字を指していることにより、 65819 中身に対して変更を行った場合やはり end が beg に落ちてしまうということである。 65820 65821 だとすると各 operator に対して end を正確に計算してもらうという手しかない。 65822 65823 x 更に試してみて気付いたことは operator 操作後のカーソル位置と、 65824 operator による変更位置は必ずしも一致しないということである。 65825 例えば矩形選択で先頭に全角文字が跨っている状態で d で削除すると、 65826 全角文字は空白に置き換えられてカーソルは残った空白の後に配置される。 65827 一方で `[ による変更開始位置は空白の前に設置される。 65828 実は、既に beg は変換後のカーソルの位置を指示するために使用している。 65829 ということは、変更範囲を調べるためには別の方法が必要になる。 65830 65831 b 或いは、変更操作の開始前に空の dirty range を用意して、 65832 後は shift-by-dirty-range において、その dirty range も一緒に更新する。 65833 更に変更操作の終了時にその dirty range を元にして mark を設定する。 65834 65835 この方法を用いれば end が beg に落ちてしまう問題も発生しない。 65836 各 operator で操作を指定する必要もない。 65837 65838 効率的には不満な点もあるかもしれないが、複雑さの度合いから言って妥当に思われる。 65839 或いはもっと良い効率的な方法が見つかればその方法でも良いが…。 65840 65841 結局 b の方法で再度実装し直すことにする。 65842 65843 * vi-mode 引数を指定した挿入モードを抜けた時の動きが変だ。 [#D0528] 65844 65845 先ず初めに繰り返し回数を正しく反映できていない。 65846 次にカーソル位置が正しくない。 65847 特に、次のコマンドでカーソルが変な動きをする。 65848 65849 →decompose-meta で分解される前の M-h が記録されていた。これは駄目だ。直した。 65850 65851 2017-10-10 65852 65853 * 2017-09-08 vi-mode: gi [#D0527] 65854 65855 変数 _ble_keymap_vi_insert_mark だけ用意した。 65856 65857 これは本来は mark を実装してから考えるべきである → #D0526 65858 65859 次に `^ の設定を実装する。 65860 65861 - 先ず繰り返しを行っている場合には繰り返しを行ったあとの位置が記録される。 65862 - C-c で中止をした場合でも記録される。 65863 - C-o で入ったときは現在地に移動するだけである。つまり、C-o に入る瞬間に記録される。 65864 - 未だ `^ が設定されていないときは gi はその場で挿入モードになる。 65865 65866 * vi-mode: mark 実装 [#D0526] 65867 65868 vim で mark について振る舞いを確認した所、 65869 行と列をそれぞれ覚えているようだ。 65870 文字の挿入・削除を行っても列の修正は行われない。 65871 行の挿入・削除を行うとそれに応じて行は修正される。 65872 行が削除されると mark も消滅する。 65873 65874 この振る舞いを厳密に再現する必要があるかは分からない。 65875 もし厳密に再現するとなると .kill-range / .delete-range に介入して、 65876 既存の mark について毎回複雑な計算を実行する必要があるということになる。 65877 65878 また mA と ma の振る舞いの違い (履歴項目ごとのマークかグローバルなマークか) 65879 の実装についても考える必要がある。履歴項目ごとのマークの場合には、 65880 履歴項目を移動する毎に保存・復元をするかあるいは履歴番号に紐付いた記録の方法を採用しなければならない。 65881 65882 a 毎回保存・復元をするとなると色々問題がある。 65883 先ず初めにどのタイミングで保存・復元を行うかである。 65884 65885 history/goto で保存・復元を行うとすると何らかの hook の機構を用意するか、 65886 保存・復元の対象となる変数のリストを外部から指定できるようにする必要がある。 65887 しかし、何れにしてもこれは遅そうである。 65888 65889 よく考えてみれば mark に触る機会というのは少ないのだから、 65890 いざ記録または読み出しを行おうとした段階で、 65891 現在の履歴項目に対応するものをロードするようにすれば良い。 65892 65893 b 履歴番号に紐付いた記録の方法の場合には記録に使用する文字を制限すれば (Unicode は使わず ASCII に制限すれば)、 65894 "256 * 履歴番号 + 文字" のような感じの index で配列に記録すれば良い。 65895 実際に vim で試してみると "mあ" などはエラー (bell) になる。 65896 65897 マークを大量に設定すると配列アクセスが遅くなってしまうが、 65898 そんなに大量のマークを設定することもないだろうからこれは気にしなくても良い。 65899 或いは処理の時間が気になるのであれば 65900 bash-4.0 以上では連想配列を用いるように実装を切り替えても良い。 65901 65902 これは b の実装の方が良いだろう。 65903 65904 根拠は先ず単純であること。 65905 また a が現実的であることは履歴項目に対するアクセスが少ないということに立脚しているが、 65906 もしそうならば b も同様にアクセスが少なければ問題にならない。 65907 a が b よりも効率的になるのは或る特定の履歴項目に対して連続で mark を大量に呼び出す 65908 というような場合しか無いがそのような状況は考えにくい。 65909 65910 mark として使える物にはどの様なものがあるか確認しておく。 65911 65912 global A-Z m で設定可能 65913 local a-z m で設定可能 65914 local 0-9 .viminfo で設定する? 65915 最後に訪れたときのカーソル位置と思えば良さそう。 65916 local [ ] m で設定可能。最後に yank した範囲 65917 local < > m で設定可能。最後にビジュアルモードで選択した範囲 65918 local ' ` m で設定可能。最後のジャンプ前の位置 65919 ジャンプリストと関係。 65920 local " 最後のバッファ内の位置。 65921 local ^ 最後に挿入モードを終了した位置 65922 local . 最後に変更された位置 65923 65924 これらの文字の分布には一貫性はない。 65925 格納する時のインデックスはそもそも密にする意味もないので 65926 128 (もしくは G0 の 96) をフルに使ってよいのではないかという気がする。 65927 65928 取り敢えず mark は実装した。 65929 65930 * resolved: 問題点: 現在の実装では history を load せずに幾つかコマンドを実行して行った時に問題が生じる。 65931 65932 LINENO を記録するなどして対処するべきなのではないか。 65933 但し、LINENO が増えたからと言って history にそれらが登録されているとは限らない。 65934 ということは未だ load していない時の、history に登録したカウントを ble-edit の方で記録するべきではないか。 65935 65936 うーん。調べてみると HISTCONTROL が設定されていない時には、 65937 _ble_edit_history_count をインクリメントしているが、 65938 HISTCONTROL が設定されているときには ignoredups などによって、 65939 history を実行しても実際には登録されない可能性があるということで、 65940 _ble_edit_history_count はクリアしている。 65941 65942 history を調べてみると最新の番号は history 1 で取得することができる。 65943 これを呼び出すのはそんなに大変ではないので、実のところ、 65944 これを呼び出して番号を取得しても良いのではないかという気がする。 65945 と思ったら、既に存在する ble-edit/history/getindex という関数ではこれをやっている。 65946 65947 1 done: 先ず、ble-edit/history/getcount 及び ble-edit/history/add を変更して、 65948 毎回 history 1 を実行するのではなくて変更の可能性のある操作をしたときに history 1 を実行するようにする。 65949 65950 と思ってよく見たらそのような実装になっている。 65951 寧ろ変更があった時にキャッシュをクリアし、そして getcount における遅延評価になっている。 65952 寧ろ現状の実装の方が優れていた。1点、ble/util/assign を利用するように変更はした。 65953 65954 2 done: ble-edit/history/getindex で得られる値を使用して、 65955 _ble_keymap_vi_mark_local_history を更新するように再実装する。 65956 65957 という具合にすれば良い。対応した。 65958 しかし実際に動かすと history/goto の中で呼び出している 65959 _ble_edit_str.reset で shift が発生してしまいずれてしまう。 65960 history/goto における reset では shift が起きない様にするにはどうしたら良いか。 65961 65962 似たような問題として第2のプロンプトに移行する時の reset があった。 65963 これについては keymap が vi_cmap である時には shift を行わないという方法で対処した。 65964 しかしながらもっと本質的な解決方法があるのではないかという気がする。 65965 65966 取り敢えず暫定的な方法を考える。 65967 65968 a 一つの方法は FUNCNAME 辺りを見て ble/history/goto がなければ良しとする方法である。 65969 しかしこの方法は ble/history/goto の関数名が変更されると使えなくなる。 65970 とはいいつつ関数名を変更する時には置換を行うだろうから、 65971 この関数名が変更されても問題はないように思う。 65972 65973 b もう一つの方法は ble/history/goto の中で定義されている変数名として特徴的なものを使い、 65974 それが定義されている場合には shift を行わないというようにする。 65975 或いは、敢えてそのための変数名を ble/history/goto で定義するという手もある。 65976 65977 c 或いは _ble_edit_str.reset 関数に、変更の理由を引数で渡すようにして、 65978 その理由を更に observer に伝達するという手もある。 65979 この方法が最も妥当な方法であるように思われる。 65980 65981 上記 c の方法を用いて実装することにした。 65982 以前の vi_cmap かどうかの判定も渡された引数で判定する様に修正した。 65983 この方法で実装した所初め動いていない様な気がしたが、 65984 改めて試してみると動くようになった。何故かは分からないが古いもので試していたのかもしれない。 65985 65986 * resolved: 問題点: 書いてみたけれどやはりこれは遅いような気がする。 65987 65988 特に . < > [ ] などは常に記録されていくので使い続けて行く程に 65989 _ble_keymap_vi_mark_local は肥大化していき、 65990 文字を入力する度に全てスキャンすることになるので、重くなっていく。 65991 65992 従って _ble_keymap_vi_mark_local は常に「現在の履歴項目」の情報を保持するようにして、 65993 更に、履歴項目を切り替える際に _ble_keymap_vi_mark_local を 65994 _ble_keymap_vi_mark_local_history に退避するなどの処置が必要になる。 65995 65996 更に言うと各要素を line:bytes としているので、 65997 これを分解する為の操作も馬鹿にはならない気がする。 65998 別の配列にして管理するという手も考えられるがそうすると bash の実装のせいで遅くなる。 65999 一つの配列の偶数番目と奇数番目でそれぞれ情報を格納するという手も考えられる。 66000 しかし、基本的には疎な配列なのでそれも分かりにくい。 66001 66002 →これは上記問題点の解決と同時に再実装した。 66003 66004 2017-10-09 66005 66006 * bash-3.0 local -a arr=() 対策 [#D0525] 66007 66008 bash-3.0 で local -a arr=() を使うと要素の単語分割がクォート除去よりも後で実行されるようだ。 66009 調べてみると今の所は要素に空白を含むような場合に使っていないので問題になっていないようだが、 66010 これについては適宜別の形式に書き換えるなどして、この書き方自体を追放するのが安全である。 66011 66012 - ble.sh/check に追加した。 66013 実のところ、この check 用コマンドを詳細に指定すれば 66014 local -a name=(...) が使える箇所は増えるのであるが、 66015 複雑な規則になっていると人間の側が間違える可能性が大きくなるので、 66016 やはり一律に禁止する方が懸命であると思われる。 66017 66018 - と思ったがやはり local -a arr=() を使えないのは辛いので、 66019 check の条件を詳しくすることで、特定の local -a arr=() についてはそのまま使えるようにした。 66020 66021 * vi-mode (visual block): < > [#D0524] 66022 振る舞いが違う→実装した。 66023 66024 * vi-mode: indent の幅を設定できるようにするべきなのでは。 [#D0523] 66025 66026 8 は大きすぎるので既定で 4 にして、自分で 2 に指定するなど。 66027 というかこれは vi-mode 特有の設定というよりは全体の設定でもある気がする。 66028 全体の設定に追加することにする。 66029 bleopt_shell_indent などの変数名が良いだろうか。 66030 66031 変更対象は vi.sh 及び vim-surround.sh の indent 関係の所にある。 66032 →対応した。 66033 66034 * vim-surround.sh: xmap S, gS [#D0522] 66035 66036 S と gS の振る舞いを調べると、S は v, C-v に対しては ys と同様に働き、 66037 V に対しては yS と同様に働くようだ。 66038 66039 %%gS はその振る舞い (ys vs yS) を反転させた物になる。%% 66040 surround.vim を簡単に見てそう判断したが実際に読んでみると分からない。 66041 :help surround を見てみると vgS は vS と同じで、VgS は VS のインデントを行わない版で、 66042 <C-v>gS は末尾拡張した領域に対して囲みを適用するということの様だ。 66043 <C-v>gS は Vim script からは末尾拡張かどうかが分からないために必要と書かれているが、 66044 実は ble.sh vi-mode の枠組みでは自然にこれは対応できてしまうので 66045 敢えてその様に動作させる必要はなかったりする気がする。 66046 それでもその様に対応することにする。 66047 66048 その為には先ず yS に対応しなければならない。yS は行指向の動作である。 66049 囲まれる文字列の前後に改行を挿入してインデントするという動作の様だ。 66050 因みに空白を指定すると <left><LF><SP><indent>content<LF><SP><indent><right> という感じになる。 66051 インデントがある場合には空白を前後に置かないのが自然なのではないかと思う。 66052 66053 実装した。チェックする。 66054 66055 yS は動いている。ySS も動いている。xmap S も動いている。xmap gS も動いている。 66056 但し、何れについても再インデントには対応していない。 66057 66058 序に cS も実装したらどうか。調べてみると cs と殆ど同じで挿入するものが異なるだけだそうだ。 66059 これは簡単に実装できると思う。実装した。 66060 66061 * vi-mode: bug: g? を set-operator rot13 にしていたが、 [#D0521] 66062 これは数字が入っているので使えないのでは? 66063 →実際にやってみたら使えなくなっていた。修正する必要がある。 66064 66065 というか、これを機に _ble_edit_arg に全て入れるのを止めた方が良い気がする。 66066 set-operator も operator 辺りに改名する。 66067 _ble_edit_arg の形式で場合分けをしているが、これは kmap を以て場合分けするのが良い。 66068 また、本当に omap の時にしか _ble_edit_arg が存在しないのか確認する必要がある。 66069 66070 →オペレータの記録の方法を作り直した。 66071 元々今の仕組みはオペレータの枠組みの全体を知らずに適当に作った物を騙し騙し使っていた物だった。 66072 今となっては一つの変数で全てを記録するのは辛いし、 66073 また _ble_edit_arg の形式が本体の ble/widget/ の想定するものと異なる点も良くない。 66074 _ble_edit_arg は空か数かのどちらかでないと都合が悪いのだ。 66075 作り直した。余り大きな変更もなく作り直すことができた。 66076 66077 * vi-mode (normal mode): C-d で抜けても良いのでは。 [#D0520] 66078 66079 そもそも vim では C-d は何に割り当てられていたのだったろうか。 66080 →スクロール用のコマンドの様だ。これは滅多に使わないので、 66081 zsh と同様に C-d でシェルを抜けるようにしても良いように思われる。 66082 66083 と思ったが、よく考えたら空文字列の時にはそもそもスクロールもしようと思わないだろうから、 66084 空文字列の時に限り抜けるようにして、それ以外の時にはスクロールという様にすることも可能のはずである。 66085 66086 * magic-space: 現状の実装では空白を入れてから展開しているが、 [#D0519] 66087 :s/ などが終端していない状態でこれを実行すると空白が余分についてしまう。 66088 →修正した。更に dirty-range も最小限になるように修正した。 66089 66090 * vi-mode (insert): @norepeat [#D0518] 66091 66092 実は norepeat でないコマンドは数える程しかないのだから、 66093 それ以外全てで norepeat を実行するように __before_command__ に書くほうが懸命なのでは。 66094 66095 実装した。動いている。これにより @norepeat は改名対象ではなくて削除対象になった。 66096 master へ merge する直前に適用することにする。 66097 66098 * vi-mode (cmap): / ? n N [#D0517] 66099 66100 * C-c で抜けても実行されてしまう。キャンセルするべき。 66101 →これは単にバグだった。直した。 66102 66103 何もないときに DEL を押したときもキャンセルにする? 66104 これは試してみると / や ? ではキャンセルになるが、 66105 surround.vim の < ではキャンセルにならない。 66106 実装によるということである。 66107 だとすると、(surround.vim で > を打つと終わりになることを含めて、) 66108 cmap のキーマップに介入できるようにする仕組みを整えたい。 66109 66110 例えば cmap/__before_command__ で外部関数を呼び出すようにして、 66111 その外部関数の名前を登録できるようにしておく。 66112 __before_command__ で好きに処理をして、 66113 もし元から設定された動作をキャンセルするときには、 66114 COMMAND= としてしまえば良い (ble-decode.sh の側で次に実行する widget は COMMAND に入れている)。 66115 というかこれは WIDGET に名称を変更した方が良い気がする。 66116 と思ったが、-cf で通常のコマンドを呼び出すときにもこれは使っている 66117 更に、widget を呼び出すときも zsh の所謂 widget ではなくて、前に ble/widget/ の prefix がついている。 66118 やはり COMMAND で良いような気もする。と思ったが、COMMAND は他の用途にも使われるので、 66119 後で一括で置換したいときなどに不便である → と思ったが COMMAND という変数はこの用途でしか使っていなかった。 66120 66121 - 取り敢えず COMMAND はそのまま。__before_command__ で COMMAND= を実行することでキャンセルできる。 66122 - シェル変数 _ble_keymap_vi_cmap_before_command で async-commandline-mode で呼び出される cmap に介入できるようにした。 66123 - vim-surround.sh のタグ名入力で > で確定するように修正 66124 - search / ? で、空文字列で DEL or C-h することでキャンセルするように修正 66125 - 序に ble-bind -L で . を含む関数名を表示しないように修正 66126 66127 66128 2017-10-07 66129 66130 * 2017-10-01 vi-mode (visual mode): r s C S R x D X Y p J U u I A ^] [#D0516] 66131 66132 done: J gJ → これは別項目 #D0540 で処理 66133 done: u U r s C S R X D x Y 66134 done: I A #D0531 66135 done: p P #D0536 66136 保留: ^] これは何処で見たものか何故か書かれていたが実際対応しなくて良い。 66137 b4b4r07/zsh-vimode-visual で見たかと思ったが、改めて確認したところない。 66138 66139 C は char のとき一旦行指向になってから .save しているようだ。1v などとすると分かる。 66140 66141 いろいろ試してわかったこと。 66142 66143 - 矩形モードで C を押すと次に 1v を実行したときに末端までの拡張状態になる。 66144 - 矩形モードで $ を押すと末端までの拡張の状態になる。 66145 - 普通の移動の方法では末端までの拡張にはならない。 66146 - 末端までの拡張の状態で、行末にいる状態で "13|" などとして 66147 動かないようにしても末端までの拡張モードは解除される。 66148 つまり位置の移動を監視して末端までの拡張かどうかを切り替えるのではなく、 66149 移動に関するコマンドが実行されたかどうかで末端までの拡張かどうかが切り替わる。 66150 - 更に v で $ に行ってから C-v としてもちゃんと末端までの拡張になっている。 66151 それどころか v $ を復元するときも本の列ではなく末端になるようだ。 66152 - さすがに OO を押して端点を交換すると末端までの拡張は解除される。 66153 従って、端点毎に "末端拡張" かどうかの状態があるのではなくて、 66154 端点の座標とは独立に "末端拡張かどうか" という情報が記録されていると思われる。 66155 66156 つまり、何か別の変数があって移動すると切り替わるようだ。 66157 66158 66159 * done: 先ず、現在末端拡張の状態かどうかを保持する変数を用意する。 66160 * done: 先ず extract-block の末端拡張のときの振る舞いを実装する。 66161 * done: それから save/restore の振る舞い。 66162 末端拡張が有効の時は char として $ を記録するようにする。 66163 * done: 移動コマンドが必ず呼び出している関数として adjust-command-mode がある。 66164 これに手を入れて末端拡張かどうかを弄るようにしたらどうだろうか。 66165 * done: また $ のコマンドを弄って xmap のときは adjust-command-mode より後に、 66166 _ble_keymap_vi_xmap_eol_extended=1 を設定するようにする。 66167 66168 取り敢えず現状で push することにした。 66169 66170 * 2017-10-01 vi-mode: 前回からの動作の修正 [#D0515] 66171 66172 - vi-mode bug: 行単位のインデントオペレータ (`>>` など) でエラーが出るバグを修正 66173 - vi-mode bug: オペレータ `g~` を呼び出せないバグを修正 66174 - vi-mode bug: `k` `-` `G` `gg` などで履歴項目を移動したときに(最後の文字でなく)行末にカーソルが来るバグの修正 66175 - vi-mode bug: オペレータ `>` および `<` で空行が消滅するバグの修正 66176 - bug: "ble-bind -d" の内部でパス名展開が起こって出力が正しくないバグの修正 66177 66178 - vi-mode change: `c{linewise}` (`{linewise}` = `j` `k` `H` `L` `+` `-` `gg` `G`) のとき空行を挿入するように修正 66179 - vi-mode change: `d` で最終行を削除したとき前の行に移動するように修正 66180 - vi-mode change: `f` `F` `t` `T` `r` `gr` に C-? の形式で文字を指定できるように修正 66181 - vi-mode change: `dd`, `yy`, etc. および `D` は最終行で 2 以上の引数を与えるとエラーにするように修正 66182 66183 - vi-mode: _ g0 g<home> g^ g$ g<end> gm go g_ ge gE / ? n N : 66184 - vi-mode: ビジュアルモード (char, line, block) 66185 - vi-mode: vim-surround.sh にて囲み文字として t T < を指定したとき、タグ名の入力を受け付ける 66186 - edit: 複数行編集時スクロール 66187 66188 * 2017-09-18 vim-surround: ds cs テキストオブジェクト [#D0514] 66189 66190 - done: pst に対応する。これは本体のテキストオブジェクトを先に対応させる必要がある。 66191 - done: 更に t に関しては第2のプロンプトを表示できるように改修する必要がある。 66192 → 第2のプロンプトに対応したので対応した。 66193 66194 * vi-mode: 正規表現検索 [#D0513] 66195 66196 | 2016-07-07 isearch: 正規表現検索? 66197 | 66198 | incremental にするのは難しい。というのも正規表現の内容を変えると一致位置が戻ってしまうかもしれないから。 66199 | 例えば abc|def として検索した時に abc まで入力した時に文字列 "def" を通り越して 66200 | "abc" に一致したとする。すると、続いて |def を入力した時に、通り越した "def" をどの様に処理するのかという問題が生じる。 66201 | その正規表現に対する "直近の一致" に拘るのであれば、一旦通り越した "def" を拾う為に、再度検索を一からやりなおす必要がある。 66202 | 或いは、emacs の様に現在の位置から検索の続きを開始するという方法でも良いがこれは直観的でない。 66203 | 66204 | 最終的にもし incremental にするとしたら Emacs の様な方式になるだろうが、 66205 | 必要が生じるまでは incremental な search は提供しなくても良いだろう。 66206 | というかそもそも正規表現検索自体必要なのか分からない。 66207 | 66208 | 正規表現による置換などについては需要があるかもしれない。 66209 | 66210 | 66211 | 更に組み込みの正規表現を用いて一致を行うにしても問題がある。 66212 | 組み込みの正規表現では途中からの一致に対応していない。 66213 | 従って、文字列の部分文字列を作成する事によって途中からの一致に対応する事になるが、 66214 | その様にすると ^ や $ の意味が変わってしまう。そこで、途中で文字列を切った場合には何か padding の様な物を付加するとしても 66215 | 今度はその padding に一致してしまう事を阻止できない。 66216 | また %%padding の内容をどうするかによって \b や \B の意味が変わってしまう。%% 66217 | →これについては隣接する文字をそのまま padding として採用すれば良い。 66218 | が、隣接文字に対する一致を阻止できないので、結局文字列を切らずに一致を試みるのと大差ない。 66219 | 66220 | - 因みに正規表現の一致位置を探すのはそんなに面倒ではない。正規表現の先頭に ^(.*) などと付加しておけば、 66221 | ${#BASH_REMATCH[1]} が一致開始位置になる。ただキャプチャの番号が一つずつずれる事に注意すれば良い。 66222 | →と思ったが、これだと .* が greedy に文字を消費してしまう。 66223 | それよりは正規表現末尾に (.*)$ を付加した方が精確である。 66224 | それにより開始位置は $((${#target}-${#BASH_REMATCH})) になる。 66225 | キャプチャグループの番号もずれないのでこれが良い。 66226 | 但し、一致文字列全体の長さを得る時に $((${#BASH_REMATCH}-${#BASH_REMATCH[n]})) などとする必要がある。 66227 | - これを応用すれば例えば位置 14 から一致を試みたい時には、正規表現の先頭に 66228 | ^(.{14}.*) などという物を付加すれば良いのではないか。 66229 | しかしこれだと先に述べたのと同様に .* が greedy に文字を消費してしまう。 66230 | それよりは .{14}(rex)(.*)$ 等の様にするのが良さそうだ。 66231 66232 * 2017-10-07 気付いたのだが実は後方参照 \1 が使える。 66233 ということは rex を () で囲む為には後方参照の番号のずれも考慮にいれなければならない。 66234 rex を直接使うのは難しい。何故なら rex=A|B の構造になっているかもしれないから。 66235 なので、何れにしても .*(rex) または (rex).* などのようにしなければならない。 66236 そうしないと一致位置を取得するのが難しい。実際できるのか? 66237 66238 もし () で囲んで後方参照の面倒も見るとすれば、更に余分に () を増やしても構わない。 66239 なので気にせず色々弄ることができる。 66240 66241 forward に位置 14 から検索するときは 66242 66243 rex=".{14}($needle)(.*)\$" 66244 66245 などとする。backward に位置 len-14 から検索するときは 66246 66247 rex="^(.*)($needle).{14}" 66248 66249 などとすれば良い。最初または最後の .{14} は、検索対象の文字列を 13 文字削るなどすれば 66250 . にまで縮めることができる気がするが、 66251 それによって特に効率的になるとも思われないので、このままで良い。 66252 寧ろ検索対象の文字列を削るか削らないかなどの場合分けが面倒である。 66253 66254 66255 $needle に含まれる後方参照をシフトするためには、 66256 $needle を簡単に parse しなければならない。 66257 先頭から順に見ていく。 66258 66259 '\\.|\[^?\]?(\[:[^]:]*:\]|\[\.[^].]*\.\]|\[=[^]=]*=\]|[^][])*]' 66260 66261 '\\.' 66262 '\[^?\]? 66263 ( 66264 | \[=[^]=]*=\] 66265 | \[\.[^].]*\.\] 66266 | 66267 |[^][])*]' 66268 66269 66270 - 試してみると [.<collating-char>.] にも対応しているようだ。 66271 rex='[[.a.]]' ; [[ a =~ $rex ]] # sucsses 66272 rex='[[.a.]]' ; [[ . =~ $rex ]] # fail 66273 66274 - [[=<c>=]] にも対応している。 66275 - \< \> にも対応している。\b も。[[:<:]] などは対応していない。 66276 66277 * 取り敢えず incremental な検索は現実的ではないが、 66278 通常の検索として実装するのはそんなに問題はない。 66279 66280 - done: 先ず検索部分のコードは分離した。 66281 - done: 後方参照のシフトがちゃんと動くかを確かめる必要がある。 66282 66283 動いていない。使っている正規表現が正しくないと出ている。確かめる。以下のものが使われている。 66284 ^(\[^?]?(\[[:][^]:]+[:]\]|\[[=][^]=]+[=]\]|\[[.][^].]+[.]\]|[^][]|\[[^]:=.])*[?\]|\\[^1-8])*\\[1-8] 66285 66286 ^(\[\^?]?(\[[:][^]:]+[:]\]|\[[=][^]=]+[=]\]|\[[.][^].]+[.]\]|[^][]|\[[^]:=.])*\[?\]|\\[^1-8])*\\[1-8] 66287 66288 - 一箇所直した [? は \[? であるべきだった。しかしこれは正規表現が正しくない理由にはならない。 66289 - どうやら \[[:][^]:]+[:]\] が駄目と言っている → と思ったら勘違いだった。 66290 - 分かった。 ^? ではなくて \^? としなければならない。 66291 66292 取り敢えず一番簡単な場合で動くことを確かめた。 66293 色々動かしてみたが、恐らく大丈夫だろう。 66294 66295 * vi.sh に実装してみたが色々変だ。動作確認する。 66296 66297 x fixed: n で前の検索を繰り返そうとすると何も起こらない。 66298 →これは前の検索文字列をロードし忘れていたために空文字列で検索していた。 66299 66300 x fixed: 一致位置が変だ → 正規表現一致後の範囲の計算が誤っていた。修正した。 66301 66302 x fixed: 表示が崩れる。これは / ? で第2プロンプトを使用したときでもなるが、 66303 n N で前の一致を繰り返した時でもなる。つまり第2プロンプトは関係ない。 66304 更に、何れも2回目以降の一致で変なことになる。 66305 66306 これは不思議だ。表示と検索機能は完全に直行しているはずなのに起こっている。 66307 しかも、表示位置が先に進むのではなくて逆方向に戻っている。1文字ずつ戻っている。 66308 つまり、何か余計な文字列が出力されているという訳ではなく、座標計算の方が怪しい。 66309 66310 C-l で再描画すると直るが n で検索し直すと再度発生する。 66311 つまり、検索の関数の中で何か誤ったことをしている。 66312 もう一つの手がかりは更新される内容がずれているということである。 66313 region layer が怪しい。umin umax の問題か、或いは buff の繋ぎ変えに失敗しているか。 66314 66315 うーん。S-left に依る移動などでも再現することが分かった。 66316 つまり、これは region レイヤーでの buff の繋ぎ変えが怪しい。 66317 しかし、改めて試してみると変な状態になっているときには S-left は不味いが、 66318 検索機能を使っていない限りは S-left が変なことになることはない様だ。 66319 66320 search を実行することによって何かの機能が破壊されている。 66321 うーん。正規表現かどうかは関係なく発現するようだ。 66322 調べてみたら、なんと plain_buff が滅茶苦茶なことになっている。何故? 66323 あー。分かった。。plain_buff が textarea の復元の対象になっていないということか。 66324 66325 ところがちゃんと復元リストの中には入っているようだ。 66326 と思ったがそもそもこの復元リストも変だ。何か重複があるし、復元しなくても良いものまで入っている。 66327 よく見たら ${!_ble_highlight_layer_$layer*} とするべきところが ${!_ble_highlight_layer_$name*} になっていた。 66328 そしたら直った。何故だろう。前のミスでは過剰に復元変数が列挙されていたのが問題だった。 66329 今回の修正で復元対象の変数は減少したはずなのに正しく復元できるようになったのは不思議だ。 66330 66331 - done: 一致している状態で次の一致を探して失敗したとき、 66332 今一致している状態を保持したい。 66333 66334 x fixed: 範囲がずれている。 66335 66336 x 履歴後方で末端で一致したときに再一致できない 66337 これは行の最後の文字にカーソルがいるときに一致しないということだろうか、と思ったら違った。 66338 調べると .call-search の中で範囲を調整する条件がいけなかった。 66339 同じものに再一致することを防ぐための条件がいけなかった。 66340 66341 x fixed: というか G で編集文字列の行末に移動できる 66342 66343 x fixed: 履歴検索に時間がかかった後、progress が表示されたままになっている。 66344 66345 x fixed: 履歴検索の progress で検索文字列が表示されていない。 66346 これは変数 _ble_edit_isearch_str を指定しなければならない。 66347 66348 x fixed: progress の表示間隔が短いのは何故だろう。 66349 forward search 時に 1項目ごとに表示されている気がする。 66350 従来の isearch ではちゃんと期待通りに 1000 項目ごとにしか表示されていない。 66351 従って、コードが破壊されたとかそういうことではないはず。 66352 と思ったら stop_check のときにしか isearch_time を incr していなかった。修正した。 66353 66354 後は空一致のときに何がおこるのかという事である。 66355 現在の実装では空一致のときには一致しなかったのと同じ状態になる。 66356 この時 n や N をしても次の空一致に移動するということが起こらない。 66357 というかむしろ backward に検索するときには逆方向に移動していく気がする。 66358 66359 念のため vim でどういう振る舞いになるかを確認することにする。 66360 と思ったら vim は空一致の場合にはパターンが見つからなかったと勘違いするようである。 66361 もしもっと前に進めば非空な一致を見つけることができるとしても、 66362 途中で空一致にぶつかってしまったらそれ以上探すのをやめ、見つからなかったという扱いの様だ。 66363 (これは例えば h? のような正規表現で確認することができる) 66364 66365 →対応した。 66366 66367 * done: 次に引数に対応しなければならない。これは繰り返し一致させるというようにするしかない。 66368 66369 さて、{count} 番目の一致が見つからないときの動作はどうするべきか。 66370 vim で試してみるとまた buffer の先頭に戻って続きを検索するので、 66371 1 つでも一致するのであれば、必ず一致する。 66372 66373 ble.sh でどうするか。また履歴の最初に戻るというのはとても分かりにくい。 66374 従って、取り敢えず一番最後に一致したものということで問題ない気がする。 66375 そう考えれば、単に繰り返し回すだけで良いので実装としても楽だ。 66376 66377 取り敢えず対応した。 66378 66379 取り敢えず現在の問題点を解決したら commit する。 66380 66381 x fixed: オペレータから呼び出せない → これは omap にも登録しなければならないからだった。 66382 66383 x fixed: 引数を指定しようとすると一致状態が解除されてしまい、ずれる。 66384 66385 →やはり matched の状態を設定・解除するのは adjust-command-mode のタイミングであるべき。 66386 その様に修正した。同時に他のモードに移行するなどの場合に _ble_edit_mark_active を解除する必要がある。 66387 66388 x fixed: 今度は最後に一致した状態で次の一致が見つからないときに、 66389 一致状態が解除されてしまう問題について。 66390 これは新しい _ble_edit_mark_active の設定・解除にしてから起こるようになった。 66391 →どうやら adjust-command-mode が search.impl の中から複数回呼び出されているのが行けない。 66392 唯一回だけ呼び出されるように修正した。直った。 66393 66394 66395 2017-10-05 66396 66397 * vi-mode: dd yy ... の最終行での振る舞い [#D0512] 66398 66399 行数が足りないときにはエラーになる。 66400 他のオペレータについても一様に同じようだ。 66401 66402 % 更に D は dd と違って末尾にいても行を削除しないようだ。 66403 % D も行数が足りないときにはエラーになる。 66404 % と思ったらこれはそもそもぜんぜん異なる働きをするコマンドだった。 66405 66406 D は 1 より大きい引数を指定して一行も動けないときエラー。 66407 66408 実は dd や yy の場合も同様のようだ。直した。 66409 66410 * vi-mode (visual mode): S [#D0511] 66411 66412 何やら次の引数を読み取ろうとしている気がする。何故か。 66413 と思ったら、これは surround.vim の仕業だった。 66414 66415 * vi-mode (visual block): 行末にいるときの範囲がずれている。 [#D0510] 66416 行末から右に1文字のところが境界になる。 66417 66418 * vi-mode (visual): vim では | で行末に行けるようだ。 [#D0509] 66419 66420 * 2017-09-12 表示レイアウト管理の方法について [#D0508] 66421 66422 | これは現在問題になっている、一番下の行で info が表示されなくなってしまうこととも関連する。 66423 | 66424 | presentation : form 66425 | \_ textarea : control 66426 | | \_ content : ble-edit/content 66427 | | \_ prompt : ble-edit/prompt 66428 | | \_ layout : ble/textmap 文字の配置 66429 | | \_ render : ble-edit/layout 66430 | \_ info : control 66431 | 66432 | もし本格的なウィンドウシステムを実装するとしたら、 66433 | 66434 | 1 textarea は一つのコントロールとして管理するべきである。 66435 | 2 textarea 毎に _ble_edit_str などの content が存在するべき。 66436 | 3 着色の設定も textarea 毎に管理するべきだ。 66437 | 66438 | 4 全ての入力は textarea を一回経由してから処理する。 66439 | というのも処理対象の _ble_edit_str を選択するため。 66440 | というかそもそも keymap だって textarea に紐付いているのではないか。 66441 | 66442 | と思ったが、これは少し違う。 66443 | ウィンドウは単一で機能を持つこともあれば、 66444 | 一つの機能を提供するために複数のウィンドウを組み合わせることもある。 66445 | 現在ある info や将来実装するかもしれない補完候補のメニューなどは、 66446 | 固有の機能を持っているものではなくて、textarea と組み合わせて使うものである。 66447 | 66448 | そのように考えるとウィンドウの集合と keymap は対応付けられるべきである。 66449 | .NET Frameworks の類推で親ウィンドウを form と称して 66450 | 子ウィンドウを control と称して考えると分かりやすそうだ。 66451 | 66452 | 何か話がとんでもない方向にそれている。元々は関数名の話だった。 66453 | 66454 | これは別の話として切り離すべきだ → #D0439 から切り離した。 66455 66456 #D0505, #D0507 取り敢えず ble/textarea として分離して実装し、 66457 第2のプロンプトを表示できるようにした。 66458 ble/textarea としての振る舞いを観察して、 66459 また需要が出てきたら control などの仕組みについては再度考え直す。 66460 66461 * 2017-09-17 第二のプロンプト・編集文字列を出すということについて。 [#D0507] 66462 66463 info の上で表示する様に再実装しても良いが、 66464 やはり似たようなコードが重複して存在するのは気になる。 66465 将来的にも必要になると思われるので、現状の ble-edit の仕組みを 66466 複数の編集文字列に対して適用できるように拡張する方が自然なのではないだろうか。 66467 66468 更に info はカーソルの位置に関しては管理しない。 66469 カーソルの位置は現在全て本体の編集文字列の描画で設定されている。 66470 66471 さて、複数の編集文字列を取り扱えるようにするには何が必要であるかを考える必要がある。 66472 66473 | * 先ず初めにどの変数を差し替えれば 66474 | 別の編集文字列を取り扱えるようになるかを調べる必要がある。 66475 | 66476 | それらの変数をひとまとまりとして textbox 的な概念にまとめるのが良い。 66477 | もっというと、今回の第二の編集文字列を出すということに特化したものではなくて、 66478 | 一般に textbox としての component を独立させるとしたらどうなるかという事を意識して 66479 | 実装したほうが汎用的で整理された実装になる気がする。それを目指す。 66480 66481 → これは ble/textarea としてまとめることにした。状態の保存・復元にも対応した。#D0505 66482 66483 * 序にいうと表示の幅や高さも管理できるようにしたい。 66484 66485 * 実は ble-decode の decode 状態も textbox 毎に用意するべきなのではないか。 66486 だとすると先ずは ble-decode について切り替える仕組みを整える必要が出てくる。 66487 66488 % うーん。思ったのだが、面倒なので第二のプロンプトなどと言わずに read -e -p / で良いのでは? 66489 % →と思ったが bind で全て上書きしているのが祟って動かない。 66490 % これは read -e も再実装する必要があるということを意味する。 66491 66492 [実装] 66493 66494 取り敢えずは decode 状態については考えないことにする。 66495 textarea を切り替えると同時に keymap も変更するということにする。 66496 動いた。取り敢えず : を簡単に実装してみた。動く。 66497 66498 * _ble_bash_loaded_in_function 条件が反転している [#D0506] 66499 66500 * 2017-09-17 第二のプロンプト・編集文字列を出すということについて (1) 状態を保存・復元する仕組み [#D0505] 66501 66502 1 存在する変数について整理する。 66503 66504 _ble_edit_prompt=("" 0 0 0 32 0 "" "") 66505 66506 ble/textmap# 66507 _ble_textmap_* 66508 66509 ble-highlight-layer 66510 _ble_highlight_layer_RandomColor2_buff 66511 _ble_highlight_layer_RandomColor_buff 66512 _ble_highlight_layer__list 66513 _ble_highlight_layer_disabled_buff 66514 _ble_highlight_layer_disabled_prev 66515 _ble_highlight_layer_overwrite_mode_buff 66516 _ble_highlight_layer_overwrite_mode_index 66517 _ble_highlight_layer_plain_buff 66518 _ble_highlight_layer_region_buff 66519 _ble_highlight_layer_region_osel 66520 _ble_highlight_layer_syntax1_table 66521 _ble_highlight_layer_syntax2_table 66522 _ble_highlight_layer_syntax3_list 66523 _ble_highlight_layer_syntax3_table 66524 _ble_highlight_layer_syntax_buff 66525 66526 誰も使っていない _ble_highlight_layer__buff=() は削除することにした。 66527 _ble_draw_trace_{brack,scorc} は関数内で定義することにした。 66528 66529 % ble-edit/text/update 66530 % _ble_line_text_buff=() 66531 % _ble_line_text_buffName= 66532 % 66533 % ble-edit/render/* 66534 % 66535 % _ble_line_cur=(0 0 32 0) 66536 % _ble_line_scroll= 66537 % _ble_line_gendx=0 66538 % _ble_line_gendy=0 66539 % _ble_line_dirty=-1 66540 66541 ble/textarea 66542 _ble_textarea_buffer=() 66543 _ble_textarea_bufferName= 66544 _ble_textarea_cur=(0 0 32 0) 66545 _ble_textarea_scroll= 66546 _ble_textarea_gendx=0 66547 _ble_textarea_gendy=0 66548 _ble_textarea_invalidated=1 66549 _ble_textarea_cache=() 66550 66551 ble-syntax 66552 _ble_syntax_text= 66553 _ble_syntax_stat=() 66554 _ble_syntax_nest=() 66555 _ble_syntax_tree=() 66556 _ble_syntax_attr=() 66557 66558 _ble_syntax_attr_umin=-1 66559 _ble_syntax_attr_umax=-1 66560 _ble_syntax_word_umin=-1 66561 _ble_syntax_word_umax=-1 66562 これらの変数は ble-highlight-layer:syntax から参照するためにある。 66563 66564 _ble_syntax_vanishing_word_umin=-1 66565 _ble_syntax_vanishing_word_umax=-1 66566 これは ble-highlight-layer:syntax/update-word-table の暫定的(?)な実装に使っている。 66567 66568 _ble_syntax_dbeg=-1 66569 _ble_syntax_dend=-1 66570 これは ble-syntax/parse 解析中断をした時に復元するためにある。 66571 但し現在は解析の中断の対応していないので、常に -1 である。 66572 66573 因みに文法を指定しているのは ble-syntax/parse 中の以下の行である。 66574 66575 ctx="$CTX_CMDX" 66576 66577 他の文法にも対応するためにはこの値を何らかの変数を用いて初期化する必要がある。 66578 例えば、_ble_syntax_lang=bash としておいて、 66579 66580 ble-syntax:$_ble_syntax_lang/initialize-context 66581 66582 のような関数を呼び出すと ctx に呼び出しが入るなど。 66583 66584 こうして見てみるととても沢山の変数が存在している。 66585 これらをえいやと切り替えるのはとても大変そうだ。 66586 66587 2 ble-edit/render 統合 66588 66589 ble-edit/text/update は ble/textarea#update-text-buffer とすることにする。 66590 ble-edit/render/* は ble/textarea#render/* にする。 66591 ble/textmap#slice は実のところ ble/textarea#slice-text-buffer が良い。 66592 66593 ble-edit/render/update-adjusted では、 66594 $bleopt_suppress_bash_output であっても念のためと称して 66595 READLINE_LINE, READLINE_POINT を設定していたが、 66596 何か問題になるとも思われないので、 66597 $bleopt_suppress_bash_output の時には適当な値を設定して抜けることにした。 66598 また、関数名は ble/textarea#adjust-for-bash-bind とした。 66599 66600 _ble_line_dirty 66601 現在 _ble_textarea_dirty は -1 か空文字列かのどちらかの気がする。 66602 と思ったが、一応 _ble_edit_str.replace で設定はしている。 66603 一方で、実際に使っているのかどうかは怪しい。 66604 結局、_ble_edit_dirty_draw_beg と役割が重複しているので、 66605 _ble_textarea_dirty 改め _ble_textarea_invalidated は、 66606 完全再描画の要求がされたかどうかだけの状態を保持することにした。 66607 66608 現在以下の変数が存在している。 66609 66610 _ble_textarea_buffer=() 66611 _ble_textarea_bufferName 66612 _ble_textarea_cur=(0 0 32 0) 66613 _ble_textarea_scroll= 66614 _ble_textarea_gendx=0 66615 _ble_textarea_gendy=0 66616 _ble_textarea_invalidated=1 66617 _ble_textarea_cache=() 66618 66619 3 切替方法について 66620 66621 何処に値を保存しておくかということ。 66622 そのまま保存すると沢山の変数を汚すことになる。 66623 何処か一つの変数に保存しておいて eval するだけで復元するということにならないか。 66624 66625 | a "declare -p" の出力を利用する方法 66626 | 66627 | 但し、直接使うとローカル変数に勝手になってしまったり、復元できなかったりするケースがあるので、 66628 | 出力は可能しなければならない。その為に以前書いた関数 ble/util/declare-print-definitions を見てみると、 66629 | これは出力を整形するために awk を使っている。遅い。頻繁に呼び出せるものではない。 66630 | 66631 | 或いは、テキストボックスのフォーカスが移動するのはそんなに頻繁ではないはずだから、 66632 | 毎回瞬間的に切り替えるのではなく、現在フォーカスが当たっているものが常に表を占拠するようにすれば良い。 66633 | だとすれば多少重くても良いかもしれない。しかし重くても良いのであれば、やはり沢山の変数を汚しても良い? 66634 | と思ったけれど、むしろローカル変数で瞬間的にというわけではなく、まとめて退避するということから、 66635 | やはり一つの変数に記録する方が良い。 66636 | 66637 | さて declare や typeset を用いるとごみが入る。set だとごみが入らない。 66638 | と思ってマニュアルを探したが set で指定した変数だけ出力するということはできない。 66639 | というか declare でも引数を指定せずに呼び出すとごみは入らない。 66640 | declare -p のようにするとゴミが入る。typeset -p でも同様。 66641 | local -p とすると何も表示されない。何故? 66642 | 66643 | b ローカル変数にコピーして local する案 66644 | 66645 | 所で、local とすると現在のフレームの変数だけ出力されるようだ。 66646 | 最終的にはこれを使うという手もある…と思ったが、 66647 | 同じ変数名で local a=$a として外の値を継承できるのか? bash-3.0 で試してみると 66648 | 66649 | - local a だと変数は空になる。 66650 | - local a=$a だと外の値を持つ (bash-3.0-4.4)。 66651 | - local -a a=($a) だと空になる (bash-3.1, 4.3-4.4)。外の値を持つ (bash-3.0, 3.2-4.2)。 66652 | 66653 | 最後の項目に関しては興味深い。実は同じスコープで既に local となっていても空になる。 66654 | うーん。従って。一旦、別の変数にコピーして、それから改めて同名の local 変数に書き戻して、 66655 | その上で local を実行するか。 66656 | 66657 | 或いは、変数名を __to_remove___ble_edit_str などのようにして、そこにコピーして、 66658 | それから local を実行してから、変数の中身の __to_remove__ を削除するか。 66659 | 但し、それだと変数の値に __to_remove__ が含まれているとそれが消滅する。 66660 | 特に、これの動作のテストのために丁度コマンドラインに同じ文字列 __to_remove__ が含まれる可能性はある。 66661 | 何れにしても、恣意的に構成されたコマンドラインで問題になるので一種の脆弱性になるかもしれない。 66662 | 66663 | 何れにしても、この方法だと全変数を一旦 local 変数にコピーするという操作は不可避なので、 66664 | 単に全変数を直接退避する方法と比べると、変数を減らすということ以外に利点がない。 66665 | 66666 | c 或いは手動で生成できるか。 66667 | 66668 | すぐに eval できる形にするのは難しい。 66669 | それに一発で eval できなくても良いのではないだろうか。 66670 | そう考えると 66671 | 66672 | aaa=(_ble_edit_str content 66673 | _some_array[3] hello1 hello2 hello3 66674 | _some_scalar value) 66675 | 66676 | などの形に配列に格納するというのも手である。 66677 | と思ったが、これは構築も復元もいかにも遅そうである。 66678 | すぐ eval できる形に手動で整形するのは難しい。printf %q には古い bash でバグが有るし、 66679 | もし printf %q を用いるとしても 文字列の結合を繰り返さなければならないことに変わりはない。 66680 | 66681 | ただ、awk を起動するよりは速いかもしれない。 66682 | (それでも長い編集文字列を扱うとこれは格段に遅くなるだろう) 66683 66684 うーん。結局単一の変数にコピーするのは難しそうである。 66685 方法があるとすれば一旦ローカル変数にコピーしておいて、 66686 そこで local を実行するという方法しか現実的なものはないと思われる。 66687 66688 取り敢えずは変数の集合として保存するという方法で我慢することにする。 66689 66690 取り敢えず ble/textarea の状態を保存・復元する仕組みは整えた。 66691 見た目は動いているように見える。取りこぼしの変数はあるかもしれないが、それは後で考える。 66692 66693 2017-10-04 66694 66695 * 2017-10-02 vi-mode (visual block): 矩形選択から text/update/position を呼び出せるようにする [#D0504] 66696 66697 連続して入力をしたときには配置情報が更新されていないことがある。 66698 その様な場合には現在は論理列による矩形にフォールバックしているが、 66699 これは直感的ではないので問題になる。 66700 66701 従って text/update/position を外部から呼び出せるようにして、 66702 配置情報が更新されていない場合にはこれを呼び出すようにする必要がある。 66703 しかし、現在は text/update/position の更新範囲は、 66704 着色の更新範囲と一緒に管理しているがために、 66705 text/update/position を単体で呼び出すことができない。 66706 更新範囲の情報を分離する必要がある。 66707 66708 * 同時に _ble_line_text_* の変数名を何とかする。案を考える。 66709 66710 _ble_line_text_cache_length= -> _ble_textmap_length 66711 _ble_line_text_cols=80 -> _ble_textmap_cols 66712 _ble_line_text_cache_pos=() -> _ble_textmap_pos 66713 _ble_line_text_cache_cs=() -> _ble_textmap_glyph 66714 _ble_line_text_cache_ichg=() -> _ble_textmap_ichg 66715 _ble_line_text_begx=0 -> _ble_textmap_begx 66716 _ble_line_text_begy=0 -> _ble_textmap_begy 66717 _ble_line_text_endx=0 -> _ble_textmap_endx 66718 _ble_line_text_endy=0 -> _ble_textmap_endy 66719 66720 | うーん。text_layout よりも良い名前はないか。 66721 | 66722 | - 文字の配置を素直に英語にすると character arrangement になる。長い。 66723 | 66724 | - .NET では Sysmtem.Drawing.Graphics に MeasureString および MeasureCharacterRanges がある。 66725 | 66726 | - _ble_text は既に s2c などの名前空間として使用されている。 66727 | 従って、_ble_textbox, _ble_textarea, _ble_line を使う必要がある。 66728 | _ble_line は今まで使ってきたものだが実態に合わないので変更したい。 66729 | textbox だと任意の場所に任意のサイズで表示できそうな気がするのでよくない。 66730 | (或いは将来的にそのような機能を実装するかもしれないが) 66731 | よく考えたら現状の配置情報の計算は textbox かどうかなどとは直交する実装になっている。 66732 | 現に render/update でスクロール機能を実装したときも _ble_line_text 側には何も変更はなかった。 66733 | 66734 | 従って、_ble_textbox や _ble_textarea というのも微妙である。 66735 | 或いは、_ble_graphics_textlayout_ などにするか。 66736 | 短くすれば _ble_draw_textrange もしくは _ble_draw_txtlayout。 66737 | うーん。もはや draw/graphics とか要らないかもしれない。 66738 | 66739 | _ble_textlayout_ とするか。_ble_textrange_ でも良いかも。 66740 | TextRange については調べてみたが色々と意味が違うような気がするのでやめる。 66741 | 66742 | うーん。実際には glyph などの描画に関する情報も保持している。 66743 | なので単に layout という訳でもないのではないか。 66744 | 但し着色などについての情報は持っていないので、やはり layout に近いというべきか。 66745 | 66746 | _ble_textlayout に収束しつつある。 66747 | 66748 | 少し変種を考えてみる。_ble_txtlayout, _ble_txtout, _ble_txtpos, 66749 | _ble_charpos, _ble_txtarrange, _ble_txtconfiguration, _ble_txtdisposition, 66750 | _ble_txtgeometry, _ble_txtgeo, _ble_txtmetric, _ble_txtmeasure, 66751 | _ble_txtmap, _ble_textmap. 66752 | 66753 | 良さそうなのは、_ble_txtpos, _ble_txtmap, _ble_textpos, _ble_textmap 辺りである。 66754 | 取り敢えず _ble_textmap にする。 66755 66756 _ble_textmap に統一した。 66757 66758 * 次に _ble_textmap 用の dirty-range を新設することにする。 66759 現在は外部から指定した BLELINE_RANGE_UPDATE を使用している。 66760 これは ble-edit/render/update で設定される変数で、 66761 dirty-range _ble_edit_dirty_draw_* を元にしている。 66762 従って、_ble_edit_dirty_draw_* の複製を作れば良いのである。 66763 66764 今までは外部からこれらの変更範囲について管理して、 66765 BLELINE_RANGE_UPDATE などの変数を介して指定できるようにしていたが、 66766 今回の変更のように内部で保持するようにしてしまって問題ないだろうか。 66767 66768 恐らく問題ないという気がする。 66769 但し、これらの変数の更新はそれ専用の関数を用いて行うようにした方が良い気がする。 66770 66771 * うーん。問題がある。 66772 66773 | ble/textmap#update では "再描画の必要がある範囲" を POS_UMIN, POS_UMAX で返す。 66774 | これは別の場所に記録して置かなければならない。 66775 | ところが、ble/textmap#update を呼び出した後で 66776 | 更に文字列に更新があった場合はこの更新範囲がどうなるかは非自明だ。 66777 | 66778 | (dbeg dend dend0) のペアを用いて範囲を更新することはできるがそれで十分だろうか。 66779 | - umin-umax で変更範囲より前にある場合はそのままで良い。 66780 | - umin-umax で変更範囲より後にある場合は…その分だけ index をシフトすれば良い。 66781 | もし変更範囲の長さが変わらない場合や変更範囲での違いが改行で吸収できるときは、 66782 | umin-umax の変更範囲はそのままシフトするだけで良いし、 66783 | もしそれで不充分であるのであれば次の ble/textmap#update でそこまで umin-umax が拡張されるはずである。 66784 | - 変更範囲が被っている場合には削って良い。 66785 | 変更範囲の領域はどうせ次の更新で再描画の対象になるだろうから。 66786 | 66787 | →_ble_edit_str の更新をする度に毎回 _ble_textmap の更新もするべきかと思ったが、 66788 | ble/textmap#update を呼び出したときに、蓄積した dirty-range を用いて 66789 | _ble_textmap_u{min,max} を shift して更新すれば良いのだと気付いた。 66790 | _ble_textmap_u{min,max} で公開するのであれば飽くまで最後の配置計算の際の更新必要範囲で良いのだ。 66791 66792 配置情報に関連する umin,umax は独自に管理し、 66793 _ble_textmap_umin, _ble_textmap_umax に蓄積することにした。 66794 これは修正した。OK 66795 66796 * ble/textmap#update のインターフェイスに疑問が生じてきた。 66797 66798 外から呼び出す時にグローバル変数と密結合にならないように、 66799 text BLELINE_DIRTY_RANGE POS_UMIN POS_UMAX などの変数を介して呼び出すようにしてきた。 66800 しかしながら現在の実装では不可避的に _ble_textmap_* という内部状態を持つので、 66801 完全に外部から自由に取り扱うためには _ble_textmap_* の変数を宣言して呼び出す必要があった。 66802 66803 一方で、今回の書き換えによって BLELINE_DIRTY_RANGE やら POS_UMIN POS_UMAX などの変数も全て、 66804 _ble_textmap_* で管理するようにした。これは順当な書き換えである。 66805 現在残っている変数は text x y である。 66806 一方でこの text というのはそれまでに渡した _ble_textmap_d* と符合するものでなければならない。 66807 ここで _ble_textmap_d* と独立に渡せるようになっているのは不自然である。 66808 それよりは寧ろ update-dirty-range を呼び出すときに一緒に text も指定する方が自然である。 66809 しかしそれはそれでデータが巨大になってくると無駄な気がする。 66810 やはり text というローカル変数で再計算の時に受け渡しするというのが良いのだろうか。 66811 66812 だとすると ble/textmap#update を呼び出す側で現在どのような目的で textmap#update を呼び出すのか 66813 ということを承知で行わなければならない。ということは簡易な ble/textmap#update-auto 的な関数で、 66814 local text=$_ble_edit_str x=... y=... して呼び出すのは変だということになる。 66815 或いは、これは widget として提供するべきか。 66816 66817 * さてここまでの書き換えによって ble/textmap#is-up-to-date でなくても、 66818 ble/widget/.update-textmap を呼び出せば最新状態になるということになった筈だ。 66819 しかし本当にちゃんと動作するのかについては謎だ。確認方法がない…。 66820 66821 一つのテスト方法は _ble_edit_str.replace の中で毎回 ble/widget/.update-textmap を呼び出すことだ。 66822 とても遅くなるが取り敢えず動作することを確認する上ではこれで良いだろうという気がする。 66823 →遅いが、何事もなく動作した。本当にこれで大丈夫なのだろうか…。 66824 分からないが取り敢えず暫く動かしてみることにする。 66825 66826 * vi-mode: ge gE [#D0503] 66827 66828 簡単かと思ったらちょっとよく分からなくなった。 66829 66830 - 先ずカーソルが単語の中に載っているときは前の単語の末端に行く 66831 - 実は [[:alnum:]]+ と [^[:space:][:alnum:]]+ の間も単語の境になりうる。 66832 - 実は二重改行にも止まる 66833 - それ以上後ろに進めないときはバッファの初めに行く 66834 66835 % 要件 1 を満たすようにするためには以下をすれば良い。 66836 % 66837 % ${str::ind+1} =~ (wb+w*){0,arg}$ 66838 % 66839 % 但し、w が単語を構成する文字で b がそれ以外の文字である。 66840 % 問題は空行である。Bash 正規表現には当然前方先読みなどは存在しない。 66841 % 従って、これを用いない形式に変換する必要がある。 66842 % 用いない形式で初めから考えようとしたがよく分からなくなった。 66843 % 66844 % % 仕方がないので、取り敢えず用いる形で書いてみることにする。 66845 % % 66846 % % ((w|(?<=n)n)(b|(?<!n)n)+w*){0,arg} 66847 % % 66848 % % 但し n が改行を表す。さて、(b|(?<!n)n)+ は、 66849 % % 66850 % % (b|(?<!n)n)(b*|(?<!n)n)* 66851 % % 66852 % % b(b+n)*b* | bn(b+n)*b* | (?<!n)n(b+n)*b* 66853 % % 66854 % % (bn?|(?<!n)n)(b+n)*b* 66855 % % 66856 % % と変形される。一方で (?<=n)n は苦しい。というか1文字戻り読みしないときつい。 66857 % % 繰り返しになるとどうすれば良いのだろうか。 66858 % % 66859 % % % 前回の最後は (bn?|(?<!n)n)(b+n)*b*w* と分かっている。 66860 % % % これを最後が n のものとそれ以外のものに分類できれば良い。 66861 % % % 最後が n のものは以下の形をしている。 66862 % % % 66863 % % % (bn?|(?<!n)n)(b+n)+ | (bn|(?<!n)n) 66864 % % % 66865 % % % 最後が n 以外のものは以下の形をしている。 66866 % % % 66867 % % % (bn?|(?<!n)n)(b+n)*b*w+ | 66868 % % % (bn?|(?<!n)n)(b+n)*b+ | 66869 % % % b 66870 % % % 66871 % % % と思ったが、これは使わない気がする。 66872 % % 66873 % % あと思ったのは、さきに (?<!n) を消去した方が良い。 66874 % % 改めて 66875 % % 66876 % % (w|(?<=n)n)(b|(?<!n)n)+w* 66877 % % = (w|(?<=n)n)(bn?|(?<!n)n)(b+n)*b*w* 66878 % % = (wbn?|wn|(?<=n)nbn?)(b+n)*b*w* 66879 % % = (w(b|b?n)|(?<=n)nbn?)(b+n)*b*w* 66880 % % 66881 % % これに後ろから (?<=n) をかけるとどうなるか。 66882 % % 66883 % % (w(b|b?n)|(?<=n)nbn?)(b+n)*b*w* (?<=n) 66884 % % = (w(b|b?n)|(?<=n)nbn?)(b+n)+ | (wb?n|(?<=n)nbn) 66885 % % = (?<=n) nbn? (b+n)+ | (?<=n) nbn 66886 % % | w(b|b?n)(b+n)+ | wb?n 66887 % % = (?<=n)(nb)(n? (b+n)+ | n) 66888 % % | w(b|b?n)(b+n)+ | wb?n 66889 % % 66890 % % 何かおかしい。二重改行の後には空白は必要ないはずだ。 66891 % 66892 % 初めの時点で間違えている。修正する。 66893 % 66894 % (w (b|(?<!n)n)+w* |(?<=n)n (b|(?<!n)n)*w*){0,arg} 66895 % : 66896 % : w(b|(?<!n)n)+w* 66897 % : = w(b|b?n)(b+n)*b*w* 66898 % : 66899 % : (?<=n)n (b|(?<!n)n)*w* 66900 % : = (?<=n) n(b+n)*b*w* 66901 % : 66902 % = ((?<=n) n | w(b|b?n)) (b+n)*b*w* 66903 % 66904 % うーん。これを見るに変換は厳しい。 66905 % (?<=n) は前のループの最後の文字を見るが、 66906 % n 自身がそれになっている。うーん。よく分からない。 66907 % 66908 % 取り敢えず後ろから (?<=n) をかけてみる。 66909 % 66910 % ((?<=n) n | w(b|b?n)) (b+n)*b*w* (?<=n) 66911 % = ((?<=n) n | w(b|b?n)) (b+n)+ 66912 % | ((?<=n) n | wb?n) 66913 % = (?<=n) n (b+n)+ | w(b|b?n) (b+n)+ 66914 % | (?<=n) n | wb?n 66915 % = (?<=n) n (b+n)* | wb (b+n)+ | wb?n (b+n)* 66916 % = (?<=n) (nb+)* n | wb b+(nb+)*n | wb? (nb+)*n 66917 % = ((?<=n) | wbb+ | wb?) (nb+)*n 66918 % = ((?<=n) | wb*) (nb+)*n 66919 % 66920 % 或いは、後ろから (?<!n) をかけてみる。 66921 % 66922 % ((?<=n) n | w(b|b?n)) (b+n)*b*w* (?<!n) 66923 % = ((?<=n) n | w(b|b?n)) (b+n)*b*w+ 66924 % | ((?<=n) n | w(b|b?n)) (b+n)*b+ | wb 66925 % = (?<=n) n (b+n)*(b*w+ | b+) 66926 % | w(b|b?n) (b+n)*(b*w+ | b+) | wb 66927 % = (?<=n) (nb+)*n (b*w+ | b+) 66928 % | w(b|b?n) (b+n)*b*w+ 66929 % | wn b+(nb+)* 66930 % | wb nb+(nb+)* 66931 % | wb b+(nb+)* 66932 % | wb 66933 % = (?<=n) (nb+)*n (b*w+ | b+) 66934 % | w(b|b?n) (b+n)*b*w+ 66935 % | wn? b+(nb+)* 66936 % 66937 % w(b|b?n) (b+n)*b*w+ 66938 % = wb b* w+ 66939 % | wbb+ (nb+)*n b* w+ 66940 % | wb (nb+)*n b* w+ 66941 % | w (nb+)*n b* w+ 66942 % = wb+ w+ | wb* (nb+)*n b* w+ 66943 % = w (b+ | b* (nb+)*n b*) w+ 66944 % = w (b|b*(nb+)*n) b*w+ 66945 % 66946 % 66947 % % やはり駄目だ。一つの希望は (?<=n) の部分と最後の文字に対する要件を分離できれば、 66948 % % (つまり "((?<=n) ... | ...) (1文字以上)" の形になれば順番を反転させることができたが、 66949 % % 今回の場合については2の累乗でパターンが増えるので駄目の気がする。) 66950 % % 正規表現ではやはり不可能と結論付けるべき気がする。 66951 % 66952 % しかしやはり変だ。やはり、明らかに DFA なのでそれに対応する正規表現があるはずだ。 66953 % と思ったが、問題は個数を {0,arg} で制限していることになる気がする。 66954 % これの所為で実質的に状態を数え上げなければならない。 66955 % これに対応して大体 2 * (arg+1) の状態が生まれる。 66956 % しかしそれでも有限個である。うーん。 66957 % 66958 % また、思うにもし無限個だったとしたら OK なら、 66959 % 無限個だったときの正規表現をまずは考えるべきなのでは。 66960 % うーん。今回の場合は NFA になって、更に面倒なことになりそうだ。 66961 % 66962 % (?<=n) (nb+)*n (?<=n) 66963 % any wb* (nb+)*n (?<=n) 66964 % (?<=n) (nb+)*n (b*w+ | b+) (?<!n) 66965 % any w (b|b*(nb+)*n) b*w+ | wn? b+(nb+)* (?<!n) 66966 % 66967 % とここで気付いたが w には二種類あって wW の境目には空白がなくても良い。 66968 % また完全に考え直しになった気がする…。 66969 66970 うーん。結局単語の種類があるとなると単語を左右に分割するわけには行かない。 66971 つまり、単語はやはり1単位として読み取るしかない。 66972 やはり、今までの実装と同じように厳密な正規表現の実装は諦めて、 66973 貪欲な一致で初めに一致するものが正しくなるように構成するしかない 66974 (或いは方法もあるかもしれないが人の手には負えない程複雑になりそうな気がする)。 66975 66976 取り敢えず後方に単語を探索することにする。 66977 66978 :w[nb]* 但し二重改行は含まない (:w は単語の正規表現とする) 66979 = :wb*(n(b+n)*b*)? 66980 = :wn?(b+n)*b* 66981 66982 (?<!n)n [nb]* 但し二重改行は含まない 66983 = (?<!n) n(b+n)*b* 66984 66985 常に最長一致するようにしていれば前の単語が終了するのは、 66986 二重改行のあとか次の :w が始まるところだけのはずである。 66987 従って、これで問題ないはず。 66988 66989 (:wn?|n) (b+n)*b* 66990 66991 但し、一番最初の一致点を制限する方法が必要である。 66992 特に一番最初を二重改行以外とする場合にはどうするのか。。 66993 うーん。結局 backward-word で使われている正規表現と同じものになるのか…。 66994 66995 (:wn?|b+n?|n) (b+n)*b* 66996 = (:wn?|n) (b+n)*b* 66997 | b+ (b+n)*b* 66998 | b+n (b+n)*b* 66999 = :wn? (b+n)*b* 67000 | n (b+n)*b* 67001 | b (b+n)*b* 67002 | b+n (b+n)*b* 67003 67004 しかし、これの問題点は arg 回一致したのかそれ未満で終わったのかが分からないということである。 67005 うーん。文字列先頭でのεを許して {0,arg} から {arg} に変えてはどうだろう。 67006 67007 ((:wn?|b+n?|n) (b+n)*b* | ^) 67008 = (:wn?|b*n?|n|^) (b+n)*b* 67009 67010 もっというと b+n が親として現れるのは文字列先頭のみである。 67011 67012 = (:wn?|n|^(b+n|b+)?) (b+n)*b* 67013 = (:wn?|n|^((b+n)?|b*)) (b+n)*b* 67014 = (:wn?|n|^) (b+n)*b* 67015 67016 うーん。こうしておいて一番初めの一致だけを切り出しておけばよいか。 67017 本当にこれで問題ないか? 本当に一番はじめの一致が空になるのだろうか。 67018 というのも数が足りない場合にはどういうことになるかというと、 67019 67020 [[ abcd =~ ((:wn?|n|^) (b+n)*b*){4}$ ]] → (a)(b)(c)(d) 67021 67022 ということも可能だからである。繰り返し回数の少ないものから順に一致するというようにすればOK? 67023 そうすればできるだけ少ない数で一致するようにできる。 67024 67025 [[ abcd =~ ((^|:wn?|n) (b+n)*b*){4}$ ]] → ()()()(abcd) 67026 67027 * 2017-10-03 vi-mode (visual block): 行折り返しがあるときの着色がおかしい。 [#D0502] 67028 67029 振る舞いは正しい。一度折り返しがあると、 67030 その後で画面を大きくして折り返しを解消しても振る舞いはおかしい。 67031 67032 そもそも sub_ranges は正しく計算されているのだろうか。 67033 振る舞いが正しいので sub_ranges 自体は問題がなくて、 67034 それよりは着色の方の問題のような気がするのだが、確認はしておく。 67035 やはり sub_ranges 周りは問題ないようだ。 67036 というより計算結果の _ble_highlight_layer_region_buff の中身まで問題ない。 67037 67038 これは ble-highlight-layer:region/getg を複数の範囲に対応していないのが問題だった。 67039 対応した。同時に中の処理も整理した。 67040 67041 2017-10-03 67042 67043 * vi-mode (visual): 前回のビジュアルモードの復元について [#D0501] 67044 67045 | 2017-09-17 67046 | * ビジュアルモードに入る時の動作を調べる。 67047 | 67048 | v, V, C-v はそれぞれ charwise-visual-mode, linewise-visual-mode, 67049 | blockwise-visual-mode と名前をつけることにする。 67050 | 67051 | 引数を指定したときは v V C-v は何れも同じ動作になる気がする。 67052 | 67053 | 前回のビジュアルモードが v/V/C-v の別も含めて記録されている。 67054 | 但し、C-c などで終わったビジュアルモードは記録されていない。 67055 | 67056 | - blockwise-visual-mode は行と列をそれぞれ別々に記録している。 67057 | - 実は v で記録したときも行と列が別々に記録されている。 67058 | 異なる行に移動するときには列は相対値ではなくて固定値で解釈される。 67059 | 引数の倍率は行だけにかかる。起点の次の行に終点があるとき行数は 2 と解釈され、 67060 | 引数の倍率はこれに乗算される。 67061 | - V を記録したときには恐らく列の情報は使用されない。 67062 | 復元するときも列は復元されず、ただ j で行を移動しているように見える。 67063 | - 負の方向に選択したかどうかは記録されていない。 67064 | つまり、常に現在位置を左上の基点として復元される。 67065 | 67066 | オペレータを指定した場合はどうなるかと yv などを試すと、 67067 | どうも全然違う機能が呼び出されているような気がするが一体何かは分からない。 67068 | 何れにしても v は omap ではなくて nmap に追加されるということ。 67069 67070 取り敢えず現状で簡単に実装してみることにする。 67071 67072 複数行に跨っているときの相対位置は表示位置の 67073 y*cols+x による比較で問題ないように見える。 67074 行末に行送りの全角文字がある場合でも表示位置に依る差である。 67075 67076 実装した。 67077 67078 * 2017-10-02 vi-mode (visual block): 貼り付け時に貼り付け先にあるタブは空白に変換されるようだ。 [#D0500] 67079 67080 | 2017-10-02 タブも機械的に押し出されるのか? 67081 67082 * bash-3.0: up down が bind できていない。 [#D0499] 67083 67084 - うーん。手で bind するとちゃんと bind できている。 67085 - ble_bind_keymap=vi_insert を通して keymap を指定した場合もできている。 67086 67087 だとすると dump 結果がおかしくて駄目なのだろうか。 67088 67089 - ble-bind -d で出力するとちゃんと登録されているのが確認できる。 67090 - ble-decode/keymap/dump vi_insert で見てみると登録されている。 67091 と思ったが複数の異なる特殊キーで登録されている。変だ。 67092 改めて ble-bind -d で確認してみると f4 に何故か割り当てられている。 67093 更に f1 - f5 に本来別のキーに割り当てられるべきものが登録されている。 67094 67095 一つの可能性は keymap を生成したときの kcode と現在の kcode がずれているということである。 67096 しかし vi.sh は頻繁に更新している一方で kcode はそんなに変更していないので、 67097 これは余り考えにくい → と思って vi.sh を touch してみたら直ってしまった。 67098 一体何だったのだろう。これはもしかすると先に直した ble-bind -d の問題? 67099 でも同関係してくるのか謎。 67100 67101 或いはキャッシュからキーマップを読み取ると駄目ということなのかもしれない。 67102 と思って再度 bash-3.0 を起動して試してみたが問題は再現しない。 67103 確かに、新しくキーマップを生成してはいないのでキャッシュから読み取っているはずである。 67104 結局問題はよく分からず消滅したようだ。 67105 67106 先程までは何度再起動しても問題だった一方で、 67107 今は再起動しても何も問題は起こらないので何かの拍子で直ったと考えて問題ないだろう。 67108 67109 * ble-decode: bug [#D0498] 67110 67111 vi_digraph の binding でグロブ展開が起こっている。 67112 と思ったら、ble-bind -d の表示するときのバグだった。直した。 67113 67114 * vi-mode: ble/string#split arr $'\n' "$text" などが用いられているが、 [#D0497] 67115 これらは非空行について処理したい場合は良いが、 67116 行の数を保持したい場合には使えない。 67117 67118 改行で分割するための特別な関数を用意する必要がある。 67119 改行で分割する良い方法はあるだろうか。 67120 67121 a 一つの方法は改行を一旦別の文字 @ に置き換えてから処理する方法である。 67122 しかしこれだとその文字 @ について事前に escape しなければならない。 67123 しかし \@ のようにエスケープしても意味が無いので、完全に別の文字に置き換える必要がある。 67124 つまり、\ → \A, @ → \B, 改行 → @ としてから分割を実行する。 67125 その後で、\A → @, \B → \ というように元に戻する必要がある。 67126 @ が含まれていない場合には幾らか工程をスキップすることができるが、 67127 面倒な方法であることに変わりはない。 67128 67129 b 或いは正規表現などを用いて手で刻んでいく方法である。 67130 これの欠点は大量の行が存在するときに遅くなってしまうということである。 67131 67132 c もう一つの方法は mapfile <<< $text を用いるというものである。 67133 これは古い bash では使えないので実装の切り替えが必要になる。 67134 67135 bash の version に応じて c または a ということになるだろうか。 67136 取り敢えず今の所は ble/string#split arr $'\n' を用いて実装する。 67137 67138 というか、調べてみると例え空白類で分割していなかったとしても、 67139 ble/string#split では、末尾にある sep は無視されるようだ。 67140 但し、数が一定している場合には特に問題にはならない。 67141 更に、最後の sep 一個だけが無視されるようなので、 67142 手で初めから最後に sep を追加しておけば問題ない。 67143 →実装した。期待通りの動作になった。 67144 67145 更に改行で区切る関数も実装する。 67146 67147 split1.measure (改行を別文字に置換してから) 67148 time 242.40 usec/eval 67149 time 728.20 usec/eval (分割に用いる文字が重複しているとき) 67150 split2.measure (正規表現で切り出す) 67151 time 1502.40 usec/eval 67152 split3.measure (mapfile を用いる) 67153 time 135.40 usec/eval 67154 split4.measure (グロブで切り出す) 67155 time 895.40 usec/eval 67156 67157 取り敢えず mapfile を用いて正しく実装でき、さらに速い。 67158 bash-4.0 以上では mapfile を用い、それ未満では別文字に置換してから split する方法で実装した。 67159 67160 * 2017-10-02 vi-mode (visual block): 矩形選択が遅い。 [#D0496] 67161 67162 行が増えてくるとやはり遅い。 67163 67164 * get-index-at の最適化? 67165 67166 get-index-at は二分探索を行っているが、 67167 この範囲を最初から行内に制限する方が良い。 67168 67169 更に、get-index-at を観察して気づいたが、 67170 getxy.cur を使用している。一方で、 67171 現在の矩形範囲の実装は getxy.out を用いている想定で行っていた。 67172 この辺りの動作の違いがどのような影響を受けるか再度考える必要がある。 67173 →実は大した影響はない? ような気がする。 67174 が、それでも getxy.out を用いる方が速いのでそちらを使うものを用意する方が良い。 67175 67176 更に、思うことは get-index-at を実行した時点で、 67177 それが厳密一致かそれとも前方に戻ったかは分かるし、 67178 更にいうと隣接する次の文字の位置も分かるはず。 67179 これらを全て一挙に取得する generic な get-index-at があっても良い気がする。 67180 67181 ※同様の探索を paste.impl でも実施している。 67182 他にも色々あるのではないか。 67183 67184 ble-edit/text/hit という関数を用意した。配列アクセスが遅くならないように、 67185 内部では配列として _ble_line_text_cache_pos しか触らないようにした。 67186 67187 さらにこれを利用して extract-graphical-block を再実装する。 67188 67189 % 実装の都合で vim の不自然な動作の再現は諦めた。つまり、 67190 % 67191 % |1234567>| 67192 % |あ89ab$ | 67193 % |stuvwxyz| 67194 % |lmnop$ | 67195 % 67196 % において C-v で 8 から z を選んで y すると、 67197 % 67198 % | あ8| 67199 % |zlmn| 67200 % 67201 % になる。vim では "あ" の前に空白は付加されず、ずれる。 67202 67203 やはりこの振る舞いは関係ない? 67204 現状の実装では全て out で計算しているので、 67205 > の位置から文字があると勘違いする。 67206 従って、切り取られる内容で左側に空白は付加されない。 67207 ということは、新しい実装でも左側に空白は入らないはずである。 67208 67209 実際に試してみるとそもそも色々表示がおかしい。 67210 これは表示のバグなのかそれとも範囲切り出しのバグなのか。 67211 →これは折り返しがあるときの座標計算のずれが悪い気がする。 67212 一度折り返しを作って、その後で画面のサイズを変更すると変なことになった。 67213 特にサイズに変更のあった文字が絡んだ時に文字の幅と座標の幅がずれているのだと思う。 67214 →これは別項目で対策する #D0502 67215 67216 どうも表示が悪いだけの気がするので、先に振る舞いを確認してから、 67217 表示に関しては後で処置することにする。 67218 67219 x done: 先ず矩形の左端について。行送りがあるときに行送り前の位置からになっている。 67220 これは vim の振る舞いと異なる。修正した。 67221 o 行送りされた文字が消滅するとき、行送りの分だけ空白が残るという動作は正しい。 67222 o 切り取られる内容について、行送りに代わる空白は補填されないという振る舞いも一致している。 67223 o 現状の実装だと行送りされた文字が被っていないのに空白に変換されてしまうという問題 (以下) 67224 があるのではないかと思ったが、vim で試してみた所全く同じ動作だったので気にしないことにする。 67225 67226 |abcd>| → (c から i までの矩形) d → |ab x| 67227 |あx | |efjkl| 67228 |efghi| 67229 |jkl | 67230 67231 多分、特別に変な処置はしなくても現状の実装のままで vim の動作と区別がつかない気がする。 67232 67233 改めて速度について確認してみる。やはり遅い。が、以前よりはましになった気がする。 67234 (もしかして extract-graphical-block 単体が律速しているわけではないのかもしれない。) 67235 67236 * 2017-10-01 vi-mode: 最終行で dd としたらその行を消して一つ上の行へ移動する [#D0495] 67237 67238 引数を指定して一番下の行まで全て削除する場合も同様 67239 dj で一番最後の行まで消すときも同様。 67240 これは operator:d (type=line) を修正する。 67241 67242 * 2017-10-02 vi-mode (block): 貼り付け時に全角文字が邪魔な時はどうなるのだろう。 [#D0494] 67243 67244 | aa → ahelloa 67245 | あ helloあ 67246 67247 空白が補填されて邪魔だった全角文字は右に押し出されるようだ。 67248 67249 ここで当初の計画の矩形選択の貼り付けには対応することにする。 67250 67251 | 2017-09-17 67252 | 67253 | * C-v の矩形選択について。どの様な範囲が選択されるのだろうか。 67254 | 67255 | - 先ず全角文字の幅は考慮される。つまり見た目の幅で矩形になるように選択される。 67256 | また、一部でも全角文字にかかればその全角文字は範囲に含まれる。 67257 | 開始点と同じ列かより右側の全角文字の上にカーソルがある場合は、 67258 | その全角文字の終端までを矩形の右端とする。 67259 | - 次に行折り返しになっている場合は、論理行での矩形選択になる。 67260 | 67261 | 矩形選択のときのオペレータの動作はどうなるだろうか。 67262 | これは kill-range, delete-range, copy-range 辺りを修正すれば簡単かもしれない。 67263 | 67264 | 矩形選択のときの表示はどうすれば良いか。 67265 | 実のところ、全体を反転表示している場合との違いは、 67266 | 途中に着色されない部分があるということだけなのではないか。 67267 | だとすれば着色の処理はそんなに難しくないのでは。 67268 | 67269 | →と思ったが左下から初めて右上に進んだ場合や、 67270 | 右上から初めて左下に進んだ場合には、 67271 | _ble_edit_ind, _ble_edit_mark の範囲外に着色がはみ出るのではないか。 67272 | 67273 | a これに対応するためには着色範囲の決定に直接 _ble_edit_ind, _ble_edit_mark を用いるのではなく、 67274 | それを修正した値を用いるようにするという手がある。 67275 | 67276 | b 或いは別の方法として _ble_edit_ind, _ble_edit_mark を移動する毎に補正するという手もある。 67277 | ただこれだと現在のカーソルの位置が正しくないことになるので、 67278 | (overwrite mode でやっているように) カーソルを消して代替表現を使う必要がある。 67279 | 更に移動コマンド全てについてこの調整を呼び出すようにしなければならない 67280 | (これは __after_command__ でできるかもしれない)。 67281 | この方法は汚い上に色々辻褄を合わせるのが大変そうなので、良い方法ではない。 67282 | 67283 | 後、各オペレータを矩形選択に対応させる必要がある。 67284 | 更に paste の際に矩形選択されたものがどう貼り付けられるのかも調べる。 67285 67286 [動作確認] 67287 67288 貼り付けを実装した。取り敢えず動くことをみた。 67289 これから細かく動作確認する。 67290 67291 o fill が働くか。 67292 o 行末では fill は入らない。 67293 o 中途半端な全角文字は空白になって貼り付けられる。右端も左端もOK 67294 67295 2017-10-02 67296 67297 * 2017-10-01 vi-mode (visual mode): ビジュアルモードでオペレータに引数を指定したときはどういう動作なのだろう。 [#D0493] 67298 67299 少なくとも v で試してみた所は引数を指定しても何も効果はないようである。 67300 もし引数に意味があるのであれば ble/widget/vi-command/set-operator を書き換える必要がある。 67301 67302 うーん。3> とすると 3 回インデントを深くするという動作が例示されている。 67303 これは同じ範囲に対して > を 3 回呼び出していると解釈できる。 67304 だとすれば y や d や c も繰り返しされているということなのだろうか。 67305 うーん。試しに 2~ を実行してみると小文字から大文字になったので、 67306 ただ愚直に繰り返されるわけではないようだ。 67307 或いは、寧ろオペレータに対する "引数" のようなものが指定されると考えるべきか。 67308 67309 オペレータに第4引数を渡して、それを繰り返し回数か何かとして取り扱ってもらう。 67310 取り敢えずオペレータに引数を渡すようにした。 67311 更に < > についてはインデントの幅を指定するものとして処理するようにした。 67312 現状で対応している他のオペレータ (y d c u U ~ ?) については全て引数は無視するようである。 67313 67314 * vi-mode: 履歴項目を移動したときのモードおよびモード表示 [#D0492] 67315 67316 - done: ノーマルモードは保持するべき。但しカーソル位置の補正が必要になる。 67317 67318 履歴の移動は .history-relative-line で起こる。修正した。 67319 67320 履歴検索をする時も常に気にする必要がある。 67321 →現在は履歴検索はノーマルモードから呼び出せないので関係ない。 67322 (逆に言えば将来的に対応する場合には注意が必要ということになるが。) 67323 67324 - ok: 挿入モードは保持するべき 67325 67326 - ok: オペレータ待機モードは解除されるはず 67327 67328 - resolved: ビジュアルモード・選択モードは解除するべき 67329 現状では解除されずに変なことになる。 67330 というか履歴移動が起こるようなコマンドを登録しているのが悪い。 67331 初めから履歴移動が起こらないようになっていれば解除だのを考えなくて良い。 67332 67333 →これは forward-line, backward-line において、 67334 _ble_decode_key__kmap=vi_command の時にのみ、 67335 履歴項目の移動をするように変更することで対処する。変更した。 67336 他にも .history-relative-line を呼び出している箇所を修正した。 67337 67338 * 2017-10-01 vi-mode (visual mode): 範囲の表示 [#D0491] 67339 67340 * done: _ble_edit_mark_active=line, block の時の着色。 67341 * done: 範囲の表示 charwise であったとしても右に 1 文字拡大しなければならない。 67342 67343 色々試したが、どうも範囲の表示と矩形領域の決定を独立に計算するのはよくない。 67344 ということなので矩形範囲の計算方法をここで調査する。 67345 67346 | ★矩形選択の実装でよく分からない動作を発見した。以下の様に入力しておいて 67347 | 67348 | | あa 67349 | | aaa 67350 | | aあ 67351 | 67352 | 1 行目の行頭で C-v して jj とすると、以下が選択(ハイライト)される。 67353 | 67354 | あ 67355 | aa 67356 | aあ 67357 | 67358 | この状態で y として適当なところに移動して p をすると 67359 | 67360 | あ 67361 | aa 67362 | a 67363 | 67364 | が貼り付けられる。もう少し幅のあるもので試してみる。 67365 | 67366 | あいうえお 67367 | aaaaaあaaa 67368 | aaaaaaせそ 67369 | 67370 | これにおいて、選択範囲と貼付け結果は以下のようになる。 67371 | 67372 | | あいう あいう 67373 | | aaaaaあ → aaaaa 67374 | | aaaaaa aaaaaa 67375 | 67376 | | えお えお 67377 | | あaaa → aaa 67378 | | せそ せそ 67379 | 67380 | と思ったら、中途半端になっている文字に関しては空白で埋められている様である。 67381 | 67382 | ★更に試すと 67383 | 67384 | | あ 67385 | | a 67386 | 67387 | 上に対して 1 行目の先頭から C-v jly とすると、p で以下が貼り付けられる。 67388 | 67389 | | あ 67390 | | a 67391 | 67392 | "つまり始点・終点のうちより右にあるものの右端" が矩形の右端になるのではなく、 67393 | "始点の右端・終点の右端のうちより右にあるもの" あ矩形の右端になるのだと思われる。 67394 | しかしながら a の後に空白が入るのは行の途中に挿入されたとき、 67395 | 続きに別の文字がある場合に限られるようである。 67396 | 先程との違いはそこに実際に文字があるかどうかである。 67397 | 先程は "あ" という文字が中途半端に切り出されて空白になっていた。 67398 | 一方で、今回は元々そこに文字がなくて空白で埋められていた。 67399 | 67400 | ★貼り付け時または読み取り時にタブは 67401 | 空白に変換するべきなのではと思ったが、 67402 | 実際に試してみるとタブはそのまま切り取られそのまま貼り付けられるようだ。 67403 | 従って、タブが含まれている場合は貼り付けの時に幅はばらばらになる。 67404 67405 分かったこと。 67406 67407 - 矩形の左端としては 始点・終点 のうちより左にあるものが選ばれる。 67408 - 矩形の右端としては 始点・終点 の右端のうちより右にあるものが選ばれる。 67409 (左端がより右にあるものの右端というわけではない。) 67410 - 中途半端な位置にある全角文字は空白に置き換えられる。 67411 - 貼り付け時には幅を合わせるように空白が追加される。 67412 - タブに対して "幅を保持するように空白に変換する" などの操作は特に行われない。 67413 67414 折り返しになっているときの動作はどうだろう。 67415 特に行末に全角文字が入り切らずに文字送りされた場合。 67416 試してみた所、 67417 67418 - 表示の行での矩形ではなくて論理行での矩形である。 67419 - ただし、列は文字の幅の勘定ではなくて行頭からの相対表示位置に従って列が決定される。 67420 (これは特に行末に入り切らない全角文字が合って文字送りされたときに違いが出る。) 67421 - この状態で切り取って、貼り付けを行うと以下のように挿入される。 67422 67423 *hello heあlo* 67424 *hello hello h* 67425 67426 つまり、貼り付け時に矩形になるようにする調整は切り取り時の表示幅 67427 で計算されていて、貼り付け時の表示幅で計算されるわけではない。 67428 67429 - 更に末尾の空行もちゃんと記録される。 67430 67431 矩形範囲の各断片の決定のときに計算するべきことは何か。以下を計算すれば良い。 67432 67433 1 各断片について 67434 1 開始位置と終了位置 (これは範囲表示用なので中途半端な全角を含む) 67435 2 切り取る場合の文字列 (中途半端な全角は空白に変換) 67436 3 貼り付け時に矩形になるようにするために必要な空白の数 67437 2 最初の非空白断片の番号・最後の非空白断片の番号 67438 (これは範囲表示用である。もしかすると直接 rmin, rmax でも良いかも) 67439 67440 * 切り取り時に境界の上に載っている全角文字があるとき、 67441 境界の外に出ている部分に関しては空白に置き換えられる。 67442 その全角文字が行送りされているとき、 67443 行送りの幅についても空白に置き換えられる。 67444 67445 例えば以下は C-v で "o" から "x" を切り取ったときの変化である。 67446 元々行送りマーク ">" のあったところに空白が付加される。 67447 67448 |.....>| |..... | 67449 |あxyz$| -> | yz$ | 67450 |....he| |....he| 67451 |lopqr$| |lqr$ | 67452 67453 2017-10-01 67454 67455 * vi-mode (visual mode): ビジュアルモードの間の切り替え [#D0490] 67456 67457 visual mode で v とすると visual mode を抜ける。 67458 この時、抜けた瞬間の状態は記録されるのだろうか。 67459 試してみた所記録されなかった。つまり、キャンセルに相当する。 67460 67461 * vi-mode: ビジュアルモード 第一実装 [#D0489] 67462 67463 そもそもビジュアルモードと選択モードの違いは何なのか。 67464 67465 zsh の vivis の実装を見れば最低限の雰囲気は分かるかもしれない。 67466 67467 _ble_edit_mark_active で区別する? 67468 67469 例えば単に _ble_edit_mark _ble_edit_mark_active を指定して、 67470 少数のコマンドにおいて kill ring に何かを設定するように改修すれば良かったりしないだろうか。 67471 67472 取り敢えず初めて visual mode を使ってみることにする。 67473 オペレータを入力するとその場で現在の範囲を確定させるようだ。 67474 67475 * ビジュアルモードを抜けるのはどの時か確認する必要がある。 67476 67477 - done: 先ずオペレータを実行した時。 67478 - v V C-v などを指定したときは別のビジュアルモードに切り替わったり今のビジュアルモードを抜けたりする。 67479 これは別項目を立てて処理することにする。 #D0490 67480 - done: C-c をすると現在のビジュアルモードをそのまま抜ける 67481 67482 C-o v として入った後に抜ける時、 67483 - done: オペレータを実行する場合には元の挿入モードに戻る。 67484 - done: C-[, ESC をすると元の挿入モードに戻る。 67485 "前回のビジュアルモードの情報" は記録しない。 67486 - done: C-c をすると全て忘れてノーマルモードになる。 67487 この時、当然、カーソル位置の行末補正は起こる。 67488 行末以外の場所にいるときは後退するなどの動作はしない。 67489 "前回のビジュアルモードの情報" は記録しない。 67490 67491 * done: カーソルの動作 67492 67493 - done: 行末に移動することは可能である。 67494 つまり needs-eol-fix は false を返すべき。 67495 →そのようにした。 67496 67497 - done: 既存の nonbol-eolp の判定の部分はそのままで良いだろうか。 67498 つまり ^ などで行末に移動しなくて良いだろうか。 67499 67500 - ok: ^ の場合はそのままで良い。移動しない。元から visual mode では、 67501 現在のカーソルの右にいる文字も取り込むようになっているので、 67502 わざわざ行末に移動しなくても行末まで範囲に含まれる。 67503 67504 - done: forward-char m (SP) で nonbol-eolp 補正をしているが、これは xmap では使わないと思う。 67505 と思って試してみたら xmap でも使うし、更にいうと行末まで移動した。 67506 これについては実装しなければならない。 67507 67508 % というか single-command-mode でも SP の動作が誤っていたりするような気がする 67509 % →と思って試してみたら single-command-mode での SP においては、 67510 % 次の行頭に移動するようだ。つまり、xmap の時にだけ nonbol-eolp に移動するという事になる。 67511 67512 forward-char m (SP), backward-char m (DEL) について 67513 個別に vi_xmap の時の条件分岐で修正を加えた。 67514 67515 - ok: 他は、行単位の移動だけれどこれはどうだろうか。 67516 例えば preserve_clumn のような移動をした時にどうなるか。 67517 試してみるとより短い行に移動するときに行末にも止まるようだ。 67518 これについてもちゃんと実装しなければならない。 67519 67520 →これは .relative-line を呼び出し最終的には needs-eol-fix 67521 に帰着するので特別に対応する必要はなかった。 67522 67523 * done: 更に挿入モードで C-o v として入ると入れ子になる。 67524 67525 これは _ble_keymap_vi_single_command{,_overwrite} 変数をそのままにしておけば良い。 67526 その後で set-operator だか何だかで xmap を抜ける時に復元を行えば良い。 67527 67528 動作を確認した。動いている。OK 67529 67530 [実装] 67531 67532 後の細かいことは実装しながら調べていくことにする。 67533 先ず初めに実装するのはビジュアルモードに入る時の動作である。 67534 67535 取り敢えず "前回のビジュアルモードを復元する" というもの以外は実装した。 67536 ビジュアルモードの種類は _ble_edit_mark_active に設定した文字列 char/line/block で区別する。 67537 また C-c, C-[ (ESC) によりビジュアルモードを抜ける動作についても実装した。 67538 オペレータに対応する前にこの状態でカーソル移動などの動作試験を行う。 67539 67540 取り敢えず動くことだけは確認した。 67541 67542 x done: ESC で抜けられないと思ったら Meta 修飾になっていた。直した。 67543 また ESC の動作はハードコードするのではなくて keymap を通して解決する様に修正した。 67544 x done: また、ble/keymap:vi/setup-map において 67545 M-left M-right が束縛されていたのを削除した。 67546 これらは ESC left, ESC right の動作を上書きしてしまっていた。 67547 67548 次にオペレータの呼び出しを実装する。 67549 67550 取り敢えず cc dd などの行単位の操作を統合する形で ble/keymap:vi/call-operator-linewise を実装した。 67551 と思ったら cc dd が動かなくなった。と思ったら get-arg を呼び出すのが抜けていた。直した。 67552 また、cc dd の振る舞いについても修正を行った #D0488。 67553 67554 次に ble/keymap:vi/call-operator-charwise も実装する。実装した。 67555 67556 他にオペレータを呼び出している箇所は ble/widget/vi-command/linewise-range.impl である。 67557 これはオペレータ作用後の位置の移動が単純ではないので call-operator-linewise に統合するのはやめた。 67558 但し、[cd] を特別扱いしていた部分を整理して最小限にした ([cd] は、常に first-non-space に移るという点で特別である)。 67559 67560 ble/keymap:vi/call-operator-linewise においては完全に [cd] は他のオペレータと同様の取り扱いに統合した。 67561 67562 更にオペレータを呼び出した後に元のモードに戻るのを実装する。 67563 67564 これは多分 vi_xmap/exit を呼び出せば良いだけではないか? 67565 67566 さて動作確認をする必要がある。 67567 67568 o オペレータ呼び出し後にちゃんと正しいモードに戻るか。 67569 OK 通常通りに呼び出した時はノーマルモードに戻り、 67570 挿入モードから C-o v を呼び出した時は上書きモードに対応する挿入モードに戻る。 67571 67572 o y の動作 d の動作 c の動作 67573 67574 x done: 範囲が足りていない。カーソルの右の文字も含めなければならない。 67575 更に vim で確かめてみると行末にあるときには更にその次の改行も含められるようだ。 67576 但し、一番最後の行の行末にいるとき (行末に行くことが出来る) には改行が付加されたりはしない。 67577 67578 そのような動作に修正した。確認した。 67579 67580 o 様々の移動コマンドを使うことができているか。特に引数付きで。 67581 67582 o 通常の文脈での c や d を書き換えたが、ちゃんと動いているだろうか。 67583 dw と cw で確認した。動いている。 67584 67585 x done: cj dj は動いている。と思ったら cj の後に行末 (インデント) に来ていない…。 67586 .relative-first-non-space の中の nonbol-eolp を needs-eol-fix に直した。直った。 67587 67588 o cc と dd もちゃんと動いているように見える。 67589 67590 x ok: 何だか分からないが上下に移動できなくなっている。 67591 と思ったら最新版ではなくて古いので試していた。 67592 67593 o 範囲が反転しているときには大丈夫か。大丈夫。 67594 67595 まあ恐らく大丈夫だろう。取り敢えずこの時点で commit しておくことにする。 67596 今までのメモで考慮するべきものに関しては分割して議論することにする。 67597 67598 * kill-current-line (dd), kill-current-line-and-insert (cc) の動作が違う気がする。 [#D0488] 67599 67600 先ず kill-current-line は first-non-space に移動しなければならない。 67601 kill-current-line-and-insert は新しい行を挿入して挿入モードにならなければならない。 67602 しかも元々あった行 (1行目) のインデントを保持しておかなければならない。 67603 67604 - dd で first-non-space に移動するように直した。 67605 - cc で元のインデントを保持して新しい行を挿入するように修正した。 67606 - cj でインデントを保持するのは未だ直っていない。直した。 67607 というか cj で行を消していたが実際には 67608 1 個新しい行を入れなければならなかったのだ。 67609 67610 2017-09-28 67611 67612 * ble-edit: 貼り付け対策のせいで RET を押しっぱなしにした時に [#D0487] 67613 67614 改行が入力されてしまう。これはそもそも自分の悪い癖なのであるが、 67615 似たようなことをする人は幾らかいると思われるし、 67616 編集文字列が空のときにはそのまま改行を実行と解釈しても問題はない。 67617 67618 従って編集文字列が空の時には次に文字が来ていたとしても 67619 そのまま実行と解釈して良いということにする。 67620 67621 2017-09-27 67622 67623 * 2017-09-06 ble-edit: BASH_REMATCH 復元について [#D0486] 67624 67625 任意の配列 BASH_REMATCH を、[[ some =~ some ]] を用いて復元するのは難しい。 67626 67627 % だとすると一つの方法は local BASH_REMATCH を ble-decode/.hook で定義することである。 67628 % 67629 % - 但し、exec:exec の場合には関数の内部でユーザコマンドを実行するので、 67630 % その際に unset BASH_REMATCH を実行する必要がある。 67631 % そしてユーザコマンドを呼び出した後で、適切な位置で再度 BASH_REMATCH を呼び出す必要がある。 67632 % 67633 % 関数 ble-decode/EPILOGUE の以下の行の直後で良いだろう。 67634 % 67635 % "ble-edit/exec:$bleopt_exec_type/process" && return 0 67636 % 67637 % - また exec:gexec の場合には ble-decode/.hook の外側でも処理を行うので、 67638 % その外で呼び出されうる全ての関数について local BASH_REMATCH を指定する必要がある。 67639 % 外で呼び出されうる関数に関しては変数 _ble_decode_bind_hook に設定されうる関数を調べれば良い。 67640 % _ble_decode_bind_hook に対する値の設定は現状でただ一箇所 ble-edit/exec:gexec/.setup の中である。 67641 % ここで指定される関数として以下のものがある。 67642 % 67643 % - ble-edit/exec:gexec/.eval-prologue 67644 % - ble-edit/exec:gexec/.save-params 67645 % - ble-edit/exec:gexec/.eval-epilogue" 67646 % - ble-edit/exec:gexec/.end 67647 % 67648 % - 他に trap を通して呼び出される関数がある。 67649 % 67650 % - ble-decode: ble-stty/TRAPEXIT これは単純な関数なので中で正規表現を使わないことは自明である。 67651 % - ble-edit: ble-edit/attach/TRAPWINCH 必要 67652 % - ble-edit: ble-edit/exec:exec/.eval-TRAPDEBUG 不要 67653 % - ble-edit: ble-edit/exec:exec/.eval-TRAPINT 不要 67654 % - ble-edit: ble-edit/exec:gexec/.eval-TRAPDEBUG 必要 67655 % - ble-edit: ble-edit/exec:gexec/.eval-TRAPINT 不要 67656 % - ble-edit: ble-edit/bind/stdout/TRAPUSR1 不要 67657 % - ble-edit: ble-edit/bind/.exit-TRAPRTMAX 不要 67658 % 67659 % また将来的に trap や _ble_decode_bind_hook を追加するときのために、 67660 % どの様な関数において local BASH_REMATCH をつける必要があるかについて 67661 % Note にまとめておく必要がある。 67662 67663 とここまでまとめて気付いたが local BASH_REMATCH を実行しても 67664 読み取り専用の変数ですと表示されて怒られる。 67665 更に、BASH_REMATCH に対する変更の影響は結局関数の外でも残る。 67666 つまり local BASH_REMATCH としても効果はなくエラーメッセージが表示されるだけである。 67667 67668 一番理想的な方法は正規表現の一致に使用された文字列と正規表現を特定することだがそれは難しい。 67669 もし一致全体 ${BASH_REMATCH[0]} のことを気にしないで良いのであれば、 67670 ${BASH_REMATCH[i]} に対して (.{${#BASH_REMATCH[i]}}) を一致させるようにすれば良い。 67671 問題は一致全体である。結局一致全体は不動なので [[ $BASH_REMATCH =~ 某 ]] とするしかない。 67672 この時各子一致は独立ではなくて overlap があることに注意する。 67673 67674 特に、各子一致は入れ子構造になっていなければならないという制限が存在する。 67675 さて、問題は子一致の内容が指定されたときに入れ子構造を再現することができるのかということである。 67676 また各子一致の順序も保持しなければならない。 67677 67678 1 各子一致について先頭から順に見ていくとする。 67679 或る子一致について、先ず既存の子一致に対する入れ子関係を決定する。 67680 一般に複数の可能性がある。つまり、全体一致の部分列として複数の位置に存在する可能性があって、 67681 更に既存の子一致に対する入れ子関係と矛盾しない (既存の子一致の終端を跨がない) という条件を課しても、 67682 複数の候補が残る可能性がある。 67683 67684 2 この時、一番初めの (即ち、一番内側の入れ子になるような) 可能性を選んでも問題は起こらない。 67685 何故ならば後続の子一致は、現在処理している子一致に完全に含まれるか、 67686 或いは現在処理している子一致より明確に後に位置するかであるため、 67687 本来の一致位置より左側に平行移動する分には何も問題が起こらないからである。 67688 67689 この手順によって各子一致の開始位置を決定することができる。 67690 その後に対応する正規表現を () と .{幅} の組み合わせで構築すれば良い。 67691 後は $BASH_REMATCH と構築した正規表現を何処かの変数に保存しておけば、 67692 [[ $saved_rematch =~ $saved_rex ]] でいつでも BASH_REMATCH の状態を復元できる。 67693 67694 [実装] 67695 67696 取り敢えず実装した。動いている気がする。実装している途中に気付いた点として、 67697 67698 - 一致に失敗すると BASH_REMATCH は空になる。 67699 - 初期の状態では BASH_REMATCH は unset の状態になっている。 67700 - BASH_REMATCH を手で unset することはできない。 67701 67702 初期の unset の状態には戻せないので ble.sh では BASH_REMATCH を空にする 67703 (具体的には [[ '' =~ none ]] を実行する) ことにした。 67704 67705 * 2017-09-25 ble-edit: 貼り付け対策 [#D0485] 67706 67707 % 誤って貼り付けを行ってしまってあらぬコマンドが次々に実行されてしまうという事故がある。 67708 % 実はこれは検出可能なのではないだろうか。 67709 % 前の入力に対して間髪を入れずに改行が入力された場合は怪しい。 67710 % 67711 % ただ IME を通して日本語を大量に入力して、その処理が終わっていない内に改行を押すこともあって、 67712 % そのような場合に改行として入力されてしまうと分かりにくいので、複数行編集の表示はやはり必要である。 67713 % 67714 % また isearch で処理に時間がかかっているときに改行を押す場合も考えられる。 67715 % この場合には accept するか無視するかにした方が良い。 67716 % 現在は accept になっているが本来は無視するのが正しい気がする。 67717 % 67718 % これの判定は以下のようにする 67719 % - self-insert に引き続いて改行を入力したときは、改行を挿入する 67720 % - それ以外に引き続いて改行を入力したときは、bell 67721 % - idle 時に改行を入力したときは accept-line または複数行編集ならば改行挿入 67722 67723 実は、その改行が前の文字に間髪入れずに入ってきたとかではなくて、 67724 単に改行に引き続いて何かが入力されているという判定で良いのでは? 67725 67726 できるかと思ってやってみたができない。 67727 貼り付けているとしても改行を処理しているときには次の文字は未だ来ていないのだろうか。 67728 と思ったが、よく見ると実行の遅延はちゃんと処理できている。 67729 ということは ble/util/is-stdin-ready は真になっているはずである。 67730 なのに accept-single-line-or をすり抜けるのはおかしい。 67731 67732 と思ったら accept-single-line-or を通過していない。何故? 67733 実は vi-{command,insert}/accept-single-line-or の方は独立した実装になっていた。 67734 これらも同時に修正する必要がある。修正した。ちゃんと動くようになった。 67735 67736 * 2017-09-25 ble-edit: 複数行編集のスクロールについて [#D0484] 67737 67738 現状の実装では端末の高さよりも高くなると変な表示になることを甘受している。 67739 zsh で試してみたら ... と表示して前方の行を省略するようである。 67740 これは ble.sh でも実装可能のはずである。 67741 67742 描画範囲を制限する様にすれば良い。 67743 描画は関数 ble-edit/render/update で行っている。 67744 幸い現在の実装では描画内容の決定と実際に描画を行う部分が分離されている。 67745 この実際に描画を行う部分の改修で済めば嬉しい。 67746 67747 実際に何に気をつけなければならないかというと、 67748 67749 1. 現在の先頭行の行番号を保持するということ、 67750 現在の先頭行の行番号は現在のカーソルの位置に依存して修正する必要があること。 67751 2. 先頭行の行番号を変更するときにはスクロールを伴うこと、 67752 特に、スクロールにより隠れていた部分は再描画が必要になる。 67753 3. 実はスクロール処理と変更部分の更新描画は分離できるということ。 67754 67755 恐らくスクロールがある場合には先にスクロール処理をしてしまってから、 67756 変更部分の描画を行うようにすれば良い。 67757 67758 * ところで、スクロールによって再描画された部分については後で再度描画する必要はなかったりする。 67759 下手すると完全に 2 度描画してしまうということも考えられる。 67760 これについてはどのように処理すればよいかは微妙。 67761 と思ったが、再描画範囲は現在単一の range で管理しているのだから、 67762 実はスクロールによって再描画範囲を削るというのの実装はそんなに難しくないのでは。 67763 →実際に観察してみると umin, umax で再描画範囲を管理している。 67764 スクロールによる描画でこれらの境界を踏む場合には umin, umax を狭めることで対処できる。 67765 67766 * と思ったけれど info が複数行ある場合などを考えると全体で収まるように調整しなければならない。 67767 67768 [実装] 67769 67770 * コメントアウトされている古いコードで 67771 - プロンプトは更新しないけれど編集文字列は全描画するものと、 67772 - 全体描画後にカーソル位置を設定するときに SC/RC を利用するものは、 67773 コードの管理・維持が面倒になったし今後使われるとも思われないので削除する。 67774 前者については、今後必要になったらその時に新しく書き起こせば問題ない。 67775 後者については、わざわざカーソル位置で表示文字列をスライスしなければならないので、 67776 処理としても無駄が多いし、ユーザの設定する SC/RC と干渉するのも嫌である。 67777 67778 [動作確認] 67779 67780 x resolved: カーソル位置が二重になっている。これはどういうことか。 67781 _ble_line_cur に収めるカーソル位置の値は実際に表示されている位置であった。 67782 修正したらこれは直った。 67783 67784 x resolved: スクロール状態になっているとき、最下行にいたとしても margin が加えられている。 67785 カーソル位置に対応するスクロール量の上限・下限の値の計算方法を書き直した。直った。 67786 67787 x resolved: 一番上の行に移動するとき、上へのスクロールが実施されていない気がする。 67788 シフト量の符号が逆転していた→直した。 67789 67790 x resolved?: X座標の位置計算をミスっている。 67791 スクロール時に常にカーソル位置が左端になっている。 67792 →スクロール量の修正をしたあとで再度確かめてみたら直っていた。 67793 結局、何が行けなかったのかは謎。 67794 67795 x resolved: C-l で clear-screen すると表示されてはならないところまで全部表示されてしまう。 67796 67797 % これは、実際に描画内容を出力している部分を全部列挙して、 67798 % 全ての箇所に対してスクロールの対応を加える必要がある。 67799 % 取り敢えずは、これについては保留として、 67800 % 初めに通常編集時の表示のずれを修正する。 67801 67802 確認してみたら単に render/update の全体描画の際の、 67803 スクロールがあるかないかの判定の部分が反転していただけであった。 67804 と思って直したら、今度は何も表示されないしカーソル位置がずれている。 67805 67806 うーん。と思ったら部分描画の部分のコードが色々間違っている。 67807 存在していない変数を使って計算していた。これを直したら直った。 67808 恐らく描画範囲が負になったりしていたのだろう。 67809 それで位置がずれたりしていたのだと思われる。 67810 修正した。直った。 67811 67812 + done: history-forward で編集文字列の末端に移動するのはどうだろう。 67813 これは編集文字列の一行目の末端に移動するのが良いのではないだろうか。 67814 振る舞いを修正した。OK 67815 67816 + done: [[ ! $bleopt_suppress_bash_output ]] のときに使われる 67817 ble-edit/render/redraw-cache の中での再描画は、 67818 現状では全体再描画になっていてスクロールに対応していない。 67819 仕方がないので [[ $_ble_line_scroll ]] の場合には最初から全部描画することにした。 67820 しかし、これはちらつきの原因になる。 67821 67822 現状では ! $bleopt_suppress_bash_output はデバグ用途でしたか使われないとはいえ、 67823 中途半端な実装になっているのは気分が悪いので後で対応を考えることにする。 67824 67825 x resolved: 弄っていたら何故か履歴項目を移動したときに 67826 スクロール領域を制限せずに全てぺろりと表示されるようになってしまった。何故か。 67827 67828 色々調べた結果、get-index-at の内部で 67829 _ble_line_begy _ble_line_endy を使っているのにも拘らず、 67830 これを更新する前に get-index-at を使用していたからであった。 67831 しかし、もし get-index-at の内部でこれを使用するのであれば、 67832 寧ろ _ble_line_{beg,end}{x,y} は ble-edit/text/update の中で更新するべきなのではないだろうか。 67833 67834 → ble-edit/text/update/position の中で更新する様に変更した。 67835 更に変数名をそれに合わせて _ble_line_text_* に変更した。動作している。 67836 また勝手に中身をクリアしたりしている箇所でもクリアしないことにした。 67837 更新は ble-edit/text/update が呼び出された時に行われるであろう。 67838 逆に言えば ble-edit/text/update が呼び出されていない状態で 67839 _ble_line_text_{beg,end}{x,y} を使用することは不正である。 67840 これについても確認してみると、何れの場合でもちゃんと 67841 ble-edit/text/update が呼び出されていることをチェックしてから使用していたので、問題ない。 67842 67843 取り敢えず複数行編集のスクロールの対応は一段落したことにする。 67844 これからまたバグや不整合が出て来る気がするが、それはその都度対応することにする。 67845 67846 2017-09-25 67847 67848 * bleopt での値チェックを実装する [#D0483] 67849 67850 これは以前発案の onchange と合わせて考察する。 67851 67852 | * 2015-11-18 bleopt コマンド: onchange 67853 | 67854 | 変数の値が変わった時に onchange イベントを起こす仕組みを整えても良い。 67855 | これは変数の内容変更にともなって処理が必要な変数が出てきてから考える。 67856 67857 或いは値を設定する関数を定義できるようにするのが一番柔軟だろうか。 67858 しかしそれは変数としての実体が存在しないものに対しては良いが、 67859 そうでないもの (bleopt 変数) に関しては適していない気もする。 67860 67861 value というローカル変数を設定してから関数を呼び出してチェック・修正してから、 67862 値を設定するというようにするのが良い気がする。 67863 67864 67865 2017-09-24 67866 67867 * vi-mode: 前回からの修正: [#D0482] 67868 67869 - vi-mode: 行単位の操作 (2yj など) をするとエラーになるバグの修正 67870 - vi-mode: 現在位置よりも先に操作対象があるとき (yib など) 位置の移動が起こらないバグの修正 67871 - vi-mode: isearch の途中でノーマルモードに移行すると選択状態がそのままになるバグの修正 67872 - char_width=emacs のとき、★などの文字 (U+2000 - U+2600) の文字幅が常に 1 になっていたバグの修正 67873 - $? 及び $_ の再設定が動かなくなっていたバグの修正 67874 - vi-mode: {count}L で現在行より上に行く場合、{count}H で現在行より下に行く場合などで範囲が裏返るバグの修正 67875 - vi-mode: + - H L yib などで非空白行頭に移る条件の修正 67876 - vi-mode: オペレータを指定したときの gg G は現在のコマンド内の移動だが、引数省略時に引数 1 と解釈していたバグを修正 67877 67878 - vi-mode: rx grx で上書き対象を着色 67879 - vi-mode: imap: C-m, C-h, DEL; nmap: o, O でインデントを特別扱い 67880 67881 - テキストオブジェクト [ia][pst] 67882 - コマンド % {count}% 67883 - vim-surround.sh: 設定 "bleopt vi_surround_45", etc. に対応 67884 67885 * 2017-09-22 vi-mode: "-- NORMAL --" という表示をした方が良いか? [#D0481] 67886 67887 zsh vi-mode で検索したら以下のような記事を見つけた。 67888 -- NORMAL -- を表示している。色も変えられる様にしている。 67889 67890 https://qiita.com/b4b4r07/items/8db0257d2e6f6b19ecb9 67891 67892 或いは (複数行編集のときのために) ~ を表示するようにするのが分かりやすい気がする。 67893 やはり現在複数行編集なのかどうかが分からないので ~ (もしくは -- NORMAL --) は表示するべきの気がする。 67894 67895 これは既定で ~ (太字) とし、設定項目で指定できるようにした。 67896 67897 * 2017-09-08 vi-mode: % [#D0480] 67898 67899 引数を指定した時の動作についてはよく分からない。 67900 括弧の上にいるときは対応する括弧の上に移動する。 67901 括弧の上にいないときは同じ行内で右に向かって括弧を探し、 67902 最初に当たった括弧に対応する括弧に移動するようだ。 67903 67904 <> は括弧として認識しない。[] () {} は括弧として認識する。 67905 引数を指定した時の動作は不明である。 67906 67907 cmplstofB: 2017-09-17 要望が入った。 67908 67909 | Vim のノーマルモードにおいて % は「対応する括弧(もしくはそれに準ずるもの)の対に飛ぶ」 67910 | という機能が割り当てられています。(:help %) 実装していただくととても嬉しいです。 67911 67912 * :help % で見てみると引数は許されないと書かれている。 67913 {count}% で count % だけ次の行に行くそうだ。 67914 成る程。確かに試してみるとそうなっている。 67915 :help N% というので説明が見られるようなので調べると、式も与えられている。 67916 67917 ({count} * number-of-lines + 99) / 100 67918 67919 count% だけ下に移動するのではなくて、 count% の位置にある行に移動するようだ。 67920 67921 * matchpairs という変数で指定できるということになっている様だが、 67922 どのように指定するものなのかは :help % には書かれていない気がする。 67923 :help matchpairs で見てみると default "(:),{:},[:]" と書かれている。 67924 67925 まあ取り敢えずこれの事は考えないことにする。 67926 67927 初めの括弧に関しては行内での探索のようである。 67928 67929 * vi-mode: o O でもインデントは認識する [#D0479] 67930 67931 O は一つ前の行のインデントではなくて、現在の行のインデントを継承する。 67932 67933 * vi-mode: 空白だけの行でインデントは有効か? [#D0478] 67934 → 有効である。C-m でも継承されるし、DEL でも一度に消せる。OK 67935 67936 * 2017-09-23 vi-mode (text object ?s): どうも実装が不完全だ。 [#D0477] 67937 67938 - 先ず yas yis で引数を指定したとき、段落を越えて範囲は拡大する。 67939 - 更に、初めに空行にいた時の動作も引数が指定したときに対応できていない。 67940 67941 連続改行は一つの文として取り扱われている気配がある。 67942 67943 正規表現を改良すればなんとかなるかもしれないしならないかもしれない。 67944 よく分からないが取り敢えず先に p を実装する。実装した。 67945 67946 * 先ずは段落を跨ぐように改造する必要がある。 67947 67948 少なくとも段落の終端は使わないようにする必要がある。 67949 更には段落の先頭も使う必要がない可能性がある。 67950 これについては先ずは段落の終端を使わないように修正し、 67951 その後で更に段落の先頭も使わないように変更できるかを考察する。 67952 67953 取り敢えず段落の終端を越えて当たるように修正する。 67954 段落の境界の取り扱いがどうなっているのかについては、 67955 yis を使って調べることができる。 67956 67957 以下 @ がカーソルの位置で、 67958 数字は "{数字}yis" とした時に何処まで範囲とするかを示したものである。 67959 67960 | @echo hello.1 2echo world.34 67961 | 67962 | 67963 | 56 67964 | echo hello.7 8echo world.9 67965 67966 % これを見るに、恐らく本来は 67967 % 67968 % | @echo hello.1 2echo world.3 67969 % | 4 67970 % | 67971 % | 5 67972 % | 6echo hello.7 8echo world.9 67973 % 67974 % の様になっていて、但し補正されて上記のようになっているのではないかと思われる。 67975 % ここで疑問となるのが 5 が何故補正されないのかということである。うーん。 67976 % 67977 % - 前の行の内容が存在している時には補正する (4) 67978 % - その行の内容が存在している時には補正する (6) 67979 % 67980 % という規則を考えれば良いだろうか。 67981 % 67982 % 更に、この補正前の 3456 の動きについて考える。 67983 % 67984 % (1) 3->4 に関しては行末にいて、 67985 % 現在行が非空行であれば次の行頭に行くということになろうか。 67986 % 67987 % もう少し検証する。行末に空白があるときの動作はどうだろう。 67988 % 67989 % | @echo hello.1 2echo world.3 (←空白がある) 67990 % | 4 67991 % | 67992 % | 5 67993 % | 6echo hello.7 8echo world.9 67994 % 67995 % 変わっていないように見える。 67996 % うーん。空行にいない限りは通常の空白探索の動作ということにして、 67997 % 更に通常の空白探索では連続する LF の内 2 番目のものを受け取らないという事にするべきか。 67998 % 67999 % (2) 4->5 に関しては、 68000 % 68001 % 1 空行にいるときに \n の連続を読み取る。 68002 % 2 最後の \n だけは読み取らずに一つ戻る。 68003 % 68004 % と理解できるだろうか。しかし幾つか疑問点が残る。 68005 % 先ず間に空行が1個しかない場合の動作はどうなるのか。 68006 % その場で動かないのか、或いは、次の段落の頭に移動してしまうのか。 68007 % 68008 % →試してみた所以下のようになった。 68009 % 68010 % | @echo hello.1 2echo world.3 (←空白がある) 68011 % | 45 68012 % | 6echo hello.7 8echo world.9 68013 % 68014 % これは変だ。ということはやはり 45 のどちらかは補正前でも 68015 % 別の場所にあると考えるべきなのだろうか。うーん。 68016 % 所が、3-6 の間にカーソル位置は 3 つしかない。 68017 % その中に 4 つの停止点があるということは、 68018 % 他の内部状態が存在するか (exclusive inclusive など)、 68019 % 或いは、実は停止などしていなくて arg を 68020 % 2 消費する移動が存在するかのどちらかである。 68021 % 68022 % うーん。2消費する移動だと解釈することにする。 68023 % どちらであったとしても区別可能であるとは思えないので。 68024 68025 もう分からないのでまた vim のソースコードを見ることにした。 68026 どうやら文の終端は /[.!?]\s/ ではなくて /[.!?][])'"]*\s/ 68027 68028 うーん。どうも "現在空白" と "現在文" という二つの読み取りを交互に行っている様だ。 68029 そして、空行の集合のスキップは "現在文" の状態の時に行われる。 68030 68031 多分以下のようになっている。 68032 偶数番から奇数番の時にだけ空行を跨ぐことができると思われる。 68033 68034 | @echo hello.1 2echo world.3 68035 | 4 68036 | 68037 | 68038 | 56echo hello.7 8echo world.9 68039 68040 他の場合にも調べることにする。 68041 空行で初めた時には、試した結果、恐らく以下のようになっている。 68042 68043 | @ 68044 | 68045 | 0 68046 | 12echo.3 68047 68048 うーん。結局実装し直しということになりそうだ。 68049 実装し直した。動作確認する。 68050 68051 o 空行しか無い時に全てを取り尽くすことを確認した。 68052 o これ。 68053 | @echo hello.1 2echo world.3 4(←空白) 68054 | 68055 | 68056 | 68057 | 56echo hello.7 8echo world.9 68058 o これ。OK 68059 | @ 68060 | 68061 | 0 68062 | 12echo.3 4world. 68063 x 行末に空白がない時に backward に空白を取るのができていない。 68064 →LF, HT の定数が定義されていない状態でそれを使って正規表現を構築していた。直した。 68065 x 今度は段落を越えて backward に空白が取られている。 68066 この正規表現の場合には一番最初に当たるのは $LF$LF だと思ったのだが…。 68067 →正規表現が悪かった。二重改行があったとしても終端 $ に接することを要求していたのが悪い。修正した。 68068 x 段落の末端にいるときに前方の空白を取り込んでくれない。 68069 →どうも試してみると正しく取り込めている。 68070 どうやら linewise で実行されると first-non-space に移動しているというだけだった。 68071 しかし vim では行頭に移動する。これは新しい linewise のオプションを追加する必要がありそう。 68072 68073 うーん。これは…。このまえ修正した linewise は正しくない気がする。 68074 68075 linewise を大修正した。これで再度チェックをやり直してみる。 68076 68077 o "@echo hello.1 2echo world.34^J^J^J^J56echo hello.7 8echo world.9" OK 68078 o "@echo hello.1 2echo world.3 4^J" OK 68079 o "@^J^J0^J12echo world.3^J" OK 68080 x yis で何故か前方の空白を取り込んでいる? 68081 68082 うーん。これはよく考えたら実装の過程では考えなかったことである。 68083 つまり、文の区切りは "二重改行" または "句読点+空白" ではなくて、 68084 "二重改行[+空白]" または "句読点+空白" なのである。修正する。 68085 68086 →修正した。yas yis の動作確認もした。 68087 最終行の時、次に空行があるときのそれぞれについても確認した。OK 68088 o 段落を越えて前の空白を取り込むということはない。 68089 o 単一行段落の末端にいるときの yas で前方の空白を取り込んでかつ、 68090 行頭に移動するという動作に関しては、既に試したようにちゃんと実装できている。 68091 68092 恐らくだいたい大丈夫であろう。 68093 68094 * vi-mode (linewise-range): bug in reverted [#D0476] 68095 68096 linewise-range.impl の実装を調べていて気がついたが。 68097 例えば一番下から 2 つ目の行で 5yL などとすると、 68098 linewise-range.impl の中の reverted の判定に失敗する。 68099 68100 結果として "先頭行の末端" から "最終行の先頭" までが切り取られ、 68101 更に切り取り後のカーソル位置は先頭行ではなくて最終行になる。 68102 68103 現在のインターフェイスを変えるのも面倒なので、 68104 linewise-range.impl の reverted の計算を厳密にやるようにするか。 68105 或いは、呼び出し元で全て解決してから渡すようにするという手もある。 68106 →呼び出し元で処理する場合には、それぞれで両端の前後関係に応じた場合分けが必要になり面倒である。 68107 その辺りのごちゃごちゃも一緒に統一したのが linewise-range.impl であった。 68108 従って、やはり linewise-range.impl の中でごちゃごちゃと計算したほうが良い気がする。 68109 68110 実装した。結局その場で各先頭行と最終行の行頭を計算するようにした。 68111 68112 # 合成する際に各実装の最適化をそのままにくっつけたのが混乱の原因だ。 68113 # もし初めからこの様にくっつけて実装するのだとしたら、以前のような変なことにはしない。 68114 # (或いは、もっと上等な遅延評価の仕組みを整えてから実装する必要があるだろう。) 68115 # 整理されたコードというのはその分だけ非効率的な部分も許容しなければならないのである。 68116 68117 次に動作チェックを行う必要がある。 68118 68119 - 特に実装の過程で require_multiline の辺りのコードも一緒に整理された。 68120 - また y オペレータの後に非空白行頭に行く処理も変更があったが、 68121 これはその処理の修正をこれからするところなのでそれが終わってからチェックすれば良い。 68122 68123 % x 2行目で 3yH を実行すると 3 行目に移動してしまう。これは変だ。 68124 % と思ったら修正までのコードで動かしていただけだった。問題なかった。 68125 % x 下から 2 行目で 5yL を実行すると、下から3-4行目だけが切り取られ、 68126 % 下から2行目に現在位置は留まる。この動作を直す為に修正したはずなのに直っていない。 68127 % と思ったらこれはまた古いコードで動かして試していた。 68128 68129 x 下から2行目で5yLを実行したら以下のようなエラーが発生した。 68130 ((: 48:-4: 式に構文エラーがあります (エラーのあるトークンは ":-4") 68131 →これは reverted かどうかの判定で直接 p q を用いていたのがいけない。直した。 68132 o 下から2行目で4yLを実行して正しく動作することを確認した。 68133 68134 [require_multiline の確認] 68135 68136 o 一番下の行で yj y+ をしてエラーになること 68137 o 一番上の行で yk y- をしてエラーになること 68138 o それ以外の場合にはエラーにならないこと 68139 68140 68141 * vi-mode (linewise-range): #D0470 の修正はやはり変だ。 [#D0475] 68142 68143 % relative-line では行を移動しない場合はないと書いたが、 68144 % y+ のように下に移動するときには beg は初めと同じ行にある。 68145 % この時のどの位置に移動する(移動しない)のかというのは非自明である。 68146 % 68147 % - 更に ygg としたときに nol が ind よりも後にある場合には ind は動かない。 68148 % これは個別に動作を考えたほうが良いような気がしてきた。 68149 % 先ず初めに言えることは従来の実装では ind は 68150 % 必ず beg-end の範囲に入っている (はず) ということである。 68151 % 68152 % 更に ind!=beg のときだけ処理を行うということになっているが本当だろうか。 68153 % これは preserve_column など各々の動作で異なるのではないだろうか。 68154 % →各処理法毎に判定することにし、外側では ind!=beg の判定はしないことにした。 68155 68156 修正した。と思って動作確認をしようとしたらやはり実装を間違えている気がする。 68157 一旦動作について整理する必要がある。 68158 68159 % y+, 2yH とすると非空白行頭へは行かないが 1yH とすると非空白行頭へ戻る。 68160 % つまり + - H G L などでは、先頭行が行き先の行であるときには非空白行頭へ移動する。 68161 % 先頭行が行き先の行でないときには、ind が先頭行にいないときに非空白行頭へ移動する。 68162 % それ以外の (先頭行が行き先ではなく、かつ ind が元からそこにある) ときは、動かない。 68163 % 68164 % "+ - H G L" の動作について整理する。 68165 % 68166 % - 先頭行が行き先の行であるとき 68167 % - 現在行が他の行にあるときは非空白行頭に移動する 68168 % - 現在行が先頭行にあるときは、現在位置が非空白行頭より後にあるときに限り非空白行頭に移動する 68169 % - 先頭行が行き先の行でないとき 68170 % - 現在行が他の行にあるときは非空白行頭に移動する 68171 % - 現在行が先頭行にあるときは、動かない 68172 % 68173 % これはもっと簡単にできる。 68174 % 68175 % - 現在行が先頭行にあるとき 68176 % - 先頭行が行き先の行であるとき、現在位置が非空白行頭より後なら非空白行頭に移動する 68177 % - 先頭行が行き先の行でないとき、動かない 68178 % - 現在行が他の行にあるときは非空白行頭に移動する 68179 68180 - 現在行が他の行にあるか先頭行が行き先の行であるとき、 68181 - 現在位置が他の行にあるか非空白行頭より後なら、非空白行頭に移動する 68182 68183 動作確認 68184 68185 - yib (block.impl) の動作確認 68186 - yis の動作確認 → これは現在実装している途中なので後でチェックするので今はいい。 68187 68188 o 2行目で 3yH, y+ を実行して動かないこと、 68189 o 2行目で 2yH を実行して非空白行頭に後退すること 68190 o 2行目の行頭空白で 2yH を実行して動かないこと 68191 68192 [yib の動作確認] 68193 68194 o "(^J echo hello^J echo world^J)" に対して、 68195 ちゃんと vim の動作と同様に、中身の行頭に移動することを確かめた。 68196 68197 2017-09-23 68198 68199 * memo.txt: ユーザ名 B-bar を cmplstofB に統一した [#D0474] 68200 68201 * vi-mode: by cmplstofB [#D0473] 68202 68203 | Bash の vi-mode にはないのですが、テキストオブジェクトを実装して欲しいです。 68204 | Zsh の vim-mode では実装されています。 68205 68206 これは実装したい。が、コマンド体系がよく分からないのでどのように dispatch するのが良いか微妙。 68207 vimindex に色々なテキストオブジェクトについて記述がある。 68208 [ydc] が設定されている時に [ia] が来たら、その時点で別のキーマップに切り替えるなどすれば良いのだろうか。 68209 68210 更に ysiw" は体系としてかなり謎である → これは独立した項目 #D0446 を立てて対応することにした。 68211 68212 現在未実装なのは [ia][pst] である。 68213 68214 * t は #D0461 68215 68216 * s は #D0472 68217 68218 * p について調べる。 68219 68220 これまで試した様子からいうと二重改行なのではないかと思われる。 68221 と思ったが、間に空白だけの行が含まれていても段落の分割になるようだ。 68222 68223 ip と ap は区別はないような気がする。 68224 と思ったが dap と dip を比べると dip は段落の次の空行を残すようだが、 68225 dap は段落に続く行たち (複数可能) も一緒に削除する。 68226 68227 また行指向の切り取りになっている。 68228 68229 1 つまり段落は1つ以上の空行 (空白だけの行) で区切られる。 68230 2 ap は段落に後続の空行たちを含む。 68231 後続の空行がない場合には前にある空行たちを含むようになる。 68232 ip は含まない。 68233 68234 うーん。これについても詳細に動作を調べる必要がある。 68235 sentence の動作に大分似ている様だ。 68236 68237 調べて実装した。 68238 68239 [確認] 動作を確認する。 68240 68241 o yap で段落の数を指定して選択し、 68242 yip で段落または空行たちの個数を指定して選択する。 68243 o yap で最後に空行のない段落の場合に前方にある空行たちを取り込む 68244 o 空行しか無い場合の yap, yip の動作も大丈夫。 68245 68246 取り敢えずは OK ということにする。 68247 68248 * vi-mode: text object is as [#D0472] 68249 68250 s について調べる。先ずは as 68251 68252 - "日本語。abc. 日本語。" を試すと 68253 "日本語。abc. " と " 日本語。" になる。 68254 日本語の句読点は認識していないということと、 68255 前後の空白も含まれるということ。 68256 - "Hello, i.e., this is a test. This is Q.E.D." 68257 これは "Hello, i.e., this is a test. " と " This is Q.E.D." になる。 68258 思ったよりは賢い。仮説: . の後に空白があれば文が切れると判定している。 68259 - 前後の改行も含まれるようだ? しかしよく分からない。 68260 1. 先ず行末の . でも良いということ 68261 2. 更に行末の . であり次の行頭にすぐ文字がある場合は、 68262 前の行の空白も含むようだ? 68263 68264 実は改行か空白かは余り区別していない気がする。 68265 先ず初めに一番最初の非空白文字から . 後の空白までを範囲とする。 68266 途中に連続改行がある場合はそこで終わるように範囲をせばめる。 68267 更に末端に改行があればそれを除くように範囲をせばめる。 68268 もし . が一番最後の文字になっている場合は、文の先頭にある空白を取り込む。 68269 これは前の行にも遡り、前の行末に空白がなくても改行だけを取り込む。 68270 68271 % 以下の方法で文の範囲を決定する。 68272 % 68273 % 1 どうも先ず二重改行で区切られている領域 (段落) を決定し、 68274 % 更にその範囲の中で探索を行っているようだ。 68275 % 二重改行は空白行を含んではいけない、厳密な二重改行である。 68276 % 2 その範囲の中で "最初の単語から . に続く空白類" までを文の範囲とする。 68277 % 3 範囲末端に改行がある場合にはそれを除くように範囲をせばめる 68278 % 4 もしこの時点で . に続く空白類が一つも範囲に含まれないのであれば、 68279 % 文の前にある空白類(改行も)を範囲に入れるように拡大する。 68280 % 5 但し、先頭の改行は除外するようにせばめる。 68281 % 68282 % 文の区切りは "! " "? " でも良い。 ": " や "; " は駄目。 68283 % [!?.] の前に非空白文字があるかどうかは問わない。 68284 % 68285 % is についてはどうだろう。これは空白類を除くだけのようだ。 68286 % つまり [!?.] の類は含まれる。 68287 % 68288 % 取り敢えず実装したと思って今度は yis を実装し始めたら思わぬ動作をする。 68289 % 空白の位置にカーソルがある場合には空白が対象になる。 68290 68291 - これは実装方法を間違えたかもしれない。 68292 - しかも引数のことも完全に忘れていた。 68293 - linewise になる条件はよく分からない。 68294 改行が含まれていれば linewise になるという訳でもない。 68295 恐らく行頭から行末までを切り取った時に限り 68296 linewise になるのではという気がする。 68297 68298 実装し直した。 68299 68300 [確認] 68301 68302 動作確認をする。 68303 68304 x yis も yas も後方に向かって空白も取り込んでいる。何故? 68305 → backward-extend を確認したら空白の幅を足し忘れていた。直した。 68306 x 文の真ん中の空白で実行するとそこから文が始まると勘違いする。 68307 →よく考えたら backward-extend で空白かどうかだけを見るのでは駄目だ。直した。 68308 x 丁度行全体を捕まえるときカーソルが移動しない。オペレータは動作している → #D0470 68309 x 一番最初の空行が段落に含まれてしまっている → これは直した。 68310 x 空行だけで構成されているとき ${str:offset:len} で len が負になるエラーが出る 68311 範囲拡大の起点が piv ではなくて _ble_edit_ind になっていた → これも直した。 68312 x 空行だけで構成されているとき対象となっている行数が少ない? 68313 これは空行だけで構成されているかどうかの判定が誤っていた → s/_ble_edit_ind/piv/ 直した。 68314 x 空行に続いて段落がある場合にカーソルが移動しない → #D0471 68315 o yis yas のそれぞれについて引数は試した。 68316 yas が後方の空白を取り込むことも確かめた。 68317 o 後方の空白が次の行にある場合にも取り込むことを確かめた。 68318 x 同じ行内の後方の空白が取り込まれていない… 68319 いや、空白は取り込まれているけれど何故か前方にも空白を取り込んでいる。 68320 →改めて末尾に関する条件を見たら良くわからない条件になっていたので直した。動作確認した。 68321 o 段落の末端または行末に達する場合に、 68322 前方の空白を取り込むことも確認した。 68323 o 前方の空白が改行だけの場合それを取り込まないことも確認した。 68324 o 前方の空白が前の行の末尾にある場合それを取り込むことも確認した。 68325 68326 * vi-mode: linewise-range.impl において [#D0471] 68327 現在位置が作用対象よりも前に存在するときに、 68328 作用後に非空白行頭に移動しないのは変なのではないか。 68329 68330 これについては vim の動作を調べる。 68331 - "カーソル ( 改行 echo 改行 )" のときに yib とすると 68332 vim では echo の先頭にカーソルが移動する。 68333 ble.sh ではカーソルは移動しない。 68334 ^ その他の既存のものでは現在位置が作用対象よりも 68335 前に来ることはなかったはずである。 68336 68337 直した。 68338 68339 * vi-mode: linewise-range.impl において [#D0470] 68340 行を移動しないときに非空白行頭に移動しないのは変なのではないか。 68341 68342 実際にこれを呼び出している各機能の振る舞いについて vim で再度確認する。 68343 - yib は vim では行頭に移るが ble.sh の現在の実装では移らない。 68344 - nth-line, nth-last-line, last-line に関しては、2行目にいるときに 68345 vim で 2yH とすると行頭に移るが ble.sh で 2yH としてもそのままである。 68346 - relative-line などでは行を移動しない場合はないので、これは気にしなくて良い。 68347 68348 以上の調査の結果、linewise-range.impl では、 68349 preserve_column でないとき行を移動しない時でも行頭に移動するべきである。 68350 68351 * 2017-09-17 vi-mode: 改行挿入時 [#D0469] 68352 68353 前の行のインデントを引き継ぐようだ。 68354 但し何も入力しない場合はインデントは消滅してなくなる。 68355 面倒なので何も入力しないときにインデントが消滅することには対応しない。 68356 68357 C-m でも C-j でも同様に動作する。 68358 更に気付いたことは BS, C-h でインデントが削除されるということ。 68359 (インデント以外であればちゃんと一文字ずつ削除される。) 68360 68361 * 2017-09-19 起動して未だ初期化している途中に入力した文字列が下に押し出されてしまう。 [#D0468] 68362 起動した瞬間の ble-form/panel の状態を別のものにした方が良いのかもしれない。 68363 →対策した。 68364 68365 * 2017-09-23 ble-edit: [bug] ble/util/c2w: 何か ★ の幅の計算が間違っている気がする。 [#D0467] 68366 emacs, screen (修正済), poderosa のどれにおいても★で変な動作になっていないが、 68367 ble.sh で★を入力した時にずれる。 68368 実際にやってみると 1 と表示される。これは変だ。 68369 68370 $ ble/util/s2c ★; echo $ret 68371 9733 68372 $ ble/util/c2w 9733 68373 1 68374 68375 自前の screen では 2 になっているのではないかという気がする。ずれていないので。 68376 しかし同じ表を使って計算している筈なのに変だ。 68377 もしかすると表の引き方を間違えているのではないかという疑惑がある。 68378 68379 9733 は表の 1797 に対応して、その周辺では 1776 1797 1799 となっている。 68380 試してみると 9732 9733 9734 9735 と全部試しても 1 になる。変だ。 68381 68382 調べてみた所 9733 が tIndex=1797 に修正されるべきところで、 68383 そのまま透過して tIndex=9733 になっている。 68384 なんと! tIndex の値を折角計算したのに上書きしていた…。修正した。動作確認した。 68385 68386 * 2017-09-20 今気づいたのだが実は現状で exit status の復元に失敗している? [#D0466] 68387 →やはりそうだ。またコードを確認する必要がある。 68388 68389 コードの編集に明らかに失敗している。 68390 そして確かめてみたところ $_ は同じ関数呼び出しレベルにおける最後の引数を指すようだ。 68391 ということは今まで通りに eval の中に設定する必要がある。 68392 68393 終了ステータスと最後の引数を同時に設定するためには 68394 ble-edit/exec/.setexit "$_ble_edit_exec_lastarg" とするしかない。 68395 と思って実際に試してみたところ $_ が常に /usr/bin/bash になってしまった。 68396 うーん。試してみたが関数だと /usr/bin/bash になってしまうということもないようだ。 68397 と思ったらそれまでに一度も引数ありでコマンドを実行していなかったために、 68398 最初の値の /usr/bin/bash が受け継がれて中に入っていただけだった。 68399 現状の実装でちゃんと復元はできている。 68400 68401 * 2017-09-19 bash -v で起動すると恐ろしいことになる。 [#D0465] 68402 68403 これは [[ -o verbose ]] で確認することができて、 68404 また set +v / set -v で切り替えられるはず。 68405 68406 必ずしもすべてのコマンドが出力されている訳ではない様だと思ったが、 68407 どうも eval ごとに実行したコマンドが出力されている気がする。 68408 68409 →取り敢えず対策した。[[ -o verbose ]] の状態を記録・復元することにした。 68410 それでも未だ色々と変な者が出力されている。 68411 もちろんこれらを完全に解決することは難しい。 68412 しかしながら、できるだけ出力内容が少なくするようにすることはできる。 68413 68414 そもそも何故 prologue, setexit, save-params, epilogue の 4 つに分かれていたのか。 68415 save-params と epilogue については理由はある。 68416 コマンド本体は文法がおかしい場合に後段の処理が潰れないように eval で囲む必要があった。 68417 しかしそうすると $_ が取れなくなってしまうので save-params だけは 68418 同じ eval の中で評価しなければならなかった (そうしないと eval に渡した引数が $_ に入ってしまう)。 68419 といってもコマンド本体に文法のおかしいものを指定したときに実行されなくなるのは困るので、 68420 重要なものに関しては eval の外に置かなければならない。 68421 68422 今一つの案は 68423 68424 1. prologue と setexit をくっつけ更に eval の中に移動する。 68425 (正しく実装している限りは prologue/setexit の中で失敗することはないと期待する) 68426 2. save-params の中で -o verbose の記録・無効化を実行し、 68427 もしそれに失敗したときのために念のため epilogue でも 68428 実行済みかチェックした上でこれを実行する。 68429 68430 修正した。現状では .save-params だけ余分に出力されている状態である。 68431 これに関してはこれ以上どうしようもないが名称を変えることはできる。 68432 68433 * .save-params 名称を変えることにする。どのような名称が良いか。 68434 68435 ble-edit/exec:gexec/ の部分は変えようがない。 68436 .save-params よりも何のために表示されているかが分かりやすい1つの単語が良い。 68437 うーん。考えるに現在の名前が的確である。これの存在意義は $_ を保存するということ1点のみにある。 68438 序でに $? も保存しているがこれは続く epilogue で改めて保存し直すのでおまけである。 68439 そう考えると .save-last-arg が的確な気がしてきた (readline 関数に yank-last-arg がある)。 68440 68441 →関数名は変更した。OK 68442 68443 * exec:exec の方でも動作しているか確認する。 68444 68445 確認した。実はそのままでも動いているようだ。 68446 関数内で実行しているのでそもそもそんなに出力の機会が多くはないようだ。 68447 68448 * 2017-09-22 vi-mode: bug: isearch から C-c などで戻ると選択状態がそのままになる。 [#D0464] 68449 68450 何らかの方法で選択状態を解除するようにした方が良いのでは。 68451 或いは、挿入モードのみで isearch をするのだとすれば、 68452 normal-mode など vi で追加した機能に対して 68453 全て選択状態をクリアするようにしても良い。 68454 68455 取り敢えずのところは normal mode に入る時に選択状態をクリアするようにし、 68456 また他に類似の修正が必要であれば修正する。 68457 68458 思うに今まで何故問題が起こらなかったのかというと、 68459 emacs の移動は全て marked/nomarked で登録していたからであった。 68460 vi-command は当然 nomarked を明示的に指定するということはしていないので、 68461 カーソル移動などをしても選択が解除されないのである。 68462 68463 vi/vim mode ではビジュアルモードまたは選択モードのみで 68464 選択状態になるという制限を設けると考えることにすれば良い。 68465 或いは、_ble_edit_mark_active の時を選択モード・ビジュアルモードと解釈することにする。 68466 68467 * 2017-09-15 cmplstofB: C-@ と accept-and-next に関する提案 [#D0463] 68468 68469 C-@ を accept-and-next にすることについて考察する。 68470 これは README.md あたりに書くということでも良いかもしれない。 68471 68472 →これは gh wiki に書いたのでよしということにする。 68473 68474 2017-09-22 68475 68476 * vi-mode: r gr で次の文字を待つまでは overwrite で色をつけても良いのでは。 [#D0462] 68477 68478 * 2017-09-11 vi-mode: text object: it, at [#D0461] 68479 68480 t について調べる。 68481 68482 どうやらちゃんとタグ名が一致するかどうかも見るようだ。 68483 また現在位置から左に < を検索して一番最初に当たったものについて、 68484 タグ名を読み取ろうとするようである。 68485 一番最初に当たったものが不正なタグで、 68486 それよりも前に正しいタグが合ったとしても失敗になる。 68487 タグの入れ子には対応している。 68488 68489 引数を指定すると 2 つ外側のタグに行く。 68490 68491 - 途中で不正なタグが存在する場合には、失敗する。 68492 目的地よりも外側に不正なタグが存在する場合には大丈夫。 68493 - 対応する終わりタグのないものは無視される 68494 (<br> などのためだろう。勿論、実際にはタグ名には関係ない)。 68495 - 途中に改行が入っていても問題ない。 68496 - <a> A <a> B <br> C </a> </a> </br> に対して、 68497 - <br> ... </br> は正しいタグということになる。 68498 - C の位置で 2yat とすると <a> B <br> C </a> になる。これは </br> がなくても同様 68499 - <br> の位置で 2yat とすると <a> B <br> C </a> になる。これは </br> がなくても同様 68500 このことから引数を指定したときに飛ばす始まりのタグに関しては、 68501 対応する終了タグがあるかどうかの確認を行わないということが分かる。 68502 - <a> A <b> </b> <c> </d> <p> </a> に対して、 68503 - A の位置で yat とすると全体を捕まえる。 68504 これにより同じ名称のタグしか数えていないということが分かる。 68505 - < a> hello </a> に対しては失敗する。 68506 つまりタグの形式は意外と厳密に調べられる。 68507 - <a href="<a"> helo </a> </a> を実行すると、 68508 中にある <a"> には決して引っかからない。 68509 <a href="<a"> helo </a> でひとまとまりであると認識される。 68510 href の位置にカーソルがある場合でも中の a の位置にカーソルがある場合でも同様である。 68511 エラーにもならない。 68512 68513 | - <check x=" 68514 | <a href="<a "> helo </a> </a> だと <a "> に引っかかる。 68515 | - <!--<check x=" --> 68516 | <a href="<a "> helo </a> </a> でも <a "> に引っかかる。 68517 | - <check x=" 68518 | <a href="<a"> helo </a> </a> だと <a"> には引っかからない。 68519 | - <a href="<a"> helo </a> </a> だと <a "> に引っかかる。 68520 68521 →初めは <check x=" に続く引用符の入れ子を考慮に入れているのかと思ったが、 68522 実は全然関係なくて <a" だと引っかからないが <a "> だと引っかかるということの様だ。 68523 68524 % 従って以下のような実装になるだろう。 68525 % 68526 % 1 引数の回数だけ繰り返し実行するようにする 68527 % 2 それぞれのステップでは先ず < を backward 検索する。 68528 % 次にその < のタグを読み取り、タグ名を取得する。 68529 % もし正しいタグならば続ける。 68530 % 3 2 を引数の回数分だけ見つけたらそれが始まり。 68531 % そこから forward に終わりタグを見つける。 68532 % 同じ名称のタグだけを数えて終わりタグを見つける。 68533 68534 - <a> < </a> 改めて。"<a> " の何れかにカーソルがある時は成功する。 68535 "< " の何れかにある場合は失敗する。"</a>" にある場合は成功する。 68536 - <a> <> </a> これの場合には何処にカーソルがあっても成功して全体に一致する。 68537 - <a> <b> <c> </c> </b> </a> hello 68538 " hello" の上で yat すると失敗する。 68539 "</a>" の上で yat すると成功する。 68540 "</a>" の上で 2yat すると失敗する。 68541 "</b>" の上で 2yat すると "<a> ... </a>" に一致する。 68542 68543 これから分かることは現在終わりタグの中にいる場合はそのタグに対応する始まりのタグを探すということ? 68544 更に、引数は始まりのタグを見つけてからそこから外側に向かって探索するということ。 68545 現在の < がタグとして成立していない時にはエラーになり、 68546 タグとして閉じてはいるが不正の場合は更に前の < を見つける? 68547 68548 - <a> <b> <b> </c> </b> </a> において "</b>" の上で yat すると何故か "<a> ... </a>" が選択される。 68549 - "</c>" の上で yat すると "<b> </c> </b>" が選択される。 68550 これは <a> <c> <b> </c> </b> </a> としても同じ。 68551 <a> <b> <c> </c> </b> </a> とすればさすがにどこでやっても期待する結果になる。 68552 68553 少なくとも正しいことは、タグ名は必ず対応するように取られるということ。 68554 どのタグが選ばれるのかという規則は不明。 68555 また <c> <b> </c> </b> で </c> にいるときに "<b> </c> </b>" にあたる事から、 68556 "終わりタグを先に確定させてからそれに対応する始まりのタグを見つける" という動作ではありえない。 68557 常に始まりのタグを先に確定させると考えなければならない。 68558 68559 % - なんと <a> <b> <b> <c> </b> </a> で "</b>" でやると 68560 % "<c> </b> </a>" が選択される。ついに異なるタグ名で一致する例が見つかってしまった。 68561 % と思ったら違った。次の行まで探索していって複数行で一致していたのだった。 68562 68563 これは vim のソースコードを見るしかない。 68564 さて git clone した。何処に対応するコードがあるだろうか。 68565 ファイルを眺めてみたら tag.c というまさにそれっぽいファイル名があった。 68566 と思ったら駄目だ。違う。これは関係ない tag だ。 68567 "text obj" で検索してみると以下の 2 行しかない。 68568 68569 ./normal.c:9023: /* in Visual mode and after an operator "a" and "i" are for text objects */ 68570 ./search.c:4501: * target text object. */ 68571 68572 前者を見ると nv_object という関数を呼んでいる。 68573 nv_object の関数の定義は normal.c:9185 に存在する。 68574 というか vim はキー操作がハードコーディングされているのか…。 68575 何れにしても normal.c:9236 で current_tagblock という関数を呼んでいる。 68576 current_tagblock は search.c:3908 に定義が存在する。 68577 https://github.com/vim/vim/blob/0263146b5dbbb6c120ce2e7720256503b864425d/src/search.c#L3828-L4111 68578 68579 実装を見るとたぶんこんな感じになっている: 68580 68581 1 後退して <.*> を探す。ただしそれよりあとに </.*> があることが条件。 68582 この時点ではタグ名が一致しているかどうかについては問わない。 68583 細かい動作は do_searchpair の中を見ないと分からない。 68584 これを count 回繰り返す。もし途中で見つからなくなったら失敗。 68585 68586 2 更にタグ名を読み取って (空なら失敗)、そのタグ名で do_searchpair を前進で実行し直す。 68587 これで終わりタグの位置を見つけることができる。 68588 見つかった組が現在地よりも前で終わっているときには更に後退する。 68589 恐らく do_seachpair は入れ子をカウントする仕組みになっているのだろう。 68590 68591 # ところで search.c:4033 の r < 1 は制御の流れ的に 68592 # 絶対に満たされない気がするが… 68593 68594 これにより今までの動作は大体説明がつくが以下の動作については不明 68595 68596 - <a> <b> <b> </c> </b> </a> の "</b>" で yat すると全体に一致する。 68597 →あー。これは初めに <a> の直後の <b> が見つかって、 68598 その後で終わりの対応する </b> が見つからずに後退したという動作だ。 68599 これは理解できる。 68600 68601 - <a> < </a> の "< " で yat → 失敗。"</a>" で成功する。 68602 68603 うーん。謎だ。<a><</a> でも同様に駄目だ。 68604 →これは以下の in_html_tag 関数に依る処理が犯人だった。 68605 68606 % タグの正規表現について調べる。うーん。謎。 68607 % これを見ても孤立した < で引っかかる要素がない気がする。 68608 % 68609 % <[^ \t>/!]\+\%(\_s\_[^>]\{-}[^/]>\|$\|\_s\=>\) 68610 % </[^>]*> 68611 % 68612 % vim の正規表現は以下にあった。 68613 % https://qiita.com/kawaz/items/d0708a4ab08e572f38f3 68614 % 68615 % うーん。ビルドして動かす? 68616 % ビルドして何処で失敗したかを調べると、一番最初の後退で失敗している。 68617 % つまり、正規表現で駄目…。分からない。 68618 % 68619 % その場で改めて do_searchpair を実行してみるとちゃんと一致する。 68620 % ということは何らかの理由で位置がずれているのか? 68621 % →curwin->w_cursor = old_pos; を直前に実行したら動いた。 68622 % ということは 1 で後退する前にカーソルの位置が調整されていることになる。 68623 % →初めに < の中にいる場合には > まで移動するようだ。 68624 % そうすると <a> < </a>★ の位置にまで移動する。 68625 % ここで yat を実行しようとすると外側にタグが必要になるので失敗する。 68626 68627 正規表現の問題ではなくて、最初にカーソルの位置を調整するというのの問題だった。 68628 in_html_tag 関数で判定が行われている。 68629 in_html_tag は現在位置の右が < か見て、或いは行内で <> を後退して探して判定する。 68630 つまり以下の手順を加えれば良い。 68631 68632 0 現在の位置の右に < があれば html タグ内にいるとする。 68633 現在位置から行内で後退して [<>] を探して < があれば html タグ内にいるとする。 68634 html タグ内にいるときはそれが開始タグならば前進して > の直前まで行き、 68635 終了タグならば後退して < の直前まで行く。 68636 開始タグかそうでないかは次の文字が / かどうかで判定する。 68637 68638 it の方の動作も調べる。 68639 - at のときと同じタグを捕まえる。 68640 終わりタグや始まりタグの上に載っていたとしても、 68641 その中身になる。つまり、初めのカーソルの位置を含まない形になりうる。 68642 - タグの内側にある空白・改行の類は削除されない。 68643 特に終わりタグの最後に改行があっても削除されないし、 68644 また改行が含まれていても linewise になることもない。 68645 68646 68647 [確認] 68648 68649 vim のソースコードを見て動作が分かったので実装した。 68650 正しいタグの場合の動作の確認は行った。引数も確認した。 68651 次に今まで試した色々のケースをチェックする必要がある。 68652 以下に試すべきことをまとめる。 68653 68654 以下 @ の位置にカーソルがあった時に yat をしたときの期待動作を示す。 68655 68656 1 @<@a@aa@>@hello@<@/@a@aa@> → 全部成功 68657 2 <a> @A <b> </b> <c> </d> <p> </a> → 全体 68658 3 < a> @hello </a> → 失敗 68659 4 <a href="<a"> @helo </a> </a> → 最初から一つ目の </a> 68660 5 <a>@ < @</a> → 成功 68661 6 <a> @<@ </a> → 失敗 68662 7 <a> <b> <b> </c> </@b> </a> → 全体 68663 8 <a> <b> <b> </@c> </b> </a> → 二つ目の <b> から </b> まで 68664 68665 早速 1 で引っかかった。一番初めの <aaa> の中で実行すると失敗する。 68666 →直した。開始タグの中にいるときに開始タグの終端に行く所、 68667 貪欲に全てのタグの終端に行っていた。 68668 68669 他は期待通りに動いている。OK 68670 68671 68672 2017-09-18 68673 68674 * cmplstofB: vim-surround.sh: $( \r ) $(( \r )) [#D0460] 68675 68676 * vim-surround: 実は ys の引数も / ./ の形式で指定できる。 [#D0459] 68677 68678 * cmplstofB: vim-surround.sh: ds cs [#D0458] 68679 68680 ds の振る舞いについて調べる → #D0456 68681 surround.vim と vim-surround.sh の実装の違いについてまとめる → #D0457 68682 68683 cs の振る舞いについて調べる。 68684 引数は / ?./ の形式である。 68685 後は ys の時と同じな気がする。 68686 取り敢えず実装した。 68687 68688 * vim-surround: ds 実装について surround.vim との違いについてまとめる [#D0457] 68689 68690 以下の項目がある。 68691 68692 * surround.vim には引用符に引数を指定した時のバグがある 68693 68694 | "A "B "C D" E" F" 68695 | ^ 68696 | 2ds" 68697 | 68698 | "A "B "C D" " F" E 68699 68700 | A "B "C" D" 68701 | ^ 68702 | 2ds" 68703 | 68704 | A C"B " 68705 68706 vim-surround.sh では引数は無視することにした。 68707 68708 * surround.vim には閉じ括弧が行頭にある時のバグがある。 68709 68710 | (A (B (C 68711 | ) E) F) 68712 | 68713 | C の上にカーソルを置く。ds( とする。 68714 | 68715 | (A C F) 68716 68717 このバグは以下で報告されているが取り込まれていない。 68718 68719 https://github.com/tpope/vim-surround/issues/232 68720 https://github.com/tpope/vim-surround/pull/217 68721 https://github.com/tpope/vim-surround/issues/215 68722 68723 vim-surround.sh ではちゃんと対応する括弧だけを削除する。 68724 68725 * surround.vim ds* では現在位置より前に * がないときにバグがある 68726 68727 | A *B* 68728 | ^ 68729 | ds* 68730 | 68731 | A 68732 68733 vim-surround.sh では ** 対の探索に失敗させる。 68734 68735 * surround.vim では /* だけがあるときに失敗するが、カーソル移動する 68736 68737 | /* hello 68738 | ^ 68739 | ds/ 68740 | 68741 | /* hello 68742 | ^ 68743 68744 カーソル移動しない方が自然なので、vim-surround.sh では移動しない。 68745 68746 * surround.vim では囲まれた部分が改行を含むときにインデントを行うが、 68747 vim-surround.sh では未対応である。その内に対応する予定。 68748 68749 * surround.vim では ** や () を ds* や ds) で削除できないが、 68750 vim-surround.sh では削除できる。 68751 68752 * surround.vim では /**/ においてカーソル位置が先頭にあると削除できないが、 68753 vim-surround.sh では削除できるようにする。 68754 68755 | /* a */ 68756 | ^ 68757 | 68758 | /* a */ 68759 | ^ 68760 | 68761 | surround.vim では ds/ で削除できない。 68762 68763 * vim-surround: ds [#D0456] 68764 68765 取り敢えず先に ds の動作を調べてそれを実装することにする。 68766 68767 当初行内での削除に限られるようだと思ったが、 68768 これは ds に続いて入力する囲みの種類に依存するようだ。 68769 68770 [引用符の時の動作について] 68771 68772 | 2ds" は謎。3ds" としても同じ動作に見える。 68773 | 1つ目の " を残して、そこから2つ目の " までを削除するようだ。 68774 | 具体的な動作について調べる。 68775 | 68776 | 前 68777 | 68778 | | "A "B "C★ D" E" F" 68779 | 68780 | ds" 後 (これはOK) 68781 | 68782 | | "A "B C D E" F" 68783 | 68784 | 2ds" / 3ds" / 4ds" 後 (謎) 68785 | 68786 | | "A "C D" F" 68787 | 68788 | 68789 | 前 68790 | 68791 | | "A "B "C D" E" ★F" 68792 | 68793 | 2ds" 後 (beep が鳴る) (謎) 68794 | 68795 | | "A "B "C D" " F" E 68796 | 68797 | →これは d2i" によって "...F" が削除された後に、 68798 | カーソルが E の手前に移動してしまって、そこで空白を挿入し、 68799 | 更に削除するべき引用符が見つからずに beep を鳴らして、 68800 | その後に改めて " F" が挿入されるということが起こった結果である。 68801 | 68802 | 前 68803 | 68804 | | ★A "B" 68805 | 68806 | ds" 後: これは理解できる。前方に見つけた " を先頭とする。 68807 | 68808 | | A B 68809 | 68810 | 前 68811 | 68812 | | ★A "B "C" D" 68813 | 68814 | 2ds" 後: これは理解できない。謎。そもそも順番が変わっている…。 68815 | 68816 | | A C"B " 68817 | 68818 | →これは surround.vim の中で 68819 | 以下のような手順によって発生している。 68820 | ★A "B "C" D" 68821 | (d2i") → A ★C" D" (clipboard = "B ") 68822 | (i \ed2i") → A C★ 68823 | (""p) → A C"B " 68824 | 68825 | よく分からない。これは surround.vim を読むしか無いのか。 68826 | 68827 | surround.vim を観察した結果、ds は dosurround を呼び出している。 68828 | cs も最終的には dosurround を呼び出しているが、 68829 | dosurround に対する引数の指定の仕方で cs と動作を変えている。 68830 | 68831 | さて、どうやら受け取った文字によって text-object または、 68832 | 独自の方法で範囲を計算・削除しているように見える。 68833 | " の場合には text-object i" を用いているようだ。 68834 | 恐らく 3ds" とすると、内部的には d3i" が呼び出されている。 68835 | 更に、その後で空白を一旦挿入して、それから再び da" を呼び出す。 68836 | 更に、その後で貼り付け p を行っている。 68837 | 何を貼り付けるのかの制御をどのようにしているのかは謎だが、 68838 | これは一番最初に切り取った内容をもとに戻しているということだろう。 68839 | 68840 | 結局 {count}ds" は exe 'norm! ""d'.count.'i"i \<Esc>d2i""p`[' に翻訳される。 68841 68842 引用符に関する振る舞いについては surround.vim の中を調べることによって解決した。 68843 68844 * Note: 問題は引数を指定している時には i" が a" と同じ動作になっていることにある気がする。 68845 →やはりそうだった。つまり、これは surround.vim のバグである気がする。 68846 これは報告したほうが良いのだろうか。 68847 68848 これについては GitHub vim-surround の Issue には登録されていなかったが、 68849 Issue に大量のものが報告されて5つもそれらが放置されているのを見ると報告しても仕方がないだろう。 68850 これについては放置することにする。 68851 68852 * done: 更にそれと共に現在の ble.sh の text-object で i" は引数を無視しているので修正したい→修正した。 68853 68854 * done: また、注記すべきこととして 3ds2" などの指定の方法も可能のようであるということ。 68855 この引数の読み取りは surround.vim において inputtarget() という関数で独自に実装されている。 68856 つまり共通の枠組みとしてそういうものがあるというわけではないので安心して新規実装できる。 68857 68858 68859 [括弧の動作について] 68860 68861 | 2ds) は二つ目の括弧と対応する括弧を削除する。 68862 | 68863 | と思ったら括弧の場合には同じ行内に見つからない場合には一番外側の括弧を削除する? 68864 | いや、何だか良くわからない。どうやら1つ目の () から 2つ目の () までを削除するようだ。 68865 | この場合は1つ目も 2つ目も削除してしまう。よく分からないので改めて試して整理していくことにする。 68866 | 68867 | 前 68868 | 68869 | | (A (B (★C 68870 | | D) E) F) 68871 | 68872 | ds( 後 68873 | 68874 | | (A (B C 68875 | | D E) F) 68876 | 68877 | 前 68878 | 68879 | | (A (B (★C 68880 | | ) E) F) 68881 | 68882 | ds( 後 → これは謎である。 68883 | 68884 | | (A C F) 68885 | 68886 | →これも分かった。 68887 | 68888 | (A (B (★C 68889 | ) E) F) 68890 | 68891 | (A (B ★( 68892 | ) E) F) 68893 | 68894 | (A (B★ ( 68895 | ) E) F) 68896 | 68897 | (A ★ F) 68898 | 68899 | どうやら ds( は以下に翻訳されるようだ。 68900 | 68901 | norm! ""di( 68902 | call search('\m.', 'bW') 68903 | norm! da(""p`[ 68904 | 68905 | ここで行末になった時に問題が生じる。 68906 | norm! ""ci(\<Esc> とすれば一文字戻る必要があるときにだけ戻るし良いのではないだろうか。 68907 | というかそもそも戻る必要はあったのだろうか? 68908 | 68909 | 68910 | 次に 3ds( とすると3階層目の括弧が削除されるものの、中身がインデントされる。 68911 | 68912 | 前 68913 | 68914 | | (A (B (C 68915 | | ) E) F) 68916 | 68917 | 3ds( 後 68918 | 68919 | | A (B (C 68920 | | ) E) F 68921 | 68922 | 前 68923 | 68924 | | (A (B (★C 68925 | | ) 68926 | | E) F) 68927 | 68928 | 3ds( 後 68929 | 68930 | | A (B (C 68931 | | ) 68932 | | E) F 68933 | 68934 | うーん。これはインデントの規則さえ分かればそんなにはおかしくはない気がする。 68935 | あと、明示的にインデントを調整している箇所があるのだろうか。うーん。 68936 | どうも surround.vim の中に call s:reindent() という行がある。これだろう。 68937 | 68938 | 68939 | 後実装を観察していて思ったのだが、行末にある括弧で ds( を実行するとずれる気がする。 68940 | 68941 | 前 | A(★B) 68942 | ds( 後 | AB 68943 | 68944 | あれ。正しい結果になっている。pP の切り替えによるものか。 68945 | よく考えたら p は後ろに挿入するもので、P が前に挿入するものだ。 68946 | なので p を使っている限りはこれは大丈夫。 68947 | 恐らく判定も大丈夫。念のため試す。 68948 | 68949 | 前 | (★A)B 68950 | ds( 後 | AB 68951 | 68952 | 正しい結果になっている。問題ない。 68953 68954 * done: 先ず yi( は囲む対象の末端が改行の場合はその改行は含まない。 68955 これは現在の ble.sh の振る舞いと異なる。修正が必要だ。 68956 これには対応した。 68957 68958 * note: 更に surround.vim は 1 文字戻るといって戻っているところが怪しい。 68959 これもバグなのだろうか。 68960 68961 報告しようと思って GitHub の vim-surround に行ったら、 68962 大量の Issue と PR が溜まっている。vim-surround は駄目だ。 68963 そして既に報告されていた。 68964 68965 https://github.com/tpope/vim-surround/issues/232 68966 https://github.com/tpope/vim-surround/pull/217 68967 https://github.com/tpope/vim-surround/issues/215 68968 68969 つまりこれはバグだと思って良いだろう。 68970 68971 * done: 文字が [ ( { < T の何れかのときには前後の空白を削除する。 68972 68973 * note: surround.vim では改行が絡むとき s:reindent を呼び出している。 68974 これにより括弧の階層によってインデントが付加される。 68975 これは 3== を実行した時と同じ結果になった。 68976 つまり = によるインデントを実装しておけばただそれを呼び出すだけである。 68977 68978 →これについては別項目で議論することにする。 68979 68980 更に以下の機能もある。これらは今既に実装した分のテストが 68981 終わってからにするのが良いだろう。 68982 68983 * done: / を指定すると /**/ を捕まえる。 68984 cs の第2引数に / を指定した場合は単に / で囲む。 68985 68986 * done: 他の文字を指定すると行内で検索する。引数は認識しないようだ。 68987 68988 [実装] 68989 68990 * done: 取り敢えず実装した部分 ds(text-object) の動作確認をする。 68991 68992 ds" を試したが動かない… → 直した。 68993 exclusive-range.impl の終了ステータスが問題だった。 68994 68995 2ds( は動いている。 68996 68997 ds( において空白がある場合に中身が消えてなくなる。 68998 → ble/string#trim の誤りだった。直した。 68999 69000 ds( と ds) の振る舞いの違いは正しく動いている。 69001 2ds( と 2ds) も動いている。 69002 69003 2ds" もちゃんと ds" と同じ動作になっている。 69004 2ds " と 2ds" の違いも動いている。 69005 69006 wW は何も変化が起こらない筈である → 宜しい。 69007 これは csw/ などでテストするべきである。 69008 69009 * done: / を指定した時の動作を実装する。 69010 69011 動作を調べると先ず、★/★**/ の ★の位置にいるときに ds/ としても効かない。 69012 また、それ以降の位置にいればいつでも効く。 69013 /**/ の外側にいても効くし、更に次の行にいても効く。 69014 恐らく現在位置以前の最近の /* を先ず初めに探して、 69015 その後で対応する */ を見つけるのだろう。 69016 69017 () との対称性を考えると先頭にいるときでも見つけられるようにして良いのではないか。 69018 69019 surround.vim では arg は最初の /* を見つけるときに ({arg}[/ として) 使っているようだ。 69020 ということは [/ の振る舞いを調べてから実装した方が良い。 69021 vimindex に載っている (vimindex の後方・前方は分かりにくい。forward/backward の訳と考えれば分かる)。 69022 これを見ると引数は N 個前の /* を見つけるという意味に解釈されるようだ。 69023 69024 [/ の振る舞いを調べてみると引数の数より少なくしか見つからない場合には、 69025 一番最後に見つかったものに一致するようだ。 69026 つまり現在の ble/string#last-index-of ではなくて正規表現を用いた実装にするべきである。 69027 69028 実装した。 69029 69030 * done: / の動作確認を実行する。 69031 69032 ds/ としてもエラーになる → 直した。古いコードが残っていた。 69033 しかし変な部分が消される → end の計算を修正した。2 足し忘れていた。 69034 2ds/ とすると期待通りに動く。2ds / の方も期待通りに動く。 69035 取り敢えず OK 69036 69037 * done: 次に行内の文字検索を実装する。 69038 先ず初めに backward search で文字を見つける。 69039 次に forward search で文字を見つける。 69040 69041 surround.vim は変な動作しかしないので模倣は諦めた。 69042 69043 取り敢えず実装した。 69044 69045 * done: ds* の動作確認をする。 69046 69047 *★* を ds* で消そうとしたが消せなかった。 69048 これは _ble_edit_ind+1 から last-index-of で検索しているために、 69049 2文字目の * を最初の文字と勘違いすることによって起こっている。 69050 先ず初めに現在のカーソル位置が開始に含まれているかどうかを確かめて、 69051 その後で _ble_edit_ind+1 から backward 検索するべきだ。 69052 69053 と思ったが問題はそういうことではない気がする。 69054 問題は +1 してしまうことによって図らずも終端の文字を拾ってしまう事にある。 69055 しかし何故そもそも +1 していたのかを考えると、 69056 現在位置が元から開始文字に含まれている場合を考慮してのことである。 69057 うーん。初めに現在位置が開始位置に含まれているかを確認し、 69058 そうでなければ +${#del} するというようにするのが正しい? 69059 69060 例えば del が3文字あるとする (現状の実装では1文字のはずだが汎用性を持たせるため) 69061 この時、調べなければならない範囲は現在位置より (3-1) = 2 文字手前の位置から、 69062 現在位置より 3 文字あとまでである。 69063 69064 うーん。本質は「現在位置より forward 方向に対しては index-of で、 69065 現在位置より backward 方向に対しては last-index-of」で検索するということだ。 69066 69067 | del="===" だとする。以下 ^ をカーソルの位置とする。 69068 | 69069 | ===== hello === ... この場合は色々な解釈方法が可能である。 69070 | ^ 69071 | ====== ... この場合は可能性としては "===" + "==="と解釈するしかない。 69072 | ^ できるだけ組を見つけられるようにするには ind-(${#del}-1) から検索するのが良い。 69073 69074 →対策した、と思ったら動かない。よく考えてみたら本質と違うことを考察していた。 69075 69076 問題は、現在開始文字の上にいるときではなくて、 69077 現在終了文字の上にいるときに起こるのであった。 69078 うーん。ということは base を ind - (${#del}-1) にするのではなくて、 69079 ind - (2*${#del} - 1) にすれば良いということなのだろうか。。 69080 うーん。色々曖昧性はあるけれどもその実装が妥当に思われる。 69081 69082 と思ったら、今度は *hello★* において ds* が使えなくなった。駄目だ。 69083 これの場合 * を開始位置と勘違いしている。本来は終端位置と捉えるべきである。 69084 69085 うーん。手順を逆転するべきだろうか。 69086 先ず初めに line::ind に対して検索を実行し、 69087 もし見つからなかったら、前方に検索を実行する。 69088 これを直したら、雰囲気動いている気がするので良いことにする。 69089 69090 * Note: 以下も surround.vim のバグである。 69091 69092 | というか以下のようになる。この動作はおかしい。 69093 | 前 | ★A *B* 69094 | ds* 後 | ★A 69095 69096 * Note: あと surround.vim は /* が孤立して存在するときに 69097 ds/ とすると / の位置にカーソルが移動してから失敗する。 69098 元の位置には戻らない。 69099 69100 * Note: surround.vim では ** の様な空の場合には認識されない。 69101 これは () で試しても同様だった。 69102 ble.sh の実装では () や ** も削除できることにしたい。 69103 69104 * done: surround.vim との動作の違いについて纏める。 69105 これは vim-suround.sh のコメント内に書けば良いだろう。 69106 69107 * cmplstofB: テキストオブジェクトに対する c の振る舞い [#D0455] 69108 69109 | テキストオブジェクトに対する c (削除後挿入モードに移行) が、 d と同じ振舞いになります。 69110 69111 本当だ…。何故だろう → vi_omap を追加したのに .insert-mode でそれが pop されていないのが問題だ。 69112 今までは adjust-command-mode でそれを調整していたが、.insert-mode を先に実行すると駄目なのだ。 69113 今回は対策として .insert-mode の中で vi_omap を pop するようにしたがこれが正しい解決法かは分からない。 69114 69115 本来であれば vi_omap に紐付けられたコマンドについては全て実行直前に vi_omap を pop するのが良さそうだが。 69116 但し __before_command__ で pop する訳には行かない。引数などの場合には pop しないからである。 69117 結局 adjust-command-mode を呼び出しているのと同じタイミングで vi_omap を pop する必要があるのである。 69118 しかし、現状では adjust-command-mode に先立って .insert-mode が呼び出されることがあり問題になった。 69119 69120 - 一般に keymap に関連するコマンドにおいてこのような不整合が生じる。 69121 取り敢えず keymap を push, pop しているところに関しては確認した。 69122 69123 - 更に ble-decode-key などで新たなキーを処理したりしている場合には、 69124 vi_omap を pop した上で ble-decode-key を呼び出す必要があるのではないかという気がする。 69125 そのような事をしているコマンドは現状では… __default__ と、vi-insert の中のコマンドのみである。 69126 今の所は問題がないが、実のところ将来的に不意に追加してしまう危険性もある。 69127 69128 うーん。原則を考える必要がある。先ず問題が発生するのは omap 周りだけである。 69129 omap に登録されているコマンドは 引数・motion・text-object・set-operator である。 69130 69131 - 引数の場合はそのまま透過して良い 69132 - motion の場合は基本的には最終的に adjust-command-mode する。 69133 但し、その前に c (.insert-mode) などを実行すると normal mode になってしまって駄目。 69134 - text-object は motion と同様である。 69135 ただ、これは omap にくっついているのでそんなに意識しなくても変な改変はしないと思う 69136 - set-operator 69137 これは既に vi_omap にいるのに更に vi_omap を積み重ねる危険性がある。 69138 実際には _ble_edit_arg の中身の状態が vi_omap と対応しているはずだから起こらないはずだが、 69139 何らかの拍子に変なことになるかもしれないということである。 69140 念のためチェックをしてから vi_omap を積み重ねるようにする。 69141 69142 2017-09-17 69143 69144 * vi-mode: imap C-k [#D0454] 69145 69146 ところで C-k は元々 (readline でも) kill-line だったところを digraph にしてしまってよかったのだろうか。 69147 そもそも digraph を使う機会なんてそんなになさそうだし、kill-line の方が便利なのではないだろうか。 69148 これはやはりマニュアルに記述して、実際には対応しないという方法のほうが良いのではないだろうか。 69149 69150 bash が C-k を kill-line にしているので、やはり C-k は kill-line であるべきだ。 69151 69152 * cmplstofB: f が失敗した時にも検索を記録する。 [#D0453] 69153 69154 更に提示された :help f を見ると digraph や Unicode 結合文字にも対応しているようだ。 69155 69156 | digraph には対応できるけれども、Unicode の結合文字についてはそもそも現状の ble.sh の枠組みで取り扱えていないので駄目。 69157 | さて digraph http://vim-jp.org/vimdoc-ja/digraph.html を参照すると普通のアルファベットの組で digraph が登録されている。 69158 | 更に :help r などを参照してみるとこれも digraph を受け取るようになっている。 69159 | :dig を参考に試しに rNU として見たが、N が入力されて "U" によって undo されてしまう。 69160 | 引数に指定する場合には digraph-arg というのを参照しなければならないということか。 69161 | と思ったら C-k に続いて入力しなければならないようだ。 69162 | 69163 | さて、digraph に対応するにはどうしたら良いか。 69164 | _ble_decode_key__hook だと問答無用で一文字だけ取ってしまうので駄目だ。 69165 | 或いは、_ble_decode_key__hook のチェーンを作って無理やり処理するか。 69166 | 69167 | それよりは cmap を登録した方が良い様な気もする。 69168 | しかし個別に登録すると大変である。 69169 | といっても結局はテーブルを作って処理することになるのだから、 69170 | 余り変わらないのかもしれない。 69171 | 69172 | 或いは新しい keymap を追加してしまうことにするか。 69173 | と思ったら、よく考えると :help f に lmap が効くと書かれている。 69174 | lmap と言っているのは lang-arg といっているもので、 69175 | もしかするとこれが一文字引数を受け取るための keymap なのではないだろうか。 69176 | 69177 | 更に vi_digraph のような感じの keymap を用意するのが良さそうだ。 69178 69179 先に digraph に対応してから考える。対応した。 69180 69181 fFtT については取り敢えず修正だけ先に行う。 69182 その後で digraph の対応について考える。 69183 当初は一文字読取るだけのために lmap なる keymap を作成する事を考えていたが、 69184 よく考えてみると C-k に対応するだけであれば 69185 別に fFtT 内で vi_digraph keymap に入れば良いだけのような気もする。 69186 69187 →結局 aread-char-arg という仕組みを整えて 69188 fFtT 及び r gr はこれを呼び出すことにした。 69189 現在のところ動作している。 69190 69191 * vi-mode: digraph 対応 [#D0452] 69192 69193 先に #D0453 で考察したように keymap を生成するのが良いだろう。 69194 69195 digraph の一覧は http://vim-jp.org/vimdoc-ja/digraph.html を wget して加工する。 69196 HTML 実体参照 ( <>") を戻して適当に列を切り出す。 69197 keymap/vi_digraph.txt に保存した。 69198 69199 vi_digraph の keymap は巨大なので vi.sh が更新される度に再生成するのは損である。 69200 という訳で vi_digraph.sh に分離して頻繁に更新しなくても良いようにする。 69201 通常文字にしか依存しないので [[ $fname_keymap_cache -nt $_ble_base/cmap/default.sh ]] 69202 のキャッシュ更新用のチェックも外して良いだろう。 69203 69204 * 2017-09-04 vi-mode: 全てのキー入力を横取りできているかどうかを確認する [#D0451] 69205 69206 → bind -p, bind -s, bind -X を見る限りは大丈夫に見える。 69207 69208 * 2017-09-11 vi-mode: by cmplstofB [#D0450] 69209 69210 | 複数行編集において、最初の行を削除した後に移動モードが機能しない。 69211 69212 これは分からない。再現しない。 69213 69214 2017-09-17 取り敢えず現在は再現しないということ。 69215 69216 | これは 1b9e2a4 において発生しませんでした。ありがとうございます。 69217 69218 本当に解決したのかどうかは謎だが、取り敢えずは解決したことにする。 69219 69220 2017-09-16 69221 69222 * dd の引数が効かなくなっている。 [#D0449] 69223 これは勘違いで追加した行が原因だった。 69224 69225 * vim-surround.sh において bBra は )}]> の aliases である。 [#D0448] 69226 69227 * vim-surround.sh について C-] / C-} に対応する。 [#D0447] 69228 69229 * cmplstofB: vi-mode ysiw" [#D0446] 69230 69231 | 更に ysiw" は体系としてかなり謎である。 69232 | と思って vim で試してみたら動かない。ys まで打った時点でエラーになる。 69233 | もしかしてビジュアルモードの機能なんだろうか。と思ったけれどそうでもないようだ。 69234 | 調べてみると surround.vim というのがあるようだ。拡張? 69235 | そうだとすると恐らく "ys" に対して直接 bind しているのだろうと理解できる。 69236 | - [surround.vimの使い方 | Memo on the Web](http://motw.mods.jp/Vim/surround.html) 69237 | - [What does the "y" stand for in "ysiw"? · Issue #128 · tpope/vim-surround](https://github.com/tpope/vim-surround/issues/128) 69238 | 69239 | でもそれをやると "yy" がその場で実行されなくなる。"yy" に対しても同時に bind することを考慮する必要がある。 69240 | が、もっと体系的なやりかたはないのだろうか。 69241 | →よく考えたら "y3y" などにも対応しなければならないので単に "yy" に bind するだけでは駄目だ。 69242 | 69243 | surround.vim を除けば i の直後には引数などが来る余地はないようなので (試した)、 69244 | 単に次のキーを一つ読み取るという具合にすれば良い。下手に keymap を追加すると 69245 | insert-mode で単に ble-decode/keymap/pop などとしているのがずれて問題になるので、 69246 | 下手に insert-mode を呼び出せない (もしくはその追加した keymap に追加する widget では必ず最初に pop をすれば良い?)。 69247 | 69248 | 取り敢えず入れてみた。結局日本語のページは古くて使い物にならなかった? 69249 | よく分からないので surround.vim 本家に書かれている方法でインストールした。 69250 | 69251 | | surround.vim インストール 69252 | | 69253 | | $ mkdir -p ~/.vim/autoload ~/.vim/bundle && curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim 69254 | | $ (cd ~/.vim/bundle && git clone https://github.com/tpope/vim-sensible.git) 69255 | | $ (cd ~/.vim/bundle && git clone git://github.com/tpope/vim-surround.git) 69256 | | 69257 | | ~/.vimrc に以下を追記 69258 | | 69259 | | execute pathogen#infect() 69260 | | filetype plugin indent on 69261 | | 69262 | | vim を起動して以下を実行 69263 | | 69264 | | :Helptags 69265 | | :help surround 69266 | 69267 | 試しに y3y としても問題は起こらない。ysiw" も動いている。 69268 | 更に y3ys でも y3y + s と解釈されているようだ。 69269 | どの様に処理しているのかは気になる。中を覗いてみる。 69270 | 69271 | nmap ys <Plug>Ysurround 69272 | 69273 | という所が怪しい。更に、Ysurround は以下の行にしか現れない。 69274 | 69275 | nnoremap <silent> <Plug>Ysurround :<C-U>set opfunc=<SID>opfunc<CR>g@ 69276 | nnoremap <silent> <Plug>YSurround :<C-U>set opfunc=<SID>opfunc2<CR>g@ 69277 | 69278 | どうやら opfunc=... となっているのでオペレータとして実装されている? 69279 | 更に s:opfunc, s:opfunc2 という関数が内部で実装されているので、これが本体だろう。 69280 | 69281 | しかしやはり ys から直接束縛している。そして問題は起こっていない。 69282 | これが意味するところは nmap に対する設定は、 69283 | オペレータが設定されている時の動作には影響を与えないという事である。 69284 | 69285 | 後気付いたことは引数を認識していない気がするという事。 69286 | 2ysiw" も ys2iw" も変わらなかった。 69287 | 更に y2s はエラーになったのでやはり "ys" の組で登録されているという事。 69288 | 69289 | うーん。調べると nmap (normal-mode map) と 69290 | omap (operator-pending mode map) という二種類のモードに対する map が存在して、 69291 | 更にそれぞれ独立に設定を行うことができるようだ。 69292 | 更に同時に設定ができるコマンドも用意されている。 69293 | 69294 | うーん。vi_omap を新しく導入することにするか。 69295 | 何が必要か。keymap を作ること自体はそんなに難しくはない。 69296 | さて問題なのは元の状態に戻るというのをどのように実装するかだ。 69297 | check-single-command に類似のものを更に用意しなければならないのか。 69298 | と思ったが、check-single-command に追加の実装をすれば良いだけの気もしてきた。 69299 | 69300 | 後、念のため現在のモードの表示については vi_omap も vi_command と同じ扱いにするという事。 69301 69302 [結論] vim には nmap の他に omap という独立した keymap が存在して、 69303 それぞれ独立に設定を行うことができる。ble.sh の実装でもこれにならう必要がある。 69304 69305 http://vim-jp.org/vimdoc-ja/map.html 69306 \_ map ... normal, visual, select, operator-pending 69307 | \_ nmap ... normal mode 69308 | \_ vmap ... visual/select mode 69309 | | \_ smap ... select mode 69310 | | \_ xmap ... visual mode 69311 | \_ omap ... operator-pending mode 69312 \_ lmap ... lang-arg, insert, commandline 69313 \_ map! ... insert, commandline 69314 \_ imap ... insert 69315 \_ cmap ... commandline 69316 69317 ys は nmap にだけ設定を行う。これにより yy などと矛盾しなくて済む。 69318 69319 [変更] 69320 69321 * done: 先ず初めに omap を追加する必要がある。 69322 69323 * cancel: 次に外部ファイルを読み込む仕組みを整える必要がある。 69324 或いは、取り敢えずは単に source "$_ble_base/lib/vim-surround.sh" を実行してもらうか。 69325 結局現状では ble-source または ble-import を実装するとしても $_ble_base/lib を前置するぐらいしかない。 69326 直接指定してもらうので問題ない気がする。 69327 69328 いよいよ ble-import などが必要になるのは複数のライブラリの間で依存関係が合って、 69329 更にそれぞれのライブラリを何処にインストールしているかを事前に決定できないときである。 69330 現状では全て $_ble_base/lib に放り込むので問題ない。 69331 69332 * done: 取り敢えず ys/yss だけ実装する。実装した。 69333 69334 2017-09-15 69335 69336 * vi-mode: operator: < > [#D0445] 69337 69338 オペレータの >< の動作について調べている。 69339 次の行の非空白行頭に行くときは前の行に範囲が縮まる。 69340 非空白行頭よりも後に行くときはその行も処理対象に含まれる。 69341 現在よりも前の行に移動するときはどうだろう。 69342 前の行の最後の文字に移動する時は、前の行も含まれる。 69343 現在の行は現在の行の行頭にいたときには対象にならない。 69344 現在の行の非空白行頭にいたときは対象になる。 69345 69346 < > で行頭の8空白はタブに変換される。 69347 また [空白][タブ] となっていると表示上はタブ一個と変わらない。 69348 この時に < > を実行するとはじめにあった空白は消える。 69349 つまり、最初に "表示" に従って全てタブに変換されてしまうようである。 69350 69351 * 2017-09-08 vi-mode: ~ [#D0444] 69352 69353 大文字小文字を変換する。ydc の引数には対応していない。 69354 また変更範囲に大文字と小文字が混在している場合には、 69355 それぞれの文字について大文字・小文字を反転する。 69356 同じ行内で移動する。 69357 69358 2017-09-15 要望が入った by cmplstofB 69359 69360 移動先は l と同じ扱いで良いのだろうか。試してみた限り同じように見える。 69361 但し一番右に行ってカーソルが動かなかったとしても bell は鳴らない。 69362 69363 * cmplstofB: iw aw の違い [#D0443] 69364 69365 これは対応したつもりで対応できていなかったと思ったが、 69366 改めて調べてみると aw の動作は思っていたよりもずっと複雑だった。 69367 69368 - 先ずカーソルの位置が空白の場合にはそれに続く単語の末端までを範囲とし、 69369 このとき単語に後続の空白は含まれない。引数が複数ある場合についても同様である。 69370 一番最後の単語に後続の空白は含まれない。先頭の空白には改行が含まれていても良い。 69371 69372 - 一方で、カーソルの位置が単語の内部にある場合には、 69373 一番最後の単語に後続の空白は含まれる。 69374 また後続の単語に改行は含まれない。 69375 69376 これに基いて正規表現を改定する。 69377 69378 2017-09-13 69379 69380 * ble-edit: 補完候補の表示で座標計算がずれる。 [#D0442] 69381 69382 info を通して表示しているはずだから、info 周りの座標系参加 ble-form#panel が悪い。 69383 これは書き換えのケアレスミスだった。 69384 69385 * ble-edit: info が表示されているとき一番下の行で、上の行に侵食する。 [#D0441] 69386 69387 ind の数が足りていないのではないかという疑惑がある。 69388 と思ったら set-height の方では ind していたけれども、 69389 set-height-and-clear の方では ind するのを忘れていた。追加した。 69390 69391 2017-09-12 69392 69393 * ble-edit/info が一番下の行で消える問題 [#D0440] 69394 69395 ターミナルの一番下にいる時に C-q C-j で本体の行数を高くした時に info が消える。 69396 これは、render/update が info の高さを認識していないということと、 69397 行数が変わった後に info を再描画していないことのどちらかまたは両方がいけない。 69398 69399 本来どのようにするべきかはもう少し考える必要がある。 69400 render/update は描画領域を確保するために IL してから NL を行数分発行する筈である。 69401 この時、 IL で一番下の行に表示されていた info は消滅する。 69402 行数が変化した時には info も再描画すべきなのだろうか。 69403 だとするとそもそも IL して表示を消さないようにしていた意味がなくなる。 69404 表示が消えないことを保証できないということなのだから。 69405 69406 うーん。現在のレイアウト (種類+行数のリスト) を管理するための仕組みを追加するほうが速いかもしれない。 69407 これは将来的なレイアウト管理への布石にもなる。取り敢えずファイルを追加してみるのが良い。 69408 69409 ble-form.sh を追加した。取り敢えずすこしずつ機能を移行していくことにすれば良い。 69410 先ずは高さに応じた領域を確保すること。 69411 69412 取り敢えず簡単に実装した。ble-edit.sh も大分すっきりしたような気がする。 69413 69414 * ble-edit: 新しく追加した関数の ble-edit/text/find-* という関数名は正しくない。 [#D0439] 69415 69416 今調べた所、従来の配置計算のための ble-edit/text/* という関数群は、 69417 _ble_edit_str とは独立に動作する物であった。 69418 つまり、他の文字列の配置計算にも転用できるようになっているのである。 69419 (ただ、その為にはどの変数に結果が格納されるかなどの情報をちゃんと調べて、 69420 それらの変数を対比する仕組みも作る必要があるが。) 69421 69422 従って、_ble_edit_str に対して様々な情報を取り出すための 69423 新しく追加した関数群には別の名前をつけるべきである。 69424 既存の関数を観察すると _ble_edit_str に対する操作は、以下の様になっている。 69425 69426 - _ble_edit_str.* 69427 - _ble_edit_str/* 69428 - ble/widget/* 69429 69430 今回の場合は特に公開する編集関数に直接に紐付いたものではないので、ble/widget/* は適当ではないだろう。 69431 一方で、_ble_edit_str.* のような関数名は他の関数との整合性が取りにくいので本当は廃止したい。 69432 しかしながらこれは大きな変更になると思われるから、取り敢えずはそのままが良いのではないか。 69433 というか、_ble_edit_str だけでなく _ble_edit_ind にも関わってくる関数の場合は、 69434 やはり _ble_edit_str.* は余り良くないのではないだろうか。 69435 69436 後でよりまともな関数名に変えるとしたらどのようなものになるかについては今此処で考えておく。 69437 比較のために既存の他のモジュールの名前も考慮する。 69438 69439 69440 | ble-edit/prompt : これは _ble_edit_PS1 を元にプロンプトを更新する仕組み。 69441 | 69442 | 内部状態の記録に使用している変数は恐らく以下のみである。 69443 | 69444 | _ble_edit_prompt=("" 0 0 0 32 0 "" "") 69445 | 69446 | 参照している変数は以下の通りである。更に、他にも様々なシェルの状態をを参照している。 69447 | 69448 | _ble_edit_PS1 69449 | _ble_edit_LINENO 69450 | _ble_edit_CMD 69451 | 69452 | 69453 | ble-edit/text : これは文字列の中の文字の配置情報を計算・キャッシュする仕組みである。 69454 | 外部から初期位置 (プロンプト末端の座標) と文字列を受け取って配置情報を計算する。 69455 | 内部状態の記録に指定している変数は以下の通り。 69456 | 69457 | _ble_line_text_cache_pos=() 69458 | _ble_line_text_cache_cs=() 69459 | _ble_line_text_cache_ichg=() 69460 | _ble_line_text_cache_length= 69461 | 69462 | 69463 | ble/widget : これは ble-decode の ble-bind から使うことを想定した関数群をいれておく場所である。 69464 | ユーザが自由にここに関数を追加して良い。但し、実際には更にshチアの階層を作って使うのが望ましい。 69465 | 69466 | _ble_edit_str : これは実際の編集文字列の管理をするところ。 69467 | 69468 | _ble_edit_str= 69469 | _ble_edit_ind=0 69470 | _ble_edit_mark=0 69471 | _ble_edit_mark_active= 69472 | _ble_edit_overwrite_mode= 69473 | _ble_edit_arg= 69474 | 69475 | _ble_edit_dirty_draw_beg=-1 69476 | _ble_edit_dirty_draw_end=-1 69477 | _ble_edit_dirty_draw_end0=-1 69478 | 69479 | _ble_edit_dirty_syntax_beg=0 69480 | _ble_edit_dirty_syntax_end=0 69481 | _ble_edit_dirty_syntax_end0=1 69482 | 69483 | _ble_edit_kill_ring= 69484 | _ble_edit_kill_type= 69485 | 69486 | _ble_edit_line_disabled= 69487 | 69488 | ble-edit/render : 編集文字列の表示にまつわる機能 69489 | 69490 | これは雑多な他の機能をまとめて描画を行っているところ。 69491 | 69492 | _ble_line_cur=(0 0 32 0) 69493 | _ble_line_x=0 _ble_line_y=0 69494 | _ble_line_begx=0 69495 | _ble_line_begy=0 69496 | _ble_line_endx=0 69497 | _ble_line_endy=0 69498 | _ble_edit_dirty=-1 -> _ble_line_dirty に改名 69499 | 69500 | _ble_edit_render_caret_state= 69501 | _ble_line_cache=() 69502 | 69503 | 69504 | ble-edit/info : 追加情報を表示するところ。 69505 | 69506 | これは更に ble-edit/render の管理外で、 69507 | ble-edit/render の表示内容の下に表示を行う。 69508 | 69509 | _ble_line_info=(0 0 "") 69510 | _ble_line_info_default=(0 0 "") 69511 | _ble_line_info_scene=default 69512 69513 どうも変数名は _ble_line_* と _ble_edit_* が混ざり合ってしまっているが、 69514 関数に関しては ble-edit に統一されているように見える。 69515 69516 うーん。ble-edit/content にするのが良いような気がしてきた。 69517 →変更した。 69518 69519 更に、ble-edit/text は ble-edit/layout にするのはどうだろうか。 69520 と思ったが、将来的には pane の配置も考えたいので、単に layout というのは余り好ましくない。 69521 しかしだからと言って ble-edit/text-layout というのも長い。 69522 更に ble-edit/text は配色情報のかんりもしているし、 69523 ble-highlight-layer の呼び出しも行っている。 69524 つまり、単にレイアウトというよりは文字列描画一般の機能を担っている。 69525 ble-edit/textbox だとか ble-edit/text-rendering だとかそういうのが適切だ。 69526 うーん。然し実際に描画をおこなっているのは ble-edit/render の方である。 69527 69528 うーん。色々考えると現在の構成は割りと現実的になっている。 69529 本来は以下のようになっているべきなのだ。 69530 69531 presentation : form 69532 \_ textarea : control 69533 | \_ content : ble-edit/content 69534 | \_ prompt : ble-edit/prompt 69535 | \_ layout : ble-edit/text 69536 | \_ render : ble-edit/layout 69537 \_ info : control 69538 69539 この話は別項目として切り離す事にした。 69540 69541 * ble-edit/info/default [#D0438] 69542 69543 実はその場で表示しなくても良いのではないだろうか。 69544 一回のコマンドの中で複数の書き換えがあった場合にちらつきが気になる。 69545 default は常に bind/.tail で更新するように修正することにした。 69546 69547 * vi-mode: operator ydc... 再編 [#D0437] 69548 69549 このページを見るとどうも ydc に対してどの様に動作するかというのはいくつかの種類があるようだ。 69550 69551 - linewise 69552 - characterwise inclusive 69553 - characterwise exclusive 69554 69555 "移動後に列1" のとき前の行の行末に移動する。 69556 69557 →これは w で試したが再現しないと思ったが、dw cw とやると確認できる。 69558 69559 "最初に first-non-space またはその直前にいて、移動後に同じ行の列1" のとき行単位になる。 69560 69561 →これは h で試してみても再現しない気がする。 69562 exclusive-linewise とマークされているコマンドだけという事か。 69563 69564 現在の実装を調べてみると inclusive/exclusive の区別がついていない。 69565 改めてどの様な振る舞いの違いが起こるべきかをマニュアルで見て、 69566 更にそれを実際に動かして見てそれから判断する必要がある。 69567 69568 どうも inclusive/exclusive の違いは ydc で処理する範囲の取り扱いのようである。 69569 exclusive だと終端の文字は対象ではなく (境界指向)、 69570 inclusive だと終端の文字も対象になる (文字指向)。 69571 殆どが exclusive であるが fx tx が inclusive である。 69572 vi.sh を読んでみたが対応していないように見える。と思ったら対応している様に見える。何故? 69573 と思ったら以下の行によって対応されているようだ。 69574 69575 [[ $flag ]] && ((index++)) 69576 69577 これで良い理由は以下の通り。 69578 69579 $flag がある場合には先頭に移動するか (y)、 69580 そもそも範囲内の文字列を削除 (c d) するので移動しなくても良い。 69581 なので index を弄ってしまっても問題ないのである。 69582 69583 では、新しいオペレータを追加してもこの方策で良いのかというのは疑問である。 69584 69585 - g~ gu gU g? → 先頭に移動する。 69586 - ! > < → これは行を丸ごと変更して先頭に移動する。 69587 - = も ! と同じと思われる。 69588 - zf も行単位である。但し複数行以上の場合でないと無効。 69589 - gq g@ は分からない。gq は行単位の疑いがある。 69590 - g@ は見ると行単位か文字単位か矩形単位かは文脈で変わる (恐らく y や g~ などと同じ)。 69591 69592 どうもこれで問題ない気がする。 69593 つまり inclusive のときは $flag が立っている時に終端を ++ する。 69594 69595 何れにしても現在の実装では operators の処理を個別に実装しすぎている。 69596 これらの実装を統合したい。 69597 69598 1 先ず inclusive-goto-char.impl を exclusive-goto-char.impl に対する補正として実装する。 69599 2 次に forward-eol の実装については inclusive-goto-char.impl に置き換えた。 69600 3 更に common-goto-line と .relative-line と .relative-first-non-space は実装が似る。 69601 これらを統合することを考える。 69602 69603 いきなり全体をくっつけることができるのかどうかは不明なので、 69604 取り敢えず $flag が立っている場合だけを統合することを考える。 69605 特に三者から呼び出すことのできる共通の関数を定義することが目標になる。 69606 69607 滅茶苦茶に書き換えたので改めて各コマンドについて動作確認する必要がある。 69608 チェックが必要なのは ^-+jkHLG である。 69609 それぞれについて ydc と組み合わせての確認も必要である。 69610 更に ftFTeE$ も inclusive の動作について確認が必要である。 69611 69612 確認事項 preserve_column require_multiline 69613 確認済み H L yH dH c2L 69614 確認済み j k yk dk ck yj dj cj 69615 確認済み + - y+ y- d+ c+ d- c- 69616 確認済み ^ $ d^ c^ y^ c$ d$ y$ 69617 確認済み e ce ye de 69618 確認済み fx yfx cfx dfx tx ytx 69619 69620 恐らく問題ないだろう。 69621 69622 2017-09-11 69623 69624 * ble-edit: stty sane をしなくて済む方法? [#D0436] 69625 69626 ble-edit/bind/.check-detach を見ていて思ったこと… 69627 もしかして stty sane はシグナルハンドラで実行すれば良いのではないだろうか。 69628 これは後で試してみる。 69629 69630 どうも試してみると stty sane を実行しなくても問題ないようになっている気がする。 69631 それよりも、readline が PS1 が空だと思っていることによる表示のずれがあるので、 69632 何でもいいからコマンドを一回実行する必要があった。 69633 stty sane はそれを実行させるための茶番の様だ (当初は意味もあったのだろうが)。 69634 69635 面倒だし ble-detach することも余りないだろうから、 69636 これはこのまま茶番として残しておく。 69637 69638 * clear-screen 直後に info が表示されない。 [#D0435] 69639 69640 直した。 69641 69642 * vi-mode: C-o の復帰位置 [#D0434] 69643 69644 現在のアルゴリズムは以下の通りである。 69645 69646 - コマンド実行直後の位置 (eol 補正される前の位置) で復帰する。 69647 69648 Note: p, P の "eol 補正" は挿入文字列の末端から最後の文字に移動するものである。 69649 69650 - C-o 時点での位置が行末であり、コマンド実行直後の位置が最後の文字のとき行末に移動する。 69651 69652 以下の動作は現在再現している。 69653 69654 - 同じ長さの行が並んでいるとき、$ i C-o k は最後の文字であり、A C-o k は行末である。 69655 - A C-o y l で行末に行く 69656 - 6文字の行で A C-o 6 | とすると行末に行く 69657 - A C-o r 8 で行末に行く 69658 69659 しかし以下の動作は再現していない。 69660 69661 - 空白だけの行で A C-o ^ とした時の位置は (行末ではなく) 最後の文字でなければならない。 69662 69663 Note: ^ は空白だけの行において最後の文字に移動する。 69664 69665 色々試すと first-non-space (^ + - や行単位の p P など) は例外のようである。 69666 取り敢えず個別規則ではあるが追加した。 69667 他にも何か vim との振る舞いの違いがまだあるのではないかと思われるが、 69668 それらは発覚してから対処するということにする。 69669 69670 * 初回起動時の INSERT がずれるようになった。何故? [#D0433] 69671 69672 ble/widget/vi-insert/.attach で呼び出すのは default ではなくて set-default であるべきだった様だ。 69673 69674 % 何故かは詳しく考えていないが、初期化と描画の順序の問題だろう。 69675 69676 ble-decode-attach より後に、プロンプトを表示する位置が確定する。 69677 先に info を描画してしまうと表示がずれることになる。初めは set-default で内容だけ指定しておいて、 69678 プロンプトの表示位置が確定した後に info も描画させるようにする必要がアアル。 69679 69680 * vi-mode: by cmplstofB [#D0432] 69681 69682 | ble.sh における vi-insert モードでの C-o は "accept-and-next" となっていますが、 69683 | vi/Vim の標準では「次に入力される「一回」のキー[^1]をノーマルモードに対する 69684 | キーとして解釈し実行した後、再び挿入モードに移る。 69685 69686 これはあとで実装する。 69687 69688 # C-o http://qiita.com/takasianpride/items/6900eebb7cde9fbb5298 69689 69690 動作を確認する。 69691 69692 - R や gR で C-o して戻るとどうなるのか。i と同じになる可能性はあるのか。 69693 試してみた所また元の R, gR の状態に戻る。 69694 表示もそれに応じて (replace) や (vreplace) になる。 69695 69696 - C-o した上で更に i, a などで挿入モードに入るとどうなるのか。 69697 どんどん入れ子で C-o できるのだろうか。 69698 試してみた所、R C-o i ESC l としても REPLACE に戻るということはなかった。 69699 つまり i, a などをすると C-o した効果は消える。 69700 69701 - 行末で C-o するとどうなるのか。 69702 A C-o y y としたら一時的にノーマルモードに戻っているときは 69703 行末から一つ戻った位置にカーソルが移動するが、終わるとまた行末に行くようだ。 69704 勿論いつでも元の位置に戻る訳ではなくて C-o のあとに移動コマンドを挟むと元の位置には戻らない。 69705 また $ i C-o y y としても行末には行かずに直前の位置に戻る。 69706 69707 % これは厄介な動作である。vim は内部的には "insert での位置" 69708 % と "normal での位置" を二重に管理している可能性がある。 69709 % だとすると現在の実装では色々と問題が残る。 69710 % 69711 % - うーん。A C-o y l をやっても行末に戻った。 69712 % 不思議だ。内部的には y l をした時点で yank した範囲の先頭に移動してもおかしくない。 69713 % 69714 % a 可能性1: 移動先が現在位置よりも前方にある時には、内部的な移動は起こらない。 69715 % b 可能性2: 実は内部的な位置というものは元から存在していなくて、 69716 % 単に C-o する直前の位置と直後の位置を記録しているのに過ぎないのかも知れない。 69717 % しかしそれは妙だ。編集によって行の中身が変わったときなどに困る。 69718 % 69719 % - 念のため A を使わずに $ i right C-o y l としても同じだった。 69720 % 69721 % - 次に "echo 6" という内の行で A C-o 6 | としてみた。 69722 % 何と修了後に行末 (位置 7) に移動した。 69723 % 69724 % ここから結論付けられることは、内部的な位置というのは実は存在していなくて、 69725 % やはり C-o した時の位置を記録していて、 69726 % 位置が変わっていなければ元に戻すということのようである。 69727 % 69728 % さて、では行の内容が変わっている場合にはどうなのであろうか。 69729 % 69730 % - A C-o r 8 としたがやはり行末に戻った。位置しか見ていない? 69731 % 69732 % では行の長さが変わっているときにはどうなるのだろうか。 69733 % しかし位置を変えずに行の長さを変えるコマンドが思い浮かばない。 69734 % y l で一文字だけ貼り付けになるとき P をすれば位置が変わらずに行の長さが変わるのではないか。 69735 % 69736 % - 0 y l A C-o P を試してみた所それでも行末に移動した。これは不思議だ 69737 % 69738 % - 同じ長さの行が並んでいるところで A C-o k としたところ上の行の行末に移動した。 69739 % $ i C-o k としても行末には移動しない。 69740 % 69741 % つまり位置を記録しているのではなくて C-o した時点で行末にいたかどうかを記録し、 69742 % C-o から抜けた時点で行末の一つ手前にいる場合に復元するという方針なのではないか。 69743 % 69744 % と思ったが P で行の長さを変えた実験からそれはおかしい。 69745 % やはり内部的な位置を二重に管理していて k を実行する時には両方移動しているのだろうか。 69746 % しかしそれは | の実験と矛盾する。或いは、| で 6 | とした時は実際の位置が変わらないということで、 69747 % 実際の処理としては無視されたことになっているという可能性もある。 69748 69749 % うーん。P の動作はそもそも不自然な気がするし、 69750 % 取り敢えず "行末にいたかどうか記録" 方式でいい気がする。 69751 % P の件に関しては別個に質問することにする 69752 % 69753 % - というかそもそも I C-o P としても次の文字に行くようだ。 69754 % 69755 % - 0 4 y l I C-o p でも同じように "貼り付けた内容の最後の文字" ではなく、 69756 % "更にその次の文字" の位置で INSERT に復帰するようだ。 69757 % 69758 % つまり p, P は内部的には一旦貼り付けた内容の末端に位置が移動して、 69759 % しかしノーマルモードに移る際に一つ戻るという動作をしているということに思われる。 69760 69761 % "行末にいたかどうか記録" という仮説が合っているのか確かめる。 69762 % 69763 % - 以下の内容で、文字 2 の位置にいる時に i C-o k としたら行末に移動した。 69764 % 69765 % echo 1 69766 % echo 12 69767 % 69768 % % つまり "行末にいたかどうかを記録" という仮説は間違っている。 69769 % これは勘違い。行末にいたかどうかが効くのはコマンド実行後に行末直前にいたときのみ。 69770 % コマンド実行後に行末にいた場合はそのまま行末になる。 69771 % 69772 % 代わりの仮説として "各コマンドを実行した直後の位置" というのが実はあって、 69773 % ノーマルモードにいるときには更にその位置から補正が起こるというものを立てる。 69774 % 69775 % しかしこれによると A C-o y l で行末に移動するというのは、 69776 % y l を実行した直後の位置が行末にあるということを示唆するが、 69777 % 複数文字の y l の動作からすると変だ。念のため複数文字の y l を試す。 69778 % 69779 % - $ h i C-o y 2 l → 別に行末に移動するということはない。 69780 69781 [結論] つまり、以下の通り。 69782 69783 - C-o をした時点で行末にいたかどうかを記録する。 69784 コマンドを実行直後 (行末補正前) に行末にいた場合は、そのまま行末に行く。 69785 行末直前にいた場合は、"C-o をした時に行末にいた" 場合に行末に補正する。 69786 それ以外の場合にはそのままの位置に行く。 69787 69788 - p, P の "直後の位置" は貼り付け範囲の末端である。 69789 ノーマルモードではその後で最後の文字に補正される。 69790 69791 - R C-o から抜けるのに c を使うとどうなるか? 69792 ただの INSERT になった。つまり i や a と同じ。 69793 69794 - d 3 l で行末まで丁度全ての文字を消すと復帰した時の位置はどうなるか? 69795 行末になった。つまり c を使うのと同様である。 69796 但し c と違って R C-o d 3 l としたらちゃんと REPLACE に戻る。 69797 69798 - I C-o back は前の行の行末に移動する 69799 - I C-o 2 r x は 2 文字目に移動する。 69800 - 空白だけの行において I C-o ^ は行末ではなくて最後の文字に移動する。 69801 これは I c ^ としても分かる。最後の空白が残る。 69802 +, - も同様。つまり ^ + - は行末には一時的にも移動しない。 69803 - 一方で I C-o $ は行末に移動する。 69804 - 6文字の行において c 7 | は最後の文字を削除しない。つまり | は行末には一時的にも移動しない。 69805 69806 69807 実装した。しかし微妙に振る舞いが異なる。 69808 69809 - 空白だけの行において A C-o ^ とすると vim では最後の文字に行く。 69810 変だ。今までの実験では最後の文字にいる時には修正されるはずだったのではないのか。 69811 69812 うーん。面倒だ。これは別の問題として残すことにする。 69813 69814 > * p の動作が正しくない気がする。 → 条件が反転していた。直した。 69815 > * あとカーソルの位置がおかしい。 → 条件を修正するべきところ eol 補正を完全に削除していた。直した。 69816 69817 * 2017-09-05 vi-mode: gR? [#D0431] 69818 69819 http://qiita.com/sfuta/items/0de4ead865c15e9e9b68 69820 69821 overwrite mode には R/gR の区別があるようだ。 69822 さて overwrite mode まで来ると複雑である。 69823 特に self-insert が複雑になる。 69824 これは再実装すると面倒なので何らかの変数を用いて vi/emacs を内部で 69825 判定して動作を微妙に変えるという様にするのが良いのではないだろうか。 69826 ところで self-insert に関しては emacs/vi で動作の違いはあっただろうか? 69827 69828 実際に vim で試してみると gR と押しても何も起こらないどういうことか? 69829 69830 これは vi ではなく vim で起動しなければならなかったという話だった。 69831 69832 69833 * 2017-09-09 テストユーザ (vim) に説明すること [#D0430] 69834 69835 - 編集文字列内に改行 LF が含まれないとき単一行編集と呼び、あるとき複数行編集と呼ぶことにする。 69836 単一行編集のとき LF を挿入して複数行編集に移るには C-v C-j (または端末のフロー制御を無効にしていれば C-q C-j でもよい) とすれば良い。 69837 複数行編集のとき RET (C-m) はコマンド実行ではなく改行挿入になる (ノーマルモードでは次の非空白行頭に移動になる)。 69838 この時コマンドの実行は RET (C-m) ではなく C-j で行う。 69839 複数行編集では端末の表示行数よりも多くの行を含むコマンド編集は想定していない。 69840 69841 実装の仕様(または妥協点・疑問点) 69842 69843 - gr が vim で動かないこと。gR が動かないこと 69844 - H L が現在の履歴項目内の移動で、G gg が履歴内の移動であること。 69845 - jk+- で現在の履歴項目の上下を踏み越えると次の履歴項目に移動すること。 69846 69847 * vi-mode: vi.sh から keymap/isearch を使っているが [#D0429] 69848 keymap/isearch は emacs.sh の中で定義されている。 69849 どうやら現状では .inputrc で vi が設定されていたとしても、 69850 ble.sh をロードした段階では -o emacs であり、 69851 後で -o vi になる様である。 69852 69853 % どうも .bashrc の中では殆ど -o emacs のようである。 69854 % ところが何処かの時点で -o vi に変わる様である。 69855 % 調べてみると ble-decode-attach の 69856 % eval -- "$(ble-decode-bind/.generate-source-to-unbind-default)" で結果が変わっている。 69857 % つまり初回の bind 実行で変化しているように思われる。 69858 % 試してみるとどうやら単に "bind" としただけでも readline が呼び出されるようである。 69859 % なので -o emacs/vi を最初にチェックする前に bind を実行すれば良い。 69860 % # さて、不思議なのはこの仕様の場合、ble.pp の最初のチェックをすり抜けるのではないかということ…。 69861 % # やはりすり抜けていた。このチェックの時点で readline をロードすれば良いだろう。 69862 69863 [結論] 最初に -o emacs/vi を参照する前に "bind &>/dev/null" を実行すれば良い。 69864 69865 さて、この時 keymap/isearch はどうなるだろうか。 69866 調べてみた所、何も操作できない状態になった。 69867 69868 二つの変更を加える必要がある。 69869 69870 1. 先ず初めに isearch.sh を分離するということ。 69871 それでも、キャッシュが複数に分かれるのは得策でないので 69872 キャッシュは emacs.sh, vi.sh で出力するようにする。 69873 69874 2. 次に ble-decode/keymap/push する時に keymap の存在をチェックするということ。 69875 もし keymap が存在しない場合にはそのキーマップに移行するべきではない。 69876 keymap の存在判定で色々手間取ったがなんとかできた。 69877 69878 2017-09-10 69879 69880 * 2017-09-07 vi-mode: C-c ESC C-| の違い。 [#D0428] 69881 69882 http://d.hatena.ne.jp/yuta84q/20101216/1292508997 69883 69884 引数を保存して繰り返し適用する? しかし途中で変な操作があると難しい。 69885 69886 % どうも途中で矢印で移動すると無効になるようである。 69887 % backspace で内容を削除する場合には問題は起こらない。 69888 % つまり許容できる操作に制限があるということだろう。 69889 % そして制限された動作を用いている限りにおいては、 69890 % 編集によって追加された文字列は、 69891 % 編集開始点から編集終了点までということが保証される。 69892 % 69893 % もう少し調べてみる。backspace の場合には引数は無効にならない。 69894 % では元々あった文字数よりも少なくなった場合にはどうするのか。 69895 % →どうやら backspace が繰り返し実行されるようである。 69896 % 更にこの backspace は (挿入モードの性質として) 行を跨って実行されるようだ。 69897 % 69898 % さて、backspace 以外の削除するコマンド (例えば前の単語を削除するコマンド) を実行した時にどうなるかは気になる。 69899 % 単語単位で削除した回数を覚えておいて引数の数だけ掛け算してそれを適用するのか、 69900 % 或いは減少した文字数だけを覚えておいて引数の数だけ掛け算したぶんだけ更に文字数を減少させるのか。 69901 % 実装としては文字数を記録するだけの方が自然である。行った操作の履歴を保持するのは大変である。 69902 % と思ったが、よく考えてみたらそもそも挿入モードで単語単位で削除するような操作があったのかどうか怪しい。 69903 % 69904 % そう思って vimindex を眺めてみたら C-w でそれを行うことができる様である。 69905 % 実際に試してみた所、ちゃんと C-w を行ったのだということを覚えているようだ。 69906 % ということはどの様な編集を行ったのかという履歴を残すということになる。 69907 % 寧ろマクロの一種と考えるほうが良いということである。 69908 % さて、ということであればこの機能に対応するならば先にキーボードマクロに対応する方が先である。 69909 69910 どうも途中で行った操作を全て記録しているようである。 69911 また、矢印などで移動をしたりするとキャンセルされる。 69912 69913 これはキーボードマクロの仕組みを整えてから対応した方が良い。 69914 69915 →より汎用的に ble-decode.sh を拡張するとしたら、__defchar__ や __default__ の様に、 69916 keymap に __before_command__ のような特殊バインディングを用意するのが良い気がする。 69917 そしてキーボードマクロその他の仕組を整えるのに利用できるようにする。 69918 69919 しかしよく考えたら単にキーボードマクロとする場合、 69920 その時の背景の変数の状態などを記録しなくても良いのだろうか。 69921 というのもノーマルモードでキーボードマクロを記録している時にどのように処理されるのかが気になる。 69922 ノーマルモードの __before_command__ でキーボードマクロを記録しているときに 69923 挿入モードに入ると、その間記録がされないことになってしまう。それはおかしい。 69924 つまり、今回追加した仕組みは実はキーボードマクロの仕組みには使用できない。 69925 キーボードマクロにしたければ実は keymap に依存しない hook を取り付ける仕組みを追加するべきだ。 69926 更に入れ子になっている場合なども考えれば複数取り付けられるようにするべきかもしれない。 69927 何れにしてもキーボードマクロは今回の仕組みとは独立に用意しなければならない。 69928 この事はキーボードマクロの計画の方に追記しておくことにする。 69929 69930 * vi-mode: C-home C-end は現在の編集文字列内の移動としても良いかもしれない。 [#D0427] 69931 69932 2017-09-09 69933 69934 * vi-mode: f F t T ; , [#D0426] 69935 69936 bash の動作を確認してみると同じ履歴項目の中だけを検索するようである。 69937 vim で試してみる。同じ行内でしか一致しない。 69938 現在位置にある文字には一致しない。 69939 t T では一つ先の文字に一致するので何回も一致する。 69940 69941 ycd は効く。f t は終端までを範囲とするのが他と少し異なる。 69942 つまり空一致は存在し得ない。 69943 引数を指定すると n 個目の文字に移動できる。 69944 n 個目がない場合には何もせずに bell である。 69945 69946 * ble-edit: 下キーなど履歴項目を移動するもの全般に… [#D0425] 69947 現在一番下の行にいるということが分かっているのであれば、 69948 下に行こうとした時に history/load する必要はないのではないだろうか。 69949 69950 * ble-edit, ble-decode: declare で宣言しているグローバル変数は [#D0424] 69951 69952 何も指定せずにただ代入するべきなのではないか。 69953 なぜならば関数内から source などした時にローカル変数になってしまうので。 69954 69955 定数として宣言するために declare -ir しているものもあるが、 69956 これらは結局 ble.sh を複数回ロードしたときのために定義されているかどうかを確認してから 69957 declare -ir するのなどの面倒な処理の原因になっている。 69958 やはり勝手に書き換える人が悪いという事にして、declare -ir は除くのが良いだろう。 69959 69960 問題になるのは declare -A である。declare を使わずして配列が連想配列であることを指定する方法はない。 69961 bash-4.2 移行であれば declare -gA で解決するが bash-4.0, 4.1 ではそれができない。 69962 bash-4.0, 4.1 では bash-3.* 用の declare -a を用いる fallback を使うという手もあるが、速度が遅くなってしまう。 69963 実のところ、関数内からロードするという事は現在考えていないし、 69964 また 4.0, 4.1 はまだまだ現役だと思われるので速度を重視したほうが良い気がする。 69965 という訳で今の所は 4.0, 4.1 に関しては関数内からロードする時に問題になるとしても取り敢えず放置することにする。 69966 69967 或いは現在関数内からロードしているかどうかを判定して、 69968 declare -A を行うかどうかを切り替えるという手もある。 69969 どうも関数内にいるかどうかは ${FUNCNAME+set} で判定できるように思う。 69970 但し FUNCNAME がユーザにより勝手に unset されていないことが前提である。 69971 従って、関数内にいてかつ bash-4.2 未満の場合には配列実装に fallback すれば良い。 69972 69973 * 確認: 関数内から source したとき source されたスクリプトの中からそれを判定できるのだろうか? 69974 69975 もしかすると source した時点で関数でないという様に解釈されて 69976 FUNCNAME が見えないという可能性も否定できない。 69977 69978 以下のようなファイルを用意しておいて、 69979 69980 ```bash:a.bash_source 69981 # bash_source 69982 69983 if [[ ${FUNCNAME+set} ]]; then 69984 echo 'source from a function' 69985 else 69986 echo 'source from out of functions' 69987 fi 69988 ``` 69989 69990 bashrc から呼び出して正しく判定できるか確認する。 69991 69992 ```bash:~/.bashrc 69993 function atest1() { source ~/prog/ble/a.bash_source; } 69994 atest1 69995 69996 source ~/prog/ble/a.bash_source 69997 ``` 69998 69999 どうやら正しく判定できる様だ。 70000 70001 * 確認: 既に同様の仕組みによって ble.sh を関数内からロードしている場合に警告を発したりしていないか。 70002 もしそうであればわざわざ関数内からロードした時について対応するのは無駄である。 70003 少なくとも FUNCNAME で検索した限りにおいてはそのような判定は行っていないようである。 70004 70005 というより実際に関数内からロードしてみれば確認は済む。 70006 試してみた所ロードできた。動作している。 70007 70008 * vi-mode: J gJ o O [#D0423] 70009 70010 J は行末に LF がある場合にはそれを SP に変える。 70011 それ以外の場合には bell を鳴らして移動もしない。 70012 gJ は SP に変えるのではなくて単に削除する。 70013 70014 o は行末に改行を挿入して挿入モードに入る。 70015 O は行頭に改行を挿入して挿入モードに入る。 70016 o O は共に新しい行の先頭にカーソルをおく。 70017 70018 これらの J gJ o O のコマンドは何れも、 70019 引数に ydc が含まれる場合は bell で、 70020 引数の数字は単に無視されるように思われる。 70021 →o O に関しては挿入モードを抜けるときの繰り返し回数を指定するようだ。 70022 70023 * そろそろ leak variables を再度チェックする。 [#D0422] 70024 70025 ble-syntax.sh で rex がリークしていた。 70026 単にロードしただけでは他にリークは見つかっていない。 70027 70028 本来はもっと長時間使用した後で leak を確かめるべきである。 70029 という訳で ble を編集しているシェルで試してみた。 70030 他に complete.sh で compgen がリークしていた。直した。 70031 70032 * vi-mode: r [#D0421] 70033 70034 f や F でも同じことであるが、引数をどのように受け取るかが問題である。 70035 70036 % quoted-insert の場合には ble-decode に特別な項目を設定して処理した。 70037 % 同じ仕組みを採用しようとするとキー入力ではなくて生の文字を受け取ることになる。 70038 % 一方で rx fx Fx などでは通常の文字を引数に取ることを想定するので生の文字を受け取る必要はない。 70039 % 寧ろ変な操作を検出するために生の文字ではなくて生のキーコードを受け取るようにしたい。 70040 % そのためには ble-decode に同様の仕組みとして生のキーコードを受け取るようにすると良いだろうか。 70041 % しかしよく考えてみるとそれ専用の keymap を定義することができるのだから ble-decode を弄る程でもない気がする。 70042 % 70043 % 念のため quoted-insert の利用している ble-decode の機能について確認し、 70044 % どちらの実装にするほうがきれいになるかを判定してから処理するようにする。 70045 % quoted-insert では _ble_decode_char__hook=ble/widget/quoted-insert/.hook を設定し、 70046 % ble-decode にこの .hook 関数を呼ばせている。 70047 % 更によく見ると既に ble-decode に _ble_decode_key__hook という変数が用意されている。 70048 % 因みに誰も使っていない。 70049 % 70050 % さて既にその仕組が整っているのだとしたら、_ble_decode_key__hook を利用したほうが簡潔なのではないだろうか。 70051 % keymap を自前で定義するにしてもコマンド毎に定義するのは変だし、 70052 % だからと言って一つ keymap を用意して _ble_keymap_vi_hook などの変数に操作を記録するという方式にすると、 70053 % 既にこれは汎用の _ble_decode_key__hook と同様な仕組みになってしまっている。 70054 % もしそうだとしたら _ble_decode_key__hook の方が keymap を通さないだけ素直な実装になっているので良い。 70055 70056 [結論] これには既存の _ble_decode_key__hook の仕組みを利用すれば良い。 70057 70058 実際の実装では overwrite をするのでその仕組を既に持っている self-insert を用いる。 70059 但し、2つの点において self-insert を改修しなければならない。 70060 70061 - 先ず 1 つ目に引数を用いて繰り返し self-insert を行うということ。 70062 効率の面から言って一気に複数文字を挿入するようにした方が良い。 70063 また、emacs 用の .get-arg を用意する必要があるのでは。 70064 70065 - 次に overwrite する時に表示幅で overwrite するのか、論理列数で overwrite するのかということ。 70066 これは r gr で異なるので両方に対応しなければならない。 70067 これは _ble_edit_overwrite_mode=R というのに対応する必要がある。 70068 先ずはどこで _ble_edit_overwrite_mode が使われているかを調べる。 70069 70070 変更を実施する。 70071 70072 * self-insert の実装をいじっていて思ったこと。 70073 delta の実装はこれで良いのか。 70074 delta は変更範囲より後ろにある _ble_edit_mark の位置を更新するのに使っている。 70075 しかし _ble_edit_str.replace で _ble_edit_mark は更新されないのだろうか。 70076 70077 →今確認してみた所 _ble_edit_mark だけでなく _ble_edit_ind も更新しないようだ。 70078 これは _ble_edit_str.replace を呼び出した後で結局再び _ble_edit_{ind,mark} を移動するなどの場合があって、 70079 そのような時に無駄な計算をしないための効率によるものと思う。 70080 70081 つまり、呼び出し元で両者とも管理しなければならない。 70082 70083 * さて、現在の self-insert の delta はどのようなものになっているだろうか。 70084 特に全角文字を空白文字で置き換えた時に delta を 1 だけ増やすのは何故だろうか。 70085 repw-w でないのには理由があるのか、それとも単なるミスだろうか。 70086 (或いは全角文字は幅 2 という仮定があればこれで問題ないが、 70087 それだとわざわざ挿入する空白の数を repw-w と計算している理由がわからない。) 70088 70089 更によく見てみるとこれは実際に使用するところで 70090 delta=${#ins}-(iend-ibeg) として計算すれば良いだけの気がする。 70091 今まで delta を別に計算していたのはそちらの方が速いと判断からなのだろう。 70092 しかし現状の実装ではむしろ複雑になっている気がするので、 70093 delta の値はその場で計算することにして delta 自身は廃止することにする。 70094 70095 一応テストする。挿入・上書きのそれぞれで全角・半角を書くのを試した。 70096 全角半角で半角・全角を上書きするのも試した。問題ない。OK 70097 70098 * _ble_edit_overwrite_mode=R には対応した。 70099 70100 * その他の _ble_edit_overwrite_mode を参照している箇所は、 70101 70102 overwrite mode の設定、caret_state の保存・復元、表示時の着色を除けば 70103 ble/widget/.delete-backward-char のみである。 70104 これについては _ble_edit_overwrite_mode=R に対応した。 70105 (引数には対応していない。引数は今後少しずつ対応していく予定である。 70106 というかそもそも keymap emacs では引数を導入できない。) 70107 70108 * r gr した後のカーソルの位置が異なる→直した。 70109 70110 * r gr ではその行内に既に足るだけの文字数がない時 bell である。 70111 70112 * vim で試すと gr は必ず bell になる。 70113 何か使い方が間違っているのだろうか。 70114 これは vim ユーザを見つけて相談するべきである。 70115 取り敢えず有効にしておくことにする。 70116 70117 70118 2017-09-08 70119 70120 * vi-mode: G H L gg [#D0420] 70121 70122 元々の vim では H L は現在画面に写っている範囲での移動である。 70123 また G は全体の行番号を指定して移動するものである。 70124 引数を省略した場合には一番最後の行に移動する。 70125 gg は引数省略時に一番最初の行に移動することの他は G と同じ。 70126 何れも非空白行頭に移動する。 70127 70128 ble.sh の実装では H L は現在の履歴項目の中での移動とし、 70129 G/gg は履歴の番号を指定した移動とするのが良さそうである。 70130 但し ydc が指定されているときには gg/G は H/L と同様に現在の項目の中で処理する。 70131 70132 * vi-mode: K [#D0419] 70133 70134 vim ではデフォルトでは現在の単語について man を呼び出すようである。 70135 ble.sh では丁度 command-help というものを既に用意している。 70136 これは現在のコマンドラインのコマンド名で --help または man を呼び出す。 70137 vim の動作とは異なるが引数について man を呼び出しても仕方がない気がするので、 70138 ここは寧ろ command-help の動作で問題ない気がする。 70139 70140 * vi-mode: 編集文字列に改行が含まれるときの RET の動作 [#D0418] 70141 70142 編集文字列に改行が含まれるとき、 70143 現在 insert mode に戻って改行を挿入する操作になっているが、 70144 これは下に移動する動作にするべきなのではないかという気がする。 70145 実際に試してみると + と同じ動作になっている様に思われる。 70146 70147 2017-09-07 70148 70149 * ble-edit: ble-edit/text/getxy は ble-edit/text/getxy.out に改名する。 [#D0417] 70150 70151 * vi-mode: accept-line したら vi_insert に戻るべきなのでは。 [#D0416] 70152 70153 * vi-mode: yh でカーソルは動かなければならない [#D0415] 70154 70155 yh でカーソルは動く。yl でカーソルは動かない。 70156 どうもコピーした領域の先頭に移動するということかもしれない。 70157 また共に範囲が空のときには kill ring の内容も空になる。 70158 70159 dl dh で領域が空の時には kill ring の内容は変更されない。 70160 70161 * vi-mode: vim の dd dj yy yj などは行単位でコピーしたということを覚えている。 [#D0414] 70162 つまり貼り付けの際に行頭に移動してから行単位で挿入を行うのである。 70163 70164 現在コピーした内容は _ble_edit_kill_ring という変数に記録している。 70165 これとは別に _ble_edit_kill_type などの変数を用意して 70166 其処に行単位かどうかの情報を記録するのはどうだろう。 70167 70168 これに関しては後で実装する→と思ったが結局 yy と同時に実装する事にした。 70169 70170 * vi-mode: 先に dd yy cc を実装する。0 も実装する [#D0413] 70171 70172 これは arg の実装の特殊なケースなので現状で中途半端になっている。 70173 70174 * ble-edit: 履歴の初期位置がおかしい。 [#D0412] 70175 70176 これは先程 ble-edit/history/load は ble-edit/history/goto 70177 でどうせ使うから呼び出さなくても良いとして削除したのがいけない。 70178 goto の引数に渡している値を取得するのに load が必要である。 70179 70180 * ble-edit で ble-edit/text/update/position が実行済みかのチェックを入れたら [#D0411] 70181 history-next, history-prev を実行した後の 70182 forward-line, backward-line で引っかかる様になった。 70183 70184 当初は一つの入力に対して forward-line, backward-line のみを呼び出すならば、 70185 編集文字列の変更はなく常に配置情報は最新になっているはずに違いないと考えたが、 70186 よく考えたら stdin に入力が溜まっている場合には配置計算を省略するようにしているので、 70187 上下のキーを連打すると容易に配置情報が更新されていない状態で forward-line/backward-line が呼び出される。 70188 70189 これは今までもチェックしていなかったために気付いていなかっただけで、 70190 今までも getxy.cur や get-index-at の計算が誤っていた事になる。 70191 実はこれが今までの _ble_edit_ind out of range のエラーの原因だったのではないか。 70192 これについては再現するかどうかを確かめた後に検証する必要がある。 70193 70194 →修正した。配置情報を使うコマンドに関しては 70195 ble-edit/text/update/position の結果が最新の場合とそうでない場合で 70196 動作を切り替える様に改修した。 70197 70198 →検証するのは面倒なのでやめた。 70199 今までの assertion failure は全て履歴の移動の後に起こっていたので 70200 もうこれが原因だということで恐らく間違いないだろう。 70201 取り敢えず今までの assertion failure の報告は全て解決済みとする。 70202 その上でまた assertion failure が出たらその時に改めて調査する事にする。 70203 70204 | 2016-09-14 70205 | 70206 | * stackdump がまた出た。 70207 | 70208 | | stackdump: 0 <= beg=28 <= end=29 <= len=1; beg=28, end=28, ins(1)=e 70209 | | @ /home/murase/prog/ble/ble.sh:5133 (_ble_edit_str.replace) 70210 | | @ /home/murase/prog/ble/ble.sh:-2006 (ble/widget/self-insert) 70211 | | @ /home/murase/prog/ble/ble.sh:33 (ble-decode-key/.invoke-command) 70212 | | @ /home/murase/prog/ble/ble.sh:22 (ble-decode-key/.invoke-partial-match) 70213 | | @ /home/murase/prog/ble/ble.sh:37 (ble-decode-key) 70214 | | @ /home/murase/prog/ble/ble.sh:92 (ble-decode-char/.send-modified-key) 70215 | | @ /home/murase/prog/ble/ble.sh:50 (ble-decode-char) 70216 | | @ /home/murase/prog/ble/ble.sh:-966 (ble-decode-byte+UTF-8) 70217 | | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 70218 | | stackdump: 0 <= beg=2 <= end=3 <= len=2; beg=2, end=2, ins(1)=c 70219 | | @ /home/murase/prog/ble/ble.sh:5133 (_ble_edit_str.replace) 70220 | | @ /home/murase/prog/ble/ble.sh:-2006 (ble/widget/self-insert) 70221 | | @ /home/murase/prog/ble/ble.sh:33 (ble-decode-key/.invoke-command) 70222 | | @ /home/murase/prog/ble/ble.sh:22 (ble-decode-key/.invoke-partial-match) 70223 | | @ /home/murase/prog/ble/ble.sh:37 (ble-decode-key) 70224 | | @ /home/murase/prog/ble/ble.sh:92 (ble-decode-char/.send-modified-key) 70225 | | @ /home/murase/prog/ble/ble.sh:50 (ble-decode-char) 70226 | | @ /home/murase/prog/ble/ble.sh:-966 (ble-decode-byte+UTF-8) 70227 | | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 70228 | | stackdump: 0 <= beg=3 <= end=4 <= len=3; beg=3, end=3, ins(1)=h 70229 | | @ /home/murase/prog/ble/ble.sh:5133 (_ble_edit_str.replace) 70230 | | @ /home/murase/prog/ble/ble.sh:-2006 (ble/widget/self-insert) 70231 | | @ /home/murase/prog/ble/ble.sh:33 (ble-decode-key/.invoke-command) 70232 | | @ /home/murase/prog/ble/ble.sh:22 (ble-decode-key/.invoke-partial-match) 70233 | | @ /home/murase/prog/ble/ble.sh:37 (ble-decode-key) 70234 | | @ /home/murase/prog/ble/ble.sh:92 (ble-decode-char/.send-modified-key) 70235 | | @ /home/murase/prog/ble/ble.sh:50 (ble-decode-char) 70236 | | @ /home/murase/prog/ble/ble.sh:-966 (ble-decode-byte+UTF-8) 70237 | | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 70238 | | (略) つづきは同様 70239 | 70240 | 1 不思議なのは _ble_edit_str.replace で修正が入っている筈なのに、 70241 | エラー状態が継続している事である。 70242 | よく見ると、修正によって初回よりはましな値になっていると言え 70243 | end の値が文字列の長さよりも一つ多いものになっている。 70244 | 70245 | 取り敢えず、初めに発生したエラーの原因は別の所にあるとしても、 70246 | 修正部分のコードが間違っている可能性があるので修正する。 70247 | 70248 | 確認してみたところ、_ble_edit_str.replace は _ble_edit_ind を修正するとは言っても、 70249 | その場で許容される値に修正するだけで _ble_edit_str.replace 呼び出し元での 70250 | _ble_edit_ind に対する操作も含めての修正ではない。 70251 | 従って、_ble_edit_str.replace の中で _ble_edit_ind を修正しても仕方がない。 70252 | 70253 | →どうも観察してみたところ、_ble_edit_str.replace の呼び出し元では、全て、 70254 | _ble_edit_str.replace を呼び出した後に _ble_edit_ind を更新している様である。 70255 | つまり、_ble_edit_str.replace 呼び出し時点では、_ble_edit_ind の値は 70256 | 文字列挿入前の値になっていると想定して良い。 70257 | と思ったが、そうでは無い物もあったので、それについては処理の順序を入れ替える。 70258 | という訳で、これでエラーが発生した時の _ble_edit_ind の修正は正しくなった筈である。 70259 | 序に _ble_edit_mark に関しても同様の修正を行う様にする。 70260 | 70261 | 2 もう一つの問題点はそもそも何故初めに変な値になったのかという事である。 70262 | 特に beg=28 end=28 という値になっている。 70263 | 因みにこの時前に実行したコマンドは "gunzip -c xp.img.gz | wc -c" の 27 文字であり、 70264 | またエラーが発生したのは最新の編集行に echo と入力しようとした瞬間である。 70265 | 勿論、最新の編集行に入力しようとすると必ずなる訳ではなく 70266 | (恐らく直前の操作手順に応じて) このエラーが発生したりしなかったりする。 70267 | 70268 | 70269 | 2016-06-25 70270 | 70271 | * また stackdump が出た。 70272 | 70273 | .ble-edit/delete-backward-char および insert-char で起こっている。 70274 | 表示されている内容から察するに、_ble_edit_ind が変な値になっている様だ。 70275 | また、履歴を上下で移動した後に起こっている事も分かっている。 70276 | 70277 | | stackdump: 0 <= beg=10 <= end=10 <= len=8; beg=10, end=11, ins(0)= 70278 | | @ /home/murase/prog/ble/ble.sh:17 (_ble_edit_str.replace) 70279 | | @ /home/murase/prog/ble/ble.sh:11 (.ble-edit/delete-backward-char) 70280 | | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit.delete-char) 70281 | | @ /home/murase/prog/ble/ble.sh:4 (ble/widget/delete-backward-char) 70282 | | @ /home/murase/prog/ble/ble.sh:-1794 (ble/widget/delete-region-or) 70283 | | @ /home/murase/prog/ble/ble.sh:16 (ble-decode-key/.invoke-command) 70284 | 70285 | この前の修正で完全に直っていたはずだと思ったのだが何故だろうか。 70286 | make を実行したら ble.sh が更新されてしまったので ble.sh 70287 | が中途半端な状態にあったのかも知れない。 70288 | 丁度最近、検索の速度向上の為に一時的に単一の配列だけを参照する様に 70289 | 書き換えたりなどしていた後である。 70290 | また、暫く様子を見てそれでも出る様だったらまた原因を探る必要がある。 70291 | 70292 | 或いは、今先程エラーが起こったシェルの history next 関数を調べて、 70293 | その内容がどの様な状態になっているかを確認すれば、 70294 | エラーが起こる様な状態に丁度編集していた最中だったかどうかが分かる。 70295 | →実際のループ処理を行っているのは ble-edit/isearch/next-history-resume.fib 70296 | の中である。ロードされている関数の中身を確認してみた所、 70297 | ちゃんとこの前修正した二つの配列を参照して内容を決定する部分は正しい。 70298 | 70299 | | if [[ ${_ble_edit_history_edit[i]-${_ble_edit_history[i]}} == *"$needle"* ]]; then 70300 | | ind="$i"; 70301 | | break; 70302 | | fi; 70303 | 70304 | では何が悪いのだろうか。考えてみると長い履歴項目を弄った後に、 70305 | 一番下の (空の) 項目に戻ってきた時に起こった様な気がする。 70306 | うーんそれでも再現は簡単にはしない…。 70307 | 又エラーの起こった状態から復帰する為に 70308 | _ble_edit_ind は調整を行ってしまうのが良い。 70309 70310 70311 * 2017-09-04 vi-mode に対応する (初期計画) [#D0410] 70312 70313 取り敢えずブランチを切る。 70314 70315 取り敢えず vi 用の keymap に切り替える仕組みを作る。 70316 70317 | - set -o vi が有効になっている時には keymap viins を使う様にする。 70318 | - 途中で set -o emacs から set -o vi になった時に ble.sh のモードも変更する様にする。 70319 | - ble-decode-attach において -m vi-insert に対して bind するようにする? 70320 | 70321 | 或いは飽くまで emacs-standard を使う様にするか。 70322 | emacs-standard を使うようにしていると [[ -o vi ]] などが意図と反する結果になるので良くない。 70323 | コマンドを実行する瞬間だけ戻すという手もあるがそれだと 70324 | - ^C などで中断した時に set -o emacs に戻す機会が失われて、また応答しなくなる状況に陥るという問題が発生する。 70325 | - ユーザが自分で定義した widget 関数の中などではやはり set -o emacs になっている様に見えてしまう。 70326 | 70327 | 従って、やはり -m vi-insert に対して設定を行う必要がある。 70328 | ところで bind で設定されるのは既定ではどの keymap なのだろうか。 70329 | set -o vi の時には vi-insert (vi-command ではなく) だと考えてよいのだろうか。 70330 | 或いは emacs-standard になってしまうという可能性もある。 70331 | 70332 | →vi_insert keymap を導入した。現在は emacs の clone である。動作している。 70333 | これから vi_insert としての振る舞いになるように少しずつ widget などを実装していけば良い。 70334 70335 先に mode の間の切り替えを実装する。 70336 70337 次に引数を管理する仕組みを考える。 70338 70339 | 初めは数字の引数を記録する枠組みを作って、 70340 | それを emacs と共有するようにしようと考えたが、 70341 | 操作体系を調べると 2d3 なども引数として処理した方が良い様に思われる。 70342 | というのも d3h d3l などは削除コマンド d に対する細かい動作の制御ではなくて、 70343 | 移動コマンド h l に対する修飾として働いている様に思われるからである。 70344 | 70345 | 引数はどの様に管理すれば良いだろうか。 70346 | これは単純に引数を記録しておく変数を用意すれば良い気がする。 70347 | 70348 | - ble_edit_str ble_edit_ind ble_edit_mark と同様に管理すれば良いだろうか? 70349 | 引数の入力状態は直接表示の仕方に影響を与えるものではないので 70350 | これらと同様に管理する必要はない。 70351 | つまり引数が変更されたとしても表示の更新を行う必要はないので、 70352 | 表示が更新されたかどうかの判定に用いる必要もない。 70353 | - また各履歴項目に紐付いた物でもないので、履歴を移動した時に記録する必要もない。 70354 | 70355 | さてもう一つ考えて置かなければならないのは editing-mode = emacs の時の 70356 | arg と統一的に扱うかどうかである。emacs の時は arg は唯の整数である。 70357 | しかし vi の時は上で決定したように d などの文字も含む。 70358 | ただ結局どのような文字を引数に入れるのかはキーバインディングに依存するので、 70359 | emacs でも vi でも同様に実装して問題ないように思われる。 70360 70361 ところで同じ forward-char であっても emacs vi で引数の取り扱いが異なる。 70362 vi では右端に行ったら次の行には行かないが emacs では次の行に行く。 70363 従って結局 emacs と vi で別々に forward-char を実装する必要があるのではないか。 70364 70365 先ずは hjkl について実装した。 70366 大体の仕組みは整ったので後は少しずつ実装していくだけの気がする。 70367 70368 * 2017-09-05 vi-mode: forward-line-or-history-next, forward-line-or-history-next [#D0409] 70369 70370 引数に対応する。そもそも emacs では引数に修飾文字が入らないことを考えると、 70371 共通で vi の引数の仕組みで実行するようにしてしまって問題ない気がする。 70372 つまり、現在 vi 専用の引数の仕組みになっているものを emacs にも拡張する。 70373 70374 と思ったが、forward-line-or-history-next は修飾に対応していない。 70375 しかし、異なる history entry の間でコピー・切り取りに対応するのは変だ。 70376 従って、修飾文字が含まれている場合には現在の履歴項目の中での移動に制限するのが自然である。 70377 70378 70379 forward-line/backward-line において見た目の行を移動するか論理的な行を移動するかが問題である。 70380 また列も見た目の列を保持するか、論理的な列 (文字数) を保持するかが問題である。 70381 emacs mode の方では見た目の行を見た目の列を保持して移動する様になっている。 70382 70383 vim で実際に試してみると一番最後に forward-line/backward-line 70384 を実行した時の見た目の列を保持している。 70385 また当然のことながら論理的な行を移動するようになっている。 70386 論理行が複数行にまたがる時、全角・半角の都合により異なる位置で改行されることがある。 70387 調べてみるとそのような場合でも "見た目" の列を保持しているようである。 70388 従って、もし厳密にこの動作に従うのだとすると、 70389 1. まず初めに論理行頭からの見た目の行・列を取得し 70390 2. 次に移動先の論理行頭の位置を求め、 70391 更に論理行頭を保持するということにする必要がある。 70392 70393 - ble-edit/text/update/positions の問題 70394 70395 所で、行の内容を変更した後に ble/widget/forward-line を呼び出す時には 70396 ble-edit/text/update/position を呼び出す必要があることには注意しなければならないのではないか。 70397 何故なら中で使用している ble-edit/text/getxy.cur などの関数は内部で 70398 配列 _ble_line_text_cache_pos を参照するがこの配列は ble-edit/text/update/position 70399 で更新される。ここで手で ble-edit/text/update/position を呼び出すというても考えられるかもしれないが、 70400 その為には変更範囲 BLELINE_RANGE_UPDATE (中身は _ble_edit_dirty_draw_{beg,end,end0}) が必要で、 70401 更にこの変更範囲は "描画" や "色つけ" と共有しているので、 70402 ble-edit/text/update/position を実行するためにはこれらと一緒に更新する必要がある。 70403 従って現状では途中で _ble_line_text_cache_pos を更新するのは難しい。 70404 70405 - もし対応させようとするならば ble-edit/text/update/position の dirty range を 70406 描画の dirty range とは独立に管理する様にしなければならない。 70407 70408 - 従って現状では変更後に forward-line は呼び出してはならないという制限を設けなければならない。 70409 安全の為に変更がないということを確認する必要はあるかもしれない。 70410 このチェックは _ble_edit_dirty_draw_beg=-1 である事を確認すれば十分である。 70411 →確認する様に修正する。 70412 70413 [結論] dirty になっていないか確認し、dirty ならエラー。 70414 70415 70416 - ble-edit/text/getxy と ble-edit/text/getxy.cur の違い 70417 70418 何であったか。memo.txt を探すと getxy は出力位置で getxy.cur はカーソルの表示位置だという。 70419 これは一体どういうことか。両者は同じではないのか。 70420 調べると _ble_line_text_cache_pos[i+1] の第3フィールドが非ゼロの時に、 70421 getxy.cur は次の行頭を指し示す様になっている。 70422 % 第3フィールドは左の文字が ASCII 表示文字以外 (isprint 以外) で、かつ、 70423 % その行に収まりきらない時に、非ゼロになる。 70424 つまり幅2以上の文字でその行に収まりきらない時に非ゼロになる。 70425 70426 うーん。getxy は左側の文字の終端位置で、 70427 getxy.cur は右側の文字の開始位置と解釈すれば良いだろうか。 70428 70429 考えていたら分かった気がする。先ず右側で折り返す文字は、 70430 行末の幅を補填する空白が追加される。これにより二行にまたがる文字になる。 70431 getxy はこの空白も含めた開始位置であり、実際に _ble_line_text_cache_cs を切り出して出力する場合には、 70432 この位置から出力を開始する必要がある。getxy.cur は実際に空白を除いた文字の本体が表示される位置である。 70433 実用的には、実際の所 getxy は左側の文字の州単一で getxy.cur は右側の文字の開始位置と解釈して問題なさそうだ。 70434 70435 [結論] 分かりにくいので getxy, getxy.cur の関数に説明を追加しておく。 70436 70437 2017-09-06 70438 70439 * ble-edit: 余分な ble-edit/history/load 呼び出しがあったので削除 [#D0408] 70440 70441 2017-09-05 70442 70443 * ble-edit: .goto-char [#D0407] 70444 70445 何やら意味のない関数のように思われたが、 70446 履歴を調べてみると以前は変更があったときのみ set-dirty を実行していた様だ。 70447 現在はカーソルの位置は別に記録してあるし表示内容の変更と 70448 カーソル位置の移動は別々に管理しているのでその必要はなくなったのであった。 70449 70450 さて、ということはこの関数の内容は単純化できる。 70451 70452 * vi-mode: (()) は bash-3.0 でエラーになる。{ :; } が意味的にも無難 [#D0406] 70453 70454 →どうやら function f () (()) ならば bash-3.0 でも OK の様である。 70455 70456 2017-09-04 70457 70458 * vi-mode: ble-edit/bind/.check-detach で編集モード切り替わり判定を行う [#D0405] 70459 70460 うーん。bleopt_default_keymap=auto のとき、これも一緒に切り替える必要があるのではないだろうか。 70461 一方で、bleopt_default_keymap を直接指定しているときには一緒に切り替えてしまっては駄目である。 70462 また切り替えた場合には必要に応じて source keymap/vi.sh などが必要である。 70463 70464 % うーん。しかし bleopt_default_keymap として auto を許容すると複雑になる。 70465 % 問題点は bleopt_default_keymap は既に別の用途で使われているということである。 70466 % その様に考えると bleopt_default_keymap とは別に bleopt_editing_mode のような感じの変数を用意するのが妥当である。 70467 % →使い方を多少変更した。改名はしないことにした。#D0402 を参照のこと。 70468 70469 [変更] 70470 70471 編集モードが変わった時には単に ble-decode-detach してから 70472 ble-decode-attach すれば良い。ble-decode-detach は前回の attach の際の編集モードで解除を行い、 70473 attach は現在の編集モードで設定を行うからである。 70474 70475 また keymap/vi.sh は DEFAULT_KEYMAP から呼び出すことにした。 70476 既に呼び出し済みかどうかの判定は関数 ble-edit/load-keymap-definition:$name 70477 を空関数にすることによって設定する。 70478 70479 vi.sh に関しては vi.sh 内部に widget を定義したいので、 70480 何れにしても必ず読み込むようにする。 70481 その場合は keymap の定義の部分のみキャッシュする。 70482 キャッシュがある場合は vi.sh の中から呼び出す様にする。 70483 70484 Note: この動作は emacs.sh の場合と異なることに注意する。 70485 emacs.sh の widget は全て ble 本体の中に定義してあるので、 70486 emacs.sh でやることは keymap の定義のみである。 70487 ということはキャッシュがある場合にはそもそも emacs.sh すら呼び出さなくて良いので、 70488 ble-edit.sh 側の ble-edit/load-keymap-definition:emacs でその操作を定義する。 70489 70490 実装した。テストした。 70491 問題が合ったので以下の変更も行った。 70492 70493 * 変数 ble-bind: ble_bind_keymap の導入 70494 70495 ble-bind で既定の keymap を指定するのに bleopt_default_keymap を local で書き換えて呼び出していたが、 70496 現在 bleopt_default_keymap は DEFAULT_KEYMAP を通して呼び出されるものであり、 70497 keymap/kmap.sh などから定義を探し出す仕組みに組み込まれているので、 70498 bleopt_default_keymap を任意に書き換えて実行するというのは良い方策ではない。 70499 従って、新しい変数として ble_bind_keymap という変数を用意した。 70500 ble_bind_keymap が設定されている場合には DEFAULT_KEYMAP は使用されない。 70501 70502 * vi-mode: どうやら set +o emacs を検知できない。 [対処不可][#D0404] 70503 70504 % set +o emacs を含む builtin eval を抜けるとそこですぐに終了してしまうようだ。 70505 % 70506 % 一応 set +o emacs を含む builtin eval の中にあるコマンドは全て実行されるようだ。 70507 % builtin eval の中で細工して一旦 set -o emacs に戻すことによって 70508 % 後処理をしてその後で抜けるという様にはできるかもしれない。 70509 % 70510 % どうやら builtin eval の中に直接 echo を書いたら実行されるが、 70511 % 関数呼び出しを通して echo を呼び出そうとしても駄目のようだ。 70512 % 関数呼び出しより後に書いても駄目のようだ。 70513 % もしかすると .save-params 関数が悪さをしている可能性もある。 70514 % 70515 % .save-params でなくて空の関数 function AAA { :; } を使ってみたが同様に駄目だった。 70516 % 関数定義が見えなくなっているのではないかと思って function AAA { :; } を eval の中に書いてみたが、 70517 % 関数定義を書いただけでそれ以降は実行されなくなってしまう。 70518 % 70519 % と思ったが今度は直接 echo を書いても実行されなくなってしまった。何故? 70520 % しかし依然として set +o emacs; echo world などとした場合の world は出力される。 70521 70522 もしかして改行があるかないかが関係しているのだろうか。 70523 →試してみたらそうだった。何と改行があると駄目なのだ。 70524 70525 でもそうだとすると実行しようとしているコマンド自体に改行が含まれている場合には、 70526 それ以降のコマンドは実行されないという事になる。実際に試してみた所そうなった。 70527 70528 また改行さえ無ければ eval の外も実行されるのかと思いきやそういう訳でもない。 70529 70530 更に .save-params を改行ではなく ; で区切れば良いのではないかと考えたが、 70531 それだと "echo ;" などのコマンドを実行した時に ";" の重複により構文エラーになってしまう。 70532 70533 [結論] 70534 70535 仕方がないので以下の制限は置く必要がある。 70536 70537 - ユーザが set +o emacs を実行すると正しく ble.sh から抜けることができない。 70538 - 更に set +o emacs に続けて改行が含まれる場合にはコマンド自体も正しく実行されることは保証できない。 70539 70540 * ble-decode: 分離: ble-decode/keymap/resolve-name 関連 [#D0403] 70541 70542 他に以下のようなものが ble-edit.sh の存在・使用方法を想定している。 70543 70544 - _ble_decode_key__kmap=emacs の既定値 70545 - bleopt_default_keymap=auto の既定値 70546 70547 ble-decode/keymap/resolve-name に関しては外部で関数定義できるようにするのが良い。 70548 bleopt_default_keymap に関しては元々外部から設定するべきものである気がする。 70549 _ble_decode_key__kmap=emacs の既定値もその時に同時に指定するべきな気がする。 70550 70551 →整理した。 70552 70553 1. ble-decode/keymap/resolve-name は外部から上書きして使う事にした。 70554 70555 またこれを機に外部から上書きして設定を行うことを目的とする関数を "設定関数" とし、 70556 またその名前をできるだけ "モジュール/大文字名" の形式になるようにした。 70557 ここで "モジュール" とは ble-decode などのことである。 70558 現在以下の設定関数が ble-decode.sh には定義されている。何れも ble-edit.sh で上書きされる。 70559 70560 - 設定関数 ble-decode/PROLOGUE 70561 - 設定関数 ble-decode/EPILOGUE 70562 - 設定関数 ble-decode/DEFAULT_KEYMAP -v varname 70563 - 設定関数 ble/widget/.SHELL_COMMAND command 70564 - 設定関数 ble/widget/.EDIT_COMMAND command 70565 70566 またこれに伴って ble-decode-byte:bind も ble-decode/.hook に改名した。 70567 使われていない ble-decode-char:bind 及び ble-decode-key:bind は削除した。 70568 (これらの関数は恐らく初期の実装のときのテストに使われたものであった。) 70569 70570 2. bleopt_default_keymap は ble-edit.sh 側で管理することにした。ble-decode.sh は関知しない。 70571 70572 3. _ble_decode_key__kmap=emacs の既定値は ble-decode.sh を単体で読み込んだ時には何れにしても 70573 (例え動作しないとしても) 何らかの値を設定しておく必要があるので現状通り取り敢えず emacs を設定することにした。 70574 同様に既定の ble-decode/DEFAULT_KEYMAP も emacs を設定するようにする。 70575 70576 * vi-mode: bleopt_default_keymap [#D0402] 70577 70578 % 結局、ble.sh で編集モードに対応しているのは bleopt_default_keymap である。 70579 % 70580 % 更に具体的な emacs keymap の定義は ble-edit/load-default-key-bindings から 70581 % source "$_ble_base/keymap/emacs.sh" を通して読み込まれている。 70582 % この時 bleopt_default_keymap などは参照せずに直に emacs.sh が指定されている。 70583 % 70584 % この辺りは bleopt_default_keymap を参照するようにして良いのではないか。 70585 % 或いは bleopt_default_keymap は動的に変わったりする物であっただろうか。 70586 70587 [現状] 70588 70589 改めて bleopt_default_keymap がどの様に使われているかについて確認しておく。 70590 70591 - 先ず ble-decode において _ble_decode_key__kmap が空の時の既定の keymap 名として使われている。 70592 70593 これについては _ble_decode_key__kmap による。調べてみると 70594 _ble_decode_key__kmap は最初は中身は空のようである。 70595 先に中身を設定してしまうと、ble の設定箇所で bleopt_default_keymap が変更された場合に対応できないからであろう。 70596 これに関しては ble-attach のタイミングで _ble_decode_key__kmap=$bleopt_default_keymap を実行するようにすれば良い。 70597 70598 - また ble-bind において既定の keymap として使われている。 70599 70600 これは、その時の _ble_decode_key__kmap がどうであれ bleopt_default_keymap に設定を行いたい。 70601 70602 - keymap/emacs.sh で ble-bind を呼び出す時の bleopt_default_keymap を上書きしている。 70603 70604 こう調べてみると bleopt_default_keymap は (_ble_decode_key__kmap さえ正しく設定されていれば) 70605 単に keymap の構築時に使用されるだけであり実際の処理に使われる訳ではない。 70606 70607 [変更] 70608 70609 結局 bleopt_default_keymap は改名しないことにした。 70610 但し特別な値 auto が入っている場合には、実際に bleopt_default_keymap の値を読み出す時に、 70611 現在の [[ -o emacs/vi ]] の状態に応じて値を解決するというようにした。 70612 これらの処理は素朴に考えると ble-edit.sh にあるべき気もするが、 70613 取り敢えず暫定的な実装として ble-decode.sh の方に配置することにした。 70614 70615 * vi-mode: 次に ble-edit-attach を改修する [不要][#D0401] 70616 70617 中で何をしているかというと 70618 70619 1. 先ず初めに ble-edit/attach を呼び出している。 70620 70621 中ではどうも大したことはしていない。 70622 attach, detach で PS1, IFS の保存と復元を行っている。 70623 70624 2. また履歴の再読込の設定を行っている。 70625 70626 他は特に何もしていない。keymap に関する設定は別の関数で行っている様だ。 70627 つまり、この関数は何も変更はいらない。 70628 70629 * 所で set -o vi してから source ble.sh した時に動かなかったというのは何故なのか。 [#D0400] 70630 70631 % GitHub #1 によるとそのように報告されていた。 70632 % しかし ble-decode-attach の現状の実装方法で特に問題がないように思われた。どういうことか。 70633 % これはよく分からないので改めて set -o vi で source ble.sh して動作を確認してみる必要がある。 70634 % 70635 % うーん。動いているような気がする。 70636 % よく考えてみたら set -o vi にしてから source すると死ぬのではなくて、 70637 % .inputrc に記述して ble.sh つきで起動すると駄目だということだった様にも思う。 70638 % 70639 % さて .inputrc に vi を使うという事を指定するにはどうしたら良いのか。 70640 % http://d.hatena.ne.jp/yamazakiccs/20081207/1216817670 70641 % → set editing-mode vi と記述すれば良いようだ。 70642 % 70643 % さて実際にやってみると特に問題もなく ble.sh が読み込まれている。 70644 % 変な動作も簡単に見た感じでは現れていない。 70645 % (もしかすると或る種のキー入力に関しては入力を奪いきれていないという可能性も残っているが、 70646 % それらの検証は後回しにして良いだろう。) 70647 % 70648 % 改めて #1 を読んでみると "無効になる" としか書かれていない。 70649 % もしかして無効になるとは set -o vi をした時と同様に反応がなくなるという意味ではなくて、 70650 % 単に set -o vi (の動作) が無効になるという意味なのではないだろうか。 70651 % だとするとこれには対応していないのだから当然のことである。 70652 % 実はこれについては対策しなくても良かったのではないかと思われる。 70653 70654 "無効" というのは #1 の報告者の苛立ちというか "いやみ" が入った表現で、 70655 実際に動かないということではなかった。気にしなくて良い。 70656 70657 因みに inputrc に set editing-mode vi とした場合でも、 70658 ちゃんと [[ -o vi ]] に反映されるので inputrc で指定されたかどうかなどのことは意識しなくても良い。 70659 70660 * vi-mode: まずは ble-decode-attach を改修する。 [#D0399] 70661 70662 取り敢えずは ble.sh を起動している最中に set -o emacs/vi が切り替わる場合については考慮しないで良いだろう。 70663 切り替わった時にするべき操作は別に実装することになるだろうからである。 70664 そして切り替わった時にするべき操作が具体的に何になるかは、ble-decode-attach の内容に依存する。 70665 70666 [現状] 70667 70668 どのような変更が必要になるのか改めて調べるために取り敢えず現在の実装について観察しておく。 70669 70670 1. ble-decode-bind/.generate-source-to-unbind-default 70671 70672 先ず初めに現在の bind の状態を調べてそれを .save ファイルに記録する。 70673 そして ESC に関しては unbind するためのコードを生成する。 70674 70675 この .save ファイルはキャッシュするような性質のものではなく、 70676 ble-decode-bind を実行する度に毎回生成するものである。 70677 70678 これは set -o vi でも同じ動作で問題ないだろうか。 70679 つまり vi と emacs で .save のファイル名を切り替えなくても良いのではないか。 70680 一度に両方の keymap を上書きしていると混乱の元だし状態の把握が面倒である。 70681 一度に片方しか上書きしないのだとしたら同じファイル名でも問題ないように思われる。 70682 70683 但し、「現在どちらのモードに対して上書きを実行しているか」の状態を管理する変数は別に保持する必要がある。 70684 これは実際 _ble_decode_bind_attached が担っている。現在は「上書きを実行しているか」「していないか」の2状態だが、 70685 emacs として上書きしているか vi として上書きしているかの情報を持たせるようにすれば良い。 70686 70687 →取り敢えず現状のままで問題ないだろう。 70688 70689 2. 次に source "$_ble_base/bind.sh" を呼び出す。 70690 70691 ここでは ble_decode_bind.40412.bind (40412 は実際は bash の version) を生成する。 70692 このファイルの中にはその bash の version において、 70693 キー入力を全て横取りする為に必要な bind の列が含まれる。 70694 70695 実はこれについても set -o vi と set -o emacs で違いはないように思われる。 70696 念のため bind.sh の中身についても確認しておく。やはり vi/emacs に依存する処理は行っていない。 70697 70698 [変更] 70699 70700 従って、変更は _ble_decode_bind_attached の管理だけである様に思われる。 70701 _ble_decode_bind_attached は他に ble-decode-detach が参照している。 70702 他の箇所からは参照されていない。 70703 70704 ble-decode-attach ではどのモードで attach したかを記録しておくだけで良い。 70705 ble-decode-detach では _ble_decode_bind_attached の内容に応じて、 70706 set -o vi/emacs で attach した時のモードに戻しておいて、 70707 その状態で bind を復元してから元のモードに戻るようにすれば良い。 70708 70709 (モードを復元している最中に ^C で中断などが入ると変なことになるがそれは仕方がないだろう。 70710 ただ簡単に状態を復元する方法というのを実装しておいても良いかもしれない。) 70711 70712 この変更により ble-decode-detach を呼び出す時の編集モードは気にしなくて良くなった。 70713 つまり、先の変更により ble-decode-detach を呼び出す前に set -o emacs に戻していたが、 70714 ble-decode-detach の中で適切な編集モードに切り替えるので、外でその操作をする必要はなくなる。 70715 70716 取り敢えず変更は実施した。 70717 70718 70719 2017-09-03 70720 70721 * ble-syntax: here string が here document と解釈されている。 [#D0398] 70722 70723 これは ble-syntax.sh の .check-delimiter-or-redirect の中の判定の順序であった。 70724 70725 * 2017-09-01 permission のないディレクトリで補完しようとすると以下のメッセージが表示される。 [#D0397] 70726 70727 ヒアドキュメント用一時ファイルを作成できません: 許可がありません 70728 -bash: ヒアドキュメント用一時ファイルを作成できません: 許可がありません 70729 70730 % TERM に依存して出たり出なかったりする様だ。 70731 % 現在 tkyntn の上でしか再現していない。 70732 % 元々 tkyntn は色々とおかしいのでもしかすると他では再現しないのかもしれない。 70733 % 70734 % どうも TERM ではなくてログインシェルかどうかで変わるようである。 70735 % ログインした後に bash として入ると大丈夫である。 70736 % 一方で、bash --login とすると駄目である。 70737 % TERM=xterm-256color でも再現することを確認した。 70738 % 70739 % どうやら ble の中で起こる問題というわけでもない様だ? 70740 % bash --norc で入って cd ~yabe して cat <<< hello とするとエラーを吐く。 70741 70742 更に以下のコマンドだけでエラーが再現する。 70743 70744 $ bash -c 'cd ~yabe; cat <<< hello' 70745 70746 これは ble.sh の問題ではなくて bash の問題かもしくは tkyntn の問題である。 70747 特に tkyntn は最近様子がおかしいので高確率で tkyntn が悪いのであろう。 70748 70749 % 何れにしてもエラーメッセージがそのまま外部に漏れるというのは変な気がするので、 70750 % これについては何処かで対策をしたほうが良いだろうか。 70751 % うーん。どのタイミングでエラーメッセージを無視するのが良いかは微妙である。 70752 % というよりエラーメッセージをそのまま握りつぶして良いのだろうかという問題もある。 70753 % もしかすると ble.sh 専用のログファイルを何処かに用意してそこにエラーを出力するようにする方が良いのかもしれない。 70754 % ただし、もしそうするのだとすると、これは今回の問題だけでなくて ble.sh 全般に関わることなので全体的に整備しなければならない。 70755 70756 改めて問題になっている ble-complete/source/argument/.compgen の ble/util/assign の中のヒアストリングの周りを見る。 70757 丁度一つ上の行で 2>/dev/null でエラーをそのまま握りつぶしているので、 70758 問題になっている行でも同様に握りつぶすという対策で問題ないだろう。 70759 70760 2017-08-30 70761 70762 * GitHub で Issue が来た。set -o vi の人だ。 [#D0396] 70763 70764 以下の点について修正する。 70765 70766 - [[ -o vi ]] の時は ble.sh をロードしない 70767 70768 - コマンドの実行の結果 -o vi になった時は ble-detach する。 70769 70770 - ble-detach する時には本来の emacs keymap に対して実行するために 70771 一時的に現在の編集モードを退避して後で復元する。 70772 70773 将来的に set -o vi に対応した時には両方で keymap を復元する様に 70774 ble-detach の中を書き換えるか、emacs/vi mode に拘らず 70775 常に bash "set -o emacs" の上で ble.sh "emacs/vi" の動作を実装すれば良い。 70776 70777 - ble-attach の時に [[ -o emacs ]] をチェックする。 70778 70779 70780 2017-08-19 70781 70782 * ble-edit: C-x C-x で内部的なカーソル位置は変わっているが表示に反映されない。 [#D0395] 70783 70784 →どうも反映されないというよりは移動前の位置にカーソルが表示される様だ。 70785 C-x C-x を二回実行すると分かる。これは何故だろう。 70786 ble/widget/exchange-point-and-mark では単に _ble_edit_ind と _ble_edit_mark の内容を交換している。 70787 その他の箇所からはこの関数は参照されていない。という事はこの関数の問題というよりは表示の問題だろう。 70788 70789 そもそもカーソル位置の更新は何処で実行されているだろうか。 70790 ble-edit/render/update が怪しい。この関数の先頭で _ble_edit_ind/_ble_edit_mark 70791 がどのような状態になっているか確認する。 70792 どうやらこの関数を呼出した時点では _ble_edit_ind 及び _ble_edit_mark は更新前の値になっている様だ。 70793 70794 % もしかして exchange-point-and-mark が呼び出されていないのでは? と考えたが、 70795 % 実際に入力すると期待する位置に文字が挿入されるため、exchange-point-and-mark は呼び出されているはずだ。 70796 % もしかすると bash が入力を食らっていて C-x C-x をユーザ側で入力しても未だ処理されていないのかもしれない。 70797 % しかしそうだとすると C-x C-x を入力した時に ble-edit/render/update がちゃんと2回呼び出されている事と矛盾する。 70798 % よくわからないので exchange-point-and-mark の中で鳴く様にしてちゃんとこの関数が呼びだれているか、 70799 % 呼び出されているとすればどのタイミングで呼び出されているかを確認する。 70800 70801 →どうやら exchange-point-and-mark が呼び出されていない。 70802 疑わしいのは decode の方である。もしかすると C-x C-x ? の様な形のコマンドが登録されてしまっているのかもしれない。 70803 或いは ble-decode が壊れていて C-x ? の様な形のキーシーケンスがその場で呼び出されない可能性もある。 70804 →これについては C-x C-v が即座に実行される事から考えにくい。 70805 何れにしても C-x C-x ? の様な紛らわしいコマンドが登録されていないかを確認する必要がある。 70806 70807 →ble-bind -d で確認してみた。C-x C-x が曖昧になるようなキーシーケンスは登録されていない。 70808 と思ったら ble-bind -k 'CAN @ h' などが怪しい。CAN は C-x に一致するはずなので、 70809 バイト C-x が単体で来た状態の場合にはそれがキー C-x なのかキー hyper, etc. なのかの判断が付かない。 70810 これが怪しい。これについては試しに CAN @ の bind を削除してみれば分かる事である。 70811 70812 取り敢えず "CAN @ ?" を削除してみたら動くようにはなった。 70813 しかしそれでも微妙な遅延が見られる。emacs では遅延がないのでこれは端末の設定だろう。 70814 少し stty 周りを見ても分からないし大きな問題でもないのでこれは後回しで良いだろう。 70815 70816 * [2017-06-12] ble-edit: 選択した状態で self-insert したら選択した範囲の文字列は消えてほしい。 [#D0394] 70817 70818 2017-06-09 70819 70820 * bash-4.2 で何か入力しようとすると segfault する。 [#D0393] 70821 70822 初めは mathieu の上で気付いたが padparadscha でも再現する。 70823 bash-4.0, bash-4.1, bash-4.3, bash-4.4 では大丈夫。 70824 これは bash-4.2 の算術式のバグを踏んでいる可能性が高い。 70825 70826 grep で '],' を探してみる。 70827 2015-02-23 04:46:57 ble-edit.sh:1286: if ((ichg=old_ichg[j], 70828 2017-03-01 10:09:47 ble-syntax.sh:1401: ((_ble_syntax_attr[i++]=_ble_syntax_attr[inest], 70829 70830 二つ目が怪しい → 修正したけれど治らない。 70831 これはクラッシュする箇所を少しずつ絞り込んでいくしかない。 70832 怪しいのは self-insert の前後と、描画部分である。 70833 しかし、描画部分に関してはプロンプトは表示されているのだから、 70834 大体大丈夫なのではないかという気がする。 70835 或いは文法に従った着色の部分が怪しいか、文法の解析部分が怪しいか。 70836 一番怪しいのは文法周りなので、先ずはそこを囲んで print してみる事にする。 70837 70838 ble-syntax/parse を呼び出しているのは function _ble_edit_str.update-syntax だけである。 70839 _ble_edit_str.update-syntax は ble-syntax.sh:3830 と complete.sh から呼び出される。 70840 complete.sh は今回の場合は使っていないので、これは関係ない。 70841 ble-syntax.sh では関数 ble-highlight-layer:syntax/update から呼び出している。 70842 更にこれは ble-edit.sh の関数 ble-edit/text/update から 70843 ble-highlight-layer/update を呼び出しているのが引き金になっている。 70844 更に呼び出し元は ble-edit/render/update である。 70845 取り敢えずこの関数で echo をしてみる事にする。 70846 70847 -> ble-edit/text/update の中で起こっている 70848 -> ble-highlight-layer/update の中で起こっている 70849 -> ble-syntax/parse の中で起こっている 70850 -> ble-syntax:bash/ctx-command の中で起こっている 70851 -> ble-syntax:bash/ctx-command/.check-word-begin の中で起こっている 70852 分かった。(((wtype=_ble_syntax_bash_command_bwtype[octx])||(wtype=ctx))) だ。 70853 修正したら大丈夫になった。念のため、類似の危険な箇所がないか確認する。 70854 70855 $ grc '\]\)[^)]' 70856 70857 ./ble-core.sh:713: if (((time2[0]-time1[0])*1000+(10#0${time2[1]::3}-10#0${time1[1]::3})>=msec)); then 70858 ./ble-syntax.sh:720: ((onest[3]<0?(parent_inest=onest[3]):(parent_inest-=onest[3]))) 70859 ./ble-syntax.sh:2585: (((klen=stat[k])<0)) && continue 70860 70861 bash-4.2 のバグは式の構造だけに依存しているので、文脈によらずに実際のその式を実行してみれば良い。 70862 現に問題になっていた式をそのまま bash-4.2 の対話シェルから実行してみると segfault が再現する。 70863 上で見つかった物についてチェックする。1つ目の式構造は大丈夫だった。2つ目も大丈夫。3つめも大丈夫。OK 70864 70865 因みに一番最初に見つけて修正した ble-syntax.sh:1401 についても bash-4.2 はクラッシュした。 70866 結局 2 箇所修正が必要だったという事である。 70867 70868 2017-05-20 70869 70870 * ble を再度 source すると history を再度読み込む様になるのは何故か。 [#D0392] 70871 既にロードされている時は無視するのではなかったか。 70872 70873 恐らく ble-attach を呼び出しているせいである。 70874 既に ble-attach されている状態で再度 ble-attach している場合何が起こるのか。 70875 現在は状態のチェックを行っていないがこれには理由はあっただろうか。 70876 70877 ble-decode-attach は内部で現在の状態を記録しているので 70878 重複して呼び出しても実際には処理は実施されない。 70879 70880 ble-edit-attach は内部でのチェックは行っていない。 70881 ここで history の情報を初期化しているので、 70882 これが原因で再度読み込む様になっているのだろう。 70883 history を再度読み込む必要があるのは、 70884 detach している間に実行したコマンドがあるかもしれず、 70885 その為に history と ble の管理している履歴情報に 70886 ずれが生じているかもしれないためである。 70887 なので既に attach しているかどうかの情報を保持する必要がある。 70888 70889 ble-attach 自体で既に attach しているかどうかの情報を管理する様にしたい。 70890 既に _ble_edit_detach_flag という変数がある様だがこれは何のために使っているのだろう。 70891 →これは次にキーに対する処理が終わる時にシェルを終了するかどうかを管理するのに使う。 70892 通常時は常に空欄になっている変数である。この変数は使えない。 70893 従って新しい変数を導入する必要がある。ble-decode-attach と同様に管理すれば良いだろう。 70894 そして ble-decode-attach の使っている変数 _ble_decode_bind_attached は単純に局所的に 70895 使われているだけであるのでこれで問題ないだろう。 70896 70897 70898 2017-04-21 70899 70900 * [2017-04-15] bash-4.4: C-x ? のキーバインドができなくなっている? [#D0391] 70901 70902 bash-4.2 以下と同様に C-x ? だけ特別に処理する様に戻した。 70903 結局、C-x ? に特別な処理が必要ないのは bash-4.3 だけということであった。 70904 70905 2017-03-13 70906 70907 * [2017-03-11] LANG=C./a 等の様に locale に変な文字列があると毎回エラーメッセージが表示されてうるさい。 [#D0390] 70908 エラーは抑制するべきではないか。 70909 70910 概ね、LC_COLLATE=C command &>/dev/null とすれば良い様だが、 70911 function ble/util/is-stdin-ready { IFS= LC_ALL=C read -t 0 &>/dev/null; } 70912 としてみたが LC_ALL に変な値が入っている時のメッセージは抑制できなかった。 70913 function ble/util/is-stdin-ready { IFS= LC_ALL=C read -t 0; } &>/dev/null 70914 の様にすれば大丈夫だった。 70915 70916 # そもそもの問題として read -t 0 の仕様として 70917 # IFS や LC_ALL を設定する必要があるのかどうかは分からないが。 70918 70919 2017-03-05 70920 70921 * complete.sh: bug 補完対象に ` \n \t が含まれる場合にエスケープされていなかった。 [#D0389] 70922 70923 * ble-core: ble_util_upvar_setup で local ret するべきなのでは。 [#D0388] 70924 ble_util_upvar で $ret を参照しているので。 70925 70926 調べてみた所、全ての ble_util_upvar_setup 使用箇所で結局 local ret を宣言している。 70927 また、ちゃんと ble_util_upvar_setup は ble_util_upvar と対になって使用されている。 70928 従って local ret を ble_util_upvar_setup の中に入れるのが適切である。 70929 70930 70931 * syntax: ヒアドキュメント: << <<- の違いや EOF 'EOF' の違いが働いているかどうか確認する。 [#D0387] 70932 70933 <<- が効いていない。というか nparam のフラグが I になっていない。 70934 と思ったら参照している ctx が nest-pop 後の ctx だった。 70935 nest-pop 前の ctx を octx に保存して、その octx を用いて判定する事にした。 70936 70937 EOF と 'EOF' の違いに関してはちゃんと期待通りに動いているので良かった。 70938 70939 * color: 古い仕組みの layer とそのアダプターの機能は流石に削除してよいのではないだろうか。 [#D0386] 70940 70941 ble-syntax-highlight+* 云々という関数は全て古い仕組みである。 70942 また変数 bleopt_syntax_highlight_mode は古い仕組みに置ける highlighter 選択の為に用いられる。 70943 これらの仕組みはアダプター ble-highlight-layer:adapter/* から参照され、 70944 アダプターは _ble_highlight_layer__list=(plain adapter) 等とする事で登録される。 70945 70946 一方でアダプターは zsh 方式の highlighter を import するのにも使えるのではないか? 70947 という気がしないでもない。これ自体そんなに長いコードでもないので残しても良いかもしれない。 70948 しかしその様に考えると実装例も一緒に残しておいた方が良いという事になり、 70949 結局古い仕組みも残しておくという事になりはすまいか。 70950 だとすれば思い切って此処で捨ててしまうのの方が良いようにも思う。 70951 70952 うーん。highlighter のサンプルとして別ファイルに残しておくという手もあるかもしれない。 70953 というかそれが良いような気がしてきた。 70954 70955 * IFS guard [#D0385] 70956 70957 所でよく考えてみたら IFS をユーザが変更した場合には色々と大惨事が起こるのではないか… 70958 bind 及び exec の部分でちゃんと local IFS=$' \t\n' を設定する様にしなければならない。 70959 →試してみた所やはり大変な事になる…。これは後で最優先で対処しなければならない。 70960 70961 何処で対処するのが良かろうか。 70962 例えば関数内で local IFS= を設定する様にするというのが一つの手である。 70963 もう一つはコマンドを実行する直前に IFS を戻して、 70964 コマンドを実行した直後に IFS を保存するという様にする方法である。 70965 70966 シグナルハンドラを設定する場合はどうだろうか。 70967 シグナルハンドラの中ではユーザの設定した IFS が見えて欲しい。 70968 そういう事を考えると local IFS= が良い様な気がする。 70969 一方で exec:exec では結局 IFS を保存・復元しなければならない。 70970 実際の所シグナルハンドラの中にいる時は LINENO 等の値も変な物になっているので、 70971 IFS だけに拘っても仕方がないかもしれない…と言いつつ IFS は影響範囲が大きいので 70972 やはりシグナルハンドラの中であってもユーザの期待する物になっているべきである。 70973 70974 うーん。以下の項目について対処すれば良いだろう。 70975 70976 - 関数内で local IFS= を設定する。 70977 1. bind から呼び出される関数 70978 2. _ble_decode_bind_hook から呼び出される関数 70979 3. シグナルハンドラから呼び出される関数 70980 → これは trap を検索すれば良い。 70981 4. 初期化時に呼び出される関数 (ble-attach 及びロード時に強制的に実行する関数たち) 70982 →これは漏れがあると行けないし汚くなるのが嫌なので、 70983 ble.pp で IFS を保存して自分の物に設定し最後に復元するというので良いだろう。 70984 - exec:exec では IFS の保存・復元を実行する 70985 70986 [書き換え] 70987 70988 - ble-decode-byte:bind 70989 - ble-edit/exec:gexec/.begin 70990 - ble-edit/exec:gexec/.eval-prologue 70991 - ble-edit/exec:gexec/.eval-epilogue 70992 - ble-edit/exec:gexec/.end 70993 - ble-edit/exec:gexec/.eval-TRAPDEBUG 70994 - ble-attach 70995 70996 以下の関数は明らかに影響がないので IFS の設定は省略する。 70997 - ble-stty/TRAPEXIT 70998 - ble-edit/exec:gexec/.eval-TRAPINT 70999 - ble-edit/exec:exec/.eval-TRAPINT 71000 - ble-edit/exec:exec/.eval-TRAPDEBUG 71001 - ble-detach 71002 71003 ble.pp では ble/.check-environment の直前で IFS を設定し、 71004 ble-attach の直前で IFS を復元する。 71005 71006 exec:exec は関数内でユーザコマンドを実行するため IFS を復元・保存しなければならない。 71007 _ble_edit_PS1 と同じ箇所で同様に復元・保存すればよいだろう。 71008 但し ble-edit/attach, detach に関しては bleopt exec_type=exec の場合のみに 71009 _ble_edit_IFS への保存と復元を行う事にする。 71010 71011 - ble-edit/attach 保存 71012 - ble-edit/detach 復元 71013 - ble-edit/exec:exec/.eval-epilogue (保存) 71014 - ble-edit/exec:exec/.eval-recursive (復元) 71015 71016 取り敢えず動いているので良い事にする。 71017 未だ何処かに漏れがある可能性もあるが、 71018 IFS に変な値を入れる人もそんなにいないだろう。 71019 71020 * memo.txt: 項目に番号を振っても良いのではないだろうか。 [#D0384] 71021 71022 過去の項目について参照する機会も度々ある。 71023 少なくとも Done に送られた項目に対して番号を振るというのはありなのではないだろうか。 71024 71025 いま確認してみると比較的複雑な問題解決に関しては、ごく初期の頃に X1-X6 の番号を振って記録している。 71026 しかしより単純な物については番号が振られていないし、また X1-X6 の番号づけもすぐに廃れている。 71027 今度改めてこれらを整理し、大小に拘らず番号を機械的に振っていくというので良いのではないだろうか。 71028 また過去の記録の形式と現在の記録の形式を合わせるというのにも役立つ。 71029 71030 取り敢えず番号を付けた。この項目は #D0384 である。 71031 71032 * syntax: select name [in ...]; do ... done [#D0383] 71033 71034 考えてみたら select には対応していなかった。 71035 71036 試してみると select name do ...; done の形式でも OK の様だ。 71037 また select name; { ... } の形式も可能である。 71038 マニュアルには書かれていないが。 71039 実の所 for と殆ど同じである。 71040 違うのは単語が一つ以上必要という事と、 71041 for ((;;)) の形式がないという事である。 71042 71043 * syntax: bug 6b84ee7 の修正はバグである。元々 CTX_ARGX0F という特殊な文脈値を用いて [#D0382] 71044 71045 特別に { を受け付ける様にしていたのであった。なので、CTX_CMDXE にするのではなくて、 71046 CTX_ARGX0F の処理の方で do も受け付ける様に修正するべきであったのである。 71047 71048 と思って CTX_ARGX0F の方で { に一致しなかったら CTX_CMDXE にする様にしてみたが、 71049 いろいろ考えて見るに CTX_CMDXE と同様に処理する CTX_CMDXD という物を用意する方が良いという事になった。 71050 結局 CTX_ARGX0F を CTX_CMDXD という名前に改めて実際の文脈値として取り扱う事になった。 71051 71052 * syntax: ヒアドキュメント (here documents) 対応 [#D0381] 71053 71054 > * [2015-02-16] ble-syntax.sh ToDo 71055 > 71056 > - Here document 71057 > Here document は次の行から始まるというのが厄介である。 71058 > 71059 > 一旦始まってしまえば Here Document の処理は比較的簡単であろう。 71060 > <<EOF の形式では $() 及び `` だけ特別に処理を行えばよい。 71061 > <<'EOF' 等の形式ではそのまま EOF を探せばよい。 71062 > 71063 > 始まる迄は何処かで待ちになっている HEREDOC の情報を記録する必要がある。 71064 > そして改行が現れた際にヒアドキュメントを開始するのである。 71065 > ヒアドキュメントは quote の中などでは始まらない。 71066 > 結局 CTX_CMD, CTX_ARG 等で改行が来た時にヒアドキュメント開始を調べる感じだろうか。 71067 71068 [考察] 71069 71070 何処に開始待ちになっている HEREDOC を記録するか。新しい変数を導入するのか。 71071 或いは、既存の変数またはネストに記録を行うのか。 71072 71073 a ネストに記録するのだとすると新しく HEREDOC を導入する為だけに新しいネストを 71074 導入しなければならない。文法構造の変化がどの様になるかはちゃんと考えていないので分からないが、 71075 本来あるべき構造と離れるために変なことになりそうに思うのでこの方法は良くない。 71076 71077 b だとすると新しい変数を導入して状態を記録するしかないように思われる。 71078 71079 因みに現在使っている変数としてどの様な物があるか改めて確認してみる事にする。 71080 結局 stat (ctx wlen wtype nlen tclen tplen) に格納される情報が全てである。 71081 その他の情報は復元の対象にならないから、これに依存した解析にはできない。 71082 stat の各要素に対応する変数は実際には関数 ble-syntax/parse/generate-stat にて 71083 変数 ctx wbegin wtype inest tchild tprev から生成される。 71084 71085 ctx wbegin wtype 等はヒアドキュメントとは異なる寿命を持つ構造なのでこれにヒアドキュメントの情報を格納する事はできない。 71086 inest tchild tprev は何れも位置を表す変数であるからこれにヒアドキュメントの文字列を格納する事もできない。 71087 ただ、文字列を格納する代わりにヒアドキュメントの word の位置を記録するというやり方もある。 71088 その方がシフトも簡単だろう。更に、入れ子構造も考慮に入れて改行が現れたらヒアドキュメントを開始するという事にするのだとすれば、 71089 tprev と同様の取り扱いにするのが良いようなきがする。シフトについても tprev と同様で良いのではないだろうか。 71090 やはりこの様に考えてみると解析用の変数を追加する事は免れない。 71091 71092 a 新しい変数の値を文字列で記録するのだとすれば shift の必要性はない。 71093 また、後々にヒアドキュメント以外の情報を格納したくなった時の拡張も比較的簡単にできる様になると思われる。 71094 同じ変数の中に文字列として連結して情報を格納できるからである。 71095 71096 b もしヒアドキュメントの単語の位置を記録するのだとすれば shift は tprev と同様にすれば良い。 71097 しかしよく考えてみれば単語の内容に依存するのであるから stat が一致しているかどうかを判定するために、 71098 その位置にある単語の内容に関しても一致するかどうか判定しなければならなくなる 71099 (丁度 inest から nest を辿っていって全て一致しているかどうかを確かめる時の様に)。 71100 更に毎回単語を読み取ってそこから終端の記号を確認しなければならない。大変である。 71101 71102 この様に考えると直接文字列で保持するのが良い。単語の内容に依存した参照である必要は全くない。 71103 71104 | 実は nest もこの様に保持するという手があったかもしれない。ただそれだと複雑なネストの場合に、 71105 | ネスト構造を記録する変数の内容がどんどん長く・複雑になっていくという問題があったという事だろうか。 71106 | 或いは、ネスト構造を判定する度に情報を毎回抽出するのが面倒?という事だろうか。 71107 | しかし、思うに nest で重要なのはその時点での状態だけであって、 71108 | nest の開始位置というのは実はそれ以降の解析に影響を与えない。 71109 | 更に shift の必要もないし、やはり nest も文字列情報として記録したほうが良かったのではないかという気がしてくる。 71110 | 現在 nest 構造を記録する度に 7 つの変数を記録しているが、 71111 | 別に一回の nest で 7 個ずつ変数を使うというので問題ない気がする。 71112 | うーん。これに関しては以下で考察を与える: 71113 | 71114 | cf. #D0377 "2017-03-04 syntax: [考察] _ble_syntax_nest の取り扱い。" 71115 71116 さて変数を追加する場合には何処を修正しなければならないだろうか。 71117 先ず stat と nest のフィールドの数は増加させなければならない。 71118 71119 nest に関しては _ble_syntax_nest を参照している箇所を確認すれば良い。 71120 stat に関しては沢山ある…。 71121 面倒なので先に変数を増やししまってから少しずつ変更していく事にする。 71122 71123 新しく増やす変数はどの様な名前にするのが良いだろうか。 71124 71125 現状の考えでは nest level に固有の文字列であり、 71126 nest-push すれば空になり、nest-pop すればまた復元するという物を考えている。 71127 (この様な動作は、将来的な do done や { } の対応を取る場合にも都合が良いだろう。) 71128 従って、その事を反映して n* という名前にするのが良さそうである。 71129 解析途中状態を記録するための一般の変数名として良いのは何だろうか。 71130 例えば Emacs の font-lock では文章中に text-property を設定できて、 71131 その text-property を様々な解析状態の記録に利用する事ができる。 71132 Visual Studio の AddIn を作る場合 (着色を設計する場合) はどうであっただろうか。 71133 これは行毎に何らかの値を保存できる様になっていたはずだが変数名までは覚えていない。 71134 しかし何か System.IntPtr だった様な気もする。LPARAM, WPARAM の様な物だろうか。 71135 その様に考えると nparam という名前で良いような気がしてきた。 71136 71137 →nparam にする。 71138 71139 [実装] 71140 71141 1 変数の追加 71142 71143 nparam という変数を導入すると共に先ずは stat 関連の修正を行う。 71144 比較的変更は少なくて済むような印象である。 71145 基本的には初期化の部分、ble-syntax/parse/generate-stat の修正と、 71146 ble-syntax/parse/shift.stat をすれば動作する。 71147 更にデバグ用の出力のために ble-syntax/print-status/stat.get-text 71148 (今回 stat の内容を文字列化する処理の部分を切り出して作った関数) を修正すれば良い。 71149 nest に関しても同様でそんなに大局的な変更は必要ないようである。 71150 つまり、nest-push, nest-pop, nest-type を抑えれば良い様だ。 71151 nest-type の実装を考えると ntype は一番最後の引数にするのが良い。 71152 だとすると nparam='' の時に nparam を記録する際には何か代替になる値を指定しなければならない。 71153 ntype と統一するのであれば none という値にするのが良い。格納する時と取り出す時に気をつければ良い。 71154 71155 →取り敢えず nparam という解析状態変数の追加と stat/nest の変更は完了した。 71156 71157 2 次に here documents 指定があった場合に nparam を設定するコードを追加する。 71158 71159 これは特別な文脈値 RDRH を導入して処理する事にする。 71160 RDRH の単語の終了時に nparam を設定する。 71161 71162 quote した時に指定する事のできる文字列 71163 71164 | 所で here document の quote で空白を含む文字列を指定した場合はどうなるのか。 71165 | →試してみた所、何と delimiter に空白を含ませる事も可能な様だ。 71166 | もっと色々試してみるとセミコロンなども含める事ができる。 71167 | stat や nest に格納する場合には空白類は含められない。 71168 | という事は nparam に設定する際に空白類はエスケープしなければならない。 71169 | 或いは stat や nest に設定する時にエスケープをするか。 71170 | stat/nest に設定する時にエスケープをするというのだと色々の箇所で対処をしなければならず面倒である。 71171 | なので初めから nparam には空白類が入らない様に構成する方が現実的である様に思う。 71172 | 71173 | 更に delimiter に改行が含まれていると、 71174 | 2行に渡って delimiter を指定したとしてもそれには引っかからず 71175 | 最後まで here documents が終わらないと解釈され、警告が出る (でも警告なのでコマンド実行は為される)。 71176 | つまり delimiter の判定をする際には行毎に切って、 71177 | その上で期待する delimiter との比較を行わなければならない。 71178 | これは step3 で処理する。 71179 71180 まとめると、何でも指定できる。 71181 空白を含める事もできるし改行を含める事もできる。 71182 但し、改行が含まれている場合には決して終端に一致する事はできない。 71183 どうやら終端文字列は行毎に判定される様だからである。 71184 71185 nparam に delimiter を格納する為にはエスケープが必要になる。 71186 71187 here documents word の bash の解析方法の確認 71188 71189 | 然し、本当に bash は $ を特別扱いしないという様な parse の仕方をしているのだろうか。 71190 | もしかすると通常通りに parse してその上で一番外側の "" だけを除去するという事をするのかもしれない。 71191 | その場合にはまた一層処理が面倒である。と思って試してみた。 71192 | 71193 | << "$(echo "lll")" 71194 | 71195 | の様に指定すると終端の文字列として '$(echo lll)' を要求する様だ。 71196 | つまり予想通りに $ を認識していないという事になる。多分。もうひとつ試してみる。 71197 | 71198 | << "$(echo "(lll)")" 71199 | 71200 | もし入れ子を認識していないのであれば裸の () が現れるのでエラーになるはず。 71201 | もし入れ子を認識しているのであれば構文エラーにはならずに '$(echo (lll))' 全体を終端文字列として要求するだろう。 71202 | →何と '$(echo (lll))' を終端文字列として要求して構文エラーにはならなかった…。 71203 | 71204 | << ""(lll)"" 71205 | 71206 | で試すとちゃんと構文エラーになる。つまり、ヒアドキュメントの word には () が指定できる等ということでも無いようだ。 71207 | つまり、これらの動作から推測するに bash の解析は、先ず初めに $() の入れ子なども考慮に入れて解析を行う。 71208 | その後で $() の置換を実行せずに字面でクォート除去に進む。という事なのだろう。 71209 | だとすると解析時とクォート除去時で不整合が生じる様なケースを人為的に作成する事ができる様な気がする。 71210 | 試してみる。 71211 | 71212 | << "$(echo "'")" 71213 | 71214 | これを実行したらエラーにはならなかったが終端文字列として '$(echo ()")"' という物を要求する様になった。 71215 | つまり ' の終端が欠けている形と見なされている様だ。この動作は先程の bash の動作の推測と合致する。 71216 71217 まとめると bash はコマンド置換などの入れ子も考慮に入れて解析を行うが、 71218 最終的には入れ子構造は無視して字面で quote 除去を実行する。 71219 中途半端な '' "" などの quote があった場合には最後まで囲まれていると見なす。 71220 除去する quote は \? '' "" $'' $"" である。 71221 71222 うーん。入れ子も考慮に入れた解析は実はそんなには難しくないような気がする。 71223 結局のところ $( が来たら対応する括弧 ) まで読み飛ばすという様に実装すれば良いのだ。 71224 内部の細かい文法規則まで追跡する必要はない。 71225 最終的には専用の文脈値を用意するという方針で行くのが良い様に思う。 71226 現状では、もっと素朴な実装をしてしまった。通常の RDRS と同様の実装に戻す事も可能であるが 71227 勿体ないので暫定的に現状の実装で進める事にする。 71228 71229 もっと bash で試してみると 71230 71231 << $(echo ${hello/)/))}) → 終端文字列 '$(echo ${hello/)/))})' 71232 71233 という事になった。つまり、(1) quote が全然なくてもちゃんと入れ子を含めて単語を認識している。 71234 (2) $() の括弧の入れ子だけではなくて ${} の入れ子についても追跡をしなければならない。 71235 これを考えると従来の方法で解析しておいた方がやはり良いのかもしれない…。 71236 71237 後で折を見て従来の方法に戻す事にする。 71238 取り敢えずは here documents の対応を完成させる事を目指す。 71239 71240 % さてここで一つの懸念に思い至った…こうした複雑な解析の結果を nparam に指定した後で 71241 % 保存されてそれから shift が起こった時に変な事にならないかという事である。 71242 % これは考えて見るに大丈夫である。というのも結局はやはり過去の情報しか参照していないという事。 71243 % そして shift などが起こって word の内部で更新が起こったとしても、 71244 % 結果として起こるのは nparam の不位置に依る stat の不一致であり、 71245 % "解析が殆ど全部やり直しになる" という事以外の問題点は発生しない。 71246 % 解析がやり直しになることについては here documents である以上は避けられない事なので気にしなくて良い。 71247 % →気にしなくて良い。 71248 71249 2.1 quote 除去も実装しなければならない。 71250 71251 →ble-syntax:bash/ctx-heredoc-word/remove-quotes に実装した。 71252 簡単にテストを実行してみる。 71253 OK ble-syntax:bash/ctx-heredoc-word/remove-quotes fire; echo $delimiter 71254 OK ble-syntax:bash/ctx-heredoc-word/remove-quotes "\"\$(echo \"(fire)\")\""; echo $delimiter 71255 OK ble-syntax:bash/ctx-heredoc-word/remove-quotes "\"\$(echo \"(fire)\")"; echo $delimiter 71256 OK ble-syntax:bash/ctx-heredoc-word/remove-quotes "\"\$(echo \"(')\")\""; echo $delimiter 71257 OK ble-syntax:bash/ctx-heredoc-word/remove-quotes '\[\$hello\`\]'; echo $delimiter 71258 NG ble-syntax:bash/ctx-heredoc-word/remove-quotes '"\[\$\"\`\\\]"'; echo $delimiter 71259 変だ。\$ (など) が $ (など) にならない 71260 → OK str=${str//"$b"/$a} の様にしなければならなかった。修正した。 71261 OK ble-syntax:bash/ctx-heredoc-word/remove-quotes 'hello$'"'\e[1mthis\e[m'"'world'; echo $delimiter 71262 71263 取り敢えず良さそうである。 71264 71265 追記: 終わっていない "" or '' で中途半端な \ が末尾にある場合にはどういう扱いになるのだろう。 71266 試してみると…。 71267 71268 $ eval 'echo << "$(echo '\''"\'\'')"\' 71269 bash: 警告: ヒアドキュメントの 10 行目でファイル終了 (EOF) に達しました (`$(echo '')' が必要) 71270 $ ble-syntax:bash/ctx-heredoc-word/remove-quotes '"$(echo '\''"\'\'')"\'; echo "$delimiter" 71271 $(echo '')\ 71272 71273 bash の振る舞いとしては終わっていない \ は消えてなくなる様である。 71274 一方で、現在の remove-quotes の実装だと \ が残ってしまう 71275 →直した。 71276 71277 2.2 nparam に設定する時の escape を実装する。 71278 71279 どの様にエスケープするのが良いだろうか。 71280 先ず除去しなければならないのは空白類である。つまり、空白・タブ・改行である。 71281 更に nparam 自体のフィールドセパレータも考慮に入れなければならない。 71282 今まではコロンをセパレータに使おうと考えていたが…。 71283 71284 また復元する時に簡単にできる様にするには \\ でエスケープして 71285 $'' で戻すという様にするのが良いかもしれない。 71286 パラメータ展開の置換 ${var//a/b} を繰り返すよりは、 71287 一回 eval を実行してしまった方が早かろう。 71288 ただ、変な文字が含まれていない限りはエスケープは必要ないので、 71289 変換方法についてはそんなに気にする事もないかもしれない。 71290 然しながら何れにしても必ずエスケープ表現は定めなければならないので、 71291 \ でエスケープする様にすれば良いだろう。実際に復元を行う場合に、 71292 71293 a if [[ $str == *\\* ]]; then str=${str//a/b}; ...; fi 71294 b eval "str=\$'$str'" 71295 71296 のどちらが良いのかというのは表現方法に関係なく選択できる。 71297 但し b を選ぶとすると追加で ' もエスケープしなければならない。 71298 しかしそうだとしても b の方が良い様な気がする。 71299 71300 また nparam 自体のフィールドセパレータに関しては、 71301 完全に変換を行って除去しなければならない。 71302 例えば 8 進数表現にするなどの方法で。 71303 しかし例えばコロン : を使うとなるとその 8 進表現が何であるかを確認する必要が出てくる。 71304 適当に ASCII C0 の FS 等を使うというのでは駄目なのか。 71305 しかし FS だって実際の描画文字と被るかどうかわからない…と言いつつ C0 領域が ASCII である 71306 事を仮定した様なコードは既に ble の中に沢山ある。という事はやはり FS で良いか。 71307 でも、一方でコロンの 8 進表現だって ble/util/s2c を使えば簡単に計算できる。 71308 何処かにキャッシュしておけば良い。或いはもう ASCII を仮定してしまっても良いかもしれない。 71309 うーん。まあ、取り敢えず FS を使うという方針で行くことにする。 71310 →FS は \034 である。もしくは ^\ である。term.sh に _ble_term_fs として追加する事にした。 71311 71312 実装した。関数 ble-syntax:bash/ctx-heredoc-word/escape-delimiters である。 71313 71314 更に nparam への値の設定も行う。 71315 ble-syntax/print-status/stat.get-text での FS のエスケープも実装する。 71316 ble_debug=1 bash で確認する限り、期待通りにエスケープ・nparam への設定が動いている様子である。 71317 71318 71319 3 コマンドの解析の文脈で改行が来た時に nparam に here documents が指定されていれば 71320 here documents の文脈値に移行する。 71321 71322 3.1 先ず初めに here documents の文脈値を実装しなければならない。 71323 71324 取り敢えず実装した。nparam として専用の特別な形式の値を持たせる事にした。 71325 ここにヒアドキュメントの属性や終端文字列を格納する。 71326 71327 3.2 改行で CTX_HERE0 に入る様にする。 71328 71329 これは ctx-command だけで良い? 71330 71331 どのタイミングでヒアドキュメントが始まりうるのかを確認しなければならない。 71332 先ず \<newline> でヒアドキュメントが始まる事はない。 71333 ${} $() $(()) の内部で始まる事もない。 71334 配列の arr=() の中では始まる。 71335 71336 ```bash 71337 cat <<EOF; \ 71338 echo line2 ${hello# 71339 } line2b $( 71340 echo line2c 71341 ) $(( 71342 1+1 71343 )) 71344 hello test1 world 71345 EOF 71346 ``` 71347 71348 多分、ctx-command と ctx-values で対応すれば良い。 71349 取り敢えず ctx-command の中を見てみる。 71350 ble-syntax:bash/ctx-command/.check-delimiter-or-redirect で改行を処理している。 71351 この関数の呼び出し元は ble-syntax:bash/ctx-command だけなので 71352 此処でそのまま here documents に突入して問題ないだろう。 71353 71354 3.3 後は ctx-values でも同様に処理すれば良い。 71355 71356 と思ったら問題が生じる。ctx-values は入れ子レベルを形成する。 71357 入れ子レベルを形成するのは復帰時にまた元の文脈に戻る為である。 71358 元の文脈は 2 種類存在する (VRHS 及び ARGVI)? 71359 この2種類の対応する VALX, VALI を導入しても良いが、別の方法を取る。 71360 71361 nest-push nest-pop の際に nparam を持ち越す様にする。 71362 そのままだと規約が分かりにくいので enter/leave という関数を作って、 71363 それを介して nest-push nest-pop を行う様にする。 71364 71365 取り敢えずは動いている様子である。 71366 71367 取り敢えず動いているので、初期実装として一旦保存する事にする。 71368 71369 2017-03-04 71370 71371 * syntax: bug: } fi done 等の直後に ; を置けなくなっている。 [#D0380] 71372 71373 * syntax: 実は for name do ...; done という形式も可能の様だ。 [#D0379] 71374 71375 * syntax: 実は for (()) の直後に do が来ても良いようだ。 [#D0378] 71376 http://qiita.com/yz2cm/items/bc5726e8aef0f2e6906e を見て気付く。 71377 71378 for ((i=0;i<10;i++)) do echo $i; done 71379 一方で while(()) の直後は駄目。 71380 71381 for (()) の直後だけは特別な文脈と考えるのが良さそうだ。 71382 while { true; } do done の } の直後と同様の文法的な取り扱いなのであろうか。 71383 取り敢えず fi を指定した時のエラーメッセージを観察してみると同じである。 71384 71385 文脈的には do しか来てはならない所を他の一部のコマンドも許すというのは変かもしれないが、 71386 ((;;)) を抜けた直後の文脈は CTX_CMDXD という事にする。 71387 71388 * syntax: [考察] _ble_syntax_nest の取り扱い。 [#D0377] 71389 71390 実は nest 構造を一つの文字列にまとめてしまった方が解析が楽になるのではないか。 71391 71392 - 現在は inest の情報を頼りに stat を比較する度に nest 構造を掘り出している。 71393 しかしそれなば flat に一つの変数に情報を詰め込んでも良いのではないだろうか。 71394 71395 - shift についても複雑な処理を行う必要はない。というか shift の必要はない? 71396 入れ子構造の保持には shift の必要はないが、よく考えてみれば 71397 単語の位置などの木構造を構築するために nest の中に単語の開始位置などの情報も記録されている。 71398 これらを shift する必要がある。寧ろ inest の shift だけで良かった所が 71399 現在の全ての nest 階層でのシフトが毎回必要になる。寧ろ面倒になる可能性がある。 71400 71401 - 以降の解析に影響を与えるのは nest 構造の中身だけであって inest は関係ない。 71402 言い換えれば、影響をあたえるのは現在どの様な入れ子になっているかの情報だけであって、 71403 現在の入れ子構造がそれぞれ何処で開始したのかという情報は関係ない。 71404 71405 考えて見るに、初めから nest 構造を一つの文字列にまとめて実装したほうが簡単だったかもしれない。 71406 一方で、shift の取り扱いなどで余計なコストがかかる様になるので、 71407 既に nest を inest で実装する様にしてしまった現状、 71408 既存のコードを捨てて nest 構造を一つの文字列にまとめる様に書き換える利点はないように思われる。 71409 71410 2017-03-02 71411 71412 * syntax: } の直後には then else elif do も来て良い。 [#D0376] 71413 但しこれらの直後は文脈はそれぞれの物に変化する。 71414 71415 * [2016-08-06] syntax: extquote と "${}" の入れ子に関して [#D0375] 71416 [cf memo/D0375.quote-in-param-expansion.sh] 71417 71418 "${var# ... }" などの中の '' $'' $"" は無効になる。 71419 では "${var:-${var: ... }}" などの入れ子になっている場合はどうなのか? 71420 現在の実装ではこの様な入れ子の場合には quote が有効になってしまっている。 71421 71422 | どの様な状況で '' $'' $"" が無効になるのか、入れ子になっている場合も含めて調べる。 71423 | 少なくとも echo "${x:-${arr:'1'}}" の quote '1' は無効 (つまりそのまま "'1'" として解釈される) のようだ。 71424 | 71425 | より厳密な判定方法について調べる。 71426 | 71427 | $ hello=check-hello; echo "${hello#check}" 71428 | $ hello=check-hello; echo "${hello#'check'}" 71429 | $ hello=check-hello; echo "${hello#$'check'}" 71430 | $ hello=check-hello; echo "${hello#"check"}" 71431 | 71432 | 以上は全て期待通りに動作する。つまり quote 除去は実施される。result="${...}" の形式でも同様であった。 71433 | 71434 | より詳しく調査してみる [cf memo/D0375.quote-in-param-expansion.sh] 71435 | 71436 | 実は算術式として解釈する時だけの問題なのではないか。 71437 | 71438 | というか現在の実装では $(()) の中の "" や '' も許容しているが実際の bash では許されない。 71439 | 実際の bash で "" や '' が許されるのは (()) の時である。 71440 | arr['1234'] も許される。${arr['1234']} も許される。一回整理した方が良い。 71441 | 71442 | OK: (('1234')) / arr['1234'] / ${arr['1234']} / arr=(['1234']=1) 71443 | NG: ${var:'1234'} / $(('1234')) / $['1234'] 71444 71445 色々調べた結果をまとめてみる。 71446 71447 - 先ず初めに算術式 ${var:...:...} / $((...)) / $[...] については、 71448 如何なる quote も有効にはならない。但し例外はあって、 71449 "${var:...:...}" でかつ shopt -q extquote の場合には $'' $"" の quote のみ許される。 71450 71451 - またそれ以外のパラメータ展開の中身 (${var#...}) に関しては、 71452 '' と "" は何時でも有効である。そして ${} が裸の場合には $'' $"" も有効である。 71453 "${}" の場合には shopt -q extquote の場合にのみ $'' $"" が有効になる。 71454 71455 - 更に入れ子になった場合の振る舞いはどうだろう。 71456 試して見た限りでは "${var#...}" / "${var:...}" の中に 71457 更に ${} を入れた場合は "${}" と同じ振る舞いになる様である。 71458 一方で "$(())" の中に ${} を入れた場合は ${} と同じ振る舞いになる様である。 71459 71460 取り敢えず入れ子になっていない場合の振る舞いについて実装する。 71461 算術式については算術式を記述している箇所によって振る舞いが異なるので、 71462 その文脈を引き継げる様にしなければならない。 71463 現在の算術式の実装では基本的に ntype を参照しながら括弧を数えているので、 71464 (これまで通り) この ntype を活用して quote の有効・無効を判定するのが良いだろう。 71465 現在は (()) の中身と $(()) の中身で ntype を区別していないのでそれを区別する必要がある。 71466 同様に [] のネストと $[] の中身で ntype を区別していないのでこれも区別する。 71467 その為に新しい ntype '$[' と '$((' を導入する。'NQ(' も導入する。 71468 71469 ここで現在の ntype について整理しておく。 71470 71471 '${' PARAM パラメータ展開の修飾 (EXPR に流れる可能性あり) 71472 '"${' PARAM パラメータ展開の修飾 (すぐ外が CTX_QUOT の場合) (EXPR に流れる可能性あり) 71473 'v[' EXPR パラメータ展開の配列添え字 71474 '$((' EXPR $(()) の中身 (ARGX0 に流れる可能性あり) 71475 '$[' EXPR $[] の中身 71476 '$(' CMDX1 $() の中身 71477 '' QUOT "" の中身 71478 '(' CMDX <() の中身 71479 ctx=? PATN @() の中身 71480 nest PATN @() の中身 71481 '' PATN case in () の中身 71482 '('/'NQ(' EXPR 式の括弧の入れ子 71483 '[' EXPR 式の括弧の入れ子 71484 '' CONDX [[ ]] の中身 71485 '(' CMDX1 function f () の中身 (エラー) 71486 '' PATN f () の中身 (エラー) 71487 色々 RDR? リダイレクトの右辺 71488 (色々 = > &> >> &>> >| >& < <> <& << <<<) 71489 (これに応じて文脈も色々 RDRF, RDRD, RDRS, ) 71490 '(' CMDX1 () の中身 71491 '((' EXPR (()) の中身 71492 '' PATN echo ... () の中身 71493 'a[' EXPR a[]= の中身 71494 '' VALX a=() の中身 71495 'd[' EXPR a=([]=) の中身 71496 71497 | 更に () [] のネストに際しても、$[ / $(( の中身であるかどうかを 71498 | 伝播させなければならないのではないだろうか。 71499 | (※ ${var:} の中身はネストしないのでこの点は考慮しなくて良い。) 71500 | →と思ったら $['1+2'] はエラーになる一方で $[a['1+2']=3] はエラーにならない様だ。 71501 | つまり [] のネストに関しては必ず配列添え字であって内部ではあらゆる quote が許される。 71502 | $[] の中身であるかどうかの情報は必要なく一律に今まで通りに扱って良い。 71503 | →逆に言えば $(()) の中身であっても途中で [] が現れたならば、その中では quote できる。 71504 | 現在の実装では $(()) の場合には () の入れ子だけを数え、 71505 | $[] の場合には [] の入れ子だけを数えという様に取り扱っているが特別な処置が必要である様に思う。 71506 | 71507 | うーん。echo $(('1+2))')) という物を bash に食わせると 71508 | $(( / '1+2))' / )) というまとまりで解釈されて、 71509 | '1+2))' という算術式の評価の中で構文エラーになる。 71510 | 決して $(( / '1+2 / )) / ')) という分割になる訳ではない。 71511 | つまり字句レベルではやはり quote は解釈しているけれども 71512 | 算術式評価がその quote を受け付けないと考えるべき? 71513 | だとすると ble はどの様に動作するべきであろうか。 71514 | 自然に考えれば算術式評価に渡る前の字句的なレベルでのチェックにするのが良い。 71515 | もし算術式評価の際の算術式の文法について取り扱うのだとすれば別の場所で行うべき。 71516 | 71517 | 他にも解析と解釈が一致していない例はある。 71518 | echo "${hello:-'aa}" は構文エラーになるので quote を解釈しているのかと思えば、 71519 | echo "${hello:-'aa'}" で出力されるのは 'aa' であり quote 除去は為されない。 71520 | 一方で echo "${hello:-"aa"}" で出力されるのは "aa" であり quote 除去はされている。 71521 | 以前の実装で '' の quote を解釈しない様にしていたのはこれが理由であろう。 71522 | 因みに "${hello:-$'aa}" "${hello:-$"aa}" "${hello:-"aa}" は全て構文エラーになる。 71523 71524 振る舞い云々以前に字句的な定義から言えば何れの文脈でも quote は解釈されている様だ。 71525 その上でその quote を含んだ文字列 (引数) について quote 除去が行われるかどうか 71526 が文脈に依って異なるのだという様に考える必要がある。 71527 - そうすると基本的な実装としては常に quote は解釈する。 71528 - quote が除去されない文脈では) quote の着色を外側の文脈と同じにする 71529 という様に実装しなければならない。 71530 71531 ここで quote が除去されない文脈を判定する為に何ができるかという事である。 71532 但し、字句的な観点から言えば常に quote は解釈するというので間違いないのだから、 71533 quote 除去が実施されるかされないかについては余り実装に凝っても仕方がない気がする。 71534 取り敢えず現在の ntype 等の構成の範囲で対応できる所までにしておく事にする。 71535 71536 - 算術式の中に直接 quote がある場合の振る舞いについて対応した。 71537 - "${ ... }" の中に入れ子で ${} が入る場合には "${}" と同じ扱いにする対策はした。 71538 71539 そしてより凝った実装にする為にはどの様なことができるかについて記録を残す事にする。 71540 71541 2017-03-01 71542 71543 * ble-edit: ble-edit/info/{draw-text,draw} overflow 対策。 [#D0374] 71544 71545 ble-edit/info/draw-text の方は COLUMNS/LINES に従った truncate を加えた。 71546 一方で ble-edit/info/draw の方は truncate は加えていない。 71547 様々な制御機能が指定される可能性があることを考えると難しい。 71548 (改行や SGR だけ受け付けるという方針でまた別の draw 関数を用意するということも考えられなくはないが)。 71549 制御機能を受け付けるぐらいであれば、呼び出し元で高さの調整は済んでいる物と考えたい所である。 71550 71551 * ble-edit: 一番下の行で複数行の編集を開始するとずれる。 [#D0373] 71552 これは制御機能 IL で行の挿入までは行わないという事に起因する。 71553 IND (LF) で行を増やしてから IL を実行する様にしなければならない。 71554 これで一応直った。 71555 71556 然し、今度は一番下の行で行を accept した直後の動作が変である。 71557 直前の行を上書きしている。 71558 試しに ble-edit/render/update で行を追加削除する直前に各変数の値を確認してみる。 71559 71560 declare -- endx="27" 71561 declare -- endy="0" 71562 declare -- begx="27" 71563 declare -- begy="0" 71564 declare -- _ble_line_endx="10" 71565 declare -- _ble_line_endy="3" 71566 71567 変である。accept した時に _ble_line_endx _ble_line_endy の各変数の値は 0 にしている筈である。 71568 と思ったら、0 にしているのはカーソルの位置 _ble_line_x, _ble_line_y だけであった。 71569 71570 * syntax: 実は } の直後に } が来ても良いようだ。 [#D0372] 71571 71572 更に fi の直後に } が来ても良い…。同様に esac done の直後も OK の様子。 71573 更に } の後に done が来ても良い。fi の後に done が来ても良い。 71574 これらを総合すると } fi esac done は重ねる事ができるという事だろう。 71575 71576 ((1+1)) の直後の場合は駄目な様だ。 71577 71578 うーん。取り敢えず } fi esac done で現在 CTX_ARGX0 としているのは 71579 CTX_CMDX に変更すれば良い。そして更にコマンドの種類を限定する為に、 71580 CTX_CMDXE 的な物を用意するという様な方針でも良いだろう。 71581 そして同様の処理を既に CTX_CMDXC で行っているのでそれの真似をすれば良い。 71582 71583 異なる点は CTX_CMDXC の状態でコマンドが終わる事はできない 71584 (関数の中身が指定されていなければならない) 一方で、 71585 CTX_CMDXE の状態でそのままコマンドが終わっても良いという点である。 71586 71587 * syntax: for (()) { に対応する。 [#D0371] 71588 71589 ble-syntax:bash/ctx-command/.check-delimiter-or-redirect で、 71590 復帰後の文脈値を CTX_ARGX0F という物に指定して、 71591 CTX_ARGX0F では { を受け取るかまたは CTX_ARGX1 の処理を行うかという様に処理する。 71592 71593 これの対応により以下の項目については完了した。 71594 (残るのはヒアドキュメントのみである。) 71595 71596 | * [2015-02-16] ble-syntax.sh ToDo 71597 | 71598 | - case構文の中の文法 71599 | > ;; ;& ;;& の後に case のパターンを受ける 71600 | - for (()) { ...; } (obsolete) 71601 71602 * syntax: ((echo)>/dev/null) を何とかする。 [#D0370] 71603 71604 二種類のパターンがある。 71605 1. ((echo)>/dev/null) 71606 2. $((echo)>/dev/null) 71607 71608 少なくとも文法エラーが出ない様にはするべき。 71609 71610 算術式 (だと思っていた文脈) の中で単体の ) が来た場合には 71611 ( もしくは $( を nest-push し直す等。 71612 →この方法だとうまく行かない。というのも、要件として少なくとも i++ してから nest-pop しなければならず、 71613 また、データを格納する為には nest-push してから少なくとも i++ しなければならない。 71614 つまり合計で少なくとも 2 文字なければ1回の解析ループで nest-pop と nest-push を連続で行う事はできない。 71615 71616 方針を変えて単体の ')' が現れたらそのまま ctx=CTX_CMDX1 に移行する事にする。 71617 そしてコマンドの ')' の処理において開始が '((' であった場合も考慮に入れる事にした。 71618 71619 * ble-syntax: CTX_CARGI2, CTX_FARGI2, CTX_CARGX2, CTX_FARGX2 に対して補完候補として "in" を生成する。 [#D0369] 71620 complete.sh で "in" を生成する source を定義して、 71621 ble-syntax/completion-context/check-prefix と ble-syntax/completion-context/check-here において、 71622 CTX_ARGI, CTX_ARGX と同様に判定して、"in" を生成する source を指定すれば良い。 71623 71624 * syntax: for VAR in 及び case VAL in に対応する。 [#D0368] 71625 71626 | * [2015-12-24] (ble-syntax:bash): case 対応 71627 | 71628 | case コマンドの直後は一つ単語を受け取って、 71629 | 次に in を受け取って更に CTX_CASE に突入する。 71630 | それ以外の単語の場合には文法エラーとなる。 71631 | 71632 | 一つ単語を受け取るのは RDRF 等と同様に処理すれば良い。 71633 | というか寧ろ RDRF で処理してしまっても良いのかもしれない? 71634 | →それだとファイル存在チェックなどに引っかかって変な事になる。 71635 71636 これは CTX_RDRS を流用する事ができそうな気がする。 71637 VAL に関しては補完候補の生成という側面から見ても CTX_RDRS に等価なのでは。 71638 VAR に関しては新しく CTX_RDRV という名前の文脈値でも定義することにすれば良いだろうか。 71639 71640 しかし流用する前に確認しておくべきことがある。 71641 先ず初めに、リダイレクトの中で用いる事のできる文法要素と 71642 VAR/VAL で用いる事のできる文法要素は本当に一致しているのかという事である。 71643 特に VAR/VAL については素朴には CTX_ARGI と同様の扱いと考えるのが自然である。 71644 この時 CTX_RDRS と CTX_ARGI の扱いの差は何であるのかについて整理しておく必要がある。 71645 71646 | 違い1 ble-syntax:bash/ctx-redirect/check-word-end において、 71647 | プロセス置換が <() 続きにある場合には単語は続くとしている。 71648 | 一方で ble-syntax:bash/ctx-command/check-word-end では、 71649 | プロセス置換が続きにあるかどうかは考えずに単語は終了としている。 71650 | 71651 | [bug1] 71652 | 71653 | これは ble-syntax:bash/ctx-command/check-word-end のバグなのではないか? 71654 | 実際に bash で以下を実行すると、A<(echo) はまとめて一つの引数であると分かる。 71655 | 71656 | $ printf '(%s)\n' A<(echo) 71657 | 71658 | つまり、単語が終了するかどうかの判定を行う場合には 71659 | 続きにプロセス置換がないかどうかも確認しなければならない。 71660 | 取り敢えず単体で fix して commit する事にした。 71661 | 71662 | 違い2 ble/syntax:bash/ctx-redirect/check-word-end において、 71663 | 単語の終了と判定された場合には nest-pop を実行している。 71664 | これは CTX_RDRS を導入する際に nest-push を伴う事に対応している。 71665 | 71666 | 何故 nest-push/nest-pop をする必要があるのかというと、 71667 | 元々の文脈を復元する必要があったからである。 71668 | リダイレクトにおける元々の文脈は様々な可能性があるので、 71669 | 元々の文脈に応じてリダイレクトの文脈値を切り替える手法では、 71670 | 文脈値をたくさん定義しなければならず非効率的である。 71671 | 従って、入れ子に依って文脈を保存するというアプローチを取った。 71672 | 71673 | ★一方で、for VAR in 及び case VAL in に関しては、 71674 | 抜けた後の文脈は一意に定まるのでわざわざリダイレクトの仕組みを間借りして、 71675 | 分かりにくくするという必要性はないのかもしれない。 71676 | 71677 | check-word-end に関してはこれ以上の違いはない様である。 71678 | (ctx-command の方では個別 ctx 毎に追加の処理をしているが、 71679 | 特に全ての文脈値に対して共通の処理をしている訳ではないということである。) 71680 | 71681 | 次に ble-syntax:bash/ctx-command と ble-syntax:bash/ctx-redirect を比べる。 71682 | 71683 | 違い3 ctx-redirect では改行やリダイレクト・コマンドの終端 (&& や | など) が来るとエラーである。 71684 | コメントが其処に入った場合も駄目である。 71685 | 一方で ctx-command では改行やコマンドの終端が来れば単に次のコマンドに移るし、 71686 | リダイレクトが来れば其処でリダイレクトを挟む事が許される。 71687 | 同じ理由でコメントが来る事も許される。 71688 | 71689 | [bug2] 71690 | 71691 | だとすると既存の ctx-redirect ではコメントに対する対策をしていないので、 71692 | リダイレクトの直後にコメントがあった場合にそれをファイル名と勘違いする事になる。 71693 | これについて確認する必要がある…と思ったら普通に bash がエラーを吐く。 71694 | 71695 | bash: 対応する `)' を探索中に予期しないファイル終了(EOF)です 71696 | 71697 | 何処からこれが出ているのかは分からない。いろいろ試した結果、 71698 | エラーが出ているのは ctx-redirect の処理中ではなくて ble-syntax/parse の処理中ですらない様だ。 71699 | 恐らく tree enumerate の辺りでエラーが出ているのではないという気がする。 71700 | しかし考えて見るに parse の外で tree enumerate 関係の関数を呼び出す機会はあっただろうか。 71701 | →いや色付を単語ごとに実行する際に使用している筈である。 71702 | もし tree enumerate 関係で出ているエラーなのだとすれば、ble_debug=1 で実行すれば 71703 | より速いタイミングでエラーが出そうな物である。試してみる→特に問題はない? 71704 | だとすれば着色の方が怪しい。あ、何か分かった気がする…。引数の内容を展開する時に、 71705 | content=($content) 的な事をするが、その時に content が # で始まると駄目という事か。 71706 | 引数の内容を展開するコードは以下の2箇所にある。特に前者で問題になっている。 71707 | 後者に関しては問題にはならない。 71708 | 71709 | ble-syntax.sh: eval "value=($wtxt)" 71710 | complete.sh: builtin eval "COMPV=$COMPS" 71711 | 71712 | これについても修正した。 71713 | 71714 | [bug3] 71715 | 71716 | さて、そもそも # で始まる単語という物が生成されるというのも行けない 71717 | (※よく考えたら shopt -u interactive_comments の場合にはその様な単語が生成されても問題ない)。 71718 | ctx-redirect でもコメントのチェックはするべきである。 71719 | そしてコメントがあった場合には delimiter の時と同様にエラーにする。 71720 | 71721 | ctx-command と同様に comment をチェックする。 71722 | コメントが有効であった場合には、そのコメント自体をエラー色にすれば良い。 71723 | 71724 | 他には本質的な違いはないようである。 71725 | 見た目上の違いとしては ctx-redirect では check-assign をしていないという事であるが、 71726 | これは ctx-command の側でも特定の ctx の場合にしか意味を持たない。 71727 | また、unexpectedWbegin のチェックをしていないという違いもあるが、 71728 | これも ctx-command で unexpectedWbegin が起こるのも ctx == CTX_ARGX0 の時だけである。 71729 | 従って、これらについて ctx-redirect と ctx-command が異なる点はないと考えて良い。 71730 71731 まとめる。 71732 71733 - 違い1 は単なるバグであったので現在は違いはない。 71734 - 違い2 は CTX_RDRS で引数を受け取った後に任意の文脈値に移行できるようにするための物であった。 71735 - 違い3 CTX_RDRS は少なくとも1つの引数を要求するので、 71736 単語の先頭で delimiters, comments, 改行が来るとエラーである。 71737 ※コメントのチェックが抜けていたのはバグであったが、修正後も取り扱いは異なる。 71738 71739 結局振る舞いとしての違いは "違い3" だけである。 71740 一方で "違い2" に関しては CTX_RDRS の枠組みの方が柔軟であるが、 71741 今回の for VAR in, case VAL in の場合には不要な機能である。 71742 今回採用するとすれば 71743 71744 - CTX_RDRS の枠組みを使えば比較的楽に実装できる。 71745 CTX_RDRS と全く同じ機能を持つ文脈値を増やすか、 71746 或いは CTX_RDRS をそのまま流用してしまって問題ない。 71747 71748 - CTX_ARGX 等と同様の枠組みを使う方が仕組みとしては綺麗な気がする。 71749 但し、"単語を少なくとも一つ受け取る" 機能と、 71750 "単語が終端したら別の文脈値に移行する" 機能を 71751 ctx-command に追加しなければならない。 71752 71753 ctx-command がまた無駄に複雑になってしまう。 71754 一方でこれを機に ctx-command を整理するという方向性も考えられる。 71755 71756 取り敢えず ctx-command を整理してから考える事にする。 71757 整理した。矢張り ctx-command の枠組みで処理した方が良い様に思われる。 71758 71759 1 先ずは新しい文脈値を定義して ARGX, ARGI と同様に処理する様に設定を行う。 71760 71761 Note: CTX_CARGX1 によって導入される単語だけは wtype として CTX_ARGI を設定する。 71762 これによって case の第一引数のみが、 71763 case のコマンド引数として抽出されたり (in ble-syntax:bash/extract-command/.construct-proc)、 71764 ファイル名としての着色がなされたりする (in ble-highlight-layer:syntax/word/.update-attributes/.proc)。 71765 71766 2 CTX_ARGI に対して指定されている特別の処理について一つ一つ確認し、 71767 必要であれば新しい文脈値にも適用する。 71768 71769 3 CTX_ARGX についても同様に確認・適用していく。 71770 71771 4 後は導入部分について。 71772 71773 観察してみたが、思うに CTX_CMDXF と CTX_FARGX1 は同一ではないかという気がする。 71774 という訳で CTX_CMDXF を廃止して CTX_FARGX1 に統合する。 71775 取り敢えずこの時点で既に for については動いている様である。 71776 71777 case についてはどうだろうか。check-word-end で 'for' の時に ctx=CTX_FARGX1 とした様に、 71778 'case' で CTX_CARGX1 を設定すればそのまま大丈夫だろうか。 71779 試してみた所ちゃんと動いている様である。 71780 # CTX_CASE については以前に実装していたのでそのまま通用する様だ。 71781 # ちゃんとパターンと esac の区別もついている。少し気になって試してみたのだが、 71782 # "esac)" というパターンを指定すると構文エラーになるという振る舞いも bash のそれと一致しているので OK。 71783 71784 5 check-word-end において in 以外の場合にエラーを吐くようにする。 71785 これは意外と簡単に対応できた。 71786 71787 取り敢えず動作しているのでこれで確定する。 71788 71789 * bug: ((echo) >/dev/null) を入力しようとすると無限ループになる。 [#D0367] 71790 というか ) を入力しただけで無限ループになる。 71791 ごく最近の ble.sh ではこの現象は起こっていなかった。 71792 という事は、先程までに行った変更によってできたバグと考えられる。 71793 71794 function ble-syntax:bash/ctx-command/.check-delimiter-or-redirect だった。 71795 71796 ")" で閉じた時に対応する nest が存在しない場合の処理において、 71797 戻り値が return 1 になっていなかった。 71798 関数に分ける時に顕在化したバグであった。 71799 71800 今までは return 1 し忘れていても次の処理へと進んでいき、 71801 (以降の処理では引っかからないので) 最終的に return 1 になっていた。 71802 これによって結果として問題になっていなかった。 71803 しかし、本来 delimiter が来てかつ対応する nest が存在しない時点で 71804 return 1 であるという事が確定しているのですぐさま return 1 するべきであった。 71805 つまり、これは顕在化していなかっただけであり、意図しない実装という意味でバグであった。 71806 71807 然し、今回 delimiter が来た時の部分を関数に分けて、 71808 そのままその関数の終了ステータスで return する様に変更したことで問題が顕在化した。 71809 処理がなされなかった場合には return 1 する様に変更した。 71810 71811 71812 2017-02-28 71813 71814 * ble-edit: 関数名の整理 [#D0366] 71815 71816 .ble-edit/stdout/on -> ble-edit/bind/stdout.on 71817 .ble-edit/stdout/off -> ble-edit/bind/stdout.off 71818 .ble-edit/stdout/finalize -> ble-edit/bind/stdout.finalize 71819 .ble-edit/stdout/* -> ble-edit/bind/stdout/* 71820 71821 .ble-line-text. -> ble-edit/text/ 71822 .ble-line-info. -> ble-edit/info/ 71823 .ble-line-cur.xyo -> ble-edit/info/.put 71824 .ble-edit-draw. -> ble-edit/render/ 71825 .ble-edit-draw.set-dirty -> ble-edit/render/invalidate 71826 71827 ble-edit/draw/goto -> ble-edit/render/goto 71828 ble-edit/draw/clear-line -> ble-edit/render/clear-line 71829 ble-edit/draw/clear-line-after -> ble-edit/render/clear-line-after 71830 71831 .ble-edit.locate-forward-xword -> ble/widget/.locate-forward-genword 71832 .ble-edit.locate-backward-xword -> ble/widget/.locate-backward-genword 71833 .ble-edit.locate-current-xword -> ble/widget/.locate-current-genword 71834 単語関連については全体的に整理した。 71835 71836 .ble-edit.bell -> ble/widget/.bell 71837 .ble-edit.*-range -> ble/widget/.*-range 71838 .ble-edit.quoted-insert.hook -> ble/widget/quoted-insert/.hook 71839 .ble-edit/delete-backward-char -> ble/widget/.delete-backward-char 71840 .ble-edit.delete-char -> ble/widget/.delete-char 71841 .ble-edit.goto-char -> ble/widget/.goto-char 71842 .ble-edit.forward-char -> ble/widget/.forward-char 71843 .ble-edit/newline -> ble/widget/.newline 71844 71845 .ble-edit.default-key-bindings -> ble-edit/load-default-key-bindings 71846 .ble-edit-finalize -> ble-edit-finalize 71847 71848 * [2016-08-08] 改行&プロンプト出力を一度に行う? [#D0365] 71849 71850 唯単に RET を押すだけだと普通の bash では一気に新しいプロンプトが表示される。 71851 然し現状の ble の実装では一旦次の行の行頭に行ってから暫くして (計算をしてから) プロンプトが表示される。 71852 その為にちらつきというか変な遅延がある様に思われる。 71853 次の行の行頭に行くのも同時に出力するべきではないか。 71854 71855 これは .ble-edit/newline の中で改行を出力してから、 71856 コマンドの有無を確認して…云々という処理をしているからである。 71857 また、プロンプトの出力部分についても確認しておく。 71858 ble-edit/prompt/update を呼び出している箇所は一箇所しかない。 71859 .ble-edit-draw.update である。 71860 .ble-edit-draw.update 自体は幾つかの場所から呼び出されている。 71861 71862 1 ble-core に専用の buffer を作成する事にするのが良いだろうか。 71863 →ble/util/buffer ble/util/buffer.flush という関数を作った。 71864 更に ble-edit/draw/bflush で ble/util/buffer に対して内容を出力する物を用意した。 71865 同様に ble/util/joblist.bflush という物も用意した。 71866 71867 2 .ble-edit-draw.update を直接 stderr に出力するのではなくて 71868 ble/util/buffer に対して出力する様に書き換える。 71869 同時に呼び出し元で必要に応じて flush を実行する様にする。 71870 71871 3 .ble-edit-draw.update-adjusted については呼び出し元は一箇所しか無い。 71872 71873 究極的には外部コマンドの呼び出し時と 71874 ble-edit/stdout/off の時にだけ flush すれば良いだけなのでは。 71875 結局、以下の箇所でのみ buffer.flush を実行すれば良い筈である。 71876 71877 * .ble-edit/stdout/off 71878 bind の終わりで最終的に必ず (何らかの異常やシグナルで止まる事はあるが) 71879 この関数が呼ばれて次の入力を受け取る状態に入る筈である。 71880 また出力の制御という観点で密接に関係がある。 71881 従って、この関数の中で buffer.flush をするのが良い。 71882 71883 但し bleopt_suppress_bash_output を設定していない時にはこの関数は空だったが、 71884 今回は bleopt_suppress_bash_output であっても .ble-edit/stdout/off で 71885 buffer.flush を実行する様に変更した。bleopt_suppress_bash_output の場合には 71886 実際 "stdout を off にする" という動作は必要としないが buffer.flush は必要である。 71887 その様な意味合いで .ble-edit/stdout/off という関数名は良くないのではないかという気がする。 71888 これは後で考え直したい。 71889 71890 * ble-edit/exec の内部では直接出力を行う。 71891 exec を開始する直前に buffer.flush を実行すれば良い。 71892 71893 * .ble-line-info.draw, .ble-line-info.clear 71894 これは時間のかかる計算 (isearch) の進捗状況を表示するのに用いている為。 71895 (実のところ、isearch の側で buffer.flush を実行しても良い様な気もする。 71896 71897 * ble/widget/command-help 71898 これはその場で less を使って内容を表示する。 71899 buffer.flush をした後に less を起動する必要がある。 71900 71901 * 終了コマンド 71902 以下の bash を終了させるコマンドを実行する時には buffer.flush を行う。 71903 71904 ble/widget/delete-forward-char-or-exit 71905 ble-edit/bind/.check-detach (ble-edit/bind/.exit-trap をシグナル経由で呼び出して終了する) 71906 71907 取り敢えず簡単な実装は終わった。 71908 71909 2017-02-25 71910 71911 * [2017-02-14] stackdump [#D0364] 71912 71913 [[ -x /home/murase ]] と入力したらなった。 71914 具体的には [[ -x a と入力して、x を消して再度 x を入力するとなる。 71915 これは再現性がある。 71916 71917 | assertion failure: [[ ${_ble_syntax_nest[inest]} ]] 71918 | ble-syntax/tree-enumerate/.initialize/FATAL1 71919 | @ /home/murase/prog/ble/ble.sh:25 (ble-assert) 71920 | @ /home/murase/prog/ble/ble.sh:3 (ble-syntax/tree-enumerate/.initialize) 71921 | @ /home/murase/prog/ble/ble.sh:5 (ble-syntax/tree-enumerate) 71922 | @ /home/murase/prog/ble/ble.sh:5 (ble-syntax/parse/shift.method2) 71923 | @ /home/murase/prog/ble/ble.sh:2167 (ble-syntax/parse/shift) 71924 | @ /home/murase/prog/ble/ble.sh:-16 (ble-syntax/parse) 71925 | @ /home/murase/prog/ble/ble.sh:4 (_ble_edit_str.update-syntax) 71926 | @ /home/murase/prog/ble/ble.sh:-135 (ble-highlight-layer:syntax/update) 71927 | @ /home/murase/prog/ble/ble.sh:4630 (ble-highlight-layer/update) 71928 | @ /home/murase/prog/ble/ble.sh:4981 (.ble-line-text/update) 71929 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 71930 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 71931 | @ /home/murase/prog/ble/ble.sh:1196 (ble-edit/bind/.tail) 71932 | @ /home/murase/prog/ble/ble.sh:-4307 (ble-decode-byte:bind/EPILOGUE) 71933 | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 71934 71935 木構造の破壊が度々起こるので ble-syntax/print-status/.dump-arrays で 71936 構造を確認して問題がある部分を着色して表示する様に変更した。 71937 これによって確認してみた所、入れ子構造になっている部分の内部で 71938 二個目以降の単語を編集した時には大体の場合に nest の参照が壊れているという事が分かった。 71939 ただ単に顕在化するのが "[[ -x a" の場合だけだったという事になる。 71940 71941 これは明らかに nest の shift に失敗しているのが原因である。 71942 現在の shift は基本的に e74c11631d62880a2600fb559e4135b8cf268110 (11ヶ月前) で作られた物である。 71943 長らくエラーが出た覚えもないのでもっと最近の変更によって問題が埋め込まれた可能性がある。 71944 71945 その他では一番最近の 0757230b41a2adfe5eb6a52ce4c97f29734845a7 しかない。 71946 (実のところ、この修正と stackdump が出たのとどちらが先だったのか覚えがない…。) 71947 しかしこの修正は単純な物でこれで問題が起こるようには思われない。 71948 実際にこの修正を戻して試してみたが、同様に問題が発生するので、この修正は関係ないとして良いだろう。 71949 という事はこれは昔から存在していたバグと考えるべきだろう。 71950 71951 % 取り敢えず nest のシフト範囲がどの様に決定されているのかについてコードを追ってみる事にする。 71952 % nest のシフトは ble-syntax/parse/shift.nest で行われている。 71953 % この関数自体が誤っている可能性について先ずは確認してみる。 71954 % と思ったが、よく見たら壊れているのは nest ではなくて nest の参照元である stat の方だった。 71955 71956 なので見るべきは stat のシフト範囲の方である。つまり、ble-syntax/parse/shift.stat である。 71957 stat の他の項目に関しては特に問題も生じていない様なので、恐らくこの関数の呼び出し自体はちゃんと行われている。 71958 問題は nest 参照 (stat[3]) のシフト方法ではないかと思われる。 71959 コードを見てみると stat[1] (wlen), stat[3] (nlen), stat[4] (tclen), stat[5] (tprev) が共通のコードでシフトされている。 71960 これは怪しい。というのも tclen, tprev によって参照されるのは境界で、 71961 wlen, nlen によって参照されるのは文字であり、両者は異なる性質のものであるはずだからである。 71962 71963 ? さて wlen に関する問題が発生しなかったのは何故だろう。word が stat に入る機会が少ないからだろうか。 71964 人為的に単語の途中に構造を導入して (例えば he"l"lo など)、word が破壊されないか確認する。 71965 うーん word に関しては余り遠くを参照したりしないので nest とは dirty-range との相対位置が異なる様だ。 71966 振る舞いが違うのはそういう事である。もしかすると特殊な状況では word にも不整合が生じるのかもしれないが、 71967 wlen で今まで問題が発生しなかった理由がわかったのでこれでよしとして深く追求はしない。 71968 nlen の修正方法が分かれば wlen の修正方法も同様にすれば良いだろう。 71969 71970 変だ。ちゃんと動いているべきな気がする。 71971 何より同じ値なのに正しく動いている shift と動いていない shift がある。 71972 どうやら shift 量が過剰の様だ。もしかして複数回 shift が実行されている? 71973 →確認してみたら予想通り複数回の shift が実行されている様だ…。 71974 71975 % 一方で全然シフトの対象でない部分についても沢山 shift が呼び出されている様な気がするがこれは何だろう? 71976 % と思ったら改めて実行してみた所何も起こっていない…と、よく考えたら "less ~/a.txt" と入力するのに 71977 % 使っているシェルがテスト用のコードを埋め込んだ後のシェルになっていて、確認のための入力をしている時に、 71978 % 変なごみが入力されてしまったというだけの事だった。 71979 71980 さて、j は j-- としているので複数回同じ j の値で shift が実行されるというのは変である。 71981 誰かが j を increment しているのだろうか。或いは、j に何か値が代入されているのだろうか。 71982 71983 + 誰かが j を increment している可能性が怪しい→と思ったがそうでもない。 71984 + どうやら "((_shift2_j=wbegin)) # skip" という行が怪しい気がする 71985 (※_shift2_j は j の値を退避している変数である)。 71986 →と思ったがこれでもない様だ…。 71987 + あー。なんと _shift2_j に j の値を保存していないコントロールパスがあった。これだ。 71988 71989 呆気なく直った。 71990 71991 71992 2016-12-21 71993 71994 * $_ には前回のコマンドの最後の引数が格納されているべきである。 [#D0363] 71995 しかもシェルによる展開を一頻り実行した後の値である。 71996 現状では現在実行しようとしているコマンド自体が代入されている。 71997 71998 先ず最後に実行した時の _ の値を取得する方法と、 71999 それからその _ を改めて設定する方法について考えなければならない。 72000 最後に実行した時の _ の値を取得する方法は簡単である。 72001 問題はどの様に _ を設定するかである。 72002 これについては : "$_ble_last_command_last_arg" とかいう感じにすれば良いのだろうか。 72003 72004 % _ の値の取得に関しては ble-edit/exec:gexec/.eval-epilogue の中に追加する事にした。 72005 % どうやら関数の実行が終了するまではその関数の最後の引数は _ に設定されない様なので。 72006 % つまり、そのコマンドが終了した時に _ が設定されるという事である。 72007 % 72008 % 一方で同じ理由で _ の設定に関しては ble-edit/exec:gexec/.eval-prologue の中に設定しても駄目だ。 72009 % というのも中で _ を設定したとしても .eval-prologue 関数を出た時に 72010 % .eval-prologue 関数自体の最後の引数が改めて _ に設定されてしまうからである。 72011 72012 実際にやってみると動かない。成る程、最後に実行したコマンドの引数が取得されるのではなくて 72013 最後に実行した eval の引数が評価されている。つまり、eval の内部で _last_exit 云々を取得しなければならない。 72014 しかしそうすると今度は lastexit 等の再設定が必要になる。いや lastexit も一緒に取得してしまえば良いという事だろうか。 72015 →少し汚いが $? と $_ を取得する為の関数 .save-params を作成してそれを eval の引数の中で評価する事にした。 72016 文法エラーになった場合にはそもそも $? と $_ が更新されないという事になるだろうがそれでも仕様がないだろう。 72017 →やはり $? が更新されないというのは変な気がするので外に伝播する事にする。 72018 72019 2016-12-06 72020 72021 * プロンプトにジョブ数が表示されてなくなって変だと思っていたら、 [#D0362] 72022 shopt -s nullglob していると GLOGIGNORE を設定していたとしても、 72023 何らかのパターンがあった時に全体が消えてしまうという事が判明した。 72024 72025 これを簡単に回避する方法はあるのだろうか。 72026 一つの方法は一旦変数の内容を取り出して、 72027 ?*[() その他のシェル特別文字をを全てエスケープしてしまうという事である。 72028 しかしエスケープするべき文字は沢山あるのでこの方法は現実的でない様な気がする。 72029 72030 だとすると nullglob を一時的に解除する様にする必要がある。 72031 さて、よく考えてみれば分割を行っている箇所はこの一箇所だけではないはずだ。 72032 と思ったが、文字列の分割を目的としてこれを行っている箇所は全て 72033 ble/string#split に書き換えたのであった。ならば、ble/string#split だけ対策をすれば問題ない筈だ。 72034 72035 →取り敢えず ble/string#split に nullglob の対策を施す事にした。 72036 72037 しかし、もしかすると他にも同様の問題で項目が消滅してしまうという箇所があるかもしれない。 72038 他に GLOBIGNORE を ble.sh の中で使用している箇所がないという事は、その様な場所は、 72039 * や ? や [..] が含まれる内容を指定した時にファイル名に展開されてしまう危険がある。 72040 その様な事にならない様に設計しているはずなので GLOGIGNORE が使われていない場所では問題ないと考えて良い様に思う。 72041 つまり、論理的にはその様な場所は存在しないはずなのでここでは余り気にしなくても良い。 72042 その様な場所があるとすれば別のバグである。 72043 72044 2016-11-07 72045 72046 * [2016-11-05] 半角仮名が入力できないという事に気づいた。コピー&ペーストしても駄目である。 [#D0361] 72047 ble-detach している時はちゃんと動作する。TAB で補完する時は入力できる。 72048 半角文字を入力すると変な文字に変換される。 72049 72050 screen を経由していると変な文字が増える。 72051 これは screen が不正な文字を受信した時の処理方法の問題だろう。 72052 今回の問題とは直接に関係は無いはずである。 72053 72054 他の文字を入力している時には何も問題は生じていないので 72055 これは utf-8 のデコードの問題ではないかと思われる。 72056 試してみると半角仮名は 3 byte 文字である。普通の漢字と同じに見える。 72057 72058 UTF-8 のデコード部分を調べてみたが誤りはない様に見える。 72059 次に ble-decode-char 65422 を実行してみる。 72060 正しく処理されている。半角仮名の ホ が入力された。 72061 直接に入力してみる…あれ…入力できる。変だ。 72062 どうやらローカルの cygwin でやると入力できなくて、padparadscha 上でやると入力できる様だ。 72063 cygwin 側のロケールの設定だろうか。。 72064 cygwin 側で ble-decode-char 65422 としてみたら変な文字が入力される様だ。 72065 cygwin 上の c2s が怪しい。 72066 72067 →なんと cygwin で printf '\UFF8E\n' をすると文字化けするという事が判明した。 72068 LC_ALL=C.UTF-8 printf '\uFF8E\n' として見ても駄目だ。version は 4.3.46 である。 72069 /bin/printf '\uFF8E\n' は正しく動作する。これは bash のバグなのか? 72070 然し padparadscha 上の bash-4.3.42 ではちゃんと動いている。 72071 72072 もう少し詳しく見る。printf '\uFF8E\n' | od -t x1 とすると結果は ed 9f bf ed be 8e 0a である。 72073 これを UTF-8 に従って戻すと U+D7FF U+DF8E になる。サローげとペアにしようとして失敗している。 72074 https://ja.wikipedia.org/wiki/UTF-16 を見るとサロゲートペアの計算方法は、 72075 char16_t w1 = 0xD800 | ((uchar >> 32) - 1 & 0xFF) << 6 | uchar >> 10 & 0x3F; 72076 char16_t w2 = 0xDC00 | uchar & 0x3FF; 72077 である。この式を多少弄って、以下のようにしてみる。 72078 char16_t w1 = (0xD800 + (uchar >> 26)) - 0x40; 72079 char16_t w2 = 0xDC00 | uchar & 0x3FF; 72080 このコードで本来サロゲートペアにならない U+FF8E をサロゲートペアにしようとすると、U+D7FF U+DF8E になる。 72081 これは実際サロゲートペアになっていないので UTF-8 にしようとすると上記の様に 6 bytes のデータになる。 72082 72083 これは誰が悪いのか? bash のソースを見る。 72084 builtins/printf.def:888: temp = u32cconv (uvalue, cp); 72085 この u32cconv が怪しい。定義は lib/sh/unicode.c:239 にある。 72086 見るとサロゲートペアに変換する関数 u32toutf16 があって怪しい。 72087 lib/sh/unicode.c:213: u32toutf16 (c, s) 72088 あー。この関数にバグがある。何故か 0x0d800 未満の文字以外を全てサロゲートペアに変換している。 72089 bash のバグ報告に投げるべきだろうか。何処かに bash の repo は落ちていないか? 72090 72091 その前に最新版をチェックしなければなるまい。最新版4.4でも直っていない。 72092 4.4 の patch は未だ出ていない。 72093 72094 報告を提出した。accept された。恐らく 4.5 で反映されるのではないかと予想される。 72095 work around を ble.sh に追加する。 72096 72097 2016-11-05 72098 72099 * 調子に乗って算術式のバグに関しても報告を行うべきだろうか。 [#D0360] 72100 72101 $ bash-4.4 -c 'a=0 x="a=1"; ((0?x:0)); echo $a' 72102 1 72103 $ bash-4.4 -c 'a=0 x="a=1"; ((0?(x):0)); echo $a' 72104 0 72105 $ bash-4.4 -c 'a=0 x="a=1"; ((0?$x:0)); echo $a' 72106 0 72107 72108 しかしできるだけソースコードのどの部分が問題であるのかも指摘した方が良い。 72109 「この様なケースは今まで報告されなかったので滅多にないことで対応する必要はない」等とはぐらかされる気がする。 72110 72111 先ず算術式は何処で処理されているのだろう。 72112 builtins/let.def を見ると evalexp という関数を呼び出している。 72113 evalexp は expr.c:365 に定義されている。引数は文字列である。そのまま subexpr に制御が渡る。 72114 グローバル変数 expression に引数の文字列をコピーし、それを readtok で読み取る。 72115 結果は EXP_HIGHEST () で取り出している。readtok は expr.c:1230 にある。中は単に単語を一個ロードするだけの様だ。 72116 ということは EXP_HIGHEST() が本体という事になる。そしてマクロによって expcomma が呼び出される様だ。 72117 expcomma は expr.c:442 にある。其処から再帰下降解析を行っている。expassign (expr.c:457) -> expcond (expr.c:572) 72118 どうも cond? lhs: rhs において cond の値に応じて noeval という変数を inc/dec して評価するかしないかを切り替えている様だ。 72119 そして再度 EXP_HIGHEST を呼び出している。さて変数参照と noeval の関係が怪しそうだ。EXP_HIGHEST から下降していく。 72120 expcomma -> expassign -> expcond -> explor うーん。この exp0 というのが怪しい。辿るまでもなくこれが一番下なのでは? 72121 どうも既にこの時点で値が計算されているらしい? だとすると readtok で変数の中身が評価されているのか? 72122 調べると次のトークン (peektok) が "=" 以外の時は expr_streval (expr.c:1085) で評価を行っている。 72123 それで expr_streval を見るとちゃんと noeval を判定している。変だ。だとすればやはり評価されない筈ではないのか。 72124 変だ。bash-4.3 を見ても同様である。と思って再度 expcond を見てみる。 72125 おや。noeval を設定する前に readtok しているではないか。これは駄目な筈だ。 72126 72127 報告を提出した。 72128 72129 2016-09-16 72130 72131 * ble-core: bug ble/util/upvar を導入してみた所、色が全く着かなくなってしまった。 [#D0359] 72132 72133 調べてみると upvar の変数名に対して配列要素 arr[index] を渡しているのがいけなかった。 72134 配列要素を指定した場合にどの様な動作をするのだろうか。調べてみる事にする。 72135 72136 先ず local arr[1] などとするとそもそも arr という変数が関数内から見えなくなる様だ。 72137 関数スコープに arr という名前でスロットが作成されるが変数の実体は配置されないなどという事だろうか。 72138 また local arr[1]=1 などの様に値まで指定すると arr=([1]=1) の様な内容の配列が local に作成される様だ。 72139 引き続き unset arr[1] 等とすると、その配列要素は削除されるが配列自体は残ってしまう。 72140 72141 a さて、どの様に定義するべきだろうか。 72142 例えば変数名が単純な変数名の場合には今まで通りに local "$var" && upvar "$var" "$value" として、 72143 変数名が arr[index] 等の場合には単に eval $var=\"\$value\" を実行する様にするか。 72144 然し、それだとローカルに arr という名前で変数が存在すると、 72145 その変数に新しい要素を追加する事になってしまい、変更が外に達しないという事になる。 72146 配列名が被ったとしても正しく外に変数を返す事ができる様にする為には、 72147 72148 local "${var%%\[*\]}" && upvar "$var" "$value" 72149 72150 として upvar の中でも unset "${var%%\[*\]}" 等の様にしなければならない。 72151 72152 b 或いは、全く発送変えても良い。例えば export を使うとどの様な動作になるだろう。 72153 72154 - 試してみた所、外側の関数で local var として内側の関数で export var=value とすると、 72155 外側の関数でその値を参照できると共に、更に外側の関数を抜けると変数が存在しなかった事になる。 72156 (少なくとも bash-4.3 ではその様な動作になっている。他の bash の version ではどの様な動作になるだろうか。) 72157 72158 % ToDo: check bash-3.0, 3.1, 4.0, 4.1, 4.2 での動作確認: 72159 % 外側の関数で local して内側の関数で export した変数は外側の関数を抜けた時に削除されるか。 72160 % もしくは export flag が削除されるか。 72161 72162 x 更に重要な事は、或る関数の中で declare した変数について、 72163 export によってその関数の外側にまで寿命を延長させる事ができるかどうかである。 72164 実際に試してみた所、できない様だ。飽くまで宣言された時の寿命は変わらない様だ。 72165 72166 - また、もしこの問題を解決できたとしても、他の実行形式に対して環境変数として 72167 変数の内容が伝播してしまうのは都合が悪い可能性がある。 72168 72169 - 更に、配列要素などが指定された時の動作についても非自明である。 72170 結局配列要素などが指定される場合を考慮に入れれば 72171 upvar を使った場合と較べてコードが簡単になるという事はない様に思われる。 72172 72173 結局今の所は export するしかない様だ。 72174 72175 2016-09-11 72176 72177 * isearch: C-g でキャンセルした時に元の位置に戻る。 [#D0358] 72178 元々の _ble_edit_ind _ble_edit_mark の値を記録して、 72179 キャンセルした時にそれを復元する様に変更すれば良い。 72180 72181 と思ったら元々 _ble_edit_ind, _ble_edit_mark の値は、 72182 一致範囲として記録されるものであった。 72183 72184 * syntax:bash: $ は単体でもOK [#D0357] 72185 72186 $ の直後に文字列終端・空白・改行その他の記号があってもエラーではなくて、 72187 単に $ という文字になるという事。 72188 72189 はじめは通常文字のリストに追加しようと思ったが、 72190 設計上、通常文字の連続のチェックの方が先に来ている。 72191 これは通常文字が登場する確率の方が高いので、 72192 特殊文字よりも先に通常文字をチェックしたほうが高速だからである。 72193 従って、この順序を変更したくはないので、check-dollar の内部で処理する事にした。 72194 どのパターンにも一致しなかった $ は単に一文字の文字として解釈を行う。 72195 72196 * edit: history の一番下で C-o した時の動作 2016-07-18 [#D0356] 72197 72198 * accept-and-next: erasedup はどの様に処理されるべきか。 [#D0355] 72199 72200 もし erasedups が指定されているとすれば、 72201 履歴に同じ内容のものが二つ以上登録されていることは無いはずである。 72202 という事は或る履歴項目を実行した事によって 72203 その次の項目が削除されてしまうという事は無いはずである。 72204 72205 しかし、実行した履歴項目がその場所から削除されてしまうので、 72206 履歴番号がずれる事になるという事に注意する。 72207 これに対する対策を追加する必要性がある。 72208 72209 同様に ignoredups が指定されている場合にも、 72210 その項目が一番最後の項目の場合には番号のずれが生じる。 72211 というか、ignorespace など他の指定に引っかかる事もある。 72212 72213 これらをどの様に判定すれば良いだろうか。 72214 自前で全て判定をしなければならないのだろうか。 72215 或いは、履歴項目の個数を数える等して処理を簡単化できないか。 72216 例えば ignoredups と ignorespace の場合を考える。 72217 ignoredups に当たった場合は新しい履歴項目は追加されないが、 72218 一番最後の履歴項目が同じ内容を持っているので、その履歴項目に移動する事にすれば良い。 72219 ignorespace や HISTIGNORE に当たった事によって履歴項目に追加されなかった場合にはどうすれば良いか。 72220 実行したのが昔の履歴項目の場合にはそのまま気にせずに次の項目に移動すれば良い。 72221 実行したのが一番最後の履歴項目の場合には履歴項目に移動するのではなくて、 72222 現在の編集内容に前回の編集内容をコピーするという様に対応すれば良い。 72223 72224 動作についてまとめるとどうなるだろうか。 72225 動作が簡単な場合から順に考えていくことにすれば良い。 72226 72227 a 先ず、実行したのが昔の履歴項目だった場合には、 72228 基本的にその次の履歴番号に進めば問題ない。 72229 但し例外が erasedups によって項目が削除された場合である。 72230 それ以外の履歴の設定では過去の履歴が変化する事はないので気にしなくて良い。 72231 erasedups が設定されている場合に、 72232 その履歴項目の内容と実行したコマンドの内容が同一の場合には 72233 erase 操作によって次の履歴項目は実行したのと同じ履歴番号になる。 72234 (履歴項目の内容と実行したコマンドの内容は、 72235 過去の履歴項目の内容を編集することができるので違っても良い事に注意する。 72236 つまり [[ ${_ble_edit_history[index]} != ${_ble_edit_history_edit[index]} ]] かもしれないという事。) 72237 72238 よく考えたら HISTIGNORE や ignorespace に引っかかってそもそも履歴項目の登録が起こらない場合は、 72239 erasedups に引っかかっていたとしても履歴項目の削除は起こらない。 72240 つまり index のずれは起きないので特別な処置は要らない。 72241 これを確かめる為には HISTIGNORE や ignorespace の判定を自前で行わなければならないのではないか。 72242 然し、二重に判定を行うのは具合が悪い。あるいは履歴項目の登録部分で履歴が登録されたかどうかの情報を返す様にするか。 72243 例えば [[ -v histadd_status ]] && histadd_status=$result の様にして。 72244 72245 もっと良い判定方法があるのではないか。 72246 実行したのが昔の履歴項目だった場合に登録が起こるのはどの様な時だろう。 72247 HISTIGNORE に引っかからなかった場合である。 72248 ignoredups に引っかかる事は基本的にない、と思ったがよく考えて見れば 72249 同じ内容の文字列が履歴項目の一番上にある場合には普通に ignoredups に引っかかるのではないか。 72250 つまり、履歴登録試行後に一番上の要素が実行した文字列と同じかどうかを見るだけでは 72251 実際に新しく履歴項目が登録されたかどうかを正確に判定することは不可能である。 72252 72253 という事はやはり history/add から結果を返す様にする必要があるか。 72254 実際に履歴項目の追加が発生したかどうかの判定を返すようにしても良いが、 72255 結局その情報が得られたとしても accept-and-next 側で、 72256 accept-line の内部実装に依存する様な処理を実行する必要がある。 72257 そのような構造になっていると将来的に history/add の処理方法を変更した時に問題が生じる。 72258 そういうことを考えれば、履歴項目番号の shift も含めて 72259 history/add の側で処理してしまったほうが良いのではないか。 72260 という訳で history/add の内部で shift も実行することにする。 72261 72262 b 実行したのが一番最近の履歴項目だった場合には、 72263 c 実行したのが最新の編集文字列だった場合には、 72264 72265 % 何れにしても一番最後に登録された項目に移れば良い。 72266 % erasedups や ignoredups の場合には、 72267 % 一番最後に登録された項目というのは丁度一番最後に実行したコマンドになっている筈だからである。 72268 % しかし、問題点は HISTIGNORE もしくは ignorespace によって、 72269 % 一番最後に実行したコマンド自体が履歴に登録されなかった場合である。 72270 % その場合には新しい編集文字列を用意して、そこに実行したコマンドの内容をコピーする事にする。 72271 72272 よく考えたらこれは一番最近の履歴項目を実行した場合ではなくて、 72273 履歴項目を編集して実行した場合ではなくて、最新の編集文字列を実行した場合の処理である。 72274 一番最近の履歴項目を実行した場合には、既に履歴項目として登録されているという事だから、 72275 もし HISTIGNORE ignorespace によって登録されなかったとしても、単に一番最近の履歴項目に移動すれば良い。 72276 但し、最近の履歴項目を編集してから実行した場合にはまた異なる処理が必要になる。 72277 というか、最新の編集文字列を編集した時と同じ処理で良い。 72278 72279 結局、一番最近の履歴項目だった場合と最新の編集文字列だった場合は処理を統合するのが良いだろう。 72280 取り敢えず、実行と履歴項目への登録を試行する。 72281 登録を試行した後に一番上にある履歴項目の内容が実行したものと同じであればそこに移動する。 72282 (もし内容が異なるのであれば、それは HISTIGNORE/ignorespace によって登録されなかった上に、 72283 一番最近の履歴項目を編集してから実行したor最新の編集文字列だったという事である。) 72284 もし内容が異なる場合には、最新の編集文字列に実行したのと同じ文字列を指定すれば良い。 72285 72286 * [check] 複数のコマンドを一度に入力し場合に、実際の実行を遅延している。 [#D0354] 72287 この時に履歴番号 (PS1 の \! という指定で表示される物) と 72288 実際の履歴項目の番号はちゃんと一致したものになっているか。 72289 72290 懸念として、実行前だから履歴番号が前のコマンドと重複してしまったり、 72291 或いは履歴項目の登録の際に登録が前後したりして番号がずれる事があるのではないか 72292 と考えたが特に問題は無いようであった。 72293 72294 * ble-edit/history/add: bug HISTCONTROL=erasedups:ignorespace が指定されている時に [#D0353] 72295 ignorespace に当たると履歴項目が消滅する。 72296 ignorespace ignoredups について確認して引っかからなかった場合にのみ erasedups するべき。 72297 HISTIGNORE に関しては先にチェックを行っているので問題ない。 72298 72299 * ble-edit: bug C-r で現在行の内容に一致しない。 2016-09-07 [#D0352] 72300 72301 2016-08-08 72302 72303 * mintty で xenl 絡みの動作がおかしい [2016-08-07] [#D0351] 72304 丁度端末の横幅と同じに為る様な履歴項目が登録されている時に項目を辿るとなっている。 72305 後で動作を調べる必要がある。 72306 もしかすると mintty と同じタイプの物では全て動作がおかしくなっている可能性がある。 72307 72308 というか今 screen で試してみてもカーソルの位置が怪しい。 72309 mintty とは又別の変な振る舞いをしているが、 72310 どうも ble.sh は次の行にカーソルを移しているつもりにいなっているが、 72311 実際には次の行にはカーソルが移っていないという事の様である。 72312 本来は次の行にちゃんとカーソルが移動する様にする必要がある。 72313 xenl 周りの計算について再度確かめる必要があるだろう。 72314 72315 xenl 周りの計算は少し見た限りは問題が何処にあるか分からない。 72316 動作確認もしながら探す必要があるだろう…と思って何となく echo $_ble_term_xenl したら変だ。 72317 rosaterm (xenl なし) でも screen (xenl あり) でも常に 0 になっている。 72318 と思って term.sh の中を覗いたら、情けないことに ble/term.sh/tput tput xterm という具合に、 72319 tput に tput を渡していた。直接の tput 使用から ble/term.sh/tput 経由での使用に切り替えた際に、 72320 元からあった tput を削除し忘れていたということであろう。 72321 72322 また他にも類似のミスがないか確認する。他にはないようだ。 72323 72324 一応 _ble_term_xenl について確認: 72325 - _ble_term_xenl=1 ... xenl あり。tput xenl; echo $? の結果は 0 (成功) 72326 - _ble_term_xenl=0 ... xenl なし。tput xenl; echo $? の結果は 1 (失敗) 72327 echo $? の結果と _ble_term_xenl の内容が逆転していることには注意する。 72328 72329 > * isearch: 検索中に長い履歴項目があるとカーソル行がずれる。 [2016-07-08] 72330 > 72331 > このずれはカーソルが一番上の行にある場合に起こる様だ。 72332 > カーソルが二行目以降にある場合は発生しない。最終行にある時でも発生しない。 72333 72334 以上の問題もこの修正によって直ったと思われる。 72335 72336 72337 2016-08-07 72338 72339 * Windows では管理者権限があるかどうかは [#D0350] 72340 test -w "$(cygpath -u $WINDIR)" 72341 で判定することができる。 72342 72343 cygpath に関してはプロセスを起動していると遅いので自前で実装する? 72344 変な文字が含まれていない限りにおいては簡単に実装できる筈である。 72345 72346 72347 2016-08-06 72348 72349 * edit: bug 履歴項目に登録されなくなる現象 [#D0349] 72350 72351 突然、履歴項目に登録されなくなってしまう現象に出会う。 72352 但し、history -s では登録されている様である。 72353 72354 調べてみると空白が登録されている様子である。 72355 というかこのプロセスはいつの version なのだろうか。。 72356 72357 % % 更に現象の発生したシェルで調べてみると、 72358 % % _ble_edit_history と同じだけ要素数を持っている筈の 72359 % % _ble_edit_history_edit 配列の中身が殆ど空になっている。長さが 20 だ。 72360 % % そもそも何故その様な事態になったのかも不思議であるが、 72361 % % これが履歴が登録されない原因なのだろうか。 72362 % % 取り敢えず、問題を確認する為に _ble_edit_history_edit の内容を復元してみる。 72363 % % →問題は発生しなくなった様に見える。 72364 % % 従って、_ble_edit_history_edit さえ空にならなければこの問題は発生しないのではないかと思われる。 72365 % % 72366 % % さて、ではそもそも何故 _ble_edit_history_edit の中身が空になってしまったのだろう。 72367 % % 再度 _ble_edit_history_edit に変更が発生しそうな箇所を探す。 72368 % 72369 % と思ったが変だ。問題が発生した直後に実行した以下のコードではちゃんと 72370 % _ble_edit_history_edit の中身は沢山の項目が登録されている。 72371 % 72372 % [murase@padparadscha 1 xgetopt]$ echo ${#_ble_edit_history_edit[@]} 72373 % 21034 72374 % 72375 % 登録されている項目数も前後に実行した history | tail の結果と較べても正しい物の様に見える。 72376 % 72377 % これで二つの謎現象が起こっていたという事になる。 72378 % 72379 % a 何故か分からないが履歴項目が登録されない状態になる。 72380 % history -s には登録されている。 72381 % b 更に原因を探す為に色々実行していると、 72382 % _ble_edit_history_edit の中身が空になってしまった。 72383 % 72384 % と思って再度前にテストの為に実行したコマンドを確認してみると、 72385 % echo "${#_ble_edit_history_edit[0]}" 72386 % を実行していた。つまり、配列の要素数ではなくて配列の先頭要素の長さを確認していた。 72387 % ただの勘違いだった。 72388 72389 さて上記の勘違いで唯一分かった事は、 72390 _ble_edit_history_edit=("${_ble_edit_history[@]}") 72391 を実行したら以上状態から直ったという事である。 72392 うーん。一応近辺の出力内容を記録しておく。 72393 72394 | [murase@padparadscha 1 xgetopt]$ history | tail 72395 | 21020 git submodule --help 72396 | 21021 g t 72397 | 21022 pwd 72398 | 21023 less xgetopt.h 72399 | 21024 g add remote origin git@gitlab:akinomyoga/libmwg-xgetopt.git 72400 | 21025 g remote origin git@gitlab.akinomyoga/libmwg-xgetopt.git 72401 | 21026 false 72402 | 21027 true 72403 | 21028 g remote add origin git@gitlab:akinomyoga/libmwg-xgetopt.git 72404 | 21029 history | tail 72405 | [murase@padparadscha 1 xgetopt]$ 72406 | [murase@padparadscha 1 xgetopt]$ 72407 | [murase@padparadscha 1 xgetopt]$ echo ${#_ble_history_edit_dirt[@]} 72408 | 0 72409 | [murase@padparadscha 1 xgetopt]$ echo ${#_ble_history_edit[@]} 72410 | 0 72411 | [murase@padparadscha 1 xgetopt]$ echo ${#_ble_edit_history_dirt[@]} 72412 | 0 72413 | [murase@padparadscha 1 xgetopt]$ echo ${#_ble_edit_history_edit[@]} 72414 | 21034 72415 | [murase@padparadscha 1 xgetopt]$ echo ${_ble_edit_history_dirt[@]: -10} 72416 | 72417 | [murase@padparadscha 1 xgetopt]$ echo ${_ble_edit_history_edit[@]: -10} 72418 | history | tail echo ${#_ble_history_edit[@]} echo ${#_ble_edit_history_dirt[@]} echo ${_ble_edit_history_edit[@]: -10} 72419 72420 うーん。どうやら ${#_ble_edit_history_edit[@]} の数が余分になっている様に見える。 72421 上記のタイミングでは本当は 21034 になっているべきである。 72422 何かが無駄に登録されてしまっている状態である。 72423 では何故その様な事になるのか? 72424 72425 →原因が分かった。現在最新の行を編集してから (何か非空の内容がある状態で) 履歴項目を移動すると、 72426 その現在最新の行が _ble_edit_history_edit に登録される。 72427 これはまた最新の行に戻ってきた時に参照する為に必要になる物である。 72428 また、この編集仕掛の行は検索の対象でもある。 72429 この時点で _ble_edit_history と要素数が異なってしまう。 72430 →実際に試してみた所、再現した。 72431 編集して echo という文字列がある状態で別の履歴項目に移る。 72432 その後でコマンドを実行する。ずれが生じる。確かに履歴項目に登録されなくなる。 72433 72434 つまり、_ble_edit_history の要素数と _ble_edit_history_edit の要素数が 72435 同じ筈だという仮定は成立しない物として取り扱わなければならない。 72436 多分、_ble_edit_history/_ble_edit_history_edit に同時に項目を登録している箇所で注意しておけば問題ない。 72437 72438 + 一箇所 _ble_edit_history から項目を削除しているのに、 72439 _ble_edit_history_edit から項目を削除していない箇所を発見する。 72440 これについては修正した。 72441 しかし、この事によって _ble_edit_history_edit の中身が空になるとは思われない。 72442 寧ろ、_ble_edit_history よりも余分な要素が残留してしまうという逆の現象になるはずだ。 72443 更に、現在の HISTCONTROL の設定ではこのコードは実行されないはずである。 72444 72445 * syntax: bug 他の問題を調査中に以下のエラーも発生した。 [#D0348] 72446 72447 _ble_edit_history_edit が空になる事故を調べる為に配列 _ble_edit_history の内容を 72448 出力しようとしたりして試行錯誤している時に以下の stackdump が生じた。 72449 72450 stackdump: unexpected ntype="${ for arithmetic expression 72451 @ /home/murase/prog/ble/ble.sh:1709 (ble-syntax:bash/ctx-expr) 72452 @ /home/murase/prog/ble/ble.sh:-16 (ble-syntax/parse) 72453 @ /home/murase/prog/ble/ble.sh:4 (_ble_edit_str.update-syntax) 72454 @ /home/murase/prog/ble/ble.sh:-135 (ble-highlight-layer:syntax/update) 72455 @ /home/murase/prog/ble/ble.sh:4598 (ble-highlight-layer/update) 72456 @ /home/murase/prog/ble/ble.sh:4933 (.ble-line-text/update) 72457 @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 72458 @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 72459 @ /home/murase/prog/ble/ble.sh:1157 (ble-edit/bind/.tail) 72460 @ /home/murase/prog/ble/ble.sh:-4279 (ble-decode-byte:bind/EPILOGUE) 72461 @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 72462 72463 1. echo ${_ble_edit_history_edit[@]: -10} 72464 2. echo ${_ble_edit_history_edit[@]: -10}" 72465 3. echo "${_ble_edit_history_edit[@]: -10}" 72466 72467 というか直接 3. を入力してもなる。 72468 何と、以下を入力するだけでなる。 72469 72470 $ echo "${a: -1}" 72471 72472 メッセージを見るに、単に ${ に入る時に nest の値として 72473 " も巻き込んで登録してしまっているというだけの事だろうか。 72474 調べてみることにする。 72475 72476 →調べてみると明示的に '"${' を nest-push している様だ。 72477 これは何の為に使っているのだろうか → "${...}" と ${...} では 72478 中のエスケープなどの取り扱い方法が異なる。これを区別する為の物である。 72479 更にこれを nest-push する時点では後ろで算術式 (:offset:length)が来るか 72480 もっと複雑な物が来るかの判定も出来ない。 72481 72482 それによく考えてみれば算術式の中であっても "${...}" と ${...} で違いがあるのではないか? 72483 そもそも "${...}" と ${...} の中の文字列の取り扱いの違いは何だったか。 72484 function ble-syntax:bash/check-quotes のコメントに書かれていた。 72485 72486 # "${var ~}" の中では '' $'' $"" は無効 (-u extquote の時は '' が無効) になる。 72487 72488 この事は ${} の中にある算術式の中でも有効の様に思われる。 72489 というか良く考えてみると、それだけではなくて "${... ${...}}" の中でも有効でなければならない気がする。 72490 現在の判定では ${...} が始まった所の文脈が CTX_QUOT かどうかだけで見ているが、 72491 そうではなくて先祖に CTX_QUOT がないかどうか (但し途中に $() などがあったら其処で探索を止める) 72492 などのように複雑な判定をしなければならないのではないだろうか。 72493 72494 取り敢えず現在の所は、算術式の中で判定として '${' だけでなく '"${' も考慮に入れる事にする。 72495 また、"${var: 算術式}" の算術式に含まれる '' $'' $"" についても正しく処理を行う (quote として解釈しない)。 72496 更に、正しい '' $'' $"" の判定方法に関しては別項目として立てる事にする。 72497 72498 2016-08-05 72499 72500 * 実は Windows 10 で試すと /dev/tcp/0.0.0.0/80 [#D0347] 72501 はエラーメッセージを出力する → これは駄目だ。 72502 やはり Cygwin では別の方法を用いる必要がある。 72503 取り敢えずのところは &>/dev/null にして様子を見る事にする。 72504 72505 →既に 1s 以上の場合には /dev/tcp を使わない方法を使っているので、 72506 いつでもその /dev/tcp を使わない方法を使用することにした。 72507 しかしこの方法だと子プロセスが死んだ時に sleep が動かなくなる。 72508 72509 この問題を解決する為には子プロセスの pid を覚えておき、 72510 死んでいたら確認して再度設置するなどの処置が考えられる。 72511 しかし面倒である。 72512 72513 % それよりは cygwin 専用の builtin sleep を添付してしまっても良い気がする。 72514 % cygwin/cygwin64 bash-4.1/4.2/4.3 それぞれについてコンパイルして添付する。 72515 % 一致する version がなければ現在の方法に fall back する様にすれば良い。 72516 % もし cygwin に binary を添付することを許すのであれば、 72517 % stty に関しても cygwin 用に builtin として提供してしまって良い。 72518 % 72519 % しかし、この事の問題点は binary を添付することを許してしまうと、 72520 % 今迄スクリプトで実装してきたことの意味は何なのかという事になるという事である。 72521 % 一応、そのバイナリが使えなくても問題なく動作するという点は有意義であるが。 72522 % バイナリが使えなくても動作するということを保証するのであれば、 72523 % 多少性能が劣るとしてもそのままで良いじゃないかという気もする。 72524 72525 2016-07-15 72526 72527 * [保留] _ble_edit_history_edit の初期化時間について [2016-07-07] [#D0346] 72528 72529 検索速度の向上の為に配列 _ble_edit_history_edit において、 72530 配列 _ble_edit_history と同様に完全な履歴を保持する様に変更した。 72531 その為に、一番最初の初期化時に _ble_edit_history_edit のコピーが必要になる。 72532 72533 気になるのは初期化にかかる時間が余計にかかる様になることだが実際にやってみた所体感としては余り変わらない。 72534 (もし気になるのだとしたら初期化についても progress を表示する様に変更する必要がある。 72535 或いは edit を使用するまでは edit の初期化は遅延するなど。) 72536 因みに、 72537 72538 $ time ble-edit/history/.generate-source-to-load-history >/dev/null 72539 real 0m0.600s 72540 user 0m0.683s 72541 sys 0m0.119s 72542 72543 $ time eval -- "$(ble-edit/history/.generate-source-to-load-history)" 72544 real 0m1.210s 72545 user 0m1.273s 72546 sys 0m0.165s 72547 72548 $ time _ble_edit_history_edit2=("${_ble_edit_history[@]}") 72549 real 0m0.320s 72550 user 0m0.316s 72551 sys 0m0.004s 72552 72553 _ble_edit_history 本体の初期化時間に較べれば _ble_edit_history_edit 72554 の初期化時間は 1/4 程度なのでそれほど問題という訳でもない。 72555 また、工夫してコピー速度を向上しようにもこれ以上の工夫のしようはないと思われる。 72556 72557 もし改善するのだとしたらコピー自体の速度向上ではなくて、 72558 コピーの遅延を行う様に修正した方が賢明である。 72559 72560 [_ble_edit_history 自体の初期化高速化] 72561 72562 あるいは、一番時間の掛かっている _ble_edit_history 初期化の方の改善が必要である。 72563 しかしこれ以上の高速化の方法は思い浮かばないし、 72564 また、部分的なロードをして残りは遅延にするなどの処置をするとしても、 72565 結局履歴を登録する際や検索を実行する際に、効率の問題から全部をロードする事を余儀なくされるだろう。 72566 72567 % 本当に改善するのだとしたら、履歴項目を独自形式で保存するような .bash_history の ble 版を管理する事になる。 72568 % 72569 % a その様にすれば mapfile/readarray などを用いて比較的高速に読み込める様にできる…かもしれない。 72570 % 実際に mapfile/readarray などのコマンドが本当に速いのかどうか (どれだけ速いのか) は確かめる必要がある。 72571 % 良く考えたら複数行に渡る履歴項目も管理しなければならない。mapfile/readarray だと改行を含む要素を読み込めないので、 72572 % 読み込んだ後で後処理を行う様な方式にしなくては為らない。しかしこれは時間が掛かる。 72573 % 72574 % b それよりは source できる様な形式にしておく方が賢明である。 72575 % 或いは eval -- "_ble_edit_history=$(< ble_history)" 72576 % の様にして eval で評価するか。結局今の方式と大して変わらない。 72577 % 72578 % (今の方式の bottle neck が awk の方にあるのだとしたら 72579 % 現在の awk の出力をキャッシュする事によって高速化が可能という事になる。 72580 % しかし bottle neck が bash の eval の方にあるのだとしたら残念ながら余り効果はないだろう。 72581 % それぞれ時間を計測する必要がある。 72582 % 72583 % eval $() にしていると非同期動作はしないので 72584 % 処理時間は awk の処理時間 + eval 時間という形に上乗せになっている。 72585 % さて上記の時間計測を見てみると、awk に 0.6s であり、 72586 % eval に 0.610 である。という事は awk の出力内容をキャッシュすることによって初期化時間を半減させる事ができるという事になる。 72587 % 72588 % しかし問題点は awk の出力内容をキャッシュしたとして、.bash_history との整合性をどの様に保つのかという事である。 72589 % a 一つの方法は .bash_history の内容は完全に無視して history で別の履歴を読み込んでしまうという事である。 72590 % しかし、これは既存の .bash_history を無効にしてしまう事になるのでユーザに混乱を与える。 72591 % また、終了時に ble が勝手に追加した内容が .bash_history に追記されないようにするなどの対策も必要である 72592 % b もう一つの方法は .bash_history の内容は飽くまで尊重して、 72593 % .bash_history に対する変更を検出して ble history cache ファイルの内容も更新する様にする事である。 72594 % しかしそれは結構面倒な事の様な気がする。結局その更新には awk などで大量の処理をする必要が生じ、 72595 % 現在の方法と速度的に変わらなくなる気がする。。 72596 % 72597 % やはりこの履歴項目を独自方式で保存する作戦は余りよくない気がする。 72598 72599 また別の高速化手法として、起動時に非同期で履歴初期化用プロセス (awk) を起動して 72600 source 用のファイル (仮に history.src とする) を生成しておき、 72601 必要になった時に awk が終了しているのを確認して source history.src を行うという方法である。 72602 - 懸念の一つは起動後・履歴初期化前に追加された履歴項目をどの様に反映するのかという事であるが、 72603 これは初期化前に追加された履歴項目についてはその都度 history.src に追記するという方法で行ける。 72604 - もう一つの懸念は履歴初期化用プロセスがジョブ管理から見えてしまうことである。 72605 これについては disown して、wait する代わりに kill -0 && sleep で待つしかないだろうか。しかし sleep が難しい。 72606 或いは名前付きパイプで同期を取るという手も考えられるがそうすると初期化用のプロセスがいつまでも残存する事になるので好ましくない。 72607 72608 * complete: double quotation の中で変数名の補完が起こらない。 [2016-07-09] [#D0345] 72609 →何でか分かった。ctx==CTX_CMDI 等の中で check/parameter-expansion を呼び出しているからだ。 72610 しかし、実際には "" の中に $VAR がある場合には ctx==CTX_QUOT になっている。 72611 72612 * complete: というか ${...} の中でも変数名の補完が起こらない。 [2016-07-09] [#D0344] 72613 72614 * complete.sh: bug 変数名の補完確定時に = の代わりに ' ' が挿入される。 [2016-07-05] [#D0343] 72615 72616 実の所、挿入したいのは += かもしれない。 72617 また、declare の引数などの場合には = でも += でもなく ' ' を挿入したいのかも知れない。 72618 配列変数の場合には =( 等の様にした方が親切かも知れない。 72619 72620 しかし取り敢えずは最大公約数的な補完として = を挿入する様にして良いのではないか。 72621 少なくとも ' ' を挿入するよりはましだし、また、変数代入においては、何も挿入しないよりは分かりやすい。 72622 ただ、declare の引数などに使用する際に何も挿入しない方が良いかも知れない。 72623 が、実際に使ってみてその辺りは判断する。 72624 72625 * 以下、GLOBIGNORE が必要なのではないか。 [2016-07-05] [#D0342] 72626 72627 ./complete.sh:197: IFS=$'\n' builtin eval 'arr=($(ble-complete/source/command/gen))' 72628 ./complete.sh:374: IFS=$'\n' builtin eval 'arr=($compgen)' 72629 ./complete.sh:385: # * arr($(...)) としないのは IFS=$'\n' の影響を $(...) の中に持ち込まないためである。 72630 ./complete.sh:421: IFS=: eval 'tmp=($FIGNORE)' 72631 ./complete.sh:485: IFS=$'\n' builtin eval 'arr=($(compgen -v -- "$COMPV"))' 72632 72633 また以前の GLOBIGNORE を使っている箇所も含めて ble/string#split を定義して使い回した方がよいのではないか。 72634 → ble/string#split を追加する事にした。 72635 72636 * ble/util/joblist: 実は set -b でジョブ状態の変更が即座に出力される? [2016-07-08] [#D0341] 72637 72638 →でもこれだと bash の stdout/off にしている時に出力された場合などの処理が面倒である。 72639 標準出力を監視して何か出力されたらそれがジョブ状態の変更に関する物であるかどうかを判定し、 72640 72641 更にジョブ状態の変更に関する物であればその部分を切り出して出力しなければならない。 72642 しかし、切り出すと言ってもジョブ項目が何処で終端するのか分からないので確実な方法は分からない。 72643 途中で切れた離別の出力が混ざったりしてしまう可能性がある。 72644 72645 現在の実装で問題なく動いているのだからこの方針を考える必要はないのではないか。 72646 72647 * ble/util/sleep: sleepenh, usleep への fallback [#D0340] 72648 72649 * isearch: backward-search で既に一致している部分を部分に持つ新しい一致がなされない。 [2016-07-07] [#D0339] 72650 例えば履歴に qqq が一件だけ存在する時に、isearch で qqq と入力すると一致しない。 72651 というのも qq まで入力した段階で qqq の内の後半二文字に一致が為され、 72652 新たに qqq を検索しようとしてもこの qqq は一致対象とはならないからである。 72653 72654 この修正は簡単だ。と思ったらそうでもなかった。 72655 72656 % 適当に検索範囲を変更したら C-r が効かなくなってしまった。 72657 % 今迄と同じものに一致してしまうからである。 72658 % 修正するべきは isMod の時の検索であった。 72659 72660 さて、isMod のときの検索範囲を修正するにしてもどの様に修正したらよいのかは謎である。 72661 現在は isMod のときには一致開始位置を固定したままその場で文字列を伸張する方向で更新を行う。 72662 しかし、qqq の時の様に一致終端位置を固定したまま伸張する場合もあれば、 72663 また、伸張ではなくて少しずれてから一致する様な場合も考えられる。 72664 72665 その様な場合も含めて考えると実は backward-search ばかりでなく forward-search にも問題がある事になる。 72666 例えば aba なる連なりが或る一箇所 ababac にのみ含まれていたとする。 72667 ここで abac を順方向に検索しようとすると一致しないという事になる。 72668 何故ならば aba まで入力した段階で [aba]bac に一致し、その後に c を入力したとしても、 72669 [abab]ac という一致と、aba[bac...] という一致しか試みられないからである。 72670 72671 これを解決する為には一致位置の伸張ばかりでなく、 72672 多少ずらした一致も許す様にしなければならない。 72673 実の所、現在の isMod の部分のコードは不要で、 72674 唯単に検索範囲を isMod に応じて変更するだけで良いのではないだろうか。 72675 →いや、逆方向の探索の時は入力して行く内に今迄一致していた位置よりも範囲が戻る事がある。 72676 そもそもその為に isMod の時の範囲が修正されているのだ。 72677 なので、isMod の時専用のコード (一致範囲延長) はそのままで、 72678 通常の検索の部分の範囲を isMod に応じて変更する様にすれば良い。 72679 72680 % ble-edit/isearch/next.fib を修正して次の様な処理を行う様に変更した。 72681 % 72682 % 0. 前提として検索中は _ble_edit_ind は一致範囲先端を表し、 72683 % _ble_edit_mark は一致範囲後尾を表す事にする。 72684 % 順方向検索の場合は先端は範囲終端位置であり、後尾は範囲開始位置である。 72685 % 逆方向検索の場合は先端は範囲開始位置であり、後尾は範囲終端位置である。 72686 % 72687 % 1. もし isMod (検索文字の追加) を行う場合には現在位置に於ける一致範囲の拡張を試す。 72688 % 72689 % 例えば順方向検索で [abc]de の様に一致している 72690 % (文字列が abcde で現在 abc に一致しているという意味である) 場合、 72691 % 初めに [abcd]e の一致を試みる。 72692 % 或いは、逆方向検索の場合には例えば a[bcd]e に一致している時は、 72693 % 初めに a[bcde] の一致を試みる。ここで一致範囲 (後尾) が後退することに注意する。 72694 % 72695 % 2. 次に通常の検索に入る。 72696 % 72697 % 但し、isMod のときとそうでない時で一致の範囲を変更する。 72698 % isMod の時には自己にオーバーラップした一致を許可する。 72699 % isMod でない時 (次の一致を探す時) は自己にオーバーラップしない一致を試す。 72700 % 72701 % 自己にオーバーラップしない一致を試すのは簡単で検索開始位置を先端 _ble_edit_ind に設定すればよい。 72702 % 自己にオーバーラップすることを許す場合は順方向検索の場合には _ble_edit_mark+1 から検索を行えばよい。 72703 % 但し、_ble_edit_mark が既に文字列末端に位置している場合は _ble_edit_ind (== _ble_edit_mark のはず) にする。 72704 % 逆方向検索の場合は微妙で、基本的には _ble_edit_mark-1 から逆方向に検索をしたいが、それだと、 72705 % q[qq] だった所にを [qqq] を入力して 1 文字ずれて一致が起こる様な場合に対応できない。 72706 % つまり一致先端が 1 ずれる事によって一致末端がずれないということも可能である。 72707 % 従って、実は _ble_edit_mark にすれば良い。それだと同じ場所に一致する様にも思われるが、 72708 % 実際は自己にオーバーラップする事を許すのは isMod の時のみであるので、同じ範囲に一致することはない。 72709 72710 しかしながら実は上記の 1 と 2 は統一可能なのではないかという気がする。 72711 →統一した。実際の所現在位置に於ける一致範囲の拡張というのは、 72712 2. の検索範囲を一つ増やすだけで 2 の動作に含ませることができる。 72713 意外と簡単にすっきりとした実装にまとまった。 72714 72715 rename: 今迄 isMod としていた識別子を isAdd に変更する。 72716 現在の実装に於いて、検索文字列の変更が実質文字の追加しかないこと、および、 72717 文字の追加しかないということを前提とした実装になっていることから。 72718 将来的に文字の追加以外の変更に対応した時に問題が生じないために。 72719 72720 2016-07-09 72721 72722 * history: bash-3.0 で history に履歴が登録されないので、 [#D0338] 72723 72724 履歴展開などの番号がずれてしまう。 72725 →良く考えてみたら history -r filename 等を用いて履歴を追加できるのではないか。 72726 実際に試してみた所期待通りに動作する様である。 72727 72728 但し、history に登録できたとしても依然として終了時に履歴ファイル (.bash_history) には 72729 追加されない様である。というのも元からファイルから読み込んだ行なので 72730 敢えて .bash_history に追記する事はないという事なのだろう。 72731 これは今迄通りに手動で (その場で) 履歴項目を書き出す必要がある。 72732 72733 * history: bash-3.0, 3.1 で履歴が登録されないだけでなく、 [#D0337] 72734 _ble_edit_history などにも追加されない様だ。 72735 history コマンドで履歴を追加できないのは以前から問題だったが、 72736 地震の管理する履歴に関してはどの様に処理する事になっていたのだったか。 72737 再確認が必要である。 72738 72739 更に、コマンドを実行した直後、履歴内の位置がそのままになっている。 72740 一番最後に移動するべきである。最後に移動する処理は履歴に登録した後に為された物だった事を重うと、 72741 履歴に登録する過程で途中で抜けてしまっているという事なのだろう。 72742 72743 2015-08-19 に関連しそうな議論が残っているが、同様の問題については言及されていない。 72744 つまりこの時点では特に大きな問題は生じていなかったという事になる。 72745 現在までの間に何か問題を埋め込んだという事だろう。 72746 72747 →分かった。[[ -o history ]] のチェックで死んでいる。 72748 しかし bash のマニュアルを見ても history というのが新機能だと書かれていない。 72749 bash changes を見ても wiki を見ても新しい機能として history が実装されたという話はない。 72750 古い MANPATH で bash のマニュアルを見たが何と bash-3.1 でもちゃんと history という項目はある様だ。 72751 ここで set -o で現在設定されているオプションの一覧を見ることができるというので見てみる。 72752 何と history off になっている。つまり項目として存在していてしかも off になっているという事である。 72753 bash-3.0 3.1 では off になっていて、bash-3.2 では on になっている。 72754 さて、試しに bash --norc で起動してみると何れの version でもちゃんと初めから on になっている。 72755 どのタイミングで off になってしまうのだろうか。 72756 - --norc で起動した後に source .bashrc をすると off になってしまう。 72757 - というか source ble.sh すると off になる。 72758 - ble-detach すると on になる。 72759 - ble-attach すると off になる。 72760 - bind -x '"\C-t":set -o' して C-t をすると ble-detach していても off である。 72761 - --norc で起動した直後に bind -x '"\C-t":set -o' としても off である。 72762 72763 つまり bash-3.0, 3.1 では bind -x のハンドラの中では常に history off という訳である。 72764 bind -x の中で、bind -x 以外の実行で history が on になっているかどうか確かめる方法は無さそうだ。 72765 それならば interactive かどうかで判断を代用するしかないのではないだろうか。 72766 interactive かどうかで言えば ble が起動している時点で interactive である。 72767 なので常に有効になっていると思って良いのではないか。 72768 72769 > それとは別に気になるのが $- である。$- で表示される文字がそれぞれ何を意味するのかについて…。 72770 > 調べようとしたがマニュアルの何処に載っているか分からない。オプションフラグを表示するとその説明には書かれているが、 72771 > そもそもオプションフラグという単語がそこ意外に記述されていない。 72772 > →と思ったら set 組み込みコマンドの説明の下の方に現在のオプションの集合は $- で知る事ができると書かれている。 72773 > 明示的に書かれていないが実の所一文字オプションが定義されている項目についてはその文字が $- に含まれるということなのだろう。 72774 > それとは別に bash が -i で起動された時には i が $- に含まれるとも別の箇所に書かれている。 72775 > さて、実際に $- に含まれている文字で h や H は何だろう。見てみると h は hashall で、H は histexpand である。 72776 > history 自体の on/off に関連する文字は割り当てられていない様だ。 72777 72778 2016-07-08 72779 72780 * bash-3.2 補完確定した時のカーソル位置が変だ。 [#D0336] 72781 72782 よく見たら shopt: autocd なんて知らない、というエラーが表示されている。 72783 つまり shopt -q を実行する際には 2>/dev/null にするべきという事である。 72784 修正した。 72785 72786 さて、ble-0.1 の方ではどうなっていたかと確かめてみた所、 72787 なんとちゃんと &>/dev/null になっていた。その他の shopt についてもついている。 72788 つまり、何処かの時点で不要だと勘違いして除去したという事になる。 72789 blame で見てみた所 854babfc62a0d7865c5cf53db0a9c42ee8813c56 (2015-12-19) 72790 の大幅な整理の際に消してしまっていた。 72791 72792 * prompt: PS1: PROMPT_DIRTRIM を実装する。 [#D0335] 72793 72794 例えば 2 に設定すると、~/hello/test/world は ~/.../test/world になり、 72795 /home/foo/bar は .../foo/bar になる。 72796 これは param_wd の段階で省略してしまえば問題ないだろう。 72797 72798 この機能は bash-3.2 以降の様だが関係なく実装してしまって問題ないだろう。 72799 72800 * prompt: PS1 \n 周りの動作? → 勘違い [#D0334] 72801 72802 % IND のつもりで \n を出力しようとするが \e[B が出力されている気がする。 72803 % これのせいで端末の最終行に何かを表示しようと言う目論見が失敗する。 72804 % →調べてみたが \n に対しては NEL = \r\n を出力している。 72805 % では何故 IND が効いていないのだろうか…。 72806 72807 →そもそも PS1 に最終行を追加する為に記述したシーケンスが誤っていただけの様だ。 72808 \e[s, \e[u でカーソル位置を復元するとしても、画面がスクロールされてしまうと意味がない。 72809 そして IND の積もりで \n やら \eD を出力するとスクロールされてしまうので \e[s, \e[u 72810 しても画面バッファ上の同じ位置には戻ってこない事になる。 72811 従って、下に一行追加する為には IND RI するのが良い。 72812 72813 % 所が、現実の端末では IND を実装しているとは限らないし、 72814 % 大体の terminfo では (端末が実際に対応しているとしても) IND に対して \n が記述されている。 72815 % しかし、それは仮想端末の設定で \n が \r\n に変換されない状況でしか意味がない。 72816 % というのも \r が混入してしまう所為で列の位置が先頭になってしまい、 72817 % 単に IND RI しただけでは元の位置に戻ってくる事ができないのだ。 72818 % まあ、元の位置に戻ってくる必要がないのであればこれで問題ない。 72819 % しかし元の位置に戻ってくる必要がある時にはどうするのだ? 72820 72821 と思ったがよく見たら ble-edit/draw/trace/process-esc-sequence でちゃんと 72822 その場合の為の対策もされていた。\eD は変換されて "\n + 列の位置に移動" に変換されていた。 72823 つまり ble においては単に PS1 に \eD を記述しておけばよいという事になる。 72824 72825 従って、プロンプトで最終行を追加する方法: 72826 PS1 の "末端" に以下を追加する。末端でなければならないのは PS1 72827 が複数行で構成されている場合を考えての事である。 72828 72829 '\[\eD\eM\e7\e[${LINES}H\e[7m hello \e[m\e8\]' 72830 72831 しかしこれだとコマンド実行時に最終行がごみとして残って厄介だ。 72832 削除できないだろうか。あるいは先頭行に表示する方が現実的かも知れない。 72833 72834 '\[\e7\e[H\e[7m hello \e[m\e8\]' 72835 72836 しかし、それだと以前に出力された内容を汚す事になってしまう。 72837 PS1 だけではどうにもならなそうだ。もしこの様な機能を提供するのだとしたら、 72838 RPS1 と同様に LPS1 だとか HPS1 だとか何かの変数を作って ble 側で特別に処理する必要がありそうだ。 72839 72840 * prompt: 履歴番号 [#D0333] 72841 72842 よく考えたら PS1 の \! の番号は履歴展開で使う為にあるのではないか。 72843 だとすれば、history に登録されている番号と実際の番号が一致している必要がある。 72844 ところが試してみると 1 ずれている。 72845 72846 bash の動作をもう少し詳しく見てみる事にする。 72847 例えば履歴に 3 項目登録されている時に \! で表示される番号は 4 である。 72848 つまり \! は既に登録されている項目の数ではなくて、 72849 "現在の行が登録された時に登録される番号" であって、履歴項目の数より1つ多い。 72850 72851 ${_ble_edit_history[]} の中身も確認してみる。番号がずれている… 72852 と思ったが、良く考えたら history の結果は 1 base の系列である。 72853 従って 1 ずれている事は問題ない。 72854 72855 また isearch で表示される "現在位置" が _ble_edit_history 内の番号になっているが、 72856 これも履歴番号と一致させた方が分かりやすい。 72857 72858 1. PS1 \! で表示されるものを現在の履歴番号に置き換える。 72859 2. isearch で表示される "現在位置" を履歴番号 (配列添字+1) にする。 72860 72861 2016-07-07 72862 72863 * 2016-06-20 isearch: 検索速度の向上 (Bash 配列の workaround) [#D0332] 72864 72865 進捗状況を表示する様に変更した。 72866 72867 しかし検索位置によって速度が著しく異なる。 72868 もしかしてこれは "Bash のループの中で二つ以上の巨大配列を触ると遅くなる" という奴だろうか。 72869 と思って触る配列を一つに絞ってみたが違いはない様だ。 72870 次に検索方向を変えて試してみた…ら、凄まじく検索速度が異なる。 72871 また触る配列を二つに増やしたら順方向の検索でも遅くなった。 72872 72873 1. 触る配列を一つに絞る 72874 2. ループの方向を順方向に変える 72875 72876 これらの二つを満たした時の検索速度は格段に速い。 72877 72878 まず実は検索は逆方向に検索する事の方が多い。 72879 従って 2. は実に都合が悪い。素直な実装方法は存在しないので、 72880 様々な対策の可能性を考えて最良の物を選択する必要がある。 72881 しかし、1. に関しては比較的簡単に解決できるのではないかという気がするので 72882 先にこちらにかたを付けてから考える方が良さそうに思われる。 72883 72884 ★という訳で、触る配列を一つに絞る方法について考える。 72885 72886 | a 一つの方法は、現在 _ble_edit_history_edit と _ble_edit_history に分けている配列を 72887 | 一つの配列にくっつけてしまう方法である。 72888 | 72889 | つまり、現在は _ble_edit_history_edit を sparse な配列として保持し、 72890 | そこに登録が為されていなかったら _ble_edit_history を参照するという仕組みにしている。 72891 | 案としては、代わりに _ble_edit_history_edit に完全な情報を保持するというものである。 72892 | 勿論、_ble_edit_history は別の場所で必要になるから、 72893 | これはこれで独立に完全な情報を持つ物として記録しておく必要がある。 72894 | そして、_ble_edit_history の更新に際しては同時に同様に _ble_edit_history_edit にも変更を加える様にする。 72895 | 実はこの案は最近別の理由で考えた。その時にどの様な理由で現状の実装で良いとしたのかを思い出す必要がある。 72896 | 72897 | →2016-05-21 のログである。ble-edit/history/add で編集仕掛の状態をクリアする必要があるが、 72898 | その際に配列を丸ごとコピーする事にしている。 72899 | このコピーに時間が掛かってコマンド実行が遅くなってしまうので廃案になった。 72900 | しかしこの問題は (aa) 編集仕掛の状態を完全にクリアする事を諦める (bash と同じ動作) 72901 | または (ab) 編集仕掛の状態になっている項目の履歴番号を全て覚えて置いて、 72902 | それについてだけ更新を実行する。という方法の何れかを取って解決する事ができる筈である。 72903 | 72904 | b もう一つの方法は _ble_edit_history (密) の内容に関しては for ent in "${arr[@]}" で取得してしまい、 72905 | _ble_edit_history_edit (疎) の内容について配列添字アクセスで回すという方法である。 72906 | 72907 | 然し疎な配列のアクセス速度がどれくらいの物か実測してみないと分からない。 72908 | 72909 | sparse_array_read.dense 72910 | time 242972.10 usec/eval 72911 | sparse_array_read.1 72912 | time 234972.10 usec/eval 72913 | 72914 | 実測してみたが密な配列の場合と殆ど変わらない。寧ろ多少速い位である。 72915 | では逆順に添字を動かしても大丈夫か。 72916 | 72917 | sparse_array_read.1r 72918 | time 246972.20 usec/eval 72919 | 72920 | 疎な場合には (殆ど) 変わらない速度で回す事ができる様だ。 72921 | とここで気付いてしまったが、for arr in "${arr[@]}" だと逆順に回す事が不可能である。 72922 | # 所で zsh にはこの様な操作がいかにも実装されていそうである。 72923 | # 調べてみたら ${(Oa)array} (zsh-4.1.1) というのがあるそうだ。 72924 72925 これは a の方針にするのが良さそうである。 72926 但し、編集しかけの状態になっている履歴番号を全て記録する様な仕組みにする。 72927 まずは、その様な実装方法によって _ble_edit_history 及び _ble_edit_history_edit 72928 の両方を完全な配列として maintain する様に変更を行う。 72929 72930 _ble_edit_history_dirt に編集状態の項目の index を記録することにした。 72931 また isearch は完全に _ble_edit_history_edit だけを用いて動作する様にした。 72932 _ble_edit_history は使用しない。初回の動作は良好である。 72933 これにより順方向の検索は格段に向上した。 72934 72935 ★逆方向の検索をできるだけ順方向の検索で処理できる様にする方法について考える。 72936 72937 | a つまり高速な検索を実現する為には、履歴項目を逆順に格納した方が早いのではないか。 72938 | と思ったが、逆方向に格納するとすると、履歴項目を追加する時に shift をしなければならず遅い。 72939 | とすれば検索を開始する直前に反転した内容の配列を一気に生成すれば良さそうだ、 72940 | と思う物のこれも良く考えてみれば外部コマンドを呼び出すなどして工夫しなければ難しい。 72941 | 内部コマンドで reverse を実現する高速な方法は存在するのだろうか。 72942 | 72943 | reverse について時間の測定を試みた (benchmark-array.sh) 72944 | 外部コマンドを使用する方法だと高速な方法でも 10万要素あたり 500ms であった。 72945 | また内部で処理を実行する場合には 10万要素辺り 2150ms であった。それ程の違いはない。 72946 | 寧ろ Cygwin で外部コマンド起動が遅くなる事を考えれば内部で処理した方が良さそうだ。 72947 | しかし、いずれにしても反転だけで 2150ms かかるというのは遅い。 72948 | 72949 | b 別の方法として実際に行う検索は逆順だとしても、 72950 | 内部では順方向に計算を行ってしまうという手も考えられる。 72951 | 履歴項目の数が少ない内は愚直に逆順に探索した方が早いとしても、 72952 | 履歴項目が増えてくると順方向に探索を行って最後に一致した物を 72953 | 取り出す方が早くなるという反転が起こるはずである。 72954 | 72955 | 例えば仮に順方向の探索速度が a [s/entry] とし、 72956 | また、逆方向の探索速度が位置 x について bx [s/entry] だとする。 72957 | 現在検索しようとしている文字列の頻度が c = 1/m [個/entry] だとする。 72958 | 現在位置 x から逆方向に探索したいとする。 72959 | 愚直に文字通り逆方向に探索を実行するとし x - m の位置で見付かるとすると、 72960 | 探索に掛かる時間は (bx + b(x-m))m/2 = bm (x+m/2) になる。 72961 | 順方向に計算して最後に当たった物を採用するとすれば、 72962 | 探索に掛かる時間は単に ax になる。 72963 | 72964 | さて実際には探索を開始するまでは m が幾つになるか分からない。 72965 | 普通は最近実行したコマンドを呼び出す場合が多いはずだから m の期待値は小さいはずである。 72966 | しかし、検索が進んで行くに連れて m が大きいという事が段々分かってくる。 72967 | 今 n 回外れた時の m を見積もる式 m = f(n) が与えられているとする。 72968 | 検索を逆順で y から始めて n 回外れて x = y - n まで来た時に、 72969 | 残りの検索を順方向で行うか逆順で行うかを予測処理時間で決定する。 72970 | 72971 | ax < bm (x+m/2) 72972 | 72973 | になっていれば其処で逆順検索はやめて順方向検索に切り替える。 72974 | 72975 | | m (> 0) について解くと 72976 | | 72977 | | -x + sqrt(x^2 + 2ax/b) < m = f(y-x) 72978 | | 72979 | | ここで逆探索が外れる程に右辺は増加し左辺は減少する。 72980 | | つまり、どこかで両者が反転する場所が存在する。 72981 | | そこで検索方向の切替を行えば良いのだ。 72982 | | 72983 | | では、n 回連続で外れだった時に m はどの様に見積もる事ができるか。 72984 | | m もしくは c = 1/m についての事前確率を指定する必要がある気がする。 72985 | | 取り敢えず考えると、二項分布で n 回連続で外れる確率は (1-c)^n である。 72986 | | - これを最尤とする c は何かというと明らかに c = 0 であり、m = ∞ である。 72987 | | やはり事前確率が必要になる気がする。 72988 | | しかし実際の所検索文字列がどの様な分布を持っているかとか、 72989 | | 更に過去に同じコマンドを実行した事があるかどうかとか、その分布とか、 72990 | | 検索文字列についてのタイプミスだとか色々考えるとその様な事前確率を 72991 | | 設定するのは困難に思われる。だとすれば、もっと別の方法に頼るしかない。 72992 | | - 例えば (1-c)^n = 1/2 に為る様な c を求めたらどうだろう。 72993 | | 解は c = 1 - (1/2)^{1/n} となる。 72994 | | ここから 不等式を満たす n を事前に計算するのは大変そうである。 72995 | | - 或いはもっと単純に n 回失敗した時 m = n とするのはどうだろう。 72996 | | これならもっと楽に計算できるのではないだろうか。 72997 | | 逆に言えばこの時点で求めるのが難しければ 72998 | | より複雑な場合は考えるのはやめた方が良い。 72999 | | 一番初めの不等式に戻って x = y-n, m = n を代入すれば、 73000 | | 73001 | | a(y-n) < bn (y - n + n/2) 73002 | | 73003 | | これを満たす n (0<n<y) の条件は、 73004 | | 73005 | | a/b+y - sqrt((a/b+y)^2 - 2ay/b) < n 73006 | | 2(a/b)y / [a/b+y + hypot(a/b, y)] < n (分子の有理化) 73007 | | 73008 | | さて、a/b は一体どれぐらいの値になるだろうか。 73009 | | 実測してみる事にする。実際にはループに掛かる定数時間 d も合わせて、 73010 | | それぞれ (a + d)N, bN^2/2+dN という時間が掛かるはずである。 73011 | | 73012 | | N=10k 順 time 223972.40 usec/eval = (a+d)M 73013 | | N=10k 逆 time 476972.40 usec/eval = bMM/2 + dM, where M=10k 73014 | | N=20k 順 time 441972.40 usec/eval = 2(a+d)M 73015 | | N=20k 逆 time 1555972.40 usec/eval = 2(bMM + dM) 73016 | | (a + d)M = 222479.3 73017 | | bMM = 602027.6, bM = 60.20276, 73018 | | dM = 175958.6, 73019 | | aM = 46520.7, 73020 | | a/b = 773. 73021 | | 73022 | | 今、r = a/by (a/b が y の内どれだけの割合をしめるか) を用いて n/y を表現すると、 73023 | | 73024 | | n/y > r + 1 - hypot(r, 1) 73025 | | n/y > 2r / [(r+1) + hypot(r, 1)] 73026 | | 73027 | | 特に y >> a/b の場合を考えれば、r << 1 であり、 73028 | | 73029 | | n/y >~ r, n >~ a/b 73030 | | 73031 | | となる。sqrt 等の計算を bash で実行する (taylor 展開 or newton 法) のは面倒なので、 73032 | | これぐらいにしておくのがよい様な気もする。 73033 | 73034 | [まとめ] 73035 | 73036 | 履歴位置 y から逆方向に検索を開始するとき、 73037 | 検索時間期待値が短くなるように途中で順方向の検索に切り替える。 73038 | n 回連続で見付からなかった場合 m = f(n) = n として期待値を評価する事にする。 73039 | この時 r = a/by として、 73040 | 73041 | n/y >= r + 1 - sqrt(r^2 + 1) 73042 | 73043 | になった時に順方向の検索に切り替えれば良い。特に y >> a/b のときは、 73044 | 73045 | n >= a/b 73046 | 73047 | で評価しても良い。実際に a/b を実測してみると a/b ~ 773 になる。 73048 | 73049 | 73050 | しかしながらこの方法の欠点は何かというと実装が汚いという事である。 73051 | 途中で順方向に検索順序を切り替えるとすると、中断時に記録しなければならない項目の数が格段に増える。 73052 | 1. まず、現在の内部検索方向 73053 | 2. それから一番最後に一致した位置 73054 | 3. 検索の開始点(これは m の見積もりに必要) 73055 | 或いは順方向の検索は十分速いと考えるならば中断しないという手も考えられる。 73056 | 73057 | 更に現在の実装では _ble_edit_history_edit と _ble_edit_history の両方を参照しなければならないので、 73058 | 順方向の検索だったとしても結局検索に時間が掛かる事に違いはない。 73059 | というか先に _ble_edit_history_edit と _ble_edit_history の 73060 | 両方を参照しなければならない現状について解決するべきの様な気がしてきた。 73061 | →先に触る配列を一つにする課題を解決することにした。 73062 | 73063 | c 中位の大きさの buffer 配列にコピーして順次検索を実行する。 73064 | 73065 | 例えば 1000 位ずつ buffer 配列にコピーを行って、 73066 | その配列から読み出しながら検索を行う。 73067 | 73068 | d あるいは部分的順方向検索にするという手もある。 73069 | 73070 | 部分的順方向検索の大きさは 2 の累乗で増加する様に設定し、 73071 | 但し、中断位置チェックの場所を跨がない様にその都度大きさを弄る。 73072 | うーん。この方法が現実的の様に思われる。 73073 | 73074 | この方法と較べると b の様な複雑な計算はまるで無駄なことである。 73075 73076 d の方向で実装する事にする。 73077 73078 実装した。良好である。以前と比べると検索速度が格段に異なる。 73079 73080 * syntax-highlight: 変数の右辺の中で * や ?, @(...) などが着色されている。 [#D0331] 73081 しかし実際には変数の右辺では glob は無効になっている筈である。 73082 73083 また bash の動作を観察すると glob pattern としての意味は失う (glob 展開はされない) が、 73084 文法的には extglob を認識している様子である。つまり hoge=@(1|2) などとできる。 73085 73086 * 2016-06-23 ジョブ状態の変更 (suspended だとか "[1]+ 終了" とか) が出力されない様だ [#D0330] 73087 73088 [状況確認] 73089 73090 % これは標準出力だか標準エラーだかに出力されている筈。 73091 % これがそのまま捨てられているということだろう。 73092 % 73093 % 調べてみたが不思議なことに何処にも何も出力されていない様に見える。 73094 % 標準エラーで処理されなかった行を出力するようにして出力されたファイルの中身を見たが何もない。 73095 % また、標準出力の出力先のファイルを見ても何も書かれていない。 73096 % (中身のクリアは行っていないはずだし、少なくともタイムスタンプが変更されていない。) 73097 % 73098 % bleopt_suppress_bash_output を off にして試してみることにする。 73099 % なんと bleopt_suppress_bash_output にしていても何も出力されない様だ。 73100 % bind -x した関数の中から実行されたジョブは終了が捕捉されないという事なのだろうか。 73101 % と思って確かめてみたがそんなことはない様だ。 73102 % 73103 % $ bind -x $'"\eM": sleep 5 &' 73104 % 73105 % では eval にしているから駄目なのだろうか。 73106 % 73107 % $ bind -x $'"\eM": eval "sleep 1 &"' 73108 % 73109 % と思ったがそういうこともない様だ。 73110 % suppress output でも出力されなかった事から、fd の繋ぎ替えだとかは関係ないはずだ。 73111 % では stty などの設定によるものなのだろうか。と思って以下を試してみたがそれでもちゃんと出力される。 73112 % 73113 % $ bind -x $'"\eM": stty/enter; eval "sleep 1 &"; stty/leave' 73114 % $ function stty/enter { stty -echo -nl -icrnl -icanon kill undef lnext undef werase undef erase undef intr undef quit undef susp undef; } 73115 % $ function stty/leave { command stty echo -nl kill '^U' lnext '^V' werase '^W' erase '^?' intr '^C' quit '^\' susp '^Z'; } 73116 % 73117 % 何が原因でジョブ管理の出力が消えているのだろうか。jobs コマンドの呼び出しが関係しているのだろうか。 73118 % うーん。jobs をやってみて一つ分かった事がある。ジョブが終了して初回の 73119 % jobs の際に "[1]+ 終了" という内容が出力されている様だ。 73120 % そしてプロンプトに \j を入れていると内部で初回の jobs が実行されることになり、 73121 % ユーザの目には何も見えないという具合に為る様だ。 73122 % 73123 % もしかして default で終了時にメッセージが表示されるのも、 73124 % 実はプロンプトに \j が入っているからなのだろうか。 73125 % と思って PS1='\$ ' にしてみたが、それでもちゃんとジョブ終了直後にメッセージが表示される。 73126 % 今迄やったのと同様に stty を弄って eval するようにしたがそれでも変わらない。 73127 % 73128 % ble を読み込んでいる時とそうでない時の違いが謎である。。 73129 % 73130 % 更に ble-detach をしてみたらちゃんと出力される様になった。 73131 % つまり、何かが違うとすれば、ble-detach の中で行っている設定に依存している可能性がある。 73132 73133 % →何と分かってしまった。通常の状態に於いてジョブ状態の変化が出力されるのは、 73134 % ユーザがコマンドを実行した直後である。しかし、ble を attach している時は、 73135 % ble の eval によってコマンドを実行しているのであって、 73136 % シェルの機能でコマンドを実行している訳ではない。 73137 % それが理由でジョブの状態変化が出力されないのである。 73138 % 73139 % 一方で、画面に出力される前に明示的に jobs を呼び出した時には、 73140 % 状態変化がその jobs で表示されて以降では表示されなくなる様だ。 73141 73142 →と思ったが色々実行してみるとそういう訳でもないらしい。 73143 コマンドを空にしたまま RET を沢山押してもジョブの状態変化に 73144 対応するメッセージは何も表示されないが、 73145 一方で、何らかのコマンド (何でも良い。echo など) を実行すると 73146 その場でジョブ状態の変更についてメッセージが出力される様だ。 73147 73148 また PS1 に \j が含まれている場合は、内部的に jobs が実行されて、 73149 その時にジョブ状態変更についての結果が出力されると、 73150 画面には表示されないという事になってしまう。 73151 73152 ※何故コマンドを実行した時にはちゃんとジョブ状態の変更について出力されるのか調べる必要がある。 73153 調べると ble-edit/exec:gexec/.eval-prologue の中の、 73154 ble-stty/leave の中でジョブ状態の変更が出力されている。 73155 中で呼び出しているのは実質 command stty だけである。 73156 だとすれば、bash は "stty で状態が変更された瞬間にジョブ状態の変更を確認し出力を行う" という事になる。 73157 73158 という訳で、コマンドを実行した直後にジョブ状態の変更があれば自動的に出力されることが分かった。 73159 明示的に対処が必要なのは、実のところ、内部的に明示的に jobs を呼び出した時だけの様に思われる。 73160 73161 73162 [方針] 73163 73164 % これを解決する方法の方向性として二通り考えられる。 73165 % 73166 % a 一つはコマンドを ble.sh で実行する度に jobs を実行して状態変化のあったコマンドを調べる。 73167 % 特に "終了" したコマンドを検知するのに使用する。ただし、終了したかどうかを判定するためには、 73168 % ロケールが設定されていると厄介である。従って LC_ALL=C jobs の様にしなければならないと思われる。 73169 % 73170 % しかしそうするとロケールに従った状態の表示ができない。が、これは仕方がない。 73171 % 73172 % この方法を取った時にもう一つしなければならないのは、 73173 % プロンプトの計算や syntax-highlight の際に jobs を実行した時にも、 73174 % 状態の変更を追跡しなければならないということである。 73175 % これは直接 jobs を呼ぶ様にするのではなく、 73176 % jobs を呼び出すと同時にその内容を確認するような ble-edit/jobs 的関数を用意すれば良い。 73177 % 色々の用途に使う際にはこの関数を通して呼び出すことにする。 73178 % 73179 % b もう一つの方法は、コマンドが実行可能な状態にある時には bind を弄って、 73180 % コマンド実行を引き起こす様なキーでシェルとしてのコマンド実行が為される様に構成する。 73181 % しかしこの方法は基本的に無理である。 73182 % というのも唯単にコマンド実行が起こる様に構成するのだとすると、 73183 % シェルの標準出力・標準エラー出力などを本来のものに戻さなければ為らず 73184 % (そうしないとコマンドを実行した結果が画面に出力されずに失われてしまう)、 73185 % その様にするとカラーに着色した表示を無理にするためにちらつくことになる。 73186 % 73187 % 他にもコマンドが実際に実行されたかどうかの判定等々色々面倒である。 73188 % この方法は駄目である。まるで枠組を一から再考しなければならなくなる。 73189 % 73190 % 73191 % 上記の a の方向で考えることにする。基本的にコマンド実行が終了した時にチェックを行う。 73192 % これはプロンプトの計算を行って、プロンプトを出力する直前に結果を出すということにする。 73193 % 或いは、明示的にコマンド実行が終了した時にチェックを行うというのではなくて、 73194 % 単にプロンプトの描画の部分で jobs を確認して出力を行うという様にすれば良い。 73195 % 特にプロンプトの再描画 (前回と同じ内容) などではなくて、プロンプトの再計算を行ったタイミングで出力することにしたい。 73196 % 73197 % その他の処理で jobs を呼び出してその際にジョブ状態の変更を検知した場合には、 73198 % 検知したということを何処かの配列にでも覚えて置いて、 73199 % その次にプロンプトを再計算・再描画しようという時に改めて出力する様にすればよい。 73200 73201 状況に誤認が多少あった。基本的に上記 a の方針で行くが、 73202 コマンドの実行が合った場合 (stty で設定が変更された場合) は、 73203 bash が自動的にジョブ状態の変更について確認を行い出力を行う事が分かったから、 73204 実際に対処が必要になるのは内部で明示的に jobs を呼び出した時のみである。 73205 特に PS1 に \j が含まれている時の動作である。 73206 73207 73208 前準備として (既定の) jobs が一体どのような出力をするのかについて詳しく調べておく必要がある。 73209 73210 - ジョブのコマンドに改行が含まれている場合は jobs の結果はどうなるのか。 73211 →複数の行にまたがって出力される。 73212 73213 現在のジョブ数のカウントではどの様にしているか。 73214 →ちゃんと対策できていない。余分に表示されてしまう様だ。これは対策が必要だ。 73215 73216 - "終了" "Done" などの文字列を検出する方針について 73217 73218 % LC_ALL=C jobs にすると "実行中" の代わりに Running と表示される。 73219 % しかし "終了" は "終了" のままである。LC_ALL=C; jobs などとしても駄目だ。 73220 % しかし、LC_ALL=C としてから jobs とするとちゃんと Done と表示される。 73221 % どの様な動作基準になっているのだろうか。 73222 % LC_ALL=C jobs → だめ 73223 % LC_ALL=C; jobs → だめ 73224 % (LC_ALL=C; jobs) → だめ 73225 % LC_ALL=C eval jobs → だめ 73226 % どうも LC_ALL は設定してから反映される迄に時間が掛かるということの気がする。 73227 % 代わりに LANG を使って同様にしてみたが動作は変わらない。 73228 % だとすれば、bash-3.0 で C-d を捕捉する為に ignoreeof-message.txt でやっている様に、 73229 % Done に対応する文字列の一覧表を作る必要がある。 73230 % 73231 % 過去の記録に基づくと ignoreeof-message.txt は generate.sh で生成している。 73232 % 73233 % また修了の仕方によって様々なメッセージが考えられる。 73234 % 単に kill すると Terminated と表示される。 73235 % 他にも色々の修了の仕方に応じてメッセージが異なるのかもしれない。 73236 % 73237 % 或いは単純に jobs を二回実行して状態が変化したジョブについてのみ 73238 % 出力を行うという風にしても良いのではないだろうか。 73239 % というかもし jobs に状態変化があるのだとすれば、 73240 % 結局二回 jobs を実行する必要がある様な気がする。 73241 % こちらの方法のほうが合理的な気がする。 73242 % 73243 % 知りたいのは特にジョブが "終了" したとか "強制停止" されたとかではなく、 73244 % 単にジョブの実行状態の変化が知りたいというわけである。 73245 % だとすれば jobs によって出力される結果の変化と等価なものを提供したい。 73246 % これを調べるためには単に jobs の状態変化を追えば良いという訳である。 73247 73248 固定文字列を使用する方法だと不安定に思われるので、 73249 jobs を二回実行して比較する方針で実装する事にした。 73250 また、ジョブの状態変化に対応するために前回の jobs の呼び出しについても記録を行っておく。 73251 73252 - jobs %1 などの様に指定を行ったとしても状態変化したジョブの情報は出力されるのか? 73253 73254 →なんと番号を指定していたとしても状態変化したジョブの情報が一緒に出力されてしまう様である。 73255 →もしかすると標準エラー出力などに出力されている可能性? 73256 確認してみたが普通に標準出力に混ざって出力されている様だ。 73257 73258 bash の既定の動作は不思議な動作なのでこれについては模倣する必要はないように思われる。 73259 73260 [実装] 73261 73262 1 取り敢えず jobs の出力を解析する関数を作成する必要があるだろう。 73263 73264 実装してみた → ble/util/joblist 73265 73266 同時に jobs に状態変化したジョブの内容が 73267 報告されている可能性があるのでそれを毎回調べる必要がある。 73268 毎回調べる必要があるのだから、毎回二回解析を実行して差分を調べる様にしてしまっても問題ないだろう。 73269 終了したジョブなどに関して言えば一回目の jobs で出力されていて、 73270 二回目の jobs で出力されていなければそうであると判断できる。 73271 73272 しかし、実行状態から停止状態に移ったジョブや、 73273 その逆のジョブに関してはこの方法では検知できないのではないかという気がする。 73274 ここで確認して置かなければならないのは通常の bash の時に、 73275 その様な状態変化が標準出力に報告されるのかそうでないのかという事である。 73276 調べてみたところ、実行状態から停止状態に移った時には報告が為されるが、 73277 停止状態から実行状態に映った時には何も報告が為されない。 73278 73279 さて速度は気になる。 73280 73281 $ ble-measure ble/util/joblist 73282 time 2410.60 usec/eval 73283 $ ble-measure 'ble/util/assign jobs jobs; GLOBIGNORE=\* IFS=$'\''\n'\'' builtin eval "jobs=(\$jobs)"' 73284 time 357.60 usec/eval 73285 $ ble-measure 'ble/util/assign jobs jobs' 73286 time 305.60 usec/eval 73287 $ ble-measure jobs 73288 time 11.10 usec/eval 73289 73290 単なる jobs の実行とは比ぶべくもない (220倍)。 73291 しかし比較対象はその出力を変数に格納するときの場合である。 73292 単なる ble/util/assign jobs jobs と比較すると 8 倍程遅い。 73293 行分割も考えれば 7 倍程度の遅さである。 73294 うーん。まあ 2ms 程度であれば許容範囲内ではあるが、 73295 7倍というのは余りに大きい。まだ高速化の余地はある様な気がする。 73296 もし使ってみて遅い様に感じたらその時にまた高速化を考える方向で良いとする。 73297 73298 ジョブを 10 個にして試してみた。 73299 $ ble-measure ble/util/joblist 73300 time 13170.60 usec/eval 73301 $ ble-measure 'ble/util/assign jobs jobs; GLOBIGNORE=\* IFS=$'\''\n'\'' builtin eval "jobs=(\$jobs)"' 73302 time 2020.60 usec/eval 73303 $ ble-measure 'ble/util/assign jobs jobs' 73304 time 729.60 usec/eval 73305 73306 % 13ms というのは結構遅い気がする。何とかならないものか。やはり正規表現による一致に時間がかかるのか。 73307 % そう思って以下のように正規表現を使わないように書き換えた。 73308 % 73309 % - [[ $line =~ $rex_ijob ]] && ijob="${BASH_REMATCH[1]}" 73310 % + local n=${line%%']'*}; [[ $line == '['[0-9]*']'* && ${n//[0-9]} == '[' ]] && ijob=${n:1} 73311 % 73312 % それで計測してみたところ、 73313 % 73314 % $ ble-measure ble/util/joblist 73315 % time 12570.60 usec/eval 73316 % 73317 % 微妙に早くなった。違いは有意である。しかし絶対量としては大して変わらない。 73318 % わざわざこの様な分かりにくい方法を選択する程の利点はない。 73319 73320 % 或いは直に正規表現を記述しておけば precompile されるだろうか。 73321 % 73322 % [[ $line =~ ^\[([0-9]+)\] ]] && ijob="${BASH_REMATCH[1]}" 73323 % 73324 % $ ble-measure ble/util/joblist 73325 % time 13170.60 usec/eval 73326 % 73327 % まったく変化しない。駄目だ。 73328 73329 遅さの原因は for ループにある様に思われる。 73330 for ループ無しにジョブの分割などを実装する方法はあるだろうか。 73331 つまり /\n\[[0-9]+\]/ の箇所で分割を実行する。 73332 その時に [0-9]+ の番号の部分を保持したい。 73333 或いは、/\n/ で分割した後に /\[[0-9]+\]/ 以外で始まる行を潰す。 73334 73335 →遅いので 1回目の jobs の時点で前回からの変化がない場合には以降の処理を省略することにする。 73336 73337 73338 遅い第一の原因が分かった。[[ $a == $b ]] の比較において二つ目の引数を quote していなかった。 73339 bash が二つ目の引数の中身を glob pattern として parse している事が原因だったようだ。 73340 これを修正したら、ジョブが 10 件ある状態でも以下の様な速度に落ち着いた。3.5倍程度である。 73341 73342 $ ble-measure ble/util/joblist 73343 time 7220.40 usec/eval 73344 73345 更に一回目の jobs の結果が前回の結果と全く同一の場合にはそもそも処理を完全にスキップできる。 73346 結果として以下の様になった。今まで (jobs) と殆ど変わらない速度である。 73347 というより今迄 (毎回 jobs + 改行で分割) より高速になっている。OK 73348 73349 $ ble-measure ble/util/joblist 73350 time 383.90 usec/eval 73351 73352 取り敢えず ble/util/joblist 完成という事でここで commit しておく事にする。 73353 73354 2 ble/util/joblist で状態変化をチェックする様にしたが、 73355 先頭の "-+" の有無の変化も検知してしまっている。これらを無視した比較が必要である。 73356 →対策した。 73357 73358 色々試した結果、あるジョブが終了した後に別のジョブが同じ番号に入った時、 73359 (同じジョブの状態が変化したというように) 誤検知してしまう。 73360 その様な誤検知が起こるのはコマンド実行の stty 時にジョブの変化が bash によって出力され、 73361 その事が ble/util/joblist のキャッシュに反映されないという場合である。 73362 73363 これを防ぐためには stty 実行時にキャッシュをクリアするか、 73364 stty 実行直前に明示的に ble/util/joblist.check を呼び出すかする必要がある。 73365 stty 実行時に確実にジョブの状態変化が bash によって出力されるというのであれば、 73366 ble/util/joblist.clear してしまって良いだろう。 73367 73368 3 検知した状態変化を何処かのタイミングで出力する必要がある。 73369 73370 これは新しくコマンドを実行する直前と、コマンドを実行した直後にしたい。 73371 73372 コマンドを実行する直前 (もしくはプロンプトの再計算を要求する箇所) を探してみる。 73373 先ず、コマンドを実行したりする為に newline を呼び出す。 73374 ここでは _ble_edit_LINENO を increment する。 73375 _ble_edit_LINENO が変化しているとプロンプトの再計算が実行され、 73376 次にプロンプトを表示する際に一から表示されることになる。 73377 さて、よく見ると _ble_edit_LINENO を更新する直前で、 73378 プロンプト・コマンドライン行の末端で改行を出力している。 73379 この直後で jobline.flush を実行すれば良いだろう。 73380 73381 一方でコマンドを実行した直後ではどうだろう。 73382 これについては、そもそもコマンドを実行している最中に内部関数 73383 ble/util/joblist を呼び出すことは想定していないので、 73384 そもそも何らのジョブ変更イベントも記録されない様に思われる。 73385 従って、わざわざ出力させる必要はないと考える。 73386 73387 →通常の bash はどの様な動作であったか。試してみる。 73388 どうやら "外部コマンド" が終了する度に確認を行っている様である。 73389 73390 一方で、複数のコマンドの間に挟まれてジョブ情報が出力されると見にくいので、 73391 ble ではコマンド実行の前とコマンド実行の後にまとめて出力するのが良さそうである。 73392 73393 現状では、コマンド実行を開始する直前の command stty でジョブ情報が出力される。 73394 (というか実は command stty でジョブ情報が出力されるのも、 73395 別に stty が呼び出されたからジョブ情報が出力される、というのではなくて、 73396 単に外部コマンドが呼び出されて終了したからジョブ情報を出力しているという動作に過ぎないのではないか。) 73397 従って、コマンド終了後にまとめてジョブ情報を出力する仕組みにしているとジョブ情報の順序が前後することになり分かりにくい。 73398 よって、コマンド実行をする前に joblist.flush はしておきたい。 73399 73400 一方で、長いコマンドを実行して終了した時に既にジョブ状態が変更されている場合、 73401 その出力を次のコマンドを入力して実行した時まで遅延するというのはまた分かりにくい。 73402 それならばいっその事コマンド実行が終了した時にも同様にチェックをしたい所である。 73403 コマンド実行が終了する箇所というのを探すのは簡単である。 73404 行末位置調整などを行っている場所で一緒に実行してしまえばよい。 73405 73406 4 動作確認 73407 73408 bug: events が二回ずつ登録されている。これはどういう事か。 73409 73410 →調べてみたら、実行中から終了に変化し、終了から空に変化し、 73411 という所で両方に引っ掛かってなっていた様である。 73412 どちらか片方だけで良い。 73413 73414 bug: それと joblist の表示が一足遅い気がする。何故か。 73415 73416 →これはプロンプトの再計算が on demand で行われている為で、 73417 joblist.check, joblist.flush をしてからプロンプトを計算して、 73418 その時にジョブ状態の変更が検出されるためではないだろうか。 73419 結果として次のコマンド実行まで検出されたジョブ状態変更が出力されない。 73420 73421 しかしそれは変だ。それならば何故初めの joblist.check で検出されないのだろうか。 73422 73423 →理由が分かった。そもそも joblist.check, joblist.flush をしていない。 73424 現在はコマンドを実行した後に joblist.check, joblist.flush をしているが、 73425 よく考えてみたら空コマンドで newline した時はそもそもコマンド実行に到らないので、 73426 joblist.check, joblist.flush には到らないのだ。 73427 従って、newline をした時でも joblist.check 及び joblist.flush 73428 を実行する様に変更しなければならない。それも明示的に。 73429 うーん。でも変だ。newline をした時に flush はしている筈なのに…。 73430 と、よく考えたら flush しているだけで check をしていなかった。 73431 73432 うーん。設計を眺めてみるに flush の直前には必ず check をする事になっている。 73433 考えてみればそれもそうだ。そうでなければならない。 73434 なので、flush の内部で check を呼び出してしまう事にする。 73435 73436 現在の所動作良好である。反応も遅くなっていない。 73437 73438 2016-07-04 73439 73440 * ble-detach して ble-attach すると、BS が効かない。 [#D0329] 73441 73442 bind -p | less で確認すると以下の項目について unbind できていない。 73443 "\C-u": self-insert 73444 "\C-v": self-insert 73445 "\C-w": self-insert 73446 "\C-?": self-insert 73447 73448 しかし不思議だ detach してみると上記のキーは self-insert 73449 ではない物に bind されている。だとすると、何処かで変な bind をしているのか? 73450 73451 うーん。変だ。この状態で 73452 73453 $ builtin bind -x '"\177":ble-decode-byte:bind 127; builtin eval "$_ble_decode_bind_hook"' 73454 73455 を手動で実行してみる。するとちゃんと BS が効く様になる。 73456 ということは ble-attach の方の問題なのだろうか。 73457 73458 ble-attach を少しずつ実行してみることにする。 73459 ble-decode-attach の source "$_ble_base_cache/ble-decode-bind.$_ble_bash.bind" を実行すれば直る。 73460 73461 うーn。何か、これ、前にも似た様なことをして対策した様な気がする…と思ったら、 73462 関数 ble-decode-bind/uvw である。ここでは変数 _ble_decode_bind__uvwflag を使って、 73463 未だ設定が行われていなければ bind をやり直すということをしている。 73464 そしてこの関数は ble-decode-byte:bind/PROLOGUE で呼び出されている。 73465 つまり、毎回ちゃんと呼び出されると考えて良いだろう。 73466 そうすると問題は _ble_decode_bind__uvwflag の値の設定ということになる。 73467 これを検索してみると、ble-decode-bind/uvw を定義した一箇所しか存在しない。 73468 つまり、最初の ble-attach でしか uvw に対する特別な bind が動作しないということである。 73469 これでは駄目だ。という訳で ble-attach の際に _ble_decode_bind__uvwflag= を設定すれば良い。 73470 →これで解決した。 73471 73472 2016-06-27 73473 73474 * $_ble_base/cache ユーザの分離ができていない。 [#D0328] 73475 73476 これも $_ble_base/tmp と同様に chmod a+rwxt 73477 してその下に $UID でデータを置く様にする必要がある。 73478 あと UID 変数は信用できるのだろうか→man bash によれば読み取り専用である。OK. 73479 73480 既に cache というディレクトリを作ってしまっているので、 73481 g pull 等で更新した時には問題になる。 73482 cache.d という名前のディレクトリに変更して処理するべきである。 73483 また、その際に既に存在しているファイル達を移動する仕組みも提供するか。 73484 73485 * [2016-06-22] sleep の実装方法 → ble/util/sleep として実装した [#D0327] 73486 73487 $ mkfifo tmp/sleep 73488 $ exec 3<> tmp/sleep 73489 $ function sleep { local v; ! read -t 0.1 v <&3; } 73490 73491 自分で作った fifo なら自分で書き込まない限りはブロックされる事が保証できる。 73492 73493 # これで cygwin でも高精度な sleep ができる! と思ったらそんな事は無い。 73494 # "bash: read: 読み込みエラー: 0: Communication error on send" 73495 # というエラーを出力して終わってしまう。 73496 # 73497 # うーん。仕方がない。cygwin では /dev/tcp/0.0.0.0/80 に頼るか…。 73498 # (少なくとも cygwin では bash /dev/tcp が有効でビルドされている事は知っている。) 73499 # しかし、/dev/tcp/0.0.0.0/80 が完全に永劫にブロックする物なのかは謎である。 73500 # これについては長時間放置したテストが必要になる。 73501 # →と思ったら高々 20 秒で接続を諦めて止まる様子だ。 73502 # しかし接続を諦めたとしてももう一回実行すればまたブロックされる。 73503 # さて、この方法の問題点は何かというと普通に外に向かって通信を開始してしまう事である。 73504 # 73505 # うーん。また mkfifo に戻ってくる。cygwin はやはり駄目なのか。 73506 # http://cygwin.1069669.n5.nabble.com/Bug-Named-Pipes-FIFO-Bash-td10925.html 73507 # と思ったらどうも cygwin では真面目に mkfifo の blocking な振る舞いを実装する気はなさそうだ。 73508 # 色々な人が文句を言っていると言う事は work around はないという事ではないか。 73509 # 73510 # あるいは cygwin ではこうする? 73511 # 73512 # exec 3< <( while :; do sleep 1d; done &> /dev/null ) 73513 # 73514 # できた! と思ったが…そもそも 73515 # 73516 # time read -t 0.1 <&3 73517 # 73518 # がきっかり 0.1 にならずに 0.109 か 0.125 になる…。うーん。何故だ。 73519 # 因みに /dev/tcp/0.0.0.0/80 は 0.094 か 0.109 になる。こちらはそんなに変ではない。 73520 # もう一つの問題点は C-c をするとそれが while :; ... に伝達して終了してしまう事。 73521 # プロセス置換が延々と生きていて欲しいのだが…。 73522 # <(while do done &) としてみたがすると今度は <&3 で読み取ろうとしても何も読み取れない。 73523 # うーん、C-c だけならば trap -- '' INT とかすれば良い。 73524 # しかし今度は C-\ を押した時にやはり消えていなくなる。QUIT を追加した。 73525 # しかし、うーん、INT と QUIT だけ無視しておけば OK なのかどうかは不明である。 73526 73527 [cygwin の場合、まとめ] 73528 73529 cygwin の場合には mkfifo でブロックされない。 73530 /dev/tcp/ は外部に変なアクセスをするので timer には向かない。 73531 というか socket を作りまくって接続数の上限に抵触する可能性すらある。 73532 更に、時々固まるので時間計測にも支障を来す。 73533 73534 exec 3< <( trap -- '' INT QUIT; while :; do sleep 1d; done &> /dev/null ) 73535 73536 で頑張るしかない。しかしこれによる sleep は多少遅延がある。 73537 73538 →実際にやってみたら read -t 0.001 <&3 するだけで 12ms の時間を消費することが分かった。 73539 read -t 0.001 -u 3 でも時間は全く変わらない様だ。 73540 一方で read -t 0.001 </dev/tcp/0.0.0.0/80 は遅延が 1.5ms 程度と短い。 73541 どうも繋がっている先によって遅延時間が異なる様である。 73542 73543 もっと他の繋ぎ方も試してみる事にする。 73544 73545 $ mkfifo tmp1 73546 $ (exec 3> tmp1; sleep 65535) & 73547 $ exec 8< tmp1 73548 $ read -t 0.001 -u 8 73549 → やはり同じ時間掛かる。 73550 73551 うーん。/dev/tcp がごく短い時間しかかからないというのが不思議だ。 73552 実は通信を始める前に処理を中断しているのだという可能性もある。 73553 →うーん。実際に while :; do read -t 0.01 </dev/tcp/0.0.0.0/80; done を試してみたが、 73554 外部に対して通信を行っている気配はない。 73555 ということはネットワークに対する負荷はないのではないか。 73556 →今度は実在する IP アドレスに対して同じ事を行ってみた。 73557 外部に対して通信を大量にしまくっている様だ。これはいけない。 73558 ということはやはり 0.0.0.0 の場合には通信が内部で閉じているという事である。 73559 しかしこれは Windows だけの話かも知れないので他の OS では事情が異なるかもしれない。 73560 やはり mkfifo が期待通りに働かず pipe が遅い Windows ならではの措置である。 73561 73562 Cygwin 上で系統的に速度の計測を行ってみる 73563 73564 $ exec 9< <( 73565 > [[ $- == *i* ]] && trap -- '' INT QUIT 73566 > while :; do command sleep 65535; done 73567 > ) 73568 $ (exec 3> tmp1; sleep 65535) & exec 8< tmp1 73569 $ exec 7<> tmp1 73570 73571 | コマンド | 実行時間 (Cygwin) | 環境2 73572 |-----------------------------------------|--------------------|-------------------- 73573 | sleep 0.001 | 1819.10 usec/eval | 1214.50 usec/eval 73574 | read -t 0.001 < /dev/tcp/0.0.0.0/80 | 1967.50 usec/eval | 1410.60 usec/eval 73575 | read -t 0.001 < /dev/tcp/127.0.0.1/80 | 1967.50 usec/eval | 1410.60 usec/eval 73576 | read -t 0.001 < /dev/tcp/███.███.6.2/80 | 23337.50 usec/eval | 14070.60 usec/eval 73577 | read -t 0.001 < /dev/udp/0.0.0.0/80 | 3067.50 usec/eval | 1310.60 usec/eval 73578 | read -t 0.001 <&9 | 12437.50 usec/eval | 1210.60 usec/eval 73579 | read -t 0.001 -u 9 | 12437.50 usec/eval | 1220.60 usec/eval 73580 | read -t 0.001 -u 8 | 12437.50 usec/eval | 1210.60 usec/eval 73581 | read -t 0.001 -u 7 | ※1 | 1200.60 usec/eval 73582 73583 ※1 bash: read: read error: 6: Communication error on send 73584 73585 | コマンド | 環境1 Cygwin | 環境2 GNU/Linux | 73586 |-----------------------------------------|----------|---------| 73587 | `read -t 0.001 < /dev/tcp/0.0.0.0/80` | 2.0 ms | 1.41 ms | 73588 | `read -t 0.001 < /dev/tcp/127.0.0.1/80` | 2.0 ms | 1.41 ms | 73589 | `read -t 0.001 < /dev/tcp/██.██.6.2/80` | 23 ms | 14.1 ms | 73590 | `read -t 0.001 < /dev/udp/0.0.0.0/80` | 3.1 ms | 1.31 ms | 73591 | `read -t 0.001 <&9` | 12 ms | 1.21 ms | 73592 | `read -t 0.001 -u 9` | 12 ms | 1.22 ms | 73593 | `read -t 0.001 -u 8` | 12 ms | 1.21 ms | 73594 | `read -t 0.001 -u 7` | エラー | 1.20 ms | 73595 73596 2016-06-20 73597 73598 * isearch: 検索に時間が掛かっている時に進捗状況を表示する。 [#D0326] 73599 73600 isearch_suspend で進捗状況を表示しようと考えたが、どうも動かない。 73601 よく考えてみたら isearch_suspend は次の文字が標準入力に来ている時にだけしか起こらない。 73602 なので、次の文字が来ているかどうかに拘わらず更新をしなければならない。 73603 最初は一定の数以上処理を行ったら中断を行う様に変更しようかとも考えたが、 73604 次の文字が来ていないのに中断を実行してしまうと続きの検索が処理されなくなってしまう。 73605 従って、中断を行うのではなくてその場で更新を行う必要がある。 73606 73607 →実装した。検索の進捗状況が表示されている。 73608 73609 * isearch: history 検索に時間が掛かっている時に次の入力が来たら中断できないか? [#D0325] 73610 73611 % 単に中断するのだと問題がある。abc と入力したのに b 73612 % が入力されなかった事になってしまうという事があるからである。 73613 % 検索に時間が掛かっている状態で次の入力が来た時の振る舞いについて整理する必要がある。 73614 % 73615 % a back 等で検索状態を一つ戻すキーが来た場合には処理を中断する。 73616 % 直前の状態に戻りキーの入力を待つ。 73617 % 73618 % b RET やその他のキーで等で確定する場合には、 73619 % 一旦 RET を受領してから検索の続きを実行し、 73620 % 当たったら其処で確定を行う。 73621 % 73622 % 引き続きその他のキーについて処理を実行する必要がある時には 73623 % それを自分で呼び出す必要がある。 73624 % 73625 % c 続きの文字を入力した場合は、 73626 % やはり一旦キーを受領してから検索の続きを実行し、 73627 % それが終わったらまた次のキーを処理し、 73628 % という事をしなければならない。 73629 % 73630 % 単に検索文字列を更新するだけでは駄目なのは、検索の進行をスタックに記録しなければならないからである。 73631 % つまり、abc と入力したら a まで入力した時の一致位置、b まで入力した時の一致位置も記録しておかなければならない。 73632 % - そうしないと abc まで打ってから back をして ab に戻した時に適切な位置にまで戻ることができないからである。 73633 % 勿論、abc が一致しているのだから ab が同じ位置で一致していたということは明かだろうが、 73634 % 例えば ab までは一致して abc について一致する項目がない場合には、 73635 % ab に戻るためには ab の位置がやはり記録されていなければならない。 73636 % - 何より、a → ab → abc という様に検索を行っても、abc を一発で検索しても検索のコストが変わらない。 73637 % 従って、わざわざ検索文字列をすりかえて処理を一回の検索で済ませる様にする利点がない。 73638 % 73639 % 検索を再開する場合には前回の検索位置からの続きとして実行をしたい。 73640 % 初めから検索をやりなおすのではどんどん時間が掛かる様になってしまうからである。 73641 % その為には現在の検索位置の変数をグローバル変数にする、 73642 % または、検索位置の変数を対応するグローバル変数に保存するようにする必要がある。 73643 % 73644 % 結局、現在検索中かどうかと言う情報を保持する様にすればよいように思う。 73645 73646 結局考察の結果として少し違った実装になったので、上記の当初の案はそのままは採用されなかった。 73647 73648 73649 さて、検索中に次の文字が来た時にどの様に検索方法を修正するかなどについては 73650 いきなり考えると訳が分からなくなってしまうので、 73651 取り敢えずは検索を単に中断して再開する方向で実装を考えてみる。 73652 73653 取り敢えず ble/widget/isearch/next-history を中断可能に書き換える。 73654 と思ったけれどももっと全体を見てから書き換えた方がよい様な気もする。 73655 どの様に実装すれば良いか。取り敢えず現在の方法はすっかり止めて、 73656 [タスクを登録] → [タスクを実行] という形に変更しなければならない。 73657 そしてタスクを実行している途中で中断があればタスクを再開する 73658 というタスクを先頭に挿入する必要がある。 73659 もしくは先頭に挿入するというよりは完全に新しくタスク列を設定し直すという考え方でも良い。 73660 もし現在待ち状態になっているタスクがない場合には、その時に限って直接実行を行っても良い? 73661 73662 73663 中断を実行できる様に設計を変更した。以下の問題点・課題がある。 73664 73665 - isearch: is-stdin-ready で中断するとき、既に一致したコマンドラインの描画が為されない 73666 →別項目 2016-06-20 73667 - isearch: 検索中の accept は実行しない。 73668 →別項目 2016-06-20 73669 - isearch: 検索に時間が掛かっている時に進捗状況を表示する。 73670 →別項目 2016-06-20 73671 73672 * isearch: is-stdin-ready で中断するとき、既に一致したコマンドラインの描画が為されない [#D0324] 73673 73674 is-stdin-ready が true になっている限りコマンドラインの描画がされないので、 73675 全ての検索が終了するまで、途中の一致が表示されない。 73676 これは恐らく今迄の実装でもそうなっていたのではないかと思われる。 73677 73678 →これについては is-stdin-ready の時に描画をスキップする様になっている箇所で、 73679 何らかの変数を参照して描画を実行する必要がある場合はスキップしない様にすれば良い。 73680 描画を実行するかどうかを決定づけているのは、ble-decode-byte:bind/EPILOGUE である。 73681 73682 しかし、ここでは is-stdin-ready の際には描画をスキップするだけでなく、 73683 ユーザによって実行を要求されたコマンドの実行もスキップされる。 73684 今回の用途の場合にはコマンドの実行もスキップする必要はあるのだろうか。 73685 そもそも今回の場合 (isearch) には検索中にコマンドの実行が要求される事がない。 73686 なので、もっと異なる状況で考えなければならない。 73687 例えば、複雑なキー操作と思い処理によって順次実行するコマンドの内容を決定していく場合を考える。 73688 この様な場合に確定したコマンドを実行するタイミングはどうであるべきか。 73689 うーん。現在の処理だと中途半端な状態でコマンドを実行すると、 73690 編集行の下に表示されているパネルなどの上にコマンドの実行結果が上書きされたりして変な事になる。 73691 本来は、コマンドを実行する前にその様なパネルなどの表示を消去しておくべきなのである。 73692 現状の方向性としては、 73693 73694 a. 描画する時はコマンド実行をスキップしない。パネルなどの表示はコマンド実行時に消去する様にする。 73695 b. is-stdin-ready の場合には描画をスキップしないとしてもコマンド実行をスキップするか、 73696 73697 の二通りが考えられる。どちらもそれなりに理に適った実装の様に思われる。 73698 但し、コマンドをスキップするかスキップしないかに拘わらず、 73699 コマンドの実行時には一時的に表示しているパネルなどは消去するべきなのは確かである。 73700 現在の所は実装が楽な b. の様に処理をすることにして後で問題になったら a. にするのが良さそうである。 73701 パネルの一時消去に関しては新しく項目を作って保留とする。 73702 73703 → 変数名は _ble_edit_bind_force_draw とする。 73704 73705 73706 変数に描画が必要である事を設定する箇所の候補は二つ考えられる。 73707 73708 a. ble-edit/isearch/.goto-match 73709 b. ble-edit/history/goto 73710 73711 そもそも描画をスキップしない様にする必要が生じるのは、 73712 時間の掛かる処理を実行している途中に、入力に応答できる様に中断する時である。 73713 ということはスキップしない様に値を設定するのは、 73714 その様な中断を行う枠組の方であるべきである。 73715 ble-edit/history/goto はその様な時間の掛かる処理以外でも使われる。 73716 つまり、ble-edit/isearch/.goto-match の側で設定を行うべきである。 73717 73718 * isearch: 検索中は accept をしないように変更したい。 [#D0323] 73719 今迄の実装だと現在実行中の検索が終わってから accept をしていた。 73720 しかし、これだと思いがけず変なコマンドが検索に当たって実行されてしまうかも知れないので。 73721 また、現在表示されている (現在までに一致した) コマンドを実行するという仕組みにするのも危険である。 73722 というのも現在実行中の検索がある場合、ユーザが accept をしようとした瞬間に 73723 表示されているコマンドが切り替わる可能性があるからである。 73724 73725 しかし accept しないと言っても検索の中断はすぐさま行われる訳ではないので、 73726 多少の検索が実行されて新しく一致した後にそのコマンドが実行される可能性もある。 73727 しかし、"基本的に accept しない" 設計にしておけば、 73728 ユーザからすれば検索中に accept することの意味が殆ど失われるので、 73729 ユーザがその様な操作を実行する可能性が少なくなる。 73730 従ってその心配はしなくても良いのではないか。 73731 73732 2016-05-21 73733 73734 * 出た 2016-04-23 [#D0322] 73735 73736 [状況] 73737 73738 | stackdump: 0 <= beg=23 <= end=24 <= len=1; beg=23, end=23, ins(1)=c 73739 | @ /home/murase/prog/ble/ble.sh:5079 (_ble_edit_str.replace) 73740 | @ /home/murase/prog/ble/ble.sh:-1789 (ble/widget/self-insert) 73741 | @ /home/murase/prog/ble/ble.sh:33 (ble-decode-key/.invoke-command) 73742 | @ /home/murase/prog/ble/ble.sh:22 (ble-decode-key/.invoke-partial-match) 73743 | @ /home/murase/prog/ble/ble.sh:37 (ble-decode-key) 73744 | @ /home/murase/prog/ble/ble.sh:92 (ble-decode-char/.send-modified-key) 73745 | @ /home/murase/prog/ble/ble.sh:50 (ble-decode-char) 73746 | @ /home/murase/prog/ble/ble.sh:-966 (ble-decode-byte+UTF-8) 73747 | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 73748 | 73749 | 改めて探してみるが不整合が出る様な場所は存在しない。 73750 | _ble_edit_str に値を設定している場所は _ble_edit_str.replace, _ble_edit_str.reset だけである。 73751 | _ble_edit_str.reset-and-check-dirty は現在の設定では使用していない筈である。 73752 | _ble_edit_dirty_syntax_{beg,end} に関しても値を設定している箇所は 73753 | _ble_edit_str/update-dirty-range だけだし、 73754 | _ble_edit_str/update-dirty-range を呼び出している箇所は、 73755 | 上記の _ble_edit_str.{replace,reset} だけである。 73756 | 73757 | と思ったが…良く考えたら挿入位置が範囲外になっているという事だろうか。 73758 | self-insert で起こっているという事は、 73759 | _ble_edit_ind の値が範囲外になっているという事である。 73760 | そして今迄の経験から言ってこの現象が起こるのは履歴の操作をした後であるから、 73761 | 履歴の移動を行った際に _ble_edit_ind の更新を忘れている、または、更新に失敗しているというのが怪しい。 73762 | 73763 | ble-edit/history/goto を確かめてみたがちゃんと _ble_edit_ind _ble_edit_mark は設定されている。 73764 | 怪しいのは、ble-edit/history/goto の直後に ble-edit/isearch/.set-region を実行している箇所である。 73765 | ここで格納されている・或いは関数外から指定されている beg end はちゃんと範囲内になっているのだろうか。 73766 | 結局また迷宮入りの様な雰囲気がしている。 73767 | しかし前よりは進歩があった。_ble_edit_ind, _ble_edit_mark の設定が怪しい。 73768 73769 → _ble_edit_ind, _ble_edit_mark が異常な値 (範囲外) になっている。 73770 73771 [原因] 73772 73773 | 怪しい所を発見した。 73774 | ble/widget/isearch/next-history において、_ble_edit_history における一致箇所を取得している。 73775 | その次に ble-edit/isearch/.goto-match で一致した箇所に移動を行っている。 73776 | しかし、ble-edit/isearch/.goto-match から呼び出された ble-edit/history/goto では 73777 | _ble_edit_history_edit または _ble_edit_history から文字列をロードしている。 73778 | もし _ble_edit_history_edit が設定されているのに _ble_edit_history の中に一致が見付かった場合、 73779 | _ble_edit_str には _ble_edit_history_edit からの文字列が設定され、 73780 | _ble_edit_ind には _ble_edit_history の中の文字列における位置が設定される。 73781 | _ble_edit_history_edit の文字列が _ble_edit_history の文字列よりも短く、 73782 | 更に検索で _ble_edit_history の末尾付近 (_ble_edit_history_edit の文字列の長さよりも後尾) で一致が発生した場合、 73783 | そこで _ble_edit_ind に対する不整合が生じることになる。 73784 73785 →ble/widget/isearch/next-history において _ble_edit_history の中を検索している。 73786 しかし、実際に ble-edit/history/goto で設定される文字列は _ble_edit_history_edit から優先して取得される。 73787 両者の文字列の内容に違いがある場合不整合が生じる。 73788 更に、長さが異なり _ble_edit_ind が範囲外になった時にエラーが発生する。 73789 73790 [再現方法] 73791 73792 | 実際に再現するかどうかを試験する。 73793 | →カーソルの位置がずれるというバグを発見した。しかしながら、 73794 | 以前から出ているエラーは再現しない。 73795 | 73796 | うーん。_ble_edit_ind が不正な状態の時に self-insert が発生する為には、 73797 | 或る時点で検索が中断されなければならない。矢印キーで検索を中断しようとすると、 73798 | カーソルの移動が起こって、その際に正しい位置に _ble_edit_ind が設定され直す様だ。 73799 | (本当か?) → 確かに関数 .ble-edit.forward-char において範囲外になった時のチェック・補正が行われている。 73800 | という事は、矢印キー以外で検索を中断する手段があるという事になる。再度キー割り当てを確認する。 73801 | 73802 | C-d にすると補正が行われずに検索状態から抜けられそうである。 73803 | 実際にやってみた。確かに初めの self-insert で変な状態になっている様に見えるが、 73804 | しかしエラーは発生しない様である。うーん。と思ったが、検索した文字がいけない? 73805 | 73806 | 1. "echo hello" RET として入力・実行 73807 | 2. up back*5 down として hello を削除 73808 | 3. C-r "h" C-d で検索を行い中断 73809 | 73810 | としたが "h" で検索を行ったので "echo " の末尾にカーソルが設置された状態になっていて 73811 | 何も問題が発生していないという事ではないだろうか。という事で o で検索を行ってみる事にする。 73812 | 出た! 再現方法が分かった! 以下に再現方法の最小操作を書く 73813 73814 再現方法 → "aa" RET up C-u down C-r "a" C-d "a" 73815 73816 [解決方法] 73817 73818 ad hoc には検索時に _ble_edit_history だけでなく _ble_edit_history_edit も参照する様にすれば良い。 73819 しかし、やはり実際に履歴を遡った時に表示する内容を _ble_edit_history に格納した方が良いのではないかという気がする。 73820 つまり、現在は実際の履歴を _ble_edit_history に格納し、履歴の編集仕掛の状態を _ble_edit_history_edit に格納しているが、 73821 そうではなくて、編集したものも含めて _ble_edit_history に格納しておいて、 73822 編集前の状態を _ble_edit_history_edit に格納するという様に変更するべきかもしれない。 73823 73824 しかし、一方で現在の編集状態が _ble_edit_history に入っていると不都合という場合もあるかもしれない。 73825 _ble_edit_history か _ble_edit_history_edit かどちらの値が入っている方が扱いやすいかについて、 73826 それぞれの配列が使用されている各箇所で確認を行う必要がある。 73827 73828 * ble-edit/history/add の erasedups のチェックで使用する _ble_edit_history は編集前の内容であるべきである。 73829 * ble-edit/history/goto で読み出しているのは編集後の内容であるべきだ。現在は既にその様な実装になっている。 73830 * ble/widget/isearch/next-history で使用するのはやはり編集後の内容であるべきだ。 73831 そしてここではループなどで読み取りを実行する為、_ble_edit_history_edit, 73832 _ble_edit_history の両方をチェックする様な実装にはしたくない。 73833 73834 両者ともループでチェックする部分を含んでいる事から、編集前の状態と編集後の状態を完全に保持するという手もある。 73835 73836 * redo undo との関係 73837 73838 | また、今後 redo undo を実装することも考えて実装を選択する必要もあるだろう。 73839 | redo undo を前提にするとどの様な実装が良いだろうか。 73840 | 73841 | a 一つの方法は現在の編集後の状態を _ble_edit_history に記録しておいて、 73842 | 編集の履歴は一つの配列に edit[編集番号]="履歴番号 文字列" の形で積み重ねて記録する方法である。 73843 | b もう一つの方法は、配列の履歴番号に対応する要素に edit[履歴番号]="文字列0 文字列1 ..." と格納する方法である。 73844 | この方法だと格納する文字列に適切な escape を施す必要がある。 73845 | 例えば空白類を別の文字で置き換えるか、或いは、%q で格納しておいて使用する時に eval で取り出す。 73846 | c 或いは編集前の状態を _ble_edit_history に記録して、編集の履歴を a と同様に格納する方法、 73847 | d また、編集前の状態を _ble_edit_history に記録して、編集の履歴を b と同様に格納する方法が考えられる。 73848 | 73849 | 何れの方法を選ぶとしても erasedup check もしくは next-history で、 73850 | 編集前の状態、編集後の状態の両方を高速に処理することはできない。 73851 | という事は結局、やはり、編集前の状態・編集後の状態・編集過程の情報 73852 | の三種類を独立に管理するという事になる。 73853 | この内の "編集過程の情報" の管理に関しては redo undo で完全に閉じている話で、 73854 | 実際に redo undo を実装する段階になってから考察すればよい。 73855 | そして、編集前の状態・編集後の状態に関しては redo undo の方法に依らずに実装できる。 73856 | つまり、redo undo と履歴データの保持は直交的である。或いは、直交的な実装にするのが見通しがよい。 73857 73858 [結論] 73859 73860 "編集前の状態"・"編集後の状態" は redo undo とは関係なく実装する。 73861 更に redo undo については "編集過程の情報" を保持する何らかの形式の配列を用いる。 73862 73863 % 現在は、編集前の状態を _ble_edit_history に格納し、 73864 % 編集がある場合には編集後の状態を _ble_edit_history_edit に格納している。 73865 % その儘 _ble_edit_history_edit が完全な情報を持つ様に拡張を行うのが自然に思われる。 73866 % しかし、その為の管理は大変ではないかどうか確かめる必要がある。 73867 % 73868 % 基本的に _ble_edit_history に値を設定している箇所で 73869 % 同様に _ble_edit_history_edit にも値を設定する様にすればよい。 73870 % 調べてみた所 _ble_edit_history に値を設定しているのは、 73871 % ble-edit/history/load と ble-edit/history/add だけである。 73872 % また _ble_edit_history_edit に値を設定しているのは、 73873 % ble-edit/history/add で _ble_edit_history_edit の中身をクリアしている所と、 73874 % ble-edit/history/goto で移動前に値を格納している所だけである。 73875 % 以外と変更範囲が少ないので拡張の見通しは良い。 73876 % 73877 % [実行] 73878 % _ble_edit_history_edit の拡張を実行する。 73879 % 更に改名: _ble_edit_history -> _ble_edit_history0, 73880 % _ble_edit_history_edit -> _ble_edit_history 73881 % 73882 % [問題] 73883 % 変更してみるとバグは発生しなくなった。しかし今度は別の問題点が生じる。 73884 % コマンドの実行が遅い。コマンドを実行する際に履歴に実行するコマンドを登録する。 73885 % その時に _ble_edit_history0 の内容を丸ごと _ble_edit_history にコピーする。 73886 % そのコピーに時間が掛かっている様だ。実際に、 73887 % 73888 % time alpha=("${_ble_edit_history[@]}") 73889 % 73890 % を実行してみると、0.374s かかっている。ble-edit/history/add ではこれを2回実行している。 73891 % つまり、毎回 0.7s 以上の遅延が生じるという事になる。 73892 % 73893 % やはり丸ごと同じ物を管理するというのは非現実的なのだろうか。 73894 % 或いは、_ble_edit_history の内容をクリアするのに丸まるデータをコピーするのではなく、 73895 % 変更のあった物だけクリアするという方法でも良い。 73896 % この方針の場合には、変更のあった履歴番号を記録に残しておく必要がある。 73897 % 73898 % 或いは、実際に _ble_edit_history を使おうとするまでは 73899 % _ble_edit_history0 -> _ble_edit_history のコピーは遅延させるか。 73900 % しかし何れにしても history の検索に無駄な時間が掛かることに違いはない。 73901 73902 速度が遅いということが判明したので、 73903 _ble_edit_history_edit にも完全な情報を持たせるという方法は棄却することにした。 73904 代わりに、(多少検索に時間が掛かる様になるかもしれないが) 編集後の値が必要な箇所では 73905 73906 ${_ble_edit_history_edit[i]-${_ble_edit_history[i]}} 73907 73908 の形式でアクセスする様に変更した。 73909 73910 何れにしても現在の時点で既に検索には時間が掛かる傾向があって、 73911 その対策として検索中に入力がないかチェックすることを考えていた。 73912 検索中に入力がないかチェックする機能が完成すれば、 73913 この形式のアクセスによるオーバーヘッドは気にならなくなるだろう。 73914 (実測はしていないが元々そんなに重くはないだろうと予想されるので)。 73915 73916 以下にある過去の報告はこの修正で直った物と思われる。 73917 もし依然として問題が残っているのだとしても、それはその時に考える事にする。 73918 73919 | 2016-01-12 73920 | 73921 | * 履歴検索を起動しただけで×になった。比較的最新版である。 73922 | 最近の構文解析のバグは全て潰した後である。 73923 | 73924 | | stackdump: X1 0 <= beg:11 <= end:12 <= iN:1, beg:11 <= end0:11 (shift=1 text=s) 73925 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73926 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:4 (_ble_edit_str.update-syntax) 73927 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-135 (ble-highlight-layer:syntax/update) 73928 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:4441 (ble-highlight-layer/update) 73929 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:4884 (.ble-line-text/update) 73930 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (.ble-edit-draw.update) 73931 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (.ble-edit-draw.update-adjusted) 73932 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:966 (ble-edit/bind/.tail) 73933 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-4230 (ble-decode-byte:bind/EPILOGUE) 73934 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1 (ble-decode-byte:bind) 73935 | | -bash: beg: 読み取り専用の変数です 73936 | | stackdump: X2 0 <= 0 <= 11 <= 12 <= 1 <= 1 73937 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73938 | | ※以降のエラーは全て ble-syntax/parse 以下で起きている。 73939 | | 上記と同じなので詳細な stackdump は以降は省略する。 73940 | | stackdump: X1 0 <= beg:12 <= end:13 <= iN:2, beg:12 <= end0:12 (shift=1 text=ss) 73941 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73942 | | -bash: beg: 読み取り専用の変数です 73943 | | stackdump: X2 0 <= 1 <= 12 <= 13 <= 2 <= 2 73944 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73945 | | stackdump: X1 0 <= beg:13 <= end:14 <= iN:3, beg:13 <= end0:13 (shift=1 text=ssh) 73946 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73947 | | -bash: beg: 読み取り専用の変数です 73948 | | stackdump: X2 0 <= 2 <= 13 <= 14 <= 3 <= 3 73949 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73950 | | stackdump: X1 0 <= beg:14 <= end:15 <= iN:4, beg:14 <= end0:14 (shift=1 text=ssh ) 73951 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73952 | | -bash: beg: 読み取り専用の変数です 73953 | | stackdump: X2 0 <= 3 <= 14 <= 15 <= 4 <= 4 73954 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73955 | | stackdump: X1 0 <= beg:15 <= end:16 <= iN:5, beg:15 <= end0:15 (shift=1 text=ssh l) 73956 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73957 | | -bash: beg: 読み取り専用の変数です 73958 | | stackdump: X2 0 <= 4 <= 15 <= 16 <= 5 <= 5 73959 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73960 | | stackdump: X1 0 <= beg:16 <= end:17 <= iN:6, beg:16 <= end0:16 (shift=1 text=ssh la) 73961 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73962 | | -bash: beg: 読み取り専用の変数です 73963 | | stackdump: X2 0 <= 5 <= 16 <= 17 <= 6 <= 6 73964 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73965 | | assertion failure: ((nofs<${#node[@]})) 73966 | | ble-syntax/tree-enumerate/.impl(i=4,iN=6,nofs=0,node=,command=ble-syntax/parse/shift.impl2/.proc1)/FATAL1 73967 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:7612 (ble-assert) 73968 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:108 (ble-syntax/tree-enumerate/.impl) 73969 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:22 (ble-syntax/tree-enumerate) 73970 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:1901 (ble-syntax/parse/shift) 73971 | | @ /home/murase/.mwg/src/ble.sh/out/ble.sh:-16 (ble-syntax/parse) 73972 | 73973 | 三つの問題点が生じている。再現性はない (正確には、再現方法は未だ不明)。 73974 | 73975 | 1. dirty range がおかしい (文字列の長さの外にある)。 73976 | これはここではなく dirty range を更新している部分でチェックを行うべきではないか。 73977 | 2. dirty range がおかしい時の対策として beg, end を再設定している。 73978 | しかしここで "-bash: beg: 読み取り専用の変数です" のエラーが発生している。 73979 | 3. 以下のエラーが発生している。node が空である。 73980 | assertion failure: ((nofs<${#node[@]})) 73981 | ble-syntax/tree-enumerate/.impl(i=4,iN=6,nofs=0,node=,command=ble-syntax/parse/shift.impl2/.proc1)/FATAL1 73982 | 73983 | どうも今迄の経験から 1. の範囲の異常は履歴の移動に関係している気がする。 73984 | 取り敢えず 2. "beg: 読み取り専用の変数です" のエラーメッセージの部分だけは修正する。 73985 | 3. に関してはこのエラーに関係しているのかどうか分からないが、 73986 | 一見すると独立なエラーのようにも思われる。 73987 | しかし発生したタイミング的には明らかに相関している。 73988 | そうだとするとどの様にしてこのエラーが発生するのか確認する必要がある。 73989 | 73990 | 先ずは改めて dirty range の計算について調べる。 73991 | _ble_edit_str が直接変更されているのは、初期化時を除けば、 73992 | function _ble_edit_str.{replace,reset,reset-and-check-dirty} のみである。 73993 | 現在の所 reset-and-check-dirty は使用されていない。 73994 | 73995 | →トラップをしかけたら直ぐに引っかかった。 73996 | _ble_edit_replace である。履歴検索をして中断した後になる。 73997 | 73998 | 2015-11-30 73999 | 74000 | * 構文解析部分更新の bug 74001 | 74002 | + bug (2015-11-28a) 74003 | 74004 | $ seq2gif -f 0 -b 254 < demo.tty > out/img/demo.gif 74005 | カーソルを先頭に移動した時?? 再現しない。 74006 | 74007 | + stackdump: X1 0 <= 48 <= 49 <= 1, 48 <= 48 74008 | @ /home/murase/prog/ble/ble.sh:-16 (ble-syntax/parse) 74009 | @ /home/murase/prog/ble/ble.sh:4 (_ble_edit_str.update-syntax) 74010 | @ /home/murase/prog/ble/ble.sh:-135 (ble-highlight-layer:syntax/update) 74011 | @ /home/murase/prog/ble/ble.sh:4327 (ble-highlight-layer/update) 74012 | @ /home/murase/prog/ble/ble.sh:4818 (.ble-line-text/update) 74013 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 74014 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 74015 | @ /home/murase/prog/ble/ble.sh:1001 (.ble-decode-byte:bind/tail) 74016 | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 74017 | stackdump: X2 0 <= 0 <= 48 <= 49 <= 1 <= 1 74018 | @ /home/murase/prog/ble/ble.sh:-16 (ble-syntax/parse) 74019 | @ /home/murase/prog/ble/ble.sh:4 (_ble_edit_str.update-syntax) 74020 | @ /home/murase/prog/ble/ble.sh:-135 (ble-highlight-layer:syntax/update) 74021 | @ /home/murase/prog/ble/ble.sh:4327 (ble-highlight-layer/update) 74022 | @ /home/murase/prog/ble/ble.sh:4818 (.ble-line-text/update) 74023 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 74024 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 74025 | @ /home/murase/prog/ble/ble.sh:1001 (.ble-decode-byte:bind/tail) 74026 | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 74027 | 74028 | また出た。一旦 C-u した後に RET して貼付をしたら出た。2015-12-03 74029 | でもまた同じようにしても再現しない?? 74030 | 74031 | stackdump: X1 0 <= beg:66 <= end:96 <= iN:30, beg:66 <= end0:66 (shift=30 text=function () () { echo hello; }) 74032 | @ /home/murase/prog/ble/ble.sh:-16 (ble-syntax/parse) 74033 | @ /home/murase/prog/ble/ble.sh:4 (_ble_edit_str.update-syntax) 74034 | @ /home/murase/prog/ble/ble.sh:-135 (ble-highlight-layer:syntax/update) 74035 | @ /home/murase/prog/ble/ble.sh:4353 (ble-highlight-layer/update) 74036 | @ /home/murase/prog/ble/ble.sh:4844 (.ble-line-text/update) 74037 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 74038 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 74039 | @ /home/murase/prog/ble/ble.sh:1140 (.ble-decode-byte:bind/tail) 74040 | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 74041 | stackdump: X2 0 <= 0 <= 66 <= 96 <= 30 <= 30 74042 | @ /home/murase/prog/ble/ble.sh:-16 (ble-syntax/parse) 74043 | @ /home/murase/prog/ble/ble.sh:4 (_ble_edit_str.update-syntax) 74044 | @ /home/murase/prog/ble/ble.sh:-135 (ble-highlight-layer:syntax/update) 74045 | @ /home/murase/prog/ble/ble.sh:4353 (ble-highlight-layer/update) 74046 | @ /home/murase/prog/ble/ble.sh:4844 (.ble-line-text/update) 74047 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 74048 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 74049 | @ /home/murase/prog/ble/ble.sh:1140 (.ble-decode-byte:bind/tail) 74050 | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 74051 | 74052 | 見た感じ dirty-range の更新に失敗している様である。 74053 74054 2016-04-07 74055 74056 * バグが出た。再現性がある。 [2016-04-05 提起] [#D0321] 74057 74058 今迄に出ていたバグとはまた種類が異なる様に見える。 74059 74060 | $ CXXKEY=g454 cxx -I$HOME/opt/libmwg-201509 20160318.idea.sfinae-overload.cpp ← 最後の引数の先頭で C-w C-y C-y する 74061 | $ CXXKEY=g454 cxx -I$HOME/opt/libmwg-201509 -I$HOME/opt/libmwg-201509 20160318.idea.sfinae-overload.cpp 74062 | $ CXXKEY=g454 cxx -I$HOME/opt/libmwg-201509 -I$HOME/opt/libmwg-201509 20160318.idea.sfinae-overload.cpp 74063 | $ CXXKEY=g454 cxx -I$HOME/opt/libmwg-201509 -I$HOME/opt/libmwg-201509/i 20160318.idea.sfinae-overload.cpp 74064 | 74065 | assertion failure: ((nofs<${#node[@]})) 74066 | ble-syntax/tree-enumerate/.impl(i=40,iN=106,nofs=0,node=,command=ble-syntax/parse/shift.impl2/.proc1)/FATAL1 74067 | @ /home/murase/prog/ble/ble.sh:7630 (ble-assert) 74068 | @ /home/murase/prog/ble/ble.sh:108 (ble-syntax/tree-enumerate/.impl) 74069 | @ /home/murase/prog/ble/ble.sh:22 (ble-syntax/tree-enumerate) 74070 | @ /home/murase/prog/ble/ble.sh:2127 (ble-syntax/parse/shift) 74071 | @ /home/murase/prog/ble/ble.sh:-16 (ble-syntax/parse) 74072 | @ /home/murase/prog/ble/ble.sh:4 (_ble_edit_str.update-syntax) 74073 | @ /home/murase/prog/ble/ble.sh:-135 (ble-highlight-layer:syntax/update) 74074 | @ /home/murase/prog/ble/ble.sh:4388 (ble-highlight-layer/update) 74075 | @ /home/murase/prog/ble/ble.sh:4902 (.ble-line-text/update) 74076 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 74077 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 74078 | @ /home/murase/prog/ble/ble.sh:966 (ble-edit/bind/.tail) 74079 | @ /home/murase/prog/ble/ble.sh:-4248 (ble-decode-byte:bind/EPILOGUE) 74080 | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 74081 74082 単純化する。何と以下の操作だけでバグが出る。 74083 74084 $ echo $B+ 74085 $ echo $B+ 74086 $ echo $B+12 74087 74088 上から二行目の時点で何か以上になっていると見るべきであろう。 74089 空白を消したりせずに、先頭から順に入力した時には何もエラーには為らないので、それと比較すればよい。 74090 74091 +-------------------------------------------------------------+-------------------------------------------------------------+ 74092 | エラーが発生する直前 | 正常時 (順に入力した時) | 74093 +-------------------------------------------------------------+-------------------------------------------------------------+ 74094 | [murase@padparadscha 0 ~]$ echo $B+ | [murase@padparadscha 0 ~]$ echo $B+ | 74095 | A? | A? | 74096 | 2 aw 000 'e' | stat=(1 w=- n=- t=-1:-1) | 2*aw 000 'e' | stat=(1 w=- n=- t=-1:-1) | 74097 | | aw 001 'c' | | |*aw 001 'c' | | 74098 | | aw 002 'h' | | |*aw 002 'h' | | 74099 | | aw 003 'o' + word=2:0-4 | |*aw 003 'o' + word=2:0-4 | 74100 | 3 a 004 ' ' | 3*a 004 ' ' | 74101 | 14 a s 005 '$' | stat=(3 w=- n=- t=1:-1) | 14*a 005 '$' | stat=(3 w=- n=- t=1:-1) | 74102 | 7 a 006 'B' | | 7*a 006 'B' | | 74103 | 4 a 007 '+' + word=4:@3>5-8 stat=(4 w=4:5- n=- t=-1:4) | 4*a 007 '+' + word=4:@3>5-8 stat=(4 w=4:5- n=- t=-1:3) | ! 74104 | \_ 'echo' | \_ 'echo' | 74105 | \_ '$B+' | \_ '$B+' | 74106 +-------------------------------------------------------------+-------------------------------------------------------------+ 74107 74108 早速違いがある。記録されている stat だ。木構造に於ける兄の位置がずれている。 74109 具体的に表示されているのは t=tclen:tplen の様だ。 74110 実際には tplen = _ble_syntax_stat[index][5] に記録されている。 74111 74112 正常値 tplen=3 は 3 文字前の 境界4 で単語が終了している事を表している。 74113 そして、それは実際には単語情報が セル3 に格納されている事を表す。 74114 一方で異常値 tplen=4 は境界3 で単語が終了して セル2 にデータが格納されている事を期待する。 74115 ところが其処には何も格納されていない為にエラーが発生するのである。 74116 74117 と言う事はスペースを削除する瞬間に _ble_syntax_stat[index][5] の shift に失敗している事になる。 74118 shift を実行しているのは function ble-syntax/parse/shift.stat である。 74119 実際に shift の際に呼び出されている所を確認する。j=9 及び j=6 で呼び出されている。 74120 これは実際に stat が設置されている場合にのみ shift を行うという事なのだろう…? 74121 しかし良く分からないのが、この時点で設置されているのは j=6 及び j=8 なのではないかという事である。 74122 うーん呼出元を確認してみる事にする。現在は ble_shift_method は 2 に設定されているので、 74123 function ble-syntax/parse/shift.impl2/.proc1 が実効的に処理をしている事になる。 74124 これに実装中という文字が書かれているのが気になるが、よく動作を見てみる事にする。 74125 74126 ここで気付いたのだが、shift が起こったかどうかは _ble_syntax_shift という配列に記録して、 74127 それを上記の dump で表示している事に気付いた。s という文字がある場所でだけ実際に shift が起こったという事を表す。 74128 確かにそれを見ると 境界7 に設定されている stat で shift が起こらなかったという事が見て取れる。 74129 つまり、このバグの問題点は shift するべき対象の列挙に失敗しているという事である。 74130 74131 やりにくいので末尾 (iN 番目) に設置されている stat も ble_debug=1 で表示する事にする。 74132 74133 改めて ble-syntax/parse/shift.impl2/.proc1 に戻る。 74134 ble-syntax/parse/shift.impl2/.proc1 の呼び出しの時点では j = 9 ... 6 について処理を行う様に呼び出しがある様だ。 74135 という事は問題は skip にあるという事だろうか。というか i だとか j2 だとか j の値は誰が決めているのだろうか。。 74136 74137 - 先ず、i については ble-syntax/tree-enumerate/.impl が設定している値の様である。 74138 現在処理を行っている word (tree node) の終端境界の番号である。 74139 具体的に word の情報は _ble_syntax_tree[i-1] に格納されている。 74140 さて、ここでの疑問は shift.impl2 で参照している変数 i が果たして 74141 本当に tree-enumerate の内部変数を意図しているのかという事である。 74142 shift.impl2 の呼出元を辿ってみるが意図して i を設定しているという箇所はないようなので、 74143 これは確かに tree-enumerate の内部変数 i を意図しているのだろうと推測・仮定する。 74144 74145 - 次に j, j2 に関しては ble-syntax/tree-enumerate/.impl では特に設定を行っていない様である。 74146 というか寧ろ shift.impl2/.proc の呼出元 (ble-syntax/parse/shift) で意図的に iN 及び j を設定している。 74147 この変数名は本当は変えるべきである。tree-enumerate の実装を変更して内部で j を使う様に変えてしまうと事故が起こる。 74148 いや、iN に関しては変更する必要はない、というか、iN は tree-enumerate に対する入力(tree 起点)なので変数名は変えては行けない。 74149 74150 うーん。変数名を変えようと思ったが tree-enumerate を跨いで共有されている変数が実は他にも沢山ある様だ。 74151 しかも広範な関数でこれらが共有されている。 74152 74153 beg,end,end0,shift は勿論の事、ble-syntax/parse のローカル変数である i1,i2,j2,iN も共有されている。 74154 そして j に関しても、shift.stat, shift.nest, shift.tree, shift.tree/1 等の 74155 諸々の関数で使用されているので変数名を変える訳には行かない。 74156 しかし j という変数名は余りに衝突が起きやすそうであり危険である。 74157 これは後で処理する事にした。 74158 74159 変数の役割については大体分かったので、実際に .proc1 を呼び出した時の変数の様子について見てみる。 74160 74161 shift.impl2/.proc1: current word: 6-9, end0=6 tprev=4 tchild=-1 74162 shift.impl2/.proc1: loop will be j = 9 (_shift2_j) ... 6 (j2) 74163 74164 という事のようだ。この時 tchild が存在していないので内部に対する探索は行われない。 74165 そのままその単語についてだけ処理が行われて中に設置されているデータに対する shift は実施されないのである。 74166 つまり "$B+" という単語については内部構造がないので内部の shift を省略するというのである。 74167 しかしながら実際には内部に解析再開点が存在している。これらの shift が飛ばされてしまうのである。 74168 74169 うーん。これはこの shift 対象列挙の strategy 自体に欠陥があるという事になる。 74170 内部の解析再開点に関しては一つ一つ配列の中身を確認して shift を試みるという手もあるが、 74171 それだと元々の strategy 1 と違いがない。寧ろ strategy 1 の様に単純に shift を全部試みるのがよい。 74172 或いは、 74173 74174 結局何が問題なのかというと内部の解析再開点については単語の内部にしか参照を持っていないと仮定したからではないかという気がする。 74175 74176 > 一つの方法は tree nest は木構造を反映した方法によって更新を行い、stat はそれとは別に更新を行うという方法である。 74177 > そして、stat を保持するに当たって直前の stat の位置を一緒に記録する事にするのである。 74178 > 直前の stat の位置の情報を保持するとなると 74179 > 74180 > - ble-syntax/parse の変数が一つ増える。 74181 > - shift の際にその直前の stat の位置もずらさなければならない。 74182 > - 直前の stat の位置も一致していないと同一状態になったと判定できないので、中断が起こりにくくなる。 74183 > 74184 > > しかしながら直前の stat の位置というのは実は解析に使用されていないので、 74185 > > それが一致していなくても解析中断を実行しても良いという気がする。 74186 > > というか、今迄が直前の stat の位置に依存せずに中断を起こしていたのでこれは問題にならない。 74187 > > 単純に前回の解析中断位置をその場で更新して終了するだけで済む話である。 74188 > > 更に、len (負のoffset) で記録しておけば shift も実は行わなくて良い様な気がする。 74189 > > len を shift する必要がある場合というのは、 74190 > > 直前の解析中断位置と現在位置の間に dirty range が被っている場合で、 74191 > > しかし、その様な場合に関しては何れにしても再解析が実行される事になるのでその時に結局上書きされるのである。 74192 > 74193 > 結論: 直前の stat の位置は解析中断判定には使わない。直前の stat の位置は stat 更新時に設定すればよい。 74194 > 74195 > しかし、shift だけを実行して、実際の解析を最後までやりきらなかった場合には一体どうなるのだろうか。 74196 > 現状ではその様な動作はしない事になっているが将来的には解析を途中で中断して、それから 74197 > 解析を後で再開するというような機能を実装したいと考えている。というか、現在の構造はそれを意図しての構造である。 74198 > しかし、解析を後で再開しようという時に直前 stat 位置の shift が中途半端な状態になっていると 74199 > 再度の shift を実行する事が不可能になってしまう。 74200 > 74201 > →えーと。でもそれは現在の tree-enumerate による実装でも同様なのではないだろうか。 74202 > 途中で解析を中断して後で解析を始めよう…という時に tree 構造が中途半端になっていると、 74203 > そもそも tree 構造を辿って shift 位置を楽しようと言う事ができなくなる。 74204 > つまり、現在の実装だと結局全探索を余儀なくされるという事になるのではないだろうか。 74205 > 74206 > ちょっと現在の手法について再度一から考え直した方が良いような気がする。 74207 > 74208 > 一応直前 stat 位置を記録する、という方法は何とか manage する事ができる。 74209 > 解析途中で一時停止をする際に辻褄が合うように直前 stat 位置を更新すればよいのである。 74210 > しかし tree 構造に関して解析一時停止をする時になんとか辻褄が合うような形にするというのは無理である。 74211 > できるとしても可成り複雑になりプログラムを書くのが面倒になる事請け合いである。 74212 > 74213 > 従って tree, nest に関してもそれぞれに直前の非空白要素の位置を管理する様にすれば良い気がする。 74214 > そもそもは、既にある tree の仕組みを利用すれば additional な情報を管理せずに 74215 > 高速に shift 対象を列挙できるのではないかと考えた事にあった。 74216 > この様に直前の非空白要素の位置を管理するようにしてしまうと管理コストが増えてしまう。 74217 > しかし、これも将来的にはしょうがないという気もする。 74218 74219 結論: 74220 74221 現状の方法では、解析一時中断を行った時に shift 対象の高速な列挙が出来なくなる。 74222 唯一の現実的な高速化手法は "直前非空白要素の位置" を管理するように変更する事である。 74223 これは解析自体の動作とは全く関係なく、_ble_syntax_tree/stat/nest の配列としてのデータ構造を拡張するという事である。 74224 解析自体の実装とは直交して実装する事が可能と思われるが、新規情報の管理コストが増えるという問題点が残る。 74225 74226 > 解析一時中断を考えない現状での解決方法についても考えてみる。 74227 > 解析一時中断を考えない事にすれば、現状の方法でも解決する方法があるかもしれない。 74228 > 何が問題だったかというと、その単語が dirty range に被っていないのであれば、 74229 > 内部に存在している stat nest の何れも dirty range 及びそれを跨いだ参照は持たないと仮定した事にある。 74230 > しかし乍らその単語自体が dirty range に被るような参照を持っている場合は、 74231 > 内部に設置された stat も dirty range に被るような参照を持っているという事を意味する。 74232 > 何故ならばその単語が dirty range に被るような参照を持つ事が出来るのは、 74233 > 内部の stat を通じてその参照が継承されたからなのである。 74234 > 従って *少なくとも* その単語自体が dirty range に被るような参照を持っている場合には、 74235 > 内部の shift を実行する必要があるという事になる。 74236 > 問題はその単語自体が dirty range に被るような参照を持たない場合に、 74237 > 実は内部の stat が dirty range に被るような参照をもっているかもしれないという事である。 74238 > 外部に対する参照として可能なのは基本的に tprev inest のみである。 74239 > 単語内部では既に wbegin が設定された状態にあり、それを跨ぐ事が出来るのは tprev (tplen) inest (nlen) だけだからである。 74240 > tchild (tclen) に関しては wbegin 以降でなければならない。wlen については wbegin その物を参照する。 74241 > その他の種類の参照は多分存在していない様に思う。 74242 74243 結論: 単語外部に対する参照として可能なのは tprev inest のみである。 74244 tplen 及び nlen について dirty-range に被らないという事が保証できる時に 74245 単語内部の探索のスキップが可能である。 74246 74247 tprev に関してチェックを追加しようと思ったら既にチェックが入っていた。 74248 というかコメントに正にその様に書かれている。 74249 それなのに今回その事が問題になった。では、一体何が悪いのか。 74250 何か ble-syntax/parse/shift.impl2/.proc1 の構造が変である。 74251 →結局大幅に直した。バグが出なくなった。skip も適切に行われている。 74252 結局、問題点については shift.impl2/.proc1 の実装当初認識していたが実装が甘かったという事だ。 74253 74254 % 後で余裕があれば shift.stat, shift.nest, shift.tree, shift.tree/1 は引数で j を受け取る様に変更する。 74255 % 74256 % shift.stat, shift.nest の呼出元は何れも 3 箇所である。意味的にも j を引数で受け取って変な事はない。 74257 % shift.tree の呼出元は二箇所である。しかし実は既に引数として nofs を受け取る仕組みになっている。 74258 % j を新しく受け取れるような仕組みにはなっていない…? 74259 % 然し意味を考えれば nofs というのは _ble_syntax_tree[j] 74260 % の要素の中の更に nofs 番目のフィールドという意味であるから、 74261 % 本来は nofs を受け取るのであればそれが属している所の j も受け取るのが自然である。 74262 % なのでこれも書き換えて問題ないと考える。 74263 % shift.tree/1 に関しては様々なローカル変数を受け取っている中で j だけ引数で受け取るようにするのは変である。 74264 % 幸いにして呼び出しているのは shift.tree だけなので、 74265 % shift.tree/1 は親の shift.tree のローカル変数を共有していると考えて、 74266 % ローカル変数 j を直截さ割って良い事にする。関数名が shift.tree/1 であるのはそういう事である。 74267 % 74268 % もう一つ確認しておくべき事は各関数が j を内部で書き換えていないかという事である。 74269 % 内部で書き換えた値が外部に伝播する事を意図しているのだとしたら、 74270 % 単純に引数で受け取るように変更してしまうと問題が生じる。 74271 % これに関しては関数内部を観察してみた所 j を書き換えている様子はないし、 74272 % 関数の役割的にも j を書き換えるのは不自然に思われたので、多分大丈夫だろう。 74273 % 多分だとアレなので再度確認する。特に別の関数を呼び出しているという事もないようなので、 74274 % 更に子関数で書き換えられているという危険性もない。 74275 % 唯一呼び出されている関数が touch-updated-word であるが、この関数も内部で j には触っていない。 74276 % 74277 % よって以下のように変更を行う → OK 74278 % - shift.stat, shift.nest, shift.tree は引数を介して j を受け取る様にする。 74279 % - 特に shift.tree に関しては第一引数に j を受け取り、第二引数に nofs を optional で受け取る様にする。 74280 74281 変数名の変更については、そもそもそんなに綺麗な実装でもないのでどうでも良くなった。 74282 というか j を紛らわしくない変数名にすると言っても余り良い変数名も思い付かないし、 74283 _shift2_j の様な不自然に長い変数名だと関数を書いていて何か変な感じがする。 74284 結局 tree-enumerate を跨ぐ部分でだけ _shift2_j という変数に値を待避する事にした。 74285 74286 tree-enumerate による skip の実装と解析一時中断の不整合に関しては別項目で残す事にする。 74287 74288 74289 2015-12-24 74290 74291 * (ble-syntax:bash): time -p 対応 [#D0320] 74292 74293 > [2015-02-16] (ble-syntax:bash): time -p 74294 74295 parse_suppressNextStat を用いて無理矢理対応した。 74296 問題があるかもしれないので注視する。 74297 74298 + parse_suppressNextStat は常に設置する事にする。 74299 74300 当初条件を満たせば parse_suppressNextStat を設置せずに 74301 -p を解析済とする様にしていたがそれでも問題が起こる様だった。 74302 74303 例えば time -p<(echo hello) の様に入力する事を考える。 74304 time -p< まで入力した時点で time -p で確定し、再開点が < に設置される。 74305 しかし <( まで入力した時点で、実は '<' はリダイレクトではなくて単語の一部だったという事になり、 74306 そこで単語が終わるという仮定の下での time -p での確定が誤りだったという事になる。 74307 74308 他にも似たような罠があるかもしれないので、 74309 複雑な条件で parse_suppressNextStat 設置を省略するのは止めて、 74310 常に parse_suppressNextStat は設置する様にする事にする。 74311 74312 + -p を確定した場合は単語を設置する事にする。 74313 74314 この様にしないとコマンドとして解釈していた時の単語着色が残ってしまう。 74315 (これは現在の単語着色の仕組みの問題点に起因する物であるが、 74316 -p を単語として登録しても別に損する事は無いし寧ろ好ましい)。 74317 74318 * (ble-syntax:bash): a=([...]=value), a+=([...]+=delta) に対応。 [#D0319] 74319 74320 > [2015-02-16] (ble-syntax:bash): a=([key]=value) b=([x]=123 [y]=321) 74321 74322 * bug: extglob の所為で var+= が正しく読み取られない。 [#D0318] 74323 74324 どうも var+ まで入力した時点で |var|+ の二箇所に解析再開点が設置される様である。 74325 この状態で var+= を入力しても解析は += から再開されるので、 74326 正規表現の var+= に引っかかる事がないという事になる。 74327 74328 これを何とかする為には、+( 以外の + については解析再開点を設置せずに 74329 前の解析に取り込んで処理する必要がある。 74330 74331 parse_suppressNextStat という変数を新しく追加してみる事にした。 74332 この変数に値を設定すると次の stat 記録が保留される。 74333 これによって不都合が起こるかもしれないので暫く様子を見る。 74334 74335 * (ble-syntax:bash): \new 文脈 CTX_CASE [#D0317] 74336 74337 > ;& ;; ;;& の次に来るのは CTX_CMDX ではなくて CTX_CASE? 的な物では? 74338 > ;& ;; ;;& の場合には CTX_ARGX CTX_CMDXV に加え CTX_CMDX でも ERR ではない。 74339 74340 case word in 直後、;; ;;& ;& 直後 の状態。 74341 次に esac が来れば esac をコマンドとして受け入れる。 74342 次に ( が来ればそれをパターンの開始と解釈する。 74343 他の場合にはそのままパターンが開始すると解釈する。 74344 74345 未だ case コマンドの方で対応していないので、 74346 現状では case a in ...) は正しく解釈されない。 74347 74348 * ble-syntax.sh: CTX_VAL{X,I} から CTX_COND{X,I} を分離。 [#D0316] 74349 74350 > 値リストと条件コマンドの文法は、 &<>() 等の文字に対して結構違う。 74351 > 分離した方が良いのではないか? 74352 74353 * ble-edit.sh: bug: 履歴展開が効かない [#D0315] 74354 74355 * ble-syntax:bash extglob 対応 [#D0314] 74356 74357 > [2015-02-16] (ble-syntax:bash): extglob 74358 74359 extglob が有効なのはどの箇所か。 74360 - case pattern 内部 74361 - パラメータ展開内部 74362 - [[ == globpat ]] 74363 - シェル単語 74364 特に色付けなどをしなくても良くて入れ子状態だけ正しく処理できれば良いのであれば、 74365 シェル単語の箇所と case pattern 内部だけ処理すれば良い。 74366 色も付けようとなると面倒である。 74367 74368 74369 [入れ子構造の解析について] 74370 74371 パラメータ展開内部に関しては extglob の括弧の中にあるかどうかに拘わらず 74372 '}' が来ればパラメータ展開は終了する様である。 74373 extglob としての解釈はパラメータ展開を切り出してからの様である。 74374 74375 シェル単語などの様に裸で extglob の括弧が登場する場合に関しては 74376 文法的に特別な扱いをして括弧を考慮に入れなければ正しく構文解析する事ができない。 74377 (現状では構文解析が滅茶苦茶になるという事は無くて、 74378 単に括弧の開始部分と内部でエラーが発生するというだけであるが。) 74379 74380 1 パラメータ展開内部・[[ ]] の == 右辺に関しては特別な扱いを考える必要はない。 74381 2 シェル単語及び case のパターン部分を解析する際には extglob 74382 を考えて入れ子構造を追う必要がある。 74383 3 実は現状でも突如として出て来る () の解釈をコマンド置換としてではなく、 74384 配列処理と同様のリストとして解釈する様にすれば見た目上の動作として充分かも知れない。 74385 もっとつめるとすれば !( @( などの組合せを正しく認識して、 74386 認識できない組合せになっている時にエラーを表示するという事である。 74387 74388 配列のリストと同じようにしてみたがやはり動作としては異なる様な気がする。 74389 配列のリスト処理では単語分割まで実行するが、extglob の括弧の場合は、 74390 内部に単語などの構造はない。スペースがあったとしてもそのままスペースの文字として解釈される。 74391 更に <, > や ;, & 等のコマンド区切の文字も extglob 内部では通常文字として取り扱われる様だ。 74392 但し | は "または" の意味を持つ。 74393 (逆に言えば @() で quote できるという事にもなる?) 74394 74395 * (ble-syntax:bash): bugfix: redirect 直後に redirect/delimiter があった時に解析データ書き込み違反。 [#D0313] 74396 具体的には echo <>& と入力した時にエラーになる (そもそも <>& というリダイレクトは存在しない)。 74397 解析に際し echo <> までは問題なく終了し、その後で & を読もうとした時にエラーになる。 74398 直前の redirect に対してエラー設置及び nest-pop を実行していた為であった。 74399 直前の redirect は既に解析が終わっているので、これに対して変更を行う事は出来ない。 74400 74401 redirect を設置した時点で次に redirect/delimiter がないかチェックする様にしてみた。 74402 →問題なく動いている。しかし、エラーの設置位置にやはり違和感がある。 74403 エラーが設置されるべきは echo <>& の <> の方ではなくて、& の方ではないのか。 74404 →やはり & の方にエラーを設置する様に変更してみる。 74405 動いている…と思ったら何か変だ。カーソルの位置がジャンプする。 74406 変数がリークしているか? 74407 と思ったら単に正規表現テストの左辺を間違えている所為で 74408 インデックスの計算がおかしくなっていただけだった。 74409 →OK 動いている。 74410 74411 * ble-syntax.sh: 正規表現の整理: rex_delimiters [#D0312] 74412 一回変数に入れてから適用しているがその必要はないのでは? 74413 74414 整理 (自然解消した項目) 74415 74416 * [2015-02-18] 履歴展開の微妙な所 [#D0311] 74417 74418 例えば echo "!a" は !a の部分が履歴展開される。 74419 しかし echo !a" は !a" の部分が履歴展開される。 74420 これらの規則は一体どうなっているのだろう。man には大して何も書かれていない。 74421 74422 2015-12-23 74423 74424 * ble-syntax:bash declare 配列初期化構文対応 [#D0310] 74425 74426 > * [2015-02-16] ble-syntax.sh: local a=(arr) a+= 74427 > これは declare や local typeset readonly 等を文法的に特別扱いしなければ対応できない 74428 74429 色々試してみた所、以下のコマンドの引数で =() を特別扱いする様である。 74430 declare readonly typeset local export alias 74431 alias に関しては他のコマンドと全然性質が違う様な気がするし、 74432 export に関しては配列の初めの要素しか export されない気がするが、 74433 文法的には両者とも =() の形式を許容する様である。 74434 或いは、他にも同様の形式の引数を許容する組コマンドが存在するかもしれない。 74435 74436 (少なくとも echo などの組み込みコマンドや、外部コマンドに関しては 74437 引数に =() 等という物が含まれていると失敗する。) 74438 74439 [書き換え] 74440 74441 > 取り敢えず、CTX_ARGX, CTX_ARGI という文脈を複製して、 74442 CTX_ARGVX, CTX_ARGVI という文脈を作成した。 74443 74444 > [[:alpha:]_][[:alnum:]_]*\+?=() の形式の引数を許容する 74445 これは CTX_CMDX の辺りを真似すればよい。 74446 74447 > 補完候補生成の種類を指定 74448 74449 > その他ちゃんと動いているかのチェック。 74450 74451 * ble-syntax:bash: assignment a=(1 2 3) 直後の文脈の変更 [#D0309] 74452 74453 今迄、配列の代入文 a=(1 2 3) において、 74454 括弧を抜けた直後に次の単語に移る様に構成していた。 74455 (具体的には "(" を nest-push する直前に一旦単語を抜けてしまって、 74456 更に、ctx (nest-pop 時の文脈) として CTX_CMDXV を設定していた。) 74457 74458 しかしながら実際の bash で試してみると、代入文の () の直後は 74459 やはり未だ代入文の右辺の続きとして取り扱われる様である。 74460 即ち、a=(1 2)b=123 と記述すると、 74461 a=(1 2) b=123 と解釈されるのではなくて、 74462 a='(1 2)b=123' と解釈される様である。 74463 74464 bash の動作に合わせて "(" を nest-push する際は、 74465 単語をキャンセルしないし、また、nest-pop 時の文脈も敢えて変更はしない、 74466 という様に動作を変更する。 74467 74468 2015-12-21 74469 74470 * ble-syntax:bash [#D0308] 74471 > a[算術式] の終了条件 (() pairs ではなくて [] pairs を数える) 74472 > $((...)) ((...)) は () pairs で終了判定する。 74473 > ${a[...]} a[...]= $[...] は [] pairs で終了判定する。 74474 > ${v:...:...} は } が来たら無条件で終了する。 74475 74476 * bash-3.0 で C-d が効かなくなっている。 [#D0307] 74477 74478 * /dev/null に色が着いていない → つけた [#D0306] 74479 74480 整理 (自然解消した項目) 74481 74482 * [2015-02-16] ble-syntax:bash: 関数定義 function ... [#D0305] 74483 74484 * [2015-02-16] ble-syntax:bash: Here string [#D0304] 74485 74486 * [2015-02-16] ble-syntax:bash: aaa=(hoge), 他に aaa+=(hoge) というパターンもある。 [#D0303] 74487 74488 * [2015-11-23] ble-detach 後の stty sane [#D0302] 74489 現在はユーザに stty sane を実行して貰っている。もっと綺麗な方法はないか? 74490 →保留する。これは今のままでも余り気にならないのでそのままで良い。 74491 74492 2015-12-20 74493 74494 * ble-synta.sh: bug: 配列添字の書き換え時に syntax error [#D0301] 74495 74496 以下の編集でエラーになる。 74497 $ a['']= 74498 $ a['a']= 74499 74500 | assertion failure: ((nofs<${#node[@]})) 74501 | ble-syntax/tree-enumerate/.impl(i=5,iN=7,nofs=0,node=,command=ble-highlight-layer:syntax/word/.proc-childnode)/FATAL1 74502 | @ /home/murase/prog/ble/ble.sh:10 (ble-assert) 74503 | @ /home/murase/prog/ble/ble.sh:4 (ble-syntax/tree-enumerate/.impl) 74504 | @ /home/murase/prog/ble/ble.sh:164 (ble-syntax/tree-enumerate-children) 74505 | @ /home/murase/prog/ble/ble.sh:472 (ble-highlight-layer:syntax/update-word-table) 74506 | @ /home/murase/prog/ble/ble.sh:-135 (ble-highlight-layer:syntax/update) 74507 | @ /home/murase/prog/ble/ble.sh:4380 (ble-highlight-layer/update) 74508 | @ /home/murase/prog/ble/ble.sh:4884 (.ble-line-text/update) 74509 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 74510 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 74511 | @ /home/murase/prog/ble/ble.sh:966 (ble-edit/bind/.tail) 74512 | @ /home/murase/prog/ble/ble.sh:-4230 (ble-decode-byte:bind/EPILOGUE) 74513 | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 74514 | assertion failure: ((nofs<${#node[@]}))te_mode_buff='()'$ 74515 | ble-syntax/tree-enumerate/.impl(i=5,iN=7,nofs=0,node=,command=ble-syntax/print-status/.dump-tree/proc1)/FATAL1 74516 | @ /home/murase/prog/ble/ble.sh:10 (ble-assert) 74517 | @ /home/murase/prog/ble/ble.sh:4 (ble-syntax/tree-enumerate/.impl) 74518 | @ /home/murase/prog/ble/ble.sh:2 (ble-syntax/tree-enumerate-children) 74519 | @ /home/murase/prog/ble/ble.sh:7614 (ble-syntax/print-status/.dump-tree/proc1) 74520 | @ /home/murase/prog/ble/ble.sh:108 (ble-syntax/tree-enumerate/.impl) 74521 | @ /home/murase/prog/ble/ble.sh:5 (ble-syntax/tree-enumerate) 74522 | @ /home/murase/prog/ble/ble.sh:8005 (ble-syntax/print-status/.dump-tree) 74523 | @ /home/murase/prog/ble/ble.sh:-24 (ble-syntax/print-status) 74524 | @ /home/murase/prog/ble/ble.sh:-135 (ble-highlight-layer:syntax/update) 74525 | @ /home/murase/prog/ble/ble.sh:4380 (ble-highlight-layer/update) 74526 | @ /home/murase/prog/ble/ble.sh:4884 (.ble-line-text/update) 74527 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 74528 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 74529 | @ /home/murase/prog/ble/ble.sh:966 (ble-edit/bind/.tail) 74530 | @ /home/murase/prog/ble/ble.sh:-4230 (ble-decode-byte:bind/EPILOGUE) 74531 | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 74532 | 74533 | 異常 74534 | A? 74535 | 7 a 000 'a' | stat=(1 w=- n=- t=-1:-1) 74536 | 8 a 001 '[' | nest=(11 w=7:0- n=- t=-1:-1) 74537 | 9*a 002 ''' | stat=(8 w=- n=@1 t=-1:-1) 74538 | 5*a 003 'a' | 74539 | 9*a 004 ''' | 74540 | 8 a s 005 ']' | stat=(8 w=- n=@1 t=-1:-1) 74541 | | a s 006 '=' + word=7:0-7>@4 74542 | \_ 'a['a']=' 74543 | 74544 | 正常 74545 | A? 74546 | 7*a 000 'a' | stat=(1 w=- n=- t=-1:-1) 74547 | 8*a 001 '[' || nest=(11 w=7:0- n=- t=-1:-1) 74548 | 9*a 002 ''' || stat=(8 w=- n=@1 t=-1:-1) 74549 | 5*a 003 'a' || 74550 | 9*a 004 ''' |+ word=na[:1-5 74551 | 8*a 005 ']' | stat=(8 w=- n=@1 t=-1:-1) 74552 | |*a 006 '=' + word=7:0-7>@4 74553 | \_ 'a['a']=' 74554 | \_ '['a'' 74555 74556 74557 設置されている筈の単語が存在しないという所にある。 74558 というかそもそも単語の設置位置が変な気もする。 74559 単語は終了が判明した時点でその前の点に設置する物だったろうか? 74560 良く分からなくなってきた。配列の添字の終了点での処理について再度確認する。 74561 74562 どうやら nest-pop をする時に i を進めた後に nest-pop するか、 74563 i を進める前に nest-pop するかの違いのようだ。 74564 調べてみると、a[...]= の時以外の nest-pop に関しては全て i を増加させた後に nest-pop を指定している。 74565 nest-pop は更に tree-append を呼び出している。tree-append は [i-1] に情報を格納している。 74566 つまり、tree-append 自体 i を進めた後にしか呼び出してはいけない物になっている。 74567 この辺りの注意書きは何処にも書かれていない。 74568 74569 [tree-append/nest-pop/word-pop 呼出条件確認] 74570 74571 実際に _ble_syntax_tree 等の使用時の条件と、tree-append の内部動作を見るに、 74572 tree-append/nest-pop/word-pop の呼出条件は以下のようになる: 74573 74574 解析開始点を p1 とする。現在の位置を i とする。tree-append/nest-pop は i >= p1+1 の時にだけ呼び出して良い。 74575 74576 この注意点を _ble_syntax_tree の制限の部分に書き加える。 74577 また、tree-append/nest-pop/word-pop のそれぞれの関数の注意書き (要件) にも記す。 74578 更に tree-append 内部にチェック用のコードを導入する事にした。 74579 74580 [既存コードの check] 74581 さて似たような誤りを他の箇所でも犯していないか確認する必要がある。 74582 74583 基本的には check-word-end の中では必ず i が進んでいる筈なので tree-append を呼び出しても nest-pop を呼び出しても問題ない。 74584 一方で、実際の解析部分では tree-append もしくは nest-pop は注意して呼び出す必要がある。 74585 nest-pop に関しては類似の呼出箇所で問題がないか確認した。 74586 tree-append を確認した所 word-pop と nest-pop だけからしか呼び出されていない。 74587 word-pop に関しても調べてみたが全ての箇所で i を進めてからの呼出になっていた。 74588 74589 * ble-edit: [[ ! -o history ]] の時は履歴に登録しない。 [#D0300] 74590 74591 * ble-syntax.sh: rex_redirect を何処かに共有する。 [#D0299] 74592 74593 rex_redirect -> _ble_syntax_bash_rex_redirect. 74594 74595 * ble-syntax.sh (ble-syntax:bash): < check [#D0298] 74596 74597 * ble-syntax.sh (ble-syntax:bash): <>| や &>| はどうなっているのか? [#D0297] 74598 →試してみたが <>| や &>| は存在しない様だ。 74599 set -C の時に上書きできるのは >| だけという事になる。 74600 74601 一方で <> は set -C でも普通に実行できている様な気がする。何故だ。 74602 多分 < として開かれるという事で書き込みはできないが読み取りはできるという事なのだろう。 74603 74604 * [2015-06-28] complete: HOGE= の直後の編集でファイル名などを補完候補として出して欲しい [#D0296] 74605 74606 →これが出てこない理由は二つあった。 74607 1 一つは HOGE= 直後の状態 CTX_VRHS について check-here でのチェックを行っていなかった事。 74608 2 もう一つの理由は check-prefix で候補が存在した場合には check-here を行っていない事。 74609 HOGE= の直後にカーソルがある時、候補生成として HOGE= を用いたコマンド補完も試みられる。 74610 その為に既に check-prefix で候補生成が設定されているという事になりその場での補完が有効にならないのだ。 74611 74612 もともとこの仕組みは単語中で単語開始の補完が実行されない様にする為の物であった。 74613 例えば CTX_CMDI の場合には既にコマンドや単語の中にいるという事が分かっているので 74614 必ず check-prefix で実行しなければならないという事が分かるが、 74615 CTX_CMDX CTX_ARGX 等の場合には、その場で単語を開始するべきか一旦スペースを挟むべきか分からない。 74616 →本当か? 直後に単語を構成する文字が存在するかどうかで判定できるのではないか? 74617 a 例えば単語を構成する文字がない場合にはそので直前の単語が終了して次の単語を希望する状態であるから、 74618 そこからいきなり次の単語を挿入するというのはおかしい。直前の単語の続きとするべきである。 74619 b 一方で、直後に単語を構成する文字が存在するのであれば…そこで丁度単語が開始しているという事なので、 74620 新しい単語を其処に挿入するのは問題ないだろう。 74621 c もし直後に文字が何も存在しない場合は、そこに何か空白などを追加するべきなのか、 74622 それとも新しい単語をその箇所で初めて良いのか分からない。 74623 74624 結局の所、その箇所から新しい単語が始まるかどうかを判定するには prefix を調べて、 74625 その続きとして挿入できそうならばそうするし、そうでなければ新しい単語の開始として処理するしかない。 74626 まさに現在の構造はそうなっている。 74627 そして単語の途中で節がある場合には、そこから新しい補完候補の生成が必要になるが、 74628 現在の実装ではそういう状況は check-prefix の中で処理されている。 74629 例えば単語中に = があった場合などにその続きから候補生成が実行されている。 74630 やはりそれがどういう節なのかという事は prefix を見ているから分かるのである。 74631 74632 →check-prefix に書き加える事で VAR= の続きの候補生成を実装する事にした。 74633 丁度 VA から変数名 VAR に補完する部分があったので其処に追加・修正する形にする。 74634 74635 また同時に RDRF や RDRS の時にも候補が生成できる様にする。 74636 74637 * [2015-08-11] complete: コマンドの補完で現在のディレクトリにあるサブディレクトリも候補に入れる。 [#D0295] 74638 74639 * [2015-11-25] complete: bug 単語と単語の間で補完が効かない。 [#D0294] 74640 74641 →単語と単語の間の空白の位置で TAB を押しても補完候補が生成されなかった。 74642 これは前の単語の終端位置から次の単語が始まっていると認識されて、 74643 空白で始まるファイル名を検索していたからであった。 74644 74645 2015-12-19 74646 74647 * [2015-12-12] complete FIGNORE に対応 [#D0293] 74648 74649 * ble-syntax.sh: 現在の実装ではリダイレクトの直後に改行が来る事を許している。 [#D0292] 74650 74651 * ble-syntax.sh: リダイレクト先 ディレクトリチェック・上書きチェック [#D0291] 74652 74653 →この着色は単語の着色時に行うのが良い。それより前に着色を行ったとしても、 74654 工夫をしないと単語の着色時に上書きされてしまうからである。 74655 しかし単語の着色時にはリダイレクトに使用した演算子の情報が消失している。 74656 74657 リダイレクトに使用した演算子を取得する為には、 74658 木情報を辿るか、或いは、自分で直前部分を読み取って抽出するかである。 74659 自分で直前部分を読み取る方法は ad hoc には良いが、 74660 実際に構築された木と独立な解析なので齟齬が生じるかも知れないし、 74661 またデバグという観点からも独立な解析が二つ存在するのは好ましくない。 74662 なので、取り敢えずは木情報を辿る方針で考えてみる事にする。 74663 74664 木情報がどうなっているかは改めて ble_debug=1 等で確認する。 74665 →確認してみると親 word の wtype に "n..." という形で格納されている。 74666 現在着色は tree-enumerate-in-range を用いて行われている。 74667 子ノードから親ノードの情報を取得するのは面倒そうである。 74668 そもそも _ble_syntax_word のデータ構造からして子には親の情報が含まれていない。 74669 tree-enumerate-in-range は木を辿って列挙している訳ではないので、 74670 呼出の過程で適当に情報を記録して、という方法も使えない。 74671 74672 しかし乍ら、リダイレクトの場合にはファイル名の終端と同じ位置に 74673 親ノードが設置されている (同じ位置でリダイレクトのネストが閉じる) と期待できる。 74674 リダイレクトのファイル名とリダイレクトが同じ位置で終了するという 74675 仮定の下に実装してしまって良いのではないだろうか。 74676 74677 * ble-edit.sh (ble/widget/command-help): less は POSIX ではないが、チェックを行っていない。 [#D0290] 74678 74679 →less がない場合は more または cat を使う様に変更。 74680 74681 * [2015-12-19] ble-syntax.sh: <<< を順に入力すると文法エラーになる。 [#D0289] 74682 74683 これは見てみた所 << と入力した時点で駄目になっている。 74684 << に対応する文法要素がない (ヒアドキュメントは未実装) 為に、 74685 < + < と解釈されて解析再開点が二箇所設定されている為である。 74686 しかしながら <<< に対応する以上、 74687 << が二回来た段階では一つ目の < で解析結果を確定させては成らない。 74688 74689 << も受け付ける様にして、単語を受け取ることができる様にする。 74690 74691 * POSIX コマンドについて全て必ず用意されている物かどうか確認する。 [#D0288] 74692 POSIX の utilities に載っていたとしても optional だったり deprecated だったりするかもしれないので。 74693 →tput は UP option だった。しかし ble.sh の動作に必ず必要という訳でもないのでチェックから外す。 74694 74695 * date の使い方が POSIX じゃない。 [#D0287] 74696 74697 %N に対応しているとは限らない。 74698 -r filename に対応しているとは限らない。 74699 特に -r filename に関しては問題である。 74700 調べてみると date ではなく stat を用いた方法が紹介されている。 74701 74702 →stat を使った date に対応する。 74703 →%N に関しては対応していない場合は単に '%N' がそのまま出力されるだけなので気にしない。 74704 74705 * [2015-12-16] パラメータ展開の中で '' single quote が効かない。 [#D0286] 74706 74707 パラメータ展開の中で '' や $'', $"" 等の quote をどの様に解釈するかは 74708 そのパラメータ展開自体がどの様な環境にあるかに依存している。 74709 パラメータ展開の親が何かの情報を取得してそれを元にして動作を変更する必要がある。 74710 74711 [動作確定] 74712 74713 動作に関して: 74714 '' に関してはパラメータ展開の親が "" の中であればそのまま "''" という文字列として解釈される。 74715 パラメータ展開の親がコマンドの文脈である時は quote として扱われ、除去の対象となる。 74716 74717 extquote -s の時 (既定) は、 74718 パラメータ展開の親が "" の中にあったとしても、 74719 $'' や $"" を quote として解釈し quote 除去が行われる。 74720 74721 "" に関しては extquote に関係なく、また、 74722 パラメータ展開が "" の中にあるか外にあるかに拘わらず 74723 常に quote として取り扱われる様です。 74724 74725 何か良く分からなくなってきたので表にする。 74726 74727 "" の外 "" の中(-s extqoute) "" の中(-u extqoute) 74728 ---- -------- -------------------- -------------------- 74729 '' 有効 無効 無効 74730 "" 有効 有効 有効 74731 $'' 有効 有効 無効 74732 $"" 有効 有効 無効 (空白になる?) 74733 74734 74735 [実装方法] 74736 74737 a 先ずはパラメータ展開の文脈の際に親の文脈を取得する所から始まる。 74738 ネスト構造を辿れば現在のパラメータ展開がどの様な文脈の下にあるのかという情報を取得できる筈である。 74739 但し、毎回ネスト構造を遡るというのも効率などの観点からどうだろうという事もある。 74740 とはいいつつも、' や $' $" に当たった時にだけネスト構造を辿れば良いのだからそんなに重くもならないだろう。 74741 74742 b 或いはパラメータ展開が開始する時点で異なる文脈として扱うという方法でも良い。 74743 現在文脈は CTX_PARAM, CTX_PWORD である。動作が異なるのは CTX_PWORD の方である。 74744 パラメータ展開が開始する時点で文脈を指定しようと思ったら 74745 CTX_PARAM2, CTX_PWORD2 の二種類を用意する必要があり、管理が面倒である。 74746 74747 c もう一つの方法はパラメータ展開のネストを開始する時の、<ネストの種類の文字列> を使って区別する方法である。 74748 現在は '${' を用いているが、例えばそれに加えて '"${' を用いるなど。 74749 ネストの種類の文字列は ble-syntax/parse/nest-type -v type でいつでも取得できる。 74750 またパラメータ展開の開始は ble-syntax:bash/check-dollar の中で以下の様にして実行される。 74751 ble-syntax/parse/nest-push "$CTX_PARAM" '${' 74752 従って (1) この部分の '${' を現在いる文脈に応じて変更する様に書き換えて、 74753 (2) check-qoutes において ble-syntax/parse/nest-type を用いてこの文字列を取得して 74754 quote が有効かどうかを判定するという形になるだろう。 74755 74756 ここでは c の方法を採用する事にする。 74757 74758 * [2015-12-12] ble-syntax.sh: extquote off に対応 [#D0285] 74759 74760 整理 (過去の修正によって解決済の物) 74761 74762 * [2015-06-28] complete: <bug> HOGE=aa| の状態で TAB を押すと滅茶苦茶沢山のコマンドが表示される [#D0284] 74763 74764 * [2013-06-06] complete: 空白文字や " や ' などをエスケープしている時も正しく単語分割する [#D0283] 74765 74766 2015-12-12 74767 74768 * 起動チェック: bash の現在の設定を取得する方法に関して [#D0282] 74769 74770 起動チェック: set -o posix を確かめる方法? 74771 → POSIXLY_CORRECT=y か空欄かで判定する事ができる。 74772 → [[ -o posix ]] で OK. ただ、POSIX の時に [[ -o optname ]] が有効なのかは不明。 74773 試すと動くから POSIX でも bash 固有の機能は相変わらず使えるのだろう。 74774 74775 a 既存の物については速度測定をして速い方法に移行する。 74776 74777 [[ $- == *H* ]] は [[ -o histexpand ]] の方が早いようだ。しかも分かり易い。 74778 74779 % shopt -q は $BASHOPTS を用いた物の方が早い方である。 74780 % しかし読みにくいのは問題だ。$BASHOPTS を使用して判定する為の関数を定義してしまっても良い気がする。 74781 shopt は >/dev/null にリダイレクトする必要はない。リダイレクトしなければ速い。 74782 74783 b set -o に関しては? 74784 74785 % set -o posix -> [[ $POSIXLY_CORRECT ]] 74786 % Note: set -o posix の時は POSIXLY_CORRECT=y になっている。 74787 % set +o posix の時は POSIXLY_CORRECT は unset になっている。 74788 % 74789 % set -o ignoreeof -> [[ $IGNOREEOF == 10 ]] 74790 % これは実行すると実際に IGNOREEOF=10 が設定されるので問題ない。 74791 % 74792 % set -o pipefail -> false | : 74793 % これは false | : で判断できるが fork が入るので遅いかも。 74794 % 74795 % set -o emacs 74796 % set -o vi 74797 % bash --noediting 74798 % EMACS=t bash 74799 % → EMACS=t に関しては環境変数を介して判定できるが、 74800 % それ以外の方法による行編集機能の有効・無効・デフォルトキーマップは判断不能? 74801 % 74802 % 74803 % 候補 bind 74804 % 一応行編集機能が有効になっているかどうかは bind がエラーメッセージを出すかどうかで判断できる? 74805 % しかし bind の返却値は常に 0 の様だ (エラーメッセージを出力するだけ)。 74806 % 74807 % 候補 set +o emacs && set -o emacs 74808 % 候補 set +o vi && set -o vi 74809 % これら (set +o emacs, vi) は訳に立たない。 74810 % 既にその設定になっているかどうかに拘わらず常に成功する様だ。 74811 % 74812 % set -o history 74813 % これの判定方法は全く不明だ。 74814 % 74815 % 候補 history 74816 % 常に成功する。動作も変わらない様だ。 74817 74818 と思ったら set に関しては全て [[ -o option-name ]] で判定できるのであった。 74819 74820 起動オプション → [[ -o name ]] または [[ $- == *X* ]] 74821 set → [[ -o option-name ]] 74822 shopt → shopt -q optname 74823 74824 * LANG だけでいいのか? LC_ALL は? [#D0281] 74825 74826 LANG=... を使っているのは read -t 0 のチェック部分と、 74827 初期化の command awk の呼出の部分だけである。 74828 74829 結局以下の bash-4.0 未満のコードは使われていない上に、 74830 仮に動いてしまったとしても問題点もある(?)ので削除する事にする。 74831 何れにしても bash-4.0 未満ではこの方法では、 74832 入力が溜まっている事を検知することはできないので削除するのが良い。 74833 74834 | # x 以下は bind '"\e[":"\xC0\x9B["' による 74835 | # byte の受信順序が乱れるので使えない。 74836 | # x bash-4.0 未満では結局以下では何も起こらない。 74837 | # read -t 0 としても必ず失敗する様である。 74838 | local byte=0 74839 | while IFS= LC_ALL=C read -t 0 -s -r -d '' -n 1 byte; do 74840 | LC_ALL=C ble-text.s2c -v byte "$byte" 0 74841 | "ble-decode-byte+$bleopt_input_encoding" "$byte" 74842 | done 74843 74844 [過去の ToDo の整理] 74845 74846 * ble-bind の説明を追加 [#D0280] 74847 74848 * cat 置き換え [#D0279] 74849 74850 * [2015-11-06] isearch-forward/backward で現在の一致範囲をハイライトする。 [#D0278] 74851 74852 * [2015-03-06] complete の古いコード [#D0277] 74853 74854 →これは誰からも使われていない古い関数達を削除した。please, see commit log. 74855 74856 * [2015-03-06] binder-source 周辺 [#D0276] 74857 74858 * [2015-02-27] complete: 既存の bash complete に対応する。 [#D0275] 74859 74860 * [2015-02-25] isearch-forward/backward の動作 [#D0274] 74861 74862 気付いたのだが bash では isearch-forward/backward は各ヒストリ項目に対して一致しているのではなく、 74863 ヒストリ項目の中にある文字列に対して一致している様だ。 74864 つまり、複数の一致が一つのコマンドラインの中にあれば、 74865 その中を C-r C-s で移動していく事になる。 74866 そればかりか現在編集している文字列の中で一致する物についてもちゃんと移動できる。。 74867 74868 * [2013-06-06] complete: complete -F に対する対応 [#D0273] 74869 74870 * [2013-06-06] complete: コマンド先頭位置の検出 (複合文の途中からコマンドが始まっている場合など) [#D0272] 74871 74872 * [2013-06-05] ^U ^V ^W ^? bind 関連 [#D0271] 74873 + 説明書にその事を書いておく。 74874 + ^U ^V ^W ^? を bind するより良い方法があれば考える 74875 + bashrc の中でも同様に問題が起こるのか? 74876 74877 + 一旦 bind '"":"hogehoge"' 等として変換したら受信できる可能性? 74878 74879 2015-12-12 →これは現在何も問題が起こっていない気がするので完了済と解釈する。 74880 74881 * [2013-06-04] vbell .time の置き場所を変更? [#D0270] 74882 74883 2015-12-12 →一時ファイルは現在は $_ble_base_tmp を介して統一的に取り扱う事になっている。 74884 もし置き場所を整理するとすれば $_ble_base_tmp 自体を変更する事になるが、 74885 現在の実装で満足しているので、現在の所変更の予定はない。 74886 74887 * [2013-06-01 以前] 編集文字列の表示 [#D0269] 74888 + スタイル指定文字列 74889 + color fall backs 74890 + forward-char 74891 + goto-char 74892 + insert-string 74893 + insert-char 74894 74895 2015-12-12 → これらの ToDo 項目が元々何を意図していたのか良く分からないが、 74896 スタイル指定文字列は gspec として実装してあるし、 74897 編集関数 goto-char, forward-char, insert-string, insert-char は実装済である。 74898 編集関数と編集文字列の「表示」にどの様な関係があるのかは不明。 74899 74900 2015-12-05 74901 74902 * ble-bind -L, ble-bind --list-edit-functions [#D0268] 74903 declare -f | sed -n -r 's/^ble-edit\+([[:alpha:]][^[:space:]();&|]+) \(\)[[:space:]]*$/\1/p' 74904 74905 * v0.1-master: release=1 で更新、release 登録する [#D0267] 74906 74907 * download/git clone 順序入れ替え [#D0266] 74908 74909 * 日本語 README.md [#D0265] 74910 74911 2015-12-03 74912 74913 * また遅くなってきたので初期化の速度について再確認する? [#D0264] 74914 74915 時間 行数 最適化後 以前の記録 74916 ble-core.sh 0m0.023s 605 0m0.013s 0.002s 74917 ble-decode.sh 0m0.010s 1632 0m0.010s 0.008s 74918 ble-color.sh 0m0.006s 1034 0m0.002s 0.003s 74919 ble-edit.sh 0m0.009s 4204 0m0.009s 0.007s 74920 ble-syntax.sh 0m0.031s 2944 0m0.006s 0.019s 74921 ble-initialize 0m0.015s 0m0.014s 74922 合計 0m0.094s 0m0.054s 74923 74924 ble.sh parse 0m0.105s 74925 ble-attach 0m0.088s 74926 74927 行数から考えるに ble-syntax.sh は ble-edit.sh に較べて load に時間が掛かりすぎる。 74928 ble-core.sh についても意外に時間が掛かっている。 74929 74930 ble-core.sh については _ble_base_tmp.wipe を弄ると 3ms になるので、 74931 悪いのは各ファイルについてプロセス生死判定を行っている事にある。 74932 → kill -0 を消しても 25ms のままだった。 74933 より詳細に _ble_base_tmp.wipe の中を調べる。 74934 74935 - ファイル列挙 = 4ms (7ms) 74936 - ファイル名存在確認 = 0ms (7ms) 74937 - ファイル名形式検査 = 15ms (22ms) 74938 - プロセス生死判定 = 3ms (25ms) 74939 74940 どうも正規表現の判定に結構時間が掛かっている様子だった。 74941 正規表現はそんなに重くないのだと思っていたがやはり重いのか。 74942 (最初のコンパイルに時間が掛かるが、それ以降は内部で再利用される?) 74943 何れにしても正規表現を止めてパラメータ展開を用いて pid を抽出する様に変更したら 74944 全体で 23ms かかっていたのが 12ms 程度まで減少した。 74945 ble-core.sh の他の箇所は 3ms 程度しか掛かっていないので気にしても仕方がない。 74946 74947 ble-syntax.sh についても見る事にする。 74948 殆ど関数定義と変数・配列への代入しかないのにと思ってみると 74949 関数 _ble_syntax_attr2iface.define, ble-color-defface を大量に呼び出している箇所がある。 74950 この部分を削除してみると 5ms にまで縮まる。 74951 特に ble-color-defface で 25ms 程度使っている様で、 74952 _ble_syntax_attr2iface.define に関しては 2ms しか使っていない様子である。 74953 74954 どのタイミングで色が必要とされるかに依るかも知れないが、 74955 例えば色の初期化について遅延を行うとどうだろうか。 74956 調べてみると幸いに _ble_faces 系統の変数を直接操作しているはごくごく一部である。 74957 →遅延初期化にしてみた…が、結局最後にプロンプトを表示する時に初期化が必要?? 74958 →調べてみた所 ble-highlight-layer:syntax/update-error-table において 74959 中身がなくても g (syntax_error) の初期化を行っていた。これを省略すれば良い。 74960 74961 と思ったら一番時間が掛かっているのは ble-attach だった。 74962 しかしながら ble とは関係ない部分でもっと時間が掛かっている様にも見える。 74963 .bashrc の方を調べた。全体で 0.513 かかっている。内訳は: 74964 - ble.sh 160ms 74965 - ble-attach 88ms 74966 - .mwg/bashrc 95ms 74967 - /etc/bashrc 155ms 74968 - 残り 15ms 74969 74970 あれ。変だ。ble.sh が結局 160+88 = 248ms も使っている。 74971 ble.sh 自身の計測だと 54+88ms しか使わないはずなのに。 74972 →どうやら parse に時間が掛かっている様だ。 74973 bash は先にファイル全体を parse して、その後で実行をしているのではないか。 74974 短いファイルの場合は 100ms も待たされないのでファイルを開くだけでそんなに時間が掛かるとは考えがたい。 74975 また、ble.sh の先頭で非自明な return を実行する場合でも 100ms 待たされるので、 74976 実際に実行しようが実行しまいがファイルの長さに依存した解析を実行するという事になる。 74977 (return の位置で 100ms 待たされなかったりする。 74978 もしかすると {} で囲まれた単位で parse を実行しているという事だろうか。 74979 そうだとするとスクリプト実行中にファイルを書き換えた時に変な事になるのも合点が行く。) 74980 そう考えると ({} が登場する毎に散発的に為される) parse に合計で 105ms かかっている。 74981 つまり 100 行あたり 1ms つかっている計算になる。 74982 74983 うーん。これは仕様がない。 74984 遅延ロードするばかりでなく遅延部分を外部に分離すれば parse 時間も短くなるかもしれないが、 74985 そもそも遅延部分でそんなに行数を食っている物は少ない。 74986 あるとすれば ble-edit の編集関数を遅延ロードにするぐらいだろうか。 74987 と思ったが ble-edit のプロンプト構築や座標計算部分は省略できないし、 74988 やはり頑張ってもそんなに初期化時間を稼ぐ事は出来ない気がする。 74989 調べてみるとやはり編集関数は2000行程度である。その他の部分は基本的な部分である。 74990 これでは 20ms 程度しか稼げない。 74991 74992 後、コメントが 2000 行程度あった。しかしコメント 2000 行程度にそんなに解析時間が掛かるとも思えない。 74993 →と思って計測したら 25ms もかかる。そもそもコメントには日本語も多くデータ量が元から多い。その事が原因か? 74994 しかしながら 25ms でも全体 250ms の 10% に過ぎない。そんなに体感は変わらないだろう。 74995 74996 まあ、取り敢えずこれはこれで良しとする。 74997 74998 * ble-syntax/parse/nest-equals bug [#D0263] 74999 75000 + bug (2015-12-03) まただ 75001 75002 C-d で以下の様に書き換えを行おうとしたらなる。 75003 $ function () () { echo hello; } 75004 $ function () { echo hello; } 75005 75006 stackdump: invalid nest 75007 @ /home/murase/prog/ble/ble.sh:1480 (ble-syntax/parse/nest-equals) 75008 @ /home/murase/prog/ble/ble.sh:-16 (ble-syntax/parse) 75009 @ /home/murase/prog/ble/ble.sh:4 (_ble_edit_str.update-syntax) 75010 @ /home/murase/prog/ble/ble.sh:2583 (ble-highlight-layer:syntax/update) 75011 @ /home/murase/prog/ble/ble.sh:4292 (ble-highlight-layer/update) 75012 @ /home/murase/prog/ble/ble.sh:4844 (.ble-line-text/update) 75013 @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 75014 @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 75015 @ /home/murase/prog/ble/ble.sh:1140 (.ble-decode-byte:bind/tail) 75016 @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 75017 75018 これは今丁度直した所の直し方が甘かった所為で余計に変な事になっていただけだった。 75019 すぐに直した。そんなに問題はない。 75020 75021 * 構文解析部分更新の bug [#D0262] 75022 75023 + bug (2015-12-02) 75024 75025 また出た。今度は 75026 75027 $ echo a "$(echo b "$(echo c "$(echo d "$(echo e "$(echo f)")")")")" 75028 75029 を 75030 75031 $ echo "a $(echo "b $(echo c "$(echo d "$(echo e "$(echo f)")")")")" 75032 75033 に書き換える過程で起きた。これは 11-28 のケースと状況が似ている。 75034 75035 75036 + bug (2015-11-28b) 75037 75038 ble-assert 75039 75040 "$f" --date="$(date +'%F %T %Z' -r "$f")" 75041 "${f}" --date="$(date +'%F %T %Z' -r "$f")" 75042 75043 の過程でエラー。最小化: 75044 75045 echo "$f" "$(B 'D' "$f")" 75046 echo "${f" "$(B 'D' "$f")" <- この時点でエラーになっている。(ble_debug= だと次の入力で明らかになるが。) 75047 echo "${f}" "$(B 'D' "$f")" 75048 75049 先ず第一に ble_debug=1 が設定されているかされていないかでエラーが表示されるタイミングが異なる。 75050 しかしこれは単にチェックのタイミングの問題である事は以前のバグ取りの時に分かっている。 75051 ble_debug=1 が設定されていると現在の状態を表示する為に、その場で構文木の構造を辿る。 75052 その際にエラーが存在している事が即座に検知されるという訳である。 75053 一方で ble_debug= になっている場合にはその場で構文木を辿らないので後になってエラーが発生している事が分かる。 75054 従って ble_debug=1 の時のエラーを先ず見るのが自然である。 75055 75056 エラーメッセージ 75057 75058 | ble-syntax/tree-enumerate/.impl(i=10,iN=26,nofs=0,node=,command=ble-syntax/print-status/.dump-tree/proc1)/FATAL1 75059 | @ /home/murase/prog/ble/ble.sh:7685 (ble-assert) 75060 | @ /home/murase/prog/ble/ble.sh:108 (ble-syntax/tree-enumerate/.impl) 75061 | @ /home/murase/prog/ble/ble.sh:5 (ble-syntax/tree-enumerate) 75062 | @ /home/murase/prog/ble/ble.sh:8034 (ble-syntax/print-status/.dump-tree) 75063 | @ /home/murase/prog/ble/ble.sh:8264 (ble-syntax/print-status) 75064 | @ /home/murase/prog/ble/ble.sh:-135 (ble-highlight-layer:syntax/update) 75065 | @ /home/murase/prog/ble/ble.sh:4290 (ble-highlight-layer/update) 75066 | @ /home/murase/prog/ble/ble.sh:4842 (.ble-line-text/update) 75067 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update)=(5 w=- n=@5 t=-1:-1) 75068 | @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 75069 | @ /home/murase/prog/ble/ble.sh:1130 (.ble-decode-byte:bind/tail)t=1:-1) 75070 | @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind)t=(5 w=- n=@10 t=-1:-1) 75071 75072 +-------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------+ 75073 | エラー状態 | 正常状態 | 75074 +-------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------+ 75075 | A? | A? | 75076 | 2 aw 000 'e' | stat=(1 w=- n=- t=-1:-1) | 2 aw 000 'e' | stat=(1 w=- n=- t=-1:-1) | 75077 | | aw 001 'c' | | | aw 001 'c' | | 75078 | | aw 002 'h' | | | aw 002 'h' | | 75079 | | aw 003 'o' + word=2:0-4 | | aw 003 'o' + word=2:0-4 | 75080 | 3 a 004 ' ' | 3 a 004 ' ' | 75081 | 9 a 005 '"' nest=(4 w=4:5- n=- t=-1:1) stat=(3 w=- n=- t=1:-1) | 9 a e 005 '"' nest=(4 w=4:5- n=- t=-1:1) stat=(3 w=- n=- t=1:-1) | 75082 | 14*a 006 '$' nest=(5 w=- n='${':5- t=-1:-1) stat=(5 w=- n=@5 t=-1:-1) | 14 a e 006 '$' nest=(5 w=- n='${':5- t=-1:-1) stat=(5 w=- n=@5 t=-1:-1) | 75083 | |*a 007 '{' | | a e 007 '{' | 75084 | 7*a 008 'f' | 7 a 008 'f' | 75085 | 9*a 009 '"' stat=(14 w=- n=@6 t=-1:-1) | 9 a 009 '"' stat=(14 w=- n=@6 t=-1:-1) | 75086 | 5*a s 010 ' ' | 5 a 010 ' ' | 75087 | 9*a s 011 '"' || | 9 a 011 '"' | 75088 | 14*a 012 '$' ||| nest=(15 w=- n='$(':6- t=-1:-1) stat=(15 w=- n=@6 t=-1:-1) | 14 a 012 '$' | nest=(15 w=- n='$(':6- t=-1:-1) stat=(15 w=- n=@6 t=-1:-1) | 75089 | |*a 013 '(' ||| | | a 013 '(' | | 75090 | 2*aw 014 'B' |||+ word=2:14-15 stat=(1 w=- n=@12 t=-1:-1) | 2 aw 014 'B' |+ word=2:14-15 stat=(1 w=- n=@12 t=-1:-1) | 75091 | 3*a 015 ' ' ||| | 3 a 015 ' ' | | 75092 | 9*a 016 ''' |||| stat=(3 w=- n=@12 t=1:-1) | 9 a 016 ''' || stat=(3 w=- n=@12 t=1:-1) | 75093 | 5*a 017 'D' |||| | 5 a 017 'D' || | 75094 | 9*a 018 ''' |||+ word=4:@14>16-19 | 9 a 018 ''' |+ word=4:@14>16-19 | 75095 | 3*a 019 ' ' ||| stat=(3 w=- n=@12 t=0:-1) | 3 a 019 ' ' | stat=(3 w=- n=@12 t=0:-1) | 75096 | 9*a 020 '"' ||||| nest=(4 w=4:20- n='none':12- t=-1:1) stat=(3 w=- n=@12 t=1:-1) | 9 a 020 '"' ||| nest=(4 w=4:20- n='none':12- t=-1:1) stat=(3 w=- n=@12 t=1:-1) | 75097 | 14 a 021 '$' ||||| stat=(5 w=- n=@20 t=-1:-1) | 14 a 021 '$' ||| stat=(5 w=- n=@20 t=-1:-1) | 75098 | 7 a 022 'f' ||||| | 7 a 022 'f' ||| | 75099 | 9 a 023 '"' |||++ word=4:@18>20-24>@23 word=nnone:20-24 stat=(5 w=- n=@20 t=-1:-1) | 9 a 023 '"' |++ word=4:@18>20-24>@23 word=nnone:20-24 stat=(5 w=- n=@20 t=-1:-1) | 75100 | 14 a 024 ')' ||+ word=n$(:12-25>@23 stat=(3 w=- n=@12 t=0:-1) | 14 a 024 ')' + word=n$(:12-25>@23 stat=(3 w=- n=@12 t=0:-1) | 75101 | 9 a 025 '"' ++ word=4:@9>11-26>@25 word=nnone:11-26>@24 stat=(5 w=- n=@11 t=0:-1) | 6 a e 025 '"' nest=(15 w=- n='none':6- t=0:-1) stat=(15 w=- n=@6 t=0:-1) | 75102 | \_ '"$(B 'D' "$f")"' | \_ 'echo' | 75103 | \_ '"$(B 'D' "$f")"' | \_ '"${f" "$(B 'D' "$f")"' | 75104 | \_ '$(B 'D' "$f")' | \_ '"${f" "$(B 'D' "$f")"' | 75105 | \_ 'B' | \_ '${f" "$(B 'D' "$f")"' | 75106 | \_ ''D'' | \_ '$(B 'D' "$f")' | 75107 | \_ '"$f"' | | \_ 'B' | 75108 | \_ '"$f"' | | \_ ''D'' | 75109 | | | \_ '"$f"' | 75110 | | | \_ '"$f"' | 75111 | | \_ '"' | 75112 +-------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------+ 75113 75114 状態の差分 75115 75116 | --- a.txt 2015-12-03 05:12:49.627927314 +0900 75117 | +++ b.txt 2015-12-03 05:12:55.499708773 +0900 75118 | @@ -1,4 +1,4 @@ 75119 | -正常状態 75120 | +エラー状態 75121 | 000 'e' stat=(1 w=- n=- t=-1:-1) 75122 | 001 'c' 75123 | 002 'h' 75124 | @@ -24,4 +24,4 @@ 75125 | 022 'f' 75126 | 023 '"' word=4:@18>20-24>@23 word=nnone:20-24 stat=(5 w=- n=@20 t=-1:-1) 75127 | 024 ')' word=n$(:12-25>@23 stat=(3 w=- n=@12 t=0:-1) 75128 | -025 '"' nest=(15 w=- n='none':6- t=0:-1) stat=(15 w=- n=@6 t=0:-1) 75129 | +025 '"' word=4:@9>11-26>@25 word=nnone:11-26>@24 stat=(5 w=- n=@11 t=0:-1) 75130 75131 これを見ると最後の状態が異なるだけの様である。 75132 解析中断点は 020 にあるが 020 までの状態は完全に同じである。 75133 %%という事は解析の状態は完全に一致している筈なのでその後の解析も同じでなければならない?%% 75134 と思ったが、解析状態の際に比較するのは (現在の状態 vs 正しいと想定される状態) ではなくて、 75135 (現在の状態 vs 前回までに解析した状態) であるのでここでは関係ないはずである。 75136 この結果から言える事は、 75137 75138 a shift に失敗している 75139 b 解析の中断の判定に失敗している 75140 c または解析途中状態が同じで以降の文字列が同じだったとしても最終的な解析結果に違いが出る可能性がある 75141 75142 のどちらかという事になる。今迄の経験から行くと初めに a, b を疑った方が良い。 75143 その為に前回までの解析状態を確認しておく必要がある。 75144 75145 +-------------------------------------------------------------------------------------------+ 75146 | 直前の状態 | 75147 +-------------------------------------------------------------------------------------------+ 75148 | A? | 75149 | 2*aw 000 'e' | stat=(1 w=- n=- t=-1:-1) | 75150 | |*aw 001 'c' | | 75151 | |*aw 002 'h' | | 75152 | |*aw 003 'o' + word=2:0-4 | 75153 | 3*a 004 ' ' | 75154 | 9*a 005 '"' || nest=(4 w=4:5- n=- t=-1:1) stat=(3 w=- n=- t=1:-1) | 75155 | 14*a 006 '$' || stat=(5 w=- n=@5 t=-1:-1) | 75156 | 7*a 007 'f' || | 75157 | 9*a 008 '"' ++ word=4:@3>5-9>@8 word=nnone:5-9 stat=(5 w=- n=@5 t=-1:-1) | 75158 | 3*a 009 ' ' stat=(3 w=- n=- t=0:-1) | 75159 | 9*a 010 '"' || nest=(4 w=4:10- n=- t=-1:1) stat=(3 w=- n=- t=1:-1) | 75160 | 14*a 011 '$' ||| nest=(5 w=- n='$(':10- t=-1:-1) stat=(5 w=- n=@10 t=-1:-1) | 75161 | |*a 012 '(' ||| | 75162 | 2*aw 013 'B' |||+ word=2:13-14 stat=(1 w=- n=@11 t=-1:-1) | 75163 | 3*a 014 ' ' ||| | 75164 | 9*a 015 ''' |||| stat=(3 w=- n=@11 t=1:-1) | 75165 | 5*a 016 'D' |||| | 75166 | 9*a 017 ''' |||+ word=4:@13>15-18 | 75167 | 3*a 018 ' ' ||| stat=(3 w=- n=@11 t=0:-1) | 75168 | 9*a 019 '"' ||||| nest=(4 w=4:19- n='none':11- t=-1:1) stat=(3 w=- n=@11 t=1:-1) | 75169 | 14*a 020 '$' ||||| stat=(5 w=- n=@19 t=-1:-1) | 75170 | 7*a 021 'f' ||||| | 75171 | 9*a 022 '"' |||++ word=4:@17>19-23>@22 word=nnone:19-23 stat=(5 w=- n=@19 t=-1:-1) | 75172 | 14*a 023 ')' ||+ word=n$(:11-24>@22 stat=(3 w=- n=@11 t=0:-1) | 75173 | 9*a 024 '"' ++ word=4:@8>10-25>@24 word=nnone:10-25>@23 stat=(5 w=- n=@10 t=0:-1) | 75174 | \_ 'echo' | 75175 | \_ '"$f"' | 75176 | | \_ '"$f"' | 75177 | \_ '"$(B 'D' "$f")"' | 75178 | \_ '"$(B 'D' "$f")"' | 75179 | \_ '$(B 'D' "$f")' | 75180 | \_ 'B' | 75181 | \_ ''D'' | 75182 | \_ '"$f"' | 75183 | \_ '"$f"' | 75184 +-------------------------------------------------------------------------------------------+ 75185 75186 やはりどうも腑に落ちない。shift に失敗しているのだとしても文法的な入れ子構造が全く違うのだから、 75187 解析の中断が起こるはずがないのである。という事は、少なくとも解析の中断の判定部分に問題があるのであり、 75188 先にそちらを解決する方が先になるであろう。という訳で例によって ble-syntax/parse/nest-equals を確認する。 75189 以下が最後の ble-syntax/parse/nest-equals 呼出時の動作の流れである。 75190 75191 | ble-syntax/parse/nest-equals 75192 | declare -- parent_inest="20" i1="6" i2="8" 75193 | A0 75194 | declare -- _onest="4 0 4 8 -1 1 none" _nnest="4 0 4 8 -1 1 none" 75195 | A1 75196 | A2 75197 | A3 75198 | declare -- parent_inest="8" i1="6" i2="8" 75199 | A0 75200 | declare -- _onest="" _nnest="" 75201 | A1 75202 | A2 75203 | A3 75204 | declare -- parent_inest="" i1="6" i2="8" 75205 | A0 75206 75207 おかしい、途中で _onest _nnest が空白になっている。そんな事があるだろうか。 75208 直前の状態ではエラーが生じていなかったはずなので直前の状態で nest を辿って空白になるという事は考えにくい。 75209 それなのに _onest についてすら空白になっている。_onest を格納している配列の中身の構築に失敗している? 75210 75211 と思ったが…あれ parent_inest=8 とはどういう事だろう。8 には勿論何もない。 75212 parent_inest の更新部分を見てみると onest[3] の中身を直接読み取っている。 75213 確かにこれでは動作しない onest[3] の中に入っているのは現在位置からみた時の parent_inest の相対位置なので、 75214 直接代入するのではなくて現在の位置からのずれとして計算しなければならない。 75215 つまり、正しくは parent_inest=$((parent_inest-onest[3]))=20-8 として計算するべきなのだ。 75216 しかしそうだとしても変である。20-8 = 12 にはやはり何も nest は設置されていないからである。 75217 →と思ってよく見てみたら設置されている。なので相対位置で計算する様に修正した。 75218 →修正した。エラーは出なくなった。OK 75219 2015-12-02 のエラーも出なくなった。OK。 75220 75221 しかしこれは 2015-11-28 のエラーとは関係ないようである。取り敢えず一旦整理する。 75222 75223 * alias 対策 [#D0261] 75224 75225 * fgrep に依存している [#D0260] 75226 75227 * bash-3 で C-d を捕獲する為のメッセージについて [#D0259] 75228 75229 これは各言語・各 version で異なるので統一的に取り扱える様にしたい。 75230 75231 これらのメッセージは 75232 75233 [u@h bash-4.3/po]$ sed -nr '/msgid "Use \\"%s\\" to leave the shell\.\\n"/{n;p;}' *.po 75234 75235 とすれば各言語版でどの様なメッセージが使用されているか調べられる。更に、 75236 75237 % [u@h bash-4.3/po]$ sed -nr '/msgid "Use \\"%s\\" to leave the shell\.\\n"/{n;s/^msgstr/printf/;s/$/ exit/;p;}' *.po | bash 75238 % 75239 % とすれば具体的なメッセージを出力する事ができる。 75240 % と思ったがエスケープしなければならない文字が shell と po では違うので駄目だ。 75241 % 例えば "" 中の ` をエスケープしないとシェルではコマンド置換と勘違いされる。 75242 % なのでもう少し慎重になる必要がある。 75243 75244 % [u@h bash-4.3/po]$ sed -nr '/msgid "Use \\"%s\\" to leave the shell\.\\n"/{n;s/^msgstr/printf/;s/$/ exit/;p;}' *.po | bash 75245 75246 この結果を何処かにファイルに放り込んでおいて readarray なり何なりで読み込むようにすれば良いのでは? 75247 75248 → generate.sh に生成用のスクリプトを書いて、生成結果を ignoreeof-messages.txt に出力することにした。 75249 C-d の検出時にはこの ignoreeof-messages.txt を使用する事にした。 75250 75251 2015-12-01 75252 75253 * bugfix: 引数に対する補完で complete -D が登録されていない場合に何も起こらなかった。 [#D0258] 75254 75255 以下のバグはこれに関連する物である: 75256 75257 > * bug: tab 補完が効かない @ laguerre 75258 > * bug cygwin 環境で補完が効かない 75259 75260 * bug: isearch/forward incremental にできない。 [#D0257] 75261 75262 2015-11-30 75263 75264 * release の登録 on GitHub [#D0256] 75265 75266 2015-11-29 75267 75268 * input_encoding=C full support as 'UTF-8' [#D0255] 75269 75270 * bug [#D0254] 75271 75272 選択している状態で history を移動すると座標がずれる。 75273 特に長いコマンドの一部を選択している時にずれる。 75274 ずれの量は選択範囲の長さや位置に依存しない。 75275 75276 どうやら ble-syntax-layer:region が悪い様だ。 75277 _ble_highlight_layer__list から region を外したら直った。 75278 75279 * ライセンスファイルの追加 [#D0253] 75280 75281 * ble-bind -xf [#D0252] 75282 ble-bind -x 未実装状態になっている 75283 →これは単純に ble-edit+... を実装してそれを ble-bind -c で登録すれば良いだけなのでは? 75284 75285 2015-11-25 75286 75287 * 公開までに特に必要な物 [2015-03-01] [#D0251] 75288 75289 > 1 背景が暗い環境での色の設定 75290 > これは確認してみたがそんなに問題にならないのではないかという気がした。 75291 > 何れにしても自由に配色を設定できるようにする仕組みは提供する必要がある。 75292 > →解説を加えれば良い。 75293 > 2 complete の設定の取り込み 75294 3 bind 等の設定の取り込み 75295 readline 関数の完全対応 75296 bind -x は対応しなくて良い 75297 inputrc は対応しない。簡単に翻訳できるから。 75298 > 4 正しい PS1 の解釈 75299 75300 取り敢えず大体の所は終わった。 75301 readline 関数の完全対応には時間が掛かると思われるので、一旦保留として別項目にする。 75302 75303 2015-11-23 75304 75305 * magic-space [#D0250] 75306 75307 特定の文字列がある時にカーソルが末端に移動する。 75308 75309 * プログラム補完: ディレクトリ名の直後の "/" 挿入 [#D0249] 75310 75311 プログラム補完でディレクトリ名を列挙されると、 75312 それがディレクトリ名であるにも関わらず直後に " " が挿入されて中のファイルを列挙できなくなる。 75313 仕方がないのでプログラム補完で生成される候補については action/file で登録する事にする。 75314 つまり、ディレクトリ名に一致すれば "/" を末尾に挿入するしそれ以外ならば " " を挿入する。 75315 75316 * complete/compopt -o の対応 [#D0248] 75317 75318 + compopt -o nospace 等の情報を取り出す事ができない? 75319 これは complete -p の解析時に先ず抽出し、 75320 更に、プログラム補完時に compopt 関数を上書きすればよい。 75321 →実装した。動いている様に見える。 75322 75323 + compopt -o filenames/dirnames/default/bashdefault 75324 現状だとこれらは全く使われない様だ。 75325 これは compgen に失敗した時にどの様に動作するかを指定する物であって、 75326 compgen 自体の動作には影響を与えない様である。 75327 75328 + compopt -o plusdirs については compgen の方で処理してくれる様なので気にする必要はない。 75329 75330 * bug: ble-detach による stty 破壊 [#D0247] 75331 75332 ble-detach した後に rm file RET yes RET とすると反応がなくなる。 75333 改行が正しく伝わっていない? stty で調べてみる。 75334 75335 ble$ bash-4.0 --norc 75336 ble$ stty -a 75337 speed 38400 baud; rows 73; columns 210; line = 0; 75338 intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; 75339 -parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts 75340 -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 75341 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 75342 isig -icanon iexten echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke 75343 75344 ble$ stty -a 75345 speed 38400 baud; rows 73; columns 210; line = 0; 75346 intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; 75347 -parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts 75348 -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 75349 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 75350 isig -icanon iexten echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke 75351 75352 ble$ ble-detach 75353 ble$ stty -a 75354 speed 38400 baud; rows 73; columns 210; line = 0; 75355 intr = <undef>; quit = <undef>; erase = <undef>; kill = <undef>; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = <undef>; start = ^Q; stop = ^S; susp = <undef>; rprnt = ^R; werase = <undef>; lnext = <undef>; 75356 flush = ^O; min = 1; time = 0; 75357 -parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts 75358 -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8 75359 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 75360 isig -icanon iexten echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke 75361 75362 どうも色々な設定が消滅している様子である。 75363 状態の復元は ble-decode-detach -> .ble-stty.finalize -> stty で実行している筈である。 75364 やはり bind -x の中で実行した stty の反映には制限が伴うという事か。 75365 一応最後に stty sane を実行すれば直る。 75366 75367 取り敢えずの暫定処置として stty sane を ble-detach 後にユーザに実行して貰う事にする。 75368 75369 * complete -p による補完を動作する様に修正。 [#D0246] 75370 75371 下らないバグだった。extract-command 内で、出力変数の筈の 75372 comp_words comp_line comp_point comp_cword に対して local を指定したままだった。 75373 (実装中にテスト用として local 宣言していたのが残っていた。) 75374 75375 * complete -F 対応 [#D0245] 75376 75377 if complete -p コマンド名 &>/dev/null; then 75378 IFS=$'\n' 75379 local arr=$( 75380 1 ble-getopt $(complete -p コマンド名) で解析 75381 2 -F, -C オプションに指定されたコマンドを ble の用意した物に置き換え 75382 ble の関数で COMP_ 変数を用意し、 75383 その後で -F -C オプションに指定されていたコマンドを呼び出す。 75384 呼出方などは -F -C の仕様に準じる。 75385 3 compgen 解析したオプション -- "$COMPV" を呼び出し候補を列挙する 75386 ) 75387 fi 75388 75389 既存のシェル関数による補完候補生成 (complete -F) の仕様について確認する。 75390 75391 | complete -F による補完を実行する際にどの様な変数を設定する事になっていたか、 75392 | どの様にして補完単語及び補完単語を指定する事になっていたかについても確認する必要がある。 75393 | それらの仕様によってどの様にコマンドラインの情報を構築するかが変わってくるからである。 75394 | 75395 | 基本的に complete -F 呼出元では COMP_ シェル変数を設定すれば良いと考えられる。 75396 | COMP_* シェル変数には以下のような物がある。 75397 | - COMP_LINE コマンドライン全体 75398 | - COMP_POINT コマンドライン全体の内の位置 75399 | - COMP_WORDS コマンドラインを構成する単語たち 75400 | - COMP_CWORD COMP_WORDS 内のどの単語に現在カーソルがあるか 75401 | - COMP_KEY 75402 | - COMP_TYPE 75403 | - COMP_WORDBREAKS ← これはユーザ側が comp の動作を制御する為に使用する変数であって、comp 側で設定する変数ではない。 75404 | 75405 | 疑問: 補完関数はどの様にして COMP_WORDS[COMP_CWORD] 内におけるカーソルの位置を知るのか? 75406 | a 例えばカーソル位置で必ず単語が切断されるのか、 75407 | b 或いは、COMP_WORDS[COMP_CWORD] にはカーソルよりも前の部分しか格納されないのか、 75408 | c COMP_WORDS 自体がカーソルよりも前の部分だけしか含まないのか、 75409 | d それともカーソル位置を知る方法はないのか。 75410 | 75411 | →d の様である。COMP_WORDS COMP_CWORD は素直に生成される。 75412 | 従って単語の途中で TAB を押している可能性もあるので、 75413 | シェル関数側では「COMP_WORDS[COMP_CWORD] から始まる単語だけを生成する」 75414 | という訳には行かないようである。ちゃんと COMP_LINE, COMP_POINT を用いて、 75415 | 現在のカーソルの位置が何処にあるのかを確認して候補を列挙する必要がある。 75416 | 75417 | 疑問: COMP_POINT の説明が気になる。コマンドの先頭からの offset というのは、 75418 | コマンドラインの先頭からの位置とは違うのだろうか。例えば複数のコマンドがコマンドラインに含まれている場合にどうなるか。 75419 | 特に、複数のコマンドが含まれている場合には、他のシェル変数 COMP_CWORD, COMP_WORDS, COMP_LINE 等もどうなるか気になる。 75420 | 75421 | →何と! ちゃんとコマンドライン中の、現在のコマンドに対応する部分を切り出して 75422 | COMP_LINE, COMP_WORDS, COMP_CWORD を設定してくれる様だ。 75423 | COMP_LINE が現在のコマンドラインだという説明が誤っていたという事になる。 75424 | 75425 | 所で $(echo $(echo $(...)) 等としてみたが、... の場所に書かれているコマンドについては 75426 | complete で設定された補完は実行されないようである。 75427 | 一番外側のコマンドについて complete が呼び出されるだけである。 75428 | 一番外側のコマンドについての補完では $(...) はちゃんとひとまとまりとして 75429 | (途中の空白で単語分割されたりせずに) 扱われる様である。 75430 | 75431 | 疑問: compgen は COMP_* に対して透過的か? 75432 | つまり、先ず compgen -F でシェル関数は呼び出されるのか? という事と、更に、 75433 | COMP_* だけ自分で適当に設定すれば compgen -F を介して呼び出される関数は期待通りに動くのか? 75434 | 75435 | →試してみた所、透過的ではなかった。関数内で見ると COMP_LINE= COMP_POINT=0 COMP_CWORD=-1 の状態になる。 75436 | そればかりか、関数呼出元の変数の内容も変更されてしまう様である。 75437 | もし compgen を利用するとなると -F の内容は一旦関数でくるんで実行する事になるだろう。 75438 | 75439 | 従来の bash 向けの補完関数の能力を最大限に引き出す為には ble 側で、 75440 | 現在のコマンドの部分を切り出して仮想的に再現した COMP_LINE, COMP_POINT を用意する必要がある。 75441 75442 結論 (origiinal complete の仕様) 75443 75444 (1) COMP_LINE, COMP_POINT, COMP_WORDS, COMP_CWORD は現在のカーソル位置にあるコマンドから作られる。 75445 (2) COMP_WORDS, COMP_CWORD はカーソルが現在の単語の中のどの位置にあるかは教えてくれない。 75446 (3) compgen -F を実行すると COMP_* の内容がクリアされてしまう。 75447 75448 結論 (方針) 75449 75450 (1) 基本的には complete -p の結果を元に compgen を用いて候補の生成を行う。 75451 (2) complete -F のシェル関数は COMP_* を設定する関数を一旦挟んでから呼び出す様に介入する。 75452 (3) 補完対象は現在カーソルがある位置のコマンド全体を特定して決める。 75453 そこから仮想 COMP_LINE COMP_POINT を構築する。 75454 75455 先ずはコマンド全体を抽出する所から始まる。 75456 75457 | [コマンド全体を抽出する手法の選択] 75458 | 75459 | というよりそもそも現在の実装で単語のどの様に抽出していたか? 75460 | →ble-edit+complete 関数から ble-syntax/completion-context 関数を呼び出している。 75461 | 更にそこから ble-syntax/completion-context/check-prefix 関数を呼び出している。 75462 | この中で現在位置が属している単語の切り出しを行っている筈である。 75463 | 実際に見てみると現在位置から先頭に向かって順に _ble_syntax_stat を見ていって、 75464 | 現在位置より前にある最後の解析再開点の情報を読む。 75465 | 解析再開点には現在の解析における単語開始位置などの情報が格納されている。 75466 | この情報を利用すれば確かに現在位置にある単語の情報を抽出する事ができる。 75467 | 75468 | では更に現在位置の属している単語だけではなくコマンドまで抽出するにはどうしたら良いか。 75469 | 取り敢えず現在の単語とそれより前にある単語を順に辿って行って、 75470 | 初めにコマンド単語に当たったら其処で停止するという方法を取れば現在のコマンドを抽出できる。 75471 | その過程でコマンド・最初の引数から現在の引数までを取得する事は可能である。 75472 | しかし、以降の単語を抽出するにはどの様にしたら良いのだろうか。 75473 | 一文字ずつ進んで確かめていく方法だとそのコマンドがとても長いコマンドであった場合に時間が掛かる。 75474 | すると木構造を辿るしかないのだろうか。現在の実装だと中身から木構造を根本に辿る方法は提供されない。 75475 | ここで二つの選択肢がある。 75476 | 75477 | a tree-enumerate を利用して根本から順に辿っていく方法 75478 | 75479 | 現状 ble_debug=1 としてデバグ用情報を表示している時でもそんなに重くは無いようだから、 75480 | 根本から情報を辿る方式でもそんなに問題は無いように思われる。 75481 | 75482 | b tree-enumerate の情報をキャッシュして葉から根本の方向へ辿る事のできるデータ構造を構築する方法 75483 | 75484 | % しかしながら、今後色付けなどの更新の方の需要から、 75485 | % 葉から根本の方向へ辿る事のできるデータ構造を構築するかもしれない。 75486 | % もしその様な仕組みが整うのだとしたら初めからその事を意識した実装にする必要がある。 75487 | % 或いはもうこの complete の実装の為にその仕組みの大枠を作ってしまう方が良いかも知れない。 75488 | % 75489 | % 例えば葉から根本の方向へ辿る事のできるデータ構造を取り敢えず作り、 75490 | % その更新は愚直に全体に対して行う事にする。 75491 | % 部分更新などの細かい最適化の可能性については後で考える事にする。 75492 | % 75493 | % しかし、昔の考察だと部分更新は(整合性を保つようにするのが)かなり難しいと思われる。 75494 | % そうすると結局最終的にも完全に全体を毎回再構築する事になるかもしれない。 75495 | % それだと結局キャッシュする事の意味も余りないという事になる。 75496 | % 色付けの更新の際にもその様な調子であれば結局この仕組みは遺棄される事になる。 75497 | % それならば無駄なデータ構造を作らない方が良いとも考えられる。 75498 | % 75499 | % 結局の所具体的な需要がはっきりしないうちに仕組みを中途半端に揃えても、 75500 | % 結局想定していた需要に対しては利用できない・実現不可能という事になって、 75501 | % 無駄になるかもしれない。それならば今の段階では余り具体的な行動は動かさない方が良い様に思われる。 75502 | 75503 | 色付け更新の方から来る需要にも対応して入れ子構造のデータを構築するのは後回しにする。 75504 | 75505 | そもそもその様な入れ子構造のデータを管理して色付けを効率化できるか不明である事、 75506 | "complete で必要としているのは現在のコマンドに於ける最後の引数の位置" という単純な物であるから、 75507 | その様な入れ子構造のデータを実装してからでも対応は難しくない事からである。 75508 | 75509 | 結局、「最後の引数の位置を特定する」機能を実装して、更に其処からコマンドを抽出するという事にする。 75510 | この最後の引数の位置は a/b のどちらでも実装できるが取り敢えずの所は a による実装で進める。 75511 | 75512 | 現在の単語抽出の枠組を流用しようかと思ったが、どうも現在の実装は不完全の様な気がする。 75513 | 現在の位置が "~" で囲まれた場所だったりした時に補完が働かない。 75514 | 一方で現在の位置が ${~} で囲まれた場所だった場合は補完が働かなくて正解なので 75515 | やはり現状の実装の様にする必要もあるかも知れない。 75516 | どの様な時にコマンド単語としての補完を実行して、どの様な時にしないのかをはっきりとさせておく必要がある。 75517 | 75518 | もう少し体系的な取り扱いをしたいが、これは現状の実装でも同じ様に体系的な扱いをしたいので、 75519 | 別に新しく作るという事はせずに、現在の枠組の延長としてコマンド抽出を実装し、 75520 | もし体系的な取り扱いをしたければ現状の実装の部分を拡張する方針で行く。 75521 75522 結論 75523 (1) コマンドの抽出部分はモジュール性が高く簡単に再実装できるので、 75524 現状の枠組 (tree-enumerate) による抽出コードを取り敢えず書いて使う。 75525 (2) もし今後最適化の機会があれば再度書き直す。 75526 75527 先に補完対象 (file, command, argument, etc.) を列挙し、 75528 その後で argument による補完候補列挙が必要になった時にコマンドの抽出を行う。 75529 75530 | [コマンド部分の抽出の実装] 75531 | 75532 | コマンドの抽出はまた別の関数として実装する事にする。 75533 | 取り敢えず入れ子構造を走るプログラムを書いてみる事にする。 75534 | 75535 | そのノードが現在地を含む一番小さな word である条件は? 75536 | 75537 | 1.そのノードが word であるという事。 75538 | 75539 | nest による構造ではなくて word であるという意味である。 75540 | これは wtype が整数 (CTX_*) か文字列化で判定できる筈。 75541 | 75542 | →本当か? nest で整数を使っている箇所はないのか? 75543 | 各場所の nest-push 調べてみた所、 75544 | 数字をしている箇所は存在しないようである。 75545 | 一箇所だけ何も指定していない場所があるが、 75546 | nest-push 関数の中を見ると何も指定しない場合は type は "none" になる様である。 75547 | →或いは、nest による node 登録は別の方法で区別できるようになっていたかも知れないのでそれも確認する。 75548 | 調べてみたが ntype をそのまま tree-append に渡しているので、 75549 | 区別する為にはやはり ntype, wtype を使用する必要がある。 75550 | 現在は ntype の値は使用していない様に思われるので、 75551 | 実は tree-append 時に type を "n$ntype" にしてしまえば良いのではないだろうか? 75552 | →また既に ${node[0]} =~ ^[0-9]+$ で判定を行っている箇所を発見した。 75553 | 75554 | 保険の為 nest の場合は tree-append 時に n$ntype とする事にした。 75555 | 75556 | 2. 内側に word を含まない事 75557 | 75558 | これは先に tree-enumerate-children して内部の構造を調べてから自分の処理を実行するという風にすれば良い。 75559 | 自分が word で内部に word を含まないと判定できれば isword=1 を設定する事にすれば良い。 75560 | 内部に word を含まないという事は isword= である事によって確認できる。 75561 | 75562 | > 現在のカーソル位置に未だ単語が出来ていない場合はどうするのか? 75563 | > つまり単語を其処に入力しようとしているが未だ 1 文字も入力していない状態の場合である。 75564 | > この様な場合を検出する為には単語ではなくて寧ろコマンドの context で検出するべきなのではという気がする。 75565 | > 75566 | > 或いは、現在地を含む単語によって検出するのではなくて、現在地より前にある単語を用いて検出するか? 75567 | > 現在地より前にある単語でかつ親ノードの内側に現在地を含む物が見付かれば良い。 75568 | > これについては後で対策する。-> Done. 75569 | 75570 | コマンドに属する単語の抽出は大体完了した様子である。 75571 | 更に comp_line や comp_point comp_cword にも対応する必要がある。 75572 | →対応した。 75573 75574 取り敢えず実装したので commit する事にする。 75575 何故か動いていないが後でデバグする。 75576 75577 2015-11-19 75578 75579 * bleopt コマンド [#D0244] 75580 75581 * PROMPT_COMMAND [#D0243] 75582 75583 普通の bash (ble のない bash) では、 75584 bind -x によって設定したコマンドを実行後に prompt を再描画するが、 75585 その時には PROMPT_COMMAND の中身は実行されない様だ。 75586 あくまで通常コマンドを実行した後にプロンプトの内容を 75587 再計算する時にコマンドが実行される様である。 75588 75589 つまり PROMPT_COMMAND はプロンプトを計算する際に実行すれば良い。 75590 プロンプトの計算は .ble-line-prompt/update の中で、 75591 _ble_edit_LINENO と _ble_line_prompt[0] (前回のプロンプトの計算をした時の LINENO) が 75592 不一致だった時に実行される。 75593 75594 PROMPT_COMMAND の内容を何処で実行するかは問題になる。 75595 関数の内側で実行すると declare した変数が見えないし、 75596 また関数の内側で定義された変数に干渉する事ができてしまう。 75597 75598 一番外側で実行しようと思うと色々面倒なことになる気がするので 75599 取り敢えずは .ble-line-prompt/update の中で 75600 eval "$PROMPT_COMMAND" を実行する事にする。 75601 75602 2017-10-26 変更を眺めていて思ったが、これは直しきれていない。改めて修正した。 75603 75604 * histexpand: "~" 中の histexpand, extglob の際の histexpand 開始 [#D0242] 75605 75606 > - 文字列 "~" 中の history-expansion は " を含まない。 75607 > - '!(' not histexpansion when shopt -s extglob 対応 75608 75609 * histexpand: histchars 対応 [#D0241] 75610 75611 histchars が設定されている時の正規表現の修正。 75612 > - _ble_syntax_bashc (旧 _BLE_SYNTAX_CSPECIAL) 75613 > - _ble_syntax_rex_simple_word 75614 > - _ble_syntax_rex_simple_word_element 75615 75616 2015-11-16 75617 75618 * bug: 解析エラー [#D0240] 75619 75620 解析のバグがようやく直ったと思っていたらまたエラーになった。 75621 今度は以下の様な状況でエラーが起こる: 75622 75623 1. echo "${a[*]}" と入力する。 75624 2. echo ""${a[*]}" 75625 3. echo ""${a[*]}"" ←これでエラーになる。更に続けて何回かエラーが出る。 75626 75627 しかもエラー状態のまま色々操作しているとついに CPU 100% でハングする。 75628 75629 | [murase@padparadscha 0 ~]$ ""${a[*]}" 75630 | A? 75631 | 9*a 000 '"' stat=(1 w=- n=- t=-1:-1) 75632 | 9*a 001 '"' || 75633 | 14*a 002 '$' ||| nest=(2 w=2:0- n=- t=-1:-1) stat=(2 w=2:0- n=- t=-1:-1) 75634 | |*a 003 '{' ||| 75635 | 7*a 004 'a' ||| 75636 | 8*a 005 '[' |||| nest=(14 w=- n='v[':2- t=-1:-1) 75637 | 8 a 006 '*' |||| stat=(8 w=- n=@5 t=-1:-1) 75638 | 8 a 007 ']' |||+ word=v[:5-8 stat=(8 w=- n=@5 t=-1:-1) 75639 | 14 a s 008 '}' ||+ word=${:2-9>@7 stat=(14 w=- n=@2 t=0:-1) 75640 | 9 a s 009 '"' ++ word=2:1-10>@9 word=none:1-10>@8 stat=(5 w=- n=@1 t=0:-1) 75641 75642 何が起こっているかはすぐに分かった。一つ目の " を挿入した時に、 75643 解析が ${a[ までで中断している。本来は入れ子の構造が異なるので中断してはならない筈である。 75644 さて最近の修正の所為で中断されなくなったのか、それとも昔からあったバグなのか。 75645 75646 先ず初めの可能性は更新された領域が誤った解析結果になっていないかという事である。 75647 上の状態で言えば 000, 002, 005 に設置されている情報に当たる。 75648 これはなさそうであるが念のため確認しておく。 75649 →挿入をせずに初めから順番に入力していった場合 (エラーは起こらない) と比較する。 75650 000, 002, 005 は完全に一致している。 75651 更にいうならば 006 に設置されている stat も一致している。 75652 75653 000, 002, 005 が一致しているのは正しく解析が行われているという事なのでOKである。 75654 ところが 006 も一致しているというのは何かおかしい。 75655 これだけの情報だと確かにこの場所で解析が中断されてしまう。 75656 75657 何故前回の解析で全く同じ stat が再現されているのだろうか?? 75658 →いや局所的に見れば stat が一致するのは不思議な事ではない。 75659 たとえ全く同じ stat になったとしてもその参照先の nest が異なるのでここで中断はないはずなのだ。 75660 念のため直前の nest の状態についても調べておく: 75661 75662 | [murase@padparadscha 0 ~]$ "${a[*]}" 75663 | A? 75664 | 9 a 000 '"' || nest=(2 w=2:0- n=- t=-1:-1) stat=(1 w=- n=- t=-1:-1) 75665 | 14 a 001 '$' ||| nest=(5 w=- n='${':0- t=-1:-1) stat=(5 w=- n=@0 t=-1:-1) 75666 | | a 002 '{' ||| 75667 | 7 a 003 'a' ||| 75668 | 8 a 004 '[' |||| nest=(14 w=- n='v[':1- t=-1:-1) 75669 | 8 a 005 '*' |||| stat=(8 w=- n=@4 t=-1:-1) 75670 | 8 a 006 ']' |||+ word=v[:4-7 stat=(8 w=- n=@4 t=-1:-1) 75671 | 14*a 007 '}' ||+ word=${:1-8>@6 stat=(14 w=- n=@1 t=0:-1) 75672 | 9*a 008 '"' ++ word=2:0-9>@8 word=none:0-9>@7 stat=(5 w=- n=@0 t=0:-1) 75673 75674 やはり "nest" が違うようだ。一つ上の nest @ 004/005 は一致している。 75675 更にもう一つ上の nest @ 001/002 は内容が異なる。 75676 '"' 挿入前は更にもう一つ上の nest @ 000 を参照しているのに対して、 75677 '"' 挿入後はもう一つ上の nest は - となっていて無効になっている。 75678 75679 原因として考えられるのは: 75680 75681 a. nest を遡った比較に失敗している? 75682 c. nest を遡って比較する為のデータを誤って参照している? 75683 またはデータを移動する時に失敗して新しいデータが混入している? 75684 b. shift に失敗している? (shift の際にデータが化けている?) 75685 75686 一つずつ確かめていくしかない。確認の簡単そうな物&怪しそうな物から順に。 75687 先ずは a を疑う。function ble-syntax/parse/nest-equals の制御パスを調べる。 75688 →おかしい。ループが終わるはずのない場所で終わっている…。 75689 変だ…と思ったらこれはデバグ用コードの return が悪さをしている?? 75690 →ああ、これだ。bash の && と || の優先順位は同じで左結合である。 75691 75692 試してみた所、 75693 * [[ ~ ]] の && と || は期待通りの優先順位である。 75694 [[ a || '' && '' ]] -> 0 75695 [[ ( a || '' ) && '' ]] -> 1 75696 * (( ~ )) の && と || の優先順位も期待通りである。 75697 ((1||0&&0)) -> 0 75698 (((1||0)&&0)) -> 1 75699 * command || command && command の優先順位は注意しなければならない。 75700 true || false && false -> 1 75701 true || { false && false; } -> 0 75702 75703 一応他にも同じ間違いをしている箇所がないか以下のコマンドで調べる: 75704 75705 $ grc '\&\&' | grep -E '\|\|' | grep --color -E '\&\&|\|\|' 75706 75707 他には同じ間違いをおかしている箇所は無いようである。 75708 元々コマンドを三つ以上 && や || で繋ぐ場合が少ない上に、 75709 使っている場合でも先に && があってその後に || があるパターンばかりの様である。 75710 左結合なので、この場合は期待通りに && が内側にあると解釈してくれる。 75711 75712 (以前同じ様な事で嵌って修正を行ったような気がするが、 75713 その時に && と || を入れ替えたのだったか…。余り覚えていないが… 恐らく、 75714 A || B && C となっているのを ! A && B && C にしたのだろう。) 75715 75716 何れにしても今後は && と || の優先順位に騙されないように注意深く実装を行う。 75717 75718 2015-11-08 75719 75720 * 補完候補列挙に時間がかかっている時に入力があった場合、中止する? [#D0239] 75721 75722 そもそも補完候補列挙のどの部分に時間がかかっているのか調べる必要がある。 75723 列挙・フィルタ部分なのか、それとも描画レイアウト決定部分なのか、描画部分なのか。 75724 75725 特に時間が掛かるのは何も入力されていない状態で TAB を押した時である。 75726 complete がどの様な手順で処理されているかについて初めに調べる。 75727 ble-edit+complete (ble-edit.sh ble-autoload) 75728 -> ble-edit+complete (complete.sh) 75729 この関数内で殆ど分岐の処理をしている。 75730 先ず初めに候補を列挙して (ble-complete/source/command)、 75731 候補をスキャンして共通部分を計算する。 75732 候補が複数あったら描画を実行する。 75733 一番時間が掛かっているのは候補の列挙であり、 75734 そして次に時間が掛かっているのは共通部分の絞り込みである。 75735 今迄描画に時間が掛かっているのかと思っていたが、 75736 描画は本当に一瞬で終わっている。 75737 75738 もっと ble-complete/source/command を詳しく見てみると、 75739 どうやら各候補についての情報を生成する所 ble-complete/yield-candidate で時間が掛かっている様だ。 75740 うーんこれを最適化するのは難しい…と思ったが、 75741 この部分はシェルによるループになっているので read -t 0 をチェックして中断するのは容易である。 75742 75743 read -t 0 の performance をチェックする: 75744 75745 > | $ time for ((i=0;i<100000;i++)); do read -t 0 && echo "$i"; done 75746 > | 75747 > | real 0m2.139s 75748 > | user 0m1.998s 75749 > | sys 0m0.139s 75750 > | [ble: exit 1] 75751 > | $ time for ((i=0;i<100000;i++)); do ((i%10==0)) && read -t 0 && echo "$i"; done 75752 > | 75753 > | real 0m1.673s 75754 > | user 0m1.664s 75755 > | sys 0m0.009s 75756 > 75757 > read -t 0 の呼出回数を 1/10 にしても対して変わらない様だ。 75758 > つまりループのコストか、或いは算術式による i%10==0 の実行の方も同じ位の実行コストがあるという事である。 75759 > これならば下手に read -t 0 の判定を間引く必要もないだろう。 75760 > 75761 > | $ function ble-util/check-input { IFS= read -t 0 -n 1; } 75762 > | $ time for ((i=0;i<100000;i++)); do ble-util/check-input && echo "$i"; done 75763 > | 75764 > | real 0m9.482s 75765 > | user 0m9.260s 75766 > | sys 0m0.213s 75767 > | 75768 > | $ function ble-util/check-input { IFS= LANG=C read -t 0 -s -r -d '' -n 1; } 75769 > | $ time for ((i=0;i<100000;i++)); do ble-util/check-input && echo "$i"; done 75770 > | 75771 > | real 0m16.039s 75772 > | user 0m15.809s 75773 > | sys 0m0.215s 75774 > | 75775 > | $ function ble-util/check-input { IFS= LANG=C read -t 0; } 75776 > | $ time for ((i=0;i<100000;i++)); do ble-util/check-input && echo "$i" && break; done 75777 > | 75778 > | real 0m11.199s 75779 > | user 0m10.965s 75780 > | sys 0m0.226s 75781 > | 75782 > | $ function ble-util/check-input { read -t 0; } 75783 > | $ time for ((i=0;i<100000;i++)); do ble-util/check-input && echo "$i"; done 75784 > | 75785 > | real 0m3.687s 75786 > | user 0m3.518s 75787 > | sys 0m0.166s 75788 > | 75789 > | 75790 > | $ IFS= LANG=C; time !! 75791 > | 75792 > | real 0m3.219s 75793 > | user 0m3.048s 75794 > | sys 0m0.168s 75795 > 75796 > 分かった事は read -t 0 の引数を増やすとそれだけ処理時間が増えるという事、 75797 > それ以上に IFS= LANG=C によって変数を書き換えるのに時間が掛かるという事。 75798 > 所で read -t 0 の引数を削除しても振る舞いには影響がないように見える。 75799 > 唯単に速度が遅くなるだけなのでループ中断の判定の歳には引数は無駄に指定しない事にする。 75800 > 75801 > | $ time for ((i=0;i<100000;i++)); do ((_ble_bash>=40000)) && read -t 0 && echo "$i"; done 75802 > | 75803 > | real 0m2.909s 75804 > | user 0m2.775s 75805 > | sys 0m0.131s 75806 > | 75807 > | $ time for ((i=0;i<100000;i++)); do ((check)) && read -t 0 && echo "$i"; done 75808 > | 75809 > | real 0m2.712s 75810 > | user 0m2.646s 75811 > | sys 0m0.064s 75812 > | 75813 > | $ check=1 75814 > | $ time for ((i=0;i<100000;i++)); do [[ $check ]] && read -t 0 && echo "$i"; done 75815 > | 75816 > | real 0m2.614s 75817 > | user 0m2.419s 75818 > | sys 0m0.193s 75819 > 75820 > 更に、関数呼出はそれほどには重くはないが多少時間は掛かるという事。 75821 > それでも算術式展開と殆ど同じである。一番早いのは [[ ]] による長さ判定である。 75822 > 関数呼出が絡むのであれば算術式 ((i%100==0)) でも挟んだ方が結局の所は有効なのかも知れない。 75823 > 75824 > | $ time for ((i=0;i<100000;i++)); do ((i%100==0)) && IFS= LANG=C ble-util/check-input && echo "$i"; done 75825 > | 75826 > | real 0m1.681s 75827 > | user 0m1.679s 75828 > | sys 0m0.001s 75829 > | 75830 > | $ time for ((i=0;i<100000;i++)); do ((i%10==0)) && IFS= LANG=C ble-util/check-input && echo "$i"; done 75831 > | 75832 > | real 0m2.475s 75833 > | user 0m2.458s 75834 > | sys 0m0.014s 75835 > | 75836 > | $ time for ((i=0;i<100000;i++)); do false && IFS= LANG=C ble-util/check-input && echo "$i"; done 75837 > | 75838 > | real 0m1.586s 75839 > | user 0m1.585s 75840 > | sys 0m0.000s 75841 > | 75842 > | $ time for ((i=0;i<100000;i++)); do :; done 75843 > | 75844 > | real 0m1.399s 75845 > | user 0m1.398s 75846 > | sys 0m0.000s 75847 > 75848 > そもそもループのコストが一番大きくて、算術式や [[ ]] による判定は殆どノーコストな様だ。 75849 > read -t 0 による判定は 10 に 1 でも良いかも知れない。 75850 75851 read -t 0 の performance は大体分かったので適当に complete.sh に中断を実装した。 75852 関数 ble/util/is-stdin-ready (ble-core.sh) に実装して、それをループ内で間引きつつ呼び出す事にする。 75853 75854 今の所は使い勝手はそんなに問題ない。誤って TAB を押しても固まるという事は無い。 75855 75856 ただし、初めのコマンドを compgen で列挙する phase は環境によって滅茶苦茶時間が掛かるかも知れない。 75857 以下に速度を計測してみる事にする。 75858 75859 | @gauge Cygwin (Intel(R) Core(TM)2 CPU 6300 @ 1.86GHz) 75860 | 75861 | $ time compgen -A command '' > /dev/null 75862 | 75863 | real 0m24.248s 75864 | user 0m0.953s 75865 | sys 0m5.875s 75866 | 75867 | $ time compgen -A command '' > /dev/null 75868 | 75869 | real 0m6.578s 75870 | user 0m1.063s 75871 | sys 0m5.375s 75872 | 75873 | $ time compgen -A command '' | wc 75874 | 6472 6494 65984 75875 | 75876 | real 0m6.734s 75877 | user 0m1.296s 75878 | sys 0m5.420s 75879 | 75880 | @padparadscha GNU/Linux (Intel(R) Core(TM) Duo CPU T2300 @ 1.66GHz) 75881 | 75882 | $ time compgen -A command '' | wc 75883 | 5274 5274 68019 75884 | 75885 | real 0m0.119s 75886 | user 0m0.038s 75887 | sys 0m0.092s 75888 | 75889 | @hankel GNU/Linux (Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz) 75890 | 75891 | $ time compgen -A command '' | wc 75892 | 4112 4112 57267 75893 | 75894 | real 0m0.051s 75895 | user 0m0.019s 75896 | sys 0m0.038s 75897 | 75898 | @laguerre GNU/Linux (Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz) 75899 | 75900 | $ time compgen -A command '' | wc 75901 | 7639 7639 87603 75902 | 75903 | real 0m0.094s 75904 | user 0m0.021s 75905 | sys 0m0.079s 75906 75907 やはり cygwin では桁違いの遅さである。 75908 cygwin では command prefix が空の時は何も列挙しないなどの対策が必要かも知れない。 75909 →しかしながらこれは ble.sh を使っていなくても同じ事である。 75910 遅いのが嫌であれば shopt -s no_empty_cmd_completion を設定している筈なのだから、 75911 この設定を参照して補完の有効・無効を切り替えるべきである。 75912 75913 2015-11-07 75914 75915 * M-\ delete-horizontal-space [#D0238] 75916 75917 2015-11-06 75918 75919 * <bug> 編集中に偶にエラーが起こる。起こる条件は不明 [提起: 2015-09-24] [#D0237] 75920 75921 [状況確認] 75922 75923 起こった時のメッセージを記録する。 75924 "${i}" → "${i" → "${i))" → "$((i))" とする過程で起きた。 75925 詳細: &kbd{'echo "${i}"' left left DEL "))" left left left DEL}: これで起こる。 75926 入れ子の境界を backspace で消した時に起きた? 75927 或いは別の入れ子の終了を挿入した時? 75928 75929 assertion failure: [[ ${_ble_syntax_nest[inest]} ]] 75930 ble-syntax/tree-enumerate/.initialize/FATAL1 75931 @ /home/murase/prog/ble/ble.sh:7397 (ble-assert) 75932 @ /home/murase/prog/ble/ble.sh:2 (ble-syntax/tree-enumerate/.initialize) 75933 @ /home/murase/prog/ble/ble.sh:22 (ble-syntax/tree-enumerate) 75934 @ /home/murase/prog/ble/ble.sh:236 (ble-syntax/parse/shift) 75935 @ /home/murase/prog/ble/ble.sh:-16 (ble-syntax/parse) 75936 @ /home/murase/prog/ble/ble.sh:4 (_ble_edit_str.update-syntax) 75937 @ /home/murase/prog/ble/ble.sh:2479 (ble-highlight-layer:syntax/update) 75938 @ /home/murase/prog/ble/ble.sh:4223 (ble-highlight-layer/update) 75939 @ /home/murase/prog/ble/ble.sh:4762 (.ble-line-text/update) 75940 @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update) 75941 @ /home/murase/prog/ble/ble.sh:1 (.ble-edit-draw.update-adjusted) 75942 @ /home/murase/prog/ble/ble.sh:975 (.ble-decode-byte:bind/tail) 75943 @ /home/murase/prog/ble/ble.sh:1 (ble-decode-byte:bind) 75944 75945 異常状態 75946 [murase@padparadscha 0 ~]$ echo "${i))" 75947 A? 75948 2 aw 000 'e' | stat=(1 w=- n=- t=-1:-1) 75949 | aw 001 'c' | 75950 | aw 002 'h' | 75951 | aw 003 'o' + word=2:0-4 75952 3 a 004 ' ' 75953 9 a e 005 '"' nest=(4 w=4:5- n=- t=-1:1) stat=(3 w=- n=- t=1:-1) 75954 14 a e 006 '$' nest=(5 w=- n='${':5- t=-1:-1) stat=(5 w=- n=@5 t=-1:-1) 75955 | a e 007 '{' 75956 7 a 008 'i' 75957 15 a 009 ')' stat=(14 w=- n=@6 t=-1:-1) 75958 | a 010 ')' 75959 6 a es 011 '"' nest=(15 w=- n='none':7- t=-1:-1) stat=(15 w=- n=@6 t=-1:-1) 75960 \_ '"' (← ※エラーの結果としてこうなっている。原因ではない。) 75961 75962 正常状態 75963 [murase@padparadscha 0 ~]$ echo "${i))" 75964 A? 75965 2 aw 000 'e' | stat=(1 w=- n=- t=-1:-1) 75966 | aw 001 'c' | 75967 | aw 002 'h' | 75968 | aw 003 'o' + word=2:0-4 75969 3 a 004 ' ' 75970 9 a e 005 '"' nest=(4 w=4:5- n=- t=-1:1) stat=(3 w=- n=- t=1:-1) 75971 14 a e 006 '$' nest=(5 w=- n='${':5- t=-1:-1) stat=(5 w=- n=@5 t=-1:-1) 75972 | a e 007 '{' 75973 7 a 008 'i' 75974 15*a 009 ')' stat=(14 w=- n=@6 t=-1:-1) 75975 |*a 010 ')' 75976 6*a e 011 '"' nest=(15 w=- n='none':6- t=-1:-1) stat=(15 w=- n=@6 t=-1:-1) 75977 \_ 'echo' 75978 \_ '"${i))"' 75979 \_ '"${i))"' 75980 \_ '${i))"' 75981 \_ '"' 75982 75983 011 文字目の nest の値に誤りがある。正しく shift されていない? 75984 どうやら "${i)" から "${i))" にした時にずれる様だ。 75985 更に色々調べていると "${i " から "${i a" にしても問題になる。 75986 "${i" を "${iaa" としても問題は起こらない。 75987 75988 [原因特定] 75989 75990 違いを見てみると最後の " の部分についても再更新を行っているかどうかに依存している様である。 75991 何も問題が生じない時には最後の " についても再更新が行われている。 75992 しかし問題が起こる場合には最後の " についての再更新が行われず、 75993 そこで状態が一致したと解釈されて解析が終了してしまう。 75994 75995 最後の " について shift が実行されていないという事から見ると、 75996 本来は最後の " に関しては必ず再更新を行うという想定なのだろう。 75997 それが何かの具合で " の位置で状態 (stat) が一致すればそこで中断可能という事になっている。 75998 (或いは、逆で、状態が一致すればそこで中断可能の筈なのに、shift が省略されているのかもしれない。) 75999 76000 最後の " (つまり、挿入部分の直後の文字) について状態が一致した時に 76001 そこで中断可能とするべきなのかどうなのかについて再度考察する必要がある。 76002 以前に、再開を可能とする為の条件についてまとめた様な気がするのでそれを参照する。 76003 →"[memo] の解析の際の原則" に書いたものだったはず。 76004 ここには解析データ配列に対する操作の原則を書いている。 76005 この原則から中断が可能かどうかについて導出ができるはず。 76006 →この原則が厳密に守られているのであれば解析は中断可能な気がする。 76007 % いや。解析データに関しては問題はないが、編集文字列本体に関してはどうだろうか。 76008 % 解析の際にどこに解析再開点を設置するかを決定するために、解析点よりも先の文字を使用している。 76009 % →でも一旦解析状態 stat (及び nest 構造) が同じになって、その点以降の文字列が同じであれば 76010 % 解析の結果は完全に同じになるほかはない。従ってその場所で解析の中断が可能なはずである。 76011 やはり解析は挿入範囲の直後で中断可能である。 76012 76013 % もう一つの疑問点は "${i" を "${iaa" とする過程で、何故解析の中断が行われないのかという点である。 76014 % stat は一致する筈のように思われるし、解析中断可能範囲は "${i a" とする時と同じはずである。 76015 % % →本当に stat は一致するのだろうか。もしその位置の stat も shift をしないのだとすれば 76016 % % 解析状態 stat は一致しないのでそこで解析が中断する事は無い。 76017 % % でも、そうすると今度は "${i a" の時に何故解析状態が一致してしまうのかという話になる。 76018 % % うーん。謎だ。というか確認してみた所 stat はちゃんと shift されている様である。 76019 % stat はやはり shift されている。従って一致しても良いように思われる。 76020 % 76021 % とすると残るのは解析中断範囲の計算方法の問題だろうか。。 76022 % (つまり、挿入範囲直後の文字を含んだり含まなかったりまちまちになっている可能性?) 76023 % →実際に調べてみると解析中断範囲 (-i1 i2-)は問題が出ている時も出ていない時も、 76024 % 挿入範囲直後の文字の位置に i2 がある。つまり、解析中断範囲の指定によると解析中断可能の筈である。 76025 % それが中断不可能と判定される理由は何であろうか…。 76026 % % 唯一の違いは '${' から解析を再開しているかその中身から解析を再開しているかに依存すると思われた。 76027 % % しかし、中身から解析を再開した場合でも問題が起きない場合には起きない様だ。 76028 % % →気のせい??→どうやら ble_debug を入れている時と入れていない時でエラーが出るタイミングが違うようだ。 76029 % % ble_debug を入れている時の方が即座にエラーを検知していると思われる。今後その仮定の下で調べる。 76030 % やはり '${' から解析を再開しているかどうかである。 76031 % '${' から解析を再開する場合、それに対応する nest 76032 % への参照を含む stat が全て削除されてしまうのが中断が起こらない原因と思われる。 76033 % さて、ここで改めて考えるに '${' から再解析をして再び全く同じ状態になった場合、 76034 % 新しく作成される nest は元々あった nest とは違うインスタンスではあるが、 76035 % やはりそれより後の解析状態は同じになるのではないだろうか。 76036 % そうだとすると nest が新しく作成された物であったとしても、 76037 % そこで中断して良いはずなのではないだろうか。 76038 % →取り敢えずは挿入範囲で削除された要素に対する参照が復元された場合でも中断可能として考える事にする★ 76039 % 76040 % もし「新しい nest インスタンスであっても同じ状態になれば中断可能」とするならば 76041 % shift の部分を弄ってその nest に対する参照がある stat/nest etc. を削除しない様に修正する。 76042 % (削除する代わりに適当なshiftを実行する。特に、内容が変わらないという仮定の下での shift で良かろう。) 76043 % 76044 % % - 挿入範囲にあって削除される単語・ネストを参照する解析要素でも削除せず 76045 % % 適当な shift を実行する事にする。 76046 % →確認してみた所初めからその様になっている様である。おかしい 76047 →解析の中断が終わらないのは nest の shift 自体にバグがあって nest が変な状態になっていたからであった? 76048 でも変である。解析の中断の判定は stat 及び stat の参照している nest だけしか参照しない。 76049 現在の位置に設定されている nest は解析を続行する事によって設定されるはずの物だから、 76050 解析の中断の判定には使わないはずだし実際に確認してみた所そうなっている様に見える。 76051 76052 未だ残っている問題というか、確認していない事項は shift 対象の範囲である。 76053 なぜ nest の情報が shift の対象になっていないのだろうか。 76054 nest の格納方法について再度確認を行う。別に特別な格納の方法はしていない様だ。 76055 原則に則った格納方法になっている。 76056 76057 各項目の shift 方法の判定についても確認してみたが問題ないようである。 76058 と思ったらバグを発見した。klen = nest[k] の値を見て nest[k] の shift 方法を判定するべき所を、 76059 nest[1] を見て nest[k] の shift 方法を判定していたようだ。 76060 →修正した。これで当初のエラーは発生しなくなった。 76061 76062 ToDo: 残る事はこの修正によって解析の中断がちゃんと起こる事を確認する事である。 76063 →おかしい。やはり解析の中断は起こっていない。 76064 確認してみたが stat の状態は同じ様である。という事は nest か。 76065 やはりそうだった nest の判定で棄却されている。ではどの様に? 76066 原因が分かったこれは別項目として独立させる (2015-11-06)。 76067 76068 2015-08-25 76069 76070 * ble-edit.sh (function .ble-edit/history/generate-source-to-load-history): bash-3.0, [#D0236] 76071 history が load されているか確認する時 history '!1' でエラーメッセージが表示される。 76072 76073 * ble-edit.sh: PS1 の中に含まれる ! が \! に化ける。 [#D0235] 76074 76075 → eval 'a="!m"' となっていても特に履歴展開は起こらない様だ。 76076 また、PS1 中の ` は特別な意味を持つのでエスケープしない。 76077 76078 * ble-edit.sh: PS1 の \w の $HOME を ~ に置換する部分で、 [#D0234] 76079 或るユーザ名が自分のユーザ名を先頭に含んでいる場合、 76080 そのユーザのホームディレクトリが部分的に ~ に置換されてしまう。 76081 76082 2015-08-19 76083 76084 * <bug> bash-3.0 で上 (prev-history) をすると今迄に実行したコマンドの履歴が消える。 [#D0233] 76085 76086 bash-3.0 で消える。bash-3.1 ではちゃんと期待通りの動作になっている。 76087 76088 そもそも history に登録されていないという可能性もある?? 76089 →しかし一回履歴を見てから実行したコマンドについてはちゃんと履歴に残っている様である。 76090 でも、それは history コマンドから拾った事に依る物ではなくて、 76091 自前で記録しているからに過ぎないのでは? 76092 76093 実際に history コマンドでどの様な物が登録されているかを確認してみればよい。 76094 と思って確認してみた所最近拾ったコマンドですら登録されていない。 76095 というか、history に項目を登録するたびに実際には 76096 history の末端の項目が削除されて行っている様である。 76097 これは history コマンドの呼出周辺に問題がありそうである。 76098 76099 少し触ってみて分かった事。 76100 bash-3.0 では history -s -- で登録したコマンドは末尾に追加されるのではなくて、 76101 一番最近のコマンドを置き換える形で実行される様である。この動作は bash-3.1 の時と異なる。 76102 history -s 'echo hello' としても同じであった。 76103 しかしこれだけならば何故コマンドを実行する度に数が減るのかを説明できない。 76104 76105 もう少し試してみる。bind -x に history ... を指定したらどうなるだろうか。 76106 76107 bind -x '"\C-t":history -s echo "$RANDOM"; echo ok' 76108 76109 として C-t を何回か押してみたが history が寧ろ減少するという状況は再現しない。 76110 76111 他に history に対して操作をしている箇所と言えば history -p ... のみである。 76112 それとも history -p を実行する度に history の中身が減少するのだろうか。。。 76113 76114 bind -x '"\C-t":history -p "echo $RANDOM"; echo ok' 76115 76116 →何とこれだった! bash-3.0 では history -p する度に history の中身が減少するのだ。 76117 しかも一回 history -p する度に 2 個ずつ項目が削除される様だ。 76118 76119 a history -sp としてやってみると何も問題は起こらないようだ。 76120 しかしこれだと評価結果が出力されないので history から読み出す必要がある。 76121 更に問題なのは history -sp を用いるとそれまでに history の一番上にあった項目が置換されてしまうという事である。 76122 これに対応する為には一番上にあった項目を一旦別の変数に覚えておいて、 76123 history -sp ...; history 1; の後に再度覚えて置いた項目を history -s で設定する必要がある。 76124 しかも history 1 で出力される内容は行番号 (と変更があれば * も) なので、自分で解析して正しい履歴内容にする必要がある。 76125 b 上の方法は大変に面倒である。面倒な事をするぐらいならば、 76126 実は (history -p ...) の様に subshell の中で history -p を実行してしまうのが一番楽である。 76127 subshell 内での履歴リストに対する変更は親シェルには影響がないので。 76128 fork のコストはあるものの、どうせ古い bash の対応であるのでこれで良いだろう。 76129 76130 しかし、history -p で履歴が削除されるのを防ぐ事が出来たとしても問題は依然として残る。 76131 実際にコマンドを履歴に登録する history -s が使えない事である。 76132 history -s を用いても最近の項目が置換されるばかりで新しい項目としての登録が出来ない。 76133 これは、複数回のコマンドを実行しても一番最近の一つのコマンドの履歴しか保持できないという事を意味する。 76134 これに対処する為には、bash の history に頼らずに初めから全て ble.sh の側で処理してしまうしかない? 76135 76136 →結局 history -s には頼らずに全部 ble 内で処理することにした。 76137 起動時に既に .bash_history を読み込んでしまい、 76138 そして、history -s には頼らずに直接 .bash_history に append を行う。 76139 76140 2015-08-18 76141 76142 * <bug> bash-3.0 で less <<< と入力した時点で assertion failure が出る [#D0232] 76143 76144 更に echo $(echo) と入力しただけでも assertion failure になる。 76145 76146 - FATAL1 が出て無限ループになる → 無限ループになっていたのは 76147 ble-assert || break による停止が働いていなかった為。 76148 ble-assert の実装を新しくして上記の使い方が出来る様にしたつもりで居たが、 76149 実際には古い ble-assert が使われていた為。 76150 76151 - さて assertion-failure になるのは children で参照した先が空欄である為。 76152 print-status で構築されている木の形を見てみようとしたが何か出力が変である。 76153 と思ったら local arr=() の形を使っていた為に bash-3.0 で arr='(...)' が代入されていた。 76154 これを local -a arr; arr=() の形に修正したらすぐに print-status は直った。 76155 76156 さて漸く print-status による出力を確認してみる。しかし assertion failure になる直前の形に問題はない。 76157 (正しく動いている bash-4.3 の出力と全く同じ物が出力されている。) 76158 逆に assertion-failure 直後の print-status の状態を確認してみると一箇所だけ間違っている。 76159 76160 | --- a.txt 2015-08-18 23:27:44.399485443 +0900 76161 | +++ b.txt 2015-08-18 23:28:20.860151961 +0900 76162 | @@ -11,7 +11,7 @@ 76163 | | aw 008 'c' ||| 76164 | | aw 009 'h' ||| 76165 | | aw 010 'o' ||+ word=2:7-11 76166 | -14 a 011 ')' ++ word=4:@3>5-12>@11 word=$(:5-12>@10 stat=(3 w=- n=@5 t=0:-1) 76167 | +14 a 011 ')' ++ word=4:@3>5-12>@11 word=$(:@4>5-12>@10 stat=(3 w=- n=@5 t=0:6) 76168 | \_ 'echo' 76169 | \_ '$(echo)' 76170 | \_ '$(echo)' 76171 76172 何故か存在しない単語を親単語としている様である ("@4>" の部分)。 76173 しかしこれは寧ろ ble-assert による中断で shift に失敗しているという事の様な気もする。 76174 しかしそもそも ble-assert が発生するのは存在しないノードへの参照がある為であり、これがその原因とも解釈できる。 76175 もう少し動作を見て判断する必要がある。 76176 76177 全体を探す前に念のため local arr=() の形式の誤りをしていないか確認を行っておく。 76178 他に2箇所その様な問題のある記述をしている箇所が見付かった。それを修正する。 76179 それを修正したら今迄出ていた assertion failure も出なくなった。 76180 echo $(echo) をしても何も起こらないし、また、cat <<< hello 等としても何も起こらない。良かった。 76181 76182 2015-08-16 76183 76184 * [2015-02-21] <bug> [#D0231] 76185 76186 word の属性が解除されてもそれが表示に反映されない。 76187 これはレイヤーの機能を使って実装した方が良いだろう。 76188 76189 付記: 以下の問題もこの問題によるものだった。 76190 76191 % * color: <bug> \ arg → \rm arg という編集をすると間の空白が構文再計算の対象から抜ける?? 76192 % →問題点は構文解析部分ではなくて単語に対する着色を削除する部分にある。 76193 % 構文解析や属性・単語の更新範囲の計算には問題がない事が分かった。 76194 % 76195 76196 % echo file とした後 echo を C-d で消すとその直後の空白がエラー状態になる。 76197 % そのまま新しいコマンドを入力してもエラーの儘? 76198 % →再現しない? 76199 76200 そればかりか…。前に存在していた word が消えた時 (word 以外の意味になった時) 76201 にそれを検知する術がない…。前回の word 配列を覚えておいてそれと比較する必要がある? 76202 二つの方向性がある。 76203 76204 a parse で消えた word についての情報も提供する 76205 76206 実は消滅した単語というのは、(1) DMIN DMAX0 の間にあったものと 76207 (2) _tail_syntax_word で使われなかった部分の2種類しかないのでは? 76208 代入する事によって上書きして消している word は存在しない。 76209 常にまっさらな所を i が走り、その i の箇所で word に代入しているから。 76210 76211 (1) はどうせ削除されるから関係なさそうとも思ったが、 76212 DMIN DMAX0 の間にあった単語に関しても蔑ろにはできない。 76213 というのも DMIN DMAX0 の間に終端があって開始点は 76214 それよりも前にあるかも知れず、これらの単語が消える可能性もあるから。 76215 76216 さて、parse の側でこれらの消滅について通知する事も出来るが、 76217 これは parse のするべき事なのかというと疑問である。 76218 もう少し別の方法…補足的情報を外部で取得する事によって、 76219 外部で消滅した単語の情報を取得する方法はないだろうか。 76220 76221 (1) に関しては外部で既に計算する事が可能である。 76222 (2) に関しては…外部で計算前の _word のコピーを持っていれば、 76223 最後に処理した i さえ分かれば分かる。 76224 そして (将来的に変わるかも知れないが) _ble_syntax_attr_uend がそれに対応する。 76225 76226 | 76227 | b 或いは、呼出側で前回の _word の内容を覚えて置いて消えた物がないか確認する。 76228 | 76229 | これだと比較する為には呼出側で覚えて置いた物について shift したりしなければならない。 76230 | というか覚えて置いたとしても同一性を確認するのは骨である。 76231 | 範囲と種類が同じであったとしても内容が同じとは限らないし、 76232 | 内容までも覚えておくのは面倒である。 76233 | それに内容が完全に一致したとしても本当に同一と言えるのか??? (同一として良い気がするが) 76234 | 76235 | c 更に別の方法としては呼出側で単語と描画属性の組を覚えておくというのもある。 76236 | (これは独立したレイヤーとして扱うという事に近い)。 76237 | 76238 | これを用いて毎回全ての単語に対して属性の適用を行う。 76239 | 但し、単語の描画属性が何になるかだとか引数の解析だとかは省略する。 76240 | 76241 | 然し乍らこれは結構なコストである。属性の適用についてキャッシュしていないから。 76242 | それに消滅する単語に対する処理は結局考えなければならないので変わりない。 76243 76244 76245 改めて考え直す。parse 呼出元で呼出前の _ble_syntax_tree を保持しておいて、 76246 消滅した単語を検知するというのは面倒である。もっと良い方法がないか。 76247 76248 呼出元で呼出前の状態を保持する場合にしなければならないのは以下の事である。 76249 1. 先ず初めに、parse による更新範囲を取得する。 76250 2. 1 で得た更新範囲に登録されている単語を列挙し、 76251 その単語が存在していた範囲を特定する。更新による shift に注意する事。 76252 3. 2 で得た範囲に含まれる文字について着色を再計算する。 76253 76254 実際には消滅した単語の更新範囲 (上記 2.) さえ分かればよいのだから、 76255 それを parse の中で計算してしまうと言う手もない事はない。 76256 76257 また、3. を実行するという事は、任意に与えられた範囲に対して 76258 入れ子構造を考慮に入れた着色を実行するという事になる。 76259 76260 これは何れ対応しなければならなかったので難点とはならない。 76261 76262 ∵現状では新規生成された単語の範囲内のみで入れ子構造を考えていたが、 76263 実はこの実装は不十分である。新規生成された単語に着色が為されない場合、 76264 本来その親節の着色を適用するべきであるが、現在の入れ子構造の処理方法だと、 76265 任意に与えられた単語の親を取得する事が困難である。 76266 仕様がないので現状では着色無し、という事にしている。 76267 更に、単語と単語の間の空隙に関しても親節の着色を適用すべき所であるが、 76268 % これについては現在の実装では何もしていない (前回の状態が残る)。 76269 これについては着色の更新範囲内に入った場合には属性を完全に削除する様に変更した。 76270 76271 つまり、色々な小細工を考えても仕方がない。現状で既に問題があるのだから、 76272 入れ子構造を用いた再着色の実装は必須である。 76273 76274 「任意に与えられた範囲に対して入れ子構造を考慮に入れた着色を実行する」のは結構骨である。 76275 後ろから入れ子構造を辿っていかなければ完全な木を構築する事が出来ないからである。 76276 実は、似た操作を shift の時にも行っている。一回木の構造 (というか親節へのポインタ) を生成してしまえば 76277 後はそれを使い回せばよいので、木の構造を何処かにキャッシュする仕組みがあると良いだろう。 76278 76279 % 1 取り敢えず消滅単語の範囲を計算するコードを書く。 76280 % 1.1 更新によって消滅する部分については、parse 呼出前に確認する。 76281 % 1.2 再解析によって捨てられる部分に関しては、何とか parse から結果を借りる方法を考える。 76282 % 適当なフラグに従って tail_* に対して local を宣言しないようにすれば良いだけでは? 76283 76284 parse をできるだけ弄らないように実装しようとしていたがどうも困難な様なので 76285 結局 parse 内に消滅単語呼出の追跡の為の関数呼出を書き込む事にした。 76286 取り敢えず実装した。以下の変数に範囲を記録する: 76287 _ble_syntax_vanishing_word_umin _ble_syntax_vanishing_word_umax 76288 76289 2 入れ子構造に対して計算を実行するコードを書く 76290 76291 現状で十分動いているので、一旦切る事にする。 76292 効率が悪くなったら再度考え直す。 76293 76294 * color: <bug> echo hello world と入力してから echo を消去すると、 [#D0230] 76295 hello に適用されるはずの色が "hello world" 全体に適用されてしまう。 76296 内部の _ble_highlight_layer_syntax?_table 系統の配列の内容は正しい物になっているが、 76297 _ble_highlight_layer_syntax_buff の内容はずれている。 76298 76299 ble-syntax.sh (ble-highlight-layer:syntax/update-attribute-table) の実装で、 76300 _ble_syntax_attr_uend とするべき所 _ble_syntax_attr_umax としている部分を見つけた。 76301 取り敢えずこれを修正する→直った。。。原因を探索することなく、案外呆気なく直った。 76302 76303 * <BUG> 表示されている文字列と内容の文字列がずれている。 [#D0229] 76304 76305 まとめ: これは ble-edit/dirty-range/update 実装中の2種のタイプミスによる物だった。 76306 今迄影響が出ていなかった(影響に気付かなかった)のが不思議な位に致命的なバグであった。 76307 76308 C-d を連続で入力した時などに発生している。 76309 どうも描画用の配列に対する shift が正しく処理されていない様に見える。 76310 _ble_highlight_layer_syntax_buff の内容を見てみたが変な事はないようだ。 76311 →異常がないように見えた物のよく見たらちゃんと shift できていない様だ。 76312 実際の文字数よりも長い配列になってしまっている。 76313 76314 もう少し詳しく見てみる事にする。これらの *_buff 配列は、 76315 function ble-highlight-layer/update/shift 76316 を呼び出す事によって shift している。そしてこの関数では DMIN, DMAX, DMAX0 76317 を用いて shift を実行している。一方で、ble-syntax/parse ではどの様に 76318 shift を行っていただろうか (もしかするとこれ自体も間違いを含んでいるかもしれない)。 76319 ble-syntax/parse text beg end end0 76320 の引数を参照している様だ。そしてこの関数は ble-edit.sh (_ble_edit_str.update-syntax) 76321 から参照されている。ここでは _ble_edit_dirty_syntax_* に格納されている情報を渡している様だ。 76322 76323 一方で *_buff の shift に用いている DMIN, DMAX, DMAX0 の出所は何処だろうか。 76324 ble-highlight-layer/update 76325 において DMIN, DMAX, DMAX0 が設定されている。この関数では配列 BLELINE_RANGE_UPDATE に 76326 格納された情報をそのままコピーしている。配列 BLELINE_RANGE_UPDATE は、 76327 ble-edit.sh (.ble-edit-draw.update) 76328 関数で、_ble_edit_dirty_draw_* から読み出している。これらの、 76329 _ble_edit_dirty_draw_*, 及び _ble_edit_dirty_syntax_* の更新は、 76330 ble-edit.sh (_ble_edit_str/update-dirty-range) 76331 にて実行されている。同時に実行されているので両者の内容に変化が生じるとは思えない。 76332 76333 という事は syntax の方も不当な shift/解析になっている可能性もある。 76334 但し、元の文字列を参照して解析を行っているので目立った問題が見えていないと言うだけと思われる。 76335 これについてもチェックする。ble-assert を試しに埋め込んで見る。 76336 やはり _ble_edit_dirty_draw_*, 及び _ble_edit_dirty_syntax_* の内容は常に同じになっている。 76337 76338 すると問題点は dirty 領域の合成自体にあると思われる。試しに、 76339 76340 $ ble-edit/dirty-range/clear --prefix=hello 76341 $ echo $hellobeg:$helloend:$helloend0 76342 -1:-1:-1 76343 $ ble-edit/dirty-range/update --prefix=hello 2 2 3 76344 $ echo $hellobeg:$helloend:$helloend0 76345 2:2:3 76346 $ ble-edit/dirty-range/update --prefix=hello 2 2 3 76347 $ echo $hellobeg:$helloend:$helloend0 76348 2:2:2 76349 76350 もうこれだけで間違った合成になっている。全然駄目だ。ble-edit/dirty-range/update の実装を見直す。 76351 ちょっと見ても分からないので過去のログを見る事にする。ble-edit/dirty-range/update の実装の詳細については、 76352 2015-02-16 の実装ログに記録が残っていた。論理についてよく見てみたが誤りは内容に思われる。 76353 結局、結果の式に値を代入しても正しい結果になると言う事を確認した。 76354 再度、コードの方を見てみると…何と変数名を間違えている。delta とするべき所が del になっていた。 76355 76356 直した。然し良く分からないのは、このミスだけだったら最終的な結果は 2:2:2 ではなくて、 76357 2:2:3 という謝り方をしていた筈なのではないかという事である。 76358 2:2:2 になるという事は未だ別の箇所で何かミスをしているという事ではないだろうか。。 76359 取り敢えず再度実行してみる…。 76360 76361 -1:-1:-1 76362 2:2:3 76363 2:2:3 76364 76365 今度は 2:2:3 がもう一度表示されるという結果になった。本当は 2:2:4 になるべきだ。 76366 手で計算しても 2:2:4 になる気がする。再度数式を追って何で 2:2:4 にならないのか確認する。 76367 と思ったら…endA0 読み出しの時点で beg を読み出していた…。 76368 76369 -1:-1:-1 76370 2:2:3 76371 2:2:4 76372 76373 今度は正しい合成になっている。 76374 76375 * eval は builtin eval に書き換え。test は [[ ]] に書き換え。 [#D0228] 76376 builtin の上書きを阻止。他にも複数のコマンドの上書きを阻止する。 76377 76378 * <bug> コマンドを編集中にカーソルの位置がずれて表示されている文字列と内部の文字列に齟齬が生じる。 [#D0227] 76379 76380 これはどうやら read -t 0 で読み取ったキーシーケンスが不当に解釈されて、 76381 結果として不正な文字が編集文字列に挿入されるためのようである。 76382 どの様な文字が挿入されているかを調べてから対策を考える事にする。 76383 76384 1 本来は不正な文字が挿入されたとしても正しく表示されるべきである。 76385 →不正な文字 (というか 0x80-0x9F) が挿入された時に M-^? と表示される様に変更を行った。 76386 (元の bash readline ではこれに対する対策は行っていない。従って表示がずれる。) 76387 76388 2 また、不正な文字が挿入される過程についても調べる。 76389 76390 挿入されている文字を確認した所 "M-^[" であった。 76391 つまりこれは ESC [ を受け取る為にこれを CSI の utf-8 表現に変換しているのが原因である。 76392 変換の際に bind '"\e[":"\xC0\x9B["' としているが、この "\xC0\x9B[" という列は 76393 bind を通じてしか読み取る事ができず read で読み取れる文字とは別である。 76394 bind で 1 byte 目を受け取った時点で read を実行すると 2 byte 目ではなく、 76395 "\e[" の更に次に来た文字を読み取ってしまう。 76396 "\e[" の 2/3 byte 目は全ての read が実行された後にようやく処理される事になる。 76397 つまり受信される文字の順序が変化してしまうのである。 76398 76399 (実際に確かめてみた所、その通りだった。しかし、この場合だけでなく複数の文字に対して 76400 bind -x または bind している物の場合に同様の問題が発生しうる? 76401 →複数文字から1コマンドへのmappingの際には問題にならない。複数文字が来て初めて 76402 コマンドが実行される為、複数文字の順序が交換されたりする事はない。) 76403 76404 解決方法は色々考え得る。 76405 76406 | a read -t 0 を使う以外の方法を考える。 76407 | 76408 | bind -s と相性の良い読み取り手段が有れば良い。 76409 | 例えば、bind -s で待機されている文字をコマンドから取り出す方法が有れば良い… 76410 | がそのような方法があるとは思えない。 76411 | 或いは、bind を用いて次の文字を直ぐに受信できるかどうかを判定する方法さえあればよい? 76412 | 76413 | a' read -t 0 で次の文字が来ていれば再描画を行わずに bind を抜ける 76414 | 76415 | 実は read -t 0 を用いて次の文字がすぐに来る事が確認できれば、 76416 | 表示を省略して bind を抜けても良いのではないだろうか。 76417 | 再描画は次の文字を処理する為の bind で実行されるであろう。 76418 | 76419 | 問題は accept-line の処理中に、 76420 | 再描画が完全に終わっている事を前提として処理が行われているかも知れないという事である。 76421 | (exec:exec の場合にはそうではなかったのでちゃんと再描画していたはずだが、 76422 | exec:gexec の場合にどうなっているかは調べないと分からない。) 76423 | →どうも exec:gexec の場合には 76424 | 76425 | ".ble-edit+accept-line/process+$bleopt_exec_type" && return 0 76426 | 76427 | によって bind を取り敢えず抜けてから exec:gexec の設定した trap の内部で 76428 | 再描画処理を実行するので、再描画を省略しても問題はない。というか、 76429 | 元々 bind 内部では再描画されない。 76430 | 76431 | 76432 | b "ESC [" を受け取る別の方法を考える。 76433 | 76434 | bind '"\e[":"\C0\9B["' が悪い、という事ならば別の方法で受け取る方法を考えればよい。 76435 | しかしこれは可成り苦しんだ事なので他に解決方法を見つけるのは難しい。 76436 | 76437 | c utf-8 decoder の内部状態を見て bind-s の処理中かどうかを確認し、 76438 | bind-s の処理中であれば read -t 0 で次の文字を読み取るのを抑制する。 76439 | 76440 | 例えば現状だと "\e[":"\xC0\x9B[" としているが、代わりに 76441 | "\e":"\xC0\9B" という事にすれば、最後の文字として \xC0 が来た場合には、 76442 | 次の read -t 0 を抑制するという風にするだけで問題は発生しなくなる。 76443 | 76444 | 実は内部状態を見なくても、その :bind の中で最後に処理された byte が 76445 | C0 かどうかだけ見れば良いのではないかという気がする。 76446 | 但し "\e[" の代わりに "\e" に対して bind を行った場合。 76447 | 76448 | % x しかし \xC0 で始まる文字は結構ある (u80-u7FF) ので、 76449 | % それらの文字の read -t 0 ができなくなるという問題点がある。 76450 | % と思ったが、\xC0 は u80-u7FF では決して使われないのでこれは気にする事は無い。 76451 | % \xC0 はいわば非正規化表現でしか使われないのでそれ程気にしなくても良い。 76452 | 76453 | x この方法だと実際に次の文字が来ているのに、 76454 | \e[ の回数 (bind-s を介した読み取りの回数) だけ 76455 | 再描画処理が実行されてしまうという問題もある。 76456 | 76457 | というか、実は "\e[" の組合せだと utf-8 の内部状態を見ても bind -s の処理途中なのか 76458 | どうなのかという事を判定できない (utf-8 decoder を弄れば出来ない事もないが) ので、 76459 | "\e" に bind -s するのが現実的となる。しかし、そうすると "\e" を含むシーケンスは全て 76460 | read -t 0 の抑制の対象になってしまい、入力の高速化には繋がらない。 76461 | 76462 | とも思ったが "\e" の読み取り過程では実際のキー入力は発生せず、 76463 | ble-decode-key または ble-decode-byte の内部状態を変更するだけで、 76464 | 再描画も何も処理されないので、read -t 0 で急いで読み取らなくても問題ないのでは? 76465 | という気もする。とも思ったが、確かに byte 毎の処理は実行されないが、 76466 | 例えば矢印キーによる移動などを考えると key 毎の矢印キーの移動・更新は実行される事になる。 76467 | その過程で syntax も更新されるだろう。key 毎に syntax を更新するという事なので、 76468 | やはり入力には従来通りの時間が掛かってしまうと言う事と思って良い。 76469 | 76470 | c' utf-8 で来るはずのない byte \xFF を用いるという手もある。 76471 | 76472 | % c において、多くの文字で read -t 0 ができないのを防ぐ為に、 76473 | % →この問題は気にしなくても良いという事が分かった。 76474 | % つまり、この方法は c と比べて何らの利点もない。 76475 | 76476 | "\e":"\xFF\9B" 等としておいて byte \xFF が来たら次の文字では read -t 0 をしないという具合に。 76477 | x この方法を用いる場合 utf-8 decoder に手を加える必要がある。 76478 | 或いは、ble-decode-byte:bind 側で \xFF のみを特別扱いして 76479 | ble-decode-byte に実際には文字が渡らない様にするなどの対処が必要である。 76480 | x この方法は utf-8 以外の文字符号化方式では使えない。 76481 | 或いは文字符号化方式毎に調整が必要である。 76482 | x 更に、c でもう一つ問題だった \e[ の入力の際に処理を抑制できない 76483 | という問題も解決されていない。 76484 | 76485 | この方法は可成り実装が面倒なのと場当たり的なので、余り考えたくない。 76486 76487 → a' の方針で行く事にした。簡単な実装だがちゃんと動いている様だ。 76488 76489 * read -t 0 を用いて貼付などの際に入力をまとめて処理するという事。 [#D0226] 76490 76491 実は read の timeout を 0 にして呼び出せば、これまでに入力されたバイトを全て読み出せるのでは? 76492 →意外と簡単に実装できた? と思ったが色々と問題がある様だ。 76493 76494 1. bash-4.0 未満では文字を既に入力していても何故か read -t 0 に失敗する。 76495 76496 (何も入力がない時には単に失敗するだけなので、bash-4.0 未満では単に動作しないだけである。) 76497 76498 bind -x 内部で実行している為に環境が違って read -t 0 が動作しないのかとも思ったが、 76499 実際に通常のスクリプト (test/readbyte.sh) として実行してみてもやはり動作しない。 76500 76501 改めてマニュアルを見てみると read -t 0 について言及があるのは bash-4.0 以降の様だ。 76502 76503 76504 2. 日本語の文字を入力した時に変な事になる。 76505 76506 bind -x で受信しているのはバイトである。一方で read で受信できるのは、 76507 bash-4.0 以降では文字である。日本語を入力すると、日本語の 1 byte 目は bind で受信され、 76508 2 byte 目以降は read で読み取る事になる。この時に、 76509 76510 - read で読み取られた不完全なバイトをどの様に処理するか 76511 - byte 単位で読み取られた文字と文字単位で読み取られた文字をどの様に区別するか 76512 - 現状不完全な byte の内容取り出しに失敗している (printf %d '文字 は常に 0 を返す様だ)。 76513 →否、負の数を返してる様だ? 76514 76515 が問題になる、解決の方法としては、 76516 76517 a byte/char を区別する方法を考える。 76518 76519 byte の場合、read の結果に不完全な文字が入っているという事なので、 76520 原理的に区別はできる筈だが…。また、区別できたとして、 76521 不完全な byte の内容を取得できる必要がある。 76522 76523 b read でバイト単位で読み取る方法を考える。 76524 76525 試しに LANG=C を read につけて読み取るなどしてみたが効果は無かった。 76526 76527 →どうやら LANG=C をつければちゃんと byte 単位で読み取られる様だ。 76528 しかし、その直後の s2c で LANG=C を付けていなかった為に 76529 変な結果になっていたという事の様だ。 76530 76531 2015-08-15 76532 76533 * ble-syntax.sh: `function ...' 対応 [#D0225] 76534 76535 先ず関数名に使用する事の出来る文字について確認しておく必要がある。 76536 76537 使える物: [][:%=~^{}@+-*:,.?/_] 76538 使えない物: [ "$&'();<>\`|] 76539 条件付き: 76540 ! shopt -H して置かないと履歴展開されてしまう。 76541 # 単語の先頭には使えない (コメントになる) 76542 \001 使えるが実際に定義される関数名は何故か \001\001 になる。 76543 \177 使えるが実際に定義される関数名は何故か \001\177 になる。 76544 76545 $'[^#\t\n "$&\'();<>\\`|][^\t\n "$&\'();<>\\`|]*' 76546 76547 * ble-syntax.sh: `hoge ()', `function hoge ()' 直後のコマンドに制限をかける。 [#D0224] 76548 76549 76550 2015-08-14 76551 76552 * ble-syntax/parse/shift.impl2: <bug>: echo $(echo hello) hello で1つ目のhelloをBSで削除すると無限ループになる。 [#D0223] 76553 76554 取り敢えず今は、古い実装を使う事にする。 76555 76556 ble-syntax/tree-enumerate ble-syntax/parse/shift.impl2/.proc1 76557 76558 の内部で無限ループになっている様である。 76559 どうやら一箇所に複数の節が登録されている時に 76560 一番外側の節に出会った時に一気に shift を実行してから、 76561 内側の節に対する処理を続けるという形にしていた為に不整合を生じていたようだ。 76562 一気に shift をするのではなく自分に対応している所だけ shift をする様に変更したら問題は発生しなくなった。 76563 取り敢えず、これで一旦解決とする。 76564 76565 76566 * [2015-03-08] <bug> $() を閉じると中身に色が着かない。 [#D0222] 76567 76568 $( だけ書いて中身を記述している時は正しく着色されている。 76569 $( の中の引数も、コマンド名についても同様に着色の対象になっていない様だ。 76570 ( ) の中については正しく処理されている様に見える。 76571 76572 原因は分かった。$() 全体が一つの単語となっている為に 76573 $() 全体としての着色が施され、内部にある個々の単語の着色が消されているという事だ。 76574 これをどの様に処理するのが良いかは考える必要がある。 76575 例えば zdepth 的な物を使って被覆されない様にするとか? 76576 しかし、それだと単語が消滅した時に困る。 76577 より上の階層にある単語の色を使いたいが 76578 その情報は失われているので単語の色を再計算しなければならない。 76579 76580 一応適用順序を範囲の広い物が先に行われる様に修正したが、 76581 それでも部分更新に際しては完全ではない。 76582 やはり部分更新と単語毎の着色は親和性が低いのだろうか。 76583 76584 これに完全に対応する為には現在存在している全ての単語について 76585 どの様に着色をしているかの情報を保持する必要がある。 76586 その為には必然的に単語の生死を完全に追跡する必要がある。 76587 76588 実は単語の生死を追跡するのは簡単なのではないか? 76589 単語の生成に関してはわざわざ述べる迄もない。 76590 単語の消滅に関しても beg-end0 に存在していた単語と、 76591 shift 後に j2-i に存在していた単語が消滅する単語と分かっている。 76592 76593 ただし、問題は単語が消滅した事が分かったとしてどの様に着色を修正するのかという事である。 76594 親単語が変更された時に全ての子単語について再度着色をするのは大変であるが、 76595 各単語の着色については _ble_syntax_tree に記録してしまうという手もある。 76596 76597 入れ子構造が変化した時の着色の変化をどの様に適用するかについて二通りの方法を考え得る。 76598 76599 a 着色の変化を考慮に入れるべき範囲を先に計算し、その範囲内の各点について色を計算する。 76600 この方法を用いるとどの部分を再度着色し直さなければならないのかという事を計算しやすい。 76601 一方で、各点がどの色になるのかという計算が難しい。 76602 愚直にやると各点についてその点に存在する word を列挙しなければならず現実的でない。 76603 76604 実は末端から順番に着色を進めていけばそんなに複雑な操作をしなくても着色ができるのでは? 76605 76606 b 生成・変更のあった各単語について着色を実行する。 76607 76608 単語に overlap がある場合に複数回着色されて非効率に思われるかもしれないが、 76609 親単語から順に着色を実行する様にすれば他の単語の事は考えずに自然に着色が出来る。 76610 問題点は親単語の一部でも変更があると、その親単語に含まれる全ての子要素について再度着色を実行する必要が生じることである。 76611 76612 特にこの問題はトップレベルの単語が消滅した場合にも拡張される。 76613 トップレベルの単語が消滅した場合、その部分の着色は解除されて既定の色になるべきである。 76614 しかし、単語に対して着色を実行するだけで、既定の色を適用するという操作をしなければそこに色が残ってしまう。 76615 結局トップレベルの文脈で既定の色を適用するという操作が必要になるのである。 76616 しかし、トップレベルで既定の色を適用すると全ての単語について再度着色を実行しなければならなくなる。 76617 76618 c もっと効率的な実装はないだろうか? 76619 76620 例えば CG で複数の物体が重なり合っている場合にどの様に処理を行うか? 76621 CG の場合には毎回全てのオブジェクトを描画し直すという事をする気がする。 76622 その場合には z-depth を用いてどのオブジェクトが前に来るかの判断を行う。 76623 76624 今回の場合には単語の入れ子構造の情報を持っているので z-depth を考える必要はなくて、 76625 単純に親のノードから順に着色を実行していけばよいだけの事である。 76626 従って z-depth だとかの手法は今回の場合には訳に立たない。 76627 76628 今回特に考えたいのは "部分更新" である。 76629 部分更新の対象は、生成された単語に対する着色、消滅した単語についての着色解除を含む。 76630 更に、コマンドに応じた着色を行っている際には、単語自体に変化が無くても着色が変化する事もあるだろう。 76631 これらを効率的に処理するにはどうしたら良いだろうか。 76632 特に最終的に "その点の配色" を格納した配列を更新・取得できればそれで良い。 76633 76634 % 例えば単語の depth 毎に配列を用意してそこに値を記録するという方式は? 76635 % →単語のレベルがまとめて上がったり下がったりする時に大移動が起こる。非効率である。 76636 % 更に、depth が深くなれば成る程より遅くなる。 76637 76638 % 各点についてそこに存在する単語へのリスト構造を保持する方式は? 76639 % この様にすれば或る単語が削除された時に、その位置に次に存在する色を直ぐに取り出す事ができる。 76640 % →リストを管理するのが大変である。 76641 % 単語の生成・消滅に際してリストへの登録・解除を行う必要がある。 76642 % 単語自体はその範囲情報を伴っているので、どの範囲に登録・解除をするべきかという情報を追加で持つ必要はない。 76643 % 逆にリストの各項目がどの単語に対応しているかという情報が必要である。 76644 % shift が起こった場合などには更に面倒な事になる。 76645 % 余り考えたくない方法である。単語が削除された時にその下にある色を取得する方法としては大袈裟すぎる。 76646 76647 色々考えたが a の方法が現実的な気がする。もう少し案を具体化する。 76648 76649 先ず、単語自体の着色と結果の着色は独立に扱う。 76650 76651 単語自体の着色情報は _ble_syntax_tree に補足情報として追加する事にする。 76652 76653 > 1 _ble_syntax_tree に色情報を記録できる様にする。 76654 > 1.1 4と即値で指定している所を修正する。 76655 > 1.2 _ble_syntax_tree の幅を5に増やす。未設定の状態では - を置く。 76656 > 終端していない単語の場合には - の代わりに -- を置く事にした。 76657 > 1.3 長さや内容の変化した node についての色も - に戻す。 76658 > _ble_syntax_word_umin 等に登録を行う。 76659 > 76660 > 2 更新された単語について色情報を再計算する。 76661 > 同時に色情報の変化のあった範囲を記録する。 76662 > 76663 > 3 色の変化のあった範囲に関して色配列を更新する。 76664 76665 取り敢えず実装した。$() の中も期待通りに着色されている。 76666 一旦此処でこの項目は解決とする。 76667 76668 削除して消滅した単語について着色が除去されない、 76669 速度について検証していない、等の問題点はあるが、 76670 これらは後で問題になってから考えればよい。 76671 76672 * leak variables [#D0221] 76673 76674 > cs ps1out # local 宣言忘れ 76675 > rex=$'^([ \t]*)(\\([ \t]*(\\))?)?' # local rex 宣言忘れ 76676 > rmax=-1 rmin=-1 # local rmax rmin 宣言忘れ 76677 > type='$(' # parse/nest-type -v type 前に local type 忘れ 76678 > tchild=11 tprev=-1 wbegin=-1 wtype=-1 # parse/nest-pop を parse の外側で呼び出していたのが原因 76679 76680 現在 g が leak している事が分かっているが、使用箇所が分散している為に見つけるのが面倒。 76681 → g も処理した。 76682 76683 * ble-syntax/parse: shift チェックのループが遅い。 [#D0220] 76684 76685 [現状] 76686 76687 % これはどんなに後ろの方であっても挿入位置に wbegin や inest の参照があるかもしれない 76688 % という可能性が否定できない所に問題点がある。取り敢えず、この可能性があるかないか 76689 % 判定する簡便な方法について考えてみる。 76690 % 76691 % 1 削除領域内に word 開始点や nest 開始点がなければこのチェックは免れられる。 76692 % 2 word 終了点や nest 終了点は一つの開始点に対して一つまでしかない 76693 76694 と思ったが、stat の有効性のチェックは上記の様に工夫すれば省略を考えられるが、 76695 shift に関しては結局全てチェックしなければならないので意味がない様に思う。 76696 ただ、stat や word を相対位置で覚えておくようにすれば、 76697 編集領域に跨る word や nest 以外についての shift をしなくても済む様になる。 76698 76699 % どの様にすればスキップを行う事ができるだろうか。 76700 % 先ずは stat から考えてみる事にする。 76701 % inest の可能性について。 76702 % 76703 % 1 編集領域の終了点でトップレベルならば中で始まった inest が外で閉じる事は無い 76704 % 76705 % 編集領域の前と後で nest level が同じ場合、新しい inest が中で始まっている可能性はあるだろうか。 76706 % と思ったが、ある。xxxx の中で一旦括弧が閉じて再び括弧が始まる可能性などを考えなければならない。 76707 % 但し、xxxx が top の nest level にある場合には中で括弧が閉じる事は出来ないので inest が中にあるとは考えにくい。 76708 % (ただ、inest の境界などで何が起こるかは慎重に考えなければならない。) 76709 % 76710 % まとめ: 編集領域の開始点と終了点でトップレベルならば中で始まった inest が外で閉じる事はない 76711 % と思ったが、別に開始点はトップレベルでなくても関係ない。終了点でトップレベルならば関係ないのだ。 76712 % 76713 % 2 編集領域の終了点での inest が編集領域の開始点よりも前を指しているのならば、 76714 % 中で始まった nest が外で閉じる事はない。 76715 % 76716 % というかつまり編集領域の終了点で inest が編集領域の内部を指していなければ OK という事である。 76717 % 76718 % 3 編集領域の終了点から順に見ていって、一度でも inest が編集領域よりも前を指したならば、 76719 % それ以降に編集領域の内部を指す inest が現れる事はない。 76720 % 76721 % 3 は 1,2 の一般化になっているので 3 だけチェックすれば OK である。 76722 % もっと条件を課す事が出来ないかとも考えたが、長いネスト領域の開始点を編集した時に 76723 % 多少処理に時間が掛かるという事は不自然な事ではない。 76724 % 長さ(相対位置)を補正するのに時間が掛かっているのだなという事は想像できるだろう。 76725 % 76726 % 次に stat に格納されている wbegin について。基本的に wbegin についても同じである。 76727 % wbegin は通常 inest よりも更に下の構造である。つまり inest < wbegin の筈である。 76728 % この事が使えるかは分からない。 76729 % 少なくとも言える事は wbegin も inest と同じ様な判定方法ができるという事である。 76730 % ここで更に考えたいのは inest と wbegin を組み合わせてより効率的に中断をできないかという事。 76731 % もう少し考える inest < wbegin であるのならば、 76732 % wbegin < dbeg になった時には inest も wbegin も更新を中断して良い。 76733 % しかし inest < dbeg となった段階では未だ wbegin が dbeg より手前にあるかもしれない。 76734 % でも少なくとも word は同じネストレベルの中で構造は作らないはずだから、 76735 % 一旦 dend0 < wbegin となったならばそのネストレベルでは二度と wbegin が編集領域内に現れる事は無いだろう。 76736 % 但し、一つネストレベルを抜けた時にまた wbegin が編集領域内に現れる可能性はある。 76737 % 一つネストレベルを抜けた時にまた wbegin が現れない為の条件は何か? 76738 % これは何とも言えない。抜けたネストレベルの inest が編集領域内にある限りは 76739 % 常に wbegin が編集領域内に新しく現れる可能性を排除できない。 76740 % 逆に inest < dbeg なネストを抜けたら OK という事になる。 76741 % 76742 % wbegin も考慮に入れた時の中断の条件を更新する: 76743 % 76744 % 4 編集領域の終了点から順に見ていって始めに以下の条件を満たした時に中断できる 76745 % inest < dbeg かつ ( wbeg < dbeg または dend0 < wbeg ) 76746 % この時に inest が再び編集領域内部に現れる事は無いし、 76747 % また wbeg も編集領域内部に現れる事は無い 76748 % 76749 % 仮定: word は或るネストレベルの中で構造を作る事はない 76750 % (これは現在の解析の仕組み上保証されている様に思うので特別に意識する必要はない) 76751 76752 此処まで書いて気付いたが、上は編集領域内に inest や wbegin がない事の条件であって、 76753 inest や wbegin の相対位置を補正しなくても良い条件ではない。 76754 相対位置で記録した場合に inest や wbegin の補正が必要になるのは、 76755 編集領域の長さが変化し、かつ、inest や wbegin が編集領域よりも前を参照している場合である。 76756 76757 一方で編集領域の長さが変化しなかった場合でも、 76758 word の invalidate が必要になるのでループを回す必要は残る。 76759 いっその事 word の invalidate は別のループで処理した方が良いのかも知れない。 76760 word の invalidate に関しては上記の方法でループを回すのを中断して問題ない。 76761 76762 思うに、尻からで良いからネストの構造を掘り出す事ができる様なデータを記録するべきだという気がする。 76763 特に、直前のネスト構造ノードへの nest の offset を保持する様な。 76764 全ての点について一々ネストノードだとか stat だとかが設定されているかどうかをチェックするのは大変である。 76765 考えなければならないのはその様なデータ構造自身も shift の対象としなければならない事、 76766 それから文脈値 (stat) が同じになった時に解析の中断をしてデータ構造が壊れないかどうか考える事。 76767 76768 少し考えてみる。その様な掘り出すのに必要なデータは何かというと…。 76769 先ず、途中から解析を再開できる様にする為にはその点よりも後の情報を含んでいる様なデータは保持できない。 76770 従って、必然的にノードはデータ構造の末尾に置く事になる。 76771 1 兄(末尾)のoffset 2 親(先頭)のoffset 3 末子(末尾)のoffset である。 76772 親の offset に関しては兄を辿っていけば早晩に辿り着くので記録しなくても良い。 76773 というか、親の offset は stat の inest に記録されているのでわざわざ此処で記録する必要はないし、 76774 そもそも親の末尾の offset さえ知っていれば問題なく、 76775 これは掘り出す過程で知っているはずなので各ノードのデータに含める事は考えない。 76776 76777 更に良く考えてみたら自身の情報についても格納しなければならない。自身の先頭の offset も含める。 76778 データの内容について改める。 76779 data="${自身の先頭のoffset} ${兄(末尾)のoffset} ${末子(末尾)のoffset(子がなければ -1)}" 76780 76781 [2015-08-11] 取り敢えず _ble_syntax_* に含まれるポインタを offset (長さ) で表現する様に書き換えた。 76782 76783 [2015-08-13] _ble_syntax_tree (旧 _ble_syntax_word): 入れ子構造を記録する様に変更 76784 76785 入れ子構造の情報を利用して shift を実行するコードを書いてみた。 76786 しかしそれ程高速化はしていないようである。もっと積極的に shift の skip を行うべきか? 76787 しかし、取り敢えずはこれで良いという事にする。 76788 76789 * [2015-08-13] _ble_syntax_tree (旧 _ble_syntax_word): 入れ子構造を記録する様に変更 [#D0219] 76790 76791 shift の際に入れ子構造を考慮に入れたスキップをする為に、 76792 入れ子構造を記録・構築する様に改良を行う。 76793 76794 % 整理2015-08-12 76795 % 76796 % 改めて _ble_syntax_* の形式についてまとめる: 76797 % 76798 % | _ble_syntax_text 解析結果の対象の文字列を記録 76799 % | _ble_syntax_stat[] 文字 #i を解釈する直前の解析状態 76800 % | ctx 現在の解析の文脈 76801 % | wlen 現在のシェル単語の継続長さ 76802 % | wtype 現在のシェル単語の種類 76803 % | nlen 現在の入れ子段階の継続長さ 76804 % | _ble_syntax_nest[] 入れ子の情報 76805 % | ctx 入れ子を抜けた時の復帰状態 76806 % | wlen 同上 76807 % | wtype 同上 76808 % | nlen 同上 76809 % | type 入れ子の種類を表す文字列 76810 % | _ble_syntax_word[] 境界 #(i+1) で終わる単語の情報を記録 76811 % | (つまり単語の最後の文字の位置に記録されると思えば良い) 76812 % | wtype シェル単語の種類 76813 % | wlen シェル単語の長さ 76814 % | 76815 % | ※境界#(i+1) (または境界#i が word[i-1] に対応する) の様に1つずらして格納しているのは、 76816 % | 部分更新の際の配列の切り貼りを他の配列と同様に行える様にする為である。 76817 % | 基本的に配列の切り貼りは、添字 data[i] に対応している情報はその境界の右にある文字に附属していると見做して実施される。 76818 % | 従って単語の情報は単語を構成する最後の文字、つまり添字 i-1、に附属しなければならない。 76819 76820 [計画] 76821 76822 - 入れ子構造を利用して効率的に shift を実行するためには、 76823 入れ子構造の情報を残して置かなければならない。 76824 現状の実装では入れ子構造の情報の一部は _ble_syntax_nest 等に残存しているが、 76825 解析終了後に再び構造を調べるのに十分な情報は記録されていない。 76826 76827 - 入れ子構造を構築するに当って、word に関する入れ子構造の管理は不要である。 76828 というのも、word が入れ子になっている場合には 76829 必ず nest を通して入れ子になっているはずだからである。 76830 76831 ただし、word を効率的に列挙して処理を実行するためには 76832 "前のword" に対するポインタを word 情報に含めておくのが良い。 76833 →しかしそうすると prev_word ポインタについても 76834 shift を考えなければならないという面倒な事に…。 76835 76836 nest に関しては自分の親、自分の兄、自分の末子に対するポインタを保持する。 76837 76838 - どこにどの様な形式で情報を格納しておくかというのも考える必要がある。 76839 既存の _ble_syntax_* のどこかに入れ子構造を記録するという形にするという手と、 76840 新しく _ble_syntax_tree などの配列を作成してそこに記録するという二種類の方法がある。 76841 76842 既存の _ble_syntax_* のどこかに記録するとしたら _ble_syntax_word が適切であろう。 76843 ちょうど _ble_syntax_word は解析の動作自体に影響は与えず「出力」としての効果を持つ。 76844 また、word と nest の入れ子構造を統合して統一的に記述できる可能性がある。 76845 この変更にあたって _ble_syntax_word の中身の形式を大幅に変更してしまっても良い。 76846 76847 新しく _ble_syntax_tree などの配列を作成して管理する事にすると、 76848 x 切り貼りをしなければならない配列が増える。 76849 元々 sparse な配列なので無駄に切り貼りの作業を増やしても損した気分になる。 76850 x word/nest の両方について入れ子構造を辿るのも面倒かも。 76851 76852 _ble_syntax_word を改造して形式を一新する方向で考える。 76853 まず、現在 _ble_syntax_word が使用されている箇所について確認を行う。 76854 - 単語の登録・shift 76855 - 色付け (syntax/update-word-table) 76856 - debug 用コード (print-status など) 76857 現在の形式は "wtype wlen" である。此処にどの様な情報を付加するべきか? 76858 - word と nest は同じ箇所で終了する可能性がある。 76859 したがって両方登録できる様にするべきである。 76860 同じ箇所で終了する場合、word の内部に nest があるという構造になっている。 76861 - word の親と nest の親は必然的に同じである。 76862 - word の親はなしまたは nest である。nest の親はなしまたは word である。 76863 word が word の親になっていたり nest が nest の親になっている事はない。 76864 76865 a 案 "wtype wlen parent prev child ..." というのはどうだろうか。 76866 [[ $wtype == ^[0-9]+$ ]] の時に word でありそれ以外の時に nest である。 76867 child > 0 の時は末子はその offset の位置に存在する。 76868 child == 0 の時は末子は同じ位置で終了し ... に末子の情報が記録される。 76869 既に登録されている場合には "wtype wlen parent prev 0 既存内容" などとすれば良い。 76870 76871 % ? 疑問点: 前回の解析までに存在していた内容を消去しなくても良いのか? 76872 % 前回の内容はいつ消去されるのだろうか。 76873 % 何処かで削除を実施しないと、前回の解析の結果が混ざってしまう。 76874 % - これは今迄の実装でも注意しなければならなかったはずだ。 76875 % 前回の解析で単語の終端だった部分が新しい解析で単語の途中になった場合、 76876 % 前回の解析で生成された単語が消去される機会が失われてしまう。 76877 % →前回の解析で存在していた内容を気にする必要はない。 76878 % これらは配列の切り貼りの時点で削除され _tail_syntax_word に移動される。 76879 % 途中で解析状態が同一になった時にのみ _tail_syntax_word から再度コピーされる。 76880 % つまり、解析する時には _ble_syntax_word は空文字列になっているので 76881 % 前回の内容の残存については気にしなくて良い。 76882 76883 この方法ならば同じ位置で複数のレベルの word が終端する場合にも対応できる。 76884 今現在ではそのような単語の区切り方は存在し得ないが、柔軟な構造にしておいた方が見通しが良いだろう。 76885 76886 ? nest-push の type として [0-9]+ の様な物が存在していると word と区別が付かない。 76887 そのような物が存在していないことを確認する必要がある。 76888 → grc --exclude=out nest-push で確認した。その様なものは今のところない。OK 76889 76890 [実装] 76891 76892 上記 a 案で行くことにする。 76893 76894 1 先ず初めに word に登録する関数を準備する。これで word を登録する様に変更する。動作を確認する。 76895 2 word に別の情報も登録できる様に word 読み取り部分の変更を行う 76896 3 nest 情報も pop 時に登録する様に変更する。print-status の改良 76897 76898 4 兄情報・子情報も登録する。入れ子になっている部分も shift する 76899 76900 > (a) 兄情報・子情報をその場で計算して登録するという可能性? 76901 > 76902 > 兄情報・子情報も登録するためには stat に兄情報・子情報を記録する必要がある? 76903 > もし兄情報・子情報をその場で計算して求めることができるのであれば、 76904 > わざわざ現在の解析状態に含める必要はないのではないかということ。 76905 > 76906 > ? stat に記録を行わなくても _ble_syntax_word, _ble_syntax_nest 等を用いて 76907 > 兄情報・子情報を構築することは可能だろうか? 76908 > 76909 > 兄は max { 終端 | 親の開始位置 < 終端 <= 自身の開始位置 } の筈である。 76910 > また、子は max { 終端 | 自身の開始位置 <= 終端 <= 自身の終端位置 } の筈である。 76911 > 親の開始位置は、 76912 > wbegin が設定されている場合は wbegin が、 76913 > inest が設定されている場合は inest が、 76914 > それ以外ならば初期位置 0 が該当する。 76915 > 自身の開始位置・終端位置は知っている。 76916 > 76917 > これらの情報を用いれば兄情報・子情報を必要になった時に構築する事は可能である。 76918 > 76919 > ? 解析時は兄情報・子情報はローカル変数に保持しながら解析して、 76920 > ただし、stat から復元する時には兄情報・子情報を再構築するという方法はどうか? 76921 > nest-pop の際にも同様に構築する必要が生じるのでは? 76922 > これだとコストがかかってしまうので、nest-push の際にまとめて兄情報・子情報も push して良い。 76923 > しかし、その様にするのであれば stat にも同様に保存してしまえば良いのではという事になる。 76924 > 但し面倒なのは、兄情報・子情報を stat/nest に記録する様にしてしまうと、 76925 > 兄情報・子情報に対する shift も実装しなければならないという事である。 76926 > 76927 > 取り敢えずの方針としては、shift の実装が面倒なので兄情報・子情報は stat/nest には含めない。 76928 > 代わりに word に登録する際に毎回自分で兄情報・子情報を計算する、という事にする。 76929 > 76930 > 問題点 76931 > 76932 > ? 兄情報・子情報は shift だけで良いのか? 76933 > stat に登録していない為に兄情報・子情報がずれていても 76934 > 解析状態が同じになったと判定されてしまう可能性がある。 76935 > 76936 > →削除された領域にあるノードを参照している stat は削除すればよい。 76937 > stat で現在参照しているのは wbegin, inest である。 76938 > 76939 > % 但しチェックする範囲が広がるのが難点かも知れない。 76940 > % →stat に兄情報・子情報を記録する場合でも stat の更新範囲が広くなるので 76941 > % 結局どのようにしても同程度チェックする範囲が広がる。気にしなくて良い。 76942 > 76943 > →削除された領域にあるノードを参照している弟ノードはどうするのか? 76944 > それも削除すると更にその弟も再構築の対象になり…を繰り返して結局すべて解析し直す事になる? 76945 > 更に、削除された領域にあるノードでなくても、 76946 > 解析状態が一致しないことによって再解析が行われて失われる word も存在している。 76947 > それらを兄情報・子情報として参照しているノードはどの様に取り扱うべきか。 76948 > 76949 > 結局 _ble_syntax_* に記録された昔の情報を参照して構築する方式だと、 76950 > 部分更新した際に不整合が生じてしまう。 76951 > 昔の情報を参照して構築した部分をすべて再計算しなければならなくなるが、 76952 > どの部分がどの部分の昔の情報まで使って構築したかの情報がないので、 76953 > すべて再計算しなければならなくなる。 76954 > (一応各ノードを調べれば再計算が必要かどうかを得ることができるが、 76955 > いずれにしてもすべてのノードについてそのチェックを実行しなければならない。) 76956 > 76957 > 因みに _ble_syntax_nest に関しては過去の情報を使用して解析が実行されるが、 76958 > 解析状態一致の確認の際にはちゃんと _ble_syntax_nest の一致まで確認されている。 76959 > 76960 > (b) 兄情報・子情報に対応する情報も stat に含めて計算を実行する 76961 > 76962 > word/nest が混合しているのでどの様に取り扱うかが微妙である。 76963 > 兄にしろ子にしろ (ある条件を満たすノードで) 最後に登録したノードへのポインタになる。 76964 > 76965 > 何れにしても wbegin/inest 設置の瞬間に兄・子の情報も更新する必要があるような気がする。 76966 > inest 設置の瞬間の処理については nest-push で行えば良い。 76967 > wbegin 設置については新しく wbegin 設置用の関数を置くことにするか? 76968 > 先ず初めに wbegin 設置位置について確認を行う。 76969 > →主に3箇所の wbegin 設置箇所があったので新しく関数を用意してそれに置き換えた。 76970 > 76971 > 更に解析状態を表す tprev, tchild という変数を追加した。 76972 > tchild は現在の level で一番最後に設置された節の位置を表す。 76973 > tprev は一つ上の level で一番最後に設置された節の位置を表す。 76974 > child/prev というのは現在の節からの視点であって、 76975 > 現在の位置に新しく設置する節からの視点ではないことに注意する。 76976 > 76977 > ? stat に tprev/tchild を記録する必要は実はないのではないか? 76978 > というのも解析再開時に状態を復元する際は、 76979 > 過去のデータ配列の内容を参照して良いはずだから、 76980 > わざわざ記録しなくても計算で tprev/tchild を再構築できるからである。 76981 > 76982 > →やはり記録する必要はある。stat には2つの役割がある。 76983 > 一つは解析再開時に解析途中の状態を復元する役割であり、 76984 > もう一つは解析状態が一致したかどうかを判定して、 76985 > 解析を中断するための参照状態となる役割である。 76986 > 76987 > 前者の役割を果たす為には tprev/tchild は再構築できるので不要であるが、 76988 > 後者の役割を果たす為には参照用の tprev/tchild を保持している必要がある。 76989 > (後者の場合でも、一応 "古いデータ配列を全て覚えておいて、かつ解析状態の比較の際に 76990 > 毎回古いデータ配列から tprev/tchild を再構築して一致するか確かめる" という力技もあるが、 76991 > それはさすがに遅くなるのでやはり記録をする。) 76992 > 76993 > 結論: stat に tprev/tchild も記録する。 76994 > 76995 > ? nest に tchild を記録する必要は実はないのでは? 76996 > nest は pop した時に状態を復元するためにある。 76997 > ところで pop した時に新しい節が作成されて tchild は上書きされて消える。 76998 > どうせ直後に上書きされて消えるのであれば記録する意味は無いのでは? 76999 > 77000 > 解析状態の一致の際にもチェックする必要はないように思われる。 77001 > というのも結局使われない情報であるため、 77002 > もしチェックをせずに違いを看過したとしても最終的な結果には何の違いも出ないからである。 77003 > 77004 > % また記録するとその分また shift のコストが上がるという事を意味する。 77005 > % 取り敢えず nest には tchild を記録しない方針で行くことにする。 77006 > 77007 > 実は nest の tchild は必要のようだ。 77008 > nest の下に word を構築する際、word に入って word から抜けた時に tprev を復元しなければならない。 77009 > それが実は nest-push した時の tchild に対応している。 77010 > 77011 > ? word-pop 後の tprev について現在のデータ形式で自然に再構築できるか? 77012 > 77013 > word-pop 後は nest の level (または top level) に必ずいる。 77014 > というのも word の下に word は直接来ないからである。 77015 > word-pop 後の tprev は何を意味するかというと、現在の nest-level の前の nest-level である。 77016 > これは nest-push する直前の tchild を意味する。 77017 > 77018 > 取り敢えず (a) で実装したが (b) に方針転換する事にする。 77019 77020 4.1 word-pop の際の tprev の再構築? 77021 4.2 ble_syntax_stat の形式変更 77022 4.3 check 77023 4.4 新しく追加した項目の shift 77024 77025 > shift は再度整理して書き直す事にする。 77026 > 77027 > 不可解な実装になっている部分についても再考察を行う。 77028 > 77029 > ? stat 無効化に於いて wbegin/inest の判定範囲が 77030 > 更新領域 beg-end0 ではなく再計算領域 i1-j2 になっているが、 77031 > 無効化は更新領域に被る時にだけ行えば問題ないのでは? 77032 > 77033 > 或いは実は原則を破っている箇所があった為にこの様になっていた? 77034 > 例えば var[]= の部分に関しては、元々原則を破った実装になっていた。 77035 > (現在は、この部分に関しては保留中である。 77036 > 最終的には word 着色で var[] としての着色を上書きしてしまうなどすれば良い。) 77037 > 77038 > ? stat の shift に於ける無効化チェックは必要なのだろうか? 77039 > 77040 > 原則さえ守っていれば stat/nest の解析状態チェックだけでOKなのでは? 77041 > 77042 > 元々この様にした理由は、無効化がないと不正確な stat が残ってしまうという事である。 77043 > % この不正確な stat の状態で解析を続行しても続きのデータを再現できない可能性がある。 77044 > % つまり、この事により予期しない解析中断が生じる可能性がある。従って無効化は必要である。 77045 > 77046 > →本当だろうか? 不正確な stat (その様な stat が生成される機会はなかった) としても 77047 > stat が一致している以上は後続のデータも全く同様の物が生成されるのではないだろうか? 77048 > つまり、stat を無効化するかどうかの判定は「前回の解析の shift だけで同じ stat が生成されるかどうか」 77049 > ではなく、もっと許容的な「後続のデータを再現することができる stat」という条件にするべきという事である。 77050 > 77051 > 逆に stat が壊れた状態になったとしても、 77052 > 後続のデータと整合する様に修正する事ができれば無効化する必要はないという事になる。 77053 > stat の wbegin/inest が指し示している部分が消滅した時の wbegin の変更の仕方を一つ決めればよい。 77054 77055 5 check: チェックの為に print-status に構文木の結果を表示する。 77056 77057 5.1 未だ終端していない入れ子構造についても正しく処理する必要がある。 77058 77059 > 例えば shift を計算する範囲を決定する際に愁嘆していない入れ子構造の部分を跳ばす事はできない。 77060 > 終端していない入れ子構造についてどの様に処理を実行するべきかは、print-status の実装で試せばよい。 77061 > 他の shift 等に対しても同様の処理を実行する際には print-status の実装を真似すれば良い。 77062 > 77063 > 一つの方法は無理矢理終端させた時のデータ配列を作成して、 77064 > その配列に対して処理を実行する方法である。 77065 > この様にすればデータ配列の形式に従ってそのまま処理を実行する事が出来る。 77066 > 終端していない節と終端した節 (データ配列に格納された節) が混合したままだと、 77067 > それに対する処理を上手に書くのが面倒なように思われる。 77068 > 77069 > 何れにしても print-status の実装を終端していない節に対応する過程で再考察を行う。 77070 > 77071 > 何だか良く分からなくなったので、結局終端していない入れ子構造についての情報を変数 tree に集計した後で、 77072 > ("${_ble_syntax_tree[@]}" "$tree") に対して処理を実行するという形にする事にした。 77073 > 関数 ble-syntax/tree-enumerate proc, ble-syntax/tree-enumerate-children proc を使う。 77074 > proc には各節を処理する関数名を指定する。 77075 > これを用いて print-status も実装した。多分動作している。 77076 77077 2015-08-11 77078 77079 * _ble_syntax_* の単語・入れ子開始位置の記録方法を変更 (絶対位置 wbegin → 相対位置 wlen) [#D0218] 77080 記録点からの負のoffset(単語長・入れ子継続長)で指定する事にした。 77081 77082 % 整理2015-08-11 77083 % 77084 % 何やらよく分からなくなってきたので改めて現在の状況についてまとめることにする。 77085 % まず、現在の _ble_syntax_* のデータは以下のような形式になっている。 77086 % 77087 % _ble_syntax_text 解析結果の対象の文字列を記録 77088 % _ble_syntax_stat[] 文字 #i を解釈する直前の解析状態 77089 % ctx 現在の解析の文脈 77090 % wbegin* 現在のシェル単語の開始位置 77091 % wtype 現在のシェル単語の種類 77092 % inest* 現在の入れ子の開始点 77093 % _ble_syntax_nest[] 入れ子の情報 77094 % ctx 入れ子を抜けた時の復帰状態 77095 % wbegin* 同上 77096 % wtype 同上 77097 % inest* 同上 77098 % type 入れ子の種類を表す文字列 77099 % _ble_syntax_word[] 境界 #(i+1) で終わる単語の情報を記録 77100 % (つまり単語の最後の文字の位置に記録されると思えば良い) 77101 % wtype シェル単語の種類 77102 % wbegin* シェル単語の開始位置 77103 % 77104 % ※境界#(i+1) (または境界#i が word[i-1] に対応する) の様に1つずらして格納しているのは、 77105 % 部分更新の際の配列の切り貼りを他の配列と同様に行える様にする為である。 77106 % 基本的に配列の切り貼りは、添字 data[i] に対応している情報はその境界の右にある文字に附属していると見做して実施される。 77107 % 従って単語の情報は単語を構成する最後の文字、つまり添字 i-1、に附属しなければならない。 77108 % 77109 % shift の対象となるのは * で示した項目である。 77110 % 現在、内部構造を表現する情報に nest と word の2種類がある。 77111 % 77112 % A word&nest を統合する可能性について: 77113 % 77114 % word と nest を別々に管理していることによって、 77115 % shift 対象の管理がより面倒になっている様に思われる。 77116 % nest は解析のために必要な入れ子の情報であり、 77117 % word は解析には必要がないが解析の結果として呼び出し元に提供する情報である。 77118 % どちらも似た様な入れ子構造を構築することには変わりないが使い方が多少異なる。 77119 % 77120 % x どちらも同じ位置で二段階の入れ子を作ったり抜けたりする事はない、 77121 % という前提で実装されている気がする。 77122 % 統合するとしたらこの前提が成立しなくなるので注意する必要がある。 77123 % 例えば echo $(command),$(command) となっている場合、 77124 % echo の第一引数の単語は、開始点で2段階の入れ子を作成し、 77125 % また、最終点で2段階の入れ子を抜ける事になっている。 77126 % (ところで、単語と解析の入れ子が交錯する様な事態は起こらないので、 77127 % 多段階の入れ子作成・解除にさえ対応すればそれで問題はなくなる。) 77128 % 77129 % x word/nest は微妙に異なる構造の構築になっている気がする。 77130 % word は word の終了時にその性質が決定され、末端に情報を格納する。 77131 % word が開始した時点では word 情報は確定していないので、 77132 % 配列には記録せずにむしろ解析状態 stat に現在の word を直接記録している。 77133 % 一方で nest は入れ子が開始した時点で、 77134 % それがどの様な入れ子なのかが確定するので、開始点に全ての情報を格納できる。 77135 % 77136 % x 何より完全に解析部分を再実装することになりそうなので統合したくない。 77137 % 現在の実装では、解析の制御に最低限必要な部分を nest に格納している形になっていて、 77138 % 解析の制御に関係のない word の部分は分離している、という体である。 77139 % Shift 時の複雑さには目を瞑ってこのままで良い気がする。 77140 % 77141 % →上記の色々な理由から word&nest の統合は取りあえず断念する 77142 % 77143 % shift 時は単純に該当する項目の補正を行うだけではなく、 77144 % 無効になった word, nest を参照している stat を削除するという事もする。 77145 % 77146 % B 単語の開始位置を offset で管理している場合: 77147 % 77148 % 単語が完全に更新領域の外側にある時は書き換えの必要性はない。 77149 % 単語の開始点が更新領域に含まれている場合、 77150 % 単語は消滅する。この単語を参照している stat (解析状態) も同時に削除しなければならない。 77151 % 削除しておかないと、再解析の結果として偶々同じ stat になった時に解析が停止してしまう。 77152 % # 或いは、解析が停止するのならばそれで良いのではないだろうか? 77153 % # 全く同じ状態になったのであれば以後の計算をしても同じ結果になるはず。 77154 % # もし同じ結果にならないのであれば shift/状態復元 に失敗しているという事だから、 77155 % # そちらを修正するべきということである。 77156 % # これは shift を正しく実行できないのだとしたら削除するべきということでもある。 77157 % # 今、単語の開始位置の表現を変更した為に、前と状況が変わっているかもしれない。 77158 % # この辺りの stat を削除するかしないかについては再度慎重に検討するべきである。 77159 % この単語を参照している nest は、使用されることがないので放置で良い。 77160 % 何故ならば解析再開点は nest が記録された位置よりも前になり、 77161 % また…(本当か???) 77162 % 単語の内部に更新領域が含まれている場合 77163 % その単語の長さの修正を行う。 77164 % 単語の終端だけが更新領域に含まれている場合 77165 % 単語は word には記録されていない。 77166 % stat にある相対位置だけ修正を行えば問題ない。 77167 % 77168 % →考えるのが面倒になったので実際に実装してしまう事にした。意外と簡単に済んだ。 77169 % _ble_syntax_{stat,word,nest} に対して内容の形式を変更した。 77170 % 先ず単語の終端が更新領域よりも後にある場合にしか単語の shift は必要ない。 77171 % (というのも、単語の終端が更新領域よりも前にある場合は勿論 shift は不要だし、 77172 % 単語の終端が更新領域の内部にある場合は単語自体が無効になるからである。) 77173 % そして更に単語の長さが変更になるのは単語の開始が更新領域よりも前にある場合である。 77174 % (というのも、単語の開始が更新領域の内部にある場合には単語自体が消滅するからである。) 77175 77176 * <bug> 履歴が正しく初期化されない [#D0217] 77177 77178 何かコマンドを実行した後に history-prev を実行すると、 77179 直前に実行されたコマンドが表示されず、少し昔のコマンドが表示される。 77180 幾つか遡っていくと直前に実行されたコマンドが表示される。 77181 77182 history で表示されるコマンドは正しいコマンド順になっている。 77183 また、遡っていって直前に実行されたコマンドに行き着けば、 77184 それより前は正しいコマンド順になっている様である。 77185 余分コマンド (直前に実行したコマンドと履歴リストの末端の間にあるコマンド) 77186 に対応した抜けがある訳でもなく、余分コマンドと同じコマンドが幾つか繰り返している。 77187 どうやらコマンド順が変になっているのではなくて、 77188 履歴のリストの末端に余分にコマンドが追加されているという事のようだ。 77189 77190 どうやら .bash_history に空行があると駄目な様だ。 77191 .bash_history の空行は初期化の際に読み取られないので行番号がずれる。 77192 行番号がずれていると history -n で追加読み取りした部分がずれる。 77193 →.bash_history の空行を削除したら問題は発生しなくなった。 77194 77195 と思ったが、それでも ble.sh を起動してからコマンドが追加されたりして、 77196 その後で初めて履歴を使う、という事をするとまた履歴が末尾に追加されて分かりにくい。 77197 77198 % 無条件で履歴を読み取るのではなくて、履歴エントリが空の時にだけ読み取る様に変更するべきでは? 77199 % →履歴エントリが空の時にだけ読み取る様にすると、 77200 % 一回でもコマンドを実行すると過去の履歴が辿れなくなる。 77201 % 履歴の初期化をせずにコマンドを実行したときの履歴の処理はどうしているのか。 77202 77203 再度履歴情報の取り扱いについて整理する: 77204 77205 履歴情報は2段階ある。shell が持っている history 情報と、 77206 ble で取り扱えるようにシェル変数に格納した履歴情報である。 77207 ble の履歴情報の初期化には時間がかかるのでできるだけ遅延したい。 77208 bashrc 処理時には shell の history にまだ履歴が読み込まれていない。 77209 bashrc の処理が終了して対話状態になった時には shell の history は初期化されている。 77210 しかし、ble の履歴情報はまだ初期化されていない状態である。 77211 ble でコマンドを実行したときには shell の history に情報を追加する。 77212 ble の history 情報が既に初期化されていればそちらの更新も行う。 77213 77214 結局、shell の history が空の時にだけ読み取る様に変更することにした。 77215 77216 2015-08-09 77217 77218 * complete: <bug> リダイレクトのファイル名でファイル名補完が効かない。 [#D0216] 77219 →対応した。 77220 * complete: <bug> .# で始まるファイルを扱うために .\# などとして tab をしても補完が効かない。 [#D0215] 77221 →再現しない。再度改めて試してみたが、補完は問題なく動いている様である。 77222 77223 * complete に関連する過去の修正 [#D0214] 77224 - 変数= の補間でファイル名を取り扱える様にする 77225 - > の直後のファイル名の補間が働かないのを修正 77226 - (command) ディレクトリ名の直後に / を挿入する 77227 77228 2015-04-25 77229 * complete: 補間挿入: 既に直後に '/' または ' ' がある場合にはこれらの文字を挿入せずに次に文字を進める。 [#D0213] 77230 * complete: option hoge=, hoge: の続きにファイル名を指定できる様にする [#D0212] 77231 77232 2015-03-22 77233 77234 * ble-decode.sh: bugfix, bash-4.1 でも ESC * に登録しないと駄目 [#D0211] 77235 77236 一回でも ESC z 等を bind -x で登録して解除すれば OK になる。 77237 しかし、一回も bind -x をしていない状態だと 77238 ESC 単体で登録しても何も起こらない。 77239 どの bash の version でも ESC * に対して張る事にする。 77240 77241 今度は ESC [ を捕まえられなくなった。 77242 bash_execute_unix_command: cannot find keymap for command のエラーになる。 77243 bash-4.3 と同じ症状である。結局 bash-4.3 と同様に ESC [ を変換する事にする。 77244 77245 2015-03-11 77246 77247 * ble-syntax.sh: <bug> 単語の先頭に空白を挿入すると空白が単語の一部とされる [#D0210] 77248 77249 % 単語の先頭に文字列を挿入した時に単語情報 _ble_syntax_word が更新されない。 77250 % 結果として単語の先頭位置が更新されず、空白も単語の一部と解釈される。 77251 % 77252 % 本来であれば wbegin の位置が変化しているのだから _ble_syntax_stat が一致せず、 77253 % 単語の終端まで行って漸く _ble_syntax_stat が一致する筈である。 77254 % 単語の終端まで行くのであるから word の情報も再設定されるはずという算段である。 77255 77256 これは単に単語の shift が実行されていない事が原因であった。 77257 元々は、単語の登録は必ず stat の設定を行った箇所でしか起こらないと決めていた。 77258 従って shift 判定の時は stat に値が設定されている時にだけ単語の shift の確認を行っていた。 77259 所が、shift の判定を stat に値が設定されているかどうかに拘わらず実行する様にしたら、問題が発生しなくなった。 77260 これはつまり stat の設定が行われた箇所とは異なる場所で word が設定されているという事を意味する。 77261 77262 - よく考えてみれば for の直後などでも空白を飛ばしているので for に対する word の箇所では stat が起きない。 77263 つまり、この場合にも stat が設定されている事を前提とした word の shift は動かない事になる。 77264 と思ったが改めてみてみると for の直後には stat が設定されている。 77265 改めて考えてみれば for の直後の状態は CTX_CMDXF で表現する様に変更したのであった。 77266 77267 - 問題の発生していた例 "echo hello" の場合には word の位置に必ず stat が設定される様に思ったが、 77268 これで問題が起きていたという事は echo の終端位置に stat が設定されていないという事を意味する。 77269 実際に echo hello を解析した後に stat の内容を吐き出してみたが、stat が設定されているのは、 77270 (echo の直前、hello の直前、終端) の三箇所だけになっている。 77271 改めて ctx-command/check-wrod-end を見てみると、 77272 関数定義に対応した時にコマンドの後の空白を読みとばす様に変更したのであった。 77273 77274 * <bug> i-word[1]: substring expression < 0 [#D0209] 77275 77276 time : $(echo | echo | echo) を time : $(: | : | :) に書き換えている最中に 77277 bash-4.0: i-word[1]: substring expression < 0 というエラーが出た。 77278 bash-4.0 と bash-4.1 で再現したが、再度起こそうとしても起きない。 77279 起きる条件が良く分からない。 77280 77281 エラーメッセージに現れる式は ble-syntax.sh の 77282 ble-highlight-layer:syntax/update-word-table 77283 にしか現れない式である。wbegin の shift に失敗しているのだろうか。 77284 77285 再び起こった。今度はもう少し違ったパターンだが共通点はある。 77286 $() の中で | の直後の単語の一部を削除している時に起こったというのが共通点である。 77287 しかし似たような編集を再度実行しても問題が再現しないようである点も同様である。 77288 77289 多少 shift の部分に手を加えた。これで解決したかは分からない。 77290 77291 追記: 77292 77293 "単語の先頭に空白を挿入した時に空白が単語の一部になる" バグの修正の際に、 77294 word は必ずしも stat の設定された場所だけに設定される訳ではない、 77295 という事が判明しそれに対する修正を行った。 77296 この修正の前は shift するべきなのに shift されていない単語があった事になる。 77297 この substring expression < 0 の問題もこれに関連していた可能性が高い。 77298 再度 $() 等を入力して色々してみても問題は再現しないようなので、 77299 取り敢えずこの bug に関しても解決したと解釈する事にする。 77300 実際には解決されていないとしても、再び問題が発生した時に考える事にする。 77301 77302 2015-03-08 77303 77304 * cygwin 上で prompt の色がついていない。 [#D0208] 77305 77306 _ble_line_prompt の内容を覗いてみると、 77307 何と ps1out に CSI 99s や CSI 99u が残っている。 77308 また、\e[32m も本来ならば \e[0;32m 等に翻訳されている筈なのにそれがない。 77309 要するに ps1esc がそのまま出力されている様に見える。 77310 出力幅が22桁余分である事から CSI sequence を認識していない様に思われる。 77311 先頭の CSI の部分だけ無視して残りを普通に出力している。 77312 77313 試しに以下を cygwin 上で実行してみた所、失敗する。(linux の上では成功する。) 77314 rex_csi=$'^\e\\[[ -?]*[@-~]' && [[ $'\e[99s' =~ $rex_csi ]] && echo hello 77315 何故だろう。locale の問題かも知れない。と思って LANG=C としたら成功した…。 77316 更にプロンプトにも色が着くようになった…。 77317 77318 然し、LANG=C にしていると今度は日本語があった場合の動作が怪しいのではという気がする。 77319 →実際に日本語を入力してみると大変な事になる。なので一時的にだけ LANG=C にしたい。 77320 実装した。テストは未だしていない。→テストした動くようになった。 77321 77322 * <bug> bash-4.1 以下でカーソルの表示位置がずれている。 [#D0207] 77323 現在のカーソル位置の追跡自体は誤っていない様に思われる。 77324 という事は、移動先の cx cy の算出を誤っているという事か? 77325 77326 bash-4.1, 4.0, 3.2 で起きる。bash-3.0, 3.1, 4.2, 4.3 では起きない。 77327 調べてみると getxy.cur の返す値が変である。 77328 変な値を返している時に _ble_line_text_cache_pos の中身を確認したが問題ない。 77329 と思ったら ((_eoc[2]&&(_pos[0]=0,_pos[1]++))) が駄目であった。 77330 bash のバグで条件分岐内で配列要素を参照できないのであった 77331 (参照するとその branch が必ず実行される)。 77332 77333 * <bug> bash-4.2, 4.0, 3.2, 不完全な編集内容に対してエラーが出る。 [#D0206] 77334 77335 i=${ で駄目。 77336 bash-4.3 では起きない。bash-4.1 でも何故か起きない? 77337 77338 どうも正規表現が正しく動いていない様な気がする。 77339 →これは正規表現中の "'" を無駄に多く escape していたのが原因であった。 77340 '[^']*' で済む所を \'[^\']*\' としていた事による。 77341 然し \' になっていた時の解釈が謎である。例えば以下が一致する。 77342 77343 rex="^([^\$]|\\'[^\\']*\\')+\$" && [[ 'i$' =~ $rex ]] && echo hello 77344 77345 上で 'i$' を '$' にすると一致しない(正常)。 77346 上をこれ以上単純化する事は出来なかった。 77347 77348 何だか良く分からないが \' を ' に修正したら問題は起きなくなったのでこれで解決とする。 77349 77350 * <bug> bash-4.0, 4.1 でプロンプトが表示されない [#D0205] 77351 これは declare DRAW_BUFF としただけの時に、 77352 ${#DRAW_BUFF[*]} が 1 になっている事が原因であった。 77353 77354 * <bug> bash-4.1 以下でプロンプトの色が着かない。。 [#D0204] 77355 何と、_ret="${specs[++i]%%:*}" を実行すると i が 2 増える…。 77356 つまり配列の添字を複数回評価しているという事になる。 77357 77358 色々試してみた。 77359 i=1; _ret="${a[++i]%%:*}" 77360 - a が配列でない場合には起こらない。 77361 - %%:* がない場合には起こらない。 77362 - %%:* の代わりに #a 等でも起こる。${a{++i]#a} では起こらない。 77363 77364 2015-03-07 77365 77366 * ble-decode.sh: CSI Function Key Sequence を特別扱いする? (2015-02-28) [#D0203] 77367 77368 現在の登録作業は些か無駄な事をしている様な気がする。 77369 ble-bind の出力も exaustive になっているし、 77370 テーブルも巨大な物になっていて declare や set の時に見苦しい。 77371 77372 - .ble-decode-char 再実装した。 77373 - それに伴って .ble-decode-char/csi/* も追加し、 77374 CSI シーケンスを特別に読み取る様に変更した。 77375 - また、cmap/default.sh も大幅に変更した。 77376 - 修飾の機能は sendkey の方で一括で行う様に変更する。 77377 C-x @ S 等に対して ESC と同様の修飾の機能を与える。 77378 77379 2015-03-06 77380 77381 * ToDoの整理 [#D0202] 77382 77383 > 2015-02-17 77384 > * for 等の末端が赤くならない 77385 > →コマンドとしての着色によってエラー色が上書きされていた。 77386 > 着色の "レイヤー" に対応できる様にしたい。その後で再度考える。 77387 77388 これは改めて確認してみた所、赤くなっている。 77389 単語の色付けよりも後にエラーの着色を行っている為であろう。 77390 エラーに関しては又後で仕組みを整えるつもりであるが、 77391 特にこの問題に関しては解決済という事にする。 77392 77393 > 2013-06-10 77394 > * <lbug> complete: ~ で始まるパス名の場合、 77395 > ディレクトリ名の末端に / を追加したり、 77396 > ファイル名の末端に SP を追加したりする機能が機能しない。 77397 > これは test -e "$hoge" としてファイル名がどうかを判定している時に、 77398 > hoge の中に含まれている ~ が展開されない為である。 77399 > 同様に ~user で始まる形式のパスについても期待通りに働かない。 77400 77401 これは新しい complete の仕組みの元では問題なく動作している。 77402 単語を eval で評価してから候補を生成している事により見た目の表現には関係なく動作する。 77403 77404 * overwrite-mode に対応 [#D0201] 77405 77406 | 2013-06-06 77407 | * overwrite mode 77408 | + 開始時は insert 77409 | + self-insert, delete-backward-char で対応するだけで OK 77410 | + 現在のカーソル位置を反転して表示する 77411 77412 ble-edit+overwrite-mode 実装、self-insert, delete-backward-char の対応。テスト。 77413 test (overwrite-mode): OK, accept-line 後のリセットOK 77414 test (self-insert): 半角を半角で上書き、全角を半角で上書き、半角を全角で上書き、全角で全角を上書き。 77415 test (self-insert): 行末での半角挿入、行末での全角挿入、改行の挿入 77416 test (delete-backward-char): 編集文字列終端での削除、文字列中途での削除、行末での削除、行頭での削除 77417 77418 TAB や改行が関係する場合の emacs の動作について調べる。 77419 - 改行とタブを挿入する場合は次にある文字を削除する事はしない様だ 77420 - 改行を上書きする事は無い。タブを上書きする時はタブの終端に達する場合にはタブを削除する。 77421 終端に達しない場合にはタブをそのまま保持する。 77422 面倒なので ble では取り敢えずはタブを常に保持する事にする。 77423 77424 →xterm の場合は元からカーソル位置を反転して表示する様になっている。 77425 この状態でカーソル位置の属性を反転させると二重に反転して、カーソルが見えなくなってしまう。 77426 カーソル位置の別の表現方法を考える必要がある。 77427 或いはカーソルの大きさを制御するシーケンスを出す? カーソルを隠すシーケンスを出しても良い。 77428 $'\e[?25l' $'\e[?25h' を発射してカーソルを隠す。 77429 77430 カーソルの反転は layer で行うか、それとも描画部分に対して完全にハードコードするか。 77431 ハードコードする前回書き込んだカーソル位置の情報を再び回復しなければならない。 77432 別に layer として実装した時と比べて実装が楽になる訳でも無い様に思われる。 77433 layer として実装した。無駄に複雑になったように思うが取り敢えずテスト。 77434 - insert を toggle しても即座に反映されてない 77435 →これは .ble-line-draw.update の更新判定に登録するのを忘れていただけ。 77436 - 前の文字の反転が解除されない 77437 前回の buffer の内容を流用しているのが行けないのかと思ったが、 77438 どうやら PREV_UMIN PREV_UMAX の方の問題の様である。 77439 とも思ったがそうでもない。どうも変な動きをすると思ったら、 77440 そもそも上のレイヤーでの更新に失敗している様だ。/update/getg を弄った事が原因だろうか。 77441 確認してみると ble-highlight-layer:syntax/update で 77442 ble-highlight-layer/update/getg を呼び出すべき所で、 77443 ble-highlight-layer/getg を呼び出していた。つまり layer:syntax 側でのバグであった。 77444 77445 ble-highlight-layer/update/getg を呼び出す様に変更してみた物の、それでも何か変だ。 77446 良く考えたら /update/getg でも駄目だ。自分自身を含めないと行けない。 77447 ble-highlight-layer:syntax/getg を呼び出して空だったら ble-highlight-layer/update/getg を呼び出す様に変更した。 77448 - bugfix: PREV_UMAX の計算 77449 insert mode の時に途中を編集するとカーソルの位置が狂う。 77450 C-u を押した時のカーソルの位置が変。 77451 C-u 等、overwrite と関係なく見える物でも起こっているので、別の箇所のバグかと思いきや、 77452 layer:overwrite_mode を外すと上記の現象は起こらなくなる。 77453 色々試した結果 oindex の shift を間違っている所為で PREV_UMAX が変に大きな値になり、 77454 その所為で座標位置が 0 0 にあると勘違いされてずれるという事が分かった。 77455 77456 2015-03-05 77457 77458 * ble-edit.sh (ble-edit/draw/trace): 描画属性も詳しく。 [#D0200] 77459 77460 描画属性の追跡も実装した。 77461 これに伴って、プロンプトの最後の文字の属性も(限定的ではあるが)取得できる様になった。 77462 77463 | 2015-02-23 77464 | * bleopt_suppress_bash_output 制限 77465 | - プロンプト最後の文字の SGR が消える。これに対応するにはプロンプト中の SGR を解析しなければならず大変。 77466 77467 完璧な対応という訳ではないが、これで上の問題は解決された。 77468 77469 2015-03-04 77470 77471 * 修正: 環境での行末での動作 [#D0199] 77472 77473 編集の行が減った時に削除される行が間違っている気がする。 77474 長い行を編集してその行が短くなった時の動作に問題がある。 77475 というか行が減った後のカーソルの表示位置が変だ。 77476 内部的なカーソルの位置(挿入位置)は正しいようだ。 77477 77478 どうも丁度ぴったり columns に収まる時の座標計算の問題? 77479 →カーソルを動かしてみると座標計算自体は問題ないようだ。 77480 やはり前の行の最後の位置にいるにも拘わらず次の行の先頭にいると勘違いしている様に見える。 77481 問題は何故前の行の最後の位置に移動してしまうのかという事である。 77482 77483 % 分かったような気がする。座標計算と部分更新に問題がある。問題点は結構複雑な気がする。 77484 % 現在、update-positions で計算されるのは「次の文字が表示される位置」という事になっている。 77485 % これは指定した位置へカーソルを移動させるのに使う。カーソルの移動先は、 77486 % そこに存在する文字の先頭にあるべきである。 77487 % 77488 % 一方で、部分更新をした後にカーソルが存在している位置、というのは xenl cap のある端末では 77489 % 実は次の文字が表示される位置とは異なっている。 77490 % 行末の文字を出力した時にカーソルはその行の末端に留まっている。 77491 % 所が、update-position に格納されているのは、次の文字の開始位置である次の行の先頭である。 77492 % この時に勘違いが起こる。これを解決するには update-positions に格納されている情報の意味を考え直すか、 77493 % 或いは、update-position とは独立に文字を出力し終わった後の位置の情報も管理するという事である。 77494 % 後者は余り考えたくない。殆どの場合で文字出力後の位置と次の文字の開始位置は同じである。 77495 % 77496 % どの様な場合にずれが生じるかというと、 77497 % 1 行末=次の行頭 77498 % 2 行末近くに wide 文字が存在して入りきらずに次の行へ送られている場合 77499 % 現在の計算だと次の表へ送られる場合は先頭に行末を埋める padding をつける事になっている。 77500 % 例えば " あ" 等としている。この時カーソルの位置は "あ" の位置ではなく行末の空白の位置になっている。 77501 % これはどちらに表示するべきか改めて考えた方が良いかも知れない。この状態で例えば "a" 等と入力すると 77502 % 行末に文字が挿入される事になる。カーソルは依然として "あ" の位置ではなくて行末にあるべきなのかもしれない。 77503 % しかしながら、例えば↑キーで更に次の行の行頭から移動してきた時に、カーソルが二つ上の行の行末に来るのは変である。 77504 % そういう意味から言うとあの先頭にやはり文字を置くべきなのかも知れない。 77505 % 77506 % 少なくとも三種類の位置が存在する 77507 % - 部分更新出力後の位置: 77508 % これは部分更新をした後の座標計算に必要である。 77509 % - 部分更新開始の位置: 77510 % これはカーソルの表示位置とは異なる。例えば行末の " あ" の場合には、 77511 % カーソルの表示位置は "あ" の直前に来るが、 77512 % 部分更新の開始位置は " " の直前になければならない。 77513 % しかし出力後の位置とも限らない。例えば出力後に行末にカーソルがある場合、 77514 % そこから部分更新の出力を開始しようと思っても、そもそも其処にカーソルを移動させる手段がない。 77515 % (xenl の厄介な所は文字を出力した時にだけ行末にカーソルが来る可能性があるという所である。) 77516 % そこ場合は移動先を次の行頭に変更しなければならない。 77517 % - カーソルの表示位置: 77518 % これは次に来る文字が何かに依存する。 77519 % positions の部分更新なども考えるとこれは記録せず、出力後の位置から計算する方が良い。 77520 % 例えば次に改行が来るのであれば行末だし(でも行末にカーソルを移動させる方法はない■)、 77521 % それ以外の文字が来るのであれば次の行頭である。 77522 % 77523 % どの箇所で getxy が呼ばれているかについて確認する 77524 % 意外と呼び出している場所は少ない様である。 77525 % (改めて考えてみればそんな物だろう、というのは 77526 % 元々は update-positions は x y endx endy cx cy 等のシェル変数を通して 77527 % 直接計算した値を返していたからである。つまり、結果は呼出元の関数でしか使っていなかったという事である。) 77528 % 77529 % - 先ず、カーソル位置へ移動する時の cx cy と、 77530 % bleopt_suppress_bash_output= の時にその左の文字 lc を取得する時。 77531 % - 後、描画領域を確保する為の begx begy endx endy 77532 % - それから部分更新の為の umin umax → uminx uminy umaxx umaxy 77533 % - また、矢印キーによる移動の際の移動先の計算 77534 % 77535 % 取り敢えず、_ble_line_text_cache_pos に格納するのは 77536 % その文字の開始位置ではなくて、前の文字の終了位置という事にする。 77537 % その文字の開始位置は前の文字の終了位置から計算する事が出来る。 77538 77539 + bugfix: ascii printable characters の行末で \n を付加した時 ichg に登録していなかった。 77540 と思って update/position を変更しようとしたら新しい事実が発覚した…。 77541 そもそも xenl の場合、行末に来た文字の末尾には \n を付けて、 77542 文字を出力した際に必ず次の行頭に進むように調整をしていた。 77543 しかしながら、ASCII 文字が連なっている場合の最適化として 77544 位置を設定しているループの部分で、「変更文字」ichg のマークをつけていなかった。 77545 これの所為で実際の出力には \n が反映されておらず期待した位置とは異なる位置に 77546 文字が出力されるという事態になっていた。 77547 77548 取り敢えずこれで問題点の一つは解決される事になる。 77549 そしてまた、上の考察で区別しなければならないとしていた部分更新後のカーソル位置と、 77550 部分更新開始時のカーソルの位置の違いがなくなった。 77551 更に、行末にカーソルが来ない事を保証しているので、 77552 部分更新開始時の位置として行末が来た場合に其処にカーソルを移動できないという問題にも引っかからない。 77553 (結局、\n を末尾に追加するというのは特に重い処理でもなく、 77554 また実装も面倒ではなく、そもそも実装されていたというのが考察の上での穴であった。) 77555 77556 上記の部分を修正してテストしてみた所、表示がずれるという問題は解消された。 77557 しかし問題(といえるかどうかは分からないが)は未だ残っている。 77558 行末に入りきらなかった wide character の先頭に移動した時のカーソルの表示位置である。 77559 77560 + bugfix: _ble_util_string_prototype の長さ指定に 0 を指定していた 77561 試してみたらかなり微妙な事になっている…。空白が挿入されていない! と思ったら 77562 x=cols を設定した後に空白を挿入していた。修正した。このバグはこの前全く同じ物を潰したような気がするが…。 77563 →検索してみたら結構色々な所に似たようなコードがある様だ。(余り良い事とは言えない…) 77564 77565 また、これに伴って意図的に terminal の幅を縮めた時の折返しの処理も正しくされる様に、 77566 xenl の時に (本当の端末の端にいる時には敢えて付加しなくても良かった) \n を付加する様に変更した。 77567 77568 更に、^? や ^A 等の特殊な制御文字の場合についても追い出しを実行する事にする。 77569 (bash の readline ではこれらの特殊文字の表現に関してはわざわざ追い出しはしないようだが。) 77570 77571 また、行末付近での tab の取り扱いについても変更を行った。 77572 特に一番右端にいる場合には " " + 改行を入れる。 77573 (所で ble-edit/draw/trace の方の tab の取り扱いも同様の問題があるのでは、 77574 と思って確認してみた所こちらについてはちゃんと実装されていた…。) 77575 77576 先ず _ble_line_text_cache_pos の形式を変更した。今迄は "x y" だったが、 77577 更に、入りきらない文字が追い出しされたかどうかを判定する為に "x y wrapping" とした。 77578 wrapping=0 が通常の文字 (出力開始位置とカーソルの位置が同じ) で、 77579 wrapping=1 が行頭に押し出された文字 (出力開始位置は前の行の最後、 77580 カーソルの表示位置は行頭) を表す物とする。 77581 カーソルの位置を取得する場合には wrapping を見て、((x=0,y++)) 等とする。 77582 77583 更に、出力位置の制御に用いる getxy とは別に 77584 カーソルの表示位置を制御する getxy.cur を用意した。 77585 カーソル移動などの際に参照するのは専ら getxy.cur である。 77586 また get-index-at 関数も getxy.cur を参照する様に変更した。 77587 77588 テスト: と、実装してからテストしてみたがずれている…。 77589 % 改めてみてみると wrapping の格納位置がずれている。 77590 その文字が wrapping の対象となるかどうかは、その文字を処理してからでないと分からない。 77591 従って、その文字の終端の境界に wrapping の情報を格納する現在の実装は正しい物である。 77592 寧ろ、参照する時に「現在の文字の位置」ではなく「次の文字の位置」の wrapping を参照するべきである。 77593 →この修正で自然な動作をする様になった。 77594 77595 * ble-edit.sh: プロンプト内の job count 等の情報が更新されない。 [#D0198] 77596 →新実装で取得したデータのキャッシュを local に設定するのを忘れていた。 77597 77598 * ble-decode.sh (stty): -icanon の設定。 [#D0197] 77599 77600 何故か bless を起動してその儘抜けると入力しても反応しなくなる 77601 →無限ループに陥っているのかと思ったらそうではない様だ。 77602 →どうも入力が buffering されている様で C-d を押した時に初めて入力が読み取られ、 77603 それまでに入力した内容が一気に書き込まれていく。 77604 →stty で bless 前後を比較してみると stty -icanon が stty icanon に変わっている。 77605 stty -icanon を設定し直したら正常に表示される様になった。 77606 stty.enter で -icanon も設定する事にする。 77607 77608 2015-03-03 77609 77610 * ble-edit.sh: prompt 再実装 [#D0196] 77611 77612 | 2013-06-06 77613 | * <bug> PS1 に $() などが含まれているとプロンプト位置を正確に計算する事が出来ない。 77614 | _ps1txt の方を eval してから再度位置の計算をする? 77615 | →それだと _ps1txt, _ps1esc の両方について $() の展開をしなければならない。 77616 | つまり、$() が2回実行される。これは意図しない動作になるかもしれない。 77617 | 77618 | 例えば \[ ... \] を [ - ] などに変換して出力し、 77619 | その後で [ ... ] を除いた物を用いて位置の計算をする? 77620 77621 この問題が未だ解決されていなかったので。 77622 bash の PS1 に対する振る舞いも確認して再実装した。 77623 bash 内部では先に \? の部分だけ展開して、 77624 その後で "" に全体を入れて eval している様な振る舞いをする様だった。 77625 それに従って再実装を行った。幅の計算は eval の後に行う事にした。 77626 \? の解決と幅の計算を独立させた事により、実装は却ってすっきりとした物になった。 77627 77628 | 2015-02-23 77629 | 77630 | * <最適化> プロンプト構築 77631 | 77632 | 改行を押し続けた時の反応が遅い 77633 | プロンプトの更新を停止すると動きが速くなる。 77634 | これはプロンプトの生成に時間が掛かっているという事。 77635 | 見てみるに高速化できる余地はそんなに無い様な気がする。 77636 | jobcount を実行するのに subshell 実行が必要なのは気にはなるが。 77637 77638 新実装に移行した後に再度確認してみたが、それ程気にならないのでこの問題は破棄する。 77639 新実装になった事で速くなったのかも知れないし、 77640 あるいは変わっていないが気分の問題で気にならなくなっただけかも知れないが。 77641 77642 77643 * ble-edit.sh, ble-edit.color: discard-line の際に着色 [#D0195] 77644 77645 | 2013-06-02 77646 | * ble-edit+discard-line: 灰色にする 77647 77648 * ble-edit.sh: bugfix, 複数行で上に行けない [#D0194] 77649 →_ble_line_begx _ble_line_begy に編集内容の開始点を格納する様に変更。 77650 77651 * ble-edit.sh: bugfix, 複数行なのに空行の accept-line でのずれ量が1行になっている [#D0193] 77652 →行を更新した後に _ble_line_x=0 _ble_line_y=0 を設定する必要。 77653 77654 2015-02-28 77655 77656 * <bug> 履歴項目を移動中色が更新されない例を発見 [#D0192] 77657 77658 "[[ ; == \; ]]" から "arr=(a b<a c)" に移動した時、初めの 2 文字の色がそのままだ。 77659 これは良く考えたら word による着色を消していない事と関係がある。 77660 特に上の二つの文字列は長さが一致しているので、shift を呼び出しても 77661 shift の実行が省略される為に中身がクリアされない。 77662 これは word 着色のバグ解決の時に解決されるはず。 77663 77664 長さが一致していても shift を実行する事にする。 77665 shift によって途中の編集部分がクリアされる方が動作として自然だからである。 77666 或いは、途中の編集部分に何が入っているか未定義、という事にしていると、 77667 一々使う側でクリアしなければならないからである。 77668 編集部分で前の属性などを保持するのは不自然であるし、 77669 使う側でクリアするよりは shift の内部で行っている様な繋ぎ替えの方がコストが小さい。 77670 77671 →結局 shift 長さが変わらない場合でも shift を実行するように変更した。 77672 77673 * 初期化最適化: ble-bind が遅い [#D0191] 77674 77675 どうも ble-bind の遅さが、後続の bashrc をも遅くしている様である。 77676 手軽に ble-bind を呼び出す事ができないのは致命的なので performance の悪さについて調べる。 77677 どうも調べてみると ble-getopt が遅い様に思われる。 77678 手で解析を書いて試してみる…(面倒だ。似たようなコードを何度も書かなければならない。 77679 確かに ble-getopt の様な仕組みを作りたくなる物である。) 77680 77681 ble-bind を ble-getopt なしで書き直してみる。 77682 今回は ~/.mwg/bashrc にある 7 つの binding について試してみる。 77683 1 ble-bind (old, using ble-getopt) 122ms - 100ms = 22ms 77684 2 ble-bind (new) 87ms - 78ms = 9ms 77685 新実装の方が半分以下の時間で実行できる様になった。 77686 これで現在 87ms で bashrc がロードされる様になった。 77687 77688 所で ble-bind が全体でどれぐらいの割合を占めているかについても概算しておく。 77689 ble-bind が 9/22 の速さで実行できる事によって全体で 122 - 87 = 35ms 短縮している。 77690 (ble-bind old 時間) * 13/22 = 35ms なのだから、(ble-bind old 時間) = 59ms という事になる。 77691 実に半分を ble-bind が占めていた事になる。残りの 63ms が他の処理である。 77692 現在は全体で 87ms に迄減った。63ms (他) + 24ms (ble-bind) という形である。 77693 77694 また、新しい実装についてより分かり易く実装できないかと、各オプションを関数に分けてみた。 77695 結果、94ms - 83ms = 11ms であった。それ程遅くはなっていない。 77696 他のコマンドのオプションを作る時にはこれを参考にしても良いだろう。 77697 77698 さてこれで ble-bind の速度は割合改善したがそれでも定数倍である。 77699 本当はもっと速くなって欲しい。改めて現在時間の掛かっている部分の特定をする。 77700 引数の解析部分を飛ばして直接呼び出して速度を確認すると、 77701 83ms - 76ms = 7ms であった。という事は引数の解析は 2ms しか費やしていない。 77702 今度は実際の登録部分について最適化を試みるべきであろう。 77703 77704 特に気になっているのは ble-decode-kbd の部分である。 77705 試しに ble-decode-kbd を再実装してみたがそんなに時間は変わらない。 77706 全体で 83ms である。元々 85ms であったから 2ms しか変わっていない。 77707 特にテストに使っている部分 (7ms) に限って言えば大体 2/3ms 程度しか速くなっていないという事。 77708 別の部分で時間が掛かっているという事だろうか。 77709 試しに ble-decode-kbd 単体の速度を測ってみる事にする。 77710 | time for ((i=0;i<1000;i++)); do ble-decode-kbd C-,; done → 292ms 77711 | time for ((i=0;i<1000;i++)); do ble-decode-kbd M-down; done → 295ms 77712 | 7 * 0.294ms = 2ms なので、全体の内 2/7 がこの ble-decode-kbd であると分かる。 77713 バグがあった。修正したらかなり変わった。 77714 | time for ((i=0;i<1000;i++)); do ble-decode-kbd C-,; done → 230ms 77715 | time for ((i=0;i<1000;i++)); do ble-decode-kbd M-down; done → 375ms 77716 正規表現によるマッチは結構重い?? 77717 →正規表現ではなく ${key//[...]/} を用いて試したら 375 → 257ms 迄速くなった。 77718 所で、長さが 1 である事を確かめるならば、 77719 算術式で長さを求めてから比較するよりは glob の pattern で一致させた方が速い様だ。 77720 所で、旧実装を削除する前に改めて速度を測っておく。 77721 →C-, に対しては 346ms, M-down に対しては 670ms である。 77722 全体の内 3.070ms / 7ms である。またこの事からこれ以外の部分に 4ms かかるという事が分かる。 77723 | time for ((i=0;i<1000;i++)); do ble-decode-kbd C-,; done → 231ms 77724 | time for ((i=0;i<1000;i++)); do ble-decode-kbd M-down; done → 257ms 77725 | → bashrc の 7 bindings に対し大体 1.667ms / (4+1.6)ms。大体 5/17 を占める。 77726 77727 その他の部分で怪しいのは .ble-decode-key.bind である。 77728 押されるキーの数×2 の eval を実行している。 77729 しかしこれはどうしようもないので取り敢えず諦める。 77730 77731 * ble-edit.sh: bugfix, .ble-line-info.clear で位置がずれる [#D0190] 77732 77733 描画後の座標値の設定時に存在しない変数 x y を参照していた。これらは 0 であるべき。 77734 77735 * 初期化の最適化 [#D0189] 77736 77737 現在の初期化のボトルネックは圧倒的に history である (2015-02-09) 77738 →.ble-edit.history-load を多少最適化した。読み取り時間が約半分になった。 77739 それでも未だ全体の半分が history 読み取りである 77740 (しかし history を 16k も溜めている場合は少ないから、実際は無視できるかも)。 77741 77742 | 改めて初期化の時間を調べる: 77743 | 多少なりとも時間が掛かっているのは以下の phase 77744 | - ble-core.sh 58ms 77745 | - ble-edit.sh 629ms (554ms が history, 75ms が他) 77746 | - ble-decode-bind.cmap 52ms 77747 | - ble-decode-bind 105ms 77748 | - .ble-edit.default-key-bindings 229ms 77749 | - .ble-edit-draw.redraw 35ms 77750 | 77751 | default-key-bindings を見るに ble-bind に平均 229/75 ms かかっている様だ。 77752 | これを考えると ble-edit.sh の中の 33ms も ble-bind の遅さに起因する。 77753 77754 改めて初期化の時間を計る (2015-02-28) 77755 前回から、初期化と attach の分離、history 遅延ロードの実装など、 77756 初期化の順序・構成が変化した。 77757 77758 1 ファイルの読込 | 39ms 77759 2 ble-initialize 77760 ble-decode-initialize | 53ms 77761 .ble-edit.default-key-bindings | 309ms -> 4ms 77762 ble-edit-initialize | 4ms 77763 3 ble-attach 77764 ble-decode-attach | 201ms -> 55ms 77765 ble-edit-attach | 0ms 77766 .ble-edit-draw.redraw | 36ms 77767 77768 ble-decode-initialize は ble-decode-bind.cmap の現在の名前と思って良い。 77769 これのロード時間は大して変わっていない。 77770 この部分は基本的にファイルにキャッシュした配列を読み取っているだけである。 77771 しかしその容量が大きい為にこれだけの時間が掛かっている。 77772 CSI Function Key が大半を占めているので、これらを特別扱いする様にすれば多少は解消するかも。 77773 77774 .ble-edit.default-key-bindings は前回よりも大幅に増えている。 77775 これは多少の bindings の追加を行った事もあるが、 77776 keymap isearch などの初期化を .default-key-bindings に統合した事もある。 77777 →これもファイルに dump を出力する様にした。これは 4ms と嘘のように軽くなった。 77778 ble-bind 自体に問題があるのかもしれない…。 77779 77780 ble-decode-attach は前回に比べて大幅に増えている。 77781 これは bash-4.3 で ESC [ ... に bind する為に、 77782 全ての可能性に対して bind を実行している為であろう。 77783 (しかしそれでも元々 100ms 程度かかっていたのでここを直しても劇的に速くなるという事はない)。 77784 更に詳しく調べる。既存の bind の保存と削除は 31ms で済んでいる。 77785 全組合せに対する bind は 77ms 掛かっている。メインの bind に 91ms かかっている。 77786 実はこの部分をこそ最適化するべきなのかも知れない。 77787 →既存の bind の保存と削除の部分は awk の呼出が2回に渡っているのを1回にくっつけた。 77788 この部分は時間を計測してみたが 31ms の儘で変化しなかった。 77789 →結局全組合せに対する bind はしないで代わりに ESC [ を utf-8 で翻訳する方向にした。 77790 →また、メインの bind はコマンドを生成するのに時間が掛かっている様に思われたので、 77791 先にコマンドを生成してファイルにキャッシュする様に変更した。 77792 その為に新しく bind のコマンドを生成する為のファイル ble/bind.sh を作成した。 77793 結果として元々の 201ms から 55ms に迄ロード時間を減らす事ができた。 77794 77795 これで一通り重い場所は解決したように思うので解決とする。 77796 77797 * ble-decode.sh (.ble-decode-bind/generate-source-to-unbind-default): awk 呼出を一回に統合。 [#D0188] 77798 77799 | * 既に bind -x してある物を削除するという事? 77800 | bash-4.3 では bind -X が実装されたので bind -x した物を列挙できる。 77801 | (但し、bind -r しても bind -X のリストには残ってしまう様だ @bash-4.3.33 77802 | リストには残っているが実際には削除されている。) 77803 77804 同時に上記の項目 (2015-02-09) も実装した。 77805 77806 * ble-core.sh, ble-color.sh: .ble-shopt-extglob-push/pop/pop-all 廃止 [#D0187] 77807 77808 ble-color.sh で、extglob を使った部分のコードの管理が 77809 好い加減面倒なので正規表現による実装に切り替えた。 77810 (そもそもこの部分は現在は使われていない部分ではあるが。) 77811 77812 さて、.ble-shopt-extglob-push/pop/pop-all 関数は 77813 この部分でしか使われていなかったので削除してしまう事にする。 77814 別にそう大した実装でもないので。 77815 77816 * history 遅延ロードについて [#D0186] 77817 77818 これから本格的に常用する為にはできるだけ速くロードできる様にしたい。 77819 特にボトルネックになっているのは history である。 77820 history の遅延ロードの可能性について考える。 77821 77822 現在の実装では history がロードされている事を前提にして書かれているので、 77823 できるだけ history の項目に触る前に history がロードされる事を 77824 保証する様に書き換えなければならない。 77825 特に history の interface を絞る事によって移行しやすくする事を考える。 77826 77827 現在の所どの様な場所で history が参照されているかを確認する。 77828 先ず現在の history 項目の数を幾つかの場所で参照している。 77829 実はこれは HISTCMD 変数を用いて参照する事ができるのではないか? 77830 77831 HISTCMD は代入してもその効果がなくずっと history に登録されている項目の数を指している様に見える。 77832 と思って実際に ble.sh を起動して確認してみると常に 1 という値になっている。これは困った。 77833 しかし何故明示的に unset している訳でもないのに HISTCMD=1 なのだろうか。 77834 これは rcfile で読み取っている事にも関係しているのだろうか。。 77835 →判明した bind -x の内部で HISTCMD を参照すると 0 になっていると言う事の様だ。 77836 77837 という事は HISTCMD を参照する事によって history 項目の数を取得するというのはできないという事だ。 77838 別の方法を考える…。どうやら count=($(history 1)) で取得した値が、 77839 実際に history からロードした時のエントリの個数と一致する様である。 77840 という事は count=($(history 1)) を必要になった時に一回呼び出して、 77841 後はそれを maintain (increment するなど) すれば問題ないという事になる。 77842 77843 更に history-add の時にもロードを遅延させる事は出来ないかと考える。 77844 その為に history -s の動作について確認しておく。 77845 - history -s を使っても HISTCONTROL は考慮に入れられる様だ 77846 従って、ble.sh の側で HISTCONTROL の処理をしなくても済む。 77847 逆に現在の history 項目の数は分からなくなる。 77848 history が追加されたのかされていないのか分からないから。 77849 返却値も確かめてみたが、重複によって登録されなかった場合でも 0 (正常終了) する様である。 77850 77851 対応できそうなので遅延ロードに対応する事にした。実際の修正は意外と小規模で済んだ。 77852 未だ、何処かに取りこぼしがあるかも知れないがそれは問題になってから対処する事にする。 77853 77854 2015-02-27 77855 77856 * <bug> bash-3.0, bash-3.1 [#D0185] 77857 77858 何故かパス名展開がされない: echo * としても * がそのまま表示される。 77859 echo $- としても f はついていない。 77860 何故か分からないが unset GLOBIGNORE したら直った。 77861 (GLOBIGNORE には何も設定されていない様に見えるのに) 77862 77863 →ble-decode-kbd の local GLOBIGNORE を削除したら直った。 77864 77865 * bash-3.0 対応 [#D0184] 77866 77867 bash-3.0 では += 演算子が使えない。また、${#param} が文字数ではない。 77868 77869 これらの事から対応を諦めていたが、 77870 += 演算子については調べてみたらそんなに使っていない様だ。 77871 77872 grc '\+=[("'\'']' --exclude=test --exclude=out --exclude=ble.sh 77873 77874 term.sh (varnames), 77875 ble-syntax.sh (completion-context context, _ble_highlight_layer_syntax3_list), 77876 ble-core.sh (ble-stackdump message), 77877 ble-decode.sh (.ble-decode/keymap/push, ble-decode-kbd keymods) 77878 ble-edit.sh (_ble_edit_accept_line, _ble_line_text_cache_ichg, _ble_edit_isearch_arr) 77879 77880 面倒になったので ble/util/array-push という関数を作って、 77881 速度に関係なさそうな所ではそれに置き換えた。 77882 (注意しなければいけないのは、array-push を使う時は、 77883 配列要素が 0 から順に割り振られている必要があるという事。 77884 専ら push のみを用いて要素を追加する場合には問題はない。) 77885 77886 さて bash-4.3 で問題なく動いているか確かめてみると、TAB を打った時に表示がずれる。 77887 →これはまた別のバグであった。別項目として独立して解決。 77888 77889 今度は bash-3.0 で起動してみる。すると、沢山のエラーが発生している。 77890 何より unknown ble edit function と表示されてそもそも関数が登録されていない様だ。 77891 ble/util/isfunction が悪いのかと思って調べたがちゃんと動いている。 77892 改めてエラーメッセージと ble-bind を照らし合わせると…そもそも ble-getopt が駄目なのかも。 77893 77894 →何と…。 77895 local a=($command) 77896 上の実行結果が a="($command)" というのと同じになっていた。以下の様に -a を指定する必要がある: 77897 local -a a=($command) 77898 77899 さてこの様な使い方をしている所は正直沢山ある。以下で列挙できる。 77900 grc '(local|declare) [a-zA-Z_][a-zA-Z_0-9]*=\(' --exclude=out --exclude=test --exclude=ble.sh 77901 特に ble-decode.sh の中にあるのは致命的なので、取り敢えずそれだけは直しておく。 77902 また ble-core.sh や ble-getopt.sh に関しても起動に致命的な影響を与えるので修正する。 77903 77904 さてそれでも ble-decode が動いていない様に見える。 77905 noattach の状態でもエラーが出ているのでそれを手がかりに原因を探る。 77906 どうも .ble-edit.default-key-bindings の中でエラーになっている。 77907 しかも其処で死んでいて、続きの初期化が実行されていない?? 77908 この中でやっているのは ble-bind の呼出だけである。 77909 という事は ble-bind に未だ問題点があるという事だろう。 77910 何と初回の ble-bind で既に死んでいる。。 77911 →ble-decode-kbd の中の同様の配列の初期化が悪かった様だ。先程 grep した正規表現では不十分だった。 77912 grc '(local|declare|readonly|typeset)[^-]* [a-zA-Z_][a-zA-Z_0-9]*=\(' --exclude=out --exclude=test --exclude=ble.sh 77913 77914 この修正で取り敢えず起動はする様になった。 77915 しかし、少し弄るだけで簡単に無限ループになる。やはり上記の配列の初期化を全部修正しないと駄目なのだろうか。 77916 →仕様がないので配列の初期化を全部修正してみたら意外とすんなりと起動した。 77917 普通に色も着いているし問題は起こっていない様に見える。 77918 但し、.ble-line-info.draw の表示が少し狂っている様に見える。 77919 77920 後ファイル名の補完候補を列挙できていない。 77921 77922 何と…初期化内容に括弧があると local/declare -a に失敗する。 77923 a="1(2" 77924 declare -a b=("$a") → エラー 77925 b=("$a") → これはOK 77926 local/declare は文法的に特別な処置を受けて折らず唯単に文字列の引数を受け取っているという事だろうか。 77927 再び大幅な書き換えが必要になりそう…。→結局全部書き換えた。 77928 77929 改めて bash-4.3 で起動してみると補完候補の表示が狂っている。 77930 今迄の書き換えで何処かミスしたという事だろう。。 77931 .ble-line-info.draw を潰すと何も問題はない様なので、 77932 .ble-line-info.draw の中か関連した所が怪しい。 77933 そもそも .ble-line-info.draw が表示されている箇所がおかしい。 77934 .ble-line-info.draw が表示されている箇所に対する相対位置としては最終的なカーソルの位置は正しい。 77935 という事は何処かで座標計算がずれているという事。 77936 77937 多分分かった…bash-3.0 の declare で吐き出した term.sh のキャッシュが間違っている。 77938 →当たりだった…。bash-3.0 は _ble_term_ind (内容は $'\n') について、 77939 | _ble_term_ind="\ 77940 | " 77941 という風に出力していて、成る程そういう扱い方もあるのか、等と思っていたが、 77942 上記のコードは "" となる(改行は消える)。試しにやってみると…やはりそうだ。 77943 | $ echo "a\ 77944 | $ b" 77945 | ab 77946 つまり bash-3.0 の declare -p は信用できないという事である。修正した。 77947 77948 * <bug> TAB 等の変更文字があった場合に文字列が表示されなくなる [#D0183] 77949 77950 bash-3.0 対応の時に _ble_line_text_cache_ichg 関係を書き換えテストした時に発見したバグ。 77951 色々試してみるとこれは今回の変更とは関係ない様に見える。今迄のコードに直しても再現する。 77952 また、_ble_line_text_cache_ichg の登録を止めるとまた異なるずれ方になるので、 77953 これは _ble_line_text_cache_ichg の登録に失敗しているのではなく、 77954 _ble_line_text_cache_ichg を使用している側で失敗しているのではないかと思う。 77955 →確認してみたが、置き換えに失敗しているという事は無い様だ。 77956 という事は、座標計算を間違っている可能性の方が高い。 77957 改めて ichg を設定している側に戻って座標について確認してみる。 77958 良く分からないので、やはり適用している側に行きそこで _ble_line_text_cache_pos を出力する。 77959 この部分についても何も問題はない様に見える。 77960 →もしかして出力している物が間違っている? 77961 と思ったら空文字列を出力していた…。 77962 元々 .ble-line-text/update で HIGHLIGHT_BUFF に指定された物を使って出力していて、 77963 .ble-line-text/update の後で slice によって出力内容を取得する様に変更したのが原因だった。 77964 変更文字があった場合には HIGHLIGHT_BUFF の示す先をローカル変数 buff に置き換えて 77965 その場で出力させていた。当然ローカル変数は他の関数 /slice を呼び出した時には 77966 残っていないので空文字列 (或いは、呼出元で buff が定義されていればその内容) が出力される事になる。 77967 変更文字があった場合にローカル変数に書き込むのは止めて、グローバルに変数を用意して其処に書き込む事にした。 77968 77969 * <bug> bash-3.1 日本語の色付け・描画が変だ [#D0182] 77970 77971 何と日本語が含まれている時の BASH_REMATCH が変だ…。 77972 一致を試みる際には文字数でカウントして、しかし結果は 77973 バイトオフセットで切り出しているという具合に見える。 77974 77975 と思って色々試したらどうも自分で指定している SGR 指定ですら変な事になっている。 77976 もしかして BASH_REMATCH 等の問題ではなく、単に自分の新しいコードの問題か? 77977 と思ったが 4.0 4.3 では問題は起きていない。3.2 でも問題は起きていない。 77978 これはやはり 3.1 固有の問題である様だ。 77979 77980 よく考えたら SGR 指定で変な事になっているのは、SGR の出力に問題があるというよりは 77981 その前後に変な文字 (UTF-8 の不完全なシーケンス) がある所為で、 77982 SGR の先頭の ESC 等が食われてしまっている事による物と推察される。 77983 さて、描画に用いている文字は基本的に _ble_line_text_cache_cs から来ている。 77984 そして、_ble_line_text_cache_cs に格納されている文字は 77985 ${text:i:1} によって取り出した物である。問題があるとすればこの辺りだろうか。 77986 77987 試しに a='ああ' として見て色々試したが問題がある様には見えない。${a:ofs:len} は勿論の事、 77988 ${#a} も正しい値を返している。取り敢えずは保留という事にする。 77989 念のため、最後に新しく実装した.ble-line-text.construct が悪さをしている訳ではない 77990 事を確かめる為に古い関数に戻して試してみる。やはり古い関数でも同様に変な風になっている。 77991 従って、新しい実装が悪さをしているという訳ではない。 77992 77993 →何と ${#BASH_REMATCH[n]} がバイト数になる様だ…。 77994 以下を実行すると、通常時は正しく日本語の文字数で数えているが、 77995 BASH_REMATCH の中ではバイト数になっている。 77996 77997 local text='あいう' 77998 [[ $text =~ ^.+$ ]] 77999 echo "#${text} = ${#text}, #${BASH_REMATCH[0]} = ${#BASH_REMATCH[0]}" 78000 78001 | ${BASH_REMATCH[0]:ofs:len} 等は問題なく動いている様なので謎だ。 78002 | 別の変数に再代入しても問題は続く。 78003 | 一旦 ${BASH_REMATCH[0]:0} 等として別の変数に移せば問題ない様だ。 78004 と思ったら関係ない様だ。 78005 78006 % if ((_ble_bash>=30200)); then 78007 % function ble/util/modify-bash31-rematch { 78008 % : 78009 % } 78010 % else 78011 % # In bash-3.1, BASH_REMATCH returns corrupted string 78012 % # when multibyte characters are matched. 78013 % function ble/util/modify-bash31-rematch { 78014 % local i iN="${#BASH_REMATCH[*]}" 78015 % for((i=0;i<iN;i++)); do 78016 % BASH_REMATCH[i]="${BASH_REMATCH[i]:0}" 78017 % done 78018 % } 78019 % fi 78020 78021 →色々試して、漸く問題点が分かった。これは BASH_REMATCH だけの問題ではなく、 78022 ${#配列[n]} 全般で起こる問題である。この形式で要素の長さを取得すると 78023 文字数ではなくバイト数が取得される。 78024 ${#配列} の様にして第一要素の長さを取得する場合は問題にはならない。 78025 (結構重大な問題だと思うが bash の ChangeLog には fixed された等とは書いていない様だ。 78026 一応 3.0 → 3.1 で ${#param} の場合にバイト数ではなく文字数を返すように修正された様ではある。) 78027 78028 取り敢えず以下で問題のありそうな部分を列挙する 78029 grc '#[a-zA-Z_][a-zA-Z_0-9]*\[[^@*]' --exclude=test --exclude=out --exclude=ble.sh 78030 78031 一番多いのは ${#BASH_REMATCH[0]} なのでこれは単に ${#BASH_REMATCH} と書き換えれば良い。 78032 次に多いのは、その場所に一致したかしていないかの判定 ((${#BASH_REMATCH[n]})) である。 78033 これは [[ ${BASH_REMATCH[n]} ]] 等に書き換えてしまえば問題ない。 78034 こういった物を除いていったら本当に ${#BASH_REMATCH[n]} を使っている場所は 11 箇所のみであった。 78035 これならば何とか対応できる。対応した。 78036 78037 これで着色の問題に関しては解決した。しかし、今度はカーソルの移動の度に C だとか D だとかの、 78038 カーソルの移動方向に対応した文字が出力される。term.sh のキャッシュの読み取りに失敗しているという事だろうか。 78039 →分かったような気がする %d の置換に失敗しているのではないか? 78040 →やはりそうだった 78041 $ aa=123%d4 78042 $ echo "${aa//%d/@}" 78043 $ echo "${aa//'%d'/@}" 78044 123%d4 78045 123@4 78046 78047 下のように %d を '' で括っておけば問題ない様なのでこれで行く事にする。 78048 しかしそうすると、visible-message も壊れているのでは…。 78049 以下で問題の有りそうな所を列挙して修正する。修正した。 78050 78051 grc '//%' --exclude=test --exclude=out --exclude=ble.sh 78052 78053 * 文脈に応じた complete [#D0181] 78054 78055 syntax の update はいつ行うか 78056 78057 | これに対応する為には描画時以外にも syntax の update を実行できる様にしなければならない。 78058 | その為には 78059 | 1. ble-syntax/parse を独立に実行できる様にする 78060 | 2. update-positions や描画なども含めて文脈補完時に実行する 78061 | 3. 実は ble-syntax/parse は up to date になっている筈? 78062 | 78063 | もし 2. の描画が無駄にならないのであれば実装でしても良いが、 78064 | 補完時には確定部分を挿入するので再度後で解析し直しが必要になる。 78065 | 3. は補完関数を直接 bind している時には正しいが、 78066 | 実際には内容を変更してから補完を呼び出すという使い方をシェル関数でするかもしれない。 78067 | 78068 | 更新の必要がなければ更新しないだけなので、余分に更新を試みるのは悪い事ではない。 78069 78070 やはり当初の考え通り 1 の方向性で行く事にする。 78071 78072 次に補完を行う文脈をどの様に判断するかについて 78073 78074 文脈に応じた補完と言っても、どの様に文脈を判断するのかが問題になる。 78075 できるだけ補完点の後の情報に依存しないようにするのが望ましい。 78076 例えば arr=hoge となっている時に ar の点で補完を開始しようとしたとする。 78077 もし現在居る単語の種類を元にして補完を行おうとすると、 78078 現在の単語は変数の代入であるから変数の代入に出てきそうな単語しか補完候補に現れない。 78079 もし ar で始まるコマンド名に補完したいと考えている場合にはこれは不便である。 78080 78081 実際に挿入をしながら補完を行う場合については、 78082 普通カーソルより後の部分は現在入力している物と関係ないと考えるのが自然である。 78083 というのも挿入を続ける事によって、挿入点以降の文字列の文法的意味は次々に変わっていくからである 78084 現在の入力状態で挿入点の次にある文字列が補完対象と同じ単語の中に含まれている様に見えても、 78085 挿入が其処で終わるとは限らないのでどんどんと挿入を続けていけば軈て別の単語になるなど。 78086 何れにしても、挿入点より後の情報を用いて補完するのは直観的でないという事である。 78087 なのでルールとして以下を設ける 78088 @ 挿入点より後の文字列は補完内容の決定に使用してはならない。 78089 78090 次に現在の attr を使用して補完方法を決める事について。 78091 結論から言うとこれは使えないのではないかと思う。 78092 先ず、エラーがある場合には attr にはエラーが設定される。 78093 エラーが発生した時には別の配列にエラー情報を記録するように設計を変更したとしても、 78094 attr は未だ0文字も入力していない場合 (例えば ${ の直後) などでは文脈の判断に使えない。 78095 ${ の直後には変数名が来る事は明らかであるので、例え何も入力していなくても補完候補が出せた方が良い。 78096 @ attr は補完の文脈の決定を行うのには使わない。 78097 78098 とすれば残るのはやはり直近の stat の状態である。 78099 stat は解析の再開に用いられる物であるから、 78100 次にどの様な文法的要素が来るのかを規定するのに充分な情報を持つ。 78101 但し、問題点は stat は解析結果ではなく解析を行う為の情報に過ぎない事である。 78102 この事から、stat を用いて補完を実行する為には、 78103 解析に極めて近い所まで処理する必要が出て来るという事である。 78104 78105 complete 側でこれを処理するのは面倒だし、 78106 また、ble-syntax/parse で用いている stat の形式に大きく依存するので、 78107 これは ble-syntax 側で実装する方が適当である。 78108 つまり ble-syntax 側で指定した位置が文法的にどの様な物を期待する物なのかを決める。 78109 実際の補完候補の決定などは ble-edit 側で行えばよい。 78110 78111 78112 実装1 取り敢えず実装してみる 78113 78114 取り敢えず簡単の実装の為に、プログラム補完は考えない事にする。 78115 補完をする為に必要な情報は何か。。 78116 補完の際に行う事が何かを考えそれを元に必要最低限の情報について考える。 78117 78118 - 補完候補を表示する → 表示される文字列 78119 この為には補完候補の一覧が取得できれば良い。 78120 但し注意しなければならないのは、 78121 表示される補完候補と実際に補完される単語が一致しているとは限らないという事である。 78122 例えば、 a/b/c/ ディレクトリの下にあるファイルを保管しようとしている時、 78123 全ての補完候補に a/b/c/... とディレクトリ名が付いているのは煩い。 78124 普通は a/b/c/ 以下のファイル名の部分しか表示しない物である。 78125 78126 - 一意確定部分を求める → 追加挿入される文字列 78127 共通一致部分。これの為にはこれから挿入しようとしている内容が必要。 78128 78129 文脈によっては何らかの方法で共通一致以外の確定方法があるかもしれない。 78130 この時にはこれから挿入しようとしている物の内容は不明である…。 78131 というか様々な種類の確定方法が混在していた時に、それらをまとめて 78132 一つの答えを出すという操作は慎重に考える必要がある。 78133 どんな候補の場合にも確定できる方法と言えば 78134 やはりこれから挿入しようとする文字列を各候補に生成させる事である。 78135 78136 特に意識したいのは曖昧一致による確定である。この場合には決定した時に 78137 既に入力した部分も含めて置き換えが行われる。 78138 これに対応するには、挿入される文字列などではなくて、 78139 既に出力されている部分も含めての置き換えを提出させるのでも良いかも知れない。 78140 その様にすればより自由度は向上する。しかし、問題は、 78141 異なる補完開始点を持つ候補が混在している場合である。 78142 その様な場合に共通一致部分を計算したり曖昧一致を計算したりするのは可能か? 78143 78144 所で、曖昧一致と先頭一致では区別して、先頭一致の方を優先させる等の処理をしたい。 78145 例えば、先頭一致だけを見ると確定しているが、曖昧一致の候補まで含めると色々ある、 78146 という場合には先頭一致で確定させてしまって良い。 78147 (一方で、先頭一致の共通一致部分に関しては確定しない方が良い? 78148 或いは曖昧一致探索と先頭一致探索はそもそも混ざり合わない様に異なるキーに 78149 割り当てるべきなのかも知れない。) 78150 それぞれの候補についてそれが曖昧一致なのか先頭一致なのかで形式を変えても良いかも。 78151 しかしそれぞれの候補をどう取り扱うかは受け取った側で設定できるようにしたくもある。 78152 それに候補生成の方法を複雑にすると言うのもなんである。 78153 そう考えるとやはり候補の生成の際には両者を区別しない形で列挙して、 78154 それを使う側で先頭一致とそれ以外に分けるという方法の方が良いようにも思う。 78155 78156 - 挿入する → 挿入関数名 78157 ただ挿入するだけではなく、様々な追加操作を行う可能性がある。 78158 例えば、一意確定の際にスペースまたは / を挿入するという事。 78159 或いはお節介な機能として確定した単語について 78160 様々な装飾・エスケープなどを施したいという需要があるかもしれない。 78161 これは色々と自由度が高い様な気がするので関数で実装する事にする。 78162 各候補についてどの関数を用いて挿入を行うかを取得できる様にする。 78163 78164 他に問題になるのは、上記に示した情報をどの段階で生成するのかという事である。 78165 必要最低限と言えば、補完候補の文字列とその取り扱いを定義する関数さえ持っていれば、 78166 後は関数を呼び出す事によって、補完候補の表示文字列も生成できるし、 78167 追加挿入される部分について生成する事もできるし、候補表示の時の着色やら、 78168 メニュー表示にした時の説明文まで何でもできる。 78169 ただ、候補生成の時にしか分からない情報もあるかもしれないから、 78170 後でそれらの関数が利用できる様に各項目に data 等というフィールドが使える様にする。 78171 (これらはそれらの補完関数に形式・使用方法を任せる。) 78172 78173 取り敢えずその形式で行く事にする。 78174 候補生成関数が用意するのは、 78175 1 補完候補 78176 2 補完関数群 (これは名前の形式を定めておき prefix 等を呈示する) 78177 3 2 で使用する内部データ (あれば) 78178 という事にする。 78179 補完の表示文字列については高確率で必要になるので、これも生成時に用意させる。 78180 4 表示文字列 78181 また、候補毎に挿入位置や元にしている文字列が異なるかもしれないので、 78182 これについても用意した方が良い様に思う。 78183 5 補完開始点・補完終了点・対象の単語 78184 補完対象の単語、というのはクォート除去・パラメータ展開などを行った後の値である。 78185 78186 補完候補、表示文字列、対象の単語に関しては内部に任意の文字列を含みうるので、 78187 独立した変数に入れる様にした方が管理しやすい。 78188 一応、固定形式の末端に入れれば何とか抽出できない事もないが面倒なので止める。 78189 補完関数群の prefix 補完開始点・補完終了点などの情報は空白を含まないので、 78190 これらは一つに纏める事ができる。 78191 補完関数群で使用できる内部データは補完関数群の内部で簡単に使える様にする為に、 78192 やはり一つの独立したデータであるべきである。 78193 従って候補のデータは以下の様な物に改める: 78194 78195 cand_word 単語 78196 cand_show 表示文字列 78197 cand_head 対象の単語 78198 cand_prop 関数群接頭辞 開始点 終了点 78199 cand_data 自由データ 78200 78201 特に簡単な候補生成の為に cand_word さえ渡せば他を fill できる様にするべきである。 78202 78203 実装2: 78204 78205 実装1の方針で実装してみたが問題がある。 78206 上記の方針では異なる補完開始点や関数群に従った候補を混在させる事ができる様になっている。 78207 しかし、候補を一意に絞れない時の動作はどの関数群に従ったらよいか判断できない。 78208 78209 但し、以下に挙げる様な特定の候補に関する操作に関しては、候補語との関数の指定で問題ない 78210 - 一意確定時の動作 (挿入した時に後に " " や "/" を追加するなど) 78211 - 各候補に対する説明の取得や色つきの表示文字列の取得など 78212 78213 問題になるのは以下の動作である。 78214 - 共通部分確定時の挿入 78215 78216 単純に挿入するだけであれば共通の動作であるので別に関数群に頼る事は無い。 78217 しかし、文脈によっては挿入によって文法構造が壊れてしまう事もある。 78218 その様な場合には色々な修飾が必要になってくる。 78219 78220 例えば myfile-$ind の末端の様に変数名補完と 78221 ファイル名補完が混在している時を考える。 78222 変数名補完としては myfile-$index になる事を考え、 78223 ファイル名補完としては myfile-${ind}ex になる事を考えている場合、 78224 両者の補完は共に ex となるので共通一致で ex を挿入しようと言う事になるが、 78225 実際に挿入する場合にはどちらか一方のやり方で挿入する訳には行かない。 78226 結局の所、共通一致しそうに見えて一致しないというのが答えである。 78227 78228 この判断をどの様にすれば良いのかについて慎重に考えなければならない。 78229 というかそもそも両者は異なる補完結果を与えるのだから、 78230 異なる候補として区別すればよいだけの事かも知れない。 78231 78232 つまり、挿入の仕方は挿入関数を定義する事によって実現するのではなくて、 78233 そもそも候補列挙の時点で挿入文字列・挿入方法を完全に確定してしまって、 78234 その後で共通部分一致などを試す必要があるのではないかという事。 78235 逆に挿入時には共通の処理しか挟まない様にする。 78236 78237 今後他にも共通操作に関して問題になる事があるかもしれないが、 78238 取り敢えず今回の共通部分確定時の挿入に関しては、 78239 事前に何が挿入されるか迄候補として生成して、 78240 共通部分探索時にそれを考慮に入れて絞る。 78241 78242 今度の実装では候補生成を以下の様に行う: 78243 1 補完範囲の開始点と終了点を得る。 78244 更にその間にある部分の評価結果を文字列として取得する。 78245 (これは補完の種類によっては不要であるかもしれない) 78246 COMP1 = 補完範囲の開始点 78247 COMP2 = 補完範囲の終了点 78248 COMPS = 補完範囲の文字列 78249 COMPV = 補完範囲評価結果 78250 78251 この次に具体的な候補を複数列挙する事になるが、 78252 ここまでの処理はそれらの候補の間で共通である。 78253 78254 2 候補を生成する 78255 78256 CAND = 候補の文字列 78257 ACTION = 関数群接頭辞 78258 DATA = 何か追加情報があれば。ACTION への引数的な物。 78259 78260 此処までは候補に依存して完全に異なる物である 78261 エスケープなどの共通の修飾などについては後段に任せる。 78262 78263 3 各候補に対する処理 78264 78265 これ以降は既に指定した ACTION による関数で処理を行う。 78266 候補の違いは全て ACTION の違いで処理する。 78267 78268 $ACTION/init で処理を行う 78269 78270 SHOW = 表示文字列 78271 INSERT = 挿入文字列 ← CAND から生成する 78272 DATA に対する加工も。 78273 78274 4 候補の情報の格納 78275 78276 cand_word+=("INSERT") 78277 cand_show+=("SHOW") 78278 cand_prop+=("ACTION COMP1 COMP2") 78279 cand_data+=("DATA") 78280 78281 その他の情報については後で使う事は無いと思う。 78282 何か特別に必要な物があれば DATA に入れる。 78283 一般的に使う機会が多そうな物があれば配列を増やす。 78284 78285 新しく共通部分の探索も加えて取り敢えず実装を行った。 78286 今の所は仕組みとしては問題なく動いている。 78287 後はこの仕組みに従って少しずつ拡張していけば良い。 78288 78289 78290 | * <bug> complete 78291 | 引用符に囲まれた場合などに挿入位置がずれる。 78292 78293 この問題は新しく実装し直した事によって解消した。 78294 78295 2015-02-25 78296 78297 * <bug> accept-single-line-or-newline が二回目以降常に accept [#D0180] 78298 * <bug> 複数行の編集時に履歴移動をすると表示が乱れる [#D0179] 78299 78300 他にも編集してから実行をすると実行後にずれるとか、 78301 複数行の場合には accept-line ではなくて newline の筈なのに accept されるとか。 78302 78303 これには二つの別の問題が関係していた 78304 1. 表示を消す時の座標の間違い 78305 2. stty -nl で icrnl が設定される事により CR が LF に変更されていた 78306 78307 accept の件は、本来は、行末が次の行に移動しているかどうかではなく 78308 $'\n' がコマンドラインに含まれているかどうかで判断するのが良い。 78309 唯単に端末が狭くて折り返しているだけで単一行の時もあるから。 78310 しかしそうだとしても accept されるのは不思議である。 78311 accept-single-line する前に一旦表示している筈だから _ble_line_endy 78312 は更新されている筈であるのに。 78313 78314 % やはり _ble_line_endy の更新に失敗しているという事であろう。 78315 % と思ったらいつの間にかに accept が正しく動くようになっている。謎だ。 78316 78317 それでも表示が乱れるのは変わっていない。 78318 色々試した結果、_ble_line_endx _ble_line_endy は正しい値になっている。 78319 よく見てみると、単純に表示を削除する時の座標を間違えていただけであった。 78320 これで問題なく動くようになった。 78321 78322 accept の方の問題に関しては再現する条件がある様だ。 78323 良く分からないが echo hello の様に単純なコマンドを一回実行してからだと 78324 常に accept される様に変わってしまう。 78325 表示の部分で _ble_line_x 等の動作を確認してみたが問題は内容に見える。 78326 78327 と思って ble-edit+accept-single-line-or-newline の内部で 78328 出力を行う様にしてみた所、何故か初めの一回だけしか呼び出されていない。。 78329 ble-bind で確認してみても何か別の物に置き換わっているという様子もないようだ。 78330 すると何が起きているのだろうか…。 78331 実行されているという事は accept-line は呼び出されていると思われる。 78332 →実際に accept-line で stackdump すると ble-decode-key/invoke-command 78333 から直接 accept-line が呼び出される様になる様だ。 78334 もう少し詳しく調べる事にする。 78335 →どうやら ble-decode-char の時点で 13 ではなく 10 を受信しているようだ。 78336 もっと遡ると ble-decode-byte でも 10 を受け取っているし、 78337 そもそも ble-decode-byte:bind でも 10 を受け取っている。 78338 (何故始めの1回だけ正しい物を受け取っているのか謎である。) 78339 78340 - bind -X で確認してみたが異常はない。 78341 - 因みにコマンドを一回も実行しない限りはずっと 13 が受信できる。 78342 何か stty の設定と関係があるのだろうか。 78343 - M-c で ble-bind -cf のコマンドを実行した場合も同様である。 78344 78345 判明した function .ble-stty.enter の中の stty -nl が駄目だった。 78346 stty nl としてみたら動くようになった。然しそうすると表示が滅茶苦茶になる。 78347 今迄の描画ルーチンでは全然駄目という事になる。 78348 78349 | 解決方法は二つある。 78350 | stty のモードをもう一つ付け加えて、入力を受け付ける時にだけ stty nl にする。 78351 | 或いは、 stty nl でも正しく描画できる様に描画ルーチンを変更する。 78352 | 78353 | a 何とかして stty を使わずに端末の設定を切り替える方法はあるか? 78354 | 78355 | 現在の所 stty のモードの変更はコマンドを実行する瞬間だけで済んでいる。 78356 | もし描画する時と表示する時で毎回 stty を呼び出して切り替えなければならないのだとすると、 78357 | かなりコストが高い。 78358 | 78359 | - できるならば stty を呼び出さずに端末を制御する方法が有れば良いのだが…。 78360 | - 或いは、stty を裏で起動しっぱなしにしてリアルタイムで変更させるなんて言う事ができたら…。 78361 | しかしそんな機能はない。 78362 | - それとも新しく仮想端末を作ってしまって設定に応じて出力先を変更する、 78363 | 等という事も出来たりするのだろうか。。 78364 | 78365 | mknod とか?? 試しに 78366 | $ mknod testtty c 4 100 78367 | 等としてみる…。許可されていない操作ですと怒られて終わる。これでは駄目だ。 78368 | $ mknod a c 136 10 78369 | としても駄目だ。今度は 78370 | $ mknod /dev/pts/10 c 136 10 78371 | 等としてみる。エラーメッセージが変わった。"許可がありません" になった。 78372 | 良く考えてみればこれは "許可されていない操作です" 以前の問題なので、 78373 | 寧ろ遠ざかったのではないかと思う。 78374 | さて、システムが落ちても嫌なので無理矢理 sudo で作るのは止めておこう。 78375 | 使い方も良く分からない事であるし。 78376 | 78377 | 関係有りそうな質問が出ている: 78378 | [[Create new /dev/pts/<n> device using bash script?>https://forums.opensuse.org/showthread.php/494468-Create-new-dev-pts-lt-n-gt-device-using-bash-script]] 78379 | しかし解決法は呈示されていない。 78380 | 78381 | [[screenの”Cannot open your terminal ‘/dev/pts/0′”対策 | Siguniang's Blog>https://siguniang.wordpress.com/2012/08/11/screen-and-pseudo-terminal/]] 78382 | によると script コマンドを起動すると新しい pts が開かれる様である。 78383 | 例えば、script コマンドを無理矢理開いて、その後でその script コマンドが作成した端末に書き込んだりするとどうなるのだろう。 78384 | script を & で開いて新しく作成された pts に何か書き込んでみたが何も起きない。 78385 | プロセスを見てみたが script コマンドが新しく pts/8 な bash を中で開いている様だ。 78386 | 要するに bash が何か出力したら script がそれを読み出す、という事なのだろう。 78387 | bash は -i で起動し入力待ち状態になる。この時に pts/8 に書き込んでも何も起きない。 78388 | うーん。良く分からない。もう少し試してみる。 78389 | 78390 | $ script $(tty) & 78391 | 78392 | 何とも微妙な事になる。先ず & で起動しても script は停止してしまう。 78393 | 仕様がないので fg に持ってくると今度は出力が二重化されている。 78394 | うーん。 78395 | 78396 | $ script $(tty) -c cat & 78397 | としてみる。cat は起動されていない様だ。 78398 | この状態で /dev/pts/8 に書き込んでも何も起こらない。 78399 | といって fg で中にはいると C-z 等で抜ける事ができない。どうした物か。 78400 | % どうも /dev/pts/8 に書き込むというのは cat に書き込むという事のようである? 78401 | とも思ったがそういう訳ではないようだ。やはりちゃんと $(tty) の方に書き込まれている。 78402 | 78403 | b もし -nl で描画を設計しなければならないとすると結構骨である。 78404 | echo 等で適当に出力する事ができないという事になる訳だから。 78405 | 何を出力するにしても .ble-line-* を通して描画するか、 78406 | 或いは stty を自分で設定して出力するかをしなければならない。 78407 | 78408 | 例えばログアウトや戻り値が 0 以外の時に [ble: hoge] 等と表示しているが、 78409 | これらも全て適当な出力としてではなく "描画" として取り扱う様に注意をしなければならなくなる。 78410 | 78411 | c 実は stty をもっと細かく設定できるのではないか? 78412 | というか入力と出力で別々に設定が出来た様な気がする。と思って stty --help を見てみたら、 78413 | 78414 | 入力設定: 78415 | [-]icrnl 復帰 (CR) を改行 (LF) に翻訳 78416 | [-]igncr 復帰 (CR) を無視 78417 | [-]inlcr 改行 (LF) を復帰 (CR) に翻訳 78418 | 78419 | 出力設定: 78420 | * [-]ocrnl 復帰 (CR) を改行 (LF) に翻訳 78421 | * [-]ofdel ヌル文字の代わりに埋める文字として削除文字を使用 78422 | * [-]ofill 遅延のタイミングの代わりに埋める文字を使用 78423 | * [-]olcuc 小文字を大文字に翻訳 78424 | * [-]onlcr 改行 (LF) を復帰改行 (CR-LF) に翻訳 78425 | * [-]onlret 改行 (LF) が復帰 (CR) として振舞う 78426 | * [-]onocr 1桁目の復帰 (CR) を表示しない 78427 | 78428 | nl -icrnl -onlcr と同じ 78429 | -nl icrnl -inlcr -igncr onlcr -ocrnl -onlret と同じ 78430 | 78431 | と書かれていた…。基本的に -nl で、問題のありそうな物を nl と同じ設定にする、 78432 | という事にすれば良いのではないだろうか。 78433 | 78434 | -nl: icrnl → cr を nl に変換する (これが駄目) 78435 | -nl: -inlcr → nl を cr に変換する (これはその儘でないと駄目) 78436 | -nl: -igncr → cr を無視しない (これもその儘でないと駄目) 78437 | -nl: onlcr → 出力の nl を cr nl に変換する (これもその儘) 78438 | -nl: -ocrnl → cr は nl にしない (その儘) 78439 | -nl: -onlret → nl は cr として振る舞わない (謎) 78440 | 78441 | 結局 -nl -icrnl とかすれば良いのでは?? 78442 78443 stty -nl -icrnl とするだけで済んだ。呆気ない事だった。 78444 また無事に問題が解決したので、 78445 accept-single-line-or-newline の判定の修正を行う。 78446 表示上の行数ではなくてコマンド内に \n があるかどうかで判定する。 78447 78448 * ble-syntax.sh: 条件式 [[ ... ]] と配列初期化子内の文脈に対応、コメントにも対応 [#D0178] 78449 78450 以下の問題はこの実装の後に確認したら直っていた。 78451 (そもそも何故この問題が起こっていたのかよく分かっていなかったが。) 78452 78453 | 2015-02-17 78454 | 78455 | * [[ ]] の括弧が異なる色になる。 78456 | "]]" は "[[" の色に合わせる様にしているのに…と思ったら、 78457 | これに関してもコマンドとしての着色によって "[[" の色が後で 78458 | 上書きされている様だ。 78459 | 78460 | 取り敢えずコマンドとして解釈されない様に、 78461 | ATTR_DEL を rword[0] に代入してみたが…。 78462 | これだと [[ に対する引数を complete の規則で取り扱えない。 78463 | 78464 | 結局、正しくキーワードと解釈される事を期待して、 78465 | "]]" に先に ATTR_CMD_KEYWORD を適用してしまう事にする。 78466 | [[ ~ ]] の取り扱いは後で又考え直す事になると思う。 78467 | 78468 | と思ったら今度は急に動かなくなった。 78469 | 先ず [[ まで入力した時点で初めの単語の長さが 0 になっている。 78470 | 更に ]] を用いて閉じると正しい長さにはなるが 78471 | 単語の種類がコマンドから引数に切り替わってしまう。 78472 | また "[[ text " と入力すると最後の空白が単語として認識されている。 78473 78474 * <bug> invalid nest " $()" の先頭に for を挿入した時 [#D0177] 78475 →これは寧ろチェックのコードの方が誤っていた。nest の形式の変更に追随していなかった。 78476 78477 * 複数行コマンドの履歴 [#D0176] 78478 78479 複数行のコマンドの履歴について何とかする…。eval -- ''... に置き換える等。 78480 読み取り時に負荷になる? 78481 78482 →複数行のコマンドを履歴に登録する時には eval -- $'' の形式にする事にした。 78483 これは printf %q を用いて出力する事ができる。 78484 読み取りの際には history-load の awk で ^eval -- ... に対して一致させる。 78485 78486 保存する時には printf %q を用いる。bash-3.0 でも bash-4.3 でも $'' の形式になる様だ。 78487 78488 意外と問題もなく直ぐに実装できた。 78489 これで複数行のコマンドも心おきなく編集・実行できる。 78490 78491 * <bug> 表示の属性の更新がうまく行かない事がある。 [#D0175] 78492 78493 例1: for ((abc)) の a を消すと bc が (( と同じ属性になる。 78494 例2: for (()) の (()) の中にカーソルを移動して中身を書くと )) の属性が中身と同じになる。 78495 78496 挿入や削除のあった箇所で sgr の再設定がされていない様子。 78497 これは見たら直ぐに分かって修正できた。 78498 78499 * カーソル移動 [#D0174] 78500 78501 複数行に渡っている場合には up down で中を移動できる様にする。 78502 カーソルが一番上にある時に up を押した時に前の履歴項目に移動する。 78503 78504 →一通り対応した。 78505 78506 従来の kill-forward-line, kill-backward-line, beginning-of-line, end-of-line は 78507 kill-forward-text, kill-backward-text, beginning-of-text, end-of-text に移動。 78508 新しく kill-forward-line, kill-backward-line, beginning-of-line, end-of-line, 78509 forward-line, backward-line, forward-line-or-history-next, backward-line-or-history-prev を実装。 78510 newline, accept-single-line-or-newline の実装。 78511 78512 * ble-syntax.sh: $[...] の形式に対応 (何故か bash の説明には一切載っていないが使える)。 [#D0173] 78513 78514 * ble-edit.sh: printf %()T を用いた実装の導入、PS1 \D{...} に対応 [#D0172] 78515 78516 | 2013-06-12 78517 | * <bug> ps1, \D{format} に対応していない。 78518 78519 * <bug> 編集文字列の行数が変わった時に info.draw の内容がずれる [#D0171] 78520 78521 これは info.draw の問題というよりは寧ろ 78522 .ble-edit-draw.update の方の問題の様に見える。 78523 → .ble-edit-draw.update の側で正しく描画領域を確保して描画する様にしたら直った。 78524 78525 2015-02-24 78526 78527 * 描画ちらつき [#D0170] 78528 78529 未だちらつく。全体を再描画するのではなく変更部分だけ更新したい 78530 先ず、開始時に bash に編集文字列を消されるのに対抗して再描画するのは 78531 bleopt_suppress_bash_output=1 である今必要はないと思って省略しようとしたら… 78532 元からちゃんと bleopt_suppress_bash_output を見て省略していた。 78533 78534 とするとちらつくのは専ら再描画の為に一旦全体を消してから 78535 全体を再度出力し直している事による。 78536 現在は実装を一新したので変更のあった部分だけ出力する様に変更を図る。 78537 78538 現在の実装について確認する。 78539 特に文字列の座標計算と表示内容の構築を行っているのは以下の関数である。 78540 .ble-line-text.update-positions 78541 .ble-line-text.construct 78542 もう少し関数に細分化・分散していると思っていたが意外とコンパクトに纏まっている。 78543 現在、update-positions は construct から呼び出されるので直接外部から呼び出す事は無い。 78544 (むしろ外部から呼び出すと update の回数がずれて 78545 二重に shift を実行してしまって全体を計算し直すことになったりして良い事は無い。) 78546 つまり、実質的に interface は .ble-line-text.construct だけという事になる。 78547 78548 計算結果は現在は専ら .ble-line-text.construct の戻り値を介して取得している。 78549 しかし、外部からもっと簡単に様々な情報にアクセスする事ができるようにしても良いと考える。 78550 幸いにしても .ble-line-text.construct の呼出元は一箇所しかないので、 78551 簡単に interface を変更する事が出来る。 78552 78553 78554 取り敢えず更新の必要な範囲についてだけ更新を行う様に変更する事を考える。 78555 実際には文字列の挿入や削除などの場合でも文字列は移動するだけだから ICH や DCH でもっと 78556 賢く再描画する事も可能かも知れない。 78557 しかし、取り敢えずの所は移動する文字についても完全に再描画する事にする。 78558 また、実際に必要とされる文字列についてはの /update で計算するのではなくて、 78559 使う側が必要になったら構築を呼び出す様に変更する。 78560 78561 * <重い> 改行を挟んでいれば編集は軽くなると思っていたが軽くない [#D0169] 78562 78563 update-positions は途中で終わると考えていたが、違うという事なのか? 78564 実際に調べてみた所 update-positions や highlight はちゃんと更新の必要がある範囲で終わっている様だ。 78565 試すと明らかに挿入が遅い。末端に文字列を書き込んでいる時にはそんなに重くないのに、 78566 改行を挟んでいる所に文字列を書き込むと遅い。 78567 再度試してみたが、そもそも内容が長くなってくると重いのは仕方がないとして、 78568 やはり途中に挿入するのが特に重い。 78569 78570 試しに syntax を止めてみたら途端に滅茶苦茶軽くなった。 78571 syntax が full に走ってしまっている可能性がある…。 78572 また syntax を入れてみて試してみる。 78573 やはり死ぬ程遅いが、ble-syntax-highlight+syntax が返す更新範囲はそんなに大きくない。 78574 次に ble-syntax-highlight+syntax の中身を覗いてみる。 78575 何と解析が最後まで走っている事が判明した…。 78576 78577 と思ってよく見てみると _ble_syntax_stat の shift に失敗していた。 78578 これを直して再度試してみる事にする。未だ最後まで走っている…。 78579 もっと調べてみるとそもそも dirty-range 拡大が最後まで走っている様だ。 78580 どうも word による dirty 拡大が連鎖で起こっている様子だ。 78581 78582 そもそも dirty 拡大の時の拡大領域の値が +1 されているのは何故だったか良く分からなくなった。 78583 もともとは、その当該要素も確実に再解析の対象になる様にという事だったとは思うが、 78584 その時点での stat の値が一致していれば直前までの解析で良いのではないか? それでは不十分なのか? 78585 という事になる。というかそもそも dirty 拡大が必要なのは何故だったか? 78586 78587 もしかすると word の古い取り扱いに関連していたのかも知れない。 78588 でもそうだとすると今回新しく word による dirty 拡大をした理由も何だか良く分からなくなる。 78589 もう少し落ち着いて考える。参照先が消滅している場合にはその stat は無効になる、と考えるのは自然である。 78590 例え解析の結果によって stat が全く同じ値になったとしてもこれは前の stat と同一か? と言えば異なるとした方が良い。 78591 とするならば解析範囲の拡大を行う事によってこれに対応するのではなくて、無効になった stat を削除すると言うのが正しい対処法ではないのか? 78592 word に対する dirty 拡大はもう少し異なる状況である。 78593 word については解析中断の条件に入っていないので word の情報を消したとしても無意味である。x 78594 抑も word の先頭が消滅・或いは無効化した時に word が更新された事を検知したいというのが目的だった。 78595 もし dirty 拡大をしていないと word の先頭が消滅・無効化した時でも再解析によって word の途中で 78596 一致した文脈状態になった時に其処で解析が終了してしまう。 78597 その時に _ble_syntax_word_umin _ble_syntax_word_umax に登録されないという問題が生じる。 78598 78599 でも _ble_syntax_word_umin, _ble_syntax_word_umax に登録するという目的であれば、 78600 dirty-range 拡大によって無理矢理に解析をやり直させるよりは良い方法がある様に思う。 78601 無理矢理解析を行わせるように成っている為に必要のない所まで再解析・単語更新を強いる事になる。 78602 例えば、"$(echo hello world)" において先頭に a を挿入した場合、dirty 拡大を行っている場合、 78603 echo や hello, world 等までも再解析の対象になり、また _ble_syntax_word_umin の対象になる。 78604 実際に考慮に入れるべきなのは a"$(echo hello world)" という全体に対してのみの筈だ。 78605 (もし挿入によって文脈構造が変化する場合については echo hello world も自然に再解釈の対象になるので問題ない)。 78606 78607 単語内部で更新が起こったかどうかによる判定は別に行うべきではないかと考える。 78608 と思って確認してみたが、既に単語内部で更新が起こった場合については _ble_syntax_word_umin に登録する様になっていた。 78609 これについては、念のため不等式を変更して word 先頭で編集が起こった場合にも対応する事にした。 78610 78611 さて今回の変更で dirty 拡大を完全に廃止した事になるが、 78612 これによって従来動いていた物が動かなくなってはいないか確認するべきである。 78613 取り敢えず、編集のあった単語について正しく再解析が行われているかどうかについて確認を行う。 78614 78615 - 色々試すと、単語の先頭に文字列を挿入しても _ble_syntax_word_umin に登録されなくなった。 78616 謎だ。と思ったら j を登録すべき所 i を登録していた。 78617 更に、一番最後の点 (index iN) を更新していなかった。 78618 文字列の末端でも状態を記録する為、一番最後の点まで確認しなければならないのだ。 78619 これは取り敢えず解決された。 78620 78621 これに関しては dirty 拡大の取り扱いを止める事によって解決した。 78622 これで途中の編集に対して末端まで解析を実行する事は防げた。 78623 今迄 dirty 拡大を行った元でテストしてきたが、これがないと解析を行うべき所で解析されないなどの問題が 78624 今後発生するかもしれない。しかし、それはまたその時に対応する事にする。 78625 78626 しかしながら、多少解消はした物のやはり途中に対する挿入は遅い。 78627 これは結局 shift をする為にループを回しているのがいけない様に思う。 78628 末端に挿入する場合には shift を確認する範囲は小さくなる。 78629 しかし初めの方に挿入する時には文字数と同じ数だけの shift のチェックを行わなければならない。 78630 何か簡単に shift が実行できてしまう様なデータ形式を思い付けば良いが、 78631 そうでなければこれは仕方がない。shift が遅いという新しい項目として残してここで終わりにする。 78632 78633 * <bug> 文字削除時 invalid nest の assertion に引っかかる。 [#D0168] 78634 invalid nest に引っかかる。 78635 再現: history で l "$(echo hello)" を出して "$ の直前に文字を挿入。その後文字を削除。 78636 別に history でなくても起こる様だ。 78637 78638 dirty 拡大に代わり stat を削除する様に変更と言いつつ、 78639 stat の該当項目に -1 を代入していただけなのが災いしている? 78640 良く考えたら -1 既に "より上位の nest が存在しない" だとか "今は word の中ではない" という意味だから、 78641 本当は良くない。でもそうだとしても nest のチェックに引っかかるのかどうかというと疑問な気はする。 78642 取り敢えず本当に削除する様に変更して様子を見てみる事にする。 78643 →出なくなった。考えるのが面倒なのでもし今度出たらその時に考える事にして此処で終わりにする。 78644 78645 * <bug> 編集内容が零文字になった瞬間に改行が起こって表示が消える。 [#D0167] 78646 78647 調べてみると編集文字列が "" になった瞬間に 78648 _ble_line_x _ble_line_y が 53 1 という変な値になっている。 78649 と思ったらこれは .ble-line-info.draw による表示の位置である。 78650 しかし、何故編集文字列が空になった時にだけ .ble-line-info.draw の 78651 位置が _ble_line_x に代入されているのだろうか。 78652 % と思ったがそれは当然である。 78653 % 変更点があって文字が描画された時には umin<umax なのでその前に描画が為されている。 78654 しかしそれでも変だ。では何故 "" になるまでは _ble_line_x に別の値が代入されているのだろう。 78655 78656 別に文字が "" にならなくても末端から削除をしている時は 78657 新しい文字を描画する必要はないので umin==umax になっているはずである。 78658 78659 何だか良く分からないのでまた別の方向でも調べてみる。 78660 部分更新ではなく、常に全体を更新する様にしてみる。 78661 →全体更新であっても勝手に改行が入ってしまう様である。 78662 もしかして何処かにデバグ用に埋め込んだ echo があるのか? 78663 →どうやら bash がエラーを出力していた様だ。 78664 何と echo 11.8 "$_ble_syntax_word_umin $_ble_syntax_word_umax" で 0 0 が出力される。 78665 _ble_syntax_word_umin の代入箇所を探しても 0 になる様な箇所はないのだが…。 78666 と思ったが分かった。削除した時に _ble_syntax_word_umin の shift によって 78667 有限の値だった物が 0 になっている。 78668 78669 これが起こるのは仕方のない事なので、これに対して特別に対策を取る事にした。 78670 更新しようと考えていた単語が消滅した時には _ble_syntax_word_umin を ++ する。 78671 それによって対象の単語が一つもなくなった場合には -1 を代入する。 78672 78673 これで直った。しかし、描画の際にエラーメッセージが消されてしまうというのは厄介な事である。 78674 78675 * <bug> 改行しても先頭がコマンドになっていない [#D0166] 78676 78677 何と [[ ${#BASH_REMATCH[0]} =~ $'\n' ]] としていた。当然 # は不要である。 78678 これは直ぐに直った。 78679 78680 * <bug> _ble_region_highlight_table で空欄になっている箇所がある。 [#D0165] 78681 echo " と入力した時の空白に対応する部分。 78682 78683 これは function ble-syntax/highlight/set-attribute の中で 78684 既に設定されている物と同じ値かどうかの確認の際に、 78685 数値として比較していた為に空欄と 0 が同一視されている事による物であった。 78686 修正した。これは無事に 0 が代入される様になった事を確認した。 78687 78688 それと共に _ble_syntax_attr_umin における色の既定値を正しく計算する様にした。 78689 (実際には問題にならなかったかも知れない。 78690 つまり _ble_syntax_attr_umin は必ず attr の設定されている点が設定される様な気がする。) 78691 78692 * <bug> 単語の属性適用が後ろに続く単語にも続いている。 [#D0164] 78693 単語の分割はちゃんとできているのに不思議だ。 78694 これは属性適用の側のバグだと思われる。 78695 78696 再現: 78697 1 以下を先頭から順に入力する 78698 echo "$(less hello world)" 78699 2 "$( の直前に文字を挿入する 78700 echo a"$(less hello world)" 78701 この時 less の属性が less hello world 全体に適用される。 78702 その他の部分の着色については問題はない様に見える。 78703 78704 取り敢えず属性適用の部分で何が起こっているか調べようとすると…。 78705 属性適用が起こっていない様だ。やはり再度試しても呼び出されていない。 78706 (よく考えてみれば _ble_syntax_word_umin はこの範囲を含んでいないので当たり前である。 78707 また、これは期待した動作でもある。この部分は変更していないのだから。) 78708 さて、この時に何故表示内容が崩れてしまうのか。。 78709 78710 また、不思議なのは先頭にあるコマンドの着色がそのまま後ろに適用されてしまう点である。 78711 つまり、一旦 word による属性が全て解除された後に word による属性が適用されない、という訳ではない様だ。 78712 _ble_syntax_attr が削除されているという事だろうか。 78713 shift の際に属性が飛んでしまうという事なのか? shift ではちゃんと削除された場所以外は保持している筈なのだが。 78714 試しに _ble_syntax_attr の中を確認してみる。_ble_syntax_attr の中は正しい値になっている。 78715 という事は adapter での繋ぎ替えに失敗している? 念のため _ble_region_highlight_table を確認する。 78716 これも正しい値になっている。という事はやはり adapter が怪し。 78717 78718 今度 _ble_highlight_layer_adapter_buff の中を出力させてみたらどうやら、 78719 問題は a を挿入前の時点で既に発生していた様だ。 78720 $( とした状態で順次入力を行っていくと常に最後にエラーの赤い印が付いた状態で入力していく。 78721 そうするとどうやら属性 0 が全てはぎ取られていく様だ。 78722 また遡って調べてみようと思ったが、_ble_region_highlight_table の時点で正しい状態だったから、 78723 78724 やはり adapter の中での更新が問題な様に思われる。 78725 と思ったら見つけた。gprev に常に 0 が入っていた。 78726 これは全体に対して _ble_region_highlight_table を読み出していた時のままになっていたという事だろう。 78727 i1>0 の時には i1 直前の gprev を読み出す様にした。 78728 これで a を " 直前に挿入した時の色付けは正しくなった。 78729 78730 しかし、今度は何故か入力していった時の色がおかしくなった。 78731 と思ったがこれは当然の事である。部分更新なので途中から出力している。 78732 それなのに前からの続きとして出力してしまっているので SGR が出力されていない。 78733 これは ble-edit-draw.update 側を修正する。 78734 これで正しく動作する様になった。 78735 78736 意外と修正に手間取った。 78737 78738 * <bug> _ble_syntax_attr の中に "BLE_ATTR_ERR" の文字列が混入している。 [#D0163] 78739 一応算術式評価では BLE_ATTR_ERR の中を読みに行くので問題はないとはいえ、その様に設計したつもりはないので修正するべき。 78740 →これは parse の末端で起こっていた。修正した。 78741 78742 2015-02-23 78743 78744 * 過去の ToDo について改めて整理を行う [#D0162] 78745 78746 既に自然に実装された物、解決した物、或いは実装する事に意味が無くなった物などを整理する。 78747 78748 | 2013-06-12 78749 | 78750 | * ble-decode-byte:bind の先頭でプロンプトを再描画する必要がある version の境を調べる。 78751 | →これは bleopt_suppress_bash_output の実装で余り意味がなくなった。 78752 | bleopt_suppress_bash_output=1 で問題が起きていないので、 78753 | 今後は bleopt_suppress_bash_output= について積極的な最適化をする事はない。 78754 | 78755 | * <bug> ウィンドウサイズを変更するとプロンプトが bash の表示する物になる 78756 | これはウィンドウサイズを変更した時に bash が自動的にプロンプトを再描画する為。 78757 | SIGWINCH を trap して自前で描画し直せばよい? 78758 | 78759 | 2015-02-09 bash-4.3 で試したが問題が再現しない。 78760 | 78761 | 2015-02-24 これも bleopt_suppress_bash_output=1 を実装したので 78762 | 今後はこの問題が発生する事は無いのではないかと考えている。 78763 78764 これらは出力関連の問題であったが、bleopt_suppress_bash_output の実装により余り意味が無くなったので削除する。 78765 78766 [Done] 78767 78768 | 2013-06-10, X7 解析器 78769 | 78770 | # bash script の解析器を作る。 78771 | # これは syntax-highlight, complete 等から用いる。 78772 | 78773 | 先ず、シェルスクリプトの文法について整理する。 78774 | 78775 | ! 履歴展開 78776 | ! に非空白の文字列が続いている時 78777 | " 二重引用符の開始 78778 | ' 単引用符の開始 78779 | ` コマンド 78780 | $' 引用符の開始 78781 | ${ パラメータ展開 {} の開始 78782 | $( コマンド置換 78783 | $(( 算術式置換 78784 | $他 パラメータ展開 78785 | 78786 | コマンド修飾 (コマンドよりも前に来る事ができる物) 78787 | [0-9]*(>|>>|&>|&>>|<|<>)(&[0-9]+|arg) 78788 | [<>]( プロセス置換開始 78789 | 78790 | コマンド 78791 | (( 算術式の開始 78792 | [[ 条件式の開始 78793 | { 重文開始 78794 | ( サブシェル開始 78795 | aaa=hoge 78796 | aaa[]=hoge 78797 | aaa=(hoge) 78798 | コマンドが続く 78799 | time 78800 | time -p 78801 | コマンドが続く 78802 | 78803 | ; & | && || |& 78804 | コマンドが続く 78805 | 78806 | ;; ;& ;;& 78807 | case パターンが続く 78808 | 78809 | ※incremental に解析できる様に再帰呼び出しなどは避けたい。 78810 78811 この中で実装されていないのは 78812 - time -p 78813 - aaa=(hoge), 他に aaa+=(hoge) というパターンもある。 78814 - ;; ;& ;;& の後に case のパターンを受ける 78815 - [[ 条件式の文法に正確に対応していない 78816 等である。その他については (多少の問題点は残るが) 実装してある。 78817 上記の物に関しては、より最近の文法対応リストに追加しておく事にする。 78818 78819 | 2013-06-09 78820 | 78821 | * split, 書きかけたけれど結局使っていない関数 78822 | function .ble-text.split { 78823 | local GLOBIGNORE='*' 78824 | test -n "${3+set}" && local IFS="$3" 78825 | eval "$1=(\$2)" 78826 | } 78827 78828 これはどうでも良い。最近では手で書いている。というか手で書いた方が楽だ。 78829 78830 | * ble-decode-char: cmap+default.sh を統合する? 78831 | 78832 | 改めてコードを見てみたが、それ程サイズが大きい訳でもないので、 78833 | ble.sh の中に埋め込んでしまっても良いかも知れない。 78834 | しかし、ユーザにカスタマイズの余地を残す、という意味では別のファイルになっていた方が親切である。 78835 | 78836 | * ble-decode-char: 78837 | 78838 | これをユーザの側で生成するのには時間が掛かるので、 78839 | 予め作成しておいた dump ファイルも一緒に配布するのが良い。 78840 | 78841 | 連想配列を使う版と使わない版の二種類だけで良い。 78842 | と思ったが、連想配列を使うか使わないかが影響を受けるのは、 78843 | cmap の側と言うよりは keyname の方なので、元々巨大ではない。 78844 | keyname の部分だけは ble.sh に統合してしまうと言う手もある。 78845 | 78846 | *.dump についても統合してしまうという手もあるが、 78847 | これについては中身が巨大なので余り統合する気にはなれない。 78848 | (でも、最終的には統合した方が綺麗かも知れない。) 78849 | 78850 | もしも統合しないのだとしたら、何れにしても複数ファイルになってしまう訳だから、 78851 | cmap+default.sh を ble.sh 内部に統合する意味も余り無い…。 78852 | というか、dump を一緒に配布する場合、 78853 | そもそも cmap+default.sh を実行する事はない筈である。 78854 | 78855 78856 ble.sh は益々肥大化しているのと、これからも様々な設定ファイルが増えていくだろうと予想されるので、 78857 single file で提供する事はもう考えない。 78858 78859 | * <bug> キャレットが編集文字列の先頭にある場合、prompt の最後の文字の SGR が反映されない。 78860 | 78861 | これに対応する為には prompt の指定から SGR を抽出するしかない。 78862 | 普通は prompt の最後の文字は空白にする (本当か?) ので気にしなくても良い気もするが。 78863 | 78864 | これを真面目に実装するには二通りの方向性が考えられる。 78865 | 78866 | 一つは zsh の様に PS1 の色・スタイルの指定を %[] の中でやって貰うという方法である。 78867 | これならば TERM に依存せずに解析できるので良い。但し、これは bash に非互換なので、 78868 | bash から何も設定を変えずに移る、という事ができなくなる。また、% の指定に対応し始めると、 78869 | その他の zsh の指定についても対応しないと収まりが悪い。全て実装しようと重うと大変である。 78870 | 78871 | もう一つは PS1 を頑張って解析して、ESC [ ... m から SGR の指定を取り出す方法である。 78872 | 現実的には ESC [ m 以外で SGR を解釈する端末が存在するとは思えないから、 78873 | これでも良い気がする。 78874 78875 これも bleopt_suppress_bash_output=1 の実装により重要性が低下した。 78876 一応 bleopt_suppress_bash_output= の問題点として残して置くが、簡単な一行の説明に収める。 78877 78878 | 2013-06-08 78879 | 78880 | * <bug> source を実行している間に C-c をして中断しようとするとその儘動きが止まる。 78881 | 通常のループなどで時間が掛かっている場合に C-c で止まる様にするには 78882 | trap return INT 等とすれば良かったが、source の内部で時間が掛かっている場合には、 78883 | C-c で止めようとするとそのまま全体の動きが止まってしまう様である。 78884 | 78885 | 序でに関数内のループで時間が掛かっている場合に関しても調べてみたが、 78886 | こちらは C-c で正常に中断する事が出来るようである。 78887 | 78888 | + 2013-06-11 12:29:07 78889 | 改めて試してみたら、ちゃんと停止はする様である。 78890 | accept-line.exec でループ構文を使わずに再帰に書き換えたがその事が影響を与えたかも知れない? 78891 | 或いは、これは前に試した時の勘違い? 78892 | 78893 | しかしながらまた例によって .ble-stty.enter が実行されていない様である。 78894 | 何故か分からないが処理の流れ的には正しくできている気がする。 78895 | しかし、処理の順番が入れ替わっている気がする。 78896 | exec.recursive から先に出力されるべき物が、プロンプトの表示よりも後になっている。 78897 | 後で再度調べ直す必要がある? 78898 78899 これは gexec の実装の際に色々試して trap - DEBUG の方向性で解決する事にした。 78900 これによってどんな場合でも確実に停止できるのではないかと考えている。 78901 具体的に source を使って検証した訳ではないが、関数では充分にテストしたので大丈夫だと考えている。 78902 もし問題があったら改めてその時に考える事にして、この項目も削除する事にする。 78903 78904 * <bug> info.draw で特殊文字が改行に跨っている時の座標計算 [#D0161] 78905 78906 例えば CR などの特殊文字を ^M と表示しているが、これが改行に跨って表示される。 78907 その時の座標がずれる。(そもそも改行に跨って表示されるのが誤り?) 78908 78909 →空白を挿入する様にしていたのだが、挿入する空白の長さを空白を挿入した後の値で計算していた。 78910 つまり空白を挿入する必要がないという解釈になっていた。式の評価の順序を正しい物に変更した。 78911 78912 * <bug> update-positions で dend-dbeg が負になると警告が出る [#D0160] 78913 →プロンプトの内容に変更があった際に初期位置 x y が変わる。 78914 その時の dbeg=0 の設定の際に dend や dend0 を正しく設定していなかった。 78915 78916 2015-02-22 78917 78918 * <bug> word の内容変化を検知する事のバグ [#D0159] 78919 78920 - transpose-chars 等を用いた場合 word の内容が変化しても word の着色が更新されないのではないか? 78921 →コードを見た所、単語内部で変更が起こった場合にはちゃんと ble-syntax/parse/touch-updated-word している。 78922 単語の終端点を巻き込んだ変項の場合には、否応なく parse で変更される筈なのでここで touch する必要はない。 78923 つまり、現状のコードでも問題が起こる事はないように思われる。 78924 78925 と思ったが正しくできていない。 78926 echo 'd'is't' で真ん中の is を tranpose して見たが、どうも期待通りに動いていない様だ。 78927 と思って調べたら、そもそも transpose した時には単語の切り出し自体に失敗している様だ。 78928 長さ 0 になっている。途中で解析が終わっている為であろう。 78929 78930 - 解析が単語の途中で終わった時に word が壊れない様にする為には? 78931 78932 これは真面目に考えなければ対応方法が分からないので後で考える。 78933 (そもそも単語が終了した所で前の位置 word[wbegin] に書き込むというのが混乱の元なのかも。 78934 データ形式から考え直した方が良いのかもしれない。) 78935 78936 眺めていたら簡単に書き換えられそうだったので書き換えた。 78937 _ble_syntax_word[]は単語の先頭ではなくて単語の終端に置く事にした。動いている。 78938 _ble_syntax_word を用いた dirty 拡大にも対応した。 78939 後 dirty 拡大の部分に問題を見つけたのでその部分も修正した。 78940 78941 * <bug> .ble-line-info.draw を使った時行がずれる [#D0158] 78942 78943 これは新しい描画関数で出力する様にした時に出力の順序を変えた所為だった。 78944 出力をバッファリングしている時には、その最中で別の複雑な関数を呼んではいけない。 78945 内部で独自に出力を行うかも知れず出力の順序 78946 (と _ble_edit_x, _ble_edit_y の参照順序) が変わるからである。 78947 78948 * <bug> for や do に色が着かない? [#D0157] 78949 78950 _ble_syntax_word_umin, _ble_syntax_word_umax の問題の様だ 78951 → ctx-redirect/check-word-end で wbegin=-1 を設定した後に touch していた所為で、 78952 _ble_syntax_word_umin=-1 になってしまい、範囲が無効化されていた様だ。 78953 ble-syntax/parse/touch-updated-word に assertion を追加した。 78954 78955 * 描画の高速化2: 現在の不具合と layer に対する対応 [#D0156] 78956 78957 | x 現在 update-positions で位置が変化しただけの部分に対しても表示用の SGR 付き文字列を更新している。 78958 | これは省略できる筈。改行やタブなどで出力内容に変化のある部分については別に記録して後で合成して表示する。 78959 | 78960 | x transpose-chars 等を用いた場合 word の内容が変化しても word の着色が更新されないのではないか? 78961 | 78962 | x word の属性が解除されてもそれが表示に反映されない。 78963 78964 先ず、word の属性が解除された時の動作について考える事にする。これは layer の実装方法にも関わってくる。 78965 word の属性が解除された時、元々其処にあった属性を復元したい。 78966 これは _ble_syntax_attr を参照して再度値を書き込めば簡単に実現はできる。 78967 しかし、今後 ble-syntax とは独立した形で様々な着色を行う事になると思われる。 78968 その際に _ble_syntax_attr やら更にその後に付加される word の着色に対して毎回参照したり計算したりするのは現実的ではない。 78969 様々な着色を分離した形で実装する為にはちゃんとした仕組みが必要になる。 78970 78971 改めて考えるにこの問題は、「word の着色をしても、概念的にはその下には syntax による着色が残っている」のに、 78972 それが word の着色によって失われてしまっているという事である。つまり、syntax による着色は依然として 78973 有効であり、word の着色が戻った時にまた有効になる物であるのに、それを上書きして消してしまっているという事である。 78974 本来は、word の着色やら syntax の着色やらを全て内部的に保持しておいて、表示の時に有効な物を選択して着色するという事が必要である。 78975 つまり、簡単に言うと layer 機能が必要になるという事である。 78976 78977 しかし、layer 機能を実装するに当たって考えるべき事がある。効率である。 78978 現状で何とかぎりぎりで現実的な速度で表示できるようになっているが、 78979 layer の機能を愚直に実装した場合、現在の高速化に使っている方法がそのままでは使えないのでかなり重くなる。 78980 現在の方法を何とか適用しようとしても結構面倒な操作が必要であり、どれぐらい遅くなるかは未知数である。 78981 78982 ここでは複数の方法について考え、また、layer としてどの程度の機能が必要に成るであろうかを整理する。 78983 もしかすると完全に layer の様なおおがかりな仕組みは実装しなくても良いかも知れない。 78984 78985 a 始めに考えた方法は、各 layer で着色された文字列を保持しておき、 78986 表示の際に有効な layer の部分をぱちぱちつなぎ合わせて実装するという物である。 78987 しかし、これは同じ layer に属する部分は連続している筈だ、という仮定に基づいている。 78988 様々な layer が滅茶苦茶に混ざり合っている場合には却って遅くなる。 78989 また、表示の際につなぎ合わせを実行するので部分更新であっても 78990 文字列の長さ (というか正確には上位 layer の着色範囲の数) に比例する時間が必要になる。 78991 78992 そもそも当初は「選択範囲の着色」や「括弧の対応」の着色が念頭にあった。 78993 これらは精々1つか2つの着色範囲しか持たないので、 78994 どんなに文字列が長くなったとしても繋ぎ替えの操作の階数は一定数に保たれる。 78995 しかし今後「各コマンドに対応した引数の着色」などに対応するとなると、 78996 これらも新しい layer として実装する必要があるし、かつ、 78997 文字列の長さに比例してつなぎ目も増えていく。 78998 78999 部分更新やカーソル移動だけでも一定の繋ぎ替えの操作が必要になるのは問題である。 79000 この方法は全く現実的ではない。しかし、この方法を改良すれば何とかなる可能性はある。 79001 79002 b 次に考えた方法は各 layer について色の配列を保持し、 79003 それを用いて表示する側で最終的な文字列を一つ構築するという方法である。 79004 そして部分更新の際には、各 layer の変更範囲を集計して最終的な文字列自体を書き換える。 79005 79006 これが一番自然な実装に思われるが多少問題点が存在する。 79007 「括弧の対応」の場合には離れた2点で局所的な更新が実行される為、 79008 単純な変更最小点と変更最大点の間を全て更新するという方法にしていると、 79009 変更範囲が無駄に大きくなってしまう。特に編集文字列全体を囲むような括弧の場合に 79010 毎回全体を更新するのと同じ事になり非現実的である。 79011 79012 この場合の対策は二つ考えられる。 79013 1 一つは変更範囲の管理方法を単純な最小点・最大点のペアではなくもっと詳細な物に変更するという方法。 79014 2 もう一つは、「括弧の対応」や「選択範囲」などの広い領域を cover する layer の場合には、 79015 自身の更新の特性を知っている筈で、そちらに編集文字列の update を任せるという方法。 79016 79017 普通は 1 の方向に進みそうな物だが、これだと実装が複雑になる。 79018 というかどの様なデータ形式にするのが良いのかも良く考えなければならない。 79019 単純に (begin,end)* の様な構造にすると例えばしましまに更新した時に更新範囲が複雑になる。 79020 しましまに近い時は複数の範囲ペアをくっつけて一つの変更範囲ペアにしてしまう方が効率が良い。 79021 しかし、この様にすると変更範囲の合成も無駄に複雑になる。却って合成操作に計算時間が掛かるかもしれない。 79022 というか 1 と 2 を組み合わせて、(1) 複雑な着色をする物に関しては (begin,end) を一組だけ報告させて、 79023 (2) 離れた点での着色になる物に関しては (begin,end) を分割して報告させるなど、 79024 変更範囲の報告を各 layer に任せてしまえば良いのかも知れない。 79025 変更範囲ペアがそれ程沢山にならないのであれば 79026 変更範囲の合成についても複雑な事を考えずに素直に実装して良い。 79027 79028 それでも未だ微妙な点がある。 79029 b.1 変更範囲が分かったとしても、どの layer が有効なのかの情報がないので、 79030 描画文字列を更新する際に上の layer から順番に描画属性が適用されているかを確認しなければならない。 79031 それも各文字についてこれを実行する必要がある。 79032 79033 しかし、これは別の方法を用いたとしてもループの順序が異なっているだけで等価な事をする 79034 必要があるのかも知れない?? でもこの方法だと b.2 に挙げる様な layer の最適化が適用できない。 79035 79036 変更範囲 pair に layer 情報を付加して対策するとしても、 79037 layer から着色が削除された場合については、 79038 結局着色が削除された部分についてどの仮想の layer が有効になるのかを計算しなければならない。 79039 特に下層の layer が複雑になっているかもしれないし、 79040 隣の変更範囲 pair と地続きになっている可能性を考えてくっつける事もできるかもしれないし#1、 79041 …など色々と再計算が複雑になってしまう。layer 情報を付加しても効果は限定的であろう。 79042 # #1 はこういう事である。層3 の属性を削除した時。更に層2、層1についても変更がある。 79043 # 更新範囲 <22><1><111> (更新の際に参照する範囲) 79044 # 変更操作 <33333><111> 79045 # 層3 ....... 79046 # 層2 <--> 79047 # 層1 <--------> 79048 # 変更操作としては二つの範囲であるが、 79049 # 実際に更新の際に参照する属性が載っている部分はより下層で分裂している。 79050 # 結果として三つの変更範囲が得られる事になるが、よく見ると<1> と隣の <111> の 79051 # 範囲は同じ layer を参照しているので無駄に範囲が分裂している事になる。 79052 # これらの無駄に分裂した物をくっつける事ができるか、或いはくっつけた方が良いのかという事である。 79053 # この様な分裂は大した問題ではない様にも思えるが本当にそうだろうか。考えてみると、 79054 # 最大で全 layer での削除範囲の合計x2 個の無駄な分裂が起こる…やはり大した問題ではない気がする。 79055 # n^(layer 数) 等の様なスケールだったら考え物だった、編集箇所の数に比例する程度なら問題ない。 79056 79057 b.2 region (選択範囲) だとか括弧の対応だとかはその着色を保持するのに配列を用意するまでの事は無い。 79058 region に関しては現在の mark と point だけで完全に記述できるし、括弧の対応に関しては 79059 配列の中は殆どの時に空である。というか、選択範囲の方も選択しない限り空である。 79060 79061 これらの sparse な配列に対しても全て描画属性が設定されていないか確認するのは無駄だ。 79062 79063 b.3 選択範囲が解除された時など、以前の状態に戻したくなった時に、 79064 また全て描画文字列を構築し直す必要がある。 79065 79066 しかしながら、以前に計算したのと同じ物を計算するのは気にくわないという事を除けば、 79067 これについては大した問題点ではない様にも思う。というのも以前の状態に戻したくなるという状況は 79068 頻繁には生じないからである。 79069 79070 これについてはおまけ的に解決できたら良いという指標で良いだろう。 79071 (これについて簡単な解決ができる方法の方が、 79072 将来的に別の問題が起こった時にも解決しやすい・汎用的だろうという程度の目安とする。) 79073 79074 c 以上を踏まえて (もしかしたら却って非効率かも知れないが) もう一つの方法についても挙げる 79075 79076 各 layer で「その layer 以下の描画属性を適用した状態の文字列」を管理する方法である。 79077 変更があった場合には、下の layer から順に変更範囲を上の layer に伝達し、 79078 下の layer は該当部分の変更を自分の持っている描画文字列に対して適用する。 79079 79080 しかしこの方法は既に挙げた問題を解決できていない。多少実装が楽になるだろうというだけである。 79081 79082 c.x1 複数の離れた変更範囲がある場合についての解決策にはなっていないので、 79083 結局複数の変更範囲 pair を扱う事になる。 79084 c.x2 次に、下層の layer の描画文字列の切り貼りをする為には、 79085 index 情報が必要 (各文字の表示にエスケープシーケンスを含めて何文字使っているか) であり、 79086 これらも独立した配列として管理しなければならない。 79087 例え選択範囲などの様な単純な描画属性に対してであっても、だ。 79088 c.o1 被覆されて実際には表示状態に変化を与えない下層の layer の更新が上部に伝達されない、 79089 というのは一つの利点ではある。しかし、その様な変化がある場合は稀であるし、 79090 結局内部的には下層の layer の保持する文字列に対する更新が行われている。 79091 79092 少しこの方法に改良を入れて考えてみる。 79093 「その layer 以下の描画属性を適用した文字の配列」と考える。 79094 一番上の layer でなければ繋げた文字列をそのまま使うとは限らない。 79095 それならばそもそも繋げなくても良いのではないか。 79096 この様にしておけば index 情報を別に覚えておく必要はなくなる。 79097 パラメータ展開に index を指定するだけで任意の部分列を取り出す事ができる。 79098 これで c.x2 の問題はなくなる。 79099 79100 | 但しカーソル移動をする時の為に index 情報は覚えておく必要がある? 79101 | とも思ったが、これも IFS= a="${cs[*]:i}" b=${#a} 等としてしまえば良い気がする。 79102 | そもそもカーソル移動は一回のキー入力に対して 1 回しか実行しないのだから、 79103 | 常に全ての位置についてのカーソル位置の為の index を保持している必要は全くない。 79104 | そればかりか、そもそも出力文字列に SCOSC SCORC を埋め込む形でカーソル位置を 79105 | 表現する必要性があるのかすら疑問である (一応この様にしておけば、何処か別の場所から 79106 | 出力があった場合 (や ble.sh の座標計算のバグがあった場合に)、 79107 | ずれても大丈夫というのはあるが。) 79108 | という事なので毎回 ${cs[*]::i} 等として文字列を連結して長さを数えれば良い。と 79109 | 思ったが、連結までするぐらいであれば ${cs[*]::i}$SCOSC${cs[*]:i} とすれば良いだけの気が。 79110 | 所で、この方法に頼っている時に、文字列が長くなると効率二度の程度の影響があるかは 79111 | 気になる所である。一般に編集はそれ程の速度で行われる事は無いが、カーソル移動は、 79112 | キーボードの押しっぱなし等によって相当の速度で入力される可能性がある。従って、 79113 | 編集の際には効率的に問題にならなくても、カーソル移動の際の効率に影響を与える可能性は残る。 79114 | 79115 | 追記: 現状の実装で index 情報を記録しているのは元々は別にカーソル位置を任意に 79116 | 取り出す為ではなかった。これは、キャッシュした文字列を任意に切り貼りできる様に 79117 | する為の物であった。後で、これがカーソル移動の際に SCOSC を挿入する位置として 79118 | 活用できる事に気付いた為に使っているだけの事である (とは言っても他に "効率的" に 79119 | SCOSC の挿入位置を決める方法、または、カーソル位置の確実な復元方法は分からないが。) 79120 | 79121 | また、連結した文字列は一番最後の layer だけで保持する事にすればよい。 79122 | →そう思ったが、連結した文字列を後で再利用しようと思ったら結局 index 情報が必要になる。 79123 | index 情報を一緒に管理しながら既存の文字列を切り貼りするのと、 79124 | 最後のレイヤーが出してきた配列全体を連結するのとどちらの方が効率的かという話になる。 79125 | 配列全体の連結でもそんなに問題はないかも知れない? 79126 | 79127 | 少し時間を計測してみる事にする: 79128 | 79129 | a=({1..100000}) 79130 | time IFS= eval 'b="${a[*]}"' 79131 | real 0m0.077s 79132 | bash の割に驚異的な速度である。 79133 | 79134 | time c="${a[*]::10000}""$ins""${a[*]:10000}" 79135 | real 0m0.200s 79136 | 多少時間が掛かる。でも 10 万の要素を連結している事を考えれば充分な速度だ。 79137 | コマンドラインに 100k も文字を書き込む事などない。10k でも多すぎる。 79138 | 79139 | index 情報によって文字列 b の中に於ける index が分かっている場合: 79140 | time c="${b::40000}""$ins""${b:40000}" 79141 | real 0m0.053s 79142 | 文字列にすれば滅茶苦茶速い、という訳でもない様だ。 79143 | (というかマルチバイトで記憶しているから文字数を数え上げなければならない、 79144 | という事なのだろうか?) 79145 | 79146 | 更に index 情報を用いているので、index 情報の更新も行わなければならない。 79147 | これだけ巨大な配列になってくると index 情報の shift にも相当の時間が掛かるだろう。 79148 | (何しろスクリプトで for でループを回さなければならない。) 79149 | 79150 | 色々考えるに index 情報を管理するのは効率的に駄目だ。 79151 | SCOSC でカーソル位置を管理したいと思う場合、 79152 | カーソル移動の際にも文字列を連結しなければならないのは惜しいが、 79153 | この辺りはカーソル移動を実際にやってみて遅ければ SCOSC は使うのを止めて、 79154 | ble.sh による座標計算を信用して update-positions のデータを元にカーソルの位置を動かす事にする。 79155 79156 結論 79157 - 各 layer 毎に「その layer 以下で計算される描画属性を適用した文字の配列」を管理・更新する 79158 - 実装の為に描画属性を持たない文字の配列も用意する。 79159 - 連結済文字列をキャッシュするのはやめる 79160 - index 情報の管理も行わない 79161 - カーソル移動の際は以下の 2 通りが考えられる 79162 - 配列の連結を用いて SCOSC を埋め込む (毎回全文字列を出力する) 79163 - update-positions を信用してカーソルを計算した位置に動かす 79164 79165 | 更に、もう一つ考えるべき事として各文字の一つ一つについて描画属性を付加するか、 79166 | 同じ属性の文字が続いている限りは描画属性の付加を省略するか、という事である。 79167 | 各文字一つ一つに対して描画属性を適用すると出力が無駄に長くなってしまう。 79168 | しかし、同じ属性の文字が続いている限りは付加を省略する、という形だと 79169 | 切り貼りをする際に切った点に新しく描画属性を追加しなければならないので、 79170 | 各点に於ける描画属性を別に管理する必要があるという事が問題になる。 79171 | 79172 | ユーザから見えなくても、余り汚い出力はしたくないので、 79173 | 各点に於ける描画属性を管理する方向性を考えたい。 79174 | さて、これはどの様に管理するのがよいかという事になる。 79175 | 79176 | A 一番簡単な方法は各点に於ける描画属性を配列に格納しておくという方法である。 79177 | 下層 layer から上層 layer まで、各層でその層以下の集約結果を配列として保持するという事である。 79178 | しかし、これは update がある度に各 layer で描画属性の配列をコピー・書き換えしなければならず、大変だ。 79179 | 特に、選択範囲や括弧対応の場合にはこの様な配列を管理し、一々書き換えを行うのは非効率に思われる。 79180 | 79181 | B そうではなく、各 layer について "描画属性を返す関数" を実装してその中で最も適した方法で 79182 | 属性値を計算し返すようにするというのも一つの手である。 79183 | 複雑な色付けを行っている場合には、単に内部で描画属性の配列を管理する様にすればよい。 79184 | さて、各 layer で独立に描画属性を管理する場合 (つまり、より下の layer の値について関知しない時)、 79185 | 下層 layer への問い合わせを順次行う必要がある (勿論、これは関数の呼出側で行う)。 79186 | これの overhead についても多少気になるが、 79187 | そもそも更新時の切り貼り自体そんなに沢山の箇所で行うとは思わないので、気にしない。 79188 | 79189 | (寧ろ全ての点について描画属性を即座に返せる様に配列で管理するという A の方が無駄である。) 79190 79191 結局、描画属性を後で必要とする頻度は小さいとして B を採用する事にする。 79192 つまり、各 layer について指定した位置での描画属性値を返す関数を用意させる。 79193 描画属性値が設定されず下位の layer に任せる場合には空文字列もしくは -1 を返させる。 79194 79195 さて、この様な実装を行うと決めたからには、再度描画用出力の生成関数を実装し直さなければならない…。 79196 後、既に書いたコードも利用できる様に、既に書いたコードを利用する layer も作った方が良い。 79197 或いは先にそれを書いてから実装を始める。 79198 79199 各 layer に関する関数名は ble-highlight-layer:*/* の形式にする。 79200 ble-edit.sh は複雑化して来たので、これらのコードは ble-color.sh の方に実装する事にする。 79201 ble-color.sh は当初 highlighter の類を記述する目的で作ったが、 79202 新しく ble-syntax.sh を作成した事で使われなくなった機能などが沢山ある。 79203 これらを整理・統合する目的もある。 79204 79205 実装した。動いている様なので差し替えた。 79206 79207 取り敢えず今回の実装で以下の項目は解決した。 79208 79209 | x 現在 update-positions で位置が変化しただけの部分に対しても表示用の SGR 付き文字列を更新している。 79210 | これは省略できる筈。改行やタブなどで出力内容に変化のある部分については別に記録して後で合成して表示する。 79211 79212 元々の目的である 79213 79214 | x word の属性が解除されてもそれが表示に反映されない。 79215 79216 に関しては未だ実装していない。レイヤーの仕組みを整えたは良いが、各レイヤーを実装する必要はある。 79217 word の属性を設定しているレイヤーをどの様に実装するのが良いかはまた別の問題である。 79218 これについては項目を改めて後で考える事にする。 79219 79220 2015-02-21 79221 79222 * 描画用のシーケンス構築を高速化する [#D0155] 79223 79224 色々考えた結果、最終的に (a) 描画用のシーケンスと 79225 (b) TAB 等の位置を制御しながら出力する update-positions を合成しなければならないので、 79226 a, b の両方を高速に合成可能な形に改良する必要があるという結論に到る。 79227 79228 update positions の側に関しては、 79229 出力の文字が事前に予測不可能な物は TAB 等限られているので、 79230 予測不可能な物に関してだけ合成時に特別な処理を行うという方向で行く。 79231 つまり、描画用の側で予測可能な文字についてのシーケンスを生成してしまう 79232 (予測不可能な物に関しては適当な可能性の高そうな文字列を入れておく)。 79233 update positions 側では出力する文字に関しては、 79234 特別な処理を行った物についてだけ記録を行う事にする。 79235 79236 現状の update-positions の実装について 79237 79238 | さて update positions では複雑な事を行っていて lc だとか lg だとかの計算も行っている。 79239 | これらの動作について今一度確認してからでないと update positions を弄れない。 79240 | 確認事項については以下の通り。 79241 | - lc lg の詳細な動作について。 79242 | 例えば行頭や行末での処理、複数文字で構成される文字の場合は? 79243 | - lc lg で計算した結果を使っている箇所は何処か? 79244 | それらの場所に影響が出ない様に書き換える必要がある。 79245 | 79246 | 取り敢えず何処で使っているかについて調べる事にする。 79247 | 先ず update-positions の中で出力している物は lc lk lj g である。 79248 | 79249 | | - _ble_line_text_cache_lc については、update-positions 及びその中から呼び出される 79250 | | save-cursor で設定されている。そして、.ble-line-text.construct で参照されて 79251 | | 変数 lc の戻り値を設定するのに使われている。lc は .ble-line-text.construct の戻り値か、 79252 | | 或いは編集文字列が空の場合にはプロンプトの構築によって計算された値になる可能性もある。 79253 | | lc はそのまま _ble_line_cur 配列の第2要素(base0)に格納される。 79254 | | _ble_line_cur[2] は .ble-edit-draw.update-adjusted の中で取り出されて、 79255 | | .ble-text.c2s を通してから READLINE_LINE に設定される。 79256 | | 79257 | | - _ble_line_text_cache_lk は update-positions 及び save-cursor で設定される。 79258 | | .ble-line-text.construct の中の初期の方に lk に代入されている。 79259 | | lk は .ble-line-text.construct の中のループで参照されているが変更はされていない。 79260 | | %%どうやら _ble_line_text_cache は lk の計算のキャッシュとして働いている様子である。%% 79261 | | 更に export する様なコードの残骸も残っている様だが関連するコードが見当たらないので、 79262 | | これに関しては廃止されてから久しい、或いは、何か書きかけて取りやめたという可能性が高い。 79263 | | さて、改めてよく見てみると lk は lg を抽出する為に使われている。つまり、 79264 | | カーソルの一つ前の文字を出力する時に使う lg が何かを計算する為には、 79265 | | カーソルの一つ前の文字の文字 index が必要になりそれが lk になっているという事である。 79266 | | lk はその他の用途では使われていない。 79267 | | 79268 | | - _ble_line_text_cache_lj はコメントの説明を見てもこれまた何の用途の為にあるのか分からない変数である。 79269 | | 実際に使われている所を見ると、多分これは以前に高速化を行おうとして実装し書けて終わった機能である。 79270 | | 改めてもう少し解釈を書いておく事にする。現在の実装では全ての文字について一々計算を行っている。 79271 | | しかし ASCII の印字可能文字が続いている場合には毎回計算しなくても位置や文字の計算は唯単に 79272 | | increment して行って設定するだけである。なので、その様な場合には最後の ASCII 文字まで 79273 | | 計算を抑えておいて、最後の ASCII 文字までいった時にそれまで溜めていた計算を一気に行う事ができる。 79274 | | lj は連続する印字可能文字の最初の位置を保持していると考えれば良い。 79275 | | 或いは、もっと実際的な機能としては次に本来の計算を実行するべき index という事になる。 79276 | | これがコメントに書かれていた説明である。 79277 | | 79278 | | しかしながら、一気に計算を行うと言っても、カーソル位置計算は簡単にはできないので 79279 | | 結局毎回計算をする事になっているという具合である。今は常に lj=i-1 の状態でループが回っている。 79280 | | カーソル位置計算についても一気に行うコードを書いたら (或いは、単純な increment を続けられる 79281 | | という事が分かる範囲を計算して、その範囲内だけで一気に行う様にしたら) lj を実際に遅延させるコードに 79282 | | 移行する予定であったのだろうと予想される。 79283 | | 79284 | | 何れにしてもこの変数は実装の詳細というか、最適化の為に用意した物であるので、 79285 | | 今回位置から実装し直すにあたってこの機能を継承する必要性はない。 79286 | | この変数について実装は未だ不完全であるし、似たような機能が必要になればまた新しく考え直した方が良さそうである。 79287 | | 79288 | | - _ble_line_text_cache_g _ble_line_text_cache_ei 79289 | | 何とこの配列は現在は使用されていない。現在の実装では .ble-text-line.construct の中で 79290 | | _ble_region_highlight_table から直接 g を読み取って使っている。 79291 | | 元々は任意のカーソル位置にある g を取得する為に使っていたという事だろうか。 79292 | | しかしそれは _ble_region_highlight_table から読み取れば良い事だし、 79293 | | そればかりか _ble_region_highlight_table からの lg の読み出しですら、 79294 | | 描画SGRと update-positions の合成のループを毎回するので、その中でおまけ的に処理している。 79295 | | 79296 | | と思ったが、もしかするとこれは最適化によって消えた変数ではなくて、 79297 | | 最適化の為に導入しようとして結局導入には到らなかった変数なのではないだろうか。 79298 | | _ble_line_text_cache_ei という似た様な位置で定義されていて使われていない変数があるので、 79299 | | 多分そう言う事だろう。これらの変数は未だ使われていない変数である。 79300 | | 79301 | | - _ble_line_text_cache_cs の意味は明確である。表示の為に出力される文字である。 79302 | | 使い方も単純で .ble-line-text.update-positions で値を fill して、 79303 | | .ble-line-text.construct の合成のループで中身を読み出すという物だ。 79304 | | 上記の2行以外では参照も代入もされていない。 79305 | | 79306 | | - _ble_line_text_cache_x, _ble_line_text_cache_y は _ble_line_text_cache_lc 79307 | | と全く同じ経路を辿って、別の関数で使われている。 79308 | | つまり、cx cy という変数に一旦入って _ble_edit_cur に格納され、 79309 | | その後其処から読み出されて使われている。 79310 | 79311 | まとめると、 79312 | - _ble_line_text_cache_x, _ble_line_text_cache_y, _ble_line_text_cache_cs 79313 | が主な計算の目的である。 79314 | - _ble_line_text_cache_lc, _ble_line_text_cache_lk 79315 | は左側にある文字の文字コードと sgr を求めるのに使う。 79316 | 文字幅などの情報は出力しない。 79317 | - _ble_line_text_cache_lj _ble_line_text_cache_g _ble_line_text_cache_ei 79318 | は実装しかけて中断している機能の為の変数の様に思われる。気にしなくてよさそう。 79319 | 79320 | さて、次にしらべるべきなのは lc と lk の処理方法の詳細についてである。 79321 | - 左側に複数文字からなる文字があった場合や、 79322 | 改行があった場合の取り扱いはどうなっているのか 79323 | →複数文字からなる文字があった場合にはその最後の文字を READLINE_LINE に設定している。 79324 | 79325 | 79326 | - 左側の文字の開始位置 (x y) の管理はどうなっているのか 79327 | →これは単に文字コード lc から計算される幅を使ってカーソル位置を ESC [ D 79328 | で後退させるだけという実装になっている。なので lc さえあれば良いという考えだ。 79329 | - 出力する sgr は本当に常に左側の文字の物で良いのか。 79330 | もしそうならば何故 i-1 等ではなく lk という変数が存在するのか。 79331 | →行頭の場合には右側の文字 (なければ空白) を READLINE_LINE に設定して 79332 | READLINE_POINT=0 を設定する様になっている。 79333 | 79334 | * lc が "文字列" ではなくて単一の "文字" である理由 79335 | READLINE_POINT に設定する値を計算する必要があるから。 79336 | 文字列であっても各文字についてバイト長を計算すれば READLINE_POINT を計算できるが面倒だ。 79337 | 単一の文字だけというルールにしておけば一回 c2bc を呼び出すだけで済む。 79338 | 79339 | * lj で計算を遅延している理由 79340 | 79341 | これは行頭の文字が来た段階では右側に来る文字を予測できないからである。 79342 | 右側の文字が確定してから lc を計算する。 79343 | 79344 | > 改めて見てみると lj 周りの実装が少し複雑になっている。 79345 | > カーソル位置が行頭にあるのが何回か続くと lj が更新されずに続く事になる。 79346 | > これは一体何の為の物だろうか??? 79347 | > 行頭が何回か続くとその後で一気に更新が実行される。 79348 | > 79349 | > lj が何の為にあるのか漸くわかった。これは「カーソルが行頭にある場合には 79350 | > 左側にある文字ではなくて右側にある文字の情報を返す」という仕様に関係している。 79351 | > 行頭に文字がある時には未だ次に文字が来るのか別の改行文字が来るのか分かっていない。 79352 | > 右側に通常文字が来た場合にはそれで良いが、改行文字が来た場合には改行を出力する訳にも行かないから、 79353 | > 代わりに空白文字を出力する事にするのである。そしてそれど同時に READLINE_POINT を 0 にする。 79354 79355 現状の実装がどうなっているかについては大体分かった。一番処理を複雑にしているのは lc lk の計算である。 79356 然し、ここで思ったのだが何故 lc lk を毎回計算してキャッシュしているのかという事である。 79357 x や y に関しては初めから順に計算して累積していかなければ計算する事ができない。 79358 なのでカーソルを移動するたびに計算するよりは前に計算した物を再利用した方が速い。 79359 しかし lc lk に関しては x y cs のキャッシュさえ残っていればどの様な物になるかはその場で計算できる。 79360 ループの中で累積的に計算し、その時の状態をキャッシュする仕組みにしていると先読みができないのでアルゴリズム的に苦しくなるが、 79361 x y cs を全て update した後に必要な所だけ計算するという事にすれば先読みも何もあった物ではなく簡単に計算できる。 79362 それに分離した方が bleopt_suppress_bash_stdout に応じて計算するかしないかの選択もできる。 79363 79364 取り敢えず x y cs だけを計算してその後でカーソル位置の lc lk だけを計算する様に簡単化した version の 79365 .ble-line-text.construct を作成してみる事にする。 79366 →様々なバグや bash の不具合が途中で見付かった為に随分と中断してしまったが、 79367 .ble-line-text.construct の単純 version は直ぐに実装できた。 79368 79369 さて使ってみるとバグが出てきた。C-u 等をした時に表示内容が変になる。 79370 保持している文字列は正常の様だから、shift に失敗しているのではないかという気がする。 79371 と思ったが、そもそも送られてくる BLELINE_RANGE_UPDATE の時点で変だ。 79372 10 文字ある文字列の 5 文字目で C-u を実行した場合 (0 0 5) 等となる筈だが、 79373 (9 10 9) という値が入っている。というか、これは最後に追加した文字の分である。 79374 79375 何処で変な事になっているのか調べる。 79376 先ず ble-edit/dirty-range/update の呼出を調べる。 79377 ble-edit/dirty-range/update 0 0 5 等となって正しい値が設定されている様に見える。 79378 では結果の _ble_edit_str_dbeg の類はどうなっているか? →これも問題ない。 79379 79380 分かった。やはり .ble-line-text.construct が悪かった。 79381 dirty<=0 の時に shift が行われていなかった。 79382 (9 10 9) という物が表示されている様に見えていたのは、前回の shift の時に出力した物を見ていただけであった。 79383 dirty<=0 の時には shift がそもそも行われていないので、その前後に設置した出力にも引っかかっていなかったという事である。 79384 これを修正したらすぐに動くようになった。 79385 79386 次に、.ble-line-text/update-highlight-layer を実装した。 79387 これは更新の必要のある部分だけ出力データを更新する物である。 79388 特に、色付けの変わった文字の部分について再計算を行う。 79389 現在は update-positions によって位置が変更された部分についても再計算を行っているが、 79390 これは将来的に削除して、update-positions による更新は別の所で処理する予定である。 79391 79392 さて、新しく実装したはいいが動きが変だ。 79393 特定の状態にある時にカーソルを移動するだけでも位置がどんどんずれていく。 79394 と思ったら、これは dbeg<0 なのにこれを変更開始点としてしまっている所があった為だった。 79395 単に dbeg>=0 を付け忘れていただけですぐに直った。 79396 79397 未だカーソルの移動が遅いと思って色々試していたら、 79398 どうやら ble-syntax-hightlight+syntax の中が重い。 79399 parse は更新された範囲だけに対して処理をしているので遅い筈はない。 79400 というかカーソルの移動の時には呼び出されない。という事は、 79401 その後の属性値の適用が重いという事になる。 79402 取り敢えず umin, uend を用いてその範囲だけ属性値を更新する様にした。 79403 それでも遅い。どうも word に対しての処理が重い様である。 79404 良く考えたら毎回各 word に対してファイルかどうかの判定を行っている。 79405 これは確かに重かろう。修正した。 79406 79407 さて。次の問題。属性値の適用を _ble_syntax_attr_umin ~ uend 79408 の間に限った事によって問題が生じている。 79409 "word による着色" がなくなった時に再び属性値を _ble_syntax_attr から 79410 復元しなければならないが、 "word による着色" は _ble_syntax_attr_umin 79411 等の管理の範囲外である。これを正しく実装する為にはやはり layer の様な仕組みが必要となる。 79412 しかし layer の仕組みを実装するに当たってどの様にすれば良いかについては申し越し考える必要がある。 79413 79414 ここでは、以下の問題点を挙げて一旦閉じる事にする。 79415 - "word による着色" がなくなった時にその部分の着色がなくなるべき 79416 79417 2015-02-20 79418 79419 * bash-3.1 ESC [ の受信について [#D0154] 79420 79421 bash-3.1 での ESC [ を受信する為に、以前の修正で ESC [ を CSI に変換していた。 79422 然し、今回 bash-4.3 で C-@ を受信する為に C-@ (0) を UTF-8 の 2-byte 符号で受信し直す様にした。 79423 この方法を用いれば ESC [ も "ESC の 2-byte 符号" + "[" として受信し直す事ができる筈だ。 79424 この様にすれば ble-decode-char に特別なコードを書き込んで 79425 CSI を無理矢理 ESC [ に戻す等という事をしなくても済みコードも綺麗になる。 79426 79427 変更した。正しく動作している。 79428 79429 * <bug> C-x a 等に対して x が読み取られる。 [#D0153] 79430 79431 ble-decode-byte を見てみた所ちゃんと 24 97 が受信されているのでこれは bind の問題ではない。 79432 その後の文字の処理の問題か、キーの処理の問題である。 79433 79434 今度は .ble-decode-char の方で何が受信されているかを確認する。 79435 UTF-8 decode に問題があるとは思われないので、ここでも 24 97 になっている筈である。 79436 →果たして 24 97 になっている。OK 79437 79438 今度は .ble-decode-key の方で受信されている物を確認する。 79439 67108984 97 が受信されている。67108984 は 16 進数に直すと、0x4000078 である。 79440 これは Ctrl フラグと 78 = 'X' の組合せになっている。この時点でも問題点は内容に思われる。 79441 とすると問題があるのは .ble-decode-key の中で行われている処理だろうか。 79442 79443 と思ったら今迄の処理にかなり問題があるという事が分かった。 79444 というか段々思い出してきた。色々書き換えようと思って弄っている途中で中断していたような気がする。 79445 (或いは、訳が分からなくなったが取り敢えず動いているから良いという事にしたのだったか。) 79446 79447 - 先ず、.ble-decode-key.invoke の KEYS に代入される値について。 79448 ${var//_/ } ではなく ${var//_/} になっているので key 分割に失敗する。 79449 79450 - .invoke-default で最後に入力された文字だけを見て既定の関数を呼び出している。これは変だ。 79451 というかそもそも invoke-default はこのタイミングで呼び出すべき物なのかも謎である。 79452 79453 - また、.ble-decode-key.invoke に失敗した時に _ble_decode_key__seq をクリアしているので、 79454 .ble-decode-key.invoke && return 79455 fallback 79456 とした時に fallback に辿り着く時には _ble_decode_key__seq の情報が消えて無くなっている。 79457 _ble_decode_key__seq= は呼出側で処理する事にする。 79458 79459 - 一致に失敗したというエラーを出力してから途中一致する物がないかを探索している。 79460 失敗したと表示したのに何かを実行するのは変ではないか? 79461 でも複数のキーからなるシーケンスで失敗した場合にはその複数のキーについてエラーメッセージが表示されて欲しい。 79462 79463 例えば、一致に失敗した時に 79464 1 遡って適用できるシーケンスがないか探す。見付かればそれを処理して終わり 79465 2 もし任意のキーに対する既定の動作が設定されていれば、それを処理して終わり 79466 3 何も設定されていなければ全体のキーについてのエラーメッセージを表示する 79467 と言う処理にすれば良いのではないかと思う。x 79468 79469 さて、これを実装する為には…遡って適用できるシーケンスが見付かって実行した時点で制御を呼出元に戻したい。 79470 が、現在の emit の再帰呼び出しの方法だとそれができない。emit 関数を再実装する必要がある様に思う。 79471 79472 また良く分からなくなった。何が望ましい動作なのだろうか。 79473 ble_opt_error_kseq_discard の意味を変えた方が良い様な気がしてきた。 79474 現在の実装を見ると ble_opt_error_kseq_discard になっている場合は部分一致がある場合でも捨てる事になっている。 79475 しかしそうではなくて、部分一致すら見付からなかった時に残っている 79476 キーの列をどの様に処理するかというのを制御したいのではないか。 79477 部分一致について処理しないようにしたいのであれば、そもそも keymap にそういう物を登録しない様にすれば良いだけの話である。 79478 keymap に色々設定しておいてから、ble_opt_error_kseq_discard で部分一致なバインドを 79479 on/off にするという使い方も可能ではあるが直観的ではないし、何が便利であるのかも分からない。 79480 79481 ここで、ble_opt_error_kseq_discard は部分一致も見付からなかった場合に残っている出力を捨てる為の設定とする事にする。 79482 79483 再実装した。すっきりした。 79484 79485 * <bug> C-@ を受信できていない @ bash-4.3 [2015-02-11] [#D0152] 79486 79487 > * bash-4.3 C-@ について 79488 > 79489 > bash-4.3 になって bind -x が三文字以上に対して使える様に bugfix されたが、 79490 > 同時に C-@ を含むような系列に対して bind が正しく処理されなくなった。 79491 > 現在 bash-4.3 において C-@ を捕捉する事は出来ていない。 79492 79493 bind -X を見ると確かに 79494 "\C-@": "ble-decode-byte:bind 0" 79495 が登録されているのだが受信できない様だ。 79496 79497 $ bash 79498 $ bind '"\C-@":"test" 79499 $ bind -s | less 79500 $ bind -x '"\C-@":"echo test"' 79501 $ bind -X | less 79502 79503 とここまで来て C-@ を押したら 79504 bash_execute_unix_command のエラーが発生するという事に気付いた。 79505 (ちらつきを抑える為に bash の出力を殺したのは良くなかったかも知れない) 79506 →bash の出力をファイルに書き出して、それをチェックする事にした。 79507 エラーを吐き出していればそれを visible-bell で表示する。 79508 79509 仕様がないので "C-@ *" に関しても全て登録する事にした。 79510 →"C-@ *" に割り当てても駄目なようだ。 79511 というか C-@ を何度も押しても C-@ を続けている限りはエラーも起きない。 79512 つまり C-@ に関連して bash は何か特別な処理をしている? 気がする。 79513 79514 % 2015-02-19 79515 % 79516 % 現在の所 bash-4.3 において keymap が見付かりませんでしたと表示されるのは 79517 % C-@ だけなので、keymap が見付かりませんでしたエラーを受信したら C-@ 79518 % を受信したという事にしてしまうというのも一つの手である。 79519 % これは既に bash-3 で C-d を受け取るのに使用している方法を使えば良い。 79520 79521 念のため他の version ではどうなっているかも調べておく。 79522 bash-4.2 は C-@ は普通に受信できる。bash-4.0 でも普通に受信できる。 79523 bash-3.2 OK。bash-3.1 OK。やはり bash-4.3 だけで C-@ が受信できない。 79524 79525 bind -x ではなく単に bind '"\C-@":"hello"' 等とすると正しく受信できると分かった。 79526 ならば bind '"\C-@":"\xC0\x80"' 等としてしまえば問題ない。 79527 "\xC0\x80" は UTF-8 の表現方式で 0 を表す。 79528 (但し、UTF-8 は或る code point を表すのに最小の長さの符号化を要求するので、 79529 上記は正しくない、或いは、正規化されていない表現、という事になる。 79530 何れにしても、これは直後に .ble-decode-char+UTF-8 で 0 に翻訳される一時的な物なので問題はない。) 79531 →これで呆気なく動くようになった。 79532 79533 2015-02-19 79534 79535 * <bug> 4.3, 3.1 いつの間にかに日本語が入力できなくなっている。いつから? [#D0151] 79536 79537 3.1 は別の問題であった。独立した項目にする。 79538 79539 4.3 では無効なシーケンスですという(自分で書いた)エラーメッセージが出る 79540 3.1, 3.2 では謎の文字が入力される。というか ^# と表示される。 79541 4.0 では何故か入力できる。"あ" とすれば 227 129 130 が UTF-8 で受信されている。 79542 4.2 でも入力できる。 79543 79544 あ E3 81 82 79545 79546 と思っていたらいよいよ全ての version で読み取れなくなった。 79547 今迄読み取れていたのは何だったのか…。良く分からない。 79548 .ble-text.c2s と .ble-text.s2c を弄っただけの筈だが何故だろう。 79549 スクリプトが行けないのかと思って色々試したがよく分からない。 79550 79551 と思っていたらそもそも受信している byte が 129 130 だけになっていた。227 が何処かに消えている。 79552 というか ESC にも bind できていない。色々とおかしい。 79553 79554 何でか分かった。bind に使う文字をどの様に生成するかが関係していた。 79555 bind に使う文字は utf-8 でエンコードして渡しては行けない。 79556 直接バイトを指定するか、そうでなければエスケープシーケンスを用いて渡す必要がある。 79557 直接バイトを指定すると別の文字とくっついたりして変な事になりそうなので専らエスケープシーケンスを用いる事にする。 79558 79559 79560 2015-02-20 79561 と思ったら今度は \C-_ \C-[ \C-] \C-^ 等が動作しなくなった。 79562 \C-@ も今迄エラーメッセージが表示されていたのに、今は bell が鳴る。 79563 と調べてみたら、この部分の変更が原因になっていた。 79564 通常文字までもエスケープシーケンスを用いて表現してしまった為に、 79565 \C-_ \C-[ \C-] \C-^ が \C-\135, etc になってしまっていた。 79566 エスケープシーケンスにするのは 127 以上の文字 (8bit 文字 + DEL) だけにして解決した。 79567 79568 * <bug> bash-3.1, .ble-text.s2c が日本語に対して正しく働いていなかった。 [#D0150] 79569 79570 先ず 3.1, 3.2 で化けている事について。 79571 内部的には正しく入力できている様なのでこれは簡単に解決できるだろう。 79572 79573 ^# 等という文字はないよ?? と思ったが、恐らく C-# とデコードされているのだろう。 79574 と思ったがやはり変だ。info.draw でも ^# と表示されているこの文字は一体何か? 79575 info.draw では特別なデコードは行っていない筈である。 79576 改めてみてみると文字コードについて 0 以上であるという仮定に基づいた処理になっている。 79577 負の文字コードになっているのであろう。 79578 そしてそれは文字デコードのエラーフラグが立っている事を示す? 79579 と思って ble_decode_Erro を確認したが別に符号ビットではなかった。 79580 というか符号ビットを立てるような富豪はないように見える。^# とは一体何なのか…。 79581 79582 うーん。そして実際に出力してみると正しく "あ" と入力されている様子である。 79583 表示だけが変になっているという事の様である。これは一体どういう事なのか…。 79584 改めて見てみると .ble-text.s2c が怪しい。 79585 実際に試してみたら果たして -29 という値を吐き出している。 79586 79587 そしてこれがどの様に実装されているかというと結局 79588 printf '%d' "'あ" 79589 の様な事をしている。これを実行してみると確かに -29 と表示される。 79590 これは utf-8 で "あ" を構成する初めのバイト 227 を signed char で解釈した時の値である。 79591 さて、とすれば bash-3 で unicode の文字コードを取得する正しい方法を考える必要がある。 79592 試しに 79593 /usr/bin/printf '%d' "'あ" 79594 等としてみたら、227 と表示されて、変な文字が余っているというエラーを出力した。使えない。 79595 79596 bash-3.1, 3.2 では "${a:b:c}" の形式ではバイト単位ではなく文字単位の操作しかできないし困った…。 79597 decode してしまったのが問題だったという事なのか。でも、補間の場合など ble-decode-byte 79598 以外を通して入力される文字列もあり、これらも正しく表示する為には ble-decode-byte+UTF-8 79599 で逐次キャッシュを作成するという方法は使えない。やはりちゃんと計算する方法が必要である。 79600 79601 うーん。どうやら 79602 while read -n 1 a; do printf '%d' "'$a"; done <<<"${text:i:1}" 79603 とすれば何とかできる様ではある。fork するよりは速いだろうか。 79604 79605 或いは、c2s があるならば二分法で攻めるという手もあるかもしれない。幸い utf-8 は順序を保存する。 79606 と思ったが c2s 自体が bash-3 では絶望的に遅いので二分法はしたくない。 79607 79608 * <bug> bash-4.2 が segfault する。算術式中の配列要素に関係して。 [#D0149] 79609 79610 | 何処で落ちるのかと調べてみたら .ble-edit-draw.redraw の中である。 79611 | 更に調べてみると以下の様な何の変哲もない部分である。 79612 | 79613 | local dbeg dend dend0 79614 | ((dbeg=BLELINE_RANGE_UPDATE[0], 79615 | dend=BLELINE_RANGE_UPDATE[1], 79616 | dend0=BLELINE_RANGE_UPDATE[2])) 79617 | 79618 | と、ここで思い出したのだが何かの bash の version が、 79619 | 一つの算術式の中で複数の配列参照を行うと落ちるという問題があった様な…。 79620 | 少し試してみた: ((x=arr[1],y=arr[2])) これで落ちる。 79621 | これは面倒臭い。かなり大幅な書き換えをしなければならない。 79622 | というか patch を当てるんだったらこの動作についても patch を当てて欲しい。 79623 79624 算術式の中で配列を使うと segfault する問題について。 79625 79626 | 算術式の中で配列要素を参照すると、次の token に添字が適用されている様だ。 79627 | 79628 | 算術式の中で配列要素を参照して代入すると segmentation fault する。 79629 | 算術式の中で2回以上配列要素の値を参照すると segmentation fault する。 79630 | 例えば ((x=arr[1],y=arr[2])) で落ちる。 79631 | 代入するのは平気な様である。また、参照すると必ず落ちる訳でも無い様だ。 79632 | 79633 | 配列でない変数に対しても同様に落ちる。 79634 | 評価時というよりは構文解析時に落ちているのかも知れない。 79635 | 括弧で括っても駄目だし、カンマ以外で区切っても駄目。let でも駄目。'' で囲んでも駄目。 79636 | 結局、安全に評価する為には、複数の参照がない様にするべきなのか? 79637 | 79638 | 調べたら http://osdir.com/ml/bug-bash-gnu/2013-01/msg00042.html に報告が上がっている。 79639 | http://osdir.com/ml/bug-bash-gnu/2013-01/msg00043.html で解決したという事になっているが。。 79640 | 4.2.39 で少なくともエラーが発生していた様だ。手許の bash-4.2 は 4.2.53 なのだが。。 79641 | もしかして 4.3 には適用されたけれども 4.2 には結局適用されなかったという事か? 79642 | 79643 | 所で上記ページで報告されている ((a=b[1],b=1)) という式を試してみたが、これでも落ちる。 79644 | つまり、配列に対する参照を複数回行った事が問題ではないという事。。うーん。 79645 | どの様な時に落ちてどの様な時に落ちないのか。。 79646 | 79647 | うーん。gdb で見ると配列添字が来るはずの所に次の tok が来ている。 79648 | 例えば ((a=b[1],b,c=1)) とすると問題なく動く。 79649 | ((a=b[1],c,d=1)) でもOK。評価結果も異常はないように見える。 79650 | また ((a=b[1],0,c=1)) とすると落ちる。((a=b[1],0)) は OK。 79651 | ((a=b[1],c,d=b[2])) も OK。 79652 | というか何故か分からないが配列に対する代入を実行しようとしている? 79653 | つまり、"配列添字" が次の tok にも適用されてしまっているという事か? 79654 | 79655 | ((a=b[1],1+1,d=b[2])) これは落ちるが、 79656 | ((a=b[1],c+1,d=b[2])) これはOK。 79657 | ((x=(c=123,a=b[1],c+1))) これもOK。評価結果 $x も問題ない。 79658 | 79659 | 所で速度比較を行ってみる。 79660 | ((a=arr[i%3]));((b=arr[i%2+1])) 79661 | ((a=arr[i%3],dummy,b=arr[i%2+1])) 79662 | 殆ど違いはない様だ。dummy= として挟んだ方が微妙に速いという程度。 79663 79664 何れにしても ble-syntax.sh で大量の算術式を使ってしまったから、 79665 これは大変な書き換えだ…と思って実際に書き換えてみた所、 79666 意外とクラッシュのパターンになっている式は少ない様だ。 79667 書き換えたら簡単にはクラッシュしなくなったので取り敢えずはこれで一件落着とする。 79668 79669 全ての実行パスについて試した訳ではないので未だクラッシュする罠が残っているかもしれないが、 79670 それは落ちてから考えれば良いという事にする。 79671 79672 * ble-decode.sh: bind C-x の変更 [#D0148] 79673 79674 改めてテストしてみた所 C-x 単体に対して bind して segfault するのは 4.2 だけの様だから、 79675 bash-4.2 の時にだけ "C-x *" のペアで bind する事にした。 79676 ペアで登録していると2文字目が入力されるまで C-x が届かないので、 79677 その他の bash の version では "C-x" 単体で bind する事にする。 79678 (とはいいつつ、emacs keymap の設定だと C-x C-x 等の key binding があるので結局は 79679 ble.sh の内部で 1 文字目の C-x が pending する事になる訳だが)。 79680 79681 また、これに伴って既定で bind されている "\C-x *" が上書きされなくなるので、 79682 bind -sp で列挙した物を全て bind -r する事にした。 79683 今迄は "\e" で始まる物しか bind -r していなかったが、そんなに速度が変わる物でもないだろう。 79684 79685 + C-x は 4.2 だけの問題化と思いきや、3.1 がクラッシュした。 79686 79687 改めて複数の version で確認を取る事にする。 79688 3.1 は先に述べたように落ちた。具体的には C-x C-b C-b 等として落ちた。 79689 3.2 も同様に C-x C-b で落ちる。4.0 も同様に落ちる。 79690 結局 C-x C-b 等と打って落ちないのは bash-4.3 だけである。 79691 79692 結果として bash-4.2 の時にだけ "C-x *" ではなくて、 79693 bash-4.2 以下の時は全て "C-x *" で bind する事にした。 79694 79695 79696 * <bug> 日本語を入力すると位置がずれる @ 4.0 bleopt_suppress_bash_output= [#D0147] 79697 79698 →どうも 4.0 は 3 と同じ様に bind -x の前後でプロンプトを消去する様だ。 79699 という事で bind 前後のコードを 3 と共通の物にした。 79700 79701 また、C-d を捕捉する事もできていない。これについても対応した。 79702 と思ったら、どうも C-d が捕捉できなかったのは、bind 前後のコードを 79703 3 と共通の物にした所為で IGNOREEOF が設定されてしまった所為であった。 79704 4.0 では READLINE_LINE が存在するからわざわざ IGNOREEOF を設定する必要はない。 79705 4.1 用のコードと同じように READLINE_LINE を設定すれば良い。 79706 79707 という事で bind 前後のコードの分岐を増やす事にした。 79708 bash の bind -x 関数の呼出の前のプロンプトの消し方に応じて _ble_bash>=40100 で分岐するのと、 79709 bash が READLINE_LINE 変数を用意しているかどうかに応じて _ble_bash>=40100 で分岐するのを区別する。 79710 79711 しかしそれでも未だログアウト時のメッセージの表示位置が変になっている気がする。 79712 その他のコマンドの実行の時にはずれていないからそれ程問題という訳でもない。 79713 これは後で対処する事にする。■ 79714 79715 * <bug> 4.0 日本語を入力すると (( の中で日本語を使ったという文句が出る。 [#D0146] 79716 どこかの算術式に文字列が紛れ込んでいるのだろうか。 79717 79718 と思ったら関係ない所を直したら何故か動くようになった。 79719 と思ったが、直した箇所は adjusted をするかどうか、 79720 つまり READLINE_LINE を用いて bash の出力を制御するかどうかの部分である。 79721 つまり、問題点は adjusted の部分である。 79722 もう一度 READLINE_LINE を用いる様に正しく修正して試してみる。これで問題が再現するはず。 79723 79724 再現した。カーソルの位置と出力されるタイミングから言って、 79725 これは明らかに adjusted の中から発生している。 79726 adjusted の中身は弄っていないから lc の計算方法を変更した事が原因であるのは明らかである。 79727 79728 どうやら .ble-text.c2w が $ret 変数に値を返すはずなのが何も値を設定していない様である。 79729 前回の値の "あ" というのが残っている。 79730 もっと調べてみると、どうも ret に予め "あ" 等の文字列が入っていると 79731 ret を計算する為の筈の算術式の評価に失敗してしまう様である。 79732 ret は代入される側なので予め入っている値が何であれ関係ない等と思っていたが、 79733 良く考えてみたら算術式の評価の方法上 ret の中身を展開してまで数式として解釈する筈で、 79734 ret に何が入っているか分からない状態で算術式を起動するのは危険という事である。 79735 79736 ble-decode-byte+UTF-8 でも似たような問題がないかと確認してみたら、 79737 此方の方は全く問題はなかった。こちらは計算した値を使ってそのまま 79738 decode-char を呼び出す様になっていて、 79739 外部の関数が用意した変数に値を設定して制御を返すという方式ではないので、 79740 未初期化の変数が算術式の中に登場するという事は無い。 79741 79742 * <bug> bleopt_suppress_bash_output= にした時にプロンプトが二重になる [#D0145] 79743 79744 暫く bash の出力を抑制して処理を行う様にしていたが、 79745 試しに bleopt_suppress_bash_output= を再度設定して動かしてみた所、 79746 bash がプロンプトを出力する様になっていた…。 79747 何故だろう。bind/tail の直後に PS1 をファイルに出力しても PS1 は空だ。 79748 bash が PS1 の内容を覚えているという事だろうか? 79749 でも同じ version で少し前には正しく動いていたはずである。 79750 79751 どうも blerc デフォルトの .bashrc をロードした時になる様だ。 79752 しかし何故だろうか。何か変な PROMPT_COMMAND が設定されているのかとも思ったがそういう訳でもない。 79753 79754 どうやら bind -x したコードの内部で PS1 を弄っても反映されない様だ。 79755 外で PS1 を設定する必要があるという事。 79756 今迄は ble.sh ロード時に PS1= を設定していたので、それがずっと生きていて動いていたが、 79757 .bashrc をロードすると PS1 に新しく値が設定されてしまうので駄目という事。 79758 79759 よく考えたら、今迄もプロンプトが表示されてからすぐに入力をしたりすると 79760 表示が乱れるなど思い当たる事が他にもある。プロンプトが表示されるのが ble.sh をロードした直後なのに 79761 その後に未だ .bashrc 等の処理を行っていたのが原因である。 79762 その時間差の間に何かを入力した事によって表示がずれていた。 79763 79764 思うに ble.sh のロード・初期化と、実際にアクティブにする attach の操作を分離すべきである。 79765 ble-initialize ble-attach ble-detach 関数を定義する事にした。 79766 また ble.sh に noattach の引数を渡した場合には、その場での attach をしない様にした。 79767 必要な場合は後で ble-attach を呼び出して貰う事にする。 79768 79769 →これで一応 bleopt_suppress_bash_output= の時にも動作する様になった。 79770 bash-3.1 の場合にも C-d を正しく捕捉できない事を除けば正しく動作する様になった様に見える。 79771 (とはいいつつやはりちらつきは気になる。) 79772 79773 * <bug> ble-detach が動かない [#D0144] 79774 79775 まとめ 79776 - awk のエラーメッセージが tmp/$$.bind.save に混入していた 79777 - awk の -v var=value の中の value はエスケープシーケンスが解釈される 79778 - bash-4.3 bind -X で表示されるコマンドは特別なエスケープがされていて bind -x では使えない 79779 79780 > 色々あるが取り敢えず $_ble_term_fghr と言った類の物が直接表示されている。 79781 > 79782 > 後、awk を呼び出そうとしたり何か変だ。取り敢えず分かり易い所から。 79783 > $$.bind.save の中を覗いてみる…と思ったら awk のエラーメッセージが bind.save の中に混入している: 79784 > awk: 警告: エスケープシーケンス `\'' は `'' と同等に扱われます 79785 > 79786 > するべき事は、 79787 > - awk のエラーメッセージは別の所に出力されるべき 79788 > gawk の幾つかの version からは "/dev/fd/数字" を用いる事ができるのでそれが利用できる。 79789 > 但し少し古い version の gawk で動かなければ結局これは積極的には採用できない。 79790 > - メッセージの通りエスケープシーケンス \' に対する処理を行う。 79791 > 79792 > 何と awk -v APOS="'\\''" 'BEGIN{print APOS;exit}' だけでエラーになる…。 79793 > awk -v apos="'" 'BEGIN{print apos "\\" apos apos; exit}' はエラーにならない。 79794 > つまり -v で渡したパラメータに含まれるエスケープシーケンスを解釈するという事??? 79795 > 調べてみたら POSIX レベルでそう動作する事になっている様だ。 79796 > [[bash - Should awk expand escape sequences in command-line assigned variables? - Stack Overflow>http://stackoverflow.com/questions/13808909/should-awk-expand-escape-sequences-in-command-line-assigned-variables]] 79797 > 79798 > 1回 ble-detach して再び ble-attach するとまたプロンプトが2重になる。 79799 > →これは .ble-edit/edit/attach での guard が1回しかロードされない事を前提とした物だった事による。修正した。 79800 > 79801 > 1回 ble-detach して再び ble-attach して、更に ble-detach すると 79802 > detach できていない。それに加えて "bash: : コマンド見付かりません" というエラーになる。 79803 > コマンドを実行しようとすると実行できずに、実行コード全体を一つのファイルと見做して実行しようとしている?? 79804 > 79805 > と思ったら ble-decode-byte:bind が復元対象に入っていた。 79806 > 復元対象に入らない様に awk でチェックしていたはずなのにと思って確認したら 79807 > ble-decode-bind と指定していた事によりチェックが正しく機能していなかった。 79808 > また、それとは別に復元の仕方にも問題がある。 79809 > "à": "ble-decode-byte:bind 224; eval \\\"$_ble_decode_bind_hook\\\"" 79810 > 等と、過剰にエスケープされている。これについてもう少し詳しく。 79811 > 79812 > 始めに attach した直後には bind -spX すると以下の様になる。 79813 > "\C-@\C-@": "ble-decode-byte:bind 0 0; eval \"$_ble_decode_bind_hook\"" 79814 > その後で ble-detach してもこの結果は変わらない。 79815 > この次に ble-attach した後に bind.save を見ると 79816 > bind -x '"\C-@)": "ble-decode-byte:bind 0 41; eval \"$_ble_decode_bind_hook\""' 79817 > 等となっている。問題はない様に見える。が、これで登録すると先程の様な事になるという事か。 79818 > 79819 > →色々 bind -X の出力を調べるとコマンドの中に制御文字が含まれているとエスケープされる様だ。 79820 > 先ず " と \ は \" と \\ に変換されている。また DEL は \C-? になり ESC は \e になる。 79821 > それ以外の制御文字 (0~31) は \C-なんとか の形に変換される。 79822 > これらを元の文字に復元する簡便な方法は存在しない様に思われる (bash の機能を使ったとしても)。 79823 > 仕方がないので awk で変換のコードを書く。面倒なので gsub を繰り返し適用する方針で。 79824 > →これで取り敢えず正しい bind -x コードを出力する事ができる様になった。 79825 > 79826 > さて、これを解決したらすっかり ble-detach が動くようになった。 79827 > bleopt_suppress_bash_output=1 でもちゃんと問題なく動いている様に見える。 79828 > 何度も ble-attach, ble-detach を繰り返しても動いている。 79829 79830 2015-02-18 79831 79832 * 履歴展開の対応 [#D0143] 79833 79834 ^string1^string2^ の形式の履歴展開の場合、順に入力しても履歴展開と認識されない。 79835 というか :x 等の modifiers も順に入力しても履歴展開に含まれない。 79836 79837 解析再開点を履歴展開の直前に置いておくか、何らかの単語?として取り扱わないと駄目。 79838 (「この点までは stat に値を設定しない」という変数を用意して、 79839 先読みを実行した場合にその変数に値を設定するというのも興味深い方法である。) 79840 79841 後、試して気付いた事だが !!$:a 等と定義されていない修飾子を指定すると、 79842 単に履歴展開をせずに実行されるのかと思いきや、履歴展開のエラーになってコマンドが実行できない。 79843 このエラー報告と整合性のある色付けにしたい。 79844 結局、履歴展開についても内部の文法構造を気にして実装するという事になるのだろうか。 79845 79846 他にも s/../../ や ^..^..^ は途中で中断すると空文字列を指定したとして解釈される事も分かった。 79847 説明書に書かれていない動作が色々あるが、この動作であれば却って順に入力していけば 79848 正しく全体が履歴展開として解釈される。 79849 適当に実装したが現状で大体OKなのではないかという気がする。 79850 79851 * CSI → ESC [ 翻訳について [#D0142] 79852 79853 現在 bash-3.1 ESC [ → CSI や、ESC ESC → ... を default keymap に設定しているが、 79854 その他の keymap の時に処理されないのは問題である。 79855 例えば isearch の時に bash-3 では矢印キーが使えない事になる。 79856 もっと前の段階で変換をするべきなのではないか? 79857 79858 charmap はそう切り替わる物でもないので charmap のレベルで受け取った CSI を 79859 ESC [ に変更するという方法があると良い。できればハードコードするのではなく一般的な枠組として。 79860 →と思ったが一般的な枠組にすると強力すぎる様に思うので取り敢えずは 79861 char==91 に対してハードコードして介入する事にした @ .ble-decode-char 79862 (utf-8 CSI を送信する様な端末があった場合にもこれで対応できた事になる…が、そんな端末があるかは不明。) 79863 79864 * <完> bash-3 で C-d を捕捉する方法? [#D0141] 79865 79866 今は IGNOREEOF を大きな値にして即座にログアウトされない様にしている。 79867 所で C-d を押すと 79868 Use "exit" to leave the shell. 79869 だとか 79870 ログアウトする為には exit を入力して下さい 79871 だとか 79872 シェルから脱出するには "exit" を使用してください。 79873 だとか言ったメッセージが出力される。 79874 79875 現在 bleopt_suppress_bash_stdout を設定している場合には 79876 bash のエラーメッセージはファイルに書き込まれるので、 79877 このファイルを読み取る事で C-d を押した事を検知する事は出来る。 79878 79879 但し、押された事が検知できるのは C-d が押された後に初めて別のキーが押された時である。 79880 C-d では何もイベントが起きてくれないので。 79881 79882 強引な手だが、常にファイルを監視する子プロセスを作成して、ファイルに Use "exit" ... が書き込まれたら 79883 シグナルを $$ に送ってそこで処理するという手が使えるかも知れない。 79884 しかし子プロセスで常にファイルを開いて確認するのでリソースを食う。余り使いたくない方法である。 79885 79886 また或いは bash のエラー出力先にコプロセスを置いておきそこで受信をするという手も…。 79887 こちらの方が未だましである。もしかしてこれで行けるんじゃないか…と思って実装してみた。 79888 動いている…と思いきやすぐにエラーを吐いて終了する。 79889 trap -- 'myfunc' USR1 79890 するだけでもエラーになって死ぬので、行っている処理の問題ではなさそう。 79891 代わりに RTMIN を使ってみたがそれでも同じエラーが発生する。 79892 trap -- 'echo hello' USR1 79893 という程度であれば何も起きない。trap の中で関数を呼び出すのが駄目という事だろうか。 79894 79895 もしかしてシグナルハンドラの処理中にシグナルハンドラが呼び出されている?? 79896 或る程度処理に時間が掛かる関数を設定するとエラーになって死ぬという事だろうか?? 79897 →必要な時にだけ呼び出す様に変更したら動くようになった 79898 (とはいいつつもシグナルによって動作しているので流石に遅い。しかし何とか動いているので良しとする。) 79899 →と思ったが内部で呼び出している mv を止めたらそんなに遅くはなくなった。fork はやはり重いという事か。 79900 79901 > 2013-06-13 79902 > 79903 > * 制限: bash-3 では C-d を捕捉する事ができない。 79904 79905 取り敢えずこれは解決したとして良いだろう。 79906 79907 * ble-edit.sh, ble-decode.sh: bugfix, bash-3 でカーソルキーの類が動かない。履歴が読み込まれていない。 [#D0140] 79908 79909 これらの原因は同じ物であった。高速化の為にコードを生成してそれを直接 source していたが、 79910 その為に source とプロセス置換を組み合わせたのがいけなかった様だ。 79911 bash-3 では source はプロセス置換から読み取ってくれない。 79912 (パイプからは読み取らないというポリシーなのか、 79913 或いはシークできないと実行できないという事なのか分からないが。) 79914 79915 source <( ... ) を eval -- "$( ... )" に変更。 79916 79917 2015-02-17 79918 79919 * ble-syntax (ble-syntax-highlight+syntax): 入れ子エラーの色の範囲 [#D0139] 79920 例えば "(( echo" 等の場合。 79921 閉じていない入れ子構造がある場合に、入れ子構造の開始字句をエラー色にしている。 79922 しかし、一文字目しか色を付けていない為、入れ子開始の字句が複数文字で構成される場合に不格好である。 79923 字句単位で色を付けられるように fill-g 関数を修正し、それを用いる事にした。 79924 79925 * ble-edit.sh (accept-line): - で始まるコマンドを実行できない。 [#D0138] 79926 履歴展開の為にコマンドを history に渡した時に history へのオプションとして解釈されていた。 79927 というか eval も - で始まるコマンドを扱えないし、history -s で履歴に登録する事もできない。 79928 eval に関しては -- 以降はコマンド部分として解釈される様なのでそれを用いる。 79929 よく bash の man を読んでみたら組み込みコマンドの章の一番上の部分に -- について書かれていた。 79930 79931 * <bug> ble-syntax.sh: 1"$1" と入力してから先頭の 1 を消すと単語情報が壊れる。 [#D0137] 79932 単語の長さが再計算されていない事による物と思われるが良く分からない。 79933 79934 落ち着いて現在の実装でどの様な振る舞いになるはずかについて考える。 79935 1"$1" の時は 1 の部分に単語情報が格納されている。 79936 ここで 1 を削除すると単語情報も消えて無くなる。 79937 次に 1 の部分から解析が始まるがこの時に新しく単語の開始点が設置される。(長さ 0) 79938 所が (単語の開始点が前回と一緒である為) 単語の末端に達する前に解析が終了する。 79939 79940 さて後段で前方の単語への参照を保持しているはずで、 79941 参照している単語開始点が編集の対象だった時は dirty 範囲をそこまで拡大する手はずになっていた筈だが。 79942 見てみると編集の対象かどうかの判定が [i1,i2) になっている。 79943 これは単語の先頭で編集が行われた場合にその単語は編集されていないという判定である。 79944 これについてはもう少し考え他方がよいのかも知れないが 79945 単純そうな [i1,i2] に変更する事にする。(単純な物の方が大概自然である。) 79946 79947 % どの様にしなければならないかというと。 79948 % 単語情報を削除してその場に新しく単語情報を追加する場合、 79949 79950 * <bug> ble-syntax.sh: ${1}1${1} の状態で真ん中の 1 の直前に空白を入れると壊れる。 [#D0136] 79951 他の部分に空白を入れたり空白以外の文字を入れても何も起こらないが、 79952 該当箇所に 1 を入れた時にだけ壊れる。 79953 79954 試行錯誤 79955 > これについても現在の実装でどうなっているのかについて調べる。 79956 > 79957 > 先ず shift の際に何が起こるかについて。${1}2${3} → ${1} 2${3} 79958 > とずらした事で単語の先頭 (${1}の前) に対する参照が更新される事は無い。 79959 > 単語の先頭は編集位置よりも前にあるからである。 79960 > …よく考えたら、${3 を読み取ろうとした時点で inest/wbegin の値が一致してしまうので 79961 > 其処で単語の読み取りが終了してしまう事になる。 79962 > 別の単語の中にいながら局所的に同一の文法状態になる事が原因で途中で解析が終了しているという事だ。 79963 > 79964 > 本当か? ではなぜ echo ""2${3} → echo "" 2${3} の時には問題が発生しないのか? 79965 > 残っている情報 79966 > ${ を読み取る直前の wbegin は "" の先頭にある。 79967 > ${ を読み取る直前の inest は -1 である。 79968 > ${ まで読み取った時の wbegin は -1 である。 79969 > ${ まで読み取った時の inest は ${ の先頭の位置にある。 79970 > 新しい解析 79971 > ${ を読み取る直前の wbegin は 2 の先頭にある。 79972 > ${ を読み取る直前の inest は -1 である。ここは不一致なのでここで停止する事は無い。 79973 > ${ まで読み取った時の wbegin は -1 である。 79974 > ${ まで読み取った時の inest は ${ の先頭の位置にある。ここで一致する気がするのだが…。 79975 > dirty-range の拡大も考慮に入れる事にする。 79976 > dirty-range の拡大は wbegin/inest の参照先が編集範囲内にある時に発生する。 79977 > ${ の外側では wbegin inest は常に wbegin=0 inest=-1 になっている。 79978 > これは dirty range の拡大には寄与しない。 79979 > ${ の内側では wbegin inest は -1 及び ${} の先頭になっている。 79980 > そしてこの先頭 of ${ は編集の対象ではない。つまり dirty-range の拡大は起きない。 79981 > →もっと色々試してみた結果 79982 > (字句単位1)(字句単位2)(字句単位N)${3} の時に、 79983 > 字句単位1 の直後に空白を挿入する場合は OK で、 79984 > 字句単位2以後の直後に空白を挿入する場合に駄目になるという事が分かった。 79985 79986 原因 79987 "(字句単位1)(字句単位2)(字句単位N)${3}" に空白挿入 の際: 79988 - 字句単位1の直後に空白を挿入する場合には再開点が単語の先頭になり、 79989 単語の先頭も編集対象としてマークされる為に単語全体が更新対象になり問題が発生しないという事の様だ。 79990 - しかし、字句単位2 の直後に空白を挿入する場合には再開点は字句単位2の先頭になり、 79991 単語全体は更新の対象とは見做されない事になる(ここまでは期待している動作である)。 79992 所が、その後で内側のネスト状態に入った所で局所的に前回の解析と同じ状態になり停止するという事のようだ。 79993 - また、字句単位N の直後に空白を挿入した場合には ${3} 全体が更新対象になるのでやはり問題は発生しない。 79994 79995 対処 79996 79997 局所的な文脈の一致ではなくて全体的な文脈の一致まで考慮しないと問題が残る。 79998 例えば現在の実装ではネストレベルが異なる場合でもネストの開始位置さえ同じであれば文脈が一致したと解釈してしまう。 79999 実装当初には「ネストの開始位置さえ一致していれば文脈的には同じ構造に戻ったと見做しても良い」 80000 という想定を行っていたが実際にはネストの開始位置が同じであっても文脈の構造が変化した可能性があるという事だ。 80001 80002 例えば (CTX_EXPR の中で) ( を上書きして [ にした場合などがこれに含まれるのではないかと思う。 80003 これは類似のまた別の問題だ。現在の文脈情報に開始括弧の情報を含めていない事による。 80004 開始括弧の対応まで一致しているかどうかを確認する為には [inest] の type が同じかどうかまで確認しなければならない。 80005 これの比較を怠っている事は結構不味い。 80006 80007 結局、細心の注意を払ってすれすれで実装するのではなく、安全確実な方法を採る方が良い。 80008 つまり、現在のネスト情報を親まで全部含めた形で記録して一致するか確認を行う。 80009 その為のネスト情報をどの様に記録するのが良いか? 80010 80011 > 一番簡単なのは stat に全ての情報を入れてしまう事である。しかしもう少し効率化できないだろうか。 80012 > 再開の為に必要なのは stat に現在記録している 3 つ組だけである。 80013 > 後は自動的に pop によって情報が復元されていく。 80014 > さて、stat には3つ組しか記録しない様にして、 80015 > 更に比較を行う為にその場で inest を辿って stat を掘り返す事にするのは非効率である。 80016 > 代わりに初期の nest 状態だけ復元して、 80017 > その後は push/pop する時に nest 状態を更新するというのはどうだろう。 80018 > しかし、この方法で現在の解析の nest 状態を更新する事は出来るが、 80019 > 前回の解析の nest 状態を追跡する事は出来ない。push/pop の情報は記録していないからだ。 80020 > 80021 > 仕方がないので stat に全てを記録してしまう事にする。 80022 > 幸い _ble_syntax_stat を参照しているのは殆ど ble-syntax/parse だけなので、 80023 > この関数内での取り扱い方法だけ変更すればOKである。 80024 > と思ったが…もし stat にネストの全階層を記録していると shift が滅茶苦茶な事になる。 80025 > 80026 > というか現在 _ble_syntax_nest に対しては shift を実行していないがこれについても shift する必要があるという事か。 80027 > 前回使った _ble_syntax_nest は今回は使わないので shift を実行する意味はなかったのである。 80028 80029 うーん。面倒だ。取り敢えず動くようにする為には 80030 1. _ble_syntax_nest もシフトする様にする 80031 2. _ble_syntax_nest を掘り返して文脈が一致するかどうか確認する 80032 という事になる。掘り返すのは効率的かどうかは疑問だが取り敢えず実装する。 80033 (今迄問題にならなかった事から、そもそもそんなに掘り返さなくてもすぐに不一致になるのかも。 80034 改めて考えてみるに其処まで性能の劣化になる様にも思われないのでこれで良い事にする)。 80035 80036 2015-02-16 80037 80038 * ble-syntax.sh: 単語終了判定の処理の変更 [#D0135] 80039 80040 ble-syntax/parse/word-end の判定は 80041 字句単位の開始時ではなくて字句単位の読み取りの終了時にするべき? 80042 というのも単語を部分編集するとその単語の長さが 0 になってしまうから。 80043 これは単語を部分編集した時の更新範囲が典型的にその単語の末端までになるので、 80044 解析もその単語の末端までで終了してしまう事が多いから。 80045 然し乍ら、word-end は次の字句単位の読み取りの際に呼び出されるので 80046 その字句単位の終端を設定する機会がないという事になる。 80047 80048 % しかし、もし word-end の判定を字句単位の終端時に行う事にすると 80049 % 別の問題が発生する。単語の末尾に字句を追加した時に単語が伸張してくれない。 80050 % というのも字句の直前で既に単語が終了している事になっているからである。 80051 80052 再開した時に正しく再開できる様にする為の簡単な条件は、 80053 その点での解析状態が次の文字に依存してはならない、という事である。 80054 しかしそれは少々無理がある。次の文字が分からなければ 80055 字句単位がそこで終わるのかどうかさえ定かではない為である。 80056 そこで、現在は解析の再開は変更のあった点ではなく「その点よりも前の最近の再開点」としている。 80057 80058 従って、其処で単語が終了するかどうかの判定もやり直されるのではないかという気がする。 80059 例えば、単語の末尾に文字を追加する事を考える。文字を追加した時に解析の再開は 80060 追加した文字の箇所で起こる訳ではない。追加位置の一つ前の再開点から開始される。 80061 そして一つ前の再開点の時点では未だ単語は終了していない事になっている筈だから、 80062 正しく単語は伸張されると期待される。 80063 なので、取り敢えず字句単位の終わりの時点で単語の終了を判定する様に書き換えてみて動くか見る。 80064 80065 呆気なく動いている。此方の方が実装としても単純だし自然である。 80066 →初めは CTX_CMDI の類の文脈が成功した時しか単語の終了判定をしていなかったが、 80067 実際に色々やってみると、nest から抜けた場合や 80068 CTX_CMDI の文脈で認識されないエラー文字があった場合にも 80069 そこに単語の終了が来る可能性があるという事に気付いたので、 80070 任意の ctx の処理の後に単語終了判定を置く事にした。 80071 →今後、"ctx の処理の後の ctx" に応じて適切な単語終了判定を行える様に 80072 WORDEND[ctx] 的な配列に関数を入れる事にしても良いかも知れない。 80073 80074 * ble-edit.sh (_ble_edit_str, ble-edit/dirty-range): 変更範囲の合成について [#D0134] 80075 80076 入力文字列に対する部分変更があった時に、全体を計算し直すのは非効率である。 80077 どの様な変更があったのかを記録しておき、変更がなかった部分の計算については省略するのが得策である。 80078 その為には部分変更を何らかの方法で表現・記録しておかなければならない。 80079 ここでは str1 → str2 への変更操作を 80080 str2="${str1::beg0}$ins${str1:end0}" 80081 の形に一般化して考える事にする。 80082 この時 str1 の [beg0,end0] の範囲が str2 の [beg,end] になったと考える。 80083 beg=beg0 であり end=beg0+${#ins} である。この時変更範囲を 80084 (beg, end, end0) の三つ組みで表す事ができる。 80085 80086 今考えたいのはこの様な変更操作を 2 回行って str3 を得た時に、 80087 str1 から str3 への部分変更をどの様な三つ組みで表せるかという事である。 80088 ※勿論自明な解として (0, ${#str3}, ${#str1}) 等を考える事ができるが、 80089 今はできるだけ共通部分を長くしたい、 80090 つまり、変更部分の長さ end-beg を最小にしたいのである。 80091 80092 式で考えようとしたが式の上での場合分けが面倒だ。 80093 str1 -(dbeg dend dend0)→ str2 -(beg end end0)→ str3 の時 80094 i2 = i1<begA?i1: i1<endA0?-1: i1+(endA-endA0) 80095 i3 = i2<begB?i2: i2<endB0?-1: i2+(endB-endB0) 80096 80097 記号的に場合分けするのではなく、もう少し具体的に場合分けを考えた方が良い。 80098 str1 = A [ B ] C → str2 = A | X | C となったとする。 80099 更に str3 に入る時に何処に切れ目が入るか ("[]" で表す) で分類できる。 80100 (1) str3 = A0 [A1] A2 | X | C 80101 (2) str3 = A0 [A1 | X0] X1 | C 80102 (3) str3 = A0 [A1 | X | C0] C1 80103 (4) str3 = A | X0 [X1] X2 | C 80104 (5) str3 = A | X0 [X1 | C0] C1 80105 (6) str3 = A | X | C0 [C1] C2 80106 先ず beg は明らかに min(begA, begB) である。 80107 次に end は max(endA-endB0+endB, endB) である。 80108 end0 は end から逆算できる。或いは end の由来を考えて場合分けすれば良い。 80109 end が endA-endB0+endB の時は endA0 がそのまま end0 になる。 80110 end が endB の時は end0 = endB0-endA+endA0 になる。 80111 80112 式で書くと: 80113 beg = min(begA,begB) 80114 end = endB + max(endA-endB0,0) 80115 end0= endA>endB0? endA0 : endB0-endA+endA0 80116 = endA0 - (endA-endB0>0?0:endA-endB0) 80117 80118 整理すると: 80119 beg = min(begA,begB) 80120 end = endB 80121 end0= endA0 80122 if((del=endA-endB0)>0) 80123 end+=del; 80124 else 80125 end0-=del; 80126 80127 数式での間接参照? 80128 alpha=111 beta=alpha*2 pref=bet 80129 echo $((${pref}a)) 80130 → ちゃんと 222 になる。。bash-4.3, bash-4.1, bash-3.1 で確認した。 80131 80132 2015-02-13 80133 80134 * <完> グローバルで実行するという事? [#D0133] 80135 80136 % 次の様な関数で eval すればグローバルで評価できるかも。 80137 % 少し試した段階では問題は生じていない。 80138 % 80139 % geval () { trap -- "$*" RTMAX; kill -RTMAX $$; } 80140 % 80141 % + 何とジョブ管理にも正しく登録される様である。 80142 % グローバルな変数は勿論定義される。 80143 % 80144 % + 返却値については流石に kill の戻り値としては入っていないが中で適当に拾えば良い。 80145 % geval () { trap -- "$*"$'\n'"echo exit=\$?" RTMAX; kill -RTMAX $$; } 80146 % (改行で区切る様にしないと $* が & や ; で終わっていた時に文法エラーになる。) 80147 % 80148 % 後 trap の内容を復元する為に 80149 % | originalTrap="$(trap -p RTMAX INT)" 80150 % | ... 80151 % | trap - RTMAX INT 80152 % | test -n "$originalTrap" && eval "$originalTrap" 80153 % 等とすると良いかもしれない。 80154 % 80155 % 但し、この様にコマンド実行中だけ ble の用意した trap を実行していると、 80156 % コマンド実行中はユーザの trap した内容が実行されないという事に注意する。 80157 % (外部コマンドの場合には bash ではなく外部コマンドがシグナルを受け取れるので問題ないが、 80158 % シェル関数の場合にはユーザが予め設定した trap でシグナルを受け取る筈だ。) 80159 % 80160 % + C-z 時の返却値 → OK 拾える 80161 % C-c 時の返却値 → 駄目。拾えない。これは今迄と同じ。なので INT に trap する。 80162 % INT の復元もした方が良い? → $(trap -p RTMAX INT) とするだけなので気にしなくて良い。 80163 % 80164 % + jobs で kill -RTMAX $$ と表示される。 80165 % といっても kill -RTMAX の待ち状態という訳ではないようだ。 80166 % 証拠に geval の次のコマンドは geval 内のコマンドで C-z した直後に実行されるし、 80167 % また、geval 内部で二つの less を呼び出して両方とも C-z しても正しく実行される。 80168 80169 と思ったら幻想だった。そもそもグローバルで実行していない。 80170 現在の文脈のままでシグナルハンドラが呼び出されている様だ。 80171 つまり、シグナルハンドラが関数内の環境に影響を与えられるという事。 80172 80173 今の所グローバルで実行できるのは bind -x だけしかない気がする。 80174 しかし bind -x した物を呼び出す為にはユーザに何か入力をして貰わないといけない。 80175 (入力を再現する方法が有れば良いがそれをシェル内から実行する方法はない気がする)。 80176 或いは何とかして readline の accept-line を呼び出す事ができればよいが。 80177 80178 うーん。汚い方法ではあるが、 80179 bind -x で "ble-decode-byte:bind 1 2 3; eval \"$_ble_onafter_bind\"" 80180 等として任意の物を外で実行できる様にしておくとか。。 80181 →この方針で実装してみた。存外問題なく動いている。 80182 80183 * <完> 現在の C-c のトラップの実装に関する疑問 [#D0132] 80184 80185 return で良いのか? return が使えない場合があるかも? 80186 →サブシェルを作らずに同じプロセスで実行する場合、 80187 内側の環境になるのは関数か source しかない。 80188 つまり、一番外側でない限りは return が使える。 80189 つまり、現状の様に関数内で実行している限りは return は常に使えるという事。 80190 80191 return で正しく抜ける事ができるのか? 80192 一番内側の 関数/source しか抜けられないのでは? 80193 或いは、入れ子になっている場合に誰が受信するのか? 80194 80195 | 実験 80196 | 80197 | trap INT はどの様な場合に働くのか? 80198 | 直接 $ sleep 10 に対して C-c しても trap されない。trap が動く条件は? 色々試した。 80199 | 何か変だ。殆どの場合で動かない様に思われる。 80200 | bind -x の中からだとまた違った結果になるのか、それとも現在の実装は問題があるのか…。 80201 | $ trap -- 'echo INT $a' SIGINT 80202 | $ sleep 10 →× 80203 | $ : $(sleep 10) →○ 80204 | $ echo 10 && sleep 10 →× 80205 | $ sleep 10 && echo 10 →× 80206 | $ (sleep 10) && echo 10 →× 80207 | $ func1() { sleep 10;}; func1→× 80208 | $ プロンプトが表示されている時に C-c→○ 80209 | $ for ((i=0;i<100000;i++)); do :; done→○中断する 80210 | ループ内では trap できて、しかも自動的に中断されるという事 80211 | $ fib1() { (($1<=1)) && eval $2=1 && return; fib1 $(($1-1)) ${2}L ; fib1 $(($1-2)) ${2}R; let $2=${2}L+${2}R; }; fib 20 x→○中断する 80212 | 関数の再帰呼び出しも trap できて、しかも自動的に中断されるという事 80213 | $ trap 'echo INT $2=${!2};return' INT; fib 20 x→○中断しない 80214 | →何度 C-c を押しても最後まで抜けられない…。return があるかないかで動作が異なる様だ。 80215 | $ for ((i=0;i<100000;i++)); do :; done→○中断する 80216 | →これは単純に return ができない為に return をしなかった場合と同じ動作をしているという事。 80217 | 結局 trap の動作は return コマンドを書いたか書かなかったかではなく、実際に return しているかしていないかを見ている。 80218 | 80219 | 分かった事 80220 | - trap INT は現在の文脈 (関数内/source内) で最大1回だけ実行される 80221 | 子プロセスが INT を受け取った場合などには受け取らない。 80222 | - 唯単に trap INT するだけの場合、シェル内で行われている全ての処理が自動的に中断される 80223 | - trap INT の中で return 等を実行した場合は、return の後で処理が続行される 80224 | 80225 | これを受けて C-c を受信した時にどの階層まで抜けるかをコントロールする方法は: 80226 | - 一気にシェルの処理を終了したい場合には trap の中で return 等を書かない。 80227 | - 一つ上の関数・source に戻りたい場合は trap の中で return を書く。 80228 | - 但し、関数呼出を沢山行っている場合 C-c で抜ける事ができなくなる可能性がある。従って return は書かない方が良い。 80229 | 任意の階数の関数・source を抜ける方法はない。 80230 80231 結論 80232 80233 現在の実装は関数の再帰呼び出しなどを C-c で停止する事ができない。 80234 →実際に試してみた for ループは抜けるが再帰呼び出しはその場では抜けられない。 80235 (一応各再帰呼び出しは抜けている様である。その為に、 80236 C-c をすると fib1 の結果が変わる (前回の呼出の時の結果が残っていると正しい結果になるが)) 80237 →これは C-c によってシェル内の無限ループを止める事ができなくなる可能性がある事を示す。よくない。 80238 80239 trap で $_ble_hook_INT 等として後処理をする関数を付け加え、return はしない様にするべき? 80240 →これだと local で変数が被覆されている場合などに正しく対処できない。 80241 まあ _ble_... を宣言しなければ大丈夫である。 80242 80243 実際にその様に実装してみたら問題がある。 80244 どうやら bind -x の中で実行している場合には return しないとそのまま実行が継続する様である。 80245 return すると現在の呼出階層だけは抜ける事ができるので以前はその様に実装していたという事か。 80246 以下はその前提で書いてみたコード。結局これは使えないという事になった。 80247 > &pre(agh-prog-bash){ 80248 > function .ble-edit/exec2/eval-prologue { 80249 > .ble-stty.leave 80250 > 80251 > # 履歴置換 80252 > set -H 80253 > 80254 > # C-c に対する trap 80255 > _ble_edit_exec_original_trapint="$(trap -p INT)" 80256 > trap .ble-edit/exec/eval-TRAPINT INT 80257 > trap 'echo INT' INT 80258 > } 80259 > function .ble-edit/exec2/eval { 80260 > # BASH_COMMAND に return が含まれていても大丈夫な様に関数内で評価 80261 > .ble-edit.accept-line.exec.setexit 80262 > eval "$BASH_COMMAND" 80263 > } 80264 > function .ble-edit/exec2/eval-TRAPINT { 80265 > # eval 中にシェルの処理で C-c (SIGINT) が来るとここに入る 80266 > 80267 > # シェルが C-c で中断した時の終了値 80268 > if ((_ble_bash>=40300)); then 80269 > _ble_edit_accept_line_lastexit=130 80270 > else 80271 > _ble_edit_accept_line_lastexit=128 80272 > fi 80273 > 80274 > .ble-edit/exec2/eval-epilogue 80275 > 80276 > # 未だ残っていれば続きを実行 80277 > # (今迄実行していたコマンドは _ble_edit_accept_line[] から既に削除済) 80278 > .ble-edit.accept-line.exec 80279 > } 80280 > function .ble-edit/exec2/eval-epilogue { 80281 > # C-c trap を削除 80282 > trap - INT 80283 > eval "$_ble_edit_exec_original_trapint" 80284 > 80285 > .ble-stty.enter 80286 > _ble_edit_PS1="$PS1" 80287 > 80288 > .ble-edit.accept-line.exec.adjust-eol 80289 > 80290 > # SIGERR処理 80291 > if [ "$_ble_edit_accept_line_lastexit" -ne 0 ]; then 80292 > if declare -f TRAPERR &>/dev/null; then 80293 > TRAPERR 80294 > else 80295 > echo "[91m[ble: exit $_ble_edit_accept_line_lastexit][m" 2>&1 80296 > fi 80297 > fi 80298 > } 80299 > function .ble-edit/exec2/recursive { 80300 > (($1>=${#_ble_edit_accept_line})) && return 80301 > 80302 > local BASH_COMMAND="${_ble_edit_accept_line[$1]}" 80303 > _ble_edit_accept_line[$1]= 80304 > if test -n "${BASH_COMMAND//[ ]/}"; then 80305 > # 実行 80306 > local PS1="$_ble_edit_PS1" HISTCMD="${#_ble_edit_history[@]}" 80307 > local _ble_edit_exec_original_trapint= 80308 > .ble-edit/exec2/eval-prologue 80309 > .ble-edit/exec2/eval 80310 > _ble_edit_accept_line_lastexit="$?" 80311 > .ble-edit/exec2/eval-epilogue 80312 > fi 80313 > 80314 > .ble-edit/exec2/recursive "$(($1+1))" 80315 > } 80316 > } 80317 80318 ここで trap - RETURN という物を発見する。関数やソースを抜けるたびに実行されるという物のようだ。 80319 正にこれを使えるのではないか…? と思って trap '((_ble_edit_accept_line_INT)) && return' RETURN 80320 等としてみたら無限ループになる。それどころかメモリを食い荒らしている。 80321 ${FUNCNAME[*]} で確認すると RETURN が評価されるのは抜ける関数やソースの中である様だ。 80322 そこで return を呼び出すと再び trap RETURN が反応してしまうという事になっている様だ。 80323 つまり、trap - RETURN を用いても呼出元の文脈で評価される訳ではないので呼出元を更に抜ける事はできず、 80324 その上無限ループになってしまうという事になる。 80325 #trap '((_ble_edit_accept_line_INT)) && return' RETURN # 無限returnループになる 80326 80327 今度は trap ERR して見ようとしたが…そもそも呼び出されないようだ。 80328 (それに trap ERR だと条件式の内部にあるコマンドについては呼び出されないというし確実に抜ける事は出来ない) 80329 #trap '((_ble_edit_accept_line_INT)) && echo hello && return 128' ERR # 呼び出されない 80330 80331 或いは trap DEBUG というのを使う事ができるかもしれない。 80332 DEBUG について色々試してみた。 80333 - 先ず、trap 'command' DEBUG した command の中では DEBUG は一切発生しない。 80334 (もし発生していたら無限ループになってしまう。) 80335 - また、bind -x 関数の中で trap - DEBUG しても bind -x の関数を抜けると消える。 80336 - trap - DEBUG 等を用いて削除しようとしても何故かできない。trap -p でも何故か一覧に出ない 80337 | 更に、trap 'command' DEBUG の command の中で trap - DEBUG しようとしても消えない。 80338 | trap 'echo 123' DEBUG 等と DEBUG を上書きする事もできない。 80339 | というか trap の中でなくても上書きできない様だ。それどころか trap -p の一覧に出ない。 80340 | (通常のシェル環境で実行している場合にはちゃんと trap -p で出るのだが)。 80341 | trap DEBUG した関数内では trap -p の一覧にも出るし trap 'echo 123' DEBUG で後から書き換える事も出来る様だ。 80342 trap DEBUG をその場で削除できないという謎があるが取り敢えず動く様になったので良しとする。 80343 80344 2015-02-11 80345 80346 * <bug> home, C-home, ... 等多くのキーに対して keymap が見付からないエラーになる [#D0131] 80347 80348 やはり初めからシーケンスが登録されているキーに関しては 80349 中途半端に bind -x するとこのエラーになる様だ。 80350 bind -x が2文字までしかできないバグは bash-4.3 で解消された様だから、 80351 登録されているキーシーケンスを全て bind -x してしまう事にした。 80352 80353 登録されていないキーシーケンスを入力した時には依然として 80354 keymap が見付からないエラーが発生するが、 80355 登録されていないエスケープシーケンスは先ず来ない事と、 80356 来たとしても自然に解釈する事ができないのでこのままでも良い。 80357 80358 登録されているキーシーケンスの列挙は例によって時間が掛かる様なので、 80359 これもキャッシュとして出力してしまう事にした。 80360 実際にやってみて良好に動いているので良しとする。 80361 80362 * <bug> ログアウトした後も stty の状態が正しくない。 [#D0130] 80363 80364 % 1 stty が正しく呼ばれているか? 正しく適用されるにはどうすれば良いか? 80365 % 80366 % - visible-bell が最後に勝手に enter しているのかもしれないと思って切ったが駄目。 80367 % - enter した時に x と表示する様にして最後に enter が起こっていないか 80368 % 確認したが起こっていない。 80369 % - stty してから暫くしないと適用されないのかと思って sleep して見たが駄目。 80370 % - stty してから何か出力しないといけないのかと思って leave してから 80371 % メッセージを表示する様にしたが駄目。 80372 % 80373 % C-d の中で leave して cat を実行すると C-c 等で終了できない。 80374 % 通常のコマンド実行の際にはちゃんと C-c できるのに何故だろう。 80375 % 何か設定で間違えている事があるのか、関数のネストが関係するのか、...。 80376 % 80377 % cat は C-c が効くのに exit 後は C-c が効かない 80378 % そして exit コマンドを実行して終了する時にも stty は正しく設定されていない。 80379 % cat の時には正しく設定されていて exit の時には正しく設定されていない理由は何か? 80380 % 或いは bash 自体が何処かの時点での stty の状態を記録していて 80381 % exit の時にその記録した時点での stty に設定してしまうのだろうか。 80382 % 80383 % 改めて確認してみる。 80384 % C-d の中で直接 cat すると C-c できないが accept-line.add して実行して貰うとちゃんと 80385 % C-c で止める事ができる。そこで exit を accept-line.add してみる殊にしたが、 80386 % 終了後の stty の状態は壊れた状態の儘である。 80387 % 80388 % 1 何故かは分からないがその場で実行しても stty は適用されないが 80389 % accept-line の実行の枠組を使用して実行すると stty が適用されている。 80390 % しかし次の項目にある様にこの振る舞いは今回は訳には立たない。 80391 % 2 accept-line の枠組を使用して stty が適用された状態にしても、 80392 % そこから exit した場合には stty の状態は反映されない。 80393 % 途中に外部コマンドを挟んでも駄目。 80394 % 80395 % .ble-stty.setup を殺して一度も stty で undef をしない様にしてみたら、 80396 % 当然の事ながらログアウト後に壊れているという事はないようだ。 80397 % 80398 % 2 detach してから exit するという事 80399 % 80400 % bind -x 内 で exit しても勝手に stty の設定が壊れた状態に戻ってしまう。 80401 % 一旦 stty を正常な状態にして ble だけを終了し、 80402 % その後で手動で exit したらどうなるか? 80403 % つまり、ble の "detach" だけを行って exit をしない時 stty が壊れなければ、 80404 % その後に普通に exit をする事で stty が壊れない様にできる。 80405 % 80406 % これを試す為に、ble の設定を全て解除するコードを書く必要がある。 80407 % つまり bind -x した物を全て外し、元々 bind されていた物を再適用する。 80408 % →stty が正常な状態で復帰できた。この後で exit をしても壊れない。 80409 % 80410 % 3 しかし detach するだけだと分かりにくいのでやはり exit についても実装する。 80411 % 80412 % その場で detach をして bind -x から抜け、その後で時間差で抜ける。 80413 % その為にシグナルを用いる。 80414 % 80415 % 所が、シグナルハンドラの中で exit をするとその stty の状態で終了する様なので、 80416 % シグナルハンドラの中でも stty で正しい状態を設定する様にする。 80417 % これで正しい stty の状態で抜ける事ができる様になった。 80418 % 80419 % 所が、また問題がある。どうやら入力待ち状態にある時にシグナルは受け付けない様だ。 80420 % まあ、スレッドが止まっている状態なのだから当然と言えばそんな気もする。 80421 % この所為で次の文字を入力した時に初めて exit される。 80422 % 80423 % と、ここでその場でシグナルを自分に投げたらどうなるのか…と思う。 80424 % シグナルハンドラの内部からならば設定した stty で exit できる… 80425 % という事はその場で読んでしまって充分なのではないか。 80426 % と思ってその様に実装したら期待通りに動く…。 80427 % 80428 % 4 残っているのはユーザが exit コマンドを使用した時である 80429 % 80430 % そのまま exit/logout されるとやはり stty が壊れる。 80431 % exit/logout 関数を上書きすれば良い。 80432 % 80433 % exit() { 80434 % if (($BASHPID==$$)); then 80435 % _ble_edit_detach_flag=exit 80436 % else 80437 % exit "$@" 80438 % fi 80439 % } 80440 80441 と、ここで man の exit の所に EXIT トラップについて書かれている…。 80442 もしかしてこれを設定すれば良いだけの話では…。。 80443 結局 trap .ble-stty.exit-trap EXIT の一行で済む話だった。 80444 80445 一応 detach という機能が実装されたので今回の変更が完全に無駄になった訳ではないが。 80446 80447 * rcfile として起動すると history がロードされない。 [#D0129] 80448 rcfile の中で history を参照しても中身が未だロードされていない様だ。 80449 history -n で読み込む事にした。 80450 80451 * C-S-a 等の \e[2... が読み取れない。というか単なる [ に変換されている…? [#D0128] 80452 80453 これも同様に bash_execute_unix_command のエラーが発生している様だ。 80454 試しに bash --norc として起動してから source ble.sh して見たら起きなくなった。 80455 なので、これに関しては余り気にする必要はない。 80456 bash --rcfile ble.sh 等として起動すればよい。 80457 80458 所で --rcfile で起動すると history が正しく読み込まれていない。 80459 source ble.sh で起動した場合には正しく読み込まれている様である。 80460 rcfile の中では history を読み取る事が出来ないという事だろうか。 80461 80462 * ちらつきを抑えるという事 [#D0127] 80463 80464 ちらつきを抑える為に ble-decode-bind:bind が呼び出される前後で 80465 標準出力・標準入力を繋ぎ変えて見る事にした。 80466 80467 % が、ちらつきは変わらない。 80468 % 今迄ちらつきの無かった所ではちらつきがない儘だし、 80469 % ちらつきが起こっていた所はちらつきが起こっている。 80470 % 80471 % 設定を間違えると何も表示されなくなるから標準出力・標準入力の繋ぎ替え自体は 80472 % 効いていて、bash が出している物は出力されなくなっている筈である。 80473 % 80474 % | 但し、他の可能性もある。 80475 % | もしかすると bash は fd を個別に持っていてそれに対して出力しているかも? 80476 % | そうすると繋ぎ替えを 1 2 に対して行っても bash 自体の出力先を変更できない。 80477 % | 上の実験で何も表示されなくなったように見えたのが勘違いの可能性もある。 80478 % | つまり、ble では PS1 を空欄にしているので bash が何も出力していない様に見えるが、 80479 % | 実際には行を消してしまう物を出力しているかもしれない。) 80480 % | 80481 % | 念のため簡単なテストをしてみる。 80482 % | $ exec 3>&1 80483 % | $ function on { exec 1>&3 2>&3; } 80484 % | $ function off { exec 1>/dev/null 2>/dev/null; } 80485 % | $ bind -x '"\C-o":"on"' 80486 % | $ bind -x '"\C-p":"off"' 80487 % | 以上の設定の後で C-o C-p で表示・非表示が切り替わる事を確認した。 80488 % | 80489 % | つまり bind -x の内部で exec してもちゃんと bash のプロンプト表示も影響を受ける。 80490 % 80491 % という事は、ちらつきは bash がプロンプトをクリアする事によって起こるのではなく、 80492 % ble 自体の再描画によって起こっていると結論する事ができる。 80493 % (bash がクリアしたプロンプトを直後に再描画しているのは功を奏しているという訳だ) 80494 80495 改めて動かしてみるとちらつきは起こらなくなっていた。 80496 テストの時に新しい物をちゃんとロードできていなかったという事か。 80497 何か腑に落ちないが今後はこの方針で行く事にする。 80498 一応 ble_opt_suppress_bash_output オプションで繋ぎ替えを off にできる様に残しておく。 80499 80500 一応註記しておくべき事は、exec で標準出力・標準入力を潰しても 80501 カーソルの位置などが乱れる事なく動作しているという事である。 80502 と思ったらカーソルの位置がずれている…。 80503 →.ble-edit-draw.update-adjusted の関数内で bash の出力に対する対策をしていたので 80504 exec を実行している場合にはその対策を行わないように修正した。これで動いている。 80505 →が、しかし今度は C-d で前触れ無く (後処理無く) ログアウトする様になってしまった。 80506 READLINE_LINE READLINE_POINT の設定はその儘にして位置調整のシーケンスの出力だけ 80507 を行わない様にした。 80508 80509 もう一つの確認事項は vbell のクリアがちゃんと出力されるかという事。 80510 これは 1 2 が端末に繋がっている時に fork している筈だから出力されるのではないかと思うが。 80511 →実際に試してみた所ちゃんと vbell の消去が出力されている様なので問題ない。 80512 80513 2015-02-09 80514 80515 * <bug> bind -x '"\"":...' 及び bind -x '"\\":...' [#D0126] 80516 80517 cygwin の bash-4.1 で改めて動かしてみた所色々問題がある 80518 80519 1 '\' と '"' が bind -r できていない 80520 良く考えたら bind -r している訳ではなくて bind -x で上書きをしているのであった。 80521 そして bind -x している物を調べたら先程弄ったコードの簡単なミスだった。修正。 80522 80523 2 カーソルキーの類が全て M-\\ と解釈されている 80524 これは 1 に関連する物だった \\ に bind する代わりに \[ に bind していた所為で 80525 CSI が M-\\ に翻訳されてしまっていたというだけの話であった。 80526 80527 * <bug> bash-4.3 日本語が入力できない。 [#D0125] 80528 8bit 文字は \ooo の形式で bind -x '"\ooo":...' しなければならなくなった。 80529 80530 | 以前までは bind -x ではマルチバイト文字を 1 文字ずつしか受信できなかったのが、 80531 | いつの間にかに日本語として受信できるようになった様だ。 80532 | 今迄は octet の 256 文字を全て登録する事で入力を全て横取りできたが、 80533 | この所為で unicode にある全ての文字について bind しなければ日本語を受信できなくなった。 80534 | どうするか…。 80535 | 80536 | 例えば以下を設定した状態で "あ" と入力すると hello となる。tttqqqrrr とはならない。 80537 | hello を bind していない状態だと tttqqqrrr となる。あれ、受信できている…。 80538 | bind '"\343\201\202":"hello"' 80539 | bind '"\343":"ttt"' 80540 | bind '"\201":"qqq"' 80541 | bind '"\202":"rrr"' 80542 | つまり bind -x では受信できない、という事なのか? と思ったらちゃんと受信できる。 80543 | 80544 | では ble.sh で受信できないのは何故か? \ooo の形式で指定する必要がある? 80545 | と思って \ooo の形式で指定する様にしたら直ぐに入力できる様になった。 80546 80547 * <bug> bash-4.3 "ESC [ 数字" 系のシーケンスを入れると [#D0124] 80548 bash_execute_unix_command: keymap云々 のエラーになる。 80549 80550 問題: C-left C-right を使おうとするとキーマップがないと出る 80551 80552 これは bash --norc から source しても変わらなかった。 80553 $ TERM=dumb bash --norc 80554 $ TERM=screen-256color; source ble.sh 80555 等としても同じだ… 80556 (というか source ble.sh する前に C-left C-right を試したら TERM=dumb でも動く。) 80557 80558 他にも試してみたがどうも "ESC [ 数字" 系のシーケンスが全部駄目な様だ。 80559 80560 仕様がないので "ESC [ *" を全て登録する事にする 80561 80562 * <bug> bind -r すべき対象を bind -sp | fgrep していたが fgrep が結果をバイナリと判定する事がある [#D0123] 80563 80564 fgrep -a とオプションを指定する事で解決した。 80565 80566 | %%問題: bash で起動するとカーソルキーを使えるが bash --norc で起動するとカーソルキーを使えない%% 80567 | 80568 | これは謎である。~/.bashrc の中で設定しているものと関係があるのだろうか。 80569 | source ~/.mwg/bashrc; source ble.sh とするとカーソルキーを使える。 80570 | source ~/.mwg/share/mshex/shrc/bashrc_interactive でも使える。 80571 | 80572 | test-prebind.sh に bashrc_interactive の中から bind 関係の部分を抜き出してみても使える。 80573 | どんどん絞り込みをしていく。複数の bind の組合せで起こっている? 80574 | かなり不思議な事が起こっている…コメントの有無で結果が変わる…。 80575 | そればかりか末尾の改行の数にも依存している。再現性がある事は明らか。 80576 | 改行の数が一定数以上ならばOK? でも改行の後に何があるかにも依存している。 80577 | 80578 | bind よりも前に何を書いても大丈夫なように見えてコメントを沢山書いたら駄目になった。 80579 | どうやら bind よりも前のコメントに何が書かれているかにも依存する様である。 80580 | 仕方がないのでコメントは以下に移動してくる。 80581 | 80582 | # @bash-4.3 80583 | # 以下を読み込んでから ble.sh を読まないと何故かカーソルキーが使えない 80584 | # bind よりも後の空白の数だとかコメントの文字数が 80585 | # 違っただけで使えたり使えなかったりする。 80586 | # コメントの内容によっても結果が異なる様だ。 80587 | # bash のメモリ関連のバグだと思われる。セキュリティ的に危ないんじゃないか?? 80588 | 80589 | また気付いた事だが、暫く時間が経つと先程まで動いていた test-prebind.sh では動かなくなったりする。 80590 | 80591 | bash のバグとしか思えない動作なのでここでは置いておく事にする。 80592 | 80593 | →何と新たな事実が判明した…。 80594 | カーソルキーが使えない場合については ble.sh 内の bind -r が走っていない。 80595 | 色々調べると bind -sp は色々物を出力しても、 80596 | fgrep の段階で「バイナリ」と判断されたり判断されなかったりする様だ。 80597 | fgrep でバイナリと判断されると中身が表示されない為に bind -r が走らない。 80598 | 80599 | 結局 何故 bind コマンドの周りのコメントやら何やらが fgrep のバイナリ判定に影響を与えるのかは分からなかった。 80600 | コメントの有無などで bind -sp で表示される順序などが変わるという事なのだろうか。 80601 | 或いは fork 元の bash のメモリの内容に fgrep の判定が影響を受けているとか。 80602 80603 * "bash: bash_execute_unix_command: コマンドのキーマップがありません" と出る問題 [#D0122] 80604 80605 久しぶりに起動してみたら色々と動かない? @bash-4.3 of padparadscha 80606 80607 カーソルキーを入力しようとすると 80608 bash: bash_execute_unix_command: コマンドのキーマップがありません 80609 等と表示される。検索すると bind -x した時の bind 先が不明な場合に発生するエラーメッセージの様だ。 80610 ESC で始まるキーシーケンスに対応するキーは全てこれなので ESC 関係が悪さをしているのだろう。 80611 80612 bind -x した物の一覧を取得する方法があれば良いのだが。 80613 以前に探した時には見付からなかった気がするが、改めて調べてみる。と、 80614 bash-4.3 以降では bind -X を用いて bind -x した物の一覧を表示する事ができる様だ。 80615 早速試してみると確かに bind -x した物の一覧を閲覧する事ができる。 80616 80617 そこで bind -x した物の削除を試みる。 80618 普通に bind -r $'\ez' しても削除できない…。 80619 と思ったら実はちゃんと削除できているが bind -X の表示に反映されていないだけという事が分かった。 80620 80621 <bashbug> bash-4.3.33, bind -r して削除した後のコマンドが bind -X の一覧から削除されない。 80622 80623 分かった事: 2文字シーケンスを登録すると1文字目にkeymap変更が割り当てられる 80624 80625 | どうやら一回でも 2 文字のシーケンスを登録してしまうと 80626 | それらを全て削除しても 2 文字のキーシーケンスに対応する keymap を探す様だ。 80627 | 例えば "ab" というシーケンスを登録すると 80628 | 「"a" は2文字のキーシーケンスの1文字目」という情報が登録されてしまい、 80629 | a に続けてどの様な文字を打っても対応する2文字のキーシーケンスが見付からない! 80630 | という状態になってしまう。(実際に "ab" で試してみたらそうなった。) 80631 | 80632 | ※唯単に bind -x '"ab":"echo"' && bind -r ab 等としただけでは再現しない。 80633 | 予めあらゆる 1 文字コマンドについて bind -r && bind -x ... しておくとなる。 80634 | bind -x でない通常の readline 関数がそれぞれの文字に割り当てられている場合はそれが呼び出される様だ。 80635 | しかし、全てを bind -x で処理する為に readline 関数を解除していると "見付からない" という事になる。 80636 | 再現方法は以下の通りになる: 80637 | 80638 | $ bind -x '"ab":"echo"' && bind -r ab && bind -x '"a":"echo"' 80639 | 80640 | 1つ目のコマンドも3つ目のコマンドも -x でなければ再現しない様だ。つまり、 80641 | $ bind '"ab":self-insert' && bind -r ab && bind -x '"a":"echo"' → 再現しない。問題なし。 80642 | $ bind -x '"ab":"echo"' && bind -r ab && bind -x '"a":self-insert' → 再現しない。問題なし。 80643 | という事である。 80644 | 80645 | これを解決する為には "a" で始まるあらゆる2文字のシーケンスを登録すれば良い。 80646 | 80647 | これは C-x の状況と似たような状況である。 80648 | (以前の bash で試した時には C-x に続けて何か入力すると bash 毎落ちていた。 80649 | これがエラーメッセージを表示するという状態に修正されたのだろう。) 80650 80651 取り敢えず "ESC なんとか" は如何にも bind -x で登録されそうな組合せなので、 80652 "ESC *" の全ての組合せを登録してしまう事にする。 80653 実際には bind -x でどの様な2文字のシーケンスが登録されているのか分からないので、 80654 あらゆる "* *" の組合せについて登録しない限りは万全とは言えない。 80655 とはいいつつあらゆる組合せについて 2 文字単位でしか入力を読み取れない状態にもなる。 80656 これは明らかに不便だ。結局、"ESC *" の組合せを登録する程度が限界だろう。 80657 80658 分かった事2: ESC は bash-4.3 では初めから2文字のシーケンスの一部と解釈される 80659 80660 | bash --norc で起動した状態から source ble.sh した場合は ESC * に bind しなくても良いかと思ったが、 80661 | 実際に試してみた所同様のメッセージ bash: bash_execute_unix_command: コマンドのキーマップがありません 80662 | が出る。bind -X で確認したが、やはり bind -x は何も存在していない状態から source ble.sh だった。 80663 | その他の version の bash がどうなのかは試していない。 80664 80665 つまり、bind -x を何もしていない状態でも "ESC *" に対して bind しなければならないという事。 80666 80667 80668 2013-06-13 80669 80670 [Done] 80671 80672 * <bug> bash-3.2.48, bash-3.1: カーソルの表示位置がずれる。 [#D0121] 80673 と思ったら、そもそも READLINE_LINE 及び READLINE_POINT に対応していない様だ? 80674 これだと C-d で即座にログアウトしてしまう…。 80675 80676 →これに関しては READLINE_LINE は空白のままで諦める事にした。 80677 この状態であれば bash による出力は何も為されないので、 80678 カーソル位置の修正などを行う必要はなく、ただ .ble-edit-draw.update を実行すればよい。 80679 80680 →また、C-d に関しては IGNOREEOF を大きな値に設定して取り敢えず諦める事にした。 80681 制限としては C-d を受信する事が出来ないという事、C-d を押すと 80682 「ログアウトする為には exit を入力して下さい」と表示され、 80683 プロンプトの表示などが乱れる (というか何も表示されない) という事。 80684 80685 [2013-06-13 21:24:46] 80686 80687 * <bashbug> bash-3.1 [#D0120] 80688 パラメータ展開の部分文字列で、範囲外のインデックスを指定すると ^? が返ってくる。 80689 これはどうしようもない。部分文字列は他の場所でも多用している上に代替手段が存在しない。 80690 (勿論、別のプログラムを呼び出せばこの機能を再現する事は出来るが、 80691 それをするととても遅くなるので受け入れがたい。) 80692 80693 bash の ChangeLog を見てみたが、このバグに関する情報は書かれていない様な気がする。 80694 一応 bash-3.2 から bash-4.0 へ変わる時に配列の ${array[@]:*:*} で stray の ^? 80695 が出るバグを修正したと書いてある。また、${var##..} で空白が絡む時の stray ^? についても 80696 バグの修正が為された様だ。 80697 80698 →何故かは知らないが、a=; echo "(${a::})" とすると ^? が出力されるが、 80699 a=; x="${a::}"; echo "($x)" とすると正しい結果が返ってくる。 80700 また "(${a::})" や "a${a::}b" 等とすると ^? が出力されるが、 80701 "(""${a::}"")" や "a""${a::}""b" とすると ^? は出力されない。 80702 もし "" で文字列を区切るだけで良いのだとしたら、少ない修正で bash-3.1 にも対応可能である。 80703 80704 取り敢えずこの修正によって見た目ちゃんと動いている様子である。 80705 [2013-06-13 21:25:43] 80706 80707 →また、bash-3.2.48 で確認してみた所、このバグは既に取り除かれている様だ。 80708 80709 2013-06-12 80710 80711 [Done] 80712 80713 * <bug> bash-3 では bind -x されたコマンドを受け取った時、 [#D0119] 80714 一度改行してから実行される為に、行がずれていく。 80715 プロンプトは消去されないので再描画の必要はない。 80716 現在位置の情報を更新するだけで良かった。 80717 80718 * <bug> ble-bind -D: cmap または kbd が全く定義されていない状態で [#D0118] 80719 ble-bind -D を実行すると内部の declare -p が無引数で実行されて、 80720 bash 内で定義されている全部の変数が出力されてしまう。 80721 これは、_ble_decode_cmap_@ または _ble_decode_kbd_@ が 1 つ以上あるか 80722 どうか確認してから declare -p を呼び出す様にすれば良い。 80723 80724 * <bug> bash-3.1, ble-decode-kbd ESC の結果が 3 になる。 [#D0117] 80725 .ble-decode-kbd.get-keycode: tmp の要素を数える所で、 80726 tmp の先頭要素の文字数を数えていた。 80727 80728 * <bug> bash-3.1: 何と bash-3.1 の算術式では ?: を数珠繋ぎに出来ない。 [#D0116] 80729 ちゃんと括弧で括っていかなければならない。これは結構痛いと思ったが、 80730 意外と書き直さなければならない所は少なかった。 80731 80732 .ble-text.c2bc+UTF-8, .ble-text.c2w+emacs, .ble-text.c2w.ambiguous 80733 80734 * <bug> bash-4 未満で _ble_decode_kbd__c2k を -A として宣言していた。 [#D0115] 80735 -a に書き換えるだけでよい。 80736 [2013-06-13 00:26:51] 80737 80738 * <opti> スタイルを一つの整数で表現する。 [#D0114] 80739 80740 文字列比較などをすると時間が掛かる為。 80741 ble-color.sh, ble-edit.sh 等を書き換えた。意外とすんなりできた。 80742 これで .ble-line-text.construct のループ内の処理をできるだけ算術式で記述し、速度向上を図る。 80743 →変更した。定量的に変化があったかどうかは分からないが。 80744 80745 * ble-edit.sh: quoted-insert, self-insert, insert-string で [#D0113] 80746 _ble_edit_mark_active を解除するように変更 80747 80748 * [ble: exit] の際の色を変更 [#D0112] 80749 80750 * 履歴展開: 展開に失敗した時の対処。 [#D0111] 80751 その儘空白のコマンドを実行してしまっていた。 80752 履歴展開に失敗した時は bash では、前回編集中のコマンドが再度表示される。 80753 それに倣って書き換えた。 80754 [2013-06-12 15:15:47] 80755 80756 * 履歴展開が使えない [#D0110] 80757 80758 set -H としてみたが eval の中では有効には為らなかった 80759 (というか、多分、set -H は初めから設定されていたのではないかと思う)。 80760 history -p で変換してから実行すれば等価だろうか。 80761 ("" で囲んでも実行された、が、通常の履歴展開の動作もそうなっている様だ。) 80762 80763 この方針で実装する事にした。 80764 [2013-06-12 15:14:22] 80765 80766 * fword: IFS に加えて / も区切とする単語単位の操作を追加。 [#D0109] 80767 80768 * uword: IFS を参照してそれを基準にして単語境界を決めるように変更。 [#D0108] 80769 80770 2013-06-11 80771 80772 [Done] 80773 80774 * <bug> 特定の操作をした時に accept-line の処理が中途半端で終了する [#D0107] 80775 C-c や C-z など。 80776 80777 [C-z 完 2013-06-11 12:22:35] 80778 80779 + C-\ の場合は問題なく続きが実行される。 80780 80781 + 実は C-z をした時にも同様の事が起こっている様だ。 80782 80783 こちらについては trap 'echo' TSTP, trap 'echo' 20, trap echo 'SIGTSTP' 等としても設定できない? 80784 trap -p をすると予め '' が割り当てられている様子である。 80785 その他にも予め '' が割り当てらrている TTIN TTOU についても、 80786 trap を仕掛けても何も trap する事ができない様だ。 80787 80788 念のため trap : 20; trap -p と、連続で実行してみたがやはり設定できていない。 80789 つまり、誰かが設定を戻しているという訳ではなく、初めから設定できないという事。 80790 また、stty susp undef としてから trap してみたが、それでも設定できない。 80791 80792 然し乍ら C-z をした直後には、何故か redraw は実行される様だ。 80793 但し、stty の設定は元に戻っていないようで、 80794 C-c や C-z 等の文字を受け取る事は出来ない。 80795 80796 + 然し C-z の直後には何故か prompt が表示されている。 80797 これは一体誰が表示しているのだろうか? 80798 →確かめてみた所、C-z した時は実行中のコマンド全てに失敗する訳ではないようだ。 80799 accept-line.exec 内のループを抜けるに留まるらしい。 80800 80801 for コマンドが C-z を受信するという事だろうか? 80802 試しに accep-line.exec 呼出元で 1 回ループにくるんで見たところ、 80803 C-z でそのループまで抜けるようになった。 80804 つまり、for 等のコマンドを使わずに実行すれば良いという事だろうか。 80805 (一応再帰と条件分岐さえあればループは可能。) 80806 80807 試してみた所 && による条件分岐は C-z で止まらない 80808 また、if 文による条件分岐も C-z では止まらない様だ。 80809 80810 2013-06-10 80811 80812 [Done] 80813 80814 * <opti> .ble-line-text.construct 文字連結最適化? [#D0106] 80815 [2013-06-11 03:37:38 余り効果は無かった] 80816 80817 カーソル移動だけの時は配置の再計算を省略できるようにしたが、 80818 カーソル移動がそれ程速くなったとは思えない。(少しは軽くなった気がしないでもないが) 80819 何がボトルネックになっているのだろう。残りは、文字連結程度しかない。 80820 なので、文字連結の最適化について考え直してみる。 80821 80822 色々試してみた結果、配列に格納していって最後に join するのが速いようである。 80823 また、${#out} の様な長さの評価の仕方は O(N) の計算量なので 80824 ループの中で毎回参照するのは避けた方が良い。 80825 →余り改善したようには思われない…。 80826 80827 或いは単に関数の呼出に時間が掛かっているだけなのか? 80828 →でもこれはあり得ない。何故なら編集文字列が短い時にはきびきびと動くから。 80829 80830 それとも cache_g[i] やら cache_ei[i] の代入に時間が掛かっているのか。 80831 →試しに off にしてみたがそれ程変わった雰囲気もない。 80832 80833 或いは座標位置の再計算をしてしまっている? → 確認してみたが、ちゃんと再計算は省略されている。 80834 80835 改めてどの場所で時間が掛かっているか確かめる為に、 80836 カーソル移動しか起こっていない場合には文字連結部分を省略してみる事にした。 80837 (この様にするとカーソル移動によって更新されるべき物が更新されないので、実際には使えない方法である。) 80838 →すると動作がとても速くなったので、やはりこの文字連結を行っている部分が悪い様だ。 80839 80840 更に、ダミーで文字連結のループを回して何処に時間が掛かっているのか調べる事にした。 80841 →文字を配列に登録する部分はそんなに時間は掛かっていないようだ。 80842 →文字列の長さを計算する部分も関係ない。 80843 →cache_ei や cache_g に代入している部分も関係ない。 80844 80845 # →と、ここで SGR 系列を追加している部分を有効にしてみたら急に遅くなった。 80846 # 先程やった時には余り変化が無かったように感じたが恐らく勘違いだった。 80847 # →どうも文字列比較 if test "$seq" != "$seq0"; then の部分が重い様子である。 80848 # (seq, seq0 はそれぞれ3文字なのでそれ程重いとは思えないのだが) 80849 # 以下のような色々な物を試してみたが、速さに大差は無いようである (当然か)。 80850 # if test -n "${seq#"$seq0"}"; then 80851 # if test "$seq" != "$seq0"; then 80852 # if [ -n "${seq#"$seq0"}" ]; then 80853 # if [ "$seq" != "$seq0" ]; then 80854 # 80855 # 或いは、sgr の表現を整数にして、整数同士で比較する様にすると速いかも知れない。 80856 と、ここまでで SGR 系列の部分が怪しいのではないかと色々調べてきたが、 80857 やはり? 違うようだ。別の所をコメントアウトして SGR 系列の部分だけ残してみると充分速い。 80858 80859 どうも、何処が特に重いという訳でもなく、これが bash の限界という事のようだ。 80860 早く dirty または色変更した部分だけしか再計算を実行しなくても済む様に変更した方が良いという事だろう。 80861 80862 * カーソル移動では dirty を設定しない様に変更。 [#D0105] 80863 →意外と少なかった。移動は全て .ble-edit.goto-char を介して実行されていた為、 80864 .ble-edit.goto-char の中で実行されている .ble-edit.set-dirty を削除するだけで良かった。 80865 その他は set-mark, exchange-point-and-mark ぐらい。 80866 80867 + と思ったらカーソルを移動しても、カーソルの移動が表示に適用されなくなった。 80868 良く考えたらカーソルの移動をした場合、文字の配置を再計算する必要はないが、 80869 表示の際の領域反転などは再度計算し直す必要があるので、 80870 描画に関しては再度実行する必要がある。 80871 80872 # * 現在 cursor 移動も dirty として扱っているが、 80873 # 別にその様に扱う必要性はないのではないか? 80874 # 80875 # dirty としたのは色付け関数によって括弧の強調などの色付けがカーソルの位置に 80876 # 依存して行われる可能性があったからである。 80877 # 色付け関数が region_highlight なり何なりを呼び出した時点で、 80878 # set-dirty が自動的に為されるような仕組みにしておけば問題ない。 80879 80880 * <bug> set-mark: 動作が emacs と違う。 [#D0104] 80881 emacs では既に mark が active な場合でも、 80882 active なまま新しく現在位置を mark の位置とする。 80883 active 状態をトグルするなどといった事はしない。 80884 [2013-06-11 00:23:12] 80885 80886 * _ble_edit_mark_active [#D0103] 80887 今迄の型は整数型で 0 または 1 の値を取っていたが、 80888 今後は様々な種類のマーク (S-move によって有効になったマークなど) を区別する為に、 80889 + マークが設定されていない場合は '' 80890 + set-mark によってマークが設定されている場合は '1' 80891 + S-move によってマークが設定されている場合は 'S' 80892 + (その他のマークを設定する事が在れば必ず有限長の文字列) 80893 等のように文字列とする事にした。これに伴って何カ所か修正。 80894 [2013-06-11 00:14:30] 80895 80896 * <bug> 今迄 sword としていたのは寧ろ unix-word の事だった。 [#D0102] 80897 名称を sword から uword に変更。 80898 [2013-06-10 22:41:22] 80899 80900 * <bug> uword の定義で空白を SP HT にしているが、LF も含める。 [#D0101] 80901 [2013-06-10 22:41:28] 80902 80903 * sword 関連に対応 [2013-06-10 22:43:42] [#D0100] 80904 80905 IFS=$'|&;()<> \t\n' (シェルのメタ文字) を区切り文字として単語分割する。 80906 但し、quote については正しく処理していない。 80907 80908 # unix-word の定義について調べて uword として実装する。 80909 80910 * forward-word, backward-word を emacs や readline と同様の位置に移動する様に変更。 [#D0099] 80911 80912 * <opti> 長い文字列を編集するのに時間が掛かる。 [#D0098] 80913 80914 これは毎回 construct-line でカーソルの位置の計算と出力文字列の構築を行っているからである。 80915 特に、一つ一つの文字幅を毎回計算しているのが一番重い気がする。 80916 理想的には dirty な部分以降の計算を実行すれば良いはずである。 80917 80918 と思ったが、カーソルの位置が変われば SCOSC, SCORC の埋込位置が変わる為、 80919 現状の実装方法ではやはりカーソルの位置から再度計算し直さなければならない。 80920 80921 これの解決方法としては、 80922 + 先ず全ての文字の後で x y lc lg がどの様な状態になるべきかを計算し、これを cache 配列に記憶する。 80923 + また、全ての文字に対して esc_line 中の何文字目に対応するかも記憶しておく。 80924 + esc_line 自体も何処かに記憶しておく。 80925 construct-line 関数は以下の処理を実行する 80926 1 dirty が設定された場所から位置解析をやり直す。 80927 この解析では各文字だけを記録し、escape sequences の構築まではしない。 80928 2 更に色付けの処理を dirty が設定された場所からやり直す。 80929 3 色付けによって変更された箇所から escape sequences を構築し esc_line とする。 80930 4 esc_line のカーソル位置と末端に SC と RC を挿入して ret に入れる。 80931 5 カーソル位置の x y lc lg を取り出す。 80932 80933 新しく .ble-line-text.construct という関数を作る事にした。 80934 80935 + 先ず始めに .ble-line-text.update-positions で dirty から x y lc を更新する。 80936 80937 i文字目を処理している時: 80938 80939 1 cache_x[i], cache_y[i] の更新 80940 cache_x[i], cache_y[i] には i 文字目を出力する **前** のカーソル位置が格納される。 80941 (或いは、i-1 文字目を出力した **後** のカーソル位置とも言う事が出来る。) 80942 80943 2 次に cache_lc[i] の更新を行う。 80944 cache_lc[i] は、cache_x[i]!=0 の場合は、その左側に位置する文字、即ち i-1 番目の文字のコードを保持する。 80945 cache_x[i]==0 の場合は、その次に同じ行に来る文字のコードを保持する。 80946 80947 cache_lc[i] は x!=0 の時は、前回の文字コード (lc) をそのまま代入すれば良い。 80948 然し、x==0 の時は、次に x!=0 になるまで代入を実行する事は出来ない。 80949 ここで変数 li を導入する。li は、次に cache_lc を代入するべき位置を保持する。 80950 80951 x!=0 の場合には cache_lc[li] ~ cache_lc[i] までの値を代入し、li=i+1 とする。 80952 x==0 の場合には cache_ic に対する代入は実行せず li の位置も進めない。 80953 cache_lc[li] ~ cache_lc[i] に対する代入は以下のように行う。 80954 x!=0 となった行 y が cache_y[j] と一致するならば lc を代入する。# これだと ^A 等の場合に A に化けるのでは?■ 80955 x!=0 となった行 y が cache_y[j] と異なるならば 32 (空白) を代入する。 80956 80957 for(j=li;j<i;j++) 80958 assert(_ble_line_text_cache_x[j]==0); 80959 80960 3 cache_lg[i] の更新は未だ行わない。 80961 80962 + その後紆余曲折を経て新しい「編集文字列構築器」ができた。 80963 古い関数 80964 .ble-cursor.construct-line.chk-cursor 80965 .ble-cursor.construct-line 80966 は削除する。 80967 [2013-06-10 22:02:41] 80968 80969 2013-06-09 80970 80971 [Done] 80972 80973 * <bug> source ble.sh でエラーが発生するようになった。 [#D0097] 80974 どうやら ble-bind で発生している様だ、 80975 と見てみたら OPTARGS の変数存在確認で "${OPTARGS+set}" を引用符で囲むのを忘れていた。 80976 [2013-06-10 04:00:03] 80977 80978 * <opti> プロンプトの初期化が異様に遅い @ cygwin [#D0096] 80979 80980 プロンプトで \j が3回参照されている。 80981 それぞれの \j の呼出で2つのプロセスが生成されているので、 80982 プロンプトの初期化で合わせて 6 つのプロセスが生成されている事になる。 80983 cygwin のプロセス生成の速度は測ってみたら秒間 10 程度であったので確かに時間を食う。 80984 (本来はプロセスを生成せずにこれを処理したいが。) 80985 80986 プロンプトの初期化中にコマンドを実行する場合は、 80987 コマンドの実行結果をキャッシュするように変更。 80988 [2013-06-10 03:31:58] 80989 80990 更に job の数を wc を使わずに数える様に変更。 80991 [2013-06-10 03:53:44] 80992 80993 これらの変更によって cygwin でなくてもかなり軽くなった様に思われる。 80994 80995 * <bug> /bin/printf, source ble.sh 時にエラー @ cygwin [#D0095] 80996 c2s: /bin/printf が使えない環境で source ble.sh 時にエラーメッセージが出る。 80997 /bin/printf の stderr を /dev/null に落とすように変更。 80998 [2013-06-10 03:37:02] 80999 81000 * <bug> [ -v ] のエラーが発生する @ cygwin [#D0094] 81001 cygwin 環境で動かしてみる→エラーが発生して初期化に失敗する。 81002 ble-bind で OPTARGS の変数存在チェックに test -v を使用していた。 81003 bash-4.1 以下でも動くようにする為には test -n "${OPTARGS+set}" を使用するべき。 81004 [2013-06-10 03:34:53] 81005 81006 * <bug> c2s-hex: /bin/printf を用いて [#D0093] 81007 function .ble-text.c2s-hex を定義するべき所を 81008 function .ble-text.c2s を定義していた。 81009 [2013-06-10 03:33:23] 81010 81011 * <bug> 再描画の際に sgr 情報が失われる。 [#D0092] 81012 カーソル位置を設定する時、lc と共に sgr の情報として lg も記録するようにしたい。 81013 81014 construct-prompt に関しては取り敢えず置いておき、 81015 construct-line の方での対応を済ませる。 81016 [2013-06-09 19:25:13] 81017 81018 * <bug> 編集文字列が右端一杯の時に縦の位置がずれる。 [#D0091] 81019 <del>右端付近に tab があると縦の位置がずれて表示される。</del> 81020 81021 多分、tab の所為で発生する改行についてちゃんと対策が取れていない為である。 81022 後でゆっくり考える必要がある。 81023 81024 と思って色々試していたら、別に tab がなくても編集文字列末端が右端付近に位置している時には 81025 縦の位置がずれてしまうという事が分かった。 81026 原因は construct-line の中で SCORC を出力する位置にあった。 81027 最後の改行を出力する前に SCORC を設定していた。本当は最後の改行の出力も済ませてから 81028 SCORC を設定するべきだった。 81029 81030 + これで丁度右端ぎりぎりまで編集文字列がある場合に常に (カーソルが何処にあっても) 81031 位置がずれると言う問題は解決した。 81032 81033 + しかし、それでもカーソルが丁度右端にある時のカーソルの位置が変な事になっている。 81034 右端にあるので本来はカーソルは見えない (?) 筈であるのに最後の文字 (右端から一文 81035 字戻った場所) に表示されたり、次の行の最後の文字の位置に表示されたりする。 81036 81037 そもそも一番右端にカーソルが来た場合に何処にカーソルを置くべきかという事だが、 81038 xenl が有効な端末でも無効な端末でも同様に表示するのであれば、次の行の先頭に表示する 81039 べきである。(その事も考えて編集文字列が丁度右端に到達している時に、xenl に対して 81040 改行を出力しているのである) 81041 81042 問題は、SCOSC をしている時に行末端に位置している為に、SCORC で戻ってきた時に、 81043 (折角改行したのに) 行末端の位置に戻ってきてしまう事である。 81044 今迄は行末端に来た時、xenl であっても次に文字が来た時に次の行に自動的に移動するから 81045 敢えて改行は出力しないようにしていたが、SCORC で戻ってくる事も考えると、 81046 ちゃんと xenl の場合には明示的に次の行に移っておいて、その後で SCOSC される様にする 81047 べきである。 81048 81049 その様に書き換えたらちゃんと期待通りにずれずに動くようになった。TAB がきても問題ない 81050 [2013-06-09 18:37:58] 81051 81052 * <bug> 全ての文字に対して SGR を出力している。 [#D0090] 81053 編集文字列の表示で出力している escape sequence を見てみると SGR が変化していないのに 81054 毎回 SGR の設定を出力している様だという事が分かった。前回の文字と SGR の設定が同じ場合には、 81055 SGR の設定は出力しないようにしていた筈である。 81056 →改めて確認してみた所 seq0=seq としていた。seq0="$seq" でなければならない。 81057 「前回の SGR」の値が常に誤った設定になっていたから、毎回 SGR が出力されたのである。 81058 [2013-06-09 18:06:30] 81059 81060 * <bug> 改行を含むコマンドを編集している時、 [#D0089] 81061 行の先頭にカーソルがある時に、そこに位置する文字が空白に化けて表示される。 81062 本来ならば行頭に文字がある場合、その文字を lc に設定する事になっているはずである。 81063 81064 見てみた所、.ble-cursor.construct-line.chk-cursor までは正しく処理できている様に見える。 81065 と思ったら、update-adjusted で lc から READLINE_LINE を設定するのではなく、 81066 単に空白を READLINE_LINE に代入していた。 81067 [完 2013-06-09 16:53:31] 81068 81069 * <bug> tab が幅ゼロで表示されている。 [#D0088] 81070 時々幅を持って表示されるがその規則は謎。 81071 81072 と思ってみていたら tab の幅が負の大きな値になったりしている。 81073 絶対値は大体 x と同じぐらいである。と、ここで /it とするべき所を %it としている事に気付いた。 81074 同様のコードを色々な所に書き散らしていたので、それらも纏めて修正した。 81075 [2013-06-09 16:43:12] 81076 81077 * <bug> 改行を含むコマンドを実行すると、実行後にカーソル位置がずれる。 [#D0087] 81078 [2013-06-09 16:14:26] 81079 81080 これは前回のプロンプトが表示されていると勘違いして原点に移動する為である。 81081 _ble_line_x, _ble_line_y を 0 に設定するべき。 81082 81083 →.ble-edit.accept-line.exec.adjust-eol で 81084 _ble_line_x, _ble_line_y を 0 に設定する事にした。 81085 81086 * <bug> quoted-insert [#D0086] 81087 一部の文字を read -n で読む事が出来ない。 81088 →これは全ての文字を ble で処理できるようになったら 81089 ble の仕組みを通じて読む事にすれば良い。 81090 81091 改めて試してみた所、大概の入力は読み取れている? 後で再度確認する必要有り。 81092 確認してみた所 ^I ^J ^M の入力をする事ができない。 81093 やはり、ble-decode-char 辺りに quoted-insert を仕掛ける必要がある。 81094 81095 # * ble-edit-quoted-insert: 81096 # 現在はデバグの為に一部の文字列しか捕まえられないので、 81097 # read -N を使って実装を行っているが、 81098 # 全部を ble で処理するようになった時は、 81099 # ble-decode-char に対して干渉するだけで良い? 81100 81101 .ble_decode-char: 81102 _ble_decode_char__hook 変数を追加、この変数が設定されている場合は、 81103 この変数に代入されている文字列をコマンドとして実行するように変更。 81104 [2013-06-09 16:09:46] 81105 81106 * デフォルトの cmap である term+default を読み込むのに時間が掛かる。 [#D0085] 81107 [完 2013-06-09 15:46:02] 81108 81109 恐らく ble-decode-kbd 辺りの処理に時間が掛かっているのではないかと思う。 81110 ble-bind に -D オプションでも追加して、これを追加した場合は、 81111 ble-bind コマンドによる設定ではなく、cmap 配列に直接値を代入する方式として、 81112 設定スクリプトを吐き出す様に変更するか? 81113 81114 直接値を設定する様にすると既に何かを設定している時にそれを上書きする事で、 81115 データを破壊する事にもなるかもしれないので、その辺りについては確かめる必要がある。 81116 基本的には設定を追加・上書きするようにすれば良い。 81117 81118 →試しに配列に直接値を代入する形式でデータを出力してみた。 81119 出力したデータは 100 KB にも及び巨大だが、 81120 それを source してみた所 0.1 秒以内にロードできた。 81121 速度としては充分である。 81122 81123 + 既存の設定が存在している時にこれを追加して問題になりそうなのは 81124 "_" を代入する場合と "数字" を代入する場合である。 81125 "_" を代入する場合は既存の "数字" の設定があった場合に、その既存の設定を消す事になる。 81126 "数字" を代入する場合は既存の "_" の設定が存在する場合に、それを消す事になる。 81127 "数字_" を追加する場合については、既存の設定が何であれ完全に上書きしてしまうので関係ない。 81128 81129 既存の設定に対して安全に追加する事が出来るように書き換えてみたが、 81130 やはり処理に時間が掛かるようになった。term+default.sh で生成したエントリを全て追加するのに 1 秒弱かかる。 81131 直接配列を設定する場合には 0.075 秒しかかかっていなかったので、12-13 倍の違いがある。 81132 81133 また、dump 結果を source してから気付いた事だが、ただ cmap 内の情報を dump するだけでなく、 81134 キーとキーコードの対応表も一緒に読み込まなければ意味がない。 81135 そして、後から登録する方式だと、登録したいキーに対応するキーコードが既に使われている場合に、 81136 番号の再配置を実行しなければならないが、これはかなり重い処理になると思われるので現実的でない。 81137 81138 + 結局、現実的には既存の cmap に対して追加登録をするのではなく、 81139 cmap、キーコード・キー対応表を全て入れ替える形にするしかない。 81140 81141 + 所で良く考えたら declare -p "${!_ble_decode_...@}" 等とすれば 81142 81143 特別にロジックを書かなくても変数の内容を直接 dump する事ができるのでは? 81144 実際に試してみた所、declare で出力した物も、 81145 自分で書いた配列要素を一つ一つ初期化する形式の物も、 81146 source するのにはそれ程時間の違いはなかった。両方とも 0.105 秒程度かかる。 81147 若干 declare の形式の方が時間が掛かっている気もするが、誤差の範囲内であろう。 81148 81149 今後は declare -p を使って dump する事とし、今迄に書いた関数は削除する: 81150 [2013-06-09 14:37:52] 81151 81152 function .ble-decode-char.dump-entry { 81153 local tseq="$1" ccode 81154 eval "local -a ccodes=(\${!_ble_decode_cmap_$tseq[@]})" 81155 echo "_ble_decode_cmap_$tseq=()" 81156 for ccode in "${ccodes[@]}"; do 81157 eval "local ent=\${_ble_decode_cmap_$tseq[$ccode]}" 81158 echo "_ble_decode_cmap_$tseq[$ccode]=$ent" 81159 if test "${ent//[0-9]/}" = _; then 81160 .ble-decode-char.dump-entry "${tseq}_$ccode" 81161 fi 81162 done 81163 } 81164 function .ble-decode-char.dump-entryA { 81165 local tseq="$1" ccode 81166 eval "local -a ccodes=(\${!_ble_decode_cmap_$tseq[@]})" 81167 for ccode in "${ccodes[@]}"; do 81168 eval "local ent=\${_ble_decode_cmap_$tseq[$ccode]}" 81169 echo ".ble-decode-char.add-entry $tseq $ccode $ent" 81170 if test "${ent//[0-9]/}" = _; then 81171 .ble-decode-char.dump-entryA "${tseq}_$ccode" 81172 fi 81173 done 81174 } 81175 function .ble-decode-char.add-entryA { 81176 local bseq="$1" byte="$2" val="$3" 81177 if test -z "${val##*[0-9]_}"; then 81178 eval "_ble_decode_cmap_$bseq[$byte]=$val" 81179 elif test -z "${val##*[0-9]}"; then 81180 eval " 81181 local ent=\"\${_ble_decode_cmap_$bseq[$byte]}\" 81182 _ble_decode_cmap_$bseq[$byte]=${val}\${ent##*[0-9]} 81183 " 81184 elif test "$val" = _; then 81185 eval " 81186 local ent=\"\${_ble_decode_cmap_$bseq[$byte]}\" 81187 _ble_decode_cmap_$bseq[$byte]=\${ent%_}${val} 81188 " 81189 else 81190 echo unexpected value 2>&1 81191 fi 81192 } 81193 81194 + cmap+default.dump が存在すればそれを source する事にし、 81195 もしなければ cmap+default.sh から構築してから dump する様にする。 81196 81197 と思ったら正しくロードされていない。新しく構築した場合にはちゃんと動いているが、 81198 cmap+default.dump からロードするとロードされていない。 81199 関数内から cmap+default.dump を source していて、 81200 cmap+default.dump 内では declare で変数を宣言している為、 81201 その関数内の局所的な変数としてロードされている。 81202 81203 これをちゃんと動く様にする為には declare を宣言しなければ良いのだが、 81204 連想配列については、それが連想配列だという事を明示的に宣言できない。 81205 →しかし既に別の場所で宣言している筈だから問題ないのでは? 81206 実際に試してみた所、既に declare -A されている場合、 81207 新しく代入する場合でも問題は起こらないという事が分かった。 81208 81209 と言う訳で先頭の declare -? を削除して dump を出力する事にしたが、 81210 今度はエラーが発生する。よく見たら代入の右辺に一々引用符がついていて、 81211 配列としての代入ではなくて一つの長い文字列としての代入になってしまっている。 81212 declare の時には、declare コマンドが文字列として受け取った右辺を展開してから代入するので問題にならないのだろう。 81213 81214 今回は値としては常に一文字以上の [0-9_] だけで構成される物なので、引用符を全て外しても問題ないだろう。 81215 という訳で sed で引用符の類も全て削除する事にした。 81216 その上で source の時間を計測してみた所 0.064 秒にまで縮んだ (単にファイルサイズの問題のような気もしてきた…)。 81217 81218 + 無事に cmap+default.dump で現実的な速度で初期化できる様になったので、 81219 <del>古いコード (必要最低限の物だけの設定) は削除する。</del> 81220 と思ったが、後でまた欲しくなるかも知れないので、cmap+minimal.sh として残しておく事にした。 81221 81222 2013-06-08 81223 81224 [Done] 81225 81226 * <bug> ble-line-info: 表示している間、編集文字列のカーソル位置の文字が空白になる。 [#D0084] 81227 [完 2013-06-09 01:42:41] 81228 81229 これはカーソル位置を移動する時に _ble_edit_lc も変更してしまっているのが原因。 81230 _ble_edit_lc は描画関連の処理が終了してユーザの入力待ち状態になった時に、 81231 最終的にカーソルが存在しているべき位置の文字を示す物であって、 81232 これは一時的なカーソルの移動の際に変更するべき物ではない。 81233 81234 現状では「最終的にカーソルが存在しているべき位置と其処の文字」と、 81235 「現在の描画処理の為に移動しているカーソルの位置と其処の文字」を一緒に扱っている。 81236 変数を分けるべきではないだろうか。 81237 + _ble_line_curx _ble_line_cury _ble_line_curlc は配列に纏める事にし、 81238 これは「最終的にカーソルがあるべき位置と文字」とする事にした。 81239 また、_ble_line_x, _ble_line_y という変数を追加し、これを 81240 「描画中の現在カーソルが存在している位置」とする事にした。 81241 81242 + .ble-edit-draw.goto-origin, .ble-edit-draw.goto-end 関数を廃止し、 81243 .ble-edit-draw.goto-xy 関数を定義し、任意の座標に簡単に移動できるようにした。 81244 81245 + この変更によって .ble-line-info.draw, .ble-line-info.clear で 81246 復帰する必要が無くなったかも知れない。 81247 現在のカーソルの位置が分かっているのだから、 81248 わざわざ元の位置に戻らなくても良い。 81249 次に移動する必要が生じた時に適切に移動すれば良いだけである。 81250 (勿論、その為には .ble-line-info.* で現在のカーソル位置の情報を更新する必要がある。) 81251 81252 最終的に必ず update-adjusted が呼び出される。 81253 そして update-adjusted は必ず始めに update を呼び出す。 81254 update は現状の実装では必ず編集文字列部分は表示し直すから、 81255 結局必ずキャレットの場所へ移動する事になる。 81256 81257 + と思って実際に試してみたら位置を移動するようになってしまった。 81258 81259 これは単に _ble_line_x の変数名を _ble_edit_x としていた為であった。 81260 正しい変数に移動後の座標を書き込んでいなかった。 81261 81262 しかしこれを修正しても未だカーソルの位置がおかしい。 81263 座標位置を勘違いしていると言うよりは、 81264 info 情報を出力した直後のカーソル位置になっていて、 81265 その後 update-adjusted 等の操作が行われた形跡がない。 81266 81267 と思ったら _ble_line_y に対して数式をその儘代入していて、 81268 計算した結果を代入していなかった。 81269 しかしこのバグは今回の異常とは関係ない気もする。 81270 81271 果たして実際に試してみると未だ直っていない。 81272 また、.ble-edit-draw.update の前後で現在の座標位置が変化していない。 81273 本来であればこの部分で適切な位置への移動が行われると期待している。 81274 という事で改めて .ble-edit-draw.update を見てみると、 81275 実は .ble-edit-draw.update の先頭で 81276 _ble_edit_dirty が全く設定されていない時には何の操作もせずに終了するようになっていた。 81277 _ble_edit_dirty が設定されていなくても、位置が異なる場合には移動を実施する様に変更する。 81278 →これで取り敢えずカーソル位置は正しくなった。 81279 [2013-06-09 01:42:41] 81280 81281 また、その際に sgr の値を再設定する必要もある。(sgr は今迄は SCORC, DECRC 等に頼っていたが、 81282 本来は自分で管理できるようにしておきたい所である。) 81283 これについては別項目で取り扱う事にする。 81284 81285 * <bug> 複数行に渡る編集を実行している時に、何かを入力する度に表示位置がずれていく。 [#D0083] 81286 [2013-06-09 01:17:29] 81287 81288 ずれない様に設計している積もりだったが正しく動作していない様子である。 81289 先ず始めにずれて上にはみ出た行が消去されていない事から、 81290 .ble-edit-draw.clear の時点で原点に移動して削除するということができていない様である。 81291 可能性としては、現在の位置座標を勘違いしているか、原点へ移動する為の制御系列を誤って生成しているかのどちらかである。 81292 81293 .ble-edit-draw.redraw-cache の始めで現在位置がどうなっているかについて確認を行う。 81294 →座標値については正しく計算されている様である。 81295 という事は goto-xy が怪しいと思って改めて考えてみたら、 81296 今回の場合は y の移動量 dy が負になる。その時に ESC [ A に渡す引数を絶対値にするのを忘れていた。 81297 81298 * <bug> 色々変更している内にカーソルが先頭に移動するようになってしまった。 [#D0082] 81299 [完 2013-06-09 01:08:14] 81300 81301 goto-xy の引数に文字列で式を指定できるようにしていたが、 81302 これをすると goto-xy の中で新しく宣言した変数に影響を受けて値が変わってしまうので、 81303 やはり goto-xy の引数にちゃんと評価した後の数値を指定する様に変更した。 81304 81305 * 不要なデバグ用の古い関数 .ble-dbg,esc2a を削除 [2013-06-09 00:32:04] [#D0081] 81306 81307 * ble-edit.sh (complete-filename): 引数が一意に確定した場合、 [#D0080] 81308 ディレクトリ名の場合には後に / を挿入し、それ以外の場合には SP を挿入する様に変更。 81309 今迄はディレクトリ名であっても後に / を挿入していた。 81310 [2013-06-08 16:50:34] 81311 81312 * <bug> ble-decode-kbd: '*' を変換しようとすると、ファイル名展開が実行されてしまう。 [#D0079] 81313 仮定: * や ?, - が含まれるような single-key 指定は、 81314 必ず最後の一文字だけが * や ?, - 等の特殊文字である。 81315 それ以外の指定を行った場合の動作は保証しない。 81316 仮定: C- 等のような中途半端な指定は C-- と解釈される。 81317 [2013-06-08 16:01:32] 81318 81319 * keyflag の定義を emacs と同じ物に変更。 [#D0078] 81320 Meta=1<<28 Ctrl=1<<27 Shft=1<<26 Hypr=1<<25 Supr=1<<24 Altr=1<<23 81321 81322 * <bug> ble-decode-kbd: C-- や - 等を正しく変換する事が出来なかった。 [#D0077] 81323 81324 2013-06-06 81325 81326 [Done] 81327 81328 * 取り敢えず色付け関数 [#D0076] 81329 81330 * <bug> C-c: プロセスを停止した直後、プロンプトが表示されない [#D0075] 81331 [完 2013-06-07 03:52:15] 81332 81333 これは accept-line の処理が中途半端になったまま終了してしまうからである。 81334 81335 + C-c 等でプロセスを停止した時に 正しく終了されるか? 81336 →正しく終了されていない様である。 81337 81338 先ず何か入力するまでプロンプトが表示されない。 81339 (但し、^? などに対してはちゃんと読み取れる様である。 81340 ^? でも何でもいいから入力をすると復帰する。) 81341 これは accept-line の後の .ble-edit-draw.redraw が実行されていない為であろう。 81342 81343 適当に trap 'echo hello' INT とすると、 81344 続きが実行される様になった。因みに hello の文字列は何処かに消える? 81345 なので trap : INT 等とする事にする。 81346 (既に存在している trap を上書きしてしまう事になるが仕方がない。) 81347 [2013-06-07 03:19] 81348 81349 と思ったが、実際に試してみると、シェルの処理で重い場合に C-c をすると 81350 trap : INT や trap 'echo hello' INT 等としていた場合にシェルの応答がなくなってしまう 81351 という事が分かった。因みに trap を何も仕掛けていなければ正しく終了する。 81352 81353 と、思っていたが trap return INT にしておけば一応問題は起こらない様だ。 81354 [2013-06-07 03:52:15] 81355 81356 <del>しかし trap 'return 128' INT にすると今度は return は関数内でなければ 81357 使えないというエラーメッセージが表示される。</del> 81358 どうも trap を定義した場所が関数内なら return を書いてもエラーは出ない様だ。 81359 なので、.ble-edit.accept-line.exec.eval 内で trap をする事にした。 81360 しかし、return 128 等としても戻り値は常に 0 となる様子なので、 81361 _ble_edit_accept_line_INT という変数を介して 128 の値を返す事にした。 81362 [2013-06-07 04:12:50] 81363 81364 * <bug> readline の accept-line をしない限り $? が設定されない? [#D0074] 81365 前回のコマンド実行の $? を何処か別の変数に覚えておいて、 81366 次のコマンドを実行する直前に設定し直せばよい。 81367 設定するには、return で好きな値を返すだけの適当な関数を作って、 81368 その関数を呼び出せばよい。 81369 [2013-06-07 02:20:26] 81370 81371 * <bug> .ble-edit-comp.complete-filename: 変数リーク ret [2013-06-07 02:02:07] [#D0073] 81372 81373 * <bug> return による accept-line 中断 [#D0072] 81374 [2013-06-07 02:09:41] 81375 81376 C-c や C-z をした時の様に、 81377 コマンドライン中に return が含まれていた場合にも同様の事が発生する。 81378 これについてはコマンドを実行する際に一つ関数にくるんで実行すればよい 81379 81380 * ジョブ管理にアクセスできるか? [#D0071] 81381 問題なくアクセスできるようである。 81382 81383 * accept-line: 存在しないコマンドでも history に追加される。 [#D0070] 81384 [キャンセル 2013-06-07 01:55:03] 81385 81386 history に追加する前にそのコマンドが存在するか確認。 81387 そもそも存在しない・実行できないコマンドに対しては history への追加を省略する。 81388 81389 存在するかどうかの確認は type で確認できる物、及び、for などの文法要素? 81390 →試しに for を type -t に入れてみたら keyword となったので、 81391 for 等を特別に区別する必要性はない。 81392 81393 と改めて調べてみたら、元々の bash でも存在しないコマンドもちゃんと history に追加されていた。 81394 なのでこれについて解決する必要性はない。 81395 81396 * <bug> accept-line: [完 2013-06-07 01:53:25] [#D0069] 81397 81398 ret 変数に値を設定できない。 81399 というか、accept-line を呼び出すまでにネストした 81400 関数で local として宣言されている変数名は全て使えない…。 81401 81402 a. accept-line は呼出のネストの浅い所で実行する? 81403 (例えば ble-decode-byte などで) 81404 b. 内部変数として使用している変数名を重複の無い物 (_ble_* を予約) にする? 81405 81406 a. の方針で行くとしたら、呼出が開始された一番浅い場所を見つける必要がある。 81407 ble-decode-byte から ble-decode-char, ble-decode-key と呼び出される過程で、 81408 何処が一番初めに呼ばれたかを判定するのは難しい。 81409 81410 ble-decode-byte:bind が起点になる場合は明らか。 81411 ble-decode-char が起点になるかどうかの判定は難しい。 81412 代わりに内部の呼出では .ble-decode-char を使う事にして、 81413 外部からの呼出 (起点) では ble-decode-char を使い、 81414 ble-decode-char は .ble-decode-char の呼出 + 修飾処理、という事にすれば良い。 81415 81416 従って、書き換えは 81417 1 全ての ble-decode-byte, ble-decode-char, ble-decode-key の内部呼出を 81418 .ble-decode-byte, .ble-decode-char, .ble-decode-key に書き換える。 81419 また、それぞれの関数名も書き換える。 81420 2 ble-decode-byte, ble-decode-char, ble-decode-key を定義し、 81421 中で .ble-decode-byte, .ble-decode-char, .ble-decode-key を呼び出すと共に、 81422 その他の前後の処理を追加する。 81423 という手順で行えば良い。 81424 81425 先ず、ble-decode-byte は内部的には何処からも呼び出されていない様である。 81426 ble-decode-char は ble-decode.sh 内にしか存在しない。 81427 ble-decode-key は ble-decode.sh が殆どで、ble-edit.sh に一箇所だけ存在する。 81428 これらを書き換えて、呼出の起点に近い場所で実行するように変更した。 81429 81430 しかし、未だ漏れている変数が存在するようだ。以下の変数は値が漏れている。 81431 arr file line ret spec 81432 81433 spec: .ble-edit.history-add 81434 line: .ble-edit.history-load, ble-decode-bind 81435 file: .ble-term.initialize 81436 arr: ble-getopt 81437 ret: ble-edit+self-insert, ble-decode-bind, ble-bind, 81438 ble-decode-unkbd 定義直後にテストコードが残っていた 81439 _getopt_*: ble-bind 81440 81441 * <bug> ble-decode-byte+C: 文字コードとして空文字列を返していた。 [#D0068] 81442 [2013-06-07 00:51:25] 81443 81444 * C-c 等でプロセスを停止した後、次のコマンドを実行するまで行が二重化する [#D0067] 81445 [2013-06-07 00:19:05] 81446 81447 C-c でプロセスが失敗した後に accept-line を押すと line が二重に表示される。 81448 これは実際に別のコマンドが実行されるまで続く。 81449 多分、これも stty の設定が変化しているから? 81450 多分エコーの設定が有効になっている為に、 81451 C-j/C-m が入力された時に行の位置がずれてしまうからだろう。 81452 81453 これは空コマンドだった場合にも .ble-stty.enter を実行すればよい。 81454 というか寧ろ ble-decode-byte:bind 辺りで実行しても良いかも知れない。 81455 81456 * <bug> accept-line: 時々コマンドを実行した時に現在位置が上の方に移動してしまう。 [#D0066] 81457 81458 <del>どうも accept-line を実行した時に、カーソル直前に存在する文字が 81459 特殊文字であるとこの現象が発生するようである。</del> 81460 81461 どうも特殊文字でなくても、カーソルの位置が line の最後の文字以外に置いてある時に、 81462 この現象が発生するようである。そして特殊文字を入力する時は大抵、先に引用符を書いておいてから、 81463 引用符の中に入って特殊文字を入力し、そのまま accept-line する為に、この条件に該当する。 81464 81465 そしてこの条件が該当しそうな箇所が .ble-edit-draw.goto-end にある。 81466 と思ったら、_ble_line_cury に x 座標を代入していた。 81467 [2013-06-06 23:57:43] 81468 81469 * <bug> カーソルの表示位置がおかしくなった [#D0065] 81470 construct-line で変数名を変更したのに、それを参照している construct-line.chk-cursor で 81471 変数名の変更していないのが原因だった。 81472 [2013-06-06 23:38:24] 81473 81474 * <bug> \\ や \$ が含まれる時の位置計算が誤っている。 [#D0064] 81475 [2013-06-06 23:37:21] 81476 81477 * .ble-line-info.clear: 既にクリアされている場合は動作を省略 [2013-06-06 23:05:49] [#D0063] 81478 81479 * discard-line, accept-line: 実行の前に .ble-line-info.clear [2013-06-06 23:06:17] [#D0062] 81480 81481 * construct-prompt: シェル変数 x y lc に計算結果を直接書込をする様に変更。 [#D0061] 81482 [完 2013-06-06 23:05:09] 81483 81484 + キャッシュ情報は 配列 _ble_line_prompt に記録する事にした。 81485 _ble_cursor_prompt__LINENO, _ble_cursor_prompt__RESULT の変数を廃止 81486 + 呼出元を調整。 81487 81488 * complete 候補一覧を表示 [#D0060] 81489 取り敢えず表示するだけ表示 [2013-06-06 18:07:53] 81490 81491 * ble-decode: [#D0059] 81492 ble-edit-bind の部分にあった bash に対する bind のロジックを 81493 ble-decode.sh の方に移動させる事にした。 81494 [2013-06-06 17:41:05] 81495 81496 * isearch: C-d を押した時に空欄だと即座に終了してしまう。 [#D0058] 81497 (C-d に delete-char-or-exit が設定されている場合)。 81498 なので、isearch で C-d を押した時は isearch モードを抜けてから 81499 唯の delete-char を実行する様に変更。 81500 [2013-06-06 17:40:50] 81501 81502 * C-x に対する hook [#D0057] 81503 81504 * ble-bind [#D0056] 81505 ESC → Meta が自動的に実行される様になったので、 81506 Meta について改めて登録する必要はなくなった。ので、その機能は削除。 81507 [完 2013-06-06 17:18:33] 81508 81509 * <bug> ble-decode-char [#D0055] 81510 [完 2013-06-06 17:02:07] 81511 81512 M-delete 等の操作が正しく key に翻訳されていない。 81513 これは ESC を meta に変換する機能を入れても入れなくても同様。 81514 更に ble-bind -k で Meta の付いた物を自動的に登録しても登録しなくても同じ。 81515 81516 と思ったらそもそも ble-decode-char 自体に二つ連続した ESC は入ってこない様だ。 81517 screen または bash bind -x で消えてしまっている可能性がある。 81518 81519 + 試しに bashrc 内で bind している '[D' と '[C', '[3;5~' を削除してみた。 81520 削除自体は正しく出来たようだが、依然として '' は消えた儘になっている。 81521 81522 + /etc/inputrc を見てみたが '\e\e' に関係する物は設定されていない。 81523 また、~/.inputrc は作っていなかった。 81524 81525 + .screenrc を見てみたが C-M-tab に windowlist を割り当てている以外は怪しい所はない。 81526 それに emacs を起動している間はちゃんと ESC ESC を入力する事が出来ているのだから、 81527 screen は犯人ではない。やはり bash が怪しい。 81528 81529 A 仕様がないので、直接 "" に対して bind を実行してしまえばよい。 81530 其処で bind -x '"":ble-decode-byte:bind 27 27' として見たが、 81531 そうすると今度は ESC ESC を受け取った時に、 81532 bash: bash_execute_unix_command: コマンドのキーマップがありません 81533 というエラーが発生してしまう。 81534 81535 B 取り敢えず、苦肉の策として ESC ESC を何か別の物に変換して受信する事にした。 81536 ble-bind -k 'ESC [ 2 7 ^' __esc__ 81537 ble-bind -@f __esc__ 'ble-decode-char 27' 81538 bind -s '"":"[27^[27^"' 81539 81540 と思ったら、何故か "ESC ^ ^ ESC ^ ^ [ 2 7 [ 2 7" という謎の順番で受信される。訳が分からない。 81541 bind -s '"":"[1027~[1027~"' に変えてみたら、 81542 "ESC 2 2 7 ~ ESC 2 2 7 ~ [ 1 0 [ 1 0" となる。^ が悪かった訳ではない様だ。 81543 文字数の問題? 81544 bind -s '"":"[^[^"' → "ESC ESC ESC [ ^ [ ^" 81545 どうやら ESC 後の 3 番目の文字が繰り返される様である? 81546 bind -s '"\e\e":"\e[^\e[^"' → "ESC ESC ESC [ ^ [ ^" # bind で文字化けしているのかとも思ったがそうではないようだ。 81547 bind -s '"\e\e":"\e[~"' → "ESC [ ~ ESC [ ESC ESC ESC ..." # 理解不能 81548 81549 もしかして、ble-decode-char の方のバグだろうか。。 81550 今度は ble-decode-byte の方で出力を行ってみる事にした。 81551 "[27^[27^" → "ESC ^ ESC ^ [ 2 7 [ 2 7" この時点で謎 81552 "[1027~[1027~" → "ESC 2 7 ~ ESC 2 7 ~ [ 1 0 [ 1 0" ~ でも駄目 81553 "[^[^" → "ESC ESC [ ^ [ ^" 短くしても駄目 81554 "[1027^" → "ESC 2 7 ^ [ 1 0" 単体の ESC でも発生する 81555 "\e[~" → "ESC [ ~" これは正しく受信されている 81556 "\e[^" → "ESC [ ^" これも OK 81557 "\e[7^" → "ESC ^ [ 7" これは駄目 81558 "\e[?^" → "ESC ^ [ ?" これも駄目 81559 "\e[?~" → "ESC ~ [ ?" これも駄目 81560 81561 取り敢えず ESC を含んで 3 文字以上のシーケンスが何故か化ける様なので、 81562 3文字 で "ESC [ ^" とする事にした。 81563 これで受信される物は正しくなったと思われる。 81564 81565 + BUG 受信しているバイトは正しいが ble-decode-char が正しく処理してくれない。 81566 81567 動作を見ていると ESC [ ^ を受け取った時点で __esc__ が生成されている。 81568 そしてその直後に M-[ が出力されている。 81569 更に次の "[" を受け取った時に再び M-[ が出力される。 81570 81571 一つの原因は、_ble_decode_key__seq をクリアしない内にコマンドを実行している為、 81572 コマンドの内部で新しいキーが来た時に _ble_decode_key__seq に追加されて処理されてしまう事である。 81573 これは、コマンドを実行する前に _ble_decode_key__seq= とする事で解決する。 81574 基本的にコマンドを実行する時には、ble-decode-key の内部状態を終了状態と同じにしてからにするべきである。 81575 要するに破壊的操作を全て終えてから、コマンドを実行する、という事。 81576 81577 ble-decode-key の中の _ble_decode_char__seq についても同様である。 81578 これを修正した所、どうやらちゃんと期待通りに動くようになった。 81579 81580 * ble-decode-char [#D0054] 81581 ESC を meta に翻訳するのは自動にするべき。 81582 例えば M-あ などまで考慮していたら、全てを登録し尽くす事は無理なので。 81583 81584 * <bug> ble-decode-key でシーケンス全体の一致に失敗して、 [#D0053] 81585 部分一致に成功した時、一致部分の直後のキーが失われる。 81586 これは 一致した場合に ble-decode-key "$fail" を実行せずに関数を抜けていたのが原因である。 81587 依然 ble-decode-char で起こったのと同様の問題点。 81588 その時には ble-decode-key には問題がないと判断したが、問題は在ったようだ。 81589 [完 2013-06-06 16:58:25] 81590 81591 * <bug> ble-edit-bind: "\e ": set-mark を unbind できていない。 [#D0052] 81592 [完 2013-06-06 15:26:53] 81593 81594 * ble-edit-bind: bind -s についても表示できるから、これについても全て unbind する。 [#D0051] 81595 [完 2013-06-06 15:26:48] 81596 81597 * <bug> ble-bind -d [#D0050] 81598 -m isearch 等を用いて登録したキーシーケンスが表示されない。 81599 現在登録されている kmap 名のリストを追加して、 81600 ble-bind -d で全ての kmap について表示するように変更した。 81601 81602 2013-06-05 81603 81604 [Discussion] 81605 81606 * COMP_KEY [#D0049] 81607 bash の manual には最後のキーとあるが、 81608 文字で表現するのか、名前で表現するのか文字コード (?) で表現するのか分からない。 81609 実際に、適当な関数を登録して確かめてみると良いだろう。 81610 81611 →試してみた所文字コードが表示された。 81612 更に function キーに complete を割り当てて試してみた所、 81613 バイトシーケンスでの最後のバイトが渡される様である。 81614 (しかし、これでは不便? な気がするので、独自解釈で ble の keycode を用いる事にする。 81615 その際に C-* 系統の物は変換した方が良いかも知れない。) 81616 81617 [Done] 81618 81619 * visible-bell: 鳴った瞬間だけ緑色に点滅する様に変更。 [#D0048] 81620 これで連続で visible-bell が鳴った時でも見た目に分かる。 81621 81622 # + 鳴った瞬間だけ赤くして直ぐに暗くする 81623 81624 * <bug> isearch: self-insert で単に入力しているだけなのにどんどん遡ってしまう。 [#D0047] 81625 self-insert の時には現在行から一致を初める様に変更する。 81626 [完 2013-06-05 23:42:37] 81627 81628 * <bug> quoted-insert, v だとか q が挿入される [#D0046] 81629 これは self-insert の仕様変更について行ってなかったのが原因。 81630 代わりに insert-string を使う実装に変更した。 81631 [完 2013-06-05 19:57:59] 81632 81633 * clear-screen: vbell の削除トラップをクリアする [#D0045] 81634 [完 2013-06-05 19:18:02] 81635 81636 * isearch: arr の top が行き先と同じであれば、arr に push せずに pop する [#D0044] 81637 [完 2013-06-05 19:03:41] 81638 81639 * isearch: 表示位置への移動などをもっとまともな物に変更する。 [#D0043] 81640 [完 2013-06-05 18:47:07] 81641 81642 * isearch: 終了時に isearch の表示を消す [#D0042] 81643 [完 2013-06-05 18:47:17] 81644 81645 * isearch: prev でもうこれ以上戻れない時、isearch から抜けない [#D0041] 81646 [完 2013-06-05 18:48:15] 81647 81648 * c2w 二分法: 0-161 の間の文字が怪しい? [#D0040] 81649 + 初めから範囲にない場合 (0-161) の場合は先に除外するべきだった。 81650 + l&1 を括弧で囲む必要があった。 81651 + while の条件は l<u ではなく l+1<u であった。 81652 [完 2013-06-05 18:27:32] 81653 81654 * ble-core.sh (.ble-print-visible-bell): .time 削除で date +%s の値が overflow しない様に [#D0039] 81655 部分文字列を取りだす部分が間違っていた。 81656 [2013-06-05 16:14:46] 81657 81658 * ble-core.sh (.ble-print-visible-bell): SC, RC を頻繁に使うので、後で変更しやすいように [#D0038] 81659 _ble_term_sc, _ble_term_rc 定数に定義。 81660 [2013-06-05 16:14:46] 81661 81662 * __defchar__ は制御文字には適用しないように変更 [#D0037] 81663 81664 2013-06-04 81665 81666 [Done] 81667 81668 * <bug> どうも履歴の動作が怪しいような気がする。 [#D0036] 81669 C-p C-n で動くと変な出てき方をする…気がする。 81670 それに先程実行したはずのコマンドが出てきたり出てこなかったりする。 81671 81672 →と思ったら history-add で実際に登録される場合だけ 81673 _ble_edit_history_ind, _ble_edit_history_edit を初期化していた。 81674 それ以外の場合は、前回の履歴位置・編集内容をそのまま使う事になっていた。 81675 そうすると例えば、前回履歴を遡って実行したコマンドは空白に変化し、 81676 また、現在の履歴の位置も途中の場所にいたりと変な事になる。 81677 81678 [完 2013-06-05 02:50:10] 81679 81680 * vbell: [#D0035] 81681 ble.sh をロードした時に、 81682 古い .time ファイルは全部削除する機能をつける。 81683 81684 * ble-bind -c: meta も登録する [#D0034] 81685 → 完了 2013-06-05 02:40:02 81686 81687 * ble-bind 引数はシェル変数で渡す様にした方が良い? (-f オプションの削除) [#D0033] 81688 + self-insert は KEYS[0] シェル変数を用いる様に変更した。 81689 + f オプションの削除 81690 81691 * ble-bind -c, -k オプションの名前を変更する [#D0032] 81692 → それぞれ -k, -f に変更した。2013-06-05 02:40:06 81693 81694 * bug? bind [#D0031] 81695 何と " を bind する事ができていない。 81696 と思って改めて試してみたらちゃんと bind されている?? 81697 取り敢えず保留という事にする。 81698 81699 * <bug> 次のコマンドを実行するまで prompt が更新されない [#D0030] 81700 CMD ではなく LINENO を参照するように変更 81701 81702 * abell はロックするので vbell の後に送信するべき [完 2013-06-05 01:25:27] [#D0029] 81703 81704 * 矢印キーなどの動作を取得する事が出来るかチェック [完 2013-06-05 01:25:41] [#D0028] 81705 (1) ESC で始まるシーケンスを全て削除する? 81706 試しに全て削除してみたら、(自分で bind -x で設定した物を除いて、) 81707 上下左右のキーや function キーも効かなくなった。 81708 ので、C-[ さえ bind -x してしまえば恐らく処理できると思われる。 81709 81710 → source されたスクリプトの中で bind -r を実行しても削除されない? 81711 と思ったら bind の時は必要だった引用符 " が、bind -r の時には不要だった。 81712 81713 (2) ESC に bind できるか? 81714 一応 ESC には bind できているみたいだが、delete を押してもそうと認識されない。 81715 しかも二回に一回だけ通常の文字列として delete が入力される。 81716 奇数回目の delete は何処へ行っているのか? 81717 81718 ble-decode-key の受信する key を見てみた所、 81719 delete を入力した直後には ble-decode-key には delete が来ない。 81720 その次の文字を入力すると ble-decode-key に delete が渡される。 81721 その後に続く文字は一文字ずつ分解されて届く様である。 81722 81723 先ず、問題点として 81724 a. ~ を受け取った時点で delete に確定している筈なので、 81725 その時点で delete が届かないのがおかしい 81726 b. また、delete が受信された後の文字が単体で必ず decode-key に渡ってくるのが問題である。 81727 c. delete は処理されなかったはずなのに、その事を表すエラーメッセージが表示されない 81728 81729 + BUG: delete が届かない? [完 2013-06-05 00:00:50] 81730 81731 と思って実際に初期化が終わった後の cmap を見てみたら 81732 最後の文字なのに「継続あり」の _ がついている。 81733 .ble-decode-char.bind を見たら条件が反対になっていた。 81734 (.ble-decode-key.bind の方は大丈夫かと思ってみたら大丈夫だった、 81735 .ble-decode-key.bind に合わせる形の方向で修正した。) 81736 81737 ** デバグの為に一時的にバグ状態に戻してある ** 81738 →他のバグも解決したのでこれはまた修正した。 81739 81740 + BUG: 曖昧文字の失敗後に、その失敗に関連した文字がすぐに送信されてくる? 81741 [完 2013-06-05 01:25:41] 81742 81743 と思って手でエスケープシーケンスを入力したりしてみたが、少し違うようだ。 81744 delete ESC [ まで入力した段階では delete までしか出力されていない。 81745 ここまでの動作は正しいが、次に A を入力した時点で、 81746 ESC [ A がその儘出力されて出て来る。 81747 81748 本来は ESC [ A は up と翻訳されて欲しい。 81749 _ble_decode_cmap_* を見てみたがここの部分は問題ない様に見える。 81750 (a. の方の BUG の事を考えると、本当は ESC [ A だけでは未だ出力されないはず…。 81751 そして実際に、先行する delete がない状態では ESC [ A を送信してもその時点では何も出力されない。 81752 従って、cmap の問題ではなく内部状態に何らかの異常が出来ていると考える方が自然である。) 81753 81754 と思ってみてみた所、delete ESC [ まで入力した段階では、 81755 実は未だ ESC [ は bash まで届いていない? 様である。 81756 screen だか或いは途中の何かが文字を止めているという事だろうか。。 81757 (と、ここで screen に C-TAB = [9;5^ に対する hook をかけているという事を思い出した)。 81758 81759 そして、ble-decode-char は delete のシーケンスが残っている状態で 81760 ESC を受け取った時にそれを組み立てずにそのまま出力しているらしい。 81761 要するに奇数回目の入力と偶数回目の入力で何が違うかというと、 81762 偶数回目の入力の一番初めの文字 ESC が到着した時には、 81763 未だ奇数回目のシーケンスが残留しているという事である。 81764 81765 という所で、怪しい部分を発見したが…その部分は今回と関係ないような気もする。 81766 しかし取り敢えず、その部分を修正する (余分な return を消す)。すると今度は、 81767 ble-decode-key に渡される key 自体は何も可笑しい所がないように見えるのに、 81768 実際に編集文字列に現れてくる文字列には違う入力されている。。 81769 先にエラーメッセージが表示されない謎を解決した方が早いかも。 81770 81771 下のバグを解決したらこちらのバグも解決した。先程の修正で良かった様だ。 81772 今迄 ESC [ A が裸で出力されている様に見えたのは勘違いで、 81773 1 delete のシーケンスが残っている状態で ESC が来ると、 81774 delete だけ出力されて ESC は出力されずに終わる (一つ目のバグ)。 81775 2 delete のシーケンスが化けて (二つ目のバグ) 81776 (1) で出力し損ねた ESC になって、self-insert で入力される。 81777 という流れになっていたのだった。つまり 81778 ESC [ A ESC [ A 81779 ~~~~~~~~~~~ 81780 delete [ A 81781 ~~~~~~ 81782 ESC [ A 81783 と言う風に変換されていたのだった。 81784 81785 81786 因みに .ble-decode-key.emit の方には同様のバグがないかと確認してみたが、 81787 その様なバグはなかった。ちゃんと余分な return は消されていた…。 81788 81789 + BUG: 知らないシーケンスが届いた筈なのにエラーメッセージが表示されない。 81790 [完 2013-06-05 01:13:43] 81791 81792 と見てみたら、すぐに気付いた。「知らないシーケンスが届いた時に "$key" 単体を 81793 文字と解釈できる場合には __defchar__ で処理する」という所で $key の代わりに $fail と 81794 書いていた。そしてこの $fail は呼出元の ble-decode-char の $fail を参照して、 81795 出力していない筈の文字を出力してしまうという事になっていた。 81796 81797 これで解決できたと思ったら、今度は up が変な文字として入力されてしまう様になった。 81798 これは __defchar__ で処理するのは unicode の16面までという制限をかければ良い。 81799 0x110000 という定数が何回か出てきたので ble_decode_function_key_base という定数として定義し直した。 81800 これを用いて文字として解釈できる unicode の範囲を絞って扱う事にした。 81801 81802 * <bug> history add したコマンドの \ が消えている。 [#D0027] 81803 [完 2013-06-04 23:26:03] 81804 81805 どうやら読み込む時に read が勝手に \ を消しているようだ。 81806 read に勝手に \ を解釈されたくなければ read -r とする。 81807 登録・書込の方には問題はないようだ。 81808 81809 他にも read を使っている所があるのでそれについても修正をする必要がある。 81810 81811 * <bug> .ble-edit.construct-prompt: \w でホームディレクトリ以下のパスが ~// となる。 [#D0026] 81812 [完 2013-06-04 23:05:35] 81813 81814 ~ に続きがある場合に / を追加する様に書いていたが、 81815 良く考えたら ~ に続きがある場合には / がどうせ先頭になっているので必要なかった。 81816 81817 * <bug> HISTIGNORE の値に反して一文字のコマンドが history に追加されている [#D0025] 81818 [完 2013-06-04 22:50:16] 81819 81820 単に配列変数の名前を間違えていただけだった。 81821 81822 * <bug> (.ble-edit.construct-prompt): \! (HISTCMD) が常に 1 [#D0024] 81823 これは bind -x で登録された関数から見るとこうなってしまうという事なのだろうか。 81824 代わりに _ble_edit_history の要素数を返せば問題はないだろう。 81825 [完 2013-06-04 22:43:49] 81826 81827 * <bug> ble-decode-byte を直接呼び出すと PS1 の値が破壊される [#D0023] 81828 [完 2013-06-04 22:32:33] 81829 81830 PS1 が解除された状態で ble-decode-byte が呼び出され…? 81831 調べてみた所、ble-decode-byte の中で PS1 を代入していた。 81832 81833 良く考えてみたら、再描画や adjust-cursor 等の呼出は、 81834 直接コマンドを叩いて呼び出した時には必要のない物である。 81835 なので、bind -x する時専用の ble-decode-byte を作って、 81836 その中で PS1 の設定や再描画、カーソル位置微調整を行えば良い。 81837 →その様に変更した。 81838 81839 * suspend した時にどうなるか? [#D0022] 81840 81841 特に問題が生じるという訳でもない様だ? 81842 但し、以下の点については意識する必要がある。 81843 81844 (1) stty の設定がどうなっているか 81845 [完 2013-06-04 20:34:42] 81846 81847 <del>恐らく stty を復元したままになっている。 81848 従って ^W ^U 等の操作を行う事ができないと思う。</del> 81849 81850 <del>直後に直すのは諦めるとしても、 81851 次に ^W ^U など以外の文字が入力された時に、 81852 stty の状態を確認して元に戻すという事はするべきである。</del> 81853 81854 と思っていたらどうやら suspend で止まった場合でも、 81855 スクリプトの続きから開始される様である。 81856 つまり、accept-line の後半部分も suspend の直後に実行される。 81857 なので何の問題も生じない。 81858 81859 (2) コマンド履歴に suspend したプロセスが追加されていない。 81860 [完 2013-06-04 19:54:07] 81861 81862 コマンド履歴に追加される前にコマンドが実行されている。 81863 これは登録を先に行うように変更するだけでよい。 81864 81865 (但し bash ではコマンド見付からなかった場合には、 81866 コマンド履歴に追加されないようになっている。 81867 コマンドを実行に移す前に予め、 81868 そのコマンドが存在するかどうかぐらいは判定しても良さそう。) 81869 81870 (3) 編集中のコマンドが残っている [完 2013-06-04 20:36:18] 81871 81872 これも編集文字列をクリアする前にコマンドを実行しているからである。 81873 コマンドを実行に移す前に編集文字列をクリアする事にする。 81874 81875 * ちらつきを抑える方法: 最初に再描画 [完 2013-06-04 18:32:52] [#D0021] 81876 ble-decode-byte に入った瞬間に .ble-decode-key.redraw を実施する? 81877 その時は、前回から内容が変わっていない筈なので、前回保存した情報をそのまま出力すれば良い。 81878 そして呼出が終わった後に変更があればその時点で再描画をまた実行する。 81879 81880 + BUG: prompt の表示が省略されている [完] 81881 81882 → 前回保存した内容が prompt 表示を省略する物だった為 81883 → prompt 表示の省略をしない物をキャッシュに入れておく事にした。 81884 81885 関数 redraw-cached は「フル」で表示し直すが内容は「前回」のまま、という関数である。 81886 ので、表示の省略などは行わないので、この方法で良い。 81887 81888 + BUG: 前回の残像が残っている [完] 81889 81890 redraw をする際に前回表示した内容を消していないので残ってしまう。 81891 これは .ble-edit-draw.redraw, .ble-edit-draw.update でも同様に起こりうる問題である。 81892 (今迄は bash が1行目を勝手に消していたので気付かなかっただけである。) 81893 81894 + BUG: 表示が滅茶苦茶になる 81895 81896 原因は色々あった。 81897 事。 81898 "前回の表示内容" に関しては保存していたが、 81899 その内容を出力した際に現在のカーソルが何処に移動するかといった情報を保存・復元するのを忘れていた。 81900 唯単に前回の表示内容を出力しただけだと、内部的にカーソル位置が先頭から動いていない事になっている。 81901 なので、ちゃんと "前回の表示内容" を保存すると共に、その内容を表示した時にカーソルが何処へ移動するか等の情報も保存するように変更した。 81902 81903 何とか、前回の表示内容を再度出力する物が完成したので、昔のコードは削除する。 81904 | function ble-decode-byte { 81905 |- # bash によって描画された物が全部消されている 81906 |- # .ble-edit-draw.set-dirty -1 81907 |+ .ble-edit-draw.redraw-cache 81908 81909 これでちらつきはかなり改善された。 81910 81911 しかし、ちらつきが全くないと迄は言えない。もし気になる様だったら 81912 81913 * bug unkbd [2013-06-04 17:59:04] [#D0020] 81914 81915 配列への追加で、添字に ${#kbd[@]} とするべき所 ${kbd[@]} としていた。 81916 81917 * LINENO が更新されない? [#D0019] 81918 →これは一回 unset LINENO してから自分で設定すればよい。 81919 81920 どうせ自分で LINENO は管理しなければならないのでこの方法でよい。 81921 81922 2013-06-04 81923 81924 * X6 stty 関連 (tty が制御文字を奪うという事) [2013-06-04 13:33:26] [#D0018] 81925 81926 * tty の設定で動かなくなるキーと tty で設定されていても動くキーがある。 81927 よく分からないので表にする事にする。 81928 81929 ^S ^Q 81930 →stty で外すか -ixon の設定にすれば OK 81931 基本的に -ixon の設定で行く方針。常にこの状態という事にする。 81932 81933 ^C 81934 →bind する時は stty intr "" でも問題ない。 81935 然し、実際に使う時には stty intr undef でないと読み取れない。 81936 ^Z 81937 →^C と同様 bind 時はどちらでも問題ない。 81938 実際に読み取りの時は stty susp undef でないと駄目。 81939 ^\ (quit) も ^C や ^Z と同様である。 81940 81941 ^V 81942 →bind する前に stty lnext undef する必要がある。 81943 bind した後も stty lnext undef の儘保持しておく必要がある。 81944 81945 ^U (kill) ^W (werase) も ^V と同じである 81946 81947 ^? 81948 →bind する間だけ stty erase undef し、 81949 <del>その後で stty erase "" などと復元すれば良い?</del> 81950 と思ったが何故か stty erase undef でなくても動いたり、 81951 stty erase undef でないと動かなかったりよく分からない。 81952 取り敢えず ^V の時と同じようにずっと erase undef の儘にしておく事にする。 81953 81954 81955 <a href="http://lists.gnu.org/archive/html/bug-bash/2004-08/msg00157.html">'bind "\C-?": delete-char' does not work any more</a> 81956 81957 ※文字列編集中だけ外されている stty 項目がある可能性? 81958 81959 # | key bind read 81960 # -------------+------------------- 81961 # -ixon | ^S ^Q 81962 # kill undef | ^U 必要 必要 81963 # lnext undef | ^V 必要 必要 81964 # werase undef | ^W 必要 必要 81965 # erase undef | ^? 必要 必要 81966 # intr undef | ^C 不要 必要 81967 # susp undef | ^Z 不要 必要 81968 # susp undef | ^\ 不要 必要 81969 # -------------+------------------- 81970 81971 * ^? が偶に bind 出来ないように見える問題 81972 81973 どうやら一回目に stty を解除して bind に挑戦すると失敗している様で、 81974 二回目に bind に挑戦すると成功している様だ? 81975 再度 stty の設定を元の状態に戻して ble.sh を設定してみたら、 81976 ^? ^U ^V ^W の四つについて bash の bind が機能していないという事が分かった。 81977 81978 改めて bind -x '"":ble-decode-byte 127' を手で入力してみた所使える様になる。 81979 やはり stty を設定した直後には bind を設定する事が出来ないという事だろうか。 81980 81981 色々試してみる 81982 (1) stty の後に適当に echo するとどうなるか? 81983 →適当に echo するだけでは駄目なようだ。 81984 81985 (2) stty の後に sleep で待ってから設定するとどうなるか? 81986 →sleep で待っても駄目なようだ。 81987 81988 (3) stty の後に >/dev/null で適当な文字列を書き込むとどうなるか? 81989 →やはり駄目。 81990 81991 (4) read -n 1 で適当に文字を読み取るとどうなるか? 81992 →これでも駄目だった。 81993 81994 (5) subshell ( date ) を呼び出す 81995 →駄目 81996 81997 もしかして source ble.sh で一つのコマンドとして実行しているから設定が有効になっていないという事だろうか? 81998 後、一回 exit してから入るとうまく行くのは、C-d で exit する直前に .ble-stty.leave していなかったからであった。 81999 或いは bashrc 等のスクリプトから実行するとうまく行くのかも知れない。 82000 82001 仕方がないので現状では .ble-decode-byte:bind で、 82002 既に ^U ^V ^W ^? に bind しているかどうか確認して、 82003 設定されていない様だったら設定を行う様にする事にした。 82004 82005 * C-@: 効かないと思っていたら bind できていない [完] 82006 82007 bind -x '" 82008 →確かにこれでは bind できない 82009 bind は '"' という文字列を受け取ったと勘違いする。 82010 82011 bind -x '"\C-@":ble-decode-byte 0' 82012 →これで正しく bind 出来るようになった。 82013 82014 * 全ての文字を入力可能かどうか確認 82015 82016 C-@ OK (bind する時に直接 ^@ の文字を引数に指定できない事に注意) 82017 C-a OK 82018 C-b OK 82019 C-c OK (stty intr undef) 82020 C-d OK (READLINE_LINE にダミー文字を設定。可成り苦労した…) 82021 C-e OK 82022 C-f OK 82023 C-g OK 82024 C-h OK 82025 C-i OK 82026 C-j OK 82027 C-m OK (stty の改行変換周りで状況が違うかも?) 82028 C-n OK 82029 C-o OK 82030 C-p OK 82031 C-q OK (stty -ixon) 82032 C-r OK 82033 C-s OK (stty -ixon) 82034 C-t OK 82035 C-u OK (stty kill undef) 82036 C-v OK (stty lnext undef) 82037 C-w OK (stty werase undef) 82038 C-x OK (二文字の組合せで bind すれば良い) 82039 * 直接 bind すると C-x に続けて何かの文字を打った瞬間に 82040 bash が segmentation fault する 82041 * C-x ? (? = \0 - \377) の組合せで全て登録しておけばよい。 82042 (恐らく C-x は C-x とそれに続く何らかの文字の組合せでしか使われないだろう。 82043 その場合にはこれで問題はない。) 82044 82045 C-y OK 82046 C-z OK (stty susp undef) 82047 82048 C-[ OK 82049 * 単独の C-[ は通常通りに bind するだけで OK。 82050 * C-[ C-[ の並びは何故か受信できないので、 82051 bind '"":"[27^[27^"' 等として、 82052 一旦別のシーケンスに翻訳してから受信する必要がある。 82053 82054 C-\ OK (stty quit undef) 82055 C-] OK 82056 C-_ OK 82057 C-^ OK (.bashrc で設定しているのを解除する必要はある) 82058 C-? OK (stty erase undef) 82059 82060 2013-06-04 82061 82062 * X5 C-x に bind -x すると死ぬ [2013-06-04 09:42:42] [#D0017] 82063 82064 * 先ず第一に、C-x に対して bind しても、 82065 単体の C-x に対して bind で指定したコマンドは呼ばれない。 82066 (bind -r で予め元々登録されていた関数を全て削除しても同様である。) 82067 82068 * 更に続けて何らかの入力をした場合、 82069 その sequence が bash bind で何も割り当てられていなかった場合、 82070 bash が segmentation fault で落ちる。 82071 82072 * C-x は単体では割り当てられず、 82073 必ず C-x hoge の形で入ってくるとするならば、 82074 C-x ではなく C-x ? に対して bind をすれば良い。 82075 82076 2013-06-03 82077 82078 * X4 history にアクセスする方法 [2013-06-03 08:19:09] [#D0016] 82079 82080 * history -s で値を設定する事が出来る。 82081 82082 但し、これは最新の履歴を置き換える形でしか追加する事が出来ない? 82083 と思ったが、最新の history -s コマンドを置き換えるだけであって、 82084 昔の履歴を削除する訳ではない様だ (多分) 82085 →実際に試してみた所期待通りに動いている様なので良しとする。 82086 82087 * また history -s は HISTIGNORE に該当する物に関しては削除するようだ。 82088 なので HISTIGNORE などについての特別な配慮は要らず、 82089 とにかくコマンドを history -s で追加すればよい。 82090 82091 * 次に isearch で history コマンドを検索する時にどの様にするのが良いのかという事。 82092 history | grep だと結構処理に時間が掛かりそう 82093 といって history の内容を何処かの配列に出してくるのも大変な気がする 82094 82095 * また history 中のコマンドに改行が含まれていた場合、 82096 検索などの結果が乱れてしまう事になる。 82097 82098 * 何故か、プロセス置換の中で history を呼び出すと HISTTIMEFORMAT= が有効にならない。 82099 cat < (HISTTIMEFORMAT=A history) # 効かない 82100 cat < (HISTTIMEFORMAT=A; history) # 効く 82101 82102 2013-06-02 82103 82104 [Done] 82105 82106 * source 直後の prompt は PS1 をそのままに。 [#D0015] 82107 未だ一度も呼ばれていないのでそもそも自前でプロンプトを表示していない。 82108 →分かりにくいのでやめた。 82109 ble.sh の最後に、自分自身で明示的にプロンプト描画関数を呼び出す事にした。 82110 82111 * quoted-insert C-@ の扱いについて [#D0014] 82112 →bash でも元から入力できない様なので気にしない 82113 self-insert で文字コード 0 を渡された場合には無視 82114 82115 * 取り敢えず実装する物: [#D0013] 82116 現在の編集行を表示する機能? 82117 →これは暫定的に唯 print するだけの物でよい。 82118 82119 * ble-decode-key, ble-bind: [#D0012] 82120 コマンドが設定されていない時の既定のコマンドを指定できる様にして、 82121 82122 其処に self-insert を割り当てていたが、この様にしておくと、 82123 self-insert で変な文字が入力されてしまう 82124 (一応 self-insert 中で flag は外す様にしているが)。 82125 更に、どんなに変な操作をしてもエラーメッセージが表示されない。 82126 82127 本来コマンドが設定されていないとしても flag の付いていない "文字" だけを 82128 self-insert で処理するべきである。従って、"文字" に対してだけ既定のコマンドを 82129 適用するように変更する。これは "文字" だけの既定動作なので変数名としても 82130 __default とするのは気分が悪い。其処で新しく __defchar__ という名前の keyname/keycode 82131 を定義し、そのキーに対してコマンドが定義されている場合に、"文字" をそのコマンドで処理するように変更した。 82132 82133 また、空文字列の bind 呼出で __default に値を設定できる機能は削除した。 82134 <del>空文字列を指定した場合は、既定の動作を指定する。</del> 82135 82136 * ble-decode-key: [#D0011] 82137 と思ったが、isearch-map 等を定義する時には、bind されていない key を指定した場合には、 82138 通常のモードに復帰してそのモードでの操作を実行したいから default の機能は使用したい。 82139 また、前の様な実装に戻す事も出来たが折角 __defchar__ を定義したので、 82140 それと同じ方式にした方が良いだろう。と言う事で __default__ というキーを定義する事にした。 82141 82142 2013-06-01 82143 82144 * 現在の実装状況 [#D0010] 82145 82146 ble-getopt 82147 取り敢えず枠組は完成している。 82148 後で拡張を行う余地はある。 82149 82150 ble-decode 82151 ble-decode-byte 82152 ble-decode-char 82153 ble-decode-key 82154 82155 ble-decode-bind 82156 ble-decode-kbd 82157 ble-decode-unkbd 82158 82159 ble-text 文字幅 82160 例えば → 8594 が曖昧幅の文字である。 82161 設定の名称をどの様にするか 82162 narrow/wide/emacs 82163 west/east/emacs 82164 82165 [Done] 82166 * ble-decode: ble-decode-* 関数の実装 [#D0009] 82167 * ble-getopt.sh: 短形式オプション引数 (':' 区切) で、'::' の様に、 [#D0008] 82168 区切が連続する場合に、正しく空引数として認識するように変更。 82169 * mwg.text.getCharFromCode, mwg.text.getCharCodeAt: [#D0007] 82170 それぞれ .ble-text.c2s, .ble-text.s2c に名称変更。 82171 * .ble-text.c2s: [#D0006] 82172 0x100 以上の文字コードを指定した場合に変な文字に変換されるバグを修正。 82173 * .ble-text.c2s: [#D0005] 82174 一度文字コードを取得した文字についてキャッシュする様に変更。 82175 82176 * X3 末端に改行を置かずに終了したコマンドの扱い [#D0004] 82177 82178 * その様なコマンドがあるとプロンプトの表示が乱れる原因である。 82179 * 右に或る回数だけ進んで其処で空白を出力してから行頭に復帰すれば良い? 82180 元々1桁目にいた場合にはぎりぎり改行をせずに済み、 82181 2桁目以降にいた場合には改行してしまうように調整をすれば良い。 82182 右に行くには ESC [ 桁数 C を出力すれば良い。 82183 82184 * 適当にやってみたが色々やってもうまく行かない。ちゃんと端末の動作を考えるべき。 82185 82186 * 先ずは xenl の場合。 82187 幾ら右に行っても一文字出力する分の余裕は必ず残る。 82188 従って右端に行ってから 2 文字は出力しないと行けない。 82189 82190 例えば (1) COLS-2 だけ右に進んでから (2) 2 文字出力して、(3) それから復帰する。 82191 82192 この様にすると 82193 何も出力していない場合 | 何か出力している場合 82194 (0) [_ ] | (0) [a_ ] 82195 [ ] | [ ] 82196 (1) [------------>_ ] | (1) [a------------>_] 82197 [ ] | [ ] 82198 (2) [ xx_ | (2) [a x] 82199 [ ] | [x_ ] 82200 (3) [_<-------------] | (3) [a x] 82201 [ ] | [_< ] 82202 82203 xenl でない端末の場合は COLS-3 に変えれば良いだけか? 82204 (1) COLS-3 だけ右に進んでから (2) 2 文字出力して、(3) それから復帰する。 82205 82206 何も出力していない場合 | 何か出力している場合 82207 (0) [_ ] | (0) [a_ ] 82208 [ ] | [ ] 82209 (1) [----------->_ ] | (1) [a----------->_ ] 82210 [ ] | [ ] 82211 (2) [ xx_] | (2) [a xx] 82212 [ ] | [_ ] 82213 (3) [_<------------ ] | (3) [a xx] 82214 [ ] | [_ ] 82215 82216 多分これで OK。 82217 82218 82219 * X2 C-v に bind できない? [#D0003] 82220 82221 * どうやら stty が C-v を食う設定になっていてこの設定が有効になっている間は、 82222 bind で C-v に割り当てをしたり C-v に対する割り当てを削除したりと言った操作ができない様だ。 82223 stty lnext undef で C-v に対する割り当てを削除した上で C-v に対して bind を行えばよい。 82224 (stty が食う所までは理解できるが、stty の設定によって bind すら出来なくなるのは何故か?) 82225 82226 * 但し、その後で stty lnext $'\26' などとして設定を元に戻すと、 82227 やはり C-v は stty に食われて bash にシグナルとして伝達する。 82228 問題が生じなければ stty lnext undef で放置という事で良い気がする。 82229 82230 然し C-z に bind する為に結局 stty susp undef をして、 82231 コマンド実行直前に復元して、コマンド実行後にまた undef するという事をしたくなりそうだから、 82232 その際には lnext も復元させる事にすればよい。 82233 82234 * 何故かスクリプトで stty lnext undef の直後に 82235 bind -x '"":ble-decode-byte 22' を実行すると、 82236 self-insert が割り当てられてしまう。 82237 bind -x の文と stty lnext の文を別の関数に配置したらこの様な事は起きなくなったが、謎。 82238 82239 * X1 [#D0002] 82240 82241 C-d を受け取る為には READLINE_LINE に何か設定する必要がある。 82242 するとオリジナルのプロンプトが表示されるがこれをどの様に殺すか? 82243 82244 [振舞] 82245 + READLINE_LINE が空の状態だと C-d を受け取れない。 82246 受け取る前にログアウトしてしまう。 82247 (man bash には EOF への翻訳は delete-char で行われる様に書かれているが、 82248 それとは別に C-d を bash が受け取った段階でチェックされ、 82249 条件に適合すればログアウトしてしまう) 82250 + READLINE_POINT が READLINE_LINE 末端を指している時は、 82251 プロンプトを表示し終わった直後に位置の移動は行わない。 82252 表示後のカーソル位置は、書き込んだ最後の場所になる。 82253 + READLINE_POINT が READLINE_LINE 先頭を指している場合は、 82254 bash が其処にカーソルがあるべきと考えている位置にカーソルが移動してしまう。 82255 (プロンプトの幅?) 82256 + 制御文字を EADLINE_LINE に代入しても、表示される時には ^A 等の表示に翻訳される。 82257 従って、通常の文字を代入しておくのが無難である。 82258 + 試しに READLINE_LINE=$'\0' として READLINE_LINE='1' として見たが、 82259 これはどうやら READLINE_LINE は空文字列であると解釈されて、 82260 C-d は即座にログアウトと解釈されてしまうので駄目である。 82261 82262 [目的] 82263 + C-d を読む為に READLINE_LINE の内容は何でも良いから 1 文字以上必要 82264 + プロンプトを表示し終わった時の位置を制御したい 82265 82266 [対策] 82267 + PS1 は空欄にする 82268 + カーソル位置 x が 2 桁目以降にある場合は、 82269 x-1 桁目に移動して READLINE_LINE には x-1 桁目の文字を入れる。 82270 READLINE_POINT には 1 (正確には x-1 桁目の文字のバイト数) を代入しておけば良い。 82271 また SGR で予め x-1 桁目の文字のスタイルを吐き出しておく。 82272 + カーソル位置 x が 1 桁目にある場合は、 82273 READLINE_LINE には 1 桁目の文字を入れておく。 82274 READLINE_POINT には 0 を入れておく。 82275 また SGR で予め 1 桁目の文字のスタイルを吐き出しておく。 82276 + 全角文字などに対する対策も必要 82277 82278 + これを正しく実装する為には、取り敢えず現在のカーソル位置を把握している必要がある。 82279 またカーソルの左側に位置している文字と、その幅を記録しておく必要もある。 82280 (幅を記録する必要はあるのか→ない気がする。) 82281 82282 *rule* 82283 82284 + lc はカーソルの左側に位置する文字の文字コードを表す。 82285 常に graphical な文字であり、bash によって直接表示される。 82286 x=0 の場合には lc に入っている文字コードの値は未定義であり、使用してはならない。 82287 (つまり x, lc を設定する側では x=0 の時は lc の中身は気にしなくて良い。)。 82288 82289 82290 関数 x y lc ; .ble-cursor-move.text text ; x y lc 82291 82292 .ble-cursor-move.text は指定した文字を現在位置 x y に書き込んだ時に、 82293 カーソルがどの様に移動するかを計算する。この時 lc の値も一緒に計算する。 82294 82295 ** 注意点 ** 82296 text に BS や VT が含まれる場合、lc を適切に計算する事が出来ない。 82297 BS, VT が含まれる場合、その直前の文字 (BS で消した文字の直前の文字、及び、VT で移動した先の左側にある文字) 82298 を今迄の出力から知る事は出来ない。この様な場合は暫定的に lc=32 (空白文字) を設定する。 82299 (この関数は prompt の幅を計算する為にある。PS1 に BS や VT などの制御文字を \[ \] で 82300 囲まずに設定する事は考えにくいので、現状ではこれについて対策する予定はない。) 82301 82302 82303 関数 .ble-cursor.construct-prompt ; ret=(x y lc ps1esc) 82304 82305 プロンプト文字列を実体化し ps1esc とする。 82306 更に、プロンプトを端末の左端から表示し始めた時の、最後のカーソルの位置 x y を計算する。 82307 また、lc にはカーソルの位置の左側にある文字の文字コードを返す。 82308 82309 ** 注意点 ** 82310 エスケープシーケンスなど実際に prompt の位置に文字として表示されない物は、必ず \[ ... \] で囲む事。 82311 \[ \] で囲んだ中でカーソルの移動などを行うとカーソル位置を正しく計算できない可能性がある。 82312 \[ \] で囲んだ中でカーソルを移動させたとしても、また元の位置に戻す事が望ましい。 82313 82314 82315 関数 _ble_cursor_x _ble_cursor_lc ; .ble-edit.adjust-cursor 82316 82317 ble-decode-byte の最後にこの関数を呼び出して、READLINE_LINE, READLINE_POINT 82318 の調整を実行する事にした。ちゃんと実装した物が完成したので、 82319 暫定的に書いた調整コードは削除 (以下) 82320 82321 # # 何か入力されていないと C-d で exit してしまう。 82322 # # これは delete-char で判定するのではなく、 82323 # # あらゆる関数を呼び出す前にチェックされる様だ。 82324 # # また、READLINE_POINT が文字列末端に設定されていれば OK 82325 82326 # [暫定v1] 82327 # READLINE_LINE="${_ble_edit_str:_ble_edit_str_ind:1}" 82328 # test -z "$READLINE_LINE" && READLINE_LINE=' ' 82329 # READLINE_POINT=1 82330 82331 # [暫定v2] 82332 # echo -n "[D" 82333 # if ((_ble_edit_ind>0)); then 82334 # READLINE_LINE="${_ble_edit_str:_ble_edit_ind-1:1}" 82335 # else 82336 # READLINE_LINE='_' 82337 # fi 82338 # READLINE_POINT=1 82339 82340 2013-05-29 highlight.sh 82341 82342 * bash で highlight? [#D0001] 82343 82344 一応、bind -x で通常文字に対して適当な関数を割り当てれば 82345 入力に対して hook をする事は可能なようである。 82346 但し、関数の呼出が終わった後に入力行が再度描画されるので、 82347 折角色を付けて出力したとしても上から塗り潰される事になる。 82348 82349 後 bind -x のもう一つの問題として、 82350 複数行に亙る行を編集している時に bind -x の関数を呼び出すと、 82351 処理が終わった後に再描画される訳だが、 82352 その時の再描画で表示している行の位置が下にずれる。 82353 これは bind -x の関数で何の操作もしていなくても同様である。 82354 これを正しく処理する為には、 82355 82356 (1) 現在の端末の幅を取得する 82357 (2) 文字列の表示上の長さを取得する 82358 (3) prompt の長さを取得する。 82359 82360 などの機能を正しく実装する必要がある。 82361 (1) は shopt -s chkwinsize でもすれば取り敢えずできる。 82362 (3) は (2) さえ正確に記述でき、現在のカーソル位置が分かれば現在の位置から逆算できる。 82363 逆に言えば、(2) と (3) さえ正確に計算できれば現在のカーソル位置も端末に問い合わせることなく分かるという事でもある。 82364 82365 + 現在のカーソルの位置を取得する関数は書けた。一応動いている。 82366 但し CSI 6 n (DSR CPR) に対応している端末でないと動かない。 82367 82368 * 現在位置を予測するという事 82369 82370 文字列の表示上の長さを計算するには、 82371 <del>文字列の文字コードを utf-8 と仮定すれば編集文字列を走査して、</del> 82372 文字コード列を生成し、更に其処から文字幅に変換して、 82373 加算するという事をすれば良い。 82374 82375 と思ったが…実際には改行やら TAB やらがあるので、 82376 現在の正確な位置が分からないと文字列の表示上の長さなどの情報を取得する事は出来ない。 82377 やはり何とかして端末が表示される長さを算出する必要があるだろうか。 82378 端末が表示される長さを取得する方法: 82379 82380 A READLINE_LINE が空だった時の位置を記録しておく? 82381 + 漢字や平仮名で始まるコマンドを入力した場合に対処できない。しかしそんなコマンドは存在するだろうか。 82382 + 前のコマンドの出力が改行で終わらなかった場合にどうなるか? 82383 →1 文字でも入力すれば再描画されてプロンプトは行頭に出て来る。 82384 0 文字の時に取得した位置はその時にしか信用できないので、1 文字の時に取得した文字の方が良い? 82385 + <strong>×</strong> プロンプトは複数行に跨らないという仮定をしないとできない。 82386 然し、人によってはプロンプトを複数行に分けるという人もいる (cygwin の人みたいに)。 82387 82388 B 自分で PS1 を解析して長さを計算する? 82389 + <strong>△</strong> 実装が大変。エスケープシーケンスの類にも対応しなければならない。 82390 + (\a \n \r \ooo はCと同じ意味, \x \f \b はそのまま出力, \v \t \u は別の意味, \e は ESC)