diff --git a/build.zig b/build.zig index e94b729..4b0c6af 100644 --- a/build.zig +++ b/build.zig @@ -17,6 +17,7 @@ pub fn build(b: *std.Build) void { const imports: []const std.Build.Module.Import = if (use_tree_sitter) &.{ .{ .name = "build_options", .module = options_mod }, .{ .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-bash/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-c-sharp/queries/highlights.scm"), @@ -28,14 +29,17 @@ pub fn build(b: *std.Build) void { ts_queryfile(b, tree_sitter_dep, "tree-sitter-elixir/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-git-rebase/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-gitcommit/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-gleam/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-go/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-fish/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-haskell/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-hare/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-html/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-java/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-javascript/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-jsdoc/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-json/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-julia/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-kdl/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-lua/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-make/queries/highlights.scm"), @@ -59,6 +63,7 @@ pub fn build(b: *std.Build) void { ts_queryfile(b, tree_sitter_dep, "tree-sitter-scala/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-scheme/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-superhtml/tree-sitter-superhtml/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-swift/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-toml/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-typescript/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-typst/queries/typst/highlights.scm"), @@ -70,9 +75,11 @@ pub fn build(b: *std.Build) void { ts_queryfile(b, tree_sitter_dep, "tree-sitter-ziggy/tree-sitter-ziggy/queries/highlights.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-ziggy/tree-sitter-ziggy-schema/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "queries/cmake/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"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-hare/queries/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-html/queries/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-javascript/queries/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-kdl/queries/injections.scm"), @@ -88,6 +95,7 @@ pub fn build(b: *std.Build) void { ts_queryfile(b, tree_sitter_dep, "tree-sitter-purescript/vim_queries/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-rust/queries/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-superhtml/tree-sitter-superhtml/queries/injections.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-swift/queries/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-typst/queries/typst/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-vim/queries/vim/injections.scm"), ts_queryfile(b, tree_sitter_dep, "tree-sitter-zig/queries/injections.scm"), diff --git a/build.zig.zon b/build.zig.zon index 905ebd3..9d4cc6c 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -4,8 +4,8 @@ .dependencies = .{ .@"tree-sitter" = .{ - .url = "https://github.com/neurocyte/tree-sitter/releases/download/master-876cc5a125cb822d44a9f94f6bde64fac66272ce/source.tar.gz", - .hash = "12208efbfead8c57adeabbd2293d6ed19e00f769e1d8aba0d544270479587c9f694a", + .url = "https://github.com/neurocyte/tree-sitter/releases/download/master-c20cbdfcdb3b9650a873614b2c361a2a2aaeb068/source.tar.gz", + .hash = "122042464e2fd94116fe6f63e8939ddb59b5e55b53ed95945537753bee9b119a5089", }, }, .paths = .{ diff --git a/src/file_types.zig b/src/file_types.zig index 284c857..ada91c1 100644 --- a/src/file_types.zig +++ b/src/file_types.zig @@ -15,7 +15,7 @@ pub const bash = .{ pub const c = .{ .icon = "", - .extensions = .{ "c", "h" }, + .extensions = .{"c"}, .comment = "//", .formatter = .{"clang-format"}, .language_server = .{"clangd"}, @@ -38,6 +38,17 @@ pub const conf = .{ .parser = fish.parser, }; +pub const cmake = .{ + .color = 0x004078, + .icon = "", + .extensions = .{ "CMakeLists.txt", "cmake", "cmake.in" }, + .comment = "#", + .highlights = "queries/cmake/highlights.scm", + .injections = "queries/cmake/injections.scm", + .formatter = .{"cmake-format"}, + .language_server = .{"cmake-language-server"}, +}; + pub const cpp = .{ .color = 0x9c033a, .icon = "", @@ -110,12 +121,27 @@ pub const gitcommit = .{ .injections = "tree-sitter-gitcommit/queries/injections.scm", }; +pub const gleam = .{ + .color = 0xffaff3, + .icon = "󰦥", + .extensions = .{"gleam"}, + .comment = "//", + .language_server = .{ "gleam", "lsp" }, + .formatter = .{ "gleam", "format", "--stdin" }, +}; + pub const go = .{ .color = 0x00acd7, .icon = "󰟓", .extensions = .{"go"}, .comment = "//", .language_server = .{"gopls"}, + .formatter = .{"gofmt"}, +}; + +pub const hare = .{ + .extensions = .{"ha"}, + .comment = "//", }; pub const haskell = .{ @@ -170,6 +196,14 @@ pub const json = .{ .formatter = .{ "hjson", "-j" }, }; +pub const julia = .{ + .color = 0x4D64AE, + .icon = "", + .extensions = .{"jl"}, + .comment = "#", + .language_server = .{ "julia", "-e", "using LanguageServer; runserver()" }, +}; + pub const kdl = .{ .color = 0x000000, .icon = "", @@ -252,7 +286,7 @@ pub const nu = .{ .icon = ">", .extensions = .{ "nu", "nushell" }, .comment = "#", - .language_server = .{"nu", "--lsp"}, + .language_server = .{ "nu", "--lsp" }, .highlights = "tree-sitter-nu/queries/nu/highlights.scm", .injections = "tree-sitter-nu/queries/nu/injections.scm", }; @@ -302,7 +336,7 @@ pub const python = .{ .icon = "󰌠", .extensions = .{"py"}, .comment = "#", - .first_line_matches = .{ .prefix = "#!", .content = "/bin/bash" }, + .first_line_matches = .{ .prefix = "#!", .content = "python" }, .language_server = .{"pylsp"}, }; @@ -316,6 +350,7 @@ pub const ruby = .{ .icon = "󰴭", .extensions = .{"rb"}, .comment = "#", + .language_server = .{"ruby-lsp"}, }; pub const rust = .{ @@ -337,6 +372,15 @@ pub const @"ssh-config" = .{ .comment = "#", }; +pub const swift = .{ + .color = 0xf05138, + .icon = "󰛥", + .extensions = .{ "swift", "swiftinterface" }, + .comment = "//", + .language_server = .{"sourcekit-lsp"}, + .formatter = .{"swift-format"}, +}; + pub const toml = .{ .extensions = .{ "toml", "ini" }, .comment = "#", diff --git a/src/syntax.zig b/src/syntax.zig index 6737389..0f8ff97 100644 --- a/src/syntax.zig +++ b/src/syntax.zig @@ -26,7 +26,7 @@ query: *Query, injections: *Query, tree: ?*treez.Tree = null, -pub fn create(file_type: *const FileType, allocator: std.mem.Allocator, content: []const u8) !*Self { +pub fn create(file_type: *const FileType, allocator: std.mem.Allocator) !*Self { const self = try allocator.create(Self); self.* = .{ .allocator = allocator, @@ -38,18 +38,17 @@ pub fn create(file_type: *const FileType, allocator: std.mem.Allocator, content: }; errdefer self.destroy(); try self.parser.setLanguage(self.lang); - try self.refresh_full(content); return self; } -pub fn create_file_type(allocator: std.mem.Allocator, content: []const u8, lang_name: []const u8) !*Self { +pub fn create_file_type(allocator: std.mem.Allocator, lang_name: []const u8) !*Self { const file_type = FileType.get_by_name(lang_name) orelse return error.NotFound; - return create(file_type, allocator, content); + return create(file_type, allocator); } pub fn create_guess_file_type(allocator: std.mem.Allocator, content: []const u8, file_path: ?[]const u8) !*Self { const file_type = FileType.guess(file_path, content) orelse return error.NotFound; - return create(file_type, allocator, content); + return create(file_type, allocator); } pub fn destroy(self: *Self) void { @@ -59,8 +58,15 @@ pub fn destroy(self: *Self) void { self.allocator.destroy(self); } +pub fn reset(self: *Self) void { + if (self.tree) |tree| { + tree.destroy(); + self.tree = null; + } +} + pub fn refresh_full(self: *Self, content: []const u8) !void { - if (self.tree) |tree| tree.destroy(); + self.reset(); self.tree = try self.parser.parseString(null, content); } @@ -68,12 +74,6 @@ pub fn edit(self: *Self, ed: Edit) void { if (self.tree) |tree| tree.edit(&ed); } -pub fn refresh(self: *Self, content: []const u8) !void { - const old_tree = self.tree; - defer if (old_tree) |tree| tree.destroy(); - self.tree = try self.parser.parseString(old_tree, content); -} - pub fn refresh_from_buffer(self: *Self, buffer: anytype, metrics: anytype) !void { const old_tree = self.tree; defer if (old_tree) |tree| tree.destroy(); @@ -105,6 +105,47 @@ pub fn refresh_from_buffer(self: *Self, buffer: anytype, metrics: anytype) !void self.tree = try self.parser.parse(old_tree, input); } +pub fn refresh_from_string(self: *Self, content: [:0]const u8) !void { + const old_tree = self.tree; + defer if (old_tree) |tree| tree.destroy(); + + const State = struct { + content: @TypeOf(content), + }; + var state: State = .{ + .content = content, + }; + + const input: Input = .{ + .payload = &state, + .read = struct { + fn read(payload: ?*anyopaque, _: u32, position: treez.Point, bytes_read: *u32) callconv(.C) [*:0]const u8 { + bytes_read.* = 0; + const ctx: *State = @ptrCast(@alignCast(payload orelse return "")); + const pos = (find_line_begin(ctx.content, position.row) orelse return "") + position.column; + if (pos >= ctx.content.len) return ""; + bytes_read.* = @intCast(ctx.content.len - pos); + return ctx.content[pos..].ptr; + } + }.read, + .encoding = .utf_8, + }; + self.tree = try self.parser.parse(old_tree, input); +} + +fn find_line_begin(s: []const u8, line: usize) ?usize { + var idx: usize = 0; + var at_line: usize = 0; + while (idx < s.len) { + if (at_line == line) + return idx; + if (s[idx] == '\n') + at_line += 1; + idx += 1; + } + return null; +} + fn CallBack(comptime T: type) type { return fn (ctx: T, sel: Range, scope: []const u8, id: u32, capture_idx: usize, node: *const Node) error{Stop}!void; } @@ -143,3 +184,9 @@ pub fn highlights_at_point(self: *const Self, ctx: anytype, comptime cb: CallBac } return; } + +pub fn node_at_point_range(self: *const Self, range: Range) error{Stop}!treez.Node { + const tree = self.tree orelse return error.Stop; + const root_node = tree.getRootNode(); + return treez.Node.externs.ts_node_descendant_for_point_range(root_node, range.start_point, range.end_point); +}