github.com/hernad/nomad@v1.6.112/command/ui/log_ui.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package ui
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"io"
    10  
    11  	"github.com/fatih/color"
    12  	"github.com/mitchellh/cli"
    13  )
    14  
    15  // LogUI is an implementation of the cli.Ui interface which can be used for
    16  // logging outputs. It differs from cli.BasicUi in the only fact that it does
    17  // not add a newline after each UI write.
    18  type LogUI struct {
    19  	reader      io.Reader
    20  	writer      io.Writer
    21  	errorWriter io.Writer
    22  
    23  	// underlyingUI stores the basic UI that was used to create this logUI. It
    24  	// allows us to call the ask functions and not implement them again.
    25  	underlyingUI cli.Ui
    26  
    27  	isColor     bool
    28  	outputColor cli.UiColor
    29  	infoColor   cli.UiColor
    30  	errorColor  cli.UiColor
    31  	warnColor   cli.UiColor
    32  }
    33  
    34  // NewLogUI generates a new cli.Ui that can be used for commands that write log
    35  // lines to the terminal. The caller is required to pass a cli.BasicUi so we
    36  // have access to the underlying writers.
    37  //
    38  // Currently, the passed ui needs to be either *cli.ColoredUi or *cli.BasicUi
    39  // to work correctly. If more are needed, please add them.
    40  func NewLogUI(ui cli.Ui) (cli.Ui, error) {
    41  
    42  	var found bool
    43  
    44  	logUI := LogUI{}
    45  
    46  	if coloredUI, ok := ui.(*cli.ColoredUi); ok {
    47  
    48  		logUI.isColor = true
    49  		logUI.outputColor = coloredUI.OutputColor
    50  		logUI.infoColor = coloredUI.InfoColor
    51  		logUI.errorColor = coloredUI.ErrorColor
    52  		logUI.warnColor = coloredUI.WarnColor
    53  		logUI.underlyingUI = coloredUI.Ui
    54  
    55  		if basicUI, ok := coloredUI.Ui.(*cli.BasicUi); ok {
    56  			logUI.reader = basicUI.Reader
    57  			logUI.writer = basicUI.Writer
    58  			logUI.errorWriter = basicUI.ErrorWriter
    59  			found = true
    60  		}
    61  	} else if basicUI, ok := ui.(*cli.BasicUi); ok && !found {
    62  		logUI.reader = basicUI.Reader
    63  		logUI.writer = basicUI.Writer
    64  		logUI.errorWriter = basicUI.ErrorWriter
    65  		logUI.underlyingUI = basicUI
    66  		found = true
    67  	}
    68  
    69  	if !found {
    70  		return nil, errors.New("failed to generate logging UI")
    71  	}
    72  
    73  	return &logUI, nil
    74  }
    75  
    76  // Ask implements the Ask function of the cli.Ui interface.
    77  func (l *LogUI) Ask(query string) (string, error) {
    78  	return l.underlyingUI.Ask(l.colorize(query, l.outputColor))
    79  }
    80  
    81  // AskSecret implements the AskSecret function of the cli.Ui interface.
    82  func (l *LogUI) AskSecret(query string) (string, error) {
    83  	return l.underlyingUI.AskSecret(l.colorize(query, l.outputColor))
    84  }
    85  
    86  // Output implements the Output function of the cli.Ui interface.
    87  func (l *LogUI) Output(message string) {
    88  	_, _ = fmt.Fprint(l.writer, l.colorize(message, l.outputColor))
    89  }
    90  
    91  // Info implements the Info function of the cli.Ui interface.
    92  func (l *LogUI) Info(message string) { l.Output(l.colorize(message, l.infoColor)) }
    93  
    94  // Error implements the Error function of the cli.Ui interface.
    95  func (l *LogUI) Error(message string) {
    96  	w := l.writer
    97  	if l.errorWriter != nil {
    98  		w = l.errorWriter
    99  	}
   100  	_, _ = fmt.Fprint(w, l.colorize(message, l.errorColor))
   101  }
   102  
   103  // Warn implements the Warn function of the cli.Ui interface.
   104  func (l *LogUI) Warn(message string) { l.Error(l.colorize(message, l.warnColor)) }
   105  
   106  func (l *LogUI) colorize(message string, uc cli.UiColor) string {
   107  	if !l.isColor {
   108  		return message
   109  	}
   110  
   111  	attr := []color.Attribute{color.Attribute(uc.Code)}
   112  	if uc.Bold {
   113  		attr = append(attr, color.Bold)
   114  	}
   115  
   116  	return color.New(attr...).SprintFunc()(message)
   117  }