ruby-changes:59754
From: aycabta <ko1@a...>
Date: Mon, 20 Jan 2020 20:16:05 +0900 (JST)
Subject: [ruby-changes:59754] 3b407abe9b (master): [ruby/reline] Implement vi_prev_char and vi_to_prev_char
https://git.ruby-lang.org/ruby.git/commit/?id=3b407abe9b From 3b407abe9b8da640dc07617d3dacac0057ca597f Mon Sep 17 00:00:00 2001 From: aycabta <aycabta@g...> Date: Fri, 17 Jan 2020 20:17:23 +0900 Subject: [ruby/reline] Implement vi_prev_char and vi_to_prev_char https://github.com/ruby/reline/commit/0ad3ee63fa diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 6890fa5..9518a05 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -2131,6 +2131,54 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L2131 @waiting_proc = nil end + private def vi_prev_char(key, arg: 1) + @waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg) } + end + + private def vi_to_prev_char(key, arg: 1) + @waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg, true) } + end + + private def search_prev_char(key, arg, need_next_char = false) + if key.instance_of?(String) + inputed_char = key + else + inputed_char = key.chr + end + prev_total = nil + total = nil + found = false + @line.byteslice(0..@byte_pointer).grapheme_clusters.reverse_each do |mbchar| + # total has [byte_size, cursor] + unless total + # skip cursor point + width = Reline::Unicode.get_mbchar_width(mbchar) + total = [mbchar.bytesize, width] + else + if inputed_char == mbchar + arg -= 1 + if arg.zero? + found = true + break + end + end + width = Reline::Unicode.get_mbchar_width(mbchar) + prev_total = total + total = [total.first + mbchar.bytesize, total.last + width] + end + end + if not need_next_char and found and total + byte_size, width = total + @byte_pointer -= byte_size + @cursor -= width + elsif need_next_char and found and prev_total + byte_size, width = prev_total + @byte_pointer -= byte_size + @cursor -= width + end + @waiting_proc = nil + end + private def vi_join_lines(key, arg: 1) if @is_multiline and @buffer_of_lines.size > @line_index + 1 @cursor = calculate_width(@line) diff --git a/test/reline/test_key_actor_vi.rb b/test/reline/test_key_actor_vi.rb index d23bdb7..00d3453 100644 --- a/test/reline/test_key_actor_vi.rb +++ b/test/reline/test_key_actor_vi.rb @@ -651,6 +651,42 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase https://github.com/ruby/ruby/blob/trunk/test/reline/test_key_actor_vi.rb#L651 assert_cursor_max(6) end + def test_vi_prev_char + input_keys("abcdef\C-[") + assert_line('abcdef') + assert_byte_pointer_size('abcde') + assert_cursor(5) + assert_cursor_max(6) + input_keys('Fz') + assert_line('abcdef') + assert_byte_pointer_size('abcde') + assert_cursor(5) + assert_cursor_max(6) + input_keys('Fa') + assert_line('abcdef') + assert_byte_pointer_size('') + assert_cursor(0) + assert_cursor_max(6) + end + + def test_vi_to_prev_char + input_keys("abcdef\C-[") + assert_line('abcdef') + assert_byte_pointer_size('abcde') + assert_cursor(5) + assert_cursor_max(6) + input_keys('Tz') + assert_line('abcdef') + assert_byte_pointer_size('abcde') + assert_cursor(5) + assert_cursor_max(6) + input_keys('Ta') + assert_line('abcdef') + assert_byte_pointer_size('a') + assert_cursor(1) + assert_cursor_max(6) + end + def test_vi_delete_next_char input_keys("abc\C-[h") assert_byte_pointer_size('a') -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/