diff --git a/lib/reline.rb b/lib/reline.rb index 0a2dba4f0d..52609e6aaf 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 / 1000) + + 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 / 1000) + + 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..c2e5075ea8 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,13 @@ def self.with_raw_input end @@buf = [] - def self.inner_getc + def self.inner_getc(timeout_second) unless @@buf.empty? return @@buf.shift end until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte } + timeout_second -= 0.1 + return nil if timeout_second <= 0 Reline.core.line_editor.resize end (c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c @@ -172,40 +173,38 @@ 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(timeout_second) buffer = String.new(encoding: Encoding::ASCII_8BIT) - buffer << inner_getc + buffer << inner_getc(timeout_second) 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(timeout_second) elsif END_BRACKETED_PASTE == buffer @@in_bracketed_paste_mode = false ungetc(-1) - return inner_getc + return inner_getc(timeout_second) 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(timeout_second) end - def self.getc + # if the usage expects to wait indefinitely, use Float::INFINITY for timeout_second + def self.getc(timeout_second) if Reline.core.config.enable_bracketed_paste - getc_with_bracketed_paste + getc_with_bracketed_paste(timeout_second) else - inner_getc + inner_getc(timeout_second) end end diff --git a/lib/reline/general_io.rb b/lib/reline/general_io.rb index 9929846568..dd2e87eaf0 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(_timeout_second) unless @@buf.empty? return @@buf.shift end diff --git a/lib/reline/windows.rb b/lib/reline/windows.rb index 7ea2a00f63..6f635f630f 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(_timeout_second) 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)