reline 0.5.10 → 0.5.11

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: 402ac8415b342c58b741ab1ae942818c44f092d43665d9546fde986572ce2bcf
4
- data.tar.gz: 0a54115c2e2b02720e67a7870edc77430493b3d2fa89c033046d817b5b984b13
3
+ metadata.gz: d2e17ec5d6de83746c38c5e0764f7fa1ecda40f01c18b9e8cdf769e4bf2a155e
4
+ data.tar.gz: 7ce06466fae4c8115bb507141998d322595b9e924dfc1ad3001871265088a680
5
5
  SHA512:
6
- metadata.gz: 0525a60f8fe7512bf23575935d15c7173c825ce6b15a062505d73e9a34836d8b751182280c4b67288af7b949b0417a57a4f384281123ef7b6e90c3072b65f20c
7
- data.tar.gz: 299034a835b97c80a119614394a650c60104d571ec95ffbff8356531dc1de96cd78b8aa3fa8830520a40d43e4b7feb1958285af29633877a772be7ed995d7d33
6
+ metadata.gz: 31e90ffea6ac235aad5c2c243fbd41163142f94e044ed9f4980860263fab97154857483755dcacd259fa9b578b1c29be5b878cd7f883f18e7b92380cb5865ef3
7
+ data.tar.gz: 54b91a893c536b3e6b5c984c0fc2b053b8978ab586ae361446fb603c4eecfb0240a99c45b25e4996ff58d9ef15fa4e33bab5cef9cb4aef3dc7eab85998af3711
data/lib/reline/config.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  class Reline::Config
2
2
  attr_reader :test_mode
3
3
 
