@@ -17,19 +17,9 @@ module Reline
17
17
18
18
class ConfigEncodingConversionError < StandardError ; end
19
19
20
- 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
20
+ Key = Struct . new ( :char , :method_symbol , :bytes ) do
21
+ def match? ( sym )
22
+ method_symbol == sym
33
23
end
34
24
alias_method :== , :match?
35
25
end
@@ -349,24 +339,22 @@ def readline(prompt = '', add_hist = false)
349
339
begin
350
340
line_editor . set_signal_handlers
351
341
loop do
352
- read_io ( config . keyseq_timeout ) { |inputs |
353
- line_editor . set_pasting_state ( io_gate . in_pasting? )
354
- inputs . each do |key |
355
- if key . char == :bracketed_paste_start
356
- text = io_gate . read_bracketed_paste
357
- line_editor . insert_pasted_text ( text )
358
- line_editor . scroll_into_view
359
- else
360
- line_editor . update ( key )
361
- end
362
- end
342
+ wait_occurs = false
343
+ key = read_io ( config . keyseq_timeout ) {
344
+ line_editor . set_pasting_state ( false )
345
+ wait_occurs = true
346
+ line_editor . rerender
363
347
}
348
+ line_editor . set_pasting_state ( !wait_occurs && io_gate . in_pasting? )
349
+ if key . method_symbol == :bracketed_paste_start
350
+ line_editor . insert_pasted_text ( io_gate . read_bracketed_paste )
351
+ line_editor . scroll_into_view
352
+ else
353
+ line_editor . update ( key )
354
+ end
364
355
if line_editor . finished?
365
356
line_editor . render_finished
366
357
break
367
- else
368
- line_editor . set_pasting_state ( io_gate . in_pasting? )
369
- line_editor . rerender
370
358
end
371
359
end
372
360
io_gate . move_cursor_column ( 0 )
@@ -378,92 +366,41 @@ def readline(prompt = '', add_hist = false)
378
366
end
379
367
end
380
368
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.
369
+ # GNU Readline waits for "keyseq-timeout" milliseconds when the input is ambiguous whether it is matching or matched.
370
+ # For example, ESC can be a standalone ESC or part of a sequence that starts with ESC.
371
+ # GNU Readline also waits for any other amibugous keybindings defined in inputrc.
390
372
private def read_io ( keyseq_timeout , &block )
391
373
buffer = [ ]
374
+ prev_status = :matching
392
375
loop do
393
- c = io_gate . getc ( Float ::INFINITY )
394
- if c == -1
395
- result = :unmatched
376
+ timeout = prev_status == :matching_matched ? keyseq_timeout . fdiv ( 1000 ) : Float ::INFINITY
377
+ block . call unless io_gate . in_pasting?
378
+ c = io_gate . getc ( timeout )
379
+ if c == -1 || c . nil?
380
+ if prev_status != :matching_matched
381
+ # Input closed
382
+ return Reline ::Key . new ( nil , nil , [ ] )
383
+ end
384
+ status = :matched
396
385
else
397
386
buffer << c
398
- result = key_stroke . match_status ( buffer )
387
+ status = key_stroke . match_status ( buffer )
399
388
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
389
+ if status == :matched || ( prev_status != :unmatched && status == :unmatched )
390
+ expanded , bytes , rest = key_stroke . expand ( buffer )
391
+ if expanded . is_a? ( Array )
392
+ rest = expanded + rest
413
393
end
414
- when :unmatched
415
- if buffer . size == 1 and c == "\e " . ord
416
- read_escaped_key ( keyseq_timeout , c , block )
417
- else
418
- expanded = buffer . map { |expanded_c |
419
- Reline ::Key . new ( expanded_c , expanded_c , false )
420
- }
421
- block . ( expanded )
394
+ rest . reverse_each { |c | io_gate . ungetc ( c ) }
395
+ buffer = [ ]
396
+ case expanded
397
+ when Symbol
398
+ return Reline ::Key . new ( bytes . last , expanded , bytes )
399
+ when String
400
+ return Reline ::Key . new ( expanded , :ed_insert , bytes )
422
401
end
423
- break
424
402
end
425
- end
426
- end
427
-
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
449
- 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 ) ] )
403
+ prev_status = status
467
404
end
468
405
end
469
406
@@ -547,7 +484,7 @@ def self.encoding_system_needs
547
484
def self . core
548
485
@core ||= Core . new { |core |
549
486
core . config = Reline ::Config . new
550
- core . key_stroke = Reline ::KeyStroke . new ( core . config )
487
+ core . key_stroke = Reline ::KeyStroke . new ( core . config , core . encoding )
551
488
core . line_editor = Reline ::LineEditor . new ( core . config , core . encoding )
552
489
553
490
core . basic_word_break_characters = " \t \n `><=;|&{("
0 commit comments