reline 0.3.5 → 0.6.2
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 +31 -1
- data/lib/reline/config.rb +101 -124
- data/lib/reline/face.rb +199 -0
- data/lib/reline/history.rb +4 -4
- data/lib/reline/io/ansi.rb +322 -0
- data/lib/reline/io/dumb.rb +120 -0
- data/lib/reline/{windows.rb → io/windows.rb} +182 -153
- data/lib/reline/io.rb +55 -0
- data/lib/reline/key_actor/base.rb +27 -9
- data/lib/reline/key_actor/composite.rb +17 -0
- data/lib/reline/key_actor/emacs.rb +103 -103
- data/lib/reline/key_actor/vi_command.rb +188 -188
- data/lib/reline/key_actor/vi_insert.rb +144 -144
- data/lib/reline/key_actor.rb +1 -0
- data/lib/reline/key_stroke.rb +94 -80
- data/lib/reline/kill_ring.rb +2 -2
- data/lib/reline/line_editor.rb +1177 -2110
- data/lib/reline/unicode/east_asian_width.rb +1288 -1192
- data/lib/reline/unicode.rb +224 -465
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +167 -247
- metadata +13 -11
- data/lib/reline/ansi.rb +0 -357
- data/lib/reline/general_io.rb +0 -113
- data/lib/reline/terminfo.rb +0 -160
data/lib/reline/version.rb
CHANGED
data/lib/reline.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'io/console'
|
2
|
-
require 'timeout'
|
3
2
|
require 'forwardable'
|
4
3
|
require 'reline/version'
|
5
4
|
require 'reline/config'
|
@@ -7,45 +6,36 @@ require 'reline/key_actor'
|
|
7
6
|
require 'reline/key_stroke'
|
8
7
|
require 'reline/line_editor'
|
9
8
|
require 'reline/history'
|
10
|
-
require 'reline/
|
9
|
+
require 'reline/io'
|
10
|
+
require 'reline/face'
|
11
11
|
require 'rbconfig'
|
12
12
|
|
13
13
|
module Reline
|
14
14
|
# NOTE: For making compatible with the rb-readline gem
|
15
|
-
FILENAME_COMPLETION_PROC = nil
|
16
|
-
USERNAME_COMPLETION_PROC = nil
|
17
|
-
|
18
|
-
class ConfigEncodingConversionError < StandardError; end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
(other.with_meta.nil? or with_meta.nil? or with_meta == other.with_meta)
|
27
|
-
when Integer, Symbol
|
28
|
-
(combined_char and combined_char == other) or
|
29
|
-
(combined_char.nil? and char and char == other)
|
30
|
-
else
|
31
|
-
false
|
32
|
-
end
|
15
|
+
FILENAME_COMPLETION_PROC = nil # :nodoc:
|
16
|
+
USERNAME_COMPLETION_PROC = nil # :nodoc:
|
17
|
+
|
18
|
+
class ConfigEncodingConversionError < StandardError; end # :nodoc:
|
19
|
+
|
20
|
+
# EOF key: { char: nil, method_symbol: nil }
|
21
|
+
# Other key: { char: String, method_symbol: Symbol }
|
22
|
+
Key = Struct.new(:char, :method_symbol, :unused_boolean) do
|
23
|
+
# For dialog_proc `key.match?(dialog.name)`
|
24
|
+
def match?(sym)
|
25
|
+
method_symbol && method_symbol == sym
|
33
26
|
end
|
34
|
-
|
35
|
-
|
36
|
-
CursorPos = Struct.new(:x, :y)
|
27
|
+
end # :nodoc:
|
28
|
+
CursorPos = Struct.new(:x, :y) # :nodoc:
|
37
29
|
DialogRenderInfo = Struct.new(
|
38
30
|
:pos,
|
39
31
|
:contents,
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:fg_color,
|
43
|
-
:pointer_fg_color,
|
32
|
+
:face,
|
33
|
+
:bg_color, # For the time being, this line should stay here for the compatibility with IRB.
|
44
34
|
:width,
|
45
35
|
:height,
|
46
36
|
:scrollbar,
|
47
37
|
keyword_init: true
|
48
|
-
)
|
38
|
+
) # :nodoc:
|
49
39
|
|
50
40
|
class Core
|
51
41
|
ATTR_READER_NAMES = %i(
|
@@ -77,50 +67,54 @@ module Reline
|
|
77
67
|
|
78
68
|
def initialize
|
79
69
|
self.output = STDOUT
|
70
|
+
@mutex = Mutex.new
|
80
71
|
@dialog_proc_list = {}
|
81
72
|
yield self
|
82
73
|
@completion_quote_character = nil
|
83
|
-
|
74
|
+
end
|
75
|
+
|
76
|
+
def io_gate
|
77
|
+
Reline::IOGate
|
84
78
|
end
|
85
79
|
|
86
80
|
def encoding
|
87
|
-
|
81
|
+
io_gate.encoding
|
88
82
|
end
|
89
83
|
|
90
84
|
def completion_append_character=(val)
|
91
85
|
if val.nil?
|
92
86
|
@completion_append_character = nil
|
93
87
|
elsif val.size == 1
|
94
|
-
@completion_append_character = val.encode(
|
88
|
+
@completion_append_character = val.encode(encoding)
|
95
89
|
elsif val.size > 1
|
96
|
-
@completion_append_character = val[0].encode(
|
90
|
+
@completion_append_character = val[0].encode(encoding)
|
97
91
|
else
|
98
92
|
@completion_append_character = nil
|
99
93
|
end
|
100
94
|
end
|
101
95
|
|
102
96
|
def basic_word_break_characters=(v)
|
103
|
-
@basic_word_break_characters = v.encode(
|
97
|
+
@basic_word_break_characters = v.encode(encoding)
|
104
98
|
end
|
105
99
|
|
106
100
|
def completer_word_break_characters=(v)
|
107
|
-
@completer_word_break_characters = v.encode(
|
101
|
+
@completer_word_break_characters = v.encode(encoding)
|
108
102
|
end
|
109
103
|
|
110
104
|
def basic_quote_characters=(v)
|
111
|
-
@basic_quote_characters = v.encode(
|
105
|
+
@basic_quote_characters = v.encode(encoding)
|
112
106
|
end
|
113
107
|
|
114
108
|
def completer_quote_characters=(v)
|
115
|
-
@completer_quote_characters = v.encode(
|
109
|
+
@completer_quote_characters = v.encode(encoding)
|
116
110
|
end
|
117
111
|
|
118
112
|
def filename_quote_characters=(v)
|
119
|
-
@filename_quote_characters = v.encode(
|
113
|
+
@filename_quote_characters = v.encode(encoding)
|
120
114
|
end
|
121
115
|
|
122
116
|
def special_prefixes=(v)
|
123
|
-
@special_prefixes = v.encode(
|
117
|
+
@special_prefixes = v.encode(encoding)
|
124
118
|
end
|
125
119
|
|
126
120
|
def completion_case_fold=(v)
|
@@ -181,21 +175,15 @@ module Reline
|
|
181
175
|
|
182
176
|
def input=(val)
|
183
177
|
raise TypeError unless val.respond_to?(:getc) or val.nil?
|
184
|
-
if val.respond_to?(:getc)
|
185
|
-
|
186
|
-
Reline::ANSI.input = val
|
187
|
-
elsif Reline::IOGate == Reline::GeneralIO
|
188
|
-
Reline::GeneralIO.input = val
|
189
|
-
end
|
178
|
+
if val.respond_to?(:getc) && io_gate.respond_to?(:input=)
|
179
|
+
io_gate.input = val
|
190
180
|
end
|
191
181
|
end
|
192
182
|
|
193
183
|
def output=(val)
|
194
184
|
raise TypeError unless val.respond_to?(:write) or val.nil?
|
195
185
|
@output = val
|
196
|
-
|
197
|
-
Reline::ANSI.output = val
|
198
|
-
end
|
186
|
+
io_gate.output = val
|
199
187
|
end
|
200
188
|
|
201
189
|
def vi_editing_mode
|
@@ -217,37 +205,30 @@ module Reline
|
|
217
205
|
end
|
218
206
|
|
219
207
|
def get_screen_size
|
220
|
-
|
208
|
+
io_gate.get_screen_size
|
221
209
|
end
|
222
210
|
|
223
211
|
Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() {
|
224
212
|
# autocomplete
|
225
|
-
return
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
if
|
235
|
-
|
236
|
-
result.shift
|
237
|
-
pointer = completion_journey_data.pointer - 1
|
238
|
-
else
|
239
|
-
result = call_completion_proc_with_checking_args(pre, target, post)
|
240
|
-
pointer = nil
|
241
|
-
end
|
242
|
-
if result and result.size == 1 and result[0] == target and pointer != 0
|
243
|
-
result = nil
|
244
|
-
end
|
213
|
+
return unless config.autocompletion
|
214
|
+
|
215
|
+
journey_data = completion_journey_data
|
216
|
+
return unless journey_data
|
217
|
+
|
218
|
+
target = journey_data.list.first
|
219
|
+
completed = journey_data.list[journey_data.pointer]
|
220
|
+
result = journey_data.list.drop(1)
|
221
|
+
pointer = journey_data.pointer - 1
|
222
|
+
return if completed.empty? || (result == [completed] && pointer < 0)
|
223
|
+
|
245
224
|
target_width = Reline::Unicode.calculate_width(target)
|
246
|
-
|
247
|
-
if x
|
248
|
-
|
225
|
+
completed_width = Reline::Unicode.calculate_width(completed)
|
226
|
+
if cursor_pos.x <= completed_width - target_width
|
227
|
+
# When target is rendered on the line above cursor position
|
228
|
+
x = screen_width - completed_width
|
249
229
|
y = -1
|
250
230
|
else
|
231
|
+
x = [cursor_pos.x - completed_width, 0].max
|
251
232
|
y = 0
|
252
233
|
end
|
253
234
|
cursor_pos_to_render = Reline::CursorPos.new(x, y)
|
@@ -261,20 +242,20 @@ module Reline
|
|
261
242
|
contents: result,
|
262
243
|
scrollbar: true,
|
263
244
|
height: [15, preferred_dialog_height].min,
|
264
|
-
|
265
|
-
pointer_bg_color: 45,
|
266
|
-
fg_color: 37,
|
267
|
-
pointer_fg_color: 37
|
245
|
+
face: :completion_dialog
|
268
246
|
)
|
269
|
-
}
|
270
|
-
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
247
|
+
} # :nodoc:
|
248
|
+
Reline::DEFAULT_DIALOG_CONTEXT = Array.new # :nodoc:
|
271
249
|
|
272
250
|
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
|
273
|
-
|
251
|
+
@mutex.synchronize do
|
274
252
|
unless confirm_multiline_termination
|
275
253
|
raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
|
276
254
|
end
|
277
|
-
|
255
|
+
|
256
|
+
io_gate.with_raw_input do
|
257
|
+
inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
|
258
|
+
end
|
278
259
|
|
279
260
|
whole_buffer = line_editor.whole_buffer.dup
|
280
261
|
whole_buffer.taint if RUBY_VERSION < '2.7'
|
@@ -282,27 +263,36 @@ module Reline
|
|
282
263
|
Reline::HISTORY << whole_buffer
|
283
264
|
end
|
284
265
|
|
285
|
-
|
286
|
-
|
266
|
+
if line_editor.eof?
|
267
|
+
line_editor.reset_line
|
268
|
+
# Return nil if the input is aborted by C-d.
|
269
|
+
nil
|
270
|
+
else
|
271
|
+
whole_buffer
|
272
|
+
end
|
287
273
|
end
|
288
274
|
end
|
289
275
|
|
290
276
|
def readline(prompt = '', add_hist = false)
|
291
|
-
|
277
|
+
@mutex.synchronize do
|
278
|
+
io_gate.with_raw_input do
|
279
|
+
inner_readline(prompt, add_hist, false)
|
280
|
+
end
|
292
281
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
282
|
+
line = line_editor.line.dup
|
283
|
+
line.taint if RUBY_VERSION < '2.7'
|
284
|
+
if add_hist and line and line.chomp("\n").size > 0
|
285
|
+
Reline::HISTORY << line.chomp("\n")
|
286
|
+
end
|
298
287
|
|
299
|
-
|
300
|
-
|
288
|
+
line_editor.reset_line if line_editor.line.nil?
|
289
|
+
line
|
290
|
+
end
|
301
291
|
end
|
302
292
|
|
303
293
|
private def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination)
|
304
294
|
if ENV['RELINE_STDERR_TTY']
|
305
|
-
if
|
295
|
+
if io_gate.win?
|
306
296
|
$stderr = File.open(ENV['RELINE_STDERR_TTY'], 'a')
|
307
297
|
else
|
308
298
|
$stderr.reopen(ENV['RELINE_STDERR_TTY'], 'w')
|
@@ -310,10 +300,15 @@ module Reline
|
|
310
300
|
$stderr.sync = true
|
311
301
|
$stderr.puts "Reline is used by #{Process.pid}"
|
312
302
|
end
|
313
|
-
|
303
|
+
unless config.test_mode or config.loaded?
|
304
|
+
config.read
|
305
|
+
io_gate.set_default_key_bindings(config)
|
306
|
+
end
|
307
|
+
otio = io_gate.prep
|
314
308
|
|
315
309
|
may_req_ambiguous_char_width
|
316
|
-
|
310
|
+
key_stroke.encoding = encoding
|
311
|
+
line_editor.reset(prompt)
|
317
312
|
if multiline
|
318
313
|
line_editor.multiline_on
|
319
314
|
if block_given?
|
@@ -322,164 +317,89 @@ module Reline
|
|
322
317
|
else
|
323
318
|
line_editor.multiline_off
|
324
319
|
end
|
325
|
-
line_editor.output = output
|
326
320
|
line_editor.completion_proc = completion_proc
|
327
321
|
line_editor.completion_append_character = completion_append_character
|
328
322
|
line_editor.output_modifier_proc = output_modifier_proc
|
329
323
|
line_editor.prompt_proc = prompt_proc
|
330
324
|
line_editor.auto_indent_proc = auto_indent_proc
|
331
325
|
line_editor.dig_perfect_match_proc = dig_perfect_match_proc
|
332
|
-
line_editor.pre_input_hook = pre_input_hook
|
333
|
-
@dialog_proc_list.each_pair do |name_sym, d|
|
334
|
-
line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
|
335
|
-
end
|
336
326
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
327
|
+
pre_input_hook&.call
|
328
|
+
|
329
|
+
unless Reline::IOGate.dumb?
|
330
|
+
@dialog_proc_list.each_pair do |name_sym, d|
|
331
|
+
line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
|
332
|
+
end
|
341
333
|
end
|
342
334
|
|
335
|
+
line_editor.update_dialogs
|
343
336
|
line_editor.rerender
|
344
337
|
|
345
338
|
begin
|
346
339
|
line_editor.set_signal_handlers
|
347
|
-
prev_pasting_state = false
|
348
340
|
loop do
|
349
|
-
prev_pasting_state = Reline::IOGate.in_pasting?
|
350
341
|
read_io(config.keyseq_timeout) { |inputs|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
342
|
+
inputs.each do |key|
|
343
|
+
case key.method_symbol
|
344
|
+
when :bracketed_paste_start
|
345
|
+
# io_gate is Reline::ANSI because the key :bracketed_paste_start is only assigned in Reline::ANSI
|
346
|
+
key = Reline::Key.new(io_gate.read_bracketed_paste, :insert_multiline_text)
|
347
|
+
when :quoted_insert, :ed_quoted_insert
|
348
|
+
char = io_gate.read_single_char(config.keyseq_timeout.fdiv(1000))
|
349
|
+
key = Reline::Key.new(char || '', :insert_raw_char)
|
350
|
+
end
|
351
|
+
line_editor.set_pasting_state(io_gate.in_pasting?)
|
352
|
+
line_editor.update(key)
|
359
353
|
end
|
360
354
|
}
|
361
|
-
if
|
362
|
-
line_editor.
|
363
|
-
|
364
|
-
|
355
|
+
if line_editor.finished?
|
356
|
+
line_editor.render_finished
|
357
|
+
break
|
358
|
+
else
|
359
|
+
line_editor.rerender
|
365
360
|
end
|
366
|
-
break if line_editor.finished?
|
367
361
|
end
|
368
|
-
|
362
|
+
io_gate.move_cursor_column(0)
|
369
363
|
rescue Errno::EIO
|
370
364
|
# Maybe the I/O has been closed.
|
371
|
-
|
372
|
-
line_editor.finalize
|
373
|
-
Reline::IOGate.deprep(otio)
|
374
|
-
raise e
|
375
|
-
rescue Exception
|
376
|
-
# Including Interrupt
|
365
|
+
ensure
|
377
366
|
line_editor.finalize
|
378
|
-
|
379
|
-
raise
|
367
|
+
io_gate.deprep(otio)
|
380
368
|
end
|
381
|
-
|
382
|
-
line_editor.finalize
|
383
|
-
Reline::IOGate.deprep(otio)
|
384
369
|
end
|
385
370
|
|
386
|
-
# GNU Readline
|
387
|
-
#
|
388
|
-
#
|
389
|
-
#
|
390
|
-
#
|
391
|
-
#
|
392
|
-
#
|
393
|
-
# GNU Readline will wait for the 2nd character with "keyseq-timeout"
|
394
|
-
# milli-seconds but wait forever after 3rd characters.
|
371
|
+
# GNU Readline watis for "keyseq-timeout" milliseconds when the input is
|
372
|
+
# ambiguous whether it is matching or matched.
|
373
|
+
# If the next character does not arrive within the specified timeout, input
|
374
|
+
# is considered as matched.
|
375
|
+
# `ESC` is ambiguous because it can be a standalone ESC (matched) or part of
|
376
|
+
# `ESC char` or part of CSI sequence (matching).
|
395
377
|
private def read_io(keyseq_timeout, &block)
|
396
378
|
buffer = []
|
379
|
+
status = KeyStroke::MATCHING
|
397
380
|
loop do
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
buffer
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
when :matched
|
408
|
-
expanded = key_stroke.expand(buffer).map{ |expanded_c|
|
409
|
-
Reline::Key.new(expanded_c, expanded_c, false)
|
410
|
-
}
|
411
|
-
block.(expanded)
|
412
|
-
break
|
413
|
-
when :matching
|
414
|
-
if buffer.size == 1
|
415
|
-
case read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
|
416
|
-
when :break then break
|
417
|
-
when :next then next
|
418
|
-
end
|
419
|
-
end
|
420
|
-
when :unmatched
|
421
|
-
if buffer.size == 1 and c == "\e".ord
|
422
|
-
read_escaped_key(keyseq_timeout, c, block)
|
381
|
+
timeout = status == KeyStroke::MATCHING_MATCHED ? keyseq_timeout.fdiv(1000) : Float::INFINITY
|
382
|
+
c = io_gate.getc(timeout)
|
383
|
+
if c.nil? || c == -1
|
384
|
+
if status == KeyStroke::MATCHING_MATCHED
|
385
|
+
status = KeyStroke::MATCHED
|
386
|
+
elsif buffer.empty?
|
387
|
+
# io_gate is closed and reached EOF
|
388
|
+
block.call([Key.new(nil, nil, false)])
|
389
|
+
return
|
423
390
|
else
|
424
|
-
|
425
|
-
Reline::Key.new(expanded_c, expanded_c, false)
|
426
|
-
}
|
427
|
-
block.(expanded)
|
391
|
+
status = KeyStroke::UNMATCHED
|
428
392
|
end
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
end
|
433
|
-
|
434
|
-
private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
|
435
|
-
begin
|
436
|
-
succ_c = nil
|
437
|
-
Timeout.timeout(keyseq_timeout / 1000.0) {
|
438
|
-
succ_c = Reline::IOGate.getc
|
439
|
-
}
|
440
|
-
rescue Timeout::Error # cancel matching only when first byte
|
441
|
-
block.([Reline::Key.new(c, c, false)])
|
442
|
-
return :break
|
443
|
-
else
|
444
|
-
case key_stroke.match_status(buffer.dup.push(succ_c))
|
445
|
-
when :unmatched
|
446
|
-
if c == "\e".ord
|
447
|
-
block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
|
448
|
-
else
|
449
|
-
block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
|
450
|
-
end
|
451
|
-
return :break
|
452
|
-
when :matching
|
453
|
-
Reline::IOGate.ungetc(succ_c)
|
454
|
-
return :next
|
455
|
-
when :matched
|
456
|
-
buffer << succ_c
|
457
|
-
expanded = key_stroke.expand(buffer).map{ |expanded_c|
|
458
|
-
Reline::Key.new(expanded_c, expanded_c, false)
|
459
|
-
}
|
460
|
-
block.(expanded)
|
461
|
-
return :break
|
393
|
+
else
|
394
|
+
buffer << c
|
395
|
+
status = key_stroke.match_status(buffer)
|
462
396
|
end
|
463
|
-
end
|
464
|
-
end
|
465
397
|
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
}
|
472
|
-
rescue Timeout::Error # independent ESC
|
473
|
-
block.([Reline::Key.new(c, c, false)])
|
474
|
-
else
|
475
|
-
if escaped_c.nil?
|
476
|
-
block.([Reline::Key.new(c, c, false)])
|
477
|
-
elsif escaped_c >= 128 # maybe, first byte of multi byte
|
478
|
-
block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)])
|
479
|
-
elsif escaped_c == "\e".ord # escape twice
|
480
|
-
block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)])
|
481
|
-
else
|
482
|
-
block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
|
398
|
+
if status == KeyStroke::MATCHED || status == KeyStroke::UNMATCHED
|
399
|
+
expanded, rest_bytes = key_stroke.expand(buffer)
|
400
|
+
rest_bytes.reverse_each { |c| io_gate.ungetc(c) }
|
401
|
+
block.call(expanded)
|
402
|
+
return
|
483
403
|
end
|
484
404
|
end
|
485
405
|
end
|
@@ -490,19 +410,19 @@ module Reline
|
|
490
410
|
end
|
491
411
|
|
492
412
|
private def may_req_ambiguous_char_width
|
493
|
-
@ambiguous_width =
|
413
|
+
@ambiguous_width = 1 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
|
494
414
|
return if defined? @ambiguous_width
|
495
|
-
|
415
|
+
io_gate.move_cursor_column(0)
|
496
416
|
begin
|
497
417
|
output.write "\u{25bd}"
|
498
418
|
rescue Encoding::UndefinedConversionError
|
499
419
|
# LANG=C
|
500
420
|
@ambiguous_width = 1
|
501
421
|
else
|
502
|
-
@ambiguous_width =
|
422
|
+
@ambiguous_width = io_gate.cursor_pos.x == 2 ? 2 : 1
|
503
423
|
end
|
504
|
-
|
505
|
-
|
424
|
+
io_gate.move_cursor_column(0)
|
425
|
+
io_gate.erase_after_cursor
|
506
426
|
end
|
507
427
|
end
|
508
428
|
|
@@ -518,6 +438,17 @@ module Reline
|
|
518
438
|
}
|
519
439
|
def_single_delegators :core, :input=, :output=
|
520
440
|
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
|
441
|
+
|
442
|
+
##
|
443
|
+
# :singleton-method: readmultiline
|
444
|
+
# :call-seq:
|
445
|
+
# readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination) -> string or nil
|
446
|
+
def_single_delegators :core, :readmultiline
|
447
|
+
|
448
|
+
##
|
449
|
+
# :singleton-method: readline
|
450
|
+
# :call-seq:
|
451
|
+
# readline(prompt = '', add_hist = false) -> string or nil
|
521
452
|
def_single_delegators :core, :readline
|
522
453
|
def_single_delegators :core, :completion_case_fold, :completion_case_fold=
|
523
454
|
def_single_delegators :core, :completion_quote_character
|
@@ -538,8 +469,8 @@ module Reline
|
|
538
469
|
def_single_delegator :line_editor, :byte_pointer, :point
|
539
470
|
def_single_delegator :line_editor, :byte_pointer=, :point=
|
540
471
|
|
541
|
-
def self.insert_text(
|
542
|
-
line_editor.
|
472
|
+
def self.insert_text(text)
|
473
|
+
line_editor.insert_multiline_text(text)
|
543
474
|
self
|
544
475
|
end
|
545
476
|
|
@@ -553,19 +484,18 @@ module Reline
|
|
553
484
|
def_single_delegators :core, :dialog_proc
|
554
485
|
def_single_delegators :core, :autocompletion, :autocompletion=
|
555
486
|
|
556
|
-
def_single_delegators :core, :readmultiline
|
557
487
|
def_instance_delegators self, :readmultiline
|
558
488
|
private :readmultiline
|
559
489
|
|
560
|
-
def self.encoding_system_needs
|
490
|
+
def self.encoding_system_needs # :nodoc:
|
561
491
|
self.core.encoding
|
562
492
|
end
|
563
493
|
|
564
494
|
def self.core
|
565
495
|
@core ||= Core.new { |core|
|
566
496
|
core.config = Reline::Config.new
|
567
|
-
core.key_stroke = Reline::KeyStroke.new(core.config)
|
568
|
-
core.line_editor = Reline::LineEditor.new(core.config
|
497
|
+
core.key_stroke = Reline::KeyStroke.new(core.config, core.encoding)
|
498
|
+
core.line_editor = Reline::LineEditor.new(core.config)
|
569
499
|
|
570
500
|
core.basic_word_break_characters = " \t\n`><=;|&{("
|
571
501
|
core.completer_word_break_characters = " \t\n`><=;|&{("
|
@@ -578,7 +508,7 @@ module Reline
|
|
578
508
|
end
|
579
509
|
|
580
510
|
def self.ungetc(c)
|
581
|
-
|
511
|
+
core.io_gate.ungetc(c)
|
582
512
|
end
|
583
513
|
|
584
514
|
def self.line_editor
|
@@ -586,22 +516,12 @@ module Reline
|
|
586
516
|
end
|
587
517
|
end
|
588
518
|
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
else
|
597
|
-
tty = $stdout.tty?
|
598
|
-
end
|
599
|
-
end
|
600
|
-
Reline::IOGate = if tty
|
601
|
-
require 'reline/ansi'
|
602
|
-
Reline::ANSI
|
603
|
-
else
|
604
|
-
io
|
605
|
-
end
|
519
|
+
|
520
|
+
Reline::IOGate = Reline::IO.decide_io_gate
|
521
|
+
|
522
|
+
# Deprecated
|
523
|
+
Reline::GeneralIO = Reline::Dumb.new # :nodoc:
|
524
|
+
|
525
|
+
Reline::Face.load_initial_configs
|
606
526
|
|
607
527
|
Reline::HISTORY = Reline::History.new(Reline.core.config)
|