sistema_progs

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

init-bind.sh (11443B)


      1 #!/bin/bash
      2 
      3 # 現在の bash の version に従って以下の二つのファイルを生成します:
      4 #
      5 #   $_ble_base_cache/decode.bind.$_ble_bash.$bleopt_input_encoding.bind
      6 #   $_ble_base_cache/decode.bind.$_ble_bash.$bleopt_input_encoding.unbind
      7 #
      8 # Note: #D1300 bind -s で束縛するマクロの非終端文字は
      9 #   decode.sh (ble/decode/nonblocking-read) でチェックする必要がある。
     10 #   現在の実装では 0xC0 と 0xDF をチェックしている。
     11 #   (( esc1B != 3 && esc1B1B )) の時には 0x1B も追加でチェックする必要がある。
     12 #   マクロを追加する時にはそれに応じてチェックを追加する必要がある。
     13 
     14 function ble/init:bind/append {
     15   local xarg="\"$1\":ble-decode/.hook $2; builtin eval -- \"\$_ble_decode_bind_hook\""
     16   local rarg=$1 condition=$3${3:+' && '}
     17   ble/util/print "${condition}builtin bind -x '${xarg//$q/$Q}'" >> "$fbind1"
     18   ble/util/print "${condition}builtin bind -r '${rarg//$q/$Q}'" >> "$fbind2"
     19 }
     20 function ble/init:bind/append-macro {
     21   local kseq1=$1 kseq2=$2 condition=$3${3:+' && '}
     22   local sarg="\"$kseq1\":\"$kseq2\"" rarg=$kseq1
     23   ble/util/print "${condition}builtin bind    '${sarg//$q/$Q}'" >> "$fbind1"
     24   ble/util/print "${condition}builtin bind -r '${rarg//$q/$Q}'" >> "$fbind2"
     25 }
     26 function ble/init:bind/bind-s {
     27   local sarg=$1
     28   ble/util/print "builtin bind '${sarg//$q/$Q}'" >> "$fbind1"
     29 }
     30 
     31 function ble/init:bind/generate-binder {
     32   local fbind1=$_ble_base_cache/decode.bind.$_ble_bash.$bleopt_input_encoding.bind
     33   local fbind2=$_ble_base_cache/decode.bind.$_ble_bash.$bleopt_input_encoding.unbind
     34 
     35   ble/edit/info/show text "ble.sh: updating binders..."
     36 
     37   : >| "$fbind1"
     38   : >| "$fbind2"
     39 
     40   local q=\' Q="'\\''"
     41   local altdqs00='\xC0\x80'
     42   local altdqs24='\xC0\x98'
     43   local altdqs27='\xC0\x9B'
     44 
     45   # ※bash-4.3 以降は bind -x の振る舞いがこれまでと色々と違う様だ
     46   #   何より 3 byte 以上の物にも bind できる様になった点が大きい (が ble.sh では使っていない)
     47 
     48   # * C-@ (0) は bash-4.3 では何故か bind -x すると
     49   #   bash: bash_execute_unix_command: コマンドのキーマップがありません
     50   #   bash_execute_unix_command: cannot find keymap for command
     51   #   になってしまう。"C-@ *" に全て割り当てても駄目である。
     52   #   bind '"\C-@":""' は使える様なので、UTF-8 の別表現に翻訳してしまう。
     53   local esc00=$((40300<=_ble_bash&&_ble_bash<50000))
     54 
     55   # * C-x (24) に単体で直接 bind -x するとクラッシュする問題。
     56   #   #D0017 #D0018 #D0057 #D0122 #D0148 #D0391 #D0583 #D1478
     57   #
     58   #   [症状]
     59   #   bash-4.3 を除く bash-3.0 ~ bash-4.4 の全てで、set -o emacs で問題が生じる。
     60   #   例えば C-x C-b C-b などと入力すると、bash-3.2 では無限ループになって固まる。
     61   #   bash-4.4 では "コマンドのキーマップがありません" というエラーメッセージになる。
     62   #   それ以外の bash では、何秒かしてクラッシュする。
     63   #   bash-5.0 では修正されたので対策は不要になった (#D1163)
     64   #
     65   #   [対処法1] "C-x ?" 全束縛 ... bash-3.0..4.2 で使用
     66   #
     67   #   C-x には直接 bind せずに 2 文字の組み合わせで bind -x '"\C-x?": ...' とする。
     68   #
     69   #   * bash-3.0..4.2: これをすると vi に切り替えた時に後遺症が残る。
     70   #     cmd_xmap[24] に submap が追加される事により、\C-x に対して \C-x\C-x の
     71   #     コマンドが実行される様になる。その対策として直接 "\C-x?" に対して bind
     72   #     -x するのではなくて、"\C-x?" をマクロで UTF-8 代替表現に置き換えて受信
     73   #     する。 (#D1478)
     74   #
     75   #   [対処法2] 却下 #D0583
     76   #   bind -s '"\C-x": "\xC0\x98"' のようにする。
     77   #   クラッシュはしなくなるが、謎の遅延が残る。
     78   #   遅延をなくすには 対処法1 を実行するしかない。
     79   #
     80   #   [対処法3] 単一 C-x (with \C-x\C-x shadow) ... bash-4.4 で使用 (#D1478)
     81   #
     82   #   一旦 bind -x '"\C-x\C-x":hook 24' としてから bind -r '\C-x\C-x' で削除す
     83   #   る。この後で bind -x '"\C-x":...' で timeout すると "\C-x\C-x" のコマンド
     84   #   が実行される。
     85   #
     86   #   * bash-3.0..4.2 で \C-x\C-x に一度でも bind すると C-x で timeout しなく
     87   #     なるので、この対策を実行するのは emacs keymap のみにする。
     88   #
     89   local bind18XX=0
     90   if ((40400<=_ble_bash&&_ble_bash<50000)); then
     91     # Insert a dummy entry in "cmd_xmap"
     92     ble/util/print "[[ -o emacs ]] && builtin bind 'set keyseq-timeout 1'" >> "$fbind1"
     93     fbind2=$fbind1 ble/init:bind/append '\C-x\C-x' 24 '[[ -o emacs ]]'
     94   elif ((_ble_bash<40300)); then
     95     bind18XX=1
     96   fi
     97 
     98   # ESC について
     99   #
    100   # * esc1B=1: bash-3 では "ESC *" の組合せも全部登録しておかないと駄目??
    101   #   (もしかすると bind -r 等に失敗していただけかも知れないが)
    102   #
    103   #   追記: bash-4.0 bash-4.3 でも必要
    104   #   追記: bash-4.1 でも bind -x '"\ez":fg' 等を一回もしていない場合は必要
    105   #   追記: この方法でも ESC を 2 つ以上連続で入力する時に
    106   #     bash_execute_unix_command のエラーが発生する。
    107   #
    108   # * esc1B=2: 2017-10-22 実は bind '"\e": "\xC0\x9B"' とすれば全バージョンで OK の様だ。
    109   #
    110   #   しかし、これだと単体の ESC と続きのある ESC の区別ができない。
    111   #   続きがあるとき Readline が標準入力からひとまとまりで読み取ってから hook を呼び出す。
    112   #   従って、標準入力に文字が残っているかどうか見ても判定できないし、
    113   #   標準入力から次の文字をタイムアウト付きで読み取るとシーケンスの順序が狂う。
    114   #
    115   # * esc1B=3: 2017-10-22 代替案として
    116   #
    117   #     bind '"\e":"\e[27;5;91~"'
    118   #     bind '"\e?":"\xC0\x9B?"'
    119   #     bind '"\e\e":"\xC0\x9B\e[27;5;91~"'
    120   #
    121   #   などの様に bind -s で1文字のものと2文字のものを両方登録して、
    122   #   Readline に ESC に続きがあるかどうかを判定させて単独 ESC を区別するという手がある。
    123   #
    124   local esc1B=3
    125 
    126   # esc1B5B (esc1B == 1 の時に有効)
    127   #
    128   # * bash-3.1
    129   #   ESC [ を bind -x で捕まえようとしてもエラーになるので、
    130   #   一旦 "ESC [" の ESC を UTF-8 2-byte code にしてから受信し直す。
    131   #   bash-3.1 で確認。bash-4.1 ではOK。他は未確認。
    132   # * bash-4.3, bash-4.1
    133   #   ESC *, ESC [ *, etc を全部割り当てないと以下のエラーになる。
    134   #   bash_execute_unix_command: cannot find keymap for command
    135   #   これを避ける為に二つの方針がある
    136   #   1 全てを登録する方針 (bindAllSeq)
    137   #   2 ESC [ を別のシーケンスに割り当てる (esc1B5B)
    138   #   初め 1 の方法を用いていたが 2 でも動く事が分かったので 2 を使う。
    139   #
    140   local esc1B5B=1 bindAllSeq=0
    141 
    142   # esc1B1B (esc1B != 3 の時に有効)
    143   #
    144   # * bash-4.1 では ESC ESC に bind すると
    145   #   bash_execute_unix_command: cannot find keymap for command
    146   #   が出るので ESC [ ^ に適当に redirect して ESC [ ^ を
    147   #   ESC ESC として解釈する様にする。
    148   #
    149   local esc1B1B=$((40100<=_ble_bash&&_ble_bash<40300))
    150 
    151   # Note: 'set convert-meta on' 対策
    152   #
    153   #   bind 'set convert-meta on' の時、bind -p '"\200": ...' などが
    154   #   "\C-@" などの cmd_xmap を上書きしてしまう。
    155   #   呼び出し元で一時的に 'set convert-meta off' になる様にしているが、
    156   #   保険として 128-255 を先に bind してから 0-127 を bind する。
    157   local i
    158   for i in {128..255} {0..127}; do
    159     local ret; ble/decode/c2dqs "$i"
    160 
    161     # *
    162     if ((i==0)); then
    163       # C-@
    164       if ((esc00)); then
    165         # ENCODING: UTF-8 2-byte code of 0 (UTF-8依存)
    166         ble/init:bind/append-macro '\C-@' "$altdqs00"
    167       else
    168         ble/init:bind/append "$ret" "$i"
    169       fi
    170     elif ((i==24)); then
    171       # C-x
    172       if ((bind18XX)); then
    173         ble/init:bind/append "$ret" "$i" '[[ ! -o emacs ]]'
    174       else
    175         ble/init:bind/append "$ret" "$i"
    176       fi
    177     elif ((i==27)); then
    178       # C-[
    179       if ((esc1B==0)); then
    180         ble/init:bind/append "$ret" "$i"
    181       elif ((esc1B==2)); then
    182         # ENCODING: UTF-8
    183         ble/init:bind/append-macro '\e' "$altdqs27"
    184       elif ((esc1B==3)); then
    185         # ENCODING: UTF-8 (_ble_decode_IsolatedESC U+07FF)
    186         ble/init:bind/append-macro '\e' '\xDF\xBF' # C-[
    187       fi
    188     else
    189       # Note: Bash-5.0 では \C-\\ で bind すると変な事になる #D1162 #D1078
    190       ((i==28&&_ble_bash>=50000)) && ret='\x1C'
    191       ble/init:bind/append "$ret" "$i"
    192     fi
    193 
    194     # # C-@ * for bash-4.3 (2015-02-11) 無駄?
    195     # ble/init:bind/append "\\C-@$ret" "0 $i"
    196 
    197     # C-x *
    198     if ((bind18XX)); then
    199       # emacs mode では "C-x ?" の組み合わせで登録する。
    200       # Note: 普通に bind -x すると cmd_xmap の \C-x が曖昧になって vi 側の単一
    201       # "C-x" が動かなくなるので、ここでは UTF-8 2B 表示を通して受信する。
    202       if ((i==0)); then
    203         ble/init:bind/append-macro "\C-x$ret" "$altdqs24$altdqs00" '[[ -o emacs ]]'
    204       elif ((i==24)); then
    205         ble/init:bind/append-macro "\C-x$ret" "$altdqs24$altdqs24" '[[ -o emacs ]]'
    206       else
    207         ble/init:bind/append-macro "\C-x$ret" "$altdqs24$ret"      '[[ -o emacs ]]'
    208       fi
    209     fi
    210 
    211     # ESC *
    212     if ((esc1B==3)); then
    213       if ((i==0)); then
    214         ble/init:bind/append-macro '\e'"$ret" "$altdqs27$altdqs00"
    215       elif ((bind18XX&&i==24)); then
    216         ble/init:bind/append-macro '\e'"$ret" "$altdqs27$altdqs24"
    217       else
    218         ble/init:bind/append-macro '\e'"$ret" "$altdqs27$ret"
    219       fi
    220     else
    221       if ((esc1B==1)); then
    222         # ESC [
    223         if ((i==91&&esc1B5B)); then
    224           # * obsoleted workaround
    225           #   ESC [ を CSI (encoded in utf-8) に変換して受信する。
    226           #   受信した後で CSI を ESC [ に戻す。
    227           #   CSI = \u009B = utf8{\xC2\x9B} = utf8{\302\233}
    228           # printf 'bind %q' '"\e[":"\302\233"'               >> "$fbind1"
    229           # ble/util/print "ble-bind -f 'CSI' '.CHARS 27 91'" >> "$fbind1"
    230 
    231           # ENCODING: \xC0\x9B is 2-byte code of ESC (UTF-8依存)
    232           ble/init:bind/append-macro '\e[' "$altdqs27["
    233         else
    234           ble/init:bind/append "\\e$ret" "27 $i"
    235         fi
    236       fi
    237 
    238       # ESC ESC
    239       if ((i==27&&esc1B1B)); then
    240         # ESC ESC for bash-4.1
    241         ble/init:bind/append-macro '\e\e' '\e[^'
    242         ble/util/print "ble-bind -k 'ESC [ ^' __esc__"      >> "$fbind1"
    243         ble/util/print "ble-bind -f __esc__ '.CHARS 27 27'" >> "$fbind1"
    244       fi
    245     fi
    246   done
    247 
    248   if ((bindAllSeq)); then
    249     # 決まったパターンのキーシーケンスは全て登録
    250     #   bash-4.3 で keymap が見付かりませんのエラーが出るので。
    251     # ※3文字以上の bind -x ができるのは bash-4.3 以降
    252     #   (bash-4.3-alpha で bugfix が入っている)
    253     ble/util/print 'source "$_ble_decode_bind_fbinder.bind"' >> "$fbind1"
    254     ble/util/print 'source "$_ble_decode_bind_fbinder.unbind"' >> "$fbind2"
    255   fi
    256 
    257   ble/function#try ble/encoding:"$bleopt_input_encoding"/generate-binder
    258 
    259   ble/edit/info/immediate-show text "ble.sh: updating binders... done"
    260 }
    261 
    262 ble/init:bind/generate-binder