summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraycabta <aycabta@gmail.com>2020-04-17 03:03:12 +0900
committeraycabta <aycabta@gmail.com>2020-04-18 23:12:52 +0900
commitbea3e31e5f8b85f0665b94312418f97e71c14fc6 (patch)
treec68fd132f15af4875d0748b0a84f6e17badaa549
parent1e4efbb6d3e1794222703c2df2b0bb69bc4956cc (diff)
[ruby/reline] Add ed_search_prev_history
https://github.com/ruby/reline/commit/e9ae288825
-rw-r--r--lib/reline/line_editor.rb47
-rw-r--r--test/reline/test_key_actor_emacs.rb69
2 files changed, 116 insertions, 0 deletions
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index 7097a3d878..6f7afea274 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -1421,6 +1421,53 @@ class Reline::LineEditor
end
alias_method :forward_search_history, :vi_search_next
+ private def ed_search_prev_history(key, arg: 1)
+ history = nil
+ h_pointer = nil
+ line_no = nil
+ substr = @line.slice(0, @byte_pointer)
+ if @history_pointer.nil?
+ return if not @line.empty? and substr.empty?
+ history = Reline::HISTORY
+ elsif @history_pointer.zero?
+ history = nil
+ h_pointer = nil
+ else
+ history = Reline::HISTORY.slice(0, @history_pointer)
+ end
+ return if history.nil?
+ if @is_multiline
+ h_pointer = history.rindex { |h|
+ h.split("\n").each_with_index { |l, i|
+ if l.start_with?(substr)
+ line_no = i
+ break
+ end
+ }
+ not line_no.nil?
+ }
+ else
+ h_pointer = history.rindex { |l|
+ l.start_with?(substr)
+ }
+ end
+ return if h_pointer.nil?
+ @history_pointer = h_pointer
+ if @is_multiline
+ @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
+ @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
+ @line_index = line_no
+ @line = @buffer_of_lines.last
+ @rerender_all = true
+ else
+ @line = Reline::HISTORY[@history_pointer]
+ end
+ @cursor_max = calculate_width(@line)
+ arg -= 1
+ ed_search_prev_history(key, arg: arg) if arg > 0
+ end
+ alias_method :history_search_backward, :ed_search_prev_history
+
private def ed_prev_history(key, arg: 1)
if @is_multiline and @line_index > 0
@previous_line_index = @line_index
diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb
index 5ab3032f4e..a5de605314 100644
--- a/test/reline/test_key_actor_emacs.rb
+++ b/test/reline/test_key_actor_emacs.rb
@@ -1912,6 +1912,75 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
$VERBOSE = verbose
end
+ def test_ed_search_prev_history
+ Reline::HISTORY.concat([
+ '12356', # old
+ '12aaa',
+ '12345' # new
+ ])
+ input_keys('123')
+ # The ed_search_prev_history doesn't have default binding
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_byte_pointer_size('123')
+ assert_cursor(3)
+ assert_cursor_max(5)
+ assert_line('12345')
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_byte_pointer_size('123')
+ assert_cursor(3)
+ assert_cursor_max(5)
+ assert_line('12356')
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_byte_pointer_size('123')
+ assert_cursor(3)
+ assert_cursor_max(5)
+ assert_line('12356')
+ end
+
+ def test_ed_search_prev_history_with_empty
+ Reline::HISTORY.concat([
+ '12356', # old
+ '12aaa',
+ '12345' # new
+ ])
+ # The ed_search_prev_history doesn't have default binding
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(5)
+ assert_line('12345')
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(5)
+ assert_line('12aaa')
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(5)
+ assert_line('12356')
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(5)
+ assert_line('12356')
+ end
+
+ def test_ed_search_prev_history_without_match
+ Reline::HISTORY.concat([
+ '12356', # old
+ '12aaa',
+ '12345' # new
+ ])
+ input_keys('ABC')
+ # The ed_search_prev_history doesn't have default binding
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_byte_pointer_size('ABC')
+ assert_cursor(3)
+ assert_cursor_max(3)
+ assert_line('ABC')
+ end
+
=begin # TODO: move KeyStroke instance from Reline to LineEditor
def test_key_delete
input_keys('ab')