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.
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.3.5'
2
+ VERSION = '0.6.2'
3
3
  end
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/terminfo'
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
- Key = Struct.new('Key', :char, :combined_char, :with_meta) do
21
- def match?(other)
22
- case other
23
- when Reline::Key
24
- (other.char.nil? or char.nil? or char == other.char) and
25
- (other.combined_char.nil? or combined_char.nil? or combined_char == other.combined_char) and
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
- alias_method :==, :match?
35
- end
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
- :bg_color,
41
- :pointer_bg_color,
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
- @bracketed_paste_finished = false
74
+ end
75
+
76
+ def io_gate
77
+ Reline::IOGate
84
78
  end
85
79
 
86
80
  def encoding
87
- Reline::IOGate.encoding
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(Reline::IOGate.encoding)
88
+ @completion_append_character = val.encode(encoding)
95
89
  elsif val.size > 1
96
- @completion_append_character = val[0].encode(Reline::IOGate.encoding)
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(Reline::IOGate.encoding)
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(Reline::IOGate.encoding)
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(Reline::IOGate.encoding)
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(Reline::IOGate.encoding)
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(Reline::IOGate.encoding)
113
+ @filename_quote_characters = v.encode(encoding)
120
114
  end
121
115
 
122
116
  def special_prefixes=(v)
123
- @special_prefixes = v.encode(Reline::IOGate.encoding)
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
- if defined?(Reline::ANSI) and Reline::IOGate == Reline::ANSI
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
- if defined?(Reline::ANSI) and Reline::IOGate == Reline::ANSI
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
- Reline::IOGate.get_screen_size
208
+ io_gate.get_screen_size
221
209
  end
222
210
 
223
211
  Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() {
224
212
  # autocomplete
225
- return nil unless config.autocompletion
226
- if just_cursor_moving and completion_journey_data.nil?
227
- # Auto complete starts only when edited
228
- return nil
229
- end
230
- pre, target, post = retrieve_completion_block(true)
231
- if target.nil? or target.empty? or (completion_journey_data&.pointer == -1 and target.size <= 3)
232
- return nil
233
- end
234
- if completion_journey_data and completion_journey_data.list
235
- result = completion_journey_data.list.dup
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
- x = cursor_pos.x - target_width
247
- if x < 0
248
- x = screen_width + x
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
- bg_color: 46,
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
- Reline::IOGate.with_raw_input do
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
- inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
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
- line_editor.reset_line if line_editor.whole_buffer.nil?
286
- whole_buffer
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
- inner_readline(prompt, add_hist, false)
277
+ @mutex.synchronize do
278
+ io_gate.with_raw_input do
279
+ inner_readline(prompt, add_hist, false)
280
+ end
292
281
 
293
- line = line_editor.line.dup
294
- line.taint if RUBY_VERSION < '2.7'
295
- if add_hist and line and line.chomp("\n").size > 0
296
- Reline::HISTORY << line.chomp("\n")
297
- end
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
- line_editor.reset_line if line_editor.line.nil?
300
- line
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 Reline::IOGate.win?
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
- otio = Reline::IOGate.prep
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
- line_editor.reset(prompt, encoding: Reline::IOGate.encoding)
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
- unless config.test_mode
338
- config.read
339
- config.reset_default_key_bindings
340
- Reline::IOGate.set_default_key_bindings(config)
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
- line_editor.set_pasting_state(Reline::IOGate.in_pasting?)
352
- inputs.each { |c|
353
- line_editor.input_key(c)
354
- line_editor.rerender
355
- }
356
- if @bracketed_paste_finished
357
- line_editor.rerender_all
358
- @bracketed_paste_finished = false
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 prev_pasting_state == true and not Reline::IOGate.in_pasting? and not line_editor.finished?
362
- line_editor.set_pasting_state(false)
363
- prev_pasting_state = false
364
- line_editor.rerender_all
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
- Reline::IOGate.move_cursor_column(0)
362
+ io_gate.move_cursor_column(0)
369
363
  rescue Errno::EIO
370
364
  # Maybe the I/O has been closed.
371
- rescue StandardError => e
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
- Reline::IOGate.deprep(otio)
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 waits for "keyseq-timeout" milliseconds to see if the ESC
387
- # is followed by a character, and times out and treats it as a standalone
388
- # ESC if the second character does not arrive. If the second character
389
- # comes before timed out, it is treated as a modifier key with the
390
- # meta-property of meta-key, so that it can be distinguished from
391
- # multibyte characters with the 8th bit turned on.
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
- c = Reline::IOGate.getc
399
- if c == -1
400
- result = :unmatched
401
- @bracketed_paste_finished = true
402
- else
403
- buffer << c
404
- result = key_stroke.match_status(buffer)
405
- end
406
- case result
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
- expanded = buffer.map{ |expanded_c|
425
- Reline::Key.new(expanded_c, expanded_c, false)
426
- }
427
- block.(expanded)
391
+ status = KeyStroke::UNMATCHED
428
392
  end
429
- break
430
- end
431
- end
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
- private def read_escaped_key(keyseq_timeout, c, block)
467
- begin
468
- escaped_c = nil
469
- Timeout.timeout(keyseq_timeout / 1000.0) {
470
- escaped_c = Reline::IOGate.getc
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 = 2 if Reline::IOGate == Reline::GeneralIO or !STDOUT.tty?
413
+ @ambiguous_width = 1 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
494
414
  return if defined? @ambiguous_width
495
- Reline::IOGate.move_cursor_column(0)
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 = Reline::IOGate.cursor_pos.x
422
+ @ambiguous_width = io_gate.cursor_pos.x == 2 ? 2 : 1
503
423
  end
504
- Reline::IOGate.move_cursor_column(0)
505
- Reline::IOGate.erase_after_cursor
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(*args, &block)
542
- line_editor.insert_text(*args, &block)
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, Reline::IOGate.encoding)
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
- Reline::IOGate.ungetc(c)
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
- require 'reline/general_io'
590
- io = Reline::GeneralIO
591
- unless ENV['TERM'] == 'dumb'
592
- case RbConfig::CONFIG['host_os']
593
- when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
594
- require 'reline/windows'
595
- tty = (io = Reline::Windows).msys_tty?
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)