Compare commits

..

1 commit

Author SHA1 Message Date
Ben Jackson
4ba3d999f7 Update debugpy 2020-12-14 21:55:13 +00:00
84 changed files with 1759 additions and 7884 deletions

View file

@ -17,12 +17,12 @@ assignees: ''
> Please answer the following questions > Please answer the following questions
* Does your issue reproduce using `vim --clean -Nu /path/to/vimspector/support/minimal_vimrc` ? \[Yes/No] * Does your issue reproduce using `vim -Nu /path/to/vimspector/support/minimal_vimrc` ? \[Yes/No]
* If you are using Neovim, does your issue reproduce using Vim? \[Yes/No] * If you are using Neovim, does your issue reproduce using Vim? \[Yes/No]
> List of steps to reproduce: > List of steps to reproduce:
> 1. Run `vim ---clean Nu /path/to/vimspector/support/minimal_vimrc` > 1. Run `vim -Nu /path/to/vimspector/support/minimal_vimrc`
> 2. Open _this project_... > 2. Open _this project_...
> 3. Press _this sequence of keys_ > 3. Press _this sequence of keys_
@ -57,12 +57,6 @@ discussing on Gitter rather than raising an issue.
* Version of Vimspector: (e.g. output of `git rev-parse HEAD` if cloned or the * Version of Vimspector: (e.g. output of `git rev-parse HEAD` if cloned or the
name of the tarball used to install otherwise) name of the tarball used to install otherwise)
* Output of `:VimspectorDebugInfo`
```
paste here
```
* Output of `vim --version` or `nvim --version` * Output of `vim --version` or `nvim --version`
``` ```

View file

@ -1,12 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Questions and support
url: http://gitter.im/vimspector/Lobby
about: Please ask and answer questions here.
- name: Discussions
url: https://github.com/puremourning/vimspector/discussions
about: Please post questions and useful hints here
- name: Support for additional languages
url: https://github.com/puremourning/vimspector/wiki/languages
about: Please see here for information on support for additional languages

View file

@ -13,7 +13,7 @@ defaults:
jobs: jobs:
PythonLint: PythonLint:
runs-on: ubuntu-18.04 runs-on: ubuntu-16.04
container: 'puremourning/vimspector:test' container: 'puremourning/vimspector:test'
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -22,7 +22,7 @@ jobs:
- name: 'Run flake8' - name: 'Run flake8'
run: '$HOME/.local/bin/flake8 python3/ *.py' run: '$HOME/.local/bin/flake8 python3/ *.py'
VimscriptLint: VimscriptLint:
runs-on: 'ubuntu-18.04' runs-on: 'ubuntu-16.04'
container: 'puremourning/vimspector:test' container: 'puremourning/vimspector:test'
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -32,7 +32,7 @@ jobs:
run: $HOME/.local/bin/vint autoload/ compiler/ plugin/ tests/ syntax/ run: $HOME/.local/bin/vint autoload/ compiler/ plugin/ tests/ syntax/
Linux: Linux:
runs-on: 'ubuntu-18.04' runs-on: 'ubuntu-16.04'
container: container:
image: 'puremourning/vimspector:test' image: 'puremourning/vimspector:test'
options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined
@ -111,16 +111,6 @@ jobs:
path: gadgets/macos/download path: gadgets/macos/download
name: Cache gadgets name: Cache gadgets
- name: 'Install .NET Core SDK 3.1'
uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: 3.1
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: ^11
name: "Switch to xcode 11 because of .NET debugging bug"
- run: vim --version - run: vim --version
name: 'Print vim version information' name: 'Print vim version information'
@ -153,10 +143,10 @@ jobs:
# if: failure() # if: failure()
# with: # with:
# NGROK_AUTH_TOKEN: ${{ secrets.NGROK_AUTH_TOKEN }} # NGROK_AUTH_TOKEN: ${{ secrets.NGROK_AUTH_TOKEN }}
# SSH_PASS: ${{ secrets.SSH_PASS }} # [V]imspector # SSH_PASS: ${{ secrets.SSH_PASS }}
PublishRelease: PublishRelease:
runs-on: 'ubuntu-18.04' runs-on: 'ubuntu-16.04'
needs: needs:
- Linux - Linux
- MacOS - MacOS

View file

@ -1,27 +0,0 @@
name: "Lock Old Issues"
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v2
with:
github-token: ${{ github.token }}
issue-lock-inactive-days: '60'
# issue-exclude-created-before: ''
# issue-exclude-labels: ''
# issue-lock-labels: ''
# issue-lock-comment: ''
# issue-lock-reason: 'resolved'
# pr-lock-inactive-days: '365'
# pr-exclude-created-before: ''
# pr-exclude-labels: ''
# pr-lock-labels: ''
# pr-lock-comment: ''
# pr-lock-reason: 'resolved'
process-only: 'issues'

1
.gitignore vendored
View file

@ -20,4 +20,3 @@ support/test/csharp/*.exe*
configurations/ configurations/
venv/ venv/
test-base/ test-base/
tags

View file

@ -9,8 +9,9 @@ pull_request_rules:
# CI https://doc.mergify.io/conditions.html#github-actions # CI https://doc.mergify.io/conditions.html#github-actions
- status-success=PythonLint - status-success=PythonLint
- status-success=VimscriptLint - status-success=VimscriptLint
- status-success=Linux
- status-success=MacOS - status-success=MacOS
actions: &merge-actions actions: &merge-actions
merge: merge:
method: merge method: merge

View file

@ -42,17 +42,7 @@ def Settings( **kwargs ):
return { return {
'sys_path': [ 'sys_path': [
p.join( PATH_TO_THIS_DIR, 'python3' ) p.join( PATH_TO_THIS_DIR, 'python3' )
], ]
'ls': {
'python': {
'analysis': {
'extraPaths': [
p.join( PATH_TO_THIS_DIR, 'python3' ),
],
'useLibraryCodeForTypes': True
}
}
}
} }
if IgnoreExtraConf: if IgnoreExtraConf:

View file

@ -46,23 +46,6 @@ The GitHub issue tracker is for *bug reports* and *features requests* for the
Vimspector project, and on-topic comments and follow-ups to them. It is not for Vimspector project, and on-topic comments and follow-ups to them. It is not for
general discussion, general support or for any other purpose. general discussion, general support or for any other purpose.
Please **search the issue tracker for similar issues** before creating a new
one. There's no point in duplication; if an existing open issue addresses your
problem, please comment there instead of creating a duplicate. However, if the
issue you found is **closed as resolved** (e.g. with a PR or the original user's
problem was resolved), raise a **new issue**, because you've found a new
problem. Reference the original issue if you think that's useful information.
Closed issues which have been inactive for 60 days will be locked, this helps to
keep discussions focussed. If you believe you are still experiencing an issue
which has been closed, please raise a new issue, completing the issue template.
If you do find a similar _open_ issue, **don't just post 'me too' or similar**
responses. This almost never helps resolve the issue, and just causes noise for
the maintainers. Only post if it will aid the maintainers in solving the issue;
if there are existing diagnostics requested in the thread, perform
them and post the results.
Please do not be offended if your Issue or comment is closed or hidden, for any Please do not be offended if your Issue or comment is closed or hidden, for any
of the following reasons: of the following reasons:
@ -70,7 +53,6 @@ of the following reasons:
* The issue or comment is off-topic * The issue or comment is off-topic
* The issue does not represent a Vimspector bug or feature request * The issue does not represent a Vimspector bug or feature request
* The issue cannot be reasonably reproduced using the minimal vimrc * The issue cannot be reasonably reproduced using the minimal vimrc
* The issue is a duplicate of an existing issue
* etc. * etc.
Issue titles are important. It's not usually helpful to write a title like Issue titles are important. It's not usually helpful to write a title like
@ -101,7 +83,7 @@ in the issue report.
The minimal vimrc is in `support/test/minimal_vimrc` and can be used as follows: The minimal vimrc is in `support/test/minimal_vimrc` and can be used as follows:
``` ```
vim --clean -Nu /path/to/vimspector/support/minimal_vimrc vim -Nu /path/to/vimspector/support/minimal_vimrc
``` ```
## Pull Requests ## Pull Requests
@ -185,10 +167,10 @@ Vimspector creator.
### Code Style ### Code Style
The code style of the Python code is "YCM" style, because that's how I like it. The code style of the Python code is "YCM" style, because that's how I like it.
`flake8` is used to check for certain errors and code style. [`flake8`][] is used to check for certain errors and code style.
The code style of the Vimscript is largely the same, and it is linted by The code style of the Vimscript is largely the same, and it is linted by
`vint`. [`vint`][].
To run them: To run them:
@ -200,31 +182,7 @@ To run them:
They're also run by CI, so please check for lint failures. The canonical They're also run by CI, so please check for lint failures. The canonical
definition of the command to run is the command run in CI, i.e. in definition of the command to run is the command run in CI, i.e. in
`.git/workflows/build.yml`. `azure-pipelines.yml`.
### Debugging Vimspector
You can debug vimspector's python code using vimspector! We can use debugpy,
from within Vim's embedded python and connect to it. Here's how:
1. In one instance of vim, run the following to get debugpy to start listening
for us to connect: `:py3 __import__( 'vimspector', fromlist=[ 'developer' ]
).developer.SetUpDebugpy()`
2. In another instance of Vim, set a breakpoint in the vimspector python code
you want to debug and launch vimspector (e.g. `<F5>`). Select the `Python:
attach to vim` profile. This will attach to the debugpy running in the other
vim.
3. Back in the first vim (the debuggee), trigger the vimspector code in
question, e.g. by starting to debug something else.
4. You'll see it pause, and the 2nd vim (the debugger), you should be able to
step through and inspect as with any other python remote debugging.
NB. It's also possible to debug the vimscript code using vimspector, but this
requires unreleased vim patches and a fair amount of faff. You can always use
`:debug` (see the help) for this though.
# Code of conduct # Code of conduct

729
README.md

File diff suppressed because it is too large Load diff

View file

@ -13,9 +13,6 @@
" See the License for the specific language governing permissions and " See the License for the specific language governing permissions and
" limitations under the License. " limitations under the License.
if !has( 'python3' )
finish
endif
" Boilerplate {{{ " Boilerplate {{{
let s:save_cpo = &cpoptions let s:save_cpo = &cpoptions
@ -44,11 +41,11 @@ function! s:Enabled() abort
return s:enabled return s:enabled
endfunction endfunction
function! vimspector#Launch( ... ) abort function! vimspector#Launch() abort
if !s:Enabled() if !s:Enabled()
return return
endif endif
py3 _vimspector_session.Start( *vim.eval( 'a:000' ) ) py3 _vimspector_session.Start()
endfunction endfunction
function! vimspector#LaunchWithSettings( settings ) abort function! vimspector#LaunchWithSettings( settings ) abort
@ -58,16 +55,11 @@ function! vimspector#LaunchWithSettings( settings ) abort
py3 _vimspector_session.Start( launch_variables = vim.eval( 'a:settings' ) ) py3 _vimspector_session.Start( launch_variables = vim.eval( 'a:settings' ) )
endfunction endfunction
function! vimspector#Reset( ... ) abort function! vimspector#Reset() abort
if !s:Enabled() if !s:Enabled()
return return
endif endif
if a:0 == 0 py3 _vimspector_session.Reset()
let options = {}
else
let options = a:1
endif
py3 _vimspector_session.Reset( **vim.eval( 'options' ) )
endfunction endfunction
function! vimspector#Restart() abort function! vimspector#Restart() abort
@ -193,16 +185,11 @@ function! vimspector#SetCurrentThread() abort
py3 _vimspector_session.SetCurrentThread() py3 _vimspector_session.SetCurrentThread()
endfunction endfunction
function! vimspector#Stop( ... ) abort function! vimspector#Stop() abort
if !s:Enabled() if !s:Enabled()
return return
endif endif
if a:0 == 0 py3 _vimspector_session.Stop()
let options = {}
else
let options = a:1
endif
py3 _vimspector_session.Stop( **vim.eval( 'options' ) )
endfunction endfunction
function! vimspector#ExpandVariable() abort function! vimspector#ExpandVariable() abort
@ -212,17 +199,6 @@ function! vimspector#ExpandVariable() abort
py3 _vimspector_session.ExpandVariable() py3 _vimspector_session.ExpandVariable()
endfunction endfunction
function! vimspector#SetVariableValue( ... ) abort
if !s:Enabled()
return
endif
if a:0 == 0
py3 _vimspector_session.SetVariableValue()
else
py3 _vimspector_session.SetVariableValue( new_value = vim.eval( 'a:1' ) )
endif
endfunction
function! vimspector#DeleteWatch() abort function! vimspector#DeleteWatch() abort
if !s:Enabled() if !s:Enabled()
return return
@ -237,28 +213,12 @@ function! vimspector#GoToFrame() abort
py3 _vimspector_session.ExpandFrameOrThread() py3 _vimspector_session.ExpandFrameOrThread()
endfunction endfunction
function! vimspector#UpFrame() abort
if !s:Enabled()
return
endif
py3 _vimspector_session.UpFrame()
endfunction
function! vimspector#DownFrame() abort
if !s:Enabled()
return
endif
py3 _vimspector_session.DownFrame()
endfunction
function! vimspector#AddWatch( ... ) abort function! vimspector#AddWatch( ... ) abort
if !s:Enabled() if !s:Enabled()
return return
endif endif
if a:0 == 0 if a:0 == 0
let expr = input( 'Enter watch expression: ', let expr = input( 'Enter watch expression: ' )
\ '',
\ 'custom,vimspector#CompleteExpr' )
else else
let expr = a:1 let expr = a:1
endif endif
@ -350,6 +310,28 @@ function! vimspector#CompleteOutput( ArgLead, CmdLine, CursorPos ) abort
return join( buffers, "\n" ) return join( buffers, "\n" )
endfunction endfunction
py3 <<EOF
def _vimspector_GetExprCompletions( ArgLead, prev_non_keyword_char ):
if not _vimspector_session:
return []
items = []
for candidate in _vimspector_session.GetCompletionsSync(
ArgLead,
prev_non_keyword_char ):
label = candidate.get( 'text', candidate[ 'label' ] )
start = prev_non_keyword_char - 1
if 'start' in candidate and 'length' in candidate:
start = candidate[ 'start' ]
items.append( ArgLead[ 0 : start ] + label )
return items
EOF
function! vimspector#CompleteExpr( ArgLead, CmdLine, CursorPos ) abort function! vimspector#CompleteExpr( ArgLead, CmdLine, CursorPos ) abort
if !s:Enabled() if !s:Enabled()
return return
@ -358,7 +340,7 @@ function! vimspector#CompleteExpr( ArgLead, CmdLine, CursorPos ) abort
let col = len( a:ArgLead ) let col = len( a:ArgLead )
let prev_non_keyword_char = match( a:ArgLead[ 0 : col - 1 ], '\k*$' ) + 1 let prev_non_keyword_char = match( a:ArgLead[ 0 : col - 1 ], '\k*$' ) + 1
return join( py3eval( '_vimspector_session.GetCommandLineCompletions( ' return join( py3eval( '_vimspector_GetExprCompletions( '
\ . 'vim.eval( "a:ArgLead" ), ' \ . 'vim.eval( "a:ArgLead" ), '
\ . 'int( vim.eval( "prev_non_keyword_char" ) ) )' ), \ . 'int( vim.eval( "prev_non_keyword_char" ) ) )' ),
\ "\n" ) \ "\n" )
@ -541,30 +523,6 @@ function! vimspector#OnBufferCreated( file_name ) abort
py3 _vimspector_session.RefreshSigns( vim.eval( 'a:file_name' ) ) py3 _vimspector_session.RefreshSigns( vim.eval( 'a:file_name' ) )
endfunction endfunction
function! vimspector#ShowEvalBalloon( is_visual ) abort
if a:is_visual
let expr = py3eval( '__import__( "vimspector", fromlist = [ "utils" ] )'
\ . '.utils.GetVisualSelection('
\ . ' int( vim.eval( "winbufnr( winnr() )" ) ) )' )
let expr = join( expr, '\n' )
else
let expr = expand( '<cexpr>' )
endif
return py3eval( '_vimspector_session.ShowEvalBalloon('
\ . ' int( vim.eval( "winnr()" ) ), "'
\ . expr
\ . '", 0 )' )
endfunction
function! vimspector#PrintDebugInfo() abort
if !s:Enabled()
return
endif
py3 _vimspector_session.PrintDebugInfo()
endfunction
" Boilerplate {{{ " Boilerplate {{{
let &cpoptions=s:save_cpo let &cpoptions=s:save_cpo

View file

@ -19,323 +19,16 @@ let s:save_cpo = &cpoptions
set cpoptions&vim set cpoptions&vim
" }}} " }}}
scriptencoding utf-8 " Returns: py.ShowBalloon( winnr, expresssion )
function! vimspector#internal#balloon#BalloonExpr() abort
let s:popup_win_id = 0 " winnr + 1 because for *no good reason* winnr is 0 based here unlike
let s:nvim_border_win_id = 0 " everywhere else
" " int() because for *no good reason* winnr is a string.
" tooltip dimensions return py3eval('_vimspector_session.ShowBalloon('
let s:min_width = 1 \ . 'int( vim.eval( "v:beval_winnr" ) ) + 1,'
let s:min_height = 1 \ . 'vim.eval( "v:beval_text" ) )' )
let s:max_width = 80
let s:max_height = 20
let s:is_neovim = has( 'nvim' )
" This is used as the balloonexpr in vim to show the Tooltip at the hover
" position
function! vimspector#internal#balloon#HoverTooltip() abort
return py3eval( '_vimspector_session.ShowEvalBalloon('
\ . ' int( vim.eval( "v:beval_winnr" ) ) + 1,'
\ . ' vim.eval( "v:beval_text"),'
\ . ' 1 )' )
endfunction endfunction
function! vimspector#internal#balloon#CreateTooltip( is_hover, ... ) abort
let body = []
if a:0 > 0
let body = a:1
endif
if s:popup_win_id != 0
call vimspector#internal#balloon#Close()
endif
if s:is_neovim
call s:CreateNeovimTooltip( body )
else
let config = {
\ 'wrap': 0,
\ 'filtermode': 'n',
\ 'maxwidth': s:max_width,
\ 'maxheight': s:max_height,
\ 'minwidth': s:min_width,
\ 'minheight': s:min_height,
\ 'scrollbar': 1,
\ 'border': [],
\ 'padding': [ 0, 1, 0, 1],
\ 'drag': 1,
\ 'resize': 1,
\ 'close': 'button',
\ 'callback': 'vimspector#internal#balloon#CloseCallback',
\ }
let config = vimspector#internal#popup#SetBorderChars( config )
if a:is_hover
let config[ 'filter' ] = 'vimspector#internal#balloon#MouseFilter'
let config[ 'mousemoved' ] = [ 0, 0, 0 ]
let s:popup_win_id = popup_beval( body, config )
else
let config[ 'filter' ] = 'vimspector#internal#balloon#CursorFilter'
let config[ 'moved' ] = 'any'
let config[ 'cursorline' ] = 1
let config[ 'mapping' ] = 0
let s:popup_win_id = popup_atcursor( body, config )
endif
endif
return s:popup_win_id
endfunction
" Filters for vim {{{
function! vimspector#internal#balloon#MouseFilter( winid, key ) abort
if a:key ==# "\<Esc>"
call vimspector#internal#balloon#Close()
return 0
endif
if index( [ "\<leftmouse>", "\<2-leftmouse>" ], a:key ) < 0
return 0
endif
let handled = 0
let mouse_coords = getmousepos()
" close the popup if mouse is clicked outside the window
if mouse_coords[ 'winid' ] != a:winid
call vimspector#internal#balloon#Close()
return 0
endif
" place the cursor according to the click
call win_execute( a:winid,
\ ':call cursor( '
\ . mouse_coords[ 'line' ]
\ . ', '
\ . mouse_coords[ 'column' ]
\ . ' )' )
" expand the variable if we got double click
if a:key ==? "\<2-leftmouse>"
call py3eval( '_vimspector_session.ExpandVariable('
\ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],'
\ . 'line_num = ' . line( '.', a:winid )
\ . ')' )
let handled = 1
endif
return handled
endfunction
function! s:MatchKey( key, candidates ) abort
for candidate in a:candidates
" If the mapping string looks like a special character, then try and
" expand it. This is... a hack. The whole thing only works if the mapping
" is a single key (anyway), and so we assume any string starting with < is a
" special key (which will be the common case) and try and map it. If it
" fails... it fails.
if candidate[ 0 ] == '<'
try
execute 'let candidate = "\' . candidate . '"'
endtry
endif
if candidate ==# a:key
return v:true
endif
endfor
return v:false
endfunction
function! vimspector#internal#balloon#CursorFilter( winid, key ) abort
let mappings = py3eval(
\ "__import__( 'vimspector',"
\." fromlist = [ 'settings' ] ).settings.Dict("
\." 'mappings' )[ 'variables' ]" )
if index( [ "\<LeftMouse>", "\<2-LeftMouse>" ], a:key ) >= 0
return vimspector#internal#balloon#MouseFilter( a:winid, a:key )
endif
if s:MatchKey( a:key, mappings.expand_collapse )
call py3eval( '_vimspector_session.ExpandVariable('
\ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],'
\ . 'line_num = ' . line( '.', a:winid )
\ . ')' )
return 1
elseif s:MatchKey( a:key, mappings.set_value )
call py3eval( '_vimspector_session.SetVariableValue('
\ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],'
\ . 'line_num = ' . line( '.', a:winid )
\ . ')' )
return 1
endif
return popup_filter_menu( a:winid, a:key )
endfunction
" }}}
" Closing {{{
function! vimspector#internal#balloon#CloseCallback( ... ) abort
let s:popup_win_id = 0
let s:nvim_border_win_id = 0
return py3eval( '_vimspector_session.CleanUpTooltip()' )
endfunction
function! vimspector#internal#balloon#Close() abort
if s:popup_win_id == 0
return
endif
if s:is_neovim
call nvim_win_close( s:popup_win_id, v:true )
call nvim_win_close( s:nvim_border_win_id, v:true )
call vimspector#internal#balloon#CloseCallback()
else
call popup_close(s:popup_win_id)
endif
endfunction
" }}}
" Neovim pollyfill {{{
function! vimspector#internal#balloon#ResizeTooltip() abort
if !s:is_neovim
" Vim does this for us
return
endif
if s:popup_win_id <= 0 || s:nvim_border_win_id <= 0
" nothing to resize
return
endif
noautocmd call win_gotoid( s:popup_win_id )
let buf_lines = getline( 1, '$' )
let width = s:min_width
let height = min( [ max( [ s:min_height, len( buf_lines ) ] ),
\ s:max_height ] )
" calculate the longest line
for l in buf_lines
let width = max( [ width, len( l ) ] )
endfor
let width = min( [ width, s:max_width ] )
let opts = {
\ 'width': width,
\ 'height': height,
\ }
" resize the content window
call nvim_win_set_config( s:popup_win_id, opts )
" resize the border window
let opts[ 'width' ] = width + 4
let opts[ 'height' ] = height + 2
call nvim_win_set_config( s:nvim_border_win_id, opts )
call nvim_buf_set_lines( nvim_win_get_buf( s:nvim_border_win_id ),
\ 0,
\ -1,
\ v:true,
\ s:GenerateBorder( width, height ) )
endfunction
" neovim doesn't have the border support, so we have to make our own.
" FIXME: This will likely break if the user has `ambiwidth=2`
function! s:GenerateBorder( width, height ) abort
let top = '╭' . repeat('─',a:width + 2) . '╮'
let mid = '│' . repeat(' ',a:width + 2) . '│'
let bot = '╰' . repeat('─',a:width + 2) . '╯'
let lines = [ top ] + repeat( [ mid ], a:height ) + [ bot ]
return lines
endfunction
function! s:CreateNeovimTooltip( body ) abort
" generate border for the float window by creating a background buffer and
" overlaying the content buffer
" see https://github.com/neovim/neovim/issues/9718#issuecomment-546603628
let buf_id = nvim_create_buf( v:false, v:true )
call nvim_buf_set_lines( buf_id,
\ 0,
\ -1,
\ v:true,
\ s:GenerateBorder( s:max_width, s:max_height ) )
" default the dimensions initially, then we'll calculate the real size and
" resize it.
let opts = {
\ 'relative': 'cursor',
\ 'width': s:max_width + 2,
\ 'height': s:max_height + 2,
\ 'col': 0,
\ 'row': 1,
\ 'anchor': 'NW',
\ 'style': 'minimal'
\ }
" this is the border window
let s:nvim_border_win_id = nvim_open_win( buf_id, 0, opts )
call nvim_win_set_option( s:nvim_border_win_id, 'signcolumn', 'no' )
call nvim_win_set_option( s:nvim_border_win_id, 'relativenumber', v:false )
call nvim_win_set_option( s:nvim_border_win_id, 'number', v:false )
" when calculating where to display the content window, we need to account
" for the border
let opts.row += 1
let opts.height -= 2
let opts.col += 2
let opts.width -= 4
" create the content window
let buf_id = nvim_create_buf( v:false, v:true )
call nvim_buf_set_lines( buf_id, 0, -1, v:true, a:body )
call nvim_buf_set_option( buf_id, 'modifiable', v:false )
let s:popup_win_id = nvim_open_win( buf_id, v:false, opts )
" Apparently none of these work, when 'style' is 'minimal'
call nvim_win_set_option( s:popup_win_id, 'wrap', v:false )
call nvim_win_set_option( s:popup_win_id, 'cursorline', v:true )
call nvim_win_set_option( s:popup_win_id, 'signcolumn', 'no' )
call nvim_win_set_option( s:popup_win_id, 'relativenumber', v:false )
call nvim_win_set_option( s:popup_win_id, 'number', v:false )
" Move the cursor into the popup window, as this is the only way we can
" interract with the popup in neovim
noautocmd call win_gotoid( s:popup_win_id )
nnoremap <silent> <buffer> <Esc> <cmd>quit<CR>
call py3eval( "__import__( 'vimspector', "
\." fromlist = [ 'variables' ] )."
\.' variables.AddExpandMappings()' )
" Close the popup whenever we leave this window
augroup vimspector#internal#balloon#nvim_float
autocmd!
autocmd WinLeave <buffer>
\ :call vimspector#internal#balloon#Close()
\ | autocmd! vimspector#internal#balloon#nvim_float
augroup END
call vimspector#internal#balloon#ResizeTooltip()
endfunction
" }}}
" Boilerplate {{{ " Boilerplate {{{
let &cpoptions=s:save_cpo let &cpoptions=s:save_cpo
unlet s:save_cpo unlet s:save_cpo

View file

@ -62,7 +62,7 @@ function! vimspector#internal#channel#StartDebugSession( config ) abort
\ ) \ )
endif endif
let l:addr = get( a:config, 'host', '127.0.0.1' ) . ':' . a:config[ 'port' ] let l:addr = get( a:config, 'host', 'localhost' ) . ':' . a:config[ 'port' ]
echo 'Connecting to ' . l:addr . '... (waiting fo up to 10 seconds)' echo 'Connecting to ' . l:addr . '... (waiting fo up to 10 seconds)'
let s:ch = ch_open( l:addr, let s:ch = ch_open( l:addr,
@ -95,44 +95,21 @@ EOF
endfunction endfunction
function! vimspector#internal#channel#StopDebugSession() abort function! vimspector#internal#channel#StopDebugSession() abort
if exists( 's:ch' ) && ch_status( s:ch ) ==# 'open'
if exists( 's:job' )
" We started the job, so we need to kill it and wait to read all the data
" from the socket
if job_status( s:job ) ==# 'run'
call job_stop( s:job, 'term' )
endif
while job_status( s:job ) ==# 'run'
call job_stop( s:job, 'kill' )
endwhile
unlet s:job
if exists( 's:ch' ) && count( [ 'closed', 'fail' ], ch_status( s:ch ) ) == 0
" We're going to block on this channel reading, then manually call the
" close callback, so remove the automatic close callback to avoid tricky
" re-entrancy
call ch_setoptions( s:ch, { 'close_cb': '' } )
endif
elseif exists( 's:ch' ) &&
\ count( [ 'closed', 'fail' ], ch_status( s:ch ) ) == 0
" channel is open, close it and trigger the callback. The callback is _not_ " channel is open, close it and trigger the callback. The callback is _not_
" triggered when manually calling ch_close. if we get here and the channel " triggered when manually calling ch_close. if we get here and the channel
" is not open, then we there is a _OnClose callback waiting for us, so do " is not open, then we there is a _OnClose callback waiting for us, so do
" nothing. " nothing.
call ch_close( s:ch ) call ch_close( s:ch )
call s:_OnClose( s:ch )
endif endif
" block until we've read all data from the socket and handled it. if exists( 's:job' )
while count( [ 'open', 'buffered' ], ch_status( s:ch ) ) == 1 if job_status( s:job ) ==# 'run'
let data = ch_read( s:ch, { 'timeout': 10 } ) call job_stop( s:job, 'kill' )
call s:_OnServerData( s:ch, data ) endif
endwhile unlet s:job
call s:_OnClose( s:ch ) endif
endfunction endfunction
function! vimspector#internal#channel#Reset() abort function! vimspector#internal#channel#Reset() abort

View file

@ -66,7 +66,7 @@ function! vimspector#internal#neochannel#StartDebugSession( config ) abort
endtry endtry
endif endif
let l:addr = get( a:config, 'host', '127.0.0.1' ) . ':' . a:config[ 'port' ] let l:addr = get( a:config, 'host', 'localhost' ) . ':' . a:config[ 'port' ]
let attempt = 1 let attempt = 1
while attempt <= 10 while attempt <= 10

View file

@ -159,16 +159,15 @@ function! s:_OnCommandEvent( category, id, data, event ) abort
call setbufvar( buffer, '&modified', 0 ) call setbufvar( buffer, '&modified', 0 )
endtry endtry
" if the buffer is visible, scroll it, but don't allow autocommands to fire, " if the buffer is visible, scroll it
" as this may close the current window!
let w = bufwinnr( buffer ) let w = bufwinnr( buffer )
if w > 0 if w > 0
let cw = winnr() let cw = winnr()
try try
noautocmd execute w . 'wincmd w' execute w . 'wincmd w'
noautocmd normal! Gz- normal! Gz-
finally finally
noautocmd execute cw . 'wincmd w' execute cw . 'wincmd w'
endtry endtry
endif endif
elseif a:event ==# 'exit' elseif a:event ==# 'exit'

View file

@ -80,56 +80,6 @@ function! vimspector#internal#neopopup#HideSplash( id ) abort
unlet s:db[ a:id ] unlet s:db[ a:id ]
endfunction endfunction
function! vimspector#internal#neopopup#Confirm( confirm_id,
\ text,
\ options,
\ default_value,
\ keys ) abort
" Neovim doesn't have an equivalent of popup_dialog, and it's way too much
" effort to write one, so we just use confirm()...
" Annoyingly we can't use confirm() here because for some reason it doesn't
" render properly in a channel callback. So we use input() and mimic dialog
" behaviour.
let prompt = a:text
for opt in a:options
let prompt .= ' ' . opt
endfor
let prompt .= ': '
try
let result = input( prompt, a:keys[ a:default_value - 1 ] )
catch /.*/
let result = -1
endtry
" Map the results to what the vim popup stuff would return (s:ConfirmCallback
" in popup.vim), i.e.:
" - 1-based index of selected item, or
" - -1 or 0 for cancellation
if result == ''
" User pressed ESC/ctrl-c
let result = -1
else
let index = 1
for k in a:keys
if k ==? result
let result = index
break
endif
let index += 1
endfor
if index > len( a:keys )
let result = -1
endif
endif
py3 __import__( 'vimspector', fromlist = [ 'utils' ] ).utils.ConfirmCallback(
\ int( vim.eval( 'a:confirm_id' ) ),
\ int( vim.eval( 'result' ) ) )
endfunction
" Boilerplate {{{ " Boilerplate {{{
let &cpoptions=s:save_cpo let &cpoptions=s:save_cpo
unlet s:save_cpo unlet s:save_cpo

View file

@ -12,7 +12,6 @@
" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
" See the License for the specific language governing permissions and " See the License for the specific language governing permissions and
" limitations under the License. " limitations under the License.
scriptencoding utf-8
" Boilerplate {{{ " Boilerplate {{{
@ -33,113 +32,6 @@ function! vimspector#internal#popup#HideSplash( id ) abort
call popup_hide( a:id ) call popup_hide( a:id )
endfunction endfunction
let s:current_selection = 0
let s:selections = []
let s:text = []
function! s:UpdatePopup( id ) abort
let buf = copy( s:text )
call extend( buf, s:DrawButtons() )
call popup_settext( a:id, buf )
endfunction
function! s:ConfirmKeyFilter( keys, id, key ) abort
if a:key ==# "\<CR>"
call popup_close( a:id, s:current_selection + 1 )
return 1
elseif index( [ "\<Tab>", "\<Right>" ], a:key ) >= 0
let s:current_selection = ( s:current_selection + 1 ) % len( s:selections )
call s:UpdatePopup( a:id )
return 1
elseif index( [ "\<S-Tab>", "\<Left>" ], a:key ) >= 0
let s:current_selection = s:current_selection == 0
\ ? len( s:selections ) - 1: s:current_selection - 1
call s:UpdatePopup( a:id )
return 1
elseif a:key ==# "\<Esc>" || a:key ==# "\<C-c>"
call popup_close( a:id, -1 )
return 1
endif
let index = 1
for key in a:keys
if a:key ==? key
call popup_close( a:id, index )
return 1
endif
let index += 1
endfor
endfunction
function! s:ConfirmCallback( confirm_id, id, result ) abort
py3 __import__( 'vimspector', fromlist = [ 'utils' ] ).utils.ConfirmCallback(
\ int( vim.eval( 'a:confirm_id' ) ),
\ int( vim.eval( 'a:result' ) ) )
endfunction
function! s:SelectionPosition( idx ) abort
return a:idx == 0 ? 0 : len( join( s:selections[ : a:idx - 1 ], ' ' ) ) + 1
endfunction
function! s:DrawButtons() abort
return [ {
\ 'text': join( s:selections, ' ' ),
\ 'props': [
\ {
\ 'col': s:SelectionPosition( s:current_selection ) + 1,
\ 'length': len( s:selections[ s:current_selection ] ),
\ 'type': 'VimspectorSelectedItem'
\ },
\ ]
\ } ]
endfunction
function! vimspector#internal#popup#Confirm(
\ confirm_id,
\ text,
\ options,
\ default_value,
\ keys ) abort
silent! call prop_type_add( 'VimspectorSelectedItem', {
\ 'highlight': 'PMenuSel'
\ } )
let lines = split( a:text, "\n", v:true )
let buf = []
for line in lines
call add( buf, { 'text': line, 'props': [] } )
endfor
call add( buf, { 'text': '', 'props': [] } )
let s:selections = a:options
let s:current_selection = ( a:default_value - 1 )
let s:text = copy( buf )
call extend( buf, s:DrawButtons() )
let config = {
\ 'callback': function( 's:ConfirmCallback', [ a:confirm_id ] ),
\ 'filter': function( 's:ConfirmKeyFilter', [ a:keys ] ),
\ 'mapping': v:false,
\ }
let config = vimspector#internal#popup#SetBorderChars( config )
return popup_dialog( buf, config )
endfunction
function! vimspector#internal#popup#SetBorderChars( config ) abort
" When ambiwidth is single, use prettier characters for the border. This
" would look silly when ambiwidth is double.
if &ambiwidth ==# 'single' && &encoding ==? 'utf-8'
let a:config[ 'borderchars' ] = [ '─', '│', '─', '│', '╭', '╮', '┛', '╰' ]
endif
return a:config
endfunction
" Boilerplate {{{ " Boilerplate {{{
let &cpoptions=s:save_cpo let &cpoptions=s:save_cpo
unlet s:save_cpo unlet s:save_cpo

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -28,5 +28,3 @@ gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
# Performance-booster for watching directories on Windows # Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.0" if Gem.win_platform? gem "wdm", "~> 0.1.0" if Gem.win_platform?
gem "webrick", "~> 1.7"

View file

@ -1,13 +1,13 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
activesupport (6.0.3.6) activesupport (6.0.3.2)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
minitest (~> 5.1) minitest (~> 5.1)
tzinfo (~> 1.1) tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2) zeitwerk (~> 2.2, >= 2.2.2)
addressable (2.8.0) addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0) public_suffix (>= 2.0.2, < 5.0)
coffee-script (2.4.1) coffee-script (2.4.1)
coffee-script-source coffee-script-source
@ -16,49 +16,46 @@ GEM
colorator (1.1.0) colorator (1.1.0)
commonmarker (0.17.13) commonmarker (0.17.13)
ruby-enum (~> 0.5) ruby-enum (~> 0.5)
concurrent-ruby (1.1.8) concurrent-ruby (1.1.7)
dnsruby (1.61.5) dnsruby (1.61.4)
simpleidn (~> 0.1) simpleidn (~> 0.1)
em-websocket (0.5.2) em-websocket (0.5.1)
eventmachine (>= 0.12.9) eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0) http_parser.rb (~> 0.6.0)
ethon (0.12.0) ethon (0.12.0)
ffi (>= 1.3.0) ffi (>= 1.3.0)
eventmachine (1.2.7) eventmachine (1.2.7)
execjs (2.7.0) execjs (2.7.0)
faraday (1.3.0) faraday (1.0.1)
faraday-net_http (~> 1.0)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
ruby2_keywords ffi (1.13.1)
faraday-net_http (1.0.1)
ffi (1.15.0)
forwardable-extended (2.6.0) forwardable-extended (2.6.0)
gemoji (3.0.1) gemoji (3.0.1)
github-pages (214) github-pages (207)
github-pages-health-check (= 1.17.0) github-pages-health-check (= 1.16.1)
jekyll (= 3.9.0) jekyll (= 3.9.0)
jekyll-avatar (= 0.7.0) jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1) jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.1.6) jekyll-commonmark-ghpages (= 0.1.6)
jekyll-default-layout (= 0.1.4) jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.15.1) jekyll-feed (= 0.13.0)
jekyll-gist (= 1.5.0) jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.13.0) jekyll-github-metadata (= 2.13.0)
jekyll-mentions (= 1.6.0) jekyll-mentions (= 1.5.1)
jekyll-optional-front-matter (= 0.3.2) jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0) jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0) jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0) jekyll-redirect-from (= 0.15.0)
jekyll-relative-links (= 0.6.1) jekyll-relative-links (= 0.6.1)
jekyll-remote-theme (= 0.4.3) jekyll-remote-theme (= 0.4.1)
jekyll-sass-converter (= 1.5.2) jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.7.1) jekyll-seo-tag (= 2.6.1)
jekyll-sitemap (= 1.4.0) jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0) jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.1.1) jekyll-theme-architect (= 0.1.1)
jekyll-theme-cayman (= 0.1.1) jekyll-theme-cayman (= 0.1.1)
jekyll-theme-dinky (= 0.1.1) jekyll-theme-dinky (= 0.1.1)
jekyll-theme-hacker (= 0.1.2) jekyll-theme-hacker (= 0.1.1)
jekyll-theme-leap-day (= 0.1.1) jekyll-theme-leap-day (= 0.1.1)
jekyll-theme-merlot (= 0.1.1) jekyll-theme-merlot (= 0.1.1)
jekyll-theme-midnight (= 0.1.1) jekyll-theme-midnight (= 0.1.1)
@ -69,20 +66,20 @@ GEM
jekyll-theme-tactile (= 0.1.1) jekyll-theme-tactile (= 0.1.1)
jekyll-theme-time-machine (= 0.1.1) jekyll-theme-time-machine (= 0.1.1)
jekyll-titles-from-headings (= 0.5.3) jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.12.0) jemoji (= 0.11.1)
kramdown (= 2.3.1) kramdown (= 2.3.0)
kramdown-parser-gfm (= 1.1.0) kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.3) liquid (= 4.0.3)
mercenary (~> 0.3) mercenary (~> 0.3)
minima (= 2.5.1) minima (= 2.5.1)
nokogiri (>= 1.10.4, < 2.0) nokogiri (>= 1.10.4, < 2.0)
rouge (= 3.26.0) rouge (= 3.19.0)
terminal-table (~> 1.4) terminal-table (~> 1.4)
github-pages-health-check (1.17.0) github-pages-health-check (1.16.1)
addressable (~> 2.3) addressable (~> 2.3)
dnsruby (~> 1.60) dnsruby (~> 1.60)
octokit (~> 4.0) octokit (~> 4.0)
public_suffix (>= 2.0.2, < 5.0) public_suffix (~> 3.0)
typhoeus (~> 1.3) typhoeus (~> 1.3)
html-pipeline (2.14.0) html-pipeline (2.14.0)
activesupport (>= 2) activesupport (>= 2)
@ -117,14 +114,14 @@ GEM
rouge (>= 2.0, < 4.0) rouge (>= 2.0, < 4.0)
jekyll-default-layout (0.1.4) jekyll-default-layout (0.1.4)
jekyll (~> 3.0) jekyll (~> 3.0)
jekyll-feed (0.15.1) jekyll-feed (0.13.0)
jekyll (>= 3.7, < 5.0) jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0) jekyll-gist (1.5.0)
octokit (~> 4.2) octokit (~> 4.2)
jekyll-github-metadata (2.13.0) jekyll-github-metadata (2.13.0)
jekyll (>= 3.4, < 5.0) jekyll (>= 3.4, < 5.0)
octokit (~> 4.0, != 4.4.0) octokit (~> 4.0, != 4.4.0)
jekyll-mentions (1.6.0) jekyll-mentions (1.5.1)
html-pipeline (~> 2.3) html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0) jekyll (>= 3.7, < 5.0)
jekyll-optional-front-matter (0.3.2) jekyll-optional-front-matter (0.3.2)
@ -132,19 +129,18 @@ GEM
jekyll-paginate (1.1.0) jekyll-paginate (1.1.0)
jekyll-readme-index (0.3.0) jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0) jekyll (>= 3.0, < 5.0)
jekyll-redirect-from (0.16.0) jekyll-redirect-from (0.15.0)
jekyll (>= 3.3, < 5.0) jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1) jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0) jekyll (>= 3.3, < 5.0)
jekyll-remote-theme (0.4.3) jekyll-remote-theme (0.4.1)
addressable (~> 2.0) addressable (~> 2.0)
jekyll (>= 3.5, < 5.0) jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) rubyzip (>= 1.3.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sass-converter (1.5.2) jekyll-sass-converter (1.5.2)
sass (~> 3.4) sass (~> 3.4)
jekyll-seo-tag (2.7.1) jekyll-seo-tag (2.6.1)
jekyll (>= 3.8, < 5.0) jekyll (>= 3.3, < 5.0)
jekyll-sitemap (1.4.0) jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0) jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0) jekyll-swiss (1.0.0)
@ -157,8 +153,8 @@ GEM
jekyll-theme-dinky (0.1.1) jekyll-theme-dinky (0.1.1)
jekyll (~> 3.5) jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0) jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.1.2) jekyll-theme-hacker (0.1.1)
jekyll (> 3.5, < 5.0) jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0) jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.1.1) jekyll-theme-leap-day (0.1.1)
jekyll (~> 3.5) jekyll (~> 3.5)
@ -192,44 +188,41 @@ GEM
jekyll (>= 3.3, < 5.0) jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1) jekyll-watch (2.2.1)
listen (~> 3.0) listen (~> 3.0)
jemoji (0.12.0) jemoji (0.11.1)
gemoji (~> 3.0) gemoji (~> 3.0)
html-pipeline (~> 2.2) html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0) jekyll (>= 3.0, < 5.0)
kramdown (2.3.1) kramdown (2.3.0)
rexml rexml
kramdown-parser-gfm (1.1.0) kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0) kramdown (~> 2.0)
liquid (4.0.3) liquid (4.0.3)
listen (3.5.1) listen (3.2.1)
rb-fsevent (~> 0.10, >= 0.10.3) rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10) rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6) mercenary (0.3.6)
mini_portile2 (2.5.1) mini_portile2 (2.4.0)
minima (2.5.1) minima (2.5.1)
jekyll (>= 3.5, < 5.0) jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9) jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1) jekyll-seo-tag (~> 2.1)
minitest (5.14.4) minitest (5.14.1)
multipart-post (2.1.1) multipart-post (2.1.1)
nokogiri (1.11.5) nokogiri (1.10.10)
mini_portile2 (~> 2.5.0) mini_portile2 (~> 2.4.0)
racc (~> 1.4) octokit (4.18.0)
octokit (4.20.0)
faraday (>= 0.9) faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3) sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2) pathutil (0.16.2)
forwardable-extended (~> 2.6) forwardable-extended (~> 2.6)
public_suffix (4.0.6) public_suffix (3.1.1)
racc (1.5.2)
rb-fsevent (0.10.4) rb-fsevent (0.10.4)
rb-inotify (0.10.1) rb-inotify (0.10.1)
ffi (~> 1.0) ffi (~> 1.0)
rexml (3.2.5) rexml (3.2.4)
rouge (3.26.0) rouge (3.19.0)
ruby-enum (0.9.0) ruby-enum (0.8.0)
i18n i18n
ruby2_keywords (0.0.4)
rubyzip (2.3.0) rubyzip (2.3.0)
safe_yaml (1.0.5) safe_yaml (1.0.5)
sass (3.7.4) sass (3.7.4)
@ -240,21 +233,20 @@ GEM
sawyer (0.8.2) sawyer (0.8.2)
addressable (>= 2.3.5) addressable (>= 2.3.5)
faraday (> 0.8, < 2.0) faraday (> 0.8, < 2.0)
simpleidn (0.2.1) simpleidn (0.1.1)
unf (~> 0.1.4) unf (~> 0.1.4)
terminal-table (1.8.0) terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1) unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6) thread_safe (0.3.6)
typhoeus (1.4.0) typhoeus (1.4.0)
ethon (>= 0.9.0) ethon (>= 0.9.0)
tzinfo (1.2.9) tzinfo (1.2.7)
thread_safe (~> 0.1) thread_safe (~> 0.1)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.7) unf_ext (0.0.7.7)
unicode-display_width (1.7.0) unicode-display_width (1.7.0)
webrick (1.7.0) zeitwerk (2.4.0)
zeitwerk (2.4.2)
PLATFORMS PLATFORMS
ruby ruby
@ -264,7 +256,6 @@ DEPENDENCIES
jekyll-feed (~> 0.6) jekyll-feed (~> 0.6)
minima (~> 2.0) minima (~> 2.0)
tzinfo-data tzinfo-data
webrick (~> 1.7)
BUNDLED WITH BUNDLED WITH
2.2.3 2.1.4

