From bb829286d1a68e00181ed8b0683adf7dbaea5206 Mon Sep 17 00:00:00 2001 From: pablu Date: Sun, 29 Mar 2026 17:53:34 +0200 Subject: [PATCH] Add removing of breakpoints --- internal/bridge/client.go | 33 ++++++++++++++++++++++++--------- internal/bridge/protocol.go | 1 + python/pybug_runtime.py | 19 +++++++++++++++++++ ui/update.go | 7 +++++-- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/internal/bridge/client.go b/internal/bridge/client.go index 95c63a6..d3ebaca 100644 --- a/internal/bridge/client.go +++ b/internal/bridge/client.go @@ -8,6 +8,7 @@ import ( "io" "log/slog" "os/exec" + "slices" "sync" ) @@ -159,13 +160,19 @@ func (b *Bridge) Step() error { return nil } -func (b *Bridge) Breakpoint(file string, line int) error { - // Check if breakpoint already exists here +func (b *Bridge) Breakpoint(file string, line int) (set bool, err error) { if !b.running { - return ErrNotRunning + return false, ErrNotRunning } - requestId, cmd := makeCommand(BreakCommand, map[string]any{ + var command CommandType + if _, ok := b.breakpoints[file]; ok && slices.Contains(b.breakpoints[file], line) { + command = UnbreakCommand + } else { + command = BreakCommand + } + + requestId, cmd := makeCommand(command, map[string]any{ "file": file, "line": line, }) @@ -175,18 +182,26 @@ func (b *Bridge) Breakpoint(file string, line int) error { obj := <-c var m map[string]any - err := json.Unmarshal([]byte(obj), &m) + err = json.Unmarshal([]byte(obj), &m) if err != nil { - return err + return false, err } if m["status"] != "ok" { - return fmt.Errorf("error occured on break, err: %s", m["error"]) + return false, fmt.Errorf("error occured on break, err: %s", m["error"]) } - b.breakpoints[file] = append(b.breakpoints[file], line) + if command == BreakCommand { + b.breakpoints[file] = append(b.breakpoints[file], line) + return true, nil + } else { + breakpointsLen := len(b.breakpoints[file]) + index := slices.Index(b.breakpoints[file], line) + b.breakpoints[file][index] = b.breakpoints[file][breakpointsLen-1] - return nil + b.breakpoints[file] = b.breakpoints[file][0 : breakpointsLen-1] + return false, nil + } } func (b *Bridge) Continue() error { diff --git a/internal/bridge/protocol.go b/internal/bridge/protocol.go index c59d253..f8ddb6b 100644 --- a/internal/bridge/protocol.go +++ b/internal/bridge/protocol.go @@ -11,6 +11,7 @@ type CommandType string const ( ContinueCommand CommandType = "continue" BreakCommand CommandType = "break" + UnbreakCommand CommandType = "unbreak" LocalsCommand CommandType = "locals" StepCommand CommandType = "step" ) diff --git a/python/pybug_runtime.py b/python/pybug_runtime.py index 351917c..49441a7 100644 --- a/python/pybug_runtime.py +++ b/python/pybug_runtime.py @@ -92,6 +92,25 @@ class PyBugBridgeDebugger(bdb.Bdb): "status": "ok", } ) + case "unbreak": + err = self.clear_break(cmd["file"], cmd["line"]) + if err: + self.send( + { + "request_id": cmd["request_id"], + "event": "unbreak", + "status": "error", + "error": err, + } + ) + else: + self.send( + { + "request_id": cmd["request_id"], + "event": "unbreak", + "status": "ok", + } + ) def main(): diff --git a/ui/update.go b/ui/update.go index 7359502..9416025 100644 --- a/ui/update.go +++ b/ui/update.go @@ -72,7 +72,10 @@ func (m Model) HandleKeyMsg(key tea.KeyMsg) (tea.Model, tea.Cmd) { case "b": lineNumber := m.codeViewer.Cursor + 1 - m.bridge.Breakpoint(m.currentFile, lineNumber) + set, err := m.bridge.Breakpoint(m.currentFile, lineNumber) + if err != nil { + slog.Error("could not set or unset breakpoint", "error", err) + } if file, ok := m.breakpoints[m.currentFile]; ok { m.breakpoints[m.currentFile] = append(file, lineNumber) } else { @@ -83,7 +86,7 @@ func (m Model) HandleKeyMsg(key tea.KeyMsg) (tea.Model, tea.Cmd) { return m, func() tea.Msg { // check if this is in currently viewed file return codeviewer.BreakpointMsg{ - Added: true, + Added: set, Line: lineNumber, } }