forked from kristoff-it/zine
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhighlight.zig
73 lines (63 loc) · 2.15 KB
/
highlight.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
const std = @import("std");
const syntax = @import("syntax");
const treez = @import("treez");
const HtmlSafe = @import("superhtml").HtmlSafe;
const log = std.log.scoped(.highlight);
pub const DotsToSpaces = struct {
bytes: []const u8,
pub fn format(
self: DotsToSpaces,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
out_stream: anytype,
) !void {
_ = options;
_ = fmt;
for (self.bytes) |b| {
switch (b) {
'.' => try out_stream.writeAll(" "),
else => try out_stream.writeByte(b),
}
}
}
};
pub fn highlightCode(
arena: std.mem.Allocator,
lang_name: []const u8,
code: []const u8,
writer: anytype,
) !void {
const lang = syntax.create_file_type(arena, lang_name) catch blk: {
const fake_filename = try std.fmt.allocPrint(arena, "file.{s}", .{lang_name});
break :blk try syntax.create_guess_file_type(arena, "", fake_filename);
};
try lang.refresh_full(code);
defer lang.destroy();
const tree = lang.tree orelse return;
const cursor = try treez.Query.Cursor.create();
defer cursor.destroy();
cursor.execute(lang.query, tree.getRootNode());
var print_cursor: usize = 0;
while (cursor.nextMatch()) |match| {
var idx: usize = 0;
for (match.captures()) |capture| {
const capture_name = lang.query.getCaptureNameForId(capture.id);
const range = capture.node.getRange();
if (range.start_byte < print_cursor) continue;
if (range.start_byte > print_cursor) {
try writer.print("{s}", .{HtmlSafe{ .bytes = code[print_cursor..range.start_byte] }});
}
try writer.print(
\\<span class="{s}">{s}</span>
, .{
DotsToSpaces{ .bytes = capture_name },
HtmlSafe{ .bytes = code[range.start_byte..range.end_byte] },
});
print_cursor = range.end_byte;
idx += 1;
}
}
if (code.len > print_cursor) {
try writer.print("{s}", .{HtmlSafe{ .bytes = code[print_cursor..] }});
}
}