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

feat: relay on languagetree commentstring as much as possible #86

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

mortezadadgar
Copy link
Contributor

@mortezadadgar mortezadadgar commented Nov 20, 2023

The idea is taken from mini.comment but it's a little simpler as i don't why languagetree children need to be traversed as well:
https://github.com/echasnovski/mini.comment/blob/main/lua/mini/comment.lua#L359

after this change merged i think many languages config can be removed as they're obtained from languagetree there are exceptions like html and jsx that need to stayed for now.

@mortezadadgar
Copy link
Contributor Author

mortezadadgar commented Nov 20, 2023

moved the logic to a separate function and removed preconfigured commentstrings not sure rescript, twing and graphql need to be removed as well
the code is mostly is taken from mini.comment i will see if i can merge it into check_node() but it seems to be so complicated

@JoosepAlviste
Copy link
Owner

This looks like a great idea! I'd bring out a couple things for now (as this PR is still a draft):

  1. The filetype commentstring checking logic probably doesn't need to be inside check_node as there we're looping through all the nodes inside a language tree. The filetype commentstring detection is relevant for language trees rather than nodes. I'm not sure what the best place to put the logic would be, though.
  2. One problem with the current location is that if the cursor is in a css block inside tsx, for example, then get_node_at_cursor_start_of_line would return the tsx language tree, rather than the css one, which would get the commentstring from tsx and wouldn't trigger your logic. A visual example:
const MyStyledComponent = styled`
  |color: red;
  ^ cursor is here
`

where get_node_at_cursor_start_of_line would check the current node (css), see that it's not in the languages config, check it's parent (tsx), see that it IS in the config, and use that for the next calculations. Hopefully that made sense 😅

  1. Removing the configs for languages with multiline comments (e.g., lua) would mean that the advanced commenting integration with Comment.nvim wouldn't be able to do multiline comments. I would still keep those in the configuration.

@mortezadadgar
Copy link
Contributor Author

thanks for suggestions I will take a look but i think we should take away removing commentstring from config for now it seems to be tricky

@echasnovski
Copy link
Contributor

The idea is taken from mini.comment but it's a little simpler as i don't why languagetree children need to be traversed as well: https://github.com/echasnovski/mini.comment/blob/main/lua/mini/comment.lua#L359

The way it works in 'mini.comment' is by traversing all possible trees in the buffer but checking only those that contain reference position. It also makes sure that the "most specific" child provides the 'commentstring' (hence the check for strictly increased level of nesting). I think that in theory there can be complex situations in which a proper source for 'commentstring' is chosen. For example, if there is a language tree A (providing its own 'commentstring') with children AA and AB (also with own values), and AA has also a children AAA (with fifth value). Which value of 'commentstring' should be chosen? 'mini.comment' goes for the language tree with highest nesting (first among those ones, to be precise).

return M.check_node(node, language_config, key)
end

function M.check_ts_node(language_tree)
local cs = vim.filetype.get_option(language_tree:lang(), 'commentstring')
Copy link
Contributor

Choose a reason for hiding this comment

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

Language of a tree doesn't always equal to the filetype it is usually used. See vim.treesitter.language.get_filetypes() (beware that it is added only in Neovim 0.9.

Copy link
Contributor Author

@mortezadadgar mortezadadgar Nov 21, 2023

Choose a reason for hiding this comment

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

yeah what i'm doing already is to obtain the language under the cursor and skip the comment type and seems to work fine(missed that part in new implementation)

@mortezadadgar
Copy link
Contributor Author

@JoosepAlviste this pr is almost done i just don't which languages can be removed from the config without breaking anything
one idea is to leave it as it's but that would make this pr useless

Copy link
Owner

@JoosepAlviste JoosepAlviste left a comment

Choose a reason for hiding this comment

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

This looks pretty good already! I haven't tested it too much yet, but had a few comments.

One thing to add is the docs, we should say that setting the commentstring in an ftplugin (or FileType autocmd) should be the first option to consider as that would work with the general Vim ecosystem much better. For fancier behavior, users can configure this plugin directly (with treesitter node specific commentstrings and separate multiline commentstrings from single line ones).

@@ -51,10 +51,8 @@ end
function M.calculate_commentstring(args)
args = args or {}
local key = args.key or '__default'
local location = args.location or nil
Copy link
Owner

Choose a reason for hiding this comment

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

We will need to keep allowing to pass in a custom location as this is required for the Comment.nvim integration. The commentstring shouldn't always be calculated from the cursor line's start (e.g., when using motions like gciw)

return M.check_node(node, language_config, key)
end

function M.check_ts_node(language_tree)
Copy link
Owner

Choose a reason for hiding this comment

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

The name for this isn't very indicative of what the function does, I'd rename it to something like "get commentstring from language tree".

Also, it would be nice to have type hints for the parameter and return type.

return M.check_node(node, language_config, key)
end

function M.check_ts_node(language_tree)
local cs = vim.filetype.get_option(language_tree:lang(), 'commentstring')
Copy link
Owner

Choose a reason for hiding this comment

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

Even if this variable is used in a very small scope, I think that it still makes sense to avoid abbreviations in variable names. "cs" makes me think of Counter Strike 😄

Same thing above

Comment on lines -62 to -84
astro = '<!-- %s -->',
c = { __default = '// %s', __multiline = '/* %s */' },
css = '/* %s */',
glimmer = '{{! %s }}',
graphql = '# %s',
handlebars = '{{! %s }}',
html = '<!-- %s -->',
lua = { __default = '-- %s', __multiline = '--[[ %s ]]' },
nix = { __default = '# %s', __multiline = '/* %s */' },
php = { __default = '// %s', __multiline = '/* %s */' },
python = { __default = '# %s', __multiline = '""" %s """' },
rescript = { __default = '// %s', __multiline = '/* %s */' },
scss = { __default = '// %s', __multiline = '/* %s */' },
sh = '# %s',
bash = '# %s',
solidity = { __default = '// %s', __multiline = '/* %s */' },
sql = '-- %s',
svelte = '<!-- %s -->',
twig = '{# %s #}',
typescript = { __default = '// %s', __multiline = '/* %s */' },
vim = '" %s',
vue = '<!-- %s -->',
zsh = '# %s',
Copy link
Owner

Choose a reason for hiding this comment

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

I'd keep the language configs that:

  • Do not have a default in Neovim core
  • Have an extra multiline comment style config

as removing those would result in breaking changes and would require people to change their configs after updating this plugin. I would very much like to avoid any breaking changes, we could group those together with other breaking changes in the future (e.g., removing the config option for good).

Here are the language configs I would keep:

  • astro - no default commentstring
  • c - has a multilline config
  • grimmer - no default
  • graphql - no default
  • handlebars - no default
  • lua - multiline config
  • nix - multiline config
  • php - multiline config
  • python - multiline config
  • rescript - multiline config
  • scss - multiline config
  • solidity - multiline config
  • sql - no default
  • svelte - no default
  • twig - no default
  • typescript - multiline config
  • vue - no default

The others can be deleted, I think.

This at least makes it so that new languages with a single commenting style would work out of the box, and wouldn't need to be configured in this plugin.

We can figure out how to get rid of the multiline comment configs in the future (maybe using :h comments somehow?).

if ltree:contains(range) and vim.tbl_contains(only_languages, ltree:lang()) then
-- always exclude the comment language as it's returning invalid
-- commentstring
if ltree:contains(range) and ltree:lang() ~= 'comment' then
Copy link
Owner

Choose a reason for hiding this comment

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

There's also jsdoc, phpdoc, and probably other parsers as well which don't map directly to a filetype. Do we need to handle those too?

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.

3 participants