mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 10:47:27 +08:00 
			
		
		
		
	terminal: better list command
- always print a header with the path to the file being displayed - always evaluate the linespec argument, even if a scope prefix is present Fixes #711, #713
This commit is contained in:
		| @ -1028,7 +1028,16 @@ func parseStackArgs(argstr string) (int, bool, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func listCommand(t *Term, ctx callContext, args string) error { | func listCommand(t *Term, ctx callContext, args string) error { | ||||||
| 	if ctx.Prefix == scopePrefix { | 	switch { | ||||||
|  | 	case len(args) == 0 && ctx.Prefix != scopePrefix: | ||||||
|  | 		state, err := t.client.GetState() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		printcontext(t, state) | ||||||
|  | 		return printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true) | ||||||
|  |  | ||||||
|  | 	case len(args) == 0 && ctx.Prefix == scopePrefix: | ||||||
| 		locs, err := t.client.Stacktrace(ctx.Scope.GoroutineID, ctx.Scope.Frame, nil) | 		locs, err := t.client.Stacktrace(ctx.Scope.GoroutineID, ctx.Scope.Frame, nil) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| @ -1037,28 +1046,31 @@ func listCommand(t *Term, ctx callContext, args string) error { | |||||||
| 			return fmt.Errorf("Frame %d does not exist in goroutine %d", ctx.Scope.Frame, ctx.Scope.GoroutineID) | 			return fmt.Errorf("Frame %d does not exist in goroutine %d", ctx.Scope.Frame, ctx.Scope.GoroutineID) | ||||||
| 		} | 		} | ||||||
| 		loc := locs[ctx.Scope.Frame] | 		loc := locs[ctx.Scope.Frame] | ||||||
|  | 		gid := ctx.Scope.GoroutineID | ||||||
|  | 		if gid < 0 { | ||||||
|  | 			state, err := t.client.GetState() | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			if state.SelectedGoroutine != nil { | ||||||
|  | 				gid = state.SelectedGoroutine.ID | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		fmt.Printf("Goroutine %d frame %d at %s:%d (PC: %#x)\n", gid, ctx.Scope.Frame, loc.File, loc.Line, loc.PC) | ||||||
| 		return printfile(t, loc.File, loc.Line, true) | 		return printfile(t, loc.File, loc.Line, true) | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if len(args) == 0 { | 	default: | ||||||
| 		state, err := t.client.GetState() | 		locs, err := t.client.FindLocation(ctx.Scope, args) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		printcontext(t, state) | 		if len(locs) > 1 { | ||||||
| 		printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true) | 			return debugger.AmbiguousLocationError{Location: args, CandidatesLocation: locs} | ||||||
| 		return nil | 		} | ||||||
|  | 		loc := locs[0] | ||||||
|  | 		fmt.Printf("Showing %s:%d (PC: %#x)\n", loc.File, loc.Line, loc.PC) | ||||||
|  | 		return printfile(t, loc.File, loc.Line, false) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	locs, err := t.client.FindLocation(api.EvalScope{GoroutineID: -1, Frame: 0}, args) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if len(locs) > 1 { |  | ||||||
| 		return debugger.AmbiguousLocationError{Location: args, CandidatesLocation: locs} |  | ||||||
| 	} |  | ||||||
| 	printfile(t, locs[0].File, locs[0].Line, false) |  | ||||||
| 	return nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (c *Commands) sourceCommand(t *Term, ctx callContext, args string) error { | func (c *Commands) sourceCommand(t *Term, ctx callContext, args string) error { | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ import ( | |||||||
| 	"net" | 	"net" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | 	"regexp" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
| @ -43,10 +44,10 @@ func (ft *FakeTerminal) Exec(cmdstr string) (outstr string, err error) { | |||||||
| 		ft.t.Fatalf("could not create temporary file: %v", err) | 		ft.t.Fatalf("could not create temporary file: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	stdout, stderr := os.Stdout, os.Stderr | 	stdout, stderr, termstdout := os.Stdout, os.Stderr, ft.Term.stdout | ||||||
| 	os.Stdout, os.Stderr = outfh, outfh | 	os.Stdout, os.Stderr, ft.Term.stdout = outfh, outfh, outfh | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		os.Stdout, os.Stderr = stdout, stderr | 		os.Stdout, os.Stderr, ft.Term.stdout = stdout, stderr, termstdout | ||||||
| 		outfh.Close() | 		outfh.Close() | ||||||
| 		outbs, err1 := ioutil.ReadFile(outfh.Name()) | 		outbs, err1 := ioutil.ReadFile(outfh.Name()) | ||||||
| 		if err1 != nil { | 		if err1 != nil { | ||||||
| @ -482,3 +483,57 @@ func TestIssue387(t *testing.T) { | |||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func listIsAt(t *testing.T, term *FakeTerminal, listcmd string, cur, start, end int) { | ||||||
|  | 	outstr := term.MustExec(listcmd) | ||||||
|  | 	lines := strings.Split(outstr, "\n") | ||||||
|  |  | ||||||
|  | 	t.Logf("%q: %q", listcmd, outstr) | ||||||
|  |  | ||||||
|  | 	if strings.Index(lines[0], fmt.Sprintf(":%d", cur)) < 0 { | ||||||
|  | 		t.Fatalf("Could not find current line number in first output line: %q", lines[0]) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	re := regexp.MustCompile(`(=>)?\s+(\d+):`) | ||||||
|  |  | ||||||
|  | 	outStart, outEnd := 0, 0 | ||||||
|  |  | ||||||
|  | 	for i, line := range lines[1:] { | ||||||
|  | 		if line == "" { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		v := re.FindStringSubmatch(line) | ||||||
|  | 		if len(v) != 3 { | ||||||
|  | 			t.Fatalf("Could not parse line %d: %q\n", i+1, line) | ||||||
|  | 		} | ||||||
|  | 		curline, _ := strconv.Atoi(v[2]) | ||||||
|  | 		if v[1] == "=>" { | ||||||
|  | 			if cur != curline { | ||||||
|  | 				t.Fatalf("Wrong current line, got %d expected %d", curline, cur) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if outStart == 0 { | ||||||
|  | 			outStart = curline | ||||||
|  | 		} | ||||||
|  | 		outEnd = curline | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if outStart != start || outEnd != end { | ||||||
|  | 		t.Fatalf("Wrong output range, got %d:%d expected %d:%d", outStart, outEnd, start, end) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestListCmd(t *testing.T) { | ||||||
|  | 	withTestTerminal("testvariables", t, func(term *FakeTerminal) { | ||||||
|  | 		term.MustExec("continue") | ||||||
|  | 		term.MustExec("continue") | ||||||
|  | 		listIsAt(t, term, "list", 24, 19, 29) | ||||||
|  | 		listIsAt(t, term, "list 69", 69, 64, 70) | ||||||
|  | 		listIsAt(t, term, "frame 1 list", 62, 57, 67) | ||||||
|  | 		listIsAt(t, term, "frame 1 list 69", 69, 64, 70) | ||||||
|  | 		_, err := term.Exec("frame 50 list") | ||||||
|  | 		if err == nil { | ||||||
|  | 			t.Fatalf("Expected error requesting 50th frame") | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 aarzilli
					aarzilli