diff --git a/cwidgets/compact/gauge.go b/cwidgets/compact/gauge.go index 0862569..37d2352 100644 --- a/cwidgets/compact/gauge.go +++ b/cwidgets/compact/gauge.go @@ -37,8 +37,9 @@ func NewMemCol() CompactCol { } func (w *MemCol) SetMetrics(m models.Metrics) { + log.Warningf("MEM WIDTH: %d", w.Width) w.BarColor = ui.ThemeAttr("gauge.bar.bg") - w.Label = fmt.Sprintf("%s / %s", cwidgets.ByteFormat(m.MemUsage), cwidgets.ByteFormat(m.MemLimit)) + w.Label = fmt.Sprintf("%s / %s", cwidgets.ByteFormat64Short(m.MemUsage), cwidgets.ByteFormat64Short(m.MemLimit)) w.Percent = m.MemPercent } diff --git a/cwidgets/compact/text.go b/cwidgets/compact/text.go index 4b419a0..3a6aa44 100644 --- a/cwidgets/compact/text.go +++ b/cwidgets/compact/text.go @@ -49,7 +49,7 @@ func NewNetCol() CompactCol { } func (w *NetCol) SetMetrics(m models.Metrics) { - label := fmt.Sprintf("%s / %s", cwidgets.ByteFormat(m.NetRx), cwidgets.ByteFormat(m.NetTx)) + label := fmt.Sprintf("%s / %s", cwidgets.ByteFormat64Short(m.NetRx), cwidgets.ByteFormat64Short(m.NetTx)) w.Text = label } @@ -62,7 +62,7 @@ func NewIOCol() CompactCol { } func (w *IOCol) SetMetrics(m models.Metrics) { - label := fmt.Sprintf("%s / %s", cwidgets.ByteFormat(m.IOBytesRead), cwidgets.ByteFormat(m.IOBytesWrite)) + label := fmt.Sprintf("%s / %s", cwidgets.ByteFormat64Short(m.IOBytesRead), cwidgets.ByteFormat64Short(m.IOBytesWrite)) w.Text = label } diff --git a/cwidgets/single/io.go b/cwidgets/single/io.go index e5619b3..41fd1ba 100644 --- a/cwidgets/single/io.go +++ b/cwidgets/single/io.go @@ -42,10 +42,10 @@ func (w *IO) Update(read int64, write int64) { var rate string w.readHist.Append(int(read)) - rate = strings.ToLower(cwidgets.ByteFormatInt(w.readHist.Val)) + rate = strings.ToLower(cwidgets.ByteFormatShort(w.readHist.Val)) w.Lines[0].Title = fmt.Sprintf("read [%s/s]", rate) w.writeHist.Append(int(write)) - rate = strings.ToLower(cwidgets.ByteFormatInt(w.writeHist.Val)) + rate = strings.ToLower(cwidgets.ByteFormatShort(w.writeHist.Val)) w.Lines[1].Title = fmt.Sprintf("write [%s/s]", rate) } diff --git a/cwidgets/single/mem.go b/cwidgets/single/mem.go index f6ce2f3..f64e802 100644 --- a/cwidgets/single/mem.go +++ b/cwidgets/single/mem.go @@ -70,7 +70,7 @@ func newMemChart() *ui.MBarChart { mbar.BarColor[1] = ui.ColorBlack mbar.NumColor[1] = ui.ColorBlack - mbar.NumFmt = cwidgets.ByteFormatInt + mbar.NumFmt = cwidgets.ByteFormatShort //mbar.ShowScale = true return mbar } @@ -78,6 +78,6 @@ func newMemChart() *ui.MBarChart { func (w *Mem) Update(val int, limit int) { w.valHist.Append(val) w.limitHist.Append(limit - val) - w.InnerLabel.Text = fmt.Sprintf("%v / %v", cwidgets.ByteFormatInt(val), cwidgets.ByteFormatInt(limit)) + w.InnerLabel.Text = fmt.Sprintf("%v / %v", cwidgets.ByteFormatShort(val), cwidgets.ByteFormatShort(limit)) //w.Data[0] = w.hist.data } diff --git a/cwidgets/single/net.go b/cwidgets/single/net.go index a7ef596..3e05594 100644 --- a/cwidgets/single/net.go +++ b/cwidgets/single/net.go @@ -42,10 +42,10 @@ func (w *Net) Update(rx int64, tx int64) { var rate string w.rxHist.Append(int(rx)) - rate = strings.ToLower(cwidgets.ByteFormatInt(w.rxHist.Val)) + rate = strings.ToLower(cwidgets.ByteFormat(w.rxHist.Val)) w.Lines[0].Title = fmt.Sprintf("RX [%s/s]", rate) w.txHist.Append(int(tx)) - rate = strings.ToLower(cwidgets.ByteFormatInt(w.txHist.Val)) + rate = strings.ToLower(cwidgets.ByteFormat(w.txHist.Val)) w.Lines[1].Title = fmt.Sprintf("TX [%s/s]", rate) } diff --git a/cwidgets/util.go b/cwidgets/util.go index 4fa1243..edb1a92 100644 --- a/cwidgets/util.go +++ b/cwidgets/util.go @@ -1,53 +1,84 @@ package cwidgets import ( - "fmt" "strconv" ) const ( - kb = 1024 - mb = kb * 1024 - gb = mb * 1024 - tb = gb * 1024 + // byte ratio constants + _ = iota + kib float64 = 1 << (10 * iota) + mib + gib + tib + pib ) -// convenience method -func ByteFormatInt(n int) string { - return ByteFormat(int64(n)) +var ( + units = []float64{ + 1, + kib, + mib, + gib, + tib, + pib, + } + + // short, full unit labels + labels = [][2]string{ + [2]string{"B", "B"}, + [2]string{"K", "KiB"}, + [2]string{"M", "MiB"}, + [2]string{"G", "GiB"}, + [2]string{"T", "TiB"}, + [2]string{"P", "PiB"}, + } + + // maximum displayed precision per unit + maxPrecision = []int{ + 0, // B + 0, // kib + 1, // mib + 1, // gib + 2, // tib + 2, // pib + } +) + +// convenience methods +func ByteFormat(n int) string { return byteFormat(float64(n), false) } +func ByteFormatShort(n int) string { return byteFormat(float64(n), true) } +func ByteFormat64(n int64) string { return byteFormat(float64(n), false) } +func ByteFormat64Short(n int64) string { return byteFormat(float64(n), true) } + +func byteFormat(n float64, short bool) string { + i := len(units) - 1 + + for i > 0 { + if n >= units[i] { + n /= units[i] + break + } + i-- + } + + if short { + return unpadFloat(n, maxPrecision[i]) + labels[i][0] + } + return unpadFloat(n, maxPrecision[i]) + labels[i][1] } -func ByteFormat(n int64) string { - if n < kb { - return fmt.Sprintf("%sB", strconv.FormatInt(n, 10)) - } - if n < mb { - n = n / kb - return fmt.Sprintf("%sK", strconv.FormatInt(n, 10)) - } - if n < gb { - n = n / mb - return fmt.Sprintf("%sM", strconv.FormatInt(n, 10)) - } - if n < tb { - nf := float64(n) / gb - return fmt.Sprintf("%sG", unpadFloat(nf)) - } - nf := float64(n) / tb - return fmt.Sprintf("%sT", unpadFloat(nf)) +func unpadFloat(f float64, maxp int) string { + return strconv.FormatFloat(f, 'f', getPrecision(f, maxp), 64) } -func unpadFloat(f float64) string { - return strconv.FormatFloat(f, 'f', getPrecision(f), 64) -} - -func getPrecision(f float64) int { +func getPrecision(f float64, maxp int) int { frac := int((f - float64(int(f))) * 100) - if frac == 0 { + if frac == 0 || maxp == 0 { return 0 } - if frac%10 == 0 { + if frac%10 == 0 || maxp < 2 { return 1 } - return 2 // default precision + return maxp }