summaryrefslogtreecommitdiff
path: root/src/exec.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/exec.zig')
-rw-r--r--src/exec.zig29
1 files changed, 24 insertions, 5 deletions
diff --git a/src/exec.zig b/src/exec.zig
index 56e6a2a9..d4480e00 100644
--- a/src/exec.zig
+++ b/src/exec.zig
@@ -312,7 +312,7 @@ pub fn spawnV9fsTty(p: *Pardes, from: usize) void {
fn spawnTtyWithMount(p: *Pardes, from: usize, v9fs: bool) ?*Pane {
const src = p.panes[from] orelse return null;
const free = p.freeSlot() orelse {
- p.reportFailure(from, "Tty: no pane free");
+ p.reportError(from, "Tty", error.NoPaneSlots);
return null;
};
const nt = p.newShell(free, Pardes.paneDir(src)) catch |err| {
@@ -443,6 +443,18 @@ fn routeToRepl(p: *Pardes, from: usize, text: []const u8) Routed {
return .asked;
}
+const repl_enter_wait_ns: u64 = 250 * std.time.ns_per_ms;
+
+/// Sends the Enters a paste into pane `id`'s REPL is owed: when the REPL
+/// has answered it (`answered`), or once the wait is up.
+pub fn flushReplEnter(p: *Pardes, id: usize, answered: bool) void {
+ const pane = p.panes[id] orelse return;
+ if (pane.repl_enter == 0) return;
+ if (!answered and p.stepped_ns < pane.repl_enter_due_ns) return;
+ for (0..pane.repl_enter) |_| p.emitWrite(id, "\r");
+ pane.repl_enter = 0;
+}
+
fn pythonBlockOpen(text: []const u8) bool {
const trimmed = std.mem.trimEnd(u8, text, " \t\n");
const start = if (std.mem.lastIndexOfScalar(u8, trimmed, '\n')) |nl| nl + 1 else 0;
@@ -475,13 +487,20 @@ pub fn sendToRepl(p: *Pardes, from: usize, to: usize, text: []const u8) void {
var said: [128]u8 = undefined;
return p.setMessage(from, std.fmt.bufPrint(&said, "Repl: {d} bytes is more than can be sent at once; send less", .{n}) catch "Repl: too long to send");
}
+ const pasted = panes.Terminal.bracketedPaste(dst);
edit.typeToTty(p, to, dst, clean[0..n]);
- p.emitWrite(to, "\r");
// A Python block whose last line is indented, or a bare header, is not
// over at one Enter, pasted into 3.13's REPL or typed into the old one:
// the blank line a second Enter gives ends it.
- if ((if (dst.repl) |r| r.lang == python_lang else false) and pythonBlockOpen(clean[0..n]))
- p.emitWrite(to, "\r");
+ const enters: u8 = if ((if (dst.repl) |r| r.lang == python_lang else false) and pythonBlockOpen(clean[0..n])) 2 else 1;
+ if (pasted) {
+ // An Enter read with the paste is part of it: 3.13's REPL takes it
+ // as a newline in the pasted text, even a one-line one, and waits.
+ // It goes once the REPL has answered the paste (its next output),
+ // or after a moment if nothing comes.
+ dst.repl_enter = enters;
+ dst.repl_enter_due_ns = p.stepped_ns + repl_enter_wait_ns;
+ } else for (0..enters) |_| p.emitWrite(to, "\r");
// Line by line, a blank line inside a Python block ends the block.
if (!panes.Terminal.bracketedPaste(dst) and !dst.repl_warned and (if (dst.repl) |r| r.lang == python_lang else false) and
std.mem.indexOfScalar(u8, text, '\n') != null)
@@ -590,7 +609,7 @@ fn runCommand(p: *Pardes, from: usize, line: []const u8) ?usize {
return id;
}
const free = p.freeSlot() orelse {
- p.reportFailure(from, "exec: no pane free for the command");
+ p.reportError(from, "exec", error.NoPaneSlots);
return null;
};
const pane = p.newCommand(free, dir, line) catch |err| {