18 KiB
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.
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.
How do I Use SprigX?
The same way you would sprig!
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.
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
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
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.
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"],
},
),
)
)
Functions
Expect this list to grow over time, and potentially more frequently than
the sprigx functions.
Operating System
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.
System/Platform/Architecture
sysArch
Returns the runtime.GOARCH
constant.
sysNumCpu
Returns the value from
runtime.NumCPU.
sysOsName
Returns the runtime.GOOS constant.
sysRuntime
This function returns a map[string]string of various information from
the runtime stdlib library.
Specifically, the following are returned.
The value type is a direct link to the runtime documentation providing
more detail about the associated value.
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 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For safety concerns,
sprigxdoes not allow settingGOMAXPROCS, this value only contains the currentGOMAXPROCSvalue.↩︎
As a convenience, some of these values also have their own dedicated functions as well:
Paths
Generic
These operate similar to the path stdlib
library and use a fixed / path separator.
pathJoin
pathJoin operates exactly like
path.Join in stdlib.
If you are joining paths in a pipeline, you almost assuredly want or instead unless you are explicitly appending a pipeline result to a path.
{{- pathJoin "a" "b" "c" }}
{{- pathJoin "/" "a" "b" "c" }}
{{- pathJoin "/a/b" "c" }}
renders as:
a/b/c
/a/b/c
/a/b/c
pathPipeJoin
pathPipeJoin operates like 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
pathSliceJoin
pathSliceJoin joins a slice of path segment strings ([]string)
instead of a variadic sequence of strings.
The splitList function shown below is from the sprig string slice
functions.
{{- $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
pathSlicePipeJoin
pathSlicePipeJoin operates like in that it is
suitable for pipeline use in which the root/base path is passed in from
the pipeline, but it is like in that it then also
accepts a slice of path segments ([]string) to append to that base
path.
The splitList function shown below is from the sprig string slice
functions.
{{- $myBase := "/a" -}}
{{- $myList := "b,c,d" | splitList "." -}}
{{- pathSlicePipeJoin $myList $myBase }}
{{- $myBase | pathSlicePipeJoin $myList }}
renders as:
/a/b/c
/a/b/c
pathSubJoin
pathSubJoin operates like but it expects an
explicit root/base path.
The pipeline-friendly equivalent of this is .
{{- pathSubJoin "/a/b" "c" }}
{{- pathSubJoin "/" "a" "b" "c" }}
{{- "c" | pathSubJoin "/" "a" "b" }}
renders as:
/a/b/c
/a/b/c
/a/b/c
OS/Platform-Tailored
These operate similar to the path/filepath stdlib
library, and use the OS-specific
os.PathSeparator.
Take special note of the oddness around specifying Windows paths and drive letters in e.g. !
It is recommended to make use of to conditionally format path bases/roots if needed.
osPathJoin
osPathJoin operates exactly like
path/filepath.Join in stdlib.
If you are joining paths in a pipeline, you almost assuredly want or instead unless you are explicitly appending a pipeline result to a path.
{{- 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) |
|
osPathPipeJoin
osPathPipeJoin operates like (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) |
|
osPathSep
osPathSep returns the
os.PathSeparator for this OS.
{{- osPathSep }}
renders as:
| OS | Result |
|---|---|
Windows |
|
Others (e.g. Linux, macOS) |
|
osPathSliceJoin
osPathSliceJoin operates like but with
OS-specific path separators.
The splitList function shown below is from the sprig string slice
functions.
{{- $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) |
|
osPathSlicePipeJoin
osPathSlicePipeJoin operates like but with
OS-specific separators.
The splitList function shown below is from the sprig string slice
functions.
{{- $myBase := "/a" -}}
{{- $myList := "b,c,d" | splitList "." -}}
{{- osPathSlicePipeJoin $myList $myBase }}
{{- $myBase | osPathSlicePipeJoin $myList }}
renders as:
| OS | Result |
|---|---|
Windows |
|
Others (e.g. Linux, macOS) |
|
osPathSubJoin
osPathSubJoin operates like but with
OS-specific separators.
The pipeline-friendly equivalent of this is .
{{- osPathSubJoin "/a/b" "c" }}
{{- osPathSubJoin "/" "a" "b" "c" }}
{{- "c" | osPathSubJoin "/" "a" "b" }}
renders as:
| OS | Result |
|---|---|
Windows |
|
Others (e.g. Linux, macOS) |
|
Strings
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.
If <indentString> is set to \n and <levels> is always set to 1,
this function can even be used to doubelspace text!
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.
Debugging
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.