aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/term.txt12
-rw-r--r--test/functional/terminal/tui_spec.lua174
2 files changed, 183 insertions, 3 deletions
diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt
index 9969fc0a79..cd6798a5de 100644
--- a/runtime/doc/term.txt
+++ b/runtime/doc/term.txt
@@ -111,11 +111,17 @@ width of the terminal.
*tui-input*
Nvim uses libtermkey to convert terminal escape sequences to key codes.
|terminfo| is used first, and CSI sequences not in |terminfo| (including
-extended keys a.k.a. modifyOtherKeys or `CSI u`) can also be parsed.
+extended keys a.k.a. modifyOtherKeys or "CSI u") can also be parsed.
For example, when running Nvim in tmux, this makes Nvim leave Insert mode and
go to the window below: >
- tmux send-keys 'Escape' [ 2 7 u 'C-W' j
-Where `'Escape' [ 2 7 u` is an unambiguous `CSI u` sequence for the <Esc> key.
+ tmux send-keys 'Escape' [ 2 7 u 'C-W' j
+Where `'Escape' [ 2 7 u` is an unambiguous "CSI u" sequence for the <Esc> key.
+
+The kitty keyboard protocol https://sw.kovidgoyal.net/kitty/keyboard-protocol/
+is partially supported, including keypad keys in Unicode Private Use Area.
+For example, this sequence is recognized by Nvim as <C-kEnter>: >
+ CSI 57414 ; 5 u
+and can be used differently from <C-CR> in mappings.
*tui-modifyOtherKeys* *tui-csiu*
Historically, terminal emulators could not distinguish between certain control
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 89704be820..1a11f6fc60 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -20,6 +20,7 @@ local nvim_prog = helpers.nvim_prog
local nvim_set = helpers.nvim_set
local ok = helpers.ok
local read_file = helpers.read_file
+local funcs = helpers.funcs
if helpers.pending_win32(pending) then return end
@@ -279,6 +280,179 @@ describe('TUI', function()
]], attrs)
end)
+ it('accepts keypad keys from kitty keyboard protocol #19180', function()
+ feed_data('i')
+ feed_data(funcs.nr2char(57399)) -- KP_0
+ feed_data(funcs.nr2char(57400)) -- KP_1
+ feed_data(funcs.nr2char(57401)) -- KP_2
+ feed_data(funcs.nr2char(57402)) -- KP_3
+ feed_data(funcs.nr2char(57403)) -- KP_4
+ feed_data(funcs.nr2char(57404)) -- KP_5
+ feed_data(funcs.nr2char(57405)) -- KP_6
+ feed_data(funcs.nr2char(57406)) -- KP_7
+ feed_data(funcs.nr2char(57407)) -- KP_8
+ feed_data(funcs.nr2char(57408)) -- KP_9
+ feed_data(funcs.nr2char(57409)) -- KP_DECIMAL
+ feed_data(funcs.nr2char(57410)) -- KP_DIVIDE
+ feed_data(funcs.nr2char(57411)) -- KP_MULTIPLY
+ feed_data(funcs.nr2char(57412)) -- KP_SUBTRACT
+ feed_data(funcs.nr2char(57413)) -- KP_ADD
+ feed_data(funcs.nr2char(57414)) -- KP_ENTER
+ feed_data(funcs.nr2char(57415)) -- KP_EQUAL
+ screen:expect([[
+ 0123456789./*-+ |
+ ={1: } |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ {3:-- INSERT --} |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data(funcs.nr2char(57417)) -- KP_LEFT
+ screen:expect([[
+ 0123456789./*-+ |
+ {1:=} |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ {3:-- INSERT --} |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data(funcs.nr2char(57418)) -- KP_RIGHT
+ screen:expect([[
+ 0123456789./*-+ |
+ ={1: } |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ {3:-- INSERT --} |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data(funcs.nr2char(57419)) -- KP_UP
+ screen:expect([[
+ 0{1:1}23456789./*-+ |
+ = |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ {3:-- INSERT --} |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data(funcs.nr2char(57420)) -- KP_DOWN
+ screen:expect([[
+ 0123456789./*-+ |
+ ={1: } |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ {3:-- INSERT --} |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data(funcs.nr2char(57425)) -- KP_INSERT
+ screen:expect([[
+ 0123456789./*-+ |
+ ={1: } |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ {3:-- REPLACE --} |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data('\027[27u') -- ESC
+ screen:expect([[
+ 0123456789./*-+ |
+ {1:=} |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data('\027[57417;5u') -- CTRL + KP_LEFT
+ screen:expect([[
+ {1:0}123456789./*-+ |
+ = |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data('\027[57418;2u') -- SHIFT + KP_RIGHT
+ screen:expect([[
+ 0123456789{1:.}/*-+ |
+ = |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data(funcs.nr2char(57426)) -- KP_DELETE
+ screen:expect([[
+ 0123456789{1:/}*-+ |
+ = |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data(funcs.nr2char(57423)) -- KP_HOME
+ screen:expect([[
+ {1:0}123456789/*-+ |
+ = |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data(funcs.nr2char(57424)) -- KP_END
+ screen:expect([[
+ 0123456789/*-{1:+} |
+ = |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ feed_data(':tab split\r:tabnew\r')
+ feed_data(':highlight Tabline ctermbg=NONE ctermfg=NONE cterm=underline\r')
+ local attrs = screen:get_default_attr_ids()
+ attrs[11] = {underline = true}
+ screen:expect([[
+ {11: + [No Name] + [No Name] }{3: [No Name] }{1: }{11:X}|
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] }|
+ |
+ {3:-- TERMINAL --} |
+ ]], attrs)
+ feed_data('\027[57421;5u') -- CTRL + KP_PAGE_UP
+ screen:expect([[
+ {11: + [No Name] }{3: + [No Name] }{11: [No Name] }{1: }{11:X}|
+ 0123456789/*-{1:+} |
+ = |
+ {4:~ }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]], attrs)
+ feed_data('\027[57422;5u') -- CTRL + KP_PAGE_DOWN
+ screen:expect([[
+ {11: + [No Name] + [No Name] }{3: [No Name] }{1: }{11:X}|
+ {1: } |
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] }|
+ |
+ {3:-- TERMINAL --} |
+ ]], attrs)
+ end)
+
it('paste: Insert mode', function()
-- "bracketed paste"
feed_data('i""\027i\027[200~')