From 70a33f1ebfd9205b4ed70961a568aecd7aac25ca Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 12 Feb 2025 10:48:02 +0100 Subject: [PATCH 01/10] feat: add astro file type support closes #175 --- src/syntax/build.zig | 2 ++ src/syntax/build.zig.zon | 4 ++-- src/syntax/src/file_types.zig | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/syntax/build.zig b/src/syntax/build.zig index c24840e..c74f15f 100644 --- a/src/syntax/build.zig +++ b/src/syntax/build.zig @@ -19,6 +19,7 @@ pub fn build(b: *std.Build) void { .{ .name = "treez", .module = tree_sitter_dep.module("treez") }, ts_queryfile(b, tree_sitter_dep, "queries/cmake/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-agda/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-astro/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-bash/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-c-sharp/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-c/queries/highlights.scm"), @@ -80,6 +81,7 @@ pub fn build(b: *std.Build) void { ts_queryfile(b, tree_sitter_dep, "nvim-treesitter/queries/verilog/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "queries/cmake/injections.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-astro/queries/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-cpp/queries/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-elixir/queries/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-gitcommit/queries/injections.scm"), diff --git a/src/syntax/build.zig.zon b/src/syntax/build.zig.zon index 46e29c4..0f161c8 100644 --- a/src/syntax/build.zig.zon +++ b/src/syntax/build.zig.zon @@ -4,8 +4,8 @@ .dependencies = .{ .@"tree-sitter" = .{ - .url = "https://github.com/neurocyte/tree-sitter/releases/download/master-69775ce3ba8a5e331bba9feb760d1ba31394eea7/source.tar.gz", - .hash = "1220f9702ca6257f5464b31e576b1e92b0f441bf0e61733c4a2fbf95b7c0c55a3e22", + .url = "https://github.com/neurocyte/tree-sitter/releases/download/master-86dd4d2536f2748c5b4ea0e1e70678039a569aac/source.tar.gz", + .hash = "1220e9fba96c468283129e977767472dee00b16f356e5912431cec8f1a009b6691a2", }, }, .paths = .{ diff --git a/src/syntax/src/file_types.zig b/src/syntax/src/file_types.zig index a634930..f5ad703 100644 --- a/src/syntax/src/file_types.zig +++ b/src/syntax/src/file_types.zig @@ -4,6 +4,14 @@ pub const agda = .{ .comment = "--", }; +pub const astro = .{ + .description = "Astro", + .icon = "", + .extensions = .{"astro"}, + .comment = "//", + .language_server = .{ "astro-ls", "--stdio" }, +}; + pub const bash = .{ .description = "Bash", .color = 0x3e474a, From 9f2e3bf4b48767a7c42bc77e609845a7b285b23c Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 12 Feb 2025 18:09:14 +0100 Subject: [PATCH 02/10] fix: load case data early on startup instead of on demand This is to avoid an issue with the decompressor causing heap corruption on macos. closes #169 --- build.zig | 4 +++- src/buffer/unicode.zig | 10 ++++++++++ src/main.zig | 2 ++ src/tui/editor.zig | 18 ++++-------------- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/build.zig b/build.zig index e6af465..99e798e 100644 --- a/build.zig +++ b/build.zig @@ -293,6 +293,7 @@ pub fn build_exe( .imports = &.{ .{ .name = "cbor", .module = cbor_mod }, .{ .name = "thespian", .module = thespian_mod }, + .{ .name = "CaseData", .module = zg_dep.module("CaseData") }, }, }); @@ -476,7 +477,6 @@ pub fn build_exe( .{ .name = "color", .module = color_mod }, .{ .name = "diff", .module = diff_mod }, .{ .name = "help.md", .module = help_mod }, - .{ .name = "CaseData", .module = zg_dep.module("CaseData") }, .{ .name = "fuzzig", .module = fuzzig_dep.module("fuzzig") }, .{ .name = "zeit", .module = zeit_mod }, }, @@ -502,6 +502,7 @@ pub fn build_exe( exe.root_module.addImport("flags", flags_dep.module("flags")); exe.root_module.addImport("cbor", cbor_mod); exe.root_module.addImport("config", config_mod); + exe.root_module.addImport("Buffer", Buffer_mod); exe.root_module.addImport("tui", tui_mod); exe.root_module.addImport("thespian", thespian_mod); exe.root_module.addImport("log", log_mod); @@ -543,6 +544,7 @@ pub fn build_exe( check_exe.root_module.addImport("flags", flags_dep.module("flags")); check_exe.root_module.addImport("cbor", cbor_mod); check_exe.root_module.addImport("config", config_mod); + check_exe.root_module.addImport("Buffer", Buffer_mod); check_exe.root_module.addImport("tui", tui_mod); check_exe.root_module.addImport("thespian", thespian_mod); check_exe.root_module.addImport("log", log_mod); diff --git a/src/buffer/unicode.zig b/src/buffer/unicode.zig index 8d0bb63..60bf389 100644 --- a/src/buffer/unicode.zig +++ b/src/buffer/unicode.zig @@ -59,3 +59,13 @@ pub fn utf8_sanitize(allocator: std.mem.Allocator, input: []const u8) error{ for (input) |byte| try writer.writeAll(try raw_byte_to_utf8(byte, &buf)); return output.toOwnedSlice(allocator); } + +pub const CaseData = @import("CaseData"); +var case_data: ?CaseData = null; +var case_data_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + +pub fn get_case_data() *CaseData { + if (case_data) |*cd| return cd; + case_data = CaseData.init(case_data_arena.allocator()) catch @panic("CaseData.init"); + return &case_data.?; +} diff --git a/src/main.zig b/src/main.zig index acf34d4..e7adc38 100644 --- a/src/main.zig +++ b/src/main.zig @@ -41,6 +41,8 @@ pub fn main() anyerror!void { } const a = std.heap.c_allocator; + const case_data = @import("Buffer").unicode.get_case_data(); + _ = case_data; // no need to free case_data as it is globally static const Flags = struct { pub const description = diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 3d4780e..59fa97c 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -9,7 +9,6 @@ const tracy = @import("tracy"); const text_manip = @import("text_manip"); const syntax = @import("syntax"); const project_manager = @import("project_manager"); -const CaseData = @import("CaseData"); const root_mod = @import("root"); const Plane = @import("renderer").Plane; @@ -350,8 +349,6 @@ pub const Editor = struct { } = null, } = null, - case_data: ?CaseData = null, - const WhitespaceMode = enum { indent, leading, eol, tabs, visible, full, none }; const StyleCache = std.AutoHashMap(u32, ?Widget.Theme.Token); @@ -468,7 +465,6 @@ pub const Editor = struct { self.handlers.deinit(); self.logger.deinit(); if (self.buffer) |p| self.buffer_manager.retire(p, meta.items); - if (self.case_data) |cd| cd.deinit(); } fn from_whitespace_mode(whitespace_mode: []const u8) WhitespaceMode { @@ -492,12 +488,6 @@ pub const Editor = struct { Widget.need_render(); } - fn get_case_data(self: *Self) *CaseData { - if (self.case_data) |*cd| return cd; - self.case_data = CaseData.init(self.allocator) catch @panic("CaseData.init"); - return &self.case_data.?; - } - fn buf_for_update(self: *Self) !*const Buffer { if (!self.pause_undo) { self.cursels_saved.clearAndFree(); @@ -4966,7 +4956,7 @@ pub const Editor = struct { var sfa = std.heap.stackFallback(4096, self.allocator); const cut_text = copy_selection(root, sel.*, sfa.get(), self.metrics) catch return error.Stop; defer allocator.free(cut_text); - const ucased = self.get_case_data().toUpperStr(allocator, cut_text) catch return error.Stop; + const ucased = Buffer.unicode.get_case_data().toUpperStr(allocator, cut_text) catch return error.Stop; defer allocator.free(ucased); root = try self.delete_selection(root, cursel, allocator); root = self.insert(root, cursel, ucased, allocator) catch return error.Stop; @@ -4994,7 +4984,7 @@ pub const Editor = struct { var sfa = std.heap.stackFallback(4096, self.allocator); const cut_text = copy_selection(root, sel.*, sfa.get(), self.metrics) catch return error.Stop; defer allocator.free(cut_text); - const ucased = self.get_case_data().toLowerStr(allocator, cut_text) catch return error.Stop; + const ucased = Buffer.unicode.get_case_data().toLowerStr(allocator, cut_text) catch return error.Stop; defer allocator.free(ucased); root = try self.delete_selection(root, cursel, allocator); root = self.insert(root, cursel, ucased, allocator) catch return error.Stop; @@ -5025,9 +5015,9 @@ pub const Editor = struct { self_: *Self, result: *std.ArrayList(u8), - const Error = @typeInfo(@typeInfo(@TypeOf(CaseData.toUpperStr)).Fn.return_type.?).ErrorUnion.error_set; + const Error = @typeInfo(@typeInfo(@TypeOf(Buffer.unicode.CaseData.toUpperStr)).Fn.return_type.?).ErrorUnion.error_set; pub fn write(writer: *@This(), bytes: []const u8) Error!void { - const cd = writer.self_.get_case_data(); + const cd = Buffer.unicode.get_case_data(); const flipped = if (cd.isLowerStr(bytes)) try cd.toUpperStr(writer.self_.allocator, bytes) else From fb5cd46d0b1fd277d6de3ded0a9d1d99bd73d643 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 12 Feb 2025 18:17:43 +0100 Subject: [PATCH 03/10] fix: check target missing color module --- build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/build.zig b/build.zig index 99e798e..b135612 100644 --- a/build.zig +++ b/build.zig @@ -552,6 +552,7 @@ pub fn build_exe( check_exe.root_module.addImport("renderer", renderer_mod); check_exe.root_module.addImport("input", input_mod); check_exe.root_module.addImport("syntax", syntax_mod); + check_exe.root_module.addImport("color", color_mod); check_exe.root_module.addImport("version_info", b.createModule(.{ .root_source_file = version_info_file })); check_step.dependOn(&check_exe.step); From b009d1a23a97a821cca2778db137332b6cd8ba16 Mon Sep 17 00:00:00 2001 From: triangularLuna Date: Wed, 12 Feb 2025 18:13:07 +0100 Subject: [PATCH 04/10] fix: remove 'jk' keybinding in insert mode --- src/keybind/builtin/vim.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/keybind/builtin/vim.json b/src/keybind/builtin/vim.json index 3291471..26b1a7a 100644 --- a/src/keybind/builtin/vim.json +++ b/src/keybind/builtin/vim.json @@ -102,7 +102,6 @@ "line_numbers": "absolute", "cursor": "beam", "press": [ - ["jk", "enter_mode", "normal"], ["", "enter_mode", "normal"], ["", "delete_forward"], ["", "delete_backward"], From 641d92a5cc45d139a5adc4aff109dfb12d53306f Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 13 Feb 2025 11:51:10 +0100 Subject: [PATCH 05/10] feat: allow calling create_scratch_buffer with no parameters --- src/tui/editor.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 59fa97c..fd31e39 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -4072,7 +4072,10 @@ pub const Editor = struct { } else if (ctx.args.match(.{tp.extract(&file_path)}) catch false) { try self.open_scratch(file_path, "", null); self.clamp(); - } else return error.InvalidOpenScratchBufferArgument; + } else { + try self.open_scratch("*scratch*", "", null); + self.clamp(); + } } pub const open_scratch_buffer_meta = .{ .arguments = &.{ .string, .string } }; From da694d7ac26e4fd054db9c86ccebf67a3cd1acd7 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 13 Feb 2025 12:01:24 +0100 Subject: [PATCH 06/10] fix: don't get stuck in an overlay mode if it is triggered from the command line --- src/tui/tui.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tui/tui.zig b/src/tui/tui.zig index 888015f..8782fc1 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -868,7 +868,7 @@ const cmds = struct { pub fn exit_overlay_mode(self: *Self, _: Ctx) Result { self.rdr.cursor_disable(); - if (self.input_mode_outer == null) return; + if (self.input_mode_outer == null) return enter_mode_default(self, .{}); if (self.input_mode) |*mode| mode.deinit(); self.input_mode = self.input_mode_outer; self.input_mode_outer = null; From 1cdfa834b92258aac3d0dd7b5bbae930aa70a76c Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 13 Feb 2025 12:02:59 +0100 Subject: [PATCH 07/10] refactor: run zig fmt --- src/gui_config.zig | 2 +- src/syntax/src/file_types.zig | 4 ++-- src/tui/tui.zig | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui_config.zig b/src/gui_config.zig index a48404e..4720515 100644 --- a/src/gui_config.zig +++ b/src/gui_config.zig @@ -1,4 +1,4 @@ -fontface: [] const u8 = "Cascadia Code", +fontface: []const u8 = "Cascadia Code", fontsize: u8 = 14, initial_window_x: u16 = 1087, diff --git a/src/syntax/src/file_types.zig b/src/syntax/src/file_types.zig index f5ad703..2b397ec 100644 --- a/src/syntax/src/file_types.zig +++ b/src/syntax/src/file_types.zig @@ -445,7 +445,7 @@ pub const scheme = .{ pub const sql = .{ .description = "SQL", .icon = "󰆼", - .extensions = .{ "sql" }, + .extensions = .{"sql"}, .comment = "--", }; @@ -472,7 +472,7 @@ pub const verilog = .{ .highlights = "nvim-treesitter/queries/verilog/highlights.scm", .injections = "nvim-treesitter/queries/verilog/injections.scm", .language_server = .{"verible-verilog-ls"}, - .formatter = .{ "verible-verilog-format", "-" } + .formatter = .{ "verible-verilog-format", "-" }, }; pub const toml = .{ diff --git a/src/tui/tui.zig b/src/tui/tui.zig index 8782fc1..8c67778 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -1290,7 +1290,8 @@ pub fn message(comptime fmt: anytype, args: anytype) void { tp.self_pid().send(.{ "message", std.fmt.bufPrint(&buf, fmt, args) catch @panic("too large") }) catch {}; } -pub fn render_file_icon(self: *renderer.Plane, icon: []const u8, color: u24) void { var cell = self.cell_init(); +pub fn render_file_icon(self: *renderer.Plane, icon: []const u8, color: u24) void { + var cell = self.cell_init(); _ = self.at_cursor_cell(&cell) catch return; if (!(color == 0xFFFFFF or color == 0x000000 or color == 0x000001)) { cell.set_fg_rgb(@intCast(color)) catch {}; @@ -1307,4 +1308,3 @@ pub fn render_match_cell(self: *renderer.Plane, y: usize, x: usize, theme_: *con cell.set_style(theme_.editor_match); _ = self.putc(&cell) catch {}; } - From 47c7b37968d0627c365fe0920d386bc5aa9e9c1e Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 13 Feb 2025 12:03:27 +0100 Subject: [PATCH 08/10] feat: don't ask for file type in create_new_file if we have a language override --- src/tui/mainview.zig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index 66fd364..7928ad8 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -465,7 +465,8 @@ const cmds = struct { } } try command.executeName("create_scratch_buffer", command.fmt(.{name.items})); - try command.executeName("change_file_type", .{}); + if (tp.env.get().str("language").len == 0) + try command.executeName("change_file_type", .{}); } pub const create_new_file_meta = .{ .description = "Create: New File…" }; From 9bedb9eccd17fff1c8bdb6a03ee59028b81edd39 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 13 Feb 2025 12:04:02 +0100 Subject: [PATCH 09/10] feat: add --scratch command line parameter --- src/main.zig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main.zig b/src/main.zig index e7adc38..4edf23f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -72,6 +72,7 @@ pub fn main() anyerror!void { .syntax_report_timing = "Report syntax highlighting time", .exec = "Execute a command on startup", .literal = "Disable :LINE and +LINE syntax", + .scratch = "Open a scratch (temporary) buffer on start", .version = "Show build version and exit", }; @@ -85,6 +86,7 @@ pub fn main() anyerror!void { .language = 'l', .exec = 'e', .literal = 'L', + .scratch = 'S', .version = 'v', }; @@ -106,6 +108,7 @@ pub fn main() anyerror!void { syntax_report_timing: bool, exec: ?[]const u8, literal: bool, + scratch: bool, version: bool, }; @@ -316,6 +319,10 @@ pub fn main() anyerror!void { try tui_proc.send(.{ "cmd", "show_home" }); } + if (args.scratch) { + try tui_proc.send(.{ "cmd", "create_scratch_buffer", .{} }); + } + if (args.exec) |exec_str| { var cmds = std.mem.splitScalar(u8, exec_str, ';'); while (cmds.next()) |cmd| try tui_proc.send(.{ "cmd", cmd, .{} }); From c537adbcddc58cba623c08f722f08aa7e3ea84f1 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 13 Feb 2025 12:06:59 +0100 Subject: [PATCH 10/10] feat: add --new-file command line parameter --- src/main.zig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main.zig b/src/main.zig index 4edf23f..ef2d734 100644 --- a/src/main.zig +++ b/src/main.zig @@ -73,6 +73,7 @@ pub fn main() anyerror!void { .exec = "Execute a command on startup", .literal = "Disable :LINE and +LINE syntax", .scratch = "Open a scratch (temporary) buffer on start", + .new_file = "Create a new untitled file on start", .version = "Show build version and exit", }; @@ -87,6 +88,7 @@ pub fn main() anyerror!void { .exec = 'e', .literal = 'L', .scratch = 'S', + .new_file = 'n', .version = 'v', }; @@ -109,6 +111,7 @@ pub fn main() anyerror!void { exec: ?[]const u8, literal: bool, scratch: bool, + new_file: bool, version: bool, }; @@ -319,7 +322,9 @@ pub fn main() anyerror!void { try tui_proc.send(.{ "cmd", "show_home" }); } - if (args.scratch) { + if (args.new_file) { + try tui_proc.send(.{ "cmd", "create_new_file", .{} }); + } else if (args.scratch) { try tui_proc.send(.{ "cmd", "create_scratch_buffer", .{} }); }