Use prompt buffer for Console
Like VSCode does, compbine console and stdout, and allow you to enter commands in the console. It's all a bit janky right now and the insertion point isn't ideal (as not all output is interactive) and some output is asynchronous via a somewhat different channel.
This commit is contained in:
parent
6d709d551c
commit
b72bc7dfbf
4 changed files with 79 additions and 17 deletions
|
|
@ -89,6 +89,12 @@ function! vimspector#AddWatchPrompt( expr ) abort
|
||||||
call vimspector#AddWatch( a:expr )
|
call vimspector#AddWatch( a:expr )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! vimspector#EvaluateConsole( expr ) abort
|
||||||
|
stopinsert
|
||||||
|
setlocal nomodified
|
||||||
|
py3 _vimspector_session.EvaluateConsole( vim.eval( 'a:expr' ) )
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! vimspector#ShowOutput( category ) abort
|
function! vimspector#ShowOutput( category ) abort
|
||||||
py3 _vimspector_session.ShowOutput( vim.eval( 'a:category' ) )
|
py3 _vimspector_session.ShowOutput( vim.eval( 'a:category' ) )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
|
||||||
|
|
@ -243,6 +243,10 @@ class DebugSession( object ):
|
||||||
self._variablesView.AddWatch( self._stackTraceView.GetCurrentFrame(),
|
self._variablesView.AddWatch( self._stackTraceView.GetCurrentFrame(),
|
||||||
expression )
|
expression )
|
||||||
|
|
||||||
|
def EvaluateConsole( self, expression ):
|
||||||
|
self._outputView.Evaluate( self._stackTraceView.GetCurrentFrame(),
|
||||||
|
expression )
|
||||||
|
|
||||||
def DeleteWatch( self ):
|
def DeleteWatch( self ):
|
||||||
self._variablesView.DeleteWatch()
|
self._variablesView.DeleteWatch()
|
||||||
|
|
||||||
|
|
@ -304,7 +308,8 @@ class DebugSession( object ):
|
||||||
# Output/logging
|
# Output/logging
|
||||||
vim.command( '10spl' )
|
vim.command( '10spl' )
|
||||||
vim.command( 'enew' )
|
vim.command( 'enew' )
|
||||||
self._outputView = output.OutputView( vim.current.window )
|
self._outputView = output.OutputView( self._connection,
|
||||||
|
vim.current.window )
|
||||||
|
|
||||||
def ClearCurrentFrame( self ):
|
def ClearCurrentFrame( self ):
|
||||||
self.SetCurrentFrame( None )
|
self.SetCurrentFrame( None )
|
||||||
|
|
@ -371,6 +376,7 @@ class DebugSession( object ):
|
||||||
self._connection = None
|
self._connection = None
|
||||||
self._stackTraceView.ConnectionClosed()
|
self._stackTraceView.ConnectionClosed()
|
||||||
self._variablesView.ConnectionClosed()
|
self._variablesView.ConnectionClosed()
|
||||||
|
self._outputView.ConnectionClosed()
|
||||||
if callback:
|
if callback:
|
||||||
callback()
|
callback()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,22 +18,44 @@ from vimspector import utils
|
||||||
import vim
|
import vim
|
||||||
|
|
||||||
|
|
||||||
|
BUFFER_MAP = {
|
||||||
|
'console': 'Console',
|
||||||
|
'stdout': 'Console'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def CategoryToBuffer( category ):
|
||||||
|
return BUFFER_MAP.get( category, category )
|
||||||
|
|
||||||
|
|
||||||
class OutputView( object ):
|
class OutputView( object ):
|
||||||
def __init__( self, window ):
|
def __init__( self, connection, window ):
|
||||||
self._window = window
|
self._window = window
|
||||||
|
self._connection = connection
|
||||||
self._buffers = {}
|
self._buffers = {}
|
||||||
|
|
||||||
self._CreateBuffer( 'stdout' )
|
for b in set( BUFFER_MAP.values() ):
|
||||||
self.ShowOutput( 'stdout' )
|
self._CreateBuffer( b )
|
||||||
|
|
||||||
|
self.ShowOutput( 'Console' )
|
||||||
|
|
||||||
def OnOutput( self, event ):
|
def OnOutput( self, event ):
|
||||||
category = event.get( 'category' ) or 'output'
|
category = CategoryToBuffer( event.get( 'category' ) or 'output' )
|
||||||
if category not in self._buffers:
|
if category not in self._buffers:
|
||||||
self._CreateBuffer( category )
|
self._CreateBuffer( category )
|
||||||
|
|
||||||
with utils.ModifiableScratchBuffer( self._buffers[ category ] ):
|
buf = self._buffers[ category ]
|
||||||
utils.AppendToBuffer( self._buffers[ category ],
|
with utils.ModifiableScratchBuffer( buf ):
|
||||||
event[ 'output' ].splitlines() )
|
utils.AppendToBuffer( buf, event[ 'output' ].splitlines() )
|
||||||
|
|
||||||
|
# Scroll the buffer
|
||||||
|
with utils.RestoreCurrentWindow():
|
||||||
|
with utils.RestoreCurrentBuffer( self._window ):
|
||||||
|
self.ShowOutput( category )
|
||||||
|
vim.command( 'normal G' )
|
||||||
|
|
||||||
|
def ConnectionClosed( self ):
|
||||||
|
self._connection = None
|
||||||
|
|
||||||
def Reset( self ):
|
def Reset( self ):
|
||||||
self.Clear()
|
self.Clear()
|
||||||
|
|
@ -48,18 +70,42 @@ class OutputView( object ):
|
||||||
vim.current.window = self._window
|
vim.current.window = self._window
|
||||||
vim.command( 'bu {0}'.format( self._buffers[ category ].name ) )
|
vim.command( 'bu {0}'.format( self._buffers[ category ].name ) )
|
||||||
|
|
||||||
|
def Evaluate( self, frame, expression ):
|
||||||
|
if not frame:
|
||||||
|
return
|
||||||
|
|
||||||
|
console = self._buffers[ 'Console' ]
|
||||||
|
utils.AppendToBuffer( console, expression )
|
||||||
|
|
||||||
|
def print_result( message ):
|
||||||
|
utils.AppendToBuffer( console, message[ 'body' ][ 'result' ] )
|
||||||
|
|
||||||
|
self._connection.DoRequest( print_result, {
|
||||||
|
'command': 'evaluate',
|
||||||
|
'arguments': {
|
||||||
|
'expression': expression,
|
||||||
|
'context': 'repl',
|
||||||
|
'frameId': frame[ 'id' ],
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
|
||||||
def _CreateBuffer( self, category ):
|
def _CreateBuffer( self, category ):
|
||||||
with utils.RestorCurrentWindow():
|
with utils.RestoreCurrentWindow():
|
||||||
vim.current.window = self._window
|
vim.current.window = self._window
|
||||||
|
|
||||||
with utils.RestoreCurrentBuffer( self._window ):
|
with utils.RestoreCurrentBuffer( self._window ):
|
||||||
vim.command( 'enew' )
|
vim.command( 'enew' )
|
||||||
self._buffers[ category ] = vim.current.buffer
|
self._buffers[ category ] = vim.current.buffer
|
||||||
utils.AppendToBuffer( self._buffers[ category ],
|
|
||||||
category + '-----' )
|
|
||||||
|
|
||||||
utils.SetUpHiddenBuffer( self._buffers[ category ],
|
if category == 'Console':
|
||||||
'vimspector.Output:{0}'.format( category ) )
|
utils.SetUpPromptBuffer( self._buffers[ category ],
|
||||||
|
'vimspector.Console',
|
||||||
|
'> ',
|
||||||
|
'vimspector#EvaluateConsole',
|
||||||
|
hidden = True )
|
||||||
|
else:
|
||||||
|
utils.SetUpHiddenBuffer( self._buffers[ category ],
|
||||||
|
'vimspector.Output:{0}'.format( category ) )
|
||||||
|
|
||||||
vim.command( "nnoremenu WinBar.{0} "
|
vim.command( "nnoremenu WinBar.{0} "
|
||||||
":call vimspector#ShowOutput( '{0}' )<CR>".format(
|
":call vimspector#ShowOutput( '{0}' )<CR>".format(
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ def SetUpHiddenBuffer( buf, name ):
|
||||||
buf.options[ 'bufhidden' ] = 'hide'
|
buf.options[ 'bufhidden' ] = 'hide'
|
||||||
buf.name = name
|
buf.name = name
|
||||||
|
|
||||||
def SetUpPromptBuffer( buf, name, prompt, callback ):
|
def SetUpPromptBuffer( buf, name, prompt, callback, hidden=False ):
|
||||||
# This feature is _super_ new, so only enable when available
|
# This feature is _super_ new, so only enable when available
|
||||||
if not int( vim.eval( "exists( '*prompt_setprompt' )" ) ):
|
if not int( vim.eval( "exists( '*prompt_setprompt' )" ) ):
|
||||||
return SetUpScratchBuffer( buf, name )
|
return SetUpScratchBuffer( buf, name )
|
||||||
|
|
@ -63,7 +63,7 @@ def SetUpPromptBuffer( buf, name, prompt, callback ):
|
||||||
buf.options[ 'modified' ] = False
|
buf.options[ 'modified' ] = False
|
||||||
buf.options[ 'readonly' ] = False
|
buf.options[ 'readonly' ] = False
|
||||||
buf.options[ 'buflisted' ] = False
|
buf.options[ 'buflisted' ] = False
|
||||||
buf.options[ 'bufhidden' ] = 'wipe'
|
buf.options[ 'bufhidden' ] = 'wipe' if not hidden else 'hide'
|
||||||
buf.name = name
|
buf.name = name
|
||||||
|
|
||||||
vim.eval( "prompt_setprompt( {0}, '{1}' )".format( buf.number,
|
vim.eval( "prompt_setprompt( {0}, '{1}' )".format( buf.number,
|
||||||
|
|
@ -101,7 +101,7 @@ def RestoreCursorPosition():
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def RestorCurrentWindow():
|
def RestoreCurrentWindow():
|
||||||
# TODO: Don't trigger autoccommands when shifting windows
|
# TODO: Don't trigger autoccommands when shifting windows
|
||||||
old_window = vim.current.window
|
old_window = vim.current.window
|
||||||
try:
|
try:
|
||||||
|
|
@ -117,7 +117,7 @@ def RestoreCurrentBuffer( window ):
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
with RestorCurrentWindow():
|
with RestoreCurrentWindow():
|
||||||
vim.current.window = window
|
vim.current.window = window
|
||||||
vim.current.buffer = old_buffer
|
vim.current.buffer = old_buffer
|
||||||
|
|
||||||
|
|
@ -218,3 +218,7 @@ def AppendToBuffer( buf, line_or_lines ):
|
||||||
|
|
||||||
def ClearBuffer( buf ):
|
def ClearBuffer( buf ):
|
||||||
buf[:] = None
|
buf[:] = None
|
||||||
|
|
||||||
|
|
||||||
|
def IsCurrent( window, buf ):
|
||||||
|
return vim.current.window == window and vim.current.window.buffer == buf
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue