Mercurial > vim
view src/testdir/keycode_check.vim @ 31105:46d1a434784b v9.0.0887
patch 9.0.0887: cannot easily try out what codes various keys produce
Commit: https://github.com/vim/vim/commit/a44c7811ff1c5519ac9acd6a34c58c98366f5c5f
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Nov 15 22:59:07 2022 +0000
patch 9.0.0887: cannot easily try out what codes various keys produce
Problem: Cannot easily try out what codes various keys produce.
Solution: Add a script to gather key code information, with an initial list
of codes to compare with.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 16 Nov 2022 00:00:04 +0100 |
parents | |
children | 17e171cf2cca |
line wrap: on
line source
vim9script # Script to get various codes that keys send, depending on the protocol used. # # Usage: vim -u keycode_check.vim # # Author: Bram Moolenaar # Last Update: 2022 Nov 15 # # The codes are stored in the file "keycode_check.json", so that you can # compare the results of various terminals. # # You can select what protocol to enable: # - None # - modifyOtherKeys level 2 # - kitty keyboard protocol # Change directory to where this script is, so that the json file is found # there. exe 'cd ' .. expand('<sfile>:h') echo 'working in directory: ' .. getcwd() const filename = 'keycode_check.json' # Dictionary of dictionaries with the results in the form: # {'xterm': {protocol: 'none', 'Tab': '09', 'S-Tab': '09'}, # 'xterm2': {protocol: 'mok2', 'Tab': '09', 'S-Tab': '09'}, # 'kitty': {protocol: 'kitty', 'Tab': '09', 'S-Tab': '09'}, # } # The values are in hex form. var keycodes = {} if filereadable(filename) keycodes = readfile(filename)->join()->json_decode() else # Use some dummy entries to try out with keycodes = { 'xterm': {protocol: 'none', 'Tab': '09', 'S-Tab': '09'}, 'kitty': {protocol: 'kitty', 'Tab': '09', 'S-Tab': '1b5b393b3275'}, } endif var orig_keycodes = deepcopy(keycodes) # used to detect something changed # Write the "keycodes" variable in JSON form to "filename". def WriteKeycodes() # If the file already exists move it to become the backup file. if filereadable(filename) if rename(filename, filename .. '~') echoerr $'Renaming {filename} to {filename}~ failed!' return endif endif if writefile([json_encode(keycodes)], filename) != 0 echoerr $'Writing {filename} failed!' endif enddef # The key entries that we want to list, in this order. # The first item is displayed in the prompt, the second is the key in # the keycodes dictionary. var key_entries = [ ['Tab', 'Tab'], ['Shift-Tab', 'S-Tab'], ['Ctrl-Tab', 'C-Tab'], ['Alt-Tab', 'A-Tab'], ['Ctrl-I', 'C-I'], ['Shift-Ctrl-I', 'S-C-I'], ['Esc', 'Esc'], ['Shift-Esc', 'S-Esc'], ['Ctrl-Esc', 'C-Esc'], ['Alt-Esc', 'A-Esc'], ['Space', 'Space'], ['Shift-Space', 'S-Space'], ['Ctrl-Space', 'C-Space'], ['Alt-Space', 'A-Space'], ] # Action: list the information in "keycodes" in a more or less nice way. def ActionList() var terms = keys(keycodes) if len(terms) == 0 echo 'No terminal results yet' return endif # Use one column of width 10 for the item name, then columns of 20 # characters to fit most codes. You will need to increase the terminal # width to avoid wrapping. echon printf(' ') for term in terms echon printf('%-20s', term) endfor echo "\n" var items = ['protocol'] + key_entries->copy()->map((_, v) => v[1]) for item in items echon printf('%8s ', item) for term in terms var val = get(keycodes[term], item, '') # see if we can pretty-print this one var pretty = val if val[0 : 1] == '1b' pretty = 'ESC' var idx = 2 if val[0 : 3] == '1b5b' pretty = 'CSI' idx = 4 endif var digits = false while idx < len(val) var cc = val[idx : idx + 1] var nr = str2nr('0x' .. cc, 16) idx += 2 if nr >= char2nr('0') && nr <= char2nr('9') if !digits pretty ..= ' ' endif digits = true pretty ..= cc[1] else digits = false if nr >= char2nr(' ') && nr <= char2nr('~') # printable character pretty ..= ' ' .. printf('%c', nr) else # non-printable, use hex code pretty = val break endif endif endwhile endif echon printf('%-20s', pretty) endfor echo '' endfor echo "\n" enddef def GetTermName(): string var name = input('Enter the name of the terminal: ') return name enddef # Gather key codes for terminal "name". def DoTerm(name: string) var proto = inputlist([$'What protocol to enable for {name}:', '1. None', '2. modifyOtherKeys level 2', '3. kitty', ]) echo "\n" &t_TE = "\<Esc>[>4;m" var proto_name = 'none' if proto == 1 &t_TI = "" elseif proto == 2 &t_TI = "\<Esc>[>4;2m" proto_name = 'mok2' elseif proto == 3 &t_TI = "\<Esc>[>1u" proto_name = 'kitty' else echoerr 'invalid protocol choice' return endif # executing a dummy shell command will output t_TI !echo >/dev/null if !has_key(keycodes, name) keycodes[name] = {} endif keycodes[name]['protocol'] = proto_name echo "When a key press doesn't get to Vim (e.g. when using Alt) press Space" for entry in key_entries ch_logfile('keylog', 'w') echo $'Press the {entry[0]} key (q to quit):' var r = getcharstr() ch_logfile('', '') if r == 'q' break endif var log = readfile('keylog') delete('keylog') if len(log) < 2 echoerr 'failed to read result' return endif var done = false for line in log if line =~ 'raw key input' var code = substitute(line, '.*raw key input: "\([^"]*\).*', '\1', '') # convert the literal bytes into hex var hex = '' for i in range(len(code)) hex ..= printf('%02x', char2nr(code[i])) endfor keycodes[name][entry[1]] = hex done = true break endif endfor if !done echo 'Code not found in log' endif endfor enddef # Action: Add key codes for a new terminal. def ActionAdd() var name = input('Enter name of the terminal: ') echo "\n" if index(keys(keycodes), name) >= 0 echoerr $'Terminal {name} already exists' return endif DoTerm(name) enddef # Action: Replace key codes for an already known terminal. def ActionReplace() var terms = keys(keycodes) if len(terms) == 0 echo 'No terminal results yet' return endif var choice = inputlist(['Select:'] + terms->copy()->map((idx, arg) => (idx + 1) .. ': ' .. arg)) echo "\n" if choice > 0 && choice <= len(terms) DoTerm(terms[choice - 1]) endif echo 'invalid index' enddef # Action: Quit, possibly after saving the results first. def ActionQuit() # If nothing was changed just quit if keycodes == orig_keycodes quit endif while true var res = input("Save the changed key codes (y/n)? ") if res == 'n' quit endif if res == 'y' WriteKeycodes() quit endif echo 'invalid reply' endwhile enddef # The main loop while true var action = inputlist(['Select operation:', '1. List results', '2. Add results for a new terminal', '3. Replace results', '4. Quit', ]) echo "\n" if action == 1 ActionList() elseif action == 2 ActionAdd() elseif action == 3 ActionReplace() elseif action == 4 ActionQuit() endif endwhile