diff --git a/.githooks/pre-commit/01-docgen b/.githooks/pre-commit/01-docgen index 2e09bd4..8158eef 100755 --- a/.githooks/pre-commit/01-docgen +++ b/.githooks/pre-commit/01-docgen @@ -19,6 +19,12 @@ for f in $(find . -type f -iname "README.adoc"); do asciidoctor -a ROOTDIR="${orig}/" -o "${newf}" "${f}" echo "Generated ${newf} from ${f}" git add "${newf}" + if command -v asciidoctor-pdf &> /dev/null; + then + newf="${pfx}.pdf" + + asciidoctor-pdf -a ROOTDIR="${orig}/" -o "${newf}" "${f}" + fi if command -v pandoc &> /dev/null; then newf="${pfx}.md" diff --git a/.gitignore b/.gitignore index cca14b4..3b4a1a2 100644 --- a/.gitignore +++ b/.gitignore @@ -19,12 +19,13 @@ .idea/ # https://github.com/github/gitignore/blob/master/Go.gitignore -# Binaries for programs and plugins +# Binaries for programs and plugins and other data *.exe *.exe~ *.dll *.so *.dylib +*.pdf # Test binary, built with `go test -c` *.test diff --git a/TODO b/TODO new file mode 100644 index 0000000..45ac5eb --- /dev/null +++ b/TODO @@ -0,0 +1 @@ +- validx: validator functions for https://pkg.go.dev/github.com/go-playground/validator/v10 diff --git a/go.sum b/go.sum index 12a6440..34e829b 100644 --- a/go.sum +++ b/go.sum @@ -69,3 +69,4 @@ golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 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.16.2/go.mod h1:iXK+ALOwIdRKjAJIE5USlkZ669SVDHBNNuYhunsznH8= diff --git a/tplx/sprigx/README.adoc b/tplx/sprigx/README.adoc index f0802a6..c361be2 100644 --- a/tplx/sprigx/README.adoc +++ b/tplx/sprigx/README.adoc @@ -14,20 +14,37 @@ Last rendered {localdatetime} :toclevels: 7 :source-highlighter: rouge :docinfo: shared +// BEGIN variable attributes +:sprig_ver: 3 +:psutil_ver: 4 +:mod_me: r00t2.io/goutils +:pkg_me: tplx/sprigx +:src_root: https://git.r00t2.io +:godoc_root: https://pkg.go.dev +:sprig_web: https://masterminds.github.io/sprig +:mod_sprig: github.com/Masterminds/sprig/v{sprig_ver} +:mod_psutil: github.com/shirou/gopsutil/v{psutil_ver} +:import_sprig: {mod_sprig} +:src_base: {src_root}/r00t2/go_goutils/src/branch/master +:src_dir: {src_base}/{pkg_me} +:import_me: {mod_me}/{pkg_me} +:godoc_me: {godoc_root}/{import_me} +:godoc_sprig: {godoc_root}/{import_sprig} +// END variable attributes [id="wat"] == What is SprigX? -SprigX is a suite of extensions to https://masterminds.github.io/sprig/[the `sprig` library^] (https://pkg.go.dev/github.com/Masterminds/sprig/v3[Go docs^]). +SprigX is a suite of extensions to {sprig_web}/[the `sprig` library^] ({godoc_sprig}[Go docs^]). They provide functions that offer more enriched use cases and domain-specific data. [TIP] ==== -If you are reading this README on the Go Module Directory documentation (https://pkg.go.dev/r00t2.io/goutils/tplx/sprigx) -or the directory landing page (https://git.r00t2.io/r00t2/go_goutils/src/branch/master/tplx/sprigx), it may not render correctly. +If you are reading this README on the Go Module Directory documentation ({godoc_me}) +or the directory landing page ({src_dir}), it may not render correctly. -Be sure to view it at properly via https://git.r00t2.io/r00t2/go_goutils/src/branch/master/tplx/sprigx/README.adoc[the AsciiDoc rendering^] -or by downloading and viewing the https://git.r00t2.io/r00t2/go_goutils/raw/branch/master/tplx/sprigx/README.html[HTML version^]. +Be sure to view it at properly via {src_dir}/README.adoc[the AsciiDoc rendering^] +or by downloading and viewing the {src_dir}/README.html[HTML version^] and/or {src_dir}/README.pdf[PDF version^]. ==== [id="use"] @@ -38,7 +55,7 @@ The same way you would `sprig`! [%collapsible] .Like this. ==== -[source,go] +[source,go,subs="attributes"] ---- package main @@ -46,7 +63,7 @@ import ( htmlTplLib "html/template" txtTplLib "text/template" - "r00t2.io/goutils/tplx/sprigx" + "{import_me}" ) var ( @@ -69,15 +86,15 @@ They can even be combined/used together. [%collapsible] .Like this. ==== -[source,go] +[source,go,subs="attributes"] ---- package main import ( "text/template" - "github.com/Masterminds/sprig/v3" - "r00t2.io/goutils/tplx/sprigx" + "{import_sprig}" + "{import_me}" ) var txtTpl *template.Template = template. @@ -113,15 +130,15 @@ this will use `foo` from `sprigx` [%collapsible] .(show) ==== -[source,go] +[source,go,subs="attributes"] ---- package main import ( "text/template" - "github.com/Masterminds/sprig/v3" - "r00t2.io/goutils/tplx/sprigx" + "{import_sprig}" + "{import_me}" ) const ( @@ -145,15 +162,15 @@ whereas this will use `foo` from `sprig` [%collapsible] .(show) ==== -[source,go] +[source,go,subs="attributes"] ---- package main import ( "text/template" - "github.com/Masterminds/sprig/v3" - "r00t2.io/goutils/tplx/sprigx" + "{import_sprig}" + "{import_me}" ) const ( @@ -179,15 +196,15 @@ and a function can even be explicitly [[override]]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] +[source,go,subs="attributes"] ---- package main import ( "text/template" - "github.com/Masterminds/sprig/v3" - "r00t2.io/goutils/tplx/sprigx" + "{import_sprig}" + "{import_me}" ) const ( @@ -227,7 +244,7 @@ func CombinedFuncMap(preferSprigX bool) (fmap map[string]any) ---- This function returns a generic function map (like <>) combined with -https://pkg.go.dev/github.com/Masterminds/sprig/v3#GenericFuncMap[`github.com/Masterminds/sprig/v3.GenericFuncMap`^]. +{godoc_sprig}#GenericFuncMap[`{import_sprig}.GenericFuncMap`^]. If `preferSprigx` is true, SprigX function names will override Sprig functions with the same name. If false, Sprig functions will override conflicting SprigX functions with the same name. @@ -240,11 +257,11 @@ as they wrap this with the appropriate type. [source,go] .Function Signature ---- -func CombinedHtmlFuncMap(preferSprigX bool) (fmap (html/template).FuncMap) +func CombinedHtmlFuncMap(preferSprigX bool) (fmap template.FuncMap) ---- -This function returns an https://pkg.go.dev/html/template#FuncMap[`(html/template).FuncMap`] function map (like <>) combined with -https://pkg.go.dev/github.com/Masterminds/sprig/v3#HtmlFuncMap[`github.com/Masterminds/sprig/v3.HtmlFuncMap`^]. +This function returns an {godoc_root}/html/template#FuncMap[`html/template.FuncMap`] function map (like <>) combined with +{godoc_sprig}#HtmlFuncMap[`github.com/Masterminds/sprig/v3.HtmlFuncMap`^]. If `preferSprigx` is true, SprigX function names will override Sprig functions with the same name. If false, Sprig functions will override conflicting SprigX functions with the same name. @@ -254,11 +271,11 @@ If false, Sprig functions will override conflicting SprigX functions with the sa [source,go] .Function Signature ---- -func CombinedTxtFuncMap(preferSprigX bool) (fmap (text/template).FuncMap) +func CombinedTxtFuncMap(preferSprigX bool) (fmap template.FuncMap) ---- -This function returns a https://pkg.go.dev/text/template#FuncMap[`(text/template).FuncMap`] function map (like <>) combined with -https://pkg.go.dev/github.com/Masterminds/sprig/v3#TxtFuncMap[`github.com/Masterminds/sprig/v3.TxtFuncMap`^]. +This function returns a {godoc_root}/text/template#FuncMap[`text/template.FuncMap`] function map (like <>) combined with +{godoc_sprig}#TxtFuncMap[`github.com/Masterminds/sprig/v3.TxtFuncMap`^]. If `preferSprigx` is true, SprigX function names will override Sprig functions with the same name. If false, Sprig functions will override conflicting SprigX functions with the same name. @@ -281,10 +298,10 @@ as they wrap this with the appropriate type. [source,go] .Function Signature ---- -func HtmlFuncMap() (fmap (html/template).FuncMap) +func HtmlFuncMap() (fmap template.FuncMap) ---- -This function returns a SprigX https://pkg.go.dev/html/template#FuncMap[`(html/template).FuncMap`^]. +This function returns a SprigX {godoc_root}/html/template#FuncMap[`html/template.FuncMap`^]. [id="lib_nop"] === `Nop` @@ -304,17 +321,24 @@ It will *never* error or panic, and `s` is *always* an empty string. [source,go] .Function Signature ---- -func TxtFuncMap() (fmap (text/template).FuncMap) +func TxtFuncMap() (fmap template.FuncMap) ---- -This function returns a SprigX https://pkg.go.dev/text/template#FuncMap[`(text/template).FuncMap`^]. +This function returns a SprigX {godoc_root}/text/template#FuncMap[`text/template.FuncMap`^]. [id="fn"] == Template Functions Expect this list to grow over time, and potentially more frequently than the `sprigx` functions. -Each function includes its function signature to indicate what types of arguments/parameters it accepts, -what it returns, and if it may potentially return an error or not. +Each function includes its *_Function Signature_* to indicate what arguments/parameters it accepts, their type(s), +what it returns, and the returned value(s) type(s). + +Because Go template functions can only return either: + +* a single value of any type, or +* a value of any type and an `error` (in that order) + +you can easily determine whether a function can return an error or not by simply referring to the Function Signature. [id="fn_dbg"] === Debugging @@ -327,7 +351,7 @@ what it returns, and if it may potentially return an error or not. func dump(a ...interface{}) (out string) ---- -The `dump` function directly calls https://pkg.go.dev/github.com/davecgh/go-spew/spew#Sdump[`github.com/davecgh/go-spew/spew.Sdump`^] +The `dump` function directly calls {godoc_root}/davecgh/go-spew/spew#Sdump[`github.com/davecgh/go-spew/spew.Sdump`^] for whatever object(s) is/are passed to it. [id="fn_meta"] @@ -343,7 +367,307 @@ func metaIsNil(obj any) (isNil bool) `metaIsNil` returns `true` if `obj` is explicitly nil, otherwise it returns false. -This function fills in the gap that https://pkg.go.dev/text/template#IsTrue[`text/template.IsTrue`^] and https://pkg.go.dev/html/template#IsTrue[`html/template.IsTrue`^] (expressed in templates as `{{ if ... }}`) leaves, as those functions/expressions return false for e.g. `false` booleans AND nils. +This function fills in the gap that {godoc_root}/text/template#IsTrue[`text/template.IsTrue`^] and {godoc_root}/html/template#IsTrue[`html/template.IsTrue`^] (expressed in templates as `{{ if ... }}`) leaves, as those functions/expressions return false for e.g. `false` booleans AND nils. + +[id="fn_net_all"] +=== Networking +These template functions use capabilities from: + +* <> +* <> +* <> + +The function prefix is used to indicate which module/package a function is added from. + +[id="fn_net"] +==== `net` +These template functions contain capabilities from {godoc_root}/net[`net`^]. + +[id="fn_net_cidrmask"] +===== `netCidrMask` +[source,go] +.Function Signature +---- +func netCidrMask(ones, bits int) (mask net.IPMask) +---- + +`netCidrMask` directly calls {godoc_root}/net#CIDRMask[`net.CIDRMask`^]. + +[id="fn_net_cidra"] +===== `netExtractAddr` +[source,go] +.Function Signature +---- +func netExtractAddr(s string) (addr net.IP, err error) +---- + +`netExtractAddr` wraps {godoc_root}/net#ParseCIDR[`net.ParseCIDR`^] and returns the {godoc_root}/net#IP[`net.IP`^] component. + +[id="fn_net_hph"] +===== `netExtractHost` +[source,go] +.Function Signature +---- +func netExtractHost(hostPort string) (host string, err error) +---- + +`netExtractHost` wraps {godoc_root}/net#SplitHostPort[`net.SplitHostPort`^] and returns the host component (as a string). + +[id="fn_net_cidrn"] +===== `netExtractIpnet` +[source,go] +.Function Signature +---- +func netExtractIpnet(s string) (ipNet *net.IPNet, err error) +---- + +`netExtractIpnet` wraps {godoc_root}/net#ParseCIDR[`net.ParseCIDR`^] and returns the {godoc_root}/net#IPNet[`net.IPNet`^] component. + +[id="fn_net_hpp"] +===== `netExtractPort` +[source,go] +.Function Signature +---- +func netExtractPort(hostPort string) (port uint16, err error) +---- + +`netExtractPort` wraps {godoc_root}/net#SplitHostPort[`net.SplitHostPort`^] and returns the port component (as a uint16). + +[id='fn_net_ifaces'] +===== `netIfaces` +[source,go] +.Function Signature +---- +func netIfaces() (ifaces []net.Interface, err error) +---- + +`netIfaces` directly calls {godoc_root}/net#Interfaces[`net.Interfaces`^]. + +[id="fn_net_ip4mask"] +===== `netIp4Mask` +[source,go] +.Function Signature +---- +func netIp4Mask(a, b, c, d any) (mask net.IPMask, err error) +---- + +`netIp4Mask` wraps {godoc_root}/net#IPv4Mask[`net.IPv4Mask`^]. + +It is wrapped so that `a`, `b`, `c`, and `d` may be a string: + +[source,gotemplate] +---- +{{- $mask := netIp4Mask "198" "51" "100" "10" -}} +---- + +or integers/other numeric: + +[source,gotemplate] +---- +{{- $mask := netIp4Mask 198 51 100 10 -}} +---- + +or bytes: + +[source,gotemplate] +---- +{{- $mask := netIp4Mask 0xc6 0x33 0x64 0x0a -}} +---- + +or even a mix: + +[source,gotemplate] +---- +{{- $mask := netIp4Mask "198" 51 "100" 0x0a -}} +---- + +[id="fn_net_jhp"] +===== `netJoinHostPort` +[source,go] +.Function Signature +---- +func netJoinHostPort(host, port string) (out string) +---- + +`netJoinHostPort` directly calls {godoc_root}/net#JoinHostPort[`net.JoinHostPort`^]. + +[id="fn_net_parseip"] +===== `netParseIP` +[source,go] +.Function Signature +---- +func netParseIP(s string) (ip net.IP) +---- + +`netParseIP` directly calls {godoc_root}/net#ParseIP[`net.ParseIP`^]. + +[id="fn_netip"] +==== `net/netip` +These template functions contain capabilities from {godoc_root}/net/netip[`net/netip`^]. + +[id="fn_netip_addrport"] +===== `netipAddrPort` +[source,go] +.Function Signature +---- +func netipAddrPort(ip netip.Addr, port uint16) (addrPort netip.AddrPort) +---- + +`netipAddrPort` directly calls {godoc_root}/net/netip#AddrPortFrom[`net/netip.AddrPortFrom`^]. + +[id="fn_netip_parseaddr"] +===== `netipParseAddr` +[source,go] +.Function Signature +---- +func netipParseAddr(s string) (addr netip.Addr, err error) +---- + +`netipParseAddr` directly calls {godoc_root}/net/netip#ParseAddr[`net/netip.ParseAddr`^]. + +[id="fn_netip_pap"] +===== `netipParseAddrPort` +[source,go] +.Function Signature +---- +func netipParseAddrPort(s string) (addrPort netip.AddrPort, err error) +---- + +`netipParseAddrPort` directly calls {godoc_root}/net/netip#ParseAddrPort[`net/netip.ParseAddrPort`^]. + +[id="fn_netip_parsepfx"] +===== `netipParsePrefix` +[source,go] +.Function Signature +---- +func netipParsePrefix(s string) (pfx netip.Prefix, err error) +---- + +`netipParsePrefix` directly calls {godoc_root}/net/netip#ParsePrefix[`net/netip.ParsePrefix`^]. + +[id="fn_netip_pfx"] +===== `netipPrefix` +[source,go] +.Function Signature +---- +func netipPrefix(ip netip.Addr, bits int) (pfx netip.Prefix) +---- + +`netipPrefix` directly calls {godoc_root}/net/netip#PrefixFrom[`net/netip.PrefixFrom`^]. + +[id="fn_netipx"] +==== `go4.org/netipx` +These template functions contain capabilities from {godoc_root}/go4.org/netipx[`go4.org/netipx`^]. + +[id="fn_netipx_addripnet"] +===== `netipxAddrIpNet` +[source,go] +.Function Signature +---- +func netipxAddrIpNet(addr netip.Addr) (ipNet *net.IPNet) +---- + +`netipxAddrIpNet` directly calls {godoc_root}/go4.org/netipx#AddrIPNet[`go4.org/netipx.AddrIPNet`^]. + +[id="fn_netipx_cmppfx"] +===== `netipxCmpPfx` +[source,go] +.Function Signature +---- +func netipxCmpPfx(a, b netip.Prefix) (cmp int) +---- + +`netipxCmpPfx` directly calls {godoc_root}/go4.org/netipx#ComparePrefix[`go4.org/netipx.ComparePrefix`^]. + +[id="fn_netipx_fromstdaddr"] +===== `netipxFromStdAddr` +[source,go] +.Function Signature +---- +func netipxFromStdAddr(ip net.IP, port int, zone string) (addrPort netip.AddrPort, err error) +---- + +`netipxFromStdAddr` wraps {godoc_root}/go4.org/netipx#FromStdAddr[`go4.org/netipx.FromStdAddr`^]. Instead of returning a boolean as the second value, it will instead be an error if the wrapped boolean is false. + +[id="fn_netipx_fromip"] +===== `netipxFromIp` +[source,go] +.Function Signature +---- +func netipxFromIp(ip net.IP) (addr netip.Addr, err error) +---- + +`netipxFromIp` wraps {godoc_root}/go4.org/netipx#FromStdIP[`go4.org/netipx.FromStdIP`^]. Instead of returning a boolean as the second value, it will instead be an error if the wrapped boolean is false. + +[id="fn_netipx_fromipnet"] +===== `netipxFromIpNet` +[source,go] +.Function Signature +---- +func netipxFromIpNet(ipNet *net.IPNet) (pfx netip.Prefix, err error) +---- + +`netipxFromIpNet` wraps {godoc_root}/go4.org/netipx#FromStdIPNet[`go4.org/netipx.FromStdIPNet`^]. Instead of returning a boolean as the second value, it will instead be an error if the wrapped boolean is false. + +[id="fn_netipx_parserange"] +===== `netipxParseRange` +[source,go] +.Function Signature +---- +func netipxParseRange(s string) (ipRange netipx.IPRange, err error) +---- + +`netipxRange` directly calls {godoc_root}/go4.org/netipx#ParseIPRange[`go4.org/netipx.ParseIPRange`^]. + +[id="fn_netipx_pfxaddr"] +===== `netipxPfxAddr` +[source,go] +.Function Signature +---- +func netipxPfxAddr(s string) (addr netip.Addr, err error) +---- + +`netipxPfxAddr` directly calls {godoc_root}/go4.org/netipx#ParsePrefixOrAddr[`go4.org/netipx.ParsePrefixOrAddr`^]. + +[id="fn_netipx_pfxipnet"] +===== `netipxPfxIpNet` +[source,go] +.Function Signature +---- +func netipxPfxIpNet(pfx netip.Prefix) (ipNet *net.IPNet) +---- + +`netipxPfxIpNet` directly calls {godoc_root}/go4.org/netipx#PrefixIPNet[`go4.org/netipx.PrefixIPNet`^]. + +[id="fn_netipx_pfxlast"] +===== `netipxPfxLast` +[source,go] +.Function Signature +---- +func netipxPfxLast(pfx netip.Prefix) (addr netip.Addr) +---- + +`netipxPfxLast` directly calls {godoc_root}/go4.org/netipx#PrefixLastIP[`go4.org/netipx.PrefixLastIP`^]. + +[id="fn_netipx_pfxrange"] +===== `netipxPfxRange` +[source,go] +.Function Signature +---- +func netipxPfxRange(pfx netip.Prefix) (ipRange netipx.IPRange) +---- + +`netipxPfxRange` directly calls {godoc_root}/go4.org/netipx#RangeOfPrefix[`go4.org/netipx.RangeOfPrefix`^]. + +[id="fn_netipx_range"] +===== `netipxRange` +[source,go] +.Function Signature +---- +func netipxRange(from, to netip.Addr) (ipRange netipx.IPRange) +---- + +`netipxRange` directly calls {godoc_root}/go4.org/netipx#IPRangeFrom[`go4.org/netipx.IPRangeFrom`^]. [id="fn_num"] === Numbers/Math @@ -401,7 +725,7 @@ func numFloatStr(val any) (s string, err error) func osFQDN() (fqdn string, err error) ---- -`osFQDN` currently just directly calls https://pkg.go.dev/os#Hostname[`os.Hostname`^]. +`osFQDN` currently just directly calls {godoc_root}/os#Hostname[`os.Hostname`^]. As such, it comes with the same caveats -- namely that it isn't guaranteed to be an FQDN, it will be precisely/exactly whatever the kernel/OS hostname is set as. @@ -410,7 +734,7 @@ In the future, it may be extended to support a more diligent effort to determine an actual FQDN, and return an error if it is unable to be derived. To (relatively) predictably get the "short hostname", use <>. -To directly/predictably use https://pkg.go.dev/os#Hostname[`os.Hostname`^], use <>. +To directly/predictably use {godoc_root}/os#Hostname[`os.Hostname`^], use <>. [id="fn_os_grpid"] ==== `osGroupById` @@ -420,9 +744,9 @@ To directly/predictably use https://pkg.go.dev/os#Hostname[`os.Hostname`^], use func osGroupById[T string | int](gid T) (g *user.Group, err error) ---- -`osGroupById` returns an https://pkg.go.dev/os/user#Group[`os/user.Group`^] from a given group ID/GID. +`osGroupById` returns an {godoc_root}/os/user#Group[`os/user.Group`^] from a given group ID/GID. -It more or less behaves exactly like https://pkg.go.dev/os/user#LookupGroupId[`os/user.LookupGroupId`^], +It more or less behaves exactly like {godoc_root}/os/user#LookupGroupId[`os/user.LookupGroupId`^], except it will accept either a `string` *or* an `int` as the GID. [id="fn_os_grpnm"] @@ -433,9 +757,9 @@ except it will accept either a `string` *or* an `int` as the GID. func osGroupByName(grpNm string) (g *user.Group, err error) ---- -`osGroupByName` returns an https://pkg.go.dev/os/user#Group[`os/user.Group`^] from a given group name. +`osGroupByName` returns an {godoc_root}/os/user#Group[`os/user.Group`^] from a given group name. -It behaves exactly like https://pkg.go.dev/os/user#LookupGroup[`os/user.LookupGroup`^]. +It behaves exactly like {godoc_root}/os/user#LookupGroup[`os/user.LookupGroup`^]. [id="fn_os_hst"] ==== `osHost` @@ -445,8 +769,8 @@ It behaves exactly like https://pkg.go.dev/os/user#LookupGroup[`os/user.LookupGr func osHost() (out string, err error) ---- -`osHost` returns the "short hostname" by calling https://pkg.go.dev/os#Hostname[`os.Hostname`^] -and returning the first "host label" (as RFCs refer to it). +`osHost` returns the "short hostname" by calling {godoc_root}/os#Hostname[`os.Hostname`^] +and returning the first "host label" (as RFCs refer to it). This is commonly/colloquially called the "hostname" or "hostname without the domain part". e.g.: @@ -460,11 +784,11 @@ osHost {{ $h }} should be equal to first label of FQDN {{ $cmp }}. [TIP] ==== -The `splitList` function shown aboce is from the https://masterminds.github.io/sprig/string_slice.html[`sprig` string slice functions^]. +The `splitList` function shown above is from the {sprig_web}/string_slice.html[`sprig` string slice functions^]. ==== To (try to) get the FQDN, use <>. -To directly use https://pkg.go.dev/os#Hostname[`os.Hostname`^], use <>. +To directly use {godoc_root}/os#Hostname[`os.Hostname`^], use <>. [id="fn_os_hstnm"] ==== `osHostname` @@ -474,7 +798,7 @@ To directly use https://pkg.go.dev/os#Hostname[`os.Hostname`^], use <> to conditionally format path base func osPathJoin(elem ...string) (out string) ---- -`osPathJoin` directly calls https://pkg.go.dev/path/filepath#Join[`path/filepath.Join`^]. +`osPathJoin` directly calls {godoc_root}/path/filepath#Join[`path/filepath.Join`^]. [WARNING] ==== @@ -799,7 +1123,7 @@ a/b/c func osPathSep() (out string) ---- -`osPathSep` returns the https://pkg.go.dev/os#PathSeparator[`os.PathSeparator`^] for this OS. +`osPathSep` returns the {godoc_root}/os#PathSeparator[`os.PathSeparator`^] for this OS. [source,gotemplate] ---- @@ -834,7 +1158,7 @@ func osPathSliceJoin(sl []string) (out string) [TIP] ==== -The `splitList` function shown below is from the https://masterminds.github.io/sprig/string_slice.html[`sprig` string slice functions^]. +The `splitList` function shown below is from the {sprig_web}/string_slice.html[`sprig` string slice functions^]. ==== [source,gotemplate] @@ -877,7 +1201,7 @@ func osPathSlicePipeJoin(sl []string, root string) (out string) [TIP] ==== -The `splitList` function shown below is from the https://masterminds.github.io/sprig/string_slice.html[`sprig` string slice functions^]. +The `splitList` function shown below is from the {sprig_web}/string_slice.html[`sprig` string slice functions^]. ==== [source,gotemplate] @@ -947,7 +1271,7 @@ renders as: [id="fn_ps"] === PSUtil -These are functions from https://pkg.go.dev/github.com/shirou/gopsutil/v4[`github.com/shirou/gopsutil/v4`^] packages. +These are functions from {godoc_root}/{mod_psutil}[`{mod_psutil}`^] packages. [id="fn_ps_cpu"] ==== CPU/Processor @@ -960,17 +1284,17 @@ These are functions from https://pkg.go.dev/github.com/shirou/gopsutil/v4[`githu func psCpuCnts(logical bool) (numCpu int, err error) ---- -`psCpuCnts` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/cpu#Counts[`github.com/shirou/gopsutil/v4/cpu.Counts`^]. +`psCpuCnts` directly calls {godoc_root}/{mod_psutil}/cpu#Counts[`{mod_psutil}/cpu.Counts`^]. [id="fn_ps_cpu_info"] ===== `psCpuInfo` [source,go] .Function Signature ---- -func psCpuInfo() (cpuInfo [](github.com/shirou/gopsutil/v4/cpu).Info, err error) +func psCpuInfo() (cpuInfo []cpu.Info, err error) ---- -`psCpuInfo` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/cpu#Info[`github.com/shirou/gopsutil/v4/cpu.Info`^]. +`psCpuInfo` directly calls {godoc_root}/{mod_psutil}/cpu#Info[`{mod_psutil}/cpu.Info`^]. [id="fn_ps_cpu_pct"] ===== `psCpuPct` @@ -980,17 +1304,17 @@ func psCpuInfo() (cpuInfo [](github.com/shirou/gopsutil/v4/cpu).Info, err error) func psCpuPct(interval time.Duration, percpu bool) (pcts []float64, err error) ---- -`psCpuPct` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/cpu#Percent[`github.com/shirou/gopsutil/v4/cpu.Percent`^]. +`psCpuPct` directly calls {godoc_root}/{mod_psutil}/cpu#Percent[`{mod_psutil}/cpu.Percent`^]. [id="fn_ps_cpu_tms"] ===== `psCpuTimes` [source,go] .Function Signature ---- -func psCpuTimes(percpu bool) (cpuTimes []TimesStat, err error) +func psCpuTimes(percpu bool) (cpuTimes []cpu.TimesStat, err error) ---- -`psCpuTimes` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/cpu#Times[`github.com/shirou/gopsutil/v4/cpu.Times`^]. +`psCpuTimes` directly calls {godoc_root}/{mod_psutil}/cpu#Times[`{mod_psutil}/cpu.Times`^]. [id="fn_ps_dsk"] ==== Disk @@ -1000,10 +1324,10 @@ func psCpuTimes(percpu bool) (cpuTimes []TimesStat, err error) [source,go] .Function Signature ---- -func psDiskIoCnts(names ...string) (stats map[string]IOCountersStat, err error) +func psDiskIoCnts(names ...string) (stats map[string]disk.IOCountersStat, err error) ---- -`psDiskIoCnts` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/disk#IOCounters[`github.com/shirou/gopsutil/v4/disk.IOCounters`^]. +`psDiskIoCnts` directly calls {godoc_root}/{mod_psutil}/disk#IOCounters[`{mod_psutil}/disk.IOCounters`^]. [id="fn_ps_dsk_lbl"] ===== `psDiskLabel` @@ -1013,17 +1337,17 @@ func psDiskIoCnts(names ...string) (stats map[string]IOCountersStat, err error) func psDiskLabel(name string) (label string, err error) ---- -`psDiskLabel` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/disk#Label[`github.com/shirou/gopsutil/v4/disk.Label`^]. +`psDiskLabel` directly calls {godoc_root}/{mod_psutil}/disk#Label[`{mod_psutil}/disk.Label`^]. [id="fn_ps_dsk_parts"] ===== `psDiskParts` [source,go] .Function Signature ---- -func psDiskParts(all bool) (parts [](github.com/shirou/gopsutil/v4/disk).PartitionStat, err error) +func psDiskParts(all bool) (parts []disk.PartitionStat, err error) ---- -`psDiskParts` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/disk#Partitions[`github.com/shirou/gopsutil/v4/disk.Partitions`^]. +`psDiskParts` directly calls {godoc_root}/{mod_psutil}/disk#Partitions[`{mod_psutil}/disk.Partitions`^]. [id="fn_ps_dsk_srl"] ===== `psDiskSerial` @@ -1033,17 +1357,17 @@ func psDiskParts(all bool) (parts [](github.com/shirou/gopsutil/v4/disk).Partiti func psDiskSerial(name string) (serial string, err error) ---- -`psDiskSerial` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/disk#SerialNumber[`github.com/shirou/gopsutil/v4/disk.SerialNumber`^]. +`psDiskSerial` directly calls {godoc_root}/{mod_psutil}/disk#SerialNumber[`{mod_psutil}/disk.SerialNumber`^]. [id="fn_ps_dsk_usg"] ===== `psDiskUsage` [source,go] .Function Signature ---- -func psDiskUsage(path string) (usage *(github.com/shirou/gopsutil/v4/disk).UsageStat, err error) +func psDiskUsage(path string) (usage *disk.UsageStat, err error) ---- -`psDiskUsage` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/disk#Usage[`github.com/shirou/gopsutil/v4/disk.Usage`^]. +`psDiskUsage` directly calls {godoc_root}/{mod_psutil}/disk#Usage[`{mod_psutil}/disk.Usage`^]. [id="fn_ps_hst"] ==== Host @@ -1056,7 +1380,7 @@ func psDiskUsage(path string) (usage *(github.com/shirou/gopsutil/v4/disk).Usage func psHostBoot() (bootEpoch uint64, err error) ---- -`psHostBoot` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/host#BootTime[`github.com/shirou/gopsutil/v4/host.BootTime`^]. +`psHostBoot` directly calls {godoc_root}/{mod_psutil}/host#BootTime[`{mod_psutil}/host.BootTime`^]. [id="fn_ps_hst_id"] ===== `psHostId` @@ -1066,17 +1390,17 @@ func psHostBoot() (bootEpoch uint64, err error) func psHostId() (hostId string, err error) ---- -`psHostId` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/host#HostID[`github.com/shirou/gopsutil/v4/host.HostID`^]. +`psHostId` directly calls {godoc_root}/{mod_psutil}/host#HostID[`{mod_psutil}/host.HostID`^]. [id="fn_ps_hst_info"] ===== `psHostInfo` [source,go] .Function Signature ---- -func psHostInfo() (info *(github.com/shirou/gopsutil/v4/host).InfoStat, err error) +func psHostInfo() (info *host.InfoStat, err error) ---- -`psHostInfo` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/host#Info[`github.com/shirou/gopsutil/v4/host.Info`^]. +`psHostInfo` directly calls {godoc_root}/{mod_psutil}/host#Info[`{mod_psutil}/host.Info`^]. [id="fn_ps_hst_krnarch"] ===== `psHostKernArch` @@ -1086,7 +1410,7 @@ func psHostInfo() (info *(github.com/shirou/gopsutil/v4/host).InfoStat, err erro func psHostKernArch() (arch string, err error) ---- -`psHostKernArch` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/host#KernelArch[`github.com/shirou/gopsutil/v4/host.KernelArch`^]. +`psHostKernArch` directly calls {godoc_root}/{mod_psutil}/host#KernelArch[`{mod_psutil}/host.KernelArch`^]. [id="fn_ps_hst_krnver"] ===== `psHostKernVer` @@ -1096,7 +1420,7 @@ func psHostKernArch() (arch string, err error) func psHostKernVer() (ver string, err error) ---- -`psHostKernVer` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/host#KernelVersion[`github.com/shirou/gopsutil/v4/host.KernelVersion`^]. +`psHostKernVer` directly calls {godoc_root}/{mod_psutil}/host#KernelVersion[`{mod_psutil}/host.KernelVersion`^]. [id="fn_ps_hst_plat"] ===== `psHostPlatInfo` @@ -1106,7 +1430,7 @@ func psHostKernVer() (ver string, err error) func psHostPlatInfo() (platInfo [3]string, err error) ---- -`psHostPlatInfo` wraps https://pkg.go.dev/github.com/shirou/gopsutil/v4/host#PlatformInformation[`github.com/shirou/gopsutil/v4/host.PlatformInformation`^]. +`psHostPlatInfo` wraps {godoc_root}/{mod_psutil}/host#PlatformInformation[`{mod_psutil}/host.PlatformInformation`^]. It is necessary to wrap because the function normally returns `(string, string, string, error)` but a template function may only return either a single value (of any type) or a single value of any type and an error, so the three `string` returns are consolidated into an ordered `[3]string`. @@ -1118,17 +1442,17 @@ It is necessary to wrap because the function normally returns `(string, string, func psHostPlatUptime() (uptimeSecs uint64, err error) ---- -`psHostPlatUptime` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/host#Uptime[`github.com/shirou/gopsutil/v4/host.Uptime`^]. +`psHostPlatUptime` directly calls {godoc_root}/{mod_psutil}/host#Uptime[`{mod_psutil}/host.Uptime`^]. [id="fn_ps_hst_usrs"] ===== `psHostUsers` [source,go] .Function Signature ---- -func psHostUsers() (users [](github.com/shirou/gopsutil/v4/host).UserStat, err error) +func psHostUsers() (users []host.UserStat, err error) ---- -`psHostUsers` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/host#Users[`github.com/shirou/gopsutil/v4/host.Users`^]. +`psHostUsers` directly calls {godoc_root}/{mod_psutil}/host#Users[`{mod_psutil}/host.Users`^]. [id="fn_ps_hst_virt"] ===== `psHostPlatVirt` @@ -1138,7 +1462,7 @@ func psHostUsers() (users [](github.com/shirou/gopsutil/v4/host).UserStat, err e func psHostVirt() (virtInfo [2]string, err error) ---- -`psHostPlatVirt` wraps https://pkg.go.dev/github.com/shirou/gopsutil/v4/host#Virtualization[`github.com/shirou/gopsutil/v4/host.Virtualization`^]. +`psHostPlatVirt` wraps {godoc_root}/{mod_psutil}/host#Virtualization[`{mod_psutil}/host.Virtualization`^]. It is necessary to wrap because the function normally returns `(string, string, error)` but a template function may only return either a single value (of any type) or a single value of any type and an error, so the two `string` returns are consolidated into an ordered `[2]string`. @@ -1150,20 +1474,20 @@ It is necessary to wrap because the function normally returns `(string, string, [source,go] .Function Signature ---- -func psLoadAvg() (avg *(github.com/shirou/gopsutil/v4/load).AvgStat, err error) +func psLoadAvg() (avg *load.AvgStat, err error) ---- -`psLoadAvg` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/load#Avg[`github.com/shirou/gopsutil/v4/load.Avg`^]. +`psLoadAvg` directly calls {godoc_root}/{mod_psutil}/load#Avg[`{mod_psutil}/load.Avg`^]. [id="fn_ps_ld_misc"] ===== `psLoadMisc` [source,go] .Function Signature ---- -func psLoadMisc() (misc *(github.com/shirou/gopsutil/v4/load).MiscStat, err error) +func psLoadMisc() (misc *load.MiscStat, err error) ---- -`psLoadMisc` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/load#Misc[`github.com/shirou/gopsutil/v4/load.Misc`^]. +`psLoadMisc` directly calls {godoc_root}/{mod_psutil}/load#Misc[`{mod_psutil}/load.Misc`^]. [id="fn_ps_mem"] ==== Memory @@ -1173,7 +1497,7 @@ func psLoadMisc() (misc *(github.com/shirou/gopsutil/v4/load).MiscStat, err erro [source,go] .Function Signature ---- -func psMemExVMem() (exVMem *(github.com/shirou/gopsutil/v4/mem).ExVirtualMemory, err error) +func psMemExVMem() (exVMem *mem.ExVirtualMemory, err error) ---- [WARNING] @@ -1185,42 +1509,42 @@ This function is available on Windows and Linux platforms *only*. ==== This function returns very different types depending on platform. -* Linux: https://pkg.go.dev/github.com/shirou/gopsutil/v4/mem?GOOS=linux#ExVirtualMemory[`mem.ExVirtualMemory`^] -* Windows: https://pkg.go.dev/github.com/shirou/gopsutil/v4/mem?GOOS=windows#ExVirtualMemory[`mem.ExVirtualMemory`^] +* Linux: {godoc_root}/{mod_psutil}/mem?GOOS=linux#ExVirtualMemory[`mem.ExVirtualMemory`^] +* Windows: {godoc_root}/{mod_psutil}/mem?GOOS=windows#ExVirtualMemory[`mem.ExVirtualMemory`^] ==== -This function wraps link:https://pkg.go.dev/github.com/shirou/gopsutil/v4/mem?GOOS=linux#NewExLinux[`github.com/shirou/gopsutil/v4/mem.NewExLinux`^].link:https://pkg.go.dev/github.com/shirou/gopsutil/v4/mem?GOOS=linux#ExLinux.VirtualMemory[`VirtualMemory`^] on Linux and -link:https://pkg.go.dev/github.com/shirou/gopsutil/v4/mem?GOOS=windows#NewExWindows[`github.com/shirou/gopsutil/v4/mem.NewExWindows`^].link:https://pkg.go.dev/github.com/shirou/gopsutil/v4/mem?GOOS=windows#ExWindows.VirtualMemory[`VirtualMemory`^] on Windows. +This function wraps link:{godoc_root}/{mod_psutil}/mem?GOOS=linux#NewExLinux[`{mod_psutil}/mem.NewExLinux`^].link:{godoc_root}/{mod_psutil}/mem?GOOS=linux#ExLinux.VirtualMemory[`VirtualMemory`^] on Linux and +link:{godoc_root}/{mod_psutil}/mem?GOOS=windows#NewExWindows[`{mod_psutil}/mem.NewExWindows`^].link:{godoc_root}/{mod_psutil}/mem?GOOS=windows#ExWindows.VirtualMemory[`VirtualMemory`^] on Windows. [id="fn_ps_mem_swap"] ===== `psMemSwap` [source,go] .Function Signature ---- -func psMemSwap() (swap *(github.com/shirou/gopsutil/v4/mem).SwapMemoryStat, err error) +func psMemSwap() (swap *mem.SwapMemoryStat, err error) ---- -`psMemSwap` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/mem#SwapMemory[`github.com/shirou/gopsutil/v4/mem.SwapMemory`^]. +`psMemSwap` directly calls {godoc_root}/{mod_psutil}/mem#SwapMemory[`{mod_psutil}/mem.SwapMemory`^]. [id="fn_ps_mem_swapdevs"] ===== `psMemSwapDevs` [source,go] .Function Signature ---- -func psMemSwapDevs() (swapDevs []*(github.com/shirou/gopsutil/v4/mem).SwapDevice, err error) +func psMemSwapDevs() (swapDevs []*mem.SwapDevice, err error) ---- -`psMemSwapDevs` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/mem#SwapDevices[`github.com/shirou/gopsutil/v4/mem.SwapDevices`^]. +`psMemSwapDevs` directly calls {godoc_root}/{mod_psutil}/mem#SwapDevices[`{mod_psutil}/mem.SwapDevices`^]. [id="fn_ps_mem_vmem"] ===== `psMemVMem` [source,go] .Function Signature ---- -func psMemVMem() (vmem *(github.com/shirou/gopsutil/v4/mem).VirtualMemoryStat, err error) +func psMemVMem() (vmem *mem.VirtualMemoryStat, err error) ---- -`psMemVMem` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/mem#VirtualMemory[`github.com/shirou/gopsutil/v4/mem.VirtualMemory`^]. +`psMemVMem` directly calls {godoc_root}/{mod_psutil}/mem#VirtualMemory[`{mod_psutil}/mem.VirtualMemory`^]. [id="fn_ps_net"] ==== Network @@ -1230,100 +1554,100 @@ func psMemVMem() (vmem *(github.com/shirou/gopsutil/v4/mem).VirtualMemoryStat, e [source,go] .Function Signature ---- -func psNetConns(kind string) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error) +func psNetConns(kind string) (conns []net.ConnectionStat, err error) ---- -`psNetConns` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#Connections[`github.com/shirou/gopsutil/v4/net.Connections`^]. +`psNetConns` directly calls {godoc_root}/{mod_psutil}/net#Connections[`{mod_psutil}/net.Connections`^]. [id="fn_ps_net_connsmax"] ===== `psNetConnsMax` [source,go] .Function Signature ---- -func psNetConnsMax(kind string, maxConn int) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error) +func psNetConnsMax(kind string, maxConn int) (conns []net.ConnectionStat, err error) ---- -`psNetConnsMax` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#ConnectionsMax[`github.com/shirou/gopsutil/v4/net.ConnectionsMax`^]. +`psNetConnsMax` directly calls {godoc_root}/{mod_psutil}/net#ConnectionsMax[`{mod_psutil}/net.ConnectionsMax`^]. [id="fn_ps_net_connspid"] ===== `psNetConnsPid` [source,go] .Function Signature ---- -func psNetConnsPid(kind string, pid int32) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error) +func psNetConnsPid(kind string, pid int32) (conns []net.ConnectionStat, err error) ---- -`psNetConnsPid` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#ConnectionsPid[`github.com/shirou/gopsutil/v4/net.ConnectionsPid`^]. +`psNetConnsPid` directly calls {godoc_root}/{mod_psutil}/net#ConnectionsPid[`{mod_psutil}/net.ConnectionsPid`^]. [id="fn_ps_net_connspidmax"] ===== `psNetConnsPidMax` [source,go] .Function Signature ---- -func psNetConnsPidMax(kind string, pid int32, maxConn int) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error) +func psNetConnsPidMax(kind string, pid int32, maxConn int) (conns []net.ConnectionStat, err error) ---- -`psNetConnsPidMax` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#ConnectionsPidMax[`github.com/shirou/gopsutil/v4/net.ConnectionsPidMax`^]. +`psNetConnsPidMax` directly calls {godoc_root}/{mod_psutil}/net#ConnectionsPidMax[`{mod_psutil}/net.ConnectionsPidMax`^]. [id="fn_ps_net_ct"] ===== `psNetCTStats` [source,go] .Function Signature ---- -func psNetCTStats(percCpu bool) (ctStats [](github.com/shirou/gopsutil/v4/net).ConntrackStat, err error) +func psNetCTStats(percCpu bool) (ctStats []net.ConntrackStat, err error) ---- -`psNetCTStats` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#ConntrackStats[`github.com/shirou/gopsutil/v4/net.ConntrackStats`^]. +`psNetCTStats` directly calls {godoc_root}/{mod_psutil}/net#ConntrackStats[`{mod_psutil}/net.ConntrackStats`^]. [id="fn_ps_net_ctlist"] ===== `psNetCTStatList` [source,go] .Function Signature ---- -func psNetCTStatList() (ctStats *(github.com/shirou/gopsutil/v4/net).ConntrackStatList, err error) +func psNetCTStatList() (ctStats *net.ConntrackStatList, err error) ---- -`psNetCTStatList` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#ConntrackStatList[`github.com/shirou/gopsutil/v4/net.ConntrackStatList`^]. +`psNetCTStatList` directly calls {godoc_root}/{mod_psutil}/net#ConntrackStatList[`{mod_psutil}/net.ConntrackStatList`^]. [id="fn_ps_net_fltcnt"] ===== `psNetFilterCnts` [source,go] .Function Signature ---- -func psNetFilterCnts() (filterCnts [](github.com/shirou/gopsutil/v4/net).FilterStat, err error) +func psNetFilterCnts() (filterCnts []net.FilterStat, err error) ---- -`psNetFilterCnts` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#FilterCounters[`github.com/shirou/gopsutil/v4/net.FilterCounters`^]. +`psNetFilterCnts` directly calls {godoc_root}/{mod_psutil}/net#FilterCounters[`{mod_psutil}/net.FilterCounters`^]. [id="fn_ps_net_iocnts"] ===== `psNetIoCnts` [source,go] .Function Signature ---- -func psNetIoCnts(perNIC bool) (ioCnts [](github.com/shirou/gopsutil/v4/net).IOCountersStat, err error) +func psNetIoCnts(perNIC bool) (ioCnts []net.IOCountersStat, err error) ---- -`psNetIoCnts` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#IOCounters[`github.com/shirou/gopsutil/v4/net.IOCounters`^]. +`psNetIoCnts` directly calls {godoc_root}/{mod_psutil}/net#IOCounters[`{mod_psutil}/net.IOCounters`^]. [id="fn_ps_net_iocntsfl"] ===== `psNetIoCntsFile` [source,go] .Function Signature ---- -func psNetIoCntsFile(perNIC bool, filepath string) (ioCnts [](github.com/shirou/gopsutil/v4/net).IOCountersStat, err error) +func psNetIoCntsFile(perNIC bool, filepath string) (ioCnts []net.IOCountersStat, err error) ---- -`psNetIoCntsFile` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#IOCountersByFile[`github.com/shirou/gopsutil/v4/net.IOCountersByFile`^]. +`psNetIoCntsFile` directly calls {godoc_root}/{mod_psutil}/net#IOCountersByFile[`{mod_psutil}/net.IOCountersByFile`^]. [id="fn_ps_net_ifaces"] ===== `psNetIfaces` [source,go] .Function Signature ---- -func psNetIfaces() (ioCnts [](github.com/shirou/gopsutil/v4/net).InterfaceStatList, err error) +func psNetIfaces() (ioCnts []net.InterfaceStatList, err error) ---- -`psNetIfaces` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#Interfaces[`github.com/shirou/gopsutil/v4/net.Interfaces`^]. +`psNetIfaces` directly calls {godoc_root}/{mod_psutil}/net#Interfaces[`{mod_psutil}/net.Interfaces`^]. [id="fn_ps_net_pids"] ===== `psNetPids` @@ -1333,14 +1657,14 @@ func psNetIfaces() (ioCnts [](github.com/shirou/gopsutil/v4/net).InterfaceStatLi func psNetPids() (pids []int32, err error) ---- -`psNetPids` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#Pids[`github.com/shirou/gopsutil/v4/net.Pids`^]. +`psNetPids` directly calls {godoc_root}/{mod_psutil}/net#Pids[`{mod_psutil}/net.Pids`^]. [id="fn_ps_net_protocnts"] ===== `psNetProtoCnt` [source,go] .Function Signature ---- -func psNetProtoCnt(protos []string) (protoCnts [](github.com/shirou/gopsutil/v4/net).ProtoCountersStat, err error) +func psNetProtoCnt(protos []string) (protoCnts []net.ProtoCountersStat, err error) ---- [WARNING] @@ -1348,7 +1672,7 @@ func psNetProtoCnt(protos []string) (protoCnts [](github.com/shirou/gopsutil/v4/ This only works properly on Linux currently per upstream. ==== -`psNetProtoCnt` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net#ProtoCounters[`github.com/shirou/gopsutil/v4/net.ProtoCounters`^]. +`psNetProtoCnt` directly calls {godoc_root}/{mod_psutil}/net#ProtoCounters[`{mod_psutil}/net.ProtoCounters`^]. [id="fn_ps_net_rev"] ===== `psNetRev` @@ -1363,7 +1687,7 @@ func psNetRev(b []byte) (out []byte) This function only exists on Linux. ==== -`psNetRev` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/net?GOOS=linux#Reverse[`github.com/shirou/gopsutil/v4/net.Reverse`^]. +`psNetRev` directly calls {godoc_root}/{mod_psutil}/net?GOOS=linux#Reverse[`{mod_psutil}/net.Reverse`^]. [id="fn_ps_proc"] ==== Processes @@ -1373,20 +1697,20 @@ This function only exists on Linux. [source,go] .Function Signature ---- -func psProcs(pid int32) (procs []*(github.com/shirou/gopsutil/v4/process).Process, err error) +func psProcs(pid int32) (procs []*process.Process, err error) ---- -`psProcs` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/process#Processes[`github.com/shirou/gopsutil/v4/proc.Processes`^]. +`psProcs` directly calls {godoc_root}/{mod_psutil}/process#Processes[`{mod_psutil}/proc.Processes`^]. [id="fn_ps_proc_new"] ===== `psProcNew` [source,go] .Function Signature ---- -func psProcNew(pid int32) (proc *(github.com/shirou/gopsutil/v4/process).Process, err error) +func psProcNew(pid int32) (proc *process.Process, err error) ---- -`psProcNew` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/process#NewProcess[`github.com/shirou/gopsutil/v4/proc.NewProcess`^]. +`psProcNew` directly calls {godoc_root}/{mod_psutil}/process#NewProcess[`{mod_psutil}/proc.NewProcess`^]. [id="fn_ps_proc_pids"] ===== `psProcPids` @@ -1396,7 +1720,7 @@ func psProcNew(pid int32) (proc *(github.com/shirou/gopsutil/v4/process).Process func psProcPids() (pids []int32, err error) ---- -`psProcPids` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/process#Pids[`github.com/shirou/gopsutil/v4/proc.Pids`^]. +`psProcPids` directly calls {godoc_root}/{mod_psutil}/process#Pids[`{mod_psutil}/proc.Pids`^]. [id="fn_ps_proc_pidxst"] ===== `psProcPidExists` @@ -1406,7 +1730,7 @@ func psProcPids() (pids []int32, err error) func psProcPidExists(pid int32) (exists bool, err error) ---- -`psProcPidExists` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/process#PidExists[`github.com/shirou/gopsutil/v4/proc.PidExists`^]. +`psProcPidExists` directly calls {godoc_root}/{mod_psutil}/process#PidExists[`{mod_psutil}/proc.PidExists`^]. [id="fn_ps_sns"] ==== Sensors/Thermals @@ -1416,7 +1740,7 @@ func psProcPidExists(pid int32) (exists bool, err error) [source,go] .Function Signature ---- -func psSensorExTemp() (temps [](github.com/shirou/gopsutil/v4/sensors).ExTemperature, err error) +func psSensorExTemp() (temps []sensors.ExTemperature, err error) ---- [WARNING] @@ -1424,17 +1748,17 @@ func psSensorExTemp() (temps [](github.com/shirou/gopsutil/v4/sensors).ExTempera This function only exists on Linux. ==== -`psSensorExTemp` wraps link:https://pkg.go.dev/github.com/shirou/gopsutil/v4/sensors?GOOS=linux#NewExLinux[`github.com/shirou/gopsutil/v4/sensors.NewExLinux`^].link:https://pkg.go.dev/github.com/shirou/gopsutil/v4/sensors?GOOS=linux#TemperatureWithContext[`github.com/shirou/gopsutil/v4/sensors.TemperatureWithContext`^]. +`psSensorExTemp` wraps link:{godoc_root}/{mod_psutil}/sensors?GOOS=linux#NewExLinux[`{mod_psutil}/sensors.NewExLinux`^].link:{godoc_root}/{mod_psutil}/sensors?GOOS=linux#TemperatureWithContext[`{mod_psutil}/sensors.TemperatureWithContext`^]. [id="fn_ps_sns_temps"] ===== `psSensorTemps` [source,go] .Function Signature ---- -func psSensorTemps() (temps [](github.com/shirou/gopsutil/v4/sensors).TemperatureStat, err error) +func psSensorTemps() (temps []sensors.TemperatureStat, err error) ---- -`psSensorTemps` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/sensors#SensorsTemperatures[`github.com/shirou/gopsutil/v4/sensors.SensorsTemperatures`^]. +`psSensorTemps` directly calls {godoc_root}/{mod_psutil}/sensors#SensorsTemperatures[`{mod_psutil}/sensors.SensorsTemperatures`^]. [id="fn_ps_winsvc"] ==== Windows Services @@ -1449,7 +1773,7 @@ All of these functions are only available on Windows. [source,go] .Function Signature ---- -func psWinsvcList() (svcs [](github.com/shirou/gopsutil/v4/winservices).Service, err error) +func psWinsvcList() (svcs []winservices.Service, err error) ---- [WARNING] @@ -1457,14 +1781,14 @@ func psWinsvcList() (svcs [](github.com/shirou/gopsutil/v4/winservices).Service, This function is only available on Windows. ==== -`psWinsvcList` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/winservices?GOOS=windows#ListServices[`github.com/shirou/gopsutil/v4/winservices.ListServices`^]. +`psWinsvcList` directly calls {godoc_root}/{mod_psutil}/winservices?GOOS=windows#ListServices[`{mod_psutil}/winservices.ListServices`^]. [id="fn_ps_winsvc_new"] ===== `psWinsvcNew` [source,go] .Function Signature ---- -func psWinsvcNew(svcName string) (svc *(github.com/shirou/gopsutil/v4/winservices).Service, err error) +func psWinsvcNew(svcName string) (svc *winservices.Service, err error) ---- [WARNING] @@ -1472,7 +1796,7 @@ func psWinsvcNew(svcName string) (svc *(github.com/shirou/gopsutil/v4/winservice This function is only available on Windows. ==== -`psWinsvcNew` directly calls https://pkg.go.dev/github.com/shirou/gopsutil/v4/winservices?GOOS=windows#NewService[`github.com/shirou/gopsutil/v4/winservices.NewService`^]. +`psWinsvcNew` directly calls {godoc_root}/{mod_psutil}/winservices?GOOS=windows#NewService[`{mod_psutil}/winservices.NewService`^]. [id="fn_str"] === Strings @@ -1495,24 +1819,95 @@ It works with both Windows (`\r\n`) and POSIX (`\n`) linebreaks. [TIP] ==== -If `` is set to `\n` and `` is always set to `1`, this function can even be used to doubelspace text! +If `` is set to `\n` and `` is always set to `1`, this function can even be used to doublespace text! ==== It has quite a few arguments, however: -[source,gotemplate] +[cols="^.^1m,^.^1m,.^4a",options="header"] +|=== +| Argument ^| Type | Description + +| levels | int | The level of indentation for the text. If less than or equal to `0`, `extIndent` just returns `` as-is and NO-OPs otherwise. +| skipFirst | bool | If true, skip indenting the first line. This is particularly handy if you like to visually align your function calls in your templates. +| skipEmpty | bool | If true, do not add an indent to *empty* lines (where an "empty line" means "only has a linebreak"). +| skipWhitespace | bool | If true, do not add an indent to lines that *only* consist of whitespace (spaces, tabs, etc.) and a linebreak. +| indentString | string | The string to use as the "indent character". This can be any string, such as `""` (https://asciiref.dev/#c32[`0x20`^]), `"\t"`, `"."`, `"\|"`, `"=="` etc. +| input | string | The text to be indented. Because it is the last argument, `extIndent` works with pipelined text as well. +|=== + +[id="fn_sys"] +=== System/Platform/Architecture + +[id="fn_sys_arch"] +==== `sysArch` +[source,go] +.Function Signature ---- -{{ extIndent }} +func sysArch() (out string) ---- -Where: +Returns the {godoc_root}/runtime#GOARCH[`runtime.GOARCH`^] constant. -* ``: The level of indentation for the text. If less than or equal to `0`, `extIndent` just returns `` as-is and NO-OPs otherwise. -* ``: If true, skip indenting the first line. This is particularly handy if you like to visually align your function calls in your templates. -* ``: If true, do not add an indent to *empty* lines (where an "empty line" means "only has a linebreak"). -* ``: If true, do not add an indent to lines that *only* consist of whitespace (spaces, tabs, etc.) and a linebreak. -* ``: The string to use as the "indent character". This can be any string, such as `" "`, `"\t"`, `"."`, `"|"`, `"=="` etc. -* ``: The text to be indented. Because it is the last argument, `extIndent` works with pipelined text as well. +[id="fn_sys_numcpu"] +==== `sysNumCpu` +[source,go] +.Function Signature +---- +func sysNumCpu() (cnt int) +---- + +`sysNumCpu` directly calls {godoc_root}/runtime#NumCPU[`runtime.NumCPU`^]. + +[id="fn_sys_os"] +==== `sysOsName` +[source,go] +.Function Signature +---- +func sysOsNm() (out string) +---- + +Returns the {godoc_root}/runtime#GOOS[`runtime.GOOS`^] constant. + +[id="fn_sys_rntm"] +==== `sysRuntime` +[source,go] +.Function Signature +---- +func sysRuntime() (out map[string]string) +---- + +This function returns a `map[string]string` of various information from the {godoc_root}/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 {sprig_web}/conversion.html[Sprig conversion functions^] if necessary. +==== + +.`sysRuntime` Values +[cols="^.^3m,^.^3",options="header"] +|=== +| Key | Value Type + +| compiler | {godoc_root}/runtime#Compiler[string^] +| arch | {godoc_root}/runtime#GOARCH[string^] +| os | {godoc_root}/runtime#GOOS[string^] +| maxprocs | {godoc_root}/runtime#GOMAXPROCS[int^] footnote:[For safety concerns, `sprigx` does not allow *setting* `GOMAXPROCS`, this value only contains the *current* `GOMAXPROCS` value.] +| cpu_cnt | {godoc_root}/runtime#NumCPU[int^] +| num_cgo | {godoc_root}/runtime#NumCgoCall[int^] +| num_go | {godoc_root}/runtime#NumGoroutine[int^] +| go_ver | {godoc_root}/runtime#Version[string^] +|=== + +As a convenience, some of these values also have their own dedicated functions as well: + +* <> +* <> +* <> [id="fn_tm"] === Time/Dates/Timestamps @@ -1532,7 +1927,7 @@ Care has been taken to name these functions differently from the Sprig functions func tmDate(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) (date time.Time) ---- -`tmDate` directly calls https://pkg.go.dev/time#Date[`time.Date`^]. +`tmDate` directly calls {godoc_root}/time#Date[`time.Date`^]. [id="fn_tm_fltmic"] ==== `tmFloatMicro` @@ -1542,7 +1937,7 @@ func tmDate(year int, month time.Month, day, hour, min, sec, nsec int, loc *time func tmFloatMicro(t time.Time) (f64 float64) ---- -`tmFloatMicro` directly calls https://pkg.go.dev/r00t2.io/goutils/timex#F64Microseconds[`(r00t2.io/goutils/timex).F64Microseconds`^]. +`tmFloatMicro` directly calls {godoc_root}/r00t2.io/goutils/timex#F64Microseconds[`(r00t2.io/goutils/timex).F64Microseconds`^]. [id="fn_tm_fltmill"] ==== `tmFloatMilli` @@ -1552,7 +1947,7 @@ func tmFloatMicro(t time.Time) (f64 float64) func tmFloatMilli(t time.Time) (f64 float64) ---- -`tmFloatMilli` directly calls https://pkg.go.dev/r00t2.io/goutils/timex#F64Milliseconds[`(r00t2.io/goutils/timex).F64Milliseconds`^]. +`tmFloatMilli` directly calls {godoc_root}/r00t2.io/goutils/timex#F64Milliseconds[`(r00t2.io/goutils/timex).F64Milliseconds`^]. [id="fn_tm_fltnano"] ==== `tmFloatNano` @@ -1562,7 +1957,7 @@ func tmFloatMilli(t time.Time) (f64 float64) func tmFloatNano(t time.Time) (f64 float64) ---- -`tmFloatNano` directly calls https://pkg.go.dev/r00t2.io/goutils/timex#F64Nanoseconds[`(r00t2.io/goutils/timex).F64Nanoseconds`^]. +`tmFloatNano` directly calls {godoc_root}/r00t2.io/goutils/timex#F64Nanoseconds[`(r00t2.io/goutils/timex).F64Nanoseconds`^]. [id="fn_tm_flt"] ==== `tmFloat` @@ -1572,7 +1967,7 @@ func tmFloatNano(t time.Time) (f64 float64) func tmFloat(t time.Time) (f64 float64) ---- -`tmFloat` directly calls https://pkg.go.dev/r00t2.io/goutils/timex#F64Seconds[`(r00t2.io/goutils/timex).F64Seconds`^]. +`tmFloat` directly calls {godoc_root}/r00t2.io/goutils/timex#F64Seconds[`(r00t2.io/goutils/timex).F64Seconds`^]. [id="fn_tm_fmt"] ==== `tmFmt` @@ -1598,7 +1993,7 @@ func tmFmt(fstr string, t time.Time) (out string) func tmNow() (now time.Time) ---- -`tmNow` directly calls https://pkg.go.dev/time#Now[`time.Now`^]. +`tmNow` directly calls {godoc_root}/time#Now[`time.Now`^]. [id="fn_tm_pdur8n"] ==== `tmParseDur8n` @@ -1608,7 +2003,7 @@ func tmNow() (now time.Time) func tmParseDur8n(s string) (d time.Duration, err error) ---- -`tmParseDur8n` directly calls https://pkg.go.dev/time#ParseDuration[`time.ParseDuration`^]. +`tmParseDur8n` directly calls {godoc_root}/time#ParseDuration[`time.ParseDuration`^]. [id="fn_tm_pmnth"] ==== `tmParseMonth` @@ -1628,14 +2023,14 @@ func tmParseMonth(v any) (mon time.Month, err error) func tmParseMonthInt(n any) (mon time.Month, err error) ---- -`tmParseMonthInt` parses a number representation of month `n` to a https://pkg.go.dev/time#Month[`time.Month`^]. +`tmParseMonthInt` parses a number representation of month `n` to a {godoc_root}/time#Month[`time.Month`^]. `n` may be any numeric type or a string representation of a number (or a custom type derived from those). A negative integer (or float, etc.) will be converted to a positive one (e.g. `-6` -> `6` -> `time.June`). Floats are rounded to the nearest integer. -The integer should map directly to the https://pkg.go.dev/time#example-Month[`time.Month` constants^] in the `time` module: +The integer should map directly to the {godoc_root}/time#example-Month[`time.Month` constants^] in the `time` module: * `1`: `time.January` * `2`: `time.February` @@ -1650,9 +2045,9 @@ The integer should map directly to the https://pkg.go.dev/time#example-Month[`ti * `11`: `time.November` * `12`: `time.December` -If `n` resolves to `0`, `mon` will be the current month (as determined by https://pkg.go.dev/time#Now[`time.Now`^]). +If `n` resolves to `0`, `mon` will be the current month (as determined by {godoc_root}/time#Now[`time.Now`^]). -If `n` resolves to > `12`, `err` will be `sprigx.ErrBadMonth` (though be sure to use https://pkg.go.dev/errors#Is[`errors.Is`^]; it will be wrapped by link:https://pkg.go.dev/text/template#ExecError[`(text/template).ExecError`]/link:https://pkg.go.dev/html/template#ExecError[`(html/template).ExecError`]. +If `n` resolves to > `12`, `err` will be `sprigx.ErrBadMonth` (though be sure to use {godoc_root}/errors#Is[`errors.Is`^]; it will be wrapped by link:{godoc_root}/text/template#ExecError[`(text/template).ExecError`]/link:{godoc_root}/html/template#ExecError[`(html/template).ExecError`]. [id="fn_tm_pmnths"] ==== `tmParseMonthStr` @@ -1662,12 +2057,12 @@ If `n` resolves to > `12`, `err` will be `sprigx.ErrBadMonth` (though be sure to func tmParseMonthStr(s string) (mon time.Month, err error) ---- -`tmParseMonthStr` parses a string representation `s` of a month to a https://pkg.go.dev/time#Month[`time.Month`^]. +`tmParseMonthStr` parses a string representation `s` of a month to a {godoc_root}/time#Month[`time.Month`^]. It normalizes `s` to lowercase and only uses the first 3 characters (the minimum length needed to determine month name uniqueness - "June" vs. "July", "March" vs. "May"). -An empty (or whitespace-only) string will use the current month (as determined by https://pkg.go.dev/time#Now[`time.Now`^]).` +An empty (or whitespace-only) string will use the current month (as determined by {godoc_root}/time#Now[`time.Now`^]). [id="fn_tm_ptm"] ==== `tmParseTime` @@ -1677,79 +2072,6 @@ An empty (or whitespace-only) string will use the current month (as determined b func tmParseTime(layout, value string) (t time.Time, err error) ---- -`tmParseTime` directly calls https://pkg.go.dev/time#Parse[`time.Parse`^]. +`tmParseTime` directly calls {godoc_root}/time#Parse[`time.Parse`^]. -Be sure that `layout` is a properly parseable https://pkg.go.dev/time#Layout[layout format^]. - -[id="fn_sys"] -=== System/Platform/Architecture - -[id="fn_sys_arch"] -==== `sysArch` -[source,go] -.Function Signature ----- -func sysArch() (out string) ----- - -Returns the https://pkg.go.dev/runtime#GOARCH[`runtime.GOARCH`^] constant. - -[id="fn_sys_numcpu"] -==== `sysNumCpu` -[source,go] -.Function Signature ----- -func sysNumCpu() (cnt int) ----- - -`sysNumCpu` directly calls https://pkg.go.dev/runtime#NumCPU[`runtime.NumCPU`^]. - -[id="fn_sys_os"] -==== `sysOsName` -[source,go] -.Function Signature ----- -func sysOsNm() (out string) ----- - -Returns the https://pkg.go.dev/runtime#GOOS[`runtime.GOOS`^] constant. - -[id="fn_sys_rntm"] -==== `sysRuntime` -[source,go] -.Function Signature ----- -func sysRuntime() (out map[string]string) ----- - -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: - -* <> -* <> -* <> +Be sure that `layout` is a properly parseable {godoc_root}/time#Layout[layout format^]. diff --git a/tplx/sprigx/README.html b/tplx/sprigx/README.html index cc22cad..07080e3 100644 --- a/tplx/sprigx/README.html +++ b/tplx/sprigx/README.html @@ -552,6 +552,83 @@ pre.rouge .gs { font-weight: bold; } + + + + + + + + + + + @@ -827,25 +945,25 @@ or by downloading and viewing the
-
package main
+
package main
 
-import (
-	"text/template"
+import (
+	"text/template"
 
-	"github.com/Masterminds/sprig/v3"
-	"r00t2.io/goutils/tplx/sprigx"
-)
+	"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(
+			sprigx.TxtFuncMap(),
+		).
+		Funcs(
+			sprig.TxtFuncMap(),
+		)
+// Or:
+/*
 var txtTpl *template.Template = template.
 		New("").
 		Funcs(
@@ -854,7 +972,7 @@ var txtTpl *template.Template = template.
 		Funcs(
 			sprigx.TxtFuncMap(),
 		)
- */
+ */
@@ -876,28 +994,28 @@ var txtTpl *template.Template = template.
-
package main
+
package main
 
-import (
-	"text/template"
+import (
+	"text/template"
 
-	"github.com/Masterminds/sprig/v3"
-	"r00t2.io/goutils/tplx/sprigx"
-)
+	"github.com/Masterminds/sprig/v3"
+	"r00t2.io/goutils/tplx/sprigx"
+)
 
-const (
-	myTpl string = `{{ "This is an example template string." | foo }}`
-)
+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())
-)
+var ( + tpl *template.Template = template.Must( + template. + New(""). + Funcs(sprig.TxtFuncMap()). + Parse(myTpl), + ). + Funcs(sprigx.TxtFuncMap()) +)
@@ -910,28 +1028,28 @@ var txtTpl *template.Template = template.
-
package main
+
package main
 
