From 75add61c7ffeee45ff10f3651edd137e7d3381b7 Mon Sep 17 00:00:00 2001 From: dlond Date: Fri, 30 May 2025 02:57:52 +1200 Subject: [PATCH] simplified clangd setup --- lua/custom/plugins/lsp/clangd.lua | 152 +++++++++++++++--------------- 1 file changed, 75 insertions(+), 77 deletions(-) diff --git a/lua/custom/plugins/lsp/clangd.lua b/lua/custom/plugins/lsp/clangd.lua index ed1e90d9..2804c304 100644 --- a/lua/custom/plugins/lsp/clangd.lua +++ b/lua/custom/plugins/lsp/clangd.lua @@ -1,19 +1,14 @@ local M = {} - M.clang_filetypes = { 'c', 'cpp', 'objc', 'objcpp', 'cuda' } local lspconfig = require 'lspconfig' -local watcher local function find_compile_commands() - local lines = vim.fn.systemlist { 'fd', '-u', '-t', 'f', 'compile_commands.json' } - if vim.tbl_isempty(lines) then - return nil - end - table.sort(lines, function(a, b) + local results = vim.fn.systemlist { 'fd', '-u', '-t', 'f', 'compile_commands.json' } + table.sort(results, function(a, b) return a:match 'debug' and not b:match 'debug' end) - return vim.fn.fnamemodify(lines[1], ':h') + return results[1] and vim.fn.fnamemodify(results[1], ':h') or nil end function M.stop_clangd() @@ -25,31 +20,39 @@ function M.stop_clangd() end end -function M.setup_clangd(commands_dir) - vim.notify('[clangd] Setting up with: ' .. commands_dir) +function M.start_clangd(commands_dir) M.stop_clangd() + local cmd = { + 'clangd', + '--background-index', + '--clang-tidy', + '--header-insertion=never', + '--query-driver=' .. vim.fn.exepath 'clang++', + '--resource-dir=' .. vim.fn.systemlist({ 'clang++', '--print-resource-dir' })[1], + } + if commands_dir then + table.insert(cmd, '--compile_commands-dir=' .. commands_dir) + end + lspconfig.clangd.setup { - cmd = { - 'clangd', - '--background-index', - '--clang-tidy', - '--header-insertion=never', - '--query-driver=' .. vim.fn.exepath 'clang++', - '--resource-dir=' .. vim.fn.systemlist({ 'clang++', '--print-resource-dir' })[1], - '--compile-commands-dir=' .. (commands_dir or '.'), - }, + cmd = cmd, root_dir = lspconfig.util.root_pattern '.git', - single_file_support = true, + -- single_file_support = true, capabilities = require('blink.cmp').get_lsp_capabilities(), } - -- for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do - -- local ft = vim.api.nvim_get_option_value('filetype', { buf = bufnr }) - -- if vim.tbl_contains(M.clang_filetypes, ft) then - -- vim.lsp.buf_attach_client(bufnr, vim.lsp.get_clients({ name = 'clangd' })[1].id) - -- end - -- end + vim.defer_fn(function() + for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do + local ft = vim.api.nvim_get_option_value('filetype', { buf = bufnr }) + if vim.tbl_contains(M.clang_filetypes, ft) then + local client = vim.lsp.get_clients({ name = 'clangd' })[1] + if client then + vim.lsp.buf_attach_client(bufnr, client.id) + end + end + end + end, 100) end function M.pick_commands_dir() @@ -58,16 +61,16 @@ function M.pick_commands_dir() local conf = require('telescope.config').values pickers .new({}, { - prompt_title = 'Choose compile_commands.json location', + prompt_title = 'Pick compile_commands.json dir', finder = finders.new_oneshot_job { 'fd', '-u', 'compile_commands.json', '-x', 'dirname', '{}' }, sorter = conf.generic_sorter {}, attach_mappings = function(_, map) map('i', '', function(prompt_bufnr) local entry = require('telescope.actions.state').get_selected_entry() - local commands_dir = entry[1] + local dir = entry[1] require('telescope.actions').close(prompt_bufnr) - if commands_dir ~= '' then - M.setup_clangd(commands_dir) + if dir then + M.start_clangd(dir) end end) return true @@ -76,58 +79,53 @@ function M.pick_commands_dir() :find() end -function M.watch_compile_commands() - vim.notify('clangd: Starting watcher for compile_commands.json', vim.log.levels.INFO) - local uv = vim.uv or vim.loop - local check_interval = 1000 -- ms - - local function try_attach() - local dir = find_compile_commands() - if dir then - vim.notify('[clangd] Found compile_commands at: ' .. dir) - M.setup_clangd(dir) - return true - end - return false - end - - local timer = uv.new_timer() - timer:start(0, check_interval, function() - if try_attach() then - timer:stop() - timer:close() - end - end) - - local fs_watcher = uv.new_fs_event() - fs_watcher:start(vim.fn.getcwd(), { recursive = true }, function(_, fname, status) - if fname and fname:match 'compile_commands%.json$' and status.change then - fs_watcher:stop() - vim.schedule(function() - vim.notify '[clangd] Detected compile_commands.json change, reloading ...' - M.setup_clangd(vim.fn.fnamemodify(fname, ':h')) - end) - end - end) -end +-- function M.watch_compile_commands() +-- vim.notify('clangd: Starting watcher for compile_commands.json', vim.log.levels.INFO) +-- local uv = vim.uv or vim.loop +-- local check_interval = 1000 -- ms +-- +-- local function try_attach() +-- local dir = find_compile_commands() +-- if dir then +-- vim.notify('[clangd] Found compile_commands at: ' .. dir) +-- M.setup_clangd(dir) +-- return true +-- end +-- return false +-- end +-- +-- local timer = uv.new_timer() +-- timer:start(0, check_interval, function() +-- if try_attach() then +-- timer:stop() +-- timer:close() +-- end +-- end) +-- +-- local fs_watcher = uv.new_fs_event() +-- fs_watcher:start(vim.fn.getcwd(), { recursive = true }, function(_, fname, status) +-- if fname and fname:match 'compile_commands%.json$' and status.change then +-- fs_watcher:stop() +-- vim.schedule(function() +-- vim.notify '[clangd] Detected compile_commands.json change, reloading ...' +-- M.setup_clangd(vim.fn.fnamemodify(fname, ':h')) +-- end) +-- end +-- end) +-- end return { 'neovim/nvim-lspconfig', ft = M.clang_filetypes, config = function() - vim.api.nvim_create_autocmd('FileType', { - pattern = M.clang_filetypes, - callback = function() - local dir = find_compile_commands() - if dir then - vim.notify('[clangd] Found compile_commands at: ' .. dir) - M.setup_clangd(dir) - else - vim.notify '[clangd] No compile_commands found, watching ...' - M.watch_compile_commands() - end - end, - }) + local dir = find_compile_commands() + if dir then + vim.notify('[clangd] Starting with compile_commands from: ' .. dir) + M.start_clangd(dir) + else + vim.notify '[clangd] No compile_commands found. Using fallback config.\nUse cc to manually set location.' + M.start_clangd(nil) + end vim.keymap.set('n', 'cc', M.pick_commands_dir, { desc = 'Pick location of compile_commands.json for clangd' }) end,