reline 0.5.9 → 0.6.1
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/reline/config.rb +41 -50
- data/lib/reline/face.rb +1 -1
- data/lib/reline/history.rb +3 -3
- data/lib/reline/io/ansi.rb +77 -123
- data/lib/reline/io/dumb.rb +16 -2
- data/lib/reline/io/windows.rb +94 -67
- data/lib/reline/io.rb +14 -0
- data/lib/reline/key_actor/base.rb +10 -4
- data/lib/reline/key_actor/emacs.rb +96 -96
- data/lib/reline/key_actor/vi_command.rb +182 -182
- data/lib/reline/key_actor/vi_insert.rb +137 -137
- data/lib/reline/key_stroke.rb +26 -16
- data/lib/reline/line_editor.rb +331 -534
- data/lib/reline/unicode/east_asian_width.rb +1289 -1192
- data/lib/reline/unicode.rb +155 -436
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +46 -34
- metadata +3 -7
- data/lib/reline/terminfo.rb +0 -158
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2fb74f487afccdfb3b0530a043cfb7090f2a4860f2fdd168bc94112818b5f57d
|
4
|
+
data.tar.gz: 96b74e0f611f24022f204e9551d8692ef017c52a197ae169fbfdc1074a130857
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ffdcec13818f2445bd9f639e75b36405c76a439378335fa7c05fad90a26f06965e54cd9dce1b8e1411e16df9ffc80c3c0ac356320654af2ebd40a33fd28cb247
|
7
|
+
data.tar.gz: 24be10266aebce2d07f1519010f6ce0e6b92b816b17e526ede204943880b54388aa5ebf5da086bde0212b5e1f837936e4972c09a57a2d6c94f7c9a41412966d9
|
data/lib/reline/config.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Reline::Config
|
2
2
|
attr_reader :test_mode
|
3
3
|
|
4
|
-
KEYSEQ_PATTERN = /\\(?:C|Control)-[A-Za-z_]|\\(?:M|Meta)-[0-9A-Za-z_]|\\(?:C|Control)
|
4
|
+
KEYSEQ_PATTERN = /\\(?:C|Control)-[A-Za-z_]|\\(?:M|Meta)-[0-9A-Za-z_]|\\(?:C|Control)-\\(?:M|Meta)-[A-Za-z_]|\\(?:M|Meta)-\\(?:C|Control)-[A-Za-z_]|\\e|\\[\\\"\'abdfnrtv]|\\\d{1,3}|\\x\h{1,2}|./
|
5
5
|
|
6
6
|
class InvalidInputrc < RuntimeError
|
7
7
|
attr_accessor :file, :lineno
|
@@ -29,6 +29,17 @@ class Reline::Config
|
|
29
29
|
attr_accessor :autocompletion
|
30
30
|
|
31
31
|
def initialize
|
32
|
+
reset_variables
|
33
|
+
end
|
34
|
+
|
35
|
+
def reset
|
36
|
+
if editing_mode_is?(:vi_command)
|
37
|
+
@editing_mode_label = :vi_insert
|
38
|
+
end
|
39
|
+
@oneshot_key_bindings.clear
|
40
|
+
end
|
41
|
+
|
42
|
+
def reset_variables
|
32
43
|
@additional_key_bindings = { # from inputrc
|
33
44
|
emacs: Reline::KeyActor::Base.new,
|
34
45
|
vi_insert: Reline::KeyActor::Base.new,
|
@@ -51,16 +62,11 @@ class Reline::Config
|
|
51
62
|
@keyseq_timeout = 500
|
52
63
|
@test_mode = false
|
53
64
|
@autocompletion = false
|
54
|
-
@convert_meta =
|
65
|
+
@convert_meta = seven_bit_encoding?(Reline::IOGate.encoding)
|
55
66
|
@loaded = false
|
56
67
|
@enable_bracketed_paste = true
|
57
|
-
|
58
|
-
|
59
|
-
def reset
|
60
|
-
if editing_mode_is?(:vi_command)
|
61
|
-
@editing_mode_label = :vi_insert
|
62
|
-
end
|
63
|
-
@oneshot_key_bindings.clear
|
68
|
+
@show_mode_in_prompt = false
|
69
|
+
@default_inputrc_path = nil
|
64
70
|
end
|
65
71
|
|
66
72
|
def editing_mode
|
@@ -188,13 +194,14 @@ class Reline::Config
|
|
188
194
|
# value ignores everything after a space, raw_value does not.
|
189
195
|
var, value, raw_value = $1.downcase, $2.partition(' ').first, $2
|
190
196
|
bind_variable(var, value, raw_value)
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
197
|
+
when /^\s*(?:M|Meta)-([a-zA-Z_])\s*:\s*(.*)\s*$/o
|
198
|
+
bind_key("\"\\M-#$1\"", $2)
|
199
|
+
when /^\s*(?:C|Control)-([a-zA-Z_])\s*:\s*(.*)\s*$/o
|
200
|
+
bind_key("\"\\C-#$1\"", $2)
|
201
|
+
when /^\s*(?:(?:C|Control)-(?:M|Meta)|(?:M|Meta)-(?:C|Control))-([a-zA-Z_])\s*:\s*(.*)\s*$/o
|
202
|
+
bind_key("\"\\M-\\C-#$1\"", $2)
|
203
|
+
when /^\s*("#{KEYSEQ_PATTERN}+")\s*:\s*(.*)\s*$/o
|
204
|
+
bind_key($1, $2)
|
198
205
|
end
|
199
206
|
end
|
200
207
|
unless if_stack.empty?
|
@@ -245,22 +252,6 @@ class Reline::Config
|
|
245
252
|
rescue ArgumentError
|
246
253
|
@history_size = 500
|
247
254
|
end
|
248
|
-
when 'bell-style'
|
249
|
-
@bell_style =
|
250
|
-
case value
|
251
|
-
when 'none', 'off'
|
252
|
-
:none
|
253
|
-
when 'audible', 'on'
|
254
|
-
:audible
|
255
|
-
when 'visible'
|
256
|
-
:visible
|
257
|
-
else
|
258
|
-
:audible
|
259
|
-
end
|
260
|
-
when 'comment-begin'
|
261
|
-
@comment_begin = value.dup
|
262
|
-
when 'completion-query-items'
|
263
|
-
@completion_query_items = value.to_i
|
264
255
|
when 'isearch-terminators'
|
265
256
|
@isearch_terminators = retrieve_string(raw_value)
|
266
257
|
when 'editing-mode'
|
@@ -320,7 +311,12 @@ class Reline::Config
|
|
320
311
|
parse_keyseq(str).map { |c| c.chr(Reline.encoding_system_needs) }.join
|
321
312
|
end
|
322
313
|
|
323
|
-
def bind_key(key,
|
314
|
+
def bind_key(key, value)
|
315
|
+
keystroke, func = parse_key_binding(key, value)
|
316
|
+
@additional_key_bindings[@keymap_label].add(@keymap_prefix + keystroke, func) if keystroke
|
317
|
+
end
|
318
|
+
|
319
|
+
def parse_key_binding(key, func_name)
|
324
320
|
if key =~ /\A"(.*)"\z/
|
325
321
|
keyseq = parse_keyseq($1)
|
326
322
|
else
|
@@ -329,27 +325,19 @@ class Reline::Config
|
|
329
325
|
if func_name =~ /"(.*)"/
|
330
326
|
func = parse_keyseq($1)
|
331
327
|
else
|
332
|
-
func = func_name.tr(?-, ?_).to_sym # It must be macro.
|
328
|
+
func = func_name.split.first.tr(?-, ?_).to_sym # It must be macro.
|
333
329
|
end
|
334
330
|
[keyseq, func]
|
335
331
|
end
|
336
332
|
|
337
333
|
def key_notation_to_code(notation)
|
338
334
|
case notation
|
335
|
+
when /(?:\\(?:C|Control)-\\(?:M|Meta)|\\(?:M|Meta)-\\(?:C|Control))-([A-Za-z_])/
|
336
|
+
[?\e.ord, $1.ord % 32]
|
339
337
|
when /\\(?:C|Control)-([A-Za-z_])/
|
340
|
-
(
|
338
|
+
($1.upcase.ord % 32)
|
341
339
|
when /\\(?:M|Meta)-([0-9A-Za-z_])/
|
342
|
-
|
343
|
-
case $1
|
344
|
-
when /[0-9]/
|
345
|
-
?\M-0.bytes.first + (modified_key.ord - ?0.ord)
|
346
|
-
when /[A-Z]/
|
347
|
-
?\M-A.bytes.first + (modified_key.ord - ?A.ord)
|
348
|
-
when /[a-z]/
|
349
|
-
?\M-a.bytes.first + (modified_key.ord - ?a.ord)
|
350
|
-
end
|
351
|
-
when /\\(?:C|Control)-(?:M|Meta)-[A-Za-z_]/, /\\(?:M|Meta)-(?:C|Control)-[A-Za-z_]/
|
352
|
-
# 129 M-^A
|
340
|
+
[?\e.ord, $1.ord]
|
353
341
|
when /\\(\d{1,3})/ then $1.to_i(8) # octal
|
354
342
|
when /\\x(\h{1,2})/ then $1.to_i(16) # hexadecimal
|
355
343
|
when "\\e" then ?\e.ord
|
@@ -369,11 +357,14 @@ class Reline::Config
|
|
369
357
|
end
|
370
358
|
|
371
359
|
def parse_keyseq(str)
|
372
|
-
|
373
|
-
|
374
|
-
ret << key_notation_to_code($&)
|
360
|
+
str.scan(KEYSEQ_PATTERN).flat_map do |notation|
|
361
|
+
key_notation_to_code(notation)
|
375
362
|
end
|
376
|
-
|
363
|
+
end
|
364
|
+
|
365
|
+
def reload
|
366
|
+
reset_variables
|
367
|
+
read
|
377
368
|
end
|
378
369
|
|
379
370
|
private def seven_bit_encoding?(encoding)
|
data/lib/reline/face.rb
CHANGED
@@ -107,7 +107,7 @@ class Reline::Face
|
|
107
107
|
|
108
108
|
def sgr_rgb_256color(key, value)
|
109
109
|
# 256 colors are
|
110
|
-
# 0..15: standard colors,
|
110
|
+
# 0..15: standard colors, high intensity colors
|
111
111
|
# 16..232: 216 colors (R, G, B each 6 steps)
|
112
112
|
# 233..255: grayscale colors (24 steps)
|
113
113
|
# This methods converts rgb_expression to 216 colors
|
data/lib/reline/history.rb
CHANGED
@@ -19,7 +19,7 @@ class Reline::History < Array
|
|
19
19
|
|
20
20
|
def []=(index, val)
|
21
21
|
index = check_index(index)
|
22
|
-
super(index,
|
22
|
+
super(index, Reline::Unicode.safe_encode(val, Reline.encoding_system_needs))
|
23
23
|
end
|
24
24
|
|
25
25
|
def concat(*val)
|
@@ -45,7 +45,7 @@ class Reline::History < Array
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
super(*(val.map{ |v|
|
48
|
-
|
48
|
+
Reline::Unicode.safe_encode(v, Reline.encoding_system_needs)
|
49
49
|
}))
|
50
50
|
end
|
51
51
|
|
@@ -56,7 +56,7 @@ class Reline::History < Array
|
|
56
56
|
if @config.history_size.positive?
|
57
57
|
shift if size + 1 > @config.history_size
|
58
58
|
end
|
59
|
-
super(
|
59
|
+
super(Reline::Unicode.safe_encode(val, Reline.encoding_system_needs))
|
60
60
|
end
|
61
61
|
|
62
62
|
private def check_index(index)
|
data/lib/reline/io/ansi.rb
CHANGED
@@ -2,18 +2,6 @@ require 'io/console'
|
|
2
2
|
require 'io/wait'
|
3
3
|
|
4
4
|
class Reline::ANSI < Reline::IO
|
5
|
-
CAPNAME_KEY_BINDINGS = {
|
6
|
-
'khome' => :ed_move_to_beg,
|
7
|
-
'kend' => :ed_move_to_end,
|
8
|
-
'kdch1' => :key_delete,
|
9
|
-
'kpp' => :ed_search_prev_history,
|
10
|
-
'knp' => :ed_search_next_history,
|
11
|
-
'kcuu1' => :ed_prev_history,
|
12
|
-
'kcud1' => :ed_next_history,
|
13
|
-
'kcuf1' => :ed_next_char,
|
14
|
-
'kcub1' => :ed_prev_char,
|
15
|
-
}
|
16
|
-
|
17
5
|
ANSI_CURSOR_KEY_BINDINGS = {
|
18
6
|
# Up
|
19
7
|
'A' => [:ed_prev_history, {}],
|
@@ -29,29 +17,27 @@ class Reline::ANSI < Reline::IO
|
|
29
17
|
'H' => [:ed_move_to_beg, {}],
|
30
18
|
}
|
31
19
|
|
32
|
-
|
33
|
-
Reline::Terminfo.setupterm(0, 2)
|
34
|
-
end
|
20
|
+
attr_writer :input, :output
|
35
21
|
|
36
22
|
def initialize
|
37
23
|
@input = STDIN
|
38
24
|
@output = STDOUT
|
39
25
|
@buf = []
|
26
|
+
@output_buffer = nil
|
40
27
|
@old_winch_handler = nil
|
41
28
|
end
|
42
29
|
|
43
30
|
def encoding
|
31
|
+
@input.external_encoding || Encoding.default_external
|
32
|
+
rescue IOError
|
33
|
+
# STDIN.external_encoding raises IOError in Ruby <= 3.0 when STDIN is closed
|
44
34
|
Encoding.default_external
|
45
35
|
end
|
46
36
|
|
47
|
-
def set_default_key_bindings(config
|
37
|
+
def set_default_key_bindings(config)
|
48
38
|
set_bracketed_paste_key_bindings(config)
|
49
39
|
set_default_key_bindings_ansi_cursor(config)
|
50
|
-
|
51
|
-
set_default_key_bindings_terminfo(config)
|
52
|
-
else
|
53
|
-
set_default_key_bindings_comprehensive_list(config)
|
54
|
-
end
|
40
|
+
set_default_key_bindings_comprehensive_list(config)
|
55
41
|
{
|
56
42
|
[27, 91, 90] => :completion_journey_up, # S-Tab
|
57
43
|
}.each_pair do |key, func|
|
@@ -75,7 +61,10 @@ class Reline::ANSI < Reline::IO
|
|
75
61
|
|
76
62
|
def set_default_key_bindings_ansi_cursor(config)
|
77
63
|
ANSI_CURSOR_KEY_BINDINGS.each do |char, (default_func, modifiers)|
|
78
|
-
bindings = [
|
64
|
+
bindings = [
|
65
|
+
["\e[#{char}", default_func], # CSI + char
|
66
|
+
["\eO#{char}", default_func] # SS3 + char, application cursor key mode
|
67
|
+
]
|
79
68
|
if modifiers[:ctrl]
|
80
69
|
# CSI + ctrl_key_modifier + char
|
81
70
|
bindings << ["\e[1;5#{char}", modifiers[:ctrl]]
|
@@ -95,23 +84,6 @@ class Reline::ANSI < Reline::IO
|
|
95
84
|
end
|
96
85
|
end
|
97
86
|
|
98
|
-
def set_default_key_bindings_terminfo(config)
|
99
|
-
key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding|
|
100
|
-
begin
|
101
|
-
key_code = Reline::Terminfo.tigetstr(capname)
|
102
|
-
[ key_code.bytes, key_binding ]
|
103
|
-
rescue Reline::Terminfo::TerminfoError
|
104
|
-
# capname is undefined
|
105
|
-
end
|
106
|
-
end.compact.to_h
|
107
|
-
|
108
|
-
key_bindings.each_pair do |key, func|
|
109
|
-
config.add_default_key_binding_by_keymap(:emacs, key, func)
|
110
|
-
config.add_default_key_binding_by_keymap(:vi_insert, key, func)
|
111
|
-
config.add_default_key_binding_by_keymap(:vi_command, key, func)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
87
|
def set_default_key_bindings_comprehensive_list(config)
|
116
88
|
{
|
117
89
|
# xterm
|
@@ -123,27 +95,9 @@ class Reline::ANSI < Reline::IO
|
|
123
95
|
[27, 91, 49, 126] => :ed_move_to_beg, # Home
|
124
96
|
[27, 91, 52, 126] => :ed_move_to_end, # End
|
125
97
|
|
126
|
-
# KDE
|
127
|
-
# Del is 0x08
|
128
|
-
[27, 71, 65] => :ed_prev_history, # ↑
|
129
|
-
[27, 71, 66] => :ed_next_history, # ↓
|
130
|
-
[27, 71, 67] => :ed_next_char, # →
|
131
|
-
[27, 71, 68] => :ed_prev_char, # ←
|
132
|
-
|
133
98
|
# urxvt / exoterm
|
134
99
|
[27, 91, 55, 126] => :ed_move_to_beg, # Home
|
135
100
|
[27, 91, 56, 126] => :ed_move_to_end, # End
|
136
|
-
|
137
|
-
# GNOME
|
138
|
-
[27, 79, 72] => :ed_move_to_beg, # Home
|
139
|
-
[27, 79, 70] => :ed_move_to_end, # End
|
140
|
-
# Del is 0x08
|
141
|
-
# Arrow keys are the same of KDE
|
142
|
-
|
143
|
-
[27, 79, 65] => :ed_prev_history, # ↑
|
144
|
-
[27, 79, 66] => :ed_next_history, # ↓
|
145
|
-
[27, 79, 67] => :ed_next_char, # →
|
146
|
-
[27, 79, 68] => :ed_prev_char, # ←
|
147
101
|
}.each_pair do |key, func|
|
148
102
|
config.add_default_key_binding_by_keymap(:emacs, key, func)
|
149
103
|
config.add_default_key_binding_by_keymap(:vi_insert, key, func)
|
@@ -151,14 +105,6 @@ class Reline::ANSI < Reline::IO
|
|
151
105
|
end
|
152
106
|
end
|
153
107
|
|
154
|
-
def input=(val)
|
155
|
-
@input = val
|
156
|
-
end
|
157
|
-
|
158
|
-
def output=(val)
|
159
|
-
@output = val
|
160
|
-
end
|
161
|
-
|
162
108
|
def with_raw_input
|
163
109
|
if @input.tty?
|
164
110
|
@input.raw(intr: true) { yield }
|
@@ -245,52 +191,57 @@ class Reline::ANSI < Reline::IO
|
|
245
191
|
self
|
246
192
|
end
|
247
193
|
|
248
|
-
def
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
@
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
break if m
|
194
|
+
private def cursor_pos_internal(timeout:)
|
195
|
+
match = nil
|
196
|
+
@input.raw do |stdin|
|
197
|
+
@output << "\e[6n"
|
198
|
+
@output.flush
|
199
|
+
timeout_at = Time.now + timeout
|
200
|
+
buf = +''
|
201
|
+
while (wait = timeout_at - Time.now) > 0 && stdin.wait_readable(wait)
|
202
|
+
buf << stdin.readpartial(1024)
|
203
|
+
if (match = buf.match(/\e\[(?<row>\d+);(?<column>\d+)R/))
|
204
|
+
buf = match.pre_match + match.post_match
|
205
|
+
break
|
261
206
|
end
|
262
|
-
(m.pre_match + m.post_match).chars.reverse_each do |ch|
|
263
|
-
stdin.ungetc ch
|
264
|
-
end
|
265
|
-
end
|
266
|
-
column = m[:column].to_i - 1
|
267
|
-
row = m[:row].to_i - 1
|
268
|
-
else
|
269
|
-
begin
|
270
|
-
buf = @output.pread(@output.pos, 0)
|
271
|
-
row = buf.count("\n")
|
272
|
-
column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0
|
273
|
-
rescue Errno::ESPIPE, IOError
|
274
|
-
# Just returns column 1 for ambiguous width because this I/O is not
|
275
|
-
# tty and can't seek.
|
276
|
-
row = 0
|
277
|
-
column = 1
|
278
207
|
end
|
208
|
+
@buf.concat buf.bytes
|
279
209
|
end
|
280
|
-
|
210
|
+
[match[:column].to_i - 1, match[:row].to_i - 1] if match
|
211
|
+
end
|
212
|
+
|
213
|
+
def cursor_pos
|
214
|
+
col, row = cursor_pos_internal(timeout: 0.5) if both_tty?
|
215
|
+
Reline::CursorPos.new(col || 0, row || 0)
|
281
216
|
end
|
282
217
|
|
283
218
|
def both_tty?
|
284
219
|
@input.tty? && @output.tty?
|
285
220
|
end
|
286
221
|
|
222
|
+
def write(string)
|
223
|
+
if @output_buffer
|
224
|
+
@output_buffer << string
|
225
|
+
else
|
226
|
+
@output.write(string)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def buffered_output
|
231
|
+
@output_buffer = +''
|
232
|
+
yield
|
233
|
+
@output.write(@output_buffer)
|
234
|
+
ensure
|
235
|
+
@output_buffer = nil
|
236
|
+
end
|
237
|
+
|
287
238
|
def move_cursor_column(x)
|
288
|
-
|
239
|
+
write "\e[#{x + 1}G"
|
289
240
|
end
|
290
241
|
|
291
242
|
def move_cursor_up(x)
|
292
243
|
if x > 0
|
293
|
-
|
244
|
+
write "\e[#{x}A"
|
294
245
|
elsif x < 0
|
295
246
|
move_cursor_down(-x)
|
296
247
|
end
|
@@ -298,38 +249,22 @@ class Reline::ANSI < Reline::IO
|
|
298
249
|
|
299
250
|
def move_cursor_down(x)
|
300
251
|
if x > 0
|
301
|
-
|
252
|
+
write "\e[#{x}B"
|
302
253
|
elsif x < 0
|
303
254
|
move_cursor_up(-x)
|
304
255
|
end
|
305
256
|
end
|
306
257
|
|
307
258
|
def hide_cursor
|
308
|
-
|
309
|
-
if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
|
310
|
-
begin
|
311
|
-
seq = Reline::Terminfo.tigetstr('civis')
|
312
|
-
rescue Reline::Terminfo::TerminfoError
|
313
|
-
# civis is undefined
|
314
|
-
end
|
315
|
-
end
|
316
|
-
@output.write seq
|
259
|
+
write "\e[?25l"
|
317
260
|
end
|
318
261
|
|
319
262
|
def show_cursor
|
320
|
-
|
321
|
-
if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
|
322
|
-
begin
|
323
|
-
seq = Reline::Terminfo.tigetstr('cnorm')
|
324
|
-
rescue Reline::Terminfo::TerminfoError
|
325
|
-
# cnorm is undefined
|
326
|
-
end
|
327
|
-
end
|
328
|
-
@output.write seq
|
263
|
+
write "\e[?25h"
|
329
264
|
end
|
330
265
|
|
331
266
|
def erase_after_cursor
|
332
|
-
|
267
|
+
write "\e[K"
|
333
268
|
end
|
334
269
|
|
335
270
|
# This only works when the cursor is at the bottom of the scroll range
|
@@ -337,28 +272,47 @@ class Reline::ANSI < Reline::IO
|
|
337
272
|
def scroll_down(x)
|
338
273
|
return if x.zero?
|
339
274
|
# We use `\n` instead of CSI + S because CSI + S would cause https://github.com/ruby/reline/issues/576
|
340
|
-
|
275
|
+
write "\n" * x
|
341
276
|
end
|
342
277
|
|
343
278
|
def clear_screen
|
344
|
-
|
345
|
-
|
279
|
+
write "\e[2J"
|
280
|
+
write "\e[1;1H"
|
346
281
|
end
|
347
282
|
|
348
283
|
def set_winch_handler(&handler)
|
349
|
-
@old_winch_handler = Signal.trap('WINCH'
|
284
|
+
@old_winch_handler = Signal.trap('WINCH') do |arg|
|
285
|
+
handler.call
|
286
|
+
@old_winch_handler.call(arg) if @old_winch_handler.respond_to?(:call)
|
287
|
+
end
|
288
|
+
@old_cont_handler = Signal.trap('CONT') do |arg|
|
289
|
+
@input.raw!(intr: true) if @input.tty?
|
290
|
+
# Rerender the screen. Note that screen size might be changed while suspended.
|
291
|
+
handler.call
|
292
|
+
@old_cont_handler.call(arg) if @old_cont_handler.respond_to?(:call)
|
293
|
+
end
|
294
|
+
rescue ArgumentError
|
295
|
+
# Signal.trap may raise an ArgumentError if the platform doesn't support the signal.
|
296
|
+
end
|
297
|
+
|
298
|
+
def read_single_char(keyseq_timeout)
|
299
|
+
# Disable intr to read `C-c` `C-z` `C-\` for quoted insert
|
300
|
+
@input.raw(intr: false) do
|
301
|
+
super
|
302
|
+
end
|
350
303
|
end
|
351
304
|
|
352
305
|
def prep
|
353
306
|
# Enable bracketed paste
|
354
|
-
|
307
|
+
write "\e[?2004h" if Reline.core.config.enable_bracketed_paste && both_tty?
|
355
308
|
retrieve_keybuffer
|
356
309
|
nil
|
357
310
|
end
|
358
311
|
|
359
312
|
def deprep(otio)
|
360
313
|
# Disable bracketed paste
|
361
|
-
|
314
|
+
write "\e[?2004l" if Reline.core.config.enable_bracketed_paste && both_tty?
|
362
315
|
Signal.trap('WINCH', @old_winch_handler) if @old_winch_handler
|
316
|
+
Signal.trap('CONT', @old_cont_handler) if @old_cont_handler
|
363
317
|
end
|
364
318
|
end
|
data/lib/reline/io/dumb.rb
CHANGED
@@ -3,8 +3,11 @@ require 'io/wait'
|
|
3
3
|
class Reline::Dumb < Reline::IO
|
4
4
|
RESET_COLOR = '' # Do not send color reset sequence
|
5
5
|
|
6
|
+
attr_writer :output
|
7
|
+
|
6
8
|
def initialize(encoding: nil)
|
7
9
|
@input = STDIN
|
10
|
+
@output = STDOUT
|
8
11
|
@buf = []
|
9
12
|
@pasting = false
|
10
13
|
@encoding = encoding
|
@@ -21,8 +24,11 @@ class Reline::Dumb < Reline::IO
|
|
21
24
|
elsif RUBY_PLATFORM =~ /mswin|mingw/
|
22
25
|
Encoding::UTF_8
|
23
26
|
else
|
24
|
-
Encoding
|
27
|
+
@input.external_encoding || Encoding.default_external
|
25
28
|
end
|
29
|
+
rescue IOError
|
30
|
+
# STDIN.external_encoding raises IOError in Ruby <= 3.0 when STDIN is closed
|
31
|
+
Encoding.default_external
|
26
32
|
end
|
27
33
|
|
28
34
|
def set_default_key_bindings(_)
|
@@ -36,6 +42,14 @@ class Reline::Dumb < Reline::IO
|
|
36
42
|
yield
|
37
43
|
end
|
38
44
|
|
45
|
+
def write(string)
|
46
|
+
@output.write(string)
|
47
|
+
end
|
48
|
+
|
49
|
+
def buffered_output
|
50
|
+
yield
|
51
|
+
end
|
52
|
+
|
39
53
|
def getc(_timeout_second)
|
40
54
|
unless @buf.empty?
|
41
55
|
return @buf.shift
|
@@ -60,7 +74,7 @@ class Reline::Dumb < Reline::IO
|
|
60
74
|
end
|
61
75
|
|
62
76
|
def cursor_pos
|
63
|
-
Reline::CursorPos.new(
|
77
|
+
Reline::CursorPos.new(0, 0)
|
64
78
|
end
|
65
79
|
|
66
80
|
def hide_cursor
|