From 2ee1f3191e8f6e5c45d9f19fa09bb04c639fd4e1 Mon Sep 17 00:00:00 2001 From: Denys Zhak Date: Mon, 10 Nov 2025 16:53:27 +0100 Subject: [PATCH] feat: add descriptions to fish shell completions --- build.zig | 2 +- src/build/GhosttyResources.zig | 5 +++- src/extra/fish.zig | 49 ++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/build.zig b/build.zig index 68dc0028b..5fd611b6c 100644 --- a/build.zig +++ b/build.zig @@ -55,7 +55,7 @@ pub fn build(b: *std.Build) !void { ); // Ghostty resources like terminfo, shell integration, themes, etc. - const resources = try buildpkg.GhosttyResources.init(b, &config); + const resources = try buildpkg.GhosttyResources.init(b, &config, &deps); const i18n = if (config.i18n) try buildpkg.GhosttyI18n.init(b, &config) else null; // Ghostty executable, the actual runnable Ghostty program. diff --git a/src/build/GhosttyResources.zig b/src/build/GhosttyResources.zig index 1ac8fe2a9..a1bbe2857 100644 --- a/src/build/GhosttyResources.zig +++ b/src/build/GhosttyResources.zig @@ -6,10 +6,11 @@ const assert = std.debug.assert; const buildpkg = @import("main.zig"); const Config = @import("Config.zig"); const RunStep = std.Build.Step.Run; +const SharedDeps = @import("SharedDeps.zig"); steps: []*std.Build.Step, -pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { +pub fn init(b: *std.Build, cfg: *const Config, deps: *const SharedDeps) !GhosttyResources { var steps: std.ArrayList(*std.Build.Step) = .empty; errdefer steps.deinit(b.allocator); @@ -26,6 +27,8 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { }); build_data_exe.linkLibC(); + deps.help_strings.addImport(build_data_exe); + // Terminfo terminfo: { const os_tag = cfg.target.result.os.tag; diff --git a/src/extra/fish.zig b/src/extra/fish.zig index 7ffc23093..2f00bca59 100644 --- a/src/extra/fish.zig +++ b/src/extra/fish.zig @@ -3,6 +3,7 @@ const std = @import("std"); const Config = @import("../config/Config.zig"); const Action = @import("../cli.zig").ghostty.Action; +const help_strings = @import("help_strings"); /// A fish completions configuration that contains all the available commands /// and options. @@ -81,6 +82,15 @@ fn writeCompletions(writer: *std.Io.Writer) !void { else => {}, } } + + if (@hasDecl(help_strings.Config, field.name)) { + const help = @field(help_strings.Config, field.name); + const desc = getDescription(help); + try writer.writeAll(" -d \""); + try writer.writeAll(desc); + try writer.writeAll("\""); + } + try writer.writeAll("\n"); } @@ -143,3 +153,42 @@ fn writeCompletions(writer: *std.Io.Writer) !void { } } } + +fn getDescription(comptime help: []const u8) []const u8 { + var out: [help.len * 2]u8 = undefined; + var len: usize = 0; + var prev_was_space = false; + + for (help, 0..) |c, i| { + switch (c) { + '.' => { + out[len] = '.'; + len += 1; + + if (i + 1 >= help.len) break; + const next = help[i + 1]; + if (next == ' ' or next == '\n') break; + }, + '\n' => { + if (!prev_was_space and len > 0) { + out[len] = ' '; + len += 1; + prev_was_space = true; + } + }, + '"' => { + out[len] = '\\'; + out[len + 1] = '"'; + len += 2; + prev_was_space = false; + }, + else => { + out[len] = c; + len += 1; + prev_was_space = (c == ' '); + }, + } + } + + return out[0..len]; +}