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