summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomoya ishida <[email protected]>2023-07-19 22:25:54 +0900
committergit <[email protected]>2023-07-19 13:25:58 +0000
commitca561480eaf8aba3d1c7ac70725cb1a726b3a5ba (patch)
treeadda4207c610253af2f15173859379f43a36f55d
parentea2fc58d9ae4da9bf280ce2d4fd87896aa4b693d (diff)
[ruby/reline] Always set ANSI CSI keybindings for Home, End, and
Arrow. (https://github.com/ruby/reline/pull/569) https://github.com/ruby/reline/commit/f363a43a45
-rw-r--r--lib/reline/ansi.rb74
-rw-r--r--test/reline/test_ansi_with_terminfo.rb16
-rw-r--r--test/reline/test_ansi_without_terminfo.rb2
3 files changed, 57 insertions, 35 deletions
diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb
index 1e018d4e82..1570a99c55 100644
--- a/lib/reline/ansi.rb
+++ b/lib/reline/ansi.rb
@@ -14,10 +14,21 @@ class Reline::ANSI
'kcud1' => :ed_next_history,
'kcuf1' => :ed_next_char,
'kcub1' => :ed_prev_char,
- 'cuu' => :ed_prev_history,
- 'cud' => :ed_next_history,
- 'cuf' => :ed_next_char,
- 'cub' => :ed_prev_char,
+ }
+
+ ANSI_CURSOR_KEY_BINDINGS = {
+ # Up
+ 'A' => [:ed_prev_history, {}],
+ # Down
+ 'B' => [:ed_next_history, {}],
+ # Right
+ 'C' => [:ed_next_char, { ctrl: :em_next_word, meta: :em_next_word }],
+ # Left
+ 'D' => [:ed_prev_char, { ctrl: :ed_prev_word, meta: :ed_prev_word }],
+ # End
+ 'F' => [:ed_move_to_end, {}],
+ # Home
+ 'H' => [:ed_move_to_beg, {}],
}
if Reline::Terminfo.enabled?
@@ -33,23 +44,13 @@ class Reline::ANSI
end
def self.set_default_key_bindings(config, allow_terminfo: true)
+ set_default_key_bindings_ansi_cursor(config)
if allow_terminfo && Reline::Terminfo.enabled?
set_default_key_bindings_terminfo(config)
else
set_default_key_bindings_comprehensive_list(config)
end
{
- # extended entries of terminfo
- [27, 91, 49, 59, 53, 67] => :em_next_word, # Ctrl+→, extended entry
- [27, 91, 49, 59, 53, 68] => :ed_prev_word, # Ctrl+←, extended entry
- [27, 91, 49, 59, 51, 67] => :em_next_word, # Meta+→, extended entry
- [27, 91, 49, 59, 51, 68] => :ed_prev_word, # Meta+←, extended entry
- }.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, 91, 90] => :completion_journey_up, # S-Tab
}.each_pair do |key, func|
config.add_default_key_binding_by_keymap(:emacs, key, func)
@@ -64,18 +65,33 @@ class Reline::ANSI
end
end
+ def self.set_default_key_bindings_ansi_cursor(config)
+ ANSI_CURSOR_KEY_BINDINGS.each do |char, (default_func, modifiers)|
+ bindings = [["\e[#{char}", default_func]] # CSI + char
+ if modifiers[:ctrl]
+ # CSI + ctrl_key_modifier + char
+ bindings << ["\e[1;5#{char}", modifiers[:ctrl]]
+ end
+ if modifiers[:meta]
+ # CSI + meta_key_modifier + char
+ bindings << ["\e[1;3#{char}", modifiers[:meta]]
+ # Meta(ESC) + CSI + char
+ bindings << ["\e\e[#{char}", modifiers[:meta]]
+ end
+ bindings.each do |sequence, func|
+ key = sequence.bytes
+ 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
+ end
+ end
+
def self.set_default_key_bindings_terminfo(config)
key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding|
begin
key_code = Reline::Terminfo.tigetstr(capname)
- case capname
- # Escape sequences that omit the move distance and are set to defaults
- # value 1 may be sometimes sent by pressing the arrow-key.
- when 'cuu', 'cud', 'cuf', 'cub'
- [ key_code.sub(/%p1%d/, '').bytes, key_binding ]
- else
- [ key_code.bytes, key_binding ]
- end
+ [ key_code.bytes, key_binding ]
rescue Reline::Terminfo::TerminfoError
# capname is undefined
end
@@ -94,14 +110,8 @@ class Reline::ANSI
[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, # ↓
@@ -118,12 +128,6 @@ class Reline::ANSI
# Del is 0x08
# Arrow keys are the same of KDE
- # iTerm2
- [27, 27, 91, 67] => :em_next_word, # Option+→, extended entry
- [27, 27, 91, 68] => :ed_prev_word, # Option+←, extended entry
- [195, 166] => :em_next_word, # Option+f
- [195, 162] => :ed_prev_word, # Option+b
-
[27, 79, 65] => :ed_prev_history, # ↑
[27, 79, 66] => :ed_next_history, # ↓
[27, 79, 67] => :ed_next_char, # →
diff --git a/test/reline/test_ansi_with_terminfo.rb b/test/reline/test_ansi_with_terminfo.rb
index 1f60f81bd8..1387460659 100644
--- a/test/reline/test_ansi_with_terminfo.rb
+++ b/test/reline/test_ansi_with_terminfo.rb
@@ -75,12 +75,28 @@ class Reline::ANSI::TestWithTerminfo < Reline::TestCase
omit e.message
end
+ # Home and End; always mapped regardless of terminfo enabled or not
+ def test_home_end
+ assert_key_binding("\e[H", :ed_move_to_beg)
+ assert_key_binding("\e[F", :ed_move_to_end)
+ end
+
+ # Arrow; always mapped regardless of terminfo enabled or not
+ def test_arrow
+ assert_key_binding("\e[A", :ed_prev_history)
+ assert_key_binding("\e[B", :ed_next_history)
+ assert_key_binding("\e[C", :ed_next_char)
+ assert_key_binding("\e[D", :ed_prev_char)
+ end
+
# Ctrl+arrow and Meta+arrow; always mapped regardless of terminfo enabled or not
def test_extended
assert_key_binding("\e[1;5C", :em_next_word) # Ctrl+→
assert_key_binding("\e[1;5D", :ed_prev_word) # Ctrl+←
assert_key_binding("\e[1;3C", :em_next_word) # Meta+→
assert_key_binding("\e[1;3D", :ed_prev_word) # Meta+←
+ assert_key_binding("\e\e[C", :em_next_word) # Meta+→
+ assert_key_binding("\e\e[D", :ed_prev_word) # Meta+←
end
# Shift-Tab; always mapped regardless of terminfo enabled or not
diff --git a/test/reline/test_ansi_without_terminfo.rb b/test/reline/test_ansi_without_terminfo.rb
index e3239cf5d8..3d153514f3 100644
--- a/test/reline/test_ansi_without_terminfo.rb
+++ b/test/reline/test_ansi_without_terminfo.rb
@@ -60,6 +60,8 @@ class Reline::ANSI::TestWithoutTerminfo < Reline::TestCase
assert_key_binding("\e[1;5D", :ed_prev_word) # Ctrl+←
assert_key_binding("\e[1;3C", :em_next_word) # Meta+→
assert_key_binding("\e[1;3D", :ed_prev_word) # Meta+←
+ assert_key_binding("\e\e[C", :em_next_word) # Meta+→
+ assert_key_binding("\e\e[D", :ed_prev_word) # Meta+←
end
# Shift-Tab; always mapped regardless of terminfo enabled or not