feat: detect first-run terminal theme (#5385)
This commit is contained in:
@@ -8,6 +8,7 @@ import * as path from "node:path";
|
||||
import { performance } from "node:perf_hooks";
|
||||
import { isKeyRelease, matchesKey } from "./keys.ts";
|
||||
import type { Terminal } from "./terminal.ts";
|
||||
import { isOsc11BackgroundColorResponse, parseOsc11BackgroundColor, type RgbColor } from "./terminal-colors.ts";
|
||||
import { deleteKittyImage, getCapabilities, isImageLine, setCellDimensions } from "./terminal-image.ts";
|
||||
import { extractSegments, normalizeTerminalOutput, sliceByColumn, sliceWithWidth, visibleWidth } from "./utils.ts";
|
||||
|
||||
@@ -82,6 +83,11 @@ export interface Component {
|
||||
|
||||
type InputListenerResult = { consume?: boolean; data?: string } | undefined;
|
||||
type InputListener = (data: string) => InputListenerResult;
|
||||
type PendingOsc11BackgroundQuery = {
|
||||
settled: boolean;
|
||||
resolve: ((rgb: RgbColor | undefined) => void) | undefined;
|
||||
timer: NodeJS.Timeout | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for components that can receive focus and display a hardware cursor.
|
||||
@@ -303,6 +309,8 @@ export class TUI extends Container {
|
||||
private previousViewportTop = 0; // Track previous viewport top for resize-aware cursor moves
|
||||
private fullRedrawCount = 0;
|
||||
private stopped = false;
|
||||
private pendingOsc11BackgroundReplies = 0;
|
||||
private pendingOsc11BackgroundQueries: PendingOsc11BackgroundQuery[] = [];
|
||||
|
||||
// Overlay stack for modal components rendered on top of base content
|
||||
private focusOrderCounter = 0;
|
||||
@@ -720,6 +728,10 @@ export class TUI extends Container {
|
||||
}
|
||||
|
||||
private handleInput(data: string): void {
|
||||
if (this.consumeOsc11BackgroundResponse(data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.inputListeners.size > 0) {
|
||||
let current = data;
|
||||
for (const listener of this.inputListeners) {
|
||||
@@ -788,6 +800,30 @@ export class TUI extends Container {
|
||||
}
|
||||
}
|
||||
|
||||
private consumeOsc11BackgroundResponse(data: string): boolean {
|
||||
if (this.pendingOsc11BackgroundReplies <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isOsc11BackgroundColorResponse(data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const rgb = parseOsc11BackgroundColor(data);
|
||||
this.pendingOsc11BackgroundReplies -= 1;
|
||||
const query = this.pendingOsc11BackgroundQueries.shift();
|
||||
if (query && !query.settled) {
|
||||
query.settled = true;
|
||||
if (query.timer) {
|
||||
clearTimeout(query.timer);
|
||||
query.timer = undefined;
|
||||
}
|
||||
query.resolve?.(rgb);
|
||||
query.resolve = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private consumeCellSizeResponse(data: string): boolean {
|
||||
// Response format: ESC [ 6 ; height ; width t
|
||||
const match = data.match(/^\x1b\[6;(\d+);(\d+)t$/);
|
||||
@@ -1561,4 +1597,32 @@ export class TUI extends Container {
|
||||
this.terminal.hideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the terminal's default background color with OSC 11 (`ESC ] 11 ; ? BEL`).
|
||||
* @param timeoutMs Query timeout in milliseconds.
|
||||
* @returns Promise containing the parsed RGB color, or undefined if it times out or fails to parse.
|
||||
*/
|
||||
queryTerminalBackgroundColor({ timeoutMs }: { timeoutMs: number }): Promise<RgbColor | undefined> {
|
||||
return new Promise((resolve) => {
|
||||
const query: PendingOsc11BackgroundQuery = {
|
||||
settled: false,
|
||||
resolve,
|
||||
timer: undefined,
|
||||
};
|
||||
|
||||
query.timer = setTimeout(() => {
|
||||
if (query.settled) {
|
||||
return;
|
||||
}
|
||||
query.settled = true;
|
||||
query.timer = undefined;
|
||||
query.resolve?.(undefined);
|
||||
query.resolve = undefined;
|
||||
}, timeoutMs);
|
||||
this.pendingOsc11BackgroundQueries.push(query);
|
||||
this.pendingOsc11BackgroundReplies += 1;
|
||||
this.terminal.write("\x1b]11;?\x07");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user