github.com/coveo/gotemplate@v2.7.7+incompatible/utils/color.go (about)

     1  package utils
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/coveo/gotemplate/errors"
     8  	"github.com/fatih/color"
     9  )
    10  
    11  // Attribute is imported from color attribute
    12  type Attribute color.Attribute
    13  
    14  // The following constant are copied from the color package in order to get
    15  // the actual names
    16  const (
    17  	Reset Attribute = iota
    18  	Bold
    19  	Faint
    20  	Italic
    21  	Underline
    22  	BlinkSlow
    23  	BlinkRapid
    24  	ReverseVideo
    25  	Concealed
    26  	CrossedOut
    27  )
    28  
    29  // Foreground attributes
    30  const (
    31  	FgBlack Attribute = iota + 30
    32  	FgRed
    33  	FgGreen
    34  	FgYellow
    35  	FgBlue
    36  	FgMagenta
    37  	FgCyan
    38  	FgWhite
    39  )
    40  
    41  // Foreground attributes high intensity
    42  const (
    43  	FgHiBlack Attribute = iota + 90
    44  	FgHiRed
    45  	FgHiGreen
    46  	FgHiYellow
    47  	FgHiBlue
    48  	FgHiMagenta
    49  	FgHiCyan
    50  	FgHiWhite
    51  )
    52  
    53  // Background attributes
    54  const (
    55  	BgBlack Attribute = iota + 40
    56  	BgRed
    57  	BgGreen
    58  	BgYellow
    59  	BgBlue
    60  	BgMagenta
    61  	BgCyan
    62  	BgWhite
    63  )
    64  
    65  // Background attributes high intensity
    66  const (
    67  	BgHiBlack Attribute = iota + 100
    68  	BgHiRed
    69  	BgHiGreen
    70  	BgHiYellow
    71  	BgHiBlue
    72  	BgHiMagenta
    73  	BgHiCyan
    74  	BgHiWhite
    75  )
    76  
    77  var EOL = fmt.Sprintln()
    78  
    79  //go:generate stringer -type=Attribute -output generated_colors.go
    80  
    81  // Color returns a color attribute build from supplied attribute names
    82  func Color(attributes ...string) (*color.Color, error) {
    83  	if nameValues == nil {
    84  		nameValues = make(map[string]color.Attribute, BgHiWhite)
    85  		for i := Reset; i < BgHiWhite; i++ {
    86  			name := strings.ToLower(Attribute(i).String())
    87  			if strings.HasPrefix(name, "attribute(") {
    88  				continue
    89  			}
    90  			nameValues[name] = color.Attribute(i)
    91  			if strings.HasPrefix(name, "fg") {
    92  				nameValues[name[2:]] = color.Attribute(i)
    93  			}
    94  		}
    95  	}
    96  
    97  	result := color.New()
    98  	var containsColor bool
    99  	var err errors.Array
   100  	for _, attr := range attributes {
   101  		for _, attr := range String(attr).FieldsID().Strings() {
   102  			if a, match := nameValues[strings.ToLower(attr)]; match {
   103  				result.Add(a)
   104  				containsColor = true
   105  
   106  			} else {
   107  				err = append(err, fmt.Errorf("Attribute not found %s", attr))
   108  			}
   109  		}
   110  	}
   111  
   112  	if !containsColor {
   113  		return result, fmt.Errorf("No color specified")
   114  	}
   115  	if len(err) > 0 {
   116  		return result, err
   117  	}
   118  	return result, nil
   119  }
   120  
   121  // SprintColor returns a string formated with attributes that are supplied before
   122  func SprintColor(args ...interface{}) (string, error) {
   123  	var i int
   124  	colorArgs := make([]string, len(args))
   125  	for i = 0; i < len(args); i++ {
   126  		if _, err := Color(fmt.Sprint(args[i])); err != nil {
   127  			break
   128  		}
   129  		colorArgs[i] = fmt.Sprint(args[i])
   130  	}
   131  
   132  	c, _ := Color(colorArgs...)
   133  	return c.Sprint(FormatMessage(args[i:]...)), nil
   134  }
   135  
   136  // FormatMessage analyses the arguments to determine if printf or println should be used.
   137  func FormatMessage(args ...interface{}) string {
   138  	switch len(args) {
   139  	case 0:
   140  		return ""
   141  	case 1:
   142  		return fmt.Sprint(args[0])
   143  	default:
   144  		if format, args := fmt.Sprint(args[0]), args[1:]; strings.Contains(format, "%") {
   145  			if result := fmt.Sprintf(format, args...); !strings.Contains(result, "%!") {
   146  				return result
   147  			}
   148  		}
   149  		return strings.TrimSuffix(fmt.Sprintln(args...), EOL)
   150  	}
   151  }
   152  
   153  var nameValues map[string]color.Attribute
   154  
   155  // ColorPrintln call standard fmt.Println function but using the color out stream.
   156  func ColorPrintln(args ...interface{}) (int, error) {
   157  	return fmt.Fprintln(color.Output, args...)
   158  }
   159  
   160  // ColorPrintf call standard fmt.Printf function but using the color out stream.
   161  func ColorPrintf(format string, args ...interface{}) (int, error) {
   162  	return fmt.Fprintf(color.Output, format, args...)
   163  }
   164  
   165  // ColorPrint call standard fmt.Printf function but using the color out stream.
   166  func ColorPrint(args ...interface{}) (int, error) {
   167  	return fmt.Fprint(color.Output, args...)
   168  }
   169  
   170  // ColorErrorPrintln call standard fmt.Println function but using the color out stream.
   171  func ColorErrorPrintln(args ...interface{}) (int, error) {
   172  	return fmt.Fprintln(color.Error, args...)
   173  }
   174  
   175  // ColorErrorPrintf call standard fmt.Printf function but using the color out stream.
   176  func ColorErrorPrintf(format string, args ...interface{}) (int, error) {
   177  	return fmt.Fprintf(color.Error, format, args...)
   178  }
   179  
   180  // ColorErrorPrint call standard fmt.Printf function but using the color out stream.
   181  func ColorErrorPrint(args ...interface{}) (int, error) {
   182  	return fmt.Fprint(color.Error, args...)
   183  }