diff options
Diffstat (limited to 'vim/.config/nvim/lsp')
26 files changed, 1045 insertions, 0 deletions
diff --git a/vim/.config/nvim/lsp/asm-lsp.lua b/vim/.config/nvim/lsp/asm-lsp.lua new file mode 100644 index 0000000..28678c0 --- /dev/null +++ b/vim/.config/nvim/lsp/asm-lsp.lua @@ -0,0 +1,15 @@ +---@brief +--- +--- https://github.com/bergercookie/asm-lsp +--- +--- Language Server for NASM/GAS/GO Assembly +--- +--- `asm-lsp` can be installed via cargo: +--- cargo install asm-lsp + +---@type vim.lsp.Config +return { + cmd = { 'asm-lsp' }, + filetypes = { 'asm', 'vmasm' }, + root_markers = { '.asm-lsp.toml', '.git' }, +} diff --git a/vim/.config/nvim/lsp/astro.lua b/vim/.config/nvim/lsp/astro.lua new file mode 100644 index 0000000..45a9e8b --- /dev/null +++ b/vim/.config/nvim/lsp/astro.lua @@ -0,0 +1,10 @@ +return { + cmd = { 'astro-ls', '--stdio' }, + filetypes = { 'astro' }, + root_markers = { 'package.json', 'tsconfig.json', 'jsconfig.json', '.git', '.jj' }, + init_options = { + typescript = { + tsdk = "./node_modules/typescript/lib" + }, + }, +} diff --git a/vim/.config/nvim/lsp/basedpyright.lua b/vim/.config/nvim/lsp/basedpyright.lua new file mode 100644 index 0000000..86fb411 --- /dev/null +++ b/vim/.config/nvim/lsp/basedpyright.lua @@ -0,0 +1,67 @@ +---@brief +--- +--- https://detachhead.github.io/basedpyright +--- +--- `basedpyright`, a static type checker and language server for python + +local function set_python_path(command) + local path = command.args + local clients = vim.lsp.get_clients { + bufnr = vim.api.nvim_get_current_buf(), + name = 'basedpyright', + } + for _, client in ipairs(clients) do + if client.settings then + client.settings.python = vim.tbl_deep_extend('force', client.settings.python or {}, { pythonPath = path }) + else + client.config.settings = vim.tbl_deep_extend('force', client.config.settings, { python = { pythonPath = path } }) + end + client:notify('workspace/didChangeConfiguration', { settings = nil }) + end +end + +---@type vim.lsp.Config +return { + cmd = { 'basedpyright-langserver', '--stdio' }, + filetypes = { 'python' }, + root_markers = { + 'pyproject.toml', + 'setup.py', + 'setup.cfg', + 'requirements.txt', + 'Pipfile', + 'pyrightconfig.json', + '.git', + '.jj' + }, + settings = { + basedpyright = { + analysis = { + autoSearchPaths = true, + useLibraryCodeForTypes = true, + diagnosticMode = 'openFilesOnly', + }, + }, + }, + on_attach = function(client, bufnr) + vim.api.nvim_buf_create_user_command(bufnr, 'LspPyrightOrganizeImports', function() + local params = { + command = 'basedpyright.organizeimports', + arguments = { vim.uri_from_bufnr(bufnr) }, + } + + -- Using client.request() directly because "basedpyright.organizeimports" is private + -- (not advertised via capabilities), which client:exec_cmd() refuses to call. + -- https://github.com/neovim/neovim/blob/c333d64663d3b6e0dd9aa440e433d346af4a3d81/runtime/lua/vim/lsp/client.lua#L1024-L1030 + client.request('workspace/executeCommand', params, nil, bufnr) + end, { + desc = 'Organize Imports', + }) + + vim.api.nvim_buf_create_user_command(bufnr, 'LspPyrightSetPythonPath', set_python_path, { + desc = 'Reconfigure basedpyright with the provided python path', + nargs = 1, + complete = 'file', + }) + end, +} diff --git a/vim/.config/nvim/lsp/ccls.lua b/vim/.config/nvim/lsp/ccls.lua new file mode 100644 index 0000000..f0a08c5 --- /dev/null +++ b/vim/.config/nvim/lsp/ccls.lua @@ -0,0 +1,26 @@ +return { + cmd = { + 'clangd', + -- '--clang-tidy', + -- '--background-index', + -- '--offset-encoding=utf-8', + }, + filetypes = { 'arduino' }, + root_markers = { + '.clangd', + '.ccls', + 'compile_commands.json', + 'compile_flags.txt', + 'configure.ac' -- AutoTools + }, + single_file_support = true, + capabilities = { + textDocument = { + completion = { + editsNearCursor = true, + }, + }, + offsetEncoding = { 'utf-8', 'utf-16' }, + }, +} + diff --git a/vim/.config/nvim/lsp/clangd.lua b/vim/.config/nvim/lsp/clangd.lua new file mode 100644 index 0000000..a3add02 --- /dev/null +++ b/vim/.config/nvim/lsp/clangd.lua @@ -0,0 +1,33 @@ +return { + cmd = { + 'clangd', + -- '--clang-tidy', + '--background-index', + '--offset-encoding=utf-8', + '--query-driver=/Users/scie/.platformio/packages/toolchain-xtensa-esp32/**', + '--query-driver=/Users/scie/.platformio/packages/framework-arduinoststm32/**', + -- '--query-driver=/Users/scie/.platformio/packages/**', + -- '--query-driver=/opt/homebrew/Cellar/avr-gcc@9/9.4.0_1/bin/avr-gcc', + -- '--query-driver=/opt/homebrew/Cellar/avr-gcc@9/9.4.0_1/bin/avr-g++' + }, + filetypes = { 'c', 'cpp', 'objc', 'objcpp', 'cuda', 'proto', 'arduino' }, + root_markers = { + '.clangd', + '.clang-tidy', + '.clang-format', + 'compile_commands.json', + 'compile_flags.txt', + 'configure.ac', -- AutoTools + '.git', + '.jj' + }, + single_file_support = true, + capabilities = { + textDocument = { + completion = { + editsNearCursor = true, + }, + }, + offsetEncoding = { 'utf-8', 'utf-16' }, + }, +} diff --git a/vim/.config/nvim/lsp/codebook.lua b/vim/.config/nvim/lsp/codebook.lua new file mode 100644 index 0000000..226046e --- /dev/null +++ b/vim/.config/nvim/lsp/codebook.lua @@ -0,0 +1,40 @@ +---@brief +--- +--- https://github.com/blopker/codebook +--- +--- An unholy spell checker for code. +--- +--- `codebook-lsp` can be installed by following the instructions [here](https://github.com/blopker/codebook/blob/main/README.md#installation). +--- +--- The default `cmd` assumes that the `codebook-lsp` binary can be found in `$PATH`. +--- + +---@type vim.lsp.Config +return { + cmd = { 'codebook-lsp', 'serve' }, + filetypes = { + 'c', + 'css', + 'gitcommit', + 'go', + 'haskell', + 'html', + 'java', + 'javascript', + 'javascriptreact', + 'lua', + 'markdown', + 'php', + 'python', + 'ruby', + 'rust', + 'swift', + 'toml', + 'text', + 'typescript', + 'typescriptreact', + 'typst', + 'zig', + }, + root_markers = { '.git', '.jj', 'codebook.toml', '.codebook.toml' }, +} diff --git a/vim/.config/nvim/lsp/csharp-ls.lua b/vim/.config/nvim/lsp/csharp-ls.lua new file mode 100644 index 0000000..037650b --- /dev/null +++ b/vim/.config/nvim/lsp/csharp-ls.lua @@ -0,0 +1,9 @@ +---@type vim.lsp.Config +return { + cmd = { 'csharp-ls' }, + root_markers = { ".git" }, + filetypes = { 'cs' }, + init_options = { + AutomaticWorkspaceInit = true, + }, +} diff --git a/vim/.config/nvim/lsp/cspell-ls.lua b/vim/.config/nvim/lsp/cspell-ls.lua new file mode 100644 index 0000000..b3c60db --- /dev/null +++ b/vim/.config/nvim/lsp/cspell-ls.lua @@ -0,0 +1,30 @@ +---@brief +--- +--- [cspell language server](https://github.com/vlabo/cspell-lsp) +--- +return { + cmd = { 'cspell-lsp', '--stdio' }, + filetypes = { "go", "rust", "js", "ts", "html", "css", "json", "yaml", "markdown", "gitcommit", "typst", "lua", "htmlua", "c", "cpp", "arduino" }, + root_markers = { + '.git', + '.jj', + 'cspell.json', + '.cspell.json', + 'cspell.json', + '.cSpell.json', + 'cSpell.json', + 'cspell.config.js', + 'cspell.config.cjs', + 'cspell.config.json', + 'cspell.config.yaml', + 'cspell.config.yml', + 'cspell.yaml', + 'cspell.yml', + }, + init_options = { + userWordsFile = vim.fn.expand('~/.config/cspell/user-dictionary.txt'), + configPaths = { + vim.fn.expand('~/.cspell.json'), + }, + }, +} diff --git a/vim/.config/nvim/lsp/css.lua b/vim/.config/nvim/lsp/css.lua new file mode 100644 index 0000000..9314747 --- /dev/null +++ b/vim/.config/nvim/lsp/css.lua @@ -0,0 +1,34 @@ +---@brief +--- +--- https://github.com/hrsh7th/vscode-langservers-extracted +--- +--- `css-languageserver` can be installed via `npm`: +--- +--- ```sh +--- npm i -g vscode-langservers-extracted +--- ``` +--- +--- Neovim does not currently include built-in snippets. `vscode-css-language-server` only provides completions when snippet support is enabled. To enable completion, install a snippet plugin and add the following override to your language client capabilities during setup. +--- +--- ```lua +--- --Enable (broadcasting) snippet capability for completion +--- local capabilities = vim.lsp.protocol.make_client_capabilities() +--- capabilities.textDocument.completion.completionItem.snippetSupport = true +--- +--- vim.lsp.config('cssls', { +--- capabilities = capabilities, +--- }) +--- ``` + +---@type vim.lsp.Config +return { + cmd = { 'vscode-css-language-server', '--stdio' }, + filetypes = { 'css', 'scss', 'less' }, + init_options = { provideFormatter = true }, -- needed to enable formatting capabilities + root_markers = { 'package.json', '.git', '.jj' }, + settings = { + css = { validate = true }, + scss = { validate = true }, + less = { validate = true }, + }, +} diff --git a/vim/.config/nvim/lsp/eslint.lua b/vim/.config/nvim/lsp/eslint.lua new file mode 100644 index 0000000..07d4ed7 --- /dev/null +++ b/vim/.config/nvim/lsp/eslint.lua @@ -0,0 +1,221 @@ +--- @brief +--- +--- https://github.com/hrsh7th/vscode-langservers-extracted +--- +--- `vscode-eslint-language-server` is a linting engine for JavaScript / Typescript. +--- It can be installed via `npm`: +--- +--- ```sh +--- npm i -g vscode-langservers-extracted +--- ``` +--- +--- The default `on_attach` config provides the `LspEslintFixAll` command that can be used to format a document on save: +--- ```lua +--- local base_on_attach = vim.lsp.config.eslint.on_attach +--- vim.lsp.config("eslint", { +--- on_attach = function(client, bufnr) +--- if not base_on_attach then return end +--- +--- base_on_attach(client, bufnr) +--- vim.api.nvim_create_autocmd("BufWritePre", { +--- buffer = bufnr, +--- command = "LspEslintFixAll", +--- }) +--- end, +--- }) +--- ``` +--- +--- See [vscode-eslint](https://github.com/microsoft/vscode-eslint/blob/55871979d7af184bf09af491b6ea35ebd56822cf/server/src/eslintServer.ts#L216-L229) for configuration options. +--- +--- Messages handled in lspconfig: `eslint/openDoc`, `eslint/confirmESLintExecution`, `eslint/probeFailed`, `eslint/noLibrary` +--- +--- Additional messages you can handle: `eslint/noConfig` +--- +--- ### Monorepo support +--- +--- `vscode-eslint-language-server` supports monorepos by default. It will automatically find the config file corresponding to the package you are working on. You can use different configs in different packages. +--- This works without the need of spawning multiple instances of `vscode-eslint-language-server`. +--- You can use a different version of ESLint in each package, but it is recommended to use the same version of ESLint in all packages. The location of the ESLint binary will be determined automatically. +--- +--- /!\ When using flat config files, you need to use them across all your packages in your monorepo, as it's a global setting for the server. +--- +--- ### Flat config in ESLint versions prior to 10.0 +--- +--- If you're using a ESLint version that supports both flat config and eslintrc (>= 8.21, < 10.0) and want to change +--- the [default behavior](https://eslint.org/blog/2023/10/flat-config-rollout-plans/), you'll need to set +--- `experimental.useFlatConfig` accordingly: +--- ```lua +--- vim.lsp.config("eslint", { +--- settings = { +--- experimental = { +--- -- If you want to use flat config on >= 8.21, < 9.0 +--- useFlatConfig = true, +--- -- Or if you want to use eslintrc on 9.* +--- -- useFlatConfig = false, +--- } +--- } +--- }) +--- ``` + +-- local util = require 'lspconfig.util' +local lsp = vim.lsp + +local eslint_config_files = { + '.eslintrc', + '.eslintrc.js', + '.eslintrc.cjs', + '.eslintrc.yaml', + '.eslintrc.yml', + '.eslintrc.json', + 'eslint.config.js', + 'eslint.config.mjs', + 'eslint.config.cjs', + 'eslint.config.ts', + 'eslint.config.mts', + 'eslint.config.cts', +} + +---@type vim.lsp.Config +return { + cmd = { 'vscode-eslint-language-server', '--stdio' }, + filetypes = { + 'javascript', + 'javascriptreact', + 'typescript', + 'typescriptreact', + 'vue', + 'svelte', + 'astro', + 'htmlangular', + }, + workspace_required = true, + -- on_attach = function(client, bufnr) + -- vim.api.nvim_buf_create_user_command(bufnr, 'LspEslintFixAll', function() + -- client:request_sync('workspace/executeCommand', { + -- command = 'eslint.applyAllFixes', + -- arguments = { + -- { + -- uri = vim.uri_from_bufnr(bufnr), + -- version = lsp.util.buf_versions[bufnr], + -- }, + -- }, + -- }, nil, bufnr) + -- end, {}) + -- end, + root_dir = function(bufnr, on_dir) + -- The project root is where the LSP can be started from + -- As stated in the documentation above, this LSP supports monorepos and simple projects. + -- We select then from the project root, which is identified by the presence of a package + -- manager lock file. + local root_markers = { 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb', 'bun.lock' } + -- Give the root markers equal priority by wrapping them in a table + root_markers = vim.fn.has('nvim-0.11.3') == 1 and { root_markers, { '.git', '.jj' } } + or vim.list_extend(root_markers, { '.git' }) + + -- exclude deno + if vim.fs.root(bufnr, { 'deno.json', 'deno.jsonc', 'deno.lock' }) then + return + end + + -- We fallback to the current working directory if no project root is found + local project_root = vim.fs.root(bufnr, root_markers) or vim.fn.getcwd() + + -- We know that the buffer is using ESLint if it has a config file + -- in its directory tree. + -- + -- Eslint used to support package.json files as config files, but it doesn't anymore. + -- We keep this for backward compatibility. + -- local filename = vim.api.nvim_buf_get_name(bufnr) + -- local eslint_config_files_with_package_json = + -- util.insert_package_json(eslint_config_files, 'eslintConfig', filename) + -- local is_buffer_using_eslint = vim.fs.find(eslint_config_files_with_package_json, { + -- path = filename, + -- type = 'file', + -- limit = 1, + -- upward = true, + -- stop = vim.fs.dirname(project_root), + -- })[1] + -- if not is_buffer_using_eslint then + -- return + -- end + + on_dir(project_root) + end, + -- Refer to https://github.com/Microsoft/vscode-eslint#settings-options for documentation. + settings = { + validate = 'on', + ---@diagnostic disable-next-line: assign-type-mismatch + packageManager = nil, + useESLintClass = false, + experimental = {}, + codeActionOnSave = { + enable = false, + mode = 'all', + }, + format = true, + quiet = false, + onIgnoredFiles = 'off', + rulesCustomizations = {}, + run = 'onType', + problems = { + shortenToSingleLine = false, + }, + -- nodePath configures the directory in which the eslint server should start its node_modules resolution. + -- This path is relative to the workspace folder (root dir) of the server instance. + nodePath = '', + -- use the workspace folder location or the file location (if no workspace folder is open) as the working directory + workingDirectory = { mode = 'auto' }, + codeAction = { + disableRuleComment = { + enable = true, + location = 'separateLine', + }, + showDocumentation = { + enable = true, + }, + }, + }, + before_init = function(_, config) + -- The "workspaceFolder" is a VSCode concept. It limits how far the + -- server will traverse the file system when locating the ESLint config + -- file (e.g., .eslintrc). + local root_dir = config.root_dir + + if root_dir then + config.settings = config.settings or {} + config.settings.workspaceFolder = { + uri = root_dir, + name = vim.fn.fnamemodify(root_dir, ':t'), + } + + -- Support Yarn2 (PnP) projects + local pnp_cjs = root_dir .. '/.pnp.cjs' + local pnp_js = root_dir .. '/.pnp.js' + if type(config.cmd) == 'table' and (vim.uv.fs_stat(pnp_cjs) or vim.uv.fs_stat(pnp_js)) then + config.cmd = vim.list_extend({ 'yarn', 'exec' }, config.cmd --[[@as table]]) + end + end + end, + handlers = { + ['eslint/openDoc'] = function(_, result) + if result then + vim.ui.open(result.url) + end + return {} + end, + ['eslint/confirmESLintExecution'] = function(_, result) + if not result then + return + end + return 4 -- approved + end, + ['eslint/probeFailed'] = function() + vim.notify('[lspconfig] ESLint probe failed.', vim.log.levels.WARN) + return {} + end, + ['eslint/noLibrary'] = function() + vim.notify('[lspconfig] Unable to find ESLint library.', vim.log.levels.WARN) + return {} + end, + }, +} diff --git a/vim/.config/nvim/lsp/fish-lsp.lua b/vim/.config/nvim/lsp/fish-lsp.lua new file mode 100644 index 0000000..d0e6500 --- /dev/null +++ b/vim/.config/nvim/lsp/fish-lsp.lua @@ -0,0 +1,17 @@ +---@brief +--- +--- https://github.com/ndonfris/fish-lsp +--- +--- A Language Server Protocol (LSP) tailored for the fish shell. +--- This project aims to enhance the coding experience for fish, +--- by introducing a suite of intelligent features like auto-completion, +--- scope aware symbol analysis, per-token hover generation, and many others. +--- +--- [homepage](https://www.fish-lsp.dev/) + +---@type vim.lsp.Config +return { + cmd = { 'fish-lsp', 'start' }, + filetypes = { 'fish' }, + root_markers = { 'config.fish', '.git', '.jj' }, +} diff --git a/vim/.config/nvim/lsp/gdscript.lua b/vim/.config/nvim/lsp/gdscript.lua new file mode 100644 index 0000000..aaba5a3 --- /dev/null +++ b/vim/.config/nvim/lsp/gdscript.lua @@ -0,0 +1,9 @@ +local port = os.getenv 'GDScript_Port' or '6005' +local cmd = vim.lsp.rpc.connect('127.0.0.1', tonumber(port)) + +---@type vim.lsp.Config +return { + cmd = cmd, + filetypes = { 'gd', 'gdscript', 'gdscript3' }, + root_markers = { 'project.godot', '.git', '.jj' }, +} diff --git a/vim/.config/nvim/lsp/gopls.lua b/vim/.config/nvim/lsp/gopls.lua new file mode 100644 index 0000000..1cec249 --- /dev/null +++ b/vim/.config/nvim/lsp/gopls.lua @@ -0,0 +1,98 @@ +---@brief +--- +--- https://github.com/golang/tools/tree/master/gopls +--- +--- Google's lsp server for golang. + +--- @class go_dir_custom_args +--- +--- @field envvar_id string +--- +--- @field custom_subdir string? + +local mod_cache = nil +local std_lib = nil + +---@param custom_args go_dir_custom_args +---@param on_complete fun(dir: string | nil) +local function identify_go_dir(custom_args, on_complete) + local cmd = { 'go', 'env', custom_args.envvar_id } + vim.system(cmd, { text = true }, function(output) + local res = vim.trim(output.stdout or '') + if output.code == 0 and res ~= '' then + if custom_args.custom_subdir and custom_args.custom_subdir ~= '' then + res = res .. custom_args.custom_subdir + end + on_complete(res) + else + vim.schedule(function() + vim.notify( + ('[gopls] identify ' .. custom_args.envvar_id .. ' dir cmd failed with code %d: %s\n%s'):format( + output.code, + vim.inspect(cmd), + output.stderr + ) + ) + end) + on_complete(nil) + end + end) +end + +---@return string? +local function get_std_lib_dir() + if std_lib and std_lib ~= '' then + return std_lib + end + + identify_go_dir({ envvar_id = 'GOROOT', custom_subdir = '/src' }, function(dir) + if dir then + std_lib = dir + end + end) + return std_lib +end + +---@return string? +local function get_mod_cache_dir() + if mod_cache and mod_cache ~= '' then + return mod_cache + end + + identify_go_dir({ envvar_id = 'GOMODCACHE' }, function(dir) + if dir then + mod_cache = dir + end + end) + return mod_cache +end + +---@param fname string +---@return string? +local function get_root_dir(fname) + if mod_cache and fname:sub(1, #mod_cache) == mod_cache then + local clients = vim.lsp.get_clients({ name = 'gopls' }) + if #clients > 0 then + return clients[#clients].config.root_dir + end + end + if std_lib and fname:sub(1, #std_lib) == std_lib then + local clients = vim.lsp.get_clients({ name = 'gopls' }) + if #clients > 0 then + return clients[#clients].config.root_dir + end + end + return vim.fs.root(fname, 'go.work') or vim.fs.root(fname, 'go.mod') or vim.fs.root(fname, '.git') or vim.fs.root(fname, '.jj') +end + +return { + cmd = { 'gopls' }, + filetypes = { 'go', 'gomod', 'gowork', 'gotmpl' }, + root_dir = function(bufnr, on_dir) + local fname = vim.api.nvim_buf_get_name(bufnr) + get_mod_cache_dir() + get_std_lib_dir() + -- see: https://github.com/neovim/nvim-lspconfig/issues/804 + on_dir(get_root_dir(fname)) + end, +} diff --git a/vim/.config/nvim/lsp/html.lua b/vim/.config/nvim/lsp/html.lua new file mode 100644 index 0000000..e9ac9c4 --- /dev/null +++ b/vim/.config/nvim/lsp/html.lua @@ -0,0 +1,36 @@ +---@brief +--- +--- https://github.com/hrsh7th/vscode-langservers-extracted +--- +--- `vscode-html-language-server` can be installed via `npm`: +--- ```sh +--- npm i -g vscode-langservers-extracted +--- ``` +--- +--- Neovim does not currently include built-in snippets. `vscode-html-language-server` only provides completions when snippet support is enabled. +--- To enable completion, install a snippet plugin and add the following override to your language client capabilities during setup. +--- +--- The code-formatting feature of the lsp can be controlled with the `provideFormatter` option. +--- +--- ```lua +--- --Enable (broadcasting) snippet capability for completion +--- local capabilities = vim.lsp.protocol.make_client_capabilities() +--- capabilities.textDocument.completion.completionItem.snippetSupport = true +--- +--- vim.lsp.config('html', { +--- capabilities = capabilities, +--- }) +--- ``` + +---@type vim.lsp.Config +return { + cmd = { 'vscode-html-language-server', '--stdio' }, + filetypes = { 'html' }, + root_markers = { 'package.json', '.git', '.jj' }, + settings = {}, + init_options = { + provideFormatter = true, + embeddedLanguages = { css = true, javascript = true }, + configurationSection = { 'html', 'css', 'javascript' }, + }, +} diff --git a/vim/.config/nvim/lsp/json.lua b/vim/.config/nvim/lsp/json.lua new file mode 100644 index 0000000..3ef906c --- /dev/null +++ b/vim/.config/nvim/lsp/json.lua @@ -0,0 +1,32 @@ +---@brief +--- +--- https://github.com/hrsh7th/vscode-langservers-extracted +--- +--- vscode-json-language-server, a language server for JSON and JSON schema +--- +--- `vscode-json-language-server` can be installed via `npm`: +--- ```sh +--- npm i -g vscode-langservers-extracted +--- ``` +--- +--- `vscode-json-language-server` only provides completions when snippet support is enabled. If you use Neovim older than v0.10 you need to enable completion, install a snippet plugin and add the following override to your language client capabilities during setup. +--- +--- ```lua +--- --Enable (broadcasting) snippet capability for completion +--- local capabilities = vim.lsp.protocol.make_client_capabilities() +--- capabilities.textDocument.completion.completionItem.snippetSupport = true +--- +--- vim.lsp.config('jsonls', { +--- capabilities = capabilities, +--- }) +--- ``` + +---@type vim.lsp.Config +return { + cmd = { 'vscode-json-language-server', '--stdio' }, + filetypes = { 'json', 'jsonc' }, + init_options = { + provideFormatter = true, + }, + root_markers = { '.git', '.jj' }, +} diff --git a/vim/.config/nvim/lsp/luals.lua b/vim/.config/nvim/lsp/luals.lua new file mode 100644 index 0000000..745f38a --- /dev/null +++ b/vim/.config/nvim/lsp/luals.lua @@ -0,0 +1,5 @@ +return { + cmd = {'lua-language-server'}, + filetypes = {'lua'}, + root_markers = {'.luarc.json', '.luarc.jsonc'}, +} diff --git a/vim/.config/nvim/lsp/pyright.lua b/vim/.config/nvim/lsp/pyright.lua new file mode 100644 index 0000000..b501b85 --- /dev/null +++ b/vim/.config/nvim/lsp/pyright.lua @@ -0,0 +1,66 @@ +---@brief +--- +--- https://github.com/microsoft/pyright +--- +--- `pyright`, a static type checker and language server for python + +local function set_python_path(command) + local path = command.args + local clients = vim.lsp.get_clients { + bufnr = vim.api.nvim_get_current_buf(), + name = 'pyright', + } + for _, client in ipairs(clients) do + if client.settings then + client.settings.python = vim.tbl_deep_extend('force', client.settings.python, { pythonPath = path }) + else + client.config.settings = vim.tbl_deep_extend('force', client.config.settings, { python = { pythonPath = path } }) + end + client:notify('workspace/didChangeConfiguration', { settings = nil }) + end +end + +---@type vim.lsp.Config +return { + cmd = { 'pyright-langserver', '--stdio' }, + filetypes = { 'python' }, + root_markers = { + 'pyproject.toml', + 'setup.py', + 'setup.cfg', + 'requirements.txt', + 'Pipfile', + 'pyrightconfig.json', + '.git', + '.jj' + }, + settings = { + python = { + analysis = { + autoSearchPaths = true, + useLibraryCodeForTypes = true, + diagnosticMode = 'openFilesOnly', + }, + }, + }, + on_attach = function(client, bufnr) + vim.api.nvim_buf_create_user_command(bufnr, 'LspPyrightOrganizeImports', function() + local params = { + command = 'pyright.organizeimports', + arguments = { vim.uri_from_bufnr(bufnr) }, + } + + -- Using client.request() directly because "pyright.organizeimports" is private + -- (not advertised via capabilities), which client:exec_cmd() refuses to call. + -- https://github.com/neovim/neovim/blob/c333d64663d3b6e0dd9aa440e433d346af4a3d81/runtime/lua/vim/lsp/client.lua#L1024-L1030 + client.request('workspace/executeCommand', params, nil, bufnr) + end, { + desc = 'Organize Imports', + }) + vim.api.nvim_buf_create_user_command(bufnr, 'LspPyrightSetPythonPath', set_python_path, { + desc = 'Reconfigure pyright with the provided python path', + nargs = 1, + complete = 'file', + }) + end, +} diff --git a/vim/.config/nvim/lsp/ruff.lua b/vim/.config/nvim/lsp/ruff.lua new file mode 100644 index 0000000..7fb61ea --- /dev/null +++ b/vim/.config/nvim/lsp/ruff.lua @@ -0,0 +1,35 @@ +---@brief +--- +--- https://github.com/astral-sh/ruff +--- +--- A Language Server Protocol implementation for Ruff, an extremely fast Python linter and code formatter, written in Rust. It can be installed via `pip`. +--- +--- ```sh +--- pip install ruff +--- ``` +--- +--- **Available in Ruff `v0.4.5` in beta and stabilized in Ruff `v0.5.3`.** +--- +--- This is the new built-in language server written in Rust. It supports the same feature set as `ruff-lsp`, but with superior performance and no installation required. Note that the `ruff-lsp` server will continue to be maintained until further notice. +--- +--- Server settings can be provided via: +--- +--- ```lua +--- vim.lsp.config('ruff', { +--- init_options = { +--- settings = { +--- -- Server settings should go here +--- } +--- } +--- }) +--- ``` +--- +--- Refer to the [documentation](https://docs.astral.sh/ruff/editors/) for more details. + +---@type vim.lsp.Config +return { + cmd = { 'ruff', 'server' }, + filetypes = { 'python' }, + root_markers = { 'pyproject.toml', 'ruff.toml', '.ruff.toml', '.git' }, + settings = {}, +} diff --git a/vim/.config/nvim/lsp/rust-analyzer.lua b/vim/.config/nvim/lsp/rust-analyzer.lua new file mode 100644 index 0000000..31c9b63 --- /dev/null +++ b/vim/.config/nvim/lsp/rust-analyzer.lua @@ -0,0 +1,15 @@ +return { + cmd = { "rust-analyzer" }, + filetypes = { "rust", "rs" }, + root_markers = { "Cargo.lock" }, + settings = { + ["rust-analyzer"] = { + check = { + command = "clippy", + }, + diagnostics = { + enable = true, + }, + }, + }, +} diff --git a/vim/.config/nvim/lsp/superhtml.lua b/vim/.config/nvim/lsp/superhtml.lua new file mode 100644 index 0000000..fcbe24b --- /dev/null +++ b/vim/.config/nvim/lsp/superhtml.lua @@ -0,0 +1,22 @@ +---@brief +--- +--- https://github.com/kristoff-it/superhtml +--- +--- HTML Language Server & Templating Language Library +--- +--- This LSP is designed to tightly adhere to the HTML spec as well as enforcing +--- some additional rules that ensure HTML clarity. +--- +--- If you want to disable HTML support for another HTML LSP, add the following +--- to your configuration: +--- +--- ```lua +--- vim.lsp.config('superhtml', { +--- filetypes = { 'superhtml' } +--- }) +--- ``` +return { + cmd = { 'superhtml', 'lsp' }, + filetypes = { 'superhtml', 'html', "htmldjango" }, + root_markers = { '.git', '.jj' }, +} diff --git a/vim/.config/nvim/lsp/tailwind-ls.lua b/vim/.config/nvim/lsp/tailwind-ls.lua new file mode 100644 index 0000000..9ab35a8 --- /dev/null +++ b/vim/.config/nvim/lsp/tailwind-ls.lua @@ -0,0 +1,62 @@ +return { + cmd = { 'tailwindcss-language-server', '--stdio' }, + filetypes = { + -- html + 'aspnetcorerazor', + 'astro', + 'astro-markdown', + 'blade', + 'clojure', + 'django-html', + 'htmldjango', + 'edge', + 'eelixir', -- vim ft + 'elixir', + 'ejs', + 'erb', + 'eruby', -- vim ft + 'gohtml', + 'gohtmltmpl', + 'haml', + 'handlebars', + 'hbs', + 'html', + 'htmlangular', + 'html-eex', + 'heex', + 'jade', + 'leaf', + 'liquid', + 'markdown', + 'mdx', + 'mustache', + 'njk', + 'nunjucks', + 'php', + 'razor', + 'slim', + 'twig', + -- css + 'css', + 'less', + 'postcss', + 'sass', + 'scss', + 'stylus', + 'sugarss', + -- js + 'javascript', + 'javascriptreact', + 'reason', + 'rescript', + 'typescript', + 'typescriptreact', + -- mixed + 'vue', + 'svelte', + 'templ', + }, + root_markers = { + 'tailwind.config.js' + }, +} diff --git a/vim/.config/nvim/lsp/textlsp.lua b/vim/.config/nvim/lsp/textlsp.lua new file mode 100644 index 0000000..a1dbfc8 --- /dev/null +++ b/vim/.config/nvim/lsp/textlsp.lua @@ -0,0 +1,48 @@ +return { + cmd = {"textlsp"}, -- You may need to provide the full path to textlsp if not in $PATH + filetypes = { "markdown", "org", "latex", "txt", "md", "markdown" }, -- and any other you want as plain text + root_markers = { + ".git", + }, + single_file_support = true, + capabilities = { + textDocument = { + completion = { + editsNearCursor = true, + }, + }, + -- textLSP does not require offsetEncoding, but you may include it for consistency: + offsetEncoding = { "utf-8", "utf-16" }, + }, + settings = { + textLSP = { + analysers = { + languagetool = { + enabled = false, + -- check_text = { + -- on_open = true, + -- on_save = true, + -- on_change = false, + -- }, + }, + ollama = { + enabled = true, + check_text = { + on_open = false, + on_save = true, + on_change = false, + }, + model = "phi3:3.8b-instruct", + max_token = 50, + }, + -- enable and configure other analyzers as desired + }, + documents = { + language = "auto:en", + min_length_language_detect = 20, + org = { org_todo_keywords = { "TODO", "IN_PROGRESS", "DONE" } }, + txt = { parse = true }, + }, + }, + }, +} diff --git a/vim/.config/nvim/lsp/tinymist.lua b/vim/.config/nvim/lsp/tinymist.lua new file mode 100644 index 0000000..eddcd7e --- /dev/null +++ b/vim/.config/nvim/lsp/tinymist.lua @@ -0,0 +1,77 @@ +---@brief +--- +--- https://github.com/Myriad-Dreamin/tinymist +--- An integrated language service for Typst [taɪpst]. You can also call it "微霭" [wēi ǎi] in Chinese. +--- +--- Currently some of Tinymist's workspace commands are supported, namely: +--- `LspTinymistExportSvg`, `LspTinymistExportPng`, `LspTinymistExportPdf +--- `LspTinymistExportMarkdown`, `LspTinymistExportText`, `LspTinymistExportQuery`, +--- `LspTinymistExportAnsiHighlight`, `LspTinymistGetServerInfo`, +--- `LspTinymistGetDocumentTrace`, `LspTinymistGetWorkspaceLabels`, and +--- `LspTinymistGetDocumentMetrics`. + +---@param command_name string +---@param client vim.lsp.Client +---@param bufnr integer +---@return fun():nil run_tinymist_command, string cmd_name, string cmd_desc +local function create_tinymist_command(command_name, client, bufnr) + local export_type = command_name:match 'tinymist%.export(%w+)' + local info_type = command_name:match 'tinymist%.(%w+)' + if info_type and info_type:match '^get' then + info_type = info_type:gsub('^get', 'Get') + end + local cmd_display = export_type or info_type + ---@return nil + local function run_tinymist_command() + local arguments = { vim.api.nvim_buf_get_name(bufnr) } + local title_str = export_type and ('Export ' .. cmd_display) or cmd_display + ---@type lsp.Handler + local function handler(err, res) + if err then + return vim.notify(err.code .. ': ' .. err.message, vim.log.levels.ERROR) + end + -- If exporting, show the string result; else, show the table for inspection + vim.notify(export_type and res or vim.inspect(res), vim.log.levels.INFO) + end + return client:exec_cmd({ + title = title_str, + command = command_name, + arguments = arguments, + }, { bufnr = bufnr }, handler) + end + -- Construct a readable command name/desc + local cmd_name = export_type and ('TinymistExport' .. cmd_display) or ('Tinymist' .. cmd_display) ---@type string + local cmd_desc = export_type and ('Export to ' .. cmd_display) or ('Get ' .. cmd_display) ---@type string + return run_tinymist_command, cmd_name, cmd_desc +end + +---@type vim.lsp.Config +return { + cmd = { 'tinymist' }, + filetypes = { 'typst' }, + root_markers = { '.git', '.jj' }, + on_attach = function(client, bufnr) + for _, command in ipairs { + 'tinymist.exportSvg', + 'tinymist.exportPng', + 'tinymist.exportPdf', + -- 'tinymist.exportHtml', -- Use typst 0.13 + 'tinymist.exportMarkdown', + 'tinymist.exportText', + 'tinymist.exportQuery', + 'tinymist.exportAnsiHighlight', + 'tinymist.getServerInfo', + 'tinymist.getDocumentTrace', + 'tinymist.getWorkspaceLabels', + 'tinymist.getDocumentMetrics', + } do + local cmd_func, cmd_name, cmd_desc = create_tinymist_command(command, client, bufnr) + vim.api.nvim_buf_create_user_command(bufnr, 'Lsp' .. cmd_name, cmd_func, { nargs = 0, desc = cmd_desc }) + end + end, + settings = { + ["tinymist"] = { + formatterMode = "typstyle" + } + } +} diff --git a/vim/.config/nvim/lsp/ty.lua b/vim/.config/nvim/lsp/ty.lua new file mode 100644 index 0000000..92efaa0 --- /dev/null +++ b/vim/.config/nvim/lsp/ty.lua @@ -0,0 +1,14 @@ +---@brief +--- +--- https://github.com/astral-sh/ty +--- +--- A Language Server Protocol implementation for ty, an extremely fast Python type checker and language server, written in Rust. +--- +--- For installation instructions, please refer to the [ty documentation](https://github.com/astral-sh/ty/blob/main/README.md#getting-started). + +---@type vim.lsp.Config +return { + cmd = { 'ty', 'server' }, + filetypes = { 'python' }, + root_markers = { 'ty.toml', 'pyproject.toml', 'setup.py', 'setup.cfg', 'requirements.txt', '.git', '.jj' }, +} diff --git a/vim/.config/nvim/lsp/zigscient.lua b/vim/.config/nvim/lsp/zigscient.lua new file mode 100644 index 0000000..bdb256f --- /dev/null +++ b/vim/.config/nvim/lsp/zigscient.lua @@ -0,0 +1,12 @@ +---@brief +--- https://github.com/zigtools/zls +--- +--- Zig LSP implementation + Zig Language Server + +---@type vim.lsp.Config +return { + cmd = { 'zigscient' }, + filetypes = { 'zig', 'zir' }, + root_markers = { 'zls.json', 'build.zig', '.git', '.jj' }, + workspace_required = false, +} diff --git a/vim/.config/nvim/lsp/zls.lua b/vim/.config/nvim/lsp/zls.lua new file mode 100644 index 0000000..6716521 --- /dev/null +++ b/vim/.config/nvim/lsp/zls.lua @@ -0,0 +1,12 @@ +---@brief +--- https://github.com/zigtools/zls +--- +--- Zig LSP implementation + Zig Language Server + +---@type vim.lsp.Config +return { + cmd = { 'zls' }, + filetypes = { 'zig', 'zir' }, + root_markers = { 'zls.json', 'build.zig', '.git', '.jj' }, + workspace_required = false, +} |
