feat(syntax): a bare figure fence is a composite figure, and the pin moves with it - #22
Merged
Merged
Conversation
…moves with it
PART 9 section 4c reserves the kind word `figure` among the `:::` types: a
BARE opener - the fence, its separator, the word, and nothing else - is ONE
figure of ordered panels, not an admonition. An opener carrying a quoted
title or a `[label]` is a generic container and must stay one.
Three things move together here, because they are one fact about this
repository: the tree-sitter queries are copies, `install_revision` pins the
grammar they were copied from, and `tools/check-query-drift.sh` compares
them against THAT rev rather than a moving main. So the pin, the seven query
files and the syntax file are bumped in one commit, and the drift check is
what proves the copy is still a copy.
The pin moves to tree-sitter-carve at composite figures, which is where a
bare `::: figure` opener's class word captures `@type.builtin` rather than
the generic `@type`.
syntax/carve.vim gets the same distinction for users who do not install the
tree-sitter grammar at all. Two details worth naming:
- ORDER IS PRECEDENCE. Vim gives a later `syntax match` priority at the
same position, so carveFigureGroup sits AFTER carveDivFence. Written
before it - which reads more naturally - the div rule won every line and
the new group was unreachable; the highlight assertions caught it.
- The separator is a SPACE run, never a tab (grammar PART 7, MARKER
SEPARATORS). A tab-separated opener is left to carveDivFence, which
over-colours it exactly as it does today.
tests/highlight.crv carries the assertions, both halves in one document: the
bare opener's fence and kind word, the group caption on the line after the
closing fence, and the titled opener whose fence and title must stay
carveDivFence and carveDivTitle.
The first pass spelled the composite figure as a `syntax match`, which has no notion of being inside anything: every nested `::: figure` was coloured as another group, where PART 9 section 4c says a bare opener inside an open group is a generic container at ANY depth. A region says it. `contains=ALLBUT,carveFigureGroup` is the whole mechanism - a bare opener inside the group cannot match the group rule again, so it falls through to carveDivFence, which is the generic reading. It holds through a quote or a list item as readily as directly, because containment is structural rather than a pattern per shape. `\z(` / `\z1` is the colon-fence depth rule (PART 9 12): the region closes on a fence of the SAME length that opened it, which is what lets `::::` nest inside `:::`. `keepend` stops an inner item from carrying the region past its own closer, and the region ending AT the closing fence is what leaves the group caption to carveCaption at the top level. The word-level group is gone with the match: `matchgroup` colours the whole delimiter line as carveFigureGroupFence, and the distinction that matters - a bare opener reading differently from `::: figure "T"` - is carried by that group against carveDivFence. Assertions cover the opener, the closer, the caption below it, the titled opener that must stay carveDivFence with its carveDivTitle, and the nested opener that must degrade.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Carries the composite-figures vocabulary into this repo, both halves of what it ships. Part of markup-carve/carve-grammars#222; spec PART 9 §4c, landed as markup-carve/carve#1215, design markup-carve/carve#1122.
Three things move together
They are one fact about this repository:
queries/carve/*.scmare copies,install_revisionpins the grammar they were copied from, andtools/check-query-drift.shcompares them against THAT rev rather than a moving main. So the pin and the seven query files move in one commit, and the drift check is what proves the copy is still a copy.The pin moves to
tree-sitter-carveat composite figures (17362de, markup-carve/tree-sitter-carve#197), where a bare::: figureopener's class word captures@type.builtinrather than the generic@type.The syntax file, for users who never install the grammar
Input:
The fence lines are
carveFigureGroupFence; the^line below the closer iscarveCaption, claimed at the top level exactly as every other caption is.The control, which must not change:
Still
carveDivFencewithcarveDivTitle.And the degradation:
The inner opener is
carveDivFence.Why a region and not a match
The first commit here used a
syntax match, which has no notion of being inside anything, so every nested::: figurecoloured as another group. A region says it:contains=ALLBUT,carveFigureGroupmeans a bare opener inside the group cannot match the group rule again and falls through tocarveDivFence. That holds through a quote or a list item as readily as directly, because containment is structural rather than a pattern per shape.\z(/\z1is the colon-fence depth rule (PART 9 §12) - the region closes on a fence of the SAME length that opened it, which is what lets::::nest inside:::.Two details found by watching the assertions fail rather than by reading:
syntax matchpriority at the same position. Written beforecarveDivFence- which reads more naturally - the div rule won every line and the new group was unreachable.carveDivFence, which over-colours it exactly as it does today.On one codex finding, deliberately not acted on
Codex flagged that
queries/carve/highlights.scmenforces the no-nesting rule only to a fixed depth. That is true, and it is upstream's residual, stated at the rule there. It must not be fixed here: that file is a verbatim copy andtools/check-query-drift.shfails the moment it diverges from the pinnedtree-sitter-carvecommit. A deeper reach belongs in markup-carve/tree-sitter-carve and arrives here with the next pin bump.