-- debug.lua -- -- Shows how to use the DAP plugin to debug your code. -- -- Primarily focused on configuring the debugger for Go, but can -- be extended to other languages as well. That's why it's called -- kickstart.nvim and not kitchen-sink.nvim ;) return { -- NOTE: Yes, you can install new plugins here! 'mfussenegger/nvim-dap', -- NOTE: And you can specify dependencies as well dependencies = { -- Creates a beautiful debugger UI 'rcarriga/nvim-dap-ui', -- Required dependency for nvim-dap-ui 'nvim-neotest/nvim-nio', -- Installs the debug adapters for you 'williamboman/mason.nvim', 'jay-babu/mason-nvim-dap.nvim', -- Add your own debuggers here 'leoluz/nvim-dap-go', -- Web { 'microsoft/vscode-js-debug', -- TODO: check wheter vscode-js-debug has some "build dap server script in package.json" build = 'npm i && npx gulp dapDebugServer', }, }, keys = { { -- NOTE: Temporary solution to open chrome - until I'll figure out how to run it automatically 'dd', ':!open -a "Google Chrome" --args --remote-debugging-port=9222', }, -- TODO: change lua formatter to keep such entries in one line { 'dB', function() require('dap').set_breakpoint(vim.fn.input 'Breakpoint condition: ') end, desc = 'Breakpoint Condition', }, { 'db', function() require('dap').toggle_breakpoint() end, desc = 'Toggle Breakpoint', }, { 'dc', function() require('dap').continue() end, desc = 'Run/Continue', }, { 'da', function() require('dap').continue { before = get_args } end, desc = 'Run with Args', }, { 'dC', function() require('dap').run_to_cursor() end, desc = 'Run to Cursor', }, { 'dg', function() require('dap').goto_() end, desc = 'Go to Line (No Execute)', }, { 'di', function() require('dap').step_into() end, desc = 'Step Into', }, { 'dj', function() require('dap').down() end, desc = 'Down', }, { 'dk', function() require('dap').up() end, desc = 'Up', }, { 'dl', function() require('dap').run_last() end, desc = 'Run Last', }, { 'do', function() require('dap').step_out() end, desc = 'Step Out', }, { 'dO', function() require('dap').step_over() end, desc = 'Step Over', }, { 'dP', function() require('dap').pause() end, desc = 'Pause', }, -- Toggle to see last session result. Without this, you can't see session output in case of unhandled exception. { 'dl', function() require('dapui').toggle() end, desc = 'Debug: See last session result.', }, { 'dr', function() require('dap').repl.toggle() end, desc = 'Toggle REPL', }, { 'ds', function() require('dap').session() end, desc = 'Session', }, { 'dt', function() require('dap').terminate() end, desc = 'Terminate', }, { 'dw', function() require('dap.ui.widgets').hover() end, desc = 'Widgets', }, }, config = function() local dap = require 'dap' local dapui = require 'dapui' require('mason-nvim-dap').setup { -- Makes a best effort to setup the various debuggers with -- reasonable debug configurations automatic_installation = true, -- You can provide additional configuration to the handlers, -- see mason-nvim-dap README for more information handlers = {}, -- You'll need to check that you have the required things installed -- online, please don't ask me how to install them :) ensure_installed = { -- Update this to ensure that you have the debuggers for the langs you want 'delve', }, } -- Dap UI setup -- For more information, see |:help nvim-dap-ui| dapui.setup { -- Set icons to characters that are more likely to work in every terminal. -- Feel free to remove or use ones that you like more! :) -- Don't feel like these are good choices. icons = { expanded = '▾', collapsed = '▸', current_frame = '*' }, controls = { icons = { pause = '⏸', play = '▶', step_into = '⏎', step_over = '⏭', step_out = '⏮', step_back = 'b', run_last = '▶▶', terminate = '⏹', disconnect = '⏏', }, }, } -- Change breakpoint icons -- vim.api.nvim_set_hl(0, 'DapBreak', { fg = '#e51400' }) -- vim.api.nvim_set_hl(0, 'DapStop', { fg = '#ffcc00' }) -- local breakpoint_icons = vim.g.have_nerd_font -- and { Breakpoint = '', BreakpointCondition = '', BreakpointRejected = '', LogPoint = '', Stopped = '' } -- or { Breakpoint = '●', BreakpointCondition = '⊜', BreakpointRejected = '⊘', LogPoint = '◆', Stopped = '⭔' } -- for type, icon in pairs(breakpoint_icons) do -- local tp = 'Dap' .. type -- local hl = (type == 'Stopped') and 'DapStop' or 'DapBreak' -- vim.fn.sign_define(tp, { text = icon, texthl = hl, numhl = hl }) -- end dap.listeners.after.event_initialized['dapui_config'] = dapui.open dap.listeners.before.event_terminated['dapui_config'] = dapui.close dap.listeners.before.event_exited['dapui_config'] = dapui.close for _, adapterType in ipairs { 'node', 'chrome', 'msedge' } do local pwaType = 'pwa-' .. adapterType dap.adapters[pwaType] = { type = 'server', host = 'localhost', port = '${port}', executable = { command = 'node', args = { vim.fn.stdpath 'data' .. '/lazy/vscode-js-debug/dist/src/dapDebugServer.js', '${port}', }, }, } -- this allow us to handle launch.json configurations -- which specify type as "node" or "chrome" or "msedge" dap.adapters[adapterType] = function(cb, config) local nativeAdapter = dap.adapters[pwaType] config.type = pwaType if type(nativeAdapter) == 'function' then nativeAdapter(cb, config) else cb(nativeAdapter) end end end local enter_launch_url = function() local co = coroutine.running() return coroutine.create(function() vim.ui.input({ prompt = 'Enter URL: ', default = 'http://localhost:4201' }, function(url) if url == nil or url == '' then return else coroutine.resume(co, url) end end) end) end for _, language in ipairs { 'typescript', 'javascript', 'typescriptreact', 'javascriptreact', 'vue' } do dap.configurations[language] = { -- NOTE: Tested configs -- NOTE: inspired by https://github.com/StevanFreeborn/nvim-config/blob/main/lua/plugins/debugging.lua -- TODO: Figure out why I have two additional configurations when starting debugger: "Launch Chrome Debugger", "Debug App Two" -- now I have to do "open -a "Google Chrome" --args --remote-debugging-port=9222" { -- TODO: Figure out how to launch chrome automatically -- url = enter_launch_url, name = 'Attach to Chrome', type = 'pwa-chrome', request = 'attach', program = '${file}', cwd = vim.fn.getcwd(), sourceMaps = true, protocol = 'inspector', port = 9222, webRoot = '${workspaceFolder}', }, { -- TODO: This config launches chrome, breapoints are working, but it's very slow for some reason type = 'pwa-chrome', request = 'launch', name = 'Launch Chrome (nvim-dap)', url = enter_launch_url, webRoot = '${workspaceFolder}', sourceMaps = true, }, -- NOTE: Untested configs { type = 'pwa-node', request = 'launch', name = 'Launch file using Node.js (nvim-dap)', program = '${file}', cwd = '${workspaceFolder}', }, { type = 'pwa-node', request = 'attach', name = 'Attach to process using Node.js (nvim-dap)', processId = require('dap.utils').pick_process, cwd = '${workspaceFolder}', }, -- requires ts-node to be installed globally or locally { type = 'pwa-node', request = 'launch', name = 'Launch file using Node.js with ts-node/register (nvim-dap)', program = '${file}', cwd = '${workspaceFolder}', runtimeArgs = { '-r', 'ts-node/register' }, }, { type = 'pwa-msedge', request = 'launch', name = 'Launch Edge (nvim-dap)', url = enter_launch_url, webRoot = '${workspaceFolder}', sourceMaps = true, }, } end -- Install golang specific config require('dap-go').setup { delve = { -- On Windows delve must be run attached or it crashes. -- See https://github.com/leoluz/nvim-dap-go/blob/main/README.md#configuring detached = vim.fn.has 'win32' == 0, }, } end, }