Files
go_goutils/tplx/sprigx
brent saner 927ad08057 v1.16.0
ADDED:
* tplx/sprigx
2026-01-24 13:41:54 -05:00
..
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00
2026-01-24 13:41:54 -05:00

What is SprigX?

SprigX are extensions to the sprig library (Go docs).

They provide functions that offer more enriched use cases and domain-specific data.

How do I Use SprigX?

package main

import (
    htmlTplLib "html/template"
    txtTplLib "text/template"

    "r00t2.io/goutils/tplx/sprigx"
)

var (
    txtTpl *txtTplLib.Template = txtTplLib.
                                    New("").
                                        Funcs(
                                            sprigx.TxtFuncMap(),
                                        )
    htmlTpl *htmlTplLib.Template = htmlTplLib.
                                    New("").
                                        Funcs(
                                            sprigx.HtmlFuncMap(),
                                        )
)

package main

import (
    "text/template"

    "github.com/Masterminds/sprig/v3"
    "r00t2.io/goutils/tplx/sprigx"
)

var txtTpl *template.Template = template.
                                    New("").
                                        Funcs(
                                            sprigx.TxtFuncMap(),
                                        ).
                                        Funcs(
                                            sprig.TxtFuncMap(),
                                        )
// Or:
/*
var txtTpl *template.Template = template.
                                    New("").
                                        Funcs(
                                            sprig.TxtFuncMap(),
                                        ).
                                        Funcs(
                                            sprigx.TxtFuncMap(),
                                        )
 */

If a <template>.FuncMap is added via .Funcs() after template parsing, it will override any functions of the same name of a <template>.FuncMap before parsing.

For example, if both sprig and sprigx provide a function foo:

package main

import (
    "text/template"

    "github.com/Masterminds/sprig/v3"
    "r00t2.io/goutils/tplx/sprigx"
)

const (
    myTpl string = `{{ "This is an example template string." | foo }}`
)

var (
    tpl *template.Template = template.Must(
                                template.
                                    New("").
                                        Funcs(sprig.TxtFuncMap()).
                                        Parse(myTpl),
                                    ).
                                    Funcs(sprigx.TxtFuncMap())
)

whereas

package main

import (
    "text/template"

    "github.com/Masterminds/sprig/v3"
    "r00t2.io/goutils/tplx/sprigx"
)

const (
    myTpl string = `{{ "This is an example template string." | foo }}`
)

var (
    tpl *template.Template = template.Must(
                                template.
                                    New("").
                                        Funcs(sprigx.TxtFuncMap()).
                                        Parse(myTpl),
                                    ).
                                    Funcs(sprig.TxtFuncMap())
)

and a function can even be

This would override a function foo and foo2 in sprigx from foo and foo2 from sprig, but leave all other sprig functions untouched.

package main

import (
    "text/template"

    "github.com/Masterminds/sprig/v3"
    "r00t2.io/goutils/tplx/sprigx"
)

const (
    myTpl string = `{{ "This is an example template string." | foo }}`
)

var (
    overrideFuncs template.FuncMap = sprig.TxtFuncMap()
    tpl *template.Template = template.Must(
                                template.
                                    New("").
                                    Funcs(sprigx.TxtFuncMap()).
                                    Parse(myTpl),
                                ).
                                    Funcs(
                                        template.FuncMap(
                                            map[string]any{
                                                "foo": overrideFuncs["foo"],
                                                "foo2": overrideFuncs["foo2"],
                                            },
                                        ),
                                    )
)

Functions

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

System/OS/Platform

sysArch

Returns the runtime.GOARCH constant.

sysNumCpu

Returns the value from runtime.NumCPU.

sysOsName

Returns the runtime.GOOS constant.

sysRuntime

This function returns a map[string]string of various information from the runtime stdlib library.

Specifically, the following are returned.

The value type is a direct link to the runtime documentation providing more detail about the associated value.

Because all values are mapped as strings, they can be converted back to their native type via e.g. the Sprig conversion functions if necessary.

sysRuntime Values
Key Value Type

compiler

string

arch

string

os

string

maxprocs

int 1

cpu_cnt

int

num_cgo

int

num_go

int

go_ver

string


  1. For safety concerns, sprigx does not allow setting GOMAXPROCS, this value only contains the current GOMAXPROCS value.↩︎

As a convenience, some of these values also have their own dedicated functions as well:

Paths

Generic

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

pathJoin

pathJoin operates exactly like path.Join in stdlib.

If you are joining paths in a pipeline, you almost assuredly want or instead.

{{- pathJoin "a" "b" "c" }}
{{- pathJoin "/" "a" "b" "c" }}
{{- pathJoin "/a/b" "c" }}

renders as:

a/b/c
/a/b/c
/a/b/c

pathPipeJoin

pathPipeJoin operates like with one deviation: the root/base path is expected to be last in the arguments.

This makes it much more suitable for use in template pipelines, as the previous value in a pipeline is passed in as the last element to the next pipe function.

{{- $myBase := "/a" -}}
{{- pathPipeJoin "b" "c" "a" }}
{{- pathPipeJoin "a" "b" "c" "/" }}
{{- $myBase | pathPipeJoin "b" "c" }}

renders as:

