summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomoya ishida <tomoyapenguin@gmail.com>2024-06-03 22:14:57 +0900
committergit <svn-admin@ruby-lang.org>2024-06-03 13:15:05 +0000
commit91d4a7ae0c719697db7dd6dd64ca664b60c9de04 (patch)
tree66e2d8d2a077c79f8acfec1feccbce48e6805df0
parent631449ac6b9336dfce577a786aff7eca0b8abcf1 (diff)
[ruby/reline] Improve key binding match/matching check
(https://github.com/ruby/reline/pull/709) * Improve key binding match/matching check * Rename key_actors to default_key_bindings * Make key_stroke.expand always return a value * Update add_default_key_binding to use a add_default_key_binding_by_keymap internally Co-authored-by: Stan Lo <stan001212@gmail.com> --------- https://github.com/ruby/reline/commit/353ec236e2 Co-authored-by: Stan Lo <stan001212@gmail.com>
-rw-r--r--lib/reline.rb31
-rw-r--r--lib/reline/config.rb40
-rw-r--r--lib/reline/key_actor.rb1
-rw-r--r--lib/reline/key_actor/base.rb28
-rw-r--r--lib/reline/key_actor/composite.rb17
-rw-r--r--lib/reline/key_actor/emacs.rb4
-rw-r--r--lib/reline/key_actor/vi_command.rb4
-rw-r--r--lib/reline/key_actor/vi_insert.rb4
-rw-r--r--lib/reline/key_stroke.rb140
-rw-r--r--lib/reline/line_editor.rb4
-rw-r--r--test/reline/helper.rb2
-rw-r--r--test/reline/test_config.rb72
-rw-r--r--test/reline/test_key_actor_emacs.rb2
-rw-r--r--test/reline/test_key_actor_vi.rb42
-rw-r--r--test/reline/test_key_stroke.rb32
-rw-r--r--test/reline/test_reline.rb4
-rw-r--r--test/reline/test_reline_key.rb51
17 files changed, 201 insertions, 277 deletions
diff --git a/lib/reline.rb b/lib/reline.rb
index 796e637e85..33a1cfc625 100644
--- a/lib/reline.rb
+++ b/lib/reline.rb
@@ -19,20 +19,10 @@ module Reline
class ConfigEncodingConversionError < StandardError; end
Key = Struct.new(:char, :combined_char, :with_meta) do
- def match?(other)
- case other
- when Reline::Key
- (other.char.nil? or char.nil? or char == other.char) and
- (other.combined_char.nil? or combined_char.nil? or combined_char == other.combined_char) and
- (other.with_meta.nil? or with_meta.nil? or with_meta == other.with_meta)
- when Integer, Symbol
- (combined_char and combined_char == other) or
- (combined_char.nil? and char and char == other)
- else
- false
- end
+ # For dialog_proc `key.match?(dialog.name)`
+ def match?(sym)
+ combined_char.is_a?(Symbol) && combined_char == sym
end
- alias_method :==, :match?
end
CursorPos = Struct.new(:x, :y)
DialogRenderInfo = Struct.new(
@@ -400,9 +390,8 @@ module Reline
end
case result
when :matched
- expanded = key_stroke.expand(buffer).map{ |expanded_c|
- Reline::Key.new(expanded_c, expanded_c, false)
- }
+ expanded, rest_bytes = key_stroke.expand(buffer)
+ rest_bytes.reverse_each { |c| io_gate.ungetc(c) }
block.(expanded)
break
when :matching
@@ -416,9 +405,8 @@ module Reline
if buffer.size == 1 and c == "\e".ord
read_escaped_key(keyseq_timeout, c, block)
else
- expanded = buffer.map{ |expanded_c|
- Reline::Key.new(expanded_c, expanded_c, false)
- }
+ expanded, rest_bytes = key_stroke.expand(buffer)
+ rest_bytes.reverse_each { |c| io_gate.ungetc(c) }
block.(expanded)
end
break
@@ -442,9 +430,8 @@ module Reline
return :next
when :matched
buffer << succ_c
- expanded = key_stroke.expand(buffer).map{ |expanded_c|
- Reline::Key.new(expanded_c, expanded_c, false)
- }
+ expanded, rest_bytes = key_stroke.expand(buffer)
+ rest_bytes.reverse_each { |c| io_gate.ungetc(c) }
block.(expanded)
return :break
end
diff --git a/lib/reline/config.rb b/lib/reline/config.rb
index 62c6d105b3..774b06b6fd 100644
--- a/lib/reline/config.rb
+++ b/lib/reline/config.rb
@@ -29,18 +29,20 @@ class Reline::Config
attr_accessor :autocompletion
def initialize
- @additional_key_bindings = {} # from inputrc
- @additional_key_bindings[:emacs] = {}
- @additional_key_bindings[:vi_insert] = {}
- @additional_key_bindings[:vi_command] = {}
- @oneshot_key_bindings = {}
+ @additional_key_bindings = { # from inputrc
+ emacs: Reline::KeyActor::Base.new,
+ vi_insert: Reline::KeyActor::Base.new,
+ vi_command: Reline::KeyActor::Base.new
+ }
+ @oneshot_key_bindings = Reline::KeyActor::Base.new
@editing_mode_label = :emacs
@keymap_label = :emacs
@keymap_prefix = []
- @key_actors = {}
- @key_actors[:emacs] = Reline::KeyActor::Emacs.new
- @key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
- @key_actors[:vi_command] = Reline::KeyActor::ViCommand.new
+ @default_key_bindings = {
+ emacs: Reline::KeyActor::Base.new(Reline::KeyActor::EMACS_MAPPING),
+ vi_insert: Reline::KeyActor::Base.new(Reline::KeyActor::VI_INSERT_MAPPING),
+ vi_command: Reline::KeyActor::Base.new(Reline::KeyActor::VI_COMMAND_MAPPING)
+ }
@vi_cmd_mode_string = '(cmd)'
@vi_ins_mode_string = '(ins)'
@emacs_mode_string = '@'
@@ -62,7 +64,7 @@ class Reline::Config
end
def editing_mode
- @key_actors[@editing_mode_label]
+ @default_key_bindings[@editing_mode_label]
end
def editing_mode=(val)
@@ -74,7 +76,7 @@ class Reline::Config
end
def keymap
- @key_actors[@keymap_label]
+ @default_key_bindings[@keymap_label]
end
def loaded?
@@ -133,14 +135,14 @@ class Reline::Config
def key_bindings
# The key bindings for each editing mode will be overwritten by the user-defined ones.
- kb = @key_actors[@editing_mode_label].default_key_bindings.dup
- kb.merge!(@additional_key_bindings[@editing_mode_label])
- kb.merge!(@oneshot_key_bindings)
- kb
+ Reline::KeyActor::Composite.new([@oneshot_key_bindings, @additional_key_bindings[@editing_mode_label], @default_key_bindings[@editing_mode_label]])
end
def add_oneshot_key_binding(keystroke, target)
- @oneshot_key_bindings[keystroke] = target
+ # IRB sets invalid keystroke [Reline::Key]. We should ignore it.
+ return unless keystroke.all? { |c| c.is_a?(Integer) }
+
+ @oneshot_key_bindings.add(keystroke, target)
end
def reset_oneshot_key_bindings
@@ -148,11 +150,11 @@ class Reline::Config
end
def add_default_key_binding_by_keymap(keymap, keystroke, target)
- @key_actors[keymap].default_key_bindings[keystroke] = target
+ @default_key_bindings[keymap].add(keystroke, target)
end
def add_default_key_binding(keystroke, target)
- @key_actors[@keymap_label].default_key_bindings[keystroke] = target
+ add_default_key_binding_by_keymap(@keymap_label, keystroke, target)
end
def read_lines(lines, file = nil)
@@ -192,7 +194,7 @@ class Reline::Config
func_name = func_name.split.first
keystroke, func = bind_key(key, func_name)
next unless keystroke
- @additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
+ @additional_key_bindings[@keymap_label].add(@keymap_prefix + keystroke, func)
end
end
unless if_stack.empty?
diff --git a/lib/reline/key_actor.rb b/lib/reline/key_actor.rb
index ebe09d2009..0ac7604556 100644
--- a/lib/reline/key_actor.rb
+++ b/lib/reline/key_actor.rb
@@ -2,6 +2,7 @@ module Reline::KeyActor
end
require 'reline/key_actor/base'
+require 'reline/key_actor/composite'
require 'reline/key_actor/emacs'
require 'reline/key_actor/vi_command'
require 'reline/key_actor/vi_insert'
diff --git a/lib/reline/key_actor/base.rb b/lib/reline/key_actor/base.rb
index 194e98938c..ee28c7681e 100644
--- a/lib/reline/key_actor/base.rb
+++ b/lib/reline/key_actor/base.rb
@@ -1,15 +1,31 @@
class Reline::KeyActor::Base
- MAPPING = Array.new(256)
+ def initialize(mapping = [])
+ @mapping = mapping
+ @matching_bytes = {}
+ @key_bindings = {}
+ end
def get_method(key)
- self.class::MAPPING[key]
+ @mapping[key]
+ end
+
+ def add(key, func)
+ (1...key.size).each do |size|
+ @matching_bytes[key.take(size)] = true
+ end
+ @key_bindings[key] = func
+ end
+
+ def matching?(key)
+ @matching_bytes[key]
end
- def initialize
- @default_key_bindings = {}
+ def get(key)
+ @key_bindings[key]
end
- def default_key_bindings
- @default_key_bindings
+ def clear
+ @matching_bytes.clear
+ @key_bindings.clear
end
end
diff --git a/lib/reline/key_actor/composite.rb b/lib/reline/key_actor/composite.rb
new file mode 100644
index 0000000000..37e94ce6cf
--- /dev/null
+++ b/lib/reline/key_actor/composite.rb
@@ -0,0 +1,17 @@
+class Reline::KeyActor::Composite
+ def initialize(key_actors)
+ @key_actors = key_actors
+ end
+
+ def matching?(key)
+ @key_actors.any? { |key_actor| key_actor.matching?(key) }
+ end
+
+ def get(key)
+ @key_actors.each do |key_actor|
+ func = key_actor.get(key)
+ return func if func
+ end
+ nil
+ end
+end
diff --git a/lib/reline/key_actor/emacs.rb b/lib/reline/key_actor/emacs.rb
index d7354520b0..ad84ee1d99 100644
--- a/lib/reline/key_actor/emacs.rb
+++ b/lib/reline/key_actor/emacs.rb
@@ -1,5 +1,5 @@
-class Reline::KeyActor::Emacs < Reline::KeyActor::Base
- MAPPING = [
+module Reline::KeyActor
+ EMACS_MAPPING = [
# 0 ^@
:em_set_mark,
# 1 ^A
diff --git a/lib/reline/key_actor/vi_command.rb b/lib/reline/key_actor/vi_command.rb
index 06bb0ba8e4..d972c5e67f 100644
--- a/lib/reline/key_actor/vi_command.rb
+++ b/lib/reline/key_actor/vi_command.rb
@@ -1,5 +1,5 @@
-class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
- MAPPING = [
+module Reline::KeyActor
+ VI_COMMAND_MAPPING = [
# 0 ^@
:ed_unassigned,
# 1 ^A
diff --git a/lib/reline/key_actor/vi_insert.rb b/lib/reline/key_actor/vi_insert.rb
index f8ccf468c6..312df1646b 100644
--- a/lib/reline/key_actor/vi_insert.rb
+++ b/lib/reline/key_actor/vi_insert.rb
@@ -1,5 +1,5 @@
-class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
- MAPPING = [
+module Reline::KeyActor
+ VI_INSERT_MAPPING = [
# 0 ^@
:ed_unassigned,
# 1 ^A
diff --git a/lib/reline/key_stroke.rb b/lib/reline/key_stroke.rb
index bceffbb53f..419ddd8cea 100644
--- a/lib/reline/key_stroke.rb
+++ b/lib/reline/key_stroke.rb
@@ -7,139 +7,69 @@ class Reline::KeyStroke
@config = config
end
- def compress_meta_key(ary)
- return ary unless @config.convert_meta
- ary.inject([]) { |result, key|
- if result.size > 0 and result.last == "\e".ord
- result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
- else
- result << key
- end
- result
- }
- end
-
- def start_with?(me, other)
- compressed_me = compress_meta_key(me)
- compressed_other = compress_meta_key(other)
- i = 0
- loop do
- my_c = compressed_me[i]
- other_c = compressed_other[i]
- other_is_last = (i + 1) == compressed_other.size
- me_is_last = (i + 1) == compressed_me.size
- if my_c != other_c
- if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
- return true
- else
- return false
- end
- elsif other_is_last
- return true
- elsif me_is_last
- return false
- end
- i += 1
- end
- end
-
- def equal?(me, other)
- case me
- when Array
- compressed_me = compress_meta_key(me)
- compressed_other = compress_meta_key(other)
- compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| equal?(i[0], i[1]) }
- when Integer
- if other.is_a?(Reline::Key)
- if other.combined_char == "\e".ord
- false
- else
- other.combined_char == me
- end
- else
- me == other
- end
- when Reline::Key
- if other.is_a?(Integer)
- me.combined_char == other
- else
- me == other
- end
- end
- end
-
def match_status(input)
- key_mapping.keys.select { |lhs|
- start_with?(lhs, input)
- }.tap { |it|
- return :matched if it.size == 1 && equal?(it[0], input)
- return :matching if it.size == 1 && !equal?(it[0], input)
- return :matched if it.max_by(&:size)&.size&.< input.size
- return :matching if it.size > 1
- }
- if key_mapping.keys.any? { |lhs| start_with?(input, lhs) }
+ if key_mapping.matching?(input)
+ :matching
+ elsif key_mapping.get(input)
+ :matched
+ elsif input[0] == ESC_BYTE
+ match_unknown_escape_sequence(input, vi_mode: @config.editing_mode_is?(:vi_insert, :vi_command))
+ elsif input.size == 1
:matched
else
- match_unknown_escape_sequence(input).first
+ :unmatched
end
end
def expand(input)
- lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
- unless lhs
- status, size = match_unknown_escape_sequence(input)
- case status
- when :matched
- return [:ed_unassigned] + expand(input.drop(size))
- when :matching
- return [:ed_unassigned]
- else
- return input
- end
+ matched_bytes = nil
+ (1..input.size).each do |i|
+ bytes = input.take(i)
+ matched_bytes = bytes if match_status(bytes) != :unmatched
end
- rhs = key_mapping[lhs]
+ return [[], []] unless matched_bytes
- case rhs
- when String
- rhs_bytes = rhs.bytes
- expand(expand(rhs_bytes) + expand(input.drop(lhs.size)))
- when Symbol
- [rhs] + expand(input.drop(lhs.size))
- when Array
- rhs
+ func = key_mapping.get(matched_bytes)
+ if func.is_a?(Array)
+ keys = func.map { |c| Reline::Key.new(c, c, false) }
+ elsif func
+ keys = [Reline::Key.new(func, func, false)]
+ elsif matched_bytes.size == 1
+ keys = [Reline::Key.new(matched_bytes.first, matched_bytes.first, false)]
+ elsif matched_bytes.size == 2 && matched_bytes[0] == ESC_BYTE
+ keys = [Reline::Key.new(matched_bytes[1], matched_bytes[1] | 0b10000000, true)]
+ else
+ keys = []
end
+
+ [keys, input.drop(matched_bytes.size)]
end
private
# returns match status of CSI/SS3 sequence and matched length
- def match_unknown_escape_sequence(input)
+ def match_unknown_escape_sequence(input, vi_mode: false)
idx = 0
- return [:unmatched, nil] unless input[idx] == ESC_BYTE
+ return :unmatched unless input[idx] == ESC_BYTE
idx += 1
idx += 1 if input[idx] == ESC_BYTE
case input[idx]
when nil
- return [:matching, nil]
+ return :matching
when 91 # == '['.ord
- # CSI sequence
+ # CSI sequence `ESC [ ... char`
idx += 1
idx += 1 while idx < input.size && CSI_PARAMETER_BYTES_RANGE.cover?(input[idx])
idx += 1 while idx < input.size && CSI_INTERMEDIATE_BYTES_RANGE.cover?(input[idx])
- input[idx] ? [:matched, idx + 1] : [:matching, nil]
when 79 # == 'O'.ord
- # SS3 sequence
- input[idx + 1] ? [:matched, idx + 2] : [:matching, nil]
+ # SS3 sequence `ESC O char`
+ idx += 1
else
- if idx == 1
- # `ESC char`, make it :unmatched so that it will be handled correctly in `read_2nd_character_of_key_sequence`
- [:unmatched, nil]
- else
- # `ESC ESC char`
- [:matched, idx + 1]
- end
+ # `ESC char` or `ESC ESC char`
+ return :unmatched if vi_mode
end
+ input[idx + 1] ? :unmatched : input[idx] ? :matched : :matching
end
def key_mapping
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index c2f5f0622e..6038d8a4fa 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -684,10 +684,8 @@ class Reline::LineEditor
@trap_key.each do |t|
@config.add_oneshot_key_binding(t, @name)
end
- elsif @trap_key.is_a?(Array)
+ else
@config.add_oneshot_key_binding(@trap_key, @name)
- elsif @trap_key.is_a?(Integer) or @trap_key.is_a?(Reline::Key)
- @config.add_oneshot_key_binding([@trap_key], @name)
end
end
dialog_render_info
diff --git a/test/reline/helper.rb b/test/reline/helper.rb
index a5f850e838..9a346a17a1 100644
--- a/test/reline/helper.rb
+++ b/test/reline/helper.rb
@@ -168,7 +168,7 @@ class Reline::TestCase < Test::Unit::TestCase
def assert_key_binding(input, method_symbol, editing_modes = [:emacs, :vi_insert, :vi_command])
editing_modes.each do |editing_mode|
@config.editing_mode = editing_mode
- assert_equal(method_symbol, @config.editing_mode.default_key_bindings[input.bytes])
+ assert_equal(method_symbol, @config.editing_mode.get(input.bytes))
end
end
end
diff --git a/test/reline/test_config.rb b/test/reline/test_config.rb
index 8c4b513600..16727c9bc9 100644
--- a/test/reline/test_config.rb
+++ b/test/reline/test_config.rb
@@ -22,6 +22,15 @@ class Reline::Config::Test < Reline::TestCase
@config.reset
end
+ def additional_key_bindings(keymap_label)
+ @config.instance_variable_get(:@additional_key_bindings)[keymap_label].instance_variable_get(:@key_bindings)
+ end
+
+ def registered_key_bindings(keys)
+ key_bindings = @config.key_bindings
+ keys.to_h { |key| [key, key_bindings.get(key)] }
+ end
+
def test_read_lines
@config.read_lines(<<~LINES.lines)
set bell-style on
@@ -97,14 +106,17 @@ class Reline::Config::Test < Reline::TestCase
assert_equal nil, @config.convert_meta
end
- def test_comment_line
- @config.read_lines([" #a: error\n"])
- assert_not_include @config.key_bindings, nil
- end
-
def test_invalid_keystroke
- @config.read_lines(["a: error\n"])
- assert_not_include @config.key_bindings, nil
+ @config.read_lines(<<~LINES.lines)
+ #"a": comment
+ a: error
+ "b": no-error
+ LINES
+ key_bindings = additional_key_bindings(:emacs)
+ assert_not_include key_bindings, 'a'.bytes
+ assert_not_include key_bindings, nil
+ assert_not_include key_bindings, []
+ assert_include key_bindings, 'b'.bytes
end
def test_bind_key
@@ -242,8 +254,8 @@ class Reline::Config::Test < Reline::TestCase
"\xC": "O"
LINES
keys = [0x1, 0x3, 0x4, 0x6, 0x7, 0xC]
- key_bindings = keys.to_h { |k| [[k.ord], ['O'.ord]] }
- assert_equal(key_bindings, @config.instance_variable_get(:@additional_key_bindings)[:emacs])
+ key_bindings = keys.to_h { |k| [[k], ['O'.ord]] }
+ assert_equal(key_bindings, additional_key_bindings(:emacs))
end
def test_unclosed_if
@@ -282,9 +294,9 @@ class Reline::Config::Test < Reline::TestCase
$endif
LINES
- assert_equal({[5] => :history_search_backward}, @config.instance_variable_get(:@additional_key_bindings)[:emacs])
- assert_equal({}, @config.instance_variable_get(:@additional_key_bindings)[:vi_insert])
- assert_equal({}, @config.instance_variable_get(:@additional_key_bindings)[:vi_command])
+ assert_equal({[5] => :history_search_backward}, additional_key_bindings(:emacs))
+ assert_equal({}, additional_key_bindings(:vi_insert))
+ assert_equal({}, additional_key_bindings(:vi_command))
end
def test_else
@@ -296,9 +308,9 @@ class Reline::Config::Test < Reline::TestCase
$endif
LINES
- assert_equal({[6] => :history_search_forward}, @config.instance_variable_get(:@additional_key_bindings)[:emacs])
- assert_equal({}, @config.instance_variable_get(:@additional_key_bindings)[:vi_insert])
- assert_equal({}, @config.instance_variable_get(:@additional_key_bindings)[:vi_command])
+ assert_equal({[6] => :history_search_forward}, additional_key_bindings(:emacs))
+ assert_equal({}, additional_key_bindings(:vi_insert))
+ assert_equal({}, additional_key_bindings(:vi_command))
end
def test_if_with_invalid_mode
@@ -310,9 +322,9 @@ class Reline::Config::Test < Reline::TestCase
$endif
LINES
- assert_equal({[6] => :history_search_forward}, @config.instance_variable_get(:@additional_key_bindings)[:emacs])
- assert_equal({}, @config.instance_variable_get(:@additional_key_bindings)[:vi_insert])
- assert_equal({}, @config.instance_variable_get(:@additional_key_bindings)[:vi_command])
+ assert_equal({[6] => :history_search_forward}, additional_key_bindings(:emacs))
+ assert_equal({}, additional_key_bindings(:vi_insert))
+ assert_equal({}, additional_key_bindings(:vi_command))
end
def test_mode_label_differs_from_keymap_label
@@ -327,9 +339,9 @@ class Reline::Config::Test < Reline::TestCase
"\C-e": history-search-backward
$endif
LINES
- assert_equal({[5] => :history_search_backward}, @config.instance_variable_get(:@additional_key_bindings)[:emacs])
- assert_equal({}, @config.instance_variable_get(:@additional_key_bindings)[:vi_insert])
- assert_equal({}, @config.instance_variable_get(:@additional_key_bindings)[:vi_command])
+ assert_equal({[5] => :history_search_backward}, additional_key_bindings(:emacs))
+ assert_equal({}, additional_key_bindings(:vi_insert))
+ assert_equal({}, additional_key_bindings(:vi_command))
end
def test_if_without_else_condition
@@ -340,9 +352,9 @@ class Reline::Config::Test < Reline::TestCase
$endif
LINES
- assert_equal({}, @config.instance_variable_get(:@additional_key_bindings)[:emacs])
- assert_equal({[5] => :history_search_backward}, @config.instance_variable_get(:@additional_key_bindings)[:vi_insert])
- assert_equal({}, @config.instance_variable_get(:@additional_key_bindings)[:vi_command])
+ assert_equal({}, additional_key_bindings(:emacs))
+ assert_equal({[5] => :history_search_backward}, additional_key_bindings(:vi_insert))
+ assert_equal({}, additional_key_bindings(:vi_command))
end
def test_default_key_bindings
@@ -353,7 +365,7 @@ class Reline::Config::Test < Reline::TestCase
LINES
expected = { 'abcd'.bytes => 'ABCD'.bytes, 'ijkl'.bytes => 'IJKL'.bytes }
- assert_equal expected, @config.key_bindings
+ assert_equal expected, registered_key_bindings(expected.keys)
end
def test_additional_key_bindings
@@ -363,7 +375,7 @@ class Reline::Config::Test < Reline::TestCase
LINES
expected = { 'ef'.bytes => 'EF'.bytes, 'gh'.bytes => 'GH'.bytes }
- assert_equal expected, @config.key_bindings
+ assert_equal expected, registered_key_bindings(expected.keys)
end
def test_additional_key_bindings_with_nesting_and_comment_out
@@ -375,7 +387,7 @@ class Reline::Config::Test < Reline::TestCase
LINES
expected = { 'ef'.bytes => 'EF'.bytes, 'gh'.bytes => 'GH'.bytes }
- assert_equal expected, @config.key_bindings
+ assert_equal expected, registered_key_bindings(expected.keys)
end
def test_additional_key_bindings_for_other_keymap
@@ -390,7 +402,7 @@ class Reline::Config::Test < Reline::TestCase
LINES
expected = { 'cd'.bytes => 'CD'.bytes }
- assert_equal expected, @config.key_bindings
+ assert_equal expected, registered_key_bindings(expected.keys)
end
def test_additional_key_bindings_for_auxiliary_emacs_keymaps
@@ -412,7 +424,7 @@ class Reline::Config::Test < Reline::TestCase
"\C-xef".bytes => 'EF'.bytes,
"\egh".bytes => 'GH'.bytes,
}
- assert_equal expected, @config.key_bindings
+ assert_equal expected, registered_key_bindings(expected.keys)
end
def test_key_bindings_with_reset
@@ -424,7 +436,7 @@ class Reline::Config::Test < Reline::TestCase
LINES
@config.reset
expected = { 'default'.bytes => 'DEFAULT'.bytes, 'additional'.bytes => 'ADDITIONAL'.bytes }
- assert_equal expected, @config.key_bindings
+ assert_equal expected, registered_key_bindings(expected.keys)
end
def test_history_size
diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb
index a2ea060ab9..36fbfd4040 100644
--- a/test/reline/test_key_actor_emacs.rb
+++ b/test/reline/test_key_actor_emacs.rb
@@ -1,6 +1,6 @@
require_relative 'helper'
-class Reline::KeyActor::Emacs::Test < Reline::TestCase
+class Reline::KeyActor::EmacsTest < Reline::TestCase
def setup
Reline.send(:test_mode)
@prompt = '> '
diff --git a/test/reline/test_key_actor_vi.rb b/test/reline/test_key_actor_vi.rb
index 4deae2dd83..1288b9aaa5 100644
--- a/test/reline/test_key_actor_vi.rb
+++ b/test/reline/test_key_actor_vi.rb
@@ -1,6 +1,6 @@
require_relative 'helper'
-class Reline::KeyActor::ViInsert::Test < Reline::TestCase
+class Reline::ViInsertTest < Reline::TestCase
def setup
Reline.send(:test_mode)
@prompt = '> '
@@ -13,69 +13,73 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
@line_editor.reset(@prompt, encoding: @encoding)
end
+ def editing_mode_label
+ @config.instance_variable_get(:@editing_mode_label)
+ end
+
def teardown
Reline.test_reset
end
def test_vi_command_mode
input_keys("\C-[")
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_equal(:vi_command, editing_mode_label)
end
def test_vi_command_mode_with_input
input_keys("abc\C-[")
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_equal(:vi_command, editing_mode_label)
assert_line_around_cursor('ab', 'c')
end
def test_vi_insert
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
input_keys('i')
assert_line_around_cursor('i', '')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
input_keys("\C-[")
assert_line_around_cursor('', 'i')
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_equal(:vi_command, editing_mode_label)
input_keys('i')
assert_line_around_cursor('', 'i')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
end
def test_vi_add
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
input_keys('a')
assert_line_around_cursor('a', '')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
input_keys("\C-[")
assert_line_around_cursor('', 'a')
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_equal(:vi_command, editing_mode_label)
input_keys('a')
assert_line_around_cursor('a', '')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
end
def test_vi_insert_at_bol
input_keys('I')
assert_line_around_cursor('I', '')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
input_keys("12345\C-[hh")
assert_line_around_cursor('I12', '345')
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_equal(:vi_command, editing_mode_label)
input_keys('I')
assert_line_around_cursor('', 'I12345')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
end
def test_vi_add_at_eol
input_keys('A')
assert_line_around_cursor('A', '')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
input_keys("12345\C-[hh")
assert_line_around_cursor('A12', '345')
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_equal(:vi_command, editing_mode_label)
input_keys('A')
assert_line_around_cursor('A12345', '')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
end
def test_ed_insert_one
@@ -901,11 +905,11 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
assert_line_around_cursor('abc', '')
input_keys("\C-[0C")
assert_line_around_cursor('', '')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
end
def test_vi_motion_operators
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
assert_nothing_raised do
input_keys("test = { foo: bar }\C-[BBBldt}b")
diff --git a/test/reline/test_key_stroke.rb b/test/reline/test_key_stroke.rb
index cd205c7d9e..de67c7ad44 100644
--- a/test/reline/test_key_stroke.rb
+++ b/test/reline/test_key_stroke.rb
@@ -27,13 +27,11 @@ class Reline::KeyStroke::Test < Reline::TestCase
assert_equal(:matching, stroke.match_status("a".bytes))
assert_equal(:matching, stroke.match_status("ab".bytes))
assert_equal(:matched, stroke.match_status("abc".bytes))
- assert_equal(:matched, stroke.match_status("abz".bytes))
- assert_equal(:matched, stroke.match_status("abx".bytes))
- assert_equal(:matched, stroke.match_status("ac".bytes))
- assert_equal(:matched, stroke.match_status("aa".bytes))
+ assert_equal(:unmatched, stroke.match_status("abz".bytes))
+ assert_equal(:unmatched, stroke.match_status("abcx".bytes))
+ assert_equal(:unmatched, stroke.match_status("aa".bytes))
assert_equal(:matched, stroke.match_status("x".bytes))
- assert_equal(:unmatched, stroke.match_status("m".bytes))
- assert_equal(:matched, stroke.match_status("abzwabk".bytes))
+ assert_equal(:unmatched, stroke.match_status("xa".bytes))
end
def test_match_unknown
@@ -47,10 +45,13 @@ class Reline::KeyStroke::Test < Reline::TestCase
"\e[1;1R", # Cursor position report
"\e[15~", # F5
"\eOP", # F1
- "\e\e[A" # Option+Up
+ "\e\e[A", # Option+Up
+ "\eX",
+ "\e\eX"
]
sequences.each do |seq|
assert_equal(:matched, stroke.match_status(seq.bytes))
+ assert_equal(:unmatched, stroke.match_status(seq.bytes + [32]))
(1...seq.size).each do |i|
assert_equal(:matching, stroke.match_status(seq.bytes.take(i)))
end
@@ -61,16 +62,18 @@ class Reline::KeyStroke::Test < Reline::TestCase
config = Reline::Config.new
{
'abc' => '123',
+ 'ab' => '456'
}.each_pair do |key, func|
config.add_default_key_binding(key.bytes, func.bytes)
end
stroke = Reline::KeyStroke.new(config)
- assert_equal('123'.bytes, stroke.expand('abc'.bytes))
+ assert_equal(['123'.bytes.map { |c| Reline::Key.new(c, c, false) }, 'de'.bytes], stroke.expand('abcde'.bytes))
+ assert_equal(['456'.bytes.map { |c| Reline::Key.new(c, c, false) }, 'de'.bytes], stroke.expand('abde'.bytes))
# CSI sequence
- assert_equal([:ed_unassigned] + 'bc'.bytes, stroke.expand("\e[1;2;3;4;5abc".bytes))
- assert_equal([:ed_unassigned] + 'BC'.bytes, stroke.expand("\e\e[ABC".bytes))
+ assert_equal([[], 'bc'.bytes], stroke.expand("\e[1;2;3;4;5abc".bytes))
+ assert_equal([[], 'BC'.bytes], stroke.expand("\e\e[ABC".bytes))
# SS3 sequence
- assert_equal([:ed_unassigned] + 'QR'.bytes, stroke.expand("\eOPQR".bytes))
+ assert_equal([[], 'QR'.bytes], stroke.expand("\eOPQR".bytes))
end
def test_oneshot_key_bindings
@@ -88,17 +91,14 @@ class Reline::KeyStroke::Test < Reline::TestCase
def test_with_reline_key
config = Reline::Config.new
{
- [
- Reline::Key.new(100, 228, true), # Alt+d
- Reline::Key.new(97, 97, false) # a
- ] => 'abc',
+ "\eda".bytes => 'abc', # Alt+d a
[195, 164] => 'def'
}.each_pair do |key, func|
config.add_oneshot_key_binding(key, func.bytes)
end
stroke = Reline::KeyStroke.new(config)
assert_equal(:unmatched, stroke.match_status('da'.bytes))
- assert_equal(:matched, stroke.match_status("\M-da".bytes))
+ assert_equal(:matched, stroke.match_status("\eda".bytes))
assert_equal(:unmatched, stroke.match_status([32, 195, 164]))
assert_equal(:matched, stroke.match_status([195, 164]))
end
diff --git a/test/reline/test_reline.rb b/test/reline/test_reline.rb
index c664ab74b0..deff411232 100644
--- a/test/reline/test_reline.rb
+++ b/test/reline/test_reline.rb
@@ -303,12 +303,12 @@ class Reline::Test < Reline::TestCase
def test_vi_editing_mode
Reline.vi_editing_mode
- assert_equal(Reline::KeyActor::ViInsert, Reline.core.config.editing_mode.class)
+ assert_equal(:vi_insert, Reline.core.config.instance_variable_get(:@editing_mode_label))
end
def test_emacs_editing_mode
Reline.emacs_editing_mode
- assert_equal(Reline::KeyActor::Emacs, Reline.core.config.editing_mode.class)
+ assert_equal(:emacs, Reline.core.config.instance_variable_get(:@editing_mode_label))
end
def test_add_dialog_proc
diff --git a/test/reline/test_reline_key.rb b/test/reline/test_reline_key.rb
index 7f9a11394a..1e6b9fcb6c 100644
--- a/test/reline/test_reline_key.rb
+++ b/test/reline/test_reline_key.rb
@@ -2,53 +2,10 @@ require_relative 'helper'
require "reline"
class Reline::TestKey < Reline::TestCase
- def setup
- Reline.test_mode
- end
-
- def teardown
- Reline.test_reset
- end
-
- def test_match_key
- assert(Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 2, false)))
- assert(Reline::Key.new(1, 2, false).match?(Reline::Key.new(nil, 2, false)))
- assert(Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 2, nil)))
-
- assert(Reline::Key.new(nil, 2, false).match?(Reline::Key.new(nil, 2, false)))
- assert(Reline::Key.new(1, nil, false).match?(Reline::Key.new(1, nil, false)))
- assert(Reline::Key.new(1, 2, nil).match?(Reline::Key.new(1, 2, nil)))
-
- assert(Reline::Key.new(nil, 2, false).match?(Reline::Key.new(nil, 2, false)))
- assert(Reline::Key.new(1, nil, false).match?(Reline::Key.new(1, nil, false)))
- assert(Reline::Key.new(1, 2, nil).match?(Reline::Key.new(1, 2, nil)))
-
- assert(!Reline::Key.new(1, 2, false).match?(Reline::Key.new(3, 1, false)))
- assert(!Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 3, false)))
- assert(!Reline::Key.new(1, 2, false).match?(Reline::Key.new(1, 3, true)))
- end
-
- def test_match_integer
- assert(Reline::Key.new(1, 2, false).match?(2))
- assert(Reline::Key.new(nil, 2, false).match?(2))
- assert(Reline::Key.new(1, nil, false).match?(1))
-
- assert(!Reline::Key.new(1, 2, false).match?(1))
- assert(!Reline::Key.new(1, nil, false).match?(2))
- assert(!Reline::Key.new(nil, nil, false).match?(1))
- end
-
def test_match_symbol
- assert(Reline::Key.new(:key1, :key2, false).match?(:key2))
- assert(Reline::Key.new(:key1, nil, false).match?(:key1))
-
- assert(!Reline::Key.new(:key1, :key2, false).match?(:key1))
- assert(!Reline::Key.new(:key1, nil, false).match?(:key2))
- assert(!Reline::Key.new(nil, nil, false).match?(:key1))
- end
-
- def test_match_other
- assert(!Reline::Key.new(:key1, 2, false).match?("key1"))
- assert(!Reline::Key.new(nil, nil, false).match?(nil))
+ assert(Reline::Key.new(:key1, :key1, false).match?(:key1))
+ refute(Reline::Key.new(:key1, :key1, false).match?(:key2))
+ refute(Reline::Key.new(:key1, :key1, false).match?(nil))
+ refute(Reline::Key.new(1, 1, false).match?(:key1))
end
end