1package survey
2
3import (
4	"fmt"
5	"strings"
6
7	"gopkg.in/AlecAivazis/survey.v1/core"
8	"gopkg.in/AlecAivazis/survey.v1/terminal"
9)
10
11type Multiline struct {
12	core.Renderer
13	Message string
14	Default string
15	Help    string
16}
17
18// data available to the templates when processing
19type MultilineTemplateData struct {
20	Multiline
21	Answer     string
22	ShowAnswer bool
23	ShowHelp   bool
24}
25
26// Templates with Color formatting. See Documentation: https://github.com/mgutz/ansi#style-format
27var MultilineQuestionTemplate = `
28{{- if .ShowHelp }}{{- color "cyan"}}{{ HelpIcon }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}}
29{{- color "green+hb"}}{{ QuestionIcon }} {{color "reset"}}
30{{- color "default+hb"}}{{ .Message }} {{color "reset"}}
31{{- if .ShowAnswer}}
32  {{- "\n"}}{{color "cyan"}}{{.Answer}}{{color "reset"}}
33  {{- if .Answer }}{{ "\n" }}{{ end }}
34{{- else }}
35  {{- if .Default}}{{color "white"}}({{.Default}}) {{color "reset"}}{{end}}
36  {{- color "cyan"}}[Enter 2 empty lines to finish]{{color "reset"}}
37{{- end}}`
38
39func (i *Multiline) Prompt() (interface{}, error) {
40	// render the template
41	err := i.Render(
42		MultilineQuestionTemplate,
43		MultilineTemplateData{Multiline: *i},
44	)
45	if err != nil {
46		return "", err
47	}
48	fmt.Println()
49
50	// start reading runes from the standard in
51	rr := i.NewRuneReader()
52	rr.SetTermMode()
53	defer rr.RestoreTermMode()
54
55	cursor := i.NewCursor()
56
57	multiline := make([]string, 0)
58
59	emptyOnce := false
60	// get the next line
61	for {
62		line := []rune{}
63		line, err = rr.ReadLine(0)
64		if err != nil {
65			return string(line), err
66		}
67
68		if string(line) == "" {
69			if emptyOnce {
70				numLines := len(multiline) + 2
71				cursor.PreviousLine(numLines)
72				for j := 0; j < numLines; j++ {
73					terminal.EraseLine(i.Stdio().Out, terminal.ERASE_LINE_ALL)
74					cursor.NextLine(1)
75				}
76				cursor.PreviousLine(numLines)
77				break
78			}
79			emptyOnce = true
80		} else {
81			emptyOnce = false
82		}
83		multiline = append(multiline, string(line))
84	}
85
86	val := strings.Join(multiline, "\n")
87	val = strings.TrimSpace(val)
88
89	// if the line is empty
90	if len(val) == 0 {
91		// use the default value
92		return i.Default, err
93	}
94
95	// we're done
96	return val, err
97}
98
99func (i *Multiline) Cleanup(val interface{}) error {
100	return i.Render(
101		MultilineQuestionTemplate,
102		MultilineTemplateData{Multiline: *i, Answer: val.(string), ShowAnswer: true},
103	)
104}
105