diff --git a/build.zig b/build.zig index c96f3db..8a47c63 100644 --- a/build.zig +++ b/build.zig @@ -1,6 +1,11 @@ const std = @import("std"); pub fn build(b: *std.Build) void { + const use_tree_sitter = b.option(bool, "use_tree_sitter", "Enable tree-sitter (default: yes)") orelse true; + const options = b.addOptions(); + options.addOption(bool, "use_tree_sitter", use_tree_sitter); + const options_mod = options.createModule(); + const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); @@ -9,81 +14,85 @@ pub fn build(b: *std.Build) void { .optimize = optimize, }); + 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, "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"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-c/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-cpp/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-css/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-diff/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-dockerfile/queries/highlights.scm"), + 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-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-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-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"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-markdown/tree-sitter-markdown/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-markdown/tree-sitter-markdown-inline/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-nasm/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-nim/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-ninja/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-nix/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-ocaml/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-openscad/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-org/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-php/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-python/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-purescript/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-regex/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-ruby/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-rust/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-ssh-config/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-scala/queries/scala/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-toml/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-typescript/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-xml/queries/dtd/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-xml/queries/xml/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-yaml/queries/highlights.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-zig/queries/highlights.scm"), + 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, "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-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"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-lua/queries/injections.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-markdown/tree-sitter-markdown-inline/queries/injections.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-markdown/tree-sitter-markdown/queries/injections.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-nasm/queries/injections.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-nix/queries/injections.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-openscad/queries/injections.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-php/queries/injections.scm"), + ts_queryfile(b, tree_sitter_dep, "tree-sitter-purescript/queries/injections.scm"), + 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-zig/queries/injections.scm"), + } else &.{ + .{ .name = "build_options", .module = options_mod }, + }; + _ = b.addModule("syntax", .{ .root_source_file = b.path("src/syntax.zig"), - .imports = &.{ - .{ .name = "treez", .module = tree_sitter_dep.module("treez") }, - 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"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-c/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-cpp/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-css/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-diff/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-dockerfile/queries/highlights.scm"), - 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-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-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-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"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-markdown/tree-sitter-markdown/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-markdown/tree-sitter-markdown-inline/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-nasm/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-nim/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-ninja/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-nix/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-ocaml/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-openscad/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-org/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-php/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-python/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-purescript/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-regex/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-ruby/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-rust/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-ssh-config/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-scala/queries/scala/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-toml/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-typescript/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-xml/queries/dtd/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-xml/queries/xml/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-yaml/queries/highlights.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-zig/queries/highlights.scm"), - 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, "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-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"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-lua/queries/injections.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-markdown/tree-sitter-markdown-inline/queries/injections.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-markdown/tree-sitter-markdown/queries/injections.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-nasm/queries/injections.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-nix/queries/injections.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-openscad/queries/injections.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-php/queries/injections.scm"), - ts_queryfile(b, tree_sitter_dep, "tree-sitter-purescript/queries/injections.scm"), - 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-zig/queries/injections.scm"), - }, + .imports = imports, }); - } fn ts_queryfile(b: *std.Build, dep: *std.Build.Dependency, comptime sub_path: []const u8) std.Build.Module.Import { diff --git a/src/file_type.zig b/src/file_type.zig index 8e0ff4b..65f8c77 100644 --- a/src/file_type.zig +++ b/src/file_type.zig @@ -1,5 +1,11 @@ const std = @import("std"); -const treez = @import("treez"); +const build_options = @import("build_options"); + +const treez = if (build_options.use_tree_sitter) + @import("treez") +else + @import("treez_dummy.zig"); + pub const FileType = @This(); color: u24, @@ -63,8 +69,12 @@ pub fn Parser(comptime lang: []const u8) LangFn { } fn get_parser(comptime lang: []const u8) LangFn { - const language_name = ft_func_name(lang); - return @extern(?LangFn, .{ .name = "tree_sitter_" ++ language_name }) orelse @compileError(std.fmt.comptimePrint("Cannot find extern tree_sitter_{s}", .{language_name})); + if (build_options.use_tree_sitter) { + const language_name = ft_func_name(lang); + return @extern(?LangFn, .{ .name = "tree_sitter_" ++ language_name }) orelse @compileError(std.fmt.comptimePrint("Cannot find extern tree_sitter_{s}", .{language_name})); + } else { + return treez.Language.LangFn; + } } fn ft_func_name(comptime lang: []const u8) []const u8 { @@ -112,8 +122,20 @@ fn load_file_types(comptime Namespace: type) []const FileType { .lang_fn = if (@hasField(@TypeOf(args), "parser")) args.parser else get_parser(lang), .extensions = vec(args.extensions), .comment = args.comment, - .highlights = if (@hasField(@TypeOf(args), "highlights")) @embedFile(args.highlights) else @embedFile("tree-sitter-" ++ lang ++ "/queries/highlights.scm"), - .injections = if (@hasField(@TypeOf(args), "injections")) @embedFile(args.injections) else null, + .highlights = if (build_options.use_tree_sitter) + if (@hasField(@TypeOf(args), "highlights")) + @embedFile(args.highlights) + else + @embedFile("tree-sitter-" ++ lang ++ "/queries/highlights.scm") + else + "", + .injections = if (build_options.use_tree_sitter) + if (@hasField(@TypeOf(args), "injections")) + @embedFile(args.injections) + else + null + else + null, .first_line_matches = if (@hasField(@TypeOf(args), "first_line_matches")) args.first_line_matches else null, .formatter = if (@hasField(@TypeOf(args), "formatter")) vec(args.formatter) else null, .language_server = if (@hasField(@TypeOf(args), "language_server")) vec(args.language_server) else null, diff --git a/src/syntax.zig b/src/syntax.zig index 4c6f1f4..01d5b18 100644 --- a/src/syntax.zig +++ b/src/syntax.zig @@ -1,5 +1,10 @@ const std = @import("std"); -const treez = @import("treez"); +const build_options = @import("build_options"); + +const treez = if (build_options.use_tree_sitter) + @import("treez") +else + @import("treez_dummy.zig"); const Self = @This(); @@ -7,10 +12,10 @@ pub const Edit = treez.InputEdit; pub const FileType = @import("file_type.zig"); pub const Range = treez.Range; pub const Point = treez.Point; +const Input = treez.Input; const Language = treez.Language; const Parser = treez.Parser; const Query = treez.Query; -const Tree = treez.Tree; pub const Node = treez.Node; a: std.mem.Allocator, @@ -19,13 +24,13 @@ file_type: *const FileType, parser: *Parser, query: *Query, injections: *Query, -tree: ?*Tree = null, +tree: ?*treez.Tree = null, pub fn create(file_type: *const FileType, a: std.mem.Allocator, content: []const u8) !*Self { const self = try a.create(Self); self.* = .{ .a = a, - .lang = file_type.lang_fn() orelse std.debug.panic("tree-sitter parser function failed for language: {d}", .{file_type.name}), + .lang = file_type.lang_fn() orelse std.debug.panic("tree-sitter parser function failed for language: {s}", .{file_type.name}), .file_type = file_type, .parser = try Parser.create(), .query = try Query.create(self.lang, file_type.highlights), @@ -85,7 +90,7 @@ pub fn refresh_from_buffer(self: *Self, buffer: anytype, metrics: anytype) !void .syntax = self, }; - const input: treez.Input = .{ + const input: Input = .{ .payload = &state, .read = struct { fn read(payload: ?*anyopaque, _: u32, position: treez.Point, bytes_read: *u32) callconv(.C) [*:0]const u8 { diff --git a/src/treez_dummy.zig b/src/treez_dummy.zig new file mode 100644 index 0000000..ccb96de --- /dev/null +++ b/src/treez_dummy.zig @@ -0,0 +1,104 @@ +pub const InputEdit = extern struct { + start_byte: u32, + old_end_byte: u32, + new_end_byte: u32, + start_point: Point, + old_end_point: Point, + new_end_point: Point, +}; +pub const Range = extern struct { + start_point: Point = .{}, + end_point: Point = .{}, + start_byte: u32 = 0, + end_byte: u32 = 0, +}; + +pub const Point = extern struct { + row: u32 = 0, + column: u32 = 0, +}; +pub const InputEncoding = enum(c_uint) { + utf_8, + utf_16, +}; +pub const Input = extern struct { + payload: ?*anyopaque, + read: ?*const fn (payload: ?*anyopaque, byte_index: u32, position: Point, bytes_read: *u32) callconv(.C) [*:0]const u8, + encoding: InputEncoding, +}; +pub const Language = struct { + var dummy: @This() = .{}; + pub fn LangFn() callconv(.C) ?*const Language { + return &dummy; + } +}; +pub const Parser = struct { + var dummy: @This() = .{}; + pub fn create() !*@This() { + return &dummy; + } + pub fn parse(_: *Parser, _: ?*Tree, _: Input) !*Tree { + return &Tree.dummy; + } + pub fn parseString(_: *@This(), _: ?[]const u8, _: []const u8) !?*Tree { + return null; + } + pub fn destroy(_: *@This()) void {} + pub fn setLanguage(_: *Parser, _: *const Language) !void {} +}; +pub const Query = struct { + var dummy: @This() = .{}; + pub fn create(_: *const Language, _: []const u8) !*Query { + return &dummy; + } + pub const Cursor = struct { + var dummy_: @This() = .{}; + pub fn create() !*@This() { + return &dummy_; + } + pub fn execute(_: *@This(), _: *Query, _: *Node) void {} + pub fn setPointRange(_: *@This(), _: Point, _: Point) void {} + pub fn nextMatch(_: *@This()) ?*Match { + return null; + } + pub fn destroy(_: *@This()) void {} + + pub const Match = struct { + pub fn captures(_: *@This()) []Capture { + return &[_]Capture{}; + } + }; + pub const Capture = struct { + id: u32, + node: Node, + }; + }; + pub fn getCaptureNameForId(_: *@This(), _: u32) []const u8 { + return ""; + } + pub fn destroy(_: *@This()) void {} +}; +pub const Tree = struct { + var dummy: @This() = .{}; + pub fn getRootNode(_: *@This()) *Node { + return &Node.dummy; + } + pub fn destroy(_: *@This()) void {} + pub fn edit(_: *Tree, _: *const InputEdit) void {} +}; +pub const Node = struct { + var dummy: @This() = .{}; + pub fn getRange(_: *const @This()) Range { + return .{}; + } + pub fn asSExpressionString(_: *const @This()) []const u8 { + return ""; + } + pub fn freeSExpressionString(_: []const u8) void {} + pub fn getParent(_: *const @This()) *Node { + return &dummy; + } + pub fn isNull(_: *const @This()) bool { + return true; + } +};