key.go 20 KB

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