Compare commits
4 commits
90aba421a2
...
3dcdb64f83
| Author | SHA1 | Date | |
|---|---|---|---|
| 3dcdb64f83 | |||
| fe2ea13024 | |||
| 4f737e4019 | |||
| 89dc5cce54 |
5 changed files with 138 additions and 7 deletions
|
|
@ -275,11 +275,11 @@ pub fn rev_parse(context_: usize, rev: []const u8, file_path: []const u8) Error!
|
||||||
|
|
||||||
pub fn cat_file(context_: usize, object: []const u8) Error!void {
|
pub fn cat_file(context_: usize, object: []const u8) Error!void {
|
||||||
const tag = @src().fn_name;
|
const tag = @src().fn_name;
|
||||||
try git_err(context_, .{ "cat-file", "-p", object }, struct {
|
try git(context_, .{ "cat-file", "-p", object }, struct {
|
||||||
fn result(context: usize, parent: tp.pid_ref, output: []const u8) void {
|
fn result(context: usize, parent: tp.pid_ref, output: []const u8) void {
|
||||||
parent.send(.{ module_name, context, tag, output }) catch {};
|
parent.send(.{ module_name, context, tag, output }) catch {};
|
||||||
}
|
}
|
||||||
}.result, log_err, exit_null(tag));
|
}.result, exit_null(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn git_line_output(context_: usize, comptime tag: []const u8, cmd: anytype) Error!void {
|
fn git_line_output(context_: usize, comptime tag: []const u8, cmd: anytype) Error!void {
|
||||||
|
|
|
||||||
|
|
@ -542,9 +542,8 @@ pub const Editor = struct {
|
||||||
tp.extract_cbor(&cursels_cbor),
|
tp.extract_cbor(&cursels_cbor),
|
||||||
}))
|
}))
|
||||||
return error.RestoreStateMatch;
|
return error.RestoreStateMatch;
|
||||||
self.insert_triggers.deinit(self.allocator);
|
self.clear_event_triggers();
|
||||||
self.insert_triggers = .fromOwnedSlice(insert_triggers);
|
self.insert_triggers = .fromOwnedSlice(insert_triggers);
|
||||||
self.delete_triggers.deinit(self.allocator);
|
|
||||||
self.delete_triggers = .fromOwnedSlice(delete_triggers);
|
self.delete_triggers = .fromOwnedSlice(delete_triggers);
|
||||||
self.refresh_tab_width();
|
self.refresh_tab_width();
|
||||||
if (op == .open_file)
|
if (op == .open_file)
|
||||||
|
|
@ -614,8 +613,7 @@ pub const Editor = struct {
|
||||||
for (self.diagnostics.items) |*d| d.deinit(self.allocator);
|
for (self.diagnostics.items) |*d| d.deinit(self.allocator);
|
||||||
self.diagnostics.deinit(self.allocator);
|
self.diagnostics.deinit(self.allocator);
|
||||||
self.completions.deinit(self.allocator);
|
self.completions.deinit(self.allocator);
|
||||||
self.insert_triggers.deinit(self.allocator);
|
self.clear_event_triggers();
|
||||||
self.delete_triggers.deinit(self.allocator);
|
|
||||||
if (self.syntax) |syn| syn.destroy(tui.query_cache());
|
if (self.syntax) |syn| syn.destroy(tui.query_cache());
|
||||||
self.cancel_all_tabstops();
|
self.cancel_all_tabstops();
|
||||||
self.cursels.deinit(self.allocator);
|
self.cursels.deinit(self.allocator);
|
||||||
|
|
@ -6234,9 +6232,31 @@ pub const Editor = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clear_event_triggers(self: *Self) void {
|
||||||
|
self.insert_triggers.deinit(self.allocator);
|
||||||
|
self.delete_triggers.deinit(self.allocator);
|
||||||
|
self.insert_triggers = .empty;
|
||||||
|
self.delete_triggers = .empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_completion_triggers(self: *Self) void {
|
||||||
|
self.clear_event_triggers();
|
||||||
|
if (self.file_type) |ft| if (ft.language_server) |ls| if (ls.len > 0) {
|
||||||
|
const lsp_arg0 = ls[0];
|
||||||
|
const info = (tui.mainview() orelse return).lsp_info.table.get(lsp_arg0) orelse return;
|
||||||
|
self.add_completion_triggers(info.trigger_characters.items);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn add_default_symbol_triggers(self: *Self) void {
|
fn add_default_symbol_triggers(self: *Self) void {
|
||||||
|
const chars: []const []const u8 = &.{"."};
|
||||||
|
self.add_completion_triggers(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_completion_triggers(self: *Self, triggers: []const []const u8) void {
|
||||||
const id = command.get_name_id("completion");
|
const id = command.get_name_id("completion");
|
||||||
self.add_symbol_trigger('.', id, .insert) catch {};
|
for (triggers) |char| if (char.len > 0)
|
||||||
|
self.add_symbol_trigger(char[0], id, .insert) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_symbol_trigger(self: *Self, char: u8, command_: command.ID, event: TriggerEvent) error{OutOfMemory}!void {
|
pub fn add_symbol_trigger(self: *Self, char: u8, command_: command.ID, event: TriggerEvent) error{OutOfMemory}!void {
|
||||||
|
|
|
||||||
93
src/tui/lsp_info.zig
Normal file
93
src/tui/lsp_info.zig
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
table: Table,
|
||||||
|
|
||||||
|
const Table = std.StringHashMapUnmanaged(Info);
|
||||||
|
|
||||||
|
pub const Info = struct {
|
||||||
|
trigger_characters: std.ArrayList([]const u8) = .empty,
|
||||||
|
};
|
||||||
|
|
||||||
|
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 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");
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -1985,3 +1994,9 @@ pub fn vcs_content_update(self: *Self, m: tp.message) void {
|
||||||
editor.vcs_content_update() catch {};
|
editor.vcs_content_update() catch {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn trigger_characters_update(self: *Self, m: tp.message) void {
|
||||||
|
self.lsp_info.add_from_event(m.buf) catch return;
|
||||||
|
const editor = self.get_active_editor() orelse return;
|
||||||
|
editor.update_completion_triggers();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -533,6 +533,9 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void {
|
||||||
if (try m.match(.{ "PRJ", "vcs_content", tp.more }))
|
if (try m.match(.{ "PRJ", "vcs_content", tp.more }))
|
||||||
return if (mainview()) |mv| mv.vcs_content_update(m);
|
return if (mainview()) |mv| mv.vcs_content_update(m);
|
||||||
|
|
||||||
|
if (try m.match(.{ "PRJ", "triggerCharacters", tp.more }))
|
||||||
|
return if (mainview()) |mv| mv.trigger_characters_update(m);
|
||||||
|
|
||||||
if (try m.match(.{ "PRJ", tp.more })) // drop late project manager query responses
|
if (try m.match(.{ "PRJ", tp.more })) // drop late project manager query responses
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue