mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
core: implement OSC 104, 110, and 111 to reset colors
This commit is contained in:
@ -67,6 +67,14 @@ font_shaper: font.Shaper,
|
|||||||
/// True if the window is focused
|
/// True if the window is focused
|
||||||
focused: bool,
|
focused: bool,
|
||||||
|
|
||||||
|
/// The actual foreground color. May differ from the config foreground color if
|
||||||
|
/// changed by a terminal application
|
||||||
|
foreground_color: terminal.color.RGB,
|
||||||
|
|
||||||
|
/// The actual background color. May differ from the config background color if
|
||||||
|
/// changed by a terminal application
|
||||||
|
background_color: terminal.color.RGB,
|
||||||
|
|
||||||
/// Padding options
|
/// Padding options
|
||||||
padding: renderer.Options.Padding,
|
padding: renderer.Options.Padding,
|
||||||
|
|
||||||
@ -310,6 +318,8 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
|||||||
.font_shaper = shaper,
|
.font_shaper = shaper,
|
||||||
.draw_background = options.config.background,
|
.draw_background = options.config.background,
|
||||||
.focused = true,
|
.focused = true,
|
||||||
|
.foreground_color = options.config.foreground,
|
||||||
|
.background_color = options.config.background,
|
||||||
.padding = options.padding,
|
.padding = options.padding,
|
||||||
.surface_mailbox = options.surface_mailbox,
|
.surface_mailbox = options.surface_mailbox,
|
||||||
.deferred_font_size = .{ .metrics = metrics },
|
.deferred_font_size = .{ .metrics = metrics },
|
||||||
@ -586,15 +596,15 @@ pub fn render(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Swap bg/fg if the terminal is reversed
|
// Swap bg/fg if the terminal is reversed
|
||||||
const bg = self.config.background;
|
const bg = self.background_color;
|
||||||
const fg = self.config.foreground;
|
const fg = self.foreground_color;
|
||||||
defer {
|
defer {
|
||||||
self.config.background = bg;
|
self.background_color = bg;
|
||||||
self.config.foreground = fg;
|
self.foreground_color = fg;
|
||||||
}
|
}
|
||||||
if (state.terminal.modes.get(.reverse_colors)) {
|
if (state.terminal.modes.get(.reverse_colors)) {
|
||||||
self.config.background = fg;
|
self.background_color = fg;
|
||||||
self.config.foreground = bg;
|
self.foreground_color = bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We used to share terminal state, but we've since learned through
|
// We used to share terminal state, but we've since learned through
|
||||||
@ -627,7 +637,7 @@ pub fn render(
|
|||||||
);
|
);
|
||||||
|
|
||||||
break :critical .{
|
break :critical .{
|
||||||
.gl_bg = self.config.background,
|
.gl_bg = self.background_color,
|
||||||
.selection = selection,
|
.selection = selection,
|
||||||
.screen = screen_copy,
|
.screen = screen_copy,
|
||||||
.preedit = if (cursor_style != null) state.preedit else null,
|
.preedit = if (cursor_style != null) state.preedit else null,
|
||||||
@ -878,7 +888,7 @@ fn addCursor(
|
|||||||
), screen.cursor.x - 1 };
|
), screen.cursor.x - 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
const color = self.config.cursor_color orelse self.config.foreground;
|
const color = self.config.cursor_color orelse self.foreground_color;
|
||||||
const alpha: u8 = if (!self.focused) 255 else alpha: {
|
const alpha: u8 = if (!self.focused) 255 else alpha: {
|
||||||
const alpha = 255 * self.config.cursor_opacity;
|
const alpha = 255 * self.config.cursor_opacity;
|
||||||
break :alpha @intFromFloat(@ceil(alpha));
|
break :alpha @intFromFloat(@ceil(alpha));
|
||||||
@ -1010,21 +1020,21 @@ pub fn updateCell(
|
|||||||
const colors: BgFg = colors: {
|
const colors: BgFg = colors: {
|
||||||
// If we are selected, we our colors are just inverted fg/bg
|
// If we are selected, we our colors are just inverted fg/bg
|
||||||
var selection_res: ?BgFg = if (selected) .{
|
var selection_res: ?BgFg = if (selected) .{
|
||||||
.bg = self.config.selection_background orelse self.config.foreground,
|
.bg = self.config.selection_background orelse self.foreground_color,
|
||||||
.fg = self.config.selection_foreground orelse self.config.background,
|
.fg = self.config.selection_foreground orelse self.background_color,
|
||||||
} else null;
|
} else null;
|
||||||
|
|
||||||
const res: BgFg = selection_res orelse if (!cell.attrs.inverse) .{
|
const res: BgFg = selection_res orelse if (!cell.attrs.inverse) .{
|
||||||
// In normal mode, background and fg match the cell. We
|
// In normal mode, background and fg match the cell. We
|
||||||
// un-optionalize the fg by defaulting to our fg color.
|
// un-optionalize the fg by defaulting to our fg color.
|
||||||
.bg = if (cell.attrs.has_bg) cell.bg else null,
|
.bg = if (cell.attrs.has_bg) cell.bg else null,
|
||||||
.fg = if (cell.attrs.has_fg) cell.fg else self.config.foreground,
|
.fg = if (cell.attrs.has_fg) cell.fg else self.foreground_color,
|
||||||
} else .{
|
} else .{
|
||||||
// In inverted mode, the background MUST be set to something
|
// In inverted mode, the background MUST be set to something
|
||||||
// (is never null) so it is either the fg or default fg. The
|
// (is never null) so it is either the fg or default fg. The
|
||||||
// fg is either the bg or default background.
|
// fg is either the bg or default background.
|
||||||
.bg = if (cell.attrs.has_fg) cell.fg else self.config.foreground,
|
.bg = if (cell.attrs.has_fg) cell.fg else self.foreground_color,
|
||||||
.fg = if (cell.attrs.has_bg) cell.bg else self.config.background,
|
.fg = if (cell.attrs.has_bg) cell.bg else self.background_color,
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the cell is "invisible" then we just make fg = bg so that
|
// If the cell is "invisible" then we just make fg = bg so that
|
||||||
@ -1032,7 +1042,7 @@ pub fn updateCell(
|
|||||||
if (cell.attrs.invisible) {
|
if (cell.attrs.invisible) {
|
||||||
break :colors BgFg{
|
break :colors BgFg{
|
||||||
.bg = res.bg,
|
.bg = res.bg,
|
||||||
.fg = res.bg orelse self.config.background,
|
.fg = res.bg orelse self.background_color,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,7 +1080,7 @@ pub fn updateCell(
|
|||||||
|
|
||||||
// If we have a background and its not the default background
|
// If we have a background and its not the default background
|
||||||
// then we apply background opacity
|
// then we apply background opacity
|
||||||
if (cell.attrs.has_bg and !std.meta.eql(rgb, self.config.background)) {
|
if (cell.attrs.has_bg and !std.meta.eql(rgb, self.background_color)) {
|
||||||
break :bg_alpha alpha;
|
break :bg_alpha alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,11 +22,11 @@ pub const Message = union(enum) {
|
|||||||
font_size: font.face.DesiredSize,
|
font_size: font.face.DesiredSize,
|
||||||
|
|
||||||
/// Change the foreground color. This can be done separately from changing
|
/// Change the foreground color. This can be done separately from changing
|
||||||
/// the config file in response to an OSC 10 command
|
/// the config file in response to an OSC 10 command.
|
||||||
foreground_color: terminal.color.RGB,
|
foreground_color: terminal.color.RGB,
|
||||||
|
|
||||||
/// Change the background color. This can be done separately from changing
|
/// Change the background color. This can be done separately from changing
|
||||||
/// the config file in response to an OSC 11 command
|
/// the config file in response to an OSC 11 command.
|
||||||
background_color: terminal.color.RGB,
|
background_color: terminal.color.RGB,
|
||||||
|
|
||||||
/// Changes the screen size.
|
/// Changes the screen size.
|
||||||
|
@ -75,8 +75,16 @@ scrolling_region: ScrollingRegion,
|
|||||||
/// The last reported pwd, if any.
|
/// The last reported pwd, if any.
|
||||||
pwd: std.ArrayList(u8),
|
pwd: std.ArrayList(u8),
|
||||||
|
|
||||||
/// The color palette to use
|
/// The default color palette. This is only modified by changing the config file
|
||||||
color_palette: color.Palette = color.default,
|
/// and is used to reset the palette when receiving an OSC 104 command.
|
||||||
|
default_palette: color.Palette = color.default,
|
||||||
|
|
||||||
|
/// The color palette to use. The mask indicates which palette indices have been
|
||||||
|
/// modified with OSC 4
|
||||||
|
color_palette: struct {
|
||||||
|
colors: color.Palette = color.default,
|
||||||
|
mask: u256 = 0,
|
||||||
|
} = .{},
|
||||||
|
|
||||||
/// The previous printed character. This is used for the repeat previous
|
/// The previous printed character. This is used for the repeat previous
|
||||||
/// char CSI (ESC [ <n> b).
|
/// char CSI (ESC [ <n> b).
|
||||||
@ -560,12 +568,12 @@ pub fn setAttribute(self: *Terminal, attr: sgr.Attribute) !void {
|
|||||||
|
|
||||||
.@"8_fg" => |n| {
|
.@"8_fg" => |n| {
|
||||||
self.screen.cursor.pen.attrs.has_fg = true;
|
self.screen.cursor.pen.attrs.has_fg = true;
|
||||||
self.screen.cursor.pen.fg = self.color_palette[@intFromEnum(n)];
|
self.screen.cursor.pen.fg = self.color_palette.colors[@intFromEnum(n)];
|
||||||
},
|
},
|
||||||
|
|
||||||
.@"8_bg" => |n| {
|
.@"8_bg" => |n| {
|
||||||
self.screen.cursor.pen.attrs.has_bg = true;
|
self.screen.cursor.pen.attrs.has_bg = true;
|
||||||
self.screen.cursor.pen.bg = self.color_palette[@intFromEnum(n)];
|
self.screen.cursor.pen.bg = self.color_palette.colors[@intFromEnum(n)];
|
||||||
},
|
},
|
||||||
|
|
||||||
.reset_fg => self.screen.cursor.pen.attrs.has_fg = false,
|
.reset_fg => self.screen.cursor.pen.attrs.has_fg = false,
|
||||||
@ -574,22 +582,22 @@ pub fn setAttribute(self: *Terminal, attr: sgr.Attribute) !void {
|
|||||||
|
|
||||||
.@"8_bright_fg" => |n| {
|
.@"8_bright_fg" => |n| {
|
||||||
self.screen.cursor.pen.attrs.has_fg = true;
|
self.screen.cursor.pen.attrs.has_fg = true;
|
||||||
self.screen.cursor.pen.fg = self.color_palette[@intFromEnum(n)];
|
self.screen.cursor.pen.fg = self.color_palette.colors[@intFromEnum(n)];
|
||||||
},
|
},
|
||||||
|
|
||||||
.@"8_bright_bg" => |n| {
|
.@"8_bright_bg" => |n| {
|
||||||
self.screen.cursor.pen.attrs.has_bg = true;
|
self.screen.cursor.pen.attrs.has_bg = true;
|
||||||
self.screen.cursor.pen.bg = self.color_palette[@intFromEnum(n)];
|
self.screen.cursor.pen.bg = self.color_palette.colors[@intFromEnum(n)];
|
||||||
},
|
},
|
||||||
|
|
||||||
.@"256_fg" => |idx| {
|
.@"256_fg" => |idx| {
|
||||||
self.screen.cursor.pen.attrs.has_fg = true;
|
self.screen.cursor.pen.attrs.has_fg = true;
|
||||||
self.screen.cursor.pen.fg = self.color_palette[idx];
|
self.screen.cursor.pen.fg = self.color_palette.colors[idx];
|
||||||
},
|
},
|
||||||
|
|
||||||
.@"256_bg" => |idx| {
|
.@"256_bg" => |idx| {
|
||||||
self.screen.cursor.pen.attrs.has_bg = true;
|
self.screen.cursor.pen.attrs.has_bg = true;
|
||||||
self.screen.cursor.pen.bg = self.color_palette[idx];
|
self.screen.cursor.pen.bg = self.color_palette.colors[idx];
|
||||||
},
|
},
|
||||||
|
|
||||||
.unknown => return error.InvalidAttribute,
|
.unknown => return error.InvalidAttribute,
|
||||||
|
@ -98,32 +98,43 @@ pub const Command = union(enum) {
|
|||||||
report_color: struct {
|
report_color: struct {
|
||||||
/// OSC 4 requests a palette color, OSC 10 requests the foreground
|
/// OSC 4 requests a palette color, OSC 10 requests the foreground
|
||||||
/// color, OSC 11 the background color.
|
/// color, OSC 11 the background color.
|
||||||
kind: DefaultColorKind,
|
kind: ColorKind,
|
||||||
|
|
||||||
/// We must reply with the same string terminator (ST) as used in the
|
/// We must reply with the same string terminator (ST) as used in the
|
||||||
/// request.
|
/// request.
|
||||||
terminator: Terminator = .st,
|
terminator: Terminator = .st,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Modify the foreground (OSC 10) or background color (OSC 11), or a palette color (OSC 4)
|
||||||
set_color: struct {
|
set_color: struct {
|
||||||
/// OSC 4 sets a palette color, OSC 10 sets the foreground color, OSC 11
|
/// OSC 4 sets a palette color, OSC 10 sets the foreground color, OSC 11
|
||||||
/// the background color.
|
/// the background color.
|
||||||
kind: DefaultColorKind,
|
kind: ColorKind,
|
||||||
|
|
||||||
/// The color spec as a string
|
/// The color spec as a string
|
||||||
value: []const u8,
|
value: []const u8,
|
||||||
},
|
},
|
||||||
|
|
||||||
pub const DefaultColorKind = union(enum) {
|
/// Reset a palette color (OSC 104) or the foreground (OSC 110), background
|
||||||
|
/// (OSC 111), or cursor (OSC 112) color.
|
||||||
|
reset_color: struct {
|
||||||
|
kind: ColorKind,
|
||||||
|
|
||||||
|
/// OSC 104 can have parameters indicating which palette colors to
|
||||||
|
/// reset.
|
||||||
|
value: []const u8,
|
||||||
|
},
|
||||||
|
|
||||||
|
pub const ColorKind = union(enum) {
|
||||||
|
palette: u8,
|
||||||
foreground,
|
foreground,
|
||||||
background,
|
background,
|
||||||
palette: u8,
|
|
||||||
|
|
||||||
pub fn code(self: DefaultColorKind) []const u8 {
|
pub fn code(self: ColorKind) []const u8 {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
|
.palette => "4",
|
||||||
.foreground => "10",
|
.foreground => "10",
|
||||||
.background => "11",
|
.background => "11",
|
||||||
.palette => "4",
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -216,13 +227,11 @@ pub const Parser = struct {
|
|||||||
@"52",
|
@"52",
|
||||||
@"7",
|
@"7",
|
||||||
|
|
||||||
// OSC 10 is used to query the default foreground color, and to set the default foreground color.
|
// OSC 10 is used to query or set the current foreground color.
|
||||||
// Only querying is currently supported.
|
query_fg_color,
|
||||||
query_default_fg,
|
|
||||||
|
|
||||||
// OSC 11 is used to query the default background color, and to set the default background color.
|
// OSC 11 is used to query or set the current background color.
|
||||||
// Only querying is currently supported.
|
query_bg_color,
|
||||||
query_default_bg,
|
|
||||||
|
|
||||||
// We're in a semantic prompt OSC command but we aren't sure
|
// We're in a semantic prompt OSC command but we aren't sure
|
||||||
// what the command is yet, i.e. `133;`
|
// what the command is yet, i.e. `133;`
|
||||||
@ -241,6 +250,9 @@ pub const Parser = struct {
|
|||||||
color_palette_index,
|
color_palette_index,
|
||||||
color_palette_index_end,
|
color_palette_index_end,
|
||||||
|
|
||||||
|
// Reset color palette index
|
||||||
|
reset_color_palette_index,
|
||||||
|
|
||||||
// Expect a string parameter. param_str must be set as well as
|
// Expect a string parameter. param_str must be set as well as
|
||||||
// buf_start.
|
// buf_start.
|
||||||
string,
|
string,
|
||||||
@ -319,12 +331,31 @@ pub const Parser = struct {
|
|||||||
},
|
},
|
||||||
|
|
||||||
.@"10" => switch (c) {
|
.@"10" => switch (c) {
|
||||||
';' => self.state = .query_default_fg,
|
';' => self.state = .query_fg_color,
|
||||||
|
'4' => {
|
||||||
|
self.command = .{ .reset_color = .{
|
||||||
|
.kind = .{ .palette = 0 },
|
||||||
|
.value = "",
|
||||||
|
} };
|
||||||
|
|
||||||
|
self.state = .reset_color_palette_index;
|
||||||
|
self.complete = true;
|
||||||
|
},
|
||||||
else => self.state = .invalid,
|
else => self.state = .invalid,
|
||||||
},
|
},
|
||||||
|
|
||||||
.@"11" => switch (c) {
|
.@"11" => switch (c) {
|
||||||
';' => self.state = .query_default_bg,
|
';' => self.state = .query_bg_color,
|
||||||
|
'0' => {
|
||||||
|
self.command = .{ .reset_color = .{ .kind = .foreground, .value = undefined } };
|
||||||
|
self.complete = true;
|
||||||
|
self.state = .invalid;
|
||||||
|
},
|
||||||
|
'1' => {
|
||||||
|
self.command = .{ .reset_color = .{ .kind = .background, .value = undefined } };
|
||||||
|
self.complete = true;
|
||||||
|
self.state = .invalid;
|
||||||
|
},
|
||||||
'2' => {
|
'2' => {
|
||||||
self.complete = true;
|
self.complete = true;
|
||||||
self.command = .{ .reset_cursor_color = {} };
|
self.command = .{ .reset_cursor_color = {} };
|
||||||
@ -408,6 +439,19 @@ pub const Parser = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.reset_color_palette_index => switch (c) {
|
||||||
|
';' => {
|
||||||
|
self.state = .string;
|
||||||
|
self.temp_state = .{ .str = &self.command.reset_color.value };
|
||||||
|
self.buf_start = self.buf_idx;
|
||||||
|
self.complete = false;
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
self.state = .invalid;
|
||||||
|
self.complete = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
.@"5" => switch (c) {
|
.@"5" => switch (c) {
|
||||||
'2' => self.state = .@"52",
|
'2' => self.state = .@"52",
|
||||||
else => self.state = .invalid,
|
else => self.state = .invalid,
|
||||||
@ -454,10 +498,11 @@ pub const Parser = struct {
|
|||||||
else => self.state = .invalid,
|
else => self.state = .invalid,
|
||||||
},
|
},
|
||||||
|
|
||||||
.query_default_fg => switch (c) {
|
.query_fg_color => switch (c) {
|
||||||
'?' => {
|
'?' => {
|
||||||
self.command = .{ .report_color = .{ .kind = .foreground } };
|
self.command = .{ .report_color = .{ .kind = .foreground } };
|
||||||
self.complete = true;
|
self.complete = true;
|
||||||
|
self.state = .invalid;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
self.command = .{ .set_color = .{
|
self.command = .{ .set_color = .{
|
||||||
@ -471,10 +516,11 @@ pub const Parser = struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
.query_default_bg => switch (c) {
|
.query_bg_color => switch (c) {
|
||||||
'?' => {
|
'?' => {
|
||||||
self.command = .{ .report_color = .{ .kind = .background } };
|
self.command = .{ .report_color = .{ .kind = .background } };
|
||||||
self.complete = true;
|
self.complete = true;
|
||||||
|
self.state = .invalid;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
self.command = .{ .set_color = .{
|
self.command = .{ .set_color = .{
|
||||||
|
@ -1059,10 +1059,12 @@ pub fn Stream(comptime Handler: type) type {
|
|||||||
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||||
},
|
},
|
||||||
|
|
||||||
else => if (@hasDecl(T, "oscUnimplemented"))
|
.reset_color => |v| {
|
||||||
try self.handler.oscUnimplemented(cmd)
|
if (@hasDecl(T, "resetColor")) {
|
||||||
else
|
try self.handler.resetColor(v.kind, v.value);
|
||||||
log.warn("unimplemented OSC command: {}", .{cmd}),
|
return;
|
||||||
|
} else log.warn("unimplemented OSC callback: {}", .{cmd});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall through for when we don't have a handler.
|
// Fall through for when we don't have a handler.
|
||||||
|
@ -138,7 +138,7 @@ pub fn init(alloc: Allocator, opts: termio.Options) !Exec {
|
|||||||
opts.grid_size.rows,
|
opts.grid_size.rows,
|
||||||
);
|
);
|
||||||
errdefer term.deinit(alloc);
|
errdefer term.deinit(alloc);
|
||||||
term.color_palette = opts.config.palette;
|
term.default_palette = opts.config.palette;
|
||||||
|
|
||||||
// Set the image size limits
|
// Set the image size limits
|
||||||
try term.screen.kitty_images.setLimit(alloc, opts.config.image_storage_limit);
|
try term.screen.kitty_images.setLimit(alloc, opts.config.image_storage_limit);
|
||||||
@ -332,7 +332,7 @@ pub fn changeConfig(self: *Exec, config: *DerivedConfig) !void {
|
|||||||
|
|
||||||
// Update the palette. Note this will only apply to new colors drawn
|
// Update the palette. Note this will only apply to new colors drawn
|
||||||
// since we decode all palette colors to RGB on usage.
|
// since we decode all palette colors to RGB on usage.
|
||||||
self.terminal.color_palette = config.palette;
|
self.terminal.default_palette = config.palette;
|
||||||
|
|
||||||
// Update our default cursor style
|
// Update our default cursor style
|
||||||
self.default_cursor_style = config.cursor_style;
|
self.default_cursor_style = config.cursor_style;
|
||||||
@ -2179,15 +2179,15 @@ const StreamHandler = struct {
|
|||||||
/// default foreground color, and background color respectively.
|
/// default foreground color, and background color respectively.
|
||||||
pub fn reportColor(
|
pub fn reportColor(
|
||||||
self: *StreamHandler,
|
self: *StreamHandler,
|
||||||
kind: terminal.osc.Command.DefaultColorKind,
|
kind: terminal.osc.Command.ColorKind,
|
||||||
terminator: terminal.osc.Terminator,
|
terminator: terminal.osc.Terminator,
|
||||||
) !void {
|
) !void {
|
||||||
if (self.osc_color_report_format == .none) return;
|
if (self.osc_color_report_format == .none) return;
|
||||||
|
|
||||||
const color = switch (kind) {
|
const color = switch (kind) {
|
||||||
|
.palette => |i| self.terminal.color_palette.colors[i],
|
||||||
.foreground => self.foreground_color,
|
.foreground => self.foreground_color,
|
||||||
.background => self.background_color,
|
.background => self.background_color,
|
||||||
.palette => |i| self.terminal.color_palette[i],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var msg: termio.Message = .{ .write_small = .{} };
|
var msg: termio.Message = .{ .write_small = .{} };
|
||||||
@ -2224,12 +2224,16 @@ const StreamHandler = struct {
|
|||||||
|
|
||||||
pub fn setColor(
|
pub fn setColor(
|
||||||
self: *StreamHandler,
|
self: *StreamHandler,
|
||||||
kind: terminal.osc.Command.DefaultColorKind,
|
kind: terminal.osc.Command.ColorKind,
|
||||||
value: []const u8,
|
value: []const u8,
|
||||||
) !void {
|
) !void {
|
||||||
const color = try terminal.color.RGB.parse(value);
|
const color = try terminal.color.RGB.parse(value);
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
.palette => |i| {
|
||||||
|
self.terminal.color_palette.colors[i] = color;
|
||||||
|
self.terminal.color_palette.mask |= @as(u256, 1) << i;
|
||||||
|
},
|
||||||
.foreground => {
|
.foreground => {
|
||||||
self.foreground_color = color;
|
self.foreground_color = color;
|
||||||
_ = self.ev.renderer_mailbox.push(.{
|
_ = self.ev.renderer_mailbox.push(.{
|
||||||
@ -2242,7 +2246,55 @@ const StreamHandler = struct {
|
|||||||
.background_color = color,
|
.background_color = color,
|
||||||
}, .{ .forever = {} });
|
}, .{ .forever = {} });
|
||||||
},
|
},
|
||||||
.palette => |i| self.terminal.color_palette[i] = color,
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resetColor(
|
||||||
|
self: *StreamHandler,
|
||||||
|
kind: terminal.osc.Command.ColorKind,
|
||||||
|
value: []const u8,
|
||||||
|
) !void {
|
||||||
|
switch (kind) {
|
||||||
|
.palette => {
|
||||||
|
var mask = self.terminal.color_palette.mask;
|
||||||
|
defer self.terminal.color_palette.mask = mask;
|
||||||
|
|
||||||
|
if (value.len == 0) {
|
||||||
|
// Find all bit positions in the mask which are set and
|
||||||
|
// reset those indices to the default palette
|
||||||
|
while (mask != 0) {
|
||||||
|
// Safe to truncate, mask is non-zero so @ctz can never
|
||||||
|
// return a u9
|
||||||
|
const i: u8 = @truncate(@ctz(mask));
|
||||||
|
log.warn("Resetting palette color {}", .{i});
|
||||||
|
self.terminal.color_palette.colors[i] = self.terminal.default_palette[i];
|
||||||
|
mask ^= @as(u256, 1) << i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var it = std.mem.tokenizeScalar(u8, value, ';');
|
||||||
|
while (it.next()) |param| {
|
||||||
|
// Skip invalid parameters
|
||||||
|
const i = std.fmt.parseUnsigned(u8, param, 10) catch continue;
|
||||||
|
log.warn("Resetting palette color {}", .{i});
|
||||||
|
if (mask & (@as(u256, 1) << i) != 0) {
|
||||||
|
self.terminal.color_palette.colors[i] = self.terminal.default_palette[i];
|
||||||
|
mask ^= @as(u256, 1) << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.foreground => {
|
||||||
|
self.foreground_color = self.default_foreground_color;
|
||||||
|
_ = self.ev.renderer_mailbox.push(.{
|
||||||
|
.foreground_color = self.foreground_color,
|
||||||
|
}, .{ .forever = {} });
|
||||||
|
},
|
||||||
|
.background => {
|
||||||
|
self.background_color = self.default_background_color;
|
||||||
|
_ = self.ev.renderer_mailbox.push(.{
|
||||||
|
.background_color = self.background_color,
|
||||||
|
}, .{ .forever = {} });
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user