github.com/containerd/nerdctl/v2@v2.0.0-beta.5.0.20240520001846-b5758f54fa28/pkg/composer/pipetagger/pipetagger.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package pipetagger
    18  
    19  import (
    20  	"bufio"
    21  	"fmt"
    22  	"hash/fnv"
    23  	"io"
    24  	"strings"
    25  
    26  	"github.com/fatih/color"
    27  )
    28  
    29  func ChooseColorAttrs(tag string) []color.Attribute {
    30  	hasher := fnv.New32()
    31  	hasher.Write([]byte(tag))
    32  	tagHash := int(hasher.Sum32())
    33  
    34  	fgCandidates := []color.Attribute{
    35  		color.FgBlack,
    36  		color.FgRed,
    37  		color.FgGreen,
    38  		color.FgYellow,
    39  		color.FgBlue,
    40  		color.FgMagenta,
    41  		color.FgCyan,
    42  		color.FgWhite,
    43  		color.FgHiBlack,
    44  		color.FgHiRed,
    45  		color.FgHiGreen,
    46  		color.FgHiYellow,
    47  		color.FgHiBlue,
    48  		color.FgHiMagenta,
    49  		color.FgHiCyan,
    50  		color.FgHiWhite,
    51  	}
    52  	fgAttr := fgCandidates[tagHash%len(fgCandidates)]
    53  
    54  	attrs := []color.Attribute{
    55  		fgAttr,
    56  	}
    57  
    58  	switch fgAttr {
    59  	case color.FgBlack:
    60  		attrs = append(attrs, color.BgWhite)
    61  	case color.FgWhite:
    62  		attrs = append(attrs, color.BgBlack)
    63  	case color.FgHiBlack:
    64  		attrs = append(attrs, color.BgHiWhite)
    65  	case color.FgHiWhite:
    66  		attrs = append(attrs, color.BgHiBlack)
    67  	}
    68  
    69  	return attrs
    70  }
    71  
    72  // New create a PipeTagger.
    73  // Set width = -1 to disable tagging.
    74  func New(w io.Writer, r io.Reader, tag string, width int, noColor bool) *PipeTagger {
    75  	var attrs []color.Attribute
    76  	if !noColor {
    77  		attrs = ChooseColorAttrs(tag)
    78  	}
    79  	return &PipeTagger{
    80  		w:     w,
    81  		r:     r,
    82  		tag:   tag,
    83  		width: width,
    84  		color: color.New(attrs...),
    85  	}
    86  }
    87  
    88  type PipeTagger struct {
    89  	w     io.Writer
    90  	r     io.Reader
    91  	tag   string
    92  	width int
    93  	color *color.Color
    94  }
    95  
    96  func (x *PipeTagger) Run() error {
    97  	scanner := bufio.NewScanner(x.r)
    98  	for scanner.Scan() {
    99  		line := scanner.Text()
   100  		if x.width < 0 {
   101  			fmt.Fprintln(x.w, line)
   102  		} else {
   103  			fmt.Fprintf(x.w, "%s%s|%s\n",
   104  				x.color.Sprint(x.tag),
   105  				strings.Repeat(" ", x.width-len(x.tag)),
   106  				line,
   107  			)
   108  		}
   109  	}
   110  	return scanner.Err()
   111  }