229 lines
6.7 KiB
Go
229 lines
6.7 KiB
Go
package pterm
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/mattn/go-runewidth"
|
|
|
|
"github.com/pterm/pterm/internal"
|
|
)
|
|
|
|
var (
|
|
// DefaultHeader returns the printer for a default header text.
|
|
// Defaults to LightWhite, Bold Text and a Gray DefaultHeader background.
|
|
DefaultHeader = HeaderPrinter{
|
|
TextStyle: &ThemeDefault.HeaderTextStyle,
|
|
BackgroundStyle: &ThemeDefault.HeaderBackgroundStyle,
|
|
Margin: 5,
|
|
}
|
|
)
|
|
|
|
// HeaderPrinter contains the data used to craft a header.
|
|
// A header is printed as a big box with text in it.
|
|
// Can be used as title screens or section separator.
|
|
type HeaderPrinter struct {
|
|
TextStyle *Style
|
|
BackgroundStyle *Style
|
|
Margin int
|
|
FullWidth bool
|
|
}
|
|
|
|
// WithTextStyle returns a new HeaderPrinter with changed
|
|
func (p HeaderPrinter) WithTextStyle(style *Style) *HeaderPrinter {
|
|
p.TextStyle = style
|
|
return &p
|
|
}
|
|
|
|
// WithBackgroundStyle changes the background styling of the header.
|
|
func (p HeaderPrinter) WithBackgroundStyle(style *Style) *HeaderPrinter {
|
|
p.BackgroundStyle = style
|
|
return &p
|
|
}
|
|
|
|
// WithMargin changes the background styling of the header.
|
|
func (p HeaderPrinter) WithMargin(margin int) *HeaderPrinter {
|
|
p.Margin = margin
|
|
return &p
|
|
}
|
|
|
|
// WithFullWidth enables full width on a HeaderPrinter.
|
|
func (p HeaderPrinter) WithFullWidth(b ...bool) *HeaderPrinter {
|
|
p.FullWidth = internal.WithBoolean(b)
|
|
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 HeaderPrinter) Sprint(a ...interface{}) string {
|
|
if RawOutput {
|
|
return Sprint(a...)
|
|
}
|
|
|
|
if p.TextStyle == nil {
|
|
p.TextStyle = NewStyle()
|
|
}
|
|
if p.BackgroundStyle == nil {
|
|
p.BackgroundStyle = NewStyle()
|
|
}
|
|
|
|
text := Sprint(a...)
|
|
|
|
var blankLine string
|
|
|
|
longestLine := internal.ReturnLongestLine(text, "\n")
|
|
longestLineLen := runewidth.StringWidth(RemoveColorFromString(longestLine)) + p.Margin*2
|
|
|
|
if p.FullWidth {
|
|
text = splitText(text, GetTerminalWidth()-p.Margin*2)
|
|
blankLine = strings.Repeat(" ", GetTerminalWidth())
|
|
} else {
|
|
if longestLineLen > GetTerminalWidth() {
|
|
text = splitText(text, GetTerminalWidth()-p.Margin*2)
|
|
blankLine = strings.Repeat(" ", GetTerminalWidth())
|
|
} else {
|
|
text = splitText(text, longestLineLen-p.Margin*2)
|
|
blankLine = strings.Repeat(" ", longestLineLen)
|
|
}
|
|
}
|
|
|
|
var marginString string
|
|
var ret string
|
|
|
|
if p.FullWidth {
|
|
longestLineLen = runewidth.StringWidth(RemoveColorFromString(internal.ReturnLongestLine(text, "\n")))
|
|
marginString = strings.Repeat(" ", (GetTerminalWidth()-longestLineLen)/2)
|
|
} else {
|
|
marginString = strings.Repeat(" ", p.Margin)
|
|
}
|
|
|
|
ret += p.BackgroundStyle.Sprint(blankLine) + "\n"
|
|
for _, line := range strings.Split(text, "\n") {
|
|
line = strings.ReplaceAll(line, "\n", "")
|
|
line = marginString + line + marginString
|
|
if runewidth.StringWidth(line) < runewidth.StringWidth(blankLine) {
|
|
line += strings.Repeat(" ", runewidth.StringWidth(blankLine)-runewidth.StringWidth(line))
|
|
}
|
|
ret += p.BackgroundStyle.Sprint(p.TextStyle.Sprint(line)) + "\n"
|
|
}
|
|
ret += p.BackgroundStyle.Sprint(blankLine) + "\n"
|
|
|
|
return ret
|
|
}
|
|
|
|
func splitText(text string, width int) string {
|
|
var lines []string
|
|
linesTmp := strings.Split(text, "\n")
|
|
for _, line := range linesTmp {
|
|
if runewidth.StringWidth(RemoveColorFromString(line)) > width {
|
|
extraLines := []string{""}
|
|
extraLinesCounter := 0
|
|
for i, letter := range line {
|
|
if i%width == 0 && i != 0 {
|
|
extraLinesCounter++
|
|
extraLines = append(extraLines, "")
|
|
}
|
|
extraLines[extraLinesCounter] += string(letter)
|
|
}
|
|
for _, extraLine := range extraLines {
|
|
extraLine += "\n"
|
|
lines = append(lines, extraLine)
|
|
}
|
|
} else {
|
|
line += "\n"
|
|
lines = append(lines, line)
|
|
}
|
|
}
|
|
|
|
var line string
|
|
for _, s := range lines {
|
|
line += s
|
|
}
|
|
|
|
return strings.TrimSuffix(line, "\n")
|
|
}
|
|
|
|
// 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 HeaderPrinter) Sprintln(a ...interface{}) string {
|
|
return p.Sprint(strings.TrimSuffix(Sprintln(a...), "\n"))
|
|
}
|
|
|
|
// Sprintf formats according to a format specifier and returns the resulting string.
|
|
func (p HeaderPrinter) Sprintf(format string, a ...interface{}) string {
|
|
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 HeaderPrinter) Sprintfln(format string, a ...interface{}) string {
|
|
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 *HeaderPrinter) Print(a ...interface{}) *TextPrinter {
|
|
Print(p.Sprint(a...))
|
|
tp := TextPrinter(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 *HeaderPrinter) Println(a ...interface{}) *TextPrinter {
|
|
Print(p.Sprintln(a...))
|
|
tp := TextPrinter(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 *HeaderPrinter) Printf(format string, a ...interface{}) *TextPrinter {
|
|
Print(p.Sprintf(format, a...))
|
|
tp := TextPrinter(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 *HeaderPrinter) Printfln(format string, a ...interface{}) *TextPrinter {
|
|
Print(p.Sprintfln(format, a...))
|
|
tp := TextPrinter(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.
|
|
func (p *HeaderPrinter) 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 *HeaderPrinter) 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
|
|
}
|