4
- KEYSEQ_PATTERN = /\\(?:C|Control)-[A-Za-z_]|\\(?:M|Meta)-[0-9A-Za-z_]|\\(?:C|Control)-(?:M|Meta)-[A-Za-z_]|\\(?:M|Meta)-(?:C|Control)-[A-Za-z_]|\\e|\\[\\\"\'abdfnrtv]|\\\d{1,3}|\\x\h{1,2}|./
4
+ KEYSEQ_PATTERN = /\\(?:C|Control)-[A-Za-z_]|\\(?:M|Meta)-[0-9A-Za-z_]|\\(?:C|Control)-\\(?:M|Meta)-[A-Za-z_]|\\(?:M|Meta)-\\(?:C|Control)-[A-Za-z_]|\\e|\\[\\\"\'abdfnrtv]|\\\d{1,3}|\\x\h{1,2}|./
5
5
 
6
6
  class InvalidInputrc < RuntimeError
7
7
  attr_accessor :file, :lineno
@@ -194,13 +194,14 @@ class Reline::Config
194
194
  # value ignores everything after a space, raw_value does not.
195
195
  var, value, raw_value = $1.downcase, $2.partition(' ').first, $2
196
196
  bind_variable(var, value, raw_value)
197
- next
198
- when /\s*("#{KEYSEQ_PATTERN}+")\s*:\s*(.*)\s*$/o
199
- key, func_name = $1, $2
200
- func_name = func_name.split.first
201
- keystroke, func = bind_key(key, func_name)
202
- next unless keystroke
203
- @additional_key_bindings[@keymap_label].add(@keymap_prefix + keystroke, func)
197
+ when /^\s*(?:M|Meta)-([a-zA-Z_])\s*:\s*(.*)\s*$/o
198
+ bind_key("\"\\M-#$1\"", $2)
199
+ when /^\s*(?:C|Control)-([a-zA-Z_])\s*:\s*(.*)\s*$/o
200
+ bind_key("\"\\C-#$1\"", $2)
201
+ when /^\s*(?:(?:C|Control)-(?:M|Meta)|(?:M|Meta)-(?:C|Control))-([a-zA-Z_])\s*:\s*(.*)\s*$/o
202
+ bind_key("\"\\M-\\C-#$1\"", $2)
203
+ when /^\s*("#{KEYSEQ_PATTERN}+")\s*:\s*(.*)\s*$/o
204
+ bind_key($1, $2)
204
205
  end
205
206
  end
206
207
  unless if_stack.empty?
@@ -310,7 +311,12 @@ class Reline::Config
310
311
  parse_keyseq(str).map { |c| c.chr(Reline.encoding_system_needs) }.join
311
312
  end
312
313
 
313
- def bind_key(key, func_name)
314
+ def bind_key(key, value)
315
+ keystroke, func = parse_key_binding(key, value)
316
+ @additional_key_bindings[@keymap_label].add(@keymap_prefix + keystroke, func) if keystroke
317
+ end
318
+
319
+ def parse_key_binding(key, func_name)
314
320
  if key =~ /\A"(.*)"\z/
315
321
  keyseq = parse_keyseq($1)
316
322
  else
@@ -319,27 +325,19 @@ class Reline::Config
319
325
  if func_name =~ /"(.*)"/
320
326
  func = parse_keyseq($1)
321
327
  else
322
- func = func_name.tr(?-, ?_).to_sym # It must be macro.
328
+ func = func_name.split.first.tr(?-, ?_).to_sym # It must be macro.
323
329
  end
324
330
  [keyseq, func]
325
331
  end
326
332
 
327
333
  def key_notation_to_code(notation)
328
334
  case notation
335
+ when /(?:\\(?:C|Control)-\\(?:M|Meta)|\\(?:M|Meta)-\\(?:C|Control))-([A-Za-z_])/
336
+ [?\e.ord, $1.ord % 32]
329
337
  when /\\(?:C|Control)-([A-Za-z_])/
330
- (1 + $1.downcase.ord - ?a.ord)
338
+ ($1.upcase.ord % 32)
331
339
  when /\\(?:M|Meta)-([0-9A-Za-z_])/
332
- modified_key = $1
333
- case $1
334
- when /[0-9]/
335
- ?\M-0.bytes.first + (modified_key.ord - ?0.ord)
336
- when /[A-Z]/
337
- ?\M-A.bytes.first + (modified_key.ord - ?A.ord)
338
- when /[a-z]/
339
- ?\M-a.bytes.first + (modified_key.ord - ?a.ord)
340
- end
341
- when /\\(?:C|Control)-(?:M|Meta)-[A-Za-z_]/, /\\(?:M|Meta)-(?:C|Control)-[A-Za-z_]/
342
- # 129 M-^A
340
+ [?\e.ord, $1.ord]
343
341
  when /\\(\d{1,3})/ then $1.to_i(8) # octal
344
342
  when /\\x(\h{1,2})/ then $1.to_i(16) # hexadecimal
345
343
  when "\\e" then ?\e.ord
@@ -359,11 +357,9 @@ class Reline::Config
359
357
  end
360
358
 
361
359
  def parse_keyseq(str)
362
- ret = []
363
- str.scan(KEYSEQ_PATTERN) do
364
- ret << key_notation_to_code($&)
360
+ str.scan(KEYSEQ_PATTERN).flat_map do |notation|
361
+ key_notation_to_code(notation)
365
362
  end
366
- ret
367
363
  end
368
364
 
369
365
  def reload
@@ -19,7 +19,7 @@ class Reline::History < Array
19
19
 
20
20
  def []=(index, val)
21
21
  index = check_index(index)
22
- super(index, String.new(val, encoding: Reline.encoding_system_needs))
22
+ super(index, Reline::Unicode.safe_encode(val, Reline.encoding_system_needs))
23
23
  end
24
24
 
25
25
  def concat(*val)
@@ -45,7 +45,7 @@ class Reline::History < Array
45
45
  end
46
46
  end
47
47
  super(*(val.map{ |v|
48
- String.new(v, encoding: Reline.encoding_system_needs)
48
+ Reline::Unicode.safe_encode(v, Reline.encoding_system_needs)
49
49
  }))
50
50
  end
51
51
 
@@ -56,7 +56,7 @@ class Reline::History < Array
56
56
  if @config.history_size.positive?
57
57
  shift if size + 1 > @config.history_size
58
58
  end
59
- super(String.new(val, encoding: Reline.encoding_system_needs))
59
+ super(Reline::Unicode.safe_encode(val, Reline.encoding_system_needs))
60
60
  end
61
61
 
62
62
  private def check_index(index)
@@ -41,7 +41,7 @@ class Reline::ANSI < Reline::IO
41
41
  end
42
42
 
43
43
  def encoding
44
- Encoding.default_external
44
+ @input.external_encoding || Encoding.default_external
45
45
  end
46
46
 
47
47
  def set_default_key_bindings(config, allow_terminfo: true)
@@ -75,7 +75,10 @@ class Reline::ANSI < Reline::IO
75
75
 
76
76
  def set_default_key_bindings_ansi_cursor(config)
77
77
  ANSI_CURSOR_KEY_BINDINGS.each do |char, (default_func, modifiers)|
78
- bindings = [["\e[#{char}", default_func]] # CSI + char
78
+ bindings = [
79
+ ["\e[#{char}", default_func], # CSI + char
80
+ ["\eO#{char}", default_func] # SS3 + char, application cursor key mode
81
+ ]
79
82
  if modifiers[:ctrl]
80
83
  # CSI + ctrl_key_modifier + char
81
84
  bindings << ["\e[1;5#{char}", modifiers[:ctrl]]
@@ -123,27 +126,9 @@ class Reline::ANSI < Reline::IO
123
126
  [27, 91, 49, 126] => :ed_move_to_beg, # Home
124
127
  [27, 91, 52, 126] => :ed_move_to_end, # End
125
128
 
126
- # KDE
127
- # Del is 0x08
128
- [27, 71, 65] => :ed_prev_history, # ↑
129
- [27, 71, 66] => :ed_next_history, # ↓
130
- [27, 71, 67] => :ed_next_char, # →
131
- [27, 71, 68] => :ed_prev_char, # ←
132
-
133
129
  # urxvt / exoterm
134
130
  [27, 91, 55, 126] => :ed_move_to_beg, # Home
135
131
  [27, 91, 56, 126] => :ed_move_to_end, # End
136
-
137
- # GNOME
138
- [27, 79, 72] => :ed_move_to_beg, # Home
139
- [27, 79, 70] => :ed_move_to_end, # End
140
- # Del is 0x08
141
- # Arrow keys are the same of KDE
142
-
143
- [27, 79, 65] => :ed_prev_history, # ↑
144
- [27, 79, 66] => :ed_next_history, # ↓
145
- [27, 79, 67] => :ed_next_char, # →
146
- [27, 79, 68] => :ed_prev_char, # ←
147
132
  }.each_pair do |key, func|
148
133
  config.add_default_key_binding_by_keymap(:emacs, key, func)
149
134
  config.add_default_key_binding_by_keymap(:vi_insert, key, func)
@@ -245,39 +230,30 @@ class Reline::ANSI < Reline::IO
245
230
  self
246
231
  end
247
232
 
248
- def cursor_pos
249
- if both_tty?
250
- res = +''
251
- m = nil
252
- @input.raw do |stdin|
253
- @output << "\e[6n"
254
- @output.flush
255
- loop do
256
- c = stdin.getc
257
- next if c.nil?
258
- res << c
259
- m = res.match(/\e\[(?<row>\d+);(?<column>\d+)R/)
260
- break if m
261
- end
262
- (m.pre_match + m.post_match).chars.reverse_each do |ch|
263
- stdin.ungetc ch
233
+ private def cursor_pos_internal(timeout:)
234
+ match = nil
235
+ @input.raw do |stdin|
236
+ @output << "\e[6n"
237
+ @output.flush
238
+ timeout_at = Time.now + timeout
239
+ buf = +''
240
+ while (wait = timeout_at - Time.now) > 0 && stdin.wait_readable(wait)
241
+ buf << stdin.readpartial(1024)
242
+ if (match = buf.match(/\e\[(?<row>\d+);(?<column>\d+)R/))
243
+ buf = match.pre_match + match.post_match
244
+ break
264
245
  end
265
246
  end
266
- column = m[:column].to_i - 1
267
- row = m[:row].to_i - 1
268
- else
269
- begin
270
- buf = @output.pread(@output.pos, 0)
271
- row = buf.count("\n")
272
- column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0
273
- rescue Errno::ESPIPE, IOError
274
- # Just returns column 1 for ambiguous width because this I/O is not
275
- # tty and can't seek.
276
- row = 0
277
- column = 1
247
+ buf.chars.reverse_each do |ch|
248
+ stdin.ungetc ch
278
249
  end
279
250
  end
280
- Reline::CursorPos.new(column, row)
251
+ [match[:column].to_i - 1, match[:row].to_i - 1] if match
252
+ end
253
+
254
+ def cursor_pos
255
+ col, row = cursor_pos_internal(timeout: 0.5) if both_tty?
256
+ Reline::CursorPos.new(col || 0, row || 0)
281
257
  end
282
258
 
283
259
  def both_tty?
@@ -21,7 +21,7 @@ class Reline::Dumb < Reline::IO
21
21
  elsif RUBY_PLATFORM =~ /mswin|mingw/
22
22
  Encoding::UTF_8
23
23
  else
24
- Encoding::default_external
24
+ @input.external_encoding || Encoding::default_external
25
25
  end
26
26
  end
27
27
 
@@ -60,7 +60,7 @@ class Reline::Dumb < Reline::IO
60
60
  end
61
61
 
62
62
  def cursor_pos
63
- Reline::CursorPos.new(1, 1)
63
+ Reline::CursorPos.new(0, 0)
64
64
  end
65
65
 
66
66
  def hide_cursor
@@ -157,6 +157,7 @@ class Reline::Windows < Reline::IO
157
157
  STD_OUTPUT_HANDLE = -11
158
158
  FILE_TYPE_PIPE = 0x0003
159
159
  FILE_NAME_INFO = 2
160
+ ENABLE_WRAP_AT_EOL_OUTPUT = 2
160
161
  ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
161
162
 
162
163
  # Calling Win32API with console handle is reported to fail after executing some external command.
@@ -170,7 +171,7 @@ class Reline::Windows < Reline::IO
170
171
  end
171
172
 
172
173
  private def getconsolemode
173
- mode = "\000\000\000\000"
174
+ mode = +"\0\0\0\0"
174
175
  call_with_console_handle(@GetConsoleMode, mode)
175
176
  mode.unpack1('L')
176
177
  end
@@ -252,7 +253,7 @@ class Reline::Windows < Reline::IO
252
253
 
253
254
  key = KeyEventRecord.new(virtual_key_code, char_code, control_key_state)
254
255
 
255
- match = KEY_MAP.find { |args,| key.matches?(**args) }
256
+ match = KEY_MAP.find { |args,| key.match?(**args) }
256
257
  unless match.nil?
257
258
  @output_buf.concat(match.last)
258
259
  return
@@ -344,35 +345,38 @@ class Reline::Windows < Reline::IO
344
345
  # [18,2] dwMaximumWindowSize.X
345
346
  # [20,2] dwMaximumWindowSize.Y
346
347
  csbi = 0.chr * 22
347
- return if call_with_console_handle(@GetConsoleScreenBufferInfo, csbi) == 0
348
- csbi
348
+ if call_with_console_handle(@GetConsoleScreenBufferInfo, csbi) != 0
349
+ # returns [width, height, x, y, attributes, left, top, right, bottom]
350
+ csbi.unpack("s9")
351
+ else
352
+ return nil
353
+ end
349
354
  end
350
355
 
356
+ ALTERNATIVE_CSBI = [80, 24, 0, 0, 7, 0, 0, 79, 23].freeze
357
+
351
358
  def get_screen_size
352
- unless csbi = get_console_screen_buffer_info
353
- return [1, 1]
354
- end
355
- csbi[0, 4].unpack('SS').reverse
359
+ width, _, _, _, _, _, top, _, bottom = get_console_screen_buffer_info || ALTERNATIVE_CSBI
360
+ [bottom - top + 1, width]
356
361
  end
357
362
 
358
363
  def cursor_pos
359
- unless csbi = get_console_screen_buffer_info
360
- return Reline::CursorPos.new(0, 0)
361
- end
362
- x = csbi[4, 2].unpack1('s')
363
- y = csbi[6, 2].unpack1('s')
364
- Reline::CursorPos.new(x, y)
364
+ _, _, x, y, _, _, top, = get_console_screen_buffer_info || ALTERNATIVE_CSBI
365
+ Reline::CursorPos.new(x, y - top)
365
366
  end
366
367
 
367
368
  def move_cursor_column(val)
368
- call_with_console_handle(@SetConsoleCursorPosition, cursor_pos.y * 65536 + val)
369
+ _, _, _, y, = get_console_screen_buffer_info
370
+ call_with_console_handle(@SetConsoleCursorPosition, y * 65536 + val) if y
369
371
  end
370
372
 
371
373
  def move_cursor_up(val)
372
374
  if val > 0
373
- y = cursor_pos.y - val
375
+ _, _, x, y, _, _, top, = get_console_screen_buffer_info
376
+ return unless y
377
+ y = (y - top) - val
374
378
  y = 0 if y < 0
375
- call_with_console_handle(@SetConsoleCursorPosition, y * 65536 + cursor_pos.x)
379
+ call_with_console_handle(@SetConsoleCursorPosition, (y + top) * 65536 + x)
376
380
  elsif val < 0
377
381
  move_cursor_down(-val)
378
382
  end
@@ -380,58 +384,39 @@ class Reline::Windows < Reline::IO
380
384
 
381
385
  def move_cursor_down(val)
382
386
  if val > 0
383
- return unless csbi = get_console_screen_buffer_info
384
- screen_height = get_screen_size.first
385
- y = cursor_pos.y + val
386
- y = screen_height - 1 if y > (screen_height - 1)
387
- call_with_console_handle(@SetConsoleCursorPosition, (cursor_pos.y + val) * 65536 + cursor_pos.x)
387
+ _, _, x, y, _, _, top, _, bottom = get_console_screen_buffer_info
388
+ return unless y
389
+ screen_height = bottom - top
390
+ y = (y - top) + val
391
+ y = screen_height if y > screen_height
392
+ call_with_console_handle(@SetConsoleCursorPosition, (y + top) * 65536 + x)
388
393
  elsif val < 0
389
394
  move_cursor_up(-val)
390
395
  end
391
396
  end
392
397
 
393
398
  def erase_after_cursor
394
- return unless csbi = get_console_screen_buffer_info
395
- attributes = csbi[8, 2].unpack1('S')
396
- cursor = csbi[4, 4].unpack1('L')
399
+ width, _, x, y, attributes, = get_console_screen_buffer_info
400
+ return unless x
397
401
  written = 0.chr * 4
398
- call_with_console_handle(@FillConsoleOutputCharacter, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
399
- call_with_console_handle(@FillConsoleOutputAttribute, attributes, get_screen_size.last - cursor_pos.x, cursor, written)
400
- end
401
-
402
- def scroll_down(val)
403
- return if val < 0
404
- return unless csbi = get_console_screen_buffer_info
405
- buffer_width, buffer_lines, x, y, attributes, window_left, window_top, window_bottom = csbi.unpack('ssssSssx2s')
406
- screen_height = window_bottom - window_top + 1
407
- val = screen_height if val > screen_height
408
-
409
- if @legacy_console || window_left != 0
410
- # unless ENABLE_VIRTUAL_TERMINAL,
411
- # if srWindow.Left != 0 then it's conhost.exe hosted console
412
- # and puts "\n" causes horizontal scroll. its glitch.
413
- # FYI irb write from culumn 1, so this gives no gain.
414
- scroll_rectangle = [0, val, buffer_width, buffer_lines - val].pack('s4')
415
- destination_origin = 0 # y * 65536 + x
416
- fill = [' '.ord, attributes].pack('SS')
417
- call_with_console_handle(@ScrollConsoleScreenBuffer, scroll_rectangle, nil, destination_origin, fill)
418
- else
419
- origin_x = x + 1
420
- origin_y = y - window_top + 1
421
- @output.write [
422
- (origin_y != screen_height) ? "\e[#{screen_height};H" : nil,
423
- "\n" * val,
424
- (origin_y != screen_height or !x.zero?) ? "\e[#{origin_y};#{origin_x}H" : nil
425
- ].join
426
- end
402
+ call_with_console_handle(@FillConsoleOutputCharacter, 0x20, width - x, y * 65536 + x, written)
403
+ call_with_console_handle(@FillConsoleOutputAttribute, attributes, width - x, y * 65536 + x, written)
404
+ end
405
+
406
+ # This only works when the cursor is at the bottom of the scroll range
407
+ # For more details, see https://github.com/ruby/reline/pull/577#issuecomment-1646679623
408
+ def scroll_down(x)
409
+ return if x.zero?
410
+ # We use `\n` instead of CSI + S because CSI + S would cause https://github.com/ruby/reline/issues/576
411
+ @output.write "\n" * x
427
412
  end
428
413
 
429
414
  def clear_screen
430
415
  if @legacy_console
431
- return unless csbi = get_console_screen_buffer_info
432
- buffer_width, _buffer_lines, attributes, window_top, window_bottom = csbi.unpack('ss@8S@12sx2s')
433
- fill_length = buffer_width * (window_bottom - window_top + 1)
434
- screen_topleft = window_top * 65536
416
+ width, _, _, _, attributes, _, top, _, bottom = get_console_screen_buffer_info
417
+ return unless width
418
+ fill_length = width * (bottom - top + 1)
419
+ screen_topleft = top * 65536
435
420
  written = 0.chr * 4
436
421
  call_with_console_handle(@FillConsoleOutputCharacter, 0x20, fill_length, screen_topleft, written)
437
422
  call_with_console_handle(@FillConsoleOutputAttribute, attributes, fill_length, screen_topleft, written)
@@ -472,6 +457,28 @@ class Reline::Windows < Reline::IO
472
457
  # do nothing
473
458
  end
474
459
 
460
+ def disable_auto_linewrap(setting = true, &block)
461
+ mode = getconsolemode
462
+ if 0 == (mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)
463
+ if block
464
+ begin
465
+ setconsolemode(mode & ~ENABLE_WRAP_AT_EOL_OUTPUT)
466
+ block.call
467
+ ensure
468
+ setconsolemode(mode | ENABLE_WRAP_AT_EOL_OUTPUT)
469
+ end
470
+ else
471
+ if setting
472
+ setconsolemode(mode & ~ENABLE_WRAP_AT_EOL_OUTPUT)
473
+ else
474
+ setconsolemode(mode | ENABLE_WRAP_AT_EOL_OUTPUT)
475
+ end
476
+ end
477
+ else
478
+ block.call if block
479
+ end
480
+ end
481
+
475
482
  class KeyEventRecord
476
483
 
477
484
  attr_reader :virtual_key_code, :char_code, :control_key_state, :control_keys
@@ -501,7 +508,7 @@ class Reline::Windows < Reline::IO
501
508
  # Verifies if the arguments match with this key event.
502
509
  # Nil arguments are ignored, but at least one must be passed as non-nil.
503
510
  # To verify that no control keys were pressed, pass an empty array: `control_keys: []`.
504
- def matches?(control_keys: nil, virtual_key_code: nil, char_code: nil)
511
+ def match?(control_keys: nil, virtual_key_code: nil, char_code: nil)
505
512
  raise ArgumentError, 'No argument was passed to match key event' if control_keys.nil? && virtual_key_code.nil? && char_code.nil?
506
513
 
507
514
  (control_keys.nil? || [*control_keys].sort == @control_keys) &&
@@ -72,17 +72,21 @@ class Reline::LineEditor
72
72
 
73
73
  MINIMUM_SCROLLBAR_HEIGHT = 1
74
74
 
75
- def initialize(config, encoding)
75
+ def initialize(config)
76
76
  @config = config
77
77
  @completion_append_character = ''
78
78
  @screen_size = [0, 0] # Should be initialized with actual winsize in LineEditor#reset
79
- reset_variables(encoding: encoding)
79
+ reset_variables
80
80
  end
81
81
 
82
82
  def io_gate
83
83
  Reline::IOGate
84
84
  end
85
85
 
86
+ def encoding
87
+ io_gate.encoding
88
+ end
89
+
86
90
  def set_pasting_state(in_pasting)
87
91
  # While pasting, text to be inserted is stored to @continuous_insertion_buffer.
88
92
  # After pasting, this buffer should be force inserted.
@@ -136,9 +140,9 @@ class Reline::LineEditor
136
140
  end
137
141
  end
138
142
 
139
- def reset(prompt = '', encoding:)
143
+ def reset(prompt = '')
140
144
  @screen_size = Reline::IOGate.get_screen_size
141
- reset_variables(prompt, encoding: encoding)
145
+ reset_variables(prompt)
142
146
  @rendered_screen.base_y = Reline::IOGate.cursor_pos.y
143
147
  if ENV.key?('RELINE_ALT_SCROLLBAR')
144
148
  @full_block = '::'
@@ -150,7 +154,7 @@ class Reline::LineEditor
150
154
  @upper_half_block = '▀'
151
155
  @lower_half_block = '▄'
152
156
  @block_elem_width = 1
153
- elsif @encoding == Encoding::UTF_8
157
+ elsif encoding == Encoding::UTF_8
154
158
  @full_block = '█'
155
159
  @upper_half_block = '▀'
156
160
  @lower_half_block = '▄'
@@ -219,10 +223,9 @@ class Reline::LineEditor
219
223
  @eof
220
224
  end
221
225
 
222
- def reset_variables(prompt = '', encoding:)
226
+ def reset_variables(prompt = '')
223
227
  @prompt = prompt.gsub("\n", "\\n")
224
228
  @mark_pointer = nil
225
- @encoding = encoding
226
229
  @is_multiline = false
227
230
  @finished = false
228
231
  @history_pointer = nil
@@ -239,7 +242,7 @@ class Reline::LineEditor
239
242
  @searching_prompt = nil
240
243
  @just_cursor_moving = false
241
244
  @eof = false
242
- @continuous_insertion_buffer = String.new(encoding: @encoding)
245
+ @continuous_insertion_buffer = String.new(encoding: encoding)
243
246
  @scroll_partial_screen = 0
244
247
  @drop_terminate_spaces = false
245
248
  @in_pasting = false
@@ -259,7 +262,7 @@ class Reline::LineEditor
259
262
 
260
263
  def reset_line
261
264
  @byte_pointer = 0
262
- @buffer_of_lines = [String.new(encoding: @encoding)]
265
+ @buffer_of_lines = [String.new(encoding: encoding)]
263
266
  @line_index = 0
264
267
  @cache.clear
265
268
  @line_backup_in_history = nil
@@ -275,7 +278,7 @@ class Reline::LineEditor
275
278
  end
276
279
 
277
280
  private def insert_new_line(cursor_line, next_line)
278
- @buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: @encoding))
281
+ @buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: encoding))
279
282
  @buffer_of_lines[@line_index] = cursor_line
