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

View file

@ -34,20 +34,50 @@ endfunction
function! vimspector#internal#neochannel#StartDebugSession( config ) abort function! vimspector#internal#neochannel#StartDebugSession( config ) abort
if exists( 's:ch' ) if exists( 's:ch' )
echom 'Not starging: Channel is already running' echom 'Not starting: Channel is already running'
redraw redraw
return v:false return v:false
endif endif
let l:addr = get( a:config, 'host', 'localhost' ) . ':' . a:config[ 'port' ] " If we _also_ have a command line, then start the actual job. This allows for
" servers which start up and listen on some port
let s:ch = sockconnect( 'tcp', addr, { 'on_data': funcref( 's:_OnEvent' ) } ) if has_key( a:config, 'command' )
if s:ch <= 0 let old_env={}
unlet s:ch try
return v:false 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 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 endfunction
function! vimspector#internal#neochannel#Send( msg ) abort function! vimspector#internal#neochannel#Send( msg ) abort
@ -62,16 +92,19 @@ function! vimspector#internal#neochannel#Send( msg ) abort
endfunction endfunction
function! vimspector#internal#neochannel#StopDebugSession() abort function! vimspector#internal#neochannel#StopDebugSession() abort
if !exists( 's:ch' ) if exists( 's:ch' )
echom "Not stopping session: Channel doesn't exist" call chanclose( s:ch )
redraw " It doesn't look like we get a callback after chanclos. Who knows if we
return " will subsequently receive data callbacks.
call s:_OnEvent( s:ch, [ '' ], 'data' )
endif endif
call chanclose( s:ch ) if exists( 's:job' )
" It doesn't look like we get a callback after chanclos. Who knows if we will if vimspector#internal#neojob#JobIsRunning( s:job )
" subsequently receive data callbacks. call jobstop( s:job )
call s:_OnEvent( s:ch, [ '' ], 'data' ) endif
unlet s:job
endif
endfunction endfunction
function! vimspector#internal#neochannel#Reset() abort function! vimspector#internal#neochannel#Reset() abort

View file

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