reline 0.0.1 → 0.0.6
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/README.md +2 -0
- data/lib/reline.rb +329 -334
- data/lib/reline/ansi.rb +28 -11
- data/lib/reline/config.rb +4 -5
- data/lib/reline/general_io.rb +4 -1
- data/lib/reline/key_actor/vi_command.rb +1 -1
- data/lib/reline/key_actor/vi_insert.rb +1 -1
- data/lib/reline/key_stroke.rb +1 -1
- data/lib/reline/line_editor.rb +181 -76
- data/lib/reline/unicode/east_asian_width.rb +1 -1
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +109 -65
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9a8719e2dd161d4d3493907d730981e19b685854247d1da4e8a107a9af88f98
|
4
|
+
data.tar.gz: 57c468696aecaa1752bf0ebacafbb9595ec8810c0dd406beb9bd95f31b8e2d05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47f940b15f36eb7e410bf9951916258c268375fffadb661766fca64a421cc4e7aeb701a919c0b47dd03ea9b4aa1110c7c5b870328bad704c40f8e6d945a90ba2
|
7
|
+
data.tar.gz: 271926159d49eaa2b6572cc5d3640c81d82cfbc42d03a7320b0731fec276575a96c7491ab192023125a02e44d0a1cf38ee3ffa5045ac29e93f18e83ab9478071
|
data/README.md
CHANGED
data/lib/reline.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'io/console'
|
2
2
|
require 'timeout'
|
3
|
+
require 'forwardable'
|
3
4
|
require 'reline/version'
|
4
5
|
require 'reline/config'
|
5
6
|
require 'reline/key_actor'
|
@@ -8,406 +9,400 @@ require 'reline/line_editor'
|
|
8
9
|
require 'reline/history'
|
9
10
|
|
10
11
|
module Reline
|
11
|
-
Key = Struct.new('Key', :char, :combined_char, :with_meta)
|
12
|
-
|
13
|
-
extend self
|
14
12
|
FILENAME_COMPLETION_PROC = nil
|
15
13
|
USERNAME_COMPLETION_PROC = nil
|
16
14
|
|
17
|
-
|
18
|
-
IS_WINDOWS = true
|
19
|
-
else
|
20
|
-
IS_WINDOWS = false
|
21
|
-
end
|
22
|
-
|
15
|
+
Key = Struct.new('Key', :char, :combined_char, :with_meta)
|
23
16
|
CursorPos = Struct.new(:x, :y)
|
24
17
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
18
|
+
class Core
|
19
|
+
ATTR_READER_NAMES = %i(
|
20
|
+
completion_append_character
|
21
|
+
basic_word_break_characters
|
22
|
+
completer_word_break_characters
|
23
|
+
basic_quote_characters
|
24
|
+
completer_quote_characters
|
25
|
+
filename_quote_characters
|
26
|
+
special_prefixes
|
27
|
+
completion_proc
|
28
|
+
output_modifier_proc
|
29
|
+
prompt_proc
|
30
|
+
auto_indent_proc
|
31
|
+
pre_input_hook
|
32
|
+
dig_perfect_match_proc
|
33
|
+
).each(&method(:attr_reader))
|
34
|
+
|
35
|
+
ATTR_ACCESSOR_NAMES = %i(
|
36
|
+
completion_case_fold
|
37
|
+
).each(&method(:attr_accessor))
|
38
|
+
|
39
|
+
attr_accessor :config
|
40
|
+
attr_accessor :key_stroke
|
41
|
+
attr_accessor :line_editor
|
42
|
+
attr_accessor :ambiguous_width
|
43
|
+
attr_reader :output
|
44
|
+
|
45
|
+
def initialize
|
46
|
+
self.output = STDOUT
|
47
|
+
yield self
|
45
48
|
end
|
46
|
-
end
|
47
49
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
def self.completer_word_break_characters=(v)
|
61
|
-
@@completer_word_break_characters = v.encode(Encoding::default_external)
|
62
|
-
end
|
63
|
-
|
64
|
-
@@basic_quote_characters = '"\''
|
65
|
-
def self.basic_quote_characters
|
66
|
-
@@basic_quote_characters
|
67
|
-
end
|
68
|
-
def self.basic_quote_characters=(v)
|
69
|
-
@@basic_quote_characters = v.encode(Encoding::default_external)
|
70
|
-
end
|
71
|
-
|
72
|
-
@@completer_quote_characters = '"\''
|
73
|
-
def self.completer_quote_characters
|
74
|
-
@@completer_quote_characters
|
75
|
-
end
|
76
|
-
def self.completer_quote_characters=(v)
|
77
|
-
@@completer_quote_characters = v.encode(Encoding::default_external)
|
78
|
-
end
|
79
|
-
|
80
|
-
@@filename_quote_characters = ''
|
81
|
-
def self.filename_quote_characters
|
82
|
-
@@filename_quote_characters
|
83
|
-
end
|
84
|
-
def self.filename_quote_characters=(v)
|
85
|
-
@@filename_quote_characters = v.encode(Encoding::default_external)
|
86
|
-
end
|
87
|
-
|
88
|
-
@@special_prefixes = ''
|
89
|
-
def self.special_prefixes
|
90
|
-
@@special_prefixes
|
91
|
-
end
|
92
|
-
def self.special_prefixes=(v)
|
93
|
-
@@special_prefixes = v.encode(Encoding::default_external)
|
94
|
-
end
|
95
|
-
|
96
|
-
@@completion_case_fold = nil
|
97
|
-
def self.completion_case_fold
|
98
|
-
@@completion_case_fold
|
99
|
-
end
|
100
|
-
def self.completion_case_fold=(v)
|
101
|
-
@@completion_case_fold = v
|
102
|
-
end
|
103
|
-
|
104
|
-
@@completion_proc = nil
|
105
|
-
def self.completion_proc
|
106
|
-
@@completion_proc
|
107
|
-
end
|
108
|
-
def self.completion_proc=(p)
|
109
|
-
raise ArgumentError unless p.is_a?(Proc)
|
110
|
-
@@completion_proc = p
|
111
|
-
end
|
50
|
+
def completion_append_character=(val)
|
51
|
+
if val.nil?
|
52
|
+
@completion_append_character = nil
|
53
|
+
elsif val.size == 1
|
54
|
+
@completion_append_character = val.encode(Encoding::default_external)
|
55
|
+
elsif val.size > 1
|
56
|
+
@completion_append_character = val[0].encode(Encoding::default_external)
|
57
|
+
else
|
58
|
+
@completion_append_character = nil
|
59
|
+
end
|
60
|
+
end
|
112
61
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
end
|
117
|
-
def self.output_modifier_proc=(p)
|
118
|
-
raise ArgumentError unless p.is_a?(Proc)
|
119
|
-
@@output_modifier_proc = p
|
120
|
-
end
|
62
|
+
def basic_word_break_characters=(v)
|
63
|
+
@basic_word_break_characters = v.encode(Encoding::default_external)
|
64
|
+
end
|
121
65
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
126
|
-
def self.prompt_proc=(p)
|
127
|
-
raise ArgumentError unless p.is_a?(Proc)
|
128
|
-
@@prompt_proc = p
|
129
|
-
end
|
66
|
+
def completer_word_break_characters=(v)
|
67
|
+
@completer_word_break_characters = v.encode(Encoding::default_external)
|
68
|
+
end
|
130
69
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
135
|
-
def self.auto_indent_proc=(p)
|
136
|
-
raise ArgumentError unless p.is_a?(Proc)
|
137
|
-
@@auto_indent_proc = p
|
138
|
-
end
|
70
|
+
def basic_quote_characters=(v)
|
71
|
+
@basic_quote_characters = v.encode(Encoding::default_external)
|
72
|
+
end
|
139
73
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
end
|
144
|
-
def self.pre_input_hook=(p)
|
145
|
-
@@pre_input_hook = p
|
146
|
-
end
|
74
|
+
def completer_quote_characters=(v)
|
75
|
+
@completer_quote_characters = v.encode(Encoding::default_external)
|
76
|
+
end
|
147
77
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
end
|
152
|
-
def self.dig_perfect_match_proc=(p)
|
153
|
-
raise ArgumentError unless p.is_a?(Proc)
|
154
|
-
@@dig_perfect_match_proc = p
|
155
|
-
end
|
78
|
+
def filename_quote_characters=(v)
|
79
|
+
@filename_quote_characters = v.encode(Encoding::default_external)
|
80
|
+
end
|
156
81
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
end
|
82
|
+
def special_prefixes=(v)
|
83
|
+
@special_prefixes = v.encode(Encoding::default_external)
|
84
|
+
end
|
161
85
|
|
162
|
-
|
163
|
-
|
164
|
-
|
86
|
+
def completion_proc=(p)
|
87
|
+
raise ArgumentError unless p.respond_to?(:call)
|
88
|
+
@completion_proc = p
|
89
|
+
end
|
165
90
|
|
166
|
-
|
167
|
-
|
168
|
-
|
91
|
+
def output_modifier_proc=(p)
|
92
|
+
raise ArgumentError unless p.respond_to?(:call)
|
93
|
+
@output_modifier_proc = p
|
94
|
+
end
|
169
95
|
|
170
|
-
|
171
|
-
|
172
|
-
|
96
|
+
def prompt_proc=(p)
|
97
|
+
raise ArgumentError unless p.respond_to?(:call)
|
98
|
+
@prompt_proc = p
|
99
|
+
end
|
173
100
|
|
174
|
-
|
175
|
-
|
176
|
-
|
101
|
+
def auto_indent_proc=(p)
|
102
|
+
raise ArgumentError unless p.respond_to?(:call)
|
103
|
+
@auto_indent_proc = p
|
104
|
+
end
|
177
105
|
|
178
|
-
|
179
|
-
|
180
|
-
|
106
|
+
def pre_input_hook=(p)
|
107
|
+
@pre_input_hook = p
|
108
|
+
end
|
181
109
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
@@config.reset
|
187
|
-
end
|
110
|
+
def dig_perfect_match_proc=(p)
|
111
|
+
raise ArgumentError unless p.respond_to?(:call)
|
112
|
+
@dig_perfect_match_proc = p
|
113
|
+
end
|
188
114
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
115
|
+
def input=(val)
|
116
|
+
raise TypeError unless val.respond_to?(:getc) or val.nil?
|
117
|
+
if val.respond_to?(:getc)
|
118
|
+
if defined?(Reline::ANSI) and Reline::IOGate == Reline::ANSI
|
119
|
+
Reline::ANSI.input = val
|
120
|
+
elsif Reline::IOGate == Reline::GeneralIO
|
121
|
+
Reline::GeneralIO.input = val
|
122
|
+
end
|
196
123
|
end
|
197
124
|
end
|
198
|
-
end
|
199
125
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
126
|
+
def output=(val)
|
127
|
+
raise TypeError unless val.respond_to?(:write) or val.nil?
|
128
|
+
@output = val
|
129
|
+
if defined?(Reline::ANSI) and Reline::IOGate == Reline::ANSI
|
130
|
+
Reline::ANSI.output = val
|
131
|
+
end
|
206
132
|
end
|
207
|
-
end
|
208
133
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
def self.emacs_editing_mode
|
215
|
-
@@config.editing_mode = :emacs
|
216
|
-
nil
|
217
|
-
end
|
218
|
-
|
219
|
-
def self.vi_editing_mode?
|
220
|
-
@@config.editing_mode_is?(:vi_insert, :vi_command)
|
221
|
-
end
|
222
|
-
|
223
|
-
def self.emacs_editing_mode?
|
224
|
-
@@config.editing_mode_is?(:emacs)
|
225
|
-
end
|
134
|
+
def vi_editing_mode
|
135
|
+
config.editing_mode = :vi_insert
|
136
|
+
nil
|
137
|
+
end
|
226
138
|
|
227
|
-
|
228
|
-
|
229
|
-
|
139
|
+
def emacs_editing_mode
|
140
|
+
config.editing_mode = :emacs
|
141
|
+
nil
|
142
|
+
end
|
230
143
|
|
231
|
-
|
232
|
-
|
233
|
-
|
144
|
+
def vi_editing_mode?
|
145
|
+
config.editing_mode_is?(:vi_insert, :vi_command)
|
146
|
+
end
|
234
147
|
|
235
|
-
|
236
|
-
|
237
|
-
raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
|
148
|
+
def emacs_editing_mode?
|
149
|
+
config.editing_mode_is?(:emacs)
|
238
150
|
end
|
239
|
-
inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
|
240
151
|
|
241
|
-
|
242
|
-
|
243
|
-
if add_hist and whole_buffer and whole_buffer.chomp.size > 0
|
244
|
-
Reline::HISTORY << whole_buffer
|
152
|
+
def get_screen_size
|
153
|
+
Reline::IOGate.get_screen_size
|
245
154
|
end
|
246
155
|
|
247
|
-
|
248
|
-
|
249
|
-
|
156
|
+
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
|
157
|
+
unless confirm_multiline_termination
|
158
|
+
raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
|
159
|
+
end
|
160
|
+
inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
|
250
161
|
|
251
|
-
|
252
|
-
|
162
|
+
whole_buffer = line_editor.whole_buffer.dup
|
163
|
+
whole_buffer.taint if RUBY_VERSION < '2.7'
|
164
|
+
if add_hist and whole_buffer and whole_buffer.chomp.size > 0
|
165
|
+
Reline::HISTORY << whole_buffer
|
166
|
+
end
|
253
167
|
|
254
|
-
|
255
|
-
|
256
|
-
if add_hist and line and line.chomp.size > 0
|
257
|
-
Reline::HISTORY << line.chomp
|
168
|
+
line_editor.reset_line if line_editor.whole_buffer.nil?
|
169
|
+
whole_buffer
|
258
170
|
end
|
259
171
|
|
260
|
-
|
261
|
-
|
262
|
-
end
|
172
|
+
def readline(prompt = '', add_hist = false)
|
173
|
+
inner_readline(prompt, add_hist, false)
|
263
174
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
$stderr.puts "Reline is used by #{Process.pid}"
|
269
|
-
end
|
270
|
-
otio = Reline::IOGate.prep
|
271
|
-
|
272
|
-
may_req_ambiguous_char_width
|
273
|
-
@@line_editor.reset(prompt)
|
274
|
-
if multiline
|
275
|
-
@@line_editor.multiline_on
|
276
|
-
if block_given?
|
277
|
-
@@line_editor.confirm_multiline_termination_proc = confirm_multiline_termination
|
175
|
+
line = line_editor.line.dup
|
176
|
+
line.taint if RUBY_VERSION < '2.7'
|
177
|
+
if add_hist and line and line.chomp.size > 0
|
178
|
+
Reline::HISTORY << line.chomp
|
278
179
|
end
|
279
|
-
|
280
|
-
|
180
|
+
|
181
|
+
line_editor.reset_line if line_editor.line.nil?
|
182
|
+
line
|
281
183
|
end
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
184
|
+
|
185
|
+
private def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination)
|
186
|
+
if ENV['RELINE_STDERR_TTY']
|
187
|
+
$stderr.reopen(ENV['RELINE_STDERR_TTY'], 'w')
|
188
|
+
$stderr.sync = true
|
189
|
+
$stderr.puts "Reline is used by #{Process.pid}"
|
190
|
+
end
|
191
|
+
otio = Reline::IOGate.prep
|
192
|
+
|
193
|
+
may_req_ambiguous_char_width
|
194
|
+
line_editor.reset(prompt)
|
195
|
+
if multiline
|
196
|
+
line_editor.multiline_on
|
197
|
+
if block_given?
|
198
|
+
line_editor.confirm_multiline_termination_proc = confirm_multiline_termination
|
199
|
+
end
|
200
|
+
else
|
201
|
+
line_editor.multiline_off
|
202
|
+
end
|
203
|
+
line_editor.output = output
|
204
|
+
line_editor.completion_proc = completion_proc
|
205
|
+
line_editor.output_modifier_proc = output_modifier_proc
|
206
|
+
line_editor.prompt_proc = prompt_proc
|
207
|
+
line_editor.auto_indent_proc = auto_indent_proc
|
208
|
+
line_editor.dig_perfect_match_proc = dig_perfect_match_proc
|
209
|
+
line_editor.pre_input_hook = pre_input_hook
|
210
|
+
line_editor.rerender
|
211
|
+
|
212
|
+
unless config.test_mode
|
213
|
+
config.read
|
214
|
+
config.reset_default_key_bindings
|
215
|
+
Reline::IOGate::RAW_KEYSTROKE_CONFIG.each_pair do |key, func|
|
216
|
+
config.add_default_key_binding(key, func)
|
217
|
+
end
|
296
218
|
end
|
297
|
-
end
|
298
219
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
220
|
+
begin
|
221
|
+
loop do
|
222
|
+
read_io(config.keyseq_timeout) { |inputs|
|
223
|
+
inputs.each { |c|
|
224
|
+
line_editor.input_key(c)
|
225
|
+
line_editor.rerender
|
226
|
+
}
|
305
227
|
}
|
306
|
-
|
307
|
-
|
228
|
+
break if line_editor.finished?
|
229
|
+
end
|
230
|
+
Reline::IOGate.move_cursor_column(0)
|
231
|
+
rescue StandardError => e
|
232
|
+
line_editor.finalize
|
233
|
+
Reline::IOGate.deprep(otio)
|
234
|
+
raise e
|
308
235
|
end
|
309
|
-
|
310
|
-
|
311
|
-
@@line_editor.finalize
|
236
|
+
|
237
|
+
line_editor.finalize
|
312
238
|
Reline::IOGate.deprep(otio)
|
313
|
-
raise e
|
314
239
|
end
|
315
240
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
block.([Reline::Key.new(c, c, false)])
|
347
|
-
break
|
348
|
-
else
|
349
|
-
if @@key_stroke.match_status(buffer.dup.push(succ_c)) == :unmatched
|
350
|
-
if c == "\e".ord
|
351
|
-
block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
|
352
|
-
else
|
353
|
-
block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
|
354
|
-
end
|
241
|
+
# Keystrokes of GNU Readline will timeout it with the specification of
|
242
|
+
# "keyseq-timeout" when waiting for the 2nd character after the 1st one.
|
243
|
+
# If the 2nd character comes after 1st ESC without timeout it has a
|
244
|
+
# meta-property of meta-key to discriminate modified key with meta-key
|
245
|
+
# from multibyte characters that come with 8th bit on.
|
246
|
+
#
|
247
|
+
# GNU Readline will wait for the 2nd character with "keyseq-timeout"
|
248
|
+
# milli-seconds but wait forever after 3rd characters.
|
249
|
+
private def read_io(keyseq_timeout, &block)
|
250
|
+
buffer = []
|
251
|
+
loop do
|
252
|
+
c = Reline::IOGate.getc
|
253
|
+
buffer << c
|
254
|
+
result = key_stroke.match_status(buffer)
|
255
|
+
case result
|
256
|
+
when :matched
|
257
|
+
expanded = key_stroke.expand(buffer).map{ |expanded_c|
|
258
|
+
Reline::Key.new(expanded_c, expanded_c, false)
|
259
|
+
}
|
260
|
+
block.(expanded)
|
261
|
+
break
|
262
|
+
when :matching
|
263
|
+
if buffer.size == 1
|
264
|
+
begin
|
265
|
+
succ_c = nil
|
266
|
+
Timeout.timeout(keyseq_timeout / 1000.0) {
|
267
|
+
succ_c = Reline::IOGate.getc
|
268
|
+
}
|
269
|
+
rescue Timeout::Error # cancel matching only when first byte
|
270
|
+
block.([Reline::Key.new(c, c, false)])
|
355
271
|
break
|
356
272
|
else
|
357
|
-
|
273
|
+
if key_stroke.match_status(buffer.dup.push(succ_c)) == :unmatched
|
274
|
+
if c == "\e".ord
|
275
|
+
block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
|
276
|
+
else
|
277
|
+
block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
|
278
|
+
end
|
279
|
+
break
|
280
|
+
else
|
281
|
+
Reline::IOGate.ungetc(succ_c)
|
282
|
+
end
|
358
283
|
end
|
359
284
|
end
|
285
|
+
when :unmatched
|
286
|
+
if buffer.size == 1 and c == "\e".ord
|
287
|
+
read_escaped_key(keyseq_timeout, c, block)
|
288
|
+
else
|
289
|
+
expanded = buffer.map{ |expanded_c|
|
290
|
+
Reline::Key.new(expanded_c, expanded_c, false)
|
291
|
+
}
|
292
|
+
block.(expanded)
|
293
|
+
end
|
294
|
+
break
|
360
295
|
end
|
361
|
-
when :unmatched
|
362
|
-
if buffer.size == 1 and c == "\e".ord
|
363
|
-
read_escaped_key(keyseq_timeout, buffer, block)
|
364
|
-
else
|
365
|
-
block.(buffer.map{ |c| Reline::Key.new(c, c, false) })
|
366
|
-
end
|
367
|
-
break
|
368
296
|
end
|
369
297
|
end
|
370
|
-
end
|
371
298
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
block.([Reline::Key.new(c, c, false)])
|
380
|
-
else
|
381
|
-
if escaped_c.nil?
|
299
|
+
private def read_escaped_key(keyseq_timeout, c, block)
|
300
|
+
begin
|
301
|
+
escaped_c = nil
|
302
|
+
Timeout.timeout(keyseq_timeout / 1000.0) {
|
303
|
+
escaped_c = Reline::IOGate.getc
|
304
|
+
}
|
305
|
+
rescue Timeout::Error # independent ESC
|
382
306
|
block.([Reline::Key.new(c, c, false)])
|
383
|
-
elsif escaped_c >= 128 # maybe, first byte of multi byte
|
384
|
-
block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)])
|
385
|
-
elsif escaped_c == "\e".ord # escape twice
|
386
|
-
block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)])
|
387
307
|
else
|
388
|
-
|
308
|
+
if escaped_c.nil?
|
309
|
+
block.([Reline::Key.new(c, c, false)])
|
310
|
+
elsif escaped_c >= 128 # maybe, first byte of multi byte
|
311
|
+
block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)])
|
312
|
+
elsif escaped_c == "\e".ord # escape twice
|
313
|
+
block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)])
|
314
|
+
else
|
315
|
+
block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
|
316
|
+
end
|
389
317
|
end
|
390
318
|
end
|
319
|
+
|
320
|
+
private def may_req_ambiguous_char_width
|
321
|
+
@ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or STDOUT.is_a?(File)
|
322
|
+
return if ambiguous_width
|
323
|
+
Reline::IOGate.move_cursor_column(0)
|
324
|
+
print "\u{25bd}"
|
325
|
+
@ambiguous_width = Reline::IOGate.cursor_pos.x
|
326
|
+
Reline::IOGate.move_cursor_column(0)
|
327
|
+
Reline::IOGate.erase_after_cursor
|
328
|
+
end
|
391
329
|
end
|
392
330
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
331
|
+
extend Forwardable
|
332
|
+
extend SingleForwardable
|
333
|
+
|
334
|
+
#--------------------------------------------------------
|
335
|
+
# Documented API
|
336
|
+
#--------------------------------------------------------
|
337
|
+
|
338
|
+
(Core::ATTR_READER_NAMES + Core::ATTR_ACCESSOR_NAMES).each { |name|
|
339
|
+
def_single_delegators :core, "#{name}", "#{name}="
|
340
|
+
}
|
341
|
+
def_single_delegators :core, :input=, :output=
|
342
|
+
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
|
343
|
+
def_single_delegators :core, :readline
|
344
|
+
def_instance_delegators self, :readline
|
345
|
+
private :readline
|
346
|
+
|
347
|
+
|
348
|
+
#--------------------------------------------------------
|
349
|
+
# Undocumented API
|
350
|
+
#--------------------------------------------------------
|
351
|
+
|
352
|
+
# Testable in original
|
353
|
+
def_single_delegators :core, :get_screen_size
|
354
|
+
def_single_delegators :line_editor, :eof?
|
355
|
+
def_instance_delegators self, :eof?
|
356
|
+
def_single_delegators :line_editor, :delete_text
|
357
|
+
def_single_delegator :line_editor, :line, :line_buffer
|
358
|
+
def_single_delegator :line_editor, :byte_pointer, :point
|
359
|
+
def_single_delegator :line_editor, :byte_pointer=, :point=
|
360
|
+
|
361
|
+
def self.insert_text(*args, &block)
|
362
|
+
line_editor.insert_text(*args, &block)
|
363
|
+
self
|
401
364
|
end
|
402
365
|
|
403
|
-
|
404
|
-
|
366
|
+
# Untestable in original
|
367
|
+
def_single_delegator :line_editor, :rerender, :redisplay
|
368
|
+
def_single_delegators :core, :vi_editing_mode?, :emacs_editing_mode?
|
369
|
+
def_single_delegators :core, :ambiguous_width
|
370
|
+
|
371
|
+
def_single_delegators :core, :readmultiline
|
372
|
+
def_instance_delegators self, :readmultiline
|
373
|
+
private :readmultiline
|
374
|
+
|
375
|
+
def self.core
|
376
|
+
@core ||= Core.new { |core|
|
377
|
+
core.config = Reline::Config.new
|
378
|
+
core.key_stroke = Reline::KeyStroke.new(core.config)
|
379
|
+
core.line_editor = Reline::LineEditor.new(core.config)
|
380
|
+
|
381
|
+
core.basic_word_break_characters = " \t\n`><=;|&{("
|
382
|
+
core.completer_word_break_characters = " \t\n`><=;|&{("
|
383
|
+
core.basic_quote_characters = '"\''
|
384
|
+
core.completer_quote_characters = '"\''
|
385
|
+
core.filename_quote_characters = ""
|
386
|
+
core.special_prefixes = ""
|
387
|
+
}
|
388
|
+
end
|
389
|
+
|
390
|
+
def self.line_editor
|
391
|
+
core.line_editor
|
405
392
|
end
|
393
|
+
|
394
|
+
HISTORY = History.new(core.config)
|
406
395
|
end
|
407
396
|
|
408
|
-
if
|
397
|
+
if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
409
398
|
require 'reline/windows'
|
410
|
-
Reline::
|
399
|
+
if Reline::Windows.get_screen_size == [0, 0]
|
400
|
+
# Maybe Mintty on Cygwin
|
401
|
+
require 'reline/ansi'
|
402
|
+
Reline::IOGate = Reline::ANSI
|
403
|
+
else
|
404
|
+
Reline::IOGate = Reline::Windows
|
405
|
+
end
|
411
406
|
else
|
412
407
|
require 'reline/ansi'
|
413
408
|
Reline::IOGate = Reline::ANSI
|