Add neovim job/terminal APIs
This commit is contained in:
parent
18627b9244
commit
29c26996fb
5 changed files with 237 additions and 2 deletions
163
autoload/vimspector/internal/neojob.vim
Normal file
163
autoload/vimspector/internal/neojob.vim
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
" vimspector - A multi-language debugging system for Vim
|
||||
" Copyright 2018 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.
|
||||
|
||||
|
||||
" Boilerplate {{{
|
||||
let s:save_cpo = &cpoptions
|
||||
set cpoptions&vim
|
||||
" }}}
|
||||
|
||||
|
||||
|
||||
function! s:_OnEvent( chan_id, data, event ) abort
|
||||
" In neovim, the data argument is a list.
|
||||
if a:event ==# 'stdout'
|
||||
py3 _vimspector_session.OnChannelData( '\n'.join( vim.eval( 'a:data' ) ) )
|
||||
elseif a:event ==# 'stderr'
|
||||
py3 _vimspector_session.OnServerStderr( '\n'.join( vim.eval( 'a:data' ) ) )
|
||||
elseif a:event ==# 'exit'
|
||||
echom 'Channel exit with status ' . a:data
|
||||
redraw
|
||||
unlet s:job
|
||||
py3 _vimspector_session.OnServerExit( vim.eval( 'a:data' ) )
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#neojob#StartDebugSession( config ) abort
|
||||
if exists( 's:job' )
|
||||
echom 'Not starging: Job is already running'
|
||||
redraw
|
||||
return v:false
|
||||
endif
|
||||
|
||||
let s:job = jobstart( a:config[ 'command' ],
|
||||
\ {
|
||||
\ 'on_stdout': funcref( 's:_OnEvent' ),
|
||||
\ 'on_stderr': funcref( 's:_OnEvent' ),
|
||||
\ 'on_exit': funcref( 's:_OnEvent' ),
|
||||
\ 'cwd': a:config[ 'cwd' ],
|
||||
\ }
|
||||
\ )
|
||||
|
||||
" FIXME: Missing in neovim 0.4. But in master:
|
||||
" \ 'env': a:config[ 'env' ],
|
||||
"
|
||||
|
||||
" FIXME: error handling ?
|
||||
return v:true
|
||||
endfunction
|
||||
|
||||
function! s:JobIsRunning( job ) abort
|
||||
return jobwait( [ s:job ], 0 )[ 0 ] == -1
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#neojob#Send( msg ) abort
|
||||
if ! exists( 's:job' )
|
||||
echom "Can't send message: Job was not initialised correctly"
|
||||
redraw
|
||||
return 0
|
||||
endif
|
||||
|
||||
if !s:JobIsRunning( s:job )
|
||||
echom "Can't send message: Job is not running"
|
||||
redraw
|
||||
return 0
|
||||
endif
|
||||
|
||||
call chansend( s:job, a:msg )
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#neojob#StopDebugSession() abort
|
||||
if !exists( 's:job' )
|
||||
echom "Not stopping session: Job doesn't exist"
|
||||
redraw
|
||||
return
|
||||
endif
|
||||
|
||||
if s:JobIsRunning( s:job )
|
||||
echom 'Terminating job'
|
||||
redraw
|
||||
call jobstop( s:job )
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#neojob#Reset() abort
|
||||
call vimspector#internal#neojob#StopDebugSession()
|
||||
endfunction
|
||||
|
||||
function! s:_OnCommandEvent( category, id, data, event ) abort
|
||||
if a:data == ['']
|
||||
return
|
||||
endif
|
||||
if a:event ==# 'stdout'
|
||||
let buffer = s:commands[ a:category ][ a:id ].stdout
|
||||
elseif a:event ==# 'stderr'
|
||||
let buffer = s:commands[ a:category ][ a:id ].stderr
|
||||
endif
|
||||
|
||||
let last_line_list = getbufline( buffer, '$' )
|
||||
if len( last_line_list ) == 0
|
||||
let last_line = ''
|
||||
else
|
||||
let last_line = last_line_list[ 0 ]
|
||||
endif
|
||||
|
||||
call setbufline( buffer, '$', last_line . a:data[ 0 ] )
|
||||
call appendbufline( buffer, '$', a:data[ 1: ] )
|
||||
endfunction
|
||||
|
||||
let s:commands = {}
|
||||
|
||||
function! vimspector#internal#neojob#StartCommandWithLog( cmd, category ) abort
|
||||
if ! has_key( s:commands, a:category )
|
||||
let s:commands[ a:category ] = {}
|
||||
endif
|
||||
|
||||
let stdout_buf = bufnr( '_vimspector_log_' . a:category . '_out', 1 )
|
||||
let stderr_buf = bufnr( '_vimspector_log_' . a:category . '_err', 1 )
|
||||
|
||||
let id = jobstart(a:cmd,
|
||||
\ {
|
||||
\ 'on_stdout': funcref( 's:_OnCommandEvent',
|
||||
\ [ a:category ] ),
|
||||
\ 'on_stderr': funcref( 's:_OnCommandEvent',
|
||||
\ [ a:category ] )
|
||||
\ } )
|
||||
|
||||
let s:commands[ a:category ][ id ] = {
|
||||
\ 'stdout': stdout_buf,
|
||||
\ 'stderr': stderr_buf
|
||||
\ }
|
||||
|
||||
return [ stdout_buf, stderr_buf ]
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#neojob#CleanUpCommand( category ) abort
|
||||
if ! has_key( s:commands, a:category )
|
||||
return
|
||||
endif
|
||||
|
||||
for id in keys( s:commands[ a:category ] )
|
||||
call jobstop( id )
|
||||
call jobwait( id )
|
||||
endfor
|
||||
unlet! s:commands[ a:category ]
|
||||
endfunction
|
||||
|
||||
" Boilerplate {{{
|
||||
let &cpoptions=s:save_cpo
|
||||
unlet s:save_cpo
|
||||
" }}}
|
||||
67
autoload/vimspector/internal/neoterm.vim
Normal file
67
autoload/vimspector/internal/neoterm.vim
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
" vimspector - A multi-language debugging system for Vim
|
||||
" Copyright 2018 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.
|
||||
|
||||
|
||||
" Boilerplate {{{
|
||||
let s:save_cpo = &cpoptions
|
||||
set cpoptions&vim
|
||||
" }}}
|
||||
|
||||
" Ids are unique throughtout the life of neovim, but obviously buffer numbers
|
||||
" aren't
|
||||
"
|
||||
" FIXME: Tidy this map when buffers are closed ?
|
||||
let s:buffer_to_id = {}
|
||||
|
||||
function! vimspector#internal#neoterm#Start( cmd, opts ) abort
|
||||
if ! get( a:opts, 'curwin', 0 )
|
||||
if get( a:opts, 'vertical', 0 )
|
||||
vsplit
|
||||
else
|
||||
split
|
||||
endif
|
||||
endif
|
||||
|
||||
" FIXME: 'env' doesn't work
|
||||
let id = termopen( a:cmd, { 'cwd': a:opts[ 'cwd' ] } )
|
||||
let bufnr = bufnr()
|
||||
let s:buffer_to_id[ bufnr ] = id
|
||||
return bufnr
|
||||
endfunction
|
||||
|
||||
function! s:JobIsRunning( job ) abort
|
||||
return jobwait( [ a:job ], 0 )[ 0 ] == -1
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#neoterm#IsFinished( bufno ) abort
|
||||
if !has_key( s:buffer_to_id, a:bufno )
|
||||
return v:true
|
||||
endif
|
||||
|
||||
return !s:JobIsRunning( s:buffer_to_id[ a:bufno ] )
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#neoterm#GetPID( bufno ) abort
|
||||
if !has_key( s:buffer_to_id, a:bufno )
|
||||
return -1
|
||||
endif
|
||||
|
||||
return jobpid( s:buffer_to_id[ a:bufno ] )
|
||||
endfunction
|
||||
|
||||
" Boilerplate {{{
|
||||
let &cpoptions=s:save_cpo
|
||||
unlet s:save_cpo
|
||||
" }}}
|
||||
|
|
@ -19,8 +19,13 @@ let s:save_cpo = &cpoptions
|
|||
set cpoptions&vim
|
||||
" }}}
|
||||
|
||||
let s:is_neovim = has( 'nvim' )
|
||||
|
||||
function! vimspector#internal#state#Reset() abort
|
||||
let prefix = ''
|
||||
if s:is_neovim
|
||||
let prefix='neo'
|
||||
endif
|
||||
py3 << EOF
|
||||
from vimspector import debug_session
|
||||
_vimspector_session = debug_session.DebugSession( vim.eval( 'prefix' ) )
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ class OutputView( object ):
|
|||
vim.command( 'bdelete! {0}'.format( tab_buffer.buf.number ) )
|
||||
except vim.error as e:
|
||||
# FIXME: For now just ignore the "no buffers were deleted" error
|
||||
if 'E516' not in e:
|
||||
if 'E516' not in str( e ):
|
||||
raise
|
||||
|
||||
self._buffers = {}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ def SetUpHiddenBuffer( buf, name ):
|
|||
def SetUpPromptBuffer( buf, name, prompt, callback, hidden=False ):
|
||||
# This feature is _super_ new, so only enable when available
|
||||
if not int( vim.eval( "exists( '*prompt_setprompt' )" ) ):
|
||||
return SetUpScratchBuffer( buf, name )
|
||||
return SetUpHiddenBuffer( buf, name )
|
||||
|
||||
buf.options[ 'buftype' ] = 'prompt'
|
||||
buf.options[ 'swapfile' ] = False
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue