Fix crash; enable syntax highlighting in hover popup; use a Watch for the popup and re-use existing drawing code

This commit is contained in:
Ben Jackson 2021-01-05 22:13:25 +00:00
commit 64e38b57ab

View file

@ -117,14 +117,27 @@ class Watch:
self.expression = expression
self.result = None
@staticmethod
def New( frame, expression, context ):
watch = {
'expression': expression,
'context': context,
}
if frame:
watch[ 'frameId' ] = frame[ 'id' ]
return Watch( watch )
class View:
lines: typing.Dict[ int, Expandable ]
draw: typing.Callable
syntax: str
def __init__( self, win, lines, draw ):
self.lines = lines
self.draw = draw
self.syntax = None
if ( win is not None ):
self.buf = win.buffer
utils.SetUpUIWindow( win )
@ -186,8 +199,8 @@ class VariablesView( object ):
'balloonexpr': vim.options[ 'balloonexpr' ],
'balloondelay': vim.options[ 'balloondelay' ],
}
vim.options[ 'balloonexpr' ] = "vimspector#internal#"
"balloon#HoverTooltip()"
vim.options[ 'balloonexpr' ] = ( "vimspector#internal#"
"balloon#HoverTooltip()" )
vim.options[ 'balloondelay' ] = 250
@ -273,28 +286,25 @@ class VariablesView( object ):
} )
def _DrawEval( self ):
watch = self._variable_eval
view = self._variable_eval_view
with utils.RestoreCursorPosition():
with utils.ModifiableScratchBuffer( self._variable_eval_view.buf ):
utils.ClearBuffer( self._variable_eval_view.buf )
# if we only have a single non-expandable variable,
# it means we ran into a simple type
# hence, there is no need to draw additional fluff around the value
if(
len( self._variable_eval.variables ) == 1
and self._variable_eval.variables[ 0 ].IsExpandable() is False
):
utils.AppendToBuffer(
self._variable_eval_view.buf,
self._variable_eval.variables[ 0 ]
.variable.get( 'value', '<unknown>' )
)
else:
self._DrawVariables(
self._variable_eval_view,
self._variable_eval.variables,
2,
True
)
with utils.ModifiableScratchBuffer( view.buf ):
utils.ClearBuffer( view.buf )
# FIXME: This probably doesn't work reliably
view.syntax = utils.SetSyntax( view.syntax,
self._current_syntax,
view.buf )
utils.AppendToBuffer(
view.buf,
f"Expression: { watch.expression[ 'expression' ] }" )
self._DrawWatchResult( view,
2,
watch,
is_short = True )
vim.eval( "vimspector#internal#balloon#nvim_resize_tooltip()" )
@ -309,9 +319,13 @@ class VariablesView( object ):
return ''
def handler( message ):
body = message[ 'body' ]
self._variable_eval = Scope( body )
watch = self._variable_eval
if watch.result is None:
watch.result = WatchResult( message[ 'body' ] )
else:
watch.result.Update( message[ 'body' ] )
float_win_id = utils.DisplayBaloon( self._is_term, [], is_hover )
float_buf_nr = int( vim.eval( "winbufnr({})".format( float_win_id ) ) )
@ -328,51 +342,41 @@ class VariablesView( object ):
self._DrawEval
)
if( self._variable_eval.VariablesReference() > 0 ):
if watch.result.IsExpandable():
# Always expand the first level
watch.result.expanded = Expandable.EXPANDED_BY_US
if watch.result.IsExpanded():
self._connection.DoRequest( partial( self._ConsumeVariables,
self._DrawEval,
self._variable_eval ), {
self._variable_eval_view.draw,
watch.result ), {
'command': 'variables',
'arguments': {
'variablesReference': self._variable_eval.VariablesReference(),
'variablesReference': watch.result.VariablesReference(),
},
} )
else:
# in case that there is nothing to expand,
# we need to simulate a response from 'variables' request
# it returns [Variable]
self._variable_eval.variables = [
Variable( { 'type': body[ 'type' ], 'value': body[ 'result' ] } )
]
self._DrawEval()
self._DrawEval()
def failure_handler( reason, message ):
display = [ reason ]
utils.DisplayBaloon( self._is_term, display, is_hover )
self._variable_eval = Watch.New( frame,
expression,
'hover' )
# Send async request
self._connection.DoRequest( handler, {
'command': 'evaluate',
'arguments': {
'expression': expression,
'frameId': frame[ 'id' ],
'context': 'hover',
}
'arguments': self._variable_eval.expression,
}, failure_handler )
# Return working (meanwhile)
return ''
def AddWatch( self, frame, expression ):
watch = {
'expression': expression,
'context': 'watch',
}
if frame:
watch[ 'frameId' ] = frame[ 'id' ]
self._watches.append( Watch( watch ) )
self._watches.append( Watch.New( frame, expression, 'watch' ) )
self.EvaluateWatches()
def DeleteWatch( self ):
@ -470,7 +474,7 @@ class VariablesView( object ):
},
} )
def _DrawVariables( self, view, variables, indent, is_short = False ):
def _DrawVariables( self, view, variables, indent, is_short = False ):
assert indent > 0
for variable in variables:
text = ''
@ -530,7 +534,7 @@ class VariablesView( object ):
'Expression: '
+ watch.expression[ 'expression' ] )
watch.line = line
self._DrawWatchResult( 2, watch )
self._DrawWatchResult( self._watch, 2, watch )
def _DrawScope( self, indent, scope ):
icon = '+' if scope.IsExpandable() and not scope.IsExpanded() else '-'
@ -546,7 +550,7 @@ class VariablesView( object ):
indent += 2
self._DrawVariables( self._vars, scope.variables, indent )
def _DrawWatchResult( self, indent, watch ):
def _DrawWatchResult( self, view, indent, watch, is_short = False ):
if not watch.result:
return
@ -561,12 +565,12 @@ class VariablesView( object ):
icon = icon,
result = watch.result.result.get( 'result', '<unknown>' ) )
line = utils.AppendToBuffer( self._watch.buf, line.split( '\n' ) )
self._watch.lines[ line ] = watch.result
line = utils.AppendToBuffer( view.buf, line.split( '\n' ) )
view.lines[ line ] = watch.result
if watch.result.ShouldDrawDrillDown():
indent = 4
self._DrawVariables( self._watch, watch.result.variables, indent )
self._DrawVariables( view, watch.result.variables, indent, is_short )
def _ConsumeVariables( self, draw, parent, message ):
new_variables = []
@ -640,6 +644,7 @@ class VariablesView( object ):
def SetSyntax( self, syntax ):
# TODO: Switch to View.syntax
self._current_syntax = utils.SetSyntax( self._current_syntax,
syntax,
self._vars.buf,