Compare commits

...

6 commits

4 changed files with 59 additions and 20 deletions

View file

@ -31,6 +31,7 @@ persistent: bool = false,
logger: log.Logger, logger: log.Logger,
logger_lsp: log.Logger, logger_lsp: log.Logger,
logger_git: log.Logger, logger_git: log.Logger,
last_used: i128,
workspace: ?[]const u8 = null, workspace: ?[]const u8 = null,
@ -100,6 +101,7 @@ pub fn init(allocator: std.mem.Allocator, name: []const u8) OutOfMemoryError!Sel
.logger = log.logger("project"), .logger = log.logger("project"),
.logger_lsp = log.logger("lsp"), .logger_lsp = log.logger("lsp"),
.logger_git = log.logger("git"), .logger_git = log.logger("git"),
.last_used = std.time.nanoTimestamp(),
}; };
} }

View file

@ -100,7 +100,7 @@ const Handler = struct {
pub const Mode = struct { pub const Mode = struct {
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
input_handler: EventHandler, input_handler: ?EventHandler,
event_handler: ?EventHandler = null, event_handler: ?EventHandler = null,
mode: []const u8, mode: []const u8,
@ -121,11 +121,24 @@ pub const Mode = struct {
} }
pub fn deinit(self: *Mode) void { pub fn deinit(self: *Mode) void {
if (self.deinit_command) |deinit_command| if (self.deinit_command) |deinit_command| deinit_command.execute_const();
deinit_command.execute_const();
self.allocator.free(self.mode);
self.input_handler.deinit();
if (self.event_handler) |eh| eh.deinit(); if (self.event_handler) |eh| eh.deinit();
if (self.input_handler) |ih| ih.deinit();
self.allocator.free(self.mode);
self.deinit_command = null;
self.event_handler = null;
self.input_handler = null;
self.mode = &.{};
self.name = "";
self.line_numbers = .inherit;
self.keybind_hints = &.{};
self.cursor_shape = null;
self.selection_style = .normal;
self.init_command = null;
self.deinit_command = null;
self.initialized = false;
} }
}; };

View file

