fix(gopls): disable semantic tokens and restore mini.sessions

- Disable semantic tokens in gopls to prevent nil index errors
- Replace auto-session with mini.sessions for better reliability
- Move session keymaps to core/keymaps.lua under <leader>m namespace
- Add Go project detection to skip session operations for Go projects
This commit is contained in:
Adam Poniatowski 2025-02-23 19:44:06 +01:00
parent e64044b066
commit 80e90a3b99
3 changed files with 116 additions and 27 deletions

View File

@ -129,12 +129,9 @@ M.dadbod_keymaps = {
-- Session management keymaps (all under <leader>m for Memory)
M.session_keymaps = {
{ mode = 'n', lhs = '<leader>ms', rhs = function() _G.MiniSession.save() end,
opts = { desc = 'Memory: Save session' } },
{ mode = 'n', lhs = '<leader>ml', rhs = function() _G.MiniSession.load() end,
opts = { desc = 'Memory: Load session' } },
{ mode = 'n', lhs = '<leader>md', rhs = function() _G.MiniSession.delete() end,
opts = { desc = 'Memory: Delete session' } },
{ mode = 'n', lhs = '<leader>mw', rhs = function() require('mini.sessions').write() end, opts = { desc = 'Memory: Write session' } },
{ mode = 'n', lhs = '<leader>mr', rhs = function() require('mini.sessions').read() end, opts = { desc = 'Memory: Read session' } },
{ mode = 'n', lhs = '<leader>md', rhs = function() require('mini.sessions').delete() end, opts = { desc = 'Memory: Delete session' } },
}
-- Setup function for dadbod keymaps
@ -294,6 +291,11 @@ local function init_keymaps()
-- Set up session keymaps
M.setup_session_keymaps()
-- Set up session keymaps
for _, mapping in ipairs(M.session_keymaps) do
vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, mapping.opts)
end
-- Set up git signs keymaps
M.setup_gitsigns_keymaps()

View File

@ -137,6 +137,11 @@ return {
local client = vim.lsp.get_client_by_id(args.data.client_id)
if not client then return end
-- Disable semantic tokens for gopls
if client.name == "gopls" then
client.server_capabilities.semanticTokensProvider = nil
end
-- Only set up document formatting for null-ls
if client.name ~= "null-ls" then
client.server_capabilities.documentFormattingProvider = false
@ -188,36 +193,65 @@ return {
ensure_installed = vim.tbl_keys(servers),
}
-- Custom semantic tokens handler for gopls
local semantic_tokens_handler = function(err, result, ctx, config)
local client = vim.lsp.get_client_by_id(ctx.client_id)
if not client then return end
-- Check if client has the required semantic tokens capabilities
local semantic_tokens = client.server_capabilities.semanticTokensProvider
if not semantic_tokens or not semantic_tokens.legend then
-- If no legend is provided, disable semantic tokens for this client
client.server_capabilities.semanticTokensProvider = nil
return
end
-- If we have a valid legend, proceed with default handler
vim.lsp.semantic_tokens.on_full(err, result, ctx, config)
end
mason_lspconfig.setup_handlers {
function(server_name)
local server_config = servers[server_name] or {}
-- For gopls, disable semantic tokens in capabilities
-- For gopls, add debug logging
if server_name == "gopls" then
server_config.capabilities = vim.tbl_deep_extend("force", capabilities, {
textDocument = {
semanticTokens = {
dynamicRegistration = false,
formats = {},
multilineTokenSupport = false,
overlappingTokenSupport = false,
requests = {
full = false,
range = false,
delta = false
},
serverCancelSupport = false,
tokenModifiers = {},
tokenTypes = {}
}
}
})
else
server_config.capabilities = capabilities
-- Create a custom on_attach that disables semantic tokens
local orig_on_attach = server_config.on_attach
server_config.on_attach = function(client, bufnr)
-- Disable semantic tokens for this client
client.server_capabilities.semanticTokensProvider = nil
-- Call original on_attach if it exists
if orig_on_attach then
orig_on_attach(client, bufnr)
end
end
end
server_config.capabilities = capabilities
require('lspconfig')[server_name].setup(server_config)
end,
}
-- Override the semantic tokens handler to be more resilient
vim.lsp.handlers['textDocument/semanticTokens/full'] = function(err, result, ctx, config)
-- If there's an error or no result, just return
if err or not result then return end
local client = vim.lsp.get_client_by_id(ctx.client_id)
if not client then return end
local bufnr = ctx.bufnr
if not bufnr then return end
-- Get the highlighter safely
local highlighter = vim.lsp.semantic_tokens.create_highlighter(bufnr, client)
if not highlighter then return end
-- Process the response safely
pcall(function()
highlighter:process_response(result, client, ctx.request.version)
end)
end
end,
}

53
lua/plugins/session.lua Normal file
View File

@ -0,0 +1,53 @@
return {
'echasnovski/mini.sessions',
version = '*',
event = "VimEnter",
config = function()
require('mini.sessions').setup({
-- Whether to read latest session if Neovim opened without file arguments
autoread = false,
-- Whether to write current session before quitting Neovim
autowrite = true,
-- Directory where global sessions are stored (use `''` to disable)
directory = vim.fn.stdpath('data') .. '/sessions',
-- File for local session (use `''` to disable)
file = '',
-- Whether to force possibly harmful actions (meaning depends on function)
force = { read = false, write = true, delete = false },
-- Hook functions for actions. Default `nil` means 'do nothing'.
hooks = {
-- Before successful action
pre = {
read = function()
-- Skip session operations for Go projects
local current_dir = vim.fn.getcwd()
local has_go_files = vim.fn.glob(current_dir .. "/*.go") ~= "" or
vim.fn.glob(current_dir .. "/go.mod") ~= "" or
vim.fn.glob(current_dir .. "/go.work") ~= ""
if has_go_files then
return false -- Skip for Go projects
end
return true
end,
write = function()
-- Skip session operations for Go projects
local current_dir = vim.fn.getcwd()
local has_go_files = vim.fn.glob(current_dir .. "/*.go") ~= "" or
vim.fn.glob(current_dir .. "/go.mod") ~= "" or
vim.fn.glob(current_dir .. "/go.work") ~= ""
if has_go_files then
return false -- Skip for Go projects
end
return true
end,
},
-- After successful action
post = { read = nil, write = nil, delete = nil },
},
-- Whether to print session path after action
verbose = { read = false, write = true, delete = true },
})
end
}