aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/pprof
diff options
context:
space:
mode:
authorHana (Hyang-Ah) Kim <hyangah@gmail.com>2018-05-10 00:01:15 +0800
committerHyang-Ah Hana Kim <hyangah@gmail.com>2018-05-23 19:01:58 +0000
commit3f89214940d1f922bc4fde923de658a2ec1e4ac3 (patch)
treefb89ac6e1aeb8f479d60fa912a337f3456bab4f7 /src/cmd/pprof
parent392ff18b8fdcb1f116f81887ddedfd43b19fdb9c (diff)
downloadgo-3f89214940d1f922bc4fde923de658a2ec1e4ac3.tar.gz
go-3f89214940d1f922bc4fde923de658a2ec1e4ac3.zip
cmd/pprof: add readline support similar to upstream
The upstream pprof implements the readline feature using the github.com/chzyer/readline package in its pprof.go main. It would be ideal to use the same readline support package as the upstream for better user experience and code maintenance. However, bringing in third-party packages requires more work than I envisioned (e.g. clean up the vendored code to meet the expected standard - iow don't break builders). As a result, this change implements the similar feature for the pprof command included in the go distribution (cmd/pprof/pprof.go) using golang.org/x/crypto/ssh/terminal for now. Auto-completion is not yet supported (same in the upstream). The feature is enabled only in linux, windows, darwin, and only when terminal support is available. This change brings in new vendored packages, golang.org/x/crypto/ssh/terminal and golang.org/x/sys/{unix,windows}. For #14041 Change-Id: If4a790796acf2ab20f7e81268b9d9354c5a5cd2b Reviewed-on: https://go-review.googlesource.com/112436 Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/cmd/pprof')
-rw-r--r--src/cmd/pprof/pprof.go5
-rw-r--r--src/cmd/pprof/readlineui.go116
2 files changed, 121 insertions, 0 deletions
diff --git a/src/cmd/pprof/pprof.go b/src/cmd/pprof/pprof.go
index 1c325b5329..42e310043d 100644
--- a/src/cmd/pprof/pprof.go
+++ b/src/cmd/pprof/pprof.go
@@ -33,6 +33,7 @@ func main() {
options := &driver.Options{
Fetch: new(fetcher),
Obj: new(objTool),
+ UI: newUI(),
}
if err := driver.PProf(options); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
@@ -369,3 +370,7 @@ func (f *file) Close() error {
f.file.Close()
return nil
}
+
+// newUI will be set in readlineui.go in some platforms
+// for interactive readline functionality.
+var newUI = func() driver.UI { return nil }
diff --git a/src/cmd/pprof/readlineui.go b/src/cmd/pprof/readlineui.go
new file mode 100644
index 0000000000..67fb7aa49c
--- /dev/null
+++ b/src/cmd/pprof/readlineui.go
@@ -0,0 +1,116 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains an driver.UI implementation
+// that provides the readline functionality if possible.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+// +build !appengine
+// +build !android
+
+package main
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/google/pprof/driver"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+func init() {
+ newUI = newReadlineUI
+}
+
+// readlineUI implements driver.UI interface using the
+// golang.org/x/crypto/ssh/terminal package.
+// The upstream pprof command implements the same functionality
+// using the github.com/chzyer/readline package.
+type readlineUI struct {
+ term *terminal.Terminal
+}
+
+func newReadlineUI() driver.UI {
+ // test if we can use terminal.ReadLine
+ // that assumes operation in the raw mode.
+ oldState, err := terminal.MakeRaw(0)
+ if err != nil {
+ return nil
+ }
+ terminal.Restore(0, oldState)
+
+ rw := struct {
+ io.Reader
+ io.Writer
+ }{os.Stdin, os.Stderr}
+ return &readlineUI{term: terminal.NewTerminal(rw, "")}
+}
+
+// Read returns a line of text (a command) read from the user.
+// prompt is printed before reading the command.
+func (r *readlineUI) ReadLine(prompt string) (string, error) {
+ r.term.SetPrompt(prompt)
+
+ // skip error checking because we tested it
+ // when creating this readlineUI initially.
+ oldState, _ := terminal.MakeRaw(0)
+ defer terminal.Restore(0, oldState)
+
+ s, err := r.term.ReadLine()
+ return s, err
+}
+
+// Print shows a message to the user.
+// It formats the text as fmt.Print would and adds a final \n if not already present.
+// For line-based UI, Print writes to standard error.
+// (Standard output is reserved for report data.)
+func (r *readlineUI) Print(args ...interface{}) {
+ r.print(false, args...)
+}
+
+// PrintErr shows an error message to the user.
+// It formats the text as fmt.Print would and adds a final \n if not already present.
+// For line-based UI, PrintErr writes to standard error.
+func (r *readlineUI) PrintErr(args ...interface{}) {
+ r.print(true, args...)
+}
+
+func (r *readlineUI) print(withColor bool, args ...interface{}) {
+ text := fmt.Sprint(args...)
+ if !strings.HasSuffix(text, "\n") {
+ text += "\n"
+ }
+ if withColor {
+ text = colorize(text)
+ }
+ fmt.Fprintf(r.term, text)
+}
+
+// colorize prints the msg in red using ANSI color escapes.
+func colorize(msg string) string {
+ const red = 31
+ var colorEscape = fmt.Sprintf("\033[0;%dm", red)
+ var colorResetEscape = "\033[0m"
+ return colorEscape + msg + colorResetEscape
+}
+
+// IsTerminal returns whether the UI is known to be tied to an
+// interactive terminal (as opposed to being redirected to a file).
+func (r *readlineUI) IsTerminal() bool {
+ const stdout = 1
+ return terminal.IsTerminal(stdout)
+}
+
+// WantBrowser indicates whether browser should be opened with the -http option.
+func (r *readlineUI) WantBrowser() bool {
+ return r.IsTerminal()
+}
+
+// SetAutoComplete instructs the UI to call complete(cmd) to obtain
+// the auto-completion of cmd, if the UI supports auto-completion at all.
+func (r *readlineUI) SetAutoComplete(complete func(string) string) {
+ // TODO: Implement auto-completion support.
+}