pmacs/builtin/runtime
Levi Neuwirth 4282b1c333 feat(injections): multi-language injection layers
Teach the syntax engine that one buffer can hold more than one
language. After the root parse, run the grammar's injections.scm, parse
each embedded region with the injected language, and merge every
layer's highlight spans. First consumer: markdown fenced code + inline
(zero new grammars — the block grammar already ships an injection query
and the injected langs already have grammars from #118).

Engine (src/syntax.rs):
- ParseTreeBundle now holds Vec<Layer> (root layer 0 + injected
  children, depth-ascending); installed atomically so the existing
  Arc::ptr_eq style gate and highlight cache keep working (Q#IJ1).
- run_parse builds layers on the worker: run injections.scm, resolve
  the injected language, compute Vec<Range> (exclude NAMED children,
  intersect the parent's ranges), set_included_ranges cold-parse,
  recurse — bounded by depth (3), a layer backstop (4096), and a
  (lang,ranges) visited guard; any child failure drops that child only
  (Q#IJ3/IJ5). LanguageEntry gains injections_query; markdown_inline is
  registered (retires the M9.7 block-only floor); markdown/rust carry
  injection queries.
- Injected languages resolve off the static BUILTIN_LANGUAGES table
  (Send loaders + query sources), preserving lazy loading. Dynamic
  fence names go through a case-folded alias map seeded with defaults
  and Lua-extensible via pmacs.parse.injection_aliases, snapshotted into
  ParseRequest at dispatch so the worker never touches the Rc registry
  or a Lua table (Q#IJ2/IJ4). Highlight queries are resolved at settle
  (resolve_layer_queries), keeping query compilation main-thread/cached.

Producers:
- SyntaxHighlightView (grid) iterates layers shallow-to-deep so a
  deeper layer's styling wins within its region (Q#IJ6/IJ7).
- scoped_style_spans (wire) flattens all layers into DISJOINT effective
  spans via a boundary sweep, since the GPU re-sorts spans by start
  (replace_style_spans / merge_style_spans) and would otherwise destroy
  producer order. The GPU source_color_at consumer is fixed to fold all
  covering spans (matching semantic_client's effective_style_at) rather
  than returning the first.

Named-children exclusion: content ranges exclude only NAMED children
(matching tree-sitter-md's own inline splitter) — excluding a block
inline node's anonymous text tokens would shred the paragraph into
unparseable fragments.

13 acceptance gates (framing docs/multi-language-injections-framing.md):
layer structure, absolute child offsets, alias resolution (static +
case-folded dynamic + unknown-skip + Lua-async override), multi-range
inline, recursion bounds, wire + grid + GPU producers, incremental edit
/ new fence, many-paragraph settle budget with tail coverage, and the
single-layer regression guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJ9FQ832QwftJXCD9LeFan
2026-07-15 12:07:21 +01:00
..
async.lua V0.2-prerequisite pull-forward + M10.11 clean audit round 2026-05-18 10:31:31 -04:00
autosave.lua fix(persistence): adopt clears the old owner's skip cache; failing sweeps are loud 2026-07-09 12:06:49 -04:00
comment.lua feat(edit): comment/uncomment toggle on M-; (Arc 2) 2026-07-09 22:56:44 -04:00
compile.lua fix(compile): PR #113 round 5 — buffer-level span translation, fragment preservation, tracked line start 2026-07-13 22:07:01 +01:00
completion.lua fix(completion): address TUI-validation findings (LSP query gaps, scoping, prefix keys, window scope) 2026-07-07 16:54:14 -04:00
desktop.lua fix(persistence): reliable daemon gate, unarm, per-pane after-load 2026-07-08 22:27:24 -04:00
editops.lua fix(edit): PR #111 round 1 — scalar-valid UTF-8, per-word capitalize, trim error reporting 2026-07-12 16:34:18 +01:00
fs.lua V0.2-prerequisite pull-forward + M10.11 clean audit round 2026-05-18 10:31:31 -04:00
indent.lua fix(edit): PR #109 round 1 — shared search invalidation, daemon anchor clear, bounded indent scan 2026-07-10 15:46:36 -04:00
killring.lua feat(edit): editing-conveniences pack (editops) 2026-07-12 15:33:17 +01:00
listview.lua feat(panels): listview module, Q#P6 round-trip seam, references panel 2026-07-07 20:15:46 -04:00
lsp.lua fix(highlight): PR #118 round 1 — drop locals-predicate captures; stale comments 2026-07-14 17:45:09 +01:00
mcp.lua M9 ship gate 2026-05-09 15:04:23 -04:00
pair.lua fix(edit): PR #110 round 2 — UTF-8 well-formedness, source-buffer relevance, non-table sets 2026-07-12 15:54:16 +01:00
recentf.lua fix(persistence): symlink confinement, real test-inertness, view_top restore 2026-07-08 18:21:46 -04:00
saveplace.lua fix(persistence): symlink confinement, real test-inertness, view_top restore 2026-07-08 18:21:46 -04:00
syntax.lua feat(injections): multi-language injection layers 2026-07-15 12:07:21 +01:00