Created tagged union for selection colors, enabled parsing

Implemented cell color for Metal

Removed use of selection-invert-fg-bg

Mirrored feature to OpenGL

Added tests for SelectionColor

Fixed selection on inverted cell behavior

Implemented cell colors for cursor-text

Implemented cell colors for cursor-color, removed uses of cursor-invert-fg-bg during rendering

Updated docs for dynamically colored options

Updated docstrings, cleaned up awkward formatting, and moved style computation to avoid unnecssary invocations

Bump version in docstrings
pull/5219/head
Daniel 2025-01-18 20:47:23 -06:00 committed by Mitchell Hashimoto
parent 7bb6d3b728
commit 9e341a3d60
3 changed files with 80 additions and 11 deletions

View File

@ -591,8 +591,11 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
/// the selection color is just the inverted window background and foreground /// the selection color is just the inverted window background and foreground
/// (note: not to be confused with the cell bg/fg). /// (note: not to be confused with the cell bg/fg).
/// Specified as either hex (`#RRGGBB` or `RRGGBB`) or a named X11 color. /// Specified as either hex (`#RRGGBB` or `RRGGBB`) or a named X11 color.
@"selection-foreground": ?Color = null, /// Since version 1.1.1, this can also be set to `cell-foreground` to match
@"selection-background": ?Color = null, /// the cell foreground color, or `cell-background` to match the cell
/// background color.
@"selection-foreground": ?DynamicColor = null,
@"selection-background": ?DynamicColor = null,
/// Swap the foreground and background colors of cells for selection. This /// Swap the foreground and background colors of cells for selection. This
/// option overrides the `selection-foreground` and `selection-background` /// option overrides the `selection-foreground` and `selection-background`
@ -600,6 +603,10 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
/// ///
/// If you select across cells with differing foregrounds and backgrounds, the /// If you select across cells with differing foregrounds and backgrounds, the
/// selection color will vary across the selection. /// selection color will vary across the selection.
///
/// Warning: This option has been deprecated as of version 1.1.1. Instead,
/// users should set `selection-foreground` and `selection-background` to
/// `cell-background` and `cell-foreground`, respectively.
@"selection-invert-fg-bg": bool = false, @"selection-invert-fg-bg": bool = false,
/// Whether to clear selected text when typing. This defaults to `true`. /// Whether to clear selected text when typing. This defaults to `true`.
@ -645,10 +652,17 @@ palette: Palette = .{},
/// The color of the cursor. If this is not set, a default will be chosen. /// The color of the cursor. If this is not set, a default will be chosen.
/// Specified as either hex (`#RRGGBB` or `RRGGBB`) or a named X11 color. /// Specified as either hex (`#RRGGBB` or `RRGGBB`) or a named X11 color.
@"cursor-color": ?Color = null, /// Since version 1.1.1, this can also be set to `cell-foreground` to match
/// the cell foreground color, or `cell-background` to match the cell
/// background color.
@"cursor-color": ?DynamicColor = null,
/// Swap the foreground and background colors of the cell under the cursor. This /// Swap the foreground and background colors of the cell under the cursor. This
/// option overrides the `cursor-color` and `cursor-text` options. /// option overrides the `cursor-color` and `cursor-text` options.
///
/// Warning: This option has been deprecated as of version 1.1.1. Instead,
/// users should set `cursor-color` and `cursor-text` to `cell-foreground` and
/// `cell-background`, respectively.
@"cursor-invert-fg-bg": bool = false, @"cursor-invert-fg-bg": bool = false,
/// The opacity level (opposite of transparency) of the cursor. A value of 1 /// The opacity level (opposite of transparency) of the cursor. A value of 1
@ -699,7 +713,10 @@ palette: Palette = .{},
/// The color of the text under the cursor. If this is not set, a default will /// The color of the text under the cursor. If this is not set, a default will
/// be chosen. /// be chosen.
/// Specified as either hex (`#RRGGBB` or `RRGGBB`) or a named X11 color. /// Specified as either hex (`#RRGGBB` or `RRGGBB`) or a named X11 color.
@"cursor-text": ?Color = null, /// Since version 1.1.1, this can also be set to `cell-foreground` to match
/// the cell foreground color, or `cell-background` to match the cell
/// background color.
@"cursor-text": ?DynamicColor = null,
/// Enables the ability to move the cursor at prompts by using `alt+click` on /// Enables the ability to move the cursor at prompts by using `alt+click` on
/// Linux and `option+click` on macOS. /// Linux and `option+click` on macOS.
@ -4409,6 +4426,54 @@ pub const Color = struct {
} }
}; };
/// Represents the color values that can be set to a non-static value.
///
/// Can either be a Color or one of the special values
/// "cell-foreground" or "cell-background".
pub const DynamicColor = union(enum) {
color: Color,
@"cell-foreground",
@"cell-background",
pub fn parseCLI(input_: ?[]const u8) !DynamicColor {
const input = input_ orelse return error.ValueRequired;
if (std.mem.eql(u8, input, "cell-foreground")) return .@"cell-foreground";
if (std.mem.eql(u8, input, "cell-background")) return .@"cell-background";
return DynamicColor{ .color = try Color.parseCLI(input) };
}
/// Used by Formatter
pub fn formatEntry(self: DynamicColor, formatter: anytype) !void {
switch (self) {
.color => try self.color.formatEntry(formatter),
.@"cell-foreground", .@"cell-background" => try formatter.formatEntry([:0]const u8, @tagName(self)),
}
}
test "parseCLI" {
const testing = std.testing;
try testing.expectEqual(DynamicColor{ .color = Color{ .r = 78, .g = 42, .b = 132 } }, try DynamicColor.parseCLI("#4e2a84"));
try testing.expectEqual(DynamicColor{ .color = Color{ .r = 0, .g = 0, .b = 0 } }, try DynamicColor.parseCLI("black"));
try testing.expectEqual(DynamicColor{.@"cell-foreground"}, try DynamicColor.parseCLI("cell-foreground"));
try testing.expectEqual(DynamicColor{.@"cell-background"}, try DynamicColor.parseCLI("cell-background"));
try testing.expectError(error.InvalidValue, DynamicColor.parseCLI("a"));
}
test "formatConfig" {
const testing = std.testing;
var buf = std.ArrayList(u8).init(testing.allocator);
defer buf.deinit();
var sc: DynamicColor = .{.@"cell-foreground"};
try sc.formatEntry(formatterpkg.entryFormatter("a", buf.writer()));
try testing.expectEqualSlices(u8, "a = cell-foreground\n", buf.items);
}
};
pub const ColorList = struct { pub const ColorList = struct {
const Self = @This(); const Self = @This();

View File

@ -163,8 +163,7 @@ pub const DerivedConfig = struct {
image_storage_limit: usize, image_storage_limit: usize,
cursor_style: terminalpkg.CursorStyle, cursor_style: terminalpkg.CursorStyle,
cursor_blink: ?bool, cursor_blink: ?bool,
cursor_color: ?configpkg.Config.Color, cursor_color: ?configpkg.Config.DynamicColor,
cursor_invert: bool,
foreground: configpkg.Config.Color, foreground: configpkg.Config.Color,
background: configpkg.Config.Color, background: configpkg.Config.Color,
osc_color_report_format: configpkg.Config.OSCColorReportFormat, osc_color_report_format: configpkg.Config.OSCColorReportFormat,
@ -185,7 +184,6 @@ pub const DerivedConfig = struct {
.cursor_style = config.@"cursor-style", .cursor_style = config.@"cursor-style",
.cursor_blink = config.@"cursor-style-blink", .cursor_blink = config.@"cursor-style-blink",
.cursor_color = config.@"cursor-color", .cursor_color = config.@"cursor-color",
.cursor_invert = config.@"cursor-invert-fg-bg",
.foreground = config.foreground, .foreground = config.foreground,
.background = config.background, .background = config.background,
.osc_color_report_format = config.@"osc-color-report-format", .osc_color_report_format = config.@"osc-color-report-format",
@ -265,8 +263,11 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
// Create our stream handler. This points to memory in self so it // Create our stream handler. This points to memory in self so it
// isn't safe to use until self.* is set. // isn't safe to use until self.* is set.
const handler: StreamHandler = handler: { const handler: StreamHandler = handler: {
const default_cursor_color = if (!opts.config.cursor_invert and opts.config.cursor_color != null) const default_cursor_color = if (opts.config.cursor_color) |color|
opts.config.cursor_color.?.toTerminalRGB() switch (color) {
.color => color.color.toTerminalRGB(),
else => null,
}
else else
null; null;

View File

@ -121,8 +121,11 @@ pub const StreamHandler = struct {
self.default_background_color = config.background.toTerminalRGB(); self.default_background_color = config.background.toTerminalRGB();
self.default_cursor_style = config.cursor_style; self.default_cursor_style = config.cursor_style;
self.default_cursor_blink = config.cursor_blink; self.default_cursor_blink = config.cursor_blink;
self.default_cursor_color = if (!config.cursor_invert and config.cursor_color != null) self.default_cursor_color = if (config.cursor_color) |color|
config.cursor_color.?.toTerminalRGB() switch (color) {
.color => color.color.toTerminalRGB(),
else => null,
}
else else
null; null;