reline 0.5.8 → 0.5.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bcccc644594f9c2e4b9ae0eb743c2ae293ef084e96a8d9bd032b76825111c01b
4
- data.tar.gz: b5ab239a3d20925d4fbd8fb827908fa3e4fa70298a172e32e9b2b4de59dc767e
3
+ metadata.gz: 402ac8415b342c58b741ab1ae942818c44f092d43665d9546fde986572ce2bcf
4
+ data.tar.gz: 0a54115c2e2b02720e67a7870edc77430493b3d2fa89c033046d817b5b984b13
5
5
  SHA512:
6
- metadata.gz: 9bce894711da0253bf9b3f0eb192ff64947d591edd00f9094430431eb470fade4d02f3f8b529d364cdd7124d7f5a5203ea755be41dbfda890e37654aca430706
7
- data.tar.gz: eed500ad148a1f83e3de03e6d7daaf5d250ba3ea25d47d24070e749dfd44a7d900b83474dd0b427faee74bad883dab97b7af1984a7fb7209e1819fd416d4381b
6
+ metadata.gz: 0525a60f8fe7512bf23575935d15c7173c825ce6b15a062505d73e9a34836d8b751182280c4b67288af7b949b0417a57a4f384281123ef7b6e90c3072b65f20c
7
+ data.tar.gz: 299034a835b97c80a119614394a650c60104d571ec95ffbff8356531dc1de96cd78b8aa3fa8830520a40d43e4b7feb1958285af29633877a772be7ed995d7d33
data/lib/reline/config.rb CHANGED
@@ -29,18 +29,31 @@ class Reline::Config
29
29
  attr_accessor :autocompletion
30
30
 
31
31
  def initialize
32
- @additional_key_bindings = {} # from inputrc
33
- @additional_key_bindings[:emacs] = {}
34
- @additional_key_bindings[:vi_insert] = {}
35
- @additional_key_bindings[:vi_command] = {}
36
- @oneshot_key_bindings = {}
32
+ reset_variables
33
+ end
34
+
35
+ def reset
36
+ if editing_mode_is?(:vi_command)
37
+ @editing_mode_label = :vi_insert
38
+ end
39
+ @oneshot_key_bindings.clear
40
+ end
41
+
42
+ def reset_variables
43
+ @additional_key_bindings = { # from inputrc
44
+ emacs: Reline::KeyActor::Base.new,
45
+ vi_insert: Reline::KeyActor::Base.new,
46
+ vi_command: Reline::KeyActor::Base.new
47
+ }
48
+ @oneshot_key_bindings = Reline::KeyActor::Base.new
37
49
  @editing_mode_label = :emacs
38
50
  @keymap_label = :emacs
39
51
  @keymap_prefix = []
40
- @key_actors = {}
41
- @key_actors[:emacs] = Reline::KeyActor::Emacs.new
42
- @key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
43
- @key_actors[:vi_command] = Reline::KeyActor::ViCommand.new
52
+ @default_key_bindings = {
53
+ emacs: Reline::KeyActor::Base.new(Reline::KeyActor::EMACS_MAPPING),
54
+ vi_insert: Reline::KeyActor::Base.new(Reline::KeyActor::VI_INSERT_MAPPING),
55
+ vi_command: Reline::KeyActor::Base.new(Reline::KeyActor::VI_COMMAND_MAPPING)
56
+ }
44
57
  @vi_cmd_mode_string = '(cmd)'
45
58
  @vi_ins_mode_string = '(ins)'
46
59
  @emacs_mode_string = '@'
@@ -49,20 +62,15 @@ class Reline::Config
49
62
  @keyseq_timeout = 500
50
63
  @test_mode = false
51
64
  @autocompletion = false
52
- @convert_meta = true if seven_bit_encoding?(Reline::IOGate.encoding)
65
+ @convert_meta = seven_bit_encoding?(Reline::IOGate.encoding)
53
66
  @loaded = false
54
67
  @enable_bracketed_paste = true