-import (
-	"text/template"
+import (
+	"text/template"
 
-	"github.com/Masterminds/sprig/v3"
-	"r00t2.io/goutils/tplx/sprigx"
-)
+	"github.com/Masterminds/sprig/v3"
+	"r00t2.io/goutils/tplx/sprigx"
+)
 
-const (
-	myTpl string = `{{ "This is an example template string." | foo }}`
-)
+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())
-)
+var ( + tpl *template.Template = template.Must( + template. + New(""). + Funcs(sprigx.TxtFuncMap()). + Parse(myTpl), + ). + Funcs(sprig.TxtFuncMap()) +)
@@ -947,36 +1065,36 @@ var txtTpl *template.Template = template.
-
package main
+
package main
 
-import (
-	"text/template"
+import (
+	"text/template"
 
-	"github.com/Masterminds/sprig/v3"
-	"r00t2.io/goutils/tplx/sprigx"
-)
+	"github.com/Masterminds/sprig/v3"
+	"r00t2.io/goutils/tplx/sprigx"
+)
 
-const (
-	myTpl string = `{{ "This is an example template string." | foo }}`
-)
+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"],
-							},
-						),
-					)
-)
+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"], + }, + ), + ) +)
@@ -1015,11 +1133,11 @@ as they wrap this with the appropriate type.

Function Signature
-
func CombinedHtmlFuncMap(preferSprigX bool) (fmap (html/template).FuncMap)
+
func CombinedHtmlFuncMap(preferSprigX bool) (fmap template.FuncMap)
-

This function returns an (html/template).FuncMap function map (like HtmlFuncMap) combined with +

This function returns an html/template.FuncMap function map (like HtmlFuncMap) combined with github.com/Masterminds/sprig/v3.HtmlFuncMap.

@@ -1032,11 +1150,11 @@ If false, Sprig functions will override conflicting SprigX functions with the sa
Function Signature
-
func CombinedTxtFuncMap(preferSprigX bool) (fmap (text/template).FuncMap)
+
func CombinedTxtFuncMap(preferSprigX bool) (fmap template.FuncMap)
-

This function returns a (text/template).FuncMap function map (like TxtFuncMap) combined with +

This function returns a text/template.FuncMap function map (like TxtFuncMap) combined with github.com/Masterminds/sprig/v3.TxtFuncMap.

@@ -1065,11 +1183,11 @@ as they wrap this with the appropriate type.

Function Signature
-
func HtmlFuncMap() (fmap (html/template).FuncMap)
+
func HtmlFuncMap() (fmap template.FuncMap)
-

This function returns a SprigX (html/template).FuncMap.

+

This function returns a SprigX html/template.FuncMap.

@@ -1093,11 +1211,11 @@ certain Sprig/SprigX functions that may be deemed "unsafe" and/or to sanitize te
Function Signature
-
func TxtFuncMap() (fmap (text/template).FuncMap)
+
func TxtFuncMap() (fmap template.FuncMap)
-

This function returns a SprigX (text/template).FuncMap.

+

This function returns a SprigX text/template.FuncMap.

@@ -1109,8 +1227,24 @@ certain Sprig/SprigX functions that may be deemed "unsafe" and/or to sanitize te

Expect this list to grow over time, and potentially more frequently than the sprigx functions.

-

Each function includes its function signature to indicate what types of arguments/parameters it accepts, -what it returns, and if it may potentially return an error or not.

+

Each function includes its Function Signature to indicate what arguments/parameters it accepts, their type(s), +what it returns, and the returned value(s) type(s).

+
+
+

Because Go template functions can only return either:

+
+
+
    +
  • +

    a single value of any type, or

    +
  • +
  • +

    a value of any type and an error (in that order)

    +
  • +
+
+
+

you can easily determine whether a function can return an error or not by simply referring to the Function Signature.

4.1. Debugging

@@ -1123,7 +1257,7 @@ what it returns, and if it may potentially return an error or not.

-

The dump function directly calls github.com/davecgh/go-spew/spew.Sdump +

The dump function directly calls github.com/davecgh/go-spew/spew.Sdump for whatever object(s) is/are passed to it.

@@ -1147,9 +1281,381 @@ for whatever object(s) is/are passed to it.

-

4.3. Numbers/Math

+

4.3. Networking

+
+

These template functions use capabilities from:

+
+
+ +
+
+

The function prefix is used to indicate which module/package a function is added from.

+
-

4.3.1. numFloat32Str

+

4.3.1. net

+
+

These template functions contain capabilities from net.

+
+
+
4.3.1.1. netCidrMask
+
+
Function Signature
+
+
func netCidrMask(ones, bits int) (mask net.IPMask)
+
+
+
+

netCidrMask directly calls net.CIDRMask.

+
+
+
+
4.3.1.2. netExtractAddr
+
+
Function Signature
+
+
func netExtractAddr(s string) (addr net.IP, err error)
+
+
+
+

netExtractAddr wraps net.ParseCIDR and returns the net.IP component.

+
+
+
+
4.3.1.3. netExtractHost
+
+
Function Signature
+
+
func netExtractHost(hostPort string) (host string, err error)
+
+
+
+

netExtractHost wraps net.SplitHostPort and returns the host component (as a string).

+
+
+
+
4.3.1.4. netExtractIpnet
+
+
Function Signature
+
+
func netExtractIpnet(s string) (ipNet *net.IPNet, err error)
+
+
+
+

netExtractIpnet wraps net.ParseCIDR and returns the net.IPNet component.

+
+
+
+
4.3.1.5. netExtractPort
+
+
Function Signature
+
+
func netExtractPort(hostPort string) (port uint16, err error)
+
+
+
+

netExtractPort wraps net.SplitHostPort and returns the port component (as a uint16).

+
+
+
+
4.3.1.6. netIfaces
+
+
Function Signature
+
+
func netIfaces() (ifaces []net.Interface, err error)
+
+
+
+

netIfaces directly calls net.Interfaces.

