diff options
Diffstat (limited to 'mac/.config/LunarVim/lua/lvim/lsp')
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/config.lua | 164 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/init.lua | 128 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/manager.lua | 141 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/null-ls/code_actions.lua | 26 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/null-ls/formatters.lua | 33 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/null-ls/init.lua | 16 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/null-ls/linters.lua | 43 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/null-ls/services.lua | 104 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/providers/jsonls.lua | 18 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/providers/lua_ls.lua | 64 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/providers/tailwindcss.lua | 15 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/providers/vuels.lua | 26 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/providers/yamlls.lua | 16 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/templates.lua | 76 | ||||
| -rw-r--r-- | mac/.config/LunarVim/lua/lvim/lsp/utils.lua | 185 |
15 files changed, 1055 insertions, 0 deletions
diff --git a/mac/.config/LunarVim/lua/lvim/lsp/config.lua b/mac/.config/LunarVim/lua/lvim/lsp/config.lua new file mode 100644 index 0000000..55f7d64 --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/config.lua @@ -0,0 +1,164 @@ +local skipped_servers = { + "angularls", + "ansiblels", + "antlersls", + "ast_grep", + "azure_pipelines_ls", + "basedpyright", + "biome", + "bzl", + "ccls", + "css_variables", + "cssmodules_ls", + "custom_elements_ls", + "denols", + "docker_compose_language_service", + "dprint", + "elp", + "ember", + "emmet_language_server", + "emmet_ls", + "eslint", + "eslintls", + "fennel_language_server", + "gitlab_ci_ls", + "glint", + "glslls", + "golangci_lint_ls", + "gradle_ls", + "graphql", + "harper_ls", + "hdl_checker", + "hydra_lsp", + "htmx", + "java_language_server", + "jedi_language_server", + "lexical", + "ltex", + "lwc_ls", + "mdx_analyzer", + "neocmake", + "nim_langserver", + "ocamlls", + "omnisharp", + "phpactor", + "psalm", + "pylsp", + "pylyzer", + "pyre", + "quick_lint_js", + "reason_ls", + "rnix", + "rome", + "rubocop", + "ruby_ls", + "ruby_lsp", + "ruff_lsp", + "scry", + "snyk_ls", + "solang", + "solc", + "solidity_ls", + "solidity_ls_nomicfoundation", + "sorbet", + "sourcekit", + "somesass_ls", + "sourcery", + "spectral", + "sqlls", + "sqls", + "standardrb", + "stimulus_ls", + "stylelint_lsp", + "svlangserver", + "swift_mesonls", + "templ", + "tflint", + "tinymist", + "unocss", + "vale_ls", + "vacuum", + "verible", + "v_analyzer", + "vtsls", + "vuels", +} + +local skipped_filetypes = { "markdown", "rst", "plaintext", "toml", "proto" } + +local join_paths = require("lvim.utils").join_paths + +return { + templates_dir = join_paths(get_runtime_dir(), "site", "after", "ftplugin"), + ---@deprecated use vim.diagnostic.config({ ... }) instead + diagnostics = {}, + document_highlight = false, + code_lens_refresh = true, + on_attach_callback = nil, + on_init_callback = nil, + automatic_configuration = { + ---@usage list of servers that the automatic installer will skip + skipped_servers = skipped_servers, + ---@usage list of filetypes that the automatic installer will skip + skipped_filetypes = skipped_filetypes, + }, + buffer_mappings = { + normal_mode = { + ["K"] = { "<cmd>lua vim.lsp.buf.hover()<cr>", "Show hover" }, + ["gd"] = { "<cmd>lua vim.lsp.buf.definition()<cr>", "Goto definition" }, + ["gD"] = { "<cmd>lua vim.lsp.buf.declaration()<cr>", "Goto Declaration" }, + ["gr"] = { "<cmd>lua vim.lsp.buf.references()<cr>", "Goto references" }, + ["gI"] = { "<cmd>lua vim.lsp.buf.implementation()<cr>", "Goto Implementation" }, + ["gs"] = { "<cmd>lua vim.lsp.buf.signature_help()<cr>", "show signature help" }, + ["gl"] = { + function() + local float = vim.diagnostic.config().float + + if float then + local config = type(float) == "table" and float or {} + config.scope = "line" + + vim.diagnostic.open_float(config) + end + end, + "Show line diagnostics", + }, + }, + insert_mode = {}, + visual_mode = {}, + }, + buffer_options = { + --- enable completion triggered by <c-x><c-o> + omnifunc = "v:lua.vim.lsp.omnifunc", + --- use gq for formatting + formatexpr = "v:lua.vim.lsp.formatexpr(#{timeout_ms:500})", + }, + ---@usage list of settings of nvim-lsp-installer + installer = { + setup = { + ensure_installed = {}, + automatic_installation = { + exclude = {}, + }, + }, + }, + nlsp_settings = { + setup = { + config_home = join_paths(get_config_dir(), "lsp-settings"), + -- set to false to overwrite schemastore.nvim + append_default_schemas = true, + ignored_servers = {}, + loader = "json", + }, + }, + null_ls = { + setup = { + debug = false, + }, + config = {}, + }, + ---@deprecated use lvim.lsp.automatic_configuration.skipped_servers instead + override = {}, + ---@deprecated use lvim.lsp.installer.setup.automatic_installation instead + automatic_servers_installation = nil, +} diff --git a/mac/.config/LunarVim/lua/lvim/lsp/init.lua b/mac/.config/LunarVim/lua/lvim/lsp/init.lua new file mode 100644 index 0000000..d59b29a --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/init.lua @@ -0,0 +1,128 @@ +local M = {} +local Log = require "lvim.core.log" +local utils = require "lvim.utils" +local autocmds = require "lvim.core.autocmds" + +local function add_lsp_buffer_options(bufnr) + for k, v in pairs(lvim.lsp.buffer_options) do + vim.api.nvim_set_option_value(k, v, { buf = bufnr }) + end +end + +local function add_lsp_buffer_keybindings(bufnr) + local mappings = { + normal_mode = "n", + insert_mode = "i", + visual_mode = "v", + } + + for mode_name, mode_char in pairs(mappings) do + for key, remap in pairs(lvim.lsp.buffer_mappings[mode_name]) do + local opts = { buffer = bufnr, desc = remap[2], noremap = true, silent = true } + vim.keymap.set(mode_char, key, remap[1], opts) + end + end +end + +function M.common_capabilities() + local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") + if status_ok then + return cmp_nvim_lsp.default_capabilities() + end + + local capabilities = vim.lsp.protocol.make_client_capabilities() + capabilities.textDocument.completion.completionItem.snippetSupport = true + capabilities.textDocument.completion.completionItem.resolveSupport = { + properties = { + "documentation", + "detail", + "additionalTextEdits", + }, + } + + return capabilities +end + +function M.common_on_exit(_, _) + if lvim.lsp.document_highlight then + autocmds.clear_augroup "lsp_document_highlight" + end + if lvim.lsp.code_lens_refresh then + autocmds.clear_augroup "lsp_code_lens_refresh" + end +end + +function M.common_on_init(client, bufnr) + if lvim.lsp.on_init_callback then + lvim.lsp.on_init_callback(client, bufnr) + Log:debug "Called lsp.on_init_callback" + return + end +end + +function M.common_on_attach(client, bufnr) + if lvim.lsp.on_attach_callback then + lvim.lsp.on_attach_callback(client, bufnr) + Log:debug "Called lsp.on_attach_callback" + end + local lu = require "lvim.lsp.utils" + if lvim.lsp.document_highlight then + lu.setup_document_highlight(client, bufnr) + end + if lvim.lsp.code_lens_refresh then + lu.setup_codelens_refresh(client, bufnr) + end + add_lsp_buffer_keybindings(bufnr) + add_lsp_buffer_options(bufnr) + lu.setup_document_symbols(client, bufnr) +end + +function M.get_common_opts() + return { + on_attach = M.common_on_attach, + on_init = M.common_on_init, + on_exit = M.common_on_exit, + capabilities = M.common_capabilities(), + } +end + +function M.setup() + Log:debug "Setting up LSP support" + + local lsp_status_ok, _ = pcall(require, "lspconfig") + if not lsp_status_ok then + return + end + + if lvim.use_icons then + for _, sign in ipairs(vim.tbl_get(vim.diagnostic.config(), "signs", "values") or {}) do + vim.fn.sign_define(sign.name, { texthl = sign.name, text = sign.text, numhl = sign.name }) + end + end + + if not utils.is_directory(lvim.lsp.templates_dir) then + require("lvim.lsp.templates").generate_templates() + end + + pcall(function() + require("nlspsettings").setup(lvim.lsp.nlsp_settings.setup) + end) + + require("lvim.lsp.null-ls").setup() + + autocmds.configure_format_on_save() + + local function set_handler_opts_if_not_set(name, handler, opts) + if debug.getinfo(vim.lsp.handlers[name], "S").source:find(vim.env.VIMRUNTIME, 1, true) then + vim.lsp.handlers[name] = vim.lsp.with(handler, opts) + end + end + + set_handler_opts_if_not_set("textDocument/hover", vim.lsp.handlers.hover, { border = "rounded" }) + set_handler_opts_if_not_set("textDocument/signatureHelp", vim.lsp.handlers.signature_help, { border = "rounded" }) + + -- Enable rounded borders in :LspInfo window. + require("lspconfig.ui.windows").default_options.border = "rounded" +end + +return M diff --git a/mac/.config/LunarVim/lua/lvim/lsp/manager.lua b/mac/.config/LunarVim/lua/lvim/lsp/manager.lua new file mode 100644 index 0000000..5e695ec --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/manager.lua @@ -0,0 +1,141 @@ +local M = {} + +local Log = require "lvim.core.log" +local fmt = string.format +local lvim_lsp_utils = require "lvim.lsp.utils" +local is_windows = vim.loop.os_uname().version:match "Windows" + +local function resolve_mason_config(server_name) + local found, mason_config = pcall(require, "mason-lspconfig.server_configurations." .. server_name) + if not found then + Log:debug(fmt("mason configuration not found for %s", server_name)) + return {} + end + local server_mapping = require "mason-lspconfig.mappings.server" + local path = require "mason-core.path" + local pkg_name = server_mapping.lspconfig_to_package[server_name] + local install_dir = path.package_prefix(pkg_name) + local conf = mason_config(install_dir) + if is_windows and conf.cmd and conf.cmd[1] then + local exepath = vim.fn.exepath(conf.cmd[1]) + if exepath ~= "" then + conf.cmd[1] = exepath + end + end + Log:debug(fmt("resolved mason configuration for %s, got %s", server_name, vim.inspect(conf))) + return conf or {} +end + +---Resolve the configuration for a server by merging with the default config +---@param server_name string +---@vararg any config table [optional] +---@return table +local function resolve_config(server_name, ...) + local defaults = { + on_attach = require("lvim.lsp").common_on_attach, + on_init = require("lvim.lsp").common_on_init, + on_exit = require("lvim.lsp").common_on_exit, + capabilities = require("lvim.lsp").common_capabilities(), + } + + local has_custom_provider, custom_config = pcall(require, "lvim/lsp/providers/" .. server_name) + if has_custom_provider then + Log:debug("Using custom configuration for requested server: " .. server_name) + defaults = vim.tbl_deep_extend("force", defaults, custom_config) + end + + defaults = vim.tbl_deep_extend("force", defaults, ...) + + return defaults +end + +-- manually start the server and don't wait for the usual filetype trigger from lspconfig +local function buf_try_add(server_name, bufnr) + bufnr = bufnr or vim.api.nvim_get_current_buf() + require("lspconfig")[server_name].manager:try_add_wrapper(bufnr) +end + +-- check if the manager autocomd has already been configured since some servers can take a while to initialize +-- this helps guarding against a data-race condition where a server can get configured twice +-- which seems to occur only when attaching to single-files +local function client_is_configured(server_name, ft) + ft = ft or vim.bo.filetype + local active_autocmds = vim.api.nvim_get_autocmds { event = "FileType", pattern = ft } + for _, result in ipairs(active_autocmds) do + if result.desc ~= nil and result.desc:match("server " .. server_name .. " ") then + Log:debug(string.format("[%q] is already configured", server_name)) + return true + end + end + return false +end + +local function launch_server(server_name, config) + pcall(function() + local command = config.cmd + or (function() + local default_config = require("lspconfig.server_configurations." .. server_name).default_config + return default_config.cmd + end)() + -- some servers have dynamic commands defined with on_new_config + if type(command) == "table" and type(command[1]) == "string" and vim.fn.executable(command[1]) ~= 1 then + Log:debug(string.format("[%q] is either not installed, missing from PATH, or not executable.", server_name)) + return + end + require("lspconfig")[server_name].setup(config) + buf_try_add(server_name) + end) +end + +---Setup a language server by providing a name +---@param server_name string name of the language server +---@param user_config table? when available it will take predence over any default configurations +function M.setup(server_name, user_config) + vim.validate { name = { server_name, "string" } } + user_config = user_config or {} + + if lvim_lsp_utils.is_client_active(server_name) or client_is_configured(server_name) then + return + end + + local server_mapping = require "mason-lspconfig.mappings.server" + local registry = require "mason-registry" + + local pkg_name = server_mapping.lspconfig_to_package[server_name] + if not pkg_name then + local config = resolve_config(server_name, user_config) + launch_server(server_name, config) + return + end + + local should_auto_install = function(name) + local installer_settings = lvim.lsp.installer.setup + return installer_settings.automatic_installation + and not vim.tbl_contains(installer_settings.automatic_installation.exclude, name) + end + + if not registry.is_installed(pkg_name) then + if should_auto_install(server_name) then + Log:debug "Automatic server installation detected" + vim.notify_once(string.format("Installation in progress for [%s]", server_name), vim.log.levels.INFO) + local pkg = registry.get_package(pkg_name) + pkg:install():once("closed", function() + if pkg:is_installed() then + vim.schedule(function() + vim.notify_once(string.format("Installation complete for [%s]", server_name), vim.log.levels.INFO) + -- mason config is only available once the server has been installed + local config = resolve_config(server_name, resolve_mason_config(server_name), user_config) + launch_server(server_name, config) + end) + end + end) + else + Log:debug(server_name .. " is not managed by the automatic installer") + end + end + + local config = resolve_config(server_name, resolve_mason_config(server_name), user_config) + launch_server(server_name, config) +end + +return M diff --git a/mac/.config/LunarVim/lua/lvim/lsp/null-ls/code_actions.lua b/mac/.config/LunarVim/lua/lvim/lsp/null-ls/code_actions.lua new file mode 100644 index 0000000..50f4cfb --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/null-ls/code_actions.lua @@ -0,0 +1,26 @@ +local M = {} + +local Log = require "lvim.core.log" + +local null_ls = require "null-ls" +local services = require "lvim.lsp.null-ls.services" +local method = null_ls.methods.CODE_ACTION + +function M.list_registered(filetype) + local registered_providers = services.list_registered_providers_names(filetype) + return registered_providers[method] or {} +end + +function M.setup(actions_configs) + if vim.tbl_isempty(actions_configs) then + return + end + + local registered = services.register_sources(actions_configs, method) + + if #registered > 0 then + Log:debug("Registered the following action-handlers: " .. unpack(registered)) + end +end + +return M diff --git a/mac/.config/LunarVim/lua/lvim/lsp/null-ls/formatters.lua b/mac/.config/LunarVim/lua/lvim/lsp/null-ls/formatters.lua new file mode 100644 index 0000000..b4fb2f3 --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/null-ls/formatters.lua @@ -0,0 +1,33 @@ +local M = {} + +local Log = require "lvim.core.log" + +local null_ls = require "null-ls" +local services = require "lvim.lsp.null-ls.services" +local method = null_ls.methods.FORMATTING + +function M.list_registered(filetype) + local registered_providers = services.list_registered_providers_names(filetype) + return registered_providers[method] or {} +end + +function M.list_supported(filetype) + local s = require "null-ls.sources" + local supported_formatters = s.get_supported(filetype, "formatting") + table.sort(supported_formatters) + return supported_formatters +end + +function M.setup(formatter_configs) + if vim.tbl_isempty(formatter_configs) then + return + end + + local registered = services.register_sources(formatter_configs, method) + + if #registered > 0 then + Log:debug("Registered the following formatters: " .. unpack(registered)) + end +end + +return M diff --git a/mac/.config/LunarVim/lua/lvim/lsp/null-ls/init.lua b/mac/.config/LunarVim/lua/lvim/lsp/null-ls/init.lua new file mode 100644 index 0000000..51a200f --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/null-ls/init.lua @@ -0,0 +1,16 @@ +local M = {} + +local Log = require "lvim.core.log" + +function M.setup() + local status_ok, null_ls = pcall(require, "null-ls") + if not status_ok then + Log:error "Missing null-ls dependency" + return + end + + local default_opts = require("lvim.lsp").get_common_opts() + null_ls.setup(vim.tbl_deep_extend("force", default_opts, lvim.lsp.null_ls.setup)) +end + +return M diff --git a/mac/.config/LunarVim/lua/lvim/lsp/null-ls/linters.lua b/mac/.config/LunarVim/lua/lvim/lsp/null-ls/linters.lua new file mode 100644 index 0000000..ba7670d --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/null-ls/linters.lua @@ -0,0 +1,43 @@ +local M = {} + +local Log = require "lvim.core.log" + +local null_ls = require "null-ls" +local services = require "lvim.lsp.null-ls.services" +local method = null_ls.methods.DIAGNOSTICS + +local alternative_methods = { + null_ls.methods.DIAGNOSTICS, + null_ls.methods.DIAGNOSTICS_ON_OPEN, + null_ls.methods.DIAGNOSTICS_ON_SAVE, +} + +function M.list_registered(filetype) + local registered_providers = services.list_registered_providers_names(filetype) + local providers_for_methods = vim.tbl_flatten(vim.tbl_map(function(m) + return registered_providers[m] or {} + end, alternative_methods)) + + return providers_for_methods +end + +function M.list_supported(filetype) + local s = require "null-ls.sources" + local supported_linters = s.get_supported(filetype, "diagnostics") + table.sort(supported_linters) + return supported_linters +end + +function M.setup(linter_configs) + if vim.tbl_isempty(linter_configs) then + return + end + + local registered = services.register_sources(linter_configs, method) + + if #registered > 0 then + Log:debug("Registered the following linters: " .. unpack(registered)) + end +end + +return M diff --git a/mac/.config/LunarVim/lua/lvim/lsp/null-ls/services.lua b/mac/.config/LunarVim/lua/lvim/lsp/null-ls/services.lua new file mode 100644 index 0000000..7dc0bb6 --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/null-ls/services.lua @@ -0,0 +1,104 @@ +local M = {} + +local Log = require "lvim.core.log" + +local function find_root_dir() + local util = require "lspconfig/util" + local lsp_utils = require "lvim.lsp.utils" + + 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" + return util.root_pattern "package.json"(dirname) +end + +local function from_node_modules(command) + local root_dir = find_root_dir() + + if not root_dir then + return nil + end + + local join_paths = require("lvim.utils").join_paths + return join_paths(root_dir, "node_modules", ".bin", command) +end + +local local_providers = { + prettier = { find = from_node_modules }, + prettierd = { find = from_node_modules }, + prettier_d_slim = { find = from_node_modules }, + eslint_d = { find = from_node_modules }, + eslint = { find = from_node_modules }, + stylelint = { find = from_node_modules }, +} + +function M.find_command(command) + if local_providers[command] then + local local_command = local_providers[command].find(command) + if local_command and vim.fn.executable(local_command) == 1 then + return local_command + end + end + + if command and vim.fn.executable(command) == 1 then + return command + end + return nil +end + +function M.list_registered_providers_names(filetype) + local s = require "null-ls.sources" + local available_sources = s.get_available(filetype) + local registered = {} + for _, source in ipairs(available_sources) do + for method in pairs(source.methods) do + registered[method] = registered[method] or {} + table.insert(registered[method], source.name) + end + end + return registered +end + +function M.register_sources(configs, method) + local null_ls = require "null-ls" + local is_registered = require("null-ls.sources").is_registered + + local sources, registered_names = {}, {} + + for _, config in ipairs(configs) do + local cmd = config.exe or config.command + local name = config.name or cmd:gsub("-", "_") + local type = method == null_ls.methods.CODE_ACTION and "code_actions" or null_ls.methods[method]:lower() + local source = type and null_ls.builtins[type][name] + Log:debug(string.format("Received request to register [%s] as a %s source", name, type)) + if not source then + Log:error("Not a valid source: " .. name) + elseif is_registered { name = source.name or name, method = method } then + Log:trace(string.format("Skipping registering [%s] more than once", name)) + else + local command = M.find_command(source._opts.command) or source._opts.command + + -- treat `args` as `extra_args` for backwards compatibility. Can otherwise use `generator_opts.args` + local compat_opts = vim.deepcopy(config) + if config.args then + compat_opts.extra_args = config.args or config.extra_args + compat_opts.args = nil + end + + local opts = vim.tbl_deep_extend("keep", { command = command }, compat_opts) + Log:debug("Registering source " .. name) + Log:trace(vim.inspect(opts)) + table.insert(sources, source.with(opts)) + vim.list_extend(registered_names, { source.name }) + end + end + + if #sources > 0 then + null_ls.register { sources = sources } + end + return registered_names +end + +return M diff --git a/mac/.config/LunarVim/lua/lvim/lsp/providers/jsonls.lua b/mac/.config/LunarVim/lua/lvim/lsp/providers/jsonls.lua new file mode 100644 index 0000000..76aea25 --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/providers/jsonls.lua @@ -0,0 +1,18 @@ +local opts = { + settings = { + json = { + schemas = require("schemastore").json.schemas(), + }, + }, + setup = { + commands = { + Format = { + function() + vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line "$", 0 }) + end, + }, + }, + }, +} + +return opts diff --git a/mac/.config/LunarVim/lua/lvim/lsp/providers/lua_ls.lua b/mac/.config/LunarVim/lua/lvim/lsp/providers/lua_ls.lua new file mode 100644 index 0000000..952e04d --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/providers/lua_ls.lua @@ -0,0 +1,64 @@ +local default_workspace = { + library = { + vim.fn.expand "$VIMRUNTIME", + get_lvim_base_dir(), + require("neodev.config").types(), + "${3rd}/busted/library", + "${3rd}/luassert/library", + "${3rd}/luv/library", + }, + + maxPreload = 5000, + preloadFileSize = 10000, +} + +local add_packages_to_workspace = function(packages, config) + -- config.settings.Lua = config.settings.Lua or { workspace = default_workspace } + local runtimedirs = vim.api.nvim__get_runtime({ "lua" }, true, { is_lua = true }) + local workspace = config.settings.Lua.workspace + for _, v in pairs(runtimedirs) do + for _, pack in ipairs(packages) do + if v:match(pack) and not vim.tbl_contains(workspace.library, v) then + table.insert(workspace.library, v) + end + end + end +end + +local lspconfig = require "lspconfig" + +local make_on_new_config = function(on_new_config, _) + return lspconfig.util.add_hook_before(on_new_config, function(new_config, _) + local server_name = new_config.name + + if server_name ~= "lua_ls" then + return + end + local plugins = { "plenary.nvim", "telescope.nvim", "nvim-treesitter", "LuaSnip" } + add_packages_to_workspace(plugins, new_config) + end) +end + +lspconfig.util.default_config = vim.tbl_extend("force", lspconfig.util.default_config, { + on_new_config = make_on_new_config(lspconfig.util.default_config.on_new_config), +}) + +local opts = { + settings = { + Lua = { + telemetry = { enable = false }, + runtime = { + version = "LuaJIT", + special = { + reload = "require", + }, + }, + diagnostics = { + globals = { "vim", "lvim", "reload" }, + }, + workspace = default_workspace, + }, + }, +} + +return opts diff --git a/mac/.config/LunarVim/lua/lvim/lsp/providers/tailwindcss.lua b/mac/.config/LunarVim/lua/lvim/lsp/providers/tailwindcss.lua new file mode 100644 index 0000000..ebf0a1c --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/providers/tailwindcss.lua @@ -0,0 +1,15 @@ +local opts = { + root_dir = function(fname) + local util = require "lspconfig/util" + return util.root_pattern( + "tailwind.config.js", + "tailwind.config.ts", + "tailwind.config.cjs", + "tailwind.js", + "tailwind.ts", + "tailwind.cjs" + )(fname) + end, +} + +return opts diff --git a/mac/.config/LunarVim/lua/lvim/lsp/providers/vuels.lua b/mac/.config/LunarVim/lua/lvim/lsp/providers/vuels.lua new file mode 100644 index 0000000..326363f --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/providers/vuels.lua @@ -0,0 +1,26 @@ +local opts = { + setup = { + root_dir = function(fname) + local util = require "lvim.lspconfig/util" + return util.root_pattern "package.json"(fname) or util.root_pattern "vue.config.js"(fname) or vim.fn.getcwd() + end, + init_options = { + config = { + vetur = { + completion = { + autoImport = true, + tagCasing = "kebab", + useScaffoldSnippets = true, + }, + useWorkspaceDependencies = true, + validation = { + script = true, + style = true, + template = true, + }, + }, + }, + }, + }, +} +return opts diff --git a/mac/.config/LunarVim/lua/lvim/lsp/providers/yamlls.lua b/mac/.config/LunarVim/lua/lvim/lsp/providers/yamlls.lua new file mode 100644 index 0000000..c9764fc --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/providers/yamlls.lua @@ -0,0 +1,16 @@ +local opts = { + settings = { + yaml = { + hover = true, + completion = true, + validate = true, + schemaStore = { + enable = true, + url = "https://www.schemastore.org/api/json/catalog.json", + }, + schemas = require("schemastore").yaml.schemas(), + }, + }, +} + +return opts diff --git a/mac/.config/LunarVim/lua/lvim/lsp/templates.lua b/mac/.config/LunarVim/lua/lvim/lsp/templates.lua new file mode 100644 index 0000000..4a65fac --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/templates.lua @@ -0,0 +1,76 @@ +local M = {} + +local Log = require "lvim.core.log" +local utils = require "lvim.utils" +local lvim_lsp_utils = require "lvim.lsp.utils" + +local ftplugin_dir = lvim.lsp.templates_dir + +local join_paths = _G.join_paths + +function M.remove_template_files() + -- remove any outdated files + for _, file in ipairs(vim.fn.glob(ftplugin_dir .. "/*.lua", 1, 1)) do + vim.fn.delete(file) + vim.wait(10) + end +end + +local skipped_filetypes = lvim.lsp.automatic_configuration.skipped_filetypes +local skipped_servers = lvim.lsp.automatic_configuration.skipped_servers + +---Check if we should skip generating an ftplugin file based on the server_name +---@param server_name string name of a valid language server +local function should_skip(server_name) + return vim.tbl_contains(skipped_servers, server_name) +end + +---Generates an ftplugin file based on the server_name in the selected directory +---@param server_name string name of a valid language server, e.g. pyright, gopls, tsserver, etc. +---@param dir string the full path to the desired directory +function M.generate_ftplugin(server_name, dir) + if should_skip(server_name) then + return + end + + -- get the supported filetypes and remove any ignored ones + local filetypes = vim.tbl_filter(function(ft) + return not vim.tbl_contains(skipped_filetypes, ft) + end, lvim_lsp_utils.get_supported_filetypes(server_name) or {}) + + if not filetypes then + return + end + + for _, filetype in ipairs(filetypes) do + filetype = filetype:match "%.([^.]*)$" or filetype + local filename = join_paths(dir, filetype .. ".lua") + local setup_cmd = string.format([[require("lvim.lsp.manager").setup(%q)]], server_name) + -- print("using setup_cmd: " .. setup_cmd) + -- overwrite the file completely + utils.write_file(filename, setup_cmd .. "\n", "a") + end +end + +---Generates ftplugin files based on a list of server_names +---The files are generated to a runtimepath: "$LUNARVIM_RUNTIME_DIR/site/after/ftplugin/template.lua" +---@param servers_names? table list of servers to be enabled. Will add all by default +function M.generate_templates(servers_names) + servers_names = servers_names or lvim_lsp_utils.get_supported_servers() + + Log:debug "Templates installation in progress" + + M.remove_template_files() + + -- create the directory if it didn't exist + if not utils.is_directory(lvim.lsp.templates_dir) then + vim.fn.mkdir(ftplugin_dir, "p") + end + + for _, server in ipairs(servers_names) do + M.generate_ftplugin(server, ftplugin_dir) + end + Log:debug "Templates installation is complete" +end + +return M diff --git a/mac/.config/LunarVim/lua/lvim/lsp/utils.lua b/mac/.config/LunarVim/lua/lvim/lsp/utils.lua new file mode 100644 index 0000000..0d9bcd7 --- /dev/null +++ b/mac/.config/LunarVim/lua/lvim/lsp/utils.lua @@ -0,0 +1,185 @@ +local M = {} + +local tbl = require "lvim.utils.table" +local Log = require "lvim.core.log" + +function M.is_client_active(name) + local clients = vim.lsp.get_clients() + return tbl.find_first(clients, function(client) + return client.name == name + end) +end + +function M.get_active_clients_by_ft(filetype) + local matches = {} + local clients = vim.lsp.get_clients() + for _, client in pairs(clients) do + local supported_filetypes = client.config.filetypes or {} + if client.name ~= "null-ls" and vim.tbl_contains(supported_filetypes, filetype) then + table.insert(matches, client) + end + end + return matches +end + +function M.get_client_capabilities(client_id) + local client = vim.lsp.get_client_by_id(tonumber(client_id)) + if not client then + Log:warn("Unable to determine client from client_id: " .. client_id) + return + end + + local enabled_caps = {} + for capability, status in pairs(client.server_capabilities) do + if status == true then + table.insert(enabled_caps, capability) + end + end + + return enabled_caps +end + +---Get supported filetypes per server +---@param server_name string can be any server supported by nvim-lsp-installer +---@return string[] supported filestypes as a list of strings +function M.get_supported_filetypes(server_name) + local status_ok, config = pcall(require, ("lspconfig.server_configurations.%s"):format(server_name)) + if not status_ok then + return {} + end + + return config.default_config.filetypes or {} +end + +---Get supported servers per filetype +---@param filter { filetype: string | string[] }?: (optional) Used to filter the list of server names. +---@return string[] list of names of supported servers +function M.get_supported_servers(filter) + -- force synchronous mode, see: |mason-registry.refresh()| + require("mason-registry").refresh() + require("mason-registry").get_all_packages() + + local _, supported_servers = pcall(function() + return require("mason-lspconfig").get_available_servers(filter) + end) + return supported_servers or {} +end + +---Get all supported filetypes by nvim-lsp-installer +---@return string[] supported filestypes as a list of strings +function M.get_all_supported_filetypes() + local status_ok, filetype_server_map = pcall(require, "mason-lspconfig.mappings.filetype") + if not status_ok then + return {} + end + return vim.tbl_keys(filetype_server_map or {}) +end + +function M.setup_document_highlight(client, bufnr) + if lvim.builtin.illuminate.active then + Log:debug "skipping setup for document_highlight, illuminate already active" + return + end + local status_ok, highlight_supported = pcall(function() + return client.supports_method "textDocument/documentHighlight" + end) + if not status_ok or not highlight_supported then + return + end + local group = "lsp_document_highlight" + local hl_events = { "CursorHold", "CursorHoldI" } + + local ok, hl_autocmds = pcall(vim.api.nvim_get_autocmds, { + group = group, + buffer = bufnr, + event = hl_events, + }) + + if ok and #hl_autocmds > 0 then + return + end + + vim.api.nvim_create_augroup(group, { clear = false }) + vim.api.nvim_create_autocmd(hl_events, { + group = group, + buffer = bufnr, + callback = vim.lsp.buf.document_highlight, + }) + vim.api.nvim_create_autocmd("CursorMoved", { + group = group, + buffer = bufnr, + callback = vim.lsp.buf.clear_references, + }) +end + +function M.setup_document_symbols(client, bufnr) + vim.g.navic_silence = false -- can be set to true to suppress error + local symbols_supported = client.supports_method "textDocument/documentSymbol" + if not symbols_supported then + Log:debug("skipping setup for document_symbols, method not supported by " .. client.name) + return + end + local status_ok, navic = pcall(require, "nvim-navic") + if status_ok then + navic.attach(client, bufnr) + end +end + +function M.setup_codelens_refresh(client, bufnr) + local status_ok, codelens_supported = pcall(function() + return client.supports_method "textDocument/codeLens" + end) + if not status_ok or not codelens_supported then + return + end + local group = "lsp_code_lens_refresh" + local cl_events = { "BufEnter", "InsertLeave" } + local ok, cl_autocmds = pcall(vim.api.nvim_get_autocmds, { + group = group, + buffer = bufnr, + event = cl_events, + }) + + if ok and #cl_autocmds > 0 then + return + end + vim.api.nvim_create_augroup(group, { clear = false }) + vim.api.nvim_create_autocmd(cl_events, { + group = group, + buffer = bufnr, + callback = function() + vim.lsp.codelens.refresh { bufnr = bufnr } + end, + }) +end + +---filter passed to vim.lsp.buf.format +---always selects null-ls if it's available and caches the value per buffer +---@param client table client attached to a buffer +---@return boolean if client matches +function M.format_filter(client) + local filetype = vim.bo.filetype + local n = require "null-ls" + local s = require "null-ls.sources" + local method = n.methods.FORMATTING + local available_formatters = s.get_available(filetype, method) + + if #available_formatters > 0 then + return client.name == "null-ls" + elseif client.supports_method "textDocument/formatting" then + return true + else + return false + end +end + +---Simple wrapper for vim.lsp.buf.format() to provide defaults +---@param opts table|nil +function M.format(opts) + opts = opts or {} + opts.filter = opts.filter or M.format_filter + + return vim.lsp.buf.format(opts) +end + +return M |
