diff --git a/after/lsp/bashls.lua b/after/lsp/bashls.lua new file mode 100644 index 0000000..63dbf5f --- /dev/null +++ b/after/lsp/bashls.lua @@ -0,0 +1,22 @@ +local lsp = require("lsp") +local util = require("util") + +---@type vim.lsp.Config +return { + filetypes = { + "sh", + "bash", + "zsh", + }, + on_attach = function(client, bufnr) + lsp.on_attach(client, bufnr) + + vim.keymap.set("n", "lf", function() + util.format({ + buf = bufnr, + cmd = { "shfmt", "-s", "-i", "4", "-" }, + output = "stdout", + }) + end, { buffer = bufnr }) + end, +} diff --git a/after/lsp/clangd.lua b/after/lsp/clangd.lua new file mode 100644 index 0000000..062fb5b --- /dev/null +++ b/after/lsp/clangd.lua @@ -0,0 +1,57 @@ +local Linter = require("linter") +local lsp = require("lsp") + +---@type vim.lsp.Config +return { + filetypes = { + "c", + "cpp", + }, + cmd = { + "clangd", + "--clang-tidy", + "--enable-config", + -- Fix for errors in files outside of project + -- https://clangd.llvm.org/faq#how-do-i-fix-errors-i-get-when-opening-headers-outside-of-my-project-directory + "--compile-commands-dir=build", + }, + single_file_support = true, + on_attach = function(client, bufnr) + lsp.on_attach(client, bufnr) + + Linter.add(bufnr, { + cmd = { + "clang-tidy", + "-p=build", + "--quiet", + "--checks=-*," + .. "clang-analyzer-*," + .. "-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling," + .. "-clang-analyzer-security.insecureAPI.strcpy", + "%file%", + }, + events = { "BufWritePost" }, + clear_events = { "TextChanged", "TextChangedI" }, + stdin = false, + stdout = true, + pattern = "^.+:(%d+):(%d+): (%w+): (.*) %[(.*)%]$", + groups = { "lnum", "col", "severity", "message", "code" }, + source = "clang-tidy", + severity_map = { + error = vim.diagnostic.severity.ERROR, + warning = vim.diagnostic.severity.WARN, + note = vim.diagnostic.severity.HINT, + }, + zero_idx_col = true, + zero_idx_lnum = true, + ignore_stderr = true, + }) + + vim.keymap.set( + "n", + "gs", + vim.cmd.LspClangdSwitchSourceHeader, + { buffer = bufnr } + ) + end, +} diff --git a/after/lsp/cmake.lua b/after/lsp/cmake.lua new file mode 100644 index 0000000..611b84d --- /dev/null +++ b/after/lsp/cmake.lua @@ -0,0 +1,9 @@ +local lsp = require("lsp") + +---@type vim.lsp.Config +return { + on_attach = lsp.on_attach, + init_options = { + buildDirectory = "build", + }, +} diff --git a/after/lsp/gopls.lua b/after/lsp/gopls.lua new file mode 100644 index 0000000..7a61b37 --- /dev/null +++ b/after/lsp/gopls.lua @@ -0,0 +1,29 @@ +local lsp = require("lsp") +local util = require("util") + +---@type vim.lsp.Config +return { + settings = { + gopls = { + staticcheck = true, + semanticTokens = true, + }, + }, + on_attach = function(client, bufnr) + lsp.on_attach(client, bufnr) + + vim.keymap.set("n", "lf", function() + util.format({ + buf = bufnr, + cmd = { + "golines", + "-m", + "80", + "--shorten-comments", + }, + output = "stdout", + }) + vim.lsp.buf.format({ async = true }) + end, { buffer = bufnr }) + end, +} diff --git a/after/lsp/intelephense.lua b/after/lsp/intelephense.lua new file mode 100644 index 0000000..173f799 --- /dev/null +++ b/after/lsp/intelephense.lua @@ -0,0 +1,59 @@ +local Linter = require("linter") +local lsp = require("lsp") +local util = require("util") + +---@type vim.lsp.Config +return { + settings = { + intelephense = { + environment = { + phpVersion = "8.4", + }, + format = { + enable = true, + braces = "psr12", + }, + }, + }, + on_attach = function(client, bufnr) + lsp.on_attach(client, bufnr) + + Linter.add(bufnr, { + cmd = { + "phpcs", + "--standard=PSR12", + "--report=emacs", + "-s", + "-q", + "-", + }, + stdin = true, + stdout = true, + pattern = "^.+:(%d+):(%d+): (%w+) %- (.*) %((.*)%)$", + groups = { "lnum", "col", "severity", "message", "code" }, + source = "phpcs", + severity_map = { + error = vim.diagnostic.severity.ERROR, + warning = vim.diagnostic.severity.WARN, + }, + zero_idx_col = true, + zero_idx_lnum = true, + }) + + vim.keymap.set("n", "lf", function() + vim.lsp.buf.format() + util.format({ + buf = bufnr, + cmd = { + "php-cs-fixer", + "fix", + "%file%", + "--quiet", + }, + output = "in_place", + ignore_stderr = true, + env = { PHP_CS_FIXER_IGNORE_ENV = "1" }, + }) + end, { buffer = bufnr }) + end, +} diff --git a/after/lsp/jedi_language_server.lua b/after/lsp/jedi_language_server.lua new file mode 100644 index 0000000..3a7bbee --- /dev/null +++ b/after/lsp/jedi_language_server.lua @@ -0,0 +1,14 @@ +local lsp = require("lsp") + +---@type vim.lsp.Config +return { + on_attach = lsp.on_attach, + init_options = { + completion = { + disableSnippets = true, + }, + diagnostics = { + enable = true, + }, + }, +} diff --git a/after/lsp/lemminx.lua b/after/lsp/lemminx.lua new file mode 100644 index 0000000..ea9c1db --- /dev/null +++ b/after/lsp/lemminx.lua @@ -0,0 +1,26 @@ +local lsp = require("lsp") + +---@type vim.lsp.Config +return { + on_attach = lsp.on_attach, + init_options = { + settings = { + xml = { + format = { + enabled = true, -- is able to format document + splitAttributes = true, -- each attribute is formatted onto new line + joinCDATALines = false, -- normalize content inside CDATA + joinCommentLines = false, -- normalize content inside comments + formatComments = true, -- keep comment in relative position + joinContentLines = false, -- normalize content inside elements + spaceBeforeEmptyCloseLine = true, -- insert whitespace before self closing tag end bracket + }, + validation = { + noGrammar = "ignore", + enabled = true, + schema = true, + }, + }, + }, + }, +} diff --git a/after/lsp/lua_ls.lua b/after/lsp/lua_ls.lua new file mode 100644 index 0000000..0e19691 --- /dev/null +++ b/after/lsp/lua_ls.lua @@ -0,0 +1,74 @@ +local lsp = require("lsp") +local util = require("util") + +local lua_library_paths = { + vim.env.VIMRUNTIME, +} +for _, plugin in ipairs(require("lazy").plugins()) do + table.insert(lua_library_paths, plugin.dir) +end + +---@type vim.lsp.Config +return { + settings = { + Lua = { + completion = { showWord = "Disable" }, + runtime = { + version = "LuaJIT", + path = { + "lua/?.lua", + "lua/?/init.lua", + }, + pathStrict = true, + }, + workspace = { + library = lua_library_paths, + checkThirdParty = false, + }, + hint = { + enable = false, + arrayIndex = "Disable", + await = true, + paramName = "All", + paramType = true, + semicolon = "Disable", + setType = true, + }, + telemetry = { enable = false }, + }, + }, + on_attach = function(client, bufnr) + lsp.on_attach(client, bufnr) + + vim.keymap.set("n", "lf", function() + util.format({ + buf = bufnr, + cmd = { + "stylua", + "--stdin-filepath", + "%file%", + "-", + }, + output = "stdout", + auto_indent = true, + }) + end, { buffer = bufnr }) + + vim.keymap.set("x", "lf", function() + util.format({ + buf = bufnr, + cmd = { + "stylua", + "--range-start", + "%byte_start%", + "--range-end", + "%byte_end%", + "--stdin-filepath", + "%file%", + "-", + }, + output = "stdout", + }) + end, { buffer = bufnr }) + end, +} diff --git a/after/lsp/mesonlsp.lua b/after/lsp/mesonlsp.lua new file mode 100644 index 0000000..2952011 --- /dev/null +++ b/after/lsp/mesonlsp.lua @@ -0,0 +1,11 @@ +local lsp = require("lsp") + +---@type vim.lsp.Config +return { + on_attach = lsp.on_attach, + settings = { + others = { + disableInlayHints = true, + }, + }, +} diff --git a/after/lsp/pyright.lua b/after/lsp/pyright.lua new file mode 100644 index 0000000..825b6b6 --- /dev/null +++ b/after/lsp/pyright.lua @@ -0,0 +1,20 @@ +local lsp = require("lsp") + +---@type vim.lsp.Config +return { + on_attach = lsp.on_attach, + settings = { + python = { + analysis = { + autoSearchPaths = true, + diagnosticMode = "openFilesOnly", + useLibraryCodeForTypes = true, + typeCheckingMode = "strict", + stubPath = "stubs", + }, + }, + pyright = { + disableLanguageServices = false, + }, + }, +} diff --git a/after/lsp/ruff.lua b/after/lsp/ruff.lua new file mode 100644 index 0000000..5a5fd3b --- /dev/null +++ b/after/lsp/ruff.lua @@ -0,0 +1,26 @@ +local lsp = require("lsp") +local util = require("util") + +---@type vim.lsp.Config +return { + on_attach = function(client, bufnr) + lsp.on_attach(client, bufnr) + + vim.keymap.set("n", "lf", function() + vim.lsp.buf.format() + util.format({ + buf = bufnr, + cmd = { + "ruff", + "check", + "--stdin-filename=%file%", + "--select=I", + "--fix", + "--quiet", + "-", + }, + output = "stdout", + }) + end, { buffer = bufnr }) + end, +} diff --git a/after/lsp/rust_analyzer.lua b/after/lsp/rust_analyzer.lua new file mode 100644 index 0000000..a0e0f33 --- /dev/null +++ b/after/lsp/rust_analyzer.lua @@ -0,0 +1,54 @@ +local lsp = require("lsp") + +---@type vim.lsp.Config +return { + on_attach = function(client, bufnr) + lsp.on_attach(client, bufnr) + + local handler_name = "textDocument/publishDiagnostics" + local default_handler = client.handlers[handler_name] + or vim.lsp.handlers[handler_name] + client.handlers[handler_name] = function(err, result, context, config) + if result and result.diagnostics then + result.diagnostics = vim.tbl_filter(function(diagnostic) + return diagnostic.severity < vim.diagnostic.severity.HINT + end, result.diagnostics) + end + + default_handler(err, result, context, config) + end + end, + settings = { + ["rust-analyzer"] = { + check = { + command = "clippy", + extraArgs = { + "--", + "-Wclippy::pedantic", + }, + }, + diagnostics = { + styleLints = { + enable = true, + }, + }, + imports = { + prefix = "self", + }, + inlayHints = { + chainingHints = { + enable = false, + }, + parameterHints = { + enable = false, + }, + typeHints = { + enable = false, + }, + }, + rustfmt = { + extraArgs = { "+nightly" }, + }, + }, + }, +} diff --git a/after/lsp/zls.lua b/after/lsp/zls.lua new file mode 100644 index 0000000..9c4d8b4 --- /dev/null +++ b/after/lsp/zls.lua @@ -0,0 +1,16 @@ +local lsp = require("lsp") + +---@type vim.lsp.Config +return { + on_attach = lsp.on_attach, + settings = { + zls = { + warn_style = true, + highlight_global_var_declarations = true, + inlay_hints_show_variable_type_hints = false, + inlay_hints_show_struct_literal_field_type = false, + inlay_hints_show_parameter_name = false, + inlay_hints_show_builtin = false, + }, + }, +} diff --git a/lua/lsp/linter.lua b/lua/linter.lua similarity index 100% rename from lua/lsp/linter.lua rename to lua/linter.lua diff --git a/lua/lsp/keymap.lua b/lua/lsp.lua similarity index 50% rename from lua/lsp/keymap.lua rename to lua/lsp.lua index 9d721c3..8e3e8b8 100644 --- a/lua/lsp/keymap.lua +++ b/lua/lsp.lua @@ -1,29 +1,22 @@ +---@type fun(name: string, cfg: vim.lsp.Config) +vim.lsp.config = vim.lsp.config + +local log = require("log") local util = require("util") ----@class ow.lsp.Keymap ----@field mode string|string[] ----@field lhs string ----@field rhs string|function ----@field opts? vim.keymap.set.Opts +local M = {} -local Keymap = {} +M.diagnostic_signs = { + text = { + [vim.diagnostic.severity.ERROR] = "E", + [vim.diagnostic.severity.WARN] = "W", + [vim.diagnostic.severity.INFO] = "I", + [vim.diagnostic.severity.HINT] = "H", + }, +} ---@param bufnr integer ----@param keymaps ow.lsp.Keymap[] -function Keymap.set(bufnr, keymaps) - for _, keymap in ipairs(keymaps) do - keymap.opts = vim.tbl_extend( - "force", - keymap.opts or {}, - { buffer = bufnr, remap = true } - ) - vim.keymap.set(keymap.mode, keymap.lhs, keymap.rhs, keymap.opts) - end -end - ----@param bufnr integer -function Keymap.set_defaults(bufnr) - ---@type ow.lsp.Keymap[] +local function set_keymaps(bufnr) local keymaps = { { mode = { "n" }, lhs = "df", rhs = vim.diagnostic.open_float }, { @@ -63,7 +56,11 @@ function Keymap.set_defaults(bufnr) lhs = "", rhs = vim.lsp.buf.document_highlight, }, - { mode = { "n", "x" }, lhs = "lf", rhs = vim.lsp.buf.format }, + { + mode = { "n", "x" }, + lhs = "lf", + rhs = vim.lsp.buf.format, + }, { mode = { "n" }, lhs = "ld", @@ -105,7 +102,100 @@ function Keymap.set_defaults(bufnr) }) end - Keymap.set(bufnr, keymaps) + for _, keymap in ipairs(keymaps) do + keymap.opts = + vim.tbl_extend("keep", keymap.opts or {}, { buffer = bufnr }) + vim.keymap.set(keymap.mode, keymap.lhs, keymap.rhs, keymap.opts) + end end -return Keymap +--- Load a JSON file and return a parsed table merged with settings +---@param path string +---@param settings? table +---@return table? +local function with_file(path, settings) + local file = io.open(path, "r") + if not file then + return + end + + local json = file:read("*all") + file:close() + local ok, resp = pcall( + vim.json.decode, + json, + { luanil = { object = true, array = true } } + ) + if not ok then + log.warning("Failed to parse json file %s: %s", path, resp) + return + end + + return vim.tbl_deep_extend("force", settings or {}, resp) +end + +function M.on_attach(client, bufnr) + set_keymaps(bufnr) + + client.settings = with_file( + string.format(".%s.json", client.name), + client.settings + ) or client.settings + + if client:supports_method("textDocument/completion") then + vim.lsp.completion.enable(true, client.id, bufnr, { + autotrigger = true, + }) + end +end + +function M.setup() + vim.diagnostic.config({ + underline = true, + signs = M.diagnostic_signs, + virtual_text = false, + float = { + show_header = false, + source = true, + border = "rounded", + focusable = true, + format = function(diagnostic) + return string.format("%s", diagnostic.message) + end, + width = 80, + }, + update_in_insert = false, + severity_sort = true, + jump = { + float = true, + wrap = false, + }, + }) + + vim.lsp.enable({ + "bashls", + "clangd", + "cmake", + "gopls", + -- "hyprls", + "intelephense", + -- "jedi_language_server", + "lemminx", + "lua_ls", + "mesonlsp", + -- "phpactor", + -- "pyrefly", + "pyright", + "ruff", + "rust_analyzer", + "zls", + }) + + local capabilities = vim.lsp.protocol.make_client_capabilities() + vim.lsp.config("*", { + capabilities = capabilities, + on_attach = M.on_attach, + }) +end + +return M diff --git a/lua/lsp/init.lua b/lua/lsp/init.lua deleted file mode 100644 index cb1efaf..0000000 --- a/lua/lsp/init.lua +++ /dev/null @@ -1,540 +0,0 @@ ----@type fun(name: string, cfg: vim.lsp.Config) -vim.lsp.config = vim.lsp.config - -local Keymap = require("lsp.keymap") -local Linter = require("lsp.linter") -local log = require("log") -local util = require("util") - -local M = {} - -M.diagnostic_signs = { - text = { - [vim.diagnostic.severity.ERROR] = "E", - [vim.diagnostic.severity.WARN] = "W", - [vim.diagnostic.severity.INFO] = "I", - [vim.diagnostic.severity.HINT] = "H", - }, -} - ----@param server string ----@param fn? fun(client: vim.lsp.Client, bufnr: integer) ----@return fun(client: vim.lsp.Client, bufnr: integer) -function M.with_defaults(server, fn) - local default_cb = vim.lsp.config[server].on_attach - return function(client, bufnr) - if default_cb then - default_cb(client, bufnr) - end - - Keymap.set_defaults(bufnr) - - -- For document highlight - vim.cmd.highlight({ "link LspReferenceRead Visual", bang = true }) - vim.cmd.highlight({ "link LspReferenceText Visual", bang = true }) - vim.cmd.highlight({ "link LspReferenceWrite Visual", bang = true }) - - client.settings = M.with_file( - string.format(".%s.json", client.name), - client.settings - ) or client.settings - - if fn then - fn(client, bufnr) - end - end -end - ---- Load a JSON file and return a parsed table merged with settings ----@param path string ----@param settings? table ----@return table? -function M.with_file(path, settings) - local file = io.open(path, "r") - if not file then - return - end - - local json = file:read("*all") - file:close() - local ok, resp = pcall( - vim.json.decode, - json, - { luanil = { object = true, array = true } } - ) - if not ok then - log.warning("Failed to parse json file %s: %s", path, resp) - return - end - - return vim.tbl_deep_extend("force", settings or {}, resp) -end - -function M.setup() - vim.diagnostic.config({ - underline = true, - signs = M.diagnostic_signs, - virtual_text = false, - float = { - show_header = false, - source = true, - border = "rounded", - focusable = true, - format = function(diagnostic) - return string.format("%s", diagnostic.message) - end, - width = 80, - }, - update_in_insert = false, - severity_sort = true, - jump = { - float = true, - wrap = false, - }, - }) - - vim.lsp.enable({ - "bashls", - "clangd", - "cmake", - "gopls", - "hyprls", - "intelephense", - -- "jedi_language_server", - "lemminx", - "lua_ls", - "mesonlsp", - -- "phpactor", - -- "pyrefly", - "pyright", - "ruff", - "rust_analyzer", - "zls", - }) - - local capabilities = vim.lsp.protocol.make_client_capabilities() - local cmp_nvim_lsp = util.try_require("cmp_nvim_lsp") - if cmp_nvim_lsp then - capabilities = vim.tbl_deep_extend( - "force", - capabilities, - cmp_nvim_lsp.default_capabilities() - ) - end - - vim.lsp.config("*", { - on_attach = M.with_defaults("*"), - capabilities = capabilities, - }) - - vim.lsp.config("bashls", { - filetypes = { - "sh", - "bash", - "zsh", - }, - on_attach = M.with_defaults("bashls", function(_, bufnr) - Keymap.set(bufnr, { - { - mode = "n", - lhs = "lf", - rhs = function() - util.format({ - buf = bufnr, - cmd = { "shfmt", "-s", "-i", "4", "-" }, - output = "stdout", - }) - end, - }, - }) - end), - }) - - vim.lsp.config("clangd", { - filetypes = { - "c", - "cpp", - }, - cmd = { - "clangd", - "--clang-tidy", - "--enable-config", - -- Fix for errors in files outside of project - -- https://clangd.llvm.org/faq#how-do-i-fix-errors-i-get-when-opening-headers-outside-of-my-project-directory - "--compile-commands-dir=build", - }, - single_file_support = true, - on_attach = M.with_defaults("clangd", function(_, bufnr) - Linter.add(bufnr, { - cmd = { - "clang-tidy", - "-p=build", - "--quiet", - "--checks=-*," - .. "clang-analyzer-*," - .. "-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling," - .. "-clang-analyzer-security.insecureAPI.strcpy", - "%file%", - }, - events = { "BufWritePost" }, - clear_events = { "TextChanged", "TextChangedI" }, - stdin = false, - stdout = true, - pattern = "^.+:(%d+):(%d+): (%w+): (.*) %[(.*)%]$", - groups = { "lnum", "col", "severity", "message", "code" }, - source = "clang-tidy", - severity_map = { - error = vim.diagnostic.severity.ERROR, - warning = vim.diagnostic.severity.WARN, - note = vim.diagnostic.severity.HINT, - }, - zero_idx_col = true, - zero_idx_lnum = true, - ignore_stderr = true, - }) - Keymap.set(bufnr, { - { - mode = "n", - lhs = "gs", - rhs = vim.cmd.LspClangdSwitchSourceHeader, - }, - }) - end), - }) - - vim.lsp.config("cmake", { - init_options = { - buildDirectory = "build", - }, - }) - - vim.lsp.config("gopls", { - settings = { - gopls = { - staticcheck = true, - semanticTokens = true, - }, - }, - on_attach = M.with_defaults("gopls", function(_, bufnr) - Keymap.set(bufnr, { - { - mode = "n", - lhs = "lf", - rhs = function() - util.format({ - buf = bufnr, - cmd = { - "golines", - "-m", - "80", - "--shorten-comments", - }, - output = "stdout", - }) - vim.lsp.buf.format({ async = true }) - end, - }, - }) - end), - }) - - vim.lsp.config("intelephense", { - settings = { - intelephense = { - environment = { - phpVersion = "8.4", - }, - format = { - enable = true, - braces = "psr12", - }, - }, - }, - on_attach = M.with_defaults("intelephense", function(_, bufnr) - Linter.add(bufnr, { - cmd = { - "phpcs", - "--standard=PSR12", - "--report=emacs", - "-s", - "-q", - "-", - }, - stdin = true, - stdout = true, - pattern = "^.+:(%d+):(%d+): (%w+) %- (.*) %((.*)%)$", - groups = { "lnum", "col", "severity", "message", "code" }, - source = "phpcs", - severity_map = { - error = vim.diagnostic.severity.ERROR, - warning = vim.diagnostic.severity.WARN, - }, - zero_idx_col = true, - zero_idx_lnum = true, - }) - - Keymap.set(bufnr, { - { - mode = "n", - lhs = "lf", - rhs = function() - vim.lsp.buf.format() - util.format({ - buf = bufnr, - cmd = { - "php-cs-fixer", - "fix", - "%file%", - "--quiet", - }, - output = "in_place", - ignore_stderr = true, - env = { PHP_CS_FIXER_IGNORE_ENV = "1" }, - }) - end, - }, - }) - end), - }) - - vim.lsp.config("jedi_language_server", { - init_options = { - completion = { - disableSnippets = true, - }, - diagnostics = { - enable = true, - }, - }, - }) - - vim.lsp.config("lemminx", { - init_options = { - settings = { - xml = { - format = { - enabled = true, -- is able to format document - splitAttributes = true, -- each attribute is formatted onto new line - joinCDATALines = false, -- normalize content inside CDATA - joinCommentLines = false, -- normalize content inside comments - formatComments = true, -- keep comment in relative position - joinContentLines = false, -- normalize content inside elements - spaceBeforeEmptyCloseLine = true, -- insert whitespace before self closing tag end bracket - }, - validation = { - noGrammar = "ignore", - enabled = true, - schema = true, - }, - }, - }, - }, - }) - - local lua_library_paths = { - vim.env.VIMRUNTIME, - } - for _, plugin in ipairs(require("lazy").plugins()) do - table.insert(lua_library_paths, plugin.dir) - end - - vim.lsp.config("lua_ls", { - settings = { - Lua = { - completion = { showWord = "Disable" }, - runtime = { - version = "LuaJIT", - path = { - "lua/?.lua", - "lua/?/init.lua", - }, - pathStrict = true, - }, - workspace = { - library = lua_library_paths, - checkThirdParty = false, - }, - hint = { - enable = false, - arrayIndex = "Disable", - await = true, - paramName = "All", - paramType = true, - semicolon = "Disable", - setType = true, - }, - telemetry = { enable = false }, - }, - }, - on_attach = M.with_defaults("lua_ls", function(_, bufnr) - Keymap.set(bufnr, { - { - mode = "n", - lhs = "lf", - rhs = function() - util.format({ - buf = bufnr, - cmd = { - "stylua", - "--stdin-filepath", - "%file%", - "-", - }, - output = "stdout", - auto_indent = true, - }) - end, - }, - { - mode = "x", - lhs = "lf", - rhs = function() - util.format({ - buf = bufnr, - cmd = { - "stylua", - "--range-start", - "%byte_start%", - "--range-end", - "%byte_end%", - "--stdin-filepath", - "%file%", - "-", - }, - output = "stdout", - }) - end, - }, - }) - end), - }) - - vim.lsp.config("mesonlsp", { - on_attach = M.with_defaults("mesonlsp"), - settings = { - others = { - disableInlayHints = true, - }, - }, - }) - - vim.lsp.config("pyright", { - -- Handled in ruff instead - -- on_attach = M.with_defaults("pyright"), - settings = { - python = { - analysis = { - autoSearchPaths = true, - diagnosticMode = "openFilesOnly", - useLibraryCodeForTypes = true, - typeCheckingMode = "strict", - stubPath = "stubs", - }, - }, - pyright = { - disableLanguageServices = false, - }, - }, - }) - - vim.lsp.config("ruff", { - on_attach = M.with_defaults("ruff", function(_, bufnr) - Keymap.set(bufnr, { - { - mode = "n", - lhs = "lf", - rhs = function() - vim.lsp.buf.format() - util.format({ - buf = bufnr, - cmd = { - "ruff", - "check", - "--stdin-filename=%file%", - "--select=I", - "--fix", - "--quiet", - "-", - }, - output = "stdout", - }) - end, - }, - }) - end), - }) - - vim.lsp.config("rust_analyzer", { - on_attach = M.with_defaults("rust_analyzer", function(client) - local handler_name = "textDocument/publishDiagnostics" - local default_handler = client.handlers[handler_name] - or vim.lsp.handlers[handler_name] - client.handlers[handler_name] = function( - err, - result, - context, - config - ) - if result and result.diagnostics then - result.diagnostics = vim.tbl_filter(function(diagnostic) - return diagnostic.severity - < vim.diagnostic.severity.HINT - end, result.diagnostics) - end - - default_handler(err, result, context, config) - end - end), - settings = { - ["rust-analyzer"] = { - check = { - command = "clippy", - extraArgs = { - "--", - "-Wclippy::pedantic", - }, - }, - diagnostics = { - styleLints = { - enable = true, - }, - }, - imports = { - prefix = "self", - }, - inlayHints = { - chainingHints = { - enable = false, - }, - parameterHints = { - enable = false, - }, - typeHints = { - enable = false, - }, - }, - rustfmt = { - extraArgs = { "+nightly" }, - }, - }, - }, - }) - - vim.lsp.config("zls", { - on_attach = M.with_defaults("zls"), - settings = { - zls = { - warn_style = true, - highlight_global_var_declarations = true, - inlay_hints_show_variable_type_hints = false, - inlay_hints_show_struct_literal_field_type = false, - inlay_hints_show_parameter_name = false, - inlay_hints_show_builtin = false, - }, - }, - }) - - vim.lsp.config("pyrefly", {}) -end - -return M diff --git a/lua/plugins/nvim-cmp.lua b/lua/plugins/nvim-cmp.lua deleted file mode 100644 index ab50108..0000000 --- a/lua/plugins/nvim-cmp.lua +++ /dev/null @@ -1,232 +0,0 @@ --- https://github.com/hrsh7th/nvim-cmp - -local word_pattern = "[%w_.]" - -local function has_words_before() - unpack = unpack or table.unpack - local line, col = unpack(vim.api.nvim_win_get_cursor(0)) - return col ~= 0 - and vim.api - .nvim_buf_get_lines(0, line - 1, line, true)[1] - :sub(col, col) - :match(word_pattern) - ~= nil -end - -local function has_words_after() - unpack = unpack or table.unpack - local line, col = unpack(vim.api.nvim_win_get_cursor(0)) - return col ~= 0 - and vim.api - .nvim_buf_get_lines(0, line - 1, line, true)[1] - :sub(col + 1, col + 1) - :match(word_pattern) - ~= nil -end - ----@type LazyPluginSpec -return { - "hrsh7th/nvim-cmp", - dependencies = { - "saadparwaiz1/cmp_luasnip", - "hrsh7th/cmp-path", - "hrsh7th/cmp-cmdline", - "hrsh7th/cmp-nvim-lsp", - { - "L3MON4D3/LuaSnip", - config = function() - require("luasnip.loaders.from_vscode").lazy_load() - end, - build = ( - require("util").os_name ~= "Windows_NT" - and "make install_jsregexp" - or nil - ), - version = "2.*", - dependencies = { "rafamadriz/friendly-snippets" }, - }, - { - "onsails/lspkind.nvim", - config = function() - require("lspkind").init() - end, - }, - "teramako/cmp-cmdline-prompt.nvim", - }, - config = function() - local cmp = require("cmp") - local luasnip = require("luasnip") - local lspkind = require("lspkind") - - ---@type cmp.ConfigSchema - local opts = { - -- enabled = function() - -- return has_words_before() - -- end, - preselect = "None", - completion = { - autocomplete = { "InsertEnter", "TextChanged" }, - keyword_length = 1, - }, - snippet = { - expand = function(args) - luasnip.lsp_expand(args.body) - end, - }, - ---@diagnostic disable-next-line: missing-fields - formatting = { - format = function(entry, vim_item) - vim_item = lspkind.cmp_format({ - mode = "symbol", - maxwidth = 50, - ellipsis_char = "...", - before = function(_, item) - item.dup = 0 -- remove duplicates, see nvim-cmp #511 - return item - end, - })(entry, vim_item) - - return vim_item - end, - }, - - mapping = { - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_next_item({ - behavior = cmp.SelectBehavior.Select, - }) - else - fallback() - end - end), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item({ - behavior = cmp.SelectBehavior.Select, - }) - else - fallback() - end - end), - [""] = cmp.mapping.select_next_item({ - behavior = cmp.SelectBehavior.Select, - }), - [""] = cmp.mapping.select_prev_item({ - behavior = cmp.SelectBehavior.Select, - }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() and cmp.get_active_entry() then - cmp.confirm({ - select = false, - behavior = cmp.ConfirmBehavior.Replace, - }) - else - fallback() - end - end), - [""] = cmp.mapping.confirm({ - select = true, - behavior = cmp.ConfirmBehavior.Replace, - }), - [""] = cmp.mapping.complete(), - [""] = function(fallback) - if luasnip.locally_jumpable(1) then - luasnip.jump(1) - else - fallback() - end - end, - [""] = function(fallback) - if luasnip.locally_jumpable(-1) then - luasnip.jump(-1) - else - fallback() - end - end, - }, - sources = { - { name = "nvim_lsp" }, - { name = "luasnip" }, - { name = "orgmode" }, - { name = "path" }, - }, - window = { - completion = cmp.config.window.bordered({ - border = "none", - winhighlight = "Normal:Pmenu,CursorLine:PmenuSel,Search:None", - zindex = 1001, - scrolloff = 0, - col_offset = 0, - side_padding = 1, - scrollbar = true, - }), - documentation = cmp.config.window.bordered({ - border = "rounded", - winhighlight = "CursorLine:Visual,Search:None", - zindex = 1001, - max_height = 80, - }), - }, - } - - cmp.setup(opts) - cmp.setup.cmdline("/", { - mapping = cmp.mapping.preset.cmdline(), - sources = { { name = "buffer" } }, - }) - cmp.setup.cmdline(":", { - mapping = cmp.mapping.preset.cmdline(), - sources = cmp.config.sources({ { name = "path" } }, { - { - name = "cmdline", - option = { ignore_cmds = { "!" } }, - }, - }), - }) - -- for cmdline `input()` prompt - -- see: `:help getcmdtype()` - cmp.setup.cmdline("@", { - mapping = cmp.mapping.preset.cmdline(), - sources = cmp.config.sources({ - { - name = "cmdline-prompt", - ---@type prompt.Option - option = { - kinds = { - file = cmp.lsp.CompletionItemKind.File, - dir = { - kind = cmp.lsp.CompletionItemKind.Folder, - hl_group = "CmpItemKindEnum", - }, - }, - }, - }, - }), - formatting = { - fields = { "kind", "abbr", "menu" }, - format = function(entry, vim_item) - local item = entry.completion_item - if entry.source.name == "cmdline-prompt" then - vim_item.kind = cmp.lsp.CompletionItemKind[item.kind] - local kind = - lspkind.cmp_format({ mode = "symbol_text" })( - entry, - vim_item - ) - local strings = - vim.split(kind.kind, "%s", { trimempty = true }) - kind.kind = " " .. (strings[1] or "") - kind.menu = " (" - .. (item.data.completion_type or "") - .. ")" - kind.menu_hl_group = kind.kind_hl_group - return kind - else - return vim_item - end - end, - }, - }) - end, -}