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