280
283
  @line_index += 1
281
284
  @byte_pointer = 0
@@ -298,7 +301,7 @@ class Reline::LineEditor
298
301
  end
299
302
 
300
303
  private def split_by_width(str, max_width, offset: 0)
301
- Reline::Unicode.split_by_width(str, max_width, @encoding, offset: offset)
304
+ Reline::Unicode.split_by_width(str, max_width, encoding, offset: offset)
302
305
  end
303
306
 
304
307
  def current_byte_pointer_cursor
@@ -461,7 +464,7 @@ class Reline::LineEditor
461
464
  def render_finished
462
465
  render_differential([], 0, 0)
463
466
  lines = @buffer_of_lines.size.times.map do |i|
464
- line = prompt_list[i] + modified_lines[i]
467
+ line = Reline::Unicode.strip_non_printing_start_end(prompt_list[i]) + modified_lines[i]
465
468
  wrapped_lines, = split_by_width(line, screen_width)
466
469
  wrapped_lines.last.empty? ? "#{line} " : line
467
470
  end
@@ -469,8 +472,11 @@ class Reline::LineEditor
469
472
  end
470
473
 
471
474
  def print_nomultiline_prompt
475
+ Reline::IOGate.disable_auto_linewrap(true) if Reline::IOGate.win?
472
476
  # Readline's test `TestRelineAsReadline#test_readline` requires first output to be prompt, not cursor reset escape sequence.
