...

Source file src/cmd/pprof/readlineui.go

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

View as plain text