summaryrefslogtreecommitdiff
path: root/test/web-snapshots
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-06 18:11:36 -0300
committerGabriel Schneider <[email protected]>2026-09-07 13:59:12 -0300
commit60367d8fe23f6af98ec28e3cf6c2094dfe332df0 (patch)
tree310fc734173cf771881f4691c71909135fadde97 /test/web-snapshots
parentfa82cac885cb4738fe36d1e49b4749b5a3e31a4a (diff)
downloadpardes-60367d8fe23f6af98ec28e3cf6c2094dfe332df0.tar.gz
pardes-60367d8fe23f6af98ec28e3cf6c2094dfe332df0.zip
Refactor panes and filesystem; replace FUSE with 9P
Consolidate pane, layout, memory and host code. Serve 9P by default over Unix sockets, with runtime mounts and optional TCP/QUIC transports. Remove FUSE and obsolete proof-of-concept examples. Fix highlighting and terminal-history performance, expand differential and stress-test infrastructure, sort navigation results while preserving the next occurrence, add syntax-colored Braille minimaps, remove SPC-k, and document 9P interaction as a repository skill.
Diffstat (limited to 'test/web-snapshots')
-rw-r--r--test/web-snapshots/README.md30
-rw-r--r--test/web-snapshots/source-list.dump.zon27
-rw-r--r--test/web-snapshots/source-list.golden228
-rw-r--r--test/web-snapshots/source-list.snap42
-rw-r--r--test/web-snapshots/touch.dump.zon73
-rw-r--r--test/web-snapshots/touch.mjs99
6 files changed, 178 insertions, 321 deletions
diff --git a/test/web-snapshots/README.md b/test/web-snapshots/README.md
index 3b121949..a7cd865e 100644
--- a/test/web-snapshots/README.md
+++ b/test/web-snapshots/README.md
@@ -1,25 +1,7 @@
-# Web browser snapshots
+# Browser interaction tests
-`source-list.dump.zon` is a byte-for-byte dump from a running Pardes instance.
-It is not assembled or normalized by a fixture generator.
-
-To recapture it:
-
-1. Build and launch the native TTY in this checkout with `PARDES_DUMP` pointing
- at a temporary file.
-2. Enter raw TTY mode, run `clear`, then run
- `git ls-files --cached --others --exclude-standard -- '*.zig' | sort`.
- This is the archive generator's tracked-plus-new/nonignored selection in its
- deterministic display order.
-3. Leave raw TTY mode, press `gg` so the listing starts at scrollback row zero,
- and middle-click Pardes's `Dump` builtin.
-4. Copy the resulting dump into `source-list.dump.zon` without editing it.
-
-The visible `.body` is the first terminal viewport; `.terminal.stream` must
-contain the command plus every path reported by Git, and every listed path must
-exist. The base64 PTY stream is the real interaction and must contain the
-command itself. `source-list.snap` then drives the freestanding WASM + DOM build
-through Chromium: top and bottom launcher snapshots jointly cover the complete
-listing, then it taps `build.zig`, snapshots packed cell styles (including
-Tree-sitter's Zig highlighting), resizes the pane separator, and finally
-verifies body scrolling.
+`zig build web-snap` loads `touch.dump.zon` and runs `touch.mjs` in Chromium.
+The fixed source fixture exercises complete keyword styles, touch Look through
+the self filesystem, separator resizing, and scrolling without another Look.
+Assertions locate current pane geometry; no live project source or author paths
+are captured in goldens.
diff --git a/test/web-snapshots/source-list.dump.zon b/test/web-snapshots/source-list.dump.zon
deleted file mode 100644
index 63d7d67d..00000000
--- a/test/web-snapshots/source-list.dump.zon
+++ /dev/null
@@ -1,27 +0,0 @@
-.{
- .magic = "pardes-dump",
- .version = 1,
- .screen = .{ .cols = 100, .rows = 30 },
- .active = 0,
- .topbar = "New Newcol Find Grep Help Tutor Dump NextColor Debug Kill",
- .theme = "helix",
- .columns = .{.{ .weight = 1, .panes = .{0} }},
- .panes = .{.{
- .kind = .terminal,
- .tag = "/home/goblin/00-projects/0x4200.cafe/02-pardes-code New Del",
- .body = "git ls-files --cached --others --exclude-standard -- '*.zig' | sort\nbuild.zig\nbuild/snap.zig\nmupdf.zig\nsrc/allocators.zig\nsrc/animation.zig\nsrc/builtins.zig\nsrc/config.zig\nsrc/dump.zig\nsrc/effect_sources.zig\nsrc/file_pane.zig\nsrc/fonts.zig\nsrc/grammar_manifest.zig\nsrc/gui/crt.zig\nsrc/gui/deck.zig\nsrc/gui/gui.zig\nsrc/image.zig\nsrc/image_pane.zig\nsrc/look.zig\nsrc/lsp/lsp.zig\nsrc/lsp/lsp_zls.zig\nsrc/macos.zig\nsrc/main.zig\nsrc/message.zig\nsrc/modal.zig\nsrc/nested.zig\nsrc/normal_input.zig\nsrc/output_pane.zig",
- .scroll = 0,
- .cols = 98,
- .rows = 28,
- .vweight = 1,
- .tag_tail = null,
- .terminal = .{
- .cwd = "/home/goblin/00-projects/0x4200.cafe/02-pardes-code",
- .stream = "git ls-files --cached --others --exclude-standard -- '*.zig' | sort\nbuild.zig\nbuild/snap.zig\nmupdf.zig\nsrc/allocators.zig\nsrc/animation.zig\nsrc/builtins.zig\nsrc/config.zig\nsrc/dump.zig\nsrc/effect_sources.zig\nsrc/file_pane.zig\nsrc/fonts.zig\nsrc/grammar_manifest.zig\nsrc/gui/crt.zig\nsrc/gui/deck.zig\nsrc/gui/gui.zig\nsrc/image.zig\nsrc/image_pane.zig\nsrc/look.zig\nsrc/lsp/lsp.zig\nsrc/lsp/lsp_zls.zig\nsrc/macos.zig\nsrc/main.zig\nsrc/message.zig\nsrc/modal.zig\nsrc/nested.zig\nsrc/normal_input.zig\nsrc/output_pane.zig\nsrc/panel_animation.zig\nsrc/pardes.zig\nsrc/pdf.zig\nsrc/pdf_pane.zig\nsrc/pdf_pane_integration_test.zig\nsrc/petscii.zig\nsrc/runtime_config.zig\nsrc/selection_pipe.zig\nsrc/shell_bin.zig\nsrc/syntax.zig\nsrc/temp_file.zig\nsrc/term_pane.zig\nsrc/themes/acme.zig\nsrc/themes/dark.zig\nsrc/themes/helix.zig\nsrc/tracy.zig\nsrc/tty/panel_compositor.zig\nsrc/tty/tty.zig\nsrc/user_config.zig\nsrc/web.zig\nsrc/web/zstbi.zig\ntest/deck/replay.zig\ntest/deck/schema.zig\ntest/e2e_harness.zig\ntest/hxdiff.zig\ntest/image_harness.zig\ntest/lspbench.zig\ntest/lspfixture/broken.zig\ntest/lspfixture/dotcomplete.zig\ntest/lspfixture/dothalf.zig\ntest/pdf_bench.zig\ntest/pdf_scroll_bench.zig\ntest/pdf_sections_bench.zig\ntest/perf.zig\ntest/snapshot.zig\ntools/embed_zig_sources.zig\ntools/gen_themes.zig\nuucode_config.zig\n",
- .stream_b64 = "G10xMzM7QwcbXTEzMztEBxtdMTMzO0MHG10wO2dvYmxpbkBwYXJkZXM6L3RtcC9wYXJkZXMtc25hcC9zb3VyY2UtbGlzdC1jYXB0dXJlL2N3ZAcbWz8yMDA0aBtdMTMzO0E7Y2w9bGluZQckIBtdMTMzO0IHDRtbSw0bXTEzMztBO2NsPWxpbmUHJCAbXTEzMztCB2NkIC9ob21lL2dvYmxpbi8wMC1wcm9qZWN0cy8weDQyMDAuY2FmZS8wMi1wYXJkZXMtY29kZQ0KG1s/MjAwNGwNG10xMzM7QwcbXTEzMztDBxtdMTMzO0QHG10xMzM7QwcbXTA7Z29ibGluQHBhcmRlczovaG9tZS9nb2JsaW4vMDAtcHJvamVjdHMvMHg0MjAwLmNhZmUvMDItcGFyZGVzLWNvZGUHG1s/MjAwNGgbXTEzMztBO2NsPWxpbmUHJCAbXTEzMztCBxtbS2NsZWFyDQobWz8yMDA0bA0bXTEzMztDBxtbSBtbMkobWzNKG10xMzM7QwcbXTEzMztEBxtdMTMzO0MHG10wO2dvYmxpbkBwYXJkZXM6L2hvbWUvZ29ibGluLzAwLXByb2plY3RzLzB4NDIwMC5jYWZlLzAyLXBhcmRlcy1jb2RlBxtbPzIwMDRoG10xMzM7QTtjbD1saW5lByQgG10xMzM7QgdnaXQgbHMtZmlsZXMgLS1jYWNoZWQgLS1vdGhlcnMgLS1leGNsdWRlLXN0YW5kYXJkIC0tICcqLnppZycgfCBzb3J0DQobWz8yMDA0bA0bXTEzMztDBxtdMTMzO0MHYnVpbGQuemlnDQpidWlsZC9zbmFwLnppZw0KbXVwZGYuemlnDQpzcmMvYWxsb2NhdG9ycy56aWcNCnNyYy9hbmltYXRpb24uemlnDQpzcmMvYnVpbHRpbnMuemlnDQpzcmMvY29uZmlnLnppZw0Kc3JjL2R1bXAuemlnDQpzcmMvZWZmZWN0X3NvdXJjZXMuemlnDQpzcmMvZmlsZV9wYW5lLnppZw0Kc3JjL2ZvbnRzLnppZw0Kc3JjL2dyYW1tYXJfbWFuaWZlc3QuemlnDQpzcmMvZ3VpL2NydC56aWcNCnNyYy9ndWkvZGVjay56aWcNCnNyYy9ndWkvZ3VpLnppZw0Kc3JjL2ltYWdlLnppZw0Kc3JjL2ltYWdlX3BhbmUuemlnDQpzcmMvbG9vay56aWcNCnNyYy9sc3AvbHNwLnppZw0Kc3JjL2xzcC9sc3BfemxzLnppZw0Kc3JjL21hY29zLnppZw0Kc3JjL21haW4uemlnDQpzcmMvbWVzc2FnZS56aWcNCnNyYy9tb2RhbC56aWcNCnNyYy9uZXN0ZWQuemlnDQpzcmMvbm9ybWFsX2lucHV0LnppZw0Kc3JjL291dHB1dF9wYW5lLnppZw0Kc3JjL3BhbmVsX2FuaW1hdGlvbi56aWcNCnNyYy9wYXJkZXMuemlnDQpzcmMvcGRmLnppZw0Kc3JjL3BkZl9wYW5lLnppZw0Kc3JjL3BkZl9wYW5lX2ludGVncmF0aW9uX3Rlc3QuemlnDQpzcmMvcGV0c2NpaS56aWcNCnNyYy9ydW50aW1lX2NvbmZpZy56aWcNCnNyYy9zZWxlY3Rpb25fcGlwZS56aWcNCnNyYy9zaGVsbF9iaW4uemlnDQpzcmMvc3ludGF4LnppZw0Kc3JjL3RlbXBfZmlsZS56aWcNCnNyYy90ZXJtX3BhbmUuemlnDQpzcmMvdGhlbWVzL2FjbWUuemlnDQpzcmMvdGhlbWVzL2RhcmsuemlnDQpzcmMvdGhlbWVzL2hlbGl4LnppZw0Kc3JjL3RyYWN5LnppZw0Kc3JjL3R0eS9wYW5lbF9jb21wb3NpdG9yLnppZw0Kc3JjL3R0eS90dHkuemlnDQpzcmMvdXNlcl9jb25maWcuemlnDQpzcmMvd2ViLnppZw0Kc3JjL3dlYi96c3RiaS56aWcNCnRlc3QvZGVjay9yZXBsYXkuemlnDQp0ZXN0L2RlY2svc2NoZW1hLnppZw0KdGVzdC9lMmVfaGFybmVzcy56aWcNCnRlc3QvaHhkaWZmLnppZw0KdGVzdC9pbWFnZV9oYXJuZXNzLnppZw0KdGVzdC9sc3BiZW5jaC56aWcNCnRlc3QvbHNwZml4dHVyZS9icm9rZW4uemlnDQp0ZXN0L2xzcGZpeHR1cmUvZG90Y29tcGxldGUuemlnDQp0ZXN0L2xzcGZpeHR1cmUvZG90aGFsZi56aWcNCnRlc3QvcGRmX2JlbmNoLnppZw0KdGVzdC9wZGZfc2Nyb2xsX2JlbmNoLnppZw0KdGVzdC9wZGZfc2VjdGlvbnNfYmVuY2guemlnDQp0ZXN0L3BlcmYuemlnDQp0ZXN0L3NuYXBzaG90LnppZw0KdG9vbHMvZW1iZWRfemlnX3NvdXJjZXMuemlnDQp0b29scy9nZW5fdGhlbWVzLnppZw0KdXVjb2RlX2NvbmZpZy56aWcNChtdMTMzO0MHG10xMzM7RAcbXTEzMztDBxtdMDtnb2JsaW5AcGFyZGVzOi9ob21lL2dvYmxpbi8wMC1wcm9qZWN0cy8weDQyMDAuY2FmZS8wMi1wYXJkZXMtY29kZQcbWz8yMDA0aBtdMTMzO0E7Y2w9bGluZQckIBtdMTMzO0IHG1tL",
- .cursor = .{ .col = 2, .row = 27 },
- },
- .file = null,
- .image = null,
- }},
-}
diff --git a/test/web-snapshots/source-list.golden b/test/web-snapshots/source-list.golden
deleted file mode 100644
index 12af692c..00000000
--- a/test/web-snapshots/source-list.golden
+++ /dev/null
@@ -1,228 +0,0 @@
-== snap launcher-bottom grid=120x37 cursor=4,36
-|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
-| /home/goblin/00-projects/0x4200.cafe/02-pardes-code Save New Newtty Del Filter
-| src/pdf_pane_integration_test.zig
-| src/petscii.zig
-| src/runtime_config.zig
-| src/selection_pipe.zig
-| src/shell_bin.zig
-| src/syntax.zig
-| src/temp_file.zig
-| src/term_pane.zig
-| src/themes/acme.zig
-| src/themes/dark.zig
-| src/themes/helix.zig
-| src/tracy.zig
-| src/tty/panel_compositor.zig
-| src/tty/tty.zig
-| src/user_config.zig
-| src/web.zig
-| src/web/zstbi.zig
-| test/deck/replay.zig
-| test/deck/schema.zig
-| test/e2e_harness.zig
-| test/hxdiff.zig
-| test/image_harness.zig
-| test/lspbench.zig
-| test/lspfixture/broken.zig
-| test/lspfixture/dotcomplete.zig
-| test/lspfixture/dothalf.zig
-| test/pdf_bench.zig
-| test/pdf_scroll_bench.zig
-| test/pdf_sections_bench.zig
-| test/perf.zig
-| test/snapshot.zig
-| tools/embed_zig_sources.zig
-| tools/gen_themes.zig
-| uucode_config.zig
-|
-== snap launcher-top grid=120x37 cursor=4,36
-|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
-| /home/goblin/00-projects/0x4200.cafe/02-pardes-code Save New Newtty Del Filter
-| git ls-files --cached --others --exclude-standard -- '*.zig' | sort
-| build.zig
-| build/snap.zig
-| mupdf.zig
-| src/allocators.zig
-| src/animation.zig
-| src/builtins.zig
-| src/config.zig
-| src/dump.zig
-| src/effect_sources.zig
-| src/file_pane.zig
-| src/fonts.zig
-| src/grammar_manifest.zig
-| src/gui/crt.zig
-| src/gui/deck.zig
-| src/gui/gui.zig
-| src/image.zig
-| src/image_pane.zig
-| src/look.zig
-| src/lsp/lsp.zig
-| src/lsp/lsp_zls.zig
-| src/macos.zig
-| src/main.zig
-| src/message.zig
-| src/modal.zig
-| src/nested.zig
-| src/normal_input.zig
-| src/output_pane.zig
-| src/panel_animation.zig
-| src/pardes.zig
-| src/pdf.zig
-| src/pdf_pane.zig
-| src/pdf_pane_integration_test.zig
-| src/petscii.zig
-| src/runtime_config.zig
-== snap source-open grid=120x37 cursor=7,2
-|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
-| build.zig Save New Newtty Del
-| 1 const std = @import("std");
-| 2 const builtin = @import("builtin");
-| 3 const mupdf_build = @import("mupdf.zig");
-| 4 const snap_build = @import("build/snap.zig");
-| 5 const grammar_manifest = @import("src/grammar_manifest.zig");
-| 6 /// The package manifest, imported UNTYPED on purpose — see the `version`
-| 7 /// option in `shellOptions` for why that word is load-bearing.
-| 8 const zon = @import("build.zig.zon");
-| 9
-| 10 /// `esp32p4` is not a shell in this package at all: it is one freestanding
-| 11 /// OBJECT, compiled for riscv32-freestanding, which the `zig_p4` firmware
-| 12 /// package links beside its own `_start`. See the esp32p4 branch below.
-| 13 pub const Platform = enum { tty, gui, web, macos, esp32p4 };
-| 14
-| 15 /// The oldest macOS pardes.app claims to run on, spelled ONCE. Three things
-| 16 /// have to agree about it or the bundle is a lie: the target this build gives
-| 17 /// the static library, the `-target` the app's swiftc link is given (which is
-| /home/goblin/00-projects/0x4200.cafe/02-pardes-code Save New Newtty Del Filter
-| git ls-files --cached --others --exclude-standard -- '*.zig' | sort
-| build.zig
-| build/snap.zig
-| mupdf.zig
-| src/allocators.zig
-| src/animation.zig
-| src/builtins.zig
-| src/config.zig
-| src/dump.zig
-| src/effect_sources.zig
-| src/file_pane.zig
-| src/fonts.zig
-| src/grammar_manifest.zig
-| src/gui/crt.zig
-| src/gui/deck.zig
-| src/gui/gui.zig
-| src/image.zig
-== style source-open
-|0: 0-74 #949494,#121212, 75-119 d,#121212,
-|1: 0-1 #ffffff,#626262, 2-99 #949494,#121212, 100-119 d,#121212,
-|2: 0-0 d,#444444, 1-1 d,#080808, 2-6 #949494,#121212, 7-18 #bdbdbd,#080808, 19-25 #cf87e8,#080808,b 26-26 #bdbdbd,#080808, 27-31 #e3c78a,#080808, 32-33 #bdbdbd,#080808, 34-119 d,#080808,
-|3: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-29 #cf87e8,#080808,b 30-30 #bdbdbd,#080808, 31-39 #e3c78a,#080808, 40-41 #bdbdbd,#080808, 42-119 d,#080808,
-|4: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-26 #bdbdbd,#080808, 27-33 #cf87e8,#080808,b 34-34 #bdbdbd,#080808, 35-45 #e3c78a,#080808, 46-47 #bdbdbd,#080808, 48-119 d,#080808,
-|5: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-25 #bdbdbd,#080808, 26-32 #cf87e8,#080808,b 33-33 #bdbdbd,#080808, 34-49 #e3c78a,#080808, 50-51 #bdbdbd,#080808, 52-119 d,#080808,
-|6: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-31 #bdbdbd,#080808, 32-38 #cf87e8,#080808,b 39-39 #bdbdbd,#080808, 40-65 #e3c78a,#080808, 66-67 #bdbdbd,#080808, 68-119 d,#080808,
-|7: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-79 #ffffff,#080808,b 80-119 d,#080808,
-|8: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-69 #ffffff,#080808,b 70-119 d,#080808,
-|9: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-18 #bdbdbd,#080808, 19-25 #cf87e8,#080808,b 26-26 #bdbdbd,#080808, 27-41 #e3c78a,#080808, 42-43 #bdbdbd,#080808, 44-119 d,#080808,
-|10: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808,
-|11: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-81 #ffffff,#080808,b 82-119 d,#080808,
-|12: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-80 #ffffff,#080808,b 81-119 d,#080808,
-|13: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-78 #ffffff,#080808,b 79-119 d,#080808,
-|14: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-27 #bdbdbd,#080808, 28-31 #cf87e8,#080808,b 32-66 #bdbdbd,#080808, 67-119 d,#080808,
-|15: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-119 d,#080808,
-|16: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-82 #ffffff,#080808,b 83-119 d,#080808,
-|17: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-84 #ffffff,#080808,b 85-119 d,#080808,
-|18: 0-0 d,#121212, 1-1 d,#080808, 2-6 #626262,#080808, 7-84 #ffffff,#080808,b 85-119 d,#080808,
-|19: 0-1 #ffffff,#262626, 2-99 #949494,#121212, 100-119 d,#121212,
-|20: 0-0 d,#444444, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|21: 0-0 d,#444444, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|22: 0-0 d,#444444, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|23: 0-0 d,#444444, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|24: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|25: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|26: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|27: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|28: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|29: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|30: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|31: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|32: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|33: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|34: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|35: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-|36: 0-0 d,#121212, 1-1 d,#080808, 2-119 #bdbdbd,#080808,
-== snap separator-resized grid=120x37 cursor=7,2
-|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
-| build.zig Save New Newtty Del
-| 1 const std = @import("std");
-| 2 const builtin = @import("builtin");
-| 3 const mupdf_build = @import("mupdf.zig");
-| 4 const snap_build = @import("build/snap.zig");
-| 5 const grammar_manifest = @import("src/grammar_manifest.zig");
-| 6 /// The package manifest, imported UNTYPED on purpose — see the `version`
-| 7 /// option in `shellOptions` for why that word is load-bearing.
-| 8 const zon = @import("build.zig.zon");
-| 9
-| 10 /// `esp32p4` is not a shell in this package at all: it is one freestanding
-| 11 /// OBJECT, compiled for riscv32-freestanding, which the `zig_p4` firmware
-| 12 /// package links beside its own `_start`. See the esp32p4 branch below.
-| 13 pub const Platform = enum { tty, gui, web, macos, esp32p4 };
-| 14
-| 15 /// The oldest macOS pardes.app claims to run on, spelled ONCE. Three things
-| 16 /// have to agree about it or the bundle is a lie: the target this build gives
-| 17 /// the static library, the `-target` the app's swiftc link is given (which is
-| /home/goblin/00-projects/0x4200.cafe/02-pardes-code Save New Newtty Del Filter
-| src/allocators.zig
-| src/animation.zig
-| src/builtins.zig
-| src/config.zig
-| src/dump.zig
-| src/effect_sources.zig
-| src/file_pane.zig
-| src/fonts.zig
-| src/grammar_manifest.zig
-| src/gui/crt.zig
-| src/gui/deck.zig
-| src/gui/gui.zig
-| src/image.zig
-| src/image_pane.zig
-| src/look.zig
-| src/lsp/lsp.zig
-| src/lsp/lsp_zls.zig
-== snap source-scrolled grid=120x37 cursor=7,2
-|New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill
-| build.zig Save New Newtty Del
-| 1 const std = @import("std");
-| 2 const builtin = @import("builtin");
-| 3 const mupdf_build = @import("mupdf.zig");
-| 4 const snap_build = @import("build/snap.zig");
-| 5 const grammar_manifest = @import("src/grammar_manifest.zig");
-| 6 /// The package manifest, imported UNTYPED on purpose — see the `version`
-| 7 /// option in `shellOptions` for why that word is load-bearing.
-| 8 const zon = @import("build.zig.zon");
-| 9
-| 10 /// `esp32p4` is not a shell in this package at all: it is one freestanding
-| 11 /// OBJECT, compiled for riscv32-freestanding, which the `zig_p4` firmware
-| 12 /// package links beside its own `_start`. See the esp32p4 branch below.
-| 13 pub const Platform = enum { tty, gui, web, macos, esp32p4 };
-| 14
-| 15 /// The oldest macOS pardes.app claims to run on, spelled ONCE. Three things
-| 16 /// have to agree about it or the bundle is a lie: the target this build gives
-| 17 /// the static library, the `-target` the app's swiftc link is given (which is
-| /home/goblin/00-projects/0x4200.cafe/02-pardes-code Save New Newtty Del Filter
-| src/fonts.zig
-| src/grammar_manifest.zig
-| src/gui/crt.zig
-| src/gui/deck.zig
-| src/gui/gui.zig
-| src/image.zig
-| src/image_pane.zig
-| src/look.zig
-| src/lsp/lsp.zig
-| src/lsp/lsp_zls.zig
-| src/macos.zig
-| src/main.zig
-| src/message.zig
-| src/modal.zig
-| src/nested.zig
-| src/normal_input.zig
-| src/output_pane.zig
diff --git a/test/web-snapshots/source-list.snap b/test/web-snapshots/source-list.snap
deleted file mode 100644
index 136e583c..00000000
--- a/test/web-snapshots/source-list.snap
+++ /dev/null
@@ -1,42 +0,0 @@
-# Browser-only .snap commands. The page is built from a dump made by a real
-# Pardes TTY after running the same tracked-plus-new/nonignored source selection
-# as the web archive generator; touch events below use Chrome's browser path.
-wait 10000 uucode_config.zig
-stable 100 5000
-snap launcher-bottom
-
-# Replayed terminal state follows its live cursor at the bottom. Scroll to the
-# first half as an actual browser gesture: together these two snapshots cover
-# every path instead of silently testing only a stale suffix. The dump command
-# is sorted like the archive, leaving build.zig at row 3 once we reach the top.
-swipe 4 60 2 60 34 40
-wait 10000 build.zig
-stable 100 5000
-snap launcher-top
-
-# A little sub-slop movement is still a tap. On web one-finger taps are LOOK,
-# so this opens build.zig from the working-tree archive generated from Git's
-# tracked-plus-new/nonignored source view.
-touch down 1 5 3
-touch move 1 5.2 3.1
-touch up 1 5.2 3.1
-# The editable path and the right-aligned command tail deliberately have
-# layout-owned padding between them. Check the two semantic facts separately.
-wait 10000 Save New Newtty Del
-wait 10000 build.zig
-stable 100 5000
-snap source-open
-snapstyle source-open
-
-# A touch that begins on the horizontal pane separator is a latched left-mouse
-# resize gesture. Crossing the body-scroll threshold must never turn it into a
-# wheel gesture.
-swipe 2 60 23 60 19 8
-stable 100 5000
-snap separator-resized
-
-# Travel well outside the tap slop becomes natural one-finger scrolling and
-# must not also click/LOOK at the release point.
-swipe 3 60 34 60 27 12
-stable 100 5000
-snap source-scrolled
diff --git a/test/web-snapshots/touch.dump.zon b/test/web-snapshots/touch.dump.zon
new file mode 100644
index 00000000..230d29e7
--- /dev/null
+++ b/test/web-snapshots/touch.dump.zon
@@ -0,0 +1,73 @@
+.{
+ .screen = .{ .cols = 100, .rows = 30 },
+ .theme = "helix",
+ .columns = .{.{ .panes = .{0} }},
+ .panes = .{.{
+ .kind = .file,
+ .tag = "touch-fixture.zig",
+ .body = "",
+ .file = .{
+ .path = "touch-fixture.zig",
+ .content =
+ \\pub fn choose(value: u32) []const u8 {
+ \\ if (value == 42) return "touch fixture";
+ \\ return "/virtual/pane/1/body";
+ \\}
+ \\
+ \\pub const rows = [_]u32{
+ \\ 0,
+ \\ 1,
+ \\ 2,
+ \\ 3,
+ \\ 4,
+ \\ 5,
+ \\ 6,
+ \\ 7,
+ \\ 8,
+ \\ 9,
+ \\ 10,
+ \\ 11,
+ \\ 12,
+ \\ 13,
+ \\ 14,
+ \\ 15,
+ \\ 16,
+ \\ 17,
+ \\ 18,
+ \\ 19,
+ \\ 20,
+ \\ 21,
+ \\ 22,
+ \\ 23,
+ \\ 24,
+ \\ 25,
+ \\ 26,
+ \\ 27,
+ \\ 28,
+ \\ 29,
+ \\ 30,
+ \\ 31,
+ \\ 32,
+ \\ 33,
+ \\ 34,
+ \\ 35,
+ \\ 36,
+ \\ 37,
+ \\ 38,
+ \\ 39,
+ \\ 40,
+ \\ 41,
+ \\ 42,
+ \\ 43,
+ \\ 44,
+ \\ 45,
+ \\ 46,
+ \\ 47,
+ \\ 48,
+ \\ 49,
+ \\ 50,
+ \\};
+ ,
+ },
+ }},
+}
diff --git a/test/web-snapshots/touch.mjs b/test/web-snapshots/touch.mjs
new file mode 100644
index 00000000..1a233e68
--- /dev/null
+++ b/test/web-snapshots/touch.mjs
@@ -0,0 +1,99 @@
+import assert from "node:assert/strict";
+
+function tags(frame) {
+ return frame.styleRows.flatMap((cells, y) => y > 0 && cells.some((cell) => cell[2] & 128) ? [y] : []);
+}
+
+function pane(frame, name) {
+ const rows = tags(frame);
+ const top = rows.find((row) => frame.lines[row].includes(name));
+ assert.notEqual(top, undefined, `missing pane ${name}`);
+ const bottom = rows.find((row) => row > top) ?? frame.rows;
+ return { top, bottom, lines: frame.lines.slice(top + 1, bottom) };
+}
+
+function styled(frame) {
+ const source = pane(frame, "touch-fixture.zig");
+ for (const [line, word, fg, bold] of [
+ ["pub fn choose", "fn", 0xcf87e8, true],
+ ["pub fn choose", "choose", 0xbdbdbd, false],
+ ["if (value", "if", 0xcf87e8, true],
+ ["if (value", "42", 0xe3c78a, false],
+ ["if (value", '"touch fixture"', 0xe3c78a, false],
+ ]) {
+ const row = source.lines.findIndex((text) => text.includes(line));
+ assert(row >= 0, `missing source line ${line}`);
+ const col = source.lines[row].indexOf(word);
+ for (let x = col; x < col + word.length; x++) {
+ const style = frame.styleRows[source.top + 1 + row][x];
+ assert.equal(style[0], fg, `${word} cell ${x - col} foreground`);
+ assert.equal(Boolean(style[2] & 1), bold, `${word} cell ${x - col} bold`);
+ }
+ }
+ for (const [row, line] of source.lines.entries()) {
+ const number = /\b(\d+),/.exec(line);
+ if (!number) continue;
+ for (let x = number.index; x < number.index + number[1].length; x++) {
+ assert.equal(frame.styleRows[source.top + 1 + row][x][0], 0xe3c78a, `row ${row} number foreground`);
+ }
+ }
+}
+
+export default async function ({ grid, touch, wait, stable, delay }) {
+ await stable(100, 5000);
+ let frame = await grid();
+ assert.equal(tags(frame).length, 1);
+ styled(frame);
+ const link = "/virtual/pane/1/body";
+ const row = frame.lines.findIndex((text) => text.includes(link));
+ const col = frame.lines[row].indexOf(link) + 5;
+ let finger = await touch("down", 1, col, row, null);
+ finger = await touch("move", 1, col + 0.2, row + 0.1, finger);
+ await touch("up", 1, col + 0.2, row + 0.1, finger);
+ await wait(async () => tags(await grid()).length === 2, 5000, "Look opening the reflected body");
+ await stable(100, 5000);
+ frame = await grid();
+ styled(frame);
+ const reflected = pane(frame, link);
+ assert(reflected.lines.some((text) => text.includes("pub fn choose")));
+ const original = pane(frame, "touch-fixture.zig");
+ const sharedRows = Math.min(reflected.lines.length, original.lines.length);
+ assert(sharedRows >= 6);
+ assert.deepEqual(reflected.lines.slice(0, sharedRows), original.lines.slice(0, sharedRows), "Look must read the source pane body");
+
+ const center = Math.floor(frame.cols / 2);
+ const separator = Math.max(original.top, reflected.top) - 1;
+ const distance = original.top < reflected.top ? 4 : -4;
+ finger = await touch("down", 2, center, separator, null);
+ for (let step = 1; step <= 8; step++) {
+ finger = await touch("move", 2, center, separator + distance * step / 8, finger);
+ await delay(20);
+ }
+ await touch("up", 2, center, separator + distance, finger);
+ await stable(100, 5000);
+ frame = await grid();
+ assert.equal(tags(frame).length, 2);
+ const resized = pane(frame, "touch-fixture.zig");
+ assert(resized.lines.length >= original.lines.length + 3, "separator drag must resize, not scroll the body");
+ assert.equal(resized.lines[0], original.lines[0], "resizing must preserve the source viewport");
+ styled(frame);
+
+ const beforeScroll = resized.lines[0];
+ const reflectedBeforeScroll = pane(frame, link).lines;
+ const from = resized.bottom - 3;
+ const to = Math.max(resized.top + 2, from - 7);
+ finger = await touch("down", 3, center, from, null);
+ for (let step = 1; step <= 12; step++) {
+ finger = await touch("move", 3, center, from + (to - from) * step / 12, finger);
+ await delay(20);
+ }
+ await touch("up", 3, center, to, finger);
+ await stable(100, 5000);
+ frame = await grid();
+ assert.equal(tags(frame).length, 2, "scroll must not also Look");
+ const scrolled = pane(frame, "touch-fixture.zig");
+ assert.equal(scrolled.top, resized.top, "body scrolling must not resize");
+ assert.notEqual(scrolled.lines[0], beforeScroll, "source must scroll");
+ assert(Number(scrolled.lines[0].trim().split(/\s+/)[0]) > 1, "scroll advances source line numbers");
+ assert.deepEqual(pane(frame, link).lines, reflectedBeforeScroll, "scrolling the source must leave its neighbor alone");
+}