зеркало из https://github.com/github/ruby.git
[ruby/reline] Implement the redo command
(https://github.com/ruby/reline/pull/707) * Implement the redo command * Commented out a test that does not pass * Changed key assignment for redo from "\C-[" to "\C-g" * Changed redo key assignment from `\C-g` to `\M-\C-_` * Revert the first implemantation * Implemented redo by sharing `@past_lines` between undo and redo * Fixed the index of past_lines that is updated when the cursor is moved * Fixed deletion of the redo history in regular input * Renamed variables: past_lines -> input_lines * Rename @position to @input_lines_position * Deleted unused variables: `@old_byte_pointer` and `@old_line_index` https://github.com/ruby/reline/commit/0b2d9fab5f
This commit is contained in:
Родитель
bc47ca5546
Коммит
7c6e4bc7ca
|
@ -319,7 +319,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
|
|||
# 158 M-^^
|
||||
:ed_unassigned,
|
||||
# 159 M-^_
|
||||
:ed_unassigned,
|
||||
:redo,
|
||||
# 160 M-SPACE
|
||||
:em_set_mark,
|
||||
# 161 M-!
|
||||
|
|
|
@ -250,7 +250,8 @@ class Reline::LineEditor
|
|||
@resized = false
|
||||
@cache = {}
|
||||
@rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0)
|
||||
@past_lines = []
|
||||
@input_lines = [[[""], 0, 0]]
|
||||
@input_lines_position = 0
|
||||
@undoing = false
|
||||
reset_line
|
||||
end
|
||||
|
@ -1137,7 +1138,7 @@ class Reline::LineEditor
|
|||
@completion_journey_state = nil
|
||||
end
|
||||
|
||||
push_past_lines unless @undoing
|
||||
push_input_lines unless @undoing
|
||||
@undoing = false
|
||||
|
||||
if @in_pasting
|
||||
|
@ -1156,21 +1157,24 @@ class Reline::LineEditor
|
|||
|
||||
def save_old_buffer
|
||||
@old_buffer_of_lines = @buffer_of_lines.dup
|
||||
@old_byte_pointer = @byte_pointer.dup
|
||||
@old_line_index = @line_index.dup
|
||||
end
|
||||
|
||||
def push_past_lines
|
||||
if @old_buffer_of_lines != @buffer_of_lines
|
||||
@past_lines.push([@old_buffer_of_lines, @old_byte_pointer, @old_line_index])
|
||||
def push_input_lines
|
||||
if @old_buffer_of_lines == @buffer_of_lines
|
||||
@input_lines[@input_lines_position] = [@buffer_of_lines.dup, @byte_pointer, @line_index]
|
||||
else
|
||||
@input_lines = @input_lines[0..@input_lines_position]
|
||||
@input_lines_position += 1
|
||||
@input_lines.push([@buffer_of_lines.dup, @byte_pointer, @line_index])
|
||||
end
|
||||
trim_past_lines
|
||||
trim_input_lines
|
||||
end
|
||||
|
||||
MAX_PAST_LINES = 100
|
||||
def trim_past_lines
|
||||
if @past_lines.size > MAX_PAST_LINES
|
||||
@past_lines.shift
|
||||
MAX_INPUT_LINES = 100
|
||||
def trim_input_lines
|
||||
if @input_lines.size > MAX_INPUT_LINES
|
||||
@input_lines.shift
|
||||
@input_lines_position -= 1
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1352,7 +1356,7 @@ class Reline::LineEditor
|
|||
@buffer_of_lines[@line_index, 1] = lines
|
||||
@line_index += lines.size - 1
|
||||
@byte_pointer = @buffer_of_lines[@line_index].bytesize - post.bytesize
|
||||
push_past_lines
|
||||
push_input_lines
|
||||
end
|
||||
|
||||
def insert_text(text)
|
||||
|
@ -2529,13 +2533,22 @@ class Reline::LineEditor
|
|||
end
|
||||
|
||||
private def undo(_key)
|
||||
return if @past_lines.empty?
|
||||
|
||||
@undoing = true
|
||||
|
||||
target_lines, target_cursor_x, target_cursor_y = @past_lines.last
|
||||
set_current_lines(target_lines, target_cursor_x, target_cursor_y)
|
||||
return if @input_lines_position <= 0
|
||||
|
||||
@past_lines.pop
|
||||
@input_lines_position -= 1
|
||||
target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
|
||||
set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
|
||||
end
|
||||
|
||||
private def redo(_key)
|
||||
@undoing = true
|
||||
|
||||
return if @input_lines_position >= @input_lines.size - 1
|
||||
|
||||
@input_lines_position += 1
|
||||
target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
|
||||
set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1498,11 +1498,115 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
|
|||
end
|
||||
|
||||
def test_undo_with_many_times
|
||||
str = "a" + "b" * 100
|
||||
str = "a" + "b" * 99
|
||||
input_keys(str, false)
|
||||
100.times { input_keys("\C-_", false) }
|
||||
assert_line_around_cursor('a', '')
|
||||
input_keys("\C-_", false)
|
||||
assert_line_around_cursor('a', '')
|
||||
end
|
||||
|
||||
def test_redo
|
||||
input_keys("aあb", false)
|
||||
assert_line_around_cursor('aあb', '')
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_line_around_cursor('aあb', '')
|
||||
input_keys("\C-_", false)
|
||||
assert_line_around_cursor('aあ', '')
|
||||
input_keys("\C-_", false)
|
||||
assert_line_around_cursor('a', '')
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_line_around_cursor('aあ', '')
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_line_around_cursor('aあb', '')
|
||||
input_keys("\C-_", false)
|
||||
assert_line_around_cursor('aあ', '')
|
||||
input_keys("c", false)
|
||||
assert_line_around_cursor('aあc', '')
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_line_around_cursor('aあc', '')
|
||||
end
|
||||
|
||||
def test_redo_with_cursor_position
|
||||
input_keys("abc\C-b\C-h", false)
|
||||
assert_line_around_cursor('a', 'c')
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_line_around_cursor('a', 'c')
|
||||
input_keys("\C-_", false)
|
||||
assert_line_around_cursor('ab', 'c')
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_line_around_cursor('a', 'c')
|
||||
end
|
||||
|
||||
def test_redo_with_multiline
|
||||
@line_editor.multiline_on
|
||||
@line_editor.confirm_multiline_termination_proc = proc {}
|
||||
input_keys("1\n2\n3", false)
|
||||
assert_whole_lines(["1", "2", "3"])
|
||||
assert_line_index(2)
|
||||
assert_line_around_cursor('3', '')
|
||||
|
||||
input_keys("\C-_", false)
|
||||
assert_whole_lines(["1", "2", ""])
|
||||
assert_line_index(2)
|
||||
assert_line_around_cursor('', '')
|
||||
|
||||
input_keys("\C-_", false)
|
||||
assert_whole_lines(["1", "2"])
|
||||
assert_line_index(1)
|
||||
assert_line_around_cursor('2', '')
|
||||
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_whole_lines(["1", "2", ""])
|
||||
assert_line_index(2)
|
||||
assert_line_around_cursor('', '')
|
||||
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_whole_lines(["1", "2", "3"])
|
||||
assert_line_index(2)
|
||||
assert_line_around_cursor('3', '')
|
||||
|
||||
input_keys("\C-p\C-h\C-h", false)
|
||||
assert_whole_lines(["1", "3"])
|
||||
assert_line_index(0)
|
||||
assert_line_around_cursor('1', '')
|
||||
|
||||
input_keys("\C-n", false)
|
||||
assert_whole_lines(["1", "3"])
|
||||
assert_line_index(1)
|
||||
assert_line_around_cursor('3', '')
|
||||
|
||||
input_keys("\C-_", false)
|
||||
assert_whole_lines(["1", "", "3"])
|
||||
assert_line_index(1)
|
||||
assert_line_around_cursor('', '')
|
||||
|
||||
input_keys("\C-_", false)
|
||||
assert_whole_lines(["1", "2", "3"])
|
||||
assert_line_index(1)
|
||||
assert_line_around_cursor('2', '')
|
||||
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_whole_lines(["1", "", "3"])
|
||||
assert_line_index(1)
|
||||
assert_line_around_cursor('', '')
|
||||
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_whole_lines(["1", "3"])
|
||||
assert_line_index(1)
|
||||
assert_line_around_cursor('3', '')
|
||||
end
|
||||
|
||||
def test_redo_with_many_times
|
||||
str = "a" + "b" * 98 + "c"
|
||||
input_keys(str, false)
|
||||
100.times { input_keys("\C-_", false) }
|
||||
assert_line_around_cursor('a', '')
|
||||
input_keys("\C-_", false)
|
||||
assert_line_around_cursor('a', '')
|
||||
100.times { input_keys("\M-\C-_", false) }
|
||||
assert_line_around_cursor(str, '')
|
||||
input_keys("\M-\C-_", false)
|
||||
assert_line_around_cursor(str, '')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -569,6 +569,22 @@ begin
|
|||
EOC
|
||||
end
|
||||
|
||||
def test_bracketed_paste_with_redo
|
||||
omit if Reline.core.io_gate.win?
|
||||
start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
|
||||
write("abc")
|
||||
write("\e[200~def hoge\r\t3\rend\e[201~")
|
||||
write("\C-_")
|
||||
write("\M-\C-_")
|
||||
close
|
||||
assert_screen(<<~EOC)
|
||||
Multiline REPL.
|
||||
prompt> abcdef hoge
|
||||
prompt> 3
|
||||
prompt> end
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_backspace_until_returns_to_initial
|
||||
start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
|
||||
write("ABC")
|
||||
|
|
Загрузка…
Ссылка в новой задаче