Add a session ID to debug_session - vim only for now
This commit is contained in:
parent
054ea35428
commit
fb2bad216f
11 changed files with 320 additions and 156 deletions
|
|
@ -19,8 +19,12 @@ let s:save_cpo = &cpoptions
|
||||||
set cpoptions&vim
|
set cpoptions&vim
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
function! s:_OnServerData( channel, data ) abort
|
let s:channels = {}
|
||||||
if !exists( 's:ch' ) || s:ch isnot a:channel
|
let s:jobs = {}
|
||||||
|
|
||||||
|
function! s:_OnServerData( session_id, channel, data ) abort
|
||||||
|
if !has_key( s:channels, a:session_id ) ||
|
||||||
|
\ s:channels[ a:session_id ] isnot a:channel
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
@ -29,20 +33,23 @@ _vimspector_session.OnChannelData( vim.eval( 'a:data' ) )
|
||||||
EOF
|
EOF
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:_OnClose( channel ) abort
|
function! s:_OnClose( session_id, channel ) abort
|
||||||
if !exists( 's:ch' ) || s:ch isnot a:channel
|
if !has_key( s:channels, a:session_id ) ||
|
||||||
|
\ s:channels[ a:session_id ] isnot a:channel
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
echom 'Channel closed'
|
echom 'Channel closed'
|
||||||
redraw
|
redraw
|
||||||
unlet s:ch
|
unlet s:channels[ a:session_id ]
|
||||||
py3 _vimspector_session.OnServerExit( 0 )
|
py3 _vimspector_session.OnServerExit( 0 )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#channel#StartDebugSession( config ) abort
|
function! vimspector#internal#channel#StartDebugSession(
|
||||||
|
\ session_id,
|
||||||
|
\ config ) abort
|
||||||
|
|
||||||
if exists( 's:ch' )
|
if has_key( s:channels, a:session_id )
|
||||||
echo 'Channel is already running'
|
echo 'Channel is already running'
|
||||||
return v:false
|
return v:false
|
||||||
endif
|
endif
|
||||||
|
|
@ -50,7 +57,7 @@ function! vimspector#internal#channel#StartDebugSession( config ) abort
|
||||||
" If we _also_ have a command line, then start the actual job. This allows for
|
" If we _also_ have a command line, then start the actual job. This allows for
|
||||||
" servers which start up and listen on some port
|
" servers which start up and listen on some port
|
||||||
if has_key( a:config, 'command' )
|
if has_key( a:config, 'command' )
|
||||||
let s:job = job_start( a:config[ 'command' ],
|
let s:jobs[ a:session_id ] = job_start( a:config[ 'command' ],
|
||||||
\ {
|
\ {
|
||||||
\ 'in_mode': 'raw',
|
\ 'in_mode': 'raw',
|
||||||
\ 'out_mode': 'raw',
|
\ 'out_mode': 'raw',
|
||||||
|
|
@ -65,16 +72,19 @@ function! vimspector#internal#channel#StartDebugSession( config ) abort
|
||||||
let l:addr = get( a:config, 'host', '127.0.0.1' ) . ':' . a:config[ 'port' ]
|
let l:addr = get( a:config, 'host', '127.0.0.1' ) . ':' . 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,
|
" FIXME: This _always_ waits 10s; the neochannel version is quicker
|
||||||
|
let s:channels[ a:session_id ] = ch_open( l:addr,
|
||||||
\ {
|
\ {
|
||||||
\ 'mode': 'raw',
|
\ 'mode': 'raw',
|
||||||
\ 'callback': funcref( 's:_OnServerData' ),
|
\ 'callback': funcref( 's:_OnServerData',
|
||||||
\ 'close_cb': funcref( 's:_OnClose' ),
|
\ [ a:session_id ] ),
|
||||||
|
\ 'close_cb': funcref( 's:_OnClose',
|
||||||
|
\ [ a:session_id ] ),
|
||||||
\ 'waittime': 10000,
|
\ 'waittime': 10000,
|
||||||
\ }
|
\ }
|
||||||
\ )
|
\ )
|
||||||
|
|
||||||
if ch_status( s:ch ) !=# 'open'
|
if ch_status( s:channels[ a:session_id ] ) !=# 'open'
|
||||||
echom 'Unable to connect to' l:addr
|
echom 'Unable to connect to' l:addr
|
||||||
redraw
|
redraw
|
||||||
return v:false
|
return v:false
|
||||||
|
|
@ -83,62 +93,68 @@ function! vimspector#internal#channel#StartDebugSession( config ) abort
|
||||||
return v:true
|
return v:true
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#channel#Send( msg ) abort
|
function! vimspector#internal#channel#Send( session_id, msg ) abort
|
||||||
call ch_sendraw( s:ch, a:msg )
|
call ch_sendraw( s:channels[ a:session_id ], a:msg )
|
||||||
return 1
|
return 1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#channel#Timeout( id ) abort
|
function! vimspector#internal#channel#Timeout( session_id, id ) abort
|
||||||
py3 << EOF
|
py3 << EOF
|
||||||
_vimspector_session.OnRequestTimeout( vim.eval( 'a:id' ) )
|
_vimspector_session.OnRequestTimeout( vim.eval( 'a:id' ) )
|
||||||
EOF
|
EOF
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#channel#StopDebugSession() abort
|
function! s:_ChannelExists( session_id ) abort
|
||||||
|
return has_key( s:channels, a:session_id ) &&
|
||||||
|
\ count( [ 'closed', 'fail' ],
|
||||||
|
\ ch_status( s:channels[ a:session_id ] ) ) == 0
|
||||||
|
endfunction
|
||||||
|
|
||||||
if exists( 's:job' )
|
function! vimspector#internal#channel#StopDebugSession( session_id ) abort
|
||||||
|
|
||||||
|
if has_key( s:jobs, a:session_id )
|
||||||
" We started the job, so we need to kill it and wait to read all the data
|
" We started the job, so we need to kill it and wait to read all the data
|
||||||
" from the socket
|
" from the socket
|
||||||
|
|
||||||
if job_status( s:job ) ==# 'run'
|
let job = s:jobs[ a:session_id ]
|
||||||
call job_stop( s:job, 'term' )
|
if job_status( job ) ==# 'run'
|
||||||
|
call job_stop( job, 'term' )
|
||||||
endif
|
endif
|
||||||
|
|
||||||
while job_status( s:job ) ==# 'run'
|
while job_status( job ) ==# 'run'
|
||||||
call job_stop( s:job, 'kill' )
|
call job_stop( job, 'kill' )
|
||||||
endwhile
|
endwhile
|
||||||
|
|
||||||
unlet s:job
|
call remove( s:jobs, a:session_id )
|
||||||
|
|
||||||
if exists( 's:ch' ) && count( [ 'closed', 'fail' ], ch_status( s:ch ) ) == 0
|
if s:_ChannelExists( a:session_id )
|
||||||
" We're going to block on this channel reading, then manually call the
|
" We're going to block on this channel reading, then manually call the
|
||||||
" close callback, so remove the automatic close callback to avoid tricky
|
" close callback, so remove the automatic close callback to avoid tricky
|
||||||
" re-entrancy
|
" re-entrancy
|
||||||
call ch_setoptions( s:ch, { 'close_cb': '' } )
|
call ch_setoptions( s:channels[ a:session_id ], { 'close_cb': '' } )
|
||||||
endif
|
endif
|
||||||
|
elseif s:_ChannelExists( a:session_id )
|
||||||
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:channels[ a:session_id ] )
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" block until we've read all data from the socket and handled it.
|
" block until we've read all data from the socket and handled it.
|
||||||
while count( [ 'open', 'buffered' ], ch_status( s:ch ) ) == 1
|
while has_key( s:channels, a:session_id ) &&
|
||||||
let data = ch_read( s:ch, { 'timeout': 10 } )
|
\ count( [ 'open', 'buffered' ],
|
||||||
call s:_OnServerData( s:ch, data )
|
\ ch_status( s:channels[ a:session_id ] ) ) == 1
|
||||||
|
let data = ch_read( s:channels[ a:session_id ], { 'timeout': 10 } )
|
||||||
|
call s:_OnServerData( s:channels[ a:session_id ], data )
|
||||||
endwhile
|
endwhile
|
||||||
call s:_OnClose( s:ch )
|
if has_key( s:channels, a:session_id )
|
||||||
|
call s:_OnClose( s:channels[ a:session_id ] )
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#channel#Reset() abort
|
function! vimspector#internal#channel#Reset( session_id ) abort
|
||||||
if exists( 's:ch' ) || exists( 's:job' )
|
call vimspector#internal#channel#StopDebugSession( a:session_id )
|
||||||
call vimspector#internal#channel#StopDebugSession()
|
|
||||||
endif
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Boilerplate {{{
|
" Boilerplate {{{
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,12 @@ let s:save_cpo = &cpoptions
|
||||||
set cpoptions&vim
|
set cpoptions&vim
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
function! s:_OnServerData( channel, data ) abort
|
let s:jobs = {}
|
||||||
if !exists( 's:job' ) || ch_getjob( a:channel ) isnot s:job
|
let s:commands = {}
|
||||||
|
|
||||||
|
function! s:_OnServerData( session_id, channel, data ) abort
|
||||||
|
if !has_key( s:jobs, a:session_id ) ||
|
||||||
|
\ ch_getjob( a:channel ) isnot s:jobs[ a:session_id ]
|
||||||
call ch_log( 'Get data after process exit' )
|
call ch_log( 'Get data after process exit' )
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
@ -28,8 +32,9 @@ function! s:_OnServerData( channel, data ) abort
|
||||||
py3 _vimspector_session.OnChannelData( vim.eval( 'a:data' ) )
|
py3 _vimspector_session.OnChannelData( vim.eval( 'a:data' ) )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:_OnServerError( channel, data ) abort
|
function! s:_OnServerError( session_id, channel, data ) abort
|
||||||
if !exists( 's:job' ) || ch_getjob( a:channel ) isnot s:job
|
if !has_key( s:jobs, a:session_id ) ||
|
||||||
|
\ ch_getjob( a:channel ) isnot s:jobs[ a:session_id ]
|
||||||
call ch_log( 'Get data after process exit' )
|
call ch_log( 'Get data after process exit' )
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
@ -41,22 +46,24 @@ endfunction
|
||||||
" FIXME: We should wait until both the exit_cb _and_ the channel closed callback
|
" FIXME: We should wait until both the exit_cb _and_ the channel closed callback
|
||||||
" have been received before OnServerExit?
|
" have been received before OnServerExit?
|
||||||
|
|
||||||
function! s:_OnExit( channel, status ) abort
|
function! s:_OnExit( session_id, channel, status ) abort
|
||||||
if !exists( 's:job' ) || ch_getjob( a:channel ) isnot s:job
|
if !has_key( s:jobs, a:session_id ) ||
|
||||||
|
\ ch_getjob( a:channel ) isnot s:jobs[ a:session_id ]
|
||||||
call ch_log( 'Unexpected exit callback' )
|
call ch_log( 'Unexpected exit callback' )
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
echom 'Channel exit with status ' . a:status
|
echom 'Channel exit with status ' . a:status
|
||||||
redraw
|
redraw
|
||||||
if exists( 's:job' )
|
if has_key( s:jobs, a:session_id )
|
||||||
unlet s:job
|
unlet s:jobs[ a:session_id ]
|
||||||
endif
|
endif
|
||||||
py3 _vimspector_session.OnServerExit( vim.eval( 'a:status' ) )
|
py3 _vimspector_session.OnServerExit( vim.eval( 'a:status' ) )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:_OnClose( channel ) abort
|
function! s:_OnClose( session_id, channel ) abort
|
||||||
if !exists( 's:job' ) || job_getchannel( s:job ) != a:channel
|
if !has_key( s:jobs, a:session_id ) ||
|
||||||
|
\ ch_getjob( a:channel ) isnot s:jobs[ a:session_id ]
|
||||||
call ch_log( 'Channel closed after exit' )
|
call ch_log( 'Channel closed after exit' )
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
@ -65,34 +72,38 @@ function! s:_OnClose( channel ) abort
|
||||||
redraw
|
redraw
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#job#StartDebugSession( config ) abort
|
function! vimspector#internal#job#StartDebugSession( session_id, config ) abort
|
||||||
if exists( 's:job' )
|
if has_key( s:jobs, a:session_id )
|
||||||
echom 'Not starting: Job is already running'
|
echom 'Not starting: Job is already running'
|
||||||
redraw
|
redraw
|
||||||
return v:false
|
return v:false
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let s:job = job_start( a:config[ 'command' ],
|
let s:jobs[ a:session_id ] = job_start( a:config[ 'command' ],
|
||||||
\ {
|
\ {
|
||||||
\ 'in_mode': 'raw',
|
\ 'in_mode': 'raw',
|
||||||
\ 'out_mode': 'raw',
|
\ 'out_mode': 'raw',
|
||||||
\ 'err_mode': 'raw',
|
\ 'err_mode': 'raw',
|
||||||
\ 'exit_cb': funcref( 's:_OnExit' ),
|
\ 'exit_cb': funcref( 's:_OnExit',
|
||||||
\ 'close_cb': funcref( 's:_OnClose' ),
|
\ [ a:session_id ] ),
|
||||||
\ 'out_cb': funcref( 's:_OnServerData' ),
|
\ 'close_cb': funcref( 's:_OnClose',
|
||||||
\ 'err_cb': funcref( 's:_OnServerError' ),
|
\ [ a:session_id ] ),
|
||||||
|
\ 'out_cb': funcref( 's:_OnServerData',
|
||||||
|
\ [ a:session_id ] ),
|
||||||
|
\ 'err_cb': funcref( 's:_OnServerError',
|
||||||
|
\ [ a:session_id ] ),
|
||||||
\ 'stoponexit': 'term',
|
\ 'stoponexit': 'term',
|
||||||
\ 'env': a:config[ 'env' ],
|
\ 'env': a:config[ 'env' ],
|
||||||
\ 'cwd': a:config[ 'cwd' ],
|
\ 'cwd': a:config[ 'cwd' ],
|
||||||
\ }
|
\ }
|
||||||
\ )
|
\ )
|
||||||
|
|
||||||
if !exists( 's:job' )
|
if !has_key( s:jobs, a:session_id )
|
||||||
" The job died immediately after starting and we cleaned up
|
" The job died immediately after starting and we cleaned up
|
||||||
return v:false
|
return v:false
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let status = job_status( s:job )
|
let status = job_status( s:jobs[ a:session_id ] )
|
||||||
|
|
||||||
echom 'Started job, status is: ' . status
|
echom 'Started job, status is: ' . status
|
||||||
redraw
|
redraw
|
||||||
|
|
@ -104,20 +115,22 @@ function! vimspector#internal#job#StartDebugSession( config ) abort
|
||||||
return v:true
|
return v:true
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#job#Send( msg ) abort
|
function! vimspector#internal#job#Send( session_id, msg ) abort
|
||||||
if ! exists( 's:job' )
|
if ! has_key( s:jobs, a:session_id )
|
||||||
echom "Can't send message: Job was not initialised correctly"
|
echom "Can't send message: Job was not initialised correctly"
|
||||||
redraw
|
redraw
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if job_status( s:job ) !=# 'run'
|
let job = s:jobs[ a:session_id ]
|
||||||
|
|
||||||
|
if job_status( job ) !=# 'run'
|
||||||
echom "Can't send message: Job is not running"
|
echom "Can't send message: Job is not running"
|
||||||
redraw
|
redraw
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let ch = job_getchannel( s:job )
|
let ch = job_getchannel( job )
|
||||||
if ch ==# 'channel fail'
|
if ch ==# 'channel fail'
|
||||||
echom 'Channel was closed unexpectedly!'
|
echom 'Channel was closed unexpectedly!'
|
||||||
redraw
|
redraw
|
||||||
|
|
@ -128,45 +141,55 @@ function! vimspector#internal#job#Send( msg ) abort
|
||||||
return 1
|
return 1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#job#StopDebugSession() abort
|
function! vimspector#internal#job#StopDebugSession( session_id ) abort
|
||||||
if !exists( 's:job' )
|
if ! has_key( s:jobs, a:session_id )
|
||||||
echom "Not stopping session: Job doesn't exist"
|
echom "Not stopping session: Job doesn't exist"
|
||||||
redraw
|
redraw
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if job_status( s:job ) ==# 'run'
|
let job = s:jobs[ a:session_id ]
|
||||||
|
|
||||||
|
if job_status( job ) ==# 'run'
|
||||||
echom 'Terminating job'
|
echom 'Terminating job'
|
||||||
redraw
|
redraw
|
||||||
call job_stop( s:job, 'kill' )
|
call job_stop( job, 'kill' )
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#job#Reset() abort
|
function! vimspector#internal#job#Reset( session_id ) abort
|
||||||
call vimspector#internal#job#StopDebugSession()
|
call vimspector#internal#job#StopDebugSession( a:session_id )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:_OnCommandExit( category, ch, code ) abort
|
function! s:_OnCommandExit( session_id, category, ch, code ) abort
|
||||||
py3 __import__( "vimspector",
|
py3 __import__( "vimspector",
|
||||||
\ fromlist = [ "utils" ] ).utils.OnCommandWithLogComplete(
|
\ fromlist = [ "utils" ] ).utils.OnCommandWithLogComplete(
|
||||||
|
\ vim.eval( 'a:session_id' ),
|
||||||
\ vim.eval( 'a:category' ),
|
\ vim.eval( 'a:category' ),
|
||||||
\ int( vim.eval( 'a:code' ) ) )
|
\ int( vim.eval( 'a:code' ) ) )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#job#StartCommandWithLog( cmd, category ) abort
|
function! vimspector#internal#job#StartCommandWithLog(
|
||||||
|
\ session_id,
|
||||||
|
\ cmd,
|
||||||
|
\ category ) abort
|
||||||
if ! exists( 's:commands' )
|
if ! exists( 's:commands' )
|
||||||
let s:commands = {}
|
let s:commands = {}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ! has_key( s:commands, a:category )
|
if ! has_key( s:commands, a:session_id )
|
||||||
let s:commands[ a:category ] = []
|
let s:commands[ a:session_id ] = {}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:index = len( s:commands[ a:category ] )
|
if ! has_key( s:commands[ a:session_id ], a:category )
|
||||||
|
let s:commands[ a:session_id ][ a:category ] = []
|
||||||
|
endif
|
||||||
|
|
||||||
let buf = '_vimspector_log_' . a:category
|
let l:index = len( s:commands[ a:session_id ][ a:category ] )
|
||||||
|
|
||||||
call add( s:commands[ a:category ], job_start(
|
let buf = '_vimspector_log_' . a:session_id . '_' . a:category
|
||||||
|
|
||||||
|
call add( s:commands[ a:session_id ][ a:category ], job_start(
|
||||||
\ a:cmd,
|
\ a:cmd,
|
||||||
\ {
|
\ {
|
||||||
\ 'out_io': 'buffer',
|
\ 'out_io': 'buffer',
|
||||||
|
|
@ -175,13 +198,14 @@ function! vimspector#internal#job#StartCommandWithLog( cmd, category ) abort
|
||||||
\ 'err_msg': 0,
|
\ 'err_msg': 0,
|
||||||
\ 'out_name': buf,
|
\ 'out_name': buf,
|
||||||
\ 'err_name': buf,
|
\ 'err_name': buf,
|
||||||
\ 'exit_cb': funcref( 's:_OnCommandExit', [ a:category ] ),
|
\ 'exit_cb': funcref( 's:_OnCommandExit',
|
||||||
|
\ [ a:session_id, a:category ] ),
|
||||||
\ 'out_modifiable': 0,
|
\ 'out_modifiable': 0,
|
||||||
\ 'err_modifiable': 0,
|
\ 'err_modifiable': 0,
|
||||||
\ 'stoponexit': 'kill'
|
\ 'stoponexit': 'kill'
|
||||||
\ } ) )
|
\ } ) )
|
||||||
|
|
||||||
if job_status( s:commands[ a:category ][ index ] ) !=# 'run'
|
if job_status( s:commands[ a:session_id ][ a:category ][ index ] ) !=# 'run'
|
||||||
echom 'Unable to start job for ' . string( a:cmd )
|
echom 'Unable to start job for ' . string( a:cmd )
|
||||||
redraw
|
redraw
|
||||||
return v:none
|
return v:none
|
||||||
|
|
@ -191,19 +215,27 @@ function! vimspector#internal#job#StartCommandWithLog( cmd, category ) abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! vimspector#internal#job#CleanUpCommand( category ) abort
|
function! vimspector#internal#job#CleanUpCommand( session_id, category ) abort
|
||||||
if ! exists( 's:commands' )
|
if ! exists( 's:commands' )
|
||||||
let s:commands = {}
|
let s:commands = {}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ! has_key( s:commands, a:category )
|
if ! has_key( s:commands, a:session_id )
|
||||||
|
let s:commands[ a:session_id ] = {}
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ! has_key( s:commands[ a:session_id ], a:category )
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
for j in s:commands[ a:category ]
|
for j in s:commands[ a:session_id ][ a:category ]
|
||||||
call job_stop( j, 'kill' )
|
call job_stop( j, 'kill' )
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
unlet s:commands[ a:category ]
|
unlet s:commands[ a:session_id ][ a:category ]
|
||||||
|
|
||||||
|
if len( s:commands[ a:session_id ] ) == 0
|
||||||
|
unlet s:commands[ a:session_id ]
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Boilerplate {{{
|
" Boilerplate {{{
|
||||||
|
|
|
||||||
|
|
@ -20,28 +20,34 @@ set cpoptions&vim
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
|
|
||||||
|
let s:channels = {}
|
||||||
|
let s:jobs = {}
|
||||||
|
|
||||||
function! s:_OnEvent( chan_id, data, event ) abort
|
|
||||||
|
function! s:_OnEvent( session_id, chan_id, data, event ) abort
|
||||||
if v:exiting isnot# v:null
|
if v:exiting isnot# v:null
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists( 's:ch' ) || a:chan_id != s:ch
|
if !has_key( s:channels, a:session_id ) ||
|
||||||
|
\ a:chan_id != s:channels[ a:session_id ]
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if a:data == ['']
|
if a:data == ['']
|
||||||
echom 'Channel closed'
|
echom 'Channel closed'
|
||||||
redraw
|
redraw
|
||||||
unlet s:ch
|
unlet s:channels[ a:session_id ]
|
||||||
py3 _vimspector_session.OnServerExit( 0 )
|
py3 _vimspector_session.OnServerExit( 0 )
|
||||||
else
|
else
|
||||||
py3 _vimspector_session.OnChannelData( '\n'.join( vim.eval( 'a:data' ) ) )
|
py3 _vimspector_session.OnChannelData( '\n'.join( vim.eval( 'a:data' ) ) )
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#neochannel#StartDebugSession( config ) abort
|
function! vimspector#internal#neochannel#StartDebugSession(
|
||||||
if exists( 's:ch' )
|
\ session_id,
|
||||||
|
\ config ) abort
|
||||||
|
if has_key( s:channels, a:session_id )
|
||||||
echom 'Not starting: Channel is already running'
|
echom 'Not starting: Channel is already running'
|
||||||
redraw
|
redraw
|
||||||
return v:false
|
return v:false
|
||||||
|
|
@ -54,12 +60,12 @@ function! vimspector#internal#neochannel#StartDebugSession( config ) abort
|
||||||
try
|
try
|
||||||
let old_env = vimspector#internal#neoterm#PrepareEnvironment(
|
let old_env = vimspector#internal#neoterm#PrepareEnvironment(
|
||||||
\ a:config[ 'env' ] )
|
\ a:config[ 'env' ] )
|
||||||
let s:job = jobstart( a:config[ 'command' ],
|
let s:jobs[ a:session_id ] = jobstart( a:config[ 'command' ],
|
||||||
\ {
|
\ {
|
||||||
\ 'cwd': a:config[ 'cwd' ],
|
\ 'cwd': a:config[ 'cwd' ],
|
||||||
\ 'env': a:config[ 'env' ],
|
\ 'env': a:config[ 'env' ],
|
||||||
\ }
|
\ }
|
||||||
\ )
|
\ )
|
||||||
finally
|
finally
|
||||||
call vimspector#internal#neoterm#ResetEnvironment( a:config[ 'env' ],
|
call vimspector#internal#neoterm#ResetEnvironment( a:config[ 'env' ],
|
||||||
\ old_env )
|
\ old_env )
|
||||||
|
|
@ -72,9 +78,10 @@ function! vimspector#internal#neochannel#StartDebugSession( config ) abort
|
||||||
while attempt <= 10
|
while attempt <= 10
|
||||||
echo 'Connecting to ' . l:addr . '... (attempt' attempt 'of 10)'
|
echo 'Connecting to ' . l:addr . '... (attempt' attempt 'of 10)'
|
||||||
try
|
try
|
||||||
let s:ch = sockconnect( 'tcp',
|
let s:channels[ a:session_id ] = sockconnect(
|
||||||
\ addr,
|
\ 'tcp',
|
||||||
\ { 'on_data': funcref( 's:_OnEvent' ) } )
|
\ addr,
|
||||||
|
\ { 'on_data': funcref( 's:_OnEvent', [ a:session_id ] ) } )
|
||||||
redraw
|
redraw
|
||||||
return v:true
|
return v:true
|
||||||
catch /connection refused/
|
catch /connection refused/
|
||||||
|
|
@ -88,30 +95,30 @@ function! vimspector#internal#neochannel#StartDebugSession( config ) abort
|
||||||
return v:false
|
return v:false
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#neochannel#Send( msg ) abort
|
function! vimspector#internal#neochannel#Send( session_id, msg ) abort
|
||||||
if ! exists( 's:ch' )
|
if ! has_key( s:channels, a:session_id )
|
||||||
echom "Can't send message: Channel was not initialised correctly"
|
echom "Can't send message: Channel was not initialised correctly"
|
||||||
redraw
|
redraw
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call chansend( s:ch, a:msg )
|
call chansend( s:channels[ a:session_id ], a:msg )
|
||||||
return 1
|
return 1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#neochannel#StopDebugSession() abort
|
function! vimspector#internal#neochannel#StopDebugSession( session_id ) abort
|
||||||
if exists( 's:ch' )
|
if has_key( s:channels, a:session_id )
|
||||||
call chanclose( s:ch )
|
call chanclose( s:channels[ a:session_id ] )
|
||||||
" It doesn't look like we get a callback after chanclos. Who knows if we
|
" It doesn't look like we get a callback after chanclos. Who knows if we
|
||||||
" will subsequently receive data callbacks.
|
" will subsequently receive data callbacks.
|
||||||
call s:_OnEvent( s:ch, [ '' ], 'data' )
|
call s:_OnEvent( a:session_id, s:channels[ a:session_id ], [ '' ], 'data' )
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if exists( 's:job' )
|
if has_key( s:jobs, a:session_id )
|
||||||
if vimspector#internal#neojob#JobIsRunning( s:job )
|
if vimspector#internal#neojob#JobIsRunning( s:jobs[ a:session_id ] )
|
||||||
call jobstop( s:job )
|
call jobstop( s:jobs[ a:session_id ] )
|
||||||
endif
|
endif
|
||||||
unlet s:job
|
unlet s:jobs[ a:session_id ]
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,17 @@ let s:save_cpo = &cpoptions
|
||||||
set cpoptions&vim
|
set cpoptions&vim
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
|
let s:jobs = {}
|
||||||
|
let s:commands = {}
|
||||||
|
|
||||||
|
|
||||||
function! s:_OnEvent( chan_id, data, event ) abort
|
|
||||||
|
function! s:_OnEvent( session_id, chan_id, data, event ) abort
|
||||||
if v:exiting isnot# v:null
|
if v:exiting isnot# v:null
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists( 's:job' ) || a:chan_id != s:job
|
if !has_key( s:jobs, a:session_id ) || a:chan_id != s:jobs[ a:session_id ]
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
@ -38,13 +41,15 @@ function! s:_OnEvent( chan_id, data, event ) abort
|
||||||
elseif a:event ==# 'exit'
|
elseif a:event ==# 'exit'
|
||||||
echom 'Channel exit with status ' . a:data
|
echom 'Channel exit with status ' . a:data
|
||||||
redraw
|
redraw
|
||||||
unlet s:job
|
unlet s:jobs[ a:session_id ]
|
||||||
py3 _vimspector_session.OnServerExit( vim.eval( 'a:data' ) )
|
py3 _vimspector_session.OnServerExit( vim.eval( 'a:data' ) )
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#neojob#StartDebugSession( config ) abort
|
function! vimspector#internal#neojob#StartDebugSession(
|
||||||
if exists( 's:job' )
|
\ session_id,
|
||||||
|
\ config ) abort
|
||||||
|
if has_key( s:jobs, a:session_id )
|
||||||
echom 'Not starging: Job is already running'
|
echom 'Not starging: Job is already running'
|
||||||
redraw
|
redraw
|
||||||
return v:false
|
return v:false
|
||||||
|
|
@ -57,11 +62,14 @@ function! vimspector#internal#neojob#StartDebugSession( config ) abort
|
||||||
try
|
try
|
||||||
let old_env = vimspector#internal#neoterm#PrepareEnvironment(
|
let old_env = vimspector#internal#neoterm#PrepareEnvironment(
|
||||||
\ a:config[ 'env' ] )
|
\ a:config[ 'env' ] )
|
||||||
let s:job = jobstart( a:config[ 'command' ],
|
let s:jobs[ a:session_id ] = jobstart( a:config[ 'command' ],
|
||||||
\ {
|
\ {
|
||||||
\ 'on_stdout': funcref( 's:_OnEvent' ),
|
\ 'on_stdout': funcref( 's:_OnEvent',
|
||||||
\ 'on_stderr': funcref( 's:_OnEvent' ),
|
\ [ a:session_id ] ),
|
||||||
\ 'on_exit': funcref( 's:_OnEvent' ),
|
\ 'on_stderr': funcref( 's:_OnEvent',
|
||||||
|
\ [ a:session_id ] ),
|
||||||
|
\ 'on_exit': funcref( 's:_OnEvent',
|
||||||
|
\ [ a:session_id ] ),
|
||||||
\ 'cwd': a:config[ 'cwd' ],
|
\ 'cwd': a:config[ 'cwd' ],
|
||||||
\ 'env': a:config[ 'env' ],
|
\ 'env': a:config[ 'env' ],
|
||||||
\ }
|
\ }
|
||||||
|
|
@ -78,40 +86,40 @@ function! vimspector#internal#neojob#JobIsRunning( job ) abort
|
||||||
return jobwait( [ a:job ], 0 )[ 0 ] == -1
|
return jobwait( [ a:job ], 0 )[ 0 ] == -1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#neojob#Send( msg ) abort
|
function! vimspector#internal#neojob#Send( session_id, msg ) abort
|
||||||
if ! exists( 's:job' )
|
if ! has_key( s:jobs, a:session_id )
|
||||||
echom "Can't send message: Job was not initialised correctly"
|
echom "Can't send message: Job was not initialised correctly"
|
||||||
redraw
|
redraw
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !vimspector#internal#neojob#JobIsRunning( s:job )
|
if !vimspector#internal#neojob#JobIsRunning( s:jobs[ a:session_id ] )
|
||||||
echom "Can't send message: Job is not running"
|
echom "Can't send message: Job is not running"
|
||||||
redraw
|
redraw
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call chansend( s:job, a:msg )
|
call chansend( s:jobs[ a:session_id ], a:msg )
|
||||||
return 1
|
return 1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#neojob#StopDebugSession() abort
|
function! vimspector#internal#neojob#StopDebugSession( session_id ) abort
|
||||||
if !exists( 's:job' )
|
if !has_key( s:jobs, a:session_id )
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if vimspector#internal#neojob#JobIsRunning( s:job )
|
if vimspector#internal#neojob#JobIsRunning( s:jobs[ a:session_id ] )
|
||||||
echom 'Terminating job'
|
echom 'Terminating job'
|
||||||
redraw
|
redraw
|
||||||
call jobstop( s:job )
|
call jobstop( s:jobs[ a:session_id ] )
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#neojob#Reset() abort
|
function! vimspector#internal#neojob#Reset( session_id ) abort
|
||||||
call vimspector#internal#neojob#StopDebugSession()
|
call vimspector#internal#neojob#StopDebugSession( a:session_id )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:_OnCommandEvent( category, id, data, event ) abort
|
function! s:_OnCommandEvent( session_id, category, id, data, event ) abort
|
||||||
if v:exiting isnot# v:null
|
if v:exiting isnot# v:null
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
@ -121,18 +129,22 @@ function! s:_OnCommandEvent( category, id, data, event ) abort
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !has_key( s:commands, a:category )
|
if ! has_key( s:commands, a:session_id )
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !has_key( s:commands[ a:category ], a:id )
|
if !has_key( s:commands[ a:session_id ], a:category )
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !has_key( s:commands[ a:session_id ][ a:category ], a:id )
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if a:event ==# 'stdout'
|
if a:event ==# 'stdout'
|
||||||
let buffer = s:commands[ a:category ][ a:id ].stdout
|
let buffer = s:commands[ a:session_id ][ a:category ][ a:id ].stdout
|
||||||
elseif a:event ==# 'stderr'
|
elseif a:event ==# 'stderr'
|
||||||
let buffer = s:commands[ a:category ][ a:id ].stderr
|
let buffer = s:commands[ a:session_id ][ a:category ][ a:id ].stderr
|
||||||
endif
|
endif
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -173,6 +185,7 @@ function! s:_OnCommandEvent( category, id, data, event ) abort
|
||||||
elseif a:event ==# 'exit'
|
elseif a:event ==# 'exit'
|
||||||
py3 __import__( "vimspector",
|
py3 __import__( "vimspector",
|
||||||
\ fromlist = [ "utils" ] ).utils.OnCommandWithLogComplete(
|
\ fromlist = [ "utils" ] ).utils.OnCommandWithLogComplete(
|
||||||
|
\ vim.eval( 'a:session_id' ),
|
||||||
\ vim.eval( 'a:category' ),
|
\ vim.eval( 'a:category' ),
|
||||||
\ int( vim.eval( 'a:data' ) ) )
|
\ int( vim.eval( 'a:data' ) ) )
|
||||||
endif
|
endif
|
||||||
|
|
@ -198,11 +211,16 @@ function! s:MakeBufferWritable( buffer ) abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
let s:commands = {}
|
function! vimspector#internal#neojob#StartCommandWithLog(
|
||||||
|
\ session_id,
|
||||||
|
\ cmd,
|
||||||
|
\ category ) abort
|
||||||
|
if ! has_key( s:commands, a:session_id )
|
||||||
|
let s:commands[ a:session_id ] = {}
|
||||||
|
endif
|
||||||
|
|
||||||
function! vimspector#internal#neojob#StartCommandWithLog( cmd, category ) abort
|
if ! has_key( s:commands[ a:session_id ], a:category )
|
||||||
if ! has_key( s:commands, a:category )
|
let s:commands[ a:session_id ][ a:category ] = {}
|
||||||
let s:commands[ a:category ] = {}
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let buf = bufnr( '_vimspector_log_' . a:category, v:true )
|
let buf = bufnr( '_vimspector_log_' . a:category, v:true )
|
||||||
|
|
@ -215,14 +233,14 @@ function! vimspector#internal#neojob#StartCommandWithLog( cmd, category ) abort
|
||||||
let id = jobstart(a:cmd,
|
let id = jobstart(a:cmd,
|
||||||
\ {
|
\ {
|
||||||
\ 'on_stdout': funcref( 's:_OnCommandEvent',
|
\ 'on_stdout': funcref( 's:_OnCommandEvent',
|
||||||
\ [ a:category ] ),
|
\ [ a:session_id, a:category ] ),
|
||||||
\ 'on_stderr': funcref( 's:_OnCommandEvent',
|
\ 'on_stderr': funcref( 's:_OnCommandEvent',
|
||||||
\ [ a:category ] ),
|
\ [ a:session_id, a:category ] ),
|
||||||
\ 'on_exit': funcref( 's:_OnCommandEvent',
|
\ 'on_exit': funcref( 's:_OnCommandEvent',
|
||||||
\ [ a:category ] ),
|
\ [ a:session_id, a:category ] ),
|
||||||
\ } )
|
\ } )
|
||||||
|
|
||||||
let s:commands[ a:category ][ id ] = {
|
let s:commands[ a:session_id ][ a:category ][ id ] = {
|
||||||
\ 'stdout': buf,
|
\ 'stdout': buf,
|
||||||
\ 'stderr': buf
|
\ 'stderr': buf
|
||||||
\ }
|
\ }
|
||||||
|
|
@ -230,19 +248,25 @@ function! vimspector#internal#neojob#StartCommandWithLog( cmd, category ) abort
|
||||||
return buf
|
return buf
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#neojob#CleanUpCommand( category ) abort
|
function! vimspector#internal#neojob#CleanUpCommand(
|
||||||
if ! has_key( s:commands, a:category )
|
\ session_id,
|
||||||
|
\ category ) abort
|
||||||
|
if ! has_key( s:commands, a:session_id )
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
for id in keys( s:commands[ a:category ] )
|
if ! has_key( s:commands[ a:session_id ], a:category )
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
for id in keys( s:commands[ a:session_id ][ a:category ] )
|
||||||
let id = str2nr( id )
|
let id = str2nr( id )
|
||||||
if jobwait( [ id ], 0 )[ 0 ] == -1
|
if jobwait( [ id ], 0 )[ 0 ] == -1
|
||||||
call jobstop( id )
|
call jobstop( id )
|
||||||
endif
|
endif
|
||||||
call jobwait( [ id ], -1 )
|
call jobwait( [ id ], -1 )
|
||||||
endfor
|
endfor
|
||||||
unlet! s:commands[ a:category ]
|
unlet! s:commands[ a:session_id ][ a:category ]
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Boilerplate {{{
|
" Boilerplate {{{
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,11 @@ class DebugAdapterConnection( object ):
|
||||||
|
|
||||||
# TODO/FIXME: This is so messy
|
# TODO/FIXME: This is so messy
|
||||||
expiry_id = vim.eval(
|
expiry_id = vim.eval(
|
||||||
'timer_start( {}, "vimspector#internal#channel#Timeout" )'.format(
|
'timer_start( {}, '
|
||||||
timeout ) )
|
' function( "vimspector#internal#channel#Timeout", '
|
||||||
|
' [ {} ] ) )'.format(
|
||||||
|
timeout,
|
||||||
|
self._handler.session_id ) )
|
||||||
|
|
||||||
request = PendingRequest( msg,
|
request = PendingRequest( msg,
|
||||||
handler,
|
handler,
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,25 @@ VIMSPECTOR_HOME = utils.GetVimspectorBase()
|
||||||
# cache of what the user entered for any option we ask them
|
# cache of what the user entered for any option we ask them
|
||||||
USER_CHOICES = {}
|
USER_CHOICES = {}
|
||||||
|
|
||||||
|
NEXT_SESSION_ID = 0
|
||||||
|
SESSIONS = {}
|
||||||
|
|
||||||
|
|
||||||
|
def PushSession( session ):
|
||||||
|
global NEXT_SESSION_ID
|
||||||
|
this_id = NEXT_SESSION_ID
|
||||||
|
NEXT_SESSION_ID = NEXT_SESSION_ID + 1
|
||||||
|
SESSIONS[ this_id ] = session
|
||||||
|
return this_id
|
||||||
|
|
||||||
|
|
||||||
|
def PopSession( session ):
|
||||||
|
SESSIONS.pop( session.session_id, None )
|
||||||
|
|
||||||
|
|
||||||
class DebugSession( object ):
|
class DebugSession( object ):
|
||||||
def __init__( self, api_prefix ):
|
def __init__( self, api_prefix ):
|
||||||
|
self.session_id = PushSession( self )
|
||||||
self._logger = logging.getLogger( __name__ )
|
self._logger = logging.getLogger( __name__ )
|
||||||
utils.SetUpLogging( self._logger )
|
utils.SetUpLogging( self._logger )
|
||||||
|
|
||||||
|
|
@ -73,6 +89,11 @@ class DebugSession( object ):
|
||||||
|
|
||||||
self._ResetServerState()
|
self._ResetServerState()
|
||||||
|
|
||||||
|
|
||||||
|
def __del__( self ):
|
||||||
|
PopSession( self )
|
||||||
|
|
||||||
|
|
||||||
def _ResetServerState( self ):
|
def _ResetServerState( self ):
|
||||||
self._connection = None
|
self._connection = None
|
||||||
self._init_complete = False
|
self._init_complete = False
|
||||||
|
|
@ -887,8 +908,10 @@ class DebugSession( object ):
|
||||||
|
|
||||||
vim.vars[ '_vimspector_adapter_spec' ] = self._adapter
|
vim.vars[ '_vimspector_adapter_spec' ] = self._adapter
|
||||||
if not vim.eval( "vimspector#internal#{}#StartDebugSession( "
|
if not vim.eval( "vimspector#internal#{}#StartDebugSession( "
|
||||||
|
" {},"
|
||||||
" g:_vimspector_adapter_spec "
|
" g:_vimspector_adapter_spec "
|
||||||
")".format( self._connection_type ) ):
|
")".format( self._connection_type,
|
||||||
|
self.session_id ) ):
|
||||||
self._logger.error( "Unable to start debug server" )
|
self._logger.error( "Unable to start debug server" )
|
||||||
self._splash_screen = utils.DisplaySplash( self._api_prefix,
|
self._splash_screen = utils.DisplaySplash( self._api_prefix,
|
||||||
self._splash_screen,
|
self._splash_screen,
|
||||||
|
|
@ -911,6 +934,7 @@ class DebugSession( object ):
|
||||||
handlers,
|
handlers,
|
||||||
lambda msg: utils.Call(
|
lambda msg: utils.Call(
|
||||||
"vimspector#internal#{}#Send".format( self._connection_type ),
|
"vimspector#internal#{}#Send".format( self._connection_type ),
|
||||||
|
self.session_id,
|
||||||
msg ) )
|
msg ) )
|
||||||
|
|
||||||
self._logger.info( 'Debug Adapter Started' )
|
self._logger.info( 'Debug Adapter Started' )
|
||||||
|
|
@ -933,8 +957,9 @@ class DebugSession( object ):
|
||||||
assert not self._run_on_server_exit
|
assert not self._run_on_server_exit
|
||||||
self._run_on_server_exit = callback
|
self._run_on_server_exit = callback
|
||||||
|
|
||||||
vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format(
|
vim.eval( 'vimspector#internal#{}#StopDebugSession( {} )'.format(
|
||||||
self._connection_type ) )
|
self._connection_type,
|
||||||
|
self.session_id ) )
|
||||||
|
|
||||||
self._connection.DoRequest( handler, {
|
self._connection.DoRequest( handler, {
|
||||||
'command': 'disconnect',
|
'command': 'disconnect',
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ class OutputView( object ):
|
||||||
self._buffers = {}
|
self._buffers = {}
|
||||||
self._api_prefix = api_prefix
|
self._api_prefix = api_prefix
|
||||||
VIEWS.add( self )
|
VIEWS.add( self )
|
||||||
|
# FIXME: hack?
|
||||||
|
self._session_id = hash( self )
|
||||||
|
|
||||||
def Print( self, categroy, text ):
|
def Print( self, categroy, text ):
|
||||||
self._Print( 'server', text.splitlines() )
|
self._Print( 'server', text.splitlines() )
|
||||||
|
|
@ -105,7 +107,7 @@ 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():
|
||||||
if tab_buffer.is_job:
|
if tab_buffer.is_job:
|
||||||
utils.CleanUpCommand( category, self._api_prefix )
|
utils.CleanUpCommand( self._session_id, category, self._api_prefix )
|
||||||
utils.CleanUpHiddenBuffer( tab_buffer.buf )
|
utils.CleanUpHiddenBuffer( tab_buffer.buf )
|
||||||
|
|
||||||
# FIXME: nunmenu the WinBar ?
|
# FIXME: nunmenu the WinBar ?
|
||||||
|
|
@ -174,6 +176,7 @@ class OutputView( object ):
|
||||||
|
|
||||||
if cmd is not None:
|
if cmd is not None:
|
||||||
out = utils.SetUpCommandBuffer(
|
out = utils.SetUpCommandBuffer(
|
||||||
|
self._session_id, # TODO: not really a session id
|
||||||
cmd,
|
cmd,
|
||||||
category,
|
category,
|
||||||
self._api_prefix,
|
self._api_prefix,
|
||||||
|
|
|
||||||
|
|
@ -87,16 +87,21 @@ def OpenFileInCurrentWindow( file_name ):
|
||||||
COMMAND_HANDLERS = {}
|
COMMAND_HANDLERS = {}
|
||||||
|
|
||||||
|
|
||||||
def OnCommandWithLogComplete( name, exit_code ):
|
def OnCommandWithLogComplete( session_id, name, exit_code ):
|
||||||
cb = COMMAND_HANDLERS.get( name )
|
cb = COMMAND_HANDLERS.get( str( session_id ) + '.' + name )
|
||||||
if cb:
|
if cb:
|
||||||
cb( exit_code )
|
cb( exit_code )
|
||||||
|
|
||||||
|
|
||||||
def SetUpCommandBuffer( cmd, name, api_prefix, completion_handler = None ):
|
def SetUpCommandBuffer( session_id,
|
||||||
COMMAND_HANDLERS[ name ] = completion_handler
|
cmd,
|
||||||
|
name,
|
||||||
|
api_prefix,
|
||||||
|
completion_handler = None ):
|
||||||
|
COMMAND_HANDLERS[ str( session_id ) + '.' + name ] = completion_handler
|
||||||
|
|
||||||
buf = Call( f'vimspector#internal#{api_prefix}job#StartCommandWithLog',
|
buf = Call( f'vimspector#internal#{api_prefix}job#StartCommandWithLog',
|
||||||
|
session_id,
|
||||||
cmd,
|
cmd,
|
||||||
name )
|
name )
|
||||||
|
|
||||||
|
|
@ -110,10 +115,12 @@ def SetUpCommandBuffer( cmd, name, api_prefix, completion_handler = None ):
|
||||||
return vim.buffers[ int( buf ) ]
|
return vim.buffers[ int( buf ) ]
|
||||||
|
|
||||||
|
|
||||||
def CleanUpCommand( name, api_prefix ):
|
def CleanUpCommand( session_id, name, api_prefix ):
|
||||||
return vim.eval( 'vimspector#internal#{}job#CleanUpCommand( "{}" )'.format(
|
return vim.eval(
|
||||||
api_prefix,
|
'vimspector#internal#{}job#CleanUpCommand( {}, "{}" )'.format(
|
||||||
name ) )
|
api_prefix,
|
||||||
|
session_id,
|
||||||
|
name ) )
|
||||||
|
|
||||||
|
|
||||||
def CleanUpHiddenBuffer( buf ):
|
def CleanUpHiddenBuffer( buf ):
|
||||||
|
|
|
||||||
|
|
@ -224,9 +224,12 @@ class VariablesView( object ):
|
||||||
'balloonexpr': vim.options[ 'balloonexpr' ],
|
'balloonexpr': vim.options[ 'balloonexpr' ],
|
||||||
'balloondelay': vim.options[ 'balloondelay' ],
|
'balloondelay': vim.options[ 'balloondelay' ],
|
||||||
}
|
}
|
||||||
|
# TODO: How can we make this work. I think we can set ballooneval as a
|
||||||
|
# buffer-local or maybe window-local variable ? We could pass session_id
|
||||||
|
# to the expression here, but still how would it work with 2 concurrent
|
||||||
|
# sessions?
|
||||||
vim.options[ 'balloonexpr' ] = ( "vimspector#internal#"
|
vim.options[ 'balloonexpr' ] = ( "vimspector#internal#"
|
||||||
"balloon#HoverTooltip()" )
|
"balloon#HoverTooltip()" )
|
||||||
|
|
||||||
vim.options[ 'balloondelay' ] = 250
|
vim.options[ 'balloondelay' ] = 250
|
||||||
|
|
||||||
if has_balloon:
|
if has_balloon:
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,9 @@ import os
|
||||||
def Main():
|
def Main():
|
||||||
print( os.environ.get( 'Something', 'ERROR' ) )
|
print( os.environ.get( 'Something', 'ERROR' ) )
|
||||||
print( os.environ.get( 'SomethingElse', 'ERROR' ) )
|
print( os.environ.get( 'SomethingElse', 'ERROR' ) )
|
||||||
|
print( os.environ.get( 'PATH', 'ERROR' ) )
|
||||||
|
|
||||||
for k, v in os.environ:
|
for k, v in os.environ.items():
|
||||||
print( f'{ k } = "{ v }"' )
|
print( f'{ k } = "{ v }"' )
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,3 +107,46 @@ function! Test_Python_Remote_Attach()
|
||||||
lcd -
|
lcd -
|
||||||
%bwipeout!
|
%bwipeout!
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! SetUp_Test_Python_Remote_Attach_With_Run()
|
||||||
|
let g:vimspector_enable_mappings = 'HUMAN'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! Test_Python_Remote_Attach_With_Run()
|
||||||
|
lcd ../support/test/python/simple_python
|
||||||
|
let fn='main.py'
|
||||||
|
exe 'edit ' . fn
|
||||||
|
|
||||||
|
call setpos( '.', [ 0, 6, 1 ] )
|
||||||
|
|
||||||
|
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 6, 1 )
|
||||||
|
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 6 )
|
||||||
|
|
||||||
|
" Add the breakpoint
|
||||||
|
call feedkeys( "\<F9>", 'xt' )
|
||||||
|
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||||
|
\ 6,
|
||||||
|
\ 'vimspectorBP',
|
||||||
|
\ 9 )
|
||||||
|
|
||||||
|
call setpos( '.', [ 0, 1, 1 ] )
|
||||||
|
|
||||||
|
" Here we go. Start Debugging (note will wait up to 10s for the script to do
|
||||||
|
" its virtualenv thing)
|
||||||
|
call vimspector#LaunchWithSettings( {
|
||||||
|
\ 'configuration': 'attach-run',
|
||||||
|
\ } )
|
||||||
|
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 6, 1 )
|
||||||
|
|
||||||
|
" Step
|
||||||
|
call feedkeys( "\<F10>", 'xt' )
|
||||||
|
|
||||||
|
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 7, 1 )
|
||||||
|
call WaitForAssert( {->
|
||||||
|
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 7 )
|
||||||
|
\ } )
|
||||||
|
|
||||||
|
call vimspector#test#setup#Reset()
|
||||||
|
lcd -
|
||||||
|
%bwipeout!
|
||||||
|
endfunction
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue