summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-10-01 10:07:05 -0300
committerGabriel Schneider <[email protected]>2026-10-01 10:36:27 -0300
commit1f2653d96656ab55956b5798bf637372ce337e29 (patch)
tree61010e2bb73534a34f6f8bd0398d1b740153fc7f /src
parent3aa24c27c62c740cd7647831d0a14a9b180992da (diff)
downloadpardes-1f2653d96656ab55956b5798bf637372ce337e29.tar.gz
pardes-1f2653d96656ab55956b5798bf637372ce337e29.zip
A bound REPL whose program exited is skipped, as the docs say: out of the question, the running one taking the text, and a done command REPL's tag says no id
Two bound REPLs always asked, an exited one offered and, chosen, sent nothing. Now an exited one is left out: one still running takes the text with no question, none running is said (`no program running`), and nothing runs as a command. A command pane bound as a REPL whose command is done no longer shows its id in the tag. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/exec.zig13
-rw-r--r--src/pardes.zig18
-rw-r--r--src/tagline.zig5
3 files changed, 21 insertions, 15 deletions
diff --git a/src/exec.zig b/src/exec.zig
index 5b170375..ac6efcdd 100644
--- a/src/exec.zig
+++ b/src/exec.zig
@@ -554,16 +554,21 @@ fn routeToRepl(p: *Pardes, from: usize, text: []const u8) Routed {
return .{ .sent = from };
}
const lang = langOf(src) orelse return .none;
- // Every REPL bound for the language, a program running in it or not:
- // which one is the text's is never guessed from which happens to be
- // running now.
+ // Every REPL bound for the language whose program still runs: one
+ // whose program exited is skipped, in the question and in the choice.
var bound: [26]usize = undefined;
var n: usize = 0;
+ var exited: ?usize = null;
for (p.panes, 0..) |slot, i| if (slot) |pane| if (pane.repl) |r| if (r.lang == lang and n < bound.len) {
+ if (!replLive(p, i)) {
+ exited = i;
+ continue;
+ }
bound[n] = i;
n += 1;
};
- if (n == 0) return .none;
+ // Bound but none running: said, never run as a command instead.
+ if (n == 0) return if (exited) |i| replGone(p, from, p.panes[i].?) else .none;
if (n == 1) {
if (!replLive(p, bound[0])) return replGone(p, from, p.panes[bound[0]].?);
sendToRepl(p, from, bound[0], text);
diff --git a/src/pardes.zig b/src/pardes.zig
index 4e578791..1659a94b 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -1717,20 +1717,20 @@ test "a REPL bound for a language takes the exec made on a body in it; tags, Exe
try std.testing.expect(p.executeBuiltinLine(2, "Repl python"));
try std.testing.expectEqualStrings("python-b", exec.replId(&idbuf, p.panes[2].?));
- // Two bound always ask, whichever has a program running: one left
- // (Ctrl-D: the shell has the tty) is still offered, and chosen, it is
- // sent nothing, nothing runs, and that is said.
+ // A bound REPL whose program exited (Ctrl-D: the shell has the tty) is
+ // skipped: the one still running takes the text, no question asked;
+ // with none running, nothing runs and that is said.
host.taken[1] = false;
_ = exec.executeFrom(p, 0, "import os", true);
- try std.testing.expectEqual(Pane.Prompt.repl_choice, file.prompt);
- p.update(.{ .key = .{ .cp = 'a' } });
+ try std.testing.expectEqual(Pane.Prompt.none, file.prompt);
Sent.drain(p);
- try std.testing.expect(Sent.len[1] == 0 and Sent.len[2] == 0 and !Sent.spawned);
- try std.testing.expect(std.mem.indexOf(u8, file.msg[0..file.msg_len], "no program running") != null);
+ try std.testing.expectEqualStrings("import os\r", Sent.said(2));
host.taken[2] = false;
_ = exec.executeFrom(p, 0, "import os", true);
- try std.testing.expectEqual(Pane.Prompt.repl_choice, file.prompt);
- p.update(.{ .key = .{ .cp = Key.escape } });
+ try std.testing.expectEqual(Pane.Prompt.none, file.prompt);
+ Sent.drain(p);
+ try std.testing.expect(Sent.len[1] == 0 and Sent.len[2] == 0 and !Sent.spawned);
+ try std.testing.expect(std.mem.indexOf(u8, file.msg[0..file.msg_len], "no program running") != null);
host.taken[1] = true;
host.taken[2] = true;
diff --git a/src/tagline.zig b/src/tagline.zig
index 032fb5a0..5a9e2346 100644
--- a/src/tagline.zig
+++ b/src/tagline.zig
@@ -116,8 +116,9 @@ pub fn pathPrefix(arena: std.mem.Allocator, pane: *Pane) ![]const u8 {
if (pane.command_status) |n| return std.fmt.allocPrint(arena, "{s} ({s}{s}) exit {d}{s}{s}", .{ (try shownDir(arena, pane)), shown, more, n, gap, id });
return std.fmt.allocPrint(arena, "{s} ({s}{s}) exit ?{s}{s}", .{ (try shownDir(arena, pane)), shown, more, gap, id });
}
- // A bound REPL says what it is bound as, beside its Tty word.
- if (pane.repl != null) {
+ // A bound REPL says what it is bound as, beside its Tty word, while its
+ // program runs: a command REPL whose command exited says no id.
+ if (pane.repl != null and !(pane.command != null and pane.command_done)) {
var idbuf: [48]u8 = undefined;
return std.fmt.allocPrint(arena, "{s} {s}", .{ (try shownDir(arena, pane)), exec.replId(&idbuf, pane) });
}