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