fix: detect non-interactive stdio and use "normal" IO operations (#204)

This commit is contained in:
Daniel Moran
2021-07-21 17:03:41 -04:00
committed by GitHub
parent a111d83b5a
commit bfd929f444
7 changed files with 503 additions and 129 deletions

View File

@ -1,17 +1,52 @@
package stdio
import "io"
import (
"bufio"
"io"
"os"
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/mattn/go-isatty"
)
const MinPasswordLen = 8
type StdIO interface {
io.Writer
// Write prints some bytes to stdout.
Write(p []byte) (n int, err error)
// WriteErr prints some bytes to stderr.
WriteErr(p []byte) (n int, err error)
// Banner displays informational text to the user.
Banner(message string) error
// Error displays an error message to the user.
Error(message string) error
InputIsInteractive() bool
// IsInteractive signals whether interactive I/O is supported.
IsInteractive() bool
// GetStringInput prompts the user for arbitrary input.
GetStringInput(prompt, defaultValue string) (string, error)
// GetSecret prompts the user for a secret.
GetSecret(prompt string, minLen int) (string, error)
// GetPassword prompts the user for a secret twice, and inputs must match.
// Uses stdio.MinPasswordLen as the minimum input length
GetPassword(prompt string) (string, error)
// GetConfirm asks the user for a y/n answer to a prompt.
GetConfirm(prompt string) bool
}
func newTerminalStdio(in terminal.FileReader, out terminal.FileWriter, err io.Writer) StdIO {
interactiveIn := isatty.IsTerminal(in.Fd()) || isatty.IsCygwinTerminal(in.Fd())
interactiveOut := isatty.IsTerminal(out.Fd()) || isatty.IsCygwinTerminal(out.Fd())
if interactiveIn && interactiveOut {
return &interactiveStdio{in: in, out: out, err: err}
}
return &noninteractiveStdio{
in: bufio.NewScanner(in),
out: out,
err: err,
}
}
// TerminalStdio interacts with users over stdin/stdout/stderr.
var TerminalStdio = newTerminalStdio(os.Stdin, os.Stdout, os.Stderr)