adding on the fly eval of inside a floating window
This commit is contained in:
parent
4c0ba92ac6
commit
07858cc250
3 changed files with 103 additions and 94 deletions
|
|
@ -53,7 +53,7 @@ function! vimspector#internal#state#Tooltip() abort
|
||||||
" winnr + 1 because for *no good reason* winnr is 0 based here unlike
|
" winnr + 1 because for *no good reason* winnr is 0 based here unlike
|
||||||
" everywhere else
|
" everywhere else
|
||||||
" int() because for *no good reason* winnr is a string.
|
" int() because for *no good reason* winnr is a string.
|
||||||
return py3eval('_vimspector_session.ShowBalloon('
|
return py3eval('_vimspector_session.ShowTooltip('
|
||||||
\ . 'int( vim.eval( "winnr()" ) ) ,'
|
\ . 'int( vim.eval( "winnr()" ) ) ,'
|
||||||
\ . 'vim.eval( "expand(\"<cexpr>\")" ) )' )
|
\ . 'vim.eval( "expand(\"<cexpr>\")" ) )' )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
@ -62,16 +62,20 @@ function! vimspector#internal#state#CreateTooltip() abort
|
||||||
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! vimspector#internal#state#ShowTooltip() abort
|
||||||
|
return py3eval('_vimspector_session.ShowTooltip(int( vim.eval( "winnr()" ) ) ,vim.eval( "expand(\"<cexpr>\")" ) )')
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#state#TooltipExec(body) abort
|
function! vimspector#internal#state#TooltipExec(body) abort
|
||||||
let buf = nvim_create_buf(v:false, v:true)
|
let buf = nvim_create_buf(v:false, v:true)
|
||||||
call nvim_buf_set_lines(buf, 0, -1, v:true, a:body)
|
call nvim_buf_set_lines(buf, 0, -1, v:true, a:body)
|
||||||
|
|
||||||
" get the max width on a line
|
" get the max width on a line
|
||||||
let width = 0
|
let width = 0
|
||||||
let maxWidth = winwidth()
|
let maxWidth = winwidth(0)
|
||||||
|
|
||||||
for w in a:body
|
for w in a:body
|
||||||
let width = max(len(w), width)
|
let width = max([len(w), width])
|
||||||
" reached the max size, no point in looping more
|
" reached the max size, no point in looping more
|
||||||
if width > maxWidth
|
if width > maxWidth
|
||||||
let width = maxWidth
|
let width = maxWidth
|
||||||
|
|
@ -79,8 +83,10 @@ function! vimspector#internal#state#TooltipExec(body) abort
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
|
|
||||||
let opts = { 'relative': 'cursor', 'width': width, 'height': len(a:body), 'col': 0, 'row': 1, 'anchor': 'NW', 'style': 'minimal' }
|
let opts = { 'relative': 'cursor', 'width': width, 'height': len(a:body), 'col': 0, 'row': 1, 'anchor': 'NW', 'style': 'minimal' }
|
||||||
let g:float_win = nvim_open_win(buf, 0, opts)
|
let g:float_win = nvim_open_win(buf, 0, opts)
|
||||||
|
call setwinvar(g:float_win, '&wrap', 0)
|
||||||
|
|
||||||
augroup vimspector#internal#balloon#nvim_float
|
augroup vimspector#internal#balloon#nvim_float
|
||||||
autocmd!
|
autocmd!
|
||||||
|
|
|
||||||
|
|
@ -538,6 +538,26 @@ class DebugSession( object ):
|
||||||
def DeleteWatch( self ):
|
def DeleteWatch( self ):
|
||||||
self._variablesView.DeleteWatch()
|
self._variablesView.DeleteWatch()
|
||||||
|
|
||||||
|
|
||||||
|
@IfConnected()
|
||||||
|
def ShowTooltip(self, winnr, expression):
|
||||||
|
"""Proxy: ballonexpr -> variables.ShowBallon"""
|
||||||
|
frame = self._stackTraceView.GetCurrentFrame()
|
||||||
|
# Check if RIP is in a frame
|
||||||
|
if frame is None:
|
||||||
|
self._logger.debug( 'Balloon: Not in a stack frame' )
|
||||||
|
return ''
|
||||||
|
|
||||||
|
# Check if cursor in code window
|
||||||
|
if winnr != int( self._codeView._window.number ):
|
||||||
|
self._logger.debug( 'Winnr %s is not the code window %s',
|
||||||
|
winnr,
|
||||||
|
self._codeView._window.number )
|
||||||
|
return ''
|
||||||
|
|
||||||
|
# Return variable aware function
|
||||||
|
return self._variablesView.VariableEval(frame, expression)
|
||||||
|
|
||||||
@IfConnected()
|
@IfConnected()
|
||||||
def ShowBalloon( self, winnr, expression ):
|
def ShowBalloon( self, winnr, expression ):
|
||||||
"""Proxy: ballonexpr -> variables.ShowBallon"""
|
"""Proxy: ballonexpr -> variables.ShowBallon"""
|
||||||
|
|
|
||||||
|
|
@ -125,9 +125,9 @@ class View:
|
||||||
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.buf = win.buffer
|
if (win is not None):
|
||||||
|
self.buf = win.buffer
|
||||||
utils.SetUpUIWindow( win )
|
utils.SetUpUIWindow( win )
|
||||||
|
|
||||||
|
|
||||||
class VariablesView( object ):
|
class VariablesView( object ):
|
||||||
|
|
@ -138,6 +138,8 @@ class VariablesView( object ):
|
||||||
self._connection = None
|
self._connection = None
|
||||||
self._current_syntax = ''
|
self._current_syntax = ''
|
||||||
|
|
||||||
|
self._variable_eval = None
|
||||||
|
|
||||||
def AddExpandMappings():
|
def AddExpandMappings():
|
||||||
vim.command( 'nnoremap <silent> <buffer> <CR> '
|
vim.command( 'nnoremap <silent> <buffer> <CR> '
|
||||||
':<C-u>call vimspector#ExpandVariable()<CR>' )
|
':<C-u>call vimspector#ExpandVariable()<CR>' )
|
||||||
|
|
@ -267,6 +269,75 @@ class VariablesView( object ):
|
||||||
},
|
},
|
||||||
} )
|
} )
|
||||||
|
|
||||||
|
def _DrawEval(self):
|
||||||
|
# TODO: create vim functin that creates a floating window and returns window id
|
||||||
|
# use that window id to retrieve the buffer
|
||||||
|
# use that buffer in order to populate the results of the query
|
||||||
|
indent = 0
|
||||||
|
icon = '+' if self._variable_eval.IsExpandable() and not self._variable_eval.IsExpanded() else '-'
|
||||||
|
|
||||||
|
line = utils.AppendToBuffer( self._vars.buf,
|
||||||
|
'{0}{1} Scope: {2}'.format(
|
||||||
|
' ' * indent,
|
||||||
|
icon,
|
||||||
|
self._variable_eval.scope[ 'name' ] ) )
|
||||||
|
self._vars.lines[ line ] = self._variable_eval
|
||||||
|
|
||||||
|
if self._variable_eval.ShouldDrawDrillDown():
|
||||||
|
indent += 2
|
||||||
|
# replace with a newly created view for the purposes of evaluation
|
||||||
|
self._DrawVariables( self._vars, self._variable_eval.variables, indent )
|
||||||
|
|
||||||
|
# vim.eval("vimspector#internal#state#TooltipExec({})".format([self._variable_eval]))
|
||||||
|
|
||||||
|
|
||||||
|
def VariableEval(self, frame, expression):
|
||||||
|
"""Callback to display variable under cursor `:h ballonexpr`"""
|
||||||
|
if not self._connection:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def handler( message ):
|
||||||
|
# TODO: this result count be expandable, but we have no way to allow the
|
||||||
|
# user to interact with the balloon to expand it, unless we use a popup
|
||||||
|
# instead, but even then we don't really want to trap the cursor.
|
||||||
|
body = message[ 'body' ]
|
||||||
|
result = body[ 'result' ]
|
||||||
|
if result is None:
|
||||||
|
result = 'null'
|
||||||
|
display = [
|
||||||
|
'Type: ' + body.get( 'type', '<unknown>' ),
|
||||||
|
'Value: ' + result
|
||||||
|
]
|
||||||
|
|
||||||
|
self._variable_eval = Scope(body)
|
||||||
|
|
||||||
|
self._connection.DoRequest( partial( self._ConsumeVariables,
|
||||||
|
self._DrawEval,
|
||||||
|
self._variable_eval ), {
|
||||||
|
'command': 'variables',
|
||||||
|
'arguments': {
|
||||||
|
'variablesReference': self._variable_eval.VariablesReference(),
|
||||||
|
},
|
||||||
|
} )
|
||||||
|
|
||||||
|
|
||||||
|
def failure_handler( reason, message ):
|
||||||
|
display = [ reason ]
|
||||||
|
utils.DisplayBaloon( self._is_term, display )
|
||||||
|
|
||||||
|
# Send async request
|
||||||
|
self._connection.DoRequest( handler, {
|
||||||
|
'command': 'evaluate',
|
||||||
|
'arguments': {
|
||||||
|
'expression': expression,
|
||||||
|
'frameId': frame[ 'id' ],
|
||||||
|
'context': 'hover',
|
||||||
|
}
|
||||||
|
}, failure_handler )
|
||||||
|
|
||||||
|
# Return working (meanwhile)
|
||||||
|
return '...'
|
||||||
|
|
||||||
def AddWatch( self, frame, expression ):
|
def AddWatch( self, frame, expression ):
|
||||||
watch = {
|
watch = {
|
||||||
'expression': expression,
|
'expression': expression,
|
||||||
|
|
@ -535,92 +606,4 @@ class VariablesView( object ):
|
||||||
syntax,
|
syntax,
|
||||||
self._vars.buf,
|
self._vars.buf,
|
||||||
self._watch.buf )
|
self._watch.buf )
|
||||||
class VariableEval
|
|
||||||
def __init__(self, stackTrace):
|
|
||||||
self.stackTrace = stackTrace
|
|
||||||
self._connection = None
|
|
||||||
self.variable = Variable()
|
|
||||||
|
|
||||||
def _ConsumeVariables(self, parent, message):
|
|
||||||
new_variables = []
|
|
||||||
for variable_body in message[ 'body' ][ 'variables' ]:
|
|
||||||
if parent.variables is None:
|
|
||||||
parent.variables = []
|
|
||||||
|
|
||||||
# Find the variable in parent
|
|
||||||
found = False
|
|
||||||
for index, v in enumerate( parent.variables ):
|
|
||||||
if v.variable[ 'name' ] == variable_body[ 'name' ]:
|
|
||||||
variable = v
|
|
||||||
found = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not found:
|
|
||||||
variable = Variable( variable_body )
|
|
||||||
else:
|
|
||||||
variable.Update( variable_body )
|
|
||||||
|
|
||||||
new_variables.append( variable )
|
|
||||||
|
|
||||||
if variable.IsExpandable() and variable.IsExpanded():
|
|
||||||
self._connection.DoRequest( partial( self._ConsumeVariables,
|
|
||||||
draw,
|
|
||||||
variable ), {
|
|
||||||
'command': 'variables',
|
|
||||||
'arguments': {
|
|
||||||
'variablesReference': variable.VariablesReference()
|
|
||||||
},
|
|
||||||
} )
|
|
||||||
|
|
||||||
parent.variables = new_variables
|
|
||||||
|
|
||||||
def _DrawVariables( self, variables, indent ):
|
|
||||||
assert indent > 0
|
|
||||||
for variable in variables:
|
|
||||||
line = utils.AppendToBuffer(
|
|
||||||
view.buf,
|
|
||||||
'{indent}{marker}{icon} {name} ({type_}): {value}'.format(
|
|
||||||
# We borrow 1 space of indent to draw the change marker
|
|
||||||
indent = ' ' * ( indent - 1 ),
|
|
||||||
marker = '*' if variable.changed else ' ',
|
|
||||||
icon = '+' if ( variable.IsExpandable()
|
|
||||||
and not variable.IsExpanded() ) else '-',
|
|
||||||
name = variable.variable[ 'name' ],
|
|
||||||
type_ = variable.variable.get( 'type', '' ),
|
|
||||||
value = variable.variable.get( 'value',
|
|
||||||
'<unknown>' ) ).split( '\n' ) )
|
|
||||||
view.lines[ line ] = variable
|
|
||||||
|
|
||||||
if variable.ShouldDrawDrillDown():
|
|
||||||
self._DrawVariables( view, variable.variables, indent + 2 )
|
|
||||||
|
|
||||||
def AddVariableEval( self, bufid ):
|
|
||||||
current_symbol = vim.eval("expand('<cexpr>')")
|
|
||||||
|
|
||||||
def handler( message ):
|
|
||||||
# TODO: this result count be expandable, but we have no way to allow the
|
|
||||||
# user to interact with the balloon to expand it, unless we use a popup
|
|
||||||
# instead, but even then we don't really want to trap the cursor.
|
|
||||||
_ConsumeVariables(self, self.variable, message)
|
|
||||||
variableEvalView = View( variables_win, {}, self._DrawScopes )
|
|
||||||
_DrawVariables(self, self.variable, 0)
|
|
||||||
|
|
||||||
|
|
||||||
def failure_handler(reason, message):
|
|
||||||
vim.eval("echom {}".format(message))
|
|
||||||
|
|
||||||
self._connection.DoRequest( handler, {
|
|
||||||
'command': 'evaluate',
|
|
||||||
'arguments': {
|
|
||||||
'expression': expression,
|
|
||||||
'frameId': frame[ 'id' ],
|
|
||||||
'context': 'hover',
|
|
||||||
}
|
|
||||||
}, failure_handler )
|
|
||||||
|
|
||||||
def ConnectionUp( self, connection ):
|
|
||||||
self._connection = connection
|
|
||||||
|
|
||||||
def ConnectionClosed(self):
|
|
||||||
self._connection = None
|
|
||||||
# vim: sw=2
|
# vim: sw=2
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue