summaryrefslogtreecommitdiff
path: root/src/builtins.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-24 10:56:05 -0300
committerGabriel Schneider <[email protected]>2026-08-25 09:42:07 -0300
commitc3d0b84b7961ae26d2d654e7120821cc2d83d20d (patch)
tree0b9a060a8ff0ee7d83c8df5ca797a99e0d66c53e /src/builtins.zig
parent70bde600793ea70bd68832018a154671c6bf1512 (diff)
downloadpardes-c3d0b84b7961ae26d2d654e7120821cc2d83d20d.tar.gz
pardes-c3d0b84b7961ae26d2d654e7120821cc2d83d20d.zip
host: the core owns the event loop; every platform becomes a vtable of optional methods
Diffstat (limited to 'src/builtins.zig')
-rw-r--r--src/builtins.zig60
1 files changed, 42 insertions, 18 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index ca3cf931..b4447289 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -520,38 +520,37 @@ pub const ClipReplace = struct {
pub const Save = struct {
pub fn run(c: Ctx) void {
- // an output buffer has no file behind it — nothing to write
if (c.pane.file) |*f| {
- if (!output_pane.fileTraits(f.output).saves) return;
+ if (f.output != null) {
+ // an unsavable output (search/help) has nothing to write; a
+ // scratch (savable output) asks for a path and becomes a file
+ if (output_pane.fileTraits(f.output).saves) c.p.startSavePrompt(c.pane);
+ return;
+ }
+ // a real file: write in place, and this edit is now on disk
c.p.emit(.{ .save_file = .{ .pane = @intCast(c.id) } });
- // ...and this edit is now the one on disk. See File.saved_revision
- // for why the mark goes here rather than after the write.
f.saved_revision = f.revision;
+ return;
}
+ // a terminal: write its plaintext scrollback to a prompted path
+ if (c.pane.isTerminal()) c.p.startSavePrompt(c.pane);
}
};
-/// Ask the native shell for an atomically-created empty temporary file. The
-/// pane and its lifetime serial are the placement token: by the time IO
-/// finishes another column may be active, or this slot may even have been
-/// reused, and neither is permission to put the document somewhere else.
+/// An empty scratch buffer below the calling pane, inheriting its directory.
+/// No file exists yet, so Save asks for a path prefilled with that directory
+/// and, once written, the buffer becomes an ordinary file pane.
pub const New = struct {
+ pub const output: OutputTraits = .{ .name = config.scratch_buffer, .doc = true, .saves = true };
pub fn run(c: Ctx) void {
- if (c.p.freeSlot() == null) return;
- c.p.emit(.{ .new_file = .{ .pane = @intCast(c.id), .serial = c.pane.serial } });
+ c.p.newScratchBelow(c.id);
}
};
+/// The same empty scratch, opened in a fresh column beside the calling pane.
pub const Newcol = struct {
pub fn run(c: Ctx) void {
- const free = c.p.freeSlot() orelse return;
- if (!c.p.layoutCanSplitColumn(c.id)) return;
- const nt = c.p.newShell(free, "") catch return;
- nt.greet = true;
- // The shared preflight above is the complete geometry refusal set.
- // Pane creation does not alter layout, so the same split is infallible.
- std.debug.assert(c.p.layoutSplitColumn(c.id, free, false));
- c.p.active = free;
+ c.p.newScratchColumn(c.id);
}
};
@@ -601,6 +600,22 @@ pub const Delcol = struct {
}
};
+/// A shell in the calling pane's directory, raw from the first frame. On every
+/// pane's tagline: the fast path from wherever you are to a prompt there.
+pub const Newtty = struct {
+ pub fn run(c: Ctx) void {
+ c.p.spawnTty(c.id);
+ }
+};
+
+/// Fold the active pane's column into the one on its right, keeping its panes.
+/// The horizontal mirror of the vertical stacking `New` does.
+pub const Joincol = struct {
+ pub fn run(c: Ctx) void {
+ c.p.joinCol();
+ }
+};
+
pub const Tutor = struct {
pub fn run(c: Ctx) void {
const free = c.p.freeSlot() orelse return;
@@ -633,6 +648,15 @@ pub const Config = struct {
}
};
+/// This build's version and what changed to reach it, printed into an output
+/// buffer the same way Config prints the live settings.
+pub const Changelog = struct {
+ pub const output: OutputTraits = .{ .name = config.changelog_buffer };
+ pub fn run(c: Ctx) void {
+ output_pane.openChangelog(c.p, c.id) catch |err| c.p.reportError(c.id, "changelog", err);
+ }
+};
+
/// Source code for the concrete backend implementation of a Panel*/scene
/// effect. The bytes are embedded at build time, so this works from an
/// installed executable rather than depending on a source checkout.