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) 46mainloop: 47 for i, r := range s { 48 for _, seq := range seqs { 49 if i >= seq[0] && i < seq[1] { 50 buf.WriteRune(r) 51 continue mainloop 52 } 53 } 54 if rw := CellCount(string(r)); rw <= w { 55 w -= rw 56 buf.WriteRune(r) 57 } else { 58 break 59 } 60 } 61 for w > 0 { 62 buf.WriteByte(' ') 63 w-- 64 } 65 return 66} 67 68func round(val float64) (newVal float64) { 69 roundOn := 0.5 70 places := 0 71 var round float64 72 pow := math.Pow(10, float64(places)) 73 digit := pow * val 74 _, div := math.Modf(digit) 75 if div >= roundOn { 76 round = math.Ceil(digit) 77 } else { 78 round = math.Floor(digit) 79 } 80 newVal = round / pow 81 return 82} 83 84// Convert bytes to human readable string. Like a 2 MiB, 64.2 KiB, or 2 MB, 64.2 kB 85// if useSIPrefix is set to true 86func formatBytes(i int64, useSIPrefix bool) (result string) { 87 if !useSIPrefix { 88 switch { 89 case i >= _TiB: 90 result = fmt.Sprintf("%.02f TiB", float64(i)/_TiB) 91 case i >= _GiB: 92 result = fmt.Sprintf("%.02f GiB", float64(i)/_GiB) 93 case i >= _MiB: 94 result = fmt.Sprintf("%.02f MiB", float64(i)/_MiB) 95 case i >= _KiB: 96 result = fmt.Sprintf("%.02f KiB", float64(i)/_KiB) 97 default: 98 result = fmt.Sprintf("%d B", i) 99 } 100 } else { 101 switch { 102 case i >= _TB: 103 result = fmt.Sprintf("%.02f TB", float64(i)/_TB) 104 case i >= _GB: 105 result = fmt.Sprintf("%.02f GB", float64(i)/_GB) 106 case i >= _MB: 107 result = fmt.Sprintf("%.02f MB", float64(i)/_MB) 108 case i >= _kB: 109 result = fmt.Sprintf("%.02f kB", float64(i)/_kB) 110 default: 111 result = fmt.Sprintf("%d B", i) 112 } 113 } 114 return 115} 116