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
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) { func (w *MemCol) SetMetrics(m models.Metrics) {
log.Warningf("MEM WIDTH: %d", w.Width)
w.BarColor = ui.ThemeAttr("gauge.bar.bg") 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 w.Percent = m.MemPercent
} }

View File

@@ -49,7 +49,7 @@ func NewNetCol() CompactCol {
} }
func (w *NetCol) SetMetrics(m models.Metrics) { 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 w.Text = label
} }
@@ -62,7 +62,7 @@ func NewIOCol() CompactCol {
} }
func (w *IOCol) SetMetrics(m models.Metrics) { 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 w.Text = label
} }

View File

@@ -42,10 +42,10 @@ func (w *IO) Update(read int64, write int64) {
var rate string var rate string
w.readHist.Append(int(read)) 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.Lines[0].Title = fmt.Sprintf("read [%s/s]", rate)
w.writeHist.Append(int(write)) 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) 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.BarColor[1] = ui.ColorBlack
mbar.NumColor[1] = ui.ColorBlack mbar.NumColor[1] = ui.ColorBlack
mbar.NumFmt = cwidgets.ByteFormatInt mbar.NumFmt = cwidgets.ByteFormatShort
//mbar.ShowScale = true //mbar.ShowScale = true
return mbar return mbar
} }
@@ -78,6 +78,6 @@ func newMemChart() *ui.MBarChart {
func (w *Mem) Update(val int, limit int) { func (w *Mem) Update(val int, limit int) {
w.valHist.Append(val) w.valHist.Append(val)
w.limitHist.Append(limit - 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 //w.Data[0] = w.hist.data
} }

View File

@@ -42,10 +42,10 @@ func (w *Net) Update(rx int64, tx int64) {
var rate string var rate string
w.rxHist.Append(int(rx)) 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.Lines[0].Title = fmt.Sprintf("RX [%s/s]", rate)
w.txHist.Append(int(tx)) 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) w.Lines[1].Title = fmt.Sprintf("TX [%s/s]", rate)
} }

View File

@@ -1,53 +1,84 @@
package cwidgets package cwidgets
import ( import (
"fmt"
"strconv" "strconv"
) )
const ( const (
kb = 1024 // byte ratio constants
mb = kb * 1024 _ = iota
gb = mb * 1024 kib float64 = 1 << (10 * iota)
tb = gb * 1024 mib
gib
tib
pib
) )
// convenience method var (
func ByteFormatInt(n int) string { units = []float64{
return ByteFormat(int64(n)) 1,
kib,
mib,
gib,
tib,
pib,
} }
func ByteFormat(n int64) string { // short, full unit labels
if n < kb { labels = [][2]string{
return fmt.Sprintf("%sB", strconv.FormatInt(n, 10)) [2]string{"B", "B"},
} [2]string{"K", "KiB"},
if n < mb { [2]string{"M", "MiB"},
n = n / kb [2]string{"G", "GiB"},
return fmt.Sprintf("%sK", strconv.FormatInt(n, 10)) [2]string{"T", "TiB"},
} [2]string{"P", "PiB"},
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) string { // maximum displayed precision per unit
return strconv.FormatFloat(f, 'f', getPrecision(f), 64) 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--
} }
func getPrecision(f float64) int { if short {
return unpadFloat(n, maxPrecision[i]) + labels[i][0]
}
return unpadFloat(n, maxPrecision[i]) + labels[i][1]
}
func unpadFloat(f float64, maxp int) string {
return strconv.FormatFloat(f, 'f', getPrecision(f, maxp), 64)
}
func getPrecision(f float64, maxp int) int {
frac := int((f - float64(int(f))) * 100) frac := int((f - float64(int(f))) * 100)
if frac == 0 { if frac == 0 || maxp == 0 {
return 0 return 0
} }
if frac%10 == 0 { if frac%10 == 0 || maxp < 2 {
return 1 return 1
} }
return 2 // default precision return maxp
} }