a/b/c
/a/b/c
/a/b/c

pathSliceJoin

pathSliceJoin joins a slice of path segment strings ([]string) instead of a variadic sequence of strings.

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

{{- $myList := "a,b,c" | splitList "," -}}
{{- $myList | pathSliceJoin }}
{{- ("a,b,c" | splitList ",") | pathSliceJoin }}
{{- ("/,a,b,c" | splitList ",") | pathSliceJoin }}

renders as:

a/b/c
a/b/c
/a/b/c

pathSlicePipeJoin

pathSlicePipeJoin operates like in that it is suitable for pipeline use in which the root/base path is passed in from the pipeline, but it is like in that it then also accepts a slice of path segments ([]string) to append to that base path.

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

{{- $myBase := "/a" -}}
{{- $myList := "b,c,d" | splitList "." -}}
{{- pathSlicePipeJoin $myList $myBase }}
{{- $myBase | pathSlicePipeJoin $myList }}

renders as:

/a/b/c
/a/b/c

pathSubJoin

pathSubJoin operates like but it expects an explicit root/base path.

The pipeline-friendly equivalent of this is .

{{- pathSubJoin "/a/b" "c" }}
{{- pathSubJoin "/" "a" "b" "c" }}
{{- "c" | pathSubJoin "/" "a" "b" }}

renders as:

/a/b/c
/a/b/c
/a/b/c

OS/Platform-Tailored

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

Take special note of the oddness around specifying Windows paths and drive letters in e.g. !

It is recommended to make use of to conditionally format path bases/roots if needed.

osPathJoin

osPathJoin operates exactly like path/filepath.Join in stdlib.

If you are joining paths in a pipeline, you almost assuredly want or instead.

{{- osPathJoin "a" "b" "c" }}
{{- osPathJoin "/" "a" "b" "c" }}
{{- osPathJoin "C:\\" "a" "b" "c" }}
{{- osPathJoin "C:" "a" "b" "c" }}

renders as:

OS Result

Windows

a\b\c
\a\b\c
\a\b\c
C:\a\b\c
C:a\b\c

Others (e.g. Linux, macOS)

a/b/c
/a/b/c
C:\/a/b/c
C:/a/b/c

osPathPipeJoin

osPathPipeJoin operates like (except using OS-specific path separators).

This makes it much more suitable for use in template pipelines, as the previous value in a pipeline is passed in as the last element to the next pipe function.

{{- $myBase := "/a" -}}
{{- osPathPipeJoin "b" "c" "a" }}
{{- osPathPipeJoin "a" "b" "c" "/" }}
{{- $myBase | osPathPipeJoin "b" "c" }}

renders as:

OS Result

Windows

a\b\c
\a\b\c
\a\b\c

Others (e.g. Linux, macOS)

a/b/c
/a/b/c
/a/b/c

osPathSep

osPathSep returns the os.PathSeparator for this OS.

{{- osPathSep }}

renders as:

OS Result

Windows

\

Others (e.g. Linux, macOS)

/

osPathSliceJoin

osPathSliceJoin operates like but with OS-specific path separators.

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

{{- $myList := "a,b,c" | splitList "," -}}
{{- $myList | osPathSliceJoin }}
{{- ("a,b,c" | splitList ",") | osPathSliceJoin }}
{{- ("/,a,b,c" | splitList ",") | osPathSliceJoin }}

renders as:

OS Result

Windows

a\b\c
a\b\c
\a\b\c

Others (e.g. Linux, macOS)

a/b/c
a/b/c
/a/b/c

osPathSlicePipeJoin

osPathSlicePipeJoin operates like but with OS-specific separators.

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

{{- $myBase := "/a" -}}
{{- $myList := "b,c,d" | splitList "." -}}
{{- osPathSlicePipeJoin $myList $myBase }}
{{- $myBase | osPathSlicePipeJoin $myList }}

renders as:

OS Result

Windows

\a\b\c\d
\a\b\c\d

Others (e.g. Linux, macOS)

/a/b/c/d
/a/b/c/d

osPathSubJoin

osPathSubJoin operates like but with OS-specific separators.

The pipeline-friendly equivalent of this is .

{{- osPathSubJoin "/a/b" "c" }}
{{- osPathSubJoin "/" "a" "b" "c" }}
{{- "c" | osPathSubJoin "/" "a" "b" }}

renders as:

OS Result

Windows

\a\b\c
\a\b\c
\a\b\c

Others (e.g. Linux, macOS)

/a/b/c
/a/b/c
/a/b/c

Strings

extIndent

extIndent allows for a MUCH more flexible indenter than the sprig indent function.

It works with both Windows (\r\n) and POSIX (\n) linebreaks.

It has quite a few arguments, however:

{{ extIndent <levels> <skipFirst> <skipEmpty> <skipWhitespace> <indentString> <input> }}

Where:

  • <levels>: The level of indentation for the text. If less than or equal to 0, extIndent just returns <input> as-is and NO-OPs otherwise.

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

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

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

  • <indentString>: The string to use as the "indent character". This can be any string, such as " ", "\t", ".", "|", "==" etc.

  • <input>: The text to be indented. Because it is the last argument, extIndent works with pipelined text as well.