Skip to content

Add ry canvas: a zoomable, transcluding map of R code - #91

Closed
felix-andreas wants to merge 1 commit into
mainfrom
claude/ast-code-viewer-zoom-xv1wix
Closed

Add ry canvas: a zoomable, transcluding map of R code#91
felix-andreas wants to merge 1 commit into
mainfrom
claude/ast-code-viewer-zoom-xv1wix

Conversation

@felix-andreas

@felix-andreas felix-andreas commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Closed: the canvas now lives in its own repository, felix-andreas/ry-canvas, and depends on ry over a git dependency pinned by its own Cargo.lock rather than by path.

What changed in the move, beyond the packaging:

  • Addressed the review on this PR. The 197 KiB row described the in-memory index, not the download, and the module shipped without wasm-opt — the build now runs wasm-opt -Oz (2.20 MiB → 1.37 MiB raw, 583 KiB → 501 KiB gzipped, and it loads faster), and the README carries a cost table separating download from index payload. The vendored stringr also now ships the full MIT permission notice, not just the CRAN stub.
  • "Nothing builds canvas in any gate" is fixed by the split: the new repo has its own CI (fmt, clippy, tests, cargo check --target wasm32-unknown-unknown, typecheck, web build) plus a weekly run against the pinned ry commit, so a break surfaces before someone hits it mid-bump. just gate is the same set locally.
  • The two-lockfile divergence noted in the review is now simply two repositories, which is what that observation was pointing at.

One correction to this PR's description: the claim that cargo check --workspace fails on repl because extendr-engine needs R was true for the base this branch was cut from, but rofy has since been removed and cargo check -p repl passes on current main. The reviewer was right.

The branch claude/ast-code-viewer-zoom-xv1wix is left in place with the original in-tree commit, so nothing here is lost.

A standalone project that consumes ry as a library and puts a whole R
codebase on one infinite surface. Zoom out for architecture, zoom in and
definitions resolve through structure into real selectable source. Click a
resolved name and its definition splices into the body you are reading,
indented and framed, recursively — the camera never moves, so following a
reference never costs you your place.

canvas/core builds ry's syntax, semantics and ide crates to
wasm32-unknown-unknown, unchanged: they have no threading or filesystem
access outside test helpers. It projects a project into one flat index of
cards, classified tokens, inferred types and — the part that makes inline
expansion possible — every reference that resolves to another project
definition, from item_naming(..).non_locals resolved through
package_definitions. Reference edges come from item_interface_reads, the
projection already maintained for the incremental firewall. The wasm
boundary is a raw C ABI rather than wasm-bindgen: one string in, one string
out does not justify a generated binding layer and a toolchain to install.

canvas/web draws structure in WebGL2 and hands the last zoom decade to the
DOM, which buys selectable text, browser find, font fallback and
screen-reader access that a glyph atlas cannot offer. Four crossfaded
bands run from colored blocks through per-line and per-token bars to full
highlighted source. Layout is deterministic and expansion is local: frame
sub-columns and shelf rows are fixed from collapsed sizes, so opening a
definition can only ever push things downward.

Its own cargo workspace, excluded from the root one, so moving it out of
this repository stays a directory move.

Verified against stringr (35 files, 167 definitions, 297 references):
64 ms native, 214 ms in wasm, 60 fps at both overview and reading zoom,
1.2 ms relayout.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MJqJJRwRnzXgLnpTFEwYiP
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying ry-lang with  Cloudflare Pages  Cloudflare Pages

Latest commit: 17ee2c9
Status: ✅  Deploy successful!
Preview URL: https://2c217691.ry-lang.pages.dev
Branch Preview URL: https://claude-ast-code-viewer-zoom.ry-lang.pages.dev

View logs

@felix-andreas

Copy link
Copy Markdown
Owner Author

Reviewed by checking the branch out and running it rather than reading the diff, since most of the claims here are testable. Not merging — it is a new subproject and that is the author's call — but here is what holds and what does not.

Verified

