From d54a3262d21a3e8d493cc7407444af3e0fa7100b Mon Sep 17 00:00:00 2001 From: Jason Del Ponte Date: Thu, 13 Nov 2014 21:51:32 -0800 Subject: [PATCH] Added aliases to commands Added: - break: b - continue: c - step: si - next: n - print: p Taken from the gdb command list Also updated .gitignore to ignore built dlv file in cmd/dlv --- .gitignore | 1 + command/command.go | 91 ++++++++++++++++++++++++++--------------- command/command_test.go | 4 +- 3 files changed, 62 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index d5140d87..0d9d35e5 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ notes.txt .tags* tags .dbg_history +cmd/dlv/dlv \ No newline at end of file diff --git a/command/command.go b/command/command.go index 71c03d32..5d23f107 100644 --- a/command/command.go +++ b/command/command.go @@ -17,47 +17,80 @@ import ( type cmdfunc func(proc *proctl.DebuggedProcess, args ...string) error +type command struct { + aliases []string + helpMsg string + cmdFn cmdfunc +} + +// Returns true if the command string matches one of the aliases for this command +func (c command) match(cmdstr string) bool { + for _, v := range c.aliases { + if v == cmdstr { + return true + } + } + return false +} + type Commands struct { - cmds map[string]cmdfunc + cmds []command + lastCmd cmdfunc } // Returns a Commands struct with default commands defined. func DebugCommands() *Commands { - cmds := map[string]cmdfunc{ - "help": help, - "continue": cont, - "next": next, - "break": breakpoint, - "step": step, - "clear": clear, - "print": printVar, - "threads": threads, - "goroutines": goroutines, - "": nullCommand, + c := &Commands{} + + c.cmds = []command{ + command{aliases: []string{"help"}, cmdFn: c.help, helpMsg: "help - Prints the help message."}, + command{aliases: []string{"break", "b"}, cmdFn: breakpoint, helpMsg: "break|b - Set break point at the entry point of a function, or at a specific file/line. Example: break foo.go:13"}, + command{aliases: []string{"continue", "c"}, cmdFn: cont, helpMsg: "continue|c - Run until breakpoint or program termination."}, + command{aliases: []string{"step", "si"}, cmdFn: step, helpMsg: "step|si - Single step through program."}, + command{aliases: []string{"next", "n"}, cmdFn: next, helpMsg: "next|n - Step over to next source line."}, + command{aliases: []string{"threads"}, cmdFn: threads, helpMsg: "threads - Print out info for every traced thread."}, + command{aliases: []string{"clear"}, cmdFn: clear, helpMsg: "clear - Deletes breakpoint."}, + command{aliases: []string{"goroutines"}, cmdFn: goroutines, helpMsg: "goroutines - Print out info for every goroutine."}, + command{aliases: []string{"print", "p"}, cmdFn: printVar, helpMsg: "print|p $var - Evaluate a variable."}, + command{aliases: []string{"exit"}, cmdFn: nullCommand, helpMsg: "exit - Exit the debugger."}, } - return &Commands{cmds} + return c } // Register custom commands. Expects cf to be a func of type cmdfunc, // returning only an error. -func (c *Commands) Register(cmdstr string, cf cmdfunc) { - c.cmds[cmdstr] = cf +func (c *Commands) Register(cmdstr string, cf cmdfunc, helpMsg string) { + for _, v := range c.cmds { + if v.match(cmdstr) { + v.cmdFn = cf + return + } + } + + c.cmds = append(c.cmds, command{aliases: []string{cmdstr}, cmdFn: cf, helpMsg: helpMsg}) } // Find will look up the command function for the given command input. // If it cannot find the command it will defualt to noCmdAvailable(). // If the command is an empty string it will replay the last command. func (c *Commands) Find(cmdstr string) cmdfunc { - cmd, ok := c.cmds[cmdstr] - if !ok { - return noCmdAvailable + // If use last command, if there was one. + if cmdstr == "" { + if c.lastCmd != nil { + return c.lastCmd + } + return nullCommand } - // Allow to replay last command - c.cmds[""] = cmd + for _, v := range c.cmds { + if v.match(cmdstr) { + c.lastCmd = v.cmdFn + return v.cmdFn + } + } - return cmd + return noCmdAvailable } func CommandFunc(fn func() error) cmdfunc { @@ -74,17 +107,11 @@ func nullCommand(p *proctl.DebuggedProcess, ars ...string) error { return nil } -func help(p *proctl.DebuggedProcess, ars ...string) error { - fmt.Println(`The following commands are available: - break - Set break point at the entry point of a function, or at a specific file/line. Example: break foo.go:13. - continue - Run until breakpoint or program termination. - step - Single step through program. - next - Step over to next source line. - threads - Print out info for every traced thread. - goroutines - Print out info for every goroutine. - print $var - Evaluate a variable. - exit - Exit the debugger.`) - +func (c *Commands) help(p *proctl.DebuggedProcess, ars ...string) error { + fmt.Println("The following commands are available:") + for _, cmd := range c.cmds { + fmt.Printf("\t%s\n", cmd.helpMsg) + } return nil } diff --git a/command/command_test.go b/command/command_test.go index 94c870dd..722ce991 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -9,7 +9,7 @@ import ( func TestCommandDefault(t *testing.T) { var ( - cmds = Commands{make(map[string]cmdfunc)} + cmds = Commands{} cmd = cmds.Find("non-existant-command") ) @@ -25,7 +25,7 @@ func TestCommandDefault(t *testing.T) { func TestCommandReplay(t *testing.T) { cmds := DebugCommands() - cmds.Register("foo", func(p *proctl.DebuggedProcess, args ...string) error { return fmt.Errorf("registered command") }) + cmds.Register("foo", func(p *proctl.DebuggedProcess, args ...string) error { return fmt.Errorf("registered command") }, "foo command") cmd := cmds.Find("foo") err := cmd(nil) -- GitLab