Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/pprof/readlineui.go

Documentation: cmd/pprof

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

View as plain text