aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lua/nvim-treesitter.lua30
-rw-r--r--lua/nvim-treesitter/configs.lua337
-rw-r--r--lua/nvim-treesitter/health.lua6
-rw-r--r--lua/nvim-treesitter/highlight.lua15
-rw-r--r--lua/nvim-treesitter/info.lua96
-rw-r--r--lua/nvim-treesitter/install.lua49
-rw-r--r--lua/nvim-treesitter/utils.lua13
-rw-r--r--plugin/nvim-treesitter.vim17
8 files changed, 452 insertions, 111 deletions
diff --git a/lua/nvim-treesitter.lua b/lua/nvim-treesitter.lua
index b053f39b0..731f55e5d 100644
--- a/lua/nvim-treesitter.lua
+++ b/lua/nvim-treesitter.lua
@@ -1,30 +1,28 @@
local api = vim.api
local parsers = require'nvim-treesitter.parsers'
-local configs = require 'nvim-treesitter.configs'
local install = require'nvim-treesitter.install'
local locals = require'nvim-treesitter.locals'
-local highlight = require'nvim-treesitter.highlight'
+local utils = require'nvim-treesitter.utils'
+local info = require'nvim-treesitter.info'
+local configs = require'nvim-treesitter.configs'
local M = {}
-function M.available_parsers()
- return vim.tbl_keys(configs.repositories)
-end
-
-- This function sets up everythin needed for a given language
-- this is the main interface through the plugin
function M.setup(lang)
- if parsers.has_parser(lang) then
- local autocmd = "autocmd NvimTreesitter FileType %s lua require'nvim-treesitter.highlight'.setup()"
- api.nvim_command(string.format(autocmd, lang))
- end
-end
+ utils.setup_commands('install', install.commands)
+ utils.setup_commands('info', info.commands)
+ utils.setup_commands('configs', configs.commands)
--- This function initialize the plugin
--- it is run at startup
-M._root = {}
-function M._root.setup()
- install.setup()
+ for _, ft in pairs(configs.available_parsers()) do
+ for _, mod in pairs(configs.available_modules()) do
+ if parsers.has_parser(ft) and configs.is_enabled(mod, ft) then
+ local cmd = string.format("lua require'nvim-treesitter.%s'.attach()", mod)
+ api.nvim_command(string.format("autocmd FileType %s %s", ft, cmd))
+ end
+ end
+ end
end
return M
diff --git a/lua/nvim-treesitter/configs.lua b/lua/nvim-treesitter/configs.lua
index fd3b41d29..c9450ed61 100644
--- a/lua/nvim-treesitter/configs.lua
+++ b/lua/nvim-treesitter/configs.lua
@@ -1,88 +1,343 @@
-local M = {}
+local api = vim.api
+local queries = require'nvim-treesitter.query'
+local parser_utils = require'nvim-treesitter.parsers'
+local parsers = {}
-M.repositories = {
- javascript = {
+parsers.javascript = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-javascript",
files = { "src/parser.c", "src/scanner.c" },
- },
- c = {
+ }
+}
+
+parsers.c = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-c",
files = { "src/parser.c" }
- },
- cpp = {
+ }
+}
+
+parsers.cpp = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-cpp",
files = { "src/parser.c", "src/scanner.cc" }
- },
- rust = {
+ }
+}
+
+parsers.rust = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-rust",
files = { "src/parser.c", "src/scanner.c" },
- },
- lua = {
+ }
+}
+
+parsers.lua = {
+ install_info = {
url = "https://github.com/nvim-treesitter/tree-sitter-lua",
files = { "src/parser.c", "src/scanner.cc" }
- },
- python = {
+ }
+}
+
+parsers.python = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-python",
files = { "src/parser.c", "src/scanner.cc" },
- },
- go = {
+ }
+}
+
+parsers.go = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-go",
files = { "src/parser.c" },
- },
- ruby = {
+ }
+}
+
+parsers.ruby = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-ruby",
files = { "src/parser.c", "src/scanner.cc" },
- },
- bash = {
+ }
+}
+
+parsers.bash = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-bash",
files = { "src/parser.c", "src/scanner.cc" },
- },
- php = {
+ }
+}
+
+parsers.php = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-php",
files = { "src/parser.c", "src/scanner.cc" },
- },
- java = {
+ }
+}
+
+parsers.java = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-java",
files = { "src/parser.c" },
- },
- html = {
+ }
+}
+
+parsers.html = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-html",
files = { "src/parser.c", "src/scanner.cc" },
- },
- julia = {
+ }
+}
+
+parsers.julia = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-julia",
files = { "src/parser.c", "src/scanner.c" },
- },
- json = {
+ }
+}
+
+parsers.json = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-json",
files = { "src/parser.c" },
- },
- css = {
+ }
+}
+
+parsers.css = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-css",
files = { "src/parser.c", "src/scanner.c" },
- },
- ocaml = {
+ }
+}
+
+parsers.ocaml = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-ocaml",
files = { "src/parser.c", "src/scanner.cc" },
- },
- swift = {
+ }
+}
+
+parsers.swift = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-swift",
files = { "src/parser.c" },
- },
- csharp = {
+ }
+}
+
+parsers.csharp = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-c-sharp",
files = { "src/parser.c", "src/scanner.c" },
- },
- typescript = {
+ }
+}
+
+parsers.typescript = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-typescript",
files = { "src/parser.c", "src/scanner.c" },
location = "tree-sitter-typescript/typescript"
- },
- tsx = {
+ }
+}
+
+parsers.tsx = {
+ install_info = {
url = "https://github.com/tree-sitter/tree-sitter-typescript",
files = { "src/parser.c", "src/scanner.c" },
location = "tree-sitter-tsx/tsx"
}
}
+-- @enable can be true or false
+-- @disable is a list of languages, only relevant if enable is true
+-- @keymaps list of user mappings for a given module if relevant
+-- @is_supported function which, given a ft, will return true if the ft works on the module
+local config = {
+ highlight = {
+ enable = false,
+ disable = {},
+ is_supported = function(ft)
+ return queries.get_query(ft, 'highlights') ~= nil
+ end
+ },
+ -- selection = {
+ -- enable = false,
+ -- disable = {},
+ -- keymaps = {},
+ -- is_supported = function() return false end
+ -- },
+ -- folding = {
+ -- enable = false,
+ -- disable = {},
+ -- keymaps = {},
+ -- is_supported = function() return false end
+ -- }
+}
+
+local M = {}
+
+local function enable_module(mod, bufnr, ft)
+ local bufnr = bufnr or api.nvim_get_current_buf()
+ local ft = ft or api.nvim_buf_get_option(bufnr, 'ft')
+ if not parsers[ft] or not config[mod] then
+ return
+ end
+
+ local loaded_mod = require(string.format("nvim-treesitter.%s", mod))
+ loaded_mod.attach(bufnr, ft)
+end
+
+local function enable_mod_conf_autocmd(mod, ft)
+ if not config[mod] or M.is_enabled(mod, ft) then return end
+
+ local cmd = string.format("lua require'nvim-treesitter.%s'.attach()", mod)
+ api.nvim_command(string.format("autocmd FileType %s %s", ft, cmd))
+ for i, parser in pairs(config[mod].disable) do
+ if parser == ft then
+ table.remove(config[mod].disable, i)
+ break
+ end
+ end
+end
+
+local function enable_all(mod, ft)
+ if not config[mod] then return end
+
+ for _, bufnr in pairs(api.nvim_list_bufs()) do
+ if not ft or api.nvim_buf_get_option(bufnr, 'ft') == ft then
+ enable_module(mod, bufnr, ft)
+ end
+ end
+ if ft then
+ enable_mod_conf_autocmd(mod, ft)
+ else
+ for _, ft in pairs(M.available_parsers()) do
+ if parser_utils.has_parser(ft) then
+ enable_mod_conf_autocmd(mod, ft)
+ end
+ end
+ end
+ config[mod].enable = true
+end
+
+local function disable_module(mod, bufnr, ft)
+ local bufnr = bufnr or api.nvim_get_current_buf()
+ local ft = ft or api.nvim_buf_get_option(bufnr, 'ft')
+ if not parsers[ft] or not config[mod] then
+ return
+ end
+
+ local loaded_mod = require(string.format("nvim-treesitter.%s", mod))
+ loaded_mod.detach(bufnr, ft)
+end
+
+local function disable_mod_conf_autocmd(mod, ft)
+ if not config[mod] or not M.is_enabled(mod, ft) then return end
+
+ api.nvim_command(string.format("autocmd! FileType %s", ft))
+ table.insert(config[mod].disable, ft)
+end
+
+local function disable_all(mod, ft)
+ for _, bufnr in pairs(api.nvim_list_bufs()) do
+ if not ft or api.nvim_buf_get_option(bufnr, 'ft') == ft then
+ disable_module(mod, bufnr, ft)
+ end
+ end
+ if ft then
+ disable_mod_conf_autocmd(mod, ft)
+ else
+ for _, ft in pairs(M.available_parsers()) do
+ if parser_utils.has_parser(ft) then
+ disable_mod_conf_autocmd(mod, ft)
+ end
+ end
+ config[mod].enable = false
+ end
+end
+
+M.commands = {
+ TSBufEnable = {
+ run = enable_module,
+ args = {
+ "-nargs=1",
+ "-complete=custom,v:lua.ts_available_modules"
+ },
+ description = '`:TSBufEnable module_name` enable a specified module on the current buffer'
+ },
+ TSBufDisable = {
+ run = disable_module,
+ args = {
+ "-nargs=1",
+ "-complete=custom,v:lua.ts_available_modules"
+ },
+ description = '`:TSBufDisable module_name` disable a specified module on the current buffer'
+ },
+ TSEnableAll = {
+ run = enable_all,
+ args = {
+ "-nargs=+",
+ "-complete=custom,v:lua.ts_available_modules"
+ },
+ description = '`:TSEnableAll module_name (filetype)` enables a specified module on all buffers. If filetype is specified, enable only for specified filetype'
+ },
+ TSDisableAll = {
+ run = disable_all,
+ args = {
+ "-nargs=+",
+ "-complete=custom,v:lua.ts_available_modules"
+ },
+ description = '`:TSDisableAll module_name (filetype)` disables a specified module on all buffers. If filetype is specified, disable only for specified filetype'
+ },
+}
+
+-- @param mod: module (string)
+-- @param ft: filetype (string)
+function M.is_enabled(mod, ft)
+ if not M.get_parser_configs()[ft] then return false end
+
+ local module_config = M.get_config()[mod]
+ if not module_config then return false end
+
+ if not module_config.enable or not module_config.is_supported(ft) then
+ return false
+ end
+
+ for _, parser in pairs(module_config.disable) do
+ if ft == parser then return false end
+ end
+ return true
+end
+
+function M.setup(user_data)
+ if not user_data then return end
+
+ for mod, data in pairs(user_data) do
+ if config[mod] then
+ if type(data.enable) == 'boolean' then
+ config[mod].enable = data.enable
+ end
+ if type(data.disable) == 'table' then
+ config[mod].disable = data.disable
+ end
+ if config[mod].keymaps and type(data.keymaps) == 'table' then
+ config[mod].keymaps = data.keymaps
+ end
+ end
+ end
+end
+
+function M.get_config()
+ return config
+end
+
+function M.get_parser_configs()
+ return parsers
+end
+
+function M.available_parsers()
+ return vim.tbl_keys(parsers)
+end
+
+function M.available_modules()
+ return vim.tbl_keys(config)
+end
+
return M
diff --git a/lua/nvim-treesitter/health.lua b/lua/nvim-treesitter/health.lua
index 25da7fe35..563e46a90 100644
--- a/lua/nvim-treesitter/health.lua
+++ b/lua/nvim-treesitter/health.lua
@@ -13,7 +13,7 @@ local health_error = vim.fn['health#report_error']
local M = {}
-local function configs_health()
+local function install_health()
if fn.executable('git') == 0 then
health_error('`git` executable not found.', {
'Install it with your package manager.',
@@ -38,11 +38,11 @@ end
function M.checkhealth()
-- Installation dependency checks
health_start('Installation')
- configs_health()
+ install_health()
local missing_parsers = {}
-- Parser installation checks
- for parser_name in pairs(configs.repositories) do
+ for _, parser_name in pairs(configs.available_parsers()) do
local installed = #api.nvim_get_runtime_file('parser/'..parser_name..'.so', false)
-- Only print informations about installed parsers
diff --git a/lua/nvim-treesitter/highlight.lua b/lua/nvim-treesitter/highlight.lua
index 110954a6a..65ab48dcb 100644
--- a/lua/nvim-treesitter/highlight.lua
+++ b/lua/nvim-treesitter/highlight.lua
@@ -1,12 +1,12 @@
local api = vim.api
-local queries = require'nvim-treesitter.query'
local ts = vim.treesitter
+local queries = require'nvim-treesitter.query'
local M = {
- highlighters={}
+ highlighters = {}
}
-function M.setup(bufnr, ft)
+function M.attach(bufnr, ft)
local buf = bufnr or api.nvim_get_current_buf()
local ft = ft or api.nvim_buf_get_option(buf, 'ft')
@@ -16,4 +16,13 @@ function M.setup(bufnr, ft)
M.highlighters[buf] = ts.TSHighlighter.new(query, buf, ft)
end
+function M.detach(bufnr)
+ local buf = bufnr or api.nvim_get_current_buf()
+ if M.highlighters[buf] then
+ M.highlighters[buf]:set_query("")
+ M.highlighters[buf] = nil
+ end
+ api.nvim_buf_set_option(buf, 'syntax', 'on')
+end
+
return M
diff --git a/lua/nvim-treesitter/info.lua b/lua/nvim-treesitter/info.lua
new file mode 100644
index 000000000..18b1b611f
--- /dev/null
+++ b/lua/nvim-treesitter/info.lua
@@ -0,0 +1,96 @@
+local api = vim.api
+local configs = require'nvim-treesitter.configs'
+
+local M = {}
+
+local function install_info()
+ local max_len = 0
+ for _, ft in pairs(configs.available_parsers()) do
+ if #ft > max_len then max_len = #ft end
+ end
+
+ for _, ft in pairs(configs.available_parsers()) do
+ local is_installed = #api.nvim_get_runtime_file('parser/'..ft..'.so', false) > 0
+ api.nvim_out_write(ft..string.rep(' ', max_len - #ft + 1))
+ if is_installed then
+ api.nvim_out_write("[✓] installed\n")
+ else
+ api.nvim_out_write("[✗] not installed\n")
+ end
+ end
+end
+
+local function print_info_module(sorted_filetypes, mod)
+ local max_str_len = #sorted_filetypes[1]
+ local header = string.format('%s%s', string.rep(' ', max_str_len + 2), mod)
+ api.nvim_out_write(header..'\n')
+ for _, ft in pairs(sorted_filetypes) do
+ local padding = string.rep(' ', max_str_len - #ft + #mod / 2 + 1)
+ api.nvim_out_write(ft..":"..padding)
+ if configs.is_enabled(mod, ft) then
+ api.nvim_out_write('✓')
+ else
+ api.nvim_out_write('✗')
+ end
+ api.nvim_out_write('\n')
+ end
+end
+
+local function print_info_modules(sorted_filetypes)
+ local max_str_len = #sorted_filetypes[1]
+ local header = string.rep(' ', max_str_len + 2)
+ for _, mod in pairs(configs.available_modules()) do
+ header = string.format('%s%s ', header, mod)
+ end
+ api.nvim_out_write(header..'\n')
+
+ for _, ft in pairs(sorted_filetypes) do
+ local padding = string.rep(' ', max_str_len - #ft)
+ api.nvim_out_write(ft..":"..padding)
+
+ for _, mod in pairs(configs.available_modules()) do
+ local pad_len = #mod / 2 + 1
+ api.nvim_out_write(string.rep(' ', pad_len))
+
+ if configs.is_enabled(mod, ft) then
+ api.nvim_out_write('✓')
+ else
+ api.nvim_out_write('✗')
+ end
+ api.nvim_out_write(string.rep(' ', pad_len - 1))
+ end
+ api.nvim_out_write('\n')
+ end
+end
+
+local function module_info(mod)
+ if mod and not configs.get_config()[mod] then return end
+
+ local ft_by_len = configs.available_parsers()
+ table.sort(ft_by_len, function(a, b) return #a > #b end)
+ if mod then
+ print_info_module(ft_by_len, mod)
+ else
+ print_info_modules(ft_by_len)
+ end
+end
+
+M.commands = {
+ TSInstallInfo = {
+ run = install_info,
+ args = {
+ "-nargs=0",
+ },
+ description = '`:TSInstallInfo` print installation state for every filetype'
+ },
+ TSModuleInfo = {
+ run = module_info,
+ args = {
+ "-nargs=?",
+ "-complete=custom,v:lua.ts_available_modules"
+ },
+ description = '`:TSModuleInfo` print module state for every filetype, if module is specified, only for current module'
+ }
+}
+
+return M
diff --git a/lua/nvim-treesitter/install.lua b/lua/nvim-treesitter/install.lua
index b00d3d773..be09a3bc1 100644
--- a/lua/nvim-treesitter/install.lua
+++ b/lua/nvim-treesitter/install.lua
@@ -1,7 +1,8 @@
local api = vim.api
local fn = vim.fn
local luv = vim.loop
-local repositories = require'nvim-treesitter/configs'.repositories
+local configs = require'nvim-treesitter/configs'
+local parsers = configs.get_parser_configs()
local M = {}
@@ -118,14 +119,15 @@ local function install(ft)
if not string.match(yesno, '^y.*') then return end
end
- local repository = repositories[ft]
- if not repository then
+ local parser_config = parsers[ft]
+ if not parser_config then
return api.nvim_err_writeln('Parser not available for language '..ft)
end
+ local install_info = parser_config.install_info
vim.validate {
- url={ repository.url, 'string' },
- files={ repository.files, 'table' }
+ url={ install_info.url, 'string' },
+ files={ install_info.files, 'table' }
}
if fn.executable('git') == 0 then
@@ -138,24 +140,7 @@ local function install(ft)
local cache_folder, err = get_cache_dir()
if err then return api.nvim_err_writeln(err) end
- run_install(cache_folder, package_path, ft, repository)
-end
-
-local function install_info()
- local max_len = 0
- for parser_name, _ in pairs(repositories) do
- if #parser_name > max_len then max_len = #parser_name end
- end
-
- for parser_name, _ in pairs(repositories) do
- local is_installed = #api.nvim_get_runtime_file('parser/'..parser_name..'.so', false) > 0
- api.nvim_out_write(parser_name..string.rep(' ', max_len - #parser_name + 1))
- if is_installed then
- api.nvim_out_write("[✓] installed\n")
- else
- api.nvim_out_write("[✗] not installed\n")
- end
- end
+ run_install(cache_folder, package_path, ft, install_info)
end
M.commands = {
@@ -166,25 +151,7 @@ M.commands = {
"-complete=custom,v:lua.ts_installable_parsers"
},
description = '`:TSInstall {ft}` installs a parser under nvim-treesitter/parser/{name}.so'
- },
- TSInstallInfo = {
- run = install_info,
- args = { "-nargs=0" },
- description = '`:TSInstallInfo` print installation state for every filetype'
}
}
-function M.setup()
- for command_name, def in pairs(M.commands) do
- local call_fn = string.format("lua require'nvim-treesitter.install'.commands.%s.run(<f-args>)", command_name)
- local parts = vim.tbl_flatten({
- "command!",
- def.args,
- command_name,
- call_fn,
- })
- api.nvim_command(table.concat(parts, " "))
- end
-end
-
return M
diff --git a/lua/nvim-treesitter/utils.lua b/lua/nvim-treesitter/utils.lua
index 8313a46a7..59de5dd57 100644
--- a/lua/nvim-treesitter/utils.lua
+++ b/lua/nvim-treesitter/utils.lua
@@ -63,4 +63,17 @@ function M.is_parent(dest, source)
return false
end
+function M.setup_commands(mod, commands)
+ for command_name, def in pairs(commands) do
+ local call_fn = string.format("lua require'nvim-treesitter.%s'.commands.%s.run(<f-args>)", mod, command_name)
+ local parts = vim.tbl_flatten({
+ "command!",
+ def.args,
+ command_name,
+ call_fn,
+ })
+ api.nvim_command(table.concat(parts, " "))
+ end
+end
+
return M
diff --git a/plugin/nvim-treesitter.vim b/plugin/nvim-treesitter.vim
index 06c760a18..a94f56a96 100644
--- a/plugin/nvim-treesitter.vim
+++ b/plugin/nvim-treesitter.vim
@@ -4,14 +4,17 @@ if exists('g:loaded_nvim_treesitter')
finish
endif
+augroup NvimTreesitter
+augroup END
+
+let g:loaded_nvim_treesitter = 1
+
lua << EOF
ts_installable_parsers = function()
- return table.concat(require'nvim-treesitter'.available_parsers(), '\n')
+ return table.concat(require'nvim-treesitter.configs'.available_parsers(), '\n')
+end
+ts_available_modules = function()
+ return table.concat(require'nvim-treesitter.configs'.available_modules(), '\n')
end
-require'nvim-treesitter'._root.setup()
+require'nvim-treesitter'.setup()
EOF
-
-let g:loaded_nvim_treesitter = 1
-
-augroup NvimTreesitter
-augroup END