diff options
Diffstat (limited to 'test')
29 files changed, 319 insertions, 171 deletions
@@ -121,6 +121,10 @@ def look(client, path, source=None): client.write(f'/pane/{serial}/look', f'{path}\n'.encode()) results = [int(row) for row in client.read('/look').split()] assert len(results) == 1 and results[0] != serial, (path, results) + # The scratch it looked from goes: a column holds only so many panes, + # each its tag and two rows. + if source is None: + client.remove(f'/pane/{serial}') return results[0] @@ -129,6 +133,16 @@ def execute(client, serial, command): client.write(f'/pane/{serial}/exec', f'{command}\n'.encode()) +def execute_refused(client, serial, command, words): + """A middle click on a builtin that fails: the write fails, saying why.""" + try: + execute(client, serial, command) + except OSError as why: + assert words in str(why), (command, why) + return + raise AssertionError(f'{command!r} was taken') + + def walk_tree(client, path='/', skip=('/log', '/os', '/screen')): """Stat every entry below `path`, as `find` does, without opening anything.""" seen = [] @@ -148,7 +162,8 @@ def discovery(binary, embedded=False): top = client.list('/') # A set: which files the root holds, not the order a listing gives. assert set(top) - {'src', 'shaders'} == {'README', 'index', 'status', 'focus', 'ctl', 'commands', - 'look', 'exec', 'log', 'screen', 'listeners', 'pane', 'os'}, top + 'look', 'exec', 'log', 'screen', 'listeners', 'layout', 'tag', 'tagexec', + 'pane', 'col', 'os'}, top assert 'self' not in top and 'cons' not in top and 'new' not in top, top assert ('src' in top) == embedded, (top, embedded) before = client.read('/index') @@ -180,7 +195,7 @@ def discovery(binary, embedded=False): assert client.read('/pane/1/dirty') == b'0\n' assert client.read('/pane/1/scroll') == b'1\n' fixture = int(before.split()[0]) - assert before.split()[1:3] == [b'text', b'0'] and before.endswith(b'/discovery.txt\n'), before + assert before.split()[1:3] == [b'text', b'0'] and before.rsplit(b' ', 1)[0].endswith(b'/discovery.txt'), before # /status reports the editor; /exec has nothing to report yet. status = dict(line.split(maxsplit=1) for line in client.read('/status').decode().splitlines()) assert int(status['pid']) > 0 and status['version'] and int(status['panes']) >= 1, status @@ -265,9 +280,13 @@ def discovery(binary, embedded=False): except OSError as refused: assert why in str(refused), refused commands = client.read('/commands').decode().splitlines() - assert 'Newcol root' in commands and 'Save arg pane' in commands, commands - assert all(row.split()[-1] in ('root', 'pane') for row in commands), commands - assert client.stat('/commands')['length'] == len('\n'.join(commands)) + 1 + def row(start): + return any(r == start or r.startswith(start + ' ') for r in commands) + assert row('Newcol root') and row('Save arg pane') and row('Edit arg both'), commands + # word, `arg` if it takes one, its ctl, a setting's values, then `-- ` what it does + assert all(r.split()[2 if r.split()[1] == 'arg' else 1] in ('root', 'pane', 'both') for r in commands), commands + assert row('Placement arg root acme,pardes'), commands + assert client.stat('/commands')['length'] == len('\n'.join(commands).encode()) + 1 # bytes: a description may end in … client.write(f'/pane/{first}/ctl', b'Msg said through ctl\n') assert 'said through ctl' in ''.join(cell[0] for cell in client.screen()['cells']) assert set(client.list('/pane')) == {'new', str(fixture), str(first), str(second)} @@ -416,12 +435,20 @@ def run_file(binary): assert run(client, term, b'fi\n') == b'error not run\n' # a syntax error runs nothing assert run(client, term, b"echo 'open\n") == b'error not run\n' # nor does an open quote assert run(client, term, b'true\n') == b'exit 0\n' # ...and the shell is clear after + # A pty asked for one row gets two: one loses the prompt's input + # mark, and the shell would read busy for ever. + client.write(f'/pane/{term}/pty/ctl', b'winsize 20 1\n') + time.sleep(.5) + assert run(client, term, b'true\n') == b'exit 0\n' + assert client.read(f'/pane/{term}/pty/ctl').split()[2] == b'2', client.read(f'/pane/{term}/pty/ctl') + client.write(f'/pane/{term}/pty/ctl', b'winsize 80 24\n') with Client(address) as other: slow = [] waiter = threading.Thread(target=lambda: slow.append(run(other, term, b'sleep 1\n')), daemon=True) waiter.start() time.sleep(.3) - assert run(client, term, b'true\n') == b'busy\n' + # The job the other client ran holds the tty, and says so. + assert run(client, term, b'true\n') == b'busy: sleep is running\n' waiter.join(5) assert slow == [b'exit 0\n'], slow closing = [] @@ -508,6 +535,26 @@ def python_repl_runs_one_line(binary): record = b'MX0 0 0 10 print(6*7)\n' client.rpc(118, struct.pack('<IQI', fid, 0, len(record)) + record) assert wait_for('\n42'), body() + # After the session has sat idle, the Enter still waits for + # the paste: core time is as old as the last frame then. + for n in range(5): + time.sleep(2) + line = f'print({1000 + n})'.encode() + record = b'MX0 0 0 %d %s\n' % (len(line), line) + client.rpc(118, struct.pack('<IQI', fid, 0, len(record)) + record) + assert wait_for(f'\n{1000 + n}'), (n, body()) + # More than one line, with and without a newline at the end, + # and a block with a statement after it: each runs whole, + # and the REPL is back at its prompt, not at `...`. + for code, outputs in [(b'print(11)\nprint(22)', ['11', '22']), + (b'print(33)\nprint(44)\n', ['33', '44']), + (b'for i in range(2):\n print(55 + i)\nprint(77)\n', ['55', '56', '77'])]: + record = b'MX0 0 0 %d %s\n' % (len(code), code) + client.rpc(118, struct.pack('<IQI', fid, 0, len(record)) + record) + for out in outputs: + assert wait_for(f'\n{out}\n'), (code, out, body()) + time.sleep(.5) + assert body().rstrip().endswith('>>>'), (code, body()[-200:]) finally: client.close(fid) @@ -528,8 +575,38 @@ def signal_cleans_up(binary): assert not address.exists() and not detached.exists(), (sig, list(root.iterdir())) +def cut_writes(binary): + """A write bigger than a 9P message comes as several, cut anywhere: each + command line runs once, whole, an Edit block once it ends, and a last + line with no newline when the open closes. Never a fragment.""" + with tempfile.TemporaryDirectory(prefix='pardes-cut-') as directory: + with session(binary, Path(directory), 'cut') as (client, _): + burst = b''.join(b'Msg burst-%04d\n' % i for i in range(1000)) + assert len(burst) > client.msize + client.write('/exec', burst) + log = client.read('/log').decode() + said = [line.split(' ', 2)[2] for line in log.splitlines() if line.startswith('msg ') and 'burst-' in line] + assert said == ['burst-%04d' % i for i in range(1000)], said[:3] + said[-3:] + assert '\nrun ' not in log and 'exit 127' not in log, log[-400:] + client.write('/exec', b'Msg no-newline-at-end') + assert 'msg ' in client.read('/log').decode().split('no-newline-at-end')[0][-40:] + serial = new_pane(client, b'') + block = b'Edit ,a\n' + b''.join(b'line %05d of the block\n' % i for i in range(2500)) + b'.\n' + assert len(block) > 50000 + client.write(f'/pane/{serial}/ctl', block) + body = client.read(f'/pane/{serial}/body').decode().splitlines() + assert body == ['line %05d of the block' % i for i in range(2500)], (len(body), body[:2]) + # A detached session with no frontend is 160x50 until told. + screen = client.screen() + assert (screen['cols'], screen['rows']) == (160, 50), (screen['cols'], screen['rows']) + client.write('/ctl', b'size 132 40\n') + screen = client.screen() + assert (screen['cols'], screen['rows']) == (132, 40), (screen['cols'], screen['rows']) + + def test(binary, quic=False): started = time.monotonic() + cut_writes(binary) run_file(binary) exit_answers(binary) unattended_messages_expire(binary) @@ -665,8 +742,9 @@ def test(binary, quic=False): execute(remote, control, 'Mount peer ' + str(address)) opened = look(remote, '/n/peer/pane/1/body', source=control) assert remote.read(f'/pane/{opened}/body') == client.read('/pane/1/body') - execute(remote, control, 'Mount peer ' + str(own_address)) - execute(remote, control, 'Unmount peer') + # A builtin that fails through exec fails the write (one rule). + execute_refused(remote, control, 'Mount peer ' + str(own_address), 'already mounted') + execute_refused(remote, control, 'Unmount peer', 'mount in use') # a pane is open on it remote.write(f'/pane/{opened}/body', b'runtime mounted Save\n', truncate=True) remote.write(f'/pane/{opened}/exec', b'Save\n') assert client.read('/pane/1/body') == b'runtime mounted Save\n' @@ -693,7 +771,7 @@ def test(binary, quic=False): with session(binary, root, name, tty=tty) as (old, address): old.write('/pane/1/body', b'dumped state\n', truncate=True) control = new_pane(old, b'') - execute(old, control, 'Restore ' + str(root / 'missing dump.zon')) + execute_refused(old, control, 'Restore ' + str(root / 'missing dump.zon'), 'no such file') assert old.read('/pane/1/body') == b'dumped state\n' execute(old, control, 'Mount own ' + str(address)) execute(old, control, 'Dump') @@ -735,7 +813,7 @@ def test(binary, quic=False): contents = restored.read(f'/pane/{file_id}/body') assert contents == b'dumped state\n', (contents, saved.read_text(), restored.read('/index')) assert restored.read(f'/pane/{control_id}/body') == b'', 'commands ran through exec, not the body' - assert restored.screen()['cols'] == 80 + assert restored.screen()['cols'] == (80 if tty else 160) # a detached one is 160x50 opened = look(restored, '/n/own/os' + str(root / (name + '.txt')), source=control_id) assert restored.read(f'/pane/{opened}/body') == b'initial\n' @@ -909,6 +987,7 @@ def test(binary, quic=False): assert path.read_bytes() == b'written through long filename\n' opened = look(client, '/n/os' + str(path)) assert client.read(f'/pane/{opened}/body') == path.read_bytes() + client.remove(f'/pane/{opened}') # a long name's tag takes rows opened = look(client, '/n/os' + str(directory)) listing = client.read(f'/pane/{opened}/body') for path in directory.iterdir(): diff --git a/test/fs_namespace.zig b/test/fs_namespace.zig index 2f78ca1a..bd620c2d 100644 --- a/test/fs_namespace.zig +++ b/test/fs_namespace.zig @@ -6,9 +6,15 @@ test "runtime Mount and Unmount copy command arguments and change Look resolutio const gpa = std.testing.allocator; const p = try pardes.Pardes.init(gpa, .{ .tty_only = true }); defer p.deinit(); - var command = "Mount peer /tmp/a socket.sock".*; - try std.testing.expect(p.executeBuiltinLine(0, &command)); - @memset(&command, 'x'); + // No peer answers at the dial: Mount mounts nothing (it dials first). + try std.testing.expect(p.executeBuiltinLine(0, "Mount peer /tmp/a socket.sock")); + try std.testing.expectEqual(@as(usize, 0), p.fs.mounts.items.len); + // Mounted (as one that answered is), its arguments are copies. + var name = "peer".*; + var dial = "/tmp/a socket.sock".*; + try p.fs.mount(gpa, &name, &dial); + @memset(&name, 'x'); + @memset(&dial, 'x'); try std.testing.expectEqual(@as(usize, 1), p.fs.mounts.items.len); try std.testing.expectEqualStrings("peer", p.fs.mounts.items[0].name); try std.testing.expectEqualStrings("/tmp/a socket.sock", p.fs.mounts.items[0].dial); diff --git a/test/gui-goldens.txt b/test/gui-goldens.txt index 263f1bcc..01bdfc7c 100644 --- a/test/gui-goldens.txt +++ b/test/gui-goldens.txt @@ -6,12 +6,12 @@ 06-tag-focus-selection 94aff8499a6e6f399761ffdd56369d526fbe65232eb21c88addd12973af611aa 07-prompt-notice 041603b841605b0a9456cbbb9b3e06e219b0a08a58e2d38229e1c81366577a87 08-wide-glyph-edges 94b0beb7cc2f2a09259f4f7d57999001ef75ed53ea210a65a1510404bd161af9 -09-collapsed-focus-tint 83db5e1acb69424c8ecdb247fcf359ff6b010a529a628012991d74b4a6428b89 -10-tagbottom 3a7d5bc8b2e821ffb082ccd548c6f312947f614be80324fbd79b4182e34cf387 -12-multiline-tag 93cdcfa151dc823d3d13af270157dcca8f69ecfd0ace7e0b888c088ca8c3deaf +09-collapsed-focus-tint 1d0e6e4b371bc3b2bba96d9177b91f240fa4bef38c62470dc078fa9feed119ac +10-tagbottom f7175dfb338b75c5ac3457c8422dc0e352c46d51b2c52533ce32ef143fcf6c6b +12-multiline-tag ddd7d775a246e91b88f0eff98b6f9bea8aa5d63dbfbe931bd830ccb9086bd5c4 13-image f609043fc0fcdb55369b836b61fcbc631f786cc2295a5ddd72c0d9a59b177a60 14-theme-ink 881b7e99f38ad4aa3c46d2c61e20598010175d7858712a67fa6638fc29f12e14 15-theme-acme-light ca5252f5117ac8d6c679cef917c9f316c9ca311fc7a8dcbac2796b4fc04d3b64 16-debug 591bb7c45b4b9c46cd2458330b4fa3962afc6dac827fa6f5e20e927a72c586e6 17-terminal 38299427891e31de0b5597159501c161474620eb26fd7708a6396f0fd685209e -18-mid-transition ab31f5fde35367edda6c7f4e45bf4396596f242a60938f384df6c392bd3712d2 +18-mid-transition 80cf350f8736fa4b348225a3872572a799ce57c763939796b68e8c839418f8ee diff --git a/test/macos_e2e.swift b/test/macos_e2e.swift index 5f172f9d..2b0eedad 100644 --- a/test/macos_e2e.swift +++ b/test/macos_e2e.swift @@ -1251,7 +1251,7 @@ private func buildWorld(stem: String) throws -> String { // sources $HOME/.bashrc (host_io.Shell) — so this is what pins the // prompt to `$ ` and keeps the developer's history out of the capture. try "PS1='$ '\nHISTFILE=\n".write(toFile: "\(home)/.bashrc", atomically: true, encoding: .utf8) - // ...and the config is not empty, because the DEFAULT shell is fish, whose + // ...and the config is not empty, because the DEFAULT shell is $SHELL (fish, say), whose // prompt carries a hostname and whose greeting carries a version. A golden // taken against that is a golden for one machine. try "Shell bash\n".write(toFile: "\(pardesConfig)/init", atomically: true, encoding: .utf8) diff --git a/test/output.zig b/test/output.zig index 95cdbfb7..478f1b4a 100644 --- a/test/output.zig +++ b/test/output.zig @@ -544,10 +544,11 @@ test "Config prints the startup path and refreshes its one output" { for ([_][]const u8{ "Startup config: " ++ path ++ "\n", "Theme orchard\n", - "Shell requested (new panes) " ++ config.default_shell ++ " (default)\n", "Shell effective (last spawn) (none)\n", "Shell pending on\n", }) |line| try std.testing.expect(std.mem.indexOf(u8, out.content, line) != null); + var default_line: [256]u8 = undefined; + try std.testing.expect(std.mem.indexOf(u8, out.content, try std.fmt.bufPrint(&default_line, "Shell requested (new panes) {s} (default)\n", .{config.defaultShell()})) != null); try std.testing.expectEqualStrings(config.config_buffer, std.fs.path.basename(out.path)); try std.testing.expectEqual(panes.Output.Origin{ .cmd = .Config }, out.output.?.from); @@ -861,6 +862,7 @@ test "n/N resumes the result output whose Look moved focus away" { const p = try Pardes.init(std.testing.allocator, .{ .file = path, .cols = 80, .rows = 24 }); defer p.deinit(); p.locations_config.layout = .@"inline"; + p.settings.look_word = .list; // the +Search listing is what is walked try std.testing.expect(p.executeBuiltinLine(0, "Look target")); const rid = p.panes[0].?.search_pane orelse return error.MissingResults; @@ -1590,10 +1592,13 @@ test "stacked search and LSP results retain source tint navigation and dump owne } restored.active = id; pardes.look.armLookWalk(restored, id); - // The dot came back on the match it was on; the walk goes on. + // The dot came back on the match it was on; the walk goes on + // from it both ways, N wrapping to the last as it does live. try std.testing.expectEqual(@as(i32, @intCast(matches[0])), restored.panes[id].?.body.cur_row); - restored.update(.{ .key = .{ .cp = 'n' } }); + restored.update(.{ .key = .{ .cp = 'N' } }); try std.testing.expectEqual(@as(i32, @intCast(matches[1])), restored.panes[id].?.body.cur_row); + restored.update(.{ .key = .{ .cp = 'n' } }); + try std.testing.expectEqual(@as(i32, @intCast(matches[0])), restored.panes[id].?.body.cur_row); try std.testing.expectEqualStrings(source_text, source.file.?.content); } } diff --git a/test/panes.zig b/test/panes.zig index 25f0f6db..3d2821aa 100644 --- a/test/panes.zig +++ b/test/panes.zig @@ -4853,7 +4853,7 @@ const LookResetTests = struct { try std.testing.expectEqualStrings("needle", selected(pane)); } - test "Look clears both source and existing destination selections before focus" { + test "Look clears the source's click highlight, not its dot, and the destination's selections before focus" { const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100, .rows = 30 }); defer p.deinit(); const source = try p.setTestFile("source\nlines\n"); @@ -4872,9 +4872,12 @@ const LookResetTests = struct { try seed(destination, "previous destination"); pardes.look.lookAt(p, 0, source.pointer_selections[0].?.raw_text.?); try std.testing.expectEqual(id, p.active); - try cleared(source); + // The source keeps its dot (acme's look leaves it); the click's + // highlight goes. + for (source.sel) |selection| try std.testing.expectEqual(.none, selection.state); + for (source.pointer_selections) |selection| try std.testing.expect(selection == null); + try std.testing.expect(source.body.vsel.active); try cleared(destination); - try std.testing.expect(!source.body.vsel.active); if (range) { try std.testing.expectEqual(@as(i32, 1), destination.body.cur_row); try std.testing.expectEqualStrings("rav", selected(destination)); @@ -4890,3 +4893,47 @@ const LookResetTests = struct { test { _ = LookResetTests; } + +test "a terminal keeps its tag and two body rows through a squeeze, a drag and a smaller window; a text pane does not" { + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100, .rows = 30 }); + defer p.deinit(); + p.presentation.enabled = false; + p.sync(); + while (p.nextEffect()) |_| {} + const term = for (p.panes, 0..) |slot, i| { + if (slot) |pane| if (pane.isTerminal()) break i; + } else return error.NoTerminal; + p.newScratchBelow(term); + p.sync(); + while (p.nextEffect()) |_| {} + const col = layout.findPane(p, term).?.col; + const floor = p.panes[term].?.tag_rows + layout.min_body_rows; + // Squeezed by the weights: the others give it its floor. + p.panes[term].?.vweight = 0.01; + for (p.col_panes[col][0..p.col_n[col]]) |k| if (k != term) { + p.panes[k].?.vweight = 1000; + }; + p.sync(); + try std.testing.expectEqual(floor, p.rects[term].h); + var rows: ?u16 = null; + while (p.nextEffect()) |effect| if (effect == .resize_pty and effect.resize_pty.pane == term) { + rows = effect.resize_pty.rows; + }; + try std.testing.expectEqual(@as(?u16, layout.min_body_rows), rows); + // A drag of the grip under it up to its tag stops at the floor; one + // the other way takes a text pane down to its tag alone. + const k = layout.findPane(p, term).?.idx; + if (k + 1 < p.col_n[col]) { + layout.applyRowSplit(p, col, k, p.rects[term].y); + p.sync(); + try std.testing.expectEqual(floor, p.rects[term].h); + const text = p.col_panes[col][k + 1]; + layout.applyRowSplit(p, col, k, p.screen_h); + p.sync(); + try std.testing.expect(p.rects[text].h <= p.panes[text].?.tag_rows); + } + // A window too short for all: the terminal keeps its floor still. + p.update(.{ .resize = .{ .cols = 100, .rows = 10 } }); + p.sync(); + try std.testing.expect(p.rects[term].h >= p.panes[term].?.tag_rows + layout.min_body_rows); +} diff --git a/test/selfmount.py b/test/selfmount.py index 90960bed..55809740 100644 --- a/test/selfmount.py +++ b/test/selfmount.py @@ -105,6 +105,39 @@ def run(binary): check(client.read(f'/pane/{first}/body') == b'HELLO initial\n', f'Save wrote back through the mount into pane {first}') text = ''.join(cell[0] for cell in client.screen()['cells']) check('saved ' + mount in text, 'the editor reported the save') + # Through the kernel mount a write is cut at its msize: a + # 1000-line burst and a 50 KB Edit block each still run whole, + # line by line, and no piece of a line runs as a shell command. + # sh: bash's and fish's prompt files are not reachable in 9ns's + # namespace here, and a command pane needs no prompt marks. + client.write('/ctl', b'Shell sh\n') + # From the fixture's directory: a pane on the mount has one a + # shell cannot enter. + client.write('/focus', f'{first}\n'.encode()) + + def run(line): + """A command pane runs the line; answers its exit status.""" + seen = client.read('/log').decode().count('\nexit ') + client.write('/exec', line) + deadline = time.monotonic() + 20 + while time.monotonic() < deadline: + drain() + exits = [row for row in client.read('/log').decode().splitlines() if row.startswith('exit ')] + if len(exits) > seen: + return exits[-1].split()[2] + time.sleep(.1) + return 'timeout' + got = run(f"seq -f 'Msg mnt-%04g' 0 999 > {mount}/exec\n".encode()) + check(got == '0', f'a 1000-line burst written through the mount ({got!r})') + log = client.read('/log').decode() + said = [line.split(' ', 2)[2] for line in log.splitlines() if line.startswith('msg ') and 'mnt-' in line] + check(said == ['mnt-%04d' % i for i in range(1000)], f'each line of it ran once, whole ({len(said)} said)') + check('exit 127' not in log, 'no piece of a line ran as a command') + scratch = int(client.read('/pane/new')) + maker = "import sys; sys.stdout.write('Edit ,a\\n' + ''.join('line %05d of the block\\n' % i for i in range(2500)) + '.\\n')" + check(run(f'python3 -c "{maker}" > {mount}/pane/{scratch}/ctl\n'.encode()) == '0', 'a 50 KB Edit block written through the mount') + body = client.read(f'/pane/{scratch}/body').decode().splitlines() + check(body == ['line %05d of the block' % i for i in range(2500)], f'it ran once, whole ({len(body)} lines)') client.write('/exec', b'Msg still here\n') text = ''.join(cell[0] for cell in client.screen()['cells']) check('still here' in text, 'the editor answers after all of that') diff --git a/test/snapshot.zig b/test/snapshot.zig index 2fa8e89c..c49e7645 100644 --- a/test/snapshot.zig +++ b/test/snapshot.zig @@ -562,8 +562,9 @@ fn runScript(arena: std.mem.Allocator, exe_z: [:0]const u8, script_path: []const // XDG directory that points outside this per-snapshot fake home. const config_home = try std.fmt.allocPrintSentinel(arena, "{s}/.config", .{home}, 0); _ = setenv("XDG_CONFIG_HOME", config_home, 1); - // ...and it is not empty: the DEFAULT shell is fish, whose prompt carries - // a hostname and whose greeting carries a version, so a golden taken + // ...and it is not empty: the DEFAULT shell is $SHELL, whatever this + // machine's user logs in with (fish's prompt carries a hostname and its + // greeting a version), so a golden taken // against it would be a golden for this machine. Every script here runs // bash — the .bashrc above pins its prompt to `$ ` — and the fish path is // covered by host_io.Shell's unit tests instead. This is an ordinary diff --git a/test/snapshots/argv.golden b/test/snapshots/argv.golden index ab143a88..e4d41d6c 100644 --- a/test/snapshots/argv.golden +++ b/test/snapshots/argv.golden @@ -20,7 +20,7 @@ | | | -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/argv/cwd/+New Save Tty Collapse Del | 1 == snap filearg grid=100x31 cursor=7,3 |Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Exit diff --git a/test/snapshots/cornerdrag.golden b/test/snapshots/cornerdrag.golden index 730cc2bf..30c1830a 100644 --- a/test/snapshots/cornerdrag.golden +++ b/test/snapshots/cornerdrag.golden @@ -243,7 +243,7 @@ |24: |25: |26: -|27: -|28: -|29: -|30: /tmp/pardes-snap/cornerdrag/cwd Tty+bash Save Mode Filter +|27: /tmp/pardes-snap/cornerdrag/cwd Tty+bash Save Mode Filter +|28: Collapse Del +|29: w.txt +|30: diff --git a/test/snapshots/filewatch.golden b/test/snapshots/filewatch.golden index f19168b1..589cfc3a 100644 --- a/test/snapshots/filewatch.golden +++ b/test/snapshots/filewatch.golden @@ -28,20 +28,8 @@ | 7 line 7 | 8 line 8 | 9 -== snap reloaded grid=210x31 cursor=15,7 -|6: /tmp/pardes-snap/filewatch/cwd/w.txt Save Tty Collapse Del -|7: 1 EXTERNAL --:--:-- reloaded /tmp/pardes-snap/filewatch/cwd/w.txt -|8: 2 -|9: -|10: -|11: -|12: -|13: -|14: -|15: -|16: -|17: -|18: +== snap kept grid=210x31 cursor=15,7 +|7: 1 liMYEDITne 1 /tmp/pardes-snap/filewatch/cwd/w.txt changed on disk (get reloads it, Save overwrites it) == snap reloaded_sub grid=210x31 cursor=15,7 |20: 1 RENAMED --:--:-- reloaded /tmp/pardes-snap/filewatch/cwd/sub/s.txt |21: 2 @@ -52,18 +40,3 @@ |26: |27: |28: -== snap undone grid=210x31 cursor=15,7 -|6: * /tmp/pardes-snap/filewatch/cwd/w.txt Save Tty Collapse Del -|7: 1 liMYEDITne 1 -|8: 2 line 2 -|9: 3 /tmp/pardes-snap/filewatch/cwd/sub/s.txt -|10: 4 line 4 -|11: 5 line 5 -|12: 6 line 6 -|13: 7 line 7 -|14: 8 line 8 -|15: 9 line 9 -|16: 10 line 10 -|17: 11 line 11 -|18: 12 line 12 -|20: 1 RENAMED diff --git a/test/snapshots/filewatch.snap b/test/snapshots/filewatch.snap index 9e6e6a13..6664519f 100644 --- a/test/snapshots/filewatch.snap +++ b/test/snapshots/filewatch.snap @@ -1,6 +1,6 @@ -# external file updates: a write from outside pardes lands in the open pane, -# and Undo brings the unsaved edit back. That is the whole contract — the -# update is committed like any other edit, so nothing has to be merged. +# external file updates: a write from outside pardes lands in an open pane +# that has no unsaved edits, committed like any other edit; a pane WITH +# unsaved edits keeps them and says the file changed on disk (File.changed). # # The writer must be a STRANGER to the editor. This script used to have a # pardes PANE run the write, which proved much less than it looked: that @@ -54,18 +54,13 @@ settle 100 stable 400 5000 snap edited # ---- from here to `snap reloaded_sub`, pardes is sent NOTHING ---- +# w.txt has the unsaved edit: it is kept, and the change is said run printf 'EXTERNAL\n' > w.txt -wait 10000 EXTERNAL +wait 10000 changed on disk stable 700 10000 -snap reloaded +snap kept +# sub/s.txt has none: it takes the new text run printf 'RENAMED\n' > sub/t && mv sub/t sub/s.txt wait 10000 RENAMED stable 700 10000 snap reloaded_sub -# back in the file pane: one undo and the unsaved edit is there again -press left 10 8 -release left 10 8 -stable 400 5000 -key u -stable 400 5000 -snap undone diff --git a/test/snapshots/jumps.golden b/test/snapshots/jumps.golden index 310f00f9..0a2063b0 100644 --- a/test/snapshots/jumps.golden +++ b/test/snapshots/jumps.golden @@ -134,9 +134,9 @@ == snap jumplist grid=150x31 cursor=7,17 |3: 86 line 86 Jumplist ls |16: /tmp/pardes-snap/jumps/cwd/+Jumps Save Tty Collapse Del LocationsConfig -|17: 1 @p1:3:3 /tmp/pardes-snap/jumps/cwd +|17: 1 @p2:3:3 /tmp/pardes-snap/jumps/cwd |18: 2 /tmp/pardes-snap/jumps/cwd/big.txt:1:1 line 1 -|19: 3 @p1:3:3 /tmp/pardes-snap/jumps/cwd +|19: 3 @p2:3:3 /tmp/pardes-snap/jumps/cwd |20: 4 /tmp/pardes-snap/jumps/cwd/big.txt:100:1 line 100 |21: 5 |22: diff --git a/test/snapshots/lookpanes.golden b/test/snapshots/lookpanes.golden index a9088166..fbab6eb1 100644 --- a/test/snapshots/lookpanes.golden +++ b/test/snapshots/lookpanes.golden @@ -14,18 +14,18 @@ |6: /tmp/pardes-snap/lookpanes/cwd/alpha/zqonly.txt Save Tty Colla |7: pse Del /tmp/pardes-snap/lookpanes/cwd/alpha Tty+bash Save Mode Filter |8: 1 ONLY-IN-ALPHA Collapse Del -== snap clicked-wins grid=130x51 cursor=7,11 -|9: /tmp/pardes-snap/lookpanes/cwd/beta/both.txt Save Tty Collapse ls -|10: Del amark.txt both.txt pick.txt twin.txt zqonly.txt -|11: 1 BOTH-FROM-BETA +== snap clicked-wins grid=130x51 cursor=7,12 +|10: /tmp/pardes-snap/lookpanes/cwd/beta/both.txt Save Tty Collapse amark.txt both.txt pick.txt twin.txt zqonly.txt +|11: Del +|12: 1 BOTH-FROM-BETA == snap mru-alpha grid=130x51 cursor=72,14 -|12: /tmp/pardes-snap/lookpanes/cwd/alpha/pick.txt Save Tty Collaps +|12: 1 BOTH-FROM-BETA /tmp/pardes-snap/lookpanes/cwd/alpha/pick.txt Save Tty Collaps |13: e Del |14: 1 PICK-FROM-ALPHA -== snap mru-beta grid=130x51 cursor=7,14 -|12: /tmp/pardes-snap/lookpanes/cwd/beta/twin.txt Save Tty Collapse /tmp/pardes-snap/lookpanes/cwd/alpha/pick.txt Save Tty Collaps -|13: Del e Del -|14: 1 TWIN-FROM-BETA 1 PICK-FROM-ALPHA +== snap mru-beta grid=130x51 cursor=7,16 +|14: /tmp/pardes-snap/lookpanes/cwd/beta/twin.txt Save Tty Collapse 1 PICK-FROM-ALPHA +|15: Del +|16: 1 TWIN-FROM-BETA == style mru-beta grid=130x51 |0: 0-70 #b2c3b8,#1d2824, 71-129 d,#1d2824, |1: 0-1 #ffffff,#887455, 2-2 d,#314738, 3-34 #becfc4,#314738, 35-64 d,#314738, 65-66 #ffffff,#887455, 67-67 d,#1d2824, 68-99 #b2c3b8,#1d2824, 100-129 d,#1d2824, @@ -36,14 +36,14 @@ |6: 0-1 #ffffff,#496656, 2-2 d,#1d2824, 3-39 #b2c3b8,#1d2824, 40-49 #d3b0d9,#1d2824, 50-64 #b2c3b8,#1d2824, 65-65 d,#608269, 66-129 d,#0d1410, |7: 0-2 d,#1d2824, 3-9 #b2c3b8,#1d2824, 10-64 d,#1d2824, 65-66 #ffffff,#496656, 67-67 d,#1d2824, 68-104 #b2c3b8,#1d2824, 105-112 #d3b0d9,#1d2824, 113-129 #b2c3b8,#1d2824, |8: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-19 #e5eee5,#0d1410, 20-64 d,#0d1410, 65-67 d,#1d2824, 68-80 #b2c3b8,#1d2824, 81-129 d,#1d2824, -|9: 0-1 #ffffff,#496656, 2-2 d,#1d2824, 3-38 #b2c3b8,#1d2824, 39-46 #d3b0d9,#1d2824, 47-64 #b2c3b8,#1d2824, 65-65 d,#608269, 66-66 d,#0d1410, 67-129 #e5eee5,#0d1410, -|10: 0-2 d,#1d2824, 3-6 #b2c3b8,#1d2824, 7-64 d,#1d2824, 65-65 d,#608269, 66-66 d,#0d1410, 67-129 #e5eee5,#0d1410, -|11: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-20 #e5eee5,#0d1410, 21-64 d,#0d1410, 65-65 d,#608269, 66-129 d,#0d1410, -|12: 0-1 #000000,#add38a, 2-2 d,#314738, 3-38 #becfc4,#314738, 39-46 #dfbce5,#314738, 47-64 #becfc4,#314738, 65-66 #ffffff,#496656, 67-67 d,#1d2824, 68-104 #b2c3b8,#1d2824, 105-112 #d3b0d9,#1d2824, 113-129 #b2c3b8,#1d2824, -|13: 0-2 d,#314738, 3-6 #becfc4,#314738, 7-64 d,#314738, 65-67 d,#1d2824, 68-72 #b2c3b8,#1d2824, 73-129 d,#1d2824, -|14: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #616f64,#0d1410,b 7-20 #e5eee5,#0d1410, 21-64 d,#0d1410, 65-65 d,#608269, 66-66 d,#0d1410, 67-71 #59675c,#0d1410, 72-86 #e5eee5,#0d1410, 87-129 d,#0d1410, -|15: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-64 d,#0d1410, 65-65 d,#608269, 66-66 d,#0d1410, 67-71 #59675c,#0d1410, 72-129 d,#0d1410, -|16: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-64 d,#0d1410, 65-65 d,#608269, 66-66 d,#0d1410, 67-71 #59675c,#0d1410, 72-129 d,#0d1410, +|9: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-64 d,#0d1410, 65-65 d,#608269, 66-66 d,#0d1410, 67-129 #e5eee5,#0d1410, +|10: 0-1 #ffffff,#496656, 2-2 d,#1d2824, 3-38 #b2c3b8,#1d2824, 39-46 #d3b0d9,#1d2824, 47-64 #b2c3b8,#1d2824, 65-65 d,#608269, 66-66 d,#0d1410, 67-129 #e5eee5,#0d1410, +|11: 0-2 d,#1d2824, 3-6 #b2c3b8,#1d2824, 7-64 d,#1d2824, 65-65 d,#608269, 66-129 d,#0d1410, +|12: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-20 #e5eee5,#0d1410, 21-64 d,#0d1410, 65-66 #ffffff,#496656, 67-67 d,#1d2824, 68-104 #b2c3b8,#1d2824, 105-112 #d3b0d9,#1d2824, 113-129 #b2c3b8,#1d2824, +|13: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-64 d,#0d1410, 65-67 d,#1d2824, 68-72 #b2c3b8,#1d2824, 73-129 d,#1d2824, +|14: 0-1 #000000,#add38a, 2-2 d,#314738, 3-38 #becfc4,#314738, 39-46 #dfbce5,#314738, 47-64 #becfc4,#314738, 65-65 d,#608269, 66-66 d,#0d1410, 67-71 #59675c,#0d1410, 72-86 #e5eee5,#0d1410, 87-129 d,#0d1410, +|15: 0-2 d,#314738, 3-6 #becfc4,#314738, 7-64 d,#314738, 65-65 d,#608269, 66-66 d,#0d1410, 67-71 #59675c,#0d1410, 72-129 d,#0d1410, +|16: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #616f64,#0d1410,b 7-20 #e5eee5,#0d1410, 21-64 d,#0d1410, 65-65 d,#608269, 66-66 d,#0d1410, 67-71 #59675c,#0d1410, 72-129 d,#0d1410, |17: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-64 d,#0d1410, 65-65 d,#608269, 66-66 d,#0d1410, 67-71 #59675c,#0d1410, 72-129 d,#0d1410, |18: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-64 d,#0d1410, 65-65 d,#608269, 66-66 d,#0d1410, 67-71 #59675c,#0d1410, 72-129 d,#0d1410, |19: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-64 d,#0d1410, 65-65 d,#608269, 66-66 d,#0d1410, 67-71 #59675c,#0d1410, 72-129 d,#0d1410, diff --git a/test/snapshots/nested.golden b/test/snapshots/nested.golden index e5244e71..9758c491 100644 --- a/test/snapshots/nested.golden +++ b/test/snapshots/nested.golden @@ -20,7 +20,7 @@ | | | -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/nested/cwd/+New Save Tty Collapse Del | 1 == snap no-arg grid=100x31 cursor=4,7 |Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Exit @@ -44,7 +44,7 @@ | | | -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/nested/cwd/+New Save Tty Collapse Del | 1 == snap dir-arg grid=100x31 cursor=4,8 |Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Exit @@ -68,5 +68,5 @@ | | | -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/nested/cwd/+New Save Tty Collapse Del | 1 diff --git a/test/snapshots/psearch.golden b/test/snapshots/psearch.golden index ee65ede2..20523962 100644 --- a/test/snapshots/psearch.golden +++ b/test/snapshots/psearch.golden @@ -20,18 +20,18 @@ | | | -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/psearch/cwd/+New Save Tty Collapse Del | 1 == snap typing grid=140x31 cursor=139,3 |3: printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n' /MARK == snap results grid=140x31 cursor=7,4 |3: printf 'x MA''RK a\nzz\nx MA''RK b\nzz\nx MA''RK c\n' |10: /tmp/pardes-snap/psearch/cwd/+Search Save Tty Collapse Del LocationsConfig -|11: 1 @p0:2:3-6 +|11: 1 @p1:2:3-6 |12: 2 x MARK a -|13: 3 @p0:4:3-6 +|13: 3 @p1:4:3-6 |14: 4 x MARK b -|15: 5 @p0:6:3-6 +|15: 5 @p1:6:3-6 |16: 6 x MARK c |17: 7 == style results grid=140x31 @@ -56,7 +56,7 @@ |18: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-139 d,#0d1410, |19: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-139 d,#0d1410, |20: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-139 d,#0d1410, -|21: 0-1 #ffffff,#496656, 2-2 d,#1d2824, 3-3 #b2c3b8,#1d2824, 4-7 #d3b0d9,#1d2824, 8-29 #b2c3b8,#1d2824, 30-139 d,#1d2824, +|21: 0-1 #ffffff,#496656, 2-2 d,#1d2824, 3-31 #b2c3b8,#1d2824, 32-35 #d3b0d9,#1d2824, 36-57 #b2c3b8,#1d2824, 58-139 d,#1d2824, |22: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-139 d,#0d1410, |23: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-139 d,#0d1410, |24: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-139 d,#0d1410, diff --git a/test/snapshots/psearch.snap b/test/snapshots/psearch.snap index a46e2b9d..6e463119 100644 --- a/test/snapshots/psearch.snap +++ b/test/snapshots/psearch.snap @@ -1,7 +1,7 @@ # `/` search on a TERMINAL pane: the same tag input as a file pane, searching # the shell's own scrollback (the plain text view Look reads, prompt rows # hidden). Results land in a +Search OUTPUT BUFFER — a file pane with no file -# behind it, so its tag has no Save — and point at `@p0:LINE:COL-ENDCOL`, the +# behind it, so its tag has no Save — and point at `@p1:LINE:COL-ENDCOL` (the terminal's serial), the # look target that names a live pane, since a terminal has no path. n/N SELECT # the next/prev row in the buffer and open nothing; Enter — the look chord — # is what scrolls the terminal to that line of its scrollback and selects the @@ -31,12 +31,12 @@ stable 400 5000 text MARK stable 400 5000 snap typing -# Enter opens the results buffer — three @p0:LINE:COL rows — and goes to the +# Enter opens the results buffer — three @p1:LINE:COL rows — and goes to the # first of them: the terminal's cursor lands on that scrollback line, on the # matched SPAN (cols 3..6, past the leading "x ") — not the start of the line, # and selected rather than merely parked on. No `n` was pressed to get here. key enter -wait 10000 @p0:2:3 +wait 10000 @p1:2:3 stable 700 15000 snap results snapstyle results @@ -83,6 +83,6 @@ key c-b stable 600 8000 press right 5 5 release right 5 5 -wait 10000 @p0:2:3 +wait 10000 @p1:2:3 stable 700 15000 snap rightsearch diff --git a/test/snapshots/reflow.golden b/test/snapshots/reflow.golden index ab8bfe9b..afd4b93f 100644 --- a/test/snapshots/reflow.golden +++ b/test/snapshots/reflow.golden @@ -16,5 +16,5 @@ | yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy | yyyyyyyyyyyyyyyyyyyyyyyyyyyyyydone | $ -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/reflow/cwd/+New Save Tty Collapse Del | 1 diff --git a/test/snapshots/rsearch.snap b/test/snapshots/rsearch.snap index 8c81db1d..75d0212c 100644 --- a/test/snapshots/rsearch.snap +++ b/test/snapshots/rsearch.snap @@ -11,6 +11,9 @@ file code.txt run count_x now\nopen sub/dep.txt:3 here\ncount_x again\npick two # the top of the body -- which moves every row this script clicks. What the # verbs do is what is under test, not the announcement. config Verbose off +# the +Search listing is what this walks: LookWord list (search, acme's look3, +# is the default; ctl.zig tests it) +config LookWord list start 31 210 -n 1 wait 8000 code.txt stable 700 20000 diff --git a/test/snapshots/shellset.golden b/test/snapshots/shellset.golden index 0af8f2e1..e2830801 100644 --- a/test/snapshots/shellset.golden +++ b/test/snapshots/shellset.golden @@ -4,7 +4,7 @@ | /tmp/pardes-snap/shellset/cwd/cmd.txt Save Tty Collapse Del | 1 Shell zznosuchshell == snap builtin-ran grid=90x21 cursor=25,3 -|3: 1 Shell zznosuchshell Shell +|3: 1 Shel Shell: no shell "zznosuchshell" (a name on the usual paths, or a path to one) == snap fallback-shell grid=90x21 cursor=49,6 |1: New Tty Find Grep Joincol Delcol New Tty Find Grep Joincol Delcol |2: /tmp/pardes-snap/shellset/cwd/cmd.txt Save /tmp/pardes-snap/shellset/cwd Tty+bash Sav diff --git a/test/snapshots/shellset.snap b/test/snapshots/shellset.snap index d2bacf38..7d213a84 100644 --- a/test/snapshots/shellset.snap +++ b/test/snapshots/shellset.snap @@ -1,12 +1,12 @@ # The Shell builtin names the binary the NEXT terminal execs. What is pinned # here is the case that has to hold on a machine you did not set up: the name -# resolves to nothing, and the pane opens anyway. +# resolves to nothing, so Shell refuses it and says why on the message row, +# and the next pane opens anyway with the shell that was set before. # -# That is not a corner — it is the DEFAULT's failure mode. pardes ships -# `Shell fish` as the default, and a box without fish must still get a working -# shell rather than a pane whose child dies at exec and shows one EOF. So the -# lookup falls back, and this is the proof: a name nothing resolves to, and the -# new pane still greets and lists like any other. +# A default $SHELL that names nothing executable falls back to /bin/sh +# (config.defaultShell), and the host's lookup still falls back at spawn for +# a shell that went away after it was set: a pane never gets a child that +# dies at exec and shows one EOF. # # The rest of the feature is unit-tested rather than pinned here, on purpose. # Which family a binary belongs to, what argv each one gets and where the diff --git a/test/snapshots/shrinktag.golden b/test/snapshots/shrinktag.golden index 552722f9..9aa29e11 100644 --- a/test/snapshots/shrinktag.golden +++ b/test/snapshots/shrinktag.golden @@ -21,23 +21,25 @@ | ls | w.txt == snap shrunk grid=100x31 cursor=2,9 -|3: /tmp/pardes-snap/shrinktag/cwd Tty+bash Save Mo de Filter Collapse Del -|4: de Filter Collapse Del ls -|5: ls w.txt -|6: w.txt -|8: +|4: w.txt ls +|5: w.txt +|6: /tmp/pardes-snap/shrinktag/cwd Tty+bash Save Mo +|7: de Filter Collapse Del +|8: ls +|9: w.txt |17: |18: |19: |20: == snap move-preview grid=100x31 cursor=2,9 -|8: ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +|8: ls ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ == snap restored grid=100x31 cursor=2,9 -|3: de Filter Collapse Del de Filter Collapse Del |4: ls ls |5: w.txt w.txt |6: +|7: |8: echo one; echo two +|9: |17: /tmp/pardes-snap/shrinktag/cwd Tty+bash Save Mo |18: de Filter Collapse Del |19: ls @@ -47,4 +49,6 @@ |18: |19: |20: -|30: /tmp/pardes-snap/shrinktag/cwd Tty+bash Save Mo +|27: /tmp/pardes-snap/shrinktag/cwd Tty+bash Save Mo +|28: de Filter Collapse Del +|29: w.txt diff --git a/test/snapshots/shrinktag.snap b/test/snapshots/shrinktag.snap index 31edad14..5264be74 100644 --- a/test/snapshots/shrinktag.snap +++ b/test/snapshots/shrinktag.snap @@ -1,8 +1,8 @@ -# a pane can shrink to just its tagline: the pane below dragged by its grip up -# to the tag row (0 body rows) -- a terminal has no rule between panes, so -# the grip is the handle, as acme's button is -- the gutter box still grabs a -# move, and dragging back down restores the body intact (the hidden pane's -# pty/vt is never resized) +# a terminal shrinks only to its tag and 2 body rows (a text pane would go +# to its tag alone): the pane below dragged by its grip up to the tag row +# stops there -- a terminal has no rule between panes, so the grip is the +# handle, as acme's button is -- the gutter box still grabs a move, and +# dragging back down restores the body intact file w.txt x start 31 100 -n 3 wait 8000 w.txt @@ -18,7 +18,7 @@ key esc settle 100 stable 400 5000 snap before -# drag the lower pane's grip up under pane 0's tag row: tag-only pane +# drag the lower pane's grip up under pane 0's tag row: it keeps 2 body rows press left 1 18 drag left 1 3 release left 1 3 @@ -34,14 +34,16 @@ snap move-preview drag left 20 3 release left 20 3 stable 400 5000 -# re-enlarge: the lower pane's grip, now under pane 0's tag, pulled back down -press left 1 4 +# re-enlarge: the lower pane's grip, now under pane 0's 2 body rows, pulled +# back down +press left 1 7 drag left 1 18 release left 1 18 motion 40 25 stable 500 8000 snap restored -# the bottom pane can shrink to ITS tag too: its grip dragged past the bottom +# the bottom pane stops at ITS tag and 2 rows too: its grip dragged past the +# bottom press left 1 18 drag left 1 31 release left 1 31 diff --git a/test/snapshots/splitparent.golden b/test/snapshots/splitparent.golden index e64df572..e626cea7 100644 --- a/test/snapshots/splitparent.golden +++ b/test/snapshots/splitparent.golden @@ -2,38 +2,34 @@ |Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Exit | New Tty Find Grep Joincol Delcol New Tty Find Grep Joincol Delcol | /tmp/pardes-snap/splitparent/cwd Tty+bash Save /tmp/pardes-snap/splitparent/cwd Tty+bash Save -| /tmp/pardes-snap/splitparent/cwd Tty+bash Save Mode Filter Collapse Del -| Mode Filter Collapse Del ls +| Mode Filter Collapse Del Mode Filter Collapse Del +| ls ls +| +| /tmp/pardes-snap/splitparent/cwd Tty+bash Save +| Mode Filter Collapse Del | ls -== snap swap-parent grid=100x31 cursor=4,9 -|5: -|6: /tmp/pardes-snap/splitparent/cwd Tty+bash Save -|7: Mode Filter Collapse Del -|8: ls -== snap tallest grid=100x6 cursor=54,5 +== snap swap-parent grid=100x31 cursor=4,13 +|10: /tmp/pardes-snap/splitparent/cwd Tty+bash Save +|11: Mode Filter Collapse Del +|12: ls +== snap tallest grid=100x6 cursor=4,5 |Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Exit | New Tty Find Grep Joincol Delcol New Tty Find Grep Joincol Delcol | /tmp/pardes-snap/splitparent/cwd Tty+bash Save /tmp/pardes-snap/splitparent/cwd Tty+bash Save -| /tmp/pardes-snap/splitparent/cwd Tty+bash Save -| /tmp/pardes-snap/splitparent/cwd Tty+bash Save /tmp/pardes-snap/splitparent/cwd Tty+bash Save -== snap regrown grid=100x31 cursor=54,20 +| /tmp/pardes-snap/splitparent/cwd Tty+bash Save Mode Filter Collapse Del +| /tmp/pardes-snap/splitparent/cwd Tty+bash Save ls +| e in that column: each keeps its tag and 2 rows +== snap regrown grid=100x31 cursor=4,13 |Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Exit | New Tty Find Grep Joincol Delcol New Tty Find Grep Joincol Delcol | /tmp/pardes-snap/splitparent/cwd Tty+bash Save /tmp/pardes-snap/splitparent/cwd Tty+bash Save -| /tmp/pardes-snap/splitparent/cwd Tty+bash Save Mode Filter Collapse Del -| Mode Filter Collapse Del ls +| Mode Filter Collapse Del Mode Filter Collapse Del +| ls ls | | /tmp/pardes-snap/splitparent/cwd Tty+bash Save | Mode Filter Collapse Del | ls | -| -| -| -| -| -| -| -| /tmp/pardes-snap/splitparent/cwd Tty+bash Save -| Mode Filter Collapse Del -| ls +| /tmp/pardes-snap/splitparent/cwd Tty+bash Save +| Mode Filter Collapse Del +| e in that column: each keeps its tag and 2 rows diff --git a/test/snapshots/splitparent.snap b/test/snapshots/splitparent.snap index b9038af2..93ed9e21 100644 --- a/test/snapshots/splitparent.snap +++ b/test/snapshots/splitparent.snap @@ -1,25 +1,29 @@ -# a new pane never opens under a too-short parent: Alt-n from a tag-only pane +# a new pane never opens under a too-short parent: Alt-n from a pane too short to halve # splits the tall sibling in its column instead; when NO pane could leave the -# newcomer 2 body rows, the tallest one anywhere is split +# newcomer 2 body rows, the tallest one anywhere is split, and when that one +# cannot keep its own tag and 2 rows either, the pane is refused # pins the pardes placement rule (Placement pardes), which it covers config Placement pardes start 31 100 -n 3 stable 700 20000 -# shrink pane 0 (top-left) to just its tagline: the pane below's grip dragged -# up under it (a terminal has no rule between panes; the grip is the handle) +# shrink pane 0 (top-left), a terminal, as far as it goes, its tag and 2 body +# rows: the pane below's grip dragged up under its tag (a terminal has no +# rule between panes; the grip is the handle) press left 1 18 drag left 1 3 release left 1 3 motion 40 25 stable 500 8000 snap shrunk -# Alt-n from the tag-only pane: the new shell opens below the tall sibling +# Alt-n from the short pane: the new shell opens below the tall sibling # underneath it, not as another 1-row sliver key a-n stable 700 15000 snap swap-parent -# squeeze the grid until no pane is 5 rows tall, then Alt-n again: the -# tallest pane (right column) is split even though the active one is left +# squeeze the grid until no pane can give a new one its tag and 2 rows, then +# Alt-n again: the new shell is refused, and the message row says why (before +# every pane had to keep only a tag and one row, the tallest pane anywhere was +# split here) resize 6 100 stable 700 15000 key a-n diff --git a/test/snapshots/tinywin.golden b/test/snapshots/tinywin.golden index d24ab0c5..c847a2f1 100644 --- a/test/snapshots/tinywin.golden +++ b/test/snapshots/tinywin.golden @@ -20,13 +20,13 @@ | | | -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/tinywin/cwd/+New Save Tty Collapse Del | 1 == snap shrunk grid=60x4 cursor=59,3 |Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor | New Tty Find Grep Joincol Delcol |$ /tmp/pardes-snap/tinywin/cwd Tty+bash Save Mode Filter Co -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/tinywin/cwd/+New Save Tty Collapse Del == snap columns grid=100x31 cursor=23,3 |Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Exit | New Tty Find Grep Joincol Delcol @@ -49,7 +49,7 @@ | | | -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/tinywin/cwd/+New Save Tty Collapse Del | 1 == snap narrow grid=4x31 cursor=2,20 |Newc @@ -74,10 +74,10 @@ | cn | | / -| + -| N -| e -| w -| -| S +| t +| m +| p +| / +| p | a +| r diff --git a/test/snapshots/ttyhelp.golden b/test/snapshots/ttyhelp.golden index cd7cb946..8b8d4195 100644 --- a/test/snapshots/ttyhelp.golden +++ b/test/snapshots/ttyhelp.golden @@ -20,7 +20,7 @@ | | | -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/ttyhelp/cwd/+New Save Tty Collapse Del | 1 == snap helped grid=100x31 cursor=7,6 |5: /tmp/pardes-snap/ttyhelp/cwd/+Help Save Tty Collapse Del diff --git a/test/snapshots/ttylook.golden b/test/snapshots/ttylook.golden index 05cace52..f2f37f9d 100644 --- a/test/snapshots/ttylook.golden +++ b/test/snapshots/ttylook.golden @@ -66,6 +66,6 @@ == snap fileopen grid=120x31 cursor=3,4 |22: /tmp/pardes-snap/ttylook/cwd/+Search Save Tty Collapse De |23: l LocationsConfig -|24: 1 @p0:1:1-2 +|24: 1 @p1:1:1-2 |25: 2 ls |26: 3 diff --git a/test/snapshots/ttyonly.golden b/test/snapshots/ttyonly.golden index 85a61d35..77f7dbb7 100644 --- a/test/snapshots/ttyonly.golden +++ b/test/snapshots/ttyonly.golden @@ -20,7 +20,7 @@ | | | -| /+New Save Tty Collapse Del +| /tmp/pardes-snap/ttyonly/cwd/+New Save Tty Collapse Del | 1 == style ttyonly grid=100x31 |0: 0-70 #b2c3b8,#1d2824, 71-99 d,#1d2824, @@ -44,7 +44,7 @@ |18: 0-0 d,#608269, 1-1 d,#0d1410, 2-99 #e5eee5,#0d1410, |19: 0-0 d,#608269, 1-1 d,#0d1410, 2-99 #e5eee5,#0d1410, |20: 0-0 d,#608269, 1-1 d,#0d1410, 2-99 #e5eee5,#0d1410, -|21: 0-1 #ffffff,#496656, 2-2 d,#1d2824, 3-3 #b2c3b8,#1d2824, 4-7 #d3b0d9,#1d2824, 8-29 #b2c3b8,#1d2824, 30-99 d,#1d2824, +|21: 0-1 #ffffff,#496656, 2-2 d,#1d2824, 3-31 #b2c3b8,#1d2824, 32-35 #d3b0d9,#1d2824, 36-57 #b2c3b8,#1d2824, 58-99 d,#1d2824, |22: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-99 d,#0d1410, |23: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-99 d,#0d1410, |24: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-99 d,#0d1410, |
