key.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. package tea
  2. import (
  3. "errors"
  4. "io"
  5. "unicode/utf8"
  6. "github.com/mattn/go-localereader"
  7. )
  8. // KeyMsg contains information about a keypress. KeyMsgs are always sent to
  9. // the program's update function. There are a couple general patterns you could
  10. // use to check for keypresses:
  11. //
  12. // // Switch on the string representation of the key (shorter)
  13. // switch msg := msg.(type) {
  14. // case KeyMsg:
  15. // switch msg.String() {
  16. // case "enter":
  17. // fmt.Println("you pressed enter!")
  18. // case "a":
  19. // fmt.Println("you pressed a!")
  20. // }
  21. // }
  22. //
  23. // // Switch on the key type (more foolproof)
  24. // switch msg := msg.(type) {
  25. // case KeyMsg:
  26. // switch msg.Type {
  27. // case KeyEnter:
  28. // fmt.Println("you pressed enter!")
  29. // case KeyRunes:
  30. // switch string(msg.Runes) {
  31. // case "a":
  32. // fmt.Println("you pressed a!")
  33. // }
  34. // }
  35. // }
  36. //
  37. // Note that Key.Runes will always contain at least one character, so you can
  38. // always safely call Key.Runes[0]. In most cases Key.Runes will only contain
  39. // one character, though certain input method editors (most notably Chinese
  40. // IMEs) can input multiple runes at once.
  41. type KeyMsg Key
  42. // String returns a string representation for a key message. It's safe (and
  43. // encouraged) for use in key comparison.
  44. func (k KeyMsg) String() (str string) {
  45. return Key(k).String()
  46. }
  47. // Key contains information about a keypress.
  48. type Key struct {
  49. Type KeyType
  50. Runes []rune
  51. Alt bool
  52. }
  53. // String returns a friendly string representation for a key. It's safe (and
  54. // encouraged) for use in key comparison.
  55. //
  56. // k := Key{Type: KeyEnter}
  57. // fmt.Println(k)
  58. // // Output: enter
  59. func (k Key) String() (str string) {
  60. if k.Alt {
  61. str += "alt+"
  62. }
  63. if k.Type == KeyRunes {
  64. str += string(k.Runes)
  65. return str
  66. } else if s, ok := keyNames[k.Type]; ok {
  67. str += s
  68. return str
  69. }
  70. return ""
  71. }
  72. // KeyType indicates the key pressed, such as KeyEnter or KeyBreak or KeyCtrlC.
  73. // All other keys will be type KeyRunes. To get the rune value, check the Rune
  74. // method on a Key struct, or use the Key.String() method:
  75. //
  76. // k := Key{Type: KeyRunes, Runes: []rune{'a'}, Alt: true}
  77. // if k.Type == KeyRunes {
  78. //
  79. // fmt.Println(k.Runes)
  80. // // Output: a
  81. //
  82. // fmt.Println(k.String())
  83. // // Output: alt+a
  84. //
  85. // }
  86. type KeyType int
  87. func (k KeyType) String() (str string) {
  88. if s, ok := keyNames[k]; ok {
  89. return s
  90. }
  91. return ""
  92. }
  93. // Control keys. We could do this with an iota, but the values are very
  94. // specific, so we set the values explicitly to avoid any confusion.
  95. //
  96. // See also:
  97. // https://en.wikipedia.org/wiki/C0_and_C1_control_codes
  98. const (
  99. keyNUL KeyType = 0 // null, \0
  100. keySOH KeyType = 1 // start of heading
  101. keySTX KeyType = 2 // start of text
  102. keyETX KeyType = 3 // break, ctrl+c
  103. keyEOT KeyType = 4 // end of transmission
  104. keyENQ KeyType = 5 // enquiry
  105. keyACK KeyType = 6 // acknowledge
  106. keyBEL KeyType = 7 // bell, \a
  107. keyBS KeyType = 8 // backspace
  108. keyHT KeyType = 9 // horizontal tabulation, \t
  109. keyLF KeyType = 10 // line feed, \n
  110. keyVT KeyType = 11 // vertical tabulation \v
  111. keyFF KeyType = 12 // form feed \f
  112. keyCR KeyType = 13 // carriage return, \r
  113. keySO KeyType = 14 // shift out
  114. keySI KeyType = 15 // shift in
  115. keyDLE KeyType = 16 // data link escape
  116. keyDC1 KeyType = 17 // device control one
  117. keyDC2 KeyType = 18 // device control two
  118. keyDC3 KeyType = 19 // device control three
  119. keyDC4 KeyType = 20 // device control four
  120. keyNAK KeyType = 21 // negative acknowledge
  121. keySYN KeyType = 22 // synchronous idle
  122. keyETB KeyType = 23 // end of transmission block
  123. keyCAN KeyType = 24 // cancel
  124. keyEM KeyType = 25 // end of medium
  125. keySUB KeyType = 26 // substitution
  126. keyESC KeyType = 27 // escape, \e
  127. keyFS KeyType = 28 // file separator
  128. keyGS KeyType = 29 // group separator
  129. keyRS KeyType = 30 // record separator
  130. keyUS KeyType = 31 // unit separator
  131. keyDEL KeyType = 127 // delete. on most systems this is mapped to backspace, I hear
  132. )
  133. // Control key aliases.
  134. const (
  135. KeyNull KeyType = keyNUL
  136. KeyBreak KeyType = keyETX
  137. KeyEnter KeyType = keyCR
  138. KeyBackspace KeyType = keyDEL
  139. KeyTab KeyType = keyHT
  140. KeyEsc KeyType = keyESC
  141. KeyEscape KeyType = keyESC
  142. KeyCtrlAt KeyType = keyNUL // ctrl+@
  143. KeyCtrlA KeyType = keySOH
  144. KeyCtrlB KeyType = keySTX
  145. KeyCtrlC KeyType = keyETX
  146. KeyCtrlD KeyType = keyEOT
  147. KeyCtrlE KeyType = keyENQ
  148. KeyCtrlF KeyType = keyACK
  149. KeyCtrlG KeyType = keyBEL
  150. KeyCtrlH KeyType = keyBS
  151. KeyCtrlI KeyType = keyHT
  152. KeyCtrlJ KeyType = keyLF
  153. KeyCtrlK KeyType = keyVT
  154. KeyCtrlL KeyType = keyFF
  155. KeyCtrlM KeyType = keyCR
  156. KeyCtrlN KeyType = keySO
  157. KeyCtrlO KeyType = keySI
  158. KeyCtrlP KeyType = keyDLE
  159. KeyCtrlQ KeyType = keyDC1
  160. KeyCtrlR KeyType = keyDC2
  161. KeyCtrlS KeyType = keyDC3
  162. KeyCtrlT KeyType = keyDC4
  163. KeyCtrlU KeyType = keyNAK
  164. KeyCtrlV KeyType = keySYN
  165. KeyCtrlW KeyType = keyETB
  166. KeyCtrlX KeyType = keyCAN
  167. KeyCtrlY KeyType = keyEM
  168. KeyCtrlZ KeyType = keySUB
  169. KeyCtrlOpenBracket KeyType = keyESC // ctrl+[
  170. KeyCtrlBackslash KeyType = keyFS // ctrl+\
  171. KeyCtrlCloseBracket KeyType = keyGS // ctrl+]
  172. KeyCtrlCaret KeyType = keyRS // ctrl+^
  173. KeyCtrlUnderscore KeyType = keyUS // ctrl+_
  174. KeyCtrlQuestionMark KeyType = keyDEL // ctrl+?
  175. )
  176. // Other keys.
  177. const (
  178. KeyRunes KeyType = -(iota + 1)
  179. KeyUp
  180. KeyDown
  181. KeyRight
  182. KeyLeft
  183. KeyShiftTab
  184. KeyHome
  185. KeyEnd
  186. KeyPgUp
  187. KeyPgDown
  188. KeyCtrlPgUp
  189. KeyCtrlPgDown
  190. KeyDelete
  191. KeyInsert
  192. KeySpace
  193. KeyCtrlUp
  194. KeyCtrlDown
  195. KeyCtrlRight
  196. KeyCtrlLeft
  197. KeyCtrlHome
  198. KeyCtrlEnd
  199. KeyShiftUp
  200. KeyShiftDown
  201. KeyShiftRight
  202. KeyShiftLeft
  203. KeyShiftHome
  204. KeyShiftEnd
  205. KeyCtrlShiftUp
  206. KeyCtrlShiftDown
  207. KeyCtrlShiftLeft
  208. KeyCtrlShiftRight
  209. KeyCtrlShiftHome
  210. KeyCtrlShiftEnd
  211. KeyF1
  212. KeyF2
  213. KeyF3
  214. KeyF4
  215. KeyF5
  216. KeyF6
  217. KeyF7
  218. KeyF8
  219. KeyF9
  220. KeyF10
  221. KeyF11
  222. KeyF12
  223. KeyF13
  224. KeyF14
  225. KeyF15
  226. KeyF16
  227. KeyF17
  228. KeyF18
  229. KeyF19
  230. KeyF20
  231. )
  232. // Mappings for control keys and other special keys to friendly consts.
  233. var keyNames = map[KeyType]string{
  234. // Control keys.
  235. keyNUL: "ctrl+@", // also ctrl+` (that's ctrl+backtick)
  236. keySOH: "ctrl+a",
  237. keySTX: "ctrl+b",
  238. keyETX: "ctrl+c",
  239. keyEOT: "ctrl+d",
  240. keyENQ: "ctrl+e",
  241. keyACK: "ctrl+f",
  242. keyBEL: "ctrl+g",
  243. keyBS: "ctrl+h",
  244. keyHT: "tab", // also ctrl+i
  245. keyLF: "ctrl+j",
  246. keyVT: "ctrl+k",
  247. keyFF: "ctrl+l",
  248. keyCR: "enter",
  249. keySO: "ctrl+n",
  250. keySI: "ctrl+o",
  251. keyDLE: "ctrl+p",
  252. keyDC1: "ctrl+q",
  253. keyDC2: "ctrl+r",
  254. keyDC3: "ctrl+s",
  255. keyDC4: "ctrl+t",
  256. keyNAK: "ctrl+u",
  257. keySYN: "ctrl+v",
  258. keyETB: "ctrl+w",
  259. keyCAN: "ctrl+x",
  260. keyEM: "ctrl+y",
  261. keySUB: "ctrl+z",
  262. keyESC: "esc",
  263. keyFS: "ctrl+\\",
  264. keyGS: "ctrl+]",
  265. keyRS: "ctrl+^",
  266. keyUS: "ctrl+_",
  267. keyDEL: "backspace",
  268. // Other keys.
  269. KeyRunes: "runes",
  270. KeyUp: "up",
  271. KeyDown: "down",
  272. KeyRight: "right",
  273. KeySpace: " ", // for backwards compatibility
  274. KeyLeft: "left",
  275. KeyShiftTab: "shift+tab",
  276. KeyHome: "home",
  277. KeyEnd: "end",
  278. KeyCtrlHome: "ctrl+home",
  279. KeyCtrlEnd: "ctrl+end",
  280. KeyShiftHome: "shift+home",
  281. KeyShiftEnd: "shift+end",
  282. KeyCtrlShiftHome: "ctrl+shift+home",
  283. KeyCtrlShiftEnd: "ctrl+shift+end",
  284. KeyPgUp: "pgup",
  285. KeyPgDown: "pgdown",
  286. KeyCtrlPgUp: "ctrl+pgup",
  287. KeyCtrlPgDown: "ctrl+pgdown",
  288. KeyDelete: "delete",
  289. KeyInsert: "insert",
  290. KeyCtrlUp: "ctrl+up",
  291. KeyCtrlDown: "ctrl+down",
  292. KeyCtrlRight: "ctrl+right",
  293. KeyCtrlLeft: "ctrl+left",
  294. KeyShiftUp: "shift+up",
  295. KeyShiftDown: "shift+down",
  296. KeyShiftRight: "shift+right",
  297. KeyShiftLeft: "shift+left",
  298. KeyCtrlShiftUp: "ctrl+shift+up",
  299. KeyCtrlShiftDown: "ctrl+shift+down",
  300. KeyCtrlShiftLeft: "ctrl+shift+left",
  301. KeyCtrlShiftRight: "ctrl+shift+right",
  302. KeyF1: "f1",
  303. KeyF2: "f2",
  304. KeyF3: "f3",
  305. KeyF4: "f4",
  306. KeyF5: "f5",
  307. KeyF6: "f6",
  308. KeyF7: "f7",
  309. KeyF8: "f8",
  310. KeyF9: "f9",
  311. KeyF10: "f10",
  312. KeyF11: "f11",
  313. KeyF12: "f12",
  314. KeyF13: "f13",
  315. KeyF14: "f14",
  316. KeyF15: "f15",
  317. KeyF16: "f16",
  318. KeyF17: "f17",
  319. KeyF18: "f18",
  320. KeyF19: "f19",
  321. KeyF20: "f20",
  322. }
  323. // Sequence mappings.
  324. var sequences = map[string]Key{
  325. // Arrow keys
  326. "\x1b[A": {Type: KeyUp},
  327. "\x1b[B": {Type: KeyDown},
  328. "\x1b[C": {Type: KeyRight},
  329. "\x1b[D": {Type: KeyLeft},
  330. "\x1b[1;2A": {Type: KeyShiftUp},
  331. "\x1b[1;2B": {Type: KeyShiftDown},
  332. "\x1b[1;2C": {Type: KeyShiftRight},
  333. "\x1b[1;2D": {Type: KeyShiftLeft},
  334. "\x1b[OA": {Type: KeyShiftUp}, // DECCKM
  335. "\x1b[OB": {Type: KeyShiftDown}, // DECCKM
  336. "\x1b[OC": {Type: KeyShiftRight}, // DECCKM
  337. "\x1b[OD": {Type: KeyShiftLeft}, // DECCKM
  338. "\x1b[a": {Type: KeyShiftUp}, // urxvt
  339. "\x1b[b": {Type: KeyShiftDown}, // urxvt
  340. "\x1b[c": {Type: KeyShiftRight}, // urxvt
  341. "\x1b[d": {Type: KeyShiftLeft}, // urxvt
  342. "\x1b[1;3A": {Type: KeyUp, Alt: true},
  343. "\x1b[1;3B": {Type: KeyDown, Alt: true},
  344. "\x1b[1;3C": {Type: KeyRight, Alt: true},
  345. "\x1b[1;3D": {Type: KeyLeft, Alt: true},
  346. "\x1b\x1b[A": {Type: KeyUp, Alt: true}, // urxvt
  347. "\x1b\x1b[B": {Type: KeyDown, Alt: true}, // urxvt
  348. "\x1b\x1b[C": {Type: KeyRight, Alt: true}, // urxvt
  349. "\x1b\x1b[D": {Type: KeyLeft, Alt: true}, // urxvt
  350. "\x1b[1;4A": {Type: KeyShiftUp, Alt: true},
  351. "\x1b[1;4B": {Type: KeyShiftDown, Alt: true},
  352. "\x1b[1;4C": {Type: KeyShiftRight, Alt: true},
  353. "\x1b[1;4D": {Type: KeyShiftLeft, Alt: true},
  354. "\x1b\x1b[a": {Type: KeyShiftUp, Alt: true}, // urxvt
  355. "\x1b\x1b[b": {Type: KeyShiftDown, Alt: true}, // urxvt
  356. "\x1b\x1b[c": {Type: KeyShiftRight, Alt: true}, // urxvt
  357. "\x1b\x1b[d": {Type: KeyShiftLeft, Alt: true}, // urxvt
  358. "\x1b[1;5A": {Type: KeyCtrlUp},
  359. "\x1b[1;5B": {Type: KeyCtrlDown},
  360. "\x1b[1;5C": {Type: KeyCtrlRight},
  361. "\x1b[1;5D": {Type: KeyCtrlLeft},
  362. "\x1b[Oa": {Type: KeyCtrlUp, Alt: true}, // urxvt
  363. "\x1b[Ob": {Type: KeyCtrlDown, Alt: true}, // urxvt
  364. "\x1b[Oc": {Type: KeyCtrlRight, Alt: true}, // urxvt
  365. "\x1b[Od": {Type: KeyCtrlLeft, Alt: true}, // urxvt
  366. "\x1b[1;6A": {Type: KeyCtrlShiftUp},
  367. "\x1b[1;6B": {Type: KeyCtrlShiftDown},
  368. "\x1b[1;6C": {Type: KeyCtrlShiftRight},
  369. "\x1b[1;6D": {Type: KeyCtrlShiftLeft},
  370. "\x1b[1;7A": {Type: KeyCtrlUp, Alt: true},
  371. "\x1b[1;7B": {Type: KeyCtrlDown, Alt: true},
  372. "\x1b[1;7C": {Type: KeyCtrlRight, Alt: true},
  373. "\x1b[1;7D": {Type: KeyCtrlLeft, Alt: true},
  374. "\x1b[1;8A": {Type: KeyCtrlShiftUp, Alt: true},
  375. "\x1b[1;8B": {Type: KeyCtrlShiftDown, Alt: true},
  376. "\x1b[1;8C": {Type: KeyCtrlShiftRight, Alt: true},
  377. "\x1b[1;8D": {Type: KeyCtrlShiftLeft, Alt: true},
  378. // Miscellaneous keys
  379. "\x1b[Z": {Type: KeyShiftTab},
  380. "\x1b[2~": {Type: KeyInsert},
  381. "\x1b[3;2~": {Type: KeyInsert, Alt: true},
  382. "\x1b\x1b[2~": {Type: KeyInsert, Alt: true}, // urxvt
  383. "\x1b[3~": {Type: KeyDelete},
  384. "\x1b[3;3~": {Type: KeyDelete, Alt: true},
  385. "\x1b\x1b[3~": {Type: KeyDelete, Alt: true}, // urxvt
  386. "\x1b[5~": {Type: KeyPgUp},
  387. "\x1b[5;3~": {Type: KeyPgUp, Alt: true},
  388. "\x1b\x1b[5~": {Type: KeyPgUp, Alt: true}, // urxvt
  389. "\x1b[5;5~": {Type: KeyCtrlPgUp},
  390. "\x1b[5^": {Type: KeyCtrlPgUp}, // urxvt
  391. "\x1b[5;7~": {Type: KeyCtrlPgUp, Alt: true},
  392. "\x1b\x1b[5^": {Type: KeyCtrlPgUp, Alt: true}, // urxvt
  393. "\x1b[6~": {Type: KeyPgDown},
  394. "\x1b[6;3~": {Type: KeyPgDown, Alt: true},
  395. "\x1b\x1b[6~": {Type: KeyPgDown, Alt: true}, // urxvt
  396. "\x1b[6;5~": {Type: KeyCtrlPgDown},
  397. "\x1b[6^": {Type: KeyCtrlPgDown}, // urxvt
  398. "\x1b[6;7~": {Type: KeyCtrlPgDown, Alt: true},
  399. "\x1b\x1b[6^": {Type: KeyCtrlPgDown, Alt: true}, // urxvt
  400. "\x1b[1~": {Type: KeyHome},
  401. "\x1b[H": {Type: KeyHome}, // xterm, lxterm
  402. "\x1b[1;3H": {Type: KeyHome, Alt: true}, // xterm, lxterm
  403. "\x1b[1;5H": {Type: KeyCtrlHome}, // xterm, lxterm
  404. "\x1b[1;7H": {Type: KeyCtrlHome, Alt: true}, // xterm, lxterm
  405. "\x1b[1;2H": {Type: KeyShiftHome}, // xterm, lxterm
  406. "\x1b[1;4H": {Type: KeyShiftHome, Alt: true}, // xterm, lxterm
  407. "\x1b[1;6H": {Type: KeyCtrlShiftHome}, // xterm, lxterm
  408. "\x1b[1;8H": {Type: KeyCtrlShiftHome, Alt: true}, // xterm, lxterm
  409. "\x1b[4~": {Type: KeyEnd},
  410. "\x1b[F": {Type: KeyEnd}, // xterm, lxterm
  411. "\x1b[1;3F": {Type: KeyEnd, Alt: true}, // xterm, lxterm
  412. "\x1b[1;5F": {Type: KeyCtrlEnd}, // xterm, lxterm
  413. "\x1b[1;7F": {Type: KeyCtrlEnd, Alt: true}, // xterm, lxterm
  414. "\x1b[1;2F": {Type: KeyShiftEnd}, // xterm, lxterm
  415. "\x1b[1;4F": {Type: KeyShiftEnd, Alt: true}, // xterm, lxterm
  416. "\x1b[1;6F": {Type: KeyCtrlShiftEnd}, // xterm, lxterm
  417. "\x1b[1;8F": {Type: KeyCtrlShiftEnd, Alt: true}, // xterm, lxterm
  418. "\x1b[7~": {Type: KeyHome}, // urxvt
  419. "\x1b\x1b[7~": {Type: KeyHome, Alt: true}, // urxvt
  420. "\x1b[7^": {Type: KeyCtrlHome}, // urxvt
  421. "\x1b\x1b[7^": {Type: KeyCtrlHome, Alt: true}, // urxvt
  422. "\x1b[7$": {Type: KeyShiftHome}, // urxvt
  423. "\x1b\x1b[7$": {Type: KeyShiftHome, Alt: true}, // urxvt
  424. "\x1b[7@": {Type: KeyCtrlShiftHome}, // urxvt
  425. "\x1b\x1b[7@": {Type: KeyCtrlShiftHome, Alt: true}, // urxvt
  426. "\x1b[8~": {Type: KeyEnd}, // urxvt
  427. "\x1b\x1b[8~": {Type: KeyEnd, Alt: true}, // urxvt
  428. "\x1b[8^": {Type: KeyCtrlEnd}, // urxvt
  429. "\x1b\x1b[8^": {Type: KeyCtrlEnd, Alt: true}, // urxvt
  430. "\x1b[8$": {Type: KeyShiftEnd}, // urxvt
  431. "\x1b\x1b[8$": {Type: KeyShiftEnd, Alt: true}, // urxvt
  432. "\x1b[8@": {Type: KeyCtrlShiftEnd}, // urxvt
  433. "\x1b\x1b[8@": {Type: KeyCtrlShiftEnd, Alt: true}, // urxvt
  434. // Function keys, Linux console
  435. "\x1b[[A": {Type: KeyF1}, // linux console
  436. "\x1b[[B": {Type: KeyF2}, // linux console
  437. "\x1b[[C": {Type: KeyF3}, // linux console
  438. "\x1b[[D": {Type: KeyF4}, // linux console
  439. "\x1b[[E": {Type: KeyF5}, // linux console
  440. // Function keys, X11
  441. "\x1bOP": {Type: KeyF1}, // vt100, xterm
  442. "\x1bOQ": {Type: KeyF2}, // vt100, xterm
  443. "\x1bOR": {Type: KeyF3}, // vt100, xterm
  444. "\x1bOS": {Type: KeyF4}, // vt100, xterm
  445. "\x1b[1;3P": {Type: KeyF1, Alt: true}, // vt100, xterm
  446. "\x1b[1;3Q": {Type: KeyF2, Alt: true}, // vt100, xterm
  447. "\x1b[1;3R": {Type: KeyF3, Alt: true}, // vt100, xterm
  448. "\x1b[1;3S": {Type: KeyF4, Alt: true}, // vt100, xterm
  449. "\x1b[11~": {Type: KeyF1}, // urxvt
  450. "\x1b[12~": {Type: KeyF2}, // urxvt
  451. "\x1b[13~": {Type: KeyF3}, // urxvt
  452. "\x1b[14~": {Type: KeyF4}, // urxvt
  453. "\x1b\x1b[11~": {Type: KeyF1, Alt: true}, // urxvt
  454. "\x1b\x1b[12~": {Type: KeyF2, Alt: true}, // urxvt
  455. "\x1b\x1b[13~": {Type: KeyF3, Alt: true}, // urxvt
  456. "\x1b\x1b[14~": {Type: KeyF4, Alt: true}, // urxvt
  457. "\x1b[15~": {Type: KeyF5}, // vt100, xterm, also urxvt
  458. "\x1b[15;3~": {Type: KeyF5, Alt: true}, // vt100, xterm, also urxvt
  459. "\x1b\x1b[15~": {Type: KeyF5, Alt: true}, // urxvt
  460. "\x1b[17~": {Type: KeyF6}, // vt100, xterm, also urxvt
  461. "\x1b[18~": {Type: KeyF7}, // vt100, xterm, also urxvt
  462. "\x1b[19~": {Type: KeyF8}, // vt100, xterm, also urxvt
  463. "\x1b[20~": {Type: KeyF9}, // vt100, xterm, also urxvt
  464. "\x1b[21~": {Type: KeyF10}, // vt100, xterm, also urxvt
  465. "\x1b\x1b[17~": {Type: KeyF6, Alt: true}, // urxvt
  466. "\x1b\x1b[18~": {Type: KeyF7, Alt: true}, // urxvt
  467. "\x1b\x1b[19~": {Type: KeyF8, Alt: true}, // urxvt
  468. "\x1b\x1b[20~": {Type: KeyF9, Alt: true}, // urxvt
  469. "\x1b\x1b[21~": {Type: KeyF10, Alt: true}, // urxvt
  470. "\x1b[17;3~": {Type: KeyF6, Alt: true}, // vt100, xterm
  471. "\x1b[18;3~": {Type: KeyF7, Alt: true}, // vt100, xterm
  472. "\x1b[19;3~": {Type: KeyF8, Alt: true}, // vt100, xterm
  473. "\x1b[20;3~": {Type: KeyF9, Alt: true}, // vt100, xterm
  474. "\x1b[21;3~": {Type: KeyF10, Alt: true}, // vt100, xterm
  475. "\x1b[23~": {Type: KeyF11}, // vt100, xterm, also urxvt
  476. "\x1b[24~": {Type: KeyF12}, // vt100, xterm, also urxvt
  477. "\x1b[23;3~": {Type: KeyF11, Alt: true}, // vt100, xterm
  478. "\x1b[24;3~": {Type: KeyF12, Alt: true}, // vt100, xterm
  479. "\x1b\x1b[23~": {Type: KeyF11, Alt: true}, // urxvt
  480. "\x1b\x1b[24~": {Type: KeyF12, Alt: true}, // urxvt
  481. "\x1b[1;2P": {Type: KeyF13},
  482. "\x1b[1;2Q": {Type: KeyF14},
  483. "\x1b[25~": {Type: KeyF13}, // vt100, xterm, also urxvt
  484. "\x1b[26~": {Type: KeyF14}, // vt100, xterm, also urxvt
  485. "\x1b[25;3~": {Type: KeyF13, Alt: true}, // vt100, xterm
  486. "\x1b[26;3~": {Type: KeyF14, Alt: true}, // vt100, xterm
  487. "\x1b\x1b[25~": {Type: KeyF13, Alt: true}, // urxvt
  488. "\x1b\x1b[26~": {Type: KeyF14, Alt: true}, // urxvt
  489. "\x1b[1;2R": {Type: KeyF15},
  490. "\x1b[1;2S": {Type: KeyF16},
  491. "\x1b[28~": {Type: KeyF15}, // vt100, xterm, also urxvt
  492. "\x1b[29~": {Type: KeyF16}, // vt100, xterm, also urxvt
  493. "\x1b[28;3~": {Type: KeyF15, Alt: true}, // vt100, xterm
  494. "\x1b[29;3~": {Type: KeyF16, Alt: true}, // vt100, xterm
  495. "\x1b\x1b[28~": {Type: KeyF15, Alt: true}, // urxvt
  496. "\x1b\x1b[29~": {Type: KeyF16, Alt: true}, // urxvt
  497. "\x1b[15;2~": {Type: KeyF17},
  498. "\x1b[17;2~": {Type: KeyF18},
  499. "\x1b[18;2~": {Type: KeyF19},
  500. "\x1b[19;2~": {Type: KeyF20},
  501. "\x1b[31~": {Type: KeyF17},
  502. "\x1b[32~": {Type: KeyF18},
  503. "\x1b[33~": {Type: KeyF19},
  504. "\x1b[34~": {Type: KeyF20},
  505. "\x1b\x1b[31~": {Type: KeyF17, Alt: true}, // urxvt
  506. "\x1b\x1b[32~": {Type: KeyF18, Alt: true}, // urxvt
  507. "\x1b\x1b[33~": {Type: KeyF19, Alt: true}, // urxvt
  508. "\x1b\x1b[34~": {Type: KeyF20, Alt: true}, // urxvt
  509. // Powershell sequences.
  510. "\x1bOA": {Type: KeyUp, Alt: false},
  511. "\x1bOB": {Type: KeyDown, Alt: false},
  512. "\x1bOC": {Type: KeyRight, Alt: false},
  513. "\x1bOD": {Type: KeyLeft, Alt: false},
  514. }
  515. // readInputs reads keypress and mouse inputs from a TTY and returns messages
  516. // containing information about the key or mouse events accordingly.
  517. func readInputs(input io.Reader) ([]Msg, error) {
  518. var buf [256]byte
  519. // Read and block
  520. numBytes, err := input.Read(buf[:])
  521. if err != nil {
  522. return nil, err
  523. }
  524. b := buf[:numBytes]
  525. b, err = localereader.UTF8(b)
  526. if err != nil {
  527. return nil, err
  528. }
  529. // Check if it's a mouse event. For now we're parsing X10-type mouse events
  530. // only.
  531. mouseEvent, err := parseX10MouseEvents(b)
  532. if err == nil {
  533. var m []Msg
  534. for _, v := range mouseEvent {
  535. m = append(m, MouseMsg(v))
  536. }
  537. return m, nil
  538. }
  539. var runeSets [][]rune
  540. var runes []rune
  541. // Translate input into runes. In most cases we'll receive exactly one
  542. // rune, but there are cases, particularly when an input method editor is
  543. // used, where we can receive multiple runes at once.
  544. for i, w := 0, 0; i < len(b); i += w {
  545. r, width := utf8.DecodeRune(b[i:])
  546. if r == utf8.RuneError {
  547. return nil, errors.New("could not decode rune")
  548. }
  549. if r == '\x1b' && len(runes) > 1 {
  550. // a new key sequence has started
  551. runeSets = append(runeSets, runes)
  552. runes = []rune{}
  553. }
  554. runes = append(runes, r)
  555. w = width
  556. }
  557. // add the final set of runes we decoded
  558. runeSets = append(runeSets, runes)
  559. if len(runeSets) == 0 {
  560. return nil, errors.New("received 0 runes from input")
  561. }
  562. var msgs []Msg
  563. for _, runes := range runeSets {
  564. // Is it a sequence, like an arrow key?
  565. if k, ok := sequences[string(runes)]; ok {
  566. msgs = append(msgs, KeyMsg(k))
  567. continue
  568. }
  569. // Is this an unrecognized CSI sequence? If so, ignore it.
  570. if len(runes) > 2 && runes[0] == 0x1b && (runes[1] == '[' ||
  571. (len(runes) > 3 && runes[1] == 0x1b && runes[2] == '[')) {
  572. continue
  573. }
  574. // Is the alt key pressed? If so, the buffer will be prefixed with an
  575. // escape.
  576. alt := false
  577. if len(runes) > 1 && runes[0] == 0x1b {
  578. alt = true
  579. runes = runes[1:]
  580. }
  581. for _, v := range runes {
  582. // Is the first rune a control character?
  583. r := KeyType(v)
  584. if r <= keyUS || r == keyDEL {
  585. msgs = append(msgs, KeyMsg(Key{Type: r, Alt: alt}))
  586. continue
  587. }
  588. // If it's a space, override the type with KeySpace (but still include
  589. // the rune).
  590. if r == ' ' {
  591. msgs = append(msgs, KeyMsg(Key{Type: KeySpace, Runes: []rune{v}, Alt: alt}))
  592. continue
  593. }
  594. // Welp, just regular, ol' runes.
  595. msgs = append(msgs, KeyMsg(Key{Type: KeyRunes, Runes: []rune{v}, Alt: alt}))
  596. }
  597. }
  598. return msgs, nil
  599. }