diff --git a/src/Project.zig b/src/Project.zig index 23eaae1..8e97119 100644 --- a/src/Project.zig +++ b/src/Project.zig @@ -413,11 +413,11 @@ pub fn walk_tree_entry(self: *Self, file_path: []const u8, mtime: i128) OutOfMem (try self.pending.addOne(self.allocator)).* = .{ .path = try self.allocator.dupe(u8, file_path), .mtime = mtime }; } -pub fn walk_tree_done(self: *Self, parent: tp.pid_ref) OutOfMemoryError!void { +pub fn walk_tree_done(self: *Self) OutOfMemoryError!void { self.state.walk_tree = .done; if (self.walker) |pid| pid.deinit(); self.walker = null; - return self.loaded(parent); + return self.loaded(); } fn merge_pending_files(self: *Self) OutOfMemoryError!void { @@ -433,7 +433,7 @@ fn merge_pending_files(self: *Self) OutOfMemoryError!void { } } -fn loaded(self: *Self, parent: tp.pid_ref) OutOfMemoryError!void { +fn loaded(self: *Self) OutOfMemoryError!void { inline for (@typeInfo(@TypeOf(self.state)).@"struct".fields) |f| if (@field(self.state, f.name) == .running) return; @@ -449,8 +449,6 @@ fn loaded(self: *Self, parent: tp.pid_ref) OutOfMemoryError!void { self.files.items.len, std.time.milliTimestamp() - self.open_time, }); - - parent.send(.{ "PRJ", "open_done", self.name, self.longest_file_path, self.files.items.len }) catch {}; } pub fn update_mru(self: *Self, file_path: []const u8, row: usize, col: usize) OutOfMemoryError!void { @@ -1915,13 +1913,13 @@ fn start_walker(self: *Self) void { }; } -pub fn process_git(self: *Self, parent: tp.pid_ref, m: tp.message) (OutOfMemoryError || error{Exit})!void { +pub fn process_git(self: *Self, m: tp.message) (OutOfMemoryError || error{Exit})!void { var value: []const u8 = undefined; var path: []const u8 = undefined; if (try m.match(.{ tp.any, tp.any, "workspace_path", tp.null_ })) { self.state.workspace_path = .done; self.start_walker(); - try self.loaded(parent); + try self.loaded(); } else if (try m.match(.{ tp.any, tp.any, "workspace_path", tp.extract(&value) })) { if (self.workspace) |p| self.allocator.free(p); self.workspace = try self.allocator.dupe(u8, value); @@ -1932,19 +1930,19 @@ pub fn process_git(self: *Self, parent: tp.pid_ref, m: tp.message) (OutOfMemoryE }; } else if (try m.match(.{ tp.any, tp.any, "current_branch", tp.null_ })) { self.state.current_branch = .done; - try self.loaded(parent); + try self.loaded(); } else if (try m.match(.{ tp.any, tp.any, "current_branch", tp.extract(&value) })) { if (self.branch) |p| self.allocator.free(p); self.branch = try self.allocator.dupe(u8, value); self.state.current_branch = .done; - try self.loaded(parent); + try self.loaded(); } else if (try m.match(.{ tp.any, tp.any, "workspace_files", tp.extract(&path) })) { self.longest_file_path = @max(self.longest_file_path, path.len); const stat = std.fs.cwd().statFile(path) catch return; (try self.pending.addOne(self.allocator)).* = .{ .path = try self.allocator.dupe(u8, path), .mtime = stat.mtime }; } else if (try m.match(.{ tp.any, tp.any, "workspace_files", tp.null_ })) { self.state.workspace_files = .done; - try self.loaded(parent); + try self.loaded(); } else { self.logger_git.err("git", tp.unexpected(m)); } diff --git a/src/project_manager.zig b/src/project_manager.zig index c29a78a..a179c1e 100644 --- a/src/project_manager.zig +++ b/src/project_manager.zig @@ -341,10 +341,10 @@ const Process = struct { project.walk_tree_entry(path, mtime) catch |e| self.logger.err("walk_tree_entry", e); } else if (try cbor.match(m.buf, .{ "walk_tree_done", tp.extract(&project_directory) })) { if (self.projects.get(project_directory)) |project| - project.walk_tree_done(self.parent.ref()) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed; + project.walk_tree_done() catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed; } else if (try cbor.match(m.buf, .{ "git", tp.extract(&context), tp.more })) { const project: *Project = @ptrFromInt(context); - project.process_git(self.parent.ref(), m) catch {}; + project.process_git(m) catch {}; } else if (try cbor.match(m.buf, .{ "update_mru", tp.extract(&project_directory), tp.extract(&path), tp.extract(&row), tp.extract(&col) })) { self.update_mru(project_directory, path, row, col) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed; } else if (try cbor.match(m.buf, .{ "child", tp.extract(&project_directory), tp.extract(&language_server), "notify", tp.extract(&method), tp.extract_cbor(¶ms_cb) })) { diff --git a/src/shell.zig b/src/shell.zig index 1678776..3e316ab 100644 --- a/src/shell.zig +++ b/src/shell.zig @@ -40,7 +40,6 @@ pub const Handlers = struct { err: ?*const OutputHandler = null, exit: *const ExitHandler = log_exit_handler, log_execute: bool = true, - line_buffered: bool = true, }; pub fn execute(allocator: std.mem.Allocator, argv: tp.message, handlers: Handlers) Error!void { @@ -146,8 +145,6 @@ const Process = struct { logger: log.Logger, stdin_behavior: std.process.Child.StdIo, handlers: Handlers, - stdout_line_buffer: std.ArrayListUnmanaged(u8) = .empty, - stderr_line_buffer: std.ArrayListUnmanaged(u8) = .empty, const Receiver = tp.Receiver(*Process); @@ -184,8 +181,6 @@ const Process = struct { self.logger.deinit(); self.allocator.free(self.arg0); self.allocator.free(self.argv.buf); - self.stdout_line_buffer.deinit(self.allocator); - self.stderr_line_buffer.deinit(self.allocator); self.allocator.destroy(self); } @@ -220,9 +215,9 @@ const Process = struct { } else if (try m.match(.{"close"})) { self.close(); } else if (try m.match(.{ module_name, "stdout", tp.extract(&bytes) })) { - self.handle_stdout(bytes) catch |e| return tp.exit_error(e, @errorReturnTrace()); + self.handlers.out(self.handlers.context, self.parent.ref(), self.arg0, bytes); } else if (try m.match(.{ module_name, "stderr", tp.extract(&bytes) })) { - self.handle_stderr(bytes) catch |e| return tp.exit_error(e, @errorReturnTrace()); + (self.handlers.err orelse self.handlers.out)(self.handlers.context, self.parent.ref(), self.arg0, bytes); } else if (try m.match(.{ module_name, "term", tp.more })) { defer self.sp = null; self.handle_terminated(m) catch |e| return tp.exit_error(e, @errorReturnTrace()); @@ -236,57 +231,9 @@ const Process = struct { } } - fn handle_stdout(self: *Process, bytes: []const u8) error{OutOfMemory}!void { - return if (!self.handlers.line_buffered) - self.handlers.out(self.handlers.context, self.parent.ref(), self.arg0, bytes) - else - self.handle_buffered_output(self.handlers.out, &self.stdout_line_buffer, bytes); - } - - fn handle_stderr(self: *Process, bytes: []const u8) error{OutOfMemory}!void { - const handler = self.handlers.err orelse self.handlers.out; - return if (!self.handlers.line_buffered) - handler(self.handlers.context, self.parent.ref(), self.arg0, bytes) - else - self.handle_buffered_output(handler, &self.stderr_line_buffer, bytes); - } - - fn handle_buffered_output(self: *Process, handler: *const OutputHandler, buffer: *std.ArrayListUnmanaged(u8), bytes: []const u8) error{OutOfMemory}!void { - var it = std.mem.splitScalar(u8, bytes, '\n'); - var have_nl = false; - var prev = it.first(); - while (it.next()) |next| { - have_nl = true; - try buffer.appendSlice(self.allocator, prev); - try buffer.append(self.allocator, '\n'); - prev = next; - } - if (have_nl) { - handler(self.handlers.context, self.parent.ref(), self.arg0, buffer.items); - buffer.clearRetainingCapacity(); - } - try buffer.appendSlice(self.allocator, prev); - } - - fn flush_stdout(self: *Process) void { - self.flush_buffer(self.handlers.out, &self.stdout_line_buffer); - } - - fn flush_stderr(self: *Process) void { - self.flush_buffer(self.handlers.err orelse self.handlers.out, &self.stderr_line_buffer); - } - - fn flush_buffer(self: *Process, handler: *const OutputHandler, buffer: *std.ArrayListUnmanaged(u8)) void { - if (!self.handlers.line_buffered) return; - if (buffer.items.len > 0) handler(self.handlers.context, self.parent.ref(), self.arg0, buffer.items); - buffer.clearRetainingCapacity(); - } - fn handle_terminated(self: *Process, m: tp.message) !void { var err_msg: []const u8 = undefined; var exit_code: i64 = undefined; - self.flush_stdout(); - self.flush_stderr(); if (try m.match(.{ tp.any, tp.any, "exited", 0 })) { self.handlers.exit(self.handlers.context, self.parent.ref(), self.arg0, "exited", 0); } else if (try m.match(.{ tp.any, tp.any, "error.FileNotFound", 1 })) { diff --git a/src/tui/mode/mini/file_browser.zig b/src/tui/mode/mini/file_browser.zig index c47d088..ea6fee7 100644 --- a/src/tui/mode/mini/file_browser.zig +++ b/src/tui/mode/mini/file_browser.zig @@ -9,7 +9,6 @@ const keybind = @import("keybind"); const project_manager = @import("project_manager"); const command = @import("command"); const EventHandler = @import("EventHandler"); -const Buffer = @import("Buffer"); const tui = @import("../../tui.zig"); const MessageFilter = @import("../../MessageFilter.zig"); @@ -24,7 +23,6 @@ pub fn Create(options: type) type { match: std.ArrayList(u8), entries: std.ArrayList(Entry), complete_trigger_count: usize = 0, - total_matches: usize = 0, matched_entry: usize = 0, commands: Commands = undefined, @@ -173,23 +171,14 @@ pub fn Create(options: type) type { fn do_complete(self: *Self) !void { self.complete_trigger_count = @min(self.complete_trigger_count, self.entries.items.len); self.file_path.clearRetainingCapacity(); - const match_number = self.complete_trigger_count; if (self.match.items.len > 0) { try self.match_path(); - if (self.total_matches == 1) - self.complete_trigger_count = 0; } else if (self.entries.items.len > 0) { try self.construct_path(self.query.items, self.entries.items[self.complete_trigger_count - 1], self.complete_trigger_count - 1); } else { try self.construct_path(self.query.items, .{ .name = "", .type = .file }, 0); } - if (self.match.items.len > 0) - if (self.total_matches > 1) - message("{d}/{d} ({d}/{d} matches)", .{ self.matched_entry + 1, self.entries.items.len, match_number, self.total_matches }) - else - message("{d}/{d} ({d} match)", .{ self.matched_entry + 1, self.entries.items.len, self.total_matches }) - else - message("{d}/{d}", .{ self.matched_entry + 1, self.entries.items.len }); + message("{d}/{d}", .{ self.matched_entry + 1, self.entries.items.len }); } fn construct_path(self: *Self, path_: []const u8, entry: Entry, entry_no: usize) error{OutOfMemory}!void { @@ -204,23 +193,22 @@ pub fn Create(options: type) type { } fn match_path(self: *Self) !void { - var found_match: ?usize = null; var matched: usize = 0; var last: ?Entry = null; var last_no: usize = 0; for (self.entries.items, 0..) |entry, i| { - if (try prefix_compare_icase(self.allocator, self.match.items, entry.name)) { + if (entry.name.len >= self.match.items.len and + std.mem.eql(u8, self.match.items, entry.name[0..self.match.items.len])) + { matched += 1; if (matched == self.complete_trigger_count) { try self.construct_path(self.query.items, entry, i); - found_match = i; + return; } last = entry; last_no = i; } } - self.total_matches = matched; - if (found_match) |_| return; if (last) |entry| { try self.construct_path(self.query.items, entry, last_no); self.complete_trigger_count = matched; @@ -230,15 +218,6 @@ pub fn Create(options: type) type { } } - fn prefix_compare_icase(allocator: std.mem.Allocator, prefix: []const u8, str: []const u8) error{OutOfMemory}!bool { - const icase_prefix = Buffer.unicode.get_letter_casing().toLowerStr(allocator, prefix) catch try allocator.dupe(u8, prefix); - defer allocator.free(icase_prefix); - const icase_str = Buffer.unicode.get_letter_casing().toLowerStr(allocator, str) catch try allocator.dupe(u8, str); - defer allocator.free(icase_str); - if (icase_str.len < icase_prefix.len) return false; - return std.mem.eql(u8, icase_prefix, icase_str[0..icase_prefix.len]); - } - fn delete_to_previous_path_segment(self: *Self) void { self.complete_trigger_count = 0; if (self.file_path.items.len == 0) return; diff --git a/src/tui/mode/mini/open_file.zig b/src/tui/mode/mini/open_file.zig index 07f70e4..3eeb4b6 100644 --- a/src/tui/mode/mini/open_file.zig +++ b/src/tui/mode/mini/open_file.zig @@ -37,9 +37,12 @@ pub fn select(self: *Type) void { var buf = std.ArrayList(u8).init(self.allocator); defer buf.deinit(); const file_path = project_manager.expand_home(&buf, self.file_path.items); - command.executeName("exit_mini_mode", .{}) catch {}; - if (root.is_directory(file_path)) - tp.self_pid().send(.{ "cmd", "change_project", .{file_path} }) catch {} - else if (file_path.len > 0) + if (root.is_directory(file_path)) { + tp.self_pid().send(.{ "cmd", "exit_overlay_mode" }) catch return; + tp.self_pid().send(.{ "cmd", "change_project", .{file_path} }) catch {}; + return; + } + if (file_path.len > 0) tp.self_pid().send(.{ "cmd", "navigate", .{ .file = file_path } }) catch {}; + command.executeName("exit_mini_mode", .{}) catch {}; } diff --git a/src/tui/mode/overlay/open_recent.zig b/src/tui/mode/overlay/open_recent.zig index b3c05dc..0c5d687 100644 --- a/src/tui/mode/overlay/open_recent.zig +++ b/src/tui/mode/overlay/open_recent.zig @@ -36,8 +36,6 @@ longest: usize = 0, commands: Commands = undefined, buffer_manager: ?*BufferManager, -const inputbox_label = "Search files by name"; - pub fn create(allocator: std.mem.Allocator) !tui.Mode { const mv = tui.mainview() orelse return error.NotFound; const self = try allocator.create(Self); @@ -53,7 +51,7 @@ pub fn create(allocator: std.mem.Allocator) !tui.Mode { .logger = log.logger(@typeName(Self)), .inputbox = (try self.menu.add_header(try InputBox.create(*Self, self.allocator, self.menu.menu.parent, .{ .ctx = self, - .label = inputbox_label, + .label = "Search files by name", }))).dynamic_cast(InputBox.State(*Self)) orelse unreachable, .buffer_manager = tui.get_buffer_manager(), }; @@ -84,7 +82,7 @@ pub fn deinit(self: *Self) void { } inline fn menu_width(self: *Self) usize { - return @max(@min(self.longest, max_menu_width()) + 2, inputbox_label.len + 2); + return @min(self.longest, max_menu_width()) + 2; } inline fn menu_pos_x(self: *Self) usize { @@ -200,10 +198,6 @@ fn process_project_manager(self: *Self, m: tp.message) MessageFilter.Error!void self.need_reset = true; if (!std.mem.eql(u8, self.inputbox.text.items, query)) try self.start_query(); - } else if (try cbor.match(m.buf, .{ "PRJ", "open_done", tp.string, tp.extract(&self.longest), tp.any })) { - self.query_pending = false; - self.need_reset = true; - try self.start_query(); } else { self.logger.err("receive", tp.unexpected(m)); } diff --git a/src/tui/mode/overlay/palette.zig b/src/tui/mode/overlay/palette.zig index 1e0e18a..926dc65 100644 --- a/src/tui/mode/overlay/palette.zig +++ b/src/tui/mode/overlay/palette.zig @@ -153,7 +153,7 @@ pub fn Create(options: type) type { fn do_resize(self: *Self) void { const screen = tui.screen(); - const w = @max(@min(self.longest, max_menu_width) + 2 + 1 + self.longest_hint, options.label.len + 2); + 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; self.view_rows = get_view_rows(screen); const h = @min(self.items + self.menu.header_count, self.view_rows + self.menu.header_count);