diff --git a/src/pkg/tplx/common.go b/src/pkg/tplx/common.go new file mode 100644 index 00000000..bf81e9c5 --- /dev/null +++ b/src/pkg/tplx/common.go @@ -0,0 +1,157 @@ +package tplx + +import ( + "fmt" + "html/template" + "math" + "regexp" + "strconv" + "time" +) + +func Unescaped(str string) interface{} { + return template.HTML(str) +} + +func Urlconvert(str string) interface{} { + return template.URL(str) +} + +func Timeformat(ts int64, pattern ...string) string { + defp := "2006-01-02 15:04:05" + if len(pattern) > 0 { + defp = pattern[0] + } + return time.Unix(ts, 0).Format(defp) +} + +func Timestamp(pattern ...string) string { + defp := "2006-01-02 15:04:05" + if len(pattern) > 0 { + defp = pattern[0] + } + return time.Now().Format(defp) +} + +func Args(args ...interface{}) map[string]interface{} { + result := make(map[string]interface{}) + for i, a := range args { + result[fmt.Sprintf("arg%d", i)] = a + } + return result +} + +func ReReplaceAll(pattern, repl, text string) string { + re := regexp.MustCompile(pattern) + return re.ReplaceAllString(text, repl) +} + +func Humanize(s string) string { + v, err := strconv.ParseFloat(s, 64) + if err != nil { + return s + } + if v == 0 || math.IsNaN(v) || math.IsInf(v, 0) { + return fmt.Sprintf("%.2f", v) + } + if math.Abs(v) >= 1 { + prefix := "" + for _, p := range []string{"k", "M", "G", "T", "P", "E", "Z", "Y"} { + if math.Abs(v) < 1000 { + break + } + prefix = p + v /= 1000 + } + return fmt.Sprintf("%.2f%s", v, prefix) + } + prefix := "" + for _, p := range []string{"m", "u", "n", "p", "f", "a", "z", "y"} { + if math.Abs(v) >= 1 { + break + } + prefix = p + v *= 1000 + } + return fmt.Sprintf("%.2f%s", v, prefix) +} + +func Humanize1024(s string) string { + v, err := strconv.ParseFloat(s, 64) + if err != nil { + return s + } + if math.Abs(v) <= 1 || math.IsNaN(v) || math.IsInf(v, 0) { + return fmt.Sprintf("%.4g", v) + } + prefix := "" + for _, p := range []string{"ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"} { + if math.Abs(v) < 1024 { + break + } + prefix = p + v /= 1024 + } + return fmt.Sprintf("%.4g%s", v, prefix) +} + +func HumanizeDuration(s string) string { + v, err := strconv.ParseFloat(s, 64) + if err != nil { + return s + } + if math.IsNaN(v) || math.IsInf(v, 0) { + return fmt.Sprintf("%.4g", v) + } + if v == 0 { + return fmt.Sprintf("%.4gs", v) + } + if math.Abs(v) >= 1 { + sign := "" + if v < 0 { + sign = "-" + v = -v + } + seconds := int64(v) % 60 + minutes := (int64(v) / 60) % 60 + hours := (int64(v) / 60 / 60) % 24 + days := int64(v) / 60 / 60 / 24 + // For days to minutes, we display seconds as an integer. + if days != 0 { + return fmt.Sprintf("%s%dd %dh %dm %ds", sign, days, hours, minutes, seconds) + } + if hours != 0 { + return fmt.Sprintf("%s%dh %dm %ds", sign, hours, minutes, seconds) + } + if minutes != 0 { + return fmt.Sprintf("%s%dm %ds", sign, minutes, seconds) + } + // For seconds, we display 4 significant digits. + return fmt.Sprintf("%s%.4gs", sign, v) + } + prefix := "" + for _, p := range []string{"m", "u", "n", "p", "f", "a", "z", "y"} { + if math.Abs(v) >= 1 { + break + } + prefix = p + v *= 1000 + } + return fmt.Sprintf("%.4g%ss", v, prefix) +} + +func HumanizePercentage(s string) string { + v, err := strconv.ParseFloat(s, 64) + if err != nil { + return s + } + return fmt.Sprintf("%.2f%%", v*100) +} + +func HumanizePercentageH(s string) string { + v, err := strconv.ParseFloat(s, 64) + if err != nil { + return s + } + return fmt.Sprintf("%.2f%%", v) +} diff --git a/src/pkg/tplx/tplx.go b/src/pkg/tplx/tplx.go index 5f6a225c..f1178884 100644 --- a/src/pkg/tplx/tplx.go +++ b/src/pkg/tplx/tplx.go @@ -2,24 +2,23 @@ package tplx import ( "html/template" - "time" + "regexp" + "strings" ) var TemplateFuncMap = template.FuncMap{ - "unescaped": func(str string) interface{} { return template.HTML(str) }, - "urlconvert": func(str string) interface{} { return template.URL(str) }, - "timeformat": func(ts int64, pattern ...string) string { - defp := "2006-01-02 15:04:05" - if len(pattern) > 0 { - defp = pattern[0] - } - return time.Unix(ts, 0).Format(defp) - }, - "timestamp": func(pattern ...string) string { - defp := "2006-01-02 15:04:05" - if len(pattern) > 0 { - defp = pattern[0] - } - return time.Now().Format(defp) - }, + "unescaped": Unescaped, + "urlconvert": Urlconvert, + "timeformat": Timeformat, + "timestamp": Timestamp, + "args": Args, + "reReplaceAll": ReReplaceAll, + "match": regexp.MatchString, + "toUpper": strings.ToUpper, + "toLower": strings.ToLower, + "humanize": Humanize, + "humanize1024": Humanize1024, + "humanizeDuration": HumanizeDuration, + "humanizePercentage": HumanizePercentage, + "humanizePercentageH": HumanizePercentageH, }