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 Jun 25, 2023
1 parent 7e367c2 commit d4dc123
Show file tree
Hide file tree
Showing 12 changed files with 336 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>codiconNerdFont-Regular 12</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"
10 changes: 10 additions & 0 deletions nvim/lua/user/cmp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ cmp.setup({
-- Disable native menu
native_menu = false,
},
enabled = function()
return vim.api.nvim_buf_get_option(0, "buftype") ~= "prompt"
or require("cmp_dap").is_dap_buffer()
end
})

cmp.setup.filetype({ "dap-repl", "dapui_watches", "dapui_hover" }, {
sources = {
{ name = "dap" },
},
})

-- Add vim-dadbod-completion in sql files
Expand Down
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
9 changes: 9 additions & 0 deletions nvim/lua/user/dap/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- DAP components
require("user.dap.telescope")
require("user.dap.keymaps")
require("user.dap.virtual_text")
require("user.dap.line_signs")
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
)
38 changes: 38 additions & 0 deletions nvim/lua/user/dap/languages/javascript.lua
Original file line number Diff line number Diff line change
@@ -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
})
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', ]]
})
19 changes: 19 additions & 0 deletions nvim/lua/user/plugins.lua
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ local plugins = function(use)
use "hrsh7th/cmp-nvim-lua"
use "kristijanhusak/vim-dadbod-completion" -- Completion for vim-dadbod
use "onsails/lspkind-nvim" -- Autocomple icons
use "rcarriga/cmp-dap" -- DAP completion

-- snippets
use "L3MON4D3/LuaSnip" --snippet engine
Expand All @@ -91,6 +92,24 @@ 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 "theHamsta/nvim-dap-virtual-text"
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",
Expand Down

0 comments on commit d4dc123

Please sign in to comment.