Initial QSfera import
This commit is contained in:
+221
@@ -0,0 +1,221 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user