mirror of
https://github.com/crazy-max/diun.git
synced 2024-12-22 19:38:28 +00:00
6f7b5b313d
Bumps [github.com/jedib0t/go-pretty/v6](https://github.com/jedib0t/go-pretty) from 6.5.9 to 6.6.5. - [Release notes](https://github.com/jedib0t/go-pretty/releases) - [Commits](https://github.com/jedib0t/go-pretty/compare/v6.5.9...v6.6.5) --- updated-dependencies: - dependency-name: github.com/jedib0t/go-pretty/v6 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
150 lines
4.2 KiB
Go
150 lines
4.2 KiB
Go
package text
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// Align denotes how text is to be aligned horizontally.
|
|
type Align int
|
|
|
|
// Align enumerations
|
|
const (
|
|
AlignDefault Align = iota // same as AlignLeft
|
|
AlignLeft // "left "
|
|
AlignCenter // " center "
|
|
AlignJustify // "justify it"
|
|
AlignRight // " right"
|
|
AlignAuto // AlignRight for numbers, AlignLeft for the rest
|
|
)
|
|
|
|
// Apply aligns the text as directed. For ex.:
|
|
// - AlignDefault.Apply("Jon Snow", 12) returns "Jon Snow "
|
|
// - AlignLeft.Apply("Jon Snow", 12) returns "Jon Snow "
|
|
// - AlignCenter.Apply("Jon Snow", 12) returns " Jon Snow "
|
|
// - AlignJustify.Apply("Jon Snow", 12) returns "Jon Snow"
|
|
// - AlignRight.Apply("Jon Snow", 12) returns " Jon Snow"
|
|
// - AlignAuto.Apply("Jon Snow", 12) returns "Jon Snow "
|
|
func (a Align) Apply(text string, maxLength int) string {
|
|
aComputed := a
|
|
if aComputed == AlignAuto {
|
|
_, err := strconv.ParseFloat(text, 64)
|
|
if err == nil { // was able to parse a number out of the string
|
|
aComputed = AlignRight
|
|
} else {
|
|
aComputed = AlignLeft
|
|
}
|
|
}
|
|
|
|
text = aComputed.trimString(text)
|
|
sLen := utf8.RuneCountInString(text)
|
|
sLenWoE := StringWidthWithoutEscSequences(text)
|
|
numEscChars := sLen - sLenWoE
|
|
|
|
// now, align the text
|
|
switch aComputed {
|
|
case AlignDefault, AlignLeft:
|
|
return fmt.Sprintf("%-"+strconv.Itoa(maxLength+numEscChars)+"s", text)
|
|
case AlignCenter:
|
|
if sLenWoE < maxLength {
|
|
// left pad with half the number of spaces needed before using %text
|
|
return fmt.Sprintf("%"+strconv.Itoa(maxLength+numEscChars)+"s",
|
|
text+strings.Repeat(" ", (maxLength-sLenWoE)/2))
|
|
}
|
|
case AlignJustify:
|
|
return justifyText(text, sLenWoE, maxLength)
|
|
}
|
|
return fmt.Sprintf("%"+strconv.Itoa(maxLength+numEscChars)+"s", text)
|
|
}
|
|
|
|
// HTMLProperty returns the equivalent HTML horizontal-align tag property.
|
|
func (a Align) HTMLProperty() string {
|
|
switch a {
|
|
case AlignLeft:
|
|
return "align=\"left\""
|
|
case AlignCenter:
|
|
return "align=\"center\""
|
|
case AlignJustify:
|
|
return "align=\"justify\""
|
|
case AlignRight:
|
|
return "align=\"right\""
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
// MarkdownProperty returns the equivalent Markdown horizontal-align separator.
|
|
func (a Align) MarkdownProperty() string {
|
|
switch a {
|
|
case AlignLeft:
|
|
return ":--- "
|
|
case AlignCenter:
|
|
return ":---:"
|
|
case AlignRight:
|
|
return " ---:"
|
|
default:
|
|
return " --- "
|
|
}
|
|
}
|
|
|
|
func (a Align) trimString(text string) string {
|
|
switch a {
|
|
case AlignDefault, AlignLeft:
|
|
if strings.HasSuffix(text, " ") {
|
|
return strings.TrimRight(text, " ")
|
|
}
|
|
case AlignRight:
|
|
if strings.HasPrefix(text, " ") {
|
|
return strings.TrimLeft(text, " ")
|
|
}
|
|
default:
|
|
if strings.HasPrefix(text, " ") || strings.HasSuffix(text, " ") {
|
|
return strings.Trim(text, " ")
|
|
}
|
|
}
|
|
return text
|
|
}
|
|
|
|
func justifyText(text string, textLength int, maxLength int) string {
|
|
// split the text into individual words
|
|
words := Filter(strings.Split(text, " "), func(item string) bool {
|
|
return item != ""
|
|
})
|
|
// empty string implies result is just spaces for maxLength
|
|
if len(words) == 0 {
|
|
return strings.Repeat(" ", maxLength)
|
|
}
|
|
|
|
// get the number of spaces to insert into the text
|
|
numSpacesNeeded := maxLength - textLength + strings.Count(text, " ")
|
|
numSpacesNeededBetweenWords := 0
|
|
if len(words) > 1 {
|
|
numSpacesNeededBetweenWords = numSpacesNeeded / (len(words) - 1)
|
|
}
|
|
// create the output string word by word with spaces in between
|
|
var outText strings.Builder
|
|
outText.Grow(maxLength)
|
|
for idx, word := range words {
|
|
if idx > 0 {
|
|
// insert spaces only after the first word
|
|
if idx == len(words)-1 {
|
|
// insert all the remaining space before the last word
|
|
outText.WriteString(strings.Repeat(" ", numSpacesNeeded))
|
|
numSpacesNeeded = 0
|
|
} else {
|
|
// insert the determined number of spaces between each word
|
|
outText.WriteString(strings.Repeat(" ", numSpacesNeededBetweenWords))
|
|
// and reduce the number of spaces needed after this
|
|
numSpacesNeeded -= numSpacesNeededBetweenWords
|
|
}
|
|
}
|
|
outText.WriteString(word)
|
|
if idx == len(words)-1 && numSpacesNeeded > 0 {
|
|
outText.WriteString(strings.Repeat(" ", numSpacesNeeded))
|
|
}
|
|
}
|
|
return outText.String()
|
|
}
|