terminal_rb 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/terminal/ansi.rb +33 -12
- data/lib/terminal/input/csiu_keys.rb +75 -79
- data/lib/terminal/input/dumb_keys.rb +3 -3
- data/lib/terminal/input/legacy_keys.rb +85 -63
- data/lib/terminal/input.rb +64 -49
- data/lib/terminal/text/char_width.rb +11 -13
- data/lib/terminal/text.rb +9 -8
- data/lib/terminal/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82d95e0e2e8423c8bbb464019e8282bb589c5bc8fb02298ec529ff58e9ee67bb
|
4
|
+
data.tar.gz: bbb98fffca9d97e21a5440644a1ddc0b91dc60e945af287da60dbab07b6ae63b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44d16eba18775b6bbd208d19288bd44265a30301607136cafb959e985e59248820829383dd714c62f235880d30c46f4ce0a86a46d46dd8b6f05e042f73068c20
|
7
|
+
data.tar.gz: 80b0d17ece194d7fa8b36080314c21683bb1d7739344529bbf47c7da8afbc27c5c910a860393bf348edaef2a27e590d2b2505ab7d7d8934ae349eed152653144
|
data/lib/terminal/ansi.rb
CHANGED
@@ -462,14 +462,7 @@ module Terminal
|
|
462
462
|
}K"
|
463
463
|
end
|
464
464
|
|
465
|
-
# Set
|
466
|
-
# This is not widely supported.
|
467
|
-
#
|
468
|
-
# @param [#to_s] title text
|
469
|
-
# @return (see cursor_up)
|
470
|
-
def title(title) = "\e]2;#{title}\a"
|
471
|
-
|
472
|
-
# Set tab title.
|
465
|
+
# Set (tab) title.
|
473
466
|
# This is not widely supported; works for
|
474
467
|
# Hyper,
|
475
468
|
# iTerm2,
|
@@ -478,9 +471,9 @@ module Terminal
|
|
478
471
|
# Tabby,
|
479
472
|
# WezTerm.
|
480
473
|
#
|
481
|
-
# @param
|
474
|
+
# @param [#to_s] title text
|
482
475
|
# @return (see cursor_up)
|
483
|
-
def
|
476
|
+
def title(title) = "\e]0;#{title}\a"
|
484
477
|
|
485
478
|
# Create a hyperlink.
|
486
479
|
# This is not widely supported; works for
|
@@ -677,15 +670,26 @@ module Terminal
|
|
677
670
|
LINE_ERASE_PREV = "#{cursor_prev_line(nil)}#{LINE_ERASE}".freeze
|
678
671
|
|
679
672
|
# @comment seems not widely supported:
|
680
|
-
# doubled
|
681
|
-
# doubled
|
673
|
+
# doubled: def cursor_column(column = 1) = "\e[#{column}`"
|
674
|
+
# doubled: def cursor_row(row = 1) = "\e[#{row}d"
|
675
|
+
# doubled: def cursor_pos(row, col) = "\e[#{row};#{col}f"
|
676
|
+
#
|
682
677
|
# def cursor_column_rel(columns = 1) = "\e[#{columns}a"
|
683
678
|
# def cursor_row_rel(rows = 1) = "\e[#{rows}e"
|
684
679
|
# def cursor_tab(count = 1) = "\e[#{column}I"
|
685
680
|
# def cursor_reverse_tab(count = 1) = "\e[#{count}Z"
|
681
|
+
#
|
682
|
+
# def lines_insert(count = 1) = "\e[#{count}L"
|
683
|
+
# def lines_delete(count = 1) = "\e[#{count}M"
|
684
|
+
#
|
685
|
+
# def chars_insert_spaces(count = 1) = "\e[#{count}@"
|
686
686
|
# def chars_delete(count = 1) = "\e[#{count}P"
|
687
687
|
# def chars_erase(count = 1) = "\e[#{count}X"
|
688
|
+
#
|
689
|
+
# def chars_repeat_last(count = 1) = "\e[#{count}b"
|
690
|
+
#
|
688
691
|
# def notify(title) = "\e]9;#{title}\a"
|
692
|
+
#
|
689
693
|
# def set_scroll_region(top = nil, bottom = nil) = "\e[#{top};#{bottom}r"
|
690
694
|
|
691
695
|
# @comment TODO:
|
@@ -695,5 +699,22 @@ module Terminal
|
|
695
699
|
# https://sw.kovidgoyal.net/kitty/color-stack
|
696
700
|
# https://sw.kovidgoyal.net/kitty/deccara
|
697
701
|
# https://sw.kovidgoyal.net/kitty/clipboard
|
702
|
+
|
703
|
+
# @comment other:
|
704
|
+
# "\eE" same as "\r\n"
|
705
|
+
# "\eD" same as "\n" but preserves X coord
|
706
|
+
# "\eM" reverse "\n"
|
707
|
+
# "\e[6n" report Cursor Position as "ESC \[ row ; col R"
|
708
|
+
# "\e[21t report window’s title as ESC ] l title ESC \"
|
709
|
+
# "\e[?Xl" set mouse mode "X":
|
710
|
+
# 9: X10_MOUSE
|
711
|
+
# 1000: VT200_MOUSE
|
712
|
+
# 1002: BTN_EVENT_MOUSE
|
713
|
+
# 1003: ANY_EVENT_MOUSE
|
714
|
+
# 1004: FOCUS_EVENT_MOUSE
|
715
|
+
# 1005: Xterm’s UTF8
|
716
|
+
# 1006: Xterm’s CSI-style
|
717
|
+
# 1015: Urxvt’s CSI-style
|
718
|
+
# "\e[?Xl" reset mouse mode "X"
|
698
719
|
end
|
699
720
|
end
|
@@ -3,83 +3,50 @@
|
|
3
3
|
module Terminal
|
4
4
|
module CSIuKeys
|
5
5
|
class << self
|
6
|
-
def
|
7
|
-
|
8
|
-
return if key[0] != "\e"
|
9
|
-
return C0_LEGACY[key[1].ord] if key.size == 2 # ESC ?
|
10
|
-
return csi(key) if key[1] == '['
|
11
|
-
SS3[key[2].ord] if key[1] == 'O' && key.size == 3 # ESC O ?
|
6
|
+
def key_name(key)
|
7
|
+
@key_name[key.ord] if key.size == 1
|
12
8
|
end
|
13
9
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
return ord == 0x5a ? 'Shift+Tab' : SS3[ord]
|
23
|
-
end
|
24
|
-
return if key.size < 5
|
25
|
-
return unless key.start_with?("\e[1;")
|
26
|
-
# ESC [ 1 ; <modifier> ?
|
27
|
-
name = SS3[type.ord] or return
|
28
|
-
mod = key[4..-2]
|
29
|
-
mod.empty? ? name : modifier(name, mod.to_i - 1)
|
30
|
-
end
|
31
|
-
|
32
|
-
def unicode(key)
|
33
|
-
with_modifier(key) do |ord|
|
34
|
-
ORD[ord] || UNICODE_ORD[ord] || ord.chr(Encoding::UTF_8)
|
10
|
+
def translate(esc)
|
11
|
+
return if esc[0] != '[' # ESC [ ...
|
12
|
+
return @csi1[esc[1].ord] if esc.size == 2 # ESC [ ?
|
13
|
+
return csi1(esc) if esc[1] == '1' && esc[2] == ';'
|
14
|
+
if esc[-1] == '~'
|
15
|
+
# ESC [ <code> ~
|
16
|
+
# ESC [ <code> ; <modifier> ~
|
17
|
+
return with_modifier(esc) { @csi[_1] }
|
35
18
|
end
|
19
|
+
return if esc[-1] != 'u'
|
20
|
+
# ESC [ <code> u
|
21
|
+
# ESC [ <code> ; <modifier> u
|
22
|
+
with_modifier(esc) { @csiu[_1] || _1.chr(Encoding::UTF_8) }
|
36
23
|
end
|
37
24
|
|
38
|
-
|
39
|
-
with_modifier(key) do |ord|
|
40
|
-
return 'F3' if ord == 13
|
41
|
-
ord == 57_427 ? 'KpBegin' : ORD[ord]
|
42
|
-
end
|
43
|
-
end
|
25
|
+
private
|
44
26
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
27
|
+
def csi1(esc)
|
28
|
+
# ESC [ 1 ; <modifier> [~ABCDEFHPQRS]
|
29
|
+
return if esc.size < 5
|
30
|
+
key = @csi1[esc[-1].ord] or return
|
31
|
+
return key if (mod = esc[3..-2].join.to_i - 1) < 1 # no mod
|
32
|
+
(@mods.filter_map { |b, n| n if mod.allbits?(b) } << key).join('+')
|
49
33
|
end
|
50
34
|
|
51
|
-
def
|
52
|
-
(
|
35
|
+
def with_modifier(esc)
|
36
|
+
return yield(esc[1..-2].join.to_i) if (idx = esc.index(';')).nil? # no mod
|
37
|
+
key = yield(esc[1..(idx - 1)].join.to_i) or return
|
38
|
+
return key if (mod = esc[(idx + 1)..-2].join.to_i - 1) < 1 # no mod
|
39
|
+
(@mods.filter_map { |b, n| n if mod.allbits?(b) } << key).join('+')
|
53
40
|
end
|
54
41
|
end
|
55
42
|
|
56
|
-
|
43
|
+
@csiu = {
|
57
44
|
0x02 => 'Ins',
|
58
|
-
0x03 => 'Del',
|
59
|
-
0x04 => 'Del',
|
60
|
-
0x05 => 'PageUp',
|
61
|
-
0x06 => 'PageDown',
|
62
|
-
0x07 => 'Home',
|
63
|
-
0x08 => 'End',
|
64
45
|
0x09 => 'Tab',
|
65
|
-
0x0b => 'F1',
|
66
|
-
0x0c => 'F2',
|
67
46
|
0x0d => 'Enter',
|
68
|
-
0x0e => 'F4',
|
69
|
-
0x0f => 'F5',
|
70
|
-
0x11 => 'F6',
|
71
|
-
0x12 => 'F7',
|
72
|
-
0x13 => 'F8',
|
73
|
-
0x14 => 'F9',
|
74
|
-
0x15 => 'F10',
|
75
|
-
0x17 => 'F11',
|
76
|
-
0x18 => 'F12',
|
77
47
|
0x1b => 'Esc',
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
# ESC [ ? u
|
82
|
-
UNICODE_ORD = {
|
48
|
+
0x20 => 'Space',
|
49
|
+
0x7f => 'Back',
|
83
50
|
57_376 => 'F13',
|
84
51
|
57_377 => 'F14',
|
85
52
|
57_378 => 'F15',
|
@@ -118,7 +85,7 @@ module Terminal
|
|
118
85
|
57_411 => 'KpMultiply',
|
119
86
|
57_412 => 'KpSubtract',
|
120
87
|
57_413 => 'KpAdd',
|
121
|
-
57_414 => 'KpEnter'
|
88
|
+
57_414 => 'Return', # 'KpEnter'
|
122
89
|
57_415 => 'KpEqual',
|
123
90
|
57_416 => 'KpSeparator',
|
124
91
|
57_417 => 'KpLeft',
|
@@ -160,21 +127,7 @@ module Terminal
|
|
160
127
|
57_454 => 'IsoLevel5Shift'
|
161
128
|
}.compare_by_identity.freeze
|
162
129
|
|
163
|
-
|
164
|
-
C0_LEGACY = {
|
165
|
-
0x00 => 'Ctrl+Space',
|
166
|
-
0x08 => 'Ctrl+Back',
|
167
|
-
0x09 => 'Alt+Tab',
|
168
|
-
0x0d => 'Alt+Enter',
|
169
|
-
0x1b => 'Alt+Esc',
|
170
|
-
0x20 => 'Alt+Space',
|
171
|
-
0x64 => 'Alt+Del',
|
172
|
-
0x7f => 'Alt+Back'
|
173
|
-
}.compare_by_identity.freeze
|
174
|
-
|
175
|
-
# ESC [ ?
|
176
|
-
# ESC [ O ?
|
177
|
-
SS3 = {
|
130
|
+
@csi1 = {
|
178
131
|
0x41 => 'Up', # A
|
179
132
|
0x42 => 'Down', # B
|
180
133
|
0x43 => 'Right', # C
|
@@ -187,7 +140,50 @@ module Terminal
|
|
187
140
|
0x53 => 'F4' # S
|
188
141
|
}.compare_by_identity.freeze
|
189
142
|
|
190
|
-
|
143
|
+
@csi = {
|
144
|
+
0x02 => 'Ins',
|
145
|
+
0x03 => 'Del',
|
146
|
+
0x05 => 'PageUp',
|
147
|
+
0x06 => 'PageDown',
|
148
|
+
0x07 => 'Home',
|
149
|
+
0x08 => 'End',
|
150
|
+
0x09 => 'Tab',
|
151
|
+
0x0b => 'F1',
|
152
|
+
0x0c => 'F2',
|
153
|
+
0x0d => 'F3',
|
154
|
+
0x0e => 'F4',
|
155
|
+
0x0f => 'F5',
|
156
|
+
0x11 => 'F6',
|
157
|
+
0x12 => 'F7',
|
158
|
+
0x13 => 'F8',
|
159
|
+
0x14 => 'F9',
|
160
|
+
0x15 => 'F10',
|
161
|
+
0x17 => 'F11',
|
162
|
+
0x18 => 'F12',
|
163
|
+
0x19 => 'F13',
|
164
|
+
0x1a => 'F14',
|
165
|
+
0x1b => 'F15',
|
166
|
+
0x1c => 'F16',
|
167
|
+
0x1d => 'F17',
|
168
|
+
0x1e => 'F18',
|
169
|
+
0x1f => 'F19',
|
170
|
+
0x20 => 'F20',
|
171
|
+
0x21 => 'F21',
|
172
|
+
0x22 => 'F22',
|
173
|
+
0x23 => 'F23',
|
174
|
+
0x24 => 'F24'
|
175
|
+
}.compare_by_identity.freeze
|
176
|
+
|
177
|
+
@key_name = {
|
178
|
+
0x04 => 'Del',
|
179
|
+
0x09 => 'Tab',
|
180
|
+
0x0d => 'Enter',
|
181
|
+
0x1b => 'Esc',
|
182
|
+
0x20 => 'Space',
|
183
|
+
0x7f => 'Back'
|
184
|
+
}.compare_by_identity.freeze
|
185
|
+
|
186
|
+
@mods = {
|
191
187
|
1 => 'Shift',
|
192
188
|
2 => 'Alt',
|
193
189
|
4 => 'Ctrl',
|
@@ -3,55 +3,102 @@
|
|
3
3
|
module Terminal
|
4
4
|
module LegacyKeys
|
5
5
|
class << self
|
6
|
-
def
|
7
|
-
|
8
|
-
return if key[0] != "\e"
|
9
|
-
return csi(key) if key[1] == '['
|
10
|
-
SS3[key[2].ord] if key[1] == 'O' && key.size == 3 # ESC O ?
|
6
|
+
def key_name(key)
|
7
|
+
@key_name[key.ord] if key.size == 1
|
11
8
|
end
|
12
9
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
if key.size == 3 # ESC [ ?
|
18
|
-
ord = key[2].ord
|
19
|
-
return ord == 0x5a ? 'Shift+Tab' : SS3[ord]
|
10
|
+
def translate(esc)
|
11
|
+
return "Alt+#{@esc1[esc[0].ord] || esc[0]}" if esc.size == 1 # ESC ?
|
12
|
+
if esc.size == 2 && (esc[0] == 'O' || esc[0] == '[')
|
13
|
+
return @ss3[esc[1].ord] # ESC O ? || ESC [ ?
|
20
14
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
15
|
+
if esc[0] == "\e" # ESC ESC ...
|
16
|
+
return "Alt+#{@esc1[esc[1].ord] || esc[1]}" if esc.size == 1
|
17
|
+
esc.shift
|
18
|
+
return (name = translate(esc)) ? "Alt+#{name}" : nil
|
19
|
+
end
|
20
|
+
return if esc[0] != '[' # ESC [ ...
|
21
|
+
return csi1(esc) if esc[1] == '1' && esc[2] == ';'
|
22
|
+
csi(esc) if esc[-1] == '~'
|
28
23
|
end
|
29
24
|
|
30
|
-
|
31
|
-
with_modifier(key) { LEGACY[_1] }
|
32
|
-
end
|
25
|
+
private
|
33
26
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
27
|
+
def csi(esc)
|
28
|
+
# ESC [ <code> ~
|
29
|
+
# ESC [ <code> ; <modifier> ~
|
30
|
+
return @csi[esc[1..-2].join.to_i] if (idx = esc.index(';')).nil? # no mod
|
31
|
+
key = @csi[esc[1..(idx - 1)].join.to_i] or return
|
32
|
+
return key if (mod = esc[(idx + 1)..-2].join.to_i - 1) < 1 # no mod
|
33
|
+
(@mods.filter_map { |b, n| n if mod.allbits?(b) } << key).join('+')
|
38
34
|
end
|
39
35
|
|
40
|
-
def
|
41
|
-
|
36
|
+
def csi1(esc)
|
37
|
+
# ESC [ 1 ; <modifier> [~ABCDEFHPQRS]
|
38
|
+
return if esc.size < 5
|
39
|
+
key = @ss3[esc[-1].ord] or return
|
40
|
+
return key if (mod = esc[3..-2].join.to_i - 1) < 1 # no mod
|
41
|
+
(@mods.filter_map { |b, n| n if mod.allbits?(b) } << key).join('+')
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
@csi = {
|
46
|
+
0x02 => 'Ins',
|
47
|
+
0x03 => 'Del',
|
48
|
+
0x05 => 'PageUp',
|
49
|
+
0x06 => 'PageDown',
|
50
|
+
0x07 => 'Home',
|
51
|
+
0x08 => 'End',
|
52
|
+
0x09 => 'Tab',
|
53
|
+
0x0b => 'F1',
|
54
|
+
0x0c => 'F2',
|
55
|
+
0x0d => 'F3',
|
56
|
+
0x0e => 'F4',
|
57
|
+
0x0f => 'F5',
|
58
|
+
0x11 => 'F6',
|
59
|
+
0x12 => 'F7',
|
60
|
+
0x13 => 'F8',
|
61
|
+
0x14 => 'F9',
|
62
|
+
0x15 => 'F10',
|
63
|
+
0x17 => 'F11',
|
64
|
+
0x18 => 'F12',
|
65
|
+
0x1b => 'Enter'
|
66
|
+
}.compare_by_identity.freeze
|
67
|
+
|
68
|
+
@ss3 = {
|
69
|
+
0x41 => 'Up', # A
|
70
|
+
0x42 => 'Down', # B
|
71
|
+
0x43 => 'Right', # C
|
72
|
+
0x44 => 'Left', # D
|
73
|
+
0x46 => 'End', # F
|
74
|
+
0x48 => 'Home', # H
|
75
|
+
0x50 => 'F1', # P
|
76
|
+
0x51 => 'F2', # Q
|
77
|
+
0x52 => 'F3', # R
|
78
|
+
0x53 => 'F4', # S
|
79
|
+
0x5a => 'Shift+Tab' # Z - not widely used
|
80
|
+
}.compare_by_identity.freeze
|
81
|
+
|
82
|
+
@esc1 = {
|
83
|
+
0x08 => 'Back',
|
84
|
+
0x09 => 'Tab',
|
85
|
+
0x10 => 'Ctrl+?',
|
86
|
+
0x0d => 'Enter',
|
87
|
+
0x1b => 'Esc',
|
88
|
+
0x20 => 'Space',
|
89
|
+
0x7f => 'Back'
|
90
|
+
}.compare_by_identity.freeze
|
91
|
+
|
92
|
+
@key_name = {
|
93
|
+
0x00 => 'Ctrl+Space',
|
47
94
|
0x01 => 'Ctrl+a',
|
48
95
|
0x02 => 'Ctrl+b',
|
49
96
|
0x03 => 'Ctrl+c',
|
50
|
-
0x04 => '
|
97
|
+
0x04 => 'Ctrl+d',
|
51
98
|
0x05 => 'Ctrl+e',
|
52
99
|
0x06 => 'Ctrl+f',
|
53
100
|
0x07 => 'Ctrl+g',
|
54
|
-
0x08 => 'Ctrl+
|
101
|
+
0x08 => 'Ctrl+Back',
|
55
102
|
0x09 => 'Tab',
|
56
103
|
0x0a => 'Ctrl+j',
|
57
104
|
0x0b => 'Ctrl+k',
|
@@ -70,41 +117,16 @@ module Terminal
|
|
70
117
|
0x18 => 'Ctrl+x',
|
71
118
|
0x19 => 'Ctrl+y',
|
72
119
|
0x1a => 'Ctrl+z',
|
73
|
-
0x1d => 'Ctrl+ü', # FIND AM
|
74
|
-
0x1e => 'Ctrl+^', # FIND AM
|
75
|
-
0x1f => 'Ctrl+-',
|
76
120
|
0x1b => 'Esc',
|
121
|
+
0x1c => 'Ctrl+4',
|
122
|
+
0x1d => 'Ctrl+5',
|
123
|
+
0x1e => 'Ctrl+6',
|
124
|
+
0x1f => 'Ctrl+7',
|
125
|
+
0x20 => 'Space',
|
77
126
|
0x7f => 'Back'
|
78
127
|
}.compare_by_identity.freeze
|
79
128
|
|
80
|
-
|
81
|
-
# ESC [ O ?
|
82
|
-
SS3 = {
|
83
|
-
0x41 => 'Up', # A
|
84
|
-
0x42 => 'Down', # B
|
85
|
-
0x43 => 'Right', # C
|
86
|
-
0x44 => 'Left', # D
|
87
|
-
0x46 => 'End', # F
|
88
|
-
0x48 => 'Home', # H
|
89
|
-
0x50 => 'F1', # P
|
90
|
-
0x51 => 'F2', # Q
|
91
|
-
0x52 => 'F3', # R
|
92
|
-
0x53 => 'F4' # S
|
93
|
-
}.compare_by_identity.freeze
|
94
|
-
|
95
|
-
LEGACY = {
|
96
|
-
0x03 => 'Del',
|
97
|
-
0x0f => 'F5',
|
98
|
-
0x11 => 'F6',
|
99
|
-
0x12 => 'F7',
|
100
|
-
0x13 => 'F8',
|
101
|
-
0x14 => 'F9',
|
102
|
-
0x15 => 'F10',
|
103
|
-
0x17 => 'F11',
|
104
|
-
0x18 => 'F12'
|
105
|
-
}.compare_by_identity.freeze
|
106
|
-
|
107
|
-
MODS = {
|
129
|
+
@mods = {
|
108
130
|
1 => 'Shift',
|
109
131
|
2 => 'Alt',
|
110
132
|
4 => 'Ctrl',
|
data/lib/terminal/input.rb
CHANGED
@@ -30,66 +30,63 @@ module Terminal
|
|
30
30
|
# @return [String] key name in `:named` mode
|
31
31
|
# @return [[String, String]] key code and key name in `:both` mode
|
32
32
|
def read_key(mode: :named)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
read_csi_u(mode)
|
40
|
-
end
|
33
|
+
return if input_mode == :error
|
34
|
+
return read_dumb(mode == :both) if @input_mode == :dumb
|
35
|
+
return read_tty&.join if mode == :raw
|
36
|
+
key, name = @input_mode == :csi_u ? read_csiu : read_legacy
|
37
|
+
return unless key
|
38
|
+
mode == :both ? [key, name] : name || key
|
41
39
|
end
|
42
40
|
|
43
41
|
private
|
44
42
|
|
45
|
-
def read_dumb(
|
46
|
-
|
43
|
+
def read_dumb(both)
|
44
|
+
inp = STDIN.getc
|
45
|
+
name = DumbKeys.key_name(inp)
|
46
|
+
both ? [inp, name] : name || inp
|
47
47
|
rescue Interrupt
|
48
|
-
|
49
|
-
rescue IOError, SystemCallError
|
50
|
-
@input_mode = :error
|
51
|
-
nil
|
48
|
+
DumbKeys.key_name("\x05")
|
52
49
|
end
|
53
50
|
|
54
|
-
def read_legacy
|
55
|
-
|
56
|
-
def read_csi_u(mode)
|
57
|
-
if _write("\e[>1u")
|
58
|
-
key = read_tty
|
59
|
-
_write("\e[<u")
|
60
|
-
translate_key(key, mode, CSIuKeys)
|
61
|
-
else
|
62
|
-
@input_mode = :legacy
|
63
|
-
read_legacy(mode)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def translate_key(key, mode, translator)
|
51
|
+
def read_legacy
|
52
|
+
key, *esc = read_tty
|
68
53
|
return unless key
|
69
|
-
return key if
|
70
|
-
|
71
|
-
mode == :both ? [key, name] : name || key
|
54
|
+
return key, LegacyKeys.key_name(key) if esc.empty?
|
55
|
+
[key + esc.join, LegacyKeys.translate(esc)]
|
72
56
|
end
|
73
57
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
77
|
-
|
58
|
+
def read_csiu
|
59
|
+
unless @csiu_set
|
60
|
+
if _write("\e[>1u").nil?
|
61
|
+
@input_mode = :legacy
|
62
|
+
return read_legacy
|
63
|
+
end
|
64
|
+
@csiu_set = true
|
65
|
+
at_exit { _write("\e[<u") if @csiu_set }
|
78
66
|
end
|
79
|
-
key
|
80
|
-
|
81
|
-
key
|
82
|
-
|
83
|
-
@input_mode = :error
|
84
|
-
nil
|
67
|
+
key, *esc = read_tty
|
68
|
+
return unless key
|
69
|
+
return key, CSIuKeys.key_name(key) if esc.empty?
|
70
|
+
[key + esc.join, CSIuKeys.translate(esc)]
|
85
71
|
end
|
86
72
|
|
87
73
|
def find_input_mode
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
74
|
+
case ENV['INPUT_MODE']
|
75
|
+
when 'dumb', 'DUMB'
|
76
|
+
:dumb
|
77
|
+
when 'legacy', 'LEGACY'
|
78
|
+
:legacy
|
79
|
+
when 'csi_u', 'CSI_U', 'csiu', 'CSIU'
|
80
|
+
:csi_u
|
81
|
+
else
|
82
|
+
return :dumb unless STDIN.tty?
|
83
|
+
STDIN.sync = true
|
84
|
+
return :legacy if !ansi? || _write("\e[>1u\e[?u\e[c").nil? || !csi_u?
|
85
|
+
_write("\e[<u")
|
86
|
+
:csi_u
|
87
|
+
end
|
88
|
+
rescue Interrupt
|
89
|
+
:legacy
|
93
90
|
rescue IOError, SystemCallError
|
94
91
|
:error
|
95
92
|
end
|
@@ -98,12 +95,30 @@ module Terminal
|
|
98
95
|
# iTerm2 returns result in two chunks :/
|
99
96
|
ret = false
|
100
97
|
while true
|
101
|
-
|
102
|
-
|
103
|
-
|
98
|
+
break if (str = STDIN.getch.dup) != "\e"
|
99
|
+
while (nc = STDIN.read_nonblock(1, exception: false))
|
100
|
+
String === nc ? str << nc : break
|
101
|
+
end
|
102
|
+
ret = true if str.include?("\e[?1u")
|
103
|
+
break if str[-1] == 'c'
|
104
104
|
end
|
105
105
|
ret
|
106
106
|
end
|
107
|
+
|
108
|
+
# nil, nil => error; key, [] => simple key; "\e", [] => esc sequence
|
109
|
+
def read_tty
|
110
|
+
key = [STDIN.getch]
|
111
|
+
return key if key[0] != "\e"
|
112
|
+
while (nc = STDIN.read_nonblock(1, exception: false))
|
113
|
+
String === nc ? key << nc : break
|
114
|
+
end
|
115
|
+
key
|
116
|
+
rescue Interrupt
|
117
|
+
key
|
118
|
+
rescue IOError, SystemCallError
|
119
|
+
@input_mode = :error
|
120
|
+
nil
|
121
|
+
end
|
107
122
|
end
|
108
123
|
|
109
124
|
dir = __dir__
|
@@ -132,7 +132,7 @@ module Terminal
|
|
132
132
|
0x450,
|
133
133
|
0x451,
|
134
134
|
0x482,
|
135
|
-
|
135
|
+
0x489,
|
136
136
|
0x590,
|
137
137
|
0x5bd,
|
138
138
|
0x5be,
|
@@ -359,6 +359,7 @@ module Terminal
|
|
359
359
|
0x109d,
|
360
360
|
0x10ff,
|
361
361
|
0x115f,
|
362
|
+
0x11ff,
|
362
363
|
0x135c,
|
363
364
|
0x135f,
|
364
365
|
0x1711,
|
@@ -414,8 +415,6 @@ module Terminal
|
|
414
415
|
0x1a7e,
|
415
416
|
0x1a7f,
|
416
417
|
0x1aaf,
|
417
|
-
0x1abd,
|
418
|
-
0x1abe,
|
419
418
|
0x1ace,
|
420
419
|
0x1aff,
|
421
420
|
0x1b03,
|
@@ -494,10 +493,6 @@ module Terminal
|
|
494
493
|
0x20ab,
|
495
494
|
0x20ac,
|
496
495
|
0x20cf,
|
497
|
-
0x20dc,
|
498
|
-
0x20e0,
|
499
|
-
0x20e1,
|
500
|
-
0x20e4,
|
501
496
|
0x20f0,
|
502
497
|
0x2102,
|
503
498
|
0x2103,
|
@@ -770,7 +765,7 @@ module Terminal
|
|
770
765
|
0xa48f,
|
771
766
|
0xa4c6,
|
772
767
|
0xa66e,
|
773
|
-
|
768
|
+
0xa672,
|
774
769
|
0xa673,
|
775
770
|
0xa67d,
|
776
771
|
0xa69d,
|
@@ -843,6 +838,10 @@ module Terminal
|
|
843
838
|
0xabed,
|
844
839
|
0xabff,
|
845
840
|
0xd7a3,
|
841
|
+
0xd7af,
|
842
|
+
0xd7c6,
|
843
|
+
0xd7ca,
|
844
|
+
0xd7fb,
|
846
845
|
0xdfff,
|
847
846
|
0xf8ff,
|
848
847
|
0xfaff,
|
@@ -1645,7 +1644,6 @@ module Terminal
|
|
1645
1644
|
0,
|
1646
1645
|
1,
|
1647
1646
|
2,
|
1648
|
-
1,
|
1649
1647
|
0,
|
1650
1648
|
1,
|
1651
1649
|
0,
|
@@ -1782,10 +1780,6 @@ module Terminal
|
|
1782
1780
|
1,
|
1783
1781
|
0,
|
1784
1782
|
1,
|
1785
|
-
0,
|
1786
|
-
1,
|
1787
|
-
0,
|
1788
|
-
1,
|
1789
1783
|
-1,
|
1790
1784
|
1,
|
1791
1785
|
-1,
|
@@ -2130,6 +2124,10 @@ module Terminal
|
|
2130
2124
|
1,
|
2131
2125
|
2,
|
2132
2126
|
1,
|
2127
|
+
0,
|
2128
|
+
1,
|
2129
|
+
0,
|
2130
|
+
1,
|
2133
2131
|
-1,
|
2134
2132
|
2,
|
2135
2133
|
1,
|
data/lib/terminal/text.rb
CHANGED
@@ -114,12 +114,13 @@ module Terminal
|
|
114
114
|
def char_width(char)
|
115
115
|
ord = char.ord
|
116
116
|
return CONTROL_CHAR_WIDTH[ord] || 2 if ord < 0x20
|
117
|
-
return 1 if ord < 0xa1
|
118
|
-
|
119
|
-
return
|
120
|
-
sco = char[1].ord
|
121
|
-
|
122
|
-
|
117
|
+
return 1 if char.size < 2 && ord < 0xa1
|
118
|
+
width = CharWidth[ord]
|
119
|
+
return @ambiguous_char_width if width == -1
|
120
|
+
sco = char[-1].ord
|
121
|
+
return width if sco != 0xff9e && sco != 0xff9f
|
122
|
+
# handle halfwidth dakuten/handakuten
|
123
|
+
char.size < 2 ? 1 : char.each_char.sum { char_width(_1) }
|
123
124
|
end
|
124
125
|
|
125
126
|
def lim_pairs(snippeds, limit)
|
@@ -452,7 +453,7 @@ module Terminal
|
|
452
453
|
SCAN_EXPR =
|
453
454
|
/\G(?:
|
454
455
|
(\r?\n)
|
455
|
-
| (\e\[[\d;:\?]*[
|
456
|
+
| (\e\[[\d;:\?]*[ABCDEFGHJKSTfhilmnsu])
|
456
457
|
| (\e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\))
|
457
458
|
| (\s+)
|
458
459
|
| (\X)
|
@@ -460,7 +461,7 @@ module Terminal
|
|
460
461
|
|
461
462
|
WIDTH_SCANNER =
|
462
463
|
/\G(?:
|
463
|
-
(?:\e\[[\d;:\?]*[
|
464
|
+
(?:\e\[[\d;:\?]*[ABCDEFGHJKSTfhilmnsu])
|
464
465
|
| (?:\e\]\d+(?:;[^\a\e]+)*(?:\a|\e\\))
|
465
466
|
| (\s+)
|
466
467
|
| (\X)
|
data/lib/terminal/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: terminal_rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Blumtritt
|
@@ -49,7 +49,7 @@ metadata:
|
|
49
49
|
rubygems_mfa_required: 'true'
|
50
50
|
source_code_uri: https://codeberg.org/mblumtritt/Terminal.rb
|
51
51
|
bug_tracker_uri: https://codeberg.org/mblumtritt/Terminal.rb/issues
|
52
|
-
documentation_uri: https://rubydoc.info/gems/terminal_rb/0.
|
52
|
+
documentation_uri: https://rubydoc.info/gems/terminal_rb/0.11.0/Terminal
|
53
53
|
rdoc_options: []
|
54
54
|
require_paths:
|
55
55
|
- lib
|
@@ -64,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
64
|
- !ruby/object:Gem::Version
|
65
65
|
version: '0'
|
66
66
|
requirements: []
|
67
|
-
rubygems_version: 3.7.
|
67
|
+
rubygems_version: 3.7.1
|
68
68
|
specification_version: 4
|
69
69
|
summary: Fast terminal access with ANSI and BBCode support.
|
70
70
|
test_files: []
|