From 4f68e692d19eaec6f9ba38a27286c9c6580ce94b Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 26 Nov 2025 19:12:27 +0100 Subject: [PATCH 1/6] refactor: add a lot of logging during change_project --- src/tui/mainview.zig | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index 131e558..19b939f 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -392,6 +392,8 @@ const cmds = struct { pub const close_project_meta: Meta = .{ .arguments = &.{.string} }; pub fn change_project(self: *Self, ctx: Ctx) Result { + const logger = log.logger("change_project"); + defer logger.deinit(); var project_dir: []const u8 = undefined; if (!try ctx.args.match(.{tp.extract(&project_dir)})) return; @@ -406,6 +408,7 @@ const cmds = struct { var state_al = state_writer.toArrayList(); const state = state_al.toManaged(self.allocator); try project_manager.store_state(old_project, state); + logger.print("stored project state for: {s} ({d} bytes)", .{ old_project, state.items.len }); } const project_state = try project_manager.open(project_dir); @@ -420,12 +423,15 @@ const cmds = struct { const project = tp.env.get().str("project"); tui.rdr().set_terminal_working_directory(project); - if (project_state) |state| try self.restore_state(state); + if (project_state) |state| { + logger.print("restoring {d} bytes of project state for: {s}", .{ state.len, project }); + try self.restore_state(state); + } else { + logger.print("no project state to restore for: {s}", .{project}); + } if (self.top_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" }); if (self.bottom_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" }); - if (project_state == null) - tp.self_pid().send(.{ "cmd", "open_recent" }) catch return; } pub const change_project_meta: Meta = .{ .arguments = &.{.string} }; @@ -436,6 +442,8 @@ const cmds = struct { pub const navigate_split_vertical_meta: Meta = .{ .arguments = &.{.object} }; pub fn navigate(self: *Self, ctx: Ctx) Result { + const logger = log.logger("navigate"); + defer logger.deinit(); tui.reset_drag_context(); const frame = tracy.initZone(@src(), .{ .name = "navigate" }); defer frame.deinit(); @@ -518,10 +526,12 @@ const cmds = struct { .path = try self.allocator.dupe(u8, f), .goto_args = try self.allocator.dupe(u8, goto_args), }; + logger.print("navigating to: {s} with restore_last_cursor_position", .{f}); try project_manager.get_mru_position(self.allocator, f, ctx_); return; } + logger.print("navigating to: {s}", .{f}); return cmds.navigate_complete(self, same_file, f, goto_args, line, column, offset); } @@ -1682,11 +1692,19 @@ fn restore_state(self: *Self, state: []const u8) !void { } fn extract_state(self: *Self, iter: *[]const u8) !void { + const logger = log.logger("extract_state"); + defer logger.deinit(); tp.trace(tp.channel.debug, .{ "mainview", "extract" }); var editor_file_path: ?[]const u8 = undefined; - if (!try cbor.matchValue(iter, cbor.extract(&editor_file_path))) return error.MatchFilePathFailed; + var prev_len = iter.len; + if (!try cbor.matchValue(iter, cbor.extract(&editor_file_path))) { + logger.print("restore editor_file_path failed", .{}); + return error.MatchFilePathFailed; + } + logger.print("restored editor_file_path: {s} ({d} bytes)", .{ editor_file_path orelse "(null)", prev_len - iter.len }); tui.clipboard_clear_all(); + prev_len = iter.len; var len = try cbor.decodeArrayHeader(iter); var prev_group: usize = 0; const clipboard_allocator = tui.clipboard_allocator(); @@ -1701,16 +1719,18 @@ fn extract_state(self: *Self, iter: *[]const u8) !void { prev_group = group; tui.clipboard_add_chunk(try clipboard_allocator.dupe(u8, text)); } + logger.print("restored clipboard ({d} bytes)", .{prev_len - iter.len}); + prev_len = iter.len; try self.buffer_manager.extract_state(iter); + logger.print("restored buffer manager ({d} bytes)", .{prev_len - iter.len}); + prev_len = iter.len; if (self.widgets.get("tabs")) |tabs_widget| if (tabs_widget.dynamic_cast(@import("status/tabs.zig").TabBar)) |tabs| - tabs.extract_state(iter) catch |e| { - const logger = log.logger("mainview"); - defer logger.deinit(); + tabs.extract_state(iter) catch |e| logger.print_err("mainview", "failed to restore tabs: {}", .{e}); - }; + logger.print("restored tabs ({d} bytes)", .{prev_len - iter.len}); const buffers = try self.buffer_manager.list_unordered(self.allocator); defer self.allocator.free(buffers); From 335f1bedab2bfad8874cf0cf24ce60e7d8a73ea7 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 26 Nov 2025 19:13:05 +0100 Subject: [PATCH 2/6] fix: some minor typos --- src/tui/mode/overlay/command_palette.zig | 4 ++-- src/tui/mode/overlay/list_all_commands_palette.zig | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tui/mode/overlay/command_palette.zig b/src/tui/mode/overlay/command_palette.zig index cd1ef34..306a53b 100644 --- a/src/tui/mode/overlay/command_palette.zig +++ b/src/tui/mode/overlay/command_palette.zig @@ -63,8 +63,8 @@ fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Pos) void { cbor.skipValue(&iter) catch break; if (!(cbor.matchValue(&iter, cbor.extract(&command_id)) catch false)) return; update_used_time(menu.*.opts.ctx, command_id); - tp.self_pid().send(.{ "cmd", "exit_overlay_mode" }) catch |e| menu.*.opts.ctx.logger.err("navigate", e); - tp.self_pid().send(.{ "cmd", command_id, .{} }) catch |e| menu.*.opts.ctx.logger.err("navigate", e); + tp.self_pid().send(.{ "cmd", "exit_overlay_mode" }) catch |e| menu.*.opts.ctx.logger.err("command_palette", e); + tp.self_pid().send(.{ "cmd", command_id, .{} }) catch |e| menu.*.opts.ctx.logger.err("command_palette", e); } fn sort_by_used_time(palette: *Type) void { diff --git a/src/tui/mode/overlay/list_all_commands_palette.zig b/src/tui/mode/overlay/list_all_commands_palette.zig index 9052685..b8185ef 100644 --- a/src/tui/mode/overlay/list_all_commands_palette.zig +++ b/src/tui/mode/overlay/list_all_commands_palette.zig @@ -79,6 +79,6 @@ fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Pos) void { while (len > 0) : (len -= 1) cbor.skipValue(&iter) catch break; if (!(cbor.matchValue(&iter, cbor.extract(&command_id)) catch false)) return; - tp.self_pid().send(.{ "cmd", "exit_overlay_mode" }) catch |e| menu.*.opts.ctx.logger.err("navigate", e); + tp.self_pid().send(.{ "cmd", "exit_overlay_mode" }) catch |e| menu.*.opts.ctx.logger.err("command_palette", e); tp.self_pid().send(.{ "cmd", "paste", .{command.get_name(command_id) orelse return} }) catch {}; } From 008950255b472e735c0c5af2bb3f289c673aeb29 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 26 Nov 2025 19:20:14 +0100 Subject: [PATCH 3/6] fix: don't respond to editor events in mainview during project switch --- src/tui/mainview.zig | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index 19b939f..697fc24 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -58,6 +58,7 @@ file_list_type: FileListType = .find_in_files, panel_height: ?usize = null, symbols: std.ArrayListUnmanaged(u8) = .empty, symbols_complete: bool = true, +closing_project: bool = false, const FileListType = enum { diagnostics, @@ -413,13 +414,17 @@ const cmds = struct { const project_state = try project_manager.open(project_dir); - try self.close_all_editors(); - self.delete_all_buffers(); - self.clear_find_in_files_results(.diagnostics); - if (self.file_list_type == .diagnostics and self.is_panel_view_showing(filelist_view)) - try self.toggle_panel_view(filelist_view, false); - self.buffer_manager.deinit(); - self.buffer_manager = Buffer.Manager.init(self.allocator); + { + self.closing_project = true; + defer self.closing_project = false; + try self.close_all_editors(); + self.delete_all_buffers(); + self.clear_find_in_files_results(.diagnostics); + if (self.file_list_type == .diagnostics and self.is_panel_view_showing(filelist_view)) + try self.toggle_panel_view(filelist_view, false); + self.buffer_manager.deinit(); + self.buffer_manager = Buffer.Manager.init(self.allocator); + } const project = tp.env.get().str("project"); tui.rdr().set_terminal_working_directory(project); @@ -1416,10 +1421,12 @@ pub fn handle_editor_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result return self.location_update(m); if (try m.match(.{ "E", "close" })) { - if (self.get_next_mru_buffer(.non_hidden)) |file_path| - self.show_file_async(file_path) - else - self.show_home_async(); + if (!self.closing_project) { + if (self.get_next_mru_buffer(.non_hidden)) |file_path| + self.show_file_async(file_path) + else + self.show_home_async(); + } else self.show_home_async(); self.active_editor = null; return; } From 198ee29abec42ca10a246c6d299801cd70d5e35c Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 26 Nov 2025 19:20:46 +0100 Subject: [PATCH 4/6] refactor: remove verbose log messages in mainview --- src/tui/mainview.zig | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index 697fc24..322d1eb 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -447,8 +447,6 @@ const cmds = struct { pub const navigate_split_vertical_meta: Meta = .{ .arguments = &.{.object} }; pub fn navigate(self: *Self, ctx: Ctx) Result { - const logger = log.logger("navigate"); - defer logger.deinit(); tui.reset_drag_context(); const frame = tracy.initZone(@src(), .{ .name = "navigate" }); defer frame.deinit(); @@ -531,12 +529,10 @@ const cmds = struct { .path = try self.allocator.dupe(u8, f), .goto_args = try self.allocator.dupe(u8, goto_args), }; - logger.print("navigating to: {s} with restore_last_cursor_position", .{f}); try project_manager.get_mru_position(self.allocator, f, ctx_); return; } - logger.print("navigating to: {s}", .{f}); return cmds.navigate_complete(self, same_file, f, goto_args, line, column, offset); } From 7dcde628ac7717295f75f4051cfe52b69840d50c Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 26 Nov 2025 19:21:05 +0100 Subject: [PATCH 5/6] refactor: drop config file loading message --- src/main.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.zig b/src/main.zig index 4df0d49..e33201c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -533,7 +533,7 @@ pub fn read_config(T: type, allocator: std.mem.Allocator) struct { T, [][]const // returns true if the file was found fn read_config_file(T: type, allocator: std.mem.Allocator, conf: *T, bufs: *[][]const u8, file_name: []const u8) bool { - std.log.info("loading {s}", .{file_name}); + // std.log.info("loading {s}", .{file_name}); const err: anyerror = blk: { if (std.mem.endsWith(u8, file_name, ".json")) if (read_json_config_file(T, allocator, conf, bufs, file_name)) return true else |e| break :blk e; if (read_text_config_file(T, allocator, conf, bufs, file_name)) return true else |e| break :blk e; From a639201807aab9ae7a8dfa35508cb3490e523331 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 26 Nov 2025 19:21:23 +0100 Subject: [PATCH 6/6] fix: remove extra close_file call in mainview.extract_state --- src/tui/mainview.zig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index 322d1eb..334389f 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -1740,11 +1740,9 @@ fn extract_state(self: *Self, iter: *[]const u8) !void { for (buffers) |buffer| if (!buffer.is_ephemeral()) send_buffer_did_open(self.allocator, buffer) catch {}; - if (editor_file_path) |file_path| { + if (editor_file_path) |file_path| if (self.buffer_manager.get_buffer_for_file(file_path)) |_| - return tp.self_pid().send(.{ "cmd", "navigate", .{ .file = file_path } }); - } - try tp.self_pid().send(.{ "cmd", "close_file" }); + try tp.self_pid().send(.{ "cmd", "navigate", .{ .file = file_path } }); } fn send_buffer_did_open(allocator: std.mem.Allocator, buffer: *Buffer) !void {