├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ └── feature_request.md └── workflows │ ├── build.yaml │ ├── build_containers.yaml │ ├── lock_old_issues.yaml │ └── update_vim_docs.yaml ├── .gitignore ├── .gitmodules ├── .lgtm.yml ├── .mergify.yml ├── .vimspector.json ├── .vintrc.yml ├── .ycm_extra_conf.py ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENCE ├── Makefile ├── README.md ├── autoload ├── vimspector.vim └── vimspector │ └── internal │ ├── balloon.vim │ ├── channel.vim │ ├── disassembly.vim │ ├── job.vim │ ├── neochannel.vim │ ├── neojob.vim │ ├── neopopup.vim │ ├── neoterm.vim │ ├── neowinbar.vim │ ├── popup.vim │ ├── state.vim │ └── term.vim ├── compiler └── vimspector_test.vim ├── dev_requirements.txt ├── doc ├── vimspector-ref.txt └── vimspector.txt ├── docs ├── .gitignore ├── 404.html ├── Gemfile ├── Gemfile.lock ├── README.local ├── _config.yml ├── configuration.md ├── custom_gadget_file.md ├── index.md ├── schema-doc │ ├── gadgets.schema.html │ ├── schema_doc.css │ ├── schema_doc.min.js │ └── vimspector.schema.html └── schema │ ├── gadgets.schema.json │ ├── index.md │ └── vimspector.schema.json ├── gh-md-toc ├── install_gadget.py ├── plugin └── vimspector.vim ├── python3 └── vimspector │ ├── __init__.py │ ├── breakpoints.py │ ├── code.py │ ├── core_utils.py │ ├── custom │ ├── java.py │ ├── js.py │ └── python.py │ ├── debug_adapter_connection.py │ ├── debug_session.py │ ├── developer.py │ ├── disassembly.py │ ├── gadgets.py │ ├── install.py │ ├── installer.py │ ├── output.py │ ├── session_manager.py │ ├── settings.py │ ├── signs.py │ ├── stack_trace.py │ ├── terminal.py │ ├── utils.py │ ├── variables.py │ └── vendor │ ├── cpuinfo.py │ ├── hexdump.py │ └── json_minify.py ├── run_tests ├── support ├── bin │ └── testecho ├── custom_ui_vimrc ├── doc │ └── example_vimrc.vim ├── gadget_upgrade │ ├── .gitignore │ ├── README.md │ ├── checksum.py │ └── download_and_checksum_gadget.py ├── import_vscode_config ├── minimal_vimrc ├── test │ ├── bash │ │ ├── .vimspector.json │ │ └── test_script │ ├── cpp │ │ ├── simple_c_program │ │ │ ├── .gitignore │ │ │ ├── .vimspector.json │ │ │ ├── .ycm_extra_conf.py │ │ │ ├── memory.cpp │ │ │ └── test_c.cpp │ │ └── tiny_c │ │ │ ├── .vimspector.json │ │ │ └── tiny.c │ ├── csharp │ │ ├── .gitignore │ │ ├── .vimspector.json │ │ ├── Program.cs │ │ ├── csharp.csproj │ │ └── csharp.sln │ ├── example │ │ ├── attach.vim │ │ └── cpp.json │ ├── go │ │ ├── Stdio │ │ │ ├── .vimspector.json │ │ │ ├── cmd │ │ │ │ └── main.go │ │ │ ├── go.mod │ │ │ └── main │ │ ├── hello_world │ │ │ ├── .gitignore │ │ │ ├── .vimspector.json │ │ │ └── hello-world.go │ │ ├── name-starts-with-vowel │ │ │ ├── .vimspector.json │ │ │ ├── README.md │ │ │ ├── cmd │ │ │ │ └── namestartswithvowel │ │ │ │ │ └── main.go │ │ │ ├── go.mod │ │ │ └── internal │ │ │ │ └── vowels │ │ │ │ ├── vowels.go │ │ │ │ └── vowels_test.go │ │ └── structs │ │ │ ├── .gitignore │ │ │ ├── .vimspector.json │ │ │ ├── __debug_bin │ │ │ └── hello-world.go │ ├── java │ │ └── test_project │ │ │ ├── .gitignore │ │ │ ├── .vimspector.json │ │ │ ├── java.vim │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── vimspector │ │ │ └── test │ │ │ ├── Base.java │ │ │ ├── TestApplication.java │ │ │ └── TestGeneric.java │ ├── kotlin │ │ ├── .gitignore │ │ ├── .vimspector.json │ │ ├── build.gradle.kts │ │ ├── settings.gradle.kts │ │ └── src │ │ │ └── main │ │ │ └── kotlin │ │ │ └── vimspector │ │ │ └── test │ │ │ └── Application.kt │ ├── lua │ │ ├── love-headless │ │ │ ├── .vimspector.json │ │ │ ├── conf.lua │ │ │ └── main.lua │ │ ├── love │ │ │ ├── .vimspector.json │ │ │ └── main.lua │ │ └── simple │ │ │ ├── .vimspector.json │ │ │ └── simple.lua │ ├── multiple_filetypes │ │ ├── .vimspector.json │ │ ├── test.js │ │ └── test.py │ ├── node │ │ ├── multiprocess │ │ │ ├── .vimspector.json │ │ │ └── multi.js │ │ ├── simple │ │ │ ├── .tern-project │ │ │ ├── .vimspector.json │ │ │ └── simple.js │ │ └── typescript │ │ │ ├── .gitignore │ │ │ ├── .vimspector.json │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── src │ │ │ └── index.ts │ │ │ └── tsconfig.json │ ├── php │ │ ├── .vimspector.json │ │ ├── 99-xdebug.ini │ │ └── test.php │ ├── python │ │ ├── django │ │ │ ├── .gitignore │ │ │ ├── .vimspector.json │ │ │ ├── mysite │ │ │ │ ├── .gitignore │ │ │ │ ├── manage.py │ │ │ │ ├── mysite │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── asgi.py │ │ │ │ │ ├── settings.py │ │ │ │ │ ├── urls.py │ │ │ │ │ └── wsgi.py │ │ │ │ └── polls │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── admin.py │ │ │ │ │ ├── apps.py │ │ │ │ │ ├── migrations │ │ │ │ │ └── __init__.py │ │ │ │ │ ├── models.py │ │ │ │ │ ├── tests.py │ │ │ │ │ ├── urls.py │ │ │ │ │ └── views.py │ │ │ ├── requirements.txt │ │ │ └── setup │ │ ├── multiple_files │ │ │ ├── .vimspector.json │ │ │ ├── cow.py │ │ │ └── moo.py │ │ ├── multiprocessing │ │ │ ├── .vimspector.json │ │ │ ├── multiprocessing_ception.py │ │ │ └── multiprocessing_test.py │ │ ├── no_conf │ │ │ └── main.py │ │ └── simple_python │ │ │ ├── .gitignore │ │ │ ├── .vimspector.json │ │ │ ├── Dockerfile │ │ │ ├── build-container │ │ │ ├── main.py │ │ │ ├── make_env.sh │ │ │ ├── print_env.py │ │ │ ├── requirements.txt │ │ │ ├── run-container │ │ │ └── run_with_debugpy │ ├── ruby │ │ ├── .bundle │ │ │ └── config │ │ ├── .gitignore │ │ ├── .ruby-version │ │ ├── .vimspector.json │ │ ├── Gemfile │ │ ├── install │ │ └── test.rb │ ├── run_test_vim │ ├── rust │ │ └── vimspector_test │ │ │ ├── .gitignore │ │ │ ├── .vimspector.json │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ └── main.rs │ ├── tcl │ │ ├── .tclpro │ │ │ └── extensions │ │ │ │ └── test.pdx │ │ ├── .vimspector.json │ │ └── test │ └── web │ │ ├── .tern-project │ │ ├── .vimspector.json │ │ ├── run_server │ │ └── www │ │ ├── index.html │ │ └── js │ │ └── test.js ├── test_python3.vim ├── test_vscode_config.json └── vimspector_process_list │ ├── .gitignore │ ├── .vimspector.json │ ├── Makefile │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── vimspector_process_list.go ├── syntax ├── vimspector-breakpoints.vim ├── vimspector-disassembly.vim ├── vimspector-installer.vim └── vimspector-memory.vim ├── tests ├── .gitignore ├── .vimspector.json ├── PIDPicker.test.vim ├── breakpoints.test.vim ├── breakpoints_doublewidth.test.vim ├── child_sessions.test.vim ├── ci │ ├── image │ │ └── Dockerfile │ └── rebuild ├── disassembly.test.vim ├── get_configurations.test.vim ├── goto.test.vim ├── language_csharp.test.vim ├── language_go.test.vim ├── language_lua.test.vim ├── language_python.test.vim ├── lib │ ├── autoload │ │ └── vimspector │ │ │ └── test │ │ │ ├── setup.vim │ │ │ └── signs.vim │ ├── plugin │ │ ├── screendump.vim │ │ └── shared.vim │ └── run_test.vim ├── manual │ ├── image │ │ ├── .vim │ │ │ └── vimrc │ │ └── Dockerfile │ ├── rebuild │ └── run ├── mappings.test.vim ├── memory.test.vim ├── parent_sesions.test.vim ├── python │ ├── Test_CoreUtils.py │ └── Test_ExpandReferencesInDict.py ├── session.test.vim ├── stack_trace.test.vim ├── tabpage.test.vim ├── temporary_breakpoints.test.vim ├── testdata │ └── cpp │ │ └── simple │ │ ├── .gitignore │ │ ├── .vimspector.json │ │ ├── .ycm_extra_conf.py │ │ ├── Makefile │ │ ├── buffer.cpp │ │ ├── printer.cpp │ │ ├── simple.cpp │ │ ├── struct.cpp │ │ ├── threads.cpp │ │ ├── tiny.c │ │ └── variables.cpp ├── ui.test.vim ├── utils.test.vim ├── variables.test.vim ├── variables_compact.test.vim └── vimrc ├── tox.ini ├── update-schema-docs └── update-vim-docs /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Questions and support 4 | url: 'https://matrix.to/#/#vimspector_Lobby:gitter.im' 5 | about: Please ask and answer questions here. 6 | - name: Support for additional languages 7 | url: https://github.com/puremourning/vimspector/wiki/languages 8 | about: Please see here for information on support for additional languages 9 | 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[Feature Request]: Short summary of request" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 25 | 26 | **Is your feature request related to a problem? Please describe.** 27 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 28 | 29 | **Describe the solution you'd like** 30 | A clear and concise description of what you want to happen. 31 | 32 | **Describe alternatives you've considered** 33 | A clear and concise description of any alternative solutions or features you've considered. 34 | 35 | **Additional context** 36 | Add any other context or screenshots about the feature request here. 37 | -------------------------------------------------------------------------------- /.github/workflows/build_containers.yaml: -------------------------------------------------------------------------------- 1 | name: "Build CI containers" 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - 'tests/ci/**' 9 | - 'test/manual/**' 10 | workflow_dispatch: 11 | 12 | jobs: 13 | Intel: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | - uses: docker/login-action@v2 18 | with: 19 | username: ${{ secrets.DOCKERHUB_USERNAME }} 20 | password: ${{ secrets.DOCKERHUB_TOKEN }} 21 | - name: 'Build base CI image' 22 | run: | 23 | pushd tests/ci 24 | ./rebuild 25 | popd 26 | - name: 'Build manual CI image' 27 | run: | 28 | pushd tests/manual 29 | ./rebuild 30 | popd 31 | - name: 'Push to docker hub' 32 | run: | 33 | docker push puremourning/vimspector:test-$(uname -m) 34 | docker push puremourning/vimspector:manual-$(uname -m) 35 | -------------------------------------------------------------------------------- /.github/workflows/lock_old_issues.yaml: -------------------------------------------------------------------------------- 1 | name: "Lock Old Issues" 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | lock: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: dessant/lock-threads@v2 13 | with: 14 | github-token: ${{ github.token }} 15 | issue-lock-inactive-days: '60' 16 | # issue-exclude-created-before: '' 17 | # issue-exclude-labels: '' 18 | # issue-lock-labels: '' 19 | # issue-lock-comment: '' 20 | # issue-lock-reason: 'resolved' 21 | # pr-lock-inactive-days: '365' 22 | # pr-exclude-created-before: '' 23 | # pr-exclude-labels: '' 24 | # pr-lock-labels: '' 25 | # pr-lock-comment: '' 26 | # pr-lock-reason: 'resolved' 27 | process-only: 'issues' 28 | -------------------------------------------------------------------------------- /.github/workflows/update_vim_docs.yaml: -------------------------------------------------------------------------------- 1 | name: "Update vim docs" 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - 'README.md' 9 | - 'docs/configuration.md' 10 | workflow_dispatch: 11 | 12 | jobs: 13 | update-vim-docs: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: 'Update local repo' 18 | run: './update-vim-docs' 19 | - name: 'Check diffs' 20 | run: 'git diff' 21 | - name: 'Create pull request' 22 | uses: peter-evans/create-pull-request@v3 23 | id: cpr 24 | with: 25 | token: ${{ secrets.VIMSPECTOR_UPDATE_BOT_PAT }} 26 | push-to-fork: VimspectorUpdateBot/vimspector 27 | commit-message: "Update vim docs" 28 | branch: 'auto/update-vim-docs' 29 | delete-branch: true 30 | title: "[Auto] Update vim docs" 31 | body: "Update the vim docs after recent changes" 32 | labels: "auto" 33 | - name: Check outputs 34 | run: | 35 | echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" 36 | echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.un~ 2 | *.sw[op] 3 | __pycache__ 4 | .vscode 5 | tests/*.res 6 | tests/messages 7 | tests/debuglog 8 | test.log 9 | *.testlog 10 | gadgets/ 11 | package/ 12 | *.pyc 13 | *.dSYM 14 | README.md.orig.* 15 | README.md.toc.* 16 | .DS_Store 17 | *.vimspector.log 18 | support/test/csharp/*.exe* 19 | .neomake.log 20 | configurations/ 21 | venv/ 22 | test-base*/ 23 | tags 24 | Session.vim 25 | .vimspector.session 26 | tiny 27 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/vader.vim"] 2 | path = vendor/vader.vim 3 | url = https://github.com/junegunn/vader.vim 4 | [submodule "vendor/vim-themis"] 5 | path = vendor/vim-themis 6 | url = https://github.com/thinca/vim-themis 7 | -------------------------------------------------------------------------------- /.lgtm.yml: -------------------------------------------------------------------------------- 1 | extraction: 2 | python: 3 | python_setup: 4 | version: 3 5 | setup_py: false 6 | index: 7 | include: 8 | - python3/vimspector 9 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | # https://blog.mergify.com/strict-mode-deprecation/ 2 | queue_rules: 3 | - name: duplicated default from Merge owner PR when all checks passed 4 | queue_conditions: 5 | - author=puremourning 6 | - base=master 7 | - status-success=code-review/reviewable 8 | - "#changes-requested-reviews-by=0" 9 | - status-success=PythonLint 10 | - status-success=VimscriptLint 11 | - status-success=Linux (vim) 12 | - status-success=Linux (nvim) 13 | - status-success=MacOS (vim) 14 | merge_conditions: 15 | # CI https://doc.mergify.io/conditions.html#github-actions 16 | - status-success=PythonLint 17 | - status-success=VimscriptLint 18 | - status-success=Linux (vim) 19 | - status-success=Linux (nvim) 20 | - status-success=MacOS (vim) 21 | #- status-success=MacOS (nvim) 22 | 23 | merge_method: merge 24 | - name: duplicated default from Merge auto pr when approved 25 | queue_conditions: 26 | - author=VimspectorUpdateBot 27 | - label=auto 28 | - base=master 29 | - status-success=code-review/reviewable 30 | - "#approved-reviews-by>=1" 31 | - "#changes-requested-reviews-by=0" 32 | merge_conditions: 33 | # CI https://doc.mergify.io/conditions.html#github-actions 34 | - status-success=PythonLint 35 | - status-success=VimscriptLint 36 | - status-success=Linux (vim) 37 | - status-success=Linux (nvim) 38 | - status-success=MacOS (vim) 39 | #- status-success=MacOS (nvim) 40 | 41 | merge_method: merge 42 | - name: duplicated default from Merge PR when all checks passed 43 | queue_conditions: 44 | - author!=puremourning 45 | - base=master 46 | - status-success=code-review/reviewable 47 | - "#approved-reviews-by>=1" 48 | - "#changes-requested-reviews-by=0" 49 | - approved-reviews-by=puremourning 50 | - status-success=PythonLint 51 | - status-success=VimscriptLint 52 | - status-success=Linux (vim) 53 | - status-success=Linux (nvim) 54 | - status-success=MacOS (vim) 55 | merge_conditions: 56 | # CI https://doc.mergify.io/conditions.html#github-actions 57 | - status-success=PythonLint 58 | - status-success=VimscriptLint 59 | - status-success=Linux (vim) 60 | - status-success=Linux (nvim) 61 | - status-success=MacOS (vim) 62 | #- status-success=MacOS (nvim) 63 | 64 | merge_method: merge 65 | - name: default 66 | # These define the conditions to get out of the merge queue 67 | conditions: 68 | # CI https://doc.mergify.io/conditions.html#github-actions 69 | - status-success=PythonLint 70 | - status-success=VimscriptLint 71 | - status-success=Linux (vim) 72 | - status-success=Linux (nvim) 73 | - status-success=MacOS (vim) 74 | #- status-success=MacOS (nvim) 75 | 76 | 77 | pull_request_rules: 78 | - name: Merge owner PR when all checks passed 79 | # These define the conditions to get into the merge queue 80 | conditions: 81 | - author=puremourning 82 | - base=master 83 | # Review 84 | - status-success=code-review/reviewable 85 | - "#changes-requested-reviews-by=0" 86 | # CI https://doc.mergify.io/conditions.html#github-actions 87 | - status-success=PythonLint 88 | - status-success=VimscriptLint 89 | - status-success=Linux (vim) 90 | - status-success=Linux (nvim) 91 | - status-success=MacOS (vim) 92 | #- status-success=MacOS (nvim) 93 | actions: &merge-actions 94 | delete_head_branch: {} 95 | - name: Merge auto pr when approved 96 | conditions: 97 | - author=VimspectorUpdateBot 98 | - label=auto 99 | - base=master 100 | # Review 101 | - status-success=code-review/reviewable 102 | - "#approved-reviews-by>=1" 103 | - "#changes-requested-reviews-by=0" 104 | actions: 105 | <<: *merge-actions 106 | - name: Merge PR when all checks passed 107 | # These define the conditions to get into the merge queue 108 | conditions: 109 | - author!=puremourning 110 | - base=master 111 | # Review 112 | - status-success=code-review/reviewable 113 | - "#approved-reviews-by>=1" 114 | - "#changes-requested-reviews-by=0" 115 | - approved-reviews-by=puremourning 116 | # CI https://doc.mergify.io/conditions.html#github-actions 117 | - status-success=PythonLint 118 | - status-success=VimscriptLint 119 | - status-success=Linux (vim) 120 | - status-success=Linux (nvim) 121 | - status-success=MacOS (vim) 122 | #- status-success=MacOS (nvim) 123 | actions: 124 | <<: *merge-actions 125 | comment: 126 | message: Thanks for sending a PR! 127 | - name: Merge PR when all checks passed + Merge auto pr when approved + Merge owner 128 | PR when all checks passed 129 | conditions: [] 130 | actions: 131 | queue: 132 | -------------------------------------------------------------------------------- /.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Python: Attach To Vim": { 4 | "variables": { 5 | "port": "5678", 6 | "host": "localhost" 7 | }, 8 | "adapter": "multi-session", 9 | "configuration": { 10 | "request": "attach" 11 | } 12 | }, 13 | "Python: Run current script": { 14 | "adapter": "debugpy", 15 | "configuration": { 16 | "request": "launch", 17 | "program": "${file}", 18 | "args": [ "*${args:--update-gadget-config}" ], 19 | "justMyCode#json": "${justMyCode:true}" 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.vintrc.yml: -------------------------------------------------------------------------------- 1 | cmdargs: 2 | color: true 3 | severity: style_problem 4 | -------------------------------------------------------------------------------- /.ycm_extra_conf.py: -------------------------------------------------------------------------------- 1 | try: 2 | from ycmd.extra_conf_support import IgnoreExtraConf 3 | except ImportError: 4 | IgnoreExtraConf = None 5 | 6 | import os.path as p 7 | 8 | PATH_TO_THIS_DIR = p.dirname( p.abspath( __file__ ) ) 9 | 10 | 11 | def Settings( **kwargs ): 12 | if kwargs[ 'language' ] == 'json': 13 | return { 14 | 'ls': { 15 | 'json': { 16 | 'schemas': [ 17 | { 18 | 'fileMatch': [ '.vimspector.json' ], 19 | 'url': 20 | f'file://{PATH_TO_THIS_DIR}/docs/schema/vimspector.schema.json' 21 | }, 22 | { 23 | 'fileMatch': [ '.gadgets.json', '.gadgets.d/*.json' ], 24 | 'url': 25 | f'file://{PATH_TO_THIS_DIR}/docs/schema/gadgets.schema.json' 26 | } 27 | ] 28 | } 29 | }, 30 | 'capabilities': { 31 | 'textDocument': { 32 | 'completion': { 33 | 'completionItem': { 34 | 'snippetSupport': True 35 | } 36 | } 37 | } 38 | } 39 | } 40 | 41 | if kwargs[ 'language' ] == 'python': 42 | return { 43 | 'sys_path': [ 44 | p.join( PATH_TO_THIS_DIR, 'python3' ) 45 | ], 46 | 'ls': { 47 | 'python': { 48 | 'analysis': { 49 | 'extraPaths': [ 50 | p.join( PATH_TO_THIS_DIR, 'python3' ), 51 | ], 52 | 'useLibraryCodeForTypes': True 53 | } 54 | } 55 | } 56 | } 57 | 58 | if IgnoreExtraConf: 59 | raise IgnoreExtraConf() 60 | 61 | return None 62 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | We, the maintainers, pledge to treat all contributors with respect and require that contributors reciprocate. 2 | 3 | The maintainers will not tolerate unwelcome, impolite, abusive or unprofessional behaviour. 4 | 5 | At the discretion of the maintainers, users who persist in behaving in a way that is unwelcome may be subject to a ban. 6 | 7 | This applies to all interractions related to this project and any associated projects. 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: check vim-docs schema-docs docs containers 2 | 3 | check: 4 | @echo "Running flake8..." 5 | flake8 python3/ *.py 6 | @echo "Running vint..." 7 | vint autoload/ compiler/ plugin/ tests/ syntax/ 8 | 9 | vim-docs: README.md 10 | $(CURDIR)/update-vim-docs 11 | 12 | schema-docs: docs/*.md docs/schema/*.json 13 | $(CURDIR)/update-schema-docs 14 | 15 | docs: vim-docs schema-docs 16 | 17 | containers: 18 | @echo "Building CI container..." 19 | cd tests/ci && \ 20 | ./rebuild && \ 21 | docker push puremourning/vimspector:test-$(shell uname -m) 22 | @echo "Building Manual container..." 23 | cd tests/manual && \ 24 | ./rebuild && \ 25 | docker push puremourning/vimspector:manual-$(shell uname -m) 26 | -------------------------------------------------------------------------------- /autoload/vimspector/internal/disassembly.vim: -------------------------------------------------------------------------------- 1 | " vimspector - A multi-language debugging system for Vim 2 | " Copyright 2022 Ben Jackson 3 | " 4 | " Licensed under the Apache License, Version 2.0 (the "License"); 5 | " you may not use this file except in compliance with the License. 6 | " You may obtain a copy of the License at 7 | " 8 | " http://www.apache.org/licenses/LICENSE-2.0 9 | " 10 | " Unless required by applicable law or agreed to in writing, software 11 | " distributed under the License is distributed on an "AS IS" BASIS, 12 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | " See the License for the specific language governing permissions and 14 | " limitations under the License. 15 | 16 | 17 | " Boilerplate {{{ 18 | let s:save_cpo = &cpoptions 19 | set cpoptions&vim 20 | " }}} 21 | 22 | function! vimspector#internal#disassembly#OnWindowScrolled() abort 23 | let win_id = expand( '' ) 24 | py3 _vimspector_session.OnDisassemblyWindowScrolled( 25 | \ int( vim.eval( 'win_id' ) ) ) 26 | endfunction 27 | 28 | " Boilerplate {{{ 29 | let &cpoptions=s:save_cpo 30 | unlet s:save_cpo 31 | " }}} 32 | -------------------------------------------------------------------------------- /autoload/vimspector/internal/neochannel.vim: -------------------------------------------------------------------------------- 1 | " vimspector - A multi-language debugging system for Vim 2 | " Copyright 2020 Ben Jackson 3 | " 4 | " Licensed under the Apache License, Version 2.0 (the "License"); 5 | " you may not use this file except in compliance with the License. 6 | " You may obtain a copy of the License at 7 | " 8 | " http://www.apache.org/licenses/LICENSE-2.0 9 | " 10 | " Unless required by applicable law or agreed to in writing, software 11 | " distributed under the License is distributed on an "AS IS" BASIS, 12 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | " See the License for the specific language governing permissions and 14 | " limitations under the License. 15 | 16 | 17 | " Boilerplate {{{ 18 | let s:save_cpo = &cpoptions 19 | set cpoptions&vim 20 | " }}} 21 | 22 | 23 | let s:channels = {} 24 | let s:jobs = {} 25 | 26 | 27 | function! s:_OnEvent( session_id, chan_id, data, event ) abort 28 | if v:exiting isnot# v:null 29 | return 30 | endif 31 | 32 | if !has_key( s:channels, a:session_id ) || 33 | \ a:chan_id != s:channels[ a:session_id ] 34 | return 35 | endif 36 | 37 | if a:data == [''] 38 | echom 'Channel closed' 39 | redraw 40 | unlet s:channels[ a:session_id ] 41 | py3 _VimspectorSession( vim.eval( 'a:session_id' ) ).OnServerExit( 0 ) 42 | else 43 | py3 _VimspectorSession( vim.eval( 'a:session_id' ) ).OnChannelData( 44 | \ '\n'.join( vim.eval( 'a:data' ) ) ) 45 | endif 46 | endfunction 47 | 48 | function! vimspector#internal#neochannel#StartDebugSession( 49 | \ session_id, 50 | \ config ) abort 51 | if has_key( s:channels, a:session_id ) 52 | echom 'Not starting: Channel is already running' 53 | redraw 54 | return v:false 55 | endif 56 | 57 | " If we _also_ have a command line, then start the actual job. This allows for 58 | " servers which start up and listen on some port 59 | if has_key( a:config, 'command' ) && !get( a:config, 'tty', 0 ) 60 | let old_env={} 61 | try 62 | let old_env = vimspector#internal#neoterm#PrepareEnvironment( 63 | \ a:config[ 'env' ] ) 64 | let s:jobs[ a:session_id ] = jobstart( a:config[ 'command' ], 65 | \ { 66 | \ 'cwd': a:config[ 'cwd' ], 67 | \ 'env': a:config[ 'env' ], 68 | \ } 69 | \ ) 70 | finally 71 | call vimspector#internal#neoterm#ResetEnvironment( a:config[ 'env' ], 72 | \ old_env ) 73 | endtry 74 | endif 75 | 76 | let l:addr = get( a:config, 'host', '127.0.0.1' ) . ':' . a:config[ 'port' ] 77 | 78 | let attempt = 1 79 | while attempt <= 10 80 | echo 'Connecting to ' . l:addr . '... (attempt' attempt 'of 10)' 81 | try 82 | let s:channels[ a:session_id ] = sockconnect( 83 | \ 'tcp', 84 | \ addr, 85 | \ { 'on_data': funcref( 's:_OnEvent', [ a:session_id ] ) } ) 86 | redraw 87 | return v:true 88 | catch /connection refused/ 89 | sleep 1 90 | endtry 91 | let attempt += 1 92 | endwhile 93 | 94 | echom 'Unable to connect to' l:addr 'after 10 attempts' 95 | redraw 96 | return v:false 97 | endfunction 98 | 99 | function! vimspector#internal#neochannel#Send( session_id, msg ) abort 100 | if ! has_key( s:channels, a:session_id ) 101 | echom "Can't send message: Channel was not initialised correctly" 102 | redraw 103 | return 0 104 | endif 105 | 106 | call chansend( s:channels[ a:session_id ], a:msg ) 107 | return 1 108 | endfunction 109 | 110 | function! vimspector#internal#neochannel#StopDebugSession( session_id ) abort 111 | if has_key( s:channels, a:session_id ) 112 | call chanclose( s:channels[ a:session_id ] ) 113 | " It doesn't look like we get a callback after chanclos. Who knows if we 114 | " will subsequently receive data callbacks. 115 | call s:_OnEvent( a:session_id, s:channels[ a:session_id ], [ '' ], 'data' ) 116 | endif 117 | 118 | if has_key( s:jobs, a:session_id ) 119 | if vimspector#internal#neojob#JobIsRunning( s:jobs[ a:session_id ] ) 120 | call jobstop( s:jobs[ a:session_id ] ) 121 | endif 122 | unlet s:jobs[ a:session_id ] 123 | endif 124 | endfunction 125 | 126 | function! vimspector#internal#neochannel#Reset() abort 127 | call vimspector#internal#neochannel#StopDebugSession() 128 | endfunction 129 | 130 | " Boilerplate {{{ 131 | let &cpoptions=s:save_cpo 132 | unlet s:save_cpo 133 | " }}} 134 | 135 | -------------------------------------------------------------------------------- /autoload/vimspector/internal/neopopup.vim: -------------------------------------------------------------------------------- 1 | " vimspector - A multi-language debugging system for Vim 2 | " Copyright 2018 Ben Jackson 3 | " 4 | " Licensed under the Apache License, Version 2.0 (the "License"); 5 | " you may not use this file except in compliance with the License. 6 | " You may obtain a copy of the License at 7 | " 8 | " http://www.apache.org/licenses/LICENSE-2.0 9 | " 10 | " Unless required by applicable law or agreed to in writing, software 11 | " distributed under the License is distributed on an "AS IS" BASIS, 12 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | " See the License for the specific language governing permissions and 14 | " limitations under the License. 15 | 16 | " Boilerplate {{{ 17 | let s:save_cpo = &cpoptions 18 | set cpoptions&vim 19 | " }}} 20 | 21 | " Neovim's float window API, like its job/channel API is painful to use 22 | " compared to Vim's so we have to employ more hacks 23 | 24 | " We can't seem to pass a Window handle back to the python, so we have to 25 | " maintain yet another cached here 26 | let s:db = {} 27 | let s:next_id = 0 28 | 29 | 30 | function! s:MessageToList( message ) abort 31 | if type( a:message ) == type( [] ) 32 | let message = a:message 33 | else 34 | let message = [ a:message ] 35 | endif 36 | return message 37 | endfunction 38 | 39 | function! s:GetSplashConfig( message ) abort 40 | let l = max( map( a:message, 'len( v:val )' ) ) 41 | let h = len( a:message ) 42 | 43 | return { 'relative': 'editor', 44 | \ 'width': l, 45 | \ 'height': h, 46 | \ 'col': ( &columns / 2 ) - ( l / 2 ), 47 | \ 'row': ( &lines / 2 ) - h / 2, 48 | \ 'anchor': 'NW', 49 | \ 'style': 'minimal', 50 | \ 'focusable': v:false, 51 | \ } 52 | endfunction 53 | 54 | function! vimspector#internal#neopopup#DisplaySplash( message ) abort 55 | let message = s:MessageToList( a:message ) 56 | let buf = nvim_create_buf(v:false, v:true) 57 | call nvim_buf_set_lines(buf, 0, -1, v:true, message ) 58 | 59 | let win = nvim_open_win(buf, 0, s:GetSplashConfig( message ) ) 60 | call nvim_win_set_option(win, 'wrap', v:false) 61 | call nvim_win_set_option(win, 'colorcolumn', '') 62 | 63 | let id = s:next_id 64 | let s:next_id += 1 65 | let s:db[ id ] = { 'win': win, 'buf': buf } 66 | return id 67 | endfunction 68 | 69 | function! vimspector#internal#neopopup#UpdateSplash( id, message ) abort 70 | let splash = s:db[ a:id ] 71 | let message = s:MessageToList( a:message ) 72 | call nvim_buf_set_lines( splash.buf, 0, -1, v:true, message ) 73 | call nvim_win_set_config( splash.win, s:GetSplashConfig( message ) ) 74 | return a:id 75 | endfunction 76 | 77 | function! vimspector#internal#neopopup#HideSplash( id ) abort 78 | let splash = s:db[ a:id ] 79 | call nvim_win_close( splash.win, v:true ) 80 | call nvim_buf_delete( splash.buf, {} ) 81 | unlet s:db[ a:id ] 82 | return v:null 83 | endfunction 84 | 85 | function! vimspector#internal#neopopup#Confirm( confirm_id, 86 | \ text, 87 | \ options, 88 | \ default_value, 89 | \ keys ) abort 90 | 91 | " Neovim doesn't have an equivalent of popup_dialog, and it's way too much 92 | " effort to write one, so we just use confirm()... 93 | " Annoyingly we can't use confirm() here because for some reason it doesn't 94 | " render properly in a channel callback. So we use input() and mimic dialog 95 | " behaviour. 96 | let prompt = a:text 97 | for opt in a:options 98 | let prompt .= ' ' . opt 99 | endfor 100 | let prompt .= ': ' 101 | 102 | try 103 | let result = input( prompt, a:keys[ a:default_value - 1 ] ) 104 | catch /.*/ 105 | let result = -1 106 | endtry 107 | 108 | " Map the results to what the vim popup stuff would return (s:ConfirmCallback 109 | " in popup.vim), i.e.: 110 | " - 1-based index of selected item, or 111 | " - -1 or 0 for cancellation 112 | if result ==# '' 113 | " User pressed ESC/ctrl-c 114 | let result = -1 115 | else 116 | let index = 1 117 | for k in a:keys 118 | if k ==? result 119 | let result = index 120 | break 121 | endif 122 | let index += 1 123 | endfor 124 | 125 | if index > len( a:keys ) 126 | let result = -1 127 | endif 128 | endif 129 | 130 | py3 __import__( 'vimspector', fromlist = [ 'utils' ] ).utils.ConfirmCallback( 131 | \ int( vim.eval( 'a:confirm_id' ) ), 132 | \ int( vim.eval( 'result' ) ) ) 133 | endfunction 134 | 135 | " Boilerplate {{{ 136 | let &cpoptions=s:save_cpo 137 | unlet s:save_cpo 138 | " }}} 139 | 140 | -------------------------------------------------------------------------------- /autoload/vimspector/internal/neoterm.vim: -------------------------------------------------------------------------------- 1 | " vimspector - A multi-language debugging system for Vim 2 | " Copyright 2018 Ben Jackson 3 | " 4 | " Licensed under the Apache License, Version 2.0 (the "License"); 5 | " you may not use this file except in compliance with the License. 6 | " You may obtain a copy of the License at 7 | " 8 | " http://www.apache.org/licenses/LICENSE-2.0 9 | " 10 | " Unless required by applicable law or agreed to in writing, software 11 | " distributed under the License is distributed on an "AS IS" BASIS, 12 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | " See the License for the specific language governing permissions and 14 | " limitations under the License. 15 | 16 | 17 | " Boilerplate {{{ 18 | let s:save_cpo = &cpoptions 19 | set cpoptions&vim 20 | " }}} 21 | 22 | " Ids are unique throughout the life of neovim, but obviously buffer numbers 23 | " aren't 24 | " 25 | " FIXME: Tidy this map when buffers are closed ? 26 | let s:buffer_to_id = {} 27 | 28 | function! vimspector#internal#neoterm#PrepareEnvironment( env ) abort 29 | let old_env = {} 30 | 31 | for key in keys( a:env ) 32 | if exists( '$' . key ) 33 | let old_env[ key ] = getenv( key ) 34 | endif 35 | call setenv( key, a:env[ key ] ) 36 | endfor 37 | 38 | return old_env 39 | endfunction 40 | 41 | function! vimspector#internal#neoterm#ResetEnvironment( env, old_env ) abort 42 | for key in keys( a:env ) 43 | let value = get( a:old_env, key, v:null ) 44 | call setenv( key, value ) 45 | endfor 46 | endfunction 47 | 48 | function! vimspector#internal#neoterm#Start( cmd, opts ) abort 49 | " Prepare current buffer to be turned into a term if curwin is not set 50 | if ! get( a:opts, 'curwin', 0 ) 51 | let mods = 'rightbelow ' 52 | if get( a:opts, 'vertical', 0 ) 53 | let mods .= 'vertical ' 54 | let mods .= get( a:opts, 'term_cols', '' ) 55 | else 56 | let mods .= get( a:opts, 'term_rows', '' ) 57 | endif 58 | 59 | execute mods . 'new' 60 | endif 61 | 62 | " HACK: Neovim's termopen doesn't support env 63 | 64 | let old_env={} 65 | try 66 | let old_env = vimspector#internal#neoterm#PrepareEnvironment( 67 | \ a:opts[ 'env' ] ) 68 | setlocal nomodified 69 | let id = termopen( a:cmd, { 70 | \ 'cwd': a:opts[ 'cwd' ], 71 | \ 'env': a:opts[ 'env' ], 72 | \ } ) 73 | finally 74 | call vimspector#internal#neoterm#ResetEnvironment( a:opts[ 'env' ], 75 | \ old_env ) 76 | endtry 77 | 78 | let bufnr = bufnr() 79 | let s:buffer_to_id[ bufnr ] = id 80 | return bufnr 81 | endfunction 82 | 83 | function! s:JobIsRunning( job ) abort 84 | return jobwait( [ a:job ], 0 )[ 0 ] == -1 85 | endfunction 86 | 87 | function! vimspector#internal#neoterm#IsFinished( bufno ) abort 88 | if !has_key( s:buffer_to_id, a:bufno ) 89 | return v:true 90 | endif 91 | 92 | return !s:JobIsRunning( s:buffer_to_id[ a:bufno ] ) 93 | endfunction 94 | 95 | function! vimspector#internal#neoterm#GetPID( bufno ) abort 96 | if !has_key( s:buffer_to_id, a:bufno ) 97 | return -1 98 | endif 99 | 100 | return jobpid( s:buffer_to_id[ a:bufno ] ) 101 | endfunction 102 | 103 | " Boilerplate {{{ 104 | let &cpoptions=s:save_cpo 105 | unlet s:save_cpo 106 | " }}} 107 | -------------------------------------------------------------------------------- /autoload/vimspector/internal/neowinbar.vim: -------------------------------------------------------------------------------- 1 | " vimspector - A multi-language debugging system for Vim 2 | " Copyright 2020 Ben Jackson 3 | " 4 | " Licensed under the Apache License, Version 2.0 (the "License"); 5 | " you may not use this file except in compliance with the License. 6 | " You may obtain a copy of the License at 7 | " 8 | " http://www.apache.org/licenses/LICENSE-2.0 9 | " 10 | " Unless required by applicable law or agreed to in writing, software 11 | " distributed under the License is distributed on an "AS IS" BASIS, 12 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | " See the License for the specific language governing permissions and 14 | " limitations under the License. 15 | 16 | 17 | " Boilerplate {{{ 18 | let s:save_cpo = &cpoptions 19 | set cpoptions&vim 20 | " }}} 21 | " 22 | function! vimspector#internal#neowinbar#Do( idx, nclick, btn, mods ) abort 23 | py3 __import__( "vimspector", 24 | \ fromlist = [ "utils" ] ).utils.DoWinBarAction( 25 | \ int( vim.eval( 'getmousepos().winid' ) ), 26 | \ int( vim.eval( 'a:idx' ) ) ) 27 | endfunction 28 | 29 | " Boilerplate {{{ 30 | let &cpoptions=s:save_cpo 31 | unlet s:save_cpo 32 | " }}} 33 | 34 | -------------------------------------------------------------------------------- /autoload/vimspector/internal/popup.vim: -------------------------------------------------------------------------------- 1 | " vimspector - A multi-language debugging system for Vim 2 | " Copyright 2018 Ben Jackson 3 | " 4 | " Licensed under the Apache License, Version 2.0 (the "License"); 5 | " you may not use this file except in compliance with the License. 6 | " You may obtain a copy of the License at 7 | " 8 | " http://www.apache.org/licenses/LICENSE-2.0 9 | " 10 | " Unless required by applicable law or agreed to in writing, software 11 | " distributed under the License is distributed on an "AS IS" BASIS, 12 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | " See the License for the specific language governing permissions and 14 | " limitations under the License. 15 | scriptencoding utf-8 16 | 17 | 18 | " Boilerplate {{{ 19 | let s:save_cpo = &cpoptions 20 | set cpoptions&vim 21 | " }}} 22 | 23 | function! vimspector#internal#popup#DisplaySplash( message ) abort 24 | return popup_dialog( a:message, { 25 | \ 'close': 'button', 26 | \ 'drag': 1, 27 | \ } ) 28 | endfunction 29 | 30 | function! vimspector#internal#popup#UpdateSplash( id, message ) abort 31 | call popup_settext( a:id, a:message ) 32 | return a:id 33 | endfunction 34 | 35 | function! vimspector#internal#popup#HideSplash( id ) abort 36 | call popup_close( a:id ) 37 | return v:null 38 | endfunction 39 | 40 | let s:current_selection = 0 41 | let s:selections = [] 42 | let s:text = [] 43 | 44 | function! s:UpdatePopup( id ) abort 45 | let buf = copy( s:text ) 46 | call extend( buf, s:DrawButtons() ) 47 | call popup_settext( a:id, buf ) 48 | endfunction 49 | 50 | function! s:ConfirmKeyFilter( keys, id, key ) abort 51 | if a:key ==# "\" 52 | call popup_close( a:id, s:current_selection + 1 ) 53 | return 1 54 | elseif index( [ "\", "\" ], a:key ) >= 0 55 | let s:current_selection = ( s:current_selection + 1 ) % len( s:selections ) 56 | call s:UpdatePopup( a:id ) 57 | return 1 58 | elseif index( [ "\", "\" ], a:key ) >= 0 59 | let s:current_selection = s:current_selection == 0 60 | \ ? len( s:selections ) - 1: s:current_selection - 1 61 | call s:UpdatePopup( a:id ) 62 | return 1 63 | elseif a:key ==# "\" || a:key ==# "\" 64 | call popup_close( a:id, -1 ) 65 | return 1 66 | endif 67 | 68 | let index = 1 69 | for key in a:keys 70 | if a:key ==? key 71 | call popup_close( a:id, index ) 72 | return 1 73 | endif 74 | let index += 1 75 | endfor 76 | endfunction 77 | 78 | function! s:ConfirmCallback( confirm_id, id, result ) abort 79 | py3 __import__( 'vimspector', fromlist = [ 'utils' ] ).utils.ConfirmCallback( 80 | \ int( vim.eval( 'a:confirm_id' ) ), 81 | \ int( vim.eval( 'a:result' ) ) ) 82 | endfunction 83 | 84 | function! s:SelectionPosition( idx ) abort 85 | return a:idx == 0 ? 0 : len( join( s:selections[ : a:idx - 1 ], ' ' ) ) + 1 86 | endfunction 87 | 88 | function! s:DrawButtons() abort 89 | return [ { 90 | \ 'text': join( s:selections, ' ' ), 91 | \ 'props': [ 92 | \ { 93 | \ 'col': s:SelectionPosition( s:current_selection ) + 1, 94 | \ 'length': len( s:selections[ s:current_selection ] ), 95 | \ 'type': 'VimspectorSelectedItem' 96 | \ }, 97 | \ ] 98 | \ } ] 99 | endfunction 100 | 101 | function! vimspector#internal#popup#Confirm( 102 | \ confirm_id, 103 | \ text, 104 | \ options, 105 | \ default_value, 106 | \ keys ) abort 107 | 108 | if empty( prop_type_get( 'VimspectorSelectedItem' ) ) 109 | call prop_type_add( 'VimspectorSelectedItem', { 110 | \ 'highlight': 'PMenuSel' 111 | \ } ) 112 | endif 113 | 114 | let lines = split( a:text, "\n", v:true ) 115 | let buf = [] 116 | for line in lines 117 | call add( buf, { 'text': line, 'props': [] } ) 118 | endfor 119 | 120 | call add( buf, { 'text': '', 'props': [] } ) 121 | 122 | let s:selections = a:options 123 | let s:current_selection = ( a:default_value - 1 ) 124 | 125 | let s:text = copy( buf ) 126 | call extend( buf, s:DrawButtons() ) 127 | 128 | let config = { 129 | \ 'callback': function( 's:ConfirmCallback', [ a:confirm_id ] ), 130 | \ 'filter': function( 's:ConfirmKeyFilter', [ a:keys ] ), 131 | \ 'mapping': v:false, 132 | \ } 133 | let config = vimspector#internal#popup#SetBorderChars( config ) 134 | 135 | return popup_dialog( buf, config ) 136 | endfunction 137 | 138 | function! vimspector#internal#popup#SetBorderChars( config ) abort 139 | " When ambiwidth is single, use prettier characters for the border. This 140 | " would look silly when ambiwidth is double. 141 | if &ambiwidth ==# 'single' && &encoding ==? 'utf-8' 142 | let a:config[ 'borderchars' ] = [ '─', '│', '─', '│', '╭', '╮', '┛', '╰' ] 143 | endif 144 | 145 | return a:config 146 | endfunction 147 | 148 | 149 | " Boilerplate {{{ 150 | let &cpoptions=s:save_cpo 151 | unlet s:save_cpo 152 | " }}} 153 | -------------------------------------------------------------------------------- /autoload/vimspector/internal/state.vim: -------------------------------------------------------------------------------- 1 | " vimspector - A multi-language debugging system for Vim 2 | " Copyright 2018 Ben Jackson 3 | " 4 | " Licensed under the Apache License, Version 2.0 (the "License"); 5 | " you may not use this file except in compliance with the License. 6 | " You may obtain a copy of the License at 7 | " 8 | " http://www.apache.org/licenses/LICENSE-2.0 9 | " 10 | " Unless required by applicable law or agreed to in writing, software 11 | " distributed under the License is distributed on an "AS IS" BASIS, 12 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | " See the License for the specific language governing permissions and 14 | " limitations under the License. 15 | 16 | 17 | " Boilerplate {{{ 18 | let s:save_cpo = &cpoptions 19 | set cpoptions&vim 20 | " }}} 21 | 22 | let s:prefix = '' 23 | let s:is_neovim = 0 24 | if has( 'nvim' ) 25 | let s:is_neovim = 1 26 | let s:prefix='neo' 27 | endif 28 | 29 | function! vimspector#internal#state#Reset() abort 30 | try 31 | py3 <, so we 103 | # use that there (it also doesn't correctly invalidate tab objects: 104 | # https://github.com/neovim/neovim/issues/16327), so we can't use the same 105 | # code for both. And as usual, when raising bugs against neovim, they are 106 | # simply closed and never fixed. sigh. 107 | # What's worse is that at this point, the tab numbers have already been 108 | # updated (the tab has already been closed), so if we close the tab 109 | # immediately prior to a vimspector tab, we incorrectly identify the 110 | # vimspector tab as the closed one! We need a TabClosedPre! 111 | s = _vimspector_session_man.FindSessionByTab( int( vim.eval( 'a:afile' ) ) ) 112 | if s: 113 | s.Reset( interactive = False ) 114 | else: 115 | for session in _vimspector_session_man.SessionsWithInvalidUI(): 116 | session.Reset( interactive = False ) 117 | 118 | EOF 119 | endfunction 120 | 121 | function! vimspector#internal#state#SwitchToSession( id ) abort 122 | py3 _VimspectorSwitchTo( _VimspectorSession( vim.eval( 'a:id' ) ) ) 123 | endfunction 124 | 125 | 126 | function! vimspector#internal#state#OnTabEnter() abort 127 | py3 <= 0 28 | endfunction 29 | 30 | function! vimspector#internal#term#GetPID( bufno ) abort 31 | return job_info( term_getjob( a:bufno ) ).process 32 | endfunction 33 | 34 | " Boilerplate {{{ 35 | let &cpoptions=s:save_cpo 36 | unlet s:save_cpo 37 | " }}} 38 | -------------------------------------------------------------------------------- /dev_requirements.txt: -------------------------------------------------------------------------------- 1 | flake8 >= 3.0.0 2 | flake8-comprehensions 3 | flake8-ycm >= 0.1.0 4 | 5 | # asciinema is used to record the output in case of failure 6 | # asciinema >= 2.2.0 7 | # use a fork which returns the exit code of child 8 | git+https://github.com/puremourning/asciinema@exit_code#egg=asciinema 9 | 10 | # Use fork of vint which is up to date 11 | git+https://github.com/puremourning/vint 12 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .sass-cache 3 | .jekyll-metadata 4 | vendor/ 5 | .bundle/ 6 | *.orig.* 7 | *.toc.* 8 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | 18 | 19 |
20 |

