1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
package progress
import (
"fmt"
)
// UnitsNotationPosition determines notation position relative to unit value.
type UnitsNotationPosition int
// Supported unit positions relative to tracker value;
// default: UnitsNotationPositionBefore
const (
UnitsNotationPositionBefore UnitsNotationPosition = iota
UnitsNotationPositionAfter
)
// UnitsFormatter defines a function that prints a value in a specific style.
type UnitsFormatter func(value int64) string
// Units defines the "type" of the value being tracked by the Tracker.
type Units struct {
Formatter UnitsFormatter // default: FormatNumber
Notation string
NotationPosition UnitsNotationPosition // default: UnitsNotationPositionBefore
}
// Sprint prints the value as defined by the Units.
func (tu Units) Sprint(value int64) string {
formatter := tu.Formatter
if formatter == nil {
formatter = FormatNumber
}
formattedValue := formatter(value)
switch tu.NotationPosition {
case UnitsNotationPositionAfter:
return formattedValue + tu.Notation
default: // UnitsNotationPositionBefore
return tu.Notation + formattedValue
}
}
var (
// UnitsDefault doesn't define any units. The value will be treated as any
// other number.
UnitsDefault = Units{
Notation: "",
NotationPosition: UnitsNotationPositionBefore,
Formatter: FormatNumber,
}
// UnitsBytes defines the value as a storage unit. Values will be converted
// and printed in one of these forms: B, KB, MB, GB, TB, PB
UnitsBytes = Units{
Notation: "",
NotationPosition: UnitsNotationPositionBefore,
Formatter: FormatBytes,
}
// UnitsCurrencyDollar defines the value as a Dollar amount. Values will be
// converted and printed in one of these forms: $x.yz, $x.yzK, $x.yzM,
// $x.yzB, $x.yzT
UnitsCurrencyDollar = Units{
Notation: "$",
NotationPosition: UnitsNotationPositionBefore,
Formatter: FormatNumber,
}
// UnitsCurrencyEuro defines the value as a Euro amount. Values will be
// converted and printed in one of these forms: ₠x.yz, ₠x.yzK, ₠x.yzM,
// ₠x.yzB, ₠x.yzT
UnitsCurrencyEuro = Units{
Notation: "₠",
NotationPosition: UnitsNotationPositionBefore,
Formatter: FormatNumber,
}
// UnitsCurrencyPound defines the value as a Pound amount. Values will be
// converted and printed in one of these forms: £x.yz, £x.yzK, £x.yzM,
// £x.yzB, £x.yzT
UnitsCurrencyPound = Units{
Notation: "£",
NotationPosition: UnitsNotationPositionBefore,
Formatter: FormatNumber,
}
)
// FormatBytes formats the given value as a "Byte".
func FormatBytes(value int64) string {
return formatNumber(value, map[int64]string{
1000000000000000: "PB",
1000000000000: "TB",
1000000000: "GB",
1000000: "MB",
1000: "KB",
0: "B",
})
}
// FormatNumber formats the given value as a "regular number".
func FormatNumber(value int64) string {
return formatNumber(value, map[int64]string{
1000000000000000: "Q",
1000000000000: "T",
1000000000: "B",
1000000: "M",
1000: "K",
0: "",
})
}
var unitScales = []int64{
1000000000000000,
1000000000000,
1000000000,
1000000,
1000,
}
func formatNumber(value int64, notations map[int64]string) string {
for _, unitScale := range unitScales {
if value >= unitScale {
return fmt.Sprintf("%.2f%s", float64(value)/float64(unitScale), notations[unitScale])
}
}
return fmt.Sprintf("%d%s", value, notations[0])
}
|