diff options
Diffstat (limited to 'src/builtins.zig')
| -rw-r--r-- | src/builtins.zig | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/builtins.zig b/src/builtins.zig index 5273cf37..be0956e0 100644 --- a/src/builtins.zig +++ b/src/builtins.zig @@ -852,6 +852,61 @@ pub const Tty9p = struct { /// Fold the active pane's column into the one on its right, keeping its panes. /// The horizontal mirror of the vertical stacking `New` does. +/// Binds this terminal as a language's REPL, by the language's name as the +/// syntax table has it: an exec made on the body of a file in that +/// language -- a middle click, the execute key, a single word like `ls` +/// as much as a selection -- and one made on this terminal's own body, is +/// typed into it (bracketed paste if its program asked for that, else line +/// by line, then Enter) instead of run. `Repl python` binds (again, it is +/// already); `Repl -` unbinds; `Repl` bare says what it is bound as. With +/// several bound for a language, the exec asks which. +/// Still commands, whatever is bound: a word in a tag, `Exec <text>` run by +/// name (typed, a 2-1 chord onto Exec, a ctl line), and a command word +/// @`cmd` in the text, looked at or clicked. +pub const Repl = struct { + pub const takes_arg = true; + pub fn run(c: Ctx) void { + const pane = c.pane; + if (!pane.isTerminal()) return c.p.reportFailure(c.id, "Repl: only a terminal is a REPL"); + const arg = std.mem.trim(u8, c.arg orelse "", " \t\r\n"); + var buf: [320]u8 = undefined; + var idbuf: [48]u8 = undefined; + if (arg.len == 0) { + if (pane.repl == null) return c.p.setMessage(c.id, "Repl: not bound"); + return c.p.setMessage(c.id, std.fmt.bufPrint(&buf, "Repl: {s}", .{exec.replId(&idbuf, pane)}) catch "Repl"); + } + if (std.mem.eql(u8, arg, "-")) { + pane.repl = null; + return c.p.setMessage(c.id, "Repl: unbound"); + } + const grammars = @import("grammar_manifest.zig").all; + const lang: u8 = for (grammars, 0..) |g, i| { + if (g.exts.len > 0 and std.mem.eql(u8, g.name, arg)) break @intCast(i); + } else { + var w = std.Io.Writer.fixed(&buf); + w.print("Repl: no language \"{s}\"; one of", .{arg[0..@min(arg.len, 32)]}) catch {}; + for (grammars) |g| if (g.exts.len > 0) w.print(" {s}", .{g.name}) catch break; + return c.p.reportFailure(c.id, w.buffered()); + }; + if (pane.repl) |r| if (r.lang == lang) + return c.p.setMessage(c.id, std.fmt.bufPrint(&buf, "Repl: {s}", .{exec.replId(&idbuf, pane)}) catch "Repl"); + // The lowest letter no other REPL of the language has: freed ones + // come back. + var letter: u8 = 'a'; + while (letter <= 'z') : (letter += 1) { + const taken = for (c.p.panes) |slot| { + const other = slot orelse continue; + if (other != pane) if (other.repl) |r| if (r.lang == lang and r.letter == letter) break true; + } else false; + if (!taken) break; + } + if (letter > 'z') return c.p.reportFailure(c.id, "Repl: every letter of the language is taken"); + pane.repl = .{ .lang = lang, .letter = letter }; + pane.repl_warned = false; + c.p.setMessage(c.id, std.fmt.bufPrint(&buf, "Repl: {s}", .{exec.replId(&idbuf, pane)}) catch "Repl"); + } +}; + pub const Joincol = struct { pub const scope: Scope = .session; pub fn run(c: Ctx) void { |
