({
input,
output,
timeoutMs = 150,
}: DetectTerminalThemeOptions)
| 79 | * This avoids treating piped diff stdin as terminal input while leaving renderer stdout unchanged. |
| 80 | */ |
| 81 | export async function detectTerminalThemeModeFromBackground({ |
| 82 | input, |
| 83 | output, |
| 84 | timeoutMs = 150, |
| 85 | }: DetectTerminalThemeOptions): Promise<TerminalThemeMode | null> { |
| 86 | const wasRaw = input.isRaw; |
| 87 | let settled = false; |
| 88 | let buffer = ""; |
| 89 | |
| 90 | return await new Promise<TerminalThemeMode | null>((resolve) => { |
| 91 | const cleanup = () => { |
| 92 | if (settled) { |
| 93 | return; |
| 94 | } |
| 95 | settled = true; |
| 96 | clearTimeout(timer); |
| 97 | input.removeListener("data", onData); |
| 98 | if (wasRaw !== undefined) { |
| 99 | input.setRawMode?.(wasRaw); |
| 100 | } |
| 101 | }; |
| 102 | |
| 103 | const finish = (mode: TerminalThemeMode | null) => { |
| 104 | cleanup(); |
| 105 | resolve(mode); |
| 106 | }; |
| 107 | |
| 108 | const timer = setTimeout(() => finish(null), timeoutMs); |
| 109 | const onData = (chunk: Buffer | string) => { |
| 110 | buffer += Buffer.isBuffer(chunk) ? chunk.toString("utf8") : chunk; |
| 111 | const color = parseOsc11BackgroundColor(buffer); |
| 112 | if (color) { |
| 113 | finish(themeModeForBackgroundColor(color)); |
| 114 | } |
| 115 | }; |
| 116 | |
| 117 | input.setRawMode?.(true); |
| 118 | input.resume?.(); |
| 119 | input.on("data", onData); |
| 120 | output.write(OSC_11_BACKGROUND_QUERY); |
| 121 | }); |
| 122 | } |
no test coverage detected