github.com/thajeztah/cli@v0.0.0-20240223162942-dc6bfac81a8b/templates/templates.go (about) 1 // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: 2 //go:build go1.19 3 4 package templates 5 6 import ( 7 "bytes" 8 "encoding/json" 9 "strings" 10 "text/template" 11 ) 12 13 // basicFunctions are the set of initial 14 // functions provided to every template. 15 var basicFunctions = template.FuncMap{ 16 "json": func(v any) string { 17 buf := &bytes.Buffer{} 18 enc := json.NewEncoder(buf) 19 enc.SetEscapeHTML(false) 20 err := enc.Encode(v) 21 if err != nil { 22 panic(err) 23 } 24 25 // Remove the trailing new line added by the encoder 26 return strings.TrimSpace(buf.String()) 27 }, 28 "split": strings.Split, 29 "join": strings.Join, 30 "title": strings.Title, //nolint:nolintlint,staticcheck // strings.Title is deprecated, but we only use it for ASCII, so replacing with golang.org/x/text is out of scope 31 "lower": strings.ToLower, 32 "upper": strings.ToUpper, 33 "pad": padWithSpace, 34 "truncate": truncateWithLength, 35 } 36 37 // HeaderFunctions are used to created headers of a table. 38 // This is a replacement of basicFunctions for header generation 39 // because we want the header to remain intact. 40 // Some functions like `pad` are not overridden (to preserve alignment 41 // with the columns). 42 var HeaderFunctions = template.FuncMap{ 43 "json": func(v string) string { 44 return v 45 }, 46 "split": func(v string, _ string) string { 47 // we want the table header to show the name of the column, and not 48 // split the table header itself. Using a different signature 49 // here, and return a string instead of []string 50 return v 51 }, 52 "join": func(v string, _ string) string { 53 // table headers are always a string, so use a different signature 54 // for the "join" function (string instead of []string) 55 return v 56 }, 57 "title": func(v string) string { 58 return v 59 }, 60 "lower": func(v string) string { 61 return v 62 }, 63 "upper": func(v string) string { 64 return v 65 }, 66 "truncate": func(v string, _ int) string { 67 return v 68 }, 69 } 70 71 // Parse creates a new anonymous template with the basic functions 72 // and parses the given format. 73 func Parse(format string) (*template.Template, error) { 74 return NewParse("", format) 75 } 76 77 // New creates a new empty template with the provided tag and built-in 78 // template functions. 79 func New(tag string) *template.Template { 80 return template.New(tag).Funcs(basicFunctions) 81 } 82 83 // NewParse creates a new tagged template with the basic functions 84 // and parses the given format. 85 func NewParse(tag, format string) (*template.Template, error) { 86 return New(tag).Parse(format) 87 } 88 89 // padWithSpace adds whitespace to the input if the input is non-empty 90 func padWithSpace(source string, prefix, suffix int) string { 91 if source == "" { 92 return source 93 } 94 return strings.Repeat(" ", prefix) + source + strings.Repeat(" ", suffix) 95 } 96 97 // truncateWithLength truncates the source string up to the length provided by the input 98 func truncateWithLength(source string, length int) string { 99 if len(source) < length { 100 return source 101 } 102 return source[:length] 103 }