github.com/elopio/cli@v6.21.2-0.20160902224010-ea909d1fdb2f+incompatible/commands/ui/ui.go (about) 1 // package ui will provide hooks into STDOUT, STDERR and STDIN. It will also 2 // handle translation as necessary. 3 package ui 4 5 import ( 6 "fmt" 7 "io" 8 "strings" 9 "text/tabwriter" 10 "text/template" 11 12 "github.com/fatih/color" 13 14 "code.cloudfoundry.org/cli/utils/config" 15 "github.com/nicksnyder/go-i18n/i18n" 16 ) 17 18 const ( 19 // red color.Attribute = color.FgRed 20 // green = color.FgGreen 21 // yellow = color.FgYellow 22 // magenta = color.FgMagenta 23 // cyan = color.FgCyan 24 // grey = color.FgWhite 25 defaultFgColor = 38 26 ) 27 28 //go:generate counterfeiter . Config 29 30 // Config is the UI configuration 31 type Config interface { 32 // ColorEnabled enables or disabled color 33 ColorEnabled() config.ColorSetting 34 35 // Locale is the language to translate the output to 36 Locale() string 37 } 38 39 // UI is interface to interact with the user 40 type UI struct { 41 // Out is the output buffer 42 Out io.Writer 43 44 colorEnabled config.ColorSetting 45 46 translate i18n.TranslateFunc 47 } 48 49 // NewUI will return a UI object where Out is set to STDOUT 50 func NewUI(c Config) (UI, error) { 51 translateFunc, err := GetTranslationFunc(c) 52 if err != nil { 53 return UI{}, err 54 } 55 56 return UI{ 57 Out: color.Output, 58 colorEnabled: c.ColorEnabled(), 59 translate: translateFunc, 60 }, nil 61 } 62 63 // NewTestUI will return a UI object where Out is customizable 64 func NewTestUI(out io.Writer) UI { 65 return UI{ 66 Out: out, 67 colorEnabled: config.ColorDisbled, 68 translate: i18n.TranslateFunc(func(s string, _ ...interface{}) string { return s }), 69 } 70 } 71 72 // DisplayTable presents a two dimentional array of strings as a table 73 func (ui UI) DisplayTable(prefix string, table [][]string) { 74 tw := tabwriter.NewWriter(ui.Out, 0, 1, 4, ' ', 0) 75 76 for _, row := range table { 77 fmt.Fprint(tw, prefix) 78 fmt.Fprintln(tw, strings.Join(row, "\t")) 79 } 80 81 tw.Flush() 82 } 83 84 // DisplayText combines the formattedString template with the key maps and then 85 // outputs it to the UI.Out file. The maps are merged in a way that the last 86 // one takes precidence over the first. Prior to outputting the 87 // formattedString, it is run through the an internationalization function to 88 // translate it to a pre-cofigured langauge. 89 func (ui UI) DisplayText(formattedString string, keys ...map[string]interface{}) { 90 mergedMap := ui.mergeMap(keys) 91 translatedFormatString := ui.translate(formattedString, mergedMap) 92 formattedTemplate := template.Must(template.New("Display Text").Parse(translatedFormatString)) 93 formattedTemplate.Execute(ui.Out, mergedMap) 94 ui.DisplayNewline() 95 } 96 97 // DisplayTextWithKeyTranslations merges keys together (similar to 98 // DisplayText), translates the keys listed in keysToTranslate, and then passes 99 // these values to DisplayText. 100 func (ui UI) DisplayTextWithKeyTranslations(formattedString string, keysToTranslate []string, keys ...map[string]interface{}) { 101 mergedMap := ui.mergeMap(keys) 102 for _, key := range keysToTranslate { 103 mergedMap[key] = ui.translate(mergedMap[key].(string)) 104 } 105 ui.DisplayText(formattedString, mergedMap) 106 } 107 108 // DisplayNewline outputs a newline. 109 func (ui UI) DisplayNewline() { 110 fmt.Fprintf(ui.Out, "\n") 111 } 112 113 // DisplayHelpHeader translates and then bolds the help header. 114 func (ui UI) DisplayHelpHeader(text string) { 115 fmt.Fprintf(ui.Out, ui.colorize(ui.translate(text), defaultFgColor, true)) 116 ui.DisplayNewline() 117 } 118 119 func (ui UI) mergeMap(maps []map[string]interface{}) map[string]interface{} { 120 if len(maps) == 1 { 121 return maps[0] 122 } 123 124 main := map[string]interface{}{} 125 126 for _, minor := range maps { 127 for key, value := range minor { 128 main[key] = value 129 } 130 } 131 132 return main 133 } 134 135 func (ui UI) colorize(message string, textColor color.Attribute, bold bool) string { 136 colorPrinter := color.New(textColor) 137 switch ui.colorEnabled { 138 case config.ColorEnabled: 139 colorPrinter.EnableColor() 140 case config.ColorDisbled: 141 colorPrinter.DisableColor() 142 } 143 144 if bold { 145 colorPrinter = colorPrinter.Add(color.Bold) 146 } 147 f := colorPrinter.SprintFunc() 148 return f(message) 149 }