From 85302944cb902daa54e322eaabc3ffd968dec8c0 Mon Sep 17 00:00:00 2001 From: verdy89 Date: Sat, 18 May 2024 19:38:02 +0900 Subject: [PATCH 01/11] Implement the redo command --- lib/reline/key_actor/emacs.rb | 2 +- lib/reline/line_editor.rb | 34 ++++++- test/reline/test_key_actor_emacs.rb | 104 ++++++++++++++++++++ test/reline/yamatanooroti/test_rendering.rb | 16 +++ 4 files changed, 153 insertions(+), 3 deletions(-) diff --git a/lib/reline/key_actor/emacs.rb b/lib/reline/key_actor/emacs.rb index edd88289a3..34151f817d 100644 --- a/lib/reline/key_actor/emacs.rb +++ b/lib/reline/key_actor/emacs.rb @@ -55,7 +55,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base # 26 ^Z :ed_ignore, # 27 ^[ - :ed_unassigned, + :redo, # 28 ^\ :ed_ignore, # 29 ^] diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 23ece60220..f30ba12072 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -252,6 +252,7 @@ def reset_variables(prompt = '', encoding:) @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0) @past_lines = [] @undoing = false + @next_lines = [] reset_line end @@ -1137,7 +1138,10 @@ def input_key(key) @completion_journey_state = nil end - push_past_lines unless @undoing + unless @undoing + push_past_lines + @next_lines = [] + end @undoing = false if @in_pasting @@ -1174,6 +1178,18 @@ def trim_past_lines end end + def push_next_lines + @next_lines.push([@buffer_of_lines, @byte_pointer, @line_index]) + trim_next_lines + end + + MAX_NEXT_LINES = 100 + def trim_next_lines + if @next_lines.size > MAX_NEXT_LINES + @next_lines.shift + end + end + def scroll_into_view _wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position if wrapped_cursor_y < screen_scroll_top @@ -2529,13 +2545,27 @@ def finish end private def undo(_key) + @undoing = true + return if @past_lines.empty? - @undoing = true + push_next_lines target_lines, target_cursor_x, target_cursor_y = @past_lines.last set_current_lines(target_lines, target_cursor_x, target_cursor_y) @past_lines.pop end + + private def redo(_key) + @undoing = true + + return if @next_lines.empty? + + @past_lines.push([@buffer_of_lines, @byte_pointer, @line_index]) + target_lines, target_cursor_x, target_cursor_y = @next_lines.last + set_current_lines(target_lines, target_cursor_x, target_cursor_y) + + @next_lines.pop + end end diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb index 013ca2f7b3..730e2ab0cb 100644 --- a/test/reline/test_key_actor_emacs.rb +++ b/test/reline/test_key_actor_emacs.rb @@ -1505,4 +1505,108 @@ def test_undo_with_many_times 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("\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("\C-[", false) + assert_line_around_cursor('aあ', '') + input_keys("\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("\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("\C-[", false) + assert_line_around_cursor('a', 'c') + input_keys("\C-_", false) + assert_line_around_cursor('ab', 'c') + input_keys("\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("\C-[", false) + assert_whole_lines(["1", "2", ""]) + assert_line_index(2) + assert_line_around_cursor('', '') + + input_keys("\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("\C-[", false) + assert_whole_lines(["1", "", "3"]) + assert_line_index(1) + assert_line_around_cursor('', '') + + input_keys("\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" * 99 + "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("\C-[", false) } + assert_line_around_cursor(str, '') + input_keys("\C-[", false) + assert_line_around_cursor(str, '') + end end diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index 37a1c1a193..2d3811c4b5 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -569,6 +569,22 @@ def test_bracketed_paste_with_undo 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("\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") From ef3653bd359c0efee29fef79768bf59647eb9660 Mon Sep 17 00:00:00 2001 From: verdy89 Date: Sun, 19 May 2024 09:49:59 +0900 Subject: [PATCH 02/11] Commented out a test that does not pass --- test/reline/yamatanooroti/test_rendering.rb | 31 +++++++++++---------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index 2d3811c4b5..3c920ab698 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -569,21 +569,22 @@ def test_bracketed_paste_with_undo 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("\C-[") - close - assert_screen(<<~EOC) - Multiline REPL. - prompt> abcdef hoge - prompt> 3 - prompt> end - EOC - end + # TODO: It seems that this feature works correctly in development environment, but this test does not pass. + # 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("\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.') From 1ddc14b72a0d5c67718a111e74154dc4b7d06a9d Mon Sep 17 00:00:00 2001 From: verdy89 Date: Mon, 20 May 2024 13:14:26 +0900 Subject: [PATCH 03/11] Changed key assignment for redo from "\C-[" to "\C-g" --- lib/reline/key_actor/emacs.rb | 4 +-- test/reline/test_key_actor_emacs.rb | 24 ++++++++-------- test/reline/yamatanooroti/test_rendering.rb | 31 ++++++++++----------- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/lib/reline/key_actor/emacs.rb b/lib/reline/key_actor/emacs.rb index 34151f817d..254b250c28 100644 --- a/lib/reline/key_actor/emacs.rb +++ b/lib/reline/key_actor/emacs.rb @@ -15,7 +15,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base # 6 ^F :ed_next_char, # 7 ^G - :ed_unassigned, + :redo, # 8 ^H :em_delete_prev_char, # 9 ^I @@ -55,7 +55,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base # 26 ^Z :ed_ignore, # 27 ^[ - :redo, + :ed_unassigned, # 28 ^\ :ed_ignore, # 29 ^] diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb index 730e2ab0cb..395996da51 100644 --- a/test/reline/test_key_actor_emacs.rb +++ b/test/reline/test_key_actor_emacs.rb @@ -1509,32 +1509,32 @@ def test_undo_with_many_times def test_redo input_keys("aあb", false) assert_line_around_cursor('aあb', '') - input_keys("\C-[", false) + input_keys("\C-g", 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("\C-[", false) + input_keys("\C-g", false) assert_line_around_cursor('aあ', '') - input_keys("\C-[", false) + input_keys("\C-g", 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("\C-[", false) + input_keys("\C-g", 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("\C-[", false) + input_keys("\C-g", false) assert_line_around_cursor('a', 'c') input_keys("\C-_", false) assert_line_around_cursor('ab', 'c') - input_keys("\C-[", false) + input_keys("\C-g", false) assert_line_around_cursor('a', 'c') end @@ -1556,12 +1556,12 @@ def test_redo_with_multiline assert_line_index(1) assert_line_around_cursor('2', '') - input_keys("\C-[", false) + input_keys("\C-g", false) assert_whole_lines(["1", "2", ""]) assert_line_index(2) assert_line_around_cursor('', '') - input_keys("\C-[", false) + input_keys("\C-g", false) assert_whole_lines(["1", "2", "3"]) assert_line_index(2) assert_line_around_cursor('3', '') @@ -1586,12 +1586,12 @@ def test_redo_with_multiline assert_line_index(1) assert_line_around_cursor('2', '') - input_keys("\C-[", false) + input_keys("\C-g", false) assert_whole_lines(["1", "", "3"]) assert_line_index(1) assert_line_around_cursor('', '') - input_keys("\C-[", false) + input_keys("\C-g", false) assert_whole_lines(["1", "3"]) assert_line_index(1) assert_line_around_cursor('3', '') @@ -1604,9 +1604,9 @@ def test_redo_with_many_times assert_line_around_cursor('a', '') input_keys("\C-_", false) assert_line_around_cursor('a', '') - 100.times { input_keys("\C-[", false) } + 100.times { input_keys("\C-g", false) } assert_line_around_cursor(str, '') - input_keys("\C-[", false) + input_keys("\C-g", false) assert_line_around_cursor(str, '') end end diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index 3c920ab698..a960880597 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -569,22 +569,21 @@ def test_bracketed_paste_with_undo EOC end - # TODO: It seems that this feature works correctly in development environment, but this test does not pass. - # 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("\C-[") - # close - # assert_screen(<<~EOC) - # Multiline REPL. - # prompt> abcdef hoge - # prompt> 3 - # prompt> end - # 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("\C-g") + 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.') From 9e5e6233a23ad11ad4b4c02139042e0821b97a9c Mon Sep 17 00:00:00 2001 From: verdy89 Date: Thu, 23 May 2024 21:34:18 +0900 Subject: [PATCH 04/11] Changed redo key assignment from `\C-g` to `\M-\C-_` --- lib/reline/key_actor/emacs.rb | 4 ++-- test/reline/test_key_actor_emacs.rb | 24 ++++++++++----------- test/reline/yamatanooroti/test_rendering.rb | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/reline/key_actor/emacs.rb b/lib/reline/key_actor/emacs.rb index 254b250c28..d7354520b0 100644 --- a/lib/reline/key_actor/emacs.rb +++ b/lib/reline/key_actor/emacs.rb @@ -15,7 +15,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base # 6 ^F :ed_next_char, # 7 ^G - :redo, + :ed_unassigned, # 8 ^H :em_delete_prev_char, # 9 ^I @@ -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-! diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb index 395996da51..ce00923ed1 100644 --- a/test/reline/test_key_actor_emacs.rb +++ b/test/reline/test_key_actor_emacs.rb @@ -1509,32 +1509,32 @@ def test_undo_with_many_times def test_redo input_keys("aあb", false) assert_line_around_cursor('aあb', '') - input_keys("\C-g", false) + 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("\C-g", false) + input_keys("\M-\C-_", false) assert_line_around_cursor('aあ', '') - input_keys("\C-g", false) + 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("\C-g", false) + 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("\C-g", false) + input_keys("\M-\C-_", false) assert_line_around_cursor('a', 'c') input_keys("\C-_", false) assert_line_around_cursor('ab', 'c') - input_keys("\C-g", false) + input_keys("\M-\C-_", false) assert_line_around_cursor('a', 'c') end @@ -1556,12 +1556,12 @@ def test_redo_with_multiline assert_line_index(1) assert_line_around_cursor('2', '') - input_keys("\C-g", false) + input_keys("\M-\C-_", false) assert_whole_lines(["1", "2", ""]) assert_line_index(2) assert_line_around_cursor('', '') - input_keys("\C-g", false) + input_keys("\M-\C-_", false) assert_whole_lines(["1", "2", "3"]) assert_line_index(2) assert_line_around_cursor('3', '') @@ -1586,12 +1586,12 @@ def test_redo_with_multiline assert_line_index(1) assert_line_around_cursor('2', '') - input_keys("\C-g", false) + input_keys("\M-\C-_", false) assert_whole_lines(["1", "", "3"]) assert_line_index(1) assert_line_around_cursor('', '') - input_keys("\C-g", false) + input_keys("\M-\C-_", false) assert_whole_lines(["1", "3"]) assert_line_index(1) assert_line_around_cursor('3', '') @@ -1604,9 +1604,9 @@ def test_redo_with_many_times assert_line_around_cursor('a', '') input_keys("\C-_", false) assert_line_around_cursor('a', '') - 100.times { input_keys("\C-g", false) } + 100.times { input_keys("\M-\C-_", false) } assert_line_around_cursor(str, '') - input_keys("\C-g", false) + input_keys("\M-\C-_", false) assert_line_around_cursor(str, '') end end diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index a960880597..1cf46b4cd1 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -575,7 +575,7 @@ def test_bracketed_paste_with_redo write("abc") write("\e[200~def hoge\r\t3\rend\e[201~") write("\C-_") - write("\C-g") + write("\M-\C-_") close assert_screen(<<~EOC) Multiline REPL. From 9e0d6ad14e18173930419f1e617fb44608984e14 Mon Sep 17 00:00:00 2001 From: verdy89 Date: Thu, 23 May 2024 23:20:14 +0900 Subject: [PATCH 05/11] Revert the first implemantation --- lib/reline/line_editor.rb | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index f30ba12072..23ece60220 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -252,7 +252,6 @@ def reset_variables(prompt = '', encoding:) @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0) @past_lines = [] @undoing = false - @next_lines = [] reset_line end @@ -1138,10 +1137,7 @@ def input_key(key) @completion_journey_state = nil end - unless @undoing - push_past_lines - @next_lines = [] - end + push_past_lines unless @undoing @undoing = false if @in_pasting @@ -1178,18 +1174,6 @@ def trim_past_lines end end - def push_next_lines - @next_lines.push([@buffer_of_lines, @byte_pointer, @line_index]) - trim_next_lines - end - - MAX_NEXT_LINES = 100 - def trim_next_lines - if @next_lines.size > MAX_NEXT_LINES - @next_lines.shift - end - end - def scroll_into_view _wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position if wrapped_cursor_y < screen_scroll_top @@ -2545,27 +2529,13 @@ def finish end private def undo(_key) - @undoing = true - return if @past_lines.empty? - push_next_lines + @undoing = true target_lines, target_cursor_x, target_cursor_y = @past_lines.last set_current_lines(target_lines, target_cursor_x, target_cursor_y) @past_lines.pop end - - private def redo(_key) - @undoing = true - - return if @next_lines.empty? - - @past_lines.push([@buffer_of_lines, @byte_pointer, @line_index]) - target_lines, target_cursor_x, target_cursor_y = @next_lines.last - set_current_lines(target_lines, target_cursor_x, target_cursor_y) - - @next_lines.pop - end end From a28ab63c51e8747b28afe3f89f4d736d114c2c86 Mon Sep 17 00:00:00 2001 From: verdy89 Date: Sat, 25 May 2024 22:42:44 +0900 Subject: [PATCH 06/11] Implemented redo by sharing `@past_lines` between undo and redo --- lib/reline/line_editor.rb | 33 ++++++++++++++++++++++------- test/reline/test_key_actor_emacs.rb | 4 ++-- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 23ece60220..f20eda2a7e 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -250,7 +250,8 @@ def reset_variables(prompt = '', encoding:) @resized = false @cache = {} @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0) - @past_lines = [] + @past_lines = [[[""], 0, 0]] + @position = 0 @undoing = false reset_line end @@ -1137,7 +1138,10 @@ def input_key(key) @completion_journey_state = nil end - push_past_lines unless @undoing + unless @undoing + @past_lines = @past_lines[0..@position] + push_past_lines + end @undoing = false if @in_pasting @@ -1161,8 +1165,11 @@ def save_old_buffer 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]) + if @old_buffer_of_lines == @buffer_of_lines + @past_lines[-1] = [@buffer_of_lines.dup, @byte_pointer, @line_index] + else + @position += 1 + @past_lines.push([@buffer_of_lines.dup, @byte_pointer, @line_index]) end trim_past_lines end @@ -1171,6 +1178,7 @@ def push_past_lines def trim_past_lines if @past_lines.size > MAX_PAST_LINES @past_lines.shift + @position -= 1 end end @@ -2529,13 +2537,22 @@ def finish end private def undo(_key) - return if @past_lines.empty? + @undoing = true + + return if @position <= 0 + + @position -= 1 + target_lines, target_cursor_x, target_cursor_y = @past_lines[@position] + set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y) + end + private def redo(_key) @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 @position >= @past_lines.size - 1 - @past_lines.pop + @position += 1 + target_lines, target_cursor_x, target_cursor_y = @past_lines[@position] + set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y) end end diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb index ce00923ed1..a2ea060ab9 100644 --- a/test/reline/test_key_actor_emacs.rb +++ b/test/reline/test_key_actor_emacs.rb @@ -1498,7 +1498,7 @@ def test_undo_with_multiline 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', '') @@ -1598,7 +1598,7 @@ def test_redo_with_multiline end def test_redo_with_many_times - str = "a" + "b" * 99 + "c" + str = "a" + "b" * 98 + "c" input_keys(str, false) 100.times { input_keys("\C-_", false) } assert_line_around_cursor('a', '') From 99cf6c1b1a8485ad78e1b6720eb935884a80ab7b Mon Sep 17 00:00:00 2001 From: verdy89 Date: Sat, 25 May 2024 23:57:04 +0900 Subject: [PATCH 07/11] Fixed the index of past_lines that is updated when the cursor is moved --- lib/reline/line_editor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index f20eda2a7e..1988198409 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -1166,7 +1166,7 @@ def save_old_buffer def push_past_lines if @old_buffer_of_lines == @buffer_of_lines - @past_lines[-1] = [@buffer_of_lines.dup, @byte_pointer, @line_index] + @past_lines[@position] = [@buffer_of_lines.dup, @byte_pointer, @line_index] else @position += 1 @past_lines.push([@buffer_of_lines.dup, @byte_pointer, @line_index]) From 720cd98a36bdc012de2201466011074d1daa5f05 Mon Sep 17 00:00:00 2001 From: verdy89 Date: Sun, 26 May 2024 09:29:04 +0900 Subject: [PATCH 08/11] Fixed deletion of the redo history in regular input --- lib/reline/line_editor.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 1988198409..bc4a3350b3 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -1138,10 +1138,7 @@ def input_key(key) @completion_journey_state = nil end - unless @undoing - @past_lines = @past_lines[0..@position] - push_past_lines - end + push_past_lines unless @undoing @undoing = false if @in_pasting @@ -1168,6 +1165,7 @@ def push_past_lines if @old_buffer_of_lines == @buffer_of_lines @past_lines[@position] = [@buffer_of_lines.dup, @byte_pointer, @line_index] else + @past_lines = @past_lines[0..@position] @position += 1 @past_lines.push([@buffer_of_lines.dup, @byte_pointer, @line_index]) end From 0ab3c67be8ba157e3179bacccd2be14939fbe612 Mon Sep 17 00:00:00 2001 From: verdy89 Date: Mon, 27 May 2024 15:51:17 +0900 Subject: [PATCH 09/11] Renamed variables: past_lines -> input_lines --- lib/reline/line_editor.rb | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index bc4a3350b3..e5fd3752d7 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -250,7 +250,7 @@ def reset_variables(prompt = '', encoding:) @resized = false @cache = {} @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0) - @past_lines = [[[""], 0, 0]] + @input_lines = [[[""], 0, 0]] @position = 0 @undoing = false reset_line @@ -1138,7 +1138,7 @@ def input_key(key) @completion_journey_state = nil end - push_past_lines unless @undoing + push_input_lines unless @undoing @undoing = false if @in_pasting @@ -1161,21 +1161,21 @@ def save_old_buffer @old_line_index = @line_index.dup end - def push_past_lines + def push_input_lines if @old_buffer_of_lines == @buffer_of_lines - @past_lines[@position] = [@buffer_of_lines.dup, @byte_pointer, @line_index] + @input_lines[@position] = [@buffer_of_lines.dup, @byte_pointer, @line_index] else - @past_lines = @past_lines[0..@position] + @input_lines = @input_lines[0..@position] @position += 1 - @past_lines.push([@buffer_of_lines.dup, @byte_pointer, @line_index]) + @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 @position -= 1 end end @@ -1358,7 +1358,7 @@ def insert_pasted_text(text) @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) @@ -2540,17 +2540,17 @@ def finish return if @position <= 0 @position -= 1 - target_lines, target_cursor_x, target_cursor_y = @past_lines[@position] + target_lines, target_cursor_x, target_cursor_y = @input_lines[@position] set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y) end private def redo(_key) @undoing = true - return if @position >= @past_lines.size - 1 + return if @position >= @input_lines.size - 1 @position += 1 - target_lines, target_cursor_x, target_cursor_y = @past_lines[@position] + target_lines, target_cursor_x, target_cursor_y = @input_lines[@position] set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y) end end From 7aee2caa05b0197607557eef80c6816b30b2ef44 Mon Sep 17 00:00:00 2001 From: verdy89 Date: Mon, 27 May 2024 15:59:00 +0900 Subject: [PATCH 10/11] Rename @position to @input_lines_position --- lib/reline/line_editor.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index e5fd3752d7..ce85213399 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -251,7 +251,7 @@ def reset_variables(prompt = '', encoding:) @cache = {} @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0) @input_lines = [[[""], 0, 0]] - @position = 0 + @input_lines_position = 0 @undoing = false reset_line end @@ -1163,10 +1163,10 @@ def save_old_buffer def push_input_lines if @old_buffer_of_lines == @buffer_of_lines - @input_lines[@position] = [@buffer_of_lines.dup, @byte_pointer, @line_index] + @input_lines[@input_lines_position] = [@buffer_of_lines.dup, @byte_pointer, @line_index] else - @input_lines = @input_lines[0..@position] - @position += 1 + @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_input_lines @@ -1176,7 +1176,7 @@ def push_input_lines def trim_input_lines if @input_lines.size > MAX_INPUT_LINES @input_lines.shift - @position -= 1 + @input_lines_position -= 1 end end @@ -2537,20 +2537,20 @@ def finish private def undo(_key) @undoing = true - return if @position <= 0 + return if @input_lines_position <= 0 - @position -= 1 - target_lines, target_cursor_x, target_cursor_y = @input_lines[@position] + @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 @position >= @input_lines.size - 1 + return if @input_lines_position >= @input_lines.size - 1 - @position += 1 - target_lines, target_cursor_x, target_cursor_y = @input_lines[@position] + @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 From 95a7108a0de765549e480a60f226636fcf7069d0 Mon Sep 17 00:00:00 2001 From: verdy89 Date: Mon, 27 May 2024 16:00:15 +0900 Subject: [PATCH 11/11] Deleted unused variables: `@old_byte_pointer` and `@old_line_index` --- lib/reline/line_editor.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index ce85213399..8f6421fb10 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -1157,8 +1157,6 @@ def input_key(key) 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_input_lines