Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions packages/core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
type CursorStyle,
DebugOverlayCorner,
type RenderContext,
type ThemeMode,
type ViewportBounds,
type WidthMethod,
} from "./types"
Expand Down Expand Up @@ -429,6 +430,7 @@ export class CliRenderer extends EventEmitter implements RenderContext {
private _cachedPalette: TerminalColors | null = null
private _paletteDetectionPromise: Promise<TerminalColors> | null = null
private _onDestroy?: () => void
private _themeMode: ThemeMode | null = null

private inputHandlers: ((sequence: string) => boolean)[] = []
private prependedInputHandlers: ((sequence: string) => boolean)[] = []
Expand Down Expand Up @@ -848,6 +850,10 @@ export class CliRenderer extends EventEmitter implements RenderContext {
return this._capabilities
}

public get themeMode(): ThemeMode | null {
return this._themeMode
}

public getDebugInputs(): Array<{ timestamp: string; sequence: string }> {
return [...this._debugInputs]
}
Expand Down Expand Up @@ -1065,6 +1071,24 @@ export class CliRenderer extends EventEmitter implements RenderContext {
return false
}).bind(this)

private themeModeHandler: (sequence: string) => boolean = ((sequence: string) => {
if (sequence === "\x1b[?997;1n") {
if (this._themeMode !== "dark") {
this._themeMode = "dark"
this.emit("theme_mode", "dark")
}
return true
}
if (sequence === "\x1b[?997;2n") {
if (this._themeMode !== "light") {
this._themeMode = "light"
this.emit("theme_mode", "light")
}
return true
}
return false
}).bind(this)

private setupInput(): void {
for (const handler of this.prependedInputHandlers) {
this.addInputHandler(handler)
Expand All @@ -1083,6 +1107,7 @@ export class CliRenderer extends EventEmitter implements RenderContext {
})
this.addInputHandler(this.capabilityHandler)
this.addInputHandler(this.focusHandler)
this.addInputHandler(this.themeModeHandler)
this.addInputHandler((sequence: string) => {
return this._keyHandler.processInput(sequence)
})
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export function getBaseAttributes(attr: number): number {
return attr & ATTRIBUTE_BASE_MASK
}

export type ThemeMode = "dark" | "light"

export type CursorStyle = "block" | "line" | "underline"

export interface CursorStyleOptions {
Expand All @@ -50,6 +52,7 @@ export interface RendererEvents {
"memory:snapshot": (snapshot: { heapUsed: number; heapTotal: number; arrayBuffers: number }) => void
selection: (selection: Selection) => void
"debugOverlay:toggle": (enabled: boolean) => void
theme_mode: (mode: ThemeMode) => void
}

export interface RenderContext extends EventEmitter {
Expand Down
16 changes: 13 additions & 3 deletions packages/core/src/zig/terminal.zig
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,7 @@ pub fn resetState(self: *Terminal, tty: anytype) !void {
}

if (self.state.color_scheme_updates) {
try tty.writeAll(ansi.ANSI.colorSchemeReset);
self.state.color_scheme_updates = false;
try self.setColorSchemeUpdates(tty, false);
}

self.setTerminalTitle(tty, "");
Expand Down Expand Up @@ -271,6 +270,11 @@ pub fn enableDetectedFeatures(self: *Terminal, tty: anytype, use_kitty_keyboard:
if (self.caps.focus_tracking) {
try self.setFocusTracking(tty, true);
}

if (!self.state.color_scheme_updates) {
try self.setColorSchemeUpdates(tty, true);
try tty.writeAll(ansi.ANSI.colorSchemeRequest);
}
}

fn checkEnvironmentOverrides(self: *Terminal) void {
Expand Down Expand Up @@ -491,6 +495,12 @@ pub fn setModifyOtherKeys(self: *Terminal, tty: anytype, enable: bool) !void {
self.state.modify_other_keys = enable;
}

pub fn setColorSchemeUpdates(self: *Terminal, tty: anytype, enable: bool) !void {
const seq = if (enable) ansi.ANSI.colorSchemeSet else ansi.ANSI.colorSchemeReset;
try tty.writeAll(seq);
self.state.color_scheme_updates = enable;
}

/// Re-send all currently-active terminal mode escape sequences unconditionally.
///
/// When the terminal loses and regains focus (e.g. alt-tab, tab switch, minimize),
Expand Down Expand Up @@ -562,7 +572,7 @@ pub fn processCapabilityResponse(self: *Terminal, response: []const u8) void {
if (std.mem.indexOf(u8, response, "2027;2$y")) |_| {
self.caps.unicode = .unicode;
}
if (std.mem.indexOf(u8, response, "2031;2$y")) |_| {
if (std.mem.indexOf(u8, response, "2031;1$y") != null or std.mem.indexOf(u8, response, "2031;2$y") != null) {
self.caps.color_scheme_updates = true;
}
if (std.mem.indexOf(u8, response, "1004;1$y") != null or std.mem.indexOf(u8, response, "1004;2$y") != null) {
Expand Down
Loading