Skip to content

feat: Add injection.parent-layer property #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

nik-rev
Copy link
Contributor

@nik-rev nik-rev commented Jun 23, 2025

This was originally brought up in helix-editor/helix#13116 (review)

When injecting markdown into the documentation comments of a language, we want the default code block to be the same as the language itself.

So in this Gleam file, with /// being documentation comments we want the default value of the code block to also have the Gleam language injection, as opposed to usually when there would not be any injection at all if there is no info string:

/// Markdown is injected into these comments
/// ```
/// fn foo()
/// ```
fn foo()

It's possible to do this by introducing a bunch of markdown languages that ; inherits markdown scopes, but instead of doing that this PR allows for a more generic way of doing this.

It introduces the injection.parent-layer property which can be set like this:

(#set! injection.language injection.parent-layer)

This will set the injection language to be whatever is the parent layer of this language, if it's injected.

Using the #any-of? injection.parent-layer predicate you are also able to only allow this for specific languages:

(#set! injection.language injection.parent-layer)
(#any-of? injection.parent-layer "gleam" "zig")

The above will have this injection effect only for the "gleam" and "zig" language. This is necessary as we want to control which languages have this power. Without it, we would see the default injection for code block without info strings in Markdown be the Markdown language itself, which we want to avoid.


To test this in Helix, add this query at the start of the file (before the (info_string (language)) injection) in runtime/queries/markdown/injections.scm:

(fenced_code_block
  (fenced_code_block_delimiter)
  (block_continuation)
  (code_fence_content) @injection.content
  (fenced_code_block_delimiter)
  (#set! injection.language injection.parent-layer)
  (#set! injection.include-unnamed-children)
  (#any-of? injection.parent-layer "gleam"))

Example file for testing:

/// *Inline markdown*
///
/// ````javascript
/// function main() {}
/// ````
///
/// ``````
/// fn main() {}
/// /// *Inline markdown*
/// ///
/// /// `````
/// /// /// *Inline markdown*
/// /// ///
/// /// /// ````javascript
/// /// /// function main() {}
/// /// /// ````
/// /// ///
/// /// /// ````
/// /// /// fn main() {}
/// /// /// /// *Inline markdown*
/// /// /// ///
/// /// /// /// ```
/// /// /// /// fn main() {}
/// /// /// /// ```
/// /// /// fn main() {}
/// /// /// ````
/// /// fn main() {}
/// /// `````
/// fn main() {}
/// ``````
fn main() {}

Note: Immediately this will be useful for Gleam in helix, and also Zig soon. Rust won't make use of this because it requires a custom language (such as injecting the rust language into markdown code block when the (info_string) is edition2024)

@nik-rev nik-rev force-pushed the injection.parent-layer branch 3 times, most recently from 9b32ce9 to d08ca18 Compare June 23, 2025 15:11
@nik-rev nik-rev force-pushed the injection.parent-layer branch from d08ca18 to e87c19a Compare June 23, 2025 15:13
Copy link
Member

@the-mikedavis the-mikedavis left a comment

Choose a reason for hiding this comment

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

For this feature - which I do think we should add - I'm thinking a few things:

  • For naming probably injection.parent-language is clearer. You can think of it as a variable which expands to the language name.
  • Along those lines you should be able to use other predicates like #eq? and #match? on the injection.parent-language variable. This requires refactors to the predicate types. I think we should allow either QueryStrs or captures in these with an enum - the current type seems a bit too strict.

This is something that would be good to align on with Neovim folks. I will drop a message in the tree-sitter-dev matrix channel and tag a few to see what they are thinking - ideally they would implement this feature as well.

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