reline 0.3.2 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
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'
@@ -8,38 +7,29 @@ require 'reline/key_stroke'
8
7
  require 'reline/line_editor'
9
8
  require 'reline/history'
10
9
  require 'reline/terminfo'
10
+ require 'reline/io'
11
+ require 'reline/face'
11
12
  require 'rbconfig'
12
13
 
13
14
  module Reline
15
+ # NOTE: For making compatible with the rb-readline gem
14
16
  FILENAME_COMPLETION_PROC = nil
15
17
  USERNAME_COMPLETION_PROC = nil
16
18
 
17
19
  class ConfigEncodingConversionError < StandardError; end
18
20
 
19
- Key = Struct.new('Key', :char, :combined_char, :with_meta) do
20
- def match?(other)
21
- case other
22
- when Reline::Key
23
- (other.char.nil? or char.nil? or char == other.char) and
24
- (other.combined_char.nil? or combined_char.nil? or combined_char == other.combined_char) and
25
- (other.with_meta.nil? or with_meta.nil? or with_meta == other.with_meta)
26
- when Integer, Symbol
27
- (combined_char and combined_char == other) or
28
- (combined_char.nil? and char and char == other)
29
- else
30
- false
31
- end
21
+ Key = Struct.new(:char, :combined_char, :with_meta) do
22
+ # For dialog_proc `key.match?(dialog.name)`
23
+ def match?(sym)
24
+ combined_char.is_a?(Symbol) && combined_char == sym
32
25
  end
33
- alias_method :==, :match?
34
26
  end
35
27
  CursorPos = Struct.new(:x, :y)
