diff --git a/pkg/terminal/command.go b/pkg/terminal/command.go index 50ab47ee..b0238077 100644 --- a/pkg/terminal/command.go +++ b/pkg/terminal/command.go @@ -1446,8 +1446,28 @@ func continueUntilCompleteNext(t *Term, state *api.DebuggerState, op string, sho } return nil } + skipBreakpoints := false for { - fmt.Printf("\tbreakpoint hit during %s, continuing...\n", op) + fmt.Printf("\tbreakpoint hit during %s", op) + if !skipBreakpoints { + fmt.Printf("\n") + answer, err := promptAutoContinue(t, op) + switch answer { + case "f": // finish next + skipBreakpoints = true + fallthrough + case "c": // continue once + fmt.Printf("continuing...\n") + case "s": // stop and cancel + fallthrough + default: + t.client.CancelNext() + printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true) + return err + } + } else { + fmt.Printf(", continuing...\n") + } stateChan := t.client.DirectionCongruentContinue() var state *api.DebuggerState for state = range stateChan { @@ -1464,6 +1484,20 @@ func continueUntilCompleteNext(t *Term, state *api.DebuggerState, op string, sho } } +func promptAutoContinue(t *Term, op string) (string, error) { + for { + answer, err := t.line.Prompt(fmt.Sprintf("[c] continue [s] stop here and cancel %s, [f] finish %s skipping all breakpoints? ", op, op)) + if err != nil { + return "", err + } + answer = strings.ToLower(strings.TrimSpace(answer)) + switch answer { + case "f", "c", "s": + return answer, nil + } + } +} + func scopePrefixSwitch(t *Term, ctx callContext) error { if ctx.Scope.GoroutineID > 0 { _, err := t.client.SwitchGoroutine(ctx.Scope.GoroutineID) diff --git a/pkg/terminal/command_test.go b/pkg/terminal/command_test.go index e23b95d6..4cd90eb9 100644 --- a/pkg/terminal/command_test.go +++ b/pkg/terminal/command_test.go @@ -582,47 +582,6 @@ func countOccurrences(s, needle string) int { return count } -func TestIssue387(t *testing.T) { - if runtime.GOOS == "freebsd" { - t.Skip("test is not valid on FreeBSD") - } - // a breakpoint triggering during a 'next' operation will interrupt it - test.AllowRecording(t) - withTestTerminal("issue387", t, func(term *FakeTerminal) { - breakpointHitCount := 0 - term.MustExec("break dostuff") - for { - outstr, err := term.Exec("continue") - breakpointHitCount += countOccurrences(outstr, "issue387.go:8") - t.Log(outstr) - if err != nil { - if !strings.Contains(err.Error(), "exited") { - t.Fatalf("Unexpected error executing 'continue': %v", err) - } - break - } - - pos := 9 - - for { - outstr = term.MustExec("next") - breakpointHitCount += countOccurrences(outstr, "issue387.go:8") - t.Log(outstr) - if countOccurrences(outstr, fmt.Sprintf("issue387.go:%d", pos)) == 0 { - t.Fatalf("did not continue to expected position %d", pos) - } - pos++ - if pos >= 11 { - break - } - } - } - if breakpointHitCount != 10 { - t.Fatalf("Breakpoint hit wrong number of times, expected 10 got %d", breakpointHitCount) - } - }) -} - func listIsAt(t *testing.T, term *FakeTerminal, listcmd string, cur, start, end int) { t.Helper() outstr := term.MustExec(listcmd)