diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 828ec18..1788c04 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 --clean -Nu /path/to/vimspector/support/minimal_vimrc` ? \[Yes/No] +* Does your issue reproduce using `vim -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 ---clean Nu /path/to/vimspector/support/minimal_vimrc` +> 1. Run `vim -Nu /path/to/vimspector/support/minimal_vimrc` > 2. Open _this project_... > 3. Press _this sequence of keys_ @@ -57,12 +57,6 @@ 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/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index f182c32..0000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,12 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: Questions and support - url: http://gitter.im/vimspector/Lobby - about: Please ask and answer questions here. - - name: Discussions - url: https://github.com/puremourning/vimspector/discussions - about: Please post questions and useful hints here - - name: Support for additional languages - url: https://github.com/puremourning/vimspector/wiki/languages - about: Please see here for information on support for additional languages - diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f186f5d..17f9601 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -13,7 +13,7 @@ defaults: jobs: PythonLint: - runs-on: ubuntu-18.04 + runs-on: ubuntu-16.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-18.04' + runs-on: 'ubuntu-16.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-18.04' + runs-on: 'ubuntu-16.04' container: image: 'puremourning/vimspector:test' options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined @@ -111,16 +111,6 @@ 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' @@ -153,10 +143,10 @@ jobs: # if: failure() # with: # NGROK_AUTH_TOKEN: ${{ secrets.NGROK_AUTH_TOKEN }} - # SSH_PASS: ${{ secrets.SSH_PASS }} # [V]imspector + # SSH_PASS: ${{ secrets.SSH_PASS }} PublishRelease: - runs-on: 'ubuntu-18.04' + runs-on: 'ubuntu-16.04' needs: - Linux - MacOS diff --git a/.github/workflows/lock_old_issues.yaml b/.github/workflows/lock_old_issues.yaml deleted file mode 100644 index 25d65e0..0000000 --- a/.github/workflows/lock_old_issues.yaml +++ /dev/null @@ -1,27 +0,0 @@ -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 05dc8cd..77f22a9 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,3 @@ support/test/csharp/*.exe* configurations/ venv/ test-base/ -tags diff --git a/.mergify.yml b/.mergify.yml index 0f02002..09d3d83 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -9,8 +9,9 @@ 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 6f42505..f2e32ae 100644 --- a/.ycm_extra_conf.py +++ b/.ycm_extra_conf.py @@ -42,17 +42,7 @@ 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 adec034..cfa6c9d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,23 +46,6 @@ 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: @@ -70,7 +53,6 @@ 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 @@ -101,47 +83,11 @@ in the issue report. The minimal vimrc is in `support/test/minimal_vimrc` and can be used as follows: ``` -vim --clean -Nu /path/to/vimspector/support/minimal_vimrc +vim -Nu /path/to/vimspector/support/minimal_vimrc ``` ## Pull Requests -Vimspector is open to all contributors with ideas great and small! However, -there is a limit to the intended scope of the plugin and the amount of time the -maintainer has to support and... well... maintain features. It's probably well -understood that the contributor's input typically ends when a PR is megred, but -the maintainers have to keep it working forever. - -### Small changes - -For bug fixes, documentation changes, gadget versin updates, etc. please just -send a PR, I'm super happy to merge these! - -If you are unsure, or looking for some pointers, feel free to ask in Gitter, or -mention is in the PR. - -### Larger changes - -For larger features that might be in any way controvertial, or increase the -complexity of the overall plugin, please come to Gitter and talk to the -maintainer(s) first. This saves a lot of potential back-and-forth and makes sure -that we're "on the same page" about the idea and the ongoing maintenance. - -In addition, if you like hacking, feel free to raise a PR tagged with `[RFC]` in -the title and we can discuss the idea. I still prefer to discuss these things on -Gitter rather than back-and-forth on GitHub, though. - -Please don't be offended if the maintainer(s) request significant rework for (or -perhaps even dismiss) a PR that's not gone through this process. - -Please also don't be offended if the maintainer(s) ask if you're willing to -provide ongoing support for the feature. As an OSS project manned entirely in -what little spare time the maintainer(s) have, we're always looking for -contributions and contributors who will help with support and maintenance of -larger new features. - -### PR Guidelines - When contributing pull requests, I ask that: * You provide a clear and complete summary of the change, the use case and how @@ -149,8 +95,6 @@ When contributing pull requests, I ask that: * You avoid using APIs that are not available in the versions listed in the dependencies on README.md * You add tests for your PR. -* You test your changes in both Vim and Neovim at the supported versions (and - state that in the PR). * You follow the style of the code as-is; the python code is YCM-stye, it is *not* PEP8, nor should it be. @@ -185,10 +129,10 @@ Vimspector creator. ### Code Style The code style of the Python code is "YCM" style, because that's how I like it. -`flake8` is used to check for certain errors and code style. +[`flake8`][] is used to check for certain errors and code style. The code style of the Vimscript is largely the same, and it is linted by -`vint`. +[`vint`][]. To run them: @@ -200,31 +144,7 @@ To run them: They're also run by CI, so please check for lint failures. The canonical definition of the command to run is the command run in CI, i.e. in -`.git/workflows/build.yml`. - -### Debugging Vimspector - -You can debug vimspector's python code using vimspector! We can use debugpy, -from within Vim's embedded python and connect to it. Here's how: - -1. In one instance of vim, run the following to get debugpy to start listening - for us to connect: `:py3 __import__( 'vimspector', fromlist=[ 'developer' ] - ).developer.SetUpDebugpy()` - -2. In another instance of Vim, set a breakpoint in the vimspector python code - you want to debug and launch vimspector (e.g. ``). Select the `Python: - attach to vim` profile. This will attach to the debugpy running in the other - vim. - -3. Back in the first vim (the debuggee), trigger the vimspector code in - question, e.g. by starting to debug something else. - -4. You'll see it pause, and the 2nd vim (the debugger), you should be able to - step through and inspect as with any other python remote debugging. - -NB. It's also possible to debug the vimscript code using vimspector, but this -requires unreleased vim patches and a fair amount of faff. You can always use -`:debug` (see the help) for this though. +`azure-pipelines.yml`. # Code of conduct diff --git a/README.md b/README.md index d198292..d964445 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,7 @@ # vimspector - A multi language graphical debugger for Vim For a tutorial and usage overview, take a look at the -[Vimspector website][website]. - -For detailed explanation of the `.vimspector.json` format, see the -[reference guide][vimspector-ref]. +[Vimspector website][website] ![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) @@ -30,27 +27,20 @@ For detailed explanation of the `.vimspector.json` format, see the * [Background](#background) * [Status](#status) * [Experimental](#experimental) - * [Motivation](#motivation) - * [License](#license) - * [Sponsorship](#sponsorship) * [Mappings](#mappings) * [Visual Studio / VSCode](#visual-studio--vscode) * [Human Mode](#human-mode) - * [Usage and API](#usage-and-api) + * [Usage](#usage) * [Launch and attach by PID:](#launch-and-attach-by-pid) * [Launch with options](#launch-with-options) * [Debug configuration selection](#debug-configuration-selection) * [Get configurations](#get-configurations) * [Breakpoints](#breakpoints) - * [Summary](#summary) - * [Line breakpoints](#line-breakpoints) - * [Conditional breakpoints](#conditional-breakpoints) * [Exception breakpoints](#exception-breakpoints) * [Clear breakpoints](#clear-breakpoints) * [Run to Cursor](#run-to-cursor) * [Stepping](#stepping) * [Variables and scopes](#variables-and-scopes) - * [Variable or selection hover evaluation](#variable-or-selection-hover-evaluation) * [Watches](#watches) * [Watch autocompletion](#watch-autocompletion) * [Stack Traces](#stack-traces) @@ -59,16 +49,15 @@ For detailed explanation 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) - * [Data visualization / pretty printing](#data-visualization--pretty-printing) - * [C++ Remote debugging](#c-remote-debugging) - * [C++ Remote launch and attach](#c-remote-launch-and-attach) + * [Debug adapter configuration](#debug-adapter-configuration) + * [C, C , Rust, etc.](#c-c-rust-etc) * [Rust](#rust) + * [Remote debugging](#remote-debugging) + * [Remote launch and attach](#remote-launch-and-attach) * [Python](#python) - * [Python Remote Debugging](#python-remote-debugging) - * [Python Remote launch and attach](#python-remote-launch-and-attach) + * [Remote Debugging](#remote-debugging-1) + * [Remote launch and attach](#remote-launch-and-attach-1) + * [Legacy: vscode-python](#legacy-vscode-python) * [TCL](#tcl) * [C♯](#c) * [Go](#go) @@ -77,7 +66,6 @@ For detailed explanation 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) @@ -87,26 +75,28 @@ For detailed explanation of the `.vimspector.json` format, see the * [Sign priority](#sign-priority) * [Changing the default window sizes](#changing-the-default-window-sizes) * [Changing the terminal size](#changing-the-terminal-size) - * [Custom mappings while debugging](#custom-mappings-while-debugging) * [Advanced UI customisation](#advanced-ui-customisation) * [Customising the WinBar](#customising-the-winbar) * [Example](#example) * [FAQ](#faq) + * [Motivation](#motivation) + * [License](#license) + * [Sponsorship](#sponsorship) - + # 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 instructions for configuration and setup. -But for now, here's a (rather old) screenshot of Vimspector debugging Vim: +But for now, here's a (rather old) screenshot of Vimsepctor debugging Vim: ![vimspector-vim-screenshot](https://puremourning.github.io/vimspector-web/img/vimspector-overview.png) @@ -127,12 +117,10 @@ And a couple of brief demos: - 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`) +- variable value display hover - interactive debug console with autocompletion -- launch debuggee within Vim's embedded terminal +- launch debugee within Vim's embedded terminal - logging/stdout display - simple stable API for custom tooling (e.g. integrate with language server) @@ -145,24 +133,22 @@ 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 | 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 | +| Language | Status | Switch (for `install_gadget.py`) | Adapter (for `:VimspectorInstall`) | Dependencies | +|--------------------|--------------|----------------------------------|------------------------------------|--------------------------------------------| +| C, C++, etc. | Tested | `--all` or `--enable-c` | 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 | +| Python.legacy | Legacy | `--force-enable-python.legacy` | vscode-python | Node 10, Python 2.7 or Python 3 | ## Other languages @@ -237,8 +223,8 @@ Why such a new vim ? Well 2 reasons: 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 +there are no regression tests for vimspector in neovim, so it's likely to break +frequently. 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. @@ -256,8 +242,7 @@ neovim doesn't implement some features Vimspector relies on: 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. +* Balloons - used to display the values of variables when debugging. Workarounds are in place as follows: @@ -266,18 +251,9 @@ Workarounds are in place as follows: [`:VimspectorReset`](#closing-debugger) * Prompt Buffers - There are [`:VimspectorEval`](#console) and [`:VimspectorWatch`](#watches) -* 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: -```viml -" 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 -``` +There is no workaroud for the lack of balloons; you'll just have to use +`:VimspectorEval` or `:VimspectorWatch`, or switch to Vim. ## Windows differences @@ -291,7 +267,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` and `support/test/go/name-starts-with-vowel`) +* Go (`support/test/go/hello_world`) * Nodejs (`support/test/node/simple`) * Chrome (`support/test/chrome/`) * etc. @@ -351,13 +327,13 @@ See support/doc/example_vimrc.vim for a minimal example. 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. +debugers. 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 +* If you downloaded a tarball, gadgets for main supported langauges are already installed for you. * Using `:VimspectorInstall ` (use TAB `wildmenu` to see the options, also accepts any `install_gadget.py` option) @@ -367,7 +343,7 @@ There are a few ways to do this: * Using `:VimspectorUpdate` to install the latest supported versions of the gadgets. -Here's a demo of doing some installs and an upgrade: +Here's a demo of doing somee installs and an upgrade: [![asciicast](https://asciinema.org/a/Hfu4ZvuyTZun8THNen9FQbTay.svg)](https://asciinema.org/a/Hfu4ZvuyTZun8THNen9FQbTay) @@ -381,7 +357,7 @@ they will: 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 + * Ensuring scripts are executable, because the VSIX pacakges are usually broken in this regard. * Set up the `gadgetDir` symlinks for the platform. @@ -469,7 +445,7 @@ 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 +The simplest way in practice is to install or start Visusal Studio Code and use its extension manager to install the relevant extension. You can then configure the adapter manually in the `adapters` section of your `.vimspector.json` or in a `gadgets.json`. @@ -527,6 +503,13 @@ Example: "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7" ], "name": "cppdbg" + }, + "vscode-python": { + "command": [ + "node", + "${gadgetDir}/vscode-python/out/client/debugger/debugAdapter/main.js" + ], + "name": "vscode-python" } } } @@ -543,7 +526,7 @@ format as `.gadgets.json` but are not overwritten when running ## Upgrade After updating the Vimspector code (either via `git pull` or whatever package -manager), run `:VimspectorUpdate` to update any already-installed gadgets. +manager), run `:VimspectorUpdate` to update any already-installed gadets. # About @@ -580,71 +563,12 @@ 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 +- keys, layout, functionatlity 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. -## 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. - -## License - -[Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) - -Copyright © 2018 Ben Jackson - -## 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](https://greyhoundrescuewales.co.uk) -* [Cancer Research UK](https://www.cancerresearchuk.org) -* [ICCF Holland](https://iccf.nl) -* Any charity of your choosing. - # Mappings By default, vimspector does not change any of your mappings. Mappings are very @@ -652,23 +576,17 @@ 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* | - +* `VimspectorContinue` +* `VimspectorStop` +* `VimspectorRestart` +* `VimspectorPause` +* `VimspectorToggleBreakpoint` +* `VimspectorToggleConditionalBreakpoint` +* `VimspectorAddFunctionBreakpoint` +* `VimspectorStepOver` +* `VimspectorStepInto` +* `VimspectorStepOut` +* `VimspectorRunToCursor` These map roughly 1-1 with the API functions below. @@ -679,14 +597,13 @@ 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](#custom-mappings-while-debugging). - That said, many people are familiar with particular debuggers, so the following mappings can be enabled by setting `g:vimspector_enable_mappings` to the specified value. +Please note: Currently there are no `` mappings. These will be added in +future to make custom mappings much easier. + ## Visual Studio / VSCode To use Visual Studio-like mappings, add the following to your `vimrc` **before @@ -696,17 +613,17 @@ 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 +| Key | Function | API | +| --- | --- | --- | +| `F5` | When debugging, continue. Otherwise start debugging. | `vimspector#Continue()` | +| `Shift F5` | Stop debugging. | `vimspector#Stop()` | +| `Ctrl Shift F5` | Restart debugging with the same configuration. | `vimspector#Restart()` | +| `F6` | Pause debugee. | `vimspector#Pause()` | +| `F9` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` | +| `Shift F9` | Add a function breakpoint for the expression under cursor | `vimspector#AddFunctionBreakpoint( '' )` | +| `F10` | Step Over | `vimspector#StepOver()` | +| `F11` | Step Into | `vimspector#StepInto()` | +| `Shift F11` | Step out of current function scope | `vimspector#StepOut()` | ## Human Mode @@ -721,45 +638,21 @@ 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 +| Key | Function | API | +| --- | --- | --- | +| `F5` | When debugging, continue. Otherwise start debugging. | `vimspector#Continue()` | +| `F3` | Stop debugging. | `vimspector#Stop()` | +| `F4` | Restart debugging with the same configuration. | `vimspector#Restart()` | +| `F6` | Pause debugee. | `vimspector#Pause()` | +| `F9` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` | +| `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()` | -In addition, I recommend adding a mapping to `VimspectorBalloonEval`, in -normal and visual modes, for example: - -```viml -" 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: - -```viml -nmap VimspectorUpFrame -nmap VimspectorDownFrame -``` - -# Usage and API - -This section defines detailed usage instructions, organised by feature. For most -users, the [mappings](#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. +# Usage ## Launch and attach by PID: @@ -780,7 +673,7 @@ 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 +This allows for some intergration and automation. For example, if you have a configuration named `Run Test` that contains a [replacement variable][vimspector-ref-var] named `${Test}` you could write a mapping which ultimately executes: @@ -823,60 +716,19 @@ For example, to get an array of configurations and fuzzy matching on the result ## Breakpoints -See the [mappings](€mappings) section for the default mappings for working with -breakpoints. This section describes the full API in vimscript functions. +* Use `vimspector#ToggleBreakpoint([ { 'condition': '' } ])` + to set/disable/delete a line breakpoint, with optional condition. +* Use `vimspector#AddFunctionBreakpoint( '' [, { 'condition': '' } ] )` + to add a function breakpoint with optional condition. -### Summary +Both of these functions take a single optional argument which is a dictionary of +options. The dictionary can have the following keys: -* 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 - -### 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. - -### 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 +* `condition`: An optional expression evaluated to deterimie 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 + times the breakpoint should be ignored. Should (probablty?) 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`. @@ -888,10 +740,9 @@ expressions in a command line (with history). ### 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. +When starting debugging, you may be asekd a few questions about how to handle +exceptoins. 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` @@ -902,14 +753,14 @@ You can configure your choices in the `.vimspector.json`. See ### Clear breakpoints -Use `vimspector#ClearBreakpoints()` -to clear all breakpoints including the memory of exception breakpoint choices. +* Use `vimspector#ClearBreakpoints()` + to clear all breakpoints including the memory of exception breakpoint choices. ### 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. +* Use `vimspector#RunToCursor` or ``: this creates a temporary + breakpoint on the current line, then continues execution, clearing the + breakpiont when it is hit. ## Stepping @@ -922,8 +773,6 @@ breakpoint when it is hit. * 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 @@ -931,22 +780,6 @@ breakpoint when it is hit. Scopes and variables are represented by the buffer `vimspector.Variables`. -## 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. - -![variable eval hover](https://puremourning.github.io/vimspector-web/img/vimspector-variable-eval-hover.png) - ## Watches The watch window is used to inspect variables and expressions. Expressions are @@ -960,8 +793,6 @@ to add a new watch expression. * 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 ``. ![watch window](https://puremourning.github.io/vimspector-web/img/vimspector-watch-window.png) @@ -971,7 +802,7 @@ The watches are represented by the buffer `vimspector.StackTrace`. ### 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 +calcualte completion for the current expression. This is trivailly used with `` (see `:help ins-completion`), or integrated with your favourite completion system. The filetype in the buffer is set to `VimspectorPrompt`. @@ -986,8 +817,8 @@ let g:ycm_semantic_triggers = { ## 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. +The stack trace window shows the state of each progream thread. Threads which +are stopped can be expanded to show the strack 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 @@ -1008,8 +839,6 @@ 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) @@ -1017,10 +846,10 @@ The stack trace is represented by the buffer `vimspector.StackTrace`. ## Program Output -* In the outputs window, use the WinBar to select the output channel. +* 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. +* The debugee prints to the stdout channel. * Other channels may be useful for debugging. ![output window](https://puremourning.github.io/vimspector-web/img/vimspector-output-window.png) @@ -1032,7 +861,7 @@ options). ### 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 +as an interactive CLI for the debug adapter. Support for this varies amongt adapters. * Enter insert mode to enter a command to evaluate. @@ -1049,7 +878,7 @@ If the output window is closed, a new one can be opened with ### 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 +calcualte completion for the current command/expression. This is trivailly used with `` (see `:help ins-completion`), or integrated with your favourite completion system. The filetype in the buffer is set to `VimspectorPrompt`. @@ -1071,36 +900,15 @@ 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: -* `Reset` WinBar button +* `Reset` WinBar button (`set mouse=a`) * `:VimspectorReset` when the WinBar is not available. * `call vimspector#Reset()` - -## 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 } )`. - - -# Debug profile configuration +# Debug adapter configuration For an introduction to the configuration of `.vimspector.json`, take a look at the Getting Started section of the [Vimspector website][website]. @@ -1177,49 +985,6 @@ 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 -`miDebuggerAddress`. Note that when doing this you should use the -`"request": "attach"`. - -### C++ Remote launch and attach - -If you're feeling fancy, checkout the [reference guide][remote-debugging] 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. @@ -1286,6 +1051,17 @@ Rust is supported with any gdb/lldb-based debugger. So it works fine with +### 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"`. + +### Remote launch and attach + +If you're feeling fancy, checkout the [reference guide][remote-debugging] for +an example of getting Vimspector to remotely launch and attach. + ## Python * Python: [debugpy][] @@ -1294,6 +1070,10 @@ 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": { @@ -1316,7 +1096,7 @@ Rust is supported with any gdb/lldb-based debugger. So it works fine with } ``` -### Python Remote Debugging +### 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 @@ -1355,11 +1135,39 @@ Additional documentation, including how to do this when the remote machine can only be contacted via SSH [are provided by debugpy](https://github.com/microsoft/debugpy/wiki/Debugging-over-SSH). -### Python Remote launch and attach +### Remote launch and attach 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) @@ -1383,8 +1191,35 @@ 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}", - "env": {} + "runtimeExecutable": "mono", + "runtimeArgs": [], + "env": [], + "externalConsole": false, + "console": "integratedTerminal" } } } @@ -1401,8 +1236,6 @@ 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": { @@ -1420,7 +1253,7 @@ NOTE: Vimspector uses the ["legacy" vscode-go debug adapter](https://github.com/ ``` See the vscode-go docs for -[troubleshooting information](https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md#troubleshooting) +[troubleshooting information](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#troubleshooting) ## PHP @@ -1451,7 +1284,7 @@ xdebug.remote_connect_back=true xdebug.remote_port=9000 ``` -* .vimspector.json +* .vimspectory.json ```json { "configurations": { @@ -1503,7 +1336,7 @@ php Requires: * `install_gadget.py --force-enable-node` -* For installation, a Node.js environment that is < node 12. I believe this is an +* For installation, a Node.js environemt that is < node 12. I believe this is an incompatibility with gulp. Advice, use [nvm][] with `nvm install --lts 10; nvm use --lts 10; ./install_gadget.py --force-enable-node ...` * Options described here: @@ -1566,20 +1399,6 @@ 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]. @@ -1730,7 +1549,7 @@ This debugger uses stdio to communicate with the running process, so calls to # Customisation -There is very limited support for customisation of the UI. +There is very limited support for customistaion of the UI. ## Changing the default signs @@ -1739,40 +1558,34 @@ 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 | -| `vimspectorCurrentThread` | Focussed thread in stack trace view | 200 | -| `vimspectorCurrentFrame` | Current stack frame in stack trace view | 200 | +| Sign | Description | Priority | +|------------------------|-------------------------------------|----------| +| `vimspectorBP` | Line breakpoint | 9 | +| `vimspectorBPCond` | Conditional line breakpiont | 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: ```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 vimspectorCurrentThread text=▶ texthl=MatchParen linehl=CursorLine -sign define vimspectorCurrentFrame text=▶ texthl=Special 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 ``` 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 +glyphs. You can easily change them by deifining 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 vimspectorCurrentThread text=> texthl=MatchParen -sign define vimspectorCurrentFrame text=> texthl=Special +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 priority @@ -1809,8 +1622,8 @@ smaller ones. ## 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 +> ***Please Note***: This cusomiation API is ***unstable***, meaning that it may +change at any time. I will endeavour to reduce the impact of this and annouce changes in Gitter. The following options control the default sizes of the UI windows (all of them @@ -1831,7 +1644,7 @@ let g:vimspector_bottombar_height = 15 ## Changing the terminal size -The terminal is typically created as a vertical split to the right of the code +The terminal is typically created as a vertical split to the righ 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. @@ -1850,7 +1663,7 @@ 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. +to satisfy the other contraints. Example: @@ -1860,33 +1673,10 @@ let g:vimspector_terminal_maxwidth = 75 let g:vimspector_terminal_minwidth = 20 ``` -## 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. - ## 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 +> ***Please Note***: This cusomiation API is ***unstable***, meaning that it may +change at any time. I will endeavour to reduce the impact of this and annouce changes in Gitter. The above customisation of window sizes is limited intentionally to keep things @@ -1918,7 +1708,7 @@ keys: * `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. + containng 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. @@ -1932,19 +1722,19 @@ In addition, the following key is added when triggering the ## Customising the WinBar You can even customise the WinBar buttons by simply running the usual `menu` -(and `unmenu`) commands. +(and `unmanu`) commands. By default, Vimspector uses something a bit like this: ```viml -nnoremenu WinBar.■\ Stop :call vimspector#Stop( { 'interactive': v:false } ) +nnoremenu WinBar.■\ Stop :call vimspector#Stop() 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 } ) +nnoremenu WinBar.✕ :call vimspector#Reset() ``` If you prefer a different layout or if the unicode symbols don't render @@ -1957,7 +1747,7 @@ func! CustomiseUI() " Clear the existing WinBar created by Vimspector nunmenu WinBar " Cretae our own WinBar - nnoremenu WinBar.Kill :call vimspector#Stop( { 'interactive': v:true } ) + nnoremenu WinBar.Kill :call vimspector#Stop() nnoremenu WinBar.Continue :call vimspector#Continue() nnoremenu WinBar.Pause :call vimspector#Pause() nnoremenu WinBar.Step\ Over :call vimspector#StepOver() @@ -1977,7 +1767,7 @@ augroup END 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. +commands, primarily `win_gotoid` funciton and the `wincmd` ex command. To try this out `vim -Nu support/custom_ui_vimrc `. @@ -2037,23 +1827,73 @@ hi link jsonComment Comment ``` 7. What is the difference between a `gadget` and an `adapter`? A gadget is - something you install with `:VimspectorInstall` or `install_gadget.py`, an + somethin 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. -8. The signs and winbar display funny symbols. How do I fix them? See +8. The signs and winbar display funny symbols. How do i fix them? See [this](#changing-the-default-signs) and [this](#customising-the-winbar) -9. 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. -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). +# 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. + +# License + +[Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) + +Copyright © 2018 Ben Jackson + +# 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 prefernce): + +* [Greyhound Rescue Wales](https://greyhoundrescuewales.co.uk) +* [Cancer Research UK](https://www.cancerresearchuk.org) +* [ICCF Holland](https://iccf.nl) +* Any charity of your choosing. [ycmd]: https://github.com/Valloric/ycmd [gitter]: https://gitter.im/vimspector/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link @@ -2068,4 +1908,3 @@ hi link jsonComment Comment [debugpy]: https://github.com/microsoft/debugpy [YouCompleteMe]: https://github.com/ycm-core/YouCompleteMe#java-semantic-completion [remote-debugging]: https://puremourning.github.io/vimspector/configuration.html#remote-debugging-support -[YcmJava]: https://github.com/ycm-core/YouCompleteMe#java-semantic-completion diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 78c7c1b..35ecd03 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -13,9 +13,6 @@ " 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 @@ -44,11 +41,11 @@ function! s:Enabled() abort return s:enabled endfunction -function! vimspector#Launch( ... ) abort +function! vimspector#Launch() abort if !s:Enabled() return endif - py3 _vimspector_session.Start( *vim.eval( 'a:000' ) ) + py3 _vimspector_session.Start() endfunction function! vimspector#LaunchWithSettings( settings ) abort @@ -58,16 +55,11 @@ function! vimspector#LaunchWithSettings( settings ) abort py3 _vimspector_session.Start( launch_variables = vim.eval( 'a:settings' ) ) endfunction -function! vimspector#Reset( ... ) abort +function! vimspector#Reset() abort if !s:Enabled() return endif - if a:0 == 0 - let options = {} - else - let options = a:1 - endif - py3 _vimspector_session.Reset( **vim.eval( 'options' ) ) + py3 _vimspector_session.Reset() endfunction function! vimspector#Restart() abort @@ -193,16 +185,11 @@ function! vimspector#SetCurrentThread() abort py3 _vimspector_session.SetCurrentThread() endfunction -function! vimspector#Stop( ... ) abort +function! vimspector#Stop() abort if !s:Enabled() return endif - if a:0 == 0 - let options = {} - else - let options = a:1 - endif - py3 _vimspector_session.Stop( **vim.eval( 'options' ) ) + py3 _vimspector_session.Stop() endfunction function! vimspector#ExpandVariable() abort @@ -212,17 +199,6 @@ function! vimspector#ExpandVariable() abort py3 _vimspector_session.ExpandVariable() endfunction -function! vimspector#SetVariableValue( ... ) abort - if !s:Enabled() - return - endif - if a:0 == 0 - py3 _vimspector_session.SetVariableValue() - else - py3 _vimspector_session.SetVariableValue( new_value = vim.eval( 'a:1' ) ) - endif -endfunction - function! vimspector#DeleteWatch() abort if !s:Enabled() return @@ -237,28 +213,12 @@ 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 endif if a:0 == 0 - let expr = input( 'Enter watch expression: ', - \ '', - \ 'custom,vimspector#CompleteExpr' ) + let expr = input( 'Enter watch expression: ' ) else let expr = a:1 endif @@ -350,6 +310,28 @@ function! vimspector#CompleteOutput( ArgLead, CmdLine, CursorPos ) abort return join( buffers, "\n" ) endfunction +py3 <' ) - endif - - return py3eval( '_vimspector_session.ShowEvalBalloon(' - \ . ' int( vim.eval( "winnr()" ) ), "' - \ . expr - \ . '", 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 b607e51..360ed08 100644 --- a/autoload/vimspector/internal/balloon.vim +++ b/autoload/vimspector/internal/balloon.vim @@ -19,323 +19,16 @@ let s:save_cpo = &cpoptions set cpoptions&vim " }}} -scriptencoding utf-8 - -let s:popup_win_id = 0 -let s:nvim_border_win_id = 0 -" -" tooltip dimensions -let s:min_width = 1 -let s:min_height = 1 -let s:max_width = 80 -let s:max_height = 20 - -let s:is_neovim = has( 'nvim' ) - - -" This is used as the balloonexpr in vim to show the Tooltip at the hover -" position -function! vimspector#internal#balloon#HoverTooltip() abort - return py3eval( '_vimspector_session.ShowEvalBalloon(' - \ . ' int( vim.eval( "v:beval_winnr" ) ) + 1,' - \ . ' vim.eval( "v:beval_text"),' - \ . ' 1 )' ) +" Returns: py.ShowBalloon( winnr, expresssion ) +function! vimspector#internal#balloon#BalloonExpr() abort + " winnr + 1 because for *no good reason* winnr is 0 based here unlike + " everywhere else + " int() because for *no good reason* winnr is a string. + return py3eval('_vimspector_session.ShowBalloon(' + \ . 'int( vim.eval( "v:beval_winnr" ) ) + 1,' + \ . 'vim.eval( "v:beval_text" ) )' ) endfunction -function! vimspector#internal#balloon#CreateTooltip( is_hover, ... ) abort - let body = [] - if a:0 > 0 - let body = a:1 - endif - - if s:popup_win_id != 0 - call vimspector#internal#balloon#Close() - endif - - if s:is_neovim - call s:CreateNeovimTooltip( body ) - else - let config = { - \ 'wrap': 0, - \ 'filtermode': 'n', - \ 'maxwidth': s:max_width, - \ 'maxheight': s:max_height, - \ 'minwidth': s:min_width, - \ 'minheight': s:min_height, - \ 'scrollbar': 1, - \ 'border': [], - \ 'padding': [ 0, 1, 0, 1], - \ 'drag': 1, - \ 'resize': 1, - \ 'close': 'button', - \ 'callback': 'vimspector#internal#balloon#CloseCallback', - \ } - - let config = vimspector#internal#popup#SetBorderChars( config ) - - if a:is_hover - let config[ 'filter' ] = 'vimspector#internal#balloon#MouseFilter' - let config[ 'mousemoved' ] = [ 0, 0, 0 ] - let s:popup_win_id = popup_beval( body, config ) - else - 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 - - endif - - return s:popup_win_id -endfunction - -" Filters for vim {{{ -function! vimspector#internal#balloon#MouseFilter( winid, key ) abort - if a:key ==# "\" - call vimspector#internal#balloon#Close() - return 0 - endif - - if index( [ "\", "\<2-leftmouse>" ], a:key ) < 0 - return 0 - endif - - let handled = 0 - let mouse_coords = getmousepos() - - " close the popup if mouse is clicked outside the window - if mouse_coords[ 'winid' ] != a:winid - call vimspector#internal#balloon#Close() - return 0 - endif - - " place the cursor according to the click - call win_execute( a:winid, - \ ':call cursor( ' - \ . mouse_coords[ 'line' ] - \ . ', ' - \ . mouse_coords[ 'column' ] - \ . ' )' ) - - " expand the variable if we got double click - if a:key ==? "\<2-leftmouse>" - call py3eval( '_vimspector_session.ExpandVariable(' - \ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],' - \ . 'line_num = ' . line( '.', a:winid ) - \ . ')' ) - let handled = 1 - endif - - return handled -endfunction - -function! s:MatchKey( key, candidates ) abort - for candidate in a:candidates - " If the mapping string looks like a special character, then try and - " expand it. This is... a hack. The whole thing only works if the mapping - " is a single key (anyway), and so we assume any string starting with < is a - " special key (which will be the common case) and try and map it. If it - " fails... it fails. - if candidate[ 0 ] == '<' - try - execute 'let candidate = "\' . candidate . '"' - endtry - endif - - if candidate ==# a:key - return v:true - endif - endfor - - return v:false -endfunction - -function! vimspector#internal#balloon#CursorFilter( winid, key ) abort - let mappings = py3eval( - \ "__import__( 'vimspector'," - \." fromlist = [ 'settings' ] ).settings.Dict(" - \." 'mappings' )[ 'variables' ]" ) - - if index( [ "\", "\<2-LeftMouse>" ], a:key ) >= 0 - return vimspector#internal#balloon#MouseFilter( a:winid, a:key ) - endif - - if s:MatchKey( a:key, mappings.expand_collapse ) - call py3eval( '_vimspector_session.ExpandVariable(' - \ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],' - \ . 'line_num = ' . line( '.', a:winid ) - \ . ')' ) - return 1 - elseif s:MatchKey( a:key, mappings.set_value ) - call py3eval( '_vimspector_session.SetVariableValue(' - \ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],' - \ . 'line_num = ' . line( '.', a:winid ) - \ . ')' ) - return 1 - endif - - return popup_filter_menu( a:winid, a:key ) -endfunction - -" }}} - -" Closing {{{ - -function! vimspector#internal#balloon#CloseCallback( ... ) abort - let s:popup_win_id = 0 - let s:nvim_border_win_id = 0 - return py3eval( '_vimspector_session.CleanUpTooltip()' ) -endfunction - -function! vimspector#internal#balloon#Close() abort - if s:popup_win_id == 0 - return - endif - - if s:is_neovim - call nvim_win_close( s:popup_win_id, v:true ) - call nvim_win_close( s:nvim_border_win_id, v:true ) - - call vimspector#internal#balloon#CloseCallback() - else - call popup_close(s:popup_win_id) - endif -endfunction - -" }}} - -" Neovim pollyfill {{{ - -function! vimspector#internal#balloon#ResizeTooltip() abort - if !s:is_neovim - " Vim does this for us - return - endif - - if s:popup_win_id <= 0 || s:nvim_border_win_id <= 0 - " nothing to resize - return - endif - - noautocmd call win_gotoid( s:popup_win_id ) - let buf_lines = getline( 1, '$' ) - - let width = s:min_width - let height = min( [ max( [ s:min_height, len( buf_lines ) ] ), - \ s:max_height ] ) - - " calculate the longest line - for l in buf_lines - let width = max( [ width, len( l ) ] ) - endfor - - let width = min( [ width, s:max_width ] ) - - let opts = { - \ 'width': width, - \ 'height': height, - \ } - - " resize the content window - call nvim_win_set_config( s:popup_win_id, opts ) - - " resize the border window - let opts[ 'width' ] = width + 4 - let opts[ 'height' ] = height + 2 - - call nvim_win_set_config( s:nvim_border_win_id, opts ) - call nvim_buf_set_lines( nvim_win_get_buf( s:nvim_border_win_id ), - \ 0, - \ -1, - \ v:true, - \ s:GenerateBorder( width, height ) ) -endfunction - -" neovim doesn't have the border support, so we have to make our own. -" FIXME: This will likely break if the user has `ambiwidth=2` -function! s:GenerateBorder( width, height ) abort - - let top = '╭' . repeat('─',a:width + 2) . '╮' - let mid = '│' . repeat(' ',a:width + 2) . '│' - let bot = '╰' . repeat('─',a:width + 2) . '╯' - let lines = [ top ] + repeat( [ mid ], a:height ) + [ bot ] - - return lines -endfunction - -function! s:CreateNeovimTooltip( body ) abort - " generate border for the float window by creating a background buffer and - " overlaying the content buffer - " see https://github.com/neovim/neovim/issues/9718#issuecomment-546603628 - let buf_id = nvim_create_buf( v:false, v:true ) - call nvim_buf_set_lines( buf_id, - \ 0, - \ -1, - \ v:true, - \ s:GenerateBorder( s:max_width, s:max_height ) ) - - " default the dimensions initially, then we'll calculate the real size and - " resize it. - let opts = { - \ 'relative': 'cursor', - \ 'width': s:max_width + 2, - \ 'height': s:max_height + 2, - \ 'col': 0, - \ 'row': 1, - \ 'anchor': 'NW', - \ 'style': 'minimal' - \ } - - " this is the border window - let s:nvim_border_win_id = nvim_open_win( buf_id, 0, opts ) - call nvim_win_set_option( s:nvim_border_win_id, 'signcolumn', 'no' ) - call nvim_win_set_option( s:nvim_border_win_id, 'relativenumber', v:false ) - call nvim_win_set_option( s:nvim_border_win_id, 'number', v:false ) - - " when calculating where to display the content window, we need to account - " for the border - let opts.row += 1 - let opts.height -= 2 - let opts.col += 2 - let opts.width -= 4 - - " create the content window - let buf_id = nvim_create_buf( v:false, v:true ) - call nvim_buf_set_lines( buf_id, 0, -1, v:true, a:body ) - call nvim_buf_set_option( buf_id, 'modifiable', v:false ) - let s:popup_win_id = nvim_open_win( buf_id, v:false, opts ) - - " Apparently none of these work, when 'style' is 'minimal' - call nvim_win_set_option( s:popup_win_id, 'wrap', v:false ) - call nvim_win_set_option( s:popup_win_id, 'cursorline', v:true ) - call nvim_win_set_option( s:popup_win_id, 'signcolumn', 'no' ) - call nvim_win_set_option( s:popup_win_id, 'relativenumber', v:false ) - call nvim_win_set_option( s:popup_win_id, 'number', v:false ) - - " Move the cursor into the popup window, as this is the only way we can - " interract with the popup in neovim - noautocmd call win_gotoid( s:popup_win_id ) - - nnoremap quit - call py3eval( "__import__( 'vimspector', " - \." fromlist = [ 'variables' ] )." - \.' variables.AddExpandMappings()' ) - - " Close the popup whenever we leave this window - augroup vimspector#internal#balloon#nvim_float - autocmd! - autocmd WinLeave - \ :call vimspector#internal#balloon#Close() - \ | autocmd! vimspector#internal#balloon#nvim_float - augroup END - - call vimspector#internal#balloon#ResizeTooltip() -endfunction - -" }}} - - " Boilerplate {{{ let &cpoptions=s:save_cpo unlet s:save_cpo diff --git a/autoload/vimspector/internal/channel.vim b/autoload/vimspector/internal/channel.vim index e033cff..b05d8e8 100644 --- a/autoload/vimspector/internal/channel.vim +++ b/autoload/vimspector/internal/channel.vim @@ -62,7 +62,7 @@ function! vimspector#internal#channel#StartDebugSession( config ) abort \ ) endif - let l:addr = get( a:config, 'host', '127.0.0.1' ) . ':' . a:config[ 'port' ] + let l:addr = get( a:config, 'host', 'localhost' ) . ':' . a:config[ 'port' ] echo 'Connecting to ' . l:addr . '... (waiting fo up to 10 seconds)' let s:ch = ch_open( l:addr, @@ -95,44 +95,21 @@ EOF endfunction function! vimspector#internal#channel#StopDebugSession() abort - - if exists( 's:job' ) - " We started the job, so we need to kill it and wait to read all the data - " from the socket - - if job_status( s:job ) ==# 'run' - call job_stop( s:job, 'term' ) - endif - - while job_status( s:job ) ==# 'run' - call job_stop( s:job, 'kill' ) - endwhile - - unlet s:job - - if exists( 's:ch' ) && count( [ 'closed', 'fail' ], ch_status( s:ch ) ) == 0 - " We're going to block on this channel reading, then manually call the - " close callback, so remove the automatic close callback to avoid tricky - " re-entrancy - call ch_setoptions( s:ch, { 'close_cb': '' } ) - endif - - elseif exists( 's:ch' ) && - \ count( [ 'closed', 'fail' ], ch_status( s:ch ) ) == 0 - + if exists( 's:ch' ) && ch_status( s:ch ) ==# 'open' " channel is open, close it and trigger the callback. The callback is _not_ " triggered when manually calling ch_close. if we get here and the channel " is not open, then we there is a _OnClose callback waiting for us, so do " nothing. call ch_close( s:ch ) + call s:_OnClose( s:ch ) endif - " block until we've read all data from the socket and handled it. - while count( [ 'open', 'buffered' ], ch_status( s:ch ) ) == 1 - let data = ch_read( s:ch, { 'timeout': 10 } ) - call s:_OnServerData( s:ch, data ) - endwhile - call s:_OnClose( s:ch ) + if exists( 's:job' ) + if job_status( s:job ) ==# 'run' + call job_stop( s:job, 'kill' ) + endif + unlet s:job + endif endfunction function! vimspector#internal#channel#Reset() abort diff --git a/autoload/vimspector/internal/neochannel.vim b/autoload/vimspector/internal/neochannel.vim index f20684d..5414568 100644 --- a/autoload/vimspector/internal/neochannel.vim +++ b/autoload/vimspector/internal/neochannel.vim @@ -66,7 +66,7 @@ function! vimspector#internal#neochannel#StartDebugSession( config ) abort endtry endif - let l:addr = get( a:config, 'host', '127.0.0.1' ) . ':' . a:config[ 'port' ] + let l:addr = get( a:config, 'host', 'localhost' ) . ':' . a:config[ 'port' ] let attempt = 1 while attempt <= 10 diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index a398afe..0cefc63 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -159,16 +159,15 @@ function! s:_OnCommandEvent( category, id, data, event ) abort call setbufvar( buffer, '&modified', 0 ) endtry - " if the buffer is visible, scroll it, but don't allow autocommands to fire, - " as this may close the current window! + " if the buffer is visible, scroll it let w = bufwinnr( buffer ) if w > 0 let cw = winnr() try - noautocmd execute w . 'wincmd w' - noautocmd normal! Gz- + execute w . 'wincmd w' + normal! Gz- finally - noautocmd execute cw . 'wincmd w' + 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 a734ca3..fe5fe05 100644 --- a/autoload/vimspector/internal/neopopup.vim +++ b/autoload/vimspector/internal/neopopup.vim @@ -80,56 +80,6 @@ function! vimspector#internal#neopopup#HideSplash( id ) abort unlet s:db[ a:id ] endfunction -function! vimspector#internal#neopopup#Confirm( confirm_id, - \ text, - \ options, - \ default_value, - \ keys ) abort - - " 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 - 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 083fdf5..fc8820b 100644 --- a/autoload/vimspector/internal/popup.vim +++ b/autoload/vimspector/internal/popup.vim @@ -12,7 +12,6 @@ " 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 {{{ @@ -33,113 +32,6 @@ function! vimspector#internal#popup#HideSplash( id ) abort call popup_hide( a:id ) endfunction -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 - - 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 - py3 __import__( 'vimspector', fromlist = [ 'utils' ] ).utils.ConfirmCallback( - \ int( vim.eval( 'a:confirm_id' ) ), - \ 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, - \ 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 - - 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 deleted file mode 100644 index 367d409..0000000 --- a/doc/vimspector-ref.txt +++ /dev/null @@ -1,1085 +0,0 @@ -*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 deleted file mode 100644 index 8def87f..0000000 --- a/doc/vimspector.txt +++ /dev/null @@ -1,2394 +0,0 @@ -*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 b/docs/Gemfile index 18f79a6..3f49941 100644 --- a/docs/Gemfile +++ b/docs/Gemfile @@ -28,5 +28,3 @@ gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] # Performance-booster for watching directories on Windows gem "wdm", "~> 0.1.0" if Gem.win_platform? - -gem "webrick", "~> 1.7" diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index acf20f2..c28eebb 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -1,13 +1,13 @@ GEM remote: https://rubygems.org/ specs: - activesupport (6.0.3.6) + activesupport (6.0.3.2) 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.8.0) + addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) coffee-script (2.4.1) coffee-script-source @@ -16,49 +16,46 @@ GEM colorator (1.1.0) commonmarker (0.17.13) ruby-enum (~> 0.5) - concurrent-ruby (1.1.8) - dnsruby (1.61.5) + concurrent-ruby (1.1.7) + dnsruby (1.61.4) simpleidn (~> 0.1) - em-websocket (0.5.2) + em-websocket (0.5.1) eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) ethon (0.12.0) ffi (>= 1.3.0) eventmachine (1.2.7) execjs (2.7.0) - faraday (1.3.0) - faraday-net_http (~> 1.0) + faraday (1.0.1) multipart-post (>= 1.2, < 3) - ruby2_keywords - faraday-net_http (1.0.1) - ffi (1.15.0) + ffi (1.13.1) forwardable-extended (2.6.0) gemoji (3.0.1) - github-pages (214) - github-pages-health-check (= 1.17.0) + github-pages (207) + github-pages-health-check (= 1.16.1) jekyll (= 3.9.0) jekyll-avatar (= 0.7.0) jekyll-coffeescript (= 1.1.1) jekyll-commonmark-ghpages (= 0.1.6) jekyll-default-layout (= 0.1.4) - jekyll-feed (= 0.15.1) + jekyll-feed (= 0.13.0) jekyll-gist (= 1.5.0) jekyll-github-metadata (= 2.13.0) - jekyll-mentions (= 1.6.0) + jekyll-mentions (= 1.5.1) jekyll-optional-front-matter (= 0.3.2) jekyll-paginate (= 1.1.0) jekyll-readme-index (= 0.3.0) - jekyll-redirect-from (= 0.16.0) + jekyll-redirect-from (= 0.15.0) jekyll-relative-links (= 0.6.1) - jekyll-remote-theme (= 0.4.3) + jekyll-remote-theme (= 0.4.1) jekyll-sass-converter (= 1.5.2) - jekyll-seo-tag (= 2.7.1) + jekyll-seo-tag (= 2.6.1) jekyll-sitemap (= 1.4.0) jekyll-swiss (= 1.0.0) jekyll-theme-architect (= 0.1.1) jekyll-theme-cayman (= 0.1.1) jekyll-theme-dinky (= 0.1.1) - jekyll-theme-hacker (= 0.1.2) + jekyll-theme-hacker (= 0.1.1) jekyll-theme-leap-day (= 0.1.1) jekyll-theme-merlot (= 0.1.1) jekyll-theme-midnight (= 0.1.1) @@ -69,20 +66,20 @@ GEM jekyll-theme-tactile (= 0.1.1) jekyll-theme-time-machine (= 0.1.1) jekyll-titles-from-headings (= 0.5.3) - jemoji (= 0.12.0) - kramdown (= 2.3.1) + jemoji (= 0.11.1) + kramdown (= 2.3.0) 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.26.0) + rouge (= 3.19.0) terminal-table (~> 1.4) - github-pages-health-check (1.17.0) + github-pages-health-check (1.16.1) addressable (~> 2.3) dnsruby (~> 1.60) octokit (~> 4.0) - public_suffix (>= 2.0.2, < 5.0) + public_suffix (~> 3.0) typhoeus (~> 1.3) html-pipeline (2.14.0) activesupport (>= 2) @@ -117,14 +114,14 @@ GEM rouge (>= 2.0, < 4.0) jekyll-default-layout (0.1.4) jekyll (~> 3.0) - jekyll-feed (0.15.1) + jekyll-feed (0.13.0) jekyll (>= 3.7, < 5.0) jekyll-gist (1.5.0) octokit (~> 4.2) jekyll-github-metadata (2.13.0) jekyll (>= 3.4, < 5.0) octokit (~> 4.0, != 4.4.0) - jekyll-mentions (1.6.0) + jekyll-mentions (1.5.1) html-pipeline (~> 2.3) jekyll (>= 3.7, < 5.0) jekyll-optional-front-matter (0.3.2) @@ -132,19 +129,18 @@ GEM jekyll-paginate (1.1.0) jekyll-readme-index (0.3.0) jekyll (>= 3.0, < 5.0) - jekyll-redirect-from (0.16.0) + jekyll-redirect-from (0.15.0) jekyll (>= 3.3, < 5.0) jekyll-relative-links (0.6.1) jekyll (>= 3.3, < 5.0) - jekyll-remote-theme (0.4.3) + jekyll-remote-theme (0.4.1) 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) + rubyzip (>= 1.3.0) jekyll-sass-converter (1.5.2) sass (~> 3.4) - jekyll-seo-tag (2.7.1) - jekyll (>= 3.8, < 5.0) + jekyll-seo-tag (2.6.1) + jekyll (>= 3.3, < 5.0) jekyll-sitemap (1.4.0) jekyll (>= 3.7, < 5.0) jekyll-swiss (1.0.0) @@ -157,8 +153,8 @@ GEM jekyll-theme-dinky (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-hacker (0.1.2) - jekyll (> 3.5, < 5.0) + jekyll-theme-hacker (0.1.1) + jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) jekyll-theme-leap-day (0.1.1) jekyll (~> 3.5) @@ -192,44 +188,41 @@ GEM jekyll (>= 3.3, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) - jemoji (0.12.0) + jemoji (0.11.1) gemoji (~> 3.0) html-pipeline (~> 2.2) jekyll (>= 3.0, < 5.0) - kramdown (2.3.1) + kramdown (2.3.0) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) liquid (4.0.3) - listen (3.5.1) + listen (3.2.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.3.6) - mini_portile2 (2.5.1) + mini_portile2 (2.4.0) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) - minitest (5.14.4) + minitest (5.14.1) multipart-post (2.1.1) - nokogiri (1.11.5) - mini_portile2 (~> 2.5.0) - racc (~> 1.4) - octokit (4.20.0) + nokogiri (1.10.10) + mini_portile2 (~> 2.4.0) + octokit (4.18.0) faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (4.0.6) - racc (1.5.2) + public_suffix (3.1.1) rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) - rexml (3.2.5) - rouge (3.26.0) - ruby-enum (0.9.0) + rexml (3.2.4) + rouge (3.19.0) + ruby-enum (0.8.0) i18n - ruby2_keywords (0.0.4) rubyzip (2.3.0) safe_yaml (1.0.5) sass (3.7.4) @@ -240,21 +233,20 @@ GEM sawyer (0.8.2) addressable (>= 2.3.5) faraday (> 0.8, < 2.0) - simpleidn (0.2.1) + simpleidn (0.1.1) unf (~> 0.1.4) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) thread_safe (0.3.6) typhoeus (1.4.0) ethon (>= 0.9.0) - tzinfo (1.2.9) + tzinfo (1.2.7) thread_safe (~> 0.1) unf (0.1.4) unf_ext unf_ext (0.0.7.7) unicode-display_width (1.7.0) - webrick (1.7.0) - zeitwerk (2.4.2) + zeitwerk (2.4.0) PLATFORMS ruby @@ -264,7 +256,6 @@ DEPENDENCIES jekyll-feed (~> 0.6) minima (~> 2.0) tzinfo-data - webrick (~> 1.7) BUNDLED WITH - 2.2.3 + 2.1.4 diff --git a/docs/configuration.md b/docs/configuration.md index 3d524bf..acf77b4 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": true + "stopOnEntry#json": true ``` Which is what we need. @@ -633,26 +633,19 @@ Vimspector then orchestrates the various tools to set you up. // 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", + "launchCommmand": [ + "python", "-m", "debugpy", "--listen", "0.0.0.0:${port}", "%CMD%" ] - // Optional alternative to runCommand (if you need to run multiple + // Optional alternative to launchCommmand (if you need to run multiple // commands) - // "runCommands": [ + // "launchCommmands": [ // [ /* 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": { @@ -692,10 +685,6 @@ Vimspector then orchestrates the various tools to set you up. // "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 } } }, @@ -722,7 +711,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": "${fileBasenameNoExtension}" + "ServiceName": "${fileBasenameNoExtention}" }, "adapter": "python-remote", @@ -765,7 +754,7 @@ and have to tell cpptools a few more options. "remote": { "host": "${host}", "account": "${account}", - "runCommand": [ + "launchCommmand": [ "gdbserver", "--once", "--no-startup-with-shell", @@ -849,25 +838,19 @@ port. // 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", + "launchCommmand": [ + "python", "-m", "debugpy", "--listen", "0.0.0.0:${port}", "%CMD%" ] - // Optional alternative to runCommand (if you need to run multiple + // Optional alternative to launchCommmand (if you need to run multiple // commands) - // "runCommands": [ + // "launchCommmands": [ // [ /* 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": { @@ -903,11 +886,6 @@ port. // ] } - - // 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 } } }, diff --git a/docs/schema/vimspector.schema.json b/docs/schema/vimspector.schema.json index cd79f11..c8af196 100644 --- a/docs/schema/vimspector.schema.json +++ b/docs/schema/vimspector.schema.json @@ -38,144 +38,11 @@ ] } }, - "adapter-launchattach": { - "properties": { - "launch": { - "allOf": [ - { "$ref": "#/definitions/adapter-remote" }, - { - "properties": { - "delay": { - "type": "string", - "description": "A time in the format understood by :help :sleep to wait after running the attachCommand(s)" - } - } - } - ] - }, - "attach": { - "allOf": [ - { "$ref": "#/definitions/adapter-remote" }, - { - "type": "object", - "required": [ "pidSelect" ], - "properties": { - "pidSelect": { - "enum": [ "ask", "none" ] - }, - "pidProperty": { - "type": "string", - "description": "The launch config property which the PID should be injected into. Required when 'pidSelect' is 'ask'." - }, - "delay": { - "type": "string", - "description": "A time in the format understood by :help :sleep to wait after running the attachCommand(s)" - } - } - } - ] - } - } - }, - "adapter-remote": { - "type": "object", - "properties": { - "remote": { - "type": "object", - "description": "Configures how Vimspector will marshal remote debugging requests. When remote debugging, Vimspector will either ssh to 'account'@'host' or docker exec -it to 'container' and run 'pidCommand', 'attachCommands', 'runCommands', etc. based on the 'remote-command' option in the debug configuration. If 'remote-command' is 'launch', it runs 'runCommand(s)', otherwise (it's 'attach') vimspector runs 'pidCommand', followed by 'attachCommand(s)'.Then it starts up the debug adapter with the debug configuration as normal. Usually this is configured with an 'attach' request (whether we remotely 'launched' or not). Once the initialization exchange is complete, Vimspector runs the optional 'initCompleteCommand' which can be used to force the application to break, e.g. by sending it SIGINT. This is required on some platforms which have buggy gdbservers (for example)", - "allOf": [ - { - "oneOf": [ - { "required": [ "host" ] }, - { "required": [ "container" ] } - ] - }, - { - "properties": { - "account": { - "type": "string", - "description": "Remote account name used when ssh'ing. Defaults to the current user account." - }, - "host": { - "type": "string", - "description": "Name of the remote host to connect to (via passwordless SSH)." - }, - "container": { - "type": "string", - "description": "Name or container id of the docker run container to connect to (via docker exec). Note the container must already be running (Vimspector will not start it) and it must have the port forwarded to the host if subsequently connecting via a port (for example docker run -p 8765:8765 -it simple_python)." - } - } - }, - { - "oneOf": [ - { - "allOf": [ - { - "oneOf": [ - { "required": [ "attachCommand" ] }, - { "required": [ "attachCommands" ] } - ] - }, - { - "properties": { - "initCompleteCommand": { - "type": "array", - "items": { "type": "string" }, - "description": "For remote-attach. Remote command to execute after initialization of the debug adapter. Can be used to work around buggy attach behaviour on certain platforms (advanced usage). Can contain the special token %PID% which is replaced with the PID returned by 'pidCommand'" - }, - "pidCommand": { - "type": "array", - "items": { "type": "string" }, - "description": "Required for remote-attach. Remote command to execute to return the PID to attach to." - }, - "attachCommands": { - "type": [ "array" ], - "items": { "type": "array", "items": { "type": "string" } }, - "description": "For remote-attach. List of commands to execute remotely to set up the attach. Can contain the special token %PID% which is replaced with the PID returned by the remote 'pidCommand'." - }, - "attachCommand": { - "type": "array", - "items": { "type": "string" }, - "description": "A single command to execute for remote-attach. Like attachCommands but for a single command. If attachCommands is supplied, this is not used." - } - } - } - ] - }, - { - "allOf": [ - { - "oneOf": [ - { "required": [ "runCommand" ] }, - { "required": [ "runCommands" ] } - ] - }, - { - "properties": { - "runCommands": { - "type": [ "array" ], - "items": { "type": "array", "items": { "type": "string" } }, - "description": "For remote-launch. List of commands to execute remotely to set up the launch. An entry in the array can be the special token '%CMD%' which is replaced with the evaluated 'remote-cmdLine' value in the debug configuration. This is useful to parameterize launcging remotely under something like gdbserver." - }, - "runCommand": { - "type": "array", - "items": { "type": "string" }, - "description": "A single command to execute for remote-launch. Like runCommands but for a single command." - } - } - } - ] - } - ] - } - ] - } - } - }, - "adapter": { + "adapter-common": { "allOf": [ - { "type": "object" }, { "$ref": "#/definitions/variables" }, + { "$ref": "#/definitions/adapter-remote" }, + { "$ref": "#/definitions/adapter-attach" }, { "properties": { "name": { @@ -187,30 +54,136 @@ "description": "Base debug configuration. Can be used to set default values for all debug configurations. When reading individual debug configurations from 'configurations', those configurations are merged with this object. Definitions in the debug configuration override anything in this object. Typical usage for this is to set the 'type' parameter, which some debug adapters are very picky about, or to set e.g. the path to an underlying debugger." } } - }, - { "$ref": "#/definitions/adapter-launchattach" }, + } + ] + }, + "adapter-attach": { + "properties": { + "attach": { + "type": "object", + "required": [ "pidSelect" ], + "properties": { + "pidSelect": { + "enum": [ "ask", "none" ] + }, + "pidProperty": { + "type": "string", + "description": "The launch config property which the PID should be injected into. Required when 'pidSelect' is 'ask'." + } + } + } + } + }, + "adapter-remote": { + "properties": { + "remote": { + "type": "object", + "oneOf": [ + { + "required": [ + "host" + ] + }, + { + "required": [ + "container" + ] + } + ], + "description": "Configures how Vimspector will marshal remote debugging requests. When remote debugging, Vimspector will either ssh to 'account'@'host' or docker exec -it to 'container' and run 'pidCommand', 'attachCommands', 'runCommands', etc. based on the 'remote-command' option in the debug configuration. If 'remote-command' is 'launch', it runs 'runCommand(s)', otherwise (it's 'attach') vimspector runs 'pidCommand', followed by 'attachCommand(s)'.Then it starts up the debug adapter with the debug configuration as normal. Usually this is configured with an 'attach' request (whether we remotely 'launched' or not). Once the initialization exchange is complete, Vimspector runs the optional 'initCompleteCommand' which can be used to force the application to break, e.g. by sending it SIGINT. This is required on some platforms which have buggy gdbservers (for example)", + "properties": { + "account": { + "type": "string", + "description": "Remote account name used when ssh'ing. Defaults to the current user account." + }, + "host": { + "type": "string", + "description": "Name of the remote host to connect to (via passwordless SSH)." + }, + "container": { + "type": "string", + "description": "Name or container id of the docker run container to connect to (via docker exec -it)." + }, + "pidCommand": { + "type": "array", + "items": { "type": "string" }, + "description": "Required for remote-attach. Remote command to execute to return the PID to attach to." + }, + "initCompleteCommand": { + "type": "array", + "items": { "type": "string" }, + "description": "For remote-attach. Remote command to execute after initialization of the debug adapter. Can be used to work around buggy attach behaviour on certain platforms (advanced usage). Can contain the special token %PID% which is replaced with the PID returned by 'pidCommand'" + }, + "attachCommands": { + "type": [ "array" ], + "items": { "type": "array", "items": { "type": "string" } }, + "description": "For remote-attach. List of commands to execute remotely to set up the attach. Can contain the special token %PID% which is replaced with the PID returned by the remote 'pidCommand'." + }, + "attachCommand": { + "type": "array", + "items": { "type": "string" }, + "description": "A single command to execute for remote-attach. Like attachCommands but for a single command. If attachCommands is supplied, this is not used." + }, + "runCommands": { + "type": [ "array" ], + "items": { "type": "array", "items": { "type": "string" } }, + "description": "For remote-launch. List of commands to execute remotely to set up the launch. An entry in the array can be the special token '%CMD%' which is replaced with the evaluated 'remote-cmdLine' value in the debug configuration. This is useful to parameterize launcging remotely under something like gdbserver." + }, + "runCommand": { + "type": "array", + "items": { "type": "string" }, + "description": "A single command to execute for remote-launch. Like runCommands but for a single command." + } + } + } + } + }, + "adapter": { + "oneOf": [ { - "anyOf": [ - { "required": [ "command" ] }, - { "required": [ "port" ] }, - { "required": [ "command", "port" ] } + "allOf": [ + { "$ref": "#/definitions/adapter-common" }, + { + "required": [ "port" ], + "properties": { + "port": { + "oneOf": [ + { + "type": "string", + "enum": [ "ask" ] + }, + { + "type": "integer" + } + ], + "description": "If supplied, indicates that a socket connection should be made to this port on 'localhost'. If the value is 'ask', then the user is asked to enter the port number to connect to." + } + } + } ] }, { - "properties": { - "host": { - "type": "string", - "default": "127.0.0.1", - "description": "Connect to this host in multi-session mode" - }, - "port": { - "oneOf": [ - { "type": "string" }, - { "type": "integer" } - ], - "description": "If supplied, indicates that a socket connection should be made to this port on 'host'. If the value is 'ask', then the user is asked to enter the port number to connect to." + "allOf": [ + { "$ref": "#/definitions/adapter-common" }, + { + "required": [ "command" ], + "properties": { + "command": { + "type": [ "string", "array" ], + "description": "Command line to execute the debug adapter.", + "items": { "type": "string" } + }, + "env": { + "type": "object", + "description": "Name/value pairs to set in the environment when starting the adapter." + }, + "cwd": { + "type": "string", + "description": "Directory from which to start the adapter. Defaults to the working directory of the window on launch" + } + } } - } + ] } ] } diff --git a/install_gadget.py b/install_gadget.py index b6e2fd7..2aa910e 100755 --- a/install_gadget.py +++ b/install_gadget.py @@ -113,36 +113,33 @@ parser.add_argument( '--sudo', "run this as root via sudo, pass this flag." ) done_languages = set() -for name, gadget in gadgets.GADGETS.items(): - langs = gadget[ 'language' ] - if not isinstance( langs, list ): - langs = [ langs ] - for lang in langs: - if lang in done_languages: - continue - - done_languages.add( lang ) - if not gadget.get( 'enabled', True ): - parser.add_argument( - '--force-enable-' + lang, - action = 'store_true', - help = 'Install the unsupported {} debug adapter for {} support'.format( - name, - lang ) ) - continue +for name, gadget in gadgets.Gadgets().items(): + lang = gadget[ 'language' ] + if lang in done_languages: + continue + done_languages.add( lang ) + if not gadget.get( 'enabled', True ): parser.add_argument( - '--enable-' + lang, + '--force-enable-' + lang, action = 'store_true', - help = 'Install the {} debug adapter for {} support'.format( + help = 'Install the unsupported {} debug adapter for {} support'.format( name, lang ) ) + continue - parser.add_argument( - '--disable-' + lang, - action = 'store_true', - help = "Don't install the {} debug adapter for {} support " - '(when supplying --all)'.format( name, lang ) ) + parser.add_argument( + '--enable-' + lang, + action = 'store_true', + help = 'Install the {} debug adapter for {} support'.format( + name, + lang ) ) + + parser.add_argument( + '--disable-' + lang, + action = 'store_true', + help = "Don't install the {} debug adapter for {} support " + '(when supplying --all)'.format( name, lang ) ) parser.add_argument( "--no-check-certificate", @@ -184,26 +181,16 @@ all_adapters = installer.ReadAdapters( read_existing = args.update_gadget_config ) manifest = installer.Manifest() -for name, gadget in gadgets.GADGETS.items(): - langs = gadget[ 'language' ] - if not isinstance( langs, list ): - langs = [ langs ] - skip = 0 - for lang in langs: - if not gadget.get( 'enabled', True ): - if ( not args.force_all - and not getattr( args, 'force_enable_' + lang ) ): - skip = skip + 1 - continue - else: - if not args.all and not getattr( args, 'enable_' + lang ): - skip = skip + 1 - continue - if getattr( args, 'disable_' + lang ): - skip = skip + 1 - continue - if skip == len( langs ): - continue +for name, gadget in gadgets.Gadgets().items(): + if not gadget.get( 'enabled', True ): + if ( not args.force_all + and not getattr( args, 'force_enable_' + gadget[ 'language' ] ) ): + continue + else: + if not args.all and not getattr( args, 'enable_' + gadget[ 'language' ] ): + continue + if getattr( args, 'disable_' + gadget[ 'language' ] ): + continue if not args.upgrade: manifest.Clear( name ) diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 2668bf1..2dbbd82 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -13,13 +13,6 @@ " 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 @@ -35,6 +28,11 @@ if exists( 'g:loaded_vimpector' ) endif "}}} +" TODO: +" - Check Vim version (for jobs) +" - Check python support +" - Add commands/mappings/menus? + let g:loaded_vimpector = 1 let g:vimspector_home = expand( ':p:h:h' ) @@ -42,8 +40,6 @@ let s:mappings = get( g:, 'vimspector_enable_mappings', '' ) nnoremap VimspectorContinue \ :call vimspector#Continue() -nnoremap VimspectorLaunch - \ :call vimspector#Launch( v:true ) nnoremap VimspectorStop \ :call vimspector#Stop() nnoremap VimspectorRestart @@ -69,18 +65,6 @@ nnoremap VimspectorStepOut nnoremap VimspectorRunToCursor \ :call vimspector#RunToCursor() -" Eval for normal mode -nnoremap VimspectorBalloonEval - \ :call vimspector#ShowEvalBalloon( 0 ) -" And for visual modes -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 @@ -93,7 +77,6 @@ if s:mappings ==# 'VISUAL_STUDIO' nmap VimspectorStepOut elseif s:mappings ==# 'HUMAN' nmap VimspectorContinue - nmap VimspectorLaunch nmap VimspectorStop nmap VimspectorRestart nmap VimspectorPause @@ -115,15 +98,12 @@ 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 +command! -bar -nargs=1 -complete=custom,vimspector#CompleteExpr \ VimspectorEval \ call vimspector#Evaluate( ) command! -bar \ VimspectorReset - \ call vimspector#Reset( { 'interactive': v:true } ) + \ call vimspector#Reset() " Installer commands command! -bar -bang -nargs=* -complete=custom,vimspector#CompleteInstall @@ -143,11 +123,8 @@ augroup VimspectorUserAutoCmds autocmd! autocmd User VimspectorUICreated silent autocmd User VimspectorTerminalOpened silent - autocmd user VimspectorJumpedToFrame silent - autocmd user VimspectorDebugEnded silent augroup END -" FIXME: Only register this _while_ debugging is active augroup Vimspector autocmd! autocmd BufNew * call vimspector#OnBufferCreated( expand( '' ) ) diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index 98aeca5..d3c6324 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -134,7 +134,6 @@ class CodeView( object ): utils.JumpToWindow( self._window ) try: utils.OpenFileInCurrentWindow( frame[ 'source' ][ 'path' ] ) - vim.command( 'doautocmd User VimspectorJumpedToFrame' ) except vim.error: self._logger.exception( 'Unexpected vim error opening file {}'.format( frame[ 'source' ][ 'path' ] ) ) diff --git a/python3/vimspector/custom/java.py b/python3/vimspector/custom/java.py deleted file mode 100644 index c2a2264..0000000 --- a/python3/vimspector/custom/java.py +++ /dev/null @@ -1,51 +0,0 @@ -# vimspector - A multi-language debugging system for Vim -# Copyright 2021 Ben Jackson -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# 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. - -from vimspector.debug_session import DebugSession -from vimspector import utils, settings - - -class JavaDebugAdapter( object ): - def __init__( self, debug_session: DebugSession ): - self.debug_session = debug_session - - def OnEvent_hotcodereplace( self, message ): - # Hack for java debug server hot-code-replace - body = message.get( 'body' ) or {} - - if body.get( 'type' ) != 'hotcodereplace': - return - - if body.get( 'changeType' ) == 'BUILD_COMPLETE': - def handler( result ): - if result == 1: - self.debug_session._connection.DoRequest( None, { - 'command': 'redefineClasses', - 'arguments': {}, - } ) - - 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 206938a..283c40c 100644 --- a/python3/vimspector/debug_adapter_connection.py +++ b/python3/vimspector/debug_adapter_connection.py @@ -29,14 +29,14 @@ class PendingRequest( object ): class DebugAdapterConnection( object ): - def __init__( self, handlers, send_func ): + def __init__( self, handler, send_func ): self._logger = logging.getLogger( __name__ ) utils.SetUpLogging( self._logger ) self._Write = send_func self._SetState( 'READ_HEADER' ) self._buffer = bytes() - self._handlers = handlers + self._handler = handler self._next_message_id = 0 self._outstanding_requests = {} @@ -124,7 +124,7 @@ class DebugAdapterConnection( object ): def Reset( self ): self._Write = None - self._handlers = None + self._handler = None while self._outstanding_requests: _, request = self._outstanding_requests.popitem() @@ -226,12 +226,7 @@ class DebugAdapterConnection( object ): # self._logger.debug( 'Message received (raw): %s', payload ) - try: - message = json.loads( payload, strict = False ) - except Exception: - self._logger.exception( "Invalid message received: %s", payload ) - self._SetState( 'READ_HEADER' ) - raise + message = json.loads( payload ) self._logger.debug( 'Message received: {0}'.format( message ) ) @@ -242,7 +237,7 @@ class DebugAdapterConnection( object ): def _OnMessageReceived( self, message ): - if not self._handlers: + if not self._handler: return if message[ 'type' ] == 'response': @@ -275,21 +270,25 @@ class DebugAdapterConnection( object ): self._logger.error( 'Request failed: {0}'.format( reason ) ) if request.failure_handler: request.failure_handler( reason, message ) + elif 'OnFailure' in dir( self._handler ): + self._handler.OnFailure( reason, request.msg, message ) else: - for h in self._handlers: - if 'OnFailure' in dir( h ): - h.OnFailure( reason, request.msg, message ) - + utils.UserMessage( 'Request failed: {0}'.format( reason ) ) elif message[ 'type' ] == 'event': method = 'OnEvent_' + message[ 'event' ] - for h in self._handlers: - if method in dir( h ): - getattr( h, method )( message ) + if method in dir( self._handler ): + getattr( self._handler, method )( message ) + else: + utils.UserMessage( 'Unhandled event: {0}'.format( message[ 'event' ] ), + persist = True ) elif message[ 'type' ] == 'request': method = 'OnRequest_' + message[ 'command' ] - for h in self._handlers: - if method in dir( h ): - getattr( h, method )( message ) + if method in dir( self._handler ): + getattr( self._handler, method )( message ) + else: + utils.UserMessage( + 'Unhandled request: {0}'.format( message[ 'command' ] ), + persist = True ) def _KillTimer( request ): diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 36ad62b..6a231a0 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -21,7 +21,6 @@ import shlex import subprocess import functools import vim -import importlib from vimspector import ( breakpoints, code, @@ -69,7 +68,6 @@ class DebugSession( object ): self._configuration = None self._adapter = None - self._launch_config = None self._ResetServerState() @@ -93,14 +91,21 @@ class DebugSession( object ): if not launch_config_file or not os.path.exists( launch_config_file ): continue - with open( launch_config_file, 'r' ) as f: - database = json.loads( minify( f.read() ) ) - configurations.update( database.get( 'configurations' ) or {} ) - adapters.update( database.get( 'adapters' ) or {} ) + try: + with open( launch_config_file, 'r' ) as f: + database = json.loads( minify( f.read() ) ) + if database: + configurations.update( database.get( 'configurations' or {} ) ) + adapters.update( database.get( 'adapters' ) or {} ) + except json.JSONDecodeError as e: + self._logger.exception( f"Unable to read { launch_config_file }" ) + utils.UserMessage( f"Unable to read { launch_config_file }: { e }", + error = True, + persist = True ) return launch_config_file, configurations - def Start( self, force_choose=False, launch_variables = None ): + def Start( self, launch_variables = None ): # We mutate launch_variables, so don't mutate the default argument. # https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments if launch_variables is None: @@ -110,16 +115,17 @@ class DebugSession( object ): launch_variables ) self._configuration = None self._adapter = None - self._launch_config = None current_file = utils.GetBufferFilepath( vim.current.buffer ) adapters = {} launch_config_file, configurations = self.GetConfigurations( adapters ) if not configurations: - utils.UserMessage( 'Unable to find any debug configurations. ' + utils.UserMessage( 'Unable to find any valid debug configurations. ' 'You need to tell vimspector how to launch your ' - 'application.' ) + 'application. See :messages for any errors.', + persist = True, + error = True ) return glob.glob( install.GetGadgetDir( VIMSPECTOR_HOME ) ) @@ -129,17 +135,18 @@ class DebugSession( object ): if not gadget_config_file or not os.path.exists( gadget_config_file ): continue - with open( gadget_config_file, 'r' ) as f: - a = json.loads( minify( f.read() ) ).get( 'adapters' ) or {} - adapters.update( a ) + try: + with open( gadget_config_file, 'r' ) as f: + a = json.loads( minify( f.read() ) ).get( 'adapters' ) or {} + adapters.update( a ) + except json.JSONDecodeError as e: + self._logger.exception( f'Unable to read { gadget_config_file }' ) + utils.UserMessage( f"Unable to read { gadget_config_file }: { e }", + error = True, + persist = True ) if 'configuration' in launch_variables: configuration_name = launch_variables.pop( 'configuration' ) - elif force_choose: - # Always display the menu - configuration_name = utils.SelectFromList( - 'Which launch configuration?', - sorted( configurations.keys() ) ) elif ( len( configurations ) == 1 and next( iter( configurations.values() ) ).get( "autoselect", True ) ): configuration_name = next( iter( configurations.keys() ) ) @@ -288,7 +295,6 @@ class DebugSession( object ): def start(): self._configuration = configuration self._adapter = adapter - self._launch_config = None self._logger.info( 'Configuration: %s', json.dumps( self._configuration ) ) @@ -300,7 +306,6 @@ class DebugSession( object ): else: vim.current.tabpage = self._uiTab - self._Prepare() self._StartDebugAdapter() self._Initialise() @@ -326,7 +331,7 @@ class DebugSession( object ): if self._connection: self._logger.debug( "_StopDebugAdapter with callback: start" ) - self._StopDebugAdapter( interactive = False, callback = start ) + self._StopDebugAdapter( start ) return start() @@ -391,15 +396,14 @@ class DebugSession( object ): self._connection = None @IfConnected() - def Stop( self, interactive = False ): + def Stop( self ): self._logger.debug( "Stop debug adapter with no callback" ) - self._StopDebugAdapter( interactive = interactive ) + self._StopDebugAdapter() - def Reset( self, interactive = False ): + def Reset( self ): if self._connection: self._logger.debug( "Stop debug adapter with callback : self._Reset()" ) - self._StopDebugAdapter( interactive = interactive, - callback = lambda: self._Reset() ) + self._StopDebugAdapter( lambda: self._Reset() ) else: self._Reset() @@ -419,7 +423,6 @@ class DebugSession( object ): self._outputView.Reset() self._codeView.Reset() vim.command( 'tabclose!' ) - vim.command( 'doautocmd User VimspectorDebugEnded' ) self._stackTraceView = None self._variablesView = None self._outputView = None @@ -528,12 +531,8 @@ class DebugSession( object ): self._stackTraceView.SetCurrentThread() @IfConnected() - def ExpandVariable( self, buf = None, line_num = None ): - self._variablesView.ExpandVariable( buf, line_num ) - - @IfConnected() - def SetVariableValue( self, new_value = None, buf = None, line_num = None ): - self._variablesView.SetVariableValue( new_value, buf, line_num ) + def ExpandVariable( self ): + self._variablesView.ExpandVariable() @IfConnected() def AddWatch( self, expression ): @@ -550,13 +549,13 @@ class DebugSession( object ): def DeleteWatch( self ): self._variablesView.DeleteWatch() - @IfConnected() - def ShowEvalBalloon( self, winnr, expression, is_hover ): + def ShowBalloon( self, winnr, expression ): + """Proxy: ballonexpr -> variables.ShowBallon""" frame = self._stackTraceView.GetCurrentFrame() # Check if RIP is in a frame if frame is None: - self._logger.debug( 'Tooltip: Not in a stack frame' ) + self._logger.debug( 'Balloon: Not in a stack frame' ) return '' # Check if cursor in code window @@ -567,24 +566,12 @@ class DebugSession( object ): return '' # Return variable aware function - return self._variablesView.VariableEval( frame, expression, is_hover ) - - - def CleanUpTooltip( self ): - return self._variablesView.CleanUpTooltip() + return self._variablesView.ShowBalloon( frame, expression ) @IfConnected() 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' ) @@ -646,18 +633,6 @@ class DebugSession( object ): return response[ 'body' ][ 'targets' ] - @IfConnected( otherwise=[] ) - def GetCommandLineCompletions( self, ArgLead, prev_non_keyword_char ): - items = [] - for candidate in self.GetCompletionsSync( ArgLead, prev_non_keyword_char ): - label = candidate.get( 'text', candidate[ 'label' ] ) - start = prev_non_keyword_char - 1 - if 'start' in candidate and 'length' in candidate: - start = candidate[ 'start' ] - items.append( ArgLead[ 0 : start ] + label ) - - return items - def RefreshSigns( self, file_name ): if self._connection: self._codeView.Refresh( file_name ) @@ -669,45 +644,6 @@ 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 ) @@ -748,73 +684,12 @@ 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 ), - '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(): @@ -863,6 +738,7 @@ class DebugSession( object ): json.dumps( self._adapter ) ) self._init_complete = False + self._on_init_complete_handlers = [] self._launch_complete = False self._run_on_server_exit = None @@ -878,9 +754,12 @@ class DebugSession( object ): self._adapter[ 'port' ] = port self._connection_type = self._api_prefix + self._connection_type - self._logger.debug( f"Connection Type: { self._connection_type }" ) - self._adapter[ 'env' ] = self._adapter.get( 'env', {} ) + # TODO: Do we actually need to copy and update or does Vim do that? + env = os.environ.copy() + if 'env' in self._adapter: + env.update( self._adapter[ 'env' ] ) + self._adapter[ 'env' ] = env if 'cwd' not in self._adapter: self._adapter[ 'cwd' ] = os.getcwd() @@ -894,93 +773,56 @@ class DebugSession( object ): self._splash_screen, "Unable to start adapter" ) else: - if 'custom_handler' in self._adapter: - spec = self._adapter[ 'custom_handler' ] - if isinstance( spec, dict ): - module = spec[ 'module' ] - cls = spec[ 'class' ] - else: - module, cls = spec.rsplit( '.', 1 ) - - CustomHandler = getattr( importlib.import_module( module ), cls ) - handlers = [ CustomHandler( self ), self ] - else: - handlers = [ self ] - self._connection = debug_adapter_connection.DebugAdapterConnection( - handlers, + self, lambda msg: utils.Call( "vimspector#internal#{}#Send".format( self._connection_type ), msg ) ) self._logger.info( 'Debug Adapter Started' ) - def _StopDebugAdapter( self, interactive = False, callback = None ): + def _StopDebugAdapter( self, callback = None ): + self._splash_screen = utils.DisplaySplash( + self._api_prefix, + self._splash_screen, + "Shutting down debug adapter..." ) + + def handler( *args ): + self._splash_screen = utils.HideSplash( self._api_prefix, + self._splash_screen ) + + if callback: + self._logger.debug( "Setting server exit handler before disconnect" ) + assert not self._run_on_server_exit + self._run_on_server_exit = callback + + vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format( + self._connection_type ) ) + arguments = {} + if self._server_capabilities.get( 'supportTerminateDebuggee' ): + # If we attached, we should _not_ terminate the debuggee + arguments[ 'terminateDebuggee' ] = False - def disconnect(): - self._splash_screen = utils.DisplaySplash( - self._api_prefix, - self._splash_screen, - "Shutting down debug adapter..." ) + self._connection.DoRequest( handler, { + 'command': 'disconnect', + 'arguments': arguments, + }, failure_handler = handler, timeout = 5000 ) - def handler( *args ): - self._splash_screen = utils.HideSplash( self._api_prefix, - self._splash_screen ) - - if callback: - self._logger.debug( "Setting server exit handler before disconnect" ) - assert not self._run_on_server_exit - self._run_on_server_exit = callback - - vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format( - self._connection_type ) ) - - self._connection.DoRequest( handler, { - 'command': 'disconnect', - 'arguments': arguments, - }, failure_handler = handler, timeout = 5000 ) - - if not interactive: - disconnect() - elif not self._server_capabilities.get( 'supportTerminateDebuggee' ): - disconnect() - elif not self._stackTraceView.AnyThreadsRunning(): - disconnect() - else: - def handle_choice( choice ): - if choice == 1: - # yes - arguments[ 'terminateDebuggee' ] = True - elif choice == 2: - # no - arguments[ 'terminateDebuggee' ] = False - elif choice <= 0: - # Abort - return - # Else, use server default - - disconnect() - - utils.Confirm( self._api_prefix, - "Terminate debuggee?", - handle_choice, - default_value = 3, - options = [ '(Y)es', '(N)o', '(D)efault' ], - keys = [ 'y', 'n', 'd' ] ) + # TODO: Use the 'tarminate' request if supportsTerminateRequest set def _PrepareAttach( self, adapter_config, launch_config ): - attach_config = adapter_config.get( 'attach' ) + atttach_config = adapter_config.get( 'attach' ) - if not attach_config: + if not atttach_config: return - if 'remote' in attach_config: + if 'remote' in atttach_config: # FIXME: We almost want this to feed-back variables to be expanded later, # e.g. expand variables when we use them, not all at once. This would # remove the whole %PID% hack. - remote = attach_config[ 'remote' ] + remote = atttach_config[ 'remote' ] remote_exec_cmd = self._GetRemoteExecCommand( remote ) # FIXME: Why does this not use self._GetCommands ? @@ -1021,23 +863,20 @@ class DebugSession( object ): self._codeView._window, self._remote_term ) else: - if attach_config[ 'pidSelect' ] == 'ask': - prop = attach_config[ 'pidProperty' ] + if atttach_config[ 'pidSelect' ] == 'ask': + prop = atttach_config[ 'pidProperty' ] if prop not in launch_config: pid = utils.AskForInput( 'Enter PID to attach to: ' ) if pid is None: return launch_config[ prop ] = pid return - elif attach_config[ 'pidSelect' ] == 'none': + elif atttach_config[ 'pidSelect' ] == 'none': return raise ValueError( 'Unrecognised pidSelect {0}'.format( - attach_config[ 'pidSelect' ] ) ) + atttach_config[ 'pidSelect' ] ) ) - if 'delay' in attach_config: - utils.UserMessage( f"Waiting ( { attach_config[ 'delay' ] } )..." ) - vim.command( f'sleep { attach_config[ "delay" ] }' ) def _PrepareLaunch( self, command_line, adapter_config, launch_config ): @@ -1070,11 +909,6 @@ class DebugSession( object ): self._codeView._window, self._remote_term ) - if 'delay' in run_config: - utils.UserMessage( f"Waiting ( {run_config[ 'delay' ]} )..." ) - vim.command( f'sleep { run_config[ "delay" ] }' ) - - def _GetSSHCommand( self, remote ): ssh = [ 'ssh' ] + remote.get( 'ssh', {} ).get( 'args', [] ) @@ -1148,7 +982,6 @@ class DebugSession( object ): def handle_initialize_response( msg ): self._server_capabilities = msg.get( 'body' ) or {} self._breakpoints.SetServerCapabilities( self._server_capabilities ) - self._variablesView.SetServerCapabilities( self._server_capabilities ) self._Launch() self._connection.DoRequest( handle_initialize_response, { @@ -1174,44 +1007,40 @@ class DebugSession( object ): message ) self._outputView.Print( 'server', msg ) - - def _Prepare( self ): - self._on_init_complete_handlers = [] - + def _Launch( self ): self._logger.debug( "LAUNCH!" ) - self._launch_config = {} - self._launch_config.update( self._adapter.get( 'configuration', {} ) ) - self._launch_config.update( self._configuration[ 'configuration' ] ) + adapter_config = self._adapter + launch_config = {} + launch_config.update( self._adapter.get( 'configuration', {} ) ) + launch_config.update( self._configuration[ 'configuration' ] ) request = self._configuration.get( 'remote-request', - self._launch_config.get( 'request', 'launch' ) ) + launch_config.get( 'request', 'launch' ) ) if request == "attach": self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, - "Attaching to debuggee..." ) + "Attaching to debugee..." ) - self._PrepareAttach( self._adapter, self._launch_config ) + self._PrepareAttach( adapter_config, launch_config ) elif request == "launch": self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, - "Launching debuggee..." ) + "Launching debugee..." ) # FIXME: This cmdLine hack is not fun. self._PrepareLaunch( self._configuration.get( 'remote-cmdLine', [] ), - self._adapter, - self._launch_config ) + adapter_config, + launch_config ) # FIXME: name is mandatory. Forcefully add it (we should really use the # _actual_ name, but that isn't actually remembered at this point) - if 'name' not in self._launch_config: - self._launch_config[ 'name' ] = 'test' + if 'name' not in launch_config: + launch_config[ 'name' ] = 'test' - - def _Launch( self ): def failure_handler( reason, msg ): text = [ 'Launch Failed', @@ -1224,11 +1053,12 @@ class DebugSession( object ): self._splash_screen, text ) + self._connection.DoRequest( lambda msg: self._OnLaunchComplete(), { - 'command': self._launch_config[ 'request' ], - 'arguments': self._launch_config + 'command': launch_config[ 'request' ], + 'arguments': launch_config }, failure_handler ) @@ -1270,37 +1100,6 @@ 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 @@ -1363,25 +1162,13 @@ class DebugSession( object ): self._connection.DoResponse( message, None, response ) - def OnEvent_terminated( self, message ): - # The debugging _session_ has terminated. This does not mean that the - # debuggee has terminated (that's the exited event). - # - # We will handle this when the server actually exists. - # - # FIXME we should always wait for this event before disconnecting closing - # any socket connection + def OnEvent_exited( self, message ): + utils.UserMessage( 'The debugee exited with status code: {}'.format( + message[ 'body' ][ 'exitCode' ] ) ) self.SetCurrentFrame( None ) - - def OnEvent_exited( self, message ): - utils.UserMessage( 'The debuggee exited with status code: {}'.format( - message[ 'body' ][ 'exitCode' ] ) ) - self._stackTraceView.OnExited( message ) - self._codeView.SetCurrentFrame( None ) - def OnEvent_process( self, message ): - utils.UserMessage( 'The debuggee was started: {}'.format( + utils.UserMessage( 'The debugee was started: {}'.format( message[ 'body' ][ 'name' ] ) ) def OnEvent_module( self, message ): @@ -1421,6 +1208,11 @@ class DebugSession( object ): else: self._logger.debug( "No server exit handler" ) + def OnEvent_terminated( self, message ): + # We will handle this when the server actually exists + utils.UserMessage( "Debugging was terminated by the server." ) + self.SetCurrentFrame( None ) + def OnEvent_output( self, message ): if self._outputView: self._outputView.OnOutput( message[ 'body' ] ) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 02eb0e7..13fa28a 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -14,462 +14,28 @@ # limitations under the License. -from vimspector import installer -import sys -import os +import pkgutil +import importlib +import vimspector.plugins + +LOADED = 0 +GADGETS = {} -GADGETS = { - 'vscode-cpptools': { - 'language': [ 'c', 'cpp', 'rust' ], - 'download': { - 'url': 'https://github.com/Microsoft/vscode-cpptools/releases/download/' - '${version}/${file_name}', - }, - 'do': lambda name, root, gadget: installer.InstallCppTools( name, - root, - gadget ), - 'all': { - 'version': '1.6.0', - "adapters": { - "vscode-cpptools": { - "name": "cppdbg", - "command": [ - "${gadgetDir}/vscode-cpptools/debugAdapters/bin/OpenDebugAD7" - ], - "attach": { - "pidProperty": "processId", - "pidSelect": "ask" - }, - "configuration": { - "type": "cppdbg", - "args": [], - "cwd": "${workspaceRoot}", - "environment": [], - } - }, - }, - }, - 'linux': { - 'file_name': 'cpptools-linux.vsix', - 'checksum': - 'c25299bcfb46b22d41aa3f125df7184e6282a35ff9fb69c47def744cb4778f55', - }, - 'macos': { - 'file_name': 'cpptools-osx-arm64.vsix', - 'checksum': - 'ceb3e8cdaa2b5bb45af50913ddd8402089969748af8d70f5d46480408287ba6f', - }, - 'windows': { - 'file_name': 'cpptools-win32.vsix', - 'checksum': - 'ef7ac5831874a3c7dbf0feb826bfda2be579aff9b6d990622fff1d0d4ede00d1', - "adapters": { - "vscode-cpptools": { - "name": "cppdbg", - "command": [ - "${gadgetDir}/vscode-cpptools/debugAdapters/bin/OpenDebugAD7.exe" - ], - "attach": { - "pidProperty": "processId", - "pidSelect": "ask" - }, - "configuration": { - "type": "cppdbg", - "args": [], - "cwd": "${workspaceRoot}", - "environment": [], - "MIMode": "gdb", - "MIDebuggerPath": "gdb.exe" - } - }, - }, - }, - }, - 'debugpy': { - 'language': 'python', - 'download': { - 'url': 'https://github.com/microsoft/debugpy/archive/${file_name}' - }, - 'all': { - 'version': '1.2.1', - 'file_name': 'v1.2.1.zip', - 'checksum': - '29a6c5d1053d2b6f3b1a63e1a8ecff93f951d3cc0b7548431592e9e3007239e6' - }, - 'do': lambda name, root, gadget: installer.InstallDebugpy( name, - root, - gadget ), - 'adapters': { - 'debugpy': { - "command": [ - sys.executable, # TODO: Will this work from within Vim ? - "${gadgetDir}/debugpy/build/lib/debugpy/adapter" - ], - "name": "debugpy", - "configuration": { - "python": sys.executable, # TODO: Will this work from within Vim ? - # Don't debug into subprocesses, as this leads to problems (vimspector - # doesn't support the custom messages) - # https://github.com/puremourning/vimspector/issues/141 - "subProcess": False, - } - } - }, - }, - 'vscode-java-debug': { - 'language': 'java', - 'enabled': False, - 'download': { - 'url': 'https://github.com/microsoft/vscode-java-debug/releases/download/' - '${version}/${file_name}', - }, - 'all': { - 'version': '0.26.0', - 'file_name': 'vscjava.vscode-java-debug-0.26.0.vsix', - 'checksum': - 'de49116ff3a3c941dad0c36d9af59baa62cd931e808a2ab392056cbb235ad5ef', - }, - 'adapters': { - "vscode-java": { - "name": "vscode-java", - "port": "${DAPPort}", - "configuration": { - "cwd": "${workspaceRoot}" - }, - 'custom_handler': 'vimspector.custom.java.JavaDebugAdapter' - } - }, - }, - 'java-language-server': { - 'language': 'javac', - 'enabled': False, - 'download': { - 'url': 'https://marketplace.visualstudio.com/_apis/public/gallery/' - 'publishers/georgewfraser/vsextensions/vscode-javac/${version}/' - 'vspackage', - 'target': 'georgewfraser.vscode-javac-0.2.31.vsix.gz', - 'format': 'zip.gz', - }, - 'all': { - 'version': '0.2.31', - 'file_name': 'georgewfraser.vscode-javac-0.2.31.vsix.gz', - 'checksum': - '5b0248ec1198d3ece9a9c6b9433b30c22e308f0ae6e4c7bd09cd943c454e3e1d', - }, - 'adapters': { - "vscode-javac": { - "name": "vscode-javac", - "type": "vscode-javac", - "command": [ - "${gadgetDir}/java-language-server/dist/debug_adapter_mac.sh" - ], - "attach": { - "pidSelect": "none" - } - } - }, - }, - 'tclpro': { - 'language': 'tcl', - 'repo': { - 'url': 'https://github.com/puremourning/TclProDebug', - 'ref': 'v1.0.0' - }, - 'do': lambda name, root, gadget: installer.InstallTclProDebug( name, - root, - gadget ), - 'adapters': { - "tclpro": { - "name": "tclpro", - "type": "tclpro", - "command": [ - "${gadgetDir}/tclpro/bin/debugadapter" - ], - "attach": { - "pidSelect": "none" - }, - "configuration": { - "target": "${file}", - "args": [ "*${args}" ], - "tclsh": "tclsh", - "cwd": "${workspaceRoot}", - "extensionDirs": [ - "${workspaceRoot}/.tclpro/extensions", - "${HOME}/.tclpro/extensions", - ] - } - } - }, - }, - 'netcoredbg': { - 'language': [ 'csharp', 'fsharp', 'vbnet' ], - 'enabled': False, - 'download': { - 'url': ( 'https://github.com/Samsung/netcoredbg/releases/download/' - '${version}/${file_name}' ), - 'format': 'tar', - }, - 'all': { - 'version': '1.2.0-782' - }, - 'macos': { - 'file_name': 'netcoredbg-osx.tar.gz', - 'checksum': - '', - }, - 'linux': { - 'file_name': 'netcoredbg-linux-bionic-amd64.tar.gz', - 'checksum': '', - }, - 'windows': { - 'file_name': 'netcoredbg-win64.zip', - 'checksum': '', - }, - 'do': lambda name, root, gadget: installer.MakeSymlink( - name, - os.path.join( root, 'netcoredbg' ) ), - 'adapters': { - 'netcoredbg': { - "name": "netcoredbg", - "command": [ - "${gadgetDir}/netcoredbg/netcoredbg", - "--interpreter=vscode" - ], - "attach": { - "pidProperty": "processId", - "pidSelect": "ask" - }, - "configuration": { - "cwd": "${workspaceRoot}" - } - }, - } - }, - 'vscode-bash-debug': { - 'language': 'bash', - 'download': { - 'url': 'https://github.com/rogalmic/vscode-bash-debug/releases/' - 'download/${version}/${file_name}', - }, - 'all': { - 'file_name': 'bash-debug-0.3.7.vsix', - 'version': 'v0.3.7', - 'checksum': - '7b73e5b4604375df8658fb5a72c645c355785a289aa785a986e508342c014bb4', - }, - 'do': lambda name, root, gadget: installer.InstallBashDebug( name, - root, - gadget ), - 'adapters': { - "vscode-bash": { - "name": "bashdb", - "command": [ - "node", - "${gadgetDir}/vscode-bash-debug/out/bashDebug.js" - ], - "variables": { - "BASHDB_HOME": "${gadgetDir}/vscode-bash-debug/bashdb_dir" - }, - "configuration": { - "request": "launch", - "type": "bashdb", - "program": "${file}", - "args": [], - "env": {}, - "pathBash": "bash", - "pathBashdb": "${BASHDB_HOME}/bashdb", - "pathBashdbLib": "${BASHDB_HOME}", - "pathCat": "cat", - "pathMkfifo": "mkfifo", - "pathPkill": "pkill", - "cwd": "${workspaceRoot}", - "terminalKind": "integrated", - } - } - } - }, - 'vscode-go': { - 'language': 'go', - 'download': { - 'url': 'https://github.com/golang/vscode-go/releases/download/' - 'v${version}/${file_name}' - }, - 'all': { - 'version': '0.19.1', - 'file_name': 'go-0.19.1.vsix', - 'checksum': - '7f9dc014245b030d9f562b28f3ea9b1fd6e2708fac996c53ff6a707f8204ec64', - }, - 'adapters': { - 'vscode-go': { - 'name': 'delve', - 'command': [ - 'node', - '${gadgetDir}/vscode-go/dist/debugAdapter.js' - ], - "configuration": { - "cwd": "${workspaceRoot}", - } - }, - }, - }, - 'vscode-php-debug': { - 'language': 'php', - 'enabled': False, - 'download': { - 'url': - 'https://github.com/xdebug/vscode-php-debug/releases/download/' - '${version}/${file_name}', - }, - 'all': { - 'version': 'v1.17.0', - 'file_name': 'php-debug-1.17.0.vsix', - 'checksum': - 'd0fff272503414b6696cc737bc2e18e060fdd5e5dc4bcaf38ae7373afd8d8bc9', - }, - 'adapters': { - 'vscode-php-debug': { - 'name': "php-debug", - 'command': [ - 'node', - "${gadgetDir}/vscode-php-debug/out/phpDebug.js", - ] - } - } - }, - 'vscode-node-debug2': { - 'language': 'node', - 'enabled': False, - 'repo': { - 'url': 'https://github.com/microsoft/vscode-node-debug2', - 'ref': 'v1.42.5' - }, - 'do': lambda name, root, gadget: installer.InstallNodeDebug( name, - root, - gadget ), - 'adapters': { - 'vscode-node': { - 'name': 'node2', - 'type': 'node2', - 'command': [ - 'node', - '${gadgetDir}/vscode-node-debug2/out/src/nodeDebug.js' - ] - }, - }, - }, - 'debugger-for-chrome': { - 'language': 'chrome', - 'enabled': False, - 'download': { - 'url': 'https://marketplace.visualstudio.com/_apis/public/gallery/' - 'publishers/msjsdiag/vsextensions/' - 'debugger-for-chrome/${version}/vspackage', - 'target': 'msjsdiag.debugger-for-chrome-4.12.10.vsix.gz', - 'format': 'zip.gz', - }, - 'all': { - 'version': '4.12.10', - 'file_name': 'msjsdiag.debugger-for-chrome-4.12.10.vsix', - 'checksum': - '' - }, - 'adapters': { - 'chrome': { - 'name': 'debugger-for-chrome', - 'type': 'chrome', - 'command': [ - 'node', - '${gadgetDir}/debugger-for-chrome/out/src/chromeDebug.js' - ], - }, - }, - }, - 'CodeLLDB': { - 'language': 'rust', - 'enabled': True, - 'download': { - 'url': 'https://github.com/vadimcn/vscode-lldb/releases/download/' - '${version}/${file_name}', - }, - 'all': { - 'version': 'v1.6.6', - }, - 'macos': { - 'file_name': 'codelldb-aarch64-darwin.vsix', - 'checksum': - '5adc3b9139eabdafd825bd5efc55df4424a203fb2b6087b425cd434956e7ec58', - 'make_executable': [ - 'adapter/codelldb', - 'lldb/bin/debugserver', - 'lldb/bin/lldb', - 'lldb/bin/lldb-argdumper', - ], - }, - 'linux': { - 'file_name': 'codelldb-x86_64-linux.vsix', - 'checksum': - 'eda2cd9b3089dcc0524c273e91ffb5875fe08c930bf643739a2cd1846e1f98d6', - 'make_executable': [ - 'adapter/codelldb', - 'lldb/bin/lldb', - 'lldb/bin/lldb-server', - 'lldb/bin/lldb-argdumper', - ], - }, - 'windows': { - 'file_name': 'codelldb-x86_64-windows.vsix', - 'checksum': - '8ddebe8381a3d22dc3d95139c3797fda06b5cc34aadf300e13b1c516b9da95fe', - 'make_executable': [] - }, - 'adapters': { - 'CodeLLDB': { - 'name': 'CodeLLDB', - 'type': 'CodeLLDB', - "command": [ - "${gadgetDir}/CodeLLDB/adapter/codelldb", - "--port", "${unusedLocalPort}" - ], - "port": "${unusedLocalPort}", - "configuration": { - "type": "lldb", - "name": "lldb", - "cargo": {}, - "args": [], - "cwd": "${workspaceRoot}", - "env": {}, - "terminal": "integrated", - } - }, - }, - }, - 'local-lua-debugger-vscode': { - 'language': 'lua', - 'enabled': True, - 'repo': { - 'url': 'https://github.com/tomblind/local-lua-debugger-vscode.git', - 'ref': 'release-${version}' - }, - 'all': { - 'version': '0.2.0', - }, - 'do': lambda name, root, gadget: installer.InstallLuaLocal( name, - root, - gadget ), - 'adapters': { - 'lua-local': { - 'command': [ - 'node', - '${gadgetDir}/local-lua-debugger-vscode/extension/debugAdapter.js' - ], - 'name': 'lua-local', - 'configuration': { - 'interpreter': 'lua', - 'extensionPath': '${gadgetDir}/local-lua-debugger-vscode' - } - } - }, - }, -} +def RegisterGadget( name, spec ): + GADGETS[ name ] = spec + + +def Gadgets(): + global LOADED + if not LOADED: + mod = vimspector.plugins + # vimspector.plugins is a namespace package + # Following: + # https://packaging.python.org/guides/creating-and-discovering-plugins/#using-namespace-packages + for finder, name, ispkg in pkgutil.iter_modules( mod.__path__, + mod.__name__ + '.' ): + importlib.import_module( name ) + LOADED = 1 + + return GADGETS diff --git a/python3/vimspector/installer.py b/python3/vimspector/installer.py index a81db8f..e586d23 100644 --- a/python3/vimspector/installer.py +++ b/python3/vimspector/installer.py @@ -225,25 +225,21 @@ def GadgetListToInstallerArgs( *gadget_list ): continue try: - gadget = gadgets.GADGETS[ name ] + gadget = gadgets.Gadgets()[ name ] except KeyError: continue - lang = gadget[ "language" ] - if isinstance( lang, list ): - lang = lang[ 0 ] - if not gadget.get( 'enabled', True ): - installer_args.append( f'--force-enable-{lang}' ) + installer_args.append( f'--force-enable-{ gadget[ "language" ] }' ) else: - installer_args.append( f'--enable-{lang}' ) + installer_args.append( f'--enable-{ gadget[ "language" ] }' ) return installer_args def FindGadgetForAdapter( adapter_name ): candidates = [] - for name, gadget in gadgets.GADGETS.items(): + for name, gadget in gadgets.Gadgets().items(): v = {} v.update( gadget.get( 'all', {} ) ) v.update( gadget.get( install.GetOS(), {} ) ) @@ -344,99 +340,13 @@ def WriteAdapters( all_adapters, to_file=None ): def InstallGeneric( name, root, gadget ): - extension_path = gadget.get( 'extension_path', 'extension' ) - extension = os.path.join( root, extension_path ) + extension = os.path.join( root, 'extension' ) for f in gadget.get( 'make_executable', [] ): MakeExecutable( os.path.join( extension, f ) ) - MakeExtensionSymlink( name, root, extension_path ) - - -def InstallCppTools( name, root, gadget ): - extension = os.path.join( root, 'extension' ) - - # 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', 'bin', 'OpenDebugAD7' ) ) - with open( os.path.join( extension, 'package.json' ) ) as f: - package = json.load( f ) - runtime_dependencies = package[ 'runtimeDependencies' ] - for dependency in runtime_dependencies: - for binary in dependency.get( 'binaries' ): - file_path = os.path.abspath( os.path.join( extension, binary ) ) - if os.path.exists( file_path ): - MakeExecutable( os.path.join( extension, binary ) ) - MakeExtensionSymlink( name, root ) -def InstallBashDebug( name, root, gadget ): - MakeExecutable( os.path.join( root, 'extension', 'bashdb_dir', 'bashdb' ) ) - MakeExtensionSymlink( name, root ) - - -def InstallDebugpy( name, root, gadget ): - wd = os.getcwd() - root = os.path.join( root, 'debugpy-{}'.format( gadget[ 'version' ] ) ) - os.chdir( root ) - try: - CheckCall( [ sys.executable, 'setup.py', 'build' ] ) - finally: - os.chdir( wd ) - - MakeSymlink( name, root ) - - -def InstallTclProDebug( name, root, gadget ): - configure = [ 'sh', './configure' ] - - if install.GetOS() == 'macos': - # Apple removed the headers from system frameworks because they are - # determined to make life difficult. And the TCL configure scripts are super - # old so don't know about this. So we do their job for them and try and find - # a tclConfig.sh. - # - # NOTE however that in Apple's infinite wisdom, installing the "headers" in - # the other location is actually broken because the paths in the - # tclConfig.sh are pointing at the _old_ location. You actually do have to - # run the package installation which puts the headers back in order to work. - # This is why the below list is does not contain stuff from - # /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform - # '/Applications/Xcode.app/Contents/Developer/Platforms' - # '/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System' - # '/Library/Frameworks/Tcl.framework', - # '/Applications/Xcode.app/Contents/Developer/Platforms' - # '/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System' - # '/Library/Frameworks/Tcl.framework/Versions' - # '/Current', - for p in [ '/usr/local/opt/tcl-tk/lib' ]: - if os.path.exists( os.path.join( p, 'tclConfig.sh' ) ): - configure.append( '--with-tcl=' + p ) - break - - - with CurrentWorkingDir( os.path.join( root, 'lib', 'tclparser' ) ): - CheckCall( configure ) - CheckCall( [ 'make' ] ) - - MakeSymlink( name, root ) - - -def InstallNodeDebug( name, root, gadget ): - with CurrentWorkingDir( root ): - CheckCall( [ 'npm', 'install' ] ) - CheckCall( [ 'npm', 'run', 'build' ] ) - MakeSymlink( name, root ) - - -def InstallLuaLocal( name, root, gadget ): - with CurrentWorkingDir( root ): - CheckCall( [ 'npm', 'install' ] ) - CheckCall( [ 'npm', 'run', 'build' ] ) - MakeSymlink( name, root ) - def InstallGagdet( name: str, gadget: dict, @@ -705,8 +615,8 @@ def ExtractZipTo( file_path, destination, format ): CheckCall( [ 'tar', 'zxvf', file_path ] ) -def MakeExtensionSymlink( name, root, extension_path = 'extension' ): - MakeSymlink( name, os.path.join( root, extension_path ) ), +def MakeExtensionSymlink( name, root ): + MakeSymlink( name, os.path.join( root, 'extension' ) ), def MakeSymlink( link, pointing_to, in_folder = None ): diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index 3f0da1e..cf2a213 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -32,9 +32,8 @@ class TabBuffer( object ): BUFFER_MAP = { 'console': 'Console', 'stdout': 'Console', - 'output': 'Console', 'stderr': 'stderr', - 'telemetry': None, + 'telemetry': 'Telemetry', } @@ -65,11 +64,8 @@ class OutputView( object ): self._api_prefix = api_prefix VIEWS.add( self ) - def Print( self, category, text: typing.Union[ str, list ] ): - if not isinstance( text, list ): - text = text.splitlines() - - self._Print( category, text ) + def Print( self, categroy, text ): + self._Print( 'server', text.splitlines() ) def OnOutput( self, event ): category = CategoryToBuffer( event.get( 'category' ) or 'output' ) @@ -81,10 +77,6 @@ class OutputView( object ): self._Print( category, text_lines ) def _Print( self, category, text_lines ): - if category is None: - # This category is supressed - return - if category not in self._buffers: self._CreateBuffer( category ) @@ -108,26 +100,13 @@ class OutputView( object ): def Clear( self ): for category, tab_buffer in self._buffers.items(): - self._CleanUpBuffer( category, tab_buffer ) + if tab_buffer.is_job: + utils.CleanUpCommand( category, self._api_prefix ) + utils.CleanUpHiddenBuffer( tab_buffer.buf ) # 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 @@ -251,7 +230,7 @@ class OutputView( object ): raise vim.command( - "nnoremenu 1.{0} WinBar.{1}{2} " + "nnoremenu 1.{0} WinBar.{1}{2} " ":call vimspector#ShowOutputInWindow( {3}, '{1}' )".format( tab_buffer.index, utils.Escape( category ), @@ -272,8 +251,7 @@ class DAPOutputView( OutputView ): self._connection = None for b in set( BUFFER_MAP.values() ): - if b is not None: - self._CreateBuffer( b ) + self._CreateBuffer( b ) self.AddLogFileView() self._ShowOutput( 'Console' ) diff --git a/python3/vimspector/__init__.py b/python3/vimspector/plugins/__init__.py similarity index 100% rename from python3/vimspector/__init__.py rename to python3/vimspector/plugins/__init__.py diff --git a/python3/vimspector/plugins/bash.py b/python3/vimspector/plugins/bash.py new file mode 100644 index 0000000..c197daf --- /dev/null +++ b/python3/vimspector/plugins/bash.py @@ -0,0 +1,70 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +import os +from vimspector import gadgets, installer + + +# FIXME: InstallGeneric would work here +def InstallBashDebug( name, root, gadget ): + installer.MakeExecutable( os.path.join( root, + 'extension', + 'bashdb_dir', + 'bashdb' ) ) + installer.MakeExtensionSymlink( name, root ) + + +gadgets.RegisterGadget( 'vscode-bash-debug', { + 'language': 'bash', + 'download': { + 'url': 'https://github.com/rogalmic/vscode-bash-debug/releases/' + 'download/${version}/${file_name}', + }, + 'all': { + 'file_name': 'bash-debug-0.3.7.vsix', + 'version': 'v0.3.7', + 'checksum': + '7b73e5b4604375df8658fb5a72c645c355785a289aa785a986e508342c014bb4', + }, + 'do': lambda name, root, gadget: InstallBashDebug( name, root, gadget ), + 'adapters': { + "vscode-bash": { + "name": "bashdb", + "command": [ + "node", + "${gadgetDir}/vscode-bash-debug/out/bashDebug.js" + ], + "variables": { + "BASHDB_HOME": "${gadgetDir}/vscode-bash-debug/bashdb_dir" + }, + "configuration": { + "request": "launch", + "type": "bashdb", + "program": "${file}", + "args": [], + "env": {}, + "pathBash": "bash", + "pathBashdb": "${BASHDB_HOME}/bashdb", + "pathBashdbLib": "${BASHDB_HOME}", + "pathCat": "cat", + "pathMkfifo": "mkfifo", + "pathPkill": "pkill", + "cwd": "${workspaceRoot}", + "terminalKind": "integrated", + } + } + } +} ) diff --git a/python3/vimspector/plugins/chrome.py b/python3/vimspector/plugins/chrome.py new file mode 100644 index 0000000..2af57e2 --- /dev/null +++ b/python3/vimspector/plugins/chrome.py @@ -0,0 +1,46 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +from vimspector import gadgets + + +gadgets.RegisterGadget( 'debugger-for-chrome', { + 'language': 'chrome', + 'enabled': False, + 'download': { + 'url': 'https://marketplace.visualstudio.com/_apis/public/gallery/' + 'publishers/msjsdiag/vsextensions/' + 'debugger-for-chrome/${version}/vspackage', + 'target': 'msjsdiag.debugger-for-chrome-4.12.10.vsix.gz', + 'format': 'zip.gz', + }, + 'all': { + 'version': '4.12.10', + 'file_name': 'msjsdiag.debugger-for-chrome-4.12.10.vsix', + 'checksum': + '' + }, + 'adapters': { + 'chrome': { + 'name': 'debugger-for-chrome', + 'type': 'chrome', + 'command': [ + 'node', + '${gadgetDir}/debugger-for-chrome/out/src/chromeDebug.js' + ], + }, + }, +} ) diff --git a/python3/vimspector/plugins/cpp.py b/python3/vimspector/plugins/cpp.py new file mode 100644 index 0000000..8115739 --- /dev/null +++ b/python3/vimspector/plugins/cpp.py @@ -0,0 +1,167 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +import json +import os +from vimspector import gadgets, installer + + +def InstallCppTools( name, root, gadget ): + extension = os.path.join( root, 'extension' ) + + # 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. + installer.MakeExecutable( os.path.join( extension, + 'debugAdapters', + 'OpenDebugAD7' ) ) + with open( os.path.join( extension, 'package.json' ) ) as f: + package = json.load( f ) + runtime_dependencies = package[ 'runtimeDependencies' ] + for dependency in runtime_dependencies: + for binary in dependency.get( 'binaries' ): + file_path = os.path.abspath( os.path.join( extension, binary ) ) + if os.path.exists( file_path ): + installer.MakeExecutable( os.path.join( extension, binary ) ) + + installer.MakeExtensionSymlink( name, root ) + + +gadgets.RegisterGadget( 'vscode-cpptools', { + 'language': 'c', + 'download': { + 'url': 'https://github.com/Microsoft/vscode-cpptools/releases/download/' + '${version}/${file_name}', + }, + 'do': lambda name, root, gadget: InstallCppTools( name, root, gadget ), + 'all': { + 'version': '0.27.0', + "adapters": { + "vscode-cpptools": { + "name": "cppdbg", + "command": [ + "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7" + ], + "attach": { + "pidProperty": "processId", + "pidSelect": "ask" + }, + "configuration": { + "type": "cppdbg", + "args": [], + "cwd": "${workspaceRoot}", + "environment": [], + } + }, + }, + }, + 'linux': { + 'file_name': 'cpptools-linux.vsix', + 'checksum': + '3695202e1e75a03de18049323b66d868165123f26151f8c974a480eaf0205435', + }, + 'macos': { + 'file_name': 'cpptools-osx.vsix', + 'checksum': + 'cb061e3acd7559a539e5586f8d3f535101c4ec4e8a48195856d1d39380b5cf3c', + }, + 'windows': { + 'file_name': 'cpptools-win32.vsix', + 'checksum': + 'aa294368ed16d48c59e49c8000e146eae5a19ad07b654efed5db8ec93b24229e', + "adapters": { + "vscode-cpptools": { + "name": "cppdbg", + "command": [ + "${gadgetDir}/vscode-cpptools/debugAdapters/bin/OpenDebugAD7.exe" + ], + "attach": { + "pidProperty": "processId", + "pidSelect": "ask" + }, + "configuration": { + "type": "cppdbg", + "args": [], + "cwd": "${workspaceRoot}", + "environment": [], + "MIMode": "gdb", + "MIDebuggerPath": "gdb.exe" + } + }, + }, + }, +} ) + + +gadgets.RegisterGadget( 'CodeLLDB', { + 'language': 'rust', + 'enabled': True, + 'download': { + 'url': 'https://github.com/vadimcn/vscode-lldb/releases/download/' + '${version}/${file_name}', + }, + 'all': { + 'version': 'v1.5.3', + }, + 'macos': { + 'file_name': 'codelldb-x86_64-darwin.vsix', + 'checksum': + '7505bc1cdfcfd1cb981e2996aec62d63577440709bac31dcadb41a3b4b44631a', + 'make_executable': [ + 'adapter/codelldb', + 'lldb/bin/debugserver', + 'lldb/bin/lldb', + 'lldb/bin/lldb-argdumper', + ], + }, + 'linux': { + 'file_name': 'codelldb-x86_64-linux.vsix', + 'checksum': + 'ce7efc3e94d775368e5942a02bf5c326b6809a0b4c389f79ffa6a8f6f6b72139', + 'make_executable': [ + 'adapter/codelldb', + 'lldb/bin/lldb', + 'lldb/bin/lldb-server', + 'lldb/bin/lldb-argdumper', + ], + }, + 'windows': { + 'file_name': 'codelldb-x86_64-windows.vsix', + 'checksum': + '', + 'make_executable': [] + }, + 'adapters': { + 'CodeLLDB': { + 'name': 'CodeLLDB', + 'type': 'CodeLLDB', + "command": [ + "${gadgetDir}/CodeLLDB/adapter/codelldb", + "--port", "${unusedLocalPort}" + ], + "port": "${unusedLocalPort}", + "configuration": { + "type": "lldb", + "name": "lldb", + "cargo": {}, + "args": [], + "cwd": "${workspaceRoot}", + "env": {}, + "terminal": "integrated", + } + }, + }, +} ) diff --git a/python3/vimspector/plugins/dotnet.py b/python3/vimspector/plugins/dotnet.py new file mode 100644 index 0000000..6d92d6f --- /dev/null +++ b/python3/vimspector/plugins/dotnet.py @@ -0,0 +1,64 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +import os +from vimspector import gadgets, installer + + +gadgets.RegisterGadget( 'netcoredbg', { + 'language': 'csharp', + 'enabled': False, + 'download': { + 'url': ( 'https://github.com/Samsung/netcoredbg/releases/download/' + '${version}/${file_name}' ), + 'format': 'tar', + }, + 'all': { + 'version': '1.2.0-635' + }, + 'macos': { + 'file_name': 'netcoredbg-osx.tar.gz', + 'checksum': + '71c773e34d358950f25119bade7e3081c4c2f9d71847bd49027ca5792e918beb', + }, + 'linux': { + 'file_name': 'netcoredbg-linux-bionic.tar.gz', + 'checksum': '', + }, + 'windows': { + 'file_name': 'netcoredbg-win64.zip', + 'checksum': '', + }, + 'do': lambda name, root, gadget: installer.MakeSymlink( + name, + os.path.join( root, 'netcoredbg' ) ), + 'adapters': { + 'netcoredbg': { + "name": "netcoredbg", + "command": [ + "${gadgetDir}/netcoredbg/netcoredbg", + "--interpreter=vscode" + ], + "attach": { + "pidProperty": "processId", + "pidSelect": "ask" + }, + "configuration": { + "cwd": "${workspaceRoot}" + } + }, + } +} ) diff --git a/python3/vimspector/plugins/go.py b/python3/vimspector/plugins/go.py new file mode 100644 index 0000000..f723df8 --- /dev/null +++ b/python3/vimspector/plugins/go.py @@ -0,0 +1,44 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +from vimspector import gadgets + + +gadgets.RegisterGadget( 'vscode-go', { + 'language': 'go', + 'download': { + 'url': 'https://github.com/golang/vscode-go/releases/download/' + 'v${version}/${file_name}' + }, + 'all': { + 'version': '0.18.1', + 'file_name': 'Go-0.18.1.vsix', + 'checksum': + '80d4522c6cf482cfa6141997e5b458034f67d7065d92e1ce24a0456c405d6061', + }, + 'adapters': { + 'vscode-go': { + 'name': 'delve', + 'command': [ + 'node', + '${gadgetDir}/vscode-go/dist/debugAdapter.js' + ], + "configuration": { + "cwd": "${workspaceRoot}", + } + }, + }, +} ) diff --git a/python3/vimspector/plugins/java.py b/python3/vimspector/plugins/java.py new file mode 100644 index 0000000..7e778ea --- /dev/null +++ b/python3/vimspector/plugins/java.py @@ -0,0 +1,73 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +from vimspector import gadgets + + +gadgets.RegisterGadget( 'java-language-server', { + 'language': 'javac', + 'enabled': False, + 'download': { + 'url': 'https://marketplace.visualstudio.com/_apis/public/gallery/' + 'publishers/georgewfraser/vsextensions/vscode-javac/${version}/' + 'vspackage', + 'target': 'georgewfraser.vscode-javac-0.2.31.vsix.gz', + 'format': 'zip.gz', + }, + 'all': { + 'version': '0.2.31', + 'file_name': 'georgewfraser.vscode-javac-0.2.31.vsix.gz', + 'checksum': + '5b0248ec1198d3ece9a9c6b9433b30c22e308f0ae6e4c7bd09cd943c454e3e1d', + }, + 'adapters': { + "vscode-javac": { + "name": "vscode-javac", + "type": "vscode-javac", + "command": [ + "${gadgetDir}/java-language-server/dist/debug_adapter_mac.sh" + ], + "attach": { + "pidSelect": "none" + } + } + }, +} ) + + +gadgets.RegisterGadget( 'vscode-java-debug', { + 'language': 'java', + 'enabled': False, + 'download': { + 'url': 'https://github.com/microsoft/vscode-java-debug/releases/download/' + '${version}/${file_name}', + }, + 'all': { + 'version': '0.26.0', + 'file_name': 'vscjava.vscode-java-debug-0.26.0.vsix', + 'checksum': + 'de49116ff3a3c941dad0c36d9af59baa62cd931e808a2ab392056cbb235ad5ef', + }, + 'adapters': { + "vscode-java": { + "name": "vscode-java", + "port": "${DAPPort}", + "configuration": { + "cwd": "${workspaceRoot}" + } + } + }, +} ) diff --git a/python3/vimspector/plugins/lua.py b/python3/vimspector/plugins/lua.py new file mode 100644 index 0000000..e18fef0 --- /dev/null +++ b/python3/vimspector/plugins/lua.py @@ -0,0 +1,51 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +from vimspector import gadgets, installer + + +def InstallLuaLocal( name, root, gadget ): + with installer.CurrentWorkingDir( root ): + installer.CheckCall( [ 'npm', 'install' ] ) + installer.CheckCall( [ 'npm', 'run', 'build' ] ) + installer.MakeSymlink( name, root ) + + +gadgets.RegisterGadget( 'local-lua-debugger-vscode', { + 'language': 'lua', + 'enabled': True, + 'repo': { + 'url': 'https://github.com/tomblind/local-lua-debugger-vscode.git', + 'ref': 'release-${version}' + }, + 'all': { + 'version': '0.2.0', + }, + 'do': lambda name, root, gadget: InstallLuaLocal( name, root, gadget ), + 'adapters': { + 'lua-local': { + 'command': [ + 'node', + '${gadgetDir}/local-lua-debugger-vscode/extension/debugAdapter.js' + ], + 'name': 'lua-local', + 'configuration': { + 'interpreter': 'lua', + 'extensionPath': '${gadgetDir}/local-lua-debugger-vscode' + } + } + }, +} ) diff --git a/python3/vimspector/plugins/mono.py b/python3/vimspector/plugins/mono.py new file mode 100644 index 0000000..cea36d8 --- /dev/null +++ b/python3/vimspector/plugins/mono.py @@ -0,0 +1,54 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +from vimspector import gadgets + + +gadgets.RegisterGadget( '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": {} + } + }, + } +} ) diff --git a/python3/vimspector/plugins/node.py b/python3/vimspector/plugins/node.py new file mode 100644 index 0000000..1feef4a --- /dev/null +++ b/python3/vimspector/plugins/node.py @@ -0,0 +1,45 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +from vimspector import gadgets, installer + + +def InstallNodeDebug( name, root, gadget ): + with installer.CurrentWorkingDir( root ): + installer.CheckCall( [ 'npm', 'install' ] ) + installer.CheckCall( [ 'npm', 'run', 'build' ] ) + installer.MakeSymlink( name, root ) + + +gadgets.RegisterGadget( 'vscode-node-debug2', { + 'language': 'node', + 'enabled': False, + 'repo': { + 'url': 'https://github.com/microsoft/vscode-node-debug2', + 'ref': 'v1.42.5' + }, + 'do': lambda name, root, gadget: InstallNodeDebug( name, root, gadget ), + 'adapters': { + 'vscode-node': { + 'name': 'node2', + 'type': 'node2', + 'command': [ + 'node', + '${gadgetDir}/vscode-node-debug2/out/src/nodeDebug.js' + ] + }, + }, +} ) diff --git a/python3/vimspector/plugins/php.py b/python3/vimspector/plugins/php.py new file mode 100644 index 0000000..11ef484 --- /dev/null +++ b/python3/vimspector/plugins/php.py @@ -0,0 +1,43 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +from vimspector import gadgets + + +gadgets.RegisterGadget( 'vscode-php-debug', { + 'language': 'php', + 'enabled': False, + 'download': { + 'url': + 'https://github.com/felixfbecker/vscode-php-debug/releases/download/' + '${version}/${file_name}', + }, + 'all': { + 'version': 'v1.13.0', + 'file_name': 'php-debug.vsix', + 'checksum': + '8a51e593458fd14623c1c89ebab87347b087d67087717f18bcf77bb788052718', + }, + 'adapters': { + 'vscode-php-debug': { + 'name': "php-debug", + 'command': [ + 'node', + "${gadgetDir}/vscode-php-debug/out/phpDebug.js", + ] + } + } +} ) diff --git a/python3/vimspector/plugins/python.py b/python3/vimspector/plugins/python.py new file mode 100644 index 0000000..d0602e9 --- /dev/null +++ b/python3/vimspector/plugins/python.py @@ -0,0 +1,86 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + +import sys +import os +from vimspector import gadgets, installer + + +def InstallDebugpy( name, root, gadget ): + wd = os.getcwd() + root = os.path.join( root, 'debugpy-{}'.format( gadget[ 'version' ] ) ) + os.chdir( root ) + try: + installer.CheckCall( [ sys.executable, 'setup.py', 'build' ] ) + finally: + os.chdir( wd ) + + installer.MakeSymlink( name, root ) + + +gadgets.RegisterGadget( 'debugpy', { + 'language': 'python', + 'download': { + 'url': 'https://github.com/microsoft/debugpy/archive/${file_name}' + }, + 'all': { + 'version': '1.0.0b12', + 'file_name': 'v1.0.0b12.zip', + 'checksum': + '210632bba2221fbb841c9785a615258819ceec401d1abdbeb5f2326f12cc72a1' + }, + 'do': lambda name, root, gadget: InstallDebugpy( name, root, gadget ), + 'adapters': { + 'debugpy': { + "command": [ + sys.executable, # TODO: Will this work from within Vim ? + "${gadgetDir}/debugpy/build/lib/debugpy/adapter" + ], + "name": "debugpy", + "configuration": { + "python": sys.executable, # TODO: Will this work from within Vim ? + # Don't debug into subprocesses, as this leads to problems (vimspector + # doesn't support the custom messages) + # https://github.com/puremourning/vimspector/issues/141 + "subProcess": False, + } + } + }, +} ) + + +gadgets.RegisterGadget( '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", + ], + } + }, +} ) diff --git a/python3/vimspector/plugins/tcl.py b/python3/vimspector/plugins/tcl.py new file mode 100644 index 0000000..d8df75b --- /dev/null +++ b/python3/vimspector/plugins/tcl.py @@ -0,0 +1,85 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2020 Ben Jackson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + + +import os +from vimspector import gadgets, installer, install + + +def InstallTclProDebug( name, root, gadget ): + configure = [ 'sh', './configure' ] + + if install.GetOS() == 'macos': + # Apple removed the headers from system frameworks because they are + # determined to make life difficult. And the TCL configure scripts are super + # old so don't know about this. So we do their job for them and try and find + # a tclConfig.sh. + # + # NOTE however that in Apple's infinite wisdom, installing the "headers" in + # the other location is actually broken because the paths in the + # tclConfig.sh are pointing at the _old_ location. You actually do have to + # run the package installation which puts the headers back in order to work. + # This is why the below list is does not contain stuff from + # /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform + # '/Applications/Xcode.app/Contents/Developer/Platforms' + # '/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System' + # '/Library/Frameworks/Tcl.framework', + # '/Applications/Xcode.app/Contents/Developer/Platforms' + # '/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System' + # '/Library/Frameworks/Tcl.framework/Versions' + # '/Current', + for p in [ '/usr/local/opt/tcl-tk/lib' ]: + if os.path.exists( os.path.join( p, 'tclConfig.sh' ) ): + configure.append( '--with-tcl=' + p ) + break + + + with installer.CurrentWorkingDir( os.path.join( root, 'lib', 'tclparser' ) ): + installer.CheckCall( configure ) + installer.CheckCall( [ 'make' ] ) + + installer.MakeSymlink( name, root ) + + +gadgets.RegisterGadget( 'tclpro', { + 'language': 'tcl', + 'repo': { + 'url': 'https://github.com/puremourning/TclProDebug', + 'ref': 'v1.0.0' + }, + 'do': lambda name, root, gadget: InstallTclProDebug( name, root, gadget ), + 'adapters': { + "tclpro": { + "name": "tclpro", + "type": "tclpro", + "command": [ + "${gadgetDir}/tclpro/bin/debugadapter" + ], + "attach": { + "pidSelect": "none" + }, + "configuration": { + "target": "${file}", + "args": [ "*${args}" ], + "tclsh": "tclsh", + "cwd": "${workspaceRoot}", + "extensionDirs": [ + "${workspaceRoot}/.tclpro/extensions", + "${HOME}/.tclpro/extensions", + ] + } + } + }, +} ) diff --git a/python3/vimspector/settings.py b/python3/vimspector/settings.py index 89378af..5ff729b 100644 --- a/python3/vimspector/settings.py +++ b/python3/vimspector/settings.py @@ -20,20 +20,11 @@ from vimspector import utils DEFAULTS = { # UI - '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, + 'bottombar_height': 10, + 'sidebar_width': 50, + 'code_minwidth': 82, + 'terminal_maxwidth': 80, + 'terminal_minwidth': 10, # Signs 'sign_priority': { @@ -42,28 +33,11 @@ DEFAULTS = { 'vimspectorBP': 9, 'vimspectorBPCond': 9, 'vimspectorBPDisabled': 9, - 'vimspectorCurrentThread': 200, - 'vimspectorCurrentFrame': 200, + 'vimspectorCurrentThread': 200 }, # Installer 'install_gadgets': [], - - # Mappings - 'mappings': { - 'variables': { - 'expand_collapse': [ '', '<2-LeftMouse>' ], - 'delete': [ '' ], - 'set_value': [ '', '' ] - }, - 'stack_trace': { - 'expand_or_jump': [ '', '<2-LeftMouse>' ], - 'focus_thread': [ '' ], - } - }, - - # Custom - 'java_hotcodereplace_mode': 'ask', } @@ -95,44 +69,9 @@ if hasattr( vim, 'Dictionary' ): DICT_TYPE = vim.Dictionary -def Dict( option ): - return _UpdateDict( DICT_TYPE( DEFAULTS.get( option, {} ) ), - vim.vars.get( f'vimspector_{ option }', DICT_TYPE() ) ) - - -def _UpdateDict( target, override ): - """Apply the updates in |override| to the dict |target|. This is like - dict.update, but recursive. i.e. if the existing element is a dict, then - override elements of the sub-dict rather than wholesale replacing. - e.g. - UpdateDict( - { - 'outer': { 'inner': { 'key': 'oldValue', 'existingKey': True } } - }, - { - 'outer': { 'inner': { 'key': 'newValue' } }, - 'newKey': { 'newDict': True }, - } - ) - yields: - { - 'outer': { - 'inner': { - 'key': 'newValue', - 'existingKey': True - } - }, - 'newKey': { newDict: True } - } - """ - - for key, value in override.items(): - current_value = target.get( key ) - if not isinstance( current_value, DICT_TYPE ): - target[ key ] = value - elif isinstance( value, DICT_TYPE ): - target[ key ] = _UpdateDict( current_value, value ) - else: - target[ key ] = value - - return target +def Dict( option: str ): + d = DICT_TYPE( DEFAULTS.get( option, {} ) ) + d.update( utils.GetVimValue( vim.vars, + f'vimspector_{ option }', + {} ) ) + return d diff --git a/python3/vimspector/stack_trace.py b/python3/vimspector/stack_trace.py index 8b1d848..df650b9 100644 --- a/python3/vimspector/stack_trace.py +++ b/python3/vimspector/stack_trace.py @@ -18,7 +18,7 @@ import os import logging import typing -from vimspector import utils, signs, settings +from vimspector import utils, signs class Thread: @@ -102,33 +102,28 @@ class StackTraceView( object ): self._scratch_buffers = [] # FIXME: This ID is by group, so should be module scope - self._current_thread_sign_id = 0 # 1 when used - self._current_frame_sign_id = 0 # 2 when used + self._next_sign_id = 1 utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' ) utils.SetUpUIWindow( win ) - mappings = settings.Dict( 'mappings' )[ 'stack_trace' ] - with utils.LetCurrentWindow( win ): - for mapping in utils.GetVimList( mappings, 'expand_or_jump' ): - vim.command( f'nnoremap { mapping } ' - ':call vimspector#GoToFrame()' ) - - for mapping in utils.GetVimList( mappings, 'focus_thread' ): - vim.command( f'nnoremap { mapping } ' - ':call vimspector#SetCurrentThread()' ) + vim.command( 'nnoremap ' + ':call vimspector#GoToFrame()' ) + vim.command( 'nnoremap ' + ':call vimspector#SetCurrentThread()' ) + vim.command( 'nnoremap <2-LeftMouse> ' + ':call vimspector#GoToFrame()' ) if utils.UseWinBar(): - vim.command( 'nnoremenu 1.1 WinBar.Pause/Continue ' + vim.command( 'nnoremenu 1.1 WinBar.Pause/Continue ' ':call vimspector#PauseContinueThread()' ) - vim.command( 'nnoremenu 1.2 WinBar.Expand/Collapse ' + vim.command( 'nnoremenu 1.2 WinBar.Expand/Collapse ' ':call vimspector#GoToFrame()' ) - vim.command( 'nnoremenu 1.3 WinBar.Focus ' + vim.command( 'nnoremenu 1.3 WinBar.Focus ' ':call vimspector#SetCurrentThread()' ) win.options[ 'cursorline' ] = False - win.options[ 'signcolumn' ] = 'auto' if not signs.SignDefined( 'vimspectorCurrentThread' ): @@ -138,13 +133,6 @@ 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 = {} @@ -166,12 +154,9 @@ class StackTraceView( object ): self._sources = {} self._requesting_threads = StackTraceView.ThreadRequestState.NO self._pending_thread_request = None - 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 + if self._next_sign_id: + signs.UnplaceSign( self._next_sign_id, 'VimspectorStackTrace' ) + self._next_sign_id = 0 with utils.ModifiableScratchBuffer( self._buf ): utils.ClearBuffer( self._buf ) @@ -203,12 +188,11 @@ class StackTraceView( object ): return def consume_threads( message ): - requesting = False if self._requesting_threads == StackTraceView.ThreadRequestState.PENDING: # We may have hit a thread event, so try again. self._requesting_threads = StackTraceView.ThreadRequestState.NO self.LoadThreads( *self._pending_thread_request ) - requesting = True + return self._requesting_threads = StackTraceView.ThreadRequestState.NO self._pending_thread_request = None @@ -227,6 +211,8 @@ class StackTraceView( object ): stoppedThreadId = stopEvent.get( 'threadId' ) allThreadsStopped = stopEvent.get( 'allThreadsStopped', False ) + requesting = False + # FIXME: This is horribly inefficient for t in message[ 'body' ][ 'threads' ]: thread = None @@ -254,10 +240,7 @@ class StackTraceView( object ): # If this is a stopped event, load the stack trace for the "current" # thread. Don't do this on other thrads requests because some servers # just break when that happens. - # - # Don't do this if we're also satisfying a cached request already (we'll - # do it then) - if infer_current_frame and not requesting: + if infer_current_frame: if thread.id == self._current_thread: if thread.CanExpand(): self._LoadStackTrace( thread, True, reason ) @@ -285,10 +268,10 @@ class StackTraceView( object ): self._line_to_frame.clear() self._line_to_thread.clear() - if self._current_thread_sign_id: - signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' ) + if self._next_sign_id: + signs.UnplaceSign( self._next_sign_id, 'VimspectorStackTrace' ) else: - self._current_thread_sign_id = 1 + self._next_sign_id = 1 with utils.ModifiableScratchBuffer( self._buf ): with utils.RestoreCursorPosition(): @@ -302,7 +285,7 @@ class StackTraceView( object ): f'({thread.State()})' ) if self._current_thread == thread.id: - signs.PlaceSign( self._current_thread_sign_id, + signs.PlaceSign( self._next_sign_id, 'VimspectorStackTrace', 'vimspectorCurrentThread', self._buf.name, @@ -379,61 +362,12 @@ 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: - return True - - return False - - def _JumpToFrame( self, frame, reason = '' ): def do_jump(): if 'line' in frame and frame[ 'line' ] > 0: # 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 @@ -523,19 +457,10 @@ class StackTraceView( object ): self.LoadThreads( infer_current_frame ) - def OnExited( self, event ): - for thread in self._threads: - thread.Exited() - def _DrawStackTrace( self, thread: Thread ): 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' ] @@ -560,14 +485,6 @@ 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 0c84704..6ffd56a 100644 --- a/python3/vimspector/terminal.py +++ b/python3/vimspector/terminal.py @@ -23,53 +23,12 @@ 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 @@ -91,23 +50,13 @@ 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.get( 'curwin', 0 ): - pass - elif term_options[ 'vertical' ]: + if term_options[ 'vertical' ] and not term_options.get( 'curwin', 0 ): 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 5f836fc..5ab9872 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -356,63 +356,20 @@ def SelectFromList( prompt, options ): return None -def AskForInput( prompt, default_value = None, completion = None ): +def AskForInput( prompt, default_value = None ): if default_value is None: - default_value = '' - - args = [ prompt, default_value ] - - if completion is not None: - if completion == 'expr': - args.append( 'custom,vimspector#CompleteExpr' ) - else: - args.append( completion ) + default_option = '' + else: + default_option = ", '{}'".format( Escape( default_value ) ) with InputSave(): try: - return Call( 'input', *args ) + return vim.eval( "input( '{}' {} )".format( Escape( prompt ), + default_option ) ) except ( KeyboardInterrupt, vim.error ): return None -CONFIRM = {} -CONFIRM_ID = 0 - - -def ConfirmCallback( confirm_id, result ): - try: - handler = CONFIRM.pop( confirm_id ) - except KeyError: - UserMessage( f"Internal error: unexpected callback id { confirm_id }", - persist = True, - error = True ) - return - - handler( result ) - - -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, - options, - default_value, - keys ) - - def AppendToBuffer( buf, line_or_lines, modified=False ): line = 1 try: @@ -441,10 +398,8 @@ def AppendToBuffer( buf, line_or_lines, modified=False ): -def ClearBuffer( buf, modified = False ): +def ClearBuffer( buf ): buf[ : ] = None - if not modified: - buf.options[ 'modified' ] = False def SetBufferContents( buf, lines, modified=False ): @@ -505,8 +460,8 @@ VAR_MATCH = re.compile( {(?P # or An {id:default} - default param, as (?P[_a-z][_a-z0-9]*) # an ID : # then a colon - (?P(?:\\}|[^}])*) # then anything up to }, or a \} - )} | # then a } + (?P(?:[^}]|\})*) # then anything up to }, or a \} + )} | # (?P) # or Something else - invalid ) """, @@ -534,6 +489,7 @@ 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( '\\}', '}' ) ) @@ -575,11 +531,8 @@ 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 as e2: - if e2.name in calculus: - default_value = calculus[ e2.name ]() - else: - default_value = e.default_value + except MissingSubstitution: + default_value = e.default_value mapping[ key ] = AskForInput( 'Enter value for {}: '.format( key ), default_value ) @@ -681,19 +634,15 @@ def ParseVariables( variables_list, return new_variables -def DisplayBalloon( is_term, display, is_hover = False ): +def DisplayBaloon( is_term, display ): if not is_term: + display = '\n'.join( display ) # To enable the Windows GUI to display the balloon correctly # Refer https://github.com/vim/vim/issues/1512#issuecomment-492070685 - display = '\n'.join( display ) + vim.eval( "balloon_show( '' )" ) - created_win_id = int( vim.eval( - "vimspector#internal#balloon#CreateTooltip({}, {})".format( - int( is_hover ), json.dumps( display ) - ) - ) ) - - return created_win_id + vim.eval( "balloon_show( {0} )".format( + json.dumps( display ) ) ) def GetBufferFilepath( buf ): @@ -754,7 +703,7 @@ def SetSyntax( current_syntax, syntax, *args ): syntax = '' if current_syntax == syntax: - return syntax + return # We use set syn= because just setting vim.Buffer.options[ 'syntax' ] # doesn't actually trigger the Syntax autocommand, and i'm not sure that @@ -770,28 +719,6 @@ def GetBufferFiletypes( buf ): return ft.split( '.' ) -def GetVisualSelection( bufnr ): - start_line, start_col = vim.current.buffer.mark( "<" ) - end_line, end_col = vim.current.buffer.mark( ">" ) - - - # lines are 1 based, but columns are 0 based - # don't ask me why... - start_line -= 1 - end_line -= 1 - - lines = vim.buffers[ bufnr ][ start_line : end_line + 1 ] - # Do end first, in case it's on the same line as start (as doing start first - # would change the offset) - lines[ -1 ] = lines[ -1 ][ : end_col + 1 ] - lines[ 0 ] = lines[ 0 ][ start_col : ] - - _logger.debug( f'Visual selection: { lines } from ' - f'{ start_line }/{ start_col } -> { end_line }/{ end_col }' ) - - return lines - - def DisplaySplash( api_prefix, splash, text ): if splash: return Call( f'vimspector#internal#{api_prefix}popup#UpdateSplash', diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index 8dcb493..4028722 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -19,7 +19,7 @@ import logging from functools import partial import typing -from vimspector import utils, settings +from vimspector import utils class Expandable: @@ -32,9 +32,8 @@ class Expandable: a 'variablesReference' to be resolved by the 'variables' request. Records the current state expanded/collapsed. Implementations just implement VariablesReference to get the variables.""" - def __init__( self, container: 'Expandable' = None ): + def __init__( self ): self.variables: typing.List[ 'Variable' ] = None - self.container: Expandable = container # None is Falsy and represents collapsed _by default_. WHen set to False, # this means the user explicitly collapsed it. When True, the user expanded # it (or we expanded it by default). @@ -49,9 +48,6 @@ class Expandable: def IsExpandable( self ): return self.VariablesReference() > 0 - def IsContained( self ): - return self.container is not None - @abc.abstractmethod def VariablesReference( self ): assert False @@ -96,8 +92,8 @@ class WatchFailure( WatchResult ): class Variable( Expandable ): """Holds one level of an expanded value tree. Also itself expandable.""" - def __init__( self, container: Expandable, variable: dict ): - super().__init__( container = container ) + def __init__( self, variable: dict ): + super().__init__() self.variable = variable # A new variable appearing is marked as changed self.changed = True @@ -121,48 +117,17 @@ class Watch: self.expression = expression self.result = None - @staticmethod - def New( frame, expression, context ): - watch = { - 'expression': expression, - 'context': context, - } - if frame: - watch[ 'frameId' ] = frame[ 'id' ] - - return Watch( watch ) - class View: lines: typing.Dict[ int, Expandable ] draw: typing.Callable - syntax: str def __init__( self, win, lines, draw ): self.lines = lines self.draw = draw - self.syntax = None - if win is not None: - self.buf = win.buffer - utils.SetUpUIWindow( win ) + self.buf = win.buffer - -class BufView( View ): - def __init__( self, buf, lines, draw ): - super().__init__( None, lines, draw ) - self.buf = buf - - -def AddExpandMappings( mappings = None ): - if mappings is None: - mappings = settings.Dict( 'mappings' )[ 'variables' ] - for mapping in utils.GetVimList( mappings, 'expand_collapse' ): - vim.command( f'nnoremap { mapping } ' - ':call vimspector#ExpandVariable()' ) - - for mapping in utils.GetVimList( mappings, 'set_value' ): - vim.command( f'nnoremap { mapping } ' - ':call vimspector#SetVariableValue()' ) + utils.SetUpUIWindow( win ) class VariablesView( object ): @@ -172,22 +137,19 @@ class VariablesView( object ): self._connection = None self._current_syntax = '' - self._server_capabilities = None - self._variable_eval: Scope = None - self._variable_eval_view: View = None - - mappings = settings.Dict( 'mappings' )[ 'variables' ] + def AddExpandMappings(): + vim.command( 'nnoremap ' + ':call vimspector#ExpandVariable()' ) + vim.command( 'nnoremap <2-LeftMouse> ' + ':call vimspector#ExpandVariable()' ) # Set up the "Variables" buffer in the variables_win self._scopes: typing.List[ Scope ] = [] self._vars = View( variables_win, {}, self._DrawScopes ) utils.SetUpHiddenBuffer( self._vars.buf, 'vimspector.Variables' ) with utils.LetCurrentWindow( variables_win ): - if utils.UseWinBar(): - vim.command( 'nnoremenu 1.1 WinBar.Set ' - ':call vimspector#SetVariableValue()' ) - AddExpandMappings( mappings ) + AddExpandMappings() # Set up the "Watches" buffer in the watches_win (and create a WinBar in # there) @@ -199,20 +161,17 @@ class VariablesView( object ): 'vimspector#AddWatchPrompt', 'vimspector#OmniFuncWatch' ) with utils.LetCurrentWindow( watches_win ): - AddExpandMappings( mappings ) - for mapping in utils.GetVimList( mappings, 'delete' ): - vim.command( - f'nnoremap { mapping } :call vimspector#DeleteWatch()' ) + AddExpandMappings() + vim.command( + 'nnoremap :call vimspector#DeleteWatch()' ) if utils.UseWinBar(): - vim.command( 'nnoremenu 1.1 WinBar.New ' + vim.command( 'nnoremenu 1.1 WinBar.New ' ':call vimspector#AddWatch()' ) - vim.command( 'nnoremenu 1.2 WinBar.Expand/Collapse ' + vim.command( 'nnoremenu 1.2 WinBar.Expand/Collapse ' ':call vimspector#ExpandVariable()' ) - vim.command( 'nnoremenu 1.3 WinBar.Delete ' + vim.command( 'nnoremenu 1.3 WinBar.Delete ' ':call vimspector#DeleteWatch()' ) - vim.command( 'nnoremenu 1.1 WinBar.Set ' - ':call vimspector#SetVariableValue()' ) # Set the (global!) balloon expr if supported has_balloon = int( vim.eval( "has( 'balloon_eval' )" ) ) @@ -224,9 +183,7 @@ class VariablesView( object ): 'balloonexpr': vim.options[ 'balloonexpr' ], 'balloondelay': vim.options[ 'balloondelay' ], } - vim.options[ 'balloonexpr' ] = ( "vimspector#internal#" - "balloon#HoverTooltip()" ) - + vim.options[ 'balloonexpr' ] = 'vimspector#internal#balloon#BalloonExpr()' vim.options[ 'balloondelay' ] = 250 if has_balloon: @@ -244,30 +201,21 @@ class VariablesView( object ): utils.ClearBuffer( self._vars.buf ) with utils.ModifiableScratchBuffer( self._watch.buf ): utils.ClearBuffer( self._watch.buf ) - self.ClearTooltip() self._current_syntax = '' def ConnectionUp( self, connection ): self._connection = connection - def SetServerCapabilities( self, capabilities ): - self._server_capabilities = capabilities - def ConnectionClosed( self ): self.Clear() self._connection = None - self._server_capabilities = None def Reset( self ): - self._server_capabilities = None - for k, v in self._oldoptions.items(): vim.options[ k ] = v utils.CleanUpHiddenBuffer( self._vars.buf ) utils.CleanUpHiddenBuffer( self._watch.buf ) - self.ClearTooltip() - def LoadScopes( self, frame ): def scopes_consumer( message ): @@ -319,97 +267,15 @@ class VariablesView( object ): }, } ) - def _DrawBalloonEval( self ): - watch = self._variable_eval - view = self._variable_eval_view - - with utils.RestoreCursorPosition(): - with utils.ModifiableScratchBuffer( view.buf ): - utils.ClearBuffer( view.buf ) - view.syntax = utils.SetSyntax( view.syntax, - self._current_syntax, - view.buf ) - - self._DrawWatchResult( view, - 0, - watch, - is_short = True ) - - vim.eval( "vimspector#internal#balloon#ResizeTooltip()" ) - - def ClearTooltip( self ): - # This will actually end up calling CleanUpTooltip via the popup close - # callback - vim.eval( 'vimspector#internal#balloon#Close()' ) - - def CleanUpTooltip( self ) : - # remove reference to old tooltip window - self._variable_eval_view = None - vim.vars[ 'vimspector_session_windows' ][ 'eval' ] = None - - def VariableEval( self, frame, expression, is_hover ): - """Callback to display variable under cursor `:h ballonexpr`""" - if not self._connection: - return '' - - def handler( message ): - - watch = self._variable_eval - if watch.result is None: - watch.result = WatchResult( message[ 'body' ] ) - else: - watch.result.Update( message[ 'body' ] ) - - popup_win_id = utils.DisplayBalloon( self._is_term, [], is_hover ) - # record the global eval window id - vim.vars[ 'vimspector_session_windows' ][ 'eval' ] = int( popup_win_id ) - popup_bufnr = int( vim.eval( "winbufnr({})".format( popup_win_id ) ) ) - - # We don't need to do any UI window setup here, as it's already done as - # part of the popup creation, so just pass the buffer to the View instance - self._variable_eval_view = BufView( - vim.buffers[ popup_bufnr ], - {}, - self._DrawBalloonEval - ) - - if watch.result.IsExpandable(): - # Always expand the first level - watch.result.expanded = Expandable.EXPANDED_BY_US - - if watch.result.IsExpanded(): - self._connection.DoRequest( partial( self._ConsumeVariables, - self._variable_eval_view.draw, - watch.result ), { - 'command': 'variables', - 'arguments': { - 'variablesReference': watch.result.VariablesReference(), - }, - } ) - - self._DrawBalloonEval() - - def failure_handler( reason, message ): - display = [ reason ] - float_win_id = utils.DisplayBalloon( self._is_term, display, is_hover ) - # record the global eval window id - vim.vars[ 'vimspector_session_windows' ][ 'eval' ] = int( float_win_id ) - - self._variable_eval = Watch.New( frame, - expression, - 'hover' ) - - # Send async request - self._connection.DoRequest( handler, { - 'command': 'evaluate', - 'arguments': self._variable_eval.expression, - }, failure_handler ) - - # Return working (meanwhile) - return '' - def AddWatch( self, frame, expression ): - self._watches.append( Watch.New( frame, expression, 'watch' ) ) + watch = { + 'expression': expression, + 'context': 'watch', + } + if frame: + watch[ 'frameId' ] = frame[ 'id' ] + + self._watches.append( Watch( watch ) ) self.EvaluateWatches() def DeleteWatch( self ): @@ -472,35 +338,20 @@ class VariablesView( object ): watch.result = WatchFailure( reason ) self._DrawWatches() - def _GetVariable( self, buf = None, line_num = None ): - none = ( None, None ) - - if buf is None: - buf = vim.current.buffer - - if line_num is None: - line_num = vim.current.window.cursor[ 0 ] - - if buf == self._vars.buf: + def ExpandVariable( self ): + if vim.current.buffer == self._vars.buf: view = self._vars - elif buf == self._watch.buf: + elif vim.current.buffer == self._watch.buf: view = self._watch - elif ( self._variable_eval_view is not None - and buf == self._variable_eval_view.buf ): - view = self._variable_eval_view else: - return none - - if line_num not in view.lines: - return none - - return view.lines[ line_num ], view - - def ExpandVariable( self, buf = None, line_num = None ): - variable, view = self._GetVariable( buf, line_num ) - if variable is None: return + current_line = vim.current.window.cursor[ 0 ] + if current_line not in view.lines: + return + + variable = view.lines[ current_line ] + if variable.IsExpanded(): # Collapse variable.expanded = Expandable.COLLAPSED_BY_USER @@ -520,101 +371,25 @@ class VariablesView( object ): }, } ) - def SetVariableValue( self, new_value = None, buf = None, line_num = None ): - variable: Variable - view: View - - if not self._server_capabilities.get( 'supportsSetVariable' ): - return - - variable, view = self._GetVariable( buf, line_num ) - if variable is None: - return - - if not variable.IsContained(): - return - - if new_value is None: - new_value = utils.AskForInput( 'New Value: ', - variable.variable.get( 'value', '' ), - completion = 'expr' ) - - if new_value is None: - return - - - def handler( message ): - # Annoyingly the response to setVariable request doesn't return a - # Variable, but some part of it, so take a copy of the existing Variable - # dict and update it, then call its update method with the updated copy. - new_variable = dict( variable.variable ) - new_variable.update( message[ 'body' ] ) - - # Clear any existing known children (FIXME: Is this the right thing to do) - variable.variables = None - - # If the variable is expanded, re-request its children - if variable.IsExpanded(): - self._connection.DoRequest( partial( self._ConsumeVariables, - view.draw, - variable ), { - 'command': 'variables', - 'arguments': { - 'variablesReference': variable.VariablesReference() - }, - } ) - - variable.Update( new_variable ) - view.draw() - - def failure_handler( reason, message ): - utils.UserMessage( f'Cannot set value: { reason }', error = True ) - - self._connection.DoRequest( handler, { - 'command': 'setVariable', - 'arguments': { - 'variablesReference': variable.container.VariablesReference(), - 'name': variable.variable[ 'name' ], - 'value': new_value - }, - }, failure_handler = failure_handler ) - - - - def _DrawVariables( self, view, variables, indent, is_short = False ): + def _DrawVariables( self, view, variables, indent ): assert indent > 0 for variable in variables: - text = '' - if is_short: - text = '{indent}{icon} {name}: {value}'.format( - # We borrow 1 space of indent to draw the change marker - indent = ' ' * ( indent - 1 ), - icon = '+' if ( variable.IsExpandable() - and not variable.IsExpanded() ) else '-', - name = variable.variable.get( 'name', '' ), - value = variable.variable.get( 'value', '' ) - ) - else: - text = '{indent}{marker}{icon} {name} ({type_}): {value}'.format( + line = utils.AppendToBuffer( + view.buf, + '{indent}{marker}{icon} {name} ({type_}): {value}'.format( # We borrow 1 space of indent to draw the change marker indent = ' ' * ( indent - 1 ), marker = '*' if variable.changed else ' ', icon = '+' if ( variable.IsExpandable() and not variable.IsExpanded() ) else '-', - name = variable.variable.get( 'name', '' ), + name = variable.variable[ 'name' ], type_ = variable.variable.get( 'type', '' ), - value = variable.variable.get( 'value', '' ) - ) - - line = utils.AppendToBuffer( - view.buf, - text.split( '\n' ) - ) - + value = variable.variable.get( 'value', + '' ) ).split( '\n' ) ) view.lines[ line ] = variable if variable.ShouldDrawDrillDown(): - self._DrawVariables( view, variable.variables, indent + 2, is_short ) + self._DrawVariables( view, variable.variables, indent + 2 ) def _DrawScopes( self ): # FIXME: The drawing is dumb and draws from scratch every time. This is @@ -641,7 +416,7 @@ class VariablesView( object ): 'Expression: ' + watch.expression[ 'expression' ] ) watch.line = line - self._DrawWatchResult( self._watch, 2, watch ) + self._DrawWatchResult( 2, watch ) def _DrawScope( self, indent, scope ): icon = '+' if scope.IsExpandable() and not scope.IsExpanded() else '-' @@ -657,36 +432,27 @@ class VariablesView( object ): indent += 2 self._DrawVariables( self._vars, scope.variables, indent ) - def _DrawWatchResult( self, view, indent, watch, is_short = False ): + def _DrawWatchResult( self, indent, watch ): if not watch.result: return - assert is_short or indent > 0 + assert indent > 0 + icon = '+' if ( watch.result.IsExpandable() and + not watch.result.IsExpanded() ) else '-' - if is_short: - # The first result is always expanded in a hover (short format) - icon = '' - marker = '' - leader = '' - else: - icon = '+' if ( watch.result.IsExpandable() and - not watch.result.IsExpanded() ) else '-' - marker = '*' if watch.result.changed else ' ' - leader = ' Result: ' - - line = '{indent}{marker}{icon}{leader}{result}'.format( + line = '{indent}{marker}{icon} Result: {result}'.format( # We borrow 1 space of indent to draw the change marker indent = ' ' * ( indent - 1 ), - marker = marker, + marker = '*' if watch.result.changed else ' ', icon = icon, - leader = leader, result = watch.result.result.get( 'result', '' ) ) - line = utils.AppendToBuffer( view.buf, line.split( '\n' ) ) - view.lines[ line ] = watch.result + line = utils.AppendToBuffer( self._watch.buf, line.split( '\n' ) ) + self._watch.lines[ line ] = watch.result if watch.result.ShouldDrawDrillDown(): - self._DrawVariables( view, watch.result.variables, indent + 2, is_short ) + indent = 4 + self._DrawVariables( self._watch, watch.result.variables, indent ) def _ConsumeVariables( self, draw, parent, message ): new_variables = [] @@ -701,8 +467,9 @@ class VariablesView( object ): variable = v found = True break + if not found: - variable = Variable( parent, variable_body ) + variable = Variable( variable_body ) else: variable.Update( variable_body ) @@ -722,10 +489,47 @@ class VariablesView( object ): draw() + def ShowBalloon( self, frame, expression ): + """Callback to display variable under cursor `:h ballonexpr`""" + if not self._connection: + return '' + + def handler( message ): + # TODO: this result count be expandable, but we have no way to allow the + # user to interact with the balloon to expand it, unless we use a popup + # instead, but even then we don't really want to trap the cursor. + body = message[ 'body' ] + result = body[ 'result' ] + if result is None: + result = 'null' + display = [ + 'Type: ' + body.get( 'type', '' ), + 'Value: ' + result + ] + utils.DisplayBaloon( self._is_term, display ) + + def failure_handler( reason, message ): + display = [ reason ] + utils.DisplayBaloon( self._is_term, display ) + + # Send async request + self._connection.DoRequest( handler, { + 'command': 'evaluate', + 'arguments': { + 'expression': expression, + 'frameId': frame[ 'id' ], + 'context': 'hover', + } + }, failure_handler ) + + # Return working (meanwhile) + return '...' + + def SetSyntax( self, syntax ): - # TODO: Switch to View.syntax self._current_syntax = utils.SetSyntax( self._current_syntax, syntax, self._vars.buf, self._watch.buf ) + # vim: sw=2 diff --git a/run_tests b/run_tests index 201ec1b..39dc7ec 100755 --- a/run_tests +++ b/run_tests @@ -21,7 +21,7 @@ out_fd=1 while [ -n "$1" ]; do case "$1" in - "--basedir"|"--base-dir"|"--test-base") + "--basedir") shift SetBaseDir $1 shift @@ -36,7 +36,7 @@ while [ -n "$1" ]; do INSTALL=$1 shift ;; - "--update"|"--upgrade") + "--update") UPDATE=1 shift ;; @@ -91,8 +91,7 @@ if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "script" ]; then if ! python3 $(dirname $0)/install_gadget.py \ --basedir ${BASEDIR} \ ${INSTALLER_ARGS} \ - --all \ - --force-enable-csharp; then + --all; then echo "Script installation reported errors" >&2 exit 1 fi @@ -103,7 +102,7 @@ if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "vim" ]; then --cmd "${BASEDIR_CMD}" \ -c 'autocmd User VimspectorInstallSuccess qa!' \ -c 'autocmd User VimspectorInstallFailed cquit!' \ - -c "VimspectorInstall --all netcoredbg"; then + -c "VimspectorInstall --all"; then echo "Vim installation reported errors" >&2 exit 1 fi @@ -145,9 +144,6 @@ 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 e76c6ee..95c3360 100644 --- a/support/custom_ui_vimrc +++ b/support/custom_ui_vimrc @@ -1,12 +1,5 @@ -" setup boilerplate to make this file usable with vim -Nu {{{ -scriptencoding utf-8 execute 'source' expand( ':p:h' ) . '/minimal_vimrc' set noequalalways -let mapleader = ',' -let maplocalleader = "\" -" }}} - -" Custom Layout {{{ function! s:CustomiseUI() let wins = g:vimspector_session_windows @@ -38,10 +31,6 @@ function! s:CustomiseUI() endfunction function s:SetUpTerminal() - if !has_key( g:vimspector_session_windows, 'terminal' ) - " There's a neovim bug which means that this doesn't work in neovim - return - endif let terminal_win = g:vimspector_session_windows.terminal " Make the terminal window at most 80 columns wide, ensuring there is enough @@ -54,7 +43,7 @@ function s:SetUpTerminal() let padding = 4 let cols = max( [ min( [ &columns - left_bar - code - padding, 80 ] ), 10 ] ) call win_gotoid( terminal_win ) - execute string(cols) . 'wincmd |' + execute cols . 'wincmd |' endfunction function! s:CustomiseWinBar() @@ -77,85 +66,9 @@ augroup TestUICustomistaion autocmd User VimspectorUICreated call s:CustomiseWinBar() augroup END -" }}} - -" Custom sign priority {{{ - let g:vimspector_sign_priority = { \ 'vimspectorBP': 3, \ 'vimspectorBPCond': 2, \ 'vimspectorBPDisabled': 1, \ 'vimspectorPC': 999, \ } - -" }}} - -" Custom mappings while debuggins {{{ -let s:mapped = {} - -function! s:OnJumpToFrame() abort - if has_key( s:mapped, string( bufnr() ) ) - return - endif - - nmap dn VimspectorStepOver - nmap ds VimspectorStepInto - nmap df VimspectorStepOut - nmap dc VimspectorContinue - nmap di VimspectorBalloonEval - xmap di VimspectorBalloonEval - - let s:mapped[ string( bufnr() ) ] = { 'modifiable': &modifiable } - - setlocal nomodifiable - -endfunction - -function! s:OnDebugEnd() abort - - let original_buf = bufnr() - let hidden = &hidden - - try - set hidden - for bufnr in keys( s:mapped ) - try - execute 'noautocmd buffer' bufnr - silent! nunmap dn - silent! nunmap ds - silent! nunmap df - silent! nunmap dc - silent! nunmap di - silent! xunmap di - - let &l:modifiable = s:mapped[ bufnr ][ 'modifiable' ] - endtry - endfor - finally - execute 'noautocmd buffer' original_buf - let &hidden = hidden - endtry - - let s:mapped = {} -endfunction - -augroup TestCustomMappings - au! - autocmd User VimspectorJumpedToFrame call s:OnJumpToFrame() - autocmd User VimspectorDebugEnded call s:OnDebugEnd() -augroup END - -" }}} - -" Custom mappings for special buffers {{{ - -let g:vimspector_mappings = { - \ 'stack_trace': {}, - \ 'variables': { - \ 'set_value': [ '', '', 'C' ], - \ } - \ } - -" }}} - -" vim: foldmethod=marker diff --git a/support/gadget_upgrade/README.md b/support/gadget_upgrade/README.md deleted file mode 100644 index 9ae3d7f..0000000 --- a/support/gadget_upgrade/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# 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 deleted file mode 100755 index d0c1404..0000000 --- a/support/gadget_upgrade/checksum.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/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 deleted file mode 100644 index a1be1b9..0000000 --- a/support/test/bash/.vimspector.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$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 fb4c958..ae61ee8 100644 --- a/support/test/cpp/simple_c_program/.vimspector.json +++ b/support/test/cpp/simple_c_program/.vimspector.json @@ -1,29 +1,12 @@ { "configurations": { - "CodeLLDB": { + "simple_c_program - Launch": { "adapter": "CodeLLDB", "configuration": { "request": "launch", "program": "${workspaceRoot}/test", "stopAtEntry": true } - }, - "lldb-vscode": { - "adapter": "lldb-vscode", - "configuration": { - "request": "launch", - "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 4203b36..0d17586 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', '-std=c++17' ] + 'flags': [ '-x', 'c++', '-Wall', '-Wextra' ] } diff --git a/support/test/cpp/simple_c_program/test_c.cpp b/support/test/cpp/simple_c_program/test_c.cpp index 8dcc2dc..4a95936 100644 --- a/support/test/cpp/simple_c_program/test_c.cpp +++ b/support/test/cpp/simple_c_program/test_c.cpp @@ -1,5 +1,3 @@ -#include -#include #include namespace Test @@ -35,8 +33,6 @@ int main ( int argc, char ** argv ) { int x{ 10 }; - printf( "HOME: %s\n", getenv( "HOME" ) ); - Test::TestStruct t{ true, {99} }; foo( t ); } diff --git a/support/test/csharp/.gitignore b/support/test/csharp/.gitignore index 03cd7d8..b7d74e4 100644 --- a/support/test/csharp/.gitignore +++ b/support/test/csharp/.gitignore @@ -1,3 +1,2 @@ bin/ obj/Debug -obj/ diff --git a/support/test/csharp/.vimspector.json b/support/test/csharp/.vimspector.json index 326739b..524ae1a 100644 --- a/support/test/csharp/.vimspector.json +++ b/support/test/csharp/.vimspector.json @@ -1,57 +1,25 @@ { - "adapters": { - "netcoredbg-debuglog": { - "attach": { - "pidProperty": "processId", - "pidSelect": "ask" + "configurations": { + "launch - netcoredbg": { + "adapter": "netcoredbg", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", + "args": [], + "stopAtEntry": true + } }, - "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": {} + "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 d453e9a..01d5113 100644 --- a/support/test/csharp/csharp.csproj +++ b/support/test/csharp/csharp.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + netcoreapp2.2 diff --git a/support/test/csharp/csharp.sln b/support/test/csharp/csharp.sln index 91f59bf..bba50e0 100644 --- a/support/test/csharp/csharp.sln +++ b/support/test/csharp/csharp.sln @@ -3,8 +3,6 @@ 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 @@ -17,18 +15,4 @@ 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 new file mode 100644 index 0000000..3ac8d84 --- /dev/null +++ b/support/test/csharp/obj/csharp.csproj.nuget.cache @@ -0,0 +1,5 @@ +{ + "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 new file mode 100644 index 0000000..c71f0e6 --- /dev/null +++ b/support/test/csharp/obj/csharp.csproj.nuget.g.props @@ -0,0 +1,21 @@ + + + + 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 new file mode 100644 index 0000000..099158b --- /dev/null +++ b/support/test/csharp/obj/csharp.csproj.nuget.g.targets @@ -0,0 +1,10 @@ + + + + $(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 new file mode 100644 index 0000000..bd6c0fc --- /dev/null +++ b/support/test/csharp/obj/project.assets.json @@ -0,0 +1,748 @@ +{ + "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 4613b98..8ab5091 100644 --- a/support/test/go/hello_world/.vimspector.json +++ b/support/test/go/hello_world/.vimspector.json @@ -1,18 +1,4 @@ { - "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", @@ -26,21 +12,6 @@ "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/name-starts-with-vowel/.vimspector.json b/support/test/go/name-starts-with-vowel/.vimspector.json deleted file mode 100644 index ffcfc93..0000000 --- a/support/test/go/name-starts-with-vowel/.vimspector.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "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 deleted file mode 100644 index fec967e..0000000 --- a/support/test/go/name-starts-with-vowel/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# 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 deleted file mode 100644 index c160aea..0000000 --- a/support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index 3070734..0000000 --- a/support/test/go/name-starts-with-vowel/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 4e76480..0000000 --- a/support/test/go/name-starts-with-vowel/internal/vowels/vowels.go +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index e0d5773..0000000 --- a/support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go +++ /dev/null @@ -1,30 +0,0 @@ -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/support/test/java/test_project/pom.xml b/support/test/java/test_project/pom.xml index e6dc4d3..890e7e8 100644 --- a/support/test/java/test_project/pom.xml +++ b/support/test/java/test_project/pom.xml @@ -4,7 +4,7 @@ TestApplication 1 - 11 - 11 + 8 + 8 diff --git a/support/test/kotlin/.gitignore b/support/test/kotlin/.gitignore deleted file mode 100644 index f8b92c3..0000000 --- a/support/test/kotlin/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.gradle -build diff --git a/support/test/kotlin/.vimspector.json b/support/test/kotlin/.vimspector.json deleted file mode 100644 index d2c2a63..0000000 --- a/support/test/kotlin/.vimspector.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "configurations": { - "kotlin-debug-adapter launch": { - "adapter": "cust_kotlin-debug-adapter", - "configuration": { - "request": "launch", - "projectRoot": "${workspaceFolder}", - "mainClass": "vimspector/test/ApplicationKt" - } - }, - "kotlin-debug-adapter attach": { - "adapter": "cust_kotlin-debug-adapter", - "configuration": { - "request": "attach", - "projectRoot": "${workspaceFolder}", - "hostName": "${hostName}", - "port": "${port}" - } - } - } -} diff --git a/support/test/kotlin/build.gradle.kts b/support/test/kotlin/build.gradle.kts deleted file mode 100644 index e93c004..0000000 --- a/support/test/kotlin/build.gradle.kts +++ /dev/null @@ -1,25 +0,0 @@ -plugins { - kotlin("jvm") version "1.4.0" - - application -} - -repositories { - // Use jcenter for resolving dependencies. - // You can declare any Maven/Ivy/file repository here. - jcenter() -} - -dependencies { - // Align versions of all Kotlin components - implementation(platform("org.jetbrains.kotlin:kotlin-bom")) - - // Use the Kotlin JDK 8 standard library. - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") -} - -application { - // Define the main class for the application. - mainClassName = "vimspector.test.ApplicationKt" -} - diff --git a/support/test/kotlin/settings.gradle.kts b/support/test/kotlin/settings.gradle.kts deleted file mode 100644 index 8cbc5be..0000000 --- a/support/test/kotlin/settings.gradle.kts +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "vimspector-test" diff --git a/support/test/kotlin/src/main/kotlin/vimspector/test/Application.kt b/support/test/kotlin/src/main/kotlin/vimspector/test/Application.kt deleted file mode 100644 index 99655da..0000000 --- a/support/test/kotlin/src/main/kotlin/vimspector/test/Application.kt +++ /dev/null @@ -1,5 +0,0 @@ -package vimspector.test - -fun main(args: Array) { - println("Hello World!") -} diff --git a/support/test/python/simple_python/.vimspector.json b/support/test/python/simple_python/.vimspector.json index 69d37a6..5eadb0c 100644 --- a/support/test/python/simple_python/.vimspector.json +++ b/support/test/python/simple_python/.vimspector.json @@ -1,47 +1,8 @@ { "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", "adapters": { - "run_with_debugpy": { - "command": [ "${workspaceRoot}/run_with_debugpy" ], - "port": 9876, - "env": { - "DEBUG_PORT": "9876" - } - }, - "python-remote-docker": { - "variables": { - "port": "8765" - }, - "port": "${port}", - "launch": { - "remote": { - "container": "${ContainerID}", - "runCommand": [ - "python3", "-m", "debugpy", "--listen", "0.0.0.0:${port}", - "--wait-for-client", - "%CMD%" - ] - }, - "delay": "5000m" - } - }, - "python-remote-ssh": { - "variables": { - "port": "8765" - }, - "port": "${port}", - "host": "${host}", - "launch": { - "remote": { - "host": "${host}", - "account": "${account}", - "runCommand": [ - "python3", "-m", "debugpy", "--listen", "0.0.0.0:${port}", - "--wait-for-client", - "%CMD%" - ] - } - } + "test_custom": { + "command": "This is a test" } }, "configurations": { @@ -83,33 +44,6 @@ } } }, - "attach-run": { - "adapter": "run_with_debugpy", - "configuration": { - "request": "attach" - }, - "breakpoints": { - "exception": { - "raised": "N", - "uncaught": "", - "userUnhandled": "" - } - } - }, - "docker-attach": { - "adapter": "python-remote-docker", - "remote-cmdLine": [ "/root/main.py" ], - "remote-request": "launch", - "configuration": { - "request": "attach", - "pathMappings": [ - { - "localRoot": "${workspaceRoot}", - "remoteRoot": "/root" - } - ] - } - }, "run": { "adapter": "debugpy", "configuration": { @@ -182,23 +116,6 @@ "stopOnEntry": false, "console": "integratedTerminal" } - }, - "run - remote host": { - "adapter": "python-remote-ssh", - "remote-cmdLine": [ - "${remoteRoot}/main.py" - ], - "remote-request": "launch", - "configuration": { - "request": "attach", - "redirectOutput": true, - "pathMappings": [ - { - "localRoot": "${workspaceRoot}", - "remoteRoot": "${remoteRoot}" - } - ] - } } } } diff --git a/support/test/python/simple_python/Dockerfile b/support/test/python/simple_python/Dockerfile deleted file mode 100644 index 7748fef..0000000 --- a/support/test/python/simple_python/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM ubuntu:18.04 - -RUN apt-get update && \ - apt-get -y dist-upgrade && \ - apt-get -y install sudo \ - lsb-release \ - ca-certificates \ - python3-dev \ - python3-pip \ - ca-cacert \ - locales \ - language-pack-en \ - libncurses5-dev libncursesw5-dev \ - git && \ - apt-get -y autoremove - -## cleanup of files from setup -RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -RUN pip3 install debugpy - -ADD main.py /root/main.py diff --git a/support/test/python/simple_python/build-container b/support/test/python/simple_python/build-container deleted file mode 100755 index bc6450a..0000000 --- a/support/test/python/simple_python/build-container +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -set -e - -if [ "$1" = "--continue" ]; then - OPTS="" -else - OPTS="--no-cache" -fi - -docker build ${OPTS} -t puremourning/vimspector:simple_python . diff --git a/support/test/python/simple_python/run_with_debugpy b/support/test/python/simple_python/run_with_debugpy index 950ce83..03da11c 100755 --- a/support/test/python/simple_python/run_with_debugpy +++ b/support/test/python/simple_python/run_with_debugpy @@ -1,7 +1,9 @@ #!/usr/bin/env bash -if [ -z "$DEBUG_PORT" ]; then - DEBUG_PORT=5678 +PYTHON=python3 + +if [ -n "$1" ]; then + PYTHON=$1 fi pushd $(dirname $0) @@ -9,11 +11,10 @@ pushd $(dirname $0) rm -rf env fi - python3 -m venv env + $PYTHON -m venv env . env/bin/activate python -m pip install -r requirements.txt - echo "using port $DEBUG_PORT" echo "*** Launching ***" - python -m debugpy --wait-for-client --listen 0.0.0.0:${DEBUG_PORT} main.py + python -m debugpy --wait-for-client --listen 0.0.0.0:5678 main.py popd diff --git a/support/test/tcl/test b/support/test/tcl/test index a77f56f..e77a486 100644 --- a/support/test/tcl/test +++ b/support/test/tcl/test @@ -3,8 +3,6 @@ set SCALAR g array set ARRAY {key1 value1 key2 value2} -set LIST [list a b c {def} {g h i j} k l m] - proc Wrap { body } { uplevel 1 $body } diff --git a/tests/breakpoints.test.vim b/tests/breakpoints.test.vim index 877c1cf..2e3eef8 100644 --- a/tests/breakpoints.test.vim +++ b/tests/breakpoints.test.vim @@ -280,8 +280,8 @@ function! Test_Conditional_Line_Breakpoint() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 ) call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 ) - " Add the conditional breakpoint (note , is the mapleader) - call feedkeys( ",\argc==0\\", 'xt' ) + " Add the conditional breakpoint + call feedkeys( "\\\argc==0\\", 'xt' ) call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', \ 16, \ 'vimspectorBPCond', @@ -360,8 +360,8 @@ function! Test_Conditional_Line_Breakpoint_Hit() exe 'edit' fn call setpos( '.', [ 0, 14, 1 ] ) - " Add the conditional breakpoint (3 times) (note , is the mapleader) - call feedkeys( ",\\3\", 'xt' ) + " Add the conditional breakpoint (3 times) + call feedkeys( "\\\\3\", 'xt' ) call vimspector#test#signs#AssertSignGroupSingletonAtLine( \ 'VimspectorBP', \ 14, diff --git a/tests/breakpoints_doublewidth.test.vim b/tests/breakpoints_doublewidth.test.vim index 4bc0571..c646c3e 100644 --- a/tests/breakpoints_doublewidth.test.vim +++ b/tests/breakpoints_doublewidth.test.vim @@ -293,8 +293,8 @@ function! Test_Conditional_Line_Breakpoint() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 ) call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 ) - " Add the conditional breakpoint (, is mapleader) - call feedkeys( ",\argc==0\\", 'xt' ) + " Add the conditional breakpoint + call feedkeys( "\\\argc==0\\", 'xt' ) call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', \ 16, \ 'vimspectorBPCond', @@ -370,8 +370,8 @@ function! Test_Conditional_Line_Breakpoint_Hit() exe 'edit' fn call setpos( '.', [ 0, 14, 1 ] ) - " Add the conditional breakpoint (3 times) (, is mapleader) - call feedkeys( ",\\3\", 'xt' ) + " Add the conditional breakpoint (3 times) + call feedkeys( "\\\\3\", 'xt' ) call vimspector#test#signs#AssertSignGroupSingletonAtLine( \ 'VimspectorBP', \ 14, diff --git a/tests/ci/image/Dockerfile b/tests/ci/image/Dockerfile index 164a5a7..a25febc 100644 --- a/tests/ci/image/Dockerfile +++ b/tests/ci/image/Dockerfile @@ -70,12 +70,6 @@ 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 33e6577..4a37d01 100644 --- a/tests/get_configurations.test.vim +++ b/tests/get_configurations.test.vim @@ -12,7 +12,6 @@ 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 deleted file mode 100644 index 64cf954..0000000 --- a/tests/language_csharp.test.vim +++ /dev/null @@ -1,65 +0,0 @@ -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 6ab220c..b0296e0 100644 --- a/tests/lib/autoload/vimspector/test/setup.vim +++ b/tests/lib/autoload/vimspector/test/setup.vim @@ -50,59 +50,3 @@ 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 f98b8e9..70e297e 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! AssertMatchList( expected, actual ) abort +function! AssertMatchist( 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/lib/run_test.vim b/tests/lib/run_test.vim index b2f1095..9006af1 100644 --- a/tests/lib/run_test.vim +++ b/tests/lib/run_test.vim @@ -82,16 +82,6 @@ func! Abort( timer_id ) qa! endfunc -func! TestLog( msg ) - if type( a:msg ) == v:t_string - let msg = [ a:msg ] - else - let msg = a:msg - endif - - call extend( s:messages, msg ) -endfunc - func RunTheTest(test) echo 'Executing ' . a:test @@ -162,6 +152,8 @@ func RunTheTest(test) augroup END exe 'call ' . a:test + + au! EarlyExit catch /^\cskipped/ call add(s:messages, ' Skipped') call add(s:skipped, @@ -201,8 +193,6 @@ func RunTheTest(test) call s:TestFailed() endtry - au! EarlyExit - call timer_stop( timer ) " In case 'insertmode' was set and something went wrong, make sure it is diff --git a/tests/mappings.test.vim b/tests/mappings.test.vim index b0e288c..fcd19fe 100644 --- a/tests/mappings.test.vim +++ b/tests/mappings.test.vim @@ -106,34 +106,14 @@ function! Test_Use_Mappings_HUMAN() \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 16 ) \ } ) - " Run to cursor (note , is the mapleader) + " Run to cursor call cursor( 9, 1 ) - call feedkeys( ",\", 'xt' ) + call feedkeys( "\\\", 'xt' ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 9, 1 ) call WaitForAssert( {-> \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 9 ) \ } ) - " Stop - call feedkeys( "\", 'xt' ) - call WaitForAssert( {-> - \ assert_equal( [], - \ getbufline( g:vimspector_session_windows.variables, - \ 1, - \ '$' ) ) - \ } ) - call WaitForAssert( {-> - \ assert_equal( [], - \ getbufline( g:vimspector_session_windows.stack_trace, - \ 1, - \ '$' ) ) - \ } ) - call WaitForAssert( {-> - \ assert_equal( [], - \ getbufline( g:vimspector_session_windows.watches, - \ 1, - \ '$' ) ) - \ } ) call vimspector#test#setup#Reset() diff --git a/tests/python/Test_ExpandReferencesInDict.py b/tests/python/Test_ExpandReferencesInDict.py deleted file mode 100644 index 15fb11b..0000000 --- a/tests/python/Test_ExpandReferencesInDict.py +++ /dev/null @@ -1,89 +0,0 @@ -import sys -import unittest -from unittest.mock import patch -from vimspector import utils - - -class TestExpandReferencesInDict( unittest.TestCase ): - def __init__( self, *args, **kwargs ): - super().__init__( *args, **kwargs ) - self.maxDiff = 4096 - - def test_ExpandReferencesInDict( self ): - mapping = { - 'one': 'one', - 'two': 'TWO', - 'bool': True, - 'words': 'these are some words' - } - calculus = { - 'three': lambda : 1 + 2, - } - CHOICES = { - 'five': '5ive!' - } - - def AskForInput( prompt, default_value = None ): - if default_value is not None: - return default_value - - return 'typed text' - - d = { - 'dollar': '$$', - 'not_a_var': '$${test}', - 'one': '${one}', - 'two': '${one} and ${two}', - 'three': '${three}', - 'three_with_default': '${three_with_default:${three\\}}', # uses calculus - 'four': '${four}', - 'five': '${five}', - 'list': [ '*${words}' ], - 'list1': [ 'start', '*${words}', 'end' ], - 'list2': [ '*${words}', '${three}' ], - 'list3': [ '${one}', '*${words}', 'three' ], - 'dict#json': '{ "key": "value" }', - 'bool#json': 'false', - 'one_default': '${one_default:one}', - 'two_default': '${two_default_1:one} and ${two_default_2:two}', - 'one_default2': '${one_default2:${one\\}}', - 'two_default2': - '${two_default2_1:${one\\}} and ${two_default2_2:${two\\}}', - 'unlikely_name#json#s': 'true', - 'empty_splice': [ '*${empty:}' ], - } - - e = { - 'dollar': '$', - 'not_a_var': '${test}', - 'one': 'one', - 'two': 'one and TWO', - 'three': '3', - 'three_with_default': '3', - 'four': 'typed text', - 'five': '5ive!', - 'list': [ 'these', 'are', 'some', 'words' ], - 'list1': [ 'start', 'these', 'are', 'some', 'words', 'end' ], - 'list2': [ 'these', 'are', 'some', 'words', '3' ], - 'list3': [ 'one', 'these', 'are', 'some', 'words', 'three' ], - 'dict': { - 'key': 'value', - }, - 'bool': False, - 'one_default': 'one', - 'two_default': 'one and two', - 'one_default2': 'one', - 'two_default2': 'one and TWO', - 'unlikely_name#json': 'true', - 'empty_splice': [], - } - - with patch( 'vimspector.utils.AskForInput', side_effect = AskForInput ): - utils.ExpandReferencesInDict( d, mapping, calculus, CHOICES ) - - self.assertDictEqual( d, e ) - - -assert unittest.main( module=__name__, - testRunner=unittest.TextTestRunner( sys.stdout ), - exit=False ).result.wasSuccessful() diff --git a/tests/stack_trace.test.vim b/tests/stack_trace.test.vim index b5ed795..569376c 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '- 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -56,7 +56,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -81,7 +81,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -106,7 +106,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -132,7 +132,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( notify_l ) @@ -157,7 +157,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '- 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ 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( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -352,209 +352,6 @@ 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 48ce801..0dca061 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 5ba2f9c..b6c8feb 100644 --- a/tests/ui.test.vim +++ b/tests/ui.test.vim @@ -1,7 +1,6 @@ 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 @@ -17,17 +16,12 @@ 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', [ @@ -49,247 +43,6 @@ 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() @@ -656,56 +409,3 @@ function! Test_CustomWinBar() call vimspector#test#setup#Reset() %bwipe! endfunction - -function! Test_VimspectorJumpedToFrame() - let s:ended = 0 - let s:au_visited_buffers = {} - - augroup TestVimspectorJumpedToFrame - au! - au User VimspectorJumpedToFrame - \ let s:au_visited_buffers[ bufname() ] = get( s:au_visited_buffers, - \ bufname(), - \ 0 ) + 1 - au User VimspectorDebugEnded - \ let s:ended = 1 - augroup END - - lcd ../support/test/python/multiple_files - edit moo.py - - let moo = 'moo.py' - let cow = getcwd() . '/cow.py' - - call vimspector#SetLineBreakpoint( 'moo.py', 13 ) - call vimspector#Launch() - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 1, 1 ) - call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 1 ) - let expected = {} - let expected[ moo ] = 1 - call assert_equal( expected, s:au_visited_buffers ) - - call vimspector#Continue() - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 13, 1 ) - call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 13 ) - let expected[ moo ] += 1 - call assert_equal( expected, s:au_visited_buffers ) - - call vimspector#SetLineBreakpoint( 'cow.py', 2 ) - call vimspector#Continue() - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'cow.py', 2, 1 ) - call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'cow.py', 2 ) - let expected[ cow ] = 1 - call assert_equal( expected, s:au_visited_buffers ) - - VimspectorReset - call WaitForAssert( { -> assert_equal( s:ended, 1 ) } ) - - au! TestVimspectorJumpedToFrame - unlet! s:au_visited_buffers - unlet! s:ended - - call vimspector#test#setup#Reset() - lcd - - %bwipe! -endfunction diff --git a/tests/utils.test.vim b/tests/utils.test.vim deleted file mode 100644 index ad485ce..0000000 --- a/tests/utils.test.vim +++ /dev/null @@ -1,28 +0,0 @@ -function! SetUp() - call vimspector#test#setup#SetUpWithMappings( v:none ) - py3 import vim - py3 __import__( 'vimspector' ) -endfunction - -function! ClearDown() - call vimspector#test#setup#ClearDown() -endfunction - -function! s:RunPyFile( file_name ) - redir => py_output - try - let v:errmsg = '' - silent! execute 'py3file python/' .. a:file_name - finally - redir END - call TestLog( [ a:file_name .. ' output:' ] + split( py_output, '\n' ) ) - endtry - - if v:errmsg !=# '' - call assert_report( v:errmsg ) - endif -endfunction - -function! Test_ExpandReferencesInDict() - call s:RunPyFile( 'Test_ExpandReferencesInDict.py' ) -endfunction diff --git a/tests/variables.test.vim b/tests/variables.test.vim index c00fb7f..9152875 100644 --- a/tests/variables.test.vim +++ b/tests/variables.test.vim @@ -194,7 +194,6 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' *+ t (Test): {...}', - \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -212,7 +211,7 @@ function! Test_ExpandVariables() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -220,7 +219,6 @@ 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, @@ -231,7 +229,7 @@ function! Test_ExpandVariables() " Step - stays expanded call vimspector#StepOver() call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '- Scope: Locals', \ ' - t (Test): {...}', @@ -239,7 +237,6 @@ 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, @@ -256,7 +253,6 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' + t (Test): {...}', - \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -271,7 +267,6 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' + t (Test): {...}', - \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -283,7 +278,7 @@ function! Test_ExpandVariables() call setpos( '.', [ 0, 2, 1 ] ) call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ '- Scope: Locals', \ ' - t (Test): {...}', @@ -291,7 +286,6 @@ function! Test_ExpandVariables() \ ' \*- c (char): 99 ''c''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', - \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -308,7 +302,6 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', - \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -323,7 +316,6 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', - \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -339,7 +331,6 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', - \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -387,7 +378,7 @@ function! Test_ExpandWatch() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -406,7 +397,7 @@ function! Test_ExpandWatch() " Step - stays expanded call vimspector#StepOver() call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -458,7 +449,7 @@ function! Test_ExpandWatch() call setpos( '.', [ 0, 3, 1 ] ) call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -522,49 +513,6 @@ function Test_EvaluateConsole() endfunction -function Test_EvaluateInput() - let fn = 'testdata/cpp/simple/struct.cpp' - call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{ - \ configuration: 'run-to-breakpoint' - \ } } ) - - " Make sure the Test t is initialised - call vimspector#StepOver() - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 ) - call vimspector#StepOver() - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 27, 1 ) - - VimspectorEval -exec print (int) printf("hello") - - call assert_equal( bufnr( 'vimspector.Console' ), - \ winbufnr( g:vimspector_session_windows.output ) ) - call WaitForAssert( {-> - \ assert_equal( - \ [ - \ '' - \ ], - \ getbufline( bufnr( 'vimspector.Console' ), '$', '$' ) - \ ) - \ } ) - - let len = getbufinfo( 'vimspector.Console' )[ 0 ].linecount - - call WaitForAssert( {-> - \ assert_equal( - \ [ - \ 'Evaluating: -exec print (int) printf("hello")', - \ ], - \ getbufline( bufnr( 'vimspector.Console' ), len-2, len-2 ) - \ ) - \ } ) - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( - \ 'vimspector.Console', len, v:null ) - - call vimspector#test#setup#Reset() - %bwipe! -endfunction - - function Test_EvaluatePromptConsole() let fn = 'testdata/cpp/simple/struct.cpp' call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{ @@ -616,7 +564,7 @@ function! Test_EvaluateFailure() " Add a wtch call vimspector#AddWatch( 'test' ) call WaitForAssert( {-> - \ AssertMatchList( + \ AssertMatchist( \ [ \ 'Watches: ----', \ 'Expression: test', @@ -643,493 +591,3 @@ function! Test_EvaluateFailure() call vimspector#test#setup#Reset() %bwipe! endfunction - -function! Test_VariableEval() - let fn = 'testdata/cpp/simple/struct.cpp' - call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{ - \ configuration: 'run-to-breakpoint' - \ } } ) - - call vimspector#StepOver() - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 ) - - " leader is , - xmap d VimspectorBalloonEval - nmap d VimspectorBalloonEval - - "evaluate the prev line - call setpos( '.', [ 0, 24, 8 ] ) - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 24, 8 ) - call feedkeys( ',d', 'xt' ) - - call WaitForAssert( {-> - \ assert_notequal( v:none, g:vimspector_session_windows.eval ) - \ } ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '{...}', - \ ' - i: 0', - \ ' - c: 0 ''\\0\{1,3}''', - \ ' - fffff: 0', - \ ' + another_test: ', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.eval ), - \ 1, - \ '$' ) - \ ) - \ } ) - - "Close - call feedkeys( "\", 'xt' ) - - call WaitForAssert( {-> - \ assert_equal( v:none, g:vimspector_session_windows.eval ) - \ } ) - - " test selection - call setpos( '.', [ 0, 24, 8 ] ) - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 24, 8 ) - - call feedkeys( 'viw,d', 'xt' ) - - call WaitForAssert( {-> - \ assert_notequal( v:none, g:vimspector_session_windows.eval ) - \ } ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '{...}', - \ ' - i: 0', - \ ' - c: 0 ''\\0\{1,3}''', - \ ' - fffff: 0', - \ ' + another_test: ', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.eval ), - \ 1, - \ '$' ) - \ ) - \ } ) - - "Close - call feedkeys( "\", 'xt' ) - - call WaitForAssert( {-> - \ assert_equal( v:none, g:vimspector_session_windows.eval ) - \ } ) - - " Get back to normal mode - call feedkeys( "\", 'xt' ) - - " Evaluation error - call setpos( '.', [ 0, 25, 1 ] ) - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 25, 1 ) - call feedkeys( ',d', 'xt' ) - - call WaitForAssert( {-> - \ assert_notequal( v:none, g:vimspector_session_windows.eval ) - \ } ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ 'Evaluation error', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.eval ), - \ 1, - \ '$' ) - \ ) - \ } ) - - "Close - call feedkeys( "\", 'xt' ) - - call WaitForAssert( {-> - \ assert_equal( v:none, g:vimspector_session_windows.eval ) - \ } ) - - call vimspector#test#setup#Reset() - %bwipe! -endfunction - -function! Test_VariableEvalExpand() - let fn = 'testdata/cpp/simple/struct.cpp' - call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{ - \ configuration: 'run-to-breakpoint' - \ } } ) - - call vimspector#StepOver() - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 ) - - " leader is , - xmap d VimspectorBalloonEval - nmap d VimspectorBalloonEval - - "evaluate the prev line - call setpos( '.', [ 0, 24, 8 ] ) - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 24, 8 ) - call feedkeys( ',d', 'xt' ) - - call WaitForAssert( {-> - \ assert_notequal( v:none, g:vimspector_session_windows.eval ) - \ } ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '{...}', - \ ' - i: 0', - \ ' - c: 0 ''\\0\{1,3}''', - \ ' - fffff: 0', - \ ' + another_test: ', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.eval ), - \ 1, - \ '$' ) - \ ) - \ } ) - - " Expand - call feedkeys( "jjjj\", 'xt' ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '{...}', - \ ' - i: 0', - \ ' - c: 0 ''\\0\{1,3}''', - \ ' - fffff: 0', - \ ' - another_test: ', - \ ' - choo: 0 ''\\0\{1,3}''', - \ ' + ints: ' - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.eval ), - \ 1, - \ '$' ) - \ ) - \ } ) - - "Collapse - call feedkeys( "\", 'xt' ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '{...}', - \ ' - i: 0', - \ ' - c: 0 ''\\0\{1,3}''', - \ ' - fffff: 0', - \ ' + another_test: ', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.eval ), - \ 1, - \ '$' ) - \ ) - \ } ) - - "Close - call feedkeys( "\", 'xt' ) - - call WaitForAssert( {-> - \ assert_equal( v:none, g:vimspector_session_windows.eval ) - \ } ) - - call vimspector#test#setup#Reset() - %bwipe! -endfunction - -function! Test_SetVariableValue_Local() - let fn = 'testdata/cpp/simple/struct.cpp' - call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{ - \ configuration: 'run-to-breakpoint' - \ } } ) - - " Make sure the Test t is initialised - call vimspector#StepOver() - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 ) - - call WaitForAssert( {-> - \ assert_equal( - \ [ - \ '- Scope: Locals', - \ ' *+ t (Test): {...}', - \ '+ Scope: Registers', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.variables ), - \ 1, - \ '$' ) - \ ) - \ } ) - call assert_equal( 'cpp', - \ getbufvar( - \ winbufnr( g:vimspector_session_windows.variables ), - \ '&syntax' ) ) - - " Expand - call win_gotoid( g:vimspector_session_windows.variables ) - call setpos( '.', [ 0, 2, 1 ] ) - call feedkeys( "\", 'xt' ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '- Scope: Locals', - \ ' \*- t (Test): {...}', - \ ' \*- i (int): 0', - \ ' \*- c (char): 0 ''\\0\{1,3}''', - \ ' \*- fffff (float): 0', - \ ' \*+ another_test (AnotherTest):\( {...}\)\?', - \ '+ Scope: Registers', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.variables ), - \ 1, - \ '$' ) - \ ) - \ } ) - - call setpos( '.', [ 0, 3, 1 ] ) - - " We can't just fire the keys to the inpit prompt because we use inputsave() - " and inputrestore(), so mock that out and fire away. - py3 <\100\", "xt" )' ) -EOF - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '- Scope: Locals', - \ ' \*- t (Test): {...}', - \ ' \*- i (int): 100', - \ ' \*- c (char): 0 ''\\0\{1,3}''', - \ ' \*- fffff (float): 0', - \ ' \*+ another_test (AnotherTest):\( {...}\)\?', - \ '+ Scope: Registers', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.variables ), - \ 1, - \ '$' ) - \ ) - \ } ) - - " Now set it via the more comforable scripting interface - call vimspector#SetVariableValue( '1234' ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '- Scope: Locals', - \ ' \*- t (Test): {...}', - \ ' \*- i (int): 1234', - \ ' \*- c (char): 0 ''\\0\{1,3}''', - \ ' \*- fffff (float): 0', - \ ' \*+ another_test (AnotherTest):\( {...}\)\?', - \ '+ Scope: Registers', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.variables ), - \ 1, - \ '$' ) - \ ) - \ } ) - - " Something fails - call vimspector#SetVariableValue( 'this is invalid' ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '- Scope: Locals', - \ ' \*- t (Test): {...}', - \ ' \*- i (int): 1234', - \ ' \*- c (char): 0 ''\\0\{1,3}''', - \ ' \*- fffff (float): 0', - \ ' \*+ another_test (AnotherTest):\( {...}\)\?', - \ '+ Scope: Registers', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.variables ), - \ 1, - \ '$' ) - \ ) - \ } ) - - - call vimspector#test#setup#Reset() - %bwipe! -endfunction - -function! Test_SetVariableValue_Watch() - let fn = 'testdata/cpp/simple/struct.cpp' - call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{ - \ configuration: 'run-to-breakpoint' - \ } } ) - - " Make sure the Test t is initialised - call vimspector#StepOver() - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 ) - - call win_gotoid( g:vimspector_session_windows.watches ) - call feedkeys( "it\", 'xt' ) - - call WaitForAssert( {-> - \ assert_equal( - \ [ - \ 'Watches: ----', - \ 'Expression: t', - \ ' *+ Result: {...}', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.watches ), - \ 1, - \ '$' ) - \ ) - \ } ) - call assert_equal( 'cpp', - \ getbufvar( - \ winbufnr( g:vimspector_session_windows.watches ), - \ '&syntax' ) ) - - " Expand - call win_gotoid( g:vimspector_session_windows.watches ) - call setpos( '.', [ 0, 3, 1 ] ) - call feedkeys( "\", 'xt' ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ 'Watches: ----', - \ 'Expression: t', - \ ' \*- Result: {...}', - \ ' \*- i (int): 0', - \ ' \*- c (char): 0 ''\\0\{1,3}''', - \ ' \*- fffff (float): 0', - \ ' \*+ another_test (AnotherTest):\( {...}\)\?', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.watches ), - \ 1, - \ '$' ) - \ ) - \ } ) - - call setpos( '.', [ 0, 4, 1 ] ) - - " We can't just fire the keys to the inpit prompt because we use inputsave() - " and inputrestore(), so mock that out and fire away. - " Note: mapleder is , - py3 <\100\", "xt" )' ) -EOF - - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ 'Watches: ----', - \ 'Expression: t', - \ ' \*- Result: {...}', - \ ' \*- i (int): 100', - \ ' \*- c (char): 0 ''\\0\{1,3}''', - \ ' \*- fffff (float): 0', - \ ' \*+ another_test (AnotherTest):\( {...}\)\?', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.watches ), - \ 1, - \ '$' ) - \ ) - \ } ) - - " Now set it via the more comforable scripting interface - call vimspector#SetVariableValue( '1234' ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ 'Watches: ----', - \ 'Expression: t', - \ ' \*- Result: {...}', - \ ' \*- i (int): 1234', - \ ' \*- c (char): 0 ''\\0\{1,3}''', - \ ' \*- fffff (float): 0', - \ ' \*+ another_test (AnotherTest):\( {...}\)\?', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.watches ), - \ 1, - \ '$' ) - \ ) - \ } ) - - call vimspector#test#setup#Reset() - %bwipe! -endfunction - -function! Test_SetVariableValue_Balloon() - let fn = 'testdata/cpp/simple/struct.cpp' - call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{ - \ configuration: 'run-to-breakpoint' - \ } } ) - - call vimspector#StepOver() - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 ) - - " leader is , - xmap d VimspectorBalloonEval - nmap d VimspectorBalloonEval - - "evaluate the prev line - call setpos( '.', [ 0, 24, 8 ] ) - call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 24, 8 ) - call feedkeys( ',d', 'xt' ) - - call WaitForAssert( {-> - \ assert_notequal( v:none, g:vimspector_session_windows.eval ) - \ } ) - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '{...}', - \ ' - i: 0', - \ ' - c: 0 ''\\0\{1,3}''', - \ ' - fffff: 0', - \ ' + another_test: ', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.eval ), - \ 1, - \ '$' ) - \ ) - \ } ) - - " Move down to the ffff line - - call feedkeys( 'jjj', 'xt' ) - " We can't just fire the keys to the inpit prompt because we use inputsave() - " and inputrestore(), so mock that out and fire away. - " Note: mapleder is , - py3 <\100\", "xt" )' ) -EOF - - call WaitForAssert( {-> - \ AssertMatchList( - \ [ - \ '{...}', - \ ' - i: 0', - \ ' - c: 0 ''\\0\{1,3}''', - \ ' - fffff: 100', - \ ' + another_test: ', - \ ], - \ getbufline( winbufnr( g:vimspector_session_windows.eval ), - \ 1, - \ '$' ) - \ ) - \ } ) - - call vimspector#test#setup#Reset() - %bwipe! -endfunction diff --git a/tests/vimrc b/tests/vimrc index c65efa8..e362824 100644 --- a/tests/vimrc +++ b/tests/vimrc @@ -1,10 +1,8 @@ let g:vimspector_test_plugin_path = expand( ':p:h:h' ) set mouse=a set noequalalways -let mapleader = ',' -let maplocalleader = "\" -let &runtimepath = &runtimepath . ',' . g:vimspector_test_plugin_path +let &rtp = &rtp . ',' . g:vimspector_test_plugin_path filetype plugin indent on syntax enable