404

21 | 22 |

Page not found :(

23 |

The requested page could not be found.

24 |
25 | -------------------------------------------------------------------------------- /docs/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | # Hello! This is where you manage which Jekyll version is used to run. 4 | # When you want to use a different version, change it below, save the 5 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: 6 | # 7 | # bundle exec jekyll serve 8 | # 9 | # This will help ensure the proper Jekyll version is running. 10 | # Happy Jekylling! 11 | #gem "jekyll", "~> 3.8.5" 12 | 13 | # This is the default theme for new Jekyll sites. You may change this to anything you like. 14 | gem "minima", "~> 2.0" 15 | 16 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and 17 | # uncomment the line below. To upgrade, run `bundle update github-pages`. 18 | gem "github-pages", group: :jekyll_plugins 19 | 20 | # If you have any plugins, put them here! 21 | group :jekyll_plugins do 22 | gem "jekyll-feed", "~> 0.6" 23 | end 24 | 25 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 26 | gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] 27 | 28 | # Performance-booster for watching directories on Windows 29 | gem "wdm", "~> 0.1.0" if Gem.win_platform? 30 | 31 | 32 | gem "webrick", "~> 1.8" 33 | -------------------------------------------------------------------------------- /docs/README.local: -------------------------------------------------------------------------------- 1 | To update/install: 2 | 3 | gem install bundler 4 | bundle install --path vendor/bundle 5 | 6 | To run a local server/test the build 7 | 8 | bundle exec jekyll serve 9 | 10 | To update deps 11 | 12 | bundle update 13 | or bundle update github-pages 14 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Jekyll! 2 | # 3 | # This config file is meant for settings that affect your whole blog, values 4 | # which you are expected to set up once and rarely edit after that. If you find 5 | # yourself editing this file very often, consider using Jekyll's data files 6 | # feature for the data you need to update frequently. 7 | # 8 | # For technical reasons, this file is *NOT* reloaded automatically when you use 9 | # 'bundle exec jekyll serve'. If you change this file, please restart the server process. 10 | 11 | # Site settings 12 | # These are used to personalize your new site. If you look in the HTML files, 13 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. 14 | # You can create any custom variable you would like, and they will be accessible 15 | # in the templates via {{ site.myvariable }}. 16 | title: Vimspector Documentation 17 | description: | 18 | Reference Documentation for Vimspector: A multi-language debugging front 19 | end for Vim 20 | 21 | # Build settings 22 | markdown: kramdown 23 | theme: minima 24 | plugins: 25 | - jekyll-feed 26 | 27 | header_pages: 28 | - index.md 29 | - configuration.md 30 | - schema/index.md 31 | 32 | # Exclude from processing. 33 | # The following items will not be processed, by default. Create a custom list 34 | # to override the default setting. 35 | # exclude: 36 | # - Gemfile 37 | # - Gemfile.lock 38 | # - node_modules 39 | # - vendor/bundle/ 40 | # - vendor/cache/ 41 | # - vendor/gems/ 42 | # - vendor/ruby/ 43 | -------------------------------------------------------------------------------- /docs/custom_gadget_file.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Configuration 3 | --- 4 | 5 | This document describes how to use vimspector's `install_gadget.py` to install 6 | custom debug adapters. This can be useful as a way to get an adapter working 7 | that isn't officially supported by Vimspector, but otherwise can be made to work 8 | by simply downloading the VScode extension into the gadget directory. 9 | 10 | ## Usage 11 | 12 | ``` 13 | ./install_gadget.py --enable-custom=/path/to/a.json \ 14 | --enable-custom=/path/to/b.json` 15 | ``` 16 | 17 | This tells `install_gadget.py` to read `a.json` and `b.json` as _gadget 18 | definitions_ and download/unpack the specified gadgets into the gadget dir, just 19 | like the supported adapters. 20 | 21 | ## Gadget Definitions 22 | 23 | A _gadget definition_ is a file containing a single JSON object definition, 24 | describing the debug adapter and how to download and install it. This mechanism 25 | is crude but can be effective. 26 | 27 | The definition of the file format is 28 | [on the wiki](https://github.com/puremourning/vimspector/wiki/languages). 29 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vimspector Reference Guide 3 | --- 4 | 5 | This section contains reference material for configuring and using 6 | [Vimspector][vimspector]. It is intentionally technical in nature and should 7 | serve as a reference guide, rather than a user guide or tutorial. 8 | 9 | It complements the following: 10 | 11 | * The [Vimspector README][readme], which contains a general overview and is the 12 | main go-to for getting started, installation, etc. 13 | * The [Vimspector Website][website], which contains a step-by-step tutorial and 14 | some detail about the user interface. 15 | 16 | ## Contents 17 | 18 | * [Configuring Vimspector for your projects](configuration.html) 19 | * [Full JSON Schema reference](schema/) 20 | * [Online configuration schema view](schema-doc/vimspector.schema.html) 21 | * [Online gadgets schema view](schema-doc/gadgets.schema.html) 22 | 23 | [vimspector]: https://github.com/puremourning/vimspector 24 | [readme]: https://github.com/puremourning/vimspector/blob/master/README.md 25 | [website]: https://puremourning.github.io/vimspector-web 26 | -------------------------------------------------------------------------------- /docs/schema-doc/schema_doc.min.js: -------------------------------------------------------------------------------- 1 | $(document).on("click",'a[href^="#"]',function(event){event.preventDefault();history.pushState({},"",this.href)});function flashElement(elementId){myElement=document.getElementById(elementId);myElement.classList.add("jsfh-animated-property");setTimeout(function(){myElement.classList.remove("jsfh-animated-property")},1e3)}function setAnchor(anchorLinkDestination){history.pushState({},"",anchorLinkDestination)}function anchorOnLoad(){let linkTarget=decodeURIComponent(window.location.hash.split("?")[0].split("&")[0]);if(linkTarget[0]==="#"){linkTarget=linkTarget.substr(1)}if(linkTarget.length>0){anchorLink(linkTarget)}}function anchorLink(linkTarget){const target=$("#"+linkTarget);target.parents().addBack().filter(".collapse:not(.show), .tab-pane, [role='tab']").each(function(index){if($(this).hasClass("collapse")){$(this).collapse("show")}else if($(this).hasClass("tab-pane")){const tabToShow=$("a[href='#"+$(this).attr("id")+"']");if(tabToShow){tabToShow.tab("show")}}else if($(this).attr("role")==="tab"){$(this).tab("show")}});setTimeout(function(){let targetElement=document.getElementById(linkTarget);if(targetElement){targetElement.scrollIntoView({block:"center",behavior:"smooth"});setTimeout(function(){flashElement(linkTarget)},500)}},1e3)} -------------------------------------------------------------------------------- /docs/schema/gadgets.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "$id": "https://puremourning.github.io/vimspector/schema/gadgets.schema.json", 4 | "type": "object", 5 | "properties": { 6 | "adapters": { 7 | "type": "object", 8 | "additionalProperties": { "$ref": "vimspector.schema.json#/definitions/adapter" } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /docs/schema/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Configuration Schema 3 | --- 4 | 5 | This area contains the [JSON Schema][json-schema] representation of the 6 | configuration objects used for configuring Vimspector. For more information on 7 | JSON Schema, check out [Understanding JSON 8 | Schema](http://json-schema.org/understanding-json-schema) 9 | 10 | Vimspector specification is based on [Draft 7][draft-7] of JSON Schema 11 | standard. 12 | 13 | ## The schemas 14 | 15 | * [`vimspector.schema.json`](vimspector.schema.json) - contains the full 16 | configuration definition (`.vimspector.json`). 17 | * [`gadgets.schema.json`](gadgets.schema.json) - contains the specification for 18 | gadget-only objects (`.gadgets.json`). 19 | 20 | [json-schema]: http://json-schema.org 21 | [draft-7]: https://json-schema.org/specification-links.html#draft-7 22 | -------------------------------------------------------------------------------- /python3/vimspector/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puremourning/vimspector/5e24df822e278ee79abfc8c7110089a5322d1a3c/python3/vimspector/__init__.py -------------------------------------------------------------------------------- /python3/vimspector/core_utils.py: -------------------------------------------------------------------------------- 1 | # vimspector - A multi-language debugging system for Vim 2 | # Copyright 2021 Ben Jackson 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import functools 17 | import typing 18 | import os 19 | from collections.abc import Mapping 20 | 21 | MEMO = {} 22 | 23 | 24 | def memoize( func ): 25 | global MEMO 26 | 27 | @functools.wraps( func ) 28 | def wrapper( *args, **kwargs ): 29 | dct = MEMO.setdefault( func, {} ) 30 | key = ( args, frozenset( kwargs.items() ) ) 31 | try: 32 | return dct[ key ] 33 | except KeyError: 34 | result = func( *args, **kwargs ) 35 | dct[ key ] = result 36 | return result 37 | 38 | return wrapper 39 | 40 | 41 | def override( target_dict: typing.MutableMapping, 42 | override_dict: typing.Mapping ): 43 | """Apply the updates in override_dict to the dict target_dict. This is like 44 | dict.update, but recursive. i.e. if the existing element is a dict, then 45 | override elements of the sub-dict rather than wholesale replacing. 46 | 47 | One special case is added. If a key within override dict starts with '!' then 48 | it is interpreted as follows: 49 | - if the associated value is "REMOVE", the key is removed from the parent 50 | dict 51 | - use !! for keys that actually start with ! and shouldn't be removed. 52 | 53 | e.g. 54 | override( 55 | { 56 | 'outer': { 'inner': { 'key': 'oldValue', 'existingKey': True } } 57 | }, 58 | { 59 | 'outer': { 'inner': { 'key': 'newValue' } }, 60 | 'newKey': { 'newDict': True }, 61 | } 62 | ) 63 | yields: 64 | { 65 | 'outer': { 66 | 'inner': { 67 | 'key': 'newValue', 68 | 'existingKey': True 69 | } 70 | }, 71 | 'newKey': { newDict: True } 72 | } 73 | """ 74 | 75 | for key, value in override_dict.items(): 76 | # 77 | # Handle special ! syntax: 78 | # "!keyname" : "REMOVE", --> remove the key 'keyname' from target_dict 79 | # 80 | if key[ 0 : 1 ] == "!" and key[ 1 : 2 ] != "!": 81 | key = key [ 1: ] 82 | if value == "REMOVE": 83 | target_dict.pop( key, None ) 84 | continue 85 | 86 | current_value = target_dict.get( key ) 87 | if not isinstance( current_value, Mapping ): 88 | # Thing or Mapping overrides Thing or None 89 | target_dict[ key ] = value 90 | elif isinstance( value, Mapping ): 91 | # Mapping overrides mapping, recurse 92 | target_dict[ key ] = override( current_value, value ) 93 | else: 94 | # Thing overrides Mapping 95 | target_dict[ key ] = value 96 | 97 | return target_dict 98 | 99 | 100 | def NormalizePath( filepath ): 101 | absolute_path = os.path.abspath( filepath ) 102 | # Normalise windows drive letters to uppercase 103 | drive, tail = os.path.splitdrive( absolute_path ) 104 | if drive: 105 | absolute_path = drive.upper() + tail 106 | return absolute_path if os.path.isfile( absolute_path ) else filepath 107 | -------------------------------------------------------------------------------- /python3/vimspector/custom/java.py: -------------------------------------------------------------------------------- 1 | # vimspector - A multi-language debugging system for Vim 2 | # Copyright 2021 Ben Jackson 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | from vimspector.debug_session import DebugSession 17 | from vimspector import utils, settings 18 | 19 | 20 | class JavaDebugAdapter( object ): 21 | def __init__( self, debug_session: DebugSession ): 22 | self.debug_session = debug_session 23 | 24 | def OnEvent_hotcodereplace( self, message ): 25 | # Hack for java debug server hot-code-replace 26 | body = message.get( 'body' ) or {} 27 | 28 | if body.get( 'type' ) != 'hotcodereplace': 29 | return 30 | 31 | if body.get( 'changeType' ) == 'BUILD_COMPLETE': 32 | def handler( result ): 33 | if result == 1: 34 | self.debug_session._connection.DoRequest( None, { 35 | 'command': 'redefineClasses', 36 | 'arguments': {}, 37 | } ) 38 | 39 | mode = settings.Get( 'java_hotcodereplace_mode' ) 40 | if mode == 'ask': 41 | utils.Confirm( self.debug_session._api_prefix, 42 | 'Code has changed, hot reload?', 43 | handler, 44 | default_value = 1 ) 45 | elif mode == 'always': 46 | self.debug_session._connection.DoRequest( None, { 47 | 'command': 'redefineClasses', 48 | 'arguments': {}, 49 | } ) 50 | elif body.get( 'message' ): 51 | utils.UserMessage( 'Hot code replace: ' + body[ 'message' ] ) 52 | -------------------------------------------------------------------------------- /python3/vimspector/custom/js.py: -------------------------------------------------------------------------------- 1 | # vimspector - A multi-language debugging system for Vim 2 | # Copyright 2023 Ben Jackson 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | from vimspector.debug_session import DebugSession 17 | 18 | import copy 19 | 20 | 21 | class JsDebug( object ): 22 | parent: DebugSession 23 | 24 | def __init__( self, debug_session: DebugSession ): 25 | self.parent = debug_session 26 | 27 | 28 | def OnRequest_startDebugging( self, message ): 29 | # Only thge parent session should start the adapter, so pop out the startup 30 | # command and use the remaining host/port/etc. 31 | adapter = copy.deepcopy( self.parent._adapter ) 32 | adapter.pop( 'command', None ) 33 | 34 | self.parent._DoStartDebuggingRequest( 35 | message, 36 | message[ 'arguments' ][ 'request' ], 37 | message[ 'arguments' ][ 'configuration' ], 38 | adapter ) 39 | # Indicate that we have processed this request 40 | return True 41 | -------------------------------------------------------------------------------- /python3/vimspector/custom/python.py: -------------------------------------------------------------------------------- 1 | # vimspector - A multi-language debugging system for Vim 2 | # Copyright 2021 Ben Jackson 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | from vimspector.debug_session import DebugSession 17 | 18 | 19 | class Debugpy( object ): 20 | parent: DebugSession 21 | 22 | def __init__( self, debug_session: DebugSession ): 23 | self.parent = debug_session 24 | 25 | def OnRequest_startDebugging( self, message ): 26 | config = message[ 'arguments' ][ 'configuration' ] 27 | adapter = config[ 'connect' ] 28 | adapter[ 'custom_handler' ] = self.parent._adapter[ 'custom_handler' ] 29 | self.parent._DoStartDebuggingRequest( 30 | message, 31 | message[ 'arguments' ][ 'request' ], 32 | message[ 'arguments' ][ 'configuration' ], 33 | adapter ) 34 | # Indicate that we have processed this request 35 | return True 36 | -------------------------------------------------------------------------------- /python3/vimspector/developer.py: -------------------------------------------------------------------------------- 1 | # vimspector - A multi-language debugging system for Vim 2 | # Copyright 2020 Ben Jackson 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | import sys 18 | import os 19 | 20 | from vimspector import install, utils, installer 21 | 22 | 23 | def SetUpDebugpy( wait=False, port=5678 ): 24 | sys.path.insert( 25 | 1, 26 | os.path.join( install.GetGadgetDir( utils.GetVimspectorBase() ), 27 | 'debugpy', 28 | 'build', 29 | 'lib' ) ) 30 | import debugpy 31 | 32 | exe = sys.executable 33 | try: 34 | # debugpy uses sys.executable (which is `vim`, so we hack it) 35 | sys.executable = installer.PathToAnyWorkingPython3() 36 | debugpy.listen( port ) 37 | finally: 38 | sys.executable = exe 39 | 40 | if wait: 41 | debugpy.wait_for_client() 42 | -------------------------------------------------------------------------------- /python3/vimspector/install.py: -------------------------------------------------------------------------------- 1 | # vimspector - A multi-language debugging system for Vim 2 | # Copyright 2019 Ben Jackson 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import platform 17 | import os 18 | from vimspector.core_utils import memoize, NormalizePath 19 | 20 | 21 | @memoize 22 | def GetOS(): 23 | if platform.system() == 'Darwin': 24 | return 'macos' 25 | elif platform.system() == 'Windows': 26 | return 'windows' 27 | else: 28 | return 'linux' 29 | 30 | 31 | @memoize 32 | def GetPlatform(): 33 | machine = platform.machine() 34 | 35 | try: 36 | from vimspector.vendor import cpuinfo 37 | except Exception: 38 | return 'unknown' 39 | 40 | machine_info = cpuinfo._parse_arch( machine ) 41 | 42 | machine_map = { 43 | ( 'X86_64', 64 ): 'x86_64', 44 | ( 'X86_32', 32 ): 'x86', 45 | ( 'ARM_8', 64 ): 'arm64', 46 | ( 'ARM_7', 32 ): 'armv7' 47 | } 48 | 49 | try: 50 | return machine_map[ machine_info ] 51 | except KeyError: 52 | return 'unknown' 53 | 54 | 55 | @memoize 56 | def GetOSPlatform(): 57 | return GetOS() + '_' + GetPlatform() 58 | 59 | 60 | def mkdirs( p ): 61 | try: 62 | os.makedirs( p ) 63 | except FileExistsError: 64 | pass 65 | 66 | 67 | def MakeInstallDirs( vimspector_base ): 68 | mkdirs( GetGadgetConfigDir( vimspector_base ) ) 69 | mkdirs( GetConfigDirForFiletype( vimspector_base, '_all' ) ) 70 | 71 | 72 | @memoize 73 | def GetGadgetDir( vimspector_base ): 74 | return os.path.join( os.path.abspath( vimspector_base ), 'gadgets', GetOS() ) 75 | 76 | 77 | def GetManifestFile( vimspector_base ): 78 | return os.path.join( GetGadgetDir( vimspector_base ), 79 | '.gadgets.manifest.json' ) 80 | 81 | 82 | def GetGadgetConfigFile( vimspector_base ): 83 | return os.path.join( GetGadgetDir( vimspector_base ), '.gadgets.json' ) 84 | 85 | 86 | def GetGadgetConfigDir( vimspector_base ): 87 | return os.path.join( GetGadgetDir( vimspector_base ), '.gadgets.d' ) 88 | 89 | 90 | def GetConfigDirForFiletype( vimspector_base, filetype ): 91 | if not filetype: 92 | filetype = 'default' 93 | 94 | return os.path.join( os.path.abspath( vimspector_base ), 95 | 'configurations', 96 | GetOS(), 97 | filetype ) 98 | 99 | 100 | def GetSupportDir(): 101 | return NormalizePath( 102 | os.path.join( os.path.dirname( __file__ ), 103 | '..', 104 | '..', 105 | 'support' ) ) 106 | -------------------------------------------------------------------------------- /python3/vimspector/session_manager.py: -------------------------------------------------------------------------------- 1 | # vimspector - A multi-language debugging system for Vim 2 | # Copyright 2020 Ben Jackson 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import typing 17 | from vimspector.debug_session import DebugSession 18 | from vimspector import utils 19 | 20 | # Singleton 21 | _session_manager = None 22 | 23 | 24 | class SessionManager: 25 | next_session_id: int 26 | sessions: typing.Dict[ int, DebugSession ] 27 | api_prefix: str = '' 28 | 29 | def __init__( self ): 30 | self.Reset() 31 | 32 | 33 | def Reset( self ): 34 | self.next_session_id = 0 35 | self.sessions = {} 36 | 37 | 38 | def NewSession( self, *args, **kwargs ) -> DebugSession: 39 | session_id = self.next_session_id 40 | self.next_session_id += 1 41 | session = DebugSession( session_id, self, self.api_prefix, *args, **kwargs ) 42 | self.sessions[ session_id ] = session 43 | 44 | return session 45 | 46 | 47 | def DestroySession( self, session: DebugSession ): 48 | try: 49 | session = self.sessions.pop( session.session_id ) 50 | except KeyError: 51 | return 52 | 53 | 54 | def DestroyRootSession( self, 55 | session: DebugSession, 56 | active_session: DebugSession ): 57 | if session.HasUI() or session.Connection(): 58 | utils.UserMessage( "Can't destroy active session; use VimspectorReset", 59 | error = True ) 60 | return active_session 61 | 62 | try: 63 | self.sessions.pop( session.session_id ) 64 | session.Destroy() 65 | except KeyError: 66 | utils.UserMessage( "Session doesn't exist", error = True ) 67 | return active_session 68 | 69 | if active_session != session: 70 | # OK, we're done. No need to change the active session 71 | return active_session 72 | 73 | # Return the first root session in the list to be the new active one 74 | for existing_session in self.sessions.values(): 75 | if not existing_session.parent_session: 76 | return existing_session 77 | 78 | # There are somehow no non-root sessions. Clear the current one. We'll 79 | # probably create a new one next time the user does anything. 80 | return None 81 | 82 | 83 | def GetSession( self, session_id ) -> DebugSession: 84 | return self.sessions.get( session_id ) 85 | 86 | 87 | def GetSessionNames( self ) -> typing.List[ str ]: 88 | return [ s.Name() 89 | for s in self.sessions.values() 90 | if not s.parent_session and s.Name() ] 91 | 92 | 93 | def SessionsWithInvalidUI( self ): 94 | for _, session in self.sessions.items(): 95 | if not session.parent_session and not session.HasUI(): 96 | yield session 97 | 98 | 99 | def FindSessionByTab( self, tabnr: int ) -> DebugSession: 100 | for _, session in self.sessions.items(): 101 | if session.IsUITab( tabnr ): 102 | return session 103 | 104 | return None 105 | 106 | 107 | def FindSessionByName( self, name ) -> DebugSession: 108 | for _, session in self.sessions.items(): 109 | if session.Name() == name: 110 | return session 111 | 112 | return None 113 | 114 | 115 | def SessionForTab( self, tabnr ) -> DebugSession: 116 | session: DebugSession 117 | for _, session in self.sessions.items(): 118 | if session.IsUITab( tabnr ): 119 | return session 120 | 121 | return None 122 | 123 | 124 | def Get(): 125 | global _session_manager 126 | if _session_manager is None: 127 | _session_manager = SessionManager() 128 | 129 | return _session_manager 130 | -------------------------------------------------------------------------------- /python3/vimspector/signs.py: -------------------------------------------------------------------------------- 1 | # vimspector - A multi-language debugging system for Vim 2 | # Copyright 2018 Ben Jackson 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import vim 17 | 18 | from vimspector import settings, utils 19 | 20 | 21 | def SignDefined( name ): 22 | if utils.Exists( "*sign_getdefined" ): 23 | return int( 24 | vim.eval( f"len( sign_getdefined( '{ utils.Escape( name ) }' ) )" ) 25 | ) 26 | 27 | return False 28 | 29 | 30 | def DefineSign( name, text, double_text, texthl, col = 'right', **kwargs ): 31 | if utils.GetVimValue( vim.options, 'ambiwidth', '' ) == 'double': 32 | text = double_text 33 | 34 | if text is not None: 35 | if col == 'right': 36 | if int( utils.Call( 'strdisplaywidth', text ) ) < 2: 37 | text = ' ' + text 38 | text = text.replace( ' ', r'\ ' ) 39 | kwargs[ 'text' ] = text 40 | 41 | if texthl is not None: 42 | kwargs[ 'texthl' ] = texthl 43 | 44 | cmd = f'sign define { name }' 45 | for key, value in kwargs.items(): 46 | cmd += f' { key }={ value }' 47 | 48 | vim.command( cmd ) 49 | 50 | 51 | def PlaceSign( sign_id, group, name, file_name, line ): 52 | priority = settings.Dict( 'sign_priority' )[ name ] 53 | 54 | cmd = ( f'sign place { sign_id } ' 55 | f'group={ group } ' 56 | f'name={ name } ' 57 | f'priority={ priority } ' 58 | f'line={ line } ' 59 | f'file={ file_name }' ) 60 | 61 | vim.command( cmd ) 62 | 63 | 64 | def UnplaceSign( sign_id, group ): 65 | vim.command( f'sign unplace { sign_id } group={ group }' ) 66 | 67 | 68 | def DefineProgramCounterSigns(): 69 | if not SignDefined( 'vimspectorPC' ): 70 | DefineSign( 'vimspectorPC', 71 | text = '▶', 72 | double_text = '▶', 73 | texthl = 'MatchParen', 74 | linehl = 'CursorLine' ) 75 | if not SignDefined( 'vimspectorPCBP' ): 76 | DefineSign( 'vimspectorPCBP', 77 | text = '●▶', 78 | double_text = '▷', 79 | texthl = 'MatchParen', 80 | linehl = 'CursorLine' ) 81 | if not SignDefined( 'vimspectorNonActivePC' ): 82 | DefineSign( 'vimspectorNonActivePC', 83 | text = None, 84 | double_text = None, 85 | texthl = None, 86 | linehl = 'DiffAdd' ) 87 | -------------------------------------------------------------------------------- /python3/vimspector/terminal.py: -------------------------------------------------------------------------------- 1 | from vimspector import utils, settings 2 | 3 | import os 4 | import vim 5 | 6 | 7 | class Terminal: 8 | window = None 9 | buffer_number: int = None 10 | 11 | 12 | def LaunchTerminal( api_prefix, 13 | params, 14 | window_for_start, 15 | existing_term ): 16 | if not existing_term: 17 | term = Terminal() 18 | else: 19 | term = existing_term 20 | 21 | cwd = params[ 'cwd' ] or os.getcwd() 22 | args = params[ 'args' ] or [] 23 | env = params.get( 'env' ) or {} 24 | 25 | term_options = { 26 | 'norestore': 1, 27 | 'cwd': cwd, 28 | 'env': env, 29 | } 30 | 31 | if settings.Get( 'ui_mode' ) == 'horizontal': 32 | # force-horizontal 33 | term_options[ 'vertical' ] = 1 34 | elif utils.GetVimValue( vim.vars[ 'vimspector_session_windows' ], 35 | 'mode' ) == 'horizontal': 36 | # horizontal, which means that we should have enough space for: 37 | # - sidebar 38 | # - code min 39 | # - term min width 40 | # - + 2 vertical spaders 41 | # - + 3 columns for signs 42 | term_options[ 'vertical' ] = 1 43 | 44 | # if we don't have enough space for terminal_maxwidth, then see if we have 45 | # enough vertically for terminal_maxheight, in which case, 46 | # that seems a better fit 47 | term_horiz_max = ( settings.Int( 'sidebar_width' ) + 48 | 1 + 2 + 3 + 49 | settings.Int( 'code_minwidth' ) + 50 | 1 + settings.Int( 'terminal_maxwidth' ) ) 51 | term_vert_max = ( settings.Int( 'bottombar_height' ) + 1 + 52 | settings.Int( 'code_minheight' ) + 1 + 53 | settings.Int( 'terminal_minheight' ) ) 54 | 55 | if ( vim.options[ 'columns' ] < term_horiz_max and 56 | vim.options[ 'lines' ] >= term_vert_max ): 57 | # Looks like it, let's try that layout 58 | term_options[ 'vertical' ] = 0 59 | 60 | 61 | else: 62 | # vertical - we need enough space horizontally for the code+terminal, but we 63 | # may fit better with code above terminal 64 | term_options[ 'vertical' ] = 0 65 | 66 | term_horiz_max = ( settings.Int( 'code_minwidth' ) + 3 + 67 | settings.Int( 'terminal_maxwidth' ) + 1 ) 68 | 69 | if vim.options[ 'columns' ] > term_horiz_max: 70 | term_options[ 'vertical' ] = 1 71 | 72 | 73 | if not window_for_start or not window_for_start.valid: 74 | # TODO: Where? Maybe we should just use botright vertical ... 75 | window_for_start = vim.current.window 76 | 77 | if term.window is not None and term.window.valid: 78 | assert term.buffer_number 79 | window_for_start = term.window 80 | if ( term.window.buffer.number == term.buffer_number 81 | and int( utils.Call( 'vimspector#internal#{}term#IsFinished'.format( 82 | api_prefix ), 83 | term.buffer_number ) ) ): 84 | term_options[ 'curwin' ] = 1 85 | else: 86 | term_options[ 'vertical' ] = 0 87 | 88 | buffer_number = None 89 | terminal_window = None 90 | with utils.LetCurrentWindow( window_for_start ): 91 | # If we're making a vertical split from the code window, make it no more 92 | # than 80 columns and no fewer than 10. Also try and keep the code window 93 | # at least 82 columns 94 | if term_options.get( 'curwin', 0 ): 95 | pass 96 | elif term_options[ 'vertical' ]: 97 | term_options[ 'term_cols' ] = max( 98 | min ( int( vim.eval( 'winwidth( 0 )' ) ) 99 | - settings.Int( 'code_minwidth' ), 100 | settings.Int( 'terminal_maxwidth' ) ), 101 | settings.Int( 'terminal_minwidth' ) 102 | ) 103 | else: 104 | term_options[ 'term_rows' ] = max( 105 | min ( int( vim.eval( 'winheight( 0 )' ) ) 106 | - settings.Int( 'code_minheight' ), 107 | settings.Int( 'terminal_maxheight' ) ), 108 | settings.Int( 'terminal_minheight' ) 109 | ) 110 | 111 | 112 | buffer_number = int( 113 | utils.Call( 114 | 'vimspector#internal#{}term#Start'.format( api_prefix ), 115 | args, 116 | term_options ) ) 117 | terminal_window = vim.current.window 118 | 119 | if buffer_number is None or buffer_number <= 0: 120 | # TODO: Do something better like reject the request? 121 | raise ValueError( "Unable to start terminal" ) 122 | 123 | term.window = terminal_window 124 | term.buffer_number = buffer_number 125 | 126 | utils.UpdateSessionWindows( { 127 | 'terminal': utils.WindowID( term.window, vim.current.tabpage ) 128 | } ) 129 | with utils.RestoreCursorPosition(): 130 | with utils.RestoreCurrentWindow(): 131 | with utils.RestoreCurrentBuffer( vim.current.window ): 132 | vim.command( 'doautocmd User VimspectorTerminalOpened' ) 133 | 134 | return term 135 | -------------------------------------------------------------------------------- /python3/vimspector/vendor/json_minify.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2020 Kyle Simpson 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining 4 | # a copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included 11 | # in all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 18 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 19 | # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | # 21 | 22 | """A port of the `JSON-minify` utility to the Python language. 23 | 24 | Based on JSON.minify.js: https://github.com/getify/JSON.minify 25 | 26 | Contributors: 27 | - Gerald Storer 28 | - Contributed original version 29 | - Felipe Machado 30 | - Performance optimization 31 | - Pradyun S. Gedam 32 | - Conditions and variable names changed 33 | - Reformatted tests and moved to separate file 34 | - Made into a PyPI Package 35 | """ 36 | 37 | import re 38 | 39 | 40 | # Vimspector modification: strip_space defaults to False; we don't actually want 41 | # to minify - we just want to strip comments. 42 | def minify(string, strip_space=False): 43 | tokenizer = re.compile(r'"|(/\*)|(\*/)|(//)|\n|\r') 44 | end_slashes_re = re.compile(r'(\\)*$') 45 | 46 | in_string = False 47 | in_multi = False 48 | in_single = False 49 | 50 | new_str = [] 51 | index = 0 52 | 53 | for match in re.finditer(tokenizer, string): 54 | 55 | if not (in_multi or in_single): 56 | tmp = string[index:match.start()] 57 | if not in_string and strip_space: 58 | # replace white space as defined in standard 59 | tmp = re.sub('[ \t\n\r]+', '', tmp) 60 | new_str.append(tmp) 61 | elif not strip_space: 62 | # Replace comments with white space so that the JSON parser reports 63 | # the correct column numbers on parsing errors. 64 | new_str.append(' ' * (match.start() - index)) 65 | 66 | index = match.end() 67 | val = match.group() 68 | 69 | if val == '"' and not (in_multi or in_single): 70 | escaped = end_slashes_re.search(string, 0, match.start()) 71 | 72 | # start of string or unescaped quote character to end string 73 | if not in_string or (escaped is None or len(escaped.group()) % 2 == 0): # noqa 74 | in_string = not in_string 75 | index -= 1 # include " character in next catch 76 | elif not (in_string or in_multi or in_single): 77 | if val == '/*': 78 | in_multi = True 79 | elif val == '//': 80 | in_single = True 81 | elif val == '*/' and in_multi and not (in_string or in_single): 82 | in_multi = False 83 | if not strip_space: 84 | new_str.append(' ' * len(val)) 85 | elif val in '\r\n' and not (in_multi or in_string) and in_single: 86 | in_single = False 87 | elif not ((in_multi or in_single) or (val in ' \r\n\t' and strip_space)): # noqa 88 | new_str.append(val) 89 | 90 | if not strip_space: 91 | if val in '\r\n': 92 | new_str.append(val) 93 | elif in_multi or in_single: 94 | new_str.append(' ' * len(val)) 95 | 96 | new_str.append(string[index:]) 97 | return ''.join(new_str) 98 | -------------------------------------------------------------------------------- /support/bin/testecho: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | while true; do 4 | read string 5 | 6 | if [ "$string" = "GOODBYE" ]; then 7 | exit 0 8 | elif [ "$string" = "FAIL" ]; then 9 | echo "There was a faytal eyror" >&2 10 | exit 1 11 | fi 12 | 13 | echo "Content-Type: Something" 14 | echo "Content-Length: ${#string}" 15 | echo "" 16 | echo $string 17 | 18 | string="Special message" 19 | echo "Content-Type: Something-else" 20 | echo "Content-Length: ${#string}" 21 | echo "" 22 | echo $string 23 | done 24 | -------------------------------------------------------------------------------- /support/doc/example_vimrc.vim: -------------------------------------------------------------------------------- 1 | let g:vimspector_enable_mappings = 'HUMAN' 2 | packadd! vimspector 3 | syntax enable 4 | filetype plugin indent on 5 | -------------------------------------------------------------------------------- /support/gadget_upgrade/.gitignore: -------------------------------------------------------------------------------- 1 | *.vsix 2 | linux/ 3 | macos/ 4 | windows/ 5 | -------------------------------------------------------------------------------- /support/gadget_upgrade/README.md: -------------------------------------------------------------------------------- 1 | # Auto download and checksum 2 | 3 | This is useful for binary gadgets with lots of packages (like cpptools) 4 | 5 | 1. Update ../../python3/vimspector/gadgets.py with the new version/url, but 6 | remove the checksums (set to `''`) 7 | 2. run ./download_and_checksum_gadget.py gadget_name to download the packages 8 | for each platform/version and print the checksums 9 | 3. update ../../python3/vimspector/gadgets.py with the checksums 10 | 2. run ./download_and_checksum_gadget.py gadget_name again to verify (should 11 | all match and not re-download) 12 | 13 | # Manually downloading and updating shipped gadgets 14 | 15 | Download the gadget files manually from their official source into this dir. 16 | Run `./checksum.py ` to get the checksums. 17 | 18 | Update ../../python3/vimspector/gadgets.py with the new version and the 19 | checksums. 20 | 21 | -------------------------------------------------------------------------------- /support/gadget_upgrade/checksum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import hashlib 4 | import sys 5 | 6 | 7 | def GetChecksumSHA254( file_path ): 8 | with open( file_path, 'rb' ) as existing_file: 9 | return hashlib.sha256( existing_file.read() ).hexdigest() 10 | 11 | 12 | for arg in sys.argv[ 1: ]: 13 | print( f"{ arg } = { GetChecksumSHA254( arg ) }" ) 14 | -------------------------------------------------------------------------------- /support/gadget_upgrade/download_and_checksum_gadget.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import os 5 | import string 6 | import fnmatch 7 | 8 | if '--help' in sys.argv: 9 | print( f"Usage: { os.path.basename( __file__ ) } [-v] gadget [gadget2 ...]" ) 10 | print( "" ) 11 | print( "Each gadget is a glob (fnmatch), so use * to do all " ) 12 | exit(0) 13 | 14 | VERBOSE = 0 15 | if '-v' in sys.argv: 16 | VERBOSE = 1 17 | sys.argv = list( filter( lambda x: x != "-v", sys.argv ) ) 18 | 19 | # Gaim access to vimspector libs 20 | sys.path.insert( 21 | 1, 22 | os.path.abspath( os.path.join( os.path.dirname( __file__ ), 23 | '..', 24 | '..', 25 | 'python3' ) ) 26 | ) 27 | 28 | from vimspector import install, installer, gadgets 29 | 30 | gadgets_to_sum = sys.argv[ 1: ] 31 | results = [] 32 | 33 | for gadget_name in gadgets.GADGETS.keys(): 34 | include = False 35 | for requested_gadget in gadgets_to_sum: 36 | if fnmatch.fnmatch( gadget_name, requested_gadget ): 37 | include = True 38 | break 39 | 40 | if not include: 41 | if VERBOSE: 42 | print( f"Skipping { gadget_name } (not in { gadgets_to_sum })" ) 43 | continue 44 | 45 | if VERBOSE: 46 | print( f"Processing { gadget_name }..." ) 47 | 48 | gadget = gadgets.GADGETS[ gadget_name ] 49 | if 'download' not in gadget: 50 | print( 51 | f"WARNING: Gadget not downloadable (probably a git clone?) {gadget_name}", 52 | file=sys.stderr ) 53 | continue 54 | 55 | root = os.path.join( os.path.abspath( os.path.dirname( __file__ ) ), 56 | 'download' ) 57 | 58 | last_url = '' 59 | seen_checksums = set() 60 | for OS in 'linux', 'macos', 'windows': 61 | for PLATFORM in 'x86_64', 'arm64', 'x86', 'armv7': 62 | spec = {} 63 | spec.update( gadget.get( 'all', {} ) ) 64 | spec.update( gadget.get( OS, {} ) ) 65 | spec.update( gadget.get( OS + '_' + PLATFORM, {} ) ) 66 | 67 | if spec.get( 'checksum', None ): 68 | print( f"WARNING: { PLATFORM } for { OS } for { gadget_name } " 69 | "has a checksum configured already. Probably you forgot to " 70 | "clear it." ) 71 | 72 | url = string.Template( gadget[ 'download' ][ 'url' ] ).substitute( spec ) 73 | if url == last_url: 74 | # Probably not different for this arch 75 | continue 76 | 77 | version = spec.get( 'version', 'vUnknown' ) 78 | destination = os.path.join( root, gadget_name, OS, PLATFORM, version ) 79 | 80 | file_path = installer.DownloadFileTo( 81 | url, 82 | destination, 83 | file_name = gadget[ 'download' ].get( 'target' ), 84 | checksum = spec.get( 'checksum' ) ) 85 | 86 | checksum = installer.GetChecksumSHA254( file_path ) 87 | if checksum in seen_checksums: 88 | continue 89 | seen_checksums.add( checksum ) 90 | 91 | last_url = url 92 | results.append( 93 | f"{ gadget_name } { version } { OS }_{ PLATFORM }: { checksum }" ) 94 | 95 | for result in results: 96 | print( result ) 97 | -------------------------------------------------------------------------------- /support/import_vscode_config: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import json 5 | import sys 6 | 7 | p = argparse.ArgumentParser() 8 | p.add_argument( "vscode_config" ) 9 | args = p.parse_args() 10 | 11 | TYPE_TO_ADAPTER = { 12 | 'cppdbg': 'vscode-cpptools' 13 | } 14 | 15 | configurations = {} 16 | with open( args.vscode_config ) as vscode_config_file: 17 | vscode = json.load( vscode_config_file ) 18 | vsconfigurations = vscode.get( "launch", {} ).get( "configurations", [] ) 19 | if not vsconfigurations: 20 | exit( f"No launch configurations found in {args.vscode_config}" ) 21 | 22 | for vsconfig in vsconfigurations: 23 | name = vsconfig.pop( "name" ) 24 | configurations[ name ] = { 25 | "adapter": TYPE_TO_ADAPTER[ vsconfig.pop( "type" ) ], 26 | "configuration": vsconfig, 27 | } 28 | 29 | vimspector = { 30 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", 31 | "configurations": configurations 32 | } 33 | 34 | json.dump( vimspector, sys.stdout, indent=2 ) 35 | -------------------------------------------------------------------------------- /support/minimal_vimrc: -------------------------------------------------------------------------------- 1 | let g:vimspector_clean = 1 2 | let s:vimspector_path = expand( ':p:h:h' ) 3 | let g:vimspector_enable_mappings = 'HUMAN' 4 | colorscheme habamax 5 | exe 'source ' . s:vimspector_path . '/tests/vimrc' 6 | 7 | -------------------------------------------------------------------------------- /support/test/bash/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", 3 | "configurations": { 4 | "Run Current Script": { 5 | "adapter": "vscode-bash", 6 | "autoselect": false, 7 | "configuration": { 8 | "request": "launch", 9 | "program": "${file}", 10 | "cwd": "${fileDirname}", 11 | "args": [ "*${args}" ] 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /support/test/bash/test_script: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function Test() { 4 | echo $1 5 | } 6 | 7 | for i in "$@"; do 8 | Test $i 9 | done 10 | -------------------------------------------------------------------------------- /support/test/cpp/simple_c_program/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | test.dSYM 3 | -------------------------------------------------------------------------------- /support/test/cpp/simple_c_program/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "adapters": { 3 | "lldb-dap": { 4 | "attach": { 5 | "pidProperty": "pid", 6 | "pidSelect": "ask" 7 | }, 8 | "command": [ 9 | "/opt/homebrew/opt/llvm/bin/lldb-dap" 10 | ], 11 | "env": { 12 | "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" 13 | }, 14 | "name": "lldb", 15 | "configuration": { 16 | "runInTerminal": true 17 | } 18 | }, 19 | "custom-lldb-dap": { 20 | "extends": "lldb-dap", 21 | "command": [ 22 | "$HOME/Development/llvm-project/build/bin/lldb-dap" 23 | ] 24 | }, 25 | "custom-codelldb": { 26 | "extends": "CodeLLDB", 27 | "command": [ 28 | "$HOME/Development/vimspector/CodeLLDB/build/adapter/codelldb", 29 | "--liblldb", "$HOME/Development/llvm-project/build/lib/liblldb.dylib" 30 | ] 31 | }, 32 | "CodeLLDB - StopOnEntry": { 33 | "extends": "custom-codelldb", 34 | "name": "CoHostingLLDB" 35 | }, 36 | "custom-cpptools": { 37 | "extends": "vscode-cpptools", 38 | "command": [ 39 | "$HOME/Development/vimspector/MIEngine/bin/Debug/vscode/OpenDebugAD7" 40 | ] 41 | } 42 | }, 43 | "configurations": { 44 | "CodeLLDB-custom": { 45 | "adapter": "custom-codelldb", 46 | "configuration": { 47 | "request": "launch", 48 | "expressions": "native", 49 | "program": "${workspaceRoot}/test" 50 | } 51 | }, 52 | "CodeLLDB": { 53 | "adapter": "CodeLLDB", 54 | "configuration": { 55 | "request": "launch", 56 | "expressions": "native", 57 | "program": "${workspaceRoot}/test" 58 | } 59 | }, 60 | "CodeLLDB-StopOnEntryFalse": { 61 | "extends": "CodeLLDB", 62 | "adapter": "CodeLLDB - StopOnEntry", 63 | "configuration": { 64 | "stopOnEntry": false 65 | } 66 | }, 67 | "CodeLLDB-StopOnEntryTrue": { 68 | "extends": "CodeLLDB-StopOnEntryFalse", 69 | "configuration": { 70 | "stopOnEntry": true 71 | } 72 | }, 73 | "lldb-dap": { 74 | "adapter": "lldb-dap", 75 | "configuration": { 76 | "request": "launch", 77 | "program": "${workspaceRoot}/test" 78 | } 79 | }, 80 | "lldb-dap-custom": { 81 | "extends": "lldb-dap", 82 | "adapter": "custom-lldb-dap" 83 | }, 84 | "lldb-vscode": { 85 | "adapter": "lldb-vscode", 86 | "variables": { 87 | "BUILDME": { 88 | "shell": "g++ -o ${workspaceRoot}/test -g -std=c++17 ${workspaceRoot}/test_c.cpp" 89 | } 90 | }, 91 | "configuration": { 92 | "request": "launch", 93 | "program": "${workspaceRoot}/test", 94 | "stopAtEntry": true 95 | } 96 | }, 97 | "cpptools (lldb)": { 98 | "adapter": "vscode-cpptools", 99 | "variables": { 100 | "BUILDME": { 101 | "shell": "g++ -o ${workspaceRoot}/test -g -std=c++17 ${file}" 102 | }, 103 | "arch": { 104 | "shell": "uname -m" 105 | } 106 | }, 107 | "configuration": { 108 | "request": "launch", 109 | "program": "${workspaceRoot}/test", 110 | "stopAtEntry": true, 111 | "MIMode": "lldb", 112 | "MIDebuggerPath": "$HOME/.vim/vimspector-conf/gadgets/macos/vscode-cpptools/debugAdapters/lldb-mi/bin/lldb-mi", 113 | "logging": { 114 | "engineLogging": true 115 | }, 116 | "targetArchitecture": "${arch}" 117 | } 118 | }, 119 | "cpptools (gdb)": { 120 | "adapter": "vscode-cpptools", 121 | "variables": { 122 | "BUILDME": { 123 | "shell": "g++ -o ${workspaceRoot}/test -g -std=c++17 ${file}" 124 | } 125 | }, 126 | "configuration": { 127 | "request": "launch", 128 | "program": "${workspaceRoot}/test", 129 | "stopAtEntry": true, 130 | "MIMode": "gdb" 131 | } 132 | }, 133 | "cpptools-attach": { 134 | "extends": "cpptools (lldb)", 135 | "configuration": { 136 | "request": "attach" 137 | }, 138 | "breakpoints": { 139 | "exception": { 140 | "cpp_throw": "", 141 | "cpp_catch": "" 142 | } 143 | } 144 | }, 145 | "CodeLLDB-attach": { 146 | "extends": "CodeLLDB", 147 | "configuration": { 148 | "request": "attach", 149 | "pid": "${PickProcess(\"test\")}" 150 | }, 151 | "breakpoints": { 152 | "exception": { 153 | "cpp_throw": "", 154 | "cpp_catch": "" 155 | } 156 | } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /support/test/cpp/simple_c_program/.ycm_extra_conf.py: -------------------------------------------------------------------------------- 1 | def Settings( **kwargs ): 2 | return { 3 | 'flags': [ '-x', 'c++', '-Wall', '-Wextra', '-std=c++17' ] 4 | } 5 | -------------------------------------------------------------------------------- /support/test/cpp/simple_c_program/memory.cpp: -------------------------------------------------------------------------------- 1 | struct Test 2 | { 3 | int x; 4 | int y; 5 | }; 6 | 7 | int main( int argc , char ** argv ) 8 | { 9 | Test x[] = { 10 | { 1, 2 }, 11 | { 3, 4 }, 12 | { 5, 6 }, 13 | }; 14 | 15 | Test y = { 7, 8 }; 16 | 17 | x[0].x += argc; 18 | argv[ 0 ][ 0 ] = 'x' ; 19 | 20 | y.x += **argv; 21 | y.y += argc * **argv; 22 | 23 | return argc; 24 | } 25 | -------------------------------------------------------------------------------- /support/test/cpp/simple_c_program/test_c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace Test 6 | { 7 | struct TestStruct 8 | { 9 | bool isInt; 10 | 11 | union { 12 | int somethingInt; 13 | char somethingChar; 14 | } something; 15 | 16 | char big[ sizeof(void*) * 100 ]; 17 | }; 18 | 19 | TestStruct _t; 20 | 21 | void bar( TestStruct b ) 22 | { 23 | std::string s; 24 | s += b.isInt ? "An int" : "A char"; 25 | std::cout << s << '\n'; 26 | } 27 | 28 | void foo( TestStruct m ) 29 | { 30 | TestStruct t{ true, {11}, {} }; 31 | bar( t ); 32 | } 33 | } 34 | 35 | 36 | int main ( int argc, char ** argv ) 37 | { 38 | int x{ 10 }; 39 | 40 | printf( "HOME: %s\n", getenv( "HOME" ) ); 41 | 42 | Test::TestStruct t{ true, {99}, { ' ', } }; 43 | foo( t ); // ADL! 44 | 45 | for ( int i = 0; i < 100 ; ++i ) { 46 | Test::foo( { true, {i}, {0} } ); 47 | } 48 | 49 | t.big[ sizeof(void*) * 0 ] = 'r'; 50 | t.big[ sizeof(void*) * 1 ] = 'o'; 51 | t.big[ sizeof(void*) * 2 ] = 'f'; 52 | t.big[ sizeof(void*) * 3 ] = 'l'; 53 | //t.big[ sizeof(void*) * 4 ] = '0'; 54 | 55 | std::cout << t.big << '\n'; 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /support/test/cpp/tiny_c/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "adapters": { 3 | "custom-codelldb": { 4 | "extends": "CodeLLDB", 5 | "command": [ 6 | "$HOME/Development/vimspector/CodeLLDB/build/adapter/codelldb", 7 | "--port", "${unusedLocalPort}" 8 | ] 9 | }, 10 | "custom-cpptools": { 11 | "extends": "vscode-cpptools", 12 | "command": [ 13 | "$HOME/Development/vimspector/MIEngine/bin/Debug/vscode/OpenDebugAD7" 14 | ] 15 | } 16 | }, 17 | "configurations": { 18 | "CodeLLDB": { 19 | "adapter": "custom-codelldb", 20 | "configuration": { 21 | "request": "launch", 22 | "program": "${workspaceRoot}/tiny" 23 | } 24 | }, 25 | "cpptools (lldb)": { 26 | "adapter": "custom-cpptools", 27 | "configuration": { 28 | "request": "launch", 29 | "program": "${workspaceRoot}/tiny", 30 | "stopAtEntry": true, 31 | "MIMode": "lldb", 32 | "MIDebuggerPath": "${gadgetDir}/vscode-cpptools/debugAdapters/lldb-mi/bin/lldb-mi", 33 | "logging": { 34 | "engineLogging": true 35 | } 36 | } 37 | }, 38 | "cpptools (gdb)": { 39 | "adapter": "custom-cpptools", 40 | "configuration": { 41 | "request": "launch", 42 | "program": "${workspaceRoot}/tiny", 43 | "stopAtEntry": true, 44 | "MIMode": "gdb" 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /support/test/cpp/tiny_c/tiny.c: -------------------------------------------------------------------------------- 1 | int main(int argc, char**argv) 2 | { 3 | return argc + 1; 4 | } 5 | -------------------------------------------------------------------------------- /support/test/csharp/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/Debug 3 | obj/ 4 | -------------------------------------------------------------------------------- /support/test/csharp/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "adapters": { 3 | "netcoredbg-debuglog": { 4 | "attach": { 5 | "pidProperty": "processId", 6 | "pidSelect": "ask" 7 | }, 8 | "command": [ 9 | "${gadgetDir}/netcoredbg/netcoredbg", 10 | "--interpreter=vscode", 11 | "--engineLogging=${workspaceRoot}/netcoredbg.engine.log", 12 | "--log=${workspaceRoot}/netcoredbg.log" 13 | ], 14 | "configuration": { 15 | "cwd": "${workspaceRoot}" 16 | }, 17 | "name": "netcoredbg" 18 | } 19 | }, 20 | "configurations": { 21 | // 22 | // NOTE: 23 | // If you add to this, you must update tests/get_configurations.test.vim 24 | // 25 | 26 | "launch - netcoredbg": { 27 | "adapter": "netcoredbg", 28 | "configuration": { 29 | "request": "launch", 30 | // If this changes, update language_csharp.test.vim 31 | "program": "${workspaceRoot}/bin/Debug/netcoreapp6.0/csharp.dll", 32 | "args": [], 33 | "stopAtEntry": false 34 | }, 35 | "breakpoints": { 36 | "exception": { 37 | "user-unhandled": "", 38 | "all": "" 39 | } 40 | } 41 | }, 42 | "launch - netcoredbg - with debug log": { 43 | "adapter": "netcoredbg-debuglog", 44 | "configuration": { 45 | "request": "launch", 46 | // If this changes, update language_csharp.test.vim 47 | "program": "${workspaceRoot}/bin/Debug/netcoreapp6.0/csharp.dll", 48 | "args": [], 49 | "stopAtEntry": false 50 | }, 51 | "breakpoints": { 52 | "exception": { 53 | "user-unhandled": "", 54 | "all": "" 55 | } 56 | } 57 | }, 58 | "launch - mono": { 59 | "adapter": "vscode-mono-debug", 60 | "configuration": { 61 | "request": "launch", 62 | "program": "${workspaceRoot}/Program.exe", 63 | "console": "integratedTerminal", 64 | "cwd": "${workspaceRoot}", 65 | "args": [], 66 | "env": {} 67 | }, 68 | "breakpoints": { 69 | "exception": { 70 | "user-unhandled": "", 71 | "all": "" 72 | } 73 | } 74 | } 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /support/test/csharp/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace csharp 4 | { 5 | class Program 6 | { 7 | string toaster = "Making round of toast"; 8 | static int max_bread = 100; 9 | int bread = max_bread; 10 | 11 | void PrintToast( int r ) { 12 | int this_round = ( max_bread - bread - r); 13 | Console.WriteLine( this.toaster + ": " + this_round ); 14 | } 15 | 16 | void MakeToast( int rounds ) { 17 | if (this.bread - rounds < 0) { 18 | throw new Exception( "No moar bread!" ); 19 | } 20 | 21 | this.bread -= rounds; 22 | for (int r = 0; r < rounds; ++r) { 23 | this.PrintToast( r ); 24 | } 25 | 26 | Console.WriteLine( "Got only " + this.bread + " left" ); 27 | } 28 | 29 | static void Main(string[] args) 30 | { 31 | Program p = new Program(); 32 | for (int x = 1; x < 10; ++ x) { 33 | p.MakeToast( x ); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /support/test/csharp/csharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp6.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /support/test/csharp/csharp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26124.0 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csharp", "csharp.csproj", "{91DB205F-E422-430B-BBB8-955110C7B3B6}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x64.ActiveCfg = Debug|Any CPU 24 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x64.Build.0 = Debug|Any CPU 25 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x86.ActiveCfg = Debug|Any CPU 26 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x86.Build.0 = Debug|Any CPU 27 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x64.ActiveCfg = Release|Any CPU 30 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x64.Build.0 = Release|Any CPU 31 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x86.ActiveCfg = Release|Any CPU 32 | {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x86.Build.0 = Release|Any CPU 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /support/test/example/attach.vim: -------------------------------------------------------------------------------- 1 | if argc() < 2 2 | echom 'Usage:' v:argv[ 0 ] 'processName binary' 3 | cquit! 4 | endif 5 | 6 | setfiletype cpp 7 | call vimspector#LaunchWithSettings( #{ 8 | \ configuration: 'C++ - Attach Local Process', 9 | \ processName: argv( 0 ), 10 | \ binary: argv( 1 ), 11 | \ } ) 12 | 13 | 1,2argd 14 | -------------------------------------------------------------------------------- /support/test/example/cpp.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "C++ - Attach Local Process": { 4 | "adapter": "vscode-cpptools", 5 | "variables": { 6 | "PID": { 7 | "shell": [ "GetPIDForProcess", "${processName}" ] 8 | } 9 | }, 10 | "configuration": { 11 | "name": "test", 12 | "request": "attach", 13 | "program": "${binary}", 14 | "processId": "${PID}", 15 | 16 | "type": "cppdbg", 17 | "stopAtEntry": true, 18 | "setupCommands": [ 19 | { "text": "source ${initFile}", "ignoreFailures": true } 20 | ] 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /support/test/go/Stdio/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", 3 | "configurations": { 4 | "Run": { 5 | "adapter": "delve", 6 | "configuration": { 7 | "request": "launch", 8 | "mode": "debug", 9 | "program": "${workspaceRoot}/cmd/main.go" 10 | } 11 | } 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /support/test/go/Stdio/cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strconv" 8 | ) 9 | 10 | func fibonacci(c, quit chan int) { 11 | x, y := 0, 1 12 | for { 13 | select { 14 | case c <- x: 15 | x, y = y, x+y 16 | case <-quit: 17 | fmt.Println("quit") 18 | return 19 | } 20 | } 21 | } 22 | 23 | func main() { 24 | c := make(chan int) 25 | quit := make(chan int) 26 | in := make(chan string) 27 | go func() { 28 | scanner := bufio.NewScanner(os.Stdin) 29 | for scanner.Scan() { 30 | fmt.Println( ":" ) 31 | in <- scanner.Text() 32 | } 33 | }() 34 | go func() { 35 | for { 36 | cmd, _ := <-in 37 | fmt.Println( "GOT: ", cmd ) 38 | if cmd == "quit" { 39 | quit <- 0 40 | return 41 | } 42 | n, err := strconv.Atoi(cmd) 43 | if err == nil { 44 | for i := 0; i < n ; i++ { 45 | fmt.Println(<-c) 46 | } 47 | } else { 48 | fmt.Println( "Unrecognised: ", cmd, err ) 49 | } 50 | } 51 | }() 52 | fibonacci(c, quit) 53 | } 54 | -------------------------------------------------------------------------------- /support/test/go/Stdio/go.mod: -------------------------------------------------------------------------------- 1 | module stdiotest 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /support/test/go/Stdio/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puremourning/vimspector/5e24df822e278ee79abfc8c7110089a5322d1a3c/support/test/go/Stdio/main -------------------------------------------------------------------------------- /support/test/go/hello_world/.gitignore: -------------------------------------------------------------------------------- 1 | hello_world 2 | -------------------------------------------------------------------------------- /support/test/go/hello_world/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "run-legacy": { 4 | "adapter": "vscode-go", 5 | "configuration": { 6 | "request": "launch", 7 | "program": "${workspaceRoot}/hello-world.go", 8 | "mode": "debug", 9 | "trace": true, 10 | "env": { "GO111MODULE": "off" } 11 | } 12 | }, 13 | "run-delve": { 14 | "adapter": "delve", 15 | "configuration": { 16 | "request": "launch", 17 | "env": { "GO111MODULE": "off" }, 18 | 19 | "mode": "debug", // debug|test 20 | "program": "${workspaceRoot}/hello-world.go" 21 | 22 | // "args": [], 23 | // "buildFlags": ... 24 | // "stackTraceDepth": ..., 25 | // "showGlobalVariables": true, 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /support/test/go/hello_world/hello-world.go: -------------------------------------------------------------------------------- 1 | package main 2 | import "fmt" 3 | func main() { 4 | var v = "test" 5 | fmt.Println("hello world: " + v) 6 | } 7 | -------------------------------------------------------------------------------- /support/test/go/name-starts-with-vowel/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "run-cmd": { 4 | "adapter": "vscode-go", 5 | "configuration": { 6 | "request": "launch", 7 | "program": "${workspaceRoot}/cmd/namestartswithvowel/main.go", 8 | "mode": "debug", 9 | "dlvToolPath": "$HOME/go/bin/dlv", 10 | "dlvLoadConfig": { 11 | "maxArrayValues": 1000, 12 | "maxStringLen": 1000 13 | } 14 | } 15 | }, 16 | "test-current-file": { 17 | "adapter": "vscode-go", 18 | "configuration": { 19 | "request": "launch", 20 | "mode": "test", 21 | "program": "${fileDirname}", 22 | "cwd": "${fileDirname}", 23 | "dlvToolPath": "$GOPATH/bin/dlv", 24 | "env": {}, 25 | "args": [] 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /support/test/go/name-starts-with-vowel/README.md: -------------------------------------------------------------------------------- 1 | # Purpose 2 | 3 | This example comes with two example vimspector configs for the Go programming language. 4 | 5 | 1) `run-cmd` will launch the main programme under `cmd/namestartswithvowel`. 6 | 1) `test-current-file` will run the tests in the current file in debug mode. 7 | 8 | ## Example use-cases 9 | 10 | ### run-cmd 11 | 12 | * Open `cmd/namestartswithvowel/main.go` 13 | * Add a breakpoint somewhere within the programme 14 | * Start the debugger (`:call vimspector#Continue()` or your relevant keymapping) 15 | * Select the first launch configuration (`1: run-cmd`) 16 | 17 | ### test-current-file 18 | 19 | * Open `internal/vowels/vowels_test.go` 20 | * Add a breakpoint somewhere within the test 21 | * Start the debugger (`:call vimspector#Continue()` or your relevant keymapping) 22 | * Select the second launch configuration (`2: test-current-file`) 23 | 24 | ## Additional Configuration 25 | 26 | There are two additional configuration options specified under `run-cmd`; these parameters configure the maximum string/array size to be shown while debugging. 27 | 28 | ``` 29 | "dlvLoadConfig": { 30 | "maxArrayValues": 1000, 31 | "maxStringLen": 1000 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "example.com/internal/vowels" 7 | ) 8 | 9 | func main() { 10 | names := []string{"Simon", "Bob", "Jennifer", "Amy", "Duke", "Elizabeth"} 11 | 12 | for _, n := range names { 13 | if vowels.NameStartsWithVowel(n) { 14 | fmt.Printf("%s starts with a vowel!\n", n) 15 | continue 16 | } 17 | 18 | fmt.Printf("%s does not start with a vowel!\n", n) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /support/test/go/name-starts-with-vowel/go.mod: -------------------------------------------------------------------------------- 1 | module example.com 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /support/test/go/name-starts-with-vowel/internal/vowels/vowels.go: -------------------------------------------------------------------------------- 1 | package vowels 2 | 3 | import "strings" 4 | 5 | func NameStartsWithVowel(name string) bool { 6 | s := strings.Split(strings.ToLower(name), "") 7 | 8 | return s[0] == "a" || s[0] == "e" || s[0] == "i" || s[0] == "o" || s[0] == "u" 9 | } 10 | -------------------------------------------------------------------------------- /support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go: -------------------------------------------------------------------------------- 1 | package vowels 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNameStartsWithVowel(t *testing.T) { 9 | testCases := []struct { 10 | input string 11 | expectedOutput bool 12 | }{ 13 | { 14 | input: "Simon", 15 | expectedOutput: false, 16 | }, 17 | { 18 | input: "Andy", 19 | expectedOutput: true, 20 | }, 21 | } 22 | for _, tt := range testCases { 23 | t.Run(fmt.Sprintf("%s should product %t", tt.input, tt.expectedOutput), func(t *testing.T) { 24 | out := NameStartsWithVowel(tt.input) 25 | if out != tt.expectedOutput { 26 | t.Errorf("%s produced %t, when %t was expected", tt.input, out, tt.expectedOutput) 27 | } 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /support/test/go/structs/.gitignore: -------------------------------------------------------------------------------- 1 | hello_world 2 | -------------------------------------------------------------------------------- /support/test/go/structs/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "run-legacy": { 4 | "adapter": "vscode-go", 5 | "configuration": { 6 | "request": "launch", 7 | "program": "${workspaceRoot}/hello-world.go", 8 | "mode": "debug", 9 | "trace": true, 10 | "env": { "GO111MODULE": "off" } 11 | } 12 | }, 13 | "run-delve": { 14 | "adapter": "delve", 15 | "configuration": { 16 | "request": "launch", 17 | "env": { "GO111MODULE": "off" }, 18 | 19 | "mode": "debug", // debug|test 20 | "program": "${workspaceRoot}/hello-world.go" 21 | 22 | // "args": [], 23 | // "buildFlags": ... 24 | // "stackTraceDepth": ..., 25 | // "showGlobalVariables": true, 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /support/test/go/structs/__debug_bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puremourning/vimspector/5e24df822e278ee79abfc8c7110089a5322d1a3c/support/test/go/structs/__debug_bin -------------------------------------------------------------------------------- /support/test/go/structs/hello-world.go: -------------------------------------------------------------------------------- 1 | package main 2 | import "fmt" 3 | 4 | type Toaster struct { 5 | Power int 6 | Colour string 7 | } 8 | 9 | type Test struct { 10 | Test string 11 | Toast Toaster 12 | } 13 | 14 | func main() { 15 | var v = "test" 16 | test := Test{ 17 | Test: "This is\na\ntest", 18 | Toast: Toaster{ 19 | Power: 10, 20 | Colour: "green", 21 | }, 22 | } 23 | fmt.Println("hello world: " + v) 24 | fmt.Println("Hi " + test.Test) 25 | } 26 | -------------------------------------------------------------------------------- /support/test/java/test_project/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .settings/ 4 | target/ 5 | -------------------------------------------------------------------------------- /support/test/java/test_project/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Java Launch": { 4 | "adapter": "vscode-java", 5 | "configuration": { 6 | "request": "launch", 7 | "mainClass": "com.vimspector.test.TestApplication", 8 | "sourcePaths": [ "${workspaceRoot}/src/main/java" ], 9 | "classPaths": [ "${workspaceRoot}/target/classes" ], 10 | "project": "TestApplication", 11 | "args": "hello world!", 12 | "stopOnEntry": true, 13 | "console": "integratedTerminal", 14 | "stepFilters": { 15 | "skipClasses": [ "$$JDK" ] 16 | } 17 | } 18 | }, 19 | "Java Attach": { 20 | "adapter": "vscode-java", 21 | "configuration": { 22 | "request": "attach", 23 | "sourcePaths": [ "${workspaceRoot}/src/main/java" ], 24 | "project": "TestApplication", 25 | "stopOnEntry": true, 26 | "hostName": "localhost", 27 | "port": "${JVMDebugPort}", 28 | "stepFilters": { 29 | "skipClasses": [ "$$JDK" ] 30 | } 31 | } 32 | }, 33 | "Attach with vscode-javac": { 34 | "adapter": "vscode-javac", 35 | "configuration": { 36 | "request": "attach", 37 | "project": "TestApplication", 38 | "port": "${debugPort}", 39 | "sourceRoots": [ 40 | "${workspaceRoot}/src/main/java" 41 | ] 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /support/test/java/test_project/java.vim: -------------------------------------------------------------------------------- 1 | let g:ycm_java_jdtls_extension_path = [ 2 | \ expand( ':p:h:h:h:h:h' ) . '/gadgets/macos' 3 | \ ] 4 | 5 | let s:jdt_ls_debugger_port = 0 6 | function! s:StartDebugging() 7 | if s:jdt_ls_debugger_port <= 0 8 | " Get the DAP port 9 | let s:jdt_ls_debugger_port = youcompleteme#GetCommandResponse( 10 | \ 'ExecuteCommand', 11 | \ 'vscode.java.startDebugSession' ) 12 | 13 | if s:jdt_ls_debugger_port == '' 14 | echom 'Unable to get DAP port - is YCM initialized?' 15 | let s:jdt_ls_debugger_port = 0 16 | return 17 | endif 18 | endif 19 | 20 | " Start debugging with the DAP port 21 | call vimspector#LaunchWithSettings( { 'DAPPort': s:jdt_ls_debugger_port } ) 22 | endfunction 23 | 24 | nnoremap :call StartDebugging() 25 | -------------------------------------------------------------------------------- /support/test/java/test_project/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | com.vimspector.test 4 | TestApplication 5 | 1 6 | 7 | 17 8 | 17 9 | 10 | 11 | -------------------------------------------------------------------------------- /support/test/java/test_project/src/main/java/com/vimspector/test/Base.java: -------------------------------------------------------------------------------- 1 | package com.vimspector.test; 2 | 3 | public class Base 4 | { 5 | public String DoSomething() 6 | { 7 | String s = new String(); 8 | s.replace( "A", "B" ); 9 | return s; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /support/test/java/test_project/src/main/java/com/vimspector/test/TestApplication.java: -------------------------------------------------------------------------------- 1 | package com.vimspector.test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | public class TestApplication { 8 | private static List getAdditionalArgs() { 9 | List list = new ArrayList<>(); 10 | for( Map.Entry e : System.getenv().entrySet() ) { 11 | list.add( e.getKey() + " = " + e.getValue() ); 12 | } 13 | return list; 14 | } 15 | 16 | private static class Bass extends Base { 17 | String bass = "Pump"; 18 | @Override 19 | public String DoSomething() { 20 | if ( Math.random() % 3 == 0 ) { 21 | return bass; 22 | } 23 | return super.DoSomething(); 24 | } 25 | } 26 | 27 | private static void DoGeneric( T b ) { 28 | TestGeneric foo = new TestGeneric<>( b ); 29 | foo.DoSomethingUseful(); 30 | } 31 | 32 | public static void main( String[] args ) { 33 | int numEntries = 0; 34 | for ( String s : args ) { 35 | System.out.println( "Arg: " + s ); 36 | ++numEntries; 37 | } 38 | for ( String s : TestApplication.getAdditionalArgs() ) { 39 | System.out.println( "Env: " + s ); 40 | ++numEntries; 41 | } 42 | System.out.println( "Number of entries: " + numEntries ); 43 | 44 | DoGeneric( new Bass() ); 45 | } 46 | } 47 | 48 | 49 | -------------------------------------------------------------------------------- /support/test/java/test_project/src/main/java/com/vimspector/test/TestGeneric.java: -------------------------------------------------------------------------------- 1 | package com.vimspector.test; 2 | 3 | class TestGeneric { 4 | T base; 5 | 6 | public TestGeneric( T b ) 7 | { 8 | this.base = b; 9 | } 10 | 11 | public String DoSomethingUseful() { 12 | String s = "A B C" + base.DoSomething(); 13 | 14 | return s.replace( "B", "C" ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /support/test/kotlin/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build 3 | -------------------------------------------------------------------------------- /support/test/kotlin/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "kotlin-debug-adapter launch": { 4 | "adapter": "cust_kotlin-debug-adapter", 5 | "configuration": { 6 | "request": "launch", 7 | "projectRoot": "${workspaceFolder}", 8 | "mainClass": "vimspector/test/ApplicationKt" 9 | } 10 | }, 11 | "kotlin-debug-adapter attach": { 12 | "adapter": "cust_kotlin-debug-adapter", 13 | "configuration": { 14 | "request": "attach", 15 | "projectRoot": "${workspaceFolder}", 16 | "hostName": "${hostName}", 17 | "port": "${port}" 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /support/test/kotlin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") version "1.4.0" 3 | 4 | application 5 | } 6 | 7 | repositories { 8 | // Use jcenter for resolving dependencies. 9 | // You can declare any Maven/Ivy/file repository here. 10 | jcenter() 11 | } 12 | 13 | dependencies { 14 | // Align versions of all Kotlin components 15 | implementation(platform("org.jetbrains.kotlin:kotlin-bom")) 16 | 17 | // Use the Kotlin JDK 8 standard library. 18 | implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") 19 | } 20 | 21 | application { 22 | // Define the main class for the application. 23 | mainClassName = "vimspector.test.ApplicationKt" 24 | } 25 | 26 | -------------------------------------------------------------------------------- /support/test/kotlin/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "vimspector-test" 2 | -------------------------------------------------------------------------------- /support/test/kotlin/src/main/kotlin/vimspector/test/Application.kt: -------------------------------------------------------------------------------- 1 | package vimspector.test 2 | 3 | fun main(args: Array) { 4 | println("Hello World!") 5 | } 6 | -------------------------------------------------------------------------------- /support/test/lua/love-headless/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#", 3 | "configurations": { 4 | "love": { 5 | "adapter": "lua-local", 6 | "configuration": { 7 | "request": "launch", 8 | "type": "lua-local", 9 | "cwd": "${workspaceFolder}", 10 | "program": { 11 | "command": "love" 12 | }, 13 | "args": ["${workspaceFolder}"], 14 | "stopOnEntry": false 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /support/test/lua/love-headless/conf.lua: -------------------------------------------------------------------------------- 1 | function love.conf(t) 2 | t.modules.audio = false 3 | t.modules.font = false 4 | t.modules.graphics = false 5 | t.modules.image = false 6 | t.modules.mouse = false 7 | t.modules.physics = false 8 | t.modules.sound = false 9 | t.modules.touch = false 10 | t.modules.video = false 11 | t.modules.window = false 12 | end 13 | -------------------------------------------------------------------------------- /support/test/lua/love-headless/main.lua: -------------------------------------------------------------------------------- 1 | if pcall(require, 'lldebugger') then 2 | require('lldebugger').start() 3 | end 4 | 5 | local time = 0 6 | 7 | function love.update(dt) 8 | time = time + dt 9 | love.event.quit() 10 | end 11 | -------------------------------------------------------------------------------- /support/test/lua/love/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#", 3 | "configurations": { 4 | "love": { 5 | "adapter": "lua-local", 6 | "configuration": { 7 | "request": "launch", 8 | "type": "lua-local", 9 | "cwd": "${workspaceFolder}", 10 | "program": { 11 | "command": "love" 12 | }, 13 | "args": ["${workspaceFolder}"], 14 | "stopOnEntry": false 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /support/test/lua/love/main.lua: -------------------------------------------------------------------------------- 1 | if pcall(require, 'lldebugger') then 2 | require('lldebugger').start() 3 | end 4 | 5 | local rect = {0, 0, 64, 64} 6 | 7 | 8 | function love.update(dt) 9 | rect[1] = rect[1] + 10 * dt 10 | rect[2] = rect[2] + 10 * dt 11 | end 12 | 13 | 14 | function love.draw() 15 | love.graphics.rectangle('fill', rect[1], rect[2], rect[3], rect[4]) 16 | end 17 | 18 | 19 | function love.keypressed() 20 | love.event.quit() 21 | end 22 | -------------------------------------------------------------------------------- /support/test/lua/simple/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#", 3 | "configurations": { 4 | "lua": { 5 | "adapter": "lua-local", 6 | "configuration": { 7 | "request": "launch", 8 | "type": "lua-local", 9 | "cwd": "${workspaceFolder}", 10 | "program": { 11 | "lua": "lua", 12 | "file": "simple.lua", 13 | "stopOnEntry": false 14 | } 15 | } 16 | }, 17 | "luajit": { 18 | "adapter": "lua-local", 19 | "configuration": { 20 | "request": "launch", 21 | "type": "lua-local", 22 | "cwd": "${workspaceFolder}", 23 | "program": { 24 | "lua": "luajit", 25 | "file": "simple.lua", 26 | "stopOnEntry": false 27 | } 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /support/test/lua/simple/simple.lua: -------------------------------------------------------------------------------- 1 | local separator = ' ' 2 | 3 | 4 | local function createMessage() 5 | local words = {} 6 | table.insert(words, 'Hello') 7 | table.insert(words, 'world') 8 | return table.concat(words, separator) 9 | end 10 | 11 | 12 | local function withEmphasis(func) 13 | return function() 14 | return func() .. '!' 15 | end 16 | end 17 | 18 | 19 | createMessage = withEmphasis(createMessage) 20 | 21 | print(createMessage()) 22 | -------------------------------------------------------------------------------- /support/test/multiple_filetypes/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Node": { 4 | "adapter": "js-debug", 5 | "filetypes": [ "javascript" ], 6 | "default": true, 7 | "configuration": { 8 | "request": "launch", 9 | "stopOnEntry": false, 10 | "console": "integratedTerminal", 11 | "program": "${workspaceRoot}/test.js", 12 | "cwd": "${workspaceRoot}" 13 | }, 14 | "breakpoints": { 15 | "exception": { 16 | "all": "", 17 | "uncaught": "" 18 | } 19 | } 20 | }, 21 | "Python": { 22 | "adapter": "debugpy", 23 | "filetypes": [ "python" ], 24 | "default": true, 25 | "configuration": { 26 | "request": "launch", 27 | "program": "${workspaceRoot}/test.py", 28 | "stopOnEntry": false, 29 | "cwd": "${workspaceRoot}" 30 | }, 31 | "breakpoints": { 32 | "exception": { 33 | "raised": "N", 34 | "uncaught": "", 35 | "userUnhandled": "" 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /support/test/multiple_filetypes/test.js: -------------------------------------------------------------------------------- 1 | console.log( "Hello" ); 2 | console.log( "From" ); 3 | console.log( "JavaScript" ); 4 | -------------------------------------------------------------------------------- /support/test/multiple_filetypes/test.py: -------------------------------------------------------------------------------- 1 | def Main(): 2 | print( "Hello" ) 3 | print( "From" ) 4 | print( "Python" ) 5 | 6 | 7 | Main() 8 | -------------------------------------------------------------------------------- /support/test/node/multiprocess/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "run - js-ddbug": { 4 | "adapter": "js-debug", 5 | "configuration": { 6 | "request": "launch", 7 | "program": "${workspaceRoot}/multi.js", 8 | "cwd": "${workspaceRoot}", 9 | "console": "intergaredTerminal" 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /support/test/node/multiprocess/multi.js: -------------------------------------------------------------------------------- 1 | const cluster = require('node:cluster'); 2 | const http = require('node:http'); 3 | const process = require('node:process'); 4 | 5 | const fibSlow = function( i ) { 6 | if ( i < 2 ) { 7 | return i; 8 | } 9 | return fibSlow( i - 1 ) + fibSlow( i - 2 ) 10 | } 11 | 12 | if (cluster.isPrimary) { 13 | console.log(`Primary ${process.pid} is running`); 14 | 15 | // Fork workers. 16 | const numWorkers = 4; 17 | workers = [] 18 | for (let i = 0; i < numWorkers; i++) { 19 | const worker = cluster.fork(); 20 | worker.on( 'message', (msg) => { 21 | console.log(`worker ${i} calculated: fib(${msg[0]}) = ${msg[1]}`); 22 | } ); 23 | workers.push( worker ); 24 | } 25 | 26 | cluster.on('exit', (worker, code, signal) => { 27 | console.log(`worker ${worker.process.pid} died`); 28 | }); 29 | 30 | for ( let i = 0 ; i < 20 ; ++ i ) { 31 | workers[ i % numWorkers ].send( i ); 32 | } 33 | } else { 34 | console.log(`Worker ${process.pid} started`); 35 | process.on( 'message', (msg) => { 36 | process.send( [ msg, fibSlow( msg ) ] ); 37 | } ); 38 | } 39 | -------------------------------------------------------------------------------- /support/test/node/simple/.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": { 3 | "node": {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /support/test/node/simple/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "run - legacy": { 4 | "adapter": "vscode-node", 5 | "configuration": { 6 | "request": "launch", 7 | "protocol": "auto", 8 | "stopOnEntry": true, 9 | "console": "integratedTerminal", 10 | "program": "${workspaceRoot}/simple.js", 11 | "cwd": "${workspaceRoot}" 12 | } 13 | }, 14 | "run - js-debug": { 15 | "adapter": "js-debug", 16 | "configuration": { 17 | "request": "launch", 18 | "program": "${workspaceRoot}/simple.js", 19 | "cwd": "${workspaceRoot}", 20 | "stopOnEntry": false 21 | }, 22 | "breakpoints": { 23 | "exception": { 24 | "all": "", 25 | "uncaught": "" 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /support/test/node/simple/simple.js: -------------------------------------------------------------------------------- 1 | var msg = 'Hello, world!' 2 | 3 | var obj = { 4 | test: 'testing', 5 | toast: function() { 6 | return 'toasty' + this.test; 7 | } 8 | } 9 | 10 | console.log( "OK stuff happened " + obj.toast() ) 11 | -------------------------------------------------------------------------------- /support/test/node/typescript/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | package-lock.json 4 | -------------------------------------------------------------------------------- /support/test/node/typescript/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "run - js-debug": { 4 | "adapter": "js-debug", 5 | "filetypes": [ "javascript", "typescript" ], 6 | "configuration": { 7 | "request": "launch", 8 | "program": "${workspaceRoot}/src/index.ts", 9 | "cwd": "${workspaceRoot}", 10 | "stopOnEntry": false, 11 | "type": "pwa-node" 12 | }, 13 | // 'breakpoints' is an optional part. This is a way to configure exception 14 | // breakpoints. You can leave this out or set as you prefer. 15 | "breakpoints": { 16 | "exception": { 17 | "all": "N", 18 | "uncaught": "N" 19 | } 20 | } 21 | } 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /support/test/node/typescript/README.md: -------------------------------------------------------------------------------- 1 | # Howto 2 | 3 | This example shows you how to use vimspector with 4 | [vscode-js-debug](https://github.com/microsoft/vscode-js-debug). For all 5 | available options see 6 | [here](https://github.com/microsoft/vscode-js-debug/blob/main/OPTIONS.md#node-launch). 7 | 8 | ## Prerequisites 9 | 10 | - Have nodejs installed (was tested with 18 and 20). 11 | - Ensure you have vscode-js-debug installed, check installation guides for 12 | nodejs of the vimspector repo on how to do so. 13 | - Install dependencies `npm i`. 14 | 15 | ## Debugging 16 | 17 | - Build the project `npm run build` 18 | - Open the typescript file with vim `vim ./src/index.ts` 19 | - Set breakpoints at line 2 and 3 (standard key mapping is F9) 20 | - Run debugging (standard key mapping is F5) 21 | - Press F5 once again (you should see console log output) 22 | - Press F5 once again (you should see another console log output) 23 | - Done🎉 24 | -------------------------------------------------------------------------------- /support/test/node/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vimspector-typescript-test", 3 | "author": "Pierre Dahmani ", 4 | "version": "1.0.0", 5 | "main": "dist/index.js", 6 | "license": "Apache-2.0", 7 | "scripts": { 8 | "build": "tsc" 9 | }, 10 | "dependencies": {}, 11 | "devDependencies": { 12 | "@tsconfig/node18": "2.0.0", 13 | "typescript": "5.3.3", 14 | "@types/node": "18.16.8" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /support/test/node/typescript/src/index.ts: -------------------------------------------------------------------------------- 1 | const main = () => { 2 | console.log(new Date().toISOString() + " Debugging typescript with vimspector🎉") 3 | console.log(new Date().toISOString() + " Done!") 4 | } 5 | 6 | main() 7 | -------------------------------------------------------------------------------- /support/test/node/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node18/tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "outDir": "dist", 6 | "sourceMap": true, 7 | "baseUrl": "." 8 | }, 9 | "include": ["src", "test"], 10 | "exclude": ["dist", "bundle", "node_modules"] 11 | } 12 | 13 | -------------------------------------------------------------------------------- /support/test/php/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Run current scipt": { 4 | "adapter": "vscode-php-debug", 5 | "configuration": { 6 | "request": "launch", 7 | "program": "${file}", 8 | "args": [], 9 | "stopOnEntry": false, 10 | "externalConsole": true 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /support/test/php/99-xdebug.ini: -------------------------------------------------------------------------------- 1 | zend_extension="xdebug.so" 2 | xdebug.mode = debug 3 | xdebug.start_with_request = yes 4 | -------------------------------------------------------------------------------- /support/test/php/test.php: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /support/test/python/django/.gitignore: -------------------------------------------------------------------------------- 1 | env/ 2 | -------------------------------------------------------------------------------- /support/test/python/django/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", 3 | "configurations": { 4 | "RunServer": { 5 | "adapter": "debugpy", 6 | "configuration": { 7 | "request": "launch", 8 | "python": "${workspaceRoot}/env/bin/python", 9 | "program": "${workspaceRoot}/mysite/manage.py", 10 | "args": [ 11 | "runserver", 12 | "localhost:5555" 13 | ], 14 | "django": true 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/mysite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puremourning/vimspector/5e24df822e278ee79abfc8c7110089a5322d1a3c/support/test/python/django/mysite/mysite/__init__.py -------------------------------------------------------------------------------- /support/test/python/django/mysite/mysite/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for mysite project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/mysite/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for mysite project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.2. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.2/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.2/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'django-insecure-_49xn676-(ten85y!l&8k#9ep*(fd86$oir2nm!$4bu#jj!wop' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | ] 41 | 42 | MIDDLEWARE = [ 43 | 'django.middleware.security.SecurityMiddleware', 44 | 'django.contrib.sessions.middleware.SessionMiddleware', 45 | 'django.middleware.common.CommonMiddleware', 46 | 'django.middleware.csrf.CsrfViewMiddleware', 47 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 48 | 'django.contrib.messages.middleware.MessageMiddleware', 49 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 50 | ] 51 | 52 | ROOT_URLCONF = 'mysite.urls' 53 | 54 | TEMPLATES = [ 55 | { 56 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 57 | 'DIRS': [], 58 | 'APP_DIRS': True, 59 | 'OPTIONS': { 60 | 'context_processors': [ 61 | 'django.template.context_processors.debug', 62 | 'django.template.context_processors.request', 63 | 'django.contrib.auth.context_processors.auth', 64 | 'django.contrib.messages.context_processors.messages', 65 | ], 66 | }, 67 | }, 68 | ] 69 | 70 | WSGI_APPLICATION = 'mysite.wsgi.application' 71 | 72 | 73 | # Database 74 | # https://docs.djangoproject.com/en/4.2/ref/settings/#databases 75 | 76 | DATABASES = { 77 | 'default': { 78 | 'ENGINE': 'django.db.backends.sqlite3', 79 | 'NAME': BASE_DIR / 'db.sqlite3', 80 | } 81 | } 82 | 83 | 84 | # Password validation 85 | # https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators 86 | 87 | AUTH_PASSWORD_VALIDATORS = [ 88 | { 89 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 90 | }, 91 | { 92 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 93 | }, 94 | { 95 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 96 | }, 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 99 | }, 100 | ] 101 | 102 | 103 | # Internationalization 104 | # https://docs.djangoproject.com/en/4.2/topics/i18n/ 105 | 106 | LANGUAGE_CODE = 'en-us' 107 | 108 | TIME_ZONE = 'UTC' 109 | 110 | USE_I18N = True 111 | 112 | USE_TZ = True 113 | 114 | 115 | # Static files (CSS, JavaScript, Images) 116 | # https://docs.djangoproject.com/en/4.2/howto/static-files/ 117 | 118 | STATIC_URL = 'static/' 119 | 120 | # Default primary key field type 121 | # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field 122 | 123 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 124 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/mysite/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URL configuration for mysite project. 3 | 4 | The `urlpatterns` list routes URLs to views. For more information please see: 5 | https://docs.djangoproject.com/en/4.2/topics/http/urls/ 6 | Examples: 7 | Function views 8 | 1. Add an import: from my_app import views 9 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 10 | Class-based views 11 | 1. Add an import: from other_app.views import Home 12 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 13 | Including another URLconf 14 | 1. Import the include() function: from django.urls import include, path 15 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 16 | """ 17 | from django.contrib import admin 18 | from django.urls import include, path 19 | 20 | urlpatterns = [ 21 | path('polls/', include( "polls.urls" ) ), 22 | path('admin/', admin.site.urls), 23 | ] 24 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/mysite/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for mysite project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/polls/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puremourning/vimspector/5e24df822e278ee79abfc8c7110089a5322d1a3c/support/test/python/django/mysite/polls/__init__.py -------------------------------------------------------------------------------- /support/test/python/django/mysite/polls/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/polls/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PollsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'polls' 7 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/polls/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puremourning/vimspector/5e24df822e278ee79abfc8c7110089a5322d1a3c/support/test/python/django/mysite/polls/migrations/__init__.py -------------------------------------------------------------------------------- /support/test/python/django/mysite/polls/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/polls/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/polls/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | urlpatterns = [ 6 | path("", views.index, name="index"), 7 | ] 8 | -------------------------------------------------------------------------------- /support/test/python/django/mysite/polls/views.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | 3 | 4 | def index(request): 5 | return HttpResponse("Hello, world. You're at the poop index.") 6 | -------------------------------------------------------------------------------- /support/test/python/django/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==4.2.17 2 | -------------------------------------------------------------------------------- /support/test/python/django/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pushd $(dirname $0) 4 | if [ -d env ]; then 5 | rm -rf env 6 | fi 7 | 8 | python3 -m venv env 9 | . env/bin/activate 10 | python -m pip install -r requirements.txt 11 | popd 12 | -------------------------------------------------------------------------------- /support/test/python/multiple_files/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "run": { 4 | "adapter": "debugpy", 5 | "default": true, 6 | "configuration": { 7 | "request": "launch", 8 | "program": "${workspaceRoot}/moo.py", 9 | "cwd": "${workspaceRoot}", 10 | "stopOnEntry": true 11 | }, 12 | "breakpoints": { 13 | "exception": { 14 | "raised": "N", 15 | "uncaught": "", 16 | "userUnhandled": "" 17 | } 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /support/test/python/multiple_files/cow.py: -------------------------------------------------------------------------------- 1 | def Say( *args, **kwargs ): 2 | print( *args, **kwargs ) 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | def Quiet(): 15 | pass 16 | -------------------------------------------------------------------------------- /support/test/python/multiple_files/moo.py: -------------------------------------------------------------------------------- 1 | import cow 2 | 3 | 4 | def Moo(): 5 | for i in range( 1, 100 ): 6 | cow.Say( 'Moo' ) 7 | 8 | for i in range( 1, 100 ): 9 | cow.Say( 'Ooom' ) 10 | 11 | 12 | if __name__ == '__main__': 13 | Moo() 14 | -------------------------------------------------------------------------------- /support/test/python/multiprocessing/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", 3 | "configurations": { 4 | "run-to-breakpoint": { 5 | "adapter": "debugpy", 6 | "configuration": { 7 | "request": "launch", 8 | "cwd": "${workspaceRoot}", 9 | "program": "${file}", 10 | "stopOnEntry": false, 11 | "console": "integratedTerminal" 12 | }, 13 | "breakpoints": { 14 | "exception": { 15 | "raised": "N", 16 | "uncaught": "Y", 17 | "userUnhandled": "" 18 | } 19 | } 20 | }, 21 | "run-to-start": { 22 | "extends": "run-to-breakpoint", 23 | "configuration": { 24 | "stopOnEntry": true 25 | } 26 | }, 27 | "attach": { 28 | "adapter": "multi-session", 29 | "configuration": { 30 | "request": "attach", 31 | "type": "python", 32 | "cwd": "${workspaceRoot}", 33 | "program": "${file}", 34 | "stopOnEntry": true, 35 | "console": "integratedTerminal", 36 | "subProcess": true 37 | }, 38 | "breakpoints": { 39 | "exception": { 40 | "raised": "N", 41 | "uncaught": "Y", 42 | "userUnhandled": "" 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /support/test/python/multiprocessing/multiprocessing_ception.py: -------------------------------------------------------------------------------- 1 | import time 2 | import multiprocessing as mp 3 | 4 | 5 | def Priant( where, i ): 6 | print( f"in {where} x is {i}" ) 7 | 8 | 9 | def First( inst, remaining ): 10 | print( f"I{inst}C{remaining} starting" ) 11 | p2 = None 12 | if remaining > 1: 13 | p2 = mp.Process( target=First, args=( inst, remaining - 1, ), name='SubSub' ) 14 | p2.start() 15 | 16 | for i in range( 10 ): 17 | Priant( f'First I{inst}C{remaining}', i ) 18 | time.sleep( 0.1 ) 19 | 20 | if p2: 21 | p2.join() 22 | 23 | print( f"I{inst}C{remaining} done" ) 24 | 25 | 26 | if __name__ == '__main__': 27 | # Even though this is supposedly buggy on macOS, it's required to avoid an 28 | # additional sub-process which makes testing awkward 29 | print( "main" ) 30 | ps = [] 31 | for p in range( 5 ): 32 | px = mp.Process( target=First, args=( p, 3, ), name='Sub' ) 33 | px.start() 34 | 35 | print( f"Main starting with len( mp.active_children() ) active children" ) 36 | 37 | for i in range( 10 ): 38 | Priant( 'main', i ) 39 | time.sleep( 0.5 ) 40 | 41 | for p in ps: 42 | p.join() 43 | 44 | print( "MainDone" ) 45 | -------------------------------------------------------------------------------- /support/test/python/multiprocessing/multiprocessing_test.py: -------------------------------------------------------------------------------- 1 | import time 2 | import multiprocessing as mp 3 | 4 | 5 | def Priant( where, i ): 6 | print( f"in {where} x is {i}" ) 7 | 8 | 9 | def First(): 10 | for i in range( 10 ): 11 | Priant( 'First', i ) 12 | time.sleep( 0.1 ) 13 | 14 | 15 | if __name__ == '__main__': 16 | # Even though this is supposedly buggy on macOS, it's required to avoid an 17 | # additional sub-process which makes testing awkward 18 | ctx = mp.get_context( 'fork' ) 19 | print( "main" ) 20 | p1 = ctx.Process( target=First, name='Sub' ) 21 | 22 | p1.start() 23 | 24 | print( ctx.current_process() ) 25 | print( ctx.active_children() ) 26 | 27 | for i in range( 20 ): 28 | Priant( 'main', i ) 29 | time.sleep( 0.5 ) 30 | 31 | p1.join() 32 | 33 | print( "Done" ) 34 | -------------------------------------------------------------------------------- /support/test/python/no_conf/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | class TestClass( object ): 5 | def __init__( self, value ): 6 | self._var = value 7 | try: 8 | self.DoSomething() 9 | except ValueError: 10 | pass 11 | 12 | def DoSomething( self ): 13 | for i in range( 0, 100 ): 14 | if i < self._var: 15 | print( '{0} is less than the value'.format( i ) ) 16 | else: 17 | print( '{0} might be more'.format( i ) ) 18 | 19 | raise ValueError( 'Done' ) 20 | 21 | 22 | def Main(): 23 | t = TestClass( 18 ) 24 | 25 | t._var = 99 26 | t.DoSomething() 27 | 28 | 29 | Main() 30 | -------------------------------------------------------------------------------- /support/test/python/simple_python/.gitignore: -------------------------------------------------------------------------------- 1 | env/ 2 | -------------------------------------------------------------------------------- /support/test/python/simple_python/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | RUN apt-get update && \ 4 | apt-get -y dist-upgrade && \ 5 | apt-get -y install sudo \ 6 | lsb-release \ 7 | ca-certificates \ 8 | python3-dev \ 9 | python3-pip \ 10 | ca-cacert \ 11 | locales \ 12 | language-pack-en \ 13 | libncurses5-dev libncursesw5-dev \ 14 | git && \ 15 | apt-get -y autoremove 16 | 17 | ## cleanup of files from setup 18 | RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 19 | 20 | RUN pip3 install debugpy 21 | 22 | ADD main.py /root/main.py 23 | -------------------------------------------------------------------------------- /support/test/python/simple_python/build-container: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [ "$1" = "--continue" ]; then 6 | OPTS="" 7 | else 8 | OPTS="--no-cache" 9 | fi 10 | 11 | docker build ${OPTS} -t puremourning/vimspector:simple_python . 12 | -------------------------------------------------------------------------------- /support/test/python/simple_python/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | class TestClass( object ): 5 | def __init__( self, value ): 6 | self._var = value 7 | try: 8 | self.DoSomething() 9 | except ValueError: 10 | pass 11 | 12 | def DoSomething( self ): 13 | for i in range( 0, 100 ): 14 | if i < self._var: 15 | print( '{0} is less than the value'.format( i ) ) 16 | else: 17 | print( '{0} might be more'.format( i ) ) 18 | 19 | raise ValueError( 'Done' ) 20 | 21 | 22 | def Main(): 23 | t = TestClass( 18 ) 24 | 25 | t._var = 99 26 | t.DoSomething() 27 | 28 | 29 | Main() 30 | -------------------------------------------------------------------------------- /support/test/python/simple_python/make_env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cat <<"EOF" 4 | { 5 | "Something": "Value1", 6 | "SomethingElse": "Value2" 7 | } 8 | EOF 9 | 10 | -------------------------------------------------------------------------------- /support/test/python/simple_python/print_env.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | 5 | 6 | def Main(): 7 | print( os.environ.get( 'Something', 'ERROR' ) ) 8 | print( os.environ.get( 'SomethingElse', 'ERROR' ) ) 9 | print( os.environ.get( 'PATH', 'ERROR' ) ) 10 | 11 | for k, v in os.environ.items(): 12 | print( f'{ k } = "{ v }"' ) 13 | 14 | 15 | Main() 16 | 17 | -------------------------------------------------------------------------------- /support/test/python/simple_python/requirements.txt: -------------------------------------------------------------------------------- 1 | debugpy 2 | -------------------------------------------------------------------------------- /support/test/python/simple_python/run-container: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [ "$1" = "--continue" ]; then 6 | OPTS="" 7 | else 8 | OPTS="--no-cache" 9 | fi 10 | 11 | docker run -p 8765:8765 --rm -it puremourning/vimspector:simple_python 12 | -------------------------------------------------------------------------------- /support/test/python/simple_python/run_with_debugpy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ -z "$DEBUG_PORT" ]; then 4 | DEBUG_PORT=5678 5 | fi 6 | 7 | pushd $(dirname $0) 8 | if [ -d env ]; then 9 | rm -rf env 10 | fi 11 | 12 | python3 -m venv env 13 | . env/bin/activate 14 | python -m pip install -r requirements.txt 15 | echo "using port $DEBUG_PORT" 16 | echo "*** Launching ***" 17 | python -m debugpy --wait-for-client --listen 0.0.0.0:${DEBUG_PORT} main.py 18 | popd 19 | 20 | -------------------------------------------------------------------------------- /support/test/ruby/.bundle/config: -------------------------------------------------------------------------------- 1 | --- 2 | BUNDLE_PATH: "vendor/bundle" 3 | -------------------------------------------------------------------------------- /support/test/ruby/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | vendor/ 3 | bin/ 4 | -------------------------------------------------------------------------------- /support/test/ruby/.ruby-version: -------------------------------------------------------------------------------- 1 | 3.2.2 2 | -------------------------------------------------------------------------------- /support/test/ruby/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", 3 | "adapters": { 4 | "rdbg-script": { 5 | "variables": { 6 | "port": "${unusedLocalPort}" 7 | }, 8 | "launch": { 9 | "remote": { 10 | "runCommand": [ 11 | "${workspaceRoot}/bin/rdbg", 12 | "--open", 13 | "--port", "${port}", 14 | "--", 15 | "%CMD%" 16 | ] 17 | } 18 | }, 19 | "port": "${port}" 20 | }, 21 | "rdbg-command": { 22 | "variables": { 23 | "port": "${unusedLocalPort}" 24 | }, 25 | "launch": { 26 | "remote": { 27 | "runCommand": [ 28 | "${workspaceRoot}/bin/rdbg", 29 | "--open", 30 | "--port", "${port}", 31 | "-c", 32 | "--", 33 | "%CMD%" 34 | ] 35 | } 36 | }, 37 | "port": "${port}" 38 | } 39 | }, 40 | "configurations": { 41 | "run current script": { 42 | "adapter": "rdbg-script", 43 | "remote-cmdLine": [ 44 | "${file}" 45 | ], 46 | "configuration": { 47 | "request": "launch" 48 | } 49 | }, 50 | "run rails": { 51 | "adapter": "rdbg-command", 52 | "remote-cmdLine": [ 53 | "rails", 54 | "server" 55 | ], 56 | "configuration": { 57 | "request": "launch" 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /support/test/ruby/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # gem "rails" 6 | 7 | gem "debug", "~> 1.9" 8 | -------------------------------------------------------------------------------- /support/test/ruby/install: -------------------------------------------------------------------------------- 1 | # First, make sure that ruby 3 is in your path 2 | 3 | bundle install 4 | bundle binstubs --force debug 5 | -------------------------------------------------------------------------------- /support/test/ruby/test.rb: -------------------------------------------------------------------------------- 1 | class Foo 2 | def initialize 3 | @bar = 'bar' 4 | end 5 | 6 | def bar 7 | @bar 8 | end 9 | end 10 | 11 | f = Foo.new 12 | puts f.bar 13 | -------------------------------------------------------------------------------- /support/test/run_test_vim: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | exec vim \ 4 | --clean \ 5 | --not-a-term \ 6 | --cmd "let g:vimspector_enable_mappings='HUMAN'" \ 7 | -Nu $(dirname $0)/../../tests/vimrc \ 8 | "$@" 9 | -------------------------------------------------------------------------------- /support/test/rust/vimspector_test/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /support/test/rust/vimspector_test/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", 3 | "adapters": { 4 | "CodeLLDB-localbuild": { 5 | "extends": "CodeLLDB", 6 | "command": [ 7 | "$HOME/Development/vimspector/CodeLLDB/build/adapter/codelldb", 8 | "--port", 9 | "${unusedLocalPort}" 10 | ] 11 | } 12 | }, 13 | "configurations": { 14 | "Run - CodeLLDB": { 15 | "adapter": "CodeLLDB", 16 | "configuration": { 17 | "request": "launch", 18 | "program": "${workspaceRoot}/target/debug/vimspector_test", 19 | "expressions": "native" 20 | } 21 | }, 22 | "CodeLLDB-localbuild": { 23 | "extends": "Run - CodeLLDB", 24 | "adapter": "CodeLLDB-localbuild" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /support/test/rust/vimspector_test/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "vimspector_test" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /support/test/rust/vimspector_test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vimspector_test" 3 | version = "0.1.0" 4 | authors = ["Ben Jackson "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /support/test/rust/vimspector_test/src/main.rs: -------------------------------------------------------------------------------- 1 | struct Point { 2 | x: i32, 3 | y: i32, 4 | } 5 | 6 | struct Foo { 7 | x: i32, 8 | } 9 | 10 | fn main() { 11 | let s = "World!"; 12 | println!("Hello, {}!", s); 13 | 14 | let f = Foo { x: 42 }; 15 | let g = &f; 16 | println!("Hello, {} {} {}!", s, g.x, f.x); 17 | 18 | let mut p = Point{ x: 1, y: 11 }; 19 | 20 | p.x = 11; 21 | p.y = 11; 22 | p.x += 11; 23 | p.y += 11; 24 | 25 | println!("Point: {}, {}", p.x, p.y); 26 | } 27 | -------------------------------------------------------------------------------- /support/test/tcl/.tclpro/extensions/test.pdx: -------------------------------------------------------------------------------- 1 | instrument::addExtension 2.0 {test} 2 | 3 | instrument::addCommand Wrap { parseBody } 4 | 5 | # vim: ft=tcl 6 | -------------------------------------------------------------------------------- /support/test/tcl/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Run Current Script": { 4 | "adapter": "tclpro", 5 | "configuration": { 6 | "request": "launch", 7 | "target": "${file}" 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /support/test/tcl/test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | 3 | set SCALAR g 4 | array set ARRAY {key1 value1 key2 value2} 5 | 6 | set LIST [list a b c {def} {g h i j} k l m] 7 | 8 | proc Wrap { body } { 9 | uplevel 1 $body 10 | } 11 | 12 | proc Main {} { 13 | global SCALAR 14 | set prefix "VAR: " 15 | Wrap { 16 | puts $SCALAR 17 | global ARRAY 18 | puts [array names ARRAY] 19 | 20 | set vars [list] 21 | foreach n [array names ::env] { 22 | set prefix "ENVVAR: $n = " 23 | puts "$prefix $::env($n)" 24 | lappend vars $n 25 | } 26 | } 27 | puts $vars 28 | } 29 | 30 | Main 31 | -------------------------------------------------------------------------------- /support/test/web/.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": { 3 | "browser": {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /support/test/web/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "chrome": { 4 | "adapter": "chrome", 5 | "configuration": { 6 | "request": "launch", 7 | "url": "http://localhost:1234/", 8 | "webRoot": "${workspaceRoot}/www" 9 | } 10 | }, 11 | "firefox": { 12 | "adapter": "firefox", 13 | "configuration": { 14 | "request": "launch", 15 | "url": "http://localhost:1234/", 16 | "webRoot": "${workspaceRoot}/www", 17 | "reAttach": true 18 | } 19 | }, 20 | "firefox-attach": { 21 | "adapter": "firefox", 22 | "configuration": { 23 | "request": "attach", 24 | "port": "${DebugPort}", 25 | "webRoot": "${workspaceRoot}/www", 26 | "reAttach": true 27 | } 28 | }, 29 | "jsdebug-attach": { 30 | "adapter": "js-debug", 31 | "configuration": { 32 | "request": "attach", 33 | "port": "${DebugPort}", 34 | "type": "pwa-chrome", 35 | "webRoot": "${workspaceRoot}/www" 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /support/test/web/run_server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | php -S localhost:1234 -t www 4 | -------------------------------------------------------------------------------- /support/test/web/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Hello, world! 12 | 13 | 14 |

Hello, world!

15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /support/test/web/www/js/test.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | var getMessage = function () { 3 | var msg = "this is "; 4 | msg += "a test"; 5 | msg += " message"; 6 | return msg; 7 | }; 8 | 9 | var obj = { 10 | test: getMessage(), 11 | toast: function () { 12 | return "egg"; 13 | }, 14 | spam: "ham", 15 | }; 16 | 17 | alert("test: " + obj.test); 18 | alert("toast: " + obj.toast()); 19 | }); 20 | 21 | function calculate(a, b) { 22 | var i = 0; 23 | while ( a > b ) { 24 | a -= b; 25 | i++; 26 | } 27 | return i; 28 | } 29 | -------------------------------------------------------------------------------- /support/test_python3.vim: -------------------------------------------------------------------------------- 1 | let &verbosefile=argv(0) 2 | " ffs neovim https://github.com/neovim/neovim/issues/14438 3 | let ignored_neovim_bug = py3eval( "0" ) 4 | execute 'cquit' py3eval( "0" ) 5 | cquit 6 | -------------------------------------------------------------------------------- /support/test_vscode_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "name": "some-name", 5 | "path": "/some/path" 6 | }, 7 | { 8 | "name": "src/include", 9 | "path": "/path/to/some/where" 10 | }, 11 | { 12 | "name": "some-other-name", 13 | "path": "/some/other/path" 14 | } 15 | ], 16 | "settings": { 17 | "terminal.integrated.env.linux": { 18 | "SOME_VAR": "/path/num/one", 19 | "SOME_OTHER_VAR":"/path/num/two" 20 | } 21 | }, 22 | "launch": { 23 | "configurations": [ 24 | { 25 | "name": "Attach", 26 | "type": "cppdbg", 27 | "request": "attach", 28 | "program": "/path/to/executable", 29 | "processId": "${command:pickProcess}", 30 | "MIMode": "gdb", 31 | "miDebuggerPath": "/path/to/gdb", 32 | "sourceFileMap": {}, 33 | "symbolLoadInfo": { 34 | "loadAll": false, 35 | "exceptionList": "some-lib.so;another-lib.so" 36 | }, 37 | "setupCommands": [ 38 | { 39 | "text": "breaksegv", 40 | "description": "Issue breaksegv helper", 41 | "ignoreFailures": true 42 | }, 43 | { 44 | "description": "Enable pretty-printing for gdb", 45 | "text": "-enable-pretty-printing", 46 | "ignoreFailures": true 47 | }, 48 | { 49 | "description": "Add file path directory", 50 | "text": "directory /path/to/root/of/repo", 51 | "ignoreFailures": true 52 | }, 53 | { 54 | "description": "Load sbtools source mapping", 55 | "text": "source /path/to/source-path.gdbinit", 56 | "ignoreFailures": true 57 | } 58 | ] 59 | }, 60 | { 61 | "name": "Launch", 62 | "type": "cppdbg", 63 | "request": "launch", 64 | "program": "/path/to/another/executable", 65 | "args": [], 66 | "cwd": "/path/to/root/of/repo", 67 | "environment": [], 68 | "externalConsole": false, 69 | "MIMode": "gdb", 70 | "miDebuggerPath": "/path/to/gdb", 71 | "sourceFileMap": {}, 72 | "symbolLoadInfo": { 73 | "loadAll": false, 74 | "exceptionList": "some-lib.so;another-lib.so" 75 | }, 76 | "setupCommands": [ 77 | { 78 | "text": "breaksegv", 79 | "description": "Issue breaksegv helper", 80 | "ignoreFailures": true 81 | }, 82 | { 83 | "description": "Enable pretty-printing for gdb", 84 | "text": "-enable-pretty-printing", 85 | "ignoreFailures": true 86 | }, 87 | { 88 | "description": "Load sbtools source mapping", 89 | "text": "source /path/to/source-path.gdbinit", 90 | "ignoreFailures": true 91 | } 92 | ] 93 | } 94 | ] 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /support/vimspector_process_list/.gitignore: -------------------------------------------------------------------------------- 1 | vimspector_process_list 2 | -------------------------------------------------------------------------------- /support/vimspector_process_list/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "run-delve": { 4 | "adapter": "delve", 5 | "filetypes": [ "go" ], 6 | "default": true, 7 | "cwd": "${workspaceRoot}", 8 | "configuration": { 9 | "request": "launch", 10 | 11 | 12 | "mode": "debug", // debug|test 13 | "program": "${workspaceRoot}/vimspector_process_list.go" 14 | 15 | // "args": [], 16 | // "buildFlags": ... 17 | // "stackTraceDepth": ..., 18 | // "showGlobalVariables": true, 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /support/vimspector_process_list/Makefile: -------------------------------------------------------------------------------- 1 | vimspector_process_list: vimspector_process_list.go go.mod 2 | go build 3 | 4 | .PHONY: clean 5 | clean: 6 | rm -f vimspector_process_list 7 | 8 | .PHONY: install 9 | install: vimspector_process_list 10 | go install 11 | -------------------------------------------------------------------------------- /support/vimspector_process_list/README.md: -------------------------------------------------------------------------------- 1 | # A simple process lister 2 | 3 | This directory contains a very very very simple process lister that _should_ 4 | work on macOS, Linux and Windows. 5 | 6 | It is _not_ indended to be a complete replacement for `ps` or similar tools, but 7 | may be useful if such tools are not available on your system. 8 | 9 | ## Build/installation 10 | 11 | Requires `go` to build it. Simply: 12 | 13 | * `cd` to this directory 14 | * `go build` 15 | 16 | Optionally, to "install it", just copy the binary to somewhere in your PATH, and 17 | vimspector will automatically start using it. 18 | 19 | If you just want to use it with Vimspector, then there's no need to "install" it 20 | anywhere: for convenience, Vimspector will also look in this directory if it 21 | doesn't find it in your path. 22 | 23 | ## Usage 24 | 25 | If the binary is found, Vimspector will use it when you put `"${PickProcess()}"` 26 | or `${PickProcess(\"someBinaryName\")}` as a replacement variable in your 27 | configuration. 28 | 29 | Usage: 30 | 31 | ``` 32 | vimspector_process_list [pattern] 33 | ``` 34 | 35 | It checks all PIDs and filters out: 36 | 37 | - Binaries which don't match the pattern (which is optional); The pattern is a 38 | go regular expression, applied to the image name (not the command line). 39 | - Processes for another user 40 | - Processes which are not running 41 | - Zombies 42 | 43 | Then it prints a table with columns: 44 | 45 | - `PID [(name)]`: The process ID, and if no pattern was supplied, the image 46 | name 47 | - `PPID (name)`: The parent process ID and name 48 | - `CMDLINE` or `CWD`: If a pattern was supplied, the working directory of the 49 | process, otherwise the command line (truncated to 40 chars). 50 | - `START`: The time the process was started 51 | 52 | Hopefully this is useful enough to identify your process amongs multiple 53 | instances. 54 | -------------------------------------------------------------------------------- /support/vimspector_process_list/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/puremourning/vimspector/support/vimspector_process_list 2 | 3 | go 1.19 4 | 5 | require github.com/shirou/gopsutil/v3 v3.24.5 6 | 7 | require ( 8 | github.com/go-ole/go-ole v1.3.0 // indirect 9 | github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect 10 | github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect 11 | github.com/shoenig/go-m1cpu v0.1.6 // indirect 12 | github.com/tklauser/go-sysconf v0.3.14 // indirect 13 | github.com/tklauser/numcpus v0.9.0 // indirect 14 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 15 | golang.org/x/sys v0.26.0 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /support/vimspector_process_list/vimspector_process_list.go: -------------------------------------------------------------------------------- 1 | // Vimspector process lister - a simple process lister 2 | // Copyright 2023 Ben Jackson (puremourning@gmail.com) 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | package main 17 | 18 | import ( 19 | "fmt" 20 | "os" 21 | "os/user" 22 | "regexp" 23 | "text/tabwriter" 24 | "time" 25 | 26 | "github.com/shirou/gopsutil/v3/process" 27 | ) 28 | 29 | const ( 30 | DateTime = "2006-01-02 15:04:05" 31 | ) 32 | 33 | func main() { 34 | pattern := ".*" 35 | pattern_supplied := false 36 | if len(os.Args) > 2 { 37 | fmt.Println("Usage: process_list ") 38 | return 39 | } else if len(os.Args) == 2 { 40 | pattern = os.Args[1] 41 | pattern_supplied = true 42 | } 43 | 44 | processes, _ := process.Processes() 45 | cur_user, _ := user.Current() 46 | w := tabwriter.NewWriter(os.Stdout, 0, 2, 1, ' ', 0) 47 | 48 | if pattern_supplied { 49 | fmt.Fprintf(w, "%v\t%v\t%v\t%v\n", "PID", "PPID", "CWD", "START") 50 | } else { 51 | fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n", "PID", "PPID", "NAME", "CMDLINE", "START") 52 | } 53 | 54 | for _, p := range processes { 55 | name, _ := p.Name() 56 | match, _ := regexp.MatchString(pattern, name) 57 | if !match { 58 | continue 59 | } 60 | 61 | if len(name) > 20 { 62 | name = name[:20] 63 | } 64 | 65 | cwd, _ := p.Cwd() 66 | pid := p.Pid 67 | ppid, _ := p.Ppid() 68 | status, _ := p.Status() 69 | cmdline, _ := p.Cmdline() 70 | if len(cmdline) > 40 { 71 | cmdline = cmdline[:40] 72 | } 73 | is_running, _ := p.IsRunning() 74 | utime, _ := p.CreateTime() 75 | dtime := time.UnixMilli(utime).Format(DateTime) 76 | 77 | username, _ := p.Username() 78 | 79 | parent, _ := process.NewProcess(ppid) 80 | pname, _ := parent.Name() 81 | 82 | if username == cur_user.Username && is_running && status[0] != "zombie" { 83 | if pattern_supplied { 84 | fmt.Fprintf(w, "%v\t%v (%v)\t%v\t%v\n", pid, ppid, pname, cwd, dtime) 85 | } else { 86 | fmt.Fprintf(w, "%v (%v)\t%v (%v)\t%v\t%v\n", pid, name, ppid, pname, cmdline, dtime) 87 | } 88 | } 89 | } 90 | w.Flush() 91 | } 92 | -------------------------------------------------------------------------------- /syntax/vimspector-breakpoints.vim: -------------------------------------------------------------------------------- 1 | if exists( 'b:current_syntax' ) 2 | finish 3 | endif 4 | 5 | let b:current_syntax = 'vimspector-breakpoints' 6 | 7 | syn keyword VimspectorBPEnabled ENABLED VERIFIED 8 | syn keyword VimspectorBPDisabled DISABLED PENDING 9 | 10 | syn match VimspectorBPFileLine /\v^\S+:{0,}/ 11 | 12 | hi default link VimspectorBPEnabled WarningMsg 13 | hi default link VimspectorBPDisabled LineNr 14 | hi default link VimspectorBPFileLine CursorLineNr 15 | -------------------------------------------------------------------------------- /syntax/vimspector-disassembly.vim: -------------------------------------------------------------------------------- 1 | if exists( 'b:current_syntax' ) 2 | finish 3 | endif 4 | 5 | runtime! syntax/asm.vim 6 | unlet b:current_syntax 7 | 8 | syn match VimspectorDisassemblyHexNibble "\<[A-F0-9]\{2}\>" display 9 | 10 | hi def link VimspectorDisassemblyHexNibble asmHexadecimal 11 | 12 | let b:current_syntax = 'vimspector-disassembly' 13 | -------------------------------------------------------------------------------- /syntax/vimspector-installer.vim: -------------------------------------------------------------------------------- 1 | if exists( 'b:current_syntax' ) 2 | finish 3 | endif 4 | 5 | let b:current_syntax = 'vimspector-installer' 6 | 7 | syn match VimspectorGadget /[^ ]*\ze@/ 8 | syn match VimspectorGadgetVersion /@\@<=[^ ]*\ze\.\.\./ 9 | 10 | 11 | syn keyword VimspectorInstalling Installing 12 | syn keyword VimspectorDone Done 13 | syn keyword VimspectorSkip Skip 14 | syn keyword VimspectorError Failed FAILED 15 | 16 | hi default link VimspectorInstalling Constant 17 | hi default link VimspectorDone DiffAdd 18 | hi default link VimspectorSkip DiffAdd 19 | hi default link VimspectorError WarningMsg 20 | hi default link VimspectorGadget String 21 | hi default link VimspectorGadgetVersion Identifier 22 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | -------------------------------------------------------------------------------- /tests/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Run test": { 4 | "adapter": "vim-debug-adapter", 5 | "variables": [ 6 | { 7 | "basedir": "${basedir:${workspaceRoot\\}/../test-base}" 8 | }, 9 | { 10 | "setupargs": "--clean --not-a-term -S lib/run_test.vim --cmd 'let g:vimspector_base_dir=\"${basedir}\"'", 11 | "tidy_messages": { "shell": "rm -f ${workspaceRoot}/messages" }, 12 | "tidy_log": { "shell": "rm -f ${workspaceRoot}/test.log" }, 13 | "tidy_testlog": { "shell": "rm -f ${workspaceRoot}/*.testlog" }, 14 | "tidy_debuglog": { "shell": "rm -f ${workspaceRoot}/debuglog" } 15 | } 16 | ], 17 | "configuration": { 18 | "request": "launch", 19 | "cwd": "${workspaceRoot}", 20 | "env": { 21 | "VIMSPECTOR_MIMODE": "lldb" 22 | }, 23 | "args": [ 24 | "*${setupargs}", 25 | "${file}", 26 | "${TestFunction}" 27 | ] 28 | } 29 | }, 30 | "Run script": { 31 | "extends": "Run test", 32 | "configuration": { 33 | "args": [ 34 | "*${setupargs}", 35 | "${file}" 36 | ] 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/PIDPicker.test.vim: -------------------------------------------------------------------------------- 1 | function! SetUp() 2 | call vimspector#test#setup#SetUpWithMappings( v:null ) 3 | unlet! g:vimspector_custom_process_picker_func 4 | endfunction 5 | 6 | function! TearDown() 7 | call vimspector#test#setup#TearDown() 8 | endfunction 9 | 10 | function! Test_PID_Picker_Called_NoArguments_BuiltInPidSelect_RetInt() 11 | let fn='test_c.cpp' 12 | lcd ../support/test/cpp/simple_c_program 13 | exe 'edit ' . fn 14 | 15 | function! PickProcess() abort 16 | let s:process_picker_called = v:true 17 | return 12345 " doesn't matter 18 | endfunction 19 | let g:vimspector_custom_process_picker_func = 'PickProcess' 20 | 21 | let s:process_picker_called = v:false 22 | call vimspector#LaunchWithSettings( { 'configuration': 'cpptools-attach' } ) 23 | call assert_true( s:process_picker_called ) 24 | call vimspector#test#setup#Reset() 25 | 26 | lcd - 27 | %bwipeout! 28 | endfunction 29 | 30 | function! Test_PID_Picker_Called_NoArguments_BuiltInPidSelect_RetStr() 31 | let fn='test_c.cpp' 32 | lcd ../support/test/cpp/simple_c_program 33 | exe 'edit ' . fn 34 | 35 | function! PickProcess() abort 36 | let s:process_picker_called = v:true 37 | return '12345' " doesn't matter 38 | endfunction 39 | let g:vimspector_custom_process_picker_func = 'PickProcess' 40 | 41 | let s:process_picker_called = v:false 42 | call vimspector#LaunchWithSettings( { 'configuration': 'cpptools-attach' } ) 43 | call assert_true( s:process_picker_called ) 44 | call vimspector#test#setup#Reset() 45 | 46 | lcd - 47 | %bwipeout! 48 | endfunction 49 | 50 | function! Test_PID_Picker_Called_NoArguments_BuiltInPidSelect_RetIntArgs() 51 | let fn='test_c.cpp' 52 | lcd ../support/test/cpp/simple_c_program 53 | exe 'edit ' . fn 54 | 55 | function! PickProcess( name ) abort 56 | let s:process_picker_called = v:true 57 | call assert_equal( 'test', a:name, 'argument passed to PickProcess' ) 58 | return 12345 " doesn't matter 59 | endfunction 60 | let g:vimspector_custom_process_picker_func = 'PickProcess' 61 | 62 | let s:process_picker_called = v:false 63 | call vimspector#LaunchWithSettings( { 'configuration': 'CodeLLDB-attach' } ) 64 | call assert_true( s:process_picker_called ) 65 | call vimspector#test#setup#Reset() 66 | 67 | lcd - 68 | %bwipeout! 69 | endfunction 70 | 71 | function! Test_PID_Picker_Called_NoArguments_BuiltInPidSelect_RetStrArgs() 72 | let fn='test_c.cpp' 73 | lcd ../support/test/cpp/simple_c_program 74 | exe 'edit ' . fn 75 | 76 | function! PickProcess( name ) abort 77 | let s:process_picker_called = v:true 78 | call assert_equal( 'test', a:name, 'argument passed to PickProcess' ) 79 | return '12345' " doesn't matter 80 | endfunction 81 | let g:vimspector_custom_process_picker_func = 'PickProcess' 82 | 83 | let s:process_picker_called = v:false 84 | call vimspector#LaunchWithSettings( { 'configuration': 'CodeLLDB-attach' } ) 85 | call assert_true( s:process_picker_called ) 86 | call vimspector#test#setup#Reset() 87 | 88 | lcd - 89 | %bwipeout! 90 | endfunction 91 | -------------------------------------------------------------------------------- /tests/ci/image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | ENV DEBIAN_FRONTEND=noninteractive 4 | ENV LC_ALL C.UTF-8 5 | ARG GOARCH=amd64 6 | ARG GOVERSION=1.23.2 7 | ARG NODE_MAJOR=18 8 | ARG VIM_VERSION=v8.2.4797 9 | ARG NVIM_VERSION=v0.8.3 10 | 11 | 12 | RUN apt-get update && \ 13 | apt-get install -y curl \ 14 | dirmngr \ 15 | apt-transport-https \ 16 | lsb-release \ 17 | ca-certificates \ 18 | gnupg \ 19 | software-properties-common && \ 20 | mkdir -p /etc/apt/keyrings && \ 21 | curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ 22 | | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ 23 | echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \ 24 | > /etc/apt/sources.list.d/nodesource.list && \ 25 | apt-get update && \ 26 | apt-get -y dist-upgrade && \ 27 | apt-get -y install gcc-8 \ 28 | g++-8 \ 29 | python3-dev \ 30 | python3-pip \ 31 | python3-venv \ 32 | ca-cacert \ 33 | locales \ 34 | language-pack-en \ 35 | libncurses5-dev libncursesw5-dev \ 36 | git \ 37 | tcl-dev \ 38 | tcllib \ 39 | gdb \ 40 | lldb \ 41 | nodejs \ 42 | pkg-config \ 43 | lua5.1 \ 44 | luajit \ 45 | lua5.1-dev \ 46 | luajit-5.1-dev \ 47 | libsdl2-dev \ 48 | libopenal-dev \ 49 | libfreetype6-dev \ 50 | libmodplug-dev \ 51 | libvorbis-dev \ 52 | libtheora-dev \ 53 | libmpg123-dev \ 54 | ninja-build \ 55 | gettext \ 56 | cmake \ 57 | unzip \ 58 | curl && \ 59 | apt-get -y autoremove && \ 60 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ 61 | pip3 install neovim && \ 62 | pip install "git+https://github.com/puremourning/asciinema@exit_code#egg=asciinema" 63 | 64 | RUN ln -fs /usr/share/zoneinfo/Europe/London /etc/localtime && \ 65 | dpkg-reconfigure --frontend noninteractive tzdata 66 | 67 | RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 1 \ 68 | --slave /usr/bin/g++ g++ /usr/bin/g++-8 69 | 70 | RUN curl -LO https://golang.org/dl/go${GOVERSION}.linux-${GOARCH}.tar.gz && \ 71 | tar -C /usr/local -xzvf go${GOVERSION}.linux-${GOARCH}.tar.gz && \ 72 | update-alternatives --install /usr/local/bin/go go /usr/local/go/bin/go 1 73 | 74 | # In order for love to work on arm64, we have to build it ourselves 75 | RUN curl -LO https://github.com/love2d/love/releases/download/11.3/love-11.3-linux-src.tar.gz && \ 76 | tar zxvf love-11.3-linux-src.tar.gz && \ 77 | cd love-11.3 && \ 78 | ./configure && \ 79 | make -j $(nproc) && \ 80 | make install && \ 81 | cd .. && \ 82 | rm -rf love-11.3 && \ 83 | rm -f love-11.3-linux-src.tar.gz 84 | 85 | ENV CONF_ARGS "--with-features=huge \ 86 | --enable-python3interp \ 87 | --enable-terminal \ 88 | --enable-multibyte \ 89 | --enable-fail-if-missing" 90 | 91 | RUN mkdir -p $HOME/vim && \ 92 | cd $HOME/vim && \ 93 | git clone --depth 1 --branch ${VIM_VERSION} https://github.com/vim/vim && \ 94 | cd vim && \ 95 | make -j 4 && \ 96 | make install && \ 97 | cd && \ 98 | rm -rf $HOME/vim 99 | 100 | RUN mkdir -p $HOME/nvim && \ 101 | cd $HOME/nvim && \ 102 | git clone --depth 1 --branch ${NVIM_VERSION} https://github.com/neovim/neovim && \ 103 | cd neovim && \ 104 | make CMAKE_BUILD_TYPE=Release CMAKE_GENERTOR=Ninja -j 4 && \ 105 | make install && \ 106 | cd && \ 107 | rm -rf $HOME/nvim 108 | 109 | # dotnet 110 | RUN curl -sSL https://dot.net/v1/dotnet-install.sh \ 111 | | bash /dev/stdin --channel 6.0 --install-dir /usr/share/dotnet && \ 112 | update-alternatives --install /usr/bin/dotnet dotnet \ 113 | /usr/share/dotnet/dotnet 1 114 | 115 | # clean up 116 | RUN rm -rf ~/.cache 117 | -------------------------------------------------------------------------------- /tests/ci/rebuild: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [ "$1" = "--clean" ]; then 6 | OPTS="--no-cache" 7 | shift 8 | else 9 | OPTS="" 10 | fi 11 | 12 | ARCH=$(uname -m) 13 | 14 | GOARCH=${ARCH} 15 | if [ "${ARCH}" = "x86_64" ]; then 16 | GOARCH=amd64 17 | fi 18 | 19 | docker build ${OPTS} --build-arg GOARCH=${GOARCH} \ 20 | "$@" \ 21 | -t puremourning/vimspector:test-${ARCH} image/ 22 | -------------------------------------------------------------------------------- /tests/get_configurations.test.vim: -------------------------------------------------------------------------------- 1 | function! SetUp() 2 | call vimspector#test#setup#SetUpWithMappings( v:null ) 3 | endfunction 4 | 5 | function! TearDown() 6 | call vimspector#test#setup#TearDown() 7 | endfunction 8 | 9 | function Test_Get_Configurations() 10 | lcd ../support/test/csharp/ 11 | 12 | let configs = vimspector#GetConfigurations() 13 | call assert_equal( [ 14 | \ 'launch - netcoredbg', 15 | \ 'launch - netcoredbg - with debug log', 16 | \ 'launch - mono', 17 | \ ], 18 | \ configs ) 19 | 20 | lcd - 21 | %bwipe! 22 | endfunction 23 | 24 | function! Test_Get_Configurations_FilteredFiletypes() 25 | edit ../support/test/multiple_filetypes/test.js 26 | call assert_equal( [ 'Node' ], vimspector#GetConfigurations() ) 27 | edit ../support/test/multiple_filetypes/test.py 28 | call assert_equal( [ 'Python' ], vimspector#GetConfigurations() ) 29 | edit ../support/test/multiple_filetypes/.vimspector.json 30 | call assert_equal( [], vimspector#GetConfigurations() ) 31 | %bwipe! 32 | endfunction 33 | 34 | function! Test_PickConfiguration_FilteredFiletypes() 35 | " This test shows that the auto-pick only uses the correct filetypes 36 | let fn = '../support/test/multiple_filetypes/test.js' 37 | exe 'edit ' . fn 38 | normal! G 39 | call vimspector#SetLineBreakpoint( fn, 1 ) 40 | call vimspector#Launch() 41 | call WaitForAssert( { -> 42 | \ vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 1, 1 ) 43 | \ } ) 44 | 45 | call vimspector#Reset() 46 | call vimspector#test#setup#WaitForReset() 47 | 48 | let fn = '../support/test/multiple_filetypes/test.py' 49 | exe 'edit ' . fn 50 | normal! G 51 | call vimspector#SetLineBreakpoint( fn, 1 ) 52 | call vimspector#Launch() 53 | call WaitForAssert( { -> 54 | \ vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 1, 1 ) 55 | \ } ) 56 | 57 | call vimspector#test#setup#Reset() 58 | %bwipe! 59 | endfunction 60 | 61 | function Test_Get_Configurations_VimDict() 62 | call SkipNeovim() 63 | call vimspector#test#setup#PushSetting( 'vimspector_configurations', #{ 64 | \ test_config: #{ 65 | \ extends: 'launch - netcoredbg' 66 | \ } 67 | \ } ) 68 | lcd ../support/test/csharp/ 69 | 70 | let configs = vimspector#GetConfigurations() 71 | call assert_equal( [ 72 | \ 'test_config', 73 | \ 'launch - netcoredbg', 74 | \ 'launch - netcoredbg - with debug log', 75 | \ 'launch - mono', 76 | \ ], 77 | \ configs ) 78 | 79 | lcd - 80 | %bwipe! 81 | endfunction 82 | 83 | -------------------------------------------------------------------------------- /tests/goto.test.vim: -------------------------------------------------------------------------------- 1 | function! SetUp() 2 | call vimspector#test#setup#SetUpWithMappings( v:null ) 3 | endfunction 4 | 5 | function! TearDown() 6 | call vimspector#test#setup#TearDown() 7 | endfunction 8 | 9 | function! Test_GoTo_Single() 10 | lcd ../support/test/python/simple_python 11 | edit main.py 12 | 13 | call vimspector#SetLineBreakpoint( 'main.py', 26 ) 14 | call vimspector#LaunchWithSettings( { 'configuration': 'run' } ) 15 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'main.py', 26, 1 ) 16 | call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'main.py', 26 ) 17 | 18 | call cursor( 23, 1 ) 19 | call vimspector#GoToCurrentLine() 20 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'main.py', 23, 1 ) 21 | call WaitForAssert( { -> 22 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'main.py', 23 ) } ) 23 | 24 | call cursor( 25, 1 ) 25 | call vimspector#GoToCurrentLine() 26 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'main.py', 25, 1 ) 27 | call WaitForAssert( { -> 28 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'main.py', 25 ) } ) 29 | 30 | call vimspector#test#setup#Reset() 31 | lcd - 32 | %bwipe! 33 | endfunction 34 | 35 | function! Test_GoTo_Single_Mapping() 36 | lcd ../support/test/python/simple_python 37 | edit main.py 38 | 39 | call vimspector#SetLineBreakpoint( 'main.py', 26 ) 40 | call vimspector#LaunchWithSettings( { 'configuration': 'run' } ) 41 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'main.py', 26, 1 ) 42 | call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'main.py', 26 ) 43 | 44 | call cursor( 23, 1 ) 45 | nmap g VimspectorGoToCurrentLine 46 | execute 'normal ,g' 47 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'main.py', 23, 1 ) 48 | call WaitForAssert( { -> 49 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'main.py', 23 ) } ) 50 | 51 | call cursor( 25, 1 ) 52 | call vimspector#GoToCurrentLine() 53 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'main.py', 25, 1 ) 54 | call WaitForAssert( { -> 55 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'main.py', 25 ) } ) 56 | 57 | call vimspector#test#setup#Reset() 58 | silent! nunmap g 59 | lcd - 60 | %bwipe! 61 | endfunction 62 | 63 | function! Test_GoTo_FailsGoTo() 64 | lcd ../support/test/python/simple_python 65 | edit main.py 66 | 67 | call vimspector#SetLineBreakpoint( 'main.py', 23 ) 68 | call vimspector#LaunchWithSettings( { 'configuration': 'run' } ) 69 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'main.py', 23, 1 ) 70 | call WaitForAssert( { -> 71 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'main.py', 23 ) } ) 72 | 73 | call cursor( 15, 10 ) 74 | call vimspector#GoToCurrentLine() 75 | sleep 100m 76 | call WaitForAssert( { -> 77 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'main.py', 23 ) } ) 78 | 79 | call vimspector#StepOver() 80 | call WaitForAssert( { -> 81 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'main.py', 25 ) } ) 82 | 83 | call vimspector#test#setup#Reset() 84 | lcd - 85 | %bwipe! 86 | endfunction 87 | 88 | function! Test_GoTo_Multiple() 89 | " TODO: Can't seem to find any adapters that actually support multiple 90 | endfunction 91 | -------------------------------------------------------------------------------- /tests/language_lua.test.vim: -------------------------------------------------------------------------------- 1 | function! SetUp() 2 | let g:vimspector_enable_mappings = 'HUMAN' 3 | call vimspector#test#setup#SetUpWithMappings( v:null ) 4 | endfunction 5 | 6 | function! TearDown() 7 | call vimspector#test#setup#TearDown() 8 | endfunction 9 | 10 | function! SkipUnsupported() abort 11 | call SkipOn( 'arm64', 'Darwin' ) 12 | endfunction 13 | 14 | 15 | function! BaseTest( configuration ) 16 | call SkipUnsupported() 17 | let fn='simple.lua' 18 | lcd ../support/test/lua/simple 19 | exe 'edit ' . fn 20 | 21 | call vimspector#SetLineBreakpoint( fn, 5 ) 22 | call vimspector#LaunchWithSettings( { 'configuration': a:configuration } ) 23 | 24 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 5, 1 ) 25 | call WaitForAssert( {-> 26 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 5 ) 27 | \ } ) 28 | 29 | " Step 30 | call feedkeys( "\", 'xt' ) 31 | 32 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 6, 1 ) 33 | call WaitForAssert( {-> 34 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 6 ) 35 | \ } ) 36 | 37 | call vimspector#test#setup#Reset() 38 | 39 | lcd - 40 | %bwipeout! 41 | endfunction 42 | 43 | 44 | function! Test_Lua_Simple() 45 | call BaseTest( 'lua' ) 46 | endfunction 47 | 48 | 49 | function! Test_Lua_Luajit() 50 | call BaseTest( 'luajit' ) 51 | endfunction 52 | 53 | 54 | function! Test_Lua_Love() 55 | call SkipUnsupported() 56 | let fn='main.lua' 57 | lcd ../support/test/lua/love-headless 58 | exe 'edit ' . fn 59 | 60 | call vimspector#SetLineBreakpoint( fn, 8 ) 61 | call vimspector#LaunchWithSettings( { 'configuration': 'love' } ) 62 | 63 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) 64 | call WaitForAssert( {-> 65 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 8 ) 66 | \ } ) 67 | 68 | " Step 69 | call feedkeys( "\", 'xt' ) 70 | 71 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 9, 1 ) 72 | call WaitForAssert( {-> 73 | \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 9 ) 74 | \ } ) 75 | 76 | call vimspector#test#setup#Reset() 77 | 78 | lcd - 79 | %bwipeout! 80 | endfunction 81 | -------------------------------------------------------------------------------- /tests/manual/image/.vim/vimrc: -------------------------------------------------------------------------------- 1 | runtime defaults.vim 2 | let g:vimspector_enable_mappings='HUMAN' 3 | source $HOME/vimspector/tests/vimrc 4 | -------------------------------------------------------------------------------- /tests/manual/image/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG ARCH=x86_64 2 | 3 | FROM puremourning/vimspector:test-${ARCH} 4 | 5 | RUN apt-get update && \ 6 | apt-get -y install sudo && \ 7 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 8 | 9 | RUN useradd -ms /bin/bash -d /home/dev -G sudo dev && \ 10 | echo "dev:dev" | chpasswd && \ 11 | echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/sudo 12 | 13 | USER dev 14 | WORKDIR /home/dev 15 | 16 | ENV HOME /home/dev 17 | ENV PYTHON_CONFIGURE_OPTS --enable-shared 18 | ENV VIMSPECTOR_MIMODE gdb 19 | ENV GOPATH /home/dev/go 20 | 21 | ENV VIMSPECTOR_TEST_BASE test-base-linux 22 | ENV TEST_NO_RETRY 1 23 | 24 | RUN go install github.com/go-delve/delve/cmd/dlv@latest 25 | 26 | ADD --chown=dev:dev .vim/ /home/dev/.vim/ 27 | RUN mkdir -p /home/dev/.config/nvim && \ 28 | cd /home/dev/.config/nvim && \ 29 | ln -s /home/dev/.vim/vimrc init.vim 30 | -------------------------------------------------------------------------------- /tests/manual/rebuild: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [ "$1" = "--clean" ]; then 6 | OPTS="--no-cache" 7 | else 8 | OPTS="" 9 | fi 10 | 11 | ARCH=$(uname -m) 12 | 13 | docker build ${OPTS} --build-arg ARCH=${ARCH} \ 14 | -t puremourning/vimspector:manual-${ARCH} image/ 15 | -------------------------------------------------------------------------------- /tests/manual/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd $(dirname $0) 4 | CONTAINER=puremourning/vimspector:manual-$(uname -m ) 5 | 6 | docker run --cap-add=SYS_PTRACE \ 7 | --security-opt seccomp=unconfined \ 8 | --mount src="$(pwd)/../..",target=/home/dev/vimspector,type=bind \ 9 | --rm \ 10 | -it ${CONTAINER} \ 11 | "$@" 12 | -------------------------------------------------------------------------------- /tests/parent_sesions.test.vim: -------------------------------------------------------------------------------- 1 | let s:fn='../support/test/python/simple_python/main.py' 2 | 3 | function! SetUp() 4 | call vimspector#test#setup#SetUpWithMappings( 'HUMAN' ) 5 | endfunction 6 | 7 | function! TearDown() 8 | call vimspector#test#setup#TearDown() 9 | endfunction 10 | 11 | 12 | function! s:StartDebugging( ... ) 13 | let config = #{ 14 | \ fn: s:fn, 15 | \ line: 23, 16 | \ col: 1, 17 | \ launch: #{ configuration: 'run' } 18 | \ } 19 | if a:0 > 0 20 | call extend( config, a:1 ) 21 | endif 22 | 23 | execute 'edit' config.fn 24 | call cursor( 1, 1 ) 25 | call vimspector#SetLineBreakpoint( config.fn, config.line ) 26 | call vimspector#LaunchWithSettings( config.launch ) 27 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 28 | \ config.fn, 29 | \ config.line, 30 | \ config.col ) 31 | endfunction 32 | 33 | function! SessionID() 34 | return py3eval( '_vimspector_session.session_id' ) 35 | endfunction 36 | 37 | function! Test_Multiple_Root_Sessions_Works() 38 | " Init vimspector session 39 | call vimspector#Reset() 40 | call assert_match( '^Unnamed-[0-9]\+$', vimspector#GetSessionName() ) 41 | call s:StartDebugging() 42 | call assert_equal( 'run', vimspector#GetSessionName() ) 43 | call assert_equal( 2, tabpagenr() ) 44 | call assert_equal( 2, tabpagenr( '$' ) ) 45 | VimspectorRenameSession One 46 | call assert_equal( 'One', vimspector#GetSessionName() ) 47 | normal! 1gt 48 | call assert_equal( 'One', vimspector#GetSessionName() ) 49 | call assert_equal( 1, tabpagenr() ) 50 | VimspectorNewSession Two 51 | call assert_equal( 'Two', vimspector#GetSessionName() ) 52 | call s:StartDebugging() 53 | call assert_equal( 'Two', vimspector#GetSessionName() ) 54 | call assert_equal( 3, tabpagenr() ) 55 | call assert_equal( 3, tabpagenr( '$' ) ) 56 | 57 | VimspectorSwitchToSession One 58 | call assert_equal( 2, tabpagenr() ) 59 | call assert_equal( 3, tabpagenr( '$' ) ) 60 | let one_win = win_getid() 61 | call vimspector#StepOver() 62 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) 63 | call assert_equal( win_getid(), one_win ) 64 | VimspectorToggleLog 65 | 66 | VimspectorSwitchToSession Two 67 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 23, 1 ) 68 | call assert_equal( 3, tabpagenr() ) 69 | call assert_equal( 3, tabpagenr( '$' ) ) 70 | let two_win = win_getid() 71 | call assert_notequal( two_win, one_win ) 72 | call vimspector#StepOver() 73 | call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) 74 | call assert_equal( win_getid(), two_win ) 75 | VimspectorToggleLog 76 | 77 | 78 | call vimspector#Reset() 79 | call vimspector#test#setup#WaitForSessionReset( SessionID() ) 80 | 81 | VimspectorSwitchToSession One 82 | call vimspector#Reset() 83 | call vimspector#test#setup#WaitForReset() 84 | 85 | %bwipe! 86 | endfunction 87 | -------------------------------------------------------------------------------- /tests/python/Test_CoreUtils.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import unittest 3 | 4 | from vimspector import core_utils 5 | 6 | 7 | class TestOverrideDict( unittest.TestCase ): 8 | def __init__( self, *args, **kwargs ): 9 | super().__init__( *args, **kwargs ) 10 | 11 | def test_override( self ): 12 | tests = ( 13 | # Empty cases 14 | ( {}, ( {}, {} ) ), 15 | ( { 'a': 'a' }, ( { 'a': 'a' }, {} ) ), 16 | ( { 'a': 'a' }, ( {}, { 'a': 'a' } ) ), 17 | # Simple cases 18 | ( 19 | { 20 | 'a': 'a', 21 | 'b': { 'a': 'aa' } 22 | }, 23 | ( 24 | { 'a': 'a' }, 25 | { 'b': { 'a': 'aa' } } 26 | ) 27 | ), 28 | # Override at various levels 29 | ( 30 | { 31 | 'outer': { 32 | 'inner': { 33 | 'key': 'newValue', 34 | 'existingKey': True 35 | } 36 | }, 37 | 'newKey': { 'newDict': True } 38 | }, 39 | ( 40 | { 41 | 'outer': { 'inner': { 'key': 'oldValue', 'existingKey': True } } 42 | }, 43 | { 44 | 'outer': { 'inner': { 'key': 'newValue' } }, 45 | 'newKey': { 'newDict': True }, 46 | } 47 | ) 48 | ), 49 | # Remove a key with overrides 50 | ( 51 | { 52 | 'outer': { 53 | 'inner': { 54 | 'key': 'newValue' 55 | } 56 | }, 57 | 'newKey': { 'newDict': True } 58 | }, 59 | ( 60 | { 61 | 'outer': { 'inner': { 'key': 'oldValue', 'existingKey': True } } 62 | }, 63 | { 64 | 'outer': { 'inner': { 'key': 'newValue', 65 | '!existingKey': 'REMOVE' } }, 66 | 'newKey': { 'newDict': True }, 67 | } 68 | ) 69 | ) 70 | ) 71 | for expect, t in tests: 72 | with self.subTest( t[ 0 ] ): 73 | self.assertDictEqual( expect, 74 | core_utils.override( *t ) ) 75 | 76 | 77 | assert unittest.main( module=__name__, 78 | testRunner=unittest.TextTestRunner( sys.stdout ), 79 | exit=False ).result.wasSuccessful() 80 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/.gitignore: -------------------------------------------------------------------------------- 1 | simple 2 | variables 3 | struct 4 | printer 5 | threads 6 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", 3 | "configurations": { 4 | "base": { 5 | "adapter": "vscode-cpptools", 6 | "configuration": { 7 | "targetArchitecture": "${VIMSPECTOR_ARCH}", 8 | "request": "launch", 9 | "program": "${workspaceRoot}/${fileBasenameNoExtension}", 10 | "externalConsole": false, 11 | "stopAtEntry": true, 12 | "stopOnEntry": true, 13 | "MIMode": "${VIMSPECTOR_MIMODE}" 14 | }, 15 | "breakpoints": { 16 | "exception": { 17 | "all": "", 18 | "cpp_catch": "", 19 | "cpp_throw": "", 20 | "objc_catch": "", 21 | "objc_throw": "", 22 | "swift_catch": "", 23 | "swift_throw": "" 24 | } 25 | } 26 | }, 27 | "run-to-entry": { 28 | "extends": "base", 29 | // This makes this configuration the default. Only one default can be set 30 | // (having two is the same as having none) 31 | "default": true 32 | }, 33 | "run-to-breakpoint": { 34 | "extends": "base", 35 | "configuration": { 36 | "externalConsole": false, 37 | "stopAtEntry": false, 38 | "stopOnEntry": false 39 | } 40 | }, 41 | "run-to-breakpoint-specify-file": { 42 | "extends": "base", 43 | "configuration": { 44 | "program": "${workspaceRoot}/${prog}", 45 | "cwd": "${workspaceRoot}", 46 | "stopAtEntry": false, 47 | "stopOnEntry": false 48 | } 49 | }, 50 | "calculate-some-variable": { 51 | "extends": "base", 52 | "variables": { 53 | "SIMPLE": "This is some text containing: $HOME", 54 | "CALCULATED_LIST": { 55 | "shell": [ "uuidgen" ] 56 | }, 57 | "CALCULATED_STR": { 58 | "shell": [ "uuidgen" ] 59 | } 60 | }, 61 | "configuration": { 62 | "args": [ 63 | "CALCULATED_LIST", "${CALCULATED_LIST}", 64 | "SIMPLE", "${SIMPLE}", 65 | "CALCULATED_STR", "${CALCULATED_STR}" 66 | ] 67 | } 68 | }, 69 | "lldb-vscode": { 70 | "adapter": "lldb-vscode", 71 | "configuration": { 72 | "request": "launch", 73 | "program": "${workspaceRoot}/${fileBasenameNoExtension}", 74 | "cwd": "${workspaceRoot}", 75 | "externalConsole": false, 76 | "MIMode": "lldb" 77 | } 78 | }, 79 | "lldb-dap": { 80 | "adapter": "lldb-dap", 81 | "configuration": { 82 | "request": "launch", 83 | "program": "${workspaceRoot}/${fileBasenameNoExtension}", 84 | "args": [ 85 | "A", "eh", 86 | "B", "bee", 87 | "C", "Sea", 88 | "D", "Ceedy" 89 | ], 90 | "stopOnEntry": true, 91 | "runInTerminal": true, 92 | "cwd": "${workspaceRoot}" 93 | } 94 | }, 95 | "CodeLLDB": { 96 | "adapter": "CodeLLDB", 97 | // "adapter": { 98 | // "extends": "CodeLLDB", 99 | // "command": [ 100 | // "$HOME/Development/vimspector/vscode-lldb/build/adapter/codelldb", 101 | // "--port", 102 | // "${unusedLocalPort}" 103 | // ] 104 | // }, 105 | "configuration": { 106 | "request": "launch", 107 | "program": "${workspaceRoot}/${fileBasenameNoExtension}", 108 | "cwd": "${workspaceRoot}", 109 | "expressions": "native", 110 | "args": [ 111 | "A", "eh", 112 | "B", "bee", 113 | "C", "Sea", 114 | "D", "Ceedy" 115 | ] 116 | }, 117 | "breakpoints": { 118 | "exception": { 119 | "cpp_throw": "", 120 | "cpp_catch": "" 121 | } 122 | } 123 | }, 124 | "CodeLLDB-localbuild": { 125 | "extends": "CodeLLDB", 126 | "adapter": "CodeLLDB-localbuild" 127 | } 128 | }, 129 | "adapters": { 130 | "lldb-vscode": { 131 | "variables": { 132 | "LLVM": { 133 | "shell": "brew --prefix llvm" 134 | } 135 | }, 136 | "attach": { 137 | "pidProperty": "pid", 138 | "pidSelect": "ask" 139 | }, 140 | "command": [ 141 | "${LLVM}/bin/lldb-vscode" 142 | ], 143 | "env": { 144 | "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" 145 | }, 146 | "name": "lldb" 147 | }, 148 | "lldb-dap": { 149 | "variables": { 150 | "LLVM": { 151 | "shell": "brew --prefix llvm" 152 | } 153 | }, 154 | "command": [ 155 | "${LLVM}/bin/lldb-dap" 156 | ], 157 | "name": "lldb" 158 | }, 159 | "CodeLLDB-localbuild": { 160 | "extends": "CodeLLDB", 161 | "command": [ 162 | "$HOME/Development/vimspector/CodeLLDB/build/adapter/codelldb" 163 | ] 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/.ycm_extra_conf.py: -------------------------------------------------------------------------------- 1 | def Settings( **kwargs ): 2 | return { 3 | 'flags': [ 4 | '-x', 'c++', 5 | '-std=c++17', 6 | '-Wextra', '-Werror', '-Wall' 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/Makefile: -------------------------------------------------------------------------------- 1 | TARGETS=simple variables struct printer threads tiny buffer 2 | 3 | CXXFLAGS=-g -O0 -std=c++17 4 | CFLAGS=-g -O0 5 | LDLIBS=-lpthread 6 | 7 | .PHONY: all 8 | all: $(TARGETS) 9 | 10 | .PHONY: clean 11 | clean: 12 | rm -f $(TARGETS) 13 | rm -rf $(TARGETS:%=%.dSYM) 14 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | struct Foo 9 | { 10 | uint32_t a; 11 | uint64_t b; 12 | float d; 13 | }; 14 | 15 | static void handle_data(const unsigned char* data, size_t length) 16 | { 17 | if (length < sizeof(Foo)) 18 | return; 19 | 20 | Foo f; 21 | memcpy(&f, data, sizeof(Foo)); 22 | 23 | std::cout << "a: " << f.a << ", b: " << f.b << ", d: " << f.d << std::endl; 24 | } 25 | 26 | int main(int , char**) 27 | { 28 | unsigned char data[1024]; 29 | Foo f{ 10, 20, 30.7f }; 30 | 31 | memcpy(data + 3, &f, sizeof(Foo)); 32 | 33 | void *ptr = mmap(nullptr, 2048, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 34 | memcpy(ptr, data+3, sizeof(Foo)); 35 | 36 | handle_data((unsigned char*)ptr, sizeof(f)); 37 | munmap(ptr, 2048); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/printer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main( int argc, char** argv ) 5 | { 6 | if ( ( argc - 1 ) % 2 ) 7 | { 8 | std::cerr << "Unbalanced arguments\n"; 9 | return 1; 10 | } 11 | 12 | for ( int i=1; i < argc; i += 2 ) 13 | { 14 | std::cout << argv[ i ] 15 | << ": " 16 | << argv[ i + 1 ] 17 | << '\n'; 18 | } 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/simple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace 4 | { 5 | void foo( int bar ) 6 | { 7 | int unused; 8 | 9 | printf( "%d\n", bar ); 10 | } 11 | } 12 | 13 | int main( int argc, char ** ) 14 | { 15 | printf( "this is a test %d\n", argc ); 16 | foo( argc ); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/struct.cpp: -------------------------------------------------------------------------------- 1 | struct AnotherTest 2 | { 3 | char choo; 4 | int ints[5]; 5 | }; 6 | 7 | struct Test 8 | { 9 | int i; 10 | char c; 11 | float fffff; 12 | 13 | AnotherTest another_test; 14 | }; 15 | 16 | static Test SetUp( Test t ) 17 | { 18 | t.another_test.choo = 'p'; 19 | t.another_test.ints[ 0 ] = t.i; return t; 20 | } 21 | 22 | int main( int , char ** ) 23 | { 24 | Test t = {}; 25 | 26 | t.i = 1; 27 | t.c = 'c'; 28 | t.fffff = 3.14; 29 | 30 | t = SetUp( t ); 31 | 32 | return t.another_test.ints[ 0 ]; 33 | } 34 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/threads.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main( int argc, char ** argv ) 14 | { 15 | int numThreads = {}; 16 | if ( argc < 2 ) 17 | { 18 | numThreads = 5; 19 | } 20 | else 21 | { 22 | std::string_view numThreadArg( argv[ 1 ] ); 23 | if ( auto [ p, ec ] = std::from_chars( numThreadArg.begin(), 24 | numThreadArg.end(), 25 | numThreads ); 26 | ec != std::errc() ) 27 | { 28 | std::cerr << "Usage " << argv[ 0 ] << " \n"; 29 | return 2; 30 | } 31 | } 32 | 33 | std::cout << "Creating " << numThreads << " threads" << '\n'; 34 | 35 | std::vector threads{}; 36 | threads.reserve( numThreads ); 37 | 38 | auto eng = std::default_random_engine() ; 39 | auto dist = std::uniform_int_distribution( 250, 1000 ); 40 | 41 | std::mutex m; 42 | std::condition_variable v; 43 | bool ready = false; 44 | { 45 | std::lock_guard l(m); 46 | 47 | std::cout << "Preparing..." << '\n'; 48 | 49 | for ( int i = 0; i < numThreads; ++i ) 50 | { 51 | using namespace std::chrono_literals; 52 | auto tp = [&,tnum=i]() { 53 | // Wait for the go-ahead 54 | { 55 | std::unique_lock l(m); 56 | while (!ready) { 57 | v.wait(l); 58 | } 59 | } 60 | 61 | std::cout << "Started thread " << tnum << '\n'; 62 | std::this_thread::sleep_for( 63 | 5s + std::chrono::milliseconds( dist( eng ) ) ); 64 | std::cout << "Completed thread " << tnum << '\n'; 65 | }; 66 | 67 | threads.emplace_back( tp ); 68 | } 69 | 70 | std::cout << "Ready to go!" << '\n'; 71 | ready = true; 72 | } 73 | 74 | v.notify_all(); 75 | 76 | for ( int i = 0; i < numThreads; ++i ) 77 | { 78 | threads[ i ].join(); 79 | } 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/tiny.c: -------------------------------------------------------------------------------- 1 | int main(int argc, char**argv) 2 | { 3 | int res = argc + 1; 4 | return res; 5 | } 6 | -------------------------------------------------------------------------------- /tests/testdata/cpp/simple/variables.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::cout << "Hello world!" << std::endl; 5 | int a = 1; 6 | ++a; 7 | int& b = a; 8 | ++a; 9 | std::cout << "a: " << a << " b: " << b << std::endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /tests/utils.test.vim: -------------------------------------------------------------------------------- 1 | function! SetUp() 2 | call vimspector#test#setup#SetUpWithMappings( v:null ) 3 | py3 import vim 4 | py3 __import__( 'vimspector' ) 5 | endfunction 6 | 7 | function! TearDown() 8 | call vimspector#test#setup#TearDown() 9 | endfunction 10 | 11 | function! s:RunPyFile( file_name ) 12 | redir => py_output 13 | try 14 | let v:errmsg = '' 15 | silent! execute 'py3file python/' .. a:file_name 16 | finally 17 | redir END 18 | call TestLog( [ a:file_name .. ' output:' ] + split( py_output, '\n' ) ) 19 | endtry 20 | 21 | if v:errmsg !=# '' 22 | call assert_report( v:errmsg ) 23 | endif 24 | endfunction 25 | 26 | function! Test_ExpandReferencesInDict() 27 | call SkipNeovim() 28 | call s:RunPyFile( 'Test_ExpandReferencesInDict.py' ) 29 | endfunction 30 | 31 | function! Test_CoreUtils() 32 | call SkipNeovim() 33 | call s:RunPyFile( 'Test_CoreUtils.py' ) 34 | endfunction 35 | -------------------------------------------------------------------------------- /tests/vimrc: -------------------------------------------------------------------------------- 1 | let g:vimspector_test_plugin_path = expand( ':p:h:h' ) 2 | set mouse=a 3 | set noequalalways 4 | let mapleader = ',' 5 | let maplocalleader = "\" 6 | let g:vimspector_install_gadgets=[ '--all', 'netcoredbg', 'vscode-js-debug' ] 7 | 8 | if exists( '$VIMSPECTOR_TEST_BASE' ) 9 | let g:vimspector_base_dir = g:vimspector_test_plugin_path .. '/' .. $VIMSPECTOR_TEST_BASE 10 | endif 11 | 12 | if has('nvim' ) && exists( 'g:vimspector_base_dir' ) 13 | \ && isdirectory( g:vimspector_base_dir . '/nvim_env' ) 14 | let g:python3_host_prog = g:vimspector_base_dir . '/nvim_env/bin/python' 15 | endif 16 | 17 | let &runtimepath = &runtimepath . ',' . g:vimspector_test_plugin_path 18 | 19 | filetype plugin indent on 20 | syntax enable 21 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = E111,E114,E121,E125,E126,E127,E128,E129,E131,E133,E201,E202,E203,E211,E221,E222,E241,E251,E261,E303,E402,W503,W504,YCM201,YCM202 3 | max-line-length = 80 4 | exclude = python3/vimspector/vendor 5 | -------------------------------------------------------------------------------- /update-schema-docs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -x 5 | 6 | tmpdir=$(mktemp -d) 7 | python3 -m venv ${tmpdir} 8 | source ${tmpdir}/bin/activate 9 | pip install json-schema-for-humans 10 | 11 | pushd $(dirname $0) 12 | generate-schema-doc docs/schema docs/schema-doc 13 | popd 14 | 15 | deactivate 16 | 17 | rm -rf ${tmpdir} 18 | -------------------------------------------------------------------------------- /update-vim-docs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -x 5 | 6 | tmpdir=$(mktemp -d) 7 | python3 -m venv ${tmpdir}/env 8 | source ${tmpdir}/env/bin/activate 9 | 10 | if [ -z "$1" ]; then 11 | git clone https://github.com/ycm-core/vim-tools ${tmpdir}/vim-tools 12 | TOOLS=${tmpdir}/vim-tools 13 | else 14 | TOOLS="$1" 15 | fi 16 | 17 | pip install -r ${TOOLS}/requirements.txt 18 | 19 | pushd $(dirname $0) 20 | python3 ${TOOLS}/html2vimdoc.py -f vimspector \ 21 | README.md \ 22 | > doc/vimspector.txt 23 | python3 ${TOOLS}/html2vimdoc.py -f vimspector-ref \ 24 | docs/configuration.md \ 25 | > doc/vimspector-ref.txt 26 | popd 27 | 28 | deactivate 29 | 30 | rm -rf ${tmpdir} 31 | --------------------------------------------------------------------------------