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  }