55
- end
56
-
57
- def reset
58
- if editing_mode_is?(:vi_command)
59
- @editing_mode_label = :vi_insert
60
- end
61
- @oneshot_key_bindings.clear
68
+ @show_mode_in_prompt = false
69
+ @default_inputrc_path = nil
62
70
  end
63
71
 
64
72
  def editing_mode
65
- @key_actors[@editing_mode_label]
73
+ @default_key_bindings[@editing_mode_label]
66
74
  end
67
75
 
68
76
  def editing_mode=(val)
@@ -74,7 +82,7 @@ class Reline::Config
74
82
  end
75
83
 
76
84
  def keymap
77
- @key_actors[@keymap_label]
85
+ @default_key_bindings[@keymap_label]
78
86
  end
79
87
 
80
88
  def loaded?
@@ -133,14 +141,14 @@ class Reline::Config
133
141
 
134
142
  def key_bindings
135
143
  # The key bindings for each editing mode will be overwritten by the user-defined ones.
136
- kb = @key_actors[@editing_mode_label].default_key_bindings.dup
137
- kb.merge!(@additional_key_bindings[@editing_mode_label])
138
- kb.merge!(@oneshot_key_bindings)
139
- kb
144
+ Reline::KeyActor::Composite.new([@oneshot_key_bindings, @additional_key_bindings[@editing_mode_label], @default_key_bindings[@editing_mode_label]])
140
145
  end
141
146
 
142
147
  def add_oneshot_key_binding(keystroke, target)
143
- @oneshot_key_bindings[keystroke] = target
148
+ # IRB sets invalid keystroke [Reline::Key]. We should ignore it.
149
+ return unless keystroke.all? { |c| c.is_a?(Integer) }
150
+
151
+ @oneshot_key_bindings.add(keystroke, target)
144
152
  end
145
153
 
146
154
  def reset_oneshot_key_bindings
@@ -148,11 +156,11 @@ class Reline::Config
148
156
  end
149
157
 
150
158
  def add_default_key_binding_by_keymap(keymap, keystroke, target)
151
- @key_actors[keymap].default_key_bindings[keystroke] = target
159
+ @default_key_bindings[keymap].add(keystroke, target)
152
160
  end
153
161
 
154
162
  def add_default_key_binding(keystroke, target)
155
- @key_actors[@keymap_label].default_key_bindings[keystroke] = target
163
+ add_default_key_binding_by_keymap(@keymap_label, keystroke, target)
156
164
  end
157
165
 
158
166
  def read_lines(lines, file = nil)
@@ -192,7 +200,7 @@ class Reline::Config
192
200
  func_name = func_name.split.first
193
201
  keystroke, func = bind_key(key, func_name)
194
202
  next unless keystroke
195
- @additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
203
+ @additional_key_bindings[@keymap_label].add(@keymap_prefix + keystroke, func)
196
204
  end
197
205
  end
198
206
  unless if_stack.empty?
@@ -243,22 +251,6 @@ class Reline::Config
243
251
  rescue ArgumentError
244
252
  @history_size = 500
245
253
  end
246
- when 'bell-style'
247
- @bell_style =
248
- case value
249
- when 'none', 'off'
250
- :none
251
- when 'audible', 'on'
252
- :audible
253
- when 'visible'
254
- :visible
255
- else
256
- :audible
257
- end
258
- when 'comment-begin'
259
- @comment_begin = value.dup
260
- when 'completion-query-items'
261
- @completion_query_items = value.to_i
262
254
  when 'isearch-terminators'
263
255
  @isearch_terminators = retrieve_string(raw_value)
264
256
  when 'editing-mode'
@@ -374,6 +366,11 @@ class Reline::Config
374
366
  ret
375
367
  end
376
368
 
369
+ def reload
370
+ reset_variables
371
+ read
372
+ end
373
+
377
374
  private def seven_bit_encoding?(encoding)
378
375
  encoding == Encoding::US_ASCII
379
376
  end
data/lib/reline/face.rb CHANGED
@@ -107,7 +107,7 @@ class Reline::Face
107
107
 
108
108
  def sgr_rgb_256color(key, value)
109
109
  # 256 colors are
