From 8fcf43ebded0e47e9587ed59442cade183c015ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nilo=20C=C3=A9sar=20Teixeira?= Date: Sat, 4 Jun 2016 14:07:27 -0300 Subject: [PATCH 1/7] Centering cursor vertically on source, from stack window command When double-clicking or hitting Enter in a stack window filename, which causes it to load the file in the source window, this change makes it always center the cursor vertically. --- plugin/python/vdebug/ui/vimui.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/python/vdebug/ui/vimui.py b/plugin/python/vdebug/ui/vimui.py index 6e9ab927..7337f280 100644 --- a/plugin/python/vdebug/ui/vimui.py +++ b/plugin/python/vdebug/ui/vimui.py @@ -244,7 +244,8 @@ def set_file(self,file): def set_line(self,lineno): self.focus() - vim.command("normal %sgg" % str(lineno)) + """ Centering display vertically on lineno """ + vim.command("normal %szz" % str(lineno)) def get_file(self): self.focus() From 40ee8a834d29962cf8349cb81442578a5294fee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nilo=20C=C3=A9sar=20Teixeira?= Date: Tue, 7 Jun 2016 15:47:27 -0300 Subject: [PATCH 2/7] Placing signs on stackwin and sourcewin, upon hitting a file With this commit now Vdebug places a stack sign (#>) on both Stack and Source windows, to make clear which file and line it's loading from user interface activity on Stack window. The refresh method on Runner clears both signs. --- plugin/python/vdebug/event.py | 8 +++++--- plugin/python/vdebug/runner.py | 6 +++++- plugin/python/vdebug/ui/vimui.py | 27 +++++++++++++++++++++++++++ plugin/vdebug.vim | 7 +++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/plugin/python/vdebug/event.py b/plugin/python/vdebug/event.py index 81d3bbb0..20c9a288 100644 --- a/plugin/python/vdebug/event.py +++ b/plugin/python/vdebug/event.py @@ -131,11 +131,11 @@ class StackWindowLineSelectEvent(Event): """Move the the currently selected file and line in the stack window """ def execute(self,runner): - lineno = vim.current.window.cursor[0] + stacklineno = vim.current.window.cursor[0] - vdebug.log.Log("User action in stack window, line %s" % lineno,\ + vdebug.log.Log("User action in stack window, line %s" % stacklineno,\ vdebug.log.Logger.DEBUG) - line = runner.ui.stackwin.buffer[lineno-1] + line = runner.ui.stackwin.buffer[stacklineno-1] if line.find(" @ ") == -1: return False filename_pos = line.find(" @ ") + 3 @@ -145,6 +145,8 @@ def execute(self,runner): lineno = file_and_line[line_pos+1:] runner.ui.sourcewin.set_file(file) runner.ui.sourcewin.set_line(lineno) + runner.ui.sourcewin.place_stack_sign(lineno) + runner.ui.stackwin.place_stack_sign(stacklineno) class WatchWindowPropertyGetEvent(Event): """Open a tree node in the watch window. diff --git a/plugin/python/vdebug/runner.py b/plugin/python/vdebug/runner.py index d828ae23..4d1eccd1 100644 --- a/plugin/python/vdebug/runner.py +++ b/plugin/python/vdebug/runner.py @@ -95,7 +95,7 @@ def save_code(self,code): return code def refresh(self,status): - """The main action performed after a deubugger step. + """The main action performed after a debugger step. Updates the status window, current stack, source file and line and watch window.""" @@ -128,6 +128,10 @@ def refresh(self,status): self.cur_file,\ self.cur_lineno) + """ Removing stack signs """ + self.ui.stackwin.remove_stack_sign() + self.ui.sourcewin.remove_stack_sign() + if self.saved_code != '': self.eval(self.saved_code) else: diff --git a/plugin/python/vdebug/ui/vimui.py b/plugin/python/vdebug/ui/vimui.py index 7337f280..8fcfa58c 100644 --- a/plugin/python/vdebug/ui/vimui.py +++ b/plugin/python/vdebug/ui/vimui.py @@ -218,6 +218,7 @@ class SourceWindow(vdebug.ui.interface.Window): file = None pointer_sign_id = '6145' breakpoint_sign_id = '6146' + stack_sign_id = '6147' def __init__(self,ui,winno): self.winno = str(winno) @@ -266,6 +267,17 @@ def place_pointer(self,line): def remove_pointer(self): vim.command('sign unplace %s' % self.pointer_sign_id) + def place_stack_sign(self, line): + self.remove_stack_sign() + vdebug.log.Log("Placing stack sign on line "+str(line),\ + vdebug.log.Logger.INFO) + vim.command('sign place '+self.stack_sign_id+\ + ' name=stack line='+str(line)+\ + ' file='+self.file) + + def remove_stack_sign(self): + vim.command('sign unplace %s' % self.stack_sign_id) + class Window(vdebug.ui.interface.Window): name = "WINDOW" open_cmd = "new" @@ -280,6 +292,9 @@ def __init__(self,ui,open_cmd): def getwinnr(self): return int(vim.eval("bufwinnr('"+self.name+"')")) + def focus(self): + vim.command(str(self.getwinnr())+"wincmd w") + def set_height(self,height): height = int(height) minheight = int(vim.eval("&winminheight")) @@ -432,6 +447,7 @@ def write(self, msg, return_focus = True): class StackWindow(Window): name = "DebuggerStack" + stack_sign_id = '6148' def on_create(self): self.command('inoremap '+\ @@ -448,6 +464,17 @@ def on_create(self): def write(self, msg, return_focus = True): Window.write(self, msg, after="normal gg") + def place_stack_sign(self, line): + self.remove_stack_sign() + self.focus() + vim.command('sign place ' + self.stack_sign_id +\ + ' name=stack' +\ + ' line=' + str(line) +\ + ' buffer=' + vim.eval("bufnr('%')")) + + def remove_stack_sign(self): + vim.command('sign unplace %s' % self.stack_sign_id) + class WatchWindow(Window): name = "DebuggerWatch" diff --git a/plugin/vdebug.vim b/plugin/vdebug.vim index 9c0c09e0..7a1644c9 100644 --- a/plugin/vdebug.vim +++ b/plugin/vdebug.vim @@ -131,10 +131,17 @@ end if hlexists("DbgBreakptSign") == 0 hi default DbgBreakptSign term=reverse ctermfg=White ctermbg=Green guifg=#ffffff guibg=#00ff00 end +if hlexists("DbgStackLine") == 0 + hi default DbgStackLine term=reverse ctermfg=White ctermbg=Blue guifg=#ffffff guibg=#0000ff +end +if hlexists("DbgStackSign") == 0 + hi default DbgStackSign term=reverse ctermfg=White ctermbg=Blue guifg=#ffffff guibg=#0000ff +end " Signs and highlighted lines for breakpoints, etc. sign define current text=-> texthl=DbgCurrentSign linehl=DbgCurrentLine sign define breakpt text=B> texthl=DbgBreakptSign linehl=DbgBreakptLine +sign define stack text=#> texthl=DbgStackSign linehl=DbgStackLine function! s:BreakpointTypes(A,L,P) let arg_to_cursor = strpart(a:L,11,a:P) From 4a8e777b68872fe8b2f207d505ebcfa506536947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nilo=20C=C3=A9sar=20Teixeira?= Date: Wed, 8 Jun 2016 23:05:37 -0300 Subject: [PATCH 3/7] Added feature of context_get in any stack depth Now Vdebug can query any stack depth, and the corresponding variables and values will appear in the watch window. Also, the stack depth file and line number will also appear correctly. A visual sign (#>) was introduced to mark clearly the source and stack windows for the current stack depth and file_and_line. When the debugging resumes, these stack signs are removed from the ui. Also updated the docs with a short description of these features. --- doc/Vdebug.txt | 14 ++++++++++---- plugin/python/vdebug/dbgp.py | 8 ++++---- plugin/python/vdebug/event.py | 13 +++++++------ plugin/python/vdebug/runner.py | 17 ++++++++++++++--- plugin/python/vdebug/ui/vimui.py | 9 ++++++++- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/doc/Vdebug.txt b/doc/Vdebug.txt index af55122d..f61cfa12 100644 --- a/doc/Vdebug.txt +++ b/doc/Vdebug.txt @@ -443,7 +443,8 @@ the current debugger status, connection details and a help message. This shows the current position of the debugger. The file will automatically change as the debugger pauses in different parts of the code, and the current -line is shown with a "->" sign in the margin. +line is shown centered vertically in the source window, with a "->" sign +in the margin. Don't edit the contents of the file when in debug mode, and especially don't edit without saving - this causes problems when swapping between files. @@ -472,8 +473,8 @@ strings to indicate relationships. The compact version has a variable on each line, and works better for smaller screens. To set this option, see |VdebugOptions-watch_window_style|. -The watch window automatically updates every time the debugger pauses, so -nothing needs to be done on your part. +The watch window automatically updates every time the debugger pauses, +or a stack jump is made on the stack window (see next topic). You can also see variables from different contexts. For example, PHP has normal context variables and global variables, and the debugging engine differentiates @@ -498,7 +499,12 @@ below show the path the script has taken. Like the watch window, the stack will update automatically every time the debugger pauses. You can jump to a place in the stack by putting your cursor over a line and pressing () or by double clicking with your mouse -(if you have mouse support enabled). +(if you have mouse support enabled). The watch window will be updated +with the file name and line number of the file in the current stack +depth (i.e. the index in the stack activated by ou double +click - the "stack jump"), and the stack window and the source window +will have a "#>" sign in their left margin marking the current stack +depth and the corresponding source line number, respectively. ------------------------------------------------------------------------------ 4.2.4 The status window *VdebugStatusWindow* diff --git a/plugin/python/vdebug/dbgp.py b/plugin/python/vdebug/dbgp.py index 0617041e..f38620ba 100644 --- a/plugin/python/vdebug/dbgp.py +++ b/plugin/python/vdebug/dbgp.py @@ -335,11 +335,11 @@ def stack_get(self): """ return self.send_cmd('stack_get','',StackGetResponse) - def context_get(self,context = 0): + def context_get(self,context = 0, depth = 0): """Get the context variables. """ return self.send_cmd('context_get',\ - '-c %i' % int(context),\ + '-c %i -d %i' % (int(context), int(depth)),\ ContextGetResponse) def context_names(self): @@ -347,10 +347,10 @@ def context_names(self): """ return self.send_cmd('context_names','',ContextNamesResponse) - def property_get(self,name): + def property_get(self,name, depth = 0): """Get a property. """ - return self.send_cmd('property_get','-n %s -d 0' % name,ContextGetResponse) + return self.send_cmd('property_get','-n %s -d %i' % (name, int(depth)),ContextGetResponse) def detach(self): """Tell the debugger to detach itself from this diff --git a/plugin/python/vdebug/event.py b/plugin/python/vdebug/event.py index 20c9a288..c5386c07 100644 --- a/plugin/python/vdebug/event.py +++ b/plugin/python/vdebug/event.py @@ -135,18 +135,19 @@ def execute(self,runner): vdebug.log.Log("User action in stack window, line %s" % stacklineno,\ vdebug.log.Logger.DEBUG) - line = runner.ui.stackwin.buffer[stacklineno-1] - if line.find(" @ ") == -1: - return False - filename_pos = line.find(" @ ") + 3 - file_and_line = line[filename_pos:] + file_and_line = runner.ui.stackwin.get_file_and_line(stacklineno) line_pos = file_and_line.rfind(":") file = vdebug.util.LocalFilePath(file_and_line[:line_pos]) + + """ Setting stack depth and current file_and_line in runner """ + runner.set_context_stack_info(stacklineno - 1, file_and_line) + lineno = file_and_line[line_pos+1:] runner.ui.sourcewin.set_file(file) runner.ui.sourcewin.set_line(lineno) runner.ui.sourcewin.place_stack_sign(lineno) runner.ui.stackwin.place_stack_sign(stacklineno) + runner.get_context(0) class WatchWindowPropertyGetEvent(Event): """Open a tree node in the watch window. @@ -164,7 +165,7 @@ def execute(self,runner): raise EventError("Cannot read the selected property") name = line[pointer_index+step:eq_index-1] - context_res = runner.api.property_get(name) + context_res = runner.api.property_get(name, runner.context_stack_depth) rend = vdebug.ui.vimui.ContextGetResponseRenderer(context_res) output = rend.render(pointer_index - 1) if vdebug.opts.Options.get('watch_window_style') == 'expanded': diff --git a/plugin/python/vdebug/runner.py b/plugin/python/vdebug/runner.py index 4d1eccd1..bd3c92cc 100644 --- a/plugin/python/vdebug/runner.py +++ b/plugin/python/vdebug/runner.py @@ -69,6 +69,10 @@ def open(self): status = self.api.step_into() else: status = self.api.run() + + """ Updating stack on open, for wathwin correct title """ + self.update_stack() + self.set_context_stack_info(0) self.refresh(status) except Exception: self.close() @@ -142,11 +146,11 @@ def get_context(self,context_id = 0): self.ui.tracewin.clean() name = self.context_names[context_id] vdebug.log.Log("Getting %s variables" % name) - context_res = self.api.context_get(context_id) + context_res = self.api.context_get(context_id, self.context_stack_depth) rend = vdebug.ui.vimui.ContextGetResponseRenderer(\ - context_res,"%s at %s:%s" \ - %(name,self.ui.sourcewin.file,self.cur_lineno),\ + context_res,"%s at %s" \ + %(name, self.context_file_and_line),\ self.context_names, context_id) self.ui.watchwin.accept_renderer(rend) @@ -349,6 +353,13 @@ def update_stack(self): renderer = vdebug.ui.vimui.StackGetResponseRenderer(res) self.ui.stackwin.accept_renderer(renderer) return res + + def set_context_stack_info(self, stack_depth, file_and_line = ''): + """ stack_depth parameter is zero-based """ + self.context_stack_depth = stack_depth + if (file_and_line == ''): + file_and_line = self.ui.stackwin.get_file_and_line(stack_depth + 1) + self.context_file_and_line = file_and_line def detach(self): """Detach the debugger engine, and allow it to continue execution. diff --git a/plugin/python/vdebug/ui/vimui.py b/plugin/python/vdebug/ui/vimui.py index 8fcfa58c..ce2b1798 100644 --- a/plugin/python/vdebug/ui/vimui.py +++ b/plugin/python/vdebug/ui/vimui.py @@ -475,6 +475,13 @@ def place_stack_sign(self, line): def remove_stack_sign(self): vim.command('sign unplace %s' % self.stack_sign_id) + def get_file_and_line(self, stacklineno): + line = self.buffer[stacklineno - 1] + if line.find(" @ ") == -1: + return False + filename_pos = line.find(" @ ") + 3 + return line[filename_pos:] + class WatchWindow(Window): name = "DebuggerWatch" @@ -568,7 +575,7 @@ def render(self): %{'num':s.get('level'),'where':where,\ 'file':str(file.as_local()),'line':s.get('lineno')} string += line + "\n" - return string + return string[:-1] class ContextGetResponseRenderer(ResponseRenderer): From d0f94180e93b7d865b83a1be7c6fbe3bd7b551f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nilo=20C=C3=A9sar=20Teixeira?= Date: Wed, 15 Jun 2016 20:36:46 -0300 Subject: [PATCH 4/7] Bugfix: context stack depth set to zero on resume debug A bug in previous commit was not setting runner.context_stack_depth to zero when resuming the debugging session with a step or run command. Also the Watch window was not showing the current file and line number in the situation above. --- plugin/python/vdebug/runner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/python/vdebug/runner.py b/plugin/python/vdebug/runner.py index bd3c92cc..5d2d44e2 100644 --- a/plugin/python/vdebug/runner.py +++ b/plugin/python/vdebug/runner.py @@ -135,6 +135,7 @@ def refresh(self,status): """ Removing stack signs """ self.ui.stackwin.remove_stack_sign() self.ui.sourcewin.remove_stack_sign() + self.set_context_stack_info(0) if self.saved_code != '': self.eval(self.saved_code) From f8f8005942e3c27954516c891bf5d4583dd43ed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nilo=20C=C3=A9sar=20Teixeira?= Date: Thu, 16 Jun 2016 20:23:05 -0300 Subject: [PATCH 5/7] Property expansion enhancement in Watch window - all children Now a property expansion in Watch window list all children from that property. The previous behavior was listing only elements (i.e. based on the pagesize attribute of parent element). As before, to invoke a property expansion either double-click it or place the cursor over it and hit Enter. --- plugin/python/vdebug/dbgp.py | 44 +++++++++++++++++++- plugin/python/vdebug/event.py | 3 +- plugin/python/vdebug/runner.py | 2 + tests/test_dbgp_response.py | 76 +++++++++++++++++++++------------- 4 files changed, 94 insertions(+), 31 deletions(-) diff --git a/plugin/python/vdebug/dbgp.py b/plugin/python/vdebug/dbgp.py index f38620ba..1668b9c3 100644 --- a/plugin/python/vdebug/dbgp.py +++ b/plugin/python/vdebug/dbgp.py @@ -7,6 +7,7 @@ import vdebug.log import base64 import time +import re """ Response objects for the DBGP module.""" @@ -119,9 +120,28 @@ def __init__(self,response,cmd,cmd_args,api): Response.__init__(self,response,cmd,cmd_args,api) self.properties = [] + def get_page(self, cmd_args): + opts = re.compile('-p (\d+)') + page = None + result = opts.search(cmd_args) + if result != None: + page = int(result.group(1)) + return page + def get_context(self): for c in list(self.as_xml()): self.create_properties(ContextProperty(c)) + page = self.get_page(self.cmd_args) + if page == 0: + """ Loop through pages 2 to num_pages """ + for p in xrange(1, self.properties[0].num_pages): + nth_cmd_args = self.cmd_args.replace('-p ' + str(page), '-p ' + str(p)) + nth_prop = self.api.send_cmd(self.cmd, nth_cmd_args, ContextGetResponse) + """ First row is duplicated on pages > 0 so delete it """ + nth_page = nth_prop.get_context() + del nth_page[0] + + self.properties.extend(nth_page) return self.properties @@ -347,10 +367,10 @@ def context_names(self): """ return self.send_cmd('context_names','',ContextNamesResponse) - def property_get(self,name, depth = 0): + def property_get(self,name, depth = 0, page = 0): """Get a property. """ - return self.send_cmd('property_get','-n %s -d %i' % (name, int(depth)),ContextGetResponse) + return self.send_cmd('property_get','-n %s -d %i -p %i' % (name, int(depth), int(page)),ContextGetResponse) def detach(self): """Tell the debugger to detach itself from this @@ -527,6 +547,9 @@ class ContextProperty: def __init__(self,node,parent = None,depth = 0): self.parent = parent + """ Every child property will have a zero-based page property set """ + if self.parent: + self.page = parent.page self.__determine_type(node) self._determine_displayname(node) self.encoding = node.get('encoding') @@ -606,6 +629,23 @@ def _determine_children(self,node): children = int(children) self.num_declared_children = children self.has_children = children > 0 + """ If the current element has children, initialize page properties """ + self.page = None + self.pagesize = None + self.num_pages = 0 + if self.has_children: + self.page = node.get('page') + self.pagesize = node.get('pagesize') + if self.page == None or self.pagesize == None: + self.page = 0 + self.pagesize = 0 + self.num_pages = 0 + else: + self.page = int(self.page) + self.pagesize = int(self.pagesize) + self.num_pages = self.num_declared_children / self.pagesize + if (self.num_declared_children % self.pagesize): + self.num_pages += 1 self.children = [] def __init_children(self,node): diff --git a/plugin/python/vdebug/event.py b/plugin/python/vdebug/event.py index c5386c07..660a1f53 100644 --- a/plugin/python/vdebug/event.py +++ b/plugin/python/vdebug/event.py @@ -165,7 +165,8 @@ def execute(self,runner): raise EventError("Cannot read the selected property") name = line[pointer_index+step:eq_index-1] - context_res = runner.api.property_get(name, runner.context_stack_depth) + """ Refactoring property_get with multiple pages """ + context_res = runner.property_get(name) rend = vdebug.ui.vimui.ContextGetResponseRenderer(context_res) output = rend.render(pointer_index - 1) if vdebug.opts.Options.get('watch_window_style') == 'expanded': diff --git a/plugin/python/vdebug/runner.py b/plugin/python/vdebug/runner.py index 5d2d44e2..427cb7d7 100644 --- a/plugin/python/vdebug/runner.py +++ b/plugin/python/vdebug/runner.py @@ -166,6 +166,8 @@ def get_context(self,context_id = 0): except vdebug.dbgp.EvalError: self.ui.tracewin.render_in_error_case() + def property_get(self, name): + return self.api.property_get(name, self.context_stack_depth) def toggle_breakpoint_window(self): """Open or close the breakpoint window. diff --git a/tests/test_dbgp_response.py b/tests/test_dbgp_response.py index c302884c..7c2eff06 100644 --- a/tests/test_dbgp_response.py +++ b/tests/test_dbgp_response.py @@ -121,39 +121,29 @@ class ContextGetTest(unittest.TestCase): type="string" size="3" encoding="base64"> +type="uninitialized"> """ def test_properties_are_objects(self): res = vdebug.dbgp.ContextGetResponse(self.response,"","",Mock()) context = res.get_context() - assert len(context) == 23 + assert len(context) == 13 self.assertIsInstance(context[0],vdebug.dbgp.ContextProperty) def test_int_property_attributes(self): @@ -165,6 +155,7 @@ def test_int_property_attributes(self): assert prop.type == "int" assert prop.value == "4" assert prop.has_children == False + assert prop.page == None def test_array_property_attributes(self): res = vdebug.dbgp.ContextGetResponse(self.response,"","",Mock()) @@ -176,6 +167,7 @@ def test_array_property_attributes(self): assert prop.value == "" assert prop.has_children == True assert prop.child_count() == 4 + assert prop.page == 0 def test_string_property_attributes(self): res = vdebug.dbgp.ContextGetResponse(self.response,"","",Mock()) @@ -188,6 +180,34 @@ def test_string_property_attributes(self): assert prop.has_children == False assert prop.size == "19" + def test_even_num_pages(self): + res = vdebug.dbgp.ContextGetResponse(self.response,"","",Mock()) + context = res.get_context() + prop = context[7] + + assert prop.display_name == "$even_num_pages_attr" + assert prop.type == "array" + assert prop.value == "" + assert prop.has_children == True + assert prop.child_count() == 2 + assert prop.page == 0 + assert prop.pagesize == 2 + assert prop.num_pages == 2 + + def test_odd_num_pages(self): + res = vdebug.dbgp.ContextGetResponse(self.response,"","",Mock()) + context = res.get_context() + prop = context[10] + + assert prop.display_name == "$odd_num_pages_attr" + assert prop.type == "array" + assert prop.value == "" + assert prop.has_children == True + assert prop.child_count() == 2 + assert prop.page == 0 + assert prop.pagesize == 2 + assert prop.num_pages == 3 + class ContextGetAlternateTest(unittest.TestCase): response = """ Date: Mon, 20 Jun 2016 12:11:08 -0300 Subject: [PATCH 6/7] (i.e. context get) now fetches all children of tree depth==1 The previous commit introduced the feature of getting all children from parent elements in the watchwin tree. This worked for property get UI commands issued from the Watch window itself. Now, the default context get (when hit or stepping through code or coming from Stack window) shows all children of tree depth==1. Before this commit, context get would only show number of children. --- plugin/python/vdebug/dbgp.py | 12 +++++--- plugin/python/vdebug/event.py | 2 +- plugin/python/vdebug/runner.py | 1 + plugin/python/vdebug/ui/vimui.py | 12 ++++++++ tests/test_dbgp_response.py | 51 +++++++++++++++++++++----------- 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/plugin/python/vdebug/dbgp.py b/plugin/python/vdebug/dbgp.py index 1668b9c3..630338d3 100644 --- a/plugin/python/vdebug/dbgp.py +++ b/plugin/python/vdebug/dbgp.py @@ -128,10 +128,13 @@ def get_page(self, cmd_args): page = int(result.group(1)) return page + def show_children(self): + return self.cmd == 'property_get' + def get_context(self): - for c in list(self.as_xml()): - self.create_properties(ContextProperty(c)) page = self.get_page(self.cmd_args) + for c in list(self.as_xml()): + self.create_properties(ContextProperty(c, init_children=self.show_children())) if page == 0: """ Loop through pages 2 to num_pages """ for p in xrange(1, self.properties[0].num_pages): @@ -545,7 +548,7 @@ class ContextProperty: ns = '{urn:debugger_protocol_v1}' - def __init__(self,node,parent = None,depth = 0): + def __init__(self,node,parent = None,depth = 0, init_children = True): self.parent = parent """ Every child property will have a zero-based page property set """ if self.parent: @@ -561,7 +564,8 @@ def __init__(self,node,parent = None,depth = 0): self._determine_children(node) self.__determine_value(node) - self.__init_children(node) + if init_children: + self.__init_children(node) if self.type == 'scalar': self.size = len(self.value) - 2 diff --git a/plugin/python/vdebug/event.py b/plugin/python/vdebug/event.py index 660a1f53..ffdf4310 100644 --- a/plugin/python/vdebug/event.py +++ b/plugin/python/vdebug/event.py @@ -162,7 +162,7 @@ def execute(self,runner): eq_index = line.find('=') if eq_index == -1: - raise EventError("Cannot read the selected property") + return name = line[pointer_index+step:eq_index-1] """ Refactoring property_get with multiple pages """ diff --git a/plugin/python/vdebug/runner.py b/plugin/python/vdebug/runner.py index 427cb7d7..8a61f0a3 100644 --- a/plugin/python/vdebug/runner.py +++ b/plugin/python/vdebug/runner.py @@ -155,6 +155,7 @@ def get_context(self,context_id = 0): self.context_names, context_id) self.ui.watchwin.accept_renderer(rend) + self.ui.watchwin.open_child_properties(self) if self.ui.tracewin.is_tracing(): try: diff --git a/plugin/python/vdebug/ui/vimui.py b/plugin/python/vdebug/ui/vimui.py index ce2b1798..ff297869 100644 --- a/plugin/python/vdebug/ui/vimui.py +++ b/plugin/python/vdebug/ui/vimui.py @@ -4,6 +4,7 @@ import vim import vdebug.log import vdebug.opts +import vdebug.event class Ui(vdebug.ui.interface.Ui): """Ui layer which manages the Vim windows. @@ -500,6 +501,17 @@ def on_create(self): def write(self, msg, return_focus = True): Window.write(self, msg, after="normal gg") + def open_child_properties(self, runner): + self.focus() + last_line_idx = int(vim.eval("line('$')")) - 1 + first_line_idx = -1 + for idx in xrange(last_line_idx, first_line_idx, -1): + self.command('normal ' + str(idx+1) + 'G') + line = vim.current.buffer[idx] + if line.startswith(' ' + vdebug.opts.Options.get('marker_closed_tree')): + vdebug.event.WatchWindowPropertyGetEvent().execute(runner) + self.command('normal gg') + class StatusWindow(Window): name = "DebuggerStatus" diff --git a/tests/test_dbgp_response.py b/tests/test_dbgp_response.py index 7c2eff06..c943f7fc 100644 --- a/tests/test_dbgp_response.py +++ b/tests/test_dbgp_response.py @@ -143,7 +143,14 @@ class ContextGetTest(unittest.TestCase): def test_properties_are_objects(self): res = vdebug.dbgp.ContextGetResponse(self.response,"","",Mock()) context = res.get_context() - assert len(context) == 13 + """ + Children are only fetched in UI. + Every context get command, or property get in Watch window, + Trigger a property_get command for the property currently focused on watchwin. + This fetches all pages, and therefore + Here every child property is bypassed + """ + assert len(context) == 5 self.assertIsInstance(context[0],vdebug.dbgp.ContextProperty) def test_int_property_attributes(self): @@ -166,30 +173,33 @@ def test_array_property_attributes(self): assert prop.type == "array" assert prop.value == "" assert prop.has_children == True - assert prop.child_count() == 4 + """ + Children are only fetched in UI. + Every context get command, or property get in Watch window, + Trigger a property_get command for the property currently focused on watchwin. + This fetches all pages, and therefore + Here every child property is bypassed + """ + assert prop.child_count() == 0 assert prop.page == 0 - def test_string_property_attributes(self): - res = vdebug.dbgp.ContextGetResponse(self.response,"","",Mock()) - context = res.get_context() - prop = context[2] - - assert prop.display_name == "$argv[0]" - assert prop.type == "string" - assert prop.value == "`/usr/local/bin/cake`" - assert prop.has_children == False - assert prop.size == "19" - def test_even_num_pages(self): res = vdebug.dbgp.ContextGetResponse(self.response,"","",Mock()) context = res.get_context() - prop = context[7] + prop = context[3] assert prop.display_name == "$even_num_pages_attr" assert prop.type == "array" assert prop.value == "" assert prop.has_children == True - assert prop.child_count() == 2 + """ + Children are only fetched in UI. + Every context get command, or property get in Watch window, + Trigger a property_get command for the property currently focused on watchwin. + This fetches all pages, and therefore + Here every child property is bypassed + """ + assert prop.child_count() == 0 assert prop.page == 0 assert prop.pagesize == 2 assert prop.num_pages == 2 @@ -197,13 +207,20 @@ def test_even_num_pages(self): def test_odd_num_pages(self): res = vdebug.dbgp.ContextGetResponse(self.response,"","",Mock()) context = res.get_context() - prop = context[10] + prop = context[4] assert prop.display_name == "$odd_num_pages_attr" assert prop.type == "array" assert prop.value == "" assert prop.has_children == True - assert prop.child_count() == 2 + """ + Children are only fetched in UI. + Every context get command, or property get in Watch window, + Trigger a property_get command for the property currently focused on watchwin. + This fetches all pages, and therefore + Here every child property is bypassed + """ + assert prop.child_count() == 0 assert prop.page == 0 assert prop.pagesize == 2 assert prop.num_pages == 3 From d6bc9e8c0d57ee2497fff303a8fb2032845fee2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nilo=20C=C3=A9sar=20Teixeira?= Date: Wed, 5 Oct 2016 07:30:10 -0300 Subject: [PATCH 7/7] Fixes #1 bug (broken continuous_mode) Now the setting continuous_mode, if set, is working again: debugger starts listening on finished debugging session. --- plugin/python/vdebug/runner.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugin/python/vdebug/runner.py b/plugin/python/vdebug/runner.py index 8a61f0a3..7fc03690 100644 --- a/plugin/python/vdebug/runner.py +++ b/plugin/python/vdebug/runner.py @@ -70,9 +70,10 @@ def open(self): else: status = self.api.run() - """ Updating stack on open, for wathwin correct title """ - self.update_stack() - self.set_context_stack_info(0) + """ Updating stack on open, for watchwin correct title """ + if status in ["running", "break"]: + self.update_stack() + self.set_context_stack_info(0) self.refresh(status) except Exception: self.close()