Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
927ad08057
|
||
|
|
2edbc9306d
|
31
.githooks/pre-commit/01-docgen
Executable file
31
.githooks/pre-commit/01-docgen
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
orig="${PWD}"
|
||||||
|
|
||||||
|
if ! command -v asciidoctor &> /dev/null;
|
||||||
|
then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
for f in $(find . -type f -iname "README.adoc"); do
|
||||||
|
filename=$(basename -- "${f}")
|
||||||
|
docsdir=$(dirname -- "${f}")
|
||||||
|
nosuffix="${filename%.*}"
|
||||||
|
pfx="${docsdir}/${nosuffix}"
|
||||||
|
|
||||||
|
newf="${pfx}.html"
|
||||||
|
asciidoctor -a ROOTDIR="${orig}/" -o "${newf}" "${f}"
|
||||||
|
echo "Generated ${newf} from ${f}"
|
||||||
|
git add "${newf}"
|
||||||
|
if command -v pandoc &> /dev/null;
|
||||||
|
then
|
||||||
|
newf="${pfx}.md"
|
||||||
|
asciidoctor -a ROOTDIR="${orig}/" -b docbook -o - "${f}" | pandoc -f docbook -t markdown_strict -o "${newf}"
|
||||||
|
echo "Generated ${newf} from ${f}"
|
||||||
|
git add "${newf}"
|
||||||
|
fi
|
||||||
|
cd ${orig}
|
||||||
|
done
|
||||||
|
echo "Regenerated docs"
|
||||||
11
go.mod
11
go.mod
@@ -3,7 +3,9 @@ module r00t2.io/goutils
|
|||||||
go 1.25
|
go 1.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/Masterminds/sprig/v3 v3.3.0
|
||||||
github.com/coreos/go-systemd/v22 v22.6.0
|
github.com/coreos/go-systemd/v22 v22.6.0
|
||||||
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/sys v0.39.0
|
golang.org/x/sys v0.39.0
|
||||||
@@ -11,6 +13,15 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
dario.cat/mergo v1.0.1 // indirect
|
||||||
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
|
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||||
github.com/djherbis/times v1.6.0 // indirect
|
github.com/djherbis/times v1.6.0 // indirect
|
||||||
|
github.com/huandu/xstrings v1.5.0 // indirect
|
||||||
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
|
github.com/shopspring/decimal v1.4.0 // indirect
|
||||||
|
github.com/spf13/cast v1.7.0 // indirect
|
||||||
|
golang.org/x/crypto v0.26.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
41
go.sum
41
go.sum
@@ -1,15 +1,56 @@
|
|||||||
|
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||||
|
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
|
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||||
|
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||||
|
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
|
||||||
|
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||||
|
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
|
||||||
|
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
|
||||||
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
|
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
|
||||||
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
|
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
|
github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
|
||||||
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
|
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
|
||||||
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
|
||||||
|
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||||
|
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
|
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||||
|
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||||
|
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||||
|
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||||
|
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
|
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||||
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
r00t2.io/sysutils v1.15.1 h1:0EVZZAxTFqQN6jjfjqUKkXye0LMshUA5MO7l3Wd6wH8=
|
r00t2.io/sysutils v1.15.1 h1:0EVZZAxTFqQN6jjfjqUKkXye0LMshUA5MO7l3Wd6wH8=
|
||||||
r00t2.io/sysutils v1.15.1/go.mod h1:T0iOnaZaSG5NE1hbXTqojRZc0ia/u8TB73lV7zhMz58=
|
r00t2.io/sysutils v1.15.1/go.mod h1:T0iOnaZaSG5NE1hbXTqojRZc0ia/u8TB73lV7zhMz58=
|
||||||
|
|||||||
21
multierr/TODO
Normal file
21
multierr/TODO
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
- add unwrapping
|
||||||
|
https://go.dev/blog/go1.13-errors#the-unwrap-method
|
||||||
|
- add As method, takes a ptr to a slice of []error to return the first matching error type (errors.As) for each?
|
||||||
|
- add AsAll [][]error ptr param for multiple errors per type?
|
||||||
|
- add Map, returns map[string][]error, where key is k:
|
||||||
|
var sb strings.Builder
|
||||||
|
t = reflect.TypeOf(err)
|
||||||
|
if t.PkgPath() != "" {
|
||||||
|
sb.WriteString(t.PkgPath())
|
||||||
|
} else {
|
||||||
|
sb.WriteString("<UNKNOWN>")
|
||||||
|
}
|
||||||
|
sb.WriteString(".")
|
||||||
|
if t.Name() != "" {
|
||||||
|
sb.WriteString(t.Name())
|
||||||
|
} else {
|
||||||
|
sb.WriteString("<UNKNOWN>")
|
||||||
|
}
|
||||||
|
k = sb.String()
|
||||||
|
- support generics for similar to above?
|
||||||
|
- this might allow for "error filtering"
|
||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
/*
|
/*
|
||||||
AddrRfc returns an RFC-friendly string from an IP address ([net/netip.Addr]).
|
AddrRfc returns an RFC-friendly string from an IP address ([net/netip.Addr]).
|
||||||
|
|
||||||
If addr is an IPv4 address, it will simmply be the string representation (e.g. "203.0.113.1").
|
If addr is an IPv4 address, it will simply be the string representation (e.g. "203.0.113.1").
|
||||||
|
|
||||||
If addr is an IPv6 address, it will be enclosed in brackets (e.g. "[2001:db8::1]").
|
If addr is an IPv6 address, it will be enclosed in brackets (e.g. "[2001:db8::1]").
|
||||||
|
|
||||||
|
|||||||
@@ -352,7 +352,6 @@ It will panic if the embedded [regexp.Regexp] is nil.
|
|||||||
|
|
||||||
This operates on only the first found match (like [regexp.Regexp.FindStringSubmatch]).
|
This operates on only the first found match (like [regexp.Regexp.FindStringSubmatch]).
|
||||||
To operate on *all* matches, use [ReMap.MapStringAll].
|
To operate on *all* matches, use [ReMap.MapStringAll].
|
||||||
To operate on *all* matches with retained grouping, use [ReMap.MapStringAllSplit].
|
|
||||||
|
|
||||||
A small deviation and caveat, though; empty strings instead of nils (because duh) will occupy slice placeholders (if `inclNoMatchStrict` is specified).
|
A small deviation and caveat, though; empty strings instead of nils (because duh) will occupy slice placeholders (if `inclNoMatchStrict` is specified).
|
||||||
This unfortunately *does not provide any indication* if an empty string positively matched the pattern (a "hit") or if it was simply
|
This unfortunately *does not provide any indication* if an empty string positively matched the pattern (a "hit") or if it was simply
|
||||||
|
|||||||
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.
|
||||||
1532
tplx/sprigx/README.html
Normal file
1532
tplx/sprigx/README.html
Normal file
File diff suppressed because it is too large
Load Diff
656
tplx/sprigx/README.md
Normal file
656
tplx/sprigx/README.md
Normal file
@@ -0,0 +1,656 @@
|
|||||||
|
# What is SprigX?
|
||||||
|
|
||||||
|
SprigX are extensions to [the `sprig`
|
||||||
|
library](https://masterminds.github.io/sprig/) ([Go
|
||||||
|
docs](https://pkg.go.dev/github.com/Masterminds/sprig/v3)).
|
||||||
|
|
||||||
|
They provide functions that offer more enriched use cases and
|
||||||
|
domain-specific data.
|
||||||
|
|
||||||
|
# How do I Use SprigX?
|
||||||
|
|
||||||
|
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(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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`:
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## System/OS/Platform
|
||||||
|
|
||||||
|
### `sysArch`
|
||||||
|
|
||||||
|
Returns the [`runtime.GOARCH`](https://pkg.go.dev/runtime#GOARCH)
|
||||||
|
constant.
|
||||||
|
|
||||||
|
### `sysNumCpu`
|
||||||
|
|
||||||
|
Returns the value from
|
||||||
|
[`runtime.NumCPU`](https://pkg.go.dev/runtime#NumCPU).
|
||||||
|
|
||||||
|
### `sysOsName`
|
||||||
|
|
||||||
|
Returns the [`runtime.GOOS`](https://pkg.go.dev/runtime#GOOS) constant.
|
||||||
|
|
||||||
|
### `sysRuntime`
|
||||||
|
|
||||||
|
This function returns a `map[string]string` of various information from
|
||||||
|
the [`runtime` stdlib library](https://pkg.go.dev/runtime).
|
||||||
|
|
||||||
|
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](https://masterminds.github.io/sprig/conversion.html) if
|
||||||
|
necessary.
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<caption><code>sysRuntime</code> Values</caption>
|
||||||
|
<colgroup>
|
||||||
|
<col style="width: 50%" />
|
||||||
|
<col style="width: 50%" />
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="text-align: center;">Key</th>
|
||||||
|
<th style="text-align: center;">Value Type</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p><code>compiler</code></p></td>
|
||||||
|
<td style="text-align: center;"><p><a
|
||||||
|
href="https://pkg.go.dev/runtime#Compiler">string</a></p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p><code>arch</code></p></td>
|
||||||
|
<td style="text-align: center;"><p><a
|
||||||
|
href="https://pkg.go.dev/runtime#GOARCH">string</a></p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p><code>os</code></p></td>
|
||||||
|
<td style="text-align: center;"><p><a
|
||||||
|
href="https://pkg.go.dev/runtime#GOOS">string</a></p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p><code>maxprocs</code></p></td>
|
||||||
|
<td style="text-align: center;"><p><a
|
||||||
|
href="https://pkg.go.dev/runtime#GOMAXPROCS">int</a> <a href="#fn1"
|
||||||
|
class="footnote-ref" id="fnref1"
|
||||||
|
role="doc-noteref"><sup>1</sup></a></p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p><code>cpu_cnt</code></p></td>
|
||||||
|
<td style="text-align: center;"><p><a
|
||||||
|
href="https://pkg.go.dev/runtime#NumCPU">int</a></p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p><code>num_cgo</code></p></td>
|
||||||
|
<td style="text-align: center;"><p><a
|
||||||
|
href="https://pkg.go.dev/runtime#NumCgoCall">int</a></p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p><code>num_go</code></p></td>
|
||||||
|
<td style="text-align: center;"><p><a
|
||||||
|
href="https://pkg.go.dev/runtime#NumGoroutine">int</a></p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p><code>go_ver</code></p></td>
|
||||||
|
<td style="text-align: center;"><p><a
|
||||||
|
href="https://pkg.go.dev/runtime#Version">string</a></p></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<section id="footnotes" class="footnotes footnotes-end-of-document"
|
||||||
|
role="doc-endnotes">
|
||||||
|
<hr />
|
||||||
|
<ol>
|
||||||
|
<li id="fn1"><p>For safety concerns, <code>sprigx</code> does not allow
|
||||||
|
<strong>setting</strong> <code>GOMAXPROCS</code>, this value only
|
||||||
|
contains the <strong>current</strong> <code>GOMAXPROCS</code> value.<a
|
||||||
|
href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
As a convenience, some of these values also have their own dedicated
|
||||||
|
functions as well:
|
||||||
|
|
||||||
|
- [](#fn_sys_arch)
|
||||||
|
|
||||||
|
- [](#fn_sys_numcpu)
|
||||||
|
|
||||||
|
- [](#fn_sys_os)
|
||||||
|
|
||||||
|
## Paths
|
||||||
|
|
||||||
|
### Generic
|
||||||
|
|
||||||
|
These operate similar to [the `path` stdlib
|
||||||
|
library](https://pkg.go.dev/path) and use a fixed `/` path separator.
|
||||||
|
|
||||||
|
#### `pathJoin`
|
||||||
|
|
||||||
|
`pathJoin` operates **exactly** like
|
||||||
|
[`path.Join`](https://pkg.go.dev/path#Join) in stdlib.
|
||||||
|
|
||||||
|
If you are joining paths in a pipeline, you almost assuredly want
|
||||||
|
[](#fn_path_gnrc_ppj) or [](#fn_path_gnrc_pspj) instead.
|
||||||
|
|
||||||
|
{{- 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 [](#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.
|
||||||
|
|
||||||
|
{{- $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](https://masterminds.github.io/sprig/string_slice.html).
|
||||||
|
|
||||||
|
{{- $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 [](#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.
|
||||||
|
|
||||||
|
The `splitList` function shown below is from the [`sprig` string slice
|
||||||
|
functions](https://masterminds.github.io/sprig/string_slice.html).
|
||||||
|
|
||||||
|
{{- $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 [](#fn_path_gnrc_pj) but it expects an
|
||||||
|
explicit root/base path.
|
||||||
|
|
||||||
|
The pipeline-friendly equivalent of this is [](#fn_path_gnrc_ppj).
|
||||||
|
|
||||||
|
{{- 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](https://pkg.go.dev/path/filepath), and use the OS-specific
|
||||||
|
[`os.PathSeparator`](https://pkg.go.dev/os#PathSeparator).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
#### `osPathJoin`
|
||||||
|
|
||||||
|
`osPathJoin` operates **exactly** like
|
||||||
|
[`path/filepath.Join`](https://pkg.go.dev/path/filepath#Join) in stdlib.
|
||||||
|
|
||||||
|
If you are joining paths in a pipeline, you almost assuredly want
|
||||||
|
[](#fn_path_os_ppj) or [](#fn_path_os_pspj) instead.
|
||||||
|
|
||||||
|
{{- osPathJoin "a" "b" "c" }}
|
||||||
|
{{- osPathJoin "/" "a" "b" "c" }}
|
||||||
|
{{- osPathJoin "C:\\" "a" "b" "c" }}
|
||||||
|
{{- osPathJoin "C:" "a" "b" "c" }}
|
||||||
|
|
||||||
|
renders as:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style="width: 33%" />
|
||||||
|
<col style="width: 66%" />
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="text-align: center;">OS</th>
|
||||||
|
<th style="text-align: center;">Result</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Windows</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>a\b\c
|
||||||
|
\a\b\c
|
||||||
|
\a\b\c
|
||||||
|
C:\a\b\c
|
||||||
|
C:a\b\c</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Others (e.g. Linux, macOS)</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>a/b/c
|
||||||
|
/a/b/c
|
||||||
|
C:\/a/b/c
|
||||||
|
C:/a/b/c</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
#### `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.
|
||||||
|
|
||||||
|
{{- $myBase := "/a" -}}
|
||||||
|
{{- osPathPipeJoin "b" "c" "a" }}
|
||||||
|
{{- osPathPipeJoin "a" "b" "c" "/" }}
|
||||||
|
{{- $myBase | osPathPipeJoin "b" "c" }}
|
||||||
|
|
||||||
|
renders as:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style="width: 33%" />
|
||||||
|
<col style="width: 66%" />
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="text-align: center;">OS</th>
|
||||||
|
<th style="text-align: center;">Result</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Windows</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>a\b\c
|
||||||
|
\a\b\c
|
||||||
|
\a\b\c</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Others (e.g. Linux, macOS)</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>a/b/c
|
||||||
|
/a/b/c
|
||||||
|
/a/b/c</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
#### `osPathSep`
|
||||||
|
|
||||||
|
`osPathSep` returns the
|
||||||
|
[`os.PathSeparator`](https://pkg.go.dev/os#PathSeparator) for this OS.
|
||||||
|
|
||||||
|
{{- osPathSep }}
|
||||||
|
|
||||||
|
renders as:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style="width: 33%" />
|
||||||
|
<col style="width: 66%" />
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="text-align: center;">OS</th>
|
||||||
|
<th style="text-align: center;">Result</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Windows</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>\</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Others (e.g. Linux, macOS)</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>/</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
#### `osPathSliceJoin`
|
||||||
|
|
||||||
|
`osPathSliceJoin` operates like [](#fn_path_gnrc_psj) but with
|
||||||
|
OS-specific path separators.
|
||||||
|
|
||||||
|
The `splitList` function shown below is from the [`sprig` string slice
|
||||||
|
functions](https://masterminds.github.io/sprig/string_slice.html).
|
||||||
|
|
||||||
|
{{- $myList := "a,b,c" | splitList "," -}}
|
||||||
|
{{- $myList | osPathSliceJoin }}
|
||||||
|
{{- ("a,b,c" | splitList ",") | osPathSliceJoin }}
|
||||||
|
{{- ("/,a,b,c" | splitList ",") | osPathSliceJoin }}
|
||||||
|
|
||||||
|
renders as:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style="width: 33%" />
|
||||||
|
<col style="width: 66%" />
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="text-align: center;">OS</th>
|
||||||
|
<th style="text-align: center;">Result</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Windows</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>a\b\c
|
||||||
|
a\b\c
|
||||||
|
\a\b\c</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Others (e.g. Linux, macOS)</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>a/b/c
|
||||||
|
a/b/c
|
||||||
|
/a/b/c</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
#### `osPathSlicePipeJoin`
|
||||||
|
|
||||||
|
`osPathSlicePipeJoin` operates like [](#fn_path_gnrc_pspj) but with
|
||||||
|
OS-specific separators.
|
||||||
|
|
||||||
|
The `splitList` function shown below is from the [`sprig` string slice
|
||||||
|
functions](https://masterminds.github.io/sprig/string_slice.html).
|
||||||
|
|
||||||
|
{{- $myBase := "/a" -}}
|
||||||
|
{{- $myList := "b,c,d" | splitList "." -}}
|
||||||
|
{{- osPathSlicePipeJoin $myList $myBase }}
|
||||||
|
{{- $myBase | osPathSlicePipeJoin $myList }}
|
||||||
|
|
||||||
|
renders as:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style="width: 33%" />
|
||||||
|
<col style="width: 66%" />
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="text-align: center;">OS</th>
|
||||||
|
<th style="text-align: center;">Result</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Windows</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>\a\b\c\d
|
||||||
|
\a\b\c\d</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Others (e.g. Linux, macOS)</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>/a/b/c/d
|
||||||
|
/a/b/c/d</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
#### `osPathSubJoin`
|
||||||
|
|
||||||
|
`osPathSubJoin` operates like [](#fn_path_gnrc_psubj) but with
|
||||||
|
OS-specific separators.
|
||||||
|
|
||||||
|
The pipeline-friendly equivalent of this is [](#fn_path_os_ppj).
|
||||||
|
|
||||||
|
{{- osPathSubJoin "/a/b" "c" }}
|
||||||
|
{{- osPathSubJoin "/" "a" "b" "c" }}
|
||||||
|
{{- "c" | osPathSubJoin "/" "a" "b" }}
|
||||||
|
|
||||||
|
renders as:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style="width: 33%" />
|
||||||
|
<col style="width: 66%" />
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="text-align: center;">OS</th>
|
||||||
|
<th style="text-align: center;">Result</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Windows</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>\a\b\c
|
||||||
|
\a\b\c
|
||||||
|
\a\b\c</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;"><p>Others (e.g. Linux, macOS)</p></td>
|
||||||
|
<td style="text-align: left;"><pre class="text"><code>/a/b/c
|
||||||
|
/a/b/c
|
||||||
|
/a/b/c</code></pre></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
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 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.
|
||||||
101
tplx/sprigx/_test.tpl
Normal file
101
tplx/sprigx/_test.tpl
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
################################################################################
|
||||||
|
# RUNTIME #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
{{- $rntm := sysRuntime }}
|
||||||
|
|
||||||
|
Arch: {{ sysArch }}
|
||||||
|
CPUs: {{ sysNumCpu }}
|
||||||
|
OS: {{ sysNumCpu }}
|
||||||
|
|
||||||
|
RUNTIME: {{ $rntm }}
|
||||||
|
{{ range $rntmk, $rntmv := $rntm }}
|
||||||
|
{{ $rntmk }}:
|
||||||
|
{{ $rntmv }}
|
||||||
|
{{- end }}
|
||||||
|
{{ dump $rntm }}
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# PATHS #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
###########
|
||||||
|
# Generic #
|
||||||
|
###########
|
||||||
|
|
||||||
|
pathJoin "a" "b" "c"
|
||||||
|
{{ pathJoin "a" "b" "c" }}
|
||||||
|
|
||||||
|
pathJoin "/" "a" "b" "c"
|
||||||
|
{{ pathJoin "/" "a" "b" "c" }}
|
||||||
|
|
||||||
|
pathJoin "/a" "b" "c"
|
||||||
|
{{ pathJoin "/a" "b" "c" }}
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
pathPipeJoin "b" "c" "d" "a"
|
||||||
|
{{ pathPipeJoin "b" "c" "d" "a" }}
|
||||||
|
|
||||||
|
"a" | pathPipeJoin "b" "c" "d"
|
||||||
|
{{ "a" | pathPipeJoin "b" "c" "d"}}
|
||||||
|
#
|
||||||
|
|
||||||
|
$base := "/"
|
||||||
|
$myPsjSlice := "a,b,c" | splitList ","
|
||||||
|
pathSliceJoin $myPsjSlice
|
||||||
|
{{- $base := "/" }}
|
||||||
|
{{- $myPsjSlice := "a,b,c" | splitList "," }}
|
||||||
|
{{ pathSliceJoin $myPsjSlice }}
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
$base | pathSlicePipeJoin $myPsjSlice
|
||||||
|
{{ $base | pathSlicePipeJoin $myPsjSlice }}
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
pathSubJoin $base "a" "b" "c"
|
||||||
|
{{ pathSubJoin $base "a" "b" "c" }}
|
||||||
|
|
||||||
|
|
||||||
|
######################
|
||||||
|
# OS/System/Platform #
|
||||||
|
######################
|
||||||
|
|
||||||
|
osPathJoin "a" "b" "c"
|
||||||
|
{{ osPathJoin "a" "b" "c" }}
|
||||||
|
|
||||||
|
osPathJoin "/" "a" "b" "c"
|
||||||
|
{{ osPathJoin "a" "b" "c" }}
|
||||||
|
|
||||||
|
osPathJoin "/a" "b" "c"
|
||||||
|
{{ osPathJoin "a" "b" "c" }}
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
osPathPipeJoin "b" "c" "d" "a"
|
||||||
|
{{ osPathPipeJoin "b" "c" "d" "a" }}
|
||||||
|
|
||||||
|
"a" | osPathPipeJoin "b" "c" "d"
|
||||||
|
{{ "a" | osPathPipeJoin "b" "c" "d" }}
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
$osBase := "/"
|
||||||
|
$myOsPsjSlice := "a,b,c" | splitList ","
|
||||||
|
osPathSliceJoin $myOsPsjSlice
|
||||||
|
{{- $osBase := "/" }}
|
||||||
|
{{- $myOsPsjSlice := "a,b,c" | splitList "," }}
|
||||||
|
{{ osPathSliceJoin $myOsPsjSlice }}
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
$osBase | osPathSlicePipeJoin $myOsPsjSlice
|
||||||
|
{{ $osBase | osPathSlicePipeJoin $myOsPsjSlice }}
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
osPathSubJoin $osBase "a" "b" "c"
|
||||||
|
{{ osPathSubJoin $osBase "a" "b" "c" }}
|
||||||
40
tplx/sprigx/consts.go
Normal file
40
tplx/sprigx/consts.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package sprigx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// genericMap holds functions usable/intended for use in either an [html/template.FuncMap] or [text/template.FuncMap].
|
||||||
|
genericMap map[string]any = map[string]any{
|
||||||
|
// Debugging
|
||||||
|
"dump": dump,
|
||||||
|
// Strings
|
||||||
|
"extIndent": extIndent, // PR in: https://github.com/Masterminds/sprig/pull/468
|
||||||
|
// OS/System
|
||||||
|
"sysArch": sysArch,
|
||||||
|
"sysNumCpu": sysNumCpu,
|
||||||
|
"sysOsName": sysOsNm,
|
||||||
|
"sysRuntime": sysRuntime,
|
||||||
|
// Paths: Generic
|
||||||
|
"pathJoin": path.Join,
|
||||||
|
"pathPipeJoin": pathPipeJoin,
|
||||||
|
"pathSliceJoin": pathSliceJoin,
|
||||||
|
"pathSlicePipeJoin": pathSlicePipeJoin,
|
||||||
|
"pathSubJoin": pathSubJoin,
|
||||||
|
// Paths: OS/Platform
|
||||||
|
"osPathJoin": filepath.Join,
|
||||||
|
"osPathPipeJoin": osPathPipeJoin,
|
||||||
|
"osPathSep": osPathSep,
|
||||||
|
"osPathSliceJoin": osPathSliceJoin,
|
||||||
|
"osPathSlicePipeJoin": osPathSlicePipeJoin,
|
||||||
|
"osPathSubJoin": osPathSubJoin,
|
||||||
|
}
|
||||||
|
|
||||||
|
// htmlMap holds functions usable/intended for use in only an [html/template.FuncMap].
|
||||||
|
htmlMap map[string]any = map[string]any{}
|
||||||
|
|
||||||
|
// txtMap holds functions usable/intended for use in only a [text/template.FuncMap].
|
||||||
|
txtMap map[string]any = map[string]any{}
|
||||||
|
)
|
||||||
16
tplx/sprigx/doc.go
Normal file
16
tplx/sprigx/doc.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
Package sprigx aims to provide additional functions that the author believes are missing from [sprig] ([Go docs]).
|
||||||
|
|
||||||
|
It's a decent enough "basics" library, but I frequently find it falls short once you start needing domain-specific data.
|
||||||
|
|
||||||
|
These may get merged into sprig, they may not. It all depends on how responsive they are to PRs.
|
||||||
|
Given that they only update it every 6 months or so, however...
|
||||||
|
|
||||||
|
See the [full documentation] on the [repo].
|
||||||
|
|
||||||
|
[sprig]: https://masterminds.github.io/sprig/
|
||||||
|
[Go docs]: https://pkg.go.dev/github.com/Masterminds/sprig/v3
|
||||||
|
[full documentation]: https://git.r00t2.io/r00t2/go_goutils/src/branch/master/tplx/sprigx/README.adoc
|
||||||
|
[repo]: https://git.r00t2.io/r00t2/go_goutils
|
||||||
|
*/
|
||||||
|
package sprigx
|
||||||
64
tplx/sprigx/funcs.go
Normal file
64
tplx/sprigx/funcs.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package sprigx
|
||||||
|
|
||||||
|
import (
|
||||||
|
htpl "html/template"
|
||||||
|
ttpl "text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Many of these functions are modeled after sprig's.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
FuncMap returns a generic function map.
|
||||||
|
|
||||||
|
You probably want [HtmlFuncMap] or [TxtFuncMap] instead,
|
||||||
|
as they wrap this with the appropriate type.
|
||||||
|
*/
|
||||||
|
func FuncMap() (fmap map[string]any) {
|
||||||
|
|
||||||
|
var fn string
|
||||||
|
var f any
|
||||||
|
|
||||||
|
fmap = make(map[string]any, len(genericMap))
|
||||||
|
|
||||||
|
for fn, f = range genericMap {
|
||||||
|
fmap[fn] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// HtmlFuncMap returns an [html/template.FuncMap].
|
||||||
|
func HtmlFuncMap() (fmap htpl.FuncMap) {
|
||||||
|
|
||||||
|
var fn string
|
||||||
|
var f any
|
||||||
|
|
||||||
|
fmap = htpl.FuncMap(FuncMap())
|
||||||
|
|
||||||
|
if htmlMap != nil && len(htmlMap) > 0 {
|
||||||
|
for fn, f = range htmlMap {
|
||||||
|
fmap[fn] = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxtFuncMap returns a [text/template.FuncMap].
|
||||||
|
func TxtFuncMap() (fmap ttpl.FuncMap) {
|
||||||
|
|
||||||
|
var fn string
|
||||||
|
var f any
|
||||||
|
|
||||||
|
fmap = ttpl.FuncMap(FuncMap())
|
||||||
|
|
||||||
|
if txtMap != nil && len(txtMap) > 0 {
|
||||||
|
for fn, f = range txtMap {
|
||||||
|
fmap[fn] = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
33
tplx/sprigx/funcs_test.go
Normal file
33
tplx/sprigx/funcs_test.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package sprigx
|
||||||
|
|
||||||
|
import (
|
||||||
|
`bytes`
|
||||||
|
_ "embed"
|
||||||
|
"testing"
|
||||||
|
`text/template`
|
||||||
|
|
||||||
|
"github.com/Masterminds/sprig/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//go:embed "_test.tpl"
|
||||||
|
testTplBytes []byte
|
||||||
|
testTpl *template.Template = template.Must(
|
||||||
|
template.
|
||||||
|
New("").
|
||||||
|
Funcs(sprig.TxtFuncMap()).
|
||||||
|
Funcs(TxtFuncMap()).
|
||||||
|
Parse(string(testTplBytes)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFuncs(t *testing.T) {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var buf *bytes.Buffer = new(bytes.Buffer)
|
||||||
|
|
||||||
|
if err = testTpl.Execute(buf, nil); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(buf.String())
|
||||||
|
}
|
||||||
17
tplx/sprigx/funcs_tpl_dbg.go
Normal file
17
tplx/sprigx/funcs_tpl_dbg.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package sprigx
|
||||||
|
|
||||||
|
import (
|
||||||
|
`github.com/davecgh/go-spew/spew`
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
dump calls [spew.Sdump] on obj.
|
||||||
|
|
||||||
|
[spew.Sdump]: https://pkg.go.dev/github.com/davecgh/go-spew/spew
|
||||||
|
*/
|
||||||
|
func dump(obj any) (out string) {
|
||||||
|
|
||||||
|
out = spew.Sdump(obj)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
155
tplx/sprigx/funcs_tpl_paths.go
Normal file
155
tplx/sprigx/funcs_tpl_paths.go
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
package sprigx
|
||||||
|
|
||||||
|
import (
|
||||||
|
`os`
|
||||||
|
`path`
|
||||||
|
`path/filepath`
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
//
|
||||||
|
// GENERIC
|
||||||
|
//
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
pathPipeJoin wraps path.Join with the root element at the *end* instead of the beginning.
|
||||||
|
|
||||||
|
{{ pathPipeJoin "b" "c" "a" }}
|
||||||
|
|
||||||
|
is equivalent to
|
||||||
|
|
||||||
|
path.Join("a", "b", "c")
|
||||||
|
|
||||||
|
This order variation is better suited for pipelines that pass the root path.
|
||||||
|
*/
|
||||||
|
func pathPipeJoin(elems ...string) (out string) {
|
||||||
|
|
||||||
|
var rootIdx int
|
||||||
|
|
||||||
|
if elems == nil || len(elems) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rootIdx = len(elems) - 1
|
||||||
|
out = elems[rootIdx]
|
||||||
|
|
||||||
|
if len(elems) == 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out = pathSubJoin(out, elems[:rootIdx]...)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// pathSliceJoin joins a slice of path segments.
|
||||||
|
func pathSliceJoin(sl []string) (out string) {
|
||||||
|
|
||||||
|
out = path.Join(sl...)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pathSlicePipeJoin behaves like a mix of pathPipeJoin (in that it accepts the root element last)
|
||||||
|
and pathSliceJoin (in that it accepts a slice of subpath segments).
|
||||||
|
|
||||||
|
It's essentially like pathSubJoin in reverse, and with an explicit slice.
|
||||||
|
*/
|
||||||
|
func pathSlicePipeJoin(sl []string, root string) (out string) {
|
||||||
|
|
||||||
|
out = pathSubJoin(root, sl...)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pathSubJoin is like path.Join except it takes an explicit root
|
||||||
|
and additional slice of subpaths to sequentially join to it.
|
||||||
|
*/
|
||||||
|
func pathSubJoin(root string, elems ...string) (out string) {
|
||||||
|
|
||||||
|
if elems == nil || len(elems) == 0 {
|
||||||
|
out = root
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out = path.Join(
|
||||||
|
root,
|
||||||
|
path.Join(
|
||||||
|
elems...,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
//
|
||||||
|
// OS/PLATFORM
|
||||||
|
//
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
osPathPipeJoin is like pathPipeJoin but uses the rendering OS' path separator (os.PathSeparator).
|
||||||
|
*/
|
||||||
|
func osPathPipeJoin(elems ...string) (out string) {
|
||||||
|
|
||||||
|
var rootIdx int
|
||||||
|
|
||||||
|
if elems == nil || len(elems) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rootIdx = len(elems) - 1
|
||||||
|
out = elems[rootIdx]
|
||||||
|
|
||||||
|
if len(elems) == 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out = osPathSubJoin(out, elems[:rootIdx]...)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// osPathSep returns os.PathSeparator.
|
||||||
|
func osPathSep() (out string) {
|
||||||
|
|
||||||
|
out = string(os.PathSeparator)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// osPathSliceJoin is the OS-specific implementation of pathSliceJoin.
|
||||||
|
func osPathSliceJoin(sl []string) (out string) {
|
||||||
|
out = filepath.Join(sl...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// osPathSlicePipeJoin is the OS-specific implementation of pathSlicePipeJoin.
|
||||||
|
func osPathSlicePipeJoin(sl []string, root string) (out string) {
|
||||||
|
|
||||||
|
out = osPathSubJoin(root, sl...)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// osPathSubJoin is the OS-specific implementation of pathSubJoin.
|
||||||
|
func osPathSubJoin(root string, elems ...string) (out string) {
|
||||||
|
|
||||||
|
if elems == nil || len(elems) == 0 {
|
||||||
|
out = root
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out = filepath.Join(
|
||||||
|
root,
|
||||||
|
filepath.Join(
|
||||||
|
elems...,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
52
tplx/sprigx/funcs_tpl_strings.go
Normal file
52
tplx/sprigx/funcs_tpl_strings.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package sprigx
|
||||||
|
|
||||||
|
import (
|
||||||
|
`strings`
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
extIndent serves as a much more flexible alternative to the Sprig `indent`.
|
||||||
|
|
||||||
|
It has 6 arguments (the last of which may be passed in via pipeline):
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
(In fact, if indentString is set to "\n" and levels is always set to 1, this function can even be used to doubelspace text!)
|
||||||
|
* input: The text to be indented. Because it is the last argument, `extIndent` works with pipelined text as well.
|
||||||
|
|
||||||
|
*/
|
||||||
|
func extIndent(levels int, skipFirst, skipEmpty, skipWhitespace bool, indentString, input string) (out string) {
|
||||||
|
|
||||||
|
var idx int
|
||||||
|
var pad string
|
||||||
|
var line string
|
||||||
|
var lines []string
|
||||||
|
|
||||||
|
if levels <= 0 {
|
||||||
|
out = input
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pad = strings.Repeat(indentString, levels)
|
||||||
|
lines = strings.Split(input, "\n")
|
||||||
|
|
||||||
|
for idx, line = range lines {
|
||||||
|
if idx == 0 && skipFirst {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if skipWhitespace && strings.TrimSpace(line) == "" && line != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if skipEmpty && (line == "" || line == "\r") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lines[idx] = pad + line
|
||||||
|
}
|
||||||
|
|
||||||
|
out = strings.Join(lines, "\n")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
47
tplx/sprigx/funcs_tpl_sys.go
Normal file
47
tplx/sprigx/funcs_tpl_sys.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package sprigx
|
||||||
|
|
||||||
|
import (
|
||||||
|
`fmt`
|
||||||
|
`runtime`
|
||||||
|
)
|
||||||
|
|
||||||
|
// sysRuntime returns various information from [runtime].
|
||||||
|
func sysRuntime() (out map[string]string) {
|
||||||
|
|
||||||
|
out = map[string]string{
|
||||||
|
"compiler": runtime.Compiler,
|
||||||
|
"arch": runtime.GOARCH,
|
||||||
|
"os": runtime.GOOS,
|
||||||
|
"maxprocs": fmt.Sprintf("%d", runtime.GOMAXPROCS(-1)),
|
||||||
|
"cpu_cnt": fmt.Sprintf("%d", runtime.NumCPU()),
|
||||||
|
"num_cgo": fmt.Sprintf("%d", runtime.NumCgoCall()),
|
||||||
|
"num_go": fmt.Sprintf("%d", runtime.NumGoroutine()),
|
||||||
|
"go_ver": runtime.Version(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// sysArch returns [runtime.GOARCH].
|
||||||
|
func sysArch() (out string) {
|
||||||
|
|
||||||
|
out = runtime.GOARCH
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// sysNumCpu returns the reuslt from [runtime.NumCPU].
|
||||||
|
func sysNumCpu() (out string) {
|
||||||
|
|
||||||
|
out = fmt.Sprintf("%d", runtime.NumCPU())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// sysOsNm returns [runtime.GOOS].
|
||||||
|
func sysOsNm() (out string) {
|
||||||
|
|
||||||
|
out = runtime.GOOS
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user