From 86735b11e02593ace8dec10284d35cc290ab52b5 Mon Sep 17 00:00:00 2001 From: andresgutgon Date: Sat, 24 Jun 2023 17:50:14 +0200 Subject: [PATCH] Introduce nvim-dap (Debugger Adapter Protocol) to my NVim I want to be able to debug Node apps (Specially NextJS) app on backend side. nvim-dap use DAP protocol from Microsoft which is the one used by VSCode on their debugging experience. This is the same in Nvim. To be honest this has been fucking painful for several reasons. 1. First Next.js latest version has fucked their debugging experience. So I had to simplify the problem and first understand how node `--inspect` flag works on a simple Node server. Then I look into existing issues on Next.js and I discoverd that their debugging experience is broken in latest version. A [fix is comming in this PR](https://github.com/vercel/next.js/pull/51467) 2. Second. After setting the `nvim-dap` plugin with the VSCode / JS debugging experience I spent a shameful amount of time hitting `node-terminal` debug mode when in reality was `pwa-node`. Yes, `pwa` is ultra weird and that took me time to figure out. [Issue here about it](https://github.com/microsoft/vscode/issues/151910) FUCK! This was hard :joy: --- nvim/init.lua | 1 + nvim/lua/user/dap/dap_ui.lua | 18 +++++ nvim/lua/user/dap/init.lua | 8 +++ nvim/lua/user/dap/keymaps.lua | 78 ++++++++++++++++++++++ nvim/lua/user/dap/languages/javascript.lua | 38 +++++++++++ nvim/lua/user/dap/line_signs.lua | 56 ++++++++++++++++ nvim/lua/user/dap/telescope.lua | 7 ++ nvim/lua/user/plugins.lua | 17 +++++ 8 files changed, 223 insertions(+) create mode 100644 nvim/lua/user/dap/dap_ui.lua create mode 100644 nvim/lua/user/dap/init.lua create mode 100644 nvim/lua/user/dap/keymaps.lua create mode 100644 nvim/lua/user/dap/languages/javascript.lua create mode 100644 nvim/lua/user/dap/line_signs.lua create mode 100644 nvim/lua/user/dap/telescope.lua diff --git a/nvim/init.lua b/nvim/init.lua index 3a812ea..3882c33 100644 --- a/nvim/init.lua +++ b/nvim/init.lua @@ -16,3 +16,4 @@ require "user.lualine" require "user.trouble" require "user.prettier" require "user.spectre" +require "user.dap" diff --git a/nvim/lua/user/dap/dap_ui.lua b/nvim/lua/user/dap/dap_ui.lua new file mode 100644 index 0000000..a1d2777 --- /dev/null +++ b/nvim/lua/user/dap/dap_ui.lua @@ -0,0 +1,18 @@ +local ok_dap, dap = pcall(require, "dap") +local ok_dapui, dapui = pcall(require, "dapui") + +if not (ok_dap and ok_dapui) then + return +end + +dapui.setup() + +dap.listeners.after.event_initialized["dapui_config"] = function(session, body) + 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 diff --git a/nvim/lua/user/dap/init.lua b/nvim/lua/user/dap/init.lua new file mode 100644 index 0000000..b3920ca --- /dev/null +++ b/nvim/lua/user/dap/init.lua @@ -0,0 +1,8 @@ +-- DAP components +require("user.dap.telescope") +require("user.dap.keymaps") +require("user.dap.line_signs") +require("user.dap.dap_ui") + +-- DAP language debuggers +require("user.dap.languages.javascript") diff --git a/nvim/lua/user/dap/keymaps.lua b/nvim/lua/user/dap/keymaps.lua new file mode 100644 index 0000000..2b43e2e --- /dev/null +++ b/nvim/lua/user/dap/keymaps.lua @@ -0,0 +1,78 @@ +local keymap = vim.api.nvim_set_keymap +local opts = { noremap = true, silent = true } + +-- This list all possible ways of debugging +-- If the app have a `./.vscode/launch.json` file it will +-- appear here +keymap("n", "dl", "Telescope dap configurations", opts) + +-- Continue. This launch the debugger +keymap( + "n", + "dr", + ":lua require(\"dap\").repl.open()", + opts +) + +-- Set breakboint +keymap( + "n", + "di", + ":lua require(\"dap\").toggle_breakpoint()", + opts +) + +-- Continue. This launch the debugger +keymap( + "n", + "dc", + ":lua require(\"dap\").continue()", + opts +) + +-- Next line +keymap( + "n", + "dn", + ":lua require(\"dap\").step_over()", + opts +) + +-- Prev line +keymap( + "n", + "dN", + ":lua require(\"dap\").step_into()", + opts +) + +-- Go out of method +keymap( + "n", + "do", + ":lua require(\"dap\").step_out()", + opts +) + +keymap( + "n", + "dl", + ":lua require(\"dap\").run_to_cursor()", + opts +) + +-- Disconnect. End debugging session +keymap( + "n", + "dS", + ":lua require(\"dap\").disconnect()", + opts +) + +-- Dap UI. Toggle +keymap( + "n", + "dww", + ":lua require(\"dapui\").toggle()", + opts +) diff --git a/nvim/lua/user/dap/languages/javascript.lua b/nvim/lua/user/dap/languages/javascript.lua new file mode 100644 index 0000000..9c4f232 --- /dev/null +++ b/nvim/lua/user/dap/languages/javascript.lua @@ -0,0 +1,38 @@ +local ok_dap, dap = pcall(require, "dap") +local ok_dap_vscode, dap_vscode = pcall(require, "dap-vscode-js") +local ok_dap_launch_vscode, dap_launch_vscode = pcall(require, "dap.ext.vscode") + +if not (ok_dap and ok_dap_vscode) then + return +end + +local home = os.getenv('HOME') +local node_path = home .. '/.nvm/versions/node/v19.7.0/bin/node' +local debugger_path = home .. "/.local/share/nvim/site/pack/packer/opt/vscode-js-debug" + +dap_vscode.setup({ + node_path = node_path, + debugger_path = debugger_path, + log_file_level = vim.log.levels.DEBUG, + log_console_level = vim.log.levels.ERROR, + log_file_path = "/tmp/dap_vscode_js.log", + adapters = { + "pwa-node", + "pwa-chrome", + "pwa-msedge", + "node-terminal", + "pwa-extensionHost" + } +}) + + +local languages = { "typescript", "javascript", "typescriptreact" } +for _, language in ipairs(languages) do + dap.configurations[language] = { {} } +end + +-- ## DAP `launch.json` +dap_launch_vscode.load_launchjs(nil, { + ["pwa-node"] = languages, + ["node-terminal"] = languages +}) diff --git a/nvim/lua/user/dap/line_signs.lua b/nvim/lua/user/dap/line_signs.lua new file mode 100644 index 0000000..cbb82fb --- /dev/null +++ b/nvim/lua/user/dap/line_signs.lua @@ -0,0 +1,56 @@ +-- VSCode theme visual line selection color +local theme_line_color = '#264F78' +vim.api.nvim_set_hl(0, 'DapLine', { ctermbg = 0, fg = nil, bg = theme_line_color }) +vim.api.nvim_set_hl(0, 'DapBreakpoint', { ctermbg = 0, fg = '#993939', bg = theme_line_color }) +vim.api.nvim_set_hl(0, 'DapLogPoint', { ctermbg = 0, fg = '#61afef', bg = theme_line_color }) +vim.api.nvim_set_hl(0, 'DapStopped', { ctermbg = 0, fg = '#98c379', bg = theme_line_color }) + + +-- # Line Signs +vim.fn.sign_define( + 'DapBreakpoint', + { + text = ' ', + texthl = 'DapBreakpoint', + linehl = 'DapLine', + numhl = 'DapLine' + } +) +vim.fn.sign_define( + 'DapBreakpointCondition', + { + text = ' ﳁ', + texthl = 'DapBreakpoint', + linehl = 'DapLine', + numhl = 'DapLine' + } +) + +vim.fn.sign_define( + 'DapBreakpointRejected', + { + text = ' ', + texthl = 'DapBreakpoint', + linehl = 'DapLine', + numhl = 'DapLine' + } +) + +vim.fn.sign_define( + 'DapLogPoint', + { + text = ' ', + texthl = 'DapLogPoint', + linehl = 'DapLine', + numhl = 'DapLine' + } +) +vim.fn.sign_define( + 'DapStopped', + { + text = ' ', + texthl = 'DapStopped', + linehl = 'DapLine', + numhl = 'DapLine' + } +) diff --git a/nvim/lua/user/dap/telescope.lua b/nvim/lua/user/dap/telescope.lua new file mode 100644 index 0000000..be74ccb --- /dev/null +++ b/nvim/lua/user/dap/telescope.lua @@ -0,0 +1,7 @@ +local ok_telescope, telescope = pcall(require, "telescope") + +if not (ok_telescope) then + return +end + +telescope.load_extension('dap') diff --git a/nvim/lua/user/plugins.lua b/nvim/lua/user/plugins.lua index 6af7036..78ecc4a 100644 --- a/nvim/lua/user/plugins.lua +++ b/nvim/lua/user/plugins.lua @@ -91,6 +91,23 @@ local plugins = function(use) use({ "williamboman/mason.nvim" }) -- An LSP installer use({ "williamboman/mason-lspconfig.nvim" }) -- Bridge between lspconfig and mason + -- Debug DAP + use "mfussenegger/nvim-dap" + use { + "rcarriga/nvim-dap-ui", + requires = { "mfussenegger/nvim-dap" } + } + use "nvim-telescope/telescope-dap.nvim" + use { + "mxsdev/nvim-dap-vscode-js", + requires = { "mfussenegger/nvim-dap" } + } + use { + "microsoft/vscode-js-debug", + opt = true, + run = "npm install --legacy-peer-deps && npx gulp vsDebugServerBundle && mv dist out" + } + -- A collection of common configurations for Neovim's built-in language server client. use({ "neovim/nvim-lspconfig",