File: ask.go

package info (click to toggle)
golang-github-tcnksm-go-input 0.0~git20180404.548a7d7-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 136 kB
  • sloc: makefile: 20
file content (90 lines) | stat: -rw-r--r-- 2,004 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package input

import (
	"bytes"
	"fmt"
)

// Ask asks the user for input using the given query. The response is
// returned as string. Error is returned based on the given option.
// If Loop is true, it continue to ask until it receives valid input.
//
// If the user sends SIGINT (Ctrl+C) while reading input, it catches
// it and return it as a error.
func (i *UI) Ask(query string, opts *Options) (string, error) {
	i.once.Do(i.setDefault)

	// Display the query to the user.
	fmt.Fprintf(i.Writer, "%s", query)

	// resultStr and resultErr are return val of this function
	var resultStr string
	var resultErr error

	loopCount := 0
	for {
		loopCount++

		// Construct the instruction to user.
		var buf bytes.Buffer
		if !opts.HideOrder || loopCount > 1 {
			buf.WriteString("\nEnter a value")
		}

		if opts.Default != "" && !opts.HideDefault {
			defaultVal := opts.Default
			if opts.MaskDefault {
				defaultVal = maskString(defaultVal)
			}
			buf.WriteString(fmt.Sprintf(" (Default is %s)", defaultVal))
		}

		// Display the instruction to user and ask to input.
		buf.WriteString(": ")
		fmt.Fprintf(i.Writer, buf.String())

		// Read user input from UI.Reader.
		line, err := i.read(opts.readOpts())
		if err != nil {
			resultErr = err
			break
		}

		// line is empty but default is provided returns it
		if line == "" && opts.Default != "" {
			resultStr = opts.Default
			break
		}

		if line == "" && opts.Required {
			if !opts.Loop {
				resultErr = ErrEmpty
				break
			}

			fmt.Fprintf(i.Writer, "Input must not be empty.\n\n")
			continue
		}

		// validate input by custom fuction
		validate := opts.validateFunc()
		if err := validate(line); err != nil {
			if !opts.Loop {
				resultErr = err
				break
			}

			fmt.Fprintf(i.Writer, "Failed to validate input string: %s\n\n", err)
			continue
		}

		// Reach here means it gets ideal input.
		resultStr = line
		break
	}

	// Insert the new line for next output
	fmt.Fprintf(i.Writer, "\n")

	return resultStr, resultErr
}