+
+
+
+
4.3.1.7. netIp4Mask
+
+
Function Signature
+
+
func netIp4Mask(a, b, c, d any) (mask net.IPMask, err error)
+
+
+
+

netIp4Mask wraps net.IPv4Mask.

+
+
+

It is wrapped so that a, b, c, and d may be a string:

+
+
+
+
{{- $mask := netIp4Mask "198" "51" "100" "10" -}}
+
+
+
+

or integers/other numeric:

+
+
+
+
{{- $mask := netIp4Mask 198 51 100 10 -}}
+
+
+
+

or bytes:

+
+
+
+
{{- $mask := netIp4Mask 0xc6 0x33 0x64 0x0a -}}
+
+
+
+

or even a mix:

+
+
+
+
{{- $mask := netIp4Mask "198" 51 "100" 0x0a -}}
+
+
+
+
+
4.3.1.8. netJoinHostPort
+
+
Function Signature
+
+
func netJoinHostPort(host, port string) (out string)
+
+
+
+

netJoinHostPort directly calls net.JoinHostPort.

+
+
+
+
4.3.1.9. netParseIP
+
+
Function Signature
+
+
func netParseIP(s string) (ip net.IP)
+
+
+
+

netParseIP directly calls net.ParseIP.

+
+
+
+
+

4.3.2. net/netip

+
+

These template functions contain capabilities from net/netip.

+
+
+
4.3.2.1. netipAddrPort
+
+
Function Signature
+
+
func netipAddrPort(ip netip.Addr, port uint16) (addrPort netip.AddrPort)
+
+
+
+

netipAddrPort directly calls net/netip.AddrPortFrom.

+
+
+
+
4.3.2.2. netipParseAddr
+
+
Function Signature
+
+
func netipParseAddr(s string) (addr netip.Addr, err error)
+
+
+
+

netipParseAddr directly calls net/netip.ParseAddr.

+
+
+
+
4.3.2.3. netipParseAddrPort
+
+
Function Signature
+
+
func netipParseAddrPort(s string) (addrPort netip.AddrPort, err error)
+
+
+
+

netipParseAddrPort directly calls net/netip.ParseAddrPort.

+
+
+
+
4.3.2.4. netipParsePrefix
+
+
Function Signature
+
+
func netipParsePrefix(s string) (pfx netip.Prefix, err error)
+
+
+
+

netipParsePrefix directly calls net/netip.ParsePrefix.

+
+
+
+
4.3.2.5. netipPrefix
+
+
Function Signature
+
+
func netipPrefix(ip netip.Addr, bits int) (pfx netip.Prefix)
+
+
+
+

netipPrefix directly calls net/netip.PrefixFrom.

+
+
+
+
+

4.3.3. go4.org/netipx

+
+

These template functions contain capabilities from go4.org/netipx.

+
+
+
4.3.3.1. netipxAddrIpNet
+
+
Function Signature
+
+
func netipxAddrIpNet(addr netip.Addr) (ipNet *net.IPNet)
+
+
+
+

netipxAddrIpNet directly calls go4.org/netipx.AddrIPNet.

+
+
+
+
4.3.3.2. netipxCmpPfx
+
+
Function Signature
+
+
func netipxCmpPfx(a, b netip.Prefix) (cmp int)
+
+
+
+

netipxCmpPfx directly calls go4.org/netipx.ComparePrefix.

+
+
+
+
4.3.3.3. netipxFromStdAddr
+
+
Function Signature
+
+
func netipxFromStdAddr(ip net.IP, port int, zone string) (addrPort netip.AddrPort, err error)
+
+
+
+

netipxFromStdAddr wraps go4.org/netipx.FromStdAddr. Instead of returning a boolean as the second value, it will instead be an error if the wrapped boolean is false.

+
+
+
+
4.3.3.4. netipxFromIp
+
+
Function Signature
+
+
func netipxFromIp(ip net.IP) (addr netip.Addr, err error)
+
+
+
+

netipxFromIp wraps go4.org/netipx.FromStdIP. Instead of returning a boolean as the second value, it will instead be an error if the wrapped boolean is false.

+
+
+
+
4.3.3.5. netipxFromIpNet
+
+
Function Signature
+
+
func netipxFromIpNet(ipNet *net.IPNet) (pfx netip.Prefix, err error)
+
+
+
+

netipxFromIpNet wraps go4.org/netipx.FromStdIPNet. Instead of returning a boolean as the second value, it will instead be an error if the wrapped boolean is false.

+
+
+
+
4.3.3.6. netipxParseRange
+
+
Function Signature
+
+
func netipxParseRange(s string) (ipRange netipx.IPRange, err error)
+
+
+
+

netipxRange directly calls go4.org/netipx.ParseIPRange.

+
+
+
+
4.3.3.7. netipxPfxAddr
+
+
Function Signature
+
+
func netipxPfxAddr(s string) (addr netip.Addr, err error)
+
+
+
+

netipxPfxAddr directly calls go4.org/netipx.ParsePrefixOrAddr.

+
+
+
+
4.3.3.8. netipxPfxIpNet
+
+
Function Signature
+
+
func netipxPfxIpNet(pfx netip.Prefix) (ipNet *net.IPNet)
+
+
+
+

netipxPfxIpNet directly calls go4.org/netipx.PrefixIPNet.

+
+
+
+
4.3.3.9. netipxPfxLast
+
+
Function Signature
+
+
func netipxPfxLast(pfx netip.Prefix) (addr netip.Addr)
+
+
+
+

netipxPfxLast directly calls go4.org/netipx.PrefixLastIP.

+
+
+
+
4.3.3.10. netipxPfxRange
+
+
Function Signature
+
+
func netipxPfxRange(pfx netip.Prefix) (ipRange netipx.IPRange)
+
+
+
+

netipxPfxRange directly calls go4.org/netipx.RangeOfPrefix.

+
+
+
+
4.3.3.11. netipxRange
+
+
Function Signature
+
+
func netipxRange(from, to netip.Addr) (ipRange netipx.IPRange)
+
+
+
+

netipxRange directly calls go4.org/netipx.IPRangeFrom.

+
+
+
+
+
+

4.4. Numbers/Math

+
+

4.4.1. numFloat32Str

Function Signature
@@ -1161,7 +1667,7 @@ for whatever object(s) is/are passed to it.

-

4.3.2. numFloat64

+

4.4.2. numFloat64

Function Signature
@@ -1173,7 +1679,7 @@ for whatever object(s) is/are passed to it.

-

4.3.3. numFloat64Str

+

4.4.3. numFloat64Str

Function Signature
@@ -1185,7 +1691,7 @@ for whatever object(s) is/are passed to it.

-

4.3.4. numFloatStr

+

4.4.4. numFloatStr

Function Signature
@@ -1201,9 +1707,9 @@ for whatever object(s) is/are passed to it.

-

4.4. Operating System

+

4.5. Operating System

-

4.4.1. osFQDN

+

4.5.1. osFQDN

Function Signature
@@ -1227,7 +1733,7 @@ To directly/predictably use -

4.4.2. osGroupById

+

4.5.2. osGroupById

Function Signature
@@ -1243,7 +1749,7 @@ except it will accept either a string or an
-

4.4.3. osGroupByName

+

4.5.3. osGroupByName

Function Signature
@@ -1258,7 +1764,7 @@ except it will accept either a string or an
-

4.4.4. osHost

+

4.5.4. osHost

Function Signature
@@ -1267,7 +1773,7 @@ except it will accept either a string or an

osHost returns the "short hostname" by calling os.Hostname -and returning the first "host label" (as RFCs refer to it).

+and returning the first "host label" (as RFCs refer to it). This is commonly/colloquially called the "hostname" or "hostname without the domain part".

e.g.:

@@ -1288,7 +1794,7 @@ osHost {{ $h }} should be equal to first label of FQDN {{ $cmp }}.
-

The splitList function shown aboce is from the sprig string slice functions.

+

The splitList function shown above is from the sprig string slice functions.

@@ -1300,7 +1806,7 @@ To directly use -

4.4.5. osHostname

+

4.5.5. osHostname

Function Signature
@@ -1312,7 +1818,7 @@ To directly use -

4.4.6. osIdState

+

4.5.6. osIdState

Function Signature
@@ -1341,7 +1847,7 @@ To directly use -

4.4.7. osUser

+

4.5.7. osUser

Function Signature
@@ -1356,7 +1862,7 @@ To directly use -

4.4.8. osUserById

+

4.5.8. osUserById

Function Signature
@@ -1372,7 +1878,7 @@ except it will accept either a string or an
-

4.4.9. osUserByName

+

4.5.9. osUserByName

Function Signature
@@ -1388,14 +1894,14 @@ except it will accept either a string or an
-

4.5. Paths

+

4.6. Paths

-

4.5.1. Generic

+

4.6.1. Generic

These operate similar to the path stdlib library and use a fixed / path separator.

-
4.5.1.1. pathJoin
+
4.6.1.1. pathJoin
Function Signature
@@ -1439,7 +1945,7 @@ unless you are explicitly appending a pipeline result to a path
-
4.5.1.2. pathPipeJoin
+
4.6.1.2. pathPipeJoin
Function Signature
@@ -1473,7 +1979,7 @@ as the last element to the next pipe function.

-
4.5.1.3. pathSliceJoin
+
4.6.1.3. pathSliceJoin
Function Signature
@@ -1517,7 +2023,7 @@ a/b/c
-
4.5.1.4. pathSlicePipeJoin
+
4.6.1.4. pathSlicePipeJoin
Function Signature
@@ -1562,7 +2068,7 @@ path segments ([]string) to append to that base path.

-
4.5.1.5. pathSubJoin
+
4.6.1.5. pathSubJoin
Function Signature
@@ -1595,7 +2101,7 @@ path segments ([]string) to append to that base path.

-

4.5.2. OS/Platform-Tailored

+

4.6.2. OS/Platform-Tailored

These operate similar to the path/filepath stdlib library, and use the OS-specific os.PathSeparator.

@@ -1617,7 +2123,7 @@ path segments ([]string) to append to that base path.

-
4.5.2.1. osPathJoin
+
4.6.2.1. osPathJoin
Function Signature
@@ -1692,7 +2198,7 @@ C:/a/b/c
-
4.5.2.2. osPathPipeJoin
+
4.6.2.2. osPathPipeJoin
Function Signature
@@ -1753,7 +2259,7 @@ as the last argument to the next pipe function.

-
4.5.2.3. osPathSep
+
4.6.2.3. osPathSep
Function Signature
@@ -1803,7 +2309,7 @@ as the last argument to the next pipe function.

-
4.5.2.4. osPathSliceJoin
+
4.6.2.4. osPathSliceJoin
Function Signature
@@ -1874,7 +2380,7 @@ a/b/c
-
4.5.2.5. osPathSlicePipeJoin
+
4.6.2.5. osPathSlicePipeJoin
Function Signature
@@ -1943,7 +2449,7 @@ a/b/c
-
4.5.2.6. osPathSubJoin
+
4.6.2.6. osPathSubJoin
Function Signature
@@ -2004,14 +2510,14 @@ a/b/c
-

4.6. PSUtil

+

4.7. PSUtil

These are functions from github.com/shirou/gopsutil/v4 packages.

-

4.6.1. CPU/Processor

+

4.7.1. CPU/Processor

-
4.6.1.1. psCpuCnts
+
4.7.1.1. psCpuCnts
Function Signature
@@ -2023,11 +2529,11 @@ a/b/c
-
4.6.1.2. psCpuInfo
+
4.7.1.2. psCpuInfo
Function Signature
-
func psCpuInfo() (cpuInfo [](github.com/shirou/gopsutil/v4/cpu).Info, err error)
+
func psCpuInfo() (cpuInfo []cpu.Info, err error)
@@ -2035,7 +2541,7 @@ a/b/c
-
4.6.1.3. psCpuPct
+
4.7.1.3. psCpuPct
Function Signature
@@ -2047,11 +2553,11 @@ a/b/c
-
4.6.1.4. psCpuTimes
+
4.7.1.4. psCpuTimes
Function Signature
-
func psCpuTimes(percpu bool) (cpuTimes []TimesStat, err error)
+
func psCpuTimes(percpu bool) (cpuTimes []cpu.TimesStat, err error)
@@ -2060,13 +2566,13 @@ a/b/c
-

4.6.2. Disk

+

4.7.2. Disk

-
4.6.2.1. psDiskIoCnts
+
4.7.2.1. psDiskIoCnts
Function Signature
-
func psDiskIoCnts(names ...string) (stats map[string]IOCountersStat, err error)
+
func psDiskIoCnts(names ...string) (stats map[string]disk.IOCountersStat, err error)
@@ -2074,7 +2580,7 @@ a/b/c
-
4.6.2.2. psDiskLabel
+
4.7.2.2. psDiskLabel
Function Signature
@@ -2086,11 +2592,11 @@ a/b/c
-
4.6.2.3. psDiskParts
+
4.7.2.3. psDiskParts
Function Signature
-
func psDiskParts(all bool) (parts [](github.com/shirou/gopsutil/v4/disk).PartitionStat, err error)
+
func psDiskParts(all bool) (parts []disk.PartitionStat, err error)
@@ -2098,7 +2604,7 @@ a/b/c
-
4.6.2.4. psDiskSerial
+
4.7.2.4. psDiskSerial
Function Signature
@@ -2110,11 +2616,11 @@ a/b/c
-
4.6.2.5. psDiskUsage
+
4.7.2.5. psDiskUsage
Function Signature
-
func psDiskUsage(path string) (usage *(github.com/shirou/gopsutil/v4/disk).UsageStat, err error)
+
func psDiskUsage(path string) (usage *disk.UsageStat, err error)
@@ -2123,9 +2629,9 @@ a/b/c
-

4.6.3. Host

+

4.7.3. Host

-
4.6.3.1. psHostBoot
+
4.7.3.1. psHostBoot
Function Signature
@@ -2137,7 +2643,7 @@ a/b/c
-
4.6.3.2. psHostId
+
4.7.3.2. psHostId
Function Signature
@@ -2149,11 +2655,11 @@ a/b/c
-
4.6.3.3. psHostInfo
+
4.7.3.3. psHostInfo
Function Signature
-
func psHostInfo() (info *(github.com/shirou/gopsutil/v4/host).InfoStat, err error)
+
func psHostInfo() (info *host.InfoStat, err error)
@@ -2161,7 +2667,7 @@ a/b/c
-
4.6.3.4. psHostKernArch
+
4.7.3.4. psHostKernArch
Function Signature
@@ -2173,7 +2679,7 @@ a/b/c
-
4.6.3.5. psHostKernVer
+
4.7.3.5. psHostKernVer
Function Signature
@@ -2185,7 +2691,7 @@ a/b/c
-
4.6.3.6. psHostPlatInfo
+
4.7.3.6. psHostPlatInfo
Function Signature
@@ -2200,7 +2706,7 @@ a/b/c
-
4.6.3.7. psHostPlatUptime
+
4.7.3.7. psHostPlatUptime
Function Signature
@@ -2212,11 +2718,11 @@ a/b/c
-
4.6.3.8. psHostUsers
+
4.7.3.8. psHostUsers
Function Signature
-
func psHostUsers() (users [](github.com/shirou/gopsutil/v4/host).UserStat, err error)
+
func psHostUsers() (users []host.UserStat, err error)
@@ -2224,7 +2730,7 @@ a/b/c
-
4.6.3.9. psHostPlatVirt
+
4.7.3.9. psHostPlatVirt
Function Signature
@@ -2240,13 +2746,13 @@ a/b/c
-

4.6.4. Load

+

4.7.4. Load

-
4.6.4.1. psLoadAvg
+
4.7.4.1. psLoadAvg
Function Signature
-
func psLoadAvg() (avg *(github.com/shirou/gopsutil/v4/load).AvgStat, err error)
+
func psLoadAvg() (avg *load.AvgStat, err error)
@@ -2254,11 +2760,11 @@ a/b/c
-
4.6.4.2. psLoadMisc
+
4.7.4.2. psLoadMisc
Function Signature
-
func psLoadMisc() (misc *(github.com/shirou/gopsutil/v4/load).MiscStat, err error)
+
func psLoadMisc() (misc *load.MiscStat, err error)
@@ -2267,13 +2773,13 @@ a/b/c
-

4.6.5. Memory

+

4.7.5. Memory

-
4.6.5.1. psMemExVMem
+
4.7.5.1. psMemExVMem
Function Signature
-
func psMemExVMem() (exVMem *(github.com/shirou/gopsutil/v4/mem).ExVirtualMemory, err error)
+
func psMemExVMem() (exVMem *mem.ExVirtualMemory, err error)
@@ -2320,11 +2826,11 @@ a/b/c
-
4.6.5.2. psMemSwap
+
4.7.5.2. psMemSwap
Function Signature
-
func psMemSwap() (swap *(github.com/shirou/gopsutil/v4/mem).SwapMemoryStat, err error)
+
func psMemSwap() (swap *mem.SwapMemoryStat, err error)
@@ -2332,11 +2838,11 @@ a/b/c
-
4.6.5.3. psMemSwapDevs
+
4.7.5.3. psMemSwapDevs
Function Signature
-
func psMemSwapDevs() (swapDevs []*(github.com/shirou/gopsutil/v4/mem).SwapDevice, err error)
+
func psMemSwapDevs() (swapDevs []*mem.SwapDevice, err error)
@@ -2344,11 +2850,11 @@ a/b/c
-
4.6.5.4. psMemVMem
+
4.7.5.4. psMemVMem
Function Signature
-
func psMemVMem() (vmem *(github.com/shirou/gopsutil/v4/mem).VirtualMemoryStat, err error)
+
func psMemVMem() (vmem *mem.VirtualMemoryStat, err error)
@@ -2357,13 +2863,13 @@ a/b/c
-

4.6.6. Network

+

4.7.6. Network

-
4.6.6.1. psNetConns
+
4.7.6.1. psNetConns
Function Signature
-
func psNetConns(kind string) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error)
+
func psNetConns(kind string) (conns []net.ConnectionStat, err error)
@@ -2371,11 +2877,11 @@ a/b/c
-
4.6.6.2. psNetConnsMax
+
4.7.6.2. psNetConnsMax
Function Signature
-
func psNetConnsMax(kind string, maxConn int) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error)
+
func psNetConnsMax(kind string, maxConn int) (conns []net.ConnectionStat, err error)
@@ -2383,11 +2889,11 @@ a/b/c
-
4.6.6.3. psNetConnsPid
+
4.7.6.3. psNetConnsPid
Function Signature
-
func psNetConnsPid(kind string, pid int32) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error)
+
func psNetConnsPid(kind string, pid int32) (conns []net.ConnectionStat, err error)
@@ -2395,11 +2901,11 @@ a/b/c
-
4.6.6.4. psNetConnsPidMax
+
4.7.6.4. psNetConnsPidMax
Function Signature
-
func psNetConnsPidMax(kind string, pid int32, maxConn int) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error)
+
func psNetConnsPidMax(kind string, pid int32, maxConn int) (conns []net.ConnectionStat, err error)
@@ -2407,11 +2913,11 @@ a/b/c
-
4.6.6.5. psNetCTStats
+
4.7.6.5. psNetCTStats
Function Signature
-
func psNetCTStats(percCpu bool) (ctStats [](github.com/shirou/gopsutil/v4/net).ConntrackStat, err error)
+
func psNetCTStats(percCpu bool) (ctStats []net.ConntrackStat, err error)
@@ -2419,11 +2925,11 @@ a/b/c
-
4.6.6.6. psNetCTStatList
+
4.7.6.6. psNetCTStatList
Function Signature
-
func psNetCTStatList() (ctStats *(github.com/shirou/gopsutil/v4/net).ConntrackStatList, err error)
+
func psNetCTStatList() (ctStats *net.ConntrackStatList, err error)
@@ -2431,11 +2937,11 @@ a/b/c
-
4.6.6.7. psNetFilterCnts
+
4.7.6.7. psNetFilterCnts
Function Signature
-
func psNetFilterCnts() (filterCnts [](github.com/shirou/gopsutil/v4/net).FilterStat, err error)
+
func psNetFilterCnts() (filterCnts []net.FilterStat, err error)
@@ -2443,11 +2949,11 @@ a/b/c
-
4.6.6.8. psNetIoCnts
+
4.7.6.8. psNetIoCnts
Function Signature
-
func psNetIoCnts(perNIC bool) (ioCnts [](github.com/shirou/gopsutil/v4/net).IOCountersStat, err error)
+
func psNetIoCnts(perNIC bool) (ioCnts []net.IOCountersStat, err error)
@@ -2455,11 +2961,11 @@ a/b/c
-
4.6.6.9. psNetIoCntsFile
+
4.7.6.9. psNetIoCntsFile
Function Signature
-
func psNetIoCntsFile(perNIC bool, filepath string) (ioCnts [](github.com/shirou/gopsutil/v4/net).IOCountersStat, err error)
+
func psNetIoCntsFile(perNIC bool, filepath string) (ioCnts []net.IOCountersStat, err error)
@@ -2467,11 +2973,11 @@ a/b/c
-
4.6.6.10. psNetIfaces
+
4.7.6.10. psNetIfaces
Function Signature
-
func psNetIfaces() (ioCnts [](github.com/shirou/gopsutil/v4/net).InterfaceStatList, err error)
+
func psNetIfaces() (ioCnts []net.InterfaceStatList, err error)
@@ -2479,7 +2985,7 @@ a/b/c
-
4.6.6.11. psNetPids
+
4.7.6.11. psNetPids
Function Signature
@@ -2491,11 +2997,11 @@ a/b/c
-
4.6.6.12. psNetProtoCnt
+
4.7.6.12. psNetProtoCnt
Function Signature
-
func psNetProtoCnt(protos []string) (protoCnts [](github.com/shirou/gopsutil/v4/net).ProtoCountersStat, err error)
+
func psNetProtoCnt(protos []string) (protoCnts []net.ProtoCountersStat, err error)
@@ -2517,7 +3023,7 @@ a/b/c
-
4.6.6.13. psNetRev
+
4.7.6.13. psNetRev
Function Signature
@@ -2544,13 +3050,13 @@ a/b/c
-

4.6.7. Processes

+

4.7.7. Processes

-
4.6.7.1. psProcs
+
4.7.7.1. psProcs
Function Signature
-
func psProcs(pid int32) (procs []*(github.com/shirou/gopsutil/v4/process).Process, err error)
+
func psProcs(pid int32) (procs []*process.Process, err error)
@@ -2558,11 +3064,11 @@ a/b/c
-
4.6.7.2. psProcNew
+
4.7.7.2. psProcNew
Function Signature
-
func psProcNew(pid int32) (proc *(github.com/shirou/gopsutil/v4/process).Process, err error)
+
func psProcNew(pid int32) (proc *process.Process, err error)
@@ -2570,7 +3076,7 @@ a/b/c
-
4.6.7.3. psProcPids
+
4.7.7.3. psProcPids
Function Signature
@@ -2582,7 +3088,7 @@ a/b/c
-
4.6.7.4. psProcPidExists
+
4.7.7.4. psProcPidExists
Function Signature
@@ -2595,13 +3101,13 @@ a/b/c
-

4.6.8. Sensors/Thermals

+

4.7.8. Sensors/Thermals

-
4.6.8.1. psSensorExTemp
+
4.7.8.1. psSensorExTemp
Function Signature
-
func psSensorExTemp() (temps [](github.com/shirou/gopsutil/v4/sensors).ExTemperature, err error)
+
func psSensorExTemp() (temps []sensors.ExTemperature, err error)
@@ -2623,11 +3129,11 @@ a/b/c
-
4.6.8.2. psSensorTemps
+
4.7.8.2. psSensorTemps
Function Signature
-
func psSensorTemps() (temps [](github.com/shirou/gopsutil/v4/sensors).TemperatureStat, err error)
+
func psSensorTemps() (temps []sensors.TemperatureStat, err error)
@@ -2636,7 +3142,7 @@ a/b/c
-

4.6.9. Windows Services

+

4.7.9. Windows Services

@@ -2652,11 +3158,11 @@ a/b/c
-
4.6.9.1. psWinsvcList
+
4.7.9.1. psWinsvcList
Function Signature
-
func psWinsvcList() (svcs [](github.com/shirou/gopsutil/v4/winservices).Service, err error)
+
func psWinsvcList() (svcs []winservices.Service, err error)
@@ -2678,11 +3184,11 @@ a/b/c
-
4.6.9.2. psWinsvcNew
+
4.7.9.2. psWinsvcNew
Function Signature
-
func psWinsvcNew(svcName string) (svc *(github.com/shirou/gopsutil/v4/winservices).Service, err error)
+
func psWinsvcNew(svcName string) (svc *winservices.Service, err error)
@@ -2706,9 +3212,9 @@ a/b/c
-

4.7. Strings

+

4.8. Strings

-

4.7.1. extIndent

+

4.8.1. extIndent

Function Signature
@@ -2733,7 +3239,7 @@ a/b/c
-

If <indentString> is set to \n and <levels> is always set to 1, this function can even be used to doubelspace text!

+

