refactor(LSP): use the new vim.lsp.* functions to set up LSP servers
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
vim.loader.enable()
|
vim.loader.enable()
|
||||||
|
|
||||||
local utils = require("ow.utils")
|
local log = require("ow.log")
|
||||||
|
|
||||||
local files = {
|
local files = {
|
||||||
"globals",
|
"globals",
|
||||||
@@ -13,28 +13,19 @@ for _, file in ipairs(files) do
|
|||||||
local pkg = "ow.core." .. file
|
local pkg = "ow.core." .. file
|
||||||
local ok, err = pcall(require, pkg)
|
local ok, err = pcall(require, pkg)
|
||||||
if not ok then
|
if not ok then
|
||||||
utils.err("Error while loading package " .. pkg)
|
log.error("Error while loading package " .. pkg)
|
||||||
utils.err(err)
|
log.error(err)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local ok, err = pcall(require, "ow.bootstrap")
|
local ok, err = pcall(require, "ow.bootstrap")
|
||||||
if not ok then
|
if not ok then
|
||||||
utils.err("Error during bootstrap")
|
log.error("Error during bootstrap")
|
||||||
utils.err(err:gsub("\t", " "))
|
log.error(err:gsub("\t", " "))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type LazyPluginSpec[]
|
|
||||||
local plugins = {
|
|
||||||
{
|
|
||||||
"neovim/nvim-lspconfig",
|
|
||||||
config = require("ow.lsp").setup,
|
|
||||||
},
|
|
||||||
{ import = "ow.plugins" },
|
|
||||||
}
|
|
||||||
|
|
||||||
---@type LazyConfig
|
---@type LazyConfig
|
||||||
local opts = {
|
local opts = {
|
||||||
install = {
|
install = {
|
||||||
@@ -69,4 +60,4 @@ local opts = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
require("lazy").setup(plugins, opts)
|
require("lazy").setup("ow.plugins", opts)
|
||||||
|
|||||||
+17
-15
@@ -1,34 +1,36 @@
|
|||||||
{
|
{
|
||||||
"Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" },
|
"Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" },
|
||||||
"LuaSnip": { "branch": "master", "commit": "03c8e67eb7293c404845b3982db895d59c0d1538" },
|
"LuaSnip": { "branch": "master", "commit": "458560534a73f7f8d7a11a146c801db00b081df0" },
|
||||||
"aerial.nvim": { "branch": "master", "commit": "2e00d1d4248f08dddfceacb8d2996e51e13e00f6" },
|
"aerial.nvim": { "branch": "master", "commit": "5c0df1679bf7c814c924dc6646cc5291daca8363" },
|
||||||
"catppuccin": { "branch": "main", "commit": "5b5e3aef9ad7af84f463d17b5479f06b87d5c429" },
|
"catppuccin": { "branch": "main", "commit": "5b5e3aef9ad7af84f463d17b5479f06b87d5c429" },
|
||||||
"cmp-cmdline": { "branch": "main", "commit": "d250c63aa13ead745e3a40f61fdd3470efde3923" },
|
"cmp-cmdline": { "branch": "main", "commit": "d126061b624e0af6c3a556428712dd4d4194ec6d" },
|
||||||
"cmp-nvim-lsp": { "branch": "main", "commit": "a8912b88ce488f411177fc8aed358b04dc246d7b" },
|
"cmp-nvim-lsp": { "branch": "main", "commit": "a8912b88ce488f411177fc8aed358b04dc246d7b" },
|
||||||
"cmp-path": { "branch": "main", "commit": "c6635aae33a50d6010bf1aa756ac2398a2d54c32" },
|
"cmp-path": { "branch": "main", "commit": "c6635aae33a50d6010bf1aa756ac2398a2d54c32" },
|
||||||
"cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" },
|
"cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" },
|
||||||
"fidget.nvim": { "branch": "main", "commit": "0ba1e16d07627532b6cae915cc992ecac249fb97" },
|
"fidget.nvim": { "branch": "main", "commit": "0ba1e16d07627532b6cae915cc992ecac249fb97" },
|
||||||
"friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" },
|
"friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" },
|
||||||
"gitsigns.nvim": { "branch": "main", "commit": "ee28ba3e70ecea811b8f6d7b51d81976e94b121c" },
|
"gitsigns.nvim": { "branch": "main", "commit": "d0f90ef51d4be86b824b012ec52ed715b5622e51" },
|
||||||
"lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" },
|
"lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" },
|
||||||
"lspkind.nvim": { "branch": "master", "commit": "d79a1c3299ad0ef94e255d045bed9fa26025dab6" },
|
"lspkind.nvim": { "branch": "master", "commit": "d79a1c3299ad0ef94e255d045bed9fa26025dab6" },
|
||||||
"mason.nvim": { "branch": "main", "commit": "fc98833b6da5de5a9c5b1446ac541577059555be" },
|
"mason.nvim": { "branch": "main", "commit": "8024d64e1330b86044fed4c8494ef3dcd483a67c" },
|
||||||
"nvim-cmp": { "branch": "main", "commit": "b5311ab3ed9c846b585c0c15b7559be131ec4be9" },
|
"nvim-cmp": { "branch": "main", "commit": "b5311ab3ed9c846b585c0c15b7559be131ec4be9" },
|
||||||
"nvim-colorizer.lua": { "branch": "master", "commit": "517df88cf2afb36652830df2c655df2da416a0ae" },
|
"nvim-colorizer.lua": { "branch": "master", "commit": "517df88cf2afb36652830df2c655df2da416a0ae" },
|
||||||
"nvim-dap": { "branch": "master", "commit": "8df427aeba0a06c6577dc3ab82de3076964e3b8d" },
|
"nvim-dap": { "branch": "master", "commit": "ea82027c3447dc1a022be9a9884de276c05cd33a" },
|
||||||
"nvim-lspconfig": { "branch": "master", "commit": "94d0fec9135719e046903bbbbf8f39e3d3436d4e" },
|
"nvim-lspconfig": { "branch": "master", "commit": "036885e8e5456d3907626b634693234f628afef6" },
|
||||||
"nvim-notify": { "branch": "master", "commit": "b5825cf9ee881dd8e43309c93374ed5b87b7a896" },
|
"nvim-notify": { "branch": "master", "commit": "b5825cf9ee881dd8e43309c93374ed5b87b7a896" },
|
||||||
"nvim-tree.lua": { "branch": "master", "commit": "582ae48c9e43d2bcd55dfcc8e2e7a1f29065d924" },
|
"nvim-tree.lua": { "branch": "master", "commit": "1c733e8c1957dc67f47580fe9c458a13b5612d5b" },
|
||||||
"nvim-treesitter": { "branch": "master", "commit": "94ea4f436d2b59c80f02e293466c374584f03b8c" },
|
"nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" },
|
||||||
"nvim-treesitter-context": { "branch": "master", "commit": "6daca3ad780f045550b820f262002f35175a6c04" },
|
"nvim-treesitter-context": { "branch": "master", "commit": "464a443b5a6657f39772b20baa95d02ffe97b268" },
|
||||||
"nvim-web-devicons": { "branch": "master", "commit": "50b5b06bff13a9b4eab946de7c7033649a6618a1" },
|
"nvim-web-devicons": { "branch": "master", "commit": "1fb58cca9aebbc4fd32b086cb413548ce132c127" },
|
||||||
"oil.nvim": { "branch": "master", "commit": "685cdb4ffa74473d75a1b97451f8654ceeab0f4a" },
|
"oil.nvim": { "branch": "master", "commit": "08c2bce8b00fd780fb7999dbffdf7cd174e896fb" },
|
||||||
"onedark.nvim": { "branch": "master", "commit": "0e5512d1bebd1f08954710086f87a5caa173a924" },
|
"onedark.nvim": { "branch": "master", "commit": "11de4da47f3e69cb70c3ae9816bd8af166cbe121" },
|
||||||
"orgmode": { "branch": "master", "commit": "15d66ead1285d99f8a21c4ef4874ac62e9320fe6" },
|
"orgmode": { "branch": "master", "commit": "32ef9e95f43a6e951fb931b438372546a4f0c524" },
|
||||||
"plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" },
|
"plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" },
|
||||||
"telescope-fzf-native.nvim": { "branch": "main", "commit": "1f08ed60cafc8f6168b72b80be2b2ea149813e55" },
|
"telescope-fzf-native.nvim": { "branch": "main", "commit": "1f08ed60cafc8f6168b72b80be2b2ea149813e55" },
|
||||||
"telescope.nvim": { "branch": "master", "commit": "a4ed82509cecc56df1c7138920a1aeaf246c0ac5" },
|
"telescope-undo.nvim": { "branch": "main", "commit": "928d0c2dc9606e01e2cc547196f48d2eaecf58e5" },
|
||||||
|
"telescope.nvim": { "branch": "master", "commit": "b4da76be54691e854d3e0e02c36b0245f945c2c7" },
|
||||||
"tokyonight.nvim": { "branch": "main", "commit": "057ef5d260c1931f1dffd0f052c685dcd14100a3" },
|
"tokyonight.nvim": { "branch": "main", "commit": "057ef5d260c1931f1dffd0f052c685dcd14100a3" },
|
||||||
|
"undotree": { "branch": "master", "commit": "b951b87b46c34356d44aa71886aecf9dd7f5788a" },
|
||||||
"vim-flog": { "branch": "master", "commit": "665b16ac8915f746bc43c9572b4581a5e9047216" },
|
"vim-flog": { "branch": "master", "commit": "665b16ac8915f746bc43c9572b4581a5e9047216" },
|
||||||
"vim-fugitive": { "branch": "master", "commit": "4a745ea72fa93bb15dd077109afbb3d1809383f2" },
|
"vim-fugitive": { "branch": "master", "commit": "4a745ea72fa93bb15dd077109afbb3d1809383f2" },
|
||||||
"vim-ucl": { "branch": "main", "commit": "efbcab5f98b663dbc3cac92801a90b11869c23d0" }
|
"vim-ucl": { "branch": "main", "commit": "efbcab5f98b663dbc3cac92801a90b11869c23d0" }
|
||||||
|
|||||||
@@ -6,20 +6,20 @@ if version.major == 0 then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local utils = require("ow.utils")
|
local util = require("ow.util")
|
||||||
|
|
||||||
-- Install lazy.nvim
|
-- Install lazy.nvim
|
||||||
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
|
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
|
||||||
if not vim.uv.fs_stat(lazypath) then
|
if not vim.uv.fs_stat(lazypath) then
|
||||||
utils.assert_installed("git")
|
util.assert_installed("git")
|
||||||
if not os.getenv("CC") then
|
if not os.getenv("CC") then
|
||||||
utils.assert_installed("cc")
|
util.assert_installed("cc")
|
||||||
end
|
end
|
||||||
utils.assert_installed("make")
|
util.assert_installed("make")
|
||||||
utils.assert_any_installed({ "curl", "wget", })
|
util.assert_any_installed({ "curl", "wget", })
|
||||||
utils.assert_installed("unzip")
|
util.assert_installed("unzip")
|
||||||
utils.assert_installed("tar")
|
util.assert_installed("tar")
|
||||||
utils.assert_installed("gzip")
|
util.assert_installed("gzip")
|
||||||
|
|
||||||
local resp = vim.system({
|
local resp = vim.system({
|
||||||
"git",
|
"git",
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
local M = {}
|
||||||
|
|
||||||
|
--- Log error message
|
||||||
|
---@param fmt string
|
||||||
|
---@param ... any
|
||||||
|
function M.error(fmt, ...)
|
||||||
|
vim.notify(
|
||||||
|
fmt:format(...),
|
||||||
|
vim.log.levels.ERROR
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Log warning message
|
||||||
|
---@param fmt string
|
||||||
|
---@param ... any
|
||||||
|
function M.warning(fmt, ...)
|
||||||
|
vim.notify(
|
||||||
|
fmt:format(...),
|
||||||
|
vim.log.levels.WARN
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Log info message
|
||||||
|
---@param fmt string
|
||||||
|
---@param ... any
|
||||||
|
function M.info(fmt, ...)
|
||||||
|
vim.notify(
|
||||||
|
fmt:format(...),
|
||||||
|
vim.log.levels.INFO
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Log debug message
|
||||||
|
---@param fmt string
|
||||||
|
---@param ... any
|
||||||
|
function M.debug(fmt, ...)
|
||||||
|
vim.notify(
|
||||||
|
fmt:format(...),
|
||||||
|
vim.log.levels.DEBUG
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
|
|
||||||
+394
-115
@@ -1,12 +1,11 @@
|
|||||||
local utils = require("ow.utils")
|
---@type fun(name: string, cfg: vim.lsp.Config)
|
||||||
|
vim.lsp.config = vim.lsp.config
|
||||||
|
|
||||||
local CONFIG_DIR = vim.fn.stdpath("config") .. "/lua/ow/lsp/config"
|
local keymap = require("ow.lsp.keymap")
|
||||||
|
local linter = require("ow.lsp.linter")
|
||||||
|
local log = require("ow.log")
|
||||||
|
local util = require("ow.util")
|
||||||
|
|
||||||
---@class Server
|
|
||||||
local Server = require("ow.lsp.server")
|
|
||||||
|
|
||||||
---@class LSP
|
|
||||||
---@field diagnostic_signs vim.diagnostic.Opts.Signs
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
M.diagnostic_signs = {
|
M.diagnostic_signs = {
|
||||||
@@ -18,122 +17,54 @@ M.diagnostic_signs = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
---@type table<string, Server>
|
---@param fn? fun(client: vim.lsp.Client, bufnr: integer)
|
||||||
local servers = {}
|
---@return fun(client: vim.lsp.Client, bufnr: integer)
|
||||||
|
function M.with_defaults(fn)
|
||||||
|
return function(client, bufnr)
|
||||||
|
keymap.set_defaults(bufnr)
|
||||||
|
|
||||||
function M.get_servers()
|
-- For document highlight
|
||||||
return servers
|
vim.cmd.highlight({ "link LspReferenceRead Visual", bang = true })
|
||||||
end
|
vim.cmd.highlight({ "link LspReferenceText Visual", bang = true })
|
||||||
|
vim.cmd.highlight({ "link LspReferenceWrite Visual", bang = true })
|
||||||
|
|
||||||
local function get_module_name(filepath)
|
client.settings = M.with_file(
|
||||||
return filepath:match("([^/\\]+)%.lua$")
|
string.format(".%s.json", client.name),
|
||||||
end
|
client.settings
|
||||||
|
) or client.settings
|
||||||
|
|
||||||
local function get_server_config(name)
|
if fn then
|
||||||
local module = "ow.lsp.config." .. name
|
fn(client, bufnr)
|
||||||
package.loaded[module] = nil
|
|
||||||
return utils.try_require("ow.lsp.config." .. name)
|
|
||||||
end
|
|
||||||
|
|
||||||
local reload_server_config = utils.debounce_with_id(function(name, events)
|
|
||||||
utils.info(("Reloading server with new config"):format(name), name)
|
|
||||||
---@type Server|nil
|
|
||||||
local server = servers[name]
|
|
||||||
|
|
||||||
if server and server.config.enable then
|
|
||||||
server:deinit()
|
|
||||||
servers[name] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if events.rename then
|
|
||||||
local _, _, err_name =
|
|
||||||
vim.uv.fs_stat(("%s/%s.lua"):format(CONFIG_DIR, name))
|
|
||||||
if err_name == "ENOENT" then
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local config = get_server_config(name)
|
--- Load a JSON file and return a parsed table merged with settings
|
||||||
if not config then
|
---@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
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
server = Server.new(name, config)
|
local json = file:read("*all")
|
||||||
if not server or not server.config.enable then
|
file:close()
|
||||||
return
|
local ok, resp = pcall(
|
||||||
end
|
vim.json.decode,
|
||||||
|
json,
|
||||||
local on_done = function(success)
|
{ luanil = { object = true, array = true } }
|
||||||
if success then
|
|
||||||
utils.info(("%s reloaded"):format(name))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if #server:get_ft_buffers() ~= 0 then
|
|
||||||
server:setup(on_done)
|
|
||||||
else
|
|
||||||
server:init(on_done)
|
|
||||||
end
|
|
||||||
|
|
||||||
servers[name] = server
|
|
||||||
end, 1000)
|
|
||||||
|
|
||||||
local function process_change(error, filename, events)
|
|
||||||
if error then
|
|
||||||
utils.err(
|
|
||||||
("Error on change for %s:\n%s"):format(filename, error),
|
|
||||||
"ow.lsp.on_config_change"
|
|
||||||
)
|
)
|
||||||
|
if not ok then
|
||||||
|
log.warning("Failed to parse json file %s: %s", path, resp)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local name = get_module_name(filename)
|
return vim.tbl_deep_extend("force", settings or {}, resp)
|
||||||
if not name or name == "init" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
reload_server_config(name, name, events)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function load_configs()
|
function M.setup()
|
||||||
local handle = vim.uv.fs_scandir(CONFIG_DIR)
|
|
||||||
while handle do
|
|
||||||
local filepath = vim.uv.fs_scandir_next(handle)
|
|
||||||
|
|
||||||
if not filepath then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
local name = get_module_name(filepath)
|
|
||||||
|
|
||||||
if name == "init" then
|
|
||||||
goto continue
|
|
||||||
end
|
|
||||||
|
|
||||||
local config = get_server_config(name)
|
|
||||||
|
|
||||||
if not config then
|
|
||||||
goto continue
|
|
||||||
end
|
|
||||||
|
|
||||||
local server = Server.new(name, config)
|
|
||||||
if server then
|
|
||||||
servers[name] = server
|
|
||||||
end
|
|
||||||
|
|
||||||
::continue::
|
|
||||||
end
|
|
||||||
|
|
||||||
vim.uv.fs_event_start(
|
|
||||||
vim.uv.new_fs_event(),
|
|
||||||
CONFIG_DIR,
|
|
||||||
{},
|
|
||||||
vim.schedule_wrap(process_change)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Setup diagnostics UI
|
|
||||||
local function setup_diagnostics()
|
|
||||||
vim.diagnostic.config({
|
vim.diagnostic.config({
|
||||||
underline = true,
|
underline = true,
|
||||||
signs = M.diagnostic_signs,
|
signs = M.diagnostic_signs,
|
||||||
@@ -155,17 +86,365 @@ local function setup_diagnostics()
|
|||||||
wrap = false,
|
wrap = false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
end
|
|
||||||
|
|
||||||
function M.setup()
|
vim.lsp.enable({
|
||||||
load_configs()
|
"bashls",
|
||||||
setup_diagnostics()
|
"clangd",
|
||||||
|
"cmake",
|
||||||
|
"gopls",
|
||||||
|
"intelephense",
|
||||||
|
-- "jedi_language_server",
|
||||||
|
"lemminx",
|
||||||
|
"lua_ls",
|
||||||
|
"mesonlsp",
|
||||||
|
-- "phpactor",
|
||||||
|
-- "pyrefly",
|
||||||
|
"pyright",
|
||||||
|
"ruff",
|
||||||
|
"rust_analyzer",
|
||||||
|
"zls",
|
||||||
|
})
|
||||||
|
|
||||||
for _, server in pairs(servers) do
|
local capabilities = vim.lsp.protocol.make_client_capabilities()
|
||||||
if server.config.enable then
|
local cmp_nvim_lsp = util.try_require("cmp_nvim_lsp")
|
||||||
server:init()
|
if cmp_nvim_lsp then
|
||||||
|
capabilities = vim.tbl_deep_extend(
|
||||||
|
"force",
|
||||||
|
capabilities,
|
||||||
|
cmp_nvim_lsp.default_capabilities()
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
vim.lsp.config("*", {
|
||||||
|
on_attach = M.with_defaults(),
|
||||||
|
capabilities = capabilities,
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.lsp.config("bashls", {
|
||||||
|
filetypes = {
|
||||||
|
"sh",
|
||||||
|
"bash",
|
||||||
|
"zsh",
|
||||||
|
},
|
||||||
|
on_attach = M.with_defaults(function(_, bufnr)
|
||||||
|
keymap.set(bufnr, {
|
||||||
|
{
|
||||||
|
mode = "n",
|
||||||
|
lhs = "<leader>lf",
|
||||||
|
rhs = function()
|
||||||
|
util.format({
|
||||||
|
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(function(_, bufnr)
|
||||||
|
keymap.set(bufnr, {
|
||||||
|
{
|
||||||
|
mode = "n",
|
||||||
|
lhs = "gs",
|
||||||
|
rhs = vim.cmd.ClangdSwitchSourceHeader,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.lsp.config("cmake", {
|
||||||
|
init_options = {
|
||||||
|
buildDirectory = "build",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.lsp.config("gopls", {
|
||||||
|
settings = {
|
||||||
|
gopls = {
|
||||||
|
staticcheck = true,
|
||||||
|
semanticTokens = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
on_attach = M.with_defaults(function(_, bufnr)
|
||||||
|
keymap.set(bufnr, {
|
||||||
|
{
|
||||||
|
mode = "n",
|
||||||
|
lhs = "<leader>lf",
|
||||||
|
rhs = function()
|
||||||
|
util.format({
|
||||||
|
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(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", "source" },
|
||||||
|
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 = "<leader>lf",
|
||||||
|
rhs = function()
|
||||||
|
vim.lsp.buf.format()
|
||||||
|
util.format({
|
||||||
|
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
|
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(function(_, bufnr)
|
||||||
|
keymap.set(bufnr, {
|
||||||
|
{
|
||||||
|
mode = "n",
|
||||||
|
lhs = "<leader>lf",
|
||||||
|
rhs = function()
|
||||||
|
util.format({
|
||||||
|
cmd = { "stylua", "-" },
|
||||||
|
output = "stdout",
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode = "x",
|
||||||
|
lhs = "<leader>lf",
|
||||||
|
rhs = function()
|
||||||
|
util.format({
|
||||||
|
cmd = {
|
||||||
|
"stylua",
|
||||||
|
"-",
|
||||||
|
"--range-start",
|
||||||
|
"%byte_start%",
|
||||||
|
"--range-end",
|
||||||
|
"%byte_end%",
|
||||||
|
},
|
||||||
|
output = "stdout",
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.lsp.config("mesonlsp", {
|
||||||
|
settings = {
|
||||||
|
others = {
|
||||||
|
disableInlayHints = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.lsp.config("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(function(_, bufnr)
|
||||||
|
keymap.set(bufnr, {
|
||||||
|
{
|
||||||
|
mode = "n",
|
||||||
|
lhs = "<leader>lf",
|
||||||
|
rhs = function()
|
||||||
|
vim.lsp.buf.format()
|
||||||
|
util.format({
|
||||||
|
cmd = {
|
||||||
|
"ruff",
|
||||||
|
"check",
|
||||||
|
"--stdin-filename=%file%",
|
||||||
|
"--select=I",
|
||||||
|
"--fix",
|
||||||
|
"--quiet",
|
||||||
|
"-",
|
||||||
|
},
|
||||||
|
output = "stdout",
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.lsp.config("rust_analyzer", {
|
||||||
|
settings = {
|
||||||
|
["rust-analyzer"] = {
|
||||||
|
inlayHints = {
|
||||||
|
chainingHints = {
|
||||||
|
enable = false,
|
||||||
|
},
|
||||||
|
parameterHints = {
|
||||||
|
enable = false,
|
||||||
|
},
|
||||||
|
typeHints = {
|
||||||
|
enable = false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.lsp.config("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
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
local utils = require("ow.utils")
|
|
||||||
|
|
||||||
return {
|
|
||||||
enable = true,
|
|
||||||
dependencies = {
|
|
||||||
"npm",
|
|
||||||
},
|
|
||||||
mason = {
|
|
||||||
"bash-language-server",
|
|
||||||
dependencies = {
|
|
||||||
{ "shellcheck" },
|
|
||||||
{ "shfmt" },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
keymaps = {
|
|
||||||
{
|
|
||||||
mode = "n",
|
|
||||||
lhs = "<leader>lf",
|
|
||||||
rhs = function()
|
|
||||||
utils.format({
|
|
||||||
cmd = { "shfmt", "-s", "-i", "4", "-" },
|
|
||||||
output = "stdout",
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = {
|
|
||||||
"sh",
|
|
||||||
"bash",
|
|
||||||
"zsh",
|
|
||||||
},
|
|
||||||
cmd = { "bash-language-server", "start" },
|
|
||||||
single_file_support = true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
---@type ServerConfig
|
|
||||||
return {
|
|
||||||
enable = true,
|
|
||||||
mason = { "clangd" },
|
|
||||||
keymaps = {
|
|
||||||
{
|
|
||||||
mode = "n",
|
|
||||||
lhs = "gs",
|
|
||||||
rhs = vim.cmd.ClangdSwitchSourceHeader,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
lspconfig = {
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
return {
|
|
||||||
enable = true,
|
|
||||||
dependencies = {
|
|
||||||
"python3",
|
|
||||||
},
|
|
||||||
mason = {
|
|
||||||
name = "cmake-language-server",
|
|
||||||
-- version = "",
|
|
||||||
},
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = {
|
|
||||||
"cmake",
|
|
||||||
},
|
|
||||||
cmd = { "cmake-language-server", },
|
|
||||||
single_file_support = true,
|
|
||||||
init_options = {
|
|
||||||
buildDirectory = "build",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
local utils = require("ow.utils")
|
|
||||||
|
|
||||||
---@type ServerConfig
|
|
||||||
return {
|
|
||||||
enable = true,
|
|
||||||
mason = { "gopls", dependencies = { "golines" } },
|
|
||||||
keymaps = {
|
|
||||||
{
|
|
||||||
mode = "n",
|
|
||||||
lhs = "<leader>lf",
|
|
||||||
rhs = function()
|
|
||||||
utils.format({
|
|
||||||
cmd = { "golines", "-m", "80", "--shorten-comments" },
|
|
||||||
output = "stdout",
|
|
||||||
})
|
|
||||||
vim.lsp.buf.format({ async = true })
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = {
|
|
||||||
"go",
|
|
||||||
"gomod",
|
|
||||||
"gowork",
|
|
||||||
"gotmpl",
|
|
||||||
},
|
|
||||||
cmd = { "gopls" },
|
|
||||||
single_file_support = true,
|
|
||||||
settings = {
|
|
||||||
gopls = {
|
|
||||||
staticcheck = true,
|
|
||||||
semanticTokens = true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
--[[
|
|
||||||
Copyright 2023 Oscar Wallberg
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
]]
|
|
||||||
|
|
||||||
return {
|
|
||||||
enable = false,
|
|
||||||
dependencies = {
|
|
||||||
"java",
|
|
||||||
},
|
|
||||||
mason = {
|
|
||||||
"groovy-language-server",
|
|
||||||
},
|
|
||||||
lspconfig = {
|
|
||||||
cmd = {
|
|
||||||
"groovy-language-server",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
return {
|
|
||||||
enable = true,
|
|
||||||
mason = {
|
|
||||||
name = "haskell-language-server",
|
|
||||||
-- version = "",
|
|
||||||
},
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = { "haskell", "lhaskell", "cabal", },
|
|
||||||
cmd = { "haskell-language-server-wrapper", "--lsp", },
|
|
||||||
single_file_support = true,
|
|
||||||
settings = {
|
|
||||||
haskell = {
|
|
||||||
cabalFormattingProvider = "cabalfmt",
|
|
||||||
formattingProvider = "ormolu",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
-- spec:
|
|
||||||
-- https://github.com/bmewburn/intelephense-docs/blob/master/installation.md
|
|
||||||
-- https://github.com/bmewburn/vscode-intelephense/blob/master/package.json
|
|
||||||
|
|
||||||
local utils = require("ow.utils")
|
|
||||||
|
|
||||||
---@type ServerConfig
|
|
||||||
return {
|
|
||||||
enable = true,
|
|
||||||
dependencies = {
|
|
||||||
"npm",
|
|
||||||
},
|
|
||||||
mason = { "intelephense", dependencies = { "phpcs" } },
|
|
||||||
linters = {
|
|
||||||
{
|
|
||||||
cmd = {
|
|
||||||
"phpcs",
|
|
||||||
"--standard=PSR12",
|
|
||||||
"--report=emacs",
|
|
||||||
"-s",
|
|
||||||
"-q",
|
|
||||||
"-",
|
|
||||||
},
|
|
||||||
stdin = true,
|
|
||||||
stdout = true,
|
|
||||||
pattern = "^.+:(%d+):(%d+): (%w+) %- (.*) %((.*)%)$",
|
|
||||||
groups = { "lnum", "col", "severity", "message", "source" },
|
|
||||||
source = "phpcs",
|
|
||||||
severity_map = {
|
|
||||||
error = vim.diagnostic.severity.ERROR,
|
|
||||||
warning = vim.diagnostic.severity.WARN,
|
|
||||||
},
|
|
||||||
zero_idx_col = true,
|
|
||||||
zero_idx_lnum = true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
keymaps = {
|
|
||||||
{
|
|
||||||
mode = "n",
|
|
||||||
lhs = "<leader>lf",
|
|
||||||
rhs = function()
|
|
||||||
vim.lsp.buf.format()
|
|
||||||
utils.format({
|
|
||||||
cmd = {
|
|
||||||
"php-cs-fixer",
|
|
||||||
"fix",
|
|
||||||
"%file%",
|
|
||||||
"--quiet",
|
|
||||||
},
|
|
||||||
output = "in_place",
|
|
||||||
ignore_stderr = true,
|
|
||||||
env = { PHP_CS_FIXER_IGNORE_ENV = "1" },
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
settings_file = ".intelephense.json",
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = {
|
|
||||||
"php",
|
|
||||||
},
|
|
||||||
cmd = { "intelephense", "--stdio" },
|
|
||||||
single_file_support = true,
|
|
||||||
settings = {
|
|
||||||
intelephense = {
|
|
||||||
environment = {
|
|
||||||
phpVersion = "8.4",
|
|
||||||
},
|
|
||||||
format = {
|
|
||||||
enable = true,
|
|
||||||
braces = "psr12",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
---@type ServerConfig
|
|
||||||
return {
|
|
||||||
mason = { "jedi-language-server" },
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = {
|
|
||||||
"python",
|
|
||||||
},
|
|
||||||
cmd = { "jedi-language-server" },
|
|
||||||
single_file_support = true,
|
|
||||||
init_options = {
|
|
||||||
completion = {
|
|
||||||
disableSnippets = true,
|
|
||||||
},
|
|
||||||
diagnostics = {
|
|
||||||
enable = true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
-- spec: https://github.com/eclipse/lemminx/blob/main/docs/Configuration.md
|
|
||||||
|
|
||||||
return {
|
|
||||||
enable = true,
|
|
||||||
mason = {
|
|
||||||
name = "lemminx",
|
|
||||||
dependencies = { "xmlformatter" },
|
|
||||||
},
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = {
|
|
||||||
"xml",
|
|
||||||
"xsd",
|
|
||||||
"xsl",
|
|
||||||
"xslt",
|
|
||||||
"svg",
|
|
||||||
},
|
|
||||||
cmd = { "lemminx", },
|
|
||||||
single_file_support = true,
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
-- spec: https://luals.github.io/wiki/settings/
|
|
||||||
local utils = require("ow.utils")
|
|
||||||
|
|
||||||
---@type ServerConfig
|
|
||||||
return {
|
|
||||||
enable = true,
|
|
||||||
dependencies = { "cargo" },
|
|
||||||
mason = {
|
|
||||||
"lua-language-server",
|
|
||||||
post_install = { { cmd = { "cargo", "install", "stylua", "--features", "lua54" } } },
|
|
||||||
},
|
|
||||||
keymaps = {
|
|
||||||
{
|
|
||||||
mode = "n",
|
|
||||||
lhs = "<leader>lf",
|
|
||||||
rhs = function()
|
|
||||||
utils.format({
|
|
||||||
cmd = { "stylua", "-" },
|
|
||||||
output = "stdout",
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
mode = "x",
|
|
||||||
lhs = "<leader>lf",
|
|
||||||
rhs = function()
|
|
||||||
utils.format({
|
|
||||||
cmd = {
|
|
||||||
"stylua",
|
|
||||||
"-",
|
|
||||||
"--range-start",
|
|
||||||
"%byte_start%",
|
|
||||||
"--range-end",
|
|
||||||
"%byte_end%",
|
|
||||||
},
|
|
||||||
output = "stdout",
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = { "lua" },
|
|
||||||
cmd = { "lua-language-server" },
|
|
||||||
single_file_support = true,
|
|
||||||
settings = {
|
|
||||||
Lua = {
|
|
||||||
completion = { showWord = "Disable" },
|
|
||||||
diagnostics = {
|
|
||||||
-- disable = { "missing-fields" },
|
|
||||||
},
|
|
||||||
runtime = {
|
|
||||||
version = "LuaJIT",
|
|
||||||
path = {
|
|
||||||
-- "?.lua",
|
|
||||||
"?.lua",
|
|
||||||
"?/init.lua",
|
|
||||||
-- "?.lua",
|
|
||||||
-- "lua/?.lua",
|
|
||||||
-- "lua/?/init.lua",
|
|
||||||
-- "?/lua/?.lua",
|
|
||||||
-- "?/lua/?/init.lua",
|
|
||||||
},
|
|
||||||
-- pathStrict = true,
|
|
||||||
},
|
|
||||||
workspace = {
|
|
||||||
library = {
|
|
||||||
vim.env.VIMRUNTIME,
|
|
||||||
"~/repos/awesome-code-doc",
|
|
||||||
"/usr/share/awesome/lib",
|
|
||||||
vim.fn.stdpath("data") .. "/lazy",
|
|
||||||
},
|
|
||||||
checkThirdParty = false,
|
|
||||||
},
|
|
||||||
hint = {
|
|
||||||
enable = false,
|
|
||||||
arrayIndex = "Disable",
|
|
||||||
await = true,
|
|
||||||
paramName = "All",
|
|
||||||
paramType = true,
|
|
||||||
semicolon = "Disable",
|
|
||||||
setType = true,
|
|
||||||
},
|
|
||||||
telemetry = { enable = false },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
---@type ServerConfig
|
|
||||||
return {
|
|
||||||
enable = true,
|
|
||||||
mason = { "mesonlsp" },
|
|
||||||
lspconfig = {
|
|
||||||
---@type fun(filename: string, bufnr: number): string?
|
|
||||||
root_dir = function(filename, bufnr)
|
|
||||||
local parent = require("lspconfig").util.find_git_ancestor(filename)
|
|
||||||
if not parent then
|
|
||||||
local win = vim.fn.bufwinid(bufnr)
|
|
||||||
parent = vim.fn.getcwd(win)
|
|
||||||
end
|
|
||||||
return parent
|
|
||||||
end,
|
|
||||||
settings = {
|
|
||||||
others = {
|
|
||||||
disableInlayHints = true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
local util = require("lspconfig.util")
|
|
||||||
|
|
||||||
---@type ServerConfig
|
|
||||||
return {
|
|
||||||
enable = false,
|
|
||||||
dependencies = { "pyrefly" },
|
|
||||||
lspconfig = {
|
|
||||||
cmd = { "pyrefly", "lsp" },
|
|
||||||
filetypes = { "python" },
|
|
||||||
root_dir = util.root_pattern(
|
|
||||||
"pyrefly.toml",
|
|
||||||
"pyproject.toml",
|
|
||||||
"setup.py",
|
|
||||||
"setup.cfg",
|
|
||||||
"requirements.txt",
|
|
||||||
"Pipfile",
|
|
||||||
".git"
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
---@type ServerConfig
|
|
||||||
return {
|
|
||||||
mason = { "pyright" },
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = {
|
|
||||||
"python",
|
|
||||||
},
|
|
||||||
cmd = { "pyright-langserver", "--stdio" },
|
|
||||||
single_file_support = true,
|
|
||||||
-- https://microsoft.github.io/pyright/#/settings
|
|
||||||
settings = {
|
|
||||||
python = {
|
|
||||||
analysis = {
|
|
||||||
autoSearchPaths = true,
|
|
||||||
diagnosticMode = "openFilesOnly",
|
|
||||||
useLibraryCodeForTypes = true,
|
|
||||||
typeCheckingMode = "strict",
|
|
||||||
stubPath = "stubs",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pyright = {
|
|
||||||
disableLanguageServices = true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
local utils = require("ow.utils")
|
|
||||||
|
|
||||||
---@type ServerConfig
|
|
||||||
return {
|
|
||||||
mason = "ruff",
|
|
||||||
keymaps = {
|
|
||||||
{
|
|
||||||
mode = "n",
|
|
||||||
lhs = "<leader>lf",
|
|
||||||
rhs = function()
|
|
||||||
vim.lsp.buf.format()
|
|
||||||
utils.format({
|
|
||||||
cmd = {
|
|
||||||
"ruff",
|
|
||||||
"check",
|
|
||||||
"--stdin-filename=%file%",
|
|
||||||
"--select=I",
|
|
||||||
"--fix",
|
|
||||||
"--quiet",
|
|
||||||
"-",
|
|
||||||
},
|
|
||||||
output = "stdout",
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,191 +0,0 @@
|
|||||||
-- spec: https://rust-analyzer.github.io/manual.html#configuration
|
|
||||||
|
|
||||||
return {
|
|
||||||
enable = true,
|
|
||||||
mason = {
|
|
||||||
name = "rust-analyzer",
|
|
||||||
-- version = "",
|
|
||||||
},
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = {
|
|
||||||
"rust",
|
|
||||||
},
|
|
||||||
cmd = { "rust-analyzer", },
|
|
||||||
single_file_support = true,
|
|
||||||
settings = {
|
|
||||||
["rust-analyzer"] = {
|
|
||||||
inlayHints = {
|
|
||||||
chainingHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
parameterHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
typeHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
--[[ assist = {
|
|
||||||
emitMustUse = false,
|
|
||||||
expressionFillDefault = false,
|
|
||||||
},
|
|
||||||
cachePriming = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
cargo = {
|
|
||||||
autoreload = false,
|
|
||||||
buildScripts = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
checkOnSave = false,
|
|
||||||
completion = {
|
|
||||||
autoimport = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
autoself = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
callable = {
|
|
||||||
snippets = false,
|
|
||||||
},
|
|
||||||
fullFunctionSignatures = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
postfix = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
privateEditable = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
diagnostics = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
highlightRelated = {
|
|
||||||
breakPoints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
closureCaptures = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
exitPoints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
references = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
yieldPoints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
hover = {
|
|
||||||
actions = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
documentation = {
|
|
||||||
enable = true,
|
|
||||||
},
|
|
||||||
links = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
memoryLayout = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
imports = {
|
|
||||||
group = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
inlayHints = {
|
|
||||||
bindingModeHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
chainingHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
closingBraceHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
closureCaptureHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
closureReturnTypeHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
discriminantHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
expressionAdjustmentHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
lifetimeElisionHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
parameterHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
reborrowHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
typeHints = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
joinLines = {
|
|
||||||
joinAssignments = false,
|
|
||||||
joinElseIf = false,
|
|
||||||
removeTrailingComma = false,
|
|
||||||
unwrapTrivialBlock = false,
|
|
||||||
},
|
|
||||||
lens = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
notifications = {
|
|
||||||
cargoTomlNotFound = false,
|
|
||||||
},
|
|
||||||
procMacro = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
references = {
|
|
||||||
excludeImports = false,
|
|
||||||
},
|
|
||||||
rustfmt = {
|
|
||||||
rangeFormatting = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
semanticHighlighting = {
|
|
||||||
doc = {
|
|
||||||
comment = {
|
|
||||||
inject = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
nonStandardTokens = false,
|
|
||||||
operator = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
punctuation = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
strings = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
signatureInfo = {
|
|
||||||
documentation = {
|
|
||||||
enable = true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
typing = {
|
|
||||||
autoClosingAngleBrackets = {
|
|
||||||
enable = false,
|
|
||||||
},
|
|
||||||
}, ]]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
-- spec: https://github.com/zigtools/zls#configuration-options
|
|
||||||
|
|
||||||
---@type ServerConfig
|
|
||||||
return {
|
|
||||||
enable = true,
|
|
||||||
dependencies = {
|
|
||||||
"zig",
|
|
||||||
},
|
|
||||||
-- mason = {
|
|
||||||
-- name = "zls",
|
|
||||||
-- -- version = "",
|
|
||||||
-- },
|
|
||||||
lspconfig = {
|
|
||||||
filetypes = {
|
|
||||||
"zig",
|
|
||||||
"zir",
|
|
||||||
},
|
|
||||||
cmd = { "zls", },
|
|
||||||
single_file_support = true,
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
+19
-55
@@ -1,7 +1,4 @@
|
|||||||
-- Mappings.
|
local util = require("ow.util")
|
||||||
-- See `:help vim.lsp.*` for documentation on any of the below functions
|
|
||||||
|
|
||||||
local utils = require("ow.utils")
|
|
||||||
|
|
||||||
---@class Keymap
|
---@class Keymap
|
||||||
---@field mode string|string[]
|
---@field mode string|string[]
|
||||||
@@ -9,29 +6,25 @@ local utils = require("ow.utils")
|
|||||||
---@field rhs string|function
|
---@field rhs string|function
|
||||||
---@field opts? vim.keymap.set.Opts
|
---@field opts? vim.keymap.set.Opts
|
||||||
|
|
||||||
local MODE_TYPES = { "n", "v", "s", "x", "o", "i", "l", "c" }
|
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
---@type table<number, vim.api.keyset.keymap[]>
|
---@param bufnr integer
|
||||||
M.old = {}
|
---@param keymaps Keymap[]
|
||||||
|
function M.set(bufnr, keymaps)
|
||||||
---@type table<number, Keymap[]>
|
for _, keymap in ipairs(keymaps) do
|
||||||
M.new = {}
|
keymap.opts = vim.tbl_extend(
|
||||||
|
"force",
|
||||||
--- Load LSP keybinds
|
keymap.opts or {},
|
||||||
---@param server Server
|
{ buffer = bufnr, remap = true }
|
||||||
function M:init(server, bufnr)
|
|
||||||
self.old[bufnr] = {}
|
|
||||||
for _, mode in ipairs(MODE_TYPES) do
|
|
||||||
vim.tbl_extend(
|
|
||||||
"error",
|
|
||||||
self.old[bufnr],
|
|
||||||
vim.api.nvim_buf_get_keymap(bufnr, mode)
|
|
||||||
)
|
)
|
||||||
|
vim.keymap.set(keymap.mode, keymap.lhs, keymap.rhs, keymap.opts)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
self.new[bufnr] = {
|
---@param bufnr integer
|
||||||
|
function M.set_defaults(bufnr)
|
||||||
|
---@type Keymap[]
|
||||||
|
local keymaps = {
|
||||||
{ mode = { "n" }, lhs = "<leader>df", rhs = vim.diagnostic.open_float },
|
{ mode = { "n" }, lhs = "<leader>df", rhs = vim.diagnostic.open_float },
|
||||||
{
|
{
|
||||||
mode = { "n" },
|
mode = { "n" },
|
||||||
@@ -88,10 +81,10 @@ function M:init(server, bufnr)
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
local telescope = utils.try_require("telescope.builtin")
|
local telescope = util.try_require("telescope.builtin")
|
||||||
|
|
||||||
if telescope then
|
if telescope then
|
||||||
vim.list_extend(self.new[bufnr], {
|
vim.list_extend(keymaps, {
|
||||||
{ mode = "n", lhs = "<leader>dl", rhs = telescope.diagnostics },
|
{ mode = "n", lhs = "<leader>dl", rhs = telescope.diagnostics },
|
||||||
{ mode = "n", lhs = "grt", rhs = telescope.lsp_type_definitions, },
|
{ mode = "n", lhs = "grt", rhs = telescope.lsp_type_definitions, },
|
||||||
{ mode = "n", lhs = "gd", rhs = telescope.lsp_definitions },
|
{ mode = "n", lhs = "gd", rhs = telescope.lsp_definitions },
|
||||||
@@ -99,43 +92,14 @@ function M:init(server, bufnr)
|
|||||||
{ mode = "n", lhs = "grr", rhs = telescope.lsp_references },
|
{ mode = "n", lhs = "grr", rhs = telescope.lsp_references },
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
vim.list_extend(self.new[bufnr], {
|
vim.list_extend(keymaps, {
|
||||||
{ mode = "n", lhs = "<leader>dl", rhs = vim.diagnostic.setloclist },
|
{ mode = "n", lhs = "<leader>dl", rhs = vim.diagnostic.setloclist },
|
||||||
{ mode = "n", lhs = "grt", rhs = vim.lsp.buf.type_definition, },
|
{ mode = "n", lhs = "grt", rhs = vim.lsp.buf.type_definition, },
|
||||||
{ mode = "n", lhs = "gd", rhs = vim.lsp.buf.definition },
|
{ mode = "n", lhs = "gd", rhs = vim.lsp.buf.definition },
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
if server.config.keymaps then
|
M.set(bufnr, keymaps)
|
||||||
vim.list_extend(self.new[bufnr], server.config.keymaps)
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, keymap in ipairs(self.new[bufnr]) 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
|
|
||||||
|
|
||||||
function M:deinit(bufnr)
|
|
||||||
if self.new[bufnr] then
|
|
||||||
for _, keymap in ipairs(self.new[bufnr]) do
|
|
||||||
-- pcall to avoid error if keymap was already removed,
|
|
||||||
-- for example if server.config.keymaps overrides a default LSP keymap
|
|
||||||
pcall(vim.keymap.del, keymap.mode, keymap.lhs, { buffer = bufnr })
|
|
||||||
end
|
|
||||||
self.new[bufnr] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.old[bufnr] then
|
|
||||||
for _, keymap in ipairs(self.old[bufnr]) do
|
|
||||||
vim.cmd.mapset(keymap)
|
|
||||||
end
|
|
||||||
self.old[bufnr] = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
+55
-58
@@ -1,10 +1,10 @@
|
|||||||
local utils = require("ow.utils")
|
local util = require("ow.util")
|
||||||
|
local log = require("ow.log")
|
||||||
|
|
||||||
---@class Linter
|
---@class Linter
|
||||||
---@field name string
|
|
||||||
---@field namespace number
|
---@field namespace number
|
||||||
---@field augroup number
|
---@field augroup number
|
||||||
---@field buffers number[]
|
---@field bufnr number
|
||||||
---@field config LinterConfig
|
---@field config LinterConfig
|
||||||
M = {}
|
M = {}
|
||||||
M.__index = M
|
M.__index = M
|
||||||
@@ -89,10 +89,9 @@ end
|
|||||||
|
|
||||||
--- Clamp column to line length
|
--- Clamp column to line length
|
||||||
---@param diag vim.Diagnostic
|
---@param diag vim.Diagnostic
|
||||||
---@param bufnr number
|
function M:clamp_col(diag)
|
||||||
function M:clamp_col(diag, bufnr)
|
|
||||||
local lines =
|
local lines =
|
||||||
vim.api.nvim_buf_get_lines(bufnr, diag.lnum, diag.lnum + 1, false)
|
vim.api.nvim_buf_get_lines(self.bufnr, diag.lnum, diag.lnum + 1, false)
|
||||||
if #lines == 0 then
|
if #lines == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -160,7 +159,7 @@ function M:fix_indexing(diag)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function M:process_json_output(json, bufnr)
|
function M:process_json_output(json)
|
||||||
---@type vim.Diagnostic[]
|
---@type vim.Diagnostic[]
|
||||||
local diagnostics = {}
|
local diagnostics = {}
|
||||||
|
|
||||||
@@ -170,7 +169,7 @@ function M:process_json_output(json, bufnr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if type(items) ~= "table" then
|
if type(items) ~= "table" then
|
||||||
utils.err("diagnostics root is not an array or object")
|
log.error("diagnostics root is not an array or object")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -198,7 +197,7 @@ function M:process_json_output(json, bufnr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
self:fix_indexing(diag)
|
self:fix_indexing(diag)
|
||||||
self:clamp_col(diag, bufnr)
|
self:clamp_col(diag)
|
||||||
self:add_tags(diag)
|
self:add_tags(diag)
|
||||||
|
|
||||||
if type(self.config.json.callback) == "function" then
|
if type(self.config.json.callback) == "function" then
|
||||||
@@ -212,12 +211,10 @@ function M:process_json_output(json, bufnr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Validate input
|
--- Validate input
|
||||||
---@param name string
|
|
||||||
---@param config LinterConfig
|
---@param config LinterConfig
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function M.validate(name, config)
|
function M.validate(config)
|
||||||
local ok, resp = pcall(vim.validate, {
|
local ok, resp = pcall(vim.validate, {
|
||||||
name = { name, "string" },
|
|
||||||
config = { config, "table" },
|
config = { config, "table" },
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -226,7 +223,7 @@ function M.validate(name, config)
|
|||||||
cmd = {
|
cmd = {
|
||||||
config.cmd,
|
config.cmd,
|
||||||
function(t)
|
function(t)
|
||||||
return utils.is_list(t, "string")
|
return util.is_list(t, "string")
|
||||||
end,
|
end,
|
||||||
"list of strings",
|
"list of strings",
|
||||||
},
|
},
|
||||||
@@ -237,7 +234,7 @@ function M.validate(name, config)
|
|||||||
groups = {
|
groups = {
|
||||||
config.groups,
|
config.groups,
|
||||||
function(t)
|
function(t)
|
||||||
return utils.is_list(t, "string")
|
return util.is_list(t, "string")
|
||||||
end,
|
end,
|
||||||
true,
|
true,
|
||||||
"list of strings",
|
"list of strings",
|
||||||
@@ -245,7 +242,7 @@ function M.validate(name, config)
|
|||||||
severity_map = {
|
severity_map = {
|
||||||
config.severity_map,
|
config.severity_map,
|
||||||
function(t)
|
function(t)
|
||||||
return utils.is_map(t, "string", "number")
|
return util.is_map(t, "string", "number")
|
||||||
end,
|
end,
|
||||||
true,
|
true,
|
||||||
"map of string and number",
|
"map of string and number",
|
||||||
@@ -258,23 +255,24 @@ function M.validate(name, config)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not ok then
|
if not ok then
|
||||||
utils.err(("Invalid config for linter:\n%s"):format(resp))
|
log.error("Invalid config for linter: %s", resp)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
if not config.json and (not config.pattern or not config.groups) then
|
if not config.json and (not config.pattern or not config.groups) then
|
||||||
utils.err("Either json or pattern and groups must be provided")
|
log.error("Either json or pattern and groups must be provided")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function M:run(bufnr)
|
---@return boolean success
|
||||||
|
function M:run()
|
||||||
local input
|
local input
|
||||||
|
|
||||||
if self.config.stdin then
|
if self.config.stdin then
|
||||||
input = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
input = vim.api.nvim_buf_get_lines(self.bufnr, 0, -1, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
local cmd = vim.fn.copy(self.config.cmd)
|
local cmd = vim.fn.copy(self.config.cmd)
|
||||||
@@ -286,6 +284,7 @@ function M:run(bufnr)
|
|||||||
cmd[i] = arg
|
cmd[i] = arg
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local success = true
|
||||||
local ok, resp = pcall(
|
local ok, resp = pcall(
|
||||||
vim.system,
|
vim.system,
|
||||||
cmd,
|
cmd,
|
||||||
@@ -301,7 +300,7 @@ function M:run(bufnr)
|
|||||||
if self.config.stderr then
|
if self.config.stderr then
|
||||||
output = out.stderr or ""
|
output = out.stderr or ""
|
||||||
elseif out.stderr and out.stderr ~= "" then
|
elseif out.stderr and out.stderr ~= "" then
|
||||||
utils.err(out.stderr)
|
log.error(out.stderr)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.config.json then
|
if self.config.json then
|
||||||
@@ -311,13 +310,14 @@ function M:run(bufnr)
|
|||||||
{ luanil = { object = true, array = true } }
|
{ luanil = { object = true, array = true } }
|
||||||
)
|
)
|
||||||
if not ok then
|
if not ok then
|
||||||
utils.err("Failed to parse JSON: " .. json)
|
log.error("Failed to parse JSON: " .. json)
|
||||||
|
success = false
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local diagnostics = self:process_json_output(json, bufnr)
|
local diagnostics = self:process_json_output(json)
|
||||||
if diagnostics then
|
if diagnostics then
|
||||||
vim.diagnostic.set(self.namespace, bufnr, diagnostics)
|
vim.diagnostic.set(self.namespace, self.bufnr, diagnostics)
|
||||||
end
|
end
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -335,67 +335,64 @@ function M:run(bufnr)
|
|||||||
)
|
)
|
||||||
|
|
||||||
if not ok then
|
if not ok then
|
||||||
utils.err(tostring(resp))
|
log.error(tostring(resp))
|
||||||
|
success = false
|
||||||
return
|
return
|
||||||
elseif resp then
|
elseif resp then
|
||||||
resp.source = resp.source or self.config.source
|
resp.source = resp.source or self.config.source
|
||||||
self:clamp_col(resp, bufnr)
|
self:clamp_col(resp)
|
||||||
self:add_tags(resp)
|
self:add_tags(resp)
|
||||||
self:fix_indexing(resp)
|
self:fix_indexing(resp)
|
||||||
table.insert(diagnostics, resp)
|
table.insert(diagnostics, resp)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
vim.diagnostic.set(self.namespace, bufnr, diagnostics)
|
vim.diagnostic.set(self.namespace, self.bufnr, diagnostics)
|
||||||
end)
|
end)
|
||||||
)
|
)
|
||||||
|
|
||||||
if not ok then
|
if not ok then
|
||||||
utils.err(("Failed to run %s:\n%s"):format(self.config.cmd[1], resp))
|
log.error("Failed to run %s: %s", self.config.cmd[1], resp)
|
||||||
|
success = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return success
|
||||||
end
|
end
|
||||||
|
|
||||||
function M:init(bufnr)
|
---@param bufnr integer
|
||||||
table.insert(self.buffers, bufnr)
|
|
||||||
vim.api.nvim_create_autocmd({ "TextChanged", "TextChangedI" }, {
|
|
||||||
buffer = bufnr,
|
|
||||||
callback = utils.debounce(function()
|
|
||||||
self:run(bufnr)
|
|
||||||
end, self.config.debounce),
|
|
||||||
group = self.augroup,
|
|
||||||
})
|
|
||||||
self:run(bufnr)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M:deinit()
|
|
||||||
for _, bufnr in ipairs(self.buffers) do
|
|
||||||
vim.api.nvim_buf_clear_namespace(bufnr, self.namespace, 0, -1)
|
|
||||||
end
|
|
||||||
self.buffers = {}
|
|
||||||
|
|
||||||
vim.api.nvim_clear_autocmds({ group = self.augroup })
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Create a new instance
|
|
||||||
---@param name string
|
|
||||||
---@param config LinterConfig
|
---@param config LinterConfig
|
||||||
---@return Linter|nil
|
function M.add(bufnr, config)
|
||||||
function M.new(name, config)
|
if not M.validate(config) then
|
||||||
if not M.validate(name, config) then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
config.debounce = config.debounce or 100
|
config.debounce = config.debounce or 100
|
||||||
|
|
||||||
local linter = {
|
local linter = {
|
||||||
name = name,
|
namespace = vim.api.nvim_create_namespace("ow.lsp.linter"),
|
||||||
namespace = vim.api.nvim_create_namespace(name),
|
augroup = vim.api.nvim_create_augroup(
|
||||||
augroup = vim.api.nvim_create_augroup(name, {}),
|
"ow.lsp.linter",
|
||||||
buffers = {},
|
{ clear = false }
|
||||||
|
),
|
||||||
|
bufnr = bufnr,
|
||||||
config = config,
|
config = config,
|
||||||
}
|
}
|
||||||
|
|
||||||
return setmetatable(linter, M)
|
linter = setmetatable(linter, M)
|
||||||
|
|
||||||
|
local success = linter:run()
|
||||||
|
if not success then
|
||||||
|
log.error("Not adding linter because of previous errors")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd({ "TextChanged", "TextChangedI" }, {
|
||||||
|
buffer = linter.bufnr,
|
||||||
|
callback = util.debounce(function()
|
||||||
|
linter:run()
|
||||||
|
end, linter.config.debounce),
|
||||||
|
group = linter.augroup,
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -1,341 +0,0 @@
|
|||||||
local utils = require("ow.utils")
|
|
||||||
|
|
||||||
---@class PostInstallStep
|
|
||||||
---@field cmd string[]
|
|
||||||
|
|
||||||
---@class MasonPackage
|
|
||||||
---@field dependencies? MasonPackage[]
|
|
||||||
---@field config MasonPackageConfig
|
|
||||||
local M = {}
|
|
||||||
M.__index = M
|
|
||||||
|
|
||||||
---@class MasonPackageConfig
|
|
||||||
---@field [1]? string
|
|
||||||
---@field name? string
|
|
||||||
---@field version? string
|
|
||||||
---@field dependencies? string[]|MasonPackageConfig[]
|
|
||||||
---@field post_install? PostInstallStep[]
|
|
||||||
M.config = {}
|
|
||||||
|
|
||||||
--- Validate MasonPackageConfig
|
|
||||||
---@param config string|MasonPackageConfig
|
|
||||||
---@return boolean
|
|
||||||
function M.validate(config)
|
|
||||||
local ok, resp = pcall(vim.validate, { config = { config, { "table" } } })
|
|
||||||
if ok then
|
|
||||||
ok, resp = pcall(vim.validate, {
|
|
||||||
name = { config.name or config[1], { "string" }, true },
|
|
||||||
version = { config.version, { "string" }, true },
|
|
||||||
dependencies = {
|
|
||||||
config.dependencies,
|
|
||||||
function(f)
|
|
||||||
if not f then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, dep in ipairs(f) do
|
|
||||||
local t = type(dep)
|
|
||||||
if
|
|
||||||
(t ~= "string" and t ~= "table")
|
|
||||||
or (type(dep) == "table" and not M.validate(dep))
|
|
||||||
then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
"list of string|MasonPackageConfig",
|
|
||||||
},
|
|
||||||
post_install = {
|
|
||||||
config.post_install,
|
|
||||||
function(field)
|
|
||||||
if not field then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
if not utils.is_list(field) then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, step in ipairs(field) do
|
|
||||||
local o, r = pcall(vim.validate, { step = { step, { "table" } } })
|
|
||||||
if o then
|
|
||||||
o, r = pcall(vim.validate, {
|
|
||||||
cmd = {
|
|
||||||
step.cmd,
|
|
||||||
function(f)
|
|
||||||
return utils.is_list(f, "string")
|
|
||||||
end,
|
|
||||||
"list of strings or nil",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
if not o then
|
|
||||||
utils.err(("Invalid config for post_install step: %s"):format(r), "LSP")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
"list of steps",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
if not ok then
|
|
||||||
utils.err(
|
|
||||||
("Invalid config for %s:\n%s"):format(config.name or config[1] or config, resp),
|
|
||||||
"LSP"
|
|
||||||
)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Run post installation steps
|
|
||||||
---@param pkg Package
|
|
||||||
function M:post_install(pkg)
|
|
||||||
---@param step PostInstallStep
|
|
||||||
---@param msg string
|
|
||||||
local function log_err(step, msg)
|
|
||||||
local cmd = table.concat(step.cmd, " ")
|
|
||||||
|
|
||||||
utils.err(
|
|
||||||
("Post installation step for %s:\n`%s`\nfailed with:\n%s"):format(
|
|
||||||
self.config.name,
|
|
||||||
cmd,
|
|
||||||
msg
|
|
||||||
),
|
|
||||||
"LSP"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.config.post_install then
|
|
||||||
for _, step in ipairs(self.config.post_install) do
|
|
||||||
utils.info("running post install step", "LSP")
|
|
||||||
local cwd = pkg:get_install_path()
|
|
||||||
local args = step.cmd
|
|
||||||
local prog = table.remove(args, 1)
|
|
||||||
|
|
||||||
if prog:find("[/\\]") then
|
|
||||||
prog = vim.fn.resolve(("%s/%s"):format(cwd, prog))
|
|
||||||
end
|
|
||||||
|
|
||||||
if not utils.is_executable(prog) then
|
|
||||||
log_err(step, "command not executable")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local job = require("plenary.job"):new({
|
|
||||||
command = prog,
|
|
||||||
args = args,
|
|
||||||
cwd = pkg:get_install_path(),
|
|
||||||
enabled_recording = true,
|
|
||||||
on_exit = vim.schedule_wrap(function(job, code, signal)
|
|
||||||
if code ~= 0 or signal ~= 0 then
|
|
||||||
log_err(step, table.concat(job:stderr_result(), "\n"))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
utils.info("post install step done", "LSP")
|
|
||||||
end),
|
|
||||||
})
|
|
||||||
job:start()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Handle installation
|
|
||||||
---@param pkg Package
|
|
||||||
---@param old_version? string
|
|
||||||
---@param new_version? string
|
|
||||||
---@param on_done? fun(success: boolean)
|
|
||||||
function M:handle_install(pkg, old_version, new_version, on_done)
|
|
||||||
local version_str = ""
|
|
||||||
if old_version and new_version then
|
|
||||||
version_str = (" %s -> %s"):format(old_version, new_version)
|
|
||||||
elseif new_version then
|
|
||||||
version_str = " " .. new_version
|
|
||||||
end
|
|
||||||
|
|
||||||
utils.info(("Installing %s%s"):format(self.config.name, version_str), "LSP")
|
|
||||||
local handle = pkg:install({ version = new_version })
|
|
||||||
local err
|
|
||||||
handle:on(
|
|
||||||
"stderr",
|
|
||||||
vim.schedule_wrap(function(msg)
|
|
||||||
err = (err or "") .. msg
|
|
||||||
end)
|
|
||||||
)
|
|
||||||
|
|
||||||
handle:once(
|
|
||||||
"closed",
|
|
||||||
vim.schedule_wrap(function()
|
|
||||||
local is_installed = pkg:is_installed()
|
|
||||||
|
|
||||||
if is_installed then
|
|
||||||
utils.info(("Successfully installed %s"):format(self.config.name), "LSP")
|
|
||||||
self:post_install(pkg)
|
|
||||||
else
|
|
||||||
if err then
|
|
||||||
err = ":\n" .. err
|
|
||||||
else
|
|
||||||
err = ""
|
|
||||||
end
|
|
||||||
|
|
||||||
utils.err(("Failed to install %s%s"):format(self.config.name, err), "LSP")
|
|
||||||
end
|
|
||||||
|
|
||||||
if on_done then
|
|
||||||
on_done(is_installed)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Perform installation
|
|
||||||
---@param on_done fun(success: boolean)?
|
|
||||||
function M:install(on_done)
|
|
||||||
local registry = require("mason-registry")
|
|
||||||
local success, result = pcall(registry.get_package, self.config.name)
|
|
||||||
|
|
||||||
if not success then
|
|
||||||
utils.err(("Failed to get package %s:\n%s"):format(self.config.name, result), "LSP")
|
|
||||||
|
|
||||||
if on_done then
|
|
||||||
on_done(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local pkg = result
|
|
||||||
|
|
||||||
if not pkg:is_installed() then
|
|
||||||
self:handle_install(pkg, nil, self.config.version, on_done)
|
|
||||||
elseif self.config.version then
|
|
||||||
pkg:get_installed_version(function(ok, version_or_err)
|
|
||||||
if not ok then
|
|
||||||
utils.err(
|
|
||||||
("Failed to check currently installed version for %s:\n%s"):format(
|
|
||||||
self.config.name,
|
|
||||||
version_or_err
|
|
||||||
),
|
|
||||||
"LSP"
|
|
||||||
)
|
|
||||||
elseif self.config.version ~= version_or_err then
|
|
||||||
self:handle_install(pkg, version_or_err, self.config.version, on_done)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if on_done then
|
|
||||||
on_done(ok)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
pkg:check_new_version(function(update_available, res)
|
|
||||||
local ok = type(res) == "table" or res == "Package is not outdated."
|
|
||||||
|
|
||||||
if not ok then
|
|
||||||
utils.err(
|
|
||||||
("Failed to check for update for %s:\n%s"):format(self.config.name, res),
|
|
||||||
"LSP"
|
|
||||||
)
|
|
||||||
elseif update_available then
|
|
||||||
self:handle_install(pkg, res.current_version, res.latest_version, on_done)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if on_done then
|
|
||||||
on_done(ok)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Install package dependencies
|
|
||||||
---@param on_done fun(success: boolean)?
|
|
||||||
function M:install_dependencies(on_done)
|
|
||||||
local total = #self.dependencies
|
|
||||||
local completed = 0
|
|
||||||
local all_successful = true
|
|
||||||
|
|
||||||
--- Handle install result
|
|
||||||
---@param success boolean
|
|
||||||
local function handle_result(success)
|
|
||||||
completed = completed + 1
|
|
||||||
|
|
||||||
if not success then
|
|
||||||
all_successful = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if completed == total and on_done then
|
|
||||||
on_done(all_successful)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, dep in ipairs(self.dependencies) do
|
|
||||||
dep:install_with_dependencies(handle_result)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Install package and any defined dependencies
|
|
||||||
---@param on_done fun(success: boolean)?
|
|
||||||
function M:install_with_dependencies(on_done)
|
|
||||||
--- Handle install result
|
|
||||||
---@param success boolean
|
|
||||||
local function handle_result(success)
|
|
||||||
if success then
|
|
||||||
self:install(on_done)
|
|
||||||
elseif on_done then
|
|
||||||
on_done(success)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
require("mason-registry").refresh(function()
|
|
||||||
if self.dependencies and #self.dependencies ~= 0 then
|
|
||||||
self:install_dependencies(handle_result)
|
|
||||||
else
|
|
||||||
self:install(on_done)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Create a new instance
|
|
||||||
---@param config MasonPackageConfig|string
|
|
||||||
---@return MasonPackage|nil
|
|
||||||
function M.new(config)
|
|
||||||
if type(config) == "string" then
|
|
||||||
config = { config }
|
|
||||||
end
|
|
||||||
|
|
||||||
if not M.validate(config) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
config.name = config.name or config[1]
|
|
||||||
|
|
||||||
local pkg = { config = config }
|
|
||||||
|
|
||||||
if pkg.config.dependencies then
|
|
||||||
pkg.dependencies = {}
|
|
||||||
|
|
||||||
for _, dep_cfg in ipairs(config.dependencies) do
|
|
||||||
local dep = M.new(dep_cfg)
|
|
||||||
if dep then
|
|
||||||
table.insert(pkg.dependencies, dep)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(pkg, M)
|
|
||||||
end
|
|
||||||
|
|
||||||
return M
|
|
||||||
@@ -1,392 +0,0 @@
|
|||||||
local keymap = require("ow.lsp.keymap")
|
|
||||||
local utils = require("ow.utils")
|
|
||||||
|
|
||||||
---@class Linter
|
|
||||||
local Linter = require("ow.lsp.linter")
|
|
||||||
|
|
||||||
---@class MasonPackage
|
|
||||||
local MasonPackage = require("ow.lsp.package")
|
|
||||||
|
|
||||||
---@class Server
|
|
||||||
---@field name? string
|
|
||||||
---@field mason? MasonPackage
|
|
||||||
---@field client? vim.lsp.Client
|
|
||||||
---@field attached_buffers? number[]
|
|
||||||
---@field manager lspconfig.Manager
|
|
||||||
---@field linters? Linter[]
|
|
||||||
---@field config ServerConfig
|
|
||||||
local M = {}
|
|
||||||
|
|
||||||
M.__index = M
|
|
||||||
|
|
||||||
---@class ServerConfig
|
|
||||||
---@field enable? boolean
|
|
||||||
---@field dependencies? string[]
|
|
||||||
---@field mason? string|MasonPackageConfig
|
|
||||||
---@field keymaps? Keymap[]
|
|
||||||
---@field linters? LinterConfig[]
|
|
||||||
---@field settings_file? string
|
|
||||||
---@field lspconfig? lspconfig.Config
|
|
||||||
M.config = {}
|
|
||||||
|
|
||||||
--- Validate ServerConfig
|
|
||||||
---@param config ServerConfig
|
|
||||||
---@return boolean
|
|
||||||
function M.validate(name, config)
|
|
||||||
local ok, resp = pcall(vim.validate, { config = { config, { "table" } } })
|
|
||||||
|
|
||||||
if ok then
|
|
||||||
ok, resp = pcall(vim.validate, {
|
|
||||||
enable = { config.enable, { "boolean" }, true },
|
|
||||||
dependencies = {
|
|
||||||
config.dependencies,
|
|
||||||
function(f)
|
|
||||||
return utils.is_list_or_nil(f, "string")
|
|
||||||
end,
|
|
||||||
"list of strings or nil",
|
|
||||||
},
|
|
||||||
mason = { config.mason, { "string", "table" }, true },
|
|
||||||
keymaps = {
|
|
||||||
config.keymaps,
|
|
||||||
function(f)
|
|
||||||
if not f then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
if not utils.is_list(f, "table") then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, key in ipairs(f) do
|
|
||||||
local o, r = pcall(vim.validate, {
|
|
||||||
mode = { key.mode, { "string", "table" } },
|
|
||||||
lhs = { key.lhs, "string" },
|
|
||||||
rhs = { key.rhs, { "string", "function" } },
|
|
||||||
opts = { key.opts, "table", true },
|
|
||||||
})
|
|
||||||
|
|
||||||
if not o then
|
|
||||||
utils.err(("Invalid keymap:\n%s"):format(r))
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
"list of keymaps",
|
|
||||||
},
|
|
||||||
lspconfig = { config.lspconfig, { "table" }, true },
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
if not ok then
|
|
||||||
utils.err(("Invalid config for %s:\n%s"):format(name, resp))
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Called when language server attaches
|
|
||||||
---@param client vim.lsp.Client
|
|
||||||
---@param bufnr integer
|
|
||||||
function M:on_attach(client, bufnr)
|
|
||||||
if self.client and self.client.id ~= client.id then
|
|
||||||
self.client:stop(true)
|
|
||||||
end
|
|
||||||
self.client = client
|
|
||||||
self.attached_buffers = self.attached_buffers or {}
|
|
||||||
table.insert(self.attached_buffers, bufnr)
|
|
||||||
|
|
||||||
keymap:init(self, bufnr)
|
|
||||||
if self.linters then
|
|
||||||
for _, linter in ipairs(self.linters) do
|
|
||||||
local bin = linter.config.cmd[1]
|
|
||||||
if utils.is_executable(bin) then
|
|
||||||
linter:init(bufnr)
|
|
||||||
else
|
|
||||||
utils.warn(
|
|
||||||
("Not adding %s because it is not installed"):format(bin)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 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 })
|
|
||||||
|
|
||||||
---@alias lsp.Client vim.lsp.Client
|
|
||||||
-- require("lsp_compl").attach(client, bufnr, {
|
|
||||||
-- server_side_fuzzy_completion = true,
|
|
||||||
-- })
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Configure the LSP client
|
|
||||||
function M:configure_client()
|
|
||||||
local lspconfig = require("lspconfig")
|
|
||||||
|
|
||||||
local capabilities = vim.lsp.protocol.make_client_capabilities()
|
|
||||||
local cmp_nvim_lsp = utils.try_require("cmp_nvim_lsp")
|
|
||||||
if cmp_nvim_lsp then
|
|
||||||
capabilities = vim.tbl_deep_extend(
|
|
||||||
"force",
|
|
||||||
capabilities,
|
|
||||||
cmp_nvim_lsp.default_capabilities()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- local epo = utils.try_require("epo")
|
|
||||||
-- if epo then
|
|
||||||
-- capabilities = vim.tbl_deep_extend(
|
|
||||||
-- "force",
|
|
||||||
-- capabilities,
|
|
||||||
-- epo.register_cap()
|
|
||||||
-- )
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- local lsp_compl = utils.try_require("lsp_compl")
|
|
||||||
-- if lsp_compl then
|
|
||||||
-- capabilities = vim.tbl_deep_extend("force", capabilities, lsp_compl.capabilities())
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
|
|
||||||
self.config.lspconfig.capabilities = capabilities
|
|
||||||
self.config.lspconfig.on_attach = function(client, bufnr)
|
|
||||||
local ok, ret = pcall(self.on_attach, self, client, bufnr)
|
|
||||||
if not ok then
|
|
||||||
utils.err(
|
|
||||||
("Failed to load on_attach for %s:\n%s"):format(self.name, ret),
|
|
||||||
"lsp.server:configure_client"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.config.settings_file then
|
|
||||||
local file = io.open(self.config.settings_file, "r")
|
|
||||||
if not file then
|
|
||||||
utils.warn(
|
|
||||||
("Failed to open file for reading: %s"):format(
|
|
||||||
self.config.settings_file
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else
|
|
||||||
local json = file:read("*all")
|
|
||||||
file:close()
|
|
||||||
local ok, resp = pcall(
|
|
||||||
vim.json.decode,
|
|
||||||
json,
|
|
||||||
{ luanil = { object = true, array = true } }
|
|
||||||
)
|
|
||||||
if not ok then
|
|
||||||
utils.warn(
|
|
||||||
("Failed to parse json file %s:%s"):format(
|
|
||||||
self.config.settings_file,
|
|
||||||
resp
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else
|
|
||||||
self.config.lspconfig.settings = vim.tbl_deep_extend(
|
|
||||||
"force",
|
|
||||||
self.config.lspconfig.settings or {},
|
|
||||||
resp
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok, ret = pcall(lspconfig[self.name].setup, self.config.lspconfig)
|
|
||||||
if not ok then
|
|
||||||
utils.err(
|
|
||||||
("Failed to setup LSP server %s with lspconfig: %s"):format(
|
|
||||||
self.name,
|
|
||||||
ret
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self.manager = lspconfig[self.name].manager
|
|
||||||
for _, bufnr in ipairs(self:get_ft_buffers()) do
|
|
||||||
self.manager:try_add_wrapper(bufnr)
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.config.linters then
|
|
||||||
self.linters = {}
|
|
||||||
for i, config in ipairs(self.config.linters) do
|
|
||||||
local linter =
|
|
||||||
Linter.new(("%s_linter%d"):format(self.name, i), config)
|
|
||||||
|
|
||||||
if linter then
|
|
||||||
table.insert(self.linters, linter)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function M:get_ft_buffers()
|
|
||||||
local filetypes = self.config.lspconfig.filetypes or {}
|
|
||||||
if not vim.list_contains(filetypes, self.config.lspconfig.filetype) then
|
|
||||||
table.insert(filetypes, self.config.lspconfig.filetype)
|
|
||||||
end
|
|
||||||
if #filetypes == 0 then
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
return vim.tbl_filter(function(bufnr)
|
|
||||||
return vim.list_contains(filetypes, vim.bo[bufnr].filetype)
|
|
||||||
end, vim.api.nvim_list_bufs())
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Check for and return missing dependencies
|
|
||||||
---@return table<string>
|
|
||||||
function M:get_missing_unmanaged_deps()
|
|
||||||
local missing_deps = {}
|
|
||||||
if self.config.dependencies ~= nil then
|
|
||||||
for _, dep in ipairs(self.config.dependencies) do
|
|
||||||
if not utils.is_executable(dep) then
|
|
||||||
table.insert(missing_deps, dep)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return missing_deps
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Install LSP server
|
|
||||||
---@param on_done fun(success: boolean)?
|
|
||||||
function M:install(on_done)
|
|
||||||
--- Handle install result
|
|
||||||
---@param success boolean
|
|
||||||
local function handle_result(success)
|
|
||||||
if not success then
|
|
||||||
self.config.enable = false
|
|
||||||
end
|
|
||||||
if on_done then
|
|
||||||
on_done(success)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self.mason:install_with_dependencies(handle_result)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Setup LSP server
|
|
||||||
function M:setup(on_done)
|
|
||||||
local missing_deps = self:get_missing_unmanaged_deps()
|
|
||||||
|
|
||||||
if #missing_deps > 0 then
|
|
||||||
utils.warn(
|
|
||||||
(
|
|
||||||
"Disabling %s because the following package(s)"
|
|
||||||
.. "are not installed: %s"
|
|
||||||
):format(self.name, table.concat(missing_deps, ", "))
|
|
||||||
)
|
|
||||||
self.config.enable = false
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.mason then
|
|
||||||
self:install(function(success)
|
|
||||||
if success then
|
|
||||||
self:configure_client()
|
|
||||||
end
|
|
||||||
|
|
||||||
if on_done then
|
|
||||||
on_done(success)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
elseif vim.fn.executable(self.config.lspconfig.cmd[1]) == 1 then
|
|
||||||
self:configure_client()
|
|
||||||
else
|
|
||||||
utils.warn(self.name .. " not installed, disabling")
|
|
||||||
self.config.enable = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Load autocmd for setting up LSP server upon entering a buffer of related
|
|
||||||
--- filetype
|
|
||||||
function M:init(on_done)
|
|
||||||
local group = vim.api.nvim_create_augroup("lsp_bootstrap_" .. self.name, {})
|
|
||||||
vim.api.nvim_create_autocmd("FileType", {
|
|
||||||
once = true,
|
|
||||||
pattern = self.config.lspconfig.filetypes or {},
|
|
||||||
callback = function()
|
|
||||||
self:setup(on_done)
|
|
||||||
end,
|
|
||||||
group = group,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function M:deinit()
|
|
||||||
if self.attached_buffers then
|
|
||||||
for _, bufnr in ipairs(self.attached_buffers) do
|
|
||||||
keymap:deinit(bufnr)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.client then
|
|
||||||
self.client:stop(true)
|
|
||||||
self.client = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
vim.api.nvim_clear_autocmds({ group = "lsp_bootstrap_" .. self.name })
|
|
||||||
|
|
||||||
if self.linters then
|
|
||||||
for _, linter in ipairs(self.linters) do
|
|
||||||
linter:deinit()
|
|
||||||
end
|
|
||||||
|
|
||||||
self.linters = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
require("lspconfig.configs")[self.name] = nil
|
|
||||||
require("lspconfig")[self.name] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Create a new instance
|
|
||||||
---@param name string
|
|
||||||
---@param config? ServerConfig
|
|
||||||
---@return Server|nil
|
|
||||||
function M.new(name, config)
|
|
||||||
config = config or {}
|
|
||||||
|
|
||||||
if config.enable == nil then
|
|
||||||
config.enable = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if not M.validate(name, config) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local ok, resp = pcall(require, "lspconfig.configs." .. name)
|
|
||||||
if not ok and config.lspconfig then
|
|
||||||
require("lspconfig.configs")[name] = vim.tbl_deep_extend(
|
|
||||||
"keep",
|
|
||||||
{ default_config = {} },
|
|
||||||
config.lspconfig
|
|
||||||
)
|
|
||||||
elseif ok then
|
|
||||||
config.lspconfig = vim.tbl_deep_extend(
|
|
||||||
"keep",
|
|
||||||
config.lspconfig or {},
|
|
||||||
resp.default_config
|
|
||||||
)
|
|
||||||
else
|
|
||||||
utils.err(
|
|
||||||
("Server with name %s does not exist in lspconfig"):format(name)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local server = { name = name, config = config }
|
|
||||||
|
|
||||||
if server.config.mason then
|
|
||||||
local pkg = MasonPackage.new(server.config.mason)
|
|
||||||
if pkg then
|
|
||||||
server.mason = pkg
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(server, M)
|
|
||||||
end
|
|
||||||
|
|
||||||
return M
|
|
||||||
@@ -38,7 +38,7 @@ return {
|
|||||||
require("luasnip.loaders.from_vscode").lazy_load()
|
require("luasnip.loaders.from_vscode").lazy_load()
|
||||||
end,
|
end,
|
||||||
build = (
|
build = (
|
||||||
require("ow.utils").os_name ~= "Windows_NT"
|
require("ow.util").os_name ~= "Windows_NT"
|
||||||
and "make install_jsregexp"
|
and "make install_jsregexp"
|
||||||
or nil
|
or nil
|
||||||
),
|
),
|
||||||
@@ -55,7 +55,6 @@ return {
|
|||||||
config = function()
|
config = function()
|
||||||
local cmp = require("cmp")
|
local cmp = require("cmp")
|
||||||
local luasnip = require("luasnip")
|
local luasnip = require("luasnip")
|
||||||
local utils = require("ow.utils")
|
|
||||||
local lspkind = require("lspkind")
|
local lspkind = require("lspkind")
|
||||||
|
|
||||||
---@type cmp.ConfigSchema
|
---@type cmp.ConfigSchema
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---@type LazyPluginSpec
|
||||||
|
return {
|
||||||
|
"neovim/nvim-lspconfig",
|
||||||
|
config = require("ow.lsp").setup,
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
local utils = require("ow.utils")
|
local util = require("ow.util")
|
||||||
|
|
||||||
local function override_highlights()
|
local function override_highlights()
|
||||||
-- File Icon
|
-- File Icon
|
||||||
local hl = utils.get_hl_source("NvimTreeFileIcon")
|
local hl = util.get_hl_source("NvimTreeFileIcon")
|
||||||
vim.api.nvim_set_hl(0, "NvimTreeFileIcon", { fg = hl.fg, bg = nil })
|
vim.api.nvim_set_hl(0, "NvimTreeFileIcon", { fg = hl.fg, bg = nil })
|
||||||
|
|
||||||
-- Symlink Icon
|
-- Symlink Icon
|
||||||
hl = utils.get_hl_source("NvimTreeSymlinkIcon")
|
hl = util.get_hl_source("NvimTreeSymlinkIcon")
|
||||||
vim.api.nvim_set_hl(0, "NvimTreeSymlinkIcon", { fg = hl.fg, bg = nil })
|
vim.api.nvim_set_hl(0, "NvimTreeSymlinkIcon", { fg = hl.fg, bg = nil })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -97,34 +97,6 @@ function M.assert_python3_module_installed(mod)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Send a debug notification
|
|
||||||
---@param msg string Message to send
|
|
||||||
---@param title? string Title of notification
|
|
||||||
function M.debug(msg, title)
|
|
||||||
notify(msg, title, vim.log.levels.DEBUG)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Send an info notification
|
|
||||||
---@param msg string Message to send
|
|
||||||
---@param title? string Title of notification
|
|
||||||
function M.info(msg, title)
|
|
||||||
notify(msg, title, vim.log.levels.INFO)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Send a warning notification
|
|
||||||
---@param msg string Message to send
|
|
||||||
---@param title? string Title of notification
|
|
||||||
function M.warn(msg, title)
|
|
||||||
notify(msg, title, vim.log.levels.WARN)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Send an error notification
|
|
||||||
---@param msg string Message to send
|
|
||||||
---@param title? string Title of notification
|
|
||||||
function M.err(msg, title)
|
|
||||||
notify(msg, title, vim.log.levels.ERROR)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Attempts to load a module and logs errors on failure.
|
--- Attempts to load a module and logs errors on failure.
|
||||||
---@param module string The module to attempt to load.
|
---@param module string The module to attempt to load.
|
||||||
---@return any module The loaded module if successful, otherwise nil.
|
---@return any module The loaded module if successful, otherwise nil.
|
||||||
Reference in New Issue
Block a user