[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:
tomoya ishida 2024-04-04 00:50:03 +09:00 коммит произвёл Hiroshi SHIBATA
Родитель 80e31663f3
Коммит 8088c88d01
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: F9CF13417264FAC2
6 изменённых файлов: 75 добавлений и 61 удалений

Просмотреть файл

@ -254,32 +254,35 @@ module Reline
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
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
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)
end
whole_buffer = line_editor.whole_buffer.dup
whole_buffer.taint if RUBY_VERSION < '2.7'
if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
Reline::HISTORY << whole_buffer
end
whole_buffer = line_editor.whole_buffer.dup
whole_buffer.taint if RUBY_VERSION < '2.7'
if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
Reline::HISTORY << whole_buffer
end
if line_editor.eof?
line_editor.reset_line
# Return nil if the input is aborted by C-d.
nil
else
whole_buffer
end
if line_editor.eof?
line_editor.reset_line
# Return nil if the input is aborted by C-d.
nil
else
whole_buffer
end
end
def readline(prompt = '', add_hist = false)
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.taint if RUBY_VERSION < '2.7'

Просмотреть файл

@ -151,7 +151,11 @@ class Reline::ANSI
end
def self.with_raw_input
@@input.raw { yield }
if @@input.tty?
@@input.raw(intr: true) { yield }
else
yield
end
end
@@buf = []
@ -159,11 +163,13 @@ class Reline::ANSI
unless @@buf.empty?
return @@buf.shift
end
until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
timeout_second -= 0.1
until @@input.wait_readable(0.01)
timeout_second -= 0.01
return nil if timeout_second <= 0
Reline.core.line_editor.resize
Reline.core.line_editor.handle_signal
end
c = @@input.getbyte
(c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
rescue Errno::EIO
# Maybe the I/O has been closed.

Просмотреть файл

@ -46,6 +46,7 @@ class Reline::GeneralIO
end
c = nil
loop do
Reline.core.line_editor.handle_signal
result = @@input.wait_readable(0.1)
next if result.nil?
c = @@input.read(1)

Просмотреть файл

@ -138,9 +138,6 @@ class Reline::LineEditor
@screen_size = Reline::IOGate.get_screen_size
reset_variables(prompt, encoding: encoding)
@rendered_screen.base_y = Reline::IOGate.cursor_pos.y
Reline::IOGate.set_winch_handler do
@resized = true
end
if ENV.key?('RELINE_ALT_SCROLLBAR')
@full_block = '::'
@upper_half_block = "''"
@ -164,7 +161,12 @@ class Reline::LineEditor
end
end
def resize
def handle_signal
handle_interrupted
handle_resized
end
private def handle_resized
return unless @resized
@screen_size = Reline::IOGate.get_screen_size
@ -177,25 +179,35 @@ class Reline::LineEditor
render_differential
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
@old_trap = Signal.trap('INT') {
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
}
Reline::IOGate.set_winch_handler do
@resized = true
end
@old_trap = Signal.trap('INT') do
@interrupted = true
end
end
def finalize
@ -212,7 +224,6 @@ class Reline::LineEditor
@encoding = encoding
@is_multiline = false
@finished = false
@cleared = false
@history_pointer = nil
@kill_ring ||= Reline::KillRing.new
@vi_clipboard = ''
@ -234,6 +245,7 @@ class Reline::LineEditor
@in_pasting = false
@auto_indent_proc = nil
@dialogs = []
@interrupted = false
@resized = false
@cache = {}
@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
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
handle_cleared
render_differential unless @in_pasting
end
@ -2074,7 +2074,11 @@ class Reline::LineEditor
alias_method :yank_pop, :em_yank_pop
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
alias_method :clear_screen, :ed_clear_screen

Просмотреть файл

@ -259,7 +259,7 @@ class Reline::Windows
def self.check_input_event
num_of_events = 0.chr * 8
while @@output_buf.empty?
Reline.core.line_editor.resize
Reline.core.line_editor.handle_signal
if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec
# prevent for background consolemode change
@@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)

Просмотреть файл

@ -255,18 +255,18 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
end
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)
assert(@line_editor.instance_variable_get(:@cleared))
assert_empty(@line_editor.instance_variable_get(:@rendered_screen).lines)
end
def test_ed_clear_screen_with_inputed
input_keys('abc')
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')
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')
end