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