[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]