Merge pull request #330 from steelsojka/fix-do-not-reattach

fix(modules): do not reattach if already attached
This commit is contained in:
Steven Sojka 2020-08-22 09:10:28 -05:00 committed by GitHub
commit 3b2cb65d4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 76 additions and 42 deletions

View file

@ -0,0 +1,48 @@
local api = vim.api
local M = {}
--- Creates a cache table for buffers keyed by a type name.
--- Cache entries attach to the buffer and cleanup entries
--- as buffers are detached.
function M.create_buffer_cache()
local cache = {}
local items = setmetatable({}, {
__index = function(tbl, key)
rawset(tbl, key, {})
return rawget(tbl, key)
end
})
function cache.set(type_name, bufnr, value)
if not cache.has(type_name, bufnr) then
-- Clean up the cache if the buffer is detached
-- to avoid memory leaks
api.nvim_buf_attach(bufnr, false, {
on_detach = function()
cache.remove(type_name, bufnr)
return true
end
})
end
items[type_name][bufnr] = value
end
function cache.get(type_name, bufnr)
return items[type_name][bufnr]
end
function cache.has(type_name, bufnr)
return cache.get(type_name, bufnr) ~= nil
end
function cache.remove(type_name, bufnr)
items[type_name][bufnr] = nil
end
return cache
end
return M

View file

@ -3,6 +3,7 @@ local api = vim.api
local queries = require'nvim-treesitter.query' local queries = require'nvim-treesitter.query'
local parsers = require'nvim-treesitter.parsers' local parsers = require'nvim-treesitter.parsers'
local utils = require'nvim-treesitter.utils' local utils = require'nvim-treesitter.utils'
local caching = require'nvim-treesitter.caching'
local M = {} local M = {}
@ -109,6 +110,8 @@ local builtin_modules = {
} }
} }
local attached_buffers_by_module = caching.create_buffer_cache()
-- Resolves a module by requiring the `module_path` or using the module definition. -- Resolves a module by requiring the `module_path` or using the module definition.
local function resolve_module(mod_name) local function resolve_module(mod_name)
local config_mod = M.get_module(mod_name) local config_mod = M.get_module(mod_name)
@ -367,8 +370,13 @@ end
-- @param lang the language of the buffer -- @param lang the language of the buffer
function M.attach_module(mod_name, bufnr, lang) function M.attach_module(mod_name, bufnr, lang)
local resolved_mod = resolve_module(mod_name) local resolved_mod = resolve_module(mod_name)
local bufnr = bufnr or api.nvim_get_current_buf()
if resolved_mod and parsers.has_parser(lang) then if resolved_mod
and parsers.has_parser(lang)
and not attached_buffers_by_module.has(mod_name, bufnr)
then
attached_buffers_by_module.set(mod_name, bufnr, true)
resolved_mod.attach(bufnr, lang) resolved_mod.attach(bufnr, lang)
end end
end end
@ -378,8 +386,10 @@ end
-- @param bufnr the bufnr -- @param bufnr the bufnr
function M.detach_module(mod_name, bufnr) function M.detach_module(mod_name, bufnr)
local resolved_mod = resolve_module(mod_name) local resolved_mod = resolve_module(mod_name)
local bufnr = bufnr or api.nvim_get_current_buf()
if resolved_mod then if resolved_mod then
attached_buffers_by_module.remove(mod_name, bufnr)
resolved_mod.detach(bufnr) resolved_mod.detach(bufnr)
end end
end end

View file

@ -69,7 +69,6 @@ hlmap["text.literal"] = "TSLiteral"
hlmap["text.uri"] = "TSURI" hlmap["text.uri"] = "TSURI"
function M.attach(bufnr, lang) function M.attach(bufnr, lang)
local bufnr = bufnr or api.nvim_get_current_buf()
local lang = lang or parsers.get_buf_lang(bufnr) local lang = lang or parsers.get_buf_lang(bufnr)
local config = configs.get_module('highlight') local config = configs.get_module('highlight')
@ -84,12 +83,11 @@ function M.attach(bufnr, lang)
end end
function M.detach(bufnr) function M.detach(bufnr)
local buf = bufnr or api.nvim_get_current_buf() if M.highlighters[bufnr] then
if M.highlighters[buf] then M.highlighters[bufnr]:set_query("")
M.highlighters[buf]:set_query("") M.highlighters[bufnr] = nil
M.highlighters[buf] = nil
end end
api.nvim_buf_set_option(buf, 'syntax', 'on') api.nvim_buf_set_option(bufnr, 'syntax', 'on')
end end
return M return M

