MCPcopy Create free account
hub / github.com/Noumena-Network/code / parseMultipleKeypresses

Function parseMultipleKeypresses

src/ink/parse-keypress.ts:217–306  ·  view source on GitHub ↗
(
  prevState: KeyParseState,
  input: Buffer | string | null = '',
)

Source from the content-addressed store, hash-verified

215}
216
217export function parseMultipleKeypresses(
218 prevState: KeyParseState,
219 input: Buffer | string | null = '',
220): [ParsedInput[], KeyParseState] {
221 const isFlush = input === null
222 const inputString = isFlush ? '' : inputToString(input)
223
224 // Get or create tokenizer
225 const tokenizer = prevState._tokenizer ?? createTokenizer({ x10Mouse: true })
226
227 // Tokenize the input
228 const tokens = isFlush ? tokenizer.flush() : tokenizer.feed(inputString)
229
230 // Convert tokens to parsed keys, handling paste mode
231 const keys: ParsedInput[] = []
232 let inPaste = prevState.mode === 'IN_PASTE'
233 let pasteBuffer = prevState.pasteBuffer
234
235 for (const token of tokens) {
236 if (token.type === 'sequence') {
237 if (token.value === PASTE_START) {
238 inPaste = true
239 pasteBuffer = ''
240 } else if (token.value === PASTE_END) {
241 // Always emit a paste key, even for empty pastes. This allows
242 // downstream handlers to detect empty pastes (e.g., for clipboard
243 // image handling on macOS). The paste content may be empty string.
244 keys.push(createPasteKey(pasteBuffer))
245 inPaste = false
246 pasteBuffer = ''
247 } else if (inPaste) {
248 // Sequences inside paste are treated as literal text
249 pasteBuffer += token.value
250 } else {
251 const response = parseTerminalResponse(token.value)
252 if (response) {
253 keys.push({ kind: 'response', sequence: token.value, response })
254 } else {
255 const mouse = parseMouseEvent(token.value)
256 if (mouse) {
257 keys.push(mouse)
258 } else {
259 keys.push(parseKeypress(token.value))
260 }
261 }
262 }
263 } else if (token.type === 'text') {
264 if (inPaste) {
265 pasteBuffer += token.value
266 } else if (
267 /^\[<\d+;\d+;\d+[Mm]$/.test(token.value) ||
268 /^\[M[\x60-\x7f][\x20-\uffff]{2}$/.test(token.value)
269 ) {
270 // Orphaned SGR/X10 mouse tail (fullscreen only — mouse tracking is off
271 // otherwise). A heavy render blocked the event loop past App's 50ms
272 // flush timer, so the buffered ESC was flushed as a lone Escape and
273 // the continuation `[<btn;col;rowM` arrived as text. Re-synthesize
274 // with the ESC prefix so the scroll event still fires instead of

Callers 3

inputEventForRawFunction · 0.85
AppClass · 0.85
inputEventForRawFunction · 0.85

Calls 8

inputToStringFunction · 0.85
createTokenizerFunction · 0.85
createPasteKeyFunction · 0.85
parseTerminalResponseFunction · 0.85
parseMouseEventFunction · 0.85
parseKeypressFunction · 0.85
flushMethod · 0.45
feedMethod · 0.45

Tested by 2

inputEventForRawFunction · 0.68
inputEventForRawFunction · 0.68