diff options
Diffstat (limited to 'src/exec.zig')
| -rw-r--r-- | src/exec.zig | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/src/exec.zig b/src/exec.zig index dbda7217..57eaad8f 100644 --- a/src/exec.zig +++ b/src/exec.zig @@ -394,10 +394,15 @@ pub fn langOf(pane: *const Pane) ?u8 { return null; } -/// A bound REPL whose program can still take input: a command pane's is -/// gone once its command is done. -pub fn replLive(pane: *const Pane) bool { - return pane.repl != null and pane.isTerminal() and !(pane.command != null and pane.command_done); +/// A bound REPL whose program is there to take input: a command pane's +/// while its command runs; an interactive terminal's while a program, not +/// the shell, has its tty (the host's `tty_taken`) -- a python3 left with +/// Ctrl-D leaves the shell, which would run `import os` as ImageMagick's. +pub fn replLive(p: *const Pardes, id: usize) bool { + const pane = p.panes[id] orelse return false; + if (pane.repl == null) return false; + if (pane.command != null) return !pane.command_done; + return p.hostTtyTaken(id); } /// `python-a`. @@ -408,22 +413,37 @@ pub fn replId(buf: []u8, pane: *const Pane) []const u8 { const Routed = union(enum) { none, sent: usize, asked }; +/// The REPL bound here has no program running to take the text: said, +/// and nothing sent or run. +fn replGone(p: *Pardes, from: usize, repl: *const Pane) Routed { + var idbuf: [48]u8 = undefined; + var said: [128]u8 = undefined; + p.setMessage(from, std.fmt.bufPrint(&said, "Repl: {s} has no program running; nothing sent", .{replId(&idbuf, repl)}) catch "Repl: no program running"); + return .asked; +} + /// Where an exec from `from`'s body goes when a REPL is bound for it: the /// one there is, or a question when there are several. fn routeToRepl(p: *Pardes, from: usize, text: []const u8) Routed { const src = p.panes[from] orelse return .none; - if (src.repl != null and replLive(src)) { + if (src.repl != null) { + if (!replLive(p, from)) return replGone(p, from, src); sendToRepl(p, from, from, text); return .{ .sent = from }; } const lang = langOf(src) orelse return .none; var bound: [26]usize = undefined; var n: usize = 0; - for (p.panes, 0..) |slot, i| if (slot) |pane| if (pane.repl) |r| if (r.lang == lang and replLive(pane) and n < bound.len) { + var gone: ?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)) { + gone = i; + continue; + } bound[n] = i; n += 1; }; - if (n == 0) return .none; + if (n == 0) return if (gone) |i| replGone(p, from, p.panes[i].?) else .none; if (n == 1) { sendToRepl(p, from, bound[0], text); return .{ .sent = bound[0] }; @@ -593,6 +613,8 @@ fn noteRun(p: *Pardes, pane: *Pane, what: []const u8, said: []const u8) void { pub fn commandDone(p: *Pardes, id: usize, status: ?u8) void { const pane = p.panes[id] orelse return; pane.command_done = true; + // A REPL it was is gone with its command; the pane's next is not one. + pane.repl = null; pane.command_status = status; pane.body.mode = .normal; var buf: [16]u8 = undefined; |
