For a tutorial and usage overview, take a look at the Vimspector website
The plugin is a capable Vim graphical debugger for multiple languages. It's mostly tested for c++ and python, but in theory supports any language that Visual Studio Code supports (but see caveats).
The Vimspector website has an overview of the UI, along with basic instructions for configuration and setup.
- breakpoints (function, line and exception breakpoints)
- step in/out/over/up, stop, restart
- launch and attach
- remote launch, remote attach
- locals and globals display
- watch expressions
- call stack and navigation
- variable value display hover
- interactive debug console
- launch debugee within Vim's embedded terminal
- logging/stdout display
The following languages are used frequently by the author and are known to work with little effort, and are supported as first-class languages.
- C, C++, etc. (languages supported by gdb or lldb)
- Python 2 and Python 3
- TCL
- Bash scripts
The following languages are used frequently by the author, but require some sort of hackery that makes it challenging to support generally. These languages are on a best-efforts basis:
- Java (see caveats)
- C# (c-sharp) using dotnet core
- Go (requires separate installation of Delve)
- Node.js (requires node <12 for installation)
- Anything running in chrome (i.e. javascript).
- C# (c-sharp) using mono debug adapter (vimspector unable to set breakpoints)
Vimspector should work for any debug adapter that works in Visual Studio Code, but there are certain limitations (see FAQ). If you're trying to get vimspector to work with a language that's not "supported", head over to Gitter and contact the author. It should be possible to get it going.
There are 2 installation methods:
- Using a release tarball, or
- Manually
Release tarballs come with debug adapters for the default languages pre-packaged. To use a release tarball:
- Check the dependencies
- Untar the release tarball for your OS into
$HOME/.vim/pack
:
$ mkdir -p $HOME/.vim/pack
$ curl -L <url> | tar -C $HOME/.vim/pack zxvf -
- Configure your project's debug profiles (create
.vimspector.json
)
Alternatively, you can clone the repo and select which gadgets are installed:
- Check the dependencies
- Install the plugin as a Vim package. See
:help packages
. - Install some 'gadgets' (debug adapters)
- Configure your project's debug profiles (create
.vimspector.json
)
Vimspector requires:
- Vim version 8.1 with at least patch 1264
- One of the following operating systems:
- Linux
- macOS Mojave or pater
Why such a new vim ? Well 2 reasons:
- Because vimspector uses a lot of new Vim features
- Because there are Vim bugs that vimspector triggers that will frustrate you if you hit them.
Why no Windows support? Because it's effort and it's not a priority for the author. PRs are welcome.
Which Linux versions? I only test on Ubuntu 18.04 and later and RHEL 6.5 and RHEL 7.6.
The debug adapters themselves have certain runtime dependencies:
Language | Status | Switch | Adapter | Dependencies |
---|---|---|---|---|
C, C++, etc. | Supported | --all or --enable-c |
vscode-cpptools | mono-core |
Python | Supported | --all or --enable-python |
vscode-python | Python 2.7 or Python 3 |
TCL | Experimental | --all or --enable-tcl |
tclpro | TCL 8.5 |
Bourne Shell | Experimental | --all or --enable-bash |
vscode-bash-debug | Bash v?? |
C# (dotnet core) | Experimental | --force-enable-csharp |
netcoredbg | DotNet core |
C# (mono) | Experimental | --force-enable-csharp |
vscode-mono-debug | Mono |
Go | Experimental | --enable-go |
vscode-go | Go, Delve |
Node.js | Experimental | --force-enable-node |
vscode-node-debug2 | 6 < Node < 12, Npm |
Javascript | Experimental | --force-enable-chrome |
debugger-for-chrome | Chrome |
For other languages, you'll need some other way to install the gadget.
There are many Vim plugin managers, and I'm not going to state a particular preference, so if you choose to use one, you're on your own with installation issues.
Install vimspector as a Vim package, either by cloning this repository into your package path, like this:
$ git clone https://github.com/puremourning/vimspector ~/.vim/pack/vimspector/opt/vimspector
- Configure vimspector in your
.vimrc
:
let g:vimspector_enable_mappings = 'HUMAN'
- Load vimspector at runtime. This can also be added to your
.vimrc
after configuring vimspector:
packadd! vimspector
See support/doc/example_vimrc.vim.
Also, if you want to try out vimspector without changing your vim config, run:
vim -Nu /path/to/vimspector/tests/vimrc --cmd "let g:vimspector_enable_mappings='HUMAN'"
There are a couple of ways of doing this, but using install_gadget.py
is
highly recommended where that's an option.
For supported languages, install_gadget.py
will:
- Download the relevant debug adapter at a version that's been tested from the internet, either as a 'vsix' (Visusal Studio plugin), or clone from GitHub. If you're in a corporate environment and this is a problem, you may need to install the gadgets manually.
- Perform any necessary post-installation actions, such as:
- Building any binary components
- Ensuring scripts are executable, because the VSIX pacakges are usually broken in this regard.
- Set up the
gadgetDir
symlinks for the platform.
To install the tested debug adapter for a language, run:
./install_gadget.py --enable-<language>
Or to install all supported gagtets:
./install_gadget.py --all
To install everything other than TCL (because TCL is sadly not as popular as it should be):
./install_gadget.py --all --disable-tcl
See --help
for more info.
You essentially need to get a working installation of the debug adapter, find
out how to start it, and configure that in an adapters
entry in either your
.vimspector.json
or in .gadgets.json
.
The simplest way in practice is to install or start Visusal Studio Code and use
its extension manager to install the relevant extension. You can then configure
the adapter manually in the adapters
section of your .vimspector.json
or in
a gagets.json
.
PRs are always welcome to add configuration to do this to install_gadget.py
.
Vimspector uses the following directory by default to look for a file named
.gadgets.json
: </path/to/vimspector>/gadgets/<os>
.
This path is exposed as the vimspector variable ${gadgetDir}
. This is useful
for configuring gadget command lines.
Where os is one of:
macos
linux
windows
(though note: Windows is not supported)
The format is the same as .vimspector.json
, but only the gagets
key is used:
Example:
{
"adapters": {
"vscode-cpptools": {
"attach": {
"pidProperty": "processId",
"pidSelect": "ask"
},
"command": [
"${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7"
],
"name": "cppdbg"
},
"vscode-python": {
"command": [
"node",
"${gadgetDir}/vscode-python/out/client/debugger/debugAdapter/main.js"
],
"name": "vscode-python"
}
}
}
The gadget file is automatically written by install_gadget.py
.
The motivation is that debugging in Vim is a pretty horrible experience, particularly if you use multiple languages. With pyclewn no more and the built-in termdebug plugin limited to gdb, I wanted to explore options.
While Language Server Protocol is well known, the Debug Adapter Protocol is less well known, but achieves a similar goal: language agnostic API abstracting debuggers from clients.
The aim of this project is to provide a simple but effective debugging experience in Vim for multiple languages, by leveraging the debug adapters that are being built for Visual Studio Code.
The ability to do remote debugging is a must. This is key to my workflow, so baking it in to the debugging experience is a top bill goal for the project. So vimspector has first-class support for executing programs remotely and attaching to them. This support is unique to vimspector and on top of (complementary to) any such support in actual debug adapters.
Vimspector is a work in progress, and any feedback/contributions are more than welcome.
The backlog can be viewed on Trello.
In order to use it you have to currently:
- Write a mostly undocumented configuration file that contains essentially undocumented parameters.
- Accept that it isn't complete yet
- Work around some frustrating bugs in Vim
- Ignore probably many bugs in vimspector!
The plugin is currently experimental. That means that any part of it can (and probably will) change, including things like:
- breaking changes to the configuration
- keys, layout, functionatlity of the UI
If a large number of people start using it then I will do my best to minimise this, or at least announce on Gitter.
By default, vimspector does not change any of your mappings. Mappings are very
personal and so you should work out what you like and use vim's powerful mapping
features to set your own mappings. For example, if you want <F5>
to
start/continue debugging, add this to some appropriate place, such as your
vimrc
(hint: run :e $MYVIMRC
).
nnoremap <F5> :call vimspector#Continue()<CR>
That said, many people are familiar with particular debuggers, so the following
mappings can be enabled by setting g:vimspector_enable_mappings
to the
specified value.
Please note: Currently there are no <plug>
mappings. These will be added in
future to make custom mappings much easier.
To use Visual Studio-like mappings, add the following to your vimrc
before
loading vimspector:
let g:vimspector_enable_mappings = 'VISUAL_STUDIO'
Key | Function | API |
---|---|---|
F5 |
When debugging, continue. Otherwise start debugging. | vimspector#Continue() |
Shift F5 |
Stop debugging. | vimspector#Stop() |
Ctrl Shift F5 |
Restart debugging with the same configuration. | vimspector#Restart() |
F6 |
Pause debugee. | vimspector#Pause() |
F9 |
Toggle line breakpoint on the current line. | vimspector#ToggleBreakpoint() |
Shift F9 |
Add a function breakpoint for the expression under cursor | vimspector#AddFunctionBreakpoint( '<cexpr>' ) |
F10 |
Step Over | vimspector#StepOver() |
F11 |
Step Into | vimspector#StepInto() |
Shift F11 |
Step out of current function scope | vimspector#StepOut() |
If, like me, you only have 2 hands and 10 fingers, you probably don't like
Ctrl-Shift-F keys. Also, if you're running in a terminal, there's a real
possibility of terminfo being wrong for shifted-F-keys, particularly if your
TERM
is screen-256color
. If these issues (number of hands, TERM
variables)
are unfixable, try the following mappings, by adding the following before
loading vimspector:
let g:vimspector_enable_mappings = 'HUMAN'
Key | Function | API |
---|---|---|
F5 |
When debugging, continue. Otherwise start debugging. | vimspector#Continue() |
F3 |
Stop debugging. | vimspector#Stop() |
F4 |
Restart debugging with the same configuration. | vimspector#Restart() |
F6 |
Pause debugee. | vimspector#Pause() |
F9 |
Toggle line breakpoint on the current line. | vimspector#ToggleBreakpoint() |
F8 |
Add a function breakpoint for the expression under cursor | vimspector#AddFunctionBreakpoint( '<cexpr>' ) |
F10 |
Step Over | vimspector#StepOver() |
F11 |
Step Into | vimspector#StepInto() |
F12 |
Step out of current function scope | vimspector#StepOut() |
- Create
vimspector.json
. See below. :call vimspector#Launch()
and select a configuration.
- Use
vimspector#ToggleBreakpoint()
to set/disable/delete a line breakpoint. - Use
vimspector#AddFunctionBreakpoint( '<name>' )
to add a function breakpoint.
- Step in/out, finish, continue, pause etc. using the WinBar.
- If you really want to, the API is
vimspector#StepInto()
etc.
- Current scope shows values of locals.
- Use
<CR>
to expand/collapse (+, -). - When changing the stack frame the locals window updates.
- While paused, hover to see values
The watches window is a prompt buffer. Enter insert mode to add a new watch expression.
- Add watches to the variables window by entering insert mode and
typing the expression. Commit with
<CR>
. - Expand result with
<CR>
. - Delete with
<DEL>
.
- In the threads window, use
<CR>
to expand/collapse. - Use
<CR>
on a stack frame to jump to it.
- In the outputs window use the WinBar to select the output channel.
- The debugee prints to the stdout channel.
- Other channels may be useful for debugging.
The console window is a prompt buffer and can be used as an interactive CLI for the debug adapter. Support for this varies amongt adapters.
- Enter insert mode to enter a command to evaluate
- Commit the request with
<CR>
- The request and subsequent result are printed.
NOTE: See also [Watches][#watches] above.
For more information on the configuration of .vimspector.json
, take a look at
the Getting Started section of the Vimspector website.
Current tested with the following debug adapters.
- C++: vscode-cpptools
Example .vimspector.json
{
"configurations": {
"<name>: Launch": {
"adapter": "vscode-cpptools",
"configuration": {
"name": "<name>",
"type": "cppdbg",
"request": "launch",
"program": "<path to binary>",
"args": [ ... ],
"cwd": "<working directory>",
"environment": [ ... ],
"externalConsole": true,
"MIMode": "lldb"
}
},
"<name>: Attach": {
"adapter": "vscode-cpptools",
"configuration": {
"name": "<name>: Attach",
"type": "cppdbg",
"request": "attach",
"program": "<path to binary>",
"MIMode": "lldb"
}
}
...
}
}
- Python: vscode-python
{
"configurations": {
"<name>: Launch": {
"adapter": "vscode-python",
"configuration": {
"name": "<name>: Launch",
"type": "python",
"request": "launch",
"cwd": "<working directory>",
"stopOnEntry": true,
"console": "externalTerminal",
"debugOptions": [],
"program": "<path to main python file>"
}
}
...
}
}
- TCL (TclProDebug)
See my fork of TclProDebug for instructions.
- C# - dotnet core
Requires install_gadget.py --force-enable-c-sharp
{
"configurations": {
"launch - netcoredbg": {
"adapter": "netcoredbg",
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll",
"args": [],
"stopAtEntry": true
}
}
}
}
- C# - mono
Requires install_gadget.py --force-enable-c-sharp
.
Known not to work.*
{
"configurations": {
"launch - mono": {
"adapter": "vscode-mono-debug",
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll",
"args": [],
"cwd": "${workspaceRoot}",
"runtimeExecutable": "mono",
"runtimeArgs": [],
"env": [],
"externalConsole": false,
"console": "integratedTerminal"
}
}
}
}
- Go
Requires:
install_gadget.py --enable-go
- Delve installed, e.g.
go get -u github.com/go-delve/delve/cmd/dlv
- Delve to be in your PATH, or specify the
dlvToolPath
launch option
{
"configurations": {
"run": {
"adapter": "vscode-go",
"configuration": {
"request": "launch",
"program": "${fileDirname}",
"mode": "debug",
"dlvToolPath": "$HOME/go/bin/dlv"
}
}
}
}
- Node.js
Requires:
install_gadget.py --force-enable-node
- For installation, a Node.js environemt that is < node 12. I believe this is an
incompatibility with gulp. Advice, use [nvm][] with
nvm install --lts 10; nvm use --lts 10; ./install_gadget.py --force-enable-node ...
- Options described here: https://code.visualstudio.com/docs/nodejs/nodejs-debugging
- Example:
support/test/node/simple
{
"configurations": {
"run": {
"adapter": "vscode-node",
"configuration": {
"request": "launch",
"protocol": "auto",
"stopOnEntry": true,
"console": "integratedTerminal",
"program": "${workspaceRoot}/simple.js",
"cwd": "${workspaceRoot}"
}
}
}
}
- Chrome
This uses the chrome debugger, see https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome.
It allows you to debug scripts running inside chrome from within Vim.
./install_gadget.py --force-enable-chrome
- Example:
support/test/chrome
{
"configurations": {
"launch": {
"adapter": "chrome",
"configuration": {
"request": "launch",
"url": "http://localhost:1234/",
"webRoot": "${workspaceRoot}/www"
}
}
}
}
Also the mock debugger, but that isn't actually useful.
- Java Debug Server. The java debug server runs as a jdt.ls plugin, rather than a standalone debug adapter. This makes a lot of sense if you already happen to be running the language server. Vimspector is not in the business of running language servers. So, rather than doing so, vimspector simply allows you to start the java debug server manually (however you might do so) and you can tell vimspector the port on which it is listening. See this issue for more background.
- Q: Does it work? A: Yeah, sort of. It's incredibly buggy and unpolished.
- Q: Does it work with this language? A: Probably, but it won't
necessarily be easy to work out what to put in the
.vimspector.json
. As you can see above, some of the servers aren't really editor agnostic, and require very-specific unique handling.
Copyright © 2018 Ben Jackson