36
28
  DialogRenderInfo = Struct.new(
37
29
  :pos,
38
30
  :contents,
39
- :bg_color,
40
- :pointer_bg_color,
41
- :fg_color,
42
- :pointer_fg_color,
31
+ :face,
32
+ :bg_color, # For the time being, this line should stay here for the compatibility with IRB.
43
33
  :width,
44
34
  :height,
45
35
  :scrollbar,
@@ -76,50 +66,54 @@ module Reline
76
66
 
77
67
  def initialize
78
68
  self.output = STDOUT
69
+ @mutex = Mutex.new
79
70
  @dialog_proc_list = {}
80
71
  yield self
81
72
  @completion_quote_character = nil
82
- @bracketed_paste_finished = false
73
+ end
74
+
75
+ def io_gate
76
+ Reline::IOGate
83
77
  end
84
78
 
85
79
  def encoding
86
- Reline::IOGate.encoding
80
+ io_gate.encoding
87
81
  end
88
82
 
89
83
  def completion_append_character=(val)
90
84
  if val.nil?
91
85
  @completion_append_character = nil
92
86
  elsif val.size == 1
93
- @completion_append_character = val.encode(Reline::IOGate.encoding)
87
+ @completion_append_character = val.encode(encoding)
94
88
  elsif val.size > 1
95
- @completion_append_character = val[0].encode(Reline::IOGate.encoding)
89
+ @completion_append_character = val[0].encode(encoding)
96
90
  else
97
91
  @completion_append_character = nil
98
92
  end
99
93
  end
100
94
 
101
95
  def basic_word_break_characters=(v)
102
- @basic_word_break_characters = v.encode(Reline::IOGate.encoding)
96
+ @basic_word_break_characters = v.encode(encoding)
103
97
  end
104
98
 
105
99
  def completer_word_break_characters=(v)
106
- @completer_word_break_characters = v.encode(Reline::IOGate.encoding)
100
+ @completer_word_break_characters = v.encode(encoding)
107
101
  end
108
102
 
109
103
  def basic_quote_characters=(v)
110
- @basic_quote_characters = v.encode(Reline::IOGate.encoding)
104
+ @basic_quote_characters = v.encode(encoding)
111
105
  end
112
106
 
113
107
  def completer_quote_characters=(v)
114
- @completer_quote_characters = v.encode(Reline::IOGate.encoding)
108
+ @completer_quote_characters = v.encode(encoding)
115
109
  end
116
110
 
117
111
  def filename_quote_characters=(v)
118
- @filename_quote_characters = v.encode(Reline::IOGate.encoding)
112
+ @filename_quote_characters = v.encode(encoding)
119
113
  end
120
114
 
121
115
  def special_prefixes=(v)
122
- @special_prefixes = v.encode(Reline::IOGate.encoding)
116
+ @special_prefixes = v.encode(encoding)
123
117
  end
124
118
 
125
119
  def completion_case_fold=(v)
@@ -165,9 +159,13 @@ module Reline
165
159
 
166
160
  DialogProc = Struct.new(:dialog_proc, :context)
167
161
  def add_dialog_proc(name_sym, p, context = nil)
168
- raise ArgumentError unless p.respond_to?(:call) or p.nil?
169
162
  raise ArgumentError unless name_sym.instance_of?(Symbol)
170
- @dialog_proc_list[name_sym] = DialogProc.new(p, context)
163
+ if p.nil?
164
+ @dialog_proc_list.delete(name_sym)
165
+ else
166
+ raise ArgumentError unless p.respond_to?(:call)
167
+ @dialog_proc_list[name_sym] = DialogProc.new(p, context)
168
+ end
171
169
  end
172
170
 
173
171
  def dialog_proc(name_sym)
@@ -176,20 +174,16 @@ module Reline
176
174
 
177
175
  def input=(val)
178
176
  raise TypeError unless val.respond_to?(:getc) or val.nil?
179
- if val.respond_to?(:getc)
180
- if defined?(Reline::ANSI) and Reline::IOGate == Reline::ANSI
181
- Reline::ANSI.input = val
182
- elsif Reline::IOGate == Reline::GeneralIO
183
- Reline::GeneralIO.input = val
184
- end
177
+ if val.respond_to?(:getc) && io_gate.respond_to?(:input=)
178
+ io_gate.input = val
185
179
  end
186
180
  end
187
181
 
188
182
  def output=(val)
189
183
  raise TypeError unless val.respond_to?(:write) or val.nil?
190
184
  @output = val
191
- if defined?(Reline::ANSI) and Reline::IOGate == Reline::ANSI
192
- Reline::ANSI.output = val
185
+ if io_gate.respond_to?(:output=)
186
+ io_gate.output = val
193
187
  end
194
188
  end
195
189
 
@@ -212,37 +206,30 @@ module Reline
212
206
  end
213
207
 
214
208
  def get_screen_size
215
- Reline::IOGate.get_screen_size
209
+ io_gate.get_screen_size
216
210
  end
217
211
 
218
212
  Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() {
219
213
  # autocomplete
220
- return nil unless config.autocompletion
221
- if just_cursor_moving and completion_journey_data.nil?
222
- # Auto complete starts only when edited
223
- return nil
224
- end
225
- pre, target, post = retrieve_completion_block(true)
226
- if target.nil? or target.empty? or (completion_journey_data&.pointer == -1 and target.size <= 3)
227
- return nil
228
- end
229
- if completion_journey_data and completion_journey_data.list
230
- result = completion_journey_data.list.dup
231
- result.shift
232
- pointer = completion_journey_data.pointer - 1
233
- else
234
- result = call_completion_proc_with_checking_args(pre, target, post)
235
- pointer = nil
236
- end
237
- if result and result.size == 1 and result[0] == target and pointer != 0
238
- result = nil
239
- end
214
+ return unless config.autocompletion
215
+
216
+ journey_data = completion_journey_data
217
+ return unless journey_data
218
+
219
+ target = journey_data.list.first
220
+ completed = journey_data.list[journey_data.pointer]
221
+ result = journey_data.list.drop(1)
222
+ pointer = journey_data.pointer - 1
223
+ return if completed.empty? || (result == [completed] && pointer < 0)
224
+
240
225
  target_width = Reline::Unicode.calculate_width(target)
241
- x = cursor_pos.x - target_width
242
- if x < 0
243
- x = screen_width + x
226
+ completed_width = Reline::Unicode.calculate_width(completed)
227
+ if cursor_pos.x <= completed_width - target_width
228
+ # When target is rendered on the line above cursor position
229
+ x = screen_width - completed_width
244
230
  y = -1
245
231
  else
232
+ x = [cursor_pos.x - completed_width, 0].max
246
233
  y = 0
247
234
  end
248
235
  cursor_pos_to_render = Reline::CursorPos.new(x, y)
@@ -255,47 +242,58 @@ module Reline
255
242
  pos: cursor_pos_to_render,
256
243
  contents: result,
257
244
  scrollbar: true,
258
- height: 15,
259
- bg_color: 46,
260
- pointer_bg_color: 45,
261
- fg_color: 37,
262
- pointer_fg_color: 37
245
+ height: [15, preferred_dialog_height].min,
246
+ face: :completion_dialog
263
247
  )
264
248
  }
