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  }