refactor: add lsp_info to mainview

This commit is contained in:
CJ van den Berg 2025-12-26 14:25:03 +01:00
parent 89dc5cce54
commit 4f737e4019
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
2 changed files with 102 additions and 0 deletions

93
src/tui/lsp_info.zig Normal file
View file

@ -0,0 +1,93 @@
allocator: std.mem.Allocator,
table: Table,
const Table = std.StringHashMapUnmanaged(Info);
pub fn init(allocator: std.mem.Allocator) @This() {
return .{
.allocator = allocator,
.table = .empty,
};
}
pub fn deinit(self: *@This()) void {
var iter = self.table.iterator();
while (iter.next()) |item| {
for (item.value_ptr.trigger_characters.items) |char|
self.allocator.free(char);
item.value_ptr.trigger_characters.deinit(self.allocator);
self.allocator.free(item.key_ptr.*);
}
self.table.deinit(self.allocator);
}
pub fn add_from_event(self: *@This(), cbor_buf: []const u8) error{ InvalidTriggersArray, OutOfMemory }!void {
var iter = cbor_buf;
var project: []const u8 = undefined;
var lsp_arg0: []const u8 = undefined;
var trigger_characters: []const u8 = undefined;
if (!(cbor.matchValue(&iter, .{
cbor.any,
cbor.any,
cbor.extract(&project),
.{ cbor.extract(&lsp_arg0), cbor.more },
cbor.extract_cbor(&trigger_characters),
}) catch return)) return;
const value = try self.add(lsp_arg0, &trigger_characters);
std.log.debug("{s} triggers: {any}", .{ lsp_arg0, value.trigger_characters.items });
}
pub fn add(self: *@This(), lsp_arg0: []const u8, iter: *[]const u8) error{ InvalidTriggersArray, OutOfMemory }!*Info {
const key = try self.allocator.dupe(u8, lsp_arg0);
errdefer self.allocator.free(key);
const p = try self.table.getOrPut(self.allocator, key);
const value = p.value_ptr;
if (p.found_existing) {
for (value.trigger_characters.items) |char|
self.allocator.free(char);
value.trigger_characters.clearRetainingCapacity();
} else {
value.* = .{};
}
var len = cbor.decodeArrayHeader(iter) catch return error.InvalidTriggersArray;
while (len > 0) : (len -= 1) {
var char: []const u8 = undefined;
if (!(cbor.matchValue(iter, cbor.extract(&char)) catch return error.InvalidTriggersArray)) return error.InvalidTriggersArray;
(try value.trigger_characters.addOne(self.allocator)).* = try self.allocator.dupe(u8, char);
}
return value;
}
pub const Info = struct {
trigger_characters: std.ArrayList([]const u8) = .empty,
};
pub fn write_state(self: *@This(), writer: *std.Io.Writer) error{WriteFailed}!void {
try cbor.writeArrayHeader(writer, self.table.count());
var iter = self.table.iterator();
while (iter.next()) |item| {
try cbor.writeArrayHeader(writer, 2);
try cbor.writeValue(writer, item.key_ptr.*);
try cbor.writeArrayHeader(writer, item.value_ptr.trigger_characters.items.len);
for (item.value_ptr.trigger_characters.items) |char| try cbor.writeValue(writer, char);
}
}
pub fn extract_state(self: *@This(), iter: *[]const u8) error{ InvalidTriggersArray, OutOfMemory }!void {
var lsp_arg0: []const u8 = undefined;
var trigger_characters: []const u8 = undefined;
var len = cbor.decodeArrayHeader(iter) catch return;
while (len > 0) : (len -= 1) {
if (cbor.matchValue(iter, .{ cbor.extract(&lsp_arg0), cbor.extract_cbor(&trigger_characters) }) catch false) {
const value = try self.add(lsp_arg0, &trigger_characters);
std.log.debug("restored {s} triggers: {any}", .{ lsp_arg0, value.trigger_characters.items });
} else {
cbor.skipValue(iter) catch return error.InvalidTriggersArray;
}
}
}
const std = @import("std");
const cbor = @import("cbor");

View file

@ -27,6 +27,7 @@ const WidgetList = @import("WidgetList.zig");
const WidgetStack = @import("WidgetStack.zig"); const WidgetStack = @import("WidgetStack.zig");
const ed = @import("editor.zig"); const ed = @import("editor.zig");
const home = @import("home.zig"); const home = @import("home.zig");
const LspInfo = @import("lsp_info.zig");
const logview = @import("logview.zig"); const logview = @import("logview.zig");
const filelist_view = @import("filelist_view.zig"); const filelist_view = @import("filelist_view.zig");
@ -61,6 +62,7 @@ panel_height: ?usize = null,
symbols: std.ArrayListUnmanaged(u8) = .empty, symbols: std.ArrayListUnmanaged(u8) = .empty,
symbols_complete: bool = true, symbols_complete: bool = true,
closing_project: bool = false, closing_project: bool = false,
lsp_info: LspInfo,
const FileListType = enum { const FileListType = enum {
diagnostics, diagnostics,
@ -85,6 +87,7 @@ pub fn create(allocator: std.mem.Allocator) CreateError!Widget {
.panes = undefined, .panes = undefined,
.panes_widget = undefined, .panes_widget = undefined,
.buffer_manager = Buffer.Manager.init(allocator), .buffer_manager = Buffer.Manager.init(allocator),
.lsp_info = .init(allocator),
}; };
try self.commands.init(self); try self.commands.init(self);
const w = Widget.to(self); const w = Widget.to(self);
@ -126,6 +129,7 @@ pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
self.symbols.deinit(allocator); self.symbols.deinit(allocator);
self.floating_views.deinit(); self.floating_views.deinit();
self.buffer_manager.deinit(); self.buffer_manager.deinit();
self.lsp_info.deinit();
allocator.destroy(self); allocator.destroy(self);
} }
@ -1773,6 +1777,8 @@ pub fn write_state(self: *Self, writer: *std.Io.Writer) WriteStateError!void {
if (self.widgets.get("tabs")) |tabs_widget| if (self.widgets.get("tabs")) |tabs_widget|
if (tabs_widget.dynamic_cast(@import("status/tabs.zig").TabBar)) |tabs| if (tabs_widget.dynamic_cast(@import("status/tabs.zig").TabBar)) |tabs|
try tabs.write_state(writer); try tabs.write_state(writer);
self.lsp_info.write_state(writer) catch return error.WriteFailed;
} }
fn read_restore_info(self: *Self) !void { fn read_restore_info(self: *Self) !void {
@ -1850,6 +1856,9 @@ fn extract_state(self: *Self, iter: *[]const u8, mode: enum { no_project, with_p
logger.print_err("mainview", "failed to restore tabs: {}", .{e}); logger.print_err("mainview", "failed to restore tabs: {}", .{e});
logger.print("restored tabs ({d} bytes)", .{prev_len - iter.len}); logger.print("restored tabs ({d} bytes)", .{prev_len - iter.len});
self.lsp_info.extract_state(iter) catch |e|
logger.print_err("mainview", "failed to restore LSP info: {}", .{e});
const buffers = try self.buffer_manager.list_unordered(self.allocator); const buffers = try self.buffer_manager.list_unordered(self.allocator);
defer self.allocator.free(buffers); defer self.allocator.free(buffers);
for (buffers) |buffer| if (!buffer.is_ephemeral()) for (buffers) |buffer| if (!buffer.is_ephemeral())