NeoVim and Xdebug post
NeoVim and Xdebug
As I continue to work on the configuration for the One True Editor I had everything working just about the way that duplicated how I use PhpStorm except for one thing -- using Xdebug.
As I write this blog post I have an article submitted for php[architect] on how I use NeoVim to do PHP development work and in that article I talked about the next few things I was going to work on adding support for ($100 a year to do enemy research on Copilot AI?!?) and getting the tool that I regret not embracing earlier but now find it indispensable.
This is not the blog post if you are looking to figure out how to get Xdebug running with whatever version of PHP you are trying to use. The excellent documentation on the Xdebug web site will absolutely point you in the right direction.
In my case, I went the route of manually compiling the 3.2.x series (I honestly cannot remember why) but most package managers for your operating system of choice can help you with that.
Xdebug and DAP
DAP (which is short for the Debug Anywhere Protocol. Look, you can quibble about who is behind DAP but the overarching goal of providing a standardized way for both debugging tools and programming languages to talk to each other makes a lot of sense. The Language Server Protocol is a similar effort that has found a lot of traction outside of Microsoft.
Prerequisites
You to have the following before we get started:
- a version of PHP with Xdebug support
- NeoVim 0.5+ or better
- the ability to edit your NeoVim configuration files
- the ability to install NeoVim plugins
- Node installed (need it to install some tooling)
- Git CLI tools installed
Debug Adapter for PHP
To start, I followed the excellent instructions found here but to replicate them here:
git clone https://github.com/xdebug/vscode-php-debug.git
cd vscode-php-debug
npm install && npm run build
Leveraging an existing tool to make it work is always galaxy-brain-level thinking.
Next, I decided on which plugins I wanted to use to interact with Xdebug while inside NeoVim. I chose:
- mfussenegger/nvim-dap for high-level support
- rcarriga/nvim-dap-ui as my UI for looking at the debug details
- theHamsta/nvim-dap-virtual-text find variable definitions
- nvim-telescope/telescope-dap.nvim to provide compatibility with Telescope
Again, I encourage people to start with a base that WORKS and then start experimenting to get it the way you want it.
DAP Plugin Configuration
Again, this is for my own setup. It might be different for your own.
I needed to make sure that I turn on Telescope support in my
init.vim
file. I need it for other plugins but make sure
you enable it if you are using telescope-dap.nvim
.
lua require('telescope').setup
Note that the above is how to load Lua files inside a Vimscript file. I am starting to work on the outline of using Lua for all my NeoVim configuration settings.
Next, I have a configuration file just for DAP that I also load in
my init.vim
file:
local dap = require('dap')
require('telescope').load_extension('dap')
dap.adapters.php = {
type = "executable",
command = "node",
args = { os.getenv("HOME") .. "/vscode-php-debug/out/phpDebug.js" }
}
dap.configurations.php = {
{
type = "php",
request = "launch",
name = "Listen for Xdebug",
port = 9003
}
}
In here I tell NeoVim:
- load the DAP extension for Telescope (it overrides the default UI)
- I want to use the VS Code DAP adapter
- what port to listen for Xdebug info on (Xdebug 3.2.x goes with 9003 as the standard port)
On the Xdebug web site section about VS Code
it points out that you can also add in a pathMappings
value in dap.configurations.php
to "map the files on the server to
the right files on your local machine." and gives an example.
I don't use pathMappings
and my setup works just fine.
Of course, I could not really use Xdebug from inside the editor without some keyboard mappings:
vim.keymap.set('n', '<F5>', function() require('dap').continue() end)
vim.keymap.set('n', '<F10>', function() require('dap').step_over() end)
vim.keymap.set('n', '<F11>', function() require('dap').step_into() end)
vim.keymap.set('n', '<F12>', function() require('dap').step_out() end)
vim.keymap.set('n', '<Leader>b', function() require('dap').toggle_breakpoint() end)
vim.keymap.set('n', '<Leader>B', function() require('dap').set_breakpoint() end)
vim.keymap.set('n', '<Leader>lp', function() require('dap').set_breakpoint(nil, nil, vim.fn.input('Log point message: ')) end)
vim.keymap.set('n', '<Leader>dr', function() require('dap').repl.open() end)
vim.keymap.set('n', '<Leader>dl', function() require('dap').run_last() end)
vim.keymap.set({'n', 'v'}, '<Leader>dh', function()
require('dap.ui.widgets').hover()
end)
vim.keymap.set({'n', 'v'}, '<Leader>dp', function()
require('dap.ui.widgets').preview()
end)
vim.keymap.set('n', '<Leader>df', function()
local widgets = require('dap.ui.widgets')
widgets.centered_float(widgets.frames)
end)
vim.keymap.set('n', '<Leader>ds', function()
local widgets = require('dap.ui.widgets')
widgets.centered_float(widgets.scopes)
end)
My usual workflow for debugging is:
- code I am debugging open in the editor
- if I didn't already start debugging, hit
F5
to turn on the debugging session - set breakpoints where I want them with
\b
- run the code, step through the breakpoints, and see what's going on
Not different in any significant way than how I would do things in PhpStorm.
So there you have it! If you are a NeoVim user and want to start utilizing Xdebug to help you, well, debug your code faster my documentation above should get you pointed in the correct direction.
Categories: testing, php, tools