473
- @output.write @prompt if @prompt && !@is_multiline
477
+ @output.write Reline::Unicode.strip_non_printing_start_end(@prompt) if @prompt && !@is_multiline
478
+ ensure
479
+ Reline::IOGate.disable_auto_linewrap(false) if Reline::IOGate.win?
474
480
  end
475
481
 
476
482
  def render
@@ -506,6 +512,7 @@ class Reline::LineEditor
506
512
  # by calculating the difference from the previous render.
507
513
 
508
514
  private def render_differential(new_lines, new_cursor_x, new_cursor_y)
515
+ Reline::IOGate.disable_auto_linewrap(true) if Reline::IOGate.win?
509
516
  rendered_lines = @rendered_screen.lines
510
517
  cursor_y = @rendered_screen.cursor_y
511
518
  if new_lines != rendered_lines
@@ -536,6 +543,8 @@ class Reline::LineEditor
536
543
  Reline::IOGate.move_cursor_column new_cursor_x
537
544
  Reline::IOGate.move_cursor_down new_cursor_y - cursor_y
538
545
  @rendered_screen.cursor_y = new_cursor_y
546
+ ensure
547
+ Reline::IOGate.disable_auto_linewrap(false) if Reline::IOGate.win?
539
548
  end
540
549
 
541
550
  private def clear_rendered_screen_cache