View file

@ -271,7 +271,7 @@ JSON value `true`, and the suffix is stripped fom the key, resulting in the
following: following:
```json ```json
"stopOnEntry": true "stopOnEntry#json": true
``` ```
Which is what we need. Which is what we need.
@ -633,26 +633,19 @@ Vimspector then orchestrates the various tools to set you up.
// Command to launch the debugee and attach the debugger; // Command to launch the debugee and attach the debugger;
// %CMD% replaced with the remote-cmdLine configured in the launch // %CMD% replaced with the remote-cmdLine configured in the launch
// configuration. (mandatory) // configuration. (mandatory)
"runCommand": [ "launchCommmand": [
"python", "-m", "debugpy", "python", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
"--listen", "0.0.0.0:${port}",
"--wait-for-client",
"%CMD%" "%CMD%"
] ]
// Optional alternative to runCommand (if you need to run multiple // Optional alternative to launchCommmand (if you need to run multiple
// commands) // commands)
// "runCommands": [ // "launchCommmands": [
// [ /* first command */ ], // [ /* first command */ ],
// [ /* second command */ ] // [ /* second command */ ]
// ] // ]
} }
// optional delay to wait after running runCommand(s). This is often
// needed because of the way docker handles TCP, or if you're using some
// wrapper (e.g. to start the JVM)
// "delay": "1000m" // format as per :help sleep
}, },
"attach": { "attach": {
"remote": { "remote": {
@ -692,10 +685,6 @@ Vimspector then orchestrates the various tools to set you up.
// "args": [ "-o", "StrictHostKeyChecking=no" ] // "args": [ "-o", "StrictHostKeyChecking=no" ]
// }, // },
} }
// optional delay to wait after running runCommand(s). This is often
// needed because of the way docker handles TCP, or if you're using some
// wrapper (e.g. to start the JVM)
// "delay": "1000m" // format as per :help sleep
} }
} }
}, },
@ -722,7 +711,7 @@ Vimspector then orchestrates the various tools to set you up.
"variables": { "variables": {
// Just an example of how to specify a variable manually rather than // Just an example of how to specify a variable manually rather than
// vimspector asking for input from the user // vimspector asking for input from the user
"ServiceName": "${fileBasenameNoExtension}" "ServiceName": "${fileBasenameNoExtention}"
}, },
"adapter": "python-remote", "adapter": "python-remote",
@ -765,7 +754,7 @@ and have to tell cpptools a few more options.
"remote": { "remote": {
"host": "${host}", "host": "${host}",
"account": "${account}", "account": "${account}",
"runCommand": [ "launchCommmand": [
"gdbserver", "gdbserver",
"--once", "--once",
"--no-startup-with-shell", "--no-startup-with-shell",
@ -849,25 +838,19 @@ port.
// Command to launch the debugee and attach the debugger; // Command to launch the debugee and attach the debugger;
// %CMD% replaced with the remote-cmdLine configured in the launch // %CMD% replaced with the remote-cmdLine configured in the launch
// configuration. (mandatory) // configuration. (mandatory)
"runCommand": [ "launchCommmand": [
"python", "-m", "debugpy", "python", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
"--listen", "0.0.0.0:${port}",
"--wait-for-client",
"%CMD%" "%CMD%"
] ]
// Optional alternative to runCommand (if you need to run multiple // Optional alternative to launchCommmand (if you need to run multiple
// commands) // commands)
// "runCommands": [ // "launchCommmands": [
// [ /* first command */ ], // [ /* first command */ ],
// [ /* second command */ ] // [ /* second command */ ]
// ] // ]
} }
// optional delay to wait after running runCommand(s). This is often
// needed because of the way docker handles TCP
"delay": "1000m" // format as per :help sleep
}, },
"attach": { "attach": {
"remote": { "remote": {
@ -903,11 +886,6 @@ port.
// ] // ]
} }
// optional delay to wait after running runCommand(s). This is often
// needed because of the way docker handles TCP, or if you're using some
// wrapper (e.g. to start the JVM)
"delay": "1000m" // format as per :help sleep
} }
} }
}, },

View file

@ -38,144 +38,11 @@
] ]
} }
}, },
"adapter-launchattach": { "adapter-common": {
"properties": {
"launch": {
"allOf": [
{ "$ref": "#/definitions/adapter-remote" },
{
"properties": {
"delay": {
"type": "string",
"description": "A time in the format understood by :help :sleep to wait after running the attachCommand(s)"
}
}
}
]
},
"attach": {
"allOf": [
{ "$ref": "#/definitions/adapter-remote" },
{
"type": "object",
"required": [ "pidSelect" ],
"properties": {
"pidSelect": {
"enum": [ "ask", "none" ]
},
"pidProperty": {
"type": "string",
"description": "The launch config property which the PID should be injected into. Required when 'pidSelect' is 'ask'."
},
"delay": {
"type": "string",
"description": "A time in the format understood by :help :sleep to wait after running the attachCommand(s)"
}
}
}
]
}
}
},
"adapter-remote": {
"type": "object",
"properties": {
"remote": {
"type": "object",
"description": "Configures how Vimspector will marshal remote debugging requests. When remote debugging, Vimspector will either ssh to 'account'@'host' or docker exec -it to 'container' and run 'pidCommand', 'attachCommands', 'runCommands', etc. based on the 'remote-command' option in the debug configuration. If 'remote-command' is 'launch', it runs 'runCommand(s)', otherwise (it's 'attach') vimspector runs 'pidCommand', followed by 'attachCommand(s)'.Then it starts up the debug adapter with the debug configuration as normal. Usually this is configured with an 'attach' request (whether we remotely 'launched' or not). Once the initialization exchange is complete, Vimspector runs the optional 'initCompleteCommand' which can be used to force the application to break, e.g. by sending it SIGINT. This is required on some platforms which have buggy gdbservers (for example)",
"allOf": [
{
"oneOf": [
{ "required": [ "host" ] },
{ "required": [ "container" ] }
]
},
{
"properties": {
"account": {
"type": "string",
"description": "Remote account name used when ssh'ing. Defaults to the current user account."
},
"host": {
"type": "string",
"description": "Name of the remote host to connect to (via passwordless SSH)."
},
"container": {
"type": "string",
"description": "Name or container id of the docker run container to connect to (via docker exec). Note the container must already be running (Vimspector will not start it) and it must have the port forwarded to the host if subsequently connecting via a port (for example <tt>docker run -p 8765:8765 -it simple_python</tt>)."
}
}
},
{
"oneOf": [
{
"allOf": [
{
"oneOf": [
{ "required": [ "attachCommand" ] },
{ "required": [ "attachCommands" ] }
]
},
{
"properties": {
"initCompleteCommand": {
"type": "array",
"items": { "type": "string" },
"description": "For remote-attach. Remote command to execute after initialization of the debug adapter. Can be used to work around buggy attach behaviour on certain platforms (advanced usage). Can contain the special token %PID% which is replaced with the PID returned by 'pidCommand'"
},
"pidCommand": {
"type": "array",
"items": { "type": "string" },
"description": "Required for remote-attach. Remote command to execute to return the PID to attach to."
},
"attachCommands": {
"type": [ "array" ],
"items": { "type": "array", "items": { "type": "string" } },
"description": "For remote-attach. List of commands to execute remotely to set up the attach. Can contain the special token %PID% which is replaced with the PID returned by the remote 'pidCommand'."
},
"attachCommand": {
"type": "array",
"items": { "type": "string" },
"description": "A single command to execute for remote-attach. Like attachCommands but for a single command. If attachCommands is supplied, this is not used."
}
}
}
]
},
{
"allOf": [
{
"oneOf": [
{ "required": [ "runCommand" ] },
{ "required": [ "runCommands" ] }
]
},
{
"properties": {
"runCommands": {
"type": [ "array" ],
"items": { "type": "array", "items": { "type": "string" } },
"description": "For remote-launch. List of commands to execute remotely to set up the launch. An entry in the array can be the special token '%CMD%' which is replaced with the evaluated 'remote-cmdLine' value in the debug configuration. This is useful to parameterize launcging remotely under something like gdbserver."
},
"runCommand": {
"type": "array",
"items": { "type": "string" },
"description": "A single command to execute for remote-launch. Like runCommands but for a single command."
}
}
}
]
}
]
}
]
}
}
},
"adapter": {
"allOf": [ "allOf": [
{ "type": "object" },
{ "$ref": "#/definitions/variables" }, { "$ref": "#/definitions/variables" },
{ "$ref": "#/definitions/adapter-remote" },
{ "$ref": "#/definitions/adapter-attach" },
{ {
"properties": { "properties": {
"name": { "name": {
@ -187,30 +54,136 @@
"description": "Base debug configuration. Can be used to set default values for all debug configurations. When reading individual debug configurations from 'configurations', those configurations are merged with this object. Definitions in the debug configuration override anything in this object. Typical usage for this is to set the 'type' parameter, which some debug adapters are very picky about, or to set e.g. the path to an underlying debugger." "description": "Base debug configuration. Can be used to set default values for all debug configurations. When reading individual debug configurations from 'configurations', those configurations are merged with this object. Definitions in the debug configuration override anything in this object. Typical usage for this is to set the 'type' parameter, which some debug adapters are very picky about, or to set e.g. the path to an underlying debugger."
} }
} }
}, }
{ "$ref": "#/definitions/adapter-launchattach" }, ]
},
"adapter-attach": {
"properties": {
"attach": {
"type": "object",
"required": [ "pidSelect" ],
"properties": {
"pidSelect": {
"enum": [ "ask", "none" ]
},
"pidProperty": {
"type": "string",
"description": "The launch config property which the PID should be injected into. Required when 'pidSelect' is 'ask'."
}
}
}
}
},
"adapter-remote": {
"properties": {
"remote": {
"type": "object",
"oneOf": [
{
"required": [
"host"
]
},
{
"required": [
"container"
]
}
],
"description": "Configures how Vimspector will marshal remote debugging requests. When remote debugging, Vimspector will either ssh to 'account'@'host' or docker exec -it to 'container' and run 'pidCommand', 'attachCommands', 'runCommands', etc. based on the 'remote-command' option in the debug configuration. If 'remote-command' is 'launch', it runs 'runCommand(s)', otherwise (it's 'attach') vimspector runs 'pidCommand', followed by 'attachCommand(s)'.Then it starts up the debug adapter with the debug configuration as normal. Usually this is configured with an 'attach' request (whether we remotely 'launched' or not). Once the initialization exchange is complete, Vimspector runs the optional 'initCompleteCommand' which can be used to force the application to break, e.g. by sending it SIGINT. This is required on some platforms which have buggy gdbservers (for example)",
"properties": {
"account": {
"type": "string",
"description": "Remote account name used when ssh'ing. Defaults to the current user account."
},
"host": {
"type": "string",
"description": "Name of the remote host to connect to (via passwordless SSH)."
},
"container": {
"type": "string",
"description": "Name or container id of the docker run container to connect to (via docker exec -it)."
},
"pidCommand": {
"type": "array",
"items": { "type": "string" },
"description": "Required for remote-attach. Remote command to execute to return the PID to attach to."
},
"initCompleteCommand": {
"type": "array",
"items": { "type": "string" },
"description": "For remote-attach. Remote command to execute after initialization of the debug adapter. Can be used to work around buggy attach behaviour on certain platforms (advanced usage). Can contain the special token %PID% which is replaced with the PID returned by 'pidCommand'"
},
"attachCommands": {
"type": [ "array" ],
"items": { "type": "array", "items": { "type": "string" } },
"description": "For remote-attach. List of commands to execute remotely to set up the attach. Can contain the special token %PID% which is replaced with the PID returned by the remote 'pidCommand'."
},
"attachCommand": {
"type": "array",
"items": { "type": "string" },
"description": "A single command to execute for remote-attach. Like attachCommands but for a single command. If attachCommands is supplied, this is not used."
},
"runCommands": {
"type": [ "array" ],
"items": { "type": "array", "items": { "type": "string" } },
"description": "For remote-launch. List of commands to execute remotely to set up the launch. An entry in the array can be the special token '%CMD%' which is replaced with the evaluated 'remote-cmdLine' value in the debug configuration. This is useful to parameterize launcging remotely under something like gdbserver."
},
"runCommand": {
"type": "array",
"items": { "type": "string" },
"description": "A single command to execute for remote-launch. Like runCommands but for a single command."
}
}
}
}
},
"adapter": {
"oneOf": [
{ {
"anyOf": [ "allOf": [
{ "required": [ "command" ] }, { "$ref": "#/definitions/adapter-common" },
{ "required": [ "port" ] }, {
{ "required": [ "command", "port" ] } "required": [ "port" ],
"properties": {
"port": {
"oneOf": [
{
"type": "string",
"enum": [ "ask" ]
},
{
"type": "integer"
}
],
"description": "If supplied, indicates that a socket connection should be made to this port on 'localhost'. If the value is 'ask', then the user is asked to enter the port number to connect to."
}
}
}
] ]
}, },
{ {
"properties": { "allOf": [
"host": { { "$ref": "#/definitions/adapter-common" },
"type": "string", {
"default": "127.0.0.1", "required": [ "command" ],
"description": "Connect to this host in multi-session mode" "properties": {
}, "command": {
"port": { "type": [ "string", "array" ],
"oneOf": [ "description": "Command line to execute the debug adapter.",
{ "type": "string" }, "items": { "type": "string" }
{ "type": "integer" } },
], "env": {
"description": "If supplied, indicates that a socket connection should be made to this port on 'host'. If the value is 'ask', then the user is asked to enter the port number to connect to." "type": "object",
"description": "Name/value pairs to set in the environment when starting the adapter."
},
"cwd": {
"type": "string",
"description": "Directory from which to start the adapter. Defaults to the working directory of the window on launch"
}
}
} }
} ]
} }
] ]
} }

View file