265
249
  Reline::DEFAULT_DIALOG_CONTEXT = Array.new
266
250
 
267
251
  def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
268
- unless confirm_multiline_termination
269
- raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
270
- end
271
- inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
252
+ @mutex.synchronize do
253
+ unless confirm_multiline_termination
254
+ raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
255
+ end
272
256
 
273
- whole_buffer = line_editor.whole_buffer.dup
274
- whole_buffer.taint if RUBY_VERSION < '2.7'
275
- if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
276
- Reline::HISTORY << whole_buffer
277
- end
257
+ io_gate.with_raw_input do
258
+ inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
259
+ end
260
+
261
+ whole_buffer = line_editor.whole_buffer.dup
262
+ whole_buffer.taint if RUBY_VERSION < '2.7'
263
+ if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
264
+ Reline::HISTORY << whole_buffer
265
+ end
278
266
 
279
- line_editor.reset_line if line_editor.whole_buffer.nil?
280
- whole_buffer
267
+ if line_editor.eof?
268
+ line_editor.reset_line
269
+ # Return nil if the input is aborted by C-d.
270
+ nil
271
+ else
272
+ whole_buffer
273
+ end
274
+ end
281
275
  end
282
276
 
283
277
  def readline(prompt = '', add_hist = false)
284
- inner_readline(prompt, add_hist, false)
278
+ @mutex.synchronize do
279
+ io_gate.with_raw_input do
280
+ inner_readline(prompt, add_hist, false)
281
+ end
285
282
 
286
- line = line_editor.line.dup
287
- line.taint if RUBY_VERSION < '2.7'
288
- if add_hist and line and line.chomp("\n").size > 0
289
- Reline::HISTORY << line.chomp("\n")
290
- end
283
+ line = line_editor.line.dup
284
+ line.taint if RUBY_VERSION < '2.7'
285
+ if add_hist and line and line.chomp("\n").size > 0
286
+ Reline::HISTORY << line.chomp("\n")
287
+ end
291
288
 
292
- line_editor.reset_line if line_editor.line.nil?
293
- line
289
+ line_editor.reset_line if line_editor.line.nil?
290
+ line
291
+ end
294
292
  end
295
293
 
296
294
  private def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination)
297
295
  if ENV['RELINE_STDERR_TTY']
298
- if Reline::IOGate.win?
296
+ if io_gate.win?
299
297
  $stderr = File.open(ENV['RELINE_STDERR_TTY'], 'a')
300
298
  else
301
299
  $stderr.reopen(ENV['RELINE_STDERR_TTY'], 'w')
@@ -303,10 +301,14 @@ module Reline
303
301
  $stderr.sync = true
304
302
  $stderr.puts "Reline is used by #{Process.pid}"
305
303
  end
306
- otio = Reline::IOGate.prep
304
+ unless config.test_mode or config.loaded?
305
+ config.read
306
+ io_gate.set_default_key_bindings(config)
307
+ end
308
+ otio = io_gate.prep
307
309
 
308
310
  may_req_ambiguous_char_width
309
- line_editor.reset(prompt, encoding: Reline::IOGate.encoding)
311
+ line_editor.reset(prompt, encoding: encoding)
310
312
  if multiline
311
313
  line_editor.multiline_on
312
314
  if block_given?
@@ -322,157 +324,81 @@ module Reline
322
324
  line_editor.prompt_proc = prompt_proc
323
325
  line_editor.auto_indent_proc = auto_indent_proc
324
326
  line_editor.dig_perfect_match_proc = dig_perfect_match_proc
