WIP: feat: restore buffer manager state on restart

This commit is contained in:
CJ van den Berg 2025-08-05 20:08:29 +02:00
parent c88e2dd975
commit 7b73ca0ccd
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
5 changed files with 103 additions and 13 deletions

View file

@ -1,5 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
const cbor = @import("cbor");
const Allocator = std.mem.Allocator;
const ArrayList = std.ArrayList;
const cwd = std.fs.cwd;
@ -1486,3 +1487,55 @@ pub fn redo(self: *Self) error{Stop}![]const u8 {
self.mtime = std.time.milliTimestamp();
return h.meta;
}
pub fn write_state(self: *const Self, writer: MetaWriter) error{ Stop, OutOfMemory }!void {
var content = std.ArrayListUnmanaged(u8).empty;
defer content.deinit(self.external_allocator);
try self.root.store(content.writer(self.external_allocator), self.file_eol_mode);
try cbor.writeArrayHeader(writer, 8);
try cbor.writeValue(writer, self.get_file_path());
try cbor.writeValue(writer, self.file_exists);
try cbor.writeValue(writer, self.file_eol_mode);
try cbor.writeValue(writer, self.hidden);
try cbor.writeValue(writer, self.ephemeral);
try cbor.writeValue(writer, self.meta);
try cbor.writeValue(writer, self.file_type_name);
try cbor.writeValue(writer, content.items);
}
pub const ExtractStateOperation = enum { none, open_file };
pub fn extract_state(self: *Self, iter: *[]const u8, comptime op: ExtractStateOperation) !void {
var file_path: []const u8 = undefined;
var file_exists: bool = undefined;
var file_eol_mode: EolMode = undefined;
var hidden: bool = undefined;
var ephemeral: bool = undefined;
var meta: ?[]const u8 = undefined;
var file_type_name: ?[]const u8 = undefined;
var content: []const u8 = undefined;
if (!try cbor.matchValue(iter, .{
cbor.extract(&file_path),
cbor.extract(&file_exists),
cbor.extract(&file_eol_mode),
cbor.extract(&hidden),
cbor.extract(&ephemeral),
cbor.extract(&meta),
cbor.extract(&file_type_name),
cbor.extract(&content),
}))
return error.Stop;
self.set_file_path(file_path);
self.file_exists = file_exists;
self.file_eol_mode = file_eol_mode;
self.hidden = hidden;
self.ephemeral = ephemeral;
self.meta = meta;
self.file_type_name = file_type_name;
try self.reset_from_string_and_update(content);
_ = op;
}

View file

@ -51,6 +51,32 @@ pub fn open_scratch(self: *Self, file_path: []const u8, content: []const u8) Buf
return buffer;
}
pub fn write_state(self: *const Self, writer: Buffer.MetaWriter) error{ Stop, OutOfMemory }!void {
const buffers = self.list_unordered(self.allocator) catch return;
defer self.allocator.free(buffers);
for (buffers) |buffer|
buffer.write_state(writer) catch |e| switch (e) {
error.Stop => {},
else => return,
};
}
pub fn extract_state(self: *Self, iter: *[]const u8, comptime op: Buffer.ExtractStateOperation) !void {
while (iter.len > 0) {
var buffer = try Buffer.create(self.allocator);
errdefer buffer.deinit();
buffer.extract_state(iter, op) catch |e| switch (e) {
error.Stop => {
buffer.deinit();
return;
},
else => |e_| return e_,
};
try self.buffers.put(self.allocator, try self.allocator.dupe(u8, buffer.get_file_path()), buffer);
tp.trace(tp.channel.debug, .{ "buffer", "extract", buffer.get_file_path(), buffer.file_type_name });
}
}
pub fn get_buffer_for_file(self: *Self, file_path: []const u8) ?*Buffer {
return self.buffers.get(file_path);
}

View file

