222 lines
5.6 KiB
Go
222 lines
5.6 KiB
Go
package strutil
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/gookit/goutil/comdef"
|
|
)
|
|
|
|
// PosFlag type
|
|
type PosFlag = comdef.Position
|
|
|
|
// Position for padding/resize string
|
|
const (
|
|
PosLeft PosFlag = iota
|
|
PosMiddle
|
|
PosRight
|
|
PosAuto
|
|
)
|
|
|
|
/*************************************************************
|
|
* String padding operation
|
|
*************************************************************/
|
|
|
|
// Padding Fill the string to the specified length.
|
|
//
|
|
// params:
|
|
// - s: 原始字符串
|
|
// - pad: 用于填充的字符或字符串
|
|
// - length: 目标长度
|
|
// - padPos: 填充位置标志(左填充或右填充)
|
|
func Padding(s, pad string, length int, padPos PosFlag) string {
|
|
return padding(s, pad, len(s), length, padPos)
|
|
}
|
|
|
|
// Utf8Padding Fill the string to the specified length. use utf8 width.
|
|
func Utf8Padding(s, pad string, wantLen int, padPos PosFlag) string {
|
|
return padding(s, pad, Utf8Width(s), wantLen, padPos)
|
|
}
|
|
|
|
func padding(s, pad string, sLen, wantLen int, padPos PosFlag) string {
|
|
diff := sLen - wantLen
|
|
if diff >= 0 { // do not need padding.
|
|
return s
|
|
}
|
|
|
|
// pad space.
|
|
if len(s) == sLen && (pad == "" || pad == " ") {
|
|
// Sprintf: 是按字数来填充的,不管中英文都是一个字符 - 有问题
|
|
if padPos == PosRight { // to right
|
|
return s + strings.Repeat(" ", -diff)
|
|
}
|
|
return strings.Repeat(" ", -diff) + s
|
|
}
|
|
|
|
// other character.
|
|
if padPos == PosRight { // to right
|
|
return s + Repeat(pad, -diff)
|
|
}
|
|
return Repeat(pad, -diff) + s
|
|
}
|
|
|
|
// PadLeft a string.
|
|
func PadLeft(s, pad string, length int) string {
|
|
return Padding(s, pad, length, PosLeft)
|
|
}
|
|
|
|
// PadRight a string.
|
|
func PadRight(s, pad string, length int) string {
|
|
return Padding(s, pad, length, PosRight)
|
|
}
|
|
|
|
// PadChars padding a rune/byte to want length and with position flag
|
|
func PadChars[T byte | rune](cs []T, pad T, length int, pos PosFlag) []T {
|
|
ln := len(cs)
|
|
if ln >= length {
|
|
ns := make([]T, length)
|
|
copy(ns, cs[:length])
|
|
return ns
|
|
}
|
|
|
|
idx := length - ln
|
|
ns := make([]T, length)
|
|
if pos == PosRight {
|
|
copy(ns, cs)
|
|
for i := ln; i < length; i++ {
|
|
ns[i] = pad
|
|
}
|
|
return ns
|
|
}
|
|
|
|
// to left
|
|
for i := 0; i < idx; i++ {
|
|
ns[i] = pad
|
|
}
|
|
copy(ns[idx:], cs)
|
|
return ns
|
|
}
|
|
|
|
// PadBytes padding a byte to want length and with position flag
|
|
func PadBytes(bs []byte, pad byte, length int, pos PosFlag) []byte {
|
|
return PadChars(bs, pad, length, pos)
|
|
}
|
|
|
|
// PadBytesLeft a byte to want length
|
|
func PadBytesLeft(bs []byte, pad byte, length int) []byte {
|
|
return PadChars(bs, pad, length, PosLeft)
|
|
}
|
|
|
|
// PadBytesRight a byte to want length
|
|
func PadBytesRight(bs []byte, pad byte, length int) []byte {
|
|
return PadChars(bs, pad, length, PosRight)
|
|
}
|
|
|
|
// PadRunes padding a rune to want length and with position flag
|
|
func PadRunes(rs []rune, pad rune, length int, pos PosFlag) []rune {
|
|
return PadChars(rs, pad, length, pos)
|
|
}
|
|
|
|
// PadRunesLeft a rune to want length
|
|
func PadRunesLeft(rs []rune, pad rune, length int) []rune {
|
|
return PadChars(rs, pad, length, PosLeft)
|
|
}
|
|
|
|
// PadRunesRight a rune to want length
|
|
func PadRunesRight(rs []rune, pad rune, length int) []rune {
|
|
return PadChars(rs, pad, length, PosRight)
|
|
}
|
|
|
|
// Align a string by given length and align settings. alias of Resize
|
|
func Align(s string, length int, align comdef.Align) string {
|
|
return resize(s, len(s), length, align, false)
|
|
}
|
|
|
|
// Utf8Align a string by given length and align settings. alias of Utf8Resize
|
|
func Utf8Align(s string, length int, align comdef.Align) string {
|
|
return resize(s, Utf8Width(s), length, align, false)
|
|
}
|
|
|
|
// Resize a string by given length and align settings. use padding space.
|
|
// If len(s) > wantLen, will truncate it.
|
|
func Resize(s string, length int, align comdef.Align) string {
|
|
return resize(s, len(s), length, align, true)
|
|
}
|
|
|
|
// Utf8Resize a string by given length and align settings. use padding space.
|
|
// If width(s) > wantLen, will truncate it.
|
|
func Utf8Resize(s string, length int, align comdef.Align) string {
|
|
return resize(s, Utf8Width(s), length, align, true)
|
|
}
|
|
|
|
// resize a string by given length and align settings. use padding space.
|
|
func resize(s string, sLen, wantLen int, align comdef.Align, cutOverflow bool) string {
|
|
diff := sLen - wantLen
|
|
if diff >= 0 { // do not need padding.
|
|
// cutOverflow: truncate on sLen > wantLen
|
|
if cutOverflow && sLen > wantLen {
|
|
if len(s) == sLen {
|
|
return s[:wantLen]
|
|
}
|
|
return utf8Truncate(s, sLen, wantLen, "")
|
|
}
|
|
return s
|
|
}
|
|
|
|
if align == comdef.Center {
|
|
padLn := (wantLen - sLen) / 2
|
|
if diff = wantLen - padLn*2; diff > 0 {
|
|
s += " "
|
|
}
|
|
padStr := string(RepeatBytes(' ', padLn))
|
|
return padStr + s + padStr
|
|
}
|
|
|
|
padStr := string(RepeatBytes(' ', wantLen-sLen))
|
|
// tip: 左对齐 - 使用空白填充右边
|
|
if align == comdef.Left || align == comdef.PosAuto {
|
|
return s + padStr
|
|
}
|
|
return padStr + s
|
|
}
|
|
|
|
/*************************************************************
|
|
* String repeat operation
|
|
*************************************************************/
|
|
|
|
// Repeat a string by given times.
|
|
func Repeat(s string, times int) string {
|
|
if times < 1 {
|
|
return ""
|
|
}
|
|
if times == 1 {
|
|
return s
|
|
}
|
|
|
|
var sb strings.Builder
|
|
sb.Grow(len(s) * times)
|
|
|
|
for i := 0; i < times; i++ {
|
|
sb.WriteString(s)
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
// RepeatRune repeat a rune char.
|
|
func RepeatRune(char rune, times int) []rune { return RepeatChars(char, times) }
|
|
|
|
// RepeatBytes repeat a byte char.
|
|
func RepeatBytes(char byte, times int) []byte { return RepeatChars(char, times) }
|
|
|
|
// RepeatChars repeat a byte char.
|
|
func RepeatChars[T byte | rune](char T, times int) []T {
|
|
if times <= 0 {
|
|
return make([]T, 0)
|
|
}
|
|
|
|
chars := make([]T, times)
|
|
for i := 0; i < times; i++ {
|
|
chars[i] = char
|
|
}
|
|
return chars
|
|
}
|