325
- line_editor.pre_input_hook = pre_input_hook
326
- @dialog_proc_list.each_pair do |name_sym, d|
327
- line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
328
- end
329
-
330
- unless config.test_mode
331
- config.read
332
- config.reset_default_key_bindings
333
- Reline::IOGate.set_default_key_bindings(config)
327
+ pre_input_hook&.call
328
+ unless Reline::IOGate.dumb?
329
+ @dialog_proc_list.each_pair do |name_sym, d|
330
+ line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
331
+ end
334
332
  end
335
333
 
334
+ line_editor.print_nomultiline_prompt(prompt)
335
+ line_editor.update_dialogs
336
336
  line_editor.rerender
337
337
 
338
338
  begin
339
339
  line_editor.set_signal_handlers
340
- prev_pasting_state = false
341
340
  loop do
342
- prev_pasting_state = Reline::IOGate.in_pasting?
343
341
  read_io(config.keyseq_timeout) { |inputs|
344
- line_editor.set_pasting_state(Reline::IOGate.in_pasting?)
345
- inputs.each { |c|
346
- line_editor.input_key(c)
347
- line_editor.rerender
348
- }
349
- if @bracketed_paste_finished
350
- line_editor.rerender_all
351
- @bracketed_paste_finished = false
342
+ line_editor.set_pasting_state(io_gate.in_pasting?)
343
+ inputs.each do |key|
344
+ if key.char == :bracketed_paste_start
345
+ text = io_gate.read_bracketed_paste
346
+ line_editor.insert_pasted_text(text)
347
+ line_editor.scroll_into_view
348
+ else
349
+ line_editor.update(key)
350
+ end
352
351
  end
353
352
  }
354
- if prev_pasting_state == true and not Reline::IOGate.in_pasting? and not line_editor.finished?
355
- line_editor.set_pasting_state(false)
356
- prev_pasting_state = false
357
- line_editor.rerender_all
353
+ if line_editor.finished?
354
+ line_editor.render_finished
355
+ break
356
+ else
357
+ line_editor.set_pasting_state(io_gate.in_pasting?)
358
+ line_editor.rerender
358
359
  end
359
- break if line_editor.finished?
360
360
  end
361
- Reline::IOGate.move_cursor_column(0)
361
+ io_gate.move_cursor_column(0)
362
362
  rescue Errno::EIO
363
363
  # Maybe the I/O has been closed.
364
- rescue StandardError => e
364
+ ensure
365
365
  line_editor.finalize
366
- Reline::IOGate.deprep(otio)
367
- raise e
368
- rescue Exception
369
- # Including Interrupt
370
- line_editor.finalize
371
- Reline::IOGate.deprep(otio)
372
- raise
366
+ io_gate.deprep(otio)
373
367
  end
374
-
375
- line_editor.finalize
376
- Reline::IOGate.deprep(otio)
377
368
  end
378
369
 
379
- # GNU Readline waits for "keyseq-timeout" milliseconds to see if the ESC
380
- # is followed by a character, and times out and treats it as a standalone
381
- # ESC if the second character does not arrive. If the second character
382
- # comes before timed out, it is treated as a modifier key with the
383
- # meta-property of meta-key, so that it can be distinguished from
384
- # multibyte characters with the 8th bit turned on.
385
- #
386
- # GNU Readline will wait for the 2nd character with "keyseq-timeout"
387
- # milli-seconds but wait forever after 3rd characters.
370
+ # GNU Readline watis for "keyseq-timeout" milliseconds when the input is
371
+ # ambiguous whether it is matching or matched.
372
+ # If the next character does not arrive within the specified timeout, input
373
+ # is considered as matched.
374
+ # `ESC` is ambiguous because it can be a standalone ESC (matched) or part of
375
+ # `ESC char` or part of CSI sequence (matching).
388
376
  private def read_io(keyseq_timeout, &block)
389
377
  buffer = []
378
+ status = KeyStroke::MATCHING
390
379
  loop do
