1. What is SprigX?
SprigX are extensions to the sprig library (Go docs).
They provide functions that offer more enriched use cases and domain-specific data.
|
Tip
|
If you are reading this README on the Go Module Directory documentation (https://pkg.go.dev/r00t2.io/goutils/tplx/sprigx) or the directory landing page (https://git.r00t2.io/r00t2/go_goutils/src/branch/master/tplx/sprigx), it may not render correctly. Be sure to view it at properly via the AsciiDoc rendering or by downloading and viewing the HTML version. |
2. How do I Use SprigX?
The same way you would sprig!
Like this.
package main
import (
htmlTplLib "html/template"
txtTplLib "text/template"
"r00t2.io/goutils/tplx/sprigx"
)
var (
txtTpl *txtTplLib.Template = txtTplLib.
New("").
Funcs(
sprigx.TxtFuncMap(),
)
htmlTpl *htmlTplLib.Template = htmlTplLib.
New("").
Funcs(
sprigx.HtmlFuncMap(),
)
)
They can even be combined/used together.
Like this.
package main
import (
"text/template"
"github.com/Masterminds/sprig/v3"
"r00t2.io/goutils/tplx/sprigx"
)
var txtTpl *template.Template = template.
New("").
Funcs(
sprigx.TxtFuncMap(),
).
Funcs(
sprig.TxtFuncMap(),
)
// Or:
/*
var txtTpl *template.Template = template.
New("").
Funcs(
sprig.TxtFuncMap(),
).
Funcs(
sprigx.TxtFuncMap(),
)
*/
If a <template>.FuncMap is added via .Funcs() after template parsing, it will override any functions of the same name of a <template>.FuncMap before parsing.
For example, if both sprig and sprigx provide a function foo:
this will use foo from sprigx
(show)
package main
import (
"text/template"
"github.com/Masterminds/sprig/v3"
"r00t2.io/goutils/tplx/sprigx"
)
const (
myTpl string = `{{ "This is an example template string." | foo }}`
)
var (
tpl *template.Template = template.Must(
template.
New("").
Funcs(sprig.TxtFuncMap()).
Parse(myTpl),
).
Funcs(sprigx.TxtFuncMap())
)
whereas this will use foo from sprig
(show)
package main
import (
"text/template"
"github.com/Masterminds/sprig/v3"
"r00t2.io/goutils/tplx/sprigx"
)
const (
myTpl string = `{{ "This is an example template string." | foo }}`
)
var (
tpl *template.Template = template.Must(
template.
New("").
Funcs(sprigx.TxtFuncMap()).
Parse(myTpl),
).
Funcs(sprig.TxtFuncMap())
)
and a function can even be explicitly overridden.
(show)
This would override a function foo and foo2 in sprigx from foo and foo2 from sprig, but leave all other sprig functions untouched.
package main
import (
"text/template"
"github.com/Masterminds/sprig/v3"
"r00t2.io/goutils/tplx/sprigx"
)
const (
myTpl string = `{{ "This is an example template string." | foo }}`
)
var (
overrideFuncs template.FuncMap = sprig.TxtFuncMap()
tpl *template.Template = template.Must(
template.
New("").
Funcs(sprigx.TxtFuncMap()).
Parse(myTpl),
).
Funcs(
template.FuncMap(
map[string]any{
"foo": overrideFuncs["foo"],
"foo2": overrideFuncs["foo2"],
},
),
)
)
3. Functions
Expect this list to grow over time, and potentially more frequently than the sprigx functions.
3.1. Operating System
3.1.1. osHostname
osHostname simply wraps and returns the result of calling os.Hostname.
As such, it comes with the same caveats - it’s possible for it to error, and it isn’t guaranteed to be an FQDN — it will be precisely/exactly whatever the kernel’s hostname is set as.
3.2. System/Platform/Architecture
3.2.1. sysArch
Returns the runtime.GOARCH constant.
3.2.2. sysNumCpu
Returns the value from runtime.NumCPU.
3.2.3. sysOsName
Returns the runtime.GOOS constant.
3.2.4. sysRuntime
This function returns a map[string]string of various information from the runtime stdlib library.
Specifically, the following are returned.
|
Tip
|
The value type is a direct link to the Because all values are mapped as strings, they can be converted back to their native type via e.g. the Sprig conversion functions if necessary. |
| Key | Value Type |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
As a convenience, some of these values also have their own dedicated functions as well:
3.3. Paths
3.3.1. Generic
These operate similar to the path stdlib library and use a fixed / path separator.
3.3.1.1. pathJoin
pathJoin operates exactly like path.Join in stdlib.
|
Warning
|
If you are joining paths in a pipeline, you almost assuredly want |
{{- pathJoin "a" "b" "c" }}
{{- pathJoin "/" "a" "b" "c" }}
{{- pathJoin "/a/b" "c" }}
renders as:
a/b/c
/a/b/c
/a/b/c
3.3.1.2. pathPipeJoin
pathPipeJoin operates like pathJoin with one deviation: the root/base path is expected to be last in the arguments.
This makes it much more suitable for use in template pipelines, as the previous value in a pipeline is passed in as the last element to the next pipe function.
{{- $myBase := "/a" -}}
{{- pathPipeJoin "b" "c" "a" }}
{{- pathPipeJoin "a" "b" "c" "/" }}
{{- $myBase | pathPipeJoin "b" "c" }}
renders as:
a/b/c
/a/b/c
/a/b/c
3.3.1.3. pathSliceJoin
pathSliceJoin joins a slice of path segment strings ([]string) instead of a variadic sequence of strings.
|
Tip
|
The |
{{- $myList := "a,b,c" | splitList "," -}}
{{- $myList | pathSliceJoin }}
{{- ("a,b,c" | splitList ",") | pathSliceJoin }}
{{- ("/,a,b,c" | splitList ",") | pathSliceJoin }}
renders as:
a/b/c
a/b/c
/a/b/c
3.3.1.4. pathSlicePipeJoin
pathSlicePipeJoin operates like pathPipeJoin in that it is suitable for pipeline use in which the root/base path is passed in from the pipeline, but it is like pathSliceJoin in that it then also accepts a slice of path segments ([]string) to append to that base path.
|
Tip
|
The |
{{- $myBase := "/a" -}}
{{- $myList := "b,c,d" | splitList "." -}}
{{- pathSlicePipeJoin $myList $myBase }}
{{- $myBase | pathSlicePipeJoin $myList }}
renders as:
/a/b/c
/a/b/c
3.3.1.5. pathSubJoin
pathSubJoin operates like pathJoin but it expects an explicit root/base path.
The pipeline-friendly equivalent of this is pathPipeJoin.
{{- pathSubJoin "/a/b" "c" }}
{{- pathSubJoin "/" "a" "b" "c" }}
{{- "c" | pathSubJoin "/" "a" "b" }}
renders as:
/a/b/c
/a/b/c
/a/b/c
3.3.2. OS/Platform-Tailored
These operate similar to the path/filepath stdlib library, and use the OS-specific os.PathSeparator.
|
Warning
|
Take special note of the oddness around specifying Windows paths and drive letters in e.g. It is recommended to make use of |
3.3.2.1. osPathJoin
osPathJoin operates exactly like path/filepath.Join in stdlib.
|
Warning
|
If you are joining paths in a pipeline, you almost assuredly want |
{{- osPathJoin "a" "b" "c" }}
{{- osPathJoin "/" "a" "b" "c" }}
{{- osPathJoin "C:\\" "a" "b" "c" }}
{{- osPathJoin "C:" "a" "b" "c" }}
renders as:
| OS | Result |
|---|---|
Windows |
|
Others (e.g. Linux, macOS) |
|
3.3.2.2. osPathPipeJoin
osPathPipeJoin operates like pathPipeJoin (except using OS-specific path separators).
This makes it much more suitable for use in template pipelines, as the previous value in a pipeline is passed in as the last element to the next pipe function.
{{- $myBase := "/a" -}}
{{- osPathPipeJoin "b" "c" "a" }}
{{- osPathPipeJoin "a" "b" "c" "/" }}
{{- $myBase | osPathPipeJoin "b" "c" }}
renders as:
| OS | Result |
|---|---|
Windows |
|
Others (e.g. Linux, macOS) |
|
3.3.2.3. osPathSep
osPathSep returns the os.PathSeparator for this OS.
{{- osPathSep }}
renders as:
| OS | Result |
|---|---|
Windows |
|
Others (e.g. Linux, macOS) |
|
3.3.2.4. osPathSliceJoin
osPathSliceJoin operates like pathSliceJoin but with OS-specific path separators.
|
Tip
|
The |
{{- $myList := "a,b,c" | splitList "," -}}
{{- $myList | osPathSliceJoin }}
{{- ("a,b,c" | splitList ",") | osPathSliceJoin }}
{{- ("/,a,b,c" | splitList ",") | osPathSliceJoin }}
renders as:
| OS | Result |
|---|---|
Windows |
|
Others (e.g. Linux, macOS) |
|
3.3.2.5. osPathSlicePipeJoin
osPathSlicePipeJoin operates like pathSlicePipeJoin but with OS-specific separators.
|
Tip
|
The |
{{- $myBase := "/a" -}}
{{- $myList := "b,c,d" | splitList "." -}}
{{- osPathSlicePipeJoin $myList $myBase }}
{{- $myBase | osPathSlicePipeJoin $myList }}
renders as:
| OS | Result |
|---|---|
Windows |
|
Others (e.g. Linux, macOS) |
|
3.3.2.6. osPathSubJoin
osPathSubJoin operates like pathSubJoin but with OS-specific separators.
The pipeline-friendly equivalent of this is osPathPipeJoin.
{{- osPathSubJoin "/a/b" "c" }}
{{- osPathSubJoin "/" "a" "b" "c" }}
{{- "c" | osPathSubJoin "/" "a" "b" }}
renders as:
| OS | Result |
|---|---|
Windows |
|
Others (e.g. Linux, macOS) |
|
3.4. Strings
3.4.1. extIndent
extIndent allows for a MUCH more flexible indenter than the sprig indent function.
It works with both Windows (\r\n) and POSIX (\n) linebreaks.
|
Tip
|
If |
It has quite a few arguments, however:
{{ extIndent <levels> <skipFirst> <skipEmpty> <skipWhitespace> <indentString> <input> }}
Where:
-
<levels>: The level of indentation for the text. If less than or equal to0,extIndentjust returns<input>as-is and NO-OPs otherwise. -
<skipFirst>: If true, skip indenting the first line. This is particularly handy if you like to visually align your function calls in your templates. -
<skipEmpty>: If true, do not add an indent to empty lines (where an "empty line" means "only has a linebreak"). -
<skipWhitespace>: If true, do not add an indent to lines that only consist of whitespace (spaces, tabs, etc.) and a linebreak. -
<indentString>: The string to use as the "indent character". This can be any string, such as" ","\t",".","|","=="etc. -
<input>: The text to be indented. Because it is the last argument,extIndentworks with pipelined text as well.
3.5. Debugging
3.5.1. dump
The dump function calls the Sdump function from go-spew (github.com/davecgh/go-spew/spew) for whatever object(s) is/are passed to it.