diff options
Diffstat (limited to 'src/exec.zig')
| -rw-r--r-- | src/exec.zig | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/src/exec.zig b/src/exec.zig index 6e6f528b..b8312a21 100644 --- a/src/exec.zig +++ b/src/exec.zig @@ -444,12 +444,28 @@ fn routeToRepl(p: *Pardes, from: usize, text: []const u8) Routed { } const repl_enter_wait_ns: u64 = 250 * std.time.ns_per_ms; +/// Python echoes a long paste over several reads: its Enter waits for the +/// echo to go quiet this long, not for the first of it. +const repl_quiet_ns: u64 = 100 * std.time.ns_per_ms; + +/// The host's clock now; core time (`now_ns`, `stepped_ns`) is as old as +/// the last frame, seconds in an idle session. +fn clockNow(p: *Pardes) u64 { + return if (p.host.vtable.now) |clock| clock(p.host.ctx) else p.now_ns; +} /// 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. +/// has answered it (`answered`), or once the wait is up. Python's answer +/// only restarts a short wait, so the Enter goes once its echo of the +/// whole paste is in (a multi-line paste read in part would leave it at +/// `...`). 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 (if (pane.repl) |r| r.lang == python_lang else false)) { + pane.repl_enter_due_ns = clockNow(p) + repl_quiet_ns; + return; + } if (!answered and p.now_ns < pane.repl_enter_due_ns) return; for (0..pane.repl_enter) |_| p.emitWrite(id, "\r"); pane.repl_enter = 0; @@ -492,7 +508,11 @@ pub fn sendToRepl(p: *Pardes, from: usize, to: usize, text: []const u8) void { // 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. - const enters: u8 = if ((if (dst.repl) |r| r.lang == python_lang else false) and pythonBlockOpen(clean[0..n])) 2 else 1; + // So is a paste of more than one line: 3.13's REPL takes it as one + // input, which one Enter leaves at `...`. + const python = if (dst.repl) |r| r.lang == python_lang else false; + const lines = std.mem.count(u8, std.mem.trim(u8, clean[0..n], " \t\n"), "\n") + 1; + const enters: u8 = if (python and (pythonBlockOpen(clean[0..n]) or (pasted and lines > 1))) 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. @@ -503,8 +523,7 @@ pub fn sendToRepl(p: *Pardes, from: usize, to: usize, text: []const u8) void { // nobody watches), `stepped_ns` and `now_ns` are as old as the last // frame, and a wait counted from there would be over already, the // Enter going out with the paste. - const now = if (p.host.vtable.now) |clock| clock(p.host.ctx) else p.now_ns; - dst.repl_enter_due_ns = now + repl_enter_wait_ns; + dst.repl_enter_due_ns = clockNow(p) + 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 |
