From 17653f763bc85c636c35e1bd0263dc6cda2b82d4 Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Fri, 12 Sep 2025 22:28:23 -0600 Subject: [PATCH 1/8] feat: add `vim.validate` checks Signed-off-by: Guennadi Maximov C --- lua/lsp-toggle.lua | 5 +++++ lua/lsp-toggle/config.lua | 5 +++++ lua/lsp-toggle/fileutils.lua | 22 ++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/lua/lsp-toggle.lua b/lua/lsp-toggle.lua index 8c2ea0e..9aaddc4 100644 --- a/lua/lsp-toggle.lua +++ b/lua/lsp-toggle.lua @@ -5,6 +5,11 @@ local M = {} ---@param opts? LspToggle.Opts function M.setup(opts) + if vim.fn.has('nvim-0.11') == 1 then + vim.validate('opts', opts, 'table', true, 'LspToggle.Opts?') + else + vim.validate({ opts = { opts, { 'table', 'nil' } } }) + end config.setup(opts or {}) end diff --git a/lua/lsp-toggle/config.lua b/lua/lsp-toggle/config.lua index ca4247d..963be36 100644 --- a/lua/lsp-toggle/config.lua +++ b/lua/lsp-toggle/config.lua @@ -30,6 +30,11 @@ M.options = {} ---@param opts? LspToggle.Opts function M.setup(opts) + if vim.fn.has('nvim-0.11') == 1 then + vim.validate('opts', opts, 'table', true, 'LspToggle.Opts?') + else + vim.validate({ opts = { opts, { 'table', 'nil' } } }) + end opts = opts or {} M.options = vim.tbl_deep_extend('keep', opts, defaults) diff --git a/lua/lsp-toggle/fileutils.lua b/lua/lsp-toggle/fileutils.lua index dad6076..842e3a5 100644 --- a/lua/lsp-toggle/fileutils.lua +++ b/lua/lsp-toggle/fileutils.lua @@ -8,6 +8,12 @@ M.file_path = '' ---@param str string ---@return string hash local function djb2(str) + if vim.fn.has('nvim-0.11') == 1 then + vim.validate('str', str, 'string', false) + else + vim.validate({ str = { str, 'string' } }) + end + local hash = 5381 for i = 1, str:len() do local c = str:byte(i) @@ -19,6 +25,12 @@ end ---@param path string function M.set_file_path(path) + if vim.fn.has('nvim-0.11') == 1 then + vim.validate('path', path, 'string', false) + else + vim.validate({ path = { path, 'string' } }) + end + M.file_path = path end @@ -34,6 +46,11 @@ end ---@param data table ---@return boolean|nil function M.save(data) + if vim.fn.has('nvim-0.11') == 1 then + vim.validate('data', data, 'table', false, 'table') + else + vim.validate({ data = { data, 'table' } }) + end local path = M.produce_path() if not path then @@ -80,6 +97,11 @@ end ---@param path? string function M.clear_cache(path) + if vim.fn.has('nvim-0.11') == 1 then + vim.validate('path', path, 'string', true) + else + vim.validate({ path = { path, { 'string', 'nil' } } }) + end path = path or M.root_dir local stat = vim.uv.fs_stat(path) From e53062321474d8c4bc49d21a353a32945d6cee8e Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Fri, 12 Sep 2025 22:31:42 -0600 Subject: [PATCH 2/8] fix: annotations added, better checks, exported autocmd callbacks Signed-off-by: Guennadi Maximov C --- lua/lsp-toggle/config.lua | 53 ++++++++++++++++-------------------- lua/lsp-toggle/fileutils.lua | 4 +-- lua/lsp-toggle/utils.lua | 12 +++++--- lua/lsp-toggle/window.lua | 12 +++++--- plugin/lsp-toggle.lua | 6 ++-- 5 files changed, 46 insertions(+), 41 deletions(-) diff --git a/lua/lsp-toggle/config.lua b/lua/lsp-toggle/config.lua index 963be36..9289892 100644 --- a/lua/lsp-toggle/config.lua +++ b/lua/lsp-toggle/config.lua @@ -39,52 +39,47 @@ function M.setup(opts) M.options = vim.tbl_deep_extend('keep', opts, defaults) - if M.options.max_height <= 0 then + if not M.options.max_height or M.options.max_height <= 0 then M.options.max_height = defaults.max_height end - if M.options.max_width <= 0 then + if not M.options.max_width or M.options.max_width <= 0 then M.options.max_width = defaults.max_width end M.setup_autocmds() end -function M.setup_autocmds() - local load_cache = function() - local opts = require('lsp-toggle.config').options - if not opts.cache then - return - end - utils.merge_table_pf() -- merge saved data before enabling/disabling clients - for _, tb_server in pairs(utils.clients) do - vim.lsp.enable(tb_server.server_name, tb_server.enabled) - end +function M.load_cache() + if not M.options.cache then + return + end + utils.merge_table_pf() -- merge saved data before enabling/disabling clients + for _, tb_server in pairs(utils.clients) do + vim.lsp.enable(tb_server.server_name, tb_server.enabled) end +end - local augroup = vim.api.nvim_create_augroup('lsp-toggle', { clear = false }) +---@param args vim.api.keyset.create_autocmd.callback_args +local function callback(args) + if vim.bo[args.buf].buftype ~= '' then + return + end + + fileutils.set_file_path(vim.api.nvim_buf_get_name(args.buf)) + M.load_cache() +end + +function M.setup_autocmds() + local augroup = vim.api.nvim_create_augroup('lsp-toggle', { clear = true }) vim.api.nvim_create_autocmd('LspAttach', { group = augroup, - callback = function() - if vim.bo.buftype ~= '' then - return - end - - fileutils.set_file_path(vim.api.nvim_buf_get_name(0)) - load_cache() - end, + callback = callback, }) vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWinEnter' }, { - callback = function(args) - if vim.bo[args.buf].buftype ~= '' then - return - end - - fileutils.set_file_path(vim.api.nvim_buf_get_name(args.buf)) - load_cache() - end, + callback = callback, }) vim.api.nvim_create_autocmd('BufLeave', { diff --git a/lua/lsp-toggle/fileutils.lua b/lua/lsp-toggle/fileutils.lua index 842e3a5..1824129 100644 --- a/lua/lsp-toggle/fileutils.lua +++ b/lua/lsp-toggle/fileutils.lua @@ -43,7 +43,7 @@ function M.produce_path() return string.format('%s/%s.json', M.root_dir, djb2(M.file_path)) end ----@param data table +---@param data table ---@return boolean|nil function M.save(data) if vim.fn.has('nvim-0.11') == 1 then @@ -67,7 +67,7 @@ function M.save(data) return true end ----@return table|nil +---@return table|nil function M.load() -- returns lspClients local path = M.produce_path() diff --git a/lua/lsp-toggle/utils.lua b/lua/lsp-toggle/utils.lua index 63af8b3..10218e5 100644 --- a/lua/lsp-toggle/utils.lua +++ b/lua/lsp-toggle/utils.lua @@ -1,8 +1,12 @@ local fileutils = require('lsp-toggle.fileutils') +---@class LspToggleUtils.Client +---@field enabled boolean +---@field server_name string + local M = {} ----@type table +---@type table M.clients = {} function M.load_all_clients() @@ -15,7 +19,7 @@ function M.load_all_clients() enabled = vim.lsp.is_enabled(client.name), server_name = client.name, } - else + elseif vim.list_contains(vim.tbl_keys(M.clients), client.name) then M.clients[client.name] = nil end end @@ -25,13 +29,13 @@ function M.merge_table_pf() local opts = require('lsp-toggle.config').options M.load_all_clients() - local file_clients = opts.cache and fileutils.load() or {} + local file_clients = opts.cache and (fileutils.load() or {}) or {} local excluded = require('lsp-toggle.config').options.exclude_lsp -- merge tables with priority to file for name, client in pairs(M.clients) do local added = false - if not vim.tbl_contains(excluded, name) then + if not vim.list_contains(excluded, name) then for fname, fclient in pairs(file_clients) do if fname == name then M.clients[fname] = fclient diff --git a/lua/lsp-toggle/window.lua b/lua/lsp-toggle/window.lua index eaee717..de930cc 100644 --- a/lua/lsp-toggle/window.lua +++ b/lua/lsp-toggle/window.lua @@ -1,9 +1,11 @@ local utils = require('lsp-toggle.utils') local M = {} + +---@type string[] M.out_buf_table = {} ----@param clients table +---@param clients table function M.print_display(clients) M.out_buf_table = {} for _, tb_server in pairs(clients) do @@ -71,10 +73,12 @@ function M.open_window() end function M.close_window() - if M.window_id then - vim.api.nvim_win_close(M.window_id, true) - M.window_id = nil + if not M.window_id then + return end + + vim.api.nvim_win_close(M.window_id, true) + M.window_id = nil end return M diff --git a/plugin/lsp-toggle.lua b/plugin/lsp-toggle.lua index 94cccd1..b5f65c0 100644 --- a/plugin/lsp-toggle.lua +++ b/plugin/lsp-toggle.lua @@ -16,8 +16,10 @@ end, { }) vim.api.nvim_create_user_command('ToggleLSPClearCache', function() - fileutils.clear_cache() - vim.notify('Cleared cache, you should probably restart nvim', vim.log.levels.WARN) + local notify = fileutils.clear_cache() + if notify then + vim.notify('Cleared cache, you should probably restart nvim', vim.log.levels.WARN) + end end, { desc = 'Clear the local cache for lsp-toggle' }) -- vim:ts=4:sts=4:sw=0:noet:ai:si:sta: From ee1469a449f86a6f9f38b5cc1a2e5fe2e687d0ad Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Fri, 12 Sep 2025 22:32:50 -0600 Subject: [PATCH 3/8] fix: module annotations included, statements improved Signed-off-by: Guennadi Maximov C --- lua/lsp-toggle/config.lua | 7 +++++-- lua/lsp-toggle/fileutils.lua | 5 ++++- lua/lsp-toggle/toggle.lua | 8 +++++--- lua/lsp-toggle/utils.lua | 1 + lua/lsp-toggle/window.lua | 1 + 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lua/lsp-toggle/config.lua b/lua/lsp-toggle/config.lua index 9289892..2ea399e 100644 --- a/lua/lsp-toggle/config.lua +++ b/lua/lsp-toggle/config.lua @@ -5,9 +5,11 @@ local utils = require('lsp-toggle.utils') ---@class LspToggle.Opts local defaults = { --- If less than `1`, this will revert back to `20` + ---@type integer max_height = 20, --- If less than `1`, this will revert back to `30` + ---@type integer max_width = 30, --- A list of LSP server names to exclude, @@ -18,11 +20,12 @@ local defaults = { ---@type string[]|'double'|'none'|'rounded'|'shadow'|'single'|'solid' border = { '╔', '-', '╗', '║', '╝', '═', '╚', '║' }, - -- Enable/Disable caching + --- Enable/Disable caching + ---@type boolean cache = true, } ----@class LspToggleConfig +---@class LspToggle.Config local M = {} ---@type LspToggle.Opts diff --git a/lua/lsp-toggle/fileutils.lua b/lua/lsp-toggle/fileutils.lua index 1824129..d3cab22 100644 --- a/lua/lsp-toggle/fileutils.lua +++ b/lua/lsp-toggle/fileutils.lua @@ -1,3 +1,4 @@ +---@class LspToggleFileUtils local M = {} M.root_dir = vim.fn.stdpath('cache') .. '/lsp-toggle' @@ -96,6 +97,7 @@ function M.load() end ---@param path? string +---@return boolean? result function M.clear_cache(path) if vim.fn.has('nvim-0.11') == 1 then vim.validate('path', path, 'string', true) @@ -130,7 +132,8 @@ function M.clear_cache(path) end end - return vim.uv.fs_rmdir(path) + local result = vim.uv.fs_rmdir(path) + return result end return M diff --git a/lua/lsp-toggle/toggle.lua b/lua/lsp-toggle/toggle.lua index fae4a8e..635da19 100644 --- a/lua/lsp-toggle/toggle.lua +++ b/lua/lsp-toggle/toggle.lua @@ -3,14 +3,16 @@ local file = require('lsp-toggle.fileutils') local window = require('lsp-toggle.window') local utils = require('lsp-toggle.utils') +---@class LspToggle.Toggle local M = {} function M.handle_toggle() local opts = require('lsp-toggle.config').options + local win = window.window_id + local bufnr = window.window_buf - local cursor_pos = vim.api.nvim_win_get_cursor(0) - local cursor_line = cursor_pos[1] - local line_text = vim.api.nvim_buf_get_lines(0, cursor_line - 1, cursor_line, false)[1] + local cursor_line = vim.api.nvim_win_get_cursor(win)[1] + local line_text = vim.api.nvim_buf_get_lines(bufnr, cursor_line - 1, cursor_line, false)[1] local server_name = line_text:sub(5) for name, tb_server in pairs(utils.clients) do diff --git a/lua/lsp-toggle/utils.lua b/lua/lsp-toggle/utils.lua index 10218e5..eb45161 100644 --- a/lua/lsp-toggle/utils.lua +++ b/lua/lsp-toggle/utils.lua @@ -4,6 +4,7 @@ local fileutils = require('lsp-toggle.fileutils') ---@field enabled boolean ---@field server_name string +---@class LspToggleUtils local M = {} ---@type table diff --git a/lua/lsp-toggle/window.lua b/lua/lsp-toggle/window.lua index de930cc..bc47a2b 100644 --- a/lua/lsp-toggle/window.lua +++ b/lua/lsp-toggle/window.lua @@ -1,5 +1,6 @@ local utils = require('lsp-toggle.utils') +---@class LspToggle.Window local M = {} ---@type string[] From ec917c485413858b57041c1953744fffb9a0facb Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Sun, 14 Sep 2025 09:40:49 -0600 Subject: [PATCH 4/8] fix(fileutils): removed recursive call Signed-off-by: Guennadi Maximov C --- lua/lsp-toggle/fileutils.lua | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/lua/lsp-toggle/fileutils.lua b/lua/lsp-toggle/fileutils.lua index d3cab22..635c3d3 100644 --- a/lua/lsp-toggle/fileutils.lua +++ b/lua/lsp-toggle/fileutils.lua @@ -38,7 +38,7 @@ end ---@return string function M.produce_path() if vim.fn.mkdir(M.root_dir, 'p') ~= 1 then - error('[File] Failed to create directory!', vim.log.levels.ERROR) + error('[FILE] Failed to create directory!', vim.log.levels.ERROR) end return string.format('%s/%s.json', M.root_dir, djb2(M.file_path)) @@ -54,16 +54,12 @@ function M.save(data) end local path = M.produce_path() - if not path then - return nil - end - local fd = vim.uv.fs_open(path, 'w', tonumber('644', 8)) if not fd then return nil end - vim.uv.fs_write(fd, vim.fn.json_encode(data)) + vim.uv.fs_write(fd, vim.fn.json_encode(data), -1) vim.uv.fs_close(fd) return true end @@ -72,10 +68,6 @@ end function M.load() -- returns lspClients local path = M.produce_path() - if not path then - return nil - end - local stat = vim.uv.fs_stat(path) if not stat then return nil @@ -87,7 +79,7 @@ function M.load() return nil end - local content = vim.uv.fs_read(fd, stat.size) + local content = vim.uv.fs_read(fd, stat.size, -1) vim.uv.fs_close(fd) if not content then return nil @@ -109,13 +101,19 @@ function M.clear_cache(path) local stat = vim.uv.fs_stat(path) if not stat or stat.type ~= 'directory' then - vim.notify('No cache to clear!', vim.log.levels.WARN) + vim.notify('[FILE] No cache to clear!', vim.log.levels.WARN) return nil end local dir = vim.uv.fs_scandir(path) + if not dir then + vim.notify('[FILE] Unable to scan directory!', vim.log.levels.ERROR) + return nil + end + + local success = true - while true do + while success do ---@type string?, 'directory'|'file'? local item, item_type = vim.uv.fs_scandir_next(dir) @@ -126,14 +124,12 @@ function M.clear_cache(path) item = path .. '/' .. item if item_type == 'file' then - vim.uv.fs_unlink(item) - elseif item_type == 'directory' then - M.clear_cache(item) + success = vim.uv.fs_unlink(item) end end - local result = vim.uv.fs_rmdir(path) - return result + success = vim.uv.fs_rmdir(path) + return success end return M From 5d03f9beece8403f05ba767928cb230d1ae603ce Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Sat, 13 Sep 2025 14:05:28 -0600 Subject: [PATCH 5/8] ci: fixed `CODEOWNERS` Signed-off-by: Guennadi Maximov C --- .github/CODEOWNERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c72eae5..3848771 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,4 @@ * @NeoSahadeo -/.github/* @DrKJeff16 -/plugin/* @DrKJeff16 -/lua/lsp-toggle/config.lua @DrKJeff16 +.github/* @DrKJeff16 +plugin/* @DrKJeff16 +lua/lsp-toggle/config.lua @DrKJeff16 From 339eb8c4603837cbb00afa9b69152dde832bf110 Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Mon, 15 Sep 2025 13:53:43 -0600 Subject: [PATCH 6/8] fix(fileutils): directory creation fix Signed-off-by: Guennadi Maximov C --- lua/lsp-toggle/fileutils.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lua/lsp-toggle/fileutils.lua b/lua/lsp-toggle/fileutils.lua index 635c3d3..24633e3 100644 --- a/lua/lsp-toggle/fileutils.lua +++ b/lua/lsp-toggle/fileutils.lua @@ -37,8 +37,11 @@ end ---@return string function M.produce_path() - if vim.fn.mkdir(M.root_dir, 'p') ~= 1 then - error('[FILE] Failed to create directory!', vim.log.levels.ERROR) + if not vim.fn.isdirectory(M.root_dir) then + local dir_fd = vim.uv.fs_mkdir(M.root_dir, tonumber('755', 8)) + if not dir_fd then + error('[FILE] Failed to create directory!', vim.log.levels.ERROR) + end end return string.format('%s/%s.json', M.root_dir, djb2(M.file_path)) From c3943e14ad8b23dcd9c8f41722dc06139cdac5db Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Mon, 15 Sep 2025 14:03:01 -0600 Subject: [PATCH 7/8] fix!: cache wasn't working Signed-off-by: Guennadi Maximov C --- lua/lsp-toggle/config.lua | 3 ++- lua/lsp-toggle/fileutils.lua | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lua/lsp-toggle/config.lua b/lua/lsp-toggle/config.lua index 2ea399e..d2012d5 100644 --- a/lua/lsp-toggle/config.lua +++ b/lua/lsp-toggle/config.lua @@ -81,7 +81,8 @@ function M.setup_autocmds() callback = callback, }) - vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWinEnter' }, { + vim.api.nvim_create_autocmd('BufEnter', { + group = augroup, callback = callback, }) diff --git a/lua/lsp-toggle/fileutils.lua b/lua/lsp-toggle/fileutils.lua index 24633e3..0cbb15f 100644 --- a/lua/lsp-toggle/fileutils.lua +++ b/lua/lsp-toggle/fileutils.lua @@ -24,15 +24,15 @@ local function djb2(str) return tostring(hash) end ----@param path string +---@param path? string function M.set_file_path(path) if vim.fn.has('nvim-0.11') == 1 then - vim.validate('path', path, 'string', false) + vim.validate('path', path, 'string', true) else - vim.validate({ path = { path, 'string' } }) + vim.validate({ path = { path, { 'string', 'nil', } } }) end - M.file_path = path + M.file_path = path or M.file_path end ---@return string From ea9d269cc5ecc56be14fb06d6bfea52e282599ac Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Mon, 15 Sep 2025 14:04:34 -0600 Subject: [PATCH 8/8] chore: format with StyLua Signed-off-by: Guennadi Maximov C --- lua/lsp-toggle/fileutils.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/lsp-toggle/fileutils.lua b/lua/lsp-toggle/fileutils.lua index 0cbb15f..22ab0b5 100644 --- a/lua/lsp-toggle/fileutils.lua +++ b/lua/lsp-toggle/fileutils.lua @@ -29,7 +29,7 @@ function M.set_file_path(path) if vim.fn.has('nvim-0.11') == 1 then vim.validate('path', path, 'string', true) else - vim.validate({ path = { path, { 'string', 'nil', } } }) + vim.validate({ path = { path, { 'string', 'nil' } } }) end M.file_path = path or M.file_path