mfer/vendor/github.com/pterm/pterm/prefix_printer.go

343 lines
9.7 KiB
Go

package pterm
import (
"fmt"
"runtime"
"strings"
"github.com/pterm/pterm/internal"
)
var (
// GrayBoxStyle wraps text in a gray box.
GrayBoxStyle = NewStyle(BgGray, FgLightWhite)
)
var (
// Info returns a PrefixPrinter, which can be used to print text with an "info" Prefix.
Info = PrefixPrinter{
MessageStyle: &ThemeDefault.InfoMessageStyle,
Prefix: Prefix{
Style: &ThemeDefault.InfoPrefixStyle,
Text: "INFO",
},
}
// Warning returns a PrefixPrinter, which can be used to print text with a "warning" Prefix.
Warning = PrefixPrinter{
MessageStyle: &ThemeDefault.WarningMessageStyle,
Prefix: Prefix{
Style: &ThemeDefault.WarningPrefixStyle,
Text: "WARNING",
},
}
// Success returns a PrefixPrinter, which can be used to print text with a "success" Prefix.
Success = PrefixPrinter{
MessageStyle: &ThemeDefault.SuccessMessageStyle,
Prefix: Prefix{
Style: &ThemeDefault.SuccessPrefixStyle,
Text: "SUCCESS",
},
}
// Error returns a PrefixPrinter, which can be used to print text with an "error" Prefix.
Error = PrefixPrinter{
MessageStyle: &ThemeDefault.ErrorMessageStyle,
Prefix: Prefix{
Style: &ThemeDefault.ErrorPrefixStyle,
Text: " ERROR ",
},
}
// Fatal returns a PrefixPrinter, which can be used to print text with an "fatal" Prefix.
// NOTICE: Fatal terminates the application immediately!
Fatal = PrefixPrinter{
MessageStyle: &ThemeDefault.FatalMessageStyle,
Prefix: Prefix{
Style: &ThemeDefault.FatalPrefixStyle,
Text: " FATAL ",
},
Fatal: true,
}
// Debug Prints debug messages. By default it will only print if PrintDebugMessages is true.
// You can change PrintDebugMessages with EnableDebugMessages and DisableDebugMessages, or by setting the variable itself.
Debug = PrefixPrinter{
MessageStyle: &ThemeDefault.DebugMessageStyle,
Prefix: Prefix{
Text: " DEBUG ",
Style: &ThemeDefault.DebugPrefixStyle,
},
Debugger: true,
}
// Description returns a PrefixPrinter, which can be used to print text with a "description" Prefix.
Description = PrefixPrinter{
MessageStyle: &ThemeDefault.DescriptionMessageStyle,
Prefix: Prefix{
Style: &ThemeDefault.DescriptionPrefixStyle,
Text: "Description",
},
}
)
// PrefixPrinter is the printer used to print a Prefix.
type PrefixPrinter struct {
Prefix Prefix
Scope Scope
MessageStyle *Style
Fatal bool
ShowLineNumber bool
LineNumberOffset int
// If Debugger is true, the printer will only print if PrintDebugMessages is set to true.
// You can change PrintDebugMessages with EnableDebugMessages and DisableDebugMessages, or by setting the variable itself.
Debugger bool
}
// WithPrefix adds a custom prefix to the printer.
func (p PrefixPrinter) WithPrefix(prefix Prefix) *PrefixPrinter {
p.Prefix = prefix
return &p
}
// WithScope adds a scope to the Prefix.
func (p PrefixPrinter) WithScope(scope Scope) *PrefixPrinter {
p.Scope = scope
return &p
}
// WithMessageStyle adds a custom prefix to the printer.
func (p PrefixPrinter) WithMessageStyle(style *Style) *PrefixPrinter {
p.MessageStyle = style
return &p
}
// WithFatal sets if the printer should panic after printing.
// NOTE:
// The printer will only panic if either PrefixPrinter.Println, PrefixPrinter.Print
// or PrefixPrinter.Printf is called.
func (p PrefixPrinter) WithFatal(b ...bool) *PrefixPrinter {
p.Fatal = internal.WithBoolean(b)
return &p
}
// WithShowLineNumber sets if the printer should print the line number from where it's called in a go file.
func (p PrefixPrinter) WithShowLineNumber(b ...bool) *PrefixPrinter {
p.ShowLineNumber = internal.WithBoolean(b)
return &p
}
// WithDebugger returns a new Printer with specific Debugger value.
// If Debugger is true, the printer will only print if PrintDebugMessages is set to true.
// You can change PrintDebugMessages with EnableDebugMessages and DisableDebugMessages, or by setting the variable itself.
func (p PrefixPrinter) WithDebugger(b ...bool) *PrefixPrinter {
p.Debugger = internal.WithBoolean(b)
return &p
}
// WithLineNumberOffset can be used to exclude a specific amount of calls in the call stack.
// If you make a wrapper function for example, you can set this to one.
// The printed line number will then be the line number where your wrapper function is called.
func (p PrefixPrinter) WithLineNumberOffset(offset int) *PrefixPrinter {
p.LineNumberOffset = offset
return &p
}
// Sprint formats using the default formats for its operands and returns the resulting string.
// Spaces are added between operands when neither is a string.
func (p *PrefixPrinter) Sprint(a ...interface{}) string {
m := Sprint(a...)
if p.Debugger && !PrintDebugMessages {
return ""
}
if RawOutput {
if p.Prefix.Text != "" {
return Sprintf("%s: %s", strings.TrimSpace(p.Prefix.Text), Sprint(a...))
} else {
return Sprint(a...)
}
}
if p.Prefix.Style == nil {
p.Prefix.Style = NewStyle()
}
if p.Scope.Style == nil {
p.Scope.Style = NewStyle()
}
if p.MessageStyle == nil {
p.MessageStyle = NewStyle()
}
var ret string
var newLine bool
if strings.HasSuffix(m, "\n") {
m = strings.TrimRight(m, "\n")
newLine = true
}
messageLines := strings.Split(m, "\n")
for i, m := range messageLines {
if i == 0 {
ret += p.GetFormattedPrefix() + " "
if p.Scope.Text != "" {
ret += NewStyle(*p.Scope.Style...).Sprint(" (" + p.Scope.Text + ") ")
}
ret += p.MessageStyle.Sprint(m)
} else {
ret += "\n" + p.Prefix.Style.Sprint(strings.Repeat(" ", len(p.Prefix.Text)+2)) + " " + p.MessageStyle.Sprint(m)
}
}
_, fileName, line, _ := runtime.Caller(3 + p.LineNumberOffset)
if p.ShowLineNumber {
ret += FgGray.Sprint("\n└ " + fmt.Sprintf("(%s:%d)\n", fileName, line))
newLine = false
}
if newLine {
ret += "\n"
}
return Sprint(ret)
}
// Sprintln formats using the default formats for its operands and returns the resulting string.
// Spaces are always added between operands and a newline is appended.
func (p PrefixPrinter) Sprintln(a ...interface{}) string {
if p.Debugger && !PrintDebugMessages {
return ""
}
str := fmt.Sprintln(a...)
return p.Sprint(str)
}
// Sprintf formats according to a format specifier and returns the resulting string.
func (p PrefixPrinter) Sprintf(format string, a ...interface{}) string {
if p.Debugger && !PrintDebugMessages {
return ""
}
return p.Sprint(Sprintf(format, a...))
}
// Sprintfln formats according to a format specifier and returns the resulting string.
// Spaces are always added between operands and a newline is appended.
func (p PrefixPrinter) Sprintfln(format string, a ...interface{}) string {
if p.Debugger && !PrintDebugMessages {
return ""
}
return p.Sprintf(format, a...) + "\n"
}
// Print formats using the default formats for its operands and writes to standard output.
// Spaces are added between operands when neither is a string.
// It returns the number of bytes written and any write error encountered.
func (p *PrefixPrinter) Print(a ...interface{}) *TextPrinter {
tp := TextPrinter(p)
if p.Debugger && !PrintDebugMessages {
return &tp
}
Print(p.Sprint(a...))
checkFatal(p)
return &tp
}
// Println formats using the default formats for its operands and writes to standard output.
// Spaces are always added between operands and a newline is appended.
// It returns the number of bytes written and any write error encountered.
func (p *PrefixPrinter) Println(a ...interface{}) *TextPrinter {
tp := TextPrinter(p)
if p.Debugger && !PrintDebugMessages {
return &tp
}
Print(p.Sprintln(a...))
checkFatal(p)
return &tp
}
// Printf formats according to a format specifier and writes to standard output.
// It returns the number of bytes written and any write error encountered.
func (p *PrefixPrinter) Printf(format string, a ...interface{}) *TextPrinter {
tp := TextPrinter(p)
if p.Debugger && !PrintDebugMessages {
return &tp
}
Print(p.Sprintf(format, a...))
checkFatal(p)
return &tp
}
// Printfln formats according to a format specifier and writes to standard output.
// Spaces are always added between operands and a newline is appended.
// It returns the number of bytes written and any write error encountered.
func (p *PrefixPrinter) Printfln(format string, a ...interface{}) *TextPrinter {
tp := TextPrinter(p)
if p.Debugger && !PrintDebugMessages {
return &tp
}
Print(p.Sprintfln(format, a...))
checkFatal(p)
return &tp
}
// PrintOnError prints every error which is not nil.
// If every error is nil, nothing will be printed.
// This can be used for simple error checking.
//
// Note: Use WithFatal(true) or Fatal to panic after first non nil error.
func (p *PrefixPrinter) PrintOnError(a ...interface{}) *TextPrinter {
for _, arg := range a {
if err, ok := arg.(error); ok {
if err != nil {
p.Println(err)
}
}
}
tp := TextPrinter(p)
return &tp
}
// PrintOnErrorf wraps every error which is not nil and prints it.
// If every error is nil, nothing will be printed.
// This can be used for simple error checking.
func (p *PrefixPrinter) PrintOnErrorf(format string, a ...interface{}) *TextPrinter {
for _, arg := range a {
if err, ok := arg.(error); ok {
if err != nil {
p.Println(fmt.Errorf(format, err))
}
}
}
tp := TextPrinter(p)
return &tp
}
// GetFormattedPrefix returns the Prefix as a styled text string.
func (p PrefixPrinter) GetFormattedPrefix() string {
return p.Prefix.Style.Sprint(" " + p.Prefix.Text + " ")
}
// Prefix contains the data used as the beginning of a printed text via a PrefixPrinter.
type Prefix struct {
Text string
Style *Style
}
// Scope contains the data of the optional scope of a prefix.
// If it has a text, it will be printed after the Prefix in brackets.
type Scope struct {
Text string
Style *Style
}
func checkFatal(p *PrefixPrinter) {
if p.Fatal {
panic("")
}
}