refactor: improve capsulation and safety of tui module public api

This commit is contained in:
CJ van den Berg 2025-01-23 16:45:04 +01:00
parent 4145460012
commit 1d947ab499
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
28 changed files with 239 additions and 198 deletions

View file

@ -125,7 +125,7 @@ pub fn State(ctx_type: type) type {
tui.need_render(); tui.need_render();
return true; return true;
} else if (try m.match(.{ "H", tp.extract(&self.hover) })) { } else if (try m.match(.{ "H", tp.extract(&self.hover) })) {
tui.current().rdr.request_mouse_cursor_pointer(self.hover); tui.rdr().request_mouse_cursor_pointer(self.hover);
tui.need_render(); tui.need_render();
return true; return true;
} }

View file

@ -36,10 +36,9 @@ pub fn Options(context: type) type {
} }
if (self.cursor) |cursor| { if (self.cursor) |cursor| {
const pos: c_int = @intCast(cursor); const pos: c_int = @intCast(cursor);
const tui_ = tui.current(); if (tui.config().enable_terminal_cursor) {
if (tui_.config.enable_terminal_cursor) {
const y, const x = self.plane.rel_yx_to_abs(0, pos + 1); const y, const x = self.plane.rel_yx_to_abs(0, pos + 1);
tui_.rdr.cursor_enable(y, x, tui_.get_cursor_shape()) catch {}; tui.rdr().cursor_enable(y, x, tui.get_cursor_shape()) catch {};
} else { } else {
self.plane.cursor_move_yx(0, pos + 1) catch return false; self.plane.cursor_move_yx(0, pos + 1) catch return false;
var cell = self.plane.cell_init(); var cell = self.plane.cell_init();
@ -119,7 +118,7 @@ pub fn State(ctx_type: type) type {
tui.need_render(); tui.need_render();
return true; return true;
} else if (try m.match(.{ "H", tp.extract(&self.hover) })) { } else if (try m.match(.{ "H", tp.extract(&self.hover) })) {
tui.current().rdr.request_mouse_cursor_pointer(self.hover); tui.rdr().request_mouse_cursor_pointer(self.hover);
tui.need_render(); tui.need_render();
return true; return true;
} }

View file

@ -63,7 +63,7 @@ pub fn create(ctx_type: type, allocator: std.mem.Allocator, parent: Widget, opts
.allocator = allocator, .allocator = allocator,
.plane = parent.plane.*, .plane = parent.plane.*,
.opts = opts, .opts = opts,
.fade_time_ms = tui.current().config.animation_max_lag, .fade_time_ms = tui.config().animation_max_lag,
.frame_rate = @intCast(tp.env.get().num("frame-rate")), .frame_rate = @intCast(tp.env.get().num("frame-rate")),
}; };
return self; return self;
@ -106,7 +106,7 @@ pub fn State(ctx_type: type) type {
self.call_click_handler(@enumFromInt(btn)); self.call_click_handler(@enumFromInt(btn));
return true; return true;
} else if (try m.match(.{ "H", tp.extract(&self.hover) })) { } else if (try m.match(.{ "H", tp.extract(&self.hover) })) {
tui.current().rdr.request_mouse_cursor_default(self.hover); tui.rdr().request_mouse_cursor_default(self.hover);
return true; return true;
} }
return false; return false;

View file

@ -98,7 +98,7 @@ pub const CurSel = struct {
} }
fn enable_selection(self: *Self, root: Buffer.Root, metrics: Buffer.Metrics) !*Selection { fn enable_selection(self: *Self, root: Buffer.Root, metrics: Buffer.Metrics) !*Selection {
return switch (tui.current().get_selection_style()) { return switch (tui.get_selection_style()) {
.normal => self.enable_selection_normal(), .normal => self.enable_selection_normal(),
.inclusive => try self.enable_selection_inclusive(root, metrics), .inclusive => try self.enable_selection_inclusive(root, metrics),
}; };
@ -131,7 +131,7 @@ pub const CurSel = struct {
} }
fn disable_selection(self: *Self, root: Buffer.Root, metrics: Buffer.Metrics) void { fn disable_selection(self: *Self, root: Buffer.Root, metrics: Buffer.Metrics) void {
switch (tui.current().get_selection_style()) { switch (tui.get_selection_style()) {
.normal => self.disable_selection_normal(), .normal => self.disable_selection_normal(),
.inclusive => self.disable_selection_inclusive(root, metrics), .inclusive => self.disable_selection_inclusive(root, metrics),
} }
@ -404,8 +404,8 @@ pub const Editor = struct {
fn init(self: *Self, allocator: Allocator, n: Plane, buffer_manager: *Buffer.Manager) void { fn init(self: *Self, allocator: Allocator, n: Plane, buffer_manager: *Buffer.Manager) void {
const logger = log.logger("editor"); const logger = log.logger("editor");
const frame_rate = tp.env.get().num("frame-rate"); const frame_rate = tp.env.get().num("frame-rate");
const indent_size = tui.current().config.indent_size; const indent_size = tui.config().indent_size;
const tab_width = tui.current().config.tab_width; const tab_width = tui.config().tab_width;
self.* = Self{ self.* = Self{
.allocator = allocator, .allocator = allocator,
.plane = n, .plane = n,
@ -423,8 +423,8 @@ pub const Editor = struct {
.cursels = CurSel.List.init(allocator), .cursels = CurSel.List.init(allocator),
.cursels_saved = CurSel.List.init(allocator), .cursels_saved = CurSel.List.init(allocator),
.matches = Match.List.init(allocator), .matches = Match.List.init(allocator),
.enable_terminal_cursor = tui.current().config.enable_terminal_cursor, .enable_terminal_cursor = tui.config().enable_terminal_cursor,
.render_whitespace = from_whitespace_mode(tui.current().config.whitespace_mode), .render_whitespace = from_whitespace_mode(tui.config().whitespace_mode),
.diagnostics = std.ArrayList(Diagnostic).init(allocator), .diagnostics = std.ArrayList(Diagnostic).init(allocator),
}; };
} }
@ -555,7 +555,7 @@ pub const Editor = struct {
self.buffer = null; self.buffer = null;
self.plane.erase(); self.plane.erase();
self.plane.home(); self.plane.home();
tui.current().rdr.cursor_disable(); tui.rdr().cursor_disable();
_ = try self.handlers.msg(.{ "E", "close" }); _ = try self.handlers.msg(.{ "E", "close" });
if (self.syntax) |_| if (self.file_path) |file_path| if (self.syntax) |_| if (self.file_path) |file_path|
project_manager.did_close(file_path) catch {}; project_manager.did_close(file_path) catch {};
@ -933,7 +933,7 @@ pub const Editor = struct {
return Buffer.Walker.keep_walking; return Buffer.Walker.keep_walking;
} }
}; };
const hl_row: ?usize = if (tui.current().config.highlight_current_line) blk: { const hl_row: ?usize = if (tui.config().highlight_current_line) blk: {
if (self.get_primary().selection) |_| if (self.get_primary().selection) |_|
if (theme.editor_selection.bg) |sel_bg| if (theme.editor_selection.bg) |sel_bg|
if (theme.editor_line_highlight.bg) |hl_bg| if (theme.editor_line_highlight.bg) |hl_bg|
@ -969,7 +969,7 @@ pub const Editor = struct {
} }
fn render_cursors(self: *Self, theme: *const Widget.Theme, cell_map: CellMap) !void { fn render_cursors(self: *Self, theme: *const Widget.Theme, cell_map: CellMap) !void {
const style = tui.current().get_selection_style(); const style = tui.get_selection_style();
const frame = tracy.initZone(@src(), .{ .name = "editor render cursors" }); const frame = tracy.initZone(@src(), .{ .name = "editor render cursors" });
defer frame.deinit(); defer frame.deinit();
for (self.cursels.items[0 .. self.cursels.items.len - 1]) |*cursel_| if (cursel_.*) |*cursel| { for (self.cursels.items[0 .. self.cursels.items.len - 1]) |*cursel_| if (cursel_.*) |*cursel| {
@ -988,19 +988,18 @@ pub const Editor = struct {
} }
fn render_cursor_primary(self: *Self, cursor: *const Cursor, theme: *const Widget.Theme, cell_map: CellMap) !void { fn render_cursor_primary(self: *Self, cursor: *const Cursor, theme: *const Widget.Theme, cell_map: CellMap) !void {
const tui_ = tui.current(); if (!tui.is_mainview_focused() or !self.enable_terminal_cursor) {
if (!tui_.is_mainview_focused() or !self.enable_terminal_cursor) {
if (self.screen_cursor(cursor)) |pos| { if (self.screen_cursor(cursor)) |pos| {
set_cell_map_cursor(cell_map, pos.row, pos.col); set_cell_map_cursor(cell_map, pos.row, pos.col);
self.plane.cursor_move_yx(@intCast(pos.row), @intCast(pos.col)) catch return; self.plane.cursor_move_yx(@intCast(pos.row), @intCast(pos.col)) catch return;
const style = if (tui_.is_mainview_focused()) theme.editor_cursor else theme.editor_cursor_secondary; const style = if (tui.is_mainview_focused()) theme.editor_cursor else theme.editor_cursor_secondary;
self.render_cursor_cell(style); self.render_cursor_cell(style);
} }
} else { } else {
if (self.screen_cursor(cursor)) |pos| { if (self.screen_cursor(cursor)) |pos| {
set_cell_map_cursor(cell_map, pos.row, pos.col); set_cell_map_cursor(cell_map, pos.row, pos.col);
const y, const x = self.plane.rel_yx_to_abs(@intCast(pos.row), @intCast(pos.col)); const y, const x = self.plane.rel_yx_to_abs(@intCast(pos.row), @intCast(pos.col));
const configured_shape = tui_.get_cursor_shape(); const configured_shape = tui.get_cursor_shape();
const cursor_shape = if (self.cursels.items.len > 1) switch (configured_shape) { const cursor_shape = if (self.cursels.items.len > 1) switch (configured_shape) {
.beam => .block, .beam => .block,
.beam_blink => .block_blink, .beam_blink => .block_blink,
@ -1008,9 +1007,9 @@ pub const Editor = struct {
.underline_blink => .block_blink, .underline_blink => .block_blink,
else => configured_shape, else => configured_shape,
} else configured_shape; } else configured_shape;
tui_.rdr.cursor_enable(y, x, cursor_shape) catch {}; tui.rdr().cursor_enable(y, x, cursor_shape) catch {};
} else { } else {
tui_.rdr.cursor_disable(); tui.rdr().cursor_disable();
} }
} }
} }
@ -2112,12 +2111,12 @@ pub const Editor = struct {
} }
fn get_animation_min_lag() f64 { fn get_animation_min_lag() f64 {
const ms: f64 = @floatFromInt(tui.current().config.animation_min_lag); const ms: f64 = @floatFromInt(tui.config().animation_min_lag);
return @max(ms * 0.001, 0.001); // to seconds return @max(ms * 0.001, 0.001); // to seconds
} }
fn get_animation_max_lag() f64 { fn get_animation_max_lag() f64 {
const ms: f64 = @floatFromInt(tui.current().config.animation_max_lag); const ms: f64 = @floatFromInt(tui.config().animation_max_lag);
return @max(ms * 0.001, 0.001); // to seconds return @max(ms * 0.001, 0.001); // to seconds
} }
@ -2249,7 +2248,7 @@ pub const Editor = struct {
@import("renderer").copy_to_windows_clipboard(text) catch |e| @import("renderer").copy_to_windows_clipboard(text) catch |e|
self.logger.print_err("clipboard", "failed to set clipboard: {any}", .{e}); self.logger.print_err("clipboard", "failed to set clipboard: {any}", .{e});
} else { } else {
tui.current().rdr.copy_to_system_clipboard(text); tui.rdr().copy_to_system_clipboard(text);
} }
} }
@ -3566,13 +3565,13 @@ pub const Editor = struct {
pub fn enable_jump_mode(self: *Self, _: Context) Result { pub fn enable_jump_mode(self: *Self, _: Context) Result {
self.jump_mode = true; self.jump_mode = true;
tui.current().rdr.request_mouse_cursor_pointer(true); tui.rdr().request_mouse_cursor_pointer(true);
} }
pub const enable_jump_mode_meta = .{ .description = "Enable jump/hover mode" }; pub const enable_jump_mode_meta = .{ .description = "Enable jump/hover mode" };
pub fn disable_jump_mode(self: *Self, _: Context) Result { pub fn disable_jump_mode(self: *Self, _: Context) Result {
self.jump_mode = false; self.jump_mode = false;
tui.current().rdr.request_mouse_cursor_text(true); tui.rdr().request_mouse_cursor_text(true);
} }
pub const disable_jump_mode_meta = .{}; pub const disable_jump_mode_meta = .{};
@ -3762,7 +3761,7 @@ pub const Editor = struct {
if (ctx.args.match(.{ "then", .{ tp.extract(&cmd), tp.extract_cbor(&args) } }) catch false) { if (ctx.args.match(.{ "then", .{ tp.extract(&cmd), tp.extract_cbor(&args) } }) catch false) {
then = true; then = true;
} }
if (tui.current().config.enable_format_on_save) if (self.get_formatter()) |_| { if (tui.config().enable_format_on_save) if (self.get_formatter()) |_| {
self.need_save_after_filter = .{ .then = if (then) .{ .cmd = cmd, .args = args } else null }; self.need_save_after_filter = .{ .then = if (then) .{ .cmd = cmd, .args = args } else null };
const primary = self.get_primary(); const primary = self.get_primary();
const sel = primary.selection; const sel = primary.selection;
@ -4888,10 +4887,10 @@ pub const EditorWidget = struct {
} else if (try m.match(.{ "H", tp.extract(&self.hover) })) { } else if (try m.match(.{ "H", tp.extract(&self.hover) })) {
if (self.editor.jump_mode) { if (self.editor.jump_mode) {
self.update_hover_timer(.init); self.update_hover_timer(.init);
tui.current().rdr.request_mouse_cursor_pointer(self.hover); tui.rdr().request_mouse_cursor_pointer(self.hover);
} else { } else {
self.update_hover_timer(.cancel); self.update_hover_timer(.cancel);
tui.current().rdr.request_mouse_cursor_text(self.hover); tui.rdr().request_mouse_cursor_text(self.hover);
} }
} else if (try m.match(.{"HOVER"})) { } else if (try m.match(.{"HOVER"})) {
self.update_hover_timer(.fired); self.update_hover_timer(.fired);
@ -4947,7 +4946,7 @@ pub const EditorWidget = struct {
} }
fn mouse_pos_abs(self: *Self, y: c_int, x: c_int, xoffset: c_int) struct { c_int, c_int } { fn mouse_pos_abs(self: *Self, y: c_int, x: c_int, xoffset: c_int) struct { c_int, c_int } {
return if (tui.current().is_cursor_beam()) return if (tui.is_cursor_beam())
self.editor.plane.abs_yx_to_rel_nearest_x(y, x, xoffset) self.editor.plane.abs_yx_to_rel_nearest_x(y, x, xoffset)
else else
self.editor.plane.abs_yx_to_rel(y, x); self.editor.plane.abs_yx_to_rel(y, x);

View file

@ -45,15 +45,15 @@ pub fn create(allocator: Allocator, parent: Widget, event_source: Widget, editor
.allocator = allocator, .allocator = allocator,
.plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent.plane.*), .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent.plane.*),
.parent = parent, .parent = parent,
.linenum = tui.current().config.gutter_line_numbers, .linenum = tui.config().gutter_line_numbers,
.relative = tui.current().config.gutter_line_numbers_relative, .relative = tui.config().gutter_line_numbers_relative,
.highlight = tui.current().config.highlight_current_line_gutter, .highlight = tui.config().highlight_current_line_gutter,
.symbols = tui.current().config.gutter_symbols, .symbols = tui.config().gutter_symbols,
.editor = editor, .editor = editor,
.diff = try diff.create(), .diff = try diff.create(),
.diff_symbols = std.ArrayList(Symbol).init(allocator), .diff_symbols = std.ArrayList(Symbol).init(allocator),
}; };
try tui.current().message_filters.add(MessageFilter.bind(self, filter_receive)); try tui.message_filters().add(MessageFilter.bind(self, filter_receive));
try event_source.subscribe(EventHandler.bind(self, handle_event)); try event_source.subscribe(EventHandler.bind(self, handle_event));
return self.widget(); return self.widget();
} }
@ -65,7 +65,7 @@ pub fn widget(self: *Self) Widget {
pub fn deinit(self: *Self, allocator: Allocator) void { pub fn deinit(self: *Self, allocator: Allocator) void {
self.diff_symbols_clear(); self.diff_symbols_clear();
self.diff_symbols.deinit(); self.diff_symbols.deinit();
tui.current().message_filters.remove_ptr(self); tui.message_filters().remove_ptr(self);
self.plane.deinit(); self.plane.deinit();
allocator.destroy(self); allocator.destroy(self);
} }
@ -130,7 +130,7 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool {
self.plane.set_style(theme.editor_gutter); self.plane.set_style(theme.editor_gutter);
_ = self.plane.fill(" "); _ = self.plane.fill(" ");
if (self.linenum) { if (self.linenum) {
const relative = self.relative or if (tui.current().input_mode) |mode| mode.line_numbers == .relative else false; const relative = self.relative or if (tui.input_mode()) |mode| mode.line_numbers == .relative else false;
if (relative) if (relative)
self.render_relative(theme) self.render_relative(theme)
else else

View file

@ -126,7 +126,7 @@ pub fn walk(self: *Self, walk_ctx: *anyopaque, f: Widget.WalkFn, w: *Widget) boo
pub fn receive(_: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool { pub fn receive(_: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var hover: bool = false; var hover: bool = false;
if (try m.match(.{ "H", tp.extract(&hover) })) { if (try m.match(.{ "H", tp.extract(&hover) })) {
tui.current().rdr.request_mouse_cursor_default(hover); tui.rdr().request_mouse_cursor_default(hover);
tui.need_render(); tui.need_render();
return true; return true;
} }

View file

@ -39,12 +39,12 @@ pub fn create(allocator: Allocator, parent: Plane) !Widget {
.plane = n, .plane = n,
.buffer = Buffer.init(allocator), .buffer = Buffer.init(allocator),
}; };
try tui.current().input_listeners.add(EventHandler.bind(self, listen)); try tui.input_listeners().add(EventHandler.bind(self, listen));
return Widget.to(self); return Widget.to(self);
} }
pub fn deinit(self: *Self, allocator: Allocator) void { pub fn deinit(self: *Self, allocator: Allocator) void {
tui.current().input_listeners.remove_ptr(self); tui.input_listeners().remove_ptr(self);
for (self.buffer.items) |item| for (self.buffer.items) |item|
self.buffer.allocator.free(item.json); self.buffer.allocator.free(item.json);
self.buffer.deinit(); self.buffer.deinit();

View file

@ -37,7 +37,7 @@ pub fn create(allocator: Allocator, parent: Plane) !Widget {
pub fn deinit(self: *Self, allocator: Allocator) void { pub fn deinit(self: *Self, allocator: Allocator) void {
self.editor.handlers.remove_ptr(self); self.editor.handlers.remove_ptr(self);
tui.current().message_filters.remove_ptr(self); tui.message_filters().remove_ptr(self);
self.plane.deinit(); self.plane.deinit();
allocator.destroy(self); allocator.destroy(self);
} }

View file

@ -80,8 +80,8 @@ pub fn create(allocator: std.mem.Allocator) !Widget {
const widgets = try WidgetList.createV(allocator, self.plane, @typeName(Self), .dynamic); const widgets = try WidgetList.createV(allocator, self.plane, @typeName(Self), .dynamic);
self.widgets = widgets; self.widgets = widgets;
self.widgets_widget = widgets.widget(); self.widgets_widget = widgets.widget();
if (tui.current().config.top_bar.len > 0) if (tui.config().top_bar.len > 0)
self.top_bar = try widgets.addP(try @import("status/bar.zig").create(allocator, self.plane, tui.current().config.top_bar, .none, null)); self.top_bar = try widgets.addP(try @import("status/bar.zig").create(allocator, self.plane, tui.config().top_bar, .none, null));
const views = try WidgetList.createH(allocator, self.plane, @typeName(Self), .dynamic); const views = try WidgetList.createH(allocator, self.plane, @typeName(Self), .dynamic);
self.views = views; self.views = views;
@ -90,8 +90,8 @@ pub fn create(allocator: std.mem.Allocator) !Widget {
try widgets.add(self.views_widget); try widgets.add(self.views_widget);
if (tui.current().config.bottom_bar.len > 0) { if (tui.config().bottom_bar.len > 0) {
self.bottom_bar = try widgets.addP(try @import("status/bar.zig").create(allocator, self.plane, tui.current().config.bottom_bar, .grip, EventHandler.bind(self, handle_bottom_bar_event))); self.bottom_bar = try widgets.addP(try @import("status/bar.zig").create(allocator, self.plane, tui.config().bottom_bar, .grip, EventHandler.bind(self, handle_bottom_bar_event)));
} }
if (tp.env.get().is("show-input")) if (tp.env.get().is("show-input"))
self.toggle_inputview_async(); self.toggle_inputview_async();
@ -142,9 +142,6 @@ pub fn receive(self: *Self, from_: tp.pid_ref, m: tp.message) error{Exit}!bool {
.end = .{ .row = end_line, .col = end_pos }, .end = .{ .row = end_line, .col = end_pos },
}); });
return true; return true;
} else if (try m.match(.{"write_restore_info"})) {
self.write_restore_info();
return true;
} }
return if (try self.floating_views.send(from_, m)) true else self.widgets.send(from_, m); return if (try self.floating_views.send(from_, m)) true else self.widgets.send(from_, m);
} }
@ -212,7 +209,7 @@ fn toggle_panel_view(self: *Self, view: anytype, enable_only: bool) !void {
try panels.add(try view.create(self.allocator, self.widgets.plane)); try panels.add(try view.create(self.allocator, self.widgets.plane));
self.panels = panels; self.panels = panels;
} }
tui.current().resize(); tui.resize();
} }
fn get_panel_view(self: *Self, comptime view: type) ?*view { fn get_panel_view(self: *Self, comptime view: type) ?*view {
@ -228,7 +225,7 @@ fn close_all_panel_views(self: *Self) void {
self.widgets.remove(panels.widget()); self.widgets.remove(panels.widget());
self.panels = null; self.panels = null;
} }
tui.current().resize(); tui.resize();
} }
fn toggle_view(self: *Self, view: anytype) !void { fn toggle_view(self: *Self, view: anytype) !void {
@ -237,7 +234,7 @@ fn toggle_view(self: *Self, view: anytype) !void {
} else { } else {
try self.widgets.add(try view.create(self.allocator, self.plane)); try self.widgets.add(try view.create(self.allocator, self.plane));
} }
tui.current().resize(); tui.resize();
} }
fn check_all_not_dirty(self: *const Self) command.Result { fn check_all_not_dirty(self: *const Self) command.Result {
@ -274,7 +271,7 @@ const cmds = struct {
return; return;
try project_manager.open(project_dir); try project_manager.open(project_dir);
const project = tp.env.get().str("project"); const project = tp.env.get().str("project");
tui.current().rdr.set_terminal_working_directory(project); tui.rdr().set_terminal_working_directory(project);
if (self.top_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" }); if (self.top_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" });
if (self.bottom_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" }); if (self.bottom_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" });
} }
@ -297,7 +294,7 @@ const cmds = struct {
self.buffer_manager = BufferManager.init(self.allocator); self.buffer_manager = BufferManager.init(self.allocator);
try project_manager.open(project_dir); try project_manager.open(project_dir);
const project = tp.env.get().str("project"); const project = tp.env.get().str("project");
tui.current().rdr.set_terminal_working_directory(project); tui.rdr().set_terminal_working_directory(project);
if (self.top_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" }); if (self.top_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" });
if (self.bottom_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" }); if (self.bottom_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" });
if (try project_manager.request_most_recent_file(self.allocator)) |file_path| if (try project_manager.request_most_recent_file(self.allocator)) |file_path|
@ -487,9 +484,9 @@ const cmds = struct {
pub const add_split_meta = .{}; pub const add_split_meta = .{};
pub fn gutter_mode_next(self: *Self, _: Ctx) Result { pub fn gutter_mode_next(self: *Self, _: Ctx) Result {
const tui_ = tui.current(); const config = tui.config_mut();
var ln = tui_.config.gutter_line_numbers; var ln = config.gutter_line_numbers;
var lnr = tui_.config.gutter_line_numbers_relative; var lnr = config.gutter_line_numbers_relative;
if (ln and !lnr) { if (ln and !lnr) {
ln = true; ln = true;
lnr = true; lnr = true;
@ -500,9 +497,9 @@ const cmds = struct {
ln = true; ln = true;
lnr = false; lnr = false;
} }
tui_.config.gutter_line_numbers = ln; config.gutter_line_numbers = ln;
tui_.config.gutter_line_numbers_relative = lnr; config.gutter_line_numbers_relative = lnr;
try tui_.save_config(); try tui.save_config();
if (self.widgets.get("editor_gutter")) |gutter_widget| { if (self.widgets.get("editor_gutter")) |gutter_widget| {
const gutter = gutter_widget.dynamic_cast(@import("editor_gutter.zig")) orelse return; const gutter = gutter_widget.dynamic_cast(@import("editor_gutter.zig")) orelse return;
gutter.linenum = ln; gutter.linenum = ln;
@ -658,7 +655,7 @@ const cmds = struct {
defer self.allocator.free(text); defer self.allocator.free(text);
return command.executeName("paste", command.fmt(.{text})) catch {}; return command.executeName("paste", command.fmt(.{text})) catch {};
} }
tui.current().rdr.request_system_clipboard(); tui.rdr().request_system_clipboard();
} }
pub const system_paste_meta = .{ .description = "Paste from system clipboard" }; pub const system_paste_meta = .{ .description = "Paste from system clipboard" };
@ -719,7 +716,7 @@ const cmds = struct {
if (!try ctx.args.match(.{tp.extract(&amount)})) if (!try ctx.args.match(.{tp.extract(&amount)}))
return error.InvalidArgument; return error.InvalidArgument;
if (build_options.gui) if (build_options.gui)
tui.current().rdr.adjust_fontsize(amount); tui.rdr().adjust_fontsize(amount);
} }
pub const adjust_fontsize_meta = .{ .arguments = &.{.float} }; pub const adjust_fontsize_meta = .{ .arguments = &.{.float} };
@ -728,13 +725,13 @@ const cmds = struct {
if (!try ctx.args.match(.{tp.extract(&fontsize)})) if (!try ctx.args.match(.{tp.extract(&fontsize)}))
return error.InvalidArgument; return error.InvalidArgument;
if (build_options.gui) if (build_options.gui)
tui.current().rdr.set_fontsize(fontsize); tui.rdr().set_fontsize(fontsize);
} }
pub const set_fontsize_meta = .{ .arguments = &.{.float} }; pub const set_fontsize_meta = .{ .arguments = &.{.float} };
pub fn reset_fontsize(_: *Self, _: Ctx) Result { pub fn reset_fontsize(_: *Self, _: Ctx) Result {
if (build_options.gui) if (build_options.gui)
tui.current().rdr.reset_fontsize(); tui.rdr().reset_fontsize();
} }
pub const reset_fontsize_meta = .{ .description = "Reset font to configured size" }; pub const reset_fontsize_meta = .{ .description = "Reset font to configured size" };
@ -743,13 +740,13 @@ const cmds = struct {
if (!try ctx.args.match(.{tp.extract(&fontface)})) if (!try ctx.args.match(.{tp.extract(&fontface)}))
return error.InvalidArgument; return error.InvalidArgument;
if (build_options.gui) if (build_options.gui)
tui.current().rdr.set_fontface(fontface); tui.rdr().set_fontface(fontface);
} }
pub const set_fontface_meta = .{ .arguments = &.{.float} }; pub const set_fontface_meta = .{ .arguments = &.{.float} };
pub fn reset_fontface(_: *Self, _: Ctx) Result { pub fn reset_fontface(_: *Self, _: Ctx) Result {
if (build_options.gui) if (build_options.gui)
tui.current().rdr.reset_fontface(); tui.rdr().reset_fontface();
} }
pub const reset_fontface_meta = .{ .description = "Reset font to configured face" }; pub const reset_fontface_meta = .{ .description = "Reset font to configured face" };
}; };
@ -888,7 +885,7 @@ fn create_editor(self: *Self) !void {
try self.replace_active_view(editor_widget); try self.replace_active_view(editor_widget);
if (editor.dynamic_cast(ed.EditorWidget)) |p| if (editor.dynamic_cast(ed.EditorWidget)) |p|
try self.add_editor(&p.editor); try self.add_editor(&p.editor);
tui.current().resize(); tui.resize();
} }
fn toggle_logview_async(_: *Self) void { fn toggle_logview_async(_: *Self) void {
@ -913,16 +910,16 @@ fn create_home(self: *Self) !void {
if (self.active_editor) |_| return; if (self.active_editor) |_| return;
try self.delete_active_view(); try self.delete_active_view();
try self.replace_active_view(try home.create(self.allocator, Widget.to(self))); try self.replace_active_view(try home.create(self.allocator, Widget.to(self)));
tui.current().resize(); tui.resize();
} }
fn create_home_split(self: *Self) !void { fn create_home_split(self: *Self) !void {
tui.reset_drag_context(); tui.reset_drag_context();
try self.add_view(try home.create(self.allocator, Widget.to(self))); try self.add_view(try home.create(self.allocator, Widget.to(self)));
tui.current().resize(); tui.resize();
} }
fn write_restore_info(self: *Self) void { pub fn write_restore_info(self: *Self) void {
const editor = self.get_active_editor() orelse return; const editor = self.get_active_editor() orelse return;
var sfa = std.heap.stackFallback(512, self.allocator); var sfa = std.heap.stackFallback(512, self.allocator);
const a = sfa.get(); const a = sfa.get();

View file

@ -5,7 +5,6 @@ const command = @import("command");
const cmd = command.executeName; const cmd = command.executeName;
const tui = @import("../tui.zig"); const tui = @import("../tui.zig");
const mainview = @import("../mainview.zig");
var commands: Commands = undefined; var commands: Commands = undefined;
@ -59,7 +58,7 @@ const cmds_ = struct {
const logger = log.logger("helix-mode"); const logger = log.logger("helix-mode");
defer logger.deinit(); defer logger.deinit();
logger.print("saved location", .{}); logger.print("saved location", .{});
const mv = tui.current().mainview.dynamic_cast(mainview) orelse return; const mv = tui.mainview() orelse return;
const file_path = mv.get_active_file_path() orelse return; const file_path = mv.get_active_file_path() orelse return;
const primary = (mv.get_active_editor() orelse return).get_primary(); const primary = (mv.get_active_editor() orelse return).get_primary();
const sel: ?location_history.Selection = if (primary.selection) |sel| .{ const sel: ?location_history.Selection = if (primary.selection) |sel| .{

View file

@ -44,7 +44,7 @@ pub fn Create(options: type) type {
.entries = std.ArrayList(Entry).init(allocator), .entries = std.ArrayList(Entry).init(allocator),
}; };
try self.commands.init(self); try self.commands.init(self);
try tui.current().message_filters.add(MessageFilter.bind(self, receive_path_entry)); try tui.message_filters().add(MessageFilter.bind(self, receive_path_entry));
try options.load_entries(self); try options.load_entries(self);
if (@hasDecl(options, "restore_state")) if (@hasDecl(options, "restore_state"))
options.restore_state(self) catch {}; options.restore_state(self) catch {};
@ -57,7 +57,7 @@ pub fn Create(options: type) type {
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
self.commands.deinit(); self.commands.deinit();
tui.current().message_filters.remove_ptr(self); tui.message_filters().remove_ptr(self);
self.clear_entries(); self.clear_entries();
self.entries.deinit(); self.entries.deinit();
self.match.deinit(); self.match.deinit();
@ -113,7 +113,7 @@ pub fn Create(options: type) type {
} else { } else {
try self.file_path.appendSlice(self.query.items); try self.file_path.appendSlice(self.query.items);
} }
if (tui.current().mini_mode) |*mini_mode| { if (tui.mini_mode()) |mini_mode| {
mini_mode.text = self.file_path.items; mini_mode.text = self.file_path.items;
mini_mode.cursor = tui.egc_chunk_width(self.file_path.items, 0, 8); mini_mode.cursor = tui.egc_chunk_width(self.file_path.items, 0, 8);
} }
@ -137,7 +137,7 @@ pub fn Create(options: type) type {
fn process_project_manager(self: *Self, m: tp.message) MessageFilter.Error!void { fn process_project_manager(self: *Self, m: tp.message) MessageFilter.Error!void {
defer { defer {
if (tui.current().mini_mode) |*mini_mode| { if (tui.mini_mode()) |mini_mode| {
mini_mode.text = self.file_path.items; mini_mode.text = self.file_path.items;
mini_mode.cursor = tui.egc_chunk_width(self.file_path.items, 0, 8); mini_mode.cursor = tui.egc_chunk_width(self.file_path.items, 0, 8);
} }
@ -241,7 +241,7 @@ pub fn Create(options: type) type {
} }
fn update_mini_mode_text(self: *Self) void { fn update_mini_mode_text(self: *Self) void {
if (tui.current().mini_mode) |*mini_mode| { if (tui.mini_mode()) |mini_mode| {
mini_mode.text = self.file_path.items; mini_mode.text = self.file_path.items;
mini_mode.cursor = tui.egc_chunk_width(self.file_path.items, 0, 8); mini_mode.cursor = tui.egc_chunk_width(self.file_path.items, 0, 8);
} }

View file

@ -140,7 +140,7 @@ fn load_history(self: *Self, pos: usize) void {
} }
fn update_mini_mode_text(self: *Self) void { fn update_mini_mode_text(self: *Self) void {
if (tui.current().mini_mode) |*mini_mode| { if (tui.mini_mode()) |mini_mode| {
mini_mode.text = self.input.items; mini_mode.text = self.input.items;
mini_mode.cursor = tui.egc_chunk_width(self.input.items, 0, 8); mini_mode.cursor = tui.egc_chunk_width(self.input.items, 0, 8);
} }

View file

@ -81,7 +81,7 @@ fn start_query(self: *Self) !void {
} }
fn update_mini_mode_text(self: *Self) void { fn update_mini_mode_text(self: *Self) void {
if (tui.current().mini_mode) |*mini_mode| { if (tui.mini_mode()) |mini_mode| {
mini_mode.text = self.input; mini_mode.text = self.input;
mini_mode.cursor = tui.egc_chunk_width(self.input, 0, 8); mini_mode.cursor = tui.egc_chunk_width(self.input, 0, 8);
} }

View file

@ -49,7 +49,7 @@ pub fn receive(self: *Self, _: tp.pid_ref, _: tp.message) error{Exit}!bool {
} }
fn update_mini_mode_text(self: *Self) void { fn update_mini_mode_text(self: *Self) void {
if (tui.current().mini_mode) |*mini_mode| { if (tui.mini_mode()) |mini_mode| {
mini_mode.text = if (self.input) |linenum| mini_mode.text = if (self.input) |linenum|
(fmt.bufPrint(&self.buf, "{d}", .{linenum}) catch "") (fmt.bufPrint(&self.buf, "{d}", .{linenum}) catch "")
else else

View file

@ -4,7 +4,6 @@ const root = @import("root");
const command = @import("command"); const command = @import("command");
const tui = @import("../../tui.zig"); const tui = @import("../../tui.zig");
const mainview = @import("../../mainview.zig");
pub const Type = @import("file_browser.zig").Create(@This()); pub const Type = @import("file_browser.zig").Create(@This());

View file

@ -20,7 +20,7 @@ pub const Entry = struct {
}; };
pub fn load_entries(palette: *Type) !usize { pub fn load_entries(palette: *Type) !usize {
const hints = if (tui.current().input_mode) |m| m.keybind_hints else @panic("no keybind hints"); const hints = if (tui.input_mode()) |m| m.keybind_hints else @panic("no keybind hints");
var longest_hint: usize = 0; var longest_hint: usize = 0;
for (command.commands.items) |cmd_| if (cmd_) |p| { for (command.commands.items) |cmd_| if (cmd_) |p| {
if (p.meta.description.len > 0) { if (p.meta.description.len > 0) {

View file

@ -33,10 +33,10 @@ pub fn deinit(palette: *Type) void {
pub fn load_entries(palette: *Type) !usize { pub fn load_entries(palette: *Type) !usize {
var idx: usize = 0; var idx: usize = 0;
previous_fontface = try palette.allocator.dupe(u8, tui.current().fontface); previous_fontface = try palette.allocator.dupe(u8, tui.fontface());
const fontfaces = tui.current().fontfaces orelse return 0; const fontfaces = try tui.fontfaces(palette.allocator);
tui.current().fontfaces = null; defer palette.allocator.free(fontfaces);
for (fontfaces.items) |fontface| { for (fontfaces) |fontface| {
idx += 1; idx += 1;
(try palette.entries.addOne()).* = .{ .label = fontface }; (try palette.entries.addOne()).* = .{ .label = fontface };
if (previous_fontface) |previous_fontface_| if (std.mem.eql(u8, fontface, previous_fontface_)) { if (previous_fontface) |previous_fontface_| if (std.mem.eql(u8, fontface, previous_fontface_)) {

View file

@ -23,7 +23,7 @@ pub fn deinit(palette: *Type) void {
} }
pub fn load_entries(palette: *Type) !usize { pub fn load_entries(palette: *Type) !usize {
const hints = if (tui.current().input_mode) |m| m.keybind_hints else @panic("no keybind hints"); const hints = if (tui.input_mode()) |m| m.keybind_hints else @panic("no keybind hints");
var longest_hint: usize = 0; var longest_hint: usize = 0;
for (command.commands.items) |cmd_| if (cmd_) |p| { for (command.commands.items) |cmd_| if (cmd_) |p| {
var label_ = std.ArrayList(u8).init(palette.allocator); var label_ = std.ArrayList(u8).init(palette.allocator);

View file

@ -18,7 +18,6 @@ const Button = @import("../../Button.zig");
const InputBox = @import("../../InputBox.zig"); const InputBox = @import("../../InputBox.zig");
const Menu = @import("../../Menu.zig"); const Menu = @import("../../Menu.zig");
const Widget = @import("../../Widget.zig"); const Widget = @import("../../Widget.zig");
const mainview = @import("../../mainview.zig");
const ModalBackground = @import("../../ModalBackground.zig"); const ModalBackground = @import("../../ModalBackground.zig");
const Self = @This(); const Self = @This();
@ -38,11 +37,11 @@ commands: Commands = undefined,
buffer_manager: ?*BufferManager, buffer_manager: ?*BufferManager,
pub fn create(allocator: std.mem.Allocator) !tui.Mode { pub fn create(allocator: std.mem.Allocator) !tui.Mode {
const mv = tui.current().mainview.dynamic_cast(mainview) orelse return error.NotFound; const mv = tui.mainview() orelse return error.NotFound;
const self: *Self = try allocator.create(Self); const self: *Self = try allocator.create(Self);
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,
.modal = try ModalBackground.create(*Self, allocator, tui.current().mainview, .{ .ctx = self }), .modal = try ModalBackground.create(*Self, allocator, tui.mainview_widget(), .{ .ctx = self }),
.menu = try Menu.create(*Self, allocator, tui.plane(), .{ .menu = try Menu.create(*Self, allocator, tui.plane(), .{
.ctx = self, .ctx = self,
.on_render = on_render_menu, .on_render = on_render_menu,
@ -56,7 +55,7 @@ pub fn create(allocator: std.mem.Allocator) !tui.Mode {
.buffer_manager = tui.get_buffer_manager(), .buffer_manager = tui.get_buffer_manager(),
}; };
try self.commands.init(self); try self.commands.init(self);
try tui.current().message_filters.add(MessageFilter.bind(self, receive_project_manager)); try tui.message_filters().add(MessageFilter.bind(self, receive_project_manager));
self.query_pending = true; self.query_pending = true;
try project_manager.request_recent_files(max_recent_files); try project_manager.request_recent_files(max_recent_files);
self.menu.resize(.{ .y = 0, .x = self.menu_pos_x(), .w = max_menu_width() + 2 }); self.menu.resize(.{ .y = 0, .x = self.menu_pos_x(), .w = max_menu_width() + 2 });
@ -72,8 +71,8 @@ pub fn create(allocator: std.mem.Allocator) !tui.Mode {
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
self.commands.deinit(); self.commands.deinit();
tui.current().message_filters.remove_ptr(self); tui.message_filters().remove_ptr(self);
if (tui.current().mainview.dynamic_cast(mainview)) |mv| { if (tui.mainview()) |mv| {
mv.floating_views.remove(self.menu.container_widget); mv.floating_views.remove(self.menu.container_widget);
mv.floating_views.remove(self.modal.widget()); mv.floating_views.remove(self.modal.widget());
} }
@ -86,13 +85,13 @@ inline fn menu_width(self: *Self) usize {
} }
inline fn menu_pos_x(self: *Self) usize { inline fn menu_pos_x(self: *Self) usize {
const screen_width = tui.current().screen().w; const screen_width = tui.screen().w;
const width = self.menu_width(); const width = self.menu_width();
return if (screen_width <= width) 0 else (screen_width - width) / 2; return if (screen_width <= width) 0 else (screen_width - width) / 2;
} }
inline fn max_menu_width() usize { inline fn max_menu_width() usize {
const width = tui.current().screen().w; const width = tui.screen().w;
return @max(15, width - (width / 5)); return @max(15, width - (width / 5));
} }

View file

@ -14,7 +14,6 @@ const tui = @import("../../tui.zig");
const Button = @import("../../Button.zig"); const Button = @import("../../Button.zig");
const InputBox = @import("../../InputBox.zig"); const InputBox = @import("../../InputBox.zig");
const Widget = @import("../../Widget.zig"); const Widget = @import("../../Widget.zig");
const mainview = @import("../../mainview.zig");
const scrollbar_v = @import("../../scrollbar_v.zig"); const scrollbar_v = @import("../../scrollbar_v.zig");
const ModalBackground = @import("../../ModalBackground.zig"); const ModalBackground = @import("../../ModalBackground.zig");
@ -47,11 +46,11 @@ pub fn Create(options: type) type {
pub const ButtonState = Button.State(*Menu.State(*Self)); pub const ButtonState = Button.State(*Menu.State(*Self));
pub fn create(allocator: std.mem.Allocator) !tui.Mode { pub fn create(allocator: std.mem.Allocator) !tui.Mode {
const mv = tui.current().mainview.dynamic_cast(mainview) orelse return error.NotFound; const mv = tui.mainview() orelse return error.NotFound;
const self: *Self = try allocator.create(Self); const self: *Self = try allocator.create(Self);
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,
.modal = try ModalBackground.create(*Self, allocator, tui.current().mainview, .{ .modal = try ModalBackground.create(*Self, allocator, tui.mainview_widget(), .{
.ctx = self, .ctx = self,
.on_click = mouse_palette_menu_cancel, .on_click = mouse_palette_menu_cancel,
}), }),
@ -68,7 +67,7 @@ pub fn Create(options: type) type {
.ctx = self, .ctx = self,
.label = options.label, .label = options.label,
}))).dynamic_cast(InputBox.State(*Self)) orelse unreachable, }))).dynamic_cast(InputBox.State(*Self)) orelse unreachable,
.view_rows = get_view_rows(tui.current().screen()), .view_rows = get_view_rows(tui.screen()),
.entries = std.ArrayList(Entry).init(allocator), .entries = std.ArrayList(Entry).init(allocator),
}; };
self.menu.scrollbar.?.style_factory = scrollbar_style; self.menu.scrollbar.?.style_factory = scrollbar_style;
@ -92,8 +91,8 @@ pub fn Create(options: type) type {
if (@hasDecl(options, "deinit")) if (@hasDecl(options, "deinit"))
options.deinit(self); options.deinit(self);
self.entries.deinit(); self.entries.deinit();
tui.current().message_filters.remove_ptr(self); tui.message_filters().remove_ptr(self);
if (tui.current().mainview.dynamic_cast(mainview)) |mv| { if (tui.mainview()) |mv| {
mv.floating_views.remove(self.menu.container_widget); mv.floating_views.remove(self.menu.container_widget);
mv.floating_views.remove(self.modal.widget()); mv.floating_views.remove(self.modal.widget());
} }
@ -160,7 +159,7 @@ pub fn Create(options: type) type {
} }
fn do_resize(self: *Self) void { fn do_resize(self: *Self) void {
const screen = tui.current().screen(); const screen = tui.screen();
const w = @min(self.longest, max_menu_width) + 2 + 1 + self.longest_hint; const w = @min(self.longest, max_menu_width) + 2 + 1 + self.longest_hint;
const x = if (screen.w > w) (screen.w - w) / 2 else 0; const x = if (screen.w > w) (screen.w - w) / 2 else 0;
self.view_rows = get_view_rows(screen); self.view_rows = get_view_rows(screen);
@ -246,7 +245,7 @@ pub fn Create(options: type) type {
while (i > 0) : (i -= 1) while (i > 0) : (i -= 1)
self.menu.select_down(); self.menu.select_down();
self.do_resize(); self.do_resize();
tui.current().refresh_hover(); tui.refresh_hover();
self.selection_updated(); self.selection_updated();
} }
} }

View file

@ -27,7 +27,7 @@ var previous_theme: ?[]const u8 = null;
pub fn load_entries(palette: *Type) !usize { pub fn load_entries(palette: *Type) !usize {
var longest_hint: usize = 0; var longest_hint: usize = 0;
var idx: usize = 0; var idx: usize = 0;
previous_theme = tui.current().theme.name; previous_theme = tui.theme().name;
for (Widget.themes) |theme| { for (Widget.themes) |theme| {
idx += 1; idx += 1;
(try palette.entries.addOne()).* = .{ (try palette.entries.addOne()).* = .{
@ -76,7 +76,7 @@ pub fn updated(palette: *Type, button_: ?*Type.ButtonState) !void {
} }
pub fn cancel(palette: *Type) !void { pub fn cancel(palette: *Type) !void {
if (previous_theme) |name_| if (!std.mem.eql(u8, name_, tui.current().theme.name)) { if (previous_theme) |name_| if (!std.mem.eql(u8, name_, tui.theme().name)) {
previous_theme = null; previous_theme = null;
tp.self_pid().send(.{ "cmd", "set_theme", .{name_} }) catch |e| palette.logger.err("theme_palette cancel", e); tp.self_pid().send(.{ "cmd", "set_theme", .{name_} }) catch |e| palette.logger.err("theme_palette cancel", e);
}; };

View file

@ -28,13 +28,13 @@ pub fn create(allocator: std.mem.Allocator, parent: Plane, event_handler: ?Event
.on_event = event_handler, .on_event = event_handler,
.tz = zeit.local(allocator, &env) catch |e| return tp.exit_error(e, @errorReturnTrace()), .tz = zeit.local(allocator, &env) catch |e| return tp.exit_error(e, @errorReturnTrace()),
}; };
try tui.current().message_filters.add(MessageFilter.bind(self, receive_tick)); try tui.message_filters().add(MessageFilter.bind(self, receive_tick));
self.update_tick_timer(.init); self.update_tick_timer(.init);
return Widget.to(self); return Widget.to(self);
} }
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
tui.current().message_filters.remove_ptr(self); tui.message_filters().remove_ptr(self);
if (self.tick_timer) |*t| { if (self.tick_timer) |*t| {
t.cancel() catch {}; t.cancel() catch {};
t.deinit(); t.deinit();

View file

@ -90,7 +90,7 @@ pub fn render(self: *Self, btn: *Button.State(Self), theme: *const Widget.Theme)
btn.plane.fill(" "); btn.plane.fill(" ");
btn.plane.home(); btn.plane.home();
} }
if (tui.current().mini_mode) |_| if (tui.mini_mode()) |_|
render_mini_mode(&btn.plane, theme) render_mini_mode(&btn.plane, theme)
else if (self.detailed) else if (self.detailed)
self.render_detailed(&btn.plane, theme) self.render_detailed(&btn.plane, theme)
@ -102,14 +102,13 @@ pub fn render(self: *Self, btn: *Button.State(Self), theme: *const Widget.Theme)
fn render_mini_mode(plane: *Plane, theme: *const Widget.Theme) void { fn render_mini_mode(plane: *Plane, theme: *const Widget.Theme) void {
plane.off_styles(style.italic); plane.off_styles(style.italic);
const tui_ = tui.current(); const mini_mode = tui.mini_mode() orelse return;
const mini_mode = tui_.mini_mode orelse return;
_ = plane.print(" {s}", .{mini_mode.text}) catch {}; _ = plane.print(" {s}", .{mini_mode.text}) catch {};
if (mini_mode.cursor) |cursor| { if (mini_mode.cursor) |cursor| {
const pos: c_int = @intCast(cursor); const pos: c_int = @intCast(cursor);
if (tui_.config.enable_terminal_cursor) { if (tui.config().enable_terminal_cursor) {
const y, const x = plane.rel_yx_to_abs(0, pos + 1); const y, const x = plane.rel_yx_to_abs(0, pos + 1);
tui_.rdr.cursor_enable(y, x, tui_.get_cursor_shape()) catch {}; tui.rdr().cursor_enable(y, x, tui.get_cursor_shape()) catch {};
} else { } else {
plane.cursor_move_yx(0, pos + 1) catch return; plane.cursor_move_yx(0, pos + 1) catch return;
var cell = plane.cell_init(); var cell = plane.cell_init();
@ -189,7 +188,7 @@ fn render_terminal_title(self: *Self) void {
if (std.mem.eql(u8, self.previous_title, new_title)) return; if (std.mem.eql(u8, self.previous_title, new_title)) return;
@memcpy(self.previous_title_buf[0..new_title.len], new_title); @memcpy(self.previous_title_buf[0..new_title.len], new_title);
self.previous_title = self.previous_title_buf[0..new_title.len]; self.previous_title = self.previous_title_buf[0..new_title.len];
tui.current().rdr.set_terminal_title(new_title); tui.rdr().set_terminal_title(new_title);
} }
pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message) error{Exit}!bool { pub fn receive(self: *Self, _: *Button.State(Self), _: tp.pid_ref, m: tp.message) error{Exit}!bool {

View file

@ -36,7 +36,7 @@ pub fn create(allocator: Allocator, parent: Plane, _: ?EventHandler) @import("wi
.plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent),
.wipe_after_frames = @divTrunc(frame_rate, 2), .wipe_after_frames = @divTrunc(frame_rate, 2),
}; };
try tui.current().input_listeners.add(EventHandler.bind(self, listen)); try tui.input_listeners().add(EventHandler.bind(self, listen));
return self.widget(); return self.widget();
} }
@ -45,7 +45,7 @@ pub fn widget(self: *Self) Widget {
} }
pub fn deinit(self: *Self, allocator: Allocator) void { pub fn deinit(self: *Self, allocator: Allocator) void {
tui.current().input_listeners.remove_ptr(self); tui.input_listeners().remove_ptr(self);
self.plane.deinit(); self.plane.deinit();
allocator.destroy(self); allocator.destroy(self);
} }
@ -171,7 +171,7 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
return true; return true;
} }
if (try m.match(.{ "H", tp.extract(&self.hover) })) { if (try m.match(.{ "H", tp.extract(&self.hover) })) {
tui.current().rdr.request_mouse_cursor_pointer(self.hover); tui.rdr().request_mouse_cursor_pointer(self.hover);
return true; return true;
} }

View file

@ -34,7 +34,7 @@ pub fn create(allocator: std.mem.Allocator, parent: Plane, event_handler: ?Event
.on_event = event_handler, .on_event = event_handler,
}; };
logview.init(allocator); logview.init(allocator);
try tui.current().message_filters.add(MessageFilter.bind(self, receive_log)); try tui.message_filters().add(MessageFilter.bind(self, receive_log));
try log.subscribe(); try log.subscribe();
return Widget.to(self); return Widget.to(self);
} }
@ -47,7 +47,7 @@ pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
} }
self.msg.deinit(); self.msg.deinit();
log.unsubscribe() catch {}; log.unsubscribe() catch {};
tui.current().message_filters.remove_ptr(self); tui.message_filters().remove_ptr(self);
self.plane.deinit(); self.plane.deinit();
allocator.destroy(self); allocator.destroy(self);
} }

View file

@ -33,11 +33,11 @@ pub fn layout(_: *void, btn: *Button.State(void)) Widget.Layout {
} }
fn is_mini_mode() bool { fn is_mini_mode() bool {
return tui.current().mini_mode != null; return tui.mini_mode() != null;
} }
fn is_overlay_mode() bool { fn is_overlay_mode() bool {
return tui.current().input_mode_outer != null; return tui.input_mode_outer() != null;
} }
pub fn render(_: *void, self: *Button.State(void), theme: *const Widget.Theme) bool { pub fn render(_: *void, self: *Button.State(void), theme: *const Widget.Theme) bool {

View file

@ -24,7 +24,7 @@ pub fn create(allocator: Allocator, parent: Plane, _: ?EventHandler) @import("wi
self.* = .{ self.* = .{
.plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent), .plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent),
}; };
try tui.current().input_listeners.add(EventHandler.bind(self, listen)); try tui.input_listeners().add(EventHandler.bind(self, listen));
return self.widget(); return self.widget();
} }
@ -33,7 +33,7 @@ pub fn widget(self: *Self) Widget {
} }
pub fn deinit(self: *Self, allocator: Allocator) void { pub fn deinit(self: *Self, allocator: Allocator) void {
tui.current().input_listeners.remove_ptr(self); tui.input_listeners().remove_ptr(self);
self.plane.deinit(); self.plane.deinit();
allocator.destroy(self); allocator.destroy(self);
} }

View file

@ -3,7 +3,6 @@ const build_options = @import("build_options");
const tp = @import("thespian"); const tp = @import("thespian");
const cbor = @import("cbor"); const cbor = @import("cbor");
const log = @import("log"); const log = @import("log");
const config = @import("config");
const project_manager = @import("project_manager"); const project_manager = @import("project_manager");
const root = @import("root"); const root = @import("root");
const tracy = @import("tracy"); const tracy = @import("tracy");
@ -16,19 +15,19 @@ const keybind = @import("keybind");
const Widget = @import("Widget.zig"); const Widget = @import("Widget.zig");
const MessageFilter = @import("MessageFilter.zig"); const MessageFilter = @import("MessageFilter.zig");
const mainview = @import("mainview.zig"); const MainView = @import("mainview.zig");
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
allocator: Allocator, allocator: Allocator,
rdr: renderer, rdr: renderer,
config: config, config: @import("config"),
frame_time: usize, // in microseconds frame_time: usize, // in microseconds
frame_clock: tp.metronome, frame_clock: tp.metronome,
frame_clock_running: bool = false, frame_clock_running: bool = false,
frame_last_time: i64 = 0, frame_last_time: i64 = 0,
receiver: Receiver, receiver: Receiver,
mainview: Widget, mainview: ?Widget = null,
message_filters: MessageFilter.List, message_filters: MessageFilter.List,
input_mode: ?Mode = null, input_mode: ?Mode = null,
delayed_init_done: bool = false, delayed_init_done: bool = false,
@ -55,7 +54,7 @@ keepalive_timer: ?tp.Cancellable = null,
mouse_idle_timer: ?tp.Cancellable = null, mouse_idle_timer: ?tp.Cancellable = null,
default_cursor: keybind.CursorShape = .default, default_cursor: keybind.CursorShape = .default,
fontface: []const u8 = "", fontface: []const u8 = "",
fontfaces: ?std.ArrayList([]const u8) = null, fontfaces: std.ArrayListUnmanaged([]const u8) = .{},
enable_mouse_idle_timer: bool = false, enable_mouse_idle_timer: bool = false,
const keepalive = std.time.us_per_day * 365; // one year const keepalive = std.time.us_per_day * 365; // one year
@ -84,13 +83,11 @@ fn start(args: StartArgs) tp.result {
} }
fn init(allocator: Allocator) !*Self { fn init(allocator: Allocator) !*Self {
var self = try allocator.create(Self); var conf, const conf_bufs = root.read_config(@import("config"), allocator);
var conf, const conf_bufs = root.read_config(config, allocator);
defer root.free_config(allocator, conf_bufs); defer root.free_config(allocator, conf_bufs);
const theme = get_theme_by_name(conf.theme) orelse get_theme_by_name("dark_modern") orelse return tp.exit("unknown theme"); const theme_ = get_theme_by_name(conf.theme) orelse get_theme_by_name("dark_modern") orelse return tp.exit("unknown theme");
conf.theme = theme.name; conf.theme = theme_.name;
conf.whitespace_mode = try allocator.dupe(u8, conf.whitespace_mode); conf.whitespace_mode = try allocator.dupe(u8, conf.whitespace_mode);
conf.input_mode = try allocator.dupe(u8, conf.input_mode); conf.input_mode = try allocator.dupe(u8, conf.input_mode);
conf.top_bar = try allocator.dupe(u8, conf.top_bar); conf.top_bar = try allocator.dupe(u8, conf.top_bar);
@ -106,6 +103,7 @@ fn init(allocator: Allocator) !*Self {
const frame_time = std.time.us_per_s / conf.frame_rate; const frame_time = std.time.us_per_s / conf.frame_rate;
const frame_clock = try tp.metronome.init(frame_time); const frame_clock = try tp.metronome.init(frame_time);
var self = try allocator.create(Self);
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,
.config = conf, .config = conf,
@ -114,14 +112,13 @@ fn init(allocator: Allocator) !*Self {
.frame_clock = frame_clock, .frame_clock = frame_clock,
.frame_clock_running = true, .frame_clock_running = true,
.receiver = Receiver.init(receive, self), .receiver = Receiver.init(receive, self),
.mainview = undefined,
.message_filters = MessageFilter.List.init(allocator), .message_filters = MessageFilter.List.init(allocator),
.input_listeners = EventHandler.List.init(allocator), .input_listeners = EventHandler.List.init(allocator),
.logger = log.logger("tui"), .logger = log.logger("tui"),
.init_timer = if (build_options.gui) null else try tp.timeout.init_ms(init_delay, tp.message.fmt( .init_timer = if (build_options.gui) null else try tp.timeout.init_ms(init_delay, tp.message.fmt(
.{"init"}, .{"init"},
)), )),
.theme = theme, .theme = theme_,
.no_sleep = tp.env.get().is("no-sleep"), .no_sleep = tp.env.get().is("no-sleep"),
}; };
instance_ = self; instance_ = self;
@ -147,11 +144,11 @@ fn init(allocator: Allocator) !*Self {
try self.listen_sigwinch(); try self.listen_sigwinch();
}, },
} }
self.mainview = try mainview.create(allocator); self.mainview = try MainView.create(allocator);
self.resize(); resize();
self.set_terminal_style(); self.set_terminal_style();
try self.rdr.render(); try self.rdr.render();
try self.save_config(); try save_config();
try self.init_input_namespace(); try self.init_input_namespace();
if (tp.env.get().is("restore-session")) { if (tp.env.get().is("restore-session")) {
command.executeName("restore_session", .{}) catch |e| self.logger.err("restore_session", e); command.executeName("restore_session", .{}) catch |e| self.logger.err("restore_session", e);
@ -168,7 +165,7 @@ fn init_input_namespace(self: *Self) !void {
self.logger.print_err("keybind", "unknown mode {s}", .{namespace_name}); self.logger.print_err("keybind", "unknown mode {s}", .{namespace_name});
try keybind.set_namespace("flow"); try keybind.set_namespace("flow");
self.config.input_mode = "flow"; self.config.input_mode = "flow";
try self.save_config(); try save_config();
}; };
} }
@ -204,7 +201,7 @@ fn deinit(self: *Self) void {
self.delayed_init_input_mode = null; self.delayed_init_input_mode = null;
} }
self.commands.deinit(); self.commands.deinit();
self.mainview.deinit(self.allocator); if (self.mainview) |*mv| mv.deinit(self.allocator);
self.message_filters.deinit(); self.message_filters.deinit();
self.input_listeners.deinit(); self.input_listeners.deinit();
if (self.frame_clock_running) if (self.frame_clock_running)
@ -296,7 +293,7 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void {
} }
if (try m.match(.{"restart"})) { if (try m.match(.{"restart"})) {
_ = try self.mainview.msg(.{"write_restore_info"}); if (mainview()) |mv| mv.write_restore_info();
project_manager.shutdown(); project_manager.shutdown();
self.final_exit = "restart"; self.final_exit = "restart";
return; return;
@ -310,8 +307,8 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void {
}; };
if (try m.match(.{"resize"})) { if (try m.match(.{"resize"})) {
self.resize(); resize();
const box = self.screen(); const box = screen();
message("{d}x{d}", .{ box.w, box.h }); message("{d}x{d}", .{ box.w, box.h });
return; return;
} }
@ -391,20 +388,16 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void {
return self.enter_overlay_mode(@import("mode/overlay/fontface_palette.zig").Type); return self.enter_overlay_mode(@import("mode/overlay/fontface_palette.zig").Type);
} }
var fontface: []const u8 = undefined; var fontface_: []const u8 = undefined;
if (try m.match(.{ "fontface", "current", tp.extract(&fontface) })) { if (try m.match(.{ "fontface", "current", tp.extract(&fontface_) })) {
if (self.fontface.len > 0) self.allocator.free(self.fontface); if (self.fontface.len > 0) self.allocator.free(self.fontface);
self.fontface = ""; self.fontface = "";
self.fontface = try self.allocator.dupe(u8, fontface); self.fontface = try self.allocator.dupe(u8, fontface_);
return; return;
} }
if (try m.match(.{ "fontface", tp.extract(&fontface) })) { if (try m.match(.{ "fontface", tp.extract(&fontface_) })) {
var fontfaces = if (self.fontfaces) |*p| p else blk: { try self.fontfaces.append(self.allocator, try self.allocator.dupe(u8, fontface_));
self.fontfaces = std.ArrayList([]const u8).init(self.allocator);
break :blk &self.fontfaces.?;
};
try fontfaces.append(try self.allocator.dupe(u8, fontface));
return; return;
} }
@ -427,14 +420,14 @@ fn render(self: *Self) void {
{ {
const frame = tracy.initZone(@src(), .{ .name = "tui update" }); const frame = tracy.initZone(@src(), .{ .name = "tui update" });
defer frame.deinit(); defer frame.deinit();
self.mainview.update(); if (self.mainview) |mv| mv.update();
} }
const more = ret: { const more = ret: {
const frame = tracy.initZone(@src(), .{ .name = "tui render" }); const frame = tracy.initZone(@src(), .{ .name = "tui render" });
defer frame.deinit(); defer frame.deinit();
self.rdr.stdplane().erase(); self.rdr.stdplane().erase();
break :ret self.mainview.render(&self.theme); break :ret if (self.mainview) |mv| mv.render(&self.theme) else false;
}; };
{ {
@ -543,7 +536,7 @@ fn find_coord_widget(self: *Self, y: usize, x: usize) ?*Widget {
} }
}; };
var ctx: Ctx = .{ .y = y, .x = x }; var ctx: Ctx = .{ .y = y, .x = x };
_ = self.mainview.walk(&ctx, Ctx.find); if (self.mainview) |*mv| _ = mv.walk(&ctx, Ctx.find);
return ctx.widget; return ctx.widget;
} }
@ -560,7 +553,7 @@ fn is_live_widget_ptr(self: *Self, w_: *Widget) bool {
} }
}; };
var ctx: Ctx = .{ .w = w_ }; var ctx: Ctx = .{ .w = w_ };
return self.mainview.walk(&ctx, Ctx.find); return if (self.mainview) |*mv| mv.walk(&ctx, Ctx.find) else false;
} }
fn send_widgets(self: *Self, from: tp.pid_ref, m: tp.message) error{Exit}!bool { fn send_widgets(self: *Self, from: tp.pid_ref, m: tp.message) error{Exit}!bool {
@ -569,8 +562,10 @@ fn send_widgets(self: *Self, from: tp.pid_ref, m: tp.message) error{Exit}!bool {
tp.trace(tp.channel.widget, m); tp.trace(tp.channel.widget, m);
return if (self.keyboard_focus) |w| return if (self.keyboard_focus) |w|
w.send(from, m) w.send(from, m)
else if (self.mainview) |mv|
mv.send(from, m)
else else
self.mainview.send(from, m); false;
} }
fn send_mouse(self: *Self, y: c_int, x: c_int, from: tp.pid_ref, m: tp.message) tp.result { fn send_mouse(self: *Self, y: c_int, x: c_int, from: tp.pid_ref, m: tp.message) tp.result {
@ -623,16 +618,19 @@ fn clear_hover_focus(self: *Self) tp.result {
self.hover_focus = null; self.hover_focus = null;
} }
pub fn refresh_hover(self: *Self) void { pub fn refresh_hover() void {
const self = current();
self.clear_hover_focus() catch return; self.clear_hover_focus() catch return;
_ = self.update_hover(self.last_hover_y, self.last_hover_x) catch {}; _ = self.update_hover(self.last_hover_y, self.last_hover_x) catch {};
} }
pub fn save_config(self: *const Self) !void { pub fn save_config() !void {
const self = current();
try root.write_config(self.config, self.allocator); try root.write_config(self.config, self.allocator);
} }
pub fn is_mainview_focused(self: *const Self) bool { pub fn is_mainview_focused() bool {
const self = current();
return self.mini_mode == null and self.input_mode_outer == null; return self.mini_mode == null and self.input_mode_outer == null;
} }
@ -643,7 +641,7 @@ fn enter_overlay_mode(self: *Self, mode: type) command.Result {
if (self.input_mode_outer) |_| try cmds.exit_overlay_mode(self, .{}); if (self.input_mode_outer) |_| try cmds.exit_overlay_mode(self, .{});
self.input_mode_outer = self.input_mode; self.input_mode_outer = self.input_mode;
self.input_mode = try mode.create(self.allocator); self.input_mode = try mode.create(self.allocator);
self.refresh_hover(); refresh_hover();
} }
fn get_input_mode(self: *Self, mode_name: []const u8) !Mode { fn get_input_mode(self: *Self, mode_name: []const u8) !Mode {
@ -703,7 +701,7 @@ const cmds = struct {
self.config.theme = self.theme.name; self.config.theme = self.theme.name;
self.set_terminal_style(); self.set_terminal_style();
self.logger.print("theme: {s}", .{self.theme.description}); self.logger.print("theme: {s}", .{self.theme.description});
try self.save_config(); try save_config();
} }
pub const set_theme_meta = .{ .arguments = &.{.string} }; pub const set_theme_meta = .{ .arguments = &.{.string} };
@ -712,7 +710,7 @@ const cmds = struct {
self.config.theme = self.theme.name; self.config.theme = self.theme.name;
self.set_terminal_style(); self.set_terminal_style();
self.logger.print("theme: {s}", .{self.theme.description}); self.logger.print("theme: {s}", .{self.theme.description});
try self.save_config(); try save_config();
} }
pub const theme_next_meta = .{ .description = "Switch to next color theme" }; pub const theme_next_meta = .{ .description = "Switch to next color theme" };
@ -721,7 +719,7 @@ const cmds = struct {
self.config.theme = self.theme.name; self.config.theme = self.theme.name;
self.set_terminal_style(); self.set_terminal_style();
self.logger.print("theme: {s}", .{self.theme.description}); self.logger.print("theme: {s}", .{self.theme.description});
try self.save_config(); try save_config();
} }
pub const theme_prev_meta = .{ .description = "Switch to previous color theme" }; pub const theme_prev_meta = .{ .description = "Switch to previous color theme" };
@ -740,7 +738,7 @@ const cmds = struct {
"full" "full"
else else
"none"; "none";
try self.save_config(); try save_config();
var buf: [32]u8 = undefined; var buf: [32]u8 = undefined;
const m = try tp.message.fmtbuf(&buf, .{ "whitespace_mode", self.config.whitespace_mode }); const m = try tp.message.fmtbuf(&buf, .{ "whitespace_mode", self.config.whitespace_mode });
_ = try self.send_widgets(tp.self_pid(), m); _ = try self.send_widgets(tp.self_pid(), m);
@ -764,7 +762,7 @@ const cmds = struct {
found = true; found = true;
} else try self.allocator.dupe(u8, namespaces[0]); } else try self.allocator.dupe(u8, namespaces[0]);
try self.save_config(); try save_config();
self.logger.print("input mode {s}", .{self.config.input_mode}); self.logger.print("input mode {s}", .{self.config.input_mode});
try keybind.set_namespace(self.config.input_mode); try keybind.set_namespace(self.config.input_mode);
return self.refresh_input_mode(); return self.refresh_input_mode();
@ -842,7 +840,7 @@ const cmds = struct {
if (self.input_mode) |*mode| mode.deinit(); if (self.input_mode) |*mode| mode.deinit();
self.input_mode = self.input_mode_outer; self.input_mode = self.input_mode_outer;
self.input_mode_outer = null; self.input_mode_outer = null;
self.refresh_hover(); refresh_hover();
} }
pub const exit_overlay_mode_meta = .{}; pub const exit_overlay_mode_meta = .{};
@ -879,13 +877,13 @@ const cmds = struct {
fn enter_mini_mode(self: *Self, comptime mode: anytype, ctx: Ctx) !void { fn enter_mini_mode(self: *Self, comptime mode: anytype, ctx: Ctx) !void {
command.executeName("disable_fast_scroll", .{}) catch {}; command.executeName("disable_fast_scroll", .{}) catch {};
command.executeName("disable_jump_mode", .{}) catch {}; command.executeName("disable_jump_mode", .{}) catch {};
const input_mode, const mini_mode = try mode.create(self.allocator, ctx); const input_mode_, const mini_mode_ = try mode.create(self.allocator, ctx);
if (self.mini_mode) |_| try exit_mini_mode(self, .{}); if (self.mini_mode) |_| try exit_mini_mode(self, .{});
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{}); if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
if (self.input_mode_outer != null) @panic("exit_overlay_mode failed"); if (self.input_mode_outer != null) @panic("exit_overlay_mode failed");
self.input_mode_outer = self.input_mode; self.input_mode_outer = self.input_mode;
self.input_mode = input_mode; self.input_mode = input_mode_;
self.mini_mode = mini_mode; self.mini_mode = mini_mode_;
} }
pub fn exit_mini_mode(self: *Self, _: Ctx) Result { pub fn exit_mini_mode(self: *Self, _: Ctx) Result {
@ -980,12 +978,52 @@ pub const KeybindHints = keybind.KeybindHints;
threadlocal var instance_: ?*Self = null; threadlocal var instance_: ?*Self = null;
pub fn current() *Self { fn current() *Self {
return instance_ orelse @panic("tui call out of context"); return instance_ orelse @panic("tui call out of context");
} }
pub fn rdr() *renderer {
return &current().rdr;
}
pub fn message_filters() *MessageFilter.List {
return &current().message_filters;
}
pub fn input_listeners() *EventHandler.List {
return &current().input_listeners;
}
pub fn input_mode() ?*Mode {
return if (current().input_mode) |*p| p else null;
}
pub fn input_mode_outer() ?*Mode {
return if (current().input_mode_outer) |*p| p else null;
}
pub fn mini_mode() ?*MiniMode {
return if (current().mini_mode) |*p| p else null;
}
pub fn config() *const @import("config") {
return &current().config;
}
pub fn config_mut() *@import("config") {
return &current().config;
}
pub fn mainview() ?*MainView {
return if (current().mainview) |*mv| mv.dynamic_cast(MainView) else null;
}
pub fn mainview_widget() Widget {
return current().mainview orelse @panic("tui main view not found");
}
pub fn get_active_editor() ?*@import("editor.zig").Editor { pub fn get_active_editor() ?*@import("editor.zig").Editor {
if (current().mainview.dynamic_cast(mainview)) |mv_| if (mv_.get_active_editor()) |editor| if (mainview()) |mv_| if (mv_.get_active_editor()) |editor|
return editor; return editor;
return null; return null;
} }
@ -997,7 +1035,7 @@ pub fn get_active_selection(allocator: std.mem.Allocator) ?[]u8 {
} }
pub fn get_buffer_manager() ?*@import("Buffer").Manager { pub fn get_buffer_manager() ?*@import("Buffer").Manager {
return if (current().mainview.dynamic_cast(mainview)) |mv_| &mv_.buffer_manager else null; return if (mainview()) |mv| &mv.buffer_manager else null;
} }
fn context_check() void { fn context_check() void {
@ -1031,9 +1069,9 @@ pub fn need_render() void {
} }
} }
pub fn resize(self: *Self) void { pub fn resize() void {
self.mainview.resize(self.screen()); mainview_widget().resize(screen());
self.refresh_hover(); refresh_hover();
need_render(); need_render();
} }
@ -1053,24 +1091,36 @@ pub fn egc_last(egcs: []const u8) []const u8 {
return plane().egc_last(egcs); return plane().egc_last(egcs);
} }
pub fn screen(self: *Self) Widget.Box { pub fn screen() Widget.Box {
return Widget.Box.from(self.rdr.stdplane()); return Widget.Box.from(plane());
}
pub fn fontface() []const u8 {
return current().fontface;
}
pub fn fontfaces(allocator: std.mem.Allocator) error{OutOfMemory}![][]const u8 {
return current().fontfaces.toOwnedSlice(allocator);
}
pub fn theme() *const Widget.Theme {
return &current().theme;
} }
pub fn get_theme_by_name(name: []const u8) ?Widget.Theme { pub fn get_theme_by_name(name: []const u8) ?Widget.Theme {
for (Widget.themes) |theme| { for (Widget.themes) |theme_| {
if (std.mem.eql(u8, theme.name, name)) if (std.mem.eql(u8, theme_.name, name))
return theme; return theme_;
} }
return null; return null;
} }
pub fn get_next_theme_by_name(name: []const u8) Widget.Theme { pub fn get_next_theme_by_name(name: []const u8) Widget.Theme {
var next = false; var next = false;
for (Widget.themes) |theme| { for (Widget.themes) |theme_| {
if (next) if (next)
return theme; return theme_;
if (std.mem.eql(u8, theme.name, name)) if (std.mem.eql(u8, theme_.name, name))
next = true; next = true;
} }
return Widget.themes[0]; return Widget.themes[0];
@ -1078,24 +1128,24 @@ pub fn get_next_theme_by_name(name: []const u8) Widget.Theme {
pub fn get_prev_theme_by_name(name: []const u8) Widget.Theme { pub fn get_prev_theme_by_name(name: []const u8) Widget.Theme {
var prev: ?Widget.Theme = null; var prev: ?Widget.Theme = null;
for (Widget.themes) |theme| { for (Widget.themes) |theme_| {
if (std.mem.eql(u8, theme.name, name)) if (std.mem.eql(u8, theme_.name, name))
return prev orelse Widget.themes[Widget.themes.len - 1]; return prev orelse Widget.themes[Widget.themes.len - 1];
prev = theme; prev = theme_;
} }
return Widget.themes[Widget.themes.len - 1]; return Widget.themes[Widget.themes.len - 1];
} }
pub fn find_scope_style(theme: *const Widget.Theme, scope: []const u8) ?Widget.Theme.Token { pub fn find_scope_style(theme_: *const Widget.Theme, scope: []const u8) ?Widget.Theme.Token {
return if (find_scope_fallback(scope)) |tm_scope| return if (find_scope_fallback(scope)) |tm_scope|
scope_to_theme_token(theme, tm_scope) orelse scope_to_theme_token(theme_, tm_scope) orelse
scope_to_theme_token(theme, scope) scope_to_theme_token(theme_, scope)
else else
scope_to_theme_token(theme, scope); scope_to_theme_token(theme_, scope);
} }
fn scope_to_theme_token(theme: *const Widget.Theme, document_scope: []const u8) ?Widget.Theme.Token { fn scope_to_theme_token(theme_: *const Widget.Theme, document_scope: []const u8) ?Widget.Theme.Token {
var idx = theme.tokens.len - 1; var idx = theme_.tokens.len - 1;
var matched: ?Widget.Theme.Token = null; var matched: ?Widget.Theme.Token = null;
var done = false; var done = false;
while (!done) : (if (idx == 0) { while (!done) : (if (idx == 0) {
@ -1103,7 +1153,7 @@ fn scope_to_theme_token(theme: *const Widget.Theme, document_scope: []const u8)
} else { } else {
idx -= 1; idx -= 1;
}) { }) {
const token = theme.tokens[idx]; const token = theme_.tokens[idx];
const theme_scope = Widget.scopes[token.id]; const theme_scope = Widget.scopes[token.id];
const last_matched_scope = if (matched) |tok| Widget.scopes[tok.id] else ""; const last_matched_scope = if (matched) |tok| Widget.scopes[tok.id] else "";
if (theme_scope.len < last_matched_scope.len) continue; if (theme_scope.len < last_matched_scope.len) continue;
@ -1178,7 +1228,8 @@ fn set_terminal_style(self: *Self) void {
} }
} }
pub fn get_cursor_shape(self: *Self) renderer.CursorShape { pub fn get_cursor_shape() renderer.CursorShape {
const self = current();
const shape = if (self.input_mode) |mode| mode.cursor_shape orelse self.default_cursor else self.default_cursor; const shape = if (self.input_mode) |mode| mode.cursor_shape orelse self.default_cursor else self.default_cursor;
return switch (shape) { return switch (shape) {
.default => .default, .default => .default,
@ -1191,15 +1242,15 @@ pub fn get_cursor_shape(self: *Self) renderer.CursorShape {
}; };
} }
pub fn is_cursor_beam(self: *Self) bool { pub fn is_cursor_beam() bool {
return switch (self.get_cursor_shape()) { return switch (get_cursor_shape()) {
.beam, .beam_blink => true, .beam, .beam_blink => true,
else => false, else => false,
}; };
} }
pub fn get_selection_style(self: *Self) @import("Buffer").Selection.Style { pub fn get_selection_style() @import("Buffer").Selection.Style {
return if (self.input_mode) |mode| mode.selection_style else .normal; return if (current().input_mode) |mode| mode.selection_style else .normal;
} }
pub fn message(comptime fmt: anytype, args: anytype) void { pub fn message(comptime fmt: anytype, args: anytype) void {