@ -114,35 +114,32 @@ parser.add_argument( '--sudo',
done_languages = set() done_languages = set()
for name, gadget in gadgets.GADGETS.items(): for name, gadget in gadgets.GADGETS.items():
langs = gadget[ 'language' ] lang = gadget[ 'language' ]
if not isinstance( langs, list ): if lang in done_languages:
langs = [ langs ] continue
for lang in langs:
if lang in done_languages:
continue
done_languages.add( lang )
if not gadget.get( 'enabled', True ):
parser.add_argument(
'--force-enable-' + lang,
action = 'store_true',
help = 'Install the unsupported {} debug adapter for {} support'.format(
name,
lang ) )
continue
done_languages.add( lang )
if not gadget.get( 'enabled', True ):
parser.add_argument( parser.add_argument(
'--enable-' + lang, '--force-enable-' + lang,
action = 'store_true', action = 'store_true',
help = 'Install the {} debug adapter for {} support'.format( help = 'Install the unsupported {} debug adapter for {} support'.format(
name, name,
lang ) ) lang ) )
continue
parser.add_argument( parser.add_argument(
'--disable-' + lang, '--enable-' + lang,
action = 'store_true', action = 'store_true',
help = "Don't install the {} debug adapter for {} support " help = 'Install the {} debug adapter for {} support'.format(
'(when supplying --all)'.format( name, lang ) ) name,
lang ) )
parser.add_argument(
'--disable-' + lang,
action = 'store_true',
help = "Don't install the {} debug adapter for {} support "
'(when supplying --all)'.format( name, lang ) )
parser.add_argument( parser.add_argument(
"--no-check-certificate", "--no-check-certificate",
@ -185,25 +182,15 @@ all_adapters = installer.ReadAdapters(
manifest = installer.Manifest() manifest = installer.Manifest()
for name, gadget in gadgets.GADGETS.items(): for name, gadget in gadgets.GADGETS.items():
langs = gadget[ 'language' ] if not gadget.get( 'enabled', True ):
if not isinstance( langs, list ): if ( not args.force_all
langs = [ langs ] and not getattr( args, 'force_enable_' + gadget[ 'language' ] ) ):
skip = 0 continue
for lang in langs: else:
if not gadget.get( 'enabled', True ): if not args.all and not getattr( args, 'enable_' + gadget[ 'language' ] ):
if ( not args.force_all continue
and not getattr( args, 'force_enable_' + lang ) ): if getattr( args, 'disable_' + gadget[ 'language' ] ):
skip = skip + 1 continue
continue
else:
if not args.all and not getattr( args, 'enable_' + lang ):
skip = skip + 1
continue
if getattr( args, 'disable_' + lang ):
skip = skip + 1
continue
if skip == len( langs ):
continue
if not args.upgrade: if not args.upgrade:
manifest.Clear( name ) manifest.Clear( name )

View file

@ -13,13 +13,6 @@
" See the License for the specific language governing permissions and " See the License for the specific language governing permissions and
" limitations under the License. " limitations under the License.
if !has( 'python3' )
echohl WarningMsg
echom 'Vimspector unavailable: Requires Vim compiled with +python3'
echohl None
finish
endif
" Boilerplate {{{ " Boilerplate {{{
let s:save_cpo = &cpoptions let s:save_cpo = &cpoptions
set cpoptions&vim set cpoptions&vim
@ -42,8 +35,6 @@ let s:mappings = get( g:, 'vimspector_enable_mappings', '' )
nnoremap <silent> <Plug>VimspectorContinue nnoremap <silent> <Plug>VimspectorContinue
\ :<c-u>call vimspector#Continue()<CR> \ :<c-u>call vimspector#Continue()<CR>
nnoremap <silent> <Plug>VimspectorLaunch
\ :<c-u>call vimspector#Launch( v:true )<CR>
nnoremap <silent> <Plug>VimspectorStop nnoremap <silent> <Plug>VimspectorStop
\ :<c-u>call vimspector#Stop()<CR> \ :<c-u>call vimspector#Stop()<CR>
nnoremap <silent> <Plug>VimspectorRestart nnoremap <silent> <Plug>VimspectorRestart
@ -69,18 +60,6 @@ nnoremap <silent> <Plug>VimspectorStepOut
nnoremap <silent> <Plug>VimspectorRunToCursor nnoremap <silent> <Plug>VimspectorRunToCursor
\ :<c-u>call vimspector#RunToCursor()<CR> \ :<c-u>call vimspector#RunToCursor()<CR>
" Eval for normal mode
nnoremap <silent> <Plug>VimspectorBalloonEval
\ :<c-u>call vimspector#ShowEvalBalloon( 0 )<CR>
" And for visual modes
xnoremap <silent> <Plug>VimspectorBalloonEval
\ :<c-u>call vimspector#ShowEvalBalloon( 1 )<CR>
nnoremap <silent> <Plug>VimspectorUpFrame
\ :<c-u>call vimspector#UpFrame()<CR>
nnoremap <silent> <Plug>VimspectorDownFrame
\ :<c-u>call vimspector#DownFrame()<CR>
if s:mappings ==# 'VISUAL_STUDIO' if s:mappings ==# 'VISUAL_STUDIO'
nmap <F5> <Plug>VimspectorContinue nmap <F5> <Plug>VimspectorContinue
nmap <S-F5> <Plug>VimspectorStop nmap <S-F5> <Plug>VimspectorStop
@ -93,7 +72,6 @@ if s:mappings ==# 'VISUAL_STUDIO'
nmap <S-F11> <Plug>VimspectorStepOut nmap <S-F11> <Plug>VimspectorStepOut
elseif s:mappings ==# 'HUMAN' elseif s:mappings ==# 'HUMAN'
nmap <F5> <Plug>VimspectorContinue nmap <F5> <Plug>VimspectorContinue
nmap <leader><F5> <Plug>VimspectorLaunch
nmap <F3> <Plug>VimspectorStop nmap <F3> <Plug>VimspectorStop
nmap <F4> <Plug>VimspectorRestart nmap <F4> <Plug>VimspectorRestart
nmap <F6> <Plug>VimspectorPause nmap <F6> <Plug>VimspectorPause
@ -115,15 +93,12 @@ command! -bar -nargs=? -complete=custom,vimspector#CompleteOutput
command! -bar command! -bar
\ VimspectorToggleLog \ VimspectorToggleLog
\ call vimspector#ToggleLog() \ call vimspector#ToggleLog()
command! -bar command! -bar -nargs=1 -complete=custom,vimspector#CompleteExpr
\ VimspectorDebugInfo
\ call vimspector#PrintDebugInfo()
command! -nargs=1 -complete=custom,vimspector#CompleteExpr
\ VimspectorEval \ VimspectorEval
\ call vimspector#Evaluate( <f-args> ) \ call vimspector#Evaluate( <f-args> )
command! -bar command! -bar
\ VimspectorReset \ VimspectorReset
\ call vimspector#Reset( { 'interactive': v:true } ) \ call vimspector#Reset()
" Installer commands " Installer commands
command! -bar -bang -nargs=* -complete=custom,vimspector#CompleteInstall command! -bar -bang -nargs=* -complete=custom,vimspector#CompleteInstall
@ -143,11 +118,8 @@ augroup VimspectorUserAutoCmds
autocmd! autocmd!
autocmd User VimspectorUICreated silent autocmd User VimspectorUICreated silent
autocmd User VimspectorTerminalOpened silent autocmd User VimspectorTerminalOpened silent
autocmd user VimspectorJumpedToFrame silent
autocmd user VimspectorDebugEnded silent
augroup END augroup END
" FIXME: Only register this _while_ debugging is active
augroup Vimspector augroup Vimspector
autocmd! autocmd!
autocmd BufNew * call vimspector#OnBufferCreated( expand( '<afile>' ) ) autocmd BufNew * call vimspector#OnBufferCreated( expand( '<afile>' ) )

View file

@ -134,7 +134,6 @@ class CodeView( object ):
utils.JumpToWindow( self._window ) utils.JumpToWindow( self._window )
try: try:
utils.OpenFileInCurrentWindow( frame[ 'source' ][ 'path' ] ) utils.OpenFileInCurrentWindow( frame[ 'source' ][ 'path' ] )
vim.command( 'doautocmd <nomodeline> User VimspectorJumpedToFrame' )
except vim.error: except vim.error:
self._logger.exception( 'Unexpected vim error opening file {}'.format( self._logger.exception( 'Unexpected vim error opening file {}'.format(
frame[ 'source' ][ 'path' ] ) ) frame[ 'source' ][ 'path' ] ) )

View file

@ -1,51 +0,0 @@
# vimspector - A multi-language debugging system for Vim
# Copyright 2021 Ben Jackson
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from vimspector.debug_session import DebugSession
from vimspector import utils, settings
class JavaDebugAdapter( object ):
def __init__( self, debug_session: DebugSession ):
self.debug_session = debug_session
def OnEvent_hotcodereplace( self, message ):
# Hack for java debug server hot-code-replace
body = message.get( 'body' ) or {}
if body.get( 'type' ) != 'hotcodereplace':
return
if body.get( 'changeType' ) == 'BUILD_COMPLETE':
def handler( result ):
if result == 1:
self.debug_session._connection.DoRequest( None, {
'command': 'redefineClasses',
'arguments': {},
} )
mode = settings.Get( 'java_hotcodereplace_mode' )
if mode == 'ask':
utils.Confirm( self.debug_session._api_prefix,
'Code has changed, hot reload?',
handler,
default_value = 1 )
elif mode == 'always':
self.debug_session._connection.DoRequest( None, {
'command': 'redefineClasses',
'arguments': {},
} )
elif body.get( 'message' ):
utils.UserMessage( 'Hot code replace: ' + body[ 'message' ] )

View file

@ -29,14 +29,14 @@ class PendingRequest( object ):
class DebugAdapterConnection( object ): class DebugAdapterConnection( object ):
def __init__( self, handlers, send_func ): def __init__( self, handler, send_func ):
self._logger = logging.getLogger( __name__ ) self._logger = logging.getLogger( __name__ )
utils.SetUpLogging( self._logger ) utils.SetUpLogging( self._logger )
self._Write = send_func self._Write = send_func
self._SetState( 'READ_HEADER' ) self._SetState( 'READ_HEADER' )
self._buffer = bytes() self._buffer = bytes()
self._handlers = handlers self._handler = handler
self._next_message_id = 0 self._next_message_id = 0
self._outstanding_requests = {} self._outstanding_requests = {}
@ -124,7 +124,7 @@ class DebugAdapterConnection( object ):
def Reset( self ): def Reset( self ):
self._Write = None self._Write = None
self._handlers = None self._handler = None
while self._outstanding_requests: while self._outstanding_requests:
_, request = self._outstanding_requests.popitem() _, request = self._outstanding_requests.popitem()
@ -226,12 +226,7 @@ class DebugAdapterConnection( object ):
# self._logger.debug( 'Message received (raw): %s', payload ) # self._logger.debug( 'Message received (raw): %s', payload )
try: message = json.loads( payload )
message = json.loads( payload, strict = False )
except Exception:
self._logger.exception( "Invalid message received: %s", payload )
self._SetState( 'READ_HEADER' )
raise
self._logger.debug( 'Message received: {0}'.format( message ) ) self._logger.debug( 'Message received: {0}'.format( message ) )
@ -242,7 +237,7 @@ class DebugAdapterConnection( object ):
def _OnMessageReceived( self, message ): def _OnMessageReceived( self, message ):
if not self._handlers: if not self._handler:
return return
if message[ 'type' ] == 'response': if message[ 'type' ] == 'response':
@ -275,21 +270,25 @@ class DebugAdapterConnection( object ):
self._logger.error( 'Request failed: {0}'.format( reason ) ) self._logger.error( 'Request failed: {0}'.format( reason ) )
if request.failure_handler: if request.failure_handler:
request.failure_handler( reason, message ) request.failure_handler( reason, message )
elif 'OnFailure' in dir( self._handler ):
self._handler.OnFailure( reason, request.msg, message )
else: else:
for h in self._handlers: utils.UserMessage( 'Request failed: {0}'.format( reason ) )
if 'OnFailure' in dir( h ):
h.OnFailure( reason, request.msg, message )
elif message[ 'type' ] == 'event': elif message[ 'type' ] == 'event':
method = 'OnEvent_' + message[ 'event' ] method = 'OnEvent_' + message[ 'event' ]
for h in self._handlers: if method in dir( self._handler ):
if method in dir( h ): getattr( self._handler, method )( message )
getattr( h, method )( message ) else:
utils.UserMessage( 'Unhandled event: {0}'.format( message[ 'event' ] ),
persist = True )
elif message[ 'type' ] == 'request': elif message[ 'type' ] == 'request':
method = 'OnRequest_' + message[ 'command' ] method = 'OnRequest_' + message[ 'command' ]
for h in self._handlers: if method in dir( self._handler ):
if method in dir( h ): getattr( self._handler, method )( message )
getattr( h, method )( message ) else:
utils.UserMessage(
'Unhandled request: {0}'.format( message[ 'command' ] ),
persist = True )
def _KillTimer( request ): def _KillTimer( request ):

View file

@ -21,7 +21,6 @@ import shlex
import subprocess import subprocess
import functools import functools
import vim import vim
import importlib
from vimspector import ( breakpoints, from vimspector import ( breakpoints,
code, code,
@ -69,7 +68,6 @@ class DebugSession( object ):
self._configuration = None self._configuration = None
self._adapter = None self._adapter = None
self._launch_config = None
self._ResetServerState() self._ResetServerState()
@ -100,7 +98,7 @@ class DebugSession( object ):
return launch_config_file, configurations return launch_config_file, configurations
def Start( self, force_choose=False, launch_variables = None ): def Start( self, launch_variables = None ):
# We mutate launch_variables, so don't mutate the default argument. # We mutate launch_variables, so don't mutate the default argument.
# https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments # https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
if launch_variables is None: if launch_variables is None:
@ -110,7 +108,6 @@ class DebugSession( object ):
launch_variables ) launch_variables )
self._configuration = None self._configuration = None
self._adapter = None self._adapter = None
self._launch_config = None
current_file = utils.GetBufferFilepath( vim.current.buffer ) current_file = utils.GetBufferFilepath( vim.current.buffer )
adapters = {} adapters = {}
@ -135,11 +132,6 @@ class DebugSession( object ):
if 'configuration' in launch_variables: if 'configuration' in launch_variables:
configuration_name = launch_variables.pop( 'configuration' ) configuration_name = launch_variables.pop( 'configuration' )
elif force_choose:
# Always display the menu
configuration_name = utils.SelectFromList(
'Which launch configuration?',
sorted( configurations.keys() ) )
elif ( len( configurations ) == 1 and elif ( len( configurations ) == 1 and
next( iter( configurations.values() ) ).get( "autoselect", True ) ): next( iter( configurations.values() ) ).get( "autoselect", True ) ):
configuration_name = next( iter( configurations.keys() ) ) configuration_name = next( iter( configurations.keys() ) )
@ -288,7 +280,6 @@ class DebugSession( object ):
def start(): def start():
self._configuration = configuration self._configuration = configuration
self._adapter = adapter self._adapter = adapter
self._launch_config = None
self._logger.info( 'Configuration: %s', self._logger.info( 'Configuration: %s',
json.dumps( self._configuration ) ) json.dumps( self._configuration ) )
@ -300,7 +291,6 @@ class DebugSession( object ):
else: else:
vim.current.tabpage = self._uiTab vim.current.tabpage = self._uiTab
self._Prepare()
self._StartDebugAdapter() self._StartDebugAdapter()
self._Initialise() self._Initialise()
@ -326,7 +316,7 @@ class DebugSession( object ):
if self._connection: if self._connection:
self._logger.debug( "_StopDebugAdapter with callback: start" ) self._logger.debug( "_StopDebugAdapter with callback: start" )
self._StopDebugAdapter( interactive = False, callback = start ) self._StopDebugAdapter( start )
return return
start() start()
@ -391,15 +381,14 @@ class DebugSession( object ):
self._connection = None self._connection = None
@IfConnected() @IfConnected()
def Stop( self, interactive = False ): def Stop( self ):
self._logger.debug( "Stop debug adapter with no callback" ) self._logger.debug( "Stop debug adapter with no callback" )
self._StopDebugAdapter( interactive = interactive ) self._StopDebugAdapter()
def Reset( self, interactive = False ): def Reset( self ):
if self._connection: if self._connection:
self._logger.debug( "Stop debug adapter with callback : self._Reset()" ) self._logger.debug( "Stop debug adapter with callback : self._Reset()" )
self._StopDebugAdapter( interactive = interactive, self._StopDebugAdapter( lambda: self._Reset() )
callback = lambda: self._Reset() )
else: else:
self._Reset() self._Reset()
@ -419,7 +408,6 @@ class DebugSession( object ):
self._outputView.Reset() self._outputView.Reset()
self._codeView.Reset() self._codeView.Reset()
vim.command( 'tabclose!' ) vim.command( 'tabclose!' )
vim.command( 'doautocmd <nomodeline> User VimspectorDebugEnded' )
self._stackTraceView = None self._stackTraceView = None
self._variablesView = None self._variablesView = None
self._outputView = None self._outputView = None
@ -528,12 +516,8 @@ class DebugSession( object ):
self._stackTraceView.SetCurrentThread() self._stackTraceView.SetCurrentThread()
@IfConnected() @IfConnected()
def ExpandVariable( self, buf = None, line_num = None ): def ExpandVariable( self ):
self._variablesView.ExpandVariable( buf, line_num ) self._variablesView.ExpandVariable()
@IfConnected()
def SetVariableValue( self, new_value = None, buf = None, line_num = None ):
self._variablesView.SetVariableValue( new_value, buf, line_num )
@IfConnected() @IfConnected()
def AddWatch( self, expression ): def AddWatch( self, expression ):
@ -550,13 +534,13 @@ class DebugSession( object ):
def DeleteWatch( self ): def DeleteWatch( self ):
self._variablesView.DeleteWatch() self._variablesView.DeleteWatch()
@IfConnected() @IfConnected()
def ShowEvalBalloon( self, winnr, expression, is_hover ): def ShowBalloon( self, winnr, expression ):
"""Proxy: ballonexpr -> variables.ShowBallon"""
frame = self._stackTraceView.GetCurrentFrame() frame = self._stackTraceView.GetCurrentFrame()
# Check if RIP is in a frame # Check if RIP is in a frame
if frame is None: if frame is None:
self._logger.debug( 'Tooltip: Not in a stack frame' ) self._logger.debug( 'Balloon: Not in a stack frame' )
return '' return ''
# Check if cursor in code window # Check if cursor in code window
@ -567,24 +551,12 @@ class DebugSession( object ):
return '' return ''
# Return variable aware function # Return variable aware function
return self._variablesView.VariableEval( frame, expression, is_hover ) return self._variablesView.ShowBalloon( frame, expression )
def CleanUpTooltip( self ):
return self._variablesView.CleanUpTooltip()
@IfConnected() @IfConnected()
def ExpandFrameOrThread( self ): def ExpandFrameOrThread( self ):
self._stackTraceView.ExpandFrameOrThread() self._stackTraceView.ExpandFrameOrThread()
@IfConnected()
def UpFrame( self ):
self._stackTraceView.UpFrame()
@IfConnected()
def DownFrame( self ):
self._stackTraceView.DownFrame()
def ToggleLog( self ): def ToggleLog( self ):
if self._HasUI(): if self._HasUI():
return self.ShowOutput( 'Vimspector' ) return self.ShowOutput( 'Vimspector' )
@ -646,18 +618,6 @@ class DebugSession( object ):
return response[ 'body' ][ 'targets' ] return response[ 'body' ][ 'targets' ]
@IfConnected( otherwise=[] )
def GetCommandLineCompletions( self, ArgLead, prev_non_keyword_char ):
items = []
for candidate in self.GetCompletionsSync( ArgLead, prev_non_keyword_char ):
label = candidate.get( 'text', candidate[ 'label' ] )
start = prev_non_keyword_char - 1
if 'start' in candidate and 'length' in candidate:
start = candidate[ 'start' ]
items.append( ArgLead[ 0 : start ] + label )
return items
def RefreshSigns( self, file_name ): def RefreshSigns( self, file_name ):
if self._connection: if self._connection:
self._codeView.Refresh( file_name ) self._codeView.Refresh( file_name )
@ -669,45 +629,6 @@ class DebugSession( object ):
vim.command( 'tab split' ) vim.command( 'tab split' )
self._uiTab = vim.current.tabpage self._uiTab = vim.current.tabpage
mode = settings.Get( 'ui_mode' )
if mode == 'auto':
# Go vertical if there isn't enough horizontal space for at least:
# the left bar width
# + the code min width
# + the terminal min width
# + enough space for a sign column and number column?
min_width = ( settings.Int( 'sidebar_width' )
+ 1 + 2 + 3
+ settings.Int( 'code_minwidth' )
+ 1 + settings.Int( 'terminal_minwidth' ) )
min_height = ( settings.Int( 'code_minheight' ) + 1 +
settings.Int( 'topbar_height' ) + 1 +
settings.Int( 'bottombar_height' ) + 1 +
2 )
mode = ( 'vertical'
if vim.options[ 'columns' ] < min_width
else 'horizontal' )
if vim.options[ 'lines' ] < min_height:
mode = 'horizontal'
self._logger.debug( 'min_width/height: %s/%s, actual: %s/%s - result: %s',
min_width,
min_height,
vim.options[ 'columns' ],
vim.options[ 'lines' ],
mode )
if mode == 'vertical':
self._SetUpUIVertical()
else:
self._SetUpUIHorizontal()
def _SetUpUIHorizontal( self ):
# Code window # Code window
code_window = vim.current.window code_window = vim.current.window
self._codeView = code.CodeView( code_window, self._api_prefix ) self._codeView = code.CodeView( code_window, self._api_prefix )
@ -748,73 +669,12 @@ class DebugSession( object ):
# TODO: If/when we support multiple sessions, we'll need some way to # TODO: If/when we support multiple sessions, we'll need some way to
# indicate which tab was created and store all the tabs # indicate which tab was created and store all the tabs
vim.vars[ 'vimspector_session_windows' ] = { vim.vars[ 'vimspector_session_windows' ] = {
'mode': 'horizontal',
'tabpage': self._uiTab.number, 'tabpage': self._uiTab.number,
'code': utils.WindowID( code_window, self._uiTab ), 'code': utils.WindowID( code_window, self._uiTab ),
'stack_trace': utils.WindowID( stack_trace_window, self._uiTab ), 'stack_trace': utils.WindowID( stack_trace_window, self._uiTab ),
'variables': utils.WindowID( vars_window, self._uiTab ), 'variables': utils.WindowID( vars_window, self._uiTab ),
'watches': utils.WindowID( watch_window, self._uiTab ), 'watches': utils.WindowID( watch_window, self._uiTab ),
'output': utils.WindowID( output_window, self._uiTab ), 'output': utils.WindowID( output_window, self._uiTab ),
'eval': None # this is going to be updated every time eval popup is opened
}
with utils.RestoreCursorPosition():
with utils.RestoreCurrentWindow():
with utils.RestoreCurrentBuffer( vim.current.window ):
vim.command( 'doautocmd User VimspectorUICreated' )
def _SetUpUIVertical( self ):
# Code window
code_window = vim.current.window
self._codeView = code.CodeView( code_window, self._api_prefix )
# Call stack
vim.command(
f'topleft { settings.Int( "topbar_height" ) }new' )
stack_trace_window = vim.current.window
one_third = int( vim.eval( 'winwidth( 0 )' ) ) / 3
self._stackTraceView = stack_trace.StackTraceView( self,
stack_trace_window )
# Watches
vim.command( 'leftabove vertical new' )
watch_window = vim.current.window
# Variables
vim.command( 'leftabove vertical new' )
vars_window = vim.current.window
with utils.LetCurrentWindow( vars_window ):
vim.command( f'{ one_third }wincmd |' )
with utils.LetCurrentWindow( watch_window ):
vim.command( f'{ one_third }wincmd |' )
with utils.LetCurrentWindow( stack_trace_window ):
vim.command( f'{ one_third }wincmd |' )
self._variablesView = variables.VariablesView( vars_window,
watch_window )
# Output/logging
vim.current.window = code_window
vim.command( f'rightbelow { settings.Int( "bottombar_height" ) }new' )
output_window = vim.current.window
self._outputView = output.DAPOutputView( output_window,
self._api_prefix )
# TODO: If/when we support multiple sessions, we'll need some way to
# indicate which tab was created and store all the tabs
vim.vars[ 'vimspector_session_windows' ] = {
'mode': 'vertical',
'tabpage': self._uiTab.number,
'code': utils.WindowID( code_window, self._uiTab ),
'stack_trace': utils.WindowID( stack_trace_window, self._uiTab ),
'variables': utils.WindowID( vars_window, self._uiTab ),
'watches': utils.WindowID( watch_window, self._uiTab ),
'output': utils.WindowID( output_window, self._uiTab ),
'eval': None # this is going to be updated every time eval popup is opened
} }
with utils.RestoreCursorPosition(): with utils.RestoreCursorPosition():
with utils.RestoreCurrentWindow(): with utils.RestoreCurrentWindow():
@ -863,6 +723,7 @@ class DebugSession( object ):
json.dumps( self._adapter ) ) json.dumps( self._adapter ) )
self._init_complete = False self._init_complete = False
self._on_init_complete_handlers = []
self._launch_complete = False self._launch_complete = False
self._run_on_server_exit = None self._run_on_server_exit = None
@ -878,7 +739,6 @@ class DebugSession( object ):
self._adapter[ 'port' ] = port self._adapter[ 'port' ] = port
self._connection_type = self._api_prefix + self._connection_type self._connection_type = self._api_prefix + self._connection_type
self._logger.debug( f"Connection Type: { self._connection_type }" )
self._adapter[ 'env' ] = self._adapter.get( 'env', {} ) self._adapter[ 'env' ] = self._adapter.get( 'env', {} )
@ -894,93 +754,56 @@ class DebugSession( object ):
self._splash_screen, self._splash_screen,
"Unable to start adapter" ) "Unable to start adapter" )
else: else:
if 'custom_handler' in self._adapter:
spec = self._adapter[ 'custom_handler' ]
if isinstance( spec, dict ):
module = spec[ 'module' ]
cls = spec[ 'class' ]
else:
module, cls = spec.rsplit( '.', 1 )
CustomHandler = getattr( importlib.import_module( module ), cls )
handlers = [ CustomHandler( self ), self ]
else:
handlers = [ self ]
self._connection = debug_adapter_connection.DebugAdapterConnection( self._connection = debug_adapter_connection.DebugAdapterConnection(
handlers, self,
lambda msg: utils.Call( lambda msg: utils.Call(
"vimspector#internal#{}#Send".format( self._connection_type ), "vimspector#internal#{}#Send".format( self._connection_type ),
msg ) ) msg ) )
self._logger.info( 'Debug Adapter Started' ) self._logger.info( 'Debug Adapter Started' )
def _StopDebugAdapter( self, interactive = False, callback = None ): def _StopDebugAdapter( self, callback = None ):
self._splash_screen = utils.DisplaySplash(
self._api_prefix,
self._splash_screen,
"Shutting down debug adapter..." )
def handler( *args ):
self._splash_screen = utils.HideSplash( self._api_prefix,
self._splash_screen )
if callback:
self._logger.debug( "Setting server exit handler before disconnect" )
assert not self._run_on_server_exit
self._run_on_server_exit = callback
vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format(
self._connection_type ) )
arguments = {} arguments = {}
if self._server_capabilities.get( 'supportTerminateDebuggee' ):
# If we attached, we should _not_ terminate the debuggee
arguments[ 'terminateDebuggee' ] = False
def disconnect(): self._connection.DoRequest( handler, {
self._splash_screen = utils.DisplaySplash( 'command': 'disconnect',
self._api_prefix, 'arguments': arguments,
self._splash_screen, }, failure_handler = handler, timeout = 5000 )
"Shutting down debug adapter..." )
def handler( *args ): # TODO: Use the 'tarminate' request if supportsTerminateRequest set
self._splash_screen = utils.HideSplash( self._api_prefix,
self._splash_screen )
if callback:
self._logger.debug( "Setting server exit handler before disconnect" )
assert not self._run_on_server_exit
self._run_on_server_exit = callback
vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format(
self._connection_type ) )
self._connection.DoRequest( handler, {
'command': 'disconnect',
'arguments': arguments,
}, failure_handler = handler, timeout = 5000 )
if not interactive:
disconnect()
elif not self._server_capabilities.get( 'supportTerminateDebuggee' ):
disconnect()
elif not self._stackTraceView.AnyThreadsRunning():
disconnect()
else:
def handle_choice( choice ):
if choice == 1:
# yes
arguments[ 'terminateDebuggee' ] = True
elif choice == 2:
# no
arguments[ 'terminateDebuggee' ] = False
elif choice <= 0:
# Abort
return
# Else, use server default
disconnect()
utils.Confirm( self._api_prefix,
"Terminate debuggee?",
handle_choice,
default_value = 3,
options = [ '(Y)es', '(N)o', '(D)efault' ],
keys = [ 'y', 'n', 'd' ] )
def _PrepareAttach( self, adapter_config, launch_config ): def _PrepareAttach( self, adapter_config, launch_config ):
attach_config = adapter_config.get( 'attach' ) atttach_config = adapter_config.get( 'attach' )
if not attach_config: if not atttach_config:
return return
if 'remote' in attach_config: if 'remote' in atttach_config:
# FIXME: We almost want this to feed-back variables to be expanded later, # FIXME: We almost want this to feed-back variables to be expanded later,
# e.g. expand variables when we use them, not all at once. This would # e.g. expand variables when we use them, not all at once. This would
# remove the whole %PID% hack. # remove the whole %PID% hack.
remote = attach_config[ 'remote' ] remote = atttach_config[ 'remote' ]
remote_exec_cmd = self._GetRemoteExecCommand( remote ) remote_exec_cmd = self._GetRemoteExecCommand( remote )
# FIXME: Why does this not use self._GetCommands ? # FIXME: Why does this not use self._GetCommands ?
@ -1021,23 +844,20 @@ class DebugSession( object ):
self._codeView._window, self._codeView._window,
self._remote_term ) self._remote_term )
else: else:
if attach_config[ 'pidSelect' ] == 'ask': if atttach_config[ 'pidSelect' ] == 'ask':
prop = attach_config[ 'pidProperty' ] prop = atttach_config[ 'pidProperty' ]
if prop not in launch_config: if prop not in launch_config:
pid = utils.AskForInput( 'Enter PID to attach to: ' ) pid = utils.AskForInput( 'Enter PID to attach to: ' )
if pid is None: if pid is None:
return return
launch_config[ prop ] = pid launch_config[ prop ] = pid
return return
elif attach_config[ 'pidSelect' ] == 'none': elif atttach_config[ 'pidSelect' ] == 'none':
return return
raise ValueError( 'Unrecognised pidSelect {0}'.format( raise ValueError( 'Unrecognised pidSelect {0}'.format(
attach_config[ 'pidSelect' ] ) ) atttach_config[ 'pidSelect' ] ) )
if 'delay' in attach_config:
utils.UserMessage( f"Waiting ( { attach_config[ 'delay' ] } )..." )
vim.command( f'sleep { attach_config[ "delay" ] }' )
def _PrepareLaunch( self, command_line, adapter_config, launch_config ): def _PrepareLaunch( self, command_line, adapter_config, launch_config ):
@ -1070,11 +890,6 @@ class DebugSession( object ):
self._codeView._window, self._codeView._window,
self._remote_term ) self._remote_term )
if 'delay' in run_config:
utils.UserMessage( f"Waiting ( {run_config[ 'delay' ]} )..." )
vim.command( f'sleep { run_config[ "delay" ] }' )
def _GetSSHCommand( self, remote ): def _GetSSHCommand( self, remote ):
ssh = [ 'ssh' ] + remote.get( 'ssh', {} ).get( 'args', [] ) ssh = [ 'ssh' ] + remote.get( 'ssh', {} ).get( 'args', [] )
@ -1148,7 +963,6 @@ class DebugSession( object ):
def handle_initialize_response( msg ): def handle_initialize_response( msg ):
self._server_capabilities = msg.get( 'body' ) or {} self._server_capabilities = msg.get( 'body' ) or {}
self._breakpoints.SetServerCapabilities( self._server_capabilities ) self._breakpoints.SetServerCapabilities( self._server_capabilities )
self._variablesView.SetServerCapabilities( self._server_capabilities )
self._Launch() self._Launch()
self._connection.DoRequest( handle_initialize_response, { self._connection.DoRequest( handle_initialize_response, {
@ -1174,44 +988,40 @@ class DebugSession( object ):
message ) message )
self._outputView.Print( 'server', msg ) self._outputView.Print( 'server', msg )
def _Launch( self ):
def _Prepare( self ):
self._on_init_complete_handlers = []
self._logger.debug( "LAUNCH!" ) self._logger.debug( "LAUNCH!" )
self._launch_config = {} adapter_config = self._adapter
self._launch_config.update( self._adapter.get( 'configuration', {} ) ) launch_config = {}
self._launch_config.update( self._configuration[ 'configuration' ] ) launch_config.update( self._adapter.get( 'configuration', {} ) )
launch_config.update( self._configuration[ 'configuration' ] )
request = self._configuration.get( request = self._configuration.get(
'remote-request', 'remote-request',
self._launch_config.get( 'request', 'launch' ) ) launch_config.get( 'request', 'launch' ) )
if request == "attach": if request == "attach":
self._splash_screen = utils.DisplaySplash( self._splash_screen = utils.DisplaySplash(
self._api_prefix, self._api_prefix,
self._splash_screen, self._splash_screen,
"Attaching to debuggee..." ) "Attaching to debugee..." )
self._PrepareAttach( self._adapter, self._launch_config ) self._PrepareAttach( adapter_config, launch_config )
elif request == "launch": elif request == "launch":
self._splash_screen = utils.DisplaySplash( self._splash_screen = utils.DisplaySplash(
self._api_prefix, self._api_prefix,
self._splash_screen, self._splash_screen,
"Launching debuggee..." ) "Launching debugee..." )
# FIXME: This cmdLine hack is not fun. # FIXME: This cmdLine hack is not fun.
self._PrepareLaunch( self._configuration.get( 'remote-cmdLine', [] ), self._PrepareLaunch( self._configuration.get( 'remote-cmdLine', [] ),
self._adapter, adapter_config,
self._launch_config ) launch_config )
# FIXME: name is mandatory. Forcefully add it (we should really use the # FIXME: name is mandatory. Forcefully add it (we should really use the
# _actual_ name, but that isn't actually remembered at this point) # _actual_ name, but that isn't actually remembered at this point)
if 'name' not in self._launch_config: if 'name' not in launch_config:
self._launch_config[ 'name' ] = 'test' launch_config[ 'name' ] = 'test'
def _Launch( self ):
def failure_handler( reason, msg ): def failure_handler( reason, msg ):
text = [ text = [
'Launch Failed', 'Launch Failed',
@ -1224,11 +1034,12 @@ class DebugSession( object ):
self._splash_screen, self._splash_screen,
text ) text )
self._connection.DoRequest( self._connection.DoRequest(
lambda msg: self._OnLaunchComplete(), lambda msg: self._OnLaunchComplete(),
{ {
'command': self._launch_config[ 'request' ], 'command': launch_config[ 'request' ],
'arguments': self._launch_config 'arguments': launch_config
}, },
failure_handler ) failure_handler )
@ -1270,37 +1081,6 @@ class DebugSession( object ):
self._stackTraceView.LoadThreads( True ) self._stackTraceView.LoadThreads( True )
@IfConnected()
@RequiresUI()
def PrintDebugInfo( self ):
def Line():
return ( "--------------------------------------------------------------"
"------------------" )
def Pretty( obj ):
if obj is None:
return [ "None" ]
return [ Line() ] + json.dumps( obj, indent=2 ).splitlines() + [ Line() ]
debugInfo = [
"Vimspector Debug Info",
Line(),
f"ConnectionType: { self._connection_type }",
"Adapter: " ] + Pretty( self._adapter ) + [
"Configuration: " ] + Pretty( self._configuration ) + [
f"API Prefix: { self._api_prefix }",
f"Launch/Init: { self._launch_complete } / { self._init_complete }",
f"Workspace Root: { self._workspace_root }",
"Launch Config: " ] + Pretty( self._launch_config ) + [
"Server Capabilities: " ] + Pretty( self._server_capabilities ) + [
]
self._outputView.ClearCategory( 'DebugInfo' )
self._outputView.Print( "DebugInfo", debugInfo )
self.ShowOutput( "DebugInfo" )
def OnEvent_loadedSource( self, msg ): def OnEvent_loadedSource( self, msg ):
pass pass
@ -1363,25 +1143,13 @@ class DebugSession( object ):
self._connection.DoResponse( message, None, response ) self._connection.DoResponse( message, None, response )
def OnEvent_terminated( self, message ): def OnEvent_exited( self, message ):
# The debugging _session_ has terminated. This does not mean that the utils.UserMessage( 'The debugee exited with status code: {}'.format(
# debuggee has terminated (that's the exited event). message[ 'body' ][ 'exitCode' ] ) )
#
# We will handle this when the server actually exists.
#
# FIXME we should always wait for this event before disconnecting closing
# any socket connection
self.SetCurrentFrame( None ) self.SetCurrentFrame( None )
def OnEvent_exited( self, message ):
utils.UserMessage( 'The debuggee exited with status code: {}'.format(
message[ 'body' ][ 'exitCode' ] ) )
self._stackTraceView.OnExited( message )
self._codeView.SetCurrentFrame( None )
def OnEvent_process( self, message ): def OnEvent_process( self, message ):
utils.UserMessage( 'The debuggee was started: {}'.format( utils.UserMessage( 'The debugee was started: {}'.format(
message[ 'body' ][ 'name' ] ) ) message[ 'body' ][ 'name' ] ) )
def OnEvent_module( self, message ): def OnEvent_module( self, message ):
@ -1421,6 +1189,11 @@ class DebugSession( object ):
else: else:
self._logger.debug( "No server exit handler" ) self._logger.debug( "No server exit handler" )
def OnEvent_terminated( self, message ):
# We will handle this when the server actually exists
utils.UserMessage( "Debugging was terminated by the server." )
self.SetCurrentFrame( None )
def OnEvent_output( self, message ): def OnEvent_output( self, message ):
if self._outputView: if self._outputView:
self._outputView.OnOutput( message[ 'body' ] ) self._outputView.OnOutput( message[ 'body' ] )

View file

@ -21,7 +21,7 @@ import os
GADGETS = { GADGETS = {
'vscode-cpptools': { 'vscode-cpptools': {
'language': [ 'c', 'cpp', 'rust' ], 'language': 'c',
'download': { 'download': {
'url': 'https://github.com/Microsoft/vscode-cpptools/releases/download/' 'url': 'https://github.com/Microsoft/vscode-cpptools/releases/download/'
'${version}/${file_name}', '${version}/${file_name}',
@ -30,12 +30,12 @@ GADGETS = {
root, root,
gadget ), gadget ),
'all': { 'all': {
'version': '1.6.0', 'version': '0.27.0',
"adapters": { "adapters": {
"vscode-cpptools": { "vscode-cpptools": {
"name": "cppdbg", "name": "cppdbg",
"command": [ "command": [
"${gadgetDir}/vscode-cpptools/debugAdapters/bin/OpenDebugAD7" "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7"
], ],
"attach": { "attach": {
"pidProperty": "processId", "pidProperty": "processId",
@ -53,17 +53,17 @@ GADGETS = {
'linux': { 'linux': {
'file_name': 'cpptools-linux.vsix', 'file_name': 'cpptools-linux.vsix',
'checksum': 'checksum':
'c25299bcfb46b22d41aa3f125df7184e6282a35ff9fb69c47def744cb4778f55', '3695202e1e75a03de18049323b66d868165123f26151f8c974a480eaf0205435',
}, },
'macos': { 'macos': {
'file_name': 'cpptools-osx-arm64.vsix', 'file_name': 'cpptools-osx.vsix',
'checksum': 'checksum':
'ceb3e8cdaa2b5bb45af50913ddd8402089969748af8d70f5d46480408287ba6f', 'cb061e3acd7559a539e5586f8d3f535101c4ec4e8a48195856d1d39380b5cf3c',
}, },
'windows': { 'windows': {
'file_name': 'cpptools-win32.vsix', 'file_name': 'cpptools-win32.vsix',
'checksum': 'checksum':
'ef7ac5831874a3c7dbf0feb826bfda2be579aff9b6d990622fff1d0d4ede00d1', 'aa294368ed16d48c59e49c8000e146eae5a19ad07b654efed5db8ec93b24229e',
"adapters": { "adapters": {
"vscode-cpptools": { "vscode-cpptools": {
"name": "cppdbg", "name": "cppdbg",
@ -86,6 +86,29 @@ GADGETS = {
}, },
}, },
}, },
'vscode-python': {
'language': 'python.legacy',
'enabled': False,
'download': {
'url': 'https://github.com/Microsoft/vscode-python/releases/download/'
'${version}/${file_name}',
},
'all': {
'version': '2019.11.50794',
'file_name': 'ms-python-release.vsix',
'checksum':
'6a9edf9ecabed14aac424e6007858068204a3638bf3bb4f235bd6035d823acc6',
},
'adapters': {
"vscode-python": {
"name": "vscode-python",
"command": [
"node",
"${gadgetDir}/vscode-python/out/client/debugger/debugAdapter/main.js",
],
}
},
},
'debugpy': { 'debugpy': {
'language': 'python', 'language': 'python',
'download': { 'download': {
@ -136,8 +159,7 @@ GADGETS = {
"port": "${DAPPort}", "port": "${DAPPort}",
"configuration": { "configuration": {
"cwd": "${workspaceRoot}" "cwd": "${workspaceRoot}"
}, }
'custom_handler': 'vimspector.custom.java.JavaDebugAdapter'
} }
}, },
}, },
@ -203,7 +225,7 @@ GADGETS = {
}, },
}, },
'netcoredbg': { 'netcoredbg': {
'language': [ 'csharp', 'fsharp', 'vbnet' ], 'language': 'csharp',
'enabled': False, 'enabled': False,
'download': { 'download': {
'url': ( 'https://github.com/Samsung/netcoredbg/releases/download/' 'url': ( 'https://github.com/Samsung/netcoredbg/releases/download/'
@ -211,15 +233,15 @@ GADGETS = {
'format': 'tar', 'format': 'tar',
}, },
'all': { 'all': {
'version': '1.2.0-782' 'version': '1.2.0-635'
}, },
'macos': { 'macos': {
'file_name': 'netcoredbg-osx.tar.gz', 'file_name': 'netcoredbg-osx.tar.gz',
'checksum': 'checksum':
'', '71c773e34d358950f25119bade7e3081c4c2f9d71847bd49027ca5792e918beb',
}, },
'linux': { 'linux': {
'file_name': 'netcoredbg-linux-bionic-amd64.tar.gz', 'file_name': 'netcoredbg-linux-bionic.tar.gz',
'checksum': '', 'checksum': '',
}, },
'windows': { 'windows': {
@ -246,6 +268,41 @@ GADGETS = {
}, },
} }
}, },
'vscode-mono-debug': {
'language': 'csharp',
'enabled': False,
'download': {
'url': 'https://marketplace.visualstudio.com/_apis/public/gallery/'
'publishers/ms-vscode/vsextensions/mono-debug/${version}/'
'vspackage',
'target': 'vscode-mono-debug.vsix.gz',
'format': 'zip.gz',
},
'all': {
'file_name': 'vscode-mono-debug.vsix',
'version': '0.16.2',
'checksum':
'121eca297d83daeeb1e6e1d791305d1827998dbd595c330086b3b94d33dba3b9',
},
'adapters': {
'vscode-mono-debug': {
"name": "mono-debug",
"command": [
"mono",
"${gadgetDir}/vscode-mono-debug/bin/Release/mono-debug.exe"
],
"attach": {
"pidSelect": "none"
},
"configuration": {
"cwd": "${workspaceRoot}",
"console": "integratedTerminal",
"args": [],
"env": {}
}
},
}
},
'vscode-bash-debug': { 'vscode-bash-debug': {
'language': 'bash', 'language': 'bash',
'download': { 'download': {
@ -319,14 +376,14 @@ GADGETS = {
'enabled': False, 'enabled': False,
'download': { 'download': {
'url': 'url':
'https://github.com/xdebug/vscode-php-debug/releases/download/' 'https://github.com/felixfbecker/vscode-php-debug/releases/download/'
'${version}/${file_name}', '${version}/${file_name}',
}, },
'all': { 'all': {
'version': 'v1.17.0', 'version': 'v1.13.0',
'file_name': 'php-debug-1.17.0.vsix', 'file_name': 'php-debug.vsix',
'checksum': 'checksum':
'd0fff272503414b6696cc737bc2e18e060fdd5e5dc4bcaf38ae7373afd8d8bc9', '8a51e593458fd14623c1c89ebab87347b087d67087717f18bcf77bb788052718',
}, },
'adapters': { 'adapters': {
'vscode-php-debug': { 'vscode-php-debug': {
@ -394,12 +451,12 @@ GADGETS = {
'${version}/${file_name}', '${version}/${file_name}',
}, },
'all': { 'all': {
'version': 'v1.6.6', 'version': 'v1.5.3',
}, },
'macos': { 'macos': {
'file_name': 'codelldb-aarch64-darwin.vsix', 'file_name': 'codelldb-x86_64-darwin.vsix',
'checksum': 'checksum':
'5adc3b9139eabdafd825bd5efc55df4424a203fb2b6087b425cd434956e7ec58', '7505bc1cdfcfd1cb981e2996aec62d63577440709bac31dcadb41a3b4b44631a',
'make_executable': [ 'make_executable': [
'adapter/codelldb', 'adapter/codelldb',
'lldb/bin/debugserver', 'lldb/bin/debugserver',
@ -410,7 +467,7 @@ GADGETS = {
'linux': { 'linux': {
'file_name': 'codelldb-x86_64-linux.vsix', 'file_name': 'codelldb-x86_64-linux.vsix',
'checksum': 'checksum':
'eda2cd9b3089dcc0524c273e91ffb5875fe08c930bf643739a2cd1846e1f98d6', 'ce7efc3e94d775368e5942a02bf5c326b6809a0b4c389f79ffa6a8f6f6b72139',
'make_executable': [ 'make_executable': [
'adapter/codelldb', 'adapter/codelldb',
'lldb/bin/lldb', 'lldb/bin/lldb',
@ -421,7 +478,7 @@ GADGETS = {
'windows': { 'windows': {
'file_name': 'codelldb-x86_64-windows.vsix', 'file_name': 'codelldb-x86_64-windows.vsix',
'checksum': 'checksum':
'8ddebe8381a3d22dc3d95139c3797fda06b5cc34aadf300e13b1c516b9da95fe', '',
'make_executable': [] 'make_executable': []
}, },
'adapters': { 'adapters': {

View file

@ -229,14 +229,10 @@ def GadgetListToInstallerArgs( *gadget_list ):
except KeyError: except KeyError:
continue continue
lang = gadget[ "language" ]
if isinstance( lang, list ):
lang = lang[ 0 ]
if not gadget.get( 'enabled', True ): if not gadget.get( 'enabled', True ):
installer_args.append( f'--force-enable-{lang}' ) installer_args.append( f'--force-enable-{ gadget[ "language" ] }' )
else: else:
installer_args.append( f'--enable-{lang}' ) installer_args.append( f'--enable-{ gadget[ "language" ] }' )
return installer_args return installer_args
@ -344,12 +340,11 @@ def WriteAdapters( all_adapters, to_file=None ):
def InstallGeneric( name, root, gadget ): def InstallGeneric( name, root, gadget ):
extension_path = gadget.get( 'extension_path', 'extension' ) extension = os.path.join( root, 'extension' )
extension = os.path.join( root, extension_path )
for f in gadget.get( 'make_executable', [] ): for f in gadget.get( 'make_executable', [] ):
MakeExecutable( os.path.join( extension, f ) ) MakeExecutable( os.path.join( extension, f ) )
MakeExtensionSymlink( name, root, extension_path ) MakeExtensionSymlink( name, root )
def InstallCppTools( name, root, gadget ): def InstallCppTools( name, root, gadget ):
@ -358,8 +353,7 @@ def InstallCppTools( name, root, gadget ):
# It's hilarious, but the execute bits aren't set in the vsix. So they # It's hilarious, but the execute bits aren't set in the vsix. So they
# actually have javascript code which does this. It's just a horrible horrible # actually have javascript code which does this. It's just a horrible horrible
# hack that really is not funny. # hack that really is not funny.
MakeExecutable( MakeExecutable( os.path.join( extension, 'debugAdapters', 'OpenDebugAD7' ) )
os.path.join( extension, 'debugAdapters', 'bin', 'OpenDebugAD7' ) )
with open( os.path.join( extension, 'package.json' ) ) as f: with open( os.path.join( extension, 'package.json' ) ) as f:
package = json.load( f ) package = json.load( f )
runtime_dependencies = package[ 'runtimeDependencies' ] runtime_dependencies = package[ 'runtimeDependencies' ]
@ -705,8 +699,8 @@ def ExtractZipTo( file_path, destination, format ):
CheckCall( [ 'tar', 'zxvf', file_path ] ) CheckCall( [ 'tar', 'zxvf', file_path ] )
def MakeExtensionSymlink( name, root, extension_path = 'extension' ): def MakeExtensionSymlink( name, root ):
MakeSymlink( name, os.path.join( root, extension_path ) ), MakeSymlink( name, os.path.join( root, 'extension' ) ),
def MakeSymlink( link, pointing_to, in_folder = None ): def MakeSymlink( link, pointing_to, in_folder = None ):

View file

@ -32,9 +32,8 @@ class TabBuffer( object ):
BUFFER_MAP = { BUFFER_MAP = {
'console': 'Console', 'console': 'Console',
'stdout': 'Console', 'stdout': 'Console',
'output': 'Console',
'stderr': 'stderr', 'stderr': 'stderr',
'telemetry': None, 'telemetry': 'Telemetry',
} }
@ -65,11 +64,8 @@ class OutputView( object ):
self._api_prefix = api_prefix self._api_prefix = api_prefix
VIEWS.add( self ) VIEWS.add( self )
def Print( self, category, text: typing.Union[ str, list ] ): def Print( self, categroy, text ):
if not isinstance( text, list ): self._Print( 'server', text.splitlines() )
text = text.splitlines()
self._Print( category, text )
def OnOutput( self, event ): def OnOutput( self, event ):
category = CategoryToBuffer( event.get( 'category' ) or 'output' ) category = CategoryToBuffer( event.get( 'category' ) or 'output' )
@ -81,10 +77,6 @@ class OutputView( object ):
self._Print( category, text_lines ) self._Print( category, text_lines )
def _Print( self, category, text_lines ): def _Print( self, category, text_lines ):
if category is None:
# This category is supressed
return
if category not in self._buffers: if category not in self._buffers:
self._CreateBuffer( category ) self._CreateBuffer( category )
@ -108,26 +100,13 @@ class OutputView( object ):
def Clear( self ): def Clear( self ):
for category, tab_buffer in self._buffers.items(): for category, tab_buffer in self._buffers.items():
self._CleanUpBuffer( category, tab_buffer ) if tab_buffer.is_job:
utils.CleanUpCommand( category, self._api_prefix )
utils.CleanUpHiddenBuffer( tab_buffer.buf )
# FIXME: nunmenu the WinBar ? # FIXME: nunmenu the WinBar ?
self._buffers = {} self._buffers = {}
def ClearCategory( self, category: str ):
if category not in self._buffers:
return
self._CleanUpBuffer( category, self._buffers[ category ] )
def _CleanUpBuffer( self, category: str, tab_buffer: TabBuffer ):
if tab_buffer.is_job:
utils.CleanUpCommand( category, self._api_prefix )
utils.CleanUpHiddenBuffer( tab_buffer.buf )
def WindowIsValid( self ): def WindowIsValid( self ):
return self._window.valid return self._window.valid
@ -251,7 +230,7 @@ class OutputView( object ):
raise raise
vim.command( vim.command(
"nnoremenu <silent> 1.{0} WinBar.{1}{2} " "nnoremenu 1.{0} WinBar.{1}{2} "
":call vimspector#ShowOutputInWindow( {3}, '{1}' )<CR>".format( ":call vimspector#ShowOutputInWindow( {3}, '{1}' )<CR>".format(
tab_buffer.index, tab_buffer.index,
utils.Escape( category ), utils.Escape( category ),
@ -272,8 +251,7 @@ class DAPOutputView( OutputView ):
self._connection = None self._connection = None
for b in set( BUFFER_MAP.values() ): for b in set( BUFFER_MAP.values() ):
if b is not None: self._CreateBuffer( b )
self._CreateBuffer( b )
self.AddLogFileView() self.AddLogFileView()
self._ShowOutput( 'Console' ) self._ShowOutput( 'Console' )

View file

@ -20,20 +20,11 @@ from vimspector import utils
DEFAULTS = { DEFAULTS = {
# UI # UI
'ui_mode': 'auto', 'bottombar_height': 10,
'bottombar_height': 10, 'sidebar_width': 50,
'code_minwidth': 82,
# For ui_mode = 'horizontal': 'terminal_maxwidth': 80,
'sidebar_width': 50, 'terminal_minwidth': 10,
'code_minwidth': 82,
'terminal_maxwidth': 80,
'terminal_minwidth': 10,
# For ui_mode = 'vertical':
'topbar_height': 15,
'code_minheight': 20,
'terminal_maxheight': 15,
'terminal_minheight': 5,
# Signs # Signs
'sign_priority': { 'sign_priority': {
@ -42,28 +33,11 @@ DEFAULTS = {
'vimspectorBP': 9, 'vimspectorBP': 9,
'vimspectorBPCond': 9, 'vimspectorBPCond': 9,
'vimspectorBPDisabled': 9, 'vimspectorBPDisabled': 9,
'vimspectorCurrentThread': 200, 'vimspectorCurrentThread': 200
'vimspectorCurrentFrame': 200,
}, },
# Installer # Installer
'install_gadgets': [], 'install_gadgets': [],
# Mappings
'mappings': {
'variables': {
'expand_collapse': [ '<CR>', '<2-LeftMouse>' ],
'delete': [ '<Del>' ],
'set_value': [ '<C-CR>', '<leader><CR>' ]
},
'stack_trace': {
'expand_or_jump': [ '<CR>', '<2-LeftMouse>' ],
'focus_thread': [ '<leader><CR>' ],
}
},
# Custom
'java_hotcodereplace_mode': 'ask',
} }
@ -95,44 +69,9 @@ if hasattr( vim, 'Dictionary' ):
DICT_TYPE = vim.Dictionary DICT_TYPE = vim.Dictionary
def Dict( option ): def Dict( option: str ):
return _UpdateDict( DICT_TYPE( DEFAULTS.get( option, {} ) ), d = DICT_TYPE( DEFAULTS.get( option, {} ) )
vim.vars.get( f'vimspector_{ option }', DICT_TYPE() ) ) d.update( utils.GetVimValue( vim.vars,
f'vimspector_{ option }',
{} ) )
def _UpdateDict( target, override ): return d
"""Apply the updates in |override| to the dict |target|. This is like
dict.update, but recursive. i.e. if the existing element is a dict, then
override elements of the sub-dict rather than wholesale replacing.
e.g.
UpdateDict(
{
'outer': { 'inner': { 'key': 'oldValue', 'existingKey': True } }
},
{
'outer': { 'inner': { 'key': 'newValue' } },
'newKey': { 'newDict': True },
}
)
yields:
{
'outer': {
'inner': {
'key': 'newValue',
'existingKey': True
}
},
'newKey': { newDict: True }
}
"""
for key, value in override.items():
current_value = target.get( key )
if not isinstance( current_value, DICT_TYPE ):
target[ key ] = value
elif isinstance( value, DICT_TYPE ):
target[ key ] = _UpdateDict( current_value, value )
else:
target[ key ] = value
return target

View file

@ -18,7 +18,7 @@ import os
import logging import logging
import typing import typing
from vimspector import utils, signs, settings from vimspector import utils, signs
class Thread: class Thread:
@ -102,33 +102,28 @@ class StackTraceView( object ):
self._scratch_buffers = [] self._scratch_buffers = []
# FIXME: This ID is by group, so should be module scope # FIXME: This ID is by group, so should be module scope
self._current_thread_sign_id = 0 # 1 when used self._next_sign_id = 1
self._current_frame_sign_id = 0 # 2 when used
utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' ) utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' )
utils.SetUpUIWindow( win ) utils.SetUpUIWindow( win )
mappings = settings.Dict( 'mappings' )[ 'stack_trace' ]
with utils.LetCurrentWindow( win ): with utils.LetCurrentWindow( win ):
for mapping in utils.GetVimList( mappings, 'expand_or_jump' ): vim.command( 'nnoremap <silent> <buffer> <CR> '
vim.command( f'nnoremap <silent> <buffer> { mapping } ' ':<C-U>call vimspector#GoToFrame()<CR>' )
':<C-U>call vimspector#GoToFrame()<CR>' ) vim.command( 'nnoremap <silent> <buffer> <leader><CR> '
':<C-U>call vimspector#SetCurrentThread()<CR>' )
for mapping in utils.GetVimList( mappings, 'focus_thread' ): vim.command( 'nnoremap <silent> <buffer> <2-LeftMouse> '
vim.command( f'nnoremap <silent> <buffer> { mapping } ' ':<C-U>call vimspector#GoToFrame()<CR>' )
':<C-U>call vimspector#SetCurrentThread()<CR>' )
if utils.UseWinBar(): if utils.UseWinBar():
vim.command( 'nnoremenu <silent> 1.1 WinBar.Pause/Continue ' vim.command( 'nnoremenu 1.1 WinBar.Pause/Continue '
':call vimspector#PauseContinueThread()<CR>' ) ':call vimspector#PauseContinueThread()<CR>' )
vim.command( 'nnoremenu <silent> 1.2 WinBar.Expand/Collapse ' vim.command( 'nnoremenu 1.2 WinBar.Expand/Collapse '
':call vimspector#GoToFrame()<CR>' ) ':call vimspector#GoToFrame()<CR>' )
vim.command( 'nnoremenu <silent> 1.3 WinBar.Focus ' vim.command( 'nnoremenu 1.3 WinBar.Focus '
':call vimspector#SetCurrentThread()<CR>' ) ':call vimspector#SetCurrentThread()<CR>' )
win.options[ 'cursorline' ] = False win.options[ 'cursorline' ] = False
win.options[ 'signcolumn' ] = 'auto'
if not signs.SignDefined( 'vimspectorCurrentThread' ): if not signs.SignDefined( 'vimspectorCurrentThread' ):
@ -138,13 +133,6 @@ class StackTraceView( object ):
texthl = 'MatchParen', texthl = 'MatchParen',
linehl = 'CursorLine' ) linehl = 'CursorLine' )
if not signs.SignDefined( 'vimspectorCurrentFrame' ):
signs.DefineSign( 'vimspectorCurrentFrame',
text = '',
double_text = '',
texthl = 'Special',
linehl = 'CursorLine' )
self._line_to_frame = {} self._line_to_frame = {}
self._line_to_thread = {} self._line_to_thread = {}
@ -166,12 +154,9 @@ class StackTraceView( object ):
self._sources = {} self._sources = {}
self._requesting_threads = StackTraceView.ThreadRequestState.NO self._requesting_threads = StackTraceView.ThreadRequestState.NO
self._pending_thread_request = None self._pending_thread_request = None
if self._current_thread_sign_id: if self._next_sign_id:
signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' ) signs.UnplaceSign( self._next_sign_id, 'VimspectorStackTrace' )
self._current_thread_sign_id = 0 self._next_sign_id = 0
if self._current_frame_sign_id:
signs.UnplaceSign( self._current_frame_sign_id, 'VimspectorStackTrace' )
self._current_frame_sign_id = 0
with utils.ModifiableScratchBuffer( self._buf ): with utils.ModifiableScratchBuffer( self._buf ):
utils.ClearBuffer( self._buf ) utils.ClearBuffer( self._buf )
@ -203,12 +188,11 @@ class StackTraceView( object ):
return return
def consume_threads( message ): def consume_threads( message ):
requesting = False
if self._requesting_threads == StackTraceView.ThreadRequestState.PENDING: if self._requesting_threads == StackTraceView.ThreadRequestState.PENDING:
# We may have hit a thread event, so try again. # We may have hit a thread event, so try again.
self._requesting_threads = StackTraceView.ThreadRequestState.NO self._requesting_threads = StackTraceView.ThreadRequestState.NO
self.LoadThreads( *self._pending_thread_request ) self.LoadThreads( *self._pending_thread_request )
requesting = True return
self._requesting_threads = StackTraceView.ThreadRequestState.NO self._requesting_threads = StackTraceView.ThreadRequestState.NO
self._pending_thread_request = None self._pending_thread_request = None
@ -227,6 +211,8 @@ class StackTraceView( object ):
stoppedThreadId = stopEvent.get( 'threadId' ) stoppedThreadId = stopEvent.get( 'threadId' )
allThreadsStopped = stopEvent.get( 'allThreadsStopped', False ) allThreadsStopped = stopEvent.get( 'allThreadsStopped', False )
requesting = False
# FIXME: This is horribly inefficient # FIXME: This is horribly inefficient
for t in message[ 'body' ][ 'threads' ]: for t in message[ 'body' ][ 'threads' ]:
thread = None thread = None
@ -254,10 +240,7 @@ class StackTraceView( object ):
# If this is a stopped event, load the stack trace for the "current" # If this is a stopped event, load the stack trace for the "current"
# thread. Don't do this on other thrads requests because some servers # thread. Don't do this on other thrads requests because some servers
# just break when that happens. # just break when that happens.
# if infer_current_frame:
# Don't do this if we're also satisfying a cached request already (we'll
# do it then)
if infer_current_frame and not requesting:
if thread.id == self._current_thread: if thread.id == self._current_thread:
if thread.CanExpand(): if thread.CanExpand():
self._LoadStackTrace( thread, True, reason ) self._LoadStackTrace( thread, True, reason )
@ -285,10 +268,10 @@ class StackTraceView( object ):
self._line_to_frame.clear() self._line_to_frame.clear()
self._line_to_thread.clear() self._line_to_thread.clear()
if self._current_thread_sign_id: if self._next_sign_id:
signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' ) signs.UnplaceSign( self._next_sign_id, 'VimspectorStackTrace' )
else: else:
self._current_thread_sign_id = 1 self._next_sign_id = 1
with utils.ModifiableScratchBuffer( self._buf ): with utils.ModifiableScratchBuffer( self._buf ):
with utils.RestoreCursorPosition(): with utils.RestoreCursorPosition():
@ -302,7 +285,7 @@ class StackTraceView( object ):
f'({thread.State()})' ) f'({thread.State()})' )
if self._current_thread == thread.id: if self._current_thread == thread.id:
signs.PlaceSign( self._current_thread_sign_id, signs.PlaceSign( self._next_sign_id,
'VimspectorStackTrace', 'VimspectorStackTrace',
'vimspectorCurrentThread', 'vimspectorCurrentThread',
self._buf.name, self._buf.name,
@ -379,61 +362,12 @@ class StackTraceView( object ):
self._JumpToFrame( frame ) self._JumpToFrame( frame )
def _GetFrameOffset( self, delta ):
thread: Thread
for thread in self._threads:
if thread.id != self._current_thread:
continue
if not thread.stacktrace:
return
frame_idx = None
for index, frame in enumerate( thread.stacktrace ):
if frame == self._current_frame:
frame_idx = index
break
if frame_idx is not None:
target_idx = frame_idx + delta
if target_idx >= 0 and target_idx < len( thread.stacktrace ):
return thread.stacktrace[ target_idx ]
break
def UpFrame( self ):
frame = self._GetFrameOffset( 1 )
if not frame:
utils.UserMessage( 'Top of stack' )
else:
self._JumpToFrame( frame, 'up' )
def DownFrame( self ):
frame = self._GetFrameOffset( -1 )
if not frame:
utils.UserMessage( 'Bottom of stack' )
else:
self._JumpToFrame( frame, 'down' )
def AnyThreadsRunning( self ):
for thread in self._threads:
if thread.state != Thread.TERMINATED:
return True
return False
def _JumpToFrame( self, frame, reason = '' ): def _JumpToFrame( self, frame, reason = '' ):
def do_jump(): def do_jump():
if 'line' in frame and frame[ 'line' ] > 0: if 'line' in frame and frame[ 'line' ] > 0:
# Should this set the current _Thread_ too ? If i jump to a frame in # Should this set the current _Thread_ too ? If i jump to a frame in
# Thread 2, should that become the focussed thread ? # Thread 2, should that become the focussed thread ?
self._current_frame = frame self._current_frame = frame
self._DrawThreads()
return self._session.SetCurrentFrame( self._current_frame, reason ) return self._session.SetCurrentFrame( self._current_frame, reason )
return False return False
@ -523,19 +457,10 @@ class StackTraceView( object ):
self.LoadThreads( infer_current_frame ) self.LoadThreads( infer_current_frame )
def OnExited( self, event ):
for thread in self._threads:
thread.Exited()
def _DrawStackTrace( self, thread: Thread ): def _DrawStackTrace( self, thread: Thread ):
if not thread.IsExpanded(): if not thread.IsExpanded():
return return
if self._current_frame_sign_id:
signs.UnplaceSign( self._current_frame_sign_id, 'VimspectorStackTrace' )
else:
self._current_frame_sign_id = 2
for frame in thread.stacktrace: for frame in thread.stacktrace:
if frame.get( 'source' ): if frame.get( 'source' ):
source = frame[ 'source' ] source = frame[ 'source' ]
@ -560,14 +485,6 @@ class StackTraceView( object ):
source[ 'name' ], source[ 'name' ],
frame[ 'line' ] ) ) frame[ 'line' ] ) )
if ( self._current_frame is not None and
self._current_frame[ 'id' ] == frame[ 'id' ] ):
signs.PlaceSign( self._current_frame_sign_id,
'VimspectorStackTrace',
'vimspectorCurrentFrame',
self._buf.name,
line )
self._line_to_frame[ line ] = ( thread, frame ) self._line_to_frame[ line ] = ( thread, frame )
def _ResolveSource( self, source, and_then ): def _ResolveSource( self, source, and_then ):

View file

@ -23,53 +23,12 @@ def LaunchTerminal( api_prefix,
env = params.get( 'env' ) or {} env = params.get( 'env' ) or {}
term_options = { term_options = {
'vertical': 1,
'norestore': 1, 'norestore': 1,
'cwd': cwd, 'cwd': cwd,
'env': env, 'env': env,
} }
if settings.Get( 'ui_mode' ) == 'horizontal':
# force-horizontal
term_options[ 'vertical' ] = 1
elif utils.GetVimValue( vim.vars[ 'vimspector_session_windows' ],
'mode' ) == 'horizontal':
# horizontal, which means that we should have enough space for:
# - sidebar
# - code min
# - term min width
# - + 2 vertical spaders
# - + 3 columns for signs
term_options[ 'vertical' ] = 1
# if we don't have enough space for terminal_maxwidth, then see if we have
# enough vertically for terminal_maxheight, in which case,
# that seems a better fit
term_horiz_max = ( settings.Int( 'sidebar_width' ) +
1 + 2 + 3 +
settings.Int( 'code_minwidth' ) +
1 + settings.Int( 'terminal_maxwidth' ) )
term_vert_max = ( settings.Int( 'bottombar_height' ) + 1 +
settings.Int( 'code_minheight' ) + 1 +
settings.Int( 'terminal_minheight' ) )
if ( vim.options[ 'columns' ] < term_horiz_max and
vim.options[ 'lines' ] >= term_vert_max ):
# Looks like it, let's try that layout
term_options[ 'vertical' ] = 0
else:
# vertical - we need enough space horizontally for the code+terminal, but we
# may fit better with code above terminal
term_options[ 'vertical' ] = 0
term_horiz_max = ( settings.Int( 'code_minwidth' ) + 3 +
settings.Int( 'terminal_maxwidth' ) + 1 )
if vim.options[ 'columns' ] > term_horiz_max:
term_options[ 'vertical' ] = 1
if not window_for_start or not window_for_start.valid: if not window_for_start or not window_for_start.valid:
# TOOD: Where? Maybe we should just use botright vertical ... # TOOD: Where? Maybe we should just use botright vertical ...
window_for_start = vim.current.window window_for_start = vim.current.window
@ -91,23 +50,13 @@ def LaunchTerminal( api_prefix,
# If we're making a vertical split from the code window, make it no more # If we're making a vertical split from the code window, make it no more
# than 80 columns and no fewer than 10. Also try and keep the code window # than 80 columns and no fewer than 10. Also try and keep the code window
# at least 82 columns # at least 82 columns
if term_options.get( 'curwin', 0 ): if term_options[ 'vertical' ] and not term_options.get( 'curwin', 0 ):
pass
elif term_options[ 'vertical' ]:
term_options[ 'term_cols' ] = max( term_options[ 'term_cols' ] = max(
min ( int( vim.eval( 'winwidth( 0 )' ) ) min ( int( vim.eval( 'winwidth( 0 )' ) )
- settings.Int( 'code_minwidth' ), - settings.Int( 'code_minwidth' ),
settings.Int( 'terminal_maxwidth' ) ), settings.Int( 'terminal_maxwidth' ) ),
settings.Int( 'terminal_minwidth' ) settings.Int( 'terminal_minwidth' )
) )
else:
term_options[ 'term_rows' ] = max(
min ( int( vim.eval( 'winheight( 0 )' ) )
- settings.Int( 'code_minheight' ),
settings.Int( 'terminal_maxheight' ) ),
settings.Int( 'terminal_minheight' )
)
buffer_number = int( buffer_number = int(
utils.Call( utils.Call(

View file

@ -356,63 +356,20 @@ def SelectFromList( prompt, options ):
return None return None
def AskForInput( prompt, default_value = None, completion = None ): def AskForInput( prompt, default_value = None ):
if default_value is None: if default_value is None:
default_value = '' default_option = ''
else:
args = [ prompt, default_value ] default_option = ", '{}'".format( Escape( default_value ) )
if completion is not None:
if completion == 'expr':
args.append( 'custom,vimspector#CompleteExpr' )
else:
args.append( completion )
with InputSave(): with InputSave():
try: try:
return Call( 'input', *args ) return vim.eval( "input( '{}' {} )".format( Escape( prompt ),
default_option ) )
except ( KeyboardInterrupt, vim.error ): except ( KeyboardInterrupt, vim.error ):
return None return None
CONFIRM = {}
CONFIRM_ID = 0
def ConfirmCallback( confirm_id, result ):
try:
handler = CONFIRM.pop( confirm_id )
except KeyError:
UserMessage( f"Internal error: unexpected callback id { confirm_id }",
persist = True,
error = True )
return
handler( result )
def Confirm( api_prefix,
prompt,
handler,
default_value = 2,
options: list = None,
keys: list = None ):
if not options:
options = [ '(Y)es', '(N)o' ]
if not keys:
keys = [ 'y', 'n' ]
global CONFIRM_ID
CONFIRM_ID += 1
CONFIRM[ CONFIRM_ID ] = handler
Call( f'vimspector#internal#{ api_prefix }popup#Confirm',
CONFIRM_ID,
prompt,
options,
default_value,
keys )
def AppendToBuffer( buf, line_or_lines, modified=False ): def AppendToBuffer( buf, line_or_lines, modified=False ):
line = 1 line = 1
try: try:
@ -441,10 +398,8 @@ def AppendToBuffer( buf, line_or_lines, modified=False ):
def ClearBuffer( buf, modified = False ): def ClearBuffer( buf ):
buf[ : ] = None buf[ : ] = None
if not modified:
buf.options[ 'modified' ] = False
def SetBufferContents( buf, lines, modified=False ): def SetBufferContents( buf, lines, modified=False ):
@ -505,8 +460,8 @@ VAR_MATCH = re.compile(
{(?P<braceddefault> # or An {id:default} - default param, as {(?P<braceddefault> # or An {id:default} - default param, as
(?P<defname>[_a-z][_a-z0-9]*) # an ID (?P<defname>[_a-z][_a-z0-9]*) # an ID
: # then a colon : # then a colon
(?P<default>(?:\\}|[^}])*) # then anything up to }, or a \} (?P<default>(?:[^}]|\})*) # then anything up to }, or a \}
)} | # then a } )} | #
(?P<invalid>) # or Something else - invalid (?P<invalid>) # or Something else - invalid
) )
""", """,
@ -534,6 +489,7 @@ def _Substitute( template, mapping ):
if mo.group( 'braceddefault' ) is not None: if mo.group( 'braceddefault' ) is not None:
named = mo.group( 'defname' ) named = mo.group( 'defname' )
if named not in mapping: if named not in mapping:
''
raise MissingSubstitution( raise MissingSubstitution(
named, named,
mo.group( 'default' ).replace( '\\}', '}' ) ) mo.group( 'default' ).replace( '\\}', '}' ) )
@ -575,11 +531,8 @@ def ExpandReferencesInString( orig_s,
if default_value is None and e.default_value is not None: if default_value is None and e.default_value is not None:
try: try:
default_value = _Substitute( e.default_value, mapping ) default_value = _Substitute( e.default_value, mapping )
except MissingSubstitution as e2: except MissingSubstitution:
if e2.name in calculus: default_value = e.default_value
default_value = calculus[ e2.name ]()
else:
default_value = e.default_value
mapping[ key ] = AskForInput( 'Enter value for {}: '.format( key ), mapping[ key ] = AskForInput( 'Enter value for {}: '.format( key ),
default_value ) default_value )
@ -681,19 +634,15 @@ def ParseVariables( variables_list,
return new_variables return new_variables
def DisplayBalloon( is_term, display, is_hover = False ): def DisplayBaloon( is_term, display ):
if not is_term: if not is_term:
display = '\n'.join( display )
# To enable the Windows GUI to display the balloon correctly # To enable the Windows GUI to display the balloon correctly
# Refer https://github.com/vim/vim/issues/1512#issuecomment-492070685 # Refer https://github.com/vim/vim/issues/1512#issuecomment-492070685
display = '\n'.join( display ) vim.eval( "balloon_show( '' )" )
created_win_id = int( vim.eval( vim.eval( "balloon_show( {0} )".format(
"vimspector#internal#balloon#CreateTooltip({}, {})".format( json.dumps( display ) ) )
int( is_hover ), json.dumps( display )
)
) )
return created_win_id
def GetBufferFilepath( buf ): def GetBufferFilepath( buf ):
@ -754,7 +703,7 @@ def SetSyntax( current_syntax, syntax, *args ):
syntax = '' syntax = ''
if current_syntax == syntax: if current_syntax == syntax:
return syntax return
# We use set syn= because just setting vim.Buffer.options[ 'syntax' ] # We use set syn= because just setting vim.Buffer.options[ 'syntax' ]
# doesn't actually trigger the Syntax autocommand, and i'm not sure that # doesn't actually trigger the Syntax autocommand, and i'm not sure that
@ -770,28 +719,6 @@ def GetBufferFiletypes( buf ):
return ft.split( '.' ) return ft.split( '.' )
def GetVisualSelection( bufnr ):
start_line, start_col = vim.current.buffer.mark( "<" )
end_line, end_col = vim.current.buffer.mark( ">" )
# lines are 1 based, but columns are 0 based
# don't ask me why...
start_line -= 1
end_line -= 1
lines = vim.buffers[ bufnr ][ start_line : end_line + 1 ]
# Do end first, in case it's on the same line as start (as doing start first
# would change the offset)
lines[ -1 ] = lines[ -1 ][ : end_col + 1 ]
lines[ 0 ] = lines[ 0 ][ start_col : ]
_logger.debug( f'Visual selection: { lines } from '
f'{ start_line }/{ start_col } -> { end_line }/{ end_col }' )
return lines
def DisplaySplash( api_prefix, splash, text ): def DisplaySplash( api_prefix, splash, text ):
if splash: if splash:
return Call( f'vimspector#internal#{api_prefix}popup#UpdateSplash', return Call( f'vimspector#internal#{api_prefix}popup#UpdateSplash',

View file

@ -19,7 +19,7 @@ import logging
from functools import partial from functools import partial
import typing import typing
from vimspector import utils, settings from vimspector import utils
class Expandable: class Expandable:
@ -32,9 +32,8 @@ class Expandable:
a 'variablesReference' to be resolved by the 'variables' request. Records the a 'variablesReference' to be resolved by the 'variables' request. Records the
current state expanded/collapsed. Implementations just implement current state expanded/collapsed. Implementations just implement
VariablesReference to get the variables.""" VariablesReference to get the variables."""
def __init__( self, container: 'Expandable' = None ): def __init__( self ):
self.variables: typing.List[ 'Variable' ] = None self.variables: typing.List[ 'Variable' ] = None
self.container: Expandable = container
# None is Falsy and represents collapsed _by default_. WHen set to False, # None is Falsy and represents collapsed _by default_. WHen set to False,
# this means the user explicitly collapsed it. When True, the user expanded # this means the user explicitly collapsed it. When True, the user expanded
# it (or we expanded it by default). # it (or we expanded it by default).
@ -49,9 +48,6 @@ class Expandable:
def IsExpandable( self ): def IsExpandable( self ):
return self.VariablesReference() > 0 return self.VariablesReference() > 0
def IsContained( self ):
return self.container is not None
@abc.abstractmethod @abc.abstractmethod
def VariablesReference( self ): def VariablesReference( self ):
assert False assert False
@ -96,8 +92,8 @@ class WatchFailure( WatchResult ):
class Variable( Expandable ): class Variable( Expandable ):
"""Holds one level of an expanded value tree. Also itself expandable.""" """Holds one level of an expanded value tree. Also itself expandable."""
def __init__( self, container: Expandable, variable: dict ): def __init__( self, variable: dict ):
super().__init__( container = container ) super().__init__()
self.variable = variable self.variable = variable
# A new variable appearing is marked as changed # A new variable appearing is marked as changed
self.changed = True self.changed = True
@ -121,48 +117,17 @@ class Watch:
self.expression = expression self.expression = expression
self.result = None self.result = None
@staticmethod
def New( frame, expression, context ):
watch = {
'expression': expression,
'context': context,
}
if frame:
watch[ 'frameId' ] = frame[ 'id' ]
return Watch( watch )
class View: class View:
lines: typing.Dict[ int, Expandable ] lines: typing.Dict[ int, Expandable ]
draw: typing.Callable draw: typing.Callable
syntax: str
def __init__( self, win, lines, draw ): def __init__( self, win, lines, draw ):
self.lines = lines self.lines = lines
self.draw = draw self.draw = draw
self.syntax = None self.buf = win.buffer
if win is not None:
self.buf = win.buffer
utils.SetUpUIWindow( win )
utils.SetUpUIWindow( win )
class BufView( View ):
def __init__( self, buf, lines, draw ):
super().__init__( None, lines, draw )
self.buf = buf
def AddExpandMappings( mappings = None ):
if mappings is None:
mappings = settings.Dict( 'mappings' )[ 'variables' ]
for mapping in utils.GetVimList( mappings, 'expand_collapse' ):
vim.command( f'nnoremap <silent> <buffer> { mapping } '
':<C-u>call vimspector#ExpandVariable()<CR>' )
for mapping in utils.GetVimList( mappings, 'set_value' ):
vim.command( f'nnoremap <silent> <buffer> { mapping } '
':<C-u>call vimspector#SetVariableValue()<CR>' )
class VariablesView( object ): class VariablesView( object ):
@ -172,22 +137,19 @@ class VariablesView( object ):
self._connection = None self._connection = None
self._current_syntax = '' self._current_syntax = ''
self._server_capabilities = None
self._variable_eval: Scope = None def AddExpandMappings():
self._variable_eval_view: View = None vim.command( 'nnoremap <silent> <buffer> <CR> '
':<C-u>call vimspector#ExpandVariable()<CR>' )
mappings = settings.Dict( 'mappings' )[ 'variables' ] vim.command( 'nnoremap <silent> <buffer> <2-LeftMouse> '
':<C-u>call vimspector#ExpandVariable()<CR>' )
# Set up the "Variables" buffer in the variables_win # Set up the "Variables" buffer in the variables_win
self._scopes: typing.List[ Scope ] = [] self._scopes: typing.List[ Scope ] = []
self._vars = View( variables_win, {}, self._DrawScopes ) self._vars = View( variables_win, {}, self._DrawScopes )
utils.SetUpHiddenBuffer( self._vars.buf, 'vimspector.Variables' ) utils.SetUpHiddenBuffer( self._vars.buf, 'vimspector.Variables' )
with utils.LetCurrentWindow( variables_win ): with utils.LetCurrentWindow( variables_win ):
if utils.UseWinBar(): AddExpandMappings()
vim.command( 'nnoremenu <silent> 1.1 WinBar.Set '
':call vimspector#SetVariableValue()<CR>' )
AddExpandMappings( mappings )
# Set up the "Watches" buffer in the watches_win (and create a WinBar in # Set up the "Watches" buffer in the watches_win (and create a WinBar in
# there) # there)
@ -199,20 +161,17 @@ class VariablesView( object ):
'vimspector#AddWatchPrompt', 'vimspector#AddWatchPrompt',
'vimspector#OmniFuncWatch' ) 'vimspector#OmniFuncWatch' )
with utils.LetCurrentWindow( watches_win ): with utils.LetCurrentWindow( watches_win ):
AddExpandMappings( mappings ) AddExpandMappings()
for mapping in utils.GetVimList( mappings, 'delete' ): vim.command(
vim.command( 'nnoremap <buffer> <DEL> :call vimspector#DeleteWatch()<CR>' )
f'nnoremap <buffer> { mapping } :call vimspector#DeleteWatch()<CR>' )
if utils.UseWinBar(): if utils.UseWinBar():
vim.command( 'nnoremenu <silent> 1.1 WinBar.New ' vim.command( 'nnoremenu 1.1 WinBar.New '
':call vimspector#AddWatch()<CR>' ) ':call vimspector#AddWatch()<CR>' )
vim.command( 'nnoremenu <silent> 1.2 WinBar.Expand/Collapse ' vim.command( 'nnoremenu 1.2 WinBar.Expand/Collapse '
':call vimspector#ExpandVariable()<CR>' ) ':call vimspector#ExpandVariable()<CR>' )
vim.command( 'nnoremenu <silent> 1.3 WinBar.Delete ' vim.command( 'nnoremenu 1.3 WinBar.Delete '
':call vimspector#DeleteWatch()<CR>' ) ':call vimspector#DeleteWatch()<CR>' )
vim.command( 'nnoremenu <silent> 1.1 WinBar.Set '
':call vimspector#SetVariableValue()<CR>' )
# Set the (global!) balloon expr if supported # Set the (global!) balloon expr if supported
has_balloon = int( vim.eval( "has( 'balloon_eval' )" ) ) has_balloon = int( vim.eval( "has( 'balloon_eval' )" ) )
@ -224,9 +183,7 @@ class VariablesView( object ):
'balloonexpr': vim.options[ 'balloonexpr' ], 'balloonexpr': vim.options[ 'balloonexpr' ],
'balloondelay': vim.options[ 'balloondelay' ], 'balloondelay': vim.options[ 'balloondelay' ],
} }
vim.options[ 'balloonexpr' ] = ( "vimspector#internal#" vim.options[ 'balloonexpr' ] = 'vimspector#internal#balloon#BalloonExpr()'
"balloon#HoverTooltip()" )
vim.options[ 'balloondelay' ] = 250 vim.options[ 'balloondelay' ] = 250
if has_balloon: if has_balloon:
@ -244,30 +201,21 @@ class VariablesView( object ):
utils.ClearBuffer( self._vars.buf ) utils.ClearBuffer( self._vars.buf )
with utils.ModifiableScratchBuffer( self._watch.buf ): with utils.ModifiableScratchBuffer( self._watch.buf ):
utils.ClearBuffer( self._watch.buf ) utils.ClearBuffer( self._watch.buf )
self.ClearTooltip()
self._current_syntax = '' self._current_syntax = ''
def ConnectionUp( self, connection ): def ConnectionUp( self, connection ):
self._connection = connection self._connection = connection
def SetServerCapabilities( self, capabilities ):
self._server_capabilities = capabilities
def ConnectionClosed( self ): def ConnectionClosed( self ):
self.Clear() self.Clear()
self._connection = None self._connection = None
self._server_capabilities = None
def Reset( self ): def Reset( self ):
self._server_capabilities = None
for k, v in self._oldoptions.items(): for k, v in self._oldoptions.items():
vim.options[ k ] = v vim.options[ k ] = v
utils.CleanUpHiddenBuffer( self._vars.buf ) utils.CleanUpHiddenBuffer( self._vars.buf )
utils.CleanUpHiddenBuffer( self._watch.buf ) utils.CleanUpHiddenBuffer( self._watch.buf )
self.ClearTooltip()
def LoadScopes( self, frame ): def LoadScopes( self, frame ):
def scopes_consumer( message ): def scopes_consumer( message ):
@ -319,97 +267,15 @@ class VariablesView( object ):
}, },
} ) } )
def _DrawBalloonEval( self ):
watch = self._variable_eval
view = self._variable_eval_view
with utils.RestoreCursorPosition():
with utils.ModifiableScratchBuffer( view.buf ):
utils.ClearBuffer( view.buf )
view.syntax = utils.SetSyntax( view.syntax,
self._current_syntax,
view.buf )
self._DrawWatchResult( view,
0,
watch,
is_short = True )
vim.eval( "vimspector#internal#balloon#ResizeTooltip()" )
def ClearTooltip( self ):
# This will actually end up calling CleanUpTooltip via the popup close
# callback
vim.eval( 'vimspector#internal#balloon#Close()' )
def CleanUpTooltip( self ) :
# remove reference to old tooltip window
self._variable_eval_view = None
vim.vars[ 'vimspector_session_windows' ][ 'eval' ] = None
def VariableEval( self, frame, expression, is_hover ):
"""Callback to display variable under cursor `:h ballonexpr`"""
if not self._connection:
return ''
def handler( message ):
watch = self._variable_eval
if watch.result is None:
watch.result = WatchResult( message[ 'body' ] )
else:
watch.result.Update( message[ 'body' ] )
popup_win_id = utils.DisplayBalloon( self._is_term, [], is_hover )
# record the global eval window id
vim.vars[ 'vimspector_session_windows' ][ 'eval' ] = int( popup_win_id )
popup_bufnr = int( vim.eval( "winbufnr({})".format( popup_win_id ) ) )
# We don't need to do any UI window setup here, as it's already done as
# part of the popup creation, so just pass the buffer to the View instance
self._variable_eval_view = BufView(
vim.buffers[ popup_bufnr ],
{},
self._DrawBalloonEval
)
if watch.result.IsExpandable():
# Always expand the first level
watch.result.expanded = Expandable.EXPANDED_BY_US
if watch.result.IsExpanded():
self._connection.DoRequest( partial( self._ConsumeVariables,
self._variable_eval_view.draw,
watch.result ), {
'command': 'variables',
'arguments': {
'variablesReference': watch.result.VariablesReference(),
},
} )
self._DrawBalloonEval()
def failure_handler( reason, message ):
display = [ reason ]
float_win_id = utils.DisplayBalloon( self._is_term, display, is_hover )
# record the global eval window id
vim.vars[ 'vimspector_session_windows' ][ 'eval' ] = int( float_win_id )
self._variable_eval = Watch.New( frame,
expression,
'hover' )
# Send async request
self._connection.DoRequest( handler, {
'command': 'evaluate',
'arguments': self._variable_eval.expression,
}, failure_handler )
# Return working (meanwhile)
return ''
def AddWatch( self, frame, expression ): def AddWatch( self, frame, expression ):
self._watches.append( Watch.New( frame, expression, 'watch' ) ) watch = {
'expression': expression,
'context': 'watch',
}
if frame:
watch[ 'frameId' ] = frame[ 'id' ]
self._watches.append( Watch( watch ) )
self.EvaluateWatches() self.EvaluateWatches()
def DeleteWatch( self ): def DeleteWatch( self ):
@ -472,35 +338,20 @@ class VariablesView( object ):
watch.result = WatchFailure( reason ) watch.result = WatchFailure( reason )
self._DrawWatches() self._DrawWatches()
def _GetVariable( self, buf = None, line_num = None ): def ExpandVariable( self ):
none = ( None, None ) if vim.current.buffer == self._vars.buf:
if buf is None:
buf = vim.current.buffer
if line_num is None:
line_num = vim.current.window.cursor[ 0 ]
if buf == self._vars.buf:
view = self._vars view = self._vars
elif buf == self._watch.buf: elif vim.current.buffer == self._watch.buf:
view = self._watch view = self._watch
elif ( self._variable_eval_view is not None
and buf == self._variable_eval_view.buf ):
view = self._variable_eval_view
else: else:
return none
if line_num not in view.lines:
return none
return view.lines[ line_num ], view
def ExpandVariable( self, buf = None, line_num = None ):
variable, view = self._GetVariable( buf, line_num )
if variable is None:
return return
current_line = vim.current.window.cursor[ 0 ]
if current_line not in view.lines:
return
variable = view.lines[ current_line ]
if variable.IsExpanded(): if variable.IsExpanded():
# Collapse # Collapse
variable.expanded = Expandable.COLLAPSED_BY_USER variable.expanded = Expandable.COLLAPSED_BY_USER
@ -520,101 +371,25 @@ class VariablesView( object ):
}, },
} ) } )
def SetVariableValue( self, new_value = None, buf = None, line_num = None ): def _DrawVariables( self, view, variables, indent ):
variable: Variable
view: View
if not self._server_capabilities.get( 'supportsSetVariable' ):
return
variable, view = self._GetVariable( buf, line_num )
if variable is None:
return
if not variable.IsContained():
return
if new_value is None:
new_value = utils.AskForInput( 'New Value: ',
variable.variable.get( 'value', '' ),
completion = 'expr' )
if new_value is None:
return
def handler( message ):
# Annoyingly the response to setVariable request doesn't return a
# Variable, but some part of it, so take a copy of the existing Variable
# dict and update it, then call its update method with the updated copy.
new_variable = dict( variable.variable )
new_variable.update( message[ 'body' ] )
# Clear any existing known children (FIXME: Is this the right thing to do)
variable.variables = None
# If the variable is expanded, re-request its children
if variable.IsExpanded():
self._connection.DoRequest( partial( self._ConsumeVariables,
view.draw,
variable ), {
'command': 'variables',
'arguments': {
'variablesReference': variable.VariablesReference()
},
} )
variable.Update( new_variable )
view.draw()
def failure_handler( reason, message ):
utils.UserMessage( f'Cannot set value: { reason }', error = True )
self._connection.DoRequest( handler, {
'command': 'setVariable',
'arguments': {
'variablesReference': variable.container.VariablesReference(),
'name': variable.variable[ 'name' ],
'value': new_value
},
}, failure_handler = failure_handler )
def _DrawVariables( self, view, variables, indent, is_short = False ):
assert indent > 0 assert indent > 0
for variable in variables: for variable in variables:
text = '' line = utils.AppendToBuffer(
if is_short: view.buf,
text = '{indent}{icon} {name}: {value}'.format( '{indent}{marker}{icon} {name} ({type_}): {value}'.format(
# We borrow 1 space of indent to draw the change marker
indent = ' ' * ( indent - 1 ),
icon = '+' if ( variable.IsExpandable()
and not variable.IsExpanded() ) else '-',
name = variable.variable.get( 'name', '' ),
value = variable.variable.get( 'value', '<unknown>' )
)
else:
text = '{indent}{marker}{icon} {name} ({type_}): {value}'.format(
# We borrow 1 space of indent to draw the change marker # We borrow 1 space of indent to draw the change marker
indent = ' ' * ( indent - 1 ), indent = ' ' * ( indent - 1 ),
marker = '*' if variable.changed else ' ', marker = '*' if variable.changed else ' ',
icon = '+' if ( variable.IsExpandable() icon = '+' if ( variable.IsExpandable()
and not variable.IsExpanded() ) else '-', and not variable.IsExpanded() ) else '-',
name = variable.variable.get( 'name', '' ), name = variable.variable[ 'name' ],
type_ = variable.variable.get( 'type', '' ), type_ = variable.variable.get( 'type', '' ),
value = variable.variable.get( 'value', '<unknown>' ) value = variable.variable.get( 'value',
) '<unknown>' ) ).split( '\n' ) )
line = utils.AppendToBuffer(
view.buf,
text.split( '\n' )
)
view.lines[ line ] = variable view.lines[ line ] = variable
if variable.ShouldDrawDrillDown(): if variable.ShouldDrawDrillDown():
self._DrawVariables( view, variable.variables, indent + 2, is_short ) self._DrawVariables( view, variable.variables, indent + 2 )
def _DrawScopes( self ): def _DrawScopes( self ):
# FIXME: The drawing is dumb and draws from scratch every time. This is # FIXME: The drawing is dumb and draws from scratch every time. This is
@ -641,7 +416,7 @@ class VariablesView( object ):
'Expression: ' 'Expression: '
+ watch.expression[ 'expression' ] ) + watch.expression[ 'expression' ] )
watch.line = line watch.line = line
self._DrawWatchResult( self._watch, 2, watch ) self._DrawWatchResult( 2, watch )
def _DrawScope( self, indent, scope ): def _DrawScope( self, indent, scope ):
icon = '+' if scope.IsExpandable() and not scope.IsExpanded() else '-' icon = '+' if scope.IsExpandable() and not scope.IsExpanded() else '-'
@ -657,36 +432,27 @@ class VariablesView( object ):
indent += 2 indent += 2
self._DrawVariables( self._vars, scope.variables, indent ) self._DrawVariables( self._vars, scope.variables, indent )
def _DrawWatchResult( self, view, indent, watch, is_short = False ): def _DrawWatchResult( self, indent, watch ):
if not watch.result: if not watch.result:
return return
assert is_short or indent > 0 assert indent > 0
icon = '+' if ( watch.result.IsExpandable() and
not watch.result.IsExpanded() ) else '-'
if is_short: line = '{indent}{marker}{icon} Result: {result}'.format(
# The first result is always expanded in a hover (short format)
icon = ''
marker = ''
leader = ''
else:
icon = '+' if ( watch.result.IsExpandable() and
not watch.result.IsExpanded() ) else '-'
marker = '*' if watch.result.changed else ' '
leader = ' Result: '
line = '{indent}{marker}{icon}{leader}{result}'.format(
# We borrow 1 space of indent to draw the change marker # We borrow 1 space of indent to draw the change marker
indent = ' ' * ( indent - 1 ), indent = ' ' * ( indent - 1 ),
marker = marker, marker = '*' if watch.result.changed else ' ',
icon = icon, icon = icon,
leader = leader,
result = watch.result.result.get( 'result', '<unknown>' ) ) result = watch.result.result.get( 'result', '<unknown>' ) )
line = utils.AppendToBuffer( view.buf, line.split( '\n' ) ) line = utils.AppendToBuffer( self._watch.buf, line.split( '\n' ) )
view.lines[ line ] = watch.result self._watch.lines[ line ] = watch.result
if watch.result.ShouldDrawDrillDown(): if watch.result.ShouldDrawDrillDown():
self._DrawVariables( view, watch.result.variables, indent + 2, is_short ) indent = 4
self._DrawVariables( self._watch, watch.result.variables, indent )
def _ConsumeVariables( self, draw, parent, message ): def _ConsumeVariables( self, draw, parent, message ):
new_variables = [] new_variables = []
@ -701,8 +467,9 @@ class VariablesView( object ):
variable = v variable = v
found = True found = True
break break
if not found: if not found:
variable = Variable( parent, variable_body ) variable = Variable( variable_body )
else: else:
variable.Update( variable_body ) variable.Update( variable_body )
@ -722,10 +489,47 @@ class VariablesView( object ):
draw() draw()
def ShowBalloon( self, frame, expression ):
"""Callback to display variable under cursor `:h ballonexpr`"""
if not self._connection:
return ''
def handler( message ):
# TODO: this result count be expandable, but we have no way to allow the
# user to interact with the balloon to expand it, unless we use a popup
# instead, but even then we don't really want to trap the cursor.
body = message[ 'body' ]
result = body[ 'result' ]
if result is None:
result = 'null'
display = [
'Type: ' + body.get( 'type', '<unknown>' ),
'Value: ' + result
]
utils.DisplayBaloon( self._is_term, display )
def failure_handler( reason, message ):
display = [ reason ]
utils.DisplayBaloon( self._is_term, display )
# Send async request
self._connection.DoRequest( handler, {
'command': 'evaluate',
'arguments': {
'expression': expression,
'frameId': frame[ 'id' ],
'context': 'hover',
}
}, failure_handler )
# Return working (meanwhile)
return '...'
def SetSyntax( self, syntax ): def SetSyntax( self, syntax ):
# TODO: Switch to View.syntax
self._current_syntax = utils.SetSyntax( self._current_syntax, self._current_syntax = utils.SetSyntax( self._current_syntax,
syntax, syntax,
self._vars.buf, self._vars.buf,
self._watch.buf ) self._watch.buf )
# vim: sw=2 # vim: sw=2

View file

@ -21,7 +21,7 @@ out_fd=1
while [ -n "$1" ]; do while [ -n "$1" ]; do
case "$1" in case "$1" in
"--basedir"|"--base-dir"|"--test-base") "--basedir")
shift shift
SetBaseDir $1 SetBaseDir $1
shift shift
@ -36,7 +36,7 @@ while [ -n "$1" ]; do
INSTALL=$1 INSTALL=$1
shift shift
;; ;;
"--update"|"--upgrade") "--update")
UPDATE=1 UPDATE=1
shift shift
;; ;;
@ -91,8 +91,7 @@ if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "script" ]; then
if ! python3 $(dirname $0)/install_gadget.py \ if ! python3 $(dirname $0)/install_gadget.py \
--basedir ${BASEDIR} \ --basedir ${BASEDIR} \
${INSTALLER_ARGS} \ ${INSTALLER_ARGS} \
--all \ --all; then
--force-enable-csharp; then
echo "Script installation reported errors" >&2 echo "Script installation reported errors" >&2
exit 1 exit 1
fi fi
@ -103,7 +102,7 @@ if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "vim" ]; then
--cmd "${BASEDIR_CMD}" \ --cmd "${BASEDIR_CMD}" \
-c 'autocmd User VimspectorInstallSuccess qa!' \ -c 'autocmd User VimspectorInstallSuccess qa!' \
-c 'autocmd User VimspectorInstallFailed cquit!' \ -c 'autocmd User VimspectorInstallFailed cquit!' \
-c "VimspectorInstall --all netcoredbg"; then -c "VimspectorInstall --all"; then
echo "Vim installation reported errors" >&2 echo "Vim installation reported errors" >&2
exit 1 exit 1
fi fi
@ -145,9 +144,6 @@ set -e
pushd tests/testdata/cpp/simple pushd tests/testdata/cpp/simple
make clean all make clean all
popd popd
pushd support/test/csharp
dotnet build
popd
set +e set +e
echo "%DONE - built test programs" echo "%DONE - built test programs"

View file

@ -1,12 +1,5 @@
" setup boilerplate to make this file usable with vim -Nu <tihs file> {{{
scriptencoding utf-8
execute 'source' expand( '<sfile>:p:h' ) . '/minimal_vimrc' execute 'source' expand( '<sfile>:p:h' ) . '/minimal_vimrc'
set noequalalways set noequalalways
let mapleader = ','
let maplocalleader = "\<Space>"
" }}}
" Custom Layout {{{
function! s:CustomiseUI() function! s:CustomiseUI()
let wins = g:vimspector_session_windows let wins = g:vimspector_session_windows
@ -38,10 +31,6 @@ function! s:CustomiseUI()
endfunction endfunction
function s:SetUpTerminal() function s:SetUpTerminal()
if !has_key( g:vimspector_session_windows, 'terminal' )
" There's a neovim bug which means that this doesn't work in neovim
return
endif
let terminal_win = g:vimspector_session_windows.terminal let terminal_win = g:vimspector_session_windows.terminal
" Make the terminal window at most 80 columns wide, ensuring there is enough " Make the terminal window at most 80 columns wide, ensuring there is enough
@ -54,7 +43,7 @@ function s:SetUpTerminal()
let padding = 4 let padding = 4
let cols = max( [ min( [ &columns - left_bar - code - padding, 80 ] ), 10 ] ) let cols = max( [ min( [ &columns - left_bar - code - padding, 80 ] ), 10 ] )
call win_gotoid( terminal_win ) call win_gotoid( terminal_win )
execute string(cols) . 'wincmd |' execute cols . 'wincmd |'
endfunction endfunction
function! s:CustomiseWinBar() function! s:CustomiseWinBar()
@ -77,85 +66,9 @@ augroup TestUICustomistaion
autocmd User VimspectorUICreated call s:CustomiseWinBar() autocmd User VimspectorUICreated call s:CustomiseWinBar()
augroup END augroup END
" }}}
" Custom sign priority {{{
let g:vimspector_sign_priority = { let g:vimspector_sign_priority = {
\ 'vimspectorBP': 3, \ 'vimspectorBP': 3,
\ 'vimspectorBPCond': 2, \ 'vimspectorBPCond': 2,
\ 'vimspectorBPDisabled': 1, \ 'vimspectorBPDisabled': 1,
\ 'vimspectorPC': 999, \ 'vimspectorPC': 999,
\ } \ }
" }}}
" Custom mappings while debuggins {{{
let s:mapped = {}
function! s:OnJumpToFrame() abort
if has_key( s:mapped, string( bufnr() ) )
return
endif
nmap <silent> <buffer> <LocalLeader>dn <Plug>VimspectorStepOver
nmap <silent> <buffer> <LocalLeader>ds <Plug>VimspectorStepInto
nmap <silent> <buffer> <LocalLeader>df <Plug>VimspectorStepOut
nmap <silent> <buffer> <LocalLeader>dc <Plug>VimspectorContinue
nmap <silent> <buffer> <LocalLeader>di <Plug>VimspectorBalloonEval
xmap <silent> <buffer> <LocalLeader>di <Plug>VimspectorBalloonEval
let s:mapped[ string( bufnr() ) ] = { 'modifiable': &modifiable }
setlocal nomodifiable
endfunction
function! s:OnDebugEnd() abort
let original_buf = bufnr()
let hidden = &hidden
try
set hidden
for bufnr in keys( s:mapped )
try
execute 'noautocmd buffer' bufnr
silent! nunmap <buffer> <LocalLeader>dn
silent! nunmap <buffer> <LocalLeader>ds
silent! nunmap <buffer> <LocalLeader>df
silent! nunmap <buffer> <LocalLeader>dc
silent! nunmap <buffer> <LocalLeader>di
silent! xunmap <buffer> <LocalLeader>di
let &l:modifiable = s:mapped[ bufnr ][ 'modifiable' ]
endtry
endfor
finally
execute 'noautocmd buffer' original_buf
let &hidden = hidden
endtry
let s:mapped = {}
endfunction
augroup TestCustomMappings
au!
autocmd User VimspectorJumpedToFrame call s:OnJumpToFrame()
autocmd User VimspectorDebugEnded call s:OnDebugEnd()
augroup END
" }}}
" Custom mappings for special buffers {{{
let g:vimspector_mappings = {
\ 'stack_trace': {},
\ 'variables': {
\ 'set_value': [ '<Tab>', '<C-CR>', 'C' ],
\ }
\ }
" }}}
" vim: foldmethod=marker

View file

@ -1,8 +0,0 @@
# Manually updating shipped gadgets
Download the gadget files manuall from their official source into this dir.
Run `./checksum.py <list of files>` to get the checksums.
Update ../../python3/vimspector/gadgets.py with the new version and the
checksums.

View file

@ -1,13 +0,0 @@
#!/usr/bin/env python3
import hashlib
import sys
def GetChecksumSHA254( file_path ):
with open( file_path, 'rb' ) as existing_file:
return hashlib.sha256( existing_file.read() ).hexdigest()
for arg in sys.argv[ 1: ]:
print( f"{ arg } = { GetChecksumSHA254( arg ) }" )

View file

@ -1,15 +0,0 @@
{
"$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json",
"configurations": {
"Run Current Script": {
"adapter": "vscode-bash",
"autoselect": false,
"configuration": {
"request": "launch",
"program": "${file}",
"cwd": "${fileDirname}",
"args": [ "*${args}" ]
}
}
}
}

View file

@ -15,15 +15,6 @@
"program": "${workspaceRoot}/test", "program": "${workspaceRoot}/test",
"stopAtEntry": true "stopAtEntry": true
} }
},
"cpptools": {
"adapter": "vscode-cpptools",
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/test",
"stopOnEntry": true,
"MIMode": "lldb"
}
} }
} }
} }

View file

@ -1,4 +1,4 @@
def Settings( **kwargs ): def Settings( **kwargs ):
return { return {
'flags': [ '-x', 'c++', '-Wall', '-Wextra', '-std=c++17' ] 'flags': [ '-x', 'c++', '-Wall', '-Wextra' ]
} }

View file

@ -1,3 +1,2 @@
bin/ bin/
obj/Debug obj/Debug
obj/

View file

@ -1,57 +1,25 @@
{ {
"adapters": { "configurations": {
"netcoredbg-debuglog": { "launch - netcoredbg": {
"attach": { "adapter": "netcoredbg",
"pidProperty": "processId", "configuration": {
"pidSelect": "ask" "request": "launch",
"program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll",
"args": [],
"stopAtEntry": true
}
}, },
"command": [ "launch - mono": {
"${gadgetDir}/netcoredbg/netcoredbg", "adapter": "vscode-mono-debug",
"--interpreter=vscode", "configuration": {
"--engineLogging=${workspaceRoot}/netcoredbg.engine.log", "request": "launch",
"--log=${workspaceRoot}/netcoredbg.log" "program": "${workspaceRoot}/Program.exe",
], "console": "integratedTerminal",
"configuration": { "cwd": "${workspaceRoot}",
"cwd": "${workspaceRoot}" "args": [],
}, "env": {}
"name": "netcoredbg" }
}
},
"configurations": {
//
// NOTE:
// If you add to this, you must update tests/get_configurations.test.vim
//
"launch - netcoredbg": {
"adapter": "netcoredbg",
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/netcoreapp3.1/csharp.dll",
"args": [],
"stopAtEntry": false
}
},
"launch - netcoredbg - with debug log": {
"adapter": "netcoredbg-debuglog",
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/netcoreapp3.1/csharp.dll",
"args": [],
"stopAtEntry": false
}
},
"launch - mono": {
"adapter": "vscode-mono-debug",
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/Program.exe",
"console": "integratedTerminal",
"cwd": "${workspaceRoot}",
"args": [],
"env": {}
} }
} }
}
} }

View file

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View file

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio 15
VisualStudioVersion = 15.0.26124.0 VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csharp", "csharp.csproj", "{91DB205F-E422-430B-BBB8-955110C7B3B6}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -17,18 +15,4 @@ Global
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x64.ActiveCfg = Debug|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x64.Build.0 = Debug|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x86.ActiveCfg = Debug|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x86.Build.0 = Debug|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|Any CPU.Build.0 = Release|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x64.ActiveCfg = Release|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x64.Build.0 = Release|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x86.ActiveCfg = Release|Any CPU
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal EndGlobal

View file

@ -0,0 +1,5 @@
{
"version": 1,
"dgSpecHash": "6/vdr7YprlSIoQecv/nNuLNflFpO0X7eN7jHUinZTsgian9nYpmHMWirsDWMi5l+29TH+Qy8O/QfaB/48QtjRQ==",
"success": true
}

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">/Users/ben/.nuget/packages/</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">/Users/ben/.nuget/packages/;/usr/local/share/dotnet/sdk/NuGetFallbackFolder</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">5.7.0</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="$([MSBuild]::EnsureTrailingSlash($(NuGetPackageFolders)))" />
</ItemGroup>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.2.0/build/netcoreapp2.2/Microsoft.NETCore.App.props" Condition="Exists('/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.2.0/build/netcoreapp2.2/Microsoft.NETCore.App.props')" />
</ImportGroup>
</Project>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="/usr/local/share/dotnet/sdk/NuGetFallbackFolder/netstandard.library/2.0.3/build/netstandard2.0/NETStandard.Library.targets" Condition="Exists('/usr/local/share/dotnet/sdk/NuGetFallbackFolder/netstandard.library/2.0.3/build/netstandard2.0/NETStandard.Library.targets')" />
<Import Project="/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.2.0/build/netcoreapp2.2/Microsoft.NETCore.App.targets" Condition="Exists('/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.2.0/build/netcoreapp2.2/Microsoft.NETCore.App.targets')" />
</ImportGroup>
</Project>

View file

@ -0,0 +1,748 @@
{
"version": 3,
"targets": {
".NETCoreApp,Version=v2.2": {
"Microsoft.NETCore.App/2.2.0": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.DotNetHostPolicy": "2.2.0",
"Microsoft.NETCore.Platforms": "2.2.0",
"Microsoft.NETCore.Targets": "2.0.0",
"NETStandard.Library": "2.0.3"
},
"compile": {
"ref/netcoreapp2.2/Microsoft.CSharp.dll": {},
"ref/netcoreapp2.2/Microsoft.VisualBasic.dll": {},
"ref/netcoreapp2.2/Microsoft.Win32.Primitives.dll": {},
"ref/netcoreapp2.2/System.AppContext.dll": {},
"ref/netcoreapp2.2/System.Buffers.dll": {},
"ref/netcoreapp2.2/System.Collections.Concurrent.dll": {},
"ref/netcoreapp2.2/System.Collections.Immutable.dll": {},
"ref/netcoreapp2.2/System.Collections.NonGeneric.dll": {},
"ref/netcoreapp2.2/System.Collections.Specialized.dll": {},
"ref/netcoreapp2.2/System.Collections.dll": {},
"ref/netcoreapp2.2/System.ComponentModel.Annotations.dll": {},
"ref/netcoreapp2.2/System.ComponentModel.DataAnnotations.dll": {},
"ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.dll": {},
"ref/netcoreapp2.2/System.ComponentModel.Primitives.dll": {},
"ref/netcoreapp2.2/System.ComponentModel.TypeConverter.dll": {},
"ref/netcoreapp2.2/System.ComponentModel.dll": {},
"ref/netcoreapp2.2/System.Configuration.dll": {},
"ref/netcoreapp2.2/System.Console.dll": {},
"ref/netcoreapp2.2/System.Core.dll": {},
"ref/netcoreapp2.2/System.Data.Common.dll": {},
"ref/netcoreapp2.2/System.Data.dll": {},
"ref/netcoreapp2.2/System.Diagnostics.Contracts.dll": {},
"ref/netcoreapp2.2/System.Diagnostics.Debug.dll": {},
"ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.dll": {},
"ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.dll": {},
"ref/netcoreapp2.2/System.Diagnostics.Process.dll": {},
"ref/netcoreapp2.2/System.Diagnostics.StackTrace.dll": {},
"ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.dll": {},
"ref/netcoreapp2.2/System.Diagnostics.Tools.dll": {},
"ref/netcoreapp2.2/System.Diagnostics.TraceSource.dll": {},
"ref/netcoreapp2.2/System.Diagnostics.Tracing.dll": {},
"ref/netcoreapp2.2/System.Drawing.Primitives.dll": {},
"ref/netcoreapp2.2/System.Drawing.dll": {},
"ref/netcoreapp2.2/System.Dynamic.Runtime.dll": {},
"ref/netcoreapp2.2/System.Globalization.Calendars.dll": {},
"ref/netcoreapp2.2/System.Globalization.Extensions.dll": {},
"ref/netcoreapp2.2/System.Globalization.dll": {},
"ref/netcoreapp2.2/System.IO.Compression.Brotli.dll": {},
"ref/netcoreapp2.2/System.IO.Compression.FileSystem.dll": {},
"ref/netcoreapp2.2/System.IO.Compression.ZipFile.dll": {},
"ref/netcoreapp2.2/System.IO.Compression.dll": {},
"ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.dll": {},
"ref/netcoreapp2.2/System.IO.FileSystem.Primitives.dll": {},
"ref/netcoreapp2.2/System.IO.FileSystem.Watcher.dll": {},
"ref/netcoreapp2.2/System.IO.FileSystem.dll": {},
"ref/netcoreapp2.2/System.IO.IsolatedStorage.dll": {},
"ref/netcoreapp2.2/System.IO.MemoryMappedFiles.dll": {},
"ref/netcoreapp2.2/System.IO.Pipes.dll": {},
"ref/netcoreapp2.2/System.IO.UnmanagedMemoryStream.dll": {},
"ref/netcoreapp2.2/System.IO.dll": {},
"ref/netcoreapp2.2/System.Linq.Expressions.dll": {},
"ref/netcoreapp2.2/System.Linq.Parallel.dll": {},
"ref/netcoreapp2.2/System.Linq.Queryable.dll": {},
"ref/netcoreapp2.2/System.Linq.dll": {},
"ref/netcoreapp2.2/System.Memory.dll": {},
"ref/netcoreapp2.2/System.Net.Http.dll": {},
"ref/netcoreapp2.2/System.Net.HttpListener.dll": {},
"ref/netcoreapp2.2/System.Net.Mail.dll": {},
"ref/netcoreapp2.2/System.Net.NameResolution.dll": {},
"ref/netcoreapp2.2/System.Net.NetworkInformation.dll": {},
"ref/netcoreapp2.2/System.Net.Ping.dll": {},
"ref/netcoreapp2.2/System.Net.Primitives.dll": {},
"ref/netcoreapp2.2/System.Net.Requests.dll": {},
"ref/netcoreapp2.2/System.Net.Security.dll": {},
"ref/netcoreapp2.2/System.Net.ServicePoint.dll": {},
"ref/netcoreapp2.2/System.Net.Sockets.dll": {},
"ref/netcoreapp2.2/System.Net.WebClient.dll": {},
"ref/netcoreapp2.2/System.Net.WebHeaderCollection.dll": {},
"ref/netcoreapp2.2/System.Net.WebProxy.dll": {},
"ref/netcoreapp2.2/System.Net.WebSockets.Client.dll": {},
"ref/netcoreapp2.2/System.Net.WebSockets.dll": {},
"ref/netcoreapp2.2/System.Net.dll": {},
"ref/netcoreapp2.2/System.Numerics.Vectors.dll": {},
"ref/netcoreapp2.2/System.Numerics.dll": {},
"ref/netcoreapp2.2/System.ObjectModel.dll": {},
"ref/netcoreapp2.2/System.Reflection.DispatchProxy.dll": {},
"ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.dll": {},
"ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.dll": {},
"ref/netcoreapp2.2/System.Reflection.Emit.dll": {},
"ref/netcoreapp2.2/System.Reflection.Extensions.dll": {},
"ref/netcoreapp2.2/System.Reflection.Metadata.dll": {},
"ref/netcoreapp2.2/System.Reflection.Primitives.dll": {},
"ref/netcoreapp2.2/System.Reflection.TypeExtensions.dll": {},
"ref/netcoreapp2.2/System.Reflection.dll": {},
"ref/netcoreapp2.2/System.Resources.Reader.dll": {},
"ref/netcoreapp2.2/System.Resources.ResourceManager.dll": {},
"ref/netcoreapp2.2/System.Resources.Writer.dll": {},
"ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.dll": {},
"ref/netcoreapp2.2/System.Runtime.Extensions.dll": {},
"ref/netcoreapp2.2/System.Runtime.Handles.dll": {},
"ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.dll": {},
"ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.dll": {},
"ref/netcoreapp2.2/System.Runtime.InteropServices.dll": {},
"ref/netcoreapp2.2/System.Runtime.Loader.dll": {},
"ref/netcoreapp2.2/System.Runtime.Numerics.dll": {},
"ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.dll": {},
"ref/netcoreapp2.2/System.Runtime.Serialization.Json.dll": {},
"ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.dll": {},
"ref/netcoreapp2.2/System.Runtime.Serialization.Xml.dll": {},
"ref/netcoreapp2.2/System.Runtime.Serialization.dll": {},
"ref/netcoreapp2.2/System.Runtime.dll": {},
"ref/netcoreapp2.2/System.Security.Claims.dll": {},
"ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.dll": {},
"ref/netcoreapp2.2/System.Security.Cryptography.Csp.dll": {},
"ref/netcoreapp2.2/System.Security.Cryptography.Encoding.dll": {},
"ref/netcoreapp2.2/System.Security.Cryptography.Primitives.dll": {},
"ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.dll": {},
"ref/netcoreapp2.2/System.Security.Principal.dll": {},
"ref/netcoreapp2.2/System.Security.SecureString.dll": {},
"ref/netcoreapp2.2/System.Security.dll": {},
"ref/netcoreapp2.2/System.ServiceModel.Web.dll": {},
"ref/netcoreapp2.2/System.ServiceProcess.dll": {},
"ref/netcoreapp2.2/System.Text.Encoding.Extensions.dll": {},
"ref/netcoreapp2.2/System.Text.Encoding.dll": {},
"ref/netcoreapp2.2/System.Text.RegularExpressions.dll": {},
"ref/netcoreapp2.2/System.Threading.Overlapped.dll": {},
"ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.dll": {},
"ref/netcoreapp2.2/System.Threading.Tasks.Extensions.dll": {},
"ref/netcoreapp2.2/System.Threading.Tasks.Parallel.dll": {},
"ref/netcoreapp2.2/System.Threading.Tasks.dll": {},
"ref/netcoreapp2.2/System.Threading.Thread.dll": {},
"ref/netcoreapp2.2/System.Threading.ThreadPool.dll": {},
"ref/netcoreapp2.2/System.Threading.Timer.dll": {},
"ref/netcoreapp2.2/System.Threading.dll": {},
"ref/netcoreapp2.2/System.Transactions.Local.dll": {},
"ref/netcoreapp2.2/System.Transactions.dll": {},
"ref/netcoreapp2.2/System.ValueTuple.dll": {},
"ref/netcoreapp2.2/System.Web.HttpUtility.dll": {},
"ref/netcoreapp2.2/System.Web.dll": {},
"ref/netcoreapp2.2/System.Windows.dll": {},
"ref/netcoreapp2.2/System.Xml.Linq.dll": {},
"ref/netcoreapp2.2/System.Xml.ReaderWriter.dll": {},
"ref/netcoreapp2.2/System.Xml.Serialization.dll": {},
"ref/netcoreapp2.2/System.Xml.XDocument.dll": {},
"ref/netcoreapp2.2/System.Xml.XPath.XDocument.dll": {},
"ref/netcoreapp2.2/System.Xml.XPath.dll": {},
"ref/netcoreapp2.2/System.Xml.XmlDocument.dll": {},
"ref/netcoreapp2.2/System.Xml.XmlSerializer.dll": {},
"ref/netcoreapp2.2/System.Xml.dll": {},
"ref/netcoreapp2.2/System.dll": {},
"ref/netcoreapp2.2/WindowsBase.dll": {},
"ref/netcoreapp2.2/mscorlib.dll": {},
"ref/netcoreapp2.2/netstandard.dll": {}
},
"build": {
"build/netcoreapp2.2/Microsoft.NETCore.App.props": {},
"build/netcoreapp2.2/Microsoft.NETCore.App.targets": {}
}
},
"Microsoft.NETCore.DotNetAppHost/2.2.0": {
"type": "package"
},
"Microsoft.NETCore.DotNetHostPolicy/2.2.0": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.DotNetHostResolver": "2.2.0"
}
},
"Microsoft.NETCore.DotNetHostResolver/2.2.0": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.DotNetAppHost": "2.2.0"
}
},
"Microsoft.NETCore.Platforms/2.2.0": {
"type": "package",
"compile": {
"lib/netstandard1.0/_._": {}
},
"runtime": {
"lib/netstandard1.0/_._": {}
}
},
"Microsoft.NETCore.Targets/2.0.0": {
"type": "package",
"compile": {
"lib/netstandard1.0/_._": {}
},
"runtime": {
"lib/netstandard1.0/_._": {}
}
},
"NETStandard.Library/2.0.3": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0"
},
"compile": {
"lib/netstandard1.0/_._": {}
},
"runtime": {
"lib/netstandard1.0/_._": {}
},
"build": {
"build/netstandard2.0/NETStandard.Library.targets": {}
}
}
}
},
"libraries": {
"Microsoft.NETCore.App/2.2.0": {
"sha512": "7z5l8Jp324S8bU8+yyWeYHXUFYvKyiI5lqS1dXgTzOx1H69Qbf6df12kCKlNX45LpMfCMd4U3M6p7Rl5Zk7SLA==",
"type": "package",
"path": "microsoft.netcore.app/2.2.0",
"files": [
".nupkg.metadata",
".signature.p7s",
"LICENSE.TXT",
"Microsoft.NETCore.App.versions.txt",
"THIRD-PARTY-NOTICES.TXT",
"build/netcoreapp2.2/Microsoft.NETCore.App.PlatformManifest.txt",
"build/netcoreapp2.2/Microsoft.NETCore.App.props",
"build/netcoreapp2.2/Microsoft.NETCore.App.targets",
"microsoft.netcore.app.2.2.0.nupkg.sha512",
"microsoft.netcore.app.nuspec",
"ref/netcoreapp2.2/Microsoft.CSharp.dll",
"ref/netcoreapp2.2/Microsoft.CSharp.xml",
"ref/netcoreapp2.2/Microsoft.VisualBasic.dll",
"ref/netcoreapp2.2/Microsoft.VisualBasic.xml",
"ref/netcoreapp2.2/Microsoft.Win32.Primitives.dll",
"ref/netcoreapp2.2/Microsoft.Win32.Primitives.xml",
"ref/netcoreapp2.2/System.AppContext.dll",
"ref/netcoreapp2.2/System.Buffers.dll",
"ref/netcoreapp2.2/System.Buffers.xml",
"ref/netcoreapp2.2/System.Collections.Concurrent.dll",
"ref/netcoreapp2.2/System.Collections.Concurrent.xml",
"ref/netcoreapp2.2/System.Collections.Immutable.dll",
"ref/netcoreapp2.2/System.Collections.Immutable.xml",
"ref/netcoreapp2.2/System.Collections.NonGeneric.dll",
"ref/netcoreapp2.2/System.Collections.NonGeneric.xml",
"ref/netcoreapp2.2/System.Collections.Specialized.dll",
"ref/netcoreapp2.2/System.Collections.Specialized.xml",
"ref/netcoreapp2.2/System.Collections.dll",
"ref/netcoreapp2.2/System.Collections.xml",
"ref/netcoreapp2.2/System.ComponentModel.Annotations.dll",
"ref/netcoreapp2.2/System.ComponentModel.Annotations.xml",
"ref/netcoreapp2.2/System.ComponentModel.DataAnnotations.dll",
"ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.dll",
"ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.xml",
"ref/netcoreapp2.2/System.ComponentModel.Primitives.dll",
"ref/netcoreapp2.2/System.ComponentModel.Primitives.xml",
"ref/netcoreapp2.2/System.ComponentModel.TypeConverter.dll",
"ref/netcoreapp2.2/System.ComponentModel.TypeConverter.xml",
"ref/netcoreapp2.2/System.ComponentModel.dll",
"ref/netcoreapp2.2/System.ComponentModel.xml",
"ref/netcoreapp2.2/System.Configuration.dll",
"ref/netcoreapp2.2/System.Console.dll",
"ref/netcoreapp2.2/System.Console.xml",
"ref/netcoreapp2.2/System.Core.dll",
"ref/netcoreapp2.2/System.Data.Common.dll",
"ref/netcoreapp2.2/System.Data.Common.xml",
"ref/netcoreapp2.2/System.Data.dll",
"ref/netcoreapp2.2/System.Diagnostics.Contracts.dll",
"ref/netcoreapp2.2/System.Diagnostics.Contracts.xml",
"ref/netcoreapp2.2/System.Diagnostics.Debug.dll",
"ref/netcoreapp2.2/System.Diagnostics.Debug.xml",
"ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.dll",
"ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.xml",
"ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.dll",
"ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.xml",
"ref/netcoreapp2.2/System.Diagnostics.Process.dll",
"ref/netcoreapp2.2/System.Diagnostics.Process.xml",
"ref/netcoreapp2.2/System.Diagnostics.StackTrace.dll",
"ref/netcoreapp2.2/System.Diagnostics.StackTrace.xml",
"ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.dll",
"ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.xml",
"ref/netcoreapp2.2/System.Diagnostics.Tools.dll",
"ref/netcoreapp2.2/System.Diagnostics.Tools.xml",
"ref/netcoreapp2.2/System.Diagnostics.TraceSource.dll",
"ref/netcoreapp2.2/System.Diagnostics.TraceSource.xml",
"ref/netcoreapp2.2/System.Diagnostics.Tracing.dll",
"ref/netcoreapp2.2/System.Diagnostics.Tracing.xml",
"ref/netcoreapp2.2/System.Drawing.Primitives.dll",
"ref/netcoreapp2.2/System.Drawing.Primitives.xml",
"ref/netcoreapp2.2/System.Drawing.dll",
"ref/netcoreapp2.2/System.Dynamic.Runtime.dll",
"ref/netcoreapp2.2/System.Globalization.Calendars.dll",
"ref/netcoreapp2.2/System.Globalization.Extensions.dll",
"ref/netcoreapp2.2/System.Globalization.dll",
"ref/netcoreapp2.2/System.IO.Compression.Brotli.dll",
"ref/netcoreapp2.2/System.IO.Compression.FileSystem.dll",
"ref/netcoreapp2.2/System.IO.Compression.ZipFile.dll",
"ref/netcoreapp2.2/System.IO.Compression.ZipFile.xml",
"ref/netcoreapp2.2/System.IO.Compression.dll",
"ref/netcoreapp2.2/System.IO.Compression.xml",
"ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.dll",
"ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.xml",
"ref/netcoreapp2.2/System.IO.FileSystem.Primitives.dll",
"ref/netcoreapp2.2/System.IO.FileSystem.Watcher.dll",
"ref/netcoreapp2.2/System.IO.FileSystem.Watcher.xml",
"ref/netcoreapp2.2/System.IO.FileSystem.dll",
"ref/netcoreapp2.2/System.IO.FileSystem.xml",
"ref/netcoreapp2.2/System.IO.IsolatedStorage.dll",
"ref/netcoreapp2.2/System.IO.IsolatedStorage.xml",
"ref/netcoreapp2.2/System.IO.MemoryMappedFiles.dll",
"ref/netcoreapp2.2/System.IO.MemoryMappedFiles.xml",
"ref/netcoreapp2.2/System.IO.Pipes.dll",
"ref/netcoreapp2.2/System.IO.Pipes.xml",
"ref/netcoreapp2.2/System.IO.UnmanagedMemoryStream.dll",
"ref/netcoreapp2.2/System.IO.dll",
"ref/netcoreapp2.2/System.Linq.Expressions.dll",
"ref/netcoreapp2.2/System.Linq.Expressions.xml",
"ref/netcoreapp2.2/System.Linq.Parallel.dll",
"ref/netcoreapp2.2/System.Linq.Parallel.xml",
"ref/netcoreapp2.2/System.Linq.Queryable.dll",
"ref/netcoreapp2.2/System.Linq.Queryable.xml",
"ref/netcoreapp2.2/System.Linq.dll",
"ref/netcoreapp2.2/System.Linq.xml",
"ref/netcoreapp2.2/System.Memory.dll",
"ref/netcoreapp2.2/System.Memory.xml",
"ref/netcoreapp2.2/System.Net.Http.dll",
"ref/netcoreapp2.2/System.Net.Http.xml",
"ref/netcoreapp2.2/System.Net.HttpListener.dll",
"ref/netcoreapp2.2/System.Net.HttpListener.xml",
"ref/netcoreapp2.2/System.Net.Mail.dll",
"ref/netcoreapp2.2/System.Net.Mail.xml",
"ref/netcoreapp2.2/System.Net.NameResolution.dll",
"ref/netcoreapp2.2/System.Net.NameResolution.xml",
"ref/netcoreapp2.2/System.Net.NetworkInformation.dll",
"ref/netcoreapp2.2/System.Net.NetworkInformation.xml",
"ref/netcoreapp2.2/System.Net.Ping.dll",
"ref/netcoreapp2.2/System.Net.Ping.xml",
"ref/netcoreapp2.2/System.Net.Primitives.dll",
"ref/netcoreapp2.2/System.Net.Primitives.xml",
"ref/netcoreapp2.2/System.Net.Requests.dll",
"ref/netcoreapp2.2/System.Net.Requests.xml",
"ref/netcoreapp2.2/System.Net.Security.dll",
"ref/netcoreapp2.2/System.Net.Security.xml",
"ref/netcoreapp2.2/System.Net.ServicePoint.dll",
"ref/netcoreapp2.2/System.Net.ServicePoint.xml",
"ref/netcoreapp2.2/System.Net.Sockets.dll",
"ref/netcoreapp2.2/System.Net.Sockets.xml",
"ref/netcoreapp2.2/System.Net.WebClient.dll",
"ref/netcoreapp2.2/System.Net.WebClient.xml",
"ref/netcoreapp2.2/System.Net.WebHeaderCollection.dll",
"ref/netcoreapp2.2/System.Net.WebHeaderCollection.xml",
"ref/netcoreapp2.2/System.Net.WebProxy.dll",
"ref/netcoreapp2.2/System.Net.WebProxy.xml",
"ref/netcoreapp2.2/System.Net.WebSockets.Client.dll",
"ref/netcoreapp2.2/System.Net.WebSockets.Client.xml",
"ref/netcoreapp2.2/System.Net.WebSockets.dll",
"ref/netcoreapp2.2/System.Net.WebSockets.xml",
"ref/netcoreapp2.2/System.Net.dll",
"ref/netcoreapp2.2/System.Numerics.Vectors.dll",
"ref/netcoreapp2.2/System.Numerics.Vectors.xml",
"ref/netcoreapp2.2/System.Numerics.dll",
"ref/netcoreapp2.2/System.ObjectModel.dll",
"ref/netcoreapp2.2/System.ObjectModel.xml",
"ref/netcoreapp2.2/System.Reflection.DispatchProxy.dll",
"ref/netcoreapp2.2/System.Reflection.DispatchProxy.xml",
"ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.dll",
"ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.xml",
"ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.dll",
"ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.xml",
"ref/netcoreapp2.2/System.Reflection.Emit.dll",
"ref/netcoreapp2.2/System.Reflection.Emit.xml",
"ref/netcoreapp2.2/System.Reflection.Extensions.dll",
"ref/netcoreapp2.2/System.Reflection.Metadata.dll",
"ref/netcoreapp2.2/System.Reflection.Metadata.xml",
"ref/netcoreapp2.2/System.Reflection.Primitives.dll",
"ref/netcoreapp2.2/System.Reflection.Primitives.xml",
"ref/netcoreapp2.2/System.Reflection.TypeExtensions.dll",
"ref/netcoreapp2.2/System.Reflection.TypeExtensions.xml",
"ref/netcoreapp2.2/System.Reflection.dll",
"ref/netcoreapp2.2/System.Resources.Reader.dll",
"ref/netcoreapp2.2/System.Resources.ResourceManager.dll",
"ref/netcoreapp2.2/System.Resources.ResourceManager.xml",
"ref/netcoreapp2.2/System.Resources.Writer.dll",
"ref/netcoreapp2.2/System.Resources.Writer.xml",
"ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.dll",
"ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.xml",
"ref/netcoreapp2.2/System.Runtime.Extensions.dll",
"ref/netcoreapp2.2/System.Runtime.Extensions.xml",
"ref/netcoreapp2.2/System.Runtime.Handles.dll",
"ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.dll",
"ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.xml",
"ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.dll",
"ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.xml",
"ref/netcoreapp2.2/System.Runtime.InteropServices.dll",
"ref/netcoreapp2.2/System.Runtime.InteropServices.xml",
"ref/netcoreapp2.2/System.Runtime.Loader.dll",
"ref/netcoreapp2.2/System.Runtime.Loader.xml",
"ref/netcoreapp2.2/System.Runtime.Numerics.dll",
"ref/netcoreapp2.2/System.Runtime.Numerics.xml",
"ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.dll",
"ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.xml",
"ref/netcoreapp2.2/System.Runtime.Serialization.Json.dll",
"ref/netcoreapp2.2/System.Runtime.Serialization.Json.xml",
"ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.dll",
"ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.xml",
"ref/netcoreapp2.2/System.Runtime.Serialization.Xml.dll",
"ref/netcoreapp2.2/System.Runtime.Serialization.Xml.xml",
"ref/netcoreapp2.2/System.Runtime.Serialization.dll",
"ref/netcoreapp2.2/System.Runtime.dll",
"ref/netcoreapp2.2/System.Runtime.xml",
"ref/netcoreapp2.2/System.Security.Claims.dll",
"ref/netcoreapp2.2/System.Security.Claims.xml",
"ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.dll",
"ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.xml",
"ref/netcoreapp2.2/System.Security.Cryptography.Csp.dll",
"ref/netcoreapp2.2/System.Security.Cryptography.Csp.xml",
"ref/netcoreapp2.2/System.Security.Cryptography.Encoding.dll",
"ref/netcoreapp2.2/System.Security.Cryptography.Encoding.xml",
"ref/netcoreapp2.2/System.Security.Cryptography.Primitives.dll",
"ref/netcoreapp2.2/System.Security.Cryptography.Primitives.xml",
"ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.dll",
"ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.xml",
"ref/netcoreapp2.2/System.Security.Principal.dll",
"ref/netcoreapp2.2/System.Security.Principal.xml",
"ref/netcoreapp2.2/System.Security.SecureString.dll",
"ref/netcoreapp2.2/System.Security.dll",
"ref/netcoreapp2.2/System.ServiceModel.Web.dll",
"ref/netcoreapp2.2/System.ServiceProcess.dll",
"ref/netcoreapp2.2/System.Text.Encoding.Extensions.dll",
"ref/netcoreapp2.2/System.Text.Encoding.Extensions.xml",
"ref/netcoreapp2.2/System.Text.Encoding.dll",
"ref/netcoreapp2.2/System.Text.RegularExpressions.dll",
"ref/netcoreapp2.2/System.Text.RegularExpressions.xml",
"ref/netcoreapp2.2/System.Threading.Overlapped.dll",
"ref/netcoreapp2.2/System.Threading.Overlapped.xml",
"ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.dll",
"ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.xml",
"ref/netcoreapp2.2/System.Threading.Tasks.Extensions.dll",
"ref/netcoreapp2.2/System.Threading.Tasks.Extensions.xml",
"ref/netcoreapp2.2/System.Threading.Tasks.Parallel.dll",
"ref/netcoreapp2.2/System.Threading.Tasks.Parallel.xml",
"ref/netcoreapp2.2/System.Threading.Tasks.dll",
"ref/netcoreapp2.2/System.Threading.Tasks.xml",
"ref/netcoreapp2.2/System.Threading.Thread.dll",
"ref/netcoreapp2.2/System.Threading.Thread.xml",
"ref/netcoreapp2.2/System.Threading.ThreadPool.dll",
"ref/netcoreapp2.2/System.Threading.ThreadPool.xml",
"ref/netcoreapp2.2/System.Threading.Timer.dll",
"ref/netcoreapp2.2/System.Threading.Timer.xml",
"ref/netcoreapp2.2/System.Threading.dll",
"ref/netcoreapp2.2/System.Threading.xml",
"ref/netcoreapp2.2/System.Transactions.Local.dll",
"ref/netcoreapp2.2/System.Transactions.Local.xml",
"ref/netcoreapp2.2/System.Transactions.dll",
"ref/netcoreapp2.2/System.ValueTuple.dll",
"ref/netcoreapp2.2/System.Web.HttpUtility.dll",
"ref/netcoreapp2.2/System.Web.HttpUtility.xml",
"ref/netcoreapp2.2/System.Web.dll",
"ref/netcoreapp2.2/System.Windows.dll",
"ref/netcoreapp2.2/System.Xml.Linq.dll",
"ref/netcoreapp2.2/System.Xml.ReaderWriter.dll",
"ref/netcoreapp2.2/System.Xml.ReaderWriter.xml",
"ref/netcoreapp2.2/System.Xml.Serialization.dll",
"ref/netcoreapp2.2/System.Xml.XDocument.dll",
"ref/netcoreapp2.2/System.Xml.XDocument.xml",
"ref/netcoreapp2.2/System.Xml.XPath.XDocument.dll",
"ref/netcoreapp2.2/System.Xml.XPath.XDocument.xml",
"ref/netcoreapp2.2/System.Xml.XPath.dll",
"ref/netcoreapp2.2/System.Xml.XPath.xml",
"ref/netcoreapp2.2/System.Xml.XmlDocument.dll",
"ref/netcoreapp2.2/System.Xml.XmlSerializer.dll",
"ref/netcoreapp2.2/System.Xml.XmlSerializer.xml",
"ref/netcoreapp2.2/System.Xml.dll",
"ref/netcoreapp2.2/System.dll",
"ref/netcoreapp2.2/WindowsBase.dll",
"ref/netcoreapp2.2/mscorlib.dll",
"ref/netcoreapp2.2/netstandard.dll",
"runtime.json"
]
},
"Microsoft.NETCore.DotNetAppHost/2.2.0": {
"sha512": "DrhaKInRKKvN6Ns2VNIlC7ZffLOp9THf8cO6X4fytPRJovJUbF49/zzx4WfgX9E44FMsw9hT8hrKiIqDSHvGvA==",
"type": "package",
"path": "microsoft.netcore.dotnetapphost/2.2.0",
"files": [
".nupkg.metadata",
".signature.p7s",
"LICENSE.TXT",
"THIRD-PARTY-NOTICES.TXT",
"microsoft.netcore.dotnetapphost.2.2.0.nupkg.sha512",
"microsoft.netcore.dotnetapphost.nuspec",
"runtime.json"
]
},
"Microsoft.NETCore.DotNetHostPolicy/2.2.0": {
"sha512": "FJie7IoPZFaPgNDxhZGmDBQP/Bs5vPdfca/G2Wf9gd6LIvMYkZcibtmJwB4tcf4KXkaOYfIOo4Cl9sEPMsSzkw==",
"type": "package",
"path": "microsoft.netcore.dotnethostpolicy/2.2.0",
"files": [
".nupkg.metadata",
".signature.p7s",
"LICENSE.TXT",
"THIRD-PARTY-NOTICES.TXT",
"microsoft.netcore.dotnethostpolicy.2.2.0.nupkg.sha512",
"microsoft.netcore.dotnethostpolicy.nuspec",
"runtime.json"
]
},
"Microsoft.NETCore.DotNetHostResolver/2.2.0": {
"sha512": "spDm3AJYmebthDNhzY17YLPtvbc+Y1lCLVeiIH1uLJ/hZaM+40pBiPefFR8J1u66Ndkqi8ipR2tEbqPnYnjRhw==",
"type": "package",
"path": "microsoft.netcore.dotnethostresolver/2.2.0",
"files": [
".nupkg.metadata",
".signature.p7s",
"LICENSE.TXT",
"THIRD-PARTY-NOTICES.TXT",
"microsoft.netcore.dotnethostresolver.2.2.0.nupkg.sha512",
"microsoft.netcore.dotnethostresolver.nuspec",
"runtime.json"
]
},
"Microsoft.NETCore.Platforms/2.2.0": {
"sha512": "T/J+XZo+YheFTJh8/4uoeJDdz5qOmOMkjg6/VL8mHJ9AnP8+fmV/kcbxeXsob0irRNiChf+V0ig1MCRLp/+Kog==",
"type": "package",
"path": "microsoft.netcore.platforms/2.2.0",
"files": [
".nupkg.metadata",
".signature.p7s",
"LICENSE.TXT",
"THIRD-PARTY-NOTICES.TXT",
"lib/netstandard1.0/_._",
"microsoft.netcore.platforms.2.2.0.nupkg.sha512",
"microsoft.netcore.platforms.nuspec",
"runtime.json",
"useSharedDesignerContext.txt",
"version.txt"
]
},
"Microsoft.NETCore.Targets/2.0.0": {
"sha512": "odP/tJj1z6GylFpNo7pMtbd/xQgTC3Ex2If63dRTL38bBNMwsBnJ+RceUIyHdRBC0oik/3NehYT+oECwBhIM3Q==",
"type": "package",
"path": "microsoft.netcore.targets/2.0.0",
"files": [
".nupkg.metadata",
"LICENSE.TXT",
"THIRD-PARTY-NOTICES.TXT",
"lib/netstandard1.0/_._",
"microsoft.netcore.targets.2.0.0.nupkg.sha512",
"microsoft.netcore.targets.nuspec",
"runtime.json",
"useSharedDesignerContext.txt",
"version.txt"
]
},
"NETStandard.Library/2.0.3": {
"sha512": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
"type": "package",
"path": "netstandard.library/2.0.3",
"files": [
".nupkg.metadata",
"LICENSE.TXT",
"THIRD-PARTY-NOTICES.TXT",
"build/netstandard2.0/NETStandard.Library.targets",
"build/netstandard2.0/ref/Microsoft.Win32.Primitives.dll",
"build/netstandard2.0/ref/System.AppContext.dll",
"build/netstandard2.0/ref/System.Collections.Concurrent.dll",
"build/netstandard2.0/ref/System.Collections.NonGeneric.dll",
"build/netstandard2.0/ref/System.Collections.Specialized.dll",
"build/netstandard2.0/ref/System.Collections.dll",
"build/netstandard2.0/ref/System.ComponentModel.Composition.dll",
"build/netstandard2.0/ref/System.ComponentModel.EventBasedAsync.dll",
"build/netstandard2.0/ref/System.ComponentModel.Primitives.dll",
"build/netstandard2.0/ref/System.ComponentModel.TypeConverter.dll",
"build/netstandard2.0/ref/System.ComponentModel.dll",
"build/netstandard2.0/ref/System.Console.dll",
"build/netstandard2.0/ref/System.Core.dll",
"build/netstandard2.0/ref/System.Data.Common.dll",
"build/netstandard2.0/ref/System.Data.dll",
"build/netstandard2.0/ref/System.Diagnostics.Contracts.dll",
"build/netstandard2.0/ref/System.Diagnostics.Debug.dll",
"build/netstandard2.0/ref/System.Diagnostics.FileVersionInfo.dll",
"build/netstandard2.0/ref/System.Diagnostics.Process.dll",
"build/netstandard2.0/ref/System.Diagnostics.StackTrace.dll",
"build/netstandard2.0/ref/System.Diagnostics.TextWriterTraceListener.dll",
"build/netstandard2.0/ref/System.Diagnostics.Tools.dll",
"build/netstandard2.0/ref/System.Diagnostics.TraceSource.dll",
"build/netstandard2.0/ref/System.Diagnostics.Tracing.dll",
"build/netstandard2.0/ref/System.Drawing.Primitives.dll",
"build/netstandard2.0/ref/System.Drawing.dll",
"build/netstandard2.0/ref/System.Dynamic.Runtime.dll",
"build/netstandard2.0/ref/System.Globalization.Calendars.dll",
"build/netstandard2.0/ref/System.Globalization.Extensions.dll",
"build/netstandard2.0/ref/System.Globalization.dll",
"build/netstandard2.0/ref/System.IO.Compression.FileSystem.dll",
"build/netstandard2.0/ref/System.IO.Compression.ZipFile.dll",
"build/netstandard2.0/ref/System.IO.Compression.dll",
"build/netstandard2.0/ref/System.IO.FileSystem.DriveInfo.dll",
"build/netstandard2.0/ref/System.IO.FileSystem.Primitives.dll",
"build/netstandard2.0/ref/System.IO.FileSystem.Watcher.dll",
"build/netstandard2.0/ref/System.IO.FileSystem.dll",
"build/netstandard2.0/ref/System.IO.IsolatedStorage.dll",
"build/netstandard2.0/ref/System.IO.MemoryMappedFiles.dll",
"build/netstandard2.0/ref/System.IO.Pipes.dll",
"build/netstandard2.0/ref/System.IO.UnmanagedMemoryStream.dll",
"build/netstandard2.0/ref/System.IO.dll",
"build/netstandard2.0/ref/System.Linq.Expressions.dll",
"build/netstandard2.0/ref/System.Linq.Parallel.dll",
"build/netstandard2.0/ref/System.Linq.Queryable.dll",
"build/netstandard2.0/ref/System.Linq.dll",
"build/netstandard2.0/ref/System.Net.Http.dll",
"build/netstandard2.0/ref/System.Net.NameResolution.dll",
"build/netstandard2.0/ref/System.Net.NetworkInformation.dll",
"build/netstandard2.0/ref/System.Net.Ping.dll",
"build/netstandard2.0/ref/System.Net.Primitives.dll",
"build/netstandard2.0/ref/System.Net.Requests.dll",
"build/netstandard2.0/ref/System.Net.Security.dll",
"build/netstandard2.0/ref/System.Net.Sockets.dll",
"build/netstandard2.0/ref/System.Net.WebHeaderCollection.dll",
"build/netstandard2.0/ref/System.Net.WebSockets.Client.dll",
"build/netstandard2.0/ref/System.Net.WebSockets.dll",
"build/netstandard2.0/ref/System.Net.dll",
"build/netstandard2.0/ref/System.Numerics.dll",
"build/netstandard2.0/ref/System.ObjectModel.dll",
"build/netstandard2.0/ref/System.Reflection.Extensions.dll",
"build/netstandard2.0/ref/System.Reflection.Primitives.dll",
"build/netstandard2.0/ref/System.Reflection.dll",
"build/netstandard2.0/ref/System.Resources.Reader.dll",
"build/netstandard2.0/ref/System.Resources.ResourceManager.dll",
"build/netstandard2.0/ref/System.Resources.Writer.dll",
"build/netstandard2.0/ref/System.Runtime.CompilerServices.VisualC.dll",
"build/netstandard2.0/ref/System.Runtime.Extensions.dll",
"build/netstandard2.0/ref/System.Runtime.Handles.dll",
"build/netstandard2.0/ref/System.Runtime.InteropServices.RuntimeInformation.dll",
"build/netstandard2.0/ref/System.Runtime.InteropServices.dll",
"build/netstandard2.0/ref/System.Runtime.Numerics.dll",
"build/netstandard2.0/ref/System.Runtime.Serialization.Formatters.dll",
"build/netstandard2.0/ref/System.Runtime.Serialization.Json.dll",
"build/netstandard2.0/ref/System.Runtime.Serialization.Primitives.dll",
"build/netstandard2.0/ref/System.Runtime.Serialization.Xml.dll",
"build/netstandard2.0/ref/System.Runtime.Serialization.dll",
"build/netstandard2.0/ref/System.Runtime.dll",
"build/netstandard2.0/ref/System.Security.Claims.dll",
"build/netstandard2.0/ref/System.Security.Cryptography.Algorithms.dll",
"build/netstandard2.0/ref/System.Security.Cryptography.Csp.dll",
"build/netstandard2.0/ref/System.Security.Cryptography.Encoding.dll",
"build/netstandard2.0/ref/System.Security.Cryptography.Primitives.dll",
"build/netstandard2.0/ref/System.Security.Cryptography.X509Certificates.dll",
"build/netstandard2.0/ref/System.Security.Principal.dll",
"build/netstandard2.0/ref/System.Security.SecureString.dll",
"build/netstandard2.0/ref/System.ServiceModel.Web.dll",
"build/netstandard2.0/ref/System.Text.Encoding.Extensions.dll",
"build/netstandard2.0/ref/System.Text.Encoding.dll",
"build/netstandard2.0/ref/System.Text.RegularExpressions.dll",
"build/netstandard2.0/ref/System.Threading.Overlapped.dll",
"build/netstandard2.0/ref/System.Threading.Tasks.Parallel.dll",
"build/netstandard2.0/ref/System.Threading.Tasks.dll",
"build/netstandard2.0/ref/System.Threading.Thread.dll",
"build/netstandard2.0/ref/System.Threading.ThreadPool.dll",
"build/netstandard2.0/ref/System.Threading.Timer.dll",
"build/netstandard2.0/ref/System.Threading.dll",
"build/netstandard2.0/ref/System.Transactions.dll",
"build/netstandard2.0/ref/System.ValueTuple.dll",
"build/netstandard2.0/ref/System.Web.dll",
"build/netstandard2.0/ref/System.Windows.dll",
"build/netstandard2.0/ref/System.Xml.Linq.dll",
"build/netstandard2.0/ref/System.Xml.ReaderWriter.dll",
"build/netstandard2.0/ref/System.Xml.Serialization.dll",
"build/netstandard2.0/ref/System.Xml.XDocument.dll",
"build/netstandard2.0/ref/System.Xml.XPath.XDocument.dll",
"build/netstandard2.0/ref/System.Xml.XPath.dll",
"build/netstandard2.0/ref/System.Xml.XmlDocument.dll",
"build/netstandard2.0/ref/System.Xml.XmlSerializer.dll",
"build/netstandard2.0/ref/System.Xml.dll",
"build/netstandard2.0/ref/System.dll",
"build/netstandard2.0/ref/mscorlib.dll",
"build/netstandard2.0/ref/netstandard.dll",
"build/netstandard2.0/ref/netstandard.xml",
"lib/netstandard1.0/_._",
"netstandard.library.2.0.3.nupkg.sha512",
"netstandard.library.nuspec"
]
}
},
"projectFileDependencyGroups": {
".NETCoreApp,Version=v2.2": [
"Microsoft.NETCore.App >= 2.2.0"
]
},
"packageFolders": {
"/Users/ben/.nuget/packages/": {},
"/usr/local/share/dotnet/sdk/NuGetFallbackFolder": {}
},
"project": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/csharp.csproj",
"projectName": "csharp",
"projectPath": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/csharp.csproj",
"packagesPath": "/Users/ben/.nuget/packages/",
"outputPath": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/obj/",
"projectStyle": "PackageReference",
"fallbackFolders": [
"/usr/local/share/dotnet/sdk/NuGetFallbackFolder"
],
"configFilePaths": [
"/Users/ben/.nuget/NuGet/NuGet.Config"
],
"originalTargetFrameworks": [
"netcoreapp2.2"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"netcoreapp2.2": {
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
}
},
"frameworks": {
"netcoreapp2.2": {
"dependencies": {
"Microsoft.NETCore.App": {
"suppressParent": "All",
"target": "Package",
"version": "[2.2.0, )",
"autoReferenced": true
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48"
],
"assetTargetFallback": true,
"warn": true,
"runtimeIdentifierGraphPath": "/usr/local/share/dotnet/sdk/3.1.402/RuntimeIdentifierGraph.json"
}
}
}
}