@@ -797,7 +806,7 @@ class Reline::LineEditor
797
806
 
798
807
  private def complete_internal_proc(list, is_menu)
799
808
  preposing, target, postposing = retrieve_completion_block
800
- list = list.select { |i|
809
+ candidates = list.select { |i|
801
810
  if i and not Encoding.compatible?(target.encoding, i.encoding)
802
811
  raise Encoding::CompatibilityError, "#{target.encoding.name} is not compatible with #{i.encoding.name}"
803
812
  end
@@ -808,10 +817,10 @@ class Reline::LineEditor
808
817
  end
809
818
  }.uniq
810
819
  if is_menu
811
- menu(target, list)
820
+ menu(target, candidates)
812
821
  return nil
813
822
  end
814
- completed = list.inject { |memo, item|
823
+ completed = candidates.inject { |memo, item|
815
824
  begin
816
825
  memo_mbchars = memo.unicode_normalize.grapheme_clusters
817
826
  item_mbchars = item.unicode_normalize.grapheme_clusters
@@ -838,7 +847,8 @@ class Reline::LineEditor
838
847
  end
839
848
  result
840
849
  }
841
- [target, preposing, completed, postposing]
850
+
851
+ [target, preposing, completed, postposing, candidates]
842
852
  end
843
853
 
844
854
  private def perform_completion(list, just_show_list)
@@ -846,7 +856,11 @@ class Reline::LineEditor
846
856
  when CompletionState::NORMAL
847
857
  @completion_state = CompletionState::COMPLETION
848
858
  when CompletionState::PERFECT_MATCH
849
- @dig_perfect_match_proc&.(@perfect_matched)
859
+ if @dig_perfect_match_proc
860
+ @dig_perfect_match_proc.(@perfect_matched)
861
+ else
862
+ @completion_state = CompletionState::COMPLETION
863
+ end
850
864
  end
851
865
  if just_show_list
852
866
  is_menu = true
@@ -862,24 +876,26 @@ class Reline::LineEditor
862
876
  @completion_state = CompletionState::PERFECT_MATCH
863
877
  end
864
878
  return if result.nil?
865
- target, preposing, completed, postposing = result
879
+ target, preposing, completed, postposing, candidates = result
866
880
  return if completed.nil?
867
881
  if target <= completed and (@completion_state == CompletionState::COMPLETION)
868
- if list.include?(completed)
869
- if list.one?
882
+ append_character = ''
883
+ if candidates.include?(completed)
884
+ if candidates.one?
885
+ append_character = completion_append_character.to_s
870
886
  @completion_state = CompletionState::PERFECT_MATCH
871
887
  else
872
888
  @completion_state = CompletionState::MENU_WITH_PERFECT_MATCH
873
- perform_completion(list, true) if @config.show_all_if_ambiguous
889
+ perform_completion(candidates, true) if @config.show_all_if_ambiguous
874
890
  end
875
891
  @perfect_matched = completed
876
892
  else
877
893
  @completion_state = CompletionState::MENU
878
- perform_completion(list, true) if @config.show_all_if_ambiguous
894
+ perform_completion(candidates, true) if @config.show_all_if_ambiguous
879
895
  end
880
- if not just_show_list and target < completed
881
- @buffer_of_lines[@line_index] = (preposing + completed + completion_append_character.to_s + postposing).split("\n")[@line_index] || String.new(encoding: @encoding)
882
- line_to_pointer = (preposing + completed + completion_append_character.to_s).split("\n")[@line_index] || String.new(encoding: @encoding)
896
+ unless just_show_list
897
+ @buffer_of_lines[@line_index] = (preposing + completed + append_character + postposing).split("\n")[@line_index] || String.new(encoding: encoding)
898
+ line_to_pointer = (preposing + completed + append_character).split("\n")[@line_index] || String.new(encoding: encoding)
883
899
  @byte_pointer = line_to_pointer.bytesize
884
900
  end
885
901
  end
@@ -1054,8 +1070,8 @@ class Reline::LineEditor
1054
1070
  private def normal_char(key)
1055
1071
  @multibyte_buffer << key.combined_char
1056
1072
  if @multibyte_buffer.size > 1
1057
- if @multibyte_buffer.dup.force_encoding(@encoding).valid_encoding?
1058
- process_key(@multibyte_buffer.dup.force_encoding(@encoding), nil)
1073
+ if @multibyte_buffer.dup.force_encoding(encoding).valid_encoding?
1074
+ process_key(@multibyte_buffer.dup.force_encoding(encoding), nil)
1059
1075
  @multibyte_buffer.clear
1060
1076
  else
1061
1077
  # invalid
@@ -1313,7 +1329,7 @@ class Reline::LineEditor
1313
1329
  if (lines.size - 1) > @line_index
1314
1330
  postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n")
1315
1331
  end
1316
- [preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
1332
+ [preposing.encode(encoding), target.encode(encoding), postposing.encode(encoding)]
1317
1333
  end
1318
1334
 
1319
1335
  def confirm_multiline_termination
@@ -1325,7 +1341,7 @@ class Reline::LineEditor
1325
1341
  save_old_buffer
1326
1342
  pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer)
1327
1343
  post = @buffer_of_lines[@line_index].byteslice(@byte_pointer..)
1328
- lines = (pre + text.gsub(/\r\n?/, "\n") + post).split("\n", -1)
1344
+ lines = (pre + Reline::Unicode.safe_encode(text, encoding).gsub(/\r\n?/, "\n") + post).split("\n", -1)
1329
1345
  lines << '' if lines.empty?
1330
1346
  @buffer_of_lines[@line_index, 1] = lines
1331
1347
  @line_index += lines.size - 1
@@ -1370,7 +1386,7 @@ class Reline::LineEditor
1370
1386
  last += current_line.bytesize if last < 0
1371
1387
  first += current_line.bytesize if first < 0
1372
1388
  range = range.exclude_end? ? first...last : first..last
1373
- line = current_line.bytes.reject.with_index{ |c, i| range.include?(i) }.map{ |c| c.chr(Encoding::ASCII_8BIT) }.join.force_encoding(@encoding)
1389
+ line = current_line.bytes.reject.with_index{ |c, i| range.include?(i) }.map{ |c| c.chr(Encoding::ASCII_8BIT) }.join.force_encoding(encoding)
1374
1390
  set_current_line(line)
1375
1391
  else
1376
1392
  set_current_line(current_line.byteslice(0, start))
@@ -1581,7 +1597,7 @@ class Reline::LineEditor
1581
1597
  alias_method :end_of_line, :ed_move_to_end
1582
1598
 
1583
1599
  private def generate_searcher(search_key)
1584
- search_word = String.new(encoding: @encoding)
1600
+ search_word = String.new(encoding: encoding)
1585
1601
  multibyte_buf = String.new(encoding: 'ASCII-8BIT')
1586
1602
  hit_pointer = nil
1587
1603
  lambda do |key|
@@ -1598,8 +1614,8 @@ class Reline::LineEditor
1598
1614
  search_key = key
1599
1615
  else
1600
1616
  multibyte_buf << key
1601
- if multibyte_buf.dup.force_encoding(@encoding).valid_encoding?
1602
- search_word << multibyte_buf.dup.force_encoding(@encoding)
1617
+ if multibyte_buf.dup.force_encoding(encoding).valid_encoding?
1618
+ search_word << multibyte_buf.dup.force_encoding(encoding)
1603
1619
  multibyte_buf.clear
1604
1620
  end
1605
1621
  end
@@ -1665,57 +1681,29 @@ class Reline::LineEditor
1665
1681
  end
1666
1682
 
1667
1683
  private def incremental_search_history(key)
1668
- unless @history_pointer
1669
- @line_backup_in_history = whole_buffer
1670
- end
1684
+ backup = @buffer_of_lines.dup, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history
1671
1685
  searcher = generate_searcher(key)
1672
1686
  @searching_prompt = "(reverse-i-search)`': "
1673
1687
  termination_keys = ["\C-j".ord]
1674
- termination_keys.concat(@config.isearch_terminators&.chars&.map(&:ord)) if @config.isearch_terminators
1688
+ termination_keys.concat(@config.isearch_terminators.chars.map(&:ord)) if @config.isearch_terminators
1675
1689
  @waiting_proc = ->(k) {
1676
- case k
1677
- when *termination_keys
1678
- if @history_pointer
1679
- buffer = Reline::HISTORY[@history_pointer]
1680
- else
1681
- buffer = @line_backup_in_history
1682
- end
1683
- @buffer_of_lines = buffer.split("\n")
1684
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1685
- @line_index = @buffer_of_lines.size - 1
1690
+ chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
1691
+ if k == "\C-g".ord
1692
+ # cancel search and restore buffer
1693
+ @buffer_of_lines, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history = backup
1686
1694
  @searching_prompt = nil
1687
1695
  @waiting_proc = nil
1688
- @byte_pointer = 0
1689
- when "\C-g".ord
1690
- @buffer_of_lines = @line_backup_in_history.split("\n")
1691
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1692
- @line_index = @buffer_of_lines.size - 1
1693
- move_history(nil, line: :end, cursor: :end, save_buffer: false)
1696
+ elsif !termination_keys.include?(k) && (chr.match?(/[[:print:]]/) || k == "\C-h".ord || k == "\C-?".ord || k == "\C-r".ord || k == "\C-s".ord)
1697
+ search_word, prompt_name, hit_pointer = searcher.call(k)
1698
+ Reline.last_incremental_search = search_word
1699
+ @searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
1700
+ @searching_prompt += ': ' unless @is_multiline
1701
+ move_history(hit_pointer, line: :end, cursor: :end) if hit_pointer
1702
+ else
1703
+ # terminaton_keys and other keys will terminalte
1704
+ move_history(@history_pointer, line: :end, cursor: :start)
1694
1705
  @searching_prompt = nil
1695
1706
  @waiting_proc = nil
1696
- @byte_pointer = 0
1697
- else
1698
- chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
1699
- if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord
1700
- search_word, prompt_name, hit_pointer = searcher.call(k)
1701
- Reline.last_incremental_search = search_word
1702
- @searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
1703
- @searching_prompt += ': ' unless @is_multiline
1704
- move_history(hit_pointer, line: :end, cursor: :end, save_buffer: false) if hit_pointer
1705
- else
1706
- if @history_pointer
1707
- line = Reline::HISTORY[@history_pointer]
1708
- else
1709
- line = @line_backup_in_history
1710
- end
1711
- @line_backup_in_history = whole_buffer
1712
- @buffer_of_lines = line.split("\n")
1713
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1714
- @line_index = @buffer_of_lines.size - 1
1715
- @searching_prompt = nil
1716
- @waiting_proc = nil
1717
- @byte_pointer = 0
1718
- end
1719
1707
  end
1720
1708
  }
1721
1709
  end
@@ -1770,14 +1758,14 @@ class Reline::LineEditor
1770
1758
  end
1771
1759
  alias_method :history_search_forward, :ed_search_next_history
1772
1760
 
1773
- private def move_history(history_pointer, line:, cursor:, save_buffer: true)
1761
+ private def move_history(history_pointer, line:, cursor:)
1774
1762
  history_pointer ||= Reline::HISTORY.size
1775
1763
  return if history_pointer < 0 || history_pointer > Reline::HISTORY.size
1776
1764
  old_history_pointer = @history_pointer || Reline::HISTORY.size
1777
1765
  if old_history_pointer == Reline::HISTORY.size
1778
- @line_backup_in_history = save_buffer ? whole_buffer : ''
1766
+ @line_backup_in_history = whole_buffer
1779
1767
  else
1780
- Reline::HISTORY[old_history_pointer] = whole_buffer if save_buffer
1768
+ Reline::HISTORY[old_history_pointer] = whole_buffer
1781
1769
  end
1782
1770
  if history_pointer == Reline::HISTORY.size
1783
1771
  buf = @line_backup_in_history
@@ -1787,7 +1775,7 @@ class Reline::LineEditor
1787
1775
  @history_pointer = history_pointer
1788
1776
  end
1789
1777
  @buffer_of_lines = buf.split("\n")
1790
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
1778
+ @buffer_of_lines = [String.new(encoding: encoding)] if @buffer_of_lines.empty?
1791
1779
  @line_index = line == :start ? 0 : line == :end ? @buffer_of_lines.size - 1 : line
1792
1780
  @byte_pointer = cursor == :start ? 0 : cursor == :end ? current_line.bytesize : cursor
1793
1781
  end
@@ -2312,7 +2300,7 @@ class Reline::LineEditor
2312
2300
  }
2313
2301
  system("#{ENV['EDITOR']} #{path}")
2314
2302
  @buffer_of_lines = File.read(path).split("\n")
2315
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
2303
+ @buffer_of_lines = [String.new(encoding: encoding)] if @buffer_of_lines.empty?
2316
2304
  @line_index = 0
2317
2305
  finish
2318
2306
  end
@@ -2396,9 +2384,9 @@ class Reline::LineEditor
2396
2384
 
2397
2385
  private def search_next_char(key, arg, need_prev_char: false, inclusive: false)
2398
2386
  if key.instance_of?(String)
2399
- inputed_char = key
2387
+ inputted_char = key
2400
2388
  else
2401
- inputed_char = key.chr
2389
+ inputted_char = key.chr
2402
2390
  end
2403
2391
  prev_total = nil
2404
2392
  total = nil
@@ -2410,7 +2398,7 @@ class Reline::LineEditor
2410
2398
  width = Reline::Unicode.get_mbchar_width(mbchar)
2411
2399
  total = [mbchar.bytesize, width]
2412
2400
  else
2413
- if inputed_char == mbchar
2401
+ if inputted_char == mbchar
2414
2402
  arg -= 1
2415
2403
  if arg.zero?
2416
2404
  found = true
@@ -2448,9 +2436,9 @@ class Reline::LineEditor
2448
2436
 
2449
2437
  private def search_prev_char(key, arg, need_next_char = false)
2450
2438
  if key.instance_of?(String)
2451
- inputed_char = key
2439
+ inputted_char = key
2452
2440
  else
2453
- inputed_char = key.chr
2441
+ inputted_char = key.chr
2454
2442
  end
2455
2443
  prev_total = nil
2456
2444
  total = nil
@@ -2462,7 +2450,7 @@ class Reline::LineEditor
2462
2450
  width = Reline::Unicode.get_mbchar_width(mbchar)
2463
2451
  total = [mbchar.bytesize, width]
2464
2452
  else
2465
- if inputed_char == mbchar
2453
+ if inputted_char == mbchar
2466
2454
  arg -= 1
2467
2455
  if arg.zero?
2468
2456
  found = true
@@ -54,6 +54,22 @@ class Reline::Unicode
54
54
  }.join
