reline 0.3.6 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3075f4003cf263e4652fc0dec716c71b55b597e6cbdc8cdb5297181b72780b57
4
- data.tar.gz: 78eb2e13f17bc0c7ae34b425effe29bf40a30b355af7d0efd271823c2cdde521
3
+ metadata.gz: 709b8943f16732f771d45da031e9676dc01c8b75f0410134a8b1fa8ab590d294
4
+ data.tar.gz: 04aa52c6ea6a8939402a1554b42bce891bd65a13be6b76cbfd3f4859df1455d4
5
5
  SHA512:
6
- metadata.gz: 9fd55d135c7b1aaffaff575f930bdb6365c202a1d15b5943d3dd9f678f416ba312b21c836ef8b78d11ee9942c4e0f0ac50d395633196bd649bd23a2fa6096456
7
- data.tar.gz: 43fe692b243560a81da41a48f4cb5cdf05514f85788bbc6b54bba72aef4d5e7258e73c2a84622c80e51adf36345cd9e7595455f8301e09c1f299f7b2ec147ff2
6
+ metadata.gz: ab8a124f732cfa4b8522f397a546fc89ea93f188ca9f44f7f560ea2afb00abbe3b95486c17a20b826d360a8bb064ca441bd357acffe1eb4ec371fbf6380cd37d
7
+ data.tar.gz: e756e58d4ae8929045998b8278fcee48ba1867741cc4d47bd72beb3e3a74902938d4c8a9dcd4c0452f20b25f5b4fe05eb96929bc39c28f326dc88c9bdf7be458
data/lib/reline/ansi.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'io/console'
2
2
  require 'io/wait'
3
- require 'timeout'
4
3
  require_relative 'terminfo'
5
4
 
6
5
  class Reline::ANSI
@@ -14,10 +13,21 @@ class Reline::ANSI
14
13
  'kcud1' => :ed_next_history,
15
14
  'kcuf1' => :ed_next_char,
16
15
  'kcub1' => :ed_prev_char,
17
- 'cuu' => :ed_prev_history,
18
- 'cud' => :ed_next_history,
19
- 'cuf' => :ed_next_char,
20
- 'cub' => :ed_prev_char,
16
+ }
17
+
18
+ ANSI_CURSOR_KEY_BINDINGS = {
19
+ # Up
20
+ 'A' => [:ed_prev_history, {}],
21
+ # Down
22
+ 'B' => [:ed_next_history, {}],
23
+ # Right
24
+ 'C' => [:ed_next_char, { ctrl: :em_next_word, meta: :em_next_word }],
25
+ # Left
26
+ 'D' => [:ed_prev_char, { ctrl: :ed_prev_word, meta: :ed_prev_word }],
27
+ # End
28
+ 'F' => [:ed_move_to_end, {}],
29
+ # Home
30
+ 'H' => [:ed_move_to_beg, {}],
21
31
  }
22
32
 
23
33
  if Reline::Terminfo.enabled?
@@ -33,22 +43,12 @@ class Reline::ANSI
33
43
  end
34
44
 
35
45
  def self.set_default_key_bindings(config, allow_terminfo: true)
46
+ set_default_key_bindings_ansi_cursor(config)
36
47
  if allow_terminfo && Reline::Terminfo.enabled?
37
48
  set_default_key_bindings_terminfo(config)
38
49
  else
39
50
  set_default_key_bindings_comprehensive_list(config)
40
51
  end
41
- {
42
- # extended entries of terminfo
43
- [27, 91, 49, 59, 53, 67] => :em_next_word, # Ctrl+→, extended entry
44
- [27, 91, 49, 59, 53, 68] => :ed_prev_word, # Ctrl+←, extended entry
45
- [27, 91, 49, 59, 51, 67] => :em_next_word, # Meta+→, extended entry
46
- [27, 91, 49, 59, 51, 68] => :ed_prev_word, # Meta+←, extended entry
47
- }.each_pair do |key, func|
48
- config.add_default_key_binding_by_keymap(:emacs, key, func)
49
- config.add_default_key_binding_by_keymap(:vi_insert, key, func)
50
- config.add_default_key_binding_by_keymap(:vi_command, key, func)
51
- end
52
52
  {
53
53
  [27, 91, 90] => :completion_journey_up, # S-Tab
54
54
  }.each_pair do |key, func|
