{"version":3,"file":"sync-output.d.ts","sourceRoot":"","sources":["../src/sync-output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,eAAO,MAAM,iBAAiB,kBAAgB,CAAC;AAC/C,eAAO,MAAM,eAAe,kBAAgB,CAAC;AAE7C,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;AAExE;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACzC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,yEAAuE;IACvE,QAAQ,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,yBAAyB,GAAG,iBAAiB,CAmB7F;AA4BD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAGjF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAEhG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAE9F","sourcesContent":["/**\n * DEC private mode 2026 — Synchronized Output.\n *\n * Wraps a render frame in `\\e[?2026h` (begin) and `\\e[?2026l` (end) so the\n * terminal commits the entire frame atomically. Eliminates intra-frame flicker\n * (interleaved redraws) on terminals that support the sequence: kitty, iTerm2,\n * WezTerm, foot, alacritty (>=0.13), Ghostty, Windows Terminal (>=1.18),\n * Konsole, contour, mintty, recent xterm. Terminals that do not understand\n * the sequence ignore it and the output renders normally — i.e. emitting it\n * is safe everywhere, but we still gate on capability detection because:\n *\n *   1. Some legacy terminals print the literal sequence as text (broken\n *      private-mode handling).\n *   2. Multiplexers (tmux <3.4) need passthrough to be enabled or the\n *      sequence is silently dropped, leaving rendering unchanged but adding\n *      bytes to the output. We disable in those environments by default.\n *   3. SSH+screen sessions sometimes lie via TERM=xterm-256color; the\n *      classification in `terminal-detect.ts` lets us be conservative.\n */\nimport type { TerminalIdentity } from \"./terminal-detect.js\";\n\nexport const SYNC_OUTPUT_BEGIN = \"\\x1b[?2026h\";\nexport const SYNC_OUTPUT_END = \"\\x1b[?2026l\";\n\nexport type SyncOutputSupport = \"supported\" | \"unsupported\" | \"unknown\";\n\n/**\n * Inputs required to classify whether the current terminal honors DEC 2026.\n *\n * We accept a `TerminalIdentity` rather than re-reading the env so the same\n * probe result drives every consumer (TUI, status line, diff view).\n */\nexport interface SyncOutputCapabilityInput {\n\tidentity: TerminalIdentity;\n\t/** Override knob — set CAVE_SYNC_OUTPUT=on|off|auto. Default: auto. */\n\toverride?: \"on\" | \"off\" | \"auto\";\n}\n\n/**\n * Classify DEC 2026 support from a probed terminal identity.\n *\n * Conservative: we return `unsupported` when the identity is unknown rather\n * than emitting bytes that may print as literal text. The override `on`\n * forces emission (useful when running under a wrapper that strips the\n * TERM_PROGRAM env). The override `off` disables emission unconditionally.\n */\nexport function classifySyncOutputSupport(input: SyncOutputCapabilityInput): SyncOutputSupport {\n\tconst override = input.override ?? \"auto\";\n\tif (override === \"on\") return \"supported\";\n\tif (override === \"off\") return \"unsupported\";\n\n\tconst { identity } = input;\n\n\t// Multiplexers need explicit passthrough; treat as unknown unless an\n\t// inner-host hint says otherwise. Modern tmux (>=3.4) advertises\n\t// passthrough but we cannot detect that from env alone, so be safe.\n\tif (identity.multiplexer === \"tmux\" || identity.multiplexer === \"screen\") {\n\t\t// Allow if the host program is known-supporting AND user opts in via env.\n\t\tif (process.env.CAVE_SYNC_OUTPUT_MULTIPLEXER === \"1\" && identity.hostProgram) {\n\t\t\treturn classifyByProgram(identity.hostProgram);\n\t\t}\n\t\treturn \"unsupported\";\n\t}\n\n\treturn classifyByProgram(identity.program);\n}\n\nfunction classifyByProgram(program: TerminalIdentity[\"program\"]): SyncOutputSupport {\n\tswitch (program) {\n\t\tcase \"kitty\":\n\t\tcase \"iterm2\":\n\t\tcase \"wezterm\":\n\t\tcase \"alacritty\":\n\t\tcase \"ghostty\":\n\t\tcase \"windows-terminal\":\n\t\tcase \"vscode\":\n\t\t\treturn \"supported\";\n\t\tcase \"vte\": // GNOME Terminal/Tilix — VTE >= 0.71. Cannot version-check from env. Conservative on.\n\t\t\treturn \"supported\";\n\t\tcase \"apple-terminal\":\n\t\tcase \"linux-console\":\n\t\t\treturn \"unsupported\";\n\t\tcase \"tmux\":\n\t\tcase \"screen\":\n\t\t\treturn \"unsupported\";\n\t\tcase \"cmux\":\n\t\tcase \"unknown\":\n\t\t\treturn \"unknown\";\n\t\tdefault:\n\t\t\treturn \"unknown\";\n\t}\n}\n\n/**\n * Wrap a buffer in DEC 2026 begin/end markers when supported.\n *\n * On `unsupported`/`unknown`, returns the buffer unchanged. The caller\n * should still call `wrap` and not branch — this is the cheap path.\n */\nexport function wrapSyncOutput(buffer: string, support: SyncOutputSupport): string {\n\tif (support !== \"supported\") return buffer;\n\treturn `${SYNC_OUTPUT_BEGIN}${buffer}${SYNC_OUTPUT_END}`;\n}\n\n/**\n * Standalone emit helper for renderers that build their buffer in two steps\n * (e.g. a status-line redraw that wants begin → write → end without holding\n * the whole frame in memory).\n */\nexport function emitSyncOutputBegin(write: (s: string) => void, support: SyncOutputSupport): void {\n\tif (support === \"supported\") write(SYNC_OUTPUT_BEGIN);\n}\n\nexport function emitSyncOutputEnd(write: (s: string) => void, support: SyncOutputSupport): void {\n\tif (support === \"supported\") write(SYNC_OUTPUT_END);\n}\n"]}