55
55
  end
56
56
 
57
+ def self.safe_encode(str, encoding)
58
+ # Reline only supports utf-8 convertible string.
59
+ converted = str.encode(encoding, invalid: :replace, undef: :replace)
60
+ return converted if str.encoding == Encoding::UTF_8 || converted.encoding == Encoding::UTF_8 || converted.ascii_only?
61
+
62
+ # This code is essentially doing the same thing as
63
+ # `str.encode(utf8, **replace_options).encode(encoding, **replace_options)`
64
+ # but also avoids unneccesary irreversible encoding conversion.
65
+ converted.gsub(/\X/) do |c|
66
+ c.encode(Encoding::UTF_8)
67
+ c
68
+ rescue Encoding::UndefinedConversionError
69
+ '?'
70
+ end
71
+ end
72
+
57
73
  require 'reline/unicode/east_asian_width'
58
74
 
59
75
  def self.get_mbchar_width(mbchar)
@@ -116,10 +132,8 @@ class Reline::Unicode
116
132
  case
117
133
  when non_printing_start
118
134
  in_zero_width = true
119
- lines.last << NON_PRINTING_START
120
135
  when non_printing_end
121
136
  in_zero_width = false
122
- lines.last << NON_PRINTING_END
123
137
  when csi
124
138
  lines.last << csi
