diff --git a/src/build/GhosttyResources.zig b/src/build/GhosttyResources.zig index 266069f83..0db1fd418 100644 --- a/src/build/GhosttyResources.zig +++ b/src/build/GhosttyResources.zig @@ -5,9 +5,6 @@ const builtin = @import("builtin"); const assert = std.debug.assert; const buildpkg = @import("main.zig"); const Config = @import("Config.zig"); -const config_vim = @import("../config/vim.zig"); -const config_sublime_syntax = @import("../config/sublime_syntax.zig"); -const terminfo = @import("../terminfo/main.zig"); const RunStep = std.Build.Step.Run; steps: []*std.Build.Step, @@ -16,6 +13,19 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { var steps = std.ArrayList(*std.Build.Step).init(b.allocator); errdefer steps.deinit(); + // This is the exe used to generate some build data. + const build_data_exe = b.addExecutable(.{ + .name = "ghostty-build-data", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main_build_data.zig"), + .target = b.graph.host, + .strip = false, + .omit_frame_pointer = false, + .unwind_tables = .sync, + }), + }); + build_data_exe.linkLibC(); + // Terminfo terminfo: { const os_tag = cfg.target.result.os.tag; @@ -25,13 +35,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { "terminfo"; // Encode our terminfo - var str = std.ArrayList(u8).init(b.allocator); - defer str.deinit(); - try terminfo.ghostty.encode(str.writer()); - - // Write it - var wf = b.addWriteFiles(); - const source = wf.add("ghostty.terminfo", str.items); + const run = b.addRunArtifact(build_data_exe); + run.addArg("+terminfo"); + const wf = b.addWriteFiles(); + const source = wf.addCopyFile(run.captureStdOut(), "ghostty.terminfo"); if (cfg.emit_terminfo) { const source_install = b.addInstallFile( @@ -130,8 +137,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { // Fish shell completions { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+fish"); const wf = b.addWriteFiles(); - _ = wf.add("ghostty.fish", buildpkg.fish_completions); + _ = wf.addCopyFile(run.captureStdOut(), "ghostty.fish"); const install_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), @@ -143,8 +152,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { // zsh shell completions { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+zsh"); const wf = b.addWriteFiles(); - _ = wf.add("_ghostty", buildpkg.zsh_completions); + _ = wf.addCopyFile(run.captureStdOut(), "_ghostty"); const install_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), @@ -156,8 +167,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { // bash shell completions { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+bash"); const wf = b.addWriteFiles(); - _ = wf.add("ghostty.bash", buildpkg.bash_completions); + _ = wf.addCopyFile(run.captureStdOut(), "ghostty.bash"); const install_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), @@ -167,39 +180,44 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { try steps.append(&install_step.step); } - // Vim plugin + // Vim and Neovim plugin { const wf = b.addWriteFiles(); - _ = wf.add("syntax/ghostty.vim", config_vim.syntax); - _ = wf.add("ftdetect/ghostty.vim", config_vim.ftdetect); - _ = wf.add("ftplugin/ghostty.vim", config_vim.ftplugin); - _ = wf.add("compiler/ghostty.vim", config_vim.compiler); - const install_step = b.addInstallDirectory(.{ + { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+vim-syntax"); + _ = wf.addCopyFile(run.captureStdOut(), "syntax/ghostty.vim"); + } + { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+vim-ftdetect"); + _ = wf.addCopyFile(run.captureStdOut(), "ftdetect/ghostty.vim"); + } + { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+vim-ftplugin"); + _ = wf.addCopyFile(run.captureStdOut(), "ftplugin/ghostty.vim"); + } + { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+vim-compiler"); + _ = wf.addCopyFile(run.captureStdOut(), "compiler/ghostty.vim"); + } + + const vim_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), .install_dir = .prefix, .install_subdir = "share/vim/vimfiles", }); - try steps.append(&install_step.step); - } + try steps.append(&vim_step.step); - // Neovim plugin - // This is just a copy-paste of the Vim plugin, but using a Neovim subdir. - // By default, Neovim doesn't look inside share/vim/vimfiles. Some distros - // configure it to do that however. Fedora, does not as a counterexample. - { - const wf = b.addWriteFiles(); - _ = wf.add("syntax/ghostty.vim", config_vim.syntax); - _ = wf.add("ftdetect/ghostty.vim", config_vim.ftdetect); - _ = wf.add("ftplugin/ghostty.vim", config_vim.ftplugin); - _ = wf.add("compiler/ghostty.vim", config_vim.compiler); - - const install_step = b.addInstallDirectory(.{ + const neovim_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), .install_dir = .prefix, .install_subdir = "share/nvim/site", }); - try steps.append(&install_step.step); + try steps.append(&neovim_step.step); } // Sublime syntax highlighting for bat cli tool @@ -209,8 +227,10 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyResources { // the config file within the '~.config/bat' directory // (ex: --map-syntax "/Users/user/.config/ghostty/config:Ghostty Config"). { + const run = b.addRunArtifact(build_data_exe); + run.addArg("+sublime"); const wf = b.addWriteFiles(); - _ = wf.add("ghostty.sublime-syntax", config_sublime_syntax.syntax); + _ = wf.addCopyFile(run.captureStdOut(), "ghostty.sublime-syntax"); const install_step = b.addInstallDirectory(.{ .source_dir = wf.getDirectory(), diff --git a/src/build/main.zig b/src/build/main.zig index f25ce1c23..af99802df 100644 --- a/src/build/main.zig +++ b/src/build/main.zig @@ -28,10 +28,5 @@ pub const LipoStep = @import("LipoStep.zig"); pub const MetallibStep = @import("MetallibStep.zig"); pub const XCFrameworkStep = @import("XCFrameworkStep.zig"); -// Shell completions -pub const fish_completions = @import("fish_completions.zig").completions; -pub const zsh_completions = @import("zsh_completions.zig").completions; -pub const bash_completions = @import("bash_completions.zig").completions; - // Helpers pub const requireZig = @import("zig.zig").requireZig; diff --git a/src/config.zig b/src/config.zig index bcb48214d..e83dff530 100644 --- a/src/config.zig +++ b/src/config.zig @@ -48,7 +48,4 @@ pub const Wasm = if (!builtin.target.cpu.arch.isWasm()) struct {} else @import(" test { @import("std").testing.refAllDecls(@This()); - - // Vim syntax file, not used at runtime but we want to keep it tested. - _ = @import("config/vim.zig"); } diff --git a/src/build/bash_completions.zig b/src/extra/bash.zig similarity index 100% rename from src/build/bash_completions.zig rename to src/extra/bash.zig diff --git a/src/build/fish_completions.zig b/src/extra/fish.zig similarity index 95% rename from src/build/fish_completions.zig rename to src/extra/fish.zig index 0b6c45e1f..5a4b38e32 100644 --- a/src/build/fish_completions.zig +++ b/src/extra/fish.zig @@ -1,3 +1,4 @@ +//! Fish completions. const std = @import("std"); const Config = @import("../config/Config.zig"); @@ -5,23 +6,23 @@ const Action = @import("../cli.zig").ghostty.Action; /// A fish completions configuration that contains all the available commands /// and options. -pub const completions = comptimeGenerateFishCompletions(); +pub const completions = comptimeGenerateCompletions(); -fn comptimeGenerateFishCompletions() []const u8 { +fn comptimeGenerateCompletions() []const u8 { comptime { @setEvalBranchQuota(50000); var counter = std.io.countingWriter(std.io.null_writer); - try writeFishCompletions(&counter.writer()); + try writeCompletions(&counter.writer()); var buf: [counter.bytes_written]u8 = undefined; var stream = std.io.fixedBufferStream(&buf); - try writeFishCompletions(stream.writer()); + try writeCompletions(stream.writer()); const final = buf; return final[0..stream.getWritten().len]; } } -fn writeFishCompletions(writer: anytype) !void { +fn writeCompletions(writer: anytype) !void { { try writer.writeAll("set -l commands \""); var count: usize = 0; diff --git a/src/config/sublime_syntax.zig b/src/extra/sublime.zig similarity index 96% rename from src/config/sublime_syntax.zig rename to src/extra/sublime.zig index dff7d758e..4af589b4f 100644 --- a/src/config/sublime_syntax.zig +++ b/src/extra/sublime.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const Config = @import("Config.zig"); +const Config = @import("../config/Config.zig"); const Template = struct { const header = diff --git a/src/config/vim.zig b/src/extra/vim.zig similarity index 98% rename from src/config/vim.zig rename to src/extra/vim.zig index 17ab0bc2e..e5261cd74 100644 --- a/src/config/vim.zig +++ b/src/extra/vim.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const Config = @import("Config.zig"); +const Config = @import("../config/Config.zig"); /// This is the associated Vim file as named by the variable. pub const syntax = comptimeGenSyntax(); diff --git a/src/build/zsh_completions.zig b/src/extra/zsh.zig similarity index 100% rename from src/build/zsh_completions.zig rename to src/extra/zsh.zig diff --git a/src/main_build_data.zig b/src/main_build_data.zig new file mode 100644 index 000000000..13e604389 --- /dev/null +++ b/src/main_build_data.zig @@ -0,0 +1,48 @@ +//! This CLI is used to generate data that is used by the build process. +//! +//! We used to do this directly in our `build.zig` but the problem with +//! that approach is that any changes to the dependencies of this data would +//! force a rebuild of our build binary. If we're just doing something like +//! running tests and not emitting any of the info below, then that is a +//! complete waste. + +const std = @import("std"); +const Allocator = std.mem.Allocator; +const cli = @import("cli.zig"); + +pub const Action = enum { + // Shell completions + bash, + fish, + zsh, + + // Editor syntax files + sublime, + @"vim-syntax", + @"vim-ftdetect", + @"vim-ftplugin", + @"vim-compiler", + + // Other + terminfo, +}; + +pub fn main() !void { + const alloc = std.heap.c_allocator; + const action_ = try cli.action.detectArgs(Action, alloc); + const action = action_ orelse return error.NoAction; + + // Our output always goes to stdout. + const writer = std.io.getStdOut().writer(); + switch (action) { + .bash => try writer.writeAll(@import("extra/bash.zig").completions), + .fish => try writer.writeAll(@import("extra/fish.zig").completions), + .zsh => try writer.writeAll(@import("extra/zsh.zig").completions), + .sublime => try writer.writeAll(@import("extra/sublime.zig").syntax), + .@"vim-syntax" => try writer.writeAll(@import("extra/vim.zig").syntax), + .@"vim-ftdetect" => try writer.writeAll(@import("extra/vim.zig").ftdetect), + .@"vim-ftplugin" => try writer.writeAll(@import("extra/vim.zig").ftplugin), + .@"vim-compiler" => try writer.writeAll(@import("extra/vim.zig").compiler), + .terminfo => try @import("terminfo/ghostty.zig").ghostty.encode(writer), + } +} diff --git a/src/main_ghostty.zig b/src/main_ghostty.zig index fb29303f1..aca33a510 100644 --- a/src/main_ghostty.zig +++ b/src/main_ghostty.zig @@ -191,4 +191,11 @@ test { _ = @import("simd/main.zig"); _ = @import("synthetic/main.zig"); _ = @import("unicode/main.zig"); + + // Extra + _ = @import("extra/bash.zig"); + _ = @import("extra/fish.zig"); + _ = @import("extra/sublime.zig"); + _ = @import("extra/vim.zig"); + _ = @import("extra/zsh.zig"); }