github.com/hs0210/hashicorp-terraform@v0.11.12-beta1/helper/wrappedreadline/wrappedreadline.go (about)

     1  // wrappedreadline is a package that has helpers for interacting with
     2  // readline from a panicwrap executable.
     3  //
     4  // panicwrap overrides the standard file descriptors so that the child process
     5  // no longer looks like a TTY. The helpers here access the extra file descriptors
     6  // passed by panicwrap to fix that.
     7  //
     8  // panicwrap should be checked for with panicwrap.Wrapped before using this
     9  // librar, since this library won't adapt if the binary is not wrapped.
    10  package wrappedreadline
    11  
    12  import (
    13  	"runtime"
    14  
    15  	"github.com/chzyer/readline"
    16  
    17  	"github.com/hashicorp/terraform/helper/wrappedstreams"
    18  )
    19  
    20  // Override overrides the values in readline.Config that need to be
    21  // set with wrapped values.
    22  func Override(cfg *readline.Config) *readline.Config {
    23  	cfg.Stdin = wrappedstreams.Stdin()
    24  	cfg.Stdout = wrappedstreams.Stdout()
    25  	cfg.Stderr = wrappedstreams.Stderr()
    26  
    27  	cfg.FuncGetWidth = TerminalWidth
    28  	cfg.FuncIsTerminal = IsTerminal
    29  
    30  	rm := RawMode{StdinFd: int(wrappedstreams.Stdin().Fd())}
    31  	cfg.FuncMakeRaw = rm.Enter
    32  	cfg.FuncExitRaw = rm.Exit
    33  
    34  	return cfg
    35  }
    36  
    37  // IsTerminal determines if this process is attached to a TTY.
    38  func IsTerminal() bool {
    39  	// Windows is always a terminal
    40  	if runtime.GOOS == "windows" {
    41  		return true
    42  	}
    43  
    44  	// Same implementation as readline but with our custom fds
    45  	return readline.IsTerminal(int(wrappedstreams.Stdin().Fd())) &&
    46  		(readline.IsTerminal(int(wrappedstreams.Stdout().Fd())) ||
    47  			readline.IsTerminal(int(wrappedstreams.Stderr().Fd())))
    48  }
    49  
    50  // TerminalWidth gets the terminal width in characters.
    51  func TerminalWidth() int {
    52  	if runtime.GOOS == "windows" {
    53  		return readline.GetScreenWidth()
    54  	}
    55  
    56  	return getWidth()
    57  }
    58  
    59  // RawMode is a helper for entering and exiting raw mode.
    60  type RawMode struct {
    61  	StdinFd int
    62  
    63  	state *readline.State
    64  }
    65  
    66  func (r *RawMode) Enter() (err error) {
    67  	r.state, err = readline.MakeRaw(r.StdinFd)
    68  	return err
    69  }
    70  
    71  func (r *RawMode) Exit() error {
    72  	if r.state == nil {
    73  		return nil
    74  	}
    75  
    76  	return readline.Restore(r.StdinFd, r.state)
    77  }