parse.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. package input
  2. import (
  3. "encoding/base64"
  4. "strings"
  5. "unicode/utf8"
  6. "github.com/charmbracelet/x/ansi"
  7. "github.com/charmbracelet/x/ansi/parser"
  8. "github.com/erikgeiser/coninput"
  9. )
  10. // Flags to control the behavior of the parser.
  11. const (
  12. // When this flag is set, the driver will treat both Ctrl+Space and Ctrl+@
  13. // as the same key sequence.
  14. //
  15. // Historically, the ANSI specs generate NUL (0x00) on both the Ctrl+Space
  16. // and Ctrl+@ key sequences. This flag allows the driver to treat both as
  17. // the same key sequence.
  18. FlagCtrlAt = 1 << iota
  19. // When this flag is set, the driver will treat the Tab key and Ctrl+I as
  20. // the same key sequence.
  21. //
  22. // Historically, the ANSI specs generate HT (0x09) on both the Tab key and
  23. // Ctrl+I. This flag allows the driver to treat both as the same key
  24. // sequence.
  25. FlagCtrlI
  26. // When this flag is set, the driver will treat the Enter key and Ctrl+M as
  27. // the same key sequence.
  28. //
  29. // Historically, the ANSI specs generate CR (0x0D) on both the Enter key
  30. // and Ctrl+M. This flag allows the driver to treat both as the same key
  31. FlagCtrlM
  32. // When this flag is set, the driver will treat Escape and Ctrl+[ as
  33. // the same key sequence.
  34. //
  35. // Historically, the ANSI specs generate ESC (0x1B) on both the Escape key
  36. // and Ctrl+[. This flag allows the driver to treat both as the same key
  37. // sequence.
  38. FlagCtrlOpenBracket
  39. // When this flag is set, the driver will send a BS (0x08 byte) character
  40. // instead of a DEL (0x7F byte) character when the Backspace key is
  41. // pressed.
  42. //
  43. // The VT100 terminal has both a Backspace and a Delete key. The VT220
  44. // terminal dropped the Backspace key and replaced it with the Delete key.
  45. // Both terminals send a DEL character when the Delete key is pressed.
  46. // Modern terminals and PCs later readded the Delete key but used a
  47. // different key sequence, and the Backspace key was standardized to send a
  48. // DEL character.
  49. FlagBackspace
  50. // When this flag is set, the driver will recognize the Find key instead of
  51. // treating it as a Home key.
  52. //
  53. // The Find key was part of the VT220 keyboard, and is no longer used in
  54. // modern day PCs.
  55. FlagFind
  56. // When this flag is set, the driver will recognize the Select key instead
  57. // of treating it as a End key.
  58. //
  59. // The Symbol key was part of the VT220 keyboard, and is no longer used in
  60. // modern day PCs.
  61. FlagSelect
  62. // When this flag is set, the driver will use Terminfo databases to
  63. // overwrite the default key sequences.
  64. FlagTerminfo
  65. // When this flag is set, the driver will preserve function keys (F13-F63)
  66. // as symbols.
  67. //
  68. // Since these keys are not part of today's standard 20th century keyboard,
  69. // we treat them as F1-F12 modifier keys i.e. ctrl/shift/alt + Fn combos.
  70. // Key definitions come from Terminfo, this flag is only useful when
  71. // FlagTerminfo is not set.
  72. FlagFKeys
  73. )
  74. var flags int
  75. // SetFlags sets the flags for the parser.
  76. // This will control the behavior of ParseSequence.
  77. func SetFlags(f int) {
  78. flags = f
  79. }
  80. // ParseSequence finds the first recognized event sequence and returns it along
  81. // with its length.
  82. //
  83. // It will return zero and nil no sequence is recognized or when the buffer is
  84. // empty. If a sequence is not supported, an UnknownEvent is returned.
  85. func ParseSequence(buf []byte) (n int, e Event) {
  86. if len(buf) == 0 {
  87. return 0, nil
  88. }
  89. switch b := buf[0]; b {
  90. case ansi.ESC:
  91. if len(buf) == 1 {
  92. // Escape key
  93. return 1, KeyPressEvent{Sym: KeyEscape}
  94. }
  95. switch b := buf[1]; b {
  96. case 'O': // Esc-prefixed SS3
  97. return parseSs3(buf)
  98. case 'P': // Esc-prefixed DCS
  99. return parseDcs(buf)
  100. case '[': // Esc-prefixed CSI
  101. return parseCsi(buf)
  102. case ']': // Esc-prefixed OSC
  103. return parseOsc(buf)
  104. case '_': // Esc-prefixed APC
  105. return parseApc(buf)
  106. default:
  107. n, e := ParseSequence(buf[1:])
  108. if k, ok := e.(KeyPressEvent); ok && !k.Mod.HasAlt() {
  109. k.Mod |= ModAlt
  110. return n + 1, k
  111. }
  112. // Not a key sequence, nor an alt modified key sequence. In that
  113. // case, just report a single escape key.
  114. return 1, KeyPressEvent{Sym: KeyEscape}
  115. }
  116. case ansi.SS3:
  117. return parseSs3(buf)
  118. case ansi.DCS:
  119. return parseDcs(buf)
  120. case ansi.CSI:
  121. return parseCsi(buf)
  122. case ansi.OSC:
  123. return parseOsc(buf)
  124. case ansi.APC:
  125. return parseApc(buf)
  126. default:
  127. if b <= ansi.US || b == ansi.DEL || b == ansi.SP {
  128. return 1, parseControl(b)
  129. } else if b >= ansi.PAD && b <= ansi.APC {
  130. // C1 control code
  131. // UTF-8 never starts with a C1 control code
  132. // Encode these as Ctrl+Alt+<code - 0x40>
  133. return 1, KeyPressEvent{Rune: rune(b) - 0x40, Mod: ModCtrl | ModAlt}
  134. }
  135. return parseUtf8(buf)
  136. }
  137. }
  138. func parseCsi(b []byte) (int, Event) {
  139. if len(b) == 2 && b[0] == ansi.ESC {
  140. // short cut if this is an alt+[ key
  141. return 2, KeyPressEvent{Rune: rune(b[1]), Mod: ModAlt}
  142. }
  143. var csi ansi.CsiSequence
  144. var params [parser.MaxParamsSize]int
  145. var paramsLen int
  146. var i int
  147. if b[i] == ansi.CSI || b[i] == ansi.ESC {
  148. i++
  149. }
  150. if i < len(b) && b[i-1] == ansi.ESC && b[i] == '[' {
  151. i++
  152. }
  153. // Initial CSI byte
  154. if i < len(b) && b[i] >= '<' && b[i] <= '?' {
  155. csi.Cmd |= int(b[i]) << parser.MarkerShift
  156. }
  157. // Scan parameter bytes in the range 0x30-0x3F
  158. var j int
  159. for j = 0; i < len(b) && paramsLen < len(params) && b[i] >= 0x30 && b[i] <= 0x3F; i, j = i+1, j+1 {
  160. if b[i] >= '0' && b[i] <= '9' {
  161. if params[paramsLen] == parser.MissingParam {
  162. params[paramsLen] = 0
  163. }
  164. params[paramsLen] *= 10
  165. params[paramsLen] += int(b[i]) - '0'
  166. }
  167. if b[i] == ':' {
  168. params[paramsLen] |= parser.HasMoreFlag
  169. }
  170. if b[i] == ';' || b[i] == ':' {
  171. paramsLen++
  172. if paramsLen < len(params) {
  173. // Don't overflow the params slice
  174. params[paramsLen] = parser.MissingParam
  175. }
  176. }
  177. }
  178. if j > 0 && paramsLen < len(params) {
  179. // has parameters
  180. paramsLen++
  181. }
  182. // Scan intermediate bytes in the range 0x20-0x2F
  183. var intermed byte
  184. for ; i < len(b) && b[i] >= 0x20 && b[i] <= 0x2F; i++ {
  185. intermed = b[i]
  186. }
  187. // Set the intermediate byte
  188. csi.Cmd |= int(intermed) << parser.IntermedShift
  189. // Scan final byte in the range 0x40-0x7E
  190. if i >= len(b) || b[i] < 0x40 || b[i] > 0x7E {
  191. // Special case for URxvt keys
  192. // CSI <number> $ is an invalid sequence, but URxvt uses it for
  193. // shift modified keys.
  194. if b[i-1] == '$' {
  195. n, ev := parseCsi(append(b[:i-1], '~'))
  196. if k, ok := ev.(KeyPressEvent); ok {
  197. k.Mod |= ModShift
  198. return n, k
  199. }
  200. }
  201. return i, UnknownEvent(b[:i-1])
  202. }
  203. // Add the final byte
  204. csi.Cmd |= int(b[i])
  205. i++
  206. csi.Params = params[:paramsLen]
  207. marker, cmd := csi.Marker(), csi.Command()
  208. switch marker {
  209. case '?':
  210. switch cmd {
  211. case 'y':
  212. switch intermed {
  213. case '$':
  214. // Report Mode (DECRPM)
  215. if paramsLen != 2 {
  216. return i, UnknownCsiEvent(b[:i])
  217. }
  218. return i, ReportModeEvent{Mode: csi.Param(0), Value: csi.Param(1)}
  219. }
  220. case 'c':
  221. // Primary Device Attributes
  222. return i, parsePrimaryDevAttrs(&csi)
  223. case 'u':
  224. // Kitty keyboard flags
  225. if param := csi.Param(0); param != -1 {
  226. return i, KittyKeyboardEvent(param)
  227. }
  228. case 'R':
  229. // This report may return a third parameter representing the page
  230. // number, but we don't really need it.
  231. if paramsLen >= 2 {
  232. return i, CursorPositionEvent{Row: csi.Param(0), Column: csi.Param(1)}
  233. }
  234. }
  235. return i, UnknownCsiEvent(b[:i])
  236. case '<':
  237. switch cmd {
  238. case 'm', 'M':
  239. // Handle SGR mouse
  240. if paramsLen != 3 {
  241. return i, UnknownCsiEvent(b[:i])
  242. }
  243. return i, parseSGRMouseEvent(&csi)
  244. default:
  245. return i, UnknownCsiEvent(b[:i])
  246. }
  247. case '>':
  248. switch cmd {
  249. case 'm':
  250. // XTerm modifyOtherKeys
  251. if paramsLen != 2 || csi.Param(0) != 4 {
  252. return i, UnknownCsiEvent(b[:i])
  253. }
  254. return i, ModifyOtherKeysEvent(csi.Param(1))
  255. default:
  256. return i, UnknownCsiEvent(b[:i])
  257. }
  258. case '=':
  259. // We don't support any of these yet
  260. return i, UnknownCsiEvent(b[:i])
  261. }
  262. switch cmd := csi.Command(); cmd {
  263. case 'R':
  264. // Cursor position report OR modified F3
  265. if paramsLen == 0 {
  266. return i, KeyPressEvent{Sym: KeyF3}
  267. } else if paramsLen != 2 {
  268. break
  269. }
  270. // XXX: We cannot differentiate between cursor position report and
  271. // CSI 1 ; <mod> R (which is modified F3) when the cursor is at the
  272. // row 1. In this case, we report a modified F3 event since it's more
  273. // likely to be the case than the cursor being at the first row.
  274. //
  275. // For a non ambiguous cursor position report, use
  276. // [ansi.RequestExtendedCursorPosition] (DECXCPR) instead.
  277. if csi.Param(0) != 1 {
  278. return i, CursorPositionEvent{Row: csi.Param(0), Column: csi.Param(1)}
  279. }
  280. fallthrough
  281. case 'a', 'b', 'c', 'd', 'A', 'B', 'C', 'D', 'E', 'F', 'H', 'P', 'Q', 'S', 'Z':
  282. var k KeyPressEvent
  283. switch cmd {
  284. case 'a', 'b', 'c', 'd':
  285. k = KeyPressEvent{Sym: KeyUp + KeySym(cmd-'a'), Mod: ModShift}
  286. case 'A', 'B', 'C', 'D':
  287. k = KeyPressEvent{Sym: KeyUp + KeySym(cmd-'A')}
  288. case 'E':
  289. k = KeyPressEvent{Sym: KeyBegin}
  290. case 'F':
  291. k = KeyPressEvent{Sym: KeyEnd}
  292. case 'H':
  293. k = KeyPressEvent{Sym: KeyHome}
  294. case 'P', 'Q', 'R', 'S':
  295. k = KeyPressEvent{Sym: KeyF1 + KeySym(cmd-'P')}
  296. case 'Z':
  297. k = KeyPressEvent{Sym: KeyTab, Mod: ModShift}
  298. }
  299. if paramsLen > 1 && csi.Param(0) == 1 {
  300. // CSI 1 ; <modifiers> A
  301. if paramsLen > 1 {
  302. k.Mod |= KeyMod(csi.Param(1) - 1)
  303. }
  304. }
  305. return i, k
  306. case 'M':
  307. // Handle X10 mouse
  308. if i+3 > len(b) {
  309. return i, UnknownCsiEvent(b[:i])
  310. }
  311. return i + 3, parseX10MouseEvent(append(b[:i], b[i:i+3]...))
  312. case 'y':
  313. // Report Mode (DECRPM)
  314. if paramsLen != 2 {
  315. return i, UnknownCsiEvent(b[:i])
  316. }
  317. return i, ReportModeEvent{Mode: csi.Param(0), Value: csi.Param(1)}
  318. case 'u':
  319. // Kitty keyboard protocol & CSI u (fixterms)
  320. if paramsLen == 0 {
  321. return i, UnknownCsiEvent(b[:i])
  322. }
  323. return i, parseKittyKeyboard(&csi)
  324. case '_':
  325. // Win32 Input Mode
  326. if paramsLen != 6 {
  327. return i, UnknownCsiEvent(b[:i])
  328. }
  329. rc := uint16(csi.Param(5))
  330. if rc == 0 {
  331. rc = 1
  332. }
  333. event := parseWin32InputKeyEvent(
  334. coninput.VirtualKeyCode(csi.Param(0)), // Vk wVirtualKeyCode
  335. coninput.VirtualKeyCode(csi.Param(1)), // Sc wVirtualScanCode
  336. rune(csi.Param(2)), // Uc UnicodeChar
  337. csi.Param(3) == 1, // Kd bKeyDown
  338. coninput.ControlKeyState(csi.Param(4)), // Cs dwControlKeyState
  339. rc, // Rc wRepeatCount
  340. )
  341. if event == nil {
  342. return i, UnknownCsiEvent(b[:])
  343. }
  344. return i, event
  345. case '@', '^', '~':
  346. if paramsLen == 0 {
  347. return i, UnknownCsiEvent(b[:i])
  348. }
  349. param := csi.Param(0)
  350. switch cmd {
  351. case '~':
  352. switch param {
  353. case 27:
  354. // XTerm modifyOtherKeys 2
  355. if paramsLen != 3 {
  356. return i, UnknownCsiEvent(b[:i])
  357. }
  358. return i, parseXTermModifyOtherKeys(&csi)
  359. case 200:
  360. // bracketed-paste start
  361. return i, PasteStartEvent{}
  362. case 201:
  363. // bracketed-paste end
  364. return i, PasteEndEvent{}
  365. }
  366. }
  367. switch param {
  368. case 1, 2, 3, 4, 5, 6, 7, 8:
  369. fallthrough
  370. case 11, 12, 13, 14, 15:
  371. fallthrough
  372. case 17, 18, 19, 20, 21, 23, 24, 25, 26:
  373. fallthrough
  374. case 28, 29, 31, 32, 33, 34:
  375. var k KeyPressEvent
  376. switch param {
  377. case 1:
  378. if flags&FlagFind != 0 {
  379. k = KeyPressEvent{Sym: KeyFind}
  380. } else {
  381. k = KeyPressEvent{Sym: KeyHome}
  382. }
  383. case 2:
  384. k = KeyPressEvent{Sym: KeyInsert}
  385. case 3:
  386. k = KeyPressEvent{Sym: KeyDelete}
  387. case 4:
  388. if flags&FlagSelect != 0 {
  389. k = KeyPressEvent{Sym: KeySelect}
  390. } else {
  391. k = KeyPressEvent{Sym: KeyEnd}
  392. }
  393. case 5:
  394. k = KeyPressEvent{Sym: KeyPgUp}
  395. case 6:
  396. k = KeyPressEvent{Sym: KeyPgDown}
  397. case 7:
  398. k = KeyPressEvent{Sym: KeyHome}
  399. case 8:
  400. k = KeyPressEvent{Sym: KeyEnd}
  401. case 11, 12, 13, 14, 15:
  402. k = KeyPressEvent{Sym: KeyF1 + KeySym(param-11)}
  403. case 17, 18, 19, 20, 21:
  404. k = KeyPressEvent{Sym: KeyF6 + KeySym(param-17)}
  405. case 23, 24, 25, 26:
  406. k = KeyPressEvent{Sym: KeyF11 + KeySym(param-23)}
  407. case 28, 29:
  408. k = KeyPressEvent{Sym: KeyF15 + KeySym(param-28)}
  409. case 31, 32, 33, 34:
  410. k = KeyPressEvent{Sym: KeyF17 + KeySym(param-31)}
  411. }
  412. // modifiers
  413. if paramsLen > 1 {
  414. k.Mod |= KeyMod(csi.Param(1) - 1)
  415. }
  416. // Handle URxvt weird keys
  417. switch cmd {
  418. case '^':
  419. k.Mod |= ModCtrl
  420. case '@':
  421. k.Mod |= ModCtrl | ModShift
  422. }
  423. return i, k
  424. }
  425. }
  426. return i, UnknownCsiEvent(b[:i])
  427. }
  428. // parseSs3 parses a SS3 sequence.
  429. // See https://vt100.net/docs/vt220-rm/chapter4.html#S4.4.4.2
  430. func parseSs3(b []byte) (int, Event) {
  431. if len(b) == 2 && b[0] == ansi.ESC {
  432. // short cut if this is an alt+O key
  433. return 2, KeyPressEvent{Rune: rune(b[1]), Mod: ModAlt}
  434. }
  435. var i int
  436. if b[i] == ansi.SS3 || b[i] == ansi.ESC {
  437. i++
  438. }
  439. if i < len(b) && b[i-1] == ansi.ESC && b[i] == 'O' {
  440. i++
  441. }
  442. // Scan numbers from 0-9
  443. var mod int
  444. for ; i < len(b) && b[i] >= '0' && b[i] <= '9'; i++ {
  445. mod *= 10
  446. mod += int(b[i]) - '0'
  447. }
  448. // Scan a GL character
  449. // A GL character is a single byte in the range 0x21-0x7E
  450. // See https://vt100.net/docs/vt220-rm/chapter2.html#S2.3.2
  451. if i >= len(b) || b[i] < 0x21 || b[i] > 0x7E {
  452. return i, UnknownEvent(b[:i])
  453. }
  454. // GL character(s)
  455. gl := b[i]
  456. i++
  457. var k KeyPressEvent
  458. switch gl {
  459. case 'a', 'b', 'c', 'd':
  460. k = KeyPressEvent{Sym: KeyUp + KeySym(gl-'a'), Mod: ModCtrl}
  461. case 'A', 'B', 'C', 'D':
  462. k = KeyPressEvent{Sym: KeyUp + KeySym(gl-'A')}
  463. case 'E':
  464. k = KeyPressEvent{Sym: KeyBegin}
  465. case 'F':
  466. k = KeyPressEvent{Sym: KeyEnd}
  467. case 'H':
  468. k = KeyPressEvent{Sym: KeyHome}
  469. case 'P', 'Q', 'R', 'S':
  470. k = KeyPressEvent{Sym: KeyF1 + KeySym(gl-'P')}
  471. case 'M':
  472. k = KeyPressEvent{Sym: KeyKpEnter}
  473. case 'X':
  474. k = KeyPressEvent{Sym: KeyKpEqual}
  475. case 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y':
  476. k = KeyPressEvent{Sym: KeyKpMultiply + KeySym(gl-'j')}
  477. default:
  478. return i, UnknownSs3Event(b[:i])
  479. }
  480. // Handle weird SS3 <modifier> Func
  481. if mod > 0 {
  482. k.Mod |= KeyMod(mod - 1)
  483. }
  484. return i, k
  485. }
  486. func parseOsc(b []byte) (int, Event) {
  487. if len(b) == 2 && b[0] == ansi.ESC {
  488. // short cut if this is an alt+] key
  489. return 2, KeyPressEvent{Rune: rune(b[1]), Mod: ModAlt}
  490. }
  491. var i int
  492. if b[i] == ansi.OSC || b[i] == ansi.ESC {
  493. i++
  494. }
  495. if i < len(b) && b[i-1] == ansi.ESC && b[i] == ']' {
  496. i++
  497. }
  498. // Parse OSC command
  499. // An OSC sequence is terminated by a BEL, ESC, or ST character
  500. var start, end int
  501. cmd := -1
  502. for ; i < len(b) && b[i] >= '0' && b[i] <= '9'; i++ {
  503. if cmd == -1 {
  504. cmd = 0
  505. } else {
  506. cmd *= 10
  507. }
  508. cmd += int(b[i]) - '0'
  509. }
  510. if i < len(b) && b[i] == ';' {
  511. // mark the start of the sequence data
  512. i++
  513. start = i
  514. }
  515. for ; i < len(b); i++ {
  516. // advance to the end of the sequence
  517. if b[i] == ansi.BEL || b[i] == ansi.ESC || b[i] == ansi.ST {
  518. break
  519. }
  520. }
  521. if i >= len(b) {
  522. return i, UnknownEvent(b[:i])
  523. }
  524. end = i // end of the sequence data
  525. i++
  526. // Check 7-bit ST (string terminator) character
  527. if i < len(b) && b[i-1] == ansi.ESC && b[i] == '\\' {
  528. i++
  529. }
  530. if end <= start {
  531. return i, UnknownOscEvent(b[:i])
  532. }
  533. data := string(b[start:end])
  534. switch cmd {
  535. case 10:
  536. return i, ForegroundColorEvent{xParseColor(data)}
  537. case 11:
  538. return i, BackgroundColorEvent{xParseColor(data)}
  539. case 12:
  540. return i, CursorColorEvent{xParseColor(data)}
  541. case 52:
  542. parts := strings.Split(data, ";")
  543. if len(parts) == 0 {
  544. return i, ClipboardEvent("")
  545. }
  546. b64 := parts[len(parts)-1]
  547. bts, err := base64.StdEncoding.DecodeString(b64)
  548. if err != nil {
  549. return i, ClipboardEvent("")
  550. }
  551. return i, ClipboardEvent(bts)
  552. default:
  553. return i, UnknownOscEvent(b[:i])
  554. }
  555. }
  556. // parseStTerminated parses a control sequence that gets terminated by a ST character.
  557. func parseStTerminated(intro8, intro7 byte) func([]byte) (int, Event) {
  558. return func(b []byte) (int, Event) {
  559. var i int
  560. if b[i] == intro8 || b[i] == ansi.ESC {
  561. i++
  562. }
  563. if i < len(b) && b[i-1] == ansi.ESC && b[i] == intro7 {
  564. i++
  565. }
  566. // Scan control sequence
  567. // Most common control sequence is terminated by a ST character
  568. // ST is a 7-bit string terminator character is (ESC \)
  569. // nolint: revive
  570. for ; i < len(b) && b[i] != ansi.ST && b[i] != ansi.ESC; i++ {
  571. }
  572. if i >= len(b) {
  573. switch intro8 {
  574. case ansi.DCS:
  575. return i, UnknownDcsEvent(b[:i])
  576. case ansi.APC:
  577. return i, UnknownApcEvent(b[:i])
  578. default:
  579. return i, UnknownEvent(b[:i])
  580. }
  581. }
  582. i++
  583. // Check 7-bit ST (string terminator) character
  584. if i < len(b) && b[i-1] == ansi.ESC && b[i] == '\\' {
  585. i++
  586. }
  587. switch intro8 {
  588. case ansi.DCS:
  589. return i, UnknownDcsEvent(b[:i])
  590. case ansi.APC:
  591. return i, UnknownApcEvent(b[:i])
  592. default:
  593. return i, UnknownEvent(b[:i])
  594. }
  595. }
  596. }
  597. func parseDcs(b []byte) (int, Event) {
  598. if len(b) == 2 && b[0] == ansi.ESC {
  599. // short cut if this is an alt+P key
  600. return 2, KeyPressEvent{Rune: rune(b[1]), Mod: ModAlt}
  601. }
  602. var params [16]int
  603. var paramsLen int
  604. var dcs ansi.DcsSequence
  605. // DCS sequences are introduced by DCS (0x90) or ESC P (0x1b 0x50)
  606. var i int
  607. if b[i] == ansi.DCS || b[i] == ansi.ESC {
  608. i++
  609. }
  610. if i < len(b) && b[i-1] == ansi.ESC && b[i] == 'P' {
  611. i++
  612. }
  613. // initial DCS byte
  614. if i < len(b) && b[i] >= '<' && b[i] <= '?' {
  615. dcs.Cmd |= int(b[i]) << parser.MarkerShift
  616. }
  617. // Scan parameter bytes in the range 0x30-0x3F
  618. var j int
  619. for j = 0; i < len(b) && paramsLen < len(params) && b[i] >= 0x30 && b[i] <= 0x3F; i, j = i+1, j+1 {
  620. if b[i] >= '0' && b[i] <= '9' {
  621. if params[paramsLen] == parser.MissingParam {
  622. params[paramsLen] = 0
  623. }
  624. params[paramsLen] *= 10
  625. params[paramsLen] += int(b[i]) - '0'
  626. }
  627. if b[i] == ':' {
  628. params[paramsLen] |= parser.HasMoreFlag
  629. }
  630. if b[i] == ';' || b[i] == ':' {
  631. paramsLen++
  632. if paramsLen < len(params) {
  633. // Don't overflow the params slice
  634. params[paramsLen] = parser.MissingParam
  635. }
  636. }
  637. }
  638. if j > 0 && paramsLen < len(params) {
  639. // has parameters
  640. paramsLen++
  641. }
  642. // Scan intermediate bytes in the range 0x20-0x2F
  643. var intermed byte
  644. for j := 0; i < len(b) && b[i] >= 0x20 && b[i] <= 0x2F; i, j = i+1, j+1 {
  645. intermed = b[i]
  646. }
  647. // set intermediate byte
  648. dcs.Cmd |= int(intermed) << parser.IntermedShift
  649. // Scan final byte in the range 0x40-0x7E
  650. if i >= len(b) || b[i] < 0x40 || b[i] > 0x7E {
  651. return i, UnknownEvent(b[:i])
  652. }
  653. // Add the final byte
  654. dcs.Cmd |= int(b[i])
  655. i++
  656. start := i // start of the sequence data
  657. for ; i < len(b); i++ {
  658. if b[i] == ansi.ST || b[i] == ansi.ESC {
  659. break
  660. }
  661. }
  662. if i >= len(b) {
  663. return i, UnknownEvent(b[:i])
  664. }
  665. end := i // end of the sequence data
  666. i++
  667. // Check 7-bit ST (string terminator) character
  668. if i < len(b) && b[i-1] == ansi.ESC && b[i] == '\\' {
  669. i++
  670. }
  671. dcs.Params = params[:paramsLen]
  672. switch cmd := dcs.Command(); cmd {
  673. case 'r':
  674. switch dcs.Intermediate() {
  675. case '+':
  676. // XTGETTCAP responses
  677. switch param := dcs.Param(0); param {
  678. case 0, 1:
  679. tc := parseTermcap(b[start:end])
  680. // XXX: some terminals like KiTTY report invalid responses with
  681. // their queries i.e. sending a query for "Tc" using "\x1bP+q5463\x1b\\"
  682. // returns "\x1bP0+r5463\x1b\\".
  683. // The specs says that invalid responses should be in the form of
  684. // DCS 0 + r ST "\x1bP0+r\x1b\\"
  685. //
  686. // See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
  687. tc.IsValid = param == 1
  688. return i, tc
  689. }
  690. }
  691. }
  692. return i, UnknownDcsEvent(b[:i])
  693. }
  694. func parseApc(b []byte) (int, Event) {
  695. if len(b) == 2 && b[0] == ansi.ESC {
  696. // short cut if this is an alt+_ key
  697. return 2, KeyPressEvent{Rune: rune(b[1]), Mod: ModAlt}
  698. }
  699. // APC sequences are introduced by APC (0x9f) or ESC _ (0x1b 0x5f)
  700. return parseStTerminated(ansi.APC, '_')(b)
  701. }
  702. func parseUtf8(b []byte) (int, Event) {
  703. r, rw := utf8.DecodeRune(b)
  704. if r <= ansi.US || r == ansi.DEL || r == ansi.SP {
  705. // Control codes get handled by parseControl
  706. return 1, parseControl(byte(r))
  707. } else if r == utf8.RuneError {
  708. return 1, UnknownEvent(b[0])
  709. }
  710. return rw, KeyPressEvent{Rune: r}
  711. }
  712. func parseControl(b byte) Event {
  713. switch b {
  714. case ansi.NUL:
  715. if flags&FlagCtrlAt != 0 {
  716. return KeyPressEvent{Rune: '@', Mod: ModCtrl}
  717. }
  718. return KeyPressEvent{Rune: ' ', Sym: KeySpace, Mod: ModCtrl}
  719. case ansi.BS:
  720. return KeyPressEvent{Rune: 'h', Mod: ModCtrl}
  721. case ansi.HT:
  722. if flags&FlagCtrlI != 0 {
  723. return KeyPressEvent{Rune: 'i', Mod: ModCtrl}
  724. }
  725. return KeyPressEvent{Sym: KeyTab}
  726. case ansi.CR:
  727. if flags&FlagCtrlM != 0 {
  728. return KeyPressEvent{Rune: 'm', Mod: ModCtrl}
  729. }
  730. return KeyPressEvent{Sym: KeyEnter}
  731. case ansi.ESC:
  732. if flags&FlagCtrlOpenBracket != 0 {
  733. return KeyPressEvent{Rune: '[', Mod: ModCtrl}
  734. }
  735. return KeyPressEvent{Sym: KeyEscape}
  736. case ansi.DEL:
  737. if flags&FlagBackspace != 0 {
  738. return KeyPressEvent{Sym: KeyDelete}
  739. }
  740. return KeyPressEvent{Sym: KeyBackspace}
  741. case ansi.SP:
  742. return KeyPressEvent{Sym: KeySpace, Rune: ' '}
  743. default:
  744. if b >= ansi.SOH && b <= ansi.SUB {
  745. // Use lower case letters for control codes
  746. return KeyPressEvent{Rune: rune(b + 0x60), Mod: ModCtrl}
  747. } else if b >= ansi.FS && b <= ansi.US {
  748. return KeyPressEvent{Rune: rune(b + 0x40), Mod: ModCtrl}
  749. }
  750. return UnknownEvent(b)
  751. }
  752. }