Skip to content

Commit

Permalink
Introduce nvim-dap (Debugger Adapter Protocol) to my NVim
Browse files Browse the repository at this point in the history
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](vercel/next.js#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](microsoft/vscode#151910)

FUCK! This was hard 😂
  • Loading branch information
andresgutgon committed Jul 2, 2023
1 parent 7e367c2 commit 96eaf94
Show file tree
Hide file tree
Showing 13 changed files with 351 additions and 10 deletions.
12 changes: 4 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,10 @@ These packages need to be installed in Mac OS X
2. For `nvim-spectre`: `brew install gnu-sed` & `brew install ripgrep`

## Nerd fonts
[This video explains how to install it and what are nerd fonts](https://www.youtube.com/watch?v=fR4ThXzhQYI&list=PLhoH5vyxr6Qq41NFL4GvhFp-WLd5xzIzZ&index=7)
[Look for icons here](https://www.nerdfonts.com/cheat-sheet)
In your machince there is this directory: `~/.local/share/fonts`. You have to put there the fonts you want.
In my case I want `Hack` font so I do this once when I setup a new machine:
``` bash
brew tap homebrew/cask-fonts
brew install --cask font-hack-nerd-font
```
To setup a custom font (in this case Nerd Font) go to:
https://www.nerdfonts.com/font-downloads
and download it. Install it with Mac OS X fonts and you're good to go.

Then if you're using iTerm go to Preferences (⌘ + ,) > Profiles > Text > Font and select `Hack` as your terminal fornt.
Already done in my case because I store iTerm preferences in my dotfiles

Expand Down
4 changes: 2 additions & 2 deletions iterm/com.googlecode.iterm2.plist
Original file line number Diff line number Diff line change
Expand Up @@ -1030,11 +1030,11 @@
<key>Name</key>
<string>Andres</string>
<key>Non Ascii Font</key>
<string>Monaco 12</string>
<string>Menlo-Regular 11</string>
<key>Non-ASCII Anti Aliased</key>
<true/>
<key>Normal Font</key>
<string>HackNerdFontCompleteM-Regular 12</string>
<string>HackNF-Regular 12</string>
<key>Option Key Sends</key>
<integer>0</integer>
<key>Prompt Before Closing 2</key>
Expand Down
1 change: 1 addition & 0 deletions nvim/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ require "user.lualine"
require "user.trouble"
require "user.prettier"
require "user.spectre"
require "user.dap"
5 changes: 5 additions & 0 deletions nvim/lua/user/cmp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ cmp.setup({
-- Disable native menu
native_menu = false,
},
enabled = function()
-- Enable pligin for nvim-dap completions on REPL panel
return vim.api.nvim_buf_get_option(0, "buftype") ~= "prompt"
or require("cmp_dap").is_dap_buffer()
end
})

-- Add vim-dadbod-completion in sql files
Expand Down
10 changes: 10 additions & 0 deletions nvim/lua/user/dap/cmp.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
local cmp_status_ok, cmp = pcall(require, "cmp")
if not cmp_status_ok then
return
end

cmp.setup.filetype({ "dap-repl", "dapui_watches", "dapui_hover" }, {
sources = {
{ name = "dap" },
},
})
86 changes: 86 additions & 0 deletions nvim/lua/user/dap/dap_ui.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
local ok_dap, dap = pcall(require, "dap")
local ok_dapui, dapui = pcall(require, "dapui")

if not (ok_dap and ok_dapui) then
return
end

local config = {
icons = { expanded = "", collapsed = "", current_frame = "" },
mappings = {
-- Use a table to apply multiple mappings
expand = { "<CR>", "<2-LeftMouse>" },
open = "o",
remove = "d",
edit = "e",
repl = "r",
toggle = "t",
},
element_mappings = {},
expand_lines = vim.fn.has("nvim-0.7") == 1,
force_buffers = true,
layouts = {
{
-- You can change the order of elements in the sidebar
elements = {
-- Provide IDs as strings or tables with "id" and "size" keys
{
id = "scopes",
size = 0.25, -- Can be float or integer > 1
},
{ id = "breakpoints", size = 0.25 },
{ id = "stacks", size = 0.25 },
{ id = "watches", size = 0.25 },
},
size = 40,
position = "left", -- Can be "left" or "right"
},
{
elements = {
"repl",
},
size = 10,
position = "bottom", -- Can be "bottom" or "top"
},
},
floating = {
max_height = nil,
max_width = nil,
border = "single",
mappings = {
["close"] = { "q", "<Esc>" },
},
},
controls = {
enabled = vim.fn.exists("+winbar") == 1,
element = "repl",
icons = {
pause = "",
play = "",
step_into = "",
step_over = "",
step_out = "",
step_back = "",
run_last = "",
terminate = "",
disconnect = "",
},
},
render = {
max_type_length = nil, -- Can be integer or nil.
max_value_lines = 100, -- Can be integer or nil.
indent = 1,
},
}

dapui.setup(config)

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
10 changes: 10 additions & 0 deletions nvim/lua/user/dap/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- DAP components
require("user.dap.telescope")
require("user.dap.keymaps")
require("user.dap.virtual_text")
require("user.dap.line_signs")
require("user.dap.cmp")
require("user.dap.dap_ui")

-- DAP language debuggers
require("user.dap.languages.javascript")
78 changes: 78 additions & 0 deletions nvim/lua/user/dap/keymaps.lua
Original file line number Diff line number Diff line change
@@ -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", "<leader>dl", "<CMD>Telescope dap configurations<CR>", opts)

-- Continue. This launch the debugger
keymap(
"n",
"<leader>dr",
":lua require(\"dap\").repl.open()<CR>",
opts
)

-- Set breakboint
keymap(
"n",
"<leader>di",
":lua require(\"dap\").toggle_breakpoint()<CR>",
opts
)

-- Continue. This launch the debugger
keymap(
"n",
"<leader>dc",
":lua require(\"dap\").continue()<CR>",
opts
)

-- Next line
keymap(
"n",
"<leader>dn",
":lua require(\"dap\").step_over()<CR>",
opts
)

-- Prev line
keymap(
"n",
"<leader>dN",
":lua require(\"dap\").step_into()<CR>",
opts
)

-- Go out of method
keymap(
"n",
"<leader>do",
":lua require(\"dap\").step_out()<CR>",
opts
)

keymap(
"n",
"<leader>dl",
":lua require(\"dap\").run_to_cursor()<CR>",
opts
)

-- Disconnect. End debugging session
keymap(
"n",
"<leader>dS",
":lua require(\"dap\").disconnect()<CR>",
opts
)

-- Dap UI. Toggle
keymap(
"n",
"<leader>dww",
":lua require(\"dapui\").toggle()<CR>",
opts
)
47 changes: 47 additions & 0 deletions nvim/lua/user/dap/languages/javascript.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
local ok_dap, dap = pcall(require, "dap")
local ok_dap_utils, dap_utils = pcall(require, "dap.utils")
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 and ok_dap_launch_vscode and ok_dap_utils) 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] = {
{
name = "Attach to process",
type = "pwa-node",
request = "attach",
processId = dap_utils.pick_process,
cwd = "${workspaceFolder}",
}
}
end

