github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/prompt/helpers.go (about) 1 package prompt 2 3 import ( 4 "math" 5 "reflect" 6 "strings" 7 8 "gopkg.in/AlecAivazis/survey.v1" 9 "gopkg.in/AlecAivazis/survey.v1/core" 10 11 "github.com/ActiveState/cli/internal/colorize" 12 "github.com/ActiveState/cli/internal/osutils/termsize" 13 14 "github.com/ActiveState/cli/internal/locale" 15 ) 16 17 func init() { 18 core.ErrorIcon = "" 19 core.HelpIcon = "" 20 core.QuestionIcon = "" 21 core.SelectFocusIcon = ">" 22 core.MarkedOptionIcon = "[x]" 23 core.UnmarkedOptionIcon = "[ ]" 24 core.ErrorTemplate = locale.Tt("survey_error_template") 25 26 // Drop questionicon from templates as it causes indented text 27 survey.SelectQuestionTemplate = `{{ .Message }} 28 {{- "\n"}} 29 {{- range $ix, $choice := .PageEntries}} 30 {{- "\n"}} 31 {{- if eq $ix $.SelectedIndex}}{{color "cyan+h"}}{{ SelectFocusIcon }} {{else}} {{end}} 32 {{- $choice}} 33 {{- color "reset"}} 34 {{- end}} 35 ` 36 37 survey.InputQuestionTemplate = `{{- if ne .Message ""}}{{- .Message }}{{- "\n"}}{{- end}} 38 {{- color "cyan+h"}}{{- "> "}}{{- color "reset"}}` 39 40 survey.ConfirmQuestionTemplate = `{{ .Message }}{{" "}} 41 {{- color "cyan+h"}}{{- if .Default}}(Y/n) {{- else}}(y/N) {{- end}}{{- color "reset"}} 42 {{color "cyan+h"}}{{- "> "}}{{- color "reset"}}` 43 44 survey.PasswordQuestionTemplate = `{{- if ne .Message ""}}{{- .Message }}{{end}} 45 {{color "cyan+h"}}{{- "> "}}{{- color "reset"}}` 46 } 47 48 // inputRequired does not allow an empty value 49 func inputRequired(val interface{}) error { 50 // the reflect value of the result 51 value := reflect.ValueOf(val) 52 53 // if the value passed in is the zero value of the appropriate type 54 if isZero(value) && value.Kind() != reflect.Bool && value.Kind() != reflect.Int { 55 return locale.NewError("err_value_required") 56 } 57 return nil 58 } 59 60 // isZero returns true if the passed value is the zero object 61 func isZero(v reflect.Value) bool { 62 switch v.Kind() { 63 case reflect.Slice, reflect.Map: 64 return v.Len() == 0 65 } 66 67 // compare the types directly with more general coverage 68 return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) 69 } 70 71 func formatMessage(message string, colors bool) string { 72 message = colorize.ColorizedOrStrip(message, colors) 73 cols := termsize.GetTerminalColumns() 74 return formatMessageByCols(message, cols) 75 } 76 77 func formatMessageByCols(message string, cols int) string { 78 var newMessage string 79 startIdx := 0 80 cols = cols - 1 // reduce cols by 1 because the final col is the linebreak 81 82 // Rebuild message and add linebreaks as needed 83 for { 84 if len(message[startIdx:]) == 0 { 85 // EOF 86 break 87 } 88 var idx int 89 var endIdx = min(startIdx+cols, len(message)) 90 if idx = strings.Index(message[startIdx:endIdx], "\n"); idx == -1 { 91 // If no linebreak was found move to the next column and add a linebreak 92 idx = startIdx + min(cols, len(message[startIdx:])) 93 } else { 94 // Linebreak was found, move past it 95 idx = startIdx + idx + 1 // Include the linebreak 96 } 97 98 newMessage = newMessage + message[startIdx:idx] 99 startIdx = idx 100 if len(message) > idx && newMessage[len(newMessage)-1:] != "\n" { 101 newMessage = newMessage + "\n" 102 } 103 } 104 105 return newMessage 106 } 107 108 func min(v1 int, v2 int) int { 109 return int(math.Min(float64(v1), float64(v2))) 110 }