okami.mom/ultraviolet
git clone https://git.nkp.pet/okami.mom/ultraviolet
b3a6f4b
main
1package uv 2 3import ( 4"strconv" 5"strings" 6 7"github.com/charmbracelet/x/ansi" 8"github.com/xo/terminfo" 9) 10 11// buildKeysTable builds a table of key sequences and their corresponding key 12// events based on the VT100/VT200, XTerm, and Urxvt terminal specs. 13func buildKeysTable (flags LegacyKeyEncoding ,term string ,useTerminfo bool )map [string ]Key { 14nul := Key {Code :KeySpace ,Mod :ModCtrl }// ctrl+@ or ctrl+space 15if flags & flagCtrlAt != 0 { 16nul = Key {Code :'@' ,Mod :ModCtrl } 17 } 18 19tab := Key {Code :KeyTab }// ctrl+i or tab 20if flags & flagCtrlI != 0 { 21tab = Key {Code :'i' ,Mod :ModCtrl } 22 } 23 24enter := Key {Code :KeyEnter }// ctrl+m or enter 25if flags & flagCtrlM != 0 { 26enter = Key {Code :'m' ,Mod :ModCtrl } 27 } 28 29esc := Key {Code :KeyEscape }// ctrl+[ or escape 30if flags & flagCtrlOpenBracket != 0 { 31esc = Key {Code :'[' ,Mod :ModCtrl }// ctrl+[ or escape 32 } 33 34del := Key {Code :KeyBackspace } 35if flags & flagBackspace != 0 { 36del .Code = KeyDelete 37 } 38 39find := Key {Code :KeyHome } 40if flags & flagFind != 0 { 41find .Code = KeyFind 42 } 43 44sel := Key {Code :KeyEnd } 45if flags & flagSelect != 0 { 46sel .Code = KeySelect 47 } 48 49// The following is a table of key sequences and their corresponding key 50// events based on the VT100/VT200 terminal specs. 51// 52// See: https://vt100.net/docs/vt100-ug/chapter3.html#S3.2 53// See: https://vt100.net/docs/vt220-rm/chapter3.html 54// 55// XXX: These keys may be overwritten by other options like XTerm or 56// Terminfo. 57table := map [string ]Key { 58// C0 control characters 59string (byte (ansi .NUL )):nul , 60string (byte (ansi .SOH )): {Code :'a' ,Mod :ModCtrl }, 61string (byte (ansi .STX )): {Code :'b' ,Mod :ModCtrl }, 62string (byte (ansi .ETX )): {Code :'c' ,Mod :ModCtrl }, 63string (byte (ansi .EOT )): {Code :'d' ,Mod :ModCtrl }, 64string (byte (ansi .ENQ )): {Code :'e' ,Mod :ModCtrl }, 65string (byte (ansi .ACK )): {Code :'f' ,Mod :ModCtrl }, 66string (byte (ansi .BEL )): {Code :'g' ,Mod :ModCtrl }, 67string (byte (ansi .BS )): {Code :'h' ,Mod :ModCtrl }, 68string (byte (ansi .HT )):tab , 69string (byte (ansi .LF )): {Code :'j' ,Mod :ModCtrl }, 70string (byte (ansi .VT )): {Code :'k' ,Mod :ModCtrl }, 71string (byte (ansi .FF )): {Code :'l' ,Mod :ModCtrl }, 72string (byte (ansi .CR )):enter , 73string (byte (ansi .SO )): {Code :'n' ,Mod :ModCtrl }, 74string (byte (ansi .SI )): {Code :'o' ,Mod :ModCtrl }, 75string (byte (ansi .DLE )): {Code :'p' ,Mod :ModCtrl }, 76string (byte (ansi .DC1 )): {Code :'q' ,Mod :ModCtrl }, 77string (byte (ansi .DC2 )): {Code :'r' ,Mod :ModCtrl }, 78string (byte (ansi .DC3 )): {Code :'s' ,Mod :ModCtrl }, 79string (byte (ansi .DC4 )): {Code :'t' ,Mod :ModCtrl }, 80string (byte (ansi .NAK )): {Code :'u' ,Mod :ModCtrl }, 81string (byte (ansi .SYN )): {Code :'v' ,Mod :ModCtrl }, 82string (byte (ansi .ETB )): {Code :'w' ,Mod :ModCtrl }, 83string (byte (ansi .CAN )): {Code :'x' ,Mod :ModCtrl }, 84string (byte (ansi .EM )): {Code :'y' ,Mod :ModCtrl }, 85string (byte (ansi .SUB )): {Code :'z' ,Mod :ModCtrl }, 86string (byte (ansi .ESC )):esc , 87string (byte (ansi .FS )): {Code :'\\' ,Mod :ModCtrl }, 88string (byte (ansi .GS )): {Code :']' ,Mod :ModCtrl }, 89string (byte (ansi .RS )): {Code :'^' ,Mod :ModCtrl }, 90string (byte (ansi .US )): {Code :'_' ,Mod :ModCtrl }, 91 92// Special keys in G0 93string (byte (ansi .SP )): {Code :KeySpace ,Text :" " }, 94string (byte (ansi .DEL )):del , 95 96// Special keys 97 98"\x1b[Z" : {Code :KeyTab ,Mod :ModShift }, 99 100"\x1b[1~" :find , 101"\x1b[2~" : {Code :KeyInsert }, 102"\x1b[3~" : {Code :KeyDelete }, 103"\x1b[4~" :sel , 104"\x1b[5~" : {Code :KeyPgUp }, 105"\x1b[6~" : {Code :KeyPgDown }, 106"\x1b[7~" : {Code :KeyHome }, 107"\x1b[8~" : {Code :KeyEnd }, 108 109// Normal mode 110"\x1b[A" : {Code :KeyUp }, 111"\x1b[B" : {Code :KeyDown }, 112"\x1b[C" : {Code :KeyRight }, 113"\x1b[D" : {Code :KeyLeft }, 114"\x1b[E" : {Code :KeyBegin }, 115"\x1b[F" : {Code :KeyEnd }, 116"\x1b[H" : {Code :KeyHome }, 117"\x1b[P" : {Code :KeyF1 }, 118"\x1b[Q" : {Code :KeyF2 }, 119"\x1b[R" : {Code :KeyF3 }, 120"\x1b[S" : {Code :KeyF4 }, 121 122// Application Cursor Key Mode (DECCKM) 123"\x1bOA" : {Code :KeyUp }, 124"\x1bOB" : {Code :KeyDown }, 125"\x1bOC" : {Code :KeyRight }, 126"\x1bOD" : {Code :KeyLeft }, 127"\x1bOE" : {Code :KeyBegin }, 128"\x1bOF" : {Code :KeyEnd }, 129"\x1bOH" : {Code :KeyHome }, 130"\x1bOP" : {Code :KeyF1 }, 131"\x1bOQ" : {Code :KeyF2 }, 132"\x1bOR" : {Code :KeyF3 }, 133"\x1bOS" : {Code :KeyF4 }, 134 135// Keypad Application Mode (DECKPAM) 136 137"\x1bOM" : {Code :KeyKpEnter }, 138"\x1bOX" : {Code :KeyKpEqual }, 139"\x1bOj" : {Code :KeyKpMultiply }, 140"\x1bOk" : {Code :KeyKpPlus }, 141"\x1bOl" : {Code :KeyKpComma }, 142"\x1bOm" : {Code :KeyKpMinus }, 143"\x1bOn" : {Code :KeyKpDecimal }, 144"\x1bOo" : {Code :KeyKpDivide }, 145"\x1bOp" : {Code :KeyKp0 }, 146"\x1bOq" : {Code :KeyKp1 }, 147"\x1bOr" : {Code :KeyKp2 }, 148"\x1bOs" : {Code :KeyKp3 }, 149"\x1bOt" : {Code :KeyKp4 }, 150"\x1bOu" : {Code :KeyKp5 }, 151"\x1bOv" : {Code :KeyKp6 }, 152"\x1bOw" : {Code :KeyKp7 }, 153"\x1bOx" : {Code :KeyKp8 }, 154"\x1bOy" : {Code :KeyKp9 }, 155 156// Function keys 157 158"\x1b[11~" : {Code :KeyF1 }, 159"\x1b[12~" : {Code :KeyF2 }, 160"\x1b[13~" : {Code :KeyF3 }, 161"\x1b[14~" : {Code :KeyF4 }, 162"\x1b[15~" : {Code :KeyF5 }, 163"\x1b[17~" : {Code :KeyF6 }, 164"\x1b[18~" : {Code :KeyF7 }, 165"\x1b[19~" : {Code :KeyF8 }, 166"\x1b[20~" : {Code :KeyF9 }, 167"\x1b[21~" : {Code :KeyF10 }, 168"\x1b[23~" : {Code :KeyF11 }, 169"\x1b[24~" : {Code :KeyF12 }, 170"\x1b[25~" : {Code :KeyF13 }, 171"\x1b[26~" : {Code :KeyF14 }, 172"\x1b[28~" : {Code :KeyF15 }, 173"\x1b[29~" : {Code :KeyF16 }, 174"\x1b[31~" : {Code :KeyF17 }, 175"\x1b[32~" : {Code :KeyF18 }, 176"\x1b[33~" : {Code :KeyF19 }, 177"\x1b[34~" : {Code :KeyF20 }, 178 } 179 180// CSI ~ sequence keys 181csiTildeKeys := map [string ]Key { 182"1" :find ,"2" : {Code :KeyInsert }, 183"3" : {Code :KeyDelete },"4" :sel , 184"5" : {Code :KeyPgUp },"6" : {Code :KeyPgDown }, 185"7" : {Code :KeyHome },"8" : {Code :KeyEnd }, 186// There are no 9 and 10 keys 187"11" : {Code :KeyF1 },"12" : {Code :KeyF2 }, 188"13" : {Code :KeyF3 },"14" : {Code :KeyF4 }, 189"15" : {Code :KeyF5 },"17" : {Code :KeyF6 }, 190"18" : {Code :KeyF7 },"19" : {Code :KeyF8 }, 191"20" : {Code :KeyF9 },"21" : {Code :KeyF10 }, 192"23" : {Code :KeyF11 },"24" : {Code :KeyF12 }, 193"25" : {Code :KeyF13 },"26" : {Code :KeyF14 }, 194"28" : {Code :KeyF15 },"29" : {Code :KeyF16 }, 195"31" : {Code :KeyF17 },"32" : {Code :KeyF18 }, 196"33" : {Code :KeyF19 },"34" : {Code :KeyF20 }, 197 } 198 199// URxvt keys 200// See https://manpages.ubuntu.com/manpages/trusty/man7/urxvt.7.html#key%20codes 201table ["\x1b[a" ]= Key {Code :KeyUp ,Mod :ModShift } 202table ["\x1b[b" ]= Key {Code :KeyDown ,Mod :ModShift } 203table ["\x1b[c" ]= Key {Code :KeyRight ,Mod :ModShift } 204table ["\x1b[d" ]= Key {Code :KeyLeft ,Mod :ModShift } 205table ["\x1bOa" ]= Key {Code :KeyUp ,Mod :ModCtrl } 206table ["\x1bOb" ]= Key {Code :KeyDown ,Mod :ModCtrl } 207table ["\x1bOc" ]= Key {Code :KeyRight ,Mod :ModCtrl } 208table ["\x1bOd" ]= Key {Code :KeyLeft ,Mod :ModCtrl } 209//nolint:godox 210// TODO: invistigate if shift-ctrl arrow keys collide with DECCKM keys i.e. 211// "\x1bOA", "\x1bOB", "\x1bOC", "\x1bOD" 212 213// URxvt modifier CSI ~ keys 214for k ,v := range csiTildeKeys { 215key := v 216// Normal (no modifier) already defined part of VT100/VT200 217// Shift modifier 218key .Mod = ModShift 219table ["\x1b[" + k + "$" ]= key 220// Ctrl modifier 221key .Mod = ModCtrl 222table ["\x1b[" + k + "^" ]= key 223// Shift-Ctrl modifier 224key .Mod = ModShift | ModCtrl 225table ["\x1b[" + k + "@" ]= key 226 } 227 228// URxvt F keys 229// Note: Shift + F1-F10 generates F11-F20. 230// This means Shift + F1 and Shift + F2 will generate F11 and F12, the same 231// applies to Ctrl + Shift F1 & F2. 232// 233// P.S. Don't like this? Blame URxvt, configure your terminal to use 234// different escapes like XTerm, or switch to a better terminal ¯\_(ツ)_/¯ 235// 236// See https://manpages.ubuntu.com/manpages/trusty/man7/urxvt.7.html#key%20codes 237table ["\x1b[23$" ]= Key {Code :KeyF11 ,Mod :ModShift } 238table ["\x1b[24$" ]= Key {Code :KeyF12 ,Mod :ModShift } 239table ["\x1b[25$" ]= Key {Code :KeyF13 ,Mod :ModShift } 240table ["\x1b[26$" ]= Key {Code :KeyF14 ,Mod :ModShift } 241table ["\x1b[28$" ]= Key {Code :KeyF15 ,Mod :ModShift } 242table ["\x1b[29$" ]= Key {Code :KeyF16 ,Mod :ModShift } 243table ["\x1b[31$" ]= Key {Code :KeyF17 ,Mod :ModShift } 244table ["\x1b[32$" ]= Key {Code :KeyF18 ,Mod :ModShift } 245table ["\x1b[33$" ]= Key {Code :KeyF19 ,Mod :ModShift } 246table ["\x1b[34$" ]= Key {Code :KeyF20 ,Mod :ModShift } 247table ["\x1b[11^" ]= Key {Code :KeyF1 ,Mod :ModCtrl } 248table ["\x1b[12^" ]= Key {Code :KeyF2 ,Mod :ModCtrl } 249table ["\x1b[13^" ]= Key {Code :KeyF3 ,Mod :ModCtrl } 250table ["\x1b[14^" ]= Key {Code :KeyF4 ,Mod :ModCtrl } 251table ["\x1b[15^" ]= Key {Code :KeyF5 ,Mod :ModCtrl } 252table ["\x1b[17^" ]= Key {Code :KeyF6 ,Mod :ModCtrl } 253table ["\x1b[18^" ]= Key {Code :KeyF7 ,Mod :ModCtrl } 254table ["\x1b[19^" ]= Key {Code :KeyF8 ,Mod :ModCtrl } 255table ["\x1b[20^" ]= Key {Code :KeyF9 ,Mod :ModCtrl } 256table ["\x1b[21^" ]= Key {Code :KeyF10 ,Mod :ModCtrl } 257table ["\x1b[23^" ]= Key {Code :KeyF11 ,Mod :ModCtrl } 258table ["\x1b[24^" ]= Key {Code :KeyF12 ,Mod :ModCtrl } 259table ["\x1b[25^" ]= Key {Code :KeyF13 ,Mod :ModCtrl } 260table ["\x1b[26^" ]= Key {Code :KeyF14 ,Mod :ModCtrl } 261table ["\x1b[28^" ]= Key {Code :KeyF15 ,Mod :ModCtrl } 262table ["\x1b[29^" ]= Key {Code :KeyF16 ,Mod :ModCtrl } 263table ["\x1b[31^" ]= Key {Code :KeyF17 ,Mod :ModCtrl } 264table ["\x1b[32^" ]= Key {Code :KeyF18 ,Mod :ModCtrl } 265table ["\x1b[33^" ]= Key {Code :KeyF19 ,Mod :ModCtrl } 266table ["\x1b[34^" ]= Key {Code :KeyF20 ,Mod :ModCtrl } 267table ["\x1b[23@" ]= Key {Code :KeyF11 ,Mod :ModShift | ModCtrl } 268table ["\x1b[24@" ]= Key {Code :KeyF12 ,Mod :ModShift | ModCtrl } 269table ["\x1b[25@" ]= Key {Code :KeyF13 ,Mod :ModShift | ModCtrl } 270table ["\x1b[26@" ]= Key {Code :KeyF14 ,Mod :ModShift | ModCtrl } 271table ["\x1b[28@" ]= Key {Code :KeyF15 ,Mod :ModShift | ModCtrl } 272table ["\x1b[29@" ]= Key {Code :KeyF16 ,Mod :ModShift | ModCtrl } 273table ["\x1b[31@" ]= Key {Code :KeyF17 ,Mod :ModShift | ModCtrl } 274table ["\x1b[32@" ]= Key {Code :KeyF18 ,Mod :ModShift | ModCtrl } 275table ["\x1b[33@" ]= Key {Code :KeyF19 ,Mod :ModShift | ModCtrl } 276table ["\x1b[34@" ]= Key {Code :KeyF20 ,Mod :ModShift | ModCtrl } 277 278// Register Alt + <key> combinations 279// XXX: this must come after URxvt but before XTerm keys to register URxvt 280// keys with alt modifier 281tmap := map [string ]Key {} 282for seq ,key := range table { 283key := key 284key .Mod |= ModAlt 285key .Text = "" // Clear runes 286tmap ["\x1b" + seq ]= key 287 } 288for seq ,key := range tmap { 289table [seq ]= key 290 } 291 292// XTerm modifiers 293// These are offset by 1 to be compatible with our Mod type. 294// See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-PC-Style-Function-Keys 295modifiers := []KeyMod { 296ModShift ,// 1 297ModAlt ,// 2 298ModShift | ModAlt ,// 3 299ModCtrl ,// 4 300ModShift | ModCtrl ,// 5 301ModAlt | ModCtrl ,// 6 302ModShift | ModAlt | ModCtrl ,// 7 303ModMeta ,// 8 304ModMeta | ModShift ,// 9 305ModMeta | ModAlt ,// 10 306ModMeta | ModShift | ModAlt ,// 11 307ModMeta | ModCtrl ,// 12 308ModMeta | ModShift | ModCtrl ,// 13 309ModMeta | ModAlt | ModCtrl ,// 14 310ModMeta | ModShift | ModAlt | ModCtrl ,// 15 311 } 312 313// SS3 keypad function keys 314ss3FuncKeys := map [string ]Key { 315// These are defined in XTerm 316// Taken from Foot keymap.h and XTerm modifyOtherKeys 317// https://codeberg.org/dnkl/foot/src/branch/master/keymap.h 318"M" : {Code :KeyKpEnter },"X" : {Code :KeyKpEqual }, 319"j" : {Code :KeyKpMultiply },"k" : {Code :KeyKpPlus }, 320"l" : {Code :KeyKpComma },"m" : {Code :KeyKpMinus }, 321"n" : {Code :KeyKpDecimal },"o" : {Code :KeyKpDivide }, 322"p" : {Code :KeyKp0 },"q" : {Code :KeyKp1 }, 323"r" : {Code :KeyKp2 },"s" : {Code :KeyKp3 }, 324"t" : {Code :KeyKp4 },"u" : {Code :KeyKp5 }, 325"v" : {Code :KeyKp6 },"w" : {Code :KeyKp7 }, 326"x" : {Code :KeyKp8 },"y" : {Code :KeyKp9 }, 327 } 328 329// XTerm keys 330csiFuncKeys := map [string ]Key { 331"A" : {Code :KeyUp },"B" : {Code :KeyDown }, 332"C" : {Code :KeyRight },"D" : {Code :KeyLeft }, 333"E" : {Code :KeyBegin },"F" : {Code :KeyEnd }, 334"H" : {Code :KeyHome },"P" : {Code :KeyF1 }, 335"Q" : {Code :KeyF2 },"R" : {Code :KeyF3 }, 336"S" : {Code :KeyF4 }, 337 } 338 339// CSI 27 ; <modifier> ; <code> ~ keys defined in XTerm modifyOtherKeys 340modifyOtherKeys := map [int ]Key { 341ansi .BS : {Code :KeyBackspace }, 342ansi .HT : {Code :KeyTab }, 343ansi .CR : {Code :KeyEnter }, 344ansi .ESC : {Code :KeyEscape }, 345ansi .DEL : {Code :KeyBackspace }, 346 } 347 348for _ ,m := range modifiers { 349// XTerm modifier offset +1 350xtermMod := strconv .Itoa (int (m )+ 1 ) 351 352// CSI 1 ; <modifier> <func> 353for k ,v := range csiFuncKeys { 354// Functions always have a leading 1 param 355seq := "\x1b[1;" + xtermMod + k 356key := v 357key .Mod = m 358table [seq ]= key 359 } 360// SS3 <modifier> <func> 361for k ,v := range ss3FuncKeys { 362seq := "\x1bO" + xtermMod + k 363key := v 364key .Mod = m 365table [seq ]= key 366 } 367// CSI <number> ; <modifier> ~ 368for k ,v := range csiTildeKeys { 369seq := "\x1b[" + k + ";" + xtermMod + "~" 370key := v 371key .Mod = m 372table [seq ]= key 373 } 374// CSI 27 ; <modifier> ; <code> ~ 375for k ,v := range modifyOtherKeys { 376code := strconv .Itoa (k ) 377seq := "\x1b[27;" + xtermMod + ";" + code + "~" 378key := v 379key .Mod = m 380table [seq ]= key 381 } 382 } 383 384// Register terminfo keys 385// XXX: this might override keys already registered in table 386if useTerminfo { 387titable := buildTerminfoKeys (flags ,term ) 388for seq ,key := range titable { 389table [seq ]= key 390 } 391 } 392 393return table 394} 395 396func buildTerminfoKeys (flags LegacyKeyEncoding ,term string )map [string ]Key { 397table := make (map [string ]Key ) 398ti ,_ := terminfo .Load (term ) 399if ti == nil { 400return table 401 } 402 403tiTable := defaultTerminfoKeys (flags ) 404 405// Default keys 406for name ,seq := range ti .StringCapsShort () { 407if ! strings .HasPrefix (name ,"k" )|| len (seq )== 0 { 408continue 409 } 410 411if k ,ok := tiTable [name ];ok { 412table [string (seq )]= k 413 } 414 } 415 416// Extended keys 417for name ,seq := range ti .ExtStringCapsShort () { 418if ! strings .HasPrefix (name ,"k" )|| len (seq )== 0 { 419continue 420 } 421 422if k ,ok := tiTable [name ];ok { 423table [string (seq )]= k 424 } 425 } 426 427return table 428} 429 430// This returns a map of terminfo keys to key events. It's a mix of ncurses 431// terminfo default and user-defined key capabilities. 432// Upper-case caps that are defined in the default terminfo database are 433// - kNXT 434// - kPRV 435// - kHOM 436// - kEND 437// - kDC 438// - kIC 439// - kLFT 440// - kRIT 441// 442// See https://man7.org/linux/man-pages/man5/terminfo.5.html 443// See https://github.com/mirror/ncurses/blob/master/include/Caps-ncurses 444func defaultTerminfoKeys (flags LegacyKeyEncoding )map [string ]Key { 445keys := map [string ]Key { 446"kcuu1" : {Code :KeyUp }, 447"kUP" : {Code :KeyUp ,Mod :ModShift }, 448"kUP3" : {Code :KeyUp ,Mod :ModAlt }, 449"kUP4" : {Code :KeyUp ,Mod :ModShift | ModAlt }, 450"kUP5" : {Code :KeyUp ,Mod :ModCtrl }, 451"kUP6" : {Code :KeyUp ,Mod :ModShift | ModCtrl }, 452"kUP7" : {Code :KeyUp ,Mod :ModAlt | ModCtrl }, 453"kUP8" : {Code :KeyUp ,Mod :ModShift | ModAlt | ModCtrl }, 454"kcud1" : {Code :KeyDown }, 455"kDN" : {Code :KeyDown ,Mod :ModShift }, 456"kDN3" : {Code :KeyDown ,Mod :ModAlt }, 457"kDN4" : {Code :KeyDown ,Mod :ModShift | ModAlt }, 458"kDN5" : {Code :KeyDown ,Mod :ModCtrl }, 459"kDN7" : {Code :KeyDown ,Mod :ModAlt | ModCtrl }, 460"kDN6" : {Code :KeyDown ,Mod :ModShift | ModCtrl }, 461"kDN8" : {Code :KeyDown ,Mod :ModShift | ModAlt | ModCtrl }, 462"kcub1" : {Code :KeyLeft }, 463"kLFT" : {Code :KeyLeft ,Mod :ModShift }, 464"kLFT3" : {Code :KeyLeft ,Mod :ModAlt }, 465"kLFT4" : {Code :KeyLeft ,Mod :ModShift | ModAlt }, 466"kLFT5" : {Code :KeyLeft ,Mod :ModCtrl }, 467"kLFT6" : {Code :KeyLeft ,Mod :ModShift | ModCtrl }, 468"kLFT7" : {Code :KeyLeft ,Mod :ModAlt | ModCtrl }, 469"kLFT8" : {Code :KeyLeft ,Mod :ModShift | ModAlt | ModCtrl }, 470"kcuf1" : {Code :KeyRight }, 471"kRIT" : {Code :KeyRight ,Mod :ModShift }, 472"kRIT3" : {Code :KeyRight ,Mod :ModAlt }, 473"kRIT4" : {Code :KeyRight ,Mod :ModShift | ModAlt }, 474"kRIT5" : {Code :KeyRight ,Mod :ModCtrl }, 475"kRIT6" : {Code :KeyRight ,Mod :ModShift | ModCtrl }, 476"kRIT7" : {Code :KeyRight ,Mod :ModAlt | ModCtrl }, 477"kRIT8" : {Code :KeyRight ,Mod :ModShift | ModAlt | ModCtrl }, 478"kich1" : {Code :KeyInsert }, 479"kIC" : {Code :KeyInsert ,Mod :ModShift }, 480"kIC3" : {Code :KeyInsert ,Mod :ModAlt }, 481"kIC4" : {Code :KeyInsert ,Mod :ModShift | ModAlt }, 482"kIC5" : {Code :KeyInsert ,Mod :ModCtrl }, 483"kIC6" : {Code :KeyInsert ,Mod :ModShift | ModCtrl }, 484"kIC7" : {Code :KeyInsert ,Mod :ModAlt | ModCtrl }, 485"kIC8" : {Code :KeyInsert ,Mod :ModShift | ModAlt | ModCtrl }, 486"kdch1" : {Code :KeyDelete }, 487"kDC" : {Code :KeyDelete ,Mod :ModShift }, 488"kDC3" : {Code :KeyDelete ,Mod :ModAlt }, 489"kDC4" : {Code :KeyDelete ,Mod :ModShift | ModAlt }, 490"kDC5" : {Code :KeyDelete ,Mod :ModCtrl }, 491"kDC6" : {Code :KeyDelete ,Mod :ModShift | ModCtrl }, 492"kDC7" : {Code :KeyDelete ,Mod :ModAlt | ModCtrl }, 493"kDC8" : {Code :KeyDelete ,Mod :ModShift | ModAlt | ModCtrl }, 494"khome" : {Code :KeyHome }, 495"kHOM" : {Code :KeyHome ,Mod :ModShift }, 496"kHOM3" : {Code :KeyHome ,Mod :ModAlt }, 497"kHOM4" : {Code :KeyHome ,Mod :ModShift | ModAlt }, 498"kHOM5" : {Code :KeyHome ,Mod :ModCtrl }, 499"kHOM6" : {Code :KeyHome ,Mod :ModShift | ModCtrl }, 500"kHOM7" : {Code :KeyHome ,Mod :ModAlt | ModCtrl }, 501"kHOM8" : {Code :KeyHome ,Mod :ModShift | ModAlt | ModCtrl }, 502"kend" : {Code :KeyEnd }, 503"kEND" : {Code :KeyEnd ,Mod :ModShift }, 504"kEND3" : {Code :KeyEnd ,Mod :ModAlt }, 505"kEND4" : {Code :KeyEnd ,Mod :ModShift | ModAlt }, 506"kEND5" : {Code :KeyEnd ,Mod :ModCtrl }, 507"kEND6" : {Code :KeyEnd ,Mod :ModShift | ModCtrl }, 508"kEND7" : {Code :KeyEnd ,Mod :ModAlt | ModCtrl }, 509"kEND8" : {Code :KeyEnd ,Mod :ModShift | ModAlt | ModCtrl }, 510"kpp" : {Code :KeyPgUp }, 511"kprv" : {Code :KeyPgUp }, 512"kPRV" : {Code :KeyPgUp ,Mod :ModShift }, 513"kPRV3" : {Code :KeyPgUp ,Mod :ModAlt }, 514"kPRV4" : {Code :KeyPgUp ,Mod :ModShift | ModAlt }, 515"kPRV5" : {Code :KeyPgUp ,Mod :ModCtrl }, 516"kPRV6" : {Code :KeyPgUp ,Mod :ModShift | ModCtrl }, 517"kPRV7" : {Code :KeyPgUp ,Mod :ModAlt | ModCtrl }, 518"kPRV8" : {Code :KeyPgUp ,Mod :ModShift | ModAlt | ModCtrl }, 519"knp" : {Code :KeyPgDown }, 520"knxt" : {Code :KeyPgDown }, 521"kNXT" : {Code :KeyPgDown ,Mod :ModShift }, 522"kNXT3" : {Code :KeyPgDown ,Mod :ModAlt }, 523"kNXT4" : {Code :KeyPgDown ,Mod :ModShift | ModAlt }, 524"kNXT5" : {Code :KeyPgDown ,Mod :ModCtrl }, 525"kNXT6" : {Code :KeyPgDown ,Mod :ModShift | ModCtrl }, 526"kNXT7" : {Code :KeyPgDown ,Mod :ModAlt | ModCtrl }, 527"kNXT8" : {Code :KeyPgDown ,Mod :ModShift | ModAlt | ModCtrl }, 528 529"kbs" : {Code :KeyBackspace }, 530"kcbt" : {Code :KeyTab ,Mod :ModShift }, 531 532// Function keys 533// This only includes the first 12 function keys. The rest are treated 534// as modifiers of the first 12. 535// Take a look at XTerm modifyFunctionKeys 536// 537// XXX: To use unambiguous function keys, use fixterms or kitty clipboard. 538// 539// See https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyFunctionKeys 540// See https://invisible-island.net/xterm/terminfo.html 541 542"kf1" : {Code :KeyF1 }, 543"kf2" : {Code :KeyF2 }, 544"kf3" : {Code :KeyF3 }, 545"kf4" : {Code :KeyF4 }, 546"kf5" : {Code :KeyF5 }, 547"kf6" : {Code :KeyF6 }, 548"kf7" : {Code :KeyF7 }, 549"kf8" : {Code :KeyF8 }, 550"kf9" : {Code :KeyF9 }, 551"kf10" : {Code :KeyF10 }, 552"kf11" : {Code :KeyF11 }, 553"kf12" : {Code :KeyF12 }, 554"kf13" : {Code :KeyF1 ,Mod :ModShift }, 555"kf14" : {Code :KeyF2 ,Mod :ModShift }, 556"kf15" : {Code :KeyF3 ,Mod :ModShift }, 557"kf16" : {Code :KeyF4 ,Mod :ModShift }, 558"kf17" : {Code :KeyF5 ,Mod :ModShift }, 559"kf18" : {Code :KeyF6 ,Mod :ModShift }, 560"kf19" : {Code :KeyF7 ,Mod :ModShift }, 561"kf20" : {Code :KeyF8 ,Mod :ModShift }, 562"kf21" : {Code :KeyF9 ,Mod :ModShift }, 563"kf22" : {Code :KeyF10 ,Mod :ModShift }, 564"kf23" : {Code :KeyF11 ,Mod :ModShift }, 565"kf24" : {Code :KeyF12 ,Mod :ModShift }, 566"kf25" : {Code :KeyF1 ,Mod :ModCtrl }, 567"kf26" : {Code :KeyF2 ,Mod :ModCtrl }, 568"kf27" : {Code :KeyF3 ,Mod :ModCtrl }, 569"kf28" : {Code :KeyF4 ,Mod :ModCtrl }, 570"kf29" : {Code :KeyF5 ,Mod :ModCtrl }, 571"kf30" : {Code :KeyF6 ,Mod :ModCtrl }, 572"kf31" : {Code :KeyF7 ,Mod :ModCtrl }, 573"kf32" : {Code :KeyF8 ,Mod :ModCtrl }, 574"kf33" : {Code :KeyF9 ,Mod :ModCtrl }, 575"kf34" : {Code :KeyF10 ,Mod :ModCtrl }, 576"kf35" : {Code :KeyF11 ,Mod :ModCtrl }, 577"kf36" : {Code :KeyF12 ,Mod :ModCtrl }, 578"kf37" : {Code :KeyF1 ,Mod :ModShift | ModCtrl }, 579"kf38" : {Code :KeyF2 ,Mod :ModShift | ModCtrl }, 580"kf39" : {Code :KeyF3 ,Mod :ModShift | ModCtrl }, 581"kf40" : {Code :KeyF4 ,Mod :ModShift | ModCtrl }, 582"kf41" : {Code :KeyF5 ,Mod :ModShift | ModCtrl }, 583"kf42" : {Code :KeyF6 ,Mod :ModShift | ModCtrl }, 584"kf43" : {Code :KeyF7 ,Mod :ModShift | ModCtrl }, 585"kf44" : {Code :KeyF8 ,Mod :ModShift | ModCtrl }, 586"kf45" : {Code :KeyF9 ,Mod :ModShift | ModCtrl }, 587"kf46" : {Code :KeyF10 ,Mod :ModShift | ModCtrl }, 588"kf47" : {Code :KeyF11 ,Mod :ModShift | ModCtrl }, 589"kf48" : {Code :KeyF12 ,Mod :ModShift | ModCtrl }, 590"kf49" : {Code :KeyF1 ,Mod :ModAlt }, 591"kf50" : {Code :KeyF2 ,Mod :ModAlt }, 592"kf51" : {Code :KeyF3 ,Mod :ModAlt }, 593"kf52" : {Code :KeyF4 ,Mod :ModAlt }, 594"kf53" : {Code :KeyF5 ,Mod :ModAlt }, 595"kf54" : {Code :KeyF6 ,Mod :ModAlt }, 596"kf55" : {Code :KeyF7 ,Mod :ModAlt }, 597"kf56" : {Code :KeyF8 ,Mod :ModAlt }, 598"kf57" : {Code :KeyF9 ,Mod :ModAlt }, 599"kf58" : {Code :KeyF10 ,Mod :ModAlt }, 600"kf59" : {Code :KeyF11 ,Mod :ModAlt }, 601"kf60" : {Code :KeyF12 ,Mod :ModAlt }, 602"kf61" : {Code :KeyF1 ,Mod :ModShift | ModAlt }, 603"kf62" : {Code :KeyF2 ,Mod :ModShift | ModAlt }, 604"kf63" : {Code :KeyF3 ,Mod :ModShift | ModAlt }, 605 } 606 607// Preserve F keys from F13 to F63 instead of using them for F-keys 608// modifiers. 609if flags & flagFKeys != 0 { 610keys ["kf13" ]= Key {Code :KeyF13 } 611keys ["kf14" ]= Key {Code :KeyF14 } 612keys ["kf15" ]= Key {Code :KeyF15 } 613keys ["kf16" ]= Key {Code :KeyF16 } 614keys ["kf17" ]= Key {Code :KeyF17 } 615keys ["kf18" ]= Key {Code :KeyF18 } 616keys ["kf19" ]= Key {Code :KeyF19 } 617keys ["kf20" ]= Key {Code :KeyF20 } 618keys ["kf21" ]= Key {Code :KeyF21 } 619keys ["kf22" ]= Key {Code :KeyF22 } 620keys ["kf23" ]= Key {Code :KeyF23 } 621keys ["kf24" ]= Key {Code :KeyF24 } 622keys ["kf25" ]= Key {Code :KeyF25 } 623keys ["kf26" ]= Key {Code :KeyF26 } 624keys ["kf27" ]= Key {Code :KeyF27 } 625keys ["kf28" ]= Key {Code :KeyF28 } 626keys ["kf29" ]= Key {Code :KeyF29 } 627keys ["kf30" ]= Key {Code :KeyF30 } 628keys ["kf31" ]= Key {Code :KeyF31 } 629keys ["kf32" ]= Key {Code :KeyF32 } 630keys ["kf33" ]= Key {Code :KeyF33 } 631keys ["kf34" ]= Key {Code :KeyF34 } 632keys ["kf35" ]= Key {Code :KeyF35 } 633keys ["kf36" ]= Key {Code :KeyF36 } 634keys ["kf37" ]= Key {Code :KeyF37 } 635keys ["kf38" ]= Key {Code :KeyF38 } 636keys ["kf39" ]= Key {Code :KeyF39 } 637keys ["kf40" ]= Key {Code :KeyF40 } 638keys ["kf41" ]= Key {Code :KeyF41 } 639keys ["kf42" ]= Key {Code :KeyF42 } 640keys ["kf43" ]= Key {Code :KeyF43 } 641keys ["kf44" ]= Key {Code :KeyF44 } 642keys ["kf45" ]= Key {Code :KeyF45 } 643keys ["kf46" ]= Key {Code :KeyF46 } 644keys ["kf47" ]= Key {Code :KeyF47 } 645keys ["kf48" ]= Key {Code :KeyF48 } 646keys ["kf49" ]= Key {Code :KeyF49 } 647keys ["kf50" ]= Key {Code :KeyF50 } 648keys ["kf51" ]= Key {Code :KeyF51 } 649keys ["kf52" ]= Key {Code :KeyF52 } 650keys ["kf53" ]= Key {Code :KeyF53 } 651keys ["kf54" ]= Key {Code :KeyF54 } 652keys ["kf55" ]= Key {Code :KeyF55 } 653keys ["kf56" ]= Key {Code :KeyF56 } 654keys ["kf57" ]= Key {Code :KeyF57 } 655keys ["kf58" ]= Key {Code :KeyF58 } 656keys ["kf59" ]= Key {Code :KeyF59 } 657keys ["kf60" ]= Key {Code :KeyF60 } 658keys ["kf61" ]= Key {Code :KeyF61 } 659keys ["kf62" ]= Key {Code :KeyF62 } 660keys ["kf63" ]= Key {Code :KeyF63 } 661 } 662 663return keys 664}