@ -942,7 +942,7 @@ pub fn get_restore_file_name() ![]const u8 {
const restore_file = if (local.restore_file) |file|
file
else
try std.fmt.bufPrint(&local.restore_file_buffer, "{s}/{s}", .{ try get_app_cache_dir(application_name), restore_file_name });
try std.fmt.bufPrint(&local.restore_file_buffer, "{s}/{s}", .{ try get_app_state_dir(application_name), restore_file_name });
local.restore_file = restore_file;
return restore_file;
}

View file

@ -401,9 +401,7 @@ pub const Editor = struct {
};
}
pub fn extract_state(self: *Self, buf: []const u8, comptime op: enum { none, open_file }) !void {
tp.trace(tp.channel.debug, .{ "extract_state", self.file_path });
tp.trace(tp.channel.debug, tp.message{ .buf = buf });
pub fn extract_state(self: *Self, iter: *[]const u8, comptime op: Buffer.ExtractStateOperation) !void {
self.restored_state = true;
var file_path: []const u8 = undefined;
var view_cbor: []const u8 = undefined;
@ -411,7 +409,7 @@ pub const Editor = struct {
var clipboard: []const u8 = undefined;
var last_find_query: []const u8 = undefined;
var find_history: []const u8 = undefined;
if (!try cbor.match(buf, .{
if (!try cbor.matchValue(iter, .{
tp.extract(&file_path),
tp.extract(&clipboard),
tp.extract(&last_find_query),
@ -440,11 +438,11 @@ pub const Editor = struct {
if (cursels_cbor.len > 0)
self.clear_all_cursors();
var iter = cursels_cbor;
var len = cbor.decodeArrayHeader(&iter) catch return error.RestoreCurSels;
var cursels_iter = cursels_cbor;
var len = cbor.decodeArrayHeader(&cursels_iter) catch return error.RestoreCurSels;
while (len > 0) : (len -= 1) {
var cursel: CurSel = .{};
if (!(cursel.extract(&iter) catch false)) break;
if (!(cursel.extract(&cursels_iter) catch false)) break;
(try self.cursels.addOne(self.allocator)).* = cursel;
}
@ -659,7 +657,8 @@ pub const Editor = struct {
if (buffer_meta) |meta| {
const frame_ = tracy.initZone(@src(), .{ .name = "extract_state" });
defer frame_.deinit();
try self.extract_state(meta, .none);
var iter = meta;
try self.extract_state(&iter, .none);
}
try self.send_editor_open(file_path, new_buf.file_exists, ftn, fti, ftc);
}

View file

@ -1288,11 +1288,21 @@ fn create_home_split(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);
const a = sfa.get();
var meta = std.ArrayListUnmanaged(u8).empty;
editor.write_state(meta.writer(a)) catch return;
// editor.write_state(meta.writer(a)) catch return;
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
const buffers = buffer_manager.list_unordered(self.allocator) catch return;
defer self.allocator.free(buffers);
for (buffers) |buffer|
buffer.write_state(meta.writer(a)) catch |e| switch (e) {
error.Stop => {},
else => return,
};
const file_name = root.get_restore_file_name() catch return;
var file = std.fs.createFileAbsolute(file_name, .{ .truncate = true }) catch return;
defer file.close();
@ -1300,7 +1310,7 @@ pub fn write_restore_info(self: *Self) void {
}
fn read_restore_info(self: *Self) !void {
const editor = self.get_active_editor() orelse return;
// const editor = self.get_active_editor() orelse return;
const file_name = try root.get_restore_file_name();
const file = try std.fs.cwd().openFile(file_name, .{ .mode = .read_only });
defer file.close();
@ -1308,7 +1318,9 @@ fn read_restore_info(self: *Self) !void {
var buf = try self.allocator.alloc(u8, @intCast(stat.size));
defer self.allocator.free(buf);
const size = try file.readAll(buf);
try editor.extract_state(buf[0..size], .open_file);
var iter: []const u8 = buf[0..size];
// try editor.extract_state(&iter, .open_file);
try self.buffer_manager.extract_state(&iter, .open_file);
}
fn get_next_mru_buffer(self: *Self) ?[]const u8 {