@@ -64,18 +64,33 @@ class Reline::ANSI
64
64
  end
65
65
  end
66
66
 
67
+ def self.set_default_key_bindings_ansi_cursor(config)
68
+ ANSI_CURSOR_KEY_BINDINGS.each do |char, (default_func, modifiers)|
69
+ bindings = [["\e[#{char}", default_func]] # CSI + char
70
+ if modifiers[:ctrl]
71
+ # CSI + ctrl_key_modifier + char
72
+ bindings << ["\e[1;5#{char}", modifiers[:ctrl]]
73
+ end
74
+ if modifiers[:meta]
75
+ # CSI + meta_key_modifier + char
76
+ bindings << ["\e[1;3#{char}", modifiers[:meta]]
77
+ # Meta(ESC) + CSI + char
78
+ bindings << ["\e\e[#{char}", modifiers[:meta]]
79
+ end
80
+ bindings.each do |sequence, func|
81
+ key = sequence.bytes
82
+ config.add_default_key_binding_by_keymap(:emacs, key, func)
83
+ config.add_default_key_binding_by_keymap(:vi_insert, key, func)
84
+ config.add_default_key_binding_by_keymap(:vi_command, key, func)
85
+ end
86
+ end
87
+ end
88
+
67
89
  def self.set_default_key_bindings_terminfo(config)
68
90
  key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding|
69
91
  begin
70
92
  key_code = Reline::Terminfo.tigetstr(capname)
71
- case capname
72
- # Escape sequences that omit the move distance and are set to defaults
73
- # value 1 may be sometimes sent by pressing the arrow-key.
74
- when 'cuu', 'cud', 'cuf', 'cub'
75
- [ key_code.sub(/%p1%d/, '').bytes, key_binding ]
76
- else
77
- [ key_code.bytes, key_binding ]
78
- end
93
+ [ key_code.bytes, key_binding ]
79
94
  rescue Reline::Terminfo::TerminfoError
80
95
  # capname is undefined
81
96
  end
@@ -94,14 +109,8 @@ class Reline::ANSI
94
109
  [27, 91, 49, 126] => :ed_move_to_beg, # Home
95
110
  [27, 91, 52, 126] => :ed_move_to_end, # End
96
111
  [27, 91, 51, 126] => :key_delete, # Del
97
- [27, 91, 65] => :ed_prev_history, # ↑
98
- [27, 91, 66] => :ed_next_history, # ↓
99
- [27, 91, 67] => :ed_next_char, # →
100
- [27, 91, 68] => :ed_prev_char, # ←
101
112
 
102
113
  # KDE
103
- [27, 91, 72] => :ed_move_to_beg, # Home
104
- [27, 91, 70] => :ed_move_to_end, # End
105
114
  # Del is 0x08
106
115
  [27, 71, 65] => :ed_prev_history, # ↑
107
116
  [27, 71, 66] => :ed_next_history, # ↓
@@ -118,12 +127,6 @@ class Reline::ANSI
118
127
  # Del is 0x08
119
128
  # Arrow keys are the same of KDE
120
129
 
121
- # iTerm2
122
- [27, 27, 91, 67] => :em_next_word, # Option+→, extended entry
123
- [27, 27, 91, 68] => :ed_prev_word, # Option+←, extended entry
124
- [195, 166] => :em_next_word, # Option+f
125
- [195, 162] => :ed_prev_word, # Option+b
126
-
127
130
  [27, 79, 65] => :ed_prev_history, # ↑
128
131
  [27, 79, 66] => :ed_next_history, # ↓
129
132
  [27, 79, 67] => :ed_next_char, # →
@@ -150,11 +153,13 @@ class Reline::ANSI
150
153
  end
151
154
 
152
155
  @@buf = []
153
- def self.inner_getc
156
+ def self.inner_getc(timeout_second)
154
157
  unless @@buf.empty?
155
158
  return @@buf.shift
156
159
  end
157
160
  until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
161
+ timeout_second -= 0.1
162
+ return nil if timeout_second <= 0
158
163
  Reline.core.line_editor.resize
159
164
  end
160
165
  (c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
@@ -168,40 +173,38 @@ class Reline::ANSI
168
173
  @@in_bracketed_paste_mode = false
169
174
  START_BRACKETED_PASTE = String.new("\e[200~,", encoding: Encoding::ASCII_8BIT)
170
175
  END_BRACKETED_PASTE = String.new("\e[200~.", encoding: Encoding::ASCII_8BIT)
171
- def self.getc_with_bracketed_paste
176
+ def self.getc_with_bracketed_paste(timeout_second)
172
177
  buffer = String.new(encoding: Encoding::ASCII_8BIT)
173
- buffer << inner_getc
178
+ buffer << inner_getc(timeout_second)
174
179
  while START_BRACKETED_PASTE.start_with?(buffer) or END_BRACKETED_PASTE.start_with?(buffer) do
175
180
  if START_BRACKETED_PASTE == buffer
176
181
  @@in_bracketed_paste_mode = true
177
- return inner_getc
182
+ return inner_getc(timeout_second)
178
183
  elsif END_BRACKETED_PASTE == buffer
179
184
  @@in_bracketed_paste_mode = false
180
185
  ungetc(-1)
181
- return inner_getc
186
+ return inner_getc(timeout_second)
182
187
  end
183
- begin
184
- succ_c = nil
185
- Timeout.timeout(Reline.core.config.keyseq_timeout * 100) {
186
- succ_c = inner_getc
187
- }
188
- rescue Timeout::Error
189
- break
190
- else
188
+ succ_c = inner_getc(Reline.core.config.keyseq_timeout)
189
+
190
+ if succ_c
191
191
  buffer << succ_c
192
+ else
193
+ break
192
194
  end
193
195
  end
194
196
  buffer.bytes.reverse_each do |ch|
195
197
  ungetc ch
196
198
  end
197
- inner_getc
199
+ inner_getc(timeout_second)
198
200
  end
199
201
 
200
- def self.getc
202
+ # if the usage expects to wait indefinitely, use Float::INFINITY for timeout_second
203
+ def self.getc(timeout_second)
201
204
  if Reline.core.config.enable_bracketed_paste
202
- getc_with_bracketed_paste
205
+ getc_with_bracketed_paste(timeout_second)
203
206
  else
204
- inner_getc
207
+ inner_getc(timeout_second)
205
208
  end
206
209
  end
207
210
 
@@ -331,9 +334,12 @@ class Reline::ANSI
331
334
  @@output.write "\e[K"
332
335
  end
333
336
 
337
+ # This only works when the cursor is at the bottom of the scroll range
338
+ # For more details, see https://github.com/ruby/reline/pull/577#issuecomment-1646679623
334
339
  def self.scroll_down(x)
335
340
  return if x.zero?
336
- @@output.write "\e[#{x}S"
341
+ # We use `\n` instead of CSI + S because CSI + S would cause https://github.com/ruby/reline/issues/576
342
+ @@output.write "\n" * x
337
343
  end
338
344
 
339
345
  def self.clear_screen
@@ -1,4 +1,3 @@
1
- require 'timeout'
2
1
  require 'io/wait'
3
2
 
4
3
  class Reline::GeneralIO
@@ -35,7 +34,7 @@ class Reline::GeneralIO
35
34
  yield
36
35
  end
37
36
 
38
- def self.getc
37
+ def self.getc(_timeout_second)
39
38
  unless @@buf.empty?
40
39
  return @@buf.shift
41
40
  end
@@ -1605,7 +1605,7 @@ class Reline::LineEditor
1605
1605
  else
1606
1606
  @just_cursor_moving = false
1607
1607
  end
1608
- if @is_multiline and @auto_indent_proc and not simplified_rendering?
1608
+ if @is_multiline and @auto_indent_proc and not simplified_rendering? and @line
1609
1609
  process_auto_indent
1610
1610
  end
1611
1611
  end
@@ -2696,6 +2696,7 @@ class Reline::LineEditor
2696
2696
  @cursor_max -= width
2697
2697
  end
2698
2698
  end
2699
+ alias_method :kill_word, :em_delete_next_word
2699
2700
 
2700
2701
  private def ed_delete_prev_word(key)
2701
2702
  if @byte_pointer > 0
@@ -2707,6 +2708,7 @@ class Reline::LineEditor
2707
2708
  @cursor_max -= width
2708
2709
  end
2709
2710
  end
2711
+ alias_method :backward_kill_word, :ed_delete_prev_word
2710
2712
 
2711
2713
  private def ed_transpose_chars(key)
2712
2714
  if @byte_pointer > 0
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.3.6'
2
+ VERSION = '0.3.8'
3
3
  end
@@ -295,7 +295,7 @@ class Reline::Windows
295
295
  yield
296
296
  end
297
297
 
298
- def self.getc
298
+ def self.getc(_timeout_second)
299
299
  check_input_event
300
300
  @@output_buf.shift
301
301
  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'
@@ -397,7 +396,7 @@ module Reline
397
396
  private def read_io(keyseq_timeout, &block)
398
397
  buffer = []
399
398
  loop do
400
- c = io_gate.getc
399
+ c = io_gate.getc(Float::INFINITY)
401
400
  if c == -1
402
401
  result = :unmatched
403
402
  @bracketed_paste_finished = true
@@ -434,15 +433,8 @@ module Reline
434
433
  end
435
434
 
436
435
  private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
437
- begin
438
- succ_c = nil
439
- Timeout.timeout(keyseq_timeout / 1000.0) {
440
- succ_c = io_gate.getc
441
- }
442
- rescue Timeout::Error # cancel matching only when first byte
443
- block.([Reline::Key.new(c, c, false)])
444
- return :break
445
- else
436
+ succ_c = io_gate.getc(keyseq_timeout.fdiv(1000))
437
+ if succ_c
446
438
  case key_stroke.match_status(buffer.dup.push(succ_c))
447
439
  when :unmatched
448
440
  if c == "\e".ord
@@ -462,27 +454,23 @@ module Reline
462
454
  block.(expanded)
463
455
  return :break
464
456
  end
457
+ else
458
+ block.([Reline::Key.new(c, c, false)])
459
+ return :break
465
460
  end
466
461
  end
467
462
 
468
463
  private def read_escaped_key(keyseq_timeout, c, block)
469
- begin
470
- escaped_c = nil
471
- Timeout.timeout(keyseq_timeout / 1000.0) {
472
- escaped_c = io_gate.getc
473
- }
474
- rescue Timeout::Error # independent ESC
464
+ escaped_c = io_gate.getc(keyseq_timeout.fdiv(1000))
465
+
466
+ if escaped_c.nil?
475
467
  block.([Reline::Key.new(c, c, false)])
468
+ elsif escaped_c >= 128 # maybe, first byte of multi byte
469
+ block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)])
470
+ elsif escaped_c == "\e".ord # escape twice
471
+ block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)])
476
472
  else
477
- if escaped_c.nil?
478
- block.([Reline::Key.new(c, c, false)])
479
- elsif escaped_c >= 128 # maybe, first byte of multi byte
480
- block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)])
481
- elsif escaped_c == "\e".ord # escape twice
482
- block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)])
483
- else
484
- block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
485
- end
473
+ block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
486
474
  end
487
475
  end
488
476
 
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.6
4
+ version: 0.3.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-08 00:00:00.000000000 Z
11
+ date: 2023-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console
@@ -72,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
72
  - !ruby/object:Gem::Version
73
73
  version: '0'
74
74
  requirements: []
75
- rubygems_version: 3.4.13
75
+ rubygems_version: 3.4.10
76
76
  signing_key:
77
77
  specification_version: 4
78
78
  summary: Alternative GNU Readline or Editline implementation by pure Ruby.