summaryrefslogtreecommitdiff
path: root/src/exec.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-10-01 04:52:47 -0300
committerGabriel Schneider <[email protected]>2026-10-01 04:52:47 -0300
commite7aaeca8e12887e2b90aae257c41efce6847c26d (patch)
tree8e79ef09fe7060fbc0174cf76d15ca61bf8772d4 /src/exec.zig
parent3f328a0646268169012c8c0a36840ffaba34823b (diff)
downloadpardes-e7aaeca8e12887e2b90aae257c41efce6847c26d.tar.gz
pardes-e7aaeca8e12887e2b90aae257c41efce6847c26d.zip
A command pane an exec open was answered is leased to it while that open stays open: another client's command in the same directory gets a pane of its own
A finished command pane was the next command's for its directory, from any client, so with four clients scripting one session, one read another's output as its own last run. An open of a look or exec file whose write was answered a pane's serial now holds that pane: reuse passes over it and a new command pane runs the line. The open's own next command may run there again, and once it is closed the directory's one command pane is reused as before. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/exec.zig')
-rw-r--r--src/exec.zig16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/exec.zig b/src/exec.zig
index 47484105..ca48bed1 100644
--- a/src/exec.zig
+++ b/src/exec.zig
@@ -766,10 +766,13 @@ fn runCommand(p: *Pardes, from: usize, line: []const u8) ?usize {
// would hang that job up.
// From a column's tag, only a finished pane in that column is reused,
// as the new one goes in that column (placeNew).
- const reuse: ?usize = if (!p.exec_header and p.exec_column == null and src != null and src.?.command != null and src.?.command_done and !src.?.command_pty) from else for (p.panes, 0..) |slot, i| {
+ // Nor one leased: an open that was answered its serial and is still
+ // open reads that pane's output, which another client's command must
+ // not replace; a new pane runs it instead.
+ const reuse: ?usize = if (!p.exec_header and p.exec_column == null and src != null and src.?.command != null and src.?.command_done and !src.?.command_pty and !leased(p, src.?.serial)) from else for (p.panes, 0..) |slot, i| {
const other = slot orelse continue;
if (p.exec_column) |c| if (if (layout.findPane(p, i)) |f| f.col != c else true) continue;
- if (other.command != null and other.command_done and !other.command_pty and std.mem.eql(u8, other.cwdSlice(), dir)) break i;
+ if (other.command != null and other.command_done and !other.command_pty and std.mem.eql(u8, other.cwdSlice(), dir) and !leased(p, other.serial)) break i;
} else null;
if (reuse) |id| {
const pane = p.panes[id].?;
@@ -812,6 +815,15 @@ fn runCommand(p: *Pardes, from: usize, line: []const u8) ?usize {
return free;
}
+/// Whether an open of a look or exec file holds `serial` from its own write
+/// (tree.Open.results): its client is reading that pane.
+fn leased(p: *const Pardes, serial: u32) bool {
+ for (p.fs.opens) |o| if (o.node != 0 and o.results.wrote) {
+ if (std.mem.indexOfScalar(u32, o.results.list[0..o.results.len], serial) != null) return true;
+ };
+ return false;
+}
+
/// The serial a command's `$winid` names: the pane it was run from, none
/// (0) from a column's or the workspace's tag.
fn winid(p: *const Pardes, src: ?*Pane) u32 {