From 22af38364b4fe71ba10604cf0f771ed628f0005b Mon Sep 17 00:00:00 2001 From: Ben Cotterell Date: Fri, 27 Jul 2018 11:16:41 +0100 Subject: [PATCH] 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. --- Documentation/cli/README.md | 6 +++++ pkg/terminal/command.go | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/Documentation/cli/README.md b/Documentation/cli/README.md index b61a8ce0..08a58787 100644 --- a/Documentation/cli/README.md +++ b/Documentation/cli/README.md @@ -16,6 +16,7 @@ Command | Description [continue](#continue) | Run until breakpoint or program termination. [disassemble](#disassemble) | Disassembler. [down](#down) | Move the current frame down. +[edit](#edit) | Open where you are in $DELVE_EDITOR or $EDITOR [exit](#exit) | Exit the debugger. [frame](#frame) | Set the current frame, or execute command on a different frame. [funcs](#funcs) | Print list of functions. @@ -183,6 +184,11 @@ Move the current frame down. Move the current frame down by . The second form runs the command on the given frame. +## edit +Open where you are in $DELVE_EDITOR or $EDITOR + +Aliases: ed + ## exit Exit the debugger. diff --git a/pkg/terminal/command.go b/pkg/terminal/command.go index 27f5994b..69b560a1 100644 --- a/pkg/terminal/command.go +++ b/pkg/terminal/command.go @@ -11,6 +11,7 @@ import ( "io" "math" "os" + "os/exec" "reflect" "regexp" "sort" @@ -323,6 +324,8 @@ Adds or removes a path substitution rule. config alias Defines as an alias to 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() { @@ -1132,6 +1135,53 @@ func tracepoint(t *Term, ctx callContext, args string) error { 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 { if len(args) == 0 { return fmt.Errorf("not enough arguments")