nvim/lua/custom/plugins/dap.lua
Jeremie Fraeys 99a6cba26a
refactor: update development tooling
- Refactor dap.lua debugger configuration
- Update neotest.lua test runner setup
- Simplify linting.lua and formatting.lua configs
- Restructure snippets.lua for better organization
2026-03-23 20:33:16 -04:00

300 lines
8 KiB
Lua
Executable file

return {
{
'mfussenegger/nvim-dap',
dependencies = {
'rcarriga/nvim-dap-ui',
'nvim-neotest/nvim-nio',
{ 'theHamsta/nvim-dap-virtual-text', opts = {} },
'jay-babu/mason-nvim-dap.nvim',
},
config = function()
local dap = require('dap')
local dapui = require('dapui')
---@diagnostic disable-next-line: missing-fields
dapui.setup({
enter = false,
layouts = {
{
elements = {
{ id = 'scopes', size = 0.25 },
{ id = 'breakpoints', size = 0.25 },
{ id = 'stacks', size = 0.25 },
{ id = 'watches', size = 0.25 },
},
size = 40,
position = 'left',
},
{
elements = {
{ id = 'repl', size = 0.5 },
{ id = 'console', size = 0.5 },
},
size = 10,
position = 'bottom',
},
},
})
-- open/close UI automatically with session lifecycle
dap.listeners.after.event_initialized['dapui_config'] = function()
dapui.open()
end
dap.listeners.before.event_terminated['dapui_config'] = function()
dapui.close()
end
dap.listeners.before.event_exited['dapui_config'] = function()
dapui.close()
end
-- defer mason disk I/O after first keypress
vim.schedule(function()
require('mason-nvim-dap').setup({
automatic_installation = true,
ensure_installed = { 'codelldb', 'python', 'delve' },
handlers = {},
})
end)
-- VSCode launch.json support
local ok, vscode = pcall(require, 'dap.ext.vscode')
if ok then
vscode.load_launchjs(nil, {
codelldb = { 'c', 'cpp', 'rust', 'zig' },
delve = { 'go' },
python = { 'python' },
})
end
-- language adapters: only setup when filetype is opened AND dap is loaded
local function get_python_path()
local venv = vim.env.VIRTUAL_ENV or vim.env.CONDA_PREFIX
if venv then
local bin = venv .. '/bin/python'
if vim.fn.executable(bin) == 1 then
return bin
end
end
local local_venv = vim.fn.getcwd() .. '/.venv/bin/python'
if vim.fn.executable(local_venv) == 1 then
return local_venv
end
return vim.fn.exepath('python3') ~= '' and vim.fn.exepath('python3')
or vim.fn.exepath('python') ~= '' and vim.fn.exepath('python')
or 'python3'
end
vim.api.nvim_create_autocmd('FileType', {
pattern = 'go',
once = true,
callback = function()
if package.loaded['dap'] then
require('dap-go').setup()
end
end,
})
vim.api.nvim_create_autocmd('FileType', {
pattern = 'python',
once = true,
callback = function()
if package.loaded['dap'] then
require('dap-python').setup(get_python_path())
end
end,
})
-- C/C++/Rust/Zig via codelldb
local codelldb_config = {
{
name = 'Launch',
type = 'codelldb',
request = 'launch',
program = function()
return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file')
end,
cwd = '${workspaceFolder}',
stopOnEntry = false,
},
{
name = 'Launch with ASan',
type = 'codelldb',
request = 'launch',
program = function()
return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file')
end,
cwd = '${workspaceFolder}',
stopOnEntry = false,
env = { ASAN_OPTIONS = 'detect_leaks=1' },
},
}
dap.configurations.c = codelldb_config
dap.configurations.cpp = vim.deepcopy(codelldb_config)
dap.configurations.rust = {
{
name = 'Launch',
type = 'codelldb',
request = 'launch',
program = function()
return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/target/debug/', 'file')
end,
cwd = '${workspaceFolder}',
stopOnEntry = false,
},
}
dap.configurations.zig = {
{
name = 'Launch',
type = 'codelldb',
request = 'launch',
program = function()
return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/zig-out/bin/', 'file')
end,
cwd = '${workspaceFolder}',
stopOnEntry = false,
},
}
-- signs
vim.fn.sign_define('DapBreakpoint', { text = '🔴', texthl = 'DiagnosticError', linehl = '', numhl = '' })
vim.fn.sign_define(
'DapBreakpointCondition',
{ text = '🟡', texthl = 'DiagnosticWarn', linehl = '', numhl = '' }
)
vim.fn.sign_define('DapBreakpointRejected', { text = '', texthl = 'DiagnosticError', linehl = '', numhl = '' })
vim.fn.sign_define('DapStopped', { text = '➡️', texthl = 'DiagnosticInfo', linehl = 'debugPC', numhl = '' })
vim.api.nvim_set_hl(0, 'DapStoppedLine', { default = true, link = 'Visual' })
end,
keys = {
{
'<leader>dc',
function()
require('dap').continue()
end,
desc = 'Debug: Continue',
},
{
'<leader>da',
function()
require('dap').continue({
before = function(c)
local args = vim.split(vim.fn.input('Args: '), ' ')
c.args = args
return c
end,
})
end,
desc = 'Debug: Run with Args',
},
{
'<leader>dC',
function()
require('dap').run_to_cursor()
end,
desc = 'Debug: Run to Cursor',
},
{
'<leader>ds',
function()
require('dap').step_over()
end,
desc = 'Debug: Step Over',
},
{
'<leader>di',
function()
require('dap').step_into()
end,
desc = 'Debug: Step Into',
},
{
'<leader>do',
function()
require('dap').step_out()
end,
desc = 'Debug: Step Out',
},
{
'<leader>dj',
function()
require('dap').down()
end,
desc = 'Debug: Down Frame',
},
{
'<leader>dk',
function()
require('dap').up()
end,
desc = 'Debug: Up Frame',
},
{
'<leader>dg',
function()
require('dap').goto_()
end,
desc = 'Debug: Go to Line',
},
{
'<leader>db',
function()
require('dap').toggle_breakpoint()
end,
desc = 'Debug: Toggle Breakpoint',
},
{
'<leader>dB',
function()
require('dap').set_breakpoint(vim.fn.input('Condition: '))
end,
desc = 'Debug: Conditional Breakpoint',
},
{
'<leader>dl',
function()
require('dap').set_breakpoint(nil, nil, vim.fn.input('Log: '))
end,
desc = 'Debug: Log Breakpoint',
},
{
'<leader>dr',
function()
require('dap').repl.toggle()
end,
desc = 'Debug: Toggle REPL',
},
{
'<leader>dR',
function()
require('dap').run_last()
end,
desc = 'Debug: Run Last',
},
{
'<leader>dt',
function()
require('dap').terminate()
end,
desc = 'Debug: Terminate',
},
{
'<leader>du',
function()
require('dapui').toggle()
end,
desc = 'Debug: Toggle UI',
},
{
'<leader>de',
function()
require('dapui').eval()
end,
desc = 'Debug: Eval',
mode = { 'n', 'v' },
},
},
},
{ 'mfussenegger/nvim-dap-python', lazy = true, config = false },
{ 'leoluz/nvim-dap-go', lazy = true, config = false },
}