From 5543695a19faccea325f91c9791d06dc4d29e132 Mon Sep 17 00:00:00 2001 From: aycabta Date: Mon, 5 Apr 2021 16:03:53 +0900 Subject: [PATCH] [ruby/reline] Separate keystrokes each editing mode https://github.com/ruby/reline/commit/ee23e6f3f8 --- lib/reline.rb | 4 +- lib/reline/ansi.rb | 92 ++++++++++++++++++++---------------- lib/reline/config.rb | 25 ++++++---- lib/reline/general_io.rb | 3 +- lib/reline/key_actor/base.rb | 12 +++++ lib/reline/windows.rb | 46 +++++++++++------- test/reline/test_config.rb | 15 ++++++ 7 files changed, 128 insertions(+), 69 deletions(-) diff --git a/lib/reline.rb b/lib/reline.rb index a7bd4d9280..6fc27caecd 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -231,9 +231,7 @@ module Reline unless config.test_mode config.read config.reset_default_key_bindings - Reline::IOGate::RAW_KEYSTROKE_CONFIG.each_pair do |key, func| - config.add_default_key_binding(key, func) - end + Reline::IOGate.set_default_key_bindings(config) end line_editor.rerender diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb index b2d7e7d910..f8e82c199d 100644 --- a/lib/reline/ansi.rb +++ b/lib/reline/ansi.rb @@ -10,52 +10,64 @@ class Reline::ANSI false end - RAW_KEYSTROKE_CONFIG = { - # Console (80x25) - [27, 91, 49, 126] => :ed_move_to_beg, # Home - [27, 91, 52, 126] => :ed_move_to_end, # End - [27, 91, 51, 126] => :key_delete, # Del - [27, 91, 65] => :ed_prev_history, # ↑ - [27, 91, 66] => :ed_next_history, # ↓ - [27, 91, 67] => :ed_next_char, # → - [27, 91, 68] => :ed_prev_char, # ← + def self.set_default_key_bindings(config) + { + # Console (80x25) + [27, 91, 49, 126] => :ed_move_to_beg, # Home + [27, 91, 52, 126] => :ed_move_to_end, # End + [27, 91, 51, 126] => :key_delete, # Del + [27, 91, 65] => :ed_prev_history, # ↑ + [27, 91, 66] => :ed_next_history, # ↓ + [27, 91, 67] => :ed_next_char, # → + [27, 91, 68] => :ed_prev_char, # ← - # KDE - [27, 91, 72] => :ed_move_to_beg, # Home - [27, 91, 70] => :ed_move_to_end, # End - # Del is 0x08 - [27, 71, 65] => :ed_prev_history, # ↑ - [27, 71, 66] => :ed_next_history, # ↓ - [27, 71, 67] => :ed_next_char, # → - [27, 71, 68] => :ed_prev_char, # ← + # KDE + [27, 91, 72] => :ed_move_to_beg, # Home + [27, 91, 70] => :ed_move_to_end, # End + # Del is 0x08 + [27, 71, 65] => :ed_prev_history, # ↑ + [27, 71, 66] => :ed_next_history, # ↓ + [27, 71, 67] => :ed_next_char, # → + [27, 71, 68] => :ed_prev_char, # ← - # urxvt / exoterm - [27, 91, 55, 126] => :ed_move_to_beg, # Home - [27, 91, 56, 126] => :ed_move_to_end, # End + # urxvt / exoterm + [27, 91, 55, 126] => :ed_move_to_beg, # Home + [27, 91, 56, 126] => :ed_move_to_end, # End - # GNOME - [27, 79, 72] => :ed_move_to_beg, # Home - [27, 79, 70] => :ed_move_to_end, # End - # Del is 0x08 - # Arrow keys are the same of KDE + # GNOME + [27, 79, 72] => :ed_move_to_beg, # Home + [27, 79, 70] => :ed_move_to_end, # End + # Del is 0x08 + # Arrow keys are the same of KDE - # iTerm2 - [27, 27, 91, 67] => :em_next_word, # Option+→ - [27, 27, 91, 68] => :ed_prev_word, # Option+← - [195, 166] => :em_next_word, # Option+f - [195, 162] => :ed_prev_word, # Option+b + # iTerm2 + [27, 27, 91, 67] => :em_next_word, # Option+→ + [27, 27, 91, 68] => :ed_prev_word, # Option+← + [195, 166] => :em_next_word, # Option+f + [195, 162] => :ed_prev_word, # Option+b - # others - [27, 32] => :em_set_mark, # M- - [24, 24] => :em_exchange_mark, # C-x C-x TODO also add Windows - [27, 91, 49, 59, 53, 67] => :em_next_word, # Ctrl+→ - [27, 91, 49, 59, 53, 68] => :ed_prev_word, # Ctrl+← + # others + [27, 91, 49, 59, 53, 67] => :em_next_word, # Ctrl+→ + [27, 91, 49, 59, 53, 68] => :ed_prev_word, # Ctrl+← - [27, 79, 65] => :ed_prev_history, # ↑ - [27, 79, 66] => :ed_next_history, # ↓ - [27, 79, 67] => :ed_next_char, # → - [27, 79, 68] => :ed_prev_char, # ← - } + [27, 79, 65] => :ed_prev_history, # ↑ + [27, 79, 66] => :ed_next_history, # ↓ + [27, 79, 67] => :ed_next_char, # → + [27, 79, 68] => :ed_prev_char, # ← + }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + config.add_default_key_binding_by_keymap(:vi_insert, key, func) + config.add_default_key_binding_by_keymap(:vi_command, key, func) + end + + { + # others + [27, 32] => :em_set_mark, # M- + [24, 24] => :em_exchange_mark, # C-x C-x TODO also add Windows + }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + end + end @@input = STDIN def self.input=(val) diff --git a/lib/reline/config.rb b/lib/reline/config.rb index 63ab7b7402..f916fc63ff 100644 --- a/lib/reline/config.rb +++ b/lib/reline/config.rb @@ -47,7 +47,9 @@ class Reline::Config def initialize @additional_key_bindings = {} # from inputrc - @default_key_bindings = {} # environment-dependent + @additional_key_bindings[:emacs] = {} + @additional_key_bindings[:vi_insert] = {} + @additional_key_bindings[:vi_command] = {} @skip_section = nil @if_stack = nil @editing_mode_label = :emacs @@ -69,8 +71,9 @@ class Reline::Config if editing_mode_is?(:vi_command) @editing_mode_label = :vi_insert end - @additional_key_bindings = {} - @default_key_bindings = {} + @additional_key_bindings.keys.each do |key| + @additional_key_bindings[key].clear + end end def editing_mode @@ -135,16 +138,22 @@ class Reline::Config end def key_bindings - # override @default_key_bindings with @additional_key_bindings - @default_key_bindings.merge(@additional_key_bindings) + # override @key_actors[@editing_mode_label].default_key_bindings with @additional_key_bindings[@editing_mode_label] + @key_actors[@editing_mode_label].default_key_bindings.merge(@additional_key_bindings[@editing_mode_label]) + end + + def add_default_key_binding_by_keymap(keymap, keystroke, target) + @key_actors[keymap].default_key_bindings[keystroke] = target end def add_default_key_binding(keystroke, target) - @default_key_bindings[keystroke] = target + @key_actors[@keymap_label].default_key_bindings[keystroke] = target end def reset_default_key_bindings - @default_key_bindings = {} + @key_actors.values.each do |ka| + ka.reset_default_key_bindings + end end def read_lines(lines, file = nil) @@ -174,7 +183,7 @@ class Reline::Config key, func_name = $1, $2 keystroke, func = bind_key(key, func_name) next unless keystroke - @additional_key_bindings[keystroke] = func + @additional_key_bindings[@keymap_label][keystroke] = func end end unless @if_stack.empty? diff --git a/lib/reline/general_io.rb b/lib/reline/general_io.rb index 01a592e038..8c8e22d2e6 100644 --- a/lib/reline/general_io.rb +++ b/lib/reline/general_io.rb @@ -13,7 +13,8 @@ class Reline::GeneralIO false end - RAW_KEYSTROKE_CONFIG = {} + def self.set_default_key_bindings(_) + end @@buf = [] diff --git a/lib/reline/key_actor/base.rb b/lib/reline/key_actor/base.rb index f4abac55d4..a1cd7fb2a1 100644 --- a/lib/reline/key_actor/base.rb +++ b/lib/reline/key_actor/base.rb @@ -4,4 +4,16 @@ class Reline::KeyActor::Base def get_method(key) self.class::MAPPING[key] end + + def initialize + @default_key_bindings = {} + end + + def default_key_bindings + @default_key_bindings + end + + def reset_default_key_bindings + @default_key_bindings.clear + end end diff --git a/lib/reline/windows.rb b/lib/reline/windows.rb index 6edc68e780..c645458cfc 100644 --- a/lib/reline/windows.rb +++ b/lib/reline/windows.rb @@ -13,23 +13,35 @@ class Reline::Windows @@legacy_console end - RAW_KEYSTROKE_CONFIG = { - [224, 72] => :ed_prev_history, # ↑ - [224, 80] => :ed_next_history, # ↓ - [224, 77] => :ed_next_char, # → - [224, 75] => :ed_prev_char, # ← - [224, 83] => :key_delete, # Del - [224, 71] => :ed_move_to_beg, # Home - [224, 79] => :ed_move_to_end, # End - [ 0, 41] => :ed_unassigned, # input method on/off - [ 0, 72] => :ed_prev_history, # ↑ - [ 0, 80] => :ed_next_history, # ↓ - [ 0, 77] => :ed_next_char, # → - [ 0, 75] => :ed_prev_char, # ← - [ 0, 83] => :key_delete, # Del - [ 0, 71] => :ed_move_to_beg, # Home - [ 0, 79] => :ed_move_to_end # End - } + def self.set_default_key_bindings(config) + { + [224, 72] => :ed_prev_history, # ↑ + [224, 80] => :ed_next_history, # ↓ + [224, 77] => :ed_next_char, # → + [224, 75] => :ed_prev_char, # ← + [224, 83] => :key_delete, # Del + [224, 71] => :ed_move_to_beg, # Home + [224, 79] => :ed_move_to_end, # End + [ 0, 41] => :ed_unassigned, # input method on/off + [ 0, 72] => :ed_prev_history, # ↑ + [ 0, 80] => :ed_next_history, # ↓ + [ 0, 77] => :ed_next_char, # → + [ 0, 75] => :ed_prev_char, # ← + [ 0, 83] => :key_delete, # Del + [ 0, 71] => :ed_move_to_beg, # Home + [ 0, 79] => :ed_move_to_end # End + }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + config.add_default_key_binding_by_keymap(:vi_insert, key, func) + config.add_default_key_binding_by_keymap(:vi_command, key, func) + end + + { + [27, 32] => :em_set_mark, # M- + }.each_pair do |key, func| + config.add_default_key_binding_by_keymap(:emacs, key, func) + end + end if defined? JRUBY_VERSION require 'win32api' diff --git a/test/reline/test_config.rb b/test/reline/test_config.rb index c1455cd136..2cca0e71f7 100644 --- a/test/reline/test_config.rb +++ b/test/reline/test_config.rb @@ -241,6 +241,21 @@ class Reline::Config::Test < Reline::TestCase assert_equal expected, @config.key_bindings end + def test_additional_key_bindings_for_other_keymap + @config.read_lines(<<~'LINES'.lines) + set keymap vi-command + "ab": "AB" + set keymap vi-insert + "cd": "CD" + set keymap emacs + "ef": "EF" + set editing-mode vi # keymap changes to be vi-insert + LINES + + expected = { 'cd'.bytes => 'CD'.bytes } + assert_equal expected, @config.key_bindings + end + def test_history_size @config.read_lines(<<~LINES.lines) set history-size 5000