updated lsp to default to mason
This commit is contained in:
parent
4564d7093e
commit
80b5d665fe
121
init.lua
121
init.lua
|
|
@ -1,92 +1,109 @@
|
|||
-- ~/.config/nvim/init.lua
|
||||
require 'core.options' -- Load general options
|
||||
require 'core.keymaps' -- Load general keymaps
|
||||
require 'core.snippets' -- Custom code snippets
|
||||
|
||||
-- Install package manager (lazy.nvim)
|
||||
local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'
|
||||
-- Install package manager
|
||||
local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim'
|
||||
if not vim.loop.fs_stat(lazypath) then
|
||||
vim.fn.system({
|
||||
'git', 'clone', '--filter=blob:none',
|
||||
vim.fn.system {
|
||||
'git',
|
||||
'clone',
|
||||
'--filter=blob:none',
|
||||
'https://github.com/folke/lazy.nvim.git',
|
||||
'--branch=stable', lazypath,
|
||||
})
|
||||
'--branch=stable', -- latest stable release
|
||||
lazypath,
|
||||
}
|
||||
end
|
||||
vim.opt.rtp:prepend(lazypath)
|
||||
|
||||
-- Filetypes
|
||||
vim.filetype.add({
|
||||
extension = { templ = 'templ' },
|
||||
extension = {
|
||||
templ = "templ",
|
||||
}
|
||||
})
|
||||
|
||||
-- Theme selection (robust against unknown NVIM_THEME)
|
||||
-- Import color theme based on environment variable NVIM_THEME
|
||||
local default_color_scheme = 'quantum'
|
||||
local env_var_nvim_theme = os.getenv('NVIM_THEME') or default_color_scheme
|
||||
local env_var_nvim_theme = os.getenv 'NVIM_THEME' or default_color_scheme
|
||||
|
||||
-- Define a table of theme modules
|
||||
local themes = {
|
||||
quantum = 'plugins.themes.quantum',
|
||||
nord = 'plugins.themes.nord',
|
||||
nord = 'plugins.themes.nord',
|
||||
onedark = 'plugins.themes.onedark',
|
||||
}
|
||||
local theme_module = themes[env_var_nvim_theme] or themes[default_color_scheme]
|
||||
|
||||
-- Plugins
|
||||
-- Setup plugins
|
||||
require('lazy').setup({
|
||||
require(theme_module),
|
||||
require(themes[env_var_nvim_theme]),
|
||||
require 'core.ui',
|
||||
|
||||
-- Load mason early so tools are ready for LSP configs
|
||||
require 'plugins.mason',
|
||||
|
||||
-- Core dev UX
|
||||
require 'plugins.treesitter',
|
||||
require 'plugins.telescope',
|
||||
require 'plugins.lualine',
|
||||
require 'plugins.aerial',
|
||||
require 'plugins.autoformat',
|
||||
require 'plugins.flash',
|
||||
require 'plugins.autocompletion',
|
||||
require 'plugins.bufferline',
|
||||
require 'plugins.comment',
|
||||
require 'plugins.conform',
|
||||
require 'plugins.database',
|
||||
require 'plugins.debug',
|
||||
require 'plugins.gitsigns',
|
||||
require 'plugins.harpoon',
|
||||
require 'plugins.lazygit',
|
||||
require 'plugins.lsp',
|
||||
require 'plugins.lualine',
|
||||
require 'plugins.none-ls',
|
||||
require 'plugins.indent-blankline',
|
||||
require 'plugins.neo-tree',
|
||||
require 'plugins.misc',
|
||||
require 'plugins.mason',
|
||||
require 'plugins.snack',
|
||||
require 'plugins.telescope',
|
||||
require 'plugins.toggleterm',
|
||||
require 'plugins.treesitter',
|
||||
require 'plugins.vim-tmux-navigator',
|
||||
require 'plugins.zellij',
|
||||
require 'plugins.flash',
|
||||
require 'plugins.comment',
|
||||
require 'plugins.harpoon',
|
||||
require 'plugins.gitsigns',
|
||||
require 'plugins.lazygit',
|
||||
require 'plugins.aerial',
|
||||
require 'plugins.misc',
|
||||
|
||||
-- LSP & companions
|
||||
require 'plugins.autocompletion',
|
||||
require 'plugins.lsp',
|
||||
require 'plugins.none-ls', -- none-ls/null-ls sources & setup
|
||||
require 'plugins.autoformat', -- your autoformat-on-save/idle logic
|
||||
|
||||
-- Optional: pick one formatter stack. If you keep Conform,
|
||||
-- ensure it doesn't also format Go on save to avoid double-format.
|
||||
require 'plugins.conform',
|
||||
|
||||
-- Debugging / DB (as you had)
|
||||
require 'plugins.debug',
|
||||
require 'plugins.database',
|
||||
}, {
|
||||
ui = {
|
||||
-- If you have a Nerd Font, set icons to an empty table which will use the
|
||||
-- default lazy.nvim defined Nerd Font icons otherwise define a unicode icons table
|
||||
icons = vim.g.have_nerd_font and {} or {
|
||||
cmd = '⌘', config = '🛠', event = '📅', ft = '📂', init = '⚙',
|
||||
keys = '🗝', plugin = '🔌', runtime = '💻', require = '🌙',
|
||||
source = '📄', start = '🚀', task = '📌', lazy = '💤 ',
|
||||
cmd = '⌘',
|
||||
config = '🛠',
|
||||
event = '📅',
|
||||
ft = '📂',
|
||||
init = '⚙',
|
||||
keys = '🗝',
|
||||
plugin = '🔌',
|
||||
runtime = '💻',
|
||||
require = '🌙',
|
||||
source = '📄',
|
||||
start = '🚀',
|
||||
task = '📌',
|
||||
lazy = '💤 ',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
-- (Optional) tiny helper if you ever want to source a session file
|
||||
-- Function to check if a file exists
|
||||
local function file_exists(file)
|
||||
local f = io.open(file, 'r')
|
||||
if f then f:close(); return true end
|
||||
return false
|
||||
if f then
|
||||
f:close()
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- local session_file = '.session.vim'
|
||||
-- if file_exists(session_file) then vim.cmd('source ' .. session_file) end
|
||||
-- Path to the session file
|
||||
local session_file = '.session.vim'
|
||||
|
||||
-- Check if the session file exists in the current directory
|
||||
-- if file_exists(session_file) then
|
||||
-- -- Source the session file
|
||||
-- vim.cmd('source ' .. session_file)
|
||||
-- end
|
||||
|
||||
-- The line beneath this is called `modeline`. See `:help modeline`
|
||||
-- vim: ts=2 sts=2 sw=2 et
|
||||
|
||||
|
|
|
|||
|
|
@ -2,162 +2,75 @@
|
|||
return {
|
||||
{
|
||||
"neovim/nvim-lspconfig",
|
||||
lazy = false,
|
||||
config = function()
|
||||
local lspconfig = require("lspconfig")
|
||||
local util = require("lspconfig.util")
|
||||
local configs = require("lspconfig.configs")
|
||||
|
||||
-- Recognize .templ files
|
||||
vim.filetype.add({ extension = { templ = "templ" } })
|
||||
|
||||
-- ==============================
|
||||
-- gopls
|
||||
-- ==============================
|
||||
lspconfig.gopls.setup({
|
||||
root_dir = function(fname)
|
||||
return util.root_pattern("go.work", "go.mod", ".git")(fname)
|
||||
or util.path.dirname(fname)
|
||||
end,
|
||||
handlers = {
|
||||
["textDocument/signatureHelp"] = function(err, result, ctx, config)
|
||||
if err and err.message and err.message:find("cannot get type") then
|
||||
return
|
||||
end
|
||||
return vim.lsp.handlers["textDocument/signatureHelp"](err, result, ctx, config)
|
||||
end,
|
||||
},
|
||||
settings = {
|
||||
gopls = {
|
||||
gofumpt = true,
|
||||
codelenses = {
|
||||
gc_details = false,
|
||||
generate = true,
|
||||
regenerate_cgo = true,
|
||||
run_govulncheck = true,
|
||||
test = true,
|
||||
tidy = true,
|
||||
upgrade_dependency = true,
|
||||
vendor = true,
|
||||
},
|
||||
hints = {
|
||||
assignVariableTypes = true,
|
||||
compositeLiteralFields = true,
|
||||
compositeLiteralTypes = true,
|
||||
constantValues = true,
|
||||
functionTypeParameters = true,
|
||||
parameterNames = true,
|
||||
rangeVariableTypes = true,
|
||||
},
|
||||
analyses = {
|
||||
fieldalignment = true,
|
||||
nilness = true,
|
||||
unusedparams = true,
|
||||
unusedwrite = true,
|
||||
useany = true,
|
||||
},
|
||||
usePlaceholders = true,
|
||||
completeUnimported = true,
|
||||
staticcheck = true,
|
||||
directoryFilters = {
|
||||
"-.git","-.vscode","-.idea","-.vscode-test","-node_modules",
|
||||
"-dist","-build","-out","-coverage","-tmp","-.cache",
|
||||
},
|
||||
semanticTokens = true,
|
||||
memoryMode = "DegradeClosed",
|
||||
symbolMatcher = "FastFuzzy",
|
||||
["ui.completion.experimentalPostfixCompletions"] = false,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
-- ==============================
|
||||
-- TypeScript / JavaScript (ts_ls OR tsserver fallback)
|
||||
-- ==============================
|
||||
local ts_server = lspconfig.ts_ls or lspconfig.tsserver
|
||||
if ts_server then
|
||||
ts_server.setup({})
|
||||
end
|
||||
|
||||
-- ==============================
|
||||
-- Astro (guard if missing)
|
||||
-- ==============================
|
||||
if lspconfig.astro then
|
||||
local function get_typescript_lib()
|
||||
local mason_ts = vim.fs.normalize(
|
||||
"~/.local/share/nvim/mason/packages/typescript-language-server/node_modules/typescript/lib"
|
||||
)
|
||||
if vim.fn.isdirectory(mason_ts) == 1 then return mason_ts end
|
||||
|
||||
local global_ts = (vim.fn.system("npm root -g"):gsub("\n", "")) .. "/typescript/lib"
|
||||
if vim.fn.isdirectory(global_ts) == 1 then return global_ts end
|
||||
|
||||
return vim.fs.normalize(
|
||||
"~/.local/share/nvim/mason/packages/astro-language-server/node_modules/typescript/lib"
|
||||
)
|
||||
end
|
||||
|
||||
lspconfig.astro.setup({
|
||||
init_options = { typescript = { tsdk = get_typescript_lib() } },
|
||||
})
|
||||
end
|
||||
|
||||
-- ==============================
|
||||
-- templ (register config if missing)
|
||||
-- ==============================
|
||||
if not configs.templ then
|
||||
configs.templ = {
|
||||
default_config = {
|
||||
cmd = { "templ", "lsp" },
|
||||
filetypes = { "templ" },
|
||||
root_dir = util.root_pattern("go.mod", ".git"),
|
||||
single_file_support = true,
|
||||
},
|
||||
}
|
||||
end
|
||||
lspconfig.templ.setup({})
|
||||
|
||||
-- ==============================
|
||||
-- Utilities
|
||||
-- ==============================
|
||||
---------------------------------------------------------------------------
|
||||
-- LSP client utilities
|
||||
---------------------------------------------------------------------------
|
||||
vim.api.nvim_create_user_command("LspClients", function()
|
||||
-- new API: vim.lsp.get_clients
|
||||
local clients = vim.lsp.get_clients()
|
||||
local counts = {}
|
||||
for _, c in ipairs(clients) do
|
||||
counts[c.name] = (counts[c.name] or 0) + 1
|
||||
local client_counts = {}
|
||||
|
||||
for _, client in ipairs(clients) do
|
||||
client_counts[client.name] = (client_counts[client.name] or 0) + 1
|
||||
end
|
||||
|
||||
print("=== Active LSP Clients ===")
|
||||
for name, n in pairs(counts) do
|
||||
local dup = n > 1 and " ⚠️ DUPLICATE" or " ✅"
|
||||
print(string.format("%s: %d client(s)%s", name, n, dup))
|
||||
for name, count in pairs(client_counts) do
|
||||
local status = count > 1 and " ⚠️ DUPLICATE" or " ✅"
|
||||
print(string.format("%s: %d client(s)%s", name, count, status))
|
||||
end
|
||||
if next(counts) == nil then print("No active LSP clients") end
|
||||
end, {})
|
||||
|
||||
if next(client_counts) == nil then
|
||||
print("No active LSP clients")
|
||||
end
|
||||
end, { desc = "Show active LSP clients and detect duplicates" })
|
||||
|
||||
vim.api.nvim_create_user_command("LspKillDuplicates", function()
|
||||
-- only worry about duplicate gopls, since that’s your main concern
|
||||
local gopls_clients = vim.lsp.get_clients({ name = "gopls" })
|
||||
if #gopls_clients <= 1 then
|
||||
print("No duplicate gopls clients found")
|
||||
return
|
||||
end
|
||||
local keep, kill = nil, {}
|
||||
for _, c in ipairs(gopls_clients) do
|
||||
local cnt = 0
|
||||
if c.config.settings and c.config.settings.gopls then
|
||||
for _ in pairs(c.config.settings.gopls) do cnt = cnt + 1 end
|
||||
end
|
||||
if cnt > 0 and not keep then keep = c else table.insert(kill, c) end
|
||||
end
|
||||
for _, c in ipairs(kill) do
|
||||
print(("Killing duplicate gopls client (id: %d)"):format(c.id))
|
||||
c.stop(true)
|
||||
end
|
||||
if keep then print(("Kept gopls client (id: %d) with settings"):format(keep.id)) end
|
||||
end, {})
|
||||
|
||||
local client_to_keep = nil
|
||||
local clients_to_kill = {}
|
||||
|
||||
for _, client in ipairs(gopls_clients) do
|
||||
local settings_count = 0
|
||||
if client.config.settings and client.config.settings.gopls then
|
||||
for _ in pairs(client.config.settings.gopls) do
|
||||
settings_count = settings_count + 1
|
||||
end
|
||||
end
|
||||
|
||||
if settings_count > 0 and not client_to_keep then
|
||||
client_to_keep = client
|
||||
else
|
||||
table.insert(clients_to_kill, client)
|
||||
end
|
||||
end
|
||||
|
||||
for _, client in ipairs(clients_to_kill) do
|
||||
print(string.format("Killing duplicate gopls client (id: %d)", client.id))
|
||||
client.stop(true)
|
||||
end
|
||||
|
||||
if client_to_keep then
|
||||
print(string.format("Kept gopls client (id: %d) with settings", client_to_keep.id))
|
||||
end
|
||||
end, { desc = "Kill duplicate gopls clients" })
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- Hover safety + keymaps
|
||||
---------------------------------------------------------------------------
|
||||
local function has_hover(bufnr)
|
||||
for _, c in pairs(vim.lsp.get_active_clients({ bufnr = bufnr })) do
|
||||
if c.server_capabilities and c.server_capabilities.hoverProvider then return true end
|
||||
local clients = vim.lsp.get_clients({ bufnr = bufnr })
|
||||
for _, c in pairs(clients) do
|
||||
if c.server_capabilities and c.server_capabilities.hoverProvider then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
|
@ -172,11 +85,16 @@ return {
|
|||
vim.keymap.set(mode, lhs, rhs, { buffer = bufnr, desc = desc })
|
||||
end
|
||||
|
||||
-- K = hover (safe)
|
||||
buf_map("n", "K", function()
|
||||
if not has_hover(bufnr) then return end
|
||||
if not has_hover(bufnr) then
|
||||
return
|
||||
end
|
||||
local ok, saga_hover = pcall(require, "lspsaga.hover")
|
||||
if ok and saga_hover and saga_hover.render_hover_doc then
|
||||
pcall(function() saga_hover:render_hover_doc() end)
|
||||
pcall(function()
|
||||
saga_hover:render_hover_doc()
|
||||
end)
|
||||
else
|
||||
pcall(vim.lsp.buf.hover)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,33 +5,39 @@ return {
|
|||
dependencies = {
|
||||
"williamboman/mason.nvim",
|
||||
"jay-babu/mason-null-ls.nvim",
|
||||
"nvimtools/none-ls-extras.nvim", -- optional
|
||||
"nvimtools/none-ls-extras.nvim", -- required for eslint_d now
|
||||
},
|
||||
config = function()
|
||||
local null_ls = require("null-ls")
|
||||
|
||||
-- eslint_d now comes from none-ls-extras, NOT null_ls.builtins
|
||||
local eslint_d = require("none-ls.diagnostics.eslint_d")
|
||||
|
||||
null_ls.setup({
|
||||
sources = {
|
||||
-- Go
|
||||
null_ls.builtins.formatting.gofumpt,
|
||||
null_ls.builtins.formatting.golines, -- optional
|
||||
null_ls.builtins.diagnostics.golangci_lint, -- if installed
|
||||
null_ls.builtins.formatting.golines, -- optional
|
||||
null_ls.builtins.diagnostics.golangci_lint, -- if installed
|
||||
|
||||
-- Web (keep only what you use)
|
||||
-- Web
|
||||
null_ls.builtins.formatting.prettierd,
|
||||
null_ls.builtins.diagnostics.eslint_d,
|
||||
eslint_d,
|
||||
},
|
||||
})
|
||||
|
||||
require("mason-null-ls").setup({
|
||||
ensure_installed = { "gofumpt", "golines", "golangci-lint", "prettierd", "eslint_d" },
|
||||
automatic_installation = true,
|
||||
-- leaving automatic_setup at default (false) so it doesn't double-register sources
|
||||
})
|
||||
|
||||
-- (optional) format on save for Go
|
||||
vim.api.nvim_create_autocmd("BufWritePre", {
|
||||
pattern = "*.go",
|
||||
callback = function() vim.lsp.buf.format({ async = false }) end,
|
||||
callback = function()
|
||||
vim.lsp.buf.format({ async = false })
|
||||
end,
|
||||
})
|
||||
end,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue