From de428d9fe9a080ae140879c8700caaaf7ede8bbb Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Thu, 11 Jan 2024 14:25:12 -0600 Subject: [PATCH 1/6] add +show-config action to print out the config from the cli --- src/cli/action.zig | 5 +++++ src/cli/show_config.zig | 46 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/cli/show_config.zig diff --git a/src/cli/action.zig b/src/cli/action.zig index 2e3afb1c0..a7cbabf25 100644 --- a/src/cli/action.zig +++ b/src/cli/action.zig @@ -8,6 +8,7 @@ const version = @import("version.zig"); const list_keybinds = @import("list_keybinds.zig"); const list_themes = @import("list_themes.zig"); const list_colors = @import("list_colors.zig"); +const show_config = @import("show_config.zig"); /// Special commands that can be invoked via CLI flags. These are all /// invoked by using `+` as a CLI flag. The only exception is @@ -31,6 +32,9 @@ pub const Action = enum { /// List named RGB colors @"list-colors", + /// Dump the config to stdout + @"show-config", + pub const Error = error{ /// Multiple actions were detected. You can specify at most one /// action on the CLI otherwise the behavior desired is ambiguous. @@ -119,6 +123,7 @@ pub const Action = enum { .@"list-keybinds" => try list_keybinds.run(alloc), .@"list-themes" => try list_themes.run(alloc), .@"list-colors" => try list_colors.run(alloc), + .@"show-config" => try show_config.run(alloc), }; } diff --git a/src/cli/show_config.zig b/src/cli/show_config.zig new file mode 100644 index 000000000..94e0dfc4e --- /dev/null +++ b/src/cli/show_config.zig @@ -0,0 +1,46 @@ +const std = @import("std"); +const args = @import("args.zig"); +const Allocator = std.mem.Allocator; +const Config = @import("../config/Config.zig"); + +pub const Options = struct { + /// If true, print out the default config instead of the user's config. + default: bool = false, + + pub fn deinit(self: Options) void { + _ = self; + } +}; + +/// The "show-config" command is used to list all the available configuration +/// settings for Ghostty. +/// +/// When executed without any arguments this will list the current settings +/// loaded by the config file(s). If no config file is found or there aren't +/// any changes to the settings it will print out the default ones configured +/// for Ghostty +/// +/// The "--default" argument will print out all the default settings +/// configured for Ghostty +pub fn run(alloc: Allocator) !u8 { + var opts: Options = .{}; + defer opts.deinit(); + + { + var iter = try std.process.argsWithAllocator(alloc); + defer iter.deinit(); + try args.parse(Options, alloc, &opts, &iter); + } + + var config = if (opts.default) try Config.default(alloc) else try Config.load(alloc); + defer config.deinit(); + + const stdout = std.io.getStdOut().writer(); + + const info = @typeInfo(Config); + std.debug.assert(info == .Struct); + + try config.formatConfig(stdout); + + return 0; +} From 73a30ccd82480d4ba6456bbaf852776a2db91c67 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Jan 2024 19:37:48 -0800 Subject: [PATCH 2/6] cli/show-config: add the changes-only and docs options --- src/cli/show_config.zig | 63 ++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/src/cli/show_config.zig b/src/cli/show_config.zig index 94e0dfc4e..fffd276d5 100644 --- a/src/cli/show_config.zig +++ b/src/cli/show_config.zig @@ -1,27 +1,54 @@ const std = @import("std"); const args = @import("args.zig"); const Allocator = std.mem.Allocator; -const Config = @import("../config/Config.zig"); +const configpkg = @import("../config.zig"); +const Config = configpkg.Config; pub const Options = struct { - /// If true, print out the default config instead of the user's config. + /// If true, do not load the user configuration, only load the defaults. default: bool = false, + /// Only show the options that have been changed from the default. + /// This has no effect if `--default` is specified. + @"changes-only": bool = true, + + /// If true print the documentation above each option as a comment, + /// if available. + docs: bool = false, + pub fn deinit(self: Options) void { _ = self; } }; -/// The "show-config" command is used to list all the available configuration -/// settings for Ghostty. +/// The "show-config" command shows the current configuration in a valid +/// Ghostty configuration file format. /// -/// When executed without any arguments this will list the current settings -/// loaded by the config file(s). If no config file is found or there aren't -/// any changes to the settings it will print out the default ones configured -/// for Ghostty +/// When executed without any arguments this will output the current +/// configuration that is different from the default configuration. If you're +/// using the default configuration this will output nothing. +/// +/// If you are a new user and want to see all available options with +/// documentation, run `ghostty +show-config --default --docs`. +/// +/// The output is not in any specific order, but the order should be +/// consistent between runs. The output is not guaranteed to be exactly +/// match the input configuration files, but it will result in the same +/// behavior. Comments, whitespace, and other formatting is not preserved +/// from user configuration files. +/// +/// Flags: +/// +/// - "--default": Show the default configuration instead of loading +/// the user configuration. +/// +/// - "--changes-only": Only show the options that have been changed +/// from the default. This has no effect if "--default" is specified. +/// +/// - "--docs": Print the documentation above each option as a comment, +/// This is very noisy but is very useful to learn about available +/// options, especially paired with "--default". /// -/// The "--default" argument will print out all the default settings -/// configured for Ghostty pub fn run(alloc: Allocator) !u8 { var opts: Options = .{}; defer opts.deinit(); @@ -35,12 +62,16 @@ pub fn run(alloc: Allocator) !u8 { var config = if (opts.default) try Config.default(alloc) else try Config.load(alloc); defer config.deinit(); + const configfmt: configpkg.FileFormatter = .{ + .alloc = alloc, + .config = &config, + .changed = !opts.default and opts.@"changes-only", + .docs = opts.docs, + }; + + // For some reason `std.fmt.format` isn't working here but it works in + // tests so we just do configfmt.format. const stdout = std.io.getStdOut().writer(); - - const info = @typeInfo(Config); - std.debug.assert(info == .Struct); - - try config.formatConfig(stdout); - + try configfmt.format("", .{}, stdout); return 0; } From 863c3933d3b5c4fc3e38a7fe70ea3d61fe6c1907 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Thu, 11 Jan 2024 14:26:09 -0600 Subject: [PATCH 3/6] use keybind struct's built-in capabity to format itself in +list-keybinds action --- src/cli/list_keybinds.zig | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/cli/list_keybinds.zig b/src/cli/list_keybinds.zig index 15df1815e..2ded21adc 100644 --- a/src/cli/list_keybinds.zig +++ b/src/cli/list_keybinds.zig @@ -46,12 +46,7 @@ pub fn run(alloc: Allocator) !u8 { defer config.deinit(); const stdout = std.io.getStdOut().writer(); - var iter = config.keybind.set.bindings.iterator(); - while (iter.next()) |next| { - const keys = next.key_ptr.*; - const value = next.value_ptr.*; - try stdout.print("{}={}\n", .{ keys, value }); - } + try config.keybind.formatConfig(stdout, "keybind="); return 0; } From ddd17eda063f8928f116efbaea902eb287a046ef Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Jan 2024 19:39:47 -0800 Subject: [PATCH 4/6] cli: list-keybinds uses new config formatting API --- src/cli/list_keybinds.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cli/list_keybinds.zig b/src/cli/list_keybinds.zig index 2ded21adc..ed831837e 100644 --- a/src/cli/list_keybinds.zig +++ b/src/cli/list_keybinds.zig @@ -4,7 +4,8 @@ const args = @import("args.zig"); const Action = @import("action.zig").Action; const Arena = std.heap.ArenaAllocator; const Allocator = std.mem.Allocator; -const Config = @import("../config/Config.zig"); +const configpkg = @import("../config.zig"); +const Config = configpkg.Config; pub const Options = struct { /// If true, print out the default keybinds instead of the ones @@ -46,7 +47,7 @@ pub fn run(alloc: Allocator) !u8 { defer config.deinit(); const stdout = std.io.getStdOut().writer(); - try config.keybind.formatConfig(stdout, "keybind="); + try config.keybind.formatEntry(configpkg.entryFormatter("keybind", stdout)); return 0; } From 27453b64e676ee609d65fd9c4f4f43102c5f4166 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Jan 2024 19:44:54 -0800 Subject: [PATCH 5/6] cli/show-config: enable --help --- src/cli/show_config.zig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/cli/show_config.zig b/src/cli/show_config.zig index fffd276d5..c62dfe9f5 100644 --- a/src/cli/show_config.zig +++ b/src/cli/show_config.zig @@ -1,6 +1,7 @@ const std = @import("std"); const args = @import("args.zig"); const Allocator = std.mem.Allocator; +const Action = @import("action.zig").Action; const configpkg = @import("../config.zig"); const Config = configpkg.Config; @@ -19,6 +20,12 @@ pub const Options = struct { pub fn deinit(self: Options) void { _ = self; } + + /// Enables "-h" and "--help" to work. + pub fn help(self: Options) !void { + _ = self; + return Action.help_error; + } }; /// The "show-config" command shows the current configuration in a valid From 558fd316c4f34914b7141c8b97c44290a5b3ab31 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 20 Jan 2024 20:02:13 -0800 Subject: [PATCH 6/6] update README for show-config --- README.md | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3fcabc71c..be96b1a33 100644 --- a/README.md +++ b/README.md @@ -100,8 +100,20 @@ palette = 7=#a89984 palette = 15=#fbf1c7 ``` -While the set of config keys and values are not yet documented, they are -discoverable in the [Config structure](https://github.com/mitchellh/ghostty/blob/main/src/config/Config.zig). +You can view all available configuration options and their documentation +by executing the command `ghostty +show-config --default --docs`. Note that +this will output the full default configuration with docs to stdout, so +you may want to pipe that through a pager, an editor, etc. + +> [!NOTE] +> +> You'll see a lot of weird blank configurations like `font-family =`. This +> is a valid syntax to specify the default behavior (no value). The +> `+show-config` outputs it so its clear that key is defaulting and also +> to have something to attach the doc comment to. + +You can also see and read all available configuration options in the source +[Config structure](https://github.com/mitchellh/ghostty/blob/main/src/config/Config.zig). The available keys are the keys verbatim, and their possible values are typically documented in the comments. You also can search for the [public config files](https://github.com/search?q=path%3Aghostty%2Fconfig&type=code) @@ -124,11 +136,13 @@ is in the "building Ghostty" section at the end of the README. In the debug output, you should see in the first 20 lines or so messages about loading (or not loading) a configuration file, as well as any errors -it may have encountered. Ghostty currently ignores errors and treats it -as if the configuration had not been set, so this is the best place to look -if something isn't working. +it may have encountered. Configuration errors are also shown in a dedicated +window on both macOS and Linux (GTK). Ghostty does not treat configuration +errors as fatal and will fall back to default values for erroneous keys. -Eventually, we'll have a better mechanism for showing errors to the user. +You can also view the full configuration Ghostty is loading using +`ghostty +show-config` from the command-line. Use the `--help` flag to +additional options for that command. ### Themes