feat: render diagnostics (part 1)
This commit is contained in:
parent
33dd4486eb
commit
e41c2d34f7
4 changed files with 67 additions and 14 deletions
|
@ -538,7 +538,7 @@ fn send_diagnostic(_: *Self, to: tp.pid_ref, file_path: []const u8, diagnostic:
|
|||
}
|
||||
|
||||
fn send_clear_diagnostics(_: *Self, to: tp.pid_ref, file_path: []const u8) !void {
|
||||
try to.send(.{ "cmd", "clear_diagnostics", file_path });
|
||||
try to.send(.{ "cmd", "clear_diagnostics", .{file_path} });
|
||||
}
|
||||
|
||||
const Range = struct { start: Position, end: Position };
|
||||
|
|
|
@ -564,3 +564,13 @@ fn walk_filtered(dir: std.fs.Dir, allocator: std.mem.Allocator) !FilteredWalker
|
|||
.name_buffer = name_buffer,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn normalize_file_path(file_path: []const u8) []const u8 {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0) return file_path;
|
||||
if (project.len >= file_path.len) return file_path;
|
||||
if (std.mem.eql(u8, project, file_path[0..project.len]) and file_path[project.len] == std.fs.path.sep)
|
||||
return file_path[project.len + 1 ..];
|
||||
return file_path;
|
||||
}
|
||||
|
||||
|
|
|
@ -149,6 +149,20 @@ pub const CurSel = struct {
|
|||
}
|
||||
};
|
||||
|
||||
const Diagnostic = struct {
|
||||
source: []const u8,
|
||||
code: []const u8,
|
||||
message: []const u8,
|
||||
severity: i32,
|
||||
sel: Selection,
|
||||
|
||||
fn deinit(self: *Diagnostic, a: std.mem.Allocator) void {
|
||||
a.free(self.source);
|
||||
a.free(self.code);
|
||||
a.free(self.message);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Editor = struct {
|
||||
const SelectMode = enum {
|
||||
char,
|
||||
|
@ -222,6 +236,8 @@ pub const Editor = struct {
|
|||
style_cache: ?StyleCache = null,
|
||||
style_cache_theme: []const u8 = "",
|
||||
|
||||
diagnostics: std.ArrayList(Diagnostic),
|
||||
|
||||
const StyleCache = std.AutoHashMap(u32, ?Widget.Theme.Token);
|
||||
|
||||
pub fn write_state(self: *const Self, writer: Buffer.MetaWriter) !void {
|
||||
|
@ -291,10 +307,13 @@ pub const Editor = struct {
|
|||
.matches = Match.List.init(a),
|
||||
.enable_terminal_cursor = tui.current().config.enable_terminal_cursor,
|
||||
.show_whitespace = tui.current().config.show_whitespace,
|
||||
.diagnostics = std.ArrayList(Diagnostic).init(a),
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: *Self) void {
|
||||
for (self.diagnostics.items) |*d| d.deinit(self.diagnostics.allocator);
|
||||
self.diagnostics.deinit();
|
||||
if (self.syntax) |syn| syn.destroy();
|
||||
self.cursels.deinit();
|
||||
self.matches.deinit();
|
||||
|
@ -688,6 +707,7 @@ pub const Editor = struct {
|
|||
_ = root.walk_from_line_begin_const(self.view.row, ctx.walker, &ctx_) catch {};
|
||||
}
|
||||
self.render_syntax(theme, cache, root) catch {};
|
||||
self.render_diagnostics(theme, root) catch {};
|
||||
self.render_cursors(theme) catch {};
|
||||
}
|
||||
|
||||
|
@ -766,6 +786,24 @@ pub const Editor = struct {
|
|||
};
|
||||
}
|
||||
|
||||
fn render_diagnostics(self: *const Self, theme: *const Widget.Theme, root: Buffer.Root) !void {
|
||||
for (self.diagnostics.items) |*diag| self.render_diagnostic(diag, theme, root);
|
||||
}
|
||||
|
||||
fn render_diagnostic(self: *const Self, diag: *const Diagnostic, theme: *const Widget.Theme, _: Buffer.Root) void {
|
||||
if (self.screen_cursor(&diag.sel.begin)) |pos| {
|
||||
self.plane.cursor_move_yx(@intCast(pos.row), @intCast(pos.col)) catch return;
|
||||
self.render_diagnostic_cell(theme);
|
||||
}
|
||||
}
|
||||
|
||||
inline fn render_diagnostic_cell(self: *const Self, theme: *const Widget.Theme) void {
|
||||
var cell = self.plane.cell_init();
|
||||
_ = self.plane.at_cursor_cell(&cell) catch return;
|
||||
tui.set_cell_style(&cell, theme.editor_error);
|
||||
_ = self.plane.putc(&cell) catch {};
|
||||
}
|
||||
|
||||
inline fn render_cursor_cell(self: *const Self, theme: *const Widget.Theme) void {
|
||||
var cell = self.plane.cell_init();
|
||||
_ = self.plane.at_cursor_cell(&cell) catch return;
|
||||
|
@ -3235,8 +3273,12 @@ pub const Editor = struct {
|
|||
return project_manager.goto_definition(file_path, primary.cursor.row, primary.cursor.col);
|
||||
}
|
||||
|
||||
pub fn clear_diagnostics(self: *Self, _: command.Context) tp.result {
|
||||
self.logger.print("diag: clear", .{});
|
||||
pub fn clear_diagnostics(self: *Self, ctx: command.Context) tp.result {
|
||||
var file_path: []const u8 = undefined;
|
||||
if (!try ctx.args.match(.{tp.extract(&file_path)})) return tp.exit_error(error.InvalidArgument);
|
||||
if (!std.mem.eql(u8, file_path, self.file_path orelse return)) return;
|
||||
for (self.diagnostics.items) |*d| d.deinit(self.diagnostics.allocator);
|
||||
self.diagnostics.clearRetainingCapacity();
|
||||
}
|
||||
|
||||
pub fn add_diagnostic(self: *Self, ctx: command.Context) tp.result {
|
||||
|
@ -3257,7 +3299,17 @@ pub const Editor = struct {
|
|||
tp.extract(&sel.end.row),
|
||||
tp.extract(&sel.end.col),
|
||||
})) return tp.exit_error(error.InvalidArgument);
|
||||
self.logger.print("diag: {d} {s} {s} {s} {any}", .{ severity, source, code, message, sel });
|
||||
file_path = project_manager.normalize_file_path(file_path);
|
||||
if (!std.mem.eql(u8, file_path, self.file_path orelse return)) return;
|
||||
|
||||
self.logger.print("diag: {d}:{d} {s}", .{ sel.begin.row, sel.begin.col, message });
|
||||
(self.diagnostics.addOne() catch |e| return tp.exit_error(e)).* = .{
|
||||
.source = self.diagnostics.allocator.dupe(u8, source) catch |e| return tp.exit_error(e),
|
||||
.code = self.diagnostics.allocator.dupe(u8, code) catch |e| return tp.exit_error(e),
|
||||
.message = self.diagnostics.allocator.dupe(u8, message) catch |e| return tp.exit_error(e),
|
||||
.severity = severity,
|
||||
.sel = sel,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn select(self: *Self, ctx: command.Context) tp.result {
|
||||
|
|
|
@ -207,7 +207,7 @@ const cmds = struct {
|
|||
file = file_name;
|
||||
} else return tp.exit_error(error.InvalidArgument);
|
||||
|
||||
const f = normalize_file_path(file orelse return);
|
||||
const f = project_manager.normalize_file_path(file orelse return);
|
||||
const same_file = if (self.editor) |editor| if (editor.file_path) |fp|
|
||||
std.mem.eql(u8, fp, f)
|
||||
else
|
||||
|
@ -462,15 +462,6 @@ fn read_restore_info(self: *Self) !void {
|
|||
}
|
||||
}
|
||||
|
||||
fn normalize_file_path(file_path: []const u8) []const u8 {
|
||||
const project = tp.env.get().str("project");
|
||||
if (project.len == 0) return file_path;
|
||||
if (project.len >= file_path.len) return file_path;
|
||||
if (std.mem.eql(u8, project, file_path[0..project.len]) and file_path[project.len] == std.fs.path.sep)
|
||||
return file_path[project.len + 1 ..];
|
||||
return file_path;
|
||||
}
|
||||
|
||||
fn push_file_stack(self: *Self, file_path: []const u8) !void {
|
||||
for (self.file_stack.items, 0..) |file_path_, i|
|
||||
if (std.mem.eql(u8, file_path, file_path_))
|
||||
|
|
Loading…
Add table
Reference in a new issue