2016-11-13 21:10:42 +01:00
|
|
|
// wrappedreadline is a package that has helpers for interacting with
|
|
|
|
// readline from a panicwrap executable.
|
|
|
|
//
|
|
|
|
// panicwrap overrides the standard file descriptors so that the child process
|
|
|
|
// no longer looks like a TTY. The helpers here access the extra file descriptors
|
|
|
|
// passed by panicwrap to fix that.
|
2016-11-14 07:18:18 +01:00
|
|
|
//
|
|
|
|
// panicwrap should be checked for with panicwrap.Wrapped before using this
|
|
|
|
// librar, since this library won't adapt if the binary is not wrapped.
|
2016-11-13 21:10:42 +01:00
|
|
|
package wrappedreadline
|
|
|
|
|
|
|
|
import (
|
|
|
|
"runtime"
|
|
|
|
|
|
|
|
"github.com/chzyer/readline"
|
|
|
|
|
2021-01-20 19:18:02 +01:00
|
|
|
"github.com/hashicorp/terraform/internal/helper/wrappedstreams"
|
2016-11-13 21:10:42 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// Override overrides the values in readline.Config that need to be
|
|
|
|
// set with wrapped values.
|
|
|
|
func Override(cfg *readline.Config) *readline.Config {
|
2016-11-14 09:32:01 +01:00
|
|
|
cfg.Stdin = wrappedstreams.Stdin()
|
|
|
|
cfg.Stdout = wrappedstreams.Stdout()
|
|
|
|
cfg.Stderr = wrappedstreams.Stderr()
|
2016-11-13 21:10:42 +01:00
|
|
|
|
|
|
|
cfg.FuncGetWidth = TerminalWidth
|
|
|
|
cfg.FuncIsTerminal = IsTerminal
|
|
|
|
|
2016-11-14 09:32:01 +01:00
|
|
|
rm := RawMode{StdinFd: int(wrappedstreams.Stdin().Fd())}
|
2016-11-13 21:10:42 +01:00
|
|
|
cfg.FuncMakeRaw = rm.Enter
|
|
|
|
cfg.FuncExitRaw = rm.Exit
|
|
|
|
|
|
|
|
return cfg
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsTerminal determines if this process is attached to a TTY.
|
|
|
|
func IsTerminal() bool {
|
|
|
|
// Windows is always a terminal
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Same implementation as readline but with our custom fds
|
2016-11-14 09:32:01 +01:00
|
|
|
return readline.IsTerminal(int(wrappedstreams.Stdin().Fd())) &&
|
|
|
|
(readline.IsTerminal(int(wrappedstreams.Stdout().Fd())) ||
|
|
|
|
readline.IsTerminal(int(wrappedstreams.Stderr().Fd())))
|
2016-11-13 21:10:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// TerminalWidth gets the terminal width in characters.
|
|
|
|
func TerminalWidth() int {
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
return readline.GetScreenWidth()
|
|
|
|
}
|
|
|
|
|
|
|
|
return getWidth()
|
|
|
|
}
|
|
|
|
|
|
|
|
// RawMode is a helper for entering and exiting raw mode.
|
|
|
|
type RawMode struct {
|
2016-11-14 09:32:01 +01:00
|
|
|
StdinFd int
|
|
|
|
|
2016-11-13 21:10:42 +01:00
|
|
|
state *readline.State
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *RawMode) Enter() (err error) {
|
2016-11-14 09:32:01 +01:00
|
|
|
r.state, err = readline.MakeRaw(r.StdinFd)
|
2016-11-13 21:10:42 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *RawMode) Exit() error {
|
|
|
|
if r.state == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-11-14 09:32:01 +01:00
|
|
|
return readline.Restore(r.StdinFd, r.state)
|
2016-11-13 21:10:42 +01:00
|
|
|
}
|