Compare commits

..

No commits in common. "0b0e72afa91fe9c085df04e43ea824034098b445" and "5583ef01b22534573bc0b4f207ce8e701ceeb9d5" have entirely different histories.

5 changed files with 44 additions and 56 deletions

View file

@ -24,8 +24,7 @@ const CacheEntry = struct {
query: ?*Query, query: ?*Query,
query_arena: ?*std.heap.ArenaAllocator, query_arena: ?*std.heap.ArenaAllocator,
query_type: QueryType, query_type: QueryType,
file_type_name: []const u8, file_type: *const FileType,
lang_fn: FileType.LangFn,
fn destroy(self: *@This(), allocator: std.mem.Allocator) void { fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
if (self.query_arena) |a| { if (self.query_arena) |a| {
@ -102,7 +101,7 @@ fn release_cache_entry_hash_map(allocator: std.mem.Allocator, hash_map: *std.Str
hash_map.deinit(allocator); hash_map.deinit(allocator);
} }
fn get_cache_entry(self: *Self, file_type: FileType, comptime query_type: QueryType) CacheError!*CacheEntry { fn get_cache_entry(self: *Self, file_type: *const FileType, comptime query_type: QueryType) CacheError!*CacheEntry {
if (self.mutex) |*mtx| mtx.lock(); if (self.mutex) |*mtx| mtx.lock();
defer if (self.mutex) |*mtx| mtx.unlock(); defer if (self.mutex) |*mtx| mtx.unlock();
@ -120,8 +119,7 @@ fn get_cache_entry(self: *Self, file_type: FileType, comptime query_type: QueryT
.query = null, .query = null,
.query_arena = null, .query_arena = null,
.mutex = if (self.mutex) |_| .{} else null, .mutex = if (self.mutex) |_| .{} else null,
.lang_fn = file_type.lang_fn, .file_type = file_type,
.file_type_name = file_type.name,
.query_type = query_type, .query_type = query_type,
}; };
entry_.value_ptr.* = q; entry_.value_ptr.* = q;
@ -135,8 +133,8 @@ fn get_cached_query(self: *Self, entry: *CacheEntry) Error!?*Query {
defer if (entry.mutex) |*mtx| mtx.unlock(); defer if (entry.mutex) |*mtx| mtx.unlock();
return if (entry.query) |query| query else blk: { return if (entry.query) |query| query else blk: {
const lang = entry.lang_fn() orelse std.debug.panic("tree-sitter parser function failed for language: {s}", .{entry.file_type_name}); const lang = entry.file_type.lang_fn() orelse std.debug.panic("tree-sitter parser function failed for language: {s}", .{entry.file_type.name});
const queries = FileType.queries.get(entry.file_type_name) orelse return null; const queries = FileType.queries.get(entry.file_type.name) orelse return null;
const query_bin = switch (entry.query_type) { const query_bin = switch (entry.query_type) {
.highlights => queries.highlights_bin, .highlights => queries.highlights_bin,
.errors => queries.errors_bin, .errors => queries.errors_bin,
@ -168,7 +166,7 @@ fn ReturnType(comptime query_type: QueryType) type {
}; };
} }
pub fn get(self: *Self, file_type: FileType, comptime query_type: QueryType) Error!ReturnType(query_type) { pub fn get(self: *Self, file_type: *const FileType, comptime query_type: QueryType) Error!ReturnType(query_type) {
const query = try self.get_cached_query(try self.get_cache_entry(file_type, query_type)); const query = try self.get_cached_query(try self.get_cache_entry(file_type, query_type));
self.add_ref_locked(); self.add_ref_locked();
return switch (@typeInfo(ReturnType(query_type))) { return switch (@typeInfo(ReturnType(query_type))) {

View file

@ -20,45 +20,43 @@ comment: []const u8,
formatter: ?[]const []const u8, formatter: ?[]const []const u8,
language_server: ?[]const []const u8, language_server: ?[]const []const u8,
pub fn get_by_name_static(name: []const u8) ?FileType { pub fn get_by_name(name: []const u8) ?*const FileType {
return FileType.static_file_types.get(name); for (file_types) |*file_type|
} if (std.mem.eql(u8, file_type.name, name))
pub fn get_all() []const FileType {
return FileType.static_file_types.values();
}
pub fn guess_static(file_path: ?[]const u8, content: []const u8) ?FileType {
if (guess_first_line_static(content)) |ft| return ft;
for (static_file_types.values()) |*file_type|
if (file_path) |fp| if (match_file_type(file_type.extensions, fp))
return file_type; return file_type;
return null; return null;
} }
fn guess_first_line_static(content: []const u8) ?FileType { pub fn guess(file_path: ?[]const u8, content: []const u8) ?*const FileType {
if (guess_first_line(content)) |ft| return ft;
for (file_types) |*file_type|
if (file_path) |fp| if (match_file_type(file_type, fp))
return file_type;
return null;
}
fn guess_first_line(content: []const u8) ?*const FileType {
const first_line = if (std.mem.indexOf(u8, content, "\n")) |pos| content[0..pos] else content; const first_line = if (std.mem.indexOf(u8, content, "\n")) |pos| content[0..pos] else content;
for (static_file_types) |*file_type| for (file_types) |*file_type|
if (file_type.first_line_matches) |match| if (file_type.first_line_matches) |match|
if (match_first_line(match.prefix, match.content, first_line)) if (match_first_line(match, first_line))
return file_type; return file_type;
return null; return null;
} }
pub fn match_first_line(match_prefix: ?[]const u8, match_content: ?[]const u8, first_line: []const u8) bool { fn match_first_line(match: FirstLineMatch, first_line: []const u8) bool {
if (match_prefix == null and match_content == null) return false; if (match.prefix) |prefix|
if (match_prefix) |prefix|
if (prefix.len > first_line.len or !std.mem.eql(u8, first_line[0..prefix.len], prefix)) if (prefix.len > first_line.len or !std.mem.eql(u8, first_line[0..prefix.len], prefix))
return false; return false;
if (match_content) |content| if (match.content) |content|
if (std.mem.indexOf(u8, first_line, content)) |_| {} else return false; if (std.mem.indexOf(u8, first_line, content)) |_| {} else return false;
return true; return true;
} }
pub fn match_file_type(extensions: []const []const u8, file_path: []const u8) bool { fn match_file_type(file_type: *const FileType, file_path: []const u8) bool {
const basename = std.fs.path.basename(file_path); const basename = std.fs.path.basename(file_path);
const extension = std.fs.path.extension(file_path); const extension = std.fs.path.extension(file_path);
return for (extensions) |ext| { return for (file_type.extensions) |ext| {
if (ext.len == basename.len and std.mem.eql(u8, ext, basename)) if (ext.len == basename.len and std.mem.eql(u8, ext, basename))
return true; return true;
if (extension.len > 0 and ext.len == extension.len - 1 and std.mem.eql(u8, ext, extension[1..])) if (extension.len > 0 and ext.len == extension.len - 1 and std.mem.eql(u8, ext, extension[1..]))
@ -87,15 +85,14 @@ fn ft_func_name(comptime lang: []const u8) []const u8 {
return &func_name; return &func_name;
} }
pub const LangFn = *const fn () callconv(.C) ?*const treez.Language; const LangFn = *const fn () callconv(.C) ?*const treez.Language;
pub const FirstLineMatch = struct { pub const FirstLineMatch = struct {
prefix: ?[]const u8 = null, prefix: ?[]const u8 = null,
content: ?[]const u8 = null, content: ?[]const u8 = null,
}; };
const static_file_type_list = load_file_types(@import("file_types.zig")); pub const file_types = load_file_types(@import("file_types.zig"));
const static_file_types = std.StaticStringMap(FileType).initComptime(static_file_type_list);
fn vec(comptime args: anytype) []const []const u8 { fn vec(comptime args: anytype) []const []const u8 {
var cmd: []const []const u8 = &[_][]const u8{}; var cmd: []const []const u8 = &[_][]const u8{};
@ -105,9 +102,7 @@ fn vec(comptime args: anytype) []const []const u8 {
return cmd; return cmd;
} }
const ListEntry = struct { []const u8, FileType }; fn load_file_types(comptime Namespace: type) []const FileType {
fn load_file_types(comptime Namespace: type) []const ListEntry {
comptime switch (@typeInfo(Namespace)) { comptime switch (@typeInfo(Namespace)) {
.@"struct" => |info| { .@"struct" => |info| {
var count = 0; var count = 0;
@ -115,12 +110,12 @@ fn load_file_types(comptime Namespace: type) []const ListEntry {
// @compileLog(decl.name, @TypeOf(@field(Namespace, decl.name))); // @compileLog(decl.name, @TypeOf(@field(Namespace, decl.name)));
count += 1; count += 1;
} }
var construct_types: [count]ListEntry = undefined; var construct_types: [count]FileType = undefined;
var i = 0; var i = 0;
for (info.decls) |decl| { for (info.decls) |decl| {
const lang = decl.name; const lang = decl.name;
const args = @field(Namespace, lang); const args = @field(Namespace, lang);
construct_types[i] = .{ lang, .{ construct_types[i] = .{
.color = if (@hasField(@TypeOf(args), "color")) args.color else 0xffffff, .color = if (@hasField(@TypeOf(args), "color")) args.color else 0xffffff,
.icon = if (@hasField(@TypeOf(args), "icon")) args.icon else "󱀫", .icon = if (@hasField(@TypeOf(args), "icon")) args.icon else "󱀫",
.name = lang, .name = lang,
@ -131,7 +126,7 @@ fn load_file_types(comptime Namespace: type) []const ListEntry {
.first_line_matches = if (@hasField(@TypeOf(args), "first_line_matches")) args.first_line_matches 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, .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, .language_server = if (@hasField(@TypeOf(args), "language_server")) vec(args.language_server) else null,
} }; };
i += 1; i += 1;
} }
const types = construct_types; const types = construct_types;
@ -147,7 +142,7 @@ pub const FileTypeQueries = struct {
injections_bin: ?[]const u8, injections_bin: ?[]const u8,
}; };
pub const queries = std.StaticStringMap(FileTypeQueries).initComptime(load_queries()); pub const queries = std.static_string_map.StaticStringMap(FileTypeQueries).initComptime(load_queries());
fn load_queries() []const struct { []const u8, FileTypeQueries } { fn load_queries() []const struct { []const u8, FileTypeQueries } {
if (!build_options.use_tree_sitter) return &.{}; if (!build_options.use_tree_sitter) return &.{};

View file

@ -88,7 +88,6 @@ pub const css = .{
.icon = "󰌜", .icon = "󰌜",
.extensions = .{"css"}, .extensions = .{"css"},
.comment = "//", .comment = "//",
.language_server = .{ "vscode-css-language-server", "--stdio" },
}; };
pub const diff = .{ pub const diff = .{
@ -231,16 +230,15 @@ pub const javascript = .{
.extensions = .{"js"}, .extensions = .{"js"},
.comment = "//", .comment = "//",
.injections = "tree-sitter-javascript/queries/injections.scm", .injections = "tree-sitter-javascript/queries/injections.scm",
.language_server = .{ "typescript-language-server", "--stdio" }, .language_server = .{ "deno", "lsp" },
.formatter = .{ "prettier", "--parser", "typescript" },
}; };
pub const json = .{ pub const json = .{
.description = "JSON", .description = "JSON",
.extensions = .{"json"}, .extensions = .{"json"},
.comment = "//", .comment = "//",
.language_server = .{ "vscode-json-language-server", "--stdio" }, .language_server = .{ "deno", "lsp" },
.formatter = .{ "prettier", "--parser", "json" }, .formatter = .{ "hjson", "-j" },
}; };
pub const julia = .{ pub const julia = .{
@ -295,8 +293,7 @@ pub const markdown = .{
.comment = "<!--", .comment = "<!--",
.highlights = "tree-sitter-markdown/tree-sitter-markdown/queries/highlights.scm", .highlights = "tree-sitter-markdown/tree-sitter-markdown/queries/highlights.scm",
.injections = "tree-sitter-markdown/tree-sitter-markdown/queries/injections.scm", .injections = "tree-sitter-markdown/tree-sitter-markdown/queries/injections.scm",
.language_server = .{ "marksman", "server" }, .language_server = .{ "deno", "lsp" },
.formatter = .{ "prettier", "--parser", "markdown" },
}; };
pub const @"markdown-inline" = .{ pub const @"markdown-inline" = .{
@ -348,8 +345,6 @@ pub const nix = .{
.extensions = .{"nix"}, .extensions = .{"nix"},
.comment = "#", .comment = "#",
.injections = "tree-sitter-nix/queries/injections.scm", .injections = "tree-sitter-nix/queries/injections.scm",
.language_server = .{"nixd"},
.formatter = .{"alejandra"},
}; };
pub const nu = .{ pub const nu = .{
@ -530,8 +525,7 @@ pub const typescript = .{
.icon = "󰛦", .icon = "󰛦",
.extensions = .{ "ts", "tsx" }, .extensions = .{ "ts", "tsx" },
.comment = "//", .comment = "//",
.language_server = .{ "typescript-language-server", "--stdio" }, .language_server = .{ "deno", "lsp" },
.formatter = .{ "prettier", "--parser", "typescript" },
}; };
pub const typst = .{ pub const typst = .{

View file

@ -21,13 +21,14 @@ pub const Node = treez.Node;
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
lang: *const Language, lang: *const Language,
file_type: *const FileType,
parser: *Parser, parser: *Parser,
query: *Query, query: *Query,
errors_query: *Query, errors_query: *Query,
injections: ?*Query, injections: ?*Query,
tree: ?*treez.Tree = null, tree: ?*treez.Tree = null,
pub fn create(file_type: FileType, allocator: std.mem.Allocator, query_cache: *QueryCache) !*Self { pub fn create(file_type: *const FileType, allocator: std.mem.Allocator, query_cache: *QueryCache) !*Self {
const query = try query_cache.get(file_type, .highlights); const query = try query_cache.get(file_type, .highlights);
const errors_query = try query_cache.get(file_type, .errors); const errors_query = try query_cache.get(file_type, .errors);
const injections = try query_cache.get(file_type, .injections); const injections = try query_cache.get(file_type, .injections);
@ -35,6 +36,7 @@ pub fn create(file_type: FileType, allocator: std.mem.Allocator, query_cache: *Q
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,
.lang = file_type.lang_fn() orelse std.debug.panic("tree-sitter parser function failed for language: {s}", .{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(), .parser = try Parser.create(),
.query = query, .query = query,
.errors_query = errors_query, .errors_query = errors_query,
@ -45,13 +47,13 @@ pub fn create(file_type: FileType, allocator: std.mem.Allocator, query_cache: *Q
return self; return self;
} }
pub fn static_create_file_type(allocator: std.mem.Allocator, lang_name: []const u8, query_cache: *QueryCache) !*Self { pub fn create_file_type(allocator: std.mem.Allocator, lang_name: []const u8, query_cache: *QueryCache) !*Self {
const file_type = FileType.get_by_name_static(lang_name) orelse return error.NotFound; const file_type = FileType.get_by_name(lang_name) orelse return error.NotFound;
return create(file_type, allocator, query_cache); return create(file_type, allocator, query_cache);
} }
pub fn static_create_guess_file_type_static(allocator: std.mem.Allocator, content: []const u8, file_path: ?[]const u8, query_cache: *QueryCache) !*Self { pub fn create_guess_file_type(allocator: std.mem.Allocator, content: []const u8, file_path: ?[]const u8, query_cache: *QueryCache) !*Self {
const file_type = FileType.guess_static(file_path, content) orelse return error.NotFound; const file_type = FileType.guess(file_path, content) orelse return error.NotFound;
return create(file_type, allocator, query_cache); return create(file_type, allocator, query_cache);
} }

View file

@ -280,7 +280,6 @@ pub const DeserializeError = error{
JsonIncompatibleType, JsonIncompatibleType,
InvalidQueryCbor, InvalidQueryCbor,
NotAnObject, NotAnObject,
BadArrayAllocExtract,
}; };
pub fn fromCbor(cb: []const u8, allocator: std.mem.Allocator) DeserializeError!struct { *TSQuery, *std.heap.ArenaAllocator } { pub fn fromCbor(cb: []const u8, allocator: std.mem.Allocator) DeserializeError!struct { *TSQuery, *std.heap.ArenaAllocator } {