Compare commits
6 commits
690498fdcc
...
e134cfc949
| Author | SHA1 | Date | |
|---|---|---|---|
| e134cfc949 | |||
| 2ca1a742a1 | |||
| 741096cb43 | |||
| c8840f0756 | |||
| 20129ea773 | |||
| bbeba10fe5 |
5 changed files with 121 additions and 53 deletions
|
|
@ -114,6 +114,7 @@ pub const WhitespaceMode = enum {
|
|||
leading,
|
||||
eol,
|
||||
tabs,
|
||||
external,
|
||||
visible,
|
||||
full,
|
||||
none,
|
||||
|
|
|
|||
|
|
@ -58,17 +58,36 @@ pub fn shutdown() void {
|
|||
pid.send(.{"shutdown"}) catch {};
|
||||
}
|
||||
|
||||
pub fn open(rel_project_directory: []const u8) (ProjectManagerError || FileSystemError || std.fs.File.OpenError || SetCwdError)!void {
|
||||
pub fn open(rel_project_directory: []const u8) (ProjectManagerError || FileSystemError || std.fs.File.OpenError || SetCwdError)!?[]const u8 {
|
||||
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||
const project_directory = std.fs.cwd().realpath(rel_project_directory, &path_buf) catch "(none)";
|
||||
const current_project = tp.env.get().str("project");
|
||||
if (std.mem.eql(u8, current_project, project_directory)) return;
|
||||
if (std.mem.eql(u8, current_project, project_directory)) return get_project_state(project_directory);
|
||||
if (!root.is_directory(project_directory)) return error.InvalidProjectDirectory;
|
||||
var dir = try std.fs.openDirAbsolute(project_directory, .{});
|
||||
try dir.setAsCwd();
|
||||
dir.close();
|
||||
tp.env.get().str_set("project", project_directory);
|
||||
return send(.{ "open", project_directory });
|
||||
try send(.{ "open", project_directory });
|
||||
return get_project_state(project_directory);
|
||||
}
|
||||
|
||||
const project_state_allocator = std.heap.c_allocator;
|
||||
var project_state_mutex: std.Thread.Mutex = .{};
|
||||
var project_state: ProjectStateMap = .empty;
|
||||
const ProjectStateMap = std.StringHashMapUnmanaged(std.array_list.Managed(u8));
|
||||
|
||||
fn get_project_state(project_directory: []const u8) ?[]const u8 {
|
||||
project_state_mutex.lock();
|
||||
defer project_state_mutex.unlock();
|
||||
return if (project_state.get(project_directory)) |state| state.items else null;
|
||||
}
|
||||
|
||||
pub fn store_state(project_directory: []const u8, state: std.array_list.Managed(u8)) error{OutOfMemory}!void {
|
||||
project_state_mutex.lock();
|
||||
defer project_state_mutex.unlock();
|
||||
if (project_state.fetchRemove(project_directory)) |old_state| old_state.value.deinit();
|
||||
try project_state.put(project_state_allocator, try project_state_allocator.dupe(u8, project_directory), state);
|
||||
}
|
||||
|
||||
pub fn close(project_directory: []const u8) (ProjectManagerError || error{CloseCurrentProject})!void {
|
||||
|
|
|
|||
|
|
@ -1562,6 +1562,18 @@ pub const Editor = struct {
|
|||
cell.cell.char.grapheme = c;
|
||||
}
|
||||
},
|
||||
.external => {
|
||||
if (leading) {
|
||||
if (get_whitespace_char(cell_type, next_cell_type)) |c|
|
||||
cell.cell.char.grapheme = c;
|
||||
}
|
||||
if (cell_type == .eol)
|
||||
cell.cell.char.grapheme = char.eol;
|
||||
if (cell_type == .tab or cell_type == .extension) {
|
||||
if (get_whitespace_char(cell_type, next_cell_type)) |c|
|
||||
cell.cell.char.grapheme = c;
|
||||
}
|
||||
},
|
||||
.visible => {
|
||||
if (get_whitespace_char(cell_type, next_cell_type)) |c|
|
||||
cell.cell.char.grapheme = c;
|
||||
|
|
@ -1573,7 +1585,7 @@ pub const Editor = struct {
|
|||
else => "#",
|
||||
};
|
||||
},
|
||||
else => {},
|
||||
.none => {},
|
||||
}
|
||||
if (tab_error) {
|
||||
cell.set_style_fg(theme.editor_error);
|
||||
|
|
|
|||
|
|
@ -356,7 +356,8 @@ const cmds = struct {
|
|||
pub const quit_without_saving_meta: Meta = .{ .description = "Quit without saving" };
|
||||
|
||||
pub fn open_project_cwd(self: *Self, _: Ctx) Result {
|
||||
try project_manager.open(".");
|
||||
if (try project_manager.open(".")) |state|
|
||||
try self.restore_state(state);
|
||||
if (self.top_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" });
|
||||
if (self.bottom_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" });
|
||||
}
|
||||
|
|
@ -366,7 +367,8 @@ const cmds = struct {
|
|||
var project_dir: []const u8 = undefined;
|
||||
if (!try ctx.args.match(.{tp.extract(&project_dir)}))
|
||||
return;
|
||||
try project_manager.open(project_dir);
|
||||
if (try project_manager.open(project_dir)) |state|
|
||||
try self.restore_state(state);
|
||||
const project = tp.env.get().str("project");
|
||||
tui.rdr().set_terminal_working_directory(project);
|
||||
if (self.top_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" });
|
||||
|
|
@ -394,7 +396,20 @@ const cmds = struct {
|
|||
if (!try ctx.args.match(.{tp.extract(&project_dir)}))
|
||||
return;
|
||||
try self.check_all_not_dirty();
|
||||
try project_manager.open(project_dir);
|
||||
|
||||
{
|
||||
var state_writer: std.Io.Writer.Allocating = .init(self.allocator);
|
||||
defer state_writer.deinit();
|
||||
try self.write_state(&state_writer.writer);
|
||||
try state_writer.writer.flush();
|
||||
const old_project = tp.env.get().str("project");
|
||||
var state_al = state_writer.toArrayList();
|
||||
const state = state_al.toManaged(self.allocator);
|
||||
try project_manager.store_state(old_project, state);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -402,11 +417,15 @@ const cmds = struct {
|
|||
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);
|
||||
if (project_state) |state| try self.restore_state(state);
|
||||
|
||||
if (self.top_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" });
|
||||
if (self.bottom_bar) |bar| _ = try bar.msg(.{ "PRJ", "open" });
|
||||
tp.self_pid().send(.{ "cmd", "open_recent" }) catch return;
|
||||
if (project_state == null)
|
||||
tp.self_pid().send(.{ "cmd", "open_recent" }) catch return;
|
||||
}
|
||||
pub const change_project_meta: Meta = .{ .arguments = &.{.string} };
|
||||
|
||||
|
|
@ -1599,42 +1618,49 @@ fn create_home_split(self: *Self) !void {
|
|||
tui.resize();
|
||||
}
|
||||
|
||||
pub fn write_restore_info(self: *Self) void {
|
||||
var sfa = std.heap.stackFallback(512, self.allocator);
|
||||
const a = sfa.get();
|
||||
var meta: std.Io.Writer.Allocating = .init(a);
|
||||
defer meta.deinit();
|
||||
const writer = &meta.writer;
|
||||
|
||||
if (self.get_active_editor()) |editor| {
|
||||
cbor.writeValue(writer, editor.file_path) catch return;
|
||||
editor.update_meta();
|
||||
} else {
|
||||
cbor.writeValue(writer, null) catch return;
|
||||
}
|
||||
|
||||
if (tui.clipboard_get_history()) |clipboard| {
|
||||
cbor.writeArrayHeader(writer, clipboard.len) catch return;
|
||||
for (clipboard) |item| {
|
||||
cbor.writeArrayHeader(writer, 2) catch return;
|
||||
cbor.writeValue(writer, item.group) catch return;
|
||||
cbor.writeValue(writer, item.text) catch return;
|
||||
}
|
||||
} else {
|
||||
cbor.writeValue(writer, null) catch return;
|
||||
}
|
||||
|
||||
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
|
||||
buffer_manager.write_state(writer) catch return;
|
||||
|
||||
if (self.widgets.get("tabs")) |tabs_widget|
|
||||
if (tabs_widget.dynamic_cast(@import("status/tabs.zig").TabBar)) |tabs|
|
||||
tabs.write_state(writer) catch return;
|
||||
pub const WriteStateError = error{
|
||||
OutOfMemory,
|
||||
Stop,
|
||||
WriteFailed,
|
||||
};
|
||||
|
||||
pub fn write_restore_info(self: *Self) WriteStateError!void {
|
||||
const file_name = root.get_restore_file_name() catch return;
|
||||
var file = std.fs.createFileAbsolute(file_name, .{ .truncate = true }) catch return;
|
||||
defer file.close();
|
||||
file.writeAll(meta.written()) catch return;
|
||||
var buf: [32 + 1024]u8 = undefined;
|
||||
var file_writer = file.writer(&buf);
|
||||
const writer = &file_writer.interface;
|
||||
|
||||
try self.write_state(writer);
|
||||
try writer.flush();
|
||||
}
|
||||
|
||||
pub fn write_state(self: *Self, writer: *std.Io.Writer) WriteStateError!void {
|
||||
if (self.get_active_editor()) |editor| {
|
||||
try cbor.writeValue(writer, editor.file_path);
|
||||
editor.update_meta();
|
||||
} else {
|
||||
try cbor.writeValue(writer, null);
|
||||
}
|
||||
|
||||
if (tui.clipboard_get_history()) |clipboard| {
|
||||
try cbor.writeArrayHeader(writer, clipboard.len);
|
||||
for (clipboard) |item| {
|
||||
try cbor.writeArrayHeader(writer, 2);
|
||||
try cbor.writeValue(writer, item.group);
|
||||
try cbor.writeValue(writer, item.text);
|
||||
}
|
||||
} else {
|
||||
try cbor.writeValue(writer, null);
|
||||
}
|
||||
|
||||
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
|
||||
try buffer_manager.write_state(writer);
|
||||
|
||||
if (self.widgets.get("tabs")) |tabs_widget|
|
||||
if (tabs_widget.dynamic_cast(@import("status/tabs.zig").TabBar)) |tabs|
|
||||
try tabs.write_state(writer);
|
||||
}
|
||||
|
||||
fn read_restore_info(self: *Self) !void {
|
||||
|
|
@ -1647,31 +1673,40 @@ fn read_restore_info(self: *Self) !void {
|
|||
const size = try file.readAll(buf);
|
||||
var iter: []const u8 = buf[0..size];
|
||||
|
||||
try self.extract_state(&iter);
|
||||
}
|
||||
|
||||
fn restore_state(self: *Self, state: []const u8) !void {
|
||||
var iter = state;
|
||||
try self.extract_state(&iter);
|
||||
}
|
||||
|
||||
fn extract_state(self: *Self, iter: *[]const u8) !void {
|
||||
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.Stop;
|
||||
if (!try cbor.matchValue(iter, cbor.extract(&editor_file_path))) return error.MatchFilePathFailed;
|
||||
|
||||
tui.clipboard_clear_all();
|
||||
var len = try cbor.decodeArrayHeader(&iter);
|
||||
var len = try cbor.decodeArrayHeader(iter);
|
||||
var prev_group: usize = 0;
|
||||
const clipboard_allocator = tui.clipboard_allocator();
|
||||
while (len > 0) : (len -= 1) {
|
||||
const len_ = try cbor.decodeArrayHeader(&iter);
|
||||
if (len_ != 2) return error.Stop;
|
||||
const len_ = try cbor.decodeArrayHeader(iter);
|
||||
if (len_ != 2) return error.MatchClipboardArrayFailed;
|
||||
var group: usize = 0;
|
||||
var text: []const u8 = undefined;
|
||||
if (!try cbor.matchValue(&iter, cbor.extract(&group))) return error.Stop;
|
||||
if (!try cbor.matchValue(&iter, cbor.extract(&text))) return error.Stop;
|
||||
if (!try cbor.matchValue(iter, cbor.extract(&group))) return error.MatchClipboardGroupFailed;
|
||||
if (!try cbor.matchValue(iter, cbor.extract(&text))) return error.MatchClipboardTextFailed;
|
||||
if (prev_group != group) tui.clipboard_start_group();
|
||||
prev_group = group;
|
||||
tui.clipboard_add_chunk(try clipboard_allocator.dupe(u8, text));
|
||||
}
|
||||
|
||||
try self.buffer_manager.extract_state(&iter);
|
||||
try self.buffer_manager.extract_state(iter);
|
||||
|
||||
if (self.widgets.get("tabs")) |tabs_widget|
|
||||
if (tabs_widget.dynamic_cast(@import("status/tabs.zig").TabBar)) |tabs|
|
||||
tabs.extract_state(&iter) catch |e| {
|
||||
tabs.extract_state(iter) catch |e| {
|
||||
const logger = log.logger("mainview");
|
||||
defer logger.deinit();
|
||||
logger.print_err("mainview", "failed to restore tabs: {}", .{e});
|
||||
|
|
@ -1683,10 +1718,10 @@ fn read_restore_info(self: *Self) !void {
|
|||
send_buffer_did_open(self.allocator, buffer) catch {};
|
||||
|
||||
if (editor_file_path) |file_path| {
|
||||
try tp.self_pid().send(.{ "cmd", "navigate", .{ .file = file_path } });
|
||||
} else {
|
||||
try tp.self_pid().send(.{ "cmd", "close_file" });
|
||||
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" });
|
||||
}
|
||||
|
||||
fn send_buffer_did_open(allocator: std.mem.Allocator, buffer: *Buffer) !void {
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void {
|
|||
}
|
||||
|
||||
if (try m.match(.{"restart"})) {
|
||||
if (mainview()) |mv| mv.write_restore_info();
|
||||
if (mainview()) |mv| try mv.write_restore_info();
|
||||
project_manager.shutdown();
|
||||
self.final_exit = "restart";
|
||||
return;
|
||||
|
|
@ -1002,7 +1002,8 @@ const cmds = struct {
|
|||
.indent => .leading,
|
||||
.leading => .eol,
|
||||
.eol => .tabs,
|
||||
.tabs => .visible,
|
||||
.tabs => .external,
|
||||
.external => .visible,
|
||||
.visible => .full,
|
||||
.full => .none,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue