Add a session ID to debug_session - vim only for now

This commit is contained in:
Ben Jackson 2020-12-03 20:42:32 +00:00
commit fb2bad216f
11 changed files with 320 additions and 156 deletions

View file

@ -19,8 +19,12 @@ let s:save_cpo = &cpoptions
set cpoptions&vim
" }}}
function! s:_OnServerData( channel, data ) abort
if !exists( 's:ch' ) || s:ch isnot a:channel
let s:channels = {}
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
endif
@ -29,20 +33,23 @@ _vimspector_session.OnChannelData( vim.eval( 'a:data' ) )
EOF
endfunction
function! s:_OnClose( channel ) abort
if !exists( 's:ch' ) || s:ch isnot a:channel
function! s:_OnClose( session_id, channel ) abort
if !has_key( s:channels, a:session_id ) ||
\ s:channels[ a:session_id ] isnot a:channel
return
endif
echom 'Channel closed'
redraw
unlet s:ch
unlet s:channels[ a:session_id ]
py3 _vimspector_session.OnServerExit( 0 )
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'
return v:false
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
" servers which start up and listen on some port
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',
\ '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' ]
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',
\ 'callback': funcref( 's:_OnServerData' ),
\ 'close_cb': funcref( 's:_OnClose' ),
\ 'callback': funcref( 's:_OnServerData',
\ [ a:session_id ] ),
\ 'close_cb': funcref( 's:_OnClose',
\ [ a:session_id ] ),
\ 'waittime': 10000,
\ }
\ )
if ch_status( s:ch ) !=# 'open'
if ch_status( s:channels[ a:session_id ] ) !=# 'open'
echom 'Unable to connect to' l:addr
redraw
return v:false
@ -83,62 +93,68 @@ function! vimspector#internal#channel#StartDebugSession( config ) abort
return v:true
endfunction
function! vimspector#internal#channel#Send( msg ) abort
call ch_sendraw( s:ch, a:msg )
function! vimspector#internal#channel#Send( session_id, msg ) abort
call ch_sendraw( s:channels[ a:session_id ], a:msg )
return 1
endfunction
function! vimspector#internal#channel#Timeout( id ) abort
function! vimspector#internal#channel#Timeout( session_id, id ) abort
py3 << EOF
_vimspector_session.OnRequestTimeout( vim.eval( 'a:id' ) )
EOF
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
" from the socket
if job_status( s:job ) ==# 'run'
call job_stop( s:job, 'term' )
let job = s:jobs[ a:session_id ]
if job_status( job ) ==# 'run'
call job_stop( job, 'term' )
endif
while job_status( s:job ) ==# 'run'
call job_stop( s:job, 'kill' )
while job_status( job ) ==# 'run'
call job_stop( job, 'kill' )
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
" close callback, so remove the automatic close callback to avoid tricky
" re-entrancy
call ch_setoptions( s:ch, { 'close_cb': '' } )
call ch_setoptions( s:channels[ a:session_id ], { 'close_cb': '' } )
endif
elseif exists( 's:ch' ) &&
\ count( [ 'closed', 'fail' ], ch_status( s:ch ) ) == 0
elseif s:_ChannelExists( a:session_id )
" channel is open, close it and trigger the callback. The callback is _not_
" triggered when manually calling ch_close. if we get here and the channel
" is not open, then we there is a _OnClose callback waiting for us, so do
" nothing.
call ch_close( s:ch )
call ch_close( s:channels[ a:session_id ] )
endif
" block until we've read all data from the socket and handled it.
while count( [ 'open', 'buffered' ], ch_status( s:ch ) ) == 1
let data = ch_read( s:ch, { 'timeout': 10 } )
call s:_OnServerData( s:ch, data )
while has_key( s:channels, a:session_id ) &&
\ count( [ 'open', 'buffered' ],
\ 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
call s:_OnClose( s:ch )
if has_key( s:channels, a:session_id )
call s:_OnClose( s:channels[ a:session_id ] )
endif
endfunction
function! vimspector#internal#channel#Reset() abort
if exists( 's:ch' ) || exists( 's:job' )
call vimspector#internal#channel#StopDebugSession()
endif
function! vimspector#internal#channel#Reset( session_id ) abort
call vimspector#internal#channel#StopDebugSession( a:session_id )
endfunction
" Boilerplate {{{

View file

@ -19,8 +19,12 @@ let s:save_cpo = &cpoptions
set cpoptions&vim
" }}}
function! s:_OnServerData( channel, data ) abort
if !exists( 's:job' ) || ch_getjob( a:channel ) isnot s:job
let s:jobs = {}
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' )
return
endif
@ -28,8 +32,9 @@ function! s:_OnServerData( channel, data ) abort
py3 _vimspector_session.OnChannelData( vim.eval( 'a:data' ) )
endfunction
function! s:_OnServerError( channel, data ) abort
if !exists( 's:job' ) || ch_getjob( a:channel ) isnot s:job
function! s:_OnServerError( 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' )
return
endif
@ -41,22 +46,24 @@ endfunction
" FIXME: We should wait until both the exit_cb _and_ the channel closed callback
" have been received before OnServerExit?
function! s:_OnExit( channel, status ) abort
if !exists( 's:job' ) || ch_getjob( a:channel ) isnot s:job
function! s:_OnExit( session_id, channel, status ) abort
if !has_key( s:jobs, a:session_id ) ||
\ ch_getjob( a:channel ) isnot s:jobs[ a:session_id ]
call ch_log( 'Unexpected exit callback' )
return
endif
echom 'Channel exit with status ' . a:status
redraw
if exists( 's:job' )
unlet s:job
if has_key( s:jobs, a:session_id )
unlet s:jobs[ a:session_id ]
endif
py3 _vimspector_session.OnServerExit( vim.eval( 'a:status' ) )
endfunction
function! s:_OnClose( channel ) abort
if !exists( 's:job' ) || job_getchannel( s:job ) != a:channel
function! s:_OnClose( session_id, channel ) abort
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' )
return
endif
@ -65,34 +72,38 @@ function! s:_OnClose( channel ) abort
redraw
endfunction
function! vimspector#internal#job#StartDebugSession( config ) abort
if exists( 's:job' )
function! vimspector#internal#job#StartDebugSession( session_id, config ) abort
if has_key( s:jobs, a:session_id )
echom 'Not starting: Job is already running'
redraw
return v:false
endif
let s:job = job_start( a:config[ 'command' ],
let s:jobs[ a:session_id ] = job_start( a:config[ 'command' ],
\ {
\ 'in_mode': 'raw',
\ 'out_mode': 'raw',
\ 'err_mode': 'raw',
\ 'exit_cb': funcref( 's:_OnExit' ),
\ 'close_cb': funcref( 's:_OnClose' ),
\ 'out_cb': funcref( 's:_OnServerData' ),
\ 'err_cb': funcref( 's:_OnServerError' ),
\ 'exit_cb': funcref( 's:_OnExit',
\ [ a:session_id ] ),
\ 'close_cb': funcref( 's:_OnClose',
\ [ a:session_id ] ),
\ 'out_cb': funcref( 's:_OnServerData',
\ [ a:session_id ] ),
\ 'err_cb': funcref( 's:_OnServerError',
\ [ a:session_id ] ),
\ 'stoponexit': 'term',
\ 'env': a:config[ 'env' ],
\ '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
return v:false
endif
let status = job_status( s:job )
let status = job_status( s:jobs[ a:session_id ] )
echom 'Started job, status is: ' . status
redraw
@ -104,20 +115,22 @@ function! vimspector#internal#job#StartDebugSession( config ) abort
return v:true
endfunction
function! vimspector#internal#job#Send( msg ) abort
if ! exists( 's:job' )
function! vimspector#internal#job#Send( session_id, msg ) abort
if ! has_key( s:jobs, a:session_id )
echom "Can't send message: Job was not initialised correctly"
redraw
return 0
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"
redraw
return 0
endif
let ch = job_getchannel( s:job )
let ch = job_getchannel( job )
if ch ==# 'channel fail'
echom 'Channel was closed unexpectedly!'
redraw
@ -128,45 +141,55 @@ function! vimspector#internal#job#Send( msg ) abort
return 1
endfunction
function! vimspector#internal#job#StopDebugSession() abort
if !exists( 's:job' )
function! vimspector#internal#job#StopDebugSession( session_id ) abort
if ! has_key( s:jobs, a:session_id )
echom "Not stopping session: Job doesn't exist"
redraw
return
endif
if job_status( s:job ) ==# 'run'
let job = s:jobs[ a:session_id ]
if job_status( job ) ==# 'run'
echom 'Terminating job'
redraw
call job_stop( s:job, 'kill' )
call job_stop( job, 'kill' )
endif
endfunction
function! vimspector#internal#job#Reset() abort
call vimspector#internal#job#StopDebugSession()
function! vimspector#internal#job#Reset( session_id ) abort
call vimspector#internal#job#StopDebugSession( a:session_id )
endfunction
function! s:_OnCommandExit( category, ch, code ) abort
function! s:_OnCommandExit( session_id, category, ch, code ) abort
py3 __import__( "vimspector",
\ fromlist = [ "utils" ] ).utils.OnCommandWithLogComplete(
\ vim.eval( 'a:session_id' ),
\ vim.eval( 'a:category' ),
\ int( vim.eval( 'a:code' ) ) )
endfunction
function! vimspector#internal#job#StartCommandWithLog( cmd, category ) abort
function! vimspector#internal#job#StartCommandWithLog(
\ session_id,
\ cmd,
\ category ) abort
if ! exists( 's:commands' )
let s:commands = {}
endif
if ! has_key( s:commands, a:category )
let s:commands[ a:category ] = []
if ! has_key( s:commands, a:session_id )
let s:commands[ a:session_id ] = {}
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,
\ {
\ 'out_io': 'buffer',
@ -175,13 +198,14 @@ function! vimspector#internal#job#StartCommandWithLog( cmd, category ) abort
\ 'err_msg': 0,
\ 'out_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,
\ 'err_modifiable': 0,
\ '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 )
redraw
return v:none
@ -191,19 +215,27 @@ function! vimspector#internal#job#StartCommandWithLog( cmd, category ) abort
endfunction
function! vimspector#internal#job#CleanUpCommand( category ) abort
function! vimspector#internal#job#CleanUpCommand( session_id, category ) abort
if ! exists( 's:commands' )
let s:commands = {}
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
endif
for j in s:commands[ a:category ]
for j in s:commands[ a:session_id ][ a:category ]
call job_stop( j, 'kill' )
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
" Boilerplate {{{

View file

@ -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
return
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
endif
if a:data == ['']
echom 'Channel closed'
redraw
unlet s:ch
unlet s:channels[ a:session_id ]
py3 _vimspector_session.OnServerExit( 0 )
else
py3 _vimspector_session.OnChannelData( '\n'.join( vim.eval( 'a:data' ) ) )
endif
endfunction
function! vimspector#internal#neochannel#StartDebugSession( config ) abort
if exists( 's:ch' )
function! vimspector#internal#neochannel#StartDebugSession(
\ session_id,
\ config ) abort
if has_key( s:channels, a:session_id )
echom 'Not starting: Channel is already running'
redraw
return v:false
@ -54,12 +60,12 @@ function! vimspector#internal#neochannel#StartDebugSession( config ) abort
try
let old_env = vimspector#internal#neoterm#PrepareEnvironment(
\ a:config[ 'env' ] )
let s:job = jobstart( a:config[ 'command' ],
\ {
\ 'cwd': a:config[ 'cwd' ],
\ 'env': a:config[ 'env' ],
\ }
\ )
let s:jobs[ a:session_id ] = jobstart( a:config[ 'command' ],
\ {
\ 'cwd': a:config[ 'cwd' ],
\ 'env': a:config[ 'env' ],
\ }
\ )
finally
call vimspector#internal#neoterm#ResetEnvironment( a:config[ 'env' ],
\ old_env )
@ -72,9 +78,10 @@ function! vimspector#internal#neochannel#StartDebugSession( config ) abort
while attempt <= 10
echo 'Connecting to ' . l:addr . '... (attempt' attempt 'of 10)'
try
let s:ch = sockconnect( 'tcp',
\ addr,
\ { 'on_data': funcref( 's:_OnEvent' ) } )
let s:channels[ a:session_id ] = sockconnect(
\ 'tcp',
\ addr,
\ { 'on_data': funcref( 's:_OnEvent', [ a:session_id ] ) } )
redraw
return v:true
catch /connection refused/
@ -88,30 +95,30 @@ function! vimspector#internal#neochannel#StartDebugSession( config ) abort
return v:false
endfunction
function! vimspector#internal#neochannel#Send( msg ) abort
if ! exists( 's:ch' )
function! vimspector#internal#neochannel#Send( session_id, msg ) abort
if ! has_key( s:channels, a:session_id )
echom "Can't send message: Channel was not initialised correctly"
redraw
return 0
endif
call chansend( s:ch, a:msg )
call chansend( s:channels[ a:session_id ], a:msg )
return 1
endfunction
function! vimspector#internal#neochannel#StopDebugSession() abort
if exists( 's:ch' )
call chanclose( s:ch )
function! vimspector#internal#neochannel#StopDebugSession( session_id ) abort
if has_key( s:channels, a:session_id )
call chanclose( s:channels[ a:session_id ] )
" It doesn't look like we get a callback after chanclos. Who knows if we
" will subsequently receive data callbacks.
call s:_OnEvent( s:ch, [ '' ], 'data' )
call s:_OnEvent( a:session_id, s:channels[ a:session_id ], [ '' ], 'data' )
endif
if exists( 's:job' )
if vimspector#internal#neojob#JobIsRunning( s:job )
call jobstop( s:job )
if has_key( s:jobs, a:session_id )
if vimspector#internal#neojob#JobIsRunning( s:jobs[ a:session_id ] )
call jobstop( s:jobs[ a:session_id ] )
endif
unlet s:job
unlet s:jobs[ a:session_id ]
endif
endfunction

View file

@ -19,14 +19,17 @@ let s:save_cpo = &cpoptions
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
return
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
endif
@ -38,13 +41,15 @@ function! s:_OnEvent( chan_id, data, event ) abort
elseif a:event ==# 'exit'
echom 'Channel exit with status ' . a:data
redraw
unlet s:job
unlet s:jobs[ a:session_id ]
py3 _vimspector_session.OnServerExit( vim.eval( 'a:data' ) )
endif
endfunction
function! vimspector#internal#neojob#StartDebugSession( config ) abort
if exists( 's:job' )
function! vimspector#internal#neojob#StartDebugSession(
\ session_id,
\ config ) abort
if has_key( s:jobs, a:session_id )
echom 'Not starging: Job is already running'
redraw
return v:false
@ -57,11 +62,14 @@ function! vimspector#internal#neojob#StartDebugSession( config ) abort
try
let old_env = vimspector#internal#neoterm#PrepareEnvironment(
\ 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_stderr': funcref( 's:_OnEvent' ),
\ 'on_exit': funcref( 's:_OnEvent' ),
\ 'on_stdout': funcref( 's:_OnEvent',
\ [ a:session_id ] ),
\ 'on_stderr': funcref( 's:_OnEvent',
\ [ a:session_id ] ),
\ 'on_exit': funcref( 's:_OnEvent',
\ [ a:session_id ] ),
\ 'cwd': a:config[ 'cwd' ],
\ 'env': a:config[ 'env' ],
\ }
@ -78,40 +86,40 @@ function! vimspector#internal#neojob#JobIsRunning( job ) abort
return jobwait( [ a:job ], 0 )[ 0 ] == -1
endfunction
function! vimspector#internal#neojob#Send( msg ) abort
if ! exists( 's:job' )
function! vimspector#internal#neojob#Send( session_id, msg ) abort
if ! has_key( s:jobs, a:session_id )
echom "Can't send message: Job was not initialised correctly"
redraw
return 0
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"
redraw
return 0
endif
call chansend( s:job, a:msg )
call chansend( s:jobs[ a:session_id ], a:msg )
return 1
endfunction
function! vimspector#internal#neojob#StopDebugSession() abort
if !exists( 's:job' )
function! vimspector#internal#neojob#StopDebugSession( session_id ) abort
if !has_key( s:jobs, a:session_id )
return
endif
if vimspector#internal#neojob#JobIsRunning( s:job )
if vimspector#internal#neojob#JobIsRunning( s:jobs[ a:session_id ] )
echom 'Terminating job'
redraw
call jobstop( s:job )
call jobstop( s:jobs[ a:session_id ] )
endif
endfunction
function! vimspector#internal#neojob#Reset() abort
call vimspector#internal#neojob#StopDebugSession()
function! vimspector#internal#neojob#Reset( session_id ) abort
call vimspector#internal#neojob#StopDebugSession( a:session_id )
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
return
endif
@ -121,18 +129,22 @@ function! s:_OnCommandEvent( category, id, data, event ) abort
return
endif
if !has_key( s:commands, a:category )
if ! has_key( s:commands, a:session_id )
return
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
endif
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'
let buffer = s:commands[ a:category ][ a:id ].stderr
let buffer = s:commands[ a:session_id ][ a:category ][ a:id ].stderr
endif
try
@ -173,6 +185,7 @@ function! s:_OnCommandEvent( category, id, data, event ) abort
elseif a:event ==# 'exit'
py3 __import__( "vimspector",
\ fromlist = [ "utils" ] ).utils.OnCommandWithLogComplete(
\ vim.eval( 'a:session_id' ),
\ vim.eval( 'a:category' ),
\ int( vim.eval( 'a:data' ) ) )
endif
@ -198,11 +211,16 @@ function! s:MakeBufferWritable( buffer ) abort
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:category )
let 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 = bufnr( '_vimspector_log_' . a:category, v:true )
@ -215,14 +233,14 @@ function! vimspector#internal#neojob#StartCommandWithLog( cmd, category ) abort
let id = jobstart(a:cmd,
\ {
\ 'on_stdout': funcref( 's:_OnCommandEvent',
\ [ a:category ] ),
\ [ a:session_id, a:category ] ),
\ 'on_stderr': funcref( 's:_OnCommandEvent',
\ [ a:category ] ),
\ [ a:session_id, a:category ] ),
\ '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,
\ 'stderr': buf
\ }
@ -230,19 +248,25 @@ function! vimspector#internal#neojob#StartCommandWithLog( cmd, category ) abort
return buf
endfunction
function! vimspector#internal#neojob#CleanUpCommand( category ) abort
if ! has_key( s:commands, a:category )
function! vimspector#internal#neojob#CleanUpCommand(
\ session_id,
\ category ) abort
if ! has_key( s:commands, a:session_id )
return
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 )
if jobwait( [ id ], 0 )[ 0 ] == -1
call jobstop( id )
endif
call jobwait( [ id ], -1 )
endfor
unlet! s:commands[ a:category ]
unlet! s:commands[ a:session_id ][ a:category ]
endfunction
" Boilerplate {{{