142 lines
4.2 KiB
Lua
142 lines
4.2 KiB
Lua
-- Telescope picker for selecting compile_commands.json
|
|
local M = {}
|
|
|
|
local function find_compile_commands()
|
|
local root = vim.fn.getcwd()
|
|
local cmd = string.format('find "%s" -name compile_commands.json -type f 2>/dev/null', root)
|
|
local handle = io.popen(cmd)
|
|
if not handle then
|
|
return {}
|
|
end
|
|
|
|
local result = handle:read('*a')
|
|
handle:close()
|
|
|
|
local files = {}
|
|
for line in result:gmatch('[^\n]+') do
|
|
-- Get relative path for display
|
|
local relative = line:gsub('^' .. vim.pesc(root) .. '/', '')
|
|
table.insert(files, {
|
|
path = line,
|
|
display = relative,
|
|
dir = vim.fn.fnamemodify(line, ':h'),
|
|
relative_dir = vim.fn.fnamemodify(relative, ':h'),
|
|
})
|
|
end
|
|
|
|
return files
|
|
end
|
|
|
|
function M.pick_compile_commands()
|
|
local files = find_compile_commands()
|
|
|
|
if #files == 0 then
|
|
vim.notify('No compile_commands.json files found', vim.log.levels.WARN)
|
|
return
|
|
elseif #files == 1 then
|
|
vim.notify('Using: ' .. files[1].display, vim.log.levels.INFO)
|
|
M.set_compile_commands(files[1])
|
|
return
|
|
end
|
|
|
|
-- Use Telescope's built-in find_files with custom settings
|
|
local builtin = require('telescope.builtin')
|
|
local actions = require('telescope.actions')
|
|
local action_state = require('telescope.actions.state')
|
|
|
|
builtin.find_files({
|
|
prompt_title = 'Select compile_commands.json',
|
|
cwd = vim.fn.getcwd(),
|
|
find_command = { 'find', '.', '-name', 'compile_commands.json', '-type', 'f' },
|
|
attach_mappings = function(prompt_bufnr, map)
|
|
actions.select_default:replace(function()
|
|
actions.close(prompt_bufnr)
|
|
local selection = action_state.get_selected_entry()
|
|
if selection then
|
|
-- Convert the selection to our file_info format
|
|
local path = selection[1]
|
|
local relative = path:gsub('^%./', '')
|
|
local file_info = {
|
|
path = vim.fn.getcwd() .. '/' .. relative,
|
|
display = relative,
|
|
dir = vim.fn.fnamemodify(path, ':h'),
|
|
relative_dir = vim.fn.fnamemodify(relative, ':h'),
|
|
}
|
|
M.set_compile_commands(file_info)
|
|
end
|
|
end)
|
|
return true
|
|
end,
|
|
})
|
|
end
|
|
|
|
function M.set_compile_commands(file_info)
|
|
local clangd_config = string.format([[
|
|
CompileFlags:
|
|
CompilationDatabase: %s
|
|
]], file_info.relative_dir)
|
|
|
|
-- Write .clangd file
|
|
local clangd_file = vim.fn.getcwd() .. '/.clangd'
|
|
local file = io.open(clangd_file, 'w')
|
|
if file then
|
|
file:write(clangd_config)
|
|
file:close()
|
|
vim.notify('Created .clangd pointing to: ' .. file_info.relative_dir, vim.log.levels.INFO)
|
|
|
|
-- Restart LSP if clangd is running
|
|
local clients = vim.lsp.get_clients({ name = 'clangd' })
|
|
if #clients > 0 then
|
|
vim.notify('Restarting clangd...', vim.log.levels.INFO)
|
|
-- Stop and start clangd to pick up new config
|
|
for _, client in ipairs(clients) do
|
|
client.stop()
|
|
end
|
|
vim.defer_fn(function()
|
|
vim.cmd('LspStart clangd')
|
|
vim.notify('Clangd restarted with new configuration', vim.log.levels.INFO)
|
|
end, 100)
|
|
end
|
|
else
|
|
vim.notify('Failed to create .clangd file', vim.log.levels.ERROR)
|
|
end
|
|
end
|
|
|
|
-- Auto-detect multiple compile_commands.json on startup
|
|
function M.auto_detect()
|
|
local files = find_compile_commands()
|
|
|
|
if #files > 1 then
|
|
-- Check if .clangd already exists
|
|
local clangd_file = vim.fn.getcwd() .. '/.clangd'
|
|
if vim.fn.filereadable(clangd_file) == 0 then
|
|
vim.notify(
|
|
string.format('Found %d compile_commands.json files. Use :CompileCommandsPicker to select one.', #files),
|
|
vim.log.levels.INFO
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Setup function to create command
|
|
function M.setup()
|
|
vim.api.nvim_create_user_command('CompileCommandsPicker', function()
|
|
M.pick_compile_commands()
|
|
end, { desc = 'Select compile_commands.json for clangd' })
|
|
|
|
-- Auto-detect on entering a C/C++ file
|
|
vim.api.nvim_create_autocmd('FileType', {
|
|
pattern = { 'c', 'cpp', 'objc', 'objcpp' },
|
|
callback = function()
|
|
-- Only run once per session
|
|
if not vim.g.compile_commands_detected then
|
|
vim.g.compile_commands_detected = true
|
|
vim.defer_fn(function()
|
|
M.auto_detect()
|
|
end, 100)
|
|
end
|
|
end,
|
|
})
|
|
end
|
|
|
|
return M |