Compare commits
14 commits
bdd1e1dd1c
...
35563822ba
| Author | SHA1 | Date | |
|---|---|---|---|
| 35563822ba | |||
| 4a1b206d2b | |||
| ebe59eb0f7 | |||
| 269815dd21 | |||
| bc3f431dee | |||
| f0bf122f22 | |||
| aed77322f3 | |||
| fd798e5775 | |||
| d3b2577338 | |||
| fa58e09a18 | |||
| 1c2e1ae494 | |||
| c1ae1fe25f | |||
| 6280d7d0b4 | |||
| 69f5448f03 |
9 changed files with 277 additions and 51 deletions
|
|
@ -24,6 +24,7 @@ inline_vcs_blame_alignment: Alignment = .right,
|
|||
animation_min_lag: usize = 0, //milliseconds
|
||||
animation_max_lag: usize = 50, //milliseconds
|
||||
hover_time_ms: usize = 500, //milliseconds
|
||||
hover_info_mode: HoverInfoMode = .box,
|
||||
input_idle_time_ms: usize = 100, //milliseconds
|
||||
idle_actions: []const IdleAction = &default_actions,
|
||||
idle_commands: ?[]const []const u8 = null, // a list of simple commands
|
||||
|
|
@ -64,6 +65,7 @@ start_debugger_on_crash: bool = false,
|
|||
completion_trigger: CompletionTrigger = .automatic,
|
||||
completion_style: CompletionStyle = .dropdown,
|
||||
completion_insert_mode: CompletionInsertMode = .insert,
|
||||
completion_info_mode: CompletionInfoMode = .box,
|
||||
|
||||
widget_style: WidgetStyle = .compact,
|
||||
palette_style: WidgetStyle = .bars_top_bottom,
|
||||
|
|
@ -74,6 +76,7 @@ pane_left_style: WidgetStyle = .bar_right,
|
|||
pane_right_style: WidgetStyle = .bar_left,
|
||||
pane_style: PaneStyle = .panel,
|
||||
hint_window_style: WidgetStyle = .thick_boxed,
|
||||
info_box_style: WidgetStyle = .bar_left_spacious,
|
||||
|
||||
centered_view: bool = false,
|
||||
centered_view_width: usize = 145,
|
||||
|
|
@ -119,6 +122,7 @@ pub const WidgetType = enum {
|
|||
pane_left,
|
||||
pane_right,
|
||||
hint_window,
|
||||
info_box,
|
||||
dropdown,
|
||||
};
|
||||
|
||||
|
|
@ -135,6 +139,8 @@ pub const WidgetStyle = enum {
|
|||
single_double_top_bottom_boxed,
|
||||
single_double_left_right_boxed,
|
||||
boxed,
|
||||
bar_left_spacious,
|
||||
bar_right_spacious,
|
||||
spacious,
|
||||
compact,
|
||||
};
|
||||
|
|
@ -204,6 +210,17 @@ pub const CompletionInsertMode = enum {
|
|||
replace,
|
||||
};
|
||||
|
||||
pub const CompletionInfoMode = enum {
|
||||
none,
|
||||
box,
|
||||
panel,
|
||||
};
|
||||
|
||||
pub const HoverInfoMode = enum {
|
||||
box,
|
||||
panel,
|
||||
};
|
||||
|
||||
pub const Alignment = enum {
|
||||
left,
|
||||
right,
|
||||
|
|
|
|||
|
|
@ -396,7 +396,9 @@
|
|||
"overlay/dropdown-noninvasive": {
|
||||
"inherit": "normal",
|
||||
"press": [
|
||||
["ctrl+space", "toggle_completion_info_mode"],
|
||||
["alt+f9", "dropdown_next_widget_style"],
|
||||
["shift+alt+f9", "info_box_next_widget_style"],
|
||||
["ctrl+p", "palette_menu_up"],
|
||||
["ctrl+n", "palette_menu_down"],
|
||||
["escape", "palette_menu_cancel"],
|
||||
|
|
@ -409,7 +411,9 @@
|
|||
"overlay/dropdown": {
|
||||
"inherit": "normal",
|
||||
"press": [
|
||||
["ctrl+space", "toggle_completion_info_mode"],
|
||||
["alt+f9", "dropdown_next_widget_style"],
|
||||
["shift+alt+f9", "info_box_next_widget_style"],
|
||||
["ctrl+p", "palette_menu_up"],
|
||||
["ctrl+n", "palette_menu_down"],
|
||||
["escape", "palette_menu_cancel"],
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ pub const Border = struct {
|
|||
const @"thick box (half)": Border = .{ .nw = "▛", .n = "▀", .ne = "▜", .e = "▐", .se = "▟", .s = "▄", .sw = "▙", .w = "▌", .nib = "▌", .nie = "▐", .sib = "▌", .sie = "▐" };
|
||||
const @"thick box (sextant)": Border = .{ .nw = "🬕", .n = "🬂", .ne = "🬨", .e = "▐", .se = "🬷", .s = "🬭", .sw = "🬲", .w = "▌", .nib = "▌", .nie = "▐", .sib = "▌", .sie = "▐" };
|
||||
const @"thick box (octant)": Border = .{ .nw = "", .n = "🮂", .ne = "", .e = "▐", .se = "", .s = "▂", .sw = "", .w = "▌", .nib = "▌", .nie = "▐", .sib = "▌", .sie = "▐" };
|
||||
const @"thick bar left (octant)": Border = .{ .nw = "▌", .n = " ", .ne = " ", .e = " ", .se = " ", .s = " ", .sw = "▌", .w = "▌", .nib = " ", .nie = " ", .sib = " ", .sie = " " };
|
||||
const @"thick bar right (octant)": Border = .{ .nw = " ", .n = " ", .ne = "▐", .e = "▐", .se = "▐", .s = " ", .sw = " ", .w = " ", .nib = " ", .nie = " ", .sib = " ", .sie = " " };
|
||||
const @"extra thick box": Border = .{ .nw = "█", .n = "▀", .ne = "█", .e = "█", .se = "█", .s = "▄", .sw = "█", .w = "█", .nib = "▌", .nie = "▐", .sib = "▌", .sie = "▐" };
|
||||
const @"round thick box": Border = .{ .nw = "█", .n = "▀", .ne = "█", .e = "█", .se = "█", .s = "▄", .sw = "█", .w = "█", .nib = "▌", .nie = "▐", .sib = "▌", .sie = "▐" };
|
||||
};
|
||||
|
|
@ -132,6 +134,16 @@ const bar_right: @This() = .{
|
|||
.border = Border.@"thick box (octant)",
|
||||
};
|
||||
|
||||
const bar_left_spacious: @This() = .{
|
||||
.padding = Margin.@"1/2",
|
||||
.border = Border.@"thick bar left (octant)",
|
||||
};
|
||||
|
||||
const bar_right_spacious: @This() = .{
|
||||
.padding = Margin.@"1/2",
|
||||
.border = Border.@"thick bar right (octant)",
|
||||
};
|
||||
|
||||
pub fn from_tag(tag: WidgetStyle) *const @This() {
|
||||
return switch (tag) {
|
||||
.compact => &compact,
|
||||
|
|
@ -148,6 +160,8 @@ pub fn from_tag(tag: WidgetStyle) *const @This() {
|
|||
.bars_left_right => &bars_left_right,
|
||||
.bar_left => &bar_left,
|
||||
.bar_right => &bar_right,
|
||||
.bar_left_spacious => &bar_left_spacious,
|
||||
.bar_right_spacious => &bar_right_spacious,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -169,6 +183,7 @@ pub fn theme_style_from_type(style_type: WidgetType, theme: *const Theme) Theme.
|
|||
.editor => .{ .fg = theme.editor_widget.bg, .bg = theme.editor.bg },
|
||||
},
|
||||
.hint_window => .{ .fg = theme.editor_widget_border.fg, .bg = theme.editor_widget.bg },
|
||||
.info_box => .{ .fg = theme.editor_widget_border.fg, .bg = theme.editor_widget.bg },
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ const WidgetList = @import("WidgetList.zig");
|
|||
const tui = @import("tui.zig");
|
||||
const IndentMode = @import("config").IndentMode;
|
||||
const WhitespaceMode = @import("config").WhitespaceMode;
|
||||
const info_view = @import("info_view.zig");
|
||||
|
||||
pub const Cursor = Buffer.Cursor;
|
||||
pub const View = Buffer.View;
|
||||
|
|
@ -414,6 +415,7 @@ pub const Editor = struct {
|
|||
diag_warnings: usize = 0,
|
||||
diag_info: usize = 0,
|
||||
diag_hints: usize = 0,
|
||||
info_box: ?Widget = null,
|
||||
|
||||
completions: CompletionState = .empty,
|
||||
completions_request: ?CompletionState = .done,
|
||||
|
|
@ -643,6 +645,7 @@ pub const Editor = struct {
|
|||
var meta: std.Io.Writer.Allocating = .init(self.allocator);
|
||||
defer meta.deinit();
|
||||
if (self.buffer) |_| self.write_state(&meta.writer) catch {};
|
||||
if (self.info_box) |*w| w.deinit(self.allocator);
|
||||
for (self.diagnostics.items) |*d| d.deinit(self.allocator);
|
||||
self.diagnostics.deinit(self.allocator);
|
||||
self.completions.deinit(self.allocator);
|
||||
|
|
@ -1294,6 +1297,7 @@ pub const Editor = struct {
|
|||
self.render_blame(theme, hl_row, ctx_.cell_map) catch {};
|
||||
self.render_column_highlights() catch {};
|
||||
self.render_cursors(theme, ctx_.cell_map, focused) catch {};
|
||||
if (self.info_box) |w| _ = w.render(theme);
|
||||
}
|
||||
|
||||
fn render_cursors(self: *Self, theme: *const Widget.Theme, cell_map: CellMap, focused: bool) !void {
|
||||
|
|
@ -1919,8 +1923,10 @@ pub const Editor = struct {
|
|||
self.last.cursels = self.cursels.items.len;
|
||||
}
|
||||
|
||||
if (lines != self.last.lines or !primary.cursor.eql(self.last.primary.cursor))
|
||||
if (lines != self.last.lines or !primary.cursor.eql(self.last.primary.cursor)) {
|
||||
self.clear_info_box();
|
||||
try self.send_editor_pos(lines, &primary.cursor);
|
||||
}
|
||||
|
||||
if (primary.selection) |primary_selection_| {
|
||||
var primary_selection = primary_selection_;
|
||||
|
|
@ -1934,8 +1940,10 @@ pub const Editor = struct {
|
|||
} else if (self.last.primary.selection) |_|
|
||||
try self.send_editor_selection_removed();
|
||||
|
||||
if (lines != self.last.lines or !self.view.eql(self.last.view))
|
||||
if (lines != self.last.lines or !self.view.eql(self.last.view)) {
|
||||
self.clear_info_box();
|
||||
try self.send_editor_view(lines, self.view);
|
||||
}
|
||||
|
||||
self.last.view = self.view;
|
||||
self.last.lines = lines;
|
||||
|
|
@ -2044,6 +2052,56 @@ pub const Editor = struct {
|
|||
_ = try self.handlers.msg(.{ "E", "eol_mode", eol_mode, utf8_sanitized, indent_mode });
|
||||
}
|
||||
|
||||
fn clear_info_box(self: *Self) void {
|
||||
if (self.info_box) |*w| {
|
||||
w.deinit(self.allocator);
|
||||
self.info_box = null;
|
||||
self.clear_matches();
|
||||
}
|
||||
}
|
||||
|
||||
const info_box_widget_type: Widget.Type = .info_box;
|
||||
fn show_info_box(self: *Self) !*info_view {
|
||||
const w = self.info_box orelse blk: {
|
||||
self.info_box = try info_view.create_widget_type(self.allocator, self.plane, info_box_widget_type);
|
||||
break :blk self.info_box.?;
|
||||
};
|
||||
const info_ = if (w.get(@typeName(info_view))) |w_| w_.dynamic_cast(info_view) orelse null else null;
|
||||
const info = info_ orelse @panic("Editor.show_info_box");
|
||||
return info;
|
||||
}
|
||||
|
||||
fn place_info_box(self: *Self, cursor: Cursor) void {
|
||||
const w = self.info_box orelse return;
|
||||
const info = self.show_info_box() catch return;
|
||||
const padding = tui.get_widget_style(info_box_widget_type).padding;
|
||||
const dim = info.content_size();
|
||||
const pos = self.screen_cursor(&cursor) orelse {
|
||||
self.clear_info_box();
|
||||
return;
|
||||
};
|
||||
const y, const x = self.plane.rel_yx_to_abs(@intCast(pos.row), @intCast(pos.col));
|
||||
|
||||
w.resize(.{
|
||||
.h = dim.rows + padding.top + padding.bottom,
|
||||
.w = dim.cols + padding.left + padding.right + 3,
|
||||
.y = @intCast(y + 1),
|
||||
.x = @intCast(x + 1),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_hover_content(self: *Self, range: Match, content: []const u8) !void {
|
||||
self.add_hover_highlight(range);
|
||||
if (content.len == 0) {
|
||||
self.clear_info_box();
|
||||
return;
|
||||
}
|
||||
const info = try self.show_info_box();
|
||||
info.clear();
|
||||
try info.append_content(content);
|
||||
self.place_info_box(range.begin);
|
||||
}
|
||||
|
||||
fn clamp_abs_offset(self: *Self, abs: bool, offset: usize) void {
|
||||
var dest: View = self.view;
|
||||
dest.clamp_offset(&self.get_primary().cursor, abs, offset);
|
||||
|
|
@ -4464,6 +4522,7 @@ pub const Editor = struct {
|
|||
pub const move_buffer_end_meta: Meta = .{ .description = "Move cursor to end of file" };
|
||||
|
||||
pub fn cancel(self: *Self, _: Context) Result {
|
||||
self.clear_info_box();
|
||||
self.cancel_all_tabstops();
|
||||
self.cancel_all_selections();
|
||||
self.cancel_all_matches();
|
||||
|
|
|
|||
|
|
@ -14,9 +14,13 @@ plane: Plane,
|
|||
view_rows: usize = 0,
|
||||
lines: std.ArrayList([]const u8),
|
||||
|
||||
const widget_type: Widget.Type = .panel;
|
||||
const default_widget_type: Widget.Type = .panel;
|
||||
|
||||
pub fn create(allocator: Allocator, parent: Plane) !Widget {
|
||||
return create_widget_type(allocator, parent, default_widget_type);
|
||||
}
|
||||
|
||||
pub fn create_widget_type(allocator: Allocator, parent: Plane, widget_type: Widget.Type) !Widget {
|
||||
const self = try allocator.create(Self);
|
||||
errdefer allocator.destroy(self);
|
||||
const container = try WidgetList.createHStyled(allocator, parent, "panel_frame", .dynamic, widget_type);
|
||||
|
|
@ -51,8 +55,9 @@ pub fn handle_resize(self: *Self, pos: Widget.Box) void {
|
|||
|
||||
pub fn append_content(self: *Self, content: []const u8) !void {
|
||||
var iter = std.mem.splitScalar(u8, content, '\n');
|
||||
while (iter.next()) |line|
|
||||
while (iter.next()) |line| if (line.len > 0) {
|
||||
(try self.lines.addOne(self.allocator)).* = try self.allocator.dupe(u8, line);
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set_content(self: *Self, content: []const u8) !void {
|
||||
|
|
@ -60,6 +65,12 @@ pub fn set_content(self: *Self, content: []const u8) !void {
|
|||
return self.append_content(content);
|
||||
}
|
||||
|
||||
pub fn content_size(self: *Self) struct { rows: usize, cols: usize } {
|
||||
var cols: usize = 0;
|
||||
for (self.lines.items) |line| cols = @max(cols, line.len);
|
||||
return .{ .rows = self.lines.items.len, .cols = cols };
|
||||
}
|
||||
|
||||
pub fn render(self: *Self, theme: *const Widget.Theme) bool {
|
||||
self.plane.set_base_style(theme.panel);
|
||||
self.plane.erase();
|
||||
|
|
|
|||
|
|
@ -175,12 +175,14 @@ pub fn receive(self: *Self, from_: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
|||
if (self.get_editor_for_file(path)) |editor| editor.done_highlight_reference();
|
||||
return true;
|
||||
} else if (try m.match(.{ "hover", tp.extract(&path), tp.string, tp.extract(&lines), tp.extract(&begin_line), tp.extract(&begin_pos), tp.extract(&end_line), tp.extract(&end_pos) })) {
|
||||
try self.set_info_content(lines, .replace);
|
||||
if (self.get_editor_for_file(path)) |editor|
|
||||
editor.add_hover_highlight(.{
|
||||
switch (tui.config().hover_info_mode) {
|
||||
.panel => self.set_info_content(lines, .replace) catch {},
|
||||
.box => if (self.get_editor_for_file(path)) |editor|
|
||||
editor.set_hover_content(.{
|
||||
.begin = .{ .row = begin_line, .col = begin_pos },
|
||||
.end = .{ .row = end_line, .col = end_pos },
|
||||
});
|
||||
}, lines) catch |e| return tp.exit_error(e, @errorReturnTrace()),
|
||||
}
|
||||
return true;
|
||||
} else if (try m.match(.{ "navigate_complete", tp.extract(&path), tp.extract(&goto_args), tp.extract(&line), tp.extract(&column) })) {
|
||||
cmds.navigate_complete(self, null, path, goto_args, line, column, null) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
|
|
@ -339,6 +341,10 @@ fn close_all_panel_views(self: *Self) void {
|
|||
tui.resize();
|
||||
}
|
||||
|
||||
pub fn hide_info_view_panel(self: *Self) void {
|
||||
self.toggle_panel_view(info_view, .disable) catch {};
|
||||
}
|
||||
|
||||
fn check_all_not_dirty(self: *const Self) command.Result {
|
||||
if (self.buffer_manager.is_dirty())
|
||||
return tp.exit("unsaved changes");
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ pub const Type = @import("dropdown.zig").Create(@This());
|
|||
const ed = @import("../../editor.zig");
|
||||
const module_name = @typeName(@This());
|
||||
const Widget = @import("../../Widget.zig");
|
||||
const info_view = @import("../../info_view.zig");
|
||||
|
||||
pub const label = "Select completion";
|
||||
pub const name = "completion";
|
||||
|
|
@ -24,6 +25,8 @@ pub const widget_type: Widget.Type = .dropdown;
|
|||
pub var detail_limit: usize = 40;
|
||||
pub var description_limit: usize = 25;
|
||||
|
||||
const info_box_widget_type: Widget.Type = .info_box;
|
||||
|
||||
pub const Entry = struct {
|
||||
label: []const u8,
|
||||
sort_text: []const u8,
|
||||
|
|
@ -38,6 +41,7 @@ pub const ValueType = struct {
|
|||
last_query: ?[]const u8 = null,
|
||||
commands: command.Collection(cmds) = undefined,
|
||||
data: []const u8 = &.{},
|
||||
info_box: ?Widget = null,
|
||||
};
|
||||
pub const defaultValue: ValueType = .{};
|
||||
|
||||
|
|
@ -97,6 +101,7 @@ pub fn load_entries(self: *Type) !usize {
|
|||
pub fn deinit(self: *Type) void {
|
||||
self.allocator.free(self.value.data);
|
||||
if (self.value.last_query) |p| self.allocator.free(p);
|
||||
if (self.value.info_box) |w| w.deinit(self.allocator);
|
||||
self.value.commands.deinit();
|
||||
}
|
||||
|
||||
|
|
@ -199,6 +204,9 @@ pub fn on_render_menu(self: *Type, button: *Type.ButtonType, theme: *const Widge
|
|||
tui.rdr().cursor_enable(@intCast(cursor.row), @intCast(cursor.col), tui.get_cursor_shape()) catch {};
|
||||
}
|
||||
|
||||
defer if (selected) if (self.value.info_box) |w| {
|
||||
_ = w.render(theme);
|
||||
};
|
||||
return tui.render_symbol(
|
||||
&button.plane,
|
||||
values.label,
|
||||
|
|
@ -217,6 +225,13 @@ pub fn on_render_menu(self: *Type, button: *Type.ButtonType, theme: *const Widge
|
|||
);
|
||||
}
|
||||
|
||||
pub fn after_resize(self: *Type) void {
|
||||
if (self.value.info_box) |w| {
|
||||
w.deinit(self.allocator);
|
||||
self.value.info_box = null;
|
||||
}
|
||||
}
|
||||
|
||||
pub const Values = struct {
|
||||
label: []const u8,
|
||||
sort_text: []const u8,
|
||||
|
|
@ -351,8 +366,18 @@ fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Pos) void {
|
|||
|
||||
pub fn updated(self: *Type, button_: ?*Type.ButtonType) !void {
|
||||
const button = button_ orelse return cancel(self);
|
||||
const values = get_values(button.opts.label);
|
||||
const mv = tui.mainview() orelse return;
|
||||
const values = get_values(button.opts.label);
|
||||
switch (tui.config().completion_info_mode) {
|
||||
.none => {},
|
||||
.box => try show_info_box(self, button, values),
|
||||
.panel => try show_info_panel(mv, values),
|
||||
}
|
||||
if (mv.get_active_editor()) |editor|
|
||||
self.value.view = editor.view;
|
||||
}
|
||||
|
||||
fn show_info_panel(mv: anytype, values: Values) !void {
|
||||
try mv.set_info_content(values.label, .replace);
|
||||
try mv.set_info_content(" ", .append); // blank line
|
||||
try mv.set_info_content(values.detail, .append);
|
||||
|
|
@ -364,8 +389,41 @@ pub fn updated(self: *Type, button_: ?*Type.ButtonType) !void {
|
|||
}
|
||||
try mv.set_info_content(" ", .append); // blank line
|
||||
try mv.set_info_content(values.documentation, .append);
|
||||
if (mv.get_active_editor()) |editor|
|
||||
self.value.view = editor.view;
|
||||
}
|
||||
|
||||
fn show_info_box(self: *Type, button: *Type.ButtonType, values: Values) !void {
|
||||
const w = self.value.info_box orelse blk: {
|
||||
self.value.info_box = try info_view.create_widget_type(self.allocator, self.menu.container.plane, info_box_widget_type);
|
||||
break :blk self.value.info_box.?;
|
||||
};
|
||||
const info_ = if (w.get(@typeName(info_view))) |w_| w_.dynamic_cast(info_view) orelse null else null;
|
||||
const info = info_ orelse @panic("show_info_box");
|
||||
|
||||
try info.set_content(values.label);
|
||||
if (values.detail.len > 0) {
|
||||
try info.append_content(" "); // blank line
|
||||
try info.append_content(values.detail);
|
||||
}
|
||||
if (builtin.mode == .Debug) {
|
||||
try info.append_content("newText:"); // blank line
|
||||
try info.append_content(values.textEdit_newText);
|
||||
try info.append_content("insertText:"); // blank line
|
||||
try info.append_content(values.insertText);
|
||||
}
|
||||
if (values.documentation.len > 0) {
|
||||
try info.append_content(" "); // blank line
|
||||
try info.append_content(values.documentation);
|
||||
}
|
||||
|
||||
const padding = tui.get_widget_style(info_box_widget_type).padding;
|
||||
const btn_box = Widget.Box.from(button.plane);
|
||||
const dim = info.content_size();
|
||||
w.resize(.{
|
||||
.h = dim.rows + padding.top + padding.bottom,
|
||||
.w = dim.cols + padding.left + padding.right + 3,
|
||||
.y = btn_box.y,
|
||||
.x = btn_box.x + btn_box.w + 1,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn cancel(_: *Type) !void {
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ pub fn Create(options: type) type {
|
|||
.menu = try Menu.create(*Self, allocator, tui.plane(), .{
|
||||
.ctx = self,
|
||||
.style = widget_type,
|
||||
.on_render = if (@hasDecl(options, "on_render_menu")) options.on_render_menu else on_render_menu,
|
||||
.on_render = options.on_render_menu,
|
||||
.prepare_resize = prepare_resize_menu,
|
||||
.after_resize = after_resize_menu,
|
||||
.on_scroll = EventHandler.bind(self, Self.on_scroll),
|
||||
|
|
@ -145,41 +145,6 @@ pub fn Create(options: type) type {
|
|||
.{ .fg = theme.scrollbar.fg, .bg = theme.editor_widget.bg };
|
||||
}
|
||||
|
||||
fn on_render_menu(_: *Self, button: *ButtonType, theme: *const Widget.Theme, selected: bool) bool {
|
||||
const style_base = theme.editor_widget;
|
||||
const style_label = if (button.active) theme.editor_cursor else if (button.hover or selected) theme.editor_selection else theme.editor_widget;
|
||||
const style_hint = if (tui.find_scope_style(theme, "entity.name")) |sty| sty.style else style_label;
|
||||
button.plane.set_base_style(style_base);
|
||||
button.plane.erase();
|
||||
button.plane.home();
|
||||
button.plane.set_style(style_label);
|
||||
if (button.active or button.hover or selected) {
|
||||
button.plane.fill(" ");
|
||||
button.plane.home();
|
||||
}
|
||||
var label: []const u8 = undefined;
|
||||
var hint: []const u8 = undefined;
|
||||
var iter = button.opts.label; // label contains cbor, first the file name, then multiple match indexes
|
||||
if (!(cbor.matchString(&iter, &label) catch false))
|
||||
label = "#ERROR#";
|
||||
if (!(cbor.matchString(&iter, &hint) catch false))
|
||||
hint = "";
|
||||
button.plane.set_style(style_hint);
|
||||
tui.render_pointer(&button.plane, selected);
|
||||
button.plane.set_style(style_label);
|
||||
_ = button.plane.print("{s} ", .{label}) catch {};
|
||||
button.plane.set_style(style_hint);
|
||||
_ = button.plane.print_aligned_right(0, "{s} ", .{hint}) catch {};
|
||||
var index: usize = 0;
|
||||
var len = cbor.decodeArrayHeader(&iter) catch return false;
|
||||
while (len > 0) : (len -= 1) {
|
||||
if (cbor.matchValue(&iter, cbor.extract(&index)) catch break) {
|
||||
tui.render_match_cell(&button.plane, 0, index + 2, theme) catch break;
|
||||
} else break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn prepare_resize_menu(self: *Self, menu: *Menu.State(*Self), _: Widget.Box) Widget.Box {
|
||||
const padding = tui.get_widget_style(menu.opts.style).padding;
|
||||
return self.prepare_resize(padding) orelse .{};
|
||||
|
|
@ -217,6 +182,8 @@ pub fn Create(options: type) type {
|
|||
fn after_resize(self: *Self) void {
|
||||
self.update_scrollbar();
|
||||
// self.start_query(0) catch {};
|
||||
if (@hasDecl(options, "after_resize"))
|
||||
options.after_resize(self);
|
||||
}
|
||||
|
||||
fn do_resize(self: *Self, padding: Widget.Style.Margin) void {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ const syntax = @import("syntax");
|
|||
const Widget = @import("Widget.zig");
|
||||
const MessageFilter = @import("MessageFilter.zig");
|
||||
const MainView = @import("mainview.zig");
|
||||
const IdleAction = @import("config").IdleAction;
|
||||
|
||||
// exports for unittesting
|
||||
pub const exports = struct {
|
||||
|
|
@ -86,6 +87,7 @@ color_scheme: enum { dark, light } = .dark,
|
|||
color_scheme_locked: bool = false,
|
||||
hint_mode: HintMode = .prefix,
|
||||
last_palette: ?LastPalette = null,
|
||||
idle_actions_: std.ArrayList(IdleAction) = .empty,
|
||||
|
||||
fast_scroll_: bool = false,
|
||||
alt_scroll_: bool = false,
|
||||
|
|
@ -296,6 +298,7 @@ fn deinit(self: *Self) void {
|
|||
m.deinit();
|
||||
self.delayed_init_input_mode = null;
|
||||
}
|
||||
self.idle_actions_.deinit(self.allocator);
|
||||
self.commands.deinit();
|
||||
if (self.mainview_) |*mv| mv.deinit(self.allocator);
|
||||
self.message_filters_.deinit();
|
||||
|
|
@ -607,6 +610,9 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void {
|
|||
return;
|
||||
}
|
||||
|
||||
if (try m.match(.{ "filter", "term", "exited", tp.more })) // drop late filter errors
|
||||
return;
|
||||
|
||||
if (try m.match(.{ "line_number_mode", tp.more })) // drop broadcast messages
|
||||
return;
|
||||
|
||||
|
|
@ -1019,6 +1025,30 @@ fn current_theme(self: *const Self) *const Widget.Theme {
|
|||
};
|
||||
}
|
||||
|
||||
fn toggle_idle_action(self: *Self, action: IdleAction) !bool {
|
||||
var enable: bool = true;
|
||||
|
||||
if (self.idle_actions_.items.len == 0)
|
||||
try self.idle_actions_.appendSlice(self.allocator, self.config_.idle_actions);
|
||||
|
||||
for (self.idle_actions_.items) |item| if (item == action) {
|
||||
enable = false;
|
||||
};
|
||||
|
||||
if (enable) {
|
||||
(try self.idle_actions_.addOne(self.allocator)).* = action;
|
||||
} else {
|
||||
for (self.idle_actions_.items, 0..) |item, idx| if (item == action) {
|
||||
_ = self.idle_actions_.orderedRemove(idx);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
self.config_.idle_actions = self.idle_actions_.items;
|
||||
try save_config();
|
||||
return enable;
|
||||
}
|
||||
|
||||
const cmds = struct {
|
||||
pub const Target = Self;
|
||||
const Ctx = command.Context;
|
||||
|
|
@ -1178,6 +1208,35 @@ const cmds = struct {
|
|||
}
|
||||
pub const toggle_completion_insert_mode_meta: Meta = .{ .description = "Toggle completion insert mode" };
|
||||
|
||||
pub fn toggle_completion_info_mode(self: *Self, _: Ctx) Result {
|
||||
self.config_.completion_info_mode = switch (self.config_.completion_info_mode) {
|
||||
.none => .box,
|
||||
.box => .panel,
|
||||
.panel => blk: {
|
||||
if (mainview()) |mv| mv.hide_info_view_panel();
|
||||
break :blk .none;
|
||||
},
|
||||
};
|
||||
defer self.logger.print("completion info mode {t}", .{self.config_.completion_info_mode});
|
||||
try save_config();
|
||||
resize();
|
||||
}
|
||||
pub const toggle_completion_info_mode_meta: Meta = .{ .description = "Toggle completion item info display" };
|
||||
|
||||
pub fn toggle_hover_info_mode(self: *Self, _: Ctx) Result {
|
||||
self.config_.hover_info_mode = switch (self.config_.hover_info_mode) {
|
||||
.box => .panel,
|
||||
.panel => blk: {
|
||||
if (mainview()) |mv| mv.hide_info_view_panel();
|
||||
break :blk .box;
|
||||
},
|
||||
};
|
||||
defer self.logger.print("hover info mode {t}", .{self.config_.hover_info_mode});
|
||||
try save_config();
|
||||
resize();
|
||||
}
|
||||
pub const toggle_hover_info_mode_meta: Meta = .{ .description = "Toggle hover info display" };
|
||||
|
||||
pub fn toggle_keybind_hints(self: *Self, _: Ctx) Result {
|
||||
self.hint_mode = switch (self.hint_mode) {
|
||||
.all => .prefix,
|
||||
|
|
@ -1203,6 +1262,18 @@ const cmds = struct {
|
|||
}
|
||||
pub const toggle_auto_find_meta: Meta = .{ .description = "Toggle auto find mode" };
|
||||
|
||||
pub fn toggle_auto_highlight_references(self: *Self, _: Ctx) Result {
|
||||
const enabled = try self.toggle_idle_action(.highlight_references);
|
||||
self.logger.print("auto highlight references {s}", .{if (enabled) "enabled" else "disabled"});
|
||||
}
|
||||
pub const toggle_auto_highlight_references_meta: Meta = .{ .description = "Toggle auto highlight references" };
|
||||
|
||||
pub fn toggle_auto_hover(self: *Self, _: Ctx) Result {
|
||||
const enabled = try self.toggle_idle_action(.hover);
|
||||
self.logger.print("auto hover {s}", .{if (enabled) "enabled" else "disabled"});
|
||||
}
|
||||
pub const toggle_auto_hover_meta: Meta = .{ .description = "Toggle auto hover" };
|
||||
|
||||
pub fn force_color_scheme(self: *Self, ctx: Ctx) Result {
|
||||
self.force_color_scheme(if (try ctx.args.match(.{"dark"}))
|
||||
.dark
|
||||
|
|
@ -1643,9 +1714,17 @@ const cmds = struct {
|
|||
pub const shrink_centered_view_meta: Meta = .{ .description = "Shrink centered view" };
|
||||
|
||||
pub fn panel_next_widget_style(_: *Self, _: Ctx) Result {
|
||||
if (mainview()) |mv| if (mv.is_any_panel_view_showing()) {
|
||||
set_next_style(.panel);
|
||||
need_render(@src());
|
||||
try save_config();
|
||||
return;
|
||||
};
|
||||
set_next_style(.info_box);
|
||||
need_render(@src());
|
||||
try save_config();
|
||||
tp.self_pid().send(.{ "cmd", "hover" }) catch {};
|
||||
return;
|
||||
}
|
||||
pub const panel_next_widget_style_meta: Meta = .{};
|
||||
|
||||
|
|
@ -1663,6 +1742,13 @@ const cmds = struct {
|
|||
}
|
||||
pub const dropdown_next_widget_style_meta: Meta = .{};
|
||||
|
||||
pub fn info_box_next_widget_style(_: *Self, _: Ctx) Result {
|
||||
set_next_style(.info_box);
|
||||
need_render(@src());
|
||||
try save_config();
|
||||
}
|
||||
pub const info_box_next_widget_style_meta: Meta = .{};
|
||||
|
||||
pub fn enable_fast_scroll(self: *Self, _: Ctx) Result {
|
||||
self.fast_scroll_ = true;
|
||||
}
|
||||
|
|
@ -2355,6 +2441,7 @@ pub fn get_widget_style(widget_type: WidgetType) *const WidgetStyle {
|
|||
.pane_left => WidgetStyle.from_tag(config_.pane_left_style),
|
||||
.pane_right => WidgetStyle.from_tag(config_.pane_right_style),
|
||||
.hint_window => WidgetStyle.from_tag(config_.hint_window_style),
|
||||
.info_box => WidgetStyle.from_tag(config_.info_box_style),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -2368,7 +2455,8 @@ pub fn set_next_style(widget_type: WidgetType) void {
|
|||
|
||||
fn next_widget_style(tag: ConfigWidgetStyle) ConfigWidgetStyle {
|
||||
const max_tag = comptime std.meta.tags(ConfigWidgetStyle).len;
|
||||
const new_value = @intFromEnum(tag) + 1;
|
||||
const value: usize = @intFromEnum(tag);
|
||||
const new_value = value + 1;
|
||||
return if (new_value >= max_tag) @enumFromInt(0) else @enumFromInt(new_value);
|
||||
}
|
||||
|
||||
|
|
@ -2383,6 +2471,7 @@ fn widget_type_config_variable(widget_type: WidgetType) *ConfigWidgetStyle {
|
|||
.pane_left => &config_.pane_left_style,
|
||||
.pane_right => &config_.pane_right_style,
|
||||
.hint_window => &config_.hint_window_style,
|
||||
.info_box => &config_.info_box_style,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue