2
0

terminfo.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. package input
  2. import (
  3. "strings"
  4. "github.com/xo/terminfo"
  5. )
  6. func buildTerminfoKeys(flags int, term string) map[string]Key {
  7. table := make(map[string]Key)
  8. ti, _ := terminfo.Load(term)
  9. if ti == nil {
  10. return table
  11. }
  12. tiTable := defaultTerminfoKeys(flags)
  13. // Default keys
  14. for name, seq := range ti.StringCapsShort() {
  15. if !strings.HasPrefix(name, "k") || len(seq) == 0 {
  16. continue
  17. }
  18. if k, ok := tiTable[name]; ok {
  19. table[string(seq)] = k
  20. }
  21. }
  22. // Extended keys
  23. for name, seq := range ti.ExtStringCapsShort() {
  24. if !strings.HasPrefix(name, "k") || len(seq) == 0 {
  25. continue
  26. }
  27. if k, ok := tiTable[name]; ok {
  28. table[string(seq)] = k
  29. }
  30. }
  31. return table
  32. }
  33. // This returns a map of terminfo keys to key events. It's a mix of ncurses
  34. // terminfo default and user-defined key capabilities.
  35. // Upper-case caps that are defined in the default terminfo database are
  36. // - kNXT
  37. // - kPRV
  38. // - kHOM
  39. // - kEND
  40. // - kDC
  41. // - kIC
  42. // - kLFT
  43. // - kRIT
  44. //
  45. // See https://man7.org/linux/man-pages/man5/terminfo.5.html
  46. // See https://github.com/mirror/ncurses/blob/master/include/Caps-ncurses
  47. func defaultTerminfoKeys(flags int) map[string]Key {
  48. keys := map[string]Key{
  49. "kcuu1": {Code: KeyUp},
  50. "kUP": {Code: KeyUp, Mod: ModShift},
  51. "kUP3": {Code: KeyUp, Mod: ModAlt},
  52. "kUP4": {Code: KeyUp, Mod: ModShift | ModAlt},
  53. "kUP5": {Code: KeyUp, Mod: ModCtrl},
  54. "kUP6": {Code: KeyUp, Mod: ModShift | ModCtrl},
  55. "kUP7": {Code: KeyUp, Mod: ModAlt | ModCtrl},
  56. "kUP8": {Code: KeyUp, Mod: ModShift | ModAlt | ModCtrl},
  57. "kcud1": {Code: KeyDown},
  58. "kDN": {Code: KeyDown, Mod: ModShift},
  59. "kDN3": {Code: KeyDown, Mod: ModAlt},
  60. "kDN4": {Code: KeyDown, Mod: ModShift | ModAlt},
  61. "kDN5": {Code: KeyDown, Mod: ModCtrl},
  62. "kDN7": {Code: KeyDown, Mod: ModAlt | ModCtrl},
  63. "kDN6": {Code: KeyDown, Mod: ModShift | ModCtrl},
  64. "kDN8": {Code: KeyDown, Mod: ModShift | ModAlt | ModCtrl},
  65. "kcub1": {Code: KeyLeft},
  66. "kLFT": {Code: KeyLeft, Mod: ModShift},
  67. "kLFT3": {Code: KeyLeft, Mod: ModAlt},
  68. "kLFT4": {Code: KeyLeft, Mod: ModShift | ModAlt},
  69. "kLFT5": {Code: KeyLeft, Mod: ModCtrl},
  70. "kLFT6": {Code: KeyLeft, Mod: ModShift | ModCtrl},
  71. "kLFT7": {Code: KeyLeft, Mod: ModAlt | ModCtrl},
  72. "kLFT8": {Code: KeyLeft, Mod: ModShift | ModAlt | ModCtrl},
  73. "kcuf1": {Code: KeyRight},
  74. "kRIT": {Code: KeyRight, Mod: ModShift},
  75. "kRIT3": {Code: KeyRight, Mod: ModAlt},
  76. "kRIT4": {Code: KeyRight, Mod: ModShift | ModAlt},
  77. "kRIT5": {Code: KeyRight, Mod: ModCtrl},
  78. "kRIT6": {Code: KeyRight, Mod: ModShift | ModCtrl},
  79. "kRIT7": {Code: KeyRight, Mod: ModAlt | ModCtrl},
  80. "kRIT8": {Code: KeyRight, Mod: ModShift | ModAlt | ModCtrl},
  81. "kich1": {Code: KeyInsert},
  82. "kIC": {Code: KeyInsert, Mod: ModShift},
  83. "kIC3": {Code: KeyInsert, Mod: ModAlt},
  84. "kIC4": {Code: KeyInsert, Mod: ModShift | ModAlt},
  85. "kIC5": {Code: KeyInsert, Mod: ModCtrl},
  86. "kIC6": {Code: KeyInsert, Mod: ModShift | ModCtrl},
  87. "kIC7": {Code: KeyInsert, Mod: ModAlt | ModCtrl},
  88. "kIC8": {Code: KeyInsert, Mod: ModShift | ModAlt | ModCtrl},
  89. "kdch1": {Code: KeyDelete},
  90. "kDC": {Code: KeyDelete, Mod: ModShift},
  91. "kDC3": {Code: KeyDelete, Mod: ModAlt},
  92. "kDC4": {Code: KeyDelete, Mod: ModShift | ModAlt},
  93. "kDC5": {Code: KeyDelete, Mod: ModCtrl},
  94. "kDC6": {Code: KeyDelete, Mod: ModShift | ModCtrl},
  95. "kDC7": {Code: KeyDelete, Mod: ModAlt | ModCtrl},
  96. "kDC8": {Code: KeyDelete, Mod: ModShift | ModAlt | ModCtrl},
  97. "khome": {Code: KeyHome},
  98. "kHOM": {Code: KeyHome, Mod: ModShift},
  99. "kHOM3": {Code: KeyHome, Mod: ModAlt},
  100. "kHOM4": {Code: KeyHome, Mod: ModShift | ModAlt},
  101. "kHOM5": {Code: KeyHome, Mod: ModCtrl},
  102. "kHOM6": {Code: KeyHome, Mod: ModShift | ModCtrl},
  103. "kHOM7": {Code: KeyHome, Mod: ModAlt | ModCtrl},
  104. "kHOM8": {Code: KeyHome, Mod: ModShift | ModAlt | ModCtrl},
  105. "kend": {Code: KeyEnd},
  106. "kEND": {Code: KeyEnd, Mod: ModShift},
  107. "kEND3": {Code: KeyEnd, Mod: ModAlt},
  108. "kEND4": {Code: KeyEnd, Mod: ModShift | ModAlt},
  109. "kEND5": {Code: KeyEnd, Mod: ModCtrl},
  110. "kEND6": {Code: KeyEnd, Mod: ModShift | ModCtrl},
  111. "kEND7": {Code: KeyEnd, Mod: ModAlt | ModCtrl},
  112. "kEND8": {Code: KeyEnd, Mod: ModShift | ModAlt | ModCtrl},
  113. "kpp": {Code: KeyPgUp},
  114. "kprv": {Code: KeyPgUp},
  115. "kPRV": {Code: KeyPgUp, Mod: ModShift},
  116. "kPRV3": {Code: KeyPgUp, Mod: ModAlt},
  117. "kPRV4": {Code: KeyPgUp, Mod: ModShift | ModAlt},
  118. "kPRV5": {Code: KeyPgUp, Mod: ModCtrl},
  119. "kPRV6": {Code: KeyPgUp, Mod: ModShift | ModCtrl},
  120. "kPRV7": {Code: KeyPgUp, Mod: ModAlt | ModCtrl},
  121. "kPRV8": {Code: KeyPgUp, Mod: ModShift | ModAlt | ModCtrl},
  122. "knp": {Code: KeyPgDown},
  123. "knxt": {Code: KeyPgDown},
  124. "kNXT": {Code: KeyPgDown, Mod: ModShift},
  125. "kNXT3": {Code: KeyPgDown, Mod: ModAlt},
  126. "kNXT4": {Code: KeyPgDown, Mod: ModShift | ModAlt},
  127. "kNXT5": {Code: KeyPgDown, Mod: ModCtrl},
  128. "kNXT6": {Code: KeyPgDown, Mod: ModShift | ModCtrl},
  129. "kNXT7": {Code: KeyPgDown, Mod: ModAlt | ModCtrl},
  130. "kNXT8": {Code: KeyPgDown, Mod: ModShift | ModAlt | ModCtrl},
  131. "kbs": {Code: KeyBackspace},
  132. "kcbt": {Code: KeyTab, Mod: ModShift},
  133. // Function keys
  134. // This only includes the first 12 function keys. The rest are treated
  135. // as modifiers of the first 12.
  136. // Take a look at XTerm modifyFunctionKeys
  137. //
  138. // XXX: To use unambiguous function keys, use fixterms or kitty clipboard.
  139. //
  140. // See https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyFunctionKeys
  141. // See https://invisible-island.net/xterm/terminfo.html
  142. "kf1": {Code: KeyF1},
  143. "kf2": {Code: KeyF2},
  144. "kf3": {Code: KeyF3},
  145. "kf4": {Code: KeyF4},
  146. "kf5": {Code: KeyF5},
  147. "kf6": {Code: KeyF6},
  148. "kf7": {Code: KeyF7},
  149. "kf8": {Code: KeyF8},
  150. "kf9": {Code: KeyF9},
  151. "kf10": {Code: KeyF10},
  152. "kf11": {Code: KeyF11},
  153. "kf12": {Code: KeyF12},
  154. "kf13": {Code: KeyF1, Mod: ModShift},
  155. "kf14": {Code: KeyF2, Mod: ModShift},
  156. "kf15": {Code: KeyF3, Mod: ModShift},
  157. "kf16": {Code: KeyF4, Mod: ModShift},
  158. "kf17": {Code: KeyF5, Mod: ModShift},
  159. "kf18": {Code: KeyF6, Mod: ModShift},
  160. "kf19": {Code: KeyF7, Mod: ModShift},
  161. "kf20": {Code: KeyF8, Mod: ModShift},
  162. "kf21": {Code: KeyF9, Mod: ModShift},
  163. "kf22": {Code: KeyF10, Mod: ModShift},
  164. "kf23": {Code: KeyF11, Mod: ModShift},
  165. "kf24": {Code: KeyF12, Mod: ModShift},
  166. "kf25": {Code: KeyF1, Mod: ModCtrl},
  167. "kf26": {Code: KeyF2, Mod: ModCtrl},
  168. "kf27": {Code: KeyF3, Mod: ModCtrl},
  169. "kf28": {Code: KeyF4, Mod: ModCtrl},
  170. "kf29": {Code: KeyF5, Mod: ModCtrl},
  171. "kf30": {Code: KeyF6, Mod: ModCtrl},
  172. "kf31": {Code: KeyF7, Mod: ModCtrl},
  173. "kf32": {Code: KeyF8, Mod: ModCtrl},
  174. "kf33": {Code: KeyF9, Mod: ModCtrl},
  175. "kf34": {Code: KeyF10, Mod: ModCtrl},
  176. "kf35": {Code: KeyF11, Mod: ModCtrl},
  177. "kf36": {Code: KeyF12, Mod: ModCtrl},
  178. "kf37": {Code: KeyF1, Mod: ModShift | ModCtrl},
  179. "kf38": {Code: KeyF2, Mod: ModShift | ModCtrl},
  180. "kf39": {Code: KeyF3, Mod: ModShift | ModCtrl},
  181. "kf40": {Code: KeyF4, Mod: ModShift | ModCtrl},
  182. "kf41": {Code: KeyF5, Mod: ModShift | ModCtrl},
  183. "kf42": {Code: KeyF6, Mod: ModShift | ModCtrl},
  184. "kf43": {Code: KeyF7, Mod: ModShift | ModCtrl},
  185. "kf44": {Code: KeyF8, Mod: ModShift | ModCtrl},
  186. "kf45": {Code: KeyF9, Mod: ModShift | ModCtrl},
  187. "kf46": {Code: KeyF10, Mod: ModShift | ModCtrl},
  188. "kf47": {Code: KeyF11, Mod: ModShift | ModCtrl},
  189. "kf48": {Code: KeyF12, Mod: ModShift | ModCtrl},
  190. "kf49": {Code: KeyF1, Mod: ModAlt},
  191. "kf50": {Code: KeyF2, Mod: ModAlt},
  192. "kf51": {Code: KeyF3, Mod: ModAlt},
  193. "kf52": {Code: KeyF4, Mod: ModAlt},
  194. "kf53": {Code: KeyF5, Mod: ModAlt},
  195. "kf54": {Code: KeyF6, Mod: ModAlt},
  196. "kf55": {Code: KeyF7, Mod: ModAlt},
  197. "kf56": {Code: KeyF8, Mod: ModAlt},
  198. "kf57": {Code: KeyF9, Mod: ModAlt},
  199. "kf58": {Code: KeyF10, Mod: ModAlt},
  200. "kf59": {Code: KeyF11, Mod: ModAlt},
  201. "kf60": {Code: KeyF12, Mod: ModAlt},
  202. "kf61": {Code: KeyF1, Mod: ModShift | ModAlt},
  203. "kf62": {Code: KeyF2, Mod: ModShift | ModAlt},
  204. "kf63": {Code: KeyF3, Mod: ModShift | ModAlt},
  205. }
  206. // Preserve F keys from F13 to F63 instead of using them for F-keys
  207. // modifiers.
  208. if flags&FlagFKeys != 0 {
  209. keys["kf13"] = Key{Code: KeyF13}
  210. keys["kf14"] = Key{Code: KeyF14}
  211. keys["kf15"] = Key{Code: KeyF15}
  212. keys["kf16"] = Key{Code: KeyF16}
  213. keys["kf17"] = Key{Code: KeyF17}
  214. keys["kf18"] = Key{Code: KeyF18}
  215. keys["kf19"] = Key{Code: KeyF19}
  216. keys["kf20"] = Key{Code: KeyF20}
  217. keys["kf21"] = Key{Code: KeyF21}
  218. keys["kf22"] = Key{Code: KeyF22}
  219. keys["kf23"] = Key{Code: KeyF23}
  220. keys["kf24"] = Key{Code: KeyF24}
  221. keys["kf25"] = Key{Code: KeyF25}
  222. keys["kf26"] = Key{Code: KeyF26}
  223. keys["kf27"] = Key{Code: KeyF27}
  224. keys["kf28"] = Key{Code: KeyF28}
  225. keys["kf29"] = Key{Code: KeyF29}
  226. keys["kf30"] = Key{Code: KeyF30}
  227. keys["kf31"] = Key{Code: KeyF31}
  228. keys["kf32"] = Key{Code: KeyF32}
  229. keys["kf33"] = Key{Code: KeyF33}
  230. keys["kf34"] = Key{Code: KeyF34}
  231. keys["kf35"] = Key{Code: KeyF35}
  232. keys["kf36"] = Key{Code: KeyF36}
  233. keys["kf37"] = Key{Code: KeyF37}
  234. keys["kf38"] = Key{Code: KeyF38}
  235. keys["kf39"] = Key{Code: KeyF39}
  236. keys["kf40"] = Key{Code: KeyF40}
  237. keys["kf41"] = Key{Code: KeyF41}
  238. keys["kf42"] = Key{Code: KeyF42}
  239. keys["kf43"] = Key{Code: KeyF43}
  240. keys["kf44"] = Key{Code: KeyF44}
  241. keys["kf45"] = Key{Code: KeyF45}
  242. keys["kf46"] = Key{Code: KeyF46}
  243. keys["kf47"] = Key{Code: KeyF47}
  244. keys["kf48"] = Key{Code: KeyF48}
  245. keys["kf49"] = Key{Code: KeyF49}
  246. keys["kf50"] = Key{Code: KeyF50}
  247. keys["kf51"] = Key{Code: KeyF51}
  248. keys["kf52"] = Key{Code: KeyF52}
  249. keys["kf53"] = Key{Code: KeyF53}
  250. keys["kf54"] = Key{Code: KeyF54}
  251. keys["kf55"] = Key{Code: KeyF55}
  252. keys["kf56"] = Key{Code: KeyF56}
  253. keys["kf57"] = Key{Code: KeyF57}
  254. keys["kf58"] = Key{Code: KeyF58}
  255. keys["kf59"] = Key{Code: KeyF59}
  256. keys["kf60"] = Key{Code: KeyF60}
  257. keys["kf61"] = Key{Code: KeyF61}
  258. keys["kf62"] = Key{Code: KeyF62}
  259. keys["kf63"] = Key{Code: KeyF63}
  260. }
  261. return keys
  262. }