[ruby/reline] Handle INT signal correctly, remove handle_cleared
because clear(C-l) is not a signal (https://github.com/ruby/reline/pull/646) https://github.com/ruby/reline/commit/3debb0ae2f
This commit is contained in:
parent
80e31663f3
commit
8088c88d01
@ -254,32 +254,35 @@ module Reline
|
|||||||
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
||||||
|
|
||||||
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
|
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
|
||||||
|
unless confirm_multiline_termination
|
||||||
|
raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
|
||||||
|
end
|
||||||
|
|
||||||
Reline.update_iogate
|
Reline.update_iogate
|
||||||
io_gate.with_raw_input do
|
io_gate.with_raw_input do
|
||||||
unless confirm_multiline_termination
|
|
||||||
raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
|
|
||||||
end
|
|
||||||
inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
|
inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
|
||||||
|
end
|
||||||
|
|
||||||
whole_buffer = line_editor.whole_buffer.dup
|
whole_buffer = line_editor.whole_buffer.dup
|
||||||
whole_buffer.taint if RUBY_VERSION < '2.7'
|
whole_buffer.taint if RUBY_VERSION < '2.7'
|
||||||
if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
|
if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
|
||||||
Reline::HISTORY << whole_buffer
|
Reline::HISTORY << whole_buffer
|
||||||
end
|
end
|
||||||
|
|
||||||
if line_editor.eof?
|
if line_editor.eof?
|
||||||
line_editor.reset_line
|
line_editor.reset_line
|
||||||
# Return nil if the input is aborted by C-d.
|
# Return nil if the input is aborted by C-d.
|
||||||
nil
|
nil
|
||||||
else
|
else
|
||||||
whole_buffer
|
whole_buffer
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def readline(prompt = '', add_hist = false)
|
def readline(prompt = '', add_hist = false)
|
||||||
Reline.update_iogate
|
Reline.update_iogate
|
||||||
inner_readline(prompt, add_hist, false)
|
io_gate.with_raw_input do
|
||||||
|
inner_readline(prompt, add_hist, false)
|
||||||
|
end
|
||||||
|
|
||||||
line = line_editor.line.dup
|
line = line_editor.line.dup
|
||||||
line.taint if RUBY_VERSION < '2.7'
|
line.taint if RUBY_VERSION < '2.7'
|
||||||
|
@ -151,7 +151,11 @@ class Reline::ANSI
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.with_raw_input
|
def self.with_raw_input
|
||||||
@@input.raw { yield }
|
if @@input.tty?
|
||||||
|
@@input.raw(intr: true) { yield }
|
||||||
|
else
|
||||||
|
yield
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@buf = []
|
@@buf = []
|
||||||
@ -159,11 +163,13 @@ class Reline::ANSI
|
|||||||
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 @@input.wait_readable(0.01)
|
||||||
timeout_second -= 0.1
|
timeout_second -= 0.01
|
||||||
return nil if timeout_second <= 0
|
return nil if timeout_second <= 0
|
||||||
Reline.core.line_editor.resize
|
|
||||||
|
Reline.core.line_editor.handle_signal
|
||||||
end
|
end
|
||||||
|
c = @@input.getbyte
|
||||||
(c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
|
(c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
|
||||||
rescue Errno::EIO
|
rescue Errno::EIO
|
||||||
# Maybe the I/O has been closed.
|
# Maybe the I/O has been closed.
|
||||||
|
@ -46,6 +46,7 @@ class Reline::GeneralIO
|
|||||||
end
|
end
|
||||||
c = nil
|
c = nil
|
||||||
loop do
|
loop do
|
||||||
|
Reline.core.line_editor.handle_signal
|
||||||
result = @@input.wait_readable(0.1)
|
result = @@input.wait_readable(0.1)
|
||||||
next if result.nil?
|
next if result.nil?
|
||||||
c = @@input.read(1)
|
c = @@input.read(1)
|
||||||
|
@ -138,9 +138,6 @@ class Reline::LineEditor
|
|||||||
@screen_size = Reline::IOGate.get_screen_size
|
@screen_size = Reline::IOGate.get_screen_size
|
||||||
reset_variables(prompt, encoding: encoding)
|
reset_variables(prompt, encoding: encoding)
|
||||||
@rendered_screen.base_y = Reline::IOGate.cursor_pos.y
|
@rendered_screen.base_y = Reline::IOGate.cursor_pos.y
|
||||||
Reline::IOGate.set_winch_handler do
|
|
||||||
@resized = true
|
|
||||||
end
|
|
||||||
if ENV.key?('RELINE_ALT_SCROLLBAR')
|
if ENV.key?('RELINE_ALT_SCROLLBAR')
|
||||||
@full_block = '::'
|
@full_block = '::'
|
||||||
@upper_half_block = "''"
|
@upper_half_block = "''"
|
||||||
@ -164,7 +161,12 @@ class Reline::LineEditor
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def resize
|
def handle_signal
|
||||||
|
handle_interrupted
|
||||||
|
handle_resized
|
||||||
|
end
|
||||||
|
|
||||||
|
private def handle_resized
|
||||||
return unless @resized
|
return unless @resized
|
||||||
|
|
||||||
@screen_size = Reline::IOGate.get_screen_size
|
@screen_size = Reline::IOGate.get_screen_size
|
||||||
@ -177,25 +179,35 @@ class Reline::LineEditor
|
|||||||
render_differential
|
render_differential
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private def handle_interrupted
|
||||||
|
return unless @interrupted
|
||||||
|
|
||||||
|
@interrupted = false
|
||||||
|
clear_dialogs
|
||||||
|
scrolldown = render_differential
|
||||||
|
Reline::IOGate.scroll_down scrolldown
|
||||||
|
Reline::IOGate.move_cursor_column 0
|
||||||
|
@rendered_screen.lines = []
|
||||||
|
@rendered_screen.cursor_y = 0
|
||||||
|
case @old_trap
|
||||||
|
when 'DEFAULT', 'SYSTEM_DEFAULT'
|
||||||
|
raise Interrupt
|
||||||
|
when 'IGNORE'
|
||||||
|
# Do nothing
|
||||||
|
when 'EXIT'
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
@old_trap.call if @old_trap.respond_to?(:call)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def set_signal_handlers
|
def set_signal_handlers
|
||||||
@old_trap = Signal.trap('INT') {
|
Reline::IOGate.set_winch_handler do
|
||||||
clear_dialogs
|
@resized = true
|
||||||
scrolldown = render_differential
|
end
|
||||||
Reline::IOGate.scroll_down scrolldown
|
@old_trap = Signal.trap('INT') do
|
||||||
Reline::IOGate.move_cursor_column 0
|
@interrupted = true
|
||||||
@rendered_screen.lines = []
|
end
|
||||||
@rendered_screen.cursor_y = 0
|
|
||||||
case @old_trap
|
|
||||||
when 'DEFAULT', 'SYSTEM_DEFAULT'
|
|
||||||
raise Interrupt
|
|
||||||
when 'IGNORE'
|
|
||||||
# Do nothing
|
|
||||||
when 'EXIT'
|
|
||||||
exit
|
|
||||||
else
|
|
||||||
@old_trap.call if @old_trap.respond_to?(:call)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def finalize
|
def finalize
|
||||||
@ -212,7 +224,6 @@ class Reline::LineEditor
|
|||||||
@encoding = encoding
|
@encoding = encoding
|
||||||
@is_multiline = false
|
@is_multiline = false
|
||||||
@finished = false
|
@finished = false
|
||||||
@cleared = false
|
|
||||||
@history_pointer = nil
|
@history_pointer = nil
|
||||||
@kill_ring ||= Reline::KillRing.new
|
@kill_ring ||= Reline::KillRing.new
|
||||||
@vi_clipboard = ''
|
@vi_clipboard = ''
|
||||||
@ -234,6 +245,7 @@ class Reline::LineEditor
|
|||||||
@in_pasting = false
|
@in_pasting = false
|
||||||
@auto_indent_proc = nil
|
@auto_indent_proc = nil
|
||||||
@dialogs = []
|
@dialogs = []
|
||||||
|
@interrupted = false
|
||||||
@resized = false
|
@resized = false
|
||||||
@cache = {}
|
@cache = {}
|
||||||
@rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0)
|
@rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0)
|
||||||
@ -541,19 +553,7 @@ class Reline::LineEditor
|
|||||||
screen_height - wrapped_cursor_y + screen_scroll_top - @rendered_screen.base_y - 1
|
screen_height - wrapped_cursor_y + screen_scroll_top - @rendered_screen.base_y - 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_cleared
|
|
||||||
return unless @cleared
|
|
||||||
|
|
||||||
@cleared = false
|
|
||||||
Reline::IOGate.clear_screen
|
|
||||||
@screen_size = Reline::IOGate.get_screen_size
|
|
||||||
@rendered_screen.lines = []
|
|
||||||
@rendered_screen.base_y = 0
|
|
||||||
@rendered_screen.cursor_y = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
def rerender
|
def rerender
|
||||||
handle_cleared
|
|
||||||
render_differential unless @in_pasting
|
render_differential unless @in_pasting
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2074,7 +2074,11 @@ class Reline::LineEditor
|
|||||||
alias_method :yank_pop, :em_yank_pop
|
alias_method :yank_pop, :em_yank_pop
|
||||||
|
|
||||||
private def ed_clear_screen(key)
|
private def ed_clear_screen(key)
|
||||||
@cleared = true
|
Reline::IOGate.clear_screen
|
||||||
|
@screen_size = Reline::IOGate.get_screen_size
|
||||||
|
@rendered_screen.lines = []
|
||||||
|
@rendered_screen.base_y = 0
|
||||||
|
@rendered_screen.cursor_y = 0
|
||||||
end
|
end
|
||||||
alias_method :clear_screen, :ed_clear_screen
|
alias_method :clear_screen, :ed_clear_screen
|
||||||
|
|
||||||
|
@ -259,7 +259,7 @@ class Reline::Windows
|
|||||||
def self.check_input_event
|
def self.check_input_event
|
||||||
num_of_events = 0.chr * 8
|
num_of_events = 0.chr * 8
|
||||||
while @@output_buf.empty?
|
while @@output_buf.empty?
|
||||||
Reline.core.line_editor.resize
|
Reline.core.line_editor.handle_signal
|
||||||
if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec
|
if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec
|
||||||
# prevent for background consolemode change
|
# prevent for background consolemode change
|
||||||
@@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
|
@@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
|
||||||
|
@ -255,18 +255,18 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_ed_clear_screen
|
def test_ed_clear_screen
|
||||||
refute(@line_editor.instance_variable_get(:@cleared))
|
@line_editor.instance_variable_get(:@rendered_screen).lines = [[]]
|
||||||
input_keys("\C-l", false)
|
input_keys("\C-l", false)
|
||||||
assert(@line_editor.instance_variable_get(:@cleared))
|
assert_empty(@line_editor.instance_variable_get(:@rendered_screen).lines)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_ed_clear_screen_with_inputed
|
def test_ed_clear_screen_with_inputed
|
||||||
input_keys('abc')
|
input_keys('abc')
|
||||||
input_keys("\C-b", false)
|
input_keys("\C-b", false)
|
||||||
refute(@line_editor.instance_variable_get(:@cleared))
|
@line_editor.instance_variable_get(:@rendered_screen).lines = [[]]
|
||||||
assert_line_around_cursor('ab', 'c')
|
assert_line_around_cursor('ab', 'c')
|
||||||
input_keys("\C-l", false)
|
input_keys("\C-l", false)
|
||||||
assert(@line_editor.instance_variable_get(:@cleared))
|
assert_empty(@line_editor.instance_variable_get(:@rendered_screen).lines)
|
||||||
assert_line_around_cursor('ab', 'c')
|
assert_line_around_cursor('ab', 'c')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user