parse.go 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  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. pa = pa[:3]
  279. return i, parseSGRMouseEvent(cmd, pa)
  280. }
  281. case 'm' | '>'<<parser.PrefixShift:
  282. // XTerm modifyOtherKeys
  283. mok, _, ok := pa.Param(0, 0)
  284. if !ok || mok != 4 {
  285. break
  286. }
  287. val, _, ok := pa.Param(1, -1)
  288. if !ok || val == -1 {
  289. break
  290. }
  291. return i, ModifyOtherKeysEvent(val) //nolint:gosec
  292. case 'I':
  293. return i, FocusEvent{}
  294. case 'O':
  295. return i, BlurEvent{}
  296. case 'R':
  297. // Cursor position report OR modified F3
  298. row, _, rok := pa.Param(0, 1)
  299. col, _, cok := pa.Param(1, 1)
  300. if paramsLen == 2 && rok && cok {
  301. m := CursorPositionEvent{Y: row - 1, X: col - 1}
  302. if row == 1 && col-1 <= int(ModMeta|ModShift|ModAlt|ModCtrl) {
  303. // XXX: We cannot differentiate between cursor position report and
  304. // CSI 1 ; <mod> R (which is modified F3) when the cursor is at the
  305. // row 1. In this case, we report both messages.
  306. //
  307. // For a non ambiguous cursor position report, use
  308. // [ansi.RequestExtendedCursorPosition] (DECXCPR) instead.
  309. return i, MultiEvent{KeyPressEvent{Code: KeyF3, Mod: KeyMod(col - 1)}, m}
  310. }
  311. return i, m
  312. }
  313. if paramsLen != 0 {
  314. break
  315. }
  316. // Unmodified key F3 (CSI R)
  317. fallthrough
  318. case 'a', 'b', 'c', 'd', 'A', 'B', 'C', 'D', 'E', 'F', 'H', 'P', 'Q', 'S', 'Z':
  319. var k KeyPressEvent
  320. switch cmd {
  321. case 'a', 'b', 'c', 'd':
  322. k = KeyPressEvent{Code: KeyUp + rune(cmd-'a'), Mod: ModShift}
  323. case 'A', 'B', 'C', 'D':
  324. k = KeyPressEvent{Code: KeyUp + rune(cmd-'A')}
  325. case 'E':
  326. k = KeyPressEvent{Code: KeyBegin}
  327. case 'F':
  328. k = KeyPressEvent{Code: KeyEnd}
  329. case 'H':
  330. k = KeyPressEvent{Code: KeyHome}
  331. case 'P', 'Q', 'R', 'S':
  332. k = KeyPressEvent{Code: KeyF1 + rune(cmd-'P')}
  333. case 'Z':
  334. k = KeyPressEvent{Code: KeyTab, Mod: ModShift}
  335. }
  336. id, _, _ := pa.Param(0, 1)
  337. if id == 0 {
  338. id = 1
  339. }
  340. mod, _, _ := pa.Param(1, 1)
  341. if mod == 0 {
  342. mod = 1
  343. }
  344. if paramsLen > 1 && id == 1 && mod != -1 {
  345. // CSI 1 ; <modifiers> A
  346. k.Mod |= KeyMod(mod - 1)
  347. }
  348. // Don't forget to handle Kitty keyboard protocol
  349. return i, parseKittyKeyboardExt(pa, k)
  350. case 'M':
  351. // Handle X10 mouse
  352. if i+2 >= len(b) {
  353. // Incomplete sequence
  354. return 0, nil
  355. }
  356. // PERFORMANCE: Do not use append here, as it will allocate a new slice
  357. // for every mouse event. Instead, pass a sub-slice of the original
  358. // buffer.
  359. return i + 3, parseX10MouseEvent(b[i-1 : i+3])
  360. case 'y' | '$'<<parser.IntermedShift:
  361. // Report Mode (DECRPM)
  362. mode, _, ok := pa.Param(0, -1)
  363. if !ok || mode == -1 {
  364. break
  365. }
  366. val, _, ok := pa.Param(1, -1)
  367. if !ok || val == -1 {
  368. break
  369. }
  370. return i, ModeReportEvent{Mode: ansi.ANSIMode(mode), Value: ansi.ModeSetting(val)}
  371. case 'u':
  372. // Kitty keyboard protocol & CSI u (fixterms)
  373. if paramsLen == 0 {
  374. return i, UnknownEvent(b[:i])
  375. }
  376. return i, parseKittyKeyboard(pa)
  377. case '_':
  378. // Win32 Input Mode
  379. if paramsLen != 6 {
  380. return i, UnknownEvent(b[:i])
  381. }
  382. vrc, _, _ := pa.Param(5, 0)
  383. rc := uint16(vrc) //nolint:gosec
  384. if rc == 0 {
  385. rc = 1
  386. }
  387. vk, _, _ := pa.Param(0, 0)
  388. sc, _, _ := pa.Param(1, 0)
  389. uc, _, _ := pa.Param(2, 0)
  390. kd, _, _ := pa.Param(3, 0)
  391. cs, _, _ := pa.Param(4, 0)
  392. event := p.parseWin32InputKeyEvent(
  393. nil,
  394. uint16(vk), //nolint:gosec // Vk wVirtualKeyCode
  395. uint16(sc), //nolint:gosec // Sc wVirtualScanCode
  396. rune(uc), // Uc UnicodeChar
  397. kd == 1, // Kd bKeyDown
  398. uint32(cs), //nolint:gosec // Cs dwControlKeyState
  399. rc, // Rc wRepeatCount
  400. )
  401. if event == nil {
  402. return i, UnknownEvent(b[:])
  403. }
  404. return i, event
  405. case '@', '^', '~':
  406. if paramsLen == 0 {
  407. return i, UnknownEvent(b[:i])
  408. }
  409. param, _, _ := pa.Param(0, 0)
  410. switch cmd {
  411. case '~':
  412. switch param {
  413. case 27:
  414. // XTerm modifyOtherKeys 2
  415. if paramsLen != 3 {
  416. return i, UnknownEvent(b[:i])
  417. }
  418. return i, parseXTermModifyOtherKeys(pa)
  419. case 200:
  420. // bracketed-paste start
  421. return i, PasteStartEvent{}
  422. case 201:
  423. // bracketed-paste end
  424. return i, PasteEndEvent{}
  425. }
  426. }
  427. switch param {
  428. case 1, 2, 3, 4, 5, 6, 7, 8,
  429. 11, 12, 13, 14, 15,
  430. 17, 18, 19, 20, 21,
  431. 23, 24, 25, 26,
  432. 28, 29, 31, 32, 33, 34:
  433. var k KeyPressEvent
  434. switch param {
  435. case 1:
  436. if p.flags&FlagFind != 0 {
  437. k = KeyPressEvent{Code: KeyFind}
  438. } else {
  439. k = KeyPressEvent{Code: KeyHome}
  440. }
  441. case 2:
  442. k = KeyPressEvent{Code: KeyInsert}
  443. case 3:
  444. k = KeyPressEvent{Code: KeyDelete}
  445. case 4:
  446. if p.flags&FlagSelect != 0 {
  447. k = KeyPressEvent{Code: KeySelect}
  448. } else {
  449. k = KeyPressEvent{Code: KeyEnd}
  450. }
  451. case 5:
  452. k = KeyPressEvent{Code: KeyPgUp}
  453. case 6:
  454. k = KeyPressEvent{Code: KeyPgDown}
  455. case 7:
  456. k = KeyPressEvent{Code: KeyHome}
  457. case 8:
  458. k = KeyPressEvent{Code: KeyEnd}
  459. case 11, 12, 13, 14, 15:
  460. k = KeyPressEvent{Code: KeyF1 + rune(param-11)}
  461. case 17, 18, 19, 20, 21:
  462. k = KeyPressEvent{Code: KeyF6 + rune(param-17)}
  463. case 23, 24, 25, 26:
  464. k = KeyPressEvent{Code: KeyF11 + rune(param-23)}
  465. case 28, 29:
  466. k = KeyPressEvent{Code: KeyF15 + rune(param-28)}
  467. case 31, 32, 33, 34:
  468. k = KeyPressEvent{Code: KeyF17 + rune(param-31)}
  469. }
  470. // modifiers
  471. mod, _, _ := pa.Param(1, -1)
  472. if paramsLen > 1 && mod != -1 {
  473. k.Mod |= KeyMod(mod - 1)
  474. }
  475. // Handle URxvt weird keys
  476. switch cmd {
  477. case '~':
  478. // Don't forget to handle Kitty keyboard protocol
  479. return i, parseKittyKeyboardExt(pa, k)
  480. case '^':
  481. k.Mod |= ModCtrl
  482. case '@':
  483. k.Mod |= ModCtrl | ModShift
  484. }
  485. return i, k
  486. }
  487. case 't':
  488. param, _, ok := pa.Param(0, 0)
  489. if !ok {
  490. break
  491. }
  492. var winop WindowOpEvent
  493. winop.Op = param
  494. for j := 1; j < paramsLen; j++ {
  495. val, _, ok := pa.Param(j, 0)
  496. if ok {
  497. winop.Args = append(winop.Args, val)
  498. }
  499. }
  500. return i, winop
  501. }
  502. return i, UnknownEvent(b[:i])
  503. }
  504. // parseSs3 parses a SS3 sequence.
  505. // See https://vt100.net/docs/vt220-rm/chapter4.html#S4.4.4.2
  506. func (p *Parser) parseSs3(b []byte) (int, Event) {
  507. if len(b) == 2 && b[0] == ansi.ESC {
  508. // short cut if this is an alt+O key
  509. return 2, KeyPressEvent{Code: rune(b[1]), Mod: ModAlt}
  510. }
  511. var i int
  512. if b[i] == ansi.SS3 || b[i] == ansi.ESC {
  513. i++
  514. }
  515. if i < len(b) && b[i-1] == ansi.ESC && b[i] == 'O' {
  516. i++
  517. }
  518. // Scan numbers from 0-9
  519. var mod int
  520. for ; i < len(b) && b[i] >= '0' && b[i] <= '9'; i++ {
  521. mod *= 10
  522. mod += int(b[i]) - '0'
  523. }
  524. // Scan a GL character
  525. // A GL character is a single byte in the range 0x21-0x7E
  526. // See https://vt100.net/docs/vt220-rm/chapter2.html#S2.3.2
  527. if i >= len(b) {
  528. // Incomplete sequence
  529. return 0, nil
  530. }
  531. if b[i] < 0x21 || b[i] > 0x7E {
  532. return i, UnknownEvent(b[:i])
  533. }
  534. // GL character(s)
  535. gl := b[i]
  536. i++
  537. var k KeyPressEvent
  538. switch gl {
  539. case 'a', 'b', 'c', 'd':
  540. k = KeyPressEvent{Code: KeyUp + rune(gl-'a'), Mod: ModCtrl}
  541. case 'A', 'B', 'C', 'D':
  542. k = KeyPressEvent{Code: KeyUp + rune(gl-'A')}
  543. case 'E':
  544. k = KeyPressEvent{Code: KeyBegin}
  545. case 'F':
  546. k = KeyPressEvent{Code: KeyEnd}
  547. case 'H':
  548. k = KeyPressEvent{Code: KeyHome}
  549. case 'P', 'Q', 'R', 'S':
  550. k = KeyPressEvent{Code: KeyF1 + rune(gl-'P')}
  551. case 'M':
  552. k = KeyPressEvent{Code: KeyKpEnter}
  553. case 'X':
  554. k = KeyPressEvent{Code: KeyKpEqual}
  555. case 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y':
  556. k = KeyPressEvent{Code: KeyKpMultiply + rune(gl-'j')}
  557. default:
  558. return i, UnknownEvent(b[:i])
  559. }
  560. // Handle weird SS3 <modifier> Func
  561. if mod > 0 {
  562. k.Mod |= KeyMod(mod - 1)
  563. }
  564. return i, k
  565. }
  566. func (p *Parser) parseOsc(b []byte) (int, Event) {
  567. defaultKey := func() KeyPressEvent {
  568. return KeyPressEvent{Code: rune(b[1]), Mod: ModAlt}
  569. }
  570. if len(b) == 2 && b[0] == ansi.ESC {
  571. // short cut if this is an alt+] key
  572. return 2, defaultKey()
  573. }
  574. var i int
  575. if b[i] == ansi.OSC || b[i] == ansi.ESC {
  576. i++
  577. }
  578. if i < len(b) && b[i-1] == ansi.ESC && b[i] == ']' {
  579. i++
  580. }
  581. // Parse OSC command
  582. // An OSC sequence is terminated by a BEL, ESC, or ST character
  583. var start, end int
  584. cmd := -1
  585. for ; i < len(b) && b[i] >= '0' && b[i] <= '9'; i++ {
  586. if cmd == -1 {
  587. cmd = 0
  588. } else {
  589. cmd *= 10
  590. }
  591. cmd += int(b[i]) - '0'
  592. }
  593. if i < len(b) && b[i] == ';' {
  594. // mark the start of the sequence data
  595. i++
  596. start = i
  597. }
  598. for ; i < len(b); i++ {
  599. // advance to the end of the sequence
  600. if slices.Contains([]byte{ansi.BEL, ansi.ESC, ansi.ST, ansi.CAN, ansi.SUB}, b[i]) {
  601. break
  602. }
  603. }
  604. if i >= len(b) {
  605. // Incomplete sequence
  606. return 0, nil
  607. }
  608. end = i // end of the sequence data
  609. i++
  610. // Check 7-bit ST (string terminator) character
  611. switch b[i-1] {
  612. case ansi.CAN, ansi.SUB:
  613. return i, UnknownEvent(b[:i])
  614. case ansi.ESC:
  615. if i >= len(b) || b[i] != '\\' {
  616. if cmd == -1 || (start == 0 && end == 2) {
  617. return 2, defaultKey()
  618. }
  619. // If we don't have a valid ST terminator, then this is a
  620. // cancelled sequence and should be ignored.
  621. return i, UnknownEvent(b[:i])
  622. }
  623. i++
  624. }
  625. if end <= start {
  626. return i, UnknownEvent(b[:i])
  627. }
  628. // PERFORMANCE: Only allocate the data string if we know we have a handler
  629. // for the command. This avoids allocations for unknown OSC sequences that
  630. // can be sent in high frequency by trackpads.
  631. switch cmd {
  632. case 10, 11, 12:
  633. data := string(b[start:end])
  634. color := ansi.XParseColor(data)
  635. switch cmd {
  636. case 10:
  637. return i, ForegroundColorEvent{color}
  638. case 11:
  639. return i, BackgroundColorEvent{color}
  640. case 12:
  641. return i, CursorColorEvent{color}
  642. }
  643. case 52:
  644. data := string(b[start:end])
  645. parts := strings.Split(data, ";")
  646. if len(parts) == 0 {
  647. return i, ClipboardEvent{}
  648. }
  649. if len(parts) != 2 || len(parts[0]) < 1 {
  650. break
  651. }
  652. b64 := parts[1]
  653. bts, err := base64.StdEncoding.DecodeString(b64)
  654. if err != nil {
  655. break
  656. }
  657. sel := ClipboardSelection(parts[0][0]) //nolint:unconvert
  658. return i, ClipboardEvent{Selection: sel, Content: string(bts)}
  659. }
  660. return i, UnknownEvent(b[:i])
  661. }
  662. // parseStTerminated parses a control sequence that gets terminated by a ST character.
  663. func (p *Parser) parseStTerminated(
  664. intro8, intro7 byte,
  665. fn func([]byte) Event,
  666. ) func([]byte) (int, Event) {
  667. defaultKey := func(b []byte) (int, Event) {
  668. switch intro8 {
  669. case ansi.SOS:
  670. return 2, KeyPressEvent{Code: 'x', Mod: ModShift | ModAlt}
  671. case ansi.PM, ansi.APC:
  672. return 2, KeyPressEvent{Code: rune(b[1]), Mod: ModAlt}
  673. }
  674. return 0, nil
  675. }
  676. return func(b []byte) (int, Event) {
  677. if len(b) == 2 && b[0] == ansi.ESC {
  678. return defaultKey(b)
  679. }
  680. var i int
  681. if b[i] == intro8 || b[i] == ansi.ESC {
  682. i++
  683. }
  684. if i < len(b) && b[i-1] == ansi.ESC && b[i] == intro7 {
  685. i++
  686. }
  687. // Scan control sequence
  688. // Most common control sequence is terminated by a ST character
  689. // ST is a 7-bit string terminator character is (ESC \)
  690. start := i
  691. for ; i < len(b); i++ {
  692. if slices.Contains([]byte{ansi.ESC, ansi.ST, ansi.CAN, ansi.SUB}, b[i]) {
  693. break
  694. }
  695. }
  696. if i >= len(b) {
  697. // Incomplete sequence
  698. return 0, nil
  699. }
  700. end := i // end of the sequence data
  701. i++
  702. // Check 7-bit ST (string terminator) character
  703. switch b[i-1] {
  704. case ansi.CAN, ansi.SUB:
  705. return i, UnknownEvent(b[:i])
  706. case ansi.ESC:
  707. if i >= len(b) || b[i] != '\\' {
  708. if start == end {
  709. return defaultKey(b)
  710. }
  711. // If we don't have a valid ST terminator, then this is a
  712. // cancelled sequence and should be ignored.
  713. return i, UnknownEvent(b[:i])
  714. }
  715. i++
  716. }
  717. // Call the function to parse the sequence and return the result
  718. if fn != nil {
  719. if e := fn(b[start:end]); e != nil {
  720. return i, e
  721. }
  722. }
  723. return i, UnknownEvent(b[:i])
  724. }
  725. }
  726. func (p *Parser) parseDcs(b []byte) (int, Event) {
  727. if len(b) == 2 && b[0] == ansi.ESC {
  728. // short cut if this is an alt+P key
  729. return 2, KeyPressEvent{Code: 'p', Mod: ModShift | ModAlt}
  730. }
  731. var params [16]ansi.Param
  732. var paramsLen int
  733. var cmd ansi.Cmd
  734. // DCS sequences are introduced by DCS (0x90) or ESC P (0x1b 0x50)
  735. var i int
  736. if b[i] == ansi.DCS || b[i] == ansi.ESC {
  737. i++
  738. }
  739. if i < len(b) && b[i-1] == ansi.ESC && b[i] == 'P' {
  740. i++
  741. }
  742. // initial DCS byte
  743. if i < len(b) && b[i] >= '<' && b[i] <= '?' {
  744. cmd |= ansi.Cmd(b[i]) << parser.PrefixShift
  745. }
  746. // Scan parameter bytes in the range 0x30-0x3F
  747. var j int
  748. for j = 0; i < len(b) && paramsLen < len(params) && b[i] >= 0x30 && b[i] <= 0x3F; i, j = i+1, j+1 {
  749. if b[i] >= '0' && b[i] <= '9' {
  750. if params[paramsLen] == parser.MissingParam {
  751. params[paramsLen] = 0
  752. }
  753. params[paramsLen] *= 10
  754. params[paramsLen] += ansi.Param(b[i]) - '0'
  755. }
  756. if b[i] == ':' {
  757. params[paramsLen] |= parser.HasMoreFlag
  758. }
  759. if b[i] == ';' || b[i] == ':' {
  760. paramsLen++
  761. if paramsLen < len(params) {
  762. // Don't overflow the params slice
  763. params[paramsLen] = parser.MissingParam
  764. }
  765. }
  766. }
  767. if j > 0 && paramsLen < len(params) {
  768. // has parameters
  769. paramsLen++
  770. }
  771. // Scan intermediate bytes in the range 0x20-0x2F
  772. var intermed byte
  773. for j := 0; i < len(b) && b[i] >= 0x20 && b[i] <= 0x2F; i, j = i+1, j+1 {
  774. intermed = b[i]
  775. }
  776. // set intermediate byte
  777. cmd |= ansi.Cmd(intermed) << parser.IntermedShift
  778. // Scan final byte in the range 0x40-0x7E
  779. if i >= len(b) {
  780. // Incomplete sequence
  781. return 0, nil
  782. }
  783. if b[i] < 0x40 || b[i] > 0x7E {
  784. return i, UnknownEvent(b[:i])
  785. }
  786. // Add the final byte
  787. cmd |= ansi.Cmd(b[i])
  788. i++
  789. start := i // start of the sequence data
  790. for ; i < len(b); i++ {
  791. if b[i] == ansi.ST || b[i] == ansi.ESC {
  792. break
  793. }
  794. }
  795. if i >= len(b) {
  796. // Incomplete sequence
  797. return 0, nil
  798. }
  799. end := i // end of the sequence data
  800. i++
  801. // Check 7-bit ST (string terminator) character
  802. if i < len(b) && b[i-1] == ansi.ESC && b[i] == '\\' {
  803. i++
  804. }
  805. pa := ansi.Params(params[:paramsLen])
  806. switch cmd {
  807. case 'r' | '+'<<parser.IntermedShift:
  808. // XTGETTCAP responses
  809. param, _, _ := pa.Param(0, 0)
  810. switch param {
  811. case 1: // 1 means valid response, 0 means invalid response
  812. tc := parseTermcap(b[start:end])
  813. // XXX: some terminals like KiTTY report invalid responses with
  814. // their queries i.e. sending a query for "Tc" using "\x1bP+q5463\x1b\\"
  815. // returns "\x1bP0+r5463\x1b\\".
  816. // The specs says that invalid responses should be in the form of
  817. // DCS 0 + r ST "\x1bP0+r\x1b\\"
  818. // We ignore invalid responses and only send valid ones to the program.
  819. //
  820. // See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
  821. return i, tc
  822. }
  823. case '|' | '>'<<parser.PrefixShift:
  824. // XTVersion response
  825. return i, TerminalVersionEvent(b[start:end])
  826. }
  827. return i, UnknownEvent(b[:i])
  828. }
  829. func (p *Parser) parseApc(b []byte) (int, Event) {
  830. if len(b) == 2 && b[0] == ansi.ESC {
  831. // short cut if this is an alt+_ key
  832. return 2, KeyPressEvent{Code: rune(b[1]), Mod: ModAlt}
  833. }
  834. // APC sequences are introduced by APC (0x9f) or ESC _ (0x1b 0x5f)
  835. return p.parseStTerminated(ansi.APC, '_', func(b []byte) Event {
  836. if len(b) == 0 {
  837. return nil
  838. }
  839. switch b[0] {
  840. case 'G': // Kitty Graphics Protocol
  841. var g KittyGraphicsEvent
  842. parts := bytes.Split(b[1:], []byte{';'})
  843. g.Options.UnmarshalText(parts[0]) //nolint:errcheck,gosec
  844. if len(parts) > 1 {
  845. g.Payload = parts[1]
  846. }
  847. return g
  848. }
  849. return nil
  850. })(b)
  851. }
  852. func (p *Parser) parseUtf8(b []byte) (int, Event) {
  853. if len(b) == 0 {
  854. return 0, nil
  855. }
  856. c := b[0]
  857. if c <= ansi.US || c == ansi.DEL || c == ansi.SP {
  858. // Control codes get handled by parseControl
  859. return 1, p.parseControl(c)
  860. } else if c > ansi.US && c < ansi.DEL {
  861. // ASCII printable characters
  862. code := rune(c)
  863. k := KeyPressEvent{Code: code, Text: string(code)}
  864. if unicode.IsUpper(code) {
  865. // Convert upper case letters to lower case + shift modifier
  866. k.Code = unicode.ToLower(code)
  867. k.ShiftedCode = code
  868. k.Mod |= ModShift
  869. }
  870. return 1, k
  871. }
  872. code, _ := utf8.DecodeRune(b)
  873. if code == utf8.RuneError {
  874. return 1, UnknownEvent(b[0])
  875. }
  876. cluster, _, _, _ := uniseg.FirstGraphemeCluster(b, -1)
  877. // PERFORMANCE: Use RuneCount to check for multi-rune graphemes instead of
  878. // looping over the string representation.
  879. if utf8.RuneCount(cluster) > 1 {
  880. code = KeyExtended
  881. }
  882. return len(cluster), KeyPressEvent{Code: code, Text: string(cluster)}
  883. }
  884. func (p *Parser) parseControl(b byte) Event {
  885. switch b {
  886. case ansi.NUL:
  887. if p.flags&FlagCtrlAt != 0 {
  888. return KeyPressEvent{Code: '@', Mod: ModCtrl}
  889. }
  890. return KeyPressEvent{Code: KeySpace, Mod: ModCtrl}
  891. case ansi.BS:
  892. return KeyPressEvent{Code: 'h', Mod: ModCtrl}
  893. case ansi.HT:
  894. if p.flags&FlagCtrlI != 0 {
  895. return KeyPressEvent{Code: 'i', Mod: ModCtrl}
  896. }
  897. return KeyPressEvent{Code: KeyTab}
  898. case ansi.CR:
  899. if p.flags&FlagCtrlM != 0 {
  900. return KeyPressEvent{Code: 'm', Mod: ModCtrl}
  901. }
  902. return KeyPressEvent{Code: KeyEnter}
  903. case ansi.ESC:
  904. if p.flags&FlagCtrlOpenBracket != 0 {
  905. return KeyPressEvent{Code: '[', Mod: ModCtrl}
  906. }
  907. return KeyPressEvent{Code: KeyEscape}
  908. case ansi.DEL:
  909. if p.flags&FlagBackspace != 0 {
  910. return KeyPressEvent{Code: KeyDelete}
  911. }
  912. return KeyPressEvent{Code: KeyBackspace}
  913. case ansi.SP:
  914. return KeyPressEvent{Code: KeySpace, Text: " "}
  915. default:
  916. if b >= ansi.SOH && b <= ansi.SUB {
  917. // Use lower case letters for control codes
  918. code := rune(b + 0x60)
  919. return KeyPressEvent{Code: code, Mod: ModCtrl}
  920. } else if b >= ansi.FS && b <= ansi.US {
  921. code := rune(b + 0x40)
  922. return KeyPressEvent{Code: code, Mod: ModCtrl}
  923. }
  924. return UnknownEvent(b)
  925. }
  926. }