sistema_progs

Programas para customizar o meu entorno de traballo nos meus equipos persoais
Log | Files | Refs

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 や  等の特殊文字が含まれる場合に、
  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 &amp; 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 実体参照 (&nbsp;&lt;&gt;&quot;) を戻して適当に列を切り出す。
  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/&lt;n&gt; 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 "[ble: exit $_ble_edit_accept_line_lastexit]" 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 している '' と '', '[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 ""
  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)