Skip to content

feat(ALL): check children treesitter languages after parents#2407

Open
TheLeoP wants to merge 2 commits into
nvim-mini:mainfrom
TheLeoP:poc
Open

feat(ALL): check children treesitter languages after parents#2407
TheLeoP wants to merge 2 commits into
nvim-mini:mainfrom
TheLeoP:poc

Conversation

@TheLeoP
Copy link
Copy Markdown
Member

@TheLeoP TheLeoP commented May 6, 2026

This PR is only a proof of concept of what a fix for #2397 would look like.

Thoughts:

  • The easiest way to test this could be to create queries for injecting Lua into some Lua strings
  • mini.surround doesn't seem to need this change since the cursor always needs to already be on top of the region with a treesitter injection. So, it will be parsed even before this PR when going up the tree.

@TheLeoP TheLeoP marked this pull request as draft May 6, 2026 03:21
@echasnovski
Copy link
Copy Markdown
Member

Thanks for the PR!

  • The easiest way to test this could be to create queries for injecting Lua into some Lua strings

There are already tests for injected languages (this one for 'mini.ai'). They use built-in Lua -> Vimscript injections.

I think tests for this could use even Lua -> Vimscript -> Lua injections. Like here:

vim.cmd([[
  set cursorline
  lua local a = 1
]])
  • mini.surround doesn't seem to need this change since the cursor always needs to already be on top of the region with a treesitter injection. So, it will be parsed even before this PR when going up the tree.

There is less overall complexity if tree-sitter related (and even some other) code in 'mini.ai' and 'mini.surround' is kept as aligned as possible.


As per this PR, please reduce code duplication. Both parents and children are meant to be processed exactly the same, right? In both 'mini.ai' and 'mini.surround' this processing is rather complicated, so even with two times duplication it adds a lot.

@TheLeoP TheLeoP marked this pull request as ready for review May 20, 2026 14:48
@TheLeoP
Copy link
Copy Markdown
Member Author

TheLeoP commented May 20, 2026

There are already tests for injected languages

I forgot about that test and I wrote it myself :p. Thanks for the pointer!

Using Lua -> Vimscript -> Lua injections was indeed easier to avoid adding new queries.

code duplication and mini.ai/mini.surround alignment on treesitter implementation

I think I improved the alignment/code duplication between mini.ai and mini.surround, but I don't usually write small functions. So, let me know if you have any more feedback.

Copy link
Copy Markdown
Member

@echasnovski echasnovski left a comment

Choose a reason for hiding this comment

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

This indeed looks like a well structured change and improvement!

Apart from variable naming nit picks, could you please also:

  • Add a concise note in each function's help about how it searches for the match.
  • Add a 'mini.surround' test.
  • Split into two commits for for 'mini.ai' and 'mini.surround'. Each with a concise description in Details: list about why this is necessary. With also Resolve #2397 line afterwards.

Comment thread lua/mini/ai.lua Outdated
Comment thread lua/mini/surround.lua Outdated
Comment thread lua/mini/surround.lua Outdated
TheLeoP added 2 commits May 21, 2026 21:46
Details:
- Users may expect next/previous textobjects in injected languages
  located before/after the cursor to work, even if they are not part of
  the LanguageTree under cursor or its ancestors. This is specially
  important for languages that rely heavily on injections like markdown
  (injecting markdown_inline).

- So, we fallback to searching in direct injected children languages if
  no textobject is found for current LanguageTree or its ancestors.

Resolve nvim-mini#2397
Details:
- Users may expect next/previous textobjects in injected languages
  located before/after the cursor to work, even if they are not part of
  the LanguageTree under cursor or its ancestors. This is specially
  important for languages that rely heavily on injections like markdown
  (injecting markdown_inline).

- So, we fallback to searching in direct injected children languages if
  no textobject is found for current LanguageTree or its ancestors.
@TheLeoP
Copy link
Copy Markdown
Member Author

TheLeoP commented May 22, 2026

Add a concise note in each function's help about how it searches for the match.

Are you referring to H.get_matched_ranges_builtin? Or to H.get_nodes_range_builtin and H.get_match_ranges_builtin?

Add a concise note in each function's help about how it searches for the match.

This is about adding a comment to the private helper functions, right? Or is it about modifying the comments used to generate the documentation for the user-facing MiniAi.gen_spec.treesitter() and MiniSurround.gen_spec.input.treesitter()?

Add a 'mini.surround' test.

I don't think a test for this change would be possible inside of mini.surround. The cursor needs to always be inside of a surround, which means that the surround would be either on the same LanguageTree or in a parent one. I can't think of a scenario where the surrounding would be on a child language tree.

Comment thread lua/mini/surround.lua
local res = {}
for i, outer in ipairs(outer_ranges) do
res[i] = { outer = outer, inner = H.get_biggest_nested_range(inner_ranges, outer) }
for i, outer in ipairs(outer) do
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

outer is redefined here.

Comment thread tests/test_ai.lua
local lines = {
'vim.cmd([[',
'set cursorline',
'lua local a = function () end',
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
'lua local a = function () end',
'lua local a = function() return true end',

This should make it more robust: no space between function and () is usual (unless it is intentional?) and non-empty body (as empty function might be problematic).

@echasnovski
Copy link
Copy Markdown
Member

echasnovski commented May 22, 2026

This is about adding a comment to the private helper functions, right? Or is it about modifying the comments used to generate the documentation for the user-facing MiniAi.gen_spec.treesitter() and MiniSurround.gen_spec.input.treesitter()?

Sorry, should have been more clear. Mentioning function's help in my mind means the text that is shown when doing :h <function-name>. For commenting local functions it is usually "function's comment" or "function's annotation".

And the explanation is very much needed because I just now (possibly) misremembered how this is supposed to work in the 'mini.ai' test. Is it intended and/or reasonable that the search is only done for "one level" children? In particular with this Lua code with cursor at the top, executing vanF doesn't work because the target is two levels deep (Lua->Vimscript->Lua):

vim.cmd([[
set cursorline
lua local a = function() return true end
]])

I think I would have expected all children to be used here, no matter however deep. Do you think it is reasonable?

Add a 'mini.surround' test.

I don't think a test for this change would be possible inside of mini.surround. The cursor needs to always be inside of a surround, which means that the surround would be either on the same LanguageTree or in a parent one. I can't think of a scenario where the surrounding would be on a child language tree.

The 'mini.ai' and 'mini.surround' are very aligned in how they find their targets (textobjects and surroundings). In this particular case, using next variant of surrounding action (like sfn to "find next surrounding") will work. Like this:

T['gen_spec']['input']['treesitter()']['works with direct injected child language'] = function()
  local lines = {
    'vim.cmd([[',
    'set cursorline',
    'lua local a = function () end',
    ']])',
  }
  validate_find(lines, { 2, 0 }, { { 3, 14 } }, type_keys, 'sfn', 'F')
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants