Skip to content

Commit 3f89214

Browse files
committed
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>
1 parent 392ff18 commit 3f89214

304 files changed

Lines changed: 168533 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/cmd/pprof/pprof.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ func main() {
3333
options := &driver.Options{
3434
Fetch: new(fetcher),
3535
Obj: new(objTool),
36+
UI: newUI(),
3637
}
3738
if err := driver.PProf(options); err != nil {
3839
fmt.Fprintf(os.Stderr, "%v\n", err)
@@ -369,3 +370,7 @@ func (f *file) Close() error {
369370
f.file.Close()
370371
return nil
371372
}
373+
374+
// newUI will be set in readlineui.go in some platforms
375+
// for interactive readline functionality.
376+
var newUI = func() driver.UI { return nil }

src/cmd/pprof/readlineui.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// This file contains an driver.UI implementation
6+
// that provides the readline functionality if possible.
7+
8+
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
9+
// +build !appengine
10+
// +build !android
11+
12+
package main
13+
14+
import (
15+
"fmt"
16+
"io"
17+
"os"
18+
"strings"
19+
20+
"github.com/google/pprof/driver"
21+
"golang.org/x/crypto/ssh/terminal"
22+
)
23+
24+
func init() {
25+
newUI = newReadlineUI
26+
}
27+
28+
// readlineUI implements driver.UI interface using the
29+
// golang.org/x/crypto/ssh/terminal package.
30+
// The upstream pprof command implements the same functionality
31+
// using the github.com/chzyer/readline package.
32+
type readlineUI struct {
33+
term *terminal.Terminal
34+
}
35+
36+
func newReadlineUI() driver.UI {
37+
// test if we can use terminal.ReadLine
38+
// that assumes operation in the raw mode.
39+
oldState, err := terminal.MakeRaw(0)
40+
if err != nil {
41+
return nil
42+
}
43+
terminal.Restore(0, oldState)
44+
45+
rw := struct {
46+
io.Reader
47+
io.Writer
48+
}{os.Stdin, os.Stderr}
49+
return &readlineUI{term: terminal.NewTerminal(rw, "")}
50+
}
51+
52+
// Read returns a line of text (a command) read from the user.
53+
// prompt is printed before reading the command.
54+
func (r *readlineUI) ReadLine(prompt string) (string, error) {
55+
r.term.SetPrompt(prompt)
56+
57+
// skip error checking because we tested it
58+
// when creating this readlineUI initially.
59+
oldState, _ := terminal.MakeRaw(0)
60+
defer terminal.Restore(0, oldState)
61+
62+
s, err := r.term.ReadLine()
63+
return s, err
64+
}
65+
66+
// Print shows a message to the user.
67+
// It formats the text as fmt.Print would and adds a final \n if not already present.
68+
// For line-based UI, Print writes to standard error.
69+
// (Standard output is reserved for report data.)
70+
func (r *readlineUI) Print(args ...interface{}) {
71+
r.print(false, args...)
72+
}
73+
74+
// PrintErr shows an error message to the user.
75+
// It formats the text as fmt.Print would and adds a final \n if not already present.
76+
// For line-based UI, PrintErr writes to standard error.
77+
func (r *readlineUI) PrintErr(args ...interface{}) {
78+
r.print(true, args...)
79+
}
80+
81+
func (r *readlineUI) print(withColor bool, args ...interface{}) {
82+
text := fmt.Sprint(args...)
83+
if !strings.HasSuffix(text, "\n") {
84+
text += "\n"
85+
}
86+
if withColor {
87+
text = colorize(text)
88+
}
89+
fmt.Fprintf(r.term, text)
90+
}
91+
92+
// colorize prints the msg in red using ANSI color escapes.
93+
func colorize(msg string) string {
94+
const red = 31
95+
var colorEscape = fmt.Sprintf("\033[0;%dm", red)
96+
var colorResetEscape = "\033[0m"
97+
return colorEscape + msg + colorResetEscape
98+
}
99+
100+
// IsTerminal returns whether the UI is known to be tied to an
101+
// interactive terminal (as opposed to being redirected to a file).
102+
func (r *readlineUI) IsTerminal() bool {
103+
const stdout = 1
104+
return terminal.IsTerminal(stdout)
105+
}
106+
107+
// WantBrowser indicates whether browser should be opened with the -http option.
108+
func (r *readlineUI) WantBrowser() bool {
109+
return r.IsTerminal()
110+
}
111+
112+
// SetAutoComplete instructs the UI to call complete(cmd) to obtain
113+
// the auto-completion of cmd, if the UI supports auto-completion at all.
114+
func (r *readlineUI) SetAutoComplete(complete func(string) string) {
115+
// TODO: Implement auto-completion support.
116+
}

src/cmd/vendor/golang.org/x/crypto/LICENSE

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/vendor/golang.org/x/crypto/PATENTS

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)