parse.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. package input
  2. import (
  3. "bytes"
  4. "encoding/base64"
  5. "slices"
  6. "strings"
  7. "unicode"
  8. "unicode/utf8"
  9. "github.com/charmbracelet/x/ansi"
  10. "github.com/charmbracelet/x/ansi/parser"
  11. "github.com/rivo/uniseg"
  12. )
  13. // Flags to control the behavior of the parser.
  14. const (
  15. // When this flag is set, the driver will treat both Ctrl+Space and Ctrl+@
  16. // as the same key sequence.
  17. //
  18. // Historically, the ANSI specs generate NUL (0x00) on both the Ctrl+Space
  19. // and Ctrl+@ key sequences. This flag allows the driver to treat both as
  20. // the same key sequence.
  21. FlagCtrlAt = 1 << iota
  22. // When this flag is set, the driver will treat the Tab key and Ctrl+I as
  23. // the same key sequence.
  24. //
  25. // Historically, the ANSI specs generate HT (0x09) on both the Tab key and
  26. // Ctrl+I. This flag allows the driver to treat both as the same key
  27. // sequence.
  28. FlagCtrlI
  29. // When this flag is set, the driver will treat the Enter key and Ctrl+M as
  30. // the same key sequence.
  31. //
  32. // Historically, the ANSI specs generate CR (0x0D) on both the Enter key
  33. // and Ctrl+M. This flag allows the driver to treat both as the same key.
  34. FlagCtrlM
  35. // When this flag is set, the driver will treat Escape and Ctrl+[ as
  36. // the same key sequence.
  37. //
  38. // Historically, the ANSI specs generate ESC (0x1B) on both the Escape key
  39. // and Ctrl+[. This flag allows the driver to treat both as the same key
  40. // sequence.
  41. FlagCtrlOpenBracket
  42. // When this flag is set, the driver will send a BS (0x08 byte) character
  43. // instead of a DEL (0x7F byte) character when the Backspace key is
  44. // pressed.
  45. //
  46. // The VT100 terminal has both a Backspace and a Delete key. The VT220
  47. // terminal dropped the Backspace key and replaced it with the Delete key.
  48. // Both terminals send a DEL character when the Delete key is pressed.
  49. // Modern terminals and PCs later readded the Delete key but used a
  50. // different key sequence, and the Backspace key was standardized to send a
  51. // DEL character.
  52. FlagBackspace
  53. // When this flag is set, the driver will recognize the Find key instead of
  54. // treating it as a Home key.
  55. //
  56. // The Find key was part of the VT220 keyboard, and is no longer used in
  57. // modern day PCs.
  58. FlagFind
  59. // When this flag is set, the driver will recognize the Select key instead
  60. // of treating it as a End key.
  61. //
  62. // The Symbol key was part of the VT220 keyboard, and is no longer used in
  63. // modern day PCs.
  64. FlagSelect
  65. // When this flag is set, the driver will use Terminfo databases to
  66. // overwrite the default key sequences.
  67. FlagTerminfo
  68. // When this flag is set, the driver will preserve function keys (F13-F63)
  69. // as symbols.
  70. //
  71. // Since these keys are not part of today's standard 20th century keyboard,
  72. // we treat them as F1-F12 modifier keys i.e. ctrl/shift/alt + Fn combos.
  73. // Key definitions come from Terminfo, this flag is only useful when
  74. // FlagTerminfo is not set.
  75. FlagFKeys
  76. // When this flag is set, the driver will enable mouse mode on Windows.
  77. // This is only useful on Windows and has no effect on other platforms.
  78. FlagMouseMode
  79. )
  80. // Parser is a parser for input escape sequences.
  81. type Parser struct {
  82. flags int
  83. }
  84. // NewParser returns a new input parser. This is a low-level parser that parses
  85. // escape sequences into human-readable events.
  86. // This differs from [ansi.Parser] and [ansi.DecodeSequence] in which it
  87. // recognizes incorrect sequences that some terminals may send.
  88. //
  89. // For instance, the X10 mouse protocol sends a `CSI M` sequence followed by 3
  90. // bytes. If the parser doesn't recognize the 3 bytes, they might be echoed to
  91. // the terminal output causing a mess.
  92. //
  93. // Another example is how URxvt sends invalid sequences for modified keys using
  94. // invalid CSI final characters like '$'.
  95. //
  96. // Use flags to control the behavior of ambiguous key sequences.
  97. func NewParser(flags int) *Parser {
  98. return &Parser{flags: flags}
  99. }
  100. // parseSequence finds the first recognized event sequence and returns it along
  101. // with its length.
  102. //
  103. // It will return zero and nil no sequence is recognized or when the buffer is
  104. // empty. If a sequence is not supported, an UnknownEvent is returned.
  105. func (p *Parser) parseSequence(buf []byte) (n int, Event Event) {
  106. if len(buf) == 0 {
  107. return 0, nil
  108. }
  109. switch b := buf[0]; b {
  110. case ansi.ESC:
  111. if len(buf) == 1 {
  112. // Escape key
  113. return 1, KeyPressEvent{Code: KeyEscape}
  114. }
  115. switch bPrime := buf[1]; bPrime {
  116. case 'O': // Esc-prefixed SS3
  117. return p.parseSs3(buf)
  118. case 'P': // Esc-prefixed DCS
  119. return p.parseDcs(buf)
  120. case '[': // Esc-prefixed CSI
  121. return p.parseCsi(buf)
  122. case ']': // Esc-prefixed OSC
  123. return p.parseOsc(buf)
  124. case '_': // Esc-prefixed APC
  125. return p.parseApc(buf)
  126. case '^': // Esc-prefixed PM
  127. return p.parseStTerminated(ansi.PM, '^', nil)(buf)
  128. case 'X': // Esc-prefixed SOS
  129. return p.parseStTerminated(ansi.SOS, 'X', nil)(buf)
  130. default:
  131. n, e := p.parseSequence(buf[1:])
  132. if k, ok := e.(KeyPressEvent); ok {
  133. k.Text = ""
  134. k.Mod |= ModAlt
  135. return n + 1, k
  136. }
  137. // Not a key sequence, nor an alt modified key sequence. In that
  138. // case, just report a single escape key.
  139. return 1, KeyPressEvent{Code: KeyEscape}
  140. }
  141. case ansi.SS3:
  142. return p.parseSs3(buf)
  143. case ansi.DCS:
  144. return p.parseDcs(buf)
  145. case ansi.CSI:
  146. return p.parseCsi(buf)
  147. case ansi.OSC:
  148. return p.parseOsc(buf)
  149. case ansi.APC:
  150. return p.parseApc(buf)
  151. case ansi.PM:
  152. return p.parseStTerminated(ansi.PM, '^', nil)(buf)
  153. case ansi.SOS:
  154. return p.parseStTerminated(ansi.SOS, 'X', nil)(buf)
  155. default:
  156. if b <= ansi.US || b == ansi.DEL || b == ansi.SP {
  157. return 1, p.parseControl(b)
  158. } else if b >= ansi.PAD && b <= ansi.APC {
  159. // C1 control code
  160. // UTF-8 never starts with a C1 control code
  161. // Encode these as Ctrl+Alt+<code - 0x40>
  162. code := rune(b) - 0x40
  163. return 1, KeyPressEvent{Code: code, Mod: ModCtrl | ModAlt}
  164. }
  165. return p.parseUtf8(buf)
  166. }
  167. }
  168. func (p *Parser) parseCsi(b []byte) (int, Event) {
  169. if len(b) == 2 && b[0] == ansi.ESC {
  170. // short cut if this is an alt+[ key
  171. return 2, KeyPressEvent{Text: string(rune(b[1])), Mod: ModAlt}
  172. }
  173. var cmd ansi.Cmd
  174. var params [parser.MaxParamsSize]ansi.Param
  175. var paramsLen int
  176. var i int
  177. if b[i] == ansi.CSI || b[i] == ansi.ESC {
  178. i++
  179. }
  180. if i < len(b) && b[i-1] == ansi.ESC && b[i] == '[' {
  181. i++
  182. }
  183. // Initial CSI byte
  184. if i < len(b) && b[i] >= '<' && b[i] <= '?' {
  185. cmd |= ansi.Cmd(b[i]) << parser.PrefixShift
  186. }
  187. // Scan parameter bytes in the range 0x30-0x3F
  188. var j int
  189. for j = 0; i < len(b) && paramsLen < len(params) && b[i] >= 0x30 && b[i] <= 0x3F; i, j = i+1, j+1 {
  190. if b[i] >= '0' && b[i] <= '9' {
  191. if params[paramsLen] == parser.MissingParam {
  192. params[paramsLen] = 0
  193. }
  194. params[paramsLen] *= 10
  195. params[paramsLen] += ansi.Param(b[i]) - '0'
  196. }
  197. if b[i] == ':' {
  198. params[paramsLen] |= parser.HasMoreFlag
  199. }
  200. if b[i] == ';' || b[i] == ':' {
  201. paramsLen++
  202. if paramsLen < len(params) {
  203. // Don't overflow the params slice
  204. params[paramsLen] = parser.MissingParam
  205. }
  206. }
  207. }
  208. if j > 0 && paramsLen < len(params) {
  209. // has parameters
  210. paramsLen++
  211. }
  212. // Scan intermediate bytes in the range 0x20-0x2F
  213. var intermed byte
  214. for ; i < len(b) && b[i] >= 0x20 && b[i] <= 0x2F; i++ {
  215. intermed = b[i]
  216. }
  217. // Set the intermediate byte
  218. cmd |= ansi.Cmd(intermed) << parser.IntermedShift
  219. // Scan final byte in the range 0x40-0x7E
  220. if i >= len(b) {
  221. // Incomplete sequence
  222. return 0, nil
  223. }
  224. if b[i] < 0x40 || b[i] > 0x7E {
  225. // Special case for URxvt keys
  226. // CSI <number> $ is an invalid sequence, but URxvt uses it for
  227. // shift modified keys.
  228. if b[i-1] == '$' {
  229. n, ev := p.parseCsi(append(b[:i-1], '~'))
  230. if k, ok := ev.(KeyPressEvent); ok {
  231. k.Mod |= ModShift
  232. return n, k
  233. }
  234. }
  235. return i, UnknownEvent(b[:i-1])
  236. }
  237. // Add the final byte
  238. cmd |= ansi.Cmd(b[i])
  239. i++
  240. pa := ansi.Params(params[:paramsLen])
  241. switch cmd {
  242. case 'y' | '?'<<parser.PrefixShift | '$'<<parser.IntermedShift:
  243. // Report Mode (DECRPM)
  244. mode, _, ok := pa.Param(0, -1)
  245. if !ok || mode == -1 {
  246. break
  247. }
  248. value, _, ok := pa.Param(1, -1)
  249. if !ok || value == -1 {
  250. break
  251. }
  252. return i, ModeReportEvent{Mode: ansi.DECMode(mode), Value: ansi.ModeSetting(value)}
  253. case 'c' | '?'<<parser.PrefixShift:
  254. // Primary Device Attributes
  255. return i, parsePrimaryDevAttrs(pa)
  256. case 'u' | '?'<<parser.PrefixShift:
  257. // Kitty keyboard flags
  258. flags, _, ok := pa.Param(0, -1)
  259. if !ok || flags == -1 {
  260. break
  261. }
  262. return i, KittyEnhancementsEvent(flags)
  263. case 'R' | '?'<<parser.PrefixShift:
  264. // This report may return a third parameter representing the page
  265. // number, but we don't really need it.
  266. row, _, ok := pa.Param(0, 1)
  267. if !ok {
  268. break
  269. }
  270. col, _, ok := pa.Param(1, 1)
  271. if !ok {
  272. break
  273. }
  274. return i, CursorPositionEvent{Y: row - 1, X: col - 1}
  275. case 'm' | '<'<<parser.PrefixShift, 'M' | '<'<<parser.PrefixShift:
  276. // Handle SGR mouse
  277. if paramsLen == 3 {
  278. return i, parseSGRMouseEvent(cmd, pa)
  279. }
  280. case 'm' | '>'<<parser.PrefixShift:
  281. // XTerm modifyOtherKeys
  282. mok, _, ok := pa.Param(0, 0)
  283. if !ok || mok != 4 {
  284. break
  285. }
  286. val, _, ok := pa.Param(1, -1)
  287. if !ok || val == -1 {
  288. break
  289. }
  290. return i, ModifyOtherKeysEvent(val) //nolint:gosec
  291. case 'I':
  292. return i, FocusEvent{}
  293. case 'O':
  294. return i, BlurEvent{}
  295. case 'R':
  296. // Cursor position report OR modified F3
  297. row, _, rok := pa.Param(0, 1)
  298. col, _, cok := pa.Param(1, 1)
  299. if paramsLen == 2 && rok && cok {
  300. m := CursorPositionEvent{Y: row - 1, X: col - 1}
  301. if row == 1 && col-1 <= int(ModMeta|ModShift|ModAlt|ModCtrl) {
  302. // XXX: We cannot differentiate between cursor position report and
  303. // CSI 1 ; <mod> R (which is modified F3) when the cursor is at the
  304. // row 1. In this case, we report both messages.
  305. //
  306. // For a non ambiguous cursor position report, use
  307. // [ansi.RequestExtendedCursorPosition] (DECXCPR) instead.
  308. return i, MultiEvent{KeyPressEvent{Code: KeyF3, Mod: KeyMod(col - 1)}, m}
  309. }
  310. return i, m
  311. }
  312. if paramsLen != 0 {
  313. break
  314. }
  315. // Unmodified key F3 (CSI R)
  316. fallthrough
  317. case 'a', 'b', 'c', 'd', 'A', 'B', 'C', 'D', 'E', 'F', 'H', 'P', 'Q', 'S', 'Z':
  318. var k KeyPressEvent
  319. switch cmd {
  320. case 'a', 'b', 'c', 'd':
  321. k = KeyPressEvent{Code: KeyUp + rune(cmd-'a'), Mod: ModShift}
  322. case 'A', 'B', 'C', 'D':
  323. k = KeyPressEvent{Code: KeyUp + rune(cmd-'A')}
  324. case 'E':
  325. k = KeyPressEvent{Code: KeyBegin}
  326. case 'F':
  327. k = KeyPressEvent{Code: KeyEnd}
  328. case 'H':
  329. k = KeyPressEvent{Code: KeyHome}
  330. case 'P', 'Q', 'R', 'S':
  331. k = KeyPressEvent{Code: KeyF1 + rune(cmd-'P')}
  332. case 'Z':
  333. k = KeyPressEvent{Code: KeyTab, Mod: ModShift}
  334. }
  335. id, _, _ := pa.Param(0, 1)
  336. if id == 0 {
  337. id = 1
  338. }
  339. mod, _, _ := pa.Param(1, 1)
  340. if mod == 0 {
  341. mod = 1
  342. }
  343. if paramsLen > 1 && id == 1 && mod != -1 {
  344. // CSI 1 ; <modifiers> A
  345. k.Mod |= KeyMod(mod - 1)
  346. }
  347. // Don't forget to handle Kitty keyboard protocol
  348. return i, parseKittyKeyboardExt(pa, k)
  349. case 'M':
  350. // Handle X10 mouse
  351. if i+2 >= len(b) {
  352. // Incomplete sequence
  353. return 0, nil
  354. }
  355. // PERFORMANCE: Do not use append here, as it will allocate a new slice
  356. // for every mouse event. Instead, pass a sub-slice of the original
  357. // buffer.
  358. return i + 3, parseX10MouseEvent(b[i-1 : i+3])
  359. case 'y' | '$'<<parser.IntermedShift:
  360. // Report Mode (DECRPM)
  361. mode, _, ok := pa.Param(0, -1)
  362. if !ok || mode == -1 {
  363. break
  364. }
  365. val, _, ok := pa.Param(1, -1)
  366. if !ok || val == -1 {
  367. break
  368. }
  369. return i, ModeReportEvent{Mode: ansi.ANSIMode(mode), Value: ansi.ModeSetting(val)}
  370. case 'u':
  371. // Kitty keyboard protocol & CSI u (fixterms)
  372. if paramsLen == 0 {
  373. return i, UnknownEvent(b[:i])
  374. }
  375. return i, parseKittyKeyboard(pa)
  376. case '_':
  377. // Win32 Input Mode
  378. if paramsLen != 6 {
  379. return i, UnknownEvent(b[:i])
  380. }
  381. vrc, _, _ := pa.Param(5, 0)
  382. rc := uint16(vrc) //nolint:gosec
  383. if rc == 0 {
  384. rc = 1
  385. }
  386. vk, _, _ := pa.Param(0, 0)
  387. sc, _, _ := pa.Param(1, 0)
  388. uc, _, _ := pa.Param(2, 0)
  389. kd, _, _ := pa.Param(3, 0)
  390. cs, _, _ := pa.Param(4, 0)
  391. event := p.parseWin32InputKeyEvent(
  392. nil,
  393. uint16(vk), //nolint:gosec // Vk wVirtualKeyCode
  394. uint16(sc), //nolint:gosec // Sc wVirtualScanCode
  395. rune(uc), // Uc UnicodeChar
  396. kd == 1, // Kd bKeyDown
  397. uint32(cs), //nolint:gosec // Cs dwControlKeyState
  398. rc, // Rc wRepeatCount
  399. )
  400. if event == nil {
  401. return i, UnknownEvent(b[:])
  402. }
  403. return i, event
  404. case '@', '^', '~':
  405. if paramsLen == 0 {
  406. return i, UnknownEvent(b[:i])
  407. }
  408. param, _, _ := pa.Param(0, 0)
  409. switch cmd {
  410. case '~':
  411. switch param {
  412. case 27:
  413. // XTerm modifyOtherKeys 2
  414. if paramsLen != 3 {
  415. return i, UnknownEvent(b[:i])
  416. }
  417. return i, parseXTermModifyOtherKeys(pa)
  418. case 200:
  419. // bracketed-paste start
  420. return i, PasteStartEvent{}
  421. case 201:
  422. // bracketed-paste end
  423. return i, PasteEndEvent{}
  424. }
  425. }
  426. switch param {
  427. case 1, 2, 3, 4, 5, 6, 7, 8,
  428. 11, 12, 13, 14, 15,
  429. 17, 18, 19, 20, 21,
  430. 23, 24, 25, 26,
  431. 28, 29, 31, 32, 33, 34:
  432. var k KeyPressEvent
  433. switch param {
  434. case 1:
  435. if p.flags&FlagFind != 0 {
  436. k = KeyPressEvent{Code: KeyFind}
  437. } else {
  438. k = KeyPressEvent{Code: KeyHome}
  439. }
  440. case 2:
  441. k = KeyPressEvent{Code: KeyInsert}
  442. case 3:
  443. k = KeyPressEvent{Code: KeyDelete}
  444. case 4:
  445. if p.flags&FlagSelect != 0 {
  446. k = KeyPressEvent{Code: KeySelect}
  447. } else {
  448. k = KeyPressEvent{Code: KeyEnd}
  449. }
  450. case 5:
  451. k = KeyPressEvent{Code: KeyPgUp}
  452. case 6:
  453. k = KeyPressEvent{Code: KeyPgDown}
  454. case 7:
  455. k = KeyPressEvent{Code: KeyHome}
  456. case 8:
  457. k = KeyPressEvent{Code: KeyEnd}
  458. case 11, 12, 13, 14, 15:
  459. k = KeyPressEvent{Code: KeyF1 + rune(param-11)}
  460. case 17, 18, 19, 20, 21:
  461. k = KeyPressEvent{Code: KeyF6 + rune(param-17)}
  462. case 23, 24, 25, 26:
  463. k = KeyPressEvent{Code: KeyF11 + rune(param-23)}
  464. case 28, 29:
  465. k = KeyPressEvent{Code: KeyF15 + rune(param-28)}
  466. case 31, 32, 33, 34:
  467. k = KeyPressEvent{Code: KeyF17 + rune(param-31)}
  468. }
  469. // modifiers
  470. mod, _, _ := pa.Param(1, -1)
  471. if paramsLen > 1 && mod != -1 {
  472. k.Mod |= KeyMod(mod - 1)
  473. }
  474. // Handle URxvt weird keys
  475. switch cmd {
  476. case '~':
  477. // Don't forget to handle Kitty keyboard protocol
  478. return i, parseKittyKeyboardExt(pa, k)
  479. case '^':
  480. k.Mod |= ModCtrl
  481. case '@':
  482. k.Mod |= ModCtrl | ModShift
  483. }
  484. return i, k
  485. }
  486. case 't':
  487. param, _, ok := pa.Param(0, 0)
  488. if !ok {
  489. break
  490. }
  491. var winop WindowOpEvent
  492. winop.Op = param
  493. for j := 1; j < paramsLen; j++ {
  494. val, _, ok := pa.Param(j, 0)
  495. if ok {
  496. winop.Args = append(winop.Args, val)
  497. }
  498. }
  499. return i, winop
  500. }
  501. return i, UnknownEvent(b[:i])
  502. }
  503. // parseSs3 parses a SS3 sequence.
  504. // See https://vt100.net/docs/vt220-rm/chapter4.html#S4.4.4.2
  505. func (p *Parser) parseSs3(b []byte) (int, Event) {
  506. if len(b) == 2 && b[0] == ansi.ESC {
  507. // short cut if this is an alt+O key
  508. return 2, KeyPressEvent{Code: rune(b[1]), Mod: ModAlt}
  509. }
  510. var i int
  511. if b[i] == ansi.SS3 || b[i] == ansi.ESC {
  512. i++
  513. }
  514. if i < len(b) && b[i-1] == ansi.ESC && b[i] == 'O' {
  515. i++
  516. }
  517. // Scan numbers from 0-9
  518. var mod int
  519. for ; i < len(b) && b[i] >= '0' && b[i] <= '9'; i++ {
  520. mod *= 10
  521. mod += int(b[i]) - '0'
  522. }
  523. // Scan a GL character
  524. // A GL character is a single byte in the range 0x21-0x7E
  525. // See https://vt100.net/docs/vt220-rm/chapter2.html#S2.3.2
  526. if i >= len(b) {
  527. // Incomplete sequence
  528. return 0, nil
  529. }
  530. if b[i] < 0x21 || b[i] > 0x7E {
  531. return i, UnknownEvent(b[:i])
  532. }
  533. // GL character(s)
  534. gl := b[i]
  535. i++
  536. var k KeyPressEvent
  537. switch gl {
  538. case 'a', 'b', 'c', 'd':
  539. k = KeyPressEvent{Code: KeyUp + rune(gl-'a'), Mod: ModCtrl}
  540. case 'A', 'B', 'C', 'D':
  541. k = KeyPressEvent{Code: KeyUp + rune(gl-'A')}
  542. case 'E':
  543. k = KeyPressEvent{Code: KeyBegin}
  544. case 'F':
  545. k = KeyPressEvent{Code: KeyEnd}
  546. case 'H':
  547. k = KeyPressEvent{Code: KeyHome}
  548. case 'P', 'Q', 'R', 'S':
  549. k = KeyPressEvent{Code: KeyF1 + rune(gl-'P')}
  550. case 'M':
  551. k = KeyPressEvent{Code: KeyKpEnter}
  552. case 'X':
  553. k = KeyPressEvent{Code: KeyKpEqual}
  554. case 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y':
  555. k = KeyPressEvent{Code: KeyKpMultiply + rune(gl-'j')}
  556. default:
  557. return i, UnknownEvent(b[:i])
  558. }
  559. // Handle weird SS3 <modifier> Func
  560. if mod > 0 {
  561. k.Mod |= KeyMod(mod - 1)
  562. }
  563. return i, k
  564. }
  565. func (p *Parser) parseOsc(b []byte) (int, Event) {
  566. defaultKey := func() KeyPressEvent {
  567. return KeyPressEvent{Code: rune(b[1]), Mod: ModAlt}
  568. }
  569. if len(b) == 2 && b[0] == ansi.ESC {
  570. // short cut if this is an alt+] key
  571. return 2, defaultKey()
  572. }
  573. var i int
  574. if b[i] == ansi.OSC || b[i] == ansi.ESC {
  575. i++
  576. }
  577. if i < len(b) && b[i-1] == ansi.ESC && b[i] == ']' {
  578. i++
  579. }
  580. // Parse OSC command
  581. // An OSC sequence is terminated by a BEL, ESC, or ST character
  582. var start, end int
  583. cmd := -1
  584. for ; i < len(b) && b[i] >= '0' && b[i] <= '9'; i++ {
  585. if cmd == -1 {
  586. cmd = 0
  587. } else {
  588. cmd *= 10
  589. }
  590. cmd += int(b[i]) - '0'
  591. }
  592. if i < len(b) && b[i] == ';' {
  593. // mark the start of the sequence data
  594. i++
  595. start = i
  596. }
  597. for ; i < len(b); i++ {
  598. // advance to the end of the sequence
  599. if slices.Contains([]byte{ansi.BEL, ansi.ESC, ansi.ST, ansi.CAN, ansi.SUB}, b[i]) {
  600. break
  601. }
  602. }
  603. if i >= len(b) {
  604. // Incomplete sequence
  605. return 0, nil
  606. }
  607. end = i // end of the sequence data
  608. i++
  609. // Check 7-bit ST (string terminator) character
  610. switch b[i-1] {
  611. case ansi.CAN, ansi.SUB:
  612. return i, UnknownEvent(b[:i])
  613. case ansi.ESC:
  614. if i >= len(b) || b[i] != '\\' {
  615. if cmd == -1 || (start == 0 && end == 2) {
  616. return 2, defaultKey()
  617. }
  618. // If we don't have a valid ST terminator, then this is a
  619. // cancelled sequence and should be ignored.
  620. return i, UnknownEvent(b[:i])
  621. }
  622. i++
  623. }
  624. if end <= start {
  625. return i, UnknownEvent(b[:i])
  626. }
  627. // PERFORMANCE: Only allocate the data string if we know we have a handler
  628. // for the command. This avoids allocations for unknown OSC sequences that
  629. // can be sent in high frequency by trackpads.
  630. switch cmd {
  631. case 10, 11, 12:
  632. data := string(b[start:end])
  633. color := ansi.XParseColor(data)
  634. switch cmd {
  635. case 10:
  636. return i, ForegroundColorEvent{color}
  637. case 11:
  638. return i, BackgroundColorEvent{color}
  639. case 12:
  640. return i, CursorColorEvent{color}
  641. }
  642. case 52:
  643. data := string(b[start:end])
  644. parts := strings.Split(data, ";")
  645. if len(parts) == 0 {
  646. return i, ClipboardEvent{}
  647. }
  648. if len(parts) != 2 || len(parts[0]) < 1 {
  649. break
  650. }
  651. b64 := parts[1]
  652. bts, err := base64.StdEncoding.DecodeString(b64)
  653. if err != nil {
  654. break
  655. }
  656. sel := ClipboardSelection(parts[0][0]) //nolint:unconvert
  657. return i, ClipboardEvent{Selection: sel, Content: string(bts)}
  658. }
  659. return i, UnknownEvent(b[:i])
  660. }
  661. // parseStTerminated parses a control sequence that gets terminated by a ST character.
  662. func (p *Parser) parseStTerminated(
  663. intro8, intro7 byte,
  664. fn func([]byte) Event,
  665. ) func([]byte) (int, Event) {
  666. defaultKey := func(b []byte) (int, Event) {
  667. switch intro8 {
  668. case ansi.SOS:
  669. return 2, KeyPressEvent{Code: 'x', Mod: ModShift | ModAlt}
  670. case ansi.PM, ansi.APC:
  671. return 2, KeyPressEvent{Code: rune(b[1]), Mod: ModAlt}
  672. }
  673. return 0, nil
  674. }
  675. return func(b []byte) (int, Event) {
  676. if len(b) == 2 && b[0] == ansi.ESC {
  677. return defaultKey(b)
  678. }
  679. var i int
  680. if b[i] == intro8 || b[i] == ansi.ESC {
  681. i++
  682. }
  683. if i < len(b) && b[i-1] == ansi.ESC && b[i] == intro7 {
  684. i++
  685. }
  686. // Scan control sequence
  687. // Most common control sequence is terminated by a ST character
  688. // ST is a 7-bit string terminator character is (ESC \)
  689. start := i
  690. for ; i < len(b); i++ {
  691. if slices.Contains([]byte{ansi.ESC, ansi.ST, ansi.CAN, ansi.SUB}, b[i]) {
  692. break
  693. }
  694. }
  695. if i >= len(b) {
  696. // Incomplete sequence
  697. return 0, nil
  698. }
  699. end := i // end of the sequence data
  700. i++
  701. // Check 7-bit ST (string terminator) character
  702. switch b[i-1] {
  703. case ansi.CAN, ansi.SUB:
  704. return i, UnknownEvent(b[:i])
  705. case ansi.ESC:
  706. if i >= len(b) || b[i] != '\\' {
  707. if start == end {
  708. return defaultKey(b)
  709. }
  710. // If we don't have a valid ST terminator, then this is a
  711. // cancelled sequence and should be ignored.
  712. return i, UnknownEvent(b[:i])
  713. }
  714. i++
  715. }
  716. // Call the function to parse the sequence and return the result
  717. if fn != nil {
  718. if e := fn(b[start:end]); e != nil {
  719. return i, e
  720. }
  721. }
  722. return i, UnknownEvent(b[:i])
  723. }
  724. }
  725. func (p *Parser) parseDcs(b []byte) (int, Event) {
  726. if len(b) == 2 && b[0] == ansi.ESC {
  727. // short cut if this is an alt+P key
  728. return 2, KeyPressEvent{Code: 'p', Mod: ModShift | ModAlt}
  729. }
  730. var params [16]ansi.Param
  731. var paramsLen int
  732. var cmd ansi.Cmd
  733. // DCS sequences are introduced by DCS (0x90) or ESC P (0x1b 0x50)
  734. var i int
  735. if b[i] == ansi.DCS || b[i] == ansi.ESC {
  736. i++
  737. }
  738. if i < len(b) && b[i-1] == ansi.ESC && b[i] == 'P' {
  739. i++
  740. }
  741. // initial DCS byte
  742. if i < len(b) && b[i] >= '<' && b[i] <= '?' {
  743. cmd |= ansi.Cmd(b[i]) << parser.PrefixShift
  744. }
  745. // Scan parameter bytes in the range 0x30-0x3F
  746. var j int
  747. for j = 0; i < len(b) && paramsLen < len(params) && b[i] >= 0x30 && b[i] <= 0x3F; i, j = i+1, j+1 {
  748. if b[i] >= '0' && b[i] <= '9' {
  749. if params[paramsLen] == parser.MissingParam {
  750. params[paramsLen] = 0
  751. }
  752. params[paramsLen] *= 10
  753. params[paramsLen] += ansi.Param(b[i]) - '0'
  754. }
  755. if b[i] == ':' {
  756. params[paramsLen] |= parser.HasMoreFlag
  757. }
  758. if b[i] == ';' || b[i] == ':' {
  759. paramsLen++
  760. if paramsLen < len(params) {
  761. // Don't overflow the params slice
  762. params[paramsLen] = parser.MissingParam
  763. }
  764. }
  765. }
  766. if j > 0 && paramsLen < len(params) {
  767. // has parameters
  768. paramsLen++
  769. }
  770. // Scan intermediate bytes in the range 0x20-0x2F
  771. var intermed byte
  772. for j := 0; i < len(b) && b[i] >= 0x20 && b[i] <= 0x2F; i, j = i+1, j+1 {
  773. intermed = b[i]
  774. }
  775. // set intermediate byte
  776. cmd |= ansi.Cmd(intermed) << parser.IntermedShift
  777. // Scan final byte in the range 0x40-0x7E
  778. if i >= len(b) {
  779. // Incomplete sequence
  780. return 0, nil
  781. }
  782. if b[i] < 0x40 || b[i] > 0x7E {
  783. return i, UnknownEvent(b[:i])
  784. }
  785. // Add the final byte
  786. cmd |= ansi.Cmd(b[i])
  787. i++
  788. start := i // start of the sequence data
  789. for ; i < len(b); i++ {
  790. if b[i] == ansi.ST || b[i] == ansi.ESC {
  791. break
  792. }
  793. }
  794. if i >= len(b) {
  795. // Incomplete sequence
  796. return 0, nil
  797. }
  798. end := i // end of the sequence data
  799. i++
  800. // Check 7-bit ST (string terminator) character
  801. if i < len(b) && b[i-1] == ansi.ESC && b[i] == '\\' {
  802. i++
  803. }
  804. pa := ansi.Params(params[:paramsLen])
  805. switch cmd {
  806. case 'r' | '+'<<parser.IntermedShift:
  807. // XTGETTCAP responses
  808. param, _, _ := pa.Param(0, 0)
  809. switch param {
  810. case 1: // 1 means valid response, 0 means invalid response
  811. tc := parseTermcap(b[start:end])
  812. // XXX: some terminals like KiTTY report invalid responses with
  813. // their queries i.e. sending a query for "Tc" using "\x1bP+q5463\x1b\\"
  814. // returns "\x1bP0+r5463\x1b\\".
  815. // The specs says that invalid responses should be in the form of
  816. // DCS 0 + r ST "\x1bP0+r\x1b\\"
  817. // We ignore invalid responses and only send valid ones to the program.
  818. //
  819. // See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
  820. return i, tc
  821. }
  822. case '|' | '>'<<parser.PrefixShift:
  823. // XTVersion response
  824. return i, TerminalVersionEvent(b[start:end])
  825. }
  826. return i, UnknownEvent(b[:i])
  827. }
  828. func (p *Parser) parseApc(b []byte) (int, Event) {
  829. if len(b) == 2 && b[0] == ansi.ESC {
  830. // short cut if this is an alt+_ key
  831. return 2, KeyPressEvent{Code: rune(b[1]), Mod: ModAlt}
  832. }
  833. // APC sequences are introduced by APC (0x9f) or ESC _ (0x1b 0x5f)
  834. return p.parseStTerminated(ansi.APC, '_', func(b []byte) Event {
  835. if len(b) == 0 {
  836. return nil
  837. }
  838. switch b[0] {
  839. case 'G': // Kitty Graphics Protocol
  840. var g KittyGraphicsEvent
  841. parts := bytes.Split(b[1:], []byte{';'})
  842. g.Options.UnmarshalText(parts[0]) //nolint:errcheck,gosec
  843. if len(parts) > 1 {
  844. g.Payload = parts[1]
  845. }
  846. return g
  847. }
  848. return nil
  849. })(b)
  850. }
  851. func (p *Parser) parseUtf8(b []byte) (int, Event) {
  852. if len(b) == 0 {
  853. return 0, nil
  854. }
  855. c := b[0]
  856. if c <= ansi.US || c == ansi.DEL || c == ansi.SP {
  857. // Control codes get handled by parseControl
  858. return 1, p.parseControl(c)
  859. } else if c > ansi.US && c < ansi.DEL {
  860. // ASCII printable characters
  861. code := rune(c)
  862. k := KeyPressEvent{Code: code, Text: string(code)}
  863. if unicode.IsUpper(code) {
  864. // Convert upper case letters to lower case + shift modifier
  865. k.Code = unicode.ToLower(code)
  866. k.ShiftedCode = code
  867. k.Mod |= ModShift
  868. }
  869. return 1, k
  870. }
  871. code, _ := utf8.DecodeRune(b)
  872. if code == utf8.RuneError {
  873. return 1, UnknownEvent(b[0])
  874. }
  875. cluster, _, _, _ := uniseg.FirstGraphemeCluster(b, -1)
  876. // PERFORMANCE: Use RuneCount to check for multi-rune graphemes instead of
  877. // looping over the string representation.
  878. if utf8.RuneCount(cluster) > 1 {
  879. code = KeyExtended
  880. }
  881. return len(cluster), KeyPressEvent{Code: code, Text: string(cluster)}
  882. }
  883. func (p *Parser) parseControl(b byte) Event {
  884. switch b {
  885. case ansi.NUL:
  886. if p.flags&FlagCtrlAt != 0 {
  887. return KeyPressEvent{Code: '@', Mod: ModCtrl}
  888. }
  889. return KeyPressEvent{Code: KeySpace, Mod: ModCtrl}
  890. case ansi.BS:
  891. return KeyPressEvent{Code: 'h', Mod: ModCtrl}
  892. case ansi.HT:
  893. if p.flags&FlagCtrlI != 0 {
  894. return KeyPressEvent{Code: 'i', Mod: ModCtrl}
  895. }
  896. return KeyPressEvent{Code: KeyTab}
  897. case ansi.CR:
  898. if p.flags&FlagCtrlM != 0 {
  899. return KeyPressEvent{Code: 'm', Mod: ModCtrl}
  900. }
  901. return KeyPressEvent{Code: KeyEnter}
  902. case ansi.ESC:
  903. if p.flags&FlagCtrlOpenBracket != 0 {
  904. return KeyPressEvent{Code: '[', Mod: ModCtrl}
  905. }
  906. return KeyPressEvent{Code: KeyEscape}
  907. case ansi.DEL:
  908. if p.flags&FlagBackspace != 0 {
  909. return KeyPressEvent{Code: KeyDelete}
  910. }
  911. return KeyPressEvent{Code: KeyBackspace}
  912. case ansi.SP:
  913. return KeyPressEvent{Code: KeySpace, Text: " "}
  914. default:
  915. if b >= ansi.SOH && b <= ansi.SUB {
  916. // Use lower case letters for control codes
  917. code := rune(b + 0x60)
  918. return KeyPressEvent{Code: code, Mod: ModCtrl}
  919. } else if b >= ansi.FS && b <= ansi.US {
  920. code := rune(b + 0x40)
  921. return KeyPressEvent{Code: code, Mod: ModCtrl}
  922. }
  923. return UnknownEvent(b)
  924. }
  925. }