ruby-changes:63940
From: aycabta <ko1@a...>
Date: Sat, 5 Dec 2020 03:09:42 +0900 (JST)
Subject: [ruby-changes:63940] ba8e5f77eb (master): [ruby/reline] Motions e, E, t, f should include a char on cursor if follows operator
https://git.ruby-lang.org/ruby.git/commit/?id=ba8e5f77eb From ba8e5f77eb2562cc0605f1414426a34c7e844964 Mon Sep 17 00:00:00 2001 From: aycabta <aycabta@g...> Date: Sat, 7 Nov 2020 12:05:43 +0900 Subject: [ruby/reline] Motions e, E, t, f should include a char on cursor if follows operator https://github.com/ruby/reline/commit/86e9a76499 diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 8425a47..f9ef980 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -698,7 +698,7 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L698 if @waiting_operator_proc if VI_MOTIONS.include?(method_symbol) old_cursor, old_byte_pointer = @cursor, @byte_pointer - block.() + block.(true) unless @waiting_proc cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer @cursor, @byte_pointer = old_cursor, old_byte_pointer @@ -718,27 +718,41 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L718 end else # Ignores operator when not motion is given. - block.() + block.(false) end @waiting_operator_proc = nil else - block.() + block.(false) end end private def argumentable?(method_obj) - method_obj and method_obj.parameters.length != 1 + method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :arg } end - def wrap_method_call(method_symbol, method_obj, key) + private def inclusive?(method_obj) + # If a motion method with the keyword argument "inclusive" follows the + # operator, it must contain the character at the cursor position. + method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :inclusive } + end + + def wrap_method_call(method_symbol, method_obj, key, with_operator = false) if @config.editing_mode_is?(:emacs, :vi_insert) and @waiting_proc.nil? and @waiting_operator_proc.nil? not_insertion = method_symbol != :ed_insert process_insert(force: not_insertion) end if @vi_arg and argumentable?(method_obj) - method_obj.(key, arg: @vi_arg) + if with_operator and inclusive?(method_obj) + method_obj.(key, arg: @vi_arg, inclusive: true) + else + method_obj.(key, arg: @vi_arg) + end else - method_obj.(key) + if with_operator and inclusive?(method_obj) + method_obj.(key, inclusive: true) + else + method_obj.(key) + end end end @@ -750,8 +764,8 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L764 end if method_symbol and key.is_a?(Symbol) if @vi_arg and argumentable?(method_obj) - run_for_operators(key, method_symbol) do - wrap_method_call(method_symbol, method_obj, key) + run_for_operators(key, method_symbol) do |with_operator| + wrap_method_call(method_symbol, method_obj, key, with_operator) end else wrap_method_call(method_symbol, method_obj, key) if method_obj @@ -763,8 +777,8 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L777 ed_argument_digit(key) else if argumentable?(method_obj) - run_for_operators(key, method_symbol) do - wrap_method_call(method_symbol, method_obj, key) + run_for_operators(key, method_symbol) do |with_operator| + wrap_method_call(method_symbol, method_obj, key, with_operator) end elsif @waiting_proc @waiting_proc.(key) @@ -783,8 +797,8 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L797 if method_symbol == :ed_argument_digit wrap_method_call(method_symbol, method_obj, key) else - run_for_operators(key, method_symbol) do - wrap_method_call(method_symbol, method_obj, key) + run_for_operators(key, method_symbol) do |with_operator| + wrap_method_call(method_symbol, method_obj, key, with_operator) end end @kill_ring.process @@ -1962,13 +1976,22 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L1976 vi_prev_word(key, arg: arg) if arg > 0 end - private def vi_end_word(key, arg: 1) + private def vi_end_word(key, arg: 1, inclusive: false) if @line.bytesize > @byte_pointer byte_size, width = Reline::Unicode.vi_forward_end_word(@line, @byte_pointer) @byte_pointer += byte_size @cursor += width end arg -= 1 + if inclusive and arg.zero? + byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) + if byte_size > 0 + c = @line.byteslice(@byte_pointer, byte_size) + width = Reline::Unicode.get_mbchar_width(c) + @byte_pointer += byte_size + @cursor += width + end + end vi_end_word(key, arg: arg) if arg > 0 end @@ -1992,13 +2015,22 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L2015 vi_prev_big_word(key, arg: arg) if arg > 0 end - private def vi_end_big_word(key, arg: 1) + private def vi_end_big_word(key, arg: 1, inclusive: false) if @line.bytesize > @byte_pointer byte_size, width = Reline::Unicode.vi_big_forward_end_word(@line, @byte_pointer) @byte_pointer += byte_size @cursor += width end arg -= 1 + if inclusive and arg.zero? + byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) + if byte_size > 0 + c = @line.byteslice(@byte_pointer, byte_size) + width = Reline::Unicode.get_mbchar_width(c) + @byte_pointer += byte_size + @cursor += width + end + end vi_end_big_word(key, arg: arg) if arg > 0 end @@ -2235,15 +2267,15 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L2267 } end - private def vi_next_char(key, arg: 1) - @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg) } + private def vi_next_char(key, arg: 1, inclusive: false) + @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, inclusive: inclusive) } end - private def vi_to_next_char(key, arg: 1) - @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, true) } + private def vi_to_next_char(key, arg: 1, inclusive: false) + @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, need_prev_char: true, inclusive: inclusive) } end - private def search_next_char(key, arg, need_prev_char = false) + private def search_next_char(key, arg, need_prev_char: false, inclusive: false) if key.instance_of?(String) inputed_char = key else @@ -2280,6 +2312,15 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L2312 @byte_pointer += byte_size @cursor += width end + if inclusive + byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) + if byte_size > 0 + c = @line.byteslice(@byte_pointer, byte_size) + width = Reline::Unicode.get_mbchar_width(c) + @byte_pointer += byte_size + @cursor += width + end + end @waiting_proc = nil end diff --git a/test/reline/test_key_actor_vi.rb b/test/reline/test_key_actor_vi.rb index 6f318db..7c0eea1 100644 --- a/test/reline/test_key_actor_vi.rb +++ b/test/reline/test_key_actor_vi.rb @@ -1224,8 +1224,8 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase https://github.com/ruby/ruby/blob/trunk/test/reline/test_key_actor_vi.rb#L1224 input_keys('df_') assert_byte_pointer_size('aaa bbb ') assert_cursor(8) - assert_cursor_max(15) - assert_line('aaa bbb ___ ddd') + assert_cursor_max(14) + assert_line('aaa bbb __ ddd') end def test_vi_delete_meta_with_arg @@ -1294,4 +1294,63 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase https://github.com/ruby/ruby/blob/trunk/test/reline/test_key_actor_vi.rb#L1294 assert_cursor(2) assert_cursor_max(10) end + + def test_vi_end_word_with_operator + input_keys("foo bar\C-[0") + assert_line('foo bar') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(7) + input_keys('de') + assert_line(' bar') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(4) + input_keys('de') + assert_line('') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + input_keys('de') + assert_line('') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + end + + def test_vi_end_big_word_with_operator + input_keys("aaa b{b}}}b\C-[0") + assert_line('aaa b{b}}}b') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(13) + input_keys('dE') + assert_line(' b{b}}}b') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(10) + input_keys('dE') + assert_line('') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + input_keys('dE') + assert_line('') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(0) + end + + def test_vi_next_char_with_operator + input_keys("foo bar\C-[0") + assert_line('foo bar') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(7) + input_keys('df ') + assert_line('bar') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(3) + end end -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/