Add an edit command

Which I miss from gdb-- it's nice to be able to open where you are in
your editor where you're already working on the project you're
debugging.
This commit is contained in:
Ben Cotterell 2018-07-27 11:16:41 +01:00 committed by Derek Parker
parent 7e15327e84
commit 22af38364b
2 changed files with 56 additions and 0 deletions

@ -16,6 +16,7 @@ Command | Description
[continue](#continue) | Run until breakpoint or program termination. [continue](#continue) | Run until breakpoint or program termination.
[disassemble](#disassemble) | Disassembler. [disassemble](#disassemble) | Disassembler.
[down](#down) | Move the current frame down. [down](#down) | Move the current frame down.
[edit](#edit) | Open where you are in $DELVE_EDITOR or $EDITOR
[exit](#exit) | Exit the debugger. [exit](#exit) | Exit the debugger.
[frame](#frame) | Set the current frame, or execute command on a different frame. [frame](#frame) | Set the current frame, or execute command on a different frame.
[funcs](#funcs) | Print list of functions. [funcs](#funcs) | Print list of functions.
@ -183,6 +184,11 @@ Move the current frame down.
Move the current frame down by <m>. The second form runs the command on the given frame. Move the current frame down by <m>. The second form runs the command on the given frame.
## edit
Open where you are in $DELVE_EDITOR or $EDITOR
Aliases: ed
## exit ## exit
Exit the debugger. Exit the debugger.

@ -11,6 +11,7 @@ import (
"io" "io"
"math" "math"
"os" "os"
"os/exec"
"reflect" "reflect"
"regexp" "regexp"
"sort" "sort"
@ -323,6 +324,8 @@ Adds or removes a path substitution rule.
config alias <alias> config alias <alias>
Defines <alias> as an alias to <command> or removes an alias.`}, Defines <alias> as an alias to <command> or removes an alias.`},
{aliases: []string{"edit", "ed"}, cmdFn: edit, helpMsg: `Open where you are in $DELVE_EDITOR or $EDITOR`},
} }
if client == nil || client.Recorded() { if client == nil || client.Recorded() {
@ -1132,6 +1135,53 @@ func tracepoint(t *Term, ctx callContext, args string) error {
return setBreakpoint(t, ctx, true, args) return setBreakpoint(t, ctx, true, args)
} }
func getLocation(t *Term, ctx callContext) (*api.Location, error) {
if ctx.scoped() {
locs, err := t.client.Stacktrace(ctx.Scope.GoroutineID, ctx.Scope.Frame, false, nil)
if err != nil {
return nil, err
}
if ctx.Scope.Frame >= len(locs) {
return nil, fmt.Errorf("Frame %d does not exist in goroutine %d", ctx.Scope.Frame, ctx.Scope.GoroutineID)
}
return &locs[ctx.Scope.Frame].Location, nil
} else {
state, err := t.client.GetState()
if err != nil {
return nil, err
}
if state.SelectedGoroutine != nil {
return &state.SelectedGoroutine.CurrentLoc, nil
} else {
thread := state.CurrentThread
loc := api.Location {
PC: thread.PC,
File: thread.File,
Line: thread.Line,
Function: thread.Function,
}
return &loc, nil
}
}
}
func edit(t *Term, ctx callContext, args string) error {
loc, err := getLocation(t, ctx)
if err != nil { return err }
var editor string
if editor = os.Getenv("DELVE_EDITOR"); editor == "" {
if editor = os.Getenv("EDITOR"); editor == "" {
return fmt.Errorf("Neither DELVE_EDITOR or EDITOR is set")
}
}
editArgs := []string{fmt.Sprintf("+%d", loc.Line), loc.File}
cmd := exec.Command(editor, editArgs...)
return cmd.Run()
}
func printVar(t *Term, ctx callContext, args string) error { func printVar(t *Term, ctx callContext, args string) error {
if len(args) == 0 { if len(args) == 0 {
return fmt.Errorf("not enough arguments") return fmt.Errorf("not enough arguments")