1package pb 2 3import ( 4 "bytes" 5 "fmt" 6 "github.com/mattn/go-runewidth" 7 "math" 8 "regexp" 9 //"unicode/utf8" 10) 11 12const ( 13 _KiB = 1024 14 _MiB = 1048576 15 _GiB = 1073741824 16 _TiB = 1099511627776 17 18 _kB = 1e3 19 _MB = 1e6 20 _GB = 1e9 21 _TB = 1e12 22) 23 24var ctrlFinder = regexp.MustCompile("\x1b\x5b[0-9;]+\x6d") 25 26func CellCount(s string) int { 27 n := runewidth.StringWidth(s) 28 for _, sm := range ctrlFinder.FindAllString(s, -1) { 29 n -= runewidth.StringWidth(sm) 30 } 31 return n 32} 33 34func StripString(s string, w int) string { 35 l := CellCount(s) 36 if l <= w { 37 return s 38 } 39 var buf = bytes.NewBuffer(make([]byte, 0, len(s))) 40 StripStringToBuffer(s, w, buf) 41 return buf.String() 42} 43 44func StripStringToBuffer(s string, w int, buf *bytes.Buffer) { 45 var seqs = ctrlFinder.FindAllStringIndex(s, -1) 46 var maxWidthReached bool 47mainloop: 48 for i, r := range s { 49 for _, seq := range seqs { 50 if i >= seq[0] && i < seq[1] { 51 buf.WriteRune(r) 52 continue mainloop 53 } 54 } 55 if rw := CellCount(string(r)); rw <= w && !maxWidthReached { 56 w -= rw 57 buf.WriteRune(r) 58 } else { 59 maxWidthReached = true 60 } 61 } 62 for w > 0 { 63 buf.WriteByte(' ') 64 w-- 65 } 66 return 67} 68 69func round(val float64) (newVal float64) { 70 roundOn := 0.5 71 places := 0 72 var round float64 73 pow := math.Pow(10, float64(places)) 74 digit := pow * val 75 _, div := math.Modf(digit) 76 if div >= roundOn { 77 round = math.Ceil(digit) 78 } else { 79 round = math.Floor(digit) 80 } 81 newVal = round / pow 82 return 83} 84 85// Convert bytes to human readable string. Like a 2 MiB, 64.2 KiB, or 2 MB, 64.2 kB 86// if useSIPrefix is set to true 87func formatBytes(i int64, useSIPrefix bool) (result string) { 88 if !useSIPrefix { 89 switch { 90 case i >= _TiB: 91 result = fmt.Sprintf("%.02f TiB", float64(i)/_TiB) 92 case i >= _GiB: 93 result = fmt.Sprintf("%.02f GiB", float64(i)/_GiB) 94 case i >= _MiB: 95 result = fmt.Sprintf("%.02f MiB", float64(i)/_MiB) 96 case i >= _KiB: 97 result = fmt.Sprintf("%.02f KiB", float64(i)/_KiB) 98 default: 99 result = fmt.Sprintf("%d B", i) 100 } 101 } else { 102 switch { 103 case i >= _TB: 104 result = fmt.Sprintf("%.02f TB", float64(i)/_TB) 105 case i >= _GB: 106 result = fmt.Sprintf("%.02f GB", float64(i)/_GB) 107 case i >= _MB: 108 result = fmt.Sprintf("%.02f MB", float64(i)/_MB) 109 case i >= _kB: 110 result = fmt.Sprintf("%.02f kB", float64(i)/_kB) 111 default: 112 result = fmt.Sprintf("%d B", i) 113 } 114 } 115 return 116} 117