@ -463,15 +463,16 @@ const Process = struct {
} }
fn open(self: *Process, project_directory: []const u8) (SpawnError || std.fs.Dir.OpenError)!void { fn open(self: *Process, project_directory: []const u8) (SpawnError || std.fs.Dir.OpenError)!void {
if (self.projects.get(project_directory) == null) { if (self.projects.get(project_directory)) |project| {
project.last_used = std.time.nanoTimestamp();
self.logger.print("switched to: {s}", .{project_directory});
} else {
self.logger.print("opening: {s}", .{project_directory}); self.logger.print("opening: {s}", .{project_directory});
const project = try self.allocator.create(Project); const project = try self.allocator.create(Project);
project.* = try Project.init(self.allocator, project_directory); project.* = try Project.init(self.allocator, project_directory);
try self.projects.put(self.allocator, try self.allocator.dupe(u8, project_directory), project); try self.projects.put(self.allocator, try self.allocator.dupe(u8, project_directory), project);
self.restore_project(project) catch |e| self.logger.err("restore_project", e); self.restore_project(project) catch |e| self.logger.err("restore_project", e);
project.query_git(); project.query_git();
} else {
self.logger.print("switched to: {s}", .{project_directory});
} }
} }
@ -505,10 +506,35 @@ const Process = struct {
return project.request_new_or_modified_files(from, max); return project.request_new_or_modified_files(from, max);
} }
fn request_recent_projects(self: *Process, from: tp.pid_ref, project_directory: []const u8) (ProjectError || Project.ClientError)!void { fn request_recent_projects(self: *Process, from: tp.pid_ref, active_project: []const u8) (ProjectError || Project.ClientError)!void {
var recent_projects: std.ArrayList(RecentProject) = .empty; var recent_projects: std.ArrayList(RecentProject) = .empty;
defer recent_projects.deinit(self.allocator); defer recent_projects.deinit(self.allocator);
self.load_recent_projects(&recent_projects, project_directory) catch {}; self.load_recent_projects(&recent_projects) catch {};
for (recent_projects.items) |*recent_project| {
if (std.mem.eql(u8, active_project, recent_project.name)) {
recent_project.last_used = std.math.maxInt(i128);
break;
}
} else {
(try recent_projects.addOne(self.allocator)).* = .{
.name = try self.allocator.dupe(u8, active_project),
.last_used = std.math.maxInt(i128),
};
}
var iter = self.projects.iterator();
while (iter.next()) |item| {
for (recent_projects.items) |*recent_project| {
if (std.mem.eql(u8, item.value_ptr.*.name, recent_project.name)) {
recent_project.last_used = item.value_ptr.*.last_used;
break;
}
} else {
(try recent_projects.addOne(self.allocator)).* = .{
.name = try self.allocator.dupe(u8, item.value_ptr.*.name),
.last_used = item.value_ptr.*.last_used,
};
}
}
self.sort_projects_by_last_used(&recent_projects); self.sort_projects_by_last_used(&recent_projects);
var message: std.Io.Writer.Allocating = .init(self.allocator); var message: std.Io.Writer.Allocating = .init(self.allocator);
defer message.deinit(); defer message.deinit();
@ -521,6 +547,7 @@ const Process = struct {
try cbor.writeArrayHeader(writer, 2); try cbor.writeArrayHeader(writer, 2);
try cbor.writeValue(writer, project.name); try cbor.writeValue(writer, project.name);
try cbor.writeValue(writer, if (self.projects.get(project.name)) |_| true else false); try cbor.writeValue(writer, if (self.projects.get(project.name)) |_| true else false);
self.allocator.free(project.name);
} }
from.send_raw(.{ .buf = message.written() }) catch return error.ClientFailed; from.send_raw(.{ .buf = message.written() }) catch return error.ClientFailed;
self.logger.print("{d} projects found", .{recent_projects.items.len}); self.logger.print("{d} projects found", .{recent_projects.items.len});
@ -755,7 +782,7 @@ const Process = struct {
return stream.toOwnedSlice(); return stream.toOwnedSlice();
} }
fn load_recent_projects(self: *Process, recent_projects: *std.ArrayList(RecentProject), project_directory: []const u8) !void { fn load_recent_projects(self: *Process, recent_projects: *std.ArrayList(RecentProject)) !void {
var path: std.Io.Writer.Allocating = .init(self.allocator); var path: std.Io.Writer.Allocating = .init(self.allocator);
defer path.deinit(); defer path.deinit();
const writer = &path.writer; const writer = &path.writer;
@ -768,7 +795,7 @@ const Process = struct {
var iter = dir.iterate(); var iter = dir.iterate();
while (try iter.next()) |entry| { while (try iter.next()) |entry| {
if (entry.kind != .file) continue; if (entry.kind != .file) continue;
try self.read_project_name(path.written(), entry.name, recent_projects, project_directory); try self.read_project_name(path.written(), entry.name, recent_projects);
} }
} }
@ -777,7 +804,6 @@ const Process = struct {
state_dir: []const u8, state_dir: []const u8,
file_path: []const u8, file_path: []const u8,
recent_projects: *std.ArrayList(RecentProject), recent_projects: *std.ArrayList(RecentProject),
project_directory: []const u8,
) !void { ) !void {
var path: std.Io.Writer.Allocating = .init(self.allocator); var path: std.Io.Writer.Allocating = .init(self.allocator);
defer path.deinit(); defer path.deinit();
@ -795,10 +821,8 @@ const Process = struct {
var iter: []const u8 = buffer; var iter: []const u8 = buffer;
var name: []const u8 = undefined; var name: []const u8 = undefined;
if (cbor.matchValue(&iter, tp.extract(&name)) catch return) { if (cbor.matchValue(&iter, tp.extract(&name)) catch return)
const last_used = if (std.mem.eql(u8, project_directory, name)) std.math.maxInt(@TypeOf(stat.mtime)) else stat.mtime; (try recent_projects.addOne(self.allocator)).* = .{ .name = try self.allocator.dupe(u8, name), .last_used = stat.mtime };
(try recent_projects.addOne(self.allocator)).* = .{ .name = try self.allocator.dupe(u8, name), .last_used = last_used };
}
} }
fn sort_projects_by_last_used(_: *Process, recent_projects: *std.ArrayList(RecentProject)) void { fn sort_projects_by_last_used(_: *Process, recent_projects: *std.ArrayList(RecentProject)) void {

View file

@ -554,7 +554,7 @@ fn active_event_handler(self: *Self) ?EventHandler {
fn dispatch_flush_input_event(self: *Self) error{ Exit, NoSpaceLeft }!void { fn dispatch_flush_input_event(self: *Self) error{ Exit, NoSpaceLeft }!void {
var buf: [32]u8 = undefined; var buf: [32]u8 = undefined;
const mode = self.input_mode_ orelse return; const mode = self.input_mode_ orelse return;
try mode.input_handler.send(tp.self_pid(), try tp.message.fmtbuf(&buf, .{"F"})); if (mode.input_handler) |ih| try ih.send(tp.self_pid(), try tp.message.fmtbuf(&buf, .{"F"}));
if (mode.event_handler) |eh| try eh.send(tp.self_pid(), try tp.message.fmtbuf(&buf, .{"F"})); if (mode.event_handler) |eh| try eh.send(tp.self_pid(), try tp.message.fmtbuf(&buf, .{"F"}));
} }
@ -577,8 +577,8 @@ fn dispatch_input(ctx: *anyopaque, cbor_msg: []const u8) void {
break :ret false; break :ret false;
}) })
return; return;
if (self.input_mode_) |mode| if (self.input_mode_) |mode| if (mode.input_handler) |ih|
mode.input_handler.send(from, m) catch |e| self.logger.err("input handler", e); ih.send(from, m) catch |e| self.logger.err("input handler", e);
} }
fn dispatch_mouse(ctx: *anyopaque, y: c_int, x: c_int, cbor_msg: []const u8) void { fn dispatch_mouse(ctx: *anyopaque, y: c_int, x: c_int, cbor_msg: []const u8) void {