feat: lazy, mason, ts
This commit is contained in:
parent
08c5a0536e
commit
bb12a11cc0
@ -1,8 +1,7 @@
|
|||||||
{
|
{
|
||||||
"conform.nvim": { "branch": "master", "commit": "235dd79731c1dc51ec04abb4045cbc54727a172a" },
|
"conform.nvim": { "branch": "master", "commit": "9fd3d5e0b689ec1bf400c53cbbec72c6fdf24081" },
|
||||||
"invero.nvim": { "branch": "main", "commit": "6acdefa2f2fdf544b53b5786e748be0ae8e9fd23" },
|
"invero.nvim": { "branch": "main", "commit": "6acdefa2f2fdf544b53b5786e748be0ae8e9fd23" },
|
||||||
"lazy.nvim": { "branch": "main", "commit": "1ea3c4085785f460fb0e46d2fe1ee895f5f9e7c1" },
|
"lazy.nvim": { "branch": "main", "commit": "1ea3c4085785f460fb0e46d2fe1ee895f5f9e7c1" },
|
||||||
"mason-lspconfig.nvim": { "branch": "main", "commit": "2304ff65ecc8cb2afc2484de3e2ed9a407edf0b9" },
|
|
||||||
"mason.nvim": { "branch": "main", "commit": "ad7146aa61dcaeb54fa900144d768f040090bff0" },
|
"mason.nvim": { "branch": "main", "commit": "ad7146aa61dcaeb54fa900144d768f040090bff0" },
|
||||||
"nvim-autopairs": { "branch": "master", "commit": "7a2c97cccd60abc559344042fefb1d5a85b3e33b" },
|
"nvim-autopairs": { "branch": "master", "commit": "7a2c97cccd60abc559344042fefb1d5a85b3e33b" },
|
||||||
"nvim-lint": { "branch": "master", "commit": "9da1fb942dd0668d5182f9c8dee801b9c190e2bb" },
|
"nvim-lint": { "branch": "master", "commit": "9da1fb942dd0668d5182f9c8dee801b9c190e2bb" },
|
||||||
|
|||||||
29
lsp/bashls.lua
Normal file
29
lsp/bashls.lua
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
---@brief
|
||||||
|
---
|
||||||
|
--- https://github.com/bash-lsp/bash-language-server
|
||||||
|
---
|
||||||
|
--- `bash-language-server` can be installed via `npm`:
|
||||||
|
--- ```sh
|
||||||
|
--- npm i -g bash-language-server
|
||||||
|
--- ```
|
||||||
|
---
|
||||||
|
--- Language server for bash, written using tree sitter in typescript.
|
||||||
|
|
||||||
|
---@type vim.lsp.Config
|
||||||
|
return {
|
||||||
|
cmd = { 'bash-language-server', 'start' },
|
||||||
|
settings = {
|
||||||
|
bashIde = {
|
||||||
|
-- Glob pattern for finding and parsing shell script files in the workspace.
|
||||||
|
-- Used by the background analysis features across files.
|
||||||
|
|
||||||
|
-- Prevent recursive scanning which will cause issues when opening a file
|
||||||
|
-- directly in the home directory (e.g. ~/foo.sh).
|
||||||
|
--
|
||||||
|
-- Default upstream pattern is "**/*@(.sh|.inc|.bash|.command)".
|
||||||
|
globPattern = vim.env.GLOB_PATTERN or '*@(.sh|.inc|.bash|.command)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
filetypes = { 'bash', 'sh' },
|
||||||
|
root_markers = { '.git' },
|
||||||
|
}
|
||||||
100
lsp/clangd.lua
Normal file
100
lsp/clangd.lua
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
---@brief
|
||||||
|
---
|
||||||
|
--- https://clangd.llvm.org/installation.html
|
||||||
|
---
|
||||||
|
--- - **NOTE:** Clang >= 11 is recommended! See [#23](https://github.com/neovim/nvim-lspconfig/issues/23).
|
||||||
|
--- - If `compile_commands.json` lives in a build directory, you should
|
||||||
|
--- symlink it to the root of your source tree.
|
||||||
|
--- ```
|
||||||
|
--- ln -s /path/to/myproject/build/compile_commands.json /path/to/myproject/
|
||||||
|
--- ```
|
||||||
|
--- - clangd relies on a [JSON compilation database](https://clang.llvm.org/docs/JSONCompilationDatabase.html)
|
||||||
|
--- specified as compile_commands.json, see https://clangd.llvm.org/installation#compile_commandsjson
|
||||||
|
|
||||||
|
-- https://clangd.llvm.org/extensions.html#switch-between-sourceheader
|
||||||
|
local function switch_source_header(bufnr, client)
|
||||||
|
local method_name = 'textDocument/switchSourceHeader'
|
||||||
|
---@diagnostic disable-next-line:param-type-mismatch
|
||||||
|
if not client or not client:supports_method(method_name) then
|
||||||
|
return vim.notify(('method %s is not supported by any servers active on the current buffer'):format(method_name))
|
||||||
|
end
|
||||||
|
local params = vim.lsp.util.make_text_document_params(bufnr)
|
||||||
|
---@diagnostic disable-next-line:param-type-mismatch
|
||||||
|
client:request(method_name, params, function(err, result)
|
||||||
|
if err then
|
||||||
|
error(tostring(err))
|
||||||
|
end
|
||||||
|
if not result then
|
||||||
|
vim.notify('corresponding file cannot be determined')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
vim.cmd.edit(vim.uri_to_fname(result))
|
||||||
|
end, bufnr)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function symbol_info(bufnr, client)
|
||||||
|
local method_name = 'textDocument/symbolInfo'
|
||||||
|
---@diagnostic disable-next-line:param-type-mismatch
|
||||||
|
if not client or not client:supports_method(method_name) then
|
||||||
|
return vim.notify('Clangd client not found', vim.log.levels.ERROR)
|
||||||
|
end
|
||||||
|
local win = vim.api.nvim_get_current_win()
|
||||||
|
local params = vim.lsp.util.make_position_params(win, client.offset_encoding)
|
||||||
|
---@diagnostic disable-next-line:param-type-mismatch
|
||||||
|
client:request(method_name, params, function(err, res)
|
||||||
|
if err or #res == 0 then
|
||||||
|
-- Clangd always returns an error, there is no reason to parse it
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local container = string.format('container: %s', res[1].containerName) ---@type string
|
||||||
|
local name = string.format('name: %s', res[1].name) ---@type string
|
||||||
|
vim.lsp.util.open_floating_preview({ name, container }, '', {
|
||||||
|
height = 2,
|
||||||
|
width = math.max(string.len(name), string.len(container)),
|
||||||
|
focusable = false,
|
||||||
|
focus = false,
|
||||||
|
title = 'Symbol Info',
|
||||||
|
})
|
||||||
|
end, bufnr)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class ClangdInitializeResult: lsp.InitializeResult
|
||||||
|
---@field offsetEncoding? string
|
||||||
|
|
||||||
|
---@type vim.lsp.Config
|
||||||
|
return {
|
||||||
|
cmd = { 'clangd' },
|
||||||
|
filetypes = { 'c', 'cpp', 'objc', 'objcpp', 'cuda' },
|
||||||
|
root_markers = {
|
||||||
|
'.clangd',
|
||||||
|
'.clang-tidy',
|
||||||
|
'.clang-format',
|
||||||
|
'compile_commands.json',
|
||||||
|
'compile_flags.txt',
|
||||||
|
'configure.ac', -- AutoTools
|
||||||
|
'.git',
|
||||||
|
},
|
||||||
|
capabilities = {
|
||||||
|
textDocument = {
|
||||||
|
completion = {
|
||||||
|
editsNearCursor = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
offsetEncoding = { 'utf-8', 'utf-16' },
|
||||||
|
},
|
||||||
|
---@param init_result ClangdInitializeResult
|
||||||
|
on_init = function(client, init_result)
|
||||||
|
if init_result.offsetEncoding then
|
||||||
|
client.offset_encoding = init_result.offsetEncoding
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_attach = function(client, bufnr)
|
||||||
|
vim.api.nvim_buf_create_user_command(bufnr, 'LspClangdSwitchSourceHeader', function()
|
||||||
|
switch_source_header(bufnr, client)
|
||||||
|
end, { desc = 'Switch between source/header' })
|
||||||
|
|
||||||
|
vim.api.nvim_buf_create_user_command(bufnr, 'LspClangdShowSymbolInfo', function()
|
||||||
|
symbol_info(bufnr, client)
|
||||||
|
end, { desc = 'Show symbol info' })
|
||||||
|
end,
|
||||||
|
}
|
||||||
85
lsp/lua_ls.lua
Normal file
85
lsp/lua_ls.lua
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
---@brief
|
||||||
|
---
|
||||||
|
--- https://github.com/luals/lua-language-server
|
||||||
|
---
|
||||||
|
--- Lua language server.
|
||||||
|
---
|
||||||
|
--- `lua-language-server` can be installed by following the instructions [here](https://luals.github.io/#neovim-install).
|
||||||
|
---
|
||||||
|
--- The default `cmd` assumes that the `lua-language-server` binary can be found in `$PATH`.
|
||||||
|
---
|
||||||
|
--- If you primarily use `lua-language-server` for Neovim, and want to provide completions,
|
||||||
|
--- analysis, and location handling for plugins on runtime path, you can use the following
|
||||||
|
--- settings.
|
||||||
|
---
|
||||||
|
--- ```lua
|
||||||
|
--- vim.lsp.config('lua_ls', {
|
||||||
|
--- on_init = function(client)
|
||||||
|
--- if client.workspace_folders then
|
||||||
|
--- local path = client.workspace_folders[1].name
|
||||||
|
--- if
|
||||||
|
--- path ~= vim.fn.stdpath('config')
|
||||||
|
--- and (vim.uv.fs_stat(path .. '/.luarc.json') or vim.uv.fs_stat(path .. '/.luarc.jsonc'))
|
||||||
|
--- then
|
||||||
|
--- return
|
||||||
|
--- end
|
||||||
|
--- end
|
||||||
|
---
|
||||||
|
--- client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, {
|
||||||
|
--- runtime = {
|
||||||
|
--- -- Tell the language server which version of Lua you're using (most
|
||||||
|
--- -- likely LuaJIT in the case of Neovim)
|
||||||
|
--- version = 'LuaJIT',
|
||||||
|
--- -- Tell the language server how to find Lua modules same way as Neovim
|
||||||
|
--- -- (see `:h lua-module-load`)
|
||||||
|
--- path = {
|
||||||
|
--- 'lua/?.lua',
|
||||||
|
--- 'lua/?/init.lua',
|
||||||
|
--- },
|
||||||
|
--- },
|
||||||
|
--- -- Make the server aware of Neovim runtime files
|
||||||
|
--- workspace = {
|
||||||
|
--- checkThirdParty = false,
|
||||||
|
--- library = {
|
||||||
|
--- vim.env.VIMRUNTIME
|
||||||
|
--- -- Depending on the usage, you might want to add additional paths
|
||||||
|
--- -- here.
|
||||||
|
--- -- '${3rd}/luv/library'
|
||||||
|
--- -- '${3rd}/busted/library'
|
||||||
|
--- }
|
||||||
|
--- -- Or pull in all of 'runtimepath'.
|
||||||
|
--- -- NOTE: this is a lot slower and will cause issues when working on
|
||||||
|
--- -- your own configuration.
|
||||||
|
--- -- See https://github.com/neovim/nvim-lspconfig/issues/3189
|
||||||
|
--- -- library = {
|
||||||
|
--- -- vim.api.nvim_get_runtime_file('', true),
|
||||||
|
--- -- }
|
||||||
|
--- }
|
||||||
|
--- })
|
||||||
|
--- end,
|
||||||
|
--- settings = {
|
||||||
|
--- Lua = {}
|
||||||
|
--- }
|
||||||
|
--- })
|
||||||
|
--- ```
|
||||||
|
---
|
||||||
|
--- See `lua-language-server`'s [documentation](https://luals.github.io/wiki/settings/) for an explanation of the above fields:
|
||||||
|
--- * [Lua.runtime.path](https://luals.github.io/wiki/settings/#runtimepath)
|
||||||
|
--- * [Lua.workspace.library](https://luals.github.io/wiki/settings/#workspacelibrary)
|
||||||
|
---
|
||||||
|
|
||||||
|
---@type vim.lsp.Config
|
||||||
|
return {
|
||||||
|
cmd = { 'lua-language-server' },
|
||||||
|
filetypes = { 'lua' },
|
||||||
|
root_markers = {
|
||||||
|
'.luarc.json',
|
||||||
|
'.luarc.jsonc',
|
||||||
|
'.luacheckrc',
|
||||||
|
'.stylua.toml',
|
||||||
|
'stylua.toml',
|
||||||
|
'selene.toml',
|
||||||
|
'selene.yml',
|
||||||
|
'.git',
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -1,14 +0,0 @@
|
|||||||
return {
|
|
||||||
cmd = { "lua-language-server" },
|
|
||||||
filetypes = { "lua" },
|
|
||||||
root_markers = {
|
|
||||||
".luarc.json",
|
|
||||||
".luarc.jsonc",
|
|
||||||
".luacheckrc",
|
|
||||||
".stylua.toml",
|
|
||||||
"stylua.toml",
|
|
||||||
"selene.toml",
|
|
||||||
"selene.yml",
|
|
||||||
".git",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
65
lsp/pyright.lua
Normal file
65
lsp/pyright.lua
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
---@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',
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
}
|
||||||
19
lsp/sqls.lua
Normal file
19
lsp/sqls.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
---@brief
|
||||||
|
---
|
||||||
|
--- https://github.com/sqls-server/sqls
|
||||||
|
---
|
||||||
|
--- ```lua
|
||||||
|
--- vim.lsp.config('sqls', {
|
||||||
|
--- cmd = {"path/to/command", "-config", "path/to/config.yml"};
|
||||||
|
--- ...
|
||||||
|
--- })
|
||||||
|
--- ```
|
||||||
|
--- Sqls can be installed via `go install github.com/sqls-server/sqls@latest`. Instructions for compiling Sqls from the source can be found at [sqls-server/sqls](https://github.com/sqls-server/sqls).
|
||||||
|
|
||||||
|
---@type vim.lsp.Config
|
||||||
|
return {
|
||||||
|
cmd = { 'sqls' },
|
||||||
|
filetypes = { 'sql', 'mysql' },
|
||||||
|
root_markers = { 'config.yml' },
|
||||||
|
settings = {},
|
||||||
|
}
|
||||||
96
lsp/vtsls.lua
Normal file
96
lsp/vtsls.lua
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
---@brief
|
||||||
|
---
|
||||||
|
--- https://github.com/yioneko/vtsls
|
||||||
|
---
|
||||||
|
--- `vtsls` can be installed with npm:
|
||||||
|
--- ```sh
|
||||||
|
--- npm install -g @vtsls/language-server
|
||||||
|
--- ```
|
||||||
|
---
|
||||||
|
--- To configure a TypeScript project, add a
|
||||||
|
--- [`tsconfig.json`](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)
|
||||||
|
--- or [`jsconfig.json`](https://code.visualstudio.com/docs/languages/jsconfig) to
|
||||||
|
--- the root of your project.
|
||||||
|
---
|
||||||
|
--- ### Vue support
|
||||||
|
---
|
||||||
|
--- Since v3.0.0, the Vue language server requires `vtsls` to support TypeScript.
|
||||||
|
---
|
||||||
|
--- ```
|
||||||
|
--- -- If you are using mason.nvim, you can get the ts_plugin_path like this
|
||||||
|
--- -- For Mason v1,
|
||||||
|
--- -- local mason_registry = require('mason-registry')
|
||||||
|
--- -- local vue_language_server_path = mason_registry.get_package('vue-language-server'):get_install_path() .. '/node_modules/@vue/language-server'
|
||||||
|
--- -- For Mason v2,
|
||||||
|
--- -- local vue_language_server_path = vim.fn.expand '$MASON/packages' .. '/vue-language-server' .. '/node_modules/@vue/language-server'
|
||||||
|
--- -- or even
|
||||||
|
--- -- local vue_language_server_path = vim.fn.stdpath('data') .. "/mason/packages/vue-language-server/node_modules/@vue/language-server"
|
||||||
|
--- local vue_language_server_path = '/path/to/@vue/language-server'
|
||||||
|
--- local vue_plugin = {
|
||||||
|
--- name = '@vue/typescript-plugin',
|
||||||
|
--- location = vue_language_server_path,
|
||||||
|
--- languages = { 'vue' },
|
||||||
|
--- configNamespace = 'typescript',
|
||||||
|
--- }
|
||||||
|
--- vim.lsp.config('vtsls', {
|
||||||
|
--- settings = {
|
||||||
|
--- vtsls = {
|
||||||
|
--- tsserver = {
|
||||||
|
--- globalPlugins = {
|
||||||
|
--- vue_plugin,
|
||||||
|
--- },
|
||||||
|
--- },
|
||||||
|
--- },
|
||||||
|
--- },
|
||||||
|
--- filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' },
|
||||||
|
--- })
|
||||||
|
--- ```
|
||||||
|
---
|
||||||
|
--- - `location` MUST be defined. If the plugin is installed in `node_modules`, `location` can have any value.
|
||||||
|
--- - `languages` must include vue even if it is listed in filetypes.
|
||||||
|
--- - `filetypes` is extended here to include Vue SFC.
|
||||||
|
---
|
||||||
|
--- You must make sure the Vue language server is setup. For example,
|
||||||
|
---
|
||||||
|
--- ```
|
||||||
|
--- vim.lsp.enable('vue_ls')
|
||||||
|
--- ```
|
||||||
|
---
|
||||||
|
--- See `vue_ls` section and https://github.com/vuejs/language-tools/wiki/Neovim for more information.
|
||||||
|
---
|
||||||
|
--- ### Monorepo support
|
||||||
|
---
|
||||||
|
--- `vtsls` supports monorepos by default. It will automatically find the `tsconfig.json` or `jsconfig.json` corresponding to the package you are working on.
|
||||||
|
--- This works without the need of spawning multiple instances of `vtsls`, saving memory.
|
||||||
|
---
|
||||||
|
--- It is recommended to use the same version of TypeScript in all packages, and therefore have it available in your workspace root. The location of the TypeScript binary will be determined automatically, but only once.
|
||||||
|
|
||||||
|
---@type vim.lsp.Config
|
||||||
|
return {
|
||||||
|
cmd = { 'vtsls', '--stdio' },
|
||||||
|
init_options = {
|
||||||
|
hostInfo = 'neovim',
|
||||||
|
},
|
||||||
|
filetypes = {
|
||||||
|
'javascript',
|
||||||
|
'javascriptreact',
|
||||||
|
'javascript.jsx',
|
||||||
|
'typescript',
|
||||||
|
'typescriptreact',
|
||||||
|
'typescript.tsx',
|
||||||
|
},
|
||||||
|
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' } }
|
||||||
|
or vim.list_extend(root_markers, { '.git' })
|
||||||
|
-- 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()
|
||||||
|
|
||||||
|
on_dir(project_root)
|
||||||
|
end,
|
||||||
|
}
|
||||||
@ -1,7 +1,5 @@
|
|||||||
-- <treesitter> or { <treesitter>, <lsp>, <linter>, <formatter>, filetype=<ft> }
|
-- language_spec = { treesitter?, lsp?, linter?, formatter?, filetype? }
|
||||||
-- filetype defaults to <treesitter>. If different, specify it.
|
local language_specs = {
|
||||||
-- any positional argument can be skipped with nil
|
|
||||||
local languages = {
|
|
||||||
-- Docs / Config
|
-- Docs / Config
|
||||||
'vim',
|
'vim',
|
||||||
'vimdoc',
|
'vimdoc',
|
||||||
@ -15,74 +13,212 @@ local languages = {
|
|||||||
'gitignore',
|
'gitignore',
|
||||||
'dockerfile',
|
'dockerfile',
|
||||||
'diff',
|
'diff',
|
||||||
{ 'json', 'jsonls', nil, 'prettier' },
|
{ 'json', nil, nil, 'prettier' },
|
||||||
{ 'jsonc', 'jsonls', nil, 'prettier' },
|
{ 'jsonc', nil, nil, 'prettier' },
|
||||||
|
|
||||||
-- Shell / Scripting
|
-- Shell / scripting
|
||||||
{ 'bash', 'bashls', 'shellcheck', 'shfmt' },
|
{ 'bash', 'bash-language-server', 'shellcheck', 'shfmt' },
|
||||||
{ 'lua', 'luals', 'luacheck', 'stylua' },
|
{ 'lua', 'lua-language-server', 'luacheck', 'stylua' },
|
||||||
{ 'sql', 'sqlls', nil, 'sqlfluff' },
|
'sql',
|
||||||
|
|
||||||
-- Programming
|
-- Programming
|
||||||
{ 'c', 'clangd', nil, 'clang-format' },
|
'c',
|
||||||
{ 'cpp', 'clangd', nil, 'clang-format' },
|
'cpp',
|
||||||
{ 'go', 'gopls', 'golangci-lint', 'gofmt' },
|
'go',
|
||||||
{ 'rust', 'rust_analyzer', 'clippy', 'rustfmt' },
|
'rust',
|
||||||
{ 'python', 'pyright', 'ruff', 'black' },
|
'python',
|
||||||
|
-- { 'python', 'pyright', 'ruff', 'ruff' }, -- install ensurepip
|
||||||
|
|
||||||
-- Web stack
|
-- Web stack
|
||||||
{ 'html', 'html', nil, 'prettier' },
|
{ 'html', nil, nil, 'prettier' },
|
||||||
{ 'css', 'cssls', 'stylelint', 'prettier' },
|
{ 'css', nil, nil, 'prettier' },
|
||||||
{ 'javascript', 'tsls', 'eslint', 'prettier' },
|
{ 'javascript', 'vtsls', 'eslint_d', 'prettier' },
|
||||||
{ 'typescript', 'tsls', 'eslint', 'prettier' },
|
{ 'typescript', 'vtsls', 'eslint_d', 'prettier' },
|
||||||
{ nil, 'tsls', 'eslint', 'prettier', filetype = 'javascriptreact' },
|
{ nil, 'vtsls', 'eslint_d', 'prettier', filetype = 'javascriptreact' },
|
||||||
{ 'tsx', 'tsls', 'eslint', 'prettier', filetype = 'typescriptreact' },
|
{ 'tsx', 'vtsls', 'eslint_d', 'prettier', filetype = 'typescriptreact' },
|
||||||
}
|
}
|
||||||
|
|
||||||
local function normalize(lang)
|
local function normalize(spec)
|
||||||
if type(lang) == 'string' then
|
if type(spec) == 'string' then
|
||||||
lang = { lang }
|
spec = { spec }
|
||||||
end
|
end
|
||||||
local t = {
|
return {
|
||||||
treesitter = lang[1],
|
treesitter = spec[1],
|
||||||
lsp = lang[2],
|
lsp = spec[2],
|
||||||
linter = lang[3],
|
linter = spec[3],
|
||||||
formatter = lang[4],
|
formatter = spec[4],
|
||||||
filetype = lang.filetype or lang[1],
|
filetype = spec.filetype or spec[1],
|
||||||
}
|
}
|
||||||
return t
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local normalized = vim.tbl_map(normalize, languages)
|
local normalized = vim.tbl_map(normalize, language_specs)
|
||||||
local general = {
|
|
||||||
ts_parsers = {},
|
|
||||||
lsps = {},
|
|
||||||
linters_by_ft = {},
|
|
||||||
formatters_by_ft = {},
|
|
||||||
}
|
|
||||||
for _, opts in ipairs(normalized) do
|
|
||||||
if opts.treesitter then
|
|
||||||
table.insert(general.ts_parsers, opts.treesitter)
|
|
||||||
end
|
|
||||||
|
|
||||||
if opts.lsp then
|
local function uniq(tbl)
|
||||||
table.insert(general.lsps, opts.lsp)
|
local seen, out = {}, {}
|
||||||
end
|
for _, v in ipairs(tbl) do
|
||||||
|
if v and not seen[v] then
|
||||||
if opts.linter then
|
seen[v] = true
|
||||||
general.linters_by_ft[opts.filetype] = { opts.linter }
|
table.insert(out, v)
|
||||||
end
|
end
|
||||||
|
|
||||||
if opts.formatter then
|
|
||||||
general.formatters_by_ft[opts.filetype] = { opts.formatter }
|
|
||||||
end
|
end
|
||||||
|
return out
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function collect(specs)
|
||||||
|
local ts, lsps, linters, formatters = {}, {}, {}, {}
|
||||||
|
for _, s in ipairs(specs) do
|
||||||
|
if s.treesitter then
|
||||||
|
table.insert(ts, s.treesitter)
|
||||||
|
end
|
||||||
|
if s.lsp then
|
||||||
|
table.insert(lsps, s.lsp)
|
||||||
|
end
|
||||||
|
if s.linter then
|
||||||
|
linters[s.filetype] = { s.linter }
|
||||||
|
end
|
||||||
|
if s.formatter then
|
||||||
|
formatters[s.filetype] = { s.formatter }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return {
|
||||||
|
ts_parsers = uniq(ts),
|
||||||
|
lsps = uniq(lsps),
|
||||||
|
linters_by_ft = linters,
|
||||||
|
formatters_by_ft = formatters,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local general = collect(normalized)
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
-- Mason Install Command
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
vim.api.nvim_create_user_command('MasonInstallAll', function()
|
||||||
|
local registry = require('mason-registry')
|
||||||
|
local list = vim.list_extend(vim.list_extend({}, general.lsps), {})
|
||||||
|
|
||||||
|
for _, ftmap in pairs({ general.linters_by_ft, general.formatters_by_ft }) do
|
||||||
|
for _, tools in pairs(ftmap) do
|
||||||
|
vim.list_extend(list, tools)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
list = uniq(list)
|
||||||
|
local installed = {}
|
||||||
|
for _, pkg in ipairs(registry.get_installed_packages()) do
|
||||||
|
installed[pkg.name] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, name in ipairs(list) do
|
||||||
|
if registry.has_package(name) then
|
||||||
|
if not installed[name] then
|
||||||
|
vim.notify('Installing ' .. name, vim.log.levels.INFO)
|
||||||
|
registry.get_package(name):install()
|
||||||
|
else
|
||||||
|
vim.notify('Already installed ' .. name, vim.log.levels.INFO)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
vim.notify('Package not found in registry: ' .. name, vim.log.levels.WARN)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, { desc = 'Install all Mason LSPs, linters, and formatters' })
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
-- Fetch LSP default configs from nvim-lspconfig
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
vim.api.nvim_create_user_command('FetchLspConfigs', function()
|
||||||
|
local registry = require('mason-registry')
|
||||||
|
local lspconfig_names = {}
|
||||||
|
|
||||||
|
for _, lsp in ipairs(general.lsps) do
|
||||||
|
if registry.has_package(lsp) then
|
||||||
|
local pkg = registry.get_package(lsp)
|
||||||
|
local spec = pkg.spec and pkg.spec.neovim
|
||||||
|
if spec and spec.lspconfig then
|
||||||
|
table.insert(lspconfig_names, spec.lspconfig)
|
||||||
|
else
|
||||||
|
table.insert(lspconfig_names, lsp)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
table.insert(lspconfig_names, lsp)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
lspconfig_names = uniq(lspconfig_names)
|
||||||
|
|
||||||
|
-- base URL same as your original
|
||||||
|
local base_url = 'https://raw.githubusercontent.com/neovim/nvim-lspconfig/master/lsp/'
|
||||||
|
-- write to current working directory
|
||||||
|
local lsp_dir = vim.fs.joinpath(vim.fn.getcwd(), 'lsp')
|
||||||
|
vim.fn.mkdir(lsp_dir, 'p')
|
||||||
|
|
||||||
|
for _, name in ipairs(lspconfig_names) do
|
||||||
|
local file = vim.fs.joinpath(lsp_dir, name .. '.lua')
|
||||||
|
if vim.fn.filereadable(file) == 0 then
|
||||||
|
local url = base_url .. name .. '.lua'
|
||||||
|
local cmd = string.format('curl -fsSL -o %q %q', file, url)
|
||||||
|
vim.fn.system(cmd)
|
||||||
|
if vim.v.shell_error ~= 0 then
|
||||||
|
vim.notify('Failed to fetch ' .. name .. '.lua', vim.log.levels.ERROR)
|
||||||
|
vim.fn.delete(file)
|
||||||
|
else
|
||||||
|
vim.notify('Fetched ' .. name .. '.lua', vim.log.levels.INFO)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
vim.notify('Skipped existing ' .. name .. '.lua', vim.log.levels.INFO)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, { desc = 'Fetch default LSP configs into ./lsp in cwd' })
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command('TreesitterInstallAll', function()
|
||||||
|
local parsers = require('nvim-treesitter.parsers')
|
||||||
|
local configs = require('nvim-treesitter.configs')
|
||||||
|
local langs = configs.get_module('ensure_installed') or {}
|
||||||
|
if type(langs) == 'string' and langs == 'all' then
|
||||||
|
vim.notify('Treesitter ensure_installed = "all" not supported here', vim.log.levels.WARN)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, lang in ipairs(langs) do
|
||||||
|
if not parsers.has_parser(lang) then
|
||||||
|
vim.cmd('TSInstall ' .. lang)
|
||||||
|
else
|
||||||
|
vim.notify('Parser already installed: ' .. lang, vim.log.levels.INFO)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, { desc = 'Install all Treesitter parsers defined in ensure_installed' })
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
-- Plugins
|
||||||
|
---------------------------------------------------------------------
|
||||||
return {
|
return {
|
||||||
{ 'windwp/nvim-ts-autotag', config = true },
|
{ 'windwp/nvim-ts-autotag', config = true },
|
||||||
{ 'windwp/nvim-autopairs', event = 'InsertEnter', config = true },
|
{ 'windwp/nvim-autopairs', event = 'InsertEnter', config = true },
|
||||||
{ 'mason-org/mason.nvim', config = true },
|
{
|
||||||
-- { 'saghen/blink.cmp', version = '1.*' },
|
'mason-org/mason.nvim',
|
||||||
|
config = function()
|
||||||
|
local mason = require('mason')
|
||||||
|
local registry = require('mason-registry')
|
||||||
|
mason.setup()
|
||||||
|
|
||||||
|
local lsp_configs = {}
|
||||||
|
|
||||||
|
for _, lsp in ipairs(general.lsps) do
|
||||||
|
if registry.has_package(lsp) then
|
||||||
|
local pkg = registry.get_package(lsp)
|
||||||
|
local spec = pkg.spec and pkg.spec.neovim
|
||||||
|
local lsp_name = (spec and spec.lspconfig) or lsp
|
||||||
|
table.insert(lsp_configs, lsp_name)
|
||||||
|
|
||||||
|
-- Native enable call (Neovim ≥ 0.11)
|
||||||
|
vim.lsp.enable(lsp_name)
|
||||||
|
else
|
||||||
|
vim.notify('Unknown LSP: ' .. lsp, vim.log.levels.WARN)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.notify('Enabled LSPs: ' .. table.concat(lsp_configs, ', '), vim.log.levels.INFO)
|
||||||
|
end,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'nvim-treesitter/nvim-treesitter',
|
'nvim-treesitter/nvim-treesitter',
|
||||||
build = ':TSUpdate',
|
build = ':TSUpdate',
|
||||||
@ -90,7 +226,6 @@ return {
|
|||||||
opts = {
|
opts = {
|
||||||
highlight = { enable = true },
|
highlight = { enable = true },
|
||||||
incremental_selection = { enable = true },
|
incremental_selection = { enable = true },
|
||||||
textobjects = { enable = true },
|
|
||||||
ensure_installed = general.ts_parsers,
|
ensure_installed = general.ts_parsers,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -101,6 +236,7 @@ return {
|
|||||||
config = function(_, opts)
|
config = function(_, opts)
|
||||||
local lint = require('lint')
|
local lint = require('lint')
|
||||||
lint.linters_by_ft = opts.linters_by_ft
|
lint.linters_by_ft = opts.linters_by_ft
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost', 'InsertLeave' }, {
|
vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost', 'InsertLeave' }, {
|
||||||
group = vim.api.nvim_create_augroup('lint_autocmd', { clear = true }),
|
group = vim.api.nvim_create_augroup('lint_autocmd', { clear = true }),
|
||||||
callback = function()
|
callback = function()
|
||||||
@ -113,27 +249,9 @@ return {
|
|||||||
'stevearc/conform.nvim',
|
'stevearc/conform.nvim',
|
||||||
event = { 'BufWritePre' },
|
event = { 'BufWritePre' },
|
||||||
opts = {
|
opts = {
|
||||||
-- Automatically format on save
|
format_on_save = { timeout_ms = 500, lsp_format = 'fallback' },
|
||||||
format_on_save = {
|
|
||||||
timeout_ms = 500,
|
|
||||||
lsp_format = 'fallback', -- Use LSP when no formatter is configured
|
|
||||||
},
|
|
||||||
|
|
||||||
-- Formatters per filetype
|
|
||||||
default_format_opts = { stop_after_first = true },
|
default_format_opts = { stop_after_first = true },
|
||||||
formatters_by_ft = general.formatters_by_ft,
|
formatters_by_ft = general.formatters_by_ft,
|
||||||
},
|
},
|
||||||
|
|
||||||
config = function(_, opts)
|
|
||||||
require('conform').setup(opts)
|
|
||||||
|
|
||||||
-- Create a command to format manually
|
|
||||||
vim.api.nvim_create_user_command('Format', function()
|
|
||||||
require('conform').format({
|
|
||||||
async = true,
|
|
||||||
lsp_format = 'fallback',
|
|
||||||
})
|
|
||||||
end, { desc = 'Format current buffer' })
|
|
||||||
end,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user