claim result
Nothing in crates/ changed True. 63 of 65 files are under canvas/; the rest are Cargo.toml (+3, the exclude) and one MEMORY.md line.
ide + semantics + syntax + salsa build for wasm32-unknown-unknown unchanged True, and it is the most valuable thing here. cargo build --release --target wasm32-unknown-unknown -p canvas-core succeeds with no changes to those crates.
Canvas builds and its tests pass Truecargo check --workspace clean, 6/6 tests pass.
No R logic reimplemented True. No parser, no lexer, no regex-based analysis in canvas/core; it consumes the queries it says it does.
Root workspace unaffected Truecanvas-core is absent from root cargo metadata, and the root gate is unchanged.

It also merges cleanly with current main and still builds — I tested that, since main moved under it (the HIR/naming queries went from returns(clone) to returns(ref) after this branch's base).

Four things to fix or answer

1. The payload figure does not describe the download. The table says payload | 197 KiB, which a reader takes as what the browser fetches. bun run core copies the wasm with no wasm-opt and no compression step, and that artifact is 2.2 MiB raw, 586 KiB gzipped. If 197 KiB is the JS bundle or the stringr index, please say which — as written it reads as the whole thing, and it is off by 3× against the gzip figure and 11× against the raw one. wasm-opt -Oz in the core script would also be a real improvement, not just an honest number.

2. The repl / extendr note is false on this branch's own base. The description says repl fails cargo check because extendr-engine needs R. That crate was deleted in 8dbf206, before this branch's base 1b42b1d. On the base commit: extendr appears nowhere in the workspace, and cargo check -p repl exits 0. Harmless to the code, but it suggests the verification run happened against a stale tree, which makes the rest of the "Verification" section harder to trust than it deserves to be.

3. Nothing builds canvas in any gate, and it depends on crates/* by path. exclude = ["canvas"] keeps it out of the root workspace, so a change to semantics or ide can break it and no gate will notice. This project has just spent a week on the consequences of exactly that shape — 2,830 legacy fixtures that nothing ran. Cheapest fix that keeps the directory-move property: a just canvas-check recipe, plus a line in the staged CI. If you would rather accept the drift, say so in canvas/README.md so the next person to break it knows it was a decision.

4. Two lockfiles, and they have already diverged. canvas/Cargo.lock resolves serde_json 1.0.151 against the root's 1.0.145. Harmless today, but it means canvas builds ry's crates against different transitive versions than the product does, so a bug can reproduce in one and not the other. Worth a note in the README that this is expected, since it is inherent to the separate-workspace choice rather than a mistake.

Smaller

  • Vendored licence. demo/LICENSE is the two-line CRAN stub (YEAR: / COPYRIGHT HOLDER:), which is correct for CRAN, where MIT + file LICENSE implies the standard text. Redistributing outside that context, the MIT terms ask for the permission notice itself to travel with the copy — upstream ships LICENSE.md for this. Adding that file is a one-line fix and removes the question. The NOTICE.md is otherwise exactly right.
  • The six tests are well chosen — stub names not being expandable and self-recursion producing a reference but no edge are the two I would have asked for.

On the design decisions

No objection to any of them, and two are worth endorsing explicitly. Raw C ABI over wasm-bindgen is right for a one-string-in-one-string-out surface. And holding layout fixed from collapsed sizes so expansion only pushes downward is the decision the whole idea rests on — a canvas whose landmarks move cannot build spatial memory, and it is easy to get that wrong by reflowing.

The wasm finding deserves to outlive this PR either way: the analysis core is browser-portable as-is, with no threading or filesystem assumptions to unpick. That is worth knowing even if the canvas itself ends up in its own repository.


Generated by Claude Code

@felix-andreas
felix-andreas deleted the claude/ast-code-viewer-zoom-xv1wix branch August 4, 2026 21:33
@felix-andreas
felix-andreas restored the claude/ast-code-viewer-zoom-xv1wix branch August 4, 2026 21:34
@felix-andreas
felix-andreas deleted the claude/ast-code-viewer-zoom-xv1wix branch August 4, 2026 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants