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 }