Skip to content

How to debug like a PRO using Neovim 🔥

Posted on:October 5, 2022 at 06:00 PM

I’ve been using Neovim to write code since a couple of years, but I must admit that every time I wanted to debug something I would switch to VS Code or Firefox debugging tools (For Node and Javascript), but recently I decided to research how to set up Neovim to do it as well, I started digging into some documentations and found it so interesting that I ended up writing this article 😅.

Few editors are as extensible and powerful as Neovim, I believe everything you can think of can be implemented on it, including debugging (like a PRO).

In this article, we will learn how to prepare our Neovim to debug any kind of language using **DAP (Debug Adapter Protocol) **and in the process understand a bit better this technology. We will focus mainly on Golang, but the same knowledge can be applied to any other language with DAP support.

What is DAP

The Debug Adapter Protocol (DAP) is a standardized protocol introduced by Microsoft and used in Visual Studio Code that allows editors and IDEs (Tools) to outsource much of the logic that before had to be implemented in every editor to an intermediary called a Debug Adapter that can be reused across multiple tools, resulting in faster development times for editors’ developers and better user experiences for normal developers as they can get similar top code assistance across multiple editors.

Before DAP

Before DAP, every time you developed a new editor, and you wanted to support code debugging inside of it, you had to take care of all the implementation details of features like:

And besides this, you also had to take care of all the UI implementation, all of these of course was a lot of effort for tool’s developers that some tools simple could not afford.

Before DAP

After DAP

Now with DAP editors’ developers only have to focus on:

After DAP

Installing a DAP Client

Currently, Neovim doesn’t have a built-in DAP Client, as it does for the Language Server Protocol (LSP). So we need to manually install nvim-dap which is a normal Neovim plugin that will act as the DAP Client.

If you’re using Packer, simply add to your plugin list:

use 'mfussenegger/nvim-dap'

Installing a debugger

In order to start debugging, you first need to install a debugger for the language you’re using, for Go:

LanguageDebugger
Golang

**Installing delve for **Golang

go install github.com/go-delve/delve/cmd/dlv@latest

Configuring the Debug Adapter

The next thing is to tell Neovim how to communicate with delve, you don’t really need to install another plugin to do this, but there are multiple plugins that basically do most of the configuration of the adapter for us.

For Go, we can use nvim-dap-go which only require the following lines:

use 'leoluz/nvim-dap-go' -- Install the plugin with Packer
require('dap-go').setup()

What does nvim-dap-go actually do?

You can skip this section unless you want to understand what nvim-dap-go actually does.

This plugin basically tells how Neovim should launch the debugger (in our case delve) by using the API provided by the plugin nvim-dap

A very simplistic version of this extension’s code would be:

dap.adapters.go = function(callback, config)
  -- Wait for delve to start
    vim.defer_fn(function()
        callback({type = "server", host = "127.0.0.1", port = "port"})
      end,
    100)
end
dap.configurations.go = {
    {
      type = "go",
      name = "Debug",
      request = "launch",
      program = "${file}",
    },
...

[nvim-dap-go complete

code](https://github.com/leoluz/nvim-dap-go/blob/main/lua/dap-go.lua)

Defining configuration using launch.json file

If you’re familiar with how VS Code works, you might know that you can provide the above configuration using a file called launch.json that is located in your project folder, if you prefer this method, this is also possible using nvim-dap!

Simply add the following line to your configuration:

require('dap.ext.vscode').load_launchjs(nil, {})

Making the debugging interface amazing 💅!

Installing nvim-dap-ui

nvim dap ui

This is a nice package that will make the debugging much nicer, it basically puts all the DAP information into Neovim buffers.

To install it:

use { "rcarriga/nvim-dap-ui", requires = {"mfussenegger/nvim-dap"} }

Open automatically when a new debug session is created

local dap, dapui =require("dap"),require("dapui")
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

Make the breakpoints look nicer

In your configuration, put this to change the ugly B text for these icons

vim.fn.sign_define('DapBreakpoint',{ text ='🟥', texthl ='', linehl ='', numhl =''})
vim.fn.sign_define('DapStopped',{ text ='▶️', texthl ='', linehl ='', numhl =''})

Set some keymaps

vim.keymap.set('n', '<F5>', require 'dap'.continue)
vim.keymap.set('n', '<F10>', require 'dap'.step_over)
vim.keymap.set('n', '<F11>', require 'dap'.step_into)
vim.keymap.set('n', '<F12>', require 'dap'.step_out)
vim.keymap.set('n', '<leader>b', require 'dap'.toggle_breakpoint)

What do you think?

What do you think about this article? Leave your comments 💬