This plugin will help you enable features that depend on treesitter. It is a complement to nvim-treesitter.
The idea here is to be able to use treesitter by setting a few variables. For example:
" This is vimscript, by the way
let g:ts_enable = {
\ 'parsers': ['json', 'gleam', 'python'],
\ 'auto_install': v:true,
\ 'highlights': v:true,
\ 'folds': v:true,
\ 'indents': v:true,
\}That's it. ts-enable.nvim will take care of the details, and if you want, it can use nvim-treesitter to install any missing treesitter parser on demand.
If you prefer lua, don't worry. You can use vim.g.ts_enable in your configuration. I also added a thing to make it compatible with lazy.nvim's option API.
Use your favorite plugin manager to install ts-enable.nvim and nvim-treesitter.
-
vim-plug
Plug 'VonHeikemen/ts-enable.nvim' Plug 'nvim-treesitter/nvim-treesitter', { 'branch': 'main' }
-
mini.deps
MiniDeps.add('VonHeikemen/ts-enable.nvim') MiniDeps.add({ source = 'nvim-treesitter/nvim-treesitter', checkout = 'main', })
-
vim.pack
vim.pack.add({ 'https://github.com/VonHeikemen/ts-enable.nvim', { src = 'https://github.com/nvim-treesitter/nvim-treesitter', version = 'main', }, })
This plugin should be configured using a vim global variable called ts_enable. You can create that variable anywhere you want. init.lua, init.vim or any random script that Neovim can pick up during the startup process.
Here's example using all the default values as reference.
" These are the default values. Change them as you see fit.
let g:ts_enable = {
\ 'parsers': [],
\ 'auto_install': v:false,
\ 'highlights': v:false,
\ 'folds': v:false,
\ 'indents': v:false,
\ 'parser_settings': {},
\}In a lua file to create a vim global use vim.g. In this case assign a lua table with the settings you want.
-- These are the default values. Change them as you see fit.
vim.g.ts_enable = {
parsers = {},
auto_install = false,
highlights = false,
folds = false,
indents = false,
parser_settings = {},
}-
parsers: list of strings. Treesitter parsers that you want to use. Ifauto_installis enabled andnvim-treesitteris installed, the parser will be downloaded if needed. -
auto_install: boolean. If enabled usenvim-treesitterto install a missing parser. -
highlights: boolean. If enabled usevim.treesitter.start()to enable treesitter based syntax highlight. -
folds: boolean. If enabled set the optionfoldexprto use treesitter. -
indents: boolean. If enabled set the optionindentexprto use an experimental function fromnvim-treesitter. -
parser_settings: table. Override global config for a specific parser.
Here I'll give you a summary. For more details you can read this: Treesitter in Neovim.
The main purpose of treesitter is to read the source code of a file and turn that into a data structure. Why? Because it's easier to extract information from structured data than plain text. And what do we do with this data thing? Us, casual Neovim users, we do nothing. Neovim mantainers and plugin authors are the ones implementing the features we will use.
Language support is where things get interesting. Treesitter is not a miracle silver bullet that supports every programming language. We add support for a language by installing the appropiate "treesitter parser," which is the component that deals with the specific syntax of a language.
If you don't mind having a bit of code in your personal configuration, you could skip ts-enable.nvim entirely. Just install treesitter parsers ahead of time and mantain your own autocommand with the features you want to enable.
-- NOTE: It is important that you install treesitter parsers and queries.
-- Otherwise none of this will work.
-- Neovim filetypes where you want to enable treesitter
local ts_filetypes = {'json', 'gleam', 'python'}
vim.api.nvim_create_autocmd('FileType', {
desc = 'Enable treesitter features',
pattern = ts_filetypes,
callback = function()
-- enable syntax highlight
vim.treesitter.start()
-- enable folds
vim.wo.foldmethod = 'expr'
vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
-- enable indents
-- NOTE: this feature depends on 'nvim-treesitter'
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
end
})ts-enable.nvim can download missing parsers on demand, meaning it'll only try to get the parsers for the files you open. So I don't think is such a terrible idea to list all the available parsers in nvim-treesitter. If you happen to find a parser that has performance issues, disable it using the parser_settings property.
vim.g.ts_enable = {
parsers = require('nvim-treesitter').get_available(),
auto_install = true,
highlights = true,
}On vimscript:
let g:ts_enable = {
\ 'parsers': v:lua.require'nvim-treesitter'.get_available(),
\ 'auto_install': v:true,
\ 'highlights': v:true,
\}You can override the configuration for a parser using parser_settings.
In the following example all the features are enable on the global config, but for the zimbu parser everything will be disabled.
vim.g.ts_enable = {
parsers = require('nvim-treesitter').get_available(),
auto_install = true,
highlights = true,
folds = true,
indents = true,
parser_settings = {
zimbu = {}
},
}The options in parser_settings take complete control over the features you want to enable. So an empty table (or vimscript object) will make ts-enable.nvim ignore the parser completely.
If you still want to use one feature of the parser but not others, then enable the ones you want.
vim.g.ts_enable = {
parsers = require('nvim-treesitter').get_available(),
auto_install = true,
highlights = true,
folds = true,
indents = true,
parser_settings = {
zimbu = {auto_install = true, highlights = true},
},
}By the way, zimbu is not an actual parser available in nvim-treesitter. Is just a silly example.
Sure. You can even use the opts table field if you like:
return {
'VonHeikemen/ts-enable.nvim',
lazy = false,
dependencies = {
{'nvim-treesitter/nvim-treesitter', branch = 'main'},
},
opts = {
parsers = {'json', 'gleam', 'python'},
auto_install = true,
highlights = true,
folds = false,
indents = false,
},
}Fun fact: lazy.nvim's opts field will pass the data to require('ts-enable').setup() after the plugin is loaded. And this .setup() function just creates vim.g.ts_enable under the hood.
If you need to use nvim-treesitter to get the list of parsers use opts as a function.
opts = function()
return {
parsers = require('nvim-treesitter').get_available(),
auto_install = true,
highlights = true,
folds = false,
indents = false,
}
endYes. Internally. So you don't have to do anything.
Can this be lazy loaded with lazy.nvim? Technically yes. But is not worth it. Just let the plugin create its own autocommand during the startup process.
There is a funny thing about this mechanism: when you access a table field Neovim returns a copy. You can't just modify a nested table in-place.
To modify a value you have to replace the entire thing.
vim.g.ts_enable = {
parsers = {'json', 'gleam', 'python'},
auto_install = true,
highlights = true,
}
-- Get a copy, modify it
local ts_enable = vim.g.ts_enable
ts_enable.auto_install = false
-- Replace the entire thing
vim.g.ts_enable = ts_enableIf you find this useful and want to support my efforts, you can donate in ko-fi.com/vonheikemen.