View file

@ -94,8 +94,6 @@ function M.node_decremental()
end end
function M.attach(bufnr) function M.attach(bufnr)
local buf = bufnr or api.nvim_get_current_buf()
local config = configs.get_module('incremental_selection') local config = configs.get_module('incremental_selection')
for funcname, mapping in pairs(config.keymaps) do for funcname, mapping in pairs(config.keymaps) do
local mode local mode
@ -105,19 +103,17 @@ function M.attach(bufnr)
mode = 'v' mode = 'v'
end end
local cmd = string.format(":lua require'nvim-treesitter.incremental_selection'.%s()<CR>", funcname) local cmd = string.format(":lua require'nvim-treesitter.incremental_selection'.%s()<CR>", funcname)
api.nvim_buf_set_keymap(buf, mode, mapping, cmd, { silent = true, noremap = true }) api.nvim_buf_set_keymap(bufnr, mode, mapping, cmd, { silent = true, noremap = true })
end end
end end
function M.detach(bufnr) function M.detach(bufnr)
local buf = bufnr or api.nvim_get_current_buf()
local config = configs.get_module('incremental_selection') local config = configs.get_module('incremental_selection')
for f, mapping in pairs(config.keymaps) do for f, mapping in pairs(config.keymaps) do
if f == "init_selection" then if f == "init_selection" then
api.nvim_buf_del_keymap(buf, 'n', mapping) api.nvim_buf_del_keymap(bufnr, 'n', mapping)
else else
api.nvim_buf_del_keymap(buf, 'v', mapping) api.nvim_buf_del_keymap(bufnr, 'v', mapping)
end end
end end
end end

View file

@ -2,20 +2,11 @@ local api = vim.api
local ts = vim.treesitter local ts = vim.treesitter
local utils = require'nvim-treesitter.utils' local utils = require'nvim-treesitter.utils'
local parsers = require'nvim-treesitter.parsers' local parsers = require'nvim-treesitter.parsers'
local caching = require'nvim-treesitter.caching'
local M = {} local M = {}
local default_dict = { local query_cache = caching.create_buffer_cache()
__index = function(table, key)
local exists = rawget(table, key)
if not exists then
table[key] = {}
end
return rawget(table, key)
end
}
local query_cache = setmetatable({}, default_dict)
-- Some treesitter grammars extend others. -- Some treesitter grammars extend others.
-- We can use that to import the queries of the base language -- We can use that to import the queries of the base language
@ -55,17 +46,17 @@ local function read_query_files(filenames)
end end
local function update_cached_matches(bufnr, changed_tick, query_group) local function update_cached_matches(bufnr, changed_tick, query_group)
query_cache[query_group][bufnr] = {tick=changed_tick, cache=( M.collect_group_results(bufnr, query_group) or {} )} query_cache.set(query_group, bufnr, {tick=changed_tick, cache=( M.collect_group_results(bufnr, query_group) or {} )})
end end
function M.get_matches(bufnr, query_group) function M.get_matches(bufnr, query_group)
local bufnr = bufnr or api.nvim_get_current_buf() local bufnr = bufnr or api.nvim_get_current_buf()
local cached_local = query_cache[query_group][bufnr] local cached_local = query_cache.get(query_group, bufnr)
if not cached_local or api.nvim_buf_get_changedtick(bufnr) > cached_local.tick then if not cached_local or api.nvim_buf_get_changedtick(bufnr) > cached_local.tick then
update_cached_matches(bufnr,api.nvim_buf_get_changedtick(bufnr), query_group) update_cached_matches(bufnr,api.nvim_buf_get_changedtick(bufnr), query_group)
end end
return query_cache[query_group][bufnr].cache return query_cache.get(query_group, bufnr).cache
end end
local function filter_files(file_list) local function filter_files(file_list)

View file

@ -27,8 +27,6 @@ function M.clear_highlights(bufnr)
end end
function M.attach(bufnr) function M.attach(bufnr)
local bufnr = bufnr or api.nvim_get_current_buf()
cmd(string.format('augroup NvimTreesitterCurrentScope_%d', bufnr)) cmd(string.format('augroup NvimTreesitterCurrentScope_%d', bufnr))
cmd 'au!' cmd 'au!'
-- luacheck: push ignore 631 -- luacheck: push ignore 631

View file

@ -39,8 +39,6 @@ function M.clear_usage_highlights(bufnr)
end end
function M.attach(bufnr) function M.attach(bufnr)
local bufnr = bufnr or api.nvim_get_current_buf()
cmd(string.format('augroup NvimTreesitterUsages_%d', bufnr)) cmd(string.format('augroup NvimTreesitterUsages_%d', bufnr))
cmd 'au!' cmd 'au!'
-- luacheck: push ignore 631 -- luacheck: push ignore 631

View file

@ -49,8 +49,6 @@ function M.list_definitions(bufnr)
end end
function M.attach(bufnr) function M.attach(bufnr)
local bufnr = bufnr or api.nvim_get_current_buf()
local config = configs.get_module('refactor.navigation') local config = configs.get_module('refactor.navigation')
for fn_name, mapping in pairs(config.keymaps) do for fn_name, mapping in pairs(config.keymaps) do

View file

@ -46,7 +46,6 @@ function M.smart_rename(bufnr)
end end
function M.attach(bufnr) function M.attach(bufnr)
local bufnr = bufnr or api.nvim_get_current_buf()
local config = configs.get_module('refactor.smart_rename') local config = configs.get_module('refactor.smart_rename')
for fn_name, mapping in pairs(config.keymaps) do for fn_name, mapping in pairs(config.keymaps) do

View file

@ -6,9 +6,8 @@ local M = {}
function M.make_attach(normal_mode_functions, submodule) function M.make_attach(normal_mode_functions, submodule)
return function(bufnr, lang) return function(bufnr, lang)
local buf = bufnr or api.nvim_get_current_buf()
local config = configs.get_module("textobjects."..submodule) local config = configs.get_module("textobjects."..submodule)
local lang = lang or parsers.get_buf_lang(buf) local lang = lang or parsers.get_buf_lang(bufnr)
for _, function_call in pairs(normal_mode_functions) do for _, function_call in pairs(normal_mode_functions) do
for mapping, query in pairs(config[function_call] or {}) do for mapping, query in pairs(config[function_call] or {}) do
@ -19,7 +18,7 @@ function M.make_attach(normal_mode_functions, submodule)
end end
if query then if query then
local cmd = ":lua require'nvim-treesitter.textobjects."..submodule.."'."..function_call.."('"..query.."')<CR>" local cmd = ":lua require'nvim-treesitter.textobjects."..submodule.."'."..function_call.."('"..query.."')<CR>"
api.nvim_buf_set_keymap(buf, "n", mapping, cmd, {silent = true, noremap = true }) api.nvim_buf_set_keymap(bufnr, "n", mapping, cmd, {silent = true, noremap = true })
end end
end end
end end
@ -28,7 +27,6 @@ end
function M.make_detach(normal_mode_functions, submodule) function M.make_detach(normal_mode_functions, submodule)
return function(bufnr) return function(bufnr)
local buf = bufnr or api.nvim_get_current_buf()
local config = configs.get_module("textobjects."..submodule) local config = configs.get_module("textobjects."..submodule)
local lang = parsers.get_buf_lang(bufnr) local lang = parsers.get_buf_lang(bufnr)
@ -39,8 +37,8 @@ function M.make_detach(normal_mode_functions, submodule)
query = nil query = nil
end end
if query then if query then
api.nvim_buf_del_keymap(buf, "o", mapping) api.nvim_buf_del_keymap(bufnr, "o", mapping)
api.nvim_buf_del_keymap(buf, "v", mapping) api.nvim_buf_del_keymap(bufnr, "v", mapping)
end end
end end
for _, function_call in pairs(normal_mode_functions) do for _, function_call in pairs(normal_mode_functions) do
@ -51,7 +49,7 @@ function M.make_detach(normal_mode_functions, submodule)
query = nil query = nil
end end
if query then if query then
api.nvim_buf_del_keymap(buf, "n", mapping) api.nvim_buf_del_keymap(bufnr, "n", mapping)
end end
end end
end end