View file

@ -1,18 +1,4 @@
{ {
"adapters": {
"dlv-dap": {
"variables": {
"port": "${unusedLocalPort}"
},
"command": [
"$HOME/go/bin/dlv",
"dap",
"--listen",
"127.0.0.1:${port}"
],
"port": "${port}"
}
},
"configurations": { "configurations": {
"run": { "run": {
"adapter": "vscode-go", "adapter": "vscode-go",
@ -26,21 +12,6 @@
"env": { "GO111MODULE": "off" } "env": { "GO111MODULE": "off" }
} }
}, },
"run-dap": {
"adapter": "dlv-dap",
"configuration": {
"request": "launch",
"env": { "GO111MODULE": "off" },
"mode": "debug", // debug|test
"program": "${workspaceRoot}/hello-world.go"
// "args": [],
// "buildFlags": ...
// "stackTraceDepth": ...,
// "showGlobalVariables": true,
}
},
"run-exec": { "run-exec": {
// NOTE: To use this you _must_ disable optimistaion: // NOTE: To use this you _must_ disable optimistaion:
// go build -o hello_world -gcflags="all=-N -l" // go build -o hello_world -gcflags="all=-N -l"

View file

@ -1,29 +0,0 @@
{
"configurations": {
"run-cmd": {
"adapter": "vscode-go",
"configuration": {
"request": "launch",
"program": "${workspaceRoot}/cmd/namestartswithvowel/main.go",
"mode": "debug",
"dlvToolPath": "$HOME/go/bin/dlv",
"dlvLoadConfig": {
"maxArrayValues": 1000,
"maxStringLen": 1000
}
}
},
"test-current-file": {
"adapter": "vscode-go",
"configuration": {
"request": "launch",
"mode": "test",
"program": "${fileDirname}",
"cwd": "${fileDirname}",
"dlvToolPath": "$GOPATH/bin/dlv",
"env": {},
"args": []
}
}
}
}

View file

@ -1,33 +0,0 @@
# Purpose
This example comes with two example vimspector configs for the Go programming language.
1) `run-cmd` will launch the main programme under `cmd/namestartswithvowel`.
1) `test-current-file` will run the tests in the current file in debug mode.
## Example use-cases
### run-cmd
* Open `cmd/namestartswithvowel/main.go`
* Add a breakpoint somewhere within the programme
* Start the debugger (`:call vimspector#Continue()` or your relevant keymapping)
* Select the first launch configuration (`1: run-cmd`)
### test-current-file
* Open `internal/vowels/vowels_test.go`
* Add a breakpoint somewhere within the test
* Start the debugger (`:call vimspector#Continue()` or your relevant keymapping)
* Select the second launch configuration (`2: test-current-file`)
## Additional Configuration
There are two additional configuration options specified under `run-cmd`; these parameters configure the maximum string/array size to be shown while debugging.
```
"dlvLoadConfig": {
"maxArrayValues": 1000,
"maxStringLen": 1000
}
```

View file

@ -1,20 +0,0 @@
package main
import (
"fmt"
"example.com/internal/vowels"
)
func main() {
names := []string{"Simon", "Bob", "Jennifer", "Amy", "Duke", "Elizabeth"}
for _, n := range names {
if vowels.NameStartsWithVowel(n) {
fmt.Printf("%s starts with a vowel!\n", n)
continue
}
fmt.Printf("%s does not start with a vowel!\n", n)
}
}

View file

@ -1,3 +0,0 @@
module example.com
go 1.16

View file

@ -1,9 +0,0 @@
package vowels
import "strings"
func NameStartsWithVowel(name string) bool {
s := strings.Split(strings.ToLower(name), "")
return s[0] == "a" || s[0] == "e" || s[0] == "i" || s[0] == "o" || s[0] == "u"
}

View file

@ -1,30 +0,0 @@
package vowels
import (
"fmt"
"testing"
)
func TestNameStartsWithVowel(t *testing.T) {
testCases := []struct {
input string
expectedOutput bool
}{
{
input: "Simon",
expectedOutput: false,
},
{
input: "Andy",
expectedOutput: true,
},
}
for _, tt := range testCases {
t.Run(fmt.Sprintf("%s should product %t", tt.input, tt.expectedOutput), func(t *testing.T) {
out := NameStartsWithVowel(tt.input)
if out != tt.expectedOutput {
t.Errorf("%s produced %t, when %t was expected", tt.input, out, tt.expectedOutput)
}
})
}
}

View file

@ -4,7 +4,7 @@
<artifactId>TestApplication</artifactId> <artifactId>TestApplication</artifactId>
<version>1</version> <version>1</version>
<properties> <properties>
<maven.compiler.source>11</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>
</properties> </properties>
</project> </project>

View file

@ -1,2 +0,0 @@
.gradle
build

View file

@ -1,21 +0,0 @@
{
"configurations": {
"kotlin-debug-adapter launch": {
"adapter": "cust_kotlin-debug-adapter",
"configuration": {
"request": "launch",
"projectRoot": "${workspaceFolder}",
"mainClass": "vimspector/test/ApplicationKt"
}
},
"kotlin-debug-adapter attach": {
"adapter": "cust_kotlin-debug-adapter",
"configuration": {
"request": "attach",
"projectRoot": "${workspaceFolder}",
"hostName": "${hostName}",
"port": "${port}"
}
}
}
}

View file

@ -1,25 +0,0 @@
plugins {
kotlin("jvm") version "1.4.0"
application
}
repositories {
// Use jcenter for resolving dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
dependencies {
// Align versions of all Kotlin components
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
// Use the Kotlin JDK 8 standard library.
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}
application {
// Define the main class for the application.
mainClassName = "vimspector.test.ApplicationKt"
}

View file

@ -1 +0,0 @@
rootProject.name = "vimspector-test"

View file

@ -1,5 +0,0 @@
package vimspector.test
fun main(args: Array<String>) {
println("Hello World!")
}

View file

@ -7,41 +7,6 @@
"env": { "env": {
"DEBUG_PORT": "9876" "DEBUG_PORT": "9876"
} }
},
"python-remote-docker": {
"variables": {
"port": "8765"
},
"port": "${port}",
"launch": {
"remote": {
"container": "${ContainerID}",
"runCommand": [
"python3", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
"--wait-for-client",
"%CMD%"
]
},
"delay": "5000m"
}
},
"python-remote-ssh": {
"variables": {
"port": "8765"
},
"port": "${port}",
"host": "${host}",
"launch": {
"remote": {
"host": "${host}",
"account": "${account}",
"runCommand": [
"python3", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
"--wait-for-client",
"%CMD%"
]
}
}
} }
}, },
"configurations": { "configurations": {
@ -96,20 +61,6 @@
} }
} }
}, },
"docker-attach": {
"adapter": "python-remote-docker",
"remote-cmdLine": [ "/root/main.py" ],
"remote-request": "launch",
"configuration": {
"request": "attach",
"pathMappings": [
{
"localRoot": "${workspaceRoot}",
"remoteRoot": "/root"
}
]
}
},
"run": { "run": {
"adapter": "debugpy", "adapter": "debugpy",
"configuration": { "configuration": {
@ -182,23 +133,6 @@
"stopOnEntry": false, "stopOnEntry": false,
"console": "integratedTerminal" "console": "integratedTerminal"
} }
},
"run - remote host": {
"adapter": "python-remote-ssh",
"remote-cmdLine": [
"${remoteRoot}/main.py"
],
"remote-request": "launch",
"configuration": {
"request": "attach",
"redirectOutput": true,
"pathMappings": [
{
"localRoot": "${workspaceRoot}",
"remoteRoot": "${remoteRoot}"
}
]
}
} }
} }
} }

View file

@ -1,22 +0,0 @@
FROM ubuntu:18.04
RUN apt-get update && \
apt-get -y dist-upgrade && \
apt-get -y install sudo \
lsb-release \
ca-certificates \
python3-dev \
python3-pip \
ca-cacert \
locales \
language-pack-en \
libncurses5-dev libncursesw5-dev \
git && \
apt-get -y autoremove
## cleanup of files from setup
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN pip3 install debugpy
ADD main.py /root/main.py

View file

@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -e
if [ "$1" = "--continue" ]; then
OPTS=""
else
OPTS="--no-cache"
fi
docker build ${OPTS} -t puremourning/vimspector:simple_python .

View file

@ -3,8 +3,6 @@
set SCALAR g set SCALAR g
array set ARRAY {key1 value1 key2 value2} array set ARRAY {key1 value1 key2 value2}
set LIST [list a b c {def} {g h i j} k l m]
proc Wrap { body } { proc Wrap { body } {
uplevel 1 $body uplevel 1 $body
} }

View file

@ -280,8 +280,8 @@ function! Test_Conditional_Line_Breakpoint()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 ) call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 )
" Add the conditional breakpoint (note , is the mapleader) " Add the conditional breakpoint
call feedkeys( ",\<F9>argc==0\<CR>\<CR>", 'xt' ) call feedkeys( "\\\<F9>argc==0\<CR>\<CR>", 'xt' )
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
\ 16, \ 16,
\ 'vimspectorBPCond', \ 'vimspectorBPCond',
@ -360,8 +360,8 @@ function! Test_Conditional_Line_Breakpoint_Hit()
exe 'edit' fn exe 'edit' fn
call setpos( '.', [ 0, 14, 1 ] ) call setpos( '.', [ 0, 14, 1 ] )
" Add the conditional breakpoint (3 times) (note , is the mapleader) " Add the conditional breakpoint (3 times)
call feedkeys( ",\<F9>\<CR>3\<CR>", 'xt' ) call feedkeys( "\\\<F9>\<CR>3\<CR>", 'xt' )
call vimspector#test#signs#AssertSignGroupSingletonAtLine( call vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorBP', \ 'VimspectorBP',
\ 14, \ 14,

