[ruby/reline] Remove Timeout usage
(https://github.com/ruby/reline/pull/580) Timeout's implementation relies on Thread, which would conflict with `ruby/debug`'s thread-freezing implementation and has casued issues like - ruby/debug#877 - ruby/debug#934 - ruby/debug#1000 This commit avoids the issue by completely removing the use of Timeout. https://github.com/ruby/reline/commit/d4f0cd3fe1
This commit is contained in:
parent
3544200513
commit
7c226291d3
@ -1,5 +1,4 @@
|
|||||||
require 'io/console'
|
require 'io/console'
|
||||||
require 'timeout'
|
|
||||||
require 'forwardable'
|
require 'forwardable'
|
||||||
require 'reline/version'
|
require 'reline/version'
|
||||||
require 'reline/config'
|
require 'reline/config'
|
||||||
@ -397,7 +396,7 @@ module Reline
|
|||||||
private def read_io(keyseq_timeout, &block)
|
private def read_io(keyseq_timeout, &block)
|
||||||
buffer = []
|
buffer = []
|
||||||
loop do
|
loop do
|
||||||
c = io_gate.getc
|
c = io_gate.getc(Float::INFINITY)
|
||||||
if c == -1
|
if c == -1
|
||||||
result = :unmatched
|
result = :unmatched
|
||||||
@bracketed_paste_finished = true
|
@bracketed_paste_finished = true
|
||||||
@ -434,15 +433,9 @@ module Reline
|
|||||||
end
|
end
|
||||||
|
|
||||||
private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
|
private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
|
||||||
begin
|
succ_c = io_gate.getc(keyseq_timeout / 1000)
|
||||||
succ_c = nil
|
|
||||||
Timeout.timeout(keyseq_timeout / 1000.0) {
|
if succ_c
|
||||||
succ_c = io_gate.getc
|
|
||||||
}
|
|
||||||
rescue Timeout::Error # cancel matching only when first byte
|
|
||||||
block.([Reline::Key.new(c, c, false)])
|
|
||||||
return :break
|
|
||||||
else
|
|
||||||
case key_stroke.match_status(buffer.dup.push(succ_c))
|
case key_stroke.match_status(buffer.dup.push(succ_c))
|
||||||
when :unmatched
|
when :unmatched
|
||||||
if c == "\e".ord
|
if c == "\e".ord
|
||||||
@ -462,18 +455,15 @@ module Reline
|
|||||||
block.(expanded)
|
block.(expanded)
|
||||||
return :break
|
return :break
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
block.([Reline::Key.new(c, c, false)])
|
||||||
|
return :break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private def read_escaped_key(keyseq_timeout, c, block)
|
private def read_escaped_key(keyseq_timeout, c, block)
|
||||||
begin
|
escaped_c = io_gate.getc(keyseq_timeout / 1000)
|
||||||
escaped_c = nil
|
|
||||||
Timeout.timeout(keyseq_timeout / 1000.0) {
|
|
||||||
escaped_c = io_gate.getc
|
|
||||||
}
|
|
||||||
rescue Timeout::Error # independent ESC
|
|
||||||
block.([Reline::Key.new(c, c, false)])
|
|
||||||
else
|
|
||||||
if escaped_c.nil?
|
if escaped_c.nil?
|
||||||
block.([Reline::Key.new(c, c, false)])
|
block.([Reline::Key.new(c, c, false)])
|
||||||
elsif escaped_c >= 128 # maybe, first byte of multi byte
|
elsif escaped_c >= 128 # maybe, first byte of multi byte
|
||||||
@ -484,7 +474,6 @@ module Reline
|
|||||||
block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
|
block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def ambiguous_width
|
def ambiguous_width
|
||||||
may_req_ambiguous_char_width unless defined? @ambiguous_width
|
may_req_ambiguous_char_width unless defined? @ambiguous_width
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
require 'io/console'
|
require 'io/console'
|
||||||
require 'io/wait'
|
require 'io/wait'
|
||||||
require 'timeout'
|
|
||||||
require_relative 'terminfo'
|
require_relative 'terminfo'
|
||||||
|
|
||||||
class Reline::ANSI
|
class Reline::ANSI
|
||||||
@ -154,11 +153,13 @@ class Reline::ANSI
|
|||||||
end
|
end
|
||||||
|
|
||||||
@@buf = []
|
@@buf = []
|
||||||
def self.inner_getc
|
def self.inner_getc(timeout_second)
|
||||||
unless @@buf.empty?
|
unless @@buf.empty?
|
||||||
return @@buf.shift
|
return @@buf.shift
|
||||||
end
|
end
|
||||||
until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
|
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
|
Reline.core.line_editor.resize
|
||||||
end
|
end
|
||||||
(c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
|
(c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
|
||||||
@ -172,40 +173,38 @@ class Reline::ANSI
|
|||||||
@@in_bracketed_paste_mode = false
|
@@in_bracketed_paste_mode = false
|
||||||
START_BRACKETED_PASTE = String.new("\e[200~,", encoding: Encoding::ASCII_8BIT)
|
START_BRACKETED_PASTE = String.new("\e[200~,", encoding: Encoding::ASCII_8BIT)
|
||||||
END_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 = 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
|
while START_BRACKETED_PASTE.start_with?(buffer) or END_BRACKETED_PASTE.start_with?(buffer) do
|
||||||
if START_BRACKETED_PASTE == buffer
|
if START_BRACKETED_PASTE == buffer
|
||||||
@@in_bracketed_paste_mode = true
|
@@in_bracketed_paste_mode = true
|
||||||
return inner_getc
|
return inner_getc(timeout_second)
|
||||||
elsif END_BRACKETED_PASTE == buffer
|
elsif END_BRACKETED_PASTE == buffer
|
||||||
@@in_bracketed_paste_mode = false
|
@@in_bracketed_paste_mode = false
|
||||||
ungetc(-1)
|
ungetc(-1)
|
||||||
return inner_getc
|
return inner_getc(timeout_second)
|
||||||
end
|
end
|
||||||
begin
|
succ_c = inner_getc(Reline.core.config.keyseq_timeout)
|
||||||
succ_c = nil
|
|
||||||
Timeout.timeout(Reline.core.config.keyseq_timeout * 100) {
|
if succ_c
|
||||||
succ_c = inner_getc
|
|
||||||
}
|
|
||||||
rescue Timeout::Error
|
|
||||||
break
|
|
||||||
else
|
|
||||||
buffer << succ_c
|
buffer << succ_c
|
||||||
|
else
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
buffer.bytes.reverse_each do |ch|
|
buffer.bytes.reverse_each do |ch|
|
||||||
ungetc ch
|
ungetc ch
|
||||||
end
|
end
|
||||||
inner_getc
|
inner_getc(timeout_second)
|
||||||
end
|
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
|
if Reline.core.config.enable_bracketed_paste
|
||||||
getc_with_bracketed_paste
|
getc_with_bracketed_paste(timeout_second)
|
||||||
else
|
else
|
||||||
inner_getc
|
inner_getc(timeout_second)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
require 'timeout'
|
|
||||||
require 'io/wait'
|
require 'io/wait'
|
||||||
|
|
||||||
class Reline::GeneralIO
|
class Reline::GeneralIO
|
||||||
@ -35,7 +34,7 @@ class Reline::GeneralIO
|
|||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.getc
|
def self.getc(_timeout_second)
|
||||||
unless @@buf.empty?
|
unless @@buf.empty?
|
||||||
return @@buf.shift
|
return @@buf.shift
|
||||||
end
|
end
|
||||||
|
@ -295,7 +295,7 @@ class Reline::Windows
|
|||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.getc
|
def self.getc(_timeout_second)
|
||||||
check_input_event
|
check_input_event
|
||||||
@@output_buf.shift
|
@@output_buf.shift
|
||||||
end
|
end
|
||||||
|
@ -3,7 +3,7 @@ require 'reline'
|
|||||||
begin
|
begin
|
||||||
require 'yamatanooroti'
|
require 'yamatanooroti'
|
||||||
|
|
||||||
class Reline::TestRendering < Yamatanooroti::TestCase
|
class Reline::RenderingTest < Yamatanooroti::TestCase
|
||||||
def setup
|
def setup
|
||||||
@pwd = Dir.pwd
|
@pwd = Dir.pwd
|
||||||
suffix = '%010d' % Random.rand(0..65535)
|
suffix = '%010d' % Random.rand(0..65535)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user