mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-20 10:46:07 +03:00
Configurable 256 Color Palette (#50)
The 256 color palette can now be configured with the `palette=N=HEX` format in the config. Example, Dracula: ``` foreground=#f8f8f2 background=#282a36 palette=0=#21222c palette=8=#6272a4 palette=1=#ff5555 palette=9=#ff6e6e palette=2=#50fa7b palette=10=#69ff94 palette=3=#f1fa8c palette=11=#ffffa5 palette=4=#bd93f9 palette=12=#d6acff palette=5=#ff79c6 palette=13=#ff92df palette=6=#8be9fd palette=14=#a4ffff palette=7=#f8f8f2 palette=15=#ffffff ```
This commit is contained in:

committed by
GitHub

parent
89834c1412
commit
01573819ea
@ -4,6 +4,7 @@ const Allocator = std.mem.Allocator;
|
|||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||||
const inputpkg = @import("input.zig");
|
const inputpkg = @import("input.zig");
|
||||||
const passwd = @import("passwd.zig");
|
const passwd = @import("passwd.zig");
|
||||||
|
const terminal = @import("terminal/main.zig");
|
||||||
|
|
||||||
const log = std.log.scoped(.config);
|
const log = std.log.scoped(.config);
|
||||||
|
|
||||||
@ -35,6 +36,16 @@ pub const Config = struct {
|
|||||||
/// Foreground color for the window.
|
/// Foreground color for the window.
|
||||||
foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
|
foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
|
||||||
|
|
||||||
|
/// Color palette for the 256 color form that many terminal applications
|
||||||
|
/// use. The syntax of this configuration is "N=HEXCODE" where "n"
|
||||||
|
/// is 0 to 255 (for the 256 colors) and HEXCODE is a typical RGB
|
||||||
|
/// color code such as "#AABBCC". The 0 to 255 correspond to the
|
||||||
|
/// terminal color table.
|
||||||
|
///
|
||||||
|
/// For definitions on all the codes:
|
||||||
|
/// https://www.ditig.com/256-colors-cheat-sheet
|
||||||
|
palette: Palette = .{},
|
||||||
|
|
||||||
/// The command to run, usually a shell. If this is not an absolute path,
|
/// The command to run, usually a shell. If this is not an absolute path,
|
||||||
/// it'll be looked up in the PATH. If this is not set, a default will
|
/// it'll be looked up in the PATH. If this is not set, a default will
|
||||||
/// be looked up from your system. The rules for the default lookup are:
|
/// be looked up from your system. The rules for the default lookup are:
|
||||||
@ -347,6 +358,49 @@ pub const Color = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Palette is the 256 color palette for 256-color mode. This is still
|
||||||
|
/// used by many terminal applications.
|
||||||
|
pub const Palette = struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
/// The actual value that is updated as we parse.
|
||||||
|
value: terminal.color.Palette = terminal.color.default,
|
||||||
|
|
||||||
|
pub const Error = error{
|
||||||
|
InvalidFormat,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn parseCLI(
|
||||||
|
self: *Self,
|
||||||
|
input: ?[]const u8,
|
||||||
|
) !void {
|
||||||
|
const value = input orelse return error.ValueRequired;
|
||||||
|
const eqlIdx = std.mem.indexOf(u8, value, "=") orelse
|
||||||
|
return Error.InvalidFormat;
|
||||||
|
|
||||||
|
const key = try std.fmt.parseInt(u8, value[0..eqlIdx], 10);
|
||||||
|
const rgb = try Color.parseCLI(value[eqlIdx + 1 ..]);
|
||||||
|
self.value[key] = .{ .r = rgb.r, .g = rgb.g, .b = rgb.b };
|
||||||
|
}
|
||||||
|
|
||||||
|
test "parseCLI" {
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
var p: Self = .{};
|
||||||
|
try p.parseCLI("0=#AABBCC");
|
||||||
|
try testing.expect(p.value[0].r == 0xAA);
|
||||||
|
try testing.expect(p.value[0].g == 0xBB);
|
||||||
|
try testing.expect(p.value[0].b == 0xCC);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "parseCLI overflow" {
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
var p: Self = .{};
|
||||||
|
try testing.expectError(error.Overflow, p.parseCLI("256=#AABBCC"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// RepeatableString is a string value that can be repeated to accumulate
|
/// RepeatableString is a string value that can be repeated to accumulate
|
||||||
/// a list of strings. This isn't called "StringList" because I find that
|
/// a list of strings. This isn't called "StringList" because I find that
|
||||||
/// sometimes leads to confusion that it _accepts_ a list such as
|
/// sometimes leads to confusion that it _accepts_ a list such as
|
||||||
|
@ -60,6 +60,9 @@ scrolling_region: ScrollingRegion,
|
|||||||
/// The charset state
|
/// The charset state
|
||||||
charset: CharsetState = .{},
|
charset: CharsetState = .{},
|
||||||
|
|
||||||
|
/// The color palette to use
|
||||||
|
color_palette: color.Palette = color.default,
|
||||||
|
|
||||||
/// 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).
|
||||||
previous_char: ?u21 = null,
|
previous_char: ?u21 = null,
|
||||||
@ -429,12 +432,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 = color.default[@enumToInt(n)];
|
self.screen.cursor.pen.fg = self.color_palette[@enumToInt(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 = color.default[@enumToInt(n)];
|
self.screen.cursor.pen.bg = self.color_palette[@enumToInt(n)];
|
||||||
},
|
},
|
||||||
|
|
||||||
.reset_fg => self.screen.cursor.pen.attrs.has_fg = false,
|
.reset_fg => self.screen.cursor.pen.attrs.has_fg = false,
|
||||||
@ -443,22 +446,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 = color.default[@enumToInt(n)];
|
self.screen.cursor.pen.fg = self.color_palette[@enumToInt(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 = color.default[@enumToInt(n)];
|
self.screen.cursor.pen.bg = self.color_palette[@enumToInt(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 = color.default[idx];
|
self.screen.cursor.pen.fg = self.color_palette[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 = color.default[idx];
|
self.screen.cursor.pen.bg = self.color_palette[idx];
|
||||||
},
|
},
|
||||||
|
|
||||||
.unknown => return error.InvalidAttribute,
|
.unknown => return error.InvalidAttribute,
|
||||||
|
@ -107,8 +107,13 @@ pub fn init(alloc: Allocator, opts: termio.Options) !Exec {
|
|||||||
log.info("started subcommand path={s} pid={?}", .{ path, cmd.pid });
|
log.info("started subcommand path={s} pid={?}", .{ path, cmd.pid });
|
||||||
|
|
||||||
// Create our terminal
|
// Create our terminal
|
||||||
var term = try terminal.Terminal.init(alloc, opts.grid_size.columns, opts.grid_size.rows);
|
var term = try terminal.Terminal.init(
|
||||||
|
alloc,
|
||||||
|
opts.grid_size.columns,
|
||||||
|
opts.grid_size.rows,
|
||||||
|
);
|
||||||
errdefer term.deinit(alloc);
|
errdefer term.deinit(alloc);
|
||||||
|
term.color_palette = opts.config.palette.value;
|
||||||
|
|
||||||
return Exec{
|
return Exec{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
|
Reference in New Issue
Block a user