refactor byte unit formatting, add unit-specific display precision

This commit is contained in:
Bradley Cicenas 2020-10-25 14:08:06 +00:00
parent c446fb0e11
commit 4d7d69d4cf
No known key found for this signature in database
GPG Key ID: AF579ED4B93CBB5C
6 changed files with 75 additions and 43 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}