101 lines
2.5 KiB
Go
101 lines
2.5 KiB
Go
package stdio
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
|
|
"github.com/AlecAivazis/survey/v2"
|
|
"github.com/AlecAivazis/survey/v2/terminal"
|
|
)
|
|
|
|
// interactiveStdio interacts with the user via an interactive terminal.
|
|
type interactiveStdio struct {
|
|
in terminal.FileReader
|
|
out terminal.FileWriter
|
|
err io.Writer
|
|
}
|
|
|
|
func (t *interactiveStdio) Write(p []byte) (int, error) {
|
|
return t.out.Write(p)
|
|
}
|
|
|
|
func (t *interactiveStdio) WriteErr(p []byte) (int, error) {
|
|
return t.err.Write(p)
|
|
}
|
|
|
|
type bannerTemplateData struct {
|
|
Message string
|
|
}
|
|
|
|
var bannerTemplate = `{{color "cyan+hb"}}> {{ .Message }}{{color "reset"}}
|
|
`
|
|
|
|
func (t *interactiveStdio) Banner(message string) error {
|
|
r := survey.Renderer{}
|
|
r.WithStdio(terminal.Stdio{In: t.in, Out: t.out, Err: t.err})
|
|
return r.Render(bannerTemplate, &bannerTemplateData{Message: message})
|
|
}
|
|
|
|
func (t *interactiveStdio) Error(message string) error {
|
|
r := survey.Renderer{}
|
|
r.WithStdio(terminal.Stdio{In: t.in, Out: t.out, Err: t.err})
|
|
cfg := survey.PromptConfig{Icons: survey.IconSet{Error: survey.Icon{Text: "X", Format: "red"}}}
|
|
return r.Error(&cfg, errors.New(message))
|
|
}
|
|
|
|
func (t *interactiveStdio) IsInteractive() bool {
|
|
return true
|
|
}
|
|
|
|
func (t *interactiveStdio) GetStringInput(prompt, defaultValue string) (input string, err error) {
|
|
question := survey.Input{
|
|
Message: prompt,
|
|
Default: defaultValue,
|
|
}
|
|
err = survey.AskOne(&question, &input,
|
|
survey.WithStdio(t.in, t.out, t.err),
|
|
survey.WithValidator(survey.Required))
|
|
return
|
|
}
|
|
|
|
func (t *interactiveStdio) GetSecret(prompt string, minLen int) (password string, err error) {
|
|
question := survey.Password{Message: prompt}
|
|
opts := []survey.AskOpt{survey.WithStdio(t.in, t.out, t.err)}
|
|
if minLen > 0 {
|
|
opts = append(opts, survey.WithValidator(survey.MinLength(minLen)))
|
|
}
|
|
err = survey.AskOne(&question, &password, opts...)
|
|
question.NewCursor().HorizontalAbsolute(0)
|
|
return
|
|
}
|
|
|
|
func (t *interactiveStdio) GetPassword(prompt string) (string, error) {
|
|
for {
|
|
pass1, err := t.GetSecret(prompt, MinPasswordLen)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
// Don't bother with the length check the 2nd time, since we check equality to pass1.
|
|
pass2, err := t.GetSecret(prompt+" again", 0)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if pass1 == pass2 {
|
|
return pass1, nil
|
|
}
|
|
if err := t.Error("Passwords do not match"); err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *interactiveStdio) GetConfirm(prompt string) (answer bool) {
|
|
question := survey.Confirm{
|
|
Message: prompt,
|
|
}
|
|
if err := survey.AskOne(&question, &answer, survey.WithStdio(t.in, t.out, t.err)); err != nil {
|
|
answer = false
|
|
}
|
|
return
|
|
}
|