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