terminal: bugfix: tolerate spurious spaces after command prefixes

Expressions such as:

 frame 0    list
 frame   0   list
 on abreakpoint     print x
 goroutine    1    frame     0     list

should all execute correctly

Fixes #712
This commit is contained in:
aarzilli
2017-04-19 12:17:21 +02:00
committed by Derek Parker
parent 182f805094
commit 86a59c52a6
4 changed files with 22 additions and 38 deletions

View File

@ -333,7 +333,7 @@ func traceCmd(cmd *cobra.Command, args []string) {
cmds := terminal.DebugCommands(client) cmds := terminal.DebugCommands(client)
t := terminal.New(client, nil) t := terminal.New(client, nil)
defer t.Close() defer t.Close()
err = cmds.Call("continue", "", t) err = cmds.Call("continue", t)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
return 1 return 1

View File

@ -260,13 +260,19 @@ func (c *Commands) Find(cmdstr string, prefix cmdPrefix) cmdfunc {
return noCmdAvailable return noCmdAvailable
} }
func (c *Commands) CallWithContext(cmdstr, args string, t *Term, ctx callContext) error { func (c *Commands) CallWithContext(cmdstr string, t *Term, ctx callContext) error {
return c.Find(cmdstr, ctx.Prefix)(t, ctx, args) vals := strings.SplitN(strings.TrimSpace(cmdstr), " ", 2)
cmdname := vals[0]
var args string
if len(vals) > 1 {
args = strings.TrimSpace(vals[1])
}
return c.Find(cmdname, ctx.Prefix)(t, ctx, args)
} }
func (c *Commands) Call(cmdstr, args string, t *Term) error { func (c *Commands) Call(cmdstr string, t *Term) error {
ctx := callContext{Prefix: noPrefix, Scope: api.EvalScope{GoroutineID: -1, Frame: 0}} ctx := callContext{Prefix: noPrefix, Scope: api.EvalScope{GoroutineID: -1, Frame: 0}}
return c.CallWithContext(cmdstr, args, t, ctx) return c.CallWithContext(cmdstr, t, ctx)
} }
// Merge takes aliases defined in the config struct and merges them with the default aliases. // Merge takes aliases defined in the config struct and merges them with the default aliases.
@ -433,7 +439,7 @@ func goroutines(t *Term, ctx callContext, argstr string) error {
} }
func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error { func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error {
args := strings.SplitN(argstr, " ", 3) args := strings.SplitN(argstr, " ", 2)
if ctx.Prefix == onPrefix { if ctx.Prefix == onPrefix {
if len(args) != 1 || args[0] != "" { if len(args) != 1 || args[0] != "" {
@ -443,8 +449,7 @@ func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error {
return nil return nil
} }
switch len(args) { if len(args) == 1 {
case 1:
if ctx.Prefix == scopePrefix { if ctx.Prefix == scopePrefix {
return errors.New("no command passed to goroutine") return errors.New("no command passed to goroutine")
} }
@ -467,8 +472,6 @@ func (c *Commands) goroutine(t *Term, ctx callContext, argstr 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
case 2:
args = append(args, "")
} }
var err error var err error
@ -477,17 +480,15 @@ func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error {
if err != nil { if err != nil {
return err return err
} }
return c.CallWithContext(args[1], args[2], t, ctx) return c.CallWithContext(args[1], t, ctx)
} }
func (c *Commands) frame(t *Term, ctx callContext, args string) error { func (c *Commands) frame(t *Term, ctx callContext, args string) error {
v := strings.SplitN(args, " ", 3) v := strings.SplitN(args, " ", 2)
switch len(v) { switch len(v) {
case 0, 1: case 0, 1:
return errors.New("not enough arguments") return errors.New("not enough arguments")
case 2:
v = append(v, "")
} }
var err error var err error
@ -496,7 +497,7 @@ func (c *Commands) frame(t *Term, ctx callContext, args string) error {
if err != nil { if err != nil {
return err return err
} }
return c.CallWithContext(v[1], v[2], t, ctx) return c.CallWithContext(v[1], t, ctx)
} }
func printscope(t *Term) error { func printscope(t *Term) error {
@ -1328,16 +1329,12 @@ func getBreakpointByIDOrName(t *Term, arg string) (*api.Breakpoint, error) {
} }
func (c *Commands) onCmd(t *Term, ctx callContext, argstr string) error { func (c *Commands) onCmd(t *Term, ctx callContext, argstr string) error {
args := strings.SplitN(argstr, " ", 3) args := strings.SplitN(argstr, " ", 2)
if len(args) < 2 { if len(args) < 2 {
return errors.New("not enough arguments") return errors.New("not enough arguments")
} }
if len(args) < 3 {
args = append(args, "")
}
bp, err := getBreakpointByIDOrName(t, args[0]) bp, err := getBreakpointByIDOrName(t, args[0])
if err != nil { if err != nil {
return err return err
@ -1345,7 +1342,7 @@ func (c *Commands) onCmd(t *Term, ctx callContext, argstr string) error {
ctx.Prefix = onPrefix ctx.Prefix = onPrefix
ctx.Breakpoint = bp ctx.Breakpoint = bp
err = c.CallWithContext(args[1], args[2], t, ctx) err = c.CallWithContext(args[1], t, ctx)
if err != nil { if err != nil {
return err return err
} }
@ -1392,9 +1389,7 @@ func (c *Commands) executeFile(t *Term, name string) error {
continue continue
} }
cmdstr, args := parseCommand(line) if err := c.Call(line, t); err != nil {
if err := c.Call(cmdstr, args, t); err != nil {
fmt.Printf("%s:%d: %v\n", name, lineno, err) fmt.Printf("%s:%d: %v\n", name, lineno, err)
} }
} }

View File

@ -38,8 +38,6 @@ type FakeTerminal struct {
} }
func (ft *FakeTerminal) Exec(cmdstr string) (outstr string, err error) { func (ft *FakeTerminal) Exec(cmdstr string) (outstr string, err error) {
cmdstr, args := parseCommand(cmdstr)
outfh, err := ioutil.TempFile("", "cmdtestout") outfh, err := ioutil.TempFile("", "cmdtestout")
if err != nil { if err != nil {
ft.t.Fatalf("could not create temporary file: %v", err) ft.t.Fatalf("could not create temporary file: %v", err)
@ -57,7 +55,7 @@ func (ft *FakeTerminal) Exec(cmdstr string) (outstr string, err error) {
outstr = string(outbs) outstr = string(outbs)
os.Remove(outfh.Name()) os.Remove(outfh.Name())
}() }()
err = ft.cmds.Call(cmdstr, args, ft.Term) err = ft.cmds.Call(cmdstr, ft.Term)
return return
} }
@ -305,7 +303,7 @@ func TestScopePrefix(t *testing.T) {
if fid < 0 { if fid < 0 {
t.Fatalf("Could not find frame for goroutine %d: %v", gid, stackOut) t.Fatalf("Could not find frame for goroutine %d: %v", gid, stackOut)
} }
term.AssertExec(fmt.Sprintf("goroutine %d frame %d locals", gid, fid), "(no locals)\n") term.AssertExec(fmt.Sprintf("goroutine %d frame %d locals", gid, fid), "(no locals)\n")
argsOut := strings.Split(term.MustExec(fmt.Sprintf("goroutine %d frame %d args", gid, fid)), "\n") argsOut := strings.Split(term.MustExec(fmt.Sprintf("goroutine %d frame %d args", gid, fid)), "\n")
if len(argsOut) != 4 || argsOut[3] != "" { if len(argsOut) != 4 || argsOut[3] != "" {
t.Fatalf("Wrong number of arguments in goroutine %d frame %d: %v", gid, fid, argsOut) t.Fatalf("Wrong number of arguments in goroutine %d frame %d: %v", gid, fid, argsOut)

View File

@ -128,8 +128,7 @@ func (t *Term) Run() (int, error) {
return 1, fmt.Errorf("Prompt for input failed.\n") return 1, fmt.Errorf("Prompt for input failed.\n")
} }
cmdstr, args := parseCommand(strings.TrimSpace(cmdstr)) if err := t.cmds.Call(cmdstr, t); err != nil {
if err := t.cmds.Call(cmdstr, args, t); err != nil {
if _, ok := err.(ExitRequestError); ok { if _, ok := err.(ExitRequestError); ok {
return t.handleExit() return t.handleExit()
} }
@ -241,11 +240,3 @@ func (t *Term) handleExit() (int, error) {
} }
return 0, nil return 0, nil
} }
func parseCommand(cmdstr string) (string, string) {
vals := strings.SplitN(cmdstr, " ", 2)
if len(vals) == 1 {
return vals[0], ""
}
return vals[0], strings.TrimSpace(vals[1])
}