diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 1dd22f1..8ad19e2 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -20,29 +20,47 @@ set cpoptions&vim " }}} -call vimspector#internal#state#Reset() +let s:enabled = vimspector#internal#state#Reset() function! vimspector#Launch() abort + if !s:enabled + return + endif py3 _vimspector_session.Start() endfunction function! vimspector#LaunchWithSettings( settings ) abort + if !s:enabled + return + endif py3 _vimspector_session.Start( launch_variables = vim.eval( 'a:settings' ) ) endfunction function! vimspector#Reset() abort + if !s:enabled + return + endif py3 _vimspector_session.Reset() endfunction function! vimspector#Restart() abort + if !s:enabled + return + endif py3 _vimspector_session.Restart() endfunction function! vimspector#ClearBreakpoints() abort + if !s:enabled + return + endif py3 _vimspector_session.ClearBreakpoints() endfunction function! vimspector#ToggleBreakpoint( ... ) abort + if !s:enabled + return + endif if a:0 == 0 let options = {} else @@ -52,6 +70,9 @@ function! vimspector#ToggleBreakpoint( ... ) abort endfunction function! vimspector#AddFunctionBreakpoint( function, ... ) abort + if !s:enabled + return + endif if a:0 == 0 let options = {} else @@ -62,42 +83,72 @@ function! vimspector#AddFunctionBreakpoint( function, ... ) abort endfunction function! vimspector#StepOver() abort + if !s:enabled + return + endif py3 _vimspector_session.StepOver() endfunction function! vimspector#StepInto() abort + if !s:enabled + return + endif py3 _vimspector_session.StepInto() endfunction function! vimspector#StepOut() abort + if !s:enabled + return + endif py3 _vimspector_session.StepOut() endfunction function! vimspector#Continue() abort + if !s:enabled + return + endif py3 _vimspector_session.Continue() endfunction function! vimspector#Pause() abort + if !s:enabled + return + endif py3 _vimspector_session.Pause() endfunction function! vimspector#Stop() abort + if !s:enabled + return + endif py3 _vimspector_session.Stop() endfunction function! vimspector#ExpandVariable() abort + if !s:enabled + return + endif py3 _vimspector_session.ExpandVariable() endfunction function! vimspector#DeleteWatch() abort + if !s:enabled + return + endif py3 _vimspector_session.DeleteWatch() endfunction function! vimspector#GoToFrame() abort + if !s:enabled + return + endif py3 _vimspector_session.ExpandFrameOrThread() endfunction function! vimspector#AddWatch( ... ) abort + if !s:enabled + return + endif if a:0 == 0 let expr = input( 'Enter watch expression: ' ) else @@ -112,27 +163,42 @@ function! vimspector#AddWatch( ... ) abort endfunction function! vimspector#AddWatchPrompt( expr ) abort + if !s:enabled + return + endif stopinsert setlocal nomodified call vimspector#AddWatch( a:expr ) endfunction function! vimspector#Evaluate( expr ) abort + if !s:enabled + return + endif py3 _vimspector_session.ShowOutput( 'Console' ) py3 _vimspector_session.EvaluateConsole( vim.eval( 'a:expr' ) ) endfunction function! vimspector#EvaluateConsole( expr ) abort + if !s:enabled + return + endif stopinsert setlocal nomodified py3 _vimspector_session.EvaluateConsole( vim.eval( 'a:expr' ) ) endfunction function! vimspector#ShowOutput( category ) abort + if !s:enabled + return + endif py3 _vimspector_session.ShowOutput( vim.eval( 'a:category' ) ) endfunction function! vimspector#ShowOutputInWindow( win_id, category ) abort + if !s:enabled + return + endif py3 __import__( 'vimspector', \ fromlist = [ 'output' ] ).output.ShowOutputInWindow( \ int( vim.eval( 'a:win_id' ) ), @@ -140,16 +206,25 @@ function! vimspector#ShowOutputInWindow( win_id, category ) abort endfunction function! vimspector#ListBreakpoints() abort + if !s:enabled + return + endif py3 _vimspector_session.ListBreakpoints() endfunction function! vimspector#CompleteOutput( ArgLead, CmdLine, CursorPos ) abort + if !s:enabled + return + endif let buffers = py3eval( '_vimspector_session.GetOutputBuffers() ' \ . ' if _vimspector_session else []' ) return join( buffers, "\n" ) endfunction function! vimspector#CompleteExpr( ArgLead, CmdLine, CursorPos ) abort + if !s:enabled + return + endif return join( py3eval( '_vimspector_session.GetCompletionsSync( ' \.' vim.eval( "a:CmdLine" ),' \.' int( vim.eval( "a:CursorPos" ) ) )' @@ -158,6 +233,9 @@ function! vimspector#CompleteExpr( ArgLead, CmdLine, CursorPos ) abort endfunction function! vimspector#Install( ... ) abort + if !s:enabled + return + endif if a:0 < 1 return endif @@ -169,6 +247,9 @@ function! vimspector#Install( ... ) abort endfunction function! vimspector#CompleteInstall( ArgLead, CmdLine, CursorPos ) abort + if !s:enabled + return + endif return py3eval( '"\n".join(' \ . '__import__( "vimspector", fromlist = [ "gadgets" ] )' \ . '.gadgets.GADGETS.keys() ' diff --git a/autoload/vimspector/internal/state.vim b/autoload/vimspector/internal/state.vim index a03d9a3..b4f18aa 100644 --- a/autoload/vimspector/internal/state.vim +++ b/autoload/vimspector/internal/state.vim @@ -25,11 +25,21 @@ if has( 'nvim' ) endif function! vimspector#internal#state#Reset() abort - py3 << EOF -import vim -from vimspector import debug_session -_vimspector_session = debug_session.DebugSession( vim.eval( 's:prefix' ) ) -EOF + try + py3 import vim + py3 _vimspector_session = __import__( + \ "vimspector", + \ fromlist=[ "debug_session" ] ).debug_session.DebugSession( + \ vim.eval( 's:prefix' ) ) + catch /.*/ + echohl WarningMsg + echom 'Exception while loading vimspector:' v:exception + echom 'Vimspector unavailable: Requires Vim compiled with Python 3.6' + echohl None + return v:false + endtry + + return v:true endfunction function! vimspector#internal#state#GetAPIPrefix() abort diff --git a/python3/vimspector/installer.py b/python3/vimspector/installer.py index e287adc..f52d667 100644 --- a/python3/vimspector/installer.py +++ b/python3/vimspector/installer.py @@ -90,7 +90,6 @@ def RunInstaller( api_prefix, *args, **kwargs ): vimspector_home = utils.GetVimString( vim.vars, 'vimspector_home' ) vimspector_base_dir = utils.GetVimspectorBase() - # TODO: Translate the arguments to something more user-friendly than -- args global OUTPUT_VIEW if OUTPUT_VIEW: OUTPUT_VIEW.Reset() diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index 4cd7c64..3a2d5cb 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -52,6 +52,8 @@ def ShowOutputInWindow( win_id, category ): class OutputView( object ): + """Container for a 'tabbed' window of buffers that can be used to display + files or the output of commands.""" def __init__( self, window, api_prefix ): self._window = window self._buffers = {} @@ -144,75 +146,73 @@ class OutputView( object ): file_name = None, cmd = None, completion_handler = None ): - win = self._window - if not win.valid: - # We need to borrow the current window - win = vim.current.window + if file_name is not None: + assert cmd is None + if install.GetOS() == "windows": + # FIXME: Can't display fiels in windows (yet?) + return - with utils.LetCurrentWindow( win ): - with utils.RestoreCurrentBuffer( win ): + cmd = [ 'tail', '-F', '-n', '+1', '--', file_name ] - if file_name is not None: - assert cmd is None - if install.GetOS() == "windows": - # FIXME: Can't display fiels in windows (yet?) - return + if cmd is not None: + out = utils.SetUpCommandBuffer( + cmd, + category, + self._api_prefix, + completion_handler = completion_handler ) + self._buffers[ category ] = TabBuffer( out, len( self._buffers ) ) + self._buffers[ category ].is_job = True + self._RenderWinBar( category ) + else: + if category == 'Console': + name = 'vimspector.Console' + else: + name = 'vimspector.Output:{0}'.format( category ) - cmd = [ 'tail', '-F', '-n', '+1', '--', file_name ] + tab_buffer = TabBuffer( utils.NewEmptyBuffer(), len( self._buffers ) ) + self._buffers[ category ] = tab_buffer - if cmd is not None: - out = utils.SetUpCommandBuffer( - cmd, - category, - self._api_prefix, - completion_handler = completion_handler ) - self._buffers[ category ] = TabBuffer( out, len( self._buffers ) ) - self._buffers[ category ].is_job = True - self._RenderWinBar( category ) - else: - vim.command( 'enew' ) - tab_buffer = TabBuffer( vim.current.buffer, len( self._buffers ) ) - self._buffers[ category ] = tab_buffer - if category == 'Console': - utils.SetUpPromptBuffer( tab_buffer.buf, - 'vimspector.Console', - '> ', - 'vimspector#EvaluateConsole' ) - else: - utils.SetUpHiddenBuffer( - tab_buffer.buf, - 'vimspector.Output:{0}'.format( category ) ) + if category == 'Console': + utils.SetUpPromptBuffer( tab_buffer.buf, + name, + '> ', + 'vimspector#EvaluateConsole' ) + else: + utils.SetUpHiddenBuffer( tab_buffer.buf, name ) - self._RenderWinBar( category ) + self._RenderWinBar( category ) def _RenderWinBar( self, category ): if not self._window.valid: return - tab_buffer = self._buffers[ category ] + with utils.LetCurrentWindow( self._window ): + tab_buffer = self._buffers[ category ] - try: - if tab_buffer.flag: - vim.command( 'nunmenu WinBar.{}'.format( utils.Escape( category ) ) ) - else: - vim.command( 'nunmenu WinBar.{}*'.format( utils.Escape( category ) ) ) - except vim.error as e: - # E329 means the menu doesn't exist; ignore that. - if 'E329' not in str( e ): - raise + try: + if tab_buffer.flag: + vim.command( 'nunmenu WinBar.{}'.format( utils.Escape( category ) ) ) + else: + vim.command( 'nunmenu WinBar.{}*'.format( utils.Escape( category ) ) ) + except vim.error as e: + # E329 means the menu doesn't exist; ignore that. + if 'E329' not in str( e ): + raise - vim.command( "nnoremenu 1.{0} WinBar.{1}{2} " - ":call vimspector#ShowOutputInWindow( {3}, '{1}' )".format( - tab_buffer.index, - utils.Escape( category ), - '*' if tab_buffer.flag else '', - utils.WindowID( self._window ) ) ) + vim.command( + "nnoremenu 1.{0} WinBar.{1}{2} " + ":call vimspector#ShowOutputInWindow( {3}, '{1}' )".format( + tab_buffer.index, + utils.Escape( category ), + '*' if tab_buffer.flag else '', + utils.WindowID( self._window ) ) ) def GetCategories( self ): return list( self._buffers.keys() ) class DAPOutputView( OutputView ): + """Specialised OutputView which adds the DAP Console (REPL)""" def __init__( self, *args ): super().__init__( *args ) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index d2870c6..fe11631 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -52,6 +52,12 @@ def BufferForFile( file_name ): return vim.buffers[ BufferNumberForFile( file_name ) ] +def NewEmptyBuffer(): + bufnr = int( vim.eval( 'bufadd("")' ) ) + Call( 'bufload', bufnr ) + return vim.buffers[ bufnr ] + + def WindowForBuffer( buf ): for w in vim.current.tabpage.windows: if w.buffer == buf: @@ -353,6 +359,7 @@ def AskForInput( prompt, default_value = None ): def AppendToBuffer( buf, line_or_lines, modified=False ): + line = 1 try: # After clearing the buffer (using buf[:] = None) there is always a single # empty line in the buffer object and no "is empty" method.