mirror of
https://github.com/go-delve/delve.git
synced 2025-10-30 02:07:58 +08:00
terminal: Split arguments inside the command function
Print and set need to receive their argument unsplit to support complex expressions
This commit is contained in:
@ -5,6 +5,8 @@ package terminal
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go/parser"
|
||||||
|
"go/scanner"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
@ -19,8 +21,8 @@ import (
|
|||||||
"github.com/derekparker/delve/service/debugger"
|
"github.com/derekparker/delve/service/debugger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cmdfunc func(t *Term, args ...string) error
|
type cmdfunc func(t *Term, args string) error
|
||||||
type scopedCmdfunc func(t *Term, scope api.EvalScope, args ...string) error
|
type scopedCmdfunc func(t *Term, scope api.EvalScope, args string) error
|
||||||
|
|
||||||
type filteringFunc func(t *Term, filter string) ([]string, error)
|
type filteringFunc func(t *Term, filter string) ([]string, error)
|
||||||
type scopedFilteringFunc func(t *Term, scope api.EvalScope, filter string) ([]string, error)
|
type scopedFilteringFunc func(t *Term, scope api.EvalScope, filter string) ([]string, error)
|
||||||
@ -129,20 +131,20 @@ func (c *Commands) Merge(allAliases map[string][]string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CommandFunc(fn func() error) cmdfunc {
|
func CommandFunc(fn func() error) cmdfunc {
|
||||||
return func(t *Term, args ...string) error {
|
return func(t *Term, args string) error {
|
||||||
return fn()
|
return fn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func noCmdAvailable(t *Term, args ...string) error {
|
func noCmdAvailable(t *Term, args string) error {
|
||||||
return fmt.Errorf("command not available")
|
return fmt.Errorf("command not available")
|
||||||
}
|
}
|
||||||
|
|
||||||
func nullCommand(t *Term, args ...string) error {
|
func nullCommand(t *Term, args string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) help(t *Term, args ...string) error {
|
func (c *Commands) help(t *Term, args string) error {
|
||||||
fmt.Println("The following commands are available:")
|
fmt.Println("The following commands are available:")
|
||||||
w := new(tabwriter.Writer)
|
w := new(tabwriter.Writer)
|
||||||
w.Init(os.Stdout, 0, 8, 0, '-', 0)
|
w.Init(os.Stdout, 0, 8, 0, '-', 0)
|
||||||
@ -162,7 +164,7 @@ func (a byThreadID) Len() int { return len(a) }
|
|||||||
func (a byThreadID) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a byThreadID) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
func (a byThreadID) Less(i, j int) bool { return a[i].ID < a[j].ID }
|
func (a byThreadID) Less(i, j int) bool { return a[i].ID < a[j].ID }
|
||||||
|
|
||||||
func threads(t *Term, args ...string) error {
|
func threads(t *Term, args string) error {
|
||||||
threads, err := t.client.ListThreads()
|
threads, err := t.client.ListThreads()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -188,11 +190,11 @@ func threads(t *Term, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func thread(t *Term, args ...string) error {
|
func thread(t *Term, args string) error {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return fmt.Errorf("you must specify a thread")
|
return fmt.Errorf("you must specify a thread")
|
||||||
}
|
}
|
||||||
tid, err := strconv.Atoi(args[0])
|
tid, err := strconv.Atoi(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -223,7 +225,8 @@ func (a byGoroutineID) Len() int { return len(a) }
|
|||||||
func (a byGoroutineID) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a byGoroutineID) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
func (a byGoroutineID) Less(i, j int) bool { return a[i].ID < a[j].ID }
|
func (a byGoroutineID) Less(i, j int) bool { return a[i].ID < a[j].ID }
|
||||||
|
|
||||||
func goroutines(t *Term, args ...string) error {
|
func goroutines(t *Term, argstr string) error {
|
||||||
|
args := strings.Split(argstr, " ")
|
||||||
var fgl = fglUserCurrent
|
var fgl = fglUserCurrent
|
||||||
|
|
||||||
switch len(args) {
|
switch len(args) {
|
||||||
@ -263,13 +266,13 @@ func goroutines(t *Term, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func goroutine(t *Term, args ...string) error {
|
func goroutine(t *Term, argstr string) error {
|
||||||
switch len(args) {
|
if argstr == "" {
|
||||||
case 0:
|
|
||||||
return printscope(t)
|
return printscope(t)
|
||||||
|
}
|
||||||
|
|
||||||
case 1:
|
if strings.Index(argstr, " ") < 0 {
|
||||||
gid, err := strconv.Atoi(args[0])
|
gid, err := strconv.Atoi(argstr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -285,54 +288,61 @@ func goroutine(t *Term, args ...string) error {
|
|||||||
|
|
||||||
fmt.Printf("Switched from %d to %d (thread %d)\n", oldState.SelectedGoroutine.ID, gid, newState.CurrentThread.ID)
|
fmt.Printf("Switched from %d to %d (thread %d)\n", oldState.SelectedGoroutine.ID, gid, newState.CurrentThread.ID)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
default:
|
|
||||||
return scopePrefix(t, "goroutine", args...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return scopePrefix(t, "goroutine "+argstr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func frame(t *Term, args ...string) error {
|
func frame(t *Term, args string) error {
|
||||||
return scopePrefix(t, "frame", args...)
|
return scopePrefix(t, "frame "+args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func scopePrefix(t *Term, cmdname string, pargs ...string) error {
|
func scopePrefix(t *Term, cmdstr string) error {
|
||||||
fullargs := make([]string, 0, len(pargs)+1)
|
|
||||||
fullargs = append(fullargs, cmdname)
|
|
||||||
fullargs = append(fullargs, pargs...)
|
|
||||||
|
|
||||||
scope := api.EvalScope{-1, 0}
|
scope := api.EvalScope{-1, 0}
|
||||||
lastcmd := ""
|
lastcmd := ""
|
||||||
|
rest := cmdstr
|
||||||
|
|
||||||
callFilterSortAndOutput := func(fn scopedFilteringFunc, fnargs []string) error {
|
nexttok := func() string {
|
||||||
|
v := strings.SplitN(rest, " ", 2)
|
||||||
|
if len(v) > 1 {
|
||||||
|
rest = v[1]
|
||||||
|
} else {
|
||||||
|
rest = ""
|
||||||
|
}
|
||||||
|
return v[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
callFilterSortAndOutput := func(fn scopedFilteringFunc, fnargs string) error {
|
||||||
outfn := filterSortAndOutput(func(t *Term, filter string) ([]string, error) {
|
outfn := filterSortAndOutput(func(t *Term, filter string) ([]string, error) {
|
||||||
return fn(t, scope, filter)
|
return fn(t, scope, filter)
|
||||||
})
|
})
|
||||||
return outfn(t, fnargs...)
|
return outfn(t, fnargs)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(fullargs); i++ {
|
for {
|
||||||
lastcmd = fullargs[i]
|
cmd := nexttok()
|
||||||
switch fullargs[i] {
|
if cmd == "" && rest == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch cmd {
|
||||||
case "goroutine":
|
case "goroutine":
|
||||||
if i+1 >= len(fullargs) {
|
if rest == "" {
|
||||||
return fmt.Errorf("goroutine command needs an argument")
|
return fmt.Errorf("goroutine command needs an argument")
|
||||||
}
|
}
|
||||||
n, err := strconv.Atoi(fullargs[i+1])
|
n, err := strconv.Atoi(nexttok())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid argument to goroutine, expected integer")
|
return fmt.Errorf("invalid argument to goroutine, expected integer")
|
||||||
}
|
}
|
||||||
scope.GoroutineID = int(n)
|
scope.GoroutineID = int(n)
|
||||||
i++
|
|
||||||
case "frame":
|
case "frame":
|
||||||
if i+1 >= len(fullargs) {
|
if rest == "" {
|
||||||
return fmt.Errorf("frame command needs an argument")
|
return fmt.Errorf("frame command needs an argument")
|
||||||
}
|
}
|
||||||
n, err := strconv.Atoi(fullargs[i+1])
|
n, err := strconv.Atoi(nexttok())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid argument to frame, expected integer")
|
return fmt.Errorf("invalid argument to frame, expected integer")
|
||||||
}
|
}
|
||||||
scope.Frame = int(n)
|
scope.Frame = int(n)
|
||||||
i++
|
|
||||||
case "list", "ls":
|
case "list", "ls":
|
||||||
frame, gid := scope.Frame, scope.GoroutineID
|
frame, gid := scope.Frame, scope.GoroutineID
|
||||||
locs, err := t.client.Stacktrace(gid, frame, false)
|
locs, err := t.client.Stacktrace(gid, frame, false)
|
||||||
@ -345,7 +355,7 @@ func scopePrefix(t *Term, cmdname string, pargs ...string) error {
|
|||||||
loc := locs[frame]
|
loc := locs[frame]
|
||||||
return printfile(t, loc.File, loc.Line, true)
|
return printfile(t, loc.File, loc.Line, true)
|
||||||
case "stack", "bt":
|
case "stack", "bt":
|
||||||
depth, full, err := parseStackArgs(fullargs[i+1:])
|
depth, full, err := parseStackArgs(rest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -356,14 +366,17 @@ func scopePrefix(t *Term, cmdname string, pargs ...string) error {
|
|||||||
printStack(stack, "")
|
printStack(stack, "")
|
||||||
return nil
|
return nil
|
||||||
case "locals":
|
case "locals":
|
||||||
return callFilterSortAndOutput(locals, fullargs[i+1:])
|
return callFilterSortAndOutput(locals, rest)
|
||||||
case "args":
|
case "args":
|
||||||
return callFilterSortAndOutput(args, fullargs[i+1:])
|
return callFilterSortAndOutput(args, rest)
|
||||||
case "print", "p":
|
case "print", "p":
|
||||||
return printVar(t, scope, fullargs[i+1:]...)
|
return printVar(t, scope, rest)
|
||||||
|
case "set":
|
||||||
|
return setVar(t, scope, rest)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown command %s", fullargs[i])
|
return fmt.Errorf("unknown command %s", cmd)
|
||||||
}
|
}
|
||||||
|
lastcmd = cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("no command passed to %s", lastcmd)
|
return fmt.Errorf("no command passed to %s", lastcmd)
|
||||||
@ -433,7 +446,7 @@ func writeGoroutineLong(w io.Writer, g *api.Goroutine, prefix string) {
|
|||||||
prefix, formatLocation(g.GoStatementLoc))
|
prefix, formatLocation(g.GoStatementLoc))
|
||||||
}
|
}
|
||||||
|
|
||||||
func restart(t *Term, args ...string) error {
|
func restart(t *Term, args string) error {
|
||||||
if err := t.client.Restart(); err != nil {
|
if err := t.client.Restart(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -441,7 +454,7 @@ func restart(t *Term, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cont(t *Term, args ...string) error {
|
func cont(t *Term, args string) error {
|
||||||
stateChan := t.client.Continue()
|
stateChan := t.client.Continue()
|
||||||
for state := range stateChan {
|
for state := range stateChan {
|
||||||
if state.Err != nil {
|
if state.Err != nil {
|
||||||
@ -452,7 +465,7 @@ func cont(t *Term, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func step(t *Term, args ...string) error {
|
func step(t *Term, args string) error {
|
||||||
state, err := t.client.Step()
|
state, err := t.client.Step()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -461,7 +474,7 @@ func step(t *Term, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func next(t *Term, args ...string) error {
|
func next(t *Term, args string) error {
|
||||||
state, err := t.client.Next()
|
state, err := t.client.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -470,11 +483,11 @@ func next(t *Term, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func clear(t *Term, args ...string) error {
|
func clear(t *Term, args string) error {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return fmt.Errorf("not enough arguments")
|
return fmt.Errorf("not enough arguments")
|
||||||
}
|
}
|
||||||
id, err := strconv.Atoi(args[0])
|
id, err := strconv.Atoi(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -486,15 +499,15 @@ func clear(t *Term, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearAll(t *Term, args ...string) error {
|
func clearAll(t *Term, args string) error {
|
||||||
breakPoints, err := t.client.ListBreakpoints()
|
breakPoints, err := t.client.ListBreakpoints()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var locPCs map[uint64]struct{}
|
var locPCs map[uint64]struct{}
|
||||||
if len(args) > 0 {
|
if args != "" {
|
||||||
locs, err := t.client.FindLocation(api.EvalScope{-1, 0}, args[0])
|
locs, err := t.client.FindLocation(api.EvalScope{-1, 0}, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -526,7 +539,7 @@ func (a ById) Len() int { return len(a) }
|
|||||||
func (a ById) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a ById) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
func (a ById) Less(i, j int) bool { return a[i].ID < a[j].ID }
|
func (a ById) Less(i, j int) bool { return a[i].ID < a[j].ID }
|
||||||
|
|
||||||
func breakpoints(t *Term, args ...string) error {
|
func breakpoints(t *Term, args string) error {
|
||||||
breakPoints, err := t.client.ListBreakpoints()
|
breakPoints, err := t.client.ListBreakpoints()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -557,7 +570,8 @@ func breakpoints(t *Term, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setBreakpoint(t *Term, tracepoint bool, args ...string) error {
|
func setBreakpoint(t *Term, tracepoint bool, argstr string) error {
|
||||||
|
args := strings.Split(argstr, " ")
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return fmt.Errorf("address required, specify either a function name or <file:line>")
|
return fmt.Errorf("address required, specify either a function name or <file:line>")
|
||||||
}
|
}
|
||||||
@ -601,17 +615,17 @@ func setBreakpoint(t *Term, tracepoint bool, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func breakpoint(t *Term, args ...string) error {
|
func breakpoint(t *Term, args string) error {
|
||||||
return setBreakpoint(t, false, args...)
|
return setBreakpoint(t, false, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tracepoint(t *Term, args ...string) error {
|
func tracepoint(t *Term, args string) error {
|
||||||
return setBreakpoint(t, true, args...)
|
return setBreakpoint(t, true, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func g0f0(fn scopedCmdfunc) cmdfunc {
|
func g0f0(fn scopedCmdfunc) cmdfunc {
|
||||||
return func(t *Term, args ...string) error {
|
return func(t *Term, args string) error {
|
||||||
return fn(t, api.EvalScope{-1, 0}, args...)
|
return fn(t, api.EvalScope{-1, 0}, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,11 +635,11 @@ func g0f0filter(fn scopedFilteringFunc) filteringFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printVar(t *Term, scope api.EvalScope, args ...string) error {
|
func printVar(t *Term, scope api.EvalScope, args string) error {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return fmt.Errorf("not enough arguments")
|
return fmt.Errorf("not enough arguments")
|
||||||
}
|
}
|
||||||
val, err := t.client.EvalVariable(scope, args[0])
|
val, err := t.client.EvalVariable(scope, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -634,12 +648,21 @@ func printVar(t *Term, scope api.EvalScope, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setVar(t *Term, scope api.EvalScope, args ...string) error {
|
func setVar(t *Term, scope api.EvalScope, args string) error {
|
||||||
if len(args) != 2 {
|
// HACK: in go '=' is not an operator, we detect the error and try to recover from it by splitting the input string
|
||||||
return fmt.Errorf("wrong number of arguments")
|
_, err := parser.ParseExpr(args)
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("syntax error '=' not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.client.SetVariable(scope, args[0], args[1])
|
el, ok := err.(scanner.ErrorList)
|
||||||
|
if !ok || el[0].Msg != "expected '==', found '='" {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
lexpr := args[:el[0].Pos.Offset]
|
||||||
|
rexpr := args[el[0].Pos.Offset+1:]
|
||||||
|
return t.client.SetVariable(scope, lexpr, rexpr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterVariables(vars []api.Variable, filter string) []string {
|
func filterVariables(vars []api.Variable, filter string) []string {
|
||||||
@ -689,7 +712,7 @@ func vars(t *Term, filter string) ([]string, error) {
|
|||||||
return filterVariables(vars, filter), nil
|
return filterVariables(vars, filter), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func regs(t *Term, args ...string) error {
|
func regs(t *Term, args string) error {
|
||||||
regs, err := t.client.ListRegisters()
|
regs, err := t.client.ListRegisters()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -699,13 +722,13 @@ func regs(t *Term, args ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func filterSortAndOutput(fn filteringFunc) cmdfunc {
|
func filterSortAndOutput(fn filteringFunc) cmdfunc {
|
||||||
return func(t *Term, args ...string) error {
|
return func(t *Term, args string) error {
|
||||||
var filter string
|
var filter string
|
||||||
if len(args) == 1 {
|
if len(args) > 0 {
|
||||||
if _, err := regexp.Compile(args[0]); err != nil {
|
if _, err := regexp.Compile(args); err != nil {
|
||||||
return fmt.Errorf("invalid filter argument: %s", err.Error())
|
return fmt.Errorf("invalid filter argument: %s", err.Error())
|
||||||
}
|
}
|
||||||
filter = args[0]
|
filter = args
|
||||||
}
|
}
|
||||||
data, err := fn(t, filter)
|
data, err := fn(t, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -719,7 +742,7 @@ func filterSortAndOutput(fn filteringFunc) cmdfunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func stackCommand(t *Term, args ...string) error {
|
func stackCommand(t *Term, args string) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
goroutineid = -1
|
goroutineid = -1
|
||||||
@ -736,26 +759,29 @@ func stackCommand(t *Term, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseStackArgs(args []string) (int, bool, error) {
|
func parseStackArgs(argstr string) (int, bool, error) {
|
||||||
var (
|
var (
|
||||||
depth = 10
|
depth = 10
|
||||||
full = false
|
full = false
|
||||||
)
|
)
|
||||||
for i := range args {
|
if argstr != "" {
|
||||||
if args[i] == "-full" {
|
args := strings.Split(argstr, " ")
|
||||||
full = true
|
for i := range args {
|
||||||
} else {
|
if args[i] == "-full" {
|
||||||
n, err := strconv.Atoi(args[i])
|
full = true
|
||||||
if err != nil {
|
} else {
|
||||||
return 0, false, fmt.Errorf("depth must be a number")
|
n, err := strconv.Atoi(args[i])
|
||||||
|
if err != nil {
|
||||||
|
return 0, false, fmt.Errorf("depth must be a number")
|
||||||
|
}
|
||||||
|
depth = n
|
||||||
}
|
}
|
||||||
depth = n
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return depth, full, nil
|
return depth, full, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func listCommand(t *Term, args ...string) error {
|
func listCommand(t *Term, args string) error {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
state, err := t.client.GetState()
|
state, err := t.client.GetState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -765,23 +791,23 @@ func listCommand(t *Term, args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
locs, err := t.client.FindLocation(api.EvalScope{-1, 0}, args[0])
|
locs, err := t.client.FindLocation(api.EvalScope{-1, 0}, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(locs) > 1 {
|
if len(locs) > 1 {
|
||||||
return debugger.AmbiguousLocationError{Location: args[0], CandidatesLocation: locs}
|
return debugger.AmbiguousLocationError{Location: args, CandidatesLocation: locs}
|
||||||
}
|
}
|
||||||
printfile(t, locs[0].File, locs[0].Line, false)
|
printfile(t, locs[0].File, locs[0].Line, false)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmds *Commands) sourceCommand(t *Term, args ...string) error {
|
func (cmds *Commands) sourceCommand(t *Term, args string) error {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return fmt.Errorf("wrong number of arguments: source <filename>")
|
return fmt.Errorf("wrong number of arguments: source <filename>")
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmds.executeFile(t, args[0])
|
return cmds.executeFile(t, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func digits(n int) int {
|
func digits(n int) int {
|
||||||
@ -925,7 +951,7 @@ func (ere ExitRequestError) Error() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func exitCommand(t *Term, args ...string) error {
|
func exitCommand(t *Term, args string) error {
|
||||||
return ExitRequestError{}
|
return ExitRequestError{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -953,7 +979,7 @@ func (cmds *Commands) executeFile(t *Term, name string) error {
|
|||||||
|
|
||||||
cmdstr, args := parseCommand(line)
|
cmdstr, args := parseCommand(line)
|
||||||
cmd := cmds.Find(cmdstr)
|
cmd := cmds.Find(cmdstr)
|
||||||
err := cmd(t, args...)
|
err := cmd(t, args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("%s:%d: %v\n", name, lineno, err)
|
fmt.Printf("%s:%d: %v\n", name, lineno, err)
|
||||||
|
|||||||
@ -14,7 +14,7 @@ func TestCommandDefault(t *testing.T) {
|
|||||||
cmd = cmds.Find("non-existant-command")
|
cmd = cmds.Find("non-existant-command")
|
||||||
)
|
)
|
||||||
|
|
||||||
err := cmd(nil)
|
err := cmd(nil, "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("cmd() did not default")
|
t.Fatal("cmd() did not default")
|
||||||
}
|
}
|
||||||
@ -26,16 +26,16 @@ func TestCommandDefault(t *testing.T) {
|
|||||||
|
|
||||||
func TestCommandReplay(t *testing.T) {
|
func TestCommandReplay(t *testing.T) {
|
||||||
cmds := DebugCommands(nil)
|
cmds := DebugCommands(nil)
|
||||||
cmds.Register("foo", func(t *Term, args ...string) error { return fmt.Errorf("registered command") }, "foo command")
|
cmds.Register("foo", func(t *Term, args string) error { return fmt.Errorf("registered command") }, "foo command")
|
||||||
cmd := cmds.Find("foo")
|
cmd := cmds.Find("foo")
|
||||||
|
|
||||||
err := cmd(nil)
|
err := cmd(nil, "")
|
||||||
if err.Error() != "registered command" {
|
if err.Error() != "registered command" {
|
||||||
t.Fatal("wrong command output")
|
t.Fatal("wrong command output")
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = cmds.Find("")
|
cmd = cmds.Find("")
|
||||||
err = cmd(nil)
|
err = cmd(nil, "")
|
||||||
if err.Error() != "registered command" {
|
if err.Error() != "registered command" {
|
||||||
t.Fatal("wrong command output")
|
t.Fatal("wrong command output")
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ func TestCommandReplayWithoutPreviousCommand(t *testing.T) {
|
|||||||
var (
|
var (
|
||||||
cmds = DebugCommands(nil)
|
cmds = DebugCommands(nil)
|
||||||
cmd = cmds.Find("")
|
cmd = cmds.Find("")
|
||||||
err = cmd(nil)
|
err = cmd(nil, "")
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -59,7 +59,7 @@ func TestCommandThread(t *testing.T) {
|
|||||||
cmd = cmds.Find("thread")
|
cmd = cmds.Find("thread")
|
||||||
)
|
)
|
||||||
|
|
||||||
err := cmd(nil)
|
err := cmd(nil, "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("thread terminal command did not default")
|
t.Fatal("thread terminal command did not default")
|
||||||
}
|
}
|
||||||
@ -75,11 +75,11 @@ func TestExecuteFile(t *testing.T) {
|
|||||||
c := &Commands{
|
c := &Commands{
|
||||||
client: nil,
|
client: nil,
|
||||||
cmds: []command{
|
cmds: []command{
|
||||||
{aliases: []string{"trace"}, cmdFn: func(t *Term, args ...string) error {
|
{aliases: []string{"trace"}, cmdFn: func(t *Term, args string) error {
|
||||||
traceCount++
|
traceCount++
|
||||||
return nil
|
return nil
|
||||||
}},
|
}},
|
||||||
{aliases: []string{"break"}, cmdFn: func(t *Term, args ...string) error {
|
{aliases: []string{"break"}, cmdFn: func(t *Term, args string) error {
|
||||||
breakCount++
|
breakCount++
|
||||||
return nil
|
return nil
|
||||||
}},
|
}},
|
||||||
|
|||||||
@ -107,7 +107,7 @@ func (t *Term) Run() (error, int) {
|
|||||||
|
|
||||||
cmdstr, args := parseCommand(cmdstr)
|
cmdstr, args := parseCommand(cmdstr)
|
||||||
cmd := cmds.Find(cmdstr)
|
cmd := cmds.Find(cmdstr)
|
||||||
if err := cmd(t, args...); err != nil {
|
if err := cmd(t, args); err != nil {
|
||||||
if _, ok := err.(ExitRequestError); ok {
|
if _, ok := err.(ExitRequestError); ok {
|
||||||
return t.handleExit()
|
return t.handleExit()
|
||||||
}
|
}
|
||||||
@ -182,7 +182,10 @@ func (t *Term) handleExit() (error, int) {
|
|||||||
return nil, 0
|
return nil, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCommand(cmdstr string) (string, []string) {
|
func parseCommand(cmdstr string) (string, string) {
|
||||||
vals := strings.Split(cmdstr, " ")
|
vals := strings.SplitN(cmdstr, " ", 2)
|
||||||
return vals[0], vals[1:]
|
if len(vals) == 1 {
|
||||||
|
return vals[0], ""
|
||||||
|
}
|
||||||
|
return vals[0], strings.TrimSpace(vals[1])
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user