Skip to content

Implement sublime-syntax Build 4075 features#610

Merged
keith-hall merged 2 commits into
trishume:masterfrom
stefanobaghino:sublime-syntax-build-4075
Mar 9, 2026
Merged

Implement sublime-syntax Build 4075 features#610
keith-hall merged 2 commits into
trishume:masterfrom
stefanobaghino:sublime-syntax-build-4075

Conversation

@stefanobaghino

@stefanobaghino stefanobaghino commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

Makes progress towards #323.

This adds support for the remaining .sublime-syntax features introduced in Sublime Text Build 4075. hidden_file_extensions and pop: N were already handled; this PR covers the rest.

What changed

extends (single syntax inheritance)

A child syntax can now declare extends: Packages/Foo/Foo.sublime-syntax to inherit all contexts and variables from a parent. The builder resolves extends chains (including transitive ones) in a fixed-point loop before the existing linking phase:

  1. Merge variables -- parent first, child overrides win.
  2. Merge contexts -- parent contexts absent from the child are inherited as-is; contexts the child redefines replace the parent version unless meta_prepend or meta_append is used.
  3. Re-resolve every regex that stored a raw string, applying the merged variable map through the full pipeline (variable substitution, POSIX class replacement, newline handling).
  4. If a child now has a main context but lacked __start/__main, the initial contexts are generated.

Missing or circular parents produce a warning on stderr and are skipped.

meta_prepend / meta_append

When a child context uses meta_prepend: true, its patterns are placed before the parent's patterns. meta_append: true places them after. Parent meta scopes and clear_scopes are inherited when the child does not set them.

apply_prototype: true

A new Pattern::IncludeWithPrototype variant. When iterating patterns, the external syntax's prototype is walked alongside the included context (respecting meta_include_prototype).

version: 2

Parsed from YAML and stored on both SyntaxDefinition and SyntaxReference. The parser reads it at match time and applies two behavioral fixes in push_meta_ops:

  • set + meta_content_scope: the old context's meta_content_scope is no longer applied to the matched text.
  • multiple push + clear_scopes: only the topmost context's clear_scopes is used instead of summing all of them.

Raw regex storage

Each MatchPattern now carries an optional raw_regex_str -- the regex as written in YAML before variable resolution. This is needed so that extends resolution can re-resolve parent regexes with overridden variables.

Files touched

