Compare commits

...

8 commits

5 changed files with 60 additions and 43 deletions

View file

@ -1250,7 +1250,7 @@ pub fn completion(self: *Self, from: tp.pid_ref, file_path: []const u8, row: usi
pub fn receive(self_: @This(), response: tp.message) (CompletionError || cbor.Error)!void {
var result: []const u8 = undefined;
if (try cbor.match(response.buf, .{ "child", tp.string, "result", tp.null_ })) {
try send_content_msg_empty(self_.from.ref(), "hover", self_.file_path, self_.row, self_.col);
send_completion_done(self_.from.ref(), self_.file_path, self_.row, self_.col);
} else if (try cbor.match(response.buf, .{ "child", tp.string, "result", tp.array })) {
if (try cbor.match(response.buf, .{ tp.any, tp.any, tp.any, tp.extract_cbor(&result) }))
try send_completion_items(self_.from.ref(), self_.file_path, self_.row, self_.col, result, false);
@ -1343,9 +1343,7 @@ fn send_completion_list(to: tp.pid_ref, file_path: []const u8, row: usize, col:
return if (items.len > 0)
send_completion_items(to, file_path, row, col, items, is_incomplete)
else
to.send(.{ "cmd", "add_completion_done", .{ file_path, row, col } }) catch |e| {
std.log.err("send add_completion_done failed: {t}", .{e});
};
send_completion_done(to, file_path, row, col);
}
pub const CompletionItemError = error{
@ -1361,6 +1359,10 @@ fn send_completion_items(to: tp.pid_ref, file_path: []const u8, row: usize, col:
if (!(try cbor.matchValue(&iter, cbor.extract_cbor(&item)))) return error.InvalidCompletionItem;
try send_completion_item(to, file_path, row, col, item, if (len > 1) true else is_incomplete);
}
send_completion_done(to, file_path, row, col);
}
fn send_completion_done(to: tp.pid_ref, file_path: []const u8, row: usize, col: usize) void {
return to.send(.{ "cmd", "add_completion_done", .{ file_path, row, col } }) catch |e| {
std.log.err("send add_completion_done failed: {t}", .{e});
};

View file

@ -1508,9 +1508,6 @@ pub fn refresh_from_file(self: *Self) LoadFromFileError!void {
}
pub fn store_to_string_cached(self: *Self, root: *const Node, eol_mode: EolMode) [:0]const u8 {
std.log.debug("BEGIN store_to_string_cached 0x{x}", .{root.to_ref()});
defer std.log.debug("END store_to_string_cached 0x{x}", .{root.to_ref()});
if (get_cached_text(self.cache, root.to_ref(), eol_mode)) |text| return text;
var s: std.Io.Writer.Allocating = std.Io.Writer.Allocating.initCapacity(self.external_allocator, root.weights_sum().len) catch @panic("OOM store_to_string_cached");
root.store(&s.writer, eol_mode) catch @panic("store_to_string_cached");
@ -1519,9 +1516,6 @@ pub fn store_to_string_cached(self: *Self, root: *const Node, eol_mode: EolMode)
pub fn store_last_save_to_string_cached(self: *Self, eol_mode: EolMode) ?[]const u8 {
const root = self.last_save orelse return null;
std.log.debug("BEGIN store_last_save_to_string_cached 0x{x}", .{root.to_ref()});
defer std.log.debug("END store_last_save_to_string_cached 0x{x}", .{root.to_ref()});
if (get_cached_text(self.last_save_cache, root.to_ref(), eol_mode)) |text| return text;
var s: std.Io.Writer.Allocating = std.Io.Writer.Allocating.initCapacity(self.external_allocator, root.weights_sum().len) catch @panic("OOM store_last_save_to_string_cached");
root.store(&s.writer, eol_mode) catch @panic("store_last_save_to_string_cached");
@ -1530,20 +1524,12 @@ pub fn store_last_save_to_string_cached(self: *Self, eol_mode: EolMode) ?[]const
fn get_cached_text(cache_: ?StringCache, ref: Node.Ref, eol_mode: EolMode) ?[:0]const u8 {
const cache = cache_ orelse return null;
return if (cache.ref == ref and cache.eol_mode == eol_mode) blk: {
std.log.debug("fetched string cache 0x{x}", .{cache.ref});
break :blk cache.text;
} else blk: {
std.log.debug("cache miss for 0x{x} (was 0x{x})", .{ ref, cache.ref });
break :blk null;
};
return if (cache.ref == ref and cache.eol_mode == eol_mode) cache.text else null;
}
fn store_cached_text(self: *Self, cache: *?StringCache, ref: Node.Ref, eol_mode: EolMode, text: [:0]const u8) [:0]const u8 {
if (cache.*) |*c| {
std.log.debug("0x{x} updated string cache 0x{x} -> 0x{x}", .{ @intFromPtr(self), c.ref, ref });
if (cache.*) |*c|
c.deinit(self.external_allocator);
} else std.log.debug("0x{x} stored string cache 0x{x}", .{ @intFromPtr(self), ref });
cache.* = .{
.ref = ref,
.eol_mode = eol_mode,
@ -1559,7 +1545,6 @@ const StringCache = struct {
code_folded: ?[:0]const u8 = null,
fn deinit(self: *@This(), allocator: std.mem.Allocator) void {
std.log.debug("cleared string cache 0x{x}", .{self.ref});
allocator.free(self.text);
if (self.code_folded) |text| allocator.free(text);
}

View file

@ -440,9 +440,15 @@ pub const Editor = struct {
is_complete: bool = true,
const empty: @This() = .{};
const pending: @This() = .empty;
const done: ?@This() = null;
fn pending(row: usize, col: usize) @This() {
return .{
.row = row,
.col = col,
};
}
fn deinit(self: *@This(), allocator: std.mem.Allocator) void {
self.data.deinit(allocator);
self.* = .empty;
@ -3559,7 +3565,7 @@ pub const Editor = struct {
try move_cursor_right(root, cursor, metrics);
}
fn move_cursor_word_left(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void {
pub fn move_cursor_word_left(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void {
try move_cursor_left(root, cursor, metrics);
move_cursor_left_until(root, cursor, is_word_boundary_left, metrics);
}
@ -4202,8 +4208,13 @@ pub const Editor = struct {
root = try self.indent_cursor(root, sel.end, true, allocator);
if (sel_from_start)
sel_.begin.col = 0;
cursel.cursor.clamp_to_buffer(root, self.metrics);
return root;
} else return try self.indent_cursor(root_, cursel.cursor, self.cursels.items.len > 1, allocator);
} else {
const root = try self.indent_cursor(root_, cursel.cursor, self.cursels.items.len > 1, allocator);
cursel.cursor.clamp_to_buffer(root, self.metrics);
return root;
}
}
pub fn indent(self: *Self, ctx: Context) Result {
@ -6285,10 +6296,14 @@ pub const Editor = struct {
pub fn completion(self: *Self, _: Context) Result {
const mv = tui.mainview() orelse return;
if (self.completions_request) |_|
self.completions_refresh_pending = true
else
self.completions_request = .pending;
const cursor = self.get_primary().cursor;
if (self.completions_request) |request| {
if (request.row != cursor.row or request.col != cursor.col)
self.completions_refresh_pending = true;
return;
} else {
self.completions_request = .pending(cursor.row, cursor.col);
}
if (!mv.is_any_panel_view_showing())
self.clamp_offset(mv.get_panel_height());
return self.pm_with_primary_cursor_pos(project_manager.completion);

View file

@ -151,6 +151,9 @@ fn maybe_update_query(self: *Type, cursor: Buffer.Cursor) error{OutOfMemory}!voi
if (!std.mem.eql(u8, query, last))
try update_query_text(self, cursor);
} else try update_query_text(self, cursor);
if (self.match_count == 0)
tp.self_pid().send(.{ "cmd", "completion" }) catch |e| self.logger.err(module_name, e);
}
fn update_query_text(self: *Type, cursor: ed.Cursor) error{OutOfMemory}!void {
@ -298,15 +301,30 @@ const Range = struct { start: Position, end: Position };
const Position = struct { line: usize, character: usize };
pub fn get_query_selection(editor: *ed.Editor, values: Values) ?Buffer.Selection {
return get_replacement_selection(editor, values.insert, values.replace);
return get_replacement_selection(editor, values.insert, values.replace, null);
}
fn get_replacement_selection(editor: *ed.Editor, insert_: ?Buffer.Selection, replace_: ?Buffer.Selection) Buffer.Selection {
fn get_replacement_selection(editor: *ed.Editor, insert_: ?Buffer.Selection, replace_: ?Buffer.Selection, query: ?Buffer.Selection) Buffer.Selection {
const pos = switch (tui.config().completion_insert_mode) {
.replace => replace_ orelse insert_ orelse return ed.Selection.from_cursor(&editor.get_primary().cursor),
.insert => insert_ orelse replace_ orelse return ed.Selection.from_cursor(&editor.get_primary().cursor),
.replace => replace_ orelse insert_,
.insert => insert_ orelse replace_,
};
var sel = if (pos) |p|
p.from_pos(editor.buf_root() catch return ed.Selection.from_cursor(&editor.get_primary().cursor), editor.metrics)
else blk: {
if (query) |sel| break :blk sel;
var cursel = editor.get_primary().*;
var sel = ed.Selection.from_cursor(&cursel.cursor);
if (cursel.cursor.col == 0) break :blk sel;
const root_ = editor.buf_root() catch break :blk sel;
ed.Editor.move_cursor_word_left(root_, &sel.begin, editor.metrics) catch break :blk sel;
if (tui.config().completion_insert_mode == .replace) {
sel.end = sel.begin;
ed.Editor.move_cursor_word_right(root_, &sel.end, editor.metrics) catch break :blk sel;
}
break :blk sel;
};
var sel = pos.from_pos(editor.buf_root() catch return ed.Selection.from_cursor(&editor.get_primary().cursor), editor.metrics);
sel.normalize();
const cursor = editor.get_primary().cursor;
return switch (tui.config().completion_insert_mode) {
@ -315,8 +333,8 @@ fn get_replacement_selection(editor: *ed.Editor, insert_: ?Buffer.Selection, rep
};
}
fn get_insert_selection(editor: *ed.Editor, values: Values) Buffer.Selection {
return get_replacement_selection(editor, values.insert, values.replace);
fn get_insert_selection(editor: *ed.Editor, values: Values, query: ?Buffer.Selection) Buffer.Selection {
return get_replacement_selection(editor, values.insert, values.replace, query);
}
pub fn complete(self: *Type, _: ?*Type.ButtonType) !void {
@ -326,7 +344,7 @@ pub fn complete(self: *Type, _: ?*Type.ButtonType) !void {
fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Pos) void {
const self = menu.*.opts.ctx;
const values = get_values(button.opts.label);
const sel = get_insert_selection(self.value.editor, values);
const sel = get_insert_selection(self.value.editor, values, self.value.query);
const text = if (values.insertText.len > 0)
values.insertText
else if (values.textEdit_newText.len > 0)
@ -372,11 +390,6 @@ const cmds = struct {
const Result = command.Result;
pub fn update_completion(self: *Type, _: Ctx) Result {
if (self.value.editor.completions.data.items.len == 0) {
tp.self_pid().send(.{ "cmd", "palette_menu_cancel" }) catch |e| self.logger.err(module_name, e);
return;
}
clear_entries(self);
self.longest_hint = try load_entries(self);
try update_query_text(self, self.value.editor.get_primary().cursor);

View file

@ -328,16 +328,18 @@ pub fn Create(options: type) type {
};
var matches: std.ArrayList(Match) = .empty;
var match_count: usize = 0;
for (self.entries.items) |*entry| {
const match = searcher.scoreMatches(entry.label, query);
if (match.score) |_| match_count += 1;
(try matches.addOne(self.allocator)).* = .{
.entry = entry,
.score = match.score orelse 0,
.matches = try self.allocator.dupe(usize, match.matches),
};
}
if (matches.items.len == 0) return 0;
if (matches.items.len == 0) return match_count;
const less_fn = struct {
fn less_fn(_: void, lhs: Match, rhs: Match) bool {
@ -358,7 +360,7 @@ pub fn Create(options: type) type {
if (self.items < self.view_rows)
try options.add_menu_entry(self, match.entry, match.matches);
}
return matches.items.len;
return match_count;
}
fn cmd(_: *Self, name_: []const u8, ctx: command.Context) tp.result {