summaryrefslogtreecommitdiff
path: root/.config/nvim
diff options
context:
space:
mode:
Diffstat (limited to '.config/nvim')
-rw-r--r--.config/nvim/.gitignore1
-rw-r--r--.config/nvim/lua/bootstrap.lua29
-rw-r--r--.config/nvim/lua/core/autopairs.lua17
-rw-r--r--.config/nvim/lua/core/cmp.lua170
-rw-r--r--.config/nvim/lua/core/commands.lua3
-rw-r--r--.config/nvim/lua/core/info.lua6
-rw-r--r--.config/nvim/lua/core/nvimtree.lua4
-rw-r--r--.config/nvim/lua/core/telescope.lua20
-rw-r--r--.config/nvim/lua/core/which-key.lua3
-rw-r--r--.config/nvim/lua/lsp/config.lua1
-rw-r--r--.config/nvim/lua/lsp/init.lua23
-rw-r--r--.config/nvim/lua/lsp/manager.lua87
-rw-r--r--.config/nvim/lua/lsp/null-ls/formatters.lua19
-rw-r--r--.config/nvim/lua/lsp/null-ls/init.lua16
-rw-r--r--.config/nvim/lua/lsp/null-ls/linters.lua19
-rw-r--r--.config/nvim/lua/lsp/null-ls/services.lua4
-rw-r--r--.config/nvim/lua/lsp/providers/jsonls.lua12
-rw-r--r--.config/nvim/lua/lsp/templates.lua2
-rw-r--r--.config/nvim/lua/lsp/utils.lua26
-rw-r--r--.config/nvim/lua/plugins.lua1
-rw-r--r--.config/nvim/lua/utils/hooks.lua33
-rw-r--r--.config/nvim/lua/utils/table.lua24
22 files changed, 361 insertions, 159 deletions
diff --git a/.config/nvim/.gitignore b/.config/nvim/.gitignore
index b56e0fb..002933c 100644
--- a/.config/nvim/.gitignore
+++ b/.config/nvim/.gitignore
@@ -9,3 +9,4 @@ session
wiki/
pack/
lua-language-server/
+site/
diff --git a/.config/nvim/lua/bootstrap.lua b/.config/nvim/lua/bootstrap.lua
index e8794d6..20cf26f 100644
--- a/.config/nvim/lua/bootstrap.lua
+++ b/.config/nvim/lua/bootstrap.lua
@@ -1,6 +1,7 @@
local M = {}
-local in_headless = #vim.api.nvim_list_uis() == 0
+package.loaded["utils.hooks"] = nil
+local _, hooks = pcall(require, "utils.hooks")
---Join path segments that were passed as input
---@return string
@@ -71,16 +72,9 @@ end
---Update LunarVim
---pulls the latest changes from github and, resets the startup cache
function M:update()
+ hooks.run_pre_update()
M:update_repo()
- M:reset_cache()
- require("lsp.templates").generate_templates()
- if not in_headless then
- vim.schedule(function()
- require("packer").install()
- -- TODO: add a changelog
- vim.notify("Update complete", vim.log.levels.INFO)
- end)
- end
+ hooks.run_post_update()
end
local function git_cmd(subcmd)
@@ -125,7 +119,8 @@ function M:update_repo()
local ret = git_cmd(sub_commands.fetch)
if ret ~= 0 then
- error "Update failed! Check the log for further information"
+ Log:error "Update failed! Check the log for further information"
+ return
end
ret = git_cmd(sub_commands.diff)
@@ -138,17 +133,9 @@ function M:update_repo()
ret = git_cmd(sub_commands.merge)
if ret ~= 0 then
- error "Error: unable to guarantee data integrity while updating your branch"
- error "Please pull the changes manually instead."
+ Log:error "Update failed! Please pull the changes manually instead."
+ return
end
end
----Reset any startup cache files used by Packer and Impatient
----Tip: Useful for clearing any outdated settings
-function M:reset_cache()
- _G.__luacache.clear_cache()
- _G.__luacache.save_cache()
- require("plugin-loader"):cache_reset()
-end
-
return M
diff --git a/.config/nvim/lua/core/autopairs.lua b/.config/nvim/lua/core/autopairs.lua
index 0c9ec28..630f3de 100644
--- a/.config/nvim/lua/core/autopairs.lua
+++ b/.config/nvim/lua/core/autopairs.lua
@@ -4,14 +4,8 @@ function M.config()
options.builtin.autopairs = {
active = true,
on_config_done = nil,
- ---@usage map <CR> on insert mode
- map_cr = true,
---@usage auto insert after select function or method item
map_complete = true,
- ---@usage automatically select the first item
- auto_select = true,
- ---@usage use insert confirm behavior instead of replace
- insert = false,
---@usage -- modifies the function or method delimiter by filetypes
map_char = {
all = "(",
@@ -60,12 +54,17 @@ M.setup = function()
if package.loaded["cmp"] then
require("nvim-autopairs.completion.cmp").setup {
- map_cr = options.builtin.autopairs.map_cr,
+ map_cr = false,
map_complete = options.builtin.autopairs.map_complete,
- auto_select = options.builtin.autopairs.auto_select,
- insert = options.builtin.autopairs.insert,
map_char = options.builtin.autopairs.map_char,
}
+ -- we map CR explicitly in cmp.lua but we still need to setup the autopairs CR keymap
+ vim.api.nvim_set_keymap(
+ "i",
+ "<CR>",
+ "v:lua.MPairs.autopairs_cr()",
+ { expr = true, noremap = true }
+ )
end
require("nvim-treesitter.configs").setup { autopairs = { enable = true } }
diff --git a/.config/nvim/lua/core/cmp.lua b/.config/nvim/lua/core/cmp.lua
index f9f2d01..fd9e96c 100644
--- a/.config/nvim/lua/core/cmp.lua
+++ b/.config/nvim/lua/core/cmp.lua
@@ -29,10 +29,109 @@ M.config = function()
if not status_luasnip_ok then
return
end
+ local win_get_cursor = vim.api.nvim_win_get_cursor
+ local get_current_buf = vim.api.nvim_get_current_buf
+
+ local function inside_snippet()
+ -- for outdated versions of luasnip
+ if not luasnip.session.current_nodes then
+ return false
+ end
+
+ local node = luasnip.session.current_nodes[get_current_buf()]
+ if not node then
+ return false
+ end
+
+ local snip_begin_pos, snip_end_pos = node.parent.snippet.mark:pos_begin_end()
+ local pos = win_get_cursor(0)
+ pos[1] = pos[1] - 1 -- LuaSnip is 0-based not 1-based like nvim for rows
+ return pos[1] >= snip_begin_pos[1] and pos[1] <= snip_end_pos[1]
+ end
+
+ ---sets the current buffer's luasnip to the one nearest the cursor
+ ---@return boolean true if a node is found, false otherwise
+ local function seek_luasnip_cursor_node()
+ -- for outdated versions of luasnip
+ if not luasnip.session.current_nodes then
+ return false
+ end
+
+ local pos = win_get_cursor(0)
+ pos[1] = pos[1] - 1
+ local node = luasnip.session.current_nodes[get_current_buf()]
+ if not node then
+ return false
+ end
+
+ local snippet = node.parent.snippet
+ local exit_node = snippet.insert_nodes[0]
+
+ -- exit early if we're past the exit node
+ if exit_node then
+ local exit_pos_end = exit_node.mark:pos_end()
+ if
+ (pos[1] > exit_pos_end[1])
+ or (pos[1] == exit_pos_end[1] and pos[2] > exit_pos_end[2])
+ then
+ snippet:remove_from_jumplist()
+ luasnip.session.current_nodes[get_current_buf()] = nil
+
+ return false
+ end
+ end
+
+ node = snippet.inner_first:jump_into(1, true)
+ while node ~= nil and node.next ~= nil and node ~= snippet do
+ local n_next = node.next
+ local next_pos = n_next and n_next.mark:pos_begin()
+ local candidate = n_next ~= snippet and next_pos and (pos[1] < next_pos[1])
+ or (pos[1] == next_pos[1] and pos[2] < next_pos[2])
+
+ -- Past unmarked exit node, exit early
+ if n_next == nil or n_next == snippet.next then
+ snippet:remove_from_jumplist()
+ luasnip.session.current_nodes[get_current_buf()] = nil
+
+ return false
+ end
+
+ if candidate then
+ luasnip.session.current_nodes[get_current_buf()] = node
+ return true
+ end
+
+ local ok
+ ok, node = pcall(node.jump_from, node, 1, true) -- no_move until last stop
+ if not ok then
+ snippet:remove_from_jumplist()
+ luasnip.session.current_nodes[get_current_buf()] = nil
+
+ return false
+ end
+ end
+
+ -- No candidate, but have an exit node
+ if exit_node then
+ -- to jump to the exit node, seek to snippet
+ luasnip.session.current_nodes[get_current_buf()] = snippet
+ return true
+ end
+
+ -- No exit node, exit from snippet
+ snippet:remove_from_jumplist()
+ luasnip.session.current_nodes[get_current_buf()] = nil
+ return false
+ end
+
options.builtin.cmp = {
confirm_opts = {
behavior = cmp.ConfirmBehavior.Replace,
- select = true,
+ select = false,
+ },
+ experimental = {
+ ghost_text = true,
+ native_menu = false,
},
formatting = {
kind_icons = {
@@ -62,23 +161,28 @@ M.config = function()
Value = " ",
Variable = " ",
},
+ source_names = {
+ nvim_lsp = "(LSP)",
+ emoji = "(Emoji)",
+ path = "(Path)",
+ calc = "(Calc)",
+ cmp_tabnine = "(Tabnine)",
+ vsnip = "(Snippet)",
+ luasnip = "(Snippet)",
+ buffer = "(Buffer)",
+ },
+ duplicates = {
+ buffer = 1,
+ path = 1,
+ nvim_lsp = 0,
+ luasnip = 1,
+ },
+ duplicates_default = 0,
format = function(entry, vim_item)
vim_item.kind = options.builtin.cmp.formatting.kind_icons[vim_item.kind]
- vim_item.menu = ({
- nvim_lsp = "(LSP)",
- emoji = "(Emoji)",
- path = "(Path)",
- calc = "(Calc)",
- cmp_tabnine = "(Tabnine)",
- vsnip = "(Snippet)",
- luasnip = "(Snippet)",
- buffer = "(Buffer)",
- })[entry.source.name]
- vim_item.dup = ({
- buffer = 1,
- path = 1,
- nvim_lsp = 0,
- })[entry.source.name] or 0
+ vim_item.menu = options.builtin.cmp.formatting.source_names[entry.source.name]
+ vim_item.dup = options.builtin.cmp.formatting.duplicates[entry.source.name]
+ or options.builtin.cmp.formatting.duplicates_default
return vim_item
end,
},
@@ -107,10 +211,16 @@ M.config = function()
["<C-f>"] = cmp.mapping.scroll_docs(4),
-- TODO: potentially fix emmet nonsense
["<Tab>"] = cmp.mapping(function()
- if vim.fn.pumvisible() == 1 then
- vim.fn.feedkeys(T "<down>", "n")
- elseif luasnip.expand_or_jumpable() then
- vim.fn.feedkeys(T "<Plug>luasnip-expand-or-jump", "")
+ if cmp.visible() then
+ cmp.select_next_item()
+ elseif luasnip.expandable() then
+ luasnip.expand()
+ elseif
+ inside_snippet()
+ and seek_luasnip_cursor_node()
+ and luasnip.jumpable()
+ then
+ luasnip.jump(1)
elseif check_backspace() then
vim.fn.feedkeys(T "<Tab>", "n")
elseif is_emmet_active() then
@@ -123,10 +233,10 @@ M.config = function()
"s",
}),
["<S-Tab>"] = cmp.mapping(function(fallback)
- if vim.fn.pumvisible() == 1 then
- vim.fn.feedkeys(T "<up>", "n")
- elseif luasnip.jumpable(-1) then
- vim.fn.feedkeys(T "<Plug>luasnip-jump-prev", "")
+ if cmp.visible() then
+ cmp.select_prev_item()
+ elseif inside_snippet() and luasnip.jumpable(-1) then
+ luasnip.jump(-1)
else
fallback()
end
@@ -138,12 +248,16 @@ M.config = function()
["<C-Space>"] = cmp.mapping.complete(),
["<C-e>"] = cmp.mapping.close(),
["<CR>"] = cmp.mapping(function(fallback)
- if not require("cmp").confirm(options.builtin.cmp.confirm_opts) then
- if luasnip.jumpable() then
- vim.fn.feedkeys(T "<Plug>luasnip-jump-next", "")
- else
+ if cmp.visible() and cmp.confirm(options.builtin.cmp.confirm_opts) then
+ return
+ end
+
+ if inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable() then
+ if not luasnip.jump(1) then
fallback()
end
+ else
+ fallback()
end
end),
},
diff --git a/.config/nvim/lua/core/commands.lua b/.config/nvim/lua/core/commands.lua
index 34033d4..8a56c40 100644
--- a/.config/nvim/lua/core/commands.lua
+++ b/.config/nvim/lua/core/commands.lua
@@ -10,7 +10,8 @@ M.defaults = {
endif
endfunction
]],
- [[command! NvimInfo lua require('core.info').toggle_popup(vim.bo.filetype)]],
+ [[ command! NvimInfo lua require('core.info').toggle_popup(vim.bo.filetype) ]],
+ [[ command! NvimCacheReset lua require('utils.hooks').reset_cache() ]],
}
M.load = function(commands)
diff --git a/.config/nvim/lua/core/info.lua b/.config/nvim/lua/core/info.lua
index bb53644..cf4387e 100644
--- a/.config/nvim/lua/core/info.lua
+++ b/.config/nvim/lua/core/info.lua
@@ -11,6 +11,7 @@ local M = {
local fmt = string.format
local text = require "interface.text"
+local lsp_utils = require "lsp.utils"
local function str_list(list)
return fmt("[ %s ]", table.concat(list, ", "))
@@ -75,7 +76,7 @@ local function tbl_set_highlight(terms, highlight_group)
end
local function make_client_info(client)
- local client_enabled_caps = require("lsp.utils").get_ls_capabilities(client.id)
+ local client_enabled_caps = lsp_utils.get_client_capabilities(client.id)
local name = client.name
local id = client.id
local document_formatting = client.resolved_capabilities.document_formatting
@@ -97,8 +98,7 @@ local function make_client_info(client)
end
function M.toggle_popup(ft)
- local lsp_utils = require "lsp.utils"
- local clients = lsp_utils.get_active_client_by_ft(ft)
+ local clients = lsp_utils.get_active_clients_by_ft(ft)
local client_names = {}
local header = {
diff --git a/.config/nvim/lua/core/nvimtree.lua b/.config/nvim/lua/core/nvimtree.lua
index ff8db15..86554ab 100644
--- a/.config/nvim/lua/core/nvimtree.lua
+++ b/.config/nvim/lua/core/nvimtree.lua
@@ -6,9 +6,9 @@ function M.config()
active = true,
on_config_done = nil,
setup = {
- auto_open = 0,
+ open_on_setup = 0,
auto_close = 1,
- tab_open = 0,
+ open_on_tab = 0,
update_focused_file = {
enable = 1,
},
diff --git a/.config/nvim/lua/core/telescope.lua b/.config/nvim/lua/core/telescope.lua
index d394884..108b6f3 100644
--- a/.config/nvim/lua/core/telescope.lua
+++ b/.config/nvim/lua/core/telescope.lua
@@ -91,6 +91,26 @@ function M.config()
})
end
+function M.code_actions()
+ local opts = {
+ winblend = 15,
+ layout_config = {
+ prompt_position = "top",
+ width = 80,
+ height = 12,
+ },
+ borderchars = {
+ prompt = { "─", "│", " ", "│", "╭", "╮", "│", "│" },
+ results = { "─", "│", "─", "│", "├", "┤", "╯", "╰" },
+ preview = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" },
+ },
+ border = {},
+ previewer = false,
+ shorten_path = false,
+ }
+ require("telescope.builtin").lsp_code_actions(require("telescope.themes").get_dropdown(opts))
+end
+
function M.setup()
local telescope = require "telescope"
diff --git a/.config/nvim/lua/core/which-key.lua b/.config/nvim/lua/core/which-key.lua
index db67055..dca1d77 100644
--- a/.config/nvim/lua/core/which-key.lua
+++ b/.config/nvim/lua/core/which-key.lua
@@ -139,7 +139,7 @@ M.config = function()
l = {
name = "LSP",
- a = { "<cmd>lua vim.lsp.buf.code_action()<cr>", "Code Action" },
+ a = { "<cmd>lua require('core.telescope').code_actions()<cr>", "Code Action" },
d = {
"<cmd>Telescope lsp_document_diagnostics<cr>",
"Document Diagnostics",
@@ -159,6 +159,7 @@ M.config = function()
"<cmd>lua vim.lsp.diagnostic.goto_prev({popup_opts = {border = options.lsp.popup_border}})<cr>",
"Prev Diagnostic",
},
+ l = { "<cmd>lua vim.lsp.codelens.run()<cr>", "CodeLens Action" },
p = {
name = "Peek",
d = { "<cmd>lua require('lsp.peek').Peek('definition')<cr>", "Definition" },
diff --git a/.config/nvim/lua/lsp/config.lua b/.config/nvim/lua/lsp/config.lua
index 32185b5..f13d965 100644
--- a/.config/nvim/lua/lsp/config.lua
+++ b/.config/nvim/lua/lsp/config.lua
@@ -17,6 +17,7 @@ return {
},
override = {},
document_highlight = true,
+ code_lens_refresh = true,
popup_border = "single",
on_attach_callback = nil,
on_init_callback = nil,
diff --git a/.config/nvim/lua/lsp/init.lua b/.config/nvim/lua/lsp/init.lua
index e3967df..f421d99 100644
--- a/.config/nvim/lua/lsp/init.lua
+++ b/.config/nvim/lua/lsp/init.lua
@@ -21,6 +21,25 @@ local function lsp_highlight_document(client)
end
end
+local function lsp_code_lens_refresh(client)
+ if options.lsp.code_lens_refresh == false then
+ return
+ end
+
+ if client.resolved_capabilities.code_lens then
+ vim.api.nvim_exec(
+ [[
+ augroup lsp_code_lens_refresh
+ autocmd! * <buffer>
+ autocmd InsertLeave <buffer> lua vim.lsp.codelens.refresh()
+ autocmd InsertLeave <buffer> lua vim.lsp.codelens.display()
+ augroup END
+ ]],
+ false
+ )
+ end
+end
+
local function add_lsp_buffer_keybindings(bufnr)
local mappings = {
normal_mode = "n",
@@ -75,11 +94,10 @@ local function select_default_formater(client)
Log:debug("Checking for formatter overriding for " .. client.name)
local client_filetypes = client.config.filetypes or {}
for _, filetype in ipairs(client_filetypes) do
- if not vim.tbl_isempty(options.lang[filetype].formatters) then
+ if options.lang[filetype] and #vim.tbl_keys(options.lang[filetype].formatters) > 0 then
Log:debug("Formatter overriding detected. Disabling formatting capabilities for " .. client.name)
client.resolved_capabilities.document_formatting = false
client.resolved_capabilities.document_range_formatting = false
- return
end
end
end
@@ -99,6 +117,7 @@ function M.common_on_attach(client, bufnr)
Log:debug "Called lsp.on_attach_callback"
end
lsp_highlight_document(client)
+ lsp_code_lens_refresh(client)
add_lsp_buffer_keybindings(bufnr)
end
diff --git a/.config/nvim/lua/lsp/manager.lua b/.config/nvim/lua/lsp/manager.lua
index 49771b2..a7d6892 100644
--- a/.config/nvim/lua/lsp/manager.lua
+++ b/.config/nvim/lua/lsp/manager.lua
@@ -24,32 +24,12 @@ local function is_overridden(server)
end
end
-function M.setup_server(server_name)
- vim.validate {
- name = { server_name, "string" },
- }
-
- if lsp_utils.is_client_active(server_name) or is_overridden(server_name) then
- return
- end
-
- local lsp_installer_servers = require "nvim-lsp-installer.servers"
- local server_available, requested_server = lsp_installer_servers.get_server(
- server_name
- )
- if server_available then
- if not requested_server:is_installed() then
- Log:debug(string.format("[%s] is not installed", server_name))
- if options.lsp.automatic_servers_installation then
- Log:debug(string.format("Installing [%s]", server_name))
- requested_server:install()
- else
- return
- end
- end
- end
-
- local default_config = {
+---Resolve the configuration for a server based on both common and user configuration
+---@param name string
+---@param user_config table [optional]
+---@return table
+local function resolve_config(name, user_config)
+ local config = {
on_attach = require("lsp").common_on_attach,
on_init = require("lsp").common_on_init,
capabilities = require("lsp").common_capabilities(),
@@ -57,35 +37,52 @@ function M.setup_server(server_name)
local status_ok, custom_config = pcall(
require,
- "lsp/providers/" .. requested_server.name
+ "lsp/providers/" .. name
)
if status_ok then
- local new_config = vim.tbl_deep_extend("force", default_config, custom_config)
- Log:debug(
- "Using custom configuration for requested server: " .. requested_server.name
- )
- requested_server:setup(new_config)
- else
- Log:debug(
- "Using the default configuration for requested server: " .. requested_server.name
- )
- requested_server:setup(default_config)
+ Log:debug("Using custom configuration for requested server: " .. name)
+ config = vim.tbl_deep_extend("force", config, custom_config)
end
+
+ if user_config then
+ config = vim.tbl_deep_extend("force", config, user_config)
+ end
+
+ return config
end
-function M.setup(servers)
- local status_ok, _ = pcall(require, "nvim-lsp-installer")
- if not status_ok then
+---Setup a language server by providing a name
+---@param server_name string name of the language server
+---@param user_config table [optional] when available it will take predence over any default configurations
+function M.setup(server_name, user_config)
+ vim.validate { name = { server_name, "string" } }
+
+ if lsp_utils.is_client_active(server_name) or is_overridden(server_name) then
return
end
- --- allow using a single value
- if type(servers) == "string" then
- servers = { servers }
+ local config = resolve_config(server_name, user_config)
+ local server_available, requested_server = require("nvim-lsp-installer.servers").get_server(server_name)
+
+ local function ensure_installed(server)
+ if server:is_installed() then
+ return true
+ end
+ if not lvim.lsp.automatic_servers_installation then
+ Log:debug(server.name .. " is not managed by the automatic installer")
+ return false
+ end
+ Log:debug(string.format("Installing [%s]", server.name))
+ server:install()
+ vim.schedule(function()
+ vim.cmd [[LspStart]]
+ end)
end
- for _, server in ipairs(servers) do
- M.setup_server(server)
+ if server_available and ensure_installed(requested_server) then
+ requested_server:setup(config)
+ else
+ require("lspconfig")[server_name].setup(config)
end
end
diff --git a/.config/nvim/lua/lsp/null-ls/formatters.lua b/.config/nvim/lua/lsp/null-ls/formatters.lua
index 0d3505f..577a0d9 100644
--- a/.config/nvim/lua/lsp/null-ls/formatters.lua
+++ b/.config/nvim/lua/lsp/null-ls/formatters.lua
@@ -13,9 +13,13 @@ end
function M.list_available(filetype)
local formatters = {}
+ local tbl = require "utils.table"
for _, provider in pairs(null_ls.builtins.formatting) do
- -- TODO: Add support for wildcard filetypes
- if vim.tbl_contains(provider.filetypes or {}, filetype) then
+ if
+ tbl.contains(provider.filetypes or {}, function(ft)
+ return ft == "*" or ft == filetype
+ end)
+ then
table.insert(formatters, provider.name)
end
end
@@ -27,7 +31,8 @@ function M.list_configured(formatter_configs)
local formatters, errors = {}, {}
for _, fmt_config in ipairs(formatter_configs) do
- local formatter = null_ls.builtins.formatting[fmt_config.exe]
+ local formatter_name = fmt_config.exe:gsub("-", "_")
+ local formatter = null_ls.builtins.formatting[formatter_name]
if not formatter then
Log:error("Not a valid formatter: " .. fmt_config.exe)
@@ -42,6 +47,7 @@ function M.list_configured(formatter_configs)
formatters[fmt_config.exe] = formatter.with {
command = formatter_cmd,
extra_args = fmt_config.args,
+ filetypes = fmt_config.filetypes,
}
end
end
@@ -50,14 +56,13 @@ function M.list_configured(formatter_configs)
return { supported = formatters, unsupported = errors }
end
-function M.setup(formatter_configs, filetype)
+function M.setup(formatter_configs)
if vim.tbl_isempty(formatter_configs) then
return
end
- local formatters_by_ft = {}
- formatters_by_ft[filetype] = M.list_configured(formatter_configs)
- null_ls.register { sources = formatters_by_ft[filetype].supported }
+ local formatters_by_ft = M.list_configured(formatter_configs)
+ null_ls.register { sources = formatters_by_ft.supported }
end
return M
diff --git a/.config/nvim/lua/lsp/null-ls/init.lua b/.config/nvim/lua/lsp/null-ls/init.lua
index 571fb6b..fde9fed 100644
--- a/.config/nvim/lua/lsp/null-ls/init.lua
+++ b/.config/nvim/lua/lsp/null-ls/init.lua
@@ -13,12 +13,18 @@ function M:setup()
null_ls.config()
require("lspconfig")["null-ls"].setup(options.lsp.null_ls.setup)
- for _, filetype in pairs(options.lang) do
- if filetype.formatters then
- formatters.setup(filetype.formatters, filetype)
+ for filetype, config in pairs(options.lang) do
+ if not vim.tbl_isempty(config.formatters) then
+ vim.tbl_map(function(c)
+ c.filetypes = { filetype }
+ end, config.formatters)
+ formatters.setup(config.formatters)
end
- if filetype.linters then
- linters.setup(filetype.linters, filetype)
+ if not vim.tbl_isempty(config.linters) then
+ vim.tbl_map(function(c)
+ c.filetypes = { filetype }
+ end, config.formatters)
+ linters.setup(config.linters)
end
end
end
diff --git a/.config/nvim/lua/lsp/null-ls/linters.lua b/.config/nvim/lua/lsp/null-ls/linters.lua
index e9e92e9..3f834ba 100644
--- a/.config/nvim/lua/lsp/null-ls/linters.lua
+++ b/.config/nvim/lua/lsp/null-ls/linters.lua
@@ -13,9 +13,13 @@ end
function M.list_available(filetype)
local linters = {}
+ local tbl = require "utils.table"
for _, provider in pairs(null_ls.builtins.diagnostics) do
- -- TODO: Add support for wildcard filetypes
- if vim.tbl_contains(provider.filetypes or {}, filetype) then
+ if
+ tbl.contains(provider.filetypes or {}, function(ft)
+ return ft == "*" or ft == filetype
+ end)
+ then
table.insert(linters, provider.name)
end
end
@@ -27,7 +31,8 @@ function M.list_configured(linter_configs)
local linters, errors = {}, {}
for _, lnt_config in pairs(linter_configs) do
- local linter = null_ls.builtins.diagnostics[lnt_config.exe]
+ local linter_name = lnt_config.exe:gsub("-", "_")
+ local linter = null_ls.builtins.diagnostics[linter_name]
if not linter then
Log:error("Not a valid linter: " .. lnt_config.exe)
@@ -42,6 +47,7 @@ function M.list_configured(linter_configs)
linters[lnt_config.exe] = linter.with {
command = linter_cmd,
extra_args = lnt_config.args,
+ filetypes = lnt_config.filetypes,
}
end
end
@@ -50,14 +56,13 @@ function M.list_configured(linter_configs)
return { supported = linters, unsupported = errors }
end
-function M.setup(linter_configs, filetype)
+function M.setup(linter_configs)
if vim.tbl_isempty(linter_configs) then
return
end
- local linters_by_ft = {}
- linters_by_ft[filetype] = M.list_configured(linter_configs)
- null_ls.register { sources = linters_by_ft[filetype].supported }
+ local linters = M.list_configured(linter_configs)
+ null_ls.register { sources = linters.supported }
end
return M
diff --git a/.config/nvim/lua/lsp/null-ls/services.lua b/.config/nvim/lua/lsp/null-ls/services.lua
index c62fc70..ef9e7d2 100644
--- a/.config/nvim/lua/lsp/null-ls/services.lua
+++ b/.config/nvim/lua/lsp/null-ls/services.lua
@@ -4,8 +4,8 @@ local function find_root_dir()
local util = require "lspconfig/util"
local lsp_utils = require "lsp.utils"
- local status_ok, ts_client = lsp_utils.is_client_active "typescript"
- if status_ok then
+ local ts_client = lsp_utils.is_client_active "typescript"
+ if ts_client then
return ts_client.config.root_dir
end
local dirname = vim.fn.expand "%:p:h"
diff --git a/.config/nvim/lua/lsp/providers/jsonls.lua b/.config/nvim/lua/lsp/providers/jsonls.lua
index 70ad7e1..e81b2c3 100644
--- a/.config/nvim/lua/lsp/providers/jsonls.lua
+++ b/.config/nvim/lua/lsp/providers/jsonls.lua
@@ -184,11 +184,13 @@ local opts = {
schemas = extended_schemas,
},
},
- commands = {
- Format = {
- function()
- vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line "$", 0 })
- end,
+ setup = {
+ commands = {
+ Format = {
+ function()
+ vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line "$", 0 })
+ end,
+ },
},
},
}
diff --git a/.config/nvim/lua/lsp/templates.lua b/.config/nvim/lua/lsp/templates.lua
index 004187e..2cce567 100644
--- a/.config/nvim/lua/lsp/templates.lua
+++ b/.config/nvim/lua/lsp/templates.lua
@@ -23,7 +23,7 @@ function M.is_ignored(server_name, filetypes)
filetypes = filetypes or get_supported_filetypes(server_name)
if vim.tbl_contains(filetypes, "javascript") then
- if server_name == "tsserver" or server_name == "tailwindcss" then
+ if server_name == "tsserver" then
return false
else
return true
diff --git a/.config/nvim/lua/lsp/utils.lua b/.config/nvim/lua/lsp/utils.lua
index e0046db..5900340 100644
--- a/.config/nvim/lua/lsp/utils.lua
+++ b/.config/nvim/lua/lsp/utils.lua
@@ -1,27 +1,15 @@
local M = {}
+local tbl = require "utils.table"
+
function M.is_client_active(name)
local clients = vim.lsp.get_active_clients()
- for _, client in pairs(clients) do
- if client.name == name then
- return true, client
- end
- end
- return false
-end
-
-function M.disable_formatting_capability(client)
- -- FIXME: figure out a reasonable way to do this
- client.resolved_capabilities.document_formatting = false
- require("core.log"):debug(
- string.format(
- "Turning off formatting capability for language server [%s] ",
- client.name
- )
- )
+ return tbl.find_first(clients, function(client)
+ return client.name == name
+ end)
end
-function M.get_active_client_by_ft(filetype)
+function M.get_active_clients_by_ft(filetype)
local matches = {}
local clients = vim.lsp.get_active_clients()
for _, client in pairs(clients) do
@@ -33,7 +21,7 @@ function M.get_active_client_by_ft(filetype)
return matches
end
-function M.get_ls_capabilities(client_id)
+function M.get_client_capabilities(client_id)
if not client_id then
local buf_clients = vim.lsp.buf_get_clients()
for _, buf_client in ipairs(buf_clients) do
diff --git a/.config/nvim/lua/plugins.lua b/.config/nvim/lua/plugins.lua
index 99a9cfa..372f7f7 100644
--- a/.config/nvim/lua/plugins.lua
+++ b/.config/nvim/lua/plugins.lua
@@ -50,7 +50,6 @@ return {
{
"windwp/nvim-autopairs",
-- event = "InsertEnter",
- after = "nvim-cmp",
config = function()
require("core.autopairs").setup()
end,
diff --git a/.config/nvim/lua/utils/hooks.lua b/.config/nvim/lua/utils/hooks.lua
new file mode 100644
index 0000000..fa667cf
--- /dev/null
+++ b/.config/nvim/lua/utils/hooks.lua
@@ -0,0 +1,33 @@
+local M = {}
+
+local Log = require "core.log"
+local in_headless = #vim.api.nvim_list_uis() == 0
+
+function M.run_pre_update()
+ Log:debug "Starting pre-update hook"
+end
+
+---Reset any startup cache files used by Packer and Impatient
+---Tip: Useful for clearing any outdated settings
+function M.reset_cache()
+ _G.__luacache.clear_cache()
+ require("plugin-loader"):cache_reset()
+end
+
+function M.run_post_update()
+ M.reset_cache()
+ Log:debug "Starting post-update hook"
+ package.loaded["lsp.templates"] = nil
+ require("lsp.templates").generate_templates()
+
+ if not in_headless then
+ vim.schedule(function()
+ require("packer").install()
+ -- TODO: add a changelog
+ vim.notify("Update complete", vim.log.levels.INFO)
+ vim.cmd "LspStart"
+ end)
+ end
+end
+
+return M
diff --git a/.config/nvim/lua/utils/table.lua b/.config/nvim/lua/utils/table.lua
new file mode 100644
index 0000000..1ac5949
--- /dev/null
+++ b/.config/nvim/lua/utils/table.lua
@@ -0,0 +1,24 @@
+local Table = {}
+
+--- Find the first entry for which the predicate returns true.
+-- @param t The table
+-- @param predicate The function called for each entry of t
+-- @return The entry for which the predicate returned True or nil
+function Table.find_first(t, predicate)
+ for _, entry in pairs(t) do
+ if predicate(entry) then
+ return entry
+ end
+ end
+ return nil
+end
+
+--- Check if the predicate returns True for at least one entry of the table.
+-- @param t The table
+-- @param predicate The function called for each entry of t
+-- @return True if predicate returned True at least once, false otherwise
+function Table.contains(t, predicate)
+ return Table.find_first(t, predicate) ~= nil
+end
+
+return Table