File What
src/parsing/syntax_definition.rs New fields (extends, version, raw_regex_str, merge_mode), new enum ContextMergeMode, new pattern variant IncludeWithPrototype
src/parsing/yaml_load.rs Parse extends, version, meta_prepend, meta_append, apply_prototype; store raw regex; re-resolution helpers
src/parsing/syntax_set.rs resolve_extends phase in build(); find_parent_index helper; updated linking/backref/prototype code for new pattern variant
src/parsing/parser.rs current_syntax_version helper; version-conditional branches in push_meta_ops
assets/*.packdump Regenerated (make packs)
tests/snapshots/public-api.txt Updated

Not included

  • Multiple inheritance (extends as a list) -- rare in practice; deferred.
  • Three of the five version: 2 edge cases (embed_scope replacement, set+clear_scopes, embed escape meta scopes) -- they need more investigation into the exact Sublime behavior.

Test plan

  • 17 new unit tests covering parsing of each new key, extends resolution (inherit, override, prepend, append, variable override, missing parent), apply_prototype, version field propagation.
  • All 146 existing + new tests pass (cargo test).
  • Verified with --features metadata (129 pass) and --no-default-features --features regex-fancy (114 pass).

Add support for the remaining sublime-syntax features from
Sublime Text Build 4075, tracked in issue trishume#323:

- `extends`: single syntax inheritance. Child syntaxes can extend a
  parent, inheriting its contexts and variables. The builder resolves
  extends chains before linking, merging contexts according to the
  child's merge mode and re-resolving regexes with merged variables.

- `meta_prepend` / `meta_append`: when a child redefines a parent
  context, these directives insert child patterns before or after the
  parent patterns instead of replacing them outright.

- `apply_prototype: true`: when including a context from another syntax,
  this flag causes the external syntax's prototype to also be included
  alongside the referenced context.

- `version: 2`: parsed and propagated to SyntaxReference so the parser
  can apply version-conditional scope fixes. Two fixes implemented:
  * `set` no longer applies the old context's meta_content_scope to the
    matched text.
  * Multiple push with clear_scopes uses only the topmost context's
    value instead of summing them.

Each MatchPattern now stores its original YAML regex string so that
variable re-resolution after extends merging can re-apply the full
regex pipeline (resolve variables, replace POSIX classes, newline
handling).

Regenerated default packdumps and updated the public API snapshot.

@keith-hall keith-hall left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, nice, thanks for taking this on - looks good to me!

@keith-hall

Copy link
Copy Markdown
Collaborator

Not included

* Multiple inheritance (`extends` as a list) -- rare in practice; deferred.

We will for sure want to support this in a future PR, in order to support TSX etc. https://github.com/sublimehq/Packages/blob/master/JavaScript/TSX.sublime-syntax#L7-L9

@CosmicHorrorDev

Copy link
Copy Markdown
Contributor

the raw regex storage should put us closer to #541 which is nice


funny seeing that the failure is a formatting difference with the MSRV. formatting could probably be dropped from that job given that MSRV is more of a "it compiles" thingy

@stefanobaghino

Copy link
Copy Markdown
Contributor Author

funny seeing that the failure is a formatting difference with the MSRV. formatting could probably be dropped from that job given that MSRV is more of a "it compiles" thingy

I still fixed it in eb4c554, seemed sensible. 🙂

@keith-hall keith-hall requested a review from Enselic March 4, 2026 19:31
@keith-hall

Copy link
Copy Markdown
Collaborator
  • Verified with --features metadata (129 pass) and --no-default-features --features regex-fancy (114 pass).

Purely out of curiosity, I'd be interested to see the results when running with fancy-regex's main branch - there's a bunch of Oniguruma compatibility fixes I have made but not released yet. (Waiting for fancy-regex/fancy-regex#230 to be reviewed/merged mainly)

@stefanobaghino

stefanobaghino commented Mar 4, 2026

Copy link
Copy Markdown
Contributor Author

I just wanted to let you know that I'm doing this because 2 years ago I couldn't get syntax highlighting for a preview feature of Java that has been removed since (but that was somehow already supported by the Sublime syntax definitions). 😄

@Enselic

Enselic commented Mar 4, 2026

Copy link
Copy Markdown
Collaborator

I've skimmed the code through and have no objections as long as I am not seen as responsible for maintaining the code over time :)

If someone didn't already try, it would be good to test this implementation against a bunch of real-world syntaxes with bat that we couldn't use before because of the missing features. So we know it works for real, and not just with unit tests.

If I were to review this I would prefer to split this into smaller PRs instead of implementing all features in one giant PR. But I don't really want to do a detailed review :) so if others are fine with the code and functionality that split is not needed as far as I'm personally concerned.

@Enselic

Enselic commented Mar 4, 2026

Copy link
Copy Markdown
Collaborator

One more thing: If we can implement this without changing the public API surface of syntect that would be even better, but I understand if that wouldn't work.

@stefanobaghino

Copy link
Copy Markdown
Contributor Author
  • Verified with --features metadata (129 pass) and --no-default-features --features regex-fancy (114 pass).

Purely out of curiosity, I'd be interested to see the results when running with fancy-regex's main branch - there's a bunch of Oniguruma compatibility fixes I have made but not released yet. (Waiting for fancy-regex/fancy-regex#230 to be reviewed/merged mainly)

I pointed the fancy-regex dependencies to both the latest state of the main and subroutine_support branches and the test results always matched the current state.

@stefanobaghino

stefanobaghino commented Mar 5, 2026

Copy link
Copy Markdown
Contributor Author

@Enselic Thanks for your feedback. To be clear, my hope here is to be helpful and from your message I'm under the impression that this contribution might be counterproductive. In the interest of making this contribution sustainable, I'd like to make sure there's alignment. I apologize in advance if I'm asking any dumb question, but I hope those ensure that this contribution is welcome:

  1. Who maintains this library? To be clear, I'm not expecting anyone specifically to be in such a position, I understand sometimes open source libraries are passion projects that became too successful.
  2. Is there something in particular I can do to make this contribution easier to be acceptable for maintainers to take over in the future? Additional documentation? Splitting it into smaller chunks that are easier to review and digest? I'm happy to do either, or both, and/or take suggestions for further improvements.

I hope these questions don't come across the wrong way, all I hope is for this contribution to be genuinely helpful. 🙂 All I really want is for delta to highlight my Java code using the most recent syntax changes. 😄

@jrappen

jrappen commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

the SublimeHQ devs and most of the more active 3rd-party plugin devs are on Discord:

https://discord.gg/D43Pecu

in case you had questions with regard to the currently-not-yet-implemented stuff.

@jrappen

jrappen commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

Any plans to address #271?

@stefanobaghino

Copy link
Copy Markdown
Contributor Author

Any plans to address #271?

Not as part of this PR, but to the best of my understanding that is unrelated, right?

@jrappen

jrappen commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

This PR does not close #323, it only partially addresses it.

Multiple inheritance might be rare, but I know for certain, I've got an open PR to the default packages for JSON where I use a list value for extends. I haven't double checked, but there might be others in defaults. The thing about list values is (1) all entries need to extend the same base and (2) order matters, where changes by later entries override changes by prior entries to the common base.

@michaelblyons

Copy link
Copy Markdown
Contributor

Would it be nice to have multiple inheritance? Yes. Should it block this? I say no. And the same for branch support.

A huge percentage of extended syntaxes are just tweaks to a base language to fix interpolations when it's embedded. Holding that up for TSX and stale PRs for C and JSON seems like a bad trade-off. If the maintainers want the PR split or API stable, that's one thing. But dropping new functionality requirements is quite another.

I wish I had the familiarity with syntect to review the code itself, but I don't.

@stefanobaghino

Copy link
Copy Markdown
Contributor Author

This PR does not close #323, it only partially addresses it.

Fair point, I reworded the PR description.

I'd appreciate the maintainers letting me know whether they'd rather merge as is, apply any change they see fit, split into smaller PRs, or get #323 fully implemented. Happy to act on any guidance.

@jrappen

jrappen commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

PR looks good from here.

I (or any maintainer) can mark whatever is partially resolved through this PR in the list at the top of #323 as "done".

@keith-hall

keith-hall commented Mar 9, 2026

Copy link
Copy Markdown
Collaborator

I think it is fine without splitting into smaller PRs. I suspect it should be possible to de-duplicate some of the code, but as syntect hasn't seen much love recently, I think it is worth merging as it is. We can always iterate on it later. (Gatekeeping at this point seems like it would detract from the goal and demotivate contributors.)

I was hoping to bump the Packages submodule to see how the syntax tests perform with the changes, but until we get branch point support, the failures would be too noisy. I unfortunately don't currently have time to test manually with syntaxes using v2 and inheritance etc.

In either case, this PR doesn't break any existing functionality and it has unit tests, so I am inclined to merge.

Edit: forgot to say, I'm pretty sure the public API changes are necessary and make sense 👍

@keith-hall keith-hall merged commit b8679bc into trishume:master Mar 9, 2026
5 checks passed
@stefanobaghino

Copy link
Copy Markdown
Contributor Author

Continuing the work in #612.

@jrappen

jrappen commented Mar 11, 2026

Copy link
Copy Markdown
Contributor
image

CI on master fails as a result of this PR.

@stefanobaghino

Copy link
Copy Markdown
Contributor Author

CI on master fails as a result of this PR.

I saw that when pushing my changes for the follow-up with #612. Not sure of whether the problem is caused strictly by what has been as part of this PR, since this check passed on CI to the best of my understanding. In any case, #612 should take care of it, specifically a2d1823.

@stefanobaghino

Copy link
Copy Markdown
Contributor Author

After having a second look, I just realize it was indeed in this PR that that check started failing. Sorry for not fixing that before, if I had noticed that I would have pushed a patch. As mentioned though, I ended up fixing the issue in #612 to make sure I had a green branch. 🙂

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.

6 participants