diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 1788c04..828ec18 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -17,12 +17,12 @@ assignees: '' > Please answer the following questions -* Does your issue reproduce using `vim -Nu /path/to/vimspector/support/minimal_vimrc` ? \[Yes/No] +* Does your issue reproduce using `vim --clean -Nu /path/to/vimspector/support/minimal_vimrc` ? \[Yes/No] * If you are using Neovim, does your issue reproduce using Vim? \[Yes/No] > List of steps to reproduce: -> 1. Run `vim -Nu /path/to/vimspector/support/minimal_vimrc` +> 1. Run `vim ---clean Nu /path/to/vimspector/support/minimal_vimrc` > 2. Open _this project_... > 3. Press _this sequence of keys_ @@ -57,6 +57,12 @@ discussing on Gitter rather than raising an issue. * Version of Vimspector: (e.g. output of `git rev-parse HEAD` if cloned or the name of the tarball used to install otherwise) +* Output of `:VimspectorDebugInfo` + +``` +paste here +``` + * Output of `vim --version` or `nvim --version` ``` diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 17f9601..f186f5d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -13,7 +13,7 @@ defaults: jobs: PythonLint: - runs-on: ubuntu-16.04 + runs-on: ubuntu-18.04 container: 'puremourning/vimspector:test' steps: - uses: actions/checkout@v2 @@ -22,7 +22,7 @@ jobs: - name: 'Run flake8' run: '$HOME/.local/bin/flake8 python3/ *.py' VimscriptLint: - runs-on: 'ubuntu-16.04' + runs-on: 'ubuntu-18.04' container: 'puremourning/vimspector:test' steps: - uses: actions/checkout@v2 @@ -32,7 +32,7 @@ jobs: run: $HOME/.local/bin/vint autoload/ compiler/ plugin/ tests/ syntax/ Linux: - runs-on: 'ubuntu-16.04' + runs-on: 'ubuntu-18.04' container: image: 'puremourning/vimspector:test' options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined @@ -111,6 +111,16 @@ jobs: path: gadgets/macos/download name: Cache gadgets + - name: 'Install .NET Core SDK 3.1' + uses: actions/setup-dotnet@v1.7.2 + with: + dotnet-version: 3.1 + + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: ^11 + name: "Switch to xcode 11 because of .NET debugging bug" + - run: vim --version name: 'Print vim version information' @@ -143,10 +153,10 @@ jobs: # if: failure() # with: # NGROK_AUTH_TOKEN: ${{ secrets.NGROK_AUTH_TOKEN }} - # SSH_PASS: ${{ secrets.SSH_PASS }} + # SSH_PASS: ${{ secrets.SSH_PASS }} # [V]imspector PublishRelease: - runs-on: 'ubuntu-16.04' + runs-on: 'ubuntu-18.04' needs: - Linux - MacOS diff --git a/.github/workflows/lock_old_issues.yaml b/.github/workflows/lock_old_issues.yaml new file mode 100644 index 0000000..25d65e0 --- /dev/null +++ b/.github/workflows/lock_old_issues.yaml @@ -0,0 +1,27 @@ +name: "Lock Old Issues" + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +jobs: + lock: + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v2 + with: + github-token: ${{ github.token }} + issue-lock-inactive-days: '60' + # issue-exclude-created-before: '' + # issue-exclude-labels: '' + # issue-lock-labels: '' + # issue-lock-comment: '' + # issue-lock-reason: 'resolved' + # pr-lock-inactive-days: '365' + # pr-exclude-created-before: '' + # pr-exclude-labels: '' + # pr-lock-labels: '' + # pr-lock-comment: '' + # pr-lock-reason: 'resolved' + process-only: 'issues' diff --git a/.gitignore b/.gitignore index 77f22a9..05dc8cd 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ support/test/csharp/*.exe* configurations/ venv/ test-base/ +tags diff --git a/.mergify.yml b/.mergify.yml index 09d3d83..0f02002 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -9,9 +9,8 @@ pull_request_rules: # CI https://doc.mergify.io/conditions.html#github-actions - status-success=PythonLint - status-success=VimscriptLint + - status-success=Linux - status-success=MacOS - - actions: &merge-actions merge: method: merge diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py index f2e32ae..6f42505 100644 --- a/.ycm_extra_conf.py +++ b/.ycm_extra_conf.py @@ -42,7 +42,17 @@ def Settings( **kwargs ): return { 'sys_path': [ p.join( PATH_TO_THIS_DIR, 'python3' ) - ] + ], + 'ls': { + 'python': { + 'analysis': { + 'extraPaths': [ + p.join( PATH_TO_THIS_DIR, 'python3' ), + ], + 'useLibraryCodeForTypes': True + } + } + } } if IgnoreExtraConf: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 578fd8f..adec034 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,6 +46,23 @@ The GitHub issue tracker is for *bug reports* and *features requests* for the Vimspector project, and on-topic comments and follow-ups to them. It is not for general discussion, general support or for any other purpose. +Please **search the issue tracker for similar issues** before creating a new +one. There's no point in duplication; if an existing open issue addresses your +problem, please comment there instead of creating a duplicate. However, if the +issue you found is **closed as resolved** (e.g. with a PR or the original user's +problem was resolved), raise a **new issue**, because you've found a new +problem. Reference the original issue if you think that's useful information. + +Closed issues which have been inactive for 60 days will be locked, this helps to +keep discussions focussed. If you believe you are still experiencing an issue +which has been closed, please raise a new issue, completing the issue template. + +If you do find a similar _open_ issue, **don't just post 'me too' or similar** +responses. This almost never helps resolve the issue, and just causes noise for +the maintainers. Only post if it will aid the maintainers in solving the issue; +if there are existing diagnostics requested in the thread, perform +them and post the results. + Please do not be offended if your Issue or comment is closed or hidden, for any of the following reasons: @@ -53,6 +70,7 @@ of the following reasons: * The issue or comment is off-topic * The issue does not represent a Vimspector bug or feature request * The issue cannot be reasonably reproduced using the minimal vimrc +* The issue is a duplicate of an existing issue * etc. Issue titles are important. It's not usually helpful to write a title like @@ -83,7 +101,7 @@ in the issue report. The minimal vimrc is in `support/test/minimal_vimrc` and can be used as follows: ``` -vim -Nu /path/to/vimspector/support/minimal_vimrc +vim --clean -Nu /path/to/vimspector/support/minimal_vimrc ``` ## Pull Requests diff --git a/README.md b/README.md index 42d4765..d198292 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ For a tutorial and usage overview, take a look at the [Vimspector website][website]. -For detailed explanatin of the `.vimspector.json` format, see the +For detailed explanation of the `.vimspector.json` format, see the [reference guide][vimspector-ref]. ![Build](https://github.com/puremourning/vimspector/workflows/Build/badge.svg?branch=master) [![Gitter](https://badges.gitter.im/vimspector/Lobby.svg)](https://gitter.im/vimspector/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) @@ -59,15 +59,16 @@ For detailed explanatin of the `.vimspector.json` format, see the * [Console autocompletion](#console-autocompletion) * [Log View](#log-view) * [Closing debugger](#closing-debugger) + * [Terminate debuggee](#terminate-debuggee) * [Debug profile configuration](#debug-profile-configuration) - * [C, C , Rust, etc.](#c-c-rust-etc) - * [C Remote debugging](#c-remote-debugging) - * [C Remote launch and attach](#c-remote-launch-and-attach) + * [C, C++, Rust, etc.](#c-c-rust-etc) + * [Data visualization / pretty printing](#data-visualization--pretty-printing) + * [C++ Remote debugging](#c-remote-debugging) + * [C++ Remote launch and attach](#c-remote-launch-and-attach) * [Rust](#rust) * [Python](#python) * [Python Remote Debugging](#python-remote-debugging) * [Python Remote launch and attach](#python-remote-launch-and-attach) - * [Legacy: vscode-python](#legacy-vscode-python) * [TCL](#tcl) * [C♯](#c) * [Go](#go) @@ -76,6 +77,7 @@ For detailed explanatin of the `.vimspector.json` format, see the * [Debug cli application](#debug-cli-application) * [JavaScript, TypeScript, etc.](#javascript-typescript-etc) * [Java](#java) + * [Hot code replace](#hot-code-replace) * [Usage with YouCompleteMe](#usage-with-youcompleteme) * [Other LSP clients](#other-lsp-clients) * [Lua](#lua) @@ -91,14 +93,14 @@ For detailed explanatin of the `.vimspector.json` format, see the * [Example](#example) * [FAQ](#faq) - + # Features and Usage The plugin is a capable Vim graphical debugger for multiple languages. -It's mostly tested for c++, python and TCL, but in theory supports any +It's mostly tested for C++, Python and TCL, but in theory supports any language that Visual Studio Code supports (but see caveats). The [Vimspector website][website] has an overview of the UI, along with basic @@ -143,23 +145,24 @@ runtime dependencies). They are categorised by their level of support: * `Supported` : Fully supported, frequently used and manually tested * `Experimental`: Working, but not frequently used and rarely tested * `Legacy`: No longer supported, please migrate your config +* `Retired`: No longer included or supported. -| Language | Status | Switch (for `install_gadget.py`) | Adapter (for `:VimspectorInstall`) | Dependencies | -|--------------------|--------------|------------------------------------|------------------------------------|--------------------------------------------| -| C, C++, Rust etc. | Tested | `--all` or `--enable-c` (or cpp) | vscode-cpptools | mono-core | -| Rust, C, C++, etc. | Supported | `--force-enable-rust` | CodeLLDB | Python 3 | -| Python | Tested | `--all` or `--enable-python` | debugpy | Python 2.7 or Python 3 | -| Go | Tested | `--enable-go` | vscode-go | Go, [Delve][] | -| TCL | Supported | `--all` or `--enable-tcl` | tclpro | TCL 8.5 | -| Bourne Shell | Supported | `--all` or `--enable-bash` | vscode-bash-debug | Bash v?? | -| Lua | Supported | `--all` or `--enable-lua` | local-lua-debugger-vscode | Node >=12.13.0, Npm, Lua interpreter | -| Node.js | Supported | `--force-enable-node` | vscode-node-debug2 | 6 < Node < 12, Npm | -| Javascript | Supported | `--force-enable-chrome` | debugger-for-chrome | Chrome | -| Java | Supported | `--force-enable-java ` | vscode-java-debug | Compatible LSP plugin (see [later](#java)) | -| C# (dotnet core) | Experimental | `--force-enable-csharp` | netcoredbg | DotNet core | -| C# (mono) | Experimental | `--force-enable-csharp` | vscode-mono-debug | Mono | -| F#, VB, etc. | Experimental | `--force-enable-fsharp` (or vbnet) | netcoredbg | DotNet core | -| Python.legacy | Legacy | `--force-enable-python.legacy` | vscode-python | Node 10, Python 2.7 or Python 3 | +| Language | Status | Switch (for `install_gadget.py`) | Adapter (for `:VimspectorInstall`) | Dependencies | +|--------------------|-----------|----------------------------------|------------------------------------|--------------------------------------------| +| C, C++, Rust etc. | Tested | `--all` or `--enable-c` (or cpp) | vscode-cpptools | mono-core | +| Rust, C, C++, etc. | Supported | `--force-enable-rust` | CodeLLDB | Python 3 | +| Python | Tested | `--all` or `--enable-python` | debugpy | Python 2.7 or Python 3 | +| Go | Tested | `--enable-go` | vscode-go | Node, Go, [Delve][] | +| TCL | Supported | `--all` or `--enable-tcl` | tclpro | TCL 8.5 | +| Bourne Shell | Supported | `--all` or `--enable-bash` | vscode-bash-debug | Bash v?? | +| Lua | Supported | `--all` or `--enable-lua` | local-lua-debugger-vscode | Node >=12.13.0, Npm, Lua interpreter | +| Node.js | Supported | `--force-enable-node` | vscode-node-debug2 | 6 < Node < 12, Npm | +| Javascript | Supported | `--force-enable-chrome` | debugger-for-chrome | Chrome | +| Java | Supported | `--force-enable-java ` | vscode-java-debug | Compatible LSP plugin (see [later](#java)) | +| C# (dotnet core) | Tested | `--force-enable-csharp` | netcoredbg | DotNet core | +| F#, VB, etc. | Supported | `--force-enable-[fsharp,vbnet]` | `, `--force-enable-vbnet` | netcoredbg | DotNet core | +| C# (mono) | _Retired_ | N/A | N/A | N/A | +| Python.legacy | _Retired_ | N/A | N/A | N/A | ## Other languages @@ -288,7 +291,7 @@ If you just want to try out vimspector without changing your vim config, there are example projects for a number of languages in `support/test`, including: * Python (`support/test/python/simple_python`) -* Go (`support/test/go/hello_world`) +* Go (`support/test/go/hello_world` and `support/test/go/name-starts-with-vowel`) * Nodejs (`support/test/node/simple`) * Chrome (`support/test/chrome/`) * etc. @@ -524,13 +527,6 @@ Example: "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7" ], "name": "cppdbg" - }, - "vscode-python": { - "command": [ - "node", - "${gadgetDir}/vscode-python/out/client/debugger/debugAdapter/main.js" - ], - "name": "vscode-python" } } } @@ -656,18 +652,23 @@ personal and so you should work out what you like and use vim's powerful mapping features to set your own mappings. To that end, Vimspector defines the following `` mappings: -* `VimspectorContinue` -* `VimspectorStop` -* `VimspectorRestart` -* `VimspectorPause` -* `VimspectorToggleBreakpoint` -* `VimspectorToggleConditionalBreakpoint` -* `VimspectorAddFunctionBreakpoint` -* `VimspectorStepOver` -* `VimspectorStepInto` -* `VimspectorStepOut` -* `VimspectorRunToCursor` -* `VimspectorBalloonEval` +| Mapping | Function | API | +| --- | --- | --- | +| `VimspectorContinue` | When debugging, continue. Otherwise start debugging. | `vimspector#Continue()` | +| `VimspectorStop` | Stop debugging. | `vimspector#Stop()` | +| `VimpectorRestart` | Restart debugging with the same configuration. | `vimspector#Restart()` | +| `VimspectorPause` | Pause debuggee. | `vimspector#Pause()` | +| `VimspectorToggleBreakpoint` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` | +| `VimspectorToggleConditionalBreakpoint` | Toggle conditional line breakpoint on the current line. | `vimspector#ToggleBreakpoint( { trigger expr, hit count expr } )` | +| `VimspectorAddFunctionBreakpoint` | Add a function breakpoint for the expression under cursor | `vimspector#AddFunctionBreakpoint( '' )` | +| `VimspectorRunToCursor` | Run to Cursor | `vimspector#RunToCursor()` | +| `VimspectorStepOver` | Step Over | `vimspector#StepOver()` | +| `VimspectorStepInto` | Step Into | `vimspector#StepInto()` | +| `VimspectorStepOut` | Step out of current function scope | `vimspector#StepOut()` | +| `VimspectorUpFrame` | Move up a frame in the current call stack | `vimspector#UpFrame()` | +| `VimspectorDownFrame` | Move down a frame in the current call stack | `vimspector#DownFrame()` | +| `VimspectorBalloonEval` | Evaluate expression under cursor (or visual) in popup | *internal* | + These map roughly 1-1 with the API functions below. @@ -695,17 +696,17 @@ 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 debuggee. | `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( '' )` | -| `F10` | Step Over | `vimspector#StepOver()` | -| `F11` | Step Into | `vimspector#StepInto()` | -| `Shift F11` | Step out of current function scope | `vimspector#StepOut()` | +| Key | Mapping | Function +| --- | --- | --- +| `F5` | `VimspectorContinue` | When debugging, continue. Otherwise start debugging. +| `Shift F5` | `VimspectorStop` | Stop debugging. +| `Ctrl Shift F5` | `VimspectorRestart` | Restart debugging with the same configuration. +| `F6` | `VimspectorPause` | Pause debuggee. +| `F9` | `VimspectorToggleBreakpoint` | Toggle line breakpoint on the current line. +| `Shift F9` | `VimspectorAddFunctionBreakpoint` | Add a function breakpoint for the expression under cursor +| `F10` | `VimspectorStepOver` | Step Over +| `F11` | `VimspectorStepInto` | Step Into +| `Shift F11` | `VimspectorStepOut` | Step out of current function scope ## Human Mode @@ -720,19 +721,19 @@ 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 debuggee. | `vimspector#Pause()` | -| `F9` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` | -| `F9` | Toggle conditional line breakpoint on the current line. | `vimspector#ToggleBreakpoint( { trigger expr, hit count expr } )` | -| `F8` | Add a function breakpoint for the expression under cursor | `vimspector#AddFunctionBreakpoint( '' )` | -| `F8` | Run to Cursor | `vimspector#RunToCursor()` | -| `F10` | Step Over | `vimspector#StepOver()` | -| `F11` | Step Into | `vimspector#StepInto()` | -| `F12` | Step out of current function scope | `vimspector#StepOut()` | +| Key | Mapping | Function +| --- | --- | --- +| `F5` | `VimspectorContinue` | When debugging, continue. Otherwise start debugging. +| `F3` | `VimspectorStop` | Stop debugging. +| `F4` | `VimspectorRestart` | Restart debugging with the same configuration. +| `F6` | `VimspectorPause` | Pause debuggee. +| `F9` | `VimspectorToggleBreakpoint` | Toggle line breakpoint on the current line. +| `F9` | `VimspectorToggleConditionalBreakpoint` | Toggle conditional line breakpoint on the current line. +| `F8` | `VimspectorAddFunctionBreakpoint` | Add a function breakpoint for the expression under cursor +| `F8` | `VimspectorRunToCursor` | Run to Cursor +| `F10` | `VimspectorStepOver` | Step Over +| `F11` | `VimspectorStepInto` | Step Into +| `F12` | `VimspectorStepOut` | Step out of current function scope In addition, I recommend adding a mapping to `VimspectorBalloonEval`, in normal and visual modes, for example: @@ -746,6 +747,13 @@ nmap di VimspectorBalloonEval xmap di VimspectorBalloonEval ``` +You may also wish to add mappings for up/down the stack, for example: + +```viml +nmap VimspectorUpFrame +nmap VimspectorDownFrame +``` + # Usage and API This section defines detailed usage instructions, organised by feature. For most @@ -1000,6 +1008,8 @@ be changed manually to "switch to" that thread. to set the "focussed" thread to the currently selected one. If the selected line is a stack frame, set the focussed thread to the thread of that frame and jump to that frame in the code window. +* The current frame when a breakpoint is hit or if manuall jumping is also + highlighted. ![stack trace](https://puremourning.github.io/vimspector-web/img/vimspector-callstack-window.png) @@ -1061,6 +1071,8 @@ information when something goes wrong that's not a Vim traceback. If you just want to see the Vimspector log file, use `:VimspectorToggleLog`, which will tail it in a little window (doesn't work on Windows). +You can see some debugging info with `:VimspectorDebugInfo` + ## Closing debugger To close the debugger, use: @@ -1165,6 +1177,38 @@ licensing. } ``` +### Data visualization / pretty printing + +Depending on the backend you need to enable pretty printing of complex types manually. + +* LLDB: Pretty printing is enabled by default + +* GDB: To enable gdb pretty printers, consider the snippet below. + It is not enough to have `set print pretty on` in your .gdbinit! + +``` +{ + "configurations": { + "Launch": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "launch", + "program": "", + ... + "MIMode": "gdb" + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + } + } + } +} +``` + ### C++ Remote debugging The cpptools documentation describes how to attach cpptools to gdbserver using @@ -1250,10 +1294,6 @@ Rust is supported with any gdb/lldb-based debugger. So it works fine with headers/libs to build a C python extension for performance. * Full options: https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings - -**Migrating from `vscode-python`**: change `"adapter": "vscode-python"` to -`"adapter": "debugpy"`. - ```json { "configurations": { @@ -1320,34 +1360,6 @@ debugpy](https://github.com/microsoft/debugpy/wiki/Debugging-over-SSH). If you're feeling fancy, checkout the [reference guide][remote-debugging] for an example of getting Vimspector to remotely launch and attach. -### Legacy: vscode-python - -* No longer installed by default - please pass `--force-enable-python.legacy` if - you just want to continue using your working setup. -* [vscode-python](https://github.com/Microsoft/vscode-python) -* NOTE: You must be running `node` 10. See [this issue](https://github.com/puremourning/vimspector/issues/105) - -```json -{ - "configurations": { - ": Launch": { - "adapter": "vscode-python", - "configuration": { - "name": ": Launch", - "type": "python", - "request": "launch", - "cwd": "", - "stopOnEntry": true, - "console": "externalTerminal", - "debugOptions": [], - "program": "" - } - } - ... - } -} -``` - ## TCL * TCL (TclProDebug) @@ -1371,35 +1383,8 @@ netcoredbg` "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", "args": [], "stopAtEntry": true, - "cwd": "${workspaceRoot}" - } - } - } -} -``` - -* C# - mono - -Install with `install_gadget.py --force-enable-csharp` or `:VimspectorInstall -vscode-mono-debug`. - -***Known not to work.*** - -```json -{ - "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" + "env": {} } } } @@ -1416,6 +1401,8 @@ Requires: * [Delve][delve-install] 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 +NOTE: Vimspector uses the ["legacy" vscode-go debug adapter](https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md) rather than the "built-in" DAP support in Delve. You can track https://github.com/puremourning/vimspector/issues/186 for that. + ```json { "configurations": { @@ -1433,7 +1420,7 @@ Requires: ``` See the vscode-go docs for -[troubleshooting information](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#troubleshooting) +[troubleshooting information](https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md#troubleshooting) ## PHP @@ -1579,6 +1566,20 @@ editor plugin to use Java. I recommend [YouCompleteMe][], which has full support for jdt.ls, and most importantly a trivial way to load the debug adapter and to use it with Vimspector. +### Hot code replace + +When using the [java debug server][java-debug-server], Vimspector supports the +hot code replace custom feature. By default, when the underlying class files +change, vimspector asks the user if they wish to reload these classes at +runtime. + +This behaviour can be customised: + +* `let g:ycm_java_hotcodereplace_mode = 'ask'` - the default, ask the user for + each reload. +* `let g:ycm_java_hotcodereplace_mode = 'always'` - don't ask, always reload +* `let g:ycm_java_hotcodereplace_mode = 'never'` - don't ask, never reload + ### Usage with YouCompleteMe * Set up [YCM for java][YcmJava]. @@ -1738,22 +1739,26 @@ Vimsector uses them, they will not be replaced. So to customise the signs, define them in your `vimrc`. -| Sign | Description | Priority | -|------------------------|-------------------------------------|----------| -| `vimspectorBP` | Line breakpoint | 9 | -| `vimspectorBPCond` | Conditional line breakpoint | 9 | -| `vimspectorBPDisabled` | Disabled breakpoint | 9 | -| `vimspectorPC` | Program counter (i.e. current line) | 200 | -| `vimspectorPCBP` | Program counter and breakpoint | 200 | +| Sign | Description | Priority | +|---------------------------|-----------------------------------------|----------| +| `vimspectorBP` | Line breakpoint | 9 | +| `vimspectorBPCond` | Conditional line breakpoint | 9 | +| `vimspectorBPDisabled` | Disabled breakpoint | 9 | +| `vimspectorPC` | Program counter (i.e. current line) | 200 | +| `vimspectorPCBP` | Program counter and breakpoint | 200 | +| `vimspectorCurrentThread` | Focussed thread in stack trace view | 200 | +| `vimspectorCurrentFrame` | Current stack frame in stack trace view | 200 | The default symbols are the equivalent of something like the following: ```viml -sign define vimspectorBP text=\ ● texthl=WarningMsg -sign define vimspectorBPCond text=\ ◆ texthl=WarningMsg -sign define vimspectorBPDisabled text=\ ● texthl=LineNr -sign define vimspectorPC text=\ ▶ texthl=MatchParen linehl=CursorLine -sign define vimspectorPCBP text=●▶ texthl=MatchParen linehl=CursorLine +sign define vimspectorBP text=\ ● texthl=WarningMsg +sign define vimspectorBPCond text=\ ◆ texthl=WarningMsg +sign define vimspectorBPDisabled text=\ ● texthl=LineNr +sign define vimspectorPC text=\ ▶ texthl=MatchParen linehl=CursorLine +sign define vimspectorPCBP text=●▶ texthl=MatchParen linehl=CursorLine +sign define vimspectorCurrentThread text=▶ texthl=MatchParen linehl=CursorLine +sign define vimspectorCurrentFrame text=▶ texthl=Special linehl=CursorLine ``` If the signs don't display properly, your font probably doesn't contain these @@ -1761,11 +1766,13 @@ glyphs. You can easily change them by defining the sign in your vimrc. For example, you could put this in your `vimrc` to use some simple ASCII symbols: ```viml -sign define vimspectorBP text=o texthl=WarningMsg -sign define vimspectorBPCond text=o? texthl=WarningMsg -sign define vimspectorBPDisabled text=o! texthl=LineNr -sign define vimspectorPC text=\ > texthl=MatchParen -sign define vimspectorPCBP text=o> texthl=MatchParen +sign define vimspectorBP text=o texthl=WarningMsg +sign define vimspectorBPCond text=o? texthl=WarningMsg +sign define vimspectorBPDisabled text=o! texthl=LineNr +sign define vimspectorPC text=\ > texthl=MatchParen +sign define vimspectorPCBP text=o> texthl=MatchParen +sign define vimspectorCurrentThread text=> texthl=MatchParen +sign define vimspectorCurrentFrame text=> texthl=Special ``` ## Sign priority @@ -2042,6 +2049,10 @@ hi link jsonComment Comment Debug adapters (for some reason) send telemetry data to clients. Vimspector simply displays this information in the output window. It *does not* and *will not ever* collect, use, forward or otherwise share any data with any third parties. +10. Do I _have_ to put a `.vimspector.json` in the root of every project? No, you + can put all of your adapter and debug configs in a [single directory](https://puremourning.github.io/vimspector/configuration.html#debug-configurations) if you want to, but note + the caveat that `${workspaceRoot}` won't be calculated correctly in that case. + The vimsepctor author uses this [a lot](https://github.com/puremourning/.vim-mac/tree/master/vimspector-conf). [ycmd]: https://github.com/Valloric/ycmd diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 39af248..78c7c1b 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -13,6 +13,9 @@ " See the License for the specific language governing permissions and " limitations under the License. +if !has( 'python3' ) + finish +endif " Boilerplate {{{ let s:save_cpo = &cpoptions @@ -220,14 +223,6 @@ function! vimspector#SetVariableValue( ... ) abort endif endfunction -function! vimspector#AddDataBreakpoint( ... ) abort - if !s:Enabled() - return - endif - " TODO: how to set options? - py3 _vimspector_session.AddDataBreakpoint( {} ) -endfunction - function! vimspector#DeleteWatch() abort if !s:Enabled() return @@ -242,6 +237,20 @@ function! vimspector#GoToFrame() abort py3 _vimspector_session.ExpandFrameOrThread() endfunction +function! vimspector#UpFrame() abort + if !s:Enabled() + return + endif + py3 _vimspector_session.UpFrame() +endfunction + +function! vimspector#DownFrame() abort + if !s:Enabled() + return + endif + py3 _vimspector_session.DownFrame() +endfunction + function! vimspector#AddWatch( ... ) abort if !s:Enabled() return @@ -548,6 +557,14 @@ function! vimspector#ShowEvalBalloon( is_visual ) abort \ . '", 0 )' ) endfunction +function! vimspector#PrintDebugInfo() abort + if !s:Enabled() + return + endif + + py3 _vimspector_session.PrintDebugInfo() +endfunction + " Boilerplate {{{ let &cpoptions=s:save_cpo diff --git a/autoload/vimspector/internal/balloon.vim b/autoload/vimspector/internal/balloon.vim index 32d17ab..b607e51 100644 --- a/autoload/vimspector/internal/balloon.vim +++ b/autoload/vimspector/internal/balloon.vim @@ -69,14 +69,9 @@ function! vimspector#internal#balloon#CreateTooltip( is_hover, ... ) abort \ 'resize': 1, \ 'close': 'button', \ 'callback': 'vimspector#internal#balloon#CloseCallback', - \ 'mapping': 0 \ } - " When ambiwidth is single, use prettier characters for the border. This - " would look silly when ambiwidth is double. - if &ambiwidth ==# 'single' && &encoding ==? 'utf-8' - let config[ 'borderchars' ] = [ '─', '│', '─', '│', '╭', '╮', '┛', '╰' ] - endif + let config = vimspector#internal#popup#SetBorderChars( config ) if a:is_hover let config[ 'filter' ] = 'vimspector#internal#balloon#MouseFilter' @@ -86,6 +81,7 @@ function! vimspector#internal#balloon#CreateTooltip( is_hover, ... ) abort let config[ 'filter' ] = 'vimspector#internal#balloon#CursorFilter' let config[ 'moved' ] = 'any' let config[ 'cursorline' ] = 1 + let config[ 'mapping' ] = 0 let s:popup_win_id = popup_atcursor( body, config ) endif diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index 0cefc63..a398afe 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -159,15 +159,16 @@ function! s:_OnCommandEvent( category, id, data, event ) abort call setbufvar( buffer, '&modified', 0 ) endtry - " if the buffer is visible, scroll it + " if the buffer is visible, scroll it, but don't allow autocommands to fire, + " as this may close the current window! let w = bufwinnr( buffer ) if w > 0 let cw = winnr() try - execute w . 'wincmd w' - normal! Gz- + noautocmd execute w . 'wincmd w' + noautocmd normal! Gz- finally - execute cw . 'wincmd w' + noautocmd execute cw . 'wincmd w' endtry endif elseif a:event ==# 'exit' diff --git a/autoload/vimspector/internal/neopopup.vim b/autoload/vimspector/internal/neopopup.vim index cc25020..a734ca3 100644 --- a/autoload/vimspector/internal/neopopup.vim +++ b/autoload/vimspector/internal/neopopup.vim @@ -82,26 +82,54 @@ endfunction function! vimspector#internal#neopopup#Confirm( confirm_id, \ text, - \ default_value ) abort - let result = confirm( a:text, '&Yes &No &Default', 3 ) + \ options, + \ default_value, + \ keys ) abort - " Map the results to what popup_menu_filter would return (ok s:ConfirmCallback - " in popup.vim) - if result == 2 - " No is represented as 0 - let result = 0 - elseif result == 0 + " Neovim doesn't have an equivalent of popup_dialog, and it's way too much + " effort to write one, so we just use confirm()... + " Annoyingly we can't use confirm() here because for some reason it doesn't + " render properly in a channel callback. So we use input() and mimic dialog + " behaviour. + let prompt = a:text + for opt in a:options + let prompt .= ' ' . opt + endfor + let prompt .= ': ' + + try + let result = input( prompt, a:keys[ a:default_value - 1 ] ) + catch /.*/ + let result = -1 + endtry + + " Map the results to what the vim popup stuff would return (s:ConfirmCallback + " in popup.vim), i.e.: + " - 1-based index of selected item, or + " - -1 or 0 for cancellation + if result == '' " User pressed ESC/ctrl-c let result = -1 - elseif result == 3 - " Default - let result = a:default_value + else + let index = 1 + for k in a:keys + if k ==? result + let result = index + break + endif + let index += 1 + endfor + + if index > len( a:keys ) + let result = -1 + endif endif py3 __import__( 'vimspector', fromlist = [ 'utils' ] ).utils.ConfirmCallback( \ int( vim.eval( 'a:confirm_id' ) ), \ int( vim.eval( 'result' ) ) ) endfunction + " Boilerplate {{{ let &cpoptions=s:save_cpo unlet s:save_cpo diff --git a/autoload/vimspector/internal/popup.vim b/autoload/vimspector/internal/popup.vim index e8658ab..083fdf5 100644 --- a/autoload/vimspector/internal/popup.vim +++ b/autoload/vimspector/internal/popup.vim @@ -12,6 +12,7 @@ " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. " See the License for the specific language governing permissions and " limitations under the License. +scriptencoding utf-8 " Boilerplate {{{ @@ -32,12 +33,42 @@ function! vimspector#internal#popup#HideSplash( id ) abort call popup_hide( a:id ) endfunction -function! s:YesNoDefaultFilter( default_value, id, key ) abort - if a:key ==# "\" || a:key ==# 'D' || a:key ==# 'd' - call popup_close( a:id, a:default_value ) +let s:current_selection = 0 +let s:selections = [] +let s:text = [] + +function! s:UpdatePopup( id ) abort + let buf = copy( s:text ) + call extend( buf, s:DrawButtons() ) + call popup_settext( a:id, buf ) +endfunction + +function! s:ConfirmKeyFilter( keys, id, key ) abort + if a:key ==# "\" + call popup_close( a:id, s:current_selection + 1 ) + return 1 + elseif index( [ "\", "\" ], a:key ) >= 0 + let s:current_selection = ( s:current_selection + 1 ) % len( s:selections ) + call s:UpdatePopup( a:id ) + return 1 + elseif index( [ "\", "\" ], a:key ) >= 0 + let s:current_selection = s:current_selection == 0 + \ ? len( s:selections ) - 1: s:current_selection - 1 + call s:UpdatePopup( a:id ) + return 1 + elseif a:key ==# "\" || a:key ==# "\" + call popup_close( a:id, -1 ) + return 1 endif - return popup_filter_yesno( a:id, a:key ) + let index = 1 + for key in a:keys + if a:key ==? key + call popup_close( a:id, index ) + return 1 + endif + let index += 1 + endfor endfunction function! s:ConfirmCallback( confirm_id, id, result ) abort @@ -46,23 +77,69 @@ function! s:ConfirmCallback( confirm_id, id, result ) abort \ int( vim.eval( 'a:result' ) ) ) endfunction +function! s:SelectionPosition( idx ) abort + return a:idx == 0 ? 0 : len( join( s:selections[ : a:idx - 1 ], ' ' ) ) + 1 +endfunction + +function! s:DrawButtons() abort + return [ { + \ 'text': join( s:selections, ' ' ), + \ 'props': [ + \ { + \ 'col': s:SelectionPosition( s:current_selection ) + 1, + \ 'length': len( s:selections[ s:current_selection ] ), + \ 'type': 'VimspectorSelectedItem' + \ }, + \ ] + \ } ] +endfunction + function! vimspector#internal#popup#Confirm( \ confirm_id, \ text, - \ default_value ) abort - let text = a:text - if type( a:text ) != v:t_list - let text = [ a:text ] + \ options, + \ default_value, + \ keys ) abort + + silent! call prop_type_add( 'VimspectorSelectedItem', { + \ 'highlight': 'PMenuSel' + \ } ) + + let lines = split( a:text, "\n", v:true ) + let buf = [] + for line in lines + call add( buf, { 'text': line, 'props': [] } ) + endfor + + call add( buf, { 'text': '', 'props': [] } ) + + let s:selections = a:options + let s:current_selection = ( a:default_value - 1 ) + + let s:text = copy( buf ) + call extend( buf, s:DrawButtons() ) + + let config = { + \ 'callback': function( 's:ConfirmCallback', [ a:confirm_id ] ), + \ 'filter': function( 's:ConfirmKeyFilter', [ a:keys ] ), + \ 'mapping': v:false, + \ } + let config = vimspector#internal#popup#SetBorderChars( config ) + + return popup_dialog( buf, config ) +endfunction + +function! vimspector#internal#popup#SetBorderChars( config ) abort + " When ambiwidth is single, use prettier characters for the border. This + " would look silly when ambiwidth is double. + if &ambiwidth ==# 'single' && &encoding ==? 'utf-8' + let a:config[ 'borderchars' ] = [ '─', '│', '─', '│', '╭', '╮', '┛', '╰' ] endif - call extend( text, [ '', '(Y)es (N)o (D)efault' ] ) - - return popup_dialog( text, { - \ 'callback': function( 's:ConfirmCallback', [ a:confirm_id ] ), - \ 'filter': function( 's:YesNoDefaultFilter', [ a:default_value ] ) - \ } ) + return a:config endfunction + " Boilerplate {{{ let &cpoptions=s:save_cpo unlet s:save_cpo diff --git a/doc/vimspector-ref.txt b/doc/vimspector-ref.txt new file mode 100644 index 0000000..367d409 --- /dev/null +++ b/doc/vimspector-ref.txt @@ -0,0 +1,1085 @@ +*vimspector-ref* + +=============================================================================== +Contents ~ + + 1. Introduction |vimspector-ref-introduction| + 2. title: Configuration |vimspector-ref-title-configuration| + 3. Concepts |vimspector-ref-concepts| + 1. Debug adapter configuration |vimspector-ref-debug-adapter-configuration| + 2. Debug profile configuration |vimspector-ref-debug-profile-configuration| + 3. Replacements and variables |vimspector-ref-replacements-variables| + 1. The splat operator |vimspector-ref-splat-operator| + 2. Default values |vimspector-ref-default-values| + 3. Coercing Types |vimspector-ref-coercing-types| + 4. Configuration Format |vimspector-ref-configuration-format| + 5. Files and locations |vimspector-ref-files-locations| + 6. Adapter configurations |vimspector-ref-adapter-configurations| + 7. Debug configurations |vimspector-ref-debug-configurations| + 1. Configuration selection |vimspector-ref-configuration-selection| + 1. Specifying a default configuration |vimspector-ref-specifying-default-configuration| + 2. Preventing automatic selection |vimspector-ref-preventing-automatic-selection| + 2. Exception Breakpoints |vimspector-ref-exception-breakpoints| + 8. Predefined Variables |vimspector-ref-predefined-variables| + 9. Remote Debugging Support |vimspector-ref-remote-debugging-support| + 1. Python (debugpy) Example |vimspector-ref-python-example| + 2. C-family (gdbserver) Example |vimspector-ref-c-family-example| + 3. Docker Example |vimspector-ref-docker-example| + 10. Appendix: Configuration file format |vimspector-ref-appendix-configuration-file-format| + 11. Appendix: Editor configuration |vimspector-ref-appendix-editor-configuration| + 12. References |vimspector-ref-references| + +=============================================================================== + *vimspector-ref-introduction* +Introduction ~ + +=============================================================================== + *vimspector-ref-title-configuration* +title: Configuration ~ + +This document defines the supported format for project and adapter +configuration for Vimspector. + +- Concepts + + - Debug adapter configuration + - Debug profile configuration + - Replacements and variables + - The splat operator + - Default values + - Coercing Types + +- Configuration Format +- Files and locations +- Adapter configurations +- Debug configurations + + - Configuration selection + + - Specifying a default configuration + - Preventing automatic selection + + - Exception Breakpoints + +- Predefined Variables +- Remote Debugging Support + + - Python (debugpy) Example + - C-family (gdbserver) Example + - Docker Example + +- Appendix: Configuration file format +- Appendix: Editor configuration + +=============================================================================== + *vimspector-ref-concepts* +Concepts ~ + +As Vimspector supports debugging arbitrary projects, you need to tell it a few +details about what you want to debug, and how to go about doing that. + +In order to debug things, Vimspector requires a Debug Adapter which bridges +between Vimspector and the actual debugger tool. Vimspector can be used with +any debug adapter that implements the Debug Adapter Protocol [1]. + +For each debugging session, you provide a _debug configuration_ which includes +things like: + +- The debug adapter to use (and possibly how to launch and configure it). +- How to connect to the remote host, if remote debugging. +- How to launch or attach to your process. + +Along with optional additional configuration for things like: + +- Exception breakpoints + +------------------------------------------------------------------------------- + *vimspector-ref-debug-adapter-configuration* +Debug adapter configuration ~ + +The adapter to use for a particular debug session can be specified inline +within the _debug configuration_, but more usually the debug adapter is defined +separately and just referenced from the _debug configuration_. + +The adapter configuration includes things like: + +- How to launch or connect to the debug adapter +- How to configure it for PID attachment +- How to set up remote debugging, such as how to launch the process remotely + (for example, under 'gdbserver', 'ptvsd', etc.) + +------------------------------------------------------------------------------- + *vimspector-ref-debug-profile-configuration* +Debug profile configuration ~ + +Projects can have many different debug profiles. For example you might have all +of the following, for a given source tree: + +- Remotely launch c++ the process, and break on 'main' +- Locally Python test and break exception +- Remotely attach to a c++ process +- Locally launch a bash script +- Attach to a JVM listening on a port + +Each of these represents a different use case and a different _debug +configuration_. As mentioned above, a _debug configuration_ is essentially: + +- The adapter to use + +- The type of session (launch or attach), and whether or not to do it + remotely + +- The configuration to pass to the adapter in order to launch or attach to + the process. + +The bulk of the configuration is the last of these, which comprises +adapter-specific options, as the Debug Adapter Protocol does not specify any +standard for launch or attach configuration. + +------------------------------------------------------------------------------- + *vimspector-ref-replacements-variables* +Replacements and variables ~ + +Vimspector _debug configuration_ is intended to be as general as possible, and +to be committed to source control so that debugging your applications becomes a +simple, quick and pain-free habit (e.g. answering questions like "what happens +if..." with "just hit F5 and step through!"). + +Therefore it's important to abstract certain details, like runtime and +build-time paths, and to parameterise the _debug configuration_. Vimspector +provides a simple mechanism to do this with '${replacement}' style +replacements. + +The values available within the '${...}' are defined below, but in summary the +following are supported: + +- Environment variables, such as '${PATH}' +- Predefined variables, such as '${workspaceRoot}', '${file}' etc. +- Configuration-defined variables, either provided by the adapter + configuration or debug configuration, or from running a simple shell + command. +- Anything else you like - the user will be asked to provide a value. + +If the latter 2 are confusing, for now, suffice to say that they are how +Vimspector allows parameterisation of debug sessions. The [Vimspector +website][website-getting-started] has a good example of where this sort of +thing is useful: accepting the name of a test to run. + +But for now, consider the following example snippet: +> + { + "configurations": { + "example-debug-configuration": { + // This is a single-line comment explaining the purpose + "adapter": "example-adapter-name", + "variables": { + "SecretToken": { // Variables should start with upper-case letters + "shell" : [ "cat", "${HOME}/.secret_token" ] + } + }, + "configuration": { + "request": "launch" /* or it could be "attach" */, + "program": [ + "${fileBasenameNoExtension}", + "-c", "configuration_file.cfg", + "-u", "${USER}", + "--test-identifier", "${TestIdentifier}", + "--secret-token", "${SecretToken}" + ] + }, + "breakpoints": { + "exception": { + "caught": "", + "uncaught": "Y" + } + } + } + } + } +< +In this (fictitious) example the 'program' launch configuration item contains +the following variable substitutions: + +- '${fileBasenameNoExtension}' - this is a Predefined Variable, set by + Vimspector to the base name of the file that's opened in Vim, with its + extension removed ('/path/to/xyz.cc' -> 'xyz'). + +- '${USER}' - this refers to the Environment Variable 'USER'. + +- '${TestIdentifier}' - this variable is not defined, so the user is asked to + provide a value interactively when starting debugging. Vimspector remembers + what they said and provides it as the default should they debug again. + +- '${SecretToken}' - this variable is provided by the configuration's + 'variables' block. Its value is taken from the 'strip''d result of running + the shell command. Note these variables can be supplied by both the debug + and adapter configurations and can be either static strings or shell + commands. + +------------------------------------------------------------------------------- + *vimspector-ref-splat-operator* +The splat operator ~ + +Often we want to create a single '.vimspector.json' entry which encompasses +many use cases, as it is tedious to write every use case/start up option in +JSON. This is why we have the replacement variables after all. + +Frequently debug adapters request command arguments as a JSON array, for +example: +> + "args": [ "one", "two three", "four" ], +< +To help with this sort of case, Vimspector supports a 'splat' operator for +replacement variables operating within lists. The syntax is: '"*${var}', which +means roughly "splice the contents of '${var}' into the list at this position". +'${var}' is parsed like a shell command (using python's 'shlex' parser) and +each word is added as a list item. + +For example: +> + "args": [ "*${CommandLineArgs}" ] +< +This would: + +- Ask the user to provide the variable 'CommandLineArgs'. Let's say they + entered 'one "two three" four' +- Split 'CommandLineArgs' like shell arguments: 'one', 'two three' and 'four' +- Set 'args' in the settings dict to: '[ "one", "two three", "four" ]' + +You can also combine with static values: +> + "args": [ "First", "*${CommandLineArgs}", "Last" ] +< +This would yield the intuitive result: '[ "First", "one", "two three", "four", +"Last" ]' + +------------------------------------------------------------------------------- + *vimspector-ref-default-values* +Default values ~ + +You can specify replacements with default values. In this case if the user has +not specified a value, they are prompted but with the default value +pre-populated, allowing them to just press return to accept the default. + +The syntax is '${variableName:default value}'. The default value can contain +any character, but to include a '}' you must escape it with a backslash. To +include a backslash in the JSON you must write '\\', as in: +> + { "key": "${value:default {\\} stuff}" } +< +The default value can also be a replacement variable. However, this _must_ be a +variable that's already defined, such as one of the predefined variables, or +one specified in a 'variables' block. In order to reference them, you _must_ +use '${var}' syntax and you _must_ escape the closing '}'. For example, the is +a common and useful case: +> + { + "configuration": { + "program": "${script:${file\\}}" + } + } +< +This will prompt the user to specify 'script', but it will default to the path +to the current file. + +------------------------------------------------------------------------------- + *vimspector-ref-coercing-types* +Coercing Types ~ + +Sometimes, you want to provide an option for a boolean parameter, or want to +allow the user to specify more than just strings. Vimspector allows you to do +this, ensuring that the resulting JSON is valid. This is done by interpreting a +value as a JSON string and substituting the resulting JSON value in its place. + +This is easier to explain with an example. Let's say we want to offer the +ability to break on entry, as an option for the user. The launch configuration +requires 'stopOnEntry' to be a bool. This doesn't work: +> + "stopOnEntry": "${StopOnEntry}" +< +The reason is that if the user types 'true', the resulting object is: +> + "stopOnEntry": "true" +< +The problem being that is a string, not a boolean. So Vimspector allows you to +re-interpret the string as a JSON value and use that instead. To do this, add +'#json' to the key's name. You can even add a default, like this: +> + "stopOnEntry#json": "${stopOnEntry:true}" +< +If the user accepts the default, the resulting string '"true"' is coerced to a +JSON value 'true', and the suffix is stripped fom the key, resulting in the +following: +> + "stopOnEntry#json": true +< +Which is what we need. + +If you happen to have a key that already ends in '#json' (unlikely!), then you +can force Vimspector to treat the value as a string by appending '#s', as in: +> + "unlikelyKeyName#json#s": "this is a string, not JSON data" +< +**_Advanced usage:_** + +The most common usage for this is for number and bool types, but it works for +objects too. If you want to be able to specify a whole object (e.g. a whole +'env' dict), then you can do that too: +> + "env#json": "${Environment:{\\}}" +< +The default value here is '{}' (note the '}' must be escaped!). The user can +then enter something like '{ "MYVAR": "MyValue", "OTHER": "Other" }' and the +resulting object would be: +> + "env": { + "MYVAR": "MyValue", + "OTHER": "Other" + } +< +It also works for lists, though the splat operator is usually more convenient +for that. + +=============================================================================== + *vimspector-ref-configuration-format* +Configuration Format ~ + +All Vimspector configuration is defined in a JSON object. The complete +specification of this object is available in the JSON Schema [2], but the basic +format for the configuration object is: +> + { + "adapters": { }, + "configurations": { } + } +< +The 'adapters' key is actually optional, as '' can be +embedded within '', though this is not recommended usage. + +=============================================================================== + *vimspector-ref-files-locations* +Files and locations ~ + +The above configuration object is constructed from a number of configuration +files, by merging objects in a specified order. + +In a minimal sense, the only file required is a '.vimspector.json' file in the +root of your project which defines the full configuration object [2], but it is +usually useful to split the 'adapters' configuration into a separate file (or +indeed one file per debug adapter). + +The following sections describe the files that are read and use the following +abbreviations: + +- '' means the path to the Vimspector installation (such as + '$HOME/.vim/pack/vimspector/start/vimspector') + +- '' is either 'macos' or 'linux' depending on the host operating system. + +- '' is the Vim filetype. Where multiple filetypes are in effect, + typically all filetypes are checked. + +=============================================================================== + *vimspector-ref-adapter-configurations* +Adapter configurations ~ + +Vimspector reads a series of files to build the 'adapters' object. The +'adapters' objects are merged in such a way that a definition for an adapter +named 'example-adapter' in a later file _completely replaces_ a previous +definition. + +- '/gadgets//.gadgets.json' - the file written by + 'install_gadget.py' and not usually edited by users. + +- '/gadgets//.gadgets.d/*.json' (sorted alphabetically). + These files are user-supplied and override the above. + +- The first such '.gadgets.json' file found in all parent directories of the + file open in Vim. + +- The '.vimspector.json' and any filetype-specific configurations (see below) + +In all cases, the required format is: +> + { + "$schema": "https://puremourning.github.io/vimspector/schema/gadgets.schema.json#", + "adapters": { + "": { + + } + } + } +< +Each adapters block can define any number of adapters. As mentioned, if the +same adapter name exists in multiple files, the last one read takes precedence +and _completely replaces_ the previous configuration. In particular that means +you can't just override one option, you have to override the whole block. + +Adapter configurations are re-read at the start of each debug session. + +The specification for the gadget object is defined in the [gadget schema][]. + +=============================================================================== + *vimspector-ref-debug-configurations* +Debug configurations ~ + +There are two locations for debug configurations for a project: + +- '/configurations///*.json' +- '.vimspector.json' in the project source + +Typically, the debug configurations are read from '.vimspector.json'. The file +is found (like '.gadgets.json' above) by recursively searching up the directory +hierarchy from the directory of the file open in Vim. The first file found is +read and no further searching is done. + +Only a single '.vimspector.json' is read. If one is found, the location of this +file is used for '${workspaceRoot}' and other workspace-relative paths. + +In addition, users can create filetype-specific configurations in the +Vimspector installation directory. This can be useful where the parameters for +the debug session for a particular filetype are always known in advance, or can +always be entered by the user. This allows for debugging to "just work" without +any modification to the project source (no need to add a '.vimspector.json'). +In this case, the '${workspaceRoot}' and workspace-relative paths are +interpreted relative to the file open in Vim. This isn't ideal, but there is no +other obvious way to default this variable. + +As with gadgets, any debug configurations appearing within '.vimspector.json' +override any that appear in the common configuration dir. + +Debug configurations are re-read at the start of each debug session, so +modifications are picked up without any restarts of Vim. + +The specification for the gadget object is defined in the schema [2], but a +typical example looks like this: +> + { + "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#", + "configurations": { + "": { + "adapter": "", + "configuration": { + "request": "", + + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-ref-configuration-selection* +Configuration selection ~ + +When starting debugging, you can specify which debug configuration to launch +with "call vimspector#LaunchWithSettings( #{ configuration: 'name here' } )". + +Otherwise, if there's only one configuration found, Vimspector will use that +configuration, unless it contains a key '"autoselect": false'. + +If multiple debug configurations are found, and no explicit configuration was +selected on Launch, the user is prompted to select a configuration, unless a +single debug configuration is found with a key '"default": true'. + +------------------------------------------------------------------------------- + *vimspector-ref-specifying-default-configuration* +Specifying a default configuration ~ + +As noted, you can specify a default configuration with '"default": true': +> + { + "configurations": { + "use this one": { + "default": true, + "adapter": " ... ", + "configuation": { + // ... + } + }, + "don't use this one": { + // ... + } + } + } +< +If multiple configurations are found with 'default' set to 'true', then the +user is prompted anyway. + +------------------------------------------------------------------------------- + *vimspector-ref-preventing-automatic-selection* +Preventing automatic selection ~ + +If you don't want a configuration to be selected automatically, then set +'"autoselect": false'. This particularly useful for configurations in the +central (as opposed to project-local) directory. For example: +> + "configurations": { + "Don't use this by default!": { + "autoselect": false, + "adapter": " ... ", + "configuation": { + // ... + } + } + } +< +Setting 'autoselect' to 'false' overrides setting 'default' to 'true'. + +------------------------------------------------------------------------------- + *vimspector-ref-exception-breakpoints* +Exception Breakpoints ~ + +Debug adapters have arbitrary configuration for exception breakpoints. Normally +this is presented as a series of question to the user on starting the debug +session. The question includes the name of the exception breakpoint option, the +default and the list of valid responses (usually 'Y' or 'N'). + +You can pre-configure the answers to these questions in the 'breakpoints' +section of the debug configuration. For each question, take the name provided +and configure the response 'exception' mapping in the 'breakpoints' mapping. If +the configured response is empty string, the debug adapter default will be +used. + +Referring to the above example, the following tells the debug adapter to use +the default value for 'caught' exceptions and to break on 'uncaught' exception: +> + { + "configurations": { + "example-debug-configuration": { + "adapter": "example-adapter-name", + "breakpoints": { + "exception": { + "caught": "", + "uncaught": "Y" + } + }, + ... +< +The keys in the 'exception' mapping are what Vimspector includes in the prompt. +For example, when prompted with the following: +> + cpp_throw: Break on C++: on throw (Y/N/default: Y)? +< +The exception breakpoint "type" is 'cpp_throw' and the default is 'Y'. + +Similarly: +> + cpp_catch: Break on C++: on catch (Y/N/default: N)? +< +The exception breakpoint "type" is 'cpp_catch' and the default is 'N'. + +Use the following to set the values in configuration and not get asked: +> + "configurations": { + "example-debug-configuration": { + "adapter": "example-adapter-name", + "breakpoints": { + "exception": { + "cpp_throw": "Y", + "cpp_catch": "Y" + } + }, +< +To just accept the defaults for these exception breakpoint types, don't specify +a value, as in : +> + "configurations": { + "example-debug-configuration": { + "adapter": "example-adapter-name", + "breakpoints": { + "exception": { + "cpp_throw": "", + "cpp_catch": "" + } + }, +< +=============================================================================== + *vimspector-ref-predefined-variables* +Predefined Variables ~ + +The following variables are provided: + +- '${dollar}' - has the value '$', can be used to enter a literal dollar +- '$$' - a literal dollar +- '${workspaceRoot}' - the path of the folder where '.vimspector.json' was + found +- '${workspaceFolder}' - the path of the folder where '.vimspector.json' was + found +- '${gadgetDir}' - path to the OS-specific gadget dir ('/gadgets/') +- '${file}' - the current opened file +- '${relativeFile}' - the current opened file relative to 'workspaceRoot' +- '${fileBasename}' - the current opened file's 'basename' +- '${fileBasenameNoExtension}' - the current opened file's 'basename' with no + file extension +- '${fileDirname}' - the current opened file's 'dirname' +- '${fileExtname}' - the current opened file's extension +- '${cwd}' - the current working directory of the active window on launch +- '${unusedLocalPort}' - an unused local TCP port + +=============================================================================== + *vimspector-ref-remote-debugging-support* +Remote Debugging Support ~ + +Vimspector has in-built support for executing remote debuggers (such as +'gdbserver', 'debugpy', 'llvm-server' etc.). This is useful for environments +where the development is done on one host and the runtime is some other host, +account, container, etc. + +In order for it to work, you have to set up paswordless SSH between the local +and remote machines/accounts. Then just tell Vimspector how to remotely launch +and/or attach to the app. + +This is presented as examples with commentary, as it's a fairly advanced/niche +case. If you're not already familiar with remote debugging tools (such as +gdbserver) or not familiar with ssh or such, you might need to independently +research that. + +Vimspector's tools are intended to automate your existing process for setting +this up rather than to offer batteries-included approach. Ultimately, all +Vimspector is going to do is run your commands over SSH, or docker, and +co-ordinate with the adapter. + +------------------------------------------------------------------------------- + *vimspector-ref-python-example* +Python (debugpy) Example ~ + +Here is some examples using the Vimspector built-in remote support (using SSH) +to remotely launch and attach a python application and connect to it using +debugpy. + +The usage pattern is to hit '', enter 'host' (the host where your app +runs), 'account' (the account it runs under), and 'port' (a port that will be +opened on the remote host). Vimspector also supports exec'ing into Docker run +containers with 'container' (the container name or id your app is running in). +Vimspector then orchestrates the various tools to set you up. +> + { + "adapters": { + "python-remote": { + "port": "${port}", + "host": "${host}", + "launch": { + "remote": { + "host": "${host}", // Remote host to ssh to (mandatory if not using container) + "account": "${account}", // User to connect as (optional) + + // Optional.... Manual additional arguments for ssh + // "ssh": { + // "args": [ "-o", "StrictHostKeyChecking=no" ] + // }, + + // Command to launch the debugee and attach the debugger; + // %CMD% replaced with the remote-cmdLine configured in the launch + // configuration. (mandatory) + "runCommand": [ + "python", "-m", "debugpy", + "--listen", "0.0.0.0:${port}", + "--wait-for-client", + "%CMD%" + ] + + // Optional alternative to runCommand (if you need to run multiple + // commands) + // "runCommands": [ + // [ /* first command */ ], + // [ /* second command */ ] + // ] + + } + + // optional delay to wait after running runCommand(s). This is often + // needed because of the way docker handles TCP, or if you're using some + // wrapper (e.g. to start the JVM) + // "delay": "1000m" // format as per :help sleep + }, + "attach": { + "remote": { + "host": "${host}", // Remote host to ssh to (mandatory if not using container) + "account": "${account}", // User to connect as (optional) + // Command to get the PID of the process to attach (mandatory) + "pidCommand": [ + // + // Remember taht you can use ${var} to ask for input. I use this to + // call a custom command to returm the PID for a named service, so + // here's an examle: + // + "/path/to/secret/script/GetPIDForService", "${ServiceName}" + ], + + // Command to attach the debugger; %PID% replaced with output of + // pidCommand above (mandatory) + "attachCommand": [ + "python", "-m", "debugpy", "--listen", "0.0.0.0:${port}", + "--pid", "%PID%" + ] + + // Optional alternative to attachCommand (if you need to run multiple + // commands) + // "attachCommands": [ + // [ /* first command */ ], + // [ /* second command */ ] + // ], + + // Optional.... useful with buggy gdbservers to kill -TRAP %PID% + // "initCompleteCommand": [ + // /* optional command to run after initialized */ + // ] + + // Optional.... Manual additional arguments for ssh + // "ssh": { + // "args": [ "-o", "StrictHostKeyChecking=no" ] + // }, + } + // optional delay to wait after running runCommand(s). This is often + // needed because of the way docker handles TCP, or if you're using some + // wrapper (e.g. to start the JVM) + // "delay": "1000m" // format as per :help sleep + } + } + }, + "configurations": { + "remote-launch": { + "adapter": "python-remote", + + "remote-request": "launch", + "remote-cmdLine": [ + "${RemoteRoot}/${fileBasename}", "*${args}" + ], + + "configuration": { + "request": "attach", + "pathMappings": [ + { + "localRoot": "${workspaceRoot}", + "remoteRoot": "${RemoteRoot}" + } + ] + } + }, + "remote-attach": { + "variables": { + // Just an example of how to specify a variable manually rather than + // vimspector asking for input from the user + "ServiceName": "${fileBasenameNoExtention}" + }, + + "adapter": "python-remote", + "remote-request": "attach", + + "configuration": { + "request": "attach", + "pathMappings": [ + { + "localRoot": "${workspaceRoot}", + "remoteRoot": "${RemoteRoot}" + } + ] + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-ref-c-family-example* +C-family (gdbserver) Example ~ + +This example uses Vimspector to remotely launch or attach to a binary using +'gdbserver' and then instructs vscode-cpptools to attach to that 'gdbserver'. + +The approach is very similar to the above for python, just that we use +gdbserver and have to tell cpptools a few more options. +> + { + "adapters": { + "cpptools-remote": { + "command": [ + "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7" + ], + "name": "cppdbg", + "configuration": { + "type": "cppdbg" + }, + "launch": { + "remote": { + "host": "${host}", + "account": "${account}", + "runCommand": [ + "gdbserver", + "--once", + "--no-startup-with-shell", + "--disable-randomisation", + "0.0.0.0:${port}", + "%CMD%" + } + }, + "attach": { + "remote": { + "host": "${host}", + "account": "${account}", + "pidCommand": [ + "/path/to/secret/script/GetPIDForService", "${ServiceName}" + ], + "attachCommand": [ + "gdbserver", + "--once", + "--attach", + "0.0.0.0:${port}", + "%PID%" + ], + // + // If your application is started by a wrapper script, then you might + // need the followin. GDB can't pause an application because it only + // sends the signal to the process group leader. Or something. + // Basically, if you find that everything just hangs and the + // application never attaches, try using the following to manually + // force the trap signal. + // + "initCompleteCommand": [ + "kill", + "-TRAP", + "%PID%" + ] + } + } + } + }, + "configurations": { + "remote launch": { + "adapter": "cpptools-remote", + "remote-cmdLine": [ "/path/to/the/remote/executable", "args..." ], + "remote-request": "launch", + "configuration": { + "request": "attach", // yes, attach! + + "program": "/path/to/the/local/executable", + "MIMode": "gdb", + "miDebuggerAddress": "${host}:${port}" + } + }, + "remote attach": { + "adapter": "cpptools-remote", + "remote-request": "attach", + "configuration": { + "request": "attach", + + "program": "/path/to/the/local/executable", + "MIMode": "gdb", + "miDebuggerAddress": "${host}:${port}" + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-ref-docker-example* +Docker Example ~ + +This example uses Vimspector to remotely launch or attach to a docker container +port. +> + { + "adapters": { + "python-remote": { + "port": "${port}", + "launch": { + "remote": { + "container": "${container}", // Docker container id or name to exec into to. + + // Command to launch the debugee and attach the debugger; + // %CMD% replaced with the remote-cmdLine configured in the launch + // configuration. (mandatory) + "runCommand": [ + "python", "-m", "debugpy", + "--listen", "0.0.0.0:${port}", + "--wait-for-client", + "%CMD%" + ] + + // Optional alternative to runCommand (if you need to run multiple + // commands) + // "runCommands": [ + // [ /* first command */ ], + // [ /* second command */ ] + // ] + + } + + // optional delay to wait after running runCommand(s). This is often + // needed because of the way docker handles TCP + "delay": "1000m" // format as per :help sleep + }, + "attach": { + "remote": { + "container": "${container}", // Docker container id or name to exec into. + // Command to get the PID of the process to attach (mandatory) + // This command gets appended to "docker exec ${container}" + "pidCommand": [ + // + // Remember taht you can use ${var} to ask for input. I use this to + // call a custom command to returm the PID for a named service, so + // here's an examle: + // + "sh", "-c", "pgrep", "-f", "${filename}" + ], + + // Command to attach the debugger; %PID% replaced with output of + // pidCommand above (mandatory) + "attachCommand": [ + "sh", "-c", "python", "-m", "debugpy", "--listen", "0.0.0.0:${port}", + "--pid", "%PID%" + ] + + // Optional alternative to attachCommand (if you need to run multiple + // commands) + // "attachCommands": [ + // [ /* first command */ ], + // [ /* second command */ ] + // ], + + // Optional.... useful with buggy gdbservers to kill -TRAP %PID% + // "initCompleteCommand": [ + // /* optional command to run after initialized */ + // ] + + } + + // optional delay to wait after running runCommand(s). This is often + // needed because of the way docker handles TCP, or if you're using some + // wrapper (e.g. to start the JVM) + "delay": "1000m" // format as per :help sleep + } + } + }, + "configurations": { + "remote-launch": { + "adapter": "python-remote", + + "remote-request": "launch", + "remote-cmdLine": [ + "${RemoteRoot}/${fileBasename}", "*${args}" + ], + + "configuration": { + "request": "attach", + "pathMappings": [ + { + "localRoot": "${workspaceRoot}", + "remoteRoot": "${RemoteRoot}" + } + ] + } + }, + "remote-attach": { + "variables": { + // Just an example of how to specify a variable manually rather than + // vimspector asking for input from the user + "FileName": "${fileName}" + }, + + "adapter": "python-remote", + "remote-request": "attach", + + "configuration": { + "request": "attach", + "pathMappings": [ + { + "localRoot": "${workspaceRoot}", + "remoteRoot": "${RemoteRoot}" + } + ] + } + } + } + } +< +=============================================================================== + *vimspector-ref-appendix-configuration-file-format* +Appendix: Configuration file format ~ + +The configuration files are text files which must be UTF-8 encoded. They +contain a single JSON object, along with optional comments. + +Comments are "c-style", i.e.: + +- '// single line comment ...' +- '/* inline comment */' + +There is much debate about whether JSON files should contain comments. I have +added them because they are useful in the context of configuration files. +Unforutnately this may mean your editor doesn't like them (they are strictly +invalid JSON) so it's up to you if you use them. + +Technically, Vimspector uses JSON minify [3] to strip comments before parsing +the JSON. + +=============================================================================== + *vimspector-ref-appendix-editor-configuration* +Appendix: Editor configuration ~ + +If you would like some assistance with writing the JSON files, and your editor +of choice has a way to use a language server, you can use the VSCode JSON +language server [4]. + +It is recommended to include the '$schema' declaration as in the above +examples, but if that isn't present, the following JSON language server +configuration [5] is recommened to load the schema from the Internet: +> + { + "json": { + "schemas": [ + { + "fileMatch": [ ".vimspector.json" ], + "url": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json" + }, + { + "fileMatch": [ ".gadgets.json", ".gadgets.d/*.json" ], + "url": "https://puremourning.github.io/vimspector/schema/gadgets.schema.json" + } + ] + } + } +< +If your language server client of choice happens to be YouCompleteMe [6], then +the following '.ycm_extra_conf.py' is good enough to get you going, after +following the instructions in the lsp-examples [7] repo to get the server set +up: +> + VIMSPECTOR_HOME = '/path/to/vimspector' # TODO: Change this + + def Settings( **kwargs ): + if kwargs[ 'language' ] == 'json': + return { + 'ls': { + 'json': { + 'schemas': [ + { + 'fileMatch': [ '.vimspector.json' ], + 'url': f'file://{VIMSPECTOR_HOME}/docs/schema/vimspector.schema.json' + }, + { + 'fileMatch': [ '.gadgets.json', '.gadgets.d/*.json' ], + 'url': f'file://{VIMSPECTOR_HOME}/docs/schema/gadgets.schema.json' + } + ] + } + } + } + + return None # Or your existing Settings definition.... +< +This configuration can be adapted to any other LSP-based editor configuration +and is provided just as an example. + +=============================================================================== + *vimspector-ref-references* +References ~ + +[1] https://microsoft.github.io/debug-adapter-protocol/ +[2] http://puremourning.github.io/vimspector/schema/vimspector.schema.json +[3] https://github.com/getify/JSON.minify +[4] https://github.com/vscode-langservers/vscode-json-languageserver +[5] https://github.com/vscode-langservers/vscode-json-languageserver#settings +[6] https://github.com/ycm-core/YouCompleteMe +[7] https://github.com/ycm-core/lsp-examples + +vim: ft=help diff --git a/doc/vimspector.txt b/doc/vimspector.txt new file mode 100644 index 0000000..8def87f --- /dev/null +++ b/doc/vimspector.txt @@ -0,0 +1,2394 @@ +*vimspector* vimspector - A multi language graphical debugger for Vim + +=============================================================================== +Contents ~ + + 1. Introduction |vimspector-introduction| + 2. Features and Usage |vimspector-features-usage| + 1. Supported debugging features |vimspector-supported-debugging-features| + 2. Supported languages |vimspector-supported-languages| + 3. Other languages |vimspector-other-languages| + 3. Installation |vimspector-installation| + 1. Quick Start |vimspector-quick-start| + 2. Dependencies |vimspector-dependencies| + 3. Neovim differences |vimspector-neovim-differences| + 4. Windows differences |vimspector-windows-differences| + 5. Trying it out |vimspector-trying-it-out| + 6. Cloning the plugin |vimspector-cloning-plugin| + 7. Install some gadgets |vimspector-install-gadgets| + 1. VimspectorInstall and VimspectorUpdate commands |vimspectorinstall-vimspectorupdate-commands| + 2. install_gadget.py |vimspector-install_gadget.py| + 8. Manual gadget installation |vimspector-manual-gadget-installation| + 1. The gadget directory |vimspector-gadget-directory| + 9. Upgrade |vimspector-upgrade| + 4. About |vimspector-about| + 1. Background |vimspector-background| + 2. Status |vimspector-status| + 1. Experimental |vimspector-experimental| + 3. Motivation |vimspector-motivation| + 4. License |vimspector-license| + 5. Sponsorship |vimspector-sponsorship| + 5. Mappings |vimspector-mappings| + 1. Visual Studio / VSCode |vimspector-visual-studio-vscode| + 2. Human Mode |vimspector-human-mode| + 6. Usage and API |vimspector-usage-api| + 1. Launch and attach by PID: |vimspector-launch-attach-by-pid| + 1. Launch with options |vimspector-launch-with-options| + 2. Debug configuration selection |vimspector-debug-configuration-selection| + 3. Get configurations |vimspector-get-configurations| + 2. Breakpoints |vimspector-breakpoints| + 1. Summary |vimspector-summary| + 2. Line breakpoints |vimspector-line-breakpoints| + 3. Conditional breakpoints |vimspector-conditional-breakpoints| + 4. Exception breakpoints |vimspector-exception-breakpoints| + 5. Clear breakpoints |vimspector-clear-breakpoints| + 6. Run to Cursor |vimspector-run-to-cursor| + 3. Stepping |vimspector-stepping| + 4. Variables and scopes |vimspector-variables-scopes| + 5. Variable or selection hover evaluation |vimspector-variable-or-selection-hover-evaluation| + 6. Watches |vimspector-watches| + 1. Watch autocompletion |vimspector-watch-autocompletion| + 7. Stack Traces |vimspector-stack-traces| + 8. Program Output |vimspector-program-output| + 1. Console |vimspector-console| + 2. Console autocompletion |vimspector-console-autocompletion| + 3. Log View |vimspector-log-view| + 9. Closing debugger |vimspector-closing-debugger| + 10. Terminate debuggee |vimspector-terminate-debuggee| + 7. Debug profile configuration |vimspector-debug-profile-configuration| + 1. C, C++, Rust, etc. |vimspector-c-c-rust-etc.| + 1. C++ Remote debugging |vimspector-c-remote-debugging| + 2. C++ Remote launch and attach |vimspector-c-remote-launch-attach| + 2. Rust |vimspector-rust| + 3. Python |vimspector-python| + 1. Python Remote Debugging |vimspector-python-remote-debugging| + 2. Python Remote launch and attach |vimspector-python-remote-launch-attach| + 3. Legacy: vscode-python |vimspector-legacy-vscode-python| + 4. TCL |vimspector-tcl| + 5. C♯ |vimspector-c| + 6. Go |vimspector-go| + 7. PHP |vimspector-php| + 1. Debug web application |vimspector-debug-web-application| + 2. Debug cli application |vimspector-debug-cli-application| + 8. JavaScript, TypeScript, etc. |vimspector-javascript-typescript-etc.| + 9. Java |vimspector-java| + 1. Usage with YouCompleteMe |vimspector-usage-with-youcompleteme| + 2. Other LSP clients |vimspector-other-lsp-clients| + 10. Lua |vimspector-lua| + 11. Other servers |vimspector-other-servers| + 8. Customisation |vimspector-customisation| + 1. Changing the default signs |vimspector-changing-default-signs| + 2. Sign priority |vimspector-sign-priority| + 3. Changing the default window sizes |vimspector-changing-default-window-sizes| + 4. Changing the terminal size |vimspector-changing-terminal-size| + 5. Custom mappings while debugging |vimspector-custom-mappings-while-debugging| + 6. Advanced UI customisation |vimspector-advanced-ui-customisation| + 7. Customising the WinBar |vimspector-customising-winbar| + 8. Example |vimspector-example| + 9. FAQ |vimspector-faq| + 10. References |vimspector-references| + +=============================================================================== + *vimspector-introduction* +Introduction ~ + +For a tutorial and usage overview, take a look at the Vimspector website [1]. + +For detailed explanatin of the '.vimspector.json' format, see the reference +guide [2]. + +Image: Build (see reference [3]) Image: Gitter [4] + +- Features and Usage + + - Supported debugging features + - Supported languages + - Other languages + +- Installation + + - Quick Start + - Dependencies + - Neovim differences + - Windows differences + - Trying it out + - Cloning the plugin + - Install some gadgets + - VimspectorInstall and VimspectorUpdate commands + - install_gadget.py + - Manual gadget installation + - The gadget directory + - Upgrade + +- About + + - Background + - Status + - Experimental + - Motivation + - License + - Sponsorship + +- Mappings + + - Visual Studio / VSCode + - Human Mode + +- Usage and API + + - Launch and attach by PID: + - Launch with options + - Debug configuration selection + - Get configurations + - Breakpoints + - Summary + - Line breakpoints + - Conditional breakpoints + - Exception breakpoints + - Clear breakpoints + - Run to Cursor + - Stepping + - Variables and scopes + - Variable or selection hover evaluation + - Watches + - Watch autocompletion + - Stack Traces + - Program Output + - Console + - Console autocompletion + - Log View + - Closing debugger + +- Debug profile configuration + + - C, C , Rust, etc. + - C Remote debugging + - C Remote launch and attach + - Rust + - Python + - Python Remote Debugging + - Python Remote launch and attach + - Legacy: vscode-python + - TCL + - C♯ + - Go + - PHP + - Debug web application + - Debug cli application + - JavaScript, TypeScript, etc. + - Java + - Usage with YouCompleteMe + - Other LSP clients + - Lua + - Other servers + +- Customisation + + - Changing the default signs + - Sign priority + - Changing the default window sizes + - Changing the terminal size + - Custom mappings while debugging + - Advanced UI customisation + - Customising the WinBar + - Example + +- FAQ + +=============================================================================== + *vimspector-features-usage* +Features and Usage ~ + +The plugin is a capable Vim graphical debugger for multiple languages. It's +mostly tested for c++, python and TCL, but in theory supports any language that +Visual Studio Code supports (but see caveats). + +The Vimspector website [1] has an overview of the UI, along with basic +instructions for configuration and setup. + +But for now, here's a (rather old) screenshot of Vimspector debugging Vim: + + Image: vimspector-vim-screenshot (see reference [6]) + +And a couple of brief demos: + + Image: asciicast [7] + + Image: asciicast [9] + +------------------------------------------------------------------------------- + *vimspector-supported-debugging-features* +Supported debugging features ~ + +- flexible configuration syntax that can be checked in to source control +- breakpoints (function, line and exception breakpoints) +- conditional breakpoints (function, line) +- step in/out/over/up, stop, restart +- run to cursor +- launch and attach +- remote launch, remote attach +- locals and globals display +- watch expressions with autocompletion +- variable inspection tooltip on hover +- set variable value in locals, watch and hover windows +- call stack display and navigation +- hierarchical variable value display popup (see + 'VimspectorBalloonEval') +- interactive debug console with autocompletion +- launch debuggee within Vim's embedded terminal +- logging/stdout display +- simple stable API for custom tooling (e.g. integrate with language server) + +------------------------------------------------------------------------------- + *vimspector-supported-languages* +Supported languages ~ + +The following table lists the languages that are "built-in" (along with their +runtime dependencies). They are categorised by their level of support: + +- 'Tested' : Fully supported, Vimspector regression tests cover them +- 'Supported' : Fully supported, frequently used and manually tested +- 'Experimental': Working, but not frequently used and rarely tested +- 'Legacy': No longer supported, please migrate your config + +======================================================================================================================================================== +| _Language_ | _Status_ | _Switch (for 'install_gadget.py')_ | _Adapter (for ':VimspectorInstall')_ | _Dependencies_ | +======================================================================================================================================================== +| C, C++, Rust etc. | Tested | '--all' or '--enable-c' (or cpp) | vscode-cpptools | mono-core | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Rust, C, C++, etc. | Supported | '--force-enable-rust' | CodeLLDB | Python 3 | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Python | Tested | '--all' or '--enable-python' | debugpy | Python 2.7 or Python 3 | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Go | Tested | '--enable-go' | vscode-go | Go, Delve [11] | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| TCL | Supported | '--all' or '--enable-tcl' | tclpro | TCL 8.5 | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Bourne Shell | Supported | '--all' or '--enable-bash' | vscode-bash-debug | Bash v?? | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Lua | Supported | '--all' or '--enable-lua' | local-lua-debugger-vscode | Node >=12.13.0, Npm, Lua interpreter | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Node.js | Supported | '--force-enable-node' | vscode-node-debug2 | 6 < Node < 12, Npm | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Javascript | Supported | '--force-enable-chrome' | debugger-for-chrome | Chrome | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Java | Supported | '--force-enable-java' | vscode-java-debug | Compatible LSP plugin (see later) | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| C# (dotnet core) | Experimental | '--force-enable-csharp' | netcoredbg | DotNet core | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| C# (mono) | Experimental | '--force-enable-csharp' | vscode-mono-debug | Mono | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| F#, VB, etc. | Experimental | '--force-enable-fsharp' (or vbnet) | netcoredbg | DotNet core | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Python.legacy | Legacy | '--force-enable-python.legacy' | vscode-python | Node 10, Python 2.7 or Python 3 | +-------------------------------------------------------------------------------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- + *vimspector-other-languages* +Other languages ~ + +Vimspector should work for any debug adapter that works in Visual Studio Code. + +To use Vimspector with a language that's not "built-in", see this wiki page +[12]. + +=============================================================================== + *vimspector-installation* +Installation ~ + +------------------------------------------------------------------------------- + *vimspector-quick-start* +Quick Start ~ + +There are 2 installation methods: + +- Using a release tarball and vim packages +- Using a clone of the repo (e.g. package manager) + +Release tarballs come with debug adapters for the default languages +pre-packaged. To use a release tarball: + +1. Check the dependencies +2. Untar the release tarball for your OS into '$HOME/.vim/pack': +> + $ mkdir -p $HOME/.vim/pack + $ curl -L | tar -C $HOME/.vim/pack zxvf - +< +1. Add 'packadd! vimspector' to you '.vimrc' + +2. (optionally) Enable the default set of mappings: +> + let g:vimspector_enable_mappings = 'HUMAN' +< +1. Configure your project's debug profiles (create '.vimspector.json') + +Alternatively, you can clone the repo and select which gadgets are installed: + +1. Check the dependencies +2. Install the plugin as a Vim package. See ':help packages'. +3. Add 'packadd! vimspector' to you '.vimrc' +4. Install some 'gadgets' (debug adapters) - see ':VimspectorInstall ...' +5. Configure your project's debug profiles (create '.vimspector.json') + +If you prefer to use a plugin manager, see the plugin manager's docs. For +Vundle, use: +> + Plugin 'puremourning/vimspector' +< +The following sections expand on the above brief overview. + +------------------------------------------------------------------------------- + *vimspector-dependencies* +Dependencies ~ + +Vimspector requires: + +- One of: +- Vim 8.2 Huge build compiled with Python 3.6 or later +- Neovim 0.4.3 with Python 3.6 or later (experimental) +- One of the following operating systems: +- Linux +- macOS Mojave or later +- Windows (experimental) + +Why such a new vim ? Well 2 reasons: + +1. Because vimspector uses a lot of new Vim features +2. Because there are Vim bugs that vimspector triggers that will frustrate + you if you hit them. + +Why is neovim experimental? Because the author doesn't use neovim regularly, +and there are no regression tests for vimspector in neovim, so it may break +occasionally. Issue reports are handled on best-efforts basis, and PRs are +welcome to fix bugs. See also the next section descibing differences for neovim +vs vim. + +Why Windows support experimental? Because it's effort and it's not a priority +for the author. PRs are welcome to fix bugs. Windows will not be regularly +tested. + +Which Linux versions? I only test on Ubuntu 18.04 and later and RHEL 7. + +------------------------------------------------------------------------------- + *vimspector-neovim-differences* +Neovim differences ~ + +neovim doesn't implement some features Vimspector relies on: + +- WinBar - used for the buttons at the top of the code window and for + changing the output window's current output. + +- Prompt Buffers - used to send commands in the Console and add Watches. + (_Note_: prompt buffers are available in neovim nightly) + +- Balloons - this allows for the variable evaluation popup to be displayed + when hovering the mouse. See below for how to create a keyboard mapping + instead. + +Workarounds are in place as follows: + +- WinBar - There are mappings, ':VimspectorShowOutput' and ':VimspectorReset' + +- Prompt Buffers - There are ':VimspectorEval' and ':VimspectorWatch' + +- Balloons - There is the 'VimspectorBalloonEval' mapping. There is no + default mapping for this, so I recommend something like this to get + variable display in a popup: +> + " mnemonic 'di' = 'debug inspect' (pick your own, if you prefer!) + + " for normal mode - the word under the cursor + nmap di VimspectorBalloonEval + " for visual mode, the visually selected text + xmap di VimspectorBalloonEval +< +------------------------------------------------------------------------------- + *vimspector-windows-differences* +Windows differences ~ + +The following features are not implemented for Windows: + +- Tailing the vimspector log in the Output Window. + +------------------------------------------------------------------------------- + *vimspector-trying-it-out* +Trying it out ~ + +If you just want to try out vimspector without changing your vim config, there +are example projects for a number of languages in 'support/test', including: + +- Python ('support/test/python/simple_python') +- Go ('support/test/go/hello_world') +- Nodejs ('support/test/node/simple') +- Chrome ('support/test/chrome/') +- etc. + +To test one of these out, cd to the directory and run: +> + vim -Nu /path/to/vimspector/tests/vimrc --cmd "let g:vimspector_enable_mappings='HUMAN'" +< +Then press ''. + +There's also a C++ project in 'tests/testdata/cpp/simple/' with a 'Makefile' +which can be used to check everything is working. This is used by the +regression tests in CI so should always work, and is a good way to check if the +problem is your configuration rather than a bug. + +------------------------------------------------------------------------------- + *vimspector-cloning-plugin* +Cloning the plugin ~ + +If you're not using a release tarball, you'll need to clone this repo to the +appropriate place. + +1. Clone the plugin + +There are many Vim plugin managers, and I'm not going to state a particular +preference, so if you choose to use one, follow the plugin manager's +documentation. For example, for Vundle, use: +> + Plugin 'puremourning/vimspector' +< +If you don't use a plugin manager already, install vimspector as a Vim package +by cloning this repository into your package path, like this: +> + $ git clone https://github.com/puremourning/vimspector ~/.vim/pack/vimspector/opt/vimspector +< +1. Configure vimspector in your '.vimrc', for example to enable the standard + mapings: +> + let g:vimspector_enable_mappings = 'HUMAN' +< +1. Load vimspector at runtime. This can also be added to your '.vimrc' after + configuring vimspector: +> + packadd! vimspector +< +See support/doc/example_vimrc.vim for a minimal example. + +------------------------------------------------------------------------------- + *vimspector-install-gadgets* +Install some gadgets ~ + +Vimspector is a generic client for Debug Adapters. Debug Adapters (referred to +as 'gadgets' or 'adapters') are what actually do the work of talking to the +real debuggers. + +In order for Vimspector to be useful, you need to have some adapters installed. + +There are a few ways to do this: + +- If you downloaded a tarball, gadgets for main supported languages are + already installed for you. + +- Using ':VimspectorInstall ' (use TAB 'wildmenu' to see + the options, also accepts any 'install_gadget.py' option) + +- Using 'python3 install_gadget.py ' (use '--help' to see all options) + +- Attempting to launch a debug configuration; if the configured adapter can't + be found, vimspector will suggest installing one. + +- Using ':VimspectorUpdate' to install the latest supported versions of the + gadgets. + +Here's a demo of doing some installs and an upgrade: + + Image: asciicast [13] + +Both 'install_gadget.py' and ':VimspectorInstall' do the same set of things, +though the default behaviours are slightly different. For supported languages, +they 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 packages are usually + broken in this regard. + +- Set up the 'gadgetDir' symlinks for the platform. + +For example, to install the tested debug adapter for a language, run: + +======================================================================================================================================== +| _To install_ | _Script_ | _Command_ | +======================================================================================================================================== +| '' | ':VimspectorInstall ' | +----------------------------------------------------------------------------------------- +| '', '', ... | ':VimspectorInstall ...' | +----------------------------------------------------------------------------------------- +| '' | './install_gadget.py --enable- ...' | ':VimspectorInstall --enable- ...' | +---------------------------------------------------------------------------------------------------------------------------------------- +| Supported adapters | './install_gadget.py --all' | ':VimspectorInstall --all' | +---------------------------------------------------------------------------------------------------------------------------------------- +| Supported adapters, but not TCL | './install_gadget.py --all --disable-tcl' | ':VimspectorInstall --all --disable-tcl' | +---------------------------------------------------------------------------------------------------------------------------------------- +| Supported and experimental adapters | './install_gadget.py --all --force-all' | ':VimspectorInstall --all' | +---------------------------------------------------------------------------------------------------------------------------------------- +| Adapter for specific debug config | Suggested by Vimspector when starting debugging | +----------------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- + *vimspectorinstall-vimspectorupdate-commands* +VimspectorInstall and VimspectorUpdate commands ~ + +':VimspectorInstall' runs 'install_gadget.py' in the background with some of +the options defaulted. + +':VimspectorUpdate' runs 'install_gadget.py' to re-install (i.e. update) any +gadgets already installed in your '.gadgets.json'. + +The output is minimal, to see the full output add '--verbose' to the command, +as in ':VimspectorInstall --verbose ...' or ':VimspectorUpdate --verbose ...'. + +If the installation is successful, the output window is closed (and the output +lost forever). Use a '!' to keep it open (e.g. ':VimspectorInstall! --verbose +--all' or ':VimspectorUpdate!' (etc.). + +If you know in advance which gadgets you want to install, for example so that +you can reproduce your config from source control, you can set +'g:vimspector_install_gadgets' to a list of gadgets. This will be used when: + +- Running ':VimspectorInstall' with no arguments, or +- Running ':VimspectorUpdate' + +For example: +> + let g:vimspector_install_gadgets = [ 'debugpy', 'vscode-cpptools', 'CodeLLDB' ] +< +------------------------------------------------------------------------------- + *vimspector-install_gadget.py* +install_gadget.py ~ + +By default 'install_gadget.py' will overwrite your '.gadgets.json' with the set +of adapters just installed, whereas ':VimspectorInstall' will _update_ it, +overwriting only newly changed or installed adapters. + +If you want to just add a new adapter using the script without destroying the +existing ones, add '--update-gadget-config', as in: +> + $ ./install_gadget.py --enable-tcl + $ ./install_gadget.py --enable-rust --update-gadget-config + $ ./install_gadget.py --enable-java --update-gadget-config +< +If you want to maintain 'configurations' outside of the vimspector repository +(this can be useful if you have custom gadgets or global configurations), you +can tell the installer to use a different basedir, then set +'g:vimspector_base_dir' to point to that directory, for example: +> + $ ./install_gadget.py --basedir $HOME/.vim/vimspector-config --all --force-all +< +Then add this to your '.vimrc': +> + let g:vimspector_base_dir=expand( '$HOME/.vim/vimspector-config' ) +< +When usnig ':VimspectorInstall', the 'g:vimspector_base_dir' setting is +respected unless '--basedir' is manually added (not recommended). + +See '--help' for more info on the various options. + +------------------------------------------------------------------------------- + *vimspector-manual-gadget-installation* +Manual gadget installation ~ + +If the language you want to debug is not in the supported list above, you can +probably still make it work, but it's more effort. + +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 Visual 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 'gadgets.json'. + +PRs are always welcome to add supported languages (which roughly translates to +updating 'python/vimspector/gadgets.py' and testing it). + +------------------------------------------------------------------------------- + *vimspector-gadget-directory* +The gadget directory ~ + +Vimspector uses the following directory by default to look for a file named +'.gadgets.json': '/gadgets/'. + +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 'adapters' key is +used: + +Example: +> + { + "adapters": { + "lldb-vscode": { + "variables": { + "LLVM": { + "shell": "brew --prefix llvm" + } + }, + "attach": { + "pidProperty": "pid", + "pidSelect": "ask" + }, + "command": [ + "${LLVM}/bin/lldb-vscode" + ], + "env": { + "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" + }, + "name": "lldb" + }, + "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' (or +':VimspectorInstall'). + +Vimspector will also load any fies matching: +'/gadgets//.gadgets.d/*.json'. These have the same +format as '.gadgets.json' but are not overwritten when running +'install_gadget.py'. + +------------------------------------------------------------------------------- + *vimspector-upgrade* +Upgrade ~ + +After updating the Vimspector code (either via 'git pull' or whatever package +manager), run ':VimspectorUpdate' to update any already-installed gadgets. + +=============================================================================== + *vimspector-about* +About ~ + +------------------------------------------------------------------------------- + *vimspector-background* +Background ~ + +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-status* +Status ~ + +Vimspector is a work in progress, and any feedback/contributions are more than +welcome. + +The backlog can be viewed on Trello [15]. + +------------------------------------------------------------------------------- + *vimspector-experimental* +Experimental ~ + +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, functionality of the UI + +However, I commit to only doing this in the most extreme cases and to annouce +such changes on Gitter well in advance. There's nothing more annoying than +stuff just breaking on you. I get that. + +------------------------------------------------------------------------------- + *vimspector-motivation* +Motivation ~ + +A message from the author about the motivation for this plugin: + +Many development environments have a built-in debugger. I spend an inordinate +amount of my time in Vim. I do all my development in Vim and I have even +customised my workflows for building code, running tests etc. + +For many years I have observed myself, friends and colleagues have been writing +'printf', 'puts', 'print', etc. debugging statements in all sorts of files +simply because there is no _easy_ way to run a debugger for _whatever_ language +we happen to be developing in. + +I truly believe that interactive, graphical debugging environments are the best +way to understand and reason about both unfamiliar and familiar code, and that +the lack of ready, simple access to a debugger is a huge hidden productivity +hole for many. + +Don't get me wrong, I know there are literally millions of developers out there +that are more than competent at developing without a graphical debugger, but I +maintain that if they had the ability to _just press a key_ and jump into the +debugger, it would be faster and more enjoyable that just cerebral code +comprehension. + +I created Vimspector because I find changing tools frustrating. 'gdb' for c++, +'pdb' for python, etc. Each has its own syntax. Each its own lexicon. Each its +own foibles. + +I designed the configuration system in such a way that the configuration can be +committed to source control so that it _just works_ for any of your colleagues, +friends, collaborators or complete strangers. + +I made remote debugging a first-class feature because that's a primary use case +for me in my job. + +With Vimspector I can _just hit ''_ in all of the languages I develop in +and debug locally or remotely using the exact same workflow, mappings and UI. I +have integrated this with my Vim in such a way that I can hit a button and _run +the test under the cursor in Vimspector_. This kind of integration has +massively improved my workflow and productivity. It's even made the process of +learning a new codebase... fun. + +- Ben Jackson, Creator. + +------------------------------------------------------------------------------- + *vimspector-license* +License ~ + +Apache 2.0 [16] + +Copyright © 2018 Ben Jackson + +------------------------------------------------------------------------------- + *vimspector-sponsorship* +Sponsorship ~ + +If you like Vimspector so much that you're wiling to part with your hard-earned +cash, please consider donating to one of the following charities, which are +meaningful to the author of Vimspector (in order of preference): + +- Greyhound Rescue Wales [17] +- Cancer Research UK [18] +- ICCF Holland [19] +- Any charity of your choosing. + +=============================================================================== + *vimspector-mappings* +Mappings ~ + +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. To that end, Vimspector defines the +following '' mappings: + +================================================================================================================================================================================= +| _Mapping_ | _Function_ | _API_ | +================================================================================================================================================================================= +| 'VimspectorContinue' | When debugging, continue. Otherwise start debugging. | 'vimspector#Continue()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorStop' | Stop debugging. | 'vimspector#Stop()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimpectorRestart' | Restart debugging with the same configuration. | 'vimspector#Restart()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorPause' | Pause debuggee. | 'vimspector#Pause()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorToggleBreakpoint' | Toggle line breakpoint on the current line. | 'vimspector#ToggleBreakpoint()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorToggleConditionalBreakpoint' | Toggle conditional line breakpoint on the current line. | 'vimspector#ToggleBreakpoint( { trigger expr, hit count expr } )' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorAddFunctionBreakpoint' | Add a function breakpoint for the expression under cursor | "vimspector#AddFunctionBreakpoint( '' )" | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorRunToCursor' | Run to Cursor | 'vimspector#RunToCursor()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorStepOver' | Step Over | 'vimspector#StepOver()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorStepInto' | Step Into | 'vimspector#StepInto()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorStepOut' | Step out of current function scope | 'vimspector#StepOut()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorUpFrame' | Move up a frame in the current call stack | 'vimspector#UpFrame()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorDownFrame' | Move down a frame in the current call stack | 'vimspector#DownFrame()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorBalloonEval' | Evaluate expression under cursor (or visual) in popup | _internal_ | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + +These map roughly 1-1 with the API functions below. + +For example, if you want '' to start/continue debugging, add this to some +appropriate place, such as your 'vimrc' (hint: run ':e $MYVIMRC'). +> + nmap VimspectorContinue +< +In addition, many users probably want to only enable certain Vimspector +mappings while debugging is active. This is also possible, though it requires +writing some vimscipt. + +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. + +------------------------------------------------------------------------------- + *vimspector-visual-studio-vscode* +Visual Studio / VSCode ~ + +To use Visual Studio-like mappings, add the following to your 'vimrc' **before +loading vimspector**: +> + let g:vimspector_enable_mappings = 'VISUAL_STUDIO' +< +========================================================================================================================= +| _Key_ | _Mapping_ | _Function_ | +========================================================================================================================= +| 'F5' | 'VimspectorContinue' | When debugging, continue. Otherwise start debugging. | +------------------------------------------------------------------------------------------------------------------------- +| 'Shift F5' | 'VimspectorStop' | Stop debugging. | +------------------------------------------------------------------------------------------------------------------------- +| 'Ctrl Shift F5' | 'VimspectorRestart' | Restart debugging with the same configuration. | +------------------------------------------------------------------------------------------------------------------------- +| 'F6' | 'VimspectorPause' | Pause debuggee. | +------------------------------------------------------------------------------------------------------------------------- +| 'F9' | 'VimspectorToggleBreakpoint' | Toggle line breakpoint on the current line. | +------------------------------------------------------------------------------------------------------------------------- +| 'Shift F9' | 'VimspectorAddFunctionBreakpoint' | Add a function breakpoint for the expression under cursor | +------------------------------------------------------------------------------------------------------------------------- +| 'F10' | 'VimspectorStepOver' | Step Over | +------------------------------------------------------------------------------------------------------------------------- +| 'F11' | 'VimspectorStepInto' | Step Into | +------------------------------------------------------------------------------------------------------------------------- +| 'Shift F11' | 'VimspectorStepOut' | Step out of current function scope | +------------------------------------------------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- + *vimspector-human-mode* +Human Mode ~ + +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_ | _Mapping_ | _Function_ | +============================================================================================================================ +| 'F5' | 'VimspectorContinue' | When debugging, continue. Otherwise start debugging. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F3' | 'VimspectorStop' | Stop debugging. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F4' | 'VimspectorRestart' | Restart debugging with the same configuration. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F6' | 'VimspectorPause' | Pause debuggee. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F9' | 'VimspectorToggleBreakpoint' | Toggle line breakpoint on the current line. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F9' | 'VimspectorToggleConditionalBreakpoint' | Toggle conditional line breakpoint on the current line. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F8' | 'VimspectorAddFunctionBreakpoint' | Add a function breakpoint for the expression under cursor | +---------------------------------------------------------------------------------------------------------------------------- +| 'F8' | 'VimspectorRunToCursor' | Run to Cursor | +---------------------------------------------------------------------------------------------------------------------------- +| 'F10' | 'VimspectorStepOver' | Step Over | +---------------------------------------------------------------------------------------------------------------------------- +| 'F11' | 'VimspectorStepInto' | Step Into | +---------------------------------------------------------------------------------------------------------------------------- +| 'F12' | 'VimspectorStepOut' | Step out of current function scope | +---------------------------------------------------------------------------------------------------------------------------- + + +In addition, I recommend adding a mapping to 'VimspectorBalloonEval', in +normal and visual modes, for example: +> + " mnemonic 'di' = 'debug inspect' (pick your own, if you prefer!) + + " for normal mode - the word under the cursor + nmap di VimspectorBalloonEval + " for visual mode, the visually selected text + xmap di VimspectorBalloonEval +< +You may also wish to add mappings for up/down the stack, for example: +> + nmap VimspectorUpFrame + nmap VimspectorDownFrame +< +=============================================================================== + *vimspector-usage-api* +Usage and API ~ + +This section defines detailed usage instructions, organised by feature. For +most users, the mappings section contains the most common commands and default +usage. This section can be used as a reference to create your own mappings or +custom behaviours. + +------------------------------------------------------------------------------- + *vimspector-launch-attach-by-pid* +Launch and attach by PID: ~ + +- Create '.vimspector.json'. See below. +- ':call vimspector#Launch()' and select a configuration. + + Image: debug session (see reference [6]) + +------------------------------------------------------------------------------- + *vimspector-launch-with-options* +Launch with options ~ + +To launch a specific debug configuration, or specify replacement variables [20] +for the launch, you can use: + +- ':call vimspector#LaunchWithSettings( dict )' + +The argument is a 'dict' with the following keys: + +- 'configuration': (optional) Name of the debug configuration to launch +- '': (optional) Name of a variable to set + +This allows for some integration and automation. For example, if you have a +configuration named 'Run Test' that contains a replacement variable [20] named +'${Test}' you could write a mapping which ultimately executes: +> + vimspector#LaunchWithSettings( #{ configuration: 'Run Test' + \ Test: 'Name of the test' } ) +< +This would start the 'Run Test' configuration with '${Test}' set to "'Name of +the test'" and Vimspector would _not_ prompt the user to enter or confirm these +things. + +See our YouCompleteMe integration guide for another example where it can be +used to specify the port to connect the java debugger + +------------------------------------------------------------------------------- + *vimspector-debug-configuration-selection* +Debug configuration selection ~ + +Vimspector uses the following logic to choose a configuration to launch: + +1. If a configuration was specified in the launch options (as above), use + that. + +2. Otherwise if there's only one configuration and it doesn't have + 'autoselect' set to 'false', use that. + +3. Otherwise if there's exactly one configuration with 'default' set to + 'true' and without 'autoselect' set to 'false', use that. + +4. Otherwise, prompt the user to select a configuration. + +See the reference guide [21] for details. + +------------------------------------------------------------------------------- + *vimspector-get-configurations* +Get configurations ~ + +- Use 'vimspector#GetConfigurations()' to get a list of configurations + +For example, to get an array of configurations and fuzzy matching on the result +> + :call matchfuzzy(vimspector#GetConfigurations(), "test::case_1") +< +------------------------------------------------------------------------------- + *vimspector-breakpoints* +Breakpoints ~ + +See the mappings [22] section for the default mappings for working with +breakpoints. This section describes the full API in vimscript functions. + +------------------------------------------------------------------------------- + *vimspector-summary* +Summary ~ + +- Use 'vimspector#ToggleBreakpoint( { options dict } )' to set/disable/delete + a line breakpoint. The argument is optional (see below). + +- Use "vimspector#AddFunctionBreakpoint( '', { options dict} )" to add + a function breakpoint. The second argument is optional (see below). + +- Use 'vimspector#SetLineBreakpoint( file_name, line_num, { options dict } )' + to set a breakpoint at a specific file/line. The last argument is optional + (see below) + +- Use 'vimspector#ClearLineBreakpoint( file_name, line_num )' to remove a + breakpoint at a specific file/line + +- Use 'vimspector#ClearBreakpoints()' to clear all breakpoints + +Examples: + +- 'call vimspector#ToggleBreakpoint()' - toggle breakpoint on current line + +- "call vimspector#SetLineBreakpoint( 'some_file.py', 10 )" - set a + breakpoint on 'some_filepy:10' + +- "call vimspector#AddFunctionBreakpoint( 'main' )" - add a function + breakpoint on the 'main' function + +- "call vimspector#ToggleBreakpoint( { 'condition': 'i > 5' } )" - add a + breakpoint on the current line that triggers only when 'i > 5' is 'true' + +- "call vimspector#SetLineBreakpoint( 'some_file.py', 10, { 'condition': 'i > + 5' } )" - add a breakpoint at 'some_file.py:10' that triggers only when 'i + > 5' is 'true' + +- "call vimspector#ClearLineBreakpoint( 'some_file.py', 10 )" - delete the + breakpoint at 'some_file.py:10' + +- 'call vimspector#ClearBreakpoints()' - clear all breakpoints + +------------------------------------------------------------------------------- + *vimspector-line-breakpoints* +Line breakpoints ~ + +The simplest and most common form of breakpoint is a line breakpoint. Execution +is paused when the specified line is executed. + +For most debugging scenarios, users will just hit '' to create a line +breakpoint on the current line and '' to launch the application. + +------------------------------------------------------------------------------- + *vimspector-conditional-breakpoints* +Conditional breakpoints ~ + +Some debug adapters support conditional breakpoints. Note that vimspector does +not tell you if the debugger doesn't support conditional breakpoints (yet). A +conditional breakpoint is a breakpoint which only triggers if some expression +evaluates to true, or has some other constraints met. + +Some of these functions above take a single optional argument which is a +dictionary of options. The dictionary can have the following keys: + +- 'condition': An optional expression evaluated to determine if the + breakpoint should fire. Not supported by all debug adapters. For example, + to break when 'abc' is '10', enter something like 'abc == 10', depending on + the language. + +- 'hitCondition': An optional expression evaluated to determine a number of + times the breakpoint should be ignored. Should (probably?) not be used in + combination with 'condition'. Not supported by all debug adapters. For + example, to break on the 3rd time hitting this line, enter '3'. + +In both cases, the expression is evaluated by the debugger, so should be in +whatever dialect the debugger understands when evaluating expressions. + +When using the '' mapping, the user is prompted to enter these +expressions in a command line (with history). + +------------------------------------------------------------------------------- + *vimspector-exception-breakpoints* +Exception breakpoints ~ + +Exception breakpoints typically fire when an exception is throw or other error +condition occurs. Depending on the debugger, when starting debugging, you may +be asked a few questions about how to handle exceptions. These are "exception +breakpoints" and vimspector remembers your choices while Vim is still running. + +Typically you can accept the defaults (just keep pressing ''!) as most +debug adapter defaults are sane, but if you want to break on, say 'uncaught +exception' then answer 'Y' to that (for example). + +You can configure your choices in the '.vimspector.json'. See the configuration +guide [23] for details on that. + +------------------------------------------------------------------------------- + *vimspector-clear-breakpoints* +Clear breakpoints ~ + +Use 'vimspector#ClearBreakpoints()' to clear all breakpoints including the +memory of exception breakpoint choices. + +------------------------------------------------------------------------------- + *vimspector-run-to-cursor* +Run to Cursor ~ + +Use 'vimspector#RunToCursor' or '': this creates a temporary +breakpoint on the current line, then continues execution, clearing the +breakpoint when it is hit. + +------------------------------------------------------------------------------- + *vimspector-stepping* +Stepping ~ + +- Step in/out, finish, continue, pause etc. using the WinBar, or mappings. +- If you really want to, the API is 'vimspector#StepInto()' etc. + + Image: code window (see reference [24]) + +------------------------------------------------------------------------------- + *vimspector-variables-scopes* +Variables and scopes ~ + +- Current scope shows values of locals. +- Use '', or double-click with left mouse to expand/collapse (+, -). +- Set the value of the variable with '' (control + '') or + '' (if 'modifyOtherKeys' doesn't work for you) +- When changing the stack frame the locals window updates. +- While paused, hover to see values + + Image: locals window (see reference [25]) + +Scopes and variables are represented by the buffer 'vimspector.Variables'. + +------------------------------------------------------------------------------- + *vimspector-variable-or-selection-hover-evaluation* +Variable or selection hover evaluation ~ + +All rules for 'Variables and scopes' apply plus the following: + +- With mouse enabled, hover over a variable and get the value it evaluates + to. + +- Use your mouse to perform a visual selection of an expression (e.g. 'a + + b') and get its result. + +- Make a normal mode ('nmap') and visual mode ('xmap') mapping to + 'VimspectorBalloonEval' to manually trigger the popup. + +- Set the value of the variable with '' (control + '') or + '' (if 'modifyOtherKeys' doesn't work for you) + +- Use regular nagivation keys ('j', 'k') to choose the current selection; + '' (or leave the tooltip window) to close the tooltip. + + Image: variable eval hover (see reference [26]) + +------------------------------------------------------------------------------- + *vimspector-watches* +Watches ~ + +The watch window is used to inspect variables and expressions. Expressions are +evaluated in the selected stack frame which is "focussed" + +The watches window is a prompt buffer, where that's available. 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 ''. + +- Alternatively, use ':VimspectorWatch '. Tab-completion for + expression is available in some debug adapters. + +- Expand result with '', or double-click with left mouse. + +- Set the value of the variable with '' (control + '') or + '' (if 'modifyOtherKeys' doesn't work for you) + +- Delete with ''. + + Image: watch window (see reference [27]) + +The watches are represented by the buffer 'vimspector.StackTrace'. + +------------------------------------------------------------------------------- + *vimspector-watch-autocompletion* +Watch autocompletion ~ + +The watch prompt buffer has its 'omnifunc' set to a function that will +calculate completion for the current expression. This is trivially used with +'' (see ':help ins-completion'), or integrated with your +favourite completion system. The filetype in the buffer is set to +'VimspectorPrompt'. + +For YouCompleteMe, the following config works well: +> + let g:ycm_semantic_triggers = { + \ 'VimspectorPrompt': [ '.', '->', ':', '<' ] + } +< +------------------------------------------------------------------------------- + *vimspector-stack-traces* +Stack Traces ~ + +The stack trace window shows the state of each program thread. Threads which +are stopped can be expanded to show the stack trace of that thread. + +Often, but not always, all threads are stopped when a breakpoint is hit. The +status of a thread is show in parentheses after the thread's name. Where +supported by the underlying debugger, threads can be paused and continued +individually from within the Stack Trace window. + +A particular thread, highlighted with the 'CursorLine' highlight group is the +"focussed" thread. This is the thread that receives commands like "Stop In", +"Stop Out", "Continue" and "Pause" in the code window. The focussed thread can +be changed manually to "switch to" that thread. + +- Use '', or double-click with left mouse to expand/collapse a thread + stack trace, or use the WinBar button. + +- Use '', or double-click with left mouse on a stack frame to jump to it. + +- Use the WinBar or 'vimspector#PauseContinueThread()' to individually pause + or continue the selected thread. + +- Use the "Focus" WinBar button, '' or + 'vimspector#SetCurrentThread()' to set the "focussed" thread to the + currently selected one. If the selected line is a stack frame, set the + focussed thread to the thread of that frame and jump to that frame in the + code window. + + Image: stack trace (see reference [28]) + +The stack trace is represented by the buffer 'vimspector.StackTrace'. + +------------------------------------------------------------------------------- + *vimspector-program-output* +Program Output ~ + +- In the outputs window, use the WinBar to select the output channel. +- Alternatively, use ':VimspectorShowOutput '. Use command-line + completion to see the categories. +- The debuggee prints to the stdout channel. +- Other channels may be useful for debugging. + + Image: output window (see reference [29]) + +If the output window is closed, a new one can be opened with +':VimspectorShowOutput ' (use tab-completion - 'wildmenu' to see the +options). + +------------------------------------------------------------------------------- + *vimspector-console* +Console ~ + +The console window is a prompt buffer, where that's available, and can be used +as an interactive CLI for the debug adapter. Support for this varies amongst +adapters. + +- Enter insert mode to enter a command to evaluate. +- Alternatively, ':VimspectorEval '. Completion is available with + some debug adapters. +- Commit the request with '' +- The request and subsequent result are printed. + +NOTE: See also Watches above. + +If the output window is closed, a new one can be opened with +':VimspectorShowOutput Console'. + +------------------------------------------------------------------------------- + *vimspector-console-autocompletion* +Console autocompletion ~ + +The console prompt buffer has its 'omnifunc' set to a function that will +calculate completion for the current command/expression. This is trivially used +with '' (see ':help ins-completion'), or integrated with your +favourite completion system. The filetype in the buffer is set to +'VimspectorPrompt'. + +For YouCompleteMe, the following config works well: +> + let g:ycm_semantic_triggers = { + \ 'VimspectorPrompt': [ '.', '->', ':', '<' ] + } +< +------------------------------------------------------------------------------- + *vimspector-log-view* +Log View ~ + +The Vimspector log file contains a full trace of the communication between +Vimspector and the debug adapter. This is the primary source of diagnostic +information when something goes wrong that's not a Vim traceback. + +If you just want to see the Vimspector log file, use ':VimspectorToggleLog', +which will tail it in a little window (doesn't work on Windows). + +------------------------------------------------------------------------------- + *vimspector-closing-debugger* +Closing debugger ~ + +To close the debugger, use: + +- 'Reset' WinBar button +- ':VimspectorReset' when the WinBar is not available. +- 'call vimspector#Reset()' + +------------------------------------------------------------------------------- + *vimspector-terminate-debuggee* +Terminate debuggee ~ + +If the debuggee is still running when stopping or resetting, then some debug +adapters allow you to specify what should happen to it when finishing +debugging. Typically, the default behaviour is sensible, and this is what +happens most of the time. These are the defaults according to DAP: + +- If the request was 'launch': terminate the debuggee +- If the request was 'attach': don't terminate the debuggee + +Some debug adapters allow you to choose what to do when disconnecting. If you +wish to control this behaviour, use ':VimspectorReset' or call +"vimspector#Reset( { 'interactive': v:true } )". If the debug adapter offers a +choice as to whether or not to terminate the debuggee, you will be prompted to +choose. The same applies for 'vimspector#Stop()' which can take an argument: +"vimspector#Stop( { 'interactive': v:true } )". + +=============================================================================== + *vimspector-debug-profile-configuration* +Debug profile configuration ~ + +For an introduction to the configuration of '.vimspector.json', take a look at +the Getting Started section of the Vimspector website [1]. + +For full explanation, including how to use variables, substitutions and how to +specify exception breakpoints, see the docs [2]. + +The JSON configuration file allows C-style comments: + +- '// comment to end of line ...' +- '/* inline comment ... */' + +Current tested with the following debug adapters. + +------------------------------------------------------------------------------- + *vimspector-c-c-rust-etc.* +C, C++, Rust, etc. ~ + +- vscode-cpptools [30] + +- On macOS, I _strongly_ recommend using CodeLLDB instead for C and C++ + projects. It's really excellent, has fewer dependencies and doesn't open + console apps in another Terminal window. + +Example '.vimspector.json' (works with both 'vscode-cpptools' and +'lldb-vscode'. For 'lldb-vscode' replace the name of the adapter with +'lldb-vscode': + +- vscode-cpptools Linux/MacOS: +> + { + "configurations": { + "Launch": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "launch", + "program": "", + "args": [ ... ], + "cwd": "", + "environment": [ ... ], + "externalConsole": true, + "MIMode": "" + } + }, + "Attach": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "attach", + "program": "", + "MIMode": "" + } + } + ... + } + } +< +- vscode-cpptools Windows + +**_NOTE FOR WINDOWS USERS:_** You need to install 'gdb.exe'. I recommend using +'scoop install gdb'. Vimspector cannot use the visual studio debugger due to +licensing. +> + { + "configurations": { + "Launch": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "launch", + "program": "", + "stopAtEntry": true + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-c-remote-debugging* +C++ Remote debugging ~ + +The cpptools documentation describes how to attach cpptools to gdbserver using +'miDebuggerAddress'. Note that when doing this you should use the '"request": +"attach"'. + +------------------------------------------------------------------------------- + *vimspector-c-remote-launch-attach* +C++ Remote launch and attach ~ + +If you're feeling fancy, checkout the reference guide [31] for an example of +getting Vimspector to remotely launch and attach. + +- CodeLLDB (MacOS) + +CodeLLDB is superior to vscode-cpptools in a number of ways on macOS at least. + +See Rust. + +- lldb-vscode (MacOS) + +An alternative is to to use 'lldb-vscode', which comes with llvm. Here's how: + +- Install llvm (e.g. with HomeBrew: 'brew install llvm') +- Create a file named + '/path/to/vimspector/gadgets/macos/.gadgets.d/lldb-vscode.json': +> + { + "adapters": { + "lldb-vscode": { + "variables": { + "LLVM": { + "shell": "brew --prefix llvm" + } + }, + "attach": { + "pidProperty": "pid", + "pidSelect": "ask" + }, + "command": [ + "${LLVM}/bin/lldb-vscode" + ], + "env": { + "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" + }, + "name": "lldb" + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-rust* +Rust ~ + +Rust is supported with any gdb/lldb-based debugger. So it works fine with +'vscode-cpptools' and 'lldb-vscode' above. However, support for rust is best in +'CodeLLDB' [32]. + +- './install_gadget.py --force-enable-rust' or ':VimspectorInstall CodeLLDB' +- Example: 'support/test/rust/vimspector_test' +> + { + "configurations": { + "launch": { + "adapter": "CodeLLDB", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/target/debug/vimspector_test" + } + } + } + } +< +- Docs: https://github.com/vadimcn/vscode-lldb/blob/master/MANUAL.md + +------------------------------------------------------------------------------- + *vimspector-python* +Python ~ + +- Python: debugpy [33] + +- Install with 'install_gadget.py --enable-python' or ':VimspectorInstall + debugpy', ideally requires a working compiler and the python development + headers/libs to build a C python extension for performance. + +- Full options: + https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings + +**Migrating from 'vscode-python'**: change '"adapter": "vscode-python"' to +'"adapter": "debugpy"'. +> + { + "configurations": { + ": Launch": { + "adapter": "debugpy", + "configuration": { + "name": ": Launch", + "type": "python", + "request": "launch", + "cwd": "", + "python": "/path/to/python/interpreter/to/use", + "stopOnEntry": true, + "console": "externalTerminal", + "debugOptions": [], + "program": "" + } + } + ... + } + } +< +------------------------------------------------------------------------------- + *vimspector-python-remote-debugging* +Python Remote Debugging ~ + +In order to use remote debugging with debugpy, you have to connect Vimspector +directly to the application that is being debugged. This is easy, but it's a +little different from how we normally configure things. Specifically, you need +to: + +- Start your application with debugpy, specifying the '--listen' argument. + See the debugpy documentation [34] for details. + +- Use the built-in "multi-session" adapter. This just asks for the host/port + to connect to. For example: +> + { + "configurations": { + "Python Attach": { + "adapter": "multi-session", + "configuration": { + "request": "attach", + "pathMappings": [ + // mappings here (optional) + ] + } + } + } + } +< +See details of the launch configuration [35] for explanation of things like +'pathMappings'. + +Additional documentation, including how to do this when the remote machine can +only be contacted via SSH are provided by debugpy [36]. + +------------------------------------------------------------------------------- + *vimspector-python-remote-launch-attach* +Python Remote launch and attach ~ + +If you're feeling fancy, checkout the reference guide [31] for an example of +getting Vimspector to remotely launch and attach. + +------------------------------------------------------------------------------- + *vimspector-legacy-vscode-python* +Legacy: vscode-python ~ + +- No longer installed by default - please pass '--force-enable-python.legacy' + if you just want to continue using your working setup. +- vscode-python [37] +- NOTE: You must be running 'node' 10. See this issue [38] +> + { + "configurations": { + ": Launch": { + "adapter": "vscode-python", + "configuration": { + "name": ": Launch", + "type": "python", + "request": "launch", + "cwd": "", + "stopOnEntry": true, + "console": "externalTerminal", + "debugOptions": [], + "program": "" + } + } + ... + } + } +< +------------------------------------------------------------------------------- + *vimspector-tcl* +TCL ~ + +- TCL (TclProDebug) + +See my fork of TclProDebug [39] for instructions. + +------------------------------------------------------------------------------- + *vimspector-c* +C♯ ~ + +- C# - dotnet core + +Install with 'install_gadget.py --force-enable-csharp' or ':VimspectorInstall +netcoredbg' +> + { + "configurations": { + "launch - netcoredbg": { + "adapter": "netcoredbg", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", + "args": [], + "stopAtEntry": true, + "cwd": "${workspaceRoot}" + } + } + } + } +< +- C# - mono + +Install with 'install_gadget.py --force-enable-csharp' or ':VimspectorInstall +vscode-mono-debug'. + +**_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" + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-go* +Go ~ + +- Go + +Requires: + +- 'install_gadget.py --enable-go' or ':VimspectorInstall vscode-go' +- Delve [40] 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" + } + } + } + } +< +See the vscode-go docs for troubleshooting information [41] + +------------------------------------------------------------------------------- + *vimspector-php* +PHP ~ + +This uses the php-debug, see +https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug + +Requires: + +- (optional) Xdebug helper for chrome https://chrome.google.com/webstore/deta + il/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc + +- 'install_gadget.py --force-enable-php' or ':VimspectorInstall + vscode-php-debug' + +- configured php xdebug extension +> + zend_extension=xdebug.so + xdebug.remote_enable=on + xdebug.remote_handler=dbgp + xdebug.remote_host=localhost + xdebug.remote_port=9000 +< + replace 'localhost' with the ip of your workstation. + +lazy alternative +> + zend_extension=xdebug.so + xdebug.remote_enable=on + xdebug.remote_handler=dbgp + xdebug.remote_connect_back=true + xdebug.remote_port=9000 +< +- .vimspector.json +> + { + "configurations": { + "Listen for XDebug": { + "adapter": "vscode-php-debug", + "configuration": { + "name": "Listen for XDebug", + "type": "php", + "request": "launch", + "port": 9000, + "stopOnEntry": false, + "pathMappings": { + "/var/www/html": "${workspaceRoot}" + } + } + }, + "Launch currently open script": { + "adapter": "vscode-php-debug", + "configuration": { + "name": "Launch currently open script", + "type": "php", + "request": "launch", + "program": "${file}", + "cwd": "${fileDirname}", + "port": 9000 + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-debug-web-application* +Debug web application ~ + +append 'XDEBUG_SESSION_START=xdebug' to your query string +> + curl "http://localhost?XDEBUG_SESSION_START=xdebug" +< +or use the previously mentioned Xdebug Helper extension (which sets a +'XDEBUG_SESSION' cookie) + +------------------------------------------------------------------------------- + *vimspector-debug-cli-application* +Debug cli application ~ +> + export XDEBUG_CONFIG="idekey=xdebug" + php +< +------------------------------------------------------------------------------- + *vimspector-javascript-typescript-etc.* +JavaScript, TypeScript, etc. ~ + +- Node.js + +Requires: + +- 'install_gadget.py --force-enable-node' + +- For installation, a Node.js environment 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?i +temName=msjsdiag.debugger-for-chrome. + +It allows you to debug scripts running inside chrome from within Vim. + +- './install_gadget.py --force-enable-chrome' or ':VimspectorInstall + debugger-for-chrome' +- Example: 'support/test/chrome' +> + { + "configurations": { + "launch": { + "adapter": "chrome", + "configuration": { + "request": "launch", + "url": "http://localhost:1234/", + "webRoot": "${workspaceRoot}/www" + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-java* +Java ~ + +Vimspector works well with the java debug server [42], which runs as a jdt.ls +(Java Language Server) plugin, rather than a standalone debug adapter. + +Vimspector is not in the business of running language servers, only debug +adapters, so this means that you need a compatible Language Server Protocol +editor plugin to use Java. I recommend YouCompleteMe [43], which has full +support for jdt.ls, and most importantly a trivial way to load the debug +adapter and to use it with Vimspector. + +------------------------------------------------------------------------------- + *vimspector-usage-with-youcompleteme* +Usage with YouCompleteMe ~ + +- Set up YCM for java [43]. + +- Get Vimspector to download the java debug plugin: 'install_gadget.py + --force-enable-java ' or ':VimspectorInstall + java-debug-adapter' + +- Configure Vimspector for your project using the 'vscode-java' adapter, + e.g.: +> + { + "configurations": { + "Java Attach": { + "adapter": "vscode-java", + "configuration": { + "request": "attach", + "hostName": "${host}", + "port": "${port}", + "sourcePaths": [ + "${workspaceRoot}/src/main/java", + "${workspaceRoot}/src/test/java" + ] + } + } + } + } +< +- Tell YCM to load the debugger plugin. This should be the 'gadgets/' + directory, not any specific adapter. e.g. in '.vimrc' +> + " Tell YCM where to find the plugin. Add to any existing values. + let g:ycm_java_jdtls_extension_path = [ + \ '' + \ ] +< +- Create a mapping, such as '' to start the debug server and + launch vimspector, e.g. in '~/.vim/ftplugin/java.vim': +> + let s:jdt_ls_debugger_port = 0 + function! s:StartDebugging() + if s:jdt_ls_debugger_port <= 0 + " Get the DAP port + let s:jdt_ls_debugger_port = youcompleteme#GetCommandResponse( + \ 'ExecuteCommand', + \ 'vscode.java.startDebugSession' ) + + if s:jdt_ls_debugger_port == '' + echom "Unable to get DAP port - is JDT.LS initialized?" + let s:jdt_ls_debugger_port = 0 + return + endif + endif + + " Start debugging with the DAP port + call vimspector#LaunchWithSettings( { 'DAPPort': s:jdt_ls_debugger_port } ) + endfunction + + nnoremap :call StartDebugging() +< +You can then use '' to start debugging rather than just ''. + +If you see "Unable to get DAP port - is JDT.LS initialized?", try running +':YcmCompleter ExecuteCommand vscode.java.startDebugSession' and note the +output. If you see an error like 'ResponseFailedException: Request failed: +-32601: No delegateCommandHandler for vscode.java.startDebugSession', make sure +that: _Your YCM jdt.ls is actually working, see the YCM docs [44] for +troubleshooting_ The YCM jdt.ls has had time to initialize before you start the +debugger * That 'g:ycm_java_jdtls_extension_path' is set in '.vimrc' or prior +to YCM starting + +For the launch arguments, see the vscode document [45]. + +------------------------------------------------------------------------------- + *vimspector-other-lsp-clients* +Other LSP clients ~ + +See this issue [46] for more background. + +------------------------------------------------------------------------------- + *vimspector-lua* +Lua ~ + +Lua is supported through local-lua-debugger-vscode [47]. This debugger uses +stdio to communicate with the running process, so calls to 'io.read' will cause +problems. + +- './install_gadget.py --enable-lua' or ':VimspectorInstall + local-lua-debugger-vscode' +- Examples: 'support/test/lua/simple' and 'support/test/lua/love' +> + { + "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#", + "configurations": { + "lua": { + "adapter": "lua-local", + "configuration": { + "request": "launch", + "type": "lua-local", + "cwd": "${workspaceFolder}", + "program": { + "lua": "lua", + "file": "${file}" + } + } + }, + "luajit": { + "adapter": "lua-local", + "configuration": { + "request": "launch", + "type": "lua-local", + "cwd": "${workspaceFolder}", + "program": { + "lua": "luajit", + "file": "${file}" + } + } + }, + "love": { + "adapter": "lua-local", + "configuration": { + "request": "launch", + "type": "lua-local", + "cwd": "${workspaceFolder}", + "program": { + "command": "love" + }, + "args": ["${workspaceFolder}"] + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-other-servers* +Other servers ~ + +- Java - vscode-javac. This works, but is not as functional as Java Debug + Server. Take a look at this comment [48] for instructions. + +=============================================================================== + *vimspector-customisation* +Customisation ~ + +There is very limited support for customisation of the UI. + +------------------------------------------------------------------------------- + *vimspector-changing-default-signs* +Changing the default signs ~ + +Vimsector uses the following signs internally. If they are defined before +Vimsector uses them, they will not be replaced. So to customise the signs, +define them in your 'vimrc'. + +============================================================================= +| _Sign_ | _Description_ | _Priority_ | +============================================================================= +| 'vimspectorBP' | Line breakpoint | 9 | +----------------------------------------------------------------------------- +| 'vimspectorBPCond' | Conditional line breakpoint | 9 | +----------------------------------------------------------------------------- +| 'vimspectorBPDisabled' | Disabled breakpoint | 9 | +----------------------------------------------------------------------------- +| 'vimspectorPC' | Program counter (i.e. current line) | 200 | +----------------------------------------------------------------------------- +| 'vimspectorPCBP' | Program counter and breakpoint | 200 | +----------------------------------------------------------------------------- + + +The default symbols are the equivalent of something like the following: +> + sign define vimspectorBP text=\ ● texthl=WarningMsg + sign define vimspectorBPCond text=\ ◆ texthl=WarningMsg + sign define vimspectorBPDisabled text=\ ● texthl=LineNr + sign define vimspectorPC text=\ ▶ texthl=MatchParen linehl=CursorLine + sign define vimspectorPCBP text=●▶ texthl=MatchParen linehl=CursorLine +< +If the signs don't display properly, your font probably doesn't contain these +glyphs. You can easily change them by defining the sign in your vimrc. For +example, you could put this in your 'vimrc' to use some simple ASCII symbols: +> + sign define vimspectorBP text=o texthl=WarningMsg + sign define vimspectorBPCond text=o? texthl=WarningMsg + sign define vimspectorBPDisabled text=o! texthl=LineNr + sign define vimspectorPC text=\ > texthl=MatchParen + sign define vimspectorPCBP text=o> texthl=MatchParen +< +------------------------------------------------------------------------------- + *vimspector-sign-priority* +Sign priority ~ + +Many different plugins provide signs for various purposes. Examples include +diagnostic signs for code errors, etc. Vim provides only a single priority to +determine which sign should be displayed when multiple signs are placed at a +single line. If you are finding that other signs are interfering with +vimspector's (or vice-versa), you can customise the priority used by vimspector +by setting the following dictionary: +> + let g:vimspector_sign_priority = { + \ '': , + \ } +< +For example: +> + let g:vimspector_sign_priority = { + \ 'vimspectorBP': 3, + \ 'vimspectorBPCond': 2, + \ 'vimspectorBPDisabled': 1, + \ 'vimspectorPC': 999, + \ } +< +All keys are optional. If a sign is not customised, the default priority it +used (as shown above). + +See ':help sign-priority'. The default priority is 10, larger numbers override +smaller ones. + +------------------------------------------------------------------------------- + *vimspector-changing-default-window-sizes* +Changing the default window sizes ~ + +**_Please Note_**: This customisation API is **_unstable_**, meaning that it +may change at any time. I will endeavour to reduce the impact of this and +announce changes in Gitter. + +The following options control the default sizes of the UI windows (all of them +are numbers) + +- 'g:vimspector_sidebar_width' (default: 50 columns): The width in columns of + the left utility windows (variables, watches, stack trace) + +- 'g:vimspector_bottombar_height' (default 10 lines): The height in rows of + the output window below the code window. + +Example: +> + let g:vimspector_sidebar_width = 75 + let g:vimspector_bottombar_height = 15 +< +------------------------------------------------------------------------------- + *vimspector-changing-terminal-size* +Changing the terminal size ~ + +The terminal is typically created as a vertical split to the right of the code +window, and that window is re-used for subsequent terminal buffers. The +following control the sizing of the terminal window used for debuggee +input/output when using Vim's built-in terminal. + +- 'g:vimspector_code_minwidth' (default: 82 columns): Minimum number of + columns to try and maintain for the code window when splitting to create + the terminal window. + +- 'g:vimspector_terminal_maxwidth' (default: 80 columns): Maximum number of + columns to use for the terminal. + +- 'g:vimspector_terminal_minwidth' (default: 10 columns): Minimum number of + columns to use when it is not possible to fit + 'g:vimspector_terminal_maxwidth' columns for the terminal. + +That's a lot of options, but essentially we try to make sure that there are at +least 'g:vimspector_code_minwidth' columns for the main code window and that +the terminal is no wider than 'g:vimspector_terminal_maxwidth' columns. +'g:vimspector_terminal_minwidth' is there to ensure that there's a reasonable +number of columns for the terminal even when there isn't enough horizontal +space to satisfy the other constraints. + +Example: +> + let g:vimspector_code_minwidth = 90 + let g:vimspector_terminal_maxwidth = 75 + let g:vimspector_terminal_minwidth = 20 +< +------------------------------------------------------------------------------- + *vimspector-custom-mappings-while-debugging* +Custom mappings while debugging ~ + +It's useful to be able to define mappings only while debugging and remove those +mappings when debugging is complete. For this purpose, Vimspector provides 2 +'User' autocommands: + +- 'VimspectorJumpedToFrame' - triggered whenever a 'break' event happens, or + when selecting a stack from to jump to. This can be used to create (for + example) buffer-local mappings for any files opened in the code window. + +- 'VimspectorDebugEnded' - triggered when the debug session is terminated + (actually when Vimspector is fully reset) + +An example way to use this is included in 'support/custom_ui_vimrc'. In there, +these autocommands are used to create buffer-local mappings for any files +visited while debugging and to clear them when completing debugging. This is +particularly useful for commands like 'VimspectorBalloonEval' which only +make sense while debugging (and only in the code window). Check the commented +section 'Custom mappings while debugging'. + +NOTE: This is a fairly advanced feature requiring some nontrivial vimscript. +It's possible that this feature will be incorporated into Vimspector in future +as it is a common requirement. + +------------------------------------------------------------------------------- + *vimspector-advanced-ui-customisation* +Advanced UI customisation ~ + +**_Please Note_**: This customisation API is **_unstable_**, meaning that it +may change at any time. I will endeavour to reduce the impact of this and +announce changes in Gitter. + +The above customisation of window sizes is limited intentionally to keep things +simple. Vimspector also provides a way for you to customise the UI without +restrictions, by running a 'User' autocommand just after creating the UI or +opening the terminal. This requires you to write some vimscript, but allows you +to do things like: + +- Hide a particular window or windows +- Move a particular window or windows +- Resize windows +- Have multiple windows for a particular buffer (say, you want 2 watch + windows) +- etc. + +You can essentially do anything you could do manually by writing a little +vimscript code. + +The 'User' autocommand is raised with 'pattern' set with the following values: + +- 'VimspectorUICreated': Just after setting up the UI for a debug session +- 'VimspectorTerminalOpened': Just after opening the terminal window for + program input/output. + +The following global variable is set up for you to get access to the UI +elements: 'g:vimspector_session_windows'. This is a 'dict' with the following +keys: + +- 'g:vimspector_session_windows.tagpage': The tab page for the session +- 'g:vimspector_session_windows.variables': Window ID of the variables + window, containing the 'vimspector.Variables' buffer. +- 'g:vimspector_session_windows.watches': Window ID of the watches window, + containing the 'vimspector.Watches' buffer. +- 'g:vimspector_session_windows.stack_trace': Window ID of the stack trade + window containing the 'vimspector.StackTrace' buffer. +- 'g:vimspector_session_windows.code': Window ID of the code window. +- 'g:vimspector_session_windows.output': Window ID of the output window. + +In addition, the following key is added when triggering the +'VimspectorTerminalOpened' event: + +- 'g:vimspector_session_windows.terminal': Window ID of the terminal window + +------------------------------------------------------------------------------- + *vimspector-customising-winbar* +Customising the WinBar ~ + +You can even customise the WinBar buttons by simply running the usual 'menu' +(and 'unmenu') commands. + +By default, Vimspector uses something a bit like this: +> + nnoremenu WinBar.■\ Stop :call vimspector#Stop( { 'interactive': v:false } ) + nnoremenu WinBar.▶\ Cont :call vimspector#Continue() + nnoremenu WinBar.▷\ Pause :call vimspector#Pause() + nnoremenu WinBar.↷\ Next :call vimspector#StepOver() + nnoremenu WinBar.→\ Step :call vimspector#StepInto() + nnoremenu WinBar.←\ Out :call vimspector#StepOut() + nnoremenu WinBar.⟲: :call vimspector#Restart() + nnoremenu WinBar.✕ :call vimspector#Reset( { 'interactive': v:false } ) +< +If you prefer a different layout or if the unicode symbols don't render +correctly in your font, you can customise this in the 'VimspectorUICreated' +autocommand, for example: +> + func! CustomiseUI() + call win_gotoid( g:vimspector_session_windows.code ) + " Clear the existing WinBar created by Vimspector + nunmenu WinBar + " Cretae our own WinBar + nnoremenu WinBar.Kill :call vimspector#Stop( { 'interactive': v:true } ) + nnoremenu WinBar.Continue :call vimspector#Continue() + nnoremenu WinBar.Pause :call vimspector#Pause() + nnoremenu WinBar.Step\ Over :call vimspector#StepOver() + nnoremenu WinBar.Step\ In :call vimspector#StepInto() + nnoremenu WinBar.Step\ Out :call vimspector#StepOut() + nnoremenu WinBar.Restart :call vimspector#Restart() + nnoremenu WinBar.Exit :call vimspector#Reset() + endfunction + + augroup MyVimspectorUICustomistaion + autocmd! + autocmd User VimspectorUICreated call s:CustomiseUI() + augroup END +< +------------------------------------------------------------------------------- + *vimspector-example* +Example ~ + +There is some example code in 'support/custom_ui_vimrc' showing how you can use +the window IDs to modify various aspects of the UI using some basic vim +commands, primarily 'win_gotoid' function and the 'wincmd' ex command. + +To try this out 'vim -Nu support/custom_ui_vimrc '. + +Here's a rather smaller example. A simple way to use this is to drop it into a +file named 'my_vimspector_ui.vim' in '~/.vim/plugin' (or paste into your +'vimrc'): +> + " Set the basic sizes + let g:vimspector_sidebar_width = 80 + let g:vimspector_code_minwidth = 85 + let g:vimspector_terminal_minwidth = 75 + + function! s:CustomiseUI() + " Customise the basic UI... + + " Close the output window + call win_gotoid( g:vimspector_session_windows.output ) + q + endfunction + + function s:SetUpTerminal() + " Customise the terminal window size/position + " For some reasons terminal buffers in Neovim have line numbers + call win_gotoid( g:vimspector_session_windows.terminal ) + set norelativenumber nonumber + endfunction + + augroup MyVimspectorUICustomistaion + autocmd! + autocmd User VimspectorUICreated call s:CustomiseUI() + autocmd User VimspectorTerminalOpened call s:SetUpTerminal() + augroup END +< +=============================================================================== + *vimspector-faq* +FAQ ~ + +1. Q: Does it work? A: Yeah. It's a bit unpolished. + +2. 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. + +3. How do I stop it starting a new Terminal.app on macOS? See this comment + [49] + +4. Can I specify answers to the annoying questions about exception + breakpoints in my '.vimspector.json' ? Yes, see here [23]. + +5. Do I have to specify the file to execute in '.vimspector.json', or could + it be the current vim file? You don't need to. You can specify $file for + the current active file. See here [20] for complete list of replacements + in the configuration file. + +6. You allow comments in '.vimspector.json', but Vim highlights these as + errors, do you know how to make this not-an-error? Yes, put this in + '~/.vim/after/syntax/json.vim': +> + syn region jsonComment start="/\*" end="\*/" + hi link jsonCommentError Comment + hi link jsonComment Comment +< +1. What is the difference between a 'gadget' and an 'adapter'? A gadget is + something you install with ':VimspectorInstall' or 'install_gadget.py', + an 'adapter' is something that Vimspector talks to (actually it's the + Vimspector config describing that thing). These are _usually_ one-to-one, + but in theory a single gadget can supply multiple 'adapter' configs. + Typically this happens when a 'gadget' supplies different 'adapter' + config for, say remote debugging, or debugging in a container, etc. + +2. The signs and winbar display funny symbols. How do I fix them? See this + and this + +3. What's this telemetry stuff all about? Are you sending my data to evil + companies? Debug adapters (for some reason) send telemetry data to + clients. Vimspector simply displays this information in the output + window. It _does not_ and _will not ever_ collect, use, forward or + otherwise share any data with any third parties. + +=============================================================================== + *vimspector-references* +References ~ + +[1] https://puremourning.github.io/vimspector-web/ +[2] https://puremourning.github.io/vimspector/configuration.html +[3] https://github.com/puremourning/vimspector/workflows/Build/badge.svg?branch=master +[4] https://gitter.im/vimspector/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge +[5] https://badges.gitter.im/vimspector/Lobby.svg +[6] https://puremourning.github.io/vimspector-web/img/vimspector-overview.png +[7] https://asciinema.org/a/VmptWmFHTNLPfK3DVsrR2bv8S +[8] https://asciinema.org/a/VmptWmFHTNLPfK3DVsrR2bv8S.svg +[9] https://asciinema.org/a/1wZJSoCgs3AvjkhKwetJOJhDh +[10] https://asciinema.org/a/1wZJSoCgs3AvjkhKwetJOJhDh.svg +[11] https://github.com/go-delve/delve +[12] https://github.com/puremourning/vimspector/wiki/languages +[13] https://asciinema.org/a/Hfu4ZvuyTZun8THNen9FQbTay +[14] https://asciinema.org/a/Hfu4ZvuyTZun8THNen9FQbTay.svg +[15] https://trello.com/b/yvAKK0rD/vimspector +[16] http://www.apache.org/licenses/LICENSE-2.0 +[17] https://greyhoundrescuewales.co.uk +[18] https://www.cancerresearchuk.org +[19] https://iccf.nl +[20] https://puremourning.github.io/vimspector/configuration.html#replacements-and-variables +[21] https://puremourning.github.io/vimspector/configuration.html#configuration-selection +[22] €mappings +[23] https://puremourning.github.io/vimspector/configuration.html#exception-breakpoints +[24] https://puremourning.github.io/vimspector-web/img/vimspector-code-window.png +[25] https://puremourning.github.io/vimspector-web/img/vimspector-locals-window.png +[26] https://puremourning.github.io/vimspector-web/img/vimspector-variable-eval-hover.png +[27] https://puremourning.github.io/vimspector-web/img/vimspector-watch-window.png +[28] https://puremourning.github.io/vimspector-web/img/vimspector-callstack-window.png +[29] https://puremourning.github.io/vimspector-web/img/vimspector-output-window.png +[30] https://github.com/Microsoft/vscode-cpptools +[31] https://puremourning.github.io/vimspector/configuration.html#remote-debugging-support +[32] https://github.com/vadimcn/vscode-lldb#features +[33] https://github.com/microsoft/debugpy +[34] https://github.com/microsoft/debugpy#debugpy-cli-usage +[35] https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings +[36] https://github.com/microsoft/debugpy/wiki/Debugging-over-SSH +[37] https://github.com/Microsoft/vscode-python +[38] https://github.com/puremourning/vimspector/issues/105 +[39] https://github.com/puremourning/TclProDebug +[40] https://github.com/go-delve/delve/tree/master/Documentation/installation +[41] https://github.com/golang/vscode-go/blob/master/docs/debugging.md#troubleshooting +[42] https://github.com/Microsoft/java-debug +[43] https://github.com/ycm-core/YouCompleteMe#java-semantic-completion +[44] https://github.com/ycm-core/YouCompleteMe#troubleshooting +[45] https://code.visualstudio.com/docs/java/java-debugging +[46] https://github.com/puremourning/vimspector/issues/3 +[47] https://github.com/tomblind/local-lua-debugger-vscode +[48] https://github.com/puremourning/vimspector/issues/3#issuecomment-576916076 +[49] https://github.com/puremourning/vimspector/issues/90#issuecomment-577857322 + +vim: ft=help diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index d2eb55f..acf20f2 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -1,13 +1,13 @@ GEM remote: https://rubygems.org/ specs: - activesupport (6.0.3.4) + activesupport (6.0.3.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - addressable (2.7.0) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) coffee-script (2.4.1) coffee-script-source @@ -16,7 +16,7 @@ GEM colorator (1.1.0) commonmarker (0.17.13) ruby-enum (~> 0.5) - concurrent-ruby (1.1.7) + concurrent-ruby (1.1.8) dnsruby (1.61.5) simpleidn (~> 0.1) em-websocket (0.5.2) @@ -30,12 +30,12 @@ GEM faraday-net_http (~> 1.0) multipart-post (>= 1.2, < 3) ruby2_keywords - faraday-net_http (1.0.0) - ffi (1.14.2) + faraday-net_http (1.0.1) + ffi (1.15.0) forwardable-extended (2.6.0) gemoji (3.0.1) - github-pages (209) - github-pages-health-check (= 1.16.1) + github-pages (214) + github-pages-health-check (= 1.17.0) jekyll (= 3.9.0) jekyll-avatar (= 0.7.0) jekyll-coffeescript (= 1.1.1) @@ -50,9 +50,9 @@ GEM jekyll-readme-index (= 0.3.0) jekyll-redirect-from (= 0.16.0) jekyll-relative-links (= 0.6.1) - jekyll-remote-theme (= 0.4.2) + jekyll-remote-theme (= 0.4.3) jekyll-sass-converter (= 1.5.2) - jekyll-seo-tag (= 2.6.1) + jekyll-seo-tag (= 2.7.1) jekyll-sitemap (= 1.4.0) jekyll-swiss (= 1.0.0) jekyll-theme-architect (= 0.1.1) @@ -70,19 +70,19 @@ GEM jekyll-theme-time-machine (= 0.1.1) jekyll-titles-from-headings (= 0.5.3) jemoji (= 0.12.0) - kramdown (= 2.3.0) + kramdown (= 2.3.1) kramdown-parser-gfm (= 1.1.0) liquid (= 4.0.3) mercenary (~> 0.3) minima (= 2.5.1) nokogiri (>= 1.10.4, < 2.0) - rouge (= 3.23.0) + rouge (= 3.26.0) terminal-table (~> 1.4) - github-pages-health-check (1.16.1) + github-pages-health-check (1.17.0) addressable (~> 2.3) dnsruby (~> 1.60) octokit (~> 4.0) - public_suffix (~> 3.0) + public_suffix (>= 2.0.2, < 5.0) typhoeus (~> 1.3) html-pipeline (2.14.0) activesupport (>= 2) @@ -136,15 +136,15 @@ GEM jekyll (>= 3.3, < 5.0) jekyll-relative-links (0.6.1) jekyll (>= 3.3, < 5.0) - jekyll-remote-theme (0.4.2) + jekyll-remote-theme (0.4.3) addressable (~> 2.0) jekyll (>= 3.5, < 5.0) jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) rubyzip (>= 1.3.0, < 3.0) jekyll-sass-converter (1.5.2) sass (~> 3.4) - jekyll-seo-tag (2.6.1) - jekyll (>= 3.3, < 5.0) + jekyll-seo-tag (2.7.1) + jekyll (>= 3.8, < 5.0) jekyll-sitemap (1.4.0) jekyll (>= 3.7, < 5.0) jekyll-swiss (1.0.0) @@ -196,23 +196,23 @@ GEM gemoji (~> 3.0) html-pipeline (~> 2.2) jekyll (>= 3.0, < 5.0) - kramdown (2.3.0) + kramdown (2.3.1) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) liquid (4.0.3) - listen (3.4.0) + listen (3.5.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.3.6) - mini_portile2 (2.5.0) + mini_portile2 (2.5.1) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) - minitest (5.14.3) + minitest (5.14.4) multipart-post (2.1.1) - nokogiri (1.11.1) + nokogiri (1.11.5) mini_portile2 (~> 2.5.0) racc (~> 1.4) octokit (4.20.0) @@ -220,16 +220,16 @@ GEM sawyer (~> 0.8.0, >= 0.5.3) pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (3.1.1) + public_suffix (4.0.6) racc (1.5.2) rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) - rexml (3.2.4) - rouge (3.23.0) - ruby-enum (0.8.0) + rexml (3.2.5) + rouge (3.26.0) + ruby-enum (0.9.0) i18n - ruby2_keywords (0.0.2) + ruby2_keywords (0.0.4) rubyzip (2.3.0) safe_yaml (1.0.5) sass (3.7.4) @@ -240,7 +240,7 @@ GEM sawyer (0.8.2) addressable (>= 2.3.5) faraday (> 0.8, < 2.0) - simpleidn (0.1.1) + simpleidn (0.2.1) unf (~> 0.1.4) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) diff --git a/docs/configuration.md b/docs/configuration.md index e736985..3d524bf 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -271,7 +271,7 @@ JSON value `true`, and the suffix is stripped fom the key, resulting in the following: ```json - "stopOnEntry#json": true + "stopOnEntry": true ``` Which is what we need. @@ -722,7 +722,7 @@ Vimspector then orchestrates the various tools to set you up. "variables": { // Just an example of how to specify a variable manually rather than // vimspector asking for input from the user - "ServiceName": "${fileBasenameNoExtention}" + "ServiceName": "${fileBasenameNoExtension}" }, "adapter": "python-remote", diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 24f8914..2668bf1 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -13,6 +13,13 @@ " See the License for the specific language governing permissions and " limitations under the License. +if !has( 'python3' ) + echohl WarningMsg + echom 'Vimspector unavailable: Requires Vim compiled with +python3' + echohl None + finish +endif + " Boilerplate {{{ let s:save_cpo = &cpoptions set cpoptions&vim @@ -69,6 +76,11 @@ nnoremap VimspectorBalloonEval xnoremap VimspectorBalloonEval \ :call vimspector#ShowEvalBalloon( 1 ) +nnoremap VimspectorUpFrame + \ :call vimspector#UpFrame() +nnoremap VimspectorDownFrame + \ :call vimspector#DownFrame() + if s:mappings ==# 'VISUAL_STUDIO' nmap VimspectorContinue nmap VimspectorStop @@ -103,6 +115,9 @@ command! -bar -nargs=? -complete=custom,vimspector#CompleteOutput command! -bar \ VimspectorToggleLog \ call vimspector#ToggleLog() +command! -bar + \ VimspectorDebugInfo + \ call vimspector#PrintDebugInfo() command! -nargs=1 -complete=custom,vimspector#CompleteExpr \ VimspectorEval \ call vimspector#Evaluate( ) diff --git a/python3/vimspector/breakpoints.py b/python3/vimspector/breakpoints.py index 5c21140..7aa50ce 100644 --- a/python3/vimspector/breakpoints.py +++ b/python3/vimspector/breakpoints.py @@ -45,7 +45,6 @@ class ProjectBreakpoints( object ): self._func_breakpoints = [] self._exception_breakpoints = None self._configured_breakpoints = {} - self._data_breakponts = [] # FIXME: Remove this. Remove breakpoints nonesense from code.py self._breakpoints_handler = None @@ -271,18 +270,6 @@ class ProjectBreakpoints( object ): # TODO: We don't really have aanything to update here, but if we're going to # have a UI list of them we should update that at this point - # but note that while debugging, this is when we actually _send_ the - # breakpoints. - self.UpdateUI() - - - def AddDataBreakpoint( self, dataId, options ): - self._data_breakponts.append( { - 'state': 'ENABLED', - 'dataId': dataId, - 'options': options, - } ) - self.UpdateUI() @@ -415,27 +402,6 @@ class ProjectBreakpoints( object ): failure_handler = response_received ) - if self._data_breakponts and self._server_capabilities[ - 'supportsDataBreakpoints' ]: - awaiting += 1 - breakpoints = [] - for bp in self._data_breakponts: - if bp[ 'state' ] != 'ENABLED': - continue - data_bp = {} - data_bp.update( bp[ 'options' ] ) - data_bp[ 'dataId' ] = bp[ 'dataId' ] - breakpoints.append( data_bp ) - - self._connection.DoRequest( - lambda msg: response_handler( None, None ), - { - 'command': 'setDataBreakpoints', - 'arguments': breakpoints, - }, - failure_handler = response_received - ) - if self._exception_breakpoints: awaiting = awaiting + 1 self._connection.DoRequest( @@ -528,11 +494,6 @@ class ProjectBreakpoints( object ): file_name, bp[ 'line' ] ) - # TODO could/should we show a sign in the variables view when there's a data - # brakpoint on the variable? Not sure how best to actually do that, but - # maybe the variable view can pass that info when calling AddDataBreakpoint, - # such as the variablesReference/name - def _SignToLine( self, file_name, bp ): if 'sign_id' not in bp: diff --git a/python3/vimspector/custom/java.py b/python3/vimspector/custom/java.py index 83705c1..c2a2264 100644 --- a/python3/vimspector/custom/java.py +++ b/python3/vimspector/custom/java.py @@ -14,7 +14,7 @@ # limitations under the License. from vimspector.debug_session import DebugSession -from vimspector import utils +from vimspector import utils, settings class JavaDebugAdapter( object ): @@ -36,8 +36,16 @@ class JavaDebugAdapter( object ): 'arguments': {}, } ) - utils.Confirm( self.debug_session._api_prefix, - 'Code has changed, hot reload?', - handler ) + mode = settings.Get( 'java_hotcodereplace_mode' ) + if mode == 'ask': + utils.Confirm( self.debug_session._api_prefix, + 'Code has changed, hot reload?', + handler, + default_value = 1 ) + elif mode == 'always': + self.debug_session._connection.DoRequest( None, { + 'command': 'redefineClasses', + 'arguments': {}, + } ) elif body.get( 'message' ): utils.UserMessage( 'Hot code replace: ' + body[ 'message' ] ) diff --git a/python3/vimspector/debug_adapter_connection.py b/python3/vimspector/debug_adapter_connection.py index df2ef13..206938a 100644 --- a/python3/vimspector/debug_adapter_connection.py +++ b/python3/vimspector/debug_adapter_connection.py @@ -226,7 +226,12 @@ class DebugAdapterConnection( object ): # self._logger.debug( 'Message received (raw): %s', payload ) - message = json.loads( payload ) + try: + message = json.loads( payload, strict = False ) + except Exception: + self._logger.exception( "Invalid message received: %s", payload ) + self._SetState( 'READ_HEADER' ) + raise self._logger.debug( 'Message received: {0}'.format( message ) ) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 8c671af..36ad62b 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -535,21 +535,6 @@ class DebugSession( object ): def SetVariableValue( self, new_value = None, buf = None, line_num = None ): self._variablesView.SetVariableValue( new_value, buf, line_num ) - @IfConnected() - def AddDataBreakpoint( self, opts, buf = None, line_num = None ): - def add_bp( breakpoint_info ): - if breakpoint_info[ 'dataId' ] is None: - utils.UserMessage( - "Can't set data breakpoint here: { breakpoint_info[ 'description' ] }" - ) - return - - # TODO: Ask the user about the possible DataBreakpointAccessType's and add - # that in to opts here - self._breakpoints.AddDataBreakpoint( breakpoint_info[ 'dataId' ], opts ) - - self._variablesView.GetDataBreakpointInfo( add_bp, buf, line_num ) - @IfConnected() def AddWatch( self, expression ): self._variablesView.AddWatch( self._stackTraceView.GetCurrentFrame(), @@ -592,6 +577,14 @@ class DebugSession( object ): def ExpandFrameOrThread( self ): self._stackTraceView.ExpandFrameOrThread() + @IfConnected() + def UpFrame( self ): + self._stackTraceView.UpFrame() + + @IfConnected() + def DownFrame( self ): + self._stackTraceView.DownFrame() + def ToggleLog( self ): if self._HasUI(): return self.ShowOutput( 'Vimspector' ) @@ -676,6 +669,45 @@ class DebugSession( object ): vim.command( 'tab split' ) self._uiTab = vim.current.tabpage + mode = settings.Get( 'ui_mode' ) + + if mode == 'auto': + # Go vertical if there isn't enough horizontal space for at least: + # the left bar width + # + the code min width + # + the terminal min width + # + enough space for a sign column and number column? + min_width = ( settings.Int( 'sidebar_width' ) + + 1 + 2 + 3 + + settings.Int( 'code_minwidth' ) + + 1 + settings.Int( 'terminal_minwidth' ) ) + + min_height = ( settings.Int( 'code_minheight' ) + 1 + + settings.Int( 'topbar_height' ) + 1 + + settings.Int( 'bottombar_height' ) + 1 + + 2 ) + + mode = ( 'vertical' + if vim.options[ 'columns' ] < min_width + else 'horizontal' ) + + if vim.options[ 'lines' ] < min_height: + mode = 'horizontal' + + self._logger.debug( 'min_width/height: %s/%s, actual: %s/%s - result: %s', + min_width, + min_height, + vim.options[ 'columns' ], + vim.options[ 'lines' ], + mode ) + + if mode == 'vertical': + self._SetUpUIVertical() + else: + self._SetUpUIHorizontal() + + + def _SetUpUIHorizontal( self ): # Code window code_window = vim.current.window self._codeView = code.CodeView( code_window, self._api_prefix ) @@ -716,6 +748,66 @@ class DebugSession( object ): # TODO: If/when we support multiple sessions, we'll need some way to # indicate which tab was created and store all the tabs vim.vars[ 'vimspector_session_windows' ] = { + 'mode': 'horizontal', + 'tabpage': self._uiTab.number, + 'code': utils.WindowID( code_window, self._uiTab ), + 'stack_trace': utils.WindowID( stack_trace_window, self._uiTab ), + 'variables': utils.WindowID( vars_window, self._uiTab ), + 'watches': utils.WindowID( watch_window, self._uiTab ), + 'output': utils.WindowID( output_window, self._uiTab ), + 'eval': None # this is going to be updated every time eval popup is opened + } + with utils.RestoreCursorPosition(): + with utils.RestoreCurrentWindow(): + with utils.RestoreCurrentBuffer( vim.current.window ): + vim.command( 'doautocmd User VimspectorUICreated' ) + + + def _SetUpUIVertical( self ): + # Code window + code_window = vim.current.window + self._codeView = code.CodeView( code_window, self._api_prefix ) + + # Call stack + vim.command( + f'topleft { settings.Int( "topbar_height" ) }new' ) + stack_trace_window = vim.current.window + one_third = int( vim.eval( 'winwidth( 0 )' ) ) / 3 + self._stackTraceView = stack_trace.StackTraceView( self, + stack_trace_window ) + + + # Watches + vim.command( 'leftabove vertical new' ) + watch_window = vim.current.window + + # Variables + vim.command( 'leftabove vertical new' ) + vars_window = vim.current.window + + + with utils.LetCurrentWindow( vars_window ): + vim.command( f'{ one_third }wincmd |' ) + with utils.LetCurrentWindow( watch_window ): + vim.command( f'{ one_third }wincmd |' ) + with utils.LetCurrentWindow( stack_trace_window ): + vim.command( f'{ one_third }wincmd |' ) + + self._variablesView = variables.VariablesView( vars_window, + watch_window ) + + + # Output/logging + vim.current.window = code_window + vim.command( f'rightbelow { settings.Int( "bottombar_height" ) }new' ) + output_window = vim.current.window + self._outputView = output.DAPOutputView( output_window, + self._api_prefix ) + + # TODO: If/when we support multiple sessions, we'll need some way to + # indicate which tab was created and store all the tabs + vim.vars[ 'vimspector_session_windows' ] = { + 'mode': 'vertical', 'tabpage': self._uiTab.number, 'code': utils.WindowID( code_window, self._uiTab ), 'stack_trace': utils.WindowID( stack_trace_window, self._uiTab ), @@ -824,7 +916,9 @@ class DebugSession( object ): self._logger.info( 'Debug Adapter Started' ) def _StopDebugAdapter( self, interactive = False, callback = None ): - def disconnect( arguments = {} ): + arguments = {} + + def disconnect(): self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, @@ -844,7 +938,7 @@ class DebugSession( object ): self._connection.DoRequest( handler, { 'command': 'disconnect', - 'arguments': {}, + 'arguments': arguments, }, failure_handler = handler, timeout = 5000 ) if not interactive: @@ -855,21 +949,25 @@ class DebugSession( object ): disconnect() else: def handle_choice( choice ): - arguments = {} if choice == 1: + # yes arguments[ 'terminateDebuggee' ] = True - elif choice == 0: + elif choice == 2: + # no arguments[ 'terminateDebuggee' ] = False - elif choice == -1: + elif choice <= 0: # Abort return + # Else, use server default - disconnect( arguments ) + disconnect() utils.Confirm( self._api_prefix, "Terminate debuggee?", handle_choice, - default_value = 3 ) + default_value = 3, + options = [ '(Y)es', '(N)o', '(D)efault' ], + keys = [ 'y', 'n', 'd' ] ) def _PrepareAttach( self, adapter_config, launch_config ): @@ -1049,10 +1147,6 @@ class DebugSession( object ): # def handle_initialize_response( msg ): self._server_capabilities = msg.get( 'body' ) or {} - self._outputView.Print( - 'server', - 'Server Capabilities:\n' + json.dumps( self._server_capabilities, - indent = 2 ) ) self._breakpoints.SetServerCapabilities( self._server_capabilities ) self._variablesView.SetServerCapabilities( self._server_capabilities ) self._Launch() @@ -1176,6 +1270,37 @@ class DebugSession( object ): self._stackTraceView.LoadThreads( True ) + @IfConnected() + @RequiresUI() + def PrintDebugInfo( self ): + def Line(): + return ( "--------------------------------------------------------------" + "------------------" ) + + def Pretty( obj ): + if obj is None: + return [ "None" ] + return [ Line() ] + json.dumps( obj, indent=2 ).splitlines() + [ Line() ] + + + debugInfo = [ + "Vimspector Debug Info", + Line(), + f"ConnectionType: { self._connection_type }", + "Adapter: " ] + Pretty( self._adapter ) + [ + "Configuration: " ] + Pretty( self._configuration ) + [ + f"API Prefix: { self._api_prefix }", + f"Launch/Init: { self._launch_complete } / { self._init_complete }", + f"Workspace Root: { self._workspace_root }", + "Launch Config: " ] + Pretty( self._launch_config ) + [ + "Server Capabilities: " ] + Pretty( self._server_capabilities ) + [ + ] + + self._outputView.ClearCategory( 'DebugInfo' ) + self._outputView.Print( "DebugInfo", debugInfo ) + self.ShowOutput( "DebugInfo" ) + + def OnEvent_loadedSource( self, msg ): pass diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 5c61074..02eb0e7 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -30,12 +30,12 @@ GADGETS = { root, gadget ), 'all': { - 'version': '0.27.0', + 'version': '1.6.0', "adapters": { "vscode-cpptools": { "name": "cppdbg", "command": [ - "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7" + "${gadgetDir}/vscode-cpptools/debugAdapters/bin/OpenDebugAD7" ], "attach": { "pidProperty": "processId", @@ -53,17 +53,17 @@ GADGETS = { 'linux': { 'file_name': 'cpptools-linux.vsix', 'checksum': - '3695202e1e75a03de18049323b66d868165123f26151f8c974a480eaf0205435', + 'c25299bcfb46b22d41aa3f125df7184e6282a35ff9fb69c47def744cb4778f55', }, 'macos': { - 'file_name': 'cpptools-osx.vsix', + 'file_name': 'cpptools-osx-arm64.vsix', 'checksum': - 'cb061e3acd7559a539e5586f8d3f535101c4ec4e8a48195856d1d39380b5cf3c', + 'ceb3e8cdaa2b5bb45af50913ddd8402089969748af8d70f5d46480408287ba6f', }, 'windows': { 'file_name': 'cpptools-win32.vsix', 'checksum': - 'aa294368ed16d48c59e49c8000e146eae5a19ad07b654efed5db8ec93b24229e', + 'ef7ac5831874a3c7dbf0feb826bfda2be579aff9b6d990622fff1d0d4ede00d1', "adapters": { "vscode-cpptools": { "name": "cppdbg", @@ -86,29 +86,6 @@ GADGETS = { }, }, }, - 'vscode-python': { - 'language': 'python.legacy', - 'enabled': False, - 'download': { - 'url': 'https://github.com/Microsoft/vscode-python/releases/download/' - '${version}/${file_name}', - }, - 'all': { - 'version': '2019.11.50794', - 'file_name': 'ms-python-release.vsix', - 'checksum': - '6a9edf9ecabed14aac424e6007858068204a3638bf3bb4f235bd6035d823acc6', - }, - 'adapters': { - "vscode-python": { - "name": "vscode-python", - "command": [ - "node", - "${gadgetDir}/vscode-python/out/client/debugger/debugAdapter/main.js", - ], - } - }, - }, 'debugpy': { 'language': 'python', 'download': { @@ -234,15 +211,15 @@ GADGETS = { 'format': 'tar', }, 'all': { - 'version': '1.2.0-635' + 'version': '1.2.0-782' }, 'macos': { 'file_name': 'netcoredbg-osx.tar.gz', 'checksum': - '71c773e34d358950f25119bade7e3081c4c2f9d71847bd49027ca5792e918beb', + '', }, 'linux': { - 'file_name': 'netcoredbg-linux-bionic.tar.gz', + 'file_name': 'netcoredbg-linux-bionic-amd64.tar.gz', 'checksum': '', }, 'windows': { @@ -269,41 +246,6 @@ GADGETS = { }, } }, - 'vscode-mono-debug': { - 'language': 'csharp', - 'enabled': False, - 'download': { - 'url': 'https://marketplace.visualstudio.com/_apis/public/gallery/' - 'publishers/ms-vscode/vsextensions/mono-debug/${version}/' - 'vspackage', - 'target': 'vscode-mono-debug.vsix.gz', - 'format': 'zip.gz', - }, - 'all': { - 'file_name': 'vscode-mono-debug.vsix', - 'version': '0.16.2', - 'checksum': - '121eca297d83daeeb1e6e1d791305d1827998dbd595c330086b3b94d33dba3b9', - }, - 'adapters': { - 'vscode-mono-debug': { - "name": "mono-debug", - "command": [ - "mono", - "${gadgetDir}/vscode-mono-debug/bin/Release/mono-debug.exe" - ], - "attach": { - "pidSelect": "none" - }, - "configuration": { - "cwd": "${workspaceRoot}", - "console": "integratedTerminal", - "args": [], - "env": {} - } - }, - } - }, 'vscode-bash-debug': { 'language': 'bash', 'download': { @@ -381,10 +323,10 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.14.9', - 'file_name': 'php-debug.vsix', + 'version': 'v1.17.0', + 'file_name': 'php-debug-1.17.0.vsix', 'checksum': - '0c5709cbbffe26b12aa63a88142195a9a045a5d8fca7fe63d62c789fe601630d', + 'd0fff272503414b6696cc737bc2e18e060fdd5e5dc4bcaf38ae7373afd8d8bc9', }, 'adapters': { 'vscode-php-debug': { @@ -452,12 +394,12 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.5.3', + 'version': 'v1.6.6', }, 'macos': { - 'file_name': 'codelldb-x86_64-darwin.vsix', + 'file_name': 'codelldb-aarch64-darwin.vsix', 'checksum': - '7505bc1cdfcfd1cb981e2996aec62d63577440709bac31dcadb41a3b4b44631a', + '5adc3b9139eabdafd825bd5efc55df4424a203fb2b6087b425cd434956e7ec58', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/debugserver', @@ -468,7 +410,7 @@ GADGETS = { 'linux': { 'file_name': 'codelldb-x86_64-linux.vsix', 'checksum': - 'ce7efc3e94d775368e5942a02bf5c326b6809a0b4c389f79ffa6a8f6f6b72139', + 'eda2cd9b3089dcc0524c273e91ffb5875fe08c930bf643739a2cd1846e1f98d6', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/lldb', @@ -479,7 +421,7 @@ GADGETS = { 'windows': { 'file_name': 'codelldb-x86_64-windows.vsix', 'checksum': - '', + '8ddebe8381a3d22dc3d95139c3797fda06b5cc34aadf300e13b1c516b9da95fe', 'make_executable': [] }, 'adapters': { diff --git a/python3/vimspector/installer.py b/python3/vimspector/installer.py index f0f85a4..a81db8f 100644 --- a/python3/vimspector/installer.py +++ b/python3/vimspector/installer.py @@ -358,7 +358,8 @@ def InstallCppTools( name, root, gadget ): # It's hilarious, but the execute bits aren't set in the vsix. So they # actually have javascript code which does this. It's just a horrible horrible # hack that really is not funny. - MakeExecutable( os.path.join( extension, 'debugAdapters', 'OpenDebugAD7' ) ) + MakeExecutable( + os.path.join( extension, 'debugAdapters', 'bin', 'OpenDebugAD7' ) ) with open( os.path.join( extension, 'package.json' ) ) as f: package = json.load( f ) runtime_dependencies = package[ 'runtimeDependencies' ] diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index df1e0c6..3f0da1e 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -32,6 +32,7 @@ class TabBuffer( object ): BUFFER_MAP = { 'console': 'Console', 'stdout': 'Console', + 'output': 'Console', 'stderr': 'stderr', 'telemetry': None, } @@ -64,8 +65,11 @@ class OutputView( object ): self._api_prefix = api_prefix VIEWS.add( self ) - def Print( self, category, text ): - self._Print( category, text.splitlines() ) + def Print( self, category, text: typing.Union[ str, list ] ): + if not isinstance( text, list ): + text = text.splitlines() + + self._Print( category, text ) def OnOutput( self, event ): category = CategoryToBuffer( event.get( 'category' ) or 'output' ) @@ -104,13 +108,26 @@ class OutputView( object ): def Clear( self ): for category, tab_buffer in self._buffers.items(): - if tab_buffer.is_job: - utils.CleanUpCommand( category, self._api_prefix ) - utils.CleanUpHiddenBuffer( tab_buffer.buf ) + self._CleanUpBuffer( category, tab_buffer ) # FIXME: nunmenu the WinBar ? self._buffers = {} + + def ClearCategory( self, category: str ): + if category not in self._buffers: + return + + self._CleanUpBuffer( category, self._buffers[ category ] ) + + + def _CleanUpBuffer( self, category: str, tab_buffer: TabBuffer ): + if tab_buffer.is_job: + utils.CleanUpCommand( category, self._api_prefix ) + + utils.CleanUpHiddenBuffer( tab_buffer.buf ) + + def WindowIsValid( self ): return self._window.valid diff --git a/python3/vimspector/settings.py b/python3/vimspector/settings.py index 9ad9e41..89378af 100644 --- a/python3/vimspector/settings.py +++ b/python3/vimspector/settings.py @@ -20,11 +20,20 @@ from vimspector import utils DEFAULTS = { # UI - 'bottombar_height': 10, - 'sidebar_width': 50, - 'code_minwidth': 82, - 'terminal_maxwidth': 80, - 'terminal_minwidth': 10, + 'ui_mode': 'auto', + 'bottombar_height': 10, + + # For ui_mode = 'horizontal': + 'sidebar_width': 50, + 'code_minwidth': 82, + 'terminal_maxwidth': 80, + 'terminal_minwidth': 10, + + # For ui_mode = 'vertical': + 'topbar_height': 15, + 'code_minheight': 20, + 'terminal_maxheight': 15, + 'terminal_minheight': 5, # Signs 'sign_priority': { @@ -33,7 +42,8 @@ DEFAULTS = { 'vimspectorBP': 9, 'vimspectorBPCond': 9, 'vimspectorBPDisabled': 9, - 'vimspectorCurrentThread': 200 + 'vimspectorCurrentThread': 200, + 'vimspectorCurrentFrame': 200, }, # Installer @@ -50,7 +60,10 @@ DEFAULTS = { 'expand_or_jump': [ '', '<2-LeftMouse>' ], 'focus_thread': [ '' ], } - } + }, + + # Custom + 'java_hotcodereplace_mode': 'ask', } diff --git a/python3/vimspector/stack_trace.py b/python3/vimspector/stack_trace.py index c32cead..8b1d848 100644 --- a/python3/vimspector/stack_trace.py +++ b/python3/vimspector/stack_trace.py @@ -102,7 +102,8 @@ class StackTraceView( object ): self._scratch_buffers = [] # FIXME: This ID is by group, so should be module scope - self._next_sign_id = 1 + self._current_thread_sign_id = 0 # 1 when used + self._current_frame_sign_id = 0 # 2 when used utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' ) utils.SetUpUIWindow( win ) @@ -127,6 +128,7 @@ class StackTraceView( object ): ':call vimspector#SetCurrentThread()' ) win.options[ 'cursorline' ] = False + win.options[ 'signcolumn' ] = 'auto' if not signs.SignDefined( 'vimspectorCurrentThread' ): @@ -136,6 +138,13 @@ class StackTraceView( object ): texthl = 'MatchParen', linehl = 'CursorLine' ) + if not signs.SignDefined( 'vimspectorCurrentFrame' ): + signs.DefineSign( 'vimspectorCurrentFrame', + text = '▶ ', + double_text = '▶', + texthl = 'Special', + linehl = 'CursorLine' ) + self._line_to_frame = {} self._line_to_thread = {} @@ -157,9 +166,12 @@ class StackTraceView( object ): self._sources = {} self._requesting_threads = StackTraceView.ThreadRequestState.NO self._pending_thread_request = None - if self._next_sign_id: - signs.UnplaceSign( self._next_sign_id, 'VimspectorStackTrace' ) - self._next_sign_id = 0 + if self._current_thread_sign_id: + signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' ) + self._current_thread_sign_id = 0 + if self._current_frame_sign_id: + signs.UnplaceSign( self._current_frame_sign_id, 'VimspectorStackTrace' ) + self._current_frame_sign_id = 0 with utils.ModifiableScratchBuffer( self._buf ): utils.ClearBuffer( self._buf ) @@ -273,10 +285,10 @@ class StackTraceView( object ): self._line_to_frame.clear() self._line_to_thread.clear() - if self._next_sign_id: - signs.UnplaceSign( self._next_sign_id, 'VimspectorStackTrace' ) + if self._current_thread_sign_id: + signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' ) else: - self._next_sign_id = 1 + self._current_thread_sign_id = 1 with utils.ModifiableScratchBuffer( self._buf ): with utils.RestoreCursorPosition(): @@ -290,7 +302,7 @@ class StackTraceView( object ): f'({thread.State()})' ) if self._current_thread == thread.id: - signs.PlaceSign( self._next_sign_id, + signs.PlaceSign( self._current_thread_sign_id, 'VimspectorStackTrace', 'vimspectorCurrentThread', self._buf.name, @@ -367,6 +379,46 @@ class StackTraceView( object ): self._JumpToFrame( frame ) + + def _GetFrameOffset( self, delta ): + thread: Thread + for thread in self._threads: + if thread.id != self._current_thread: + continue + + if not thread.stacktrace: + return + + frame_idx = None + for index, frame in enumerate( thread.stacktrace ): + if frame == self._current_frame: + frame_idx = index + break + + if frame_idx is not None: + target_idx = frame_idx + delta + if target_idx >= 0 and target_idx < len( thread.stacktrace ): + return thread.stacktrace[ target_idx ] + + break + + + def UpFrame( self ): + frame = self._GetFrameOffset( 1 ) + if not frame: + utils.UserMessage( 'Top of stack' ) + else: + self._JumpToFrame( frame, 'up' ) + + + def DownFrame( self ): + frame = self._GetFrameOffset( -1 ) + if not frame: + utils.UserMessage( 'Bottom of stack' ) + else: + self._JumpToFrame( frame, 'down' ) + + def AnyThreadsRunning( self ): for thread in self._threads: if thread.state != Thread.TERMINATED: @@ -381,6 +433,7 @@ class StackTraceView( object ): # Should this set the current _Thread_ too ? If i jump to a frame in # Thread 2, should that become the focussed thread ? self._current_frame = frame + self._DrawThreads() return self._session.SetCurrentFrame( self._current_frame, reason ) return False @@ -478,6 +531,11 @@ class StackTraceView( object ): if not thread.IsExpanded(): return + if self._current_frame_sign_id: + signs.UnplaceSign( self._current_frame_sign_id, 'VimspectorStackTrace' ) + else: + self._current_frame_sign_id = 2 + for frame in thread.stacktrace: if frame.get( 'source' ): source = frame[ 'source' ] @@ -502,6 +560,14 @@ class StackTraceView( object ): source[ 'name' ], frame[ 'line' ] ) ) + if ( self._current_frame is not None and + self._current_frame[ 'id' ] == frame[ 'id' ] ): + signs.PlaceSign( self._current_frame_sign_id, + 'VimspectorStackTrace', + 'vimspectorCurrentFrame', + self._buf.name, + line ) + self._line_to_frame[ line ] = ( thread, frame ) def _ResolveSource( self, source, and_then ): diff --git a/python3/vimspector/terminal.py b/python3/vimspector/terminal.py index 6ffd56a..0c84704 100644 --- a/python3/vimspector/terminal.py +++ b/python3/vimspector/terminal.py @@ -23,12 +23,53 @@ def LaunchTerminal( api_prefix, env = params.get( 'env' ) or {} term_options = { - 'vertical': 1, 'norestore': 1, 'cwd': cwd, 'env': env, } + if settings.Get( 'ui_mode' ) == 'horizontal': + # force-horizontal + term_options[ 'vertical' ] = 1 + elif utils.GetVimValue( vim.vars[ 'vimspector_session_windows' ], + 'mode' ) == 'horizontal': + # horizontal, which means that we should have enough space for: + # - sidebar + # - code min + # - term min width + # - + 2 vertical spaders + # - + 3 columns for signs + term_options[ 'vertical' ] = 1 + + # if we don't have enough space for terminal_maxwidth, then see if we have + # enough vertically for terminal_maxheight, in which case, + # that seems a better fit + term_horiz_max = ( settings.Int( 'sidebar_width' ) + + 1 + 2 + 3 + + settings.Int( 'code_minwidth' ) + + 1 + settings.Int( 'terminal_maxwidth' ) ) + term_vert_max = ( settings.Int( 'bottombar_height' ) + 1 + + settings.Int( 'code_minheight' ) + 1 + + settings.Int( 'terminal_minheight' ) ) + + if ( vim.options[ 'columns' ] < term_horiz_max and + vim.options[ 'lines' ] >= term_vert_max ): + # Looks like it, let's try that layout + term_options[ 'vertical' ] = 0 + + + else: + # vertical - we need enough space horizontally for the code+terminal, but we + # may fit better with code above terminal + term_options[ 'vertical' ] = 0 + + term_horiz_max = ( settings.Int( 'code_minwidth' ) + 3 + + settings.Int( 'terminal_maxwidth' ) + 1 ) + + if vim.options[ 'columns' ] > term_horiz_max: + term_options[ 'vertical' ] = 1 + + if not window_for_start or not window_for_start.valid: # TOOD: Where? Maybe we should just use botright vertical ... window_for_start = vim.current.window @@ -50,13 +91,23 @@ def LaunchTerminal( api_prefix, # If we're making a vertical split from the code window, make it no more # than 80 columns and no fewer than 10. Also try and keep the code window # at least 82 columns - if term_options[ 'vertical' ] and not term_options.get( 'curwin', 0 ): + if term_options.get( 'curwin', 0 ): + pass + elif term_options[ 'vertical' ]: term_options[ 'term_cols' ] = max( min ( int( vim.eval( 'winwidth( 0 )' ) ) - settings.Int( 'code_minwidth' ), settings.Int( 'terminal_maxwidth' ) ), settings.Int( 'terminal_minwidth' ) ) + else: + term_options[ 'term_rows' ] = max( + min ( int( vim.eval( 'winheight( 0 )' ) ) + - settings.Int( 'code_minheight' ), + settings.Int( 'terminal_maxheight' ) ), + settings.Int( 'terminal_minheight' ) + ) + buffer_number = int( utils.Call( diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 5aefc37..5f836fc 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -378,6 +378,7 @@ def AskForInput( prompt, default_value = None, completion = None ): CONFIRM = {} CONFIRM_ID = 0 + def ConfirmCallback( confirm_id, result ): try: handler = CONFIRM.pop( confirm_id ) @@ -390,14 +391,26 @@ def ConfirmCallback( confirm_id, result ): handler( result ) -def Confirm( api_prefix, prompt, handler, default_value = 1 ): +def Confirm( api_prefix, + prompt, + handler, + default_value = 2, + options: list = None, + keys: list = None ): + if not options: + options = [ '(Y)es', '(N)o' ] + if not keys: + keys = [ 'y', 'n' ] + global CONFIRM_ID CONFIRM_ID += 1 CONFIRM[ CONFIRM_ID ] = handler Call( f'vimspector#internal#{ api_prefix }popup#Confirm', CONFIRM_ID, prompt, - default_value ) + options, + default_value, + keys ) def AppendToBuffer( buf, line_or_lines, modified=False ): @@ -521,7 +534,6 @@ def _Substitute( template, mapping ): if mo.group( 'braceddefault' ) is not None: named = mo.group( 'defname' ) if named not in mapping: - '' raise MissingSubstitution( named, mo.group( 'default' ).replace( '\\}', '}' ) ) @@ -563,8 +575,11 @@ def ExpandReferencesInString( orig_s, if default_value is None and e.default_value is not None: try: default_value = _Substitute( e.default_value, mapping ) - except MissingSubstitution: - default_value = e.default_value + except MissingSubstitution as e2: + if e2.name in calculus: + default_value = calculus[ e2.name ]() + else: + default_value = e.default_value mapping[ key ] = AskForInput( 'Enter value for {}: '.format( key ), default_value ) diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index 8d8498a..8dcb493 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -580,33 +580,6 @@ class VariablesView( object ): }, failure_handler = failure_handler ) - def GetDataBreakpointInfo( self, - then, - buf = None, - line_num = None ): - variable: Variable - view: View - - if not self._server_capabilities.get( 'supportsDataBreakpoints' ): - return None - - variable, view = self._GetVariable( buf, line_num ) - if variable is None: - return None - - arguments = { - 'name': variable.variable[ 'name' ], - } - if variable.IsContained(): - arguments[ 'variablesReference' ] = ( - variable.container.VariablesReference() ) - - self._connection.DoRequest( lambda msg: then( msg[ 'body' ] ), { - 'command': 'dataBreakpointInfo', - 'arguments': arguments, - } ) - - def _DrawVariables( self, view, variables, indent, is_short = False ): assert indent > 0 diff --git a/run_tests b/run_tests index 39dc7ec..201ec1b 100755 --- a/run_tests +++ b/run_tests @@ -21,7 +21,7 @@ out_fd=1 while [ -n "$1" ]; do case "$1" in - "--basedir") + "--basedir"|"--base-dir"|"--test-base") shift SetBaseDir $1 shift @@ -36,7 +36,7 @@ while [ -n "$1" ]; do INSTALL=$1 shift ;; - "--update") + "--update"|"--upgrade") UPDATE=1 shift ;; @@ -91,7 +91,8 @@ if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "script" ]; then if ! python3 $(dirname $0)/install_gadget.py \ --basedir ${BASEDIR} \ ${INSTALLER_ARGS} \ - --all; then + --all \ + --force-enable-csharp; then echo "Script installation reported errors" >&2 exit 1 fi @@ -102,7 +103,7 @@ if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "vim" ]; then --cmd "${BASEDIR_CMD}" \ -c 'autocmd User VimspectorInstallSuccess qa!' \ -c 'autocmd User VimspectorInstallFailed cquit!' \ - -c "VimspectorInstall --all"; then + -c "VimspectorInstall --all netcoredbg"; then echo "Vim installation reported errors" >&2 exit 1 fi @@ -144,6 +145,9 @@ set -e pushd tests/testdata/cpp/simple make clean all popd + pushd support/test/csharp + dotnet build + popd set +e echo "%DONE - built test programs" diff --git a/support/custom_ui_vimrc b/support/custom_ui_vimrc index a8812cb..e76c6ee 100644 --- a/support/custom_ui_vimrc +++ b/support/custom_ui_vimrc @@ -54,7 +54,7 @@ function s:SetUpTerminal() let padding = 4 let cols = max( [ min( [ &columns - left_bar - code - padding, 80 ] ), 10 ] ) call win_gotoid( terminal_win ) - execute cols . 'wincmd |' + execute string(cols) . 'wincmd |' endfunction function! s:CustomiseWinBar() diff --git a/support/gadget_upgrade/README.md b/support/gadget_upgrade/README.md new file mode 100644 index 0000000..9ae3d7f --- /dev/null +++ b/support/gadget_upgrade/README.md @@ -0,0 +1,8 @@ +# Manually updating shipped gadgets + +Download the gadget files manuall from their official source into this dir. +Run `./checksum.py ` to get the checksums. + +Update ../../python3/vimspector/gadgets.py with the new version and the +checksums. + diff --git a/support/gadget_upgrade/checksum.py b/support/gadget_upgrade/checksum.py new file mode 100755 index 0000000..d0c1404 --- /dev/null +++ b/support/gadget_upgrade/checksum.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import hashlib +import sys + + +def GetChecksumSHA254( file_path ): + with open( file_path, 'rb' ) as existing_file: + return hashlib.sha256( existing_file.read() ).hexdigest() + + +for arg in sys.argv[ 1: ]: + print( f"{ arg } = { GetChecksumSHA254( arg ) }" ) diff --git a/support/test/bash/.vimspector.json b/support/test/bash/.vimspector.json new file mode 100644 index 0000000..a1be1b9 --- /dev/null +++ b/support/test/bash/.vimspector.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", + "configurations": { + "Run Current Script": { + "adapter": "vscode-bash", + "autoselect": false, + "configuration": { + "request": "launch", + "program": "${file}", + "cwd": "${fileDirname}", + "args": [ "*${args}" ] + } + } + } +} diff --git a/support/test/cpp/simple_c_program/.vimspector.json b/support/test/cpp/simple_c_program/.vimspector.json index 7b8c53a..fb4c958 100644 --- a/support/test/cpp/simple_c_program/.vimspector.json +++ b/support/test/cpp/simple_c_program/.vimspector.json @@ -15,6 +15,15 @@ "program": "${workspaceRoot}/test", "stopAtEntry": true } + }, + "cpptools": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/test", + "stopOnEntry": true, + "MIMode": "lldb" + } } } } diff --git a/support/test/cpp/simple_c_program/.ycm_extra_conf.py b/support/test/cpp/simple_c_program/.ycm_extra_conf.py index 0d17586..4203b36 100644 --- a/support/test/cpp/simple_c_program/.ycm_extra_conf.py +++ b/support/test/cpp/simple_c_program/.ycm_extra_conf.py @@ -1,4 +1,4 @@ def Settings( **kwargs ): return { - 'flags': [ '-x', 'c++', '-Wall', '-Wextra' ] + 'flags': [ '-x', 'c++', '-Wall', '-Wextra', '-std=c++17' ] } diff --git a/support/test/csharp/.gitignore b/support/test/csharp/.gitignore index b7d74e4..03cd7d8 100644 --- a/support/test/csharp/.gitignore +++ b/support/test/csharp/.gitignore @@ -1,2 +1,3 @@ bin/ obj/Debug +obj/ diff --git a/support/test/csharp/.vimspector.json b/support/test/csharp/.vimspector.json index 524ae1a..326739b 100644 --- a/support/test/csharp/.vimspector.json +++ b/support/test/csharp/.vimspector.json @@ -1,25 +1,57 @@ { - "configurations": { - "launch - netcoredbg": { - "adapter": "netcoredbg", - "configuration": { - "request": "launch", - "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", - "args": [], - "stopAtEntry": true - } + "adapters": { + "netcoredbg-debuglog": { + "attach": { + "pidProperty": "processId", + "pidSelect": "ask" }, - "launch - mono": { - "adapter": "vscode-mono-debug", - "configuration": { - "request": "launch", - "program": "${workspaceRoot}/Program.exe", - "console": "integratedTerminal", - "cwd": "${workspaceRoot}", - "args": [], - "env": {} - } + "command": [ + "${gadgetDir}/netcoredbg/netcoredbg", + "--interpreter=vscode", + "--engineLogging=${workspaceRoot}/netcoredbg.engine.log", + "--log=${workspaceRoot}/netcoredbg.log" + ], + "configuration": { + "cwd": "${workspaceRoot}" + }, + "name": "netcoredbg" + } + }, + "configurations": { + // + // NOTE: + // If you add to this, you must update tests/get_configurations.test.vim + // + + "launch - netcoredbg": { + "adapter": "netcoredbg", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/bin/Debug/netcoreapp3.1/csharp.dll", + "args": [], + "stopAtEntry": false + } + }, + "launch - netcoredbg - with debug log": { + "adapter": "netcoredbg-debuglog", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/bin/Debug/netcoreapp3.1/csharp.dll", + "args": [], + "stopAtEntry": false + } + }, + "launch - mono": { + "adapter": "vscode-mono-debug", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/Program.exe", + "console": "integratedTerminal", + "cwd": "${workspaceRoot}", + "args": [], + "env": {} } } + } } diff --git a/support/test/csharp/csharp.csproj b/support/test/csharp/csharp.csproj index 01d5113..d453e9a 100644 --- a/support/test/csharp/csharp.csproj +++ b/support/test/csharp/csharp.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.2 + netcoreapp3.1 diff --git a/support/test/csharp/csharp.sln b/support/test/csharp/csharp.sln index bba50e0..91f59bf 100644 --- a/support/test/csharp/csharp.sln +++ b/support/test/csharp/csharp.sln @@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csharp", "csharp.csproj", "{91DB205F-E422-430B-BBB8-955110C7B3B6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,4 +17,18 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x64.ActiveCfg = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x64.Build.0 = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x86.ActiveCfg = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x86.Build.0 = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|Any CPU.Build.0 = Release|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x64.ActiveCfg = Release|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x64.Build.0 = Release|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x86.ActiveCfg = Release|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection EndGlobal diff --git a/support/test/csharp/obj/csharp.csproj.nuget.cache b/support/test/csharp/obj/csharp.csproj.nuget.cache deleted file mode 100644 index 3ac8d84..0000000 --- a/support/test/csharp/obj/csharp.csproj.nuget.cache +++ /dev/null @@ -1,5 +0,0 @@ -{ - "version": 1, - "dgSpecHash": "6/vdr7YprlSIoQecv/nNuLNflFpO0X7eN7jHUinZTsgian9nYpmHMWirsDWMi5l+29TH+Qy8O/QfaB/48QtjRQ==", - "success": true -} \ No newline at end of file diff --git a/support/test/csharp/obj/csharp.csproj.nuget.g.props b/support/test/csharp/obj/csharp.csproj.nuget.g.props deleted file mode 100644 index c71f0e6..0000000 --- a/support/test/csharp/obj/csharp.csproj.nuget.g.props +++ /dev/null @@ -1,21 +0,0 @@ - - - - True - NuGet - $(MSBuildThisFileDirectory)project.assets.json - /Users/ben/.nuget/packages/ - /Users/ben/.nuget/packages/;/usr/local/share/dotnet/sdk/NuGetFallbackFolder - PackageReference - 5.7.0 - - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - \ No newline at end of file diff --git a/support/test/csharp/obj/csharp.csproj.nuget.g.targets b/support/test/csharp/obj/csharp.csproj.nuget.g.targets deleted file mode 100644 index 099158b..0000000 --- a/support/test/csharp/obj/csharp.csproj.nuget.g.targets +++ /dev/null @@ -1,10 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - - \ No newline at end of file diff --git a/support/test/csharp/obj/project.assets.json b/support/test/csharp/obj/project.assets.json deleted file mode 100644 index bd6c0fc..0000000 --- a/support/test/csharp/obj/project.assets.json +++ /dev/null @@ -1,748 +0,0 @@ -{ - "version": 3, - "targets": { - ".NETCoreApp,Version=v2.2": { - "Microsoft.NETCore.App/2.2.0": { - "type": "package", - "dependencies": { - "Microsoft.NETCore.DotNetHostPolicy": "2.2.0", - "Microsoft.NETCore.Platforms": "2.2.0", - "Microsoft.NETCore.Targets": "2.0.0", - "NETStandard.Library": "2.0.3" - }, - "compile": { - "ref/netcoreapp2.2/Microsoft.CSharp.dll": {}, - "ref/netcoreapp2.2/Microsoft.VisualBasic.dll": {}, - "ref/netcoreapp2.2/Microsoft.Win32.Primitives.dll": {}, - "ref/netcoreapp2.2/System.AppContext.dll": {}, - "ref/netcoreapp2.2/System.Buffers.dll": {}, - "ref/netcoreapp2.2/System.Collections.Concurrent.dll": {}, - "ref/netcoreapp2.2/System.Collections.Immutable.dll": {}, - "ref/netcoreapp2.2/System.Collections.NonGeneric.dll": {}, - "ref/netcoreapp2.2/System.Collections.Specialized.dll": {}, - "ref/netcoreapp2.2/System.Collections.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.Annotations.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.DataAnnotations.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.Primitives.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.TypeConverter.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.dll": {}, - "ref/netcoreapp2.2/System.Configuration.dll": {}, - "ref/netcoreapp2.2/System.Console.dll": {}, - "ref/netcoreapp2.2/System.Core.dll": {}, - "ref/netcoreapp2.2/System.Data.Common.dll": {}, - "ref/netcoreapp2.2/System.Data.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.Contracts.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.Debug.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.Process.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.StackTrace.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.Tools.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.TraceSource.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.Tracing.dll": {}, - "ref/netcoreapp2.2/System.Drawing.Primitives.dll": {}, - "ref/netcoreapp2.2/System.Drawing.dll": {}, - "ref/netcoreapp2.2/System.Dynamic.Runtime.dll": {}, - "ref/netcoreapp2.2/System.Globalization.Calendars.dll": {}, - "ref/netcoreapp2.2/System.Globalization.Extensions.dll": {}, - "ref/netcoreapp2.2/System.Globalization.dll": {}, - "ref/netcoreapp2.2/System.IO.Compression.Brotli.dll": {}, - "ref/netcoreapp2.2/System.IO.Compression.FileSystem.dll": {}, - "ref/netcoreapp2.2/System.IO.Compression.ZipFile.dll": {}, - "ref/netcoreapp2.2/System.IO.Compression.dll": {}, - "ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.dll": {}, - "ref/netcoreapp2.2/System.IO.FileSystem.Primitives.dll": {}, - "ref/netcoreapp2.2/System.IO.FileSystem.Watcher.dll": {}, - "ref/netcoreapp2.2/System.IO.FileSystem.dll": {}, - "ref/netcoreapp2.2/System.IO.IsolatedStorage.dll": {}, - "ref/netcoreapp2.2/System.IO.MemoryMappedFiles.dll": {}, - "ref/netcoreapp2.2/System.IO.Pipes.dll": {}, - "ref/netcoreapp2.2/System.IO.UnmanagedMemoryStream.dll": {}, - "ref/netcoreapp2.2/System.IO.dll": {}, - "ref/netcoreapp2.2/System.Linq.Expressions.dll": {}, - "ref/netcoreapp2.2/System.Linq.Parallel.dll": {}, - "ref/netcoreapp2.2/System.Linq.Queryable.dll": {}, - "ref/netcoreapp2.2/System.Linq.dll": {}, - "ref/netcoreapp2.2/System.Memory.dll": {}, - "ref/netcoreapp2.2/System.Net.Http.dll": {}, - "ref/netcoreapp2.2/System.Net.HttpListener.dll": {}, - "ref/netcoreapp2.2/System.Net.Mail.dll": {}, - "ref/netcoreapp2.2/System.Net.NameResolution.dll": {}, - "ref/netcoreapp2.2/System.Net.NetworkInformation.dll": {}, - "ref/netcoreapp2.2/System.Net.Ping.dll": {}, - "ref/netcoreapp2.2/System.Net.Primitives.dll": {}, - "ref/netcoreapp2.2/System.Net.Requests.dll": {}, - "ref/netcoreapp2.2/System.Net.Security.dll": {}, - "ref/netcoreapp2.2/System.Net.ServicePoint.dll": {}, - "ref/netcoreapp2.2/System.Net.Sockets.dll": {}, - "ref/netcoreapp2.2/System.Net.WebClient.dll": {}, - "ref/netcoreapp2.2/System.Net.WebHeaderCollection.dll": {}, - "ref/netcoreapp2.2/System.Net.WebProxy.dll": {}, - "ref/netcoreapp2.2/System.Net.WebSockets.Client.dll": {}, - "ref/netcoreapp2.2/System.Net.WebSockets.dll": {}, - "ref/netcoreapp2.2/System.Net.dll": {}, - "ref/netcoreapp2.2/System.Numerics.Vectors.dll": {}, - "ref/netcoreapp2.2/System.Numerics.dll": {}, - "ref/netcoreapp2.2/System.ObjectModel.dll": {}, - "ref/netcoreapp2.2/System.Reflection.DispatchProxy.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Emit.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Extensions.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Metadata.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Primitives.dll": {}, - "ref/netcoreapp2.2/System.Reflection.TypeExtensions.dll": {}, - "ref/netcoreapp2.2/System.Reflection.dll": {}, - "ref/netcoreapp2.2/System.Resources.Reader.dll": {}, - "ref/netcoreapp2.2/System.Resources.ResourceManager.dll": {}, - "ref/netcoreapp2.2/System.Resources.Writer.dll": {}, - "ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Extensions.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Handles.dll": {}, - "ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.dll": {}, - "ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.dll": {}, - "ref/netcoreapp2.2/System.Runtime.InteropServices.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Loader.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Numerics.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Serialization.Json.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Serialization.Xml.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Serialization.dll": {}, - "ref/netcoreapp2.2/System.Runtime.dll": {}, - "ref/netcoreapp2.2/System.Security.Claims.dll": {}, - "ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.dll": {}, - "ref/netcoreapp2.2/System.Security.Cryptography.Csp.dll": {}, - "ref/netcoreapp2.2/System.Security.Cryptography.Encoding.dll": {}, - "ref/netcoreapp2.2/System.Security.Cryptography.Primitives.dll": {}, - "ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.dll": {}, - "ref/netcoreapp2.2/System.Security.Principal.dll": {}, - "ref/netcoreapp2.2/System.Security.SecureString.dll": {}, - "ref/netcoreapp2.2/System.Security.dll": {}, - "ref/netcoreapp2.2/System.ServiceModel.Web.dll": {}, - "ref/netcoreapp2.2/System.ServiceProcess.dll": {}, - "ref/netcoreapp2.2/System.Text.Encoding.Extensions.dll": {}, - "ref/netcoreapp2.2/System.Text.Encoding.dll": {}, - "ref/netcoreapp2.2/System.Text.RegularExpressions.dll": {}, - "ref/netcoreapp2.2/System.Threading.Overlapped.dll": {}, - "ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.dll": {}, - "ref/netcoreapp2.2/System.Threading.Tasks.Extensions.dll": {}, - "ref/netcoreapp2.2/System.Threading.Tasks.Parallel.dll": {}, - "ref/netcoreapp2.2/System.Threading.Tasks.dll": {}, - "ref/netcoreapp2.2/System.Threading.Thread.dll": {}, - "ref/netcoreapp2.2/System.Threading.ThreadPool.dll": {}, - "ref/netcoreapp2.2/System.Threading.Timer.dll": {}, - "ref/netcoreapp2.2/System.Threading.dll": {}, - "ref/netcoreapp2.2/System.Transactions.Local.dll": {}, - "ref/netcoreapp2.2/System.Transactions.dll": {}, - "ref/netcoreapp2.2/System.ValueTuple.dll": {}, - "ref/netcoreapp2.2/System.Web.HttpUtility.dll": {}, - "ref/netcoreapp2.2/System.Web.dll": {}, - "ref/netcoreapp2.2/System.Windows.dll": {}, - "ref/netcoreapp2.2/System.Xml.Linq.dll": {}, - "ref/netcoreapp2.2/System.Xml.ReaderWriter.dll": {}, - "ref/netcoreapp2.2/System.Xml.Serialization.dll": {}, - "ref/netcoreapp2.2/System.Xml.XDocument.dll": {}, - "ref/netcoreapp2.2/System.Xml.XPath.XDocument.dll": {}, - "ref/netcoreapp2.2/System.Xml.XPath.dll": {}, - "ref/netcoreapp2.2/System.Xml.XmlDocument.dll": {}, - "ref/netcoreapp2.2/System.Xml.XmlSerializer.dll": {}, - "ref/netcoreapp2.2/System.Xml.dll": {}, - "ref/netcoreapp2.2/System.dll": {}, - "ref/netcoreapp2.2/WindowsBase.dll": {}, - "ref/netcoreapp2.2/mscorlib.dll": {}, - "ref/netcoreapp2.2/netstandard.dll": {} - }, - "build": { - "build/netcoreapp2.2/Microsoft.NETCore.App.props": {}, - "build/netcoreapp2.2/Microsoft.NETCore.App.targets": {} - } - }, - "Microsoft.NETCore.DotNetAppHost/2.2.0": { - "type": "package" - }, - "Microsoft.NETCore.DotNetHostPolicy/2.2.0": { - "type": "package", - "dependencies": { - "Microsoft.NETCore.DotNetHostResolver": "2.2.0" - } - }, - "Microsoft.NETCore.DotNetHostResolver/2.2.0": { - "type": "package", - "dependencies": { - "Microsoft.NETCore.DotNetAppHost": "2.2.0" - } - }, - "Microsoft.NETCore.Platforms/2.2.0": { - "type": "package", - "compile": { - "lib/netstandard1.0/_._": {} - }, - "runtime": { - "lib/netstandard1.0/_._": {} - } - }, - "Microsoft.NETCore.Targets/2.0.0": { - "type": "package", - "compile": { - "lib/netstandard1.0/_._": {} - }, - "runtime": { - "lib/netstandard1.0/_._": {} - } - }, - "NETStandard.Library/2.0.3": { - "type": "package", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0" - }, - "compile": { - "lib/netstandard1.0/_._": {} - }, - "runtime": { - "lib/netstandard1.0/_._": {} - }, - "build": { - "build/netstandard2.0/NETStandard.Library.targets": {} - } - } - } - }, - "libraries": { - "Microsoft.NETCore.App/2.2.0": { - "sha512": "7z5l8Jp324S8bU8+yyWeYHXUFYvKyiI5lqS1dXgTzOx1H69Qbf6df12kCKlNX45LpMfCMd4U3M6p7Rl5Zk7SLA==", - "type": "package", - "path": "microsoft.netcore.app/2.2.0", - "files": [ - ".nupkg.metadata", - ".signature.p7s", - "LICENSE.TXT", - "Microsoft.NETCore.App.versions.txt", - "THIRD-PARTY-NOTICES.TXT", - "build/netcoreapp2.2/Microsoft.NETCore.App.PlatformManifest.txt", - "build/netcoreapp2.2/Microsoft.NETCore.App.props", - "build/netcoreapp2.2/Microsoft.NETCore.App.targets", - "microsoft.netcore.app.2.2.0.nupkg.sha512", - "microsoft.netcore.app.nuspec", - "ref/netcoreapp2.2/Microsoft.CSharp.dll", - "ref/netcoreapp2.2/Microsoft.CSharp.xml", - "ref/netcoreapp2.2/Microsoft.VisualBasic.dll", - "ref/netcoreapp2.2/Microsoft.VisualBasic.xml", - "ref/netcoreapp2.2/Microsoft.Win32.Primitives.dll", - "ref/netcoreapp2.2/Microsoft.Win32.Primitives.xml", - "ref/netcoreapp2.2/System.AppContext.dll", - "ref/netcoreapp2.2/System.Buffers.dll", - "ref/netcoreapp2.2/System.Buffers.xml", - "ref/netcoreapp2.2/System.Collections.Concurrent.dll", - "ref/netcoreapp2.2/System.Collections.Concurrent.xml", - "ref/netcoreapp2.2/System.Collections.Immutable.dll", - "ref/netcoreapp2.2/System.Collections.Immutable.xml", - "ref/netcoreapp2.2/System.Collections.NonGeneric.dll", - "ref/netcoreapp2.2/System.Collections.NonGeneric.xml", - "ref/netcoreapp2.2/System.Collections.Specialized.dll", - "ref/netcoreapp2.2/System.Collections.Specialized.xml", - "ref/netcoreapp2.2/System.Collections.dll", - "ref/netcoreapp2.2/System.Collections.xml", - "ref/netcoreapp2.2/System.ComponentModel.Annotations.dll", - "ref/netcoreapp2.2/System.ComponentModel.Annotations.xml", - "ref/netcoreapp2.2/System.ComponentModel.DataAnnotations.dll", - "ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.dll", - "ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.xml", - "ref/netcoreapp2.2/System.ComponentModel.Primitives.dll", - "ref/netcoreapp2.2/System.ComponentModel.Primitives.xml", - "ref/netcoreapp2.2/System.ComponentModel.TypeConverter.dll", - "ref/netcoreapp2.2/System.ComponentModel.TypeConverter.xml", - "ref/netcoreapp2.2/System.ComponentModel.dll", - "ref/netcoreapp2.2/System.ComponentModel.xml", - "ref/netcoreapp2.2/System.Configuration.dll", - "ref/netcoreapp2.2/System.Console.dll", - "ref/netcoreapp2.2/System.Console.xml", - "ref/netcoreapp2.2/System.Core.dll", - "ref/netcoreapp2.2/System.Data.Common.dll", - "ref/netcoreapp2.2/System.Data.Common.xml", - "ref/netcoreapp2.2/System.Data.dll", - "ref/netcoreapp2.2/System.Diagnostics.Contracts.dll", - "ref/netcoreapp2.2/System.Diagnostics.Contracts.xml", - "ref/netcoreapp2.2/System.Diagnostics.Debug.dll", - "ref/netcoreapp2.2/System.Diagnostics.Debug.xml", - "ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.dll", - "ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.xml", - "ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.dll", - "ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.xml", - "ref/netcoreapp2.2/System.Diagnostics.Process.dll", - "ref/netcoreapp2.2/System.Diagnostics.Process.xml", - "ref/netcoreapp2.2/System.Diagnostics.StackTrace.dll", - "ref/netcoreapp2.2/System.Diagnostics.StackTrace.xml", - "ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.dll", - "ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.xml", - "ref/netcoreapp2.2/System.Diagnostics.Tools.dll", - "ref/netcoreapp2.2/System.Diagnostics.Tools.xml", - "ref/netcoreapp2.2/System.Diagnostics.TraceSource.dll", - "ref/netcoreapp2.2/System.Diagnostics.TraceSource.xml", - "ref/netcoreapp2.2/System.Diagnostics.Tracing.dll", - "ref/netcoreapp2.2/System.Diagnostics.Tracing.xml", - "ref/netcoreapp2.2/System.Drawing.Primitives.dll", - "ref/netcoreapp2.2/System.Drawing.Primitives.xml", - "ref/netcoreapp2.2/System.Drawing.dll", - "ref/netcoreapp2.2/System.Dynamic.Runtime.dll", - "ref/netcoreapp2.2/System.Globalization.Calendars.dll", - "ref/netcoreapp2.2/System.Globalization.Extensions.dll", - "ref/netcoreapp2.2/System.Globalization.dll", - "ref/netcoreapp2.2/System.IO.Compression.Brotli.dll", - "ref/netcoreapp2.2/System.IO.Compression.FileSystem.dll", - "ref/netcoreapp2.2/System.IO.Compression.ZipFile.dll", - "ref/netcoreapp2.2/System.IO.Compression.ZipFile.xml", - "ref/netcoreapp2.2/System.IO.Compression.dll", - "ref/netcoreapp2.2/System.IO.Compression.xml", - "ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.dll", - "ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.xml", - "ref/netcoreapp2.2/System.IO.FileSystem.Primitives.dll", - "ref/netcoreapp2.2/System.IO.FileSystem.Watcher.dll", - "ref/netcoreapp2.2/System.IO.FileSystem.Watcher.xml", - "ref/netcoreapp2.2/System.IO.FileSystem.dll", - "ref/netcoreapp2.2/System.IO.FileSystem.xml", - "ref/netcoreapp2.2/System.IO.IsolatedStorage.dll", - "ref/netcoreapp2.2/System.IO.IsolatedStorage.xml", - "ref/netcoreapp2.2/System.IO.MemoryMappedFiles.dll", - "ref/netcoreapp2.2/System.IO.MemoryMappedFiles.xml", - "ref/netcoreapp2.2/System.IO.Pipes.dll", - "ref/netcoreapp2.2/System.IO.Pipes.xml", - "ref/netcoreapp2.2/System.IO.UnmanagedMemoryStream.dll", - "ref/netcoreapp2.2/System.IO.dll", - "ref/netcoreapp2.2/System.Linq.Expressions.dll", - "ref/netcoreapp2.2/System.Linq.Expressions.xml", - "ref/netcoreapp2.2/System.Linq.Parallel.dll", - "ref/netcoreapp2.2/System.Linq.Parallel.xml", - "ref/netcoreapp2.2/System.Linq.Queryable.dll", - "ref/netcoreapp2.2/System.Linq.Queryable.xml", - "ref/netcoreapp2.2/System.Linq.dll", - "ref/netcoreapp2.2/System.Linq.xml", - "ref/netcoreapp2.2/System.Memory.dll", - "ref/netcoreapp2.2/System.Memory.xml", - "ref/netcoreapp2.2/System.Net.Http.dll", - "ref/netcoreapp2.2/System.Net.Http.xml", - "ref/netcoreapp2.2/System.Net.HttpListener.dll", - "ref/netcoreapp2.2/System.Net.HttpListener.xml", - "ref/netcoreapp2.2/System.Net.Mail.dll", - "ref/netcoreapp2.2/System.Net.Mail.xml", - "ref/netcoreapp2.2/System.Net.NameResolution.dll", - "ref/netcoreapp2.2/System.Net.NameResolution.xml", - "ref/netcoreapp2.2/System.Net.NetworkInformation.dll", - "ref/netcoreapp2.2/System.Net.NetworkInformation.xml", - "ref/netcoreapp2.2/System.Net.Ping.dll", - "ref/netcoreapp2.2/System.Net.Ping.xml", - "ref/netcoreapp2.2/System.Net.Primitives.dll", - "ref/netcoreapp2.2/System.Net.Primitives.xml", - "ref/netcoreapp2.2/System.Net.Requests.dll", - "ref/netcoreapp2.2/System.Net.Requests.xml", - "ref/netcoreapp2.2/System.Net.Security.dll", - "ref/netcoreapp2.2/System.Net.Security.xml", - "ref/netcoreapp2.2/System.Net.ServicePoint.dll", - "ref/netcoreapp2.2/System.Net.ServicePoint.xml", - "ref/netcoreapp2.2/System.Net.Sockets.dll", - "ref/netcoreapp2.2/System.Net.Sockets.xml", - "ref/netcoreapp2.2/System.Net.WebClient.dll", - "ref/netcoreapp2.2/System.Net.WebClient.xml", - "ref/netcoreapp2.2/System.Net.WebHeaderCollection.dll", - "ref/netcoreapp2.2/System.Net.WebHeaderCollection.xml", - "ref/netcoreapp2.2/System.Net.WebProxy.dll", - "ref/netcoreapp2.2/System.Net.WebProxy.xml", - "ref/netcoreapp2.2/System.Net.WebSockets.Client.dll", - "ref/netcoreapp2.2/System.Net.WebSockets.Client.xml", - "ref/netcoreapp2.2/System.Net.WebSockets.dll", - "ref/netcoreapp2.2/System.Net.WebSockets.xml", - "ref/netcoreapp2.2/System.Net.dll", - "ref/netcoreapp2.2/System.Numerics.Vectors.dll", - "ref/netcoreapp2.2/System.Numerics.Vectors.xml", - "ref/netcoreapp2.2/System.Numerics.dll", - "ref/netcoreapp2.2/System.ObjectModel.dll", - "ref/netcoreapp2.2/System.ObjectModel.xml", - "ref/netcoreapp2.2/System.Reflection.DispatchProxy.dll", - "ref/netcoreapp2.2/System.Reflection.DispatchProxy.xml", - "ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.dll", - "ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.xml", - "ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.dll", - "ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.xml", - "ref/netcoreapp2.2/System.Reflection.Emit.dll", - "ref/netcoreapp2.2/System.Reflection.Emit.xml", - "ref/netcoreapp2.2/System.Reflection.Extensions.dll", - "ref/netcoreapp2.2/System.Reflection.Metadata.dll", - "ref/netcoreapp2.2/System.Reflection.Metadata.xml", - "ref/netcoreapp2.2/System.Reflection.Primitives.dll", - "ref/netcoreapp2.2/System.Reflection.Primitives.xml", - "ref/netcoreapp2.2/System.Reflection.TypeExtensions.dll", - "ref/netcoreapp2.2/System.Reflection.TypeExtensions.xml", - "ref/netcoreapp2.2/System.Reflection.dll", - "ref/netcoreapp2.2/System.Resources.Reader.dll", - "ref/netcoreapp2.2/System.Resources.ResourceManager.dll", - "ref/netcoreapp2.2/System.Resources.ResourceManager.xml", - "ref/netcoreapp2.2/System.Resources.Writer.dll", - "ref/netcoreapp2.2/System.Resources.Writer.xml", - "ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.dll", - "ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.xml", - "ref/netcoreapp2.2/System.Runtime.Extensions.dll", - "ref/netcoreapp2.2/System.Runtime.Extensions.xml", - "ref/netcoreapp2.2/System.Runtime.Handles.dll", - "ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.dll", - "ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.xml", - "ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.dll", - "ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.xml", - "ref/netcoreapp2.2/System.Runtime.InteropServices.dll", - "ref/netcoreapp2.2/System.Runtime.InteropServices.xml", - "ref/netcoreapp2.2/System.Runtime.Loader.dll", - "ref/netcoreapp2.2/System.Runtime.Loader.xml", - "ref/netcoreapp2.2/System.Runtime.Numerics.dll", - "ref/netcoreapp2.2/System.Runtime.Numerics.xml", - "ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.dll", - "ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.xml", - "ref/netcoreapp2.2/System.Runtime.Serialization.Json.dll", - "ref/netcoreapp2.2/System.Runtime.Serialization.Json.xml", - "ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.dll", - "ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.xml", - "ref/netcoreapp2.2/System.Runtime.Serialization.Xml.dll", - "ref/netcoreapp2.2/System.Runtime.Serialization.Xml.xml", - "ref/netcoreapp2.2/System.Runtime.Serialization.dll", - "ref/netcoreapp2.2/System.Runtime.dll", - "ref/netcoreapp2.2/System.Runtime.xml", - "ref/netcoreapp2.2/System.Security.Claims.dll", - "ref/netcoreapp2.2/System.Security.Claims.xml", - "ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.dll", - "ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.xml", - "ref/netcoreapp2.2/System.Security.Cryptography.Csp.dll", - "ref/netcoreapp2.2/System.Security.Cryptography.Csp.xml", - "ref/netcoreapp2.2/System.Security.Cryptography.Encoding.dll", - "ref/netcoreapp2.2/System.Security.Cryptography.Encoding.xml", - "ref/netcoreapp2.2/System.Security.Cryptography.Primitives.dll", - "ref/netcoreapp2.2/System.Security.Cryptography.Primitives.xml", - "ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.dll", - "ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.xml", - "ref/netcoreapp2.2/System.Security.Principal.dll", - "ref/netcoreapp2.2/System.Security.Principal.xml", - "ref/netcoreapp2.2/System.Security.SecureString.dll", - "ref/netcoreapp2.2/System.Security.dll", - "ref/netcoreapp2.2/System.ServiceModel.Web.dll", - "ref/netcoreapp2.2/System.ServiceProcess.dll", - "ref/netcoreapp2.2/System.Text.Encoding.Extensions.dll", - "ref/netcoreapp2.2/System.Text.Encoding.Extensions.xml", - "ref/netcoreapp2.2/System.Text.Encoding.dll", - "ref/netcoreapp2.2/System.Text.RegularExpressions.dll", - "ref/netcoreapp2.2/System.Text.RegularExpressions.xml", - "ref/netcoreapp2.2/System.Threading.Overlapped.dll", - "ref/netcoreapp2.2/System.Threading.Overlapped.xml", - "ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.dll", - "ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.xml", - "ref/netcoreapp2.2/System.Threading.Tasks.Extensions.dll", - "ref/netcoreapp2.2/System.Threading.Tasks.Extensions.xml", - "ref/netcoreapp2.2/System.Threading.Tasks.Parallel.dll", - "ref/netcoreapp2.2/System.Threading.Tasks.Parallel.xml", - "ref/netcoreapp2.2/System.Threading.Tasks.dll", - "ref/netcoreapp2.2/System.Threading.Tasks.xml", - "ref/netcoreapp2.2/System.Threading.Thread.dll", - "ref/netcoreapp2.2/System.Threading.Thread.xml", - "ref/netcoreapp2.2/System.Threading.ThreadPool.dll", - "ref/netcoreapp2.2/System.Threading.ThreadPool.xml", - "ref/netcoreapp2.2/System.Threading.Timer.dll", - "ref/netcoreapp2.2/System.Threading.Timer.xml", - "ref/netcoreapp2.2/System.Threading.dll", - "ref/netcoreapp2.2/System.Threading.xml", - "ref/netcoreapp2.2/System.Transactions.Local.dll", - "ref/netcoreapp2.2/System.Transactions.Local.xml", - "ref/netcoreapp2.2/System.Transactions.dll", - "ref/netcoreapp2.2/System.ValueTuple.dll", - "ref/netcoreapp2.2/System.Web.HttpUtility.dll", - "ref/netcoreapp2.2/System.Web.HttpUtility.xml", - "ref/netcoreapp2.2/System.Web.dll", - "ref/netcoreapp2.2/System.Windows.dll", - "ref/netcoreapp2.2/System.Xml.Linq.dll", - "ref/netcoreapp2.2/System.Xml.ReaderWriter.dll", - "ref/netcoreapp2.2/System.Xml.ReaderWriter.xml", - "ref/netcoreapp2.2/System.Xml.Serialization.dll", - "ref/netcoreapp2.2/System.Xml.XDocument.dll", - "ref/netcoreapp2.2/System.Xml.XDocument.xml", - "ref/netcoreapp2.2/System.Xml.XPath.XDocument.dll", - "ref/netcoreapp2.2/System.Xml.XPath.XDocument.xml", - "ref/netcoreapp2.2/System.Xml.XPath.dll", - "ref/netcoreapp2.2/System.Xml.XPath.xml", - "ref/netcoreapp2.2/System.Xml.XmlDocument.dll", - "ref/netcoreapp2.2/System.Xml.XmlSerializer.dll", - "ref/netcoreapp2.2/System.Xml.XmlSerializer.xml", - "ref/netcoreapp2.2/System.Xml.dll", - "ref/netcoreapp2.2/System.dll", - "ref/netcoreapp2.2/WindowsBase.dll", - "ref/netcoreapp2.2/mscorlib.dll", - "ref/netcoreapp2.2/netstandard.dll", - "runtime.json" - ] - }, - "Microsoft.NETCore.DotNetAppHost/2.2.0": { - "sha512": "DrhaKInRKKvN6Ns2VNIlC7ZffLOp9THf8cO6X4fytPRJovJUbF49/zzx4WfgX9E44FMsw9hT8hrKiIqDSHvGvA==", - "type": "package", - "path": "microsoft.netcore.dotnetapphost/2.2.0", - "files": [ - ".nupkg.metadata", - ".signature.p7s", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "microsoft.netcore.dotnetapphost.2.2.0.nupkg.sha512", - "microsoft.netcore.dotnetapphost.nuspec", - "runtime.json" - ] - }, - "Microsoft.NETCore.DotNetHostPolicy/2.2.0": { - "sha512": "FJie7IoPZFaPgNDxhZGmDBQP/Bs5vPdfca/G2Wf9gd6LIvMYkZcibtmJwB4tcf4KXkaOYfIOo4Cl9sEPMsSzkw==", - "type": "package", - "path": "microsoft.netcore.dotnethostpolicy/2.2.0", - "files": [ - ".nupkg.metadata", - ".signature.p7s", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "microsoft.netcore.dotnethostpolicy.2.2.0.nupkg.sha512", - "microsoft.netcore.dotnethostpolicy.nuspec", - "runtime.json" - ] - }, - "Microsoft.NETCore.DotNetHostResolver/2.2.0": { - "sha512": "spDm3AJYmebthDNhzY17YLPtvbc+Y1lCLVeiIH1uLJ/hZaM+40pBiPefFR8J1u66Ndkqi8ipR2tEbqPnYnjRhw==", - "type": "package", - "path": "microsoft.netcore.dotnethostresolver/2.2.0", - "files": [ - ".nupkg.metadata", - ".signature.p7s", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "microsoft.netcore.dotnethostresolver.2.2.0.nupkg.sha512", - "microsoft.netcore.dotnethostresolver.nuspec", - "runtime.json" - ] - }, - "Microsoft.NETCore.Platforms/2.2.0": { - "sha512": "T/J+XZo+YheFTJh8/4uoeJDdz5qOmOMkjg6/VL8mHJ9AnP8+fmV/kcbxeXsob0irRNiChf+V0ig1MCRLp/+Kog==", - "type": "package", - "path": "microsoft.netcore.platforms/2.2.0", - "files": [ - ".nupkg.metadata", - ".signature.p7s", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "lib/netstandard1.0/_._", - "microsoft.netcore.platforms.2.2.0.nupkg.sha512", - "microsoft.netcore.platforms.nuspec", - "runtime.json", - "useSharedDesignerContext.txt", - "version.txt" - ] - }, - "Microsoft.NETCore.Targets/2.0.0": { - "sha512": "odP/tJj1z6GylFpNo7pMtbd/xQgTC3Ex2If63dRTL38bBNMwsBnJ+RceUIyHdRBC0oik/3NehYT+oECwBhIM3Q==", - "type": "package", - "path": "microsoft.netcore.targets/2.0.0", - "files": [ - ".nupkg.metadata", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "lib/netstandard1.0/_._", - "microsoft.netcore.targets.2.0.0.nupkg.sha512", - "microsoft.netcore.targets.nuspec", - "runtime.json", - "useSharedDesignerContext.txt", - "version.txt" - ] - }, - "NETStandard.Library/2.0.3": { - "sha512": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", - "type": "package", - "path": "netstandard.library/2.0.3", - "files": [ - ".nupkg.metadata", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "build/netstandard2.0/NETStandard.Library.targets", - "build/netstandard2.0/ref/Microsoft.Win32.Primitives.dll", - "build/netstandard2.0/ref/System.AppContext.dll", - "build/netstandard2.0/ref/System.Collections.Concurrent.dll", - "build/netstandard2.0/ref/System.Collections.NonGeneric.dll", - "build/netstandard2.0/ref/System.Collections.Specialized.dll", - "build/netstandard2.0/ref/System.Collections.dll", - "build/netstandard2.0/ref/System.ComponentModel.Composition.dll", - "build/netstandard2.0/ref/System.ComponentModel.EventBasedAsync.dll", - "build/netstandard2.0/ref/System.ComponentModel.Primitives.dll", - "build/netstandard2.0/ref/System.ComponentModel.TypeConverter.dll", - "build/netstandard2.0/ref/System.ComponentModel.dll", - "build/netstandard2.0/ref/System.Console.dll", - "build/netstandard2.0/ref/System.Core.dll", - "build/netstandard2.0/ref/System.Data.Common.dll", - "build/netstandard2.0/ref/System.Data.dll", - "build/netstandard2.0/ref/System.Diagnostics.Contracts.dll", - "build/netstandard2.0/ref/System.Diagnostics.Debug.dll", - "build/netstandard2.0/ref/System.Diagnostics.FileVersionInfo.dll", - "build/netstandard2.0/ref/System.Diagnostics.Process.dll", - "build/netstandard2.0/ref/System.Diagnostics.StackTrace.dll", - "build/netstandard2.0/ref/System.Diagnostics.TextWriterTraceListener.dll", - "build/netstandard2.0/ref/System.Diagnostics.Tools.dll", - "build/netstandard2.0/ref/System.Diagnostics.TraceSource.dll", - "build/netstandard2.0/ref/System.Diagnostics.Tracing.dll", - "build/netstandard2.0/ref/System.Drawing.Primitives.dll", - "build/netstandard2.0/ref/System.Drawing.dll", - "build/netstandard2.0/ref/System.Dynamic.Runtime.dll", - "build/netstandard2.0/ref/System.Globalization.Calendars.dll", - "build/netstandard2.0/ref/System.Globalization.Extensions.dll", - "build/netstandard2.0/ref/System.Globalization.dll", - "build/netstandard2.0/ref/System.IO.Compression.FileSystem.dll", - "build/netstandard2.0/ref/System.IO.Compression.ZipFile.dll", - "build/netstandard2.0/ref/System.IO.Compression.dll", - "build/netstandard2.0/ref/System.IO.FileSystem.DriveInfo.dll", - "build/netstandard2.0/ref/System.IO.FileSystem.Primitives.dll", - "build/netstandard2.0/ref/System.IO.FileSystem.Watcher.dll", - "build/netstandard2.0/ref/System.IO.FileSystem.dll", - "build/netstandard2.0/ref/System.IO.IsolatedStorage.dll", - "build/netstandard2.0/ref/System.IO.MemoryMappedFiles.dll", - "build/netstandard2.0/ref/System.IO.Pipes.dll", - "build/netstandard2.0/ref/System.IO.UnmanagedMemoryStream.dll", - "build/netstandard2.0/ref/System.IO.dll", - "build/netstandard2.0/ref/System.Linq.Expressions.dll", - "build/netstandard2.0/ref/System.Linq.Parallel.dll", - "build/netstandard2.0/ref/System.Linq.Queryable.dll", - "build/netstandard2.0/ref/System.Linq.dll", - "build/netstandard2.0/ref/System.Net.Http.dll", - "build/netstandard2.0/ref/System.Net.NameResolution.dll", - "build/netstandard2.0/ref/System.Net.NetworkInformation.dll", - "build/netstandard2.0/ref/System.Net.Ping.dll", - "build/netstandard2.0/ref/System.Net.Primitives.dll", - "build/netstandard2.0/ref/System.Net.Requests.dll", - "build/netstandard2.0/ref/System.Net.Security.dll", - "build/netstandard2.0/ref/System.Net.Sockets.dll", - "build/netstandard2.0/ref/System.Net.WebHeaderCollection.dll", - "build/netstandard2.0/ref/System.Net.WebSockets.Client.dll", - "build/netstandard2.0/ref/System.Net.WebSockets.dll", - "build/netstandard2.0/ref/System.Net.dll", - "build/netstandard2.0/ref/System.Numerics.dll", - "build/netstandard2.0/ref/System.ObjectModel.dll", - "build/netstandard2.0/ref/System.Reflection.Extensions.dll", - "build/netstandard2.0/ref/System.Reflection.Primitives.dll", - "build/netstandard2.0/ref/System.Reflection.dll", - "build/netstandard2.0/ref/System.Resources.Reader.dll", - "build/netstandard2.0/ref/System.Resources.ResourceManager.dll", - "build/netstandard2.0/ref/System.Resources.Writer.dll", - "build/netstandard2.0/ref/System.Runtime.CompilerServices.VisualC.dll", - "build/netstandard2.0/ref/System.Runtime.Extensions.dll", - "build/netstandard2.0/ref/System.Runtime.Handles.dll", - "build/netstandard2.0/ref/System.Runtime.InteropServices.RuntimeInformation.dll", - "build/netstandard2.0/ref/System.Runtime.InteropServices.dll", - "build/netstandard2.0/ref/System.Runtime.Numerics.dll", - "build/netstandard2.0/ref/System.Runtime.Serialization.Formatters.dll", - "build/netstandard2.0/ref/System.Runtime.Serialization.Json.dll", - "build/netstandard2.0/ref/System.Runtime.Serialization.Primitives.dll", - "build/netstandard2.0/ref/System.Runtime.Serialization.Xml.dll", - "build/netstandard2.0/ref/System.Runtime.Serialization.dll", - "build/netstandard2.0/ref/System.Runtime.dll", - "build/netstandard2.0/ref/System.Security.Claims.dll", - "build/netstandard2.0/ref/System.Security.Cryptography.Algorithms.dll", - "build/netstandard2.0/ref/System.Security.Cryptography.Csp.dll", - "build/netstandard2.0/ref/System.Security.Cryptography.Encoding.dll", - "build/netstandard2.0/ref/System.Security.Cryptography.Primitives.dll", - "build/netstandard2.0/ref/System.Security.Cryptography.X509Certificates.dll", - "build/netstandard2.0/ref/System.Security.Principal.dll", - "build/netstandard2.0/ref/System.Security.SecureString.dll", - "build/netstandard2.0/ref/System.ServiceModel.Web.dll", - "build/netstandard2.0/ref/System.Text.Encoding.Extensions.dll", - "build/netstandard2.0/ref/System.Text.Encoding.dll", - "build/netstandard2.0/ref/System.Text.RegularExpressions.dll", - "build/netstandard2.0/ref/System.Threading.Overlapped.dll", - "build/netstandard2.0/ref/System.Threading.Tasks.Parallel.dll", - "build/netstandard2.0/ref/System.Threading.Tasks.dll", - "build/netstandard2.0/ref/System.Threading.Thread.dll", - "build/netstandard2.0/ref/System.Threading.ThreadPool.dll", - "build/netstandard2.0/ref/System.Threading.Timer.dll", - "build/netstandard2.0/ref/System.Threading.dll", - "build/netstandard2.0/ref/System.Transactions.dll", - "build/netstandard2.0/ref/System.ValueTuple.dll", - "build/netstandard2.0/ref/System.Web.dll", - "build/netstandard2.0/ref/System.Windows.dll", - "build/netstandard2.0/ref/System.Xml.Linq.dll", - "build/netstandard2.0/ref/System.Xml.ReaderWriter.dll", - "build/netstandard2.0/ref/System.Xml.Serialization.dll", - "build/netstandard2.0/ref/System.Xml.XDocument.dll", - "build/netstandard2.0/ref/System.Xml.XPath.XDocument.dll", - "build/netstandard2.0/ref/System.Xml.XPath.dll", - "build/netstandard2.0/ref/System.Xml.XmlDocument.dll", - "build/netstandard2.0/ref/System.Xml.XmlSerializer.dll", - "build/netstandard2.0/ref/System.Xml.dll", - "build/netstandard2.0/ref/System.dll", - "build/netstandard2.0/ref/mscorlib.dll", - "build/netstandard2.0/ref/netstandard.dll", - "build/netstandard2.0/ref/netstandard.xml", - "lib/netstandard1.0/_._", - "netstandard.library.2.0.3.nupkg.sha512", - "netstandard.library.nuspec" - ] - } - }, - "projectFileDependencyGroups": { - ".NETCoreApp,Version=v2.2": [ - "Microsoft.NETCore.App >= 2.2.0" - ] - }, - "packageFolders": { - "/Users/ben/.nuget/packages/": {}, - "/usr/local/share/dotnet/sdk/NuGetFallbackFolder": {} - }, - "project": { - "version": "1.0.0", - "restore": { - "projectUniqueName": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/csharp.csproj", - "projectName": "csharp", - "projectPath": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/csharp.csproj", - "packagesPath": "/Users/ben/.nuget/packages/", - "outputPath": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/obj/", - "projectStyle": "PackageReference", - "fallbackFolders": [ - "/usr/local/share/dotnet/sdk/NuGetFallbackFolder" - ], - "configFilePaths": [ - "/Users/ben/.nuget/NuGet/NuGet.Config" - ], - "originalTargetFrameworks": [ - "netcoreapp2.2" - ], - "sources": { - "https://api.nuget.org/v3/index.json": {} - }, - "frameworks": { - "netcoreapp2.2": { - "projectReferences": {} - } - }, - "warningProperties": { - "warnAsError": [ - "NU1605" - ] - } - }, - "frameworks": { - "netcoreapp2.2": { - "dependencies": { - "Microsoft.NETCore.App": { - "suppressParent": "All", - "target": "Package", - "version": "[2.2.0, )", - "autoReferenced": true - } - }, - "imports": [ - "net461", - "net462", - "net47", - "net471", - "net472", - "net48" - ], - "assetTargetFallback": true, - "warn": true, - "runtimeIdentifierGraphPath": "/usr/local/share/dotnet/sdk/3.1.402/RuntimeIdentifierGraph.json" - } - } - } -} \ No newline at end of file diff --git a/support/test/go/hello_world/.vimspector.json b/support/test/go/hello_world/.vimspector.json index 8ab5091..4613b98 100644 --- a/support/test/go/hello_world/.vimspector.json +++ b/support/test/go/hello_world/.vimspector.json @@ -1,4 +1,18 @@ { + "adapters": { + "dlv-dap": { + "variables": { + "port": "${unusedLocalPort}" + }, + "command": [ + "$HOME/go/bin/dlv", + "dap", + "--listen", + "127.0.0.1:${port}" + ], + "port": "${port}" + } + }, "configurations": { "run": { "adapter": "vscode-go", @@ -12,6 +26,21 @@ "env": { "GO111MODULE": "off" } } }, + "run-dap": { + "adapter": "dlv-dap", + "configuration": { + "request": "launch", + "env": { "GO111MODULE": "off" }, + + "mode": "debug", // debug|test + "program": "${workspaceRoot}/hello-world.go" + + // "args": [], + // "buildFlags": ... + // "stackTraceDepth": ..., + // "showGlobalVariables": true, + } + }, "run-exec": { // NOTE: To use this you _must_ disable optimistaion: // go build -o hello_world -gcflags="all=-N -l" diff --git a/support/test/go/hello_world/hello-world.go b/support/test/go/hello_world/hello-world.go index efff2c0..673d1b2 100644 --- a/support/test/go/hello_world/hello-world.go +++ b/support/test/go/hello_world/hello-world.go @@ -1,25 +1,6 @@ package main import "fmt" - -type Toaster struct { - Power int - Colour string -} - -type Test struct { - Test string - Toast Toaster -} - func main() { var v = "test" - test := Test{ - Test: "This is\na\ntest", - Toast: Toaster{ - Power: 10, - Colour: "green", - }, - } fmt.Println("hello world: " + v) - fmt.Println("Hi " + test.Test) } diff --git a/support/test/go/name-starts-with-vowel/.vimspector.json b/support/test/go/name-starts-with-vowel/.vimspector.json new file mode 100644 index 0000000..ffcfc93 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/.vimspector.json @@ -0,0 +1,29 @@ +{ + "configurations": { + "run-cmd": { + "adapter": "vscode-go", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/cmd/namestartswithvowel/main.go", + "mode": "debug", + "dlvToolPath": "$HOME/go/bin/dlv", + "dlvLoadConfig": { + "maxArrayValues": 1000, + "maxStringLen": 1000 + } + } + }, + "test-current-file": { + "adapter": "vscode-go", + "configuration": { + "request": "launch", + "mode": "test", + "program": "${fileDirname}", + "cwd": "${fileDirname}", + "dlvToolPath": "$GOPATH/bin/dlv", + "env": {}, + "args": [] + } + } + } +} diff --git a/support/test/go/name-starts-with-vowel/README.md b/support/test/go/name-starts-with-vowel/README.md new file mode 100644 index 0000000..fec967e --- /dev/null +++ b/support/test/go/name-starts-with-vowel/README.md @@ -0,0 +1,33 @@ +# Purpose + +This example comes with two example vimspector configs for the Go programming language. + +1) `run-cmd` will launch the main programme under `cmd/namestartswithvowel`. +1) `test-current-file` will run the tests in the current file in debug mode. + +## Example use-cases + +### run-cmd + +* Open `cmd/namestartswithvowel/main.go` +* Add a breakpoint somewhere within the programme +* Start the debugger (`:call vimspector#Continue()` or your relevant keymapping) +* Select the first launch configuration (`1: run-cmd`) + +### test-current-file + +* Open `internal/vowels/vowels_test.go` +* Add a breakpoint somewhere within the test +* Start the debugger (`:call vimspector#Continue()` or your relevant keymapping) +* Select the second launch configuration (`2: test-current-file`) + +## Additional Configuration + +There are two additional configuration options specified under `run-cmd`; these parameters configure the maximum string/array size to be shown while debugging. + +``` +"dlvLoadConfig": { + "maxArrayValues": 1000, + "maxStringLen": 1000 +} +``` diff --git a/support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go b/support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go new file mode 100644 index 0000000..c160aea --- /dev/null +++ b/support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + + "example.com/internal/vowels" +) + +func main() { + names := []string{"Simon", "Bob", "Jennifer", "Amy", "Duke", "Elizabeth"} + + for _, n := range names { + if vowels.NameStartsWithVowel(n) { + fmt.Printf("%s starts with a vowel!\n", n) + continue + } + + fmt.Printf("%s does not start with a vowel!\n", n) + } +} diff --git a/support/test/go/name-starts-with-vowel/go.mod b/support/test/go/name-starts-with-vowel/go.mod new file mode 100644 index 0000000..3070734 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/go.mod @@ -0,0 +1,3 @@ +module example.com + +go 1.16 diff --git a/support/test/go/name-starts-with-vowel/internal/vowels/vowels.go b/support/test/go/name-starts-with-vowel/internal/vowels/vowels.go new file mode 100644 index 0000000..4e76480 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/internal/vowels/vowels.go @@ -0,0 +1,9 @@ +package vowels + +import "strings" + +func NameStartsWithVowel(name string) bool { + s := strings.Split(strings.ToLower(name), "") + + return s[0] == "a" || s[0] == "e" || s[0] == "i" || s[0] == "o" || s[0] == "u" +} diff --git a/support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go b/support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go new file mode 100644 index 0000000..e0d5773 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go @@ -0,0 +1,30 @@ +package vowels + +import ( + "fmt" + "testing" +) + +func TestNameStartsWithVowel(t *testing.T) { + testCases := []struct { + input string + expectedOutput bool + }{ + { + input: "Simon", + expectedOutput: false, + }, + { + input: "Andy", + expectedOutput: true, + }, + } + for _, tt := range testCases { + t.Run(fmt.Sprintf("%s should product %t", tt.input, tt.expectedOutput), func(t *testing.T) { + out := NameStartsWithVowel(tt.input) + if out != tt.expectedOutput { + t.Errorf("%s produced %t, when %t was expected", tt.input, out, tt.expectedOutput) + } + }) + } +} diff --git a/tests/ci/image/Dockerfile b/tests/ci/image/Dockerfile index a25febc..164a5a7 100644 --- a/tests/ci/image/Dockerfile +++ b/tests/ci/image/Dockerfile @@ -70,6 +70,12 @@ RUN mkdir -p /home/linuxbrew/.linuxbrew &&\ RUN /home/linuxbrew/.linuxbrew/bin/brew install golang +# dotnet +RUN curl -sSL https://dot.net/v1/dotnet-install.sh \ + | bash /dev/stdin --channel LTS --install-dir /usr/share/dotnet && \ + update-alternatives --install /usr/bin/dotnet dotnet \ + /usr/share/dotnet/dotnet 1 + # clean up RUN /home/linuxbrew/.linuxbrew/bin/brew cleanup && \ rm -rf ~/.cache && \ diff --git a/tests/get_configurations.test.vim b/tests/get_configurations.test.vim index 4a37d01..33e6577 100644 --- a/tests/get_configurations.test.vim +++ b/tests/get_configurations.test.vim @@ -12,6 +12,7 @@ function Test_Get_Configurations() let configs = vimspector#GetConfigurations() call assert_equal([ \ 'launch - netcoredbg', + \ 'launch - netcoredbg - with debug log', \ 'launch - mono', \ ], configs) diff --git a/tests/language_csharp.test.vim b/tests/language_csharp.test.vim new file mode 100644 index 0000000..64cf954 --- /dev/null +++ b/tests/language_csharp.test.vim @@ -0,0 +1,65 @@ +function! SetUp() + call vimspector#test#setup#SetUpWithMappings( v:none ) +endfunction + +function! ClearDown() + call vimspector#test#setup#ClearDown() +endfunction + +function! SetUp_Test_Go_Simple() + let g:vimspector_enable_mappings = 'HUMAN' +endfunction + +function! Test_CSharp_Simple() + let fn='Program.cs' + lcd ../support/test/csharp + exe 'edit ' . fn + + call vimspector#SetLineBreakpoint( fn, 31 ) + call vimspector#LaunchWithSettings( { + \ 'configuration': 'launch - netcoredbg' + \ } ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 31, 7 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 31 ) + \ } ) + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 32, 12 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 32 ) + \ } ) + + call vimspector#test#setup#Reset() + + lcd - + %bwipeout! +endfunction + + +function! Test_Run_To_Cursor() + let fn='Program.cs' + lcd ../support/test/csharp + exe 'edit ' . fn + + call vimspector#SetLineBreakpoint( fn, 31 ) + call vimspector#LaunchWithSettings( { + \ 'configuration': 'launch - netcoredbg' + \ } ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 31, 7 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 31 ) + \ } ) + + call cursor( 33, 1 ) + call vimspector#RunToCursor() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 33, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 33 ) + \ } ) + + call vimspector#test#setup#Reset() + lcd - + %bwipeout! +endfunction + diff --git a/tests/lib/autoload/vimspector/test/setup.vim b/tests/lib/autoload/vimspector/test/setup.vim index b0296e0..6ab220c 100644 --- a/tests/lib/autoload/vimspector/test/setup.vim +++ b/tests/lib/autoload/vimspector/test/setup.vim @@ -50,3 +50,59 @@ function! vimspector#test#setup#Reset() abort call popup_clear() endfunction +let s:g_stack = {} + +function! vimspector#test#setup#PushGlobal( name, value ) abort + if !has_key( s:g_stack, a:name ) + let s:g_stack[ a:name ] = [] + endif + + let old_value = get( g:, a:name, v:null ) + call add( s:g_stack[ a:name ], old_value ) + let g:[ a:name ] = a:value + + return old_value +endfunction + +function! vimspector#test#setup#PopGlobal( name ) abort + if !has_key( s:g_stack, a:name ) || len( s:g_stack[ a:name ] ) == 0 + return v:null + endif + + let old_value = s:g_stack[ a:name ][ -1 ] + call remove( s:g_stack[ a:name ], -1 ) + + if old_value is v:null + silent! call remove( g:, a:name ) + else + let g:[ a:name ] = old_value + endif + + return old_value +endfunction + +let s:o_stack = {} + +function! vimspector#test#setup#PushOption( name, value ) abort + if !has_key( s:o_stack, a:name ) + let s:o_stack[ a:name ] = [] + endif + + let old_value = v:null + execute 'let old_value = &' . a:name + call add( s:o_stack[ a:name ], old_value ) + execute 'set ' . a:name . '=' . a:value + return old_value +endfunction + +function! vimspector#test#setup#PopOption( name ) abort + if !has_key( s:o_stack, a:name ) || len( s:o_stack[ a:name ] ) == 0 + return v:null + endif + + let old_value = s:o_stack[ a:name ][ -1 ] + call remove( s:o_stack[ a:name ], -1 ) + + execute 'set ' . a:name . '=' . old_value + return old_value +endfunction diff --git a/tests/lib/plugin/shared.vim b/tests/lib/plugin/shared.vim index 70e297e..f98b8e9 100644 --- a/tests/lib/plugin/shared.vim +++ b/tests/lib/plugin/shared.vim @@ -99,7 +99,7 @@ function! ThisTestIsFlaky() let g:test_is_flaky = v:true endfunction -function! AssertMatchist( expected, actual ) abort +function! AssertMatchList( expected, actual ) abort let ret = assert_equal( len( a:expected ), len( a:actual ) ) let len = min( [ len( a:expected ), len( a:actual ) ] ) let idx = 0 diff --git a/tests/python/Test_ExpandReferencesInDict.py b/tests/python/Test_ExpandReferencesInDict.py index 4998350..15fb11b 100644 --- a/tests/python/Test_ExpandReferencesInDict.py +++ b/tests/python/Test_ExpandReferencesInDict.py @@ -35,6 +35,7 @@ class TestExpandReferencesInDict( unittest.TestCase ): 'one': '${one}', 'two': '${one} and ${two}', 'three': '${three}', + 'three_with_default': '${three_with_default:${three\\}}', # uses calculus 'four': '${four}', 'five': '${five}', 'list': [ '*${words}' ], @@ -58,6 +59,7 @@ class TestExpandReferencesInDict( unittest.TestCase ): 'one': 'one', 'two': 'one and TWO', 'three': '3', + 'three_with_default': '3', 'four': 'typed text', 'five': '5ive!', 'list': [ 'these', 'are', 'some', 'words' ], diff --git a/tests/stack_trace.test.vim b/tests/stack_trace.test.vim index 569376c..b5ed795 100644 --- a/tests/stack_trace.test.vim +++ b/tests/stack_trace.test.vim @@ -30,7 +30,7 @@ function! Test_Multiple_Threads_Continue() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call cursor( 1, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -45,7 +45,7 @@ function! Test_Multiple_Threads_Continue() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call cursor( 1, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -56,7 +56,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -70,7 +70,7 @@ function! Test_Multiple_Threads_Continue() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call cursor( 1, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -81,7 +81,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -95,7 +95,7 @@ function! Test_Multiple_Threads_Continue() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call cursor( 1, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -106,7 +106,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -121,7 +121,7 @@ function! Test_Multiple_Threads_Continue() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call cursor( 1, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -132,7 +132,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -146,7 +146,7 @@ function! Test_Multiple_Threads_Continue() " So we break out of the loop call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, notify_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( notify_l ) @@ -157,7 +157,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -192,7 +192,7 @@ function! Test_Multiple_Threads_Step() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -205,7 +205,7 @@ function! Test_Multiple_Threads_Step() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -218,7 +218,7 @@ function! Test_Multiple_Threads_Step() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -230,7 +230,7 @@ function! Test_Multiple_Threads_Step() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -244,7 +244,7 @@ function! Test_Multiple_Threads_Step() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -257,7 +257,7 @@ function! Test_Multiple_Threads_Step() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -273,7 +273,7 @@ function! Test_Multiple_Threads_Step() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -287,7 +287,7 @@ function! Test_Multiple_Threads_Step() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -304,7 +304,7 @@ function! Test_Multiple_Threads_Step() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -319,7 +319,7 @@ function! Test_Multiple_Threads_Step() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -338,7 +338,7 @@ function! Test_Multiple_Threads_Step() " So we break out of the loop call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, notify_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -352,6 +352,209 @@ function! Test_Multiple_Threads_Step() \ ) \ } ) + call vimspector#ClearBreakpoints() + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! Test_UpDownStack() + let fn='../support/test/python/simple_python/main.py' + exe 'edit ' . fn + call setpos( '.', [ 0, 6, 1 ] ) + + call vimspector#SetLineBreakpoint( fn, 15 ) + call vimspector#LaunchWithSettings( { 'configuration': 'run' } ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) + call WaitForAssert( {-> + \ AssertMatchList( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 2, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + + call vimspector#DownFrame() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) + call WaitForAssert( {-> + \ AssertMatchList( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 2, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + + + call vimspector#UpFrame() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) + call WaitForAssert( {-> + \ AssertMatchList( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 3, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + + + call feedkeys( "\VimspectorUpFrame", 'x' ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 23, 1 ) + call WaitForAssert( {-> + \ AssertMatchList( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 4, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + + + call feedkeys( "\VimspectorDownFrame", 'x' ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) + call WaitForAssert( {-> + \ AssertMatchList( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 3, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + + + call vimspector#DownFrame() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) + call WaitForAssert( {-> + \ AssertMatchList( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 2, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + + + call vimspector#ClearBreakpoints() call vimspector#test#setup#Reset() %bwipe! diff --git a/tests/testdata/cpp/simple/.vimspector.json b/tests/testdata/cpp/simple/.vimspector.json index 0dca061..48ce801 100644 --- a/tests/testdata/cpp/simple/.vimspector.json +++ b/tests/testdata/cpp/simple/.vimspector.json @@ -12,7 +12,7 @@ "externalConsole": false, "stopAtEntry": true, "stopOnEntry": true, - "MImode": "${VIMSPECTOR_MIMODE}" + "MIMode": "${VIMSPECTOR_MIMODE}" }, "breakpoints": { "exception": { @@ -33,7 +33,7 @@ "externalConsole": false, "stopAtEntry": false, "stopOnEntry": false, - "MImode": "${VIMSPECTOR_MIMODE}" + "MIMode": "${VIMSPECTOR_MIMODE}" }, "breakpoints": { "exception": { @@ -55,7 +55,7 @@ "externalConsole": false, "stopAtEntry": false, "stopOnEntry": false, - "MImode": "${VIMSPECTOR_MIMODE}" + "MIMode": "${VIMSPECTOR_MIMODE}" }, "breakpoints": { "exception": { @@ -82,7 +82,7 @@ "configuration": { "request": "launch", "program": "${workspaceRoot}/${fileBasenameNoExtension}", - "MImode": "${VIMSPECTOR_MIMODE}", + "MIMode": "${VIMSPECTOR_MIMODE}", "externalConsole": false, "args": [ "CALCULATED_LIST", "${CALCULATED_LIST}", diff --git a/tests/ui.test.vim b/tests/ui.test.vim index f251539..5ba2f9c 100644 --- a/tests/ui.test.vim +++ b/tests/ui.test.vim @@ -1,6 +1,7 @@ let s:fn='../support/test/python/simple_python/main.py' function! SetUp() + let g:vimspector_ui_mode = get( s:, 'vimspector_ui_mode', 'horizontal' ) call vimspector#test#setup#SetUpWithMappings( 'HUMAN' ) endfunction @@ -16,12 +17,17 @@ function! s:StartDebugging() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 23, 1 ) endfunction +function! SetUp_Test_StandardLayout() + call vimspector#test#setup#PushOption( 'columns', 200 ) +endfunction + function! Test_StandardLayout() call s:StartDebugging() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + call assert_equal( 'horizontal', g:vimspector_session_windows.mode ) call assert_equal( \ [ 'row', [ \ [ 'col', [ @@ -43,6 +49,247 @@ function! Test_StandardLayout() %bwipe! endfunction +function! TearDown_Test_StandardLayout() + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_NarrowLayout() + call vimspector#test#setup#PushOption( 'columns', 100 ) + let s:vimspector_ui_mode = 'vertical' +endfunction + +function! Test_NarrowLayout() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'vertical', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'col', [ + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_NarrowLayout() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_AutoLayoutTerminalVert() + let s:vimspector_ui_mode = 'auto' + call vimspector#test#setup#PushOption( 'columns', 250 ) + call vimspector#test#setup#PushOption( 'lines', 30 ) +endfunction + +function! Test_AutoLayoutTerminalVert() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'horizontal', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'row', [ + \ [ 'col', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'col', [ + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ ] ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ] + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_AutoLayoutTerminalVert() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'lines' ) + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_AutoLayoutTerminalHorizVert() + let s:vimspector_ui_mode = 'auto' + " Wide enough to be horizontal layout, but not wide enough to fully fit the + " terminal, with enough rows to fit the max terminal below + call vimspector#test#setup#PushOption( 'columns', + \ 50 + 82 + 3 + 2 + 12 ) + call vimspector#test#setup#PushOption( 'lines', 50 ) +endfunction + +function! Test_AutoLayoutTerminalHorizVert() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'horizontal', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'row', [ + \ [ 'col', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'col', [ + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ] + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_AutoLayoutTerminalHorizVert() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'lines' ) + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_AutoLayoutTerminalHorizVertButNotEnoughLines() + let s:vimspector_ui_mode = 'auto' + " Wide enough to be horizontal layout, but not wide enough to fully fit the + " terminal, with enough rows to fit the max terminal below, but there are not + " enough lines to do this + call vimspector#test#setup#PushOption( 'columns', + \ 50 + 82 + 3 + 2 + 12 ) + call vimspector#test#setup#PushOption( 'lines', 20 ) +endfunction + +function! Test_AutoLayoutTerminalHorizVertButNotEnoughLines() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'horizontal', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'row', [ + \ [ 'col', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'col', [ + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ ] ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ], + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_AutoLayoutTerminalHorizVertButNotEnoughLines() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'lines' ) + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_AutoLayoutTerminalHoriz() + let s:vimspector_ui_mode = 'vertical' + " Vertical layout, but we split the terminal horizonally + call vimspector#test#setup#PushOption( 'columns', 200 ) + call vimspector#test#setup#PushOption( 'lines', 50 ) +endfunction + +function! Test_AutoLayoutTerminalHoriz() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'vertical', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'col', [ + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ ] ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_AutoLayoutTerminalHoriz() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'lines' ) + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_AutoLayoutTerminalVertVert() + let s:vimspector_ui_mode = 'auto' + " Not wide enough to go horizontal, but wide enough to put the terminal and + " code vertically split + call vimspector#test#setup#PushOption( 'columns', 80 ) + call vimspector#test#setup#PushOption( 'lines', 50 ) +endfunction + +function! Test_AutoLayoutTerminalVertVert() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'vertical', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'col', [ + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_AutoLayoutTerminalVertVert() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'lines' ) + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + + function! Test_CloseVariables() call s:StartDebugging() diff --git a/tests/variables.test.vim b/tests/variables.test.vim index c7d373b..c00fb7f 100644 --- a/tests/variables.test.vim +++ b/tests/variables.test.vim @@ -194,6 +194,7 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' *+ t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -211,7 +212,7 @@ function! Test_ExpandVariables() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -219,6 +220,7 @@ function! Test_ExpandVariables() \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -229,7 +231,7 @@ function! Test_ExpandVariables() " Step - stays expanded call vimspector#StepOver() call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' - t (Test): {...}', @@ -237,6 +239,7 @@ function! Test_ExpandVariables() \ ' - c (char): 0 ''\\0\{1,3}''', \ ' - fffff (float): 0', \ ' + another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -253,6 +256,7 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' + t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -267,6 +271,7 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' + t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -278,7 +283,7 @@ function! Test_ExpandVariables() call setpos( '.', [ 0, 2, 1 ] ) call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' - t (Test): {...}', @@ -286,6 +291,7 @@ function! Test_ExpandVariables() \ ' \*- c (char): 99 ''c''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -302,6 +308,7 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -316,6 +323,7 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -331,6 +339,7 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -378,7 +387,7 @@ function! Test_ExpandWatch() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -397,7 +406,7 @@ function! Test_ExpandWatch() " Step - stays expanded call vimspector#StepOver() call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -449,7 +458,7 @@ function! Test_ExpandWatch() call setpos( '.', [ 0, 3, 1 ] ) call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -607,7 +616,7 @@ function! Test_EvaluateFailure() " Add a wtch call vimspector#AddWatch( 'test' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: test', @@ -658,7 +667,7 @@ function! Test_VariableEval() \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -690,7 +699,7 @@ function! Test_VariableEval() \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -724,7 +733,7 @@ function! Test_VariableEval() \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Evaluation error', \ ], @@ -768,7 +777,7 @@ function! Test_VariableEvalExpand() \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -786,7 +795,7 @@ function! Test_VariableEvalExpand() call feedkeys( "jjjj\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -806,7 +815,7 @@ function! Test_VariableEvalExpand() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -846,6 +855,7 @@ function! Test_SetVariableValue_Local() \ [ \ '- Scope: Locals', \ ' *+ t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -863,7 +873,7 @@ function! Test_SetVariableValue_Local() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -871,6 +881,7 @@ function! Test_SetVariableValue_Local() \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -889,7 +900,7 @@ with mock.patch( 'vimspector.utils.InputSave' ): EOF call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -897,6 +908,7 @@ EOF \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -908,7 +920,7 @@ EOF call vimspector#SetVariableValue( '1234' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -916,6 +928,7 @@ EOF \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -927,7 +940,7 @@ EOF call vimspector#SetVariableValue( 'this is invalid' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -935,6 +948,7 @@ EOF \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -983,7 +997,7 @@ function! Test_SetVariableValue_Watch() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -1012,7 +1026,7 @@ EOF call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -1032,7 +1046,7 @@ EOF call vimspector#SetVariableValue( '1234' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -1075,7 +1089,7 @@ function! Test_SetVariableValue_Balloon() \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -1102,7 +1116,7 @@ with mock.patch( 'vimspector.utils.InputSave' ): EOF call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0',