125
139
  unless in_zero_width
@@ -131,7 +145,7 @@ class Reline::Unicode
131
145
  end
132
146
  when osc
133
147
  lines.last << osc
134
- seq << osc
148
+ seq << osc unless in_zero_width
135
149
  when gc
136
150
  unless in_zero_width
137
151
  mbchar_width = get_mbchar_width(gc)
@@ -154,6 +168,10 @@ class Reline::Unicode
154
168
  [lines, height]
155
169
  end
156
170
 
171
+ def self.strip_non_printing_start_end(prompt)
172
+ prompt.gsub(/\x01([^\x02]*)(?:\x02|\z)/) { $1 }
173
+ end
174
+
157
175
  # Take a chunk of a String cut by width with escape sequences.
158
176
  def self.take_range(str, start_col, max_width)
159
177
  take_mbchar_range(str, start_col, max_width).first
@@ -173,10 +191,8 @@ class Reline::Unicode
173
191
  case
174
192
  when non_printing_start
175
193
  in_zero_width = true
176
- chunk << NON_PRINTING_START
177
194
  when non_printing_end
178
195
  in_zero_width = false
179
- chunk << NON_PRINTING_END
180
196
  when csi
181
197
  has_csi = true
182
198
  chunk << csi
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.5.10'
2
+ VERSION = '0.5.11'
3
3
  end