If <indentString> is set to \n and <levels> is always set to 1, this function can even be used to doublespace text!

@@ -2742,273 +3248,65 @@ a/b/c

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.

    -
  • -
-
-
-
-
-

4.8. Time/Dates/Timestamps

-
- +
+++++ + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-
Note
-
-
-

Some of these functions duplicate Sprig functionality, but are included here for predictable API.

-
-
-

Care has been taken to name these functions differently from the Sprig functions where possible and sensible.

-
-
ArgumentTypeDescription

levels

int

+

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

bool

+

If true, skip indenting the first line. This is particularly handy if you like to visually align your function calls in your templates.

+

skipEmpty

bool

+

If true, do not add an indent to empty lines (where an "empty line" means "only has a linebreak").

+

skipWhitespace

bool

+

If true, do not add an indent to lines that only consist of whitespace (spaces, tabs, etc.) and a linebreak.

+

indentString

string

+

The string to use as the "indent character". This can be any string, such as "<SP>" (0x20), "\t", ".", "|", "==" etc.

+

input

string

+

The text to be indented. Because it is the last argument, extIndent works with pipelined text as well.

+
-
-

4.8.1. tmDate

-
-
Function Signature
-
-
func tmDate(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) (date time.Time)
-
-
-
-

tmDate directly calls time.Date.

-
-
-
-

4.8.2. tmFloatMicro

-
-
Function Signature
-
-
func tmFloatMicro(t time.Time) (f64 float64)
-
-
-
-

tmFloatMicro directly calls (r00t2.io/goutils/timex).F64Microseconds.

-
-
-
-

4.8.3. tmFloatMilli

-
-
Function Signature
-
-
func tmFloatMilli(t time.Time) (f64 float64)
-
-
-
-

tmFloatMilli directly calls (r00t2.io/goutils/timex).F64Milliseconds.

-
-
-
-

4.8.4. tmFloatNano

-
-
Function Signature
-
-
func tmFloatNano(t time.Time) (f64 float64)
-
-
-
-

tmFloatNano directly calls (r00t2.io/goutils/timex).F64Nanoseconds.

-
-
-
-

4.8.5. tmFloat

-
-
Function Signature
-
-
func tmFloat(t time.Time) (f64 float64)
-
-
-
-

tmFloat directly calls (r00t2.io/goutils/timex).F64Seconds.

-
-
-
-

4.8.6. tmFmt

-
-
Function Signature
-
-
func tmFmt(fstr string, t time.Time) (out string)
-
-
-
-

tmFormat provides a more pipeline-friendly alternative to calling e.g.

-
-
-
-
{{- $t := tmNow -}}
-{{ $t.Format "<some time format string>" }}
-
-
-
-
-

4.8.7. tmNow

-
-
Function Signature
-
-
func tmNow() (now time.Time)
-
-
-
-

tmNow directly calls time.Now.

-
-
-
-

4.8.8. tmParseDur8n

-
-
Function Signature
-
-
func tmParseDur8n(s string) (d time.Duration, err error)
-
-
-
-

tmParseDur8n directly calls time.ParseDuration.

-
-
-
-

4.8.9. tmParseMonth

-
-
Function Signature
-
-
func tmParseMonth(v any) (mon time.Month, err error)
-
-
-
-

tmParseMonth attempts to first try tmParseMonthInt and then tries tmParseMonthStr if v is not "numeric".

-
-
-
-

4.8.10. tmParseMonthInt

-
-
Function Signature
-
-
func tmParseMonthInt(n any) (mon time.Month, err error)
-
-
-
-

tmParseMonthInt parses a number representation of month n to a time.Month. -n may be any numeric type or a string representation of a number (or a custom type derived from those).

-
-
-

A negative integer (or float, etc.) will be converted to a positive one (e.g. -66time.June).

-
-
-

Floats are rounded to the nearest integer.

-
-
-

The integer should map directly to the time.Month constants in the time module:

-
-
-
    -
  • -

    1: time.January

    -
  • -
  • -

    2: time.February

    -
  • -
  • -

    3: time.March

    -
  • -
  • -

    4: time.April

    -
  • -
  • -

    5: time.May

    -
  • -
  • -

    6: time.June

    -
  • -
  • -

    7: time.July

    -
  • -
  • -

    8: time.August

    -
  • -
  • -

    9: time.September

    -
  • -
  • -

    10: time.October

    -
  • -
  • -

    11: time.November

    -
  • -
  • -

    12: time.December

    -
  • -
-
-
-

If n resolves to 0, mon will be the current month (as determined by time.Now).

-
-
-

If n resolves to > 12, err will be sprigx.ErrBadMonth (though be sure to use errors.Is; it will be wrapped by (text/template).ExecError/(html/template).ExecError.

-
-
-
-

4.8.11. tmParseMonthStr

-
-
Function Signature
-
-
func tmParseMonthStr(s string) (mon time.Month, err error)
-
-
-
-

tmParseMonthStr parses a string representation s of a month to a time.Month.

-
-
-

It normalizes s to lowercase and only uses the first 3 characters (the minimum length needed to determine month name -uniqueness - "June" vs. "July", "March" vs. "May").

-
-
-

An empty (or whitespace-only) string will use the current month (as determined by time.Now).`

-
-
-
-

4.8.12. tmParseTime

-
-
Function Signature
-
-
func tmParseTime(layout, value string) (t time.Time, err error)
-
-
-
-

tmParseTime directly calls time.Parse.

-
-
-

Be sure that layout is a properly parseable layout format.

-
-

4.9. System/Platform/Architecture

@@ -3144,6 +3442,242 @@ uniqueness - "June" vs. "July", "March" vs. "May").

+
+

4.10. Time/Dates/Timestamps

+
+ + + + + +
+
Note
+
+
+

Some of these functions duplicate Sprig functionality, but are included here for predictable API.

+
+
+

Care has been taken to name these functions differently from the Sprig functions where possible and sensible.

+
+
+
+
+

4.10.1. tmDate

+
+
Function Signature
+
+
func tmDate(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) (date time.Time)
+
+
+
+

tmDate directly calls time.Date.

+
+
+
+

4.10.2. tmFloatMicro

+
+
Function Signature
+
+
func tmFloatMicro(t time.Time) (f64 float64)
+
+
+
+

tmFloatMicro directly calls (r00t2.io/goutils/timex).F64Microseconds.

+
+
+
+

4.10.3. tmFloatMilli

+
+
Function Signature
+
+
func tmFloatMilli(t time.Time) (f64 float64)
+
+
+
+

tmFloatMilli directly calls (r00t2.io/goutils/timex).F64Milliseconds.

+
+
+
+

4.10.4. tmFloatNano

+
+
Function Signature
+
+
func tmFloatNano(t time.Time) (f64 float64)
+
+
+
+

tmFloatNano directly calls (r00t2.io/goutils/timex).F64Nanoseconds.

+
+
+
+

4.10.5. tmFloat

+
+
Function Signature
+
+
func tmFloat(t time.Time) (f64 float64)
+
+
+
+

tmFloat directly calls (r00t2.io/goutils/timex).F64Seconds.

+
+
+
+

4.10.6. tmFmt

+
+
Function Signature
+
+
func tmFmt(fstr string, t time.Time) (out string)
+
+
+
+

tmFormat provides a more pipeline-friendly alternative to calling e.g.

+
+
+
+
{{- $t := tmNow -}}
+{{ $t.Format "<some time format string>" }}
+
+
+
+
+

4.10.7. tmNow

+
+
Function Signature
+
+
func tmNow() (now time.Time)
+
+
+
+

tmNow directly calls time.Now.

+
+
+
+

4.10.8. tmParseDur8n

+
+
Function Signature
+
+
func tmParseDur8n(s string) (d time.Duration, err error)
+
+
+
+

tmParseDur8n directly calls time.ParseDuration.

+
+
+
+

4.10.9. tmParseMonth

+
+
Function Signature
+
+
func tmParseMonth(v any) (mon time.Month, err error)
+
+
+
+

tmParseMonth attempts to first try tmParseMonthInt and then tries tmParseMonthStr if v is not "numeric".

+
+
+
+

4.10.10. tmParseMonthInt

+
+
Function Signature
+
+
func tmParseMonthInt(n any) (mon time.Month, err error)
+
+
+
+

tmParseMonthInt parses a number representation of month n to a time.Month. +n may be any numeric type or a string representation of a number (or a custom type derived from those).

+
+
+

A negative integer (or float, etc.) will be converted to a positive one (e.g. -66time.June).

+
+
+

Floats are rounded to the nearest integer.

+
+
+

The integer should map directly to the time.Month constants in the time module:

+
+
+
    +
  • +

    1: time.January

    +
  • +
  • +

    2: time.February

    +
  • +
  • +

    3: time.March

    +
  • +
  • +

    4: time.April

    +
  • +
  • +

    5: time.May

    +
  • +
  • +

    6: time.June

    +
  • +
  • +

    7: time.July

    +
  • +
  • +

    8: time.August

    +
  • +
  • +

    9: time.September

    +
  • +
  • +

    10: time.October

    +
  • +
  • +

    11: time.November

    +
  • +
  • +

    12: time.December

    +
  • +
+
+
+

If n resolves to 0, mon will be the current month (as determined by time.Now).

+
+
+

If n resolves to > 12, err will be sprigx.ErrBadMonth (though be sure to use errors.Is; it will be wrapped by (text/template).ExecError/(html/template).ExecError.

+
+
+
+

4.10.11. tmParseMonthStr

+
+
Function Signature
+
+
func tmParseMonthStr(s string) (mon time.Month, err error)
+
+
+
+

tmParseMonthStr parses a string representation s of a month to a time.Month.

+
+
+

It normalizes s to lowercase and only uses the first 3 characters (the minimum length needed to determine month name +uniqueness - "June" vs. "July", "March" vs. "May").

+
+
+

An empty (or whitespace-only) string will use the current month (as determined by time.Now).

+
+
+
+

4.10.12. tmParseTime

+
+
Function Signature
+
+
func tmParseTime(layout, value string) (t time.Time, err error)
+
+
+
+

tmParseTime directly calls time.Parse.

+
+
+

Be sure that layout is a properly parseable layout format.

+
+
+
@@ -3155,7 +3689,7 @@ uniqueness - "June" vs. "July", "March" vs. "May").

diff --git a/tplx/sprigx/README.md b/tplx/sprigx/README.md index 3211804..970a999 100644 --- a/tplx/sprigx/README.md +++ b/tplx/sprigx/README.md @@ -6,7 +6,7 @@ Brent Saner -Last rendered 2026-01-30 20:21:34 -0500 +Last rendered 2026-02-11 10:21:41 -0500
@@ -33,110 +33,139 @@ Table of Contents - [4.1.1. `dump`](#fn_dbg_dump) - [4.2. "Meta"/Template Helpers](#fn_meta) - [4.2.1. `metaIsNil`](#fn_meta_isnil) - - [4.3. Numbers/Math](#fn_num) - - [4.3.1. `numFloat32Str`](#fn_num_f32s) - - [4.3.2. `numFloat64`](#fn_num_f64) - - [4.3.3. `numFloat64Str`](#fn_num_f64s) - - [4.3.4. `numFloatStr`](#fn_num_fs) - - [4.4. Operating System](#fn_os) - - [4.4.1. `osFQDN`](#fn_os_fqdn) - - [4.4.2. `osGroupById`](#fn_os_grpid) - - [4.4.3. `osGroupByName`](#fn_os_grpnm) - - [4.4.4. `osHost`](#fn_os_hst) - - [4.4.5. `osHostname`](#fn_os_hstnm) - - [4.4.6. `osIdState`](#fn_os_idst) - - [4.4.7. `osUser`](#fn_os_usr) - - [4.4.8. `osUserById`](#fn_os_usrid) - - [4.4.9. `osUserByName`](#fn_os_usrnm) - - [4.5. Paths](#fn_path) - - [4.5.1. Generic](#fn_path_gnrc) - - [4.5.1.1. `pathJoin`](#fn_path_gnrc_pj) - - [4.5.1.2. `pathPipeJoin`](#fn_path_gnrc_ppj) - - [4.5.1.3. `pathSliceJoin`](#fn_path_gnrc_psj) - - [4.5.1.4. `pathSlicePipeJoin`](#fn_path_gnrc_pspj) - - [4.5.1.5. `pathSubJoin`](#fn_path_gnrc_psubj) - - [4.5.2. OS/Platform-Tailored](#fn_path_os) - - [4.5.2.1. `osPathJoin`](#fn_path_os_pj) - - [4.5.2.2. `osPathPipeJoin`](#fn_path_os_ppj) - - [4.5.2.3. `osPathSep`](#fn_path_ossep) - - [4.5.2.4. `osPathSliceJoin`](#fn_path_os_psj) - - [4.5.2.5. `osPathSlicePipeJoin`](#fn_path_os_pspj) - - [4.5.2.6. `osPathSubJoin`](#fn_path_os_psubj) - - [4.6. PSUtil](#fn_ps) - - [4.6.1. CPU/Processor](#fn_ps_cpu) - - [4.6.1.1. `psCpuCnts`](#fn_ps_cpu_cnts) - - [4.6.1.2. `psCpuInfo`](#fn_ps_cpu_info) - - [4.6.1.3. `psCpuPct`](#fn_ps_cpu_pct) - - [4.6.1.4. `psCpuTimes`](#fn_ps_cpu_tms) - - [4.6.2. Disk](#fn_ps_dsk) - - [4.6.2.1. `psDiskIoCnts`](#fn_ps_dsk_iocnts) - - [4.6.2.2. `psDiskLabel`](#fn_ps_dsk_lbl) - - [4.6.2.3. `psDiskParts`](#fn_ps_dsk_parts) - - [4.6.2.4. `psDiskSerial`](#fn_ps_dsk_srl) - - [4.6.2.5. `psDiskUsage`](#fn_ps_dsk_usg) - - [4.6.3. Host](#fn_ps_hst) - - [4.6.3.1. `psHostBoot`](#fn_ps_hst_boot) - - [4.6.3.2. `psHostId`](#fn_ps_hst_id) - - [4.6.3.3. `psHostInfo`](#fn_ps_hst_info) - - [4.6.3.4. `psHostKernArch`](#fn_ps_hst_krnarch) - - [4.6.3.5. `psHostKernVer`](#fn_ps_hst_krnver) - - [4.6.3.6. `psHostPlatInfo`](#fn_ps_hst_plat) - - [4.6.3.7. `psHostPlatUptime`](#fn_ps_hst_uptm) - - [4.6.3.8. `psHostUsers`](#fn_ps_hst_usrs) - - [4.6.3.9. `psHostPlatVirt`](#fn_ps_hst_virt) - - [4.6.4. Load](#fn_ps_ld) - - [4.6.4.1. `psLoadAvg`](#fn_ps_ld_avg) - - [4.6.4.2. `psLoadMisc`](#fn_ps_ld_misc) - - [4.6.5. Memory](#fn_ps_mem) - - [4.6.5.1. `psMemExVMem`](#fn_ps_mem_exvmem) - - [4.6.5.2. `psMemSwap`](#fn_ps_mem_swap) - - [4.6.5.3. `psMemSwapDevs`](#fn_ps_mem_swapdevs) - - [4.6.5.4. `psMemVMem`](#fn_ps_mem_vmem) - - [4.6.6. Network](#fn_ps_net) - - [4.6.6.1. `psNetConns`](#fn_ps_net_conns) - - [4.6.6.2. `psNetConnsMax`](#fn_ps_net_connsmax) - - [4.6.6.3. `psNetConnsPid`](#fn_ps_net_connspid) - - [4.6.6.4. `psNetConnsPidMax`](#fn_ps_net_connspidmax) - - [4.6.6.5. `psNetCTStats`](#fn_ps_net_ct) - - [4.6.6.6. `psNetCTStatList`](#fn_ps_net_ctlist) - - [4.6.6.7. `psNetFilterCnts`](#fn_ps_net_fltcnt) - - [4.6.6.8. `psNetIoCnts`](#fn_ps_net_iocnts) - - [4.6.6.9. `psNetIoCntsFile`](#fn_ps_net_iocntsfl) - - [4.6.6.10. `psNetIfaces`](#fn_ps_net_ifaces) - - [4.6.6.11. `psNetPids`](#fn_ps_net_pids) - - [4.6.6.12. `psNetProtoCnt`](#fn_ps_net_protocnts) - - [4.6.6.13. `psNetRev`](#fn_ps_net_rev) - - [4.6.7. Processes](#fn_ps_proc) - - [4.6.7.1. `psProcs`](#fn_ps_procs_procs) - - [4.6.7.2. `psProcNew`](#fn_ps_proc_new) - - [4.6.7.3. `psProcPids`](#fn_ps_proc_pids) - - [4.6.7.4. `psProcPidExists`](#fn_ps_proc_pidxst) - - [4.6.8. Sensors/Thermals](#fn_ps_sns) - - [4.6.8.1. `psSensorExTemp`](#fn_ps_sns_extemp) - - [4.6.8.2. `psSensorTemps`](#fn_ps_sns_temps) - - [4.6.9. Windows Services](#fn_ps_winsvc) - - [4.6.9.1. `psWinsvcList`](#fn_ps_winsvc_list) - - [4.6.9.2. `psWinsvcNew`](#fn_ps_winsvc_new) - - [4.7. Strings](#fn_str) - - [4.7.1. `extIndent`](#fn_str_extindent) - - [4.8. Time/Dates/Timestamps](#fn_tm) - - [4.8.1. `tmDate`](#fn_tm_date) - - [4.8.2. `tmFloatMicro`](#fn_tm_fltmic) - - [4.8.3. `tmFloatMilli`](#fn_tm_fltmill) - - [4.8.4. `tmFloatNano`](#fn_tm_fltnano) - - [4.8.5. `tmFloat`](#fn_tm_flt) - - [4.8.6. `tmFmt`](#fn_tm_fmt) - - [4.8.7. `tmNow`](#fn_tm_now) - - [4.8.8. `tmParseDur8n`](#fn_tm_pdur8n) - - [4.8.9. `tmParseMonth`](#fn_tm_pmnth) - - [4.8.10. `tmParseMonthInt`](#fn_tm_pmnthi) - - [4.8.11. `tmParseMonthStr`](#fn_tm_pmnths) - - [4.8.12. `tmParseTime`](#fn_tm_ptm) + - [4.3. Networking](#fn_net_all) + - [4.3.1. `net`](#fn_net) + - [4.3.1.1. `netCidrMask`](#fn_net_cidrmask) + - [4.3.1.2. `netExtractAddr`](#fn_net_cidra) + - [4.3.1.3. `netExtractHost`](#fn_net_hph) + - [4.3.1.4. `netExtractIpnet`](#fn_net_cidrn) + - [4.3.1.5. `netExtractPort`](#fn_net_hpp) + - [4.3.1.6. `netIfaces`](#fn_net_ifaces) + - [4.3.1.7. `netIp4Mask`](#fn_net_ip4mask) + - [4.3.1.8. `netJoinHostPort`](#fn_net_jhp) + - [4.3.1.9. `netParseIP`](#fn_net_parseip) + - [4.3.2. `net/netip`](#fn_netip) + - [4.3.2.1. `netipAddrPort`](#fn_netip_addrport) + - [4.3.2.2. `netipParseAddr`](#fn_netip_parseaddr) + - [4.3.2.3. `netipParseAddrPort`](#fn_netip_pap) + - [4.3.2.4. `netipParsePrefix`](#fn_netip_parsepfx) + - [4.3.2.5. `netipPrefix`](#fn_netip_pfx) + - [4.3.3. `go4.org/netipx`](#fn_netipx) + - [4.3.3.1. `netipxAddrIpNet`](#fn_netipx_addripnet) + - [4.3.3.2. `netipxCmpPfx`](#fn_netipx_cmppfx) + - [4.3.3.3. `netipxFromStdAddr`](#fn_netipx_fromstdaddr) + - [4.3.3.4. `netipxFromIp`](#fn_netipx_fromip) + - [4.3.3.5. `netipxFromIpNet`](#fn_netipx_fromipnet) + - [4.3.3.6. `netipxParseRange`](#fn_netipx_parserange) + - [4.3.3.7. `netipxPfxAddr`](#fn_netipx_pfxaddr) + - [4.3.3.8. `netipxPfxIpNet`](#fn_netipx_pfxipnet) + - [4.3.3.9. `netipxPfxLast`](#fn_netipx_pfxlast) + - [4.3.3.10. `netipxPfxRange`](#fn_netipx_pfxrange) + - [4.3.3.11. `netipxRange`](#fn_netipx_range) + - [4.4. Numbers/Math](#fn_num) + - [4.4.1. `numFloat32Str`](#fn_num_f32s) + - [4.4.2. `numFloat64`](#fn_num_f64) + - [4.4.3. `numFloat64Str`](#fn_num_f64s) + - [4.4.4. `numFloatStr`](#fn_num_fs) + - [4.5. Operating System](#fn_os) + - [4.5.1. `osFQDN`](#fn_os_fqdn) + - [4.5.2. `osGroupById`](#fn_os_grpid) + - [4.5.3. `osGroupByName`](#fn_os_grpnm) + - [4.5.4. `osHost`](#fn_os_hst) + - [4.5.5. `osHostname`](#fn_os_hstnm) + - [4.5.6. `osIdState`](#fn_os_idst) + - [4.5.7. `osUser`](#fn_os_usr) + - [4.5.8. `osUserById`](#fn_os_usrid) + - [4.5.9. `osUserByName`](#fn_os_usrnm) + - [4.6. Paths](#fn_path) + - [4.6.1. Generic](#fn_path_gnrc) + - [4.6.1.1. `pathJoin`](#fn_path_gnrc_pj) + - [4.6.1.2. `pathPipeJoin`](#fn_path_gnrc_ppj) + - [4.6.1.3. `pathSliceJoin`](#fn_path_gnrc_psj) + - [4.6.1.4. `pathSlicePipeJoin`](#fn_path_gnrc_pspj) + - [4.6.1.5. `pathSubJoin`](#fn_path_gnrc_psubj) + - [4.6.2. OS/Platform-Tailored](#fn_path_os) + - [4.6.2.1. `osPathJoin`](#fn_path_os_pj) + - [4.6.2.2. `osPathPipeJoin`](#fn_path_os_ppj) + - [4.6.2.3. `osPathSep`](#fn_path_ossep) + - [4.6.2.4. `osPathSliceJoin`](#fn_path_os_psj) + - [4.6.2.5. `osPathSlicePipeJoin`](#fn_path_os_pspj) + - [4.6.2.6. `osPathSubJoin`](#fn_path_os_psubj) + - [4.7. PSUtil](#fn_ps) + - [4.7.1. CPU/Processor](#fn_ps_cpu) + - [4.7.1.1. `psCpuCnts`](#fn_ps_cpu_cnts) + - [4.7.1.2. `psCpuInfo`](#fn_ps_cpu_info) + - [4.7.1.3. `psCpuPct`](#fn_ps_cpu_pct) + - [4.7.1.4. `psCpuTimes`](#fn_ps_cpu_tms) + - [4.7.2. Disk](#fn_ps_dsk) + - [4.7.2.1. `psDiskIoCnts`](#fn_ps_dsk_iocnts) + - [4.7.2.2. `psDiskLabel`](#fn_ps_dsk_lbl) + - [4.7.2.3. `psDiskParts`](#fn_ps_dsk_parts) + - [4.7.2.4. `psDiskSerial`](#fn_ps_dsk_srl) + - [4.7.2.5. `psDiskUsage`](#fn_ps_dsk_usg) + - [4.7.3. Host](#fn_ps_hst) + - [4.7.3.1. `psHostBoot`](#fn_ps_hst_boot) + - [4.7.3.2. `psHostId`](#fn_ps_hst_id) + - [4.7.3.3. `psHostInfo`](#fn_ps_hst_info) + - [4.7.3.4. `psHostKernArch`](#fn_ps_hst_krnarch) + - [4.7.3.5. `psHostKernVer`](#fn_ps_hst_krnver) + - [4.7.3.6. `psHostPlatInfo`](#fn_ps_hst_plat) + - [4.7.3.7. `psHostPlatUptime`](#fn_ps_hst_uptm) + - [4.7.3.8. `psHostUsers`](#fn_ps_hst_usrs) + - [4.7.3.9. `psHostPlatVirt`](#fn_ps_hst_virt) + - [4.7.4. Load](#fn_ps_ld) + - [4.7.4.1. `psLoadAvg`](#fn_ps_ld_avg) + - [4.7.4.2. `psLoadMisc`](#fn_ps_ld_misc) + - [4.7.5. Memory](#fn_ps_mem) + - [4.7.5.1. `psMemExVMem`](#fn_ps_mem_exvmem) + - [4.7.5.2. `psMemSwap`](#fn_ps_mem_swap) + - [4.7.5.3. `psMemSwapDevs`](#fn_ps_mem_swapdevs) + - [4.7.5.4. `psMemVMem`](#fn_ps_mem_vmem) + - [4.7.6. Network](#fn_ps_net) + - [4.7.6.1. `psNetConns`](#fn_ps_net_conns) + - [4.7.6.2. `psNetConnsMax`](#fn_ps_net_connsmax) + - [4.7.6.3. `psNetConnsPid`](#fn_ps_net_connspid) + - [4.7.6.4. `psNetConnsPidMax`](#fn_ps_net_connspidmax) + - [4.7.6.5. `psNetCTStats`](#fn_ps_net_ct) + - [4.7.6.6. `psNetCTStatList`](#fn_ps_net_ctlist) + - [4.7.6.7. `psNetFilterCnts`](#fn_ps_net_fltcnt) + - [4.7.6.8. `psNetIoCnts`](#fn_ps_net_iocnts) + - [4.7.6.9. `psNetIoCntsFile`](#fn_ps_net_iocntsfl) + - [4.7.6.10. `psNetIfaces`](#fn_ps_net_ifaces) + - [4.7.6.11. `psNetPids`](#fn_ps_net_pids) + - [4.7.6.12. `psNetProtoCnt`](#fn_ps_net_protocnts) + - [4.7.6.13. `psNetRev`](#fn_ps_net_rev) + - [4.7.7. Processes](#fn_ps_proc) + - [4.7.7.1. `psProcs`](#fn_ps_procs_procs) + - [4.7.7.2. `psProcNew`](#fn_ps_proc_new) + - [4.7.7.3. `psProcPids`](#fn_ps_proc_pids) + - [4.7.7.4. `psProcPidExists`](#fn_ps_proc_pidxst) + - [4.7.8. Sensors/Thermals](#fn_ps_sns) + - [4.7.8.1. `psSensorExTemp`](#fn_ps_sns_extemp) + - [4.7.8.2. `psSensorTemps`](#fn_ps_sns_temps) + - [4.7.9. Windows Services](#fn_ps_winsvc) + - [4.7.9.1. `psWinsvcList`](#fn_ps_winsvc_list) + - [4.7.9.2. `psWinsvcNew`](#fn_ps_winsvc_new) + - [4.8. Strings](#fn_str) + - [4.8.1. `extIndent`](#fn_str_extindent) - [4.9. System/Platform/Architecture](#fn_sys) - [4.9.1. `sysArch`](#fn_sys_arch) - [4.9.2. `sysNumCpu`](#fn_sys_numcpu) - [4.9.3. `sysOsName`](#fn_sys_os) - [4.9.4. `sysRuntime`](#fn_sys_rntm) + - [4.10. Time/Dates/Timestamps](#fn_tm) + - [4.10.1. `tmDate`](#fn_tm_date) + - [4.10.2. `tmFloatMicro`](#fn_tm_fltmic) + - [4.10.3. `tmFloatMilli`](#fn_tm_fltmill) + - [4.10.4. `tmFloatNano`](#fn_tm_fltnano) + - [4.10.5. `tmFloat`](#fn_tm_flt) + - [4.10.6. `tmFmt`](#fn_tm_fmt) + - [4.10.7. `tmNow`](#fn_tm_now) + - [4.10.8. `tmParseDur8n`](#fn_tm_pdur8n) + - [4.10.9. `tmParseMonth`](#fn_tm_pmnth) + - [4.10.10. `tmParseMonthInt`](#fn_tm_pmnthi) + - [4.10.11. `tmParseMonthStr`](#fn_tm_pmnths) + - [4.10.12. `tmParseTime`](#fn_tm_ptm)
@@ -193,8 +222,10 @@ it may not render correctly.

href="https://git.r00t2.io/r00t2/go_goutils/src/branch/master/tplx/sprigx/README.adoc" target="_blank" rel="noopener">the AsciiDoc rendering or by downloading and viewing the HTML version.

+href="https://git.r00t2.io/r00t2/go_goutils/src/branch/master/tplx/sprigx/README.html" +target="_blank" rel="noopener">HTML version and/or PDF version.

@@ -565,7 +596,7 @@ Function Signature
``` rouge -func CombinedHtmlFuncMap(preferSprigX bool) (fmap (html/template).FuncMap) +func CombinedHtmlFuncMap(preferSprigX bool) (fmap template.FuncMap) ```
@@ -575,7 +606,7 @@ func CombinedHtmlFuncMap(preferSprigX bool) (fmap (html/template).FuncMap)
This function returns an -[`(html/template).FuncMap`](https://pkg.go.dev/html/template#FuncMap) +[`html/template.FuncMap`](https://pkg.go.dev/html/template#FuncMap) function map (like [`HtmlFuncMap`](#lib_hfmap)) combined with ``` rouge -func CombinedTxtFuncMap(preferSprigX bool) (fmap (text/template).FuncMap) +func CombinedTxtFuncMap(preferSprigX bool) (fmap template.FuncMap) ```
@@ -619,7 +650,7 @@ func CombinedTxtFuncMap(preferSprigX bool) (fmap (text/template).FuncMap) @@ -701,7 +732,7 @@ func HtmlFuncMap() (fmap (html/template).FuncMap) This function returns a SprigX (html/template).FuncMap. +rel="noopener">html/template.FuncMap.
@@ -761,7 +792,7 @@ Function Signature
``` rouge -func TxtFuncMap() (fmap (text/template).FuncMap) +func TxtFuncMap() (fmap template.FuncMap) ```
@@ -772,7 +803,7 @@ func TxtFuncMap() (fmap (text/template).FuncMap) This function returns a SprigX (text/template).FuncMap. +rel="noopener">text/template.FuncMap.
@@ -797,9 +828,30 @@ the `sprigx` functions.
-Each function includes its function signature to indicate what types of -arguments/parameters it accepts, what it returns, and if it may -potentially return an error or not. +Each function includes its ***Function Signature*** to indicate what +arguments/parameters it accepts, their type(s), what it returns, and the +returned value(s) type(s). + +
+ +
+ +Because Go template functions can only return either: + +
+ +
+ +- a single value of any type, or + +- a value of any type and an `error` (in that order) + +
+ +
+ +you can easily determine whether a function can return an error or not +by simply referring to the Function Signature.
@@ -832,8 +884,7 @@ func dump(a ...interface{}) (out string)
The `dump` function directly calls -github.com/davecgh/go-spew/spew.Sdump for whatever object(s) is/are passed to it. @@ -894,11 +945,994 @@ false for e.g. `false` booleans AND nils.
-### 4.3. Numbers/Math +### 4.3. Networking + +
+ +These template functions use capabilities from: + +
+ +
+ +- [`net`](#fn_net) + +- [`net/netip`](#fn_netip) + +- [`go4.org/netipx`](#fn_netipx) + +
+ +
+ +The function prefix is used to indicate which module/package a function +is added from. + +
-#### 4.3.1. +#### 4.3.1. net + +
+ +These template functions contain capabilities from +net. + +
+ +
+ +##### 4.3.1.1. +netCidrMask + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netCidrMask(ones, bits int) (mask net.IPMask) +``` + +
+ +
+ +
+ +`netCidrMask` directly calls +net.CIDRMask. + +
+ +
+ +
+ +##### 4.3.1.2. +netExtractAddr + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netExtractAddr(s string) (addr net.IP, err error) +``` + +
+ +
+ +
+ +`netExtractAddr` wraps +net.ParseCIDR and returns the +net.IP component. + +
+ +
+ +
+ +##### 4.3.1.3. +netExtractHost + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netExtractHost(hostPort string) (host string, err error) +``` + +
+ +
+ +
+ +`netExtractHost` wraps +net.SplitHostPort and returns the host +component (as a string). + +
+ +
+ +
+ +##### 4.3.1.4. +netExtractIpnet + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netExtractIpnet(s string) (ipNet *net.IPNet, err error) +``` + +
+ +
+ +
+ +`netExtractIpnet` wraps +net.ParseCIDR and returns the +net.IPNet component. + +
+ +
+ +
+ +##### 4.3.1.5. +netExtractPort + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netExtractPort(hostPort string) (port uint16, err error) +``` + +
+ +
+ +
+ +`netExtractPort` wraps +net.SplitHostPort and returns the port +component (as a uint16). + +
+ +
+ +
+ +##### 4.3.1.6. +netIfaces + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netIfaces() (ifaces []net.Interface, err error) +``` + +
+ +
+ +
+ +`netIfaces` directly calls +net.Interfaces. + +
+ +
+ +
+ +##### 4.3.1.7. +netIp4Mask + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netIp4Mask(a, b, c, d any) (mask net.IPMask, err error) +``` + +
+ +
+ +
+ +`netIp4Mask` wraps +net.IPv4Mask. + +
+ +
+ +It is wrapped so that `a`, `b`, `c`, and `d` may be a string: + +
+ +
+ +
+ +``` rouge +{{- $mask := netIp4Mask "198" "51" "100" "10" -}} +``` + +
+ +
+ +
+ +or integers/other numeric: + +
+ +
+ +
+ +``` rouge +{{- $mask := netIp4Mask 198 51 100 10 -}} +``` + +
+ +
+ +
+ +or bytes: + +
+ +
+ +
+ +``` rouge +{{- $mask := netIp4Mask 0xc6 0x33 0x64 0x0a -}} +``` + +
+ +
+ +
+ +or even a mix: + +
+ +
+ +
+ +``` rouge +{{- $mask := netIp4Mask "198" 51 "100" 0x0a -}} +``` + +
+ +
+ +
+ +
+ +##### 4.3.1.8. +netJoinHostPort + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netJoinHostPort(host, port string) (out string) +``` + +
+ +
+ +
+ +`netJoinHostPort` directly calls +net.JoinHostPort. + +
+ +
+ +
+ +##### 4.3.1.9. +netParseIP + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netParseIP(s string) (ip net.IP) +``` + +
+ +
+ +
+ +`netParseIP` directly calls +net.ParseIP. + +
+ +
+ +
+ +
+ +#### 4.3.2. net/netip + +
+ +These template functions contain capabilities from +net/netip. + +
+ +
+ +##### 4.3.2.1. +netipAddrPort + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipAddrPort(ip netip.Addr, port uint16) (addrPort netip.AddrPort) +``` + +
+ +
+ +
+ +`netipAddrPort` directly calls +net/netip.AddrPortFrom. + +
+ +
+ +
+ +##### 4.3.2.2. +netipParseAddr + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipParseAddr(s string) (addr netip.Addr, err error) +``` + +
+ +
+ +
+ +`netipParseAddr` directly calls +net/netip.ParseAddr. + +
+ +
+ +
+ +##### 4.3.2.3. +netipParseAddrPort + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipParseAddrPort(s string) (addrPort netip.AddrPort, err error) +``` + +
+ +
+ +
+ +`netipParseAddrPort` directly calls +net/netip.ParseAddrPort. + +
+ +
+ +
+ +##### 4.3.2.4. +netipParsePrefix + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipParsePrefix(s string) (pfx netip.Prefix, err error) +``` + +
+ +
+ +
+ +`netipParsePrefix` directly calls +net/netip.ParsePrefix. + +
+ +
+ +
+ +##### 4.3.2.5. +netipPrefix + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipPrefix(ip netip.Addr, bits int) (pfx netip.Prefix) +``` + +
+ +
+ +
+ +`netipPrefix` directly calls +net/netip.PrefixFrom. + +
+ +
+ +
+ +
+ +#### 4.3.3. go4.org/netipx + +
+ +These template functions contain capabilities from +go4.org/netipx. + +
+ +
+ +##### 4.3.3.1. +netipxAddrIpNet + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxAddrIpNet(addr netip.Addr) (ipNet *net.IPNet) +``` + +
+ +
+ +
+ +`netipxAddrIpNet` directly calls +go4.org/netipx.AddrIPNet. + +
+ +
+ +
+ +##### 4.3.3.2. +netipxCmpPfx + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxCmpPfx(a, b netip.Prefix) (cmp int) +``` + +
+ +
+ +
+ +`netipxCmpPfx` directly calls +go4.org/netipx.ComparePrefix. + +
+ +
+ +
+ +##### 4.3.3.3. +netipxFromStdAddr + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxFromStdAddr(ip net.IP, port int, zone string) (addrPort netip.AddrPort, err error) +``` + +
+ +
+ +
+ +`netipxFromStdAddr` wraps +go4.org/netipx.FromStdAddr. Instead of +returning a boolean as the second value, it will instead be an error if +the wrapped boolean is false. + +
+ +
+ +
+ +##### 4.3.3.4. +netipxFromIp + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxFromIp(ip net.IP) (addr netip.Addr, err error) +``` + +
+ +
+ +
+ +`netipxFromIp` wraps +go4.org/netipx.FromStdIP. Instead of +returning a boolean as the second value, it will instead be an error if +the wrapped boolean is false. + +
+ +
+ +
+ +##### 4.3.3.5. +netipxFromIpNet + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxFromIpNet(ipNet *net.IPNet) (pfx netip.Prefix, err error) +``` + +
+ +
+ +
+ +`netipxFromIpNet` wraps +go4.org/netipx.FromStdIPNet. Instead of +returning a boolean as the second value, it will instead be an error if +the wrapped boolean is false. + +
+ +
+ +
+ +##### 4.3.3.6. +netipxParseRange + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxParseRange(s string) (ipRange netipx.IPRange, err error) +``` + +
+ +
+ +
+ +`netipxRange` directly calls +go4.org/netipx.ParseIPRange. + +
+ +
+ +
+ +##### 4.3.3.7. +netipxPfxAddr + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxPfxAddr(s string) (addr netip.Addr, err error) +``` + +
+ +
+ +
+ +`netipxPfxAddr` directly calls +go4.org/netipx.ParsePrefixOrAddr. + +
+ +
+ +
+ +##### 4.3.3.8. +netipxPfxIpNet + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxPfxIpNet(pfx netip.Prefix) (ipNet *net.IPNet) +``` + +
+ +
+ +
+ +`netipxPfxIpNet` directly calls +go4.org/netipx.PrefixIPNet. + +
+ +
+ +
+ +##### 4.3.3.9. +netipxPfxLast + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxPfxLast(pfx netip.Prefix) (addr netip.Addr) +``` + +
+ +
+ +
+ +`netipxPfxLast` directly calls +go4.org/netipx.PrefixLastIP. + +
+ +
+ +
+ +##### 4.3.3.10. +netipxPfxRange + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxPfxRange(pfx netip.Prefix) (ipRange netipx.IPRange) +``` + +
+ +
+ +
+ +`netipxPfxRange` directly calls +go4.org/netipx.RangeOfPrefix. + +
+ +
+ +
+ +##### 4.3.3.11. +netipxRange + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func netipxRange(from, to netip.Addr) (ipRange netipx.IPRange) +``` + +
+ +
+ +
+ +`netipxRange` directly calls +go4.org/netipx.IPRangeFrom. + +
+ +
+ +
+ +
+ +
+ +### 4.4. Numbers/Math + +
+ +#### 4.4.1. numFloat32Str
@@ -930,7 +1964,7 @@ string representation of a `float32`.
-#### 4.3.2. numFloat64 +#### 4.4.2. numFloat64
@@ -961,7 +1995,7 @@ type of numeric value to a `float64`.
-#### 4.3.3. +#### 4.4.3. numFloat64Str
@@ -993,7 +2027,7 @@ string representation of a `float64`.
-#### 4.3.4. numFloatStr +#### 4.4.4. numFloatStr
@@ -1033,11 +2067,11 @@ numeric value.
-### 4.4. Operating System +### 4.5. Operating System
-#### 4.4.1. osFQDN +#### 4.5.1. osFQDN
@@ -1095,7 +2129,7 @@ rel="noopener">os.Hostname, use
-#### 4.4.2. osGroupById +#### 4.5.2. osGroupById
@@ -1136,7 +2170,7 @@ accept either a `string` **or** an `int` as the GID.
-#### 4.4.3. +#### 4.5.3. osGroupByName
@@ -1177,7 +2211,7 @@ rel="noopener">os/user.LookupGroup.
-#### 4.4.4. osHost +#### 4.5.4. osHost
@@ -1202,7 +2236,8 @@ func osHost() (out string, err error) `osHost` returns the "short hostname" by calling os.Hostname and returning the first -"host label" (as RFCs refer to it). +"host label" (as RFCs refer to it). This is commonly/colloquially called +the "hostname" or "hostname without the domain part".
@@ -1240,7 +2275,7 @@ osHost {{ $h }} should be equal to first label of FQDN {{ $cmp }}. Tip
-

The splitList function shown aboce is from the The splitList function shown above is from the sprig string slice functions.

@@ -1264,7 +2299,7 @@ rel="noopener">os.Hostname, use
-#### 4.4.5. osHostname +#### 4.5.5. osHostname
@@ -1296,7 +2331,7 @@ rel="noopener">os.Hostname.
-#### 4.4.6. osIdState +#### 4.5.6. osIdState
@@ -1359,7 +2394,7 @@ struct for cross-platform compatibility.

-#### 4.4.7. osUser +#### 4.5.7. osUser
@@ -1399,7 +2434,7 @@ rel="noopener">os/user.Current.
-#### 4.4.8. osUserById +#### 4.5.8. osUserById
@@ -1440,7 +2475,7 @@ either a `string` **or** an `int` as the UID.
-#### 4.4.9. osUserByName +#### 4.5.9. osUserByName
@@ -1482,11 +2517,11 @@ rel="noopener">os/user.Lookup.
-### 4.5. Paths +### 4.6. Paths
-#### 4.5.1. Generic +#### 4.6.1. Generic
@@ -1498,7 +2533,7 @@ These operate similar to
-##### 4.5.1.1. +##### 4.6.1.1. pathJoin
@@ -1590,7 +2625,7 @@ a/b/c
-##### 4.5.1.2. +##### 4.6.1.2. pathPipeJoin
@@ -1666,7 +2701,7 @@ a/b/c
-##### 4.5.1.3. +##### 4.6.1.3. pathSliceJoin
@@ -1757,7 +2792,7 @@ a/b/c
-##### 4.5.1.4. +##### 4.6.1.4. pathSlicePipeJoin
@@ -1850,7 +2885,7 @@ renders as:
-##### 4.5.1.5. +##### 4.6.1.5. pathSubJoin
@@ -1925,7 +2960,7 @@ renders as:
-#### 4.5.2. OS/Platform-Tailored +#### 4.6.2. OS/Platform-Tailored
@@ -1968,7 +3003,7 @@ path bases/roots if needed.

-##### 4.5.2.1. +##### 4.6.2.1. osPathJoin
@@ -2090,7 +3125,7 @@ C:/a/b/c
-##### 4.5.2.2. +##### 4.6.2.2. osPathPipeJoin
@@ -2191,7 +3226,7 @@ Linux, macOS)

