Support channel-based adapters with jobs in neovim

Again, the neovim API is lacking - we have to hack around our own retry
loop (where vim offers 'waittime').

Note neovim documentation says that it returns 0 on connection failure,
but actually it throws an error, so we catch that. There are probably a
ton of other problems with error handling, but i'll rely on user
testing/feedback for that.
This commit is contained in:
Ben Jackson 2020-07-06 10:34:16 +01:00
commit 32c7960b5f
3 changed files with 58 additions and 23 deletions

View file

@ -67,7 +67,7 @@ function! vimspector#internal#channel#StartDebugSession( config ) abort
\ )
if ch_status( s:ch ) !=# 'open'
echom 'Unable to connect to debug adapter'
echom 'Unable to connect to' l:addr
redraw
return v:false
endif
@ -96,8 +96,10 @@ function! vimspector#internal#channel#StopDebugSession() abort
call s:_OnClose( s:ch )
endif
if exists( 's:job' ) && job_status( s:job ) ==# 'run'
call job_stop( s:job, 'kill' )
if exists( 's:job' )
if job_status( s:job ) ==# 'run'
call job_stop( s:job, 'kill' )
endif
unlet s:job
endif
endfunction

View file

@ -34,20 +34,50 @@ endfunction
function! vimspector#internal#neochannel#StartDebugSession( config ) abort
if exists( 's:ch' )
echom 'Not starging: Channel is already running'
echom 'Not starting: Channel is already running'
redraw
return v:false
endif
let l:addr = get( a:config, 'host', 'localhost' ) . ':' . a:config[ 'port' ]
let s:ch = sockconnect( 'tcp', addr, { 'on_data': funcref( 's:_OnEvent' ) } )
if s:ch <= 0
unlet s:ch
return v:false
" 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 old_env={}
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' ],
\ }
\ )
finally
call vimspector#internal#neoterm#ResetEnvironment( a:config[ 'env' ],
\ old_env )
endtry
endif
return v:true
let l:addr = get( a:config, 'host', 'localhost' ) . ':' . a:config[ 'port' ]
let attempt = 1
while attempt <= 10
echo 'Connecting to ' . l:addr . '... (attempt' attempt 'of 10)'
try
let s:ch = sockconnect( 'tcp',
\ addr,
\ { 'on_data': funcref( 's:_OnEvent' ) } )
redraw
return v:true
catch /connection refused/
sleep 1
endtry
let attempt += 1
endwhile
echom 'Unable to connect to' l:addr 'after 10 attempts'
redraw
return v:false
endfunction
function! vimspector#internal#neochannel#Send( msg ) abort
@ -62,16 +92,19 @@ function! vimspector#internal#neochannel#Send( msg ) abort
endfunction
function! vimspector#internal#neochannel#StopDebugSession() abort
if !exists( 's:ch' )
echom "Not stopping session: Channel doesn't exist"
redraw
return
if exists( 's:ch' )
call chanclose( s:ch )
" 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' )
endif
call chanclose( s:ch )
" 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' )
if exists( 's:job' )
if vimspector#internal#neojob#JobIsRunning( s:job )
call jobstop( s:job )
endif
unlet s:job
endif
endfunction
function! vimspector#internal#neochannel#Reset() abort

View file

@ -70,8 +70,8 @@ function! vimspector#internal#neojob#StartDebugSession( config ) abort
return v:true
endfunction
function! s:JobIsRunning( job ) abort
return jobwait( [ s:job ], 0 )[ 0 ] == -1
function! vimspector#internal#neojob#JobIsRunning( job ) abort
return jobwait( [ a:job ], 0 )[ 0 ] == -1
endfunction
function! vimspector#internal#neojob#Send( msg ) abort
@ -81,7 +81,7 @@ function! vimspector#internal#neojob#Send( msg ) abort
return 0
endif
if !s:JobIsRunning( s:job )
if !vimspector#internal#neojob#JobIsRunning( s:job )
echom "Can't send message: Job is not running"
redraw
return 0
@ -96,7 +96,7 @@ function! vimspector#internal#neojob#StopDebugSession() abort
return
endif
if s:JobIsRunning( s:job )
if vimspector#internal#neojob#JobIsRunning( s:job )
echom 'Terminating job'
redraw
call jobstop( s:job )