tomtom / tcomment_vim

An extensible & universal comment vim-plugin that also handles embedded filetypes

Home Page:http://www.vim.org/scripts/script.php?script_id=1173

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

neovim + treesitter + vue.js + tcomment_vim not working in JS section

eduardoarandah opened this issue · comments

Comments aren't working fine with treesitter

I'm not sure if this is an issue to be reported here or in https://github.com/ikatyang/tree-sitter-vue
so I'll post in both sites

neovim + treesitter commenting the same in html, js

image

Debug info:

:echo tcomment#debug#CollectInfo()

on template section:

TCOMMENT: &ft = vue => vue
TCOMMENT: stx =  => 
TCOMMENT: ct  = {'_args': {'beg': 98, 'fallbackFiletype': '', 'end': 98, 'filetype': 'vue', 'comment_mode': ''}, 'commentstring': '/*%s*/', 'mode': '', 'whitespace': 'both'}

on js section:


TCOMMENT: &ft = vue => vue
TCOMMENT: stx =  => 
TCOMMENT: ct  = {'_args': {'beg': 115, 'fallbackFiletype': '', 'end': 115, 'filetype': 'vue', 'comment_mode': ''}, 'commentstring': '/*%s*/', 'mode': '', 'whitespace': 'both'}

vim + polyglot works fine!

image

on template part:

TCOMMENT: &ft = vue => vue
TCOMMENT: stx = htmlTag => htmlTag
TCOMMENT: ct  = {'_args': {'beg': 55, 'fallbackFiletype': '', 'end': 55, 'filetype': 'vue', 'comment_mode': ''}, 'commentstring': '<!-- %s -->', 'replacements': {'&': '&#38;', '-': '&#45;'}, 'mode': '', 'filetype': 'html'}

on js part:

TCOMMENT: &ft = vue => vue
TCOMMENT: stx = jsObjectSeparator => javascriptObjectSeparator
TCOMMENT: ct  = {'rxmid': '', 'rxend': '', '_args': {'beg': 76, 'fallbackFiletype': '', 'end': 76, 'filetype': 'vue', 'comment_mode': ''}, 'commentstring': '// %s', 'commentstring_rx': '\%%(// %s\|/* %s */\)', 'mode': '', 'filetype': 'javascript', 'replacements': {'*/': {'subst': '|)}>#', 'guard_rx': '^\s*/\?\*'}, '/*': {'subst': '#<{(|', 'guard_rx': '^\s*/\?\*'}}, 'rxbeg': '\*\+'}

If you're here with same issue, you can use non-treesitter syntax with:

if (has("nvim"))
  " Treesitter
  Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}  " We recommend updating the parsers on update
endif

" also install Vue syntax
Plug 'posva/vim-vue', { 'for': ['vue' ] }

and later, add disable to vue

" treesitter enable
if (has("nvim"))
lua <<EOF
require'nvim-treesitter.configs'.setup {
  ensure_installed ={ "javascript", "json", "css", .... here others....  }, -- one of "all", "maintained" (parsers with maintainers), or a list of languages
  highlight = {
    enable = true,
    disable = { "vue" }
  },
  indent = {
    enable = false
  },
}
EOF
endif

Not sure that disabling treesitter should be an acceptable solution here.

Not sure that disabling treesitter should be an acceptable solution here.

@cloggier Agree. It's just a temporary workaround.
In debug info there's some clues on what might be happening: 'posva/vim-vue' reports filetype: html and javascript.
treesitter reports "vue" everywhere

I'd be glad to help but I've no idea how treesitter-vue works

treesitter-vue does very little actually, it only injects other languages for each block (js, css, html). It shouldn't be over complicated to retrieve what parser/grammar is used in a block under cursor and set comment string accordingly.

And @JoosepAlviste did just that in amazing https://github.com/JoosepAlviste/nvim-ts-context-commentstring, which works with any commentstringbased commenting plugin.

@cloggier thanks for the tip!

Installed that plugin and is setting up comment string correctly https://github.com/JoosepAlviste/nvim-ts-context-commentstring

However, tcomment is not commenting based on that info.

(Moved to https://github.com/tpope/vim-commentary/ and it works fine)

Cursor in JS part:

image

Cursor in HTML part:

image

tcomment also uses commentstring if no special comment definition is defined. If tcomment doesn't use commentstring, then something in autoload/tcomment/types/default.vim or maybe syntax based syntax definition interferes with it.

I don't do JS/JSX/etc myself so I have to rely on pull requests from users. My main problem with these bug reports is that they are selfcontradictory and inconsistent to some extent -- at least that what it appears to me.

I a simpler comment plugin suffices for you needs please use that one.

If you want to continue using tcomment, please tell me exactly what kind of behaviour you observe under exacly which conditions and what behaviour you expect. Just telling me "Comments aren't working fine with treesitter" isn't exactly useful because I have no idea what treesitter is and I don't have the time to look it up.

@tomtom neovim 0.5 (not released yet, stable is 0.4.4) is promoting treesitter as an alternative to vim regex-based syntax.

Treesitter is a parsing library (builds a syntax tree) and is supposed to have advantages over regex.

Is there a list of variables that I can dump to make this issue productive? this might be an issue with the other plugin (treesitter) not this one, of course!

Links:

https://github.com/nvim-treesitter/nvim-treesitter

https://github.com/tree-sitter/tree-sitter

I've little experience with this, if you want to play with treesitter parsing, you can do this:

  1. install neovim nightly https://gist.github.com/eduardoarandah/40e18928363d0462b30aa18ffe2e1fbe

  2. In your .vimrc add treesitter and the playground. Example with VimPlug:

if (has("nvim"))
  " Treesitter
  Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}  " We recommend updating the parsers on update
  Plug 'nvim-treesitter/playground' 
endif

  1. After call plug#end() configure treesitter, example:
" treesitter enable
if (has("nvim"))
lua <<EOF
require'nvim-treesitter.configs'.setup {
  ensure_installed ={ "javascript", "json", "css", "php", "html", "python", "bash", "regex", "ruby", "yaml", "jsonc", "tsx", "lua", "vue" }, -- one of "all", "maintained" (parsers with maintainers), or a list of languages
  highlight = {
    enable = true,
    disable = { "php" },  -- list of language that will be disabled
  },
  indent = {
    enable = false
  },
}
EOF
endif

  1. Now you can see treesitter parsing with TSPlayground check video:
Grabacion.de.pantalla.2021-03-29.a.la.s.14.15.02.mov.mp4

I don't know much more about how to query the parser to get the exact syntax info.
This plugin code might be helpful: https://github.com/JoosepAlviste/nvim-ts-context-commentstring

commented

I'm having the same issue too (pretty much same setup: nvim + treesitter).

The issue is just with vuejs files (which embed multiple languages into different blocks). No matter where I comment, this plugin always uses <-- %s --> to comment -- which is not valid in javascript blocks.

In other words, it seems that the plugin won't properly detect which language is the one under the cursor.

I hacked around this for a while (this was challenging, but I'm happy with the solution I've found), and managed to write this snippet to determine the language at the cursor's current position. It works with just one level of nested languages, which I think is a reasonable limitation:

local function print_language_at_cursor()
  local parsers = require("nvim-treesitter.parsers")

  local root = parsers.get_parser()
  local cursor = vim.api.nvim_win_get_cursor(0)

  local range = { cursor[1], cursor[2], cursor[1], cursor[2] }
  local node_lang = root

  -- TODO: Should be able to use `root:for_each_tree()` with a callback to get
  -- the last leaf language that contains this range.
  for _, child in pairs(root:children()) do
    if child:contains(range) then
      node_lang = child
    end
  end

  print(vim.inspect(node_lang:lang()))
end
-- Mapping I used to test this:
vim.keymap.set("n", "<Leader>I", print_language_at_cursor)

I tested this with vue files, and it recognises typescript and css just fine. The HTML portion is recognised as vue, but that's kind find, since both vue and html use the same comment format (this is also the correct language, since them template portion of vue files has special syntax that's not strictly HTML).

commented

Oh, this is actually pretty close to what Comment.nvim does, so I think I'll just use that (it seems like a better fit for neovim+treesitter) never mind, it has all kind of quirky bugs.

Thanks for this plugin; it's served me well many many years! 🍻

commented

So I guess that including a bunch of lua code inside this plugin is too out-of-scope, and explicit tree-sitter support might be too invasive.

As a less invasive approach, I wonder if a new setting could be added (something like tcomment#commentstringFunc) which is a function that one can provide and returns the commentstring that should be used.

So basically, if this is set try and use it to determine commentstring, otherwise, use commentstring normally.

The key details her is that since this is a function, it can return a new value for commentstring depending on the current cursor position.

Thoughts?

commented

Yup, I noticed that some plugins do that, but it seems inefficient, there's a lot of parsing and work getting done on each CursorHold. I'd rather the work be done only when needed (e.g.: when actually commenting a line).

Thanks for the change, I'll figure out the rest and leave the result for reference in case anyone else is interested.