github.com/neilotoole/jsoncolor@v0.7.2-0.20231115150201-1637fae69be1/helper/fatihcolor/fatihcolor.go (about)

     1  // Package fatihcolor provides an adapter between fatih/color
     2  // and neilotoole/jsoncolor's native mechanism. See ToCoreColors.
     3  package fatihcolor
     4  
     5  import (
     6  	"bytes"
     7  
     8  	"github.com/fatih/color"
     9  	"github.com/neilotoole/jsoncolor"
    10  )
    11  
    12  // Colors encapsulates JSON color output, using fatih/color elements.
    13  // It can be converted to a jsoncolor.Colors using ToCoreColors.
    14  type Colors struct {
    15  	// Bool is the color for boolean values.
    16  	Bool *color.Color
    17  
    18  	// Bytes is the color for byte / binary values.
    19  	Bytes *color.Color
    20  
    21  	// Datetime is the color for time-related values.
    22  	Datetime *color.Color
    23  
    24  	// Null is the color for null.
    25  	Null *color.Color
    26  
    27  	// Number is the color for number values, including int,
    28  	// float, decimal etc.
    29  	Number *color.Color
    30  
    31  	// String is the color for string values.
    32  	String *color.Color
    33  
    34  	// Key is the color for keys such as a JSON field name.
    35  	Key *color.Color
    36  
    37  	// Punc is the color for punctuation such as colons, braces, etc.
    38  	// Frequently Punc will just be color.Bold.
    39  	Punc *color.Color
    40  
    41  	// TextMarshaler is the color for types implementing encoding.TextMarshaler.
    42  	TextMarshaler *color.Color
    43  }
    44  
    45  // DefaultColors returns default Colors instance.
    46  func DefaultColors() *Colors {
    47  	return &Colors{
    48  		Bool:          color.New(color.FgYellow),
    49  		Bytes:         color.New(color.Faint),
    50  		Datetime:      color.New(color.FgGreen, color.Faint),
    51  		Key:           color.New(color.FgBlue, color.Bold),
    52  		Null:          color.New(color.Faint),
    53  		Number:        color.New(color.FgCyan),
    54  		String:        color.New(color.FgGreen),
    55  		Punc:          color.New(color.Bold),
    56  		TextMarshaler: color.New(color.FgGreen),
    57  	}
    58  }
    59  
    60  // ToCoreColors converts clrs to a core jsoncolor.Colors instance.
    61  func ToCoreColors(clrs *Colors) *jsoncolor.Colors {
    62  	if clrs == nil {
    63  		return nil
    64  	}
    65  
    66  	return &jsoncolor.Colors{
    67  		Null:          ToCoreColor(clrs.Null),
    68  		Bool:          ToCoreColor(clrs.Bool),
    69  		Number:        ToCoreColor(clrs.Number),
    70  		String:        ToCoreColor(clrs.String),
    71  		Key:           ToCoreColor(clrs.Key),
    72  		Bytes:         ToCoreColor(clrs.Bytes),
    73  		Time:          ToCoreColor(clrs.Datetime),
    74  		Punc:          ToCoreColor(clrs.Punc),
    75  		TextMarshaler: ToCoreColor(clrs.TextMarshaler),
    76  	}
    77  }
    78  
    79  // ToCoreColor creates a jsoncolor.Color instance from a fatih/color
    80  // instance.
    81  func ToCoreColor(c *color.Color) jsoncolor.Color {
    82  	if c == nil {
    83  		return jsoncolor.Color{}
    84  	}
    85  
    86  	// Dirty conversion function ahead: print
    87  	// a space using c, then grab the bytes printed
    88  	// before the space, as those are the bytes we need.
    89  	// There's definitely a better way of doing this, but
    90  	// it works for now.
    91  
    92  	// Make a copy because the pkg-level color.NoColor could be false.
    93  	c2 := *c
    94  	c2.EnableColor()
    95  
    96  	b := []byte(c2.Sprint(" "))
    97  	i := bytes.IndexByte(b, ' ')
    98  	if i <= 0 {
    99  		return jsoncolor.Color{}
   100  	}
   101  
   102  	return b[:i]
   103  }