From 6355a6e0b21bb95163fe63dbaace84f93661b475 Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Fri, 13 Dec 2024 01:40:03 +0900 Subject: [PATCH] Undo and redo should restore indentation (#793) * Undo and redo should restore indentation Undo and redo should not perform auto indentation. It should not change the indentation. Instead, it should restore previous indentation. * Rename ivar undoing(undoing or redoing) to restoring --- lib/reline/line_editor.rb | 43 ++++++++++------------------- test/reline/test_key_actor_emacs.rb | 14 ++++++++++ 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 86c7596df7..1b61d9abe7 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -252,7 +252,7 @@ def reset_variables(prompt = '') @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0) @input_lines = [[[""], 0, 0]] @input_lines_position = 0 - @undoing = false + @restoring = false @prev_action_state = NullActionState @next_action_state = NullActionState reset_line @@ -1070,8 +1070,8 @@ def input_key(key) @completion_journey_state = nil end - push_input_lines unless @undoing - @undoing = false + push_input_lines unless @restoring + @restoring = false if @in_pasting clear_dialogs @@ -1185,18 +1185,6 @@ def set_current_line(line, byte_pointer = nil) process_auto_indent end - def set_current_lines(lines, byte_pointer = nil, line_index = 0) - cursor = current_byte_pointer_cursor - @buffer_of_lines = lines - @line_index = line_index - if byte_pointer - @byte_pointer = byte_pointer - else - calculate_nearest_cursor(cursor) - end - process_auto_indent - end - def retrieve_completion_block quote_characters = Reline.completer_quote_characters before = current_line.byteslice(0, @byte_pointer).grapheme_clusters @@ -2368,24 +2356,23 @@ def finish @config.editing_mode = :vi_insert end - private def undo(_key) - @undoing = true + private def move_undo_redo(direction) + @restoring = true + return unless (0..@input_lines.size - 1).cover?(@input_lines_position + direction) - return if @input_lines_position <= 0 + @input_lines_position += direction + buffer_of_lines, byte_pointer, line_index = @input_lines[@input_lines_position] + @buffer_of_lines = buffer_of_lines.dup + @line_index = line_index + @byte_pointer = byte_pointer + end - @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) + private def undo(_key) + move_undo_redo(-1) 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) + move_undo_redo(+1) end private def prev_action_state_value(type) diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb index 9fd19f6079..4aea3a6547 100644 --- a/test/reline/test_key_actor_emacs.rb +++ b/test/reline/test_key_actor_emacs.rb @@ -1676,6 +1676,20 @@ def test_redo_with_multiline assert_line_around_cursor('3', '') end + def test_undo_redo_restores_indentation + @line_editor.multiline_on + @line_editor.confirm_multiline_termination_proc = proc {} + input_keys(" 1", false) + assert_whole_lines([' 1']) + input_keys("2", false) + assert_whole_lines([' 12']) + @line_editor.auto_indent_proc = proc { 2 } + input_keys("\C-_", false) + assert_whole_lines([' 1']) + input_keys("\M-\C-_", false) + assert_whole_lines([' 12']) + end + def test_redo_with_many_times str = "a" + "b" * 98 + "c" input_keys(str, false)