391
- c = Reline::IOGate.getc
392
- if c == -1
393
- result = :unmatched
394
- @bracketed_paste_finished = true
395
- else
396
- buffer << c
397
- result = key_stroke.match_status(buffer)
398
- end
399
- case result
400
- when :matched
401
- expanded = key_stroke.expand(buffer).map{ |expanded_c|
402
- Reline::Key.new(expanded_c, expanded_c, false)
403
- }
404
- block.(expanded)
405
- break
406
- when :matching
407
- if buffer.size == 1
408
- case read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
409
- when :break then break
410
- when :next then next
411
- end
412
- end
413
- when :unmatched
414
- if buffer.size == 1 and c == "\e".ord
415
- read_escaped_key(keyseq_timeout, c, block)
380
+ timeout = status == KeyStroke::MATCHING_MATCHED ? keyseq_timeout.fdiv(1000) : Float::INFINITY
381
+ c = io_gate.getc(timeout)
382
+ if c.nil? || c == -1
383
+ if status == KeyStroke::MATCHING_MATCHED
384
+ status = KeyStroke::MATCHED
385
+ elsif buffer.empty?
386
+ # io_gate is closed and reached EOF
387
+ block.call([Key.new(nil, nil, false)])
388
+ return
416
389
  else
417
- expanded = buffer.map{ |expanded_c|
418
- Reline::Key.new(expanded_c, expanded_c, false)
419
- }
420
- block.(expanded)
390
+ status = KeyStroke::UNMATCHED
421
391
  end
422
- break
423
- end
424
- end
425
- end
426
-
427
- private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
428
- begin
429
- succ_c = nil
430
- Timeout.timeout(keyseq_timeout / 1000.0) {
431
- succ_c = Reline::IOGate.getc
432
- }
433
- rescue Timeout::Error # cancel matching only when first byte
434
- block.([Reline::Key.new(c, c, false)])
435
- return :break
436
- else
437
- case key_stroke.match_status(buffer.dup.push(succ_c))
438
- when :unmatched
439
- if c == "\e".ord
440
- block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
441
- else
442
- block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
443
- end
444
- return :break
445
- when :matching
446
- Reline::IOGate.ungetc(succ_c)
447
- return :next
448
- when :matched
449
- buffer << succ_c
450
- expanded = key_stroke.expand(buffer).map{ |expanded_c|
451
- Reline::Key.new(expanded_c, expanded_c, false)
452
- }
453
- block.(expanded)
454
- return :break
392
+ else
393
+ buffer << c
394
+ status = key_stroke.match_status(buffer)
455
395
  end
456
- end
457
- end
458
396
 
459
- private def read_escaped_key(keyseq_timeout, c, block)
460
- begin
461
- escaped_c = nil
462
- Timeout.timeout(keyseq_timeout / 1000.0) {
463
- escaped_c = Reline::IOGate.getc
464
- }
465
- rescue Timeout::Error # independent ESC
466
- block.([Reline::Key.new(c, c, false)])
467
- else
468
- if escaped_c.nil?
469
- block.([Reline::Key.new(c, c, false)])
470
- elsif escaped_c >= 128 # maybe, first byte of multi byte
471
- block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)])
472
- elsif escaped_c == "\e".ord # escape twice
473
- block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)])
474
- else
475
- block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
397
+ if status == KeyStroke::MATCHED || status == KeyStroke::UNMATCHED
398
+ expanded, rest_bytes = key_stroke.expand(buffer)
399
+ rest_bytes.reverse_each { |c| io_gate.ungetc(c) }
400
+ block.call(expanded)
401
+ return
476
402
  end
477
403
  end
478
404
  end
@@ -483,19 +409,19 @@ module Reline
483
409
  end
484
410
 
485
411
  private def may_req_ambiguous_char_width
486
- @ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or !STDOUT.tty?
412
+ @ambiguous_width = 2 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
487
413
  return if defined? @ambiguous_width
488
- Reline::IOGate.move_cursor_column(0)
414
+ io_gate.move_cursor_column(0)
489
415
  begin
490
416
  output.write "\u{25bd}"
491
417
  rescue Encoding::UndefinedConversionError
492
418
  # LANG=C
493
419
  @ambiguous_width = 1
494
420
  else
495
- @ambiguous_width = Reline::IOGate.cursor_pos.x
421
+ @ambiguous_width = io_gate.cursor_pos.x
496
422
  end
497
- Reline::IOGate.move_cursor_column(0)
498
- Reline::IOGate.erase_after_cursor
423
+ io_gate.move_cursor_column(0)
424
+ io_gate.erase_after_cursor
499
425
  end
500
426
  end
501
427
 
@@ -558,7 +484,7 @@ module Reline
558
484
  @core ||= Core.new { |core|
559
485
  core.config = Reline::Config.new
560
486
  core.key_stroke = Reline::KeyStroke.new(core.config)
561
- core.line_editor = Reline::LineEditor.new(core.config, Reline::IOGate.encoding)
487
+ core.line_editor = Reline::LineEditor.new(core.config, core.encoding)
562
488
 
563
489
  core.basic_word_break_characters = " \t\n`><=;|&{("
564
490
  core.completer_word_break_characters = " \t\n`><=;|&{("
@@ -571,7 +497,7 @@ module Reline
571
497
  end
572
498
 
573
499
  def self.ungetc(c)
574
- Reline::IOGate.ungetc(c)
500
+ core.io_gate.ungetc(c)
575
501
  end
576
502
 
577
503
  def self.line_editor
@@ -579,22 +505,12 @@ module Reline
579
505
  end
580
506
  end
581
507
 
582
- require 'reline/general_io'
583
- io = Reline::GeneralIO
584
- unless ENV['TERM'] == 'dumb'
585
- case RbConfig::CONFIG['host_os']
586
- when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
587
- require 'reline/windows'
588
- tty = (io = Reline::Windows).msys_tty?
589
- else
590
- tty = $stdout.tty?
591
- end
592
- end
593
- Reline::IOGate = if tty
594
- require 'reline/ansi'
595
- Reline::ANSI
596
- else
597
- io
598
- end
508
+
509
+ Reline::IOGate = Reline::IO.decide_io_gate
510
+
511
+ # Deprecated
512
+ Reline::GeneralIO = Reline::Dumb.new
513
+
514
+ Reline::Face.load_initial_configs
599
515
 
600
516
  Reline::HISTORY = Reline::History.new(Reline.core.config)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-14 00:00:00.000000000 Z
11
+ date: 2024-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console
@@ -35,12 +35,16 @@ files:
35
35
  - COPYING
36
36
  - README.md
37
37
  - lib/reline.rb
38
- - lib/reline/ansi.rb
39
38
  - lib/reline/config.rb
40
- - lib/reline/general_io.rb
39
+ - lib/reline/face.rb
41
40
  - lib/reline/history.rb
41
+ - lib/reline/io.rb
42
+ - lib/reline/io/ansi.rb
43
+ - lib/reline/io/dumb.rb
44
+ - lib/reline/io/windows.rb
42
45
  - lib/reline/key_actor.rb
43
46
  - lib/reline/key_actor/base.rb
47
+ - lib/reline/key_actor/composite.rb
44
48
  - lib/reline/key_actor/emacs.rb
45
49
  - lib/reline/key_actor/vi_command.rb
46
50
  - lib/reline/key_actor/vi_insert.rb
@@ -51,12 +55,14 @@ files:
51
55
  - lib/reline/unicode.rb
52
56
  - lib/reline/unicode/east_asian_width.rb
53
57
  - lib/reline/version.rb
54
- - lib/reline/windows.rb
55
58
  - license_of_rb-readline
56
59
  homepage: https://github.com/ruby/reline
57
60
  licenses:
58
61
  - Ruby
59
- metadata: {}
62
+ metadata:
63
+ bug_tracker_uri: https://github.com/ruby/reline/issues
64
+ changelog_uri: https://github.com/ruby/reline/releases
65
+ source_code_uri: https://github.com/ruby/reline
60
66
  post_install_message:
61
67
  rdoc_options: []
62
68
  require_paths:
@@ -72,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
78
  - !ruby/object:Gem::Version
73
79
  version: '0'
74
80
  requirements: []
75
- rubygems_version: 3.4.0.dev
81
+ rubygems_version: 3.5.9
76
82
  signing_key:
77
83
  specification_version: 4
78
84
  summary: Alternative GNU Readline or Editline implementation by pure Ruby.