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

Extend functionality to any buffer with injected language blocks? #3

Closed
bew opened this issue Aug 23, 2022 · 13 comments · Fixed by #4
Closed

Extend functionality to any buffer with injected language blocks? #3

bew opened this issue Aug 23, 2022 · 13 comments · Fixed by #4

Comments

@bew
Copy link

bew commented Aug 23, 2022

Hello!

This plugin looks nice & simple 👍

Have you considered making it work in all files (not just markdown), to support any language block injected in a base language using treesitter ?

@bew bew changed the title Extend functionality to any injected language? Extend functionality to buffer with injected language blocks? Aug 23, 2022
@bew bew changed the title Extend functionality to buffer with injected language blocks? Extend functionality to any buffer with injected language blocks? Aug 23, 2022
@AckslD
Copy link
Owner

AckslD commented Aug 23, 2022

Hi @bew! I think this would be great indeed. What I don't know is how uniform the structure for injected languages are. For example at the moment we make use of eg the following structure:

fenced_code_block [2, 0] - [5, 0]
  fenced_code_block_delimiter [2, 0] - [2, 3]
  info_string [2, 3] - [2, 9]
    language [2, 3] - [2, 9]
  block_continuation [3, 0] - [3, 0]
  code_fence_content [3, 0] - [4, 0]
    ...
  fenced_code_block_delimiter [4, 0] - [4, 3]

to both find what the injected language is and where the content lives in the buffer. Maybe there are other ways to retrieve this without querying the tree directly. If so, I'd be interested in knowing this :)

@bew
Copy link
Author

bew commented Aug 23, 2022

With a quick look at the documentation around treesitter, I've found the functions around LanguageTrees:
https://neovim.io/doc/user/treesitter.html#treesitter-languagetree

I didn't test anything, but it looks like you might not even need to navigate the parsed tree yourself, matching individual nodes, but instead you should be able to access directly the current injected language, where it starts/ends, etc...

Edit: Looking a bit more at neovim's & nvim-treesitter's source code, the parser you get from parsers.get_parser(0) is actually a LanguageTree object \o/

@AckslD
Copy link
Owner

AckslD commented Aug 23, 2022

This looks great and might indeed be a better way and more powerful. Thanks for sharing! I'll try to take a look at this 👍

@AckslD
Copy link
Owner

AckslD commented Aug 24, 2022

@bew I started trying this out in #4, feel free to try it if it works for you. It does seem to work pretty well I think.

One small issue is that if you for example have an empty codeblock in markdown, eg:

\```python
\```

then there is in fact no injected language tree there and you can't selected. Also for a similar reason you currently only be able to open the window when you're on the start (back-ticks) of the code-block but not the last line with back-ticks.

@bew
Copy link
Author

bew commented Aug 25, 2022

Hmm that's too bad..
Does it work if you add an empty line in code block and trigger the plugin there?

As far for trying, you'll have to wait a bit, as I'm in the process of migrating my conf to Lua, with all the new things like treesitter.
I don't have treesitter setup yet, but I should be able to try in a few days (:

@ziontee113
Copy link

HI @AckslD , what do you think about the option of letting the user to use their own Treesittter queries?

@AckslD
Copy link
Owner

AckslD commented Sep 10, 2022

That might be the way to go indeed @ziontee113, ideally this would work automatically for any language injection but doesn't seem feasible since "empty" languages are not injected (which I guess makes sense).

Do you have some language with a query in mind that I could try out as an example?

@ziontee113
Copy link

You can take a look at this screenshot

Screenshot from 2022-09-10 19-37-54

We're in a lua file, and I can inject query (or scheme) into that string query_template [[ ]]. All I need is in my nvim config: after/queries/lua/injections.lua:

(
 ("string_content") @query
 (#match? @query ";; query")
)

Only strings that has the ;; query in it will be highlighted.

@AckslD
Copy link
Owner

AckslD commented Sep 10, 2022

Thanks!

Actually, this got me thinking, maybe we can also just extend eg the current markdown query to also match empty code-blocks. So I tried changing current injections.scm for markdown to something like:

;; matches non-empty code-blocks
(fenced_code_block
  (info_string
    (language) @language)
  (#not-match? @language "elm")
  (code_fence_content) @content (#exclude_children! @content))

;; matches empty code-blocks
(fenced_code_block
  (info_string
    (language) @language)
  (#not-match? @language "elm")
  (block_continuation) @content
  .
  (fenced_code_block_delimiter))

This seems to indeed work. So I updated #4 to instead find matches of language injections queries. Feel free to try it if it works for you.

I also tried to add the second query in after/queries/markdown/injections.scm but that did not work for some reason, not sure why yet.

Note that femaco currently assumes that whatever surrounds the content of the injection is on separate lines. One could maybe change that but not sure it's useful and would then anyway be a separate feature.

Edit: turns out I just forgot ;; extends in the after query. So #4 should now work out of the box without editing any queries.

@AckslD
Copy link
Owner

AckslD commented Sep 10, 2022

One more thing I just realised is that is currently only works for injections with matches @language and @content. If I'm not mistaken, injection queries can also be a single match where the name of the match is the language. This is easy to fix though

Edit: fixed by #6

@AckslD
Copy link
Owner

AckslD commented Sep 11, 2022

#8 now enables also inline injections

for example see the following example where lua is temporarily injected into python strings:

femaco_inline_injections.mp4

@ziontee113
Copy link

This is awesome.

@AckslD
Copy link
Owner

AckslD commented Sep 12, 2022

Will just need to wait for nvim-treesitter/nvim-treesitter#3486 :)

@AckslD AckslD closed this as completed in #4 Sep 12, 2022
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 a pull request may close this issue.

3 participants