-##### 4.5.2.3. +##### 4.6.2.3. osPathSep
@@ -2278,7 +3313,7 @@ Linux, macOS)

-##### 4.5.2.4. +##### 4.6.2.4. osPathSliceJoin
@@ -2395,7 +3430,7 @@ a/b/c
-##### 4.5.2.5. +##### 4.6.2.5. osPathSlicePipeJoin
@@ -2511,7 +3546,7 @@ Linux, macOS)

-##### 4.5.2.6. +##### 4.6.2.6. osPathSubJoin
@@ -2614,7 +3649,7 @@ Linux, macOS)

-### 4.6. PSUtil +### 4.7. PSUtil
@@ -2627,11 +3662,11 @@ rel="noopener">github.com/shirou/gopsutil/v4 packages.
-#### 4.6.1. CPU/Processor +#### 4.7.1. CPU/Processor
-##### 4.6.1.1. +##### 4.7.1.1. psCpuCnts
@@ -2665,7 +3700,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/cpu.Counts.
-##### 4.6.1.2. +##### 4.7.1.2. psCpuInfo
@@ -2679,7 +3714,7 @@ Function Signature
``` rouge -func psCpuInfo() (cpuInfo [](github.com/shirou/gopsutil/v4/cpu).Info, err error) +func psCpuInfo() (cpuInfo []cpu.Info, err error) ```
@@ -2699,7 +3734,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/cpu.Info.
-##### 4.6.1.3. psCpuPct +##### 4.7.1.3. psCpuPct
@@ -2732,7 +3767,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/cpu.Percent.
-##### 4.6.1.4. +##### 4.7.1.4. psCpuTimes
@@ -2746,7 +3781,7 @@ Function Signature
``` rouge -func psCpuTimes(percpu bool) (cpuTimes []TimesStat, err error) +func psCpuTimes(percpu bool) (cpuTimes []cpu.TimesStat, err error) ```
@@ -2768,11 +3803,11 @@ rel="noopener">github.com/shirou/gopsutil/v4/cpu.Times.
-#### 4.6.2. Disk +#### 4.7.2. Disk
-##### 4.6.2.1. +##### 4.7.2.1. psDiskIoCnts
@@ -2786,7 +3821,7 @@ Function Signature
``` rouge -func psDiskIoCnts(names ...string) (stats map[string]IOCountersStat, err error) +func psDiskIoCnts(names ...string) (stats map[string]disk.IOCountersStat, err error) ```
@@ -2806,7 +3841,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/disk.IOCounters.
-##### 4.6.2.2. +##### 4.7.2.2. psDiskLabel
@@ -2840,7 +3875,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/disk.Label.
-##### 4.6.2.3. +##### 4.7.2.3. psDiskParts
@@ -2854,7 +3889,7 @@ Function Signature
``` rouge -func psDiskParts(all bool) (parts [](github.com/shirou/gopsutil/v4/disk).PartitionStat, err error) +func psDiskParts(all bool) (parts []disk.PartitionStat, err error) ```
@@ -2874,7 +3909,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/disk.Partitions.
-##### 4.6.2.4. +##### 4.7.2.4. psDiskSerial
@@ -2908,7 +3943,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/disk.SerialNumber.
-##### 4.6.2.5. +##### 4.7.2.5. psDiskUsage
@@ -2922,7 +3957,7 @@ Function Signature
``` rouge -func psDiskUsage(path string) (usage *(github.com/shirou/gopsutil/v4/disk).UsageStat, err error) +func psDiskUsage(path string) (usage *disk.UsageStat, err error) ```
@@ -2944,11 +3979,11 @@ rel="noopener">github.com/shirou/gopsutil/v4/disk.Usage.
-#### 4.6.3. Host +#### 4.7.3. Host
-##### 4.6.3.1. +##### 4.7.3.1. psHostBoot
@@ -2982,7 +4017,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/host.BootTime.
-##### 4.6.3.2. psHostId +##### 4.7.3.2. psHostId
@@ -3015,7 +4050,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/host.HostID.
-##### 4.6.3.3. +##### 4.7.3.3. psHostInfo
@@ -3029,7 +4064,7 @@ Function Signature
``` rouge -func psHostInfo() (info *(github.com/shirou/gopsutil/v4/host).InfoStat, err error) +func psHostInfo() (info *host.InfoStat, err error) ```
@@ -3049,7 +4084,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/host.Info.
-##### 4.6.3.4. +##### 4.7.3.4. psHostKernArch
@@ -3083,7 +4118,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/host.KernelArch.
-##### 4.6.3.5. +##### 4.7.3.5. psHostKernVer
@@ -3117,7 +4152,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/host.KernelVersion
-##### 4.6.3.6. +##### 4.7.3.6. psHostPlatInfo
@@ -3161,7 +4196,7 @@ ordered `[3]string`.
-##### 4.6.3.7. +##### 4.7.3.7. psHostPlatUptime
@@ -3195,7 +4230,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/host.Uptime.
-##### 4.6.3.8. +##### 4.7.3.8. psHostUsers
@@ -3209,7 +4244,7 @@ Function Signature
``` rouge -func psHostUsers() (users [](github.com/shirou/gopsutil/v4/host).UserStat, err error) +func psHostUsers() (users []host.UserStat, err error) ```
@@ -3229,7 +4264,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/host.Users.
-##### 4.6.3.9. +##### 4.7.3.9. psHostPlatVirt
@@ -3275,11 +4310,11 @@ so the two `string` returns are consolidated into an ordered
-#### 4.6.4. Load +#### 4.7.4. Load
-##### 4.6.4.1. psLoadAvg +##### 4.7.4.1. psLoadAvg
@@ -3292,7 +4327,7 @@ Function Signature
``` rouge -func psLoadAvg() (avg *(github.com/shirou/gopsutil/v4/load).AvgStat, err error) +func psLoadAvg() (avg *load.AvgStat, err error) ```
@@ -3312,7 +4347,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/load.Avg.
-##### 4.6.4.2. +##### 4.7.4.2. psLoadMisc
@@ -3326,7 +4361,7 @@ Function Signature
``` rouge -func psLoadMisc() (misc *(github.com/shirou/gopsutil/v4/load).MiscStat, err error) +func psLoadMisc() (misc *load.MiscStat, err error) ```
@@ -3348,11 +4383,11 @@ rel="noopener">github.com/shirou/gopsutil/v4/load.Misc.
-#### 4.6.5. Memory +#### 4.7.5. Memory
-##### 4.6.5.1. +##### 4.7.5.1. psMemExVMem
@@ -3366,7 +4401,7 @@ Function Signature
``` rouge -func psMemExVMem() (exVMem *(github.com/shirou/gopsutil/v4/mem).ExVirtualMemory, err error) +func psMemExVMem() (exVMem *mem.ExVirtualMemory, err error) ```
@@ -3448,7 +4483,7 @@ on Windows.
-##### 4.6.5.2. +##### 4.7.5.2. psMemSwap
@@ -3462,7 +4497,7 @@ Function Signature
``` rouge -func psMemSwap() (swap *(github.com/shirou/gopsutil/v4/mem).SwapMemoryStat, err error) +func psMemSwap() (swap *mem.SwapMemoryStat, err error) ```
@@ -3482,7 +4517,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/mem.SwapMemory.
-##### 4.6.5.3. +##### 4.7.5.3. psMemSwapDevs
@@ -3496,7 +4531,7 @@ Function Signature
``` rouge -func psMemSwapDevs() (swapDevs []*(github.com/shirou/gopsutil/v4/mem).SwapDevice, err error) +func psMemSwapDevs() (swapDevs []*mem.SwapDevice, err error) ```
@@ -3516,7 +4551,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/mem.SwapDevices.
-##### 4.6.5.4. +##### 4.7.5.4. psMemVMem
@@ -3530,7 +4565,7 @@ Function Signature
``` rouge -func psMemVMem() (vmem *(github.com/shirou/gopsutil/v4/mem).VirtualMemoryStat, err error) +func psMemVMem() (vmem *mem.VirtualMemoryStat, err error) ```
@@ -3552,11 +4587,11 @@ rel="noopener">github.com/shirou/gopsutil/v4/mem.VirtualMemory.
-#### 4.6.6. Network +#### 4.7.6. Network
-##### 4.6.6.1. +##### 4.7.6.1. psNetConns
@@ -3570,7 +4605,7 @@ Function Signature
``` rouge -func psNetConns(kind string) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error) +func psNetConns(kind string) (conns []net.ConnectionStat, err error) ```
@@ -3590,7 +4625,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.Connections.
-##### 4.6.6.2. +##### 4.7.6.2. psNetConnsMax
@@ -3604,7 +4639,7 @@ Function Signature
``` rouge -func psNetConnsMax(kind string, maxConn int) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error) +func psNetConnsMax(kind string, maxConn int) (conns []net.ConnectionStat, err error) ```
@@ -3624,7 +4659,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.ConnectionsMax
-##### 4.6.6.3. +##### 4.7.6.3. psNetConnsPid
@@ -3638,7 +4673,7 @@ Function Signature
``` rouge -func psNetConnsPid(kind string, pid int32) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error) +func psNetConnsPid(kind string, pid int32) (conns []net.ConnectionStat, err error) ```
@@ -3658,7 +4693,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.ConnectionsPid
-##### 4.6.6.4. +##### 4.7.6.4. psNetConnsPidMax
@@ -3672,7 +4707,7 @@ Function Signature
``` rouge -func psNetConnsPidMax(kind string, pid int32, maxConn int) (conns [](github.com/shirou/gopsutil/v4/net).ConnectionStat, err error) +func psNetConnsPidMax(kind string, pid int32, maxConn int) (conns []net.ConnectionStat, err error) ```
@@ -3692,7 +4727,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.ConnectionsPidMax<
-##### 4.6.6.5. +##### 4.7.6.5. psNetCTStats
@@ -3706,7 +4741,7 @@ Function Signature
``` rouge -func psNetCTStats(percCpu bool) (ctStats [](github.com/shirou/gopsutil/v4/net).ConntrackStat, err error) +func psNetCTStats(percCpu bool) (ctStats []net.ConntrackStat, err error) ```
@@ -3726,7 +4761,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.ConntrackStats
-##### 4.6.6.6. +##### 4.7.6.6. psNetCTStatList
@@ -3740,7 +4775,7 @@ Function Signature
``` rouge -func psNetCTStatList() (ctStats *(github.com/shirou/gopsutil/v4/net).ConntrackStatList, err error) +func psNetCTStatList() (ctStats *net.ConntrackStatList, err error) ```
@@ -3760,7 +4795,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.ConntrackStatList<
-##### 4.6.6.7. +##### 4.7.6.7. psNetFilterCnts
@@ -3774,7 +4809,7 @@ Function Signature
``` rouge -func psNetFilterCnts() (filterCnts [](github.com/shirou/gopsutil/v4/net).FilterStat, err error) +func psNetFilterCnts() (filterCnts []net.FilterStat, err error) ```
@@ -3794,7 +4829,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.FilterCounters
-##### 4.6.6.8. +##### 4.7.6.8. psNetIoCnts
@@ -3808,7 +4843,7 @@ Function Signature
``` rouge -func psNetIoCnts(perNIC bool) (ioCnts [](github.com/shirou/gopsutil/v4/net).IOCountersStat, err error) +func psNetIoCnts(perNIC bool) (ioCnts []net.IOCountersStat, err error) ```
@@ -3828,7 +4863,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.IOCounters.
-##### 4.6.6.9. +##### 4.7.6.9. psNetIoCntsFile
@@ -3842,7 +4877,7 @@ Function Signature
``` rouge -func psNetIoCntsFile(perNIC bool, filepath string) (ioCnts [](github.com/shirou/gopsutil/v4/net).IOCountersStat, err error) +func psNetIoCntsFile(perNIC bool, filepath string) (ioCnts []net.IOCountersStat, err error) ```
@@ -3862,7 +4897,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.IOCountersByFile -##### 4.6.6.10. +##### 4.7.6.10. psNetIfaces
@@ -3876,7 +4911,7 @@ Function Signature
``` rouge -func psNetIfaces() (ioCnts [](github.com/shirou/gopsutil/v4/net).InterfaceStatList, err error) +func psNetIfaces() (ioCnts []net.InterfaceStatList, err error) ```
@@ -3896,7 +4931,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.Interfaces.
-##### 4.6.6.11. +##### 4.7.6.11. psNetPids
@@ -3930,7 +4965,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.Pids.
-##### 4.6.6.12. +##### 4.7.6.12. psNetProtoCnt
@@ -3944,7 +4979,7 @@ Function Signature
``` rouge -func psNetProtoCnt(protos []string) (protoCnts [](github.com/shirou/gopsutil/v4/net).ProtoCountersStat, err error) +func psNetProtoCnt(protos []string) (protoCnts []net.ProtoCountersStat, err error) ```
@@ -3985,7 +5020,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.ProtoCounters.
-##### 4.6.6.13. +##### 4.7.6.13. psNetRev
@@ -4042,11 +5077,11 @@ rel="noopener">github.com/shirou/gopsutil/v4/net.Reverse.
-#### 4.6.7. Processes +#### 4.7.7. Processes
-##### 4.6.7.1. +##### 4.7.7.1. psProcs
@@ -4060,7 +5095,7 @@ Function Signature
``` rouge -func psProcs(pid int32) (procs []*(github.com/shirou/gopsutil/v4/process).Process, err error) +func psProcs(pid int32) (procs []*process.Process, err error) ```
@@ -4080,7 +5115,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/proc.Processes.
-##### 4.6.7.2. +##### 4.7.7.2. psProcNew
@@ -4094,7 +5129,7 @@ Function Signature
``` rouge -func psProcNew(pid int32) (proc *(github.com/shirou/gopsutil/v4/process).Process, err error) +func psProcNew(pid int32) (proc *process.Process, err error) ```
@@ -4114,7 +5149,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/proc.NewProcess.
-##### 4.6.7.3. +##### 4.7.7.3. psProcPids
@@ -4148,7 +5183,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/proc.Pids.
-##### 4.6.7.4. +##### 4.7.7.4. psProcPidExists
@@ -4184,11 +5219,11 @@ rel="noopener">github.com/shirou/gopsutil/v4/proc.PidExists.
-#### 4.6.8. Sensors/Thermals +#### 4.7.8. Sensors/Thermals
-##### 4.6.8.1. +##### 4.7.8.1. psSensorExTemp
@@ -4202,7 +5237,7 @@ Function Signature
``` rouge -func psSensorExTemp() (temps [](github.com/shirou/gopsutil/v4/sensors).ExTemperature, err error) +func psSensorExTemp() (temps []sensors.ExTemperature, err error) ```
@@ -4244,7 +5279,7 @@ Warning
-##### 4.6.8.2. +##### 4.7.8.2. psSensorTemps
@@ -4258,7 +5293,7 @@ Function Signature
``` rouge -func psSensorTemps() (temps [](github.com/shirou/gopsutil/v4/sensors).TemperatureStat, err error) +func psSensorTemps() (temps []sensors.TemperatureStat, err error) ```
@@ -4280,7 +5315,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/sensors.SensorsTemperatures -#### 4.6.9. Windows Services +#### 4.7.9. Windows Services
@@ -4305,7 +5340,7 @@ Warning
-##### 4.6.9.1. +##### 4.7.9.1. psWinsvcList
@@ -4319,7 +5354,7 @@ Function Signature
``` rouge -func psWinsvcList() (svcs [](github.com/shirou/gopsutil/v4/winservices).Service, err error) +func psWinsvcList() (svcs []winservices.Service, err error) ```
@@ -4360,7 +5395,7 @@ rel="noopener">github.com/shirou/gopsutil/v4/winservices.ListServices -##### 4.6.9.2. +##### 4.7.9.2. psWinsvcNew
@@ -4374,7 +5409,7 @@ Function Signature
``` rouge -func psWinsvcNew(svcName string) (svc *(github.com/shirou/gopsutil/v4/winservices).Service, err error) +func psWinsvcNew(svcName string) (svc *winservices.Service, err error) ```
@@ -4419,11 +5454,11 @@ rel="noopener">github.com/shirou/gopsutil/v4/winservices.NewService
-### 4.7. Strings +### 4.8. Strings
-#### 4.7.1. +#### 4.8.1. extIndent
@@ -4476,7 +5511,7 @@ Tip

If <indentString> is set to \n and <levels> is always set to 1, this -function can even be used to doubelspace text!

+function can even be used to doublespace text!

@@ -4490,75 +5525,95 @@ It has quite a few arguments, however:
-
- -
- -``` rouge -{{ extIndent }} -``` - -
- -
- -
- -Where: - -
- -
- -- ``: The level of indentation for the text. If less than or - equal to `0`, `extIndent` just returns `` as-is and NO-OPs - otherwise. - -- ``: If true, skip indenting the first line. This is - particularly handy if you like to visually align your function calls - in your templates. - -- ``: If true, do not add an indent to **empty** lines (where - an "empty line" means "only has a linebreak"). - -- ``: If true, do not add an indent to lines that - **only** consist of whitespace (spaces, tabs, etc.) and a linebreak. - -- ``: The string to use as the "indent character". This - can be any string, such as `" "`, `"\t"`, `"."`, `"|"`, `"=="` etc. - -- ``: The text to be indented. Because it is the last argument, - `extIndent` works with pipelined text as well. - -
- -
- -
- -
- -### 4.8. Time/Dates/Timestamps - -
- - +
--+++ + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4566,504 +5621,6 @@ Sprig functions where possible and sensible.

-
- -#### 4.8.1. tmDate - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmDate(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) (date time.Time) -``` - -
- -
- -
- -`tmDate` directly calls -time.Date. - -
- -
- -
- -#### 4.8.2. -tmFloatMicro - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmFloatMicro(t time.Time) (f64 float64) -``` - -
- -
- -
- -`tmFloatMicro` directly calls -(r00t2.io/goutils/timex).F64Microseconds. - -
- -
- -
- -#### 4.8.3. -tmFloatMilli - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmFloatMilli(t time.Time) (f64 float64) -``` - -
- -
- -
- -`tmFloatMilli` directly calls -(r00t2.io/goutils/timex).F64Milliseconds. - -
- -
- -
- -#### 4.8.4. -tmFloatNano - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmFloatNano(t time.Time) (f64 float64) -``` - -
- -
- -
- -`tmFloatNano` directly calls -(r00t2.io/goutils/timex).F64Nanoseconds. - -
- -
- -
- -#### 4.8.5. tmFloat - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmFloat(t time.Time) (f64 float64) -``` - -
- -
- -
- -`tmFloat` directly calls -(r00t2.io/goutils/timex).F64Seconds. - -
- -
- -
- -#### 4.8.6. tmFmt - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmFmt(fstr string, t time.Time) (out string) -``` - -
- -
- -
- -`tmFormat` provides a more pipeline-friendly alternative to calling e.g. - -
- -
- -
- -``` rouge -{{- $t := tmNow -}} -{{ $t.Format "" }} -``` - -
- -
- -
- -
- -#### 4.8.7. tmNow - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmNow() (now time.Time) -``` - -
- -
- -
- -`tmNow` directly calls -time.Now. - -
- -
- -
- -#### 4.8.8. -tmParseDur8n - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmParseDur8n(s string) (d time.Duration, err error) -``` - -
- -
- -
- -`tmParseDur8n` directly calls -time.ParseDuration. - -
- -
- -
- -#### 4.8.9. tmParseMonth - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmParseMonth(v any) (mon time.Month, err error) -``` - -
- -
- -
- -`tmParseMonth` attempts to first try [`tmParseMonthInt`](#fn_tm_pmnthi) -and then tries [`tmParseMonthStr`](#fn_tm_pmnths) if `v` is not -"numeric". - -
- -
- -
- -#### 4.8.10. -tmParseMonthInt - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmParseMonthInt(n any) (mon time.Month, err error) -``` - -
- -
- -
- -`tmParseMonthInt` parses a number representation of month `n` to a -time.Month. `n` may be any numeric type -or a string representation of a number (or a custom type derived from -those). - -
- -
- -A negative integer (or float, etc.) will be converted to a positive one -(e.g. `-6` → `6` → `time.June`). - -
- -
- -Floats are rounded to the nearest integer. - -
- -
- -The integer should map directly to the -time.Month constants in the `time` -module: - -
- -
- -- `1`: `time.January` - -- `2`: `time.February` - -- `3`: `time.March` - -- `4`: `time.April` - -- `5`: `time.May` - -- `6`: `time.June` - -- `7`: `time.July` - -- `8`: `time.August` - -- `9`: `time.September` - -- `10`: `time.October` - -- `11`: `time.November` - -- `12`: `time.December` - -
- -
- -If `n` resolves to `0`, `mon` will be the current month (as determined -by time.Now). - -
- -
- -If `n` resolves to \> `12`, `err` will be `sprigx.ErrBadMonth` (though -be sure to use errors.Is; it will be wrapped by -[`(text/template).ExecError`](https://pkg.go.dev/text/template#ExecError)/[`(html/template).ExecError`](https://pkg.go.dev/html/template#ExecError). - -
- -
- -
- -#### 4.8.11. -tmParseMonthStr - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmParseMonthStr(s string) (mon time.Month, err error) -``` - -
- -
- -
- -`tmParseMonthStr` parses a string representation `s` of a month to a -time.Month. - -
- -
- -It normalizes `s` to lowercase and only uses the first 3 characters (the -minimum length needed to determine month name uniqueness - "June" vs. -"July", "March" vs. "May"). - -
- -
- -An empty (or whitespace-only) string will use the current month (as -determined by time.Now).\` - -
- -
- -
- -#### 4.8.12. tmParseTime - -
- -
- -Function Signature - -
- -
- -``` rouge -func tmParseTime(layout, value string) (t time.Time, err error) -``` - -
- -
- -
- -`tmParseTime` directly calls -time.Parse. - -
- -
- -Be sure that `layout` is a properly parseable -layout format. - -
- -
-
@@ -5272,6 +5829,537 @@ functions as well:
+
ArgumentTypeDescription
-Note -
-

Some of these functions duplicate Sprig functionality, but are -included here for predictable API.

-
+

levels

int

-

Care has been taken to name these functions differently from the -Sprig functions where possible and sensible.

+

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

bool

+
+

If true, skip indenting the first line. This is particularly handy if +you like to visually align your function calls in your templates.

+
+

skipEmpty

bool

+
+

If true, do not add an indent to empty lines (where +an "empty line" means "only has a linebreak").

+
+

skipWhitespace

bool

+
+

If true, do not add an indent to lines that only +consist of whitespace (spaces, tabs, etc.) and a linebreak.

+
+

indentString

string

+
+

The string to use as the "indent character". This can be any string, +such as "<SP>" (0x20), +"\t", ".", "|", "==" +etc.

+
+

input

string

+
+

The text to be indented. Because it is the last argument, +extIndent works with pipelined text as well.

+
++++ + + + + + + +
+Note +
+

Some of these functions duplicate Sprig functionality, but are +included here for predictable API.

+
+
+

Care has been taken to name these functions differently from the +Sprig functions where possible and sensible.

+
+ +
+ +
+ +#### 4.10.1. tmDate + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmDate(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) (date time.Time) +``` + +
+ +
+ +
+ +`tmDate` directly calls +time.Date. + +
+ +
+ +
+ +#### 4.10.2. +tmFloatMicro + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmFloatMicro(t time.Time) (f64 float64) +``` + +
+ +
+ +
+ +`tmFloatMicro` directly calls +(r00t2.io/goutils/timex).F64Microseconds. + +
+ +
+ +
+ +#### 4.10.3. +tmFloatMilli + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmFloatMilli(t time.Time) (f64 float64) +``` + +
+ +
+ +
+ +`tmFloatMilli` directly calls +(r00t2.io/goutils/timex).F64Milliseconds. + +
+ +
+ +
+ +#### 4.10.4. +tmFloatNano + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmFloatNano(t time.Time) (f64 float64) +``` + +
+ +
+ +
+ +`tmFloatNano` directly calls +(r00t2.io/goutils/timex).F64Nanoseconds. + +
+ +
+ +
+ +#### 4.10.5. tmFloat + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmFloat(t time.Time) (f64 float64) +``` + +
+ +
+ +
+ +`tmFloat` directly calls +(r00t2.io/goutils/timex).F64Seconds. + +
+ +
+ +
+ +#### 4.10.6. tmFmt + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmFmt(fstr string, t time.Time) (out string) +``` + +
+ +
+ +
+ +`tmFormat` provides a more pipeline-friendly alternative to calling e.g. + +
+ +
+ +
+ +``` rouge +{{- $t := tmNow -}} +{{ $t.Format "" }} +``` + +
+ +
+ +
+ +
+ +#### 4.10.7. tmNow + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmNow() (now time.Time) +``` + +
+ +
+ +
+ +`tmNow` directly calls +time.Now. + +
+ +
+ +
+ +#### 4.10.8. +tmParseDur8n + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmParseDur8n(s string) (d time.Duration, err error) +``` + +
+ +
+ +
+ +`tmParseDur8n` directly calls +time.ParseDuration. + +
+ +
+ +
+ +#### 4.10.9. +tmParseMonth + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmParseMonth(v any) (mon time.Month, err error) +``` + +
+ +
+ +
+ +`tmParseMonth` attempts to first try [`tmParseMonthInt`](#fn_tm_pmnthi) +and then tries [`tmParseMonthStr`](#fn_tm_pmnths) if `v` is not +"numeric". + +
+ +
+ +
+ +#### 4.10.10. +tmParseMonthInt + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmParseMonthInt(n any) (mon time.Month, err error) +``` + +
+ +
+ +
+ +`tmParseMonthInt` parses a number representation of month `n` to a +time.Month. `n` may be any numeric type +or a string representation of a number (or a custom type derived from +those). + +
+ +
+ +A negative integer (or float, etc.) will be converted to a positive one +(e.g. `-6` → `6` → `time.June`). + +
+ +
+ +Floats are rounded to the nearest integer. + +
+ +
+ +The integer should map directly to the +time.Month constants in the `time` +module: + +
+ +
+ +- `1`: `time.January` + +- `2`: `time.February` + +- `3`: `time.March` + +- `4`: `time.April` + +- `5`: `time.May` + +- `6`: `time.June` + +- `7`: `time.July` + +- `8`: `time.August` + +- `9`: `time.September` + +- `10`: `time.October` + +- `11`: `time.November` + +- `12`: `time.December` + +
+ +
+ +If `n` resolves to `0`, `mon` will be the current month (as determined +by time.Now). + +
+ +
+ +If `n` resolves to \> `12`, `err` will be `sprigx.ErrBadMonth` (though +be sure to use errors.Is; it will be wrapped by +[`(text/template).ExecError`](https://pkg.go.dev/text/template#ExecError)/[`(html/template).ExecError`](https://pkg.go.dev/html/template#ExecError). + +
+ +
+ +
+ +#### 4.10.11. +tmParseMonthStr + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmParseMonthStr(s string) (mon time.Month, err error) +``` + +
+ +
+ +
+ +`tmParseMonthStr` parses a string representation `s` of a month to a +time.Month. + +
+ +
+ +It normalizes `s` to lowercase and only uses the first 3 characters (the +minimum length needed to determine month name uniqueness - "June" vs. +"July", "March" vs. "May"). + +
+ +
+ +An empty (or whitespace-only) string will use the current month (as +determined by time.Now). + +
+ +
+ +
+ +#### 4.10.12. tmParseTime + +
+ +
+ +Function Signature + +
+ +
+ +``` rouge +func tmParseTime(layout, value string) (t time.Time, err error) +``` + +
+ +
+ +
+ +`tmParseTime` directly calls +time.Parse. + +
+ +
+ +Be sure that `layout` is a properly parseable +layout format. + +
+ +
+ +
+
@@ -5296,7 +6384,7 @@ functions as well: diff --git a/tplx/sprigx/TODO b/tplx/sprigx/TODO new file mode 100644 index 0000000..2ab1ee1 --- /dev/null +++ b/tplx/sprigx/TODO @@ -0,0 +1,14 @@ +- osReadFileBytes +- osReadFileStr +- osReadDir + +- `dns*` funcs (net) +- `url*` funcs (net/url) +- `uuid*` funcs (github.com/google/uuid and r00t2.io/goutils/uuidx) + +- `http*` funcs: +-- `httpReq`: returns a net/http.Request +-- `http`: performs (? seems redundant if exposing httpReq) +-- also have `resty*` funcs? + +- i should probably explicitly provide a "safe" set vs. "full" set. can just mod the map func getters to accept a "safeOnly" bool param. diff --git a/tplx/sprigx/consts.go b/tplx/sprigx/consts.go index 5eb54ec..3809893 100644 --- a/tplx/sprigx/consts.go +++ b/tplx/sprigx/consts.go @@ -1,6 +1,8 @@ package sprigx import ( + `net` + `net/netip` `os` `os/user` `path` @@ -17,6 +19,7 @@ import ( psnet `github.com/shirou/gopsutil/v4/net` `github.com/shirou/gopsutil/v4/process` `github.com/shirou/gopsutil/v4/sensors` + `go4.org/netipx` `r00t2.io/goutils/timex` `r00t2.io/sysutils` ) @@ -30,6 +33,40 @@ var ( "Meta"/Template-Helpers */ "metaIsNil": metaIsNil, + /* + Networking (net) + */ + "netCidrMask": net.CIDRMask, + "netExtractAddr": netExtractAddr, + "netExtractHost": netExtractHost, + "netExtractIpnet": netExtractIpnet, + "netExtractPort": netExtractPort, + "netIfaces": net.Interfaces, + "netIp4Mask": netIp4Mask, + "netJoinHostPort": net.JoinHostPort, + "netParseIP": net.ParseIP, + /* + Networking (net/netip) + */ + "netipAddrPort": netip.AddrPortFrom, + "netipParseAddr": netip.ParseAddr, + "netipParseAddrPort": netip.ParseAddrPort, + "netipParsePrefix": netip.ParsePrefix, + "netipPrefix": netip.PrefixFrom, + /* + Networking (go4.org/netipx) + */ + "netipxAddrIpNet": netipx.AddrIPNet, + "netipxCmpPfx": netipx.ComparePrefix, + "netipxFromStdAddr": netipxFromStdAddr, + "netipxFromIp": netipxFromIp, + "netipxFromIpNet": netipxFromIpNet, + "netipxParseRange": netipx.ParseIPRange, + "netipxPfxAddr": netipx.ParsePrefixOrAddr, + "netipxPfxIpNet": netipx.PrefixIPNet, + "netipxPfxLast": netipx.PrefixLastIP, + "netipxPfxRange": netipx.RangeOfPrefix, + "netipxRange": netipx.IPRangeFrom, /* Numbers/Math */ diff --git a/tplx/sprigx/docinfo.html b/tplx/sprigx/docinfo.html new file mode 100644 index 0000000..2234fc0 --- /dev/null +++ b/tplx/sprigx/docinfo.html @@ -0,0 +1,77 @@ + + + + + + + + + + + diff --git a/tplx/sprigx/errs.go b/tplx/sprigx/errs.go index d19319e..4bfd19d 100644 --- a/tplx/sprigx/errs.go +++ b/tplx/sprigx/errs.go @@ -5,7 +5,12 @@ import ( ) var ( - ErrBadMonth error = errors.New("could not determine/parse month") - ErrBadType error = errors.New("an invalid/unknown type was passed") - ErrNilVal error = errors.New("a nil value was passed") + ErrBadAddr error = errors.New("invalid/bad address") + ErrBadAddrPort error = errors.New("invalid/bad address/port") + ErrBadMonth error = errors.New("could not determine/parse month") + ErrBadNet error = errors.New("invalid/bad network") + ErrOverflow error = errors.New("integer/buffer overflow") + ErrBadType error = errors.New("an invalid/unknown type was passed") + ErrNilVal error = errors.New("a nil value was passed") + ErrUnderflow error = errors.New("integer/buffer underflow") ) diff --git a/tplx/sprigx/funcs_tpl_net.go b/tplx/sprigx/funcs_tpl_net.go new file mode 100644 index 0000000..ac534a7 --- /dev/null +++ b/tplx/sprigx/funcs_tpl_net.go @@ -0,0 +1,82 @@ +package sprigx + +import ( + `math` + `net` + `strconv` +) + +// netExtractAddr calls net.ParseCIDR and returns the net.IP from it. +func netExtractAddr(s string) (addr net.IP, err error) { + + if addr, _, err = net.ParseCIDR(s); err != nil { + return + } + + return +} + +// netExtractHost extracts the host component from hostPort. +func netExtractHost(hostPort string) (host string, err error) { + + if host, _, err = net.SplitHostPort(hostPort); err != nil { + return + } + + return +} + +// netExtractIpnet calls net.ParseCIDR and returns the net.IPNet from it. +func netExtractIpnet(s string) (ipnet *net.IPNet, err error) { + + if _, ipnet, err = net.ParseCIDR(s); err != nil { + return + } + + return +} + +// netExtractPort extracts the port component from hostPort. +func netExtractPort(hostPort string) (port uint16, err error) { + + var portStr string + var u64 uint64 + + if _, portStr, err = net.SplitHostPort(hostPort); err != nil { + return + } + + if u64, err = strconv.ParseUint(portStr, 10, 16); err != nil { + return + } + port = uint16(u64) + + return +} + +// netIp4Mask is a more flexible wrapper around net.IPv4Mask. +func netIp4Mask(a, b, c, d any) (mask net.IPMask, err error) { + + var idx int + var elem any + var elemInt int + var mBytes [4]byte + var orig [4]any = [4]any{a, b, c, d} + + for idx, elem = range orig { + if elemInt, _, err = toPosInt(elem); err != nil { + return + } + if elemInt > math.MaxUint8 { + err = ErrOverflow + return + } + mBytes[idx] = byte(uint8(elemInt)) + } + + mask = net.IPv4Mask( + mBytes[0], mBytes[1], mBytes[2], mBytes[3], + ) + + return +} diff --git a/tplx/sprigx/funcs_tpl_netipx.go b/tplx/sprigx/funcs_tpl_netipx.go new file mode 100644 index 0000000..fc8d050 --- /dev/null +++ b/tplx/sprigx/funcs_tpl_netipx.go @@ -0,0 +1,47 @@ +package sprigx + +import ( + `net` + `net/netip` + + `go4.org/netipx` +) + +// netipxFromStdAddr wraps go4.org/netipx.FromStdAddr to comply with Go template requirements. +func netipxFromStdAddr(ip net.IP, port int, zone string) (addrPort netip.AddrPort, err error) { + + var ok bool + + if addrPort, ok = netipx.FromStdAddr(ip, port, zone); !ok { + err = ErrBadAddrPort + return + } + + return +} + +// netipxFromIp wraps go4.org/netipx.FromStdIP to comply with Go template requirements. +func netipxFromIp(ip net.IP) (addr netip.Addr, err error) { + + var ok bool + + if addr, ok = netipx.FromStdIP(ip); !ok { + err = ErrBadAddr + return + } + + return +} + +// netipxFromIpNet wraps go4.org/netipx.FromStdIPNet to comply with Go template requirements. +func netipxFromIpNet(ipnet *net.IPNet) (pfx netip.Prefix, err error) { + + var ok bool + + if pfx, ok = netipx.FromStdIPNet(ipnet); !ok { + err = ErrBadNet + return + } + + return +} diff --git a/uuidx/consts.go b/uuidx/consts.go new file mode 100644 index 0000000..977fc56 --- /dev/null +++ b/uuidx/consts.go @@ -0,0 +1,11 @@ +package uuidx + +const ( + RfcNone RfcGen = iota + Rfc4122 + Rfc9562 +) + +const ( + MsGuidThreshold int = 4 +) diff --git a/uuidx/doc.go b/uuidx/doc.go new file mode 100644 index 0000000..98d5f11 --- /dev/null +++ b/uuidx/doc.go @@ -0,0 +1,73 @@ +/* +Package uuidx intends to supplement [github.com/google/uuid]. + +# Microsoft GUID Shenanigans + +The following functions are provided to deal with [Microsoft's incompetence]: + + * [DetectMsGuid] (a confidence'd determination if a UUID is a Microsoft GUID or not) + * [IsFlippedEndian] for flipped-endian [uuid.UUID] comparison (e.g. a is the Microsoft-flipped-endian version of b) + * [IsMsGuid] (wraps [DetectMsGuid] and returns true if confidence is reasonably strong that it's a Microsoft GUID) + * [IsRfc] (the inverse of IsMsGuid, but also checks for strict RFC compliance and returns which RFC) + * [MsGuidToUuid] (explicitly convert/ensure a GUID/UUID is likely a UUID) + * [ToggleUuidMsGuid] (blindly flip the endianness of selected byte ranges for MS GUID <-> UUID conversion) + * [UuidToMsGuid] (explicitly convert/ensure a GUID/UUID is likely an MS GUID) + +Microsoft, in their typical insanity, uses a proprietary UUID format (usually referred to as the "Microsoft GUID Format" +or "Mixed-Endian Format"). + +Normally for, for example a UUIDv4, it's structured as thus per RFC 9562 [§ 5.4] (which obsoletes RFC 4122 [§ 4.4]): + + A B C D E + HEX(BE(uint32))-HEX(BE(uint16))-HEX(BE(uint16))-HEX(BE(), BE(<6 bytes>)) + +(where is big-endian packing). + +However, thanks to Microsoft we can't have nice things. They decided to completely ignore the standard, and +instead keep D/E as big-endian *but use little-endian* for A through C inclusive: + + A B C D E + HEX(LE(uint32))-HEX(LE(uint16))-HEX(LE(uint16))-HEX(BE(), BE(<6 bytes>)) + +"Surely that had SOME reason to do that," you may say to yourself, "they wouldn't make some arbitrary formatting +change from a standard just because." + +You would be wrong. To my knowledge, they have never provided any technological justfification to this insanity, +and now it's infected its way into a slew of other technologies they've had their grubby little hands involved in +(e.g. UEFI). And it's of course too late to change. + +So anyways here's a library to make dealing with Microsoft's hubris a little easier. + +# Validation/Verification + +Aside from trying to address Microsoft silliness, there are some additional functions: + + * [Equal] for [uuid.UUID] comparison + * [IsMaxUUID] (if a given [uuid.UUID] is an RFC 9562 [§ 5.10] UUID) + * [IsNilUUID] (if a given [uuid.UUID] is an RFC 9562 [§ 5.9] UUID) + * [IsValid] (If an RFC can be considered safely conformant to RFC spec) + +# Future Incorporation/Deprecation/Obsolescence + +Worth keeping an eye on are: + + * https://github.com/google/uuid/pull/192 + * https://github.com/golang/go/issues/62026 + * https://github.com/golang/go/issues/76319 + (generally it's a bad idea for an API addition overall, but some good ideas were raised) + +Some of these additions may deprecate/obsolete components of this package. +I'll try to keep them around but mark as deprecated as they are (if they are), +but I make no concrete promises - I hate making new major releases in Go's +[silly module architecture] even more than I do keeping old deprecated code around. +So caveat emptor. + +[Microsoft's incompetence]: https://learn.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid +[§ 5.4]: https://datatracker.ietf.org/doc/html/rfc9562#section-5.4 +[§ 4.4]: https://datatracker.ietf.org/doc/html/rfc4122#section-4.4 +[§ 5.9]: https://datatracker.ietf.org/doc/html/rfc9562#section-5.9 +[§ 5.10]: https://datatracker.ietf.org/doc/html/rfc9562#section-5.10 +[github:google/uuid#192]: https://github.com/google/uuid/pull/192 +[silly module architecture]: https://go.dev/doc/modules/major-version +*/ +package uuidx diff --git a/uuidx/funcs.go b/uuidx/funcs.go new file mode 100644 index 0000000..659f095 --- /dev/null +++ b/uuidx/funcs.go @@ -0,0 +1,461 @@ +package uuidx + +import ( + "github.com/google/uuid" +) + +/* +DetectMsGuid tries to guess if a given [uuid.UUID] is actually a Microsoft GUID or not. + +Note that there are technically *two* types of Microsoft GUIDs: + + * One is predictable, and defined in RFC 9562 [§ 4.2] as a known variant. + Detecting this is very easy and (assuming an RFC-compliant UUID is originally passed) is detectable with 100% confidence. + It's also legacy, and Microsoft no longer uses this format. Because they are insane and enjoy the suffering of others. + * The other, MODERN Microsoft GUID currently in use is the endianness-flipped version (see [ToggleUuidMsGuid]). + This is impossible to 100% determine, but analysis can get *pretty* close. + +cs is a confidence scoring. As more logic is added, it *is* mathematically possible +(though unlikely) that cs == 0, so the caller is then responsible for making further +guesswork based on contextual analysis ("Did I get this UUID/GUID from an Active Directory attribute?" +"Is it a SID constant?" etc.). + +A score > 0 indicates a confidence leaning towards the provided UUID/GUID being a Microsoft GUID. +A score < 0 indicates a confidence leaning towards the provided UUID/GUID *not* being a Microsoft GUID. +Note that a score of < 0 does not necessarily indicate it is a *proper, standard RFC-compliant UUID*, +simply that it is likely NOT a Microsoft GUID. [IsRfc] will be of further help in these cases. + +csFlip indicates a score for the [ToggleUuidMsGuid]-flipped version of u. +It follows the same rules for thresholds and such as cs, but may be awarded different confidence levels +internally due to different chances of false positives. +If both cs and csFlip are > 0 but csFlip > cs, it is better to assume that u is *not* in the flipped-endian format +but *is* a Microsoft GUID (in other words, it is likely that u has *already been flipped* to proper/consistent endianness +instead of being a mixed-endian GUID). + +In some cases where flipped-endianness does not matter (e.g. [IsNilUUID], [IsMaxUUID]), +cs and csFlip will be equal. + +*Randomly-generated* GUIDs on Windows Server 2000-family and up are almost always UUIDv4. +Pre-Windows Server 2000 family *OR* any *statically-defined* GUIDs (schemaIDGUID, rightsGUID, CLSID constants, etc.) +are all over the place - TYPICALLY UUIDv1, but it's nothing predictable enough to be useful in definitive classification. +COM interfaces are all OVER the place in UUID version, but usually *not* UUIDv4. + +A target/expected UUID version can be provided via tgtVer. To disable version analysis, use 0 (or 0x00, etc.). +It is *highly* recommended to provide a tgtVer if it is known; it can significantly boost confidence in the correct direction. +A warning, though - if a *wrong* tgtVer IS specified, it can negatively affect confidence accuracy. +Thus if you aren't ABSOLUTELY certain of the target UUID version, it's better to use 0/0x00 to disable the check. +Providing a target version is key to breaking some ties (e.g. both cs and csFlip are equal). +For example, the given RFC-compliant UUIDv4: + + 8d8e35ae-58d2-4d28-b09d-ffffffffffff + +when flipped evaluates to an RFC-compliant UUIDv2: + + ae358e8d-d258-284d-b09d-ffffffffffff + +and in this case, cs and csFlip will both end up as 0. +Providing a tgtVer of 4 shifts this to a proper "tie-breaker" of cs == -3 and csFlip == 0. +Similarly, the endian-flipped UUIDv4 evaluates as a UUIDv2: + + 9856ea36-c2ca-2347-af0c-3b42f76c9eca + +from the original unflipped UUIDv4: + + 36ea5698-cac2-4723-af0c-3b42f76c9eca + +which results in a cs == 1 and csFlip == 0 - not very high confidence (but at least a correct and non-zero lean). +Providing a tgtVer == 4 changes this to cs == 7 and csFlip == 0, which is *much* more decisive. + +UUIDs/GUIDs found to be strictly RFC-conforming (via [IsRfc], which returns false for Microsoft GUIDs) +are *heavily* weighted negatively. + +Confidence levels can be generally considered as the following: + + cs >= 7: Likely Microsoft GUID (mixed-endian) + cs >= 4: Likely Microsoft GUID + 0 < cs < 4: Leans Microsoft GUID, but untrusted + cs == 0: Entirely ambiguous/indeterminate + -4 < cs < 0: Leans UUID/non-Microsoft GUID but untrusted + cs <= -5: Likely UUID/not Microsoft GUID + csFlip >=cs && csFlip >= 4: Likely a pre-flipped (ToggleUuidMsGuid'd) Microsoft GUID + +[§ 4.2]: https://datatracker.ietf.org/doc/html/rfc9562#section-4.2 +*/ + +func DetectMsGuid(u uuid.UUID, tgtVer uuid.Version) (cs, csFlip int) { + + var isRfc bool + var flippedRfc bool + var flipped uuid.UUID = ToggleUuidMsGuid(u) + + // These are the exact same when flipped, and are statically defined. + if IsNilUUID(u) || IsMaxUUID(u) { + cs = -12 + csFlip = -12 + return + } + + // Most/all(?) Microsoft GUIDs are not NCS. + if IsNcs(u) { + cs -= 2 + } + if IsNcs(flipped) { + // The flipped has a higher likelihood of false-pos, so we don't score it as confidently. + csFlip -= 1 + } + + if u.Version() == 0 { + if u.Variant() == uuid.Microsoft { + cs += 10 + } else { + cs -= 2 + } + } + if flipped.Version() == 0 { + if flipped.Variant() == uuid.Microsoft { + csFlip += 4 + } else { + csFlip -= 1 + } + } + + // Valid RFC version and variant. IsRfc returns false for the Microsoft Variant and version == 0. + // Modern MS uses an RFC 4122 variant indicator but flips the endianness. + isRfc, _ = IsRfc(u) + flippedRfc, _ = IsRfc(flipped) + if u.Variant() == uuid.RFC4122 { // This might be the strongest indicator. + if isRfc && !flippedRfc { + // This is *very* strong of being an MS GUID. + cs -= 8 + csFlip += 4 + } else if !isRfc && flippedRfc { + // It probably is an MS GUID but was already flipped. + csFlip += 6 + } else if isRfc && flippedRfc { + /* + If both are RFC-compat, it's a weird case where + it actually IS RFC compliant and by chance the flipped is *also* RFC compat. + An example of this is: + 8d8e35ae-58d2-4d28-b09d-ffffffffffff + Which has the flipped version of: + ae358e8d-d258-284d-b09d-ffffffffffff + The original is a v4, the flipped evaluates as a v2! + + Providing a target version breaks this away to a definitive score. + */ + } + } + + // *HEAVILY* weigh a provided version. + if tgtVer != 0 { + // NCS does some weird things to the versioning field. We return early on it though. + // MS GUIDs have a pretty small chance of matching, + // but their flipped counterpart SHOULD match versions. + if flipped.Version() == tgtVer { + cs += 7 + } else { + cs -= 3 + } + } else { + // Give a *very small* boost to flippedRfc and flipped.Version() == 4, since it's so common. + // Don't make this too high though since the version is explicitly specified as unknown. + if flippedRfc && flipped.Version() == 4 { + cs += 1 + } + } + + return +} + +/* +Equal returns `true` if [uuid.UUID] the two provided [uuid.UUID] are the same. + +Currently it just wraps: + + eq = a == b + +but is provided as a safety guarantee if the underlying structures/types should change. +*/ +func Equal(a, b uuid.UUID) (eq bool) { + + eq = a == b + + return +} + +/* +IsFlippedEndian can be used to check if [uuid.UUID] is a direct endian-flipped ([ToggleUuidMsGuid]) +of b (or vice versa, obviously). + +It simply wraps: + + isFlipped = Equal(a, ToggleUuidMsGuid(b)) + +but can be useful for shorthand/readability. +*/ +func IsFlippedEndian(a, b uuid.UUID) (isFlipped bool) { + + isFlipped = Equal(a, ToggleUuidMsGuid(b)) + + return +} + +/* +IsMaxUUID returns `true` if the specified UUID is explicitly an RFC-defined +"Max UUID". (You may also see it specified in some places as the "Omni UUID".) + +For details, see RFC 9562 [§ 5.10]. + +[§ 5.10]: https://datatracker.ietf.org/doc/html/rfc9562#section-5.10 +*/ +func IsMaxUUID(u uuid.UUID) (isMax bool) { + + isMax = u == uuid.Max + + return +} + +/* +IsMsGuid wraps + + if cmp, _ = DetectMsGuid(msGUID, tgtVer); cmp < -3 { + isMs = true + } + +Note that [uuid.Microsoft] is an actual RFC-defined variant, but *Microsoft no longer uses it* +and in MODERN implementations do the endianness flip [ToggleUuidMsGuid] of (USUALLY) a UUIDv4. + +See [DetectMsGuid] for a more in-depth result that will let you use the confidence level directly, +and for details on the weird things that can go wrong with this guesswork. + +Note that this won't be 100% reliable due to math things, but it should be reliable enough most of the time. + +See also [MsGuidToUuid] and [UuidToMsGuid]. +*/ +func IsMsGuid(msGUID uuid.UUID, tgtVer uuid.Version) (isMs bool) { + + var cmp int + + if cmp, _ = DetectMsGuid(msGUID, tgtVer); cmp < -3 { + isMs = true + } + + return +} + +/* +IsNcs is shorthand for: + + isNcs = u.Variant() == uuid.Reserved + +See also the notes in [IsRfc]. +*/ +func IsNcs(u uuid.UUID) (isNcs bool) { + + // https://archive.org/details/networkcomputing0000zahn/page/10/mode/1up + + isNcs = u.Variant() == uuid.Reserved + + return +} + +/* +IsNilUUID returns `true` if the specified UUID is explicitly an RFC-defined +"Nil UUID". + +For details, see RFC 9562 [§ 5.9]. + +[§ 5.9]: https://datatracker.ietf.org/doc/html/rfc9562#section-5.9 +*/ +func IsNilUUID(u uuid.UUID) (isNil bool) { + + isNil = u == uuid.Nil + + return +} + +/* +IsRfc returns `true` if the specified UUID is a proper standard RFC UUID. + +Because Microsoft is insane, rfc will be false even if it's a (legacy) Microsoft form +of an RFC UUID. Use [IsMsGuid] for that. + +In the special case of u being a valid NCS UUID, rfc will be false but gen will be [Rfc4122]. +This is because RFC 9652 deprecates the NCS UUID. See [IsNcs]. +(You are highly unlikely to encounter an NCS UUID "in the wild" unless you are receiving +a UUID from someone who severely misunderstands that UUIDs are structured/versioned/typed +and thinks they're just random byes in hex with hyphens in certain places.) +(They aren't that, if you're one of those someones.) + +Nil UUID ([IsNilUUID]) and Max UUID ([IsMaxUUID]) return true with RFCs 4122 and RFC 9562 respectively. +*/ +func IsRfc(u uuid.UUID) (rfc bool, gen RfcGen) { + + if IsNilUUID(u) { + rfc = true + gen = Rfc4122 + return + } + if IsMaxUUID(u) { + rfc = true + gen = Rfc9562 + return + } + if IsNcs(u) { + gen = Rfc4122 + return + } + + // TODO: Are there any sub-version checks that can be applied? + switch u.Variant() { + case uuid.Invalid, uuid.Microsoft, uuid.Future: + return + case uuid.RFC4122: + if !(0x01 <= u.Version() && u.Version() <= 0x08) { + return + } + rfc = true + gen = Rfc4122 + // 4122 only covers UUIDv1 through UUIDv5. + if 0x06 <= u.Version() && u.Version() <= 0x08 { + gen = Rfc9562 + } + default: // Safety net in case upstream adds a uuid.RFC9562 variant or something. + if !(0x01 <= u.Version() && u.Version() <= 0x08) { + return + } + if u.Variant() < uuid.Future { + return + } + rfc = true + gen = RfcNone + // 4122 only covers UUIDv1 through UUIDv5. + if 0x06 <= u.Version() && u.Version() <= 0x08 { + gen = Rfc9562 + } + } + + return +} + +/* +IsValid indicates if the given [uuid.UUID] strictly conforms to RFC. + +A Nil UUID (as in RFC 9562 [§ 5.9], not a `nil` *uuid.UUID) will return `true` +as it IS technically defined per RFC despite not conforming to a version. +Use [IsNilUUID] to further determine that. + +Likewise, a Max UUID (RFC 9562 [§ 5.10]) will return `true` as it is also +defined per RFC despite not conforming to a version. +Use [IsMaxUUID] to further determine that. + +Microsoft GUIDs will always return false since they defy RFC. +Use [IsMsGuid] to check for that condition. + +[§ 5.9]: https://datatracker.ietf.org/doc/html/rfc9562#section-5.9 +[§ 5.10]: https://datatracker.ietf.org/doc/html/rfc9562#section-5.10 +*/ +func IsValid(u uuid.UUID) (valid bool) { + + if IsNilUUID(u) { + valid = true + return + } + if IsMaxUUID(u) { + valid = true + return + } + + switch u.Variant() { + case uuid.Invalid, uuid.Reserved, uuid.Microsoft, uuid.Future: + return + case uuid.RFC4122: + valid = true + // TODO: If they add an RFC9562 or something, need a case here. + default: + return + } + + // If we got here, it *should* be RFC. + if valid, _ = IsRfc(u); !valid { + return + } + + return +} + +/* +MsGuidToUuid converts a Microsoft GUID to a UUID. + +If [IsMsGuid] is false for msGUID, u will be equal to msGUID. + +See [UuidToMsGuid] for the inverse, and [IsRfc] to check +if the result is a strictly conforming UUID. +*/ +func MsGuidToUuid(msGUID uuid.UUID) (u uuid.UUID) { + + if !IsMsGuid(msGUID, 0x00) { + u = msGUID + return + } + u = ToggleUuidMsGuid(msGUID) + + return +} + +/* +ToggleUuidMsGuid switches the src to it's "other" format: + + * if it's a Microsoft GUID, it will be converted to a UUID + * if it's a UUID, it will be converted to a Microsoft GUID + +No detection ([IsRfc], [IsMsGuid], etc.) nor validation/verification ([IsValid]) is performed, +which is why this is a "toggle" - it just flips some endianness for certain byte ranges. + +If you prefer something a little more explicit, see [MsGuidToUuid] and/or [UuidToMsGuid]. +Alternatively call [IsMsGuid] or [IsRfc] directly. +*/ +func ToggleUuidMsGuid(orig uuid.UUID) (converted uuid.UUID) { + + var cb [16]byte + var ob [16]byte = orig + + // Can just directly map the allocations; + // the operation is the exact same regardless of whether the original is RFC and target is MS or vice versa. + cb = [16]byte{ + // THESE GET ENDIAN-SWAPPED + ob[3], ob[2], ob[1], ob[0], // "A" + ob[5], ob[4], // "B" + ob[7], ob[6], // "C" + // THESE STAY THE SAME (should be BE for both) + ob[8], ob[9], ob[10], ob[11], // "D" + ob[12], ob[13], ob[14], ob[15], // "E" + } + + converted = uuid.UUID(cb) + + return +} + +/* +UuidToMsGuid converts a UUID to a Microsoft GUID. + +If [DetectMsGuid] indicates a good likelihood for u already being a Microsoft GUID +(greater than or equal) to [MsGuidThreshold], msGUID will be equal to u. +(If it detects it as unflipped endianness, it will automatically be flipped by this function.) + +See [MsGuidToUuid] for the inverse. +*/ +func UuidToMsGuid(u uuid.UUID) (msGUID uuid.UUID) { + + var msCmp int + var flipped int + + if msCmp, flipped = DetectMsGuid(u, 0x00); msCmp >= MsGuidThreshold && msCmp > flipped { + msGUID = u + return + } + msGUID = ToggleUuidMsGuid(u) + + return +} diff --git a/uuidx/funcs_rfcgen.go b/uuidx/funcs_rfcgen.go new file mode 100644 index 0000000..843430b --- /dev/null +++ b/uuidx/funcs_rfcgen.go @@ -0,0 +1,22 @@ +package uuidx + +// String conforms an [RfcGen] to a [fmt.Stringer] interface. +func (g *RfcGen) String() (s string) { + + if g == nil { + s = "UNSPECIFIED_NIL" + } + + switch *g { + case RfcNone: + s = "INVALID" + case Rfc4122: + s = "RFC 4122" + case Rfc9562: + s = "RFC 9562" + default: + s = "UNKNOWN" + } + + return +} diff --git a/uuidx/types.go b/uuidx/types.go new file mode 100644 index 0000000..2e53ca2 --- /dev/null +++ b/uuidx/types.go @@ -0,0 +1,5 @@ +package uuidx + +type ( + RfcGen uint8 +)