summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIke Devolder <ike.devolder@gmail.com>2019-07-04 23:32:08 +0200
committerGitHub <noreply@github.com>2019-07-04 23:32:08 +0200
commitf16351a94bc784a7c5e20e4b1a08f2f4de34f2be (patch)
tree525d7ca4b63e58c4c6b7763b48746d9884c294d9
parente3af9800fd19f903a96e54dd4b15886a195cc1ee (diff)
parent3223b2aea1d80d5f568be5efd32023d12cbff3c5 (diff)
downloadvdebug-f16351a94bc784a7c5e20e4b1a08f2f4de34f2be.zip
Merge pull request #404 from Garethp/breakpoint-toggle
Adding support for breakpoint enabling/disabling (Solve #393)
-rw-r--r--plugin/vdebug.vim6
-rw-r--r--python3/vdebug/breakpoint.py47
-rw-r--r--python3/vdebug/dbgp.py6
-rw-r--r--python3/vdebug/debugger_interface.py25
-rw-r--r--python3/vdebug/event.py116
-rw-r--r--python3/vdebug/ui/vimui.py11
-rw-r--r--python3/vdebug/util.py3
7 files changed, 210 insertions, 4 deletions
diff --git a/plugin/vdebug.vim b/plugin/vdebug.vim
index 5997950..084e640 100644
--- a/plugin/vdebug.vim
+++ b/plugin/vdebug.vim
@@ -90,6 +90,7 @@ let g:vdebug_options_defaults = {
\ 'marker_open_tree' : '▾',
\ 'sign_breakpoint' : '▷',
\ 'sign_current' : '▶',
+\ 'sign_disabled': '▌▌',
\ 'continuous_mode' : 1,
\ 'background_listener' : 1,
\ 'auto_start' : 1,
@@ -120,7 +121,8 @@ python3 import vdebug.debugger_interface
python3 debugger = vdebug.debugger_interface.DebuggerInterface()
" Commands
-command! -nargs=? -complete=customlist,s:BreakpointTypes Breakpoint python3 debugger.set_breakpoint(<q-args>)
+command! -nargs=? -complete=customlist,s:BreakpointTypes Breakpoint python3 debugger.cycle_breakpoint(<q-args>)
+command! -nargs=? -complete=customlist,s:BreakpointTypes SetBreakpoint python3 debugger.set_breakpoint(<q-args>)
command! VdebugStart python3 debugger.run()
command! -nargs=? BreakpointRemove python3 debugger.remove_breakpoint(<q-args>)
command! BreakpointWindow python3 debugger.toggle_breakpoint_window()
@@ -129,6 +131,7 @@ command! -nargs=+ -complete=customlist,s:OptionNames VdebugOpt :call Vdebug_set_
command! -nargs=+ VdebugPathMap :call Vdebug_path_map(<f-args>)
command! -nargs=+ VdebugAddPathMap :call Vdebug_add_path_map(<f-args>)
command! -nargs=? VdebugTrace python3 debugger.handle_trace(<q-args>)
+command! -nargs=? BreakpointStatus python3 debugger.breakpoint_status(<q-args>)
if hlexists('DbgCurrentLine') == 0
hi default DbgCurrentLine term=reverse ctermfg=White ctermbg=Red guifg=#ffffff guibg=#ff0000
@@ -147,6 +150,7 @@ end
function! s:DefineSigns()
exe 'sign define breakpt text=' . g:vdebug_options['sign_breakpoint'] . ' texthl=DbgBreakptSign linehl=DbgBreakptLine'
exe 'sign define current text=' . g:vdebug_options['sign_current'] . ' texthl=DbgCurrentSign linehl=DbgCurrentLine'
+ exe 'sign define breakpt_dis text=' . g:vdebug_options['sign_disabled'] . ' texthl=DbgDisabledSign linehl=DbgDisabledLine'
endfunction
function! s:BreakpointTypes(A,L,P)
diff --git a/python3/vdebug/breakpoint.py b/python3/vdebug/breakpoint.py
index ccabcd9..48b529d 100644
--- a/python3/vdebug/breakpoint.py
+++ b/python3/vdebug/breakpoint.py
@@ -41,6 +41,33 @@ class Store:
res = self.api.breakpoint_set(breakpoint.get_cmd())
breakpoint.set_debugger_id(res.get_id())
+ def toggle_breakpoint_by_id(self, id):
+ id = str(id)
+ if id not in self.breakpoints:
+ raise error.BreakpointError("No breakpoint matching ID %s" % id)
+ if self.breakpoints[id].enabled:
+ self.disable_breakpoint_by_id(id)
+ else:
+ self.enable_breakpoint_by_id(id)
+
+ def enable_breakpoint_by_id(self, id):
+ id = str(id)
+ if id not in self.breakpoints:
+ raise error.BreakpointError("No breakpoint matching ID %s" % id)
+ dbg_id = self.breakpoints[id].get_debugger_id()
+ if dbg_id is not None:
+ self.api.breakpoint_enable(dbg_id)
+ self.breakpoints[id].on_enable()
+
+ def disable_breakpoint_by_id(self, id):
+ id = str(id)
+ if id not in self.breakpoints:
+ raise error.BreakpointError("No breakpoint matching ID %s" % id)
+ dbg_id = self.breakpoints[id].get_debugger_id()
+ if dbg_id is not None:
+ self.api.breakpoint_disable(dbg_id)
+ self.breakpoints[id].on_disable()
+
def remove_breakpoint(self, breakpoint):
self.remove_breakpoint_by_id(breakpoint.get_id())
@@ -63,6 +90,13 @@ class Store:
self.remove_breakpoint_by_id(id)
self.breakpoints = {}
+ def get_breakpoint_by_id(self, id):
+ id = str(id)
+ if id not in list(self.breakpoints.keys()):
+ return None
+
+ return self.breakpoints[id]
+
def find_breakpoint(self, file, line):
found = None
for bp in self.breakpoints.values():
@@ -88,6 +122,7 @@ class Breakpoint:
self.id = Breakpoint.id
Breakpoint.id += 1
self.ui = ui
+ self.enabled = True
def get_id(self):
return self.id
@@ -101,6 +136,14 @@ class Breakpoint:
def on_add(self):
self.ui.register_breakpoint(self)
+ def on_enable(self):
+ self.enabled = True
+ self.ui.enable_breakpoint(self)
+
+ def on_disable(self):
+ self.enabled = False
+ self.ui.disable_breakpoint(self)
+
def on_remove(self):
self.ui.remove_breakpoint(self)
@@ -188,8 +231,8 @@ class LineBreakpoint(Breakpoint):
return self.file
def get_cmd(self):
- return '-t {} -f "{}" -n {} -s enabled'.format(
- self.type, self.file.as_remote(), self.line)
+ return '-t {} -f "{}" -n {} -s {}'.format(
+ self.type, self.file.as_remote(), self.line, "enabled" if self.enabled else "disabled")
class TemporaryLineBreakpoint(LineBreakpoint):
diff --git a/python3/vdebug/dbgp.py b/python3/vdebug/dbgp.py
index bfa2ec8..91d5912 100644
--- a/python3/vdebug/dbgp.py
+++ b/python3/vdebug/dbgp.py
@@ -381,6 +381,12 @@ class Api:
def breakpoint_list(self):
return self.send_cmd('breakpoint_list')
+ def breakpoint_disable(self, id):
+ return self.send_cmd('breakpoint_update', '-d %i -s disabled' % id, Response)
+
+ def breakpoint_enable(self, id):
+ return self.send_cmd('breakpoint_update', '-d %i -s enabled' % id, Response)
+
def breakpoint_remove(self, id):
"""Remove a breakpoint by ID.
diff --git a/python3/vdebug/debugger_interface.py b/python3/vdebug/debugger_interface.py
index 030d508..b154291 100644
--- a/python3/vdebug/debugger_interface.py
+++ b/python3/vdebug/debugger_interface.py
@@ -114,6 +114,31 @@ class DebuggerInterface:
"""
self.session_handler.dispatch_event("set_breakpoint", args)
+ def cycle_breakpoint(self, args=None):
+ """Cycle a breakpoint between Enabled, Disabled and Removed
+ """
+ self.session_handler.dispatch_event("cycle_breakpoint", args)
+
+ def toggle_breakpoint(self, args=None):
+ """Toggle a breakpoint, specified by args
+ """
+ self.session_handler.dispatch_event("toggle_breakpoint", args)
+
+ def enable_breakpoint(self, args=None):
+ """Enable a breakpoint, specified by args
+ """
+ self.session_handler.dispatch_event("enable_breakpoint", args)
+
+ def disable_breakpoint(self, args=None):
+ """Disable a breakpoint, specified by args
+ """
+ self.session_handler.dispatch_event("disable_breakpoint", args)
+
+ def breakpoint_status(self, args=None):
+ """Either gets the status of a breakpoint or changes it
+ """
+ self.session_handler.dispatch_event("breakpoint_status", args)
+
def remove_breakpoint(self, args=None):
"""Remove one or more breakpoints, specified by args.
"""
diff --git a/python3/vdebug/event.py b/python3/vdebug/event.py
index 49eb893..7463f9a 100644
--- a/python3/vdebug/event.py
+++ b/python3/vdebug/event.py
@@ -401,6 +401,117 @@ class SetBreakpointEvent(Event):
self.session_handler.breakpoints().add_breakpoint(bp)
+class BreakpointStatusEvent(Event):
+ def parseArgs(self, args):
+ if args is None:
+ args = ""
+ args = args.strip()
+
+ arg_parts = args.split(' ')
+ first_param = arg_parts.pop(0)
+ if first_param == "":
+ return { "id": None, "action": None }
+
+ if first_param in ("toggle", "enable", "disable"):
+ return { "id": None, "action": first_param }
+
+ if len(arg_parts) == 0:
+ return { "id": first_param , "action": None }
+
+ second_param = arg_parts.pop(0)
+ return { "id": first_param, "action": second_param }
+
+ def get_breakpoint(self, id):
+ if id is not None:
+ return self.session_handler.breakpoints().get_breakpoint_by_id(id)
+
+ """ Line breakpoint """
+ try:
+ file = self.ui.get_current_file()
+ line = self.ui.get_current_row()
+ id = self.session_handler.breakpoints().find_breakpoint(file, line)
+ if id is None:
+ return None
+
+ return self.session_handler.breakpoints().get_breakpoint_by_id(id)
+ except error.FilePathError:
+ raise error.BreakpointError('No file, cannot set breakpoint')
+
+ def run(self, args):
+ parsed_args = self.parseArgs(args)
+ id = parsed_args["id"]
+ action = parsed_args["action"]
+ bp = self.get_breakpoint(id)
+
+ if bp is None:
+ print("No breakpoint found")
+ return
+
+ if action is None:
+ print("enabled" if bp.enabled else "disabled")
+ return
+
+ if action == "enable":
+ return self.dispatch("enable_breakpoint", str(bp.id))
+
+ if action == "disable":
+ return self.dispatch("disable_breakpoint", str(bp.id))
+
+ if action == "toggle":
+ return self.dispatch("toggle_breakpoint", str(bp.id))
+
+
+class CycleBreakpointStatusEvent(BreakpointStatusEvent):
+
+ def run(self, args):
+ parsed_args = self.parseArgs(args)
+ id = parsed_args["id"]
+ bp = self.get_breakpoint(id)
+
+ if bp is None:
+ self.dispatch("set_breakpoint", args)
+ return
+
+ if bp is not None:
+ if bp.enabled:
+ self.session_handler.breakpoints().disable_breakpoint_by_id(bp.id)
+ else:
+ self.session_handler.breakpoints().remove_breakpoint_by_id(bp.id)
+
+
+class ToggleBreakpointEvent(BreakpointStatusEvent):
+
+ def run(self, args):
+ parsed_args = self.parseArgs(args)
+ id = parsed_args["id"]
+ bp = self.get_breakpoint(id)
+
+ if bp is not None and bp.type == "line":
+ self.session_handler.breakpoints().toggle_breakpoint_by_id(bp.id)
+
+
+class EnableBreakpointEvent(BreakpointStatusEvent):
+
+ def run(self, args):
+ parsed_args = self.parseArgs(args)
+ id = parsed_args["id"]
+ bp = self.get_breakpoint(id)
+
+ if bp is not None and bp.type == "line":
+ self.session_handler.breakpoints().enable_breakpoint_by_id(id)
+
+
+class DisableBreakpointEvent(BreakpointStatusEvent):
+
+ def run(self, args):
+ parsed_args = self.parseArgs(args)
+ id = parsed_args["id"]
+ bp = self.get_breakpoint(id)
+
+ if bp is not None and bp.type == "line":
+ self.session_handler.breakpoints().disable_breakpoint_by_id(id)
+
+
class RemoveBreakpointEvent(Event):
def run(self, args):
@@ -506,6 +617,11 @@ class Dispatcher:
"eval": EvalEvent,
"set_eval_expression": SetEvalExpressionEvent,
"set_breakpoint": SetBreakpointEvent,
+ "cycle_breakpoint": CycleBreakpointStatusEvent,
+ "toggle_breakpoint": ToggleBreakpointEvent,
+ "enable_breakpoint": EnableBreakpointEvent,
+ "disable_breakpoint": DisableBreakpointEvent,
+ "breakpoint_status": BreakpointStatusEvent,
"get_context": GetContextEvent,
"reload_keymappings": ReloadKeymappingsEvent,
"remove_breakpoint": RemoveBreakpointEvent,
diff --git a/python3/vdebug/ui/vimui.py b/python3/vdebug/ui/vimui.py
index 7653966..d543ad5 100644
--- a/python3/vdebug/ui/vimui.py
+++ b/python3/vdebug/ui/vimui.py
@@ -204,6 +204,17 @@ class Ui(interface.Ui):
vim.command('sign place %s name=breakpt line=%s file=%s'
% (sign_id, line, file.as_local()))
+ def enable_breakpoint(self, breakpoint):
+ self.place_breakpoint(breakpoint.id, breakpoint.file, breakpoint.line)
+
+ def disable_breakpoint(self, breakpoint):
+ self.place_disabled_breakpoint(breakpoint.id, breakpoint.file, breakpoint.line)
+
+ @staticmethod
+ def place_disabled_breakpoint(sign_id, file, line):
+ vim.command('sign place %s name=breakpt_dis line=%s file=%s'
+ % (sign_id, line, file.as_local()))
+
def remove_breakpoint(self, breakpoint):
id = breakpoint.id
vim.command('sign unplace %i' % id)
diff --git a/python3/vdebug/util.py b/python3/vdebug/util.py
index 9ee1e49..653705e 100644
--- a/python3/vdebug/util.py
+++ b/python3/vdebug/util.py
@@ -104,7 +104,8 @@ class Keymapper:
"""Map and unmap key commands for the Vim user interface.
"""
- exclude = ["run", "close", "set_breakpoint", "eval_visual"]
+ exclude = ["run", "close", "set_breakpoint", "enable_breakpoint", "disable_breakpoint",
+ "toggle_breakpoint" "eval_visual"]
def __init__(self):
self.is_mapped = False