reline 0.5.7 → 0.5.9

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.
data/lib/reline.rb CHANGED
@@ -7,6 +7,7 @@ require 'reline/key_stroke'
7
7
  require 'reline/line_editor'
8
8
  require 'reline/history'
9
9
  require 'reline/terminfo'
10
+ require 'reline/io'
10
11
  require 'reline/face'
11
12
  require 'rbconfig'
12
13
 
@@ -18,20 +19,10 @@ module Reline
18
19
  class ConfigEncodingConversionError < StandardError; end
19
20
 
20
21
  Key = Struct.new(: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
22
+ # For dialog_proc `key.match?(dialog.name)`
23
+ def match?(sym)
24
+ combined_char.is_a?(Symbol) && combined_char == sym
33
25
  end
34
- alias_method :==, :match?
35
26
  end
36
27
  CursorPos = Struct.new(:x, :y)
37
28
  DialogRenderInfo = Struct.new(
@@ -263,7 +254,6 @@ module Reline
263
254
  raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
264
255
  end
265
256
 
266
- Reline.update_iogate
267
257
  io_gate.with_raw_input do
268
258
  inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
269
259
  end
@@ -286,7 +276,6 @@ module Reline
286
276
 
287
277
  def readline(prompt = '', add_hist = false)
288
278
  @mutex.synchronize do
289
- Reline.update_iogate
290
279
  io_gate.with_raw_input do
291
280
  inner_readline(prompt, add_hist, false)
292
281
  end
@@ -336,7 +325,7 @@ module Reline
336
325
  line_editor.auto_indent_proc = auto_indent_proc
337
326
  line_editor.dig_perfect_match_proc = dig_perfect_match_proc
338
327
  pre_input_hook&.call
339
- unless Reline::IOGate == Reline::GeneralIO
328
+ unless Reline::IOGate.dumb?
340
329
  @dialog_proc_list.each_pair do |name_sym, d|
341
330
  line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
342
331
  end
@@ -378,92 +367,39 @@ module Reline
378
367
  end
379
368
  end
380
369
 
381
- # GNU Readline waits for "keyseq-timeout" milliseconds to see if the ESC
382
- # is followed by a character, and times out and treats it as a standalone
383
- # ESC if the second character does not arrive. If the second character
384
- # comes before timed out, it is treated as a modifier key with the
385
- # meta-property of meta-key, so that it can be distinguished from
386
- # multibyte characters with the 8th bit turned on.
387
- #
388
- # GNU Readline will wait for the 2nd character with "keyseq-timeout"
389
- # 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).
390
376
  private def read_io(keyseq_timeout, &block)
391
377
  buffer = []
378
+ status = KeyStroke::MATCHING
392
379
  loop do
393
- c = io_gate.getc(Float::INFINITY)
394
- if c == -1
395
- result = :unmatched
396
- else
397
- buffer << c
398
- result = key_stroke.match_status(buffer)
399
- end
400
- case result
401
- when :matched
402
- expanded = key_stroke.expand(buffer).map{ |expanded_c|
403
- Reline::Key.new(expanded_c, expanded_c, false)
404
- }
405
- block.(expanded)
406
- break
407
- when :matching
408
- if buffer.size == 1
409
- case read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
410
- when :break then break
411
- when :next then next
412
- end
413
- end
414
- when :unmatched
415
- if buffer.size == 1 and c == "\e".ord
416
- 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
417
389
  else
418
- expanded = buffer.map{ |expanded_c|
419
- Reline::Key.new(expanded_c, expanded_c, false)
420
- }
421
- block.(expanded)
390
+ status = KeyStroke::UNMATCHED
422
391
  end
423
- break
392
+ else
393
+ buffer << c
394
+ status = key_stroke.match_status(buffer)
424
395
  end
425
- end
426
- end
427
396
 
428
- private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
429
- succ_c = io_gate.getc(keyseq_timeout.fdiv(1000))
430
- if succ_c
431
- case key_stroke.match_status(buffer.dup.push(succ_c))
432
- when :unmatched
433
- if c == "\e".ord
434
- block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
435
- else
436
- block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
437
- end
438
- return :break
439
- when :matching
440
- io_gate.ungetc(succ_c)
441
- return :next
442
- when :matched
443
- buffer << succ_c
444
- expanded = key_stroke.expand(buffer).map{ |expanded_c|
445
- Reline::Key.new(expanded_c, expanded_c, false)
446
- }
447
- block.(expanded)
448
- return :break
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
449
402
  end
450
- else
451
- block.([Reline::Key.new(c, c, false)])
452
- return :break
453
- end
454
- end
455
-
456
- private def read_escaped_key(keyseq_timeout, c, block)
457
- escaped_c = io_gate.getc(keyseq_timeout.fdiv(1000))
458
-
459
- if escaped_c.nil?
460
- block.([Reline::Key.new(c, c, false)])
461
- elsif escaped_c >= 128 # maybe, first byte of multi byte
462
- block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)])
463
- elsif escaped_c == "\e".ord # escape twice
464
- block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)])
465
- else
466
- block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
467
403
  end
468
404
  end
469
405
 
@@ -473,7 +409,7 @@ module Reline
473
409
  end
474
410
 
