diff --git a/src/keybind/builtin/flow.json b/src/keybind/builtin/flow.json index 30ddc9c..ed576da 100644 --- a/src/keybind/builtin/flow.json +++ b/src/keybind/builtin/flow.json @@ -165,7 +165,6 @@ ["shift+f11", "toggle_highlight_columns"], ["ctrl+f11", "toggle_inspector_view"], ["f12", "goto_definition"], - ["ctrl+.", "completion"], ["f34", "toggle_whitespace_mode"], ["escape", "cancel"], ["enter", "smart_insert_line"], diff --git a/src/tui/editor.zig b/src/tui/editor.zig index d90d6cc..03b5900 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -351,9 +351,6 @@ pub const Editor = struct { diag_hints: usize = 0, completions: std.ArrayListUnmanaged(u8) = .empty, - completion_row: usize = 0, - completion_col: usize = 0, - completion_is_complete: bool = true, enable_auto_save: bool, enable_format_on_save: bool, @@ -5681,13 +5678,10 @@ pub const Editor = struct { } pub fn add_completion(self: *Self, row: usize, col: usize, is_incomplete: bool, msg: tp.message) Result { - if (!(row == self.completion_row and col == self.completion_col)) { - self.completions.clearRetainingCapacity(); - self.completion_row = row; - self.completion_col = col; - } try self.completions.appendSlice(self.allocator, msg.buf); - self.completion_is_complete = is_incomplete; + _ = row; + _ = col; + _ = is_incomplete; } pub fn select(self: *Self, ctx: Context) Result { diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index 288963a..197fbcf 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -827,11 +827,8 @@ const cmds = struct { tp.more, })) return error.InvalidAddDiagnosticArgument; file_path = project_manager.normalize_file_path(file_path); - if (self.get_active_editor()) |editor| { - if (std.mem.eql(u8, file_path, editor.file_path orelse "")) - try editor.add_completion(row, col, is_incomplete, ctx.args); - try tui.open_overlay(@import("mode/overlay/completion_palette.zig").Type); - } + if (self.get_active_editor()) |editor| if (std.mem.eql(u8, file_path, editor.file_path orelse "")) + try editor.add_completion(row, col, is_incomplete, ctx.args); } pub const add_completion_meta: Meta = .{ .arguments = &.{ diff --git a/src/tui/mode/overlay/completion_palette.zig b/src/tui/mode/overlay/completion_palette.zig deleted file mode 100644 index eac3856..0000000 --- a/src/tui/mode/overlay/completion_palette.zig +++ /dev/null @@ -1,175 +0,0 @@ -const std = @import("std"); -const cbor = @import("cbor"); -const tp = @import("thespian"); -const root = @import("root"); -const command = @import("command"); - -const tui = @import("../../tui.zig"); -pub const Type = @import("palette.zig").Create(@This()); -const module_name = @typeName(@This()); -const Widget = @import("../../Widget.zig"); - -pub const label = "Select completion"; -pub const name = "completion"; -pub const description = "completions"; -pub const icon = "󱎸 "; - -pub const Entry = struct { - label: []const u8, - sort_text: []const u8, - cbor: []const u8, -}; - -pub fn load_entries(palette: *Type) !usize { - const editor = tui.get_active_editor() orelse return error.NotFound; - var iter: []const u8 = editor.completions.items; - while (iter.len > 0) { - var cbor_item: []const u8 = undefined; - if (!try cbor.matchValue(&iter, cbor.extract_cbor(&cbor_item))) return error.BadCompletion; - (try palette.entries.addOne()).* = .{ .cbor = cbor_item, .label = undefined, .sort_text = undefined }; - } - - var max_label_len: usize = 0; - for (palette.entries.items) |*item| { - const label_, const sort_text, _ = get_values(item.cbor); - item.label = label_; - item.sort_text = sort_text; - max_label_len = @max(max_label_len, item.label.len); - } - - const less_fn = struct { - fn less_fn(_: void, lhs: Entry, rhs: Entry) bool { - const lhs_str = if (lhs.sort_text.len > 0) lhs.sort_text else lhs.label; - const rhs_str = if (rhs.sort_text.len > 0) rhs.sort_text else rhs.label; - return std.mem.order(u8, lhs_str, rhs_str) == .lt; - } - }.less_fn; - std.mem.sort(Entry, palette.entries.items, {}, less_fn); - - return if (max_label_len > label.len + 3) 0 else label.len + 3 - max_label_len; -} - -pub fn clear_entries(palette: *Type) void { - palette.entries.clearRetainingCapacity(); -} - -pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !void { - var value = std.ArrayList(u8).init(palette.allocator); - defer value.deinit(); - const writer = value.writer(); - try writer.writeAll(entry.cbor); - try cbor.writeValue(writer, matches orelse &[_]usize{}); - try palette.menu.add_item_with_handler(value.items, select); - palette.items += 1; -} - -pub fn on_render_menu(_: *Type, button: *Type.ButtonState, theme: *const Widget.Theme, selected: bool) bool { - var item_cbor: []const u8 = undefined; - var matches_cbor: []const u8 = undefined; - - var iter = button.opts.label; - if (!(cbor.matchValue(&iter, cbor.extract_cbor(&item_cbor)) catch false)) return false; - if (!(cbor.matchValue(&iter, cbor.extract_cbor(&matches_cbor)) catch false)) return false; - - const label_, _, const kind = get_values(item_cbor); - const icon_: []const u8 = kind_icon(@enumFromInt(kind)); - const color: u24 = 0x0; - const indicator: []const u8 = &.{}; - - return tui.render_file_item(&button.plane, label_, icon_, color, indicator, matches_cbor, button.active, selected, button.hover, theme); -} - -fn get_values(item_cbor: []const u8) struct { []const u8, []const u8, u8 } { - var label_: []const u8 = ""; - var sort_text: []const u8 = ""; - var kind: u8 = 0; - _ = cbor.match(item_cbor, .{ - cbor.any, // file_path - cbor.any, // row - cbor.any, // col - cbor.any, // is_incomplete - cbor.extract(&label_), // label - cbor.any, // label_detail - cbor.any, // label_description - cbor.extract(&kind), // kind - cbor.any, // detail - cbor.any, // documentation - cbor.any, // documentation_kind - cbor.extract(&sort_text), // sortText - cbor.any, // insertTextFormat - cbor.any, // textEdit_newText - cbor.any, // insert.begin.row - cbor.any, // insert.begin.col - cbor.any, // insert.end.row - cbor.any, // insert.end.col - cbor.any, // replace.begin.row - cbor.any, // replace.begin.col - cbor.any, // replace.end.row - cbor.any, // replace.end.col - }) catch false; - return .{ label_, sort_text, kind }; -} - -fn select(menu: **Type.MenuState, button: *Type.ButtonState) void { - const label_, _, _ = get_values(button.opts.label); - tp.self_pid().send(.{ "cmd", "exit_overlay_mode" }) catch |e| menu.*.opts.ctx.logger.err(module_name, e); - tp.self_pid().send(.{ "cmd", "insert_chars", .{label_} }) catch |e| menu.*.opts.ctx.logger.err(module_name, e); -} - -const CompletionItemKind = enum(u8) { - Text = 1, - Method = 2, - Function = 3, - Constructor = 4, - Field = 5, - Variable = 6, - Class = 7, - Interface = 8, - Module = 9, - Property = 10, - Unit = 11, - Value = 12, - Enum = 13, - Keyword = 14, - Snippet = 15, - Color = 16, - File = 17, - Reference = 18, - Folder = 19, - EnumMember = 20, - Constant = 21, - Struct = 22, - Event = 23, - Operator = 24, - TypeParameter = 25, -}; - -fn kind_icon(kind: CompletionItemKind) []const u8 { - return switch (kind) { - .Text => "󰊄", - .Method => "", - .Function => "󰊕", - .Constructor => "", - .Field => "", - .Variable => "", - .Class => "", - .Interface => "", - .Module => "", - .Property => "", - .Unit => "󱔁", - .Value => "󱔁", - .Enum => "", - .Keyword => "", - .Snippet => "", - .Color => "", - .File => "", - .Reference => "※", - .Folder => "🗀", - .EnumMember => "", - .Constant => "", - .Struct => "", - .Event => "", - .Operator => "", - .TypeParameter => "", - }; -} diff --git a/src/tui/tui.zig b/src/tui/tui.zig index 7ccdfe4..7b95860 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -1498,18 +1498,7 @@ pub fn render_pointer(self: *renderer.Plane, selected: bool) void { _ = self.print("{s}", .{pointer}) catch {}; } -pub fn render_file_item( - self: *renderer.Plane, - file_path_: []const u8, - icon: []const u8, - color: u24, - indicator: []const u8, - matches_cbor: []const u8, - active: bool, - selected: bool, - hover: bool, - theme_: *const Widget.Theme, -) bool { +pub fn render_file_item_cbor(self: *renderer.Plane, file_item_cbor: []const u8, active: bool, selected: bool, hover: bool, theme_: *const Widget.Theme) bool { const style_base = theme_.editor_widget; const style_label = if (active) theme_.editor_cursor else if (hover or selected) theme_.editor_selection else theme_.editor_widget; const style_hint = if (find_scope_style(theme_, "entity.name")) |sty| sty.style else style_label; @@ -1525,15 +1514,25 @@ pub fn render_file_item( self.set_style(style_hint); render_pointer(self, selected); + var iter = file_item_cbor; + var file_path_: []const u8 = undefined; + var icon: []const u8 = undefined; + var color: u24 = undefined; + if (!(cbor.matchString(&iter, &file_path_) catch false)) @panic("invalid buffer file path"); + if (!(cbor.matchString(&iter, &icon) catch false)) @panic("invalid buffer file type icon"); + if (!(cbor.matchInt(u24, &iter, &color) catch false)) @panic("invalid buffer file type color"); + const icon_width = render_file_icon(self, icon, color); self.set_style(style_label); _ = self.print("{s} ", .{file_path_}) catch {}; + var indicator: []const u8 = undefined; + if (!(cbor.matchString(&iter, &indicator) catch false)) + indicator = ""; self.set_style(style_hint); _ = self.print_aligned_right(0, "{s} ", .{indicator}) catch {}; - var iter = matches_cbor; var index: usize = 0; var len = cbor.decodeArrayHeader(&iter) catch return false; while (len > 0) : (len -= 1) { @@ -1544,23 +1543,6 @@ pub fn render_file_item( return false; } -pub fn render_file_item_cbor(self: *renderer.Plane, file_item_cbor: []const u8, active: bool, selected: bool, hover: bool, theme_: *const Widget.Theme) bool { - var iter = file_item_cbor; - var file_path_: []const u8 = undefined; - var icon: []const u8 = undefined; - var color: u24 = undefined; - var indicator: []const u8 = undefined; - var matches_cbor: []const u8 = undefined; - - if (!(cbor.matchString(&iter, &file_path_) catch false)) @panic("invalid buffer file path"); - if (!(cbor.matchString(&iter, &icon) catch false)) @panic("invalid buffer file type icon"); - if (!(cbor.matchInt(u24, &iter, &color) catch false)) @panic("invalid buffer file type color"); - if (!(cbor.matchString(&iter, &indicator) catch false)) indicator = ""; - - if (!(cbor.matchValue(&iter, cbor.extract_cbor(&matches_cbor)) catch false)) @panic("invalid matches cbor"); - return render_file_item(self, file_path_, icon, color, indicator, matches_cbor, active, selected, hover, theme_); -} - fn get_or_create_theme_file(self: *Self, allocator: std.mem.Allocator) ![]const u8 { const theme_name = self.theme_.name; if (root.read_theme(allocator, theme_name)) |content| {