Pārlūkot izejas kodu

Add command-line editing support for interactive pprof (#362)

Add command-line editing support for interactive pprof

This implements basic command-line editing, using
github.com/chzyer/readline. This will not affect the golang
distribution as it uses its own pprof driver, with its own
driver.

Only tested on Linux.
TODO: Implement auto-completion and persistent history.
Raul Silvera 7 gadus atpakaļ
vecāks
revīzija
a1a3fd83be
2 mainītis faili ar 77 papildinājumiem un 1 dzēšanām
  1. 1
    0
      appveyor.yml
  2. 76
    1
      pprof.go

+ 1
- 0
appveyor.yml Parādīt failu

@@ -5,6 +5,7 @@ install:
5 5
 
6 6
 before_build:
7 7
  - go get github.com/ianlancetaylor/demangle
8
+ - go get github.com/chzyer/readline
8 9
 
9 10
 build_script:
10 11
  - go build github.com/google/pprof

+ 76
- 1
pprof.go Parādīt failu

@@ -19,13 +19,88 @@ package main
19 19
 import (
20 20
 	"fmt"
21 21
 	"os"
22
+	"strings"
22 23
 
24
+	"github.com/chzyer/readline"
23 25
 	"github.com/google/pprof/driver"
24 26
 )
25 27
 
26 28
 func main() {
27
-	if err := driver.PProf(&driver.Options{}); err != nil {
29
+	if err := driver.PProf(&driver.Options{UI: newUI()}); err != nil {
28 30
 		fmt.Fprintf(os.Stderr, "pprof: %v\n", err)
29 31
 		os.Exit(2)
30 32
 	}
31 33
 }
34
+
35
+// readlineUI implements the driver.UI interface using the
36
+// github.com/chzyer/readline library.
37
+// This is contained in pprof.go to avoid adding the readline
38
+// dependency in the vendored copy of pprof in the Go distribution,
39
+// which does not use this file.
40
+type readlineUI struct {
41
+	rl *readline.Instance
42
+}
43
+
44
+func newUI() driver.UI {
45
+	rl, err := readline.New("")
46
+	if err != nil {
47
+		fmt.Fprintf(os.Stderr, "readline: %v", err)
48
+		return nil
49
+	}
50
+	return &readlineUI{
51
+		rl: rl,
52
+	}
53
+}
54
+
55
+// Read returns a line of text (a command) read from the user.
56
+// prompt is printed before reading the command.
57
+func (r *readlineUI) ReadLine(prompt string) (string, error) {
58
+	r.rl.SetPrompt(prompt)
59
+	return r.rl.Readline()
60
+}
61
+
62
+// Print shows a message to the user.
63
+// It is printed over stderr as stdout is reserved for regular output.
64
+func (r *readlineUI) Print(args ...interface{}) {
65
+	text := fmt.Sprint(args...)
66
+	if !strings.HasSuffix(text, "\n") {
67
+		text += "\n"
68
+	}
69
+	fmt.Fprint(r.rl.Stderr(), text)
70
+}
71
+
72
+// Print shows a message to the user, colored in red for emphasis.
73
+// It is printed over stderr as stdout is reserved for regular output.
74
+func (r *readlineUI) PrintErr(args ...interface{}) {
75
+	text := fmt.Sprint(args...)
76
+	if !strings.HasSuffix(text, "\n") {
77
+		text += "\n"
78
+	}
79
+	fmt.Fprint(r.rl.Stderr(), colorize(text))
80
+}
81
+
82
+// colorize the msg using ANSI color escapes.
83
+func colorize(msg string) string {
84
+	var red = 31
85
+	var colorEscape = fmt.Sprintf("\033[0;%dm", red)
86
+	var colorResetEscape = "\033[0m"
87
+	return colorEscape + msg + colorResetEscape
88
+}
89
+
90
+// IsTerminal returns whether the UI is known to be tied to an
91
+// interactive terminal (as opposed to being redirected to a file).
92
+func (r *readlineUI) IsTerminal() bool {
93
+	const stdout = 1
94
+	return readline.IsTerminal(stdout)
95
+}
96
+
97
+// Start a browser on interactive mode.
98
+func (r *readlineUI) WantBrowser() bool {
99
+	return r.IsTerminal()
100
+}
101
+
102
+// SetAutoComplete instructs the UI to call complete(cmd) to obtain
103
+// the auto-completion of cmd, if the UI supports auto-completion at all.
104
+func (r *readlineUI) SetAutoComplete(complete func(string) string) {
105
+	// TODO: Implement auto-completion support.
106
+}