| 97 | * Real terminal using process.stdin/stdout |
| 98 | */ |
| 99 | export class ProcessTerminal implements Terminal { |
| 100 | private wasRaw = false; |
| 101 | private inputHandler?: (data: string) => void; |
| 102 | private resizeHandler?: () => void; |
| 103 | private _kittyProtocolActive = false; |
| 104 | private _modifyOtherKeysActive = false; |
| 105 | private keyboardProtocolPushed = false; |
| 106 | private keyboardProtocolNegotiationBuffer = ""; |
| 107 | private keyboardProtocolBufferFlushTimer?: ReturnType<typeof setTimeout>; |
| 108 | private stdinBuffer?: StdinBuffer; |
| 109 | private stdinDataHandler?: (data: string) => void; |
| 110 | private progressInterval?: ReturnType<typeof setInterval>; |
| 111 | private writeLogPath = (() => { |
| 112 | const env = process.env['PI_TUI_WRITE_LOG'] || ""; |
| 113 | if (!env) return ""; |
| 114 | try { |
| 115 | if (fs.statSync(env).isDirectory()) { |
| 116 | const now = new Date(); |
| 117 | const ts = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}_${String(now.getHours()).padStart(2, "0")}-${String(now.getMinutes()).padStart(2, "0")}-${String(now.getSeconds()).padStart(2, "0")}`; |
| 118 | return path.join(env, `tui-${ts}-${process.pid}.log`); |
| 119 | } |
| 120 | } catch { |
| 121 | // Not an existing directory - use as-is (file path) |
| 122 | } |
| 123 | return env; |
| 124 | })(); |
| 125 | |
| 126 | get kittyProtocolActive(): boolean { |
| 127 | return this._kittyProtocolActive; |
| 128 | } |
| 129 | |
| 130 | get modifyOtherKeysActive(): boolean { |
| 131 | return this._modifyOtherKeysActive; |
| 132 | } |
| 133 | |
| 134 | start(onInput: (data: string) => void, onResize: () => void): void { |
| 135 | this.inputHandler = onInput; |
| 136 | this.resizeHandler = onResize; |
| 137 | |
| 138 | // Save previous state and enable raw mode |
| 139 | this.wasRaw = process.stdin.isRaw || false; |
| 140 | if (process.stdin.setRawMode) { |
| 141 | process.stdin.setRawMode(true); |
| 142 | } |
| 143 | process.stdin.setEncoding("utf8"); |
| 144 | process.stdin.resume(); |
| 145 | |
| 146 | // Enable bracketed paste mode - terminal will wrap pastes in \x1b[200~ ... \x1b[201~ |
| 147 | process.stdout.write("\x1b[?2004h"); |
| 148 | |
| 149 | // Set up resize handler immediately |
| 150 | process.stdout.on("resize", this.resizeHandler); |
| 151 | |
| 152 | // Refresh terminal dimensions - they may be stale after suspend/resume |
| 153 | // (SIGWINCH is lost while process is stopped). Unix only. |
| 154 | if (process.platform !== "win32") { |
| 155 | process.kill(process.pid, "SIGWINCH"); |
| 156 | } |
nothing calls this directly
no outgoing calls
no test coverage detected