v1.16.0
ADDED: * tplx/sprigx
This commit is contained in:
631
tplx/sprigx/README.adoc
Normal file
631
tplx/sprigx/README.adoc
Normal file
@@ -0,0 +1,631 @@
|
||||
= SprigX
|
||||
Brent Saner <bts@square-r00t.net>
|
||||
Last rendered {localdatetime}
|
||||
:doctype: book
|
||||
:docinfo: shared
|
||||
:data-uri:
|
||||
:imagesdir: images
|
||||
:sectlinks:
|
||||
:sectnums:
|
||||
:sectnumlevels: 7
|
||||
:toc: preamble
|
||||
:toc2: left
|
||||
:idprefix:
|
||||
:toclevels: 7
|
||||
:source-highlighter: rouge
|
||||
:docinfo: shared
|
||||
|
||||
[id="wat"]
|
||||
== What is SprigX?
|
||||
SprigX are extensions to https://masterminds.github.io/sprig/[the `sprig` library^] (https://pkg.go.dev/github.com/Masterminds/sprig/v3[Go docs^]).
|
||||
|
||||
They provide functions that offer more enriched use cases and domain-specific data.
|
||||
|
||||
[id="use"]
|
||||
== How do I Use SprigX?
|
||||
|
||||
[%collapsible]
|
||||
.The same way you would `sprig`!
|
||||
====
|
||||
[source,go]
|
||||
----
|
||||
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(),
|
||||
)
|
||||
)
|
||||
----
|
||||
====
|
||||
|
||||
[%collapsible]
|
||||
.They can even be combined/used together.
|
||||
====
|
||||
[source,go]
|
||||
----
|
||||
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`:
|
||||
|
||||
[%collapsible]
|
||||
.this will use `foo` from `sprigx`
|
||||
====
|
||||
[source,go]
|
||||
----
|
||||
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
|
||||
|
||||
[%collapsible]
|
||||
.this will use `foo` from `sprig`
|
||||
====
|
||||
[source,go]
|
||||
----
|
||||
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
|
||||
|
||||
[%collapsible]
|
||||
.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.
|
||||
|
||||
[source,go]
|
||||
----
|
||||
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"],
|
||||
},
|
||||
),
|
||||
)
|
||||
)
|
||||
----
|
||||
====
|
||||
|
||||
[id="fn"]
|
||||
== Functions
|
||||
Expect this list to grow over time, and potentially more frequently than the `sprigx` functions.
|
||||
|
||||
[id="fn_sys"]
|
||||
=== System/OS/Platform
|
||||
|
||||
[id="fn_sys_arch"]
|
||||
==== `sysArch`
|
||||
Returns the https://pkg.go.dev/runtime#GOARCH[`runtime.GOARCH`^] constant.
|
||||
|
||||
[id="fn_sys_numcpu"]
|
||||
==== `sysNumCpu`
|
||||
Returns the value from https://pkg.go.dev/runtime#NumCPU[`runtime.NumCPU`^].
|
||||
|
||||
[id="fn_sys_os"]
|
||||
==== `sysOsName`
|
||||
Returns the https://pkg.go.dev/runtime#GOOS[`runtime.GOOS`^] constant.
|
||||
|
||||
[id="fn_sys_rntm"]
|
||||
==== `sysRuntime`
|
||||
This function returns a `map[string]string` of various information from the https://pkg.go.dev/runtime[`runtime` stdlib library^].
|
||||
|
||||
Specifically, the following are returned.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
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 https://masterminds.github.io/sprig/conversion.html[Sprig conversion functions^] if necessary.
|
||||
====
|
||||
|
||||
.`sysRuntime` Values
|
||||
[cols="^.^3m,^.^3",options="header"]
|
||||
|===
|
||||
| Key | Value Type
|
||||
|
||||
| compiler | https://pkg.go.dev/runtime#Compiler[string^]
|
||||
| arch | https://pkg.go.dev/runtime#GOARCH[string^]
|
||||
| os | https://pkg.go.dev/runtime#GOOS[string^]
|
||||
| maxprocs | https://pkg.go.dev/runtime#GOMAXPROCS[int^] footnote:[For safety concerns, `sprigx` does not allow *setting* `GOMAXPROCS`, this value only contains the *current* `GOMAXPROCS` value.]
|
||||
| cpu_cnt | https://pkg.go.dev/runtime#NumCPU[int^]
|
||||
| num_cgo | https://pkg.go.dev/runtime#NumCgoCall[int^]
|
||||
| num_go | https://pkg.go.dev/runtime#NumGoroutine[int^]
|
||||
| go_ver | https://pkg.go.dev/runtime#Version[string^]
|
||||
|===
|
||||
|
||||
As a convenience, some of these values also have their own dedicated functions as well:
|
||||
|
||||
* <<fn_sys_arch>>
|
||||
* <<fn_sys_numcpu>>
|
||||
* <<fn_sys_os>>
|
||||
|
||||
[id="fn_path"]
|
||||
=== Paths
|
||||
|
||||
[id="fn_path_gnrc"]
|
||||
==== Generic
|
||||
These operate similar to https://pkg.go.dev/path[the `path` stdlib library^] and use a fixed `/` path separator.
|
||||
|
||||
[id="fn_path_gnrc_pj"]
|
||||
===== `pathJoin`
|
||||
`pathJoin` operates *exactly* like https://pkg.go.dev/path#Join[`path.Join`^] in stdlib.
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
If you are joining paths in a pipeline, you almost assuredly want <<fn_path_gnrc_ppj>> or <<fn_path_gnrc_pspj>> instead unless you are explicitly *appending* a pipeline result to a path.
|
||||
====
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- pathJoin "a" "b" "c" }}
|
||||
{{- pathJoin "/" "a" "b" "c" }}
|
||||
{{- pathJoin "/a/b" "c" }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[source,text]
|
||||
----
|
||||
a/b/c
|
||||
/a/b/c
|
||||
/a/b/c
|
||||
----
|
||||
|
||||
[id="fn_path_gnrc_ppj"]
|
||||
===== `pathPipeJoin`
|
||||
`pathPipeJoin` operates like <<fn_path_gnrc_pj>> 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.
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- $myBase := "/a" -}}
|
||||
{{- pathPipeJoin "b" "c" "a" }}
|
||||
{{- pathPipeJoin "a" "b" "c" "/" }}
|
||||
{{- $myBase | pathPipeJoin "b" "c" }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[source,text]
|
||||
----
|
||||
a/b/c
|
||||
/a/b/c
|
||||
/a/b/c
|
||||
----
|
||||
|
||||
[id="fn_path_gnrc_psj"]
|
||||
===== `pathSliceJoin`
|
||||
`pathSliceJoin` joins a slice of path segment strings (`[]string`) instead of a variadic sequence of strings.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
The `splitList` function shown below is from the https://masterminds.github.io/sprig/string_slice.html[`sprig` string slice functions^].
|
||||
====
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- $myList := "a,b,c" | splitList "," -}}
|
||||
{{- $myList | pathSliceJoin }}
|
||||
{{- ("a,b,c" | splitList ",") | pathSliceJoin }}
|
||||
{{- ("/,a,b,c" | splitList ",") | pathSliceJoin }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[source,text]
|
||||
----
|
||||
a/b/c
|
||||
a/b/c
|
||||
/a/b/c
|
||||
----
|
||||
|
||||
[id="fn_path_gnrc_pspj"]
|
||||
===== `pathSlicePipeJoin`
|
||||
`pathSlicePipeJoin` operates like <<fn_path_gnrc_ppj>> in that it is suitable for pipeline use in which the root/base path is passed in from the pipeline, but it is like <<fn_path_gnrc_psj>> in that it then also accepts a slice of path segments (`[]string`) to append to that base path.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
The `splitList` function shown below is from the https://masterminds.github.io/sprig/string_slice.html[`sprig` string slice functions^].
|
||||
====
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- $myBase := "/a" -}}
|
||||
{{- $myList := "b,c,d" | splitList "." -}}
|
||||
{{- pathSlicePipeJoin $myList $myBase }}
|
||||
{{- $myBase | pathSlicePipeJoin $myList }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[source,text]
|
||||
----
|
||||
/a/b/c
|
||||
/a/b/c
|
||||
----
|
||||
|
||||
[id="fn_path_gnrc_psubj"]
|
||||
===== `pathSubJoin`
|
||||
`pathSubJoin` operates like <<fn_path_gnrc_pj>> but it expects an explicit root/base path.
|
||||
|
||||
The pipeline-friendly equivalent of this is <<fn_path_gnrc_ppj>>.
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- pathSubJoin "/a/b" "c" }}
|
||||
{{- pathSubJoin "/" "a" "b" "c" }}
|
||||
{{- "c" | pathSubJoin "/" "a" "b" }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[source,text]
|
||||
----
|
||||
/a/b/c
|
||||
/a/b/c
|
||||
/a/b/c
|
||||
----
|
||||
|
||||
[id="fn_path_os"]
|
||||
==== OS/Platform-Tailored
|
||||
These operate similar to https://pkg.go.dev/path/filepath[the `path/filepath` stdlib library^], and use the OS-specific https://pkg.go.dev/os#PathSeparator[`os.PathSeparator`^].
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
Take special note of the oddness around specifying Windows paths and drive letters in e.g. <<fn_path_os_pj>>!
|
||||
|
||||
It is recommended to make use of <<fn_sys_os>> to conditionally format path bases/roots if needed.
|
||||
====
|
||||
|
||||
[id="fn_path_os_pj"]
|
||||
===== `osPathJoin`
|
||||
`osPathJoin` operates *exactly* like https://pkg.go.dev/path/filepath#Join[`path/filepath.Join`^] in stdlib.
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
If you are joining paths in a pipeline, you almost assuredly want <<fn_path_os_ppj>> or <<fn_path_os_pspj>> instead unless you are explicitly *appending* a pipeline result to a path.
|
||||
====
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- osPathJoin "a" "b" "c" }}
|
||||
{{- osPathJoin "/" "a" "b" "c" }}
|
||||
{{- osPathJoin "C:\\" "a" "b" "c" }}
|
||||
{{- osPathJoin "C:" "a" "b" "c" }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[cols="^.^2,.^4a",options="header"]
|
||||
|===
|
||||
| OS ^| Result
|
||||
|
||||
| Windows | [source,text]
|
||||
----
|
||||
a\b\c
|
||||
\a\b\c
|
||||
\a\b\c
|
||||
C:\a\b\c
|
||||
C:a\b\c
|
||||
----
|
||||
| Others (e.g. Linux, macOS) | [source,text]
|
||||
----
|
||||
a/b/c
|
||||
/a/b/c
|
||||
C:\/a/b/c
|
||||
C:/a/b/c
|
||||
----
|
||||
|===
|
||||
|
||||
[id="fn_path_os_ppj"]
|
||||
===== `osPathPipeJoin`
|
||||
`osPathPipeJoin` operates like <<fn_path_gnrc_ppj>> (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.
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- $myBase := "/a" -}}
|
||||
{{- osPathPipeJoin "b" "c" "a" }}
|
||||
{{- osPathPipeJoin "a" "b" "c" "/" }}
|
||||
{{- $myBase | osPathPipeJoin "b" "c" }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[cols="^.^2,.^4a",options="header"]
|
||||
|===
|
||||
| OS ^| Result
|
||||
|
||||
| Windows | [source,text]
|
||||
----
|
||||
a\b\c
|
||||
\a\b\c
|
||||
\a\b\c
|
||||
----
|
||||
| Others (e.g. Linux, macOS) | [source,text]
|
||||
----
|
||||
a/b/c
|
||||
/a/b/c
|
||||
/a/b/c
|
||||
----
|
||||
|===
|
||||
|
||||
[id="fn_path_ossep"]
|
||||
===== `osPathSep`
|
||||
`osPathSep` returns the https://pkg.go.dev/os#PathSeparator[`os.PathSeparator`^] for this OS.
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- osPathSep }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[cols="^.^2,.^4a",options="header"]
|
||||
|===
|
||||
| OS ^| Result
|
||||
|
||||
| Windows | [source,text]
|
||||
----
|
||||
\
|
||||
----
|
||||
| Others (e.g. Linux, macOS) | [source,text]
|
||||
----
|
||||
/
|
||||
----
|
||||
|===
|
||||
|
||||
[id="fn_path_os_psj"]
|
||||
===== `osPathSliceJoin`
|
||||
`osPathSliceJoin` operates like <<fn_path_gnrc_psj>> but with OS-specific path separators.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
The `splitList` function shown below is from the https://masterminds.github.io/sprig/string_slice.html[`sprig` string slice functions^].
|
||||
====
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- $myList := "a,b,c" | splitList "," -}}
|
||||
{{- $myList | osPathSliceJoin }}
|
||||
{{- ("a,b,c" | splitList ",") | osPathSliceJoin }}
|
||||
{{- ("/,a,b,c" | splitList ",") | osPathSliceJoin }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[cols="^.^2,.^4a",options="header"]
|
||||
|===
|
||||
| OS ^| Result
|
||||
|
||||
| Windows | [source,text]
|
||||
----
|
||||
a\b\c
|
||||
a\b\c
|
||||
\a\b\c
|
||||
----
|
||||
| Others (e.g. Linux, macOS) | [source,text]
|
||||
----
|
||||
a/b/c
|
||||
a/b/c
|
||||
/a/b/c
|
||||
----
|
||||
|===
|
||||
|
||||
[id="fn_path_os_pspj"]
|
||||
===== `osPathSlicePipeJoin`
|
||||
`osPathSlicePipeJoin` operates like <<fn_path_gnrc_pspj>> but with OS-specific separators.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
The `splitList` function shown below is from the https://masterminds.github.io/sprig/string_slice.html[`sprig` string slice functions^].
|
||||
====
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- $myBase := "/a" -}}
|
||||
{{- $myList := "b,c,d" | splitList "." -}}
|
||||
{{- osPathSlicePipeJoin $myList $myBase }}
|
||||
{{- $myBase | osPathSlicePipeJoin $myList }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[cols="^.^2,.^4a",options="header"]
|
||||
|===
|
||||
| OS ^| Result
|
||||
|
||||
| Windows | [source,text]
|
||||
----
|
||||
\a\b\c\d
|
||||
\a\b\c\d
|
||||
----
|
||||
| Others (e.g. Linux, macOS) | [source,text]
|
||||
----
|
||||
/a/b/c/d
|
||||
/a/b/c/d
|
||||
----
|
||||
|===
|
||||
|
||||
[id="fn_path_os_psubj"]
|
||||
===== `osPathSubJoin`
|
||||
`osPathSubJoin` operates like <<fn_path_gnrc_psubj>> but with OS-specific separators.
|
||||
|
||||
The pipeline-friendly equivalent of this is <<fn_path_os_ppj>>.
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{- osPathSubJoin "/a/b" "c" }}
|
||||
{{- osPathSubJoin "/" "a" "b" "c" }}
|
||||
{{- "c" | osPathSubJoin "/" "a" "b" }}
|
||||
----
|
||||
|
||||
renders as:
|
||||
|
||||
[cols="^.^2,.^4a",options="header"]
|
||||
|===
|
||||
| OS ^| Result
|
||||
|
||||
| Windows | [source,text]
|
||||
----
|
||||
\a\b\c
|
||||
\a\b\c
|
||||
\a\b\c
|
||||
----
|
||||
| Others (e.g. Linux, macOS) | [source,text]
|
||||
----
|
||||
/a/b/c
|
||||
/a/b/c
|
||||
/a/b/c
|
||||
----
|
||||
|===
|
||||
|
||||
[id="fn_str"]
|
||||
=== Strings
|
||||
|
||||
[id="fn_str_extindent"]
|
||||
==== `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 `<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:
|
||||
|
||||
[source,gotemplate]
|
||||
----
|
||||
{{ extIndent <levels> <skipFirst> <skipEmpty> <skipWhitespace> <indentString> <input> }}
|
||||
----
|
||||
|
||||
Where:
|
||||
|
||||
* `<levels>`: The level of indentation for the text. If less than or equal to `0`, `extIndent` just 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, `extIndent` works with pipelined text as well.
|
||||
|
||||
[id="fn_dbg"]
|
||||
=== Debugging
|
||||
|
||||
[id="fn_dbg_dump"]
|
||||
==== `dump`
|
||||
The `dump` function calls https://pkg.go.dev/github.com/davecgh/go-spew/spew#Sdump[the `Sdump` function^] from https://github.com/davecgh/go-spew[`go-spew`] (https://pkg.go.dev/github.com/davecgh/go-spew/spew[`github.com/davecgh/go-spew/spew`^]) for whatever object(s) is/are passed to it.
|
||||
Reference in New Issue
Block a user