data/lib/reline.rb CHANGED
@@ -308,7 +308,7 @@ module Reline
308
308
  otio = io_gate.prep
309
309
 
310
310
  may_req_ambiguous_char_width
311
- line_editor.reset(prompt, encoding: encoding)
311
+ line_editor.reset(prompt)
312
312
  if multiline
313
313
  line_editor.multiline_on
314
314
  if block_given?
@@ -412,7 +412,7 @@ module Reline
412
412
  end
413
413
 
414
414
  private def may_req_ambiguous_char_width
415
- @ambiguous_width = 2 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
415
+ @ambiguous_width = 1 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
416
416
  return if defined? @ambiguous_width
417
417
  io_gate.move_cursor_column(0)
418
418
  begin
@@ -421,7 +421,7 @@ module Reline
421
421
  # LANG=C
422
422
  @ambiguous_width = 1
423
423
  else
424
- @ambiguous_width = io_gate.cursor_pos.x
424
+ @ambiguous_width = io_gate.cursor_pos.x == 2 ? 2 : 1
425
425
  end
426
426
  io_gate.move_cursor_column(0)
427
427
  io_gate.erase_after_cursor
@@ -487,7 +487,7 @@ module Reline
487
487
  @core ||= Core.new { |core|
488
488
  core.config = Reline::Config.new
489
489
  core.key_stroke = Reline::KeyStroke.new(core.config)
490
- core.line_editor = Reline::LineEditor.new(core.config, core.encoding)
490
+ core.line_editor = Reline::LineEditor.new(core.config)
491
491
 
492
492
  core.basic_word_break_characters = " \t\n`><=;|&{("
493
493
  core.completer_word_break_characters = " \t\n`><=;|&{("
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.10
4
+ version: 0.5.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2024-09-05 00:00:00.000000000 Z
10
+ date: 2024-11-08 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: io-console