(data: string)
| 1347 | * @returns The printable character, or undefined if not a printable CSI-u sequence |
| 1348 | */ |
| 1349 | export function decodeKittyPrintable(data: string): string | undefined { |
| 1350 | const match = data.match(KITTY_CSI_U_REGEX); |
| 1351 | if (!match) return undefined; |
| 1352 | |
| 1353 | // CSI-u groups: <codepoint>[:<shifted>[:<base>]];<mod>[:<event>]u |
| 1354 | const codepoint = Number.parseInt(match[1] ?? "", 10); |
| 1355 | if (!Number.isFinite(codepoint)) return undefined; |
| 1356 | |
| 1357 | const shiftedKey = match[2] && match[2].length > 0 ? Number.parseInt(match[2], 10) : undefined; |
| 1358 | const modValue = match[4] ? Number.parseInt(match[4], 10) : 1; |
| 1359 | // Modifiers are 1-indexed in CSI-u; normalize to our bitmask. |
| 1360 | const modifier = Number.isFinite(modValue) ? modValue - 1 : 0; |
| 1361 | |
| 1362 | // Only accept printable CSI-u input for plain or Shift-modified text keys. |
| 1363 | // Reject unsupported modifier bits (e.g. Super/Meta) to avoid inserting |
| 1364 | // characters from modifier-only terminal events. |
| 1365 | if ((modifier & ~KITTY_PRINTABLE_ALLOWED_MODIFIERS) !== 0) return undefined; |
| 1366 | if (modifier & (MODIFIERS.alt | MODIFIERS.ctrl)) return undefined; |
| 1367 | |
| 1368 | // Prefer the shifted keycode when Shift is held. |
| 1369 | let effectiveCodepoint = codepoint; |
| 1370 | if (modifier & MODIFIERS.shift && typeof shiftedKey === "number") { |
| 1371 | effectiveCodepoint = shiftedKey; |
| 1372 | } |
| 1373 | effectiveCodepoint = normalizeKittyFunctionalCodepoint(effectiveCodepoint); |
| 1374 | // Drop control characters or invalid codepoints. |
| 1375 | if (!Number.isFinite(effectiveCodepoint) || effectiveCodepoint < 32) return undefined; |
| 1376 | |
| 1377 | try { |
| 1378 | return String.fromCodePoint(effectiveCodepoint); |
| 1379 | } catch { |
| 1380 | return undefined; |
| 1381 | } |
| 1382 | } |
| 1383 | |
| 1384 | function decodeModifyOtherKeysPrintable(data: string): string | undefined { |
| 1385 | const parsed = parseModifyOtherKeysSequence(data); |
no test coverage detected