Skip to content
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

Is it possible to get matchup to work with treesitter injections? #352

Open
pejrich opened this issue Jul 2, 2024 · 3 comments
Open

Is it possible to get matchup to work with treesitter injections? #352

pejrich opened this issue Jul 2, 2024 · 3 comments

Comments

@pejrich
Copy link

pejrich commented Jul 2, 2024

Is your feature request related to a problem? Please describe.
I love this plugin by the way. But I have a slight edge case in Elixir. Elixir can have it's html templates in a separate file with a .html.heex extension. Currently vim-matchup works a charm for these files. HTML markup can also be embedded within an Elixir file(this is a somewhat newer thing, but seems to be moving more in this direction). These files have the regular Elixir extension .ex, and HTML is denoted in the file as follows:

def some_elixir_function(assigns) do
  ~H"""
    <div>some html stuff here</div>
  """
end

Everything from the ~H""" to the next """ is HTML, even though the overall file is of filetype elixir.

This is one place where matchup doesn't work for me, but I would love if it did, and wanted to open this to see what it would take. Of course I'm happy to put the work in, but am a little lost on what the right direction is.

From my limited knowledge of Treesitter, it seems to use something called injections to denote a part of a file that is following different syntax rules than the rest of the file.

I notice in the after/queries/* there isn't currently one for Elixir. Would writing one likely fix this issue? If so I'm happy to look into writing one, but wasn't sure if that was A. What was needed and B. If there is something else needed too.

Describe the solution you'd like
Ideally some way to let the plugin be aware of the HTML syntax within the non-HTML file.

Describe alternatives you've considered

Additional context
Again, I'm happy to do the grunt work/write the queries, but just wanted to float it by you to see if it's a lot more work than it's worth, or if it's doable.

Thanks!

@andymass
Copy link
Owner

andymass commented Jul 11, 2024 via email

@pejrich
Copy link
Author

pejrich commented Aug 19, 2024

Hey @andymass I've been playing around to try to get this to work because I miss matchup dearly every time I'm working with HTML embedded into an elixir document.

This is the query i've cobbled together based on looking at other queries, as well as the syntax tree from :InspectTree

; inherits: quote

(component) @scope.tag
(start_component (identifier) @open.tag)
(end_component
  (identifier) @close.tag
  (#offset! @close.tag 0 -1 0 0))

(self_closing_component
  name: (identifier) @open.selftag
  "/>" @close.selftag) @scope.selftag

(tag) @scope.tag
(start_tag (identifier) @open.tag)
(end_tag
  (identifier) @close.tag
  (#offset! @close.tag 0 -1 0 0))

(self_closing_tag
  name: (identifier) @open.selftag
  "/>" @close.selftag) @scope.selftag

Here's a screenshot of some example code + TS inspect:
Screenshot 2024-08-19 at 13 55 52

However with this I get Invalid node type 'component', and Invalid node type 'tag'

I also tried the following query, as well as copying the current HTML query verbatim:

; inherits: quote

[
	(component)
] @scope.tag

(start_component (component_name) @open.tag)
(end_component
  (component_name) @close.tag
  (#offset! @close.tag 0 -1 0 0))

(self_closing_component
  (component_name) @open.selftag
  "/>" @close.selftag) @scope.selftag

[
	(tag)
] @scope.tag

(start_tag (tag_name) @open.tag)
(end_tag
  (tag_name) @close.tag
  (#offset! @close.tag 0 -1 0 0))

(self_closing_tag
  (tag_name) @open.selftag
  "/>" @close.selftag) @scope.selftag

but even those still gave me the "Invalid node type 'tag'" in the Elixir file, even though the InspectTree does seem to show that those names are correct(or at least the equivalent of what the HTML query seems to be matching again in an HTML file.

I'm wondering if you have any pointers about where I might be getting stuck. I'm not sure if there's some filetype stuff that I need to update.

Currently I have a matchup.scm in after/queries/elixir, as well as an elixir_matchup.vim in after/ftplugin which contains the following(basically just the boilerplate they all seemed to have.

" vim match-up - even better matching
"
" Maintainer: Andy Massimino
" Email:      a@normed.space
"

if !exists('g:loaded_matchup') || !exists('b:did_ftplugin')
  finish
endif

" vim: fdm=marker sw=2

On another note, the HTML tag matching works correctly for filetypes of heex, which is elixir embedded in html .html.heex ext. even though there's no queries for heex. I'm trying to get it to work for the opposite(HTML embedded into an elixir file), but strangely even if I set the filetype of the elixir file to heex, matchup doesn't work for the HTML part of that file. I'm honestly pretty unclear on TS and fairly new to vim/neovim in general. Any advice for what might be stopping this from working?

Thanks in advance. I appreciate your time and effort.

@pejrich
Copy link
Author

pejrich commented Aug 19, 2024

As is so often the case, I manage to get it working just minutes after posting for help. Though the way I got it working was not via TS, but rather match_words. I just queried match_words from the heex file which I think is just picking up HTML match_words, and I set let b:match_words = HEEX_MATCH_WORDS in after/ftplugin/elixir.vim, and now matchup highlights and matches correctly!

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

No branches or pull requests

2 participants