Commited dependencies
This commit is contained in:
325
vendor/github.com/manifoldco/promptui/prompt.go
generated
vendored
Normal file
325
vendor/github.com/manifoldco/promptui/prompt.go
generated
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
package promptui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/manifoldco/promptui/screenbuf"
|
||||
)
|
||||
|
||||
const cursor = "\u2588"
|
||||
|
||||
// Prompt represents a single line text field input.
|
||||
type Prompt struct {
|
||||
// Label is the value displayed on the command line prompt. It can be any
|
||||
// value one would pass to a text/template Execute(), including just a string.
|
||||
Label interface{}
|
||||
|
||||
Default string // Default is the initial value to populate in the prompt
|
||||
|
||||
// Validate is optional. If set, this function is used to validate the input
|
||||
// after each character entry.
|
||||
Validate ValidateFunc
|
||||
|
||||
// If mask is set, this value is displayed instead of the actual input
|
||||
// characters.
|
||||
Mask rune
|
||||
|
||||
// Templates can be used to customize the prompt output. If nil is passed, the
|
||||
// default templates are used.
|
||||
Templates *PromptTemplates
|
||||
|
||||
IsConfirm bool
|
||||
IsVimMode bool
|
||||
|
||||
stdin io.Reader
|
||||
stdout io.Writer
|
||||
}
|
||||
|
||||
// PromptTemplates allow a prompt to be customized following stdlib
|
||||
// text/template syntax. If any field is blank a default template is used.
|
||||
type PromptTemplates struct {
|
||||
// Prompt is a text/template for the initial prompt question.
|
||||
Prompt string
|
||||
|
||||
// Prompt is a text/template if the prompt is a confirmation.
|
||||
Confirm string
|
||||
|
||||
// Valid is a text/template for when the current input is valid.
|
||||
Valid string
|
||||
|
||||
// Invalid is a text/template for when the current input is invalid.
|
||||
Invalid string
|
||||
|
||||
// Success is a text/template for the successful result.
|
||||
Success string
|
||||
|
||||
// Prompt is a text/template when there is a validation error.
|
||||
ValidationError string
|
||||
|
||||
// FuncMap is a map of helpers for the templates. If nil, the default helpers
|
||||
// are used.
|
||||
FuncMap template.FuncMap
|
||||
|
||||
prompt *template.Template
|
||||
valid *template.Template
|
||||
invalid *template.Template
|
||||
validation *template.Template
|
||||
success *template.Template
|
||||
}
|
||||
|
||||
// Run runs the prompt, returning the validated input.
|
||||
func (p *Prompt) Run() (string, error) {
|
||||
c := &readline.Config{}
|
||||
err := c.Init()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = p.prepareTemplates()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if p.stdin != nil {
|
||||
c.Stdin = p.stdin
|
||||
}
|
||||
|
||||
if p.stdout != nil {
|
||||
c.Stdout = p.stdout
|
||||
}
|
||||
|
||||
if p.Mask != 0 {
|
||||
c.EnableMask = true
|
||||
c.MaskRune = p.Mask
|
||||
}
|
||||
|
||||
if p.IsVimMode {
|
||||
c.VimMode = true
|
||||
}
|
||||
|
||||
c.HistoryLimit = -1
|
||||
c.UniqueEditLine = true
|
||||
|
||||
rl, err := readline.NewEx(c)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
rl.Write([]byte(hideCursor))
|
||||
sb := screenbuf.New(rl)
|
||||
|
||||
validFn := func(x string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if p.Validate != nil {
|
||||
validFn = p.Validate
|
||||
}
|
||||
|
||||
var inputErr error
|
||||
input := p.Default
|
||||
eraseDefault := input != ""
|
||||
|
||||
c.SetListener(func(line []rune, pos int, key rune) ([]rune, int, bool) {
|
||||
if line != nil {
|
||||
input += string(line)
|
||||
}
|
||||
|
||||
switch key {
|
||||
case 0: // empty
|
||||
case readline.CharEnter:
|
||||
return nil, 0, false
|
||||
case readline.CharBackspace:
|
||||
if eraseDefault {
|
||||
eraseDefault = false
|
||||
input = ""
|
||||
}
|
||||
if len(input) > 0 {
|
||||
input = input[:len(input)-1]
|
||||
}
|
||||
default:
|
||||
if eraseDefault {
|
||||
eraseDefault = false
|
||||
input = string(line)
|
||||
}
|
||||
}
|
||||
|
||||
err := validFn(input)
|
||||
var prompt []byte
|
||||
|
||||
if err != nil {
|
||||
prompt = render(p.Templates.invalid, p.Label)
|
||||
} else {
|
||||
prompt = render(p.Templates.valid, p.Label)
|
||||
if p.IsConfirm {
|
||||
prompt = render(p.Templates.prompt, p.Label)
|
||||
}
|
||||
}
|
||||
|
||||
echo := input
|
||||
if p.Mask != 0 {
|
||||
echo = strings.Repeat(string(p.Mask), len(echo))
|
||||
}
|
||||
|
||||
prompt = append(prompt, []byte(echo+cursor)...)
|
||||
|
||||
sb.Reset()
|
||||
sb.Write(prompt)
|
||||
|
||||
if inputErr != nil {
|
||||
validation := render(p.Templates.validation, inputErr)
|
||||
sb.Write(validation)
|
||||
inputErr = nil
|
||||
}
|
||||
|
||||
sb.Flush()
|
||||
|
||||
return nil, 0, true
|
||||
})
|
||||
|
||||
for {
|
||||
_, err = rl.Readline()
|
||||
|
||||
inputErr = validFn(input)
|
||||
if inputErr == nil {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
switch err {
|
||||
case readline.ErrInterrupt:
|
||||
err = ErrInterrupt
|
||||
case io.EOF:
|
||||
err = ErrEOF
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if err.Error() == "Interrupt" {
|
||||
err = ErrInterrupt
|
||||
}
|
||||
sb.Reset()
|
||||
sb.WriteString("")
|
||||
sb.Flush()
|
||||
rl.Write([]byte(showCursor))
|
||||
rl.Close()
|
||||
return "", err
|
||||
}
|
||||
|
||||
echo := input
|
||||
if p.Mask != 0 {
|
||||
echo = strings.Repeat(string(p.Mask), len(echo))
|
||||
}
|
||||
|
||||
prompt := render(p.Templates.valid, p.Label)
|
||||
prompt = append(prompt, []byte(echo)...)
|
||||
|
||||
if p.IsConfirm && strings.ToLower(echo) != "y" {
|
||||
prompt = render(p.Templates.invalid, p.Label)
|
||||
err = ErrAbort
|
||||
}
|
||||
|
||||
sb.Reset()
|
||||
sb.Write(prompt)
|
||||
sb.Flush()
|
||||
rl.Write([]byte(showCursor))
|
||||
rl.Close()
|
||||
|
||||
return input, err
|
||||
}
|
||||
|
||||
func (p *Prompt) prepareTemplates() error {
|
||||
tpls := p.Templates
|
||||
if tpls == nil {
|
||||
tpls = &PromptTemplates{}
|
||||
}
|
||||
|
||||
if tpls.FuncMap == nil {
|
||||
tpls.FuncMap = FuncMap
|
||||
}
|
||||
|
||||
bold := Styler(FGBold)
|
||||
|
||||
if p.IsConfirm {
|
||||
p.Default = ""
|
||||
if tpls.Confirm == "" {
|
||||
confirm := "y/N"
|
||||
if strings.ToLower(p.Default) == "y" {
|
||||
confirm = "Y/n"
|
||||
}
|
||||
tpls.Confirm = fmt.Sprintf(`{{ "%s" | bold }} {{ . | bold }}? {{ "[%s]" | faint }} `, IconInitial, confirm)
|
||||
}
|
||||
|
||||
tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Confirm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tpls.prompt = tpl
|
||||
} else {
|
||||
if tpls.Prompt == "" {
|
||||
tpls.Prompt = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconInitial), bold(":"))
|
||||
}
|
||||
|
||||
tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Prompt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tpls.prompt = tpl
|
||||
}
|
||||
|
||||
if tpls.Valid == "" {
|
||||
tpls.Valid = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconGood), bold(":"))
|
||||
}
|
||||
|
||||
tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Valid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tpls.valid = tpl
|
||||
|
||||
if tpls.Invalid == "" {
|
||||
tpls.Invalid = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconBad), bold(":"))
|
||||
}
|
||||
|
||||
tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Invalid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tpls.invalid = tpl
|
||||
|
||||
if tpls.ValidationError == "" {
|
||||
tpls.ValidationError = `{{ ">>" | red }} {{ . | red }}`
|
||||
}
|
||||
|
||||
tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.ValidationError)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tpls.validation = tpl
|
||||
|
||||
if tpls.Success == "" {
|
||||
tpls.Success = `{{ . | faint }}`
|
||||
}
|
||||
|
||||
tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Success)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tpls.success = tpl
|
||||
|
||||
p.Templates = tpls
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user