Prove multi-file terminal coding loop
This commit is contained in:
+19
-3
@@ -163,6 +163,7 @@ fn openLocalEditor(
|
||||
switch (metadata.kind) {
|
||||
.directory => try openDirectoryPreview(allocator, io, &client, path),
|
||||
.file => {
|
||||
if (std.fs.path.dirname(path)) |parent| seedDirectoryRepo(allocator, io, &client, parent) catch {};
|
||||
const bytes = std.Io.Dir.cwd().readFileAlloc(io, path, allocator, .limited(diagnostics.max_file_bytes)) catch |err| switch (err) {
|
||||
error.StreamTooLong => {
|
||||
try client.handleTraceLine("open diagnostic:file_too_large");
|
||||
@@ -184,7 +185,7 @@ fn openLocalEditor(
|
||||
try runLocalEditor(allocator, io, stdout, stderr, &client, path, stat != null and stat.?.kind == .directory);
|
||||
}
|
||||
|
||||
fn openDirectoryPreview(allocator: std.mem.Allocator, io: std.Io, client: *tui.Client, path: []const u8) !void {
|
||||
fn seedDirectoryRepo(allocator: std.mem.Allocator, io: std.Io, client: *tui.Client, path: []const u8) !void {
|
||||
var dir = try std.Io.Dir.cwd().openDir(io, path, .{ .iterate = true });
|
||||
defer dir.close(io);
|
||||
|
||||
@@ -211,6 +212,10 @@ fn openDirectoryPreview(allocator: std.mem.Allocator, io: std.Io, client: *tui.C
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn openDirectoryPreview(allocator: std.mem.Allocator, io: std.Io, client: *tui.Client, path: []const u8) !void {
|
||||
try seedDirectoryRepo(allocator, io, client, path);
|
||||
try client.handleTraceLine("file_picker");
|
||||
}
|
||||
|
||||
@@ -236,6 +241,8 @@ fn runLocalEditor(
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_dir) try client.openFilePicker();
|
||||
|
||||
var raw_terminal = try RawTerminal.enable(stdin_file.handle);
|
||||
defer raw_terminal.restore();
|
||||
|
||||
@@ -259,10 +266,12 @@ fn runLocalEditor(
|
||||
if (client.saved()) |saved_bytes| {
|
||||
const new_save_request = last_client_saved == null or !std.mem.eql(u8, saved_bytes, last_client_saved.?);
|
||||
if (new_save_request) {
|
||||
if (is_dir) {
|
||||
if (is_dir and client.currentPath() == null) {
|
||||
client.setStatusMessage("directory browser has nothing to save");
|
||||
} else {
|
||||
try persistLocalSave(allocator, io, path, saved_bytes, &last_saved, &last_client_saved);
|
||||
const save_path = try resolveLocalSavePath(allocator, path, client.currentPath());
|
||||
defer allocator.free(save_path);
|
||||
try persistLocalSave(allocator, io, save_path, saved_bytes, &last_saved, &last_client_saved);
|
||||
dirty = false;
|
||||
client.setStatusMessage("saved");
|
||||
}
|
||||
@@ -280,6 +289,13 @@ fn runLocalEditor(
|
||||
}
|
||||
}
|
||||
|
||||
fn resolveLocalSavePath(allocator: std.mem.Allocator, launch_path: []const u8, current_path: ?[]const u8) ![]u8 {
|
||||
const selected = current_path orelse launch_path;
|
||||
if (std.fs.path.isAbsolute(selected) or std.mem.indexOfScalar(u8, selected, '/') != null) return allocator.dupe(u8, selected);
|
||||
const base = std.fs.path.dirname(launch_path) orelse ".";
|
||||
return std.fs.path.join(allocator, &.{ base, selected });
|
||||
}
|
||||
|
||||
fn persistLocalSave(
|
||||
allocator: std.mem.Allocator,
|
||||
io: std.Io,
|
||||
|
||||
+23
-4
@@ -474,6 +474,10 @@ pub const Client = struct {
|
||||
return self.saved_bytes orelse Error.NothingSaved;
|
||||
}
|
||||
|
||||
pub fn currentPath(self: *const Client) ?[]const u8 {
|
||||
return self.current_path;
|
||||
}
|
||||
|
||||
pub fn snapshotBytesAlloc(self: *const Client, allocator: std.mem.Allocator) ![]u8 {
|
||||
const snap = try self.session.snapshot();
|
||||
return allocator.dupe(u8, snap.bytes);
|
||||
@@ -487,6 +491,10 @@ pub const Client = struct {
|
||||
return self.discard_on_quit;
|
||||
}
|
||||
|
||||
pub fn openFilePicker(self: *Client) !void {
|
||||
try self.openFilePickerPanel();
|
||||
}
|
||||
|
||||
pub fn clearQuit(self: *Client) void {
|
||||
self.quit = false;
|
||||
self.discard_on_quit = false;
|
||||
@@ -669,11 +677,18 @@ pub const Client = struct {
|
||||
const path = repo_mod.gitPathFromStatusRow(selected) catch return Error.ProtocolRejected;
|
||||
const content = repo_mod.readRepoFileAlloc(self.allocator, io, cwd, path) catch return Error.ProtocolRejected;
|
||||
defer self.allocator.free(content);
|
||||
try self.session.openFixture(content);
|
||||
try self.openRepoContentAtPath(path, content, 0);
|
||||
try self.session.closePanel();
|
||||
self.message = null;
|
||||
}
|
||||
|
||||
fn openRepoContentAtPath(self: *Client, path: []const u8, content: []const u8, cursor: usize) !void {
|
||||
if (self.current_path) |old| self.allocator.free(old);
|
||||
self.current_path = try self.allocator.dupe(u8, path);
|
||||
try self.session.openFixtureAt(content, cursor);
|
||||
self.message = null;
|
||||
}
|
||||
|
||||
fn openJobRun(self: *Client, cwd_and_command: []const u8) !void {
|
||||
const io = self.io orelse return Error.ProtocolRejected;
|
||||
const split = splitCwdAndCommand(cwd_and_command) orelse return Error.ProtocolRejected;
|
||||
@@ -2239,9 +2254,13 @@ pub const Client = struct {
|
||||
self.message = "quit:discard";
|
||||
},
|
||||
.open => |path| {
|
||||
const line = try std.fmt.allocPrint(self.allocator, "open {s}", .{path});
|
||||
defer self.allocator.free(line);
|
||||
try self.applyProtocol(line);
|
||||
if (self.repo.content(path)) |content| {
|
||||
try self.openRepoContentAtPath(path, content, 0);
|
||||
} else |_| {
|
||||
const line = try std.fmt.allocPrint(self.allocator, "open {s}", .{path});
|
||||
defer self.allocator.free(line);
|
||||
try self.applyProtocol(line);
|
||||
}
|
||||
},
|
||||
.symbol => |symbol| try self.applyProtocol(symbol_mod.protocolCommand(symbol)),
|
||||
.file_picker => try self.openFilePickerPanel(),
|
||||
|
||||
Reference in New Issue
Block a user