diff --git a/lib/reline.rb b/lib/reline.rb index 0a2dba4f0d..ee88cf2c13 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -1,5 +1,4 @@ require 'io/console' -require 'timeout' require 'forwardable' require 'reline/version' require 'reline/config' @@ -397,7 +396,7 @@ def readline(prompt = '', add_hist = false) private def read_io(keyseq_timeout, &block) buffer = [] loop do - c = io_gate.getc + c = io_gate.getc(Float::INFINITY) if c == -1 result = :unmatched @bracketed_paste_finished = true @@ -434,15 +433,9 @@ def readline(prompt = '', add_hist = false) end private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block) - begin - succ_c = nil - Timeout.timeout(keyseq_timeout / 1000.0) { - succ_c = io_gate.getc - } - rescue Timeout::Error # cancel matching only when first byte - block.([Reline::Key.new(c, c, false)]) - return :break - else + succ_c = io_gate.getc(keyseq_timeout / 100) + + if succ_c case key_stroke.match_status(buffer.dup.push(succ_c)) when :unmatched if c == "\e".ord @@ -462,27 +455,23 @@ def readline(prompt = '', add_hist = false) block.(expanded) return :break end + else + block.([Reline::Key.new(c, c, false)]) + return :break end end private def read_escaped_key(keyseq_timeout, c, block) - begin - escaped_c = nil - Timeout.timeout(keyseq_timeout / 1000.0) { - escaped_c = io_gate.getc - } - rescue Timeout::Error # independent ESC + escaped_c = io_gate.getc(keyseq_timeout / 100) + + if escaped_c.nil? block.([Reline::Key.new(c, c, false)]) + elsif escaped_c >= 128 # maybe, first byte of multi byte + block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)]) + elsif escaped_c == "\e".ord # escape twice + block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)]) else - if escaped_c.nil? - block.([Reline::Key.new(c, c, false)]) - elsif escaped_c >= 128 # maybe, first byte of multi byte - block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)]) - elsif escaped_c == "\e".ord # escape twice - block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)]) - else - block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)]) - end + block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)]) end end diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb index d1a0e5b138..e4a07a4a34 100644 --- a/lib/reline/ansi.rb +++ b/lib/reline/ansi.rb @@ -1,6 +1,5 @@ require 'io/console' require 'io/wait' -require 'timeout' require_relative 'terminfo' class Reline::ANSI @@ -154,11 +153,14 @@ def self.with_raw_input end @@buf = [] - def self.inner_getc + # a single count is 0.1 sec + def self.inner_getc(count) unless @@buf.empty? return @@buf.shift end until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte } + count -= 1 + return nil if count <= 0 Reline.core.line_editor.resize end (c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c @@ -172,40 +174,37 @@ def self.inner_getc @@in_bracketed_paste_mode = false START_BRACKETED_PASTE = String.new("\e[200~,", encoding: Encoding::ASCII_8BIT) END_BRACKETED_PASTE = String.new("\e[200~.", encoding: Encoding::ASCII_8BIT) - def self.getc_with_bracketed_paste + def self.getc_with_bracketed_paste(count) buffer = String.new(encoding: Encoding::ASCII_8BIT) - buffer << inner_getc + buffer << inner_getc(count) while START_BRACKETED_PASTE.start_with?(buffer) or END_BRACKETED_PASTE.start_with?(buffer) do if START_BRACKETED_PASTE == buffer @@in_bracketed_paste_mode = true - return inner_getc + return inner_getc(count) elsif END_BRACKETED_PASTE == buffer @@in_bracketed_paste_mode = false ungetc(-1) - return inner_getc + return inner_getc(count) end - begin - succ_c = nil - Timeout.timeout(Reline.core.config.keyseq_timeout * 100) { - succ_c = inner_getc - } - rescue Timeout::Error - break - else + succ_c = inner_getc(Reline.core.config.keyseq_timeout) + + if succ_c buffer << succ_c + else + break end end buffer.bytes.reverse_each do |ch| ungetc ch end - inner_getc + inner_getc(count) end - def self.getc + def self.getc(count) if Reline.core.config.enable_bracketed_paste - getc_with_bracketed_paste + getc_with_bracketed_paste(count) else - inner_getc + inner_getc(count) end end diff --git a/lib/reline/general_io.rb b/lib/reline/general_io.rb index 9929846568..86468530c0 100644 --- a/lib/reline/general_io.rb +++ b/lib/reline/general_io.rb @@ -1,4 +1,3 @@ -require 'timeout' require 'io/wait' class Reline::GeneralIO @@ -35,7 +34,7 @@ def self.with_raw_input yield end - def self.getc + def self.getc(_count) unless @@buf.empty? return @@buf.shift end diff --git a/lib/reline/windows.rb b/lib/reline/windows.rb index 7ea2a00f63..1056e5d813 100644 --- a/lib/reline/windows.rb +++ b/lib/reline/windows.rb @@ -295,7 +295,7 @@ def self.with_raw_input yield end - def self.getc + def self.getc(_) check_input_event @@output_buf.shift end diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index c72e47fd38..8ac0c0c096 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -3,7 +3,7 @@ begin require 'yamatanooroti' - class Reline::TestRendering < Yamatanooroti::TestCase + class Reline::RenderingTest < Yamatanooroti::TestCase def setup @pwd = Dir.pwd suffix = '%010d' % Random.rand(0..65535)