diff options
56 files changed, 2906 insertions, 854 deletions
@@ -1,5 +1,5 @@ zig-pkg -zig-out +zig-out* .zig-cache/ .zig-cache/* assets/MapleMono-NF-Regular.ttf @@ -16,6 +16,7 @@ pub fn build(b: *std.Build) void { const optimize = if (is_emscripten) .ReleaseSmall else requested_optimize; const default_grammars: TreeSitterGrammars = if (is_emscripten) .minimal else .full; const tree_sitter_grammars = b.option(TreeSitterGrammars, "tree-sitter", "tree-sitter grammar set: disabled, minimal, full") orelse default_grammars; + const tracy = b.option([]const u8, "tracy", "enable Tracy profiling; supply the path to a Tracy source checkout"); // the browser shell: zig object + emcc link + html, installed to zig-out/web const web_step = b.step("web", "build the browser shell into zig-out/web (-Dplatform=web -Dtarget=wasm32-emscripten -Ddump=<dump.zon>)"); @@ -59,13 +60,41 @@ pub fn build(b: *std.Build) void { // static archives the emcc link needs beyond the zig object (grammars, SDL) var wasm_libs: std.ArrayList(std.Build.LazyPath) = .empty; + // 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) + root_mod.linkSystemLibrary("util", .{}); + const opts = b.addOptions(); opts.addOption(Platform, "platform", platform); opts.addOption(bool, "syntax_highlighting", tree_sitter_grammars != .disabled); opts.addOption(bool, "syntax_minimal_grammars", tree_sitter_grammars != .disabled); opts.addOption(bool, "syntax_full_grammars", tree_sitter_grammars == .full); + opts.addOption(bool, "enable_tracy", tracy != null); root_mod.addOptions("pardes_config", opts); + // Tracy zones (src/tracy.zig): compile the client into the binary only when + // -Dtracy=<path> names a Tracy checkout; otherwise every zone is a no-op. + // Sampling/callstacks/system tracing stay off: tracy's symbol worker + // SIGSEGVs on this binary's debug info, and its crash handler then parks + // every thread — the app wedges before the first frame. Zones don't need + // any of it. + if (tracy) |tracy_path| { + root_mod.addIncludePath(.{ .cwd_relative = tracy_path }); + root_mod.addCSourceFile(.{ + .file = .{ .cwd_relative = b.pathJoin(&.{ tracy_path, "public", "TracyClient.cpp" }) }, + .flags = &.{ + "-DTRACY_ENABLE=1", + "-DTRACY_NO_SAMPLING", + "-DTRACY_NO_CALLSTACK", + "-DTRACY_NO_SYSTEM_TRACING", + "-DTRACY_NO_CRASH_HANDLER", + "-DTRACY_NO_CODE_TRANSFER", + "-fno-sanitize=undefined", + }, + }); + root_mod.link_libcpp = true; + } + // tree-sitter: the zig bindings + C runtime, one static lib per grammar, // and each grammar's highlights.scm slurped at build time into the // ts_queries options module (codegen consumed by comptime in syntax.zig). @@ -171,7 +200,26 @@ pub fn build(b: *std.Build) void { }).module("vaxis"); var ghostty_vt_for_snap: ?*std.Build.Module = null; - if (b.lazyDependency("ghostty", .{ .simd = target.result.os.tag != .emscripten })) |dep| { + // ghostty's simd libs (simdutf/highway, C++) locate the Apple SDK via + // xcrun on darwin targets, so cross-compiling to macOS from elsewhere + // uses the scalar fallback (the same configuration the web shell ships). + // Native/cross builds hand ghostty the real target (it defaults to the + // host otherwise); the web path keeps its original no-target fetch, whose + // zig object never uses ghostty's artifacts. + // NOTE: darwin targets also need two one-line zig-0.16 fixes in the + // pinned ghostty (applied in the zig-pkg cache; re-apply after a fresh + // fetch, or bump the pin once upstream carries them): + // src/os/mach.zig — std.heap.next_mmap_addr_hint is gone (make the hint + // var module-local) and posix.mmap prot is now a packed struct + // (.{ .READ = true, .WRITE = true }); + // src/terminal/kitty/graphics_image.zig:185 — shm_open's variadic mode + // literal 0 must be @as(std.c.mode_t, 0). + const ghostty_simd = !target.result.os.tag.isDarwin() or b.graph.host.result.os.tag.isDarwin(); + const ghostty_dep = if (is_emscripten) + b.lazyDependency("ghostty", .{ .simd = false }) + else + b.lazyDependency("ghostty", .{ .target = target, .optimize = optimize, .simd = ghostty_simd }); + if (ghostty_dep) |dep| { const ghostty_vt = dep.module("ghostty-vt"); ghostty_vt_for_snap = ghostty_vt; ghostty_vt.addImport("uucode", uucode_mod); @@ -309,6 +357,8 @@ pub fn build(b: *std.Build) void { }), }); if (ghostty_vt_for_snap) |vt| snap.root_module.addImport("ghostty-vt", vt); + if (target.result.os.tag == .freebsd or target.result.os.tag == .netbsd or target.result.os.tag == .openbsd) + snap.root_module.linkSystemLibrary("util", .{}); b.installArtifact(snap); const run_snap = b.addRunArtifact(snap); run_snap.addArtifactArg(exe); diff --git a/next-steps.txt b/next-steps.txt new file mode 100644 index 00000000..09a48f08 --- /dev/null +++ b/next-steps.txt @@ -0,0 +1,19 @@ +- clean the workspace directory at .. (we may just leave a single directory (don'tmess with the old change)) +- after pardes exists on the tty, the tty should be clean and not left with any garbage (right now the spawner shell gets kinda broken) +- sometimes when I select something by mistake instead of clicking the editor crashes (this seems to happen only on paths?) +- during layout when opening or closing a pane it should only expand/split a single pane (it's chosen as a parent, child or something, the heuristic is just to be the closest one the most important thing is that it should't change the layout of the whole column) and right now there are some cases where this isn't the case. +- the tty platform renders highlighted text way slower than it should be (this is noticeable when scrolling), but the gui version doesn't seem to have this issue. make tracy tracing work and use the cli version of the tool to understand what's happening (the zig compiler also uses tracy so this might be as simple as adding some flag to build.zig or something). +- only on ghostty the middle mouse click doesn't work +- make pardes work on macos and other posix compliant targets +- mode indicators: three characters, uppercase +- the cursor's line number in the gutter gets a different bg/fg (tagline style) +- opening a file at a specific line centers the line if possible +- keyboard movement implements scroll_offset (vim/helix scrolloff) +- generalize n/N: look the next/prev tty line that yields a look result (search becomes a special case) +- dumps go to a per-user data dir (zig stdlib app-data path), not /tmp, with timestamped filenames so they never overwrite; new Restore builtin loads a dump file (first argument) +- horizontal scroll: no scrollbar, just horizontal mouse wheel + modal movements (scrolloff applies); minimal, goal is only to read the whole text +- cursor looks different in insert vs normal mode, in all pane types (tty and file); the tagline is always insert mode (normal makes no sense there) +- crash: drainEffects assert(ptys[sp.pane]==null) — spawn reusing a pane id whose old pty hasn't EOF'd yet +- initial layout: one pane, not three +- focusing a file at a line also moves the modal cursor to that line (not just the scroll) +- let's implement file searching, pardes philosophy is that what you do and the texts you read are sacred, so we don't want to implement file search with popups or information that will just dissapear. How I want you to do this is to: when I search something with / (in a text file, leave tty for later), we'll call grep -n on the current file with the search text. so far very simple, the neat thing is when I press n/N pardes will use the semantic tty access we have to select grep's result next line up or down and LOOK it (note we aren't introducing a new search concept or anything, just hooking modal editing, with semantic tty info from ghostty, and look semantics from acme). diff --git a/src/gui.zig b/src/gui.zig index 516a6b79..2653a056 100644 --- a/src/gui.zig +++ b/src/gui.zig @@ -1,6 +1,6 @@ //! The SDL3 GPU shell: owns an SDL window + event loop, translates SDL input //! into core events, performs the core's effects (fork ptys, write them, -//! resize them — same duties as tty.zig, this is also native linux), and +//! resize them — same duties as tty.zig, this is also native), and //! rasterizes the core's Surface: one instanced quad per cell, glyphs from an //! stb_truetype R8 atlas. Test modes: PARDES_TEST_GRID=1 is headless (no SDL, //! stdin escape sequences in, text grid frames out); PARDES_TEST=1 keeps the @@ -13,10 +13,11 @@ const std = @import("std"); const builtin = @import("builtin"); const posix = std.posix; -const linux = std.os.linux; +const libc = std.c; 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 look = @import("look.zig"); const is_emscripten = builtin.os.tag == .emscripten; @@ -34,6 +35,12 @@ extern "c" fn _exit(status: c_int) noreturn; extern "c" fn emscripten_get_element_css_size(target: [*:0]const u8, width: *f64, height: *f64) c_int; const EMSCRIPTEN_RESULT_SUCCESS: c_int = 0; +// absolute shell path per OS: execv must not search PATH (no allocation +// between fork and exec) +const bash_path: [*:0]const u8 = if (builtin.os.tag == .linux) "/usr/bin/bash" else "/bin/bash"; +// TIOCSWINSZ: absent from std.c.T on darwin — _IOW('t', 103, winsize) +const TIOCSWINSZ: c_int = @bitCast(@as(u32, if (@hasDecl(posix.T, "IOCSWINSZ")) posix.T.IOCSWINSZ else 0x80087467)); + const log = std.log.scoped(.gui); const font_ttf = @embedFile("AdwaitaMono-Regular.ttf"); @@ -271,9 +278,9 @@ fn normCell(norm: f32, win: f32, cell: f32) u16 { // ---- pty plumbing: reader threads feed a mutex-protected queue ---- -const Pty = struct { fd: c_int, pid: linux.pid_t }; +const Pty = struct { fd: c_int, pid: libc.pid_t }; -const Msg = union(enum) { output: struct { pane: u8, bytes: []u8 }, eof: u8 }; +const Msg = union(enum) { output: struct { pane: u8, gen: u32, bytes: []u8 }, eof: struct { pane: u8, gen: u32, fd: c_int } }; const Queue = struct { gpa: std.mem.Allocator, @@ -335,24 +342,23 @@ const Queue = struct { } }; -fn readPtyThread(gpa: std.mem.Allocator, fd: c_int, pane: u8, q: *Queue) void { +fn readPtyThread(gpa: std.mem.Allocator, fd: c_int, pane: u8, gen: u32, q: *Queue) void { var buf: [0x10000]u8 = undefined; while (true) { - const rc = linux.read(fd, &buf, buf.len); - const n: isize = @bitCast(rc); + const n = libc.read(fd, &buf, buf.len); if (n < 0) { - if (n == -@as(isize, @intFromEnum(linux.E.INTR))) continue; + if (libc.errno(n) == .INTR) continue; break; // EIO when the child exits: treat as EOF } if (n == 0) break; const bytes = gpa.dupe(u8, buf[0..@intCast(n)]) catch break; - q.push(.{ .output = .{ .pane = pane, .bytes = bytes } }); + q.push(.{ .output = .{ .pane = pane, .gen = gen, .bytes = bytes } }); } - q.push(.{ .eof = pane }); + q.push(.{ .eof = .{ .pane = pane, .gen = gen, .fd = fd } }); } -fn spawnReader(gpa: std.mem.Allocator, pt: Pty, pane: u8, q: *Queue) void { - const th = std.Thread.spawn(.{}, readPtyThread, .{ gpa, pt.fd, pane, q }) catch return; +fn spawnReader(gpa: std.mem.Allocator, pt: Pty, pane: u8, gen: u32, q: *Queue) void { + const th = std.Thread.spawn(.{}, readPtyThread, .{ gpa, pt.fd, pane, gen, q }) catch return; th.detach(); } @@ -621,8 +627,11 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options) !void { writeFile(pardes.bash_rc); 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) + var gens: [pardes.MAX_PANES]u32 = @splat(0); defer for (&ptys) |*slot| if (slot.*) |pt| { - _ = linux.close(pt.fd); + _ = libc.close(pt.fd); slot.* = null; }; var queue: Queue = .{ .gpa = gpa, .sdl_wake = true }; @@ -630,8 +639,8 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options) !void { // initial spawns BEFORE any worker thread exists: forkpty from a // multithreaded process can wedge the child before exec (see tty.zig). - drainEffects(core, &ptys, gpa, &queue, &g, false); - for (&ptys, 0..) |*slot, id| if (slot.*) |pt| spawnReader(gpa, pt, @intCast(id), &queue); + drainEffects(core, &ptys, &gens, gpa, &queue, &g, false); + for (&ptys, 0..) |*slot, id| if (slot.*) |pt| spawnReader(gpa, pt, @intCast(id), gens[id], &queue); _ = c.SDL_StartTextInput(window); @@ -657,22 +666,23 @@ fn runNative(init: std.process.Init, opts_in: pardes.Options) !void { var msgs = queue.take(); for (msgs.items) |m| switch (m) { .output => |o| { - core.update(.{ .output = .{ .pane = o.pane, .bytes = o.bytes } }); + if (gens[o.pane] == o.gen) + core.update(.{ .output = .{ .pane = o.pane, .bytes = o.bytes } }); gpa.free(o.bytes); }, - .eof => |id| { - if (ptys[id]) |pt| { - _ = linux.close(pt.fd); - ptys[id] = null; + .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 } }); } - core.update(.{ .eof = .{ .pane = id } }); }, }; msgs.deinit(gpa); // 3. steamdeck: poll gamepad axes into virtual cursor / wheel events pollGamepad(&g, core); // 4. effects - drainEffects(core, &ptys, gpa, &queue, &g, true); + drainEffects(core, &ptys, &gens, gpa, &queue, &g, true); if (core.quit) break; // 5. live cwd for tags/look: cheap /proc readlink per pane, per frame pollCwds(core, &ptys); @@ -894,14 +904,17 @@ fn runGrid(init: std.process.Init, opts_in: pardes.Options) !void { writeFile(pardes.bash_rc); 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) + var gens: [pardes.MAX_PANES]u32 = @splat(0); defer for (&ptys) |*slot| if (slot.*) |pt| { - _ = linux.close(pt.fd); + _ = libc.close(pt.fd); slot.* = null; }; var queue: Queue = .{ .gpa = gpa, .sdl_wake = false }; defer queue.close(); - drainEffects(core, &ptys, gpa, &queue, null, false); - for (&ptys, 0..) |*slot, id| if (slot.*) |pt| spawnReader(gpa, pt, @intCast(id), &queue); + drainEffects(core, &ptys, &gens, gpa, &queue, null, false); + for (&ptys, 0..) |*slot, id| if (slot.*) |pt| spawnReader(gpa, pt, @intCast(id), gens[id], &queue); setStdinRaw() catch {}; // stdin may be a pipe, not a pty — best effort @@ -921,21 +934,22 @@ fn runGrid(init: std.process.Init, opts_in: pardes.Options) !void { var msgs = queue.take(); for (msgs.items) |m| switch (m) { .output => |o| { - core.update(.{ .output = .{ .pane = o.pane, .bytes = o.bytes } }); + if (gens[o.pane] == o.gen) + core.update(.{ .output = .{ .pane = o.pane, .bytes = o.bytes } }); gpa.free(o.bytes); n_events += 1; }, - .eof => |id| { - if (ptys[id]) |pt| { - _ = linux.close(pt.fd); - ptys[id] = null; + .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 } }); } - core.update(.{ .eof = .{ .pane = id } }); n_events += 1; }, }; msgs.deinit(gpa); - drainEffects(core, &ptys, gpa, &queue, null, true); + drainEffects(core, &ptys, &gens, gpa, &queue, null, true); pollCwds(core, &ptys); if (n_events == 0) continue; // idle tick: nothing changed, no frame _ = frame_arena.reset(.retain_capacity); @@ -981,8 +995,7 @@ const StdinFeed = struct { if ((fds[0].revents & (posix.POLL.HUP | posix.POLL.ERR)) != 0) out.eof = true; return out; } - const rc = linux.read(0, f.buf[f.fill..].ptr, f.buf.len - f.fill); - const rn: isize = @bitCast(rc); + const rn = libc.read(0, f.buf[f.fill..].ptr, f.buf.len - f.fill); if (rn < 0) return out; if (rn == 0) { out.eof = true; @@ -1413,6 +1426,7 @@ fn pollGamepad(g: *Gui, core: *pardes.Pardes) void { fn drainEffects( core: *pardes.Pardes, ptys: *[pardes.MAX_PANES]?Pty, + gens: *[pardes.MAX_PANES]u32, gpa: std.mem.Allocator, queue: *Queue, g: ?*Gui, // null in grid test mode (no SDL: clipboard effects are no-ops) @@ -1420,7 +1434,15 @@ fn drainEffects( ) void { while (core.nextEffect()) |effect| switch (effect) { .spawn => |sp| { - std.debug.assert(ptys[sp.pane] == null); + // 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; @@ -1433,13 +1455,8 @@ fn drainEffects( ptys[sp.pane] = pt; // report the pane's starting directory back to the core (tags) var lbuf: [1024]u8 = undefined; - var pbuf: [64]u8 = undefined; - if (std.fmt.bufPrintSentinel(&pbuf, "/proc/{d}/cwd", .{pt.pid}, 0) catch null) |path| { - const rc = linux.readlinkat(linux.AT.FDCWD, path, &lbuf, lbuf.len); - const n: isize = @bitCast(rc); - if (n > 0) core.setCwd(sp.pane, lbuf[0..@intCast(n)]); - } - if (threads_ok) spawnReader(gpa, pt, sp.pane, queue); + 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()); @@ -1447,7 +1464,7 @@ fn drainEffects( .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, posix.T.IOCSWINSZ, @intFromPtr(&ws)); + _ = posix.system.ioctl(pt.fd, TIOCSWINSZ, @intFromPtr(&ws)); } }, .open_link => {}, // native: look opens panes instead; nothing to launch @@ -1458,21 +1475,17 @@ fn drainEffects( if (f.path.len >= pathbuf.len) continue; @memcpy(pathbuf[0..f.path.len], f.path); pathbuf[f.path.len] = 0; - const rc = linux.open(pathbuf[0..f.path.len :0], .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, 0o644); - const sfd: isize = @bitCast(rc); - if (sfd < 0) continue; - const fd: c_int = @intCast(sfd); + 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); - _ = linux.close(fd); + _ = libc.close(fd); }, .write_dump => { const out = core.dump_out orelse continue; - const rc = linux.open(pardes.dump.default_path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, 0o644); - const sfd: isize = @bitCast(rc); - if (sfd < 0) continue; - const fd: c_int = @intCast(sfd); + const fd = libc.open(pardes.dump.default_path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); + if (fd < 0) continue; writeFd(fd, out); - _ = linux.close(fd); + _ = libc.close(fd); }, .set_clipboard => { if (g == null) continue; @@ -1500,8 +1513,8 @@ fn forkShell(cwd: ?[*:0]const u8, rows: u16, cols: u16) Pty { const pid = forkpty(&master, null, null, &ws); if (pid == 0) { if (cwd) |cd| _ = chdir(cd); - const argv: [4:null]?[*:0]const u8 = .{ "/usr/bin/bash", "--rcfile", "/tmp/pardes-osc133.bash", null }; - _ = execv("/usr/bin/bash", &argv); + const argv: [4:null]?[*:0]const u8 = .{ bash_path, "--rcfile", "/tmp/pardes-osc133.bash", null }; + _ = execv(bash_path, &argv); _exit(127); } return .{ .fd = master, .pid = pid }; @@ -1510,11 +1523,7 @@ fn forkShell(cwd: ?[*:0]const u8, rows: u16, cols: u16) Pty { fn pollCwds(core: *pardes.Pardes, ptys: *[pardes.MAX_PANES]?Pty) void { for (ptys, 0..) |slot, id| if (slot) |pt| { var lbuf: [1024]u8 = undefined; - var pbuf: [64]u8 = undefined; - const path = std.fmt.bufPrintSentinel(&pbuf, "/proc/{d}/cwd", .{pt.pid}, 0) catch continue; - const rc = linux.readlinkat(linux.AT.FDCWD, path, &lbuf, lbuf.len); - const n: isize = @bitCast(rc); - if (n > 0) core.setCwd(id, lbuf[0..@intCast(n)]); + if (look.shellCwd(pt.pid, &lbuf)) |cwd| core.setCwd(id, cwd); }; } @@ -2073,11 +2082,9 @@ fn writeCapturePpm(g: *Gui, gpa: std.mem.Allocator, pixels: []const u8, width: u const tmp_path = std.fmt.bufPrintSentinel(&tmp_buf, "{s}/latest.ppm.tmp", .{g.capture_dir}, 0) catch return error.CapturePathTooLong; const final_path = std.fmt.bufPrintSentinel(&final_buf, "{s}/latest.ppm", .{g.capture_dir}, 0) catch return error.CapturePathTooLong; - const orc = linux.open(tmp_path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, 0o644); - const sfd: isize = @bitCast(orc); - if (sfd < 0) return error.CaptureWriteFailed; - const fd: c_int = @intCast(sfd); - defer _ = linux.close(fd); + const fd = libc.open(tmp_path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); + if (fd < 0) return error.CaptureWriteFailed; + defer _ = libc.close(fd); var header: [64]u8 = undefined; const hdr = std.fmt.bufPrint(&header, "P6\n{d} {d}\n255\n", .{ width, height }) catch return error.CaptureWriteFailed; @@ -2096,9 +2103,7 @@ fn writeCapturePpm(g: *Gui, gpa: std.mem.Allocator, pixels: []const u8, width: u } writeFd(fd, row_rgb); } - const rrc = linux.rename(tmp_path, final_path); - const rs: isize = @bitCast(rrc); - if (rs < 0) return error.CaptureWriteFailed; + if (libc.rename(tmp_path, final_path) != 0) return error.CaptureWriteFailed; } // ===================================================================== @@ -2377,21 +2382,18 @@ fn envU16(env: *std.process.Environ.Map, name: []const u8) ?u16 { } fn writeFile(data: []const u8) void { - const rc = linux.open("/tmp/pardes-osc133.bash", .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, 0o644); - const sfd: isize = @bitCast(rc); - if (sfd < 0) return; - const fd: c_int = @intCast(sfd); - defer _ = linux.close(fd); + const fd = libc.open("/tmp/pardes-osc133.bash", .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); + if (fd < 0) return; + defer _ = libc.close(fd); writeFd(fd, data); } fn writeFd(fd: c_int, data: []const u8) void { var off: usize = 0; while (off < data.len) { - const rc = linux.write(fd, data[off..].ptr, data.len - off); - const n: isize = @bitCast(rc); + const n = libc.write(fd, data[off..].ptr, data.len - off); if (n < 0) { - if (n == -@as(isize, @intFromEnum(linux.E.INTR))) continue; + if (libc.errno(n) == .INTR) continue; return; } off += @intCast(n); diff --git a/src/look.zig b/src/look.zig index 67fbf8c5..8744da24 100644 --- a/src/look.zig +++ b/src/look.zig @@ -8,7 +8,8 @@ //! web — there is no filesystem; only URLs mean anything, and a URL //! opens in a new tab (the open_link effect). const std = @import("std"); -const linux = std.os.linux; +const builtin = @import("builtin"); +const libc = std.c; const pardes = @import("pardes.zig"); extern "c" fn realpath(path: [*:0]const u8, resolved: [*]u8) ?[*:0]u8; @@ -88,10 +89,9 @@ const platform_has_fs = switch (pardes.platform) { /// true if `path` exists and is a directory (open(O_DIRECTORY), no stat needed) fn isDir(path: [*:0]const u8) bool { - const rc = linux.open(path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true, .CLOEXEC = true }, 0); - const sfd: isize = @bitCast(rc); - if (sfd < 0) return false; - _ = linux.close(@intCast(sfd)); + const fd = libc.open(path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true, .CLOEXEC = true }); + if (fd < 0) return false; + _ = libc.close(fd); return true; } @@ -101,19 +101,16 @@ pub fn readFile(gpa: std.mem.Allocator, path: []const u8) ![]u8 { if (!platform_has_fs) return error.NoFilesystem; var pathbuf: [4096]u8 = undefined; const path_z = std.fmt.bufPrintSentinel(&pathbuf, "{s}", .{path}, 0) catch return error.PathTooLong; - const rc = linux.open(path_z, .{ .ACCMODE = .RDONLY }, 0); - const sfd: isize = @bitCast(rc); - if (sfd < 0) return error.OpenFailed; - const fd: i32 = @intCast(sfd); - defer _ = linux.close(fd); + const fd = libc.open(path_z, .{ .ACCMODE = .RDONLY }); + if (fd < 0) return error.OpenFailed; + defer _ = libc.close(fd); var buf: std.ArrayList(u8) = .empty; errdefer buf.deinit(gpa); var chunk: [16384]u8 = undefined; while (true) { - const r = linux.read(fd, &chunk, chunk.len); - const n: isize = @bitCast(r); + const n = libc.read(fd, &chunk, chunk.len); if (n < 0) { - if (n == -@as(isize, @intFromEnum(linux.E.INTR))) continue; + if (libc.errno(n) == .INTR) continue; return error.ReadFailed; } if (n == 0) break; @@ -121,3 +118,44 @@ pub fn readFile(gpa: std.mem.Allocator, path: []const u8) ![]u8 { } return buf.toOwnedSlice(gpa); } + +// ---- shell cwd: what directory a pane's looks resolve against ---- + +// macOS has no /proc; libproc's proc_pidinfo(PROC_PIDVNODEPATHINFO) yields the +// cwd vnode path. Not in std.c — layout from xnu's sys/proc_info.h. +const vnode_info_path = extern struct { + vi: [152]u8 align(8), // struct vnode_info: vinfo_stat + type + pad + fsid + path: [1024]u8, // MAXPATHLEN +}; +const proc_vnodepathinfo = extern struct { + cdir: vnode_info_path, + rdir: vnode_info_path, +}; +const PROC_PIDVNODEPATHINFO: c_int = 9; +extern "c" fn proc_pidinfo(pid: c_int, flavor: c_int, arg: u64, buffer: *anyopaque, buffersize: c_int) c_int; + +/// Live cwd of a shell process (pane tags, look resolution). linux reads +/// /proc/<pid>/cwd, darwin asks libproc; other POSIX systems have no cheap +/// answer — return null and panes keep their spawn-time cwd (callers already +/// tolerate failure: dead shells have no cwd either). +pub fn shellCwd(pid: libc.pid_t, buf: *[1024]u8) ?[]const u8 { + switch (builtin.os.tag) { + .linux => { + var pbuf: [64]u8 = undefined; + const path = std.fmt.bufPrintSentinel(&pbuf, "/proc/{d}/cwd", .{pid}, 0) catch return null; + const n = libc.readlink(path, buf, buf.len); + if (n <= 0) return null; + return buf[0..@intCast(n)]; + }, + .macos, .ios, .tvos, .watchos, .visionos => { + var info: proc_vnodepathinfo = undefined; + const n = proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &info, @sizeOf(proc_vnodepathinfo)); + if (n < @as(c_int, @sizeOf(proc_vnodepathinfo))) return null; + const path = std.mem.sliceTo(&info.cdir.path, 0); + if (path.len == 0) return null; + @memcpy(buf[0..path.len], path); + return buf[0..path.len]; + }, + else => return null, + } +} diff --git a/src/pardes.zig b/src/pardes.zig index c4893b25..7fe4d95f 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -14,6 +14,7 @@ const uucode = @import("uucode"); const modal = @import("modal.zig"); const look = @import("look.zig"); const syntax = @import("syntax.zig"); +const tracy = @import("tracy.zig"); pub const image = @import("image.zig"); pub const dump = @import("dump.zig"); @@ -31,6 +32,9 @@ pub const BOX_H: u16 = 1; pub const MINW: u16 = 10; pub const MINH: u16 = 3; pub const PREFIX_W: u16 = 5; +/// vim 'scrolloff': keyboard cursor moves keep this many context rows visible +/// above/below the cursor (clamped at file boundaries and short panes) +const scroll_off = 3; pub const topbar_str = "Kill Newcol Tutor Debug Colors NextColor Dump"; const pane_builtins_str = "Del"; @@ -462,6 +466,14 @@ pub const Pane = struct { vsel: CharSel = .{}, /// one pending prefix codepoint (0 = none): `g` and `z` pending: u21 = 0, + /// `/` file search: the pattern is typed into the tag tail (no popup); + /// search_at is the tail length before " /" was appended (submit/cancel + /// restore it). n/N walk the grep results in pane search_pane, starting + /// just below search_row (the results shell's prompt row at submit). + search_edit: bool = false, + search_at: u16 = 0, + search_pane: ?usize = null, + search_row: i32 = 0, /// the editable tag tail: seeded with the default builtins on first touch; /// edited in place by a modal one-line editor sharing the pane's mode tag_tail: std.ArrayList(u8) = .empty, @@ -523,9 +535,19 @@ pub const Pane = struct { } fn ensureCursorVisible(pane: *Pane) void { + // scrolloff margin, shrunk on short panes so the band stays non-empty + const margin: i32 = @min(scroll_off, @divTrunc(@as(i32, pane.rows) - 1, 2)); const off = pane.scroll(); const last = off + @as(i32, pane.rows) - 1; - if (pane.cur_row < off) pane.scrollBy(pane.cur_row - off) else if (pane.cur_row > last) pane.scrollBy(pane.cur_row - last); + if (pane.cur_row < off + margin) { + pane.scrollBy(pane.cur_row - margin - off); // scrollBy clamps at line 0 + } else if (pane.cur_row > last - margin) { + // don't scroll a file past EOF-at-bottom-row (vim's bottom clamp); + // terminals overshoot harmlessly — the vt clamps at the live bottom + var to = pane.cur_row + margin; + if (pane.file) |f| to = @min(to, @as(i32, @intCast(modal.lineCount(f.content) -| 1))); + pane.scrollBy(@max(0, to - last)); + } } /// the last navigable row: file -> last content line; terminal -> viewport bottom @@ -628,9 +650,11 @@ pub const Pardes = struct { /// press during an active middle select-drag; consumed on middle release chord_arg: ?[]u8 = null, - effects: [64]Effect = undefined, + /// pending effects, drained by the shell after each update. Growable: one + /// update can emit unbounded writes (a big selection executed is chunked + /// into 64-byte write effects) — a fixed ring overflows and panics. + effects: std.ArrayList(Effect) = .empty, effects_head: usize = 0, - effects_tail: usize = 0, /// modal yank register (gpa-owned); a yank also mirrors out to the system /// clipboard via the set_clipboard effect. @@ -678,6 +702,7 @@ pub const Pardes = struct { if (p.yank) |y| gpa.free(y); if (p.dump_out) |d| gpa.free(d); if (p.chord_arg) |a| gpa.free(a); + p.effects.deinit(gpa); p.scratch.deinit(); gpa.free(p.surface.cells); gpa.destroy(p); @@ -717,6 +742,7 @@ pub const Pardes = struct { fn newShell(p: *Pardes, id: usize, cwd: []const u8) !*Pane { std.debug.assert(p.panes[id] == null); + if (cwd.len > 256) return error.PathTooLong; // spawn effect cwd is a Buf(256) const pane = try p.gpa.create(Pane); pane.* = .{ .vt = try ghostty_vt.Terminal.init(p.gpa, .{ @@ -780,14 +806,16 @@ pub const Pardes = struct { } fn emit(p: *Pardes, e: Effect) void { - std.debug.assert(p.effects_tail - p.effects_head < p.effects.len); - p.effects[p.effects_tail % p.effects.len] = e; - p.effects_tail += 1; + p.effects.append(p.gpa, e) catch {}; } pub fn nextEffect(p: *Pardes) ?Effect { - if (p.effects_head == p.effects_tail) return null; - const e = p.effects[p.effects_head % p.effects.len]; + if (p.effects_head == p.effects.items.len) { + p.effects.clearRetainingCapacity(); + p.effects_head = 0; + return null; + } + const e = p.effects.items[p.effects_head]; p.effects_head += 1; return e; } @@ -840,13 +868,13 @@ pub const Pardes = struct { return std.fmt.allocPrint(arena, "img {s} Petscii {s} Ascii {s}", .{ iv.path, mode, pane_builtins_str }); } if (pane.file) |f| { - const fmode = if (pane.mode == .insert) "in" else "nm"; + const fmode = if (pane.mode == .insert) "INS" else "NOR"; return std.fmt.allocPrint(arena, "{s} {s}", .{ fmode, f.path }); } const mode = switch (pane.mode) { - .normal => "nm", - .insert => "in", - .tty => "sy", + .normal => "NOR", + .insert => "INS", + .tty => "TTY", }; return std.fmt.allocPrint(arena, "{s} {s}", .{ mode, pane.cwdSlice() }); } @@ -878,6 +906,7 @@ pub const Pardes = struct { fn exitTagEdit(pane: *Pane) void { pane.tag_edit = false; pane.tag_sel = false; + pane.search_edit = false; // an abandoned `/` input stays as tag text } fn tagSelBounds(pane: *Pane) struct { lo: usize, hi: usize } { @@ -1145,12 +1174,14 @@ pub const Pardes = struct { nt.greet = true; const f = p.layoutFindTerm(p.active).?; p.layoutInsert(f.col, f.idx + 1, free); + p.splitBelow(p.active, nt); p.active = free; return; } if (key.alt and !key.ctrl and key.cp == 'c') { const f = p.layoutFindTerm(p.active).?; if (p.ncol < MAX_COLS and p.col_n[f.col] > 1) { + p.absorbVWeight(p.active); p.layoutRemove(p.active); p.layoutAppendColumn(p.active); } @@ -1165,6 +1196,16 @@ pub const Pardes = struct { } else p.enterTty(p.active); return; } + // `/` search input in flight: Enter greps, Esc abandons; both restore + // the tag tail and hand focus back to the body. + if (pane.search_edit and (is(key, Key.enter) or is(key, Key.escape))) { + if (is(key, Key.enter)) p.submitSearch(pane); + pane.tag_tail.shrinkRetainingCapacity(@min(pane.search_at, pane.tag_tail.items.len)); + exitTagEdit(pane); + pane.mode = .normal; + pane.pending = 0; + return; + } // normal-mode Enter/Tab: the acme chords — look at (Enter) or execute // (Tab) the modal selection, else the file-ish word under the cursor // (on the tag tail when it's focused for editing, else the body). @@ -1522,6 +1563,129 @@ pub const Pardes = struct { if (is(key, 'y')) return p.normalYank(pane); if (is(key, 'u')) return p.doUndo(pane); if (is(key, 'U')) return p.doRedo(pane); + // file search: `/` types a pattern into the tag, n/N walk the results + if (pane.file != null and is(key, '/')) return p.startSearch(pane); + if (pane.file != null and is(key, 'n')) return p.searchStep(pane, 1); + if (pane.file != null and is(key, 'N')) return p.searchStep(pane, -1); + // terminal n/N: look the next/previous output row that looks somewhere + if (pane.isTerminal() and is(key, 'n')) return p.lookStep(pane, pl, 1); + if (pane.isTerminal() and is(key, 'N')) return p.lookStep(pane, pl, -1); + } + + // ---- file search (`/` + n/N): grep into a shell pane, look the results ---- + + /// `/` on a file pane: type the pattern into the tag tail after a " /" + /// marker — the existing modal one-line editor, visible while typing, + /// nothing that disappears. Enter/Esc are intercepted in handleKey. + fn startSearch(p: *Pardes, pane: *Pane) void { + if (!pane.tag_init) { + pane.tag_tail.appendSlice(p.gpa, file_pane_tail) catch return; + pane.tag_init = true; + } + pane.search_at = @intCast(pane.tag_tail.items.len); + pane.tag_tail.appendSlice(p.gpa, " /") catch return; + pane.search_edit = true; + pane.tag_edit = true; + pane.tag_sel = false; + pane.mode = .insert; + pane.pending = 0; + pane.tag_col = @intCast(pane.tag_tail.items.len); + } + + /// Enter on a `/` input: run `grep -nH '<pat>' <path>` in a shell in the + /// file's directory (the same path middle-click send takes), so the + /// results are ordinary persistent terminal text. Remember the results + /// pane and start n/N below its current prompt row. + fn submitSearch(p: *Pardes, pane: *Pane) void { + const f = pane.file orelse return; + const tail = pane.tag_tail.items; + const pat = std.mem.trim(u8, tail[@min(@as(usize, pane.search_at) + 2, tail.len)..], " \t\r\n"); + if (pat.len == 0) return; + const arena = p.scratch.allocator(); + var cmd: std.ArrayList(u8) = .empty; + cmd.appendSlice(arena, "grep -nH '") catch return; + for (pat) |ch| { + if (ch == '\'') cmd.appendSlice(arena, "'\\''") catch return else cmd.append(arena, ch) catch return; + } + cmd.appendSlice(arena, "' '") catch return; + cmd.appendSlice(arena, f.path) catch return; + cmd.append(arena, '\'') catch return; + const dst = p.ttyForDir(std.fs.path.dirname(f.path) orelse "/") orelse return; + const rp = p.panes[dst] orelse return; + p.padOutputBelowEdits(dst); + p.emitWrite(dst, cmd.items); + p.emitWrite(dst, "\r"); + pane.search_pane = dst; + // absolute row of the shell's cursor (the prompt echoing the grep); + // results land below it, so n scans from there — older output and + // stale results of a previous search stay behind + const sb = rp.vt.screens.active.pages.scrollbar(); + pane.search_row = @intCast(sb.total -| rp.rows + rp.vt.screens.active.cursor.y); + } + + /// n/N: select the next/previous grep result row in the results pane and + /// look it. Result rows read `path:NNN:...` and are found by their path + /// prefix; prompt/echo rows are already blanked by paneCursorLines (the + /// OSC 133 semantic row marks), so only real output is walked. + fn searchStep(p: *Pardes, pane: *Pane, delta: i32) void { + const f = pane.file orelse return; + const rid = pane.search_pane orelse return; + const rp = p.panes[rid] orelse return; + if (!rp.isTerminal()) return; + const pl = p.paneCursorLines(rp) catch return; + const nrows: i32 = @intCast(pl.lines.len); + var r = pane.search_row + delta; + while (r >= 0 and r < nrows) : (r += delta) { + const ln = pl.lines[@intCast(r)]; + if (!std.mem.startsWith(u8, ln, f.path) or ln.len <= f.path.len or ln[f.path.len] != ':') continue; + pane.search_row = r; + // select the result line in the results pane and keep it in view + rp.msel = .{ .active = true, .r0 = r, .r1 = r }; + rp.vsel.active = false; + rp.cur_row = r; + rp.cur_col = 0; + rp.cur_off = 0; + rp.cur_pinned = true; + rp.ensureCursorVisible(); + // look the leading file-ish word (path:NNN:) — the ordinary look + // path scrolls this file pane to the line + var hi: usize = 0; + while (hi < ln.len and look.isFileChar(ln[hi])) hi += 1; + p.actOnSelection(.right, rid, ln[0..hi], null); + return; + } + // no result that way (or none at all): nowhere to go, stay put + } + + /// n/N on a terminal pane (normal mode): select the next/previous output + /// row whose leading file-ish word looks somewhere — resolves to a + /// file/dir/path:NNN exactly as a right click would — and look it. The + /// scan only resolves (realpath, no pane opens, no scrolls); the one + /// chosen row gets the real look. The modal cursor is the position, so + /// the walk continues from wherever j/k left it. The look may focus what + /// it opened; focus comes back here so the next n keeps stepping. + fn lookStep(p: *Pardes, pane: *Pane, pl: PaneLines, delta: i32) void { + const id = p.active; + const nrows: i32 = @intCast(pl.lines.len); + var realbuf: [4096]u8 = undefined; + var r = pane.cur_row + delta; + while (r >= 0 and r < nrows) : (r += delta) { + const ln = pl.lines[@intCast(r)]; + var hi: usize = 0; + while (hi < ln.len and look.isFileChar(ln[hi])) hi += 1; + if (hi == 0 or look.resolve(ln[0..hi], pane.cwdSlice(), &realbuf) == .none) continue; + pane.msel = .{ .active = true, .r0 = r, .r1 = r }; + pane.vsel.active = false; + pane.cur_row = r; + pane.cur_col = 0; + pane.cur_off = 0; + pane.cur_pinned = true; + pane.ensureCursorVisible(); + p.actOnSelection(.right, id, ln[0..hi], null); + p.active = id; + return; + } + // nothing lookable that way: stay put } const InsertAt = enum { at, append, line_start, line_end, open_below, open_above }; @@ -2433,29 +2597,49 @@ pub const Pardes = struct { p.ncol += 1; } - /// Hand a dying pane's vertical weight to ONE sibling (the pane above, or - /// below for the topmost) so the rest of the column keeps its sizes — the - /// deletion mirror of splitBelow. Call while `id` is still in the layout. + /// Snap every pane in column `c` to its on-screen row count so later + /// weight edits move ONLY the panes they name: computeGeom rounds + /// round(avail*w/vsum) per pane, and with fractional weights a split or + /// absorb elsewhere in the column can jiggle a bystander by a row. + fn snapColWeights(p: *Pardes, c: usize) void { + for (0..p.col_n[c]) |k| { + const pid = p.col_terms[c][k]; + if (p.panes[pid]) |pp| pp.vweight = @floatFromInt(@max(1, p.rects[pid].h)); + } + } + + /// Hand a dying pane's rows to ONE sibling (the pane above, or below for + /// the topmost) so the rest of the column keeps its sizes bit-identical — + /// the deletion mirror of splitBelow. Call while `id` is still in the + /// layout, with rects current. fn absorbVWeight(p: *Pardes, id: usize) void { const f = p.layoutFindTerm(id) orelse return; if (p.col_n[f.col] <= 1) return; - const gone = p.panes[id] orelse return; + p.snapColWeights(f.col); const sib = if (f.idx > 0) p.col_terms[f.col][f.idx - 1] else p.col_terms[f.col][f.idx + 1]; - if (p.panes[sib]) |s| s.vweight += gone.vweight; + if (p.panes[sib]) |s| s.vweight += @as(f32, @floatFromInt(@max(1, p.rects[id].h))); } /// Open a window BELOW `src` (acme-style) without rebalancing the column: /// shrink ONLY src to its content height (cursor row kept visible) and hand - /// the freed rows to `nw` — together they fill src's old slot. + /// the freed rows to `nw` — together they fill src's old slot and the other + /// panes keep their sizes bit-identical (weights snap to row counts). fn splitBelow(p: *Pardes, src_id: usize, nw: *Pane) void { const src = p.panes[src_id] orelse return; const src_h = p.rects[src_id].h; const body: u16 = if (src_h > BOX_H) src_h - BOX_H else 1; const cur: u16 = if (src.file != null) body / 2 else @as(u16, @intCast(src.vt.screens.active.cursor.y)) + 1; - const keep = std.math.clamp(cur, 1, @max(1, body -| 1)); - const w = src.vweight; - src.vweight = w * @as(f32, @floatFromInt(BOX_H + keep)) / @as(f32, @floatFromInt(src_h)); - nw.vweight = w - src.vweight; + // cap keep so a content-full source still leaves the new pane a tag + + // a few body rows (an Alt-n from a full shell was born 0 rows tall) + const keep = std.math.clamp(cur, 1, @max(1, body -| (BOX_H + 3))); + if (p.layoutFindTerm(src_id)) |f| for (0..p.col_n[f.col]) |k| { + const pid = p.col_terms[f.col][k]; + if (p.panes[pid]) |pp| if (pp != nw) { + pp.vweight = @floatFromInt(@max(1, p.rects[pid].h)); + }; + }; + src.vweight = @floatFromInt(BOX_H + keep); + nw.vweight = @floatFromInt(@max(1, src_h -| (BOX_H + keep))); } /// a shell nobody has touched: no typing, cursor on the first prompt line, @@ -2482,6 +2666,7 @@ pub const Pardes = struct { if (n_tty != 1) return; const tt = p.panes[tty_id] orelse return; if (!isPristineTty(tt)) return; + p.computeGeom(); // a just-stacked doc has no rect yet; absorb snaps to rows p.absorbVWeight(tty_id); p.layoutRemove(tty_id); p.deinitPane(tt); @@ -2501,6 +2686,7 @@ pub const Pardes = struct { const nt = p.newShell(free, dir) catch return null; nt.greet = false; const rc = if (p.ncol > 0) p.ncol - 1 else 0; + if (p.col_n[rc] > 0) p.splitBelow(p.col_terms[rc][p.col_n[rc] - 1], nt); p.layoutInsert(rc, p.col_n[rc], free); return free; } @@ -2558,18 +2744,17 @@ pub const Pardes = struct { } /// stack a fresh doc pane at the top of the LEFT column (acme convention: - /// files left, terminals right) with a fair share, then evict a leftover - /// pristine shell + /// files left, terminals right), halving ONLY the old top pane's slot so + /// the rest of the column keeps its sizes; then evict a leftover pristine + /// shell fn stackDocLeft(p: *Pardes, free: usize, nt: *Pane) void { const lc = 0; - const ln = p.col_n[lc]; - if (ln > 0) { - var vsum: f32 = 0; - for (0..ln) |i| if (p.panes[p.col_terms[lc][i]]) |pp| { - vsum += pp.vweight; - }; - nt.vweight = vsum / @as(f32, @floatFromInt(ln)); - } + if (p.col_n[lc] > 0) if (p.panes[p.col_terms[lc][0]]) |top| { + p.snapColWeights(lc); + const h = p.rects[p.col_terms[lc][0]].h; + nt.vweight = @floatFromInt(@max(1, h / 2)); + top.vweight = @floatFromInt(@max(1, h -| h / 2)); + }; p.layoutInsert(lc, 0, free); p.active = free; p.evictLonePristineTty(lc, free); @@ -2607,7 +2792,7 @@ pub const Pardes = struct { }; switch (look.resolve(txt, cwd, &realbuf)) { .none => {}, - .url => |u| p.emit(.{ .open_link = .from(u) }), + .url => |u| if (u.len <= 256) p.emit(.{ .open_link = .from(u) }), .dir => |dir| { // focus an existing terminal on this dir, else fork one below for (p.panes, 0..) |slot, i| { @@ -2631,11 +2816,17 @@ pub const Pardes = struct { if (slot) |tt| if (tt.file) |*ff| if (std.mem.eql(u8, ff.path, target.path)) { p.active = i; if (target.line > 0 and target.line <= fileLineCount(ff.content)) { - const next = target.line - 1; + const next = (target.line - 1) -| tt.rows / 2; // center, clamp at top if (next != ff.scroll) { ff.scroll = next; ff.syntax_dirty = true; } + // land the modal cursor on the target line (and keep + // ensureCursorVisible agreeing with the recenter — + // a stale cursor would yank the view right back) + tt.cur_row = @intCast(target.line - 1); + tt.cur_col = 0; + tt.cur_pinned = true; } return; }; @@ -2643,6 +2834,11 @@ pub const Pardes = struct { const free = p.freeSlot() orelse return; const nt = p.openFileView(free, target.path, target.line) catch return; p.placeDoc(id, free, nt); + // center the target line: the pane's real body height only + // exists after placement, so lay out now and pull the + // scroll up by half a body (line 0 opens stay at the top) + p.computeGeom(); + nt.file.?.scroll -|= @max(1, p.rects[free].h -| BOX_H) / 2; }, .image => |target| { for (p.panes, 0..) |slot, i| { @@ -2918,7 +3114,7 @@ pub const Pardes = struct { if (src.scroll > 0) pane.vt.screens.active.scroll(.{ .delta_row = -@as(isize, @intCast(src.scroll)) }); } p.setCwd(i, t.cwd); - if (std.mem.startsWith(u8, src.tag, "sy ")) pane.mode = .tty; + if (std.mem.startsWith(u8, src.tag, "TTY ")) pane.mode = .tty; p.restoreTail(pane, src.tag); }, .file => { @@ -3077,6 +3273,8 @@ pub const Pardes = struct { /// re-highlight the visible window of any file whose syntax went stale /// (edit, scroll, load) — visible-range-first so big files stay snappy fn refreshDirtyHighlights(p: *Pardes) void { + const tz = tracy.zone(@src(), "refreshDirtyHighlights"); + defer tz.end(); for (p.panes) |slot| { const pane = slot orelse continue; if (pane.file == null) continue; @@ -3226,6 +3424,8 @@ pub const Pardes = struct { } fn renderPane(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rect, active: bool) !void { + const tz = tracy.zone(@src(), "renderPane"); + defer tz.end(); if (r.w <= GUTTER or r.h == 0) return; const s = &p.surface; const th = p.theme(); @@ -3278,7 +3478,9 @@ pub const Pardes = struct { .fg = if (th.fg) |c| .{ .rgb = c } else .default, .bg = if (th.bg) |c| .{ .rgb = c } else .default, }; + const tz_body = tracy.zone(@src(), "bodyText"); const body = try p.bodyText(arena, pane); + tz_body.end(); var it = std.mem.splitScalar(u8, body, '\n'); var i: u16 = 0; while (it.next()) |line| : (i += 1) { @@ -3288,14 +3490,24 @@ pub const Pardes = struct { // file line-number gutter: mute the first PREFIX_W columns. Cheap // chrome, not gated on colors_on; selection/cursor passes still win. + // The cursor row's number takes the tag style (same row math as the + // cursor pass below) so the eye finds the current line. if (pane.file != null) { + const goff = pane.scroll(); + const gcur = pane.vt.screens.active.cursor; + const gcrow = if (pane.cur_pinned) pane.cur_row else @as(i32, @intCast(gcur.y)) + goff; + const cur_vr: i32 = if (active and !pane.tag_edit) gcrow - goff else -1; var vr: u16 = 0; while (vr < body_h) : (vr += 1) { + const on_cursor = @as(i32, vr) == cur_vr; var c: u16 = 0; while (c < PREFIX_W and c < tw) : (c += 1) { const cell = s.at(tx + c, r.y + BOX_H + vr); cell.default = false; // paints blank gutter rows too - cell.style.fg = .{ .rgb = th.lineno }; + if (on_cursor) { + cell.style.fg = .{ .rgb = th.tag_fg }; + cell.style.bg = .{ .rgb = th.tag_bg }; + } else cell.style.fg = .{ .rgb = th.lineno }; } } } @@ -3303,6 +3515,8 @@ pub const Pardes = struct { // tree-sitter style byte; content starts after the lineno gutter if (p.colors_on) if (pane.file) |*f| { if (f.highlights.len > 0) { + const tz_recolor = tracy.zone(@src(), "synRecolor"); + defer tz_recolor.end(); var flines = std.mem.splitScalar(u8, f.content, '\n'); var skip: usize = 0; while (skip < f.scroll) : (skip += 1) { diff --git a/src/syntax.zig b/src/syntax.zig index a9914fd7..0d2fa291 100644 --- a/src/syntax.zig +++ b/src/syntax.zig @@ -4,6 +4,7 @@ //! compiles queries at startup; `full` adds ~23 languages lazily on first use. const std = @import("std"); const config = @import("pardes_config"); +const tracy = @import("tracy.zig"); pub const enabled = config.syntax_highlighting; const minimal_grammars = config.syntax_minimal_grammars; @@ -140,6 +141,8 @@ pub fn highlightFile(gpa: std.mem.Allocator, path: []const u8, content: []const /// One Syn byte per content byte in [start, end). Caller frees. pub fn highlightFileRange(gpa: std.mem.Allocator, path: []const u8, content: []const u8, start_byte_raw: usize, end_byte_raw: usize) ![]u8 { + const tz = tracy.zone(@src(), "highlightFileRange"); + defer tz.end(); if (!enabled) return &.{}; const ext = std.fs.path.extension(path); const selected = (forExt(ext) catch return &.{}) orelse return &.{}; diff --git a/src/tracy.zig b/src/tracy.zig new file mode 100644 index 00000000..3b0b8621 --- /dev/null +++ b/src/tracy.zig @@ -0,0 +1,50 @@ +//! Minimal Tracy client (the Zig compiler's pattern): `zone(@src(), "name")` +//! ... `.end()`, plus `frameMark()`. Everything compiles to a no-op unless the +//! build sets -Dtracy=<path-to-tracy-checkout>, which also compiles and links +//! TracyClient.cpp. Capture with tracy-capture, inspect with tracy-csvexport. +const std = @import("std"); +const builtin = @import("builtin"); + +pub const enable = if (builtin.is_test) false else @import("pardes_config").enable_tracy; + +const SourceLocation = extern struct { + name: ?[*:0]const u8, + function: [*:0]const u8, + file: [*:0]const u8, + line: u32, + color: u32, +}; + +pub const Ctx = if (enable) extern struct { + id: u32, + active: i32, + + pub inline fn end(c: @This()) void { + ___tracy_emit_zone_end(c); + } +} else struct { + pub inline fn end(_: @This()) void {} +}; + +pub inline fn zone(comptime src: std.builtin.SourceLocation, comptime name: [:0]const u8) Ctx { + if (!enable) return .{}; + const static = struct { + const loc: SourceLocation = .{ + .name = name.ptr, + .function = src.fn_name.ptr, + .file = src.file.ptr, + .line = src.line, + .color = 0, + }; + }; + return ___tracy_emit_zone_begin(&static.loc, 1); +} + +pub inline fn frameMark() void { + if (!enable) return; + ___tracy_emit_frame_mark(null); +} + +extern fn ___tracy_emit_zone_begin(srcloc: *const SourceLocation, active: c_int) Ctx; +extern fn ___tracy_emit_zone_end(ctx: Ctx) void; +extern fn ___tracy_emit_frame_mark(name: ?[*:0]const u8) void; diff --git a/src/tty.zig b/src/tty.zig index f2b36ed4..97f10a7a 100644 --- a/src/tty.zig +++ b/src/tty.zig @@ -3,16 +3,25 @@ //! them, resize them), and hands the core's Surface to vaxis cell-for-cell — //! the canonical interface rendered with no interpretation. const std = @import("std"); +const builtin = @import("builtin"); const posix = std.posix; -const linux = std.os.linux; +const libc = std.c; const vaxis = @import("vaxis"); const pardes = @import("pardes.zig"); +const tracy = @import("tracy.zig"); +const look = @import("look.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; extern "c" fn chdir(path: [*:0]const u8) c_int; extern "c" fn _exit(status: c_int) noreturn; +// absolute shell path per OS: execv must not search PATH (no allocation +// between fork and exec) +const bash_path: [*:0]const u8 = if (builtin.os.tag == .linux) "/usr/bin/bash" else "/bin/bash"; +// TIOCSWINSZ: absent from std.c.T on darwin — _IOW('t', 103, winsize) +const TIOCSWINSZ: c_int = @bitCast(@as(u32, if (@hasDecl(posix.T, "IOCSWINSZ")) posix.T.IOCSWINSZ else 0x80087467)); + pub const Command = struct { pub var value: union(enum) { nop, @@ -20,7 +29,7 @@ pub const Command = struct { tick, key_press: vaxis.Key, pty_read: struct { id: usize, bytes: []u8 }, - pty_eof: usize, + pty_eof: struct { id: usize, gen: u32 }, winsize: vaxis.Winsize, mouse: vaxis.Mouse, paste: []const u8, @@ -45,6 +54,11 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { defer vx.deinit(gpa, tty.writer()); try vx.enterAltScreen(tty.writer()); defer vx.exitAltScreen(tty.writer()) catch {}; + // requests 1002;1003;1004;1006 (cell-coordinate SGR; called pre-query, so + // vaxis never upgrades to 1016 pixel mode). Note: ghostty's GTK apprt drops + // middle press+release BEFORE mouse reporting when the desktop sets + // gtk-enable-primary-paste=false — no mode we request can surface middle + // clicks there (see test/snapshots/ghostty-mid.snap). try vx.setMouseMode(tty.writer(), true); var frame_arena: std.heap.ArenaAllocator = .init(gpa); @@ -55,7 +69,7 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { defer pardes.image.stop(); const core = if (opts.load_path) |lp| blk: { - const bytes = try @import("look.zig").readFile(gpa, lp); + const bytes = try look.readFile(gpa, lp); defer gpa.free(bytes); break :blk try pardes.Pardes.initFromDump(gpa, opts, bytes); } else try pardes.Pardes.init(gpa, opts); @@ -66,6 +80,9 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { var kitty_handles: [pardes.MAX_PANES]?vaxis.Image = @splat(null); 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); var loop: Loop = .init(io, &tty, &vx); defer { // reap the reader tasks (cancel interrupts a blocked read) before @@ -74,7 +91,7 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { // queue: leftover events own gpa bytes and would dump as leaks. for (&ptys) |*slot| if (slot.*) |*pt| { pt.reader.cancel(io) catch {}; - _ = linux.close(pt.file.handle); + _ = libc.close(pt.file.handle); slot.* = null; }; while (loop.tryEvent() catch null) |ev| switch (ev) { @@ -86,7 +103,7 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { // Perform the initial spawns BEFORE any worker thread exists: forkpty from // a multithreaded process can wedge the child before exec. - drainEffects(core, &ptys, io, gpa, &loop, &vx, &tty, false); + drainEffects(core, &ptys, &gens, io, gpa, &loop, &vx, &tty, false); try loop.start(); defer loop.stop(); @@ -95,84 +112,99 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { // 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, &loop }); + pt.reader = try io.concurrent(readPty, .{ io, gpa, pt.file, id, gens[id], &loop }); }; var pending: ?@TypeOf(Command.value) = .tick; while (!core.quit) { - const event = if (pending) |ev| blk: { + var event = if (pending) |ev| blk: { pending = null; break :blk ev; } else try loop.nextEvent(); - switch (event) { - .nop, .tick => {}, - .quit => break, - .winsize => |ws| { - try vx.resize(gpa, tty.writer(), ws); - core.update(.{ .resize = .{ .cols = @intCast(ws.cols), .rows = @intCast(ws.rows) } }); - }, - .pty_read => |pr| { - core.update(.{ .output = .{ .pane = @intCast(pr.id), .bytes = pr.bytes } }); - gpa.free(pr.bytes); - }, - .pty_eof => |id| { - if (ptys[id]) |*pt| { - pt.reader.await(io) catch {}; // reader just finished; join it or its future leaks - _ = linux.close(pt.file.handle); - ptys[id] = null; - } - core.update(.{ .eof = .{ .pane = @intCast(id) } }); - }, - .key_press => |key| core.update(.{ .key = .{ - .cp = mapKey(effCp(key)), - .text = key.text orelse "", - .ctrl = key.mods.ctrl, - .alt = key.mods.alt, - } }), - .mouse => |m| { - const button: ?pardes.Mouse.Button = switch (m.button) { - .left => .left, - .middle => .middle, - .right => .right, - .wheel_up => .wheel_up, - .wheel_down => .wheel_down, - .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), - } }); - }, - .paste => |bytes| { - core.update(.{ .paste = bytes }); - gpa.free(@constCast(bytes)); - }, + 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. + // pty output keeps a frame per chunk: progress paints as it arrives. + var stop = false; + var batch: usize = 0; + while (true) { + var output = false; + switch (event) { + .nop, .tick => {}, + .quit => stop = true, + .winsize => |ws| { + try vx.resize(gpa, tty.writer(), ws); + core.update(.{ .resize = .{ .cols = @intCast(ws.cols), .rows = @intCast(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| core.update(.{ .key = .{ + .cp = mapKey(effCp(key)), + .text = key.text orelse "", + .ctrl = key.mods.ctrl, + .alt = key.mods.alt, + } }), + .mouse => |m| { + const button: ?pardes.Mouse.Button = switch (m.button) { + .left => .left, + .middle => .middle, + .right => .right, + .wheel_up => .wheel_up, + .wheel_down => .wheel_down, + .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), + } }); + }, + .paste => |bytes| { + core.update(.{ .paste = bytes }); + gpa.free(@constCast(bytes)); + }, + } + batch += 1; + if (stop or output or batch >= 64) break; + event = (try loop.tryEvent()) orelse break; } + tz_event.end(); + if (stop) break; - drainEffects(core, &ptys, io, gpa, &loop, &vx, &tty, true); + drainEffects(core, &ptys, &gens, io, gpa, &loop, &vx, &tty, true); if (core.quit) break; - // live cwd for tags/look: cheap /proc readlink per pane, per frame + // live cwd for tags/look: cheap per-pane lookup, per frame for (&ptys, 0..) |*slot, id| if (slot.*) |pt| { var lbuf: [1024]u8 = undefined; - var pbuf: [64]u8 = undefined; - const path = std.fmt.bufPrintSentinel(&pbuf, "/proc/{d}/cwd", .{pt.pid}, 0) catch continue; - const rc = linux.readlinkat(linux.AT.FDCWD, path, &lbuf, lbuf.len); - const n: isize = @bitCast(rc); - if (n > 0) core.setCwd(id, lbuf[0..@intCast(n)]); + if (look.shellCwd(pt.pid, &lbuf)) |cwd| core.setCwd(id, cwd); }; // ---- render: surface -> vaxis, cell for cell ---- _ = frame_arena.reset(.retain_capacity); + const tz_core = tracy.zone(@src(), "core.render"); const surface = try core.render(frame_arena.allocator()); + tz_core.end(); + const tz_cells = tracy.zone(@src(), "surface->vaxis"); const win = vx.window(); win.clear(); var y: u16 = 0; @@ -187,6 +219,7 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { }); } } + tz_cells.end(); // pixel attachments (kitty graphics): transmit once per pane, then // re-place every frame (placements aren't persistent) for (surface.images[0..surface.nimages]) |maybe| { @@ -205,13 +238,17 @@ pub fn run(init: std.process.Init, opts: pardes.Options) !void { } } if (surface.cursor) |cur| win.showCursor(cur.x, cur.y); + const tz_render = tracy.zone(@src(), "vx.render"); try vx.render(tty.writer()); + tz_render.end(); + tracy.frameMark(); } } fn drainEffects( core: *pardes.Pardes, ptys: *[pardes.MAX_PANES]?Pty, + gens: *[pardes.MAX_PANES]u32, io: std.Io, gpa: std.mem.Allocator, loop: *Loop, @@ -221,7 +258,15 @@ fn drainEffects( ) void { while (core.nextEffect()) |effect| switch (effect) { .spawn => |sp| { - std.debug.assert(ptys[sp.pane] == null); + // 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; @@ -234,15 +279,10 @@ fn drainEffects( 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) var lbuf: [1024]u8 = undefined; - var pbuf: [64]u8 = undefined; - if (std.fmt.bufPrintSentinel(&pbuf, "/proc/{d}/cwd", .{child.pid}, 0) catch null) |path| { - const rc = linux.readlinkat(linux.AT.FDCWD, path, &lbuf, lbuf.len); - const n: isize = @bitCast(rc); - if (n > 0) core.setCwd(sp.pane, lbuf[0..@intCast(n)]); - } + 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), loop }) catch pt.reader; + pt.reader = io.concurrent(readPty, .{ io, gpa, pt.file, @as(usize, sp.pane), gens[sp.pane], loop }) catch pt.reader; } } }, @@ -252,7 +292,7 @@ fn drainEffects( .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, posix.T.IOCSWINSZ, @intFromPtr(&ws)); + _ = posix.system.ioctl(pt.file.handle, TIOCSWINSZ, @intFromPtr(&ws)); } }, .open_link => {}, // tty: no link handling (look opens panes instead) @@ -263,21 +303,17 @@ fn drainEffects( if (f.path.len >= pathbuf.len) continue; @memcpy(pathbuf[0..f.path.len], f.path); pathbuf[f.path.len] = 0; - const rc = linux.open(pathbuf[0..f.path.len :0], .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, 0o644); - const sfd: isize = @bitCast(rc); - if (sfd < 0) continue; - const fd: c_int = @intCast(sfd); + 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); - _ = linux.close(fd); + _ = libc.close(fd); }, .write_dump => { const out = core.dump_out orelse continue; - const rc = linux.open(pardes.dump.default_path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, 0o644); - const sfd: isize = @bitCast(rc); - if (sfd < 0) continue; - const fd: c_int = @intCast(sfd); + const fd = libc.open(pardes.dump.default_path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); + if (fd < 0) continue; writeFd(fd, out); - _ = linux.close(fd); + _ = libc.close(fd); }, .set_clipboard => { // mirror the core's yank register out via OSC 52 @@ -294,14 +330,14 @@ fn forkShell(cwd: ?[*:0]const u8, rows: u16, cols: u16) struct { file: std.Io.Fi const pid = forkpty(&master, null, null, &ws); if (pid == 0) { if (cwd) |c| _ = chdir(c); - const argv: [4:null]?[*:0]const u8 = .{ "/usr/bin/bash", "--rcfile", "/tmp/pardes-osc133.bash", null }; - _ = execv("/usr/bin/bash", &argv); + const argv: [4:null]?[*:0]const u8 = .{ bash_path, "--rcfile", "/tmp/pardes-osc133.bash", null }; + _ = execv(bash_path, &argv); _exit(127); } return .{ .file = .{ .handle = master, .flags = .{ .nonblocking = false } }, .pid = pid }; } -fn readPty(io: std.Io, gpa: std.mem.Allocator, pty: std.Io.File, id: usize, loop: *Loop) anyerror!void { +fn readPty(io: std.Io, gpa: std.mem.Allocator, pty: std.Io.File, id: usize, gen: u32, loop: *Loop) anyerror!void { var read_buf: [0x10000]u8 = undefined; var reader = pty.readerStreaming(io, &read_buf); while (true) { @@ -317,7 +353,7 @@ fn readPty(io: std.Io, gpa: std.mem.Allocator, pty: std.Io.File, id: usize, loop } // non-blocking: a teardown cancel only unblocks one wait, so a blocking // post into a full queue here could hang the exit - _ = loop.tryPostEvent(.{ .pty_eof = id }) catch {}; + _ = loop.tryPostEvent(.{ .pty_eof = .{ .id = id, .gen = gen } }) catch {}; } /// The effective codepoint the way vaxis Key.matches sees it: a single-char @@ -380,21 +416,18 @@ fn vaxisColor(c: pardes.Color) vaxis.Color { } fn writeFile(data: []const u8) void { - const rc = linux.open("/tmp/pardes-osc133.bash", .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, 0o644); - const sfd: isize = @bitCast(rc); - if (sfd < 0) return; - const fd: c_int = @intCast(sfd); - defer _ = linux.close(fd); + const fd = libc.open("/tmp/pardes-osc133.bash", .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); + if (fd < 0) return; + defer _ = libc.close(fd); writeFd(fd, data); } fn writeFd(fd: c_int, data: []const u8) void { var off: usize = 0; while (off < data.len) { - const rc = linux.write(fd, data[off..].ptr, data.len - off); - const n: isize = @bitCast(rc); + const n = libc.write(fd, data[off..].ptr, data.len - off); if (n < 0) { - if (n == -@as(isize, @intFromEnum(linux.E.INTR))) continue; + if (libc.errno(n) == .INTR) continue; return; } off += @intCast(n); diff --git a/src/tutor.txt b/src/tutor.txt index 5a93d388..94a2a20e 100644 --- a/src/tutor.txt +++ b/src/tutor.txt @@ -18,9 +18,9 @@ over. Modal editing (helix-style) is layered on top of that. Three modes (the tag shows which): - nm NORMAL block cursor, keys move/edit. DEFAULT on startup. - in INSERT keys type text at the cursor. - sy TTY keys go straight to the shell. (terminals only) + NOR NORMAL block cursor, keys move/edit. DEFAULT on startup. + INS INSERT keys type text at the cursor. + TTY TTY keys go straight to the shell. (terminals only) This tutor is in THREE parts, ordered by what's most different from editors you may know: @@ -71,7 +71,7 @@ - or select with the keyboard (`v` chars / `x` lines), then press Tab to execute or Enter to look — the acme chords on the keyboard. - THE TAG: each pane has a one-line tag: its MODE (nm/in/sy) + directory + THE TAG: each pane has a one-line tag: its MODE (NOR/INS/TTY) + directory or file path + builtins. File panes show "Save Del" by default; Save writes the current file to disk, Del closes the window. Terminal and image panes show "Del". "Delcol" still exists as a command: type it in @@ -110,11 +110,11 @@ prompt model rather than layering an editor cursor on top. On a terminal pane: - NORMAL (nm) prompt rows are HIDDEN — a clean acme-style page. You + NORMAL (NOR) prompt rows are HIDDEN — a clean acme-style page. You navigate it with the same h/j/k/l/w/b/e as a file. - INSERT (in) same clean page; keys type an insertion overlay (the + INSERT (INS) same clean page; keys type an insertion overlay (the command you're composing). Prompts still hidden. - TTY (sy) the REAL shell — prompts + typed input shown, and keys + TTY (TTY) the REAL shell — prompts + typed input shown, and keys go straight to the pty as terminal input. ESC: insert -> normal. (Esc never reaches tty.) diff --git a/test/e2e_harness.zig b/test/e2e_harness.zig index 6354aa4b..9099f13e 100644 --- a/test/e2e_harness.zig +++ b/test/e2e_harness.zig @@ -1,8 +1,11 @@ const std = @import("std"); const posix = std.posix; -const linux = std.os.linux; +const libc = std.c; const ghostty_vt = @import("ghostty-vt"); +// TIOCSWINSZ: absent from std.c.T on darwin — _IOW('t', 103, winsize) +const TIOCSWINSZ: c_int = @bitCast(@as(u32, if (@hasDecl(posix.T, "IOCSWINSZ")) posix.T.IOCSWINSZ else 0x80087467)); + extern "c" fn forkpty( amaster: *c_int, name: ?[*:0]u8, @@ -13,9 +16,9 @@ extern "c" fn execvp(file: [*:0]const u8, argv: [*:null]const ?[*:0]const u8) c_ extern "c" fn _exit(status: c_int) noreturn; fn nowMs() i64 { - var ts: linux.timespec = undefined; - _ = linux.clock_gettime(linux.CLOCK.MONOTONIC, &ts); - return ts.sec * 1000 + @divFloor(@as(i64, ts.nsec), 1_000_000); + var ts: libc.timespec = undefined; + _ = libc.clock_gettime(.MONOTONIC, &ts); + return @as(i64, @intCast(ts.sec)) * 1000 + @divFloor(@as(i64, @intCast(ts.nsec)), 1_000_000); } /// E2E test harness: forks the app in a pty and parses its output with a @@ -92,7 +95,7 @@ pub const Harness = struct { pub fn deinit(self: *Harness) void { posix.kill(self.pid, posix.SIG.KILL) catch {}; - _ = linux.close(self.master); + _ = libc.close(self.master); self.stream.deinit(); self.raw.deinit(self.gpa); self.term.deinit(self.gpa); @@ -103,10 +106,9 @@ pub const Harness = struct { pub fn send(self: *Harness, bytes: []const u8) !void { var off: usize = 0; while (off < bytes.len) { - const rc = linux.write(self.master, bytes[off..].ptr, bytes.len - off); - const n: isize = @bitCast(rc); + const n = libc.write(self.master, bytes[off..].ptr, bytes.len - off); if (n < 0) { - if (n == -@as(isize, @intFromEnum(linux.E.INTR))) continue; + if (libc.errno(n) == .INTR) continue; return error.WriteFailed; } off += @intCast(n); @@ -139,7 +141,7 @@ pub const Harness = struct { self.cols = cols; self.term.resize(self.gpa, cols, rows) catch {}; const ws = posix.winsize{ .row = rows, .col = cols, .xpixel = 0, .ypixel = 0 }; - _ = posix.system.ioctl(self.master, posix.T.IOCSWINSZ, @intFromPtr(&ws)); + _ = posix.system.ioctl(self.master, TIOCSWINSZ, @intFromPtr(&ws)); } /// The full viewport text (plainString), newline-joined rows. Caller frees. @@ -261,18 +263,15 @@ pub const Harness = struct { } }; -/// Write a file (helper for test setup, raw linux syscalls). +/// Write a file (helper for test setup, raw libc). pub fn writeFile(path: [*:0]const u8, data: []const u8) !void { - const rc = linux.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, 0o644); - const sfd: isize = @bitCast(rc); - if (sfd < 0) return error.OpenFailed; - const fd: c_int = @intCast(sfd); - defer _ = linux.close(fd); + const fd = libc.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644)); + if (fd < 0) return error.OpenFailed; + defer _ = libc.close(fd); var off: usize = 0; while (off < data.len) { - const w = linux.write(fd, data[off..].ptr, data.len - off); - const sw: isize = @bitCast(w); - if (sw <= 0) break; - off += @intCast(sw); + const w = libc.write(fd, data[off..].ptr, data.len - off); + if (w <= 0) break; + off += @intCast(w); } } diff --git a/test/snapshot.zig b/test/snapshot.zig index c1bf03c0..10aa0c86 100644 --- a/test/snapshot.zig +++ b/test/snapshot.zig @@ -28,8 +28,7 @@ // snap <label> capture grid text + cursor // snapstyle <label> capture per-cell style runs (fg,bg,attrs) const std = @import("std"); -const posix = std.posix; -const linux = std.os.linux; +const libc = std.c; const ghostty_vt = @import("ghostty-vt"); const eh = @import("e2e_harness.zig"); @@ -48,9 +47,8 @@ pub fn main(init: std.process.Init) !void { // argv: exe-under-test, then flags/scripts. All paths made absolute up // front because runScript chdirs into a per-script workdir. var cwd_buf: [4096]u8 = undefined; - const cwd_rc: isize = @bitCast(linux.getcwd(&cwd_buf, cwd_buf.len)); - if (cwd_rc <= 0) fatal("getcwd failed", .{}); - const orig_cwd = cwd_buf[0..@intCast(cwd_rc - 1)]; + const cwd_p = libc.getcwd(&cwd_buf, cwd_buf.len) orelse fatal("getcwd failed", .{}); + const orig_cwd = std.mem.span(@as([*:0]u8, @ptrCast(cwd_p))); var exe: ?[]const u8 = null; var update = false; @@ -461,41 +459,26 @@ fn absPath(arena: std.mem.Allocator, cwd: []const u8, p: []const u8) ![]const u8 fn listSnaps(arena: std.mem.Allocator, dir_path: []const u8, scripts: *std.ArrayList([]const u8)) !void { const dir_z = try arena.dupeZ(u8, dir_path); - const rc = linux.open(dir_z, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, 0); - const sfd: isize = @bitCast(rc); - if (sfd < 0) fatal("no snapshots/ dir at {s}", .{dir_path}); - const fd: i32 = @intCast(sfd); - defer _ = linux.close(fd); - var buf: [8192]u8 align(@alignOf(linux.dirent64)) = undefined; - while (true) { - const r = linux.getdents64(fd, &buf, buf.len); - const n: isize = @bitCast(r); - if (n <= 0) break; - var off: usize = 0; - while (off < @as(usize, @intCast(n))) { - const d: *align(1) linux.dirent64 = @ptrCast(&buf[off]); - const name = std.mem.span(@as([*:0]const u8, @ptrCast(&d.name))); - if (std.mem.endsWith(u8, name, ".snap")) - try scripts.append(arena, try std.fmt.allocPrint(arena, "{s}/{s}", .{ dir_path, name })); - off += d.reclen; - } + const dir = libc.opendir(dir_z) orelse fatal("no snapshots/ dir at {s}", .{dir_path}); + defer _ = libc.closedir(dir); + while (libc.readdir(dir)) |d| { + const name = std.mem.sliceTo(@as([*:0]const u8, @ptrCast(&d.name)), 0); + if (std.mem.endsWith(u8, name, ".snap")) + try scripts.append(arena, try std.fmt.allocPrint(arena, "{s}/{s}", .{ dir_path, name })); } } fn readFileAlloc(arena: std.mem.Allocator, path: []const u8) ![]u8 { const path_z = try arena.dupeZ(u8, path); - const rc = linux.open(path_z, .{ .ACCMODE = .RDONLY }, 0); - const sfd: isize = @bitCast(rc); - if (sfd < 0) return error.OpenFailed; - const fd: i32 = @intCast(sfd); - defer _ = linux.close(fd); + const fd = libc.open(path_z, .{ .ACCMODE = .RDONLY }); + if (fd < 0) return error.OpenFailed; + defer _ = libc.close(fd); var buf: std.ArrayList(u8) = .empty; var chunk: [16384]u8 = undefined; while (true) { - const r = linux.read(fd, &chunk, chunk.len); - const n: isize = @bitCast(r); + const n = libc.read(fd, &chunk, chunk.len); if (n < 0) { - if (n == -@as(isize, @intFromEnum(linux.E.INTR))) continue; + if (libc.errno(n) == .INTR) continue; return error.ReadFailed; } if (n == 0) break; @@ -506,15 +489,15 @@ fn readFileAlloc(arena: std.mem.Allocator, path: []const u8) ![]u8 { fn mkdir(arena: std.mem.Allocator, path: []const u8, exist_ok: bool) !void { const path_z = try arena.dupeZ(u8, path); - const n: isize = @bitCast(linux.mkdir(path_z, 0o755)); - if (n < 0) { - if (exist_ok and n == -@as(isize, @intFromEnum(linux.E.EXIST))) return; + const rc = libc.mkdir(path_z, 0o755); + if (rc != 0) { + if (exist_ok and libc.errno(rc) == .EXIST) return; return error.MkdirFailed; } } -fn chdirRc(path_z: [:0]const u8) isize { - return @bitCast(linux.chdir(path_z.ptr)); +fn chdirRc(path_z: [:0]const u8) c_int { + return libc.chdir(path_z.ptr); } fn rmrf(path: []const u8) void { @@ -522,15 +505,15 @@ fn rmrf(path: []const u8) void { if (path.len >= path_buf.len) return; @memcpy(path_buf[0..path.len], path); path_buf[path.len] = 0; - const pid: isize = @bitCast(linux.fork()); + const pid = libc.fork(); if (pid == 0) { const argv: [4:null]?[*:0]const u8 = .{ "rm", "-rf", @as([*:0]const u8, @ptrCast(&path_buf)), null }; _ = execvp("rm", &argv); - linux.exit_group(127); + libc._exit(127); } if (pid < 0) return; - var status: u32 = 0; - _ = linux.wait4(@intCast(pid), &status, 0, null); + var status: c_int = 0; + _ = libc.waitpid(pid, &status, 0); } fn printFirstDiff(golden: []const u8, actual: []const u8) void { diff --git a/test/snapshots/boot.golden b/test/snapshots/boot.golden index 85bac8dd..e17d9f3d 100644 --- a/test/snapshots/boot.golden +++ b/test/snapshots/boot.golden @@ -1,6 +1,6 @@ == snap boot grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/boot/cwd Del nm /tmp/pardes-snap/boot/cwd Del +| NOR /tmp/pardes-snap/boot/cwd Del NOR /tmp/pardes-snap/boot/cwd Del | | hello.txt hello.txt | @@ -15,7 +15,7 @@ | | | -| nm /tmp/pardes-snap/boot/cwd Del +| NOR /tmp/pardes-snap/boot/cwd Del | | hello.txt | @@ -31,7 +31,7 @@ | == style boot |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-33 #969696,#2c2a3e, 34-49 d,#2c2a3e, 50-51 d,#383c54, 52-83 #969696,#2c2a3e, 84-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#383c54, 52-84 #969696,#2c2a3e, 85-99 d,#2c2a3e, |2: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -46,7 +46,7 @@ |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#383c54, 2-33 #969696,#2c2a3e, 34-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/cursorline.golden b/test/snapshots/cursorline.golden new file mode 100644 index 00000000..2902e41f --- /dev/null +++ b/test/snapshots/cursorline.golden @@ -0,0 +1,124 @@ +== snap top grid=100x30 cursor=7,2 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/cursorline/cwd/cur.txt Save NOR /tmp/pardes-snap/cursorline/cwd Del +| 1 line 1 +| 2 line 2 cur.txt +| 3 line 3 +| 4 line 4 +| 5 line 5 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/cursorline/cwd Del +| +| cur.txt +| +| +| +| cur.txt +| +| NOR /tmp/pardes-snap/cursorline/cwd Del +| +| cur.txt +| +| +| +| +| +| +| +| +| +| +| +== style top +|0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-90 #969696,#2c2a3e, 91-99 d,#2c2a3e, +|2: 0-1 d,#525252, 2-6 #969696,#2c2a3e, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|3: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|4: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|5: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|6: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|7: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|8: 0-1 d,#383c54, 2-40 #969696,#2c2a3e, 41-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|11: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-40 #969696,#2c2a3e, 41-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|21: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|25: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|26: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|27: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|28: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +== snap down3 grid=100x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/cursorline/cwd/cur.txt Save NOR /tmp/pardes-snap/cursorline/cwd Del +| 1 line 1 +| 2 line 2 cur.txt +| 3 line 3 +| 4 line 4 +| 5 line 5 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/cursorline/cwd Del +| +| cur.txt +| +| +| +| cur.txt +| +| NOR /tmp/pardes-snap/cursorline/cwd Del +| +| cur.txt +| +| +| +| +| +| +| +| +| +| +| +== style down3 +|0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-90 #969696,#2c2a3e, 91-99 d,#2c2a3e, +|2: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|3: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|4: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|5: 0-1 d,#2a2a2a, 2-6 #969696,#2c2a3e, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|6: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|7: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|8: 0-1 d,#383c54, 2-40 #969696,#2c2a3e, 41-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|11: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-40 #969696,#2c2a3e, 41-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|21: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|25: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|26: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|27: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|28: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/cursorline.snap b/test/snapshots/cursorline.snap new file mode 100644 index 00000000..f9b3de5b --- /dev/null +++ b/test/snapshots/cursorline.snap @@ -0,0 +1,25 @@ +# cursor-line gutter: the line number on the cursor's row takes the tag style +# and follows modal movement (gg to the top, then jjj down three lines) +lines cur.txt 20 +start 30 100 +wait 8000 cur.txt +stable 700 20000 +press left 5 8 +release left 5 8 +stable 400 5000 +key i +text cur.txt +key esc +settle 700 +stable 400 5000 +press right 6 8 +release right 6 8 +stable 700 15000 +key g g +stable 400 5000 +snap top +snapstyle top +key j j j +stable 400 5000 +snap down3 +snapstyle down3 diff --git a/test/snapshots/dump.actual b/test/snapshots/dump.actual deleted file mode 100644 index cf39f324..00000000 --- a/test/snapshots/dump.actual +++ /dev/null @@ -1,63 +0,0 @@ -== file dump (3004 bytes) -.{ - .magic = "pardes-dump", - .version = 1, - .screen = .{ .cols = 100, .rows = 30 }, - .active = 0, - .topbar = "Kill Newcol Tutor Debug Colors NextColor Dump", - .theme = "dark", - .columns = .{ .{ .weight = 1, .panes = .{ 0, 1 } }, .{ .weight = 1, .panes = .{2} } }, - .panes = .{ - .{ - .kind = .terminal, - .tag = "nm /tmp/pardes-snap/dump/cwd Del", - .body = "\nd.txt\n\n\n\n typed-marker\n\n\n\n\n\n\n\n", - .scroll = 0, - .cols = 48, - .rows = 14, - .vweight = 1, - .terminal = .{ - .cwd = "/tmp/pardes-snap/dump/cwd", - .stream = "\nd.txt\n", - .stream_b64 = "G10xMzM7QwcbXTEzMztEBxtdMTMzO0MHG10wO2dvYmxpbkBwYXJkZXM6L3RtcC9wYXJkZXMtc25hcC9kdW1wL2N3ZAcbWz8yMDA0aBtdMTMzO0E7Y2w9bGluZQckIBtdMTMzO0IHDRtbSw0bXTEzMztBO2NsPWxpbmUHJCAbXTEzMztCB2xzDQobWz8yMDA0bA0bXTEzMztDB2QudHh0DQobXTEzMztDBxtdMTMzO0QHG10xMzM7QwcbXTA7Z29ibGluQHBhcmRlczovdG1wL3BhcmRlcy1zbmFwL2R1bXAvY3dkBxtbPzIwMDRoG10xMzM7QTtjbD1saW5lByQgG10xMzM7Qgc=", - .cursor = .{ .col = 2, .row = 2 }, - }, - .file = null, - .image = null, - }, - .{ - .kind = .terminal, - .tag = "nm /tmp/pardes-snap/dump/cwd Del", - .body = "\nd.txt\n\n\n\n\n\n\n\n\n\n\n", - .scroll = 0, - .cols = 48, - .rows = 13, - .vweight = 1, - .terminal = .{ - .cwd = "/tmp/pardes-snap/dump/cwd", - .stream = "\nd.txt\n", - .stream_b64 = "G10xMzM7QwcbXTEzMztEBxtdMTMzO0MHG10wO2dvYmxpbkBwYXJkZXM6L3RtcC9wYXJkZXMtc25hcC9kdW1wL2N3ZAcbWz8yMDA0aBtdMTMzO0E7Y2w9bGluZQckIBtdMTMzO0IHDRtbSw0bXTEzMztBO2NsPWxpbmUHJCAbXTEzMztCB2xzDQobWz8yMDA0bA0bXTEzMztDB2QudHh0DQobXTEzMztDBxtdMTMzO0QHG10xMzM7QwcbXTA7Z29ibGluQHBhcmRlczovdG1wL3BhcmRlcy1zbmFwL2R1bXAvY3dkBxtbPzIwMDRoG10xMzM7QTtjbD1saW5lByQgG10xMzM7Qgc=", - .cursor = .{ .col = 2, .row = 2 }, - }, - .file = null, - .image = null, - }, - .{ - .kind = .terminal, - .tag = "nm /tmp/pardes-snap/dump/cwd Del", - .body = "\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, - .rows = 28, - .vweight = 1, - .terminal = .{ - .cwd = "/tmp/pardes-snap/dump/cwd", - .stream = "\nd.txt\n", - .stream_b64 = "G10xMzM7QwcbXTEzMztEBxtdMTMzO0MHG10wO2dvYmxpbkBwYXJkZXM6L3RtcC9wYXJkZXMtc25hcC9kdW1wL2N3ZAcbWz8yMDA0aBtdMTMzO0E7Y2w9bGluZQckIBtdMTMzO0IHDRtbSw0bXTEzMztBO2NsPWxpbmUHJCAbXTEzMztCB2xzDQobWz8yMDA0bA0bXTEzMztDB2QudHh0DQobXTEzMztDBxtdMTMzO0QHG10xMzM7QwcbXTA7Z29ibGluQHBhcmRlczovdG1wL3BhcmRlcy1zbmFwL2R1bXAvY3dkBxtbPzIwMDRoG10xMzM7QTtjbD1saW5lByQgG10xMzM7Qgc=", - .cursor = .{ .col = 2, .row = 2 }, - }, - .file = null, - .image = null, - }, - }, -}== end file diff --git a/test/snapshots/dump.golden b/test/snapshots/dump.golden index c18003d5..9527f838 100644 --- a/test/snapshots/dump.golden +++ b/test/snapshots/dump.golden @@ -10,7 +10,7 @@ .panes = .{ .{ .kind = .terminal, - .tag = "nm /tmp/pardes-snap/dump/cwd Del", + .tag = "NOR /tmp/pardes-snap/dump/cwd Del", .body = "\nd.txt\n\n\n\n typed-marker\n\n\n\n\n\n\n\n", .scroll = 0, .cols = 48, @@ -27,7 +27,7 @@ }, .{ .kind = .terminal, - .tag = "nm /tmp/pardes-snap/dump/cwd Del", + .tag = "NOR /tmp/pardes-snap/dump/cwd Del", .body = "\nd.txt\n\n\n\n\n\n\n\n\n\n\n", .scroll = 0, .cols = 48, @@ -44,7 +44,7 @@ }, .{ .kind = .terminal, - .tag = "nm /tmp/pardes-snap/dump/cwd Del", + .tag = "NOR /tmp/pardes-snap/dump/cwd Del", .body = "\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/edit.actual b/test/snapshots/edit.actual deleted file mode 100644 index e45687a2..00000000 --- a/test/snapshots/edit.actual +++ /dev/null @@ -1,62 +0,0 @@ -== snap inserted grid=100x30 cursor=4,4 -|Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/edit/cwd Del nm /tmp/pardes-snap/edit/cwd Del -| -| e.txt e.txt -| -| -| -| -| -| -| -| -| -| -| -| -| nm /tmp/pardes-snap/edit/cwd Del -| -| e.txt -| -| -| -| -| -| -| -| -| -| -| -== style inserted -|0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-33 #969696,#2c2a3e, 34-49 d,#2c2a3e, 50-51 d,#383c54, 52-83 #969696,#2c2a3e, 84-99 d,#2c2a3e, -|2: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|3: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|4: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|5: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|6: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|7: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#383c54, 2-33 #969696,#2c2a3e, 34-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, -|17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|25: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|26: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|27: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|28: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/edit.golden b/test/snapshots/edit.golden index 846bfa30..1e253388 100644 --- a/test/snapshots/edit.golden +++ b/test/snapshots/edit.golden @@ -1,6 +1,6 @@ == snap inserted grid=100x30 cursor=4,9 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/edit/cwd Del nm /tmp/pardes-snap/edit/cwd Del +| NOR /tmp/pardes-snap/edit/cwd Del NOR /tmp/pardes-snap/edit/cwd Del | | e.txt e.txt | @@ -15,7 +15,7 @@ | | | -| nm /tmp/pardes-snap/edit/cwd Del +| NOR /tmp/pardes-snap/edit/cwd Del | | e.txt | @@ -31,7 +31,7 @@ | == style inserted |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-33 #969696,#2c2a3e, 34-49 d,#2c2a3e, 50-51 d,#383c54, 52-83 #969696,#2c2a3e, 84-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#383c54, 52-84 #969696,#2c2a3e, 85-99 d,#2c2a3e, |2: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -46,7 +46,7 @@ |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#383c54, 2-33 #969696,#2c2a3e, 34-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/exec-bigdrag.golden b/test/snapshots/exec-bigdrag.golden new file mode 100644 index 00000000..1d5df56b --- /dev/null +++ b/test/snapshots/exec-bigdrag.golden @@ -0,0 +1,61 @@ +== snap alive grid=200x60 cursor=104,37 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/exec-bigdrag/cwd Del NOR /tmp/pardes-snap/exec-bigdrag/cwd Del +| bash: line: command not found +| big.txt +| bash: 4line: command not found +| +| bash: 15line: command not found +| +| bash: 726line: command not found +| +| bash: 2737line: command not found +| +| bash: 2748line: command not found +| +| bash: e: command not found +| +| bash: ne: command not found +| +| bash: ine: command not found +| +| bash: line: command not found +| +| bash: 2line: command not found +| +| bash: 13line: command not found +| +| bash: 824line: command not found +| +| bash: 2835line: command not found +| +| bash: 2846line: command not found +| NOR /tmp/pardes-snap/exec-bigdrag/cwd Del +| bash: e: command not found +| big.txt +| bash: ne: command not found +| +| bash: ine: command not found +| echo alive-o''k +| bash: line: command not found +| +| bash: 0line: command not found +| +| bash: 11line: command not found +| +| bash: 922line: command not found +| +| bash: 2933line: command not found +| +| bash: 2944line: command not found +| +| bash: e: command not found +| +| bash: ne: command not found +| +| bash: ine: command not found +| +| bash: line: command not found +| +| alive-ok +| diff --git a/test/snapshots/exec-bigdrag.snap b/test/snapshots/exec-bigdrag.snap new file mode 100644 index 00000000..dae92205 --- /dev/null +++ b/test/snapshots/exec-bigdrag.snap @@ -0,0 +1,40 @@ +# a giant accidental middle-drag: the whole selection is executed, chunked +# into 64-byte write effects in ONE update — this used to burst the fixed +# 64-slot effect ring and panic the core (assert in emit). Needs a big grid: +# the selection must exceed 64*64 bytes, more than any 30x100 pane can hold. +lines big.txt 3000 +start 60 200 +wait 8000 big.txt +stable 500 20000 +press left 105 8 +release left 105 8 +stable 300 5000 +key i +text tr -d '\n' < big.txt +key esc +settle 400 +press middle 105 8 +drag middle 126 8 +release middle 126 8 +stable 800 30000 +# the accidental sweep over the full-height right pane, then release +press middle 105 4 +drag middle 150 30 +drag middle 198 58 +release middle 198 58 +settle 500 +stable 800 30000 +# still alive: type and execute a marker command +press left 105 40 +release left 105 40 +stable 300 5000 +key i +text echo alive-o''k +key esc +settle 300 +press middle 105 40 +drag middle 119 40 +release middle 119 40 +wait 10000 alive-ok +stable 800 20000 +snap alive diff --git a/test/snapshots/exec.golden b/test/snapshots/exec.golden index 23b1305b..01464fd9 100644 --- a/test/snapshots/exec.golden +++ b/test/snapshots/exec.golden @@ -1,6 +1,6 @@ == snap exec grid=100x30 cursor=4,7 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/exec/cwd Del nm /tmp/pardes-snap/exec/cwd Del +| NOR /tmp/pardes-snap/exec/cwd Del NOR /tmp/pardes-snap/exec/cwd Del | | e.txt e.txt | @@ -15,7 +15,7 @@ | | | -| nm /tmp/pardes-snap/exec/cwd Del +| NOR /tmp/pardes-snap/exec/cwd Del | | e.txt | @@ -31,7 +31,7 @@ | == snap kept grid=100x30 cursor=6,2 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/exec/cwd Del nm /tmp/pardes-snap/exec/cwd Del +| NOR /tmp/pardes-snap/exec/cwd Del NOR /tmp/pardes-snap/exec/cwd Del | ZZARG | ./c.sh e.txt | @@ -46,7 +46,7 @@ | | | -| nm /tmp/pardes-snap/exec/cwd Del +| NOR /tmp/pardes-snap/exec/cwd Del | | e.txt | @@ -62,7 +62,7 @@ | == snap chord grid=100x30 cursor=6,2 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/exec/cwd Del nm /tmp/pardes-snap/exec/cwd Del +| NOR /tmp/pardes-snap/exec/cwd Del NOR /tmp/pardes-snap/exec/cwd Del | ZZARG | ./c.sh e.txt | @@ -77,7 +77,7 @@ | | | -| nm /tmp/pardes-snap/exec/cwd Del +| NOR /tmp/pardes-snap/exec/cwd Del | | e.txt | @@ -93,7 +93,7 @@ | == snap deleted grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/exec/cwd Del nm /tmp/pardes-snap/exec/cwd Del +| NOR /tmp/pardes-snap/exec/cwd Del NOR /tmp/pardes-snap/exec/cwd Del | | e.txt e.txt | diff --git a/test/snapshots/exec.snap b/test/snapshots/exec.snap index dd8c24ee..a588d9f3 100644 --- a/test/snapshots/exec.snap +++ b/test/snapshots/exec.snap @@ -40,7 +40,7 @@ wait 10000 CHORDARG:ZZARG stable 700 10000 snap chord # middle-click Del in this pane's tag (after cwd prefix) closes it -press middle 32 2 -release middle 32 2 +press middle 33 2 +release middle 33 2 stable 700 10000 snap deleted diff --git a/test/snapshots/fileedit.golden b/test/snapshots/fileedit.golden index c6fb40aa..72950b96 100644 --- a/test/snapshots/fileedit.golden +++ b/test/snapshots/fileedit.golden @@ -1,16 +1,13 @@ == snap edited grid=100x30 cursor=17,2 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/fileedit/cwd/f.txt Save Del nm /tmp/pardes-snap/fileedit/cwd Del +| NOR /tmp/pardes-snap/fileedit/cwd/f.txt Save Del NOR /tmp/pardes-snap/fileedit/cwd Del | 1 liEDIT''MEne 1 | 2 line 2 f.txt | 3 line 3 | 4 line 4 | 5 line 5 | 6 line 6 -| 7 line 7 -| 8 line 8 -| 9 line 9 -| nm /tmp/pardes-snap/fileedit/cwd Del +| NOR /tmp/pardes-snap/fileedit/cwd Del | | f.txt | @@ -18,11 +15,14 @@ | | f.txt | +| NOR /tmp/pardes-snap/fileedit/cwd Del +| +| f.txt +| +| | | -| nm /tmp/pardes-snap/fileedit/cwd Del | -| f.txt | | | @@ -31,17 +31,14 @@ | == snap deleted grid=100x30 cursor=7,3 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/fileedit/cwd/f.txt Save Del nm /tmp/pardes-snap/fileedit/cwd Del +| NOR /tmp/pardes-snap/fileedit/cwd/f.txt Save Del NOR /tmp/pardes-snap/fileedit/cwd Del | 1 liEDIT''MEne 1 | 2 line 3 f.txt | 3 line 4 | 4 line 5 | 5 line 6 | 6 line 7 -| 7 line 8 -| 8 line 9 -| 9 line 10 -| nm /tmp/pardes-snap/fileedit/cwd Del +| NOR /tmp/pardes-snap/fileedit/cwd Del | | f.txt | @@ -49,11 +46,14 @@ | | f.txt | +| NOR /tmp/pardes-snap/fileedit/cwd Del +| +| f.txt +| +| | | -| nm /tmp/pardes-snap/fileedit/cwd Del | -| f.txt | | | @@ -62,17 +62,14 @@ | == snap undone grid=100x30 cursor=7,3 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/fileedit/cwd/f.txt Save Del nm /tmp/pardes-snap/fileedit/cwd Del +| NOR /tmp/pardes-snap/fileedit/cwd/f.txt Save Del NOR /tmp/pardes-snap/fileedit/cwd Del | 1 liEDIT''MEne 1 | 2 line 2 f.txt | 3 line 3 | 4 line 4 | 5 line 5 | 6 line 6 -| 7 line 7 -| 8 line 8 -| 9 line 9 -| nm /tmp/pardes-snap/fileedit/cwd Del +| NOR /tmp/pardes-snap/fileedit/cwd Del | | f.txt | @@ -80,11 +77,14 @@ | | f.txt | +| NOR /tmp/pardes-snap/fileedit/cwd Del +| +| f.txt +| +| | | -| nm /tmp/pardes-snap/fileedit/cwd Del | -| f.txt | | | diff --git a/test/snapshots/fileedit.snap b/test/snapshots/fileedit.snap index 7bafa358..bd259c8b 100644 --- a/test/snapshots/fileedit.snap +++ b/test/snapshots/fileedit.snap @@ -33,8 +33,8 @@ snap deleted key u stable 400 5000 snap undone -# Save via the tag: middle-click the Save word (after "nm <path> ") -press middle 42 2 -release middle 42 2 +# Save via the tag: middle-click the Save word (after "NOR <path> ") +press middle 43 2 +release middle 43 2 settle 800 snapfile saved /tmp/pardes-snap/fileedit/cwd/f.txt diff --git a/test/snapshots/fsearch.golden b/test/snapshots/fsearch.golden new file mode 100644 index 00000000..9b287277 --- /dev/null +++ b/test/snapshots/fsearch.golden @@ -0,0 +1,310 @@ +== snap opened grid=120x30 cursor=7,2 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del +| 1 l1 +| 2 MARK a g.txt +| 3 l3 +| 4 l4 +| 5 l5 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| g.txt +| +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap typing grid=120x30 cursor=55,1 +|Kill Newcol Tutor Debug Colors NextColor Dump +| INS /tmp/pardes-snap/fsearch/cwd/g.txt Save Del /MARK NOR /tmp/pardes-snap/fsearch/cwd Del +| 1 l1 +| 2 MARK a g.txt +| 3 l3 +| 4 l4 +| 5 l5 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| g.txt +| +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap results grid=120x30 cursor=7,2 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del +| 1 l1 +| 2 MARK a g.txt +| 3 l3 +| 4 l4 +| 5 l5 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| +| g.txt +| /tmp/pardes-snap/fsearch/cwd/g.txt:2:MARK a +| /tmp/pardes-snap/fsearch/cwd/g.txt:6:MARK b +| /tmp/pardes-snap/fsearch/cwd/g.txt:10:MARK c +| +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap first grid=120x30 cursor=7,3 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del +| 1 l1 +| 2 MARK a g.txt +| 3 l3 +| 4 l4 +| 5 l5 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| +| g.txt +| /tmp/pardes-snap/fsearch/cwd/g.txt:2:MARK a +| /tmp/pardes-snap/fsearch/cwd/g.txt:6:MARK b +| /tmp/pardes-snap/fsearch/cwd/g.txt:10:MARK c +| +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== style first +|0: 0-44 #969696,#2c2a3e, 45-119 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-48 #969696,#2c2a3e, 49-59 d,#2c2a3e, 60-61 d,#383c54, 62-97 #969696,#2c2a3e, 98-119 d,#2c2a3e, +|2: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|3: 0-1 d,#525252, 2-6 #969696,#2c2a3e, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|4: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|5: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|6: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|7: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|8: 0-1 d,#383c54, 2-37 #969696,#2c2a3e, 38-59 d,#2c2a3e, 60-61 d,#525252, 62-119 d,d, +|9: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|10: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|11: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|12: 0-1 d,#525252, 2-59 #d8c8a8,#4a3a1e, 60-61 d,#525252, 62-119 d,d, +|13: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|14: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|15: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|16: 0-1 d,#383c54, 2-37 #969696,#2c2a3e, 38-59 d,#2c2a3e, 60-61 d,#525252, 62-119 d,d, +|17: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|18: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|19: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|20: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|21: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|22: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|23: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|24: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|25: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|26: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|27: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|28: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|29: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +== snap second grid=120x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del +| 3 l3 +| 4 l4 g.txt +| 5 l5 +| 6 MARK b +| 7 l7 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| +| g.txt +| /tmp/pardes-snap/fsearch/cwd/g.txt:2:MARK a +| /tmp/pardes-snap/fsearch/cwd/g.txt:6:MARK b +| /tmp/pardes-snap/fsearch/cwd/g.txt:10:MARK c +| +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap third grid=120x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del +| 7 l7 +| 8 l8 g.txt +| 9 l9 +| 10 MARK c +| 11 l11 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| +| g.txt +| /tmp/pardes-snap/fsearch/cwd/g.txt:2:MARK a +| /tmp/pardes-snap/fsearch/cwd/g.txt:6:MARK b +| /tmp/pardes-snap/fsearch/cwd/g.txt:10:MARK c +| +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap back grid=120x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del +| 3 l3 +| 4 l4 g.txt +| 5 l5 +| 6 MARK b +| 7 l7 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| +| g.txt +| /tmp/pardes-snap/fsearch/cwd/g.txt:2:MARK a +| /tmp/pardes-snap/fsearch/cwd/g.txt:6:MARK b +| /tmp/pardes-snap/fsearch/cwd/g.txt:10:MARK c +| +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap cancel grid=120x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del +| 3 l3 +| 4 l4 g.txt +| 5 l5 +| 6 MARK b +| 7 l7 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| +| g.txt +| /tmp/pardes-snap/fsearch/cwd/g.txt:2:MARK a +| /tmp/pardes-snap/fsearch/cwd/g.txt:6:MARK b +| /tmp/pardes-snap/fsearch/cwd/g.txt:10:MARK c +| +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap nomatch grid=120x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del +| 3 l3 +| 4 l4 g.txt +| 5 l5 +| 6 MARK b +| 7 l7 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| /tmp/pardes-snap/fsearch/cwd/g.txt:2:MARK a +| /tmp/pardes-snap/fsearch/cwd/g.txt:6:MARK b +| /tmp/pardes-snap/fsearch/cwd/g.txt:10:MARK c +| +| +| NOR /tmp/pardes-snap/fsearch/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| diff --git a/test/snapshots/fsearch.snap b/test/snapshots/fsearch.snap new file mode 100644 index 00000000..eab702cb --- /dev/null +++ b/test/snapshots/fsearch.snap @@ -0,0 +1,63 @@ +# `/` file search: the pattern types into the tag (persistent, no popup); +# Enter runs grep -nH into a shell pane so the results are ordinary terminal +# text; n/N select the next/prev result row there (prompt rows skipped via the +# OSC 133 semantic marks) and look it — the file pane scrolls to path:NNN. +# Esc abandons the input; a no-match search leaves n with nowhere to go. +file g.txt l1\nMARK a\nl3\nl4\nl5\nMARK b\nl7\nl8\nl9\nMARK c\nl11\nl12 +start 30 120 +wait 8000 g.txt +stable 700 20000 +# open g.txt: type the name in the shell, look it (as in look-file.snap) +press left 5 8 +release left 5 8 +stable 400 5000 +key i +text g.txt +key esc +settle 700 +stable 400 5000 +press right 6 8 +release right 6 8 +wait 10000 MARK a +stable 700 15000 +snap opened +# / starts the search input in the tag; the pattern is visible while typing +key / +stable 400 5000 +text MARK +stable 400 5000 +snap typing +key enter +wait 10000 g.txt:2:MARK +stable 700 10000 +snap results +# n selects result 1 in the results pane + scrolls the file to line 2 +key n +stable 700 15000 +snap first +snapstyle first +key n +stable 700 15000 +snap second +key n +stable 700 15000 +snap third +# N walks back up to result 2 (line 6) +key N +stable 700 15000 +snap back +# Esc abandons the input: the tag tail is restored +key / +text zz +key esc +settle 700 +stable 400 5000 +snap cancel +# a no-match search: n has nowhere to go (nothing changes, no crash) +key / +text zzqq +key enter +stable 700 10000 +key n +stable 400 5000 +snap nomatch diff --git a/test/snapshots/ghostty-mid.golden b/test/snapshots/ghostty-mid.golden new file mode 100644 index 00000000..929549c6 --- /dev/null +++ b/test/snapshots/ghostty-mid.golden @@ -0,0 +1,31 @@ +== snap ghostty-mid grid=100x30 cursor=4,7 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/ghostty-mid/cwd Del NOR /tmp/pardes-snap/ghostty-mid/cwd Del +| ZZPAD +| ./g.sh g.txt +| +| GHOSTOK +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/ghostty-mid/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| diff --git a/test/snapshots/ghostty-mid.snap b/test/snapshots/ghostty-mid.snap new file mode 100644 index 00000000..437fce27 --- /dev/null +++ b/test/snapshots/ghostty-mid.snap @@ -0,0 +1,32 @@ +# ghostty's wire flavor of a middle click, byte-exact (mode 1002;1003;1004;1006 +# as pardes requests): focus-in, per-cell hover motions (ghostty dedups per +# cell, so none repeat), press keeping SGR button identity, release 'm', +# trailing hover — split across writes like real input. Proves the tty input +# path (vaxis parse -> core execute) handles ghostty's encoding: the live bug +# ("middle click dead only in ghostty") is ghostty's GTK apprt swallowing +# middle press+release BEFORE mouse reporting whenever the desktop has +# gtk-enable-primary-paste=false (apprt/gtk/class/surface.zig, gcMouseDown/ +# gcMouseUp) — the bytes below simply never get sent. +file g.txt x +start 30 100 +wait 8000 g.txt +stable 700 20000 +press left 5 8 +release left 5 8 +stable 400 5000 +key c-b +stable 600 8000 +text printf '#!/bin/sh\necho GHOST''OK\n' > g.sh; chmod +x g.sh; clear; printf 'ZZPAD\n./g.sh\n' +key enter +wait 10000 ./g.sh +stable 700 10000 +key c-b +stable 600 8000 +send \x1b[I +send \x1b[<35;10;8M\x1b[<35;7;6M\x1b[<35;4;4M +send \x1b[<1;4;4M +send \x1b[<1;4;4m +send \x1b[<35;6;4M +wait 10000 GHOSTOK +stable 700 10000 +snap ghostty-mid diff --git a/test/snapshots/images.golden b/test/snapshots/images.golden index b6e75fbf..ae12bedf 100644 --- a/test/snapshots/images.golden +++ b/test/snapshots/images.golden @@ -1,16 +1,13 @@ == snap img-open grid=100x30 cursor=4,7 |Kill Newcol Tutor Debug Colors NextColor Dump -| img /tmp/pardes-snap/images/cwd/pic.ppm Petscii nm /tmp/pardes-snap/images/cwd Del -| 🬝🬹 -| 🬝▀█ pic.ppm -| 🬝▀█ -| 🬝▀█ -| 🬝▀█ -| █🬆█ -| █🬆█ -| █🬆█ -| 🬝🬹█ -| nm /tmp/pardes-snap/images/cwd Del +| img /tmp/pardes-snap/images/cwd/pic.ppm Petscii NOR /tmp/pardes-snap/images/cwd Del +| 🬝🬂 +| 🬝🬂█ pic.ppm +| 🬝🬂█ +| 🬝🬂 +| 🬝🬂█ +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/images/cwd Del | | pic.ppm | @@ -18,11 +15,14 @@ | | pic.ppm | +| NOR /tmp/pardes-snap/images/cwd Del +| +| pic.ppm +| +| | | -| nm /tmp/pardes-snap/images/cwd Del | -| pic.ppm | | | @@ -31,27 +31,27 @@ | == style img-open |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, -|2: 0-1 d,#2a2a2a, 2-16 d,d, 17-32 #ffffff,#ffffff, 33-33 #ffffff,#352879, 34-34 #352879,#ffffff, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|3: 0-1 d,#2a2a2a, 2-16 d,d, 17-30 #ffffff,#ffffff, 31-32 #ffffff,#352879, 33-33 #352879,#ffffff, 34-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|4: 0-1 d,#2a2a2a, 2-16 d,d, 17-28 #ffffff,#ffffff, 29-30 #ffffff,#352879, 31-31 #352879,#ffffff, 32-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|5: 0-1 d,#2a2a2a, 2-16 d,d, 17-26 #ffffff,#ffffff, 27-28 #ffffff,#352879, 29-29 #352879,#ffffff, 30-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|6: 0-1 d,#2a2a2a, 2-16 d,d, 17-24 #ffffff,#ffffff, 25-26 #ffffff,#352879, 27-27 #352879,#ffffff, 28-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|7: 0-1 d,#2a2a2a, 2-16 d,d, 17-22 #ffffff,#ffffff, 23-24 #ffffff,#352879, 25-25 #352879,#ffffff, 26-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#2a2a2a, 2-16 d,d, 17-20 #ffffff,#ffffff, 21-22 #ffffff,#352879, 23-23 #352879,#ffffff, 24-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#2a2a2a, 2-16 d,d, 17-18 #ffffff,#ffffff, 19-20 #ffffff,#352879, 21-21 #352879,#ffffff, 22-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#2a2a2a, 2-16 d,d, 17-17 #ffffff,#352879, 18-19 #352879,#ffffff, 20-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-86 #969696,#2c2a3e, 87-99 d,#2c2a3e, +|2: 0-1 d,#2a2a2a, 2-19 d,d, 20-29 #ffffff,#ffffff, 30-31 #ffffff,#6c5eb5, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|3: 0-1 d,#2a2a2a, 2-19 d,d, 20-27 #ffffff,#ffffff, 28-29 #ffffff,#6c5eb5, 30-30 #352879,#ffffff, 31-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|4: 0-1 d,#2a2a2a, 2-19 d,d, 20-25 #ffffff,#ffffff, 26-27 #ffffff,#6c5eb5, 28-28 #352879,#ffffff, 29-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|5: 0-1 d,#2a2a2a, 2-19 d,d, 20-23 #ffffff,#ffffff, 24-25 #ffffff,#6c5eb5, 26-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|6: 0-1 d,#2a2a2a, 2-19 d,d, 20-21 #ffffff,#ffffff, 22-23 #ffffff,#6c5eb5, 24-24 #352879,#ffffff, 25-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|7: 0-1 d,#2a2a2a, 2-19 d,d, 20-21 #ffffff,#6c5eb5, 22-22 #352879,#ffffff, 23-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|8: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|11: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|21: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -62,27 +62,27 @@ |29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, == style term-palette |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, -|2: 0-1 d,#2a2a2a, 2-16 d,d, 17-32 #ffffff,#ffffff, 33-33 #ffffff,#352879, 34-34 #352879,#ffffff, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|3: 0-1 d,#2a2a2a, 2-16 d,d, 17-30 #ffffff,#ffffff, 31-32 #ffffff,#352879, 33-33 #352879,#ffffff, 34-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|4: 0-1 d,#2a2a2a, 2-16 d,d, 17-28 #ffffff,#ffffff, 29-30 #ffffff,#352879, 31-31 #352879,#ffffff, 32-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|5: 0-1 d,#2a2a2a, 2-16 d,d, 17-26 #ffffff,#ffffff, 27-28 #ffffff,#352879, 29-29 #352879,#ffffff, 30-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|6: 0-1 d,#2a2a2a, 2-16 d,d, 17-24 #ffffff,#ffffff, 25-26 #ffffff,#352879, 27-27 #352879,#ffffff, 28-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|7: 0-1 d,#2a2a2a, 2-16 d,d, 17-22 #ffffff,#ffffff, 23-24 #ffffff,#352879, 25-25 #352879,#ffffff, 26-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#2a2a2a, 2-16 d,d, 17-20 #ffffff,#ffffff, 21-22 #ffffff,#352879, 23-23 #352879,#ffffff, 24-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#2a2a2a, 2-16 d,d, 17-18 #ffffff,#ffffff, 19-20 #ffffff,#352879, 21-21 #352879,#ffffff, 22-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#2a2a2a, 2-16 d,d, 17-17 #ffffff,#352879, 18-19 #352879,#ffffff, 20-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-86 #969696,#2c2a3e, 87-99 d,#2c2a3e, +|2: 0-1 d,#2a2a2a, 2-19 d,d, 20-29 #ffffff,#ffffff, 30-31 #ffffff,#6c5eb5, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|3: 0-1 d,#2a2a2a, 2-19 d,d, 20-27 #ffffff,#ffffff, 28-29 #ffffff,#6c5eb5, 30-30 #352879,#ffffff, 31-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|4: 0-1 d,#2a2a2a, 2-19 d,d, 20-25 #ffffff,#ffffff, 26-27 #ffffff,#6c5eb5, 28-28 #352879,#ffffff, 29-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|5: 0-1 d,#2a2a2a, 2-19 d,d, 20-23 #ffffff,#ffffff, 24-25 #ffffff,#6c5eb5, 26-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|6: 0-1 d,#2a2a2a, 2-19 d,d, 20-21 #ffffff,#ffffff, 22-23 #ffffff,#6c5eb5, 24-24 #352879,#ffffff, 25-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|7: 0-1 d,#2a2a2a, 2-19 d,d, 20-21 #ffffff,#6c5eb5, 22-22 #352879,#ffffff, 23-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|8: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|11: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|21: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -93,27 +93,27 @@ |29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, == style no-ascii |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, -|2: 0-1 d,#2a2a2a, 2-16 d,d, 17-32 #ffffff,#ffffff, 33-33 #ffffff,#352879, 34-34 #352879,#ffffff, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|3: 0-1 d,#2a2a2a, 2-16 d,d, 17-30 #ffffff,#ffffff, 31-32 #ffffff,#352879, 33-33 #352879,#ffffff, 34-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|4: 0-1 d,#2a2a2a, 2-16 d,d, 17-28 #ffffff,#ffffff, 29-30 #ffffff,#352879, 31-31 #352879,#ffffff, 32-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|5: 0-1 d,#2a2a2a, 2-16 d,d, 17-26 #ffffff,#ffffff, 27-28 #ffffff,#352879, 29-29 #352879,#ffffff, 30-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|6: 0-1 d,#2a2a2a, 2-16 d,d, 17-24 #ffffff,#ffffff, 25-26 #ffffff,#352879, 27-27 #352879,#ffffff, 28-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|7: 0-1 d,#2a2a2a, 2-16 d,d, 17-22 #ffffff,#ffffff, 23-24 #ffffff,#352879, 25-25 #352879,#ffffff, 26-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#2a2a2a, 2-16 d,d, 17-20 #ffffff,#ffffff, 21-22 #ffffff,#352879, 23-23 #352879,#ffffff, 24-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#2a2a2a, 2-16 d,d, 17-18 #ffffff,#ffffff, 19-20 #ffffff,#352879, 21-21 #352879,#ffffff, 22-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#2a2a2a, 2-16 d,d, 17-17 #ffffff,#352879, 18-19 #352879,#ffffff, 20-34 #352879,#352879, 35-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-86 #969696,#2c2a3e, 87-99 d,#2c2a3e, +|2: 0-1 d,#2a2a2a, 2-19 d,d, 20-29 #ffffff,#ffffff, 30-31 #ffffff,#6c5eb5, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|3: 0-1 d,#2a2a2a, 2-19 d,d, 20-27 #ffffff,#ffffff, 28-29 #ffffff,#6c5eb5, 30-30 #352879,#ffffff, 31-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|4: 0-1 d,#2a2a2a, 2-19 d,d, 20-25 #ffffff,#ffffff, 26-27 #ffffff,#6c5eb5, 28-28 #352879,#ffffff, 29-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|5: 0-1 d,#2a2a2a, 2-19 d,d, 20-23 #ffffff,#ffffff, 24-25 #ffffff,#6c5eb5, 26-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|6: 0-1 d,#2a2a2a, 2-19 d,d, 20-21 #ffffff,#ffffff, 22-23 #ffffff,#6c5eb5, 24-24 #352879,#ffffff, 25-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|7: 0-1 d,#2a2a2a, 2-19 d,d, 20-21 #ffffff,#6c5eb5, 22-22 #352879,#ffffff, 23-31 #352879,#352879, 32-49 d,d, 50-51 d,#525252, 52-99 d,d, +|8: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|11: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|21: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/layout-close.golden b/test/snapshots/layout-close.golden new file mode 100644 index 00000000..b54b765b --- /dev/null +++ b/test/snapshots/layout-close.golden @@ -0,0 +1,205 @@ +== snap built grid=140x40 cursor=4,16 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/layout-close/cwd Del NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt marker.txt +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| +| +| +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +== snap altc grid=140x40 cursor=98,4 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/layout-close/cwd Del NOR /tmp/pardes-snap/layout-close/cwd Del NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt marker.txt marker.txt +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +== snap del grid=140x40 cursor=98,4 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/layout-close/cwd Del NOR /tmp/pardes-snap/layout-close/cwd Del NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt marker.txt marker.txt +| +| +| +| +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +== snap exit grid=140x40 cursor=4,7 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/layout-close/cwd Del NOR /tmp/pardes-snap/layout-close/cwd Del NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt marker.txt marker.txt +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +== snap colclose grid=140x40 cursor=4,7 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/layout-close/cwd Del NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt marker.txt +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/layout-close/cwd Del +| +| marker.txt +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| diff --git a/test/snapshots/layout-close.snap b/test/snapshots/layout-close.snap new file mode 100644 index 00000000..63f5cd81 --- /dev/null +++ b/test/snapshots/layout-close.snap @@ -0,0 +1,53 @@ +# every pane close hands its space to ONE sibling, the rest of the column +# keeps its sizes: Alt-c move-out, tag Del, and shell exit (pty EOF); an +# emptied column hands its width to one neighbor +file marker.txt x +start 40 140 +wait 8000 marker.txt +stable 700 20000 +# build a left column of five: Alt-n three times from pane 0 (active follows +# the new pane, each split takes from the freshly split pane only) +press left 5 8 +release left 5 8 +stable 400 5000 +key a-n +stable 700 15000 +key a-n +stable 700 15000 +key a-n +stable 700 15000 +snap built +# Alt-c: the active (4th) pane moves to a fresh column; the pane above it +# absorbs its rows, the other three keep theirs (columns reflow horizontally) +key a-c +stable 700 15000 +snap altc +# middle-click Del in the 2nd pane's tag: the pane above absorbs +press middle 41 6 +release middle 41 6 +stable 700 10000 +snap del +# exit the (now) 2nd shell (type the command, esc, Tab executes the word): +# pty EOF, again only the pane above absorbs +press left 5 14 +release left 5 14 +stable 400 5000 +key i +text exit +key esc +settle 700 +key tab +stable 700 10000 +snap exit +# exit the moved-out pane's shell: its column empties and hands its width to +# the middle column only; the left column's width must not change +press left 100 8 +release left 100 8 +stable 400 5000 +key i +text exit +key esc +settle 700 +key tab +stable 700 10000 +snap colclose diff --git a/test/snapshots/layout-open.golden b/test/snapshots/layout-open.golden new file mode 100644 index 00000000..c0690d3c --- /dev/null +++ b/test/snapshots/layout-open.golden @@ -0,0 +1,155 @@ +== snap before grid=100x30 cursor=4,7 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/layout-open/cwd Del NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub sub +| +| +| +| echo one; echo two +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub +| +| +| +| +| +| +| +| +| +| +| +== snap altn-left grid=100x30 cursor=4,8 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/layout-open/cwd Del NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub sub +| +| NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub +| +| +| +| +| +| +| +| +| +| +| +== snap altn-right grid=100x30 cursor=54,8 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/layout-open/cwd Del NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub sub +| +| NOR /tmp/pardes-snap/layout-open/cwd Del NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub sub +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub +| +| +| +| +| +| +| +| +| +| +| +== snap file-open grid=100x30 cursor=7,2 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/layout-open/cwd/sub/f.txt S NOR /tmp/pardes-snap/layout-open/cwd Del +| 1 echo 'TTY'OK +| NOR /tmp/pardes-snap/layout-open/cwd Del sub +| +| NOR /tmp/pardes-snap/layout-open/cwd Del NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub sub +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub +| +| +| +| +| +| +| +| sub/f.txt +| +| +| +== snap ttydir grid=100x30 cursor=7,2 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/layout-open/cwd/sub/f.txt S NOR /tmp/pardes-snap/layout-open/cwd Del +| 1 echo 'TTY'OK +| NOR /tmp/pardes-snap/layout-open/cwd Del sub +| +| NOR /tmp/pardes-snap/layout-open/cwd Del NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub sub +| +| NOR /tmp/pardes-snap/layout-open/cwd/sub Del +| echo 'TTY'OK +| +| TTYOK +| +| +| +| NOR /tmp/pardes-snap/layout-open/cwd Del +| +| sub +| +| +| +| +| +| +| +| sub/f.txt +| +| +| diff --git a/test/snapshots/layout-open.snap b/test/snapshots/layout-open.snap new file mode 100644 index 00000000..773cf70d --- /dev/null +++ b/test/snapshots/layout-open.snap @@ -0,0 +1,55 @@ +# every pane open splits ONE existing pane, the rest of the column keeps its +# sizes: Alt-n splits the active pane, a looked-up file stacking top-left +# splits only the old top pane, an execute-spawned shell for a file's dir +# splits only the bottom pane of the rightmost column +dirmk sub +file sub/f.txt echo 'TTY'OK +start 30 100 +wait 8000 sub +stable 700 20000 +# give pane 0 (top-left) some content so its content-height split is visible +press left 5 8 +release left 5 8 +stable 400 5000 +key i +text echo one; echo two +key enter +key esc +settle 700 +stable 400 5000 +snap before +# Alt-n: new shell below pane 0 — the bottom pane's boundary must not move +key a-n +stable 700 15000 +snap altn-left +# make the right column two panes (Alt-n in a fresh column, trivial split) +press left 70 8 +release left 70 8 +stable 400 5000 +key a-n +stable 700 15000 +snap altn-right +# look sub/f.txt from the bottom-left shell: the doc stacks at the top of the +# left column, splitting only the old top pane — lower boundaries must not move +press left 5 27 +release left 5 27 +stable 400 5000 +key i +text sub/f.txt +key esc +settle 700 +stable 400 5000 +press right 7 27 +release right 7 27 +stable 700 15000 +snap file-open +# execute the file's command (middle drag over line 1): no shell has cwd sub/, +# so one is forked at the bottom of the rightmost column, splitting only the +# pane above it +press middle 8 3 +drag middle 19 3 +release middle 19 3 +wait 10000 TTYOK +motion 40 25 +stable 700 10000 +snap ttydir diff --git a/test/snapshots/load.golden b/test/snapshots/load.golden index ade03fe3..5ca1bfc8 100644 --- a/test/snapshots/load.golden +++ b/test/snapshots/load.golden @@ -1,6 +1,6 @@ == snap loaded grid=100x30 cursor=4,15 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/load/cwd Del nm /tmp/pardes-snap/load/cwd Del +| NOR /tmp/pardes-snap/load/cwd Del NOR /tmp/pardes-snap/load/cwd Del | | LOADMARK d.txt | 1 @@ -15,7 +15,7 @@ | 10 | 11 | 12 -| nm /tmp/pardes-snap/load/cwd Del +| NOR /tmp/pardes-snap/load/cwd Del | | d.txt | @@ -31,7 +31,7 @@ | == style loaded |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-33 #969696,#2c2a3e, 34-49 d,#2c2a3e, 50-51 d,#383c54, 52-83 #969696,#2c2a3e, 84-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#383c54, 52-84 #969696,#2c2a3e, 85-99 d,#2c2a3e, |2: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -46,7 +46,7 @@ |13: 0-1 d,#2a2a2a, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#2a2a2a, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#2a2a2a, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#383c54, 2-33 #969696,#2c2a3e, 34-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/look-center.golden b/test/snapshots/look-center.golden new file mode 100644 index 00000000..67ef9a71 --- /dev/null +++ b/test/snapshots/look-center.golden @@ -0,0 +1,93 @@ +== snap center-open grid=100x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/look-center/cwd/big.txt Sav NOR /tmp/pardes-snap/look-center/cwd Del +| 97 line 97 +| 98 line 98 big.txt +| 99 line 99 +| 100 line 100 +| 101 line 101 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/look-center/cwd Del +| +| big.txt +| +| +| +| big.txt:100 big.txt:150 big.txt:2 +| +| NOR /tmp/pardes-snap/look-center/cwd Del +| +| big.txt +| +| +| +| +| +| +| +| +| +| +| +== snap center-dedup grid=100x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/look-center/cwd/big.txt Sav NOR /tmp/pardes-snap/look-center/cwd Del +| 147 line 147 +| 148 line 148 big.txt +| 149 line 149 +| 150 line 150 +| 151 line 151 +| 152 line 152 +| NOR /tmp/pardes-snap/look-center/cwd Del +| +| big.txt +| +| +| +| big.txt:100 big.txt:150 big.txt:2 +| +| NOR /tmp/pardes-snap/look-center/cwd Del +| +| big.txt +| +| +| +| +| +| +| +| +| +| +| +== snap center-clamp grid=100x30 cursor=7,3 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/look-center/cwd/big.txt Sav NOR /tmp/pardes-snap/look-center/cwd Del +| 1 line 1 +| 2 line 2 big.txt +| 3 line 3 +| 4 line 4 +| 5 line 5 +| 6 line 6 +| NOR /tmp/pardes-snap/look-center/cwd Del +| +| big.txt +| +| +| +| big.txt:100 big.txt:150 big.txt:2 +| +| NOR /tmp/pardes-snap/look-center/cwd Del +| +| big.txt +| +| +| +| +| +| +| +| +| +| +| diff --git a/test/snapshots/look-center.snap b/test/snapshots/look-center.snap new file mode 100644 index 00000000..a56ff038 --- /dev/null +++ b/test/snapshots/look-center.snap @@ -0,0 +1,28 @@ +# a look on path:NN opens the file with the target line CENTERED in the body +# (scroll = line - body/2): fresh open at a deep line, then dedup re-looks at +# the same path re-center the existing pane, and a look near line 1 clamps +# the scroll at 0 (no negative scroll) +lines big.txt 200 +start 30 100 +wait 8000 big.txt +stable 700 20000 +press left 5 8 +release left 5 8 +stable 400 5000 +key i +text big.txt:100 big.txt:150 big.txt:2 +key esc +settle 700 +stable 400 5000 +press right 7 8 +release right 7 8 +stable 700 15000 +snap center-open +press right 18 15 +release right 18 15 +stable 700 15000 +snap center-dedup +press right 30 15 +release right 30 15 +stable 700 15000 +snap center-clamp diff --git a/test/snapshots/look-dir.actual b/test/snapshots/look-dir.actual deleted file mode 100644 index 523560ba..00000000 --- a/test/snapshots/look-dir.actual +++ /dev/null @@ -1,31 +0,0 @@ -== snap dir-open grid=100x30 cursor=4,9 -|Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/look-dir/cwd Del nm /tmp/pardes-snap/look-dir/cwd Del -| -| sub top.txt sub top.txt -| -| nm /tmp/pardes-snap/look-dir/cwd/sub Del -| ls -| -| inner.txt -| -| -| -| -| -| -| -| nm /tmp/pardes-snap/look-dir/cwd Del -| -| sub top.txt -| -| -| -| -| -| -| -| -| -| -| diff --git a/test/snapshots/look-dir.golden b/test/snapshots/look-dir.golden index c4337878..ccd6b9e9 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 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/look-dir/cwd Del nm /tmp/pardes-snap/look-dir/cwd Del +| NOR /tmp/pardes-snap/look-dir/cwd Del NOR /tmp/pardes-snap/look-dir/cwd Del | | sub top.txt sub top.txt | -| nm /tmp/pardes-snap/look-dir/cwd/sub Del +| NOR /tmp/pardes-snap/look-dir/cwd/sub Del | | inner.txt | @@ -15,7 +15,7 @@ | | | -| nm /tmp/pardes-snap/look-dir/cwd Del +| NOR /tmp/pardes-snap/look-dir/cwd Del | | sub top.txt | diff --git a/test/snapshots/look-file.golden b/test/snapshots/look-file.golden index 4f6d4a71..e3d40b84 100644 --- a/test/snapshots/look-file.golden +++ b/test/snapshots/look-file.golden @@ -1,16 +1,13 @@ -== snap file-open grid=100x30 cursor=7,2 +== snap file-open grid=100x30 cursor=7,5 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/look-file/cwd/big.txt Save D nm /tmp/pardes-snap/look-file/cwd Del +| NOR /tmp/pardes-snap/look-file/cwd/big.txt Save NOR /tmp/pardes-snap/look-file/cwd Del +| 37 line 37 +| 38 line 38 big.txt +| 39 line 39 | 40 line 40 -| 41 line 41 big.txt -| 42 line 42 -| 43 line 43 -| 44 line 44 -| 45 line 45 -| 46 line 46 -| 47 line 47 -| 48 line 48 -| nm /tmp/pardes-snap/look-file/cwd Del +| 41 line 41 +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/look-file/cwd Del | | big.txt | @@ -18,11 +15,14 @@ | | big.txt:40 | +| NOR /tmp/pardes-snap/look-file/cwd Del +| +| big.txt +| +| | | -| nm /tmp/pardes-snap/look-file/cwd Del | -| big.txt | | | @@ -31,27 +31,27 @@ | == style file-open |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-88 #969696,#2c2a3e, 89-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-89 #969696,#2c2a3e, 90-99 d,#2c2a3e, |2: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|5: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|5: 0-1 d,#525252, 2-6 #969696,#2c2a3e, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |6: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|7: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#383c54, 2-38 #969696,#2c2a3e, 39-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|7: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|8: 0-1 d,#383c54, 2-39 #969696,#2c2a3e, 40-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|11: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-39 #969696,#2c2a3e, 40-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#383c54, 2-38 #969696,#2c2a3e, 39-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|21: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/modal.golden b/test/snapshots/modal.golden index b4922f12..668fd02c 100644 --- a/test/snapshots/modal.golden +++ b/test/snapshots/modal.golden @@ -1,6 +1,6 @@ == snap top grid=100x30 cursor=2,2 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/modal/cwd Del nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del NOR /tmp/pardes-snap/modal/cwd Del | | words.txt words.txt | @@ -15,7 +15,7 @@ | | | -| nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del | | words.txt | @@ -31,7 +31,7 @@ | == snap moved grid=100x30 cursor=2,6 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/modal/cwd Del nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del NOR /tmp/pardes-snap/modal/cwd Del | | words.txt words.txt | @@ -46,7 +46,7 @@ | | | -| nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del | | words.txt | @@ -62,7 +62,7 @@ | == snap xsel grid=100x30 cursor=2,6 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/modal/cwd Del nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del NOR /tmp/pardes-snap/modal/cwd Del | | words.txt words.txt | @@ -77,7 +77,7 @@ | | | -| nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del | | words.txt | @@ -93,7 +93,7 @@ | == style xsel |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#383c54, 52-84 #969696,#2c2a3e, 85-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, |2: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -108,7 +108,7 @@ |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#383c54, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -124,7 +124,7 @@ |29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, == snap xsel2 grid=100x30 cursor=2,7 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/modal/cwd Del nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del NOR /tmp/pardes-snap/modal/cwd Del | | words.txt words.txt | @@ -139,7 +139,7 @@ | | | -| nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del | | words.txt | @@ -155,7 +155,7 @@ | == snap yanked grid=100x30 cursor=2,6 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/modal/cwd Del nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del NOR /tmp/pardes-snap/modal/cwd Del | | words.txt words.txt | @@ -170,7 +170,7 @@ | | | -| nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del | | words.txt | @@ -186,7 +186,7 @@ | == snap vsel grid=100x30 cursor=3,7 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/modal/cwd Del nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del NOR /tmp/pardes-snap/modal/cwd Del | | words.txt words.txt | @@ -201,7 +201,7 @@ | | | -| nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del | | words.txt | @@ -217,7 +217,7 @@ | == style vsel |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#383c54, 52-84 #969696,#2c2a3e, 85-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, |2: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -232,7 +232,7 @@ |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#383c54, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -248,7 +248,7 @@ |29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, == snap typed grid=100x30 cursor=3,7 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/modal/cwd Del nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del NOR /tmp/pardes-snap/modal/cwd Del | | words.txt words.txt | @@ -263,7 +263,7 @@ | | | -| nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del | | words.txt | @@ -279,7 +279,7 @@ | == snap undone grid=100x30 cursor=3,7 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/modal/cwd Del nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del NOR /tmp/pardes-snap/modal/cwd Del | | words.txt words.txt | @@ -294,7 +294,7 @@ | | | -| nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del | | words.txt | @@ -310,7 +310,7 @@ | == snap redone grid=100x30 cursor=3,7 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/modal/cwd Del nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del NOR /tmp/pardes-snap/modal/cwd Del | | words.txt words.txt | @@ -325,7 +325,7 @@ | | | -| nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del | | words.txt | @@ -341,7 +341,7 @@ | == snap bottom grid=100x30 cursor=2,9 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/modal/cwd Del nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del NOR /tmp/pardes-snap/modal/cwd Del | | words.txt words.txt | @@ -356,7 +356,7 @@ | | | -| nm /tmp/pardes-snap/modal/cwd Del +| NOR /tmp/pardes-snap/modal/cwd Del | | words.txt | diff --git a/test/snapshots/respawn.golden b/test/snapshots/respawn.golden new file mode 100644 index 00000000..2e5e1552 --- /dev/null +++ b/test/snapshots/respawn.golden @@ -0,0 +1,31 @@ +== snap respawn grid=100x30 cursor=4,8 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/respawn/cwd Del NOR /tmp/pardes-snap/respawn/cwd Del +| +| +| TTY /tmp/pardes-snap/respawn/cwd Del +| $ ls +| $ echo RESP''AWNOK +| RESPAWNOK +| $ +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| diff --git a/test/snapshots/respawn.snap b/test/snapshots/respawn.snap new file mode 100644 index 00000000..fbed77e1 --- /dev/null +++ b/test/snapshots/respawn.snap @@ -0,0 +1,21 @@ +# a deleted shell pane's pty lingers in its slot (there is no close effect); +# a later spawn reusing the pane id must reap it instead of tripping the +# drainEffects spawn assert — this exact sequence crashed pre-fix +start 30 100 +wait 8000 Kill Newcol +stable 700 20000 +# middle-click Del on the lower-left pane's tag: the pane id is freed while +# its shell process stays alive in the pty slot +press middle 36 17 +release middle 36 17 +stable 700 10000 +# Alt-n reuses the freed id -> spawn effect lands on the occupied slot +key a-n +stable 700 15000 +key c-b +stable 600 8000 +text echo RESP''AWNOK +key enter +wait 10000 RESPAWNOK +stable 700 10000 +snap respawn diff --git a/test/snapshots/scroll.golden b/test/snapshots/scroll.golden index 899c7dec..971f9659 100644 --- a/test/snapshots/scroll.golden +++ b/test/snapshots/scroll.golden @@ -1,6 +1,6 @@ == snap bottom grid=100x30 cursor=4,15 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/scroll/cwd Del nm /tmp/pardes-snap/scroll/cwd Del +| NOR /tmp/pardes-snap/scroll/cwd Del NOR /tmp/pardes-snap/scroll/cwd Del | 188 | 189 s.txt | 190 @@ -15,7 +15,7 @@ | 199 | 200 | -| nm /tmp/pardes-snap/scroll/cwd Del +| NOR /tmp/pardes-snap/scroll/cwd Del | | s.txt | @@ -31,7 +31,7 @@ | == snap wheel3 grid=100x30 cursor=4,15 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/scroll/cwd Del nm /tmp/pardes-snap/scroll/cwd Del +| NOR /tmp/pardes-snap/scroll/cwd Del NOR /tmp/pardes-snap/scroll/cwd Del | 185 | 186 s.txt | 187 @@ -46,7 +46,7 @@ | 196 | 197 | 198 -| nm /tmp/pardes-snap/scroll/cwd Del +| NOR /tmp/pardes-snap/scroll/cwd Del | | s.txt | @@ -62,7 +62,7 @@ | == snap gutter-up grid=100x30 cursor=4,15 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/scroll/cwd Del nm /tmp/pardes-snap/scroll/cwd Del +| NOR /tmp/pardes-snap/scroll/cwd Del NOR /tmp/pardes-snap/scroll/cwd Del | 178 | 179 s.txt | 180 @@ -77,7 +77,7 @@ | 189 | 190 | 191 -| nm /tmp/pardes-snap/scroll/cwd Del +| NOR /tmp/pardes-snap/scroll/cwd Del | | s.txt | @@ -93,7 +93,7 @@ | == snap gutter-down grid=100x30 cursor=4,15 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/scroll/cwd Del nm /tmp/pardes-snap/scroll/cwd Del +| NOR /tmp/pardes-snap/scroll/cwd Del NOR /tmp/pardes-snap/scroll/cwd Del | 180 | 181 s.txt | 182 @@ -108,7 +108,7 @@ | 191 | 192 | 193 -| nm /tmp/pardes-snap/scroll/cwd Del +| NOR /tmp/pardes-snap/scroll/cwd Del | | s.txt | @@ -124,7 +124,7 @@ | == snap wheel-down grid=100x30 cursor=4,15 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/scroll/cwd Del nm /tmp/pardes-snap/scroll/cwd Del +| NOR /tmp/pardes-snap/scroll/cwd Del NOR /tmp/pardes-snap/scroll/cwd Del | 181 | 182 s.txt | 183 @@ -139,7 +139,7 @@ | 192 | 193 | 194 -| nm /tmp/pardes-snap/scroll/cwd Del +| NOR /tmp/pardes-snap/scroll/cwd Del | | s.txt | @@ -155,7 +155,7 @@ | == style wheel-down |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#383c54, 52-86 #969696,#2c2a3e, 87-99 d,#2c2a3e, |2: 0-1 d,#2a2a2a, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#2a2a2a, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#2a2a2a, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -170,7 +170,7 @@ |13: 0-1 d,#2a2a2a, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#2a2a2a, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/scrolloff.golden b/test/snapshots/scrolloff.golden new file mode 100644 index 00000000..90e0e83f --- /dev/null +++ b/test/snapshots/scrolloff.golden @@ -0,0 +1,217 @@ +== snap top grid=100x30 cursor=7,2 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/scrolloff/cwd/g.txt Save De NOR /tmp/pardes-snap/scrolloff/cwd Del +| 1 line 1 +| 2 line 2 g.txt +| 3 line 3 +| 4 line 4 +| 5 line 5 +| 6 line 6 +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap edge grid=100x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/scrolloff/cwd/g.txt Save De NOR /tmp/pardes-snap/scrolloff/cwd Del +| 3 line 3 +| 4 line 4 g.txt +| 5 line 5 +| 6 line 6 +| 7 line 7 +| 8 line 8 +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap scrolled1 grid=100x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/scrolloff/cwd/g.txt Save De NOR /tmp/pardes-snap/scrolloff/cwd Del +| 4 line 4 +| 5 line 5 g.txt +| 6 line 6 +| 7 line 7 +| 8 line 8 +| 9 line 9 +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap jdown grid=100x30 cursor=7,5 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/scrolloff/cwd/g.txt Save De NOR /tmp/pardes-snap/scrolloff/cwd Del +| 8 line 8 +| 9 line 9 g.txt +| 10 line 10 +| 11 line 11 +| 12 line 12 +| 13 line 13 +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap end grid=100x30 cursor=7,7 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/scrolloff/cwd/g.txt Save De NOR /tmp/pardes-snap/scrolloff/cwd Del +| 36 line 36 +| 37 line 37 g.txt +| 38 line 38 +| 39 line 39 +| 40 line 40 +| 41 +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap kup grid=100x30 cursor=7,4 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/scrolloff/cwd/g.txt Save De NOR /tmp/pardes-snap/scrolloff/cwd Del +| 31 line 31 +| 32 line 32 g.txt +| 33 line 33 +| 34 line 34 +| 35 line 35 +| 36 line 36 +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| +== snap top2 grid=100x30 cursor=7,2 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/scrolloff/cwd/g.txt Save De NOR /tmp/pardes-snap/scrolloff/cwd Del +| 1 line 1 +| 2 line 2 g.txt +| 3 line 3 +| 4 line 4 +| 5 line 5 +| 6 line 6 +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| NOR /tmp/pardes-snap/scrolloff/cwd Del +| +| g.txt +| +| +| +| +| +| +| +| +| +| +| diff --git a/test/snapshots/scrolloff.snap b/test/snapshots/scrolloff.snap new file mode 100644 index 00000000..e231e8de --- /dev/null +++ b/test/snapshots/scrolloff.snap @@ -0,0 +1,41 @@ +# 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 30 100 +wait 8000 g.txt +stable 700 20000 +# right-click the g.txt name in the greeting ls -> file pane, 9 body rows +press right 4 4 +release right 4 4 +wait 10000 line 3 +stable 700 15000 +press left 10 3 +release left 10 3 +stable 400 5000 +# (b) gg: cursor CAN sit on the top body row, no forced scroll +key g g +stable 400 5000 +snap top +# (a) five j's reach the bottom margin (visual row 5 of 9) without scrolling... +key j j j j j +stable 400 5000 +snap edge +# ...the sixth j scrolls: view slides one line, cursor holds the margin +key j +stable 400 5000 +snap scrolled1 +key j j j j +stable 400 5000 +snap jdown +# (d) G: bottom clamp, view stops at EOF-at-bottom, cursor on the bottom row +key G +stable 400 5000 +snap end +# (c) k-walk up: cursor climbs to the top margin, then the view scrolls +key k k k k k k k k +stable 400 5000 +snap kup +# (b) again from deep in the file: gg puts the cursor back on the top row +key g g +stable 400 5000 +snap top2 diff --git a/test/snapshots/syntax.actual b/test/snapshots/syntax.actual deleted file mode 100644 index d8c537b7..00000000 --- a/test/snapshots/syntax.actual +++ /dev/null @@ -1,124 +0,0 @@ -== snap zig-open grid=100x30 cursor=7,2 -|Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/syntax/cwd/demo.zig Save Del nm /tmp/pardes-snap/syntax/cwd Del -| 1 const std = @import("std"); // greet -| 2 pub fn main() void { demo.zig -| 3 var x: u32 = 42; -| 4 _ = x; -| 5 } -| -| -| -| -| nm /tmp/pardes-snap/syntax/cwd Del -| -| demo.zig -| -| -| -| demo.zig -| -| -| -| nm /tmp/pardes-snap/syntax/cwd Del -| -| demo.zig -| -| -| -| -| -| -== style zig-open -|0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, -|2: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-18 d,d, 19-25 #cc70d8,d,b 26-26 d,d, 27-31 #8ab87a,d, 32-34 d,d, 35-42 #f0f0f0,d,b 43-49 d,d, 50-51 d,#525252, 52-99 d,d, -|3: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-10 d,d, 11-12 #cc70d8,d,b 13-49 d,d, 50-51 d,#525252, 52-99 d,d, -|4: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-23 d,d, 24-25 #d0c070,d, 26-49 d,d, 50-51 d,#525252, 52-99 d,d, -|5: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|6: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|7: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, -|12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, -|22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|25: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|26: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|27: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|28: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -== style colors-off -|0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, -|2: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|3: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|4: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|5: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|6: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|7: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, -|12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, -|22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|25: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|26: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|27: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|28: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -== style colors-on -|0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, -|2: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-18 d,d, 19-25 #cc70d8,d,b 26-26 d,d, 27-31 #8ab87a,d, 32-34 d,d, 35-42 #f0f0f0,d,b 43-49 d,d, 50-51 d,#525252, 52-99 d,d, -|3: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-10 d,d, 11-12 #cc70d8,d,b 13-49 d,d, 50-51 d,#525252, 52-99 d,d, -|4: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-23 d,d, 24-25 #d0c070,d, 26-49 d,d, 50-51 d,#525252, 52-99 d,d, -|5: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|6: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|7: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, -|12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, -|22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|25: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|26: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|27: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|28: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/syntax.golden b/test/snapshots/syntax.golden index 310d6d64..f6d673a3 100644 --- a/test/snapshots/syntax.golden +++ b/test/snapshots/syntax.golden @@ -1,28 +1,28 @@ == snap zig-open grid=100x30 cursor=7,2 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/syntax/cwd/demo.zig Save Del nm /tmp/pardes-snap/syntax/cwd Del +| NOR /tmp/pardes-snap/syntax/cwd/demo.zig Save De NOR /tmp/pardes-snap/syntax/cwd Del | 1 const std = @import("std"); // greet | 2 pub fn main() void { demo.zig | 3 var x: u32 = 42; | 4 _ = x; | 5 } +|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +| NOR /tmp/pardes-snap/syntax/cwd Del | +| demo.zig | | | -| nm /tmp/pardes-snap/syntax/cwd Del -| -| demo.zig +| demo.zig | +| NOR /tmp/pardes-snap/syntax/cwd Del | +| demo.zig | -| demo.zig | | | -| nm /tmp/pardes-snap/syntax/cwd Del | -| demo.zig | | | @@ -31,27 +31,27 @@ | == style zig-open |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, -|2: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-18 d,d, 19-25 #cc70d8,d,b 26-26 d,d, 27-31 #8ab87a,d, 32-34 d,d, 35-42 #f0f0f0,d,b 43-49 d,d, 50-51 d,#525252, 52-99 d,d, +|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-86 #969696,#2c2a3e, 87-99 d,#2c2a3e, +|2: 0-1 d,#525252, 2-6 #969696,#2c2a3e, 7-18 d,d, 19-25 #cc70d8,d,b 26-26 d,d, 27-31 #8ab87a,d, 32-34 d,d, 35-42 #f0f0f0,d,b 43-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-10 d,d, 11-12 #cc70d8,d,b 13-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-23 d,d, 24-25 #d0c070,d, 26-49 d,d, 50-51 d,#525252, 52-99 d,d, |5: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |6: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |7: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|8: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|11: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|21: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -62,27 +62,27 @@ |29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, == style colors-off |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, -|2: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, +|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-86 #969696,#2c2a3e, 87-99 d,#2c2a3e, +|2: 0-1 d,#525252, 2-6 #969696,#2c2a3e, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |5: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |6: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |7: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|8: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|11: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|21: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -93,27 +93,27 @@ |29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, == style colors-on |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, -|2: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-18 d,d, 19-25 #cc70d8,d,b 26-26 d,d, 27-31 #8ab87a,d, 32-34 d,d, 35-42 #f0f0f0,d,b 43-49 d,d, 50-51 d,#525252, 52-99 d,d, +|1: 0-1 d,#6e4fd0, 2-49 #969696,#2c2a3e, 50-51 d,#383c54, 52-86 #969696,#2c2a3e, 87-99 d,#2c2a3e, +|2: 0-1 d,#525252, 2-6 #969696,#2c2a3e, 7-18 d,d, 19-25 #cc70d8,d,b 26-26 d,d, 27-31 #8ab87a,d, 32-34 d,d, 35-42 #f0f0f0,d,b 43-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-10 d,d, 11-12 #cc70d8,d,b 13-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-23 d,d, 24-25 #d0c070,d, 26-49 d,d, 50-51 d,#525252, 52-99 d,d, |5: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |6: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, |7: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|8: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|9: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|10: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-49 d,d, 50-51 d,#525252, 52-99 d,d, -|11: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|8: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|9: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|10: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|11: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |12: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-36 #969696,#2c2a3e, 37-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |20: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|21: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|21: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |22: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |23: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |24: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/tag.golden b/test/snapshots/tag.golden index 9275777b..9632ab6a 100644 --- a/test/snapshots/tag.golden +++ b/test/snapshots/tag.golden @@ -1,6 +1,6 @@ -== snap tag-focus grid=100x30 cursor=33,1 +== snap tag-focus grid=100x30 cursor=34,1 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/tag/cwd Del nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwd Del NOR /tmp/pardes-snap/tag/cwd Del | | t.txt t.txt | @@ -15,7 +15,7 @@ | | | -| nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwd Del | | t.txt | @@ -29,9 +29,9 @@ | | | -== snap tag-typed grid=100x30 cursor=46,1 +== snap tag-typed grid=100x30 cursor=47,1 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/tag/cwd Del echo TAG''OK nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwd Del echo TAG''OK NOR /tmp/pardes-snap/tag/cwd Del | | t.txt t.txt | @@ -46,7 +46,7 @@ | | | -| nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwd Del | | t.txt | @@ -60,9 +60,9 @@ | | | -== snap tag-exec grid=100x30 cursor=45,1 +== snap tag-exec grid=100x30 cursor=46,1 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/tag/cwd Del echo TAG''OK nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwd Del echo TAG''OK NOR /tmp/pardes-snap/tag/cwd Del | | t.txt t.txt | @@ -77,7 +77,7 @@ | | | -| nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwd Del | | t.txt | @@ -91,9 +91,9 @@ | | | -== snap tag-vsel grid=100x30 cursor=31,1 +== snap tag-vsel grid=100x30 cursor=32,1 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/tag/cwd Del echo TAG''OK nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwd Del echo TAG''OK NOR /tmp/pardes-snap/tag/cwd Del | | t.txt t.txt | @@ -108,7 +108,7 @@ | | | -| nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwd Del | | t.txt | @@ -124,7 +124,7 @@ | == style tag-vsel |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-28 #969696,#2c2a3e, 29-31 #d8c8a8,#4a3a1e, 32-45 #969696,#2c2a3e, 46-49 d,#2c2a3e, 50-51 d,#383c54, 52-82 #969696,#2c2a3e, 83-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-29 #969696,#2c2a3e, 30-32 #d8c8a8,#4a3a1e, 33-46 #969696,#2c2a3e, 47-49 d,#2c2a3e, 50-51 d,#383c54, 52-83 #969696,#2c2a3e, 84-99 d,#2c2a3e, |2: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -139,7 +139,7 @@ |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#383c54, 2-32 #969696,#2c2a3e, 33-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-33 #969696,#2c2a3e, 34-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -153,9 +153,9 @@ |27: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |28: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |29: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -== snap tag-del grid=100x30 cursor=29,1 +== snap tag-del grid=100x30 cursor=30,1 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/tag/cwdl echo TAG''OK nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwdl echo TAG''OK NOR /tmp/pardes-snap/tag/cwd Del | | t.txt t.txt | @@ -170,7 +170,7 @@ | | | -| nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwd Del | | t.txt | @@ -186,7 +186,7 @@ | == snap tag-exit grid=100x30 cursor=4,6 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/tag/cwdl echo TAG''OK nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwdl echo TAG''OK NOR /tmp/pardes-snap/tag/cwd Del | | t.txt t.txt | @@ -201,7 +201,7 @@ | | | -| nm /tmp/pardes-snap/tag/cwd Del +| NOR /tmp/pardes-snap/tag/cwd Del | | t.txt | diff --git a/test/snapshots/theme.golden b/test/snapshots/theme.golden index b90e0011..5435eee4 100644 --- a/test/snapshots/theme.golden +++ b/test/snapshots/theme.golden @@ -1,6 +1,6 @@ == snap acme grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/theme/cwd Del nm /tmp/pardes-snap/theme/cwd Del +| NOR /tmp/pardes-snap/theme/cwd Del NOR /tmp/pardes-snap/theme/cwd Del | | t.txt t.txt | @@ -15,7 +15,7 @@ | | | -| nm /tmp/pardes-snap/theme/cwd Del +| NOR /tmp/pardes-snap/theme/cwd Del | | t.txt | @@ -31,7 +31,7 @@ | == style acme |0: 0-44 #000000,#eaffff, 45-99 d,#eaffff, -|1: 0-1 d,#6e4fd0, 2-34 #000000,#eaffff, 35-49 d,#eaffff, 50-51 d,#383c54, 52-84 #000000,#eaffff, 85-99 d,#eaffff, +|1: 0-1 d,#6e4fd0, 2-35 #000000,#eaffff, 36-49 d,#eaffff, 50-51 d,#383c54, 52-85 #000000,#eaffff, 86-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, @@ -46,7 +46,7 @@ |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 d,#383c54, 2-34 #000000,#eaffff, 35-49 d,#eaffff, 50-51 d,#ffffea, 52-99 #000000,#ffffea, +|16: 0-1 d,#383c54, 2-35 #000000,#eaffff, 36-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, @@ -62,7 +62,7 @@ |29: 0-1 d,#ffffea, 2-49 #000000,#ffffea, 50-51 d,#ffffea, 52-99 #000000,#ffffea, == snap colors-off grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/theme/cwd Del nm /tmp/pardes-snap/theme/cwd Del +| NOR /tmp/pardes-snap/theme/cwd Del NOR /tmp/pardes-snap/theme/cwd Del | | t.txt t.txt | @@ -77,7 +77,7 @@ | | | -| nm /tmp/pardes-snap/theme/cwd Del +| NOR /tmp/pardes-snap/theme/cwd Del | | t.txt | @@ -93,7 +93,7 @@ | == style colors-off |0: 0-44 #000000,#eaffff, 45-99 d,#eaffff, -|1: 0-1 d,#6e4fd0, 2-34 #000000,#eaffff, 35-49 d,#eaffff, 50-51 d,#383c54, 52-84 #000000,#eaffff, 85-99 d,#eaffff, +|1: 0-1 d,#6e4fd0, 2-35 #000000,#eaffff, 36-49 d,#eaffff, 50-51 d,#383c54, 52-85 #000000,#eaffff, 86-99 d,#eaffff, |2: 0-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, @@ -108,7 +108,7 @@ |13: 0-99 d,#ffffea, |14: 0-99 d,#ffffea, |15: 0-99 d,#ffffea, -|16: 0-1 d,#383c54, 2-34 #000000,#eaffff, 35-49 d,#eaffff, 50-99 d,#ffffea, +|16: 0-1 d,#383c54, 2-35 #000000,#eaffff, 36-49 d,#eaffff, 50-99 d,#ffffea, |17: 0-99 d,#ffffea, |18: 0-1 d,#ffffea, 2-6 #000000,#ffffea, 7-99 d,#ffffea, |19: 0-99 d,#ffffea, @@ -124,7 +124,7 @@ |29: 0-99 d,#ffffea, == snap dark-again grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/theme/cwd Del nm /tmp/pardes-snap/theme/cwd Del +| NOR /tmp/pardes-snap/theme/cwd Del NOR /tmp/pardes-snap/theme/cwd Del | | t.txt t.txt | @@ -139,7 +139,7 @@ | | | -| nm /tmp/pardes-snap/theme/cwd Del +| NOR /tmp/pardes-snap/theme/cwd Del | | t.txt | @@ -155,7 +155,7 @@ | == style dark-again |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#383c54, 52-84 #969696,#2c2a3e, 85-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#383c54, 52-85 #969696,#2c2a3e, 86-99 d,#2c2a3e, |2: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |3: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |4: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, @@ -170,7 +170,7 @@ |13: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |14: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |15: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, -|16: 0-1 d,#383c54, 2-34 #969696,#2c2a3e, 35-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, +|16: 0-1 d,#383c54, 2-35 #969696,#2c2a3e, 36-49 d,#2c2a3e, 50-51 d,#525252, 52-99 d,d, |17: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |18: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, |19: 0-1 d,#525252, 2-49 d,d, 50-51 d,#525252, 52-99 d,d, diff --git a/test/snapshots/tty.golden b/test/snapshots/tty.golden index 7e6bebc5..63e4a760 100644 --- a/test/snapshots/tty.golden +++ b/test/snapshots/tty.golden @@ -1,6 +1,6 @@ == snap tty-on grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| sy /tmp/pardes-snap/tty/cwd Del nm /tmp/pardes-snap/tty/cwd Del +| TTY /tmp/pardes-snap/tty/cwd Del NOR /tmp/pardes-snap/tty/cwd Del | $ ls | m.txt m.txt | $ @@ -15,7 +15,7 @@ | | | -| nm /tmp/pardes-snap/tty/cwd Del +| NOR /tmp/pardes-snap/tty/cwd Del | | m.txt | @@ -31,7 +31,7 @@ | == snap tty-echo grid=100x30 cursor=4,6 |Kill Newcol Tutor Debug Colors NextColor Dump -| sy /tmp/pardes-snap/tty/cwd Del nm /tmp/pardes-snap/tty/cwd Del +| TTY /tmp/pardes-snap/tty/cwd Del NOR /tmp/pardes-snap/tty/cwd Del | $ ls | m.txt m.txt | $ echo SNAP''OK @@ -46,7 +46,7 @@ | | | -| nm /tmp/pardes-snap/tty/cwd Del +| NOR /tmp/pardes-snap/tty/cwd Del | | m.txt | @@ -62,7 +62,7 @@ | == snap tty-off grid=100x30 cursor=4,6 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/tty/cwd Del nm /tmp/pardes-snap/tty/cwd Del +| NOR /tmp/pardes-snap/tty/cwd Del NOR /tmp/pardes-snap/tty/cwd Del | | m.txt m.txt | @@ -77,7 +77,7 @@ | | | -| nm /tmp/pardes-snap/tty/cwd Del +| NOR /tmp/pardes-snap/tty/cwd Del | | m.txt | diff --git a/test/snapshots/ttylook.golden b/test/snapshots/ttylook.golden new file mode 100644 index 00000000..8465dbea --- /dev/null +++ b/test/snapshots/ttylook.golden @@ -0,0 +1,279 @@ +== snap lsrow grid=120x30 cursor=2,2 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/ttylook/cwd/big.txt Save Del NOR /tmp/pardes-snap/ttylook/cwd Del +| 1 line 1 +| 2 line 2 big.txt plain.txt sub +| 3 line 3 +| 4 line 4 +| 5 line 5 +| 6 line 6 +| NOR /tmp/pardes-snap/ttylook/cwd Del +| +| plain.txt +| big.txt:33 +| zz +| +| DONE +| +| NOR /tmp/pardes-snap/ttylook/cwd Del +| +| big.txt plain.txt sub +| +| +| +| +| +| +| +| +| +| +| +== style lsrow +|0: 0-44 #969696,#2c2a3e, 45-119 d,#2c2a3e, +|1: 0-1 d,#383c54, 2-50 #969696,#2c2a3e, 51-59 d,#2c2a3e, 60-61 d,#383c54, 62-97 #969696,#2c2a3e, 98-119 d,#2c2a3e, +|2: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|3: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|4: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|5: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|6: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|7: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|8: 0-1 d,#6e4fd0, 2-37 #969696,#2c2a3e, 38-59 d,#2c2a3e, 60-61 d,#525252, 62-119 d,d, +|9: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|10: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|11: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|12: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|13: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|14: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|15: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|16: 0-1 d,#383c54, 2-37 #969696,#2c2a3e, 38-59 d,#2c2a3e, 60-61 d,#525252, 62-119 d,d, +|17: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|18: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|19: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|20: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|21: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|22: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|23: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|24: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|25: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|26: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|27: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|28: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|29: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +== snap line20 grid=120x30 cursor=2,12 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/ttylook/cwd/big.txt Save Del NOR /tmp/pardes-snap/ttylook/cwd Del +| 17 line 17 +| 18 line 18 big.txt plain.txt sub +| 19 line 19 +| 20 line 20 +| 21 line 21 +| 22 line 22 +| NOR /tmp/pardes-snap/ttylook/cwd Del +| big.txt plain.txt sub +| +| zz +| big.txt:20 +| ww +| +| plain.txt +| NOR /tmp/pardes-snap/ttylook/cwd Del +| +| big.txt plain.txt sub +| +| +| +| +| +| +| +| +| +| +| +== snap plain grid=120x30 cursor=2,12 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/ttylook/cwd/big.txt Save Del NOR /tmp/pardes-snap/ttylook/cwd Del +| 17 line 17 +| 18 line 18 big.txt plain.txt sub +| NOR /tmp/pardes-snap/ttylook/cwd/plain.txt Save Del +| 1 just text +| +| +| NOR /tmp/pardes-snap/ttylook/cwd Del +| big.txt:20 +| ww +| +| plain.txt +| big.txt:33 +| zz +| +| NOR /tmp/pardes-snap/ttylook/cwd Del +| +| big.txt plain.txt sub +| +| +| +| +| +| +| +| +| +| +| +== snap line33 grid=120x30 cursor=2,12 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/ttylook/cwd/big.txt Save Del NOR /tmp/pardes-snap/ttylook/cwd Del +| 32 line 32 +| 33 line 33 big.txt plain.txt sub +| NOR /tmp/pardes-snap/ttylook/cwd/plain.txt Save Del +| 1 just text +| +| +| NOR /tmp/pardes-snap/ttylook/cwd Del +| ww +| +| plain.txt +| big.txt:33 +| zz +| +| DONE +| NOR /tmp/pardes-snap/ttylook/cwd Del +| +| big.txt plain.txt sub +| +| +| +| +| +| +| +| +| +| +| +== snap back grid=120x30 cursor=2,12 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/ttylook/cwd/big.txt Save Del NOR /tmp/pardes-snap/ttylook/cwd Del +| 32 line 32 +| 33 line 33 big.txt plain.txt sub +| NOR /tmp/pardes-snap/ttylook/cwd/plain.txt Save Del +| 1 just text +| +| +| NOR /tmp/pardes-snap/ttylook/cwd Del +| big.txt:20 +| ww +| +| plain.txt +| big.txt:33 +| zz +| +| NOR /tmp/pardes-snap/ttylook/cwd Del +| +| big.txt plain.txt sub +| +| +| +| +| +| +| +| +| +| +| +== style back +|0: 0-44 #969696,#2c2a3e, 45-119 d,#2c2a3e, +|1: 0-1 d,#383c54, 2-50 #969696,#2c2a3e, 51-59 d,#2c2a3e, 60-61 d,#383c54, 62-97 #969696,#2c2a3e, 98-119 d,#2c2a3e, +|2: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|3: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|4: 0-1 d,#383c54, 2-52 #969696,#2c2a3e, 53-59 d,#2c2a3e, 60-61 d,#525252, 62-119 d,d, +|5: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|6: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|7: 0-1 d,#525252, 2-6 #5a5a5a,d, 7-59 d,d, 60-61 d,#525252, 62-119 d,d, +|8: 0-1 d,#6e4fd0, 2-37 #969696,#2c2a3e, 38-59 d,#2c2a3e, 60-61 d,#525252, 62-119 d,d, +|9: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|10: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|11: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|12: 0-1 d,#525252, 2-59 #d8c8a8,#4a3a1e, 60-61 d,#525252, 62-119 d,d, +|13: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|14: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|15: 0-1 d,#2a2a2a, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|16: 0-1 d,#383c54, 2-37 #969696,#2c2a3e, 38-59 d,#2c2a3e, 60-61 d,#525252, 62-119 d,d, +|17: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|18: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|19: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|20: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|21: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|22: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|23: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|24: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|25: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|26: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|27: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|28: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +|29: 0-1 d,#525252, 2-59 d,d, 60-61 d,#525252, 62-119 d,d, +== snap insert grid=120x30 cursor=2,12 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/ttylook/cwd/big.txt Save Del NOR /tmp/pardes-snap/ttylook/cwd Del +| 32 line 32 +| 33 line 33 big.txt plain.txt sub +| NOR /tmp/pardes-snap/ttylook/cwd/plain.txt Save Del +| 1 just text +| +| +| NOR /tmp/pardes-snap/ttylook/cwd Del +| big.txt:20 +| ww +| +| nnplain.txt +| big.txt:33 +| zz +| +| NOR /tmp/pardes-snap/ttylook/cwd Del +| +| big.txt plain.txt sub +| +| +| +| +| +| +| +| +| +| +| +== snap noop grid=120x30 cursor=2,13 +|Kill Newcol Tutor Debug Colors NextColor Dump +| NOR /tmp/pardes-snap/ttylook/cwd/big.txt Save Del NOR /tmp/pardes-snap/ttylook/cwd Del +| 32 line 32 +| 33 line 33 big.txt plain.txt sub +| NOR /tmp/pardes-snap/ttylook/cwd/plain.txt Save Del +| 1 just text +| +| +| NOR /tmp/pardes-snap/ttylook/cwd Del +| +| DONE +| +| NOR /tmp/pardes-snap/ttylook/cwd/sub Del +| +| big.txt plain.txt sub +| +| NOR /tmp/pardes-snap/ttylook/cwd Del +| +| big.txt plain.txt sub +| +| +| +| +| +| +| +| +| +| +| diff --git a/test/snapshots/ttylook.snap b/test/snapshots/ttylook.snap new file mode 100644 index 00000000..648dcd42 --- /dev/null +++ b/test/snapshots/ttylook.snap @@ -0,0 +1,77 @@ +# tty n/N look-motion (normal mode only): n selects the next output row of +# the terminal whose leading file-ish word looks somewhere (file, path:NNN — +# resolved by the look machinery, prompt/echo rows blanked via the OSC 133 +# marks) and looks it; plain rows are skipped; N steps back up. Insert-mode +# n still types (run splice); with nothing lookable n is a no-op. +lines big.txt 40 +file plain.txt just text +dirmk sub +start 30 120 +wait 8000 big.txt +stable 700 20000 +# real shell output mixing lookable and plain rows (two short printfs so the +# echoes never wrap; echo rows are prompt-marked and invisible to the walk) +key c-b +stable 600 8000 +text printf 'zz\nbig.txt:20\nww\n' +key enter +text printf 'plain.txt\nbig.txt:33\nzz\n' +key enter +text echo DO''NE +key enter +wait 8000 DONE +stable 700 15000 +key c-b +stable 600 8000 +# from the top: n skips nothing-rows, lands on the ls row (big.txt ...) first +key g g +stable 400 5000 +key n +stable 700 15000 +snap lsrow +snapstyle lsrow +# next hits: big.txt:20 (file pane scrolls there), plain.txt, big.txt:33 +key n +stable 700 15000 +snap line20 +key n +stable 700 15000 +snap plain +key n +stable 700 15000 +snap line33 +# N walks back up to the plain.txt row +key N +stable 700 15000 +snap back +snapstyle back +# insert mode: n types (a run splice), it does not step +key i +text nn +key esc +settle 700 +stable 400 5000 +snap insert +key u +stable 400 5000 +# a shell with nothing lookable: cd into the empty subdir (the old ls row no +# longer resolves from there), print plain rows — n has nowhere to go +key a-n +stable 700 15000 +key c-b +stable 600 8000 +text cd sub +key enter +text printf 'qq\nrr\n' +key enter +text echo O''VER +key enter +wait 8000 OVER +stable 700 15000 +key c-b +stable 600 8000 +key g g +stable 400 5000 +key n +stable 400 5000 +snap noop diff --git a/test/snapshots/ttyonly.golden b/test/snapshots/ttyonly.golden index 20ddf792..f8722061 100644 --- a/test/snapshots/ttyonly.golden +++ b/test/snapshots/ttyonly.golden @@ -1,6 +1,6 @@ == snap ttyonly grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| sy /tmp/pardes-snap/ttyonly/cwd Del +| TTY /tmp/pardes-snap/ttyonly/cwd Del | $ echo TTY''ONLY | TTYONLY | $ @@ -31,7 +31,7 @@ | == style ttyonly |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#6e4fd0, 2-36 #969696,#2c2a3e, 37-99 d,#2c2a3e, +|1: 0-1 d,#6e4fd0, 2-37 #969696,#2c2a3e, 38-99 d,#2c2a3e, |2: 0-1 d,#525252, 2-99 d,d, |3: 0-1 d,#525252, 2-99 d,d, |4: 0-1 d,#525252, 2-99 d,d, diff --git a/test/snapshots/tutor.golden b/test/snapshots/tutor.golden index 55d66c9b..d4c5d644 100644 --- a/test/snapshots/tutor.golden +++ b/test/snapshots/tutor.golden @@ -1,16 +1,13 @@ == snap tutor grid=100x30 cursor=7,2 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /Tutor Save Del nm /tmp/pardes-snap/tutor/cwd Del +| NOR /Tutor Save Del NOR /tmp/pardes-snap/tutor/cwd Del | 1 | 2 PARDES TUTOR | 3 tmux + vi + acme, from | 4 | 5 The model is acme's: EVERYTHING is | 6 the same way. Modal editing (helix- -| 7 Press j until you reach the introdu -| 8 -| 9 -| nm /tmp/pardes-snap/tutor/cwd Del +| NOR /tmp/pardes-snap/tutor/cwd Del | | | @@ -18,9 +15,12 @@ | | | +| NOR /tmp/pardes-snap/tutor/cwd Del +| +| +| | | -| nm /tmp/pardes-snap/tutor/cwd Del | | | diff --git a/test/snapshots/windowops.golden b/test/snapshots/windowops.golden index 061ceca9..a7750e33 100644 --- a/test/snapshots/windowops.golden +++ b/test/snapshots/windowops.golden @@ -1,6 +1,6 @@ == snap hover-v grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del ╎ nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del ╎ NOR /tmp/pardes-snap/windowops/cwd Del | ╎ | w.txt ╎ w.txt | ╎ @@ -15,7 +15,7 @@ | ╎ | ╎ | ╎ -| nm /tmp/pardes-snap/windowops/cwd Del ╎ +| NOR /tmp/pardes-snap/windowops/cwd Del ╎ | ╎ | w.txt ╎ | ╎ @@ -31,7 +31,7 @@ | ╎ == snap hover-h grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt w.txt | @@ -46,7 +46,7 @@ | | |╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ -| nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt | @@ -62,7 +62,7 @@ | == snap border-drag grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del╎ nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd De╎ NOR /tmp/pardes-snap/windowops/cwd Del | ╎ | w.txt ╎ w.txt | ╎ @@ -77,7 +77,7 @@ | ╎ | ╎ | ╎ -| nm /tmp/pardes-snap/windowops/cwd Del╎ +| NOR /tmp/pardes-snap/windowops/cwd De╎ | ╎ | w.txt ╎ | ╎ @@ -93,7 +93,7 @@ | ╎ == snap border-done grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del╎ nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd De╎ NOR /tmp/pardes-snap/windowops/cwd Del | ╎ | w.txt ╎ w.txt | ╎ @@ -108,7 +108,7 @@ | ╎ | ╎ | ╎ -| nm /tmp/pardes-snap/windowops/cwd Del╎ +| NOR /tmp/pardes-snap/windowops/cwd De╎ | ╎ | w.txt ╎ | ╎ @@ -124,7 +124,7 @@ | ╎ == snap hborder-done grid=100x30 cursor=4,4 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt w.txt | @@ -135,7 +135,7 @@ | | |╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ -| nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt | @@ -155,7 +155,7 @@ | == snap move-preview grid=100x30 cursor=4,15 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt w.txt | @@ -166,7 +166,7 @@ | | | -| nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt | @@ -186,7 +186,7 @@ | == snap moved grid=100x30 cursor=4,15 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt w.txt | @@ -197,7 +197,7 @@ | | | -| nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt | @@ -215,30 +215,30 @@ | | | -== snap altn grid=100x30 cursor=4,23 +== snap altn grid=100x30 cursor=4,19 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt w.txt | | | | -| nm /tmp/pardes-snap/windowops/cwd Del | -| w.txt | | | +| NOR /tmp/pardes-snap/windowops/cwd Del | +| w.txt | +| NOR /tmp/pardes-snap/windowops/cwd Del | +| w.txt | | | -| nm /tmp/pardes-snap/windowops/cwd Del | -| w.txt | | | @@ -246,30 +246,30 @@ | | | -== snap focus-left grid=100x30 cursor=4,23 +== snap focus-left grid=100x30 cursor=4,19 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt w.txt | | | | -| nm /tmp/pardes-snap/windowops/cwd Del | -| w.txt | | | +| NOR /tmp/pardes-snap/windowops/cwd Del | +| w.txt | +| NOR /tmp/pardes-snap/windowops/cwd Del | +| w.txt | | | -| nm /tmp/pardes-snap/windowops/cwd Del | -| w.txt | | | @@ -277,30 +277,30 @@ | | | -== snap debug-on grid=100x30 cursor=4,23 +== snap debug-on grid=100x30 cursor=4,19 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del nm /tmp/pardes-snap/windowop╭────────────────────────────╮ +| NOR /tmp/pardes-snap/windowops/cwd Del NOR /tmp/pardes-snap/windowo╭────────────────────────────╮ | │pardes resizes=1 │ | w.txt w.txt │terms 4 cols 2 │ -| │active #3 38x9 │ -| │scroll 0/9 │ +| │active #3 38x13 │ +| │scroll 0/13 │ | │pinch 1.0000 │ | │tscroll 0.0000 │ -| nm /tmp/pardes-snap/windowops/cwd Del ╰────────────────────────────╯ -| -| w.txt +| ╰────────────────────────────╯ | | | +| NOR /tmp/pardes-snap/windowops/cwd Del | +| w.txt | +| NOR /tmp/pardes-snap/windowops/cwd Del | +| w.txt | | | -| nm /tmp/pardes-snap/windowops/cwd Del | -| w.txt | | | @@ -310,26 +310,26 @@ | == style debug-on |0: 0-44 #969696,#2c2a3e, 45-99 d,#2c2a3e, -|1: 0-1 d,#383c54, 2-38 #969696,#2c2a3e, 39-39 d,#2c2a3e, 40-41 d,#383c54, 42-69 #969696,#2c2a3e, 70-99 d,d, +|1: 0-1 d,#383c54, 2-39 #969696,#2c2a3e, 40-41 d,#383c54, 42-69 #969696,#2c2a3e, 70-99 d,d, |2: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-70 d,d, 71-87 #969696,d, 88-98 d,#2a2a2a, 99-99 d,d, |3: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-70 d,d, 71-85 #969696,d, 86-98 d,#2a2a2a, 99-99 d,d, -|4: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-70 d,d, 71-85 #969696,d, 86-98 d,#2a2a2a, 99-99 d,d, -|5: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-70 d,d, 71-80 #969696,d, 81-98 d,#2a2a2a, 99-99 d,d, +|4: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-70 d,d, 71-86 #969696,d, 87-98 d,#2a2a2a, 99-99 d,d, +|5: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-70 d,d, 71-81 #969696,d, 82-98 d,#2a2a2a, 99-99 d,d, |6: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-70 d,d, 71-83 #969696,d, 84-98 d,#2a2a2a, 99-99 d,d, |7: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-70 d,d, 71-85 #969696,d, 86-98 d,#2a2a2a, 99-99 d,d, -|8: 0-1 d,#383c54, 2-38 #969696,#2c2a3e, 39-39 d,#2c2a3e, 40-41 d,#525252, 42-99 d,d, +|8: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |9: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |10: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |11: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, -|12: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, +|12: 0-1 d,#383c54, 2-39 #969696,#2c2a3e, 40-41 d,#525252, 42-99 d,d, |13: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |14: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |15: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, -|16: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, +|16: 0-1 d,#6e4fd0, 2-39 #969696,#2c2a3e, 40-41 d,#525252, 42-99 d,d, |17: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |18: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |19: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, -|20: 0-1 d,#6e4fd0, 2-38 #969696,#2c2a3e, 39-39 d,#2c2a3e, 40-41 d,#525252, 42-99 d,d, +|20: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |21: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |22: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |23: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, @@ -339,30 +339,30 @@ |27: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |28: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, |29: 0-1 d,#525252, 2-39 d,d, 40-41 d,#525252, 42-99 d,d, -== snap debug-off grid=100x30 cursor=4,23 +== snap debug-off grid=100x30 cursor=4,19 |Kill Newcol Tutor Debug Colors NextColor Dump -| nm /tmp/pardes-snap/windowops/cwd Del nm /tmp/pardes-snap/windowops/cwd Del +| NOR /tmp/pardes-snap/windowops/cwd Del NOR /tmp/pardes-snap/windowops/cwd Del | | w.txt w.txt | | | | -| nm /tmp/pardes-snap/windowops/cwd Del | -| w.txt | | | +| NOR /tmp/pardes-snap/windowops/cwd Del | +| w.txt | +| NOR /tmp/pardes-snap/windowops/cwd Del | +| w.txt | | | -| nm /tmp/pardes-snap/windowops/cwd Del | -| w.txt | | | |