View file

@ -293,8 +293,8 @@ function! Test_Conditional_Line_Breakpoint()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 ) call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 )
" Add the conditional breakpoint (, is mapleader) " Add the conditional breakpoint
call feedkeys( ",\<F9>argc==0\<CR>\<CR>", 'xt' ) call feedkeys( "\\\<F9>argc==0\<CR>\<CR>", 'xt' )
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP', call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
\ 16, \ 16,
\ 'vimspectorBPCond', \ 'vimspectorBPCond',
@ -370,8 +370,8 @@ function! Test_Conditional_Line_Breakpoint_Hit()
exe 'edit' fn exe 'edit' fn
call setpos( '.', [ 0, 14, 1 ] ) call setpos( '.', [ 0, 14, 1 ] )
" Add the conditional breakpoint (3 times) (, is mapleader) " Add the conditional breakpoint (3 times)
call feedkeys( ",\<F9>\<CR>3\<CR>", 'xt' ) call feedkeys( "\\\<F9>\<CR>3\<CR>", 'xt' )
call vimspector#test#signs#AssertSignGroupSingletonAtLine( call vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorBP', \ 'VimspectorBP',
\ 14, \ 14,

View file

@ -70,12 +70,6 @@ RUN mkdir -p /home/linuxbrew/.linuxbrew &&\
RUN /home/linuxbrew/.linuxbrew/bin/brew install golang RUN /home/linuxbrew/.linuxbrew/bin/brew install golang
# dotnet
RUN curl -sSL https://dot.net/v1/dotnet-install.sh \
| bash /dev/stdin --channel LTS --install-dir /usr/share/dotnet && \
update-alternatives --install /usr/bin/dotnet dotnet \
/usr/share/dotnet/dotnet 1
# clean up # clean up
RUN /home/linuxbrew/.linuxbrew/bin/brew cleanup && \ RUN /home/linuxbrew/.linuxbrew/bin/brew cleanup && \
rm -rf ~/.cache && \ rm -rf ~/.cache && \