110
- # 0..15: standard colors, hight intensity colors
110
+ # 0..15: standard colors, high intensity colors
111
111
  # 16..232: 216 colors (R, G, B each 6 steps)
112
112
  # 233..255: grayscale colors (24 steps)
113
113
  # This methods converts rgb_expression to 216 colors
@@ -1,10 +1,7 @@
1
1
  require 'io/console'
2
2
  require 'io/wait'
3
- require_relative 'terminfo'
4
-
5
- class Reline::ANSI
6
- RESET_COLOR = "\e[0m"
7
3
 
4
+ class Reline::ANSI < Reline::IO
8
5
  CAPNAME_KEY_BINDINGS = {
9
6
  'khome' => :ed_move_to_beg,
10
7
  'kend' => :ed_move_to_end,
@@ -36,15 +33,18 @@ class Reline::ANSI
36
33
  Reline::Terminfo.setupterm(0, 2)
37
34
  end
38
35
 
39
- def self.encoding
40
- Encoding.default_external
36
+ def initialize
37
+ @input = STDIN
38
+ @output = STDOUT
39
+ @buf = []
40
+ @old_winch_handler = nil
41
41
  end
42
42
 
43
- def self.win?
44
- false
43
+ def encoding
44
+ Encoding.default_external
45
45
  end
46
46
 
47
- def self.set_default_key_bindings(config, allow_terminfo: true)
47
+ def set_default_key_bindings(config, allow_terminfo: true)
48
48
  set_bracketed_paste_key_bindings(config)
49
49
  set_default_key_bindings_ansi_cursor(config)
50
50
  if allow_terminfo && Reline::Terminfo.enabled?
@@ -67,13 +67,13 @@ class Reline::ANSI
67
67
  end
68
68
  end
69
69
 
70
- def self.set_bracketed_paste_key_bindings(config)
70
+ def set_bracketed_paste_key_bindings(config)
71
71
  [:emacs, :vi_insert, :vi_command].each do |keymap|
72
72
  config.add_default_key_binding_by_keymap(keymap, START_BRACKETED_PASTE.bytes, :bracketed_paste_start)
73
73
  end
74
74
  end
75
75
 
76
- def self.set_default_key_bindings_ansi_cursor(config)
76
+ def set_default_key_bindings_ansi_cursor(config)
77
77
  ANSI_CURSOR_KEY_BINDINGS.each do |char, (default_func, modifiers)|
78
78
  bindings = [["\e[#{char}", default_func]] # CSI + char
79
79
  if modifiers[:ctrl]
@@ -95,7 +95,7 @@ class Reline::ANSI
95
95
  end
96
96
  end
97
97
 
98
- def self.set_default_key_bindings_terminfo(config)
98
+ def set_default_key_bindings_terminfo(config)
99
99
  key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding|
100
100
  begin
101
101
  key_code = Reline::Terminfo.tigetstr(capname)
@@ -112,12 +112,16 @@ class Reline::ANSI
112
112
  end
113
113
  end
114
114
 
115
- def self.set_default_key_bindings_comprehensive_list(config)
115
+ def set_default_key_bindings_comprehensive_list(config)
116
116
  {
117
+ # xterm
118
+ [27, 91, 51, 126] => :key_delete, # kdch1
119
+ [27, 91, 53, 126] => :ed_search_prev_history, # kpp
120
+ [27, 91, 54, 126] => :ed_search_next_history, # knp
121
+
117
122
  # Console (80x25)
118
123
  [27, 91, 49, 126] => :ed_move_to_beg, # Home
119
124
  [27, 91, 52, 126] => :ed_move_to_end, # End
120
- [27, 91, 51, 126] => :key_delete, # Del
121
125
 
122
126
  # KDE
123
127
  # Del is 0x08
@@ -147,47 +151,42 @@ class Reline::ANSI
147
151
  end
148
152
  end
149
153
 
150
- @@input = STDIN
151
- def self.input=(val)
152
- @@input = val
154
+ def input=(val)
155
+ @input = val
153
156
  end
154
157
 
155
- @@output = STDOUT
156
- def self.output=(val)
157
- @@output = val
158
+ def output=(val)
159
+ @output = val
158
160
  end
159
161
 
160
- def self.with_raw_input
161
- if @@input.tty?
162
- @@input.raw(intr: true) { yield }
162
+ def with_raw_input
163
+ if @input.tty?
164
+ @input.raw(intr: true) { yield }
163
165
  else
164
166
  yield
165
167
  end
166
168
  end
167
169
 
168
- @@buf = []
169
- def self.inner_getc(timeout_second)
170
- unless @@buf.empty?
171
- return @@buf.shift
170
+ def inner_getc(timeout_second)
171
+ unless @buf.empty?
172
+ return @buf.shift
172
173
  end
173
- until @@input.wait_readable(0.01)
174
+ until @input.wait_readable(0.01)
174
175
  timeout_second -= 0.01
175
176
  return nil if timeout_second <= 0
176
177
 
177
178
  Reline.core.line_editor.handle_signal
178
179
  end
179
- c = @@input.getbyte
180
- (c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
180
+ c = @input.getbyte
181
+ (c == 0x16 && @input.tty? && @input.raw(min: 0, time: 0, &:getbyte)) || c
181
182
  rescue Errno::EIO
182
183
  # Maybe the I/O has been closed.
183
184
  nil
184
- rescue Errno::ENOTTY
185
- nil
186
185
  end
187
186
 
188
187
  START_BRACKETED_PASTE = String.new("\e[200~", encoding: Encoding::ASCII_8BIT)
189
188
  END_BRACKETED_PASTE = String.new("\e[201~", encoding: Encoding::ASCII_8BIT)
190
- def self.read_bracketed_paste
189
+ def read_bracketed_paste
191
190
  buffer = String.new(encoding: Encoding::ASCII_8BIT)
192
191
  until buffer.end_with?(END_BRACKETED_PASTE)
193
192
  c = inner_getc(Float::INFINITY)
@@ -199,38 +198,38 @@ class Reline::ANSI
199
198
  end
200
199
 
201
200
  # if the usage expects to wait indefinitely, use Float::INFINITY for timeout_second
202
- def self.getc(timeout_second)
201
+ def getc(timeout_second)
203
202
  inner_getc(timeout_second)
204
203
  end
205
204
 
206
- def self.in_pasting?
205
+ def in_pasting?
207
206
  not empty_buffer?
208
207
  end
209
208
 
210
- def self.empty_buffer?
211
- unless @@buf.empty?
209
+ def empty_buffer?
210
+ unless @buf.empty?
212
211
  return false
213
212
  end
214
- !@@input.wait_readable(0)
213
+ !@input.wait_readable(0)
215
214
  end
216
215
 
217
- def self.ungetc(c)
218
- @@buf.unshift(c)
216
+ def ungetc(c)
217
+ @buf.unshift(c)
219
218
  end
220
219
 
221
- def self.retrieve_keybuffer
220
+ def retrieve_keybuffer
222
221
  begin
223
- return unless @@input.wait_readable(0.001)
224
- str = @@input.read_nonblock(1024)
222
+ return unless @input.wait_readable(0.001)
223
+ str = @input.read_nonblock(1024)
225
224
  str.bytes.each do |c|
226
- @@buf.push(c)
225
+ @buf.push(c)
227
226
  end
228
227
  rescue EOFError
229
228
  end
230
229
  end
231
230
 
232
- def self.get_screen_size
233
- s = @@input.winsize
231
+ def get_screen_size
232
+ s = @input.winsize
234
233
  return s if s[0] > 0 && s[1] > 0
235
234
  s = [ENV["LINES"].to_i, ENV["COLUMNS"].to_i]
236
235
  return s if s[0] > 0 && s[1] > 0
@@ -239,20 +238,20 @@ class Reline::ANSI
239
238
  [24, 80]
240
239
  end
241
240
 
242
- def self.set_screen_size(rows, columns)
243
- @@input.winsize = [rows, columns]
241
+ def set_screen_size(rows, columns)
242
+ @input.winsize = [rows, columns]
244
243
  self
245
- rescue Errno::ENOTTY
244
+ rescue Errno::ENOTTY, Errno::ENODEV
246
245
  self
247
246
  end
248
247
 
249
- def self.cursor_pos
250
- begin
248
+ def cursor_pos
249
+ if both_tty?
251
250
  res = +''
252
251
  m = nil
253
- @@input.raw do |stdin|
254
- @@output << "\e[6n"
255
- @@output.flush
252
+ @input.raw do |stdin|
253
+ @output << "\e[6n"
254
+ @output.flush
256
255
  loop do
257
256
  c = stdin.getc
258
257
  next if c.nil?
@@ -266,9 +265,9 @@ class Reline::ANSI
266
265
  end
267
266
  column = m[:column].to_i - 1
268
267
  row = m[:row].to_i - 1
269
- rescue Errno::ENOTTY
268
+ else
270
269
  begin
271
- buf = @@output.pread(@@output.pos, 0)
270
+ buf = @output.pread(@output.pos, 0)
272
271
  row = buf.count("\n")
273
272
  column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0
274
273
  rescue Errno::ESPIPE, IOError
@@ -281,82 +280,93 @@ class Reline::ANSI
281
280
  Reline::CursorPos.new(column, row)
282
281
  end
283
282
 
284
- def self.move_cursor_column(x)
285
- @@output.write "\e[#{x + 1}G"
283
+ def both_tty?
284
+ @input.tty? && @output.tty?
285
+ end
286
+
287
+ def move_cursor_column(x)
288
+ @output.write "\e[#{x + 1}G"
286
289
  end
287
290
 
288
- def self.move_cursor_up(x)
291
+ def move_cursor_up(x)
289
292
  if x > 0
290
- @@output.write "\e[#{x}A"
293
+ @output.write "\e[#{x}A"
291
294
  elsif x < 0
292
295
  move_cursor_down(-x)
293
296
  end
294
297
  end
295
298
 
296
- def self.move_cursor_down(x)
299
+ def move_cursor_down(x)
297
300
  if x > 0
298
- @@output.write "\e[#{x}B"
301
+ @output.write "\e[#{x}B"
299
302
  elsif x < 0
300
303
  move_cursor_up(-x)
301
304
  end
302
305
  end
303
306
 
304
- def self.hide_cursor
307
+ def hide_cursor
308
+ seq = "\e[?25l"
305
309
  if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
306
310
  begin
307
- @@output.write Reline::Terminfo.tigetstr('civis')
311
+ seq = Reline::Terminfo.tigetstr('civis')
308
312
  rescue Reline::Terminfo::TerminfoError
309
313
  # civis is undefined
310
314
  end
311
- else
312
- # ignored
313
315
  end
316
+ @output.write seq
314
317
  end
315
318
 
316
- def self.show_cursor
319
+ def show_cursor
320
+ seq = "\e[?25h"
317
321
  if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
318
322
  begin
319
- @@output.write Reline::Terminfo.tigetstr('cnorm')
323
+ seq = Reline::Terminfo.tigetstr('cnorm')
320
324
  rescue Reline::Terminfo::TerminfoError
321
325
  # cnorm is undefined
322
326
  end
323
- else
324
- # ignored
325
327
  end
328
+ @output.write seq
326
329
  end
327
330
 
328
- def self.erase_after_cursor
329
- @@output.write "\e[K"
331
+ def erase_after_cursor
332
+ @output.write "\e[K"
330
333
  end
331
334
 
332
335
  # This only works when the cursor is at the bottom of the scroll range
333
336
  # For more details, see https://github.com/ruby/reline/pull/577#issuecomment-1646679623
334
- def self.scroll_down(x)
337
+ def scroll_down(x)
335
338
  return if x.zero?
336
339
  # We use `\n` instead of CSI + S because CSI + S would cause https://github.com/ruby/reline/issues/576
337
- @@output.write "\n" * x
340
+ @output.write "\n" * x
338
341
  end
339
342
 
340
- def self.clear_screen
341
- @@output.write "\e[2J"
342
- @@output.write "\e[1;1H"
343
+ def clear_screen
344
+ @output.write "\e[2J"
345
+ @output.write "\e[1;1H"
343
346
  end
344
347
 
345
- @@old_winch_handler = nil
346
- def self.set_winch_handler(&handler)
347
- @@old_winch_handler = Signal.trap('WINCH', &handler)
348
+ def set_winch_handler(&handler)
349
+ @old_winch_handler = Signal.trap('WINCH', &handler)
350
+ @old_cont_handler = Signal.trap('CONT') do
351
+ @input.raw!(intr: true) if @input.tty?
352
+ # Rerender the screen. Note that screen size might be changed while suspended.
353
+ handler.call
354
+ end
355
+ rescue ArgumentError
356
+ # Signal.trap may raise an ArgumentError if the platform doesn't support the signal.
348
357
  end
349
358
 
350
- def self.prep
359
+ def prep
351
360
  # Enable bracketed paste
352
- @@output.write "\e[?2004h" if Reline.core.config.enable_bracketed_paste
361
+ @output.write "\e[?2004h" if Reline.core.config.enable_bracketed_paste && both_tty?
353
362
  retrieve_keybuffer
354
363
  nil
355
364
  end
356
365
 
357
- def self.deprep(otio)
366
+ def deprep(otio)
358
367
  # Disable bracketed paste
359
- @@output.write "\e[?2004l" if Reline.core.config.enable_bracketed_paste
360
- Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
368
+ @output.write "\e[?2004l" if Reline.core.config.enable_bracketed_paste && both_tty?
369
+ Signal.trap('WINCH', @old_winch_handler) if @old_winch_handler
370
+ Signal.trap('CONT', @old_cont_handler) if @old_cont_handler
361
371
  end
362
372
  end
@@ -0,0 +1,106 @@
1
+ require 'io/wait'
2
+
3
+ class Reline::Dumb < Reline::IO
4
+ RESET_COLOR = '' # Do not send color reset sequence
5
+
6
+ def initialize(encoding: nil)
7
+ @input = STDIN
8
+ @buf = []
9
+ @pasting = false
10
+ @encoding = encoding
11
+ @screen_size = [24, 80]
12
+ end
13
+
14
+ def dumb?
15
+ true
16
+ end
17
+
18
+ def encoding
19
+ if @encoding
20
+ @encoding
21
+ elsif RUBY_PLATFORM =~ /mswin|mingw/
22
+ Encoding::UTF_8
23
+ else
24
+ Encoding::default_external
25
+ end
26
+ end
27
+
28
+ def set_default_key_bindings(_)
29
+ end
30
+
31
+ def input=(val)
32
+ @input = val
33
+ end
34
+
35
+ def with_raw_input
36
+ yield
37
+ end
38
+
39
+ def getc(_timeout_second)
40
+ unless @buf.empty?
41
+ return @buf.shift
42
+ end
43
+ c = nil
44
+ loop do
45
+ Reline.core.line_editor.handle_signal
46
+ result = @input.wait_readable(0.1)
47
+ next if result.nil?
48
+ c = @input.read(1)
49
+ break
50
+ end
51
+ c&.ord
52
+ end
53
+
54
+ def ungetc(c)
55
+ @buf.unshift(c)
56
+ end
57
+
58
+ def get_screen_size
59
+ @screen_size
60
+ end
61
+
62
+ def cursor_pos
63
+ Reline::CursorPos.new(1, 1)
64
+ end
65
+
66
+ def hide_cursor
67
+ end
68
+
69
+ def show_cursor
70
+ end
71
+
72
+ def move_cursor_column(val)
73
+ end
74
+
75
+ def move_cursor_up(val)
76
+ end
77
+
78
+ def move_cursor_down(val)
79
+ end
80
+
81
+ def erase_after_cursor
82
+ end
83
+
84
+ def scroll_down(val)
85
+ end
86
+
87
+ def clear_screen
88
+ end
89
+
90
+ def set_screen_size(rows, columns)
91
+ @screen_size = [rows, columns]
92
+ end
93
+
94
+ def set_winch_handler(&handler)
95
+ end
96
+
97
+ def in_pasting?
98
+ @pasting
99
+ end
100
+
101
+ def prep
102
+ end
103
+
104
+ def deprep(otio)
105
+ end
106
+ end