-- ## DAP `launch.json`
dap_launch_vscode.load_launchjs(nil, {
["pwa-node"] = languages,
["node-terminal"] = languages
})
56 changes: 56 additions & 0 deletions nvim/lua/user/dap/line_signs.lua
Original file line number Diff line number Diff line change
@@ -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'
}
)
7 changes: 7 additions & 0 deletions nvim/lua/user/dap/telescope.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
local ok_telescope, telescope = pcall(require, "telescope")

if not (ok_telescope) then
return
end

telescope.load_extension('dap')
26 changes: 26 additions & 0 deletions nvim/lua/user/dap/virtual_text.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
local ok_virtual_text, virtual_text = pcall(require, "nvim-dap-virtual-text")

if not (ok_virtual_text) then
return
end

virtual_text.setup({
enabled = true,
enabled_commands = true,
highlight_changed_variables = true,
highlight_new_as_changed = false,
show_stop_reason = true,
commented = false,
only_first_definition = true,
all_references = false,
clear_on_continue = false,
display_callback = function(variable, _, _, _, options)
if options.virt_text_pos == 'inline' then
return ' = ' .. variable.value
else
return variable.name .. ' = ' .. variable.value
end
end,
-- TODO: Use when in 0.10 version of NVim
--[[ virt_text_pos = vim.fn.has 'nvim-0.10' == 1 and 'inline' or 'eol', ]]
})
Loading

0 comments on commit 96eaf94

Please sign in to comment.