View file

@ -12,7 +12,6 @@ function Test_Get_Configurations()
let configs = vimspector#GetConfigurations() let configs = vimspector#GetConfigurations()
call assert_equal([ call assert_equal([
\ 'launch - netcoredbg', \ 'launch - netcoredbg',
\ 'launch - netcoredbg - with debug log',
\ 'launch - mono', \ 'launch - mono',
\ ], configs) \ ], configs)

View file

@ -1,65 +0,0 @@
function! SetUp()
call vimspector#test#setup#SetUpWithMappings( v:none )
endfunction
function! ClearDown()
call vimspector#test#setup#ClearDown()
endfunction
function! SetUp_Test_Go_Simple()
let g:vimspector_enable_mappings = 'HUMAN'
endfunction
function! Test_CSharp_Simple()
let fn='Program.cs'
lcd ../support/test/csharp
exe 'edit ' . fn
call vimspector#SetLineBreakpoint( fn, 31 )
call vimspector#LaunchWithSettings( {
\ 'configuration': 'launch - netcoredbg'
\ } )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 31, 7 )
call WaitForAssert( {->
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 31 )
\ } )
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 32, 12 )
call WaitForAssert( {->
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 32 )
\ } )
call vimspector#test#setup#Reset()
lcd -
%bwipeout!
endfunction
function! Test_Run_To_Cursor()
let fn='Program.cs'
lcd ../support/test/csharp
exe 'edit ' . fn
call vimspector#SetLineBreakpoint( fn, 31 )
call vimspector#LaunchWithSettings( {
\ 'configuration': 'launch - netcoredbg'
\ } )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 31, 7 )
call WaitForAssert( {->
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 31 )
\ } )
call cursor( 33, 1 )
call vimspector#RunToCursor()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 33, 1 )
call WaitForAssert( {->
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 33 )
\ } )
call vimspector#test#setup#Reset()
lcd -
%bwipeout!
endfunction

View file

@ -50,59 +50,3 @@ function! vimspector#test#setup#Reset() abort
call popup_clear() call popup_clear()
endfunction endfunction
let s:g_stack = {}
function! vimspector#test#setup#PushGlobal( name, value ) abort
if !has_key( s:g_stack, a:name )
let s:g_stack[ a:name ] = []
endif
let old_value = get( g:, a:name, v:null )
call add( s:g_stack[ a:name ], old_value )
let g:[ a:name ] = a:value
return old_value
endfunction
function! vimspector#test#setup#PopGlobal( name ) abort
if !has_key( s:g_stack, a:name ) || len( s:g_stack[ a:name ] ) == 0
return v:null
endif
let old_value = s:g_stack[ a:name ][ -1 ]
call remove( s:g_stack[ a:name ], -1 )
if old_value is v:null
silent! call remove( g:, a:name )
else
let g:[ a:name ] = old_value
endif
return old_value
endfunction
let s:o_stack = {}
function! vimspector#test#setup#PushOption( name, value ) abort
if !has_key( s:o_stack, a:name )
let s:o_stack[ a:name ] = []
endif
let old_value = v:null
execute 'let old_value = &' . a:name
call add( s:o_stack[ a:name ], old_value )
execute 'set ' . a:name . '=' . a:value
return old_value
endfunction
function! vimspector#test#setup#PopOption( name ) abort
if !has_key( s:o_stack, a:name ) || len( s:o_stack[ a:name ] ) == 0
return v:null
endif
let old_value = s:o_stack[ a:name ][ -1 ]
call remove( s:o_stack[ a:name ], -1 )
execute 'set ' . a:name . '=' . old_value
return old_value
endfunction

View file

@ -99,7 +99,7 @@ function! ThisTestIsFlaky()
let g:test_is_flaky = v:true let g:test_is_flaky = v:true
endfunction endfunction
function! AssertMatchList( expected, actual ) abort function! AssertMatchist( expected, actual ) abort
let ret = assert_equal( len( a:expected ), len( a:actual ) ) let ret = assert_equal( len( a:expected ), len( a:actual ) )
let len = min( [ len( a:expected ), len( a:actual ) ] ) let len = min( [ len( a:expected ), len( a:actual ) ] )
let idx = 0 let idx = 0

View file

@ -82,16 +82,6 @@ func! Abort( timer_id )
qa! qa!
endfunc endfunc
func! TestLog( msg )
if type( a:msg ) == v:t_string
let msg = [ a:msg ]
else
let msg = a:msg
endif
call extend( s:messages, msg )
endfunc
func RunTheTest(test) func RunTheTest(test)
echo 'Executing ' . a:test echo 'Executing ' . a:test
@ -162,6 +152,8 @@ func RunTheTest(test)
augroup END augroup END
exe 'call ' . a:test exe 'call ' . a:test
au! EarlyExit
catch /^\cskipped/ catch /^\cskipped/
call add(s:messages, ' Skipped') call add(s:messages, ' Skipped')
call add(s:skipped, call add(s:skipped,
@ -201,8 +193,6 @@ func RunTheTest(test)
call s:TestFailed() call s:TestFailed()
endtry endtry
au! EarlyExit
call timer_stop( timer ) call timer_stop( timer )
" In case 'insertmode' was set and something went wrong, make sure it is " In case 'insertmode' was set and something went wrong, make sure it is

View file

@ -106,34 +106,14 @@ function! Test_Use_Mappings_HUMAN()
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 16 ) \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 16 )
\ } ) \ } )
" Run to cursor (note , is the mapleader) " Run to cursor
call cursor( 9, 1 ) call cursor( 9, 1 )
call feedkeys( ",\<F8>", 'xt' ) call feedkeys( "\\\<F8>", 'xt' )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 9, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 9, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 9 ) \ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 9 )
\ } ) \ } )
" Stop
call feedkeys( "\<F3>", 'xt' )
call WaitForAssert( {->
\ assert_equal( [],
\ getbufline( g:vimspector_session_windows.variables,
\ 1,
\ '$' ) )
\ } )
call WaitForAssert( {->
\ assert_equal( [],
\ getbufline( g:vimspector_session_windows.stack_trace,
\ 1,
\ '$' ) )
\ } )
call WaitForAssert( {->
\ assert_equal( [],
\ getbufline( g:vimspector_session_windows.watches,
\ 1,
\ '$' ) )
\ } )
call vimspector#test#setup#Reset() call vimspector#test#setup#Reset()

View file

@ -1,89 +0,0 @@
import sys
import unittest
from unittest.mock import patch
from vimspector import utils
class TestExpandReferencesInDict( unittest.TestCase ):
def __init__( self, *args, **kwargs ):
super().__init__( *args, **kwargs )
self.maxDiff = 4096
def test_ExpandReferencesInDict( self ):
mapping = {
'one': 'one',
'two': 'TWO',
'bool': True,
'words': 'these are some words'
}
calculus = {
'three': lambda : 1 + 2,
}
CHOICES = {
'five': '5ive!'
}
def AskForInput( prompt, default_value = None ):
if default_value is not None:
return default_value
return 'typed text'
d = {
'dollar': '$$',
'not_a_var': '$${test}',
'one': '${one}',
'two': '${one} and ${two}',
'three': '${three}',
'three_with_default': '${three_with_default:${three\\}}', # uses calculus
'four': '${four}',
'five': '${five}',
'list': [ '*${words}' ],
'list1': [ 'start', '*${words}', 'end' ],
'list2': [ '*${words}', '${three}' ],
'list3': [ '${one}', '*${words}', 'three' ],
'dict#json': '{ "key": "value" }',
'bool#json': 'false',
'one_default': '${one_default:one}',
'two_default': '${two_default_1:one} and ${two_default_2:two}',
'one_default2': '${one_default2:${one\\}}',
'two_default2':
'${two_default2_1:${one\\}} and ${two_default2_2:${two\\}}',
'unlikely_name#json#s': 'true',
'empty_splice': [ '*${empty:}' ],
}
e = {
'dollar': '$',
'not_a_var': '${test}',
'one': 'one',
'two': 'one and TWO',
'three': '3',
'three_with_default': '3',
'four': 'typed text',
'five': '5ive!',
'list': [ 'these', 'are', 'some', 'words' ],
'list1': [ 'start', 'these', 'are', 'some', 'words', 'end' ],
'list2': [ 'these', 'are', 'some', 'words', '3' ],
'list3': [ 'one', 'these', 'are', 'some', 'words', 'three' ],
'dict': {
'key': 'value',
},
'bool': False,
'one_default': 'one',
'two_default': 'one and two',
'one_default2': 'one',
'two_default2': 'one and TWO',
'unlikely_name#json': 'true',
'empty_splice': [],
}
with patch( 'vimspector.utils.AskForInput', side_effect = AskForInput ):
utils.ExpandReferencesInDict( d, mapping, calculus, CHOICES )
self.assertDictEqual( d, e )
assert unittest.main( module=__name__,
testRunner=unittest.TextTestRunner( sys.stdout ),
exit=False ).result.wasSuccessful()

View file

@ -30,7 +30,7 @@ function! Test_Multiple_Threads_Continue()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 )
call cursor( 1, 1 ) call cursor( 1, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '- Thread [0-9]\+: .* (paused)', \ '- Thread [0-9]\+: .* (paused)',
\ ' .*: .*@threads.cpp:' . string( thread_l ) \ ' .*: .*@threads.cpp:' . string( thread_l )
@ -45,7 +45,7 @@ function! Test_Multiple_Threads_Continue()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 )
call cursor( 1, 1 ) call cursor( 1, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '- Thread [0-9]\+: .* (paused)', \ '- Thread [0-9]\+: .* (paused)',
\ ' .*: .*@threads.cpp:' . string( thread_l ) \ ' .*: .*@threads.cpp:' . string( thread_l )
@ -56,7 +56,7 @@ function! Test_Multiple_Threads_Continue()
\ ) \ )
\ } ) \ } )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ ], \ ],
@ -70,7 +70,7 @@ function! Test_Multiple_Threads_Continue()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 )
call cursor( 1, 1 ) call cursor( 1, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '- Thread [0-9]\+: .* (paused)', \ '- Thread [0-9]\+: .* (paused)',
\ ' .*: .*@threads.cpp:' . string( thread_l ) \ ' .*: .*@threads.cpp:' . string( thread_l )
@ -81,7 +81,7 @@ function! Test_Multiple_Threads_Continue()
\ ) \ )
\ } ) \ } )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ ], \ ],
@ -95,7 +95,7 @@ function! Test_Multiple_Threads_Continue()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 )
call cursor( 1, 1 ) call cursor( 1, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '- Thread [0-9]\+: .* (paused)', \ '- Thread [0-9]\+: .* (paused)',
\ ' .*: .*@threads.cpp:' . string( thread_l ) \ ' .*: .*@threads.cpp:' . string( thread_l )
@ -106,7 +106,7 @@ function! Test_Multiple_Threads_Continue()
\ ) \ )
\ } ) \ } )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ ], \ ],
@ -121,7 +121,7 @@ function! Test_Multiple_Threads_Continue()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 )
call cursor( 1, 1 ) call cursor( 1, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '- Thread [0-9]\+: .* (paused)', \ '- Thread [0-9]\+: .* (paused)',
\ ' .*: .*@threads.cpp:' . string( thread_l ) \ ' .*: .*@threads.cpp:' . string( thread_l )
@ -132,7 +132,7 @@ function! Test_Multiple_Threads_Continue()
\ ) \ )
\ } ) \ } )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ ], \ ],
@ -146,7 +146,7 @@ function! Test_Multiple_Threads_Continue()
" So we break out of the loop " So we break out of the loop
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, notify_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, notify_l, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '- Thread [0-9]\+: .* (paused)', \ '- Thread [0-9]\+: .* (paused)',
\ ' .*: .*@threads.cpp:' . string( notify_l ) \ ' .*: .*@threads.cpp:' . string( notify_l )
@ -157,7 +157,7 @@ function! Test_Multiple_Threads_Continue()
\ ) \ )
\ } ) \ } )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ ], \ ],
@ -192,7 +192,7 @@ function! Test_Multiple_Threads_Step()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '- Thread [0-9]\+: .* (paused)', \ '- Thread [0-9]\+: .* (paused)',
\ ' .*: .*@threads.cpp:' . string( thread_l ) \ ' .*: .*@threads.cpp:' . string( thread_l )
@ -205,7 +205,7 @@ function! Test_Multiple_Threads_Step()
call vimspector#StepOver() call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ ], \ ],
@ -218,7 +218,7 @@ function! Test_Multiple_Threads_Step()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ ], \ ],
@ -230,7 +230,7 @@ function! Test_Multiple_Threads_Step()
call vimspector#StepOver() call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
@ -244,7 +244,7 @@ function! Test_Multiple_Threads_Step()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
@ -257,7 +257,7 @@ function! Test_Multiple_Threads_Step()
call vimspector#StepOver() call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
@ -273,7 +273,7 @@ function! Test_Multiple_Threads_Step()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
@ -287,7 +287,7 @@ function! Test_Multiple_Threads_Step()
call vimspector#StepOver() call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
@ -304,7 +304,7 @@ function! Test_Multiple_Threads_Step()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
@ -319,7 +319,7 @@ function! Test_Multiple_Threads_Step()
call vimspector#StepOver() call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
@ -338,7 +338,7 @@ function! Test_Multiple_Threads_Step()
" So we break out of the loop " So we break out of the loop
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, notify_l, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, notify_l, 1 )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
\ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)',
@ -352,209 +352,6 @@ function! Test_Multiple_Threads_Step()
\ ) \ )
\ } ) \ } )
call vimspector#ClearBreakpoints()
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! Test_UpDownStack()
let fn='../support/test/python/simple_python/main.py'
exe 'edit ' . fn
call setpos( '.', [ 0, 6, 1 ] )
call vimspector#SetLineBreakpoint( fn, 15 )
call vimspector#LaunchWithSettings( { 'configuration': 'run' } )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '- Thread 1: MainThread (paused)',
\ ' 2: DoSomething@main.py:15',
\ ' 3: __init__@main.py:8',
\ ' 4: Main@main.py:23',
\ ' 5: <module>@main.py:29',
\ ],
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
\ 1,
\ '$' )
\ )
\ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 2,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call vimspector#DownFrame()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '- Thread 1: MainThread (paused)',
\ ' 2: DoSomething@main.py:15',
\ ' 3: __init__@main.py:8',
\ ' 4: Main@main.py:23',
\ ' 5: <module>@main.py:29',
\ ],
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
\ 1,
\ '$' )
\ )
\ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 2,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call vimspector#UpFrame()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '- Thread 1: MainThread (paused)',
\ ' 2: DoSomething@main.py:15',
\ ' 3: __init__@main.py:8',
\ ' 4: Main@main.py:23',
\ ' 5: <module>@main.py:29',
\ ],
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
\ 1,
\ '$' )
\ )
\ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 3,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call feedkeys( "\<Plug>VimspectorUpFrame", 'x' )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 23, 1 )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '- Thread 1: MainThread (paused)',
\ ' 2: DoSomething@main.py:15',
\ ' 3: __init__@main.py:8',
\ ' 4: Main@main.py:23',
\ ' 5: <module>@main.py:29',
\ ],
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
\ 1,
\ '$' )
\ )
\ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 4,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call feedkeys( "\<Plug>VimspectorDownFrame", 'x' )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '- Thread 1: MainThread (paused)',
\ ' 2: DoSomething@main.py:15',
\ ' 3: __init__@main.py:8',
\ ' 4: Main@main.py:23',
\ ' 5: <module>@main.py:29',
\ ],
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
\ 1,
\ '$' )
\ )
\ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 3,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call vimspector#DownFrame()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '- Thread 1: MainThread (paused)',
\ ' 2: DoSomething@main.py:15',
\ ' 3: __init__@main.py:8',
\ ' 4: Main@main.py:23',
\ ' 5: <module>@main.py:29',
\ ],
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
\ 1,
\ '$' )
\ )
\ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 2,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call vimspector#ClearBreakpoints() call vimspector#ClearBreakpoints()
call vimspector#test#setup#Reset() call vimspector#test#setup#Reset()
%bwipe! %bwipe!

