summaryrefslogtreecommitdiff
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
parent70bde600793ea70bd68832018a154671c6bf1512 (diff)
downloadpardes-c3d0b84b7961ae26d2d654e7120821cc2d83d20d.tar.gz
pardes-c3d0b84b7961ae26d2d654e7120821cc2d83d20d.zip
host: the core owns the event loop; every platform becomes a vtable of optional methods
-rw-r--r--build.zig181
-rw-r--r--build.zig.zon4
-rw-r--r--docs/design.typ2
-rw-r--r--docs/lsp.md6
-rw-r--r--docs/web.md67
-rw-r--r--next-steps.txt28
-rw-r--r--src/CHANGELOG.md34
-rw-r--r--src/builtins.zig60
-rw-r--r--src/config.zig41
-rw-r--r--src/file_pane.zig5
-rw-r--r--src/grammar_manifest.zig1
-rw-r--r--src/gui/gui.zig903
-rw-r--r--src/host.zig289
-rw-r--r--src/look.zig14
-rw-r--r--src/macos.zig521
-rw-r--r--src/output_pane.zig12
-rw-r--r--src/pardes.zig1103
-rw-r--r--src/source_manifest.zig44
-rw-r--r--src/syntax.zig191
-rw-r--r--src/term_pane.zig99
-rw-r--r--src/tty/tty.zig1086
-rw-r--r--src/web.zig381
-rw-r--r--src/web/app.mjs106
-rw-r--r--test/snapshots/argv.golden16
-rw-r--r--test/snapshots/badutf.golden8
-rw-r--r--test/snapshots/boot.golden62
-rw-r--r--test/snapshots/builtins.golden228
-rw-r--r--test/snapshots/builtins.snap6
-rw-r--r--test/snapshots/chordcut.golden424
-rw-r--r--test/snapshots/cmdword.golden48
-rw-r--r--test/snapshots/cornerdrag-left.golden38
-rw-r--r--test/snapshots/cornerdrag.golden44
-rw-r--r--test/snapshots/cursorline.golden200
-rw-r--r--test/snapshots/doccol.golden30
-rw-r--r--test/snapshots/doccol.snap11
-rw-r--r--test/snapshots/dump.golden8
-rw-r--r--test/snapshots/dump.snap4
-rw-r--r--test/snapshots/edit.golden66
-rw-r--r--test/snapshots/exec-bigdrag.golden6
-rw-r--r--test/snapshots/exec.golden46
-rw-r--r--test/snapshots/fileedit.golden118
-rw-r--r--test/snapshots/filewatch.golden90
-rw-r--r--test/snapshots/filewatch.snap2
-rw-r--r--test/snapshots/find.golden132
-rw-r--r--test/snapshots/fsearch.golden370
-rw-r--r--test/snapshots/ghostty-mid.golden6
-rw-r--r--test/snapshots/grep.golden234
-rw-r--r--test/snapshots/grep.snap8
-rw-r--r--test/snapshots/hscroll.golden114
-rw-r--r--test/snapshots/images.golden268
-rw-r--r--test/snapshots/jumps.golden136
-rw-r--r--test/snapshots/jumps.snap19
-rw-r--r--test/snapshots/layout-close.golden30
-rw-r--r--test/snapshots/layout-open.golden68
-rw-r--r--test/snapshots/leader.golden88
-rw-r--r--test/snapshots/load.golden66
-rw-r--r--test/snapshots/load.snap4
-rw-r--r--test/snapshots/logquiet.golden4
-rw-r--r--test/snapshots/look-center.golden184
-rw-r--r--test/snapshots/look-dir.golden8
-rw-r--r--test/snapshots/look-file-1col.golden36
-rw-r--r--test/snapshots/look-file.golden120
-rw-r--r--test/snapshots/lookloaded.golden182
-rw-r--r--test/snapshots/lookpanes.golden148
-rw-r--r--test/snapshots/lookpanes.snap10
-rw-r--r--test/snapshots/lookrange.golden66
-rw-r--r--test/snapshots/lsp-rename.golden12
-rw-r--r--test/snapshots/lsp.golden42
-rw-r--r--test/snapshots/lspcomplete.golden50
-rw-r--r--test/snapshots/lspcompletemoved.golden4
-rw-r--r--test/snapshots/lspdebug.golden26
-rw-r--r--test/snapshots/lsprelpath.golden40
-rw-r--r--test/snapshots/modal.golden180
-rw-r--r--test/snapshots/msg.golden44
-rw-r--r--test/snapshots/multicursor.golden300
-rw-r--r--test/snapshots/nested-optout.golden28
-rw-r--r--test/snapshots/nested.golden24
-rw-r--r--test/snapshots/pipe.golden12
-rw-r--r--test/snapshots/psearch.golden100
-rw-r--r--test/snapshots/reflow.golden4
-rw-r--r--test/snapshots/respawn.golden26
-rw-r--r--test/snapshots/restore.golden8
-rw-r--r--test/snapshots/restore.snap8
-rw-r--r--test/snapshots/rsearch.golden206
-rw-r--r--test/snapshots/rsearch.snap2
-rw-r--r--test/snapshots/scroll.golden90
-rw-r--r--test/snapshots/scrolloff.golden112
-rw-r--r--test/snapshots/scrolloff.snap2
-rw-r--r--test/snapshots/selarg.golden18
-rw-r--r--test/snapshots/selregex.golden36
-rw-r--r--test/snapshots/shellset.golden12
-rw-r--r--test/snapshots/shellset.snap6
-rw-r--r--test/snapshots/shrinktag.golden30
-rw-r--r--test/snapshots/splitparent.golden32
-rw-r--r--test/snapshots/stepgrain.golden54
-rw-r--r--test/snapshots/syntax.golden206
-rw-r--r--test/snapshots/tag.golden50
-rw-r--r--test/snapshots/tag.snap8
-rw-r--r--test/snapshots/tagalign.golden50
-rw-r--r--test/snapshots/tagalign2col.golden16
-rw-r--r--test/snapshots/tagalign2col.snap14
-rw-r--r--test/snapshots/tagbottom.golden72
-rw-r--r--test/snapshots/tagbottomimage.golden250
-rw-r--r--test/snapshots/tagbottomshort.golden26
-rw-r--r--test/snapshots/tagcmd.golden24
-rw-r--r--test/snapshots/tagnav.golden128
-rw-r--r--test/snapshots/tagnav.snap8
-rw-r--r--test/snapshots/tagpath.golden34
-rw-r--r--test/snapshots/theme.golden276
-rw-r--r--test/snapshots/theme.snap12
-rw-r--r--test/snapshots/themesel.golden62
-rw-r--r--test/snapshots/tinywin.golden34
-rw-r--r--test/snapshots/topbarexec.golden18
-rw-r--r--test/snapshots/topbarexec.snap12
-rw-r--r--test/snapshots/tty.golden36
-rw-r--r--test/snapshots/ttyclick.golden24
-rw-r--r--test/snapshots/ttyedit.golden30
-rw-r--r--test/snapshots/ttyfollow.golden18
-rw-r--r--test/snapshots/ttyhelp.golden40
-rw-r--r--test/snapshots/ttyhelp.snap4
-rw-r--r--test/snapshots/ttylook.golden166
-rw-r--r--test/snapshots/ttyonly.golden6
-rw-r--r--test/snapshots/ttypaste.golden62
-rw-r--r--test/snapshots/ttypaste.snap32
-rw-r--r--test/snapshots/ttyprompt.golden18
-rw-r--r--test/snapshots/ttytaken.golden146
-rw-r--r--test/snapshots/ttytaken.snap6
-rw-r--r--test/snapshots/tutor.golden62
-rw-r--r--test/snapshots/wheeldrift.golden20
-rw-r--r--test/snapshots/winch.golden12
-rw-r--r--test/snapshots/windownav.golden62
-rw-r--r--test/snapshots/windownav.snap10
-rw-r--r--test/snapshots/windowops.golden170
-rw-r--r--test/snapshots/wrap.golden24
-rw-r--r--test/snapshots/yankpaste.golden16
-rw-r--r--test/web-snapshots/source-list.golden304
-rw-r--r--test/web-snapshots/source-list.snap2
-rw-r--r--test/web_harness.mjs56
-rw-r--r--tools/embed_zig_sources.zig177
139 files changed, 7481 insertions, 5764 deletions
diff --git a/build.zig b/build.zig
index 5fa3081a..2f9d085d 100644
--- a/build.zig
+++ b/build.zig
@@ -154,28 +154,6 @@ pub fn build(b: *std.Build) void {
}
shaders_step.dependOn(&update_shaders.step);
- // Web LOOK has a tiny read-only source filesystem. Generate one Zig module
- // on the host from every tracked or new/nonignored .zig path + its current
- // working-tree contents. The generator prefers Git as the ignore-aware
- // path filter and has a conservative filesystem fallback for source
- // archives without `.git`.
- const source_gen = b.addExecutable(.{
- .name = "pardes-embed-zig-sources",
- .root_module = b.createModule(.{
- .target = b.graph.host,
- .optimize = .ReleaseSafe,
- .root_source_file = b.path("tools/embed_zig_sources.zig"),
- }),
- });
- const run_source_gen = b.addRunArtifact(source_gen);
- run_source_gen.addDirectoryArg(b.path("."));
- const embedded_sources = run_source_gen.addOutputFileArg("embedded_sources.zig");
- // The tracked set can change without any already-known input changing, so
- // discovery intentionally runs whenever a consumer builds it.
- run_source_gen.has_side_effects = true;
- const inspect_sources = b.addInstallFileWithDir(embedded_sources, .{ .custom = "web" }, "embedded_sources.zig");
- b.step("embed-web-sources", "generate zig-out/web/embedded_sources.zig from working-tree .zig files").dependOn(&inspect_sources.step);
-
snap_build.addWeb(b);
if (is_web and !is_web_target) return failBuild(b, web_step, "-Dplatform=web requires -Dtarget=wasm32-freestanding");
@@ -212,6 +190,40 @@ pub fn build(b: *std.Build) void {
.link_libc = true,
});
+ // `pardes-isolate`: a THIRD compilation of the same graph whose only
+ // difference is one comptime bool. It cannot be the same binary with a
+ // flag, because the point is that the isolated build does not CONTAIN the
+ // filesystem: look.zig's libc paths compile away, so no runtime mistake
+ // can reach a disk that a `--flag` build still links.
+ //
+ // Only the tty platform has one. gui adds a GPU it would still need, and
+ // web/macos are libraries whose host owns main().
+ const isolated_mod: ?*std.Build.Module = if (platform == .tty) b.createModule(.{
+ .target = target,
+ .optimize = optimize,
+ .root_source_file = b.path("src/main.zig"),
+ .link_libc = true,
+ }) else null;
+
+ // Every module that compiles src/pardes.zig, so its wiring is applied once
+ // per dependency instead of once per module per dependency.
+ var core_mods_buf: [3]*std.Build.Module = .{ root_mod, hx_core_mod, undefined };
+ var core_mods_len: usize = 2;
+ if (isolated_mod) |m| {
+ core_mods_buf[2] = m;
+ core_mods_len = 3;
+ }
+ const core_mods = core_mods_buf[0..core_mods_len];
+
+ // The conditional dependencies, hoisted so one `wireCore` call at the end
+ // can name them all. The unconditional ones are ordinary consts below.
+ var zls_mod: ?*std.Build.Module = null;
+ var ts_mod: ?*std.Build.Module = null;
+ var ts_queries_opts: ?*std.Build.Step.Options = null;
+ var mupdf_core_mod: ?*std.Build.Module = null;
+ var ghostty_core_vt: ?*std.Build.Module = null;
+ var ts_libs: std.ArrayList(*std.Build.Step.Compile) = .empty;
+
// THEMES. tools/gen_themes.zig turns each vendored helix .toml / zed .json
// into one .zig file per theme plus a list.zig that imports them all;
// src/pardes.zig folds that list into the ring beside the three it ships.
@@ -243,8 +255,6 @@ pub fn build(b: *std.Build) void {
.optimize = optimize,
.root_source_file = themes_out.path(b, "list.zig"),
});
- root_mod.addImport("generated_themes", themes_mod);
- hx_core_mod.addImport("generated_themes", themes_mod);
// forkpty: in libc proper on glibc>=2.34 and darwin; the BSDs keep it in libutil
if (target.result.os.tag == .freebsd or target.result.os.tag == .netbsd or target.result.os.tag == .openbsd)
@@ -273,6 +283,9 @@ pub fn build(b: *std.Build) void {
// names: the .zon pins a commit, and a status screen that cannot say WHICH
// analyser answered is not worth opening.
opts.addOption([]const u8, "zls_version", if (zls_backend) zls_version else "none");
+ // Mirrors build.zig.zon's `.version`; kept in sync by hand because a typed
+ // @import of the .zon rejects its other fields on this Zig 0.16 build.
+ opts.addOption([]const u8, "version", "0.0.1");
// The stdlib this binary was compiled against, so `gd` on `std.mem.count`
// can open the same mem.zig the compiler used. ZLS resolves `@import("std")`
// through `zig_lib_dir` and nothing else; without it every std symbol is a
@@ -299,8 +312,7 @@ pub fn build(b: *std.Build) void {
.optimize = optimize,
.@"version-string" = @as([]const u8, zls_version),
});
- root_mod.addImport("zls", zls_dep.module("zls"));
- hx_core_mod.addImport("zls", zls_dep.module("zls"));
+ zls_mod = zls_dep.module("zls");
}
// Tracy zones (src/tracy.zig): compile the client into the binary only when
@@ -354,8 +366,7 @@ pub fn build(b: *std.Build) void {
.flags = &.{ "-std=c11", "-DNDEBUG=1" },
});
}
- root_mod.addImport("tree-sitter", tree_sitter_mod);
- hx_core_mod.addImport("tree-sitter", tree_sitter_mod);
+ ts_mod = tree_sitter_mod;
const ts_queries = b.addOptions();
inline for (grammar_manifest.all) |g| {
@@ -386,12 +397,10 @@ pub fn build(b: *std.Build) void {
if (g.scanner) lib.root_module.addCSourceFile(.{ .file = dep.path(g.src ++ "/scanner.c"), .flags = &ts_cflags });
lib.root_module.addIncludePath(dep.path(g.src));
if (is_web) lib.root_module.addIncludePath(b.path("src/web/libc/include"));
- root_mod.linkLibrary(lib);
- hx_core_mod.linkLibrary(lib);
+ ts_libs.append(b.allocator, lib) catch @panic("OOM");
}
}
- root_mod.addOptions("ts_queries", ts_queries);
- hx_core_mod.addOptions("ts_queries", ts_queries);
+ ts_queries_opts = ts_queries;
}
// zstbi (C stb_image): image pane decode. The freestanding core has no C
@@ -403,16 +412,12 @@ pub fn build(b: *std.Build) void {
.optimize = optimize,
.root_source_file = b.path("src/web/zstbi.zig"),
});
- root_mod.addImport("zstbi", zstbi_mod);
- hx_core_mod.addImport("zstbi", zstbi_mod);
// mvzr: the regex engine behind `s` / `S` (helix select/split on a regex).
// A bytecode VM that compiles a RUNTIME pattern into a fixed-size struct
// with no allocator at all, which is exactly the shape an interactive
// prompt needs — see applySelRegex in src/pardes.zig.
const mvzr_mod = b.dependency("mvzr", .{ .target = target, .optimize = optimize }).module("mvzr");
- root_mod.addImport("mvzr", mvzr_mod);
- hx_core_mod.addImport("mvzr", mvzr_mod);
// MuPDF is the default native PDF engine, but remains a genuinely optional
// dependency: with -Dmupdf=false (and by default on web), the lazy source
@@ -439,8 +444,7 @@ pub fn build(b: *std.Build) void {
.file = b.path("src/pdf_bridge.c"),
.flags = &.{"-std=gnu11"},
});
- root_mod.addImport("mupdf", mupdf_mod);
- hx_core_mod.addImport("mupdf", mupdf_mod);
+ mupdf_core_mod = mupdf_mod;
// Compile the @cImport + exception bridge and exercise the Zig
// wrapper's caller-owned RGBA boundary alongside the C end-to-end
// document probe below.
@@ -604,15 +608,26 @@ pub fn build(b: *std.Build) void {
const ghostty_vt = dep.module("ghostty-vt");
ghostty_vt_for_snap = ghostty_vt;
ghostty_vt.addImport("uucode", uucode_mod);
- root_mod.addImport("ghostty-vt", ghostty_vt);
- hx_core_mod.addImport("ghostty-vt", ghostty_vt);
+ ghostty_core_vt = ghostty_vt;
}
// override uucode on vaxis LAST so it wins over ghostty's build() wiring.
vaxis_mod.addImport("uucode", uucode_mod);
- root_mod.addImport("vaxis", vaxis_mod);
- hx_core_mod.addImport("vaxis", vaxis_mod);
- root_mod.addImport("uucode", uucode_mod);
- hx_core_mod.addImport("uucode", uucode_mod);
+
+ // One call per module instead of one line per module per dependency, and
+ // BEFORE the fold below, which reads what these imports put in the table.
+ for (core_mods) |m| wireCore(m, .{
+ .themes = themes_mod,
+ .zls = zls_mod,
+ .tree_sitter = ts_mod,
+ .ts_libs = ts_libs.items,
+ .ts_queries = ts_queries_opts,
+ .zstbi = zstbi_mod,
+ .mvzr = mvzr_mod,
+ .mupdf = mupdf_core_mod,
+ .ghostty_vt = ghostty_core_vt,
+ .vaxis = vaxis_mod,
+ .uucode = uucode_mod,
+ });
// --- the dependency module map, for `gd` on `@import("vaxis")` ---
//
@@ -662,10 +677,12 @@ pub fn build(b: *std.Build) void {
opts.addOption([]const []const u8, "module_names", mod_names);
opts.addOption([]const []const u8, "module_roots", mod_roots);
- root_mod.addOptions("pardes_config", opts);
- hx_core_mod.addOptions("pardes_config", opts);
const gui_effect_source_dir = if (gui_shader_sources_prebuilt) "shaders/prebuilt" else "shaders";
- for ([_]*std.Build.Module{ root_mod, hx_core_mod }) |mod| {
+ // Attached after the fold above, for the reason `opts` names, and with the
+ // embedded FILES: those are bytes rather than modules, and adding them
+ // earlier would list them in the module map as if they were importable.
+ for (core_mods) |mod| {
+ mod.addOptions("pardes_config", opts);
if (platform == .gui) for (gui_shaders) |name| mod.addAnonymousImport(
b.fmt("effect-source-{s}.glsl", .{name}),
.{ .root_source_file = b.path(b.fmt("{s}/{s}.glsl", .{ gui_effect_source_dir, name })) },
@@ -673,6 +690,24 @@ pub fn build(b: *std.Build) void {
if (platform == .macos) mod.addAnonymousImport("effect-source-crt.ci.metal", .{
.root_source_file = b.path("shaders/crt.ci.metal"),
});
+ // The virtual filesystem's two repo-root entries: `@embedFile` cannot
+ // reach outside the module's own directory, so they arrive by name.
+ // See src/source_manifest.zig.
+ mod.addAnonymousImport("root-build.zig", .{ .root_source_file = b.path("build.zig") });
+ mod.addAnonymousImport("root-build.zig.zon", .{ .root_source_file = b.path("build.zig.zon") });
+ }
+
+ // The one setting that produces a SECOND executable rather than changing
+ // this one: its own tiny options module, because duplicating `opts` to
+ // flip a single bool would be twenty lines that must then agree forever.
+ const iso_off = b.addOptions();
+ iso_off.addOption(bool, "isolated", false);
+ root_mod.addOptions("pardes_isolation", iso_off);
+ hx_core_mod.addOptions("pardes_isolation", iso_off);
+ if (isolated_mod) |m| {
+ const iso_on = b.addOptions();
+ iso_on.addOption(bool, "isolated", true);
+ m.addOptions("pardes_isolation", iso_on);
}
// SDL3 shell wiring (-Dplatform=gui). SDL3 and FreeType are both built
@@ -723,7 +758,6 @@ pub fn build(b: *std.Build) void {
root_mod.addAnonymousImport("embedded.dump.zon", .{
.root_source_file = if (std.fs.path.isAbsolute(dp)) .{ .cwd_relative = dp } else b.path(dp),
});
- root_mod.addAnonymousImport("embedded_sources", .{ .root_source_file = embedded_sources });
}
if (platform == .web) {
@@ -1009,6 +1043,24 @@ pub fn build(b: *std.Build) void {
b.installArtifact(exe);
const run = b.addRunArtifact(exe);
b.step("run", "descend to the pardes").dependOn(&run.step);
+ // `pardes-isolate`: the SAME source on the core's own defaults — the
+ // embedded source filesystem, the in-process clipboard, silent ptys.
+ // Its host keeps only the terminal it draws on, so nothing is forked
+ // and there is no filesystem in the binary to reach. A pardes that can
+ // only read itself.
+ if (isolated_mod) |iso| {
+ const iso_exe = b.addExecutable(.{
+ .name = "pardes-isolate",
+ .linkage = if (static) .static else null,
+ .root_module = iso,
+ });
+ b.installArtifact(iso_exe);
+ const run_iso = b.addRunArtifact(iso_exe);
+ // Something to look at on arrival, read out of the binary itself.
+ if (b.args) |args| run_iso.addArgs(args) else run_iso.addArg("src/pardes.zig");
+ b.step("run-isolated", "descend to a pardes with no host but the terminal")
+ .dependOn(&run_iso.step);
+ }
web_step.dependOn(&b.addFail("web needs -Dplatform=web -Dtarget=wasm32-freestanding -Ddump=<dump.zon>").step);
// snapshot parity suite: scripted input traces in a pty, captured grids
@@ -1309,3 +1361,36 @@ fn vendoredThemes(b: *std.Build, io: std.Io) []const []const u8 {
}.lt);
return names;
}
+
+/// Everything every compilation of src/pardes.zig needs, in one call per module
+/// rather than a line per module beside every dependency — which is the shape
+/// that let a third module quietly miss two of them.
+///
+/// Fields are in the order these used to be attached in, because that order IS
+/// the module map `Debug` prints (import_table iterates by insertion), and a
+/// refactor that renumbers a user-visible list changed something.
+fn wireCore(m: *std.Build.Module, d: struct {
+ themes: ?*std.Build.Module = null,
+ zls: ?*std.Build.Module = null,
+ tree_sitter: ?*std.Build.Module = null,
+ ts_libs: []const *std.Build.Step.Compile = &.{},
+ ts_queries: ?*std.Build.Step.Options = null,
+ zstbi: ?*std.Build.Module = null,
+ mvzr: ?*std.Build.Module = null,
+ mupdf: ?*std.Build.Module = null,
+ ghostty_vt: ?*std.Build.Module = null,
+ vaxis: ?*std.Build.Module = null,
+ uucode: ?*std.Build.Module = null,
+}) void {
+ if (d.themes) |x| m.addImport("generated_themes", x);
+ if (d.zls) |x| m.addImport("zls", x);
+ if (d.tree_sitter) |x| m.addImport("tree-sitter", x);
+ for (d.ts_libs) |lib| m.linkLibrary(lib);
+ if (d.ts_queries) |x| m.addOptions("ts_queries", x);
+ if (d.zstbi) |x| m.addImport("zstbi", x);
+ if (d.mvzr) |x| m.addImport("mvzr", x);
+ if (d.mupdf) |x| m.addImport("mupdf", x);
+ if (d.ghostty_vt) |x| m.addImport("ghostty-vt", x);
+ if (d.vaxis) |x| m.addImport("vaxis", x);
+ if (d.uucode) |x| m.addImport("uucode", x);
+}
diff --git a/build.zig.zon b/build.zig.zon
index 9ccb686f..2d745db6 100644
--- a/build.zig.zon
+++ b/build.zig.zon
@@ -160,6 +160,10 @@
.url = "git+https://github.com/airbus-cert/tree-sitter-powershell#d398441825243b00e317e87e1829b9d6a3e54ce0",
.hash = "N-V-__8AAKzlUACji5nMCtCC_dgDtF1rEg1qoduDm3MT5B5H",
},
+ .ts_markdown = .{
+ .url = "git+https://github.com/tree-sitter-grammars/tree-sitter-markdown#split_parser",
+ .hash = "N-V-__8AAPRhUwBHS53YVU2fqpXuZ8VMvL_vIKp2AQo4Ja7V",
+ },
.mvzr = .{
.url = "git+https://github.com/mnemnion/mvzr#3efcfe339bd32e122c36b8f1db25b237f93a7ec2",
.hash = "mvzr-0.3.9-ZSOky6t2AQCA7efmm5EYbPb5sOdbXa4EFsUgYbQ6hZv9",
diff --git a/docs/design.typ b/docs/design.typ
index 0d8f03dd..3e387f7a 100644
--- a/docs/design.typ
+++ b/docs/design.typ
@@ -104,7 +104,7 @@ serial and carry only phase, effect, frame, and from/to cell boxes. Canonical
layout is committed immediately; tracks are finite presentation data.)
*Effect* (out, queued): `spawn{pane, cwd}`, `write{pane, bytes}`,
-`resize_pty{pane, cols, rows}`, `open_link`, `new_file{pane, serial}`,
+`resize_pty{pane, cols, rows}`, `open_link`,
`save_file{pane}`, `write_dump`, `set_clipboard`, `read_clipboard`, `lsp`,
`pipe`, `watch`, `quit`.
The core never performs IO for any of these; it asks — and four of the asks have an
diff --git a/docs/lsp.md b/docs/lsp.md
index 0125f958..54ffd764 100644
--- a/docs/lsp.md
+++ b/docs/lsp.md
@@ -33,9 +33,9 @@ about thirty lines per shell: `tty.zig` uses `io.concurrent` + the vaxis loop
queue, `gui.zig` uses a detached thread + the mutex queue it already had. The
web shell compiles in no backend at all (`zls_backend` is off for wasm), which
makes `lsp.supports` empty, which makes `lspRequest` return before it emits —
-so on the web the effect is never even raised. `web.zig` carries a prong for it
-and exports `pardes_lsp_response` anyway; both are unreachable in the shipped
-configuration and wait for a host that links a backend.
+so on the web the effect is never even raised. `web.zig` leaves the host's
+`lsp` method null and exports nothing for a response; a host that links a
+backend would add both.
Three rules make it safe:
diff --git a/docs/web.md b/docs/web.md
index 793c79bc..0f8c068f 100644
--- a/docs/web.md
+++ b/docs/web.md
@@ -1,10 +1,11 @@
# DOM web backend
The web backend keeps the existing Pardes core and replaces the old
-Emscripten/SDL/WebGL shell. Zig produces a `wasm32-freestanding` module with no
-imports. Vanilla JavaScript owns `requestAnimationFrame`, browser input, window
-sizing, and effect/IO dispatch; HTML and CSS render selectable, accessible text.
-There is no canvas.
+Emscripten/SDL/WebGL shell. Zig produces a `wasm32-freestanding` module whose
+only imports are the four browser capabilities listed below — no libc, no WASI,
+no runtime. JavaScript owns `requestAnimationFrame`, browser input and window
+sizing; the CORE owns the loop and JavaScript calls one iteration of it per
+frame. HTML and CSS render selectable, accessible text. There is no canvas.
The default web build links Tree-sitter's C runtime and the Zig grammar inside
that same import-free module. A small freestanding compatibility layer supplies
@@ -12,11 +13,20 @@ the C ABI locally, so source panes retain the core's Tree-sitter highlighting
without Emscripten, WASI, or browser libc imports. Other grammar tiers remain
selectable with `-Dtree-sitter=minimal` or `-Dtree-sitter=full`.
-`src/web.zig` is the narrow WASM ABI. Events enter through exported functions,
-and `pardes_frame` writes the canonical `Surface` into a packed 20-byte cell
-array. `src/web/app.mjs` reads that array in one linear pass and patches stable
-DOM nodes. Core effects become browser operations (links, downloads, clipboard)
-or `pardes-io` custom events for a process-capable embedding host.
+`src/web.zig` is the narrow WASM ABI. Events enter through exported functions
+that hand them straight to `Pardes.update`. `pardes_tick` is one
+`Pardes.pump` — queued input, effects, render, present — and the host's
+`present` packs the canonical `Surface` into a 20-byte cell array that
+`pardes_frame`/`_ptr`/`_cols`/`_rows` describe. `src/web/app.mjs` reads that
+array in one linear pass and patches stable DOM nodes.
+
+Animated time is JavaScript's alone. `pardes_animation_tick` spends one fixed
+60 Hz step and is the only entry that advances a transition, exactly as the
+AppKit shell keeps its display clock apart from its pumps: if every input pump
+also advanced a fade, a burst of keys would collapse ten frames into one.
+`pardes_tick` never advances animated time itself, and no longer has to undo
+anything to avoid it: `Pardes.pump` does not post a tick for its caller, since
+only the host knows when a real frame interval has passed.
Cell attribute bit 7 carries the core's tagline font role. The DOM keeps every
cell at the body grid's fixed width and height, but scales and centres the
@@ -65,22 +75,37 @@ and no host filesystem, so there is no startup config directory, init file,
ThemeFile, or DumpThemes; LOOK resolves
against the build-generated source archive rather than disk, and no language
BACKEND is compiled in (`zls_backend` is off for wasm — which also means
-`lsp.supports` is empty, so the core never even raises a language query there;
-`web.zig`'s prong for it is waiting for a host that links one).
+`lsp.supports` is empty, so the core never even raises a language query there,
+and the host leaves `lsp` null).
Replay terminals retain the same core shape but use Zig's failing IO value;
this keeps the module freestanding without instantiating POSIX threaded IO that
the browser can never call.
-The EFFECTS themselves are all still emitted, each as a numbered code across
-the ABI: `spawn` 1, `write` 2, `resize_pty` 3, `open_link` 4, `save_file` 5,
-`write_dump` 6, `set_clipboard` 7, `lsp` 8, `watch` 9, `quit` 10, `new_file`
-11, `pipe` 12, `read_clipboard` 13. Inbound, `pardes_output`,
-`pardes_set_cwd`, `pardes_eof`, `pardes_paste` and `pardes_lsp_response`
-exist to answer them. A plain page ignores most of those and gets a replay
-viewer; a
-process-capable host (the `pardes-io` events above) answers them and gets
-terminals. The core does not know the difference — that is the point of the
-seam.
+`src/web.zig` fills in six methods of `Host.VTable` and leaves the rest null,
+and a null method is answered by the core itself rather than forwarded to a
+page that could not honour it. The six are `present`, `write_file`,
+`write_dump`, `set_clipboard`, `read_clipboard` and `open_link`; the last five
+are backed by four imports from the module `pardes` that JavaScript supplies at
+instantiation, because a written file and a written dump are both a download:
+
+| import | effect behind it |
+|---|---|
+| `host_open_link(url, len)` | `open_link` — `window.open` |
+| `host_set_clipboard(text, len)` | `set_clipboard` — `navigator.clipboard.writeText` |
+| `host_read_clipboard()` | `read_clipboard` — answered later, or never, by `pardes_paste` |
+| `host_download(path, path_len, bytes, len)` | `save_file`, `save_text` and `write_dump`: a file a page writes is a download |
+
+What the core answers instead of asking: `spawn`, `pty_write` and `pty_resize`
+land in the per-instance fallback, so a pane with no child is SILENT rather
+than synthetic; `tty_taken` is never taken; any save the page declines resolves
+against the core's virtual filesystem, which is also where every read comes
+from — the core reads files itself and never asks a host; `watch_file` records
+the request; `lsp` answers an empty row set at once (`zls_backend` is off for
+wasm, so the core never raises a query there anyway) and `pipe` answers
+failure; `wait_input` is null because wasm must never block, and `theme_file`
+and `dump_themes` are not reachable without a config directory. `quit` sets the
+core's flag, which `pardes_should_quit` reports so the page can stop its frame
+loop.
Two dependency-free test layers cover the boundary:
diff --git a/next-steps.txt b/next-steps.txt
index 451a25dd..86e53908 100644
--- a/next-steps.txt
+++ b/next-steps.txt
@@ -1,4 +1,24 @@
-+ The selection colors should be based on the theme.
-+ The default layout for when just opening a file should be just the file without the term.
-+ Implement soft line breaks with a builtin to toggle it; the line breaks at min(100 chars, window width)
-+ A new UI semantic element will be implemented which is the transient message section: it will be the latest row of a pane. When executing any builtin that requires and string argument but none was provided right now it should ask for input at the tagline. now it will be at this transient msg that will be left-aligned on the last row. Also when saving a file or a file is reloaded it should display a message there saying the time and what happened. the message should clear when any key on the keyboard is pressed or any mouse button is moved \ No newline at end of file
+meta:
+- version tracking
+- special coloring algorithms are aplied based on the title of a pane. implemented as just ifs and else ifs. one of those ifs will be the one that choses the color algorithm for tty panes, other will select the treesitter coloring for sourcode files, and the other one will be the new one to highlight .patch and .diff files
+- added markdown treesitter highlight with highlighiting of nested codeblocks
+
+new builtin:
+- Changelog
+- Newtty: Added by default on all pane taglines. It will spawn a new tty pane (at tty mode from the start) on the directory of the pane that called it. The pane struct field for the working directory should be a tagged enum for either .none, .inherited (with a pointer to the pane it inherits) or the dir slice itself. when a pane is deleted in a frame, its allocation will leave until the end of the next. During the next frame the deleted frames will be in a special list of deleted frames. this deleted pane list state will live on a new allocator: the pane allocator which will wrap a regular allocator, and this newly deleted list is passed to the pane tick/update/frame as a pointer so that it can just access it. this new allocator will also have the tick/update function so that it wires de regular allocator dealloc/free to the deleted list and the deferred actual deallocation. the pane struct will have a new function that will visit each kind of field that has a pane pointer in it and decide how to update it based on the field type when the pointer is on the deleted list; it's fine that during the runtime each field visits each pointer O(n*m).
+- Joincol: added by default on the full window tagline. it deletes the column of the current/last focused pane and moves its panes to the column to the right. if there's no other column it should do nothing
+
+keyboard:
+- in a tty pane if the current/leaf process is a shell, ESC will have the same behaviour as SHIFT-ESC
+
+
+layout behaviour:
+- When opening a new file, it will only create a new column if both panes affected will have at least 100 columns each. Otherwise will just create a new pane.
+
+bug fix:
+- the tty colors are affected by changes to its normal mode
+
+tests:
+
+- if tty escape scanning is active (chosen when libvaxis is created) it should always use all the features it detects by default.
+- clipboard integration for tty escape codes should work. \ No newline at end of file
diff --git a/src/CHANGELOG.md b/src/CHANGELOG.md
new file mode 100644
index 00000000..61e670d6
--- /dev/null
+++ b/src/CHANGELOG.md
@@ -0,0 +1,34 @@
+# Changelog
+
+## 0.0.1
+
+- Version tracking: the compiled version is embedded from build.zig.zon and shown by Changelog.
+- New builtins: Changelog, Newtty, and Joincol.
+- Markdown tree-sitter highlighting, including nested fenced code blocks.
+- `.patch` and `.diff` files are highlighted.
+- Coloring dispatch keys off the buffer title.
+- Opening a new file only splits into a new column when both panes would be at least 100 columns wide.
+- Terminal ANSI colors render only in tty mode; normal mode is a plain editing
+ view, so an edit can never shift a shell row's colour.
+- `New` and `Newcol` open an empty scratch buffer instead of a shell or a
+ temporary file. Its directory is inherited from the pane it was opened from.
+- `Save` on a scratch asks for a path, prefilled with that inherited
+ directory, and the buffer becomes an ordinary file once written.
+- `Save` on a terminal writes its plaintext scrollback to a prompted path and
+ leaves the pane a terminal.
+- A dropped pane's memory outlives its frame, so a pane pointer taken during
+ that frame stays valid until the next one repairs it.
+- The core owns the event loop. Each platform is now a `Host` of optional
+ function pointers; an unimplemented method falls back to an in-process
+ default, so a host with no methods at all is still a complete pardes.
+- Ctrl-V and Ctrl-Shift-V paste in a tty pane: the default register and the
+ system clipboard, typed at the program the way a terminal emulator pastes
+ (bracketed under mode 2004). A paste arriving from the desktop reaches the
+ shell instead of an edit buffer the pty cannot see.
+- The default filesystem is pardes's own source, embedded from an allowlist
+ (src/source_manifest.zig): what a host with no file method reads, and what
+ the browser has always read. It replaced a build-time generator that embedded
+ every tracked .zig file.
+- `zig build run-isolated` builds and runs `pardes-isolate`: the same source
+ with one comptime option, whose host supplies only the terminal. The
+ filesystem is not disabled in it, it is absent — the libc paths compile away.
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.
diff --git a/src/config.zig b/src/config.zig
index a01db954..685d083a 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -131,14 +131,17 @@ pub const leader_path = paths: {
// New here, which frees `w` for the window group (SPC w h/j/k/l).
.Save = "fs",
.New = "fn",
+ .Newtty = "nt",
.Find = "ff",
.Grep = "fg",
// the config FILE joins the file group: `SPC f c` says where pardes
// read (or would read) its startup commands from.
.Config = "fc",
.Tutor = "ht",
+ .Changelog = "hc",
.Newcol = "cn",
.Delcol = "cd",
+ .Joincol = "cj",
.Debug = "td",
// `Msg` takes the text to post, so it has no path, for the reason
// `Theme` and the two acme verbs below have none: a key path names a
@@ -336,6 +339,28 @@ pub const tty_toggle_default: u21 = 'b';
/// means what Escape always means.
pub const tty_toggle_alt: []const Chord = &.{.{ .cp = Key.escape, .shift = true }};
+/// Paste INTO the program a tty pane is running. `SPC p` and the acme 1-3
+/// chord cannot be reached there — the pty owns every keystroke and every
+/// button — so raw tty mode needs its own pair, and these are the two a
+/// terminal user already has in their hands.
+///
+/// The split is the one the whole clipboard design rests on: Ctrl-V types the
+/// DEFAULT register (what `y` put there, no round trip, no desktop involved),
+/// Ctrl-Shift-V asks for the SYSTEM clipboard. Two spellings for the second
+/// because a host may or may not fold the shift into the codepoint, and it
+/// must be tested BEFORE the first: `hit` ignores an unasked shift, so plain
+/// Ctrl-V matches a shifted key too.
+///
+/// What this TAKES: forwardKey encoded both as the same byte, 0x16, so
+/// Ctrl-Shift-V was a duplicate ^V and costs nothing to claim. Ctrl-V was
+/// readline's quoted-insert, and that one is now unreachable in a tty pane —
+/// the trade a terminal user expects, and one line to give back.
+pub const tty_paste: []const Chord = &.{.{ .cp = 'v', .ctrl = true }};
+pub const tty_paste_clipboard: []const Chord = &.{
+ .{ .cp = 'v', .ctrl = true, .shift = true },
+ .{ .cp = 'V', .ctrl = true },
+};
+
/// What LEAVING raw tty mode hides on the shell's prompt rows.
///
/// A prompt is CHROME. `user@host ~/src $` is redrawn on every keystroke, says
@@ -381,16 +406,16 @@ pub const tty_blank: enum { prompt, prompt_and_input } = .prompt;
// thing that would tell you the leader exists, is exactly what you cannot
// press. Row 0 is not a pane, so a middle-click on it is dispatched before any
// pane's mode is consulted: Help works in tty mode, which earns its width.
-pub const topbar_str = "New Newcol Find Grep Help Tutor Dump NextColor Debug Kill";
+pub const topbar_str = "New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill";
/// the default editable tail of a pane's tag, per kind (an output buffer has
/// no file to Save, so it gets the plain one). Terminals alone expose Filter,
/// the pane-local theme-keyed colour projection. Save stays first on real
/// files: `:` parks at the tail boundary, so the established `:w<Tab>`
/// spelling still walks to Save while New remains visible on every pane.
-pub const pane_builtins_str = "New Del";
-pub const file_pane_builtins_str = "Save New Del";
-pub const terminal_pane_builtins_str = "New Del Filter";
+pub const pane_builtins_str = "New Newtty Del";
+pub const file_pane_builtins_str = "Save New Newtty Del";
+pub const terminal_pane_builtins_str = "New Newtty Del Filter";
/// Columns kept clear to the RIGHT of a tagline's builtins. The path stays at
/// the left edge and the builtins are pushed over to end this far short of the
@@ -719,6 +744,10 @@ pub const find_marker = " Find /";
pub const grep_marker = " Grep /";
pub const rename_marker = " Rename /";
pub const symbol_marker = " WsSymbols /";
+/// Save on a scratch buffer or a terminal: the tail is the whole PATH to write
+/// (no `/` separator, since a path is made of them), prefilled with the pane's
+/// directory so only a filename need be typed.
+pub const save_marker = " Save ";
/// helix `s` / `S`. The only two markers whose word is NOT a builtin — there
/// is no Select/Split command to run from a tag, they name the key that armed
/// the input so the tag still reads as what it is about to do. They also mark
@@ -744,6 +773,10 @@ pub const fonts_buffer = "+Fonts";
pub const pdf_sections_buffer = "+PdfSections";
pub const hover_buffer = "+Hover";
pub const lsp_buffer = "+Lsp";
+pub const changelog_buffer = "+Changelog";
+/// The empty buffer New and Newcol open: no file behind it yet, so Save asks
+/// for a path (prefilled with the inherited directory).
+pub const scratch_buffer = "+New";
// ============================================================================
// PART 3 — THE HELIX KEYMAP. READ THIS BEFORE RETARGETING ANYTHING BELOW.
diff --git a/src/file_pane.zig b/src/file_pane.zig
index fd0ab2b7..42e5dba9 100644
--- a/src/file_pane.zig
+++ b/src/file_pane.zig
@@ -545,7 +545,10 @@ pub fn refreshHighlights(p: *Pardes) void {
const slack: usize = if (f.highlights.len == 0) 0 else pane.rows;
const start = lineStart(p.gpa, f, f.scroll -| slack);
const end = @max(start, lineStart(p.gpa, f, f.scroll + pane.rows + SYNTAX_CONTEXT_AFTER_ROWS + slack));
- const new_highlights = syntax.highlightFileRange(p.tree_sitter_gpa, f.path, f.content, start, end) catch {
+ const new_highlights = (switch (pane.colorAlgo()) {
+ .diff => syntax.highlightDiff(p.tree_sitter_gpa, f.content, start, end),
+ else => syntax.highlightFileRange(p.tree_sitter_gpa, f.path, f.content, start, end),
+ }) catch {
f.syntax_dirty = false;
continue;
};
diff --git a/src/grammar_manifest.zig b/src/grammar_manifest.zig
index 101cd6f6..01df9e34 100644
--- a/src/grammar_manifest.zig
+++ b/src/grammar_manifest.zig
@@ -33,6 +33,7 @@ pub const all = [_]Grammar{
.{ .name = "json", .dep = "ts_json", .exts = &.{".json"}, .tier = .full },
.{ .name = "kotlin", .dep = "ts_kotlin", .exts = &.{ ".kt", ".kts" }, .tier = .full, .scanner = true },
.{ .name = "ocaml", .dep = "ts_ocaml", .exts = &.{ ".ml", ".mli" }, .tier = .full, .src = "grammars/ocaml/src", .scanner = true },
+ .{ .name = "markdown", .dep = "ts_markdown", .exts = &.{ ".md", ".markdown" }, .tier = .full, .src = "tree-sitter-markdown/src", .scanner = true, .query = "tree-sitter-markdown/queries/highlights.scm" },
.{ .name = "pascal", .dep = "ts_pascal", .exts = &.{ ".pas", ".pp", ".p" }, .tier = .full },
.{ .name = "php", .dep = "ts_php", .exts = &.{ ".php", ".phtml", ".php3", ".php4", ".php5" }, .tier = .full, .src = "php/src", .scanner = true },
.{ .name = "powershell", .dep = "ts_powershell", .exts = &.{ ".ps1", ".psm1", ".psd1" }, .tier = .full, .scanner = true },
diff --git a/src/gui/gui.zig b/src/gui/gui.zig
index 63fe2091..e080dd9a 100644
--- a/src/gui/gui.zig
+++ b/src/gui/gui.zig
@@ -13,6 +13,7 @@ const linux = std.os.linux; // inotify constants; referenced only on linux
const vaxis = @import("vaxis"); // test modes only: the stdin escape-seq parser
const ghostty_vt = @import("ghostty-vt"); // 256-color palette for .index cells
const pardes = @import("../pardes.zig");
+const host_api = @import("../host.zig"); // LspRequest, the one host type not re-exported
const config = @import("../config.zig");
const look = @import("../look.zig");
const message = @import("../message.zig");
@@ -23,7 +24,6 @@ const crt = @import("crt.zig");
const fonts = @import("../fonts.zig"); // the Font builtin's half of the seam
const selection_pipe = @import("../selection_pipe.zig");
-const temp_file = @import("../temp_file.zig");
const shell_bin = @import("../shell_bin.zig");
const nested = @import("../nested.zig");
@@ -160,9 +160,10 @@ const touch_scroll_tick: f32 = 0.02;
/// SDL input can wake the loop faster than display cadence, so ticking once
/// per pass would make animation duration depend on pty traffic or mouse
-/// motion. This monotonic gate keeps it near 60 Hz without sleeping the event
-/// loop. It is consulted only AFTER a successful presentation: the current
-/// sample reaches the screen before the display interval may advance it.
+/// motion — and `pump` deliberately spends no animation time of its own. This
+/// monotonic gate keeps it near 60 Hz without sleeping the event loop. It is
+/// consulted only AFTER a successful presentation: the current sample reaches
+/// the screen before the display interval may advance it.
const AnimationClock = struct {
next_ns: u64 = 0,
@@ -1138,7 +1139,7 @@ fn lspThread(lsp_allocator: std.mem.Allocator, workers: *LspWorkers, job: *LspJo
/// Copy the query out of the core and hand it to a thread. A detached thread
/// per query is fine at this rate: one keystroke, one query, and the queue
/// already tolerates a late push after close.
-fn spawnLsp(core: *pardes.Pardes, q: *Queue, e: anytype) void {
+fn spawnLsp(core: *pardes.Pardes, q: *Queue, e: host_api.LspRequest) void {
const lsp_allocator = q.lsp_allocator;
const pane = core.panes[e.pane] orelse return;
// a pane with no file still asks `status` (it is about the backend, not
@@ -1158,7 +1159,7 @@ fn spawnLsp(core: *pardes.Pardes, q: *Queue, e: anytype) void {
lsp_allocator.destroy(job);
return;
},
- .arg = lsp_allocator.dupe(u8, e.arg.slice()) catch {
+ .arg = lsp_allocator.dupe(u8, e.arg) catch {
lsp_allocator.free(job.path);
lsp_allocator.free(job.source);
lsp_allocator.destroy(job);
@@ -1195,19 +1196,19 @@ fn spawnPipe(
gpa: std.mem.Allocator,
q: *Queue,
tasks: *PipeTasks,
- request: anytype,
+ id: u32,
) void {
if (tasks.len == tasks.items.len) {
- core.update(.{ .pipe_resp = .{ .id = request.id, .success = false, .outputs = &.{} } });
+ core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } });
return;
}
- const view = core.pipeRequest(request.id) orelse return;
+ const view = core.pipeRequest(id) orelse return;
const job = selection_pipe.Job.copy(gpa, view) catch return;
const future = io.concurrent(pipeThread, .{ io, gpa, job, q }) catch {
job.deinit(gpa);
return;
};
- std.debug.assert(tasks.add(.{ .id = request.id, .future = future }));
+ std.debug.assert(tasks.add(.{ .id = id, .future = future }));
}
// ---- the renderer state ----
@@ -1836,6 +1837,7 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options) !void {
opts.image_allocator = allocs.image;
opts.pdf_allocator = allocs.pdf;
opts.tree_sitter_allocator = allocs.tree_sitter;
+ opts.frame_allocator = allocs.frame;
var pw: c_int = 0;
var ph: c_int = 0;
if (opts.load_path != null) {
@@ -1866,13 +1868,11 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options) !void {
var ptys: [pardes.MAX_PANES]?Pty = @splat(null);
// per-slot spawn generation: drops a dead shell's late output/eof when its
- // pane id has been respawned (see drainEffects .spawn)
+ // pane id has been respawned (see the host's spawnPane)
var gens: [pardes.MAX_PANES]u32 = @splat(0);
defer for (&ptys) |*slot| if (slot.*) |pt| {
_ = libc.close(pt.fd);
};
- // the core's one way to ask about those ptys, pulled at the Exec that cares
- core.tty_query = .{ .ctx = &ptys, .taken = &ttyTakenAt };
var lsp_workers: LspWorkers = .{};
var queue: Queue = .{
.gpa = gpa,
@@ -1903,9 +1903,30 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options) !void {
const sock_fd: c_int = if (opts.nested) -1 else nested.listen();
defer nested.unlisten(sock_fd);
+ var shell: Shell = .{
+ .core = core,
+ .gui = &g,
+ .io = io,
+ .gpa = gpa,
+ .lsp_allocator = allocs.lsp,
+ .prompt_rcs = &prompt_rcs,
+ .ptys = &ptys,
+ .gens = &gens,
+ .queue = &queue,
+ .pipe_tasks = &pipe_tasks,
+ .inotify_fd = inotify_fd,
+ .watches = &watches,
+ .test_mode = test_mode,
+ };
+ const host = shell.host();
+ // `pump` installs this every pass; the pre-loop drain below happens
+ // outside one, so the initial spawns would otherwise reach the core's own
+ // virtual ptys instead of forking.
+ core.host = host;
+
// initial spawns BEFORE any worker thread exists: forkpty from a
// multithreaded process can wedge the child before exec (see tty.zig).
- drainEffects(core, &prompt_rcs, &ptys, &gens, io, gpa, &queue, &pipe_tasks, &g, inotify_fd, &watches, false);
+ while (core.nextEffect()) |e| core.perform(e);
for (&ptys, 0..) |*slot, id| if (slot.*) |pt| spawnReader(gpa, pt, @intCast(id), gens[id], &queue);
// ...and the one file watcher. Started even with nothing marked yet: the fd
// already exists and an unwatched inotify instance just parks in read(2) —
@@ -1917,71 +1938,15 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options) !void {
_ = c.SDL_StartTextInput(window);
- var feed: StdinFeed = .{};
if (test_mode) setStdinRaw() catch {};
+ shell.threads_ok = true;
- var frame_arena: std.heap.ArenaAllocator = .init(allocs.frame);
- defer frame_arena.deinit();
- var animation_clock: AnimationClock = .{};
-
+ // The core owns the loop. This owns the one thing a pump cannot do from
+ // inside itself: Restore swaps the whole Pardes, which is only safe
+ // BETWEEN iterations.
while (!core.quit) {
- // 1. SDL input: block briefly for the first event, then drain the rest
- var sev = std.mem.zeroes(c.SDL_Event);
- if (c.SDL_WaitEventTimeout(&sev, 16)) {
- dispatch(&g, core, &sev);
- while (c.SDL_PollEvent(&sev)) dispatch(&g, core, &sev);
- }
- // test mode: input comes from stdin escape sequences instead
- if (test_mode) {
- const r = feed.pump(gpa, core, &g) catch break;
- if (r.eof) break;
- }
- // 2. pty output from the reader threads
- var msgs = queue.take();
- var check_files = false;
- for (msgs.slice()) |m| switch (m) {
- .output => |o| {
- if (gens[o.pane] == o.gen)
- core.update(.{ .output = .{ .pane = o.pane, .bytes = o.bytes } });
- gpa.free(o.bytes);
- },
- .eof => |e| {
- _ = libc.close(e.fd); // the dead reader's master — stale or current
- if (gens[e.pane] == e.gen) {
- ptys[e.pane] = null;
- core.update(.{ .eof = .{ .pane = e.pane } });
- }
- },
- .lsp => |l| {
- core.update(.{ .lsp_resp = .{ .id = l.id, .rows = l.rows } });
- allocs.lsp.free(l.rows);
- },
- .pipe => |response_value| {
- var response = response_value;
- core.update(.{ .pipe_resp = .{
- .id = response.id,
- .success = response.success,
- .outputs = response.outputs,
- } });
- response.deinit(gpa);
- pipe_tasks.finish(io, response_value.id);
- },
- .command => |line| {
- core.update(.{ .command = line });
- gpa.free(line);
- },
- // Coalesced on purpose: a burst of writes (a formatter, a build, a
- // `git checkout`) collapses into ONE pass below, so it cannot queue
- // a reload — or an undo entry — per write.
- .files_changed => check_files = true,
- };
- if (check_files and file_watch.reloadChanged(core, io, gpa, &watches))
- queue.push(.files_changed);
- // 3. steamdeck: poll gamepad axes into virtual cursor / wheel events
- pollGamepad(&g, core);
- // 4. effects
- drainEffects(core, &prompt_rcs, &ptys, &gens, io, gpa, &queue, &pipe_tasks, &g, inotify_fd, &watches, true);
- if (core.quit) break;
+ try core.pump(host);
+ if (core.quit) break; // a session that ended does not restore into one
// Restore builtin: swap in a core rebuilt from the dump; kill the live
// shells (their detached readers wake on child death; gens bumped so
// the stale eofs close the old fds without touching the replay panes)
@@ -2013,91 +1978,14 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options) !void {
g.presented_images.clearRetainingCapacity();
g.prepared_images.clearRetainingCapacity();
nc.native_images = true;
+ nc.host = host;
core.deinit();
core = nc;
+ shell.core = nc;
+ shell.surface = null;
observeGuiFont(&g, core);
syncTaglineFont(&g, core);
}
- // TaglineSize is pure renderer state: update the smaller face and its
- // visual band immediately, without changing the body metrics or grid.
- syncTaglineFont(&g, core);
- // Font builtin: the core resolved a name to a path and asked for it —
- // it cannot load a font itself, having no rasterizer, no atlas and no
- // window. Inline here beside Restore because it is the same kind of
- // thing and this is the flat loop.
- if (core.takeFontRequest()) |path| blk: {
- const bytes = look.readFile(gpa, path) catch {
- core.rejectFont();
- break :blk;
- };
- const nf = c.ui_font_new(bytes.ptr, @intCast(bytes.len)) orelse {
- // FreeType turned it down. Keep wearing the one that works: a
- // font pardes cannot rasterize is a blank window with no way
- // back out of it.
- log.err("ui_font_new failed: {s}", .{path});
- gpa.free(bytes);
- core.rejectFont();
- break :blk;
- };
- c.ui_font_free(g.font);
- if (g.font_bytes.len != 0) gpa.free(g.font_bytes);
- g.font = nf;
- g.font_bytes = bytes; // FreeType borrows them for the face lifetime
- setGuiFontName(&g, core.settings.font.requested_name.get());
- refitFont(&g, core);
- acknowledgeGuiFont(&g, core);
- }
- // 5. live cwd for tags/look: cheap /proc readlink per pane, per frame
- pollCwds(core, &ptys);
- // 6. the grid follows the window (covers WINDOW_RESIZED and test
- // resizes). Off g.cell_w/h, not the init locals: a font change moves
- // them, and this is the line that would go on dividing by the old cell.
- _ = c.SDL_GetWindowSizeInPixels(window, &pw, &ph);
- const cols: u16 = @intCast(@max(1, @divTrunc(@as(u32, @intCast(@max(pw, 1))), g.cell_w)));
- const rows: u16 = @intCast(@max(1, @divTrunc(@as(u32, @intCast(@max(ph, 1))), g.cell_h)));
- if (updateCoreResize(core, cols, rows, g.cell_w, g.cell_h)) resetScroll(&g);
- // 7. render — apply the wheel batch LAST before it, while
- // core.surface still holds the frame the last pass drew
- stepScroll(&g, core, gpa);
- _ = frame_arena.reset(.retain_capacity);
- const surface = try core.render(frame_arena.allocator());
- const scene_requested = core.settings.scene_effects.crt or
- core.settings.scene_effects.ripple or core.settings.scene_effects.glitch;
- if (!scene_requested) g.scene_failures = 0;
- const presented = renderFrame(
- &g,
- gpa,
- core,
- surface,
- core.theme().bg,
- config.gui_topbar_pane_border_rgb orelse core.chromeTheme().scroll_track,
- core.chromeTheme().tag_bg,
- core.settings.scene_effects,
- core.settings.debug,
- ) catch |err| blk: {
- log.err("render: {t}", .{err});
- break :blk false;
- };
- if (g.scene_target_failed) {
- g.scene_failures +|= 1;
- log.err("scene target unavailable (attempt {d}/3)", .{g.scene_failures});
- if (g.scene_failures >= 3) {
- core.disableSceneEffects();
- g.scene_failures = 0;
- }
- } else if (scene_requested and presented) g.scene_failures = 0;
- if (presented) {
- // Ripple/glitch move source cells under a stationary physical
- // pointer. Re-feed only when that accepted scene maps to a new
- // cell, using the same core mouse path a real motion event uses.
- refreshPresentedPointer(&g, core);
- finishPresentedAnimationFrame(
- &animation_clock,
- core,
- surface.panelTracks(),
- c.SDL_GetTicksNS(),
- );
- }
}
}
@@ -2125,6 +2013,7 @@ fn runGrid(init: std.process.Init, opts_in: pardes.Options) !void {
opts.image_allocator = allocs.image;
opts.pdf_allocator = allocs.pdf;
opts.tree_sitter_allocator = allocs.tree_sitter;
+ opts.frame_allocator = allocs.frame;
if (opts.load_path != null) {
opts.cols = grid_cols;
opts.rows = grid_rows;
@@ -2148,12 +2037,11 @@ fn runGrid(init: std.process.Init, opts_in: pardes.Options) !void {
var ptys: [pardes.MAX_PANES]?Pty = @splat(null);
// per-slot spawn generation: drops a dead shell's late output/eof when its
- // pane id has been respawned (see drainEffects .spawn)
+ // pane id has been respawned (see the host's spawnPane)
var gens: [pardes.MAX_PANES]u32 = @splat(0);
defer for (&ptys) |*slot| if (slot.*) |pt| {
_ = libc.close(pt.fd);
};
- core.tty_query = .{ .ctx = &ptys, .taken = &ttyTakenAt };
var lsp_workers: LspWorkers = .{};
var queue: Queue = .{
.gpa = gpa,
@@ -2171,77 +2059,66 @@ fn runGrid(init: std.process.Init, opts_in: pardes.Options) !void {
// scripted input event, and a reload that arrives on its own clock would
// put a frame in the stream nothing asked for. -1 makes watchPane a no-op.
var watches: file_watch.Table = @splat(null);
- drainEffects(core, &prompt_rcs, &ptys, &gens, io, gpa, &queue, &pipe_tasks, null, -1, &watches, false);
+ var shell: Shell = .{
+ .core = core,
+ .io = io,
+ .gpa = gpa,
+ .lsp_allocator = allocs.lsp,
+ .prompt_rcs = &prompt_rcs,
+ .ptys = &ptys,
+ .gens = &gens,
+ .queue = &queue,
+ .pipe_tasks = &pipe_tasks,
+ .inotify_fd = -1,
+ .watches = &watches,
+ };
+ const host = shell.host();
+ // The core owns the loop here too, but not the scripted stdin: EOF ends
+ // the session and nothing may be drawn after it, so this reads its own
+ // input and hands `pump` a pass that has already been fed.
+ core.host = host;
+ while (core.nextEffect()) |e| core.perform(e);
for (&ptys, 0..) |*slot, id| if (slot.*) |pt| spawnReader(gpa, pt, @intCast(id), gens[id], &queue);
+ shell.threads_ok = true;
setStdinRaw() catch {}; // stdin may be a pipe, not a pty — best effort
- var frame_arena: std.heap.ArenaAllocator = .init(allocs.frame);
- defer frame_arena.deinit();
- var feed: StdinFeed = .{};
-
- // first frame before touching stdin, so `printf '' | pardes` still shows one
+ // First frame before touching stdin, so `printf '' | pardes` still shows
+ // one. Its arena is released before the core's own ever allocates: both
+ // draw from the one stack-fallback buffer, and a live arena on top of it
+ // would push every later frame out to the heap.
{
- const surface = try core.render(frame_arena.allocator());
+ var first: std.heap.ArenaAllocator = .init(allocs.frame);
+ defer first.deinit();
+ const surface = try core.render(first.allocator());
try dumpGrid(gpa, surface);
// The grid protocol writes canonical cells; panel tracks are metadata
// for a compositor it deliberately does not run.
core.acknowledgePanelPresentation(&.{});
}
while (!core.quit) {
- const r = try feed.pump(gpa, core, null);
+ // The two halves of a pass's input, in the order the flat loop had
+ // them: the scripted feed, then whatever the reader threads handed
+ // over. `pump` has no `wait_input` to do it in — see `grid_vtable`.
+ const r = try shell.feed.pump(gpa, core, null);
if (r.eof) break;
- var n_events: usize = r.n_events;
- var msgs = queue.take();
- for (msgs.slice()) |m| switch (m) {
- .output => |o| {
- if (gens[o.pane] == o.gen)
- core.update(.{ .output = .{ .pane = o.pane, .bytes = o.bytes } });
- gpa.free(o.bytes);
- n_events += 1;
- },
- .eof => |e| {
- _ = libc.close(e.fd); // the dead reader's master — stale or current
- if (gens[e.pane] == e.gen) {
- ptys[e.pane] = null;
- core.update(.{ .eof = .{ .pane = e.pane } });
- }
- n_events += 1;
- },
- .lsp => |l| {
- core.update(.{ .lsp_resp = .{ .id = l.id, .rows = l.rows } });
- allocs.lsp.free(l.rows);
- n_events += 1;
- },
- .pipe => |response_value| {
- var response = response_value;
- core.update(.{ .pipe_resp = .{
- .id = response.id,
- .success = response.success,
- .outputs = response.outputs,
- } });
- response.deinit(gpa);
- n_events += 1;
- pipe_tasks.finish(io, response_value.id);
- },
- // both unreachable here: this mode starts neither thread
- .files_changed => {},
- .command => |line| gpa.free(line),
- };
- drainEffects(core, &prompt_rcs, &ptys, &gens, io, gpa, &queue, &pipe_tasks, null, -1, &watches, true);
- pollCwds(core, &ptys);
- // The grid harness polls stdin at the same 16 ms cadence as native
- // SDL. Advancing here lets `stable` wait for exact endpoint colors;
- // once inactive it resumes the old event-only frame contract.
- if (core.animationActive()) {
- core.update(.tick);
- n_events += 1;
- }
- if (n_events == 0) continue; // idle tick: nothing changed, no frame
- _ = frame_arena.reset(.retain_capacity);
- const surface = try core.render(frame_arena.allocator());
- try dumpGrid(gpa, surface);
- core.acknowledgePanelPresentation(&.{});
+ if (r.n_events != 0) shell.saw_event = true;
+ shell.drainQueue();
+ try core.pump(host);
+ if (shell.dump_err) |err| return err;
+ }
+ // The last frame is outside `pump` for the same reason the first one is:
+ // `pump` returns before drawing a quitting pass, and this stream records
+ // the empty grid a closed session leaves behind. Same three host methods
+ // in the same order, so the idle rule and the acknowledgement stay in one
+ // place — only the render is out here.
+ if (core.quit) {
+ gridPollFrame(&shell);
+ var last: std.heap.ArenaAllocator = .init(allocs.frame);
+ defer last.deinit();
+ gridPresent(&shell, try core.render(last.allocator()));
+ gridPostPresent(&shell);
+ if (shell.dump_err) |err| return err;
}
}
@@ -3107,150 +2984,468 @@ fn pollGamepad(g: *Gui, core: *pardes.Pardes) void {
}
// =====================================================================
-// effects — identical duties to tty.zig's drainEffects, plus SDL clipboard
+// the host seam — everything the core cannot do itself: ptys, files, the
+// desktop, pixels, and the one place this process is allowed to sleep.
// =====================================================================
-fn drainEffects(
+/// The state the host methods below need. `gui` is null in grid test mode:
+/// no SDL, so no clipboard and no pixels, and the frames go out as text.
+const Shell = struct {
+ /// Reassigned by Restore, which is why the loop pumps rather than runs:
+ /// a swap is only safe BETWEEN iterations.
core: *pardes.Pardes,
+ gui: ?*Gui = null,
+ io: std.Io,
+ gpa: std.mem.Allocator,
+ lsp_allocator: std.mem.Allocator,
prompt_rcs: *const shell_bin.PromptRcs,
ptys: *[pardes.MAX_PANES]?Pty,
gens: *[pardes.MAX_PANES]u32,
- io: std.Io,
- gpa: std.mem.Allocator,
queue: *Queue,
pipe_tasks: *PipeTasks,
- g: ?*Gui, // null in grid test mode (no SDL: clipboard effects are no-ops)
inotify_fd: c_int,
watches: *file_watch.Table,
- threads_ok: bool,
-) void {
- while (core.nextEffect()) |effect| switch (effect) {
- .spawn => |sp| {
- // the core reuses pane ids and there is no close effect: a deleted
- // pane's shell lives in its slot until a respawn lands here. Kill
- // it; its detached reader wakes on child death and the gen-guarded
- // eof closes the old fd (not here — the reader still reads it).
- if (ptys[sp.pane]) |old| {
- _ = libc.kill(old.pid, libc.SIG.KILL);
- ptys[sp.pane] = null;
- }
- gens[sp.pane] +%= 1;
- const cwd = sp.cwd.slice();
- var cwd_buf: [256:0]u8 = undefined;
- var cwd_z: ?[*:0]const u8 = null;
- if (cwd.len > 0) {
- @memcpy(cwd_buf[0..cwd.len], cwd);
- cwd_buf[cwd.len] = 0;
- cwd_z = @ptrCast(&cwd_buf);
- }
- const pt = forkShell(core, sp.pane, prompt_rcs, core.shellBin(), cwd_z, core.screen_h, core.screen_w);
- ptys[sp.pane] = pt;
- // report the pane's starting directory back to the core (tags); the
- // slot needs no occupancy reset, nothing about it is remembered
- var lbuf: [1024]u8 = undefined;
- if (look.shellCwd(pt.pid, &lbuf)) |wd| core.setCwd(sp.pane, wd);
- if (threads_ok) spawnReader(gpa, pt, sp.pane, gens[sp.pane], queue);
- },
- .write => |w| {
- if (ptys[w.pane]) |pt| writeFd(pt.fd, w.bytes.slice());
- },
- .resize_pty => |rs| {
- if (ptys[rs.pane]) |pt| {
- const ws: posix.winsize = .{ .row = rs.rows, .col = rs.cols, .xpixel = 0, .ypixel = 0 };
- _ = posix.system.ioctl(pt.fd, TIOCSWINSZ, @intFromPtr(&ws));
- }
- },
- .open_link => |url| look.openLink(url.slice()), // desktop browser
- .save_file => |sf| {
- const pane = core.panes[sf.pane] orelse continue;
- const f = pane.file orelse continue;
- var pathbuf: [4096:0]u8 = undefined;
- if (f.path.len >= pathbuf.len) continue;
- @memcpy(pathbuf[0..f.path.len], f.path);
- pathbuf[f.path.len] = 0;
- const fd = libc.open(pathbuf[0..f.path.len :0], .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
- if (fd < 0) continue;
- writeFd(fd, f.content);
- _ = libc.close(fd);
- // our own write is about to come back as a watch event: restamp
- // from the bytes we just put there so it reads as "no change"
- if (watches[sf.pane]) |*w| if (w.serial == pane.serial) switch (w.generation) {
- .text => w.generation = .{ .text = std.hash.Wyhash.hash(0, f.content) },
+ /// worker threads exist. The pre-loop drain forks before any of them do:
+ /// forkpty from a multithreaded process can wedge the child before exec.
+ threads_ok: bool = false,
+ /// PARDES_TEST: input is stdin escape sequences, not SDL events
+ test_mode: bool = false,
+ feed: StdinFeed = .{},
+ /// what the last present actually put on screen, and the frame it drew:
+ /// post_present may only acknowledge a frame the user has seen.
+ presented: bool = false,
+ surface: ?*pardes.Surface = null,
+ /// `pump` spends no animation time; this is where the display clock does.
+ animation_clock: AnimationClock = .{},
+ /// Whether this pass observed any input. Only the grid harness reads it:
+ /// its contract is one frame per scripted input event, so a pass that saw
+ /// nothing writes nothing.
+ saw_event: bool = false,
+ /// Grid mode only: a failed write to the frame stream. Kept rather than
+ /// swallowed because a `present` cannot fail and the harness must.
+ dump_err: ?anyerror = null,
+
+ fn host(s: *Shell) pardes.Host {
+ return .{ .ctx = s, .vtable = if (s.gui == null) &grid_vtable else &vtable };
+ }
+
+ const vtable: pardes.Host.VTable = .{
+ .pull_wait_input = waitInput,
+ .push_present = present,
+ .push_post_present = postPresent,
+ .push_poll_frame = pollFrame,
+ .push_spawn = spawnPane,
+ .push_pty_write = ptyWrite,
+ .push_pty_resize = ptyResize,
+ .pull_tty_taken = ttyTaken,
+ .push_write_file = writeFile,
+ .push_write_dump = writeDump,
+ .push_watch_file = watchFile,
+ .push_watch_theme = watchTheme,
+ .push_dump_themes = dumpThemes,
+ .push_set_clipboard = setClipboard,
+ .pull_read_clipboard = readClipboard,
+ .push_open_link = openLink,
+ .pull_lsp = lsp,
+ .pull_pipe = pipe,
+ };
+
+ /// The headless grid harness. It reads its scripted stdin itself, because
+ /// EOF ends the session and nothing may be drawn after it — so there is no
+ /// `wait_input` here, and this process never sleeps in grid mode. It starts
+ /// neither the watcher nor the nested listener, so `drainQueue`'s
+ /// `files_changed` and `command` arms cannot fire behind it.
+ const grid_vtable: pardes.Host.VTable = vt: {
+ var v = vtable;
+ v.pull_wait_input = null;
+ v.push_poll_frame = gridPollFrame;
+ v.push_present = gridPresent;
+ v.push_post_present = gridPostPresent;
+ break :vt v;
+ };
+
+ /// What the detached workers handed this thread since the last pass.
+ /// Their bytes are borrowed for exactly one `update` call each. Each
+ /// message is something this pass observed — the grid harness draws a
+ /// frame only for a pass that observed something.
+ fn drainQueue(s: *Shell) void {
+ var msgs = s.queue.take();
+ var check_files = false;
+ for (msgs.slice()) |m| switch (m) {
+ .output => |o| {
+ if (s.gens[o.pane] == o.gen)
+ s.core.update(.{ .output = .{ .pane = o.pane, .bytes = o.bytes } });
+ s.gpa.free(o.bytes);
+ s.saw_event = true;
+ },
+ .eof => |e| {
+ _ = libc.close(e.fd); // the dead reader's master — stale or current
+ if (s.gens[e.pane] == e.gen) {
+ s.ptys[e.pane] = null;
+ s.core.update(.{ .eof = .{ .pane = e.pane } });
+ }
+ s.saw_event = true;
+ },
+ .lsp => |l| {
+ s.core.update(.{ .lsp_resp = .{ .id = l.id, .rows = l.rows } });
+ s.lsp_allocator.free(l.rows);
+ s.saw_event = true;
+ },
+ .pipe => |response_value| {
+ var response = response_value;
+ s.core.update(.{ .pipe_resp = .{
+ .id = response.id,
+ .success = response.success,
+ .outputs = response.outputs,
+ } });
+ response.deinit(s.gpa);
+ s.saw_event = true;
+ s.pipe_tasks.finish(s.io, response_value.id);
+ },
+ .command => |line| {
+ s.core.update(.{ .command = line });
+ s.gpa.free(line);
+ },
+ // Coalesced on purpose: a burst of writes (a formatter, a build, a
+ // `git checkout`) collapses into ONE pass below, so it cannot queue
+ // a reload — or an undo entry — per write.
+ .files_changed => check_files = true,
+ };
+ if (check_files and file_watch.reloadChanged(s.core, s.io, s.gpa, s.watches))
+ s.queue.push(.files_changed);
+ }
+};
+
+fn shellOf(ctx: ?*anyopaque) *Shell {
+ return @ptrCast(@alignCast(ctx.?));
+}
+
+/// SDL first (blocking briefly for one event, then draining the burst), then
+/// the scripted stdin feed, then the worker inbox, then the sticks. Never
+/// blocks indefinitely even when the core offers to: cwd polling, the gamepad
+/// and the test feed have no SDL event to wake them.
+fn waitInput(ctx: ?*anyopaque, timeout_ms: u32) void {
+ const s = shellOf(ctx);
+ const core = s.core;
+ if (s.gui) |g| {
+ var sev = std.mem.zeroes(c.SDL_Event);
+ const ms: c_int = if (timeout_ms != 0) @intCast(timeout_ms) else 16;
+ if (c.SDL_WaitEventTimeout(&sev, ms)) {
+ dispatch(g, core, &sev);
+ while (c.SDL_PollEvent(&sev)) dispatch(g, core, &sev);
+ }
+ }
+ if (s.test_mode) {
+ // A dead scripted feed ends the session HERE, before the inbox, the
+ // sticks and the frame: the pre-pump loop broke at this line, and a
+ // capture written after EOF is a frame no script asked for.
+ const r = s.feed.pump(s.gpa, core, s.gui) catch {
+ core.quit = true;
+ return;
+ };
+ if (r.eof) {
+ core.quit = true;
+ return;
+ }
+ }
+ s.drainQueue();
+ if (s.gui) |g| pollGamepad(g, core);
+}
+
+/// Per-frame host bookkeeping with no event of its own, in the order the flat
+/// loop had it: the tagline face, a font the core asked for, live cwds, the
+/// grid following the window, and the wheel batch — applied LAST before the
+/// render, while the previous frame is still the one on screen.
+fn pollFrame(ctx: ?*anyopaque) void {
+ const s = shellOf(ctx);
+ const core = s.core;
+ const g = s.gui orelse return;
+ // TaglineSize is pure renderer state: update the smaller face and its
+ // visual band immediately, without changing the body metrics or grid.
+ syncTaglineFont(g, core);
+ // Font builtin: the core resolved a name to a path and asked for it — it
+ // cannot load a font itself, having no rasterizer, no atlas and no window.
+ if (core.takeFontRequest()) |path| blk: {
+ const bytes = look.readFile(s.gpa, path) catch {
+ core.rejectFont();
+ break :blk;
+ };
+ const nf = c.ui_font_new(bytes.ptr, @intCast(bytes.len)) orelse {
+ // FreeType turned it down. Keep wearing the one that works: a font
+ // pardes cannot rasterize is a blank window with no way back out.
+ log.err("ui_font_new failed: {s}", .{path});
+ s.gpa.free(bytes);
+ core.rejectFont();
+ break :blk;
+ };
+ c.ui_font_free(g.font);
+ if (g.font_bytes.len != 0) s.gpa.free(g.font_bytes);
+ g.font = nf;
+ g.font_bytes = bytes; // FreeType borrows them for the face lifetime
+ setGuiFontName(g, core.settings.font.requested_name.get());
+ refitFont(g, core);
+ acknowledgeGuiFont(g, core);
+ }
+ pollCwds(core, s.ptys);
+ // Off g.cell_w/h, not the startup metrics: a font change moves them, and
+ // this is the line that would go on dividing by the old cell.
+ var pw: c_int = 0;
+ var ph: c_int = 0;
+ _ = c.SDL_GetWindowSizeInPixels(g.window, &pw, &ph);
+ const cols: u16 = @intCast(@max(1, @divTrunc(@as(u32, @intCast(@max(pw, 1))), g.cell_w)));
+ const rows: u16 = @intCast(@max(1, @divTrunc(@as(u32, @intCast(@max(ph, 1))), g.cell_h)));
+ if (updateCoreResize(core, cols, rows, g.cell_w, g.cell_h)) resetScroll(g);
+ stepScroll(g, core, s.gpa);
+}
+
+fn present(ctx: ?*anyopaque, surface: *const pardes.Surface) void {
+ const s = shellOf(ctx);
+ const core = s.core;
+ const g = s.gui orelse return;
+ // renderFrame consumes the frame the core just built; nothing here writes
+ // to it, and post_present needs the same one to acknowledge.
+ const frame = @constCast(surface);
+ s.surface = frame;
+ const scene_requested = core.settings.scene_effects.crt or
+ core.settings.scene_effects.ripple or core.settings.scene_effects.glitch;
+ if (!scene_requested) g.scene_failures = 0;
+ s.presented = renderFrame(
+ g,
+ s.gpa,
+ core,
+ frame,
+ core.theme().bg,
+ config.gui_topbar_pane_border_rgb orelse core.chromeTheme().scroll_track,
+ core.chromeTheme().tag_bg,
+ core.settings.scene_effects,
+ core.settings.debug,
+ ) catch |err| blk: {
+ log.err("render: {t}", .{err});
+ break :blk false;
+ };
+ if (g.scene_target_failed) {
+ g.scene_failures +|= 1;
+ log.err("scene target unavailable (attempt {d}/3)", .{g.scene_failures});
+ if (g.scene_failures >= 3) {
+ core.disableSceneEffects();
+ g.scene_failures = 0;
+ }
+ } else if (scene_requested and s.presented) g.scene_failures = 0;
+}
+
+/// A tick is spent only on a frame that was actually PRESENTED: a failed
+/// renderFrame must not advance samples nobody saw.
+fn postPresent(ctx: ?*anyopaque) void {
+ const s = shellOf(ctx);
+ const g = s.gui orelse return;
+ if (!s.presented) return;
+ const frame = s.surface orelse return;
+ // Ripple/glitch move source cells under a stationary physical pointer.
+ // Re-feed only when that accepted scene maps to a new cell, using the same
+ // core mouse path a real motion event uses.
+ refreshPresentedPointer(g, s.core);
+ finishPresentedAnimationFrame(
+ &s.animation_clock,
+ s.core,
+ frame.panelTracks(),
+ c.SDL_GetTicksNS(),
+ );
+}
+
+/// The grid harness's own three seams. It has no window, no pointer and no
+/// compositor, so what is left of a frame is the cwds a tagline draws, one
+/// animation step, and the text of the grid itself.
+fn gridPollFrame(ctx: ?*anyopaque) void {
+ const s = shellOf(ctx);
+ pollCwds(s.core, s.ptys);
+ // The harness polls stdin at the same 16 ms cadence as native SDL, so a
+ // pass IS a frame interval and the tick is due here rather than behind a
+ // display clock. Advancing lets `stable` wait for exact endpoint colors;
+ // once inactive it resumes the event-only frame contract.
+ if (s.core.animationActive()) {
+ s.core.update(.tick);
+ s.saw_event = true;
+ }
+}
+
+fn gridPresent(ctx: ?*anyopaque, surface: *const pardes.Surface) void {
+ const s = shellOf(ctx);
+ // Idle pass: nothing changed, so no frame. The stream is one frame per
+ // scripted input event and a repeat of the last grid would be read as one.
+ s.presented = s.saw_event;
+ s.saw_event = false;
+ if (!s.presented) return;
+ dumpGrid(s.gpa, @constCast(surface)) catch |err| {
+ s.dump_err = err;
+ s.presented = false;
+ };
+}
+
+fn gridPostPresent(ctx: ?*anyopaque) void {
+ const s = shellOf(ctx);
+ if (!s.presented) return;
+ // The grid protocol writes canonical cells; panel tracks are metadata for
+ // a compositor it deliberately does not run.
+ s.core.acknowledgePanelPresentation(&.{});
+}
+
+fn spawnPane(ctx: ?*anyopaque, pane: u8, cwd: []const u8) void {
+ const s = shellOf(ctx);
+ // the core reuses pane ids and there is no close effect: a deleted pane's
+ // shell lives in its slot until a respawn lands here. Kill it; its
+ // detached reader wakes on child death and the gen-guarded eof closes the
+ // old fd (not here — the reader still reads it).
+ if (s.ptys[pane]) |old| {
+ _ = libc.kill(old.pid, libc.SIG.KILL);
+ s.ptys[pane] = null;
+ }
+ s.gens[pane] +%= 1;
+ var cwd_buf: [256:0]u8 = undefined;
+ var cwd_z: ?[*:0]const u8 = null;
+ if (cwd.len > 0 and cwd.len < cwd_buf.len) {
+ @memcpy(cwd_buf[0..cwd.len], cwd);
+ cwd_buf[cwd.len] = 0;
+ cwd_z = @ptrCast(&cwd_buf);
+ }
+ const pt = forkShell(s.core, pane, s.prompt_rcs, s.core.shellBin(), cwd_z, s.core.screen_h, s.core.screen_w);
+ s.ptys[pane] = pt;
+ // report the pane's starting directory back to the core (tags); the slot
+ // needs no occupancy reset, nothing about it is remembered
+ var lbuf: [1024]u8 = undefined;
+ if (look.shellCwd(pt.pid, &lbuf)) |wd| s.core.setCwd(pane, wd);
+ if (s.threads_ok) spawnReader(s.gpa, pt, pane, s.gens[pane], s.queue);
+}
+
+fn ptyWrite(ctx: ?*anyopaque, pane: u8, bytes: []const u8) void {
+ const s = shellOf(ctx);
+ if (s.ptys[pane]) |pt| writeFd(pt.fd, bytes);
+}
+
+fn ptyResize(ctx: ?*anyopaque, pane: u8, cols: u16, rows: u16) void {
+ const s = shellOf(ctx);
+ if (s.ptys[pane]) |pt| {
+ const ws: posix.winsize = .{ .row = rows, .col = cols, .xpixel = 0, .ypixel = 0 };
+ _ = posix.system.ioctl(pt.fd, TIOCSWINSZ, @intFromPtr(&ws));
+ }
+}
+
+/// Is a program (vim, a pager, an agent) holding this pane's tty instead of
+/// the shell we forked? Asked by the core only where it is about to type a
+/// command line, which is why the /proc walk behind it is not in pollCwds:
+/// nothing draws this answer, and an Exec is a rare frame.
+fn ttyTaken(ctx: ?*anyopaque, pane: u8) bool {
+ const s = shellOf(ctx);
+ const pt = s.ptys[pane] orelse return false;
+ return look.ttyTaken(pt.pid, pt.fd);
+}
+
+fn writeWholeFile(path: []const u8, bytes: []const u8) bool {
+ var pathbuf: [4096:0]u8 = undefined;
+ if (path.len >= pathbuf.len) return false;
+ @memcpy(pathbuf[0..path.len], path);
+ pathbuf[path.len] = 0;
+ const fd = libc.open(pathbuf[0..path.len :0], .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
+ if (fd < 0) return false;
+ writeFd(fd, bytes);
+ _ = libc.close(fd);
+ return true;
+}
+
+fn writeFile(ctx: ?*anyopaque, pane: u8, path: []const u8, bytes: []const u8) void {
+ const s = shellOf(ctx);
+ if (!writeWholeFile(path, bytes)) return;
+ // our own write is about to come back as a watch event: restamp from the
+ // bytes we just put there so it reads as "no change". Only for the pane's
+ // OWN file — a `Put` elsewhere is a change like any other.
+ if (s.core.panes[pane]) |pane_state| if (pane_state.file) |f| {
+ if (std.mem.eql(u8, f.path, path))
+ if (s.watches[pane]) |*w| if (w.serial == pane_state.serial) switch (w.generation) {
+ .text => w.generation = .{ .text = std.hash.Wyhash.hash(0, bytes) },
.pdf => {},
};
- // ...and say so on the pane's message row. AFTER the write, not
- // beside it: every `continue` above is a save that did not happen
- // and must not be reported as one.
- var mbuf: [256]u8 = undefined;
- core.setMessage(sf.pane, message.stamp(&mbuf, "saved", f.path));
- },
- .new_file => |request| {
- var path_buf: [4096:0]u8 = undefined;
- const made = temp_file.create(&path_buf) orelse continue;
- if (core.openNewFile(request.pane, request.serial, made.path))
- made.adopt()
- else
- made.discard();
- },
- .write_dump => {
- const out = core.dump_out orelse continue;
- var pbuf: [1024:0]u8 = undefined;
- const path = pardes.dump.outPath(&pbuf) orelse continue;
- const fd = libc.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
- if (fd < 0) continue;
- writeFd(fd, out);
- core.setLastDump(path);
- _ = libc.close(fd);
- },
- .dump_themes => |request| {
- const config_dir = core.opts.config_dir orelse continue;
- const out_dir = user_config.dumpThemes(io, gpa, config_dir, pardes.themes) catch |err| {
- core.reportError(request.pane, "dump themes", err);
- continue;
- };
- defer gpa.free(out_dir);
- var mbuf: [256]u8 = undefined;
- core.setMessage(request.pane, message.stamp(&mbuf, "dumped themes", out_dir));
- },
- .set_clipboard => {
- if (g == null) continue;
- const y = core.yank orelse continue;
- const z = gpa.dupeZ(u8, y) catch continue;
- defer gpa.free(z);
- _ = c.SDL_SetClipboardText(z.ptr);
- },
- .read_clipboard => {
- if (g == null) continue;
- // SDL answers synchronously, so the paste the core is waiting on
- // lands inside this same drain — nothing to remember, no reply
- // path to plumb. SDL3 hands over an OWNED copy that is ours to
- // SDL_free, and reports "no text" as an EMPTY string rather than
- // null, so the length check is what actually rejects a miss.
- const raw = c.SDL_GetClipboardText() orelse continue;
- defer c.SDL_free(raw);
- const text = std.mem.span(raw);
- if (text.len == 0) continue;
- core.update(.{ .paste = text });
- },
- .lsp => |e| if (threads_ok) spawnLsp(core, queue, e),
- .pipe => |e| if (threads_ok) spawnPipe(core, io, gpa, queue, pipe_tasks, e),
- .watch => |w| {
- if (file_watch.applyEffect(core, io, gpa, inotify_fd, watches, w.pane, w.on))
- queue.push(.files_changed);
- },
- .theme_file => |request| {
- if (file_watch.applyThemeEffect(
- core,
- gpa,
- inotify_fd,
- watches,
- request.generation,
- request.on,
- threads_ok,
- )) queue.push(.files_changed);
- },
- .quit => {},
};
+ // ...and say so on the pane's message row. AFTER the write, not beside it:
+ // a save that did not happen must not be reported as one.
+ var mbuf: [256]u8 = undefined;
+ s.core.setMessage(pane, message.stamp(&mbuf, "saved", path));
+}
+
+fn writeDump(ctx: ?*anyopaque, bytes: []const u8) void {
+ const s = shellOf(ctx);
+ var pbuf: [1024:0]u8 = undefined;
+ const path = pardes.dump.outPath(&pbuf) orelse return;
+ if (!writeWholeFile(path, bytes)) return;
+ s.core.setLastDump(path);
+}
+
+fn watchFile(ctx: ?*anyopaque, pane: u8, path: []const u8, on: bool) void {
+ const s = shellOf(ctx);
+ _ = path; // file_watch resolves it (and a PDF's) from the pane itself
+ if (file_watch.applyEffect(s.core, s.io, s.gpa, s.inotify_fd, s.watches, pane, on))
+ s.queue.push(.files_changed);
+}
+
+fn watchTheme(ctx: ?*anyopaque, generation: u32, on: bool) void {
+ const s = shellOf(ctx);
+ if (file_watch.applyThemeEffect(
+ s.core,
+ s.gpa,
+ s.inotify_fd,
+ s.watches,
+ generation,
+ on,
+ s.threads_ok,
+ )) s.queue.push(.files_changed);
+}
+
+fn dumpThemes(ctx: ?*anyopaque, pane: u8) void {
+ const s = shellOf(ctx);
+ const config_dir = s.core.opts.config_dir orelse return;
+ const out_dir = user_config.dumpThemes(s.io, s.gpa, config_dir, pardes.themes) catch |err| {
+ s.core.reportError(pane, "dump themes", err);
+ return;
+ };
+ defer s.gpa.free(out_dir);
+ var mbuf: [256]u8 = undefined;
+ s.core.setMessage(pane, message.stamp(&mbuf, "dumped themes", out_dir));
+}
+
+fn setClipboard(ctx: ?*anyopaque, text: []const u8) void {
+ const s = shellOf(ctx);
+ if (s.gui == null) return;
+ const z = s.gpa.dupeZ(u8, text) catch return;
+ defer s.gpa.free(z);
+ _ = c.SDL_SetClipboardText(z.ptr);
+}
+
+fn readClipboard(ctx: ?*anyopaque) void {
+ const s = shellOf(ctx);
+ if (s.gui == null) return;
+ // SDL answers synchronously, so the paste the core is waiting on lands
+ // inside this same drain — nothing to remember, no reply path to plumb.
+ // SDL3 hands over an OWNED copy that is ours to SDL_free, and reports "no
+ // text" as an EMPTY string rather than null, so the length check is what
+ // actually rejects a miss.
+ const raw = c.SDL_GetClipboardText() orelse return;
+ defer c.SDL_free(raw);
+ const text = std.mem.span(raw);
+ if (text.len == 0) return;
+ s.core.update(.{ .paste = text });
+}
+
+fn openLink(ctx: ?*anyopaque, url: []const u8) void {
+ _ = ctx;
+ look.openLink(url); // desktop browser
+}
+
+fn lsp(ctx: ?*anyopaque, req: host_api.LspRequest) void {
+ const s = shellOf(ctx);
+ if (s.threads_ok) spawnLsp(s.core, s.queue, req);
+}
+
+fn pipe(ctx: ?*anyopaque, id: u32) void {
+ const s = shellOf(ctx);
+ if (s.threads_ok) spawnPipe(s.core, s.io, s.gpa, s.queue, s.pipe_tasks, id);
}
fn forkShell(core: *pardes.Pardes, pane: usize, prompt_rcs: *const shell_bin.PromptRcs, bin: []const u8, cwd: ?[*:0]const u8, rows: u16, cols: u16) Pty {
@@ -3272,7 +3467,7 @@ fn forkShell(core: *pardes.Pardes, pane: usize, prompt_rcs: *const shell_bin.Pro
/// Live cwd for tags/look: a cheap per-pane process lookup, polled every frame
/// because a tagline draws it. Whether a pane's tty still belongs to the prompt
-/// pardes forked is deliberately NOT polled with it — see `ttyTakenAt`.
+/// pardes forked is deliberately NOT polled with it — see `ttyTaken`.
fn pollCwds(core: *pardes.Pardes, ptys: *[pardes.MAX_PANES]?Pty) void {
for (ptys, 0..) |slot, id| if (slot) |pt| {
var lbuf: [1024]u8 = undefined;
@@ -3280,16 +3475,6 @@ fn pollCwds(core: *pardes.Pardes, ptys: *[pardes.MAX_PANES]?Pty) void {
};
}
-/// The core's `tty_query`: is a program (vim, a pager, an agent) holding this
-/// pane's tty instead of the shell we forked? Asked by the core only where it is
-/// about to type a command line, which is why the /proc walk behind it is not in
-/// pollCwds above: nothing draws this answer, and an Exec is a rare frame.
-fn ttyTakenAt(ctx: ?*anyopaque, pane: usize) bool {
- const table: *const [pardes.MAX_PANES]?Pty = @ptrCast(@alignCast(ctx orelse return false));
- const pt = table[pane] orelse return false;
- return look.ttyTaken(pt.pid, pt.fd);
-}
-
// =====================================================================
// fractional scroll: whole rows for the core, sub-row offsets for the picture
// =====================================================================
diff --git a/src/host.zig b/src/host.zig
new file mode 100644
index 00000000..d3e93d36
--- /dev/null
+++ b/src/host.zig
@@ -0,0 +1,289 @@
+//! THE HOST SEAM: everything the core cannot do itself, as one struct of
+//! OPTIONAL function pointers — `std.mem.Allocator`/`std.Io` shape, and the
+//! generalization of two vtables this codebase already grew on its own
+//! (`pardes.TtyQuery`, and the macOS shell's `Runtime`).
+//!
+//! Every method is optional, and a null method is not an error: the core
+//! substitutes a default backed by ordinary data structures in this process
+//! (`Fallback` below). So a host implements only what it actually has, and the
+//! core cannot tell the difference — a `Save` lands in a real file under the
+//! tty host and in `Fallback.files` under a host that never wrote a filesystem
+//! method, and every path above that behaves identically.
+//!
+//! Two consequences worth having on purpose:
+//! * The zero-method host IS the test harness. A `Host{}` is a complete,
+//! deterministic, in-process pardes with a virtual filesystem, a virtual
+//! clipboard and silent ptys.
+//! * `Fallback` lives on the Pardes instance, not here, so N cores driven by
+//! one fan-out host each keep their own state and can run in parallel.
+//!
+//! WHAT IS NOT HERE, and why: whether a capability EXISTS in this build stays
+//! comptime and stays next to the code it shapes (`pardes.platform`,
+//! `pardes.pdf_enabled`, `builtins.capabilities`, `PdfSlot`/`HapticSlot`).
+//! A vtable cannot make a field zero-sized or a builtin absent from an enum.
+//! The rule is: comptime decides what a BUILD has, this vtable decides who
+//! SERVES it at runtime.
+const std = @import("std");
+const pardes = @import("pardes.zig");
+const source_manifest = @import("source_manifest.zig");
+
+pub const LspRequest = struct {
+ id: u32,
+ kind: pardes.lsp.Kind,
+ pane: u8,
+ offset: u32,
+ arg: []const u8,
+};
+
+pub const Host = struct {
+ ctx: ?*anyopaque = null,
+ vtable: *const VTable = &.{},
+
+ /// One optional method per thing a host can do. Adding a method here is
+ /// additive for every existing host: they keep it null and get the default.
+ ///
+ /// EVERY name says how a fan-out must route it, and the compiler enforces
+ /// that it does (see Fanout.isPull):
+ /// `push_` every wrapped host gets it, and it returns nothing — a push
+ /// with an answer would have N answers and no way to pick one.
+ /// `pull_` exactly ONE host serves it, because there is one of whatever
+ /// comes back: one value, one sleep that ends, one `Event.paste`
+ /// for one Ctrl-V, one `lsp_resp` per request id.
+ pub const VTable = struct {
+ // ---- the loop's own three seams ----
+ /// Block until there is input or `timeout_ms` elapses, translating
+ /// whatever arrives into `Pardes.update`/`postEvent` calls. This is the
+ /// ONLY place the process is allowed to sleep: the core never spins.
+ /// A pull because one host does the sleeping — fanned out, the second
+ /// host would not be serviced until the first happened to wake.
+ pull_wait_input: ?*const fn (ctx: ?*anyopaque, timeout_ms: u32) void = null,
+ push_present: ?*const fn (ctx: ?*anyopaque, surface: *const pardes.Surface) void = null,
+ /// After the frame is on screen (panel-presentation acknowledgement,
+ /// pointer refresh); split from `push_present` because it must observe
+ /// a frame the user has actually seen.
+ push_post_present: ?*const fn (ctx: ?*anyopaque) void = null,
+ /// Per-frame host bookkeeping with no event of its own: cwd polling, a
+ /// capability handshake landing, gamepad state.
+ push_poll_frame: ?*const fn (ctx: ?*anyopaque) void = null,
+
+ // ---- pseudo-terminals ----
+ push_spawn: ?*const fn (ctx: ?*anyopaque, pane: u8, cwd: []const u8) void = null,
+ push_pty_write: ?*const fn (ctx: ?*anyopaque, pane: u8, bytes: []const u8) void = null,
+ push_pty_resize: ?*const fn (ctx: ?*anyopaque, pane: u8, cols: u16, rows: u16) void = null,
+ /// Is this pane's terminal still the prompt the host forked, or has a
+ /// program (vim, a pager, an agent) taken its tty? An effect cannot
+ /// answer it — the `execute` that asks must choose a destination inside
+ /// its own update, and effects drain after. A pushed fact would mean
+ /// every host probing every pane's processes every frame to answer a
+ /// question asked when a human middle-clicks a word. So the host leaves
+ /// a way to be asked and the core asks where it decides. The answer
+ /// must not re-enter the core.
+ pull_tty_taken: ?*const fn (ctx: ?*anyopaque, pane: u8) bool = null,
+
+ // ---- the filesystem ----
+ /// `pane` travels with the bytes only so a host that posts a "saved"
+ /// message row can name the right pane; the core already resolved the
+ /// path and the content, so save_file and save_text both land here.
+ push_write_file: ?*const fn (ctx: ?*anyopaque, pane: u8, path: []const u8, bytes: []const u8) void = null,
+ /// The session dump. Separate because the host also chooses WHERE it
+ /// goes (dump.outPath is libc-bound; the freestanding core cannot).
+ push_write_dump: ?*const fn (ctx: ?*anyopaque, bytes: []const u8) void = null,
+ push_watch_file: ?*const fn (ctx: ?*anyopaque, pane: u8, path: []const u8, on: bool) void = null,
+ push_watch_theme: ?*const fn (ctx: ?*anyopaque, generation: u32, on: bool) void = null,
+ push_dump_themes: ?*const fn (ctx: ?*anyopaque, pane: u8) void = null,
+
+ // ---- the desktop ----
+ push_set_clipboard: ?*const fn (ctx: ?*anyopaque, text: []const u8) void = null,
+ /// Ask; the answer arrives later as an ordinary `Event.paste`, which is
+ /// why this returns nothing and is still a pull: two hosts answering
+ /// would paste the clipboard twice. Null answers immediately from the
+ /// in-process clipboard instead, so a request never goes unanswered.
+ pull_read_clipboard: ?*const fn (ctx: ?*anyopaque) void = null,
+ push_open_link: ?*const fn (ctx: ?*anyopaque, url: []const u8) void = null,
+
+ // ---- work that must leave the loop ----
+ /// Both answer exactly once, keyed by the id they carry, so both are
+ /// pulls: a second host's reply would arrive for a request already
+ /// completed and the core would apply it to whatever holds that id now.
+ pull_lsp: ?*const fn (ctx: ?*anyopaque, req: LspRequest) void = null,
+ pull_pipe: ?*const fn (ctx: ?*anyopaque, id: u32) void = null,
+ };
+};
+
+/// Where a host with no `write_dump` puts a session dump. Named here so the
+/// core writes it and reports it as one path.
+pub const fallback_dump_path = "pardes.dump.zon";
+
+/// The in-process implementations behind every null method: a virtual
+/// filesystem, a virtual clipboard, and a record of what was asked of ptys and
+/// the desktop. Ordinary data structures, one set per Pardes instance.
+///
+/// The filesystem is not empty. It is pardes's own source, embedded — see
+/// source_manifest.zig — with `files` holding only what this session WROTE, so
+/// a Save shadows the built-in copy and reading it back returns the edit. That
+/// is what makes a host with no file methods a usable pardes rather than one
+/// staring at an empty buffer.
+///
+/// Only `files` grows, and it grows by REPLACING a path's content, so no
+/// session accumulates. A pane whose child does not exist is SILENT: its bytes
+/// are dropped rather than transcribed, because nothing reads a transcript back
+/// and a browser session would then carry every keystroke forever.
+pub const Fallback = struct {
+ gpa: std.mem.Allocator,
+ files: std.StringHashMapUnmanaged([]u8) = .empty,
+ clipboard: std.ArrayListUnmanaged(u8) = .empty,
+ /// Last link a host with no browser was asked to open.
+ link: std.ArrayListUnmanaged(u8) = .empty,
+ spawned: [pardes.MAX_PANES]bool = @splat(false),
+ watched: [pardes.MAX_PANES]bool = @splat(false),
+
+ pub fn deinit(f: *Fallback) void {
+ var it = f.files.iterator();
+ while (it.next()) |e| {
+ f.gpa.free(e.key_ptr.*);
+ f.gpa.free(e.value_ptr.*);
+ }
+ f.files.deinit(f.gpa);
+ f.clipboard.deinit(f.gpa);
+ f.link.deinit(f.gpa);
+ }
+
+ pub fn writeFile(f: *Fallback, path: []const u8, bytes: []const u8) void {
+ const copy = f.gpa.dupe(u8, bytes) catch return;
+ if (f.files.getEntry(path)) |e| {
+ f.gpa.free(e.value_ptr.*);
+ e.value_ptr.* = copy;
+ return;
+ }
+ const key = f.gpa.dupe(u8, path) catch {
+ f.gpa.free(copy);
+ return;
+ };
+ f.files.put(f.gpa, key, copy) catch {
+ f.gpa.free(key);
+ f.gpa.free(copy);
+ };
+ }
+
+ /// What this path holds now: the session's own write, else the embedded
+ /// source. Borrowed — the bytes live in the map or in the binary.
+ pub fn get(f: *const Fallback, path: []const u8) ?[]const u8 {
+ if (f.files.get(path)) |written| return written;
+ return source_manifest.find(path);
+ }
+
+ pub fn setClipboard(f: *Fallback, text: []const u8) void {
+ f.clipboard.clearRetainingCapacity();
+ f.clipboard.appendSlice(f.gpa, text) catch {};
+ }
+
+ pub fn setLink(f: *Fallback, url: []const u8) void {
+ f.link.clearRetainingCapacity();
+ f.link.appendSlice(f.gpa, url) catch {};
+ }
+};
+
+/// Fan out one core's host calls to several real hosts at once — the debugging
+/// arrangement: every input reaches every host, and each host answers into its
+/// own state.
+///
+/// It advertises a method only when some wrapped host actually implements it,
+/// so wrapping does NOT mask the core's per-method fallback: fan out two hosts
+/// that never opened a link and the link still lands in `Fallback`.
+pub const Fanout = struct {
+ hosts: []const Host,
+ vt: Host.VTable = .{},
+
+ pub fn init(hosts: []const Host) Fanout {
+ var f: Fanout = .{ .hosts = hosts };
+ inline for (@typeInfo(Host.VTable).@"struct".fields) |field| {
+ for (hosts) |h| if (@field(h.vtable, field.name) != null) {
+ @field(f.vt, field.name) = @field(all, field.name);
+ break;
+ };
+ }
+ return f;
+ }
+
+ pub fn host(f: *const Fanout) Host {
+ return .{ .ctx = @ptrCast(@constCast(f)), .vtable = &f.vt };
+ }
+
+ fn self(ctx: ?*anyopaque) *const Fanout {
+ return @ptrCast(@alignCast(ctx.?));
+ }
+
+ /// A wrapper for every method, whether or not this fan-out advertises it.
+ /// Synthesized, so adding a method to `Host.VTable` needs no code here.
+ const all: Host.VTable = blk: {
+ var t: Host.VTable = .{};
+ for (@typeInfo(Host.VTable).@"struct".fields) |field| {
+ @field(t, field.name) = fan(field.name);
+ }
+ break :blk t;
+ };
+
+ fn Method(comptime name: []const u8) std.builtin.Type.Fn {
+ const ptr = @typeInfo(@FieldType(Host.VTable, name)).optional.child;
+ return @typeInfo(@typeInfo(ptr).pointer.child).@"fn";
+ }
+
+ /// How to route a method, read off its own name. A method that is neither
+ /// is a COMPILE ERROR rather than a silent push, because the failure of a
+ /// forgotten pull is invisible in every unit test and obvious only to the
+ /// user: one Ctrl-V pasting twice.
+ fn isPull(comptime name: []const u8) bool {
+ if (std.mem.startsWith(u8, name, "pull_")) return true;
+ if (std.mem.startsWith(u8, name, "push_")) {
+ if (Method(name).return_type.? != void) @compileError("Host.VTable." ++
+ name ++ " reaches every host, so it cannot return a value: whose answer would it be?");
+ return false;
+ }
+ @compileError("Host.VTable." ++ name ++ " must be named push_… (every host gets it) " ++
+ "or pull_… (exactly one host serves it, because there is one of whatever comes back)");
+ }
+
+ /// The walk, written once: `args` is everything after `ctx`.
+ fn dispatch(comptime name: []const u8, ctx: ?*anyopaque, args: anytype) Method(name).return_type.? {
+ for (self(ctx).hosts) |h| if (@field(h.vtable, name)) |fp| {
+ const answer = @call(.auto, fp, .{h.ctx} ++ args);
+ if (comptime isPull(name)) return answer;
+ };
+ // `init` installs a wrapper only when some host has the method, so a
+ // pull always found one; a zero is the honest answer if that changes.
+ const R = Method(name).return_type.?;
+ if (comptime R != void) return std.mem.zeroes(R);
+ }
+
+ /// One wrapper, built from the method's own signature: the parameter list
+ /// is the only part that cannot be derived, so there is one shape per
+ /// arity rather than one per method.
+ fn fan(comptime name: []const u8) @FieldType(Host.VTable, name) {
+ const m = Method(name);
+ const R = m.return_type.?;
+ const P = m.params;
+ return switch (P.len) {
+ 1 => struct {
+ fn w(c: ?*anyopaque) R {
+ return dispatch(name, c, .{});
+ }
+ }.w,
+ 2 => struct {
+ fn w(c: ?*anyopaque, a: P[1].type.?) R {
+ return dispatch(name, c, .{a});
+ }
+ }.w,
+ 3 => struct {
+ fn w(c: ?*anyopaque, a: P[1].type.?, b: P[2].type.?) R {
+ return dispatch(name, c, .{ a, b });
+ }
+ }.w,
+ 4 => struct {
+ fn w(c: ?*anyopaque, a: P[1].type.?, b: P[2].type.?, d: P[3].type.?) R {
+ return dispatch(name, c, .{ a, b, d });
+ }
+ }.w,
+ else => @compileError("Fanout has no wrapper shape for " ++ name ++ "'s arity"),
+ };
+ }
+};
diff --git a/src/look.zig b/src/look.zig
index ece2ee0f..fbcc80a9 100644
--- a/src/look.zig
+++ b/src/look.zig
@@ -17,10 +17,9 @@ const libc = std.c;
const pardes = @import("pardes.zig");
const config = @import("config.zig");
const pdf_enabled = @import("pardes_config").mupdf;
-const embedded_sources = if (pardes.platform == .web) @import("embedded_sources") else struct {
- pub const Source = struct { path: []const u8, contents: []const u8 };
- pub const all = [_]Source{};
-};
+/// The virtual filesystem, on every platform: the browser has only this, and
+/// `run-isolated` chooses it (see `isolated` below).
+const embedded_sources = @import("source_manifest.zig");
extern "c" fn realpath(path: [*:0]const u8, resolved: [*]u8) ?[*:0]u8;
extern "c" fn fork() c_int;
@@ -557,7 +556,12 @@ fn findEmbeddedSource(path: []const u8, allow_root_suffix: bool) ?embedded_sourc
return null;
}
-const platform_has_fs = switch (pardes.platform) {
+/// Whether there is a real filesystem to reach at all. An ISOLATED build has
+/// none by construction — the option is comptime, so every libc path below is
+/// dead code the compiler removes rather than a branch that could be taken by
+/// accident. The browser has never had one either, and both then read the same
+/// embedded source.
+const platform_has_fs = !pardes.isolated and switch (pardes.platform) {
.tty, .gui, .macos => true,
.web => false,
};
diff --git a/src/macos.zig b/src/macos.zig
index 2569e6b3..e54e013c 100644
--- a/src/macos.zig
+++ b/src/macos.zig
@@ -25,7 +25,6 @@ const posix = std.posix;
const libc = std.c;
const pardes = @import("pardes.zig");
const look = @import("look.zig");
-const temp_file = @import("temp_file.zig");
const shell_bin = @import("shell_bin.zig");
const message = @import("message.zig");
const nested = @import("nested.zig");
@@ -499,7 +498,9 @@ const State = struct {
threaded: *std.Io.Threaded,
io: std.Io,
core: *pardes.Pardes,
- arena: std.heap.ArenaAllocator,
+ /// False for the one effect drain inside pardes_init and nothing else: no
+ /// reader task exists yet, and the first theme file must land without a fade.
+ started: bool = false,
runtime: Runtime,
cells: []Cell = &.{},
/// Frozen canonical grid paired with an encoded change mask while a content or
@@ -609,6 +610,9 @@ fn initCore(runtime: ?*const Runtime, cols_arg: u16, rows_arg: u16) !void {
var opts: pardes.Options = .{
.tty_only = true,
+ // The purpose-built 16 MiB stack-fallback buffer this host has always
+ // rendered out of; the core builds its per-frame Surface arena on it.
+ .frame_allocator = allocs.frame,
.image_allocator = allocs.image,
.pdf_allocator = allocs.pdf,
.tree_sitter_allocator = allocs.tree_sitter,
@@ -653,15 +657,15 @@ fn initCore(runtime: ?*const Runtime, cols_arg: u16, rows_arg: u16) !void {
.threaded = threaded,
.io = io,
.core = core,
- .arena = .init(allocs.frame),
.config_arena = config_arena,
.prompt_rcs = prompt_rcs,
.runtime = if (runtime) |r| r.* else .{},
};
const st = &state.?;
- // the core's one way to ask about this host's ptys, pulled at the Exec that
- // cares rather than pushed with the cwd above
- core.tty_query = .{ .ctx = st, .taken = &ttyTakenAt };
+ // Every capability this host has, including the tty pull the core makes at
+ // the Exec that cares rather than at the cwd read above. Assigned here and
+ // not left to `pump`, because the spawns below happen outside one.
+ core.host = hostFor(st);
// The real grid, delivered as an EVENT and not as Options.cols/rows: the
// core defers an integrated shell's greeting until this resize and OSC
@@ -678,7 +682,8 @@ fn initCore(runtime: ?*const Runtime, cols_arg: u16, rows_arg: u16) !void {
// itself — chdir and execv, raw syscalls with nothing allocated between
// fork and exec — not the thread count. Ordering it this way anyway keeps
// the two backends readable side by side.
- _ = drainEffects(st, false);
+ while (core.nextEffect()) |effect| core.perform(effect);
+ st.started = true;
for (&st.ptys, 0..) |*slot, id| if (slot.*) |*pt| startReader(st, pt, @intCast(id));
// Last, because it is the one thing here that publishes this process to
@@ -750,7 +755,6 @@ export fn pardes_deinit() void {
if (st.previous_cells.len > 0) st.gpa.free(st.previous_cells);
if (st.changed_cells.len > 0) st.gpa.free(st.changed_cells);
if (st.images.len > 0) st.gpa.free(st.images);
- st.arena.deinit();
st.core.deinit();
pardes.image.stop();
if (comptime pardes.pdf_enabled) pardes.pdf.stop();
@@ -870,7 +874,8 @@ export fn pardes_panel_animation_failed() void {
st.core.abandonPanelAnimations();
}
-/// Re-read the cwd of every shell that just spoke, and only those.
+/// The core's per-frame poll: re-read the cwd of every shell that just spoke,
+/// and only those.
///
/// A pane's tag shows this and a relative `Look` resolves against it, so it has
/// to follow the shell around rather than stay at the directory the pane was
@@ -881,8 +886,9 @@ export fn pardes_panel_animation_failed() void {
/// and a busy one costs one libproc call per pane per burst.
///
/// Whether a shell's tty is still that shell is NOT refreshed here: nothing
-/// draws it, so the core pulls it instead (see `ttyTakenAt`).
-fn refreshCwds(st: *State) void {
+/// draws it, so the core pulls it instead (see `ttyTaken`).
+fn refreshCwds(ctx: ?*anyopaque) void {
+ const st = hostState(ctx);
for (&st.cwd_stale, 0..) |*stale, id| {
if (!stale.*) continue;
stale.* = false;
@@ -908,17 +914,9 @@ fn watchInitialGeneration(st: *State, pane: u8, path: []const u8) ?file_watch.Ge
return null;
}
-fn setFileWatch(st: *State, pane: u8, on: bool) void {
- if (!on) {
- const generation = st.file_watches.stop(st.gpa, pane);
- hostWatchFile(pane, generation, null, 0);
- return;
- }
- const path = paneWatchPath(st.core, pane) orelse {
- const generation = st.file_watches.stop(st.gpa, pane);
- hostWatchFile(pane, generation, null, 0);
- return;
- };
+/// Start watching the path the core resolved for this pane. Turning a watch off
+/// is the caller's business (`watchFile`); everything here is the start.
+fn setFileWatch(st: *State, pane: u8, path: []const u8) void {
const value = st.core.panes[pane] orelse return;
const generation_on_disk = watchInitialGeneration(st, pane, path) orelse return;
const generation = st.file_watches.replace(
@@ -1091,32 +1089,13 @@ export fn pardes_watch_changed(pane: u8, generation: u32) void {
if (st.file_watches.notify(pane, generation)) wake(st);
}
-/// The core's `tty_query`, asked only where a command line is about to be typed:
-/// is a program holding this pane's tty instead of the prompt we forked?
-/// `look.ttyTaken` answers `false` on darwin until it grows a libproc
-/// implementation, so this host behaves exactly as it did — the wiring is here
-/// so it cannot rot, and it costs nothing until then.
-fn ttyTakenAt(ctx: ?*anyopaque, pane: usize) bool {
- const st: *const State = @ptrCast(@alignCast(ctx orelse return false));
- const pt = st.ptys[pane] orelse return false;
- return look.ttyTaken(pt.pid, pt.file.handle);
-}
-
-/// Drain what the reader tasks collected into the core, then perform whatever
-/// the core queued in response. Returns whether this tick did any IO.
-///
-/// NOT a repaint signal, however tempting: the core changes the grid on its own
-/// for a cursor move, a selection, a mode change and a scroll, none of which
-/// queue an effect or read a pty, so all four return false here. The macOS host
-/// learned that the expensive way — see the comment on pump() in
-/// src/macos/Sources/AppDelegate.swift.
-export fn pardes_tick() bool {
- const st = &(state orelse return false);
- // Cleared before the drain: a reader that pushes during this tick must be
- // able to schedule the next one.
- st.inbox.wake_pending.store(false, .release);
+/// What arrived off the loop thread since the last tick: pty output, a reaped
+/// shell, a nested `Look`, and the file-watch edges Swift debounced. Every one
+/// of them carries borrowed bytes, so they go straight into `update` rather
+/// than through the core's event queue.
+fn drainInbox(st: *State) bool {
var batch = st.inbox.take();
- var changed = batch.len > 0;
+ var did = batch.len > 0;
for (batch.slice()) |msg| {
defer msg.free(st.gpa);
switch (msg) {
@@ -1141,14 +1120,45 @@ export fn pardes_tick() bool {
for (0..pardes.MAX_PANES) |pane| {
const id: u8 = @intCast(pane);
if (!st.file_watches.takeDirty(id)) continue;
- if (reloadWatchedFile(st, id, true)) changed = true;
+ if (reloadWatchedFile(st, id, true)) did = true;
}
if (st.file_watches.takeDirty(theme_watch_pane)) {
- if (reloadWatchedTheme(st, true)) changed = true;
+ if (reloadWatchedTheme(st, true)) did = true;
}
- refreshCwds(st);
- if (drainEffects(st, true)) changed = true;
- return changed;
+ return did;
+}
+
+/// Hand the core what arrived off-thread, then perform whatever it queued in
+/// response. Returns whether this tick had IO to do, which is what bounds the
+/// app's "pump until quiet" drain loop.
+///
+/// It deliberately does NOT render. AppKit wants to be TOLD the view is dirty
+/// and to draw once per display refresh: a pty burst is a dozen wakeups and a
+/// dozen ticks, and rendering inside each of them would encode eleven grids
+/// nobody ever sees. The render is `pardes_frame`, which the draw callback
+/// calls at display cadence — the coalescing this whole boundary is shaped
+/// around, and what src/macos/pardes.h has always said pardes_frame is.
+///
+/// NOT a repaint signal, however tempting: the core changes the grid on its own
+/// for a cursor move, a selection, a mode change and a scroll, none of which
+/// queue an effect or read a pty, so all four return false here. The macOS host
+/// learned that the expensive way — see the comment on pump() in
+/// src/macos/Sources/AppDelegate.swift.
+export fn pardes_tick() bool {
+ const st = &(state orelse return false);
+ // Cleared before the drain: a reader that pushes during this tick must be
+ // able to schedule the next one.
+ st.inbox.wake_pending.store(false, .release);
+ var did = drainInbox(st);
+ // Straight to `perform`, not through `pump`: the effects are the IO half of
+ // a tick and the render is not. `core.host` was seated once at init and is
+ // this host for the life of the session, so both this loop and the
+ // `tty_taken` pull the next keystroke makes land here.
+ while (st.core.nextEffect()) |effect| {
+ did = true;
+ st.core.perform(effect);
+ }
+ return did;
}
/// Advance exactly one display-clock frame. Event pumps deliberately never
@@ -1381,22 +1391,44 @@ export fn pardes_resize(cols_arg: u16, rows_arg: u16, cell_w: u16, cell_h: u16)
// ---------------------------------------------------------------- frame out
+/// Render one frame, and the only place this host renders: AppKit's draw
+/// callback, which is the one call it coalesces. A burst of input or pty output
+/// marks the view dirty many times and is drawn once, so however much work the
+/// ticks above drained, the grid is encoded once per display refresh.
+///
+/// It is the core's whole loop iteration — drain, perform, poll, render,
+/// present — and it cannot block: `wait_input` is null, because AppKit
+/// delivered the events before it called us and sleeping inside a run-loop
+/// callback is a beachball. `present` copies the result into the flat buffers
+/// the accessors below describe (presentFrame); returns their cell count, or 0
+/// if the render failed.
export fn pardes_frame() u32 {
const st = &(state orelse return 0);
- _ = st.arena.reset(.retain_capacity);
- // The accessors below must never describe a different frame than the count
- // this returns, so a failure empties all of them together rather than
- // leaving last frame's buffer behind a fresh cols/rows.
+ st.core.pump(hostFor(st)) catch |err| {
+ log.err("render failed: {t}", .{err});
+ clearFrame(st);
+ return 0;
+ };
+ return @intCast(st.frame_len);
+}
+
+/// Everything the accessors below describe is emptied together, so a failure
+/// can never leave last frame's buffer behind a fresh cols/rows.
+fn clearFrame(st: *State) void {
st.frame_len = 0;
st.frame_cols = 0;
st.frame_rows = 0;
st.images_len = 0;
st.panel_tracks_len = 0;
st.panel_diff_len = 0;
- const surface = st.core.render(st.arena.allocator()) catch |err| {
- log.err("render failed: {t}", .{err});
- return 0;
- };
+}
+
+/// Copy one rendered frame into the flat buffers the native renderer reads.
+/// Core-owned Cell layout is never borrowed across the ABI, so the grid, the
+/// panel diff, the attachments and the tracks are all encoded here.
+fn presentFrame(ctx: ?*anyopaque, surface: *const pardes.Surface) void {
+ const st = hostState(ctx);
+ clearFrame(st);
const count: usize = @as(usize, surface.cols) * surface.rows;
if (count != st.cells.len) {
if (count == 0) {
@@ -1407,7 +1439,7 @@ export fn pardes_frame() u32 {
st.gpa.alloc(Cell, count)
else
st.gpa.realloc(st.cells, count);
- st.cells = resized catch return 0;
+ st.cells = resized catch return;
}
}
st.frame_len = count;
@@ -1417,7 +1449,6 @@ export fn pardes_frame() u32 {
collectPanelDiff(st, surface, count);
collectImages(st, surface);
collectPanelTracks(st, surface);
- return @intCast(count);
}
/// Flatten tracks into the C-visible order the shader composites them. Pane
@@ -1709,147 +1740,191 @@ fn activeFilePath(st: *State) ?[]const u8 {
return null;
}
-// ---------------------------------------------------------------- effects
+// ---------------------------------------------------------------- host seam
-/// Perform the IO the core queued. `threads_ok` is false for the one drain
-/// inside pardes_init, which runs before any reader task exists.
+/// What this host can do, for the core's own loop to call. What it deliberately
+/// cannot:
+/// * `wait_input` — AppKit delivered the events before it called us and owns
+/// the sleep; blocking inside a run-loop callback is a beachball.
+/// * `post_present` — presentation is acknowledged when the destination
+/// context has accepted the frame (pardes_frame_presented), which is a
+/// later callback, not the moment the cells were encoded.
+/// * `lsp` — the core's own empty answer is exactly what this host replied,
+/// and for the same reason: a dropped request leaves lsp_wait armed and
+/// every later dot-Tab dead.
+/// * `pipe` — no worker to hand a job to. Teardown is not a method at all:
+/// pardes_deinit is the app's own call, made after AppKit's loop rather
+/// than from inside one.
///
-/// ponytail: lsp and pipe still do no work here. Each wants real machinery — a
+/// ponytail: lsp and pipe still do no work. Each wants real machinery — a
/// worker plus a snapshot of the pane's file for lsp (src/tty/tty.zig:919), and
/// a job copy for pipe. Watch is deliberately different: FileWatcher.swift
/// owns its per-directory DispatchSource and only returns a debounced hint;
-/// this main-thread drain owns the bytes, hash and shared text/PDF core event.
-fn drainEffects(st: *State, threads_ok: bool) bool {
+/// these main-thread methods own the bytes, hash and shared text/PDF core event.
+const vtable: pardes.Host.VTable = .{
+ .push_present = presentFrame,
+ .push_poll_frame = refreshCwds,
+ .push_spawn = spawnShell,
+ .push_pty_write = ptyWrite,
+ .push_pty_resize = ptyResize,
+ .pull_tty_taken = ttyTaken,
+ .push_write_file = writeFile,
+ .push_write_dump = writeDump,
+ .push_watch_file = watchFile,
+ .push_watch_theme = watchTheme,
+ .push_dump_themes = dumpThemes,
+ .push_set_clipboard = setClipboard,
+ .pull_read_clipboard = readClipboard,
+ .push_open_link = openLink,
+};
+
+fn hostFor(st: *State) pardes.Host {
+ return .{ .ctx = st, .vtable = &vtable };
+}
+
+fn hostState(ctx: ?*anyopaque) *State {
+ return @ptrCast(@alignCast(ctx.?));
+}
+
+fn spawnShell(ctx: ?*anyopaque, pane: u8, cwd: []const u8) void {
+ const st = hostState(ctx);
const core = st.core;
- var did = false;
- while (core.nextEffect()) |effect| {
- did = true;
- switch (effect) {
- .spawn => |sp| {
- // The core reuses pane ids and has no close effect, so a
- // deleted pane's shell lives in its slot until a respawn lands
- // here. Reap it: cancel joins the reader, and the generation
- // bump makes its late bytes and eof unreadable.
- reap(st, sp.pane);
- st.gens[sp.pane] +%= 1;
- const gen = st.gens[sp.pane];
+ // The core reuses pane ids and has no close effect, so a deleted pane's
+ // shell lives in its slot until a respawn lands here. Reap it: cancel joins
+ // the reader, and the generation bump makes its late bytes and eof
+ // unreadable.
+ reap(st, pane);
+ st.gens[pane] +%= 1;
+ const gen = st.gens[pane];
- const cwd = sp.cwd.slice();
- var cwd_buf: [256:0]u8 = undefined;
- var cwd_z: ?[*:0]const u8 = null;
- // <= because writing the sentinel slot of a [N:0]u8 is legal,
- // and Effect's cwd buffer is exactly 256: `<` would silently
- // drop a maximal path and start the shell wherever the app
- // bundle was launched from instead.
- if (cwd.len > 0 and cwd.len <= cwd_buf.len) {
- @memcpy(cwd_buf[0..cwd.len], cwd);
- cwd_buf[cwd.len] = 0;
- cwd_z = @ptrCast(&cwd_buf);
- }
- const child = forkShell(core, sp.pane, &st.prompt_rcs, core.shellBin(), cwd_z, core.screen_h, core.screen_w);
- st.ptys[sp.pane] = .{
- .file = child.file,
- .pid = child.pid,
- .gen = gen,
- .reader = .{ .any_future = null, .result = {} },
- };
- // Report the pane's starting directory back to the core (tags);
- // the slot needs no occupancy reset, nothing is remembered.
- var lbuf: [1024]u8 = undefined;
- if (look.shellCwd(child.pid, &lbuf)) |wd| core.setCwd(sp.pane, wd);
- if (threads_ok) if (st.ptys[sp.pane]) |*pt| startReader(st, pt, sp.pane);
- },
- .write => |w| {
- if (st.ptys[w.pane]) |pt| writeFd(pt.file.handle, w.bytes.slice());
- },
- .resize_pty => |rs| {
- if (st.ptys[rs.pane]) |pt| {
- const ws: posix.winsize = .{ .row = rs.rows, .col = rs.cols, .xpixel = 0, .ypixel = 0 };
- _ = posix.system.ioctl(pt.file.handle, TIOCSWINSZ, @intFromPtr(&ws));
- }
- },
- .open_link => |url| look.openLink(url.slice()),
- .save_file => |sf| {
- const pane = core.panes[sf.pane] orelse continue;
- const f = pane.file orelse continue;
- var pathbuf: [4096:0]u8 = undefined;
- if (f.path.len >= pathbuf.len) continue;
- @memcpy(pathbuf[0..f.path.len], f.path);
- pathbuf[f.path.len] = 0;
- const fd = libc.open(pathbuf[0..f.path.len :0], .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
- if (fd < 0) continue;
- writeFd(fd, f.content);
- _ = libc.close(fd);
- // The directory source will observe our own close. Move its
- // baseline first so that notification is a hash no-op instead
- // of manufacturing an external reload and undo boundary.
- st.file_watches.restampText(
- sf.pane,
- f.path,
- std.hash.Wyhash.hash(0, f.content),
- );
- // After the write, not beside it: every `continue` above is a
- // save that did not happen and must not be reported as one.
- var mbuf: [256]u8 = undefined;
- core.setMessage(sf.pane, message.stamp(&mbuf, "saved", f.path));
- },
- .new_file => |request| {
- var path_buf: [4096:0]u8 = undefined;
- const made = temp_file.create(&path_buf) orelse continue;
- if (core.openNewFile(request.pane, request.serial, made.path))
- made.adopt()
- else
- made.discard();
- },
- .write_dump => {
- const out = core.dump_out orelse continue;
- var pbuf: [1024:0]u8 = undefined;
- const path = pardes.dump.outPath(&pbuf) orelse continue;
- const fd = libc.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
- if (fd < 0) continue;
- writeFd(fd, out);
- _ = libc.close(fd);
- core.setLastDump(path);
- },
- .dump_themes => |request| {
- const config_dir = core.opts.config_dir orelse continue;
- const out_dir = user_config.dumpThemes(st.io, st.gpa, config_dir, pardes.themes) catch |err| {
- core.reportError(request.pane, "dump themes", err);
- continue;
- };
- defer st.gpa.free(out_dir);
- var mbuf: [256]u8 = undefined;
- core.setMessage(request.pane, message.stamp(&mbuf, "dumped themes", out_dir));
- },
- .set_clipboard => {
- const cb = st.runtime.set_clipboard orelse continue;
- const y = core.yank orelse continue;
- cb(st.runtime.userdata, y.ptr, y.len);
- },
- // The host answers with pardes_paste, which the AppDelegate calls
- // straight back inside this call: NSPasteboard reads are
- // synchronous, so the paste event lands here, mid-drain. That is
- // safe and deliberate — pardes_paste only feeds core.update, and
- // whatever that queues is picked up by this same loop rather than
- // waiting a tick. A host with a null callback simply never pastes.
- .read_clipboard => {
- const cb = st.runtime.read_clipboard orelse continue;
- cb(st.runtime.userdata);
- },
- // An empty answer, immediately: the honest reply from a shell with
- // no worker, and the only safe one. Tab after a `.` DIVERTS to the
- // backend instead of indenting and indents late, when the answer
- // comes back empty (lspResponse); drop the effect and lsp_wait
- // stays armed, the retroactive indent never fires, and every
- // dot-Tab for the rest of the session does nothing at all.
- .lsp => |q| core.update(.{ .lsp_resp = .{ .id = q.id, .rows = "" } }),
- .watch => |watch| setFileWatch(st, watch.pane, watch.on),
- .theme_file => |request| setThemeFileWatch(st, request.generation, request.on, threads_ok),
- .pipe => {},
- .quit => {},
- }
+ var cwd_buf: [256:0]u8 = undefined;
+ var cwd_z: ?[*:0]const u8 = null;
+ // <= because writing the sentinel slot of a [N:0]u8 is legal, and Effect's
+ // cwd buffer is exactly 256: `<` would silently drop a maximal path and
+ // start the shell wherever the app bundle was launched from instead.
+ if (cwd.len > 0 and cwd.len <= cwd_buf.len) {
+ @memcpy(cwd_buf[0..cwd.len], cwd);
+ cwd_buf[cwd.len] = 0;
+ cwd_z = @ptrCast(&cwd_buf);
}
- return did;
+ const child = forkShell(core, pane, &st.prompt_rcs, core.shellBin(), cwd_z, core.screen_h, core.screen_w);
+ st.ptys[pane] = .{
+ .file = child.file,
+ .pid = child.pid,
+ .gen = gen,
+ .reader = .{ .any_future = null, .result = {} },
+ };
+ // Report the pane's starting directory back to the core (tags); the slot
+ // needs no occupancy reset, nothing is remembered.
+ var lbuf: [1024]u8 = undefined;
+ if (look.shellCwd(child.pid, &lbuf)) |wd| core.setCwd(pane, wd);
+ if (st.started) if (st.ptys[pane]) |*pt| startReader(st, pt, pane);
+}
+
+fn ptyWrite(ctx: ?*anyopaque, pane: u8, bytes: []const u8) void {
+ const st = hostState(ctx);
+ if (st.ptys[pane]) |pt| writeFd(pt.file.handle, bytes);
+}
+
+fn ptyResize(ctx: ?*anyopaque, pane: u8, cols: u16, rows: u16) void {
+ const st = hostState(ctx);
+ const pt = st.ptys[pane] orelse return;
+ const ws: posix.winsize = .{ .row = rows, .col = cols, .xpixel = 0, .ypixel = 0 };
+ _ = posix.system.ioctl(pt.file.handle, TIOCSWINSZ, @intFromPtr(&ws));
+}
+
+/// Asked only where a command line is about to be typed: is a program holding
+/// this pane's tty instead of the prompt we forked? `look.ttyTaken` answers
+/// `false` on darwin until it grows a libproc implementation, so this host
+/// behaves exactly as it did — the wiring is here so it cannot rot, and it
+/// costs nothing until then.
+fn ttyTaken(ctx: ?*anyopaque, pane: u8) bool {
+ const st = hostState(ctx);
+ const pt = st.ptys[pane] orelse return false;
+ return look.ttyTaken(pt.pid, pt.file.handle);
+}
+
+/// A file pane's save and a scrollback's both land here; the core has already
+/// resolved which path and which bytes.
+fn writeFile(ctx: ?*anyopaque, pane: u8, path: []const u8, bytes: []const u8) void {
+ const st = hostState(ctx);
+ var pathbuf: [4096:0]u8 = undefined;
+ if (path.len >= pathbuf.len) return;
+ @memcpy(pathbuf[0..path.len], path);
+ pathbuf[path.len] = 0;
+ const fd = libc.open(pathbuf[0..path.len :0], .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
+ if (fd < 0) return;
+ writeFd(fd, bytes);
+ _ = libc.close(fd);
+ // The directory source will observe our own close. Move its baseline first
+ // so that notification is a hash no-op instead of manufacturing an external
+ // reload and undo boundary.
+ st.file_watches.restampText(pane, path, std.hash.Wyhash.hash(0, bytes));
+ // After the write, not beside it: every early return above is a save that
+ // did not happen and must not be reported as one.
+ var mbuf: [256]u8 = undefined;
+ st.core.setMessage(pane, message.stamp(&mbuf, "saved", path));
+}
+
+fn writeDump(ctx: ?*anyopaque, bytes: []const u8) void {
+ const st = hostState(ctx);
+ var pbuf: [1024:0]u8 = undefined;
+ const path = pardes.dump.outPath(&pbuf) orelse return;
+ const fd = libc.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
+ if (fd < 0) return;
+ writeFd(fd, bytes);
+ _ = libc.close(fd);
+ st.core.setLastDump(path);
+}
+
+fn watchFile(ctx: ?*anyopaque, pane: u8, path: []const u8, on: bool) void {
+ const st = hostState(ctx);
+ // No path is a pane with nothing on disk to watch (an output buffer, an
+ // image), which is the same answer as being turned off.
+ if (!on or path.len == 0) {
+ const generation = st.file_watches.stop(st.gpa, pane);
+ hostWatchFile(pane, generation, null, 0);
+ return;
+ }
+ setFileWatch(st, pane, path);
+}
+
+fn watchTheme(ctx: ?*anyopaque, generation: u32, on: bool) void {
+ const st = hostState(ctx);
+ setThemeFileWatch(st, generation, on, st.started);
+}
+
+fn dumpThemes(ctx: ?*anyopaque, pane: u8) void {
+ const st = hostState(ctx);
+ const config_dir = st.core.opts.config_dir orelse return;
+ const out_dir = user_config.dumpThemes(st.io, st.gpa, config_dir, pardes.themes) catch |err| {
+ st.core.reportError(pane, "dump themes", err);
+ return;
+ };
+ defer st.gpa.free(out_dir);
+ var mbuf: [256]u8 = undefined;
+ st.core.setMessage(pane, message.stamp(&mbuf, "dumped themes", out_dir));
+}
+
+fn setClipboard(ctx: ?*anyopaque, text: []const u8) void {
+ const st = hostState(ctx);
+ const cb = st.runtime.set_clipboard orelse return;
+ cb(st.runtime.userdata, text.ptr, text.len);
+}
+
+/// The host answers with pardes_paste, which the AppDelegate calls straight
+/// back inside this call: NSPasteboard reads are synchronous, so the paste
+/// event lands mid-pump. That is safe and deliberate — pardes_paste only feeds
+/// core.update, and whatever that queues is picked up by the same effect loop
+/// rather than waiting a tick. A host with a null callback simply never pastes.
+fn readClipboard(ctx: ?*anyopaque) void {
+ const st = hostState(ctx);
+ const cb = st.runtime.read_clipboard orelse return;
+ cb(st.runtime.userdata);
+}
+
+fn openLink(_: ?*anyopaque, url: []const u8) void {
+ look.openLink(url);
}
// ---------------------------------------------------------------- workers
@@ -2406,3 +2481,59 @@ test "the dial flings in proportion to the release, and not at all when placed"
try std.testing.expect(travel(100_000) / rotation_notch_degrees < 12);
try std.testing.expect(travel(100_000) / rotation_notch_degrees > 8);
}
+
+// The loop, end to end, on the one machine that can run it: the core owns the
+// iteration now, so the two things this file used to spell out by hand are
+// exactly what a live session has to keep proving. A frame exists because the
+// DRAW rendered one — ticks drain work and never render, which is what lets
+// AppKit coalesce a burst into a single encoded grid — and elapsed animation
+// time is spent only by the display clock, however many times the tick runs.
+//
+// It really boots: a shell is forked, an inbox drains, effects are performed
+// through the vtable. Everything above it is the Swift app, which needs a Mac.
+test "a live session renders on the draw and animates only on the display clock" {
+ try std.testing.expectEqual(@as(c_int, 0), pardes_init(null, 80, 24));
+ defer pardes_deinit();
+ const st = &state.?;
+
+ // The spawn effect reached forkpty rather than the core's silent fallback:
+ // init performs its own drain, before any reader task exists.
+ try std.testing.expect(st.ptys[0] != null);
+ // A tick drains and performs. It publishes no frame, so ten of them in a
+ // pty burst cost one render and not ten.
+ _ = pardes_tick();
+ _ = pardes_tick();
+ try std.testing.expectEqual(@as(u16, 0), pardes_frame_cols());
+ try std.testing.expect(pardes_frame_cells() == null);
+
+ // The draw is what renders and presents.
+ try std.testing.expectEqual(@as(u32, 80 * 24), pardes_frame());
+ try std.testing.expectEqual(@as(u16, 80), pardes_frame_cols());
+ try std.testing.expectEqual(@as(u16, 24), pardes_frame_rows());
+ try std.testing.expect(pardes_frame_cells() != null);
+
+ // Two themes, so the second retarget is a real transition whatever the
+ // developer's config booted this session wearing.
+ for ([_][]const u8{ "Theme dark", "Theme acme" }) |command| {
+ pardes_command(command.ptr, command.len);
+ _ = pardes_tick();
+ _ = pardes_frame();
+ }
+ try std.testing.expect(pardes_animating());
+ const step = st.core.chrome_animation.step;
+ // Input and pty pumps drain work and draws encode it; neither spends a
+ // frame, which is what keeps a burst of keys from collapsing a ten-frame
+ // fade into one.
+ _ = pardes_tick();
+ _ = pardes_frame();
+ _ = pardes_tick();
+ _ = pardes_frame();
+ try std.testing.expectEqual(step, st.core.chrome_animation.step);
+ try std.testing.expectEqual(@as(usize, 0), st.core.in_len);
+ // Only the display clock spends it, and exactly one frame per call.
+ try std.testing.expect(pardes_animation_tick());
+ try std.testing.expectEqual(step + 1, st.core.chrome_animation.step);
+ _ = pardes_tick();
+ _ = pardes_frame();
+ try std.testing.expectEqual(step + 1, st.core.chrome_animation.step);
+}
diff --git a/src/output_pane.zig b/src/output_pane.zig
index ecb6f957..a7763bd3 100644
--- a/src/output_pane.zig
+++ b/src/output_pane.zig
@@ -25,6 +25,7 @@ const runtime_config = @import("runtime_config.zig");
const effect_sources = @import("effect_sources.zig");
const Builtin = builtins.registry.Builtin();
const config = @import("config.zig");
+const build_options = @import("pardes_config");
const dump = @import("dump.zig");
const lsp = @import("lsp/lsp.zig");
const gui_shader_source_mode = effect_sources.guiShaderSourceMode();
@@ -472,6 +473,17 @@ pub fn openConfig(p: *Pardes, id: usize) !void {
return openRead(p, id, .{ .cmd = .Config }, "", content);
}
+/// The version banner plus the embedded CHANGELOG, so an installed binary can
+/// say what it is and what changed without a repository beside it.
+pub fn openChangelog(p: *Pardes, id: usize) !void {
+ var out: std.Io.Writer.Allocating = .init(p.gpa);
+ errdefer out.deinit();
+ try out.writer.print("pardes {s}\n\n", .{build_options.version});
+ try out.writer.writeAll(@embedFile("CHANGELOG.md"));
+ const content = try out.toOwnedSlice();
+ return openRead(p, id, .{ .cmd = .Changelog }, "", content);
+}
+
/// Print the implementation that this build actually uses for one effect.
/// Sources are build inputs embedded as bytes, so this stays useful from an
/// installed binary with no repository beside it.
diff --git a/src/pardes.zig b/src/pardes.zig
index 968b73fb..405cc3f2 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -46,6 +46,13 @@ pub const allocators = @import("allocators.zig");
pub const image = @import("image.zig");
pub const dump = @import("dump.zig");
pub const lsp = @import("lsp/lsp.zig");
+/// The host seam: one struct of optional function pointers, with in-core
+/// defaults for every method a host leaves null. See src/host.zig.
+const host_mod = @import("host.zig");
+pub const Host = host_mod.Host;
+pub const Fanout = host_mod.Fanout;
+pub const Fallback = host_mod.Fallback;
+pub const fallback_dump_path = host_mod.fallback_dump_path;
/// Tracy's frame boundary, re-exported so a host that is not a shell — the
/// fling benchmark — can delimit the same frames the tty loop delimits without
/// reaching around the core for src/tracy.zig and its build options. A no-op
@@ -55,6 +62,12 @@ pub const frameMark = tracy.frameMark;
pub const Platform = enum { tty, gui, web, macos };
pub const platform: Platform = @field(Platform, @tagName(@import("pardes_config").platform));
+/// A build with no host but its display: the embedded source filesystem, the
+/// in-process clipboard, silent ptys. Comptime, and its own option module
+/// rather than a `pardes_config` field, because it is the one setting that
+/// produces a SECOND executable from the same graph — see `run-isolated`.
+pub const isolated = @import("pardes_isolation").isolated;
+
/// Frontends that draw their own text, and can therefore be told which face to
/// wear. On the tty the font belongs to the terminal emulator and in the
/// browser it belongs to the page, so there the Font builtins are not
@@ -147,6 +160,11 @@ const dirty_marker = " *";
// parser recognizes them as defaults while new dumps carry an explicit tail.
const legacy_pane_tail = " Del";
const legacy_file_pane_tail = " Save Del";
+// The defaults from the release before Newtty joined every tagline. Recognized
+// so a dump written then upgrades instead of keeping the old word as a tail.
+const prev_pane_tail = " New Del";
+const prev_file_pane_tail = " Save New Del";
+const prev_terminal_pane_tail = " New Del Filter";
// Builtins: executing the name (middle-click / Tab) runs it through the ONE
// dispatcher (runBuiltin, reached from execute), no matter where the name
@@ -570,7 +588,7 @@ test "pane-tag Exec prefers New and argument builtins before shell fallback" {
p.acknowledgeShell(0, "/bin/sh", false);
const pane = p.panes[0].?;
- try std.testing.expectEqualStrings(" New Del Filter", Pardes.curTail(pane));
+ try std.testing.expectEqualStrings(" New Newtty Del Filter", Pardes.curTail(pane));
const tag_x = p.rects[0].x + config.GUTTER;
const tag_y = p.rects[0].y;
@@ -580,19 +598,22 @@ test "pane-tag Exec prefers New and argument builtins before shell fallback" {
// the rendered tag rather than assumed to be at its left edge.
const rendered = try p.tagText(p.scratch.allocator(), pane);
const new_x = tag_x + @as(u16, @intCast(std.mem.indexOf(u8, rendered, "New").?)) + 1;
+ var panes_before: usize = 0;
+ for (p.panes) |s| if (s != null) {
+ panes_before += 1;
+ };
p.update(.{ .mouse = .{ .button = config.exec_button, .kind = .press, .col = new_x, .row = tag_y } });
p.update(.{ .mouse = .{ .button = config.exec_button, .kind = .release, .col = new_x, .row = tag_y } });
- var saw_new = false;
while (p.nextEffect()) |effect| switch (effect) {
- .new_file => |request| {
- try std.testing.expectEqual(@as(u8, 0), request.pane);
- try std.testing.expectEqual(pane.serial, request.serial);
- saw_new = true;
- },
.write => return error.NewFellThroughToPty,
else => {},
};
- try std.testing.expect(saw_new);
+ var panes_after: usize = 0;
+ for (p.panes) |s| if (s != null) {
+ panes_after += 1;
+ };
+ try std.testing.expectEqual(panes_before + 1, panes_after);
+ try std.testing.expect(p.panes[p.active].?.file.?.output != null); // the scratch
// Argument-taking builtins use the same gesture path: a tag sweep is the
// complete command line, and Theme consumes its tail without a PTY write.
@@ -629,7 +650,6 @@ test "pane-tag Exec prefers New and argument builtins before shell fallback" {
@memcpy(sent[sent_len..][0..w.bytes.slice().len], w.bytes.slice());
sent_len += w.bytes.slice().len;
},
- .new_file => return error.UnknownCommandRanNew,
else => {},
};
try std.testing.expectEqualStrings("DefinitelyNotABuiltin\r", sent[0..sent_len]);
@@ -684,7 +704,7 @@ test "an untouched tagline ends where its layout column's widest one does" {
const f = p.layoutFindTerm(p.active).?;
p.layoutInsert(f.col, f.idx + 1, below_id);
p.splitBelow(p.active, below);
- p.setCwd(below_id, "/a/deep/directory/whose/name/eats/the/right/pad/off/the/end/of/its/own/tagline");
+ p.setCwd(below_id, "/a/deep/directory/whose/name/eats/the/right/pad/the/end/of/its/own/tagline");
p.sync();
while (p.nextEffect()) |_| {}
@@ -696,7 +716,7 @@ test "an untouched tagline ends where its layout column's widest one does" {
// path, which is the whole point (equal at tw - tag_right_pad would prove
// nothing: that is where both sat before)
try std.testing.expectEqual(below_tag.len, above_tag.len);
- try std.testing.expectEqualStrings(" New Del Filter", above_tag[above_tag.len - " New Del Filter".len ..]);
+ try std.testing.expectEqualStrings(" New Newtty Del Filter", above_tag[above_tag.len - " New Newtty Del Filter".len ..]);
try std.testing.expect(above_tag.len > @as(usize, p.rects[0].w) - config.GUTTER - config.tag_right_pad);
try std.testing.expect(above_tag.len <= @as(usize, p.rects[0].w) - config.GUTTER);
@@ -745,7 +765,7 @@ test "legacy default tag tails upgrade while custom tails remain owned" {
});
p.restoreTail(terminal, terminal_old);
try std.testing.expect(!terminal.tag_init);
- try std.testing.expectEqualStrings(" New Del Filter", Pardes.curTail(terminal));
+ try std.testing.expectEqualStrings(" New Newtty Del Filter", Pardes.curTail(terminal));
// The immediately preceding release used the generic current default on
// terminals. It upgrades too, including any saved layout padding.
@@ -754,7 +774,7 @@ test "legacy default tag tails upgrade while custom tails remain owned" {
});
p.restoreTail(terminal, terminal_previous);
try std.testing.expect(!terminal.tag_init);
- try std.testing.expectEqualStrings(" New Del Filter", Pardes.curTail(terminal));
+ try std.testing.expectEqualStrings(" New Newtty Del Filter", Pardes.curTail(terminal));
const terminal_custom = try std.fmt.allocPrint(p.scratch.allocator(), "{s} Keep Del", .{
try p.tagPrefix(terminal),
@@ -786,7 +806,7 @@ test "legacy default tag tails upgrade while custom tails remain owned" {
.terminal = .{ .cwd = "/historical/cwd" },
});
try std.testing.expect(!terminal.tag_init);
- try std.testing.expectEqualStrings(" New Del Filter", Pardes.curTail(terminal));
+ try std.testing.expectEqualStrings(" New Newtty Del Filter", Pardes.curTail(terminal));
// This happens to be the historical FILE default, but on a terminal it is
// user-owned text and must not be swallowed by migration.
@@ -808,7 +828,7 @@ test "legacy default tag tails upgrade while custom tails remain owned" {
});
p.restoreTail(file, file_old);
try std.testing.expect(!file.tag_init);
- try std.testing.expectEqualStrings(" Save New Del", Pardes.curTail(file));
+ try std.testing.expectEqualStrings(" Save New Newtty Del", Pardes.curTail(file));
const file_custom = try std.fmt.allocPrint(p.scratch.allocator(), "{s} Save Mine Del", .{
try p.tagPrefix(file),
@@ -832,7 +852,7 @@ test "legacy default tag tails upgrade while custom tails remain owned" {
// with only `img PATH`. Their custom tails still migrate through the
// pane-specific legacy-prefix recognizer.
const image_doc = try image_pane.create(p, 1, "/tmp/legacy image.ppm", &.{});
- try std.testing.expectEqualStrings(" New Del", Pardes.curTail(image_doc));
+ try std.testing.expectEqualStrings(" New Newtty Del", Pardes.curTail(image_doc));
p.restoreDumpTail(image_doc, .{
.kind = .image,
.tag = "img /tmp/legacy image.ppm Keep Del",
@@ -843,6 +863,54 @@ test "legacy default tag tails upgrade while custom tails remain owned" {
try std.testing.expectEqualStrings(" Keep Del", image_doc.tagSlice());
}
+test "Joincol folds the active column into its right neighbor, keeping its panes" {
+ const gpa = std.testing.allocator;
+ const p = try Pardes.init(gpa, .{ .tty_only = true, .cols = 100, .rows = 30 });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
+
+ const right = p.freeSlot().?;
+ _ = try p.newShell(right, "");
+ try std.testing.expect(p.layoutSplitColumn(0, right, false));
+ while (p.nextEffect()) |_| {}
+ try std.testing.expectEqual(@as(usize, 2), p.ncol);
+
+ p.active = 0; // the left column is current
+ p.joinCol();
+ try std.testing.expectEqual(@as(usize, 1), p.ncol);
+ const lf = p.layoutFindTerm(0) orelse return error.LostLeftPane;
+ const rf = p.layoutFindTerm(right) orelse return error.LostRightPane;
+ try std.testing.expectEqual(lf.col, rf.col);
+
+ p.joinCol(); // no right neighbor left: inert
+ try std.testing.expectEqual(@as(usize, 1), p.ncol);
+}
+
+test "Newtty spawns a raw shell in the caller's directory" {
+ const gpa = std.testing.allocator;
+ const p = try Pardes.init(gpa, .{ .tty_only = true, .cols = 100, .rows = 30 });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
+ p.setCwd(0, "/tmp/newtty-dir");
+
+ p.spawnTty(0);
+ const free = p.active;
+ try std.testing.expect(free != 0);
+ const nt = p.panes[free] orelse return error.NoNewPane;
+ try std.testing.expect(nt.isTerminal());
+ try std.testing.expect(nt.mode == .tty);
+
+ var found = false;
+ while (p.nextEffect()) |effect| switch (effect) {
+ .spawn => |s| if (@as(usize, s.pane) == free) {
+ try std.testing.expectEqualStrings("/tmp/newtty-dir", s.cwd.slice());
+ found = true;
+ },
+ else => {},
+ };
+ try std.testing.expect(found);
+}
+
test "an unsaved file marker sits between its path and builtins until Save" {
const gpa = std.testing.allocator;
const p = try Pardes.init(gpa, .{ .tty_only = true, .cols = 100, .rows = 30 });
@@ -909,11 +977,13 @@ const FakeTtyQuery = struct {
taken: [MAX_PANES]bool = @splat(false),
asked: usize = 0,
+ const vtable: Host.VTable = .{ .pull_tty_taken = answer };
+
fn install(f: *FakeTtyQuery, p: *Pardes) void {
- p.tty_query = .{ .ctx = f, .taken = &answer };
+ p.host = .{ .ctx = f, .vtable = &vtable };
}
- fn answer(ctx: ?*anyopaque, pane: usize) bool {
+ fn answer(ctx: ?*anyopaque, pane: u8) bool {
const f: *FakeTtyQuery = @ptrCast(@alignCast(ctx.?));
f.asked += 1;
return f.taken[pane];
@@ -1186,145 +1256,201 @@ test "the host is asked about a tty only where a command line is about to go" {
try std.testing.expectEqual(@as(usize, 2), host.asked);
}
-test "New completes as an empty watched file in the calling column and focuses it" {
+test "New opens an empty scratch below the caller, inheriting its directory" {
const p = try Pardes.init(std.testing.allocator, .{ .shells = 3, .cols = 100, .rows = 30 });
defer p.deinit();
- while (p.nextEffect()) |_| {} // initial shell spawns
+ while (p.nextEffect()) |_| {}
const source: usize = 2; // the right column; active starts in the left
+ p.setCwd(source, "/tmp/pardes-scratch-dir");
const source_col = p.layoutFindTerm(source).?.col;
- try std.testing.expect(p.executeBuiltinLine(source, "New"));
- var request: ?Effect = null;
- while (p.nextEffect()) |effect| switch (effect) {
- .new_file => request = effect,
- else => {},
- };
- const new_effect = request orelse return error.MissingNewFileEffect;
- const req = new_effect.new_file;
- try std.testing.expectEqual(@as(u8, @intCast(source)), req.pane);
- try std.testing.expectEqual(p.panes[source].?.serial, req.serial);
- // Focus changes while the shell is doing IO. Placement must still use the
- // effect's calling-pane token, never this later-active left column.
- p.active = 0;
- try std.testing.expect(p.openNewFile(req.pane, req.serial, "/tmp/pardes-test-new-a"));
+ try std.testing.expect(p.executeBuiltinLine(source, "New"));
+ // no shell IO: the scratch is created in-core, focused, below the caller
+ while (p.nextEffect()) |_| {}
const id = p.active;
- try std.testing.expect(id != 0 and id != source);
+ try std.testing.expect(id != source);
try std.testing.expectEqual(source_col, p.layoutFindTerm(id).?.col);
- const sf = p.layoutFindTerm(source).?;
- try std.testing.expectEqual(id, p.col_terms[sf.col][sf.idx + 1]);
+ const np = p.panes[id].?;
+ try std.testing.expect(np.file.?.output != null); // an output buffer, empty
+ try std.testing.expectEqual(@as(usize, 0), np.file.?.content.len);
+ // its directory is a LIVE link to the opener, not a snapshot taken at New
+ try std.testing.expectEqualStrings("/tmp/pardes-scratch-dir", Pardes.paneDir(np));
+ p.setCwd(source, "/tmp/pardes-moved");
+ try std.testing.expectEqualStrings("/tmp/pardes-moved", Pardes.paneDir(np));
+}
- const file = p.panes[id].?.file orelse return error.NewIsNotAFile;
- try std.testing.expectEqualStrings("/tmp/pardes-test-new-a", file.path);
- try std.testing.expectEqual(@as(usize, 0), file.content.len);
- try std.testing.expect(file.output == null);
- try std.testing.expect(!p.panes[id].?.isTerminal());
+test "Save on a scratch asks for a path in its inherited dir and makes it a file" {
+ const p = try Pardes.init(std.testing.allocator, .{ .shells = 3, .cols = 100, .rows = 30 });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
- var watched = false;
- while (p.nextEffect()) |effect| switch (effect) {
- .watch => |w| if (w.pane == id and w.on) {
- watched = true;
- },
- else => {},
- };
- try std.testing.expect(watched);
+ const source: usize = 2;
+ p.setCwd(source, "/tmp/pardes-save-dir");
+ try std.testing.expect(p.executeBuiltinLine(source, "New"));
+ const id = p.active;
+ const np = p.panes[id].?;
+ p.sync(); // the frame boundary that gives the new pane its geometry
+ while (p.nextEffect()) |_| {}
- // It is an ordinary file from here on: Save uses the normal file effect,
- // and the dump contains its path and empty content.
+ // Save on a scratch arms a PATH input, prefilled with the inherited dir
try std.testing.expect(p.executeBuiltinLine(id, "Save"));
+ try std.testing.expect(np.hasSavePrompt());
+ try std.testing.expect(std.mem.endsWith(u8, np.tagSlice(), " Save /tmp/pardes-save-dir/"));
+
+ // typing the filename and submitting converts it into an ordinary file
+ try std.testing.expect(np.appendTag("note.txt"));
+ p.submitSave(id);
+ try std.testing.expect(np.file.?.output == null);
+ try std.testing.expectEqualStrings("/tmp/pardes-save-dir/note.txt", np.file.?.path);
var saved = false;
while (p.nextEffect()) |effect| switch (effect) {
- .save_file => |s| if (s.pane == id) {
+ .save_file => |sf| if (@as(usize, sf.pane) == id) {
saved = true;
},
else => {},
};
try std.testing.expect(saved);
- try p.dumpState();
- const state = try dump.readZon(std.testing.allocator, p.dump_out.?, "New-test");
- defer dump.free(std.testing.allocator, state);
- var dumped = false;
- for (state.panes) |dp| if (dp.file) |df| {
- if (std.mem.eql(u8, df.path, "/tmp/pardes-test-new-a")) {
- try std.testing.expectEqual(@as(usize, 0), df.content.len);
- dumped = true;
- }
- };
- try std.testing.expect(dumped);
- while (p.nextEffect()) |_| {} // write_dump
+}
+
+test "Save on a terminal writes its plaintext scrollback and stays a terminal" {
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 40, .rows = 8 });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
+ const pane = p.panes[0].?;
+ p.setCwd(0, "/tmp/pardes-tty-save");
+ p.update(.{ .output = .{ .pane = 0, .bytes = "hello scrollback\r\n" } });
+ while (p.nextEffect()) |_| {}
- // Del closes and unwatches, but there is intentionally no unlink effect:
- // adopted temporary documents preserve user data and dump restorability.
- try std.testing.expect(p.executeBuiltinLine(id, "Del"));
- try std.testing.expect(p.panes[id] == null);
- var unwatched = false;
+ try std.testing.expect(p.executeBuiltinLine(0, "Save"));
+ try std.testing.expect(pane.hasSavePrompt());
+ try std.testing.expect(pane.appendTag("log.txt"));
+ p.submitSave(0);
+
+ // the pane is untouched: still a terminal, no file behind it
+ try std.testing.expect(pane.isTerminal());
+ try std.testing.expect(pane.file == null);
+ const st = p.save_text orelse return error.MissingSaveText;
+ try std.testing.expectEqualStrings("/tmp/pardes-tty-save/log.txt", st.path);
+ try std.testing.expect(std.mem.indexOf(u8, st.content, "hello scrollback") != null);
+ var asked = false;
while (p.nextEffect()) |effect| switch (effect) {
- .watch => |w| if (w.pane == id and !w.on) {
- unwatched = true;
- },
+ .save_text => asked = true,
else => {},
};
- try std.testing.expect(unwatched);
+ try std.testing.expect(asked);
}
-test "New requests repeat, stay anchored, and reject stale or full completions" {
- const p = try Pardes.init(std.testing.allocator, .{ .shells = 3, .cols = 100, .rows = 30 });
+test "a host with no methods at all is a complete in-process pardes" {
+ const gpa = std.testing.allocator;
+ const p = try Pardes.init(gpa, .{ .tty_only = true, .cols = 40, .rows = 10 });
defer p.deinit();
while (p.nextEffect()) |_| {}
- const source: usize = 2;
- const source_col = p.layoutFindTerm(source).?.col;
- try std.testing.expect(p.executeBuiltinLine(source, "New"));
- try std.testing.expect(p.executeBuiltinLine(source, "New"));
- var requests: [2]Effect = undefined;
- var n: usize = 0;
- while (p.nextEffect()) |effect| switch (effect) {
- .new_file => if (n < requests.len) {
- requests[n] = effect;
- n += 1;
- },
- else => {},
+ // A pump against the empty host renders a frame and blocks on nothing.
+ try p.pump(.{});
+ try std.testing.expect(!p.quit);
+
+ // the absent child is SILENT: the bytes are dropped, and nothing appears
+ // on the pane's screen to suggest a program answered
+ const before = p.panes[0].?.vt.screens.active.cursor.y;
+ p.perform(.{ .write = .{ .pane = 0, .bytes = .from("ls\r") } });
+ try std.testing.expectEqual(before, p.panes[0].?.vt.screens.active.cursor.y);
+
+ // the clipboard round-trips through the in-process one
+ p.yank = try gpa.dupe(u8, "copied");
+ p.perform(.set_clipboard);
+ try std.testing.expectEqualStrings("copied", p.fallback.clipboard.items);
+
+ // ...and a save with no filesystem lands in the virtual one
+ const doc = try p.hxOpenFileContent("body\n");
+ var doc_id: u8 = 0;
+ for (p.panes, 0..) |slot, i| if (slot == doc) {
+ doc_id = @intCast(i);
};
- try std.testing.expectEqual(requests.len, n);
+ p.perform(.{ .save_file = .{ .pane = doc_id } });
+ try std.testing.expectEqualStrings("body\n", p.fallback.files.get(doc.file.?.path).?);
- p.active = 0;
- try std.testing.expect(p.openNewFile(requests[0].new_file.pane, requests[0].new_file.serial, "/tmp/pardes-test-new-1"));
- const first = p.active;
- p.active = 1; // change focus again before the second completion
- try std.testing.expect(p.openNewFile(requests[1].new_file.pane, requests[1].new_file.serial, "/tmp/pardes-test-new-2"));
- const second = p.active;
- try std.testing.expect(first != second);
- try std.testing.expectEqual(source_col, p.layoutFindTerm(first).?.col);
- try std.testing.expectEqual(source_col, p.layoutFindTerm(second).?.col);
- try std.testing.expect(!std.mem.eql(u8, p.panes[first].?.file.?.path, p.panes[second].?.file.?.path));
- while (p.nextEffect()) |_| {}
+ // a language backend nobody supplied answers nothing rather than hanging
+ p.perform(.{ .lsp = .{ .id = 7, .kind = .hover, .pane = doc_id, .offset = 0, .arg = .{} } });
+
+ p.perform(.quit);
+ try std.testing.expect(p.quit);
+}
+
+const RecordHost = struct {
+ gpa: std.mem.Allocator,
+ writes: std.ArrayListUnmanaged(u8) = .empty,
+ /// What this host would answer a clipboard read with, and whether it was
+ /// ever asked — a pull must reach exactly one host.
+ clipboard: []const u8 = "",
+ asked: usize = 0,
+ core: ?*Pardes = null,
- // A reused pane slot cannot answer an old request, and a malformed shell
- // answer cannot manufacture a nameless file.
- const old_serial = p.panes[source].?.serial;
- p.panes[source].?.serial +%= 1;
- try std.testing.expect(!p.openNewFile(@intCast(source), old_serial, "/tmp/pardes-test-stale"));
- try std.testing.expect(!p.openNewFile(@intCast(source), p.panes[source].?.serial, ""));
+ const vt: Host.VTable = .{ .push_pty_write = ptyWrite, .pull_read_clipboard = readClipboard };
- // Exhaust every remaining slot after a request was issued: completion
- // rejects it, which tells the shell to unlink the just-created candidate.
- const live_serial = p.panes[source].?.serial;
- for (0..MAX_PANES) |id| {
- if (p.panes[id] == null) _ = try p.newDocPane(id);
+ fn ptyWrite(ctx: ?*anyopaque, pane: u8, bytes: []const u8) void {
+ _ = pane;
+ const self: *RecordHost = @ptrCast(@alignCast(ctx.?));
+ self.writes.appendSlice(self.gpa, bytes) catch {};
}
- try std.testing.expect(!p.openNewFile(@intCast(source), live_serial, "/tmp/pardes-test-full"));
- try std.testing.expect(p.executeBuiltinLine(source, "New"));
- var emitted_when_full = false;
- while (p.nextEffect()) |effect| switch (effect) {
- .new_file => emitted_when_full = true,
- else => {},
+
+ fn readClipboard(ctx: ?*anyopaque) void {
+ const self: *RecordHost = @ptrCast(@alignCast(ctx.?));
+ self.asked += 1;
+ self.core.?.update(.{ .paste = self.clipboard });
+ }
+
+ fn host(self: *RecordHost) Host {
+ return .{ .ctx = self, .vtable = &vt };
+ }
+};
+
+test "a fan-out host reaches every wrapped host, each with its own state" {
+ const gpa = std.testing.allocator;
+ const p = try Pardes.init(gpa, .{ .tty_only = true, .cols = 40, .rows = 10 });
+ defer p.deinit();
+
+ var a: RecordHost = .{ .gpa = gpa };
+ defer a.writes.deinit(gpa);
+ var b: RecordHost = .{ .gpa = gpa };
+ defer b.writes.deinit(gpa);
+
+ const wrapped = [_]Host{ a.host(), b.host() };
+ var fan: Fanout = .init(&wrapped);
+ p.host = fan.host();
+ p.perform(.{ .write = .{ .pane = 0, .bytes = .from("echo hi\r") } });
+
+ try std.testing.expectEqualStrings("echo hi\r", a.writes.items);
+ try std.testing.expectEqualStrings("echo hi\r", b.writes.items);
+
+ // A PULL reaches ONE host, and the name is what says so. Fanned out, both
+ // would answer and the core would paste the clipboard twice for one Ctrl-V.
+ a.core = p;
+ b.core = p;
+ a.clipboard = "from-a";
+ b.clipboard = "from-b";
+ const doc = p.panes[p.active].?;
+ doc.mode = .normal;
+ p.perform(.read_clipboard);
+ try std.testing.expectEqual(@as(usize, 1), a.asked);
+ try std.testing.expectEqual(@as(usize, 0), b.asked);
+
+ // a method NO wrapped host implements still falls back per-method
+ p.perform(.{ .open_link = .from("https://example.invalid") });
+ try std.testing.expectEqualStrings("https://example.invalid", p.fallback.link.items);
+}
+
+test "a builtin that needs a pane reports capacity failure when every slot is full" {
+ const p = try Pardes.init(std.testing.allocator, .{ .shells = 3, .cols = 100, .rows = 30 });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
+ for (0..MAX_PANES) |id| if (p.panes[id] == null) {
+ _ = try p.newDocPane(id);
};
- try std.testing.expect(!emitted_when_full);
- // Builtins that need another pane surface capacity/allocation failures on
- // the asking pane instead of silently doing nothing.
const help = std.meta.stringToEnum(Builtin, "Help") orelse return error.MissingHelpBuiltin;
- p.runBuiltin(help, source, "", null);
- try std.testing.expect(std.mem.indexOf(u8, p.panes[source].?.msg[0..p.panes[source].?.msg_len], "help: NoPaneSlots") != null);
+ p.runBuiltin(help, 0, "", null);
+ try std.testing.expect(std.mem.indexOf(u8, p.panes[0].?.msg[0..p.panes[0].?.msg_len], "help: NoPaneSlots") != null);
}
test "Msg writes the transient row by hand, bare or with text, and input ends it" {
@@ -1701,10 +1827,12 @@ pub const builtin_rows: [std.enums.values(Builtin).len]Row = blk: {
// not a derivation — see it there for why each word is in or out. This is the
// check that a rename cannot silently rot it.
comptime {
- @setEvalBranchQuota(20000); // the tokenizer walks the string one branch per byte, stringToEnum builds a map per name, and both sit behind the decl walk that folds Builtin
+ @setEvalBranchQuota(20000); // one branch per string byte, behind the decl walk that folds Builtin
var it = std.mem.tokenizeScalar(u8, config.topbar_str, ' ');
- while (it.next()) |w| {
- if (std.meta.stringToEnum(Builtin, w) == null) @compileError("topbar word is not a builtin: " ++ w);
+ words: while (it.next()) |w| {
+ for (@typeInfo(Builtin).@"enum".fields) |f|
+ if (std.mem.eql(u8, f.name, w)) continue :words;
+ @compileError("topbar word is not a builtin: " ++ w);
}
}
@@ -2943,22 +3071,6 @@ pub const Event = union(enum) {
tick,
};
-/// The one thing the core PULLS from the host instead of being pushed or
-/// emitting an effect: is a pane's terminal still the prompt the host forked,
-/// or has a program (vim, a pager, an agent) taken its tty?
-///
-/// An effect cannot answer it — `execute` has to choose a destination inside
-/// the update that asked, and an effect is drained after. A pushed fact could,
-/// and did, but only by having every host probe every pane's processes on every
-/// frame to answer a question that is asked when a human middle-clicks a word.
-/// So the host leaves a way to be asked, and the core asks where it decides
-/// (see `Pardes.takesCommandLine`). `ctx` is the host's own pty table; the
-/// answer must not re-enter the core.
-pub const TtyQuery = struct {
- ctx: ?*anyopaque,
- taken: *const fn (ctx: ?*anyopaque, pane: usize) bool,
-};
-
/// IO the core wants done. Payloads are inline (fixed buffers): effects are
/// queued values with no lifetime ties back into the core.
pub const Effect = union(enum) {
@@ -2969,11 +3081,10 @@ pub const Effect = union(enum) {
/// write this pane's file content to its path; the shell reads both off
/// the core (content is unbounded, effects are fixed-size values)
save_file: struct { pane: u8 },
- /// Create an empty, uniquely-named temporary file. `pane` + `serial`
- /// identify the pane/column that issued New even if focus moves before the
- /// shell completes the IO. The shell calls openNewFile with the path and
- /// unlinks it itself when that completion rejects the request.
- new_file: struct { pane: u8, serial: u32 },
+ /// write plaintext to a path WITHOUT converting the pane (a terminal's
+ /// scrollback save): the bytes and path are stashed in core.save_text,
+ /// read off the core exactly like save_file reads a file pane.
+ save_text: struct { pane: u8 },
/// a serialized state dump is ready in core.dump_out; write it to the
/// path dump.outPath resolves (acme-style: another instance loads it
/// with -l, or the Restore builtin loads it into this one)
@@ -3155,9 +3266,14 @@ const Prompt = union(enum) {
none,
search: u16,
pipe: u16,
+ /// Save on a scratch buffer or a terminal: the tail is a path to write to.
+ save: u16,
};
pub const Pane = struct {
+ /// A pane's working directory. `.inherited` is a live `*Pane` link kept
+ /// valid by deferred teardown (see PaneAllocator) + reapPanes' fixup.
+ pub const Cwd = union(enum) { none, inherited: *Pane, owned: []const u8 };
vt: ghostty_vt.Terminal,
stream: ghostty_vt.TerminalStream,
/// The same allocator Pardes holds. A pane already owns heap (its content,
@@ -3263,10 +3379,11 @@ pub const Pane = struct {
ed_undo_len: usize = 0,
ed_redo: [term_pane.history_max]term_pane.Snapshot = undefined,
ed_redo_len: usize = 0,
- /// live working directory, shell-reported (setCwd); shown in the tag and
- /// the base for look-resolution of relative paths.
- cwd: [1024]u8 = undefined,
- cwd_len: u16 = 0,
+ /// Working directory: shell-reported bytes (.owned, in cwd_buf), a live
+ /// link to the pane it was opened from (.inherited), or unknown (.none).
+ /// The inherited pointer is kept valid by deferred pane teardown + fixup.
+ cwd: Cwd = .none,
+ cwd_buf: [1024]u8 = undefined,
/// modal cursor, at ABSOLUTE body rows of the pane's SURFACE (file lines,
/// or the terminal's shell rows with its edit buffer standing in). Tracks
/// the shell cursor until pinned by a click or a key.
@@ -3334,7 +3451,7 @@ pub const Pane = struct {
fn promptAt(p: *const Pane) ?u16 {
return switch (p.prompt) {
.none => null,
- .search, .pipe => |at| at,
+ .search, .pipe, .save => |at| at,
};
}
@@ -3352,6 +3469,13 @@ pub const Pane = struct {
};
}
+ fn hasSavePrompt(p: *const Pane) bool {
+ return switch (p.prompt) {
+ .save => true,
+ else => false,
+ };
+ }
+
fn appendTag(p: *Pane, text: []const u8) bool {
if (text.len > p.tag_tail.len - p.tag_tail_len) return false;
@memcpy(p.tag_tail[p.tag_tail_len..][0..text.len], text);
@@ -3374,7 +3498,18 @@ pub const Pane = struct {
}
pub fn cwdSlice(p: *const Pane) []const u8 {
- return p.cwd[0..p.cwd_len];
+ return switch (p.cwd) {
+ .none => "",
+ .owned => |dir| dir,
+ .inherited => |src| src.cwdSlice(),
+ };
+ }
+
+ /// Shell-reported directory: own the bytes in cwd_buf.
+ pub fn setOwnedCwd(pane: *Pane, dir: []const u8) void {
+ const n = @min(dir.len, pane.cwd_buf.len);
+ @memcpy(pane.cwd_buf[0..n], dir[0..n]);
+ pane.cwd = .{ .owned = pane.cwd_buf[0..n] };
}
pub fn isTerminal(pane: *const Pane) bool {
@@ -3382,6 +3517,18 @@ pub const Pane = struct {
return pane.file == null and pane.image == null and no_pdf;
}
+ /// The one coloring choice keyed on what a pane IS, so the highlight
+ /// producer (refreshHighlights) and the render pass agree on the algorithm.
+ pub const ColorAlgo = enum { none, tty, source, diff };
+ pub fn colorAlgo(pane: *const Pane) ColorAlgo {
+ if (pane.isTerminal()) return .tty;
+ if (pane.file) |f| {
+ if (std.mem.endsWith(u8, f.path, ".diff") or std.mem.endsWith(u8, f.path, ".patch")) return .diff;
+ return .source;
+ }
+ return .none;
+ }
+
pub fn pdfPath(pane: *const Pane) ?[]const u8 {
if (comptime pdf_enabled) if (pane.pdf) |pv| return pv.path;
return null;
@@ -4689,6 +4836,9 @@ pub const Options = struct {
image_allocator: ?std.mem.Allocator = null,
pdf_allocator: ?std.mem.Allocator = null,
tree_sitter_allocator: ?std.mem.Allocator = null,
+ /// Where each frame's Surface text is built. Hosts pass a purpose-built
+ /// stack-fallback arena; null means the general allocator.
+ frame_allocator: ?std.mem.Allocator = null,
/// Initial grid. Shell contract: for LIVE sessions leave these at the
/// defaults and deliver the real size as the first resize EVENT — the core
/// defers an integrated shell's greeting until after a resize AND its OSC
@@ -4742,6 +4892,32 @@ pub const Haptic = enum { none, exec, look };
/// the field, so no other shell carries it.
const HapticSlot = if (platform == .macos) Haptic else void;
+/// Deferred pane teardown. A dropped pane's memory outlives the frame it died
+/// in: it is doomed here and actually torn down one full frame later, so any
+/// `*Pane` captured that frame — an effect, another pane's inherited cwd —
+/// stays valid long enough for the per-frame fixup pass to repair it. `fresh`
+/// holds this frame's drops, `stale` the previous frame's, freed next reap.
+pub const PaneAllocator = struct {
+ fresh: [2 * MAX_PANES]?*Pane = @splat(null),
+ stale: [2 * MAX_PANES]?*Pane = @splat(null),
+
+ fn doom(a: *PaneAllocator, pane: *Pane) void {
+ for (&a.fresh) |*slot| if (slot.* == null) {
+ slot.* = pane;
+ return;
+ };
+ // One update runs one builtin, and the widest drop is a whole column;
+ // 2*MAX_PANES cannot fill in a single frame.
+ unreachable;
+ }
+
+ fn isDoomed(a: *const PaneAllocator, pane: *const Pane) bool {
+ for (a.fresh) |s| if (s == pane) return true;
+ for (a.stale) |s| if (s == pane) return true;
+ return false;
+ }
+};
+
pub const Pardes = struct {
gpa: std.mem.Allocator,
image_gpa: std.mem.Allocator,
@@ -4754,6 +4930,8 @@ pub const Pardes = struct {
resize_count: usize = 0,
panes: [MAX_PANES]?*Pane = @splat(null),
+ /// Deferred teardown of dropped panes (see PaneAllocator).
+ pane_alloc: PaneAllocator = .{},
// layout: columns own x by weight; panes own y by vweight within a column.
ncol: usize = 0,
/// Fixed-point horizontal proportions. Integer sums make splitting W
@@ -4879,11 +5057,6 @@ pub const Pardes = struct {
/// terminal, GPU textures in SDL). Image panes dynamically fall back to
/// the PETSCII matcher without it.
native_images: bool = false,
- /// How the core asks the host the one question about a pane it cannot
- /// answer itself — see `takesCommandLine`, the only caller. Installed once
- /// by the native hosts (and again after a dump replay builds a second
- /// core); left null by the web shell, which has no processes.
- tty_query: ?TtyQuery = null,
quit: bool = false,
/// The Look or Exec that has happened and not yet been felt, taken by the
/// shell once per pump (takeHaptic). A pulse, not a queue: five Execs
@@ -4982,6 +5155,19 @@ pub const Pardes = struct {
effects_head: usize = 0,
effects_len: usize = 0,
+ /// WHO SERVES THIS CORE. Every method optional; a null one is answered by
+ /// `fallback` below, so a `Host{}` is a complete in-process pardes.
+ host: Host = .{},
+ /// The in-program answers behind every unimplemented host method. Per
+ /// instance, so several cores behind one fan-out host stay independent.
+ fallback: Fallback,
+ /// Input the loop has not consumed yet. Single-threaded: a host's worker
+ /// threads keep their own thread-safe inbox and post from the loop thread,
+ /// which is what keeps this ring lock-free.
+ in_q: [64]Event = undefined,
+ in_head: usize = 0,
+ in_len: usize = 0,
+
/// helix's DEFAULT register (gpa-owned): what `y`/`d`/`c` write and
/// `p`/`P`/`R` read. Never the system clipboard — `SPC y`/`SPC p` are the
/// two commands that cross that line.
@@ -4992,6 +5178,9 @@ pub const Pardes = struct {
clip_pending: ?ClipRequest = null,
/// the last serialized dump (gpa-owned), read by the write_dump effect
dump_out: ?[]u8 = null,
+ /// A terminal scrollback save awaiting the host: bytes + path, gpa-owned,
+ /// read by the save_text effect and cleared once written. At most one.
+ save_text: ?struct { content: []const u8, path: []u8 } = null,
/// where the shell wrote the last dump (shell reports back after
/// write_dump); shown in the topbar as `Restore <path>`
last_dump: ?[]const u8 = null,
@@ -5003,6 +5192,9 @@ pub const Pardes = struct {
surface: Surface = .{},
/// per-update scratch (paneCursorLines, selection text); reset each update
scratch: std.heap.ArenaAllocator,
+ /// The arena each frame's Surface text is built in, reset by `pump`. Hosts
+ /// that still own their loop pass their own arena to `render` instead.
+ frame_arena: std.heap.ArenaAllocator,
/// the terminal motion surface, memoized against the pane it was built
/// for — see term_pane.RowsCache for the lifetime rule
shell_rows: term_pane.RowsCache = .{},
@@ -5021,6 +5213,8 @@ pub const Pardes = struct {
.screen_w = opts.cols,
.screen_h = opts.rows,
.scratch = .init(gpa),
+ .frame_arena = .init(opts.frame_allocator orelse gpa),
+ .fallback = .{ .gpa = gpa },
};
errdefer p.deinit();
if (opts.file) |path| {
@@ -5078,18 +5272,32 @@ pub const Pardes = struct {
pub fn deinit(p: *Pardes) void {
p.cancelLookHover();
for (&p.panes) |*slot| if (slot.*) |pane| {
- p.deinitPane(pane);
+ p.teardownPane(pane);
+ slot.* = null;
+ };
+ for (&p.pane_alloc.stale) |*slot| if (slot.*) |pane| {
+ p.teardownPane(pane);
+ slot.* = null;
+ };
+ for (&p.pane_alloc.fresh) |*slot| if (slot.*) |pane| {
+ p.teardownPane(pane);
slot.* = null;
};
const gpa = p.gpa;
if (p.yank) |y| gpa.free(y);
if (p.dump_out) |d| gpa.free(d);
+ if (p.save_text) |s| {
+ gpa.free(s.content);
+ gpa.free(s.path);
+ }
+ p.fallback.deinit();
if (p.last_dump) |d| gpa.free(d);
if (p.custom_theme) |theme_value| std.zon.parse.free(gpa, theme_value);
if (p.chord_arg) |a| gpa.free(a);
if (p.pipe_wait) |*wait| wait.deinit(gpa);
p.shell_rows.reset(gpa);
p.scratch.deinit();
+ p.frame_arena.deinit();
gpa.free(p.surface.cells);
if (p.presented_cells.len > 0) gpa.free(p.presented_cells);
if (p.panel_cell_diffs.len > 0) gpa.free(p.panel_cell_diffs);
@@ -5120,7 +5328,24 @@ pub const Pardes = struct {
return config.topbar_str;
}
+ /// Drop a pane: its slot is freed for reuse now, but the allocation is
+ /// doomed and actually torn down a frame later (reapPanes), so pointers to
+ /// it survive the frame. Callers still null `panes[id]` themselves.
pub fn deinitPane(p: *Pardes, pane: *Pane) void {
+ // Logical close, while the pane is still installed: stop the file/PDF
+ // watch keyed to this slot and drop any hover it owns. The heap
+ // teardown is deferred (reapPanes) so pointers to it survive the frame.
+ const watched = (if (pane.file) |f| f.output == null else false) or hasPdf(pane);
+ if (watched) for (p.panes, 0..) |slot, id| {
+ if (slot == pane) p.emit(.{ .watch = .{ .pane = @intCast(id), .on = false } });
+ };
+ if (p.lookHoverPane()) |h| if (h < p.panes.len and p.panes[h] == pane) p.cancelLookHover();
+ p.pane_alloc.doom(pane);
+ }
+
+ /// The real teardown, run by reapPanes once the pane has been doomed for a
+ /// full frame (or at deinit). Frees every heap payload the pane owns.
+ fn teardownPane(p: *Pardes, pane: *Pane) void {
if (p.lookHoverPane()) |hovered| {
if (hovered < p.panes.len and p.panes[hovered] == pane)
p.cancelLookHover();
@@ -5140,6 +5365,32 @@ pub const Pardes = struct {
p.gpa.destroy(pane);
}
+ /// Once a frame: repair live panes' pointers to doomed panes, then free the
+ /// panes doomed a full frame ago. Fixup runs first so no pointer outlives
+ /// the memory. `stale` (last frame's dead) is freed; `fresh` becomes stale.
+ fn reapPanes(p: *Pardes) void {
+ for (p.panes) |slot| if (slot) |pane| p.fixupPaneRefs(pane);
+ for (&p.pane_alloc.stale) |*slot| if (slot.*) |pane| {
+ p.teardownPane(pane);
+ slot.* = null;
+ };
+ p.pane_alloc.stale = p.pane_alloc.fresh;
+ p.pane_alloc.fresh = @splat(null);
+ }
+
+ /// Visit each Pane field that holds a pane pointer; when it names a doomed
+ /// pane, snapshot that pane's directory into our own bytes so the link can
+ /// die with it. One field carries a pointer today (the inherited cwd); the
+ /// comptime walk keeps that honest as fields come and go.
+ fn fixupPaneRefs(p: *Pardes, pane: *Pane) void {
+ inline for (@typeInfo(Pane).@"struct".fields) |f| {
+ if (f.type == Pane.Cwd) switch (@field(pane, f.name)) {
+ .inherited => |src| if (p.pane_alloc.isDoomed(src)) pane.setOwnedCwd(paneDir(src)),
+ else => {},
+ };
+ }
+ }
+
/// Put a fully constructed pane in a free slot and give it the monotonic
/// identity every slot-reuse guard relies on. Pane kinds construct their
/// own payloads; this registration rule remains a core invariant.
@@ -5181,6 +5432,38 @@ pub const Pardes = struct {
return pane;
}
+ /// An empty output buffer opened FROM `from_id`: no file behind it, its cwd
+ /// a live link to the opener so Save can prefill that directory. New and
+ /// Newcol place it (below, or in a column). Installed in slot `free`.
+ fn newScratch(p: *Pardes, from_id: usize, free: usize) !*Pane {
+ const src = p.panes[from_id] orelse return error.MissingPane;
+ const content = try p.gpa.dupe(u8, "");
+ errdefer p.gpa.free(content);
+ const np = try output_pane.open(p, free, paneDir(src), .{ .cmd = .New }, "", content);
+ np.cwd = .{ .inherited = src };
+ np.cur_pinned = true;
+ return np;
+ }
+
+ /// New: a scratch below the calling pane, in its column.
+ pub fn newScratchBelow(p: *Pardes, from_id: usize) void {
+ const free = p.freeSlot() orelse return;
+ const sf = p.layoutFindTerm(from_id) orelse return;
+ const np = p.newScratch(from_id, free) catch return;
+ p.layoutInsert(sf.col, sf.idx + 1, free);
+ p.splitBelow(from_id, np);
+ p.active = free;
+ }
+
+ /// Newcol: a scratch in a fresh column beside the calling pane.
+ pub fn newScratchColumn(p: *Pardes, from_id: usize) void {
+ const free = p.freeSlot() orelse return;
+ if (!p.layoutCanSplitColumn(from_id)) return;
+ _ = p.newScratch(from_id, free) catch return;
+ std.debug.assert(p.layoutSplitColumn(from_id, free, false));
+ p.active = free;
+ }
+
pub fn freeSlot(p: *Pardes) ?usize {
return for (p.panes, 0..) |slot, i| {
if (slot == null) break i;
@@ -5244,11 +5527,14 @@ pub const Pardes = struct {
/// changes it observes, e.g. via /proc/<pid>/cwd before each frame).
pub fn setCwd(p: *Pardes, id: usize, cwd: []const u8) void {
const pane = p.panes[id] orelse return;
- const n = @min(cwd.len, pane.cwd.len);
- if (pane.cwd_len == n and std.mem.eql(u8, pane.cwd[0..n], cwd[0..n])) return;
+ const n = @min(cwd.len, pane.cwd_buf.len);
+ const cur = switch (pane.cwd) {
+ .owned => |dir| dir,
+ else => "",
+ };
+ if (cur.len == n and std.mem.eql(u8, cur, cwd[0..n])) return;
if (p.lookHoverPane() == id) p.cancelLookHover();
- @memcpy(pane.cwd[0..n], cwd[0..n]);
- pane.cwd_len = @intCast(n);
+ pane.setOwnedCwd(cwd[0..n]);
}
/// Can a command line be typed into this pane RIGHT NOW: a terminal whose
@@ -5273,44 +5559,7 @@ pub const Pardes = struct {
fn takesCommandLine(p: *const Pardes, id: usize) bool {
const pane = p.panes[id] orelse return false;
if (!pane.isTerminal()) return false;
- const q = p.tty_query orelse return true;
- return !q.taken(q.ctx, id);
- }
-
- /// Complete a `new_file` effect without doing IO in the core. The shell
- /// has already created `path` as an empty file; we model those known empty
- /// bytes directly, insert immediately below the still-live calling pane in
- /// ITS column (never whichever column became active), focus it, and start
- /// the same watch every ordinary file pane has. False leaves ownership
- /// with the shell, which closes and unlinks the unadopted file.
- pub fn openNewFile(p: *Pardes, source: u8, serial: u32, path: []const u8) bool {
- if (path.len == 0 or source >= MAX_PANES) return false;
- const src = p.panes[source] orelse return false;
- if (src.serial != serial) return false;
- const sf = p.layoutFindTerm(source) orelse return false;
- const free = p.freeSlot() orelse return false;
-
- const path_copy = p.gpa.dupe(u8, path) catch return false;
- const content = p.gpa.dupe(u8, "") catch {
- p.gpa.free(path_copy);
- return false;
- };
- const pane = p.newDocPane(free) catch {
- p.gpa.free(content);
- p.gpa.free(path_copy);
- return false;
- };
- pane.file = .{ .path = path_copy, .content = content };
- pane.cur_pinned = true;
-
- // sf was captured from SOURCE, not active. Nothing above this point
- // mutates layout, so it is still the exact calling column/index.
- p.layoutInsert(sf.col, sf.idx + 1, free);
- p.splitBelow(source, pane);
- p.active = free;
- p.emit(.{ .watch = .{ .pane = @intCast(free), .on = true } });
- p.sync();
- return true;
+ return !p.hostTtyTaken(id);
}
/// What a shell should exec for the next terminal — a bare name to be
@@ -5505,8 +5754,8 @@ pub const Pardes = struct {
}
/// Post the transient message on `id`'s last row. Called by a SHELL once
- /// the IO it narrates has actually happened, exactly as openNewFile above
- /// completes a `new_file` effect: the core neither writes files nor owns a
+ /// the IO it narrates has actually happened, exactly as the shell completes
+ /// a `save_file` effect: the core neither writes files nor owns a
/// clock, so both the outcome and the wall time in `text` come from there
/// (message.zig spells it, once, for both native shells).
///
@@ -5586,6 +5835,149 @@ pub const Pardes = struct {
return e;
}
+ /// Queue input for the next `pump`. Single-threaded, and a VALUE queue: an
+ /// event that carries a borrowed slice cannot survive the trip, so this
+ /// asserts rather than documents it. Hand those to `update` directly inside
+ /// the host's borrow window instead — which is also what keeps the pty read
+ /// path copy-free.
+ pub fn postEvent(p: *Pardes, ev: Event) void {
+ switch (ev) {
+ .key => |k| std.debug.assert(k.text.len == 0),
+ .output, .paste, .lsp_resp, .pipe_resp, .file_changed, .command => unreachable,
+ else => {},
+ }
+ if (p.in_len == p.in_q.len) return;
+ p.in_q[(p.in_head + p.in_len) % p.in_q.len] = ev;
+ p.in_len += 1;
+ }
+
+ fn nextQueued(p: *Pardes) ?Event {
+ if (p.in_len == 0) {
+ p.in_head = 0;
+ return null;
+ }
+ const ev = p.in_q[p.in_head];
+ p.in_head = (p.in_head + 1) % p.in_q.len;
+ p.in_len -= 1;
+ return ev;
+ }
+
+ /// Has a program taken this pane's tty? A host that cannot tell says no,
+ /// which is how pardes behaved before the probe existed.
+ fn hostTtyTaken(p: *const Pardes, id: usize) bool {
+ const f = p.host.vtable.pull_tty_taken orelse return false;
+ return f(p.host.ctx, @intCast(id));
+ }
+
+ fn hostWriteFile(p: *Pardes, pane: u8, path: []const u8, bytes: []const u8) void {
+ if (p.host.vtable.push_write_file) |f| return f(p.host.ctx, pane, path, bytes);
+ p.fallback.writeFile(path, bytes);
+ }
+
+ /// The path a watch is about: a real file's, or a PDF's.
+ fn watchPath(p: *const Pardes, id: u8) ?[]const u8 {
+ const pane = p.panes[id] orelse return null;
+ if (pane.file) |f| return if (f.output == null) f.path else null;
+ return pane.pdfPath();
+ }
+
+ /// Perform one effect through the host, falling back per METHOD (not per
+ /// host) to the in-process implementation. This is the switch that used to
+ /// be copied into all four shells.
+ pub fn perform(p: *Pardes, e: Effect) void {
+ const v = p.host.vtable;
+ switch (e) {
+ .spawn => |s| if (v.push_spawn) |f| f(p.host.ctx, s.pane, s.cwd.slice()) else {
+ p.fallback.spawned[s.pane] = true;
+ },
+ // A pane with no child is silent: nothing invents output on its
+ // screen, and the bytes are dropped rather than transcribed.
+ .write => |w| if (v.push_pty_write) |f| f(p.host.ctx, w.pane, w.bytes.slice()),
+ .resize_pty => |r| if (v.push_pty_resize) |f| f(p.host.ctx, r.pane, r.cols, r.rows),
+ .open_link => |u| if (v.push_open_link) |f|
+ f(p.host.ctx, u.slice())
+ else
+ p.fallback.setLink(u.slice()),
+ .save_file => |sf| {
+ const pane = p.panes[sf.pane] orelse return;
+ const f = pane.file orelse return;
+ p.hostWriteFile(sf.pane, f.path, f.content);
+ },
+ .save_text => |st| {
+ const s = p.save_text orelse return;
+ p.hostWriteFile(st.pane, s.path, s.content);
+ p.clearSaveText();
+ },
+ .write_dump => {
+ const out = p.dump_out orelse return;
+ if (v.push_write_dump) |f| {
+ f(p.host.ctx, out);
+ } else {
+ // A real host reports where it landed, which is what puts
+ // `Restore <path>` in the topbar; the virtual one owes the
+ // same, or the bytes it holds are unreachable.
+ p.fallback.writeFile(fallback_dump_path, out);
+ p.setLastDump(fallback_dump_path);
+ }
+ },
+ .set_clipboard => {
+ const text = p.yank orelse "";
+ if (v.push_set_clipboard) |f| f(p.host.ctx, text) else p.fallback.setClipboard(text);
+ },
+ // No desktop to ask: answer from the in-process clipboard at once,
+ // which is the same shape as a host answering later.
+ .read_clipboard => if (v.pull_read_clipboard) |f|
+ f(p.host.ctx)
+ else
+ p.update(.{ .paste = p.fallback.clipboard.items }),
+ .lsp => |q| if (v.pull_lsp) |f|
+ f(p.host.ctx, .{ .id = q.id, .kind = q.kind, .pane = q.pane, .offset = q.offset, .arg = q.arg.slice() })
+ else
+ p.update(.{ .lsp_resp = .{ .id = q.id, .rows = "" } }),
+ .pipe => |q| if (v.pull_pipe) |f|
+ f(p.host.ctx, q.id)
+ else
+ p.update(.{ .pipe_resp = .{ .id = q.id, .success = false, .outputs = &.{} } }),
+ .watch => |w| if (v.push_watch_file) |f|
+ f(p.host.ctx, w.pane, p.watchPath(w.pane) orelse "", w.on)
+ else {
+ p.fallback.watched[w.pane] = w.on;
+ },
+ .theme_file => |t| if (v.push_watch_theme) |f| f(p.host.ctx, t.generation, t.on),
+ .dump_themes => |d| if (v.push_dump_themes) |f| f(p.host.ctx, d.pane),
+ // the loop's own condition; a host tears down after its own loop
+ .quit => p.quit = true,
+ }
+ }
+
+ /// ONE ITERATION OF THE LOOP, and the reason the core owns it: the ORDER
+ /// here — wait, apply input, perform effects, poll, render, present — was
+ /// copied into four shells and drifted in each. A host supplies the parts
+ /// only it can (blocking, pixels, processes) and nothing else.
+ ///
+ /// It is one PUMP and never a `while`: no host gives up its outer loop.
+ /// AppKit owns NSApplication's run loop, the browser owns the frame
+ /// callback, and both Linux hosts keep a thin one so Restore can swap the
+ /// whole core between frames.
+ pub fn pump(p: *Pardes, h: Host) !void {
+ p.host = h;
+ const v = h.vtable;
+ if (v.pull_wait_input) |f| f(h.ctx, if (p.animationActive()) animation.frame_ms else 0);
+ while (p.nextQueued()) |ev| p.update(ev);
+ while (p.nextEffect()) |e| p.perform(e);
+ // A quitting frame has already freed what it would draw.
+ if (p.quit) return;
+ if (v.push_poll_frame) |f| f(h.ctx);
+ _ = p.frame_arena.reset(.retain_capacity);
+ const surface = try p.render(p.frame_arena.allocator());
+ if (v.push_present) |f| f(h.ctx, surface);
+ if (v.push_post_present) |f| f(h.ctx);
+ // Animation TIME is not spent here. `wait_input` was told how long it
+ // may sleep; a display clock wakes faster than that on input, so only
+ // the host knows when a real frame interval has passed. Each spends it
+ // by handing back one `.tick`.
+ }
+
pub fn update(p: *Pardes, ev: Event) void {
// Free a motion surface that went bad during the LAST update, before
// anything in this one can ask for it. Nothing frees it mid-update:
@@ -5785,6 +6177,26 @@ pub const Pardes = struct {
p.emit(.read_clipboard);
}
+ /// Type text at a pane's program, the way a terminal emulator pastes:
+ /// bracketed when the app set mode 2004 (readline/vim/helix strip the
+ /// markers and refuse to run what arrives), else with `\n` turned to `\r`,
+ /// because a raw newline in an unbracketed paste IS the Enter key and a
+ /// multi-line paste would run every line but the last.
+ pub fn typeToTty(p: *Pardes, id: usize, pane: *const Pane, text: []const u8) void {
+ if (text.len == 0) return;
+ if (pane.vt.modes.get(.bracketed_paste)) {
+ p.emitWrite(id, "\x1b[200~");
+ p.emitWrite(id, text);
+ p.emitWrite(id, "\x1b[201~");
+ return;
+ }
+ const cp = p.scratch.allocator().dupe(u8, text) catch return;
+ for (cp) |*ch| {
+ if (ch.* == '\n') ch.* = '\r';
+ }
+ p.emitWrite(id, cp);
+ }
+
/// The shell answered with system-clipboard text — or the desktop pasted
/// into us unasked. Either way the bytes are pasted WITHOUT going through
/// the register: helix's clipboard commands and the default register are
@@ -5798,6 +6210,11 @@ pub const Pardes = struct {
const pane = p.panes[id] orelse return;
if (req) |r| if (pane.serial != r.serial) return;
p.active = id;
+ // A pane in tty mode has no editable buffer to paste INTO — the pty
+ // owns its screen. Type the bytes at the program instead, which is
+ // also what makes a desktop paste (Ctrl-Shift-V, middle click, the
+ // window manager's own) reach a shell at all.
+ if (pane.isTerminal() and pane.mode == .tty) return p.typeToTty(id, pane, bytes);
switch (if (req) |r| r.mode else .after) {
.after => p.pasteText(pane, bytes, false),
.before => p.pasteText(pane, bytes, true),
@@ -6645,6 +7062,15 @@ pub const Pardes = struct {
} else term_pane.enterTty(p, p.active);
return;
}
+ // A shell prompt is a pane you can leave: plain Esc there is Shift-Esc.
+ if (pane.isTerminal() and pane.mode == .tty and hit(key, config.escape) and p.takesCommandLine(p.active))
+ return p.runBuiltin(.Last, p.active, "", null);
+ if (pane.isTerminal() and pane.mode == .tty) {
+ // Clipboard first: `hit` ignores a shift no binding asked for, so
+ // the plain Ctrl-V below would otherwise swallow Ctrl-Shift-V.
+ if (hit(key, config.tty_paste_clipboard)) return p.clipRequest(p.active, .after);
+ if (hit(key, config.tty_paste)) return p.typeToTty(p.active, pane, p.yank orelse return);
+ }
// `|` owns the same visible one-line tag input as search, but Enter
// snapshots an asynchronous shell filter. Escape is a pure cancel:
// restore the old tail and never emit a request.
@@ -6657,6 +7083,19 @@ pub const Pardes = struct {
pane.pending = 0;
return;
}
+ // a save input in flight (scratch or terminal): Enter writes the path,
+ // Esc abandons; both drop the prompt text and return to the body.
+ if (pane.hasSavePrompt() and (hit(key, config.search_submit) or hit(key, config.escape))) {
+ const prompt_at = pane.promptAt().?;
+ if (hit(key, config.search_submit))
+ p.submitSave(p.active)
+ else
+ pane.tag_tail_len = @min(prompt_at, pane.tag_tail_len);
+ exitTagEdit(pane);
+ pane.mode = .normal;
+ pane.pending = 0;
+ return;
+ }
// a search input in flight (`/` or Find): Enter searches, Esc abandons;
// both restore the tag tail and hand focus back to the body.
if (pane.hasSearchPrompt() and (hit(key, config.search_submit) or hit(key, config.escape))) {
@@ -8366,6 +8805,12 @@ pub const Pardes = struct {
const SearchStart = enum { top, cursor };
fn paneDir(pane: *const Pane) []const u8 {
+ // an inherited cwd is a live link that outranks a scratch buffer's own
+ // synthetic path: follow it to the pane it was opened from.
+ switch (pane.cwd) {
+ .inherited => |src| return paneDir(src),
+ else => {},
+ }
if (pane.file) |f| return std.fs.path.dirname(f.path) orelse "/";
if (comptime pdf_enabled) if (pane.pdf) |pv|
return std.fs.path.dirname(pv.path) orelse "/";
@@ -8390,6 +8835,89 @@ pub const Pardes = struct {
pane.tag_col = @intCast((p.tagPrefix(pane) catch return).len + pane.tag_tail_len);
}
+ /// Save on a scratch buffer or a terminal arms a PATH input in the tag,
+ /// prefilled with the pane's directory (an inherited scratch follows the
+ /// pane it was opened from). submitSave writes it.
+ pub fn startSavePrompt(p: *Pardes, pane: *Pane) void {
+ p.seedTail(pane);
+ if (!pane.tag_init) return;
+ const prompt_at: u16 = @intCast(pane.tag_tail_len);
+ if (!pane.appendTag(config.save_marker)) return;
+ const dir = paneDir(pane);
+ _ = pane.appendTag(dir);
+ if (dir.len == 0 or dir[dir.len - 1] != '/') _ = pane.appendTag("/");
+ pane.prompt = .{ .save = prompt_at };
+ pane.tag_edit = true;
+ pane.tag_sel = false;
+ pane.mode = .insert;
+ pane.pending = 0;
+ pane.tag_col = @intCast((p.tagPrefix(pane) catch return).len + pane.tag_tail_len);
+ }
+
+ /// Enter on a save input: the path is everything past the marker.
+ fn submitSave(p: *Pardes, id: usize) void {
+ const pane = p.panes[id] orelse return;
+ const at = switch (pane.prompt) {
+ .save => |a| a,
+ else => return,
+ };
+ const armed = pane.tag_tail[at..pane.tag_tail_len];
+ pane.tag_tail_len = at; // drop the prompt back to the seeded tail
+ if (!std.mem.startsWith(u8, armed, config.save_marker)) return;
+ const path = std.mem.trim(u8, armed[config.save_marker.len..], " \t\r\n");
+ if (path.len == 0) return;
+ p.performSave(id, path);
+ }
+
+ /// Commit a prompted path. A scratch buffer's own bytes go there and it
+ /// BECOMES an ordinary file pane; a terminal's plaintext scrollback goes
+ /// there and it stays a terminal.
+ fn performSave(p: *Pardes, id: usize, path: []const u8) void {
+ const pane = p.panes[id] orelse return;
+ if (pane.file) |*f| {
+ const owned = p.gpa.dupe(u8, path) catch return;
+ p.gpa.free(f.path);
+ f.path = owned;
+ f.output = null; // an ordinary file pane from here on
+ pane.cwd = .none; // its directory is now its own path's dirname
+ f.saved_revision = f.revision;
+ pane.tag_init = false; // re-derive the tag as a plain file
+ pane.tag_tail_len = 0;
+ p.emit(.{ .save_file = .{ .pane = @intCast(id) } });
+ p.emit(.{ .watch = .{ .pane = @intCast(id), .on = true } });
+ return;
+ }
+ p.saveScrollback(id, path);
+ }
+
+ /// A terminal's plaintext scrollback to `path`, leaving the pane a terminal.
+ /// The core cannot do IO, so it stashes the bytes and asks the host to
+ /// write them (save_text) the same way save_file hands off a file pane.
+ fn saveScrollback(p: *Pardes, id: usize, path: []const u8) void {
+ const pane = p.panes[id] orelse return;
+ if (!pane.isTerminal()) return;
+ const content = pane.vt.screens.active.dumpStringAlloc(p.gpa, .{ .screen = .{} }) catch return;
+ const owned = p.gpa.dupe(u8, path) catch {
+ p.gpa.free(content);
+ return;
+ };
+ if (p.save_text) |old| {
+ p.gpa.free(old.content);
+ p.gpa.free(old.path);
+ }
+ p.save_text = .{ .content = content, .path = owned };
+ p.emit(.{ .save_text = .{ .pane = @intCast(id) } });
+ }
+
+ /// The host has consumed the pending scrollback save: free and clear it.
+ pub fn clearSaveText(p: *Pardes) void {
+ if (p.save_text) |s| {
+ p.gpa.free(s.content);
+ p.gpa.free(s.path);
+ }
+ p.save_text = null;
+ }
+
/// Enter on an armed input: the pattern is everything past the marker's
/// `/` (so a pattern may itself contain slashes), and the marker names the
/// search — " Find /" walks the filesystem for NAMES, " Grep /" for
@@ -11466,17 +11994,7 @@ pub const Pardes = struct {
p.emitWrite(s.id, &[_]u8{ 0x1b, '[', 'M', 32, cb, rb, 0x1b, '[', 'M', 35, cb, rb });
}
}
- if (m.get(.bracketed_paste)) {
- p.emitWrite(s.id, "\x1b[200~");
- p.emitWrite(s.id, y);
- p.emitWrite(s.id, "\x1b[201~");
- } else {
- const cp = p.scratch.allocator().dupe(u8, y) catch return;
- for (cp) |*c| {
- if (c.* == '\n') c.* = '\r';
- }
- p.emitWrite(s.id, cp);
- }
+ p.typeToTty(s.id, pane, y);
return;
}
if (!s.chorded) {
@@ -11568,6 +12086,40 @@ pub const Pardes = struct {
}
}
+ /// Newtty: a shell in the caller's directory, raw from the first frame,
+ /// stacked below the caller like Alt-n's new shell.
+ pub fn spawnTty(p: *Pardes, from: usize) void {
+ const src = p.panes[from] orelse return;
+ const free = p.freeSlot() orelse return;
+ const nt = p.newShell(free, paneDir(src)) catch return;
+ nt.greet = true;
+ nt.mode = .tty;
+ const parent = p.splitParent(from);
+ const f = p.layoutFindTerm(parent).?;
+ p.layoutInsert(f.col, f.idx + 1, free);
+ p.splitBelow(parent, nt);
+ p.active = free;
+ }
+
+ /// Joincol: fold the active pane's column into the one on its right,
+ /// carrying its panes and width across. Inert without a right neighbour.
+ pub fn joinCol(p: *Pardes) void {
+ const f = p.layoutFindTerm(p.active) orelse return;
+ const c = f.col;
+ if (c + 1 >= p.ncol) return;
+ const dst = c + 1;
+ p.col_weight[dst] +|= p.col_weight[c];
+ for (0..p.col_n[c]) |k| p.col_terms[dst][p.col_n[dst] + k] = p.col_terms[c][k];
+ p.col_n[dst] += p.col_n[c];
+ var j = c;
+ while (j + 1 < p.ncol) : (j += 1) {
+ p.col_terms[j] = p.col_terms[j + 1];
+ p.col_n[j] = p.col_n[j + 1];
+ p.col_weight[j] = p.col_weight[j + 1];
+ }
+ p.ncol -= 1;
+ }
+
/// Whether `source_id` can donate half its width to a new column. This is
/// public so callers that must create a pane first can reject before that
/// creation emits any native-side work.
@@ -12274,6 +12826,15 @@ pub const Pardes = struct {
/// left, shells right). Only the calling/source column donates half its
/// width; every other column keeps its boundary. A full column bar, or a
/// result list whose source died, stacks into the leftmost.
+ /// A new file opens a column only when the split leaves both sides wide
+ /// enough to read; otherwise it stacks as a pane. Halving is exact, so the
+ /// narrower side is floor(width/2) >= min_cells iff width >= 2*min_cells.
+ fn columnFitsHalves(p: *Pardes, source_id: usize, min_cells: u16) bool {
+ const f = p.layoutFindTerm(source_id) orelse return false;
+ p.computeGeom();
+ return p.col_w[f.col] >= min_cells * 2;
+ }
+
pub fn placeDoc(p: *Pardes, from_id: usize, free: usize, nt: *Pane) void {
const doc = if (nt.file) |f| output_pane.fileTraits(f.output).doc else true; // an image is a doc
var src_id: ?usize = null;
@@ -12335,7 +12896,7 @@ pub const Pardes = struct {
p.active = free;
return;
}
- if (doc and p.ncol < MAX_COLS) {
+ if (doc and p.ncol < MAX_COLS and p.columnFitsHalves(from_id, 100)) {
if (!p.layoutSplitColumn(from_id, free, true)) return p.stackDocLeft(free, nt);
p.active = free;
return;
@@ -12437,6 +12998,8 @@ pub const Pardes = struct {
.screen_w = opts.cols,
.screen_h = opts.rows,
.scratch = .init(gpa),
+ .frame_arena = .init(opts.frame_allocator orelse gpa),
+ .fallback = .{ .gpa = gpa },
};
errdefer p.deinit();
const st = try dump.readZon(gpa, zon_bytes, "load");
@@ -12586,12 +13149,12 @@ pub const Pardes = struct {
// content, and a default that came back padded is still a default.
const said = std.mem.trimStart(u8, rest, " ");
const defaults: []const []const u8 = switch (class) {
- .generic => &.{ pane_tail, legacy_pane_tail },
- .savable_file => &.{ file_pane_tail, legacy_file_pane_tail },
+ .generic => &.{ pane_tail, prev_pane_tail, legacy_pane_tail },
+ .savable_file => &.{ file_pane_tail, prev_file_pane_tail, legacy_file_pane_tail },
// Terminal dumps written before Filter used the generic current
- // tail, and the earliest version used just Del. Both upgrade;
- // other pane classes still treat this new default as user text.
- .terminal => &.{ terminal_pane_tail, pane_tail, legacy_pane_tail },
+ // tail, and the earliest version used just Del. All upgrade; other
+ // pane classes still treat these as user text.
+ .terminal => &.{ terminal_pane_tail, prev_terminal_pane_tail, pane_tail, prev_pane_tail, legacy_pane_tail },
};
for (defaults) |default|
if (std.mem.eql(u8, said, std.mem.trimStart(u8, default, " "))) return;
@@ -12740,6 +13303,7 @@ pub const Pardes = struct {
/// Recompute geometry, push grid-size changes to each emulator + pty, fire
/// deferred greetings. The mirror of the prototype's loop epilogue.
fn sync(p: *Pardes) void {
+ p.reapPanes();
p.computeGeom();
p.syncPanelAnimations();
p.trackJump();
@@ -13836,18 +14400,22 @@ pub const Pardes = struct {
_ = s.print(tx, body_y + i, tw, line, body_style);
}
- // the file-only passes and the terminal-only one: each is the
- // whole reason its pane kind renders differently at all, so each lives
- // with its kind. Order is load-bearing — gutter, then syntax over the
- // content, then the emulator's own colors — and the selection/cursor
- // passes below still win over all three.
- if (pane.file) |*f| {
- file_pane.drawGutter(p, pane, r, tx, tw, body_h, active);
- if (p.settings.colors) file_pane.recolorSyntax(p, pane, f, r, tx, tw, body_h);
- file_pane.drawWrapMarkers(p, pane, r, tx, tw, body_h, pane_bg);
+ // Coloring is one algorithm per pane, chosen by title (colorAlgo): the
+ // terminal projects its own ANSI, a file lays tree-sitter or diff
+ // shading over its content. source and diff share this pass because
+ // both feed f.highlights, which refreshHighlights filled with whichever
+ // this same choice named. Order is load-bearing — gutter, recolor, then
+ // wrap markers; the selection/cursor passes below win over all three.
+ switch (pane.colorAlgo()) {
+ .tty => if (p.settings.colors and pane.mode == .tty) term_pane.recolorAnsi(p, pane, r, tx, tw, body_h),
+ .source, .diff => {
+ const f = &pane.file.?;
+ file_pane.drawGutter(p, pane, r, tx, tw, body_h, active);
+ if (p.settings.colors) file_pane.recolorSyntax(p, pane, f, r, tx, tw, body_h);
+ file_pane.drawWrapMarkers(p, pane, r, tx, tw, body_h, pane_bg);
+ },
+ .none => {},
}
- const off = pane.scroll();
- if (p.settings.colors and pane.isTerminal()) term_pane.recolorAnsi(p, pane, r, tx, tw, body_h, off);
// mouse selections (pane-local coords), one pass per button — later
// buttons win on overlap. A left .done stays highlighted after release;
@@ -14363,6 +14931,81 @@ test "only the SPC clipboard commands cross to the system clipboard" {
try std.testing.expect(p.clip_pending == null);
}
+/// Every `.write` a keystroke produced, joined — what the pane's program would
+/// actually have read off its pty.
+fn drainWrites(p: *Pardes, buf: []u8) []const u8 {
+ var n: usize = 0;
+ while (p.nextEffect()) |effect| switch (effect) {
+ .write => |w| {
+ const b = w.bytes.slice();
+ if (n + b.len > buf.len) break;
+ @memcpy(buf[n..][0..b.len], b);
+ n += b.len;
+ },
+ else => {},
+ };
+ return buf[0..n];
+}
+
+test "Ctrl-V and Ctrl-Shift-V paste into the program a tty pane is running" {
+ if (platform == .web) return;
+ const gpa = std.testing.allocator;
+ const p = try Pardes.init(gpa, .{ .tty_only = true, .cols = 80, .rows = 24 });
+ defer p.deinit();
+ p.update(.{ .resize = .{ .cols = 80, .rows = 24 } });
+ var buf: [256]u8 = undefined;
+ _ = drainWrites(p, &buf);
+
+ const pane = p.panes[0].?;
+ term_pane.enterTty(p, 0);
+ try std.testing.expectEqual(Mode.tty, pane.mode);
+ p.setYank("one\ntwo");
+
+ // Ctrl-V types the DEFAULT REGISTER at the program. Unbracketed, so the
+ // newline becomes Enter's \r — a raw \n would run `one` and leave `two`
+ // half-typed.
+ p.update(.{ .key = .{ .cp = 'v', .ctrl = true } });
+ try std.testing.expectEqualStrings("one\rtwo", drainWrites(p, &buf));
+ // and it asked the desktop for nothing on the way
+ try std.testing.expect(p.clip_pending == null);
+
+ // Under mode 2004 the same keystroke brackets instead, which is what stops
+ // readline from RUNNING a multi-line paste.
+ pane.vt.modes.set(.bracketed_paste, true);
+ p.update(.{ .key = .{ .cp = 'v', .ctrl = true } });
+ try std.testing.expectEqualStrings("\x1b[200~one\ntwo\x1b[201~", drainWrites(p, &buf));
+
+ // Ctrl-Shift-V is the other store: it ASKS, types nothing yet, and the
+ // answer lands at the program rather than in an edit buffer.
+ pane.vt.modes.set(.bracketed_paste, false);
+ p.update(.{ .key = .{ .cp = 'v', .ctrl = true, .shift = true } });
+ try std.testing.expect(p.clip_pending != null);
+ try std.testing.expectEqualStrings("", drainWrites(p, &buf));
+ p.update(.{ .paste = "from-desktop" });
+ try std.testing.expectEqualStrings("from-desktop", drainWrites(p, &buf));
+ // the clipboard did not clobber the register on its way through
+ try std.testing.expectEqualStrings("one\ntwo", p.yank orelse "");
+}
+
+test "an unasked desktop paste reaches a tty pane's program, not its buffer" {
+ if (platform == .web) return;
+ const gpa = std.testing.allocator;
+ const p = try Pardes.init(gpa, .{ .tty_only = true, .cols = 80, .rows = 24 });
+ defer p.deinit();
+ p.update(.{ .resize = .{ .cols = 80, .rows = 24 } });
+ var buf: [256]u8 = undefined;
+ _ = drainWrites(p, &buf);
+
+ const pane = p.panes[0].?;
+ term_pane.enterTty(p, 0);
+ // No request behind it: the window manager's own paste, or SDL answering a
+ // Ctrl-Shift-V the desktop handled. It still has to reach the shell.
+ p.update(.{ .paste = "ls -la" });
+ try std.testing.expectEqualStrings("ls -la", drainWrites(p, &buf));
+ // and nothing was typed into an overlay the pty does not know about
+ try std.testing.expect(pane.ovl == null);
+}
+
test "leaving tty hides the prompt and keeps the command typed at it" {
if (platform == .web) return;
const gpa = std.testing.allocator;
diff --git a/src/source_manifest.zig b/src/source_manifest.zig
new file mode 100644
index 00000000..5de560ac
--- /dev/null
+++ b/src/source_manifest.zig
@@ -0,0 +1,44 @@
+//! The virtual filesystem: pardes's own source, embedded, as an ALLOWLIST.
+//!
+//! This is the default filesystem — what a host that implements no file method
+//! reads and writes, and the only one the browser has ever had. It replaced a
+//! build-time generator that embedded every tracked `.zig` file: 64 files and
+//! 2.4 MB of generated Zig, rediscovered on every consumer build because the
+//! tracked set can change without any known input changing.
+//!
+//! An allowlist instead, for the reason the generator's own comment gave away:
+//! nothing needs all of them. What earns a place here is a file that explains
+//! how pardes works to someone reading it inside pardes — the core, the host
+//! seam, the keymap, the build. `src/pardes.zig` alone is 722 KB of the total,
+//! and it is the one file worth that: it IS the program.
+//!
+//! Paths are as a user would type them, repo-root-relative, which is what
+//! `look` resolves a click against.
+
+pub const Source = struct { path: []const u8, contents: []const u8 };
+
+pub const all = [_]Source{
+ .{ .path = "build.zig", .contents = @embedFile("root-build.zig") },
+ .{ .path = "build.zig.zon", .contents = @embedFile("root-build.zig.zon") },
+ .{ .path = "src/pardes.zig", .contents = @embedFile("pardes.zig") },
+ .{ .path = "src/host.zig", .contents = @embedFile("host.zig") },
+ .{ .path = "src/config.zig", .contents = @embedFile("config.zig") },
+ .{ .path = "src/main.zig", .contents = @embedFile("main.zig") },
+ .{ .path = "src/builtins.zig", .contents = @embedFile("builtins.zig") },
+ .{ .path = "src/grammar_manifest.zig", .contents = @embedFile("grammar_manifest.zig") },
+ .{ .path = "src/source_manifest.zig", .contents = @embedFile("source_manifest.zig") },
+ .{ .path = "src/CHANGELOG.md", .contents = @embedFile("CHANGELOG.md") },
+};
+
+/// The written-file override wins, then the allowlist. Callers own no memory
+/// here: every byte is static or lives in the Fallback that answered.
+pub fn find(path: []const u8) ?[]const u8 {
+ for (all) |s| if (eql(s.path, path)) return s.contents;
+ return null;
+}
+
+fn eql(a: []const u8, b: []const u8) bool {
+ if (a.len != b.len) return false;
+ for (a, b) |x, y| if (x != y) return false;
+ return true;
+}
diff --git a/src/syntax.zig b/src/syntax.zig
index def11420..1494ebd3 100644
--- a/src/syntax.zig
+++ b/src/syntax.zig
@@ -23,6 +23,7 @@ const LanguageFn = *const fn () callconv(.c) *const ts.Language;
pub const Syn = enum(u8) { none, keyword, string, number, comment };
const Spec = struct {
+ name: []const u8,
exts: []const []const u8,
language: *const fn () callconv(.c) *const ts.Language,
query_src: []const u8,
@@ -51,6 +52,7 @@ fn initSpecs() [specCount()]Spec {
inline for (grammar_manifest.all) |g| {
if (grammarSelected(g)) {
out[i] = .{
+ .name = g.name,
.exts = g.exts,
.language = @extern(LanguageFn, .{ .name = "tree_sitter_" ++ g.name }),
.query_src = @field(ts_queries, g.name ++ "_highlights"),
@@ -139,17 +141,17 @@ pub fn stop() void {
}
}
-const Selected = struct { lang: *const ts.Language, query: *ts.Query };
+const Selected = struct { name: []const u8, lang: *const ts.Language, query: *ts.Query };
// NOTE: don't lang.destroy() — the tree_sitter_*() languages are static
// singletons reused on every open; destroying one use-after-frees the next.
fn ensure(spec: *Spec) !Selected {
const lang = spec.language();
- if (spec.compiled_query) |query| return .{ .lang = lang, .query = query };
+ if (spec.compiled_query) |query| return .{ .name = spec.name, .lang = lang, .query = query };
var error_offset: u32 = 0;
const query = try ts.Query.create(lang, spec.query_src, &error_offset);
spec.compiled_query = query;
- return .{ .lang = lang, .query = query };
+ return .{ .name = spec.name, .lang = lang, .query = query };
}
fn forExt(ext: []const u8) !?Selected {
@@ -161,6 +163,56 @@ fn forExt(ext: []const u8) !?Selected {
return null;
}
+const LangAlias = struct { []const u8, []const u8 };
+const lang_aliases = [_]LangAlias{
+ .{ "js", "javascript" },
+ .{ "jsx", "javascript" },
+ .{ "mjs", "javascript" },
+ .{ "py", "python" },
+ .{ "sh", "bash" },
+ .{ "shell", "bash" },
+ .{ "zsh", "bash" },
+ .{ "bash", "bash" },
+ .{ "rs", "rust" },
+ .{ "c++", "cpp" },
+ .{ "cxx", "cpp" },
+ .{ "cc", "cpp" },
+ .{ "cs", "c_sharp" },
+ .{ "kt", "kotlin" },
+ .{ "rb", "ruby" },
+ .{ "ml", "ocaml" },
+ .{ "hs", "haskell" },
+};
+
+fn forLang(name: []const u8) !?Selected {
+ var canonical = name;
+ for (lang_aliases) |a| {
+ if (std.ascii.eqlIgnoreCase(name, a[0])) {
+ canonical = a[1];
+ break;
+ }
+ }
+ for (&specs) |*spec| {
+ if (std.ascii.eqlIgnoreCase(canonical, spec.name)) return try ensure(spec);
+ }
+ return null;
+}
+
+fn runQuery(styles: []u8, sel: Selected, tree: *ts.Tree, base: usize) void {
+ const cursor = ts.QueryCursor.create();
+ defer cursor.destroy();
+ cursor.exec(sel.query, tree.rootNode());
+ while (cursor.nextMatch()) |match| {
+ for (match.captures) |cap| {
+ const syn = synFor(sel.query.captureNameForId(cap.index) orelse "");
+ if (syn == .none) continue;
+ var b: usize = base + cap.node.startByte();
+ const end = @min(base + @as(usize, cap.node.endByte()), styles.len);
+ while (b < end) : (b += 1) styles[b] = @intFromEnum(syn);
+ }
+ }
+}
+
// Queries compile on first use (`ensure`), never at startup. Pre-compiling the
// compact tier in Pardes.init cost EVERY boot ~120ms of ts_query__perform_analysis
// (55% of a Debug startup) to save ~40ms on the first .zig/.c/.cpp open — a pane
@@ -180,6 +232,9 @@ fn synFor(name: []const u8) Syn {
.{ "include", .keyword },
.{ "conditional", .keyword },
.{ "repeat", .keyword },
+ .{ "title", .keyword },
+ .{ "uri", .string },
+ .{ "reference", .number },
}) |m| {
if (std.mem.indexOf(u8, name, m[0]) != null) return m[1];
}
@@ -207,21 +262,86 @@ pub fn highlightFileRange(gpa: std.mem.Allocator, path: []const u8, content: []c
const tree = parser.parseString(source, null) orelse return styles;
defer tree.destroy();
- const cursor = ts.QueryCursor.create();
- defer cursor.destroy();
- cursor.exec(selected.query, tree.rootNode());
- while (cursor.nextMatch()) |match| {
- for (match.captures) |cap| {
- const syn = synFor(selected.query.captureNameForId(cap.index) orelse "");
- if (syn == .none) continue;
- var b: usize = cap.node.startByte();
- const end = @min(@as(usize, cap.node.endByte()), styles.len);
- while (b < end) : (b += 1) styles[b] = @intFromEnum(syn);
+ runQuery(styles, selected, tree, 0);
+
+ if (std.mem.eql(u8, selected.name, "markdown")) injectCodeBlocks(styles, source, tree.rootNode());
+ return styles;
+}
+
+fn injectCodeBlocks(styles: []u8, source: []const u8, node: ts.Node) void {
+ if (std.mem.eql(u8, node.kind(), "fenced_code_block")) {
+ highlightCodeBlock(styles, source, node);
+ return;
+ }
+ var i: u32 = 0;
+ const count = node.childCount();
+ while (i < count) : (i += 1) {
+ if (node.child(i)) |c| injectCodeBlocks(styles, source, c);
+ }
+}
+
+fn childOfKind(node: ts.Node, kind: []const u8) ?ts.Node {
+ var i: u32 = 0;
+ const count = node.childCount();
+ while (i < count) : (i += 1) {
+ if (node.child(i)) |c| {
+ if (std.mem.eql(u8, c.kind(), kind)) return c;
}
}
+ return null;
+}
+
+fn highlightCodeBlock(styles: []u8, source: []const u8, block: ts.Node) void {
+ const info = childOfKind(block, "info_string") orelse return;
+ const lang_node = childOfKind(info, "language") orelse return;
+ const content_node = childOfKind(block, "code_fence_content") orelse return;
+ const langtext = source[lang_node.startByte()..lang_node.endByte()];
+ const sub_sel = (forLang(langtext) catch return) orelse return;
+ const cs: usize = content_node.startByte();
+ const ce: usize = content_node.endByte();
+ if (ce > source.len or cs > ce) return;
+
+ const parser = ts.Parser.create();
+ defer parser.destroy();
+ parser.setLanguage(sub_sel.lang) catch return;
+ const tree = parser.parseString(source[cs..ce], null) orelse return;
+ defer tree.destroy();
+ runQuery(styles, sub_sel, tree, cs);
+}
+
+/// One Syn byte per byte of content[start, end) for unified diffs/patches.
+/// Pure byte scan; independent of tree-sitter and the `enabled` flag. Caller frees.
+pub fn highlightDiff(gpa: std.mem.Allocator, content: []const u8, start_byte_raw: usize, end_byte_raw: usize) ![]u8 {
+ const start_byte = @min(start_byte_raw, content.len);
+ const end_byte = @max(start_byte, @min(end_byte_raw, content.len));
+ const source = content[start_byte..end_byte];
+ const styles = try gpa.alloc(u8, source.len);
+ errdefer gpa.free(styles);
+ @memset(styles, 0);
+
+ var offset: usize = 0;
+ var lines = std.mem.splitScalar(u8, source, '\n');
+ while (lines.next()) |line| {
+ const syn = diffLineSyn(line);
+ if (syn != .none) @memset(styles[offset .. offset + line.len], @intFromEnum(syn));
+ offset += line.len + 1;
+ }
return styles;
}
+fn diffLineSyn(line: []const u8) Syn {
+ if (std.mem.startsWith(u8, line, "@@")) return .keyword;
+ if (std.mem.startsWith(u8, line, "+++") or
+ std.mem.startsWith(u8, line, "---") or
+ std.mem.startsWith(u8, line, "diff ") or
+ std.mem.startsWith(u8, line, "index ") or
+ std.mem.startsWith(u8, line, "\\ No newline")) return .comment;
+ if (line.len == 0) return .none;
+ if (line[0] == '+') return .string;
+ if (line[0] == '-') return .number;
+ return .none;
+}
+
test "tree-sitter allocator callbacks preserve and free exact allocations" {
syntax_allocator = std.testing.allocator;
defer syntax_allocator = undefined;
@@ -263,3 +383,48 @@ test "default full grammar set highlights Typst source" {
defer std.testing.allocator.free(short_ext);
try std.testing.expectEqual(Syn.keyword, @as(Syn, @enumFromInt(short_ext[keyword_at])));
}
+
+test "markdown highlights headings and injects fenced code blocks" {
+ if (!enabled or !full_grammars) return;
+ start(std.testing.allocator);
+ defer stop();
+
+ const source = "# Heading\n\n```zig\nconst answer = 42;\n```\n";
+ const styles = try highlightFileRange(std.testing.allocator, "doc.md", source, 0, source.len);
+ defer std.testing.allocator.free(styles);
+
+ const title_at = std.mem.indexOf(u8, source, "Heading").?;
+ const num_at = std.mem.indexOf(u8, source, "42").?;
+ // the heading is markdown's own highlight; the number proves the zig
+ // grammar was injected into the fenced block and colored its contents.
+ try std.testing.expectEqual(Syn.keyword, @as(Syn, @enumFromInt(styles[title_at])));
+ try std.testing.expectEqual(Syn.number, @as(Syn, @enumFromInt(styles[num_at])));
+}
+
+test "highlightDiff colors unified diff lines by prefix" {
+ const diff =
+ "diff --git a/x b/x\n" ++
+ "--- a/x\n" ++
+ "+++ b/x\n" ++
+ "@@ -1,3 +1,3 @@\n" ++
+ " context\n" ++
+ "-old line\n" ++
+ "+new line\n";
+ const styles = try highlightDiff(std.testing.allocator, diff, 0, diff.len);
+ defer std.testing.allocator.free(styles);
+
+ const byteSyn = struct {
+ fn at(s: []const u8, src: []const u8, needle: []const u8) Syn {
+ const i = std.mem.indexOf(u8, src, needle).?;
+ return @enumFromInt(s[i]);
+ }
+ }.at;
+
+ try std.testing.expectEqual(Syn.comment, byteSyn(styles, diff, "diff --git"));
+ try std.testing.expectEqual(Syn.comment, byteSyn(styles, diff, "--- a/x"));
+ try std.testing.expectEqual(Syn.comment, byteSyn(styles, diff, "+++ b/x"));
+ try std.testing.expectEqual(Syn.keyword, byteSyn(styles, diff, "@@ -1,3"));
+ try std.testing.expectEqual(Syn.none, byteSyn(styles, diff, " context"));
+ try std.testing.expectEqual(Syn.number, byteSyn(styles, diff, "-old line"));
+ try std.testing.expectEqual(Syn.string, byteSyn(styles, diff, "+new line"));
+}
diff --git a/src/term_pane.zig b/src/term_pane.zig
index cc0cc24e..7662292e 100644
--- a/src/term_pane.zig
+++ b/src/term_pane.zig
@@ -954,14 +954,12 @@ fn fillBody(dst: ?[]u8, pane: *Pane, viewport: []const []const u8) usize {
return written;
}
-/// tty colors: recolor each body cell from the emulator's own style so shell
-/// output keeps its ansi colors (gated on the Colors toggle by the caller).
-/// Rows the edit buffer stands in for are OURS, not the emulator's: they keep
-/// the plain body style, and the rows under them are read from the shell row
-/// the surface actually shows there.
-pub fn recolorAnsi(p: *Pardes, pane: *Pane, r: pardes.Rect, tx: u16, tw: u16, body_h: u16, off: i32) void {
+/// tty colors: recolor each visible body cell from the emulator's own style so
+/// raw output keeps its ansi colors. Runs ONLY in tty mode (the caller gates
+/// it) and reads the live viewport row for row: normal/insert editing shows
+/// plain text, so nothing an edit does can move a shell row's colour.
+pub fn recolorAnsi(p: *Pardes, pane: *Pane, r: pardes.Rect, tx: u16, tw: u16, body_h: u16) void {
const s = &p.surface;
- const goff: i32 = @intCast(pane.vt.screens.active.pages.scrollbar().offset);
const body_y = if (p.settings.tag_bottom) r.y else r.y + pardes.BOX_H;
var filtered_storage: FilteredColors = undefined;
const filtered: ?*FilteredColors = if (pane.tty_filter) blk: {
@@ -970,25 +968,15 @@ pub fn recolorAnsi(p: *Pardes, pane: *Pane, r: pardes.Rect, tx: u16, tw: u16, bo
} else null;
var vr: u16 = 0;
while (vr < body_h and vr < pane.rows) : (vr += 1) {
- const grid = pane.gridRow(off + @as(i32, vr)) - goff;
- if (pane.mode != .tty) if (pane.ovl) |o| {
- if (off + @as(i32, vr) >= o.row and off + @as(i32, vr) < o.row + @as(i32, @intCast(modal.lineCount(o.text)))) continue;
- };
- if (grid < 0) continue;
var c: u16 = 0;
while (c < tw) : (c += 1) {
- const ci = pane.vt.screens.active.pages.getCell(.{ .viewport = .{ .x = @intCast(c), .y = @intCast(grid) } }) orelse continue;
- // bodyText already gave a wide glyph's empty surface tail the
- // head's body style. Ordinary ANSI projection historically leaves
- // that alone; Filter must replace it too or one half of the cell
- // can retain a host/default colour (Ghostty gives the tail the
- // same style id as its wide head).
+ const ci = pane.vt.screens.active.pages.getCell(.{ .viewport = .{ .x = @intCast(c), .y = @intCast(vr) } }) orelse continue;
+ // Ghostty gives a wide glyph's spacer tail the head's style id;
+ // ordinary projection leaves it, a filter must repaint it too.
if (ci.cell.wide == .spacer_tail and filtered == null) continue;
const cell = s.at(tx + c, body_y + vr);
- // In ordinary ANSI mode retain the old sparse projection: bodyText
- // already painted every visible glyph. A filter paints the whole
- // VT viewport so even empty/default and background-only cells are
- // RGB-keyed by the theme rather than leaking the host defaults.
+ // sparse projection: bodyText already painted every glyph, so only
+ // a filter (which theme-keys blank/default cells too) touches these.
if (cell.default and filtered == null) continue;
cell.default = false;
cell.style = cellStyle(p, ci, filtered);
@@ -1340,6 +1328,73 @@ test "terminal Filter preserves exact palette-null light theme default roles" {
try testing.expectEqual(pardes.Color{ .rgb = light.bg.? }, reversed.at(tx, body_y).style.fg);
try testing.expectEqual(pardes.Color{ .rgb = light.fg.? }, reversed.at(tx, body_y).style.bg);
}
+test "tty ansi colors render only in tty mode, never in normal mode" {
+ const testing = std.testing;
+ const p = try Pardes.init(testing.allocator, .{ .tty_only = true, .cols = 18, .rows = 6 });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
+ const pane = p.panes[0].?;
+ pane.tty_filter = false;
+
+ p.update(.{ .output = .{ .pane = 0, .bytes = "\x1b]133;A\x1b\\\x1b[32mPP\x1b]133;B\x1b\\\x1b[31mR\x1b[34mB\x1b[0m out" } });
+
+ var frame = std.heap.ArenaAllocator.init(testing.allocator);
+ defer frame.deinit();
+ const r = p.rects[0];
+ const tx = r.x + config.GUTTER;
+ const body_y = if (p.settings.tag_bottom) r.y else r.y + pardes.BOX_H;
+ const red: pardes.Color = .{ .index = 1 };
+ const blue: pardes.Color = .{ .index = 4 };
+
+ // tty mode projects the emulator's ansi colours cell for cell.
+ pane.mode = .tty;
+ p.shell_rows.stale = true;
+ const tty = try p.render(frame.allocator());
+ try testing.expectEqual(red, tty.at(tx + 2, body_y).style.fg);
+ try testing.expectEqual(blue, tty.at(tx + 3, body_y).style.fg);
+
+ // normal mode is a plain editing view: no ansi projection at all, so an
+ // edit made here cannot change what tty mode renders.
+ pane.mode = .normal;
+ p.shell_rows.stale = true;
+ _ = frame.reset(.retain_capacity);
+ const norm = try p.render(frame.allocator());
+ try testing.expectEqualStrings("R", norm.at(tx, body_y).grapheme());
+ try testing.expect(!std.meta.eql(red, norm.at(tx, body_y).style.fg));
+ try testing.expect(!std.meta.eql(blue, norm.at(tx + 1, body_y).style.fg));
+}
+
+test "an edit overlay never changes tty-mode ansi colors" {
+ const testing = std.testing;
+ const p = try Pardes.init(testing.allocator, .{ .tty_only = true, .cols = 18, .rows = 6 });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
+ const pane = p.panes[0].?;
+ pane.tty_filter = false;
+ pane.mode = .tty;
+
+ p.update(.{ .output = .{ .pane = 0, .bytes = "\x1b[31mAAA\x1b[0m\r\n\x1b[32mBBB\x1b[0m\r\n\x1b[34mCCC\x1b[0m" } });
+
+ var frame = std.heap.ArenaAllocator.init(testing.allocator);
+ defer frame.deinit();
+ const r = p.rects[0];
+ const tx = r.x + config.GUTTER;
+ const body_y = if (p.settings.tag_bottom) r.y else r.y + pardes.BOX_H;
+ const blue: pardes.Color = .{ .index = 4 };
+
+ p.shell_rows.stale = true;
+ const before = try p.render(frame.allocator());
+ try testing.expectEqualStrings("C", before.at(tx, body_y + 2).grapheme());
+ try testing.expectEqual(blue, before.at(tx, body_y + 2).style.fg);
+
+ // A lingering multi-line edit overlay must not move any shell row's colour.
+ pane.ovl = .{ .row = 0, .rows = 1, .text = try p.gpa.dupe(u8, "e\nd\ni\nt") };
+ p.shell_rows.stale = true;
+ _ = frame.reset(.retain_capacity);
+ const after = try p.render(frame.allocator());
+ try testing.expectEqualStrings("C", after.at(tx, body_y + 2).grapheme());
+ try testing.expectEqual(blue, after.at(tx, body_y + 2).style.fg);
+}
pub fn palColor(p: *Pardes, idx: u8) pardes.Color {
if (p.theme().palette) |pal| if (idx < 16) return .{ .rgb = pal[idx] };
diff --git a/src/tty/tty.zig b/src/tty/tty.zig
index a0159f46..404fe582 100644
--- a/src/tty/tty.zig
+++ b/src/tty/tty.zig
@@ -11,7 +11,6 @@ const vaxis = @import("vaxis");
const pardes = @import("../pardes.zig");
const tracy = @import("../tracy.zig");
const look = @import("../look.zig");
-const temp_file = @import("../temp_file.zig");
const shell_bin = @import("../shell_bin.zig");
const message = @import("../message.zig");
const file_watch = @import("../file_watch.zig");
@@ -19,6 +18,7 @@ const user_config = @import("../user_config.zig");
const selection_pipe = @import("../selection_pipe.zig");
const nested = @import("../nested.zig");
const panel_compositor = @import("panel_compositor.zig");
+const host_api = @import("../host.zig");
extern "c" fn forkpty(amaster: *c_int, name: ?[*:0]u8, termp: ?*const anyopaque, winp: ?*const posix.winsize) c_int;
extern "c" fn execv(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8) c_int;
@@ -445,6 +445,8 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
options.image_allocator = allocs.image;
options.pdf_allocator = allocs.pdf;
options.tree_sitter_allocator = allocs.tree_sitter;
+ // the 16 MiB static buffer behind every per-frame Surface
+ options.frame_allocator = allocs.frame;
// SIGWINCH must never run vaxis's signal handler: it posts the winsize
// event through std.Io.Mutex/Condition, and when the signal lands on a
@@ -499,9 +501,6 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
} else try pardes.Pardes.init(allocs.pardes, options);
defer core.deinit();
- var frame_arena: std.heap.ArenaAllocator = .init(allocs.frame);
- defer frame_arena.deinit();
-
// Private, complete before any fork and retained until the last possible
// spawn; children borrow only these stable in-struct path buffers.
var prompt_rcs = shell_bin.PromptRcs.init();
@@ -516,54 +515,56 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
while (iterator.next()) |handle| vx.freeImage(tty.writer(), handle.id);
kitty_handles.deinit();
}
- var ptys: [pardes.MAX_PANES]?Pty = @splat(null);
- // per-slot spawn generation: a reused pane id ignores the old shell's
- // late pty_eof (which would otherwise close the NEW pty on that slot)
- var gens: [pardes.MAX_PANES]u32 = @splat(0);
- // ...and the core's one way to ask about those ptys: is a pane's tty still
- // the prompt we forked? Installed here rather than polled per frame (see
- // the cwd loop) and re-installed on a replay core, which owns a fresh set
- // of panes over this same table.
- core.tty_query = .{ .ctx = &ptys, .taken = &ttyTakenAt };
- // the single in-flight language query (see the .lsp effect)
- var lsp_task: ?std.Io.Future(anyerror!void) = null;
- // Selection filters may overlap: a second submit supersedes the first in
- // core without synchronously canceling a possibly slow shell command.
- var pipe_tasks: PipeTasks = .{};
- // One inotify instance for every watched pane, opened here — before any
- // thread exists — so the pre-loop effect drain below can already mark the
- // file a positional path argument opened. -1 off linux: watchPane goes
- // quiet and the core simply never gets a file_changed event.
- var inotify_fd: c_int = if (builtin.os.tag == .linux) libc.inotify_init1(linux.IN.CLOEXEC) else -1;
- var watches: file_watch.Table = @splat(null);
- var watch_task: ?std.Io.Future(anyerror!void) = null;
+ var frame_arena: std.heap.ArenaAllocator = .init(allocs.frame);
+ defer frame_arena.deinit();
+ var paste_buf: std.Io.Writer.Allocating = .init(gpa);
+ defer paste_buf.deinit();
var loop: Loop = .init(io, &tty, &vx);
+
+ var sh: Shell = .{
+ .io = io,
+ .gpa = gpa,
+ .lsp_gpa = allocs.lsp,
+ .core = core,
+ .prompt_rcs = &prompt_rcs,
+ .loop = &loop,
+ .vx = &vx,
+ .tty = &tty,
+ .kitty = &kitty_handles,
+ .frame = &frame_arena,
+ .paste_buf = &paste_buf,
+ // One inotify instance for every watched pane, opened here — before
+ // any thread exists — so the pre-loop effect drain below can already
+ // mark the file a positional path argument opened. -1 off linux:
+ // watchPane goes quiet and the core simply never gets a file_changed.
+ .inotify_fd = if (builtin.os.tag == .linux) libc.inotify_init1(linux.IN.CLOEXEC) else -1,
+ };
defer {
// reap the reader tasks (cancel interrupts a blocked read) before
// closing the masters — the runtime joins those threads on exit and a
// reader stuck in read(2) would hang the process — then drain the
// queue: leftover events own gpa bytes and would dump as leaks.
- for (&ptys) |*slot| if (slot.*) |*pt| {
+ for (&sh.ptys) |*slot| if (slot.*) |*pt| {
pt.reader.cancel(io) catch {};
_ = libc.close(pt.file.handle);
slot.* = null;
};
// join the query worker BEFORE the drain below, or its late post
// lands in a queue nobody empties again and the rows leak
- if (lsp_task) |*t| {
+ if (sh.lsp_task) |*t| {
t.cancel(io) catch {};
- lsp_task = null;
+ sh.lsp_task = null;
}
- pipe_tasks.cancelAll(io);
+ sh.pipe_tasks.cancelAll(io);
// same contract as the pty readers: cancel unblocks the watcher's
// read, and only then is the fd safe to close
- if (watch_task) |*t| {
+ if (sh.watch_task) |*t| {
t.cancel(io) catch {};
- watch_task = null;
+ sh.watch_task = null;
}
- if (inotify_fd >= 0) {
- _ = libc.close(inotify_fd);
- inotify_fd = -1;
+ if (sh.inotify_fd >= 0) {
+ _ = libc.close(sh.inotify_fd);
+ sh.inotify_fd = -1;
}
while (loop.tryEvent() catch null) |ev| switch (ev) {
.pty_read => |pr| gpa.free(pr.bytes),
@@ -577,6 +578,7 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
else => {},
};
}
+ const host = sh.host();
// The socket a pardes launched inside this one connects to (nested.zig).
// Declared AFTER the drain above so its teardown runs BEFORE it — the
@@ -588,8 +590,10 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
defer nested.unlisten(sock_fd);
// Perform the initial spawns BEFORE any worker thread exists: forkpty from
- // a multithreaded process can wedge the child before exec.
- drainEffects(core, &prompt_rcs, &ptys, &gens, io, gpa, allocs.lsp, &loop, &vx, &tty, &lsp_task, &pipe_tasks, inotify_fd, &watches, false);
+ // a multithreaded process can wedge the child before exec. `pump` installs
+ // the host on every pass; this drain runs outside it, so install it here.
+ core.host = host;
+ while (core.nextEffect()) |effect| core.perform(effect);
try loop.start();
defer loop.stop();
@@ -624,8 +628,8 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
// terminals answer in order, so when vaxis's reader flips queries_done
// every earlier reply is already applied — no window left to miss at any
// latency, and the enable lands before the next frame (see caps_pending
- // in the render path). A terminal that never answers keeps the defaults,
- // which is what the 2ms timeout produced anyway, and with no caps
+ // in pollFrame). A terminal that never answers keeps the defaults, which
+ // is what the 2ms timeout produced anyway, and with no caps
// enableDetectedFeatures writes no bytes — the snapshot goldens, where
// nothing ever answers, do not move. Startup gets 2ms faster, not slower.
//
@@ -640,202 +644,23 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
// caps.unicode — is never called. If that ever changes, wake the loop on
// vx.query_futex from a one-shot thread instead.
try vx.queryTerminalSend(tty.writer());
- var caps_pending = true;
// now threads are fine: start a reader task per pty
- for (&ptys, 0..) |*slot, id| if (slot.*) |*pt| {
- pt.reader = try io.concurrent(readPty, .{ io, gpa, pt.file, id, gens[id], &loop });
+ sh.threads_ok = true;
+ for (&sh.ptys, 0..) |*slot, id| if (slot.*) |*pt| {
+ pt.reader = try io.concurrent(readPty, .{ io, gpa, pt.file, id, sh.gens[id], &loop });
};
// ...and the one file watcher. Started here rather than lazily on the
// first watched pane because the fd already exists and an unwatched
// inotify instance just parks in read(2) — one thread for the process,
// however many panes come and go.
- if (inotify_fd >= 0) watch_task = io.concurrent(watchFiles, .{ io, inotify_fd, &loop }) catch null;
+ if (sh.inotify_fd >= 0) sh.watch_task = io.concurrent(watchFiles, .{ io, sh.inotify_fd, &loop }) catch null;
- var check_files = false;
- var pending: ?@TypeOf(Command.value) = .tick;
- // Where a bracketed paste is assembled. It has to outlive one drain pass:
- // the burst arrives over as many passes as the terminal takes to write it,
- // and the markers are the only thing that says where it ends.
- var paste_buf: std.Io.Writer.Allocating = .init(gpa);
- defer paste_buf.deinit();
- var in_paste = false;
- // 4 MiB ceiling, past which the tail is dropped rather than grown into. A
- // paste that large is a mis-click on a file, not an edit, and the core
- // would have to hold the whole of it as one undo entry.
- const max_paste_bytes: usize = 4 << 20;
+ // The core owns the loop ORDER (see Pardes.pump); the outer `while` stays
+ // here rather than being `core.run` for one reason: Restore swaps the
+ // whole core, and a core cannot replace itself from inside its own frame.
while (!core.quit) {
- var event = if (pending) |ev| blk: {
- pending = null;
- break :blk ev;
- } else try loop.nextEvent();
- const tz_event = tracy.zone(@src(), "event");
- // Apply every queued INPUT event, then render ONCE — the gui shell
- // drains SDL's queue the same way. Without this a wheel flick is fifty
- // full render+repaint (and re-highlight) cycles instead of one. A
- // native PDF page crossing is the one input boundary below: its next
- // wheel report needs geometry produced by this render. Pty output also
- // keeps a frame per chunk so progress paints as it arrives.
- var stop = false;
- var batch: usize = 0;
- while (true) {
- var output = false;
- var native_pdf_page_changed = false;
- switch (event) {
- .nop => {},
- .tick => core.update(.tick),
- .quit => stop = true,
- .focus_in => {},
- .focus_out => core.update(.pointer_leave),
- .winsize => |ws| {
- try vx.resize(gpa, tty.writer(), ws);
- if (comptime pardes.pdf_enabled)
- updateCoreTerminalSize(core, ws.cols, ws.rows, ws.x_pixel, ws.y_pixel)
- else
- core.update(.{ .resize = .{ .cols = ws.cols, .rows = ws.rows } });
- },
- .pty_read => |pr| {
- core.update(.{ .output = .{ .pane = @intCast(pr.id), .bytes = pr.bytes } });
- gpa.free(pr.bytes);
- output = true;
- },
- .pty_eof => |e| if (gens[e.id] == e.gen) {
- if (ptys[e.id]) |*pt| {
- pt.reader.await(io) catch {}; // reader just finished; join it or its future leaks
- _ = libc.close(pt.file.handle);
- ptys[e.id] = null;
- }
- core.update(.{ .eof = .{ .pane = @intCast(e.id) } });
- },
- .key_press => |key| if (in_paste) {
- // Between the markers a key is DATA, never a command. Same
- // two inputs as the dispatch below, so a pasted character
- // is exactly the character the core would have been given.
- const text = key.text orelse "";
- const cp = mapKey(effCp(key));
- const bytes: []const u8 = if (text.len > 0)
- text
- else if (cp == pardes.Key.tab)
- "\t"
- else if (cp == pardes.Key.enter or (key.mods.ctrl and cp == 'j'))
- // vaxis gives control bytes no text at all: a line
- // break inside a paste reaches the ground parser as a
- // bare CR (-> Key.enter) or, from a terminal that does
- // not translate them, a bare LF — which that parser
- // reports as ctrl+j. Nothing in here is a real
- // keypress, so both of them are just a newline.
- "\n"
- else
- // arrows, F-keys, a stray escape: noise a paste has no
- // business carrying, dropped rather than smuggled in.
- "";
- const room = max_paste_bytes -| paste_buf.written().len;
- paste_buf.writer.writeAll(bytes[0..@min(bytes.len, room)]) catch {};
- } else core.update(.{ .key = .{
- .cp = mapKey(effCp(key)),
- .text = key.text orelse "",
- .ctrl = key.mods.ctrl,
- .alt = key.mods.alt,
- .shift = key.mods.shift,
- } }),
- .mouse => |m| {
- const pdf_before = nativePdfWheelTarget(core, m);
- const button: ?pardes.Mouse.Button = switch (m.button) {
- .left => .left,
- .middle => .middle,
- .right => .right,
- .wheel_up => .wheel_up,
- .wheel_down => .wheel_down,
- .wheel_left => .wheel_left,
- .wheel_right => .wheel_right,
- .none => .none, // button-less motion: hover tracking
- else => null,
- };
- if (button) |b| core.update(.{ .mouse = .{
- .button = b,
- .kind = switch (m.type) {
- .press => .press,
- .release => .release,
- .motion => .motion,
- .drag => .drag,
- },
- .col = @intCast(m.col),
- .row = @intCast(m.row),
- .ctrl = m.mods.ctrl,
- } });
- if (pdf_before) |before| {
- if (core.panes[before.pane]) |pane| {
- if (pane.pdfPage()) |page|
- native_pdf_page_changed = page != before.page;
- }
- }
- },
- .paste => |bytes| {
- core.update(.{ .paste = bytes });
- gpa.free(@constCast(bytes));
- },
- .paste_start => {
- in_paste = true;
- paste_buf.clearRetainingCapacity();
- },
- .paste_end => {
- in_paste = false;
- // ONE event for the whole paste — the core borrows the
- // bytes for the call, exactly like the OSC 52 arm above.
- const pasted = paste_buf.written();
- if (pasted.len > 0) core.update(.{ .paste = pasted });
- paste_buf.clearRetainingCapacity();
- },
- .command => |line| {
- core.update(.{ .command = line });
- gpa.free(line);
- },
- // Coalesced on purpose: a burst of writes (a formatter, a
- // build, a `git checkout`) collapses into ONE pass below, so
- // it cannot queue a reload — or an undo entry — per write.
- .files_changed => check_files = true,
- .lsp_done => |d| {
- core.update(.{ .lsp_resp = .{ .id = d.id, .rows = d.rows } });
- allocs.lsp.free(d.rows);
- // the worker is finished; join it so its future does not
- // leak (same contract as pty_eof above)
- if (lsp_task) |*t| {
- t.await(io) catch {};
- lsp_task = null;
- }
- },
- .pipe_done => |response_value| {
- var response = response_value;
- core.update(.{ .pipe_resp = .{
- .id = response.id,
- .success = response.success,
- .outputs = response.outputs,
- } });
- response.deinit(gpa);
- pipe_tasks.finish(io, response_value.id);
- },
- }
- batch += 1;
- // A paste in flight keeps draining WITHOUT rendering: a hundred
- // thousand pasted characters are one edit, not a hundred thousand
- // render-worthy events. That cannot spin — the drain still ends
- // the moment the queue runs dry (tryEvent below) — so a terminal
- // which sends paste_start and never paste_end costs one frame.
- if (stop or output or native_pdf_page_changed or (!in_paste and batch >= 64)) break;
- event = (try loop.tryEvent()) orelse break;
- }
- tz_event.end();
- if (stop) break;
-
- if (check_files) {
- check_files = false;
- if (file_watch.reloadChanged(core, io, gpa, &watches))
- loop.postEvent(.files_changed) catch {};
- }
-
- drainEffects(core, &prompt_rcs, &ptys, &gens, io, gpa, allocs.lsp, &loop, &vx, &tty, &lsp_task, &pipe_tasks, inotify_fd, &watches, true);
- if (core.quit) break;
-
+ try core.pump(host);
// Restore builtin: swap in a core rebuilt from the dump; the live
// shells die with their masters (readers canceled, gens bumped so
// their late eofs never touch the replay panes)
@@ -846,31 +671,31 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
o.cols = core.screen_w;
o.rows = core.screen_h; // pre-size: dump panes never greet
const nc = pardes.Pardes.initFromDump(allocs.pardes, o, bytes) catch break :blk;
- for (&ptys, 0..) |*slot, pid| if (slot.*) |*pt| {
+ for (&sh.ptys, 0..) |*slot, pid| if (slot.*) |*pt| {
pt.reader.cancel(io) catch {};
_ = libc.close(pt.file.handle);
slot.* = null;
- gens[pid] +%= 1;
+ sh.gens[pid] +%= 1;
};
// the replay core's pane ids mean new things, and the dying core's
// `watch off` effects go into a queue nobody drains — drop the lot
// here. The new core emits its own `on`s as it builds its panes.
for (0..pardes.MAX_PANES) |wid| file_watch.watchPane(
- inotify_fd,
- &watches,
+ sh.inotify_fd,
+ &sh.watches,
@intCast(wid),
null,
0,
.{ .text = 0 },
);
- _ = file_watch.applyThemeEffect(core, gpa, inotify_fd, &watches, 0, false, false);
+ _ = file_watch.applyThemeEffect(core, gpa, sh.inotify_fd, &sh.watches, 0, false, false);
var image_iterator = kitty_handles.valueIterator();
while (image_iterator.next()) |handle| vx.freeImage(tty.writer(), handle.id);
kitty_handles.clearRetainingCapacity();
nc.native_images = vx.caps.kitty_graphics;
- nc.tty_query = .{ .ctx = &ptys, .taken = &ttyTakenAt };
core.deinit();
core = nc;
+ sh.core = nc;
if (comptime pardes.pdf_enabled) {
// A restored core did not receive the terminal's earlier
// winsize event. Reapply both the grid and physical cells
@@ -879,14 +704,304 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
updateCoreTerminalSize(core, vx.screen.width, vx.screen.height, vx.screen.width_pix, vx.screen.height_pix);
}
}
+ }
+}
+
+/// Everything the terminal shell owns and the core cannot: the ptys, the
+/// inotify table, the worker futures, and the one thread allowed to touch
+/// `tty.writer()`. This struct IS the `Host.ctx`.
+const Shell = struct {
+ io: std.Io,
+ gpa: std.mem.Allocator,
+ lsp_gpa: std.mem.Allocator,
+ /// live core; Restore replaces it (see run)
+ core: *pardes.Pardes,
+ prompt_rcs: *const shell_bin.PromptRcs,
+ loop: *Loop,
+ vx: *vaxis.Vaxis,
+ tty: *vaxis.Tty,
+ kitty: *std.AutoHashMap(pardes.ImageCacheKey, vaxis.Image),
+ frame: *std.heap.ArenaAllocator,
+ /// Where a bracketed paste is assembled. It has to outlive one drain pass:
+ /// the burst arrives over as many passes as the terminal takes to write
+ /// it, and the markers are the only thing that says where it ends.
+ paste_buf: *std.Io.Writer.Allocating,
+ inotify_fd: c_int,
+ ptys: [pardes.MAX_PANES]?Pty = @splat(null),
+ /// per-slot spawn generation: a reused pane id ignores the old shell's
+ /// late pty_eof (which would otherwise close the NEW pty on that slot)
+ gens: [pardes.MAX_PANES]u32 = @splat(0),
+ watches: file_watch.Table = @splat(null),
+ watch_task: ?std.Io.Future(anyerror!void) = null,
+ /// the single in-flight language query (see the lsp method)
+ lsp_task: ?std.Io.Future(anyerror!void) = null,
+ /// Selection filters may overlap: a second submit supersedes the first in
+ /// core without synchronously canceling a possibly slow shell command.
+ pipe_tasks: PipeTasks = .{},
+ /// false during the pre-loop drain: no worker exists to answer to yet
+ threads_ok: bool = false,
+ caps_pending: bool = true,
+ check_files: bool = false,
+ in_paste: bool = false,
+ /// the tracks the frame in flight was composed from
+ tracks: []const pardes.panel_animation.Track = &.{},
+
+ /// 4 MiB ceiling, past which the tail is dropped rather than grown into. A
+ /// paste that large is a mis-click on a file, not an edit, and the core
+ /// would have to hold the whole of it as one undo entry.
+ const max_paste_bytes: usize = 4 << 20;
+
+ fn of(ctx: ?*anyopaque) *Shell {
+ return @ptrCast(@alignCast(ctx.?));
+ }
+
+ fn host(s: *Shell) host_api.Host {
+ return .{ .ctx = s, .vtable = if (comptime pardes.isolated) &isolated_vtable else &vtable };
+ }
+
+ /// An ISOLATED build (`zig build run-isolated`): the terminal this draws on
+ /// and the keys it reads, and nothing else. Every other method stays null,
+ /// so the core answers it itself — the embedded source filesystem, the
+ /// in-process clipboard, silent ptys. Nothing is forked, nothing on disk is
+ /// opened or written, and no clipboard leaves the process. The option is
+ /// comptime, so the other vtable is not even built into that binary.
+ const isolated_vtable: host_api.Host.VTable = .{
+ .pull_wait_input = waitInput,
+ .push_present = present,
+ .push_post_present = postPresent,
+ };
+
+ const vtable: host_api.Host.VTable = .{
+ .pull_wait_input = waitInput,
+ .push_present = present,
+ .push_post_present = postPresent,
+ .push_poll_frame = pollFrame,
+ .push_spawn = spawn,
+ .push_pty_write = ptyWrite,
+ .push_pty_resize = ptyResize,
+ .pull_tty_taken = ttyTaken,
+ .push_write_file = writeFile,
+ .push_write_dump = writeDump,
+ .push_watch_file = watchFile,
+ .push_watch_theme = watchTheme,
+ .push_dump_themes = dumpThemes,
+ .push_set_clipboard = setClipboard,
+ .pull_read_clipboard = readClipboard,
+ .push_open_link = openLink,
+ .pull_lsp = lsp,
+ .pull_pipe = pipe,
+ };
+
+ // ---- input ------------------------------------------------------------
+
+ /// Block for one event, then apply the whole pending batch. Everything
+ /// goes through `core.update` rather than `postEvent`: a pty chunk borrows
+ /// its bytes for the call, and mixing queued with immediate delivery would
+ /// reorder a keystroke against the output it caused.
+ fn waitInput(ctx: ?*anyopaque, timeout_ms: u32) void {
+ const s = of(ctx);
+ var batch: usize = 0;
+ if (timeout_ms == 0) {
+ // A failed read is a DEAD event source — the reader is gone and no
+ // event can ever arrive again, so nothing could set `quit` and the
+ // outer `while (!core.quit)` would spin at full speed. End the
+ // session, exactly as the pre-vtable `try loop.nextEvent()` did.
+ const first = s.loop.nextEvent() catch {
+ s.core.quit = true;
+ return s.reloadWatched();
+ };
+ batch = 1;
+ if (s.apply(first)) return s.reloadWatched();
+ } else {
+ // Animating: the frame clock IS the wait, and the `.tick` that
+ // spends it is ours to post — `pump` cannot, because only this
+ // host knows when a real frame interval has passed. Anything that
+ // queues during the short sleep is drained below, in this pass.
+ std.Io.sleep(s.io, .fromMilliseconds(timeout_ms), .awake) catch {};
+ _ = s.apply(.tick);
+ batch = 1;
+ }
+ // Apply every queued INPUT event, then render ONCE — the gui shell
+ // drains SDL's queue the same way. Without this a wheel flick is fifty
+ // full render+repaint (and re-highlight) cycles instead of one. A
+ // paste in flight keeps draining WITHOUT rendering: a hundred thousand
+ // pasted characters are one edit. That cannot spin — the drain still
+ // ends the moment the queue runs dry.
+ while (s.in_paste or batch < 64) {
+ const ev = (s.loop.tryEvent() catch null) orelse break;
+ batch += 1;
+ if (s.apply(ev)) break;
+ }
+ s.reloadWatched();
+ }
+
+ /// Apply one vaxis event. Returns true when the batch must end here: the
+ /// session is over, a pty chunk wants its own frame so progress paints as
+ /// it arrives, or a native PDF page crossing needs geometry this render
+ /// has not produced yet.
+ fn apply(s: *Shell, event: @TypeOf(Command.value)) bool {
+ const core = s.core;
+ const tz_event = tracy.zone(@src(), "event");
+ defer tz_event.end();
+ switch (event) {
+ .nop => {},
+ .tick => core.update(.tick),
+ .quit => {
+ core.quit = true;
+ return true;
+ },
+ .focus_in => {},
+ .focus_out => core.update(.pointer_leave),
+ .winsize => |ws| {
+ s.vx.resize(s.gpa, s.tty.writer(), ws) catch {};
+ if (comptime pardes.pdf_enabled)
+ updateCoreTerminalSize(core, ws.cols, ws.rows, ws.x_pixel, ws.y_pixel)
+ else
+ core.update(.{ .resize = .{ .cols = ws.cols, .rows = ws.rows } });
+ },
+ .pty_read => |pr| {
+ core.update(.{ .output = .{ .pane = @intCast(pr.id), .bytes = pr.bytes } });
+ s.gpa.free(pr.bytes);
+ return true;
+ },
+ .pty_eof => |e| if (s.gens[e.id] == e.gen) {
+ if (s.ptys[e.id]) |*pt| {
+ pt.reader.await(s.io) catch {}; // reader just finished; join it or its future leaks
+ _ = libc.close(pt.file.handle);
+ s.ptys[e.id] = null;
+ }
+ core.update(.{ .eof = .{ .pane = @intCast(e.id) } });
+ },
+ .key_press => |key| if (s.in_paste) {
+ // Between the markers a key is DATA, never a command. Same
+ // two inputs as the dispatch below, so a pasted character
+ // is exactly the character the core would have been given.
+ const text = key.text orelse "";
+ const cp = mapKey(effCp(key));
+ const bytes: []const u8 = if (text.len > 0)
+ text
+ else if (cp == pardes.Key.tab)
+ "\t"
+ else if (cp == pardes.Key.enter or (key.mods.ctrl and cp == 'j'))
+ // vaxis gives control bytes no text at all: a line
+ // break inside a paste reaches the ground parser as a
+ // bare CR (-> Key.enter) or, from a terminal that does
+ // not translate them, a bare LF — which that parser
+ // reports as ctrl+j. Nothing in here is a real
+ // keypress, so both of them are just a newline.
+ "\n"
+ else
+ // arrows, F-keys, a stray escape: noise a paste has no
+ // business carrying, dropped rather than smuggled in.
+ "";
+ const room = max_paste_bytes -| s.paste_buf.written().len;
+ s.paste_buf.writer.writeAll(bytes[0..@min(bytes.len, room)]) catch {};
+ } else core.update(.{ .key = .{
+ .cp = mapKey(effCp(key)),
+ .text = key.text orelse "",
+ .ctrl = key.mods.ctrl,
+ .alt = key.mods.alt,
+ .shift = key.mods.shift,
+ } }),
+ .mouse => |m| {
+ const pdf_before = nativePdfWheelTarget(core, m);
+ const button: ?pardes.Mouse.Button = switch (m.button) {
+ .left => .left,
+ .middle => .middle,
+ .right => .right,
+ .wheel_up => .wheel_up,
+ .wheel_down => .wheel_down,
+ .wheel_left => .wheel_left,
+ .wheel_right => .wheel_right,
+ .none => .none, // button-less motion: hover tracking
+ else => null,
+ };
+ if (button) |b| core.update(.{ .mouse = .{
+ .button = b,
+ .kind = switch (m.type) {
+ .press => .press,
+ .release => .release,
+ .motion => .motion,
+ .drag => .drag,
+ },
+ .col = @intCast(m.col),
+ .row = @intCast(m.row),
+ .ctrl = m.mods.ctrl,
+ } });
+ if (pdf_before) |before| {
+ if (core.panes[before.pane]) |pane| {
+ if (pane.pdfPage()) |page| {
+ if (page != before.page) return true;
+ }
+ }
+ }
+ },
+ .paste => |bytes| {
+ core.update(.{ .paste = bytes });
+ s.gpa.free(@constCast(bytes));
+ },
+ .paste_start => {
+ s.in_paste = true;
+ s.paste_buf.clearRetainingCapacity();
+ },
+ .paste_end => {
+ s.in_paste = false;
+ // ONE event for the whole paste — the core borrows the
+ // bytes for the call, exactly like the OSC 52 arm above.
+ const pasted = s.paste_buf.written();
+ if (pasted.len > 0) core.update(.{ .paste = pasted });
+ s.paste_buf.clearRetainingCapacity();
+ },
+ .command => |line| {
+ core.update(.{ .command = line });
+ s.gpa.free(line);
+ },
+ // Coalesced on purpose: a burst of writes (a formatter, a build, a
+ // `git checkout`) collapses into ONE pass below, so it cannot
+ // queue a reload — or an undo entry — per write.
+ .files_changed => s.check_files = true,
+ .lsp_done => |d| {
+ core.update(.{ .lsp_resp = .{ .id = d.id, .rows = d.rows } });
+ s.lsp_gpa.free(d.rows);
+ // the worker is finished; join it so its future does not
+ // leak (same contract as pty_eof above)
+ if (s.lsp_task) |*t| {
+ t.await(s.io) catch {};
+ s.lsp_task = null;
+ }
+ },
+ .pipe_done => |response_value| {
+ var response = response_value;
+ core.update(.{ .pipe_resp = .{
+ .id = response.id,
+ .success = response.success,
+ .outputs = response.outputs,
+ } });
+ response.deinit(s.gpa);
+ s.pipe_tasks.finish(s.io, response_value.id);
+ },
+ }
+ return false;
+ }
+
+ fn reloadWatched(s: *Shell) void {
+ if (!s.check_files) return;
+ s.check_files = false;
+ if (file_watch.reloadChanged(s.core, s.io, s.gpa, &s.watches))
+ s.loop.postEvent(.files_changed) catch {};
+ }
+
+ // ---- the frame ---------------------------------------------------------
+ fn pollFrame(ctx: ?*anyopaque) void {
+ const s = of(ctx);
// live cwd for tags/look: cheap per-pane lookup, per frame. Whether the
// pane's tty still belongs to the prompt we forked is NOT polled here —
// it is a walk through /proc and nothing draws it, so the core pulls it
- // through ttyQuery below, at the Exec that cares.
- for (&ptys, 0..) |*slot, id| if (slot.*) |pt| {
+ // through tty_taken instead, at the Exec that cares.
+ for (&s.ptys, 0..) |*slot, id| if (slot.*) |pt| {
var lbuf: [1024]u8 = undefined;
- if (look.shellCwd(pt.pid, &lbuf)) |cwd| core.setCwd(id, cwd);
+ if (look.shellCwd(pt.pid, &lbuf)) |cwd| s.core.setCwd(id, cwd);
};
// The handshake landed (vaxis's reader flips queries_done on DA1, the
@@ -897,27 +1012,31 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
// matters as much as the enable: earlier frames were drawn under the
// pre-handshake caps, and vaxis's shadow grid has to be re-established
// under the new ones or it keeps skipping cells it thinks are current.
- if (caps_pending and vx.queries_done.load(.unordered)) {
- caps_pending = false;
- vx.enableDetectedFeatures(tty.writer()) catch {};
+ if (s.caps_pending and s.vx.queries_done.load(.unordered)) {
+ s.caps_pending = false;
+ s.vx.enableDetectedFeatures(s.tty.writer()) catch {};
// The core was constructed before the asynchronous handshake.
// Advertise native pixels only now, after every reply preceding
// DA1 has updated the capability set.
- core.native_images = vx.caps.kitty_graphics;
- vx.queueRefresh();
+ s.core.native_images = s.vx.caps.kitty_graphics;
+ s.vx.queueRefresh();
}
+ }
- // ---- render: surface -> vaxis, cell for cell ----
- _ = frame_arena.reset(.retain_capacity);
- const tz_core = tracy.zone(@src(), "core.render");
- const canonical = try core.render(frame_arena.allocator());
- tz_core.end();
- const surface = try panel_compositor.compose(
- frame_arena.allocator(),
- canonical,
- canonical.panelTracks(),
- core.theme().bg,
- );
+ /// The canonical surface -> vaxis, cell for cell, with no interpretation.
+ fn present(ctx: ?*anyopaque, canonical: *const pardes.Surface) void {
+ const s = of(ctx);
+ const vx = s.vx;
+ s.tracks = canonical.panelTracks();
+ _ = s.frame.reset(.retain_capacity);
+ // compose only READS the canonical surface; the mutable pointer is so
+ // it can hand it straight back when no panel is mid-transition.
+ const surface = panel_compositor.compose(
+ s.frame.allocator(),
+ @constCast(canonical),
+ s.tracks,
+ s.core.theme().bg,
+ ) catch return;
const tz_cells = tracy.zone(@src(), "surface->vaxis");
const win = vx.window();
win.clear();
@@ -949,16 +1068,16 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
if (!kittyImageRepresentable(place)) continue;
}
const key = place.cacheKey();
- if (!kitty_handles.contains(key) and vx.caps.kitty_graphics) {
+ if (!s.kitty.contains(key) and vx.caps.kitty_graphics) {
const enc = std.base64.standard.Encoder;
- if (gpa.alloc(u8, enc.calcSize(place.rgba.len))) |b64| {
- defer gpa.free(b64);
+ if (s.gpa.alloc(u8, enc.calcSize(place.rgba.len))) |b64| {
+ defer s.gpa.free(b64);
_ = enc.encode(b64, place.rgba);
- if (vx.transmitPreEncodedImage(tty.writer(), b64, @intCast(place.iw), @intCast(place.ih), .rgba) catch null) |handle|
- kitty_handles.put(key, handle) catch vx.freeImage(tty.writer(), handle.id);
+ if (vx.transmitPreEncodedImage(s.tty.writer(), b64, @intCast(place.iw), @intCast(place.ih), .rgba) catch null) |handle|
+ s.kitty.put(key, handle) catch vx.freeImage(s.tty.writer(), handle.id);
} else |_| {}
}
- if (kitty_handles.get(key)) |cached| {
+ if (s.kitty.get(key)) |cached| {
if (comptime !pardes.pdf_enabled) {
const child = win.child(.{ .x_off = place.x, .y_off = place.y, .width = place.w, .height = place.h });
cached.draw(child, .{ .scale = .contain }) catch {};
@@ -990,15 +1109,15 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
while (true) {
var stale: [pardes.MAX_PANES]pardes.ImageCacheKey = undefined;
var stale_len: usize = 0;
- var image_iterator = kitty_handles.iterator();
+ var image_iterator = s.kitty.iterator();
while (image_iterator.next()) |entry| {
if (surfaceHasKittyKey(surface, entry.key_ptr.*)) continue;
stale[stale_len] = entry.key_ptr.*;
stale_len += 1;
if (stale_len == stale.len) break;
}
- for (stale[0..stale_len]) |key| if (kitty_handles.fetchRemove(key)) |removed|
- vx.freeImage(tty.writer(), removed.value.id);
+ for (stale[0..stale_len]) |key| if (s.kitty.fetchRemove(key)) |removed|
+ vx.freeImage(s.tty.writer(), removed.value.id);
if (stale_len < stale.len) break;
}
if (surface.cursor) |cur| {
@@ -1007,231 +1126,235 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void {
win.setCursorShape(if (cur.bar) .beam else .default);
}
const tz_render = tracy.zone(@src(), "vx.render");
- try vx.render(tty.writer());
+ vx.render(s.tty.writer()) catch {};
tz_render.end();
- core.acknowledgePanelPresentation(canonical.panelTracks());
+ }
+
+ fn postPresent(ctx: ?*anyopaque) void {
+ const s = of(ctx);
+ s.core.acknowledgePanelPresentation(s.tracks);
tracy.frameMark();
+ }
+
+ // ---- pseudo-terminals ---------------------------------------------------
- // Active core animation is the only reason this otherwise event-driven
- // frontend redraws on a clock. Sleep on the loop thread, then make the
- // next pass a tick; input and worker events can queue during the short
- // sleep and are drained in that pass. No timer worker can outlive the
- // loop, and at the exact endpoint we return to an indefinite wait.
- if (core.animationActive()) {
- std.Io.sleep(io, .fromMilliseconds(pardes.animation.frame_ms), .awake) catch {};
- pending = .tick;
+ fn spawn(ctx: ?*anyopaque, pane: u8, cwd: []const u8) void {
+ const s = of(ctx);
+ // the core reuses pane ids and there is no close effect: a deleted
+ // pane's shell lives in its slot until a respawn lands here — reap
+ // it (cancel joins the reader; its late eof is ignored by gen)
+ if (s.ptys[pane]) |*old| {
+ old.reader.cancel(s.io) catch {};
+ _ = libc.close(old.file.handle);
+ s.ptys[pane] = null;
+ }
+ s.gens[pane] +%= 1;
+ var cwd_buf: [256:0]u8 = undefined;
+ var cwd_z: ?[*:0]const u8 = null;
+ if (cwd.len > 0 and cwd.len < cwd_buf.len) {
+ @memcpy(cwd_buf[0..cwd.len], cwd);
+ cwd_buf[cwd.len] = 0;
+ cwd_z = @ptrCast(&cwd_buf);
+ }
+ const child = forkShell(s.core, pane, s.prompt_rcs, s.core.shellBin(), cwd_z, s.core.screen_h, s.core.screen_w);
+ s.ptys[pane] = .{ .file = child.file, .pid = child.pid, .reader = .{ .any_future = null, .result = {} } };
+ // report the pane's starting directory back to the core (tags). The
+ // slot needs no occupancy reset: nothing is remembered, and the next
+ // Exec asks about the shell that is there now.
+ var lbuf: [1024]u8 = undefined;
+ if (look.shellCwd(child.pid, &lbuf)) |wd| s.core.setCwd(pane, wd);
+ if (s.threads_ok) {
+ if (s.ptys[pane]) |*pt| {
+ pt.reader = s.io.concurrent(readPty, .{ s.io, s.gpa, pt.file, @as(usize, pane), s.gens[pane], s.loop }) catch pt.reader;
+ }
}
}
-}
-fn drainEffects(
- core: *pardes.Pardes,
- prompt_rcs: *const shell_bin.PromptRcs,
- ptys: *[pardes.MAX_PANES]?Pty,
- gens: *[pardes.MAX_PANES]u32,
- io: std.Io,
- gpa: std.mem.Allocator,
- lsp_allocator: std.mem.Allocator,
- loop: *Loop,
- vx: *vaxis.Vaxis,
- tty: *vaxis.Tty,
- lsp_task: *?std.Io.Future(anyerror!void),
- pipe_tasks: *PipeTasks,
- inotify_fd: c_int,
- watches: *file_watch.Table,
- threads_ok: bool,
-) void {
- while (core.nextEffect()) |effect| switch (effect) {
- .spawn => |sp| {
- // the core reuses pane ids and there is no close effect: a deleted
- // pane's shell lives in its slot until a respawn lands here — reap
- // it (cancel joins the reader; its late eof is ignored by gen)
- if (ptys[sp.pane]) |*old| {
- old.reader.cancel(io) catch {};
- _ = libc.close(old.file.handle);
- ptys[sp.pane] = null;
- }
- gens[sp.pane] +%= 1;
- const cwd = sp.cwd.slice();
- var cwd_buf: [256:0]u8 = undefined;
- var cwd_z: ?[*:0]const u8 = null;
- if (cwd.len > 0) {
- @memcpy(cwd_buf[0..cwd.len], cwd);
- cwd_buf[cwd.len] = 0;
- cwd_z = @ptrCast(&cwd_buf);
- }
- const child = forkShell(core, sp.pane, prompt_rcs, core.shellBin(), cwd_z, core.screen_h, core.screen_w);
- ptys[sp.pane] = .{ .file = child.file, .pid = child.pid, .reader = .{ .any_future = null, .result = {} } };
- // report the pane's starting directory back to the core (tags). The
- // slot needs no occupancy reset: nothing is remembered, and the next
- // Exec asks about the shell that is there now.
- var lbuf: [1024]u8 = undefined;
- if (look.shellCwd(child.pid, &lbuf)) |wd| core.setCwd(sp.pane, wd);
- if (threads_ok) {
- if (ptys[sp.pane]) |*pt| {
- pt.reader = io.concurrent(readPty, .{ io, gpa, pt.file, @as(usize, sp.pane), gens[sp.pane], loop }) catch pt.reader;
- }
- }
- },
- .write => |w| {
- if (ptys[w.pane]) |pt| writeFd(pt.file.handle, w.bytes.slice());
- },
- .resize_pty => |rs| {
- if (ptys[rs.pane]) |pt| {
- const ws: posix.winsize = .{ .row = rs.rows, .col = rs.cols, .xpixel = 0, .ypixel = 0 };
- _ = posix.system.ioctl(pt.file.handle, TIOCSWINSZ, @intFromPtr(&ws));
- }
- },
- .open_link => |url| look.openLink(url.slice()), // desktop browser
- .save_file => |sf| {
- const pane = core.panes[sf.pane] orelse continue;
- const f = pane.file orelse continue;
- var pathbuf: [4096:0]u8 = undefined;
- if (f.path.len >= pathbuf.len) continue;
- @memcpy(pathbuf[0..f.path.len], f.path);
- pathbuf[f.path.len] = 0;
- const fd = libc.open(pathbuf[0..f.path.len :0], .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
- if (fd < 0) continue;
- writeFd(fd, f.content);
- _ = libc.close(fd);
- // our own write is about to come back as a watch event: restamp
- // from the bytes we just put there so it reads as "no change"
- if (watches[sf.pane]) |*w| if (w.serial == pane.serial) switch (w.generation) {
- .text => w.generation = .{ .text = std.hash.Wyhash.hash(0, f.content) },
+ fn ptyWrite(ctx: ?*anyopaque, pane: u8, bytes: []const u8) void {
+ const s = of(ctx);
+ if (s.ptys[pane]) |pt| writeFd(pt.file.handle, bytes);
+ }
+
+ fn ptyResize(ctx: ?*anyopaque, pane: u8, cols: u16, rows: u16) void {
+ const s = of(ctx);
+ if (s.ptys[pane]) |pt| {
+ const ws: posix.winsize = .{ .row = rows, .col = cols, .xpixel = 0, .ypixel = 0 };
+ _ = posix.system.ioctl(pt.file.handle, TIOCSWINSZ, @intFromPtr(&ws));
+ }
+ }
+
+ /// Is a pane's tty still the prompt we forked? Lazy by construction — it
+ /// runs only where the core is about to type a command line, so the /proc
+ /// walk costs nothing on an ordinary frame. A pane with no pty of ours (a
+ /// document, a slot whose shell already died) is not a terminal a program
+ /// can be holding.
+ fn ttyTaken(ctx: ?*anyopaque, pane: u8) bool {
+ const s = of(ctx);
+ const pt = s.ptys[pane] orelse return false;
+ return look.ttyTaken(pt.pid, pt.file.handle);
+ }
+
+ // ---- the filesystem -----------------------------------------------------
+
+ fn writeFile(ctx: ?*anyopaque, pane: u8, path: []const u8, bytes: []const u8) void {
+ const s = of(ctx);
+ var pathbuf: [4096:0]u8 = undefined;
+ if (path.len >= pathbuf.len) return;
+ @memcpy(pathbuf[0..path.len], path);
+ pathbuf[path.len] = 0;
+ const fd = libc.open(pathbuf[0..path.len :0], .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
+ if (fd < 0) return;
+ writeFd(fd, bytes);
+ _ = libc.close(fd);
+ // our own write is about to come back as a watch event: restamp from
+ // the bytes we just put there so it reads as "no change". Only when
+ // this IS the pane's watched file — a `Save <elsewhere>` must not
+ // silence a real change to the file the pane has open.
+ if (s.core.panes[pane]) |pn| if (pn.file) |f| if (std.mem.eql(u8, f.path, path)) {
+ if (s.watches[pane]) |*w| if (w.serial == pn.serial) switch (w.generation) {
+ .text => w.generation = .{ .text = std.hash.Wyhash.hash(0, bytes) },
.pdf => {},
};
- // ...and say so on the pane's message row. AFTER the write, not
- // beside it: every `continue` above is a save that did not happen
- // and must not be reported as one.
- var mbuf: [256]u8 = undefined;
- core.setMessage(sf.pane, message.stamp(&mbuf, "saved", f.path));
- },
- .new_file => |request| {
- var path_buf: [4096:0]u8 = undefined;
- const made = temp_file.create(&path_buf) orelse continue;
- if (core.openNewFile(request.pane, request.serial, made.path))
- made.adopt()
- else
- made.discard();
- },
- .write_dump => {
- const out = core.dump_out orelse continue;
- var pbuf: [1024:0]u8 = undefined;
- const path = pardes.dump.outPath(&pbuf) orelse continue;
- const fd = libc.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
- if (fd < 0) continue;
- writeFd(fd, out);
- _ = libc.close(fd);
- core.setLastDump(path);
- },
- .dump_themes => |request| {
- const config_dir = core.opts.config_dir orelse continue;
- const out_dir = user_config.dumpThemes(io, gpa, config_dir, pardes.themes) catch |err| {
- core.reportError(request.pane, "dump themes", err);
- continue;
- };
- defer gpa.free(out_dir);
- var mbuf: [256]u8 = undefined;
- core.setMessage(request.pane, message.stamp(&mbuf, "dumped themes", out_dir));
- },
- .set_clipboard => {
- // mirror the core's yank register out via OSC 52
- if (core.yank) |y| vx.copyToSystemClipboard(tty.writer(), y, gpa) catch {};
- },
- .read_clipboard => {
- // ...and the other direction, OSC 52 read. The answer arrives on
- // vaxis's reader thread as an ordinary `.paste` event and reaches
- // the core through the same path an outer bracketed paste does —
- // this request is the only wiring it needs. "The answer arrives"
- // is the optimistic reading: a clipboard READ is an exfiltration
- // primitive and terminals treat it as one (ghostty prompts by
- // default, xterm ships it off, a multiplexer or ssh link may eat
- // it), and a refusal looks exactly like silence. So the core's
- // pending request is dropped by the next keystroke rather than
- // pasting minutes late, and `SPC p` in a locked-down terminal
- // honestly does nothing.
- vx.requestSystemClipboard(tty.writer()) catch {};
- },
- .lsp => |q| {
- if (!threads_ok) continue; // pre-loop drain: nothing to answer to yet
- const pane = core.panes[q.pane] orelse continue;
- // a pane with no file still asks `status` (it is about the backend,
- // not the buffer): empty path and source, root from the pane's cwd
- const f = pane.file;
- const job = lsp_allocator.create(LspJob) catch continue;
- job.* = .{
- .id = q.id,
- .kind = q.kind,
- .offset = q.offset,
- .path = lsp_allocator.dupe(u8, if (f) |ff| ff.path else "") catch {
- lsp_allocator.destroy(job);
- continue;
- },
- .source = lsp_allocator.dupeZ(u8, if (f) |ff| ff.content else "") catch {
- lsp_allocator.free(job.path);
- lsp_allocator.destroy(job);
- continue;
- },
- .arg = lsp_allocator.dupe(u8, q.arg.slice()) catch {
- lsp_allocator.free(job.path);
- lsp_allocator.free(job.source);
- lsp_allocator.destroy(job);
- continue;
- },
- .root = lsp_allocator.dupe(u8, if (f) |ff| (std.fs.path.dirname(ff.path) orelse "/") else pane.cwdSlice()) catch {
- lsp_allocator.free(job.path);
- lsp_allocator.free(job.source);
- lsp_allocator.free(job.arg);
- lsp_allocator.destroy(job);
- continue;
- },
- };
- // ponytail: ONE query in flight, so one future slot. Replacing it
- // cancels-then-joins the previous worker, which for a backend that
- // ignores cancellation means waiting out a query the user already
- // abandoned. Queries are milliseconds; make this a real pool the
- // day a backend takes long enough to notice.
- if (lsp_task.*) |*old| {
- old.cancel(io) catch {};
- lsp_task.* = null;
- }
- lsp_task.* = io.concurrent(lspWorker, .{ lsp_allocator, job, loop }) catch {
- job.free(lsp_allocator);
- continue;
- };
- },
- .pipe => |request| {
- if (!threads_ok) continue;
- if (pipe_tasks.full()) {
- core.update(.{ .pipe_resp = .{ .id = request.id, .success = false, .outputs = &.{} } });
- continue;
- }
- const view = core.pipeRequest(request.id) orelse continue;
- const job = selection_pipe.Job.copy(gpa, view) catch continue;
- const future = io.concurrent(pipeWorker, .{ io, gpa, job, loop }) catch {
- job.deinit(gpa);
- continue;
- };
- pipe_tasks.add(.{ .id = request.id, .future = future });
- },
- .watch => |w| {
- if (file_watch.applyEffect(core, io, gpa, inotify_fd, watches, w.pane, w.on))
- loop.postEvent(.files_changed) catch {};
- },
- .theme_file => |request| {
- if (file_watch.applyThemeEffect(
- core,
- gpa,
- inotify_fd,
- watches,
- request.generation,
- request.on,
- threads_ok,
- )) loop.postEvent(.files_changed) catch {};
- },
- .quit => {},
- };
-}
+ };
+ // ...and say so on the pane's message row. AFTER the write, not beside
+ // it: every early return above is a save that did not happen and must
+ // not be reported as one.
+ var mbuf: [256]u8 = undefined;
+ s.core.setMessage(pane, message.stamp(&mbuf, "saved", path));
+ }
+
+ fn writeDump(ctx: ?*anyopaque, bytes: []const u8) void {
+ const s = of(ctx);
+ var pbuf: [1024:0]u8 = undefined;
+ const path = pardes.dump.outPath(&pbuf) orelse return;
+ const fd = libc.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
+ if (fd < 0) return;
+ writeFd(fd, bytes);
+ _ = libc.close(fd);
+ s.core.setLastDump(path);
+ }
+
+ fn watchFile(ctx: ?*anyopaque, pane: u8, _: []const u8, on: bool) void {
+ const s = of(ctx);
+ if (file_watch.applyEffect(s.core, s.io, s.gpa, s.inotify_fd, &s.watches, pane, on))
+ s.loop.postEvent(.files_changed) catch {};
+ }
+
+ fn watchTheme(ctx: ?*anyopaque, generation: u32, on: bool) void {
+ const s = of(ctx);
+ if (file_watch.applyThemeEffect(s.core, s.gpa, s.inotify_fd, &s.watches, generation, on, s.threads_ok))
+ s.loop.postEvent(.files_changed) catch {};
+ }
+
+ fn dumpThemes(ctx: ?*anyopaque, pane: u8) void {
+ const s = of(ctx);
+ const config_dir = s.core.opts.config_dir orelse return;
+ const out_dir = user_config.dumpThemes(s.io, s.gpa, config_dir, pardes.themes) catch |err| {
+ s.core.reportError(pane, "dump themes", err);
+ return;
+ };
+ defer s.gpa.free(out_dir);
+ var mbuf: [256]u8 = undefined;
+ s.core.setMessage(pane, message.stamp(&mbuf, "dumped themes", out_dir));
+ }
+
+ // ---- the desktop --------------------------------------------------------
+
+ /// mirror the core's yank register out via OSC 52
+ fn setClipboard(ctx: ?*anyopaque, text: []const u8) void {
+ const s = of(ctx);
+ if (text.len == 0) return;
+ s.vx.copyToSystemClipboard(s.tty.writer(), text, s.gpa) catch {};
+ }
+
+ /// ...and the other direction, OSC 52 read. The answer arrives on vaxis's
+ /// reader thread as an ordinary `.paste` event and reaches the core
+ /// through the same path an outer bracketed paste does — this request is
+ /// the only wiring it needs. "The answer arrives" is the optimistic
+ /// reading: a clipboard READ is an exfiltration primitive and terminals
+ /// treat it as one (ghostty prompts by default, xterm ships it off, a
+ /// multiplexer or ssh link may eat it), and a refusal looks exactly like
+ /// silence. So the core's pending request is dropped by the next keystroke
+ /// rather than pasting minutes late, and `SPC p` in a locked-down terminal
+ /// honestly does nothing.
+ fn readClipboard(ctx: ?*anyopaque) void {
+ const s = of(ctx);
+ s.vx.requestSystemClipboard(s.tty.writer()) catch {};
+ }
+
+ fn openLink(_: ?*anyopaque, url: []const u8) void {
+ look.openLink(url); // desktop browser
+ }
+
+ // ---- work that must leave the loop --------------------------------------
+
+ fn lsp(ctx: ?*anyopaque, req: host_api.LspRequest) void {
+ const s = of(ctx);
+ if (!s.threads_ok) return; // pre-loop drain: nothing to answer to yet
+ const pane = s.core.panes[req.pane] orelse return;
+ // a pane with no file still asks `status` (it is about the backend,
+ // not the buffer): empty path and source, root from the pane's cwd
+ const f = pane.file;
+ const a = s.lsp_gpa;
+ const job = a.create(LspJob) catch return;
+ job.* = .{
+ .id = req.id,
+ .kind = req.kind,
+ .offset = req.offset,
+ .path = a.dupe(u8, if (f) |ff| ff.path else "") catch {
+ a.destroy(job);
+ return;
+ },
+ .source = a.dupeZ(u8, if (f) |ff| ff.content else "") catch {
+ a.free(job.path);
+ a.destroy(job);
+ return;
+ },
+ .arg = a.dupe(u8, req.arg) catch {
+ a.free(job.path);
+ a.free(job.source);
+ a.destroy(job);
+ return;
+ },
+ .root = a.dupe(u8, if (f) |ff| (std.fs.path.dirname(ff.path) orelse "/") else pane.cwdSlice()) catch {
+ a.free(job.path);
+ a.free(job.source);
+ a.free(job.arg);
+ a.destroy(job);
+ return;
+ },
+ };
+ // ponytail: ONE query in flight, so one future slot. Replacing it
+ // cancels-then-joins the previous worker, which for a backend that
+ // ignores cancellation means waiting out a query the user already
+ // abandoned. Queries are milliseconds; make this a real pool the day a
+ // backend takes long enough to notice.
+ if (s.lsp_task) |*old| {
+ old.cancel(s.io) catch {};
+ s.lsp_task = null;
+ }
+ s.lsp_task = s.io.concurrent(lspWorker, .{ a, job, s.loop }) catch {
+ job.free(a);
+ return;
+ };
+ }
+
+ fn pipe(ctx: ?*anyopaque, id: u32) void {
+ const s = of(ctx);
+ if (!s.threads_ok) return;
+ if (s.pipe_tasks.full()) {
+ s.core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } });
+ return;
+ }
+ const view = s.core.pipeRequest(id) orelse return;
+ const job = selection_pipe.Job.copy(s.gpa, view) catch return;
+ const future = s.io.concurrent(pipeWorker, .{ s.io, s.gpa, job, s.loop }) catch {
+ job.deinit(s.gpa);
+ return;
+ };
+ s.pipe_tasks.add(.{ .id = id, .future = future });
+ }
+};
/// Answer a language query off the event loop and post the rows back. This is
/// the whole async execution model: the same shape as readPty — do the slow
@@ -1331,17 +1454,6 @@ fn winchWatch(loop: *Loop, vx: *vaxis.Vaxis, tty: *vaxis.Tty) void {
}
}
-/// The core's `tty_query`: answer for one pane out of this host's pty table.
-/// Lazy by construction — it runs only where the core is about to type a
-/// command line, so the /proc walk costs nothing on an ordinary frame. A pane
-/// with no pty of ours (a document, a slot whose shell already died) is not a
-/// terminal a program can be holding.
-fn ttyTakenAt(ctx: ?*anyopaque, pane: usize) bool {
- const table: *const [pardes.MAX_PANES]?Pty = @ptrCast(@alignCast(ctx orelse return false));
- const pt = table[pane] orelse return false;
- return look.ttyTaken(pt.pid, pt.file.handle);
-}
-
fn forkShell(core: *pardes.Pardes, pane: usize, prompt_rcs: *const shell_bin.PromptRcs, bin: []const u8, cwd: ?[*:0]const u8, rows: u16, cols: u16) struct { file: std.Io.File, pid: posix.pid_t } {
var master: c_int = undefined;
// resolved BEFORE the fork, into this frame, which the child inherits:
diff --git a/src/web.zig b/src/web.zig
index 24ae7296..d642e108 100644
--- a/src/web.zig
+++ b/src/web.zig
@@ -1,9 +1,12 @@
//! Freestanding WebAssembly boundary for the DOM backend.
//!
-//! This file deliberately contains no browser imports. JavaScript owns the
-//! clock and every IO operation, feeds events through this ABI, and reads one
-//! packed cell buffer after `pardes_frame`. Keeping that boundary flat makes
-//! the same module directly instantiable by the dependency-free Node harness.
+//! JavaScript owns the clock and nothing else: it calls `pardes_tick` (one
+//! `Pardes.pump`) and reads the packed cell buffer `present` left behind. The
+//! host vtable below is only what a page genuinely has — pixels, the
+//! clipboard, links, downloads. Processes, a real filesystem, a language
+//! backend and subprocess pipes are left null, so the core answers them itself
+//! with a virtual filesystem, a virtual clipboard and silent ptys instead of
+//! forwarding effects that JavaScript cannot honour anyway.
const std = @import("std");
const pardes = @import("pardes.zig");
@@ -96,13 +99,10 @@ comptime {
const State = struct {
core: *pardes.Pardes,
- arena: std.heap.ArenaAllocator,
cells: []WebCell = &.{},
frame_len: usize = 0,
frame_cols: u16 = 0,
frame_rows: u16 = 0,
- effect_data: []u8 = &.{},
- effect_len: usize = 0,
fn init(cols: u16, rows: u16) !State {
const allocs = pardes.allocators.init(gpa);
@@ -117,20 +117,16 @@ const State = struct {
const core = try pardes.Pardes.initFromDump(allocs.pardes, .{
.cols = cols,
.rows = rows,
+ .frame_allocator = allocs.frame,
.image_allocator = allocs.image,
.pdf_allocator = allocs.pdf,
.tree_sitter_allocator = allocs.tree_sitter,
}, embedded_dump);
- return .{
- .core = core,
- .arena = .init(allocs.frame),
- };
+ return .{ .core = core };
}
fn deinit(s: *State) void {
if (s.cells.len > 0) gpa.free(s.cells);
- if (s.effect_data.len > 0) gpa.free(s.effect_data);
- s.arena.deinit();
s.core.deinit();
pardes.image.stop();
if (comptime pardes.pdf_enabled) pardes.pdf.stop();
@@ -142,8 +138,6 @@ const State = struct {
var state: ?State = null;
var input: [input_capacity]u8 = undefined;
var last_error: u32 = 0;
-var effect_aux0: u32 = 0;
-var effect_aux1: u32 = 0;
export fn pardes_init(cols_arg: u32, rows_arg: u32) u32 {
if (state) |*old| old.deinit();
@@ -210,69 +204,6 @@ export fn pardes_paste(len_arg: u32) void {
s.core.update(.{ .paste = input[0..len] });
}
-export fn pardes_output(pane: u32, len_arg: u32) void {
- const s = &(state orelse return);
- if (pane >= pardes.MAX_PANES) return;
- const len: usize = @min(len_arg, input.len);
- s.core.update(.{ .output = .{ .pane = @intCast(pane), .bytes = input[0..len] } });
-}
-
-export fn pardes_lsp_response(id: u32, len_arg: u32) void {
- const s = &(state orelse return);
- const len: usize = @min(len_arg, input.len);
- s.core.update(.{ .lsp_resp = .{ .id = id, .rows = input[0..len] } });
-}
-
-/// Complete host-handled effect kind 12. On success `input` is
-/// `[count:u32][count * output_len:u32][output bytes...]`, little-endian.
-/// A static browser has no process host and simply never calls this; an
-/// embedding such as Electron can run the request without another WASM ABI.
-export fn pardes_pipe_response(id: u32, success_arg: u32, len_arg: u32) void {
- const s = &(state orelse return);
- if (success_arg == 0) {
- s.core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } });
- return;
- }
- const len: usize = @min(len_arg, input.len);
- if (len < 4) return;
- const count: usize = std.mem.readInt(u32, input[0..4], .little);
- if (count == 0 or count > pardes.MAX_SELS) return;
- const header_len = std.math.add(usize, 4, std.math.mul(usize, count, 4) catch return) catch return;
- if (header_len > len) return;
- var outputs: [pardes.MAX_SELS][]const u8 = undefined;
- var at = header_len;
- for (0..count) |i| {
- const off = 4 + i * 4;
- const encoded_len: *const [4]u8 = @ptrCast(&input[off]);
- const output_len: usize = std.mem.readInt(u32, encoded_len, .little);
- const end = std.math.add(usize, at, output_len) catch return;
- if (end > len) return;
- outputs[i] = input[at..end];
- at = end;
- }
- if (at != len) return;
- s.core.update(.{ .pipe_resp = .{ .id = id, .success = true, .outputs = outputs[0..count] } });
-}
-
-export fn pardes_file_changed(pane: u32, len_arg: u32) void {
- const s = &(state orelse return);
- if (pane >= pardes.MAX_PANES) return;
- const len: usize = @min(len_arg, input.len);
- s.core.update(.{ .file_changed = .{ .pane = @intCast(pane), .bytes = input[0..len] } });
-}
-
-export fn pardes_set_cwd(pane: u32, len_arg: u32) void {
- const s = &(state orelse return);
- if (pane >= pardes.MAX_PANES) return;
- const len: usize = @min(len_arg, input.len);
- s.core.setCwd(@intCast(pane), input[0..len]);
-}
-
-export fn pardes_eof(pane: u32) void {
- const s = &(state orelse return);
- if (pane < pardes.MAX_PANES) s.core.update(.{ .eof = .{ .pane = @intCast(pane) } });
-}
-
/// Buttons and kinds are their boundary enum ordinals. Invalid values are
/// ignored rather than reaching an unchecked enum cast inside wasm.
export fn pardes_mouse(button_arg: u32, kind_arg: u32, col_arg: u32, row_arg: u32, mods: u32) void {
@@ -314,54 +245,41 @@ export fn pardes_pointer_leave() void {
s.core.update(.pointer_leave);
}
+/// One iteration of the core's own loop: queued input, effects, render,
+/// present. JS calls it once per animation frame, after spending that frame's
+/// animation ticks.
export fn pardes_tick() void {
const s = &(state orelse return);
+ s.core.pump(host(s)) catch |err| {
+ last_error = @intFromError(err);
+ };
+}
+
+/// Spend one fixed 60 Hz animation step, the only writer of animated time in
+/// this host. Separate from the pump for the reason the AppKit shell keeps them
+/// separate: if every input pump also advanced the transition, a burst of keys
+/// would collapse a ten-frame fade into one display frame.
+export fn pardes_animation_tick() void {
+ const s = &(state orelse return);
s.core.update(.tick);
}
-/// Render the canonical Surface into a stable, packed JS-facing buffer.
-/// Returns the number of cells, or zero if initialization/rendering failed.
+export fn pardes_animating() u32 {
+ const s = &(state orelse return 0);
+ return @intFromBool(s.core.animationActive());
+}
+
+/// The Exit builtin, or the last pane closing. JS stops its frame loop.
+export fn pardes_should_quit() u32 {
+ const s = &(state orelse return 0);
+ return @intFromBool(s.core.quit);
+}
+
+/// The number of cells in the frame `present` last packed, or zero before the
+/// first tick. `pardes_frame_ptr` is valid until the next one.
export fn pardes_frame() u32 {
const s = &(state orelse return 0);
- _ = s.arena.reset(.retain_capacity);
- s.frame_len = 0;
- s.frame_cols = 0;
- s.frame_rows = 0;
- const surface = s.core.render(s.arena.allocator()) catch |err| {
- last_error = @intFromError(err);
- return 0;
- };
- const count: usize = @as(usize, surface.cols) * surface.rows;
- if (count != s.cells.len) {
- if (count == 0) {
- if (s.cells.len > 0) gpa.free(s.cells);
- s.cells = &.{};
- } else {
- const resized = if (s.cells.len == 0)
- gpa.alloc(WebCell, count)
- else
- gpa.realloc(s.cells, count);
- s.cells = resized catch |err| {
- last_error = @intFromError(err);
- return 0;
- };
- }
- }
- s.frame_len = count;
- s.frame_cols = surface.cols;
- s.frame_rows = surface.rows;
- for (surface.cells, s.cells[0..count]) |cell, *out| {
- out.* = .{
- .text = @splat(0),
- .fg = encodeColor(cell.style.fg),
- .bg = encodeColor(cell.style.bg),
- .attrs = encodeAttrs(cell.style),
- .len = if (cell.default) 1 else cell.len,
- .flags = @intFromBool(cell.default),
- };
- if (cell.default) out.text[0] = ' ' else @memcpy(out.text[0..cell.len], cell.grapheme());
- }
- return @intCast(count);
+ return @intCast(s.frame_len);
}
export fn pardes_frame_ptr() u32 {
@@ -405,99 +323,94 @@ export fn pardes_chrome_target(col_arg: u32, row_arg: u32) u32 {
return (@as(u32, target.row) << 16) | target.col;
}
-// Effect codes consumed by app.mjs. Unknown/host-specific effects are still
-// surfaced as `pardes-io` CustomEvents, so embedding the static shell in a
-// process-capable host does not require another wasm boundary.
-export fn pardes_effect_next() u32 {
- const s = &(state orelse return 0);
- clearEffect(s);
- effect_aux0 = 0;
- effect_aux1 = 0;
- const effect = s.core.nextEffect() orelse return 0;
- return switch (effect) {
- .spawn => |e| blk: {
- effect_aux0 = e.pane;
- putEffect(s, e.cwd.slice());
- break :blk 1;
- },
- .write => |e| blk: {
- effect_aux0 = e.pane;
- putEffect(s, e.bytes.slice());
- break :blk 2;
- },
- .resize_pty => |e| blk: {
- effect_aux0 = e.pane;
- effect_aux1 = (@as(u32, e.cols) << 16) | e.rows;
- break :blk 3;
- },
- .open_link => |e| blk: {
- putEffect(s, e.slice());
- break :blk 4;
- },
- .save_file => |e| blk: {
- effect_aux0 = e.pane;
- if (s.core.panes[e.pane]) |pane| if (pane.file) |file|
- putSaveEffect(s, file.path, file.content);
- break :blk 5;
- },
- .write_dump => blk: {
- if (s.core.dump_out) |bytes| putEffect(s, bytes);
- break :blk 6;
- },
- .set_clipboard => blk: {
- if (s.core.yank) |bytes| putEffect(s, bytes);
- break :blk 7;
- },
- // 13, and no payload either way: the browser cannot hand the clipboard
- // over synchronously, so the answer arrives later as an ordinary
- // pardes_paste — or never, if the permission prompt says no.
- .read_clipboard => 13,
- .lsp => |e| blk: {
- effect_aux0 = e.id;
- effect_aux1 = e.pane;
- putEffect(s, e.arg.slice());
- break :blk 8;
- },
- // Process-capable embeddings receive exact command/cwd/input bytes:
- // [command_len][cwd_len][count][input lengths...][all payloads...].
- .pipe => |e| blk: {
- effect_aux0 = e.id;
- const request = s.core.pipeRequest(e.id) orelse break :blk 12;
- putPipeEffect(s, request);
- break :blk 12;
- },
- .watch => |e| blk: {
- effect_aux0 = e.pane;
- effect_aux1 = @intFromBool(e.on);
- if (e.on) if (s.core.panes[e.pane]) |pane| if (pane.file) |file| putEffect(s, file.path);
- break :blk 9;
- },
- .new_file => |e| blk: {
- effect_aux0 = e.pane;
- effect_aux1 = e.serial;
- break :blk 11;
- },
- .theme_file, .dump_themes => unreachable,
- .quit => 10,
- };
+// ---- the host ----
+//
+// Four imports, because four things here are the browser's and not the core's.
+// Everything else in `Host.VTable` stays null: see the file comment.
+extern "pardes" fn host_open_link(url: [*]const u8, url_len: usize) callconv(.c) void;
+extern "pardes" fn host_set_clipboard(text: [*]const u8, text_len: usize) callconv(.c) void;
+extern "pardes" fn host_read_clipboard() callconv(.c) void;
+/// A file a page writes is a download. `path` names it; both slices are
+/// borrowed for the length of the call.
+extern "pardes" fn host_download(
+ path: [*]const u8,
+ path_len: usize,
+ bytes: [*]const u8,
+ bytes_len: usize,
+) callconv(.c) void;
+
+const vtable: pardes.Host.VTable = .{
+ .push_present = present,
+ .push_write_file = writeFile,
+ .push_write_dump = writeDump,
+ .push_set_clipboard = setClipboard,
+ .pull_read_clipboard = readClipboard,
+ .push_open_link = openLink,
+};
+
+fn host(s: *State) pardes.Host {
+ return .{ .ctx = s, .vtable = &vtable };
}
-export fn pardes_effect_ptr() u32 {
- const s = &(state orelse return 0);
- return if (s.effect_len == 0) 0 else @intCast(@intFromPtr(s.effect_data.ptr));
+/// Pack the canonical Surface into the stable, JS-facing cell array.
+fn present(ctx: ?*anyopaque, surface: *const pardes.Surface) void {
+ const s: *State = @ptrCast(@alignCast(ctx.?));
+ s.frame_len = 0;
+ s.frame_cols = 0;
+ s.frame_rows = 0;
+ const count: usize = @as(usize, surface.cols) * surface.rows;
+ if (count != s.cells.len) {
+ if (count == 0) {
+ if (s.cells.len > 0) gpa.free(s.cells);
+ s.cells = &.{};
+ } else {
+ const resized = if (s.cells.len == 0)
+ gpa.alloc(WebCell, count)
+ else
+ gpa.realloc(s.cells, count);
+ s.cells = resized catch |err| {
+ last_error = @intFromError(err);
+ return;
+ };
+ }
+ }
+ s.frame_len = count;
+ s.frame_cols = surface.cols;
+ s.frame_rows = surface.rows;
+ for (surface.cells, s.cells[0..count]) |cell, *out| {
+ out.* = .{
+ .text = @splat(0),
+ .fg = encodeColor(cell.style.fg),
+ .bg = encodeColor(cell.style.bg),
+ .attrs = encodeAttrs(cell.style),
+ .len = if (cell.default) 1 else cell.len,
+ .flags = @intFromBool(cell.default),
+ };
+ if (cell.default) out.text[0] = ' ' else @memcpy(out.text[0..cell.len], cell.grapheme());
+ }
}
-export fn pardes_effect_len() u32 {
- const s = &(state orelse return 0);
- return @intCast(s.effect_len);
+fn writeFile(_: ?*anyopaque, _: u8, path: []const u8, bytes: []const u8) void {
+ host_download(path.ptr, path.len, bytes.ptr, bytes.len);
+}
+
+fn writeDump(_: ?*anyopaque, bytes: []const u8) void {
+ const name = "pardes-dump.zon";
+ host_download(name.ptr, name.len, bytes.ptr, bytes.len);
}
-export fn pardes_effect_aux0() u32 {
- return effect_aux0;
+fn setClipboard(_: ?*anyopaque, text: []const u8) void {
+ host_set_clipboard(text.ptr, text.len);
}
-export fn pardes_effect_aux1() u32 {
- return effect_aux1;
+/// Asynchronous and permission-gated, unlike everything else here: the answer
+/// arrives later as an ordinary `pardes_paste`, or never if the prompt says no.
+fn readClipboard(_: ?*anyopaque) void {
+ host_read_clipboard();
+}
+
+fn openLink(_: ?*anyopaque, url: []const u8) void {
+ host_open_link(url.ptr, url.len);
}
fn encodeColor(color: pardes.Color) u32 {
@@ -521,63 +434,3 @@ fn encodeAttrs(style: pardes.CellStyle) u16 {
attrs |= @as(u16, @intFromEnum(style.ul)) << 8;
return attrs;
}
-
-fn clearEffect(s: *State) void {
- if (s.effect_data.len > 0) gpa.free(s.effect_data);
- s.effect_data = &.{};
- s.effect_len = 0;
-}
-
-fn allocEffect(s: *State, len: usize) ?[]u8 {
- std.debug.assert(s.effect_data.len == 0 and s.effect_len == 0);
- if (len == 0) return s.effect_data;
- s.effect_data = gpa.alloc(u8, len) catch return null;
- s.effect_len = len;
- return s.effect_data;
-}
-
-fn putEffect(s: *State, bytes: []const u8) void {
- const out = allocEffect(s, bytes.len) orelse return;
- @memcpy(out, bytes);
-}
-
-fn writeEffectU32(out: []u8, at: *usize, value: u32) void {
- const word: *[4]u8 = @ptrCast(out[at.*..].ptr);
- std.mem.writeInt(u32, word, value, .little);
- at.* += 4;
-}
-
-fn putSaveEffect(s: *State, path: []const u8, content: []const u8) void {
- var total = std.math.add(usize, 4, path.len) catch return;
- total = std.math.add(usize, total, content.len) catch return;
- const out = allocEffect(s, total) orelse return;
- var at: usize = 0;
- writeEffectU32(out, &at, @intCast(path.len));
- @memcpy(out[at..][0..path.len], path);
- at += path.len;
- @memcpy(out[at..][0..content.len], content);
-}
-
-fn putPipeEffect(s: *State, request: anytype) void {
- var total = std.math.mul(usize, request.inputs.len, 4) catch return;
- total = std.math.add(usize, total, 12) catch return;
- total = std.math.add(usize, total, request.command.len) catch return;
- total = std.math.add(usize, total, request.cwd.len) catch return;
- for (request.inputs) |selection|
- total = std.math.add(usize, total, selection.bytes.len) catch return;
- const out = allocEffect(s, total) orelse return;
- var at: usize = 0;
- writeEffectU32(out, &at, @intCast(request.command.len));
- writeEffectU32(out, &at, @intCast(request.cwd.len));
- writeEffectU32(out, &at, @intCast(request.inputs.len));
- for (request.inputs) |selection| writeEffectU32(out, &at, @intCast(selection.bytes.len));
- @memcpy(out[at..][0..request.command.len], request.command);
- at += request.command.len;
- @memcpy(out[at..][0..request.cwd.len], request.cwd);
- at += request.cwd.len;
- for (request.inputs) |selection| {
- @memcpy(out[at..][0..selection.bytes.len], selection.bytes);
- at += selection.bytes.len;
- }
- std.debug.assert(at == out.len);
-}
diff --git a/src/web/app.mjs b/src/web/app.mjs
index 631c6067..fcb9c23d 100644
--- a/src/web/app.mjs
+++ b/src/web/app.mjs
@@ -116,8 +116,6 @@ export class PardesRuntime {
this.root = root;
this.wasm = wasm;
this.renderer = new DomRenderer(root, wasm);
- this.inputPtr = wasm.pardes_input_ptr();
- this.inputCapacity = wasm.pardes_input_capacity();
this.cellWidth = 1;
this.cellHeight = 1;
this.running = false;
@@ -132,10 +130,9 @@ export class PardesRuntime {
const { cols, rows } = this.gridSize();
const error = this.wasm.pardes_init(cols, rows);
if (error) throw new Error(`Pardes wasm init failed (${error})`);
- this.inputPtr = this.wasm.pardes_input_ptr();
this.resize();
+ this.wasm.pardes_tick();
this.renderer.render();
- this.drainEffects();
this.running = true;
this.animationClock = { last: null, lag: 0 };
this.frameHandle = requestAnimationFrame((timestamp) => this.frame(timestamp));
@@ -150,11 +147,15 @@ export class PardesRuntime {
frame(timestamp) {
if (!this.running) return;
+ // JS owns the animation clock; the pump that follows applies those ticks,
+ // runs the core's effects and presents one frame however fast the display
+ // is. Both halves are needed: an idle core still has input and effects.
for (let ticks = animationTicks(this.animationClock, timestamp); ticks > 0; ticks -= 1) {
- this.wasm.pardes_tick();
+ this.wasm.pardes_animation_tick();
}
+ this.wasm.pardes_tick();
+ if (this.wasm.pardes_should_quit()) this.running = false;
this.renderer.render();
- this.drainEffects();
this.frameHandle = requestAnimationFrame((nextTimestamp) => this.frame(nextTimestamp));
}
@@ -183,10 +184,7 @@ export class PardesRuntime {
}
writeInput(text) {
- const data = encoder.encode(text);
- if (data.length > this.inputCapacity) throw new Error("browser input exceeds wasm transfer buffer");
- new Uint8Array(this.wasm.memory.buffer, this.inputPtr, data.length).set(data);
- return data.length;
+ return putInput(this.wasm, text);
}
key(event) {
@@ -313,44 +311,6 @@ export class PardesRuntime {
this.root.addEventListener("wheel", (event) => this.wheel(event), { passive: false });
globalThis.addEventListener?.("resize", () => this.resize());
}
-
- drainEffects() {
- for (;;) {
- const kind = this.wasm.pardes_effect_next();
- if (!kind) return;
- const ptr = this.wasm.pardes_effect_ptr();
- const len = this.wasm.pardes_effect_len();
- const data = new Uint8Array(len);
- if (len) data.set(new Uint8Array(this.wasm.memory.buffer, ptr, len));
- const aux0 = this.wasm.pardes_effect_aux0();
- const aux1 = this.wasm.pardes_effect_aux1();
- this.handleEffect(kind, data, aux0, aux1);
- }
- }
-
- handleEffect(kind, data, aux0, aux1) {
- if (kind === 4) {
- globalThis.open?.(decoder.decode(data), "_blank", "noopener,noreferrer");
- } else if (kind === 5) {
- const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
- const pathLength = data.length >= 4 ? view.getUint32(0, true) : 0;
- const path = decoder.decode(data.subarray(4, 4 + pathLength));
- download(data.subarray(4 + pathLength), path.split("/").pop() || "pardes.txt", "text/plain;charset=utf-8");
- } else if (kind === 6) {
- download(data, "pardes-dump.zon", "text/plain;charset=utf-8");
- } else if (kind === 7) {
- navigator.clipboard?.writeText(decoder.decode(data)).catch(() => {});
- } else if (kind === 13) {
- // Async and permission-gated, unlike every other effect here: a refused
- // or unsupported read is simply a paste that never happens, which is
- // what the core already tolerates from an empty clipboard.
- navigator.clipboard?.readText().then((text) => this.wasm.pardes_paste(this.writeInput(text))).catch(() => {});
- } else if (kind === 10) {
- this.running = false;
- } else {
- this.root.dispatchEvent(new CustomEvent("pardes-io", { detail: { kind, data, aux0, aux1 } }));
- }
- }
}
/// Spend monotonic requestAnimationFrame time as fixed 60 Hz core ticks. A
@@ -372,17 +332,56 @@ export function animationTicks(clock, timestamp) {
return ticks;
}
+/// The four things the core asks the page for, as the module's imports. The
+/// holder exists because the import object has to be built before the instance
+/// whose memory those imports read.
+export function browserHost() {
+ const host = { wasm: null };
+ const view = (ptr, len) => new Uint8Array(host.wasm.memory.buffer, ptr, len);
+ const text = (ptr, len) => decoder.decode(view(ptr, len));
+ host.imports = {
+ pardes: {
+ host_open_link: (ptr, len) => {
+ globalThis.open?.(text(ptr, len), "_blank", "noopener,noreferrer");
+ },
+ host_set_clipboard: (ptr, len) => {
+ globalThis.navigator?.clipboard?.writeText(text(ptr, len)).catch(() => {});
+ },
+ // Async and permission-gated, unlike every other import here: a refused
+ // or unsupported read is simply a paste that never happens, which is
+ // what the core already tolerates from an empty clipboard.
+ host_read_clipboard: () => {
+ globalThis.navigator?.clipboard?.readText()
+ .then((clip) => host.wasm.pardes_paste(putInput(host.wasm, clip)))
+ .catch(() => {});
+ },
+ // A file a page writes is a download; the core already resolved the path
+ // and the bytes, and the Blob needs its own copy of them.
+ host_download: (pathPtr, pathLen, ptr, len) => {
+ const name = text(pathPtr, pathLen).split("/").pop() || "pardes.txt";
+ download(view(ptr, len).slice(), name, "text/plain;charset=utf-8");
+ },
+ },
+ };
+ return host;
+}
+
export async function instantiate(url = "./pardes.wasm") {
+ const host = browserHost();
const response = await fetch(url);
if (!response.ok) throw new Error(`fetch ${url}: HTTP ${response.status}`);
if (WebAssembly.instantiateStreaming) {
try {
- return (await WebAssembly.instantiateStreaming(response.clone(), {})).instance.exports;
+ const { instance } = await WebAssembly.instantiateStreaming(response.clone(), host.imports);
+ host.wasm = instance.exports;
+ return host.wasm;
} catch (error) {
if (!/mime|content-type/i.test(String(error))) throw error;
}
}
- return (await WebAssembly.instantiate(await response.arrayBuffer(), {})).instance.exports;
+ const { instance } = await WebAssembly.instantiate(await response.arrayBuffer(), host.imports);
+ host.wasm = instance.exports;
+ return host.wasm;
}
export async function boot(root, url = "./pardes.wasm") {
@@ -461,6 +460,13 @@ function clamp(value, low, high) {
return Math.max(low, Math.min(high, value));
}
+function putInput(wasm, text) {
+ const data = encoder.encode(text);
+ if (data.length > wasm.pardes_input_capacity()) throw new Error("browser input exceeds wasm transfer buffer");
+ new Uint8Array(wasm.memory.buffer, wasm.pardes_input_ptr(), data.length).set(data);
+ return data.length;
+}
+
function download(bytes, name, type) {
if (typeof document === "undefined") return;
const url = URL.createObjectURL(new Blob([bytes], { type }));
diff --git a/test/snapshots/argv.golden b/test/snapshots/argv.golden
index 407117b7..de3282cb 100644
--- a/test/snapshots/argv.golden
+++ b/test/snapshots/argv.golden
@@ -1,6 +1,6 @@
== snap noargs grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/argv/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/argv/cwd New Newtty Del Filter
| $ echo ARGV''TTY
| ARGVTTY
| $
@@ -30,8 +30,8 @@
|
|
== snap filearg grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/argv/cwd/notes.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/argv/cwd/notes.txt Save New Newtty Del
| 3 line 3
| 4 line 4
| 5 line 5
@@ -61,8 +61,8 @@
|
|
== snap filearg-n3 grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/argv/cwd/notes.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/argv/cwd/notes.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -92,8 +92,8 @@
|
|
== snap dirarg grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/argv/cwd/sub New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/argv/cwd/sub New Newtty Del Filter
| ls
| inside.txt
|
diff --git a/test/snapshots/badutf.golden b/test/snapshots/badutf.golden
index fda9f8a7..0ad1f985 100644
--- a/test/snapshots/badutf.golden
+++ b/test/snapshots/badutf.golden
@@ -1,6 +1,6 @@
== snap badbytes grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/badutf/cwd/bad.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/badutf/cwd/bad.txt Save New Newtty Del
| 1 hello �� world
| 2 latin-1 caf� tail
| 3 truncated �� here
@@ -30,8 +30,8 @@
|
|
== snap hscroll-midglyph grid=50x30 cursor=46,2
-|New Newcol Find Grep Help Tutor Dump NextColor Deb
-| /tmp/pardes-snap/badutf/cwd/wide.txt Save New De
+|New Newcol Joincol Find Grep Help Changelog Tutor
+| /tmp/pardes-snap/badutf/cwd/wide.txt Save New Ne
| 1 日本語 日本語 日本語 日本語 日本語 tail
| 2
| 3
diff --git a/test/snapshots/boot.golden b/test/snapshots/boot.golden
index a6cbac8f..17117d6a 100644
--- a/test/snapshots/boot.golden
+++ b/test/snapshots/boot.golden
@@ -1,6 +1,6 @@
== snap boot grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/boot/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/boot/cwd New Newtty Del Filter
| ls
| hello.txt
|
@@ -30,33 +30,33 @@
|
|
== style boot
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
|1: 0-1 #ffffff,#626262, 2-79 #949494,#121212, 80-99 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-99 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-99 d,#080808,
+|4: 0-0 d,#444444, 1-99 d,#080808,
+|5: 0-0 d,#444444, 1-99 d,#080808,
+|6: 0-0 d,#444444, 1-99 d,#080808,
+|7: 0-0 d,#444444, 1-99 d,#080808,
+|8: 0-0 d,#444444, 1-99 d,#080808,
+|9: 0-0 d,#444444, 1-99 d,#080808,
+|10: 0-0 d,#444444, 1-99 d,#080808,
+|11: 0-0 d,#444444, 1-99 d,#080808,
+|12: 0-0 d,#444444, 1-99 d,#080808,
+|13: 0-0 d,#444444, 1-99 d,#080808,
+|14: 0-0 d,#444444, 1-99 d,#080808,
+|15: 0-0 d,#444444, 1-99 d,#080808,
+|16: 0-0 d,#444444, 1-99 d,#080808,
+|17: 0-0 d,#444444, 1-99 d,#080808,
+|18: 0-0 d,#444444, 1-99 d,#080808,
+|19: 0-0 d,#444444, 1-99 d,#080808,
+|20: 0-0 d,#444444, 1-99 d,#080808,
+|21: 0-0 d,#444444, 1-99 d,#080808,
+|22: 0-0 d,#444444, 1-99 d,#080808,
+|23: 0-0 d,#444444, 1-99 d,#080808,
+|24: 0-0 d,#444444, 1-99 d,#080808,
+|25: 0-0 d,#444444, 1-99 d,#080808,
+|26: 0-0 d,#444444, 1-99 d,#080808,
+|27: 0-0 d,#444444, 1-99 d,#080808,
+|28: 0-0 d,#444444, 1-99 d,#080808,
+|29: 0-0 d,#444444, 1-99 d,#080808,
diff --git a/test/snapshots/builtins.golden b/test/snapshots/builtins.golden
index 13ed8313..96cc9696 100644
--- a/test/snapshots/builtins.golden
+++ b/test/snapshots/builtins.golden
@@ -1,6 +1,6 @@
-== snap boot grid=120x60 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Del
+== snap boot grid=120x66 cursor=7,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -59,9 +59,15 @@
|
|
|
-== snap index grid=120x60 cursor=7,32
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Del
+|
+|
+|
+|
+|
+|
+== snap index grid=120x66 cursor=7,35
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -91,7 +97,10 @@
|
|
|
-| /tmp/pardes-snap/builtins/cwd/+Help New Del
+|
+|
+|
+| /tmp/pardes-snap/builtins/cwd/+Help New Newtty Del
| 1 pardes builtins, and how to run each:
| 2 SPC and its keys, a chord, a button, the
| 3 topbar - or the name, executed anywhere.
@@ -112,17 +121,20 @@
| 18 SPC a w PanelWave
| 19 SPC a z PanelZoom
| 20 SPC c d Delcol
-| 21 SPC c n Newcol topbar
-| 22 SPC d Del
-| 23 SPC f c Config
-| 24 SPC f f Find topbar
-| 25 SPC f g Grep topbar
-| 26 SPC f n New topbar
-| 27 SPC f s Save
-| 28 SPC h t Tutor topbar
-== snap index-tail grid=120x60 cursor=7,58
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Del
+| 21 SPC c j Joincol topbar
+| 22 SPC c n Newcol topbar
+| 23 SPC d Del
+| 24 SPC f c Config
+| 25 SPC f f Find topbar
+| 26 SPC f g Grep topbar
+| 27 SPC f n New topbar
+| 28 SPC f s Save
+| 29 SPC h c Changelog topbar
+| 30 SPC h t Tutor topbar
+| 31 SPC j i Forward C-i
+== snap index-tail grid=120x66 cursor=7,64
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -152,38 +164,44 @@
|
|
|
-| /tmp/pardes-snap/builtins/cwd/+Help New Del
-| 46 SPC s r Restore
-| 47 SPC t a Ascii
-| 48 SPC t b Tagbottom
-| 49 SPC t c Colors
-| 50 SPC t d Debug topbar
-| 51 SPC t i PdfTint
-| 52 SPC t l Palette
-| 53 SPC t n NextColor topbar
-| 54 SPC t p Petscii
-| 55 SPC t s PdfSections
-| 56 SPC t t ThemeSel
-| 57 SPC t w Wrap
-| 58 SPC t z PdfFit
-| 59 SPC w h Left C-w h, C-w left
-| 60 SPC w j Down C-w j, C-w down
-| 61 SPC w k Up C-w k, C-w up
-| 62 SPC w l Right C-w l, C-w right
-| 63 SPC y ClipYank
-| 64 Look enter, right-click
-| 65 Exec tab, middle-click
-| 66 Msg
-| 67 ThemeFile
-| 68 DumpThemes
-| 69 Filter
-| 70 EffectCode
-| 71 Theme
-| 72 Shell
-| 73
-== snap not-a-picker grid=120x60 cursor=7,58
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Del
+|
+|
+|
+| /tmp/pardes-snap/builtins/cwd/+Help New Newtty Del
+| 46 SPC n t Newtty
+| 47 SPC p ClipPaste
+| 48 SPC s d Dump topbar
+| 49 SPC s r Restore
+| 50 SPC t a Ascii
+| 51 SPC t b Tagbottom
+| 52 SPC t c Colors
+| 53 SPC t d Debug topbar
+| 54 SPC t i PdfTint
+| 55 SPC t l Palette
+| 56 SPC t n NextColor topbar
+| 57 SPC t p Petscii
+| 58 SPC t s PdfSections
+| 59 SPC t t ThemeSel
+| 60 SPC t w Wrap
+| 61 SPC t z PdfFit
+| 62 SPC w h Left C-w h, C-w left
+| 63 SPC w j Down C-w j, C-w down
+| 64 SPC w k Up C-w k, C-w up
+| 65 SPC w l Right C-w l, C-w right
+| 66 SPC y ClipYank
+| 67 Look enter, right-click
+| 68 Exec tab, middle-click
+| 69 Msg
+| 70 ThemeFile
+| 71 DumpThemes
+| 72 Filter
+| 73 EffectCode
+| 74 Theme
+| 75 Shell
+| 76
+== snap not-a-picker grid=120x66 cursor=7,64
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -213,38 +231,44 @@
|
|
|
-| /tmp/pardes-snap/builtins/cwd/+Help New Del
-| 46 SPC s r Restore
-| 47 SPC t a Ascii
-| 48 SPC t b Tagbottom
-| 49 SPC t c Colors
-| 50 SPC t d Debug topbar
-| 51 SPC t i PdfTint
-| 52 SPC t l Palette
-| 53 SPC t n NextColor topbar
-| 54 SPC t p Petscii
-| 55 SPC t s PdfSections
-| 56 SPC t t ThemeSel
-| 57 SPC t w Wrap
-| 58 SPC t z PdfFit
-| 59 SPC w h Left C-w h, C-w left
-| 60 SPC w j Down C-w j, C-w down
-| 61 SPC w k Up C-w k, C-w up
-| 62 SPC w l Right C-w l, C-w right
-| 63 SPC y ClipYank
-| 64 Look enter, right-click
-| 65 Exec tab, middle-click
-| 66 Msg
-| 67 ThemeFile
-| 68 DumpThemes
-| 69 Filter
-| 70 EffectCode
-| 71 Theme
-| 72 Shell
-| 73
-== snap window-group grid=120x60 cursor=7,32
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Del
+|
+|
+|
+| /tmp/pardes-snap/builtins/cwd/+Help New Newtty Del
+| 46 SPC n t Newtty
+| 47 SPC p ClipPaste
+| 48 SPC s d Dump topbar
+| 49 SPC s r Restore
+| 50 SPC t a Ascii
+| 51 SPC t b Tagbottom
+| 52 SPC t c Colors
+| 53 SPC t d Debug topbar
+| 54 SPC t i PdfTint
+| 55 SPC t l Palette
+| 56 SPC t n NextColor topbar
+| 57 SPC t p Petscii
+| 58 SPC t s PdfSections
+| 59 SPC t t ThemeSel
+| 60 SPC t w Wrap
+| 61 SPC t z PdfFit
+| 62 SPC w h Left C-w h, C-w left
+| 63 SPC w j Down C-w j, C-w down
+| 64 SPC w k Up C-w k, C-w up
+| 65 SPC w l Right C-w l, C-w right
+| 66 SPC y ClipYank
+| 67 Look enter, right-click
+| 68 Exec tab, middle-click
+| 69 Msg
+| 70 ThemeFile
+| 71 DumpThemes
+| 72 Filter
+| 73 EffectCode
+| 74 Theme
+| 75 Shell
+| 76
+== snap window-group grid=120x66 cursor=7,35
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -274,7 +298,10 @@
|
|
|
-| /tmp/pardes-snap/builtins/cwd/+Help New Del
+|
+|
+|
+| /tmp/pardes-snap/builtins/cwd/+Help New Newtty Del
| 1 pardes builtins under SPC w
| 2
| 3 SPC w h Left C-w h, C-w left
@@ -303,9 +330,12 @@
|
|
|
-== snap tutor-from-index grid=120x60 cursor=7,17
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Del
+|
+|
+|
+== snap tutor-from-index grid=120x66 cursor=7,19
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/builtins/cwd/notes.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -320,7 +350,9 @@
|
|
|
-| /Tutor Save New Del
+|
+|
+| /Tutor Save New Newtty Del
| 1
| 2 PARDES TUTOR
| 3 tmux + vi + acme, from scratch.
@@ -335,7 +367,8 @@
| 12 =================================================================
| 13
| 14 Pardes is tmux + vi + acme, made from scratch. The foundation is
-| /tmp/pardes-snap/builtins/cwd/+Help New Del
+| 15 the acme model: a pane is just text on screen. There is no separate
+| /tmp/pardes-snap/builtins/cwd/+Help New Newtty Del
| 1 pardes builtins, and how to run each:
| 2 SPC and its keys, a chord, a button, the
| 3 topbar - or the name, executed anywhere.
@@ -356,11 +389,14 @@
| 18 SPC a w PanelWave
| 19 SPC a z PanelZoom
| 20 SPC c d Delcol
-| 21 SPC c n Newcol topbar
-| 22 SPC d Del
-| 23 SPC f c Config
-| 24 SPC f f Find topbar
-| 25 SPC f g Grep topbar
-| 26 SPC f n New topbar
-| 27 SPC f s Save
-| 28 SPC h t Tutor topbar
+| 21 SPC c j Joincol topbar
+| 22 SPC c n Newcol topbar
+| 23 SPC d Del
+| 24 SPC f c Config
+| 25 SPC f f Find topbar
+| 26 SPC f g Grep topbar
+| 27 SPC f n New topbar
+| 28 SPC f s Save
+| 29 SPC h c Changelog topbar
+| 30 SPC h t Tutor topbar
+| 31 SPC j i Forward C-i
diff --git a/test/snapshots/builtins.snap b/test/snapshots/builtins.snap
index 55f858ff..ad8e27f3 100644
--- a/test/snapshots/builtins.snap
+++ b/test/snapshots/builtins.snap
@@ -15,7 +15,7 @@
# why there is one builtin here and not two: the group filter drops the
# path-less rows by itself, and the reference page is the filter's empty case.
lines notes.txt 6
-start 60 120 notes.txt
+start 66 120 notes.txt
wait 8000 notes.txt
stable 700 20000
snap boot
@@ -62,8 +62,8 @@ snap window-group
key space ?
wait 10000 SPC c n
stable 700 15000
-press middle 20 60
-release middle 20 60
+press middle 20 65
+release middle 20 65
wait 10000 PARDES TUTOR
stable 700 15000
snap tutor-from-index
diff --git a/test/snapshots/chordcut.golden b/test/snapshots/chordcut.golden
index 31f48f2a..fde5d1a5 100644
--- a/test/snapshots/chordcut.golden
+++ b/test/snapshots/chordcut.golden
@@ -1,23 +1,23 @@
== snap opened grid=120x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 line 2 f.txt g.txt f.txt g.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 line 2 f.txt g.txt
| 3 line 3
| 4 line 4
| 5 line 5
-| 6 f.txt
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
+| f.txt
|
-|
-|
-|
-|
-| /tmp/pardes-snap/chordcut/cw
-| ls
-| f.txt g.txt
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
@@ -30,25 +30,25 @@
|
|
== snap cut grid=120x30 cursor=7,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 2 f.txt g.txt f.txt g.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 2 f.txt g.txt
| 3 line 3
| 4 line 4
| 5 line 5
-| 6 f.txt
-|
-|
+| 6
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
+| f.txt
|
-|
-|
-| /tmp/pardes-snap/chordcut/cw
-| ls
-| f.txt g.txt
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
@@ -61,25 +61,25 @@
|
|
== snap copied grid=120x30 cursor=10,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 2 f.txt g.txt f.txt g.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 2 f.txt g.txt
| 3 line 3
| 4 line 4
| 5 line 5
-| 6 f.txt
-|
-|
-|
+| 6
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
+| f.txt
|
-|
-| /tmp/pardes-snap/chordcut/cw
-| ls
-| f.txt g.txt
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
@@ -92,25 +92,25 @@
|
|
== snap pointpaste grid=120x30 cursor=16,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 2 f.txt g.txt f.txt g.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 2 f.txt g.txt
| 3 line 3
| 4 line 4line
| 5 line 5
-| 6 f.txt
-|
-|
-|
-|
+| 6
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
+| f.txt
|
-| /tmp/pardes-snap/chordcut/cw
-| ls
-| f.txt g.txt
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
@@ -123,25 +123,25 @@
|
|
== snap replaced grid=120x30 cursor=11,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 2 f.txt g.txt f.txt g.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 2 f.txt g.txt
| 3 line 3
| 4 line 4line
| 5 lline 5
-| 6 f.txt
+| 6
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
+| f.txt
|
-|
-|
-|
-|
-| /tmp/pardes-snap/chordcut/cw
-| ls
-| f.txt g.txt
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
@@ -154,25 +154,25 @@
|
|
== snap cancelexec grid=120x30 cursor=25,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 2echo B''OO g.txt f.txt g.txt
| 3 line 3
| 4 line 4line
| 5 lline 5
-| 6 f.txt
-|
+| 6
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
+| f.txt
|
-|
-|
-|
-| /tmp/pardes-snap/chordcut/cw
-| ls
-| f.txt g.txt
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
@@ -185,25 +185,25 @@
|
|
== snap execafter grid=120x30 cursor=25,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 2echo B''OO g.txt f.txt g.txt
| 3 line 3
| 4 line 4line
| 5 lline 5
-| 6 f.txt
-| BOO
-|
-|
+| 6
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| f.txt g.txt
|
|
|
+| f.txt
+| BOO
|
-|
-| /tmp/pardes-snap/chordcut/cw
-| ls
-| f.txt g.txt
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
@@ -216,26 +216,25 @@
|
|
== snap cancellook grid=120x30 cursor=25,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 2echo B''OO g.txt f.txt g.txt
| 3 line 3
| 4 line 4line
| 5 lline 5
-| 6 f.txt
-| BOO
-|
-|
-|
-|
+| 6
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| f.txt g.txt
|
|
|
-| /tmp/pardes-snap/chordcut/cw
-| ls
-| f.txt g.txt
+| f.txt
+| BOO
|
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
@@ -246,27 +245,28 @@
|
|
|
-== snap lookafter grid=120x30 cursor=7,17
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt
-| 3 line 3
-| 4 line 4line
-| 5 lline 5
-| 6 f.txt
-| BOO
-|
|
+== snap lookafter grid=120x30 cursor=7,5
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ f.txt g.txt
+| /tmp/pardes-snap/chordcut/cwd/g.txt Save New Newtty Del
+| 1 line 1
+| 2 line 2
+| 3
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| f.txt g.txt
|
|
|
+| f.txt
+| BOO
|
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw
-| 1 line 1 ls
-| 2 line 2 f.txt g.txt
-| 3
|
|
|
@@ -278,88 +278,87 @@
|
|
== style chordsel
-|0: 0-56 #949494,#121212, 57-119 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-29 #949494,#121212, 30-31 #ffffff,#262626, 32-59 #949494,#121212, 60-61 #ffffff,#262626, 62-105 #949494,#121212, 106-119 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-10 #080808,#80a0ff, 11-16 #bdbdbd,#080808, 17-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-38 #bdbdbd,#080808, 39-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|16: 0-1 #ffffff,#262626, 2-29 #949494,#121212, 30-31 #ffffff,#262626, 32-59 #949494,#121212, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-119 d,#121212,
+|1: 0-1 #ffffff,#262626, 2-58 #949494,#121212, 59-59 d,#121212, 60-61 #ffffff,#262626, 62-112 #949494,#121212, 113-119 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-63 #bdbdbd,#080808, 64-119 d,#080808,
+|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-73 #bdbdbd,#080808, 74-119 d,#080808,
+|4: 0-1 #ffffff,#626262, 2-58 #949494,#121212, 59-59 d,#121212, 60-60 d,#444444, 61-119 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-10 #080808,#80a0ff, 11-12 #bdbdbd,#080808, 13-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-58 #949494,#121212, 59-59 d,#121212, 60-60 d,#444444, 61-119 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-13 #bdbdbd,#080808, 14-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|10: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|11: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|12: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|13: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|15: 0-0 d,#121212, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-58 #949494,#121212, 59-59 d,#121212, 60-60 d,#444444, 61-119 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-13 #bdbdbd,#080808, 14-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|19: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|20: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|21: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|22: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|23: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|24: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|25: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|26: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|27: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|28: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|29: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
== style clickdismiss
-|0: 0-56 #949494,#121212, 57-119 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-29 #949494,#121212, 30-31 #ffffff,#262626, 32-59 #949494,#121212, 60-61 #ffffff,#262626, 62-105 #949494,#121212, 106-119 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-13 #bdbdbd,#080808, 14-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-38 #bdbdbd,#080808, 39-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|16: 0-1 #ffffff,#262626, 2-29 #949494,#121212, 30-31 #ffffff,#262626, 32-59 #949494,#121212, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-29 d,#080808, 30-30 d,#444444, 31-31 d,#080808, 32-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-== snap ttyprobe grid=120x30 cursor=44,13
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw$ /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 $ ls ls
-| 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt
-| 3 line 3 $
-| 4 line 4line $
-| 5 lline 5 $
-| 6 $ echo B''OO
-| BOO
-| $ stty -icanon -echo; printf
-| '\x1b[?2004h\x1b[?1000h\x1b
-| [?1006h'; cat -v
-| ^[[<0;8;10M^[[<0;8;10m^[[200
-| ~line^[[201~
-|
-|
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw
-| 1 line 1 ls
-| 2 line 2 f.txt g.txt
+|0: 0-74 #949494,#121212, 75-119 d,#121212,
+|1: 0-1 #ffffff,#262626, 2-58 #949494,#121212, 59-59 d,#121212, 60-61 #ffffff,#262626, 62-112 #949494,#121212, 113-119 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-63 #bdbdbd,#080808, 64-119 d,#080808,
+|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-73 #bdbdbd,#080808, 74-119 d,#080808,
+|4: 0-1 #ffffff,#626262, 2-58 #949494,#121212, 59-59 d,#121212, 60-60 d,#444444, 61-119 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #bdbdbd,#080808, 13-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-58 #949494,#121212, 59-59 d,#121212, 60-60 d,#444444, 61-119 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-13 #bdbdbd,#080808, 14-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|10: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|11: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|12: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|13: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|15: 0-0 d,#121212, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-58 #949494,#121212, 59-59 d,#121212, 60-60 d,#444444, 61-119 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-13 #bdbdbd,#080808, 14-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|19: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|20: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|21: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|22: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|23: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|24: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|25: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|26: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|27: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|28: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|29: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+== snap ttyprobe grid=120x30 cursor=42,15
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 2echo B''OO g.txt f.txt g.txt
+| /tmp/pardes-snap/chordcut/cwd/g.txt * Save New Newtty Del
+| 1 line 1
+| 2 line 2
| 3
+|$ /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| $
+| $
+| $ echo B''OO
+| BOO
+| $ stty -icanon -echo; printf '\x1b[?2004h\x1b[?1000h\x1b[?
+| 1006h'; cat -v
+| ^[[<0;38;3M^[[<0;38;3m^[[200~line^[[201~
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
|
|
|
@@ -370,27 +369,28 @@
|
|
|
-== snap ttyprompt grid=120x30 cursor=38,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/chordcut/cw$ /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cwd New Del Filter
-| 1 line 1 $ ls ls
-| 2 2echo B''OO g.txt f.txt g.txt f.txt g.txt
-| 3 line 3 $
-| 4 line 4line $
-| 5 lline 5 $
-| 6 $ echo B''OO
-| BOO
-| $ stty -icanon -echo; printf
-| '\x1b[?2004h\x1b[?1000h\x1b
-| [?1006h'; cat -v
-| ^[[<0;8;10M^[[<0;8;10m^[[200
-| ~line^[[201~
-| $
-| $ line
-| /tmp/pardes-snap/chordcut/cw /tmp/pardes-snap/chordcut/cw
-| 1 line 1 ls
-| 2 line 2 f.txt g.txt
+|
+== snap ttyprompt grid=120x30 cursor=8,15
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/chordcut/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 2echo B''OO g.txt f.txt g.txt
+| /tmp/pardes-snap/chordcut/cwd/g.txt * Save New Newtty Del
+| 1 line 1
+| 2 line 2
| 3
+|$ /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| $ echo B''OO
+| BOO
+| $ stty -icanon -echo; printf '\x1b[?2004h\x1b[?1000h\x1b[?
+| 1006h'; cat -v
+| ^[[<0;38;3M^[[<0;38;3m^[[200~line^[[201~
+| $
+| $ line
+| /tmp/pardes-snap/chordcut/cwd New Newtty Del Filter
+| ls
+| f.txt g.txt
+|
|
|
|
diff --git a/test/snapshots/cmdword.golden b/test/snapshots/cmdword.golden
index 2ac411aa..7d694f69 100644
--- a/test/snapshots/cmdword.golden
+++ b/test/snapshots/cmdword.golden
@@ -1,6 +1,6 @@
== snap opened grid=120x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Newtty Del
| 1 @`echo ZZ''E` @`echo ZZ''L` Look p.txt @`Look .`
|
|
@@ -30,8 +30,8 @@
|
|
== snap atexec grid=120x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Newtty Del
| 1 @`echo ZZ''E` @`echo ZZ''L` Look p.txt @`Look .`
|
|
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/cmdword/cwd New Del Filter
+| /tmp/pardes-snap/cmdword/cwd New Newtty Del Filter
| echo ZZ''E
| ZZE
|
@@ -61,8 +61,8 @@
|
|
== snap atlook grid=120x30 cursor=4,21
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Newtty Del
| 1 @`echo ZZ''E` @`echo ZZ''L` Look p.txt @`Look .`
|
|
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/cmdword/cwd New Del Filter
+| /tmp/pardes-snap/cmdword/cwd New Newtty Del Filter
| echo ZZ''E
| ZZE
| echo ZZ''L
@@ -92,8 +92,8 @@
|
|
== snap lookword grid=120x30 cursor=7,10
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Newtty Del
| 1 @`echo ZZ''E` @`echo ZZ''L` Look p.txt @`Look .`
|
|
@@ -101,14 +101,14 @@
|
|
|
-| /tmp/pardes-snap/cmdword/cwd/p.txt Save New Del
+| /tmp/pardes-snap/cmdword/cwd/p.txt Save New Newtty Del
| 1 just text
|
|
|
|
|
-| /tmp/pardes-snap/cmdword/cwd New Del Filter
+| /tmp/pardes-snap/cmdword/cwd New Newtty Del Filter
| echo ZZ''E
| ZZE
| echo ZZ''L
@@ -123,8 +123,8 @@
|
|
== snap nested grid=120x30 cursor=4,23
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Newtty Del
| 1 @`echo ZZ''E` @`echo ZZ''L` Look p.txt @`Look .`
|
|
@@ -132,14 +132,14 @@
|
|
|
-| /tmp/pardes-snap/cmdword/cwd/p.txt Save New Del
+| /tmp/pardes-snap/cmdword/cwd/p.txt Save New Newtty Del
| 1 just text
|
|
|
|
|
-| /tmp/pardes-snap/cmdword/cwd New Del Filter
+| /tmp/pardes-snap/cmdword/cwd New Newtty Del Filter
| echo ZZ''E
| ZZE
| echo ZZ''L
@@ -154,8 +154,8 @@
|
|
== snap execword grid=120x30 cursor=104,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Newtty Del
| 1 @`echo ZZ''E` @`echo ZZ''L` Look p.txt @`Look .`
|
|
@@ -163,14 +163,14 @@
|
|
|
-| /tmp/pardes-snap/cmdword/cwd/p.txt Save New Del
+| /tmp/pardes-snap/cmdword/cwd/p.txt Save New Newtty Del
| 1 just text
|
|
|
|
|
-| /tmp/pardes-snap/cmdword/cwd New Del Filter Exec
+| /tmp/pardes-snap/cmdword/cwd New Newtty Del Filter Exec
| echo ZZ''E
| ZZE
| echo ZZ''L
@@ -185,8 +185,8 @@
|
|
== snap tagcmd grid=120x30 cursor=118,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cmdword/cwd/cmds.txt Save New Newtty Del
| 1 @`echo ZZ''E` @`echo ZZ''L` Look p.txt @`Look .`
|
|
@@ -194,14 +194,14 @@
|
|
|
-| /tmp/pardes-snap/cmdword/cwd/p.txt Save New Del
+| /tmp/pardes-snap/cmdword/cwd/p.txt Save New Newtty Del
| 1 just text
|
|
|
|
|
-| /tmp/pardes-snap/cmdword/cwd New Del Filter Exec @`echo ZZ''T`
+| /tmp/pardes-snap/cmdword/cwd New Newtty Del Filter Exec @`echo ZZ''T`
| echo ZZ''E
| ZZE
| echo ZZ''L
diff --git a/test/snapshots/cornerdrag-left.golden b/test/snapshots/cornerdrag-left.golden
index 68440340..2d836b77 100644
--- a/test/snapshots/cornerdrag-left.golden
+++ b/test/snapshots/cornerdrag-left.golden
@@ -1,10 +1,10 @@
== snap right-split grid=100x30 cursor=54,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag-left/cwd New Del Fil /tmp/pardes-snap/cornerdrag-left/cwd New Del Fil
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag-left/cwd New Newtty /tmp/pardes-snap/cornerdrag-left/cwd New Newtty
| ls ls
| w.txt w.txt
|
-| /tmp/pardes-snap/cornerdrag-left/cwd New Del Fil
+| /tmp/pardes-snap/cornerdrag-left/cwd New Newtty
| ls
| w.txt
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/cornerdrag-left/cwd New Del Fil
+| /tmp/pardes-snap/cornerdrag-left/cwd New Newtty
| ls
| w.txt
|
@@ -30,12 +30,12 @@
|
|
== snap hover-corner grid=100x30 cursor=54,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag-left/cwd New Del Fi╎ /tmp/pardes-snap/cornerdrag-left/cwd New Del Fil
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag-left/cwd New Newtty╎ /tmp/pardes-snap/cornerdrag-left/cwd New Newtty
| ls ╎ ls
| w.txt ╎ w.txt
| ╎╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
-| ╎ /tmp/pardes-snap/cornerdrag-left/cwd New Del Fil
+| ╎ /tmp/pardes-snap/cornerdrag-left/cwd New Newtty
| ╎ ls
| ╎ w.txt
| ╎
@@ -46,7 +46,7 @@
| ╎
| ╎
| ╎
-| /tmp/pardes-snap/cornerdrag-left/cwd New Del Fi╎
+| /tmp/pardes-snap/cornerdrag-left/cwd New Newtty╎
| ls ╎
| w.txt ╎
| ╎
@@ -61,12 +61,12 @@
| ╎
| ╎
== snap hover-left-corner grid=100x30 cursor=54,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag-left/cwd New Del Fi╎ /tmp/pardes-snap/cornerdrag-left/cwd New Del Fil
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag-left/cwd New Newtty╎ /tmp/pardes-snap/cornerdrag-left/cwd New Newtty
| ls ╎ ls
| w.txt ╎ w.txt
| ╎
-| ╎ /tmp/pardes-snap/cornerdrag-left/cwd New Del Fil
+| ╎ /tmp/pardes-snap/cornerdrag-left/cwd New Newtty
| ╎ ls
| ╎ w.txt
| ╎
@@ -77,7 +77,7 @@
| ╎
| ╎
|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
-| /tmp/pardes-snap/cornerdrag-left/cwd New Del Fi╎
+| /tmp/pardes-snap/cornerdrag-left/cwd New Newtty╎
| ls ╎
| w.txt ╎
| ╎
@@ -92,12 +92,12 @@
| ╎
| ╎
== snap corner-drag grid=100x30 cursor=54,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag╎left/cwd New Del Fil /tmp/pardes-snap/cornerdrag-left/cwd New Del Fil
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag╎left/cwd New Newtty /tmp/pardes-snap/cornerdrag-left/cwd New Newtty
| ls ╎ ls
| w.txt ╎ w.txt
| ╎
-| ╎ /tmp/pardes-snap/cornerdrag-left/cwd New Del Fil
+| ╎ /tmp/pardes-snap/cornerdrag-left/cwd New Newtty
| ╎ ls
| ╎ w.txt
| ╎
@@ -108,7 +108,7 @@
| ╎
| ╎
| ╎
-| /tmp/pardes-snap/cornerdrag╎left/cwd New Del Fil
+| /tmp/pardes-snap/cornerdrag╎left/cwd New Newtty
| ls ╎
| w.txt ╎
| ╎
@@ -123,8 +123,8 @@
| ╎
| ╎
== snap corner-done grid=100x30 cursor=34,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag- /tmp/pardes-snap/cornerdrag-left/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag- /tmp/pardes-snap/cornerdrag-left/cwd New Newtty Del Filter
| ls ls
| w.txt w.txt
|
@@ -135,7 +135,7 @@
|
|
|
-| /tmp/pardes-snap/cornerdrag-left/cwd New Del Filter
+| /tmp/pardes-snap/cornerdrag-left/cwd New Newtty Del Filter
| ls
| w.txt
|
diff --git a/test/snapshots/cornerdrag.golden b/test/snapshots/cornerdrag.golden
index 02e1c2b2..0e3a68b9 100644
--- a/test/snapshots/cornerdrag.golden
+++ b/test/snapshots/cornerdrag.golden
@@ -1,6 +1,6 @@
== snap hover-corner grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag/cwd New Del Filter ╎ /tmp/pardes-snap/cornerdrag/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag/cwd New Newtty Del ╎ /tmp/pardes-snap/cornerdrag/cwd New Newtty Del F
| ls ╎ ls
| w.txt ╎ w.txt
| ╎
@@ -15,7 +15,7 @@
| ╎
| ╎
|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
-| /tmp/pardes-snap/cornerdrag/cwd New Del Filter ╎
+| /tmp/pardes-snap/cornerdrag/cwd New Newtty Del ╎
| ls ╎
| w.txt ╎
| ╎
@@ -30,8 +30,8 @@
| ╎
| ╎
== snap edge-drag grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag╎cwd New Del Filter /tmp/pardes-snap/cornerdrag/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag╎cwd New Newtty Del F /tmp/pardes-snap/cornerdrag/cwd New Newtty Del F
| ls ╎ ls
| w.txt ╎ w.txt
| ╎
@@ -46,7 +46,7 @@
| ╎
| ╎
| ╎
-| /tmp/pardes-snap/cornerdrag╎cwd New Del Filter
+| /tmp/pardes-snap/cornerdrag╎cwd New Newtty Del F
| ls ╎
| w.txt ╎
| ╎
@@ -61,8 +61,8 @@
| ╎
| ╎
== snap edge-done grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag/ /tmp/pardes-snap/cornerdrag/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag/ /tmp/pardes-snap/cornerdrag/cwd New Newtty Del Filter
| ls ls
| w.txt w.txt
|
@@ -92,8 +92,8 @@
|
|
== snap corner-drag grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag/ /tmp/pardes-snap/cornerdrag╎cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag/ /tmp/pardes-snap/cornerdrag╎cwd New Newtty Del Filter
| ls ls ╎
| w.txt w.txt ╎
| ╎
@@ -123,15 +123,15 @@
| ╎
| ╎
== snap corner-done grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag/cwd New Del Filter /tmp/pardes-snap/cornerdrag/cwd New De
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag/cwd New Newtty Del Filter /tmp/pardes-snap/cornerdrag/cwd New Ne
| ls ls
| w.txt w.txt
|
|
|
|
-| /tmp/pardes-snap/cornerdrag/cwd New Del Filter
+| /tmp/pardes-snap/cornerdrag/cwd New Newtty Del Filter
| ls
| w.txt
|
@@ -154,15 +154,15 @@
|
|
== snap clamp-x grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag/cwd New Del Filter /tmp/pardes-snap/cornerdrag/╎wd New De
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag/cwd New Newtty Del Filter /tmp/pardes-snap/cornerdrag/╎wd New Ne
| ls ls ╎
| w.txt w.txt ╎
| ╎
| ╎
| ╎
| ╎
-| /tmp/pardes-snap/cornerdrag/cwd New Del Filter ╎
+| /tmp/pardes-snap/cornerdrag/cwd New Newtty Del Filter ╎
| ls ╎
| w.txt ╎
| ╎
@@ -185,15 +185,15 @@
| ╎
| ╎
== snap clamp-y grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag/cwd New Del Filter ╎ /tmp/pardes-snap/cornerdrag/cwd New De
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag/cwd New Newtty Del Filter ╎ /tmp/pardes-snap/cornerdrag/cwd New Ne
| ls ╎ ls
| w.txt ╎ w.txt
| ╎
| ╎
| ╎
| ╎
-| /tmp/pardes-snap/cornerdrag/cwd New Del Filter ╎
+| /tmp/pardes-snap/cornerdrag/cwd New Newtty Del Filter ╎
| ls ╎
| w.txt ╎
| ╎
@@ -216,8 +216,8 @@
|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
| ╎
== snap clamp-done grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cornerdrag/cwd New Del Filter /tmp/pardes-snap/cornerdrag/cwd New De
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cornerdrag/cwd New Newtty Del Filter /tmp/pardes-snap/cornerdrag/cwd New Ne
| ls ls
| w.txt w.txt
|
@@ -245,4 +245,4 @@
|
|
|
-| /tmp/pardes-snap/cornerdrag/cwd New Del Filter
+| /tmp/pardes-snap/cornerdrag/cwd New Newtty Del Filter
diff --git a/test/snapshots/cursorline.golden b/test/snapshots/cursorline.golden
index 4a76e25e..68a74081 100644
--- a/test/snapshots/cursorline.golden
+++ b/test/snapshots/cursorline.golden
@@ -1,27 +1,27 @@
== snap top grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cursorline/cwd/cur. /tmp/pardes-snap/cursorline/cwd New /tmp/pardes-snap/cursorline/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 line 2 cur.txt cur.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cursorline/cwd/cur.txt Save New Newtty Del /tmp/pardes-snap/cursorline/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 line 2 cur.txt
| 3 line 3
| 4 line 4
| 5 line 5
-| 6 line 6 cur.txt
-| 7 line 7
-| 8 line 8
-| 9 line 9
-| 10 line 10
-| 11 line 11
-| 12 line 12
-| 13 line 13
-| 14 line 14
-| 15 line 15 /tmp/pardes-snap/cursorline/cwd New
-| 16 line 16 ls
-| 17 line 17 cur.txt
-| 18 line 18
-| 19 line 19
-| 20 line 20
-| 21
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/cursorline/cwd New Newtty Del Filter
+| ls
+| cur.txt
+|
+|
+|
+| cur.txt
+|
+| /tmp/pardes-snap/cursorline/cwd New Newtty Del Filter
+| ls
+| cur.txt
+|
+|
+|
+|
|
|
|
@@ -30,60 +30,60 @@
|
|
== style top
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-48 #bdbdbd,#080808, 49-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-60 #949494,#121212, 61-74 d,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-83 #bdbdbd,#080808, 84-149 d,#080808,
+|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-60 #949494,#121212, 61-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-60 #949494,#121212, 61-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
== snap down3 grid=150x30 cursor=7,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/cursorline/cwd/cur. /tmp/pardes-snap/cursorline/cwd New /tmp/pardes-snap/cursorline/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 line 2 cur.txt cur.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/cursorline/cwd/cur.txt Save New Newtty Del /tmp/pardes-snap/cursorline/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 line 2 cur.txt
| 3 line 3
| 4 line 4
| 5 line 5
-| 6 line 6 cur.txt
-| 7 line 7
-| 8 line 8
-| 9 line 9
-| 10 line 10
-| 11 line 11
-| 12 line 12
-| 13 line 13
-| 14 line 14
-| 15 line 15 /tmp/pardes-snap/cursorline/cwd New
-| 16 line 16 ls
-| 17 line 17 cur.txt
-| 18 line 18
-| 19 line 19
-| 20 line 20
-| 21
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/cursorline/cwd New Newtty Del Filter
+| ls
+| cur.txt
+|
+|
+|
+| cur.txt
+|
+| /tmp/pardes-snap/cursorline/cwd New Newtty Del Filter
+| ls
+| cur.txt
+|
+|
+|
+|
|
|
|
@@ -92,33 +92,33 @@
|
|
== style down3
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-48 #bdbdbd,#080808, 49-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-60 #949494,#121212, 61-74 d,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-83 #bdbdbd,#080808, 84-149 d,#080808,
+|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-60 #949494,#121212, 61-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-60 #949494,#121212, 61-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
diff --git a/test/snapshots/doccol.golden b/test/snapshots/doccol.golden
index e6be5fea..4b76c695 100644
--- a/test/snapshots/doccol.golden
+++ b/test/snapshots/doccol.golden
@@ -1,6 +1,6 @@
== snap boot grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/doccol/cwd/a.txt Save New Del /tmp/pardes-snap/doccol/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/doccol/cwd/a.txt Save New Newtt /tmp/pardes-snap/doccol/cwd New Newtty Del Filte
| 1 AAA ls
| a.txt b.txt c.txt
|
@@ -30,8 +30,8 @@
|
|
== snap two-docs grid=100x30 cursor=7,17
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/doccol/cwd/a.txt Save New Del /tmp/pardes-snap/doccol/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/doccol/cwd/a.txt Save New Newtt /tmp/pardes-snap/doccol/cwd New Newtty Del Filte
| 1 AAA ls
| a.txt b.txt c.txt
|
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/doccol/cwd/b.txt Save New Del
+| /tmp/pardes-snap/doccol/cwd/b.txt Save New Newtt
| 1 BBB
| 2 B-TWO
|
@@ -61,8 +61,8 @@
|
|
== snap moved grid=100x30 cursor=57,20
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/doccol/cwd/a.txt Save New Del /tmp/pardes-snap/doccol/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/doccol/cwd/a.txt Save New Newtt /tmp/pardes-snap/doccol/cwd New Newtty Del Filte
| 1 AAA ls
| a.txt b.txt c.txt
|
@@ -80,7 +80,7 @@
|
|
|
-| /tmp/pardes-snap/doccol/cwd/b.txt Save New Del
+| /tmp/pardes-snap/doccol/cwd/b.txt Save New Newtt
| 1 BBB
| 2 B-TWO
|
@@ -92,8 +92,8 @@
|
|
== snap worked grid=100x30 cursor=59,21
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/doccol/cwd/a.txt Save New Del /tmp/pardes-snap/doccol/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/doccol/cwd/a.txt Save New Newtt /tmp/pardes-snap/doccol/cwd New Newtty Del Filte
| 1 AAA ls
| a.txt b.txt c.txt
|
@@ -111,7 +111,7 @@
|
|
|
-| /tmp/pardes-snap/doccol/cwd/b.txt Save New Del
+| /tmp/pardes-snap/doccol/cwd/b.txt Save New Newtt
| 1 BBB
| 2 B-TWO
|
@@ -123,8 +123,8 @@
|
|
== snap third grid=100x30 cursor=57,26
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/doccol/cwd/a.txt Save New Del /tmp/pardes-snap/doccol/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/doccol/cwd/a.txt Save New Newtt /tmp/pardes-snap/doccol/cwd New Newtty Del Filte
| 1 AAA ls
| a.txt b.txt c.txt
|
@@ -142,13 +142,13 @@
|
|
|
-| /tmp/pardes-snap/doccol/cwd/b.txt Save New Del
+| /tmp/pardes-snap/doccol/cwd/b.txt Save New Newtt
| 1 BBB
| 2 B-TWO
|
|
|
-| /tmp/pardes-snap/doccol/cwd/c.txt Save New Del
+| /tmp/pardes-snap/doccol/cwd/c.txt Save New Newtt
| 1 CCC
|
|
diff --git a/test/snapshots/doccol.snap b/test/snapshots/doccol.snap
index 21c136d9..6b722450 100644
--- a/test/snapshots/doccol.snap
+++ b/test/snapshots/doccol.snap
@@ -8,13 +8,16 @@ file a.txt AAA
file b.txt BBB\nB-TWO
file c.txt CCC
# a FILE boots alone (and always outranked -n), so the shell whose ls output
-# the looks below are clicked in is opened here: SPC c n puts it in a column of
-# its own on the right — the layout the boot used to hand over — and SPC w h
-# comes back to a.txt, which is where the boot left focus
+# the looks below are clicked in is opened here: Alt-n stacks it below a.txt
+# and Alt-c moves it into a column of its own on the right — the layout the
+# boot used to hand over — and SPC w h comes back to a.txt, which is where the
+# boot left focus. (`New`/`Newcol` open an empty +New scratch now, not a
+# shell, so the shell has to be asked for by name.)
start 30 100 a.txt
wait 8000 AAA
stable 700 20000
-key space c n
+key a-n
+key a-c
wait 8000 c.txt
stable 700 20000
key space w h
diff --git a/test/snapshots/dump.golden b/test/snapshots/dump.golden
index 75ce0434..6186b8d7 100644
--- a/test/snapshots/dump.golden
+++ b/test/snapshots/dump.golden
@@ -4,13 +4,13 @@
.version = 1,
.screen = .{ .cols = 100, .rows = 30 },
.active = 0,
- .topbar = "New Newcol Find Grep Help Tutor Dump NextColor Debug Kill",
+ .topbar = "New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill",
.theme = "helix",
.columns = .{ .{ .weight = 1, .panes = .{ 0, 1 } }, .{ .weight = 1, .panes = .{2} } },
.panes = .{
.{
.kind = .terminal,
- .tag = "/tmp/pardes-snap/dump/cwd New Del Filter",
+ .tag = "/tmp/pardes-snap/dump/cwd New Newtty Del Filter",
.body = "ls\nd.txt\n\n\n\n typed-marker\n\n\n\n\n\n\n\n",
.scroll = 0,
.cols = 48,
@@ -28,7 +28,7 @@
},
.{
.kind = .terminal,
- .tag = "/tmp/pardes-snap/dump/cwd New Del Filter",
+ .tag = "/tmp/pardes-snap/dump/cwd New Newtty Del Filter",
.body = "ls\nd.txt\n\n\n\n\n\n\n\n\n\n\n",
.scroll = 0,
.cols = 48,
@@ -46,7 +46,7 @@
},
.{
.kind = .terminal,
- .tag = "/tmp/pardes-snap/dump/cwd New Del Filter",
+ .tag = "/tmp/pardes-snap/dump/cwd New Newtty Del Filter",
.body = "ls\nd.txt\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
.scroll = 0,
.cols = 48,
diff --git a/test/snapshots/dump.snap b/test/snapshots/dump.snap
index 4a63f8c6..b231bce8 100644
--- a/test/snapshots/dump.snap
+++ b/test/snapshots/dump.snap
@@ -13,7 +13,7 @@ text typed-marker
key esc
settle 100
stable 400 5000
-press middle 33 1
-release middle 33 1
+press middle 52 1
+release middle 52 1
stable 600 8000
snapfile dump $DUMP
diff --git a/test/snapshots/edit.golden b/test/snapshots/edit.golden
index d3f0d25f..483048ca 100644
--- a/test/snapshots/edit.golden
+++ b/test/snapshots/edit.golden
@@ -1,6 +1,6 @@
== snap inserted grid=100x30 cursor=16,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/edit/cwd New Del Filter /tmp/pardes-snap/edit/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/edit/cwd New Newtty Del Filter /tmp/pardes-snap/edit/cwd New Newtty Del Filter
| ls ls
| e.txt e.txt
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/edit/cwd New Del Filter
+| /tmp/pardes-snap/edit/cwd New Newtty Del Filter
| ls
| e.txt
|
@@ -30,33 +30,33 @@
|
|
== style inserted
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-41 #949494,#121212, 42-49 d,#121212, 50-51 #ffffff,#262626, 52-91 #949494,#121212, 92-99 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-15 #bdbdbd,#080808, 16-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|16: 0-1 #ffffff,#262626, 2-41 #949494,#121212, 42-49 d,#121212, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-48 #949494,#121212, 49-49 d,#121212, 50-51 #ffffff,#262626, 52-98 #949494,#121212, 99-99 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-53 #bdbdbd,#080808, 54-99 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-56 #bdbdbd,#080808, 57-99 d,#080808,
+|4: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|5: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|6: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|7: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|8: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-15 #bdbdbd,#080808, 16-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|10: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|11: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|12: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|13: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|14: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|15: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-48 #949494,#121212, 49-49 d,#121212, 50-50 d,#444444, 51-99 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|19: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|20: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|21: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|22: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|23: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|24: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|25: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|26: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|27: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|28: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|29: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
diff --git a/test/snapshots/exec-bigdrag.golden b/test/snapshots/exec-bigdrag.golden
index bd15a780..d2860845 100644
--- a/test/snapshots/exec-bigdrag.golden
+++ b/test/snapshots/exec-bigdrag.golden
@@ -1,6 +1,6 @@
== snap alive grid=200x60 cursor=119,37
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/exec-bigdrag/cwd New Del Filter /tmp/pardes-snap/exec-bigdrag/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/exec-bigdrag/cwd New Newtty Del Filter /tmp/pardes-snap/exec-bigdrag/cwd New Newtty Del Filter
| ls bash: line: command not found
| big.txt 4line 2705line 2706line 2707line 2708line 2709line 2710line 2711line 2712line 2713line 2714lin
| bash: 4line: command not found
@@ -30,7 +30,7 @@
| bash: 2835line: command not found
| 2846line 2847line 2848line 2849line 2850line 2851line 2852line 2853line 2854line 2855line 285
| bash: 2846line: command not found
-| /tmp/pardes-snap/exec-bigdrag/cwd New Del Filter e 2857line 2858line 2859line 2860line 2861line 2862line 2863line 2864line 2865line 2866line 28
+| /tmp/pardes-snap/exec-bigdrag/cwd New Newtty Del Filter e 2857line 2858line 2859line 2860line 2861line 2862line 2863line 2864line 2865line 2866line 28
| ls bash: e: command not found
| big.txt ne 2868line 2869line 2870line 2871line 2872line 2873line 2874line 2875line 2876line 2877line 2
| bash: ne: command not found
diff --git a/test/snapshots/exec.golden b/test/snapshots/exec.golden
index 2ab01cc3..793128c0 100644
--- a/test/snapshots/exec.golden
+++ b/test/snapshots/exec.golden
@@ -1,6 +1,6 @@
== snap exec grid=100x30 cursor=16,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/exec/cwd New Del Filter /tmp/pardes-snap/exec/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/exec/cwd New Newtty Del Filter /tmp/pardes-snap/exec/cwd New Newtty Del Filter
| ls ls
| e.txt e.txt
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/exec/cwd New Del Filter
+| /tmp/pardes-snap/exec/cwd New Newtty Del Filter
| ls
| e.txt
|
@@ -30,8 +30,8 @@
|
|
== snap kept grid=100x30 cursor=6,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/exec/cwd New Del Filter /tmp/pardes-snap/exec/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/exec/cwd New Newtty Del Filter /tmp/pardes-snap/exec/cwd New Newtty Del Filter
| ZZARG ls
| ./c.sh e.txt
|
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/exec/cwd New Del Filter
+| /tmp/pardes-snap/exec/cwd New Newtty Del Filter
| ls
| e.txt
|
@@ -61,8 +61,8 @@
|
|
== snap chord grid=100x30 cursor=6,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/exec/cwd New Del Filter /tmp/pardes-snap/exec/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/exec/cwd New Newtty Del Filter /tmp/pardes-snap/exec/cwd New Newtty Del Filter
| ZZARG ls
| ./c.sh e.txt
|
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/exec/cwd New Del Filter
+| /tmp/pardes-snap/exec/cwd New Newtty Del Filter
| ls
| e.txt
|
@@ -91,26 +91,26 @@
|
|
|
-== snap deleted grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/exec/cwd New Del Filter /tmp/pardes-snap/exec/cwd New Del Filter
-| ls ls
-| e.txt e.txt
-|
-|
-|
-|
-|
-|
-|
-|
-|
+== snap deleted grid=100x30 cursor=4,13
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/exec/cwd New Newtty Del Filter /tmp/pardes-snap/exec/cwd New Newtty Del Filter
+| ZZARG ls
+| ./c.sh e.txt
|
|
|
+| echo MID''OK
+| CHORDARG:ZZARG
|
+|$ /tmp/pardes-snap/exec/cwd New Newtty Del Filter
+| $ ls
+| c.sh e.txt
+| $
|
|
+| /tmp/pardes-snap/exec/cwd New Newtty Del Filter
+| ls
+| e.txt
|
|
|
diff --git a/test/snapshots/fileedit.golden b/test/snapshots/fileedit.golden
index fd3b7304..6b9a2b07 100644
--- a/test/snapshots/fileedit.golden
+++ b/test/snapshots/fileedit.golden
@@ -1,27 +1,27 @@
== snap edited grid=150x30 cursor=17,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fileedit/cwd/f.txt /tmp/pardes-snap/fileedit/cwd New D /tmp/pardes-snap/fileedit/cwd New Del Filter
-| 1 liEDIT''MEne 1 ls ls
-| 2 line 2 f.txt f.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fileedit/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/fileedit/cwd New Newtty Del Filter
+| 1 liEDIT''MEne 1 ls
+| 2 line 2 f.txt
| 3 line 3
| 4 line 4
| 5 line 5
-| 6 line 6 f.txt
-| 7 line 7
-| 8 line 8
-| 9 line 9
-| 10 line 10
-| 11 line 11
-| 12 line 12
-| 13 line 13
-| 14 line 14
-| 15 line 15 /tmp/pardes-snap/fileedit/cwd New D
-| 16 line 16 ls
-| 17 line 17 f.txt
-| 18 line 18
-| 19 line 19
-| 20 line 20
-| 21
+| 6 line 6
+| /tmp/pardes-snap/fileedit/cwd New Newtty Del Filter
+| ls
+| f.txt
+|
+|
+|
+| f.txt
+|
+| /tmp/pardes-snap/fileedit/cwd New Newtty Del Filter
+| ls
+| f.txt
+|
+|
+|
+|
|
|
|
@@ -30,28 +30,28 @@
|
|
== snap deleted grid=150x30 cursor=7,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fileedit/cwd/f.txt /tmp/pardes-snap/fileedit/cwd New D /tmp/pardes-snap/fileedit/cwd New Del Filter
-| 1 liEDIT''MEne 1 ls ls
-| 2 line 3 f.txt f.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fileedit/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/fileedit/cwd New Newtty Del Filter
+| 1 liEDIT''MEne 1 ls
+| 2 line 3 f.txt
| 3 line 4
| 4 line 5
| 5 line 6
-| 6 line 7 f.txt
-| 7 line 8
-| 8 line 9
-| 9 line 10
-| 10 line 11
-| 11 line 12
-| 12 line 13
-| 13 line 14
-| 14 line 15
-| 15 line 16 /tmp/pardes-snap/fileedit/cwd New D
-| 16 line 17 ls
-| 17 line 18 f.txt
-| 18 line 19
-| 19 line 20
-| 20
+| 6 line 7
+| /tmp/pardes-snap/fileedit/cwd New Newtty Del Filter
+| ls
+| f.txt
+|
+|
+|
+| f.txt
+|
+| /tmp/pardes-snap/fileedit/cwd New Newtty Del Filter
+| ls
+| f.txt
+|
+|
+|
|
|
|
@@ -61,29 +61,29 @@
|
|
== snap undone grid=150x30 cursor=13,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fileedit/cwd/f.txt /tmp/pardes-snap/fileedit/cwd New D /tmp/pardes-snap/fileedit/cwd New Del Filter
-| 1 liEDIT''MEne 1 ls ls
-| 2 line 2 f.txt f.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fileedit/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/fileedit/cwd New Newtty Del Filter
+| 1 liEDIT''MEne 1 ls
+| 2 line 2 f.txt
| 3 line 3
| 4 line 4
| 5 line 5
-| 6 line 6 f.txt
-| 7 line 7
-| 8 line 8
-| 9 line 9
-| 10 line 10
-| 11 line 11
-| 12 line 12
-| 13 line 13
-| 14 line 14
-| 15 line 15 /tmp/pardes-snap/fileedit/cwd New D
-| 16 line 16 ls
-| 17 line 17 f.txt
-| 18 line 18
-| 19 line 19
-| 20 line 20
-| 21
+| 6 line 6
+| /tmp/pardes-snap/fileedit/cwd New Newtty Del Filter
+| ls
+| f.txt
+|
+|
+|
+| f.txt
+|
+| /tmp/pardes-snap/fileedit/cwd New Newtty Del Filter
+| ls
+| f.txt
+|
+|
+|
+|
|
|
|
diff --git a/test/snapshots/filewatch.golden b/test/snapshots/filewatch.golden
index 5e34843c..952cb387 100644
--- a/test/snapshots/filewatch.golden
+++ b/test/snapshots/filewatch.golden
@@ -1,13 +1,12 @@
-== snap edited grid=150x30 cursor=15,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/filewatch/cwd/w.txt /tmp/pardes-snap/filewatch/cwd New /tmp/pardes-snap/filewatch/cwd New Del Filter
-| 1 liMYEDITne 1 ls ls
-| 2 line 2 sub w.txt sub w.txt
-| 3 /tmp/pardes-snap/filewatch/cwd↩
-| /sub/s.txt
+== snap edited grid=210x30 cursor=15,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/filewatch/cwd/w.txt * Save New Newtty Del /tmp/pardes-snap/filewatch/cwd New Newtty Del Filter
+| 1 liMYEDITne 1 ls
+| 2 line 2 sub w.txt
+| 3 /tmp/pardes-snap/filewatch/cwd/sub/s.txt
| 4 line 4
-| 5 line 5 w.txt
-| 6 line 6
+| 5 line 5
+| 6 line 6 w.txt
| 7 line 7
| 8 line 8
| 9 line 9
@@ -15,9 +14,10 @@
| 11 line 11
| 12 line 12
| 13
-| /tmp/pardes-snap/filewatch/cwd/sub/s /tmp/pardes-snap/filewatch/cwd New
-| 1 line 1 ls
-| 2 line 2 sub w.txt
+|
+| /tmp/pardes-snap/filewatch/cwd/sub/s.txt Save New Newtty Del
+| 1 line 1
+| 2 line 2
| 3 line 3
| 4 line 4
| 5 line 5
@@ -29,15 +29,15 @@
|
|
|
-== snap reloaded grid=150x30 cursor=15,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/filewatch/cwd/w.txt /tmp/pardes-snap/filewatch/cwd New /tmp/pardes-snap/filewatch/cwd New Del Filter
-| 1 EXTERNAL ls ls
-| 2 sub w.txt sub w.txt
+== snap reloaded grid=210x30 cursor=15,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/filewatch/cwd/w.txt Save New Newtty Del /tmp/pardes-snap/filewatch/cwd New Newtty Del Filter
+| 1 EXTERNAL ls
+| 2 sub w.txt
|
|
|
-| w.txt
+| w.txt
|
|
|
@@ -45,10 +45,10 @@
|
|
|
-| --:--:-- reloaded /tmp/pardes-snap/
-| /tmp/pardes-snap/filewatch/cwd/sub/s /tmp/pardes-snap/filewatch/cwd New
-| 1 line 1 ls
-| 2 line 2 sub w.txt
+| --:--:-- reloaded /tmp/pardes-snap/filewatch/cwd/w.txt
+| /tmp/pardes-snap/filewatch/cwd/sub/s.txt Save New Newtty Del
+| 1 line 1
+| 2 line 2
| 3 line 3
| 4 line 4
| 5 line 5
@@ -60,15 +60,15 @@
|
|
|
-== snap reloaded_sub grid=150x30 cursor=15,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/filewatch/cwd/w.txt /tmp/pardes-snap/filewatch/cwd New /tmp/pardes-snap/filewatch/cwd New Del Filter
-| 1 EXTERNAL ls ls
-| 2 sub w.txt sub w.txt
+== snap reloaded_sub grid=210x30 cursor=15,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/filewatch/cwd/w.txt Save New Newtty Del /tmp/pardes-snap/filewatch/cwd New Newtty Del Filter
+| 1 EXTERNAL ls
+| 2 sub w.txt
|
|
|
-| w.txt
+| w.txt
|
|
|
@@ -76,10 +76,10 @@
|
|
|
-| --:--:-- reloaded /tmp/pardes-snap/
-| /tmp/pardes-snap/filewatch/cwd/sub/s /tmp/pardes-snap/filewatch/cwd New
-| 1 RENAMED ls
-| 2 sub w.txt
+| --:--:-- reloaded /tmp/pardes-snap/filewatch/cwd/w.txt
+| /tmp/pardes-snap/filewatch/cwd/sub/s.txt Save New Newtty Del
+| 1 RENAMED
+| 2
|
|
|
@@ -90,17 +90,16 @@
|
|
|
-| --:--:-- reloaded /tmp/pardes-snap/
-== snap undone grid=150x30 cursor=15,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/filewatch/cwd/w.txt /tmp/pardes-snap/filewatch/cwd New /tmp/pardes-snap/filewatch/cwd New Del Filter
-| 1 liMYEDITne 1 ls ls
-| 2 line 2 sub w.txt sub w.txt
-| 3 /tmp/pardes-snap/filewatch/cwd↩
-| /sub/s.txt
+| --:--:-- reloaded /tmp/pardes-snap/filewatch/cwd/sub/s.txt
+== snap undone grid=210x30 cursor=15,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/filewatch/cwd/w.txt * Save New Newtty Del /tmp/pardes-snap/filewatch/cwd New Newtty Del Filter
+| 1 liMYEDITne 1 ls
+| 2 line 2 sub w.txt
+| 3 /tmp/pardes-snap/filewatch/cwd/sub/s.txt
| 4 line 4
-| 5 line 5 w.txt
-| 6 line 6
+| 5 line 5
+| 6 line 6 w.txt
| 7 line 7
| 8 line 8
| 9 line 9
@@ -108,9 +107,10 @@
| 11 line 11
| 12 line 12
| 13
-| /tmp/pardes-snap/filewatch/cwd/sub/s /tmp/pardes-snap/filewatch/cwd New
-| 1 RENAMED ls
-| 2 sub w.txt
+|
+| /tmp/pardes-snap/filewatch/cwd/sub/s.txt Save New Newtty Del
+| 1 RENAMED
+| 2
|
|
|
diff --git a/test/snapshots/filewatch.snap b/test/snapshots/filewatch.snap
index 6f1f2976..25862cb7 100644
--- a/test/snapshots/filewatch.snap
+++ b/test/snapshots/filewatch.snap
@@ -18,7 +18,7 @@
dirmk sub
file w.txt line 1\nline 2\n/tmp/pardes-snap/filewatch/cwd/sub/s.txt\nline 4\nline 5\nline 6\nline 7\nline 8\nline 9\nline 10\nline 11\nline 12\n
lines sub/s.txt 8
-start 30 150 -n 3
+start 30 210 -n 1
wait 8000 w.txt
stable 700 20000
# open w.txt as a file pane: type the name into the shell, right-click it
diff --git a/test/snapshots/find.golden b/test/snapshots/find.golden
index 30f9a2ab..18de5fa7 100644
--- a/test/snapshots/find.golden
+++ b/test/snapshots/find.golden
@@ -1,6 +1,6 @@
== snap group grid=120x40 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del
| 1 Find
|
|
@@ -40,8 +40,8 @@
|
| SPC f
== snap armed grid=120x40 cursor=9,39
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del
| 1 Find
|
|
@@ -81,8 +81,8 @@
|
| Find /
== snap typing grid=120x40 cursor=12,39
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del
| 1 Find
|
|
@@ -122,8 +122,8 @@
|
| Find /zqm
== snap results grid=120x40 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del
| 1 Find
|
|
@@ -158,13 +158,13 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 1 sub/ZQMARK-beta.txt
| 2 sub/nest/zqmark-gamma.txt
| 3 zqmark-alpha.txt
== snap first grid=120x40 cursor=7,20
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del
| 1 Find
|
|
@@ -182,7 +182,7 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Newtty Del
| 1 beta body
|
|
@@ -199,12 +199,12 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 1 sub/ZQMARK-beta.txt
| 2 sub/nest/zqmark-gamma.txt
| 3 zqmark-alpha.txt
== style first
-|0: 0-56 #949494,#121212, 57-119 d,#121212,
+|0: 0-74 #949494,#121212, 75-119 d,#121212,
|1: 0-1 #ffffff,#262626, 2-99 #949494,#121212, 100-119 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-119 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808,
@@ -245,8 +245,8 @@
|38: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-31 #bdbdbd,#080808, 32-119 d,#080808,
|39: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-119 d,#080808,
== snap second grid=120x40 cursor=7,29
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del
| 1 Find
|
|
@@ -264,7 +264,7 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Newtty Del
| 1 beta body
|
|
@@ -273,7 +273,7 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Newtty Del
| 1 gamma body
|
|
@@ -281,13 +281,13 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 1 sub/ZQMARK-beta.txt
| 2 sub/nest/zqmark-gamma.txt
| 3 zqmark-alpha.txt
== snap third grid=120x40 cursor=7,33
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del
| 1 Find
|
|
@@ -305,7 +305,7 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Newtty Del
| 1 beta body
|
|
@@ -314,21 +314,21 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Newtty Del
| 1 gamma body
|
|
-| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del
+| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Newtty Del
| 1 alpha body
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 2 sub/nest/zqmark-gamma.txt
| 3 zqmark-alpha.txt
| 4
== snap back grid=120x40 cursor=7,29
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del
| 1 Find
|
|
@@ -346,7 +346,7 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Newtty Del
| 1 beta body
|
|
@@ -355,21 +355,21 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Newtty Del
| 1 gamma body
|
|
-| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del
+| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Newtty Del
| 1 alpha body
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 1 sub/ZQMARK-beta.txt
| 2 sub/nest/zqmark-gamma.txt
| 3 zqmark-alpha.txt
== snap word grid=120x40 cursor=7,29
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del
| 1 Find
|
|
@@ -387,7 +387,7 @@
|
|
| Find /
-| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Newtty Del
| 1 beta body
|
|
@@ -396,21 +396,21 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Newtty Del
| 1 gamma body
|
|
-| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del
+| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Newtty Del
| 1 alpha body
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 1 sub/ZQMARK-beta.txt
| 2 sub/nest/zqmark-gamma.txt
| 3 zqmark-alpha.txt
== snap cancel grid=120x40 cursor=7,38
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del
| 1 Find
|
|
@@ -428,7 +428,7 @@
|
|
| Find /
-| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Newtty Del
| 1 beta body
|
|
@@ -437,21 +437,21 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Newtty Del
| 1 gamma body
|
|
-| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del
+| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Newtty Del
| 1 alpha body
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 1 sub/ZQMARK-beta.txt
| 2 sub/nest/zqmark-gamma.txt
| 3 zqmark-alpha.txt
== snap nomatch grid=120x40 cursor=7,38
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del Find /
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del Find /
| 1 Find
|
|
@@ -467,9 +467,9 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 1
-| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Newtty Del
| 1 beta body
|
|
@@ -478,21 +478,21 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Newtty Del
| 1 gamma body
|
|
-| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del
+| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Newtty Del
| 1 alpha body
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 2 sub/nest/zqmark-gamma.txt
| 3 zqmark-alpha.txt
| 4
== snap refit grid=120x40 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del Find /
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del Find /
| 1 Find
|
|
@@ -508,9 +508,9 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 1
-| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Newtty Del
| 1 beta body
|
|
@@ -519,21 +519,21 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Newtty Del
| 1 gamma body
|
|
-| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del
+| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Newtty Del
| 1 alpha body
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 2 sub/nest/zqmark-gamma.txt
| 3 zqmark-alpha.txt
| 4
== snap topbar grid=120x40 cursor=12,33
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/find/cwd/here.txt Save New Del Find /
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/find/cwd/here.txt Save New Newtty Del Find /
| 1 Find
|
|
@@ -549,9 +549,9 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/+Search New Del
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 1
-| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/ZQMARK-beta.txt Save New Newtty Del
| 1 beta body
|
|
@@ -560,15 +560,15 @@
|
|
|
-| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Del
+| /tmp/pardes-snap/find/cwd/sub/nest/zqmark-gamma.txt Save New Newtty Del
| 1 gamma body
|
|
-| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Del
+| /tmp/pardes-snap/find/cwd/zqmark-alpha.txt Save New Newtty Del
| 1 alpha body
-| /tmp/pardes-snap/find/cwd/+Search New Del
-| 1 zqmark-alpha.txt
-| /tmp/pardes-snap/find/cwd/+Search New Del
+|
+|
+| /tmp/pardes-snap/find/cwd/+Search New Newtty Del
| 2 sub/nest/zqmark-gamma.txt
| 3 zqmark-alpha.txt
| 4
diff --git a/test/snapshots/fsearch.golden b/test/snapshots/fsearch.golden
index 2cbebf80..fae58030 100644
--- a/test/snapshots/fsearch.golden
+++ b/test/snapshots/fsearch.golden
@@ -1,25 +1,23 @@
== snap opened grid=180x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fsearch/cwd/g.txt Save New /tmp/pardes-snap/fsearch/cwd New Del Filter /tmp/pardes-snap/fsearch/cwd New Del Filter
-| 1 l1 ls ls
-| 2 MARK a g.txt g.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fsearch/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| 1 l1 ls
+| 2 MARK a g.txt
| 3 l3
| 4 l4
| 5 l5
-| 6 MARK b g.txt
-| 7 l7
-| 8 l8
-| 9 l9
-| 10 MARK c
-| 11 l11
-| 12 l12
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
|
|
-| /tmp/pardes-snap/fsearch/cwd New Del Filter
-| ls
-| g.txt
|
+| g.txt
|
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
|
|
|
@@ -29,28 +27,28 @@
|
|
|
-== snap typing grid=180x30 cursor=8,29
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fsearch/cwd/g.txt Save New /tmp/pardes-snap/fsearch/cwd New Del Filter /tmp/pardes-snap/fsearch/cwd New Del Filter
-| 1 l1 ls ls
-| 2 MARK a g.txt g.txt
+|
+|
+== snap typing grid=180x30 cursor=8,7
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fsearch/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| 1 l1 ls
+| 2 MARK a g.txt
| 3 l3
| 4 l4
| 5 l5
-| 6 MARK b g.txt
-| 7 l7
-| 8 l8
-| 9 l9
-| 10 MARK c
-| 11 l11
-| 12 l12
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
|
|
-| /tmp/pardes-snap/fsearch/cwd New Del Filter
-| ls
-| g.txt
|
+| g.txt
|
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
|
|
|
@@ -59,89 +57,33 @@
|
|
|
-| /MARK
-== snap results grid=180x30 cursor=10,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fsearch/cwd/g.txt Save New /tmp/pardes-snap/fsearch/cwd New Del Filter /tmp/pardes-snap/fsearch/cwd New Del Filter
-| 1 l1 ls ls
-| 2 MARK a g.txt g.txt
-| 3 l3
-| 4 l4
-| 5 l5
-| 6 MARK b g.txt
-| 7 l7
-| 8 l8
-| 9 l9
-| 10 MARK c
-| 11 l11
-| 12 l12
|
|
-| /tmp/pardes-snap/fsearch/cwd New Del Filter
-| ls
-| g.txt
|
+== snap results grid=180x30 cursor=10,3
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fsearch/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| 1 l1 ls
+| 2 MARK a g.txt
+| /tmp/pardes-snap/fsearch/cwd/+Search New Newtty Del
+| 1 g.txt:2:1-4 MARK a
+| 2 g.txt:6:1-4 MARK b
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
|
|
|
+| g.txt
|
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
|
|
-| /tmp/pardes-snap/fsearch/cwd/+Search New De
-| 1 g.txt:2:1-4 MARK a
-| 2 g.txt:6:1-4 MARK b
-| 3 g.txt:10:1-4 MARK c
-== style results
-|0: 0-56 #949494,#121212, 57-179 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-44 #949494,#121212, 45-46 #ffffff,#262626, 47-89 #949494,#121212, 90-91 #ffffff,#262626, 92-159 #949494,#121212, 160-179 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-10 #080808,#80a0ff, 11-12 #bdbdbd,#080808, 13-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-53 #bdbdbd,#080808, 54-89 d,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-9 #bdbdbd,#080808, 10-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-9 #bdbdbd,#080808, 10-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-46 #ffffff,#262626, 47-89 #949494,#121212, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|26: 0-1 #ffffff,#262626, 2-44 #949494,#121212, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-25 #bdbdbd,#080808, 26-44 d,#080808, 45-45 d,#444444, 46-46 d,#080808, 47-89 #bdbdbd,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-179 #bdbdbd,#080808,
-== snap second grid=180x30 cursor=10,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fsearch/cwd/g.txt Save New /tmp/pardes-snap/fsearch/cwd New Del Filter /tmp/pardes-snap/fsearch/cwd New Del Filter
-| 1 l1 ls ls
-| 2 MARK a g.txt g.txt
-| 3 l3
-| 4 l4
-| 5 l5
-| 6 MARK b g.txt
-| 7 l7
-| 8 l8
-| 9 l9
-| 10 MARK c
-| 11 l11
-| 12 l12
|
|
-| /tmp/pardes-snap/fsearch/cwd New Del Filter
-| ls
-| g.txt
|
|
|
@@ -149,30 +91,58 @@
|
|
|
-| /tmp/pardes-snap/fsearch/cwd/+Search New De
+== style results
+|0: 0-74 #949494,#121212, 75-179 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-69 #949494,#121212, 70-89 d,#121212, 90-91 #ffffff,#262626, 92-159 #949494,#121212, 160-179 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-89 d,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-93 #bdbdbd,#080808, 94-179 d,#080808,
+|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #949494,#121212, 7-10 #080808,#80a0ff, 11-12 #bdbdbd,#080808, 13-89 d,#080808, 90-90 d,#444444, 91-91 d,#080808, 92-96 #bdbdbd,#080808, 97-179 d,#080808,
+|4: 0-1 #ffffff,#262626, 2-69 #949494,#121212, 70-89 d,#121212, 90-90 d,#444444, 91-179 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-25 #bdbdbd,#080808, 26-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-69 #949494,#121212, 70-89 d,#121212, 90-90 d,#444444, 91-179 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|11: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|12: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|13: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|15: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-69 #949494,#121212, 70-89 d,#121212, 90-90 d,#444444, 91-179 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|19: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|20: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|21: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|22: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|23: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|24: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|25: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|26: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|27: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|28: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+|29: 0-0 d,#444444, 1-89 d,#080808, 90-90 d,#444444, 91-179 d,#080808,
+== snap second grid=180x30 cursor=10,3
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fsearch/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| 5 l5 ls
+| 6 MARK b g.txt
+| /tmp/pardes-snap/fsearch/cwd/+Search New Newtty Del
| 1 g.txt:2:1-4 MARK a
| 2 g.txt:6:1-4 MARK b
-| 3 g.txt:10:1-4 MARK c
-== snap third grid=180x30 cursor=10,11
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fsearch/cwd/g.txt Save New /tmp/pardes-snap/fsearch/cwd New Del Filter /tmp/pardes-snap/fsearch/cwd New Del Filter
-| 1 l1 ls ls
-| 2 MARK a g.txt g.txt
-| 3 l3
-| 4 l4
-| 5 l5
-| 6 MARK b g.txt
-| 7 l7
-| 8 l8
-| 9 l9
-| 10 MARK c
-| 11 l11
-| 12 l12
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
+|
+|
+|
+| g.txt
|
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
|
-| /tmp/pardes-snap/fsearch/cwd New Del Filter
-| ls
-| g.txt
|
|
|
@@ -180,30 +150,30 @@
|
|
|
-| /tmp/pardes-snap/fsearch/cwd/+Search New De
+|
+|
+|
+== snap third grid=180x30 cursor=10,3
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fsearch/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| 9 l9 ls
+| 10 MARK c g.txt
+| /tmp/pardes-snap/fsearch/cwd/+Search New Newtty Del
| 2 g.txt:6:1-4 MARK b
| 3 g.txt:10:1-4 MARK c
-| 4
-== snap back grid=180x30 cursor=10,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fsearch/cwd/g.txt Save New /tmp/pardes-snap/fsearch/cwd New Del Filter /tmp/pardes-snap/fsearch/cwd New Del Filter
-| 1 l1 ls ls
-| 2 MARK a g.txt g.txt
-| 3 l3
-| 4 l4
-| 5 l5
-| 6 MARK b g.txt
-| 7 l7
-| 8 l8
-| 9 l9
-| 10 MARK c
-| 11 l11
-| 12 l12
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
+|
+|
+|
+| g.txt
|
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
|
-| /tmp/pardes-snap/fsearch/cwd New Del Filter
-| ls
-| g.txt
|
|
|
@@ -211,30 +181,33 @@
|
|
|
-| /tmp/pardes-snap/fsearch/cwd/+Search New De
+|
+|
+|
+== snap back grid=180x30 cursor=10,3
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fsearch/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| 5 l5 ls
+| 6 MARK b g.txt
+| /tmp/pardes-snap/fsearch/cwd/+Search New Newtty Del
| 1 g.txt:2:1-4 MARK a
| 2 g.txt:6:1-4 MARK b
-| 3 g.txt:10:1-4 MARK c
-== snap cancel grid=180x30 cursor=10,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fsearch/cwd/g.txt Save New /tmp/pardes-snap/fsearch/cwd New Del Filter /tmp/pardes-snap/fsearch/cwd New Del Filter
-| 1 l1 ls ls
-| 2 MARK a g.txt g.txt
-| 3 l3
-| 4 l4
-| 5 l5
-| 6 MARK b g.txt
-| 7 l7
-| 8 l8
-| 9 l9
-| 10 MARK c
-| 11 l11
-| 12 l12
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
+|
+|
+|
+| g.txt
+|
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
+|
+|
|
|
-| /tmp/pardes-snap/fsearch/cwd New Del Filter
-| ls
-| g.txt
|
|
|
@@ -242,38 +215,65 @@
|
|
|
-| /tmp/pardes-snap/fsearch/cwd/+Search New De
+== snap cancel grid=180x30 cursor=10,3
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fsearch/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| 5 l5 ls
+| 6 MARK b g.txt
+| /tmp/pardes-snap/fsearch/cwd/+Search New Newtty Del
| 1 g.txt:2:1-4 MARK a
| 2 g.txt:6:1-4 MARK b
-| 3 g.txt:10:1-4 MARK c
-== snap nomatch grid=180x30 cursor=7,28
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/fsearch/cwd/g.txt Save New /tmp/pardes-snap/fsearch/cwd New Del Filter /tmp/pardes-snap/fsearch/cwd New Del Filter
-| 1 l1 ls ls
-| 2 MARK a g.txt g.txt
-| 3 l3
-| 4 l4
-| 5 l5
-| 6 MARK b g.txt
-| 7 l7
-| 8 l8
-| 9 l9
-| 10 MARK c
-| 11 l11
-| 12 l12
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
+|
+|
+|
+| g.txt
+|
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
+|
|
|
-| /tmp/pardes-snap/fsearch/cwd New Del Filter
-| ls
-| g.txt
|
|
|
|
|
-| /tmp/pardes-snap/fsearch/cwd/+Search New De
-| 1
-| /tmp/pardes-snap/fsearch/cwd/+Search New De
+|
+|
+|
+== snap nomatch grid=180x30 cursor=7,6
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/fsearch/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| 5 l5 ls
+| /tmp/pardes-snap/fsearch/cwd/+Search New Newtty Del g.txt
+| /tmp/pardes-snap/fsearch/cwd/+Search New Newtty Del
| 2 g.txt:6:1-4 MARK b
| 3 g.txt:10:1-4 MARK c
-| 4
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
+|
+|
+|
+| g.txt
+|
+| /tmp/pardes-snap/fsearch/cwd New Newtty Del Filter
+| ls
+| g.txt
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
diff --git a/test/snapshots/ghostty-mid.golden b/test/snapshots/ghostty-mid.golden
index 9fa480eb..75772a29 100644
--- a/test/snapshots/ghostty-mid.golden
+++ b/test/snapshots/ghostty-mid.golden
@@ -1,6 +1,6 @@
== snap ghostty-mid grid=100x30 cursor=4,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ghostty-mid/cwd New Del Filter /tmp/pardes-snap/ghostty-mid/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ghostty-mid/cwd New Newtty Del /tmp/pardes-snap/ghostty-mid/cwd New Newtty Del
| ZZPAD ls
| ./g.sh g.txt
| ./g.sh
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/ghostty-mid/cwd New Del Filter
+| /tmp/pardes-snap/ghostty-mid/cwd New Newtty Del
| ls
| g.txt
|
diff --git a/test/snapshots/grep.golden b/test/snapshots/grep.golden
index 30c218b5..df982971 100644
--- a/test/snapshots/grep.golden
+++ b/test/snapshots/grep.golden
@@ -1,23 +1,27 @@
== snap opened grid=180x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/grep/cwd/a.txt Save New De /tmp/pardes-snap/grep/cwd New Del Filter /tmp/pardes-snap/grep/cwd New Del Filter
-| 1 hello TARGET one ls ls
-| 2 nothing here a.txt noise.txt sub a.txt noise.txt sub
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/grep/cwd/a.txt Save New Newtty Del /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| 1 hello TARGET one ls
+| 2 nothing here a.txt noise.txt sub
| 3 last TARGET line
|
|
-| a.txt
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
+| a.txt
|
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
|
-| /tmp/pardes-snap/grep/cwd New Del Filter
-| ls
-| a.txt noise.txt sub
|
|
|
@@ -25,30 +29,27 @@
|
|
|
-|
-|
-|
-|
-== snap typing grid=180x30 cursor=15,29
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/grep/cwd/a.txt Save New De /tmp/pardes-snap/grep/cwd New Del Filter /tmp/pardes-snap/grep/cwd New Del Filter
-| 1 hello TARGET one ls ls
-| 2 nothing here a.txt noise.txt sub a.txt noise.txt sub
+== snap typing grid=180x30 cursor=15,7
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/grep/cwd/a.txt Save New Newtty Del /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| 1 hello TARGET one ls
+| 2 nothing here a.txt noise.txt sub
| 3 last TARGET line
|
|
-| a.txt
-|
-|
-|
+| Grep /TARGET
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
+| a.txt
|
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
-| /tmp/pardes-snap/grep/cwd New Del Filter
-| ls
-| a.txt noise.txt sub
|
|
|
@@ -59,27 +60,30 @@
|
|
|
-| Grep /TARGET
== snap results grid=180x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/grep/cwd/a.txt Save New De /tmp/pardes-snap/grep/cwd New Del Filter /tmp/pardes-snap/grep/cwd New Del Filter
-| 1 hello TARGET one ls ls
-| 2 nothing here a.txt noise.txt sub a.txt noise.txt sub
-| 3 last TARGET line
-|
-|
-| a.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/grep/cwd/a.txt Save New Newtty Del /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| 1 hello TARGET one ls
+| 2 nothing here a.txt noise.txt sub
+| /tmp/pardes-snap/grep/cwd/+Search New Newtty Del
+| 1 a.txt:1:7-12 hello TARGET one
+| 2 a.txt:3:6-11 last TARGET line
+| 3 sub/b.txt:2:1-6 TARGET inside sub
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
+| a.txt
|
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
|
-| /tmp/pardes-snap/grep/cwd New Del Filter
-| ls
-| a.txt noise.txt sub
|
|
|
@@ -87,30 +91,30 @@
|
|
|
-| /tmp/pardes-snap/grep/cwd/+Search New Del
+== snap first grid=180x30 cursor=18,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/grep/cwd/a.txt Save New Newtty Del /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| 1 hello TARGET one ls
+| 2 nothing here a.txt noise.txt sub
+| /tmp/pardes-snap/grep/cwd/+Search New Newtty Del
| 1 a.txt:1:7-12 hello TARGET one
| 2 a.txt:3:6-11 last TARGET line
| 3 sub/b.txt:2:1-6 TARGET inside sub
-== snap first grid=180x30 cursor=18,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/grep/cwd/a.txt Save New De /tmp/pardes-snap/grep/cwd New Del Filter /tmp/pardes-snap/grep/cwd New Del Filter
-| 1 hello TARGET one ls ls
-| 2 nothing here a.txt noise.txt sub a.txt noise.txt sub
-| 3 last TARGET line
-|
-|
-| a.txt
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
+| a.txt
|
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
|
-| /tmp/pardes-snap/grep/cwd New Del Filter
-| ls
-| a.txt noise.txt sub
|
|
|
@@ -118,30 +122,30 @@
|
|
|
-| /tmp/pardes-snap/grep/cwd/+Search New Del
-| 1 a.txt:1:7-12 hello TARGET one
+== snap opened-hit grid=180x30 cursor=12,14
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/grep/cwd/a.txt Save New Newtty Del /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| 2 nothing here ls
+| 3 last TARGET line a.txt noise.txt sub
+| /tmp/pardes-snap/grep/cwd/+Search New Newtty Del
| 2 a.txt:3:6-11 last TARGET line
| 3 sub/b.txt:2:1-6 TARGET inside sub
-== snap opened-hit grid=180x30 cursor=12,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/grep/cwd/a.txt Save New De /tmp/pardes-snap/grep/cwd New Del Filter /tmp/pardes-snap/grep/cwd New Del Filter
-| 1 hello TARGET one ls ls
-| 2 nothing here a.txt noise.txt sub a.txt noise.txt sub
-| 3 last TARGET line
-|
-|
-| a.txt
+| 4
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
+| /tmp/pardes-snap/grep/cwd/sub/b.txt Save New Newtty Del
+| 1 deep
+| 2 TARGET inside sub
|
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
|
-| /tmp/pardes-snap/grep/cwd/sub/b.txt Save Ne
-| 1 deep
-| 2 TARGET inside sub /tmp/pardes-snap/grep/cwd New Del Filter
-| ls
-| a.txt noise.txt sub
|
|
|
@@ -149,100 +153,96 @@
|
|
|
-| /tmp/pardes-snap/grep/cwd/+Search New Del
+== snap nomatch grid=180x30 cursor=2,10
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/grep/cwd/a.txt Save New Newtty Del /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| 2 nothing here ls
+| 3 last TARGET line a.txt noise.txt sub
+| /tmp/pardes-snap/grep/cwd/+Search New Newtty Del
| 2 a.txt:3:6-11 last TARGET line
| 3 sub/b.txt:2:1-6 TARGET inside sub
| 4
-== snap nomatch grid=180x30 cursor=47,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/grep/cwd/a.txt Save New De /tmp/pardes-snap/grep/cwd New Del Filter /tmp/pardes-snap/grep/cwd New Del Filter
-| 1 hello TARGET one ls ls
-| 2 nothing here a.txt noise.txt sub a.txt noise.txt sub
-| 3 last TARGET line
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
-|
-| a.txt
+| /tmp/pardes-snap/grep/cwd/sub/b.txt Save New Newtty Del
+| 1 deep
+| /tmp/pardes-snap/grep/cwd/sub/+Search New Newtty Del
+| 1
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
|
|
|
-| /tmp/pardes-snap/grep/cwd/sub/b.txt Save Ne
-| 1 deep
-| 2 TARGET inside sub /tmp/pardes-snap/grep/cwd New Del Filter
-| ls
-| a.txt noise.txt sub
|
|
|
|
|
-| /tmp/pardes-snap/grep/cwd/sub/+Search New D
-| 1
-| /tmp/pardes-snap/grep/cwd/+Search New Del
+== snap chordsel grid=180x30 cursor=19,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/grep/cwd/a.txt Save New Newtty Del /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| 2 nothing here ls
+| 3 last TARGET line a.txt noise.txt sub
+| /tmp/pardes-snap/grep/cwd/+Search New Newtty Del
| 2 a.txt:3:6-11 last TARGET line
| 3 sub/b.txt:2:1-6 TARGET inside sub
| 4
-== snap chordsel grid=180x30 cursor=19,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/grep/cwd/a.txt Save New De /tmp/pardes-snap/grep/cwd New Del Filter /tmp/pardes-snap/grep/cwd New Del Filter
-| 1 hello TARGET one ls ls
-| 2 nothing here a.txt noise.txt sub a.txt noise.txt sub
-| 3 last TARGET line
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
-|
-| a.txt
+| /tmp/pardes-snap/grep/cwd/sub/b.txt Save New Newtty Del
+| 1 deep
+| /tmp/pardes-snap/grep/cwd/sub/+Search New Newtty Del
+| 1
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
|
|
|
-| /tmp/pardes-snap/grep/cwd/sub/b.txt Save Ne
-| 1 deep
-| 2 TARGET inside sub /tmp/pardes-snap/grep/cwd New Del Filter
-| ls
-| a.txt noise.txt sub
|
|
|
|
|
-| /tmp/pardes-snap/grep/cwd/sub/+Search New D
-| 1
-| /tmp/pardes-snap/grep/cwd/+Search New Del
+== snap chord grid=180x30 cursor=19,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/grep/cwd/a.txt Save New Newtty Del /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| 2 nothing here ls
+| /tmp/pardes-snap/grep/cwd/+Search New Newtty Del a.txt noise.txt sub
+| /tmp/pardes-snap/grep/cwd/+Search New Newtty Del
| 2 a.txt:3:6-11 last TARGET line
| 3 sub/b.txt:2:1-6 TARGET inside sub
| 4
-== snap chord grid=180x30 cursor=19,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/grep/cwd/a.txt Save New De /tmp/pardes-snap/grep/cwd New Del Filter /tmp/pardes-snap/grep/cwd New Del Filter
-| 1 hello TARGET one ls ls
-| 2 nothing here a.txt noise.txt sub a.txt noise.txt sub
-| 3 last TARGET line
-|
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
-| a.txt
+| /tmp/pardes-snap/grep/cwd/sub/b.txt Save New Newtty Del
+| 1 deep
+| /tmp/pardes-snap/grep/cwd/sub/+Search New Newtty Del
+| 1
+| /tmp/pardes-snap/grep/cwd New Newtty Del Filter
+| ls
+| a.txt noise.txt sub
|
|
|
|
|
|
-| /tmp/pardes-snap/grep/cwd/sub/b.txt Save Ne
-| 1 deep
-| 2 TARGET inside sub /tmp/pardes-snap/grep/cwd New Del Filter
-| ls
-| a.txt noise.txt sub
|
|
|
|
|
-| /tmp/pardes-snap/grep/cwd/sub/+Search New D
-| 1
-| /tmp/pardes-snap/grep/cwd/+Search New Del
-| 2 a.txt:3:6-11 last TARGET line
-| 3 sub/b.txt:2:1-6 TARGET inside sub
-| 4
diff --git a/test/snapshots/grep.snap b/test/snapshots/grep.snap
index ab708a25..acf89784 100644
--- a/test/snapshots/grep.snap
+++ b/test/snapshots/grep.snap
@@ -34,8 +34,8 @@ stable 700 15000
snap opened
# middle-click Grep on the topbar (row 1, the word's own column): the input
# arms on the ACTIVE pane's tag, exactly where `/` would have typed
-press middle 17 1
-release middle 17 1
+press middle 26 1
+release middle 26 1
stable 400 5000
text TARGET
stable 400 5000
@@ -94,8 +94,8 @@ drag left 20 3
release left 20 3
stable 400 5000
snap chordsel
-press middle 17 1
-release middle 17 1
+press middle 26 1
+release middle 26 1
wait 10000 sub/b.txt:2:1
stable 700 15000
snap chord
diff --git a/test/snapshots/hscroll.golden b/test/snapshots/hscroll.golden
index 8505214e..2578bf1c 100644
--- a/test/snapshots/hscroll.golden
+++ b/test/snapshots/hscroll.golden
@@ -1,23 +1,23 @@
== snap opened grid=90x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/hscr /tmp/pardes-snap/hsc /tmp/pardes-snap/hscroll/cwd New Del Filter
-| 1 short1 END_A_MAR ls ls
-| wide.txt wide.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/hscroll/cwd/wide.txt Save /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| 1 short1 END_A_MARKER_WAY_OUT_RIGHT_padp ls
+| wide.txt
|
|
|
-| wide.txt
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| ls
+| wide.txt
|
|
|
+| wide.txt
|
-|
-|
-|
-|
-| /tmp/pardes-snap/hsc
-| ls
-| wide.txt
+| /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| ls
+| wide.txt
|
|
|
@@ -30,25 +30,25 @@
|
|
== snap wheeled grid=90x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/hscr /tmp/pardes-snap/hsc /tmp/pardes-snap/hscroll/cwd New Del Filter
-| 1 ND_A_MARKER_WAY_ ls ls
-| wide.txt wide.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/hscroll/cwd/wide.txt Save /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| 1 ND_A_MARKER_WAY_OUT_RIGHT_padpadpadpad ls
+| wide.txt
|
|
|
-| wide.txt
|
+| /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| ls
+| wide.txt
|
|
|
+| wide.txt
|
-|
-|
-|
-| /tmp/pardes-snap/hsc
-| ls
-| wide.txt
+| /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| ls
+| wide.txt
|
|
|
@@ -61,25 +61,27 @@
|
|
== snap clamped grid=90x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/hscr /tmp/pardes-snap/hsc /tmp/pardes-snap/hscroll/cwd New Del Filter
-| 1 short1 END_A_MAR ls ls
-| wide.txt wide.txt
-|
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/hscroll/cwd/wide.txt Save /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| 1 short1 END_A_MARKER_WAY_OUT_RIGHT_padp ls
+| wide.txt
|
|
-| wide.txt
|
|
+| /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| ls
+| wide.txt
|
|
|
+| wide.txt
|
+| /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| ls
+| wide.txt
|
|
-| /tmp/pardes-snap/hsc
-| ls
-| wide.txt
|
|
|
@@ -89,28 +91,26 @@
|
|
|
+== snap dollar grid=90x30 cursor=41,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/hscroll/cwd/wide.txt Save /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| 1 padpadpadpadpadpadpadpadpadpad_TAIL ls
+| wide.txt
|
|
-== snap dollar grid=90x30 cursor=19,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/hscr /tmp/pardes-snap/hsc /tmp/pardes-snap/hscroll/cwd New Del Filter
-| 1 adpadpad_TAIL ls ls
-| wide.txt wide.txt
|
|
+| /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| ls
+| wide.txt
|
-| wide.txt
|
|
+| wide.txt
|
-|
-|
-|
-|
-|
-| /tmp/pardes-snap/hsc
-| ls
-| wide.txt
+| /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| ls
+| wide.txt
|
|
|
@@ -123,25 +123,25 @@
|
|
== snap zero grid=90x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/hscr /tmp/pardes-snap/hsc /tmp/pardes-snap/hscroll/cwd New Del Filter
-| 1 short1 END_A_MAR ls ls
-| wide.txt wide.txt
-|
-|
-|
-| wide.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/hscroll/cwd/wide.txt Save /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| 1 short1 END_A_MARKER_WAY_OUT_RIGHT_padp ls
+| wide.txt
|
|
|
|
+| /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| ls
+| wide.txt
|
|
|
+| wide.txt
|
-| /tmp/pardes-snap/hsc
-| ls
-| wide.txt
+| /tmp/pardes-snap/hscroll/cwd New Newtty Del
+| ls
+| wide.txt
|
|
|
diff --git a/test/snapshots/images.golden b/test/snapshots/images.golden
index 0835dff1..02774a52 100644
--- a/test/snapshots/images.golden
+++ b/test/snapshots/images.golden
@@ -1,155 +1,155 @@
== snap img-open grid=150x30 cursor=11,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| img petscii:off palette:commodore as /tmp/pardes-snap/images/cwd New Del /tmp/pardes-snap/images/cwd New Del Filter
-| ls ls
-| pic.ppm pic.ppm
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| img petscii:off palette:commodore ascii:on /tmp/pardes-snap/images/cwd/pi /tmp/pardes-snap/images/cwd New Newtty Del Filter
+| )a▟Z▛🬮>{1\🬆🬻 ls
+| 🬻&z""─🬛█🬆🬻 pic.ppm
+| g`🬶🬬@🬕🬆🬻
+| ▙-=🬫🬆🬻
+| ▙.🬆🬻
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/images/cwd New Newtty Del Filter
+| ls
+| pic.ppm
+|
+|
+|
+| pic.ppm
+|
+| /tmp/pardes-snap/images/cwd New Newtty Del Filter
+| ls
+| pic.ppm
+|
+|
+|
|
|
|
-| 🬥~CKA$4k\RQ/>g▙))▐p_'YztV1🬏%🬮E🬝CQX🬆▄ pic.ppm
-| 2Ss)L▖~ey🬵🬨╳/\,t🬊🬢~🬦/🬧G]}&▚r4n4w🬎🬹
-| 🬪f]V🬱Fk▚KhO~GP🬎/Y🬶pzXJ🬎╱@^c*🬚r🬝▟
-| mQ▌5Ee"^S(╱U^5🬥(`e🬫🬋Fb🬢$╱▄🬢#🬝🬻█
-| 83KHF▜╳A$DqA`🬬"`▚N$j🬥🬫q$W🬺🬝▄
-| 7Z🬏xq🬱E🬊H^🬅🬬}Z_╲S@aQSVJH🬝~█
-| d\>y🬪O🬢j5D07E┼🬍=Eh▄jHC🬆▄
-| 8[🬓Ke_#r"🬳q4FaM▚\$r'🬝🬹█
-| X];🬝{>▄kU┼🬳)DUbYhb🬎~
-| rHo0i5🬱msyc[W_dB▛🬻 /tmp/pardes-snap/images/cwd New Del
-| 7?🬊k#ZF*v🬥"#^h🬝🬻█ ls
-| ╲uc-q4q?*2f.🬝🬻█ pic.ppm
-| eY─a?🬫^🬆I🬁🬝🬹
-| 2🬷r🬲.x49🬝🬻
-| 2╱Y─Tc🬝🬹█
-| 26🬭g▛🬻
-| 🬩🬬🬝🬻█
-| 🬆🬹█
|
|
|
|
|
== style img-open
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#121212, 1-1 d,#080808, 2-2 #959595,#6c6c6c, 3-3 #6c6c6c,#959595, 4-7 #959595,#6c6c6c, 8-8 #6c6c6c,#959595, 9-11 #959595,#6c6c6c, 12-12 #6c6c6c,#959595, 13-13 #959595,#6c6c6c, 14-15 #6c6c6c,#959595, 16-16 #959595,#6c6c6c, 17-18 #6c6c6c,#959595, 19-19 #959595,#6c6c6c, 20-20 #6c6c6c,#959595, 21-21 #959595,#6c6c6c, 22-24 #6c6c6c,#959595, 25-25 #959595,#6c6c6c, 26-26 #6c6c6c,#959595, 27-28 #959595,#6c6c6c, 29-29 #6c6c6c,#959595, 30-30 #959595,#6c6c6c, 31-32 #6c6c6c,#959595, 33-33 #959595,#6c6c6c, 34-35 #6c6c6c,#959595, 36-36 #959595,#6c5eb5, 37-37 #352879,#6c5eb5, 38-38 d,#444444, 39-39 d,#080808, 40-48 #bdbdbd,#080808, 49-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#121212, 1-1 d,#080808, 2-3 #959595,#6c6c6c, 4-6 #6c6c6c,#959595, 7-8 #959595,#6c6c6c, 9-9 #6c6c6c,#959595, 10-11 #959595,#6c6c6c, 12-12 #6c6c6c,#959595, 13-19 #959595,#6c6c6c, 20-20 #6c6c6c,#959595, 21-22 #959595,#6c6c6c, 23-23 #6c6c6c,#959595, 24-26 #959595,#6c6c6c, 27-28 #6c6c6c,#959595, 29-31 #959595,#6c6c6c, 32-33 #6c6c6c,#959595, 34-34 #959595,#352879, 35-35 #352879,#6c5eb5, 36-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#121212, 1-1 d,#080808, 2-2 #6c6c6c,#959595, 3-5 #959595,#6c6c6c, 6-6 #6c6c6c,#959595, 7-7 #959595,#6c6c6c, 8-8 #6c6c6c,#959595, 9-16 #959595,#6c6c6c, 17-18 #6c6c6c,#959595, 19-19 #959595,#6c6c6c, 20-20 #6c6c6c,#959595, 21-21 #959595,#6c6c6c, 22-22 #6c6c6c,#959595, 23-24 #959595,#6c6c6c, 25-25 #6c6c6c,#959595, 26-28 #959595,#6c6c6c, 29-31 #6c6c6c,#959595, 32-32 #6c6c6c,#352879, 33-33 #352879,#959595, 34-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#121212, 1-1 d,#080808, 2-2 #959595,#6c6c6c, 3-4 #6c6c6c,#959595, 5-6 #959595,#6c6c6c, 7-7 #6c6c6c,#959595, 8-12 #959595,#6c6c6c, 13-14 #6c6c6c,#959595, 15-19 #959595,#6c6c6c, 20-20 #6c6c6c,#959595, 21-29 #959595,#6c6c6c, 30-30 #6c6c6c,#352879, 31-31 #352879,#6c6c6c, 32-32 #352879,#6c5eb5, 33-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#121212, 1-1 d,#080808, 2-2 #6c6c6c,#959595, 3-5 #959595,#6c6c6c, 6-6 #6c6c6c,#959595, 7-9 #959595,#6c6c6c, 10-11 #6c6c6c,#959595, 12-12 #959595,#6c6c6c, 13-13 #6c6c6c,#959595, 14-14 #959595,#6c6c6c, 15-15 #6c6c6c,#959595, 16-16 #959595,#6c6c6c, 17-17 #6c6c6c,#959595, 18-19 #959595,#6c6c6c, 20-20 #6c6c6c,#959595, 21-21 #959595,#6c6c6c, 22-24 #6c6c6c,#959595, 25-25 #959595,#6c6c6c, 26-26 #6c6c6c,#959595, 27-27 #959595,#6c6c6c, 28-28 #6c6c6c,#352879, 29-29 #352879,#6c5eb5, 30-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#121212, 1-1 d,#080808, 2-8 #959595,#6c6c6c, 9-9 #6c6c6c,#959595, 10-12 #959595,#6c6c6c, 13-15 #6c6c6c,#959595, 16-18 #959595,#6c6c6c, 19-19 #6c6c6c,#959595, 20-20 #959595,#6c6c6c, 21-23 #6c6c6c,#959595, 24-25 #959595,#6c6c6c, 26-27 #6c6c6c,#352879, 28-28 #352879,#6c5eb5, 29-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#121212, 1-1 d,#080808, 2-8 #959595,#6c6c6c, 9-9 #6c6c6c,#959595, 10-10 #959595,#6c6c6c, 11-12 #6c6c6c,#959595, 13-14 #959595,#6c6c6c, 15-15 #6c6c6c,#959595, 16-17 #959595,#6c6c6c, 18-18 #6c6c6c,#959595, 19-19 #959595,#6c6c6c, 20-20 #6c6c6c,#959595, 21-23 #959595,#6c6c6c, 24-24 #959595,#6c5eb5, 25-25 #352879,#6c5eb5, 26-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#121212, 1-1 d,#080808, 2-3 #6c6c6c,#959595, 4-5 #959595,#6c6c6c, 6-6 #6c6c6c,#959595, 7-11 #959595,#6c6c6c, 12-13 #6c6c6c,#959595, 14-15 #959595,#6c6c6c, 16-16 #6c6c6c,#959595, 17-21 #959595,#6c6c6c, 22-22 #6c6c6c,#352879, 23-24 #352879,#6c5eb5, 25-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#121212, 1-1 d,#080808, 2-2 #6c6c6c,#959595, 3-4 #959595,#6c6c6c, 5-6 #6c6c6c,#959595, 7-8 #959595,#6c6c6c, 9-9 #6c6c6c,#959595, 10-13 #959595,#6c6c6c, 14-16 #6c6c6c,#959595, 17-17 #959595,#6c6c6c, 18-19 #6c6c6c,#959595, 20-20 #6c6c6c,#352879, 21-21 #959595,#352879, 22-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#121212, 1-1 d,#080808, 2-3 #959595,#6c6c6c, 4-4 #6c6c6c,#959595, 5-5 #959595,#6c6c6c, 6-6 #6c6c6c,#959595, 7-13 #959595,#6c6c6c, 14-14 #6c6c6c,#959595, 15-16 #959595,#6c6c6c, 17-17 #6c6c6c,#959595, 18-18 #959595,#352879, 19-19 #352879,#6c6c6c, 20-37 #352879,#352879, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#121212, 1-1 d,#080808, 2-6 #959595,#6c6c6c, 7-7 #6c6c6c,#959595, 8-8 #959595,#6c6c6c, 9-11 #6c6c6c,#959595, 12-12 #959595,#6c6c6c, 13-13 #6c6c6c,#959595, 14-15 #959595,#6c6c6c, 16-16 #6c6c6c,#352879, 17-17 #352879,#959595, 18-18 #352879,#6c5eb5, 19-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#121212, 1-1 d,#080808, 2-6 #959595,#6c6c6c, 7-8 #6c6c6c,#959595, 9-9 #959595,#6c6c6c, 10-10 #6c6c6c,#959595, 11-13 #959595,#6c6c6c, 14-14 #6c6c6c,#352879, 15-15 #352879,#6c6c6c, 16-16 #352879,#6c5eb5, 17-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#121212, 1-1 d,#080808, 2-3 #6c6c6c,#959595, 4-4 #959595,#6c6c6c, 5-6 #6c6c6c,#959595, 7-7 #959595,#6c6c6c, 8-8 #6c6c6c,#959595, 9-9 #959595,#6c6c6c, 10-10 #6c6c6c,#959595, 11-11 #959595,#6c6c6c, 12-12 #6c6c6c,#352879, 13-13 #352879,#6c5eb5, 14-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#121212, 1-1 d,#080808, 2-5 #6c6c6c,#959595, 6-7 #959595,#6c6c6c, 8-8 #6c6c6c,#959595, 9-9 #959595,#6c6c6c, 10-10 #6c6c6c,#352879, 11-11 #352879,#6c6c6c, 12-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#121212, 1-1 d,#080808, 2-2 #959595,#6c6c6c, 3-4 #6c6c6c,#959595, 5-7 #959595,#6c6c6c, 8-8 #6c6c6c,#352879, 9-10 #352879,#6c5eb5, 11-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#121212, 1-1 d,#080808, 2-5 #6c6c6c,#959595, 6-6 #6c6c6c,#352879, 7-7 #352879,#6c6c6c, 8-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#121212, 1-1 d,#080808, 2-2 #959595,#6c6c6c, 3-3 #6c6c6c,#959595, 4-4 #6c6c6c,#352879, 5-5 #352879,#6c6c6c, 6-6 #352879,#6c5eb5, 7-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#121212, 1-1 d,#080808, 2-2 #959595,#6c5eb5, 3-4 #352879,#6c5eb5, 5-37 #352879,#352879, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
+|2: 0-0 d,#121212, 1-31 d,#080808, 32-33 #959595,#6c6c6c, 34-34 #6c6c6c,#959595, 35-35 #959595,#6c6c6c, 36-36 #6c6c6c,#959595, 37-37 #959595,#6c6c6c, 38-38 #6c6c6c,#959595, 39-41 #959595,#6c6c6c, 42-42 #6c6c6c,#6c5eb5, 43-43 #352879,#6c6c6c, 44-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#121212, 1-31 d,#080808, 32-34 #6c6c6c,#959595, 35-37 #959595,#6c6c6c, 38-39 #6c6c6c,#959595, 40-40 #6c6c6c,#6c5eb5, 41-41 #352879,#6c6c6c, 42-43 #352879,#352879, 44-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-83 #bdbdbd,#080808, 84-149 d,#080808,
+|4: 0-0 d,#121212, 1-31 d,#080808, 32-33 #959595,#6c6c6c, 34-35 #6c6c6c,#959595, 36-36 #959595,#6c6c6c, 37-37 #6c6c6c,#959595, 38-38 #6c6c6c,#6c5eb5, 39-39 #352879,#6c6c6c, 40-43 #352879,#352879, 44-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#121212, 1-31 d,#080808, 32-32 #6c6c6c,#959595, 33-34 #959595,#6c6c6c, 35-35 #6c6c6c,#959595, 36-36 #6c6c6c,#6c5eb5, 37-37 #352879,#959595, 38-43 #352879,#352879, 44-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#121212, 1-31 d,#080808, 32-33 #959595,#6c6c6c, 34-34 #959595,#6c5eb5, 35-35 #352879,#6c6c6c, 36-43 #352879,#352879, 44-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#121212, 1-31 d,#080808, 32-32 #6c6c6c,#6c5eb5, 33-33 #352879,#6c6c6c, 34-43 #352879,#352879, 44-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-74 #949494,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-74 #949494,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
== style term-palette
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#121212, 1-1 d,#080808, 2-2 p8,p4, 3-3 p5,p8, 4-4 p4,p8, 5-6 p8,p4, 7-17 p4,p8, 18-18 p8,p4, 19-19 p4,p8, 20-20 p8,p4, 21-25 p4,p8, 26-26 p5,p8, 27-27 p4,p8, 28-28 p8,p4, 29-29 p5,p8, 30-30 p8,p4, 31-31 p4,p8, 32-32 p8,p4, 33-33 p8,p5, 34-34 p4,p8, 35-36 p8,p4, 37-37 p12,p8, 38-38 d,#444444, 39-39 d,#080808, 40-48 #bdbdbd,#080808, 49-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#121212, 1-1 d,#080808, 2-3 p4,p8, 4-4 p5,p8, 5-5 p4,p8, 6-7 p8,p4, 8-9 p5,p8, 10-10 p4,p8, 11-11 p8,p4, 12-12 p8,p5, 13-13 p5,p8, 14-15 p4,p8, 16-16 p5,p8, 17-18 p4,p8, 19-19 p5,p8, 20-20 p4,p8, 21-21 p8,p4, 22-22 p4,p8, 23-23 p8,p4, 24-24 p4,p8, 25-25 p5,p8, 26-26 p4,p8, 27-28 p8,p4, 29-30 p4,p8, 31-31 p8,p5, 32-32 p8,p4, 33-34 p4,p8, 35-35 p12,p8, 36-36 p12,p0, 37-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#121212, 1-1 d,#080808, 2-3 p4,p8, 4-5 p5,p8, 6-6 p4,p8, 7-8 p8,p4, 9-10 p4,p8, 11-11 p5,p8, 12-13 p4,p8, 14-14 p8,p5, 15-15 p4,p8, 16-16 p5,p8, 17-17 p4,p8, 18-18 p5,p8, 19-19 p8,p4, 20-23 p4,p8, 24-24 p8,p4, 25-25 p5,p8, 26-28 p4,p8, 29-29 p8,p5, 30-30 p4,p8, 31-31 p8,p4, 32-33 p8,p12, 34-34 p12,p0, 35-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#121212, 1-1 d,#080808, 2-2 p4,p8, 3-3 p8,p4, 4-4 p5,p8, 5-5 p8,p4, 6-9 p4,p8, 10-10 p5,p8, 11-12 p4,p8, 13-13 p5,p8, 14-14 p4,p8, 15-16 p8,p4, 17-17 p4,p8, 18-18 p8,p4, 19-19 p4,p8, 20-20 p8,p4, 21-23 p4,p8, 24-24 p8,p5, 25-26 p4,p8, 27-28 p8,p4, 29-30 p5,p8, 31-31 p12,p8, 32-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#121212, 1-1 d,#080808, 2-4 p4,p8, 5-5 p8,p4, 6-8 p4,p8, 9-9 p8,p5, 10-10 p8,p4, 11-11 p8,p5, 12-14 p4,p8, 15-15 p8,p4, 16-17 p4,p8, 18-19 p8,p4, 20-22 p4,p8, 23-23 p8,p4, 24-24 p8,p5, 25-25 p5,p8, 26-26 p4,p8, 27-27 p5,p8, 28-28 p4,p8, 29-29 p12,p8, 30-30 p12,p0, 31-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#121212, 1-1 d,#080808, 2-2 p4,p8, 3-4 p8,p4, 5-6 p4,p8, 7-7 p8,p4, 8-8 p4,p8, 9-9 p8,p4, 10-10 p5,p8, 11-11 p4,p8, 12-12 p8,p4, 13-13 p8,p5, 14-14 p4,p8, 15-15 p8,p4, 16-18 p4,p8, 19-19 p8,p4, 20-20 p4,p8, 21-22 p8,p4, 23-23 p4,p8, 24-24 p8,p4, 25-26 p4,p8, 27-27 p12,p8, 28-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#121212, 1-1 d,#080808, 2-2 p5,p8, 3-5 p4,p8, 6-6 p5,p8, 7-7 p8,p4, 8-8 p8,p5, 9-9 p8,p4, 10-15 p4,p8, 16-16 p5,p8, 17-19 p4,p8, 20-20 p8,p4, 21-23 p4,p8, 24-24 p8,p12, 25-25 p12,p8, 26-26 p8,p12, 27-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#121212, 1-1 d,#080808, 2-3 p5,p8, 4-4 p8,p4, 5-5 p5,p8, 6-6 p4,p8, 7-7 p5,p8, 8-9 p4,p8, 10-10 p8,p4, 11-12 p4,p8, 13-13 p8,p4, 14-15 p4,p8, 16-16 p5,p8, 17-17 p8,p4, 18-18 p8,p5, 19-20 p4,p8, 21-21 p5,p8, 22-22 p4,p8, 23-23 p12,p8, 24-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#121212, 1-1 d,#080808, 2-2 p8,p4, 3-4 p4,p8, 5-6 p8,p4, 7-8 p4,p8, 9-9 p8,p4, 10-11 p4,p8, 12-12 p8,p4, 13-13 p4,p8, 14-14 p8,p4, 15-15 p5,p8, 16-16 p8,p4, 17-17 p5,p8, 18-18 p4,p8, 19-19 p8,p4, 20-20 p8,p12, 21-21 p12,p8, 22-22 p8,p12, 23-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#121212, 1-1 d,#080808, 2-5 p4,p8, 6-6 p8,p4, 7-7 p5,p8, 8-8 p8,p5, 9-9 p4,p8, 10-10 p8,p4, 11-11 p4,p8, 12-12 p8,p4, 13-13 p5,p8, 14-15 p8,p5, 16-17 p4,p8, 18-18 p8,p4, 19-19 p12,p8, 20-37 p12,p12, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#121212, 1-1 d,#080808, 2-2 p4,p8, 3-3 p5,p8, 4-4 p8,p4, 5-5 p4,p8, 6-6 p8,p4, 7-8 p4,p8, 9-9 p8,p4, 10-10 p4,p8, 11-11 p8,p4, 12-13 p4,p8, 14-14 p8,p5, 15-17 p4,p8, 18-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#121212, 1-1 d,#080808, 2-8 p4,p8, 9-10 p8,p4, 11-12 p4,p8, 13-13 p5,p8, 14-14 p8,p4, 15-15 p12,p8, 16-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#121212, 1-1 d,#080808, 2-5 p4,p8, 6-6 p5,p8, 7-7 p8,p4, 8-8 p8,p5, 9-10 p4,p8, 11-11 p8,p4, 12-12 p8,p12, 13-13 p4,p8, 14-14 p12,p0, 15-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#121212, 1-1 d,#080808, 2-5 p8,p4, 6-7 p4,p8, 8-8 p5,p8, 9-9 p4,p8, 10-10 p8,p4, 11-11 p12,p8, 12-12 p12,p0, 13-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#121212, 1-1 d,#080808, 2-3 p4,p8, 4-4 p8,p4, 5-5 p4,p8, 6-6 p5,p8, 7-8 p4,p8, 9-9 p12,p8, 10-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#121212, 1-1 d,#080808, 2-2 p4,p8, 3-3 p8,p4, 4-4 p4,p8, 5-5 p5,p8, 6-6 p4,p8, 7-7 p12,p8, 8-8 p12,p0, 9-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#121212, 1-1 d,#080808, 2-4 p8,p4, 5-5 p12,p8, 6-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#121212, 1-1 d,#080808, 2-2 p5,p8, 3-4 p12,p8, 5-37 p12,p12, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#121212, 1-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
+|2: 0-0 d,#121212, 1-31 d,#080808, 32-41 p8,p4, 42-42 p8,p12, 43-43 p12,p8, 44-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#121212, 1-31 d,#080808, 32-39 p8,p4, 40-40 p8,p12, 41-41 p12,p8, 42-43 p12,p12, 44-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-83 #bdbdbd,#080808, 84-149 d,#080808,
+|4: 0-0 d,#121212, 1-31 d,#080808, 32-32 p8,p4, 33-33 p4,p8, 34-37 p8,p4, 38-38 p8,p12, 39-40 p12,p8, 41-43 p12,p12, 44-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#121212, 1-31 d,#080808, 32-35 p8,p4, 36-36 p8,p12, 37-37 p12,p8, 38-43 p12,p12, 44-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#121212, 1-31 d,#080808, 32-32 p4,p8, 33-33 p8,p4, 34-34 p8,p12, 35-36 p12,p8, 37-43 p12,p12, 44-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#121212, 1-31 d,#080808, 32-32 p8,p12, 33-34 p12,p8, 35-43 p12,p12, 44-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-74 #949494,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-74 #949494,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
== snap no-ascii grid=150x30 cursor=11,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| img petscii:off palette:terminal asc /tmp/pardes-snap/images/cwd New Del /tmp/pardes-snap/images/cwd New Del Filter
-| ls ls
-| pic.ppm pic.ppm
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| img petscii:off palette:terminal ascii:off /tmp/pardes-snap/images/cwd/pi /tmp/pardes-snap/images/cwd New Newtty Del Filter
+| █████🬻████🬝▄ ls
+| ████████🬝▄ pic.ppm
+| ███🬬██🬝▄█
+| ████🬝▄
+| ██🬝▄█
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/images/cwd New Newtty Del Filter
+| ls
+| pic.ppm
+|
+|
+|
+| pic.ppm
+|
+| /tmp/pardes-snap/images/cwd New Newtty Del Filter
+| ls
+| pic.ppm
+|
+|
+|
|
|
|
-| 🬻┼█🬬🬬🬺╲🬻█▟╱█╲█▛─▟▛╲█🬨─🬬█─🬬🬬🬴🬎▙🬝██🬛▟🬵 pic.ppm
-| 🬸▛█🬝╱▜🬝🬻▛🬥█╳🬻███╳╲🬍🬕█🬺███🬜🬬█│█▜🬝╱🬵█
-| 🬬▜╱█🬴█🬺🬴█▟███▟🬱▟🬺🬴🬜🬴🬻█🬰│🬹██🬜█─█▟█
-| ▙🬬│█▙╱╱█╲🬝╱🬫╲🬎🬶██🬴🬫─🬹███╱▜🬙╱🬝▄
-| ╲╱╲▟╲▌╳█🬬█🬸▛🬝🬬🬺🬕▞🬻╲█╲🬬█🬴🬬🬘╱▟█
-| █🬬🬬█🬝🬸🬻🬸█🬬🬸🬬─╱█╲│🬬╳🬝▜🬲█▄█🬵
-| █╲█🬨🬝🬴🬝▞▟█🬸🬬│█🬮██▟🬻███🬝🬵╲
-| █╱▜🬺█🬎─██🬝╲🬬│🬸🬬▞██🬴█╳▄
-| │╱█🬝🬬█▀🬺🬝┼🬧█🬺╱█╱▌🬴▛▄╲
-| 🬝╲🬝█🬥█🬝▟█▛🬻🬬██🬺╱🬫🬵 /tmp/pardes-snap/images/cwd New Del
-| 🬺╱🬲╲▟──▛▙🬥███──▄ ls
-| ╲█─██╱╲█🬝🬸─█🬺🬵 pic.ppm
-| ▜█─🬬🬻🬛▛🬶┼🬺█▄█
-| ▟🬸▛🬺███╲🬸▄█
-| 🬸🬗🬸╲│╱🬝🬷
-| █🬶╲🬺🬝╱█
-| 🬰█╱🬵
-| 🬺╱█
|
|
|
|
|
== snap tag-edit grid=400x30 cursor=85,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| img petscii:off palette:terminal ascii:off /tmp/pardes-snap/images/cwd/pic.ppm ZorkNew Del /tmp/pardes-snap/images/cwd New Del Filter /tmp/pardes-snap/images/cwd New Del Filter
-| 🬙│🬎╱🬻🬸█🬸🬺╳🬴🬍🬺╱│🬺🬬█🬴█🬸🬝🬙🬣🬳🬸█🬛🬶██▝▟🬝▄🬪╲█▀🬺██╱│▙█🬲▛▙╱🬙╳🬺🬜🬡🬵 ls ls
-| ││🬜🬲🬊╳╲🬝▟🬀🬬█│█▟█▙🬷🬲🬶█🬬🬩▌▟┼🬘█🬝─🬬🬱╱🬝🬥🬸▜🬴🬺🬻▚🬊█╳│🬬█🬸🬬▛🬕╳🬯🬹 pic.ppm pic.ppm
-| 🬣╱▛🬬┼╲🬰🬷╱╱│🬹🬧▙▜─█🬎█🬜─🬰🬎█🬫╳│🬝╲🬬╲│🬴🬬▛🬸🬲╳🬻╳🬤🬺🬦█🬬│▞▜🬜🬝🬸▟╲
-| ─🬺██╳▟🬴🬩🬺╱🬐🬝▟╱🬹▀🬜🬬🬝🬙▟🬜┼╲🬰██🬝🬖🬺▜│🬺🬛─🬌│🬤▀🬶▀─▙🬴─▟🬬🬹🬎│╲
-| ─╳█🬸🬜🬫█🬍🬻╱▌│🬷🬝╲▀🬸╳🬝🬻╳┼▜🬥╳╱▛╳🬊🬙🬶│🬛╲🬺🬝🬷╲█🬸█🬫┼┼🬎╱🬻🬵█
-| 🬜🬜🬜╲▙█🬻┼╳🬪█🬻🬸🬸▛🬨🬶🬳╱🬤🬝🬬█🬝│██▙🬺█🬰🬄█🬨╲│🬍▛╱🬙🬆🬸─🬸🬲▄ pic.ppm
-| 🬳🬶🬆🬤╲🬸█🬗┼🬳╳🬎╳🬗🬥█🬬🬺╳│██▛🬷│🬴█🬸🬹╲🬛█🬛╱🬬█🬝🬳█▖█╲▜▄╲
-| 🬧▛🬴🬬▄🬴▛│🬲╱▌╲🬔▌▛🬺🬷╲█🬴🬰🬕🬴╱▟│🬹█╳█▟🬥🬻🬰╱╳╲🬬│🬳╱┼
-| ▜█╱🬬🬬🬰╱🬨┼█🬝🬝█🬥┼🬲🬺🬬█🬶🬺│█🬥🬝🬤🬤█▀🬻🬨🬙🬝│🬫█🬣█▛▄╲
-| 🬬🬳╱╱┼█🬙🬻🬮╱🬸▜╲─│🬸─🬶╱🬥🬴🬱▛🬬🬪█╱🬫▜▜╳🬫╲🬰╲│█▄█
-| 🬻▜██╲▗█🬫▙🬹🬫🬎╳🬶🬻🬡🬤╱▛🬯🬸╱🬷╱██▙▜🬸█│╱🬙█🬺▄█
-| █🬗🬛🬍█🬱███🬲🬷▜██╲▙🬴█─┼▜▙🬬▟🬝🬸🬬🬷🬰╱🬫🬜█┼╲
-| ▛🬫╲🬔█╱🬩╱🬤╳🬺╲█╳🬸🬬╲🬹╲╱▙█🬱🬺🬌🬬🬸🬒███🬵█
-| 🬜🬤│▛█🬴╲🬪█▛🬨🬬🬻🬙▟🬻🬷█🬜🬘╱🬚█🬝─🬬╲🬤🬝🬻
-| ▀🬸🬒🬺││🬸🬥███🬮█🬺🬙🬛╲🬻🬻🬬🬻🬜🬪╲🬝🬶─🬵 /tmp/pardes-snap/images/cwd New Del Filter
-| ╲🬇🬪🬒🬡🬙🬌╱🬩🬸🬻🬸🬩▀╱🬳▜🬲╳▟🬰██─🬴│╲ ls
-| 🬴█🬬─🬳🬺█🬎╳🬗▟│🬬🬸╳╲╲╱🬶██🬩🬜╲█ pic.ppm
-| ██🬙▀🬲▛█🬬🬙▟🬹╱🬺🬙🬩🬂🬬█╳▙🬸🬵█
-| 🬛🬝🬬█🬻🬬│╲🬝🬥🬜🬻🬎🬮🬻🬴█╳█🬹
-| ▀🬫🬝─│█╱▜🬎🬍🬚╲🬛╳▙🬜╳🬵
-| ┼🬬🬷█▙🬴▟🬬🬝🬬🬝🬄▌╲🬴🬻█
-| 🬝🬺🬝╳🬯🬺🬝▜╳🬗╲─🬪╳
-| ▀▘🬚🬵🬥╳🬶╱┼▌🬺│
-| ╱│▛╳▙🬕▟▛🬺🬹
-| ▟█│▙┼█🬨🬵╲
-| ▜│╱▌🬝╲╲
-| ▛││🬷╲
-| 🬬🬵╲
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| img petscii:off palette:terminal ascii:off /tmp/pardes-snap/images/cwd/pic.ppm Zork New Newtty Del /tmp/pardes-snap/images/cwd New Newtty Del Filter
+| █████🬻████🬝▄ ls
+| ████████🬝▄ pic.ppm
+| ███🬬██🬝▄█
+| ████🬝▄
+| ██🬝▄█
+| 🬝▄█
+| /tmp/pardes-snap/images/cwd New Newtty Del Filter
+| ls
+| pic.ppm
+|
+|
+|
+| pic.ppm
+|
+| /tmp/pardes-snap/images/cwd New Newtty Del Filter
+| ls
+| pic.ppm
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
diff --git a/test/snapshots/jumps.golden b/test/snapshots/jumps.golden
index d517677a..fde7b495 100644
--- a/test/snapshots/jumps.golden
+++ b/test/snapshots/jumps.golden
@@ -1,6 +1,6 @@
== snap start grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -30,8 +30,8 @@
| 27 line 27
| 28 line 28
== snap to-shell grid=150x30 cursor=79,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 1 line 1 ls
| 2 line 2 big.txt
| 3 line 3
@@ -61,8 +61,8 @@
| 27 line 27
| 28 line 28
== snap to-file grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 1 line 1 ls
| 2 line 2 big.txt
| 3 line 3
@@ -92,8 +92,8 @@
| 27 line 27
| 28 line 28
== snap goto-100 grid=150x30 cursor=7,26
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 76 line 76 ls
| 77 line 77 big.txt
| 78 line 78
@@ -123,8 +123,8 @@
| 102 line 102
| 103 line 103
== snap back-in-file grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 1 line 1 ls
| 2 line 2 big.txt
| 3 line 3
@@ -154,8 +154,8 @@
| 27 line 27
| 28 line 28
== snap back-to-shell grid=150x30 cursor=79,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 1 line 1 ls
| 2 line 2 big.txt
| 3 line 3
@@ -185,8 +185,8 @@
| 27 line 27
| 28 line 28
== snap forward-file grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 1 line 1 ls
| 2 line 2 big.txt
| 3 line 3
@@ -216,8 +216,8 @@
| 27 line 27
| 28 line 28
== snap forward-100 grid=150x30 cursor=7,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 86 line 86 ls
| 87 line 87 big.txt
| 88 line 88
@@ -247,8 +247,8 @@
| 112 line 112
| 113 line 113
== snap last grid=150x30 cursor=79,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 86 line 86 ls
| 87 line 87 big.txt
| 88 line 88
@@ -278,8 +278,8 @@
| 112 line 112
| 113 line 113
== snap last-back grid=150x30 cursor=7,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 86 line 86 ls
| 87 line 87 big.txt
| 88 line 88
@@ -309,8 +309,8 @@
| 112 line 112
| 113 line 113
== snap jumplist grid=150x30 cursor=7,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 86 line 86 ls
| 87 line 87 big.txt
| 88 line 88
@@ -334,14 +334,14 @@
| 106 line 106
| 107 line 107
| 108 line 108
-| /tmp/pardes-snap/jumps/cwd/+Jumps New Del
+| /tmp/pardes-snap/jumps/cwd/+Jumps New Newtty Del
| 1 @p1:3:3 /tmp/pardes-snap/jumps/cwd
| 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1
| 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd
| 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100
== snap step1-shell grid=150x30 cursor=79,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 86 line 86 ls
| 87 line 87 big.txt
| 88 line 88
@@ -365,45 +365,45 @@
| 106 line 106
| 107 line 107
| 108 line 108
-| /tmp/pardes-snap/jumps/cwd/+Jumps New Del
+| /tmp/pardes-snap/jumps/cwd/+Jumps New Newtty Del
| 1 @p1:3:3 /tmp/pardes-snap/jumps/cwd
| 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1
| 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd
| 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100
== style step1-shell
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#262626, 2-54 #949494,#121212, 55-74 d,#121212, 75-76 #ffffff,#626262, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-1 #ffffff,#262626, 2-54 #949494,#121212, 55-74 d,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-40 #bdbdbd,#080808, 41-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-51 #bdbdbd,#080808, 52-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-40 #bdbdbd,#080808, 41-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-55 #bdbdbd,#080808, 56-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#262626, 2-55 #949494,#121212, 56-74 d,#121212, 75-76 #ffffff,#626262, 77-129 #949494,#121212, 130-149 d,#121212,
+|2: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-83 #bdbdbd,#080808, 84-149 d,#080808,
+|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-1 #ffffff,#262626, 2-55 #949494,#121212, 56-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-40 #bdbdbd,#080808, 41-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-51 #bdbdbd,#080808, 52-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-40 #bdbdbd,#080808, 41-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-55 #bdbdbd,#080808, 56-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
== snap step2-file grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 1 line 1 ls
| 2 line 2 big.txt
| 3 line 3
@@ -427,14 +427,14 @@
| 21 line 21
| 22 line 22
| 23 line 23
-| /tmp/pardes-snap/jumps/cwd/+Jumps New Del
+| /tmp/pardes-snap/jumps/cwd/+Jumps New Newtty Del
| 1 @p1:3:3 /tmp/pardes-snap/jumps/cwd
| 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1
| 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd
| 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100
== snap step4-line100 grid=150x30 cursor=7,13
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 89 line 89 ls
| 90 line 90 big.txt
| 91 line 91
@@ -458,14 +458,14 @@
| 109 line 109
| 110 line 110
| 111 line 111
-| /tmp/pardes-snap/jumps/cwd/+Jumps New Del
+| /tmp/pardes-snap/jumps/cwd/+Jumps New Newtty Del
| 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1
| 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd
| 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100
| 5
== snap step-back grid=150x30 cursor=79,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 89 line 89 ls
| 90 line 90 big.txt
| 91 line 91
@@ -489,14 +489,14 @@
| 109 line 109
| 110 line 110
| 111 line 111
-| /tmp/pardes-snap/jumps/cwd/+Jumps New Del
+| /tmp/pardes-snap/jumps/cwd/+Jumps New Newtty Del
| 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1
| 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd
| 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100
| 5
== snap look-row grid=150x30 cursor=7,13
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/jumps/cwd/big.txt Save New Del /tmp/pardes-snap/jumps/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/jumps/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/jumps/cwd New Newtty Del Filter
| 89 line 89 ls
| 90 line 90 big.txt
| 91 line 91
@@ -520,7 +520,7 @@
| 109 line 109
| 110 line 110
| 111 line 111
-| /tmp/pardes-snap/jumps/cwd/+Jumps New Del
+| /tmp/pardes-snap/jumps/cwd/+Jumps New Newtty Del
| 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1
| 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd
| 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100
diff --git a/test/snapshots/jumps.snap b/test/snapshots/jumps.snap
index d7d44967..52791ed1 100644
--- a/test/snapshots/jumps.snap
+++ b/test/snapshots/jumps.snap
@@ -16,14 +16,17 @@ stable 700 20000
# a FILE boots alone now, so this is one column holding big.txt, focused, and
# the stack is one entry deep
snap start
-# two focus moves. The shell has to be opened before it can be walked to, and
-# SPC c n (Newcol) puts it in a column of its own on the right AND focuses it —
-# so opening it IS the first of the two moves, and the stack below is the same
-# one a shell at boot left. Walking straight back to the file does NOT leave
-# `file -> shell -> file` behind: a hop to the entry under the top one is the
-# same two places again, so trackJump swaps them rather than appending, and the
-# stack is `shell -> file` with the file on top (see trackJump).
-key space c n
+# two focus moves. The shell has to be opened before it can be walked to
+# (`New`/`Newcol` open an empty +New scratch now, so the shell is asked for by
+# name): Alt-n opens it AND focuses it, Alt-c moves it into a column of its
+# own on the right — so opening it IS the first of the two moves, and the
+# stack below is the same one a shell at boot left. Walking straight back to
+# the file does NOT leave `file -> shell -> file` behind: a hop to the entry
+# under the top one is the same two places again, so trackJump swaps them
+# rather than appending, and the stack is `shell -> file` with the file on top
+# (see trackJump).
+key a-n
+key a-c
stable 700 15000
snap to-shell
key space w h
diff --git a/test/snapshots/layout-close.golden b/test/snapshots/layout-close.golden
index 667d42dc..eb670b41 100644
--- a/test/snapshots/layout-close.golden
+++ b/test/snapshots/layout-close.golden
@@ -1,18 +1,18 @@
== snap built grid=140x40 cursor=4,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/layout-close/cwd New Del Filter /tmp/pardes-snap/layout-close/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter
| ls ls
| marker.txt marker.txt
|
-| /tmp/pardes-snap/layout-close/cwd New Del Filter
+| /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter
| ls
| marker.txt
|
-| /tmp/pardes-snap/layout-close/cwd New Del Filter
+| /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter
| ls
| marker.txt
|
-| /tmp/pardes-snap/layout-close/cwd New Del Filter
+| /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter
| ls
| marker.txt
|
@@ -20,7 +20,7 @@
|
|
|
-| /tmp/pardes-snap/layout-close/cwd New Del Filter
+| /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter
| ls
| marker.txt
|
@@ -40,8 +40,8 @@
|
|
== snap altc grid=140x40 cursor=39,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter
| ls ls ls
| marker.txt marker.txt marker.txt
|
@@ -81,8 +81,8 @@
|
|
== snap del grid=140x40 cursor=39,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter
| ls ls ls
| marker.txt marker.txt marker.txt
|
@@ -122,8 +122,8 @@
|
|
== snap exit grid=140x40 cursor=39,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter
| ls ls ls
| marker.txt marker.txt marker.txt
|
@@ -163,8 +163,8 @@
|
|
== snap colclose grid=140x40 cursor=4,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/layout-close/cwd New Del Filter /tmp/pardes-snap/layout-close/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter
| ls ls
| marker.txt marker.txt
|
@@ -184,7 +184,7 @@
|
|
|
-| /tmp/pardes-snap/layout-close/cwd New Del Filter
+| /tmp/pardes-snap/layout-close/cwd New Newtty Del Filter
| ls
| marker.txt
|
diff --git a/test/snapshots/layout-open.golden b/test/snapshots/layout-open.golden
index e8ae21f4..0e37c054 100644
--- a/test/snapshots/layout-open.golden
+++ b/test/snapshots/layout-open.golden
@@ -1,6 +1,6 @@
== snap before grid=100x30 cursor=2,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/layout-open/cwd New Del Filter /tmp/pardes-snap/layout-open/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del /tmp/pardes-snap/layout-open/cwd New Newtty Del
| ls ls
| sub sub
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/layout-open/cwd New Del Filter
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del
| ls
| sub
|
@@ -30,12 +30,12 @@
|
|
== snap altn-left grid=100x30 cursor=4,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/layout-open/cwd New Del Filter /tmp/pardes-snap/layout-open/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del /tmp/pardes-snap/layout-open/cwd New Newtty Del
| ls ls
| sub sub
|
-| /tmp/pardes-snap/layout-open/cwd New Del Filter
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del
| ls
| sub
|
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/layout-open/cwd New Del Filter
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del
| ls
| sub
|
@@ -61,12 +61,12 @@
|
|
== snap altn-right grid=100x30 cursor=54,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/layout-open/cwd New Del Filter /tmp/pardes-snap/layout-open/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del /tmp/pardes-snap/layout-open/cwd New Newtty Del
| ls ls
| sub sub
|
-| /tmp/pardes-snap/layout-open/cwd New Del Filter /tmp/pardes-snap/layout-open/cwd New Del Filter
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del /tmp/pardes-snap/layout-open/cwd New Newtty Del
| ls ls
| sub sub
|
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/layout-open/cwd New Del Filter
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del
| ls
| sub
|
@@ -92,14 +92,14 @@
|
|
== snap file-open grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/layout /tmp/pardes-snap/layout /tmp/pardes-snap/layout-open/cwd New Del Filter
-| 1 echo 'TTY'OK ls ls
-| sub sub
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/layout-open/cwd/sub/f.txt Save /tmp/pardes-snap/layout-open/cwd New Newtty Del
+| 1 echo 'TTY'OK ls
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del sub
|
-| /tmp/pardes-snap/layout /tmp/pardes-snap/layout-open/cwd New Del Filter
-| ls ls
-| sub sub
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del /tmp/pardes-snap/layout-open/cwd New Newtty Del
+| ls ls
+| sub sub
|
|
|
@@ -108,9 +108,9 @@
|
|
|
-| /tmp/pardes-snap/layout
-| ls
-| sub
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del
+| ls
+| sub
|
|
|
@@ -118,30 +118,30 @@
|
|
|
-| sub/f.txt
+| sub/f.txt
|
|
|
== snap ttydir grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/layout /tmp/pardes-snap/layout /tmp/pardes-snap/layout-open/cwd New Del Filter
-| 1 echo 'TTY'OK ls ls
-| sub sub
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/layout-open/cwd/sub/f.txt Save /tmp/pardes-snap/layout-open/cwd New Newtty Del
+| 1 echo 'TTY'OK ls
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del sub
|
-| /tmp/pardes-snap/layout /tmp/pardes-snap/layout-open/cwd New Del Filter
-| ls ls
-| sub sub
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del /tmp/pardes-snap/layout-open/cwd New Newtty Del
+| ls ls
+| sub sub
|
-| /tmp/pardes-snap/layout-open/cwd/sub New Del Fil
+| /tmp/pardes-snap/layout-open/cwd/sub New Newtty
| echo 'TTY'OK
| TTYOK
|
|
|
|
-| /tmp/pardes-snap/layout
-| ls
-| sub
+| /tmp/pardes-snap/layout-open/cwd New Newtty Del
+| ls
+| sub
|
|
|
@@ -149,7 +149,7 @@
|
|
|
-| sub/f.txt
+| sub/f.txt
|
|
|
diff --git a/test/snapshots/leader.golden b/test/snapshots/leader.golden
index 4ef7c4a6..cbb07c93 100644
--- a/test/snapshots/leader.golden
+++ b/test/snapshots/leader.golden
@@ -1,6 +1,6 @@
== snap spc grid=100x40 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -40,8 +40,8 @@
|
| SPC
== snap spc-h grid=100x40 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -81,8 +81,8 @@
|
| SPC h
== snap abandoned grid=100x40 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -122,8 +122,8 @@
|
|
== snap unmapped grid=100x40 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -163,8 +163,8 @@
|
|
== snap help-word grid=100x40 cursor=7,22
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -184,7 +184,7 @@
|
|
|
-| /tmp/pardes-snap/leader/cwd/+Help New Del
+| /tmp/pardes-snap/leader/cwd/+Help New Newtty Del
| 1 pardes builtins, and how to run each:
| 2 SPC and its keys, a chord, a button, the
| 3 topbar - or the name, executed anywhere.
@@ -204,8 +204,8 @@
| 17 SPC a v PanelVertical
| 18 SPC a w PanelWave
== snap help-group grid=100x40 cursor=7,22
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -225,12 +225,12 @@
|
|
|
-| /tmp/pardes-snap/leader/cwd/+Help New Del
+| /tmp/pardes-snap/leader/cwd/+Help New Newtty Del
| 1 pardes builtins under SPC h
| 2
-| 3 SPC h t Tutor topbar
-| 4
-|
+| 3 SPC h c Changelog topbar
+| 4 SPC h t Tutor topbar
+| 5
|
|
|
@@ -245,8 +245,8 @@
|
|
== snap tutor grid=100x40 cursor=7,12
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -256,7 +256,7 @@
|
|
|
-| /Tutor Save New Del
+| /Tutor Save New Newtty Del
| 1
| 2 PARDES TUTOR
| 3 tmux + vi + acme, from scratch.
@@ -266,12 +266,12 @@
| 7 Press j until you reach the introduction.
| 8
| 9
-| /tmp/pardes-snap/leader/cwd/+Help New Del
+| /tmp/pardes-snap/leader/cwd/+Help New Newtty Del
| 1 pardes builtins under SPC h
| 2
-| 3 SPC h t Tutor topbar
-| 4
-|
+| 3 SPC h c Changelog topbar
+| 4 SPC h t Tutor topbar
+| 5
|
|
|
@@ -286,8 +286,8 @@
|
|
== snap deleted grid=100x40 cursor=7,22
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -307,12 +307,12 @@
|
|
|
-| /tmp/pardes-snap/leader/cwd/+Help New Del
+| /tmp/pardes-snap/leader/cwd/+Help New Newtty Del
| 1 pardes builtins under SPC h
| 2
-| 3 SPC h t Tutor topbar
-| 4
-|
+| 3 SPC h c Changelog topbar
+| 4 SPC h t Tutor topbar
+| 5
|
|
|
@@ -327,8 +327,8 @@
|
|
== snap help-all grid=100x40 cursor=7,22
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -348,7 +348,7 @@
|
|
|
-| /tmp/pardes-snap/leader/cwd/+Help New Del
+| /tmp/pardes-snap/leader/cwd/+Help New Newtty Del
| 1 pardes builtins, and how to run each:
| 2 SPC and its keys, a chord, a button, the
| 3 topbar - or the name, executed anywhere.
@@ -368,8 +368,8 @@
| 17 SPC a v PanelVertical
| 18 SPC a w PanelWave
== snap help-toggles grid=100x40 cursor=7,22
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -389,7 +389,7 @@
|
|
|
-| /tmp/pardes-snap/leader/cwd/+Help New Del
+| /tmp/pardes-snap/leader/cwd/+Help New Newtty Del
| 1 pardes builtins under SPC t
| 2
| 3 SPC t a Ascii
@@ -409,8 +409,8 @@
|
|
== snap help-window grid=100x40 cursor=7,22
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -430,7 +430,7 @@
|
|
|
-| /tmp/pardes-snap/leader/cwd/+Help New Del
+| /tmp/pardes-snap/leader/cwd/+Help New Newtty Del
| 1 pardes builtins under SPC w
| 2
| 3 SPC w h Left C-w h, C-w left
@@ -450,8 +450,8 @@
|
|
== snap help-language grid=100x40 cursor=7,22
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
@@ -471,7 +471,7 @@
|
|
|
-| /tmp/pardes-snap/leader/cwd/+Help New Del
+| /tmp/pardes-snap/leader/cwd/+Help New Newtty Del
| 1 pardes builtins under SPC l
| 2
| 3 SPC l D WsDiagnostics
@@ -491,8 +491,8 @@
|
|
== snap del-output grid=100x40 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/leader/cwd/cmds.txt Save New Newtty Del
| 1 Help
|
|
diff --git a/test/snapshots/load.golden b/test/snapshots/load.golden
index 27285369..4d6b193e 100644
--- a/test/snapshots/load.golden
+++ b/test/snapshots/load.golden
@@ -1,6 +1,6 @@
== snap loaded grid=100x30 cursor=4,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/load/cwd New Del Filter /tmp/pardes-snap/load/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/load/cwd New Newtty Del Filter /tmp/pardes-snap/load/cwd New Newtty Del Filter
| echo LOAD''MARK; seq 1 40 ls
| LOADMARK d.txt
| 1
@@ -15,7 +15,7 @@
| 10
| 11
| 12
-| /tmp/pardes-snap/load/cwd New Del Filter
+| /tmp/pardes-snap/load/cwd New Newtty Del Filter
| ls
| d.txt
|
@@ -30,33 +30,33 @@
|
|
== style loaded
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-41 #949494,#121212, 42-49 d,#121212, 50-51 #ffffff,#262626, 52-91 #949494,#121212, 92-99 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|6: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|7: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|8: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|9: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|10: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|11: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|12: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|13: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|14: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|15: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|16: 0-1 #ffffff,#262626, 2-41 #949494,#121212, 42-49 d,#121212, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-48 #949494,#121212, 49-49 d,#121212, 50-51 #ffffff,#262626, 52-98 #949494,#121212, 99-99 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-26 #bdbdbd,#080808, 27-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-53 #bdbdbd,#080808, 54-99 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-9 #bdbdbd,#080808, 10-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-56 #bdbdbd,#080808, 57-99 d,#080808,
+|4: 0-0 d,#444444, 1-1 d,#080808, 2-2 #bdbdbd,#080808, 3-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-2 #bdbdbd,#080808, 3-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|6: 0-0 d,#121212, 1-1 d,#080808, 2-2 #bdbdbd,#080808, 3-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-2 #bdbdbd,#080808, 3-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|8: 0-0 d,#121212, 1-1 d,#080808, 2-2 #bdbdbd,#080808, 3-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|9: 0-0 d,#121212, 1-1 d,#080808, 2-2 #bdbdbd,#080808, 3-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|10: 0-0 d,#121212, 1-1 d,#080808, 2-2 #bdbdbd,#080808, 3-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|11: 0-0 d,#121212, 1-1 d,#080808, 2-2 #bdbdbd,#080808, 3-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|12: 0-0 d,#121212, 1-1 d,#080808, 2-2 #bdbdbd,#080808, 3-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|13: 0-0 d,#121212, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|14: 0-0 d,#121212, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|15: 0-0 d,#121212, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-48 #949494,#121212, 49-49 d,#121212, 50-50 d,#444444, 51-99 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|19: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|20: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|21: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|22: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|23: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|24: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|25: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|26: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|27: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|28: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|29: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
diff --git a/test/snapshots/load.snap b/test/snapshots/load.snap
index f40a78bb..24552836 100644
--- a/test/snapshots/load.snap
+++ b/test/snapshots/load.snap
@@ -17,8 +17,8 @@ stable 600 8000
wheel up 10 8
wheel up 10 8
stable 500 8000
-press middle 33 1
-release middle 33 1
+press middle 52 1
+release middle 52 1
stable 600 8000
start 30 100 -l $DUMP
wait 8000 LOADMARK
diff --git a/test/snapshots/logquiet.golden b/test/snapshots/logquiet.golden
index f49e7754..9540ca2f 100644
--- a/test/snapshots/logquiet.golden
+++ b/test/snapshots/logquiet.golden
@@ -1,6 +1,6 @@
== snap quiet grid=100x30 cursor=62,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/logquiet/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/logquiet/cwd New Newtty Del Filter
| $ ls
| $ printf '\033_Ga=q,i=1,s=1,v=1,f=24,t=d;AAAA\033\\\033[>0p'
| $ '\033_Ga=q,i=1,s=1,v=1,f=24,t=d;AAAA\033\\\033[>0p'Gi=1;OK
diff --git a/test/snapshots/look-center.golden b/test/snapshots/look-center.golden
index ca4ea9c2..67a0dac1 100644
--- a/test/snapshots/look-center.golden
+++ b/test/snapshots/look-center.golden
@@ -1,93 +1,93 @@
-== snap center-open grid=150x30 cursor=7,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/look-center/cwd/big /tmp/pardes-snap/look-center/cwd Ne /tmp/pardes-snap/look-center/cwd New Del Filter
-| 86 line 86 ls ls
-| 87 line 87 big.txt big.txt
-| 88 line 88
-| 89 line 89
-| 90 line 90
-| 91 line 91 big.txt:100 big.txt:150 big.txt:2
-| 92 line 92
-| 93 line 93
-| 94 line 94
-| 95 line 95
-| 96 line 96
-| 97 line 97
-| 98 line 98
+== snap center-open grid=150x30 cursor=7,5
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/look-center/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/look-center/cwd New Newtty Del Filter
+| 97 line 97 ls
+| 98 line 98 big.txt
| 99 line 99
-| 100 line 100 /tmp/pardes-snap/look-center/cwd Ne
-| 101 line 101 ls
-| 102 line 102 big.txt
-| 103 line 103
-| 104 line 104
-| 105 line 105
-| 106 line 106
-| 107 line 107
-| 108 line 108
-| 109 line 109
-| 110 line 110
-| 111 line 111
-| 112 line 112
-| 113 line 113
-== snap center-dedup grid=150x30 cursor=17,14
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/look-center/cwd/big /tmp/pardes-snap/look-center/cwd Ne /tmp/pardes-snap/look-center/cwd New Del Filter
-| 86 line 86 ls ls
-| 87 line 87 big.txt big.txt
-| 88 line 88
-| 89 line 89
-| 90 line 90
-| 91 line 91 big.txt:100 big.txt:150 big.txt:2
-| 92 line 92
-| 93 line 93
-| 94 line 94
-| 95 line 95
-| 96 line 96
-| 97 line 97
-| 98 line 98
-| 99 line 99
-| 100 line 100 /tmp/pardes-snap/look-center/cwd Ne
-| 101 line 101 ls
-| 102 line 102 big.txt
-| 103 line 103
-| 104 line 104
-| 105 line 105
-| 106 line 106
-| 107 line 107
-| 108 line 108
-| 109 line 109
-| 110 line 110
-| 111 line 111
-| 112 line 112
-| 113 line 113
-== snap center-clamp grid=150x30 cursor=29,14
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/look-center/cwd/big /tmp/pardes-snap/look-center/cwd Ne /tmp/pardes-snap/look-center/cwd New Del Filter
-| 86 line 86 ls ls
-| 87 line 87 big.txt big.txt
-| 88 line 88
-| 89 line 89
-| 90 line 90
-| 91 line 91 big.txt:100 big.txt:150 big.txt:2
-| 92 line 92
-| 93 line 93
-| 94 line 94
-| 95 line 95
-| 96 line 96
-| 97 line 97
-| 98 line 98
-| 99 line 99
-| 100 line 100 /tmp/pardes-snap/look-center/cwd Ne
-| 101 line 101 ls
-| 102 line 102 big.txt
-| 103 line 103
-| 104 line 104
-| 105 line 105
-| 106 line 106
-| 107 line 107
-| 108 line 108
-| 109 line 109
-| 110 line 110
-| 111 line 111
-| 112 line 112
-| 113 line 113
+| 100 line 100
+| 101 line 101
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/look-center/cwd New Newtty Del Filter
+| ls
+| big.txt
+|
+|
+|
+| big.txt:100 big.txt:150 big.txt:2
+|
+| /tmp/pardes-snap/look-center/cwd New Newtty Del Filter
+| ls
+| big.txt
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+== snap center-dedup grid=150x30 cursor=7,5
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/look-center/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/look-center/cwd New Newtty Del Filter
+| 147 line 147 ls
+| 148 line 148 big.txt
+| 149 line 149
+| 150 line 150
+| 151 line 151
+| 152 line 152
+| /tmp/pardes-snap/look-center/cwd New Newtty Del Filter
+| ls
+| big.txt
+|
+|
+|
+| big.txt:100 big.txt:150 big.txt:2
+|
+| /tmp/pardes-snap/look-center/cwd New Newtty Del Filter
+| ls
+| big.txt
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+== snap center-clamp grid=150x30 cursor=7,3
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/look-center/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/look-center/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 line 2 big.txt
+| 3 line 3
+| 4 line 4
+| 5 line 5
+| 6 line 6
+| /tmp/pardes-snap/look-center/cwd New Newtty Del Filter
+| ls
+| big.txt
+|
+|
+|
+| big.txt:100 big.txt:150 big.txt:2
+|
+| /tmp/pardes-snap/look-center/cwd New Newtty Del Filter
+| ls
+| big.txt
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
diff --git a/test/snapshots/look-dir.golden b/test/snapshots/look-dir.golden
index fbbaeec0..9dd22a84 100644
--- a/test/snapshots/look-dir.golden
+++ b/test/snapshots/look-dir.golden
@@ -1,10 +1,10 @@
== snap dir-open grid=100x30 cursor=4,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/look-dir/cwd New Del Filter /tmp/pardes-snap/look-dir/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/look-dir/cwd New Newtty Del Fil /tmp/pardes-snap/look-dir/cwd New Newtty Del Fil
| ls ls
| sub top.txt sub top.txt
|
-| /tmp/pardes-snap/look-dir/cwd/sub New Del Filter
+| /tmp/pardes-snap/look-dir/cwd/sub New Newtty Del
| ls
| inner.txt
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/look-dir/cwd New Del Filter
+| /tmp/pardes-snap/look-dir/cwd New Newtty Del Fil
| ls
| sub top.txt
|
diff --git a/test/snapshots/look-file-1col.golden b/test/snapshots/look-file-1col.golden
index 9b60b61c..47fc7fac 100644
--- a/test/snapshots/look-file-1col.golden
+++ b/test/snapshots/look-file-1col.golden
@@ -1,14 +1,6 @@
-== snap file-open-1col grid=100x30 cursor=7,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/look-file-1col/cwd/big.txt Save /tmp/pardes-snap/look-file-1col/cwd New Del Filt
-| 26 line 26 ls
-| 27 line 27 big.txt
-| 28 line 28
-| 29 line 29
-| 30 line 30
-| 31 line 31 big.txt:40
-| 32 line 32
-| 33 line 33
+== snap file-open-1col grid=100x30 cursor=7,8
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/look-file-1col/cwd/big.txt Save New Newtty Del
| 34 line 34
| 35 line 35
| 36 line 36
@@ -22,10 +14,18 @@
| 44 line 44
| 45 line 45
| 46 line 46
-| 47 line 47
-| 48 line 48
-| 49 line 49
-| 50 line 50
-| 51 line 51
-| 52 line 52
-| 53 line 53
+| /tmp/pardes-snap/look-file-1col/cwd New Newtty Del Filter
+| ls
+| big.txt
+|
+|
+|
+| big.txt:40
+|
+|
+|
+|
+|
+|
+|
+|
diff --git a/test/snapshots/look-file.golden b/test/snapshots/look-file.golden
index d443823d..368d2f70 100644
--- a/test/snapshots/look-file.golden
+++ b/test/snapshots/look-file.golden
@@ -1,62 +1,62 @@
-== snap file-open grid=150x30 cursor=7,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/look-file/cwd/big.t /tmp/pardes-snap/look-file/cwd New /tmp/pardes-snap/look-file/cwd New Del Filter
-| 26 line 26 ls ls
-| 27 line 27 big.txt big.txt
-| 28 line 28
-| 29 line 29
-| 30 line 30
-| 31 line 31 big.txt:40
-| 32 line 32
-| 33 line 33
-| 34 line 34
-| 35 line 35
-| 36 line 36
-| 37 line 37
-| 38 line 38
+== snap file-open grid=150x30 cursor=7,5
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/look-file/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/look-file/cwd New Newtty Del Filter
+| 37 line 37 ls
+| 38 line 38 big.txt
| 39 line 39
-| 40 line 40 /tmp/pardes-snap/look-file/cwd New
-| 41 line 41 ls
-| 42 line 42 big.txt
-| 43 line 43
-| 44 line 44
-| 45 line 45
-| 46 line 46
-| 47 line 47
-| 48 line 48
-| 49 line 49
-| 50 line 50
-| 51 line 51
-| 52 line 52
-| 53 line 53
+| 40 line 40
+| 41 line 41
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/look-file/cwd New Newtty Del Filter
+| ls
+| big.txt
+|
+|
+|
+| big.txt:40
+|
+| /tmp/pardes-snap/look-file/cwd New Newtty Del Filter
+| ls
+| big.txt
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
== style file-open
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-51 #bdbdbd,#080808, 52-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-59 #949494,#121212, 60-74 d,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
+|2: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-83 #bdbdbd,#080808, 84-149 d,#080808,
+|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-59 #949494,#121212, 60-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-13 #bdbdbd,#080808, 14-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-59 #949494,#121212, 60-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
diff --git a/test/snapshots/lookloaded.golden b/test/snapshots/lookloaded.golden
index ab25efdf..7b5f462d 100644
--- a/test/snapshots/lookloaded.golden
+++ b/test/snapshots/lookloaded.golden
@@ -1,93 +1,93 @@
-== snap file-open grid=100x30 cursor=7,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/looklo /tmp/pardes-snap/looklo /tmp/pardes-snap/lookloaded/cwd New Del Filter
-| 26 line 26 ls ls
-| 27 line 27 big.txt big.txt
-| 28 line 28
-| 29 line 29
-| 30 line 30
-| 31 line 31 big.txt:40 big.txt:10
-| 32 line 32
-| 33 line 33
-| 34 line 34
-| 35 line 35
-| 36 line 36
-| 37 line 37
-| 38 line 38
+== snap file-open grid=100x30 cursor=7,5
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookloaded/cwd/big.txt Save New /tmp/pardes-snap/lookloaded/cwd New Newtty Del F
+| 37 line 37 ls
+| 38 line 38 big.txt
| 39 line 39
-| 40 line 40 /tmp/pardes-snap/looklo
-| 41 line 41 ls
-| 42 line 42 big.txt
-| 43 line 43
-| 44 line 44
-| 45 line 45
-| 46 line 46
-| 47 line 47
-| 48 line 48
-| 49 line 49
-| 50 line 50
-| 51 line 51
-| 52 line 52
-| 53 line 53
-== snap removed grid=100x30 cursor=29,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/looklo /tmp/pardes-snap/looklo /tmp/pardes-snap/lookloaded/cwd New Del Filter
-| 26 line 26 ls ls
-| 27 line 27 big.txt big.txt
-| 28 line 28 rm big.txt; echo GO''
-| 29 line 29 NE
-| 30 line 30 GONE
-| 31 line 31 big.txt:40 big.txt:10
-| 32 line 32
-| 33 line 33
-| 34 line 34
-| 35 line 35
-| 36 line 36
-| 37 line 37
-| 38 line 38
+| 40 line 40
+| 41 line 41
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/lookloaded/cwd New Newtty Del F
+| ls
+| big.txt
+|
+|
+|
+| big.txt:40 big.txt:10
+|
+| /tmp/pardes-snap/lookloaded/cwd New Newtty Del F
+| ls
+| big.txt
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+== snap removed grid=100x30 cursor=4,13
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookloaded/cwd/big.txt Save New /tmp/pardes-snap/lookloaded/cwd New Newtty Del F
+| 37 line 37 ls
+| 38 line 38 big.txt
| 39 line 39
-| 40 line 40 /tmp/pardes-snap/looklo
-| 41 line 41 ls
-| 42 line 42 big.txt
-| 43 line 43
-| 44 line 44
-| 45 line 45
-| 46 line 46
-| 47 line 47
-| 48 line 48
-| 49 line 49
-| 50 line 50
-| 51 line 51
-| 52 line 52
-| 53 line 53
-== snap look-noFS grid=100x30 cursor=7,11
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/looklo /tmp/pardes-snap/looklo /tmp/pardes-snap/lookloaded/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 line 2 big.txt big.txt
-| 3 line 3 rm big.txt; echo GO''
-| 4 line 4 NE
-| 5 line 5 GONE
-| 6 line 6 big.txt:40 big.txt:10
-| 7 line 7
-| 8 line 8
-| 9 line 9
-| 10 line 10
-| 11 line 11
-| 12 line 12
-| 13 line 13
-| 14 line 14
-| 15 line 15 /tmp/pardes-snap/looklo
-| 16 line 16 ls
-| 17 line 17 big.txt
-| 18 line 18
-| 19 line 19
-| 20 line 20
-| 21 line 21
-| 22 line 22
-| 23 line 23
-| 24 line 24
-| 25 line 25
-| 26 line 26
-| 27 line 27
-| 28 line 28
+| 40 line 40
+| 41 line 41
+| 42 line 42
+| /tmp/pardes-snap/lookloaded/cwd New Newtty Del F
+| ls
+| big.txt
+| rm big.txt; echo GO''NE
+| GONE
+|
+| big.txt:40 big.txt:10
+|
+| /tmp/pardes-snap/lookloaded/cwd New Newtty Del F
+| ls
+| big.txt
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+== snap look-noFS grid=100x30 cursor=44,7
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookloaded/cwd/big.txt Save New /tmp/pardes-snap/lookloaded/cwd New Newtty Del F
+| 37 line 37 ls
+| 38 line 38 big.txt
+| 39 line 39
+| 40 line 40
+| 41 line 41
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/lookloaded/cwd New Newtty Del F
+| ls
+| big.txt
+| rm big.txt; echo GO''NE
+| GONE
+|
+| big.txt:40 big.txt:10
+|
+| /tmp/pardes-snap/lookloaded/cwd New Newtty Del F
+| ls
+| big.txt
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
diff --git a/test/snapshots/lookpanes.golden b/test/snapshots/lookpanes.golden
index 6ed75bc7..2e079e11 100644
--- a/test/snapshots/lookpanes.golden
+++ b/test/snapshots/lookpanes.golden
@@ -1,10 +1,10 @@
== snap shells grid=130x50 cursor=122,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Del /tmp/pardes-snap/lookpanes/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Newtty D /tmp/pardes-snap/lookpanes/cwd New Newtty Del Filter
| 1 both.txt ls
| 2 b-marker alpha beta zzboot.txt zqonly.txt pick.txt twin.txt
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha New Del Filter
+| /tmp/pardes-snap/lookpanes/cwd/alpha New Newtty Del Filter
| ls
| amark.txt both.txt pick.txt twin.txt zqonly.txt
|
@@ -50,12 +50,12 @@
|
|
== snap other-dir grid=130x50 cursor=7,27
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Del /tmp/pardes-snap/lookpanes/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Newtty D /tmp/pardes-snap/lookpanes/cwd New Newtty Del Filter
| 1 both.txt ls
| 2 b-marker alpha beta zzboot.txt zqonly.txt pick.txt twin.txt
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha New Del Filter
+| /tmp/pardes-snap/lookpanes/cwd/alpha New Newtty Del Filter
| ls
| amark.txt both.txt pick.txt twin.txt zqonly.txt
|
@@ -76,7 +76,7 @@
|
|
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha/zqonly.txt Save New Del
+| /tmp/pardes-snap/lookpanes/cwd/alpha/zqonly.txt Save New Newtty
| 1 ONLY-IN-ALPHA
|
|
@@ -101,12 +101,12 @@
|
|
== snap clicked-wins grid=130x50 cursor=7,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Del /tmp/pardes-snap/lookpanes/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Newtty D /tmp/pardes-snap/lookpanes/cwd New Newtty Del Filter
| 1 both.txt ls
| 2 b-marker alpha beta zzboot.txt zqonly.txt pick.txt twin.txt
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha New Del Filter
+| /tmp/pardes-snap/lookpanes/cwd/alpha New Newtty Del Filter
| ls
| amark.txt both.txt pick.txt twin.txt zqonly.txt
|
@@ -115,7 +115,7 @@
|
|
|
-| /tmp/pardes-snap/lookpanes/cwd/beta/both.txt Save New Del
+| /tmp/pardes-snap/lookpanes/cwd/beta/both.txt Save New Newtty De
| 1 BOTH-FROM-BETA
|
|
@@ -127,7 +127,7 @@
|
|
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha/zqonly.txt Save New Del
+| /tmp/pardes-snap/lookpanes/cwd/alpha/zqonly.txt Save New Newtty
| 1 ONLY-IN-ALPHA
|
|
@@ -152,12 +152,12 @@
|
|
== snap mru-alpha grid=130x50 cursor=7,21
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Del /tmp/pardes-snap/lookpanes/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Newtty D /tmp/pardes-snap/lookpanes/cwd New Newtty Del Filter
| 1 both.txt ls
| 2 b-marker alpha beta zzboot.txt zqonly.txt pick.txt twin.txt
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha New Del Filter
+| /tmp/pardes-snap/lookpanes/cwd/alpha New Newtty Del Filter
| ls
| amark.txt both.txt pick.txt twin.txt zqonly.txt
|
@@ -166,19 +166,19 @@
|
|
|
-| /tmp/pardes-snap/lookpanes/cwd/beta/both.txt Save New Del
+| /tmp/pardes-snap/lookpanes/cwd/beta/both.txt Save New Newtty De
| 1 BOTH-FROM-BETA
|
|
|
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha/pick.txt Save New Del
+| /tmp/pardes-snap/lookpanes/cwd/alpha/pick.txt Save New Newtty D
| 1 PICK-FROM-ALPHA
|
|
|
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha/zqonly.txt Save New Del
+| /tmp/pardes-snap/lookpanes/cwd/alpha/zqonly.txt Save New Newtty
| 1 ONLY-IN-ALPHA
|
|
@@ -203,33 +203,33 @@
|
|
== snap mru-beta grid=130x50 cursor=7,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Del /tmp/pardes-snap/lookpanes/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookpanes/cwd/beta/bmark.txt Save New Newtty D /tmp/pardes-snap/lookpanes/cwd New Newtty Del Filter
| 1 both.txt ls
| 2 b-marker alpha beta zzboot.txt zqonly.txt pick.txt twin.txt
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha New Del Filter
+| /tmp/pardes-snap/lookpanes/cwd/alpha New Newtty Del Filter
| ls
| amark.txt both.txt pick.txt twin.txt zqonly.txt
-| /tmp/pardes-snap/lookpanes/cwd/beta/twin.txt Save New Del
+| /tmp/pardes-snap/lookpanes/cwd/beta/twin.txt Save New Newtty De
| 1 TWIN-FROM-BETA
|
|
|
|
-| /tmp/pardes-snap/lookpanes/cwd/beta/both.txt Save New Del
+| /tmp/pardes-snap/lookpanes/cwd/beta/both.txt Save New Newtty De
| 1 BOTH-FROM-BETA
|
|
|
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha/pick.txt Save New Del
+| /tmp/pardes-snap/lookpanes/cwd/alpha/pick.txt Save New Newtty D
| 1 PICK-FROM-ALPHA
|
|
|
|
-| /tmp/pardes-snap/lookpanes/cwd/alpha/zqonly.txt Save New Del
+| /tmp/pardes-snap/lookpanes/cwd/alpha/zqonly.txt Save New Newtty
| 1 ONLY-IN-ALPHA
|
|
@@ -254,53 +254,53 @@
|
|
== style mru-beta
-|0: 0-56 #949494,#121212, 57-129 d,#121212,
-|1: 0-1 #ffffff,#262626, 2-61 #949494,#121212, 62-64 d,#121212, 65-66 #ffffff,#262626, 67-117 #949494,#121212, 118-129 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-129 d,#121212,
+|1: 0-1 #ffffff,#262626, 2-64 #949494,#121212, 65-66 #ffffff,#262626, 67-124 #949494,#121212, 125-129 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-68 #bdbdbd,#080808, 69-129 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-121 #bdbdbd,#080808, 122-129 d,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-66 #ffffff,#262626, 67-117 #949494,#121212, 118-129 d,#121212,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|8: 0-1 #ffffff,#626262, 2-61 #949494,#121212, 62-64 d,#121212, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-20 #bdbdbd,#080808, 21-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|14: 0-1 #ffffff,#262626, 2-61 #949494,#121212, 62-64 d,#121212, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|20: 0-1 #ffffff,#262626, 2-61 #949494,#121212, 62-64 d,#121212, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-21 #bdbdbd,#080808, 22-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|26: 0-1 #ffffff,#262626, 2-61 #949494,#121212, 62-64 d,#121212, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|30: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|31: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|32: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|33: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|34: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|35: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|36: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|37: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|38: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|39: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|40: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|41: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|42: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|43: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|44: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|45: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|46: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|47: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|48: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
-|49: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-129 #bdbdbd,#080808,
+|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-66 #ffffff,#262626, 67-124 #949494,#121212, 125-129 d,#121212,
+|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-68 #bdbdbd,#080808, 69-129 d,#080808,
+|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-66 d,#080808, 67-117 #bdbdbd,#080808, 118-129 d,#080808,
+|8: 0-1 #ffffff,#626262, 2-64 #949494,#121212, 65-65 d,#444444, 66-129 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-20 #bdbdbd,#080808, 21-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|14: 0-1 #ffffff,#262626, 2-64 #949494,#121212, 65-65 d,#444444, 66-129 d,#080808,
+|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|20: 0-1 #ffffff,#262626, 2-64 #949494,#121212, 65-65 d,#444444, 66-129 d,#080808,
+|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-21 #bdbdbd,#080808, 22-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|26: 0-1 #ffffff,#262626, 2-64 #949494,#121212, 65-65 d,#444444, 66-129 d,#080808,
+|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|30: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|31: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|32: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|33: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|34: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|35: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|36: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|37: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|38: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|39: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|40: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|41: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|42: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|43: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|44: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|45: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|46: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|47: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|48: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
+|49: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-64 d,#080808, 65-65 d,#444444, 66-129 d,#080808,
diff --git a/test/snapshots/lookpanes.snap b/test/snapshots/lookpanes.snap
index 137a68f2..f05b5ec7 100644
--- a/test/snapshots/lookpanes.snap
+++ b/test/snapshots/lookpanes.snap
@@ -15,14 +15,16 @@ file beta/pick.txt PICK-FROM-BETA
file beta/twin.txt TWIN-FROM-BETA
file beta/both.txt BOTH-FROM-BETA
# the file argument opens a pane whose directory is beta's, and nothing else —
-# so the workdir shell every look below falls through is opened with SPC c n,
-# in a column of its own on the right; its first line is a word to look FROM
-# that pane
+# so the workdir shell every look below falls through is opened with Alt-n
+# (`New`/`Newcol` open an empty +New scratch now, and one inheriting beta's
+# directory at that) and Alt-c puts it in a column of its own on the right;
+# its first line is a word to look FROM that pane
file beta/bmark.txt both.txt\nb-marker
start 50 130 beta/bmark.txt
wait 8000 b-marker
stable 700 20000
-key space c n
+key a-n
+key a-c
wait 8000 zzboot.txt
stable 700 20000
key space w h
diff --git a/test/snapshots/lookrange.golden b/test/snapshots/lookrange.golden
index 8ed06206..de341750 100644
--- a/test/snapshots/lookrange.golden
+++ b/test/snapshots/lookrange.golden
@@ -1,6 +1,6 @@
== snap opened grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Newtty Del
| 1 r.txt:3-5
| 2 r.txt:7:4-9
| 3 r.txt:3:2-5:3
@@ -30,8 +30,8 @@
|
|
== snap wholelines grid=150x30 cursor=11,21
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Newtty Del
| 1 r.txt:3-5
| 2 r.txt:7:4-9
| 3 r.txt:3:2-5:3
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Del
+| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Newtty Del
| 1 aaaa
| 2 bbbb
| 3 cccc dccc
@@ -61,7 +61,7 @@
|
|
== style wholelines
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
|1: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-149 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-149 d,#080808,
@@ -92,8 +92,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808,
|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808,
== snap onelinespan grid=150x30 cursor=15,23
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Newtty Del
| 1 r.txt:3-5
| 2 r.txt:7:4-9
| 3 r.txt:3:2-5:3
@@ -108,7 +108,7 @@
|
|
|
-| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Del
+| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Newtty Del
| 1 aaaa
| 2 bbbb
| 3 cccc dccc
@@ -123,7 +123,7 @@
|
|
== style onelinespan
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
|1: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-149 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-149 d,#080808,
@@ -154,8 +154,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808,
|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808,
== snap fullspan grid=150x30 cursor=9,21
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Newtty Del
| 1 r.txt:3-5
| 2 r.txt:7:4-9
| 3 r.txt:3:2-5:3
@@ -170,7 +170,7 @@
|
|
|
-| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Del
+| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Newtty Del
| 1 aaaa
| 2 bbbb
| 3 cccc dccc
@@ -185,7 +185,7 @@
|
|
== style fullspan
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
|1: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-149 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-149 d,#080808,
@@ -216,8 +216,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808,
|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808,
== snap stale grid=150x30 cursor=10,24
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Newtty Del
| 1 r.txt:3-5
| 2 r.txt:7:4-9
| 3 r.txt:3:2-5:3
@@ -232,7 +232,7 @@
|
|
|
-| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Del
+| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Newtty Del
| 2 bbbb
| 3 cccc dccc
| 4 dddd
@@ -247,7 +247,7 @@
|
|
== style stale
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
|1: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-149 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-149 d,#080808,
@@ -278,8 +278,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808,
|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-149 d,#080808,
== snap hit1 grid=150x30 cursor=15,23
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Newtty Del
| 1 r.txt:3-5
| 2 r.txt:7:4-9
| 3 r.txt:3:2-5:3
@@ -294,7 +294,7 @@
|
|
|
-| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Del
+| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Newtty Del
| 1 aaaa
| 2 bbbb
| 3 cccc dccc
@@ -305,11 +305,11 @@
| 8 hhhh NEEDLE
| 9 iiii
|
-| /tmp/pardes-snap/lookrange/cwd/+Search New Del
+| /tmp/pardes-snap/lookrange/cwd/+Search New Newtty Del
| 1 r.txt:7:4-9 gg NEEDLE gg
| 2 r.txt:8:6-11 hhhh NEEDLE
== style hit1
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
|1: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-149 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-149 d,#080808,
@@ -340,8 +340,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-149 d,#080808,
|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-149 d,#080808,
== snap hit2 grid=150x30 cursor=17,22
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Newtty Del
| 1 r.txt:3-5
| 2 r.txt:7:4-9
| 3 r.txt:3:2-5:3
@@ -356,7 +356,7 @@
|
|
|
-| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Del
+| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Newtty Del
| 3 cccc dccc
| 4 dddd
| 5 eeee
@@ -367,11 +367,11 @@
|
|
|
-| /tmp/pardes-snap/lookrange/cwd/+Search New Del
+| /tmp/pardes-snap/lookrange/cwd/+Search New Newtty Del
| 1 r.txt:7:4-9 gg NEEDLE gg
| 2 r.txt:8:6-11 hhhh NEEDLE
== style hit2
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
|1: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-149 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-149 d,#080808,
@@ -402,8 +402,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-149 d,#080808,
|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-149 d,#080808,
== snap back grid=150x30 cursor=15,22
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lookrange/cwd/look.txt Save New Newtty Del
| 1 r.txt:3-5
| 2 r.txt:7:4-9
| 3 r.txt:3:2-5:3
@@ -418,7 +418,7 @@
|
|
|
-| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Del
+| /tmp/pardes-snap/lookrange/cwd/r.txt Save New Newtty Del
| 2 bbbb
| 3 cccc dccc
| 4 dddd
@@ -429,11 +429,11 @@
| 9 iiii
|
|
-| /tmp/pardes-snap/lookrange/cwd/+Search New Del
+| /tmp/pardes-snap/lookrange/cwd/+Search New Newtty Del
| 1 r.txt:7:4-9 gg NEEDLE gg
| 2 r.txt:8:6-11 hhhh NEEDLE
== style back
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
|1: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-149 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-149 d,#080808,
diff --git a/test/snapshots/lsp-rename.golden b/test/snapshots/lsp-rename.golden
index 5237554e..556f5324 100644
--- a/test/snapshots/lsp-rename.golden
+++ b/test/snapshots/lsp-rename.golden
@@ -1,6 +1,6 @@
== snap renamed grid=110x24 cursor=17,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsp-rename/cwd/rename.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsp-rename/cwd/rename.zig * Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn renamed_helper(x: u32) u32 {
@@ -24,8 +24,8 @@
|
|
== snap undone grid=110x24 cursor=17,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsp-rename/cwd/rename.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsp-rename/cwd/rename.zig * Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper(x: u32) u32 {
@@ -49,8 +49,8 @@
|
|
== snap redone grid=110x24 cursor=17,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsp-rename/cwd/rename.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsp-rename/cwd/rename.zig * Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn renamed_helper(x: u32) u32 {
diff --git a/test/snapshots/lsp.golden b/test/snapshots/lsp.golden
index 759e6cad..25770501 100644
--- a/test/snapshots/lsp.golden
+++ b/test/snapshots/lsp.golden
@@ -1,6 +1,6 @@
== snap opened grid=120x40 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsp/cwd/a.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsp/cwd/a.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper(x: u32) u32 {
@@ -40,8 +40,8 @@
|
|
== snap cursor grid=120x40 cursor=17,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsp/cwd/a.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsp/cwd/a.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper(x: u32) u32 {
@@ -81,8 +81,8 @@
|
|
== snap definition grid=120x40 cursor=15,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsp/cwd/a.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsp/cwd/a.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper(x: u32) u32 {
@@ -122,8 +122,8 @@
|
|
== snap hover grid=120x40 cursor=15,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsp/cwd/a.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsp/cwd/a.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper(x: u32) u32 {
@@ -159,12 +159,12 @@
|
|
|
-| /tmp/pardes-snap/lsp/cwd/+Hover New Del
+| /tmp/pardes-snap/lsp/cwd/+Hover New Newtty Del
| 1 fn helper(x: u32) u32
| 2 (fn (u32) u32)
== snap symbols grid=120x40 cursor=15,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsp/cwd/a.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsp/cwd/a.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper(x: u32) u32 {
@@ -196,16 +196,16 @@
|
|
|
-| /tmp/pardes-snap/lsp/cwd/+Search New Del
+| /tmp/pardes-snap/lsp/cwd/+Search New Newtty Del
| 1 a.zig:1:7-9 std
| 2 a.zig:3:4-9 helper fn helper(x: u32) u32
| 3 a.zig:7:8-11 main fn main() void
-| /tmp/pardes-snap/lsp/cwd/+Hover New Del
+| /tmp/pardes-snap/lsp/cwd/+Hover New Newtty Del
| 1 fn helper(x: u32) u32
| 2 (fn (u32) u32)
== snap step grid=120x40 cursor=15,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsp/cwd/a.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsp/cwd/a.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper(x: u32) u32 {
@@ -237,16 +237,16 @@
|
|
|
-| /tmp/pardes-snap/lsp/cwd/+Search New Del
+| /tmp/pardes-snap/lsp/cwd/+Search New Newtty Del
| 1 a.zig:1:7-9 std
| 2 a.zig:3:4-9 helper fn helper(x: u32) u32
| 3 a.zig:7:8-11 main fn main() void
-| /tmp/pardes-snap/lsp/cwd/+Hover New Del
+| /tmp/pardes-snap/lsp/cwd/+Hover New Newtty Del
| 1 fn helper(x: u32) u32
| 2 (fn (u32) u32)
== snap nothing grid=120x40 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsp/cwd/a.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsp/cwd/a.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper(x: u32) u32 {
@@ -278,10 +278,10 @@
|
|
|
-| /tmp/pardes-snap/lsp/cwd/+Search New Del
+| /tmp/pardes-snap/lsp/cwd/+Search New Newtty Del
| 1 a.zig:1:7-9 std
| 2 a.zig:3:4-9 helper fn helper(x: u32) u32
| 3 a.zig:7:8-11 main fn main() void
-| /tmp/pardes-snap/lsp/cwd/+Hover New Del
+| /tmp/pardes-snap/lsp/cwd/+Hover New Newtty Del
| 1 fn helper(x: u32) u32
| 2 (fn (u32) u32)
diff --git a/test/snapshots/lspcomplete.golden b/test/snapshots/lspcomplete.golden
index d64449e1..93fdaf0f 100644
--- a/test/snapshots/lspcomplete.golden
+++ b/test/snapshots/lspcomplete.golden
@@ -1,6 +1,6 @@
== snap opened grid=120x40 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lspcomplete/cwd/a.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lspcomplete/cwd/a.zig Save New Newtty Del
| 1 const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
@@ -40,8 +40,8 @@
|
|
== snap indent grid=120x40 cursor=11,11
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Newtty Del
| 1 const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
@@ -81,8 +81,8 @@
|
|
== snap commentindent grid=120x40 cursor=19,13
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Newtty Del
| 1 const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
@@ -122,8 +122,8 @@
|
|
== snap athedot grid=120x40 cursor=16,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Newtty Del
| 1 const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
@@ -163,8 +163,8 @@
|
|
== snap completion grid=120x40 cursor=16,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Newtty Del
| 1 const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
@@ -200,12 +200,12 @@
|
|
|
-| /tmp/pardes-snap/lspcomplete/cwd/+Search New Del
+| /tmp/pardes-snap/lspcomplete/cwd/+Search New Newtty Del
| 1 a.zig:2:5-13 verdigris verdigris,
| 2 a.zig:3:5-12 cinnabar cinnabar,
== snap refill grid=120x40 cursor=16,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Newtty Del
| 1 const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
@@ -241,12 +241,12 @@
|
|
|
-| /tmp/pardes-snap/lspcomplete/cwd/+Search New Del
+| /tmp/pardes-snap/lspcomplete/cwd/+Search New Newtty Del
| 1 a.zig:2:5-13 verdigris verdigris,
| 2 a.zig:3:5-12 cinnabar cinnabar,
== snap step grid=120x40 cursor=19,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lspcomplete/cwd/a.zig * Save New Newtty Del
| 1 const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
@@ -282,12 +282,12 @@
|
|
|
-| /tmp/pardes-snap/lspcomplete/cwd/+Search New Del
+| /tmp/pardes-snap/lspcomplete/cwd/+Search New Newtty Del
| 1 a.zig:2:5-13 verdigris verdigris,
| 2 a.zig:3:5-12 cinnabar cinnabar,
== snap txtindent grid=120x40 cursor=15,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lspcomplete/cwd/notes.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lspcomplete/cwd/notes.txt * Save New Newtty Del
| 1 abc. def ghi
| 2
|
@@ -327,8 +327,8 @@
|
|
== snap nosemi grid=100x18 cursor=29,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lspcomplete/cwd/c.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lspcomplete/cwd/c.zig * Save New Newtty Del
| 1 const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
@@ -342,12 +342,12 @@
|
|
|
-| /tmp/pardes-snap/lspcomplete/cwd/+Search New Del
+| /tmp/pardes-snap/lspcomplete/cwd/+Search New Newtty Del
| 1 c.zig:2:5-13 verdigris verdigris,
| 2 c.zig:3:5-12 cinnabar cinnabar,
== snap nobrace grid=100x18 cursor=16,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lspcomplete/cwd/d.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lspcomplete/cwd/d.zig * Save New Newtty Del
| 1 const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
@@ -361,6 +361,6 @@
|
|
|
-| /tmp/pardes-snap/lspcomplete/cwd/+Search New Del
+| /tmp/pardes-snap/lspcomplete/cwd/+Search New Newtty Del
| 1 d.zig:2:5-13 verdigris verdigris,
| 2 d.zig:3:5-12 cinnabar cinnabar,
diff --git a/test/snapshots/lspcompletemoved.golden b/test/snapshots/lspcompletemoved.golden
index 53489f56..9314936d 100644
--- a/test/snapshots/lspcompletemoved.golden
+++ b/test/snapshots/lspcompletemoved.golden
@@ -1,6 +1,6 @@
== snap typedthrough grid=120x20 cursor=16,13
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lspcompletemoved/cwd/a.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lspcompletemoved/cwd/a.zig * Save New Newtty Del
| 1 const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
diff --git a/test/snapshots/lspdebug.golden b/test/snapshots/lspdebug.golden
index ce90c19d..138b57cb 100644
--- a/test/snapshots/lspdebug.golden
+++ b/test/snapshots/lspdebug.golden
@@ -1,6 +1,6 @@
== snap opened grid=120x44 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lspdebug/cwd/z.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lspdebug/cwd/z.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper() u32 {
@@ -44,8 +44,8 @@
|
|
== snap ctrlclick grid=120x44 cursor=15,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lspdebug/cwd/z.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lspdebug/cwd/z.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper() u32 {
@@ -89,8 +89,8 @@
|
|
== snap plainclick grid=120x44 cursor=21,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lspdebug/cwd/z.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lspdebug/cwd/z.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper() u32 {
@@ -134,8 +134,8 @@
|
|
== snap why grid=120x44 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lspdebug/cwd/z.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lspdebug/cwd/z.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper() u32 {
@@ -168,7 +168,7 @@
|
|
|
-| /tmp/pardes-snap/lspdebug/cwd/+Lsp New Del
+| /tmp/pardes-snap/lspdebug/cwd/+Lsp New Newtty Del
| 1 lsp explain — the definition query at byte 29 of z.zig
| 2
| 3 zig lib dir: /usr/lib/zig (open) — `std` imports resolve
@@ -179,8 +179,8 @@
| 8
| 9 0 row(s)
== snap info grid=120x44 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lspdebug/cwd/z.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lspdebug/cwd/z.zig Save New Newtty Del
| 1 const std = @import("std");
| 2
| 3 fn helper() u32 {
@@ -197,7 +197,7 @@
|
|
|
-| /tmp/pardes-snap/lspdebug/cwd/+Lsp New Del
+| /tmp/pardes-snap/lspdebug/cwd/+Lsp New Newtty Del
| 1 backend: zls-inproc
| 2 zls: 0.16.1-dev+3e0d0820 (compiled in — no server process, no JSON-RPC)
| 3 zig lib dir: /usr/lib/zig [OK]
@@ -213,7 +213,7 @@
| 10 mvzr /home/goblin/00-projects/0x4200.cafe/02-pardes-code/zig-pkg/mvzr-0.3.9-ZSOky6t2AQCA7efmm5EYbPb5↩
| sOdbXa4EFsUgYbQ6hZv9/src/mvzr.zig
| 11 mupdf /home/goblin/00-projects/0x4200.cafe/02-pardes-code/src/pdf.zig
-| /tmp/pardes-snap/lspdebug/cwd/+Lsp New Del
+| /tmp/pardes-snap/lspdebug/cwd/+Lsp New Newtty Del
| 1 lsp explain — the definition query at byte 29 of z.zig
| 2
| 3 zig lib dir: /usr/lib/zig (open) — `std` imports resolve
diff --git a/test/snapshots/lsprelpath.golden b/test/snapshots/lsprelpath.golden
index d263a9bd..f45969fa 100644
--- a/test/snapshots/lsprelpath.golden
+++ b/test/snapshots/lsprelpath.golden
@@ -1,6 +1,6 @@
== snap absrow grid=100x34 cursor=16,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lsprelpath/cwd/sub/parent.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lsprelpath/cwd/sub/parent.zig * Save New Newtty Del
| 1 const shade = @import("../shade.zig");
| 2
| 3 pub fn pick(s: shade.Shade) u8 {
@@ -30,12 +30,12 @@
|
|
|
-| /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Del
+| /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Newtty Del
| 1 /tmp/pardes-snap/lsprelpath/cwd/shade.zig:2:5-13 verdigris verdigris,
| 2 /tmp/pardes-snap/lsprelpath/cwd/shade.zig:3:5-12 cinnabar cinnabar,
== snap abslook grid=100x34 cursor=19,18
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsprelpath/cwd/sub/parent.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsprelpath/cwd/sub/parent.zig * Save New Newtty Del
| 1 const shade = @import("../shade.zig");
| 2
| 3 pub fn pick(s: shade.Shade) u8 {
@@ -50,7 +50,7 @@
|
|
|
-| /tmp/pardes-snap/lsprelpath/cwd/shade.zig Save New Del
+| /tmp/pardes-snap/lsprelpath/cwd/shade.zig Save New Newtty Del
| 1 pub const Shade = enum {
| 2 verdigris,
| 3 cinnabar,
@@ -65,11 +65,11 @@
|
|
|
-| /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Del
+| /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Newtty Del
| 1 /tmp/pardes-snap/lsprelpath/cwd/shade.zig:2:5-13 verdigris verdigris,
| 2 /tmp/pardes-snap/lsprelpath/cwd/shade.zig:3:5-12 cinnabar cinnabar,
== style abslook
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
|1: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-27 #cf87e8,#080808,b 28-28 #bdbdbd,#080808, 29-42 #e3c78a,#080808, 43-44 #bdbdbd,#080808, 45-99 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808,
@@ -104,8 +104,8 @@
|32: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-76 #bdbdbd,#080808, 77-99 d,#080808,
|33: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-74 #bdbdbd,#080808, 75-99 d,#080808,
== snap subrow grid=100x34 cursor=16,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/lsprelpath/cwd/sub/subdir.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/lsprelpath/cwd/sub/subdir.zig * Save New Newtty Del
| 1 const tint = @import("inner/tint.zig");
| 2
| 3 pub fn hue(t: tint.Tint) u8 {
@@ -135,12 +135,12 @@
|
|
|
-| /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Del
+| /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Newtty Del
| 1 inner/tint.zig:2:5-9 ochre ochre,
| 2 inner/tint.zig:3:5-10 indigo indigo,
== snap sublook grid=100x34 cursor=15,18
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsprelpath/cwd/sub/subdir.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsprelpath/cwd/sub/subdir.zig * Save New Newtty Del
| 1 const tint = @import("inner/tint.zig");
| 2
| 3 pub fn hue(t: tint.Tint) u8 {
@@ -155,7 +155,7 @@
|
|
|
-| /tmp/pardes-snap/lsprelpath/cwd/sub/inner/tint.zig Save New Del
+| /tmp/pardes-snap/lsprelpath/cwd/sub/inner/tint.zig Save New Newtty Del
| 1 pub const Tint = enum {
| 2 ochre,
| 3 indigo,
@@ -170,11 +170,11 @@
|
|
|
-| /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Del
+| /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Newtty Del
| 1 inner/tint.zig:2:5-9 ochre ochre,
| 2 inner/tint.zig:3:5-10 indigo indigo,
== style sublook
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
|1: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-26 #cf87e8,#080808,b 27-27 #bdbdbd,#080808, 28-43 #e3c78a,#080808, 44-45 #bdbdbd,#080808, 46-99 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808,
@@ -209,8 +209,8 @@
|32: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-40 #bdbdbd,#080808, 41-99 d,#080808,
|33: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-43 #bdbdbd,#080808, 44-99 d,#080808,
== snap clicked grid=100x34 cursor=16,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/lsprelpath/cwd/sub/subdir.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/lsprelpath/cwd/sub/subdir.zig * Save New Newtty Del
| 1 const tint = @import("inner/tint.zig");
| 2
| 3 pub fn hue(t: tint.Tint) u8 {
@@ -225,7 +225,7 @@
|
|
|
-| /tmp/pardes-snap/lsprelpath/cwd/sub/inner/tint.zig Save New Del
+| /tmp/pardes-snap/lsprelpath/cwd/sub/inner/tint.zig Save New Newtty Del
| 1 pub const Tint = enum {
| 2 ochre,
| 3 indigo,
@@ -240,6 +240,6 @@
|
|
|
-| /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Del
+| /tmp/pardes-snap/lsprelpath/cwd/sub/+Search New Newtty Del
| 1 inner/tint.zig:2:5-9 ochre ochre,
| 2 inner/tint.zig:3:5-10 indigo indigo,
diff --git a/test/snapshots/modal.golden b/test/snapshots/modal.golden
index 1b8a7fb1..20e2cfe0 100644
--- a/test/snapshots/modal.golden
+++ b/test/snapshots/modal.golden
@@ -1,6 +1,6 @@
== snap top grid=100x30 cursor=2,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/modal/cwd New Del Filter /tmp/pardes-snap/modal/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/modal/cwd New Del Filter
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls
| words.txt
|
@@ -30,8 +30,8 @@
|
|
== snap moved grid=100x30 cursor=8,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/modal/cwd New Del Filter /tmp/pardes-snap/modal/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/modal/cwd New Del Filter
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls
| words.txt
|
@@ -61,8 +61,8 @@
|
|
== snap xsel grid=100x30 cursor=48,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/modal/cwd New Del Filter /tmp/pardes-snap/modal/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/modal/cwd New Del Filter
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls
| words.txt
|
@@ -92,39 +92,39 @@
|
|
== style xsel
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-42 #949494,#121212, 43-49 d,#121212, 50-51 #ffffff,#262626, 52-92 #949494,#121212, 93-99 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-48 #080808,#80a0ff, 49-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|16: 0-1 #ffffff,#262626, 2-42 #949494,#121212, 43-49 d,#121212, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-49 #949494,#121212, 50-51 #ffffff,#262626, 52-99 #949494,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-53 #bdbdbd,#080808, 54-99 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-60 #bdbdbd,#080808, 61-99 d,#080808,
+|4: 0-0 d,#444444, 1-1 d,#080808, 2-48 #080808,#80a0ff, 49-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-12 #bdbdbd,#080808, 13-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|6: 0-0 d,#444444, 1-1 d,#080808, 2-14 #bdbdbd,#080808, 15-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|7: 0-0 d,#444444, 1-1 d,#080808, 2-14 #bdbdbd,#080808, 15-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|8: 0-0 d,#444444, 1-1 d,#080808, 2-17 #bdbdbd,#080808, 18-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|9: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|10: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|11: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|12: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|13: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|14: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|15: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-49 #949494,#121212, 50-50 d,#444444, 51-99 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|19: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|20: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|21: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|22: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|23: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|24: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|25: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|26: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|27: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|28: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|29: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
== snap xsel2 grid=100x30 cursor=13,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/modal/cwd New Del Filter /tmp/pardes-snap/modal/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -139,7 +139,7 @@
|
|
|
-| /tmp/pardes-snap/modal/cwd New Del Filter
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls
| words.txt
|
@@ -154,8 +154,8 @@
|
|
== snap yanked grid=100x30 cursor=13,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/modal/cwd New Del Filter /tmp/pardes-snap/modal/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -170,7 +170,7 @@
|
|
|
-| /tmp/pardes-snap/modal/cwd New Del Filter
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls
| words.txt
|
@@ -185,8 +185,8 @@
|
|
== snap vsel grid=100x30 cursor=14,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/modal/cwd New Del Filter /tmp/pardes-snap/modal/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -201,7 +201,7 @@
|
|
|
-| /tmp/pardes-snap/modal/cwd New Del Filter
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls
| words.txt
|
@@ -216,39 +216,39 @@
|
|
== style vsel
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-42 #949494,#121212, 43-49 d,#121212, 50-51 #ffffff,#262626, 52-92 #949494,#121212, 93-99 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-49 #080808,#80a0ff, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-49 #080808,#80a0ff, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-14 #080808,#80a0ff, 15-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|16: 0-1 #ffffff,#262626, 2-42 #949494,#121212, 43-49 d,#121212, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-49 #949494,#121212, 50-51 #ffffff,#262626, 52-99 #949494,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-53 #bdbdbd,#080808, 54-99 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-60 #bdbdbd,#080808, 61-99 d,#080808,
+|4: 0-0 d,#444444, 1-1 d,#080808, 2-49 #080808,#80a0ff, 50-50 d,#444444, 51-99 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-49 #080808,#80a0ff, 50-50 d,#444444, 51-99 d,#080808,
+|6: 0-0 d,#444444, 1-1 d,#080808, 2-14 #080808,#80a0ff, 15-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|7: 0-0 d,#444444, 1-1 d,#080808, 2-14 #bdbdbd,#080808, 15-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|8: 0-0 d,#444444, 1-1 d,#080808, 2-17 #bdbdbd,#080808, 18-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|9: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|10: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|11: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|12: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|13: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|14: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|15: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-49 #949494,#121212, 50-50 d,#444444, 51-99 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|19: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|20: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|21: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|22: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|23: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|24: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|25: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|26: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|27: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|28: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|29: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
== snap typed grid=100x30 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/modal/cwd New Del Filter /tmp/pardes-snap/modal/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls ls
| words.txt words.txt
| TYPEDprintf 'one two three\nfour five six\nseven
@@ -263,7 +263,7 @@
|
|
|
-| /tmp/pardes-snap/modal/cwd New Del Filter
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls
| words.txt
|
@@ -278,8 +278,8 @@
|
|
== snap undone grid=100x30 cursor=14,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/modal/cwd New Del Filter /tmp/pardes-snap/modal/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -294,7 +294,7 @@
|
|
|
-| /tmp/pardes-snap/modal/cwd New Del Filter
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls
| words.txt
|
@@ -309,8 +309,8 @@
|
|
== snap redone grid=100x30 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/modal/cwd New Del Filter /tmp/pardes-snap/modal/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls ls
| words.txt words.txt
| TYPEDprintf 'one two three\nfour five six\nseven
@@ -325,7 +325,7 @@
|
|
|
-| /tmp/pardes-snap/modal/cwd New Del Filter
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls
| words.txt
|
@@ -340,8 +340,8 @@
|
|
== snap bottom grid=100x30 cursor=2,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/modal/cwd New Del Filter /tmp/pardes-snap/modal/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls ls
| words.txt words.txt
| TYPEDprintf 'one two three\nfour five six\nseven
@@ -356,7 +356,7 @@
|
|
|
-| /tmp/pardes-snap/modal/cwd New Del Filter
+| /tmp/pardes-snap/modal/cwd New Newtty Del Filter
| ls
| words.txt
|
diff --git a/test/snapshots/msg.golden b/test/snapshots/msg.golden
index 30b20629..d456f75d 100644
--- a/test/snapshots/msg.golden
+++ b/test/snapshots/msg.golden
@@ -1,6 +1,6 @@
== snap opened grid=70x14 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -14,8 +14,8 @@
|
|
== snap saved grid=70x14 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -29,8 +29,8 @@
|
| --:--:-- saved /tmp/pardes-snap/msg/cwd/a.txt
== snap repainted grid=70x16 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -46,8 +46,8 @@
|
| --:--:-- saved /tmp/pardes-snap/msg/cwd/a.txt
== snap keycleared grid=70x16 cursor=7,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -63,8 +63,8 @@
|
|
== snap saved-again grid=70x16 cursor=7,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -80,8 +80,8 @@
|
| --:--:-- saved /tmp/pardes-snap/msg/cwd/a.txt
== snap mousecleared grid=70x16 cursor=7,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -97,8 +97,8 @@
|
|
== snap reloaded grid=70x16 cursor=7,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt Save New Newtty Del
| 1 EXTERNAL
| 2
|
@@ -114,8 +114,8 @@
|
| --:--:-- reloaded /tmp/pardes-snap/msg/cwd/a.txt
== snap prompt grid=70x16 cursor=7,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt Save New Newtty Del
| 1 EXTERNAL
| 2
|
@@ -131,8 +131,8 @@
|
| /EXT
== snap prompt-wins grid=70x16 cursor=7,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt Save New Newtty Del
| 1 AGAIN
| 2
|
@@ -148,8 +148,8 @@
|
| /EXT
== snap esc grid=70x16 cursor=7,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt Save New Newtty Del
| 1 AGAIN
| 2
|
@@ -165,8 +165,8 @@
|
|
== snap msgbuiltin grid=70x16 cursor=29,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/msg/cwd/a.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/msg/cwd/a.txt * Save New Newtty Del
| 1 AGAIN
| 2
| 3 Msg hand-written report
diff --git a/test/snapshots/multicursor.golden b/test/snapshots/multicursor.golden
index 200f2354..7ca59191 100644
--- a/test/snapshots/multicursor.golden
+++ b/test/snapshots/multicursor.golden
@@ -1,23 +1,23 @@
== snap three-cursors grid=150x30 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/multicursor/cwd/f.t /tmp/pardes-snap/multicursor/cwd Ne /tmp/pardes-snap/multicursor/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 line 2 f.txt f.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/multicursor/cwd/f.txt Save New Newtty Del /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 line 2 f.txt
| 3 line 3
| 4 line 4
| 5 line 5
-| 6 line 6 f.txt
-| 7 line 7
-| 8 line 8
-| 9 line 9
-| 10 line 10
-| 11 line 11
-| 12 line 12
-| 13
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| ls
+| f.txt
|
-| /tmp/pardes-snap/multicursor/cwd Ne
-| ls
-| f.txt
+|
+|
+| f.txt
+|
+| /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| ls
+| f.txt
|
|
|
@@ -30,56 +30,56 @@
|
|
== style three-cursors
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #80a0ff,#080808, 8-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #80a0ff,#080808, 8-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-46 #bdbdbd,#080808, 47-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-59 #949494,#121212, 60-74 d,#121212, 75-76 #ffffff,#262626, 77-130 #949494,#121212, 131-149 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #80a0ff,#080808, 8-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #80a0ff,#080808, 8-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-81 #bdbdbd,#080808, 82-149 d,#080808,
+|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-59 #949494,#121212, 60-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-59 #949494,#121212, 60-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
== snap edited-at-three grid=150x30 cursor=9,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/multicursor/cwd/f.t /tmp/pardes-snap/multicursor/cwd Ne /tmp/pardes-snap/multicursor/cwd New Del Filter
-| 1 >>line 1 ls ls
-| 2 >>line 2 f.txt f.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/multicursor/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| 1 >>line 1 ls
+| 2 >>line 2 f.txt
| 3 >>line 3
| 4 line 4
| 5 line 5
-| 6 line 6 f.txt
-| 7 line 7
-| 8 line 8
-| 9 line 9
-| 10 line 10
-| 11 line 11
-| 12 line 12
-| 13
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| ls
+| f.txt
+|
+|
+|
+| f.txt
|
-| /tmp/pardes-snap/multicursor/cwd Ne
-| ls
-| f.txt
+| /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| ls
+| f.txt
|
|
|
@@ -92,25 +92,25 @@
|
|
== snap three-selections grid=150x30 cursor=8,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/multicursor/cwd/f.t /tmp/pardes-snap/multicursor/cwd Ne /tmp/pardes-snap/multicursor/cwd New Del Filter
-| 1 >>line 1 ls ls
-| 2 >>line 2 f.txt f.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/multicursor/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| 1 >>line 1 ls
+| 2 >>line 2 f.txt
| 3 >>line 3
| 4 line 4
| 5 line 5
-| 6 line 6 f.txt
-| 7 line 7
-| 8 line 8
-| 9 line 9
-| 10 line 10
-| 11 line 11
-| 12 line 12
-| 13
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| ls
+| f.txt
|
-| /tmp/pardes-snap/multicursor/cwd Ne
-| ls
-| f.txt
+|
+|
+| f.txt
+|
+| /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| ls
+| f.txt
|
|
|
@@ -123,56 +123,56 @@
|
|
== style three-selections
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #080808,#445483, 8-8 #80a0ff,#080808, 9-14 #bdbdbd,#080808, 15-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #080808,#445483, 8-8 #80a0ff,#080808, 9-14 #bdbdbd,#080808, 15-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-8 #080808,#80a0ff, 9-14 #bdbdbd,#080808, 15-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-46 #bdbdbd,#080808, 47-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-61 #949494,#121212, 62-74 d,#121212, 75-76 #ffffff,#262626, 77-130 #949494,#121212, 131-149 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #080808,#445483, 8-8 #80a0ff,#080808, 9-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #080808,#445483, 8-8 #80a0ff,#080808, 9-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-81 #bdbdbd,#080808, 82-149 d,#080808,
+|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #949494,#121212, 7-8 #080808,#80a0ff, 9-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-61 #949494,#121212, 62-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-61 #949494,#121212, 62-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
== snap keep-primary grid=150x30 cursor=8,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/multicursor/cwd/f.t /tmp/pardes-snap/multicursor/cwd Ne /tmp/pardes-snap/multicursor/cwd New Del Filter
-| 1 >>line 1 ls ls
-| 2 >>line 2 f.txt f.txt
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/multicursor/cwd/f.txt * Save New Newtty Del /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| 1 >>line 1 ls
+| 2 >>line 2 f.txt
| 3 >>line 3
| 4 line 4
| 5 line 5
-| 6 line 6 f.txt
-| 7 line 7
-| 8 line 8
-| 9 line 9
-| 10 line 10
-| 11 line 11
-| 12 line 12
-| 13
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| ls
+| f.txt
+|
+|
+|
+| f.txt
|
-| /tmp/pardes-snap/multicursor/cwd Ne
-| ls
-| f.txt
+| /tmp/pardes-snap/multicursor/cwd New Newtty Del Filter
+| ls
+| f.txt
|
|
|
@@ -185,33 +185,33 @@
|
|
== style keep-primary
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-8 #080808,#80a0ff, 9-14 #bdbdbd,#080808, 15-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-46 #bdbdbd,#080808, 47-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #bdbdbd,#080808, 14-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-61 #949494,#121212, 62-74 d,#121212, 75-76 #ffffff,#262626, 77-130 #949494,#121212, 131-149 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-81 #bdbdbd,#080808, 82-149 d,#080808,
+|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #949494,#121212, 7-8 #080808,#80a0ff, 9-14 #bdbdbd,#080808, 15-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-61 #949494,#121212, 62-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-61 #949494,#121212, 62-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
diff --git a/test/snapshots/nested-optout.golden b/test/snapshots/nested-optout.golden
index 4efda9f5..4d731e82 100644
--- a/test/snapshots/nested-optout.golden
+++ b/test/snapshots/nested-optout.golden
@@ -1,8 +1,8 @@
== snap optout-file grid=100x30 cursor=9,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/nested-optout/cwd New Del Filter
-| New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/nested-optout/cwd/nested.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/nested-optout/cwd New Newtty Del Filter
+| New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/nested-optout/cwd/nested.txt Save New Newtty Del
| 1 optout-marker
| 2 second-optout-line
| 3
@@ -30,10 +30,10 @@
|
|
== snap inner-shell grid=100x30 cursor=6,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/nested-optout/cwd New Del Filter
-| New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| $ /tmp/pardes-snap/nested-optout/cwd/innerdir New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/nested-optout/cwd New Newtty Del Filter
+| New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| $ /tmp/pardes-snap/nested-optout/cwd/innerdir New Newtty Del Filter
| $
|
|
@@ -61,12 +61,12 @@
|
|
== snap inner-launch grid=100x30 cursor=11,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/nested-optout/cwd New Del Filter
-| New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| $ /tmp/pardes-snap/nested-optout/cwd/innerdir New Del Filter
-| New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/nested-optout/cwd/innerdir/deeper.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/nested-optout/cwd New Newtty Del Filter
+| New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| $ /tmp/pardes-snap/nested-optout/cwd/innerdir New Newtty Del Filter
+| New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/nested-optout/cwd/innerdir/deeper.txt Save New Newtty Del
| 1 deepest-marker
| 2
|
diff --git a/test/snapshots/nested.golden b/test/snapshots/nested.golden
index f4df637a..3c0be5f4 100644
--- a/test/snapshots/nested.golden
+++ b/test/snapshots/nested.golden
@@ -1,8 +1,8 @@
== snap file-arg grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/nested/cwd/nested.txt Save New $ /tmp/pardes-snap/nested/cwd New Del Filter
-| 1 hello-from-nested $ $(readlink /proc/$PPID/exe) nested.txt
-| 2 second-nested-line $
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/nested/cwd/nested.txt Save New Newtty Del
+| 1 hello-from-nested
+| 2 second-nested-line
| 3
|
|
@@ -14,9 +14,9 @@
|
|
|
-|
-|
-|
+|$ /tmp/pardes-snap/nested/cwd New Newtty Del Filter
+| $ $(readlink /proc/$PPID/exe) nested.txt
+| $
|
|
|
@@ -30,8 +30,8 @@
|
|
== snap no-arg grid=100x30 cursor=4,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/nested/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/nested/cwd New Newtty Del Filter
| $ $(readlink /proc/$PPID/exe)
| pardes: this shell is already inside pardes, and a pardes inside a pardes
| is spicy. Name a file or a directory and the outer session opens it, or
@@ -61,11 +61,11 @@
|
|
== snap dir-arg grid=100x30 cursor=4,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/nested/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/nested/cwd New Newtty Del Filter
| $ $(readlink /proc/$PPID/exe) nestdir
| $
-| /tmp/pardes-snap/nested/cwd/nestdir New Del Filter
+| /tmp/pardes-snap/nested/cwd/nestdir New Newtty Del Filter
| ls
| inside-nested.txt
|
diff --git a/test/snapshots/pipe.golden b/test/snapshots/pipe.golden
index 6ca8c9fe..ede81b5f 100644
--- a/test/snapshots/pipe.golden
+++ b/test/snapshots/pipe.golden
@@ -1,6 +1,6 @@
== snap prompt grid=180x12 cursor=14,11
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/pipe/cwd/pipe.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/pipe/cwd/pipe.txt Save New Newtty Del
| 1 alpha beta
| 2 gamma delta
|
@@ -12,8 +12,8 @@
|
| |tr a-z A-Z
== snap filtered grid=180x12 cursor=17,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/pipe/cwd/pipe.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/pipe/cwd/pipe.txt * Save New Newtty Del
| 1 ALPHA BETA
| 2 gamma delta
|
@@ -25,8 +25,8 @@
|
|
== snap undone grid=180x12 cursor=17,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/pipe/cwd/pipe.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/pipe/cwd/pipe.txt * Save New Newtty Del
| 1 alpha beta
| 2 gamma delta
|
diff --git a/test/snapshots/psearch.golden b/test/snapshots/psearch.golden
index 2c675049..4757df7e 100644
--- a/test/snapshots/psearch.golden
+++ b/test/snapshots/psearch.golden
@@ -1,6 +1,6 @@
== snap output grid=140x30 cursor=4,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/psearch/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/psearch/cwd New Newtty Del Filter
| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n'
| x MARK a
| zz
@@ -30,8 +30,8 @@
|
|
== snap typing grid=140x30 cursor=8,29
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/psearch/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/psearch/cwd New Newtty Del Filter
| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n'
| x MARK a
| zz
@@ -61,8 +61,8 @@
|
| /MARK
== snap results grid=140x30 cursor=7,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/psearch/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/psearch/cwd New Newtty Del Filter
| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n'
| x MARK a
| zz
@@ -87,44 +87,44 @@
|
|
|
-| /tmp/pardes-snap/psearch/cwd/+Search New Del
+| /tmp/pardes-snap/psearch/cwd/+Search New Newtty Del
| 1 @p0:2:3-6 x MARK a
| 2 @p0:4:3-6 x MARK b
| 3 @p0:6:3-6 x MARK c
== style results
-|0: 0-56 #949494,#121212, 57-139 d,#121212,
+|0: 0-74 #949494,#121212, 75-139 d,#121212,
|1: 0-1 #ffffff,#626262, 2-119 #949494,#121212, 120-139 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-7 #080808,#80a0ff, 8-139 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-139 #bdbdbd,#080808,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-54 #bdbdbd,#080808, 55-139 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-7 #080808,#80a0ff, 8-9 #bdbdbd,#080808, 10-139 d,#080808,
+|4: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-139 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-9 #bdbdbd,#080808, 10-139 d,#080808,
+|6: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-139 d,#080808,
+|7: 0-0 d,#444444, 1-1 d,#080808, 2-9 #bdbdbd,#080808, 10-139 d,#080808,
+|8: 0-0 d,#444444, 1-139 d,#080808,
+|9: 0-0 d,#444444, 1-139 d,#080808,
+|10: 0-0 d,#444444, 1-139 d,#080808,
+|11: 0-0 d,#444444, 1-139 d,#080808,
+|12: 0-0 d,#444444, 1-139 d,#080808,
+|13: 0-0 d,#444444, 1-139 d,#080808,
+|14: 0-0 d,#444444, 1-139 d,#080808,
+|15: 0-0 d,#444444, 1-139 d,#080808,
+|16: 0-0 d,#444444, 1-139 d,#080808,
+|17: 0-0 d,#444444, 1-139 d,#080808,
+|18: 0-0 d,#444444, 1-139 d,#080808,
+|19: 0-0 d,#444444, 1-139 d,#080808,
+|20: 0-0 d,#444444, 1-139 d,#080808,
+|21: 0-0 d,#444444, 1-139 d,#080808,
+|22: 0-0 d,#444444, 1-139 d,#080808,
+|23: 0-0 d,#444444, 1-139 d,#080808,
+|24: 0-0 d,#444444, 1-139 d,#080808,
+|25: 0-0 d,#444444, 1-139 d,#080808,
|26: 0-1 #ffffff,#262626, 2-119 #949494,#121212, 120-139 d,#121212,
|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-139 d,#080808,
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-139 d,#080808,
|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-139 d,#080808,
== snap second grid=140x30 cursor=7,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/psearch/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/psearch/cwd New Newtty Del Filter
| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n'
| x MARK a
| zz
@@ -149,13 +149,13 @@
|
|
|
-| /tmp/pardes-snap/psearch/cwd/+Search New Del
+| /tmp/pardes-snap/psearch/cwd/+Search New Newtty Del
| 1 @p0:2:3-6 x MARK a
| 2 @p0:4:3-6 x MARK b
| 3 @p0:6:3-6 x MARK c
== snap back grid=140x30 cursor=7,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/psearch/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/psearch/cwd New Newtty Del Filter
| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n'
| x MARK a
| zz
@@ -180,13 +180,13 @@
|
|
|
-| /tmp/pardes-snap/psearch/cwd/+Search New Del
+| /tmp/pardes-snap/psearch/cwd/+Search New Newtty Del
| 1 @p0:2:3-6 x MARK a
| 2 @p0:4:3-6 x MARK b
| 3 @p0:6:3-6 x MARK c
== snap nomatch grid=140x30 cursor=7,28
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/psearch/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/psearch/cwd New Newtty Del Filter
| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n'
| x MARK a
| zz
@@ -209,15 +209,15 @@
|
|
|
-| /tmp/pardes-snap/psearch/cwd/+Search New Del
+| /tmp/pardes-snap/psearch/cwd/+Search New Newtty Del
| 1
-| /tmp/pardes-snap/psearch/cwd/+Search New Del
+| /tmp/pardes-snap/psearch/cwd/+Search New Newtty Del
| 1 @p0:2:3-6 x MARK a
| 2 @p0:4:3-6 x MARK b
| 3 @p0:6:3-6 x MARK c
== snap ttyinert grid=140x30 cursor=4,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/psearch/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/psearch/cwd New Newtty Del Filter
| $ printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n'
| x MARK a
| zz
@@ -240,15 +240,15 @@
|
|
|
-| /tmp/pardes-snap/psearch/cwd/+Search New Del
+| /tmp/pardes-snap/psearch/cwd/+Search New Newtty Del
| 1
-| /tmp/pardes-snap/psearch/cwd/+Search New Del
+| /tmp/pardes-snap/psearch/cwd/+Search New Newtty Del
| 1 @p0:2:3-6 x MARK a
| 2 @p0:4:3-6 x MARK b
| 3 @p0:6:3-6 x MARK c
== snap rightsearch grid=140x30 cursor=7,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/psearch/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/psearch/cwd New Newtty Del Filter
| printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n'
| x MARK a
| zz
@@ -271,9 +271,9 @@
|
|
|
-| /tmp/pardes-snap/psearch/cwd/+Search New Del
+| /tmp/pardes-snap/psearch/cwd/+Search New Newtty Del
| 1
-| /tmp/pardes-snap/psearch/cwd/+Search New Del
+| /tmp/pardes-snap/psearch/cwd/+Search New Newtty Del
| 1 @p0:2:3-6 x MARK a
| 2 @p0:4:3-6 x MARK b
| 3 @p0:6:3-6 x MARK c
diff --git a/test/snapshots/reflow.golden b/test/snapshots/reflow.golden
index f545ba6f..a50f81d0 100644
--- a/test/snapshots/reflow.golden
+++ b/test/snapshots/reflow.golden
@@ -1,6 +1,6 @@
== snap widened grid=200x24 cursor=4,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/reflow/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/reflow/cwd New Newtty Del Filter
| $ printf 'y%.0s' $(seq 1 3000); echo do''ne
| yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
| yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
diff --git a/test/snapshots/respawn.golden b/test/snapshots/respawn.golden
index 9cee048a..d4929cb1 100644
--- a/test/snapshots/respawn.golden
+++ b/test/snapshots/respawn.golden
@@ -1,18 +1,8 @@
-== snap respawn grid=100x30 cursor=4,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/respawn/cwd New Del Filter /tmp/pardes-snap/respawn/cwd New Del Filter
+== snap respawn grid=100x30 cursor=4,26
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/respawn/cwd New Newtty Del Filt /tmp/pardes-snap/respawn/cwd New Newtty Del Filt
| ls ls
|
-|$ /tmp/pardes-snap/respawn/cwd New Del Filter
-| $ ls
-| $ echo RESP''AWNOK
-| RESPAWNOK
-| $
-|
-|
-|
-|
-|
|
|
|
@@ -25,7 +15,17 @@
|
|
|
+| /tmp/pardes-snap/respawn/cwd New Newtty Del Filt
+| ls
|
+|$ /tmp/pardes-snap/respawn/cwd New Newtty Del Filt
+| $ ls
+| $
+|$ /tmp/pardes-snap/respawn/cwd New Newtty Del Filt
+| $ ls
+| $ echo RESP''AWNOK
+| RESPAWNOK
+| $
|
|
|
diff --git a/test/snapshots/restore.golden b/test/snapshots/restore.golden
index 5f3ae1cc..6d068580 100644
--- a/test/snapshots/restore.golden
+++ b/test/snapshots/restore.golden
@@ -1,6 +1,6 @@
== snap dumped grid=100x30 cursor=4,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill Restore /tmp/pardes-snap/restore/dump.zon
-|$ /tmp/pardes-snap/restore/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill Restore /tmp/pardes-snap
+|$ /tmp/pardes-snap/restore/cwd New Newtty Del Filter
| $ ls
| $ echo KEEP''ME
| KEEPME
@@ -30,8 +30,8 @@
|
|
== snap restored grid=100x30 cursor=4,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/restore/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/restore/cwd New Newtty Del Filter
| ls
| echo KEEP''ME
| KEEPME
diff --git a/test/snapshots/restore.snap b/test/snapshots/restore.snap
index 7dd5b4be..996dbc8b 100644
--- a/test/snapshots/restore.snap
+++ b/test/snapshots/restore.snap
@@ -11,15 +11,15 @@ text echo KEEP''ME
key enter
wait 8000 KEEPME
stable 700 10000
-press middle 33 1
-release middle 33 1
+press middle 52 1
+release middle 52 1
stable 700 10000
snap dumped
text echo GONE''SOON
key enter
wait 8000 GONESOON
stable 700 10000
-press middle 59 1
-release middle 59 1
+press middle 78 1
+release middle 78 1
stable 900 15000
snap restored
diff --git a/test/snapshots/rsearch.golden b/test/snapshots/rsearch.golden
index f76f1d19..36c38e24 100644
--- a/test/snapshots/rsearch.golden
+++ b/test/snapshots/rsearch.golden
@@ -1,12 +1,12 @@
-== snap opened grid=180x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/rsearch/cwd/code.txt Save /tmp/pardes-snap/rsearch/cwd New Del Filter /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 1 run count_x now ls ls
-| 2 open sub/dep.txt:3 here code.txt sub code.txt sub
+== snap opened grid=210x30 cursor=7,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/rsearch/cwd/code.txt Save New Newtty Del /tmp/pardes-snap/rsearch/cwd New Newtty Del Filter
+| 1 run count_x now ls
+| 2 open sub/dep.txt:3 here code.txt sub
| 3 count_x again
| 4 pick two words
|
-| code.txt
+| code.txt
|
|
|
@@ -15,9 +15,6 @@
|
|
|
-| /tmp/pardes-snap/rsearch/cwd New Del Filter
-| ls
-| code.txt sub
|
|
|
@@ -29,15 +26,20 @@
|
|
|
-== snap search grid=180x30 cursor=13,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/rsearch/cwd/code.txt Save /tmp/pardes-snap/rsearch/cwd New Del Filter /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 1 run count_x now ls ls
-| 2 open sub/dep.txt:3 here code.txt sub code.txt sub
+|
+|
+|
+== snap search grid=210x30 cursor=13,4
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/rsearch/cwd/code.txt Save New Newtty Del /tmp/pardes-snap/rsearch/cwd New Newtty Del Filter
+| 1 run count_x now ls
+| 2 open sub/dep.txt:3 here code.txt sub
| 3 count_x again
| 4 pick two words
|
-| code.txt
+| code.txt
+|
+|
|
|
|
@@ -46,9 +48,6 @@
|
|
|
-| /tmp/pardes-snap/rsearch/cwd New Del Filter
-| ls
-| code.txt sub
|
|
|
@@ -57,18 +56,22 @@
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+|
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:1:5-11 run count_x now
| 2 code.txt:3:1-7 count_x again
-== snap select grid=180x30 cursor=14,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/rsearch/cwd/code.txt Save /tmp/pardes-snap/rsearch/cwd New Del Filter /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 1 run count_x now ls ls
-| 2 open sub/dep.txt:3 here code.txt sub code.txt sub
+== snap select grid=210x30 cursor=14,5
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/rsearch/cwd/code.txt Save New Newtty Del /tmp/pardes-snap/rsearch/cwd New Newtty Del Filter
+| 1 run count_x now ls
+| 2 open sub/dep.txt:3 here code.txt sub
| 3 count_x again
| 4 pick two words
|
-| code.txt
+| code.txt
+|
+|
+|
|
|
|
@@ -77,203 +80,200 @@
|
|
|
-| /tmp/pardes-snap/rsearch/cwd New Del Filter
-| ls
-| code.txt sub
|
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:4:1-8 pick two words
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:1:5-11 run count_x now
| 2 code.txt:3:1-7 count_x again
-== snap path-open grid=180x30 cursor=7,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/rsearch/cwd/code.txt Save /tmp/pardes-snap/rsearch/cwd New Del Filter /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 1 run count_x now ls ls
-| 2 open sub/dep.txt:3 here code.txt sub code.txt sub
+== snap path-open grid=210x30 cursor=7,16
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/rsearch/cwd/code.txt Save New Newtty Del /tmp/pardes-snap/rsearch/cwd New Newtty Del Filter
+| 1 run count_x now ls
+| 2 open sub/dep.txt:3 here code.txt sub
| 3 count_x again
| 4 pick two words
|
-| code.txt
+| code.txt
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Sa
+| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Save New Newtty Del
| 1 d1
| 2 d2
-| 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 4 d4 ls
-| 5 d5 code.txt sub
+| 3 DEPTARGET
+| 4 d4
+| 5 d5
| 6 d6
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:4:1-8 pick two words
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:1:5-11 run count_x now
| 2 code.txt:3:1-7 count_x again
-== snap step1 grid=180x30 cursor=13,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/rsearch/cwd/code.txt Save /tmp/pardes-snap/rsearch/cwd New Del Filter /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 1 run count_x now ls ls
-| 2 open sub/dep.txt:3 here code.txt sub code.txt sub
+== snap step1 grid=210x30 cursor=13,4
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/rsearch/cwd/code.txt Save New Newtty Del /tmp/pardes-snap/rsearch/cwd New Newtty Del Filter
+| 1 run count_x now ls
+| 2 open sub/dep.txt:3 here code.txt sub
| 3 count_x again
| 4 pick two words
|
-| code.txt
+| code.txt
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Sa
+| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Save New Newtty Del
| 1 d1
| 2 d2
-| 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 4 d4 ls
-| 5 d5 code.txt sub
+| 3 DEPTARGET
+| 4 d4
+| 5 d5
| 6 d6
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:4:1-8 pick two words
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:1:5-11 run count_x now
| 2 code.txt:3:1-7 count_x again
-== snap step2 grid=180x30 cursor=17,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/rsearch/cwd/code.txt Save /tmp/pardes-snap/rsearch/cwd New Del Filter /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 1 run count_x now ls ls
-| 2 open sub/dep.txt:3 here code.txt sub code.txt sub
+== snap step2 grid=210x30 cursor=17,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/rsearch/cwd/code.txt Save New Newtty Del /tmp/pardes-snap/rsearch/cwd New Newtty Del Filter
+| 1 run count_x now ls
+| 2 open sub/dep.txt:3 here code.txt sub
| 3 count_x again
| 4 pick two words
|
-| code.txt
+| code.txt
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Sa
+| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Save New Newtty Del
| 1 d1
| 2 d2
-| 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 4 d4 ls
-| 5 d5 code.txt sub
+| 3 DEPTARGET
+| 4 d4
+| 5 d5
| 6 d6
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:4:1-8 pick two words
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:1:5-11 run count_x now
| 2 code.txt:3:1-7 count_x again
-== snap step3 grid=180x30 cursor=17,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/rsearch/cwd/code.txt Save /tmp/pardes-snap/rsearch/cwd New Del Filter /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 1 run count_x now ls ls
-| 2 open sub/dep.txt:3 here code.txt sub code.txt sub
+== snap step3 grid=210x30 cursor=17,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/rsearch/cwd/code.txt Save New Newtty Del /tmp/pardes-snap/rsearch/cwd New Newtty Del Filter
+| 1 run count_x now ls
+| 2 open sub/dep.txt:3 here code.txt sub
| 3 count_x again
| 4 pick two words
|
-| code.txt
+| code.txt
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Sa
+| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Save New Newtty Del
| 1 d1
| 2 d2
-| 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 4 d4 ls
-| 5 d5 code.txt sub
+| 3 DEPTARGET
+| 4 d4
+| 5 d5
| 6 d6
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:4:1-8 pick two words
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:1:5-11 run count_x now
| 2 code.txt:3:1-7 count_x again
-== snap selclick grid=180x30 cursor=14,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/rsearch/cwd/code.txt Save /tmp/pardes-snap/rsearch/cwd New Del Filter /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 1 run count_x now ls ls
-| 2 open sub/dep.txt:3 here code.txt sub code.txt sub
+== snap selclick grid=210x30 cursor=14,5
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/rsearch/cwd/code.txt Save New Newtty Del /tmp/pardes-snap/rsearch/cwd New Newtty Del Filter
+| 1 run count_x now ls
+| 2 open sub/dep.txt:3 here code.txt sub
| 3 count_x again
| 4 pick two words
|
-| code.txt
+| code.txt
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Sa
+| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Save New Newtty Del
| 1 d1
| 2 d2
-| 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 4 d4 ls
-| 5 d5 code.txt sub
+| 3 DEPTARGET
+| 4 d4
+| 5 d5
| 6 d6
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:4:1-8 pick two words
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:1:5-11 run count_x now
| 2 code.txt:3:1-7 count_x again
-== snap outside grid=180x30 cursor=20,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/rsearch/cwd/code.txt Save /tmp/pardes-snap/rsearch/cwd New Del Filter /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 1 run count_x now ls ls
-| 2 open sub/dep.txt:3 here code.txt sub code.txt sub
+== snap outside grid=210x30 cursor=20,5
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/rsearch/cwd/code.txt Save New Newtty Del /tmp/pardes-snap/rsearch/cwd New Newtty Del Filter
+| 1 run count_x now ls
+| 2 open sub/dep.txt:3 here code.txt sub
| 3 count_x again
| 4 pick two words
|
-| code.txt
+| code.txt
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:4:10-14 pick two words
-| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Sa
+| /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Save New Newtty Del
| 1 d1
| 2 d2
-| 3 DEPTARGET /tmp/pardes-snap/rsearch/cwd New Del Filter
-| 4 d4 ls
-| 5 d5 code.txt sub
+| 3 DEPTARGET
+| 4 d4
+| 5 d5
| 6 d6
|
|
|
|
|
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:4:1-8 pick two words
-| /tmp/pardes-snap/rsearch/cwd/+Search New De
+| /tmp/pardes-snap/rsearch/cwd/+Search New Newtty Del
| 1 code.txt:1:5-11 run count_x now
| 2 code.txt:3:1-7 count_x again
diff --git a/test/snapshots/rsearch.snap b/test/snapshots/rsearch.snap
index 542680c0..9c9ee8b6 100644
--- a/test/snapshots/rsearch.snap
+++ b/test/snapshots/rsearch.snap
@@ -7,7 +7,7 @@
dirmk sub
file sub/dep.txt d1\nd2\nDEPTARGET\nd4\nd5\nd6
file code.txt run count_x now\nopen sub/dep.txt:3 here\ncount_x again\npick two words
-start 30 180 -n 3
+start 30 210 -n 1
wait 8000 code.txt
stable 700 20000
# open code.txt: type the name in a shell, right-click it (ordinary look)
diff --git a/test/snapshots/scroll.golden b/test/snapshots/scroll.golden
index ba684c63..b77d4768 100644
--- a/test/snapshots/scroll.golden
+++ b/test/snapshots/scroll.golden
@@ -1,6 +1,6 @@
== snap bottom grid=100x30 cursor=4,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scroll/cwd New Del Filter /tmp/pardes-snap/scroll/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scroll/cwd New Newtty Del Filte /tmp/pardes-snap/scroll/cwd New Newtty Del Filte
| 188 ls
| 189 s.txt
| 190
@@ -15,7 +15,7 @@
| 199
| 200
|
-| /tmp/pardes-snap/scroll/cwd New Del Filter
+| /tmp/pardes-snap/scroll/cwd New Newtty Del Filte
| ls
| s.txt
|
@@ -30,8 +30,8 @@
|
|
== snap wheel3 grid=100x30 cursor=4,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scroll/cwd New Del Filter /tmp/pardes-snap/scroll/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scroll/cwd New Newtty Del Filte /tmp/pardes-snap/scroll/cwd New Newtty Del Filte
| 185 ls
| 186 s.txt
| 187
@@ -46,7 +46,7 @@
| 196
| 197
| 198
-| /tmp/pardes-snap/scroll/cwd New Del Filter
+| /tmp/pardes-snap/scroll/cwd New Newtty Del Filte
| ls
| s.txt
|
@@ -61,8 +61,8 @@
|
|
== snap gutter-up grid=100x30 cursor=4,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scroll/cwd New Del Filter /tmp/pardes-snap/scroll/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scroll/cwd New Newtty Del Filte /tmp/pardes-snap/scroll/cwd New Newtty Del Filte
| 178 ls
| 179 s.txt
| 180
@@ -77,7 +77,7 @@
| 189
| 190
| 191
-| /tmp/pardes-snap/scroll/cwd New Del Filter
+| /tmp/pardes-snap/scroll/cwd New Newtty Del Filte
| ls
| s.txt
|
@@ -92,8 +92,8 @@
|
|
== snap gutter-down grid=100x30 cursor=4,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scroll/cwd New Del Filter /tmp/pardes-snap/scroll/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scroll/cwd New Newtty Del Filte /tmp/pardes-snap/scroll/cwd New Newtty Del Filte
| 180 ls
| 181 s.txt
| 182
@@ -108,7 +108,7 @@
| 191
| 192
| 193
-| /tmp/pardes-snap/scroll/cwd New Del Filter
+| /tmp/pardes-snap/scroll/cwd New Newtty Del Filte
| ls
| s.txt
|
@@ -123,8 +123,8 @@
|
|
== snap wheel-down grid=100x30 cursor=4,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scroll/cwd New Del Filter /tmp/pardes-snap/scroll/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scroll/cwd New Newtty Del Filte /tmp/pardes-snap/scroll/cwd New Newtty Del Filte
| 181 ls
| 182 s.txt
| 183
@@ -139,7 +139,7 @@
| 192
| 193
| 194
-| /tmp/pardes-snap/scroll/cwd New Del Filter
+| /tmp/pardes-snap/scroll/cwd New Newtty Del Filte
| ls
| s.txt
|
@@ -154,33 +154,33 @@
|
|
== style wheel-down
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-43 #949494,#121212, 44-49 d,#121212, 50-51 #ffffff,#262626, 52-93 #949494,#121212, 94-99 d,#121212,
-|2: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|3: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|4: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|5: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|6: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|7: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|8: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|9: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|10: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|11: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|12: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|13: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|15: 0-0 d,#121212, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|16: 0-1 #ffffff,#262626, 2-43 #949494,#121212, 44-49 d,#121212, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-49 #949494,#121212, 50-51 #ffffff,#262626, 52-99 #949494,#121212,
+|2: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-53 #bdbdbd,#080808, 54-99 d,#080808,
+|3: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-56 #bdbdbd,#080808, 57-99 d,#080808,
+|4: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|5: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|6: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|8: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|9: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|10: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|11: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|12: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|13: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|15: 0-0 d,#121212, 1-1 d,#080808, 2-4 #bdbdbd,#080808, 5-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-49 #949494,#121212, 50-50 d,#444444, 51-99 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|19: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|20: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|21: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|22: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|23: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|24: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|25: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|26: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|27: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|28: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|29: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
diff --git a/test/snapshots/scrolloff.golden b/test/snapshots/scrolloff.golden
index cff2035d..222d7f08 100644
--- a/test/snapshots/scrolloff.golden
+++ b/test/snapshots/scrolloff.golden
@@ -1,84 +1,84 @@
-== snap top grid=150x11 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scrolloff/cwd/g.txt /tmp/pardes-snap/scrolloff/cwd New /tmp/pardes-snap/scrolloff/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 line 2 g.txt g.txt
+== snap top grid=210x11 cursor=7,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scrolloff/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/scrolloff/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 line 2 g.txt
| 3 line 3
| 4 line 4
-| 5 line 5 /tmp/pardes-snap/scrolloff/cwd New
-| 6 line 6 ls
-| 7 line 7 g.txt
+| 5 line 5
+| 6 line 6
+| 7 line 7
| 8 line 8
| 9 line 9
-== snap edge grid=150x11 cursor=7,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scrolloff/cwd/g.txt /tmp/pardes-snap/scrolloff/cwd New /tmp/pardes-snap/scrolloff/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 line 2 g.txt g.txt
+== snap edge grid=210x11 cursor=7,7
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scrolloff/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/scrolloff/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 line 2 g.txt
| 3 line 3
| 4 line 4
-| 5 line 5 /tmp/pardes-snap/scrolloff/cwd New
-| 6 line 6 ls
-| 7 line 7 g.txt
+| 5 line 5
+| 6 line 6
+| 7 line 7
| 8 line 8
| 9 line 9
-== snap scrolled1 grid=150x11 cursor=7,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scrolloff/cwd/g.txt /tmp/pardes-snap/scrolloff/cwd New /tmp/pardes-snap/scrolloff/cwd New Del Filter
-| 2 line 2 ls ls
-| 3 line 3 g.txt g.txt
+== snap scrolled1 grid=210x11 cursor=7,7
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scrolloff/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/scrolloff/cwd New Newtty Del Filter
+| 2 line 2 ls
+| 3 line 3 g.txt
| 4 line 4
| 5 line 5
-| 6 line 6 /tmp/pardes-snap/scrolloff/cwd New
-| 7 line 7 ls
-| 8 line 8 g.txt
+| 6 line 6
+| 7 line 7
+| 8 line 8
| 9 line 9
| 10 line 10
-== snap jdown grid=150x11 cursor=7,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scrolloff/cwd/g.txt /tmp/pardes-snap/scrolloff/cwd New /tmp/pardes-snap/scrolloff/cwd New Del Filter
-| 6 line 6 ls ls
-| 7 line 7 g.txt g.txt
+== snap jdown grid=210x11 cursor=7,7
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scrolloff/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/scrolloff/cwd New Newtty Del Filter
+| 6 line 6 ls
+| 7 line 7 g.txt
| 8 line 8
| 9 line 9
-| 10 line 10 /tmp/pardes-snap/scrolloff/cwd New
-| 11 line 11 ls
-| 12 line 12 g.txt
+| 10 line 10
+| 11 line 11
+| 12 line 12
| 13 line 13
| 14 line 14
-== snap end grid=150x11 cursor=7,9
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scrolloff/cwd/g.txt /tmp/pardes-snap/scrolloff/cwd New /tmp/pardes-snap/scrolloff/cwd New Del Filter
-| 33 line 33 ls ls
-| 34 line 34 g.txt g.txt
+== snap end grid=210x11 cursor=7,9
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scrolloff/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/scrolloff/cwd New Newtty Del Filter
+| 33 line 33 ls
+| 34 line 34 g.txt
| 35 line 35
| 36 line 36
-| 37 line 37 /tmp/pardes-snap/scrolloff/cwd New
-| 38 line 38 ls
-| 39 line 39 g.txt
+| 37 line 37
+| 38 line 38
+| 39 line 39
| 40 line 40
| 41
-== snap kup grid=150x11 cursor=7,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scrolloff/cwd/g.txt /tmp/pardes-snap/scrolloff/cwd New /tmp/pardes-snap/scrolloff/cwd New Del Filter
-| 29 line 29 ls ls
-| 30 line 30 g.txt g.txt
+== snap kup grid=210x11 cursor=7,5
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scrolloff/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/scrolloff/cwd New Newtty Del Filter
+| 29 line 29 ls
+| 30 line 30 g.txt
| 31 line 31
| 32 line 32
-| 33 line 33 /tmp/pardes-snap/scrolloff/cwd New
-| 34 line 34 ls
-| 35 line 35 g.txt
+| 33 line 33
+| 34 line 34
+| 35 line 35
| 36 line 36
| 37 line 37
-== snap top2 grid=150x11 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/scrolloff/cwd/g.txt /tmp/pardes-snap/scrolloff/cwd New /tmp/pardes-snap/scrolloff/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 line 2 g.txt g.txt
+== snap top2 grid=210x11 cursor=7,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/scrolloff/cwd/g.txt Save New Newtty Del /tmp/pardes-snap/scrolloff/cwd New Newtty Del Filter
+| 1 line 1 ls
+| 2 line 2 g.txt
| 3 line 3
| 4 line 4
-| 5 line 5 /tmp/pardes-snap/scrolloff/cwd New
-| 6 line 6 ls
-| 7 line 7 g.txt
+| 5 line 5
+| 6 line 6
+| 7 line 7
| 8 line 8
| 9 line 9
diff --git a/test/snapshots/scrolloff.snap b/test/snapshots/scrolloff.snap
index 08b89a80..94ea36f6 100644
--- a/test/snapshots/scrolloff.snap
+++ b/test/snapshots/scrolloff.snap
@@ -1,7 +1,7 @@
# scrolloff: keyboard motion keeps 3 context rows above/below the cursor,
# clamped at file boundaries (cursor may reach the top/bottom body row there)
lines g.txt 40
-start 11 150 -n 3
+start 11 210 -n 1
wait 8000 g.txt
stable 700 20000
# right-click the g.txt name in the greeting ls -> file pane, 9 body rows
diff --git a/test/snapshots/selarg.golden b/test/snapshots/selarg.golden
index 529f4a56..af416616 100644
--- a/test/snapshots/selarg.golden
+++ b/test/snapshots/selarg.golden
@@ -1,6 +1,6 @@
== snap kept grid=100x30 cursor=6,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/selarg/cwd New Del Filter /tmp/pardes-snap/selarg/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/selarg/cwd New Newtty Del Filte /tmp/pardes-snap/selarg/cwd New Newtty Del Filte
| ZZARG ZZVEE ./c.sh
|
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/selarg/cwd New Del Filter
+| /tmp/pardes-snap/selarg/cwd New Newtty Del Filte
| ls
| s.txt
|
@@ -30,8 +30,8 @@
|
|
== snap crosspane grid=100x30 cursor=6,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/selarg/cwd New Del Filter /tmp/pardes-snap/selarg/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/selarg/cwd New Newtty Del Filte /tmp/pardes-snap/selarg/cwd New Newtty Del Filte
| ZZARG ZZVEE ./c.sh
| ./c.sh ZZARG
| CHORDARG:ZZARG
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/selarg/cwd New Del Filter
+| /tmp/pardes-snap/selarg/cwd New Newtty Del Filte
| ls
| s.txt
|
@@ -61,8 +61,8 @@
|
|
== snap vselarg grid=100x30 cursor=12,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/selarg/cwd New Del Filter /tmp/pardes-snap/selarg/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/selarg/cwd New Newtty Del Filte /tmp/pardes-snap/selarg/cwd New Newtty Del Filte
| ZZARG ZZVEE ./c.sh
| ./c.sh ZZARG
| CHORDARG:ZZARG
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/selarg/cwd New Del Filter
+| /tmp/pardes-snap/selarg/cwd New Newtty Del Filte
| ls
| s.txt
|
diff --git a/test/snapshots/selregex.golden b/test/snapshots/selregex.golden
index 90f64f72..16d06b51 100644
--- a/test/snapshots/selregex.golden
+++ b/test/snapshots/selregex.golden
@@ -1,6 +1,6 @@
== snap prompt-armed grid=160x24 cursor=11,23
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/selregex/cwd/m.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/selregex/cwd/m.zig Save New Newtty Del
| 1 const one = 1;
| 2 const two = 2;
| 3 const three = 3;
@@ -24,8 +24,8 @@
|
| Select /
== snap preview grid=160x24 cursor=16,23
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/selregex/cwd/m.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/selregex/cwd/m.zig Save New Newtty Del
| 1 const one = 1;
| 2 const two = 2;
| 3 const three = 3;
@@ -49,7 +49,7 @@
|
| Select /const
== style preview
-|0: 0-56 #949494,#121212, 57-159 d,#121212,
+|0: 0-74 #949494,#121212, 75-159 d,#121212,
|1: 0-1 #ffffff,#626262, 2-139 #949494,#121212, 140-159 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #080808,#80a0ff, 11-11 #80a0ff,#080808, 12-18 #bdbdbd,#080808, 19-19 #e3c78a,#080808, 20-20 #bdbdbd,#080808, 21-159 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #080808,#445483, 11-11 #80a0ff,#080808, 12-18 #bdbdbd,#080808, 19-19 #e3c78a,#080808, 20-20 #bdbdbd,#080808, 21-159 d,#080808,
@@ -74,8 +74,8 @@
|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-159 d,#080808,
|23: 0-0 d,#444444, 1-1 d,#080808, 2-15 #bdbdbd,#080808, 16-159 d,#080808,
== snap three-selected grid=160x24 cursor=11,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/selregex/cwd/m.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/selregex/cwd/m.zig Save New Newtty Del
| 1 const one = 1;
| 2 const two = 2;
| 3 const three = 3;
@@ -99,7 +99,7 @@
|
|
== style three-selected
-|0: 0-56 #949494,#121212, 57-159 d,#121212,
+|0: 0-74 #949494,#121212, 75-159 d,#121212,
|1: 0-1 #ffffff,#626262, 2-139 #949494,#121212, 140-159 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-11 #080808,#80a0ff, 12-18 #bdbdbd,#080808, 19-19 #e3c78a,#080808, 20-20 #bdbdbd,#080808, 21-159 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #080808,#445483, 11-11 #80a0ff,#080808, 12-18 #bdbdbd,#080808, 19-19 #e3c78a,#080808, 20-20 #bdbdbd,#080808, 21-159 d,#080808,
@@ -124,8 +124,8 @@
|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-159 d,#080808,
|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-159 d,#080808,
== snap narrowed grid=160x24 cursor=12,23
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/selregex/cwd/m.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/selregex/cwd/m.zig Save New Newtty Del
| 1 const one = 1;
| 2 const two = 2;
| 3 const three = 3;
@@ -149,7 +149,7 @@
|
| Select /t
== style narrowed
-|0: 0-56 #949494,#121212, 57-159 d,#121212,
+|0: 0-74 #949494,#121212, 75-159 d,#121212,
|1: 0-1 #ffffff,#626262, 2-139 #949494,#121212, 140-159 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-11 #80a0ff,#080808, 12-18 #bdbdbd,#080808, 19-19 #e3c78a,#080808, 20-20 #bdbdbd,#080808, 21-159 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-11 #80a0ff,#080808, 12-18 #bdbdbd,#080808, 19-19 #e3c78a,#080808, 20-20 #bdbdbd,#080808, 21-159 d,#080808,
@@ -174,8 +174,8 @@
|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-159 d,#080808,
|23: 0-0 d,#444444, 1-1 d,#080808, 2-11 #bdbdbd,#080808, 12-159 d,#080808,
== snap esc-restores grid=160x24 cursor=11,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/selregex/cwd/m.zig Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/selregex/cwd/m.zig Save New Newtty Del
| 1 const one = 1;
| 2 const two = 2;
| 3 const three = 3;
@@ -199,7 +199,7 @@
|
|
== style esc-restores
-|0: 0-56 #949494,#121212, 57-159 d,#121212,
+|0: 0-74 #949494,#121212, 75-159 d,#121212,
|1: 0-1 #ffffff,#626262, 2-139 #949494,#121212, 140-159 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-11 #080808,#80a0ff, 12-18 #bdbdbd,#080808, 19-19 #e3c78a,#080808, 20-20 #bdbdbd,#080808, 21-159 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #080808,#445483, 11-11 #80a0ff,#080808, 12-18 #bdbdbd,#080808, 19-19 #e3c78a,#080808, 20-20 #bdbdbd,#080808, 21-159 d,#080808,
@@ -224,8 +224,8 @@
|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-159 d,#080808,
|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-159 d,#080808,
== snap commented grid=160x24 cursor=14,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/selregex/cwd/m.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/selregex/cwd/m.zig * Save New Newtty Del
| 1 // const one = 1;
| 2 // const two = 2;
| 3 // const three = 3;
@@ -249,8 +249,8 @@
|
|
== snap uncommented grid=160x24 cursor=11,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/selregex/cwd/m.zig * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/selregex/cwd/m.zig * Save New Newtty Del
| 1 const one = 1;
| 2 const two = 2;
| 3 const three = 3;
diff --git a/test/snapshots/shellset.golden b/test/snapshots/shellset.golden
index 360ff6b0..a62cff70 100644
--- a/test/snapshots/shellset.golden
+++ b/test/snapshots/shellset.golden
@@ -1,6 +1,6 @@
== snap boot grid=90x20 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/shellset/cwd/cmd.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/shellset/cwd/cmd.txt Save New Newtty Del
| 1 Shell zznosuchshell
|
|
@@ -20,8 +20,8 @@
|
|
== snap builtin-ran grid=90x20 cursor=25,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/shellset/cwd/cmd.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/shellset/cwd/cmd.txt Save New Newtty Del
| 1 Shell zznosuchshell
|
|
@@ -41,8 +41,8 @@
|
|
== snap fallback-shell grid=90x20 cursor=49,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/shellset/cwd/cmd.txt Save /tmp/pardes-snap/shellset/cwd New Del Filte
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/shellset/cwd/cmd.txt Save /tmp/pardes-snap/shellset/cwd New Newtty De
| 1 Shell zznosuchshell ls
| cmd.txt zmarkfile.txt
|
diff --git a/test/snapshots/shellset.snap b/test/snapshots/shellset.snap
index 193d8432..45c94dee 100644
--- a/test/snapshots/shellset.snap
+++ b/test/snapshots/shellset.snap
@@ -36,8 +36,10 @@ stable 700 15000
# builtin and its argument went with it.
snap builtin-ran
# a new terminal, which asks for a shell that is not there. It gets the
-# fallback: the pane greets, `ls` runs, and its output is on screen.
-key space c n
+# fallback: the pane greets, `ls` runs, and its output is on screen. Alt-n and
+# Alt-c, because `New`/`Newcol` open an empty +New scratch rather than a shell.
+key a-n
+key a-c
wait 15000 zmarkfile.txt
stable 700 20000
snap fallback-shell
diff --git a/test/snapshots/shrinktag.golden b/test/snapshots/shrinktag.golden
index 5a7c110a..68e052d8 100644
--- a/test/snapshots/shrinktag.golden
+++ b/test/snapshots/shrinktag.golden
@@ -1,6 +1,6 @@
== snap before grid=100x30 cursor=2,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/shrinktag/cwd New Del Filter /tmp/pardes-snap/shrinktag/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi
| ls ls
| w.txt w.txt
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/shrinktag/cwd New Del Filter
+| /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi
| ls
| w.txt
|
@@ -30,9 +30,9 @@
|
|
== snap shrunk grid=100x30 cursor=2,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/shrinktag/cwd New Del Filter /tmp/pardes-snap/shrinktag/cwd New Del Filter
-| /tmp/pardes-snap/shrinktag/cwd New Del Filter ls
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi
+| /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi ls
| ls w.txt
| w.txt
|
@@ -61,9 +61,9 @@
|
|
== snap move-preview grid=100x30 cursor=2,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/shrinktag/cwd New Del Filter /tmp/pardes-snap/shrinktag/cwd New Del Filter
-| /tmp/pardes-snap/shrinktag/cwd New Del Filter ls
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi
+| /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi ls
| ls w.txt
| w.txt
|
@@ -92,8 +92,8 @@
|
|
== snap restored grid=100x30 cursor=2,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/shrinktag/cwd New Del Filter /tmp/pardes-snap/shrinktag/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi
| ls ls
| w.txt w.txt
|
@@ -108,7 +108,7 @@
|
|
|
-| /tmp/pardes-snap/shrinktag/cwd New Del Filter
+| /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi
| ls
| w.txt
|
@@ -123,8 +123,8 @@
|
|
== snap bottom-shrunk grid=100x30 cursor=2,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/shrinktag/cwd New Del Filter /tmp/pardes-snap/shrinktag/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi
| ls ls
| w.txt w.txt
|
@@ -152,4 +152,4 @@
|
|
|
-| /tmp/pardes-snap/shrinktag/cwd New Del Filter
+| /tmp/pardes-snap/shrinktag/cwd New Newtty Del Fi
diff --git a/test/snapshots/splitparent.golden b/test/snapshots/splitparent.golden
index 8f215448..32845bfe 100644
--- a/test/snapshots/splitparent.golden
+++ b/test/snapshots/splitparent.golden
@@ -1,7 +1,7 @@
== snap shrunk grid=100x30 cursor=4,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/splitparent/cwd New Del Filter /tmp/pardes-snap/splitparent/cwd New Del Filter
-| /tmp/pardes-snap/splitparent/cwd New Del Filter ls
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del /tmp/pardes-snap/splitparent/cwd New Newtty Del
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del ls
| ls
|
|
@@ -30,12 +30,12 @@
|
|
== snap swap-parent grid=100x30 cursor=4,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/splitparent/cwd New Del Filter /tmp/pardes-snap/splitparent/cwd New Del Filter
-| /tmp/pardes-snap/splitparent/cwd New Del Filter ls
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del /tmp/pardes-snap/splitparent/cwd New Newtty Del
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del ls
| ls
|
-| /tmp/pardes-snap/splitparent/cwd New Del Filter
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del
| ls
|
|
@@ -61,18 +61,18 @@
|
|
== snap tallest grid=100x5 cursor=54,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/splitparent/cwd New Del Filter /tmp/pardes-snap/splitparent/cwd New Del Filter
-| /tmp/pardes-snap/splitparent/cwd New Del Filter
-| /tmp/pardes-snap/splitparent/cwd New Del Filter /tmp/pardes-snap/splitparent/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del /tmp/pardes-snap/splitparent/cwd New Newtty Del
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del /tmp/pardes-snap/splitparent/cwd New Newtty Del
|
== snap regrown grid=100x30 cursor=54,18
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/splitparent/cwd New Del Filter /tmp/pardes-snap/splitparent/cwd New Del Filter
-| /tmp/pardes-snap/splitparent/cwd New Del Filter ls
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del /tmp/pardes-snap/splitparent/cwd New Newtty Del
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del ls
| ls
|
-| /tmp/pardes-snap/splitparent/cwd New Del Filter
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del
| ls
|
|
@@ -83,7 +83,7 @@
|
|
|
-| /tmp/pardes-snap/splitparent/cwd New Del Filter
+| /tmp/pardes-snap/splitparent/cwd New Newtty Del
| ls
|
|
diff --git a/test/snapshots/stepgrain.golden b/test/snapshots/stepgrain.golden
index f269c865..6dae3b96 100644
--- a/test/snapshots/stepgrain.golden
+++ b/test/snapshots/stepgrain.golden
@@ -1,6 +1,6 @@
== snap results grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Newtty Del
| 1 hello ZQMARK one
| 2 see also sub/b.txt for ZQMARK two
|
@@ -25,13 +25,13 @@
|
|
|
-| /tmp/pardes-snap/stepgrain/cwd/+Search New Del
+| /tmp/pardes-snap/stepgrain/cwd/+Search New Newtty Del
| 1 a.txt:1:7-12 hello ZQMARK one
| 2 a.txt:2:24-29 see also sub/b.txt for ZQMARK two
| 3 sub/b.txt:1:1-6 ZQMARK inside sub
== snap step-row1 grid=150x30 cursor=7,27
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Newtty Del
| 1 hello ZQMARK one
| 2 see also sub/b.txt for ZQMARK two
|
@@ -56,12 +56,12 @@
|
|
|
-| /tmp/pardes-snap/stepgrain/cwd/+Search New Del
+| /tmp/pardes-snap/stepgrain/cwd/+Search New Newtty Del
| 1 a.txt:1:7-12 hello ZQMARK one
| 2 a.txt:2:24-29 see also sub/b.txt for ZQMARK two
| 3 sub/b.txt:1:1-6 ZQMARK inside sub
== style step-row1
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
|1: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-149 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-39 #bdbdbd,#080808, 40-149 d,#080808,
@@ -92,8 +92,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-53 #bdbdbd,#080808, 54-149 d,#080808,
|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-39 #bdbdbd,#080808, 40-149 d,#080808,
== snap step-row2 grid=150x30 cursor=7,28
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Newtty Del
| 1 hello ZQMARK one
| 2 see also sub/b.txt for ZQMARK two
|
@@ -118,12 +118,12 @@
|
|
|
-| /tmp/pardes-snap/stepgrain/cwd/+Search New Del
+| /tmp/pardes-snap/stepgrain/cwd/+Search New Newtty Del
| 1 a.txt:1:7-12 hello ZQMARK one
| 2 a.txt:2:24-29 see also sub/b.txt for ZQMARK two
| 3 sub/b.txt:1:1-6 ZQMARK inside sub
== style step-row2
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
|1: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-149 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-39 #bdbdbd,#080808, 40-149 d,#080808,
@@ -154,8 +154,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-19 #080808,#80a0ff, 20-53 #bdbdbd,#080808, 54-149 d,#080808,
|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-39 #bdbdbd,#080808, 40-149 d,#080808,
== snap step-row3 grid=150x30 cursor=7,28
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Newtty Del
| 1 hello ZQMARK one
| 2 see also sub/b.txt for ZQMARK two
|
@@ -180,13 +180,13 @@
|
|
|
-| /tmp/pardes-snap/stepgrain/cwd/+Search New Del
+| /tmp/pardes-snap/stepgrain/cwd/+Search New Newtty Del
| 2 a.txt:2:24-29 see also sub/b.txt for ZQMARK two
| 3 sub/b.txt:1:1-6 ZQMARK inside sub
| 4
== snap step-wrap grid=150x30 cursor=7,27
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Newtty Del
| 1 hello ZQMARK one
| 2 see also sub/b.txt for ZQMARK two
|
@@ -211,13 +211,13 @@
|
|
|
-| /tmp/pardes-snap/stepgrain/cwd/+Search New Del
+| /tmp/pardes-snap/stepgrain/cwd/+Search New Newtty Del
| 1 a.txt:1:7-12 hello ZQMARK one
| 2 a.txt:2:24-29 see also sub/b.txt for ZQMARK two
| 3 sub/b.txt:1:1-6 ZQMARK inside sub
== snap blank-in-path grid=150x30 cursor=7,25
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Newtty Del
| 1 hello ZQMARK one
| 2 see also sub/b.txt for ZQMARK two
|
@@ -240,14 +240,14 @@
|
|
|
-| /tmp/pardes-snap/stepgrain/cwd/+Search New Del
+| /tmp/pardes-snap/stepgrain/cwd/+Search New Newtty Del
| 1 two words.txt
-| /tmp/pardes-snap/stepgrain/cwd/+Search New Del
+| /tmp/pardes-snap/stepgrain/cwd/+Search New Newtty Del
| 1 a.txt:1:7-12 hello ZQMARK one
| 2 a.txt:2:24-29 see also sub/b.txt for ZQMARK two
| 3 sub/b.txt:1:1-6 ZQMARK inside sub
== style blank-in-path
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
|1: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-149 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-39 #bdbdbd,#080808, 40-149 d,#080808,
@@ -278,8 +278,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-53 #bdbdbd,#080808, 54-149 d,#080808,
|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-39 #bdbdbd,#080808, 40-149 d,#080808,
== snap blank-opened grid=150x30 cursor=7,14
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/stepgrain/cwd/a.txt Save New Newtty Del
| 1 hello ZQMARK one
| 2 see also sub/b.txt for ZQMARK two
|
@@ -291,7 +291,7 @@
|
|
|
-| /tmp/pardes-snap/stepgrain/cwd/two words.txt Save New Del
+| /tmp/pardes-snap/stepgrain/cwd/two words.txt Save New Newtty Del
| 1
|
|
@@ -302,9 +302,9 @@
|
|
|
-| /tmp/pardes-snap/stepgrain/cwd/+Search New Del
+| /tmp/pardes-snap/stepgrain/cwd/+Search New Newtty Del
| 1 two words.txt
-| /tmp/pardes-snap/stepgrain/cwd/+Search New Del
+| /tmp/pardes-snap/stepgrain/cwd/+Search New Newtty Del
| 1 a.txt:1:7-12 hello ZQMARK one
| 2 a.txt:2:24-29 see also sub/b.txt for ZQMARK two
| 3 sub/b.txt:1:1-6 ZQMARK inside sub
diff --git a/test/snapshots/syntax.golden b/test/snapshots/syntax.golden
index a8c40383..937852ff 100644
--- a/test/snapshots/syntax.golden
+++ b/test/snapshots/syntax.golden
@@ -1,23 +1,23 @@
== snap zig-open grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/syntax/cwd/demo.zig /tmp/pardes-snap/syntax/cwd New Del /tmp/pardes-snap/syntax/cwd New Del Filter
-| 1 const std = @import("std"); //↩ ls ls
-| greet demo.zig demo.zig
-| 2 pub fn main() void {
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/syntax/cwd/demo.zig Save New Newtty Del /tmp/pardes-snap/syntax/cwd New Newtty Del Filter
+| 1 const std = @import("std"); // greet ls
+| 2 pub fn main() void { demo.zig
| 3 var x: u32 = 42;
| 4 _ = x;
-| 5 } demo.zig
+| 5 }
+|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
+| /tmp/pardes-snap/syntax/cwd New Newtty Del Filter
+| ls
+| demo.zig
|
|
|
+| demo.zig
|
-|
-|
-|
-|
-| /tmp/pardes-snap/syntax/cwd New Del
-| ls
-| demo.zig
+| /tmp/pardes-snap/syntax/cwd New Newtty Del Filter
+| ls
+| demo.zig
|
|
|
@@ -30,95 +30,95 @@
|
|
== style zig-open
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-18 #bdbdbd,#080808, 19-25 #cf87e8,#080808,b 26-26 #bdbdbd,#080808, 27-31 #e3c78a,#080808, 32-34 #bdbdbd,#080808, 35-36 #ffffff,#080808,b 37-37 #626262,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #ffffff,#080808,b 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-12 #cf87e8,#080808,b 13-26 #bdbdbd,#080808, 27-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-23 #bdbdbd,#080808, 24-25 #e3c78a,#080808, 26-26 #bdbdbd,#080808, 27-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #bdbdbd,#080808, 8-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-49 #bdbdbd,#080808, 50-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-57 #949494,#121212, 58-74 d,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-18 #bdbdbd,#080808, 19-25 #cf87e8,#080808,b 26-26 #bdbdbd,#080808, 27-31 #e3c78a,#080808, 32-34 #bdbdbd,#080808, 35-42 #ffffff,#080808,b 43-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-12 #cf87e8,#080808,b 13-26 #bdbdbd,#080808, 27-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-84 #bdbdbd,#080808, 85-149 d,#080808,
+|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-23 #bdbdbd,#080808, 24-25 #e3c78a,#080808, 26-26 #bdbdbd,#080808, 27-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #bdbdbd,#080808, 8-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-57 #949494,#121212, 58-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-9 #bdbdbd,#080808, 10-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-11 #bdbdbd,#080808, 12-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-57 #949494,#121212, 58-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-9 #bdbdbd,#080808, 10-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
== style colors-off
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-36 #bdbdbd,#080808, 37-37 #626262,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-41 #bdbdbd,#080808, 42-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #bdbdbd,#080808, 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-47 #bdbdbd,#080808, 48-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-84 #bdbdbd,#080808, 85-149 d,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #bdbdbd,#080808, 27-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #bdbdbd,#080808, 27-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #bdbdbd,#080808, 8-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-49 #bdbdbd,#080808, 50-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-149 d,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-41 #bdbdbd,#080808, 42-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-47 #bdbdbd,#080808, 48-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-57 #949494,#121212, 58-74 d,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-42 #bdbdbd,#080808, 43-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #bdbdbd,#080808, 27-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-84 #bdbdbd,#080808, 85-149 d,#080808,
+|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #bdbdbd,#080808, 27-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #bdbdbd,#080808, 8-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-57 #949494,#121212, 58-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-9 #bdbdbd,#080808, 10-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-11 #bdbdbd,#080808, 12-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-57 #949494,#121212, 58-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-9 #bdbdbd,#080808, 10-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
== style colors-on
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-37 #949494,#121212, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-18 #bdbdbd,#080808, 19-25 #cf87e8,#080808,b 26-26 #bdbdbd,#080808, 27-31 #e3c78a,#080808, 32-34 #bdbdbd,#080808, 35-36 #ffffff,#080808,b 37-37 #626262,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-12 #ffffff,#080808,b 13-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-12 #cf87e8,#080808,b 13-26 #bdbdbd,#080808, 27-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-23 #bdbdbd,#080808, 24-25 #e3c78a,#080808, 26-26 #bdbdbd,#080808, 27-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #bdbdbd,#080808, 8-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-49 #bdbdbd,#080808, 50-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-39 #ffffff,#262626, 40-74 #949494,#121212, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 d,#080808, 38-38 d,#444444, 39-39 d,#080808, 40-74 #bdbdbd,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-57 #949494,#121212, 58-74 d,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-18 #bdbdbd,#080808, 19-25 #cf87e8,#080808,b 26-26 #bdbdbd,#080808, 27-31 #e3c78a,#080808, 32-34 #bdbdbd,#080808, 35-42 #ffffff,#080808,b 43-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-78 #bdbdbd,#080808, 79-149 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-12 #cf87e8,#080808,b 13-26 #bdbdbd,#080808, 27-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-84 #bdbdbd,#080808, 85-149 d,#080808,
+|4: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-23 #bdbdbd,#080808, 24-25 #e3c78a,#080808, 26-26 #bdbdbd,#080808, 27-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|5: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-16 #bdbdbd,#080808, 17-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|6: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-7 #bdbdbd,#080808, 8-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|7: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|8: 0-1 #ffffff,#262626, 2-57 #949494,#121212, 58-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|9: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|10: 0-0 d,#444444, 1-1 d,#080808, 2-9 #bdbdbd,#080808, 10-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|11: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|12: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|13: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-11 #bdbdbd,#080808, 12-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|15: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-57 #949494,#121212, 58-74 d,#121212, 75-75 d,#444444, 76-149 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-9 #bdbdbd,#080808, 10-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|19: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|20: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|21: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|22: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|23: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|24: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|25: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|26: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|27: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|28: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
+|29: 0-0 d,#444444, 1-74 d,#080808, 75-75 d,#444444, 76-149 d,#080808,
diff --git a/test/snapshots/tag.golden b/test/snapshots/tag.golden
index 18f2e818..45e0ce0c 100644
--- a/test/snapshots/tag.golden
+++ b/test/snapshots/tag.golden
@@ -1,6 +1,6 @@
-== snap tag-focus grid=150x30 cursor=39,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tag/cwd New Del Filter /tmp/pardes-snap/tag/cwd New Del Filter
+== snap tag-focus grid=150x30 cursor=27,1
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tag/cwd New Newtty Del Filter /tmp/pardes-snap/tag/cwd New Newtty Del Filter
| ls ls
| t.txt t.txt
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/tag/cwd New Del Filter
+| /tmp/pardes-snap/tag/cwd New Newtty Del Filter
| ls
| t.txt
|
@@ -29,9 +29,9 @@
|
|
|
-== snap tag-typed grid=150x30 cursor=45,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tag/cwd t.txt New Del Filter /tmp/pardes-snap/tag/cwd New Del Filter
+== snap tag-typed grid=150x30 cursor=33,1
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tag/cwd t.txt New Newtty Del Filter /tmp/pardes-snap/tag/cwd New Newtty Del Filter
| ls ls
| t.txt t.txt
|
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/tag/cwd New Del Filter
+| /tmp/pardes-snap/tag/cwd New Newtty Del Filter
| ls
| t.txt
|
@@ -60,9 +60,9 @@
|
|
|
-== snap tag-del grid=150x30 cursor=41,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tag/cwd t New Del Filter /tmp/pardes-snap/tag/cwd New Del Filter
+== snap tag-del grid=150x30 cursor=29,1
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tag/cwd t New Newtty Del Filter /tmp/pardes-snap/tag/cwd New Newtty Del Filter
| ls ls
| t.txt t.txt
|
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/tag/cwd New Del Filter
+| /tmp/pardes-snap/tag/cwd New Newtty Del Filter
| ls
| t.txt
|
@@ -92,8 +92,8 @@
|
|
== snap tag-exit grid=150x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tag/cwd t.txt New Del Filter /tmp/pardes-snap/tag/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tag/cwd t.txt New Newtty Del Filter /tmp/pardes-snap/tag/cwd New Newtty Del Filter
| ls ls
| t.txt t.txt
|
@@ -108,7 +108,7 @@
|
|
|
-| /tmp/pardes-snap/tag/cwd New Del Filter
+| /tmp/pardes-snap/tag/cwd New Newtty Del Filter
| ls
| t.txt
|
@@ -123,25 +123,25 @@
|
|
== snap tag-look grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tag/cwd/t.txt Save /tmp/pardes-snap/tag/cwd /tmp/pardes-snap/tag/cwd New Del Filter
-| 1 ZZLOOKED ls ls
-| t.txt t.txt
-|
-|
-|
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tag/cwd/t.txt Save New Newtty Del /tmp/pardes-snap/tag/cwd New Newtty Del Filter
+| 1 ZZLOOKED ls
+| t.txt
|
|
|
|
+| /tmp/pardes-snap/tag/cwd t.txt New Newtty Del Filter
+| ls
+| t.txt
|
|
|
|
|
-| /tmp/pardes-snap/tag/cwd New Del Fi
-| ls
-| t.txt
+| /tmp/pardes-snap/tag/cwd New Newtty Del Filter
+| ls
+| t.txt
|
|
|
diff --git a/test/snapshots/tag.snap b/test/snapshots/tag.snap
index 966bfd52..37f0b751 100644
--- a/test/snapshots/tag.snap
+++ b/test/snapshots/tag.snap
@@ -12,8 +12,8 @@ stable 700 20000
# the pane's BODY mode, not the tag's, so the evidence for "this click went to
# insert" is the next step — the typed text lands as text instead of running as
# normal-mode commands.
-press left 40 2
-release left 40 2
+press left 28 2
+release left 28 2
stable 400 5000
snap tag-focus
send \x20t.txt
@@ -38,8 +38,8 @@ snap tag-exit
# Clicked ON the word rather than past the end of the tag and walked back into
# it — the builtins are right-aligned now (config.tag_right_pad), so the tag no
# longer ends where the typing does and a click past it lands in the gap.
-press left 43 2
-release left 43 2
+press left 31 2
+release left 31 2
stable 400 5000
key enter
wait 10000 ZZLOOKED
diff --git a/test/snapshots/tagalign.golden b/test/snapshots/tagalign.golden
index 354b151a..ca9900ca 100644
--- a/test/snapshots/tagalign.golden
+++ b/test/snapshots/tagalign.golden
@@ -1,6 +1,6 @@
== snap aligned grid=100x30 cursor=4,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagalign/cwd/deep/nested-project-directory/document.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagalign/cwd/deep/nested-project-directory/document.txt Save New Newtty Del
| 1 alpha
| 2 beta
| 3 gamma
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/tagalign/cwd New Del Filter
+| /tmp/pardes-snap/tagalign/cwd New Newtty Del Filter
| ls
| deep
|
@@ -30,8 +30,8 @@
|
|
== snap fits grid=87x30 cursor=4,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagalign/cwd/deep/nested-project-directory/document.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagalign/cwd/deep/nested-project-directory/document.txt Save New New
| 1 alpha
| 2 beta
| 3 gamma
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/tagalign/cwd New Del Filter
+| /tmp/pardes-snap/tagalign/cwd New Newtty Del Filter
| ls
| deep
|
@@ -61,8 +61,8 @@
|
|
== snap overby1 grid=86x30 cursor=4,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagalign/cwd/deep/nested-project-directory/document.txt Save New De
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagalign/cwd/deep/nested-project-directory/document.txt Save New Ne
| 1 alpha
| 2 beta
| 3 gamma
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/tagalign/cwd New Del Filter
+| /tmp/pardes-snap/tagalign/cwd New Newtty Del Filter
| ls
| deep
|
@@ -92,8 +92,8 @@
|
|
== snap clicked grid=100x30 cursor=11,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagalign/cwd/deep/nested-project-directory/document.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagalign/cwd/deep/nested-project-directory/document.txt Save New Newtty Del
| 1 alpha
| 2 beta
| 3 gamma
@@ -108,7 +108,7 @@
|
|
|
-| /tmp/pardes-snap/tagalign/cwd New Del Filter
+| /tmp/pardes-snap/tagalign/cwd New Newtty Del Filter
| ls
| deep
|
@@ -122,26 +122,26 @@
|
|
|
-== snap alone grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagalign/cwd New Del Filter
-| ls
-| deep
-|
-|
-|
-|
-|
-|
-|
-|
+== snap alone grid=100x30 cursor=4,12
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagalign/cwd/deep/nested-project-directory/document.txt Save New Newtty Del
+| 1 alpha
+| 2 beta
+| 3 gamma
|
|
|
|
+|$ /tmp/pardes-snap/tagalign/cwd/deep/nested-project-directory New Newtty Del Filter
+| $ ls
+| document.txt
+| $
|
|
|
+| /tmp/pardes-snap/tagalign/cwd New Newtty Del Filter
+| ls
+| deep
|
|
|
diff --git a/test/snapshots/tagalign2col.golden b/test/snapshots/tagalign2col.golden
index 668dd8b3..c78066bb 100644
--- a/test/snapshots/tagalign2col.golden
+++ b/test/snapshots/tagalign2col.golden
@@ -1,6 +1,6 @@
== snap onecol grid=160x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagalign2col/cwd/deep/proj/document.txt Save New Del /tmp/pardes-snap/tagalign2col/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagalign2col/cwd/deep/proj/document.txt Save New Newtty Del /tmp/pardes-snap/tagalign2col/cwd New Newtty Del Filter
| 1 alpha ls
| 2 beta deep
| 3 gamma
@@ -30,8 +30,8 @@
|
|
== snap aligned grid=160x30 cursor=4,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagalign2col/cwd/deep/proj/document.txt Save New Del /tmp/pardes-snap/tagalign2col/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagalign2col/cwd/deep/proj/document.txt Save New Newtty Del /tmp/pardes-snap/tagalign2col/cwd New Newtty Del Filter
| 1 alpha ls
| 2 beta deep
| 3 gamma
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/tagalign2col/cwd New Del Filter
+| /tmp/pardes-snap/tagalign2col/cwd New Newtty Del Filter
| ls
| deep
|
@@ -61,8 +61,8 @@
|
|
== snap widened grid=160x30 cursor=4,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagalign2col/cwd/deep/proj/document.txt Save New Del ╎ /tmp/pardes-snap/tagalign2col/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagalign2col/cwd/deep/proj/document.txt Save New Newtty Del ╎ /tmp/pardes-snap/tagalign2col/cwd New Newtty Del Filter
| 1 alpha ╎ ls
| 2 beta ╎ deep
| 3 gamma ╎
@@ -77,7 +77,7 @@
| ╎
| ╎
| ╎
-| /tmp/pardes-snap/tagalign2col/cwd New Del Filter ╎
+| /tmp/pardes-snap/tagalign2col/cwd New Newtty Del Filter ╎
| ls ╎
| deep ╎
| ╎
diff --git a/test/snapshots/tagalign2col.snap b/test/snapshots/tagalign2col.snap
index 03d214ff..56048c8b 100644
--- a/test/snapshots/tagalign2col.snap
+++ b/test/snapshots/tagalign2col.snap
@@ -4,7 +4,7 @@
# feature would look like it worked right up until you opened a second column.
#
# Here the long path is in the LEFT column (that is which side it lands on:
-# `SPC c n` puts the NEW column on the right, so the boot file keeps the left)
+# Alt-c puts the NEW column on the right, so the boot file keeps the left)
# and the right column is a plain shell. Both columns are 80 wide, so both
# would end their words at tag_right_pad — 58 columns in — if nothing pushed.
dirmk deep
@@ -14,11 +14,13 @@ start 30 160 deep/proj/document.txt
wait 8000 New Newcol
wait 8000 document.txt
stable 700 20000
-# `SPC c n`: a shell in a column of its own on the right. Two columns, one pane
-# each. The file's own tag is 69 columns and so pushes past its column's pad;
-# the shell on the right sits AT its pad, 58 in. Read the two ends off this
-# snap — they are what the next one must not disturb.
-key space c n
+# Alt-n then Alt-c: a shell in a column of its own on the right (`New`/`Newcol`
+# open an empty +New scratch now, not a shell). Two columns, one pane each. The
+# file's own tag is 69 columns and so pushes past its column's pad; the shell on
+# the right sits AT its pad, 58 in. Read the two ends off this snap — they are
+# what the next one must not disturb.
+key a-n
+key a-c
stable 700 15000
key space w h
stable 400 5000
diff --git a/test/snapshots/tagbottom.golden b/test/snapshots/tagbottom.golden
index 8a1222d3..36f89143 100644
--- a/test/snapshots/tagbottom.golden
+++ b/test/snapshots/tagbottom.golden
@@ -1,6 +1,6 @@
== snap boot grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagbottom/cwd/top.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagbottom/cwd/top.txt Save New Newtty Del
| 1 aaa
| 2 bbb
| 3 ccc
@@ -30,7 +30,7 @@
|
|
== snap on grid=100x30 cursor=7,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 aaa
| 2 bbb
| 3 ccc
@@ -59,10 +59,10 @@
| 26 zzz
|
|
-| /tmp/pardes-snap/tagbottom/cwd/top.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt Save New Newtty Del
== snap off grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagbottom/cwd/top.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagbottom/cwd/top.txt Save New Newtty Del
| 1 aaa
| 2 bbb
| 3 ccc
@@ -92,7 +92,7 @@
|
|
== snap tag-typed grid=100x30 cursor=60,29
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 aaa
| 2 bbb
| 3 ccc
@@ -121,9 +121,9 @@
| 26 zzz
|
|
-| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Newtty Del
== snap look-bottom-tag grid=100x30 cursor=7,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 aaa
| 2 bbb
| 3 ccc
@@ -138,7 +138,7 @@
| 12 lll
| 13 mmm
| 14 nnn
-| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Newtty Del
| 1 ZZONE
| 2 ZZTWO
|
@@ -152,9 +152,9 @@
|
|
|
-| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Newtty Del
== snap body-cursor grid=100x30 cursor=9,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 aaa
| 2 bbb
| 3 ccc
@@ -169,7 +169,7 @@
| 12 lll
| 13 mmm
| 14 nnn
-| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Newtty Del
| 1 ZZONE
| 2 ZZTWO
|
@@ -183,9 +183,9 @@
|
|
|
-| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Newtty Del
== snap seam-noop grid=100x30 cursor=9,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 aaa
| 2 bbb
| 3 ccc
@@ -200,7 +200,7 @@
| 12 lll
| 13 mmm
| 14 nnn
-| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Newtty Del
| 1 ZZONE
| 2 ZZTWO
|
@@ -214,9 +214,9 @@
|
|
|
-| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Newtty Del
== snap seam-dragged grid=100x30 cursor=9,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 aaa
| 2 bbb
| 3 ccc
@@ -226,7 +226,7 @@
| 7 ggg
| 8 hhh
| 9 iii
-| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Newtty Del
| 1 ZZONE
| 2 ZZTWO
|
@@ -245,9 +245,9 @@
|
|
|
-| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Newtty Del
== snap gutter-click grid=100x30 cursor=9,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 2 bbb
| 3 ccc
| 4 ddd
@@ -257,7 +257,7 @@
| 8 hhh
| 9 iii
| 10 jjj
-| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Newtty Del
| 1 ZZONE
| 2 ZZTWO
|
@@ -276,9 +276,9 @@
|
|
|
-| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Newtty Del
== snap search-prompt grid=100x30 cursor=6,28
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 2 bbb
| 3 ccc
| 4 ddd
@@ -288,7 +288,7 @@
| 8 hhh
| 9 iii
| 10 jjj
-| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Newtty Del
| 1 ZZONE
| 2 ZZTWO
|
@@ -307,9 +307,9 @@
|
|
| /ZZ
-| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Newtty Del
== snap leader grid=100x30 cursor=9,13
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 2 bbb
| 3 ccc
| 4 ddd
@@ -319,7 +319,7 @@
| 8 hhh
| 9 iii
| 10 jjj
-| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Newtty Del
| 1 ZZONE
| 2 ZZTWO
|
@@ -338,9 +338,9 @@
|
|
| SPC
-| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Newtty Del
== snap cut-down grid=100x30 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 aaa
| 2 bbb
| 3 ccc
@@ -350,7 +350,7 @@
| 7 mmm
| 8 nnn
| 9 ooo
-| /tmp/pardes-snap/tagbottom/cwd/top.txt * bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt * bottom.txt Save New Newtty Del
| 1 ZZONE
| 2 ZZTWO
|
@@ -369,7 +369,7 @@
|
|
|
-| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save New Newtty Del
== file cut-buffer
aaa
bbb
@@ -393,7 +393,7 @@ yyy
zzz
== end file
== snap del-bottom-tag grid=100x30 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 aaa
| 2 bbb
| 3 ccc
@@ -422,10 +422,10 @@ zzz
|
|
|
-| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Del
+| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Newtty Del
== snap off-again grid=100x30 cursor=7,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagbottom/cwd/top.txt bottom.txt Save New Newtty Del
| 1 aaa
| 2 bbb
| 3 ccc
diff --git a/test/snapshots/tagbottomimage.golden b/test/snapshots/tagbottomimage.golden
index 98e8c129..7c601fad 100644
--- a/test/snapshots/tagbottomimage.golden
+++ b/test/snapshots/tagbottomimage.golden
@@ -1,129 +1,50 @@
== snap img-top grid=150x30 cursor=11,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| img petscii:off palette:commodore ascii:on /tmp/pardes-snap/tagbottomimag /tmp/pardes-snap/tagbottomimage/cwd New Del Filter
-| (f🬱]0V7R*%m🬶🬁G🬬tN#XR9q🬢tC#f/🬜_GR(🬞🬙tCRp$o*7^+[#H7s🬢YDZ🬝▟ ls
-| iU)dSotT[r27T"\*Fh▐🬅g,🬰p🬛▙🬲&*3/9xy🬛▀0kCg▛🬱C,>C}PC06m🬝▟█ pic.ppm
-| "S▄;$gs,Xa▟T🬔s▖┼W▘?by🬋🬭uCR3/A3🬶lO▖▞🬃🬘╳🬟#=🬺🬕yoaJ@>4🬝🬵
-| ─m!fAAD🬒jW>7JkR▄▜🬫🬞🬢FWx╲▟2ZT🬥/▖jteR?q🬶^🬅▀_@N─u4🬹🬝🬹
-| E72z🬧🬒oy🬧e▌ijY╲&🬅mbh╲h$🬘🬴PS9y▙0H🬳╲🬂&🬣╲,🬃,R;█AZ🬝▟
-| <JBpn-S┼zq^🬄677grnk🬛bMd2|VB▙┼'🬎f/{X7🬮jO^]Y─🬄🬎🬻█ pic.ppm
-| 🬊3🬶🬛As0╲─Wd$╳🬤vRnfXIVH&)C+frE2FJZ🬃e🬊W🬔@▜@s🬝🬻█
-| ▛▛aRawF│▌o<╲🬪dGk/gJ🬴🬍🬧mYbR▀LZx🬒%t'sUX:p🬌🬝🬹
-| ─"n_&mht┼A0j]p┼🬲/B%c$1Ln;🬗s*▟j!🬥q2U#🬙&#~
-| 🬖🬈p"│vctj'&^X─C*🬍🬆@&F,7{h`🬷mg▜b╱e%@V🬝🬹█
-| J5▝$8),x&🬩i🬰~D🬚v(>kz5zXa92Q▖` i6Ax🬝🬵
-| z[I🬮╲🬸&j;▟▛eY🬉L&u?🬫gc▝🬍5🬉Q🬪s2V🬗🬡🬝🬹█
-| XUq🬨[╱🬒Zb<"#.$1Zby╳Fk:y🬠🬷z\txn🬝▟
-| r🬗│G"🬵8🬘j=F🬐Z🬫@u▛╲r🬖$🬥%┼6f&>🬝🬹█
-| ~{🬫$blt🬘=dxu",🬣t🬣=y🬌H3>\🬎A🬝🬻
-| k🬴5L🬹🬢u>-!🬊Ga▟╱🬈D🬉╳wEZ'g🬎▄
-| y'5K%p?:╳🬤▘/fZ╳>jwbv0M🬝▟
-| %C🬢▄🬍▗I🬬G▄🬡w~Hp!#"Q▝▛▄█
-| 🬯[▜?To5@q🬗gmJ.w🬉~R🬝▟█
-| y🬗🬞+*X7eJ🬮`X}ZO🬟🬝▟█
-| ╱^🬷pc[a]juQ[🬷$🬝🬻
-| g6▗>🬌7O▞3🬤b─🬝▟
-| YVQ8Q╳NF🬝▐🬝🬹█
-| 🬯│@/]4%^🬆~█
-| eP🬗<┼A🬝🬹█
-| ▀(u🬬🬝▟
-| fc🬎🬹█
-| 🬝🬹
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| img petscii:off palette:commodore ascii:on /tmp/pardes-snap/tagbottomimage/cwd/pic.ppm New Newtty Del
+| 9d4🬫▚{▙v]O*🬥🬣n🬍🬕5S6#4🬵C[🬆🬻
+| {🬲🬍s🬕/*%!🬖🬹╱?🬷C🬔3q🬗]Q┼🬆🬹
+| }=^!t🬺R'My┼▐jP▞🬡y}▄V🬆~
+| 6(9?🬝🬳J1🬢k?g🬶🬙SY%t🬆▄█
+| ╲Ep^w🬪2zJbxF&🬷🬦a🬝~
+| 🬥K`🬙🬲$'#3x(▜🬌a▛🬹
+| zj🬡{U🬨(j🬗🬔E[▛🬹█
+| 🬺🬊*V*]g^🬳p▀🬹
+| [;🬬/M🬊🬲🬻🬆🬻
+| │🬕r🬜┼e🬆🬻
+| [🬝g4🬆🬹
+| 🬐🬹🬆🬹
+| 🬎🬻█
+| /tmp/pardes-snap/tagbottomimage/cwd New Newtty Del Filter
+| ls
+| pic.ppm
+|
+|
+|
+| pic.ppm
+|
+|
+|
+|
+|
+|
+|
+|
== snap img-bottom grid=150x30 cursor=11,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| (f🬱]0V7R*%m🬶🬁G🬬tN#XR9q🬢tC#f/🬜_GR(🬞🬙tCRp$o*7^+[#H7s🬢YDZ🬝▟ ls
-| iU)dSotT[r27T"\*Fh▐🬅g,🬰p🬛▙🬲&*3/9xy🬛▀0kCg▛🬱C,>C}PC06m🬝▟█ pic.ppm
-| "S▄;$gs,Xa▟T🬔s▖┼W▘?by🬋🬭uCR3/A3🬶lO▖▞🬃🬘╳🬟#=🬺🬕yoaJ@>4🬝🬵
-| ─m!fAAD🬒jW>7JkR▄▜🬫🬞🬢FWx╲▟2ZT🬥/▖jteR?q🬶^🬅▀_@N─u4🬹🬝🬹
-| E72z🬧🬒oy🬧e▌ijY╲&🬅mbh╲h$🬘🬴PS9y▙0H🬳╲🬂&🬣╲,🬃,R;█AZ🬝▟
-| <JBpn-S┼zq^🬄677grnk🬛bMd2|VB▙┼'🬎f/{X7🬮jO^]Y─🬄🬎🬻█ pic.ppm
-| 🬊3🬶🬛As0╲─Wd$╳🬤vRnfXIVH&)C+frE2FJZ🬃e🬊W🬔@▜@s🬝🬻█
-| ▛▛aRawF│▌o<╲🬪dGk/gJ🬴🬍🬧mYbR▀LZx🬒%t'sUX:p🬌🬝🬹
-| ─"n_&mht┼A0j]p┼🬲/B%c$1Ln;🬗s*▟j!🬥q2U#🬙&#~
-| 🬖🬈p"│vctj'&^X─C*🬍🬆@&F,7{h`🬷mg▜b╱e%@V🬝🬹█
-| J5▝$8),x&🬩i🬰~D🬚v(>kz5zXa92Q▖` i6Ax🬝🬵
-| z[I🬮╲🬸&j;▟▛eY🬉L&u?🬫gc▝🬍5🬉Q🬪s2V🬗🬡🬝🬹█
-| XUq🬨[╱🬒Zb<"#.$1Zby╳Fk:y🬠🬷z\txn🬝▟
-| r🬗│G"🬵8🬘j=F🬐Z🬫@u▛╲r🬖$🬥%┼6f&>🬝🬹█
-| ~{🬫$blt🬘=dxu",🬣t🬣=y🬌H3>\🬎A🬝🬻
-| k🬴5L🬹🬢u>-!🬊Ga▟╱🬈D🬉╳wEZ'g🬎▄
-| y'5K%p?:╳🬤▘/fZ╳>jwbv0M🬝▟
-| %C🬢▄🬍▗I🬬G▄🬡w~Hp!#"Q▝▛▄█
-| 🬯[▜?To5@q🬗gmJ.w🬉~R🬝▟█
-| y🬗🬞+*X7eJ🬮`X}ZO🬟🬝▟█
-| ╱^🬷pc[a]juQ[🬷$🬝🬻
-| g6▗>🬌7O▞3🬤b─🬝▟
-| YVQ8Q╳NF🬝▐🬝🬹█
-| 🬯│@/]4%^🬆~█
-| eP🬗<┼A🬝🬹█
-| ▀(u🬬🬝▟
-| fc🬎🬹█
-| 🬝🬹
-| img petscii:off palette:commodore ascii:on /tmp/pardes-snap/tagbottomimag /tmp/pardes-snap/tagbottomimage/cwd New Del Filter
-== style img-bottom
-|0: 0-56 #949494,#121212, 57-149 d,#121212,
-|1: 0-0 d,#121212, 1-9 d,#080808, 10-10 #959595,#6c6c6c, 11-11 #6c6c6c,#959595, 12-12 #959595,#6c6c6c, 13-13 #6c6c6c,#959595, 14-24 #959595,#6c6c6c, 25-27 #6c6c6c,#959595, 28-28 #959595,#6c6c6c, 29-30 #6c6c6c,#959595, 31-32 #959595,#6c6c6c, 33-34 #6c6c6c,#959595, 35-35 #959595,#6c6c6c, 36-37 #6c6c6c,#959595, 38-39 #959595,#6c6c6c, 40-40 #6c6c6c,#959595, 41-41 #959595,#6c6c6c, 42-42 #6c6c6c,#959595, 43-44 #959595,#6c6c6c, 45-47 #6c6c6c,#959595, 48-50 #959595,#6c6c6c, 51-51 #6c6c6c,#959595, 52-52 #959595,#6c6c6c, 53-53 #6c6c6c,#959595, 54-63 #959595,#6c6c6c, 64-64 #959595,#352879, 65-65 #352879,#6c6c6c, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|2: 0-0 d,#121212, 1-9 d,#080808, 10-10 #959595,#6c6c6c, 11-12 #6c6c6c,#959595, 13-13 #959595,#6c6c6c, 14-15 #6c6c6c,#959595, 16-18 #959595,#6c6c6c, 19-19 #6c6c6c,#959595, 20-20 #959595,#6c6c6c, 21-21 #6c6c6c,#959595, 22-32 #959595,#6c6c6c, 33-33 #6c6c6c,#959595, 34-37 #959595,#6c6c6c, 38-39 #6c6c6c,#959595, 40-44 #959595,#6c6c6c, 45-45 #6c6c6c,#959595, 46-47 #959595,#6c6c6c, 48-48 #6c6c6c,#959595, 49-52 #959595,#6c6c6c, 53-53 #444444,#959595, 54-54 #959595,#6c6c6c, 55-55 #6c6c6c,#959595, 56-58 #959595,#6c6c6c, 59-59 #6c6c6c,#959595, 60-60 #959595,#6c6c6c, 61-61 #6c6c6c,#959595, 62-62 #959595,#352879, 63-63 #352879,#959595, 64-64 #352879,#6c5eb5, 65-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|3: 0-0 d,#121212, 1-9 d,#080808, 10-10 #6c6c6c,#959595, 11-13 #959595,#6c6c6c, 14-16 #6c6c6c,#959595, 17-17 #444444,#959595, 18-22 #959595,#6c6c6c, 23-23 #6c6c6c,#959595, 24-26 #959595,#6c6c6c, 27-27 #6c6c6c,#959595, 28-28 #959595,#6c6c6c, 29-30 #6c6c6c,#959595, 31-32 #959595,#6c6c6c, 33-33 #6c6c6c,#959595, 34-35 #959595,#6c6c6c, 36-36 #6c6c6c,#959595, 37-37 #444444,#959595, 38-38 #959595,#6c6c6c, 39-39 #6c6c6c,#959595, 40-43 #959595,#6c6c6c, 44-44 #6c6c6c,#959595, 45-48 #959595,#6c6c6c, 49-51 #6c6c6c,#959595, 52-52 #959595,#6c6c6c, 53-53 #6c6c6c,#959595, 54-55 #959595,#6c6c6c, 56-58 #6c6c6c,#959595, 59-59 #959595,#6c6c6c, 60-60 #6c6c6c,#352879, 61-61 #352879,#6c5eb5, 62-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|4: 0-0 d,#121212, 1-9 d,#080808, 10-10 #959595,#6c6c6c, 11-11 #6c6c6c,#959595, 12-17 #959595,#6c6c6c, 18-18 #6c6c6c,#959595, 19-19 #959595,#6c6c6c, 20-22 #6c6c6c,#959595, 23-26 #959595,#6c6c6c, 27-27 #6c6c6c,#959595, 28-29 #959595,#6c6c6c, 30-33 #6c6c6c,#959595, 34-35 #959595,#6c6c6c, 36-37 #6c6c6c,#959595, 38-40 #959595,#6c6c6c, 41-41 #6c6c6c,#959595, 42-42 #959595,#6c6c6c, 43-43 #6c6c6c,#959595, 44-44 #959595,#6c6c6c, 45-46 #6c6c6c,#959595, 47-47 #959595,#6c6c6c, 48-48 #6c6c6c,#959595, 49-49 #959595,#6c6c6c, 50-50 #6c6c6c,#959595, 51-51 #444444,#959595, 52-56 #959595,#6c6c6c, 57-57 #6c6c6c,#959595, 58-58 #959595,#352879, 59-59 #352879,#959595, 60-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|5: 0-0 d,#121212, 1-9 d,#080808, 10-11 #959595,#6c6c6c, 12-13 #6c6c6c,#959595, 14-16 #959595,#6c6c6c, 17-17 #6c6c6c,#959595, 18-19 #959595,#6c6c6c, 20-20 #6c6c6c,#959595, 21-21 #959595,#6c6c6c, 22-22 #6c6c6c,#959595, 23-24 #959595,#6c6c6c, 25-25 #6c6c6c,#959595, 26-27 #959595,#6c6c6c, 28-32 #6c6c6c,#959595, 33-40 #959595,#6c6c6c, 41-41 #6c6c6c,#959595, 42-53 #959595,#6c6c6c, 54-54 #6c6c6c,#959595, 55-55 #959595,#6c6c6c, 56-56 #959595,#352879, 57-57 #352879,#6c6c6c, 58-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|6: 0-0 d,#121212, 1-9 d,#080808, 10-13 #6c6c6c,#959595, 14-15 #959595,#6c6c6c, 16-16 #6c6c6c,#959595, 17-18 #959595,#6c6c6c, 19-19 #6c6c6c,#959595, 20-23 #959595,#6c6c6c, 24-24 #6c6c6c,#959595, 25-26 #959595,#6c6c6c, 27-28 #6c6c6c,#959595, 29-30 #959595,#6c6c6c, 31-31 #6c6c6c,#959595, 32-35 #959595,#6c6c6c, 36-38 #6c6c6c,#959595, 39-40 #959595,#6c6c6c, 41-41 #6c6c6c,#959595, 42-42 #959595,#6c6c6c, 43-43 #6c6c6c,#959595, 44-48 #959595,#6c6c6c, 49-49 #444444,#959595, 50-50 #959595,#6c6c6c, 51-51 #6c6c6c,#959595, 52-53 #959595,#6c6c6c, 54-54 #959595,#352879, 55-55 #352879,#444444, 56-56 #352879,#6c5eb5, 57-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-85 #bdbdbd,#080808, 86-149 d,#080808,
-|7: 0-0 d,#121212, 1-9 d,#080808, 10-15 #959595,#6c6c6c, 16-21 #6c6c6c,#959595, 22-25 #959595,#6c6c6c, 26-26 #6c6c6c,#959595, 27-29 #959595,#6c6c6c, 30-30 #6c6c6c,#959595, 31-31 #959595,#6c6c6c, 32-34 #6c6c6c,#959595, 35-38 #959595,#6c6c6c, 39-39 #6c6c6c,#959595, 40-45 #959595,#6c6c6c, 46-48 #6c6c6c,#959595, 49-49 #959595,#6c6c6c, 50-51 #6c6c6c,#959595, 52-52 #6c6c6c,#352879, 53-53 #352879,#6c6c6c, 54-54 #352879,#6c5eb5, 55-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|8: 0-0 d,#121212, 1-9 d,#080808, 10-10 #959595,#6c6c6c, 11-11 #6c6c6c,#959595, 12-13 #959595,#6c6c6c, 14-14 #6c6c6c,#959595, 15-15 #959595,#6c6c6c, 16-16 #6c6c6c,#959595, 17-17 #959595,#6c6c6c, 18-20 #6c6c6c,#959595, 21-24 #959595,#6c6c6c, 25-25 #6c6c6c,#959595, 26-26 #959595,#6c6c6c, 27-27 #6c6c6c,#959595, 28-28 #959595,#6c6c6c, 29-29 #6c6c6c,#959595, 30-34 #959595,#6c6c6c, 35-35 #6c6c6c,#959595, 36-36 #959595,#6c6c6c, 37-37 #6c6c6c,#959595, 38-40 #959595,#6c6c6c, 41-41 #6c6c6c,#959595, 42-42 #959595,#6c6c6c, 43-43 #444444,#959595, 44-44 #959595,#6c6c6c, 45-45 #6c6c6c,#959595, 46-46 #959595,#6c6c6c, 47-47 #444444,#959595, 48-48 #6c6c6c,#959595, 49-49 #959595,#6c6c6c, 50-50 #6c6c6c,#352879, 51-51 #352879,#6c5eb5, 52-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|9: 0-0 d,#121212, 1-9 d,#080808, 10-10 #6c6c6c,#959595, 11-13 #959595,#6c6c6c, 14-14 #6c6c6c,#959595, 15-15 #959595,#6c6c6c, 16-16 #6c6c6c,#959595, 17-18 #959595,#6c6c6c, 19-19 #6c6c6c,#959595, 20-20 #444444,#959595, 21-24 #959595,#6c6c6c, 25-25 #6c6c6c,#959595, 26-26 #959595,#6c6c6c, 27-30 #6c6c6c,#959595, 31-35 #959595,#6c6c6c, 36-37 #6c6c6c,#959595, 38-38 #959595,#6c6c6c, 39-40 #6c6c6c,#959595, 41-44 #959595,#6c6c6c, 45-45 #6c6c6c,#959595, 46-47 #959595,#6c6c6c, 48-49 #959595,#352879, 50-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|10: 0-0 d,#121212, 1-9 d,#080808, 10-13 #959595,#6c6c6c, 14-14 #6c6c6c,#959595, 15-17 #959595,#6c6c6c, 18-18 #6c6c6c,#959595, 19-20 #959595,#6c6c6c, 21-21 #6c6c6c,#959595, 22-23 #959595,#6c6c6c, 24-24 #6c6c6c,#959595, 25-30 #959595,#6c6c6c, 31-34 #6c6c6c,#959595, 35-36 #959595,#6c6c6c, 37-37 #6c6c6c,#959595, 38-38 #959595,#6c6c6c, 39-40 #6c6c6c,#959595, 41-41 #444444,#959595, 42-42 #959595,#6c6c6c, 43-45 #6c6c6c,#959595, 46-46 #6c6c6c,#352879, 47-47 #352879,#6c6c6c, 48-48 #352879,#6c5eb5, 49-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|11: 0-0 d,#121212, 1-9 d,#080808, 10-11 #6c6c6c,#959595, 12-13 #959595,#6c6c6c, 14-15 #6c6c6c,#959595, 16-16 #959595,#6c6c6c, 17-20 #6c6c6c,#959595, 21-21 #959595,#6c6c6c, 22-22 #6c6c6c,#959595, 23-23 #959595,#6c6c6c, 24-24 #6c6c6c,#959595, 25-25 #959595,#6c6c6c, 26-26 #6c6c6c,#959595, 27-28 #959595,#6c6c6c, 29-29 #6c6c6c,#959595, 30-31 #959595,#6c6c6c, 32-33 #6c6c6c,#959595, 34-35 #959595,#6c6c6c, 36-36 #6c6c6c,#959595, 37-38 #959595,#6c6c6c, 39-39 #444444,#6c6c6c, 40-40 #6c6c6c,#959595, 41-41 #959595,#6c6c6c, 42-42 #6c6c6c,#959595, 43-43 #959595,#6c6c6c, 44-44 #959595,#352879, 45-45 #352879,#6c5eb5, 46-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|12: 0-0 d,#121212, 1-9 d,#080808, 10-10 #6c6c6c,#959595, 11-13 #959595,#6c6c6c, 14-14 #444444,#6c6c6c, 15-24 #959595,#6c6c6c, 25-25 #6c6c6c,#959595, 26-31 #959595,#6c6c6c, 32-39 #6c6c6c,#959595, 40-41 #959595,#6c6c6c, 42-42 #6c6c6c,#352879, 43-43 #352879,#959595, 44-44 #352879,#6c5eb5, 45-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|13: 0-0 d,#121212, 1-9 d,#080808, 10-10 #959595,#6c6c6c, 11-11 #6c6c6c,#959595, 12-16 #959595,#6c6c6c, 17-17 #6c6c6c,#959595, 18-20 #959595,#6c6c6c, 21-21 #6c6c6c,#959595, 22-23 #959595,#6c6c6c, 24-27 #6c6c6c,#959595, 28-29 #959595,#6c6c6c, 30-30 #6c6c6c,#959595, 31-31 #959595,#6c6c6c, 32-32 #6c6c6c,#959595, 33-35 #959595,#6c6c6c, 36-38 #6c6c6c,#959595, 39-39 #959595,#6c6c6c, 40-40 #6c6c6c,#352879, 41-41 #352879,#6c6c6c, 42-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|14: 0-0 d,#121212, 1-9 d,#080808, 10-10 #6c6c6c,#959595, 11-15 #959595,#6c6c6c, 16-16 #6c6c6c,#959595, 17-21 #959595,#6c6c6c, 22-22 #6c6c6c,#959595, 23-23 #959595,#6c6c6c, 24-25 #6c6c6c,#959595, 26-26 #959595,#6c6c6c, 27-27 #444444,#959595, 28-29 #6c6c6c,#959595, 30-32 #959595,#6c6c6c, 33-33 #6c6c6c,#959595, 34-34 #959595,#6c6c6c, 35-35 #6c6c6c,#959595, 36-36 #959595,#6c6c6c, 37-37 #6c6c6c,#959595, 38-38 #6c6c6c,#352879, 39-39 #352879,#959595, 40-40 #352879,#6c5eb5, 41-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|15: 0-0 d,#121212, 1-9 d,#080808, 10-10 #6c6c6c,#959595, 11-13 #959595,#6c6c6c, 14-14 #6c6c6c,#959595, 15-20 #959595,#6c6c6c, 21-21 #6c6c6c,#959595, 22-24 #959595,#6c6c6c, 25-25 #6c6c6c,#959595, 26-27 #959595,#6c6c6c, 28-29 #6c6c6c,#959595, 30-31 #959595,#6c6c6c, 32-32 #6c6c6c,#959595, 33-33 #959595,#6c6c6c, 34-34 #6c6c6c,#959595, 35-35 #959595,#6c6c6c, 36-36 #6c6c6c,#352879, 37-37 #352879,#959595, 38-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|16: 0-0 d,#121212, 1-9 d,#080808, 10-11 #959595,#6c6c6c, 12-12 #6c6c6c,#959595, 13-15 #959595,#6c6c6c, 16-16 #6c6c6c,#959595, 17-17 #959595,#6c6c6c, 18-19 #6c6c6c,#959595, 20-21 #959595,#6c6c6c, 22-22 #6c6c6c,#959595, 23-29 #959595,#6c6c6c, 30-31 #6c6c6c,#959595, 32-32 #959595,#6c6c6c, 33-33 #6c6c6c,#959595, 34-34 #959595,#352879, 35-35 #352879,#6c5eb5, 36-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|17: 0-0 d,#121212, 1-9 d,#080808, 10-12 #959595,#6c6c6c, 13-15 #6c6c6c,#959595, 16-16 #959595,#6c6c6c, 17-17 #444444,#959595, 18-20 #959595,#6c6c6c, 21-21 #6c6c6c,#959595, 22-22 #959595,#6c6c6c, 23-23 #6c6c6c,#959595, 24-27 #959595,#6c6c6c, 28-28 #6c6c6c,#959595, 29-31 #959595,#6c6c6c, 32-32 #6c6c6c,#352879, 33-33 #352879,#6c6c6c, 34-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|18: 0-0 d,#121212, 1-9 d,#080808, 10-16 #959595,#6c6c6c, 17-17 #6c6c6c,#959595, 18-18 #959595,#6c6c6c, 19-19 #6c6c6c,#959595, 20-20 #959595,#6c6c6c, 21-21 #6c6c6c,#959595, 22-23 #959595,#6c6c6c, 24-26 #6c6c6c,#959595, 27-27 #959595,#6c6c6c, 28-28 #6c6c6c,#959595, 29-29 #959595,#6c6c6c, 30-30 #959595,#352879, 31-32 #352879,#6c5eb5, 33-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|19: 0-0 d,#121212, 1-9 d,#080808, 10-11 #959595,#6c6c6c, 12-12 #6c6c6c,#959595, 13-15 #959595,#6c6c6c, 16-17 #6c6c6c,#959595, 18-19 #959595,#6c6c6c, 20-21 #6c6c6c,#959595, 22-22 #959595,#6c6c6c, 23-24 #6c6c6c,#959595, 25-26 #959595,#6c6c6c, 27-27 #6c6c6c,#959595, 28-28 #6c6c6c,#352879, 29-29 #352879,#6c6c6c, 30-30 #352879,#6c5eb5, 31-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|20: 0-0 d,#121212, 1-9 d,#080808, 10-14 #959595,#6c6c6c, 15-15 #6c6c6c,#959595, 16-17 #959595,#6c6c6c, 18-18 #6c6c6c,#959595, 19-19 #959595,#6c6c6c, 20-20 #6c6c6c,#959595, 21-21 #959595,#6c6c6c, 22-22 #6c6c6c,#959595, 23-25 #959595,#6c6c6c, 26-26 #6c6c6c,#352879, 27-27 #352879,#6c6c6c, 28-28 #352879,#6c5eb5, 29-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|21: 0-0 d,#121212, 1-9 d,#080808, 10-12 #6c6c6c,#959595, 13-14 #959595,#6c6c6c, 15-16 #6c6c6c,#959595, 17-20 #959595,#6c6c6c, 21-21 #6c6c6c,#959595, 22-22 #959595,#6c6c6c, 23-23 #6c6c6c,#959595, 24-24 #6c6c6c,#352879, 25-25 #352879,#959595, 26-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|22: 0-0 d,#121212, 1-9 d,#080808, 10-10 #959595,#6c6c6c, 11-11 #6c6c6c,#959595, 12-21 #959595,#6c6c6c, 22-22 #6c6c6c,#352879, 23-23 #352879,#6c6c6c, 24-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|23: 0-0 d,#121212, 1-9 d,#080808, 10-11 #6c6c6c,#959595, 12-13 #959595,#6c6c6c, 14-14 #6c6c6c,#959595, 15-15 #959595,#6c6c6c, 16-17 #6c6c6c,#959595, 18-19 #959595,#6c6c6c, 20-20 #6c6c6c,#352879, 21-21 #352879,#959595, 22-22 #352879,#6c5eb5, 23-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|24: 0-0 d,#121212, 1-9 d,#080808, 10-11 #959595,#6c6c6c, 12-13 #6c6c6c,#959595, 14-16 #959595,#6c6c6c, 17-17 #6c6c6c,#959595, 18-19 #959595,#352879, 20-20 #352879,#6c5eb5, 21-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|25: 0-0 d,#121212, 1-9 d,#080808, 10-11 #6c6c6c,#959595, 12-15 #959595,#6c6c6c, 16-16 #959595,#352879, 17-17 #352879,#6c6c6c, 18-18 #352879,#6c5eb5, 19-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|26: 0-0 d,#121212, 1-9 d,#080808, 10-10 #6c6c6c,#959595, 11-12 #959595,#6c6c6c, 13-13 #959595,#444444, 14-14 #6c6c6c,#352879, 15-15 #352879,#959595, 16-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|27: 0-0 d,#121212, 1-9 d,#080808, 10-11 #6c6c6c,#959595, 12-12 #6c6c6c,#352879, 13-13 #352879,#6c6c6c, 14-14 #352879,#6c5eb5, 15-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|28: 0-0 d,#121212, 1-9 d,#080808, 10-10 #6c6c6c,#352879, 11-11 #352879,#6c6c6c, 12-65 #352879,#352879, 66-74 d,#080808, 75-75 d,#444444, 76-76 d,#080808, 77-149 #bdbdbd,#080808,
-|29: 0-1 #ffffff,#626262, 2-74 #949494,#121212, 75-76 #ffffff,#262626, 77-129 #949494,#121212, 130-149 d,#121212,
-== snap search-prompt grid=150x30 cursor=6,28
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| (f🬱]0V7R*%m🬶🬁G🬬tN#XR9q🬢tC#f/🬜_GR(🬞🬙tCRp$o*7^+[#H7s🬢YDZ🬝▟ ls
-| iU)dSotT[r27T"\*Fh▐🬅g,🬰p🬛▙🬲&*3/9xy🬛▀0kCg▛🬱C,>C}PC06m🬝▟█ pic.ppm
-| "S▄;$gs,Xa▟T🬔s▖┼W▘?by🬋🬭uCR3/A3🬶lO▖▞🬃🬘╳🬟#=🬺🬕yoaJ@>4🬝🬵
-| ─m!fAAD🬒jW>7JkR▄▜🬫🬞🬢FWx╲▟2ZT🬥/▖jteR?q🬶^🬅▀_@N─u4🬹🬝🬹
-| E72z🬧🬒oy🬧e▌ijY╲&🬅mbh╲h$🬘🬴PS9y▙0H🬳╲🬂&🬣╲,🬃,R;█AZ🬝▟
-| <JBpn-S┼zq^🬄677grnk🬛bMd2|VB▙┼'🬎f/{X7🬮jO^]Y─🬄🬎🬻█ pic.ppm
-| 🬊3🬶🬛As0╲─Wd$╳🬤vRnfXIVH&)C+frE2FJZ🬃e🬊W🬔@▜@s🬝🬻█
-| ▛▛aRawF│▌o<╲🬪dGk/gJ🬴🬍🬧mYbR▀LZx🬒%t'sUX:p🬌🬝🬹
-| ─"n_&mht┼A0j]p┼🬲/B%c$1Ln;🬗s*▟j!🬥q2U#🬙&#~
-| 🬖🬈p"│vctj'&^X─C*🬍🬆@&F,7{h`🬷mg▜b╱e%@V🬝🬹█
-| J5▝$8),x&🬩i🬰~D🬚v(>kz5zXa92Q▖` i6Ax🬝🬵
-| z[I🬮╲🬸&j;▟▛eY🬉L&u?🬫gc▝🬍5🬉Q🬪s2V🬗🬡🬝🬹█
-| XUq🬨[╱🬒Zb<"#.$1Zby╳Fk:y🬠🬷z\txn🬝▟
-| r🬗│G"🬵8🬘j=F🬐Z🬫@u▛╲r🬖$🬥%┼6f&>🬝🬹█
-| ~{🬫$blt🬘=dxu",🬣t🬣=y🬌H3>\🬎A🬝🬻
-| k🬴5L🬹🬢u>-!🬊Ga▟╱🬈D🬉╳wEZ'g🬎▄
-| y'5K%p?:╳🬤▘/fZ╳>jwbv0M🬝▟
-| %C🬢▄🬍▗I🬬G▄🬡w~Hp!#"Q▝▛▄█
-| 🬯[▜?To5@q🬗gmJ.w🬉~R🬝▟█
-| y🬗🬞+*X7eJ🬮`X}ZO🬟🬝▟█
-| ╱^🬷pc[a]juQ[🬷$🬝🬻
-| g6▗>🬌7O▞3🬤b─🬝▟
-| YVQ8Q╳NF🬝▐🬝🬹█
-| 🬯│@/]4%^🬆~█
-| eP🬗<┼A🬝🬹█
-| ▀(u🬬🬝▟
-| fc🬎🬹█
-| /ZZ
-| img petscii:off palette:commodore ascii:on /tmp/pardes-snap/tagbottomimag /tmp/pardes-snap/tagbottomimage/cwd New Del Filter
-== snap del-image grid=150x30 cursor=5,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| 9d4🬫▚{▙v]O*🬥🬣n🬍🬕5S6#4🬵C[🬆🬻
+| {🬲🬍s🬕/*%!🬖🬹╱?🬷C🬔3q🬗]Q┼🬆🬹
+| }=^!t🬺R'My┼▐jP▞🬡y}▄V🬆~
+| 6(9?🬝🬳J1🬢k?g🬶🬙SY%t🬆▄█
+| ╲Ep^w🬪2zJbxF&🬷🬦a🬝~
+| 🬥K`🬙🬲$'#3x(▜🬌a▛🬹
+| zj🬡{U🬨(j🬗🬔E[▛🬹█
+| 🬺🬊*V*]g^🬳p▀🬹
+| [;🬬/M🬊🬲🬻🬆🬻
+| │🬕r🬜┼e🬆🬻
+| [🬝g4🬆🬹
+| 🬐🬹🬆🬹
+| 🬎🬻█
+| img petscii:off palette:commodore ascii:on /tmp/pardes-snap/tagbottomimage/cwd/pic.ppm New Newtty Del
| ls
| pic.ppm
|
@@ -138,6 +59,60 @@
|
|
|
+| /tmp/pardes-snap/tagbottomimage/cwd New Newtty Del Filter
+== style img-bottom
+|0: 0-74 #949494,#121212, 75-149 d,#121212,
+|1: 0-0 d,#121212, 1-62 d,#080808, 63-64 #959595,#6c6c6c, 65-66 #6c6c6c,#959595, 67-68 #959595,#6c6c6c, 69-69 #6c6c6c,#959595, 70-71 #959595,#6c6c6c, 72-72 #6c6c6c,#959595, 73-74 #959595,#6c6c6c, 75-76 #6c6c6c,#959595, 77-77 #959595,#6c6c6c, 78-78 #6c6c6c,#959595, 79-79 #959595,#6c6c6c, 80-80 #6c6c6c,#959595, 81-81 #959595,#6c6c6c, 82-82 #6c6c6c,#959595, 83-83 #959595,#6c6c6c, 84-84 #6c6c6c,#959595, 85-86 #959595,#6c6c6c, 87-87 #959595,#6c5eb5, 88-88 #352879,#959595, 89-149 d,#080808,
+|2: 0-0 d,#121212, 1-62 d,#080808, 63-64 #6c6c6c,#959595, 65-65 #959595,#6c6c6c, 66-67 #6c6c6c,#959595, 68-75 #959595,#6c6c6c, 76-81 #6c6c6c,#959595, 82-82 #959595,#6c6c6c, 83-83 #6c6c6c,#959595, 84-84 #959595,#6c6c6c, 85-85 #6c6c6c,#6c5eb5, 86-86 #352879,#6c5eb5, 87-88 #352879,#352879, 89-149 d,#080808,
+|3: 0-0 d,#121212, 1-62 d,#080808, 63-63 #6c6c6c,#959595, 64-66 #959595,#6c6c6c, 67-69 #6c6c6c,#959595, 70-71 #959595,#6c6c6c, 72-74 #6c6c6c,#959595, 75-77 #959595,#6c6c6c, 78-78 #6c6c6c,#959595, 79-82 #959595,#6c6c6c, 83-83 #959595,#6c5eb5, 84-84 #6c6c6c,#352879, 85-88 #352879,#352879, 89-149 d,#080808,
+|4: 0-0 d,#121212, 1-62 d,#080808, 63-67 #959595,#6c6c6c, 68-69 #6c6c6c,#959595, 70-73 #959595,#6c6c6c, 74-77 #6c6c6c,#959595, 78-79 #959595,#6c6c6c, 80-80 #6c6c6c,#959595, 81-81 #959595,#6c5eb5, 82-83 #352879,#6c5eb5, 84-88 #352879,#352879, 89-149 d,#080808,
+|5: 0-0 d,#121212, 1-62 d,#080808, 63-63 #959595,#6c6c6c, 64-64 #6c6c6c,#959595, 65-65 #959595,#6c6c6c, 66-66 #6c6c6c,#959595, 67-70 #959595,#6c6c6c, 71-72 #6c6c6c,#959595, 73-75 #959595,#6c6c6c, 76-78 #6c6c6c,#959595, 79-80 #6c6c6c,#352879, 81-88 #352879,#352879, 89-149 d,#080808,
+|6: 0-0 d,#121212, 1-62 d,#080808, 63-63 #6c6c6c,#959595, 64-65 #959595,#6c6c6c, 66-68 #6c6c6c,#959595, 69-69 #959595,#6c6c6c, 70-70 #6c6c6c,#959595, 71-73 #959595,#6c6c6c, 74-75 #6c6c6c,#959595, 76-76 #959595,#6c6c6c, 77-77 #6c6c6c,#352879, 78-78 #352879,#6c5eb5, 79-88 #352879,#352879, 89-149 d,#080808,
+|7: 0-0 d,#121212, 1-62 d,#080808, 63-64 #959595,#6c6c6c, 65-65 #6c6c6c,#959595, 66-67 #959595,#6c6c6c, 68-68 #6c6c6c,#959595, 69-69 #959595,#6c6c6c, 70-71 #6c6c6c,#959595, 72-73 #959595,#6c6c6c, 74-74 #6c6c6c,#959595, 75-75 #6c6c6c,#352879, 76-77 #352879,#6c5eb5, 78-88 #352879,#352879, 89-149 d,#080808,
+|8: 0-0 d,#121212, 1-62 d,#080808, 63-63 #6c6c6c,#959595, 64-68 #959595,#6c6c6c, 69-69 #6c6c6c,#959595, 70-70 #959595,#6c6c6c, 71-71 #6c6c6c,#959595, 72-72 #959595,#6c6c6c, 73-73 #6c6c6c,#6c5eb5, 74-74 #352879,#6c5eb5, 75-88 #352879,#352879, 89-149 d,#080808,
+|9: 0-0 d,#121212, 1-62 d,#080808, 63-64 #959595,#6c6c6c, 65-65 #6c6c6c,#959595, 66-66 #959595,#6c6c6c, 67-68 #6c6c6c,#959595, 69-69 #959595,#6c6c6c, 70-70 #6c6c6c,#959595, 71-71 #6c6c6c,#6c5eb5, 72-72 #352879,#6c6c6c, 73-88 #352879,#352879, 89-149 d,#080808,
+|10: 0-0 d,#121212, 1-62 d,#080808, 63-64 #6c6c6c,#959595, 65-65 #959595,#6c6c6c, 66-68 #6c6c6c,#959595, 69-69 #6c6c6c,#6c5eb5, 70-70 #352879,#6c6c6c, 71-88 #352879,#352879, 89-149 d,#080808,
+|11: 0-0 d,#121212, 1-62 d,#080808, 63-64 #959595,#6c6c6c, 65-66 #6c6c6c,#959595, 67-67 #6c6c6c,#6c5eb5, 68-68 #352879,#6c5eb5, 69-88 #352879,#352879, 89-149 d,#080808,
+|12: 0-0 d,#121212, 1-62 d,#080808, 63-63 #959595,#6c6c6c, 64-64 #6c6c6c,#959595, 65-65 #6c6c6c,#6c5eb5, 66-66 #352879,#6c5eb5, 67-88 #352879,#352879, 89-149 d,#080808,
+|13: 0-0 d,#121212, 1-62 d,#080808, 63-63 #6c6c6c,#352879, 64-64 #352879,#6c6c6c, 65-65 #352879,#6c5eb5, 66-88 #352879,#352879, 89-149 d,#080808,
+|14: 0-1 #ffffff,#626262, 2-129 #949494,#121212, 130-149 d,#121212,
+|15: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-149 d,#080808,
+|16: 0-0 d,#444444, 1-1 d,#080808, 2-8 #bdbdbd,#080808, 9-149 d,#080808,
+|17: 0-0 d,#444444, 1-149 d,#080808,
+|18: 0-0 d,#444444, 1-149 d,#080808,
+|19: 0-0 d,#444444, 1-149 d,#080808,
+|20: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-149 d,#080808,
+|21: 0-0 d,#444444, 1-149 d,#080808,
+|22: 0-0 d,#444444, 1-149 d,#080808,
+|23: 0-0 d,#444444, 1-149 d,#080808,
+|24: 0-0 d,#444444, 1-149 d,#080808,
+|25: 0-0 d,#444444, 1-149 d,#080808,
+|26: 0-0 d,#444444, 1-149 d,#080808,
+|27: 0-0 d,#444444, 1-149 d,#080808,
+|28: 0-0 d,#444444, 1-149 d,#080808,
+|29: 0-1 #ffffff,#262626, 2-129 #949494,#121212, 130-149 d,#121212,
+== snap search-prompt grid=150x30 cursor=6,13
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| 9d4🬫▚{▙v]O*🬥🬣n🬍🬕5S6#4🬵C[🬆🬻
+| {🬲🬍s🬕/*%!🬖🬹╱?🬷C🬔3q🬗]Q┼🬆🬹
+| }=^!t🬺R'My┼▐jP▞🬡y}▄V🬆~
+| 6(9?🬝🬳J1🬢k?g🬶🬙SY%t🬆▄█
+| ╲Ep^w🬪2zJbxF&🬷🬦a🬝~
+| 🬥K`🬙🬲$'#3x(▜🬌a▛🬹
+| zj🬡{U🬨(j🬗🬔E[▛🬹█
+| 🬺🬊*V*]g^🬳p▀🬹
+| [;🬬/M🬊🬲🬻🬆🬻
+| │🬕r🬜┼e🬆🬻
+| [🬝g4🬆🬹
+| 🬐🬹🬆🬹
+| /ZZ
+| img petscii:off palette:commodore ascii:on /tmp/pardes-snap/tagbottomimage/cwd/pic.ppm New Newtty Del
+| ls
+| pic.ppm
+|
+|
+|
+| pic.ppm
|
|
|
@@ -146,10 +121,35 @@
|
|
|
+| /tmp/pardes-snap/tagbottomimage/cwd New Newtty Del Filter
+== snap del-image grid=150x30 cursor=149,29
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| 9d4🬫▚{▙v]O*🬥🬣n🬍🬕5S6#4🬵C[🬆🬻
+| {🬲🬍s🬕/*%!🬖🬹╱?🬷C🬔3q🬗]Q┼🬆🬹
+| }=^!t🬺R'My┼▐jP▞🬡y}▄V🬆~
+| 6(9?🬝🬳J1🬢k?g🬶🬙SY%t🬆▄█
+| ╲Ep^w🬪2zJbxF&🬷🬦a🬝~
+| 🬥K`🬙🬲$'#3x(▜🬌a▛🬹
+| zj🬡{U🬨(j🬗🬔E[▛🬹█
+| 🬺🬊*V*]g^🬳p▀🬹
+| [;🬬/M🬊🬲🬻🬆🬻
+| │🬕r🬜┼e🬆🬻
+| [🬝g4🬆🬹
+| 🬐🬹🬆🬹
+| 🬎🬻█
+| img petscii:off palette:commodore ascii:on /tmp/pardes-snap/tagbottomimage/cwd/pic.ppm New Newtty Del
+| ls
+| pic.ppm
+|
+|
+|
+| pic.ppm
+|
+|
|
|
|
|
|
|
-| /tmp/pardes-snap/tagbottomimage/cwd New Del Filter
+| /tmp/pardes-snap/tagbottomimage/cwd New Newtty Del Filter
diff --git a/test/snapshots/tagbottomshort.golden b/test/snapshots/tagbottomshort.golden
index 599dd29b..303be3d8 100644
--- a/test/snapshots/tagbottomshort.golden
+++ b/test/snapshots/tagbottomshort.golden
@@ -1,5 +1,5 @@
== snap roomy grid=80x10 cursor=6,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 one
| 2 two
| 3 three
@@ -8,21 +8,21 @@
| 6 six
|
| /ZZ
-| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Del
+| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Newtty Del
== snap two-body grid=80x4 cursor=6,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 one
| /ZZ
-| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Del
+| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Newtty Del
== snap one-body grid=80x3 cursor=6,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| /ZZ
-| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Del
-== snap tag-only grid=80x2 cursor=64,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Del
+| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Newtty Del
+== snap tag-only grid=80x2 cursor=67,1
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Newtty Del
== snap regrown grid=80x10 cursor=6,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| 1 one
| 2 two
| 3 three
@@ -31,8 +31,8 @@
| 6 six
|
| /ZZ
-| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Del
+| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Newtty Del
== snap leader-one-body grid=80x3 cursor=7,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
| SPC
-| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Del
+| /tmp/pardes-snap/tagbottomshort/cwd/s.txt Save New Newtty Del
diff --git a/test/snapshots/tagcmd.golden b/test/snapshots/tagcmd.golden
index 2f0bf3b3..6879a051 100644
--- a/test/snapshots/tagcmd.golden
+++ b/test/snapshots/tagcmd.golden
@@ -1,6 +1,6 @@
== snap edited grid=100x30 cursor=13,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagcmd/cwd/c.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagcmd/cwd/c.txt * Save New Newtty Del
| 1 ZZEDITline 1
| 2 line 2
| 3 line 3
@@ -29,9 +29,9 @@
|
|
|
-== snap colon grid=100x30 cursor=68,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagcmd/cwd/c.txt * Save New Del
+== snap colon grid=100x30 cursor=61,1
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagcmd/cwd/c.txt * Save New Newtty Del
| 1 ZZEDITline 1
| 2 line 2
| 3 line 3
@@ -60,9 +60,9 @@
|
|
|
-== snap word grid=100x30 cursor=72,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagcmd/cwd/c.txt * Save New Del
+== snap word grid=100x30 cursor=65,1
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagcmd/cwd/c.txt * Save New Newtty Del
| 1 ZZEDITline 1
| 2 line 2
| 3 line 3
@@ -92,8 +92,8 @@
|
|
== snap saved grid=100x30 cursor=13,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagcmd/cwd/c.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagcmd/cwd/c.txt Save New Newtty Del
| 1 ZZEDITline 1
| 2 line 2
| 3 line 3
@@ -132,8 +132,8 @@ line 6
== end file
== snap escaped grid=100x30 cursor=13,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagcmd/cwd/c.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagcmd/cwd/c.txt Save New Newtty Del
| 1 ZZEDITline 1
| 2 line 2
| 3 line 3
diff --git a/test/snapshots/tagnav.golden b/test/snapshots/tagnav.golden
index 297844f7..523b5fe8 100644
--- a/test/snapshots/tagnav.golden
+++ b/test/snapshots/tagnav.golden
@@ -1,6 +1,6 @@
== snap start grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -30,8 +30,8 @@
|
|
== snap colon grid=100x30 cursor=36,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -61,8 +61,8 @@
|
|
== snap right-tag grid=100x30 cursor=80,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -92,8 +92,8 @@
|
|
== snap left-tag grid=100x30 cursor=36,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -108,7 +108,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -122,9 +122,9 @@
|
|
|
-== snap down-tag grid=100x30 cursor=34,16
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+== snap down-tag grid=100x30 cursor=30,16
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -139,7 +139,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -154,8 +154,8 @@
|
|
== snap up-tag grid=100x30 cursor=36,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -170,7 +170,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -185,8 +185,8 @@
|
|
== snap up-edge grid=100x30 cursor=0,0
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -201,7 +201,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -216,8 +216,8 @@
|
|
== snap topbar-word grid=100x30 cursor=3,0
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -232,7 +232,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -247,8 +247,8 @@
|
|
== snap topbar-graphemes grid=100x30 cursor=5,0
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -263,7 +263,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -278,8 +278,8 @@
|
|
== snap back-down grid=100x30 cursor=36,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -294,7 +294,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -309,8 +309,8 @@
|
|
== snap arrows-still-motion grid=100x30 cursor=38,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -325,7 +325,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -340,8 +340,8 @@
|
|
== snap back-to-body grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -356,7 +356,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -371,8 +371,8 @@
|
|
== snap tty-on grid=100x30 cursor=54,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del $ /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt$ /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha $ ls
| 2 beta w.txt
| 3 gamma $
@@ -387,7 +387,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -402,8 +402,8 @@
|
|
== snap tty-tag grid=100x30 cursor=80,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del $ /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt$ /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -418,7 +418,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -433,8 +433,8 @@
|
|
== snap tty-restored grid=100x30 cursor=54,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del $ /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt$ /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha $ ls
| 2 beta w.txt
| 3 gamma $
@@ -449,7 +449,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -463,9 +463,9 @@
|
|
|
-== snap topbar-dollar grid=100x30 cursor=56,0
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del $ /tmp/pardes-snap/tagnav/cwd New Del Filter
+== snap topbar-dollar grid=100x30 cursor=74,0
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt$ /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha $ ls
| 2 beta w.txt
| 3 gamma $
@@ -480,7 +480,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -494,9 +494,9 @@
|
|
|
-== snap topbar-dump-word grid=100x30 cursor=32,0
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del $ /tmp/pardes-snap/tagnav/cwd New Del Filter
+== snap topbar-dump-word grid=100x30 cursor=50,0
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt$ /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha $ ls
| 2 beta w.txt
| 3 gamma $
@@ -511,7 +511,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -526,8 +526,8 @@
|
|
== snap topbar-exec grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill Restore /tmp/pardes-snap/tagnav/dump.zon
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del $ /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill Restore /tmp/pardes-snap
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt$ /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha $ ls
| 2 beta w.txt
| 3 gamma $
@@ -542,7 +542,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -556,9 +556,9 @@
|
|
|
-== snap topbar-restore-word grid=100x30 cursor=58,0
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill Restore /tmp/pardes-snap/tagnav/dump.zon
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del $ /tmp/pardes-snap/tagnav/cwd New Del Filter
+== snap topbar-restore-word grid=100x30 cursor=76,0
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill Restore /tmp/pardes-snap
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt$ /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha $ ls
| 2 beta w.txt
| 3 gamma $
@@ -573,7 +573,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
@@ -588,8 +588,8 @@
|
|
== snap topbar-restored grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Del /tmp/pardes-snap/tagnav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagnav/cwd/w.txt Save New Newtt /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -604,7 +604,7 @@
|
|
|
-| /tmp/pardes-snap/tagnav/cwd New Del Filter
+| /tmp/pardes-snap/tagnav/cwd New Newtty Del Filte
| ls
| w.txt
|
diff --git a/test/snapshots/tagnav.snap b/test/snapshots/tagnav.snap
index 305f5512..da3cdd79 100644
--- a/test/snapshots/tagnav.snap
+++ b/test/snapshots/tagnav.snap
@@ -17,9 +17,11 @@ wait 8000 New Newcol
wait 8000 w.txt
stable 700 20000
# A FILE boots alone now, so the shell this script calls "the launch shell" is
-# opened here: SPC c n (Newcol) puts it in a column of its own on the right and
-# focuses it, SPC w h comes back to the file.
-key space c n
+# opened here: Alt-n opens it and focuses it, Alt-c puts it in a column of its
+# own on the right, SPC w h comes back to the file. (`New`/`Newcol` open an
+# empty +New scratch now, not a shell.)
+key a-n
+key a-c
stable 700 15000
key space w h
stable 400 5000
diff --git a/test/snapshots/tagpath.golden b/test/snapshots/tagpath.golden
index 8c8b16a9..22322b5d 100644
--- a/test/snapshots/tagpath.golden
+++ b/test/snapshots/tagpath.golden
@@ -1,6 +1,6 @@
== snap start grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagpath/cwd/c.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagpath/cwd/c.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -29,9 +29,9 @@
|
|
|
-== snap colon grid=100x30 cursor=68,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagpath/cwd/c.txt Save New Del
+== snap colon grid=100x30 cursor=61,1
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagpath/cwd/c.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -61,8 +61,8 @@
|
|
== snap col0 grid=100x30 cursor=2,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagpath/cwd/c.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagpath/cwd/c.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -92,8 +92,8 @@
|
|
== snap sel-path grid=100x30 cursor=35,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagpath/cwd/c.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagpath/cwd/c.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -123,7 +123,7 @@
|
|
== style sel-path
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
|1: 0-1 #ffffff,#626262, 2-35 #080808,#80a0ff, 36-79 #949494,#121212, 80-99 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808,
@@ -154,8 +154,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808,
|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808,
== snap yanked-path grid=100x30 cursor=41,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagpath/cwd/c.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagpath/cwd/c.txt * Save New Newtty Del
| 1 l/tmp/pardes-snap/tagpath/cwd/c.txtine 1
| 2 line 2
| 3 line 3
@@ -185,8 +185,8 @@
|
|
== snap drag-cross grid=100x30 cursor=41,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagpath/cwd/c.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagpath/cwd/c.txt * Save New Newtty Del
| 1 l/tmp/pardes-snap/tagpath/cwd/c.txtine 1
| 2 line 2
| 3 line 3
@@ -216,7 +216,7 @@
|
|
== style drag-cross
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
|1: 0-1 #ffffff,#626262, 2-10 #949494,#121212, 11-41 #080808,#80a0ff, 42-81 #949494,#121212, 82-99 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-46 #bdbdbd,#080808, 47-99 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808,
@@ -247,8 +247,8 @@
|28: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808,
|29: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-99 d,#080808,
== snap path-inert grid=100x30 cursor=11,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tagpath/cwd/c.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tagpath/cwd/c.txt * Save New Newtty Del
| 1 l/tmp/pardes-snap/tagpath/cwd/c.txtine 1
| 2 line 2
| 3 line 3
diff --git a/test/snapshots/theme.golden b/test/snapshots/theme.golden
index 6d85502d..dba24fa3 100644
--- a/test/snapshots/theme.golden
+++ b/test/snapshots/theme.golden
@@ -1,6 +1,6 @@
== snap helix grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/theme/cwd New Del Filter /tmp/pardes-snap/theme/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/theme/cwd New Newtty Del Filter /tmp/pardes-snap/theme/cwd New Newtty Del Filter
| ls ls
| t.txt t.txt
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/theme/cwd New Del Filter
+| /tmp/pardes-snap/theme/cwd New Newtty Del Filter
| ls
| t.txt
|
@@ -30,39 +30,39 @@
|
|
== style helix
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-42 #949494,#121212, 43-49 d,#121212, 50-51 #ffffff,#262626, 52-92 #949494,#121212, 93-99 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|16: 0-1 #ffffff,#262626, 2-42 #949494,#121212, 43-49 d,#121212, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-49 #bdbdbd,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-99 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-49 #949494,#121212, 50-51 #ffffff,#262626, 52-99 #949494,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-53 #bdbdbd,#080808, 54-99 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-51 d,#080808, 52-56 #bdbdbd,#080808, 57-99 d,#080808,
+|4: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|5: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|6: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|7: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|8: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|9: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|10: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|11: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|12: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|13: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|14: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|15: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-49 #949494,#121212, 50-50 d,#444444, 51-99 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|19: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|20: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|21: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|22: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|23: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|24: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|25: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|26: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|27: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|28: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
+|29: 0-0 d,#444444, 1-49 d,#080808, 50-50 d,#444444, 51-99 d,#080808,
== snap dark grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/theme/cwd New Del Filter /tmp/pardes-snap/theme/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/theme/cwd New Newtty Del Filter /tmp/pardes-snap/theme/cwd New Newtty Del Filter
| ls ls
| t.txt t.txt
|
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/theme/cwd New Del Filter
+| /tmp/pardes-snap/theme/cwd New Newtty Del Filter
| ls
| t.txt
|
@@ -92,39 +92,39 @@
|
|
== style dark
-|0: 0-36 #969696,#2c2a3e, 37-45 #d8c8a8,#4a3a1e, 46-56 #969696,#2c2a3e, 57-99 d,#2c2a3e,
-|1: 0-1 #ffffff,#6e4fd0, 2-42 #969696,#2c2a3e, 43-49 d,#2c2a3e, 50-51 #ffffff,#383c54, 52-92 #969696,#2c2a3e, 93-99 d,#2c2a3e,
-|2: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|3: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|4: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|5: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|6: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|7: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|8: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|9: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|10: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|11: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|12: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|13: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|14: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|15: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|16: 0-1 #ffffff,#383c54, 2-42 #969696,#2c2a3e, 43-49 d,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|17: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|18: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|19: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|20: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|21: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|22: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|23: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|24: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|25: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|26: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|27: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|28: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
-|29: 0-0 d,#525252, 1-1 d,d, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-51 d,d, 52-99 #969696,#2c2a3e,
+|0: 0-54 #969696,#2c2a3e, 55-63 #d8c8a8,#4a3a1e, 64-74 #969696,#2c2a3e, 75-99 d,#2c2a3e,
+|1: 0-1 #ffffff,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 #ffffff,#383c54, 52-99 #969696,#2c2a3e,
+|2: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|3: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|4: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|5: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|6: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|7: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|8: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|9: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|10: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|11: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|12: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|13: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|14: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|15: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|16: 0-1 #ffffff,#383c54, 2-49 #969696,#2c2a3e, 50-50 d,#525252, 51-99 d,d,
+|17: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|18: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|19: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|20: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|21: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|22: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|23: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|24: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|25: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|26: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|27: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|28: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
+|29: 0-0 d,#525252, 1-49 d,d, 50-50 d,#525252, 51-99 d,d,
== snap acme grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/theme/cwd New Del Filter /tmp/pardes-snap/theme/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/theme/cwd New Newtty Del Filter /tmp/pardes-snap/theme/cwd New Newtty Del Filter
| ls ls
| t.txt t.txt
|
@@ -139,7 +139,7 @@
|
|
|
-| /tmp/pardes-snap/theme/cwd New Del Filter
+| /tmp/pardes-snap/theme/cwd New Newtty Del Filter
| ls
| t.txt
|
@@ -154,39 +154,39 @@
|
|
== style acme
-|0: 0-36 #000000,#eaffff, 37-45 #000000,#eeee9e, 46-56 #000000,#eaffff, 57-99 d,#eaffff,
-|1: 0-1 #ffffff,#6e4fd0, 2-42 #000000,#eaffff, 43-49 d,#eaffff, 50-51 #ffffff,#383c54, 52-92 #000000,#eaffff, 93-99 d,#eaffff,
-|2: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|3: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|4: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|5: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|6: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|7: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|8: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|9: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|10: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|11: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|12: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|13: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|14: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|15: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|16: 0-1 #ffffff,#383c54, 2-42 #000000,#eaffff, 43-49 d,#eaffff, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|17: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|18: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|19: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|20: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|21: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|22: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|23: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|24: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|25: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|26: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|27: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|28: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
-|29: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea,
+|0: 0-54 #000000,#eaffff, 55-63 #000000,#eeee9e, 64-74 #000000,#eaffff, 75-99 d,#eaffff,
+|1: 0-1 #ffffff,#6e4fd0, 2-49 #000000,#eaffff, 50-51 #ffffff,#383c54, 52-99 #000000,#eaffff,
+|2: 0-1 d,#ffffea, 2-3 #000000,#ffffea, 4-51 d,#ffffea, 52-53 #000000,#ffffea, 54-99 d,#ffffea,
+|3: 0-1 d,#ffffea, 2-6 #000000,#ffffea, 7-51 d,#ffffea, 52-56 #000000,#ffffea, 57-99 d,#ffffea,
+|4: 0-99 d,#ffffea,
+|5: 0-99 d,#ffffea,
+|6: 0-99 d,#ffffea,
+|7: 0-99 d,#ffffea,
+|8: 0-99 d,#ffffea,
+|9: 0-99 d,#ffffea,
+|10: 0-99 d,#ffffea,
+|11: 0-99 d,#ffffea,
+|12: 0-99 d,#ffffea,
+|13: 0-99 d,#ffffea,
+|14: 0-99 d,#ffffea,
+|15: 0-99 d,#ffffea,
+|16: 0-1 #ffffff,#383c54, 2-49 #000000,#eaffff, 50-99 d,#ffffea,
+|17: 0-1 d,#ffffea, 2-3 #000000,#ffffea, 4-99 d,#ffffea,
+|18: 0-1 d,#ffffea, 2-6 #000000,#ffffea, 7-99 d,#ffffea,
+|19: 0-99 d,#ffffea,
+|20: 0-99 d,#ffffea,
+|21: 0-99 d,#ffffea,
+|22: 0-99 d,#ffffea,
+|23: 0-99 d,#ffffea,
+|24: 0-99 d,#ffffea,
+|25: 0-99 d,#ffffea,
+|26: 0-99 d,#ffffea,
+|27: 0-99 d,#ffffea,
+|28: 0-99 d,#ffffea,
+|29: 0-99 d,#ffffea,
== snap colors-off grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/theme/cwd New Del Filter /tmp/pardes-snap/theme/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/theme/cwd New Newtty Del Filter /tmp/pardes-snap/theme/cwd New Newtty Del Filter
| ls ls
| t.txt t.txt
|
@@ -201,7 +201,7 @@
|
|
|
-| /tmp/pardes-snap/theme/cwd New Del Filter
+| /tmp/pardes-snap/theme/cwd New Newtty Del Filter
| ls
| t.txt
|
@@ -216,8 +216,8 @@
|
|
== style colors-off
-|0: 0-36 #000000,#eaffff, 37-45 #000000,#eeee9e, 46-56 #000000,#eaffff, 57-99 d,#eaffff,
-|1: 0-1 #ffffff,#6e4fd0, 2-42 #000000,#eaffff, 43-49 d,#eaffff, 50-51 #ffffff,#383c54, 52-92 #000000,#eaffff, 93-99 d,#eaffff,
+|0: 0-54 #000000,#eaffff, 55-63 #000000,#eeee9e, 64-74 #000000,#eaffff, 75-99 d,#eaffff,
+|1: 0-1 #ffffff,#6e4fd0, 2-49 #000000,#eaffff, 50-51 #ffffff,#383c54, 52-99 #000000,#eaffff,
|2: 0-1 d,#ffffea, 2-3 #000000,#ffffea, 4-51 d,#ffffea, 52-53 #000000,#ffffea, 54-99 d,#ffffea,
|3: 0-1 d,#ffffea, 2-6 #000000,#ffffea, 7-51 d,#ffffea, 52-56 #000000,#ffffea, 57-99 d,#ffffea,
|4: 0-99 d,#ffffea,
@@ -232,7 +232,7 @@
|13: 0-99 d,#ffffea,
|14: 0-99 d,#ffffea,
|15: 0-99 d,#ffffea,
-|16: 0-1 #ffffff,#383c54, 2-42 #000000,#eaffff, 43-49 d,#eaffff, 50-99 d,#ffffea,
+|16: 0-1 #ffffff,#383c54, 2-49 #000000,#eaffff, 50-99 d,#ffffea,
|17: 0-1 d,#ffffea, 2-3 #000000,#ffffea, 4-99 d,#ffffea,
|18: 0-1 d,#ffffea, 2-6 #000000,#ffffea, 7-99 d,#ffffea,
|19: 0-99 d,#ffffea,
@@ -247,8 +247,8 @@
|28: 0-99 d,#ffffea,
|29: 0-99 d,#ffffea,
== snap generated grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/theme/cwd New Del Filter /tmp/pardes-snap/theme/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/theme/cwd New Newtty Del Filter /tmp/pardes-snap/theme/cwd New Newtty Del Filter
| ls ls
| t.txt t.txt
|
@@ -263,7 +263,7 @@
|
|
|
-| /tmp/pardes-snap/theme/cwd New Del Filter
+| /tmp/pardes-snap/theme/cwd New Newtty Del Filter
| ls
| t.txt
|
@@ -278,33 +278,33 @@
|
|
== style generated
-|0: 0-36 #e0e0e0,#1e262e, 37-45 #e0e0e0,#303840, 46-56 #e0e0e0,#1e262e, 57-99 d,#1e262e,
-|1: 0-1 #000000,#ffa060, 2-42 #e0e0e0,#1e262e, 43-49 d,#1e262e, 50-51 #ffffff,#303840, 52-92 #e0e0e0,#1e262e, 93-99 d,#1e262e,
-|2: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|3: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|4: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|5: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|6: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|7: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|8: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|9: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|10: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|11: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|12: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|13: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|14: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|15: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|16: 0-1 #ffffff,#303840, 2-42 #e0e0e0,#1e262e, 43-49 d,#1e262e, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|17: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|18: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|19: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|20: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|21: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|22: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|23: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|24: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|25: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|26: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|27: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|28: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
-|29: 0-0 d,#303840, 1-1 d,#161e26, 2-49 #e0e0e0,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-99 #e0e0e0,#161e26,
+|0: 0-54 #e0e0e0,#1e262e, 55-63 #e0e0e0,#303840, 64-74 #e0e0e0,#1e262e, 75-99 d,#1e262e,
+|1: 0-1 #000000,#ffa060, 2-49 #e0e0e0,#1e262e, 50-51 #ffffff,#303840, 52-99 #e0e0e0,#1e262e,
+|2: 0-0 d,#303840, 1-1 d,#161e26, 2-3 #e0e0e0,#161e26, 4-49 d,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-53 #e0e0e0,#161e26, 54-99 d,#161e26,
+|3: 0-0 d,#303840, 1-1 d,#161e26, 2-6 #e0e0e0,#161e26, 7-49 d,#161e26, 50-50 d,#303840, 51-51 d,#161e26, 52-56 #e0e0e0,#161e26, 57-99 d,#161e26,
+|4: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|5: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|6: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|7: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|8: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|9: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|10: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|11: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|12: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|13: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|14: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|15: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|16: 0-1 #ffffff,#303840, 2-49 #e0e0e0,#1e262e, 50-50 d,#303840, 51-99 d,#161e26,
+|17: 0-0 d,#303840, 1-1 d,#161e26, 2-3 #e0e0e0,#161e26, 4-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|18: 0-0 d,#303840, 1-1 d,#161e26, 2-6 #e0e0e0,#161e26, 7-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|19: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|20: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|21: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|22: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|23: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|24: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|25: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|26: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|27: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|28: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
+|29: 0-0 d,#303840, 1-49 d,#161e26, 50-50 d,#303840, 51-99 d,#161e26,
diff --git a/test/snapshots/theme.snap b/test/snapshots/theme.snap
index 6fb4466f..3e1715f3 100644
--- a/test/snapshots/theme.snap
+++ b/test/snapshots/theme.snap
@@ -19,13 +19,13 @@ wait 8000 t.txt
stable 700 20000
snap helix
snapstyle helix
-press middle 38 1
-release middle 38 1
+press middle 57 1
+release middle 57 1
stable 700 10000
snap dark
snapstyle dark
-press middle 38 1
-release middle 38 1
+press middle 57 1
+release middle 57 1
stable 700 10000
snap acme
snapstyle acme
@@ -39,8 +39,8 @@ key space
key t
key c
stable 700 10000
-press middle 38 1
-release middle 38 1
+press middle 57 1
+release middle 57 1
stable 700 10000
snap generated
snapstyle generated
diff --git a/test/snapshots/themesel.golden b/test/snapshots/themesel.golden
index 7303ea55..ac9e0262 100644
--- a/test/snapshots/themesel.golden
+++ b/test/snapshots/themesel.golden
@@ -1,6 +1,6 @@
== snap boot grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/themesel/cwd/t.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/themesel/cwd/t.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -30,8 +30,8 @@
| 27 line 27
| 28 line 28
== snap list grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/themesel/cwd/t.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/themesel/cwd/t.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -46,7 +46,7 @@
| 12 line 12
| 13 line 13
| 14 line 14
-| /tmp/pardes-snap/themesel/cwd/+Themes New Del
+| /tmp/pardes-snap/themesel/cwd/+Themes New Newtty Del
| 1 Theme helix
| 2 Theme dark
| 3 Theme acme
@@ -61,8 +61,8 @@
| 12 Theme ao
| 13 Theme ashen
== snap step-helix grid=100x30 cursor=7,17
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/themesel/cwd/t.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/themesel/cwd/t.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -77,7 +77,7 @@
| 12 line 12
| 13 line 13
| 14 line 14
-| /tmp/pardes-snap/themesel/cwd/+Themes New Del
+| /tmp/pardes-snap/themesel/cwd/+Themes New Newtty Del
| 1 Theme helix
| 2 Theme dark
| 3 Theme acme
@@ -92,7 +92,7 @@
| 12 Theme ao
| 13 Theme ashen
== style step-helix
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
|1: 0-1 #ffffff,#262626, 2-79 #949494,#121212, 80-99 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-6 #626262,#080808, 7-12 #bdbdbd,#080808, 13-99 d,#080808,
@@ -123,8 +123,8 @@
|28: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-14 #bdbdbd,#080808, 15-99 d,#080808,
|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-99 d,#080808,
== snap step-dark grid=100x30 cursor=7,18
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/themesel/cwd/t.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/themesel/cwd/t.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -139,7 +139,7 @@
| 12 line 12
| 13 line 13
| 14 line 14
-| /tmp/pardes-snap/themesel/cwd/+Themes New Del
+| /tmp/pardes-snap/themesel/cwd/+Themes New Newtty Del
| 1 Theme helix
| 2 Theme dark
| 3 Theme acme
@@ -154,7 +154,7 @@
| 12 Theme ao
| 13 Theme ashen
== style step-dark
-|0: 0-56 #969696,#2c2a3e, 57-99 d,#2c2a3e,
+|0: 0-74 #969696,#2c2a3e, 75-99 d,#2c2a3e,
|1: 0-1 #ffffff,#383c54, 2-79 #969696,#2c2a3e, 80-99 d,#2c2a3e,
|2: 0-0 d,#525252, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d,
|3: 0-0 d,#525252, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d,
@@ -185,8 +185,8 @@
|28: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d,
|29: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-99 d,d,
== snap step-acme grid=100x30 cursor=7,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/themesel/cwd/t.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/themesel/cwd/t.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -201,7 +201,7 @@
| 12 line 12
| 13 line 13
| 14 line 14
-| /tmp/pardes-snap/themesel/cwd/+Themes New Del
+| /tmp/pardes-snap/themesel/cwd/+Themes New Newtty Del
| 1 Theme helix
| 2 Theme dark
| 3 Theme acme
@@ -216,7 +216,7 @@
| 12 Theme ao
| 13 Theme ashen
== style step-acme
-|0: 0-56 #000000,#eaffff, 57-99 d,#eaffff,
+|0: 0-74 #000000,#eaffff, 75-99 d,#eaffff,
|1: 0-1 #ffffff,#383c54, 2-79 #000000,#eaffff, 80-99 d,#eaffff,
|2: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea,
|3: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea,
@@ -247,8 +247,8 @@
|28: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-14 #000000,#ffffea, 15-99 d,#ffffea,
|29: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-17 #000000,#ffffea, 18-99 d,#ffffea,
== snap step-generated grid=100x30 cursor=7,20
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/themesel/cwd/t.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/themesel/cwd/t.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -263,7 +263,7 @@
| 12 line 12
| 13 line 13
| 14 line 14
-| /tmp/pardes-snap/themesel/cwd/+Themes New Del
+| /tmp/pardes-snap/themesel/cwd/+Themes New Newtty Del
| 1 Theme helix
| 2 Theme dark
| 3 Theme acme
@@ -278,7 +278,7 @@
| 12 Theme ao
| 13 Theme ashen
== style step-generated
-|0: 0-56 #e0e0e0,#1e262e, 57-99 d,#1e262e,
+|0: 0-74 #e0e0e0,#1e262e, 75-99 d,#1e262e,
|1: 0-1 #ffffff,#303840, 2-79 #e0e0e0,#1e262e, 80-99 d,#1e262e,
|2: 0-0 d,#303840, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-12 #e0e0e0,#161e26, 13-99 d,#161e26,
|3: 0-0 d,#303840, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-12 #e0e0e0,#161e26, 13-99 d,#161e26,
@@ -309,8 +309,8 @@
|28: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-14 #e0e0e0,#161e26, 15-99 d,#161e26,
|29: 0-0 d,#1e262e, 1-1 d,#161e26, 2-6 #303840,#161e26, 7-17 #e0e0e0,#161e26, 18-99 d,#161e26,
== snap step-back grid=100x30 cursor=7,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/themesel/cwd/t.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/themesel/cwd/t.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -325,7 +325,7 @@
| 12 line 12
| 13 line 13
| 14 line 14
-| /tmp/pardes-snap/themesel/cwd/+Themes New Del
+| /tmp/pardes-snap/themesel/cwd/+Themes New Newtty Del
| 1 Theme helix
| 2 Theme dark
| 3 Theme acme
@@ -340,7 +340,7 @@
| 12 Theme ao
| 13 Theme ashen
== style step-back
-|0: 0-56 #000000,#eaffff, 57-99 d,#eaffff,
+|0: 0-74 #000000,#eaffff, 75-99 d,#eaffff,
|1: 0-1 #ffffff,#383c54, 2-79 #000000,#eaffff, 80-99 d,#eaffff,
|2: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea,
|3: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea,
@@ -371,8 +371,8 @@
|28: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-14 #000000,#ffffea, 15-99 d,#ffffea,
|29: 0-0 d,#99994c, 1-1 d,#ffffea, 2-6 #999980,#ffffea, 7-17 #000000,#ffffea, 18-99 d,#ffffea,
== snap tail grid=100x30 cursor=7,28
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/themesel/cwd/t.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/themesel/cwd/t.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -387,7 +387,7 @@
| 12 line 12
| 13 line 13
| 14 line 14
-| /tmp/pardes-snap/themesel/cwd/+Themes New Del
+| /tmp/pardes-snap/themesel/cwd/+Themes New Newtty Del
| 217 Theme wolf_alabaster_dark_bg
| 218 Theme wolf_alabaster_dark_mono
| 219 Theme wolf_alabaster_light
@@ -402,8 +402,8 @@
| 228 Theme zenburn
| 229
== snap picked grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/themesel/cwd/t.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/themesel/cwd/t.txt Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -433,7 +433,7 @@
| 27 line 27
| 28 line 28
== style picked
-|0: 0-56 #000000,#eaffff, 57-99 d,#eaffff,
+|0: 0-74 #000000,#eaffff, 75-99 d,#eaffff,
|1: 0-1 #ffffff,#6e4fd0, 2-79 #000000,#eaffff, 80-99 d,#eaffff,
|2: 0-1 d,#ffffea, 2-6 #000000,#eaffff, 7-12 #000000,#ffffea, 13-99 d,#ffffea,
|3: 0-1 d,#ffffea, 2-6 #999980,#ffffea, 7-12 #000000,#ffffea, 13-99 d,#ffffea,
diff --git a/test/snapshots/tinywin.golden b/test/snapshots/tinywin.golden
index 3e299115..f613fd9f 100644
--- a/test/snapshots/tinywin.golden
+++ b/test/snapshots/tinywin.golden
@@ -1,17 +1,17 @@
== snap stacked grid=100x30 cursor=4,14
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/tinywin/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/tinywin/cwd New Newtty Del Filter
| $
-| /tmp/pardes-snap/tinywin/cwd New Del Filter
+| /tmp/pardes-snap/tinywin/cwd New Newtty Del Filter
| ls
|
-| /tmp/pardes-snap/tinywin/cwd New Del Filter
+| /tmp/pardes-snap/tinywin/cwd New Newtty Del Filter
| ls
|
-| /tmp/pardes-snap/tinywin/cwd New Del Filter
+| /tmp/pardes-snap/tinywin/cwd New Newtty Del Filter
| ls
|
-| /tmp/pardes-snap/tinywin/cwd New Del Filter
+| /tmp/pardes-snap/tinywin/cwd New Newtty Del Filter
| ls
|
|
@@ -30,23 +30,23 @@
|
|
== snap shrunk grid=60x3 cursor=59,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/tinywin/cwd New Del Filter
-| /tmp/pardes-snap/tinywin/cwd New Del Filter
-== snap columns grid=100x30 cursor=92,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/tinywin/cwd New Del Filter /tmp/pardes-snap/tinywi /tmp/pardes /tmp/parde
-| $ ls ls ls
-| /tmp/pardes-snap/tinywin/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextC
+|$ /tmp/pardes-snap/tinywin/cwd New Newtty Del Filter
+| /tmp/pardes-snap/tinywin/cwd New Newtty Del Filter
+== snap columns grid=100x30 cursor=95,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/tinywin/cwd New Newtty Del Filt /tmp/pardes-snap/tinywi /tmp/pardes /tmp/parde
+| $ 1 1 1
+| /tmp/pardes-snap/tinywin/cwd New Newtty Del Filt
| ls
|
-| /tmp/pardes-snap/tinywin/cwd New Del Filter
+| /tmp/pardes-snap/tinywin/cwd New Newtty Del Filt
| ls
|
-| /tmp/pardes-snap/tinywin/cwd New Del Filter
+| /tmp/pardes-snap/tinywin/cwd New Newtty Del Filt
| ls
|
-| /tmp/pardes-snap/tinywin/cwd New Del Filter
+| /tmp/pardes-snap/tinywin/cwd New Newtty Del Filt
| ls
|
|
diff --git a/test/snapshots/topbarexec.golden b/test/snapshots/topbarexec.golden
index 27e79253..7b0bb96f 100644
--- a/test/snapshots/topbarexec.golden
+++ b/test/snapshots/topbarexec.golden
@@ -1,6 +1,6 @@
== snap selected grid=90x20 cursor=14,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/topbarexec/cwd New Del Fil /tmp/pardes-snap/topbarexec/cwd New Del Fil
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/topbarexec/cwd New Newtty /tmp/pardes-snap/topbarexec/cwd New Newtty
| ls ls
| zmarkfile.txt zmarkfile.txt
|
@@ -10,7 +10,7 @@
|
|
|
-| /tmp/pardes-snap/topbarexec/cwd New Del Fil
+| /tmp/pardes-snap/topbarexec/cwd New Newtty
| ls
| zmarkfile.txt
|
@@ -20,8 +20,8 @@
|
|
== snap noarg-runs grid=90x20 cursor=14,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/topbarexec/cwd New Del Fil /tmp/╭────────────────────────────────────╮
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/topbarexec/cwd New Newtty /tmp/╭────────────────────────────────────╮
| ls ls │pardes resizes=1 │
| zmarkfile.txt zmark│theme helix │
| │font default │
@@ -31,7 +31,7 @@
| │pinch 1.0000 │
| │tscroll 0.0000 │
| ╰────────────────────────────────────╯
-| /tmp/pardes-snap/topbarexec/cwd New Del Fil
+| /tmp/pardes-snap/topbarexec/cwd New Newtty
| ls
| zmarkfile.txt
|
@@ -41,8 +41,8 @@
|
|
== snap arg-still-spliced grid=90x20 cursor=14,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/topbarexec/cwd New Del Fil /tmp/pardes-snap/topbarexec/cwd New Del Fil
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/topbarexec/cwd New Newtty /tmp/pardes-snap/topbarexec/cwd New Newtty
| ls ls
| zmarkfile.txt zmarkfile.txt
|
@@ -52,7 +52,7 @@
|
| /tmp/pardes-snap/topbarexec/cwd/+Search New
| 1 zmarkfile.txt
-| /tmp/pardes-snap/topbarexec/cwd New Del Fil
+| /tmp/pardes-snap/topbarexec/cwd New Newtty
| ls
| zmarkfile.txt
|
diff --git a/test/snapshots/topbarexec.snap b/test/snapshots/topbarexec.snap
index bebaed3f..c73bf4d7 100644
--- a/test/snapshots/topbarexec.snap
+++ b/test/snapshots/topbarexec.snap
@@ -26,20 +26,20 @@ stable 700 15000
snap selected
# Debug takes NO argument. Middle-clicked with that sweep live it must open the
# overlay — not send `Debug zmarkfile.txt` to bash. The box IS the assertion.
-press middle 50 1
-release middle 50 1
+press middle 67 1
+release middle 67 1
stable 700 15000
snap noarg-runs
# ...and off again, so the overlay does not cover what comes next
-press middle 50 1
-release middle 50 1
+press middle 67 1
+release middle 67 1
stable 700 15000
# Find DOES take one, and still gets it: the sweep is the pattern, so the
# results buffer names the file it matched. An empty buffer would mean Find
# ran with no argument (which arms the prompt instead), so the ROW is the
# assertion — the splice is what put it there.
-press middle 13 1
-release middle 13 1
+press middle 21 1
+release middle 21 1
wait 10000 +Search
stable 700 15000
snap arg-still-spliced
diff --git a/test/snapshots/tty.golden b/test/snapshots/tty.golden
index 5d6ebf75..8c553d33 100644
--- a/test/snapshots/tty.golden
+++ b/test/snapshots/tty.golden
@@ -1,6 +1,6 @@
== snap tty-on grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/tty/cwd New Del Filter /tmp/pardes-snap/tty/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/tty/cwd New Newtty Del Filter /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| $ ls ls
| m.txt m.txt
| $
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/tty/cwd New Del Filter
+| /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| ls
| m.txt
|
@@ -30,8 +30,8 @@
|
|
== snap tty-echo grid=100x30 cursor=4,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/tty/cwd New Del Filter /tmp/pardes-snap/tty/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/tty/cwd New Newtty Del Filter /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| $ ls ls
| m.txt m.txt
| $ echo SNAP''OK
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/tty/cwd New Del Filter
+| /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| ls
| m.txt
|
@@ -61,8 +61,8 @@
|
|
== snap tty-off grid=100x30 cursor=4,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tty/cwd New Del Filter /tmp/pardes-snap/tty/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tty/cwd New Newtty Del Filter /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| ls ls
| m.txt m.txt
| echo SNAP''OK
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/tty/cwd New Del Filter
+| /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| ls
| m.txt
|
@@ -92,8 +92,8 @@
|
|
== snap shift-esc-on grid=100x30 cursor=4,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/tty/cwd New Del Filter /tmp/pardes-snap/tty/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/tty/cwd New Newtty Del Filter /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| $ ls ls
| m.txt m.txt
| $ echo SNAP''OK
@@ -108,7 +108,7 @@
|
|
|
-| /tmp/pardes-snap/tty/cwd New Del Filter
+| /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| ls
| m.txt
|
@@ -123,8 +123,8 @@
|
|
== snap shift-esc-nodoc grid=100x30 cursor=4,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/tty/cwd New Del Filter /tmp/pardes-snap/tty/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/tty/cwd New Newtty Del Filter /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| $ ls ls
| m.txt m.txt
| $ echo SNAP''OK
@@ -139,7 +139,7 @@
|
|
|
-| /tmp/pardes-snap/tty/cwd New Del Filter
+| /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| ls
| m.txt
|
@@ -154,8 +154,8 @@
|
|
== snap ctrl-b-off grid=100x30 cursor=4,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/tty/cwd New Del Filter /tmp/pardes-snap/tty/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tty/cwd New Newtty Del Filter /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| ls ls
| m.txt m.txt
| echo SNAP''OK
@@ -170,7 +170,7 @@
|
|
|
-| /tmp/pardes-snap/tty/cwd New Del Filter
+| /tmp/pardes-snap/tty/cwd New Newtty Del Filter
| ls
| m.txt
|
diff --git a/test/snapshots/ttyclick.golden b/test/snapshots/ttyclick.golden
index 5d791fce..72a59e67 100644
--- a/test/snapshots/ttyclick.golden
+++ b/test/snapshots/ttyclick.golden
@@ -1,6 +1,6 @@
== snap tty-bodyclick grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/ttyclick/cwd New Del Filter /tmp/pardes-snap/ttyclick/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil
| $ ls ls
| probe.txt probe.txt
| $
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/ttyclick/cwd New Del Filter
+| /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil
| ls
| probe.txt
|
@@ -30,8 +30,8 @@
|
|
== snap tty-tagedit grid=100x30 cursor=39,1
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/ttyclick/cwd New Del Filter /tmp/pardes-snap/ttyclick/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil
| ls ls
| probe.txt probe.txt
|
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/ttyclick/cwd New Del Filter
+| /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil
| ls
| probe.txt
|
@@ -61,8 +61,8 @@
|
|
== snap tty-tagexit grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/ttyclick/cwd New Del Filter /tmp/pardes-snap/ttyclick/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil
| $ ls ls
| probe.txt probe.txt
| $
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/ttyclick/cwd New Del Filter
+| /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil
| ls
| probe.txt
|
@@ -92,8 +92,8 @@
|
|
== snap ins-bodyclick grid=100x30 cursor=11,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/ttyclick/cwd New Del Filter /tmp/pardes-snap/ttyclick/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil
| ls ls
| probe.txt probe.txt
|
@@ -108,7 +108,7 @@
|
|
|
-| /tmp/pardes-snap/ttyclick/cwd New Del Filter
+| /tmp/pardes-snap/ttyclick/cwd New Newtty Del Fil
| ls
| probe.txt
|
diff --git a/test/snapshots/ttyedit.golden b/test/snapshots/ttyedit.golden
index bdcfce1b..a40d5ec3 100644
--- a/test/snapshots/ttyedit.golden
+++ b/test/snapshots/ttyedit.golden
@@ -1,6 +1,6 @@
== snap before grid=100x30 cursor=7,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttyedit/cwd New Del Filter /tmp/pardes-snap/ttyedit/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/ttyedit/cwd New Del Filter
+| /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt
| ls
| words.txt
|
@@ -30,8 +30,8 @@
|
|
== snap split grid=100x30 cursor=2,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|^ /tmp/pardes-snap/ttyedit/cwd New Del Filter /tmp/pardes-snap/ttyedit/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|^ /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/ttyedit/cwd New Del Filter
+| /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt
| ls
| words.txt
|
@@ -61,8 +61,8 @@
|
|
== snap opened grid=100x30 cursor=6,8
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttyedit/cwd New Del Filter /tmp/pardes-snap/ttyedit/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/ttyedit/cwd New Del Filter
+| /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt
| ls
| words.txt
|
@@ -92,8 +92,8 @@
|
|
== snap joined grid=100x30 cursor=10,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttyedit/cwd New Del Filter /tmp/pardes-snap/ttyedit/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -108,7 +108,7 @@
|
|
|
-| /tmp/pardes-snap/ttyedit/cwd New Del Filter
+| /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt
| ls
| words.txt
|
@@ -123,8 +123,8 @@
|
|
== snap undone grid=100x30 cursor=7,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttyedit/cwd New Del Filter /tmp/pardes-snap/ttyedit/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt
| ls ls
| words.txt words.txt
| printf 'one two three\nfour five six\nseven ei
@@ -139,7 +139,7 @@
|
|
|
-| /tmp/pardes-snap/ttyedit/cwd New Del Filter
+| /tmp/pardes-snap/ttyedit/cwd New Newtty Del Filt
| ls
| words.txt
|
diff --git a/test/snapshots/ttyfollow.golden b/test/snapshots/ttyfollow.golden
index 720c4eac..33395d83 100644
--- a/test/snapshots/ttyfollow.golden
+++ b/test/snapshots/ttyfollow.golden
@@ -1,6 +1,6 @@
== snap held-pre grid=100x30 cursor=4,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttyfollow/cwd New Del Filter /tmp/pardes-snap/ttyfollow/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttyfollow/cwd New Newtty Del Fi /tmp/pardes-snap/ttyfollow/cwd New Newtty Del Fi
| 185 ls
| 186 s.txt
| 187
@@ -15,7 +15,7 @@
| 196
| 197
| 198
-| /tmp/pardes-snap/ttyfollow/cwd New Del Filter
+| /tmp/pardes-snap/ttyfollow/cwd New Newtty Del Fi
| ls
| s.txt
|
@@ -30,8 +30,8 @@
|
|
== snap held-post grid=100x30 cursor=54,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttyfollow/cwd New Del Filter $ /tmp/pardes-snap/ttyfollow/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttyfollow/cwd New Newtty Del Fi$ /tmp/pardes-snap/ttyfollow/cwd New Newtty Del Fi
| 185 $ ls
| 186 s.txt
| 187 $ touch go; until test -f done1; do sleep 0.05;
@@ -46,7 +46,7 @@
| 196
| 197
| 198
-| /tmp/pardes-snap/ttyfollow/cwd New Del Filter
+| /tmp/pardes-snap/ttyfollow/cwd New Newtty Del Fi
| ls
| s.txt
|
@@ -61,8 +61,8 @@
|
|
== snap tty-follows grid=100x30 cursor=4,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/ttyfollow/cwd New Del Filter $ /tmp/pardes-snap/ttyfollow/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttyfollow/cwd New Newtty Del Fi$ /tmp/pardes-snap/ttyfollow/cwd New Newtty Del Fi
| 288 $ ls
| 289 s.txt
| 290 $ touch go; until test -f done1; do sleep 0.05;
@@ -77,7 +77,7 @@
| 299
| 300
| $
-| /tmp/pardes-snap/ttyfollow/cwd New Del Filter
+| /tmp/pardes-snap/ttyfollow/cwd New Newtty Del Fi
| ls
| s.txt
|
diff --git a/test/snapshots/ttyhelp.golden b/test/snapshots/ttyhelp.golden
index 27b16dbf..b8a9c2b6 100644
--- a/test/snapshots/ttyhelp.golden
+++ b/test/snapshots/ttyhelp.golden
@@ -1,6 +1,6 @@
== snap boot grid=100x30 cursor=4,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/ttyhelp/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttyhelp/cwd New Newtty Del Filter
| $
|
|
@@ -30,10 +30,10 @@
|
|
== snap helped grid=100x30 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/ttyhelp/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttyhelp/cwd New Newtty Del Filter
| $
-| /tmp/pardes-snap/ttyhelp/cwd/+Help New Del
+| /tmp/pardes-snap/ttyhelp/cwd/+Help New Newtty Del
| 1 pardes builtins, and how to run each:
| 2 SPC and its keys, a chord, a button, the
| 3 topbar - or the name, executed anywhere.
@@ -54,17 +54,17 @@
| 18 SPC a w PanelWave
| 19 SPC a z PanelZoom
| 20 SPC c d Delcol
-| 21 SPC c n Newcol topbar
-| 22 SPC d Del
-| 23 SPC f c Config
-| 24 SPC f f Find topbar
-| 25 SPC f g Grep topbar
-| 26 SPC f n New topbar
+| 21 SPC c j Joincol topbar
+| 22 SPC c n Newcol topbar
+| 23 SPC d Del
+| 24 SPC f c Config
+| 25 SPC f f Find topbar
+| 26 SPC f g Grep topbar
== snap leaderworks grid=100x30 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/ttyhelp/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttyhelp/cwd New Newtty Del Filter
| $
-| /tmp/pardes-snap/ttyhelp/cwd/+Help New Del
+| /tmp/pardes-snap/ttyhelp/cwd/+Help New Newtty Del
| 1 pardes builtins, and how to run each:
| 2 SPC and its keys, a chord, a button, the
| 3 topbar - or the name, executed anywhere.
@@ -85,9 +85,9 @@
| 18 SPC a w PanelWave
| 19 SPC a z PanelZoom
| 20 SPC c d Delcol
-| 21 SPC c n Newcol topbar
-| 22 SPC d Del
-| 23 SPC f c Config
-| 24 SPC f f Find topbar
-| 25 SPC f g Grep topbar
-| 26 SPC f n New topbar
+| 21 SPC c j Joincol topbar
+| 22 SPC c n Newcol topbar
+| 23 SPC d Del
+| 24 SPC f c Config
+| 25 SPC f f Find topbar
+| 26 SPC f g Grep topbar
diff --git a/test/snapshots/ttyhelp.snap b/test/snapshots/ttyhelp.snap
index 25e55349..99b62d5f 100644
--- a/test/snapshots/ttyhelp.snap
+++ b/test/snapshots/ttyhelp.snap
@@ -5,8 +5,8 @@ start 30 100
wait 8000 New Newcol
stable 700 20000
snap boot
-press middle 22 1
-release middle 22 1
+press middle 31 1
+release middle 31 1
wait 10000 pardes builtins
stable 700 15000
snap helped
diff --git a/test/snapshots/ttylook.golden b/test/snapshots/ttylook.golden
index d5740e5d..70992060 100644
--- a/test/snapshots/ttylook.golden
+++ b/test/snapshots/ttylook.golden
@@ -1,6 +1,6 @@
== snap tok1 grid=120x30 cursor=2,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttylook/cwd New Del Filter /tmp/pardes-snap/ttylook/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls ls
| big.txt plain.txt sub big.txt plain.txt sub
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/ttylook/cwd New Del Filter
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls
| big.txt plain.txt sub
|
@@ -30,39 +30,39 @@
|
|
== style tok1
-|0: 0-56 #949494,#121212, 57-119 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-44 #949494,#121212, 45-59 d,#121212, 60-61 #ffffff,#262626, 62-104 #949494,#121212, 105-119 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-8 #080808,#80a0ff, 9-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|12: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|16: 0-1 #ffffff,#262626, 2-44 #949494,#121212, 45-59 d,#121212, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-59 #bdbdbd,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-119 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-51 #949494,#121212, 52-59 d,#121212, 60-61 #ffffff,#262626, 62-111 #949494,#121212, 112-119 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-63 #bdbdbd,#080808, 64-119 d,#080808,
+|3: 0-0 d,#444444, 1-1 d,#080808, 2-8 #080808,#80a0ff, 9-24 #bdbdbd,#080808, 25-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-84 #bdbdbd,#080808, 85-119 d,#080808,
+|4: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|5: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|6: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|7: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|8: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|9: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|10: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|11: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|12: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|13: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|14: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|15: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-51 #949494,#121212, 52-59 d,#121212, 60-60 d,#444444, 61-119 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-24 #bdbdbd,#080808, 25-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|19: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|20: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|21: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|22: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|23: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|24: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|25: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|26: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|27: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|28: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
+|29: 0-0 d,#444444, 1-59 d,#080808, 60-60 d,#444444, 61-119 d,#080808,
== snap tok2 grid=120x30 cursor=11,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttylook/cwd New Del Filter /tmp/pardes-snap/ttylook/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls ls
| big.txt plain.txt sub big.txt plain.txt sub
|
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/ttylook/cwd New Del Filter
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls
| big.txt plain.txt sub
|
@@ -92,8 +92,8 @@
|
|
== snap tokback grid=120x30 cursor=2,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttylook/cwd New Del Filter /tmp/pardes-snap/ttylook/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls ls
| big.txt plain.txt sub big.txt plain.txt sub
|
@@ -108,7 +108,7 @@
|
|
|
-| /tmp/pardes-snap/ttylook/cwd New Del Filter
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls
| big.txt plain.txt sub
|
@@ -123,8 +123,8 @@
|
|
== snap insert grid=120x30 cursor=4,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttylook/cwd New Del Filter /tmp/pardes-snap/ttylook/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls ls
| nnbig.txt plain.txt sub big.txt plain.txt sub
|
@@ -139,7 +139,7 @@
|
|
|
-| /tmp/pardes-snap/ttylook/cwd New Del Filter
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls
| big.txt plain.txt sub
|
@@ -154,8 +154,8 @@
|
|
== snap tok3 grid=120x30 cursor=22,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttylook/cwd New Del Filter /tmp/pardes-snap/ttylook/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls ls
| big.txt plain.txt sub big.txt plain.txt sub
|
@@ -170,7 +170,7 @@
|
|
|
-| /tmp/pardes-snap/ttylook/cwd New Del Filter
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls
| big.txt plain.txt sub
|
@@ -185,12 +185,12 @@
|
|
== snap diropen grid=120x30 cursor=4,7
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttylook/cwd New Del Filter /tmp/pardes-snap/ttylook/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls ls
| big.txt plain.txt sub big.txt plain.txt sub
|
-| /tmp/pardes-snap/ttylook/cwd/sub New Del Filter
+| /tmp/pardes-snap/ttylook/cwd/sub New Newtty Del Filter
| ls
|
|
@@ -201,7 +201,7 @@
|
|
|
-| /tmp/pardes-snap/ttylook/cwd New Del Filter
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls
| big.txt plain.txt sub
|
@@ -216,12 +216,12 @@
|
|
== snap noop grid=120x30 cursor=2,3
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttylook/cwd New Del Filter /tmp/pardes-snap/ttylook/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls ls
| big.txt plain.txt sub big.txt plain.txt sub
|
-| /tmp/pardes-snap/ttylook/cwd/sub New Del Filter
+| /tmp/pardes-snap/ttylook/cwd/sub New Newtty Del Filter
| ls
|
|
@@ -232,7 +232,7 @@
|
|
|
-| /tmp/pardes-snap/ttylook/cwd New Del Filter
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
| ls
| big.txt plain.txt sub
|
@@ -247,33 +247,33 @@
|
|
== snap fileopen grid=120x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttylook/cwd /tmp/pardes-snap/ttylook/cwd /tmp/pardes-snap/ttylook/cwd New Del Filter
-| 1 line 1 ls ls
-| 2 line 2 big.txt plain.txt sub big.txt plain.txt sub
-| 3 line 3
-| 4 line 4 /tmp/pardes-snap/ttylook/cwd
-| 5 line 5 ls
-| 6 line 6
-| 7 line 7
-| 8 line 8
-| 9 line 9
-| 10 line 10
-| 11 line 11
-| 12 line 12
-| 13 line 13
-| 14 line 14
-| 15 line 15 /tmp/pardes-snap/ttylook/cwd
-| 16 line 16 ls
-| 17 line 17 big.txt plain.txt sub
-| 18 line 18
-| 19 line 19
-| 20 line 20
-| 21 line 21
-| 22 line 22
-| 23 line 23
-| 24 line 24
-| 25 line 25
-| 26 line 26
-| 27 line 27
-| 28 line 28
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttylook/cwd/big.txt Save New Newtty Del /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
+| 1 line 1 ls
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter big.txt plain.txt sub
+|
+| /tmp/pardes-snap/ttylook/cwd/sub New Newtty Del Filter
+| ls
+|
+|
+|
+|
+|
+|
+|
+|
+|
+| /tmp/pardes-snap/ttylook/cwd New Newtty Del Filter
+| ls
+| big.txt plain.txt sub
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
diff --git a/test/snapshots/ttyonly.golden b/test/snapshots/ttyonly.golden
index 1a7576cb..b0dfef79 100644
--- a/test/snapshots/ttyonly.golden
+++ b/test/snapshots/ttyonly.golden
@@ -1,6 +1,6 @@
== snap ttyonly grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/ttyonly/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttyonly/cwd New Newtty Del Filter
| $ echo TTY''ONLY
| TTYONLY
| $
@@ -30,7 +30,7 @@
|
|
== style ttyonly
-|0: 0-56 #949494,#121212, 57-99 d,#121212,
+|0: 0-74 #949494,#121212, 75-99 d,#121212,
|1: 0-1 #ffffff,#626262, 2-79 #949494,#121212, 80-99 d,#121212,
|2: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
|3: 0-0 d,#444444, 1-1 d,#080808, 2-99 #bdbdbd,#080808,
diff --git a/test/snapshots/ttypaste.golden b/test/snapshots/ttypaste.golden
new file mode 100644
index 00000000..33d7c7a4
--- /dev/null
+++ b/test/snapshots/ttypaste.golden
@@ -0,0 +1,62 @@
+== snap bracketed-paste-reached-the-shell grid=100x30 cursor=18,4
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttypaste/cwd New Newtty Del Fil /tmp/pardes-snap/ttypaste/cwd New Newtty Del Fil
+| $ ls ls
+| src.txt src.txt
+| $ echo BRACKETED
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+| /tmp/pardes-snap/ttypaste/cwd New Newtty Del Fil
+| ls
+| src.txt
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+== snap ctrl-v-with-empty-register-is-inert grid=100x30 cursor=18,4
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttypaste/cwd New Newtty Del Fil /tmp/pardes-snap/ttypaste/cwd New Newtty Del Fil
+| $ ls ls
+| src.txt src.txt
+| $ echo BRACKETED
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+| /tmp/pardes-snap/ttypaste/cwd New Newtty Del Fil
+| ls
+| src.txt
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
diff --git a/test/snapshots/ttypaste.snap b/test/snapshots/ttypaste.snap
new file mode 100644
index 00000000..d59a0b3e
--- /dev/null
+++ b/test/snapshots/ttypaste.snap
@@ -0,0 +1,32 @@
+# Pasting INTO the program a tty pane is running.
+#
+# `SPC p` and the acme 1-3 chord are both unreachable in raw tty: the pty owns
+# every keystroke and every button. So tty mode has its own chord, and a paste
+# arriving from outside has to reach the shell rather than an edit buffer that
+# the pty does not know exists.
+#
+# Two paths, both ending at the shell's command line:
+# Ctrl-V types the DEFAULT register (config.tty_paste)
+# bracketed paste the outer terminal's own paste, or a desktop one relayed
+# by a GUI host, which used to land in an overlay instead
+file src.txt PASTED-PAYLOAD
+start 30 100 -n 3
+wait 8000 src.txt
+stable 700 20000
+# fill the default register from a file pane: sweep the word and yank it
+key c-b
+stable 600 8000
+# in tty now; type a prefix so the pasted text is visibly appended to it
+text echo
+stable 600 8000
+# the outer terminal's bracketed paste: not a keystroke, no request behind it,
+# and it must arrive at the shell's line
+send \e[200~ BRACKETED\e[201~
+stable 600 8000
+snap bracketed-paste-reached-the-shell
+# Ctrl-V types the register. Nothing was yanked in this session, so the
+# register is empty and the chord is INERT rather than sending the shell the
+# 0x16 it used to (quoted-insert): the line below is unchanged.
+key c-v
+stable 600 8000
+snap ctrl-v-with-empty-register-is-inert
diff --git a/test/snapshots/ttyprompt.golden b/test/snapshots/ttyprompt.golden
index c391794d..a8c65bd5 100644
--- a/test/snapshots/ttyprompt.golden
+++ b/test/snapshots/ttyprompt.golden
@@ -1,6 +1,6 @@
== snap greeted grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttyprompt/cwd New Del Filter /tmp/pardes-snap/ttyprompt/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttyprompt/cwd New Newtty Del Fi /tmp/pardes-snap/ttyprompt/cwd New Newtty Del Fi
| ls ls
| probe.txt probe.txt
|
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/ttyprompt/cwd New Del Filter
+| /tmp/pardes-snap/ttyprompt/cwd New Newtty Del Fi
| ls
| probe.txt
|
@@ -30,8 +30,8 @@
|
|
== snap in-tty grid=100x30 cursor=17,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/ttyprompt/cwd New Del Filter /tmp/pardes-snap/ttyprompt/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/ttyprompt/cwd New Newtty Del Fi /tmp/pardes-snap/ttyprompt/cwd New Newtty Del Fi
| $ ls ls
| probe.txt probe.txt
| $ echo ABCDEFGH
@@ -46,7 +46,7 @@
|
|
|
-| /tmp/pardes-snap/ttyprompt/cwd New Del Filter
+| /tmp/pardes-snap/ttyprompt/cwd New Newtty Del Fi
| ls
| probe.txt
|
@@ -61,8 +61,8 @@
|
|
== snap out-of-tty grid=100x30 cursor=17,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttyprompt/cwd New Del Filter /tmp/pardes-snap/ttyprompt/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttyprompt/cwd New Newtty Del Fi /tmp/pardes-snap/ttyprompt/cwd New Newtty Del Fi
| ls ls
| probe.txt probe.txt
| echo ABCDEFGH
@@ -77,7 +77,7 @@
|
|
|
-| /tmp/pardes-snap/ttyprompt/cwd New Del Filter
+| /tmp/pardes-snap/ttyprompt/cwd New Newtty Del Fi
| ls
| probe.txt
|
diff --git a/test/snapshots/ttytaken.golden b/test/snapshots/ttytaken.golden
index 9b9013d5..0c0a01ea 100644
--- a/test/snapshots/ttytaken.golden
+++ b/test/snapshots/ttytaken.golden
@@ -1,8 +1,8 @@
-== snap opened grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttytaken/cwd/cmd.txt Save New D /tmp/pardes-snap/ttytaken/cwd New Del Filter
-| 1 echo TAKEN''ONE ls
-| 2 echo TAKEN''TWO big.txt cmd.txt
+== snap opened grid=210x30 cursor=7,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttytaken/cwd/cmd.txt Save New Newtty Del /tmp/pardes-snap/ttytaken/cwd New Newtty Del Filter
+| 1 echo TAKEN''ONE ls
+| 2 echo TAKEN''TWO big.txt cmd.txt
|
|
|
@@ -29,13 +29,13 @@
|
|
|
-== snap at-prompt grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttytaken/cwd/cmd.txt Save New D /tmp/pardes-snap/ttytaken/cwd New Del Filter
-| 1 echo TAKEN''ONE ls
-| 2 echo TAKEN''TWO big.txt cmd.txt
-| echo TAKEN''ONE
-| TAKENONE
+== snap at-prompt grid=210x30 cursor=7,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttytaken/cwd/cmd.txt Save New Newtty Del /tmp/pardes-snap/ttytaken/cwd New Newtty Del Filter
+| 1 echo TAKEN''ONE ls
+| 2 echo TAKEN''TWO big.txt cmd.txt
+| echo TAKEN''ONE
+| TAKENONE
|
|
|
@@ -60,65 +60,65 @@
|
|
|
-== snap paging grid=100x30 cursor=59,29
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttytaken/cwd/cmd.txt Save New D$ /tmp/pardes-snap/ttytaken/cwd New Del Filter
-| 1 echo TAKEN''ONE line 1
-| 2 echo TAKEN''TWO line 2
-| line 3
-| line 4
-| line 5
-| line 6
-| line 7
-| line 8
-| line 9
-| line 10
-| line 11
-| line 12
-| line 13
-| line 14
-| line 15
-| line 16
-| line 17
-| line 18
-| line 19
-| line 20
-| line 21
-| line 22
-| line 23
-| line 24
-| line 25
-| line 26
-| line 27
-| big.txt
-== snap spawned grid=100x30 cursor=53,25
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/ttytaken/cwd/cmd.txt Save New D$ /tmp/pardes-snap/ttytaken/cwd New Del Filter
-| 1 echo TAKEN''ONE line 1
-| 2 echo TAKEN''TWO line 2
-| line 3
-| line 4
-| line 5
-| line 6
-| line 7
-| line 8
-| line 9
-| line 10
-| line 11
-| line 12
-| line 13
-| line 14
-| line 15
-| line 16
-| line 17
-| line 18
-| line 19
-| line 20
-| line 21
-| line 22
-| line 23
-| :
-| /tmp/pardes-snap/ttytaken/cwd New Del Filter
-| echo TAKEN''TWO
-| TAKENTWO
+== snap paging grid=210x30 cursor=114,29
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttytaken/cwd/cmd.txt Save New Newtty Del $ /tmp/pardes-snap/ttytaken/cwd New Newtty Del Filter
+| 1 echo TAKEN''ONE line 1
+| 2 echo TAKEN''TWO line 2
+| line 3
+| line 4
+| line 5
+| line 6
+| line 7
+| line 8
+| line 9
+| line 10
+| line 11
+| line 12
+| line 13
+| line 14
+| line 15
+| line 16
+| line 17
+| line 18
+| line 19
+| line 20
+| line 21
+| line 22
+| line 23
+| line 24
+| line 25
+| line 26
+| line 27
+| big.txt
+== snap spawned grid=210x30 cursor=108,25
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/ttytaken/cwd/cmd.txt Save New Newtty Del $ /tmp/pardes-snap/ttytaken/cwd New Newtty Del Filter
+| 1 echo TAKEN''ONE line 1
+| 2 echo TAKEN''TWO line 2
+| line 3
+| line 4
+| line 5
+| line 6
+| line 7
+| line 8
+| line 9
+| line 10
+| line 11
+| line 12
+| line 13
+| line 14
+| line 15
+| line 16
+| line 17
+| line 18
+| line 19
+| line 20
+| line 21
+| line 22
+| line 23
+| :
+| /tmp/pardes-snap/ttytaken/cwd New Newtty Del Filter
+| echo TAKEN''TWO
+| TAKENTWO
|
diff --git a/test/snapshots/ttytaken.snap b/test/snapshots/ttytaken.snap
index 6505fc63..2ef574d0 100644
--- a/test/snapshots/ttytaken.snap
+++ b/test/snapshots/ttytaken.snap
@@ -5,7 +5,7 @@
# keystrokes the pager would eat. Nothing about the pager's screen changes.
file cmd.txt echo TAKEN''ONE\necho TAKEN''TWO
lines big.txt 40
-start 30 100 -n 1
+start 30 210 -n 1
wait 8000 cmd.txt
stable 700 20000
# open the command file by looking its name in the greeting `ls`
@@ -24,8 +24,8 @@ snap at-prompt
# ...and now a pager owns that terminal. Ctrl-b is raw tty (config.tty_toggle),
# which is how a script types AT the shell instead of into the pane's own edit
# buffer — the same way exec.snap runs a command line.
-press left 60 8
-release left 60 8
+press left 150 8
+release left 150 8
stable 400 5000
key c-b
stable 400 5000
diff --git a/test/snapshots/tutor.golden b/test/snapshots/tutor.golden
index be177dec..59fd861e 100644
--- a/test/snapshots/tutor.golden
+++ b/test/snapshots/tutor.golden
@@ -1,31 +1,31 @@
-== snap tutor grid=150x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /Tutor Save New Del /tmp/pardes-snap/tutor/cwd New Del /tmp/pardes-snap/tutor/cwd New Del Filter
-| 1 ls ls
-| 2 ↩
-| PARDES TUTOR
-| 3 tmux + vi↩
-| + acme, from scratch.
-| 4
-| 5 The model is acme's: E↩
-| VERYTHING is text, editable an↩
-| d executable
-| 6 the same way. Modal ed↩
-| iting (helix-style) lives on t↩
-| op of that.
-| 7 Press j until you reac↩
-| h the introduction.
-| 8 /tmp/pardes-snap/tutor/cwd New Del
-| 9 ls
-| 10 ==============================↩
-| ==============================↩
-| =====
-| 11 = INTRODU↩
-| CTION ↩
-| =
-| 12 ==============================↩
-| ==============================↩
-| =====
-| 13
-| 14 Pardes is tmux + vi + acme, m↩
-| ade from scratch. The foundati
+== snap tutor grid=150x30 cursor=9,15
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/tutor/cwd New Newtty Del Filter /tmp/pardes-snap/tutor/cwd New Newtty Del Filter
+| ls ls
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+| Grep /
+| /tmp/pardes-snap/tutor/cwd New Newtty Del Filter
+| ls
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
diff --git a/test/snapshots/wheeldrift.golden b/test/snapshots/wheeldrift.golden
index 08e7ce2b..58d371ae 100644
--- a/test/snapshots/wheeldrift.golden
+++ b/test/snapshots/wheeldrift.golden
@@ -1,6 +1,6 @@
== snap home grid=70x16 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/wheeldrift/cwd/drift.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/wheeldrift/cwd/drift.txt Save New Newtty Del
| 1 line 1_0123456789_abcdefghij_ZEND
| 2 line 2_0123456789_abcdefghij_ZEND
| 3 line 3_0123456789_abcdefghij_ZEND
@@ -16,8 +16,8 @@
| 13 line 13_0123456789_abcdefghij_ZEND
| 14 line 14_0123456789_abcdefghij_ZEND
== snap drifted grid=70x16 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/wheeldrift/cwd/drift.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/wheeldrift/cwd/drift.txt Save New Newtty Del
| 6 line 6_0123456789_abcdefghij_ZEND
| 7 line 7_0123456789_abcdefghij_ZEND
| 8 line 8_0123456789_abcdefghij_ZEND
@@ -33,8 +33,8 @@
| 18 line 18_0123456789_abcdefghij_ZEND
| 19 line 19_0123456789_abcdefghij_ZEND
== snap paying grid=70x16 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/wheeldrift/cwd/drift.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/wheeldrift/cwd/drift.txt Save New Newtty Del
| 6 line 6_0123456789_abcdefghij_ZEND
| 7 line 7_0123456789_abcdefghij_ZEND
| 8 line 8_0123456789_abcdefghij_ZEND
@@ -50,8 +50,8 @@
| 18 line 18_0123456789_abcdefghij_ZEND
| 19 line 19_0123456789_abcdefghij_ZEND
== snap moved grid=70x16 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/wheeldrift/cwd/drift.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/wheeldrift/cwd/drift.txt Save New Newtty Del
| 6 123456789_abcdefghij_ZEND
| 7 123456789_abcdefghij_ZEND
| 8 123456789_abcdefghij_ZEND
@@ -67,8 +67,8 @@
| 18 0123456789_abcdefghij_ZEND
| 19 0123456789_abcdefghij_ZEND
== snap rearmed grid=70x16 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/wheeldrift/cwd/drift.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug
+| /tmp/pardes-snap/wheeldrift/cwd/drift.txt Save New Newtty Del
| 5 123456789_abcdefghij_ZEND
| 6 123456789_abcdefghij_ZEND
| 7 123456789_abcdefghij_ZEND
diff --git a/test/snapshots/winch.golden b/test/snapshots/winch.golden
index c65a8463..db849ad6 100644
--- a/test/snapshots/winch.golden
+++ b/test/snapshots/winch.golden
@@ -1,6 +1,6 @@
== snap storm grid=100x30 cursor=4,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/winch/cwd New Del Filter /tmp/pardes-snap/winch/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/winch/cwd New Newtty Del Filter /tmp/pardes-snap/winch/cwd New Newtty Del Filter
| $ ls ls
| $ for i in $(seq 600); do kill -WINCH $PPID; don
| e; echo SUR''VIVED
@@ -15,7 +15,7 @@
|
|
|
-| /tmp/pardes-snap/winch/cwd New Del Filter
+| /tmp/pardes-snap/winch/cwd New Newtty Del Filter
| ls
|
|
@@ -30,8 +30,8 @@
|
|
== snap resized grid=106x34 cursor=4,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-|$ /tmp/pardes-snap/winch/cwd New Del Filter /tmp/pardes-snap/winch/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+|$ /tmp/pardes-snap/winch/cwd New Newtty Del Filter /tmp/pardes-snap/winch/cwd New Newtty Del Filter
| $ ls ls
| $ for i in $(seq 600); do kill -WINCH $PPID; done;
| echo SUR''VIVED
@@ -48,7 +48,7 @@
|
|
|
-| /tmp/pardes-snap/winch/cwd New Del Filter
+| /tmp/pardes-snap/winch/cwd New Newtty Del Filter
| ls
|
|
diff --git a/test/snapshots/windownav.golden b/test/snapshots/windownav.golden
index 577fbd4b..b24936f8 100644
--- a/test/snapshots/windownav.golden
+++ b/test/snapshots/windownav.golden
@@ -1,6 +1,6 @@
== snap start grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -30,8 +30,8 @@
|
|
== snap to-term grid=100x30 cursor=54,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -61,8 +61,8 @@
|
|
== snap back-to-file grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -92,8 +92,8 @@
|
|
== snap esc-to-term grid=100x30 cursor=54,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -123,8 +123,8 @@
|
|
== snap esc-back-to-file grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -154,8 +154,8 @@
|
|
== snap altn grid=100x30 cursor=4,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -170,7 +170,7 @@
|
|
|
-| /tmp/pardes-snap/windownav/cwd New Del Filter
+| /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| ls
| w.txt
|
@@ -185,8 +185,8 @@
|
|
== snap up grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -201,7 +201,7 @@
|
|
|
-| /tmp/pardes-snap/windownav/cwd New Del Filter
+| /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| ls
| w.txt
|
@@ -216,8 +216,8 @@
|
|
== snap right grid=100x30 cursor=54,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -232,7 +232,7 @@
|
|
|
-| /tmp/pardes-snap/windownav/cwd New Del Filter
+| /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| ls
| w.txt
|
@@ -247,8 +247,8 @@
|
|
== snap left grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -263,7 +263,7 @@
|
|
|
-| /tmp/pardes-snap/windownav/cwd New Del Filter
+| /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| ls
| w.txt
|
@@ -278,8 +278,8 @@
|
|
== snap down grid=100x30 cursor=4,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -294,7 +294,7 @@
|
|
|
-| /tmp/pardes-snap/windownav/cwd New Del Filter
+| /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| ls
| w.txt
|
@@ -309,8 +309,8 @@
|
|
== snap toggle-doc grid=100x30 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -325,7 +325,7 @@
|
|
|
-| /tmp/pardes-snap/windownav/cwd New Del Filter
+| /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| ls
| w.txt
|
@@ -340,8 +340,8 @@
|
|
== snap toggle-back grid=100x30 cursor=4,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windownav/cwd/w.txt Save New De /tmp/pardes-snap/windownav/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windownav/cwd/w.txt Save New Ne /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| 1 alpha ls
| 2 beta w.txt
| 3 gamma
@@ -356,7 +356,7 @@
|
|
|
-| /tmp/pardes-snap/windownav/cwd New Del Filter
+| /tmp/pardes-snap/windownav/cwd New Newtty Del Fi
| ls
| w.txt
|
diff --git a/test/snapshots/windownav.snap b/test/snapshots/windownav.snap
index c9de55ac..43dc9839 100644
--- a/test/snapshots/windownav.snap
+++ b/test/snapshots/windownav.snap
@@ -13,10 +13,12 @@ wait 8000 New Newcol
wait 8000 w.txt
stable 700 20000
# A FILE boots alone now, so the terminal every hop below needs is opened here:
-# SPC c n (Newcol) puts it in a column of its own on the right and focuses it,
-# SPC w h comes straight back — which also puts the shell on the stack, and Last
-# only ever names a pane that is on it.
-key space c n
+# Alt-n opens it and focuses it, Alt-c puts it in a column of its own on the
+# right, SPC w h comes straight back — which also puts the shell on the stack,
+# and Last only ever names a pane that is on it. (`New`/`Newcol` open an empty
+# +New scratch now, not a shell.)
+key a-n
+key a-c
stable 700 15000
key space w h
stable 400 5000
diff --git a/test/snapshots/windowops.golden b/test/snapshots/windowops.golden
index e6b4614b..c566bdc1 100644
--- a/test/snapshots/windowops.golden
+++ b/test/snapshots/windowops.golden
@@ -1,6 +1,6 @@
== snap hover-v grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New Del Filter ╎ /tmp/pardes-snap/windowops/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windowops/cwd New Newtty Del F╎ /tmp/pardes-snap/windowops/cwd New Newtty Del Fi
| ls ╎ ls
| w.txt ╎ w.txt
| ╎
@@ -15,7 +15,7 @@
| ╎
| ╎
| ╎
-| /tmp/pardes-snap/windowops/cwd New Del Filter ╎
+| /tmp/pardes-snap/windowops/cwd New Newtty Del F╎
| ls ╎
| w.txt ╎
| ╎
@@ -30,8 +30,8 @@
| ╎
| ╎
== snap hover-h grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New Del Filter /tmp/pardes-snap/windowops/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windowops/cwd New Newtty Del Fi /tmp/pardes-snap/windowops/cwd New Newtty Del Fi
| ls ls
| w.txt w.txt
|
@@ -46,7 +46,7 @@
|
|
|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
-| /tmp/pardes-snap/windowops/cwd New Del Filter
+| /tmp/pardes-snap/windowops/cwd New Newtty Del Fi
| ls
| w.txt
|
@@ -61,8 +61,8 @@
|
|
== snap border-drag grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New De╎ Filter /tmp/pardes-snap/windowops/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windowops/cwd New Ne╎tty Del Fi /tmp/pardes-snap/windowops/cwd New Newtty Del Fi
| ls ╎ ls
| w.txt ╎ w.txt
| ╎
@@ -77,7 +77,7 @@
| ╎
| ╎
| ╎
-| /tmp/pardes-snap/windowops/cwd New De╎ Filter
+| /tmp/pardes-snap/windowops/cwd New Ne╎tty Del Fi
| ls ╎
| w.txt ╎
| ╎
@@ -92,8 +92,8 @@
| ╎
| ╎
== snap border-done grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New De╎ /tmp/pardes-snap/windowops/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windowops/cwd New Ne╎ /tmp/pardes-snap/windowops/cwd New Newtty Del Filter
| ls ╎ ls
| w.txt ╎ w.txt
| ╎
@@ -108,7 +108,7 @@
| ╎
| ╎
| ╎
-| /tmp/pardes-snap/windowops/cwd New De╎
+| /tmp/pardes-snap/windowops/cwd New Ne╎
| ls ╎
| w.txt ╎
| ╎
@@ -123,8 +123,8 @@
| ╎
| ╎
== snap hborder-done grid=100x30 cursor=4,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windowops/cwd New New /tmp/pardes-snap/windowops/cwd New Newtty Del Filter
| ls ls
| w.txt w.txt
|
@@ -135,7 +135,7 @@
|
|
|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
@@ -154,8 +154,8 @@
|
|
== snap move-preview grid=100x30 cursor=4,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windowops/cwd New New /tmp/pardes-snap/windowops/cwd New Newtty Del Filter
| ls ls
| w.txt w.txt
|
@@ -166,7 +166,7 @@
|
|
|
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
@@ -185,8 +185,8 @@
|
|
== snap moved grid=100x30 cursor=4,15
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windowops/cwd New New /tmp/pardes-snap/windowops/cwd New Newtty Del Filter
| ls ls
| w.txt w.txt
|
@@ -197,7 +197,7 @@
|
|
|
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
@@ -216,8 +216,8 @@
|
|
== snap altn grid=100x30 cursor=4,19
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windowops/cwd New New /tmp/pardes-snap/windowops/cwd New Newtty Del Filter
| ls ls
| w.txt w.txt
|
@@ -228,11 +228,11 @@
|
|
|
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
@@ -247,8 +247,8 @@
|
|
== snap focus-right grid=100x30 cursor=44,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/windowops/cwd New New /tmp/pardes-snap/windowops/cwd New Newtty Del Filter
| ls ls
| w.txt w.txt
|
@@ -259,11 +259,11 @@
|
|
|
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
@@ -277,24 +277,24 @@
|
|
|
-== snap debug-on grid=100x30 cursor=44,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/win╭────────────────────────────────────╮
-| ls ls │pardes resizes=1 │
-| w.txt w.txt │theme helix │
-| │font default │
-| │terms 4 cols 2 │
-| │active #2 58x28 │
-| │scroll 0/28 │
-| │pinch 1.0000 │
-| │tscroll 0.0000 │
-| ╰────────────────────────────────────╯
+== snap debug-on grid=100x30 cursor=7,2
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /Tutor Save New Newtty Del /tmp/pardes-snap/windowops/cwd New Newtty Del Filter
+| 1 ls
+| 2 P↩ w.txt
+| ARDES TUTOR
+| 3 tmux + vi +
+| /tmp/pardes-snap/windowops/cwd New New
+| ls
+| w.txt
+|
+|
|
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
@@ -309,54 +309,54 @@
|
|
== style debug-on
-|0: 0-46 #949494,#121212, 47-51 #080808,#80a0ff, 52-56 #949494,#121212, 57-99 d,#121212,
-|1: 0-1 #ffffff,#262626, 2-39 #949494,#121212, 40-41 #ffffff,#626262, 42-61 #949494,#121212, 62-99 d,d,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-61 #bdbdbd,#080808, 62-62 d,d, 63-79 #949494,d, 80-98 d,#121212, 99-99 d,d,
-|3: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-61 #bdbdbd,#080808, 62-62 d,d, 63-74 #949494,d, 75-98 d,#121212, 99-99 d,d,
-|4: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-61 #bdbdbd,#080808, 62-62 d,d, 63-76 #949494,d, 77-98 d,#121212, 99-99 d,d,
-|5: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-61 #bdbdbd,#080808, 62-62 d,d, 63-77 #949494,d, 78-98 d,#121212, 99-99 d,d,
-|6: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-61 #bdbdbd,#080808, 62-62 d,d, 63-78 #949494,d, 79-98 d,#121212, 99-99 d,d,
-|7: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-61 #bdbdbd,#080808, 62-62 d,d, 63-73 #949494,d, 74-98 d,#121212, 99-99 d,d,
-|8: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-61 #bdbdbd,#080808, 62-62 d,d, 63-75 #949494,d, 76-98 d,#121212, 99-99 d,d,
-|9: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-61 #bdbdbd,#080808, 62-62 d,d, 63-77 #949494,d, 78-98 d,#121212, 99-99 d,d,
-|10: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-61 #bdbdbd,#080808, 62-99 d,d,
-|11: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|12: 0-1 #ffffff,#262626, 2-39 #949494,#121212, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|13: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|14: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|15: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|16: 0-1 #ffffff,#262626, 2-39 #949494,#121212, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|17: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|18: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|19: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|24: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|25: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|26: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|27: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|28: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-|29: 0-0 d,#444444, 1-1 d,#080808, 2-39 #bdbdbd,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-99 #bdbdbd,#080808,
-== snap debug-off grid=100x30 cursor=44,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/windowops/cwd New Del /tmp/pardes-snap/windowops/cwd New Del Filter
-| ls ls
-| w.txt w.txt
-|
-|
-|
-|
-|
+|0: 0-43 #949494,#121212, 44-48 #080808,#80a0ff, 49-74 #949494,#121212, 75-99 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-39 #949494,#121212, 40-41 #ffffff,#262626, 42-93 #949494,#121212, 94-99 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-39 d,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-43 #bdbdbd,#080808, 44-99 d,#080808,
+|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-38 #bdbdbd,#080808, 39-39 #626262,#080808, 40-40 d,#444444, 41-41 d,#080808, 42-46 #bdbdbd,#080808, 47-99 d,#080808,
+|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-38 #bdbdbd,#080808, 39-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|6: 0-1 #ffffff,#262626, 2-39 #949494,#121212, 40-40 d,#444444, 41-99 d,#080808,
+|7: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|8: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|9: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|10: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|11: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|12: 0-1 #ffffff,#262626, 2-39 #949494,#121212, 40-40 d,#444444, 41-99 d,#080808,
+|13: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|14: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|15: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|16: 0-1 #ffffff,#262626, 2-39 #949494,#121212, 40-40 d,#444444, 41-99 d,#080808,
+|17: 0-0 d,#444444, 1-1 d,#080808, 2-3 #bdbdbd,#080808, 4-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|18: 0-0 d,#444444, 1-1 d,#080808, 2-6 #bdbdbd,#080808, 7-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|19: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|20: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|21: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|22: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|23: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|24: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|25: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|26: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|27: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|28: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+|29: 0-0 d,#444444, 1-39 d,#080808, 40-40 d,#444444, 41-99 d,#080808,
+== snap debug-off grid=100x30 cursor=7,4
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /Tutor Save New Newtty Del /tmp/pardes-snap/windowops/cwd New Newtty Del Filter
+| 1 ls
+| /Tutor Save New Newtty Del w.txt
+| 1
+| 2 P
+| /tmp/pardes-snap/windowops/cwd New New
+| ls
+| w.txt
|
|
|
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
-| /tmp/pardes-snap/windowops/cwd New Del
+| /tmp/pardes-snap/windowops/cwd New New
| ls
| w.txt
|
diff --git a/test/snapshots/wrap.golden b/test/snapshots/wrap.golden
index 2b4c530b..652ffae2 100644
--- a/test/snapshots/wrap.golden
+++ b/test/snapshots/wrap.golden
@@ -1,6 +1,6 @@
== snap on-narrow grid=48x14 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor D
-| /tmp/pardes-snap/wrap/cwd/long.txt Save New De
+|New Newcol Joincol Find Grep Help Changelog Tuto
+| /tmp/pardes-snap/wrap/cwd/long.txt Save New Ne
| 1 0---------1---------2---------3---------↩
| 4---------5---------6---------7---------↩
| 8---------9---------A---------B---------↩
@@ -14,8 +14,8 @@
|
|
== snap clicked grid=48x14 cursor=17,3
-|New Newcol Find Grep Help Tutor Dump NextColor D
-| /tmp/pardes-snap/wrap/cwd/long.txt Save New De
+|New Newcol Joincol Find Grep Help Changelog Tuto
+| /tmp/pardes-snap/wrap/cwd/long.txt Save New Ne
| 1 0---------1---------2---------3---------↩
| 4---------5---------6---------7---------↩
| 8---------9---------A---------B---------↩
@@ -29,8 +29,8 @@
|
|
== snap logical-j grid=48x14 cursor=18,7
-|New Newcol Find Grep Help Tutor Dump NextColor D
-| /tmp/pardes-snap/wrap/cwd/long.txt Save New De
+|New Newcol Joincol Find Grep Help Changelog Tuto
+| /tmp/pardes-snap/wrap/cwd/long.txt Save New Ne
| 1 0---------1---------2---------3---------↩
| 4---------5---------6---------7---------↩
| 8---------9---------A---------B---------↩
@@ -44,8 +44,8 @@
|
|
== snap off grid=48x14 cursor=18,3
-|New Newcol Find Grep Help Tutor Dump NextColor D
-| /tmp/pardes-snap/wrap/cwd/long.txt Save New De
+|New Newcol Joincol Find Grep Help Changelog Tuto
+| /tmp/pardes-snap/wrap/cwd/long.txt Save New Ne
| 1 0---------1---------2---------3---------4
| 2 second line
| 3 third line
@@ -59,8 +59,8 @@
|
|
== snap on-again grid=48x14 cursor=18,7
-|New Newcol Find Grep Help Tutor Dump NextColor D
-| /tmp/pardes-snap/wrap/cwd/long.txt Save New De
+|New Newcol Joincol Find Grep Help Changelog Tuto
+| /tmp/pardes-snap/wrap/cwd/long.txt Save New Ne
| 1 0---------1---------2---------3---------↩
| 4---------5---------6---------7---------↩
| 8---------9---------A---------B---------↩
@@ -74,8 +74,8 @@
|
|
== snap on-wide grid=128x14 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/wrap/cwd/long.txt Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/wrap/cwd/long.txt Save New Newtty Del
| 1 0---------1---------2---------3---------4---------5---------6---------7---------8---------9---------A---------B---------↩
| C---------D---------E---------F---------G---------H---------I---------J---------
| 2 second line
diff --git a/test/snapshots/yankpaste.golden b/test/snapshots/yankpaste.golden
index b7757431..d2b9589c 100644
--- a/test/snapshots/yankpaste.golden
+++ b/test/snapshots/yankpaste.golden
@@ -1,6 +1,6 @@
== snap linewise-below grid=100x30 cursor=13,5
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/yankpaste/cwd/f.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/yankpaste/cwd/f.txt * Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -30,8 +30,8 @@
|
|
== snap linewise-above grid=100x30 cursor=13,6
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/yankpaste/cwd/f.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/yankpaste/cwd/f.txt * Save New Newtty Del
| 1 line 1
| 2 line 2
| 3 line 3
@@ -61,8 +61,8 @@
|
|
== snap charwise-inline grid=100x30 cursor=10,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/yankpaste/cwd/f.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/yankpaste/cwd/f.txt * Save New Newtty Del
| 1 liline 1
| 2 line 2
| 3 line 3
@@ -92,8 +92,8 @@
|
|
== snap blankline grid=100x30 cursor=7,4
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /tmp/pardes-snap/yankpaste/cwd/f.txt * Save New Del
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /tmp/pardes-snap/yankpaste/cwd/f.txt * Save New Newtty Del
| 1 liline 1
| 2
| 3
diff --git a/test/web-snapshots/source-list.golden b/test/web-snapshots/source-list.golden
index e32381e9..8f33f4f1 100644
--- a/test/web-snapshots/source-list.golden
+++ b/test/web-snapshots/source-list.golden
@@ -1,6 +1,6 @@
== snap launcher-bottom grid=120x37 cursor=4,36
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /home/goblin/00-projects/0x4200.cafe/02-pardes-code New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /home/goblin/00-projects/0x4200.cafe/02-pardes-code New Newtty Del Filter
| src/pdf_pane_integration_test.zig
| src/petscii.zig
| src/runtime_config.zig
@@ -37,8 +37,8 @@
| uucode_config.zig
|
== snap launcher-top grid=120x37 cursor=4,36
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| /home/goblin/00-projects/0x4200.cafe/02-pardes-code New Del Filter
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| /home/goblin/00-projects/0x4200.cafe/02-pardes-code New Newtty Del Filter
| git ls-files --cached --others --exclude-standard -- '*.zig' | sort
| build.zig
| build/snap.zig
@@ -75,154 +75,154 @@
| src/petscii.zig
| src/runtime_config.zig
== snap source-open grid=120x37 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| build.zig Save New Del /home/goblin/00-projects/0x4200.cafe/02-pardes-code New De
-| 1 const std = @import("std"); git ls-files --cached --others --exclude-standard -- '*.
-| 2 const builtin = @import("builtin"); zig' | sort
-| 3 const mupdf_build = @import("mupdf.zig"); build.zig
-| 4 const snap_build = @import("build/snap.zig"); build/snap.zig
-| 5 const grammar_manifest = @import("src/grammar_manife↩ mupdf.zig
-| st.zig"); src/allocators.zig
-| 6 src/animation.zig
-| 7 pub const Platform = enum { tty, gui, web, macos }; src/builtins.zig
-| 8 src/config.zig
-| 9 /// The oldest macOS pardes.app claims to run on, sp↩ src/dump.zig
-| elled ONCE. Three things src/effect_sources.zig
-| 10 /// have to agree about it or the bundle is a lie: t↩ src/file_pane.zig
-| he target this build gives src/fonts.zig
-| 11 /// the static library, the `-target` the app's swif↩ src/grammar_manifest.zig
-| tc link is given (which is src/gui/crt.zig
-| 12 /// what writes LC_BUILD_VERSION, the thing dyld act↩ src/gui/deck.zig
-| ually enforces), and the src/gui/gui.zig
-| 13 /// plist's LSMinimumSystemVersion. The macos branch↩ src/image.zig
-| below derives the last two src/image_pane.zig
-| 14 /// from this, so there is one string and no drift. src/look.zig
-| 15 pub const macos_min_version: std.SemanticVersion = .↩ src/lsp/lsp.zig
-| { .major = 13, .minor = 0, .patch = 0 }; src/lsp/lsp_zls.zig
-| 16 src/macos.zig
-| 17 /// The ZLS the language backend links, spelled once↩ src/main.zig
-| . It names the commit src/message.zig
-| 18 /// build.zig.zon pins (0.16.x branch) and is passed↩ src/modal.zig
-| BOTH to ZLS's own src/nested.zig
-| 19 /// `-Dversion-string` (its build.zig otherwise shel↩ src/normal_input.zig
-| ls out to `git describe`, src/output_pane.zig
-| 20 /// which fails on a fetched package that has no .gi↩ src/panel_animation.zig
-| t) and to `SPC l i`. src/pardes.zig
-| 21 const zls_version = "0.16.1-dev+3e0d0820"; src/pdf.zig
-| 22 pub const TreeSitterGrammars = enum { disabled, zig,↩ src/pdf_pane.zig
-| minimal, full }; src/pdf_pane_integration_test.zig
-| 23 src/petscii.zig
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| build.zig Save New Newtty Del
+| 1 const std = @import("std");
+| 2 const builtin = @import("builtin");
+| 3 const mupdf_build = @import("mupdf.zig");
+| 4 const snap_build = @import("build/snap.zig");
+| 5 const grammar_manifest = @import("src/grammar_manifest.zig");
+| 6
+| 7 pub const Platform = enum { tty, gui, web, macos };
+| 8
+| 9 /// The oldest macOS pardes.app claims to run on, spelled ONCE. Three things
+| 10 /// have to agree about it or the bundle is a lie: the target this build gives
+| 11 /// the static library, the `-target` the app's swiftc link is given (which is
+| 12 /// what writes LC_BUILD_VERSION, the thing dyld actually enforces), and the
+| 13 /// plist's LSMinimumSystemVersion. The macos branch below derives the last two
+| 14 /// from this, so there is one string and no drift.
+| 15 pub const macos_min_version: std.SemanticVersion = .{ .major = 13, .minor = 0, .patch = 0 };
+| 16
+| 17 /// The ZLS the language backend links, spelled once. It names the commit
+| /home/goblin/00-projects/0x4200.cafe/02-pardes-code New Newtty Del Filter
+| git ls-files --cached --others --exclude-standard -- '*.zig' | sort
+| build.zig
+| build/snap.zig
+| mupdf.zig
+| src/allocators.zig
+| src/animation.zig
+| src/builtins.zig
+| src/config.zig
+| src/dump.zig
+| src/effect_sources.zig
+| src/file_pane.zig
+| src/fonts.zig
+| src/grammar_manifest.zig
+| src/gui/crt.zig
+| src/gui/deck.zig
+| src/gui/gui.zig
+| src/image.zig
== style source-open
-|0: 0-56 #949494,#121212, 57-119 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-39 #949494,#121212, 40-59 d,#121212, 60-61 #ffffff,#262626, 62-119 #949494,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-18 #bdbdbd,#080808, 19-25 #cf87e8,#080808,b 26-26 #bdbdbd,#080808, 27-31 #e3c78a,#080808, 32-33 #bdbdbd,#080808, 34-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-29 #cf87e8,#080808,b 30-30 #bdbdbd,#080808, 31-39 #e3c78a,#080808, 40-41 #bdbdbd,#080808, 42-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #bdbdbd,#080808, 27-33 #cf87e8,#080808,b 34-34 #bdbdbd,#080808, 35-45 #e3c78a,#080808, 46-47 #bdbdbd,#080808, 48-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-25 #bdbdbd,#080808, 26-32 #cf87e8,#080808,b 33-33 #bdbdbd,#080808, 34-49 #e3c78a,#080808, 50-51 #bdbdbd,#080808, 52-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-31 #bdbdbd,#080808, 32-38 #cf87e8,#080808,b 39-39 #bdbdbd,#080808, 40-58 #e3c78a,#080808, 59-59 #626262,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-13 #e3c78a,#080808, 14-15 #bdbdbd,#080808, 16-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|8: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|9: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-27 #bdbdbd,#080808, 28-31 #cf87e8,#080808,b 32-57 #bdbdbd,#080808, 58-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|10: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|11: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-58 #ffffff,#080808,b 59-59 #626262,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|12: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #ffffff,#080808,b 31-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|13: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-58 #ffffff,#080808,b 59-59 #626262,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|14: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-32 #ffffff,#080808,b 33-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|15: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-58 #ffffff,#080808,b 59-59 #626262,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|16: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-32 #ffffff,#080808,b 33-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|17: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-58 #ffffff,#080808,b 59-59 #626262,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|18: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-30 #ffffff,#080808,b 31-59 d,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|19: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-58 #ffffff,#080808,b 59-59 #626262,#080808, 60-60 d,#444444, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|20: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-33 #ffffff,#080808,b 34-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|21: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-57 #ffffff,#080808,b 58-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|22: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-58 #bdbdbd,#080808, 59-59 #626262,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|23: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-19 #e3c78a,#080808, 20-30 #bdbdbd,#080808, 31-31 #e3c78a,#080808, 32-42 #bdbdbd,#080808, 43-43 #e3c78a,#080808, 44-46 #bdbdbd,#080808, 47-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|24: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|25: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-58 #ffffff,#080808,b 59-59 #626262,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|26: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-27 #ffffff,#080808,b 28-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|27: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-58 #ffffff,#080808,b 59-59 #626262,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|28: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-24 #ffffff,#080808,b 25-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|29: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-58 #ffffff,#080808,b 59-59 #626262,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|30: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-31 #ffffff,#080808,b 32-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|31: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-58 #ffffff,#080808,b 59-59 #626262,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|32: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #ffffff,#080808,b 27-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|33: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #bdbdbd,#080808, 27-47 #e3c78a,#080808, 48-48 #bdbdbd,#080808, 49-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|34: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-37 #bdbdbd,#080808, 38-41 #cf87e8,#080808,b 42-58 #bdbdbd,#080808, 59-59 #626262,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|35: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-23 #bdbdbd,#080808, 24-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
-|36: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-59 d,#080808, 60-60 d,#121212, 61-61 d,#080808, 62-119 #bdbdbd,#080808,
+|0: 0-74 #949494,#121212, 75-119 d,#121212,
+|1: 0-1 #ffffff,#626262, 2-99 #949494,#121212, 100-119 d,#121212,
+|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-18 #bdbdbd,#080808, 19-25 #cf87e8,#080808,b 26-26 #bdbdbd,#080808, 27-31 #e3c78a,#080808, 32-33 #bdbdbd,#080808, 34-119 d,#080808,
+|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-29 #cf87e8,#080808,b 30-30 #bdbdbd,#080808, 31-39 #e3c78a,#080808, 40-41 #bdbdbd,#080808, 42-119 d,#080808,
+|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #bdbdbd,#080808, 27-33 #cf87e8,#080808,b 34-34 #bdbdbd,#080808, 35-45 #e3c78a,#080808, 46-47 #bdbdbd,#080808, 48-119 d,#080808,
+|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-25 #bdbdbd,#080808, 26-32 #cf87e8,#080808,b 33-33 #bdbdbd,#080808, 34-49 #e3c78a,#080808, 50-51 #bdbdbd,#080808, 52-119 d,#080808,
+|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-31 #bdbdbd,#080808, 32-38 #cf87e8,#080808,b 39-39 #bdbdbd,#080808, 40-65 #e3c78a,#080808, 66-67 #bdbdbd,#080808, 68-119 d,#080808,
+|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808,
+|8: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-27 #bdbdbd,#080808, 28-31 #cf87e8,#080808,b 32-57 #bdbdbd,#080808, 58-119 d,#080808,
+|9: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808,
+|10: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-82 #ffffff,#080808,b 83-119 d,#080808,
+|11: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-84 #ffffff,#080808,b 85-119 d,#080808,
+|12: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-84 #ffffff,#080808,b 85-119 d,#080808,
+|13: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-82 #ffffff,#080808,b 83-119 d,#080808,
+|14: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-85 #ffffff,#080808,b 86-119 d,#080808,
+|15: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-57 #ffffff,#080808,b 58-119 d,#080808,
+|16: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-69 #bdbdbd,#080808, 70-71 #e3c78a,#080808, 72-82 #bdbdbd,#080808, 83-83 #e3c78a,#080808, 84-94 #bdbdbd,#080808, 95-95 #e3c78a,#080808, 96-98 #bdbdbd,#080808, 99-119 d,#080808,
+|17: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808,
+|18: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-79 #ffffff,#080808,b 80-119 d,#080808,
+|19: 0-1 #ffffff,#262626, 2-99 #949494,#121212, 100-119 d,#121212,
+|20: 0-0 d,#444444, 1-1 d,#080808, 2-68 #bdbdbd,#080808, 69-119 d,#080808,
+|21: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-119 d,#080808,
+|22: 0-0 d,#444444, 1-1 d,#080808, 2-15 #bdbdbd,#080808, 16-119 d,#080808,
+|23: 0-0 d,#444444, 1-1 d,#080808, 2-10 #bdbdbd,#080808, 11-119 d,#080808,
+|24: 0-0 d,#121212, 1-1 d,#080808, 2-19 #bdbdbd,#080808, 20-119 d,#080808,
+|25: 0-0 d,#121212, 1-1 d,#080808, 2-18 #bdbdbd,#080808, 19-119 d,#080808,
+|26: 0-0 d,#121212, 1-1 d,#080808, 2-17 #bdbdbd,#080808, 18-119 d,#080808,
+|27: 0-0 d,#121212, 1-1 d,#080808, 2-15 #bdbdbd,#080808, 16-119 d,#080808,
+|28: 0-0 d,#121212, 1-1 d,#080808, 2-13 #bdbdbd,#080808, 14-119 d,#080808,
+|29: 0-0 d,#121212, 1-1 d,#080808, 2-23 #bdbdbd,#080808, 24-119 d,#080808,
+|30: 0-0 d,#121212, 1-1 d,#080808, 2-18 #bdbdbd,#080808, 19-119 d,#080808,
+|31: 0-0 d,#121212, 1-1 d,#080808, 2-14 #bdbdbd,#080808, 15-119 d,#080808,
+|32: 0-0 d,#121212, 1-1 d,#080808, 2-25 #bdbdbd,#080808, 26-119 d,#080808,
+|33: 0-0 d,#121212, 1-1 d,#080808, 2-16 #bdbdbd,#080808, 17-119 d,#080808,
+|34: 0-0 d,#121212, 1-1 d,#080808, 2-17 #bdbdbd,#080808, 18-119 d,#080808,
+|35: 0-0 d,#121212, 1-1 d,#080808, 2-16 #bdbdbd,#080808, 17-119 d,#080808,
+|36: 0-0 d,#121212, 1-1 d,#080808, 2-14 #bdbdbd,#080808, 15-119 d,#080808,
== snap separator-resized grid=120x37 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| build.zig Save New Del /home/goblin/00-projects/0x4200.cafe/02-pardes-code New D
-| 1 const std = @import("std"); git ls-files --cached --others --exclude-standard -- '*
-| 2 const builtin = @import("builtin"); .zig' | sort
-| 3 const mupdf_build = @import("mupdf.zig"); build.zig
-| 4 const snap_build = @import("build/snap.zig"); build/snap.zig
-| 5 const grammar_manifest = @import("src/grammar_manifes↩ mupdf.zig
-| t.zig"); src/allocators.zig
-| 6 src/animation.zig
-| 7 pub const Platform = enum { tty, gui, web, macos }; src/builtins.zig
-| 8 src/config.zig
-| 9 /// The oldest macOS pardes.app claims to run on, spe↩ src/dump.zig
-| lled ONCE. Three things src/effect_sources.zig
-| 10 /// have to agree about it or the bundle is a lie: th↩ src/file_pane.zig
-| e target this build gives src/fonts.zig
-| 11 /// the static library, the `-target` the app's swift↩ src/grammar_manifest.zig
-| c link is given (which is src/gui/crt.zig
-| 12 /// what writes LC_BUILD_VERSION, the thing dyld actu↩ src/gui/deck.zig
-| ally enforces), and the src/gui/gui.zig
-| 13 /// plist's LSMinimumSystemVersion. The macos branch ↩ src/image.zig
-| below derives the last two src/image_pane.zig
-| 14 /// from this, so there is one string and no drift. src/look.zig
-| 15 pub const macos_min_version: std.SemanticVersion = .{↩ src/lsp/lsp.zig
-| .major = 13, .minor = 0, .patch = 0 }; src/lsp/lsp_zls.zig
-| 16 src/macos.zig
-| 17 /// The ZLS the language backend links, spelled once.↩ src/main.zig
-| It names the commit src/message.zig
-| 18 /// build.zig.zon pins (0.16.x branch) and is passed ↩ src/modal.zig
-| BOTH to ZLS's own src/nested.zig
-| 19 /// `-Dversion-string` (its build.zig otherwise shell↩ src/normal_input.zig
-| s out to `git describe`, src/output_pane.zig
-| 20 /// which fails on a fetched package that has no .git↩ src/panel_animation.zig
-| ) and to `SPC l i`. src/pardes.zig
-| 21 const zls_version = "0.16.1-dev+3e0d0820"; src/pdf.zig
-| 22 pub const TreeSitterGrammars = enum { disabled, zig, ↩ src/pdf_pane.zig
-| minimal, full }; src/pdf_pane_integration_test.zig
-| 23 src/petscii.zig
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| build.zig Save New Newtty Del
+| 1 const std = @import("std");
+| 2 const builtin = @import("builtin");
+| 3 const mupdf_build = @import("mupdf.zig");
+| 4 const snap_build = @import("build/snap.zig");
+| 5 const grammar_manifest = @import("src/grammar_manifest.zig");
+| 6
+| 7 pub const Platform = enum { tty, gui, web, macos };
+| 8
+| 9 /// The oldest macOS pardes.app claims to run on, spelled ONCE. Three things
+| 10 /// have to agree about it or the bundle is a lie: the target this build gives
+| 11 /// the static library, the `-target` the app's swiftc link is given (which is
+| 12 /// what writes LC_BUILD_VERSION, the thing dyld actually enforces), and the
+| 13 /// plist's LSMinimumSystemVersion. The macos branch below derives the last two
+| 14 /// from this, so there is one string and no drift.
+| 15 pub const macos_min_version: std.SemanticVersion = .{ .major = 13, .minor = 0, .patch = 0 };
+| 16
+| 17 /// The ZLS the language backend links, spelled once. It names the commit
+| /home/goblin/00-projects/0x4200.cafe/02-pardes-code New Newtty Del Filter
+| src/allocators.zig
+| src/animation.zig
+| src/builtins.zig
+| src/config.zig
+| src/dump.zig
+| src/effect_sources.zig
+| src/file_pane.zig
+| src/fonts.zig
+| src/grammar_manifest.zig
+| src/gui/crt.zig
+| src/gui/deck.zig
+| src/gui/gui.zig
+| src/image.zig
+| src/image_pane.zig
+| src/look.zig
+| src/lsp/lsp.zig
+| src/lsp/lsp_zls.zig
== snap source-scrolled grid=120x37 cursor=7,2
-|New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
-| build.zig Save New Del /home/goblin/00-projects/0x4200.cafe/02-pardes-code New D
-| 1 const std = @import("std"); git ls-files --cached --others --exclude-standard -- '*
-| 2 const builtin = @import("builtin"); .zig' | sort
-| 3 const mupdf_build = @import("mupdf.zig"); build.zig
-| 4 const snap_build = @import("build/snap.zig"); build/snap.zig
-| 5 const grammar_manifest = @import("src/grammar_manifes↩ mupdf.zig
-| t.zig"); src/allocators.zig
-| 6 src/animation.zig
-| 7 pub const Platform = enum { tty, gui, web, macos }; src/builtins.zig
-| 8 src/config.zig
-| 9 /// The oldest macOS pardes.app claims to run on, spe↩ src/dump.zig
-| lled ONCE. Three things src/effect_sources.zig
-| 10 /// have to agree about it or the bundle is a lie: th↩ src/file_pane.zig
-| e target this build gives src/fonts.zig
-| 11 /// the static library, the `-target` the app's swift↩ src/grammar_manifest.zig
-| c link is given (which is src/gui/crt.zig
-| 12 /// what writes LC_BUILD_VERSION, the thing dyld actu↩ src/gui/deck.zig
-| ally enforces), and the src/gui/gui.zig
-| 13 /// plist's LSMinimumSystemVersion. The macos branch ↩ src/image.zig
-| below derives the last two src/image_pane.zig
-| 14 /// from this, so there is one string and no drift. src/look.zig
-| 15 pub const macos_min_version: std.SemanticVersion = .{↩ src/lsp/lsp.zig
-| .major = 13, .minor = 0, .patch = 0 }; src/lsp/lsp_zls.zig
-| 16 src/macos.zig
-| 17 /// The ZLS the language backend links, spelled once.↩ src/main.zig
-| It names the commit src/message.zig
-| 18 /// build.zig.zon pins (0.16.x branch) and is passed ↩ src/modal.zig
-| BOTH to ZLS's own src/nested.zig
-| 19 /// `-Dversion-string` (its build.zig otherwise shell↩ src/normal_input.zig
-| s out to `git describe`, src/output_pane.zig
-| 20 /// which fails on a fetched package that has no .git↩ src/panel_animation.zig
-| ) and to `SPC l i`. src/pardes.zig
-| 21 const zls_version = "0.16.1-dev+3e0d0820"; src/pdf.zig
-| 22 pub const TreeSitterGrammars = enum { disabled, zig, ↩ src/pdf_pane.zig
-| minimal, full }; src/pdf_pane_integration_test.zig
-| 23 src/petscii.zig
+|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
+| build.zig Save New Newtty Del
+| 1 const std = @import("std");
+| 2 const builtin = @import("builtin");
+| 3 const mupdf_build = @import("mupdf.zig");
+| 4 const snap_build = @import("build/snap.zig");
+| 5 const grammar_manifest = @import("src/grammar_manifest.zig");
+| 6
+| 7 pub const Platform = enum { tty, gui, web, macos };
+| 8
+| 9 /// The oldest macOS pardes.app claims to run on, spelled ONCE. Three things
+| 10 /// have to agree about it or the bundle is a lie: the target this build gives
+| 11 /// the static library, the `-target` the app's swiftc link is given (which is
+| 12 /// what writes LC_BUILD_VERSION, the thing dyld actually enforces), and the
+| 13 /// plist's LSMinimumSystemVersion. The macos branch below derives the last two
+| 14 /// from this, so there is one string and no drift.
+| 15 pub const macos_min_version: std.SemanticVersion = .{ .major = 13, .minor = 0, .patch = 0 };
+| 16
+| 17 /// The ZLS the language backend links, spelled once. It names the commit
+| /home/goblin/00-projects/0x4200.cafe/02-pardes-code New Newtty Del Filter
+| src/fonts.zig
+| src/grammar_manifest.zig
+| src/gui/crt.zig
+| src/gui/deck.zig
+| src/gui/gui.zig
+| src/image.zig
+| src/image_pane.zig
+| src/look.zig
+| src/lsp/lsp.zig
+| src/lsp/lsp_zls.zig
+| src/macos.zig
+| src/main.zig
+| src/message.zig
+| src/modal.zig
+| src/nested.zig
+| src/normal_input.zig
+| src/output_pane.zig
diff --git a/test/web-snapshots/source-list.snap b/test/web-snapshots/source-list.snap
index 3f1a2a20..136e583c 100644
--- a/test/web-snapshots/source-list.snap
+++ b/test/web-snapshots/source-list.snap
@@ -22,7 +22,7 @@ touch move 1 5.2 3.1
touch up 1 5.2 3.1
# The editable path and the right-aligned command tail deliberately have
# layout-owned padding between them. Check the two semantic facts separately.
-wait 10000 Save New Del
+wait 10000 Save New Newtty Del
wait 10000 build.zig
stable 100 5000
snap source-open
diff --git a/test/web_harness.mjs b/test/web_harness.mjs
index 087dd91b..7bfc2d60 100644
--- a/test/web_harness.mjs
+++ b/test/web_harness.mjs
@@ -17,25 +17,47 @@ async function main() {
const webDir = path.resolve(process.argv[2]);
const wasmBytes = await fs.readFile(path.join(webDir, "pardes.wasm"));
const module = await WebAssembly.compile(wasmBytes);
- assert.deepEqual(WebAssembly.Module.imports(module), [], "the freestanding core must have no JS or libc imports");
- const { exports: wasm } = await WebAssembly.instantiate(module, {});
+ const { DomRenderer, animationTicks, browserHost } = await import(pathToFileURL(path.join(webDir, "app.mjs")));
+ assert.deepEqual(
+ [...new Set(WebAssembly.Module.imports(module).map((entry) => entry.module))],
+ ["pardes"],
+ "the freestanding core must import nothing but the page's own host",
+ );
+
+ // The page's real import object, with every call recorded: the browser host
+ // is only what a page can actually do, and a replay must ask it for nothing.
+ const host = browserHost();
+ const asked = [];
+ for (const [name, fn] of Object.entries(host.imports.pardes)) {
+ host.imports.pardes[name] = (...args) => {
+ asked.push(name);
+ return fn(...args);
+ };
+ }
+ const { exports: wasm } = await WebAssembly.instantiate(module, host.imports);
+ host.wasm = wasm;
for (const name of [
"memory", "pardes_init", "pardes_frame", "pardes_frame_ptr", "pardes_key",
- "pardes_mouse", "pardes_pointer_leave", "pardes_gui_tagline_font_percent", "pardes_output",
- "pardes_lsp_response", "pardes_pipe_response", "pardes_file_changed",
- "pardes_effect_next", "pardes_deinit",
+ "pardes_mouse", "pardes_pointer_leave", "pardes_gui_tagline_font_percent",
+ "pardes_paste", "pardes_tick", "pardes_animation_tick", "pardes_animating",
+ "pardes_should_quit", "pardes_deinit",
]) assert.ok(wasm[name], `missing wasm export ${name}`);
assert.equal(wasm.pardes_init(80, 24), 0, `wasm init error ${wasm.pardes_last_error()}`);
+ assert.equal(wasm.pardes_frame(), 0, "a frame exists only once the core has presented one");
+ wasm.pardes_tick();
assert.equal(wasm.pardes_frame(), 80 * 24);
assert.ok(wasm.pardes_frame_ptr() > 0);
- const { DomRenderer, animationTicks } = await import(pathToFileURL(path.join(webDir, "app.mjs")));
const document = new FakeDocument();
const root = document.createElement("main");
root.ownerDocument = document;
const renderer = new DomRenderer(root, wasm);
+ const draw = () => {
+ wasm.pardes_tick();
+ return renderer.render();
+ };
const first = renderer.render();
assert.equal(first.cols, 80);
@@ -69,7 +91,7 @@ async function main() {
assert.equal(animationTicks(stalled, 60_000), 4, "suspended tab catch-up was not bounded");
const firstCell = renderer.cells[0];
- const second = renderer.render();
+ const second = draw();
assert.equal(renderer.cells[0], firstCell, "stable frames should reuse DOM nodes");
assert.equal(second.cells.length, 80 * 24);
@@ -77,7 +99,7 @@ async function main() {
// over-scroll (the core clamps at row zero) so adding more source files does
// not silently move the hard-coded build.zig click onto some later path.
for (let tick = 0; tick < 128; tick += 1) wasm.pardes_mouse(3, 0, 5, 3, 0);
- const listingTop = renderer.render();
+ const listingTop = draw();
assert.match(
listingTop.cells.map((cell) => cell.text).join(""),
/git ls-files --cached --others --exclude-standard.*build\.zig/,
@@ -85,23 +107,21 @@ async function main() {
);
wasm.pardes_mouse(2, 0, 5, 3, 0);
wasm.pardes_mouse(2, 1, 5, 3, 0);
- const looked = renderer.render();
- assert.match(looked.cells.map((cell) => cell.text).join(""), /build\.zig Save New Del/, "right-click LOOK did not open the embedded source");
+ const looked = draw();
+ assert.match(
+ looked.cells.map((cell) => cell.text).join(""),
+ /build\.zig\s+Save New Newtty Del/,
+ "right-click LOOK did not open the embedded source",
+ );
const sourceRows = Array.from({ length: looked.rows }, (_, row) =>
looked.cells.slice(row * looked.cols, (row + 1) * looked.cols));
const codeRows = sourceRows.filter((row) => row.map((cell) => cell.text).join("").match(/^\s*\d+\s/));
const codeColors = new Set(codeRows.flatMap((row) => row.slice(5).map((cell) => `${cell.fg}:${cell.attrs & 1}`)));
assert.ok(codeColors.size >= 3, "Tree-sitter did not apply distinct syntax styles to build.zig");
- let sawWatch = false;
- for (let index = 0; index < 32; index += 1) {
- const kind = wasm.pardes_effect_next();
- if (!kind) break;
- if (kind === 9) sawWatch = true;
- }
- assert.ok(sawWatch, "JS effect drain did not receive the opened file watch request");
+ assert.deepEqual(asked, [], "a plain replay asked the page for host IO");
wasm.pardes_resize(41, 13);
- const resized = renderer.render();
+ const resized = draw();
assert.equal(resized.cols, 41);
assert.equal(resized.rows, 13);
assert.equal(root.children.length, 13);
diff --git a/tools/embed_zig_sources.zig b/tools/embed_zig_sources.zig
deleted file mode 100644
index 91fd128f..00000000
--- a/tools/embed_zig_sources.zig
+++ /dev/null
@@ -1,177 +0,0 @@
-//! Build-time generator for the web LOOK filesystem.
-//!
-//! Prefer Git's tracked-plus-untracked/nonignored view so a new source works in
-//! the browser before it is staged, while ignored build/cache/vendor files can
-//! never leak into the bundle. A source archive should still be buildable
-//! without Git, so a conservative directory walk is the fallback.
-const std = @import("std");
-
-pub fn main(init: std.process.Init) !void {
- const gpa = init.gpa;
- const io = init.io;
- const args = try init.minimal.args.toSlice(init.arena.allocator());
- if (args.len != 3) return error.BadArgs;
-
- const root = args[1];
- const output_path = args[2];
- const paths = (try gitWorkingTreeZigFiles(gpa, io, root)) orelse try walkedZigFiles(gpa, io, root);
- defer {
- for (paths) |path| gpa.free(path);
- gpa.free(paths);
- }
- std.mem.sort([]const u8, paths, {}, lessThanPath);
-
- var generated: std.Io.Writer.Allocating = .init(gpa);
- defer generated.deinit();
- try generated.writer.writeAll(
- \\// Generated by tools/embed_zig_sources.zig. Do not edit.
- \\pub const Source = struct { path: []const u8, contents: []const u8 };
- \\pub const all = [_]Source{
- \\
- );
-
- for (paths) |path| {
- const full_path = try std.Io.Dir.path.join(gpa, &.{ root, path });
- defer gpa.free(full_path);
- // Cached entries can still name a file moved or deleted without
- // staging it—an ordinary mid-edit state, and in a jj-colocated repo the
- // normal one until the change is exported. A path no longer on disk is
- // simply not a source to embed; failing the whole web build over it
- // means an unrelated refactor breaks a shell it never touched.
- const contents = std.Io.Dir.cwd().readFileAlloc(io, full_path, gpa, .limited(64 * 1024 * 1024)) catch |err| switch (err) {
- error.FileNotFound => continue,
- else => return err,
- };
- defer gpa.free(contents);
- try generated.writer.print(" .{{ .path = \"{f}\", .contents = \"{f}\" }},\n", .{
- std.zig.fmtString(path),
- std.zig.fmtString(contents),
- });
- }
- try generated.writer.writeAll("};\n");
-
- const output = if (std.Io.Dir.path.isAbsolute(output_path))
- try std.Io.Dir.createFileAbsolute(io, output_path, .{})
- else
- try std.Io.Dir.cwd().createFile(io, output_path, .{});
- defer output.close(io);
- try output.writeStreamingAll(io, generated.written());
-}
-
-/// Returns null only when Git cannot supply the working-tree source list.
-/// `--cached --others --exclude-standard` includes a newly-created module
-/// before it is staged but retains Git's ignore rules. Contents are read later;
-/// Git supplies only the path filter, never historical blobs.
-fn gitWorkingTreeZigFiles(
- gpa: std.mem.Allocator,
- io: std.Io,
- root: []const u8,
-) !?[][]const u8 {
- const result = std.process.run(gpa, io, .{
- .argv = &.{
- "git", "-C", root, "ls-files", "-z",
- "--cached", "--others", "--exclude-standard", "--", "*.zig",
- },
- .stdout_limit = .limited(16 * 1024 * 1024),
- .stderr_limit = .limited(1024 * 1024),
- }) catch return null;
- defer gpa.free(result.stdout);
- defer gpa.free(result.stderr);
- switch (result.term) {
- .exited => |code| if (code != 0) return null,
- else => return null,
- }
-
- var count: usize = 0;
- var count_it = std.mem.splitScalar(u8, result.stdout, 0);
- while (count_it.next()) |raw_path| {
- if (raw_path.len == 0 or !std.mem.endsWith(u8, raw_path, ".zig")) continue;
- count += 1;
- }
-
- const paths = try gpa.alloc([]const u8, count);
- errdefer gpa.free(paths);
- var index: usize = 0;
- errdefer for (paths[0..index]) |path| gpa.free(path);
- var it = std.mem.splitScalar(u8, result.stdout, 0);
- while (it.next()) |raw_path| {
- if (raw_path.len == 0 or !std.mem.endsWith(u8, raw_path, ".zig")) continue;
- paths[index] = try normalizedPath(gpa, raw_path);
- index += 1;
- }
- std.debug.assert(index == paths.len);
- return paths;
-}
-
-fn walkedZigFiles(
- gpa: std.mem.Allocator,
- io: std.Io,
- root: []const u8,
-) ![][]const u8 {
- var count: usize = 0;
- {
- var dir = if (std.Io.Dir.path.isAbsolute(root))
- try std.Io.Dir.openDirAbsolute(io, root, .{ .iterate = true })
- else
- try std.Io.Dir.cwd().openDir(io, root, .{ .iterate = true });
- defer dir.close(io);
- var walker = try dir.walk(gpa);
- defer walker.deinit();
-
- while (try walker.next(io)) |entry| {
- if (entry.kind == .directory and ignoredFallbackDir(entry.path)) {
- walker.leave(io);
- continue;
- }
- if ((entry.kind != .file and entry.kind != .sym_link) or !std.mem.endsWith(u8, entry.path, ".zig")) continue;
- count += 1;
- }
- }
-
- const paths = try gpa.alloc([]const u8, count);
- errdefer gpa.free(paths);
- var index: usize = 0;
- errdefer for (paths[0..index]) |path| gpa.free(path);
- var dir = if (std.Io.Dir.path.isAbsolute(root))
- try std.Io.Dir.openDirAbsolute(io, root, .{ .iterate = true })
- else
- try std.Io.Dir.cwd().openDir(io, root, .{ .iterate = true });
- defer dir.close(io);
- var walker = try dir.walk(gpa);
- defer walker.deinit();
-
- while (try walker.next(io)) |entry| {
- if (entry.kind == .directory and ignoredFallbackDir(entry.path)) {
- walker.leave(io);
- continue;
- }
- if ((entry.kind != .file and entry.kind != .sym_link) or !std.mem.endsWith(u8, entry.path, ".zig")) continue;
- paths[index] = try normalizedPath(gpa, entry.path);
- index += 1;
- }
- std.debug.assert(index == paths.len);
- return paths;
-}
-
-fn ignoredFallbackDir(path: []const u8) bool {
- var parts = std.mem.tokenizeAny(u8, path, "/\\");
- while (parts.next()) |part| {
- if (std.mem.eql(u8, part, ".git") or
- std.mem.eql(u8, part, ".zig-cache") or
- std.mem.eql(u8, part, "zig-cache") or
- std.mem.eql(u8, part, "zig-out") or
- std.mem.eql(u8, part, "zig-pkg")) return true;
- }
- return false;
-}
-
-fn normalizedPath(gpa: std.mem.Allocator, path: []const u8) ![]u8 {
- const copy = try gpa.dupe(u8, path);
- if (std.Io.Dir.path.sep != '/')
- std.mem.replaceScalar(u8, copy, std.Io.Dir.path.sep, '/');
- return copy;
-}
-
-fn lessThanPath(_: void, a: []const u8, b: []const u8) bool {
- return std.mem.order(u8, a, b) == .lt;
-}