475
411
  private def may_req_ambiguous_char_width
476
- @ambiguous_width = 2 if io_gate == Reline::GeneralIO or !STDOUT.tty?
412
+ @ambiguous_width = 2 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
477
413
  return if defined? @ambiguous_width
478
414
  io_gate.move_cursor_column(0)
479
415
  begin
@@ -567,37 +503,13 @@ module Reline
567
503
  def self.line_editor
568
504
  core.line_editor
569
505
  end
506
+ end
570
507
 
571
- def self.update_iogate
572
- return if core.config.test_mode
573
508
 
574
- # Need to change IOGate when `$stdout.tty?` change from false to true by `$stdout.reopen`
575
- # Example: rails/spring boot the application in non-tty, then run console in tty.
576
- if ENV['TERM'] != 'dumb' && core.io_gate == Reline::GeneralIO && $stdout.tty?
577
- require 'reline/ansi'
578
- remove_const(:IOGate)
579
- const_set(:IOGate, Reline::ANSI)
580
- end
581
- end
582
- end
509
+ Reline::IOGate = Reline::IO.decide_io_gate
583
510
 
584
- require 'reline/general_io'
585
- io = Reline::GeneralIO
586
- unless ENV['TERM'] == 'dumb'
587
- case RbConfig::CONFIG['host_os']
588
- when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
589
- require 'reline/windows'
590
- tty = (io = Reline::Windows).msys_tty?
591
- else
592
- tty = $stdout.tty?
593
- end
594
- end
595
- Reline::IOGate = if tty
596
- require 'reline/ansi'
597
- Reline::ANSI
598
- else
599
- io
600
- end
511
+ # Deprecated
512
+ Reline::GeneralIO = Reline::Dumb.new
601
513
 
602
514
  Reline::Face.load_initial_configs
603
515
 
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.5.7
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: 2024-05-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,13 +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
39
  - lib/reline/face.rb
41
- - lib/reline/general_io.rb
42
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
43
45
  - lib/reline/key_actor.rb
44
46
  - lib/reline/key_actor/base.rb
47
+ - lib/reline/key_actor/composite.rb
45
48
  - lib/reline/key_actor/emacs.rb
46
49
  - lib/reline/key_actor/vi_command.rb
47
50
  - lib/reline/key_actor/vi_insert.rb
@@ -52,7 +55,6 @@ files:
52
55
  - lib/reline/unicode.rb
53
56
  - lib/reline/unicode/east_asian_width.rb
54
57
  - lib/reline/version.rb
55
- - lib/reline/windows.rb
56
58
  - license_of_rb-readline
57
59
  homepage: https://github.com/ruby/reline
58
60
  licenses:
@@ -1,111 +0,0 @@
1
- require 'io/wait'
2
-
3
- class Reline::GeneralIO
4
- RESET_COLOR = '' # Do not send color reset sequence
5
-
6
- def self.reset(encoding: nil)
7
- @@pasting = false
8
- if encoding
9
- @@encoding = encoding
10
- elsif defined?(@@encoding)
11
- remove_class_variable(:@@encoding)
12
- end
13
- end
14
-
15
- def self.encoding
16
- if defined?(@@encoding)
17
- @@encoding
18
- elsif RUBY_PLATFORM =~ /mswin|mingw/
19
- Encoding::UTF_8
20
- else
21
- Encoding::default_external
22
- end
23
- end
24
-
25
- def self.win?
26
- false
27
- end
28
-
29
- def self.set_default_key_bindings(_)
30
- end
31
-
32
- @@buf = []
33
- @@input = STDIN
34
-
35
- def self.input=(val)
36
- @@input = val
37
- end
38
-
39
- def self.with_raw_input
40
- yield
41
- end
42
-
43
- def self.getc(_timeout_second)
44
- unless @@buf.empty?
45
- return @@buf.shift
46
- end
47
- c = nil
48
- loop do
49
- Reline.core.line_editor.handle_signal
50
- result = @@input.wait_readable(0.1)
51
- next if result.nil?
52
- c = @@input.read(1)
53
- break
54
- end
55
- c&.ord
56
- end
57
-
58
- def self.ungetc(c)
59
- @@buf.unshift(c)
60
- end
61
-
62
- def self.get_screen_size
63
- [24, 80]
64
- end
65
-
66
- def self.cursor_pos
67
- Reline::CursorPos.new(1, 1)
68
- end
69
-
70
- def self.hide_cursor
71
- end
72
-
73
- def self.show_cursor
74
- end
75
-
76
- def self.move_cursor_column(val)
77
- end
78
-
79
- def self.move_cursor_up(val)
80
- end
81
-
82
- def self.move_cursor_down(val)
83
- end
84
-
85
- def self.erase_after_cursor
86
- end
87
-
88
- def self.scroll_down(val)
89
- end
90
-
91
- def self.clear_screen
92
- end
93
-
94
- def self.set_screen_size(rows, columns)
95
- end
96
-
97
- def self.set_winch_handler(&handler)
98
- end
99
-
100
- @@pasting = false
101
-
102
- def self.in_pasting?
103
- @@pasting
104
- end
105
-
106
- def self.prep
107
- end
108
-
109
- def self.deprep(otio)
110
- end
111
- end