View file

@ -12,7 +12,7 @@
"externalConsole": false, "externalConsole": false,
"stopAtEntry": true, "stopAtEntry": true,
"stopOnEntry": true, "stopOnEntry": true,
"MIMode": "${VIMSPECTOR_MIMODE}" "MImode": "${VIMSPECTOR_MIMODE}"
}, },
"breakpoints": { "breakpoints": {
"exception": { "exception": {
@ -33,7 +33,7 @@
"externalConsole": false, "externalConsole": false,
"stopAtEntry": false, "stopAtEntry": false,
"stopOnEntry": false, "stopOnEntry": false,
"MIMode": "${VIMSPECTOR_MIMODE}" "MImode": "${VIMSPECTOR_MIMODE}"
}, },
"breakpoints": { "breakpoints": {
"exception": { "exception": {
@ -55,7 +55,7 @@
"externalConsole": false, "externalConsole": false,
"stopAtEntry": false, "stopAtEntry": false,
"stopOnEntry": false, "stopOnEntry": false,
"MIMode": "${VIMSPECTOR_MIMODE}" "MImode": "${VIMSPECTOR_MIMODE}"
}, },
"breakpoints": { "breakpoints": {
"exception": { "exception": {
@ -82,7 +82,7 @@
"configuration": { "configuration": {
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/${fileBasenameNoExtension}", "program": "${workspaceRoot}/${fileBasenameNoExtension}",
"MIMode": "${VIMSPECTOR_MIMODE}", "MImode": "${VIMSPECTOR_MIMODE}",
"externalConsole": false, "externalConsole": false,
"args": [ "args": [
"CALCULATED_LIST", "${CALCULATED_LIST}", "CALCULATED_LIST", "${CALCULATED_LIST}",

View file

@ -1,7 +1,6 @@
let s:fn='../support/test/python/simple_python/main.py' let s:fn='../support/test/python/simple_python/main.py'
function! SetUp() function! SetUp()
let g:vimspector_ui_mode = get( s:, 'vimspector_ui_mode', 'horizontal' )
call vimspector#test#setup#SetUpWithMappings( 'HUMAN' ) call vimspector#test#setup#SetUpWithMappings( 'HUMAN' )
endfunction endfunction
@ -17,17 +16,12 @@ function! s:StartDebugging()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 23, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 23, 1 )
endfunction endfunction
function! SetUp_Test_StandardLayout()
call vimspector#test#setup#PushOption( 'columns', 200 )
endfunction
function! Test_StandardLayout() function! Test_StandardLayout()
call s:StartDebugging() call s:StartDebugging()
call vimspector#StepOver() call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 )
call assert_equal( 'horizontal', g:vimspector_session_windows.mode )
call assert_equal( call assert_equal(
\ [ 'row', [ \ [ 'row', [
\ [ 'col', [ \ [ 'col', [
@ -49,247 +43,6 @@ function! Test_StandardLayout()
%bwipe! %bwipe!
endfunction endfunction
function! TearDown_Test_StandardLayout()
call vimspector#test#setup#PopOption( 'columns' )
endfunction
function! SetUp_Test_NarrowLayout()
call vimspector#test#setup#PushOption( 'columns', 100 )
let s:vimspector_ui_mode = 'vertical'
endfunction
function! Test_NarrowLayout()
call s:StartDebugging()
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 )
call assert_equal( 'vertical', g:vimspector_session_windows.mode )
call assert_equal(
\ [ 'col', [
\ [ 'row', [
\ [ 'leaf', g:vimspector_session_windows.variables ],
\ [ 'leaf', g:vimspector_session_windows.watches ],
\ [ 'leaf', g:vimspector_session_windows.stack_trace ],
\ ] ],
\ [ 'leaf', g:vimspector_session_windows.code ],
\ [ 'leaf', g:vimspector_session_windows.terminal ],
\ [ 'leaf', g:vimspector_session_windows.output ],
\ ] ],
\ winlayout( g:vimspector_session_windows.tabpage ) )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! TearDown_Test_NarrowLayout()
unlet s:vimspector_ui_mode
call vimspector#test#setup#PopOption( 'columns' )
endfunction
function! SetUp_Test_AutoLayoutTerminalVert()
let s:vimspector_ui_mode = 'auto'
call vimspector#test#setup#PushOption( 'columns', 250 )
call vimspector#test#setup#PushOption( 'lines', 30 )
endfunction
function! Test_AutoLayoutTerminalVert()
call s:StartDebugging()
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 )
call assert_equal( 'horizontal', g:vimspector_session_windows.mode )
call assert_equal(
\ [ 'row', [
\ [ 'col', [
\ [ 'leaf', g:vimspector_session_windows.variables ],
\ [ 'leaf', g:vimspector_session_windows.watches ],
\ [ 'leaf', g:vimspector_session_windows.stack_trace ],
\ ] ],
\ [ 'col', [
\ [ 'row', [
\ [ 'leaf', g:vimspector_session_windows.code ],
\ [ 'leaf', g:vimspector_session_windows.terminal ],
\ ] ],
\ [ 'leaf', g:vimspector_session_windows.output ],
\ ] ]
\ ] ],
\ winlayout( g:vimspector_session_windows.tabpage ) )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! TearDown_Test_AutoLayoutTerminalVert()
unlet s:vimspector_ui_mode
call vimspector#test#setup#PopOption( 'lines' )
call vimspector#test#setup#PopOption( 'columns' )
endfunction
function! SetUp_Test_AutoLayoutTerminalHorizVert()
let s:vimspector_ui_mode = 'auto'
" Wide enough to be horizontal layout, but not wide enough to fully fit the
" terminal, with enough rows to fit the max terminal below
call vimspector#test#setup#PushOption( 'columns',
\ 50 + 82 + 3 + 2 + 12 )
call vimspector#test#setup#PushOption( 'lines', 50 )
endfunction
function! Test_AutoLayoutTerminalHorizVert()
call s:StartDebugging()
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 )
call assert_equal( 'horizontal', g:vimspector_session_windows.mode )
call assert_equal(
\ [ 'row', [
\ [ 'col', [
\ [ 'leaf', g:vimspector_session_windows.variables ],
\ [ 'leaf', g:vimspector_session_windows.watches ],
\ [ 'leaf', g:vimspector_session_windows.stack_trace ],
\ ] ],
\ [ 'col', [
\ [ 'leaf', g:vimspector_session_windows.code ],
\ [ 'leaf', g:vimspector_session_windows.terminal ],
\ [ 'leaf', g:vimspector_session_windows.output ],
\ ] ]
\ ] ],
\ winlayout( g:vimspector_session_windows.tabpage ) )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! TearDown_Test_AutoLayoutTerminalHorizVert()
unlet s:vimspector_ui_mode
call vimspector#test#setup#PopOption( 'lines' )
call vimspector#test#setup#PopOption( 'columns' )
endfunction
function! SetUp_Test_AutoLayoutTerminalHorizVertButNotEnoughLines()
let s:vimspector_ui_mode = 'auto'
" Wide enough to be horizontal layout, but not wide enough to fully fit the
" terminal, with enough rows to fit the max terminal below, but there are not
" enough lines to do this
call vimspector#test#setup#PushOption( 'columns',
\ 50 + 82 + 3 + 2 + 12 )
call vimspector#test#setup#PushOption( 'lines', 20 )
endfunction
function! Test_AutoLayoutTerminalHorizVertButNotEnoughLines()
call s:StartDebugging()
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 )
call assert_equal( 'horizontal', g:vimspector_session_windows.mode )
call assert_equal(
\ [ 'row', [
\ [ 'col', [
\ [ 'leaf', g:vimspector_session_windows.variables ],
\ [ 'leaf', g:vimspector_session_windows.watches ],
\ [ 'leaf', g:vimspector_session_windows.stack_trace ],
\ ] ],
\ [ 'col', [
\ [ 'row', [
\ [ 'leaf', g:vimspector_session_windows.code ],
\ [ 'leaf', g:vimspector_session_windows.terminal ],
\ ] ],
\ [ 'leaf', g:vimspector_session_windows.output ],
\ ] ],
\ ] ],
\ winlayout( g:vimspector_session_windows.tabpage ) )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! TearDown_Test_AutoLayoutTerminalHorizVertButNotEnoughLines()
unlet s:vimspector_ui_mode
call vimspector#test#setup#PopOption( 'lines' )
call vimspector#test#setup#PopOption( 'columns' )
endfunction
function! SetUp_Test_AutoLayoutTerminalHoriz()
let s:vimspector_ui_mode = 'vertical'
" Vertical layout, but we split the terminal horizonally
call vimspector#test#setup#PushOption( 'columns', 200 )
call vimspector#test#setup#PushOption( 'lines', 50 )
endfunction
function! Test_AutoLayoutTerminalHoriz()
call s:StartDebugging()
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 )
call assert_equal( 'vertical', g:vimspector_session_windows.mode )
call assert_equal(
\ [ 'col', [
\ [ 'row', [
\ [ 'leaf', g:vimspector_session_windows.variables ],
\ [ 'leaf', g:vimspector_session_windows.watches ],
\ [ 'leaf', g:vimspector_session_windows.stack_trace ],
\ ] ],
\ [ 'row', [
\ [ 'leaf', g:vimspector_session_windows.code ],
\ [ 'leaf', g:vimspector_session_windows.terminal ],
\ ] ],
\ [ 'leaf', g:vimspector_session_windows.output ],
\ ] ],
\ winlayout( g:vimspector_session_windows.tabpage ) )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! TearDown_Test_AutoLayoutTerminalHoriz()
unlet s:vimspector_ui_mode
call vimspector#test#setup#PopOption( 'lines' )
call vimspector#test#setup#PopOption( 'columns' )
endfunction
function! SetUp_Test_AutoLayoutTerminalVertVert()
let s:vimspector_ui_mode = 'auto'
" Not wide enough to go horizontal, but wide enough to put the terminal and
" code vertically split
call vimspector#test#setup#PushOption( 'columns', 80 )
call vimspector#test#setup#PushOption( 'lines', 50 )
endfunction
function! Test_AutoLayoutTerminalVertVert()
call s:StartDebugging()
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 )
call assert_equal( 'vertical', g:vimspector_session_windows.mode )
call assert_equal(
\ [ 'col', [
\ [ 'row', [
\ [ 'leaf', g:vimspector_session_windows.variables ],
\ [ 'leaf', g:vimspector_session_windows.watches ],
\ [ 'leaf', g:vimspector_session_windows.stack_trace ],
\ ] ],
\ [ 'leaf', g:vimspector_session_windows.code ],
\ [ 'leaf', g:vimspector_session_windows.terminal ],
\ [ 'leaf', g:vimspector_session_windows.output ],
\ ] ],
\ winlayout( g:vimspector_session_windows.tabpage ) )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! TearDown_Test_AutoLayoutTerminalVertVert()
unlet s:vimspector_ui_mode
call vimspector#test#setup#PopOption( 'lines' )
call vimspector#test#setup#PopOption( 'columns' )
endfunction
function! Test_CloseVariables() function! Test_CloseVariables()
call s:StartDebugging() call s:StartDebugging()
@ -656,56 +409,3 @@ function! Test_CustomWinBar()
call vimspector#test#setup#Reset() call vimspector#test#setup#Reset()
%bwipe! %bwipe!
endfunction endfunction
function! Test_VimspectorJumpedToFrame()
let s:ended = 0
let s:au_visited_buffers = {}
augroup TestVimspectorJumpedToFrame
au!
au User VimspectorJumpedToFrame
\ let s:au_visited_buffers[ bufname() ] = get( s:au_visited_buffers,
\ bufname(),
\ 0 ) + 1
au User VimspectorDebugEnded
\ let s:ended = 1
augroup END
lcd ../support/test/python/multiple_files
edit moo.py
let moo = 'moo.py'
let cow = getcwd() . '/cow.py'
call vimspector#SetLineBreakpoint( 'moo.py', 13 )
call vimspector#Launch()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 1, 1 )
call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 1 )
let expected = {}
let expected[ moo ] = 1
call assert_equal( expected, s:au_visited_buffers )
call vimspector#Continue()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 13, 1 )
call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 13 )
let expected[ moo ] += 1
call assert_equal( expected, s:au_visited_buffers )
call vimspector#SetLineBreakpoint( 'cow.py', 2 )
call vimspector#Continue()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'cow.py', 2, 1 )
call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'cow.py', 2 )
let expected[ cow ] = 1
call assert_equal( expected, s:au_visited_buffers )
VimspectorReset
call WaitForAssert( { -> assert_equal( s:ended, 1 ) } )
au! TestVimspectorJumpedToFrame
unlet! s:au_visited_buffers
unlet! s:ended
call vimspector#test#setup#Reset()
lcd -
%bwipe!
endfunction

View file

@ -1,28 +0,0 @@
function! SetUp()
call vimspector#test#setup#SetUpWithMappings( v:none )
py3 import vim
py3 __import__( 'vimspector' )
endfunction
function! ClearDown()
call vimspector#test#setup#ClearDown()
endfunction
function! s:RunPyFile( file_name )
redir => py_output
try
let v:errmsg = ''
silent! execute 'py3file python/' .. a:file_name
finally
redir END
call TestLog( [ a:file_name .. ' output:' ] + split( py_output, '\n' ) )
endtry
if v:errmsg !=# ''
call assert_report( v:errmsg )
endif
endfunction
function! Test_ExpandReferencesInDict()
call s:RunPyFile( 'Test_ExpandReferencesInDict.py' )
endfunction

View file

@ -194,7 +194,6 @@ function! Test_ExpandVariables()
\ [ \ [
\ '- Scope: Locals', \ '- Scope: Locals',
\ ' *+ t (Test): {...}', \ ' *+ t (Test): {...}',
\ '+ Scope: Registers',
\ ], \ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1, \ 1,
@ -212,7 +211,7 @@ function! Test_ExpandVariables()
call feedkeys( "\<CR>", 'xt' ) call feedkeys( "\<CR>", 'xt' )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '- Scope: Locals', \ '- Scope: Locals',
\ ' \*- t (Test): {...}', \ ' \*- t (Test): {...}',
@ -220,7 +219,6 @@ function! Test_ExpandVariables()
\ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- c (char): 0 ''\\0\{1,3}''',
\ ' \*- fffff (float): 0', \ ' \*- fffff (float): 0',
\ ' \*+ another_test (AnotherTest):\( {...}\)\?', \ ' \*+ another_test (AnotherTest):\( {...}\)\?',
\ '+ Scope: Registers',
\ ], \ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1, \ 1,
@ -231,7 +229,7 @@ function! Test_ExpandVariables()
" Step - stays expanded " Step - stays expanded
call vimspector#StepOver() call vimspector#StepOver()
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '- Scope: Locals', \ '- Scope: Locals',
\ ' - t (Test): {...}', \ ' - t (Test): {...}',
@ -239,7 +237,6 @@ function! Test_ExpandVariables()
\ ' - c (char): 0 ''\\0\{1,3}''', \ ' - c (char): 0 ''\\0\{1,3}''',
\ ' - fffff (float): 0', \ ' - fffff (float): 0',
\ ' + another_test (AnotherTest):\( {...}\)\?', \ ' + another_test (AnotherTest):\( {...}\)\?',
\ '+ Scope: Registers',
\ ], \ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1, \ 1,
@ -256,7 +253,6 @@ function! Test_ExpandVariables()
\ [ \ [
\ '- Scope: Locals', \ '- Scope: Locals',
\ ' + t (Test): {...}', \ ' + t (Test): {...}',
\ '+ Scope: Registers',
\ ], \ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1, \ 1,
@ -271,7 +267,6 @@ function! Test_ExpandVariables()
\ [ \ [
\ '- Scope: Locals', \ '- Scope: Locals',
\ ' + t (Test): {...}', \ ' + t (Test): {...}',
\ '+ Scope: Registers',
\ ], \ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1, \ 1,
@ -283,7 +278,7 @@ function! Test_ExpandVariables()
call setpos( '.', [ 0, 2, 1 ] ) call setpos( '.', [ 0, 2, 1 ] )
call feedkeys( "\<CR>", 'xt' ) call feedkeys( "\<CR>", 'xt' )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ '- Scope: Locals', \ '- Scope: Locals',
\ ' - t (Test): {...}', \ ' - t (Test): {...}',
@ -291,7 +286,6 @@ function! Test_ExpandVariables()
\ ' \*- c (char): 99 ''c''', \ ' \*- c (char): 99 ''c''',
\ ' \*- fffff (float): 0', \ ' \*- fffff (float): 0',
\ ' \*+ another_test (AnotherTest):\( {...}\)\?', \ ' \*+ another_test (AnotherTest):\( {...}\)\?',
\ '+ Scope: Registers',
\ ], \ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1, \ 1,
@ -308,7 +302,6 @@ function! Test_ExpandVariables()
\ assert_equal( \ assert_equal(
\ [ \ [
\ '+ Scope: Locals', \ '+ Scope: Locals',
\ '+ Scope: Registers',
\ ], \ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1, \ 1,
@ -323,7 +316,6 @@ function! Test_ExpandVariables()
\ assert_equal( \ assert_equal(
\ [ \ [
\ '+ Scope: Locals', \ '+ Scope: Locals',
\ '+ Scope: Registers',
\ ], \ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1, \ 1,
@ -339,7 +331,6 @@ function! Test_ExpandVariables()
\ assert_equal( \ assert_equal(
\ [ \ [
\ '+ Scope: Locals', \ '+ Scope: Locals',
\ '+ Scope: Registers',
\ ], \ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1, \ 1,
@ -387,7 +378,7 @@ function! Test_ExpandWatch()
call feedkeys( "\<CR>", 'xt' ) call feedkeys( "\<CR>", 'xt' )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ 'Watches: ----', \ 'Watches: ----',
\ 'Expression: t', \ 'Expression: t',
@ -406,7 +397,7 @@ function! Test_ExpandWatch()
" Step - stays expanded " Step - stays expanded
call vimspector#StepOver() call vimspector#StepOver()
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ 'Watches: ----', \ 'Watches: ----',
\ 'Expression: t', \ 'Expression: t',
@ -458,7 +449,7 @@ function! Test_ExpandWatch()
call setpos( '.', [ 0, 3, 1 ] ) call setpos( '.', [ 0, 3, 1 ] )
call feedkeys( "\<CR>", 'xt' ) call feedkeys( "\<CR>", 'xt' )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ 'Watches: ----', \ 'Watches: ----',
\ 'Expression: t', \ 'Expression: t',
@ -522,49 +513,6 @@ function Test_EvaluateConsole()
endfunction endfunction
function Test_EvaluateInput()
let fn = 'testdata/cpp/simple/struct.cpp'
call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{
\ configuration: 'run-to-breakpoint'
\ } } )
" Make sure the Test t is initialised
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 )
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 27, 1 )
VimspectorEval -exec print (int) printf("hello")
call assert_equal( bufnr( 'vimspector.Console' ),
\ winbufnr( g:vimspector_session_windows.output ) )
call WaitForAssert( {->
\ assert_equal(
\ [
\ ''
\ ],
\ getbufline( bufnr( 'vimspector.Console' ), '$', '$' )
\ )
\ } )
let len = getbufinfo( 'vimspector.Console' )[ 0 ].linecount
call WaitForAssert( {->
\ assert_equal(
\ [
\ 'Evaluating: -exec print (int) printf("hello")',
\ ],
\ getbufline( bufnr( 'vimspector.Console' ), len-2, len-2 )
\ )
\ } )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer(
\ 'vimspector.Console', len, v:null )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function Test_EvaluatePromptConsole() function Test_EvaluatePromptConsole()
let fn = 'testdata/cpp/simple/struct.cpp' let fn = 'testdata/cpp/simple/struct.cpp'
call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{ call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{
@ -616,7 +564,7 @@ function! Test_EvaluateFailure()
" Add a wtch " Add a wtch
call vimspector#AddWatch( 'test' ) call vimspector#AddWatch( 'test' )
call WaitForAssert( {-> call WaitForAssert( {->
\ AssertMatchList( \ AssertMatchist(
\ [ \ [
\ 'Watches: ----', \ 'Watches: ----',
\ 'Expression: test', \ 'Expression: test',
@ -643,493 +591,3 @@ function! Test_EvaluateFailure()
call vimspector#test#setup#Reset() call vimspector#test#setup#Reset()
%bwipe! %bwipe!
endfunction endfunction
function! Test_VariableEval()
let fn = 'testdata/cpp/simple/struct.cpp'
call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{
\ configuration: 'run-to-breakpoint'
\ } } )
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 )
" leader is ,
xmap <buffer> <Leader>d <Plug>VimspectorBalloonEval
nmap <buffer> <Leader>d <Plug>VimspectorBalloonEval
"evaluate the prev line
call setpos( '.', [ 0, 24, 8 ] )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 24, 8 )
call feedkeys( ',d', 'xt' )
call WaitForAssert( {->
\ assert_notequal( v:none, g:vimspector_session_windows.eval )
\ } )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '{...}',
\ ' - i: 0',
\ ' - c: 0 ''\\0\{1,3}''',
\ ' - fffff: 0',
\ ' + another_test: ',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.eval ),
\ 1,
\ '$' )
\ )
\ } )
"Close
call feedkeys( "\<Esc>", 'xt' )
call WaitForAssert( {->
\ assert_equal( v:none, g:vimspector_session_windows.eval )
\ } )
" test selection
call setpos( '.', [ 0, 24, 8 ] )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 24, 8 )
call feedkeys( 'viw,d', 'xt' )
call WaitForAssert( {->
\ assert_notequal( v:none, g:vimspector_session_windows.eval )
\ } )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '{...}',
\ ' - i: 0',
\ ' - c: 0 ''\\0\{1,3}''',
\ ' - fffff: 0',
\ ' + another_test: ',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.eval ),
\ 1,
\ '$' )
\ )
\ } )
"Close
call feedkeys( "\<Esc>", 'xt' )
call WaitForAssert( {->
\ assert_equal( v:none, g:vimspector_session_windows.eval )
\ } )
" Get back to normal mode
call feedkeys( "\<Esc>", 'xt' )
" Evaluation error
call setpos( '.', [ 0, 25, 1 ] )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 25, 1 )
call feedkeys( ',d', 'xt' )
call WaitForAssert( {->
\ assert_notequal( v:none, g:vimspector_session_windows.eval )
\ } )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ 'Evaluation error',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.eval ),
\ 1,
\ '$' )
\ )
\ } )
"Close
call feedkeys( "\<Esc>", 'xt' )
call WaitForAssert( {->
\ assert_equal( v:none, g:vimspector_session_windows.eval )
\ } )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! Test_VariableEvalExpand()
let fn = 'testdata/cpp/simple/struct.cpp'
call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{
\ configuration: 'run-to-breakpoint'
\ } } )
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 )
" leader is ,
xmap <buffer> <Leader>d <Plug>VimspectorBalloonEval
nmap <buffer> <Leader>d <Plug>VimspectorBalloonEval
"evaluate the prev line
call setpos( '.', [ 0, 24, 8 ] )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 24, 8 )
call feedkeys( ',d', 'xt' )
call WaitForAssert( {->
\ assert_notequal( v:none, g:vimspector_session_windows.eval )
\ } )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '{...}',
\ ' - i: 0',
\ ' - c: 0 ''\\0\{1,3}''',
\ ' - fffff: 0',
\ ' + another_test: ',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.eval ),
\ 1,
\ '$' )
\ )
\ } )
" Expand
call feedkeys( "jjjj\<CR>", 'xt' )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '{...}',
\ ' - i: 0',
\ ' - c: 0 ''\\0\{1,3}''',
\ ' - fffff: 0',
\ ' - another_test: ',
\ ' - choo: 0 ''\\0\{1,3}''',
\ ' + ints: '
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.eval ),
\ 1,
\ '$' )
\ )
\ } )
"Collapse
call feedkeys( "\<CR>", 'xt' )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '{...}',
\ ' - i: 0',
\ ' - c: 0 ''\\0\{1,3}''',
\ ' - fffff: 0',
\ ' + another_test: ',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.eval ),
\ 1,
\ '$' )
\ )
\ } )
"Close
call feedkeys( "\<Esc>", 'xt' )
call WaitForAssert( {->
\ assert_equal( v:none, g:vimspector_session_windows.eval )
\ } )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! Test_SetVariableValue_Local()
let fn = 'testdata/cpp/simple/struct.cpp'
call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{
\ configuration: 'run-to-breakpoint'
\ } } )
" Make sure the Test t is initialised
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 )
call WaitForAssert( {->
\ assert_equal(
\ [
\ '- Scope: Locals',
\ ' *+ t (Test): {...}',
\ '+ Scope: Registers',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1,
\ '$' )
\ )
\ } )
call assert_equal( 'cpp',
\ getbufvar(
\ winbufnr( g:vimspector_session_windows.variables ),
\ '&syntax' ) )
" Expand
call win_gotoid( g:vimspector_session_windows.variables )
call setpos( '.', [ 0, 2, 1 ] )
call feedkeys( "\<CR>", 'xt' )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '- Scope: Locals',
\ ' \*- t (Test): {...}',
\ ' \*- i (int): 0',
\ ' \*- c (char): 0 ''\\0\{1,3}''',
\ ' \*- fffff (float): 0',
\ ' \*+ another_test (AnotherTest):\( {...}\)\?',
\ '+ Scope: Registers',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1,
\ '$' )
\ )
\ } )
call setpos( '.', [ 0, 3, 1 ] )
" We can't just fire the keys to the inpit prompt because we use inputsave()
" and inputrestore(), so mock that out and fire away.
py3 <<EOF
from unittest import mock
with mock.patch( 'vimspector.utils.InputSave' ):
vim.eval( 'feedkeys( "\<C-CR>\<C-u>100\<CR>", "xt" )' )
EOF
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '- Scope: Locals',
\ ' \*- t (Test): {...}',
\ ' \*- i (int): 100',
\ ' \*- c (char): 0 ''\\0\{1,3}''',
\ ' \*- fffff (float): 0',
\ ' \*+ another_test (AnotherTest):\( {...}\)\?',
\ '+ Scope: Registers',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1,
\ '$' )
\ )
\ } )
" Now set it via the more comforable scripting interface
call vimspector#SetVariableValue( '1234' )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '- Scope: Locals',
\ ' \*- t (Test): {...}',
\ ' \*- i (int): 1234',
\ ' \*- c (char): 0 ''\\0\{1,3}''',
\ ' \*- fffff (float): 0',
\ ' \*+ another_test (AnotherTest):\( {...}\)\?',
\ '+ Scope: Registers',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1,
\ '$' )
\ )
\ } )
" Something fails
call vimspector#SetVariableValue( 'this is invalid' )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '- Scope: Locals',
\ ' \*- t (Test): {...}',
\ ' \*- i (int): 1234',
\ ' \*- c (char): 0 ''\\0\{1,3}''',
\ ' \*- fffff (float): 0',
\ ' \*+ another_test (AnotherTest):\( {...}\)\?',
\ '+ Scope: Registers',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.variables ),
\ 1,
\ '$' )
\ )
\ } )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! Test_SetVariableValue_Watch()
let fn = 'testdata/cpp/simple/struct.cpp'
call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{
\ configuration: 'run-to-breakpoint'
\ } } )
" Make sure the Test t is initialised
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 )
call win_gotoid( g:vimspector_session_windows.watches )
call feedkeys( "it\<CR>", 'xt' )
call WaitForAssert( {->
\ assert_equal(
\ [
\ 'Watches: ----',
\ 'Expression: t',
\ ' *+ Result: {...}',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.watches ),
\ 1,
\ '$' )
\ )
\ } )
call assert_equal( 'cpp',
\ getbufvar(
\ winbufnr( g:vimspector_session_windows.watches ),
\ '&syntax' ) )
" Expand
call win_gotoid( g:vimspector_session_windows.watches )
call setpos( '.', [ 0, 3, 1 ] )
call feedkeys( "\<CR>", 'xt' )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ 'Watches: ----',
\ 'Expression: t',
\ ' \*- Result: {...}',
\ ' \*- i (int): 0',
\ ' \*- c (char): 0 ''\\0\{1,3}''',
\ ' \*- fffff (float): 0',
\ ' \*+ another_test (AnotherTest):\( {...}\)\?',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.watches ),
\ 1,
\ '$' )
\ )
\ } )
call setpos( '.', [ 0, 4, 1 ] )
" We can't just fire the keys to the inpit prompt because we use inputsave()
" and inputrestore(), so mock that out and fire away.
" Note: mapleder is ,
py3 <<EOF
from unittest import mock
with mock.patch( 'vimspector.utils.InputSave' ):
vim.eval( 'feedkeys( ",\<CR>\<C-u>100\<CR>", "xt" )' )
EOF
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ 'Watches: ----',
\ 'Expression: t',
\ ' \*- Result: {...}',
\ ' \*- i (int): 100',
\ ' \*- c (char): 0 ''\\0\{1,3}''',
\ ' \*- fffff (float): 0',
\ ' \*+ another_test (AnotherTest):\( {...}\)\?',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.watches ),
\ 1,
\ '$' )
\ )
\ } )
" Now set it via the more comforable scripting interface
call vimspector#SetVariableValue( '1234' )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ 'Watches: ----',
\ 'Expression: t',
\ ' \*- Result: {...}',
\ ' \*- i (int): 1234',
\ ' \*- c (char): 0 ''\\0\{1,3}''',
\ ' \*- fffff (float): 0',
\ ' \*+ another_test (AnotherTest):\( {...}\)\?',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.watches ),
\ 1,
\ '$' )
\ )
\ } )
call vimspector#test#setup#Reset()
%bwipe!
endfunction
function! Test_SetVariableValue_Balloon()
let fn = 'testdata/cpp/simple/struct.cpp'
call s:StartDebugging( #{ fn: fn, line: 24, col: 1, launch: #{
\ configuration: 'run-to-breakpoint'
\ } } )
call vimspector#StepOver()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 26, 1 )
" leader is ,
xmap <buffer> <Leader>d <Plug>VimspectorBalloonEval
nmap <buffer> <Leader>d <Plug>VimspectorBalloonEval
"evaluate the prev line
call setpos( '.', [ 0, 24, 8 ] )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 24, 8 )
call feedkeys( ',d', 'xt' )
call WaitForAssert( {->
\ assert_notequal( v:none, g:vimspector_session_windows.eval )
\ } )
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '{...}',
\ ' - i: 0',
\ ' - c: 0 ''\\0\{1,3}''',
\ ' - fffff: 0',
\ ' + another_test: ',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.eval ),
\ 1,
\ '$' )
\ )
\ } )
" Move down to the ffff line
call feedkeys( 'jjj', 'xt' )
" We can't just fire the keys to the inpit prompt because we use inputsave()
" and inputrestore(), so mock that out and fire away.
" Note: mapleder is ,
py3 <<EOF
from unittest import mock
with mock.patch( 'vimspector.utils.InputSave' ):
vim.eval( 'feedkeys( "\<C-CR>\<C-u>100\<CR>", "xt" )' )
EOF
call WaitForAssert( {->
\ AssertMatchList(
\ [
\ '{...}',
\ ' - i: 0',
\ ' - c: 0 ''\\0\{1,3}''',
\ ' - fffff: 100',
\ ' + another_test: ',
\ ],
\ getbufline( winbufnr( g:vimspector_session_windows.eval ),
\ 1,
\ '$' )
\ )
\ } )
call vimspector#test#setup#Reset()
%bwipe!
endfunction

View file

@ -1,10 +1,8 @@
let g:vimspector_test_plugin_path = expand( '<sfile>:p:h:h' ) let g:vimspector_test_plugin_path = expand( '<sfile>:p:h:h' )
set mouse=a set mouse=a
set noequalalways set noequalalways
let mapleader = ','
let maplocalleader = "\<Space>"
let &runtimepath = &runtimepath . ',' . g:vimspector_test_plugin_path let &rtp = &rtp . ',' . g:vimspector_test_plugin_path
filetype plugin indent on filetype plugin indent on
syntax enable syntax enable