Compare commits
7 commits
5583ef01b2
...
0b0e72afa9
Author | SHA1 | Date | |
---|---|---|---|
0b0e72afa9 | |||
a0cd3e95c8 | |||
![]() |
a547d6ee49 | ||
54069d1301 | |||
6969727e07 | |||
8bb8ebb544 | |||
d200fdd581 |
5 changed files with 56 additions and 44 deletions
|
@ -24,7 +24,8 @@ const CacheEntry = struct {
|
|||
query: ?*Query,
|
||||
query_arena: ?*std.heap.ArenaAllocator,
|
||||
query_type: QueryType,
|
||||
file_type: *const FileType,
|
||||
file_type_name: []const u8,
|
||||
lang_fn: FileType.LangFn,
|
||||
|
||||
fn destroy(self: *@This(), allocator: std.mem.Allocator) void {
|
||||
if (self.query_arena) |a| {
|
||||
|
@ -101,7 +102,7 @@ fn release_cache_entry_hash_map(allocator: std.mem.Allocator, hash_map: *std.Str
|
|||
hash_map.deinit(allocator);
|
||||
}
|
||||
|
||||
fn get_cache_entry(self: *Self, file_type: *const FileType, comptime query_type: QueryType) CacheError!*CacheEntry {
|
||||
fn get_cache_entry(self: *Self, file_type: FileType, comptime query_type: QueryType) CacheError!*CacheEntry {
|
||||
if (self.mutex) |*mtx| mtx.lock();
|
||||
defer if (self.mutex) |*mtx| mtx.unlock();
|
||||
|
||||
|
@ -119,7 +120,8 @@ fn get_cache_entry(self: *Self, file_type: *const FileType, comptime query_type:
|
|||
.query = null,
|
||||
.query_arena = null,
|
||||
.mutex = if (self.mutex) |_| .{} else null,
|
||||
.file_type = file_type,
|
||||
.lang_fn = file_type.lang_fn,
|
||||
.file_type_name = file_type.name,
|
||||
.query_type = query_type,
|
||||
};
|
||||
entry_.value_ptr.* = q;
|
||||
|
@ -133,8 +135,8 @@ fn get_cached_query(self: *Self, entry: *CacheEntry) Error!?*Query {
|
|||
defer if (entry.mutex) |*mtx| mtx.unlock();
|
||||
|
||||
return if (entry.query) |query| query else blk: {
|
||||
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 lang = entry.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 query_bin = switch (entry.query_type) {
|
||||
.highlights => queries.highlights_bin,
|
||||
.errors => queries.errors_bin,
|
||||
|
@ -166,7 +168,7 @@ fn ReturnType(comptime query_type: QueryType) type {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn get(self: *Self, file_type: *const FileType, comptime query_type: QueryType) Error!ReturnType(query_type) {
|
||||
pub fn get(self: *Self, file_type: 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));
|
||||
self.add_ref_locked();
|
||||
return switch (@typeInfo(ReturnType(query_type))) {
|
||||
|
|
|
@ -20,43 +20,45 @@ comment: []const u8,
|
|||
formatter: ?[]const []const u8,
|
||||
language_server: ?[]const []const u8,
|
||||
|
||||
pub fn get_by_name(name: []const u8) ?*const FileType {
|
||||
for (file_types) |*file_type|
|
||||
if (std.mem.eql(u8, file_type.name, name))
|
||||
pub fn get_by_name_static(name: []const u8) ?FileType {
|
||||
return FileType.static_file_types.get(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 null;
|
||||
}
|
||||
|
||||
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 {
|
||||
fn guess_first_line_static(content: []const u8) ?FileType {
|
||||
const first_line = if (std.mem.indexOf(u8, content, "\n")) |pos| content[0..pos] else content;
|
||||
for (file_types) |*file_type|
|
||||
for (static_file_types) |*file_type|
|
||||
if (file_type.first_line_matches) |match|
|
||||
if (match_first_line(match, first_line))
|
||||
if (match_first_line(match.prefix, match.content, first_line))
|
||||
return file_type;
|
||||
return null;
|
||||
}
|
||||
|
||||
fn match_first_line(match: FirstLineMatch, first_line: []const u8) bool {
|
||||
if (match.prefix) |prefix|
|
||||
pub fn match_first_line(match_prefix: ?[]const u8, match_content: ?[]const u8, first_line: []const u8) bool {
|
||||
if (match_prefix == null and match_content == null) return false;
|
||||
if (match_prefix) |prefix|
|
||||
if (prefix.len > first_line.len or !std.mem.eql(u8, first_line[0..prefix.len], prefix))
|
||||
return false;
|
||||
if (match.content) |content|
|
||||
if (match_content) |content|
|
||||
if (std.mem.indexOf(u8, first_line, content)) |_| {} else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
fn match_file_type(file_type: *const FileType, file_path: []const u8) bool {
|
||||
pub fn match_file_type(extensions: []const []const u8, file_path: []const u8) bool {
|
||||
const basename = std.fs.path.basename(file_path);
|
||||
const extension = std.fs.path.extension(file_path);
|
||||
return for (file_type.extensions) |ext| {
|
||||
return for (extensions) |ext| {
|
||||
if (ext.len == basename.len and std.mem.eql(u8, ext, basename))
|
||||
return true;
|
||||
if (extension.len > 0 and ext.len == extension.len - 1 and std.mem.eql(u8, ext, extension[1..]))
|
||||
|
@ -85,14 +87,15 @@ fn ft_func_name(comptime lang: []const u8) []const u8 {
|
|||
return &func_name;
|
||||
}
|
||||
|
||||
const LangFn = *const fn () callconv(.C) ?*const treez.Language;
|
||||
pub const LangFn = *const fn () callconv(.C) ?*const treez.Language;
|
||||
|
||||
pub const FirstLineMatch = struct {
|
||||
prefix: ?[]const u8 = null,
|
||||
content: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub const file_types = load_file_types(@import("file_types.zig"));
|
||||
const static_file_type_list = 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 {
|
||||
var cmd: []const []const u8 = &[_][]const u8{};
|
||||
|
@ -102,7 +105,9 @@ fn vec(comptime args: anytype) []const []const u8 {
|
|||
return cmd;
|
||||
}
|
||||
|
||||
fn load_file_types(comptime Namespace: type) []const FileType {
|
||||
const ListEntry = struct { []const u8, FileType };
|
||||
|
||||
fn load_file_types(comptime Namespace: type) []const ListEntry {
|
||||
comptime switch (@typeInfo(Namespace)) {
|
||||
.@"struct" => |info| {
|
||||
var count = 0;
|
||||
|
@ -110,12 +115,12 @@ fn load_file_types(comptime Namespace: type) []const FileType {
|
|||
// @compileLog(decl.name, @TypeOf(@field(Namespace, decl.name)));
|
||||
count += 1;
|
||||
}
|
||||
var construct_types: [count]FileType = undefined;
|
||||
var construct_types: [count]ListEntry = undefined;
|
||||
var i = 0;
|
||||
for (info.decls) |decl| {
|
||||
const lang = decl.name;
|
||||
const args = @field(Namespace, lang);
|
||||
construct_types[i] = .{
|
||||
construct_types[i] = .{ lang, .{
|
||||
.color = if (@hasField(@TypeOf(args), "color")) args.color else 0xffffff,
|
||||
.icon = if (@hasField(@TypeOf(args), "icon")) args.icon else "",
|
||||
.name = lang,
|
||||
|
@ -126,7 +131,7 @@ fn load_file_types(comptime Namespace: type) []const FileType {
|
|||
.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,
|
||||
};
|
||||
} };
|
||||
i += 1;
|
||||
}
|
||||
const types = construct_types;
|
||||
|
@ -142,7 +147,7 @@ pub const FileTypeQueries = struct {
|
|||
injections_bin: ?[]const u8,
|
||||
};
|
||||
|
||||
pub const queries = std.static_string_map.StaticStringMap(FileTypeQueries).initComptime(load_queries());
|
||||
pub const queries = std.StaticStringMap(FileTypeQueries).initComptime(load_queries());
|
||||
|
||||
fn load_queries() []const struct { []const u8, FileTypeQueries } {
|
||||
if (!build_options.use_tree_sitter) return &.{};
|
||||
|
|
|
@ -88,6 +88,7 @@ pub const css = .{
|
|||
.icon = "",
|
||||
.extensions = .{"css"},
|
||||
.comment = "//",
|
||||
.language_server = .{ "vscode-css-language-server", "--stdio" },
|
||||
};
|
||||
|
||||
pub const diff = .{
|
||||
|
@ -230,15 +231,16 @@ pub const javascript = .{
|
|||
.extensions = .{"js"},
|
||||
.comment = "//",
|
||||
.injections = "tree-sitter-javascript/queries/injections.scm",
|
||||
.language_server = .{ "deno", "lsp" },
|
||||
.language_server = .{ "typescript-language-server", "--stdio" },
|
||||
.formatter = .{ "prettier", "--parser", "typescript" },
|
||||
};
|
||||
|
||||
pub const json = .{
|
||||
.description = "JSON",
|
||||
.extensions = .{"json"},
|
||||
.comment = "//",
|
||||
.language_server = .{ "deno", "lsp" },
|
||||
.formatter = .{ "hjson", "-j" },
|
||||
.language_server = .{ "vscode-json-language-server", "--stdio" },
|
||||
.formatter = .{ "prettier", "--parser", "json" },
|
||||
};
|
||||
|
||||
pub const julia = .{
|
||||
|
@ -293,7 +295,8 @@ pub const markdown = .{
|
|||
.comment = "<!--",
|
||||
.highlights = "tree-sitter-markdown/tree-sitter-markdown/queries/highlights.scm",
|
||||
.injections = "tree-sitter-markdown/tree-sitter-markdown/queries/injections.scm",
|
||||
.language_server = .{ "deno", "lsp" },
|
||||
.language_server = .{ "marksman", "server" },
|
||||
.formatter = .{ "prettier", "--parser", "markdown" },
|
||||
};
|
||||
|
||||
pub const @"markdown-inline" = .{
|
||||
|
@ -345,6 +348,8 @@ pub const nix = .{
|
|||
.extensions = .{"nix"},
|
||||
.comment = "#",
|
||||
.injections = "tree-sitter-nix/queries/injections.scm",
|
||||
.language_server = .{"nixd"},
|
||||
.formatter = .{"alejandra"},
|
||||
};
|
||||
|
||||
pub const nu = .{
|
||||
|
@ -525,7 +530,8 @@ pub const typescript = .{
|
|||
.icon = "",
|
||||
.extensions = .{ "ts", "tsx" },
|
||||
.comment = "//",
|
||||
.language_server = .{ "deno", "lsp" },
|
||||
.language_server = .{ "typescript-language-server", "--stdio" },
|
||||
.formatter = .{ "prettier", "--parser", "typescript" },
|
||||
};
|
||||
|
||||
pub const typst = .{
|
||||
|
|
|
@ -21,14 +21,13 @@ pub const Node = treez.Node;
|
|||
|
||||
allocator: std.mem.Allocator,
|
||||
lang: *const Language,
|
||||
file_type: *const FileType,
|
||||
parser: *Parser,
|
||||
query: *Query,
|
||||
errors_query: *Query,
|
||||
injections: ?*Query,
|
||||
tree: ?*treez.Tree = null,
|
||||
|
||||
pub fn create(file_type: *const FileType, allocator: std.mem.Allocator, query_cache: *QueryCache) !*Self {
|
||||
pub fn create(file_type: FileType, allocator: std.mem.Allocator, query_cache: *QueryCache) !*Self {
|
||||
const query = try query_cache.get(file_type, .highlights);
|
||||
const errors_query = try query_cache.get(file_type, .errors);
|
||||
const injections = try query_cache.get(file_type, .injections);
|
||||
|
@ -36,7 +35,6 @@ pub fn create(file_type: *const FileType, allocator: std.mem.Allocator, query_ca
|
|||
self.* = .{
|
||||
.allocator = allocator,
|
||||
.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 = query,
|
||||
.errors_query = errors_query,
|
||||
|
@ -47,13 +45,13 @@ pub fn create(file_type: *const FileType, allocator: std.mem.Allocator, query_ca
|
|||
return 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(lang_name) orelse return error.NotFound;
|
||||
pub fn static_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;
|
||||
return create(file_type, allocator, query_cache);
|
||||
}
|
||||
|
||||
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(file_path, content) orelse return error.NotFound;
|
||||
pub fn static_create_guess_file_type_static(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;
|
||||
return create(file_type, allocator, query_cache);
|
||||
}
|
||||
|
||||
|
|
|
@ -280,6 +280,7 @@ pub const DeserializeError = error{
|
|||
JsonIncompatibleType,
|
||||
InvalidQueryCbor,
|
||||
NotAnObject,
|
||||
BadArrayAllocExtract,
|
||||
};
|
||||
|
||||
pub fn fromCbor(cb: []const u8, allocator: std.mem.Allocator) DeserializeError!struct { *TSQuery, *std.heap.ArenaAllocator } {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue