neovim icon indicating copy to clipboard operation
neovim copied to clipboard

feat(comment): allow commentstring to be determined from node metadata

Open ribru17 opened this issue 1 year ago • 15 comments

Problem: Some weird languages have different comment syntax depending on the location in the code, and we do not have a way to determine the correct commentstring for these special cases.

Solution: Allow queries to specify commentstring values in metadata, allowing users/nvim-treesitter to provide a better commenting experience without hugely increasing the scope of the code in core.

Fixes #28830

ribru17 avatar Sep 24 '24 19:09 ribru17

Where should this be documented?

justinmk avatar Sep 24 '24 23:09 justinmk

I was wondering the same. Maybe in treesitter.txt in a similar section under *treesitter-highlight-priority*? There are a few sections in there related to special metadata stuff

ribru17 avatar Sep 24 '24 23:09 ribru17

I don't think this should be specific to commentstring, at least at the underlying function level (it's ok at the metadata level for now, unless we can think of a way to generalize this too). Can't this support any vim.filetype.get_option?

clason avatar Sep 25 '24 06:09 clason

Sorry, I don't really understand what this would look like. Are you just saying to modify the helper function the be able to extract any option (not just commentstring)? Also when would it be helpful/make sense to set a different option in the metadata?

ribru17 avatar Sep 25 '24 14:09 ribru17

Hypothetically, what other options could this potentially be useful for? Are there any options like commentstring where the option may be different line by line?

Some ideas:

  • expandtab in Makefiles? Recipe lines should have hard tabs, whereas variable logic ~should~ can be indented with spaces.
  • 'breakat' (though this is a global option)
  • 'equalprg'
  • 'formatprj', 'formatexpr'
  • 'indentexpr'
  • 'iskeyword'
  • 'filetype'?

Though I'd imagine in practice most of these would be handled via injections instead of this.

lewis6991 avatar Sep 25 '24 15:09 lewis6991

@ribru17, is traversing the output of vim.treesitter.get_captures_at_pos() backwards enough to guarantee that the "most narrow" capture is used? Because skipping manual traversing for this step is a big win. Could you, please, add a test for how it works with separate "conflicting" captures (because right now it looks like traverse forward would also pass the tests).

And if the current implementation is good from tree-sitter POV, it can be visibly simplified. I'll test and post suggestions tomorrow.

echasnovski avatar Sep 25 '24 16:09 echasnovski

@ribru17, is traversing the output of vim.treesitter.get_captures_at_pos() backwards enough to guarantee that the "most narrow" capture is used?

I am 99% sure it is, though I don't know if we have a test for get_captures_at_pos() ensuring this. That said I've added a test for the inner metadata logic, so I think all functionality is tested now

ribru17 avatar Sep 25 '24 16:09 ribru17

As for the generic helper function, it sorta depends on another PR I will put out soon (which depends on #30514, due to a small conflict)

ribru17 avatar Sep 25 '24 18:09 ribru17

I don't think this should be specific to commentstring, at least at the underlying function level (it's ok at the metadata level for now, unless we can think of a way to generalize this too). Can't this support any vim.filetype.get_option?

@clason this PR may have changed since your comment, but is this still an open question / blocker? Does the "generalize _get_urls" TODO capture your suggestion?

justinmk avatar Oct 09 '24 12:10 justinmk

Hypothetically, what other options could this potentially be useful for? Are there any options like commentstring where the option may be different line by line

@lewis6991 are you suggesting something like:

((list) @_list (#set! @_list option.foo "..."))

or something else?

justinmk avatar Oct 09 '24 12:10 justinmk

Yeah something like that. Clason suggested making this more generic, so I was just going through the thought process of any hypothetical benefits if we were to do that. The fact this is done using the #set! directive means we don't need any upstream support or community alignment to implement this.

lewis6991 avatar Oct 09 '24 12:10 lewis6991

Yes, I think it should be generic on the level of the queries/metadata, but I have been convinced that it makes sense for the actual feature/Lua implementation to be specific to commentstring.

clason avatar Oct 09 '24 12:10 clason

Idea: Use bo.foo or wo.foo for symmetry with the Lua API (aids discoverability and reinforces domain knowledge)?

clason avatar Oct 09 '24 13:10 clason

Would this look like using wo.foo as a table key or creating a wo table within metadata, then using foo for its key?

ribru17 avatar Oct 09 '24 13:10 ribru17

I didn't envision any table handling (yet; that can come later under the hood if that makes things easier); I was thinking merely as a namespace (alternative to options.commentstring -> bo.commentstring).

clason avatar Oct 09 '24 13:10 clason

Is it possible to add this to the 0.11 milestone?

ribru17 avatar Nov 24 '24 17:11 ribru17

If it's done before 0.11 is released (which doesn't look imminent), it'll be included. I don't think it needs to block the release (which is what the milestone is for).

clason avatar Nov 24 '24 19:11 clason

If it's done before 0.11 is released (which doesn't look imminent), it'll be included. I don't think it needs to block the release (which is what the milestone is for).

Is there anything left to do here?

echasnovski avatar Nov 24 '24 19:11 echasnovski

Hypothetically, what other options could this potentially be useful for? Are there any options like commentstring where the option may be different line by line

Could this approach be used to tackle #32129?

wurli avatar Mar 03 '25 10:03 wurli

No. What's needed is to rewrite that functionality from scratch based on treesitter indentation. (But not node-level metadata.)

clason avatar Mar 03 '25 10:03 clason