From f9ecf5f05daad39ff6d2c0a554dc4e8ca219ffc2 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 28 May 2018 15:14:41 +0100 Subject: [PATCH] Move the output window to its own space And separate all the different channels into their own buffers. Use the WinBar to select between them. --- autoload/vimspector.vim | 4 ++ python3/vimspector/debug_session.py | 32 +++++++++------- python3/vimspector/output.py | 58 +++++++++++++++++++++++++++++ python3/vimspector/utils.py | 29 +++++++++++++++ 4 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 python3/vimspector/output.py diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 0c4e25e..182a665 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -79,6 +79,10 @@ function! vimspector#AddWatch( expr ) abort py3 _vimspector_session.AddWatch( vim.eval( 'a:expr' ) ) endfunction +function! vimspector#ShowOutput( category ) abort + py3 _vimspector_session.ShowOutput( vim.eval( 'a:category' ) ) +endfunction + " Boilerplate {{{ let &cpo=s:save_cpo unlet s:save_cpo diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 3ad06c0..bbb4a9e 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -23,6 +23,7 @@ from collections import defaultdict from vimspector import ( code, debug_adapter_connection, + output, stack_trace, utils, variables ) @@ -38,7 +39,6 @@ class DebugSession( object ): self._connection = None self._uiTab = None - self._outputBuffer = None # TODO: Need something less terrible here self._stackTraceView = None self._variablesView = None @@ -219,6 +219,9 @@ class DebugSession( object ): def ExpandFrameOrThread( self ): self._stackTraceView.ExpandFrameOrThread() + def ShowOutput( self, category ): + self._outputView.ShowOutput( category ) + def _SetUpUI( self ): vim.command( 'tabnew' ) self._uiTab = vim.current.tabpage @@ -227,7 +230,7 @@ class DebugSession( object ): self._codeView = code.CodeView( vim.current.window ) # Call stack - vim.command( '50vspl' ) + vim.command( 'topleft 50vspl' ) vim.command( 'enew' ) self._stackTraceView = stack_trace.StackTraceView( self, self._connection, @@ -235,18 +238,21 @@ class DebugSession( object ): with utils.TemporaryVimOption( 'eadirection', 'ver' ): with utils.TemporaryVimOption( 'equalalways', 1 ): - # Output/logging - vim.command( 'spl' ) - vim.command( 'enew' ) - self._outputBuffer = vim.current.buffer - utils.SetUpScratchBuffer( self._outputBuffer, 'vimspector.Console' ) - # Variables vim.command( 'spl' ) vim.command( 'enew' ) self._variablesView = variables.VariablesView( self._connection, vim.current.buffer ) + + with utils.TemporaryVimOption( 'splitbelow', True ): + vim.current.window = self._codeView._window + + # Output/logging + vim.command( '10spl' ) + vim.command( 'enew' ) + self._outputView = output.OutputView( vim.current.window ) + def ClearCurrentFrame( self ): self.SetCurrentFrame( None ) @@ -279,7 +285,6 @@ class DebugSession( object ): vim.command( 'autocmd VimLeavePre * py3 _vimspector_session.CloseDown()' ) vim.command( 'augroup END' ) - def CloseDown( self ): state = { 'done': False } @@ -293,7 +298,9 @@ class DebugSession( object ): }, } ) - while not state[ 'done' ]: + tries = 0 + while not state[ 'done' ] and tries < 10: + tries = tries + 1 vim.eval( 'vimspector#internal#job#ForceRead()' ) vim.eval( 'vimspector#internal#job#StopDebugSession()' ) @@ -457,10 +464,7 @@ class DebugSession( object ): file_name ) ) def OnEvent_output( self, message ): - with utils.ModifiableScratchBuffer( self._outputBuffer ): - t = [ message[ 'body' ][ 'category' ] + ':' + '-' * 20 ] - t += message[ 'body' ][ 'output' ].splitlines() - self._outputBuffer.append( t, 0 ) + self._outputView.OnOutput( message[ 'body' ] ) def OnEvent_stopped( self, message ): event = message[ 'body' ] diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py new file mode 100644 index 0000000..af3b744 --- /dev/null +++ b/python3/vimspector/output.py @@ -0,0 +1,58 @@ +# 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. + +from vimspector import utils + +import vim + + +class OutputView( object ): + def __init__( self, window ): + self._window = window + self._buffers = {} + + self._CreateBuffer( 'stdout' ) + self.ShowOutput( 'stdout' ) + + def OnOutput( self, event ): + category = event[ 'category' ] + if category not in self._buffers: + self._CreateBuffer( category ) + + with utils.ModifiableScratchBuffer( self._buffers[ category ] ): + self._buffers[ category ].append( event[ 'output' ].splitlines() ) + + def Clear( self ): + for buf in self._buffers: + self._buffers[ buf ] = None + + def ShowOutput( self, category ): + vim.current.window = self._window + vim.command( 'bu {0}'.format( self._buffers[ category ].name ) ) + + def _CreateBuffer( self, category ): + with utils.RestorCurrentWindow(): + vim.current.window = self._window + + vim.command( 'enew' ) + self._buffers[ category ] = vim.current.buffer + self._buffers[ category ].append( category + '-----' ) + + utils.SetUpHiddenBuffer( self._buffers[ category ], + 'vimspector.Output:{0}'.format( category ) ) + + vim.command( "nnoremenu WinBar.{0} " + ":call vimspector#ShowOutput( '{0}' )".format( + utils.Escape( category ) ) ) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 88ba9f5..3bd1270 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -40,6 +40,17 @@ def SetUpScratchBuffer( buf, name ): buf.name = name +def SetUpHiddenBuffer( buf, name ): + buf.options[ 'buftype' ] = 'nofile' + buf.options[ 'swapfile' ] = False + buf.options[ 'modifiable' ] = False + buf.options[ 'modified' ] = False + buf.options[ 'readonly' ] = True + buf.options[ 'buflisted' ] = False + buf.options[ 'bufhidden' ] = 'hide' + buf.name = name + + @contextlib.contextmanager def ModifiableScratchBuffer( buf ): buf.options[ 'modifiable' ] = True @@ -62,6 +73,24 @@ def RestoreCursorPosition(): current_pos[ 1 ] ) +@contextlib.contextmanager +def RestorCurrentWindow(): + old_window = vim.current.window + try: + yield + finally: + vim.current.window = old_window + + +@contextlib.contextmanager +def RestoreCurrentBuffer( window ): + old_buffer_name = window.buffer.name + try: + yield + finally: + window.buffer.name = old_buffer_name + + @contextlib.contextmanager def TemporaryVimOption( opt, value ): old_value = vim.options[ opt ]