diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb index b0f4d3dbff..12ae903186 100644 --- a/lib/reline/ansi.rb +++ b/lib/reline/ansi.rb @@ -6,7 +6,9 @@ class Reline::ANSI [27, 91, 68] => :ed_prev_char, # ← [27, 91, 51, 126] => :key_delete, # Del [27, 91, 49, 126] => :ed_move_to_beg, # Home - [27, 91, 52, 126] => :ed_move_to_end, # End + [27, 91, 68] => :ed_prev_char, # ← + [27, 32] => :em_set_mark, # M- + [24, 24] => :em_exchange_mark, # C-x C-x TODO also add Windows } @@input = STDIN diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index ddb9e0ae2a..8071080ccf 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -138,6 +138,7 @@ def eof? def reset_variables(prompt = '', encoding = Encoding.default_external) @prompt = prompt + @mark_pointer = nil @encoding = encoding @is_multiline = false @finished = false @@ -1941,4 +1942,20 @@ def finish arg -= 1 vi_join_lines(key, arg: arg) if arg > 0 end + + private def em_set_mark(key) + @mark_pointer = [@byte_pointer, @line_index] + end + alias_method :set_mark, :em_set_mark + + private def em_exchange_mark(key) + new_pointer = [@byte_pointer, @line_index] + @previous_line_index = @line_index + @byte_pointer, @line_index = @mark_pointer + @byte_pointer, @line_index = @mark_pointer + @cursor = calculate_width(@line.byteslice(0, @byte_pointer)) + @cursor_max = calculate_width(@line) + @mark_pointer = new_pointer + end + alias_method :exchange_point_and_mark, :em_exchange_mark end diff --git a/test/reline/helper.rb b/test/reline/helper.rb index b1759f1d80..0b5b8af310 100644 --- a/test/reline/helper.rb +++ b/test/reline/helper.rb @@ -44,6 +44,10 @@ class Reline::TestCase < Test::Unit::TestCase retry end + def input_key_by_symbol(input) + @line_editor.input_key(Reline::Key.new(input, input, false)) + end + def input_keys(input, convert = true) input = convert_str(input) if convert input.chars.each do |c| diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb index 5c5e74f5c8..5857f653cf 100644 --- a/test/reline/test_key_actor_emacs.rb +++ b/test/reline/test_key_actor_emacs.rb @@ -1403,6 +1403,38 @@ def test_larger_histories_than_history_size @config.history_size = history_size end + def test_em_set_mark_and_em_exchange_mark + input_keys('aaa bbb ccc ddd') + assert_byte_pointer_size('aaa bbb ccc ddd') + assert_cursor(15) + assert_cursor_max(15) + assert_line('aaa bbb ccc ddd') + input_keys("\C-a\M-F\M-F", false) + assert_byte_pointer_size('aaa bbb') + assert_cursor(7) + assert_cursor_max(15) + assert_line('aaa bbb ccc ddd') + assert_equal(nil, @line_editor.instance_variable_get(:@mark_pointer)) + input_keys("\x00", false) # C-Space + assert_byte_pointer_size('aaa bbb') + assert_cursor(7) + assert_cursor_max(15) + assert_line('aaa bbb ccc ddd') + assert_equal([7, 0], @line_editor.instance_variable_get(:@mark_pointer)) + input_keys("\C-a", false) + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(15) + assert_line('aaa bbb ccc ddd') + assert_equal([7, 0], @line_editor.instance_variable_get(:@mark_pointer)) + input_key_by_symbol(:em_exchange_mark) + assert_byte_pointer_size('aaa bbb') + assert_cursor(7) + assert_cursor_max(15) + assert_line('aaa bbb ccc ddd') + assert_equal([0, 0], @line_editor.instance_variable_get(:@mark_pointer)) + end + =begin # TODO: move KeyStroke instance from Reline to LineEditor def test_key_delete input_keys('ab')