diff --git a/docs/strings.md b/docs/strings.md index 2e0f455d..4df226f1 100644 --- a/docs/strings.md +++ b/docs/strings.md @@ -268,6 +268,28 @@ nindent 4 $lots_of_text The above will indent every line of text by 4 space characters and add a new line to the beginning. +## extindent + +The `extindent` function offers a much more flexible extended indenter +at the cost of complexity. + +It allows for a customized indentation and indentation behavor but +requires 5 arguments in addition to the string to be indented. + +``` +$levels := 1 +$skipFirst := false +$skipEmpty := true +$skipWs := true +$indentString := "\t" + +extindent $levels $skipFirst $skipEmpty $skipWs $indentString $lots_of_text +``` + +The above will indent every line of `$lots_of_text` with a single (`1`) `\t` (horizontal tab), +*unless* that line is entirely empty (only a newline) or is comprised only entirely of whitespace +(tabs, spaces, etc.). + ## replace Perform simple string replacement. diff --git a/functions.go b/functions.go index cda47d26..d12ed2cf 100644 --- a/functions.go +++ b/functions.go @@ -157,6 +157,7 @@ var genericMap = map[string]interface{}{ "cat": cat, "indent": indent, "nindent": nindent, + "extindent": extIndent, "replace": replace, "plural": plural, "sha1sum": sha1sum, diff --git a/strings.go b/strings.go index e0ae628c..d5ac44f7 100644 --- a/strings.go +++ b/strings.go @@ -115,6 +115,24 @@ func nindent(spaces int, v string) string { return "\n" + indent(spaces, v) } +func extIndent(levels int, skipFirst, skipEmpty, skipWhitespace bool, indentStr, v string) string { + pad := strings.Repeat(indentStr, int(levels)) + lines := strings.Split(v, "\n") + for idx, line := range lines { + if idx == 0 && skipFirst { + continue + } + if skipWhitespace && strings.TrimSpace(line) == "" && line != "" { + continue + } + if skipEmpty && (line == "" || line == "\r") { + continue + } + lines[idx] = pad + line + } + return strings.Join(lines, "\n") +} + func replace(old, new, src string) string { return strings.Replace(src, old, new, -1) } diff --git a/strings_test.go b/strings_test.go index 28b9a1e8..51395855 100644 --- a/strings_test.go +++ b/strings_test.go @@ -280,6 +280,50 @@ func TestNindent(t *testing.T) { } } +func TestExtIndent(t *testing.T) { + + cmpstr := "1\nmt\n\nws\n\t\n." + + for _, tCase := range []struct{ + indt string + lvls int + skipFirst bool + skipEmpty bool + skipWs bool + tgt string + + }{ + {indt: "\t", lvls: 1, skipFirst: true, skipEmpty: true, skipWs: true, tgt: "1\n\tmt\n\n\tws\n\t\n\t."}, + {indt: "\t", lvls: 1, skipFirst: true, skipEmpty: true, skipWs: false, tgt: "1\n\tmt\n\n\tws\n\t\t\n\t."}, + {indt: "\t", lvls: 1, skipFirst: true, skipEmpty: false, skipWs: true, tgt: "1\n\tmt\n\t\n\tws\n\t\n\t."}, + {indt: "\t", lvls: 1, skipFirst: true, skipEmpty: false, skipWs: false, tgt: "1\n\tmt\n\t\n\tws\n\t\t\n\t."}, + {indt: "\t", lvls: 1, skipFirst: false, skipEmpty: true, skipWs: true, tgt: "\t1\n\tmt\n\n\tws\n\t\n\t."}, + {indt: "\t", lvls: 1, skipFirst: false, skipEmpty: true, skipWs: false, tgt: "\t1\n\tmt\n\n\tws\n\t\t\n\t."}, + {indt: "\t", lvls: 1, skipFirst: false, skipEmpty: false, skipWs: true, tgt: "\t1\n\tmt\n\t\n\tws\n\t\n\t."}, + {indt: "\t", lvls: 1, skipFirst: false, skipEmpty: false, skipWs: false, tgt: "\t1\n\tmt\n\t\n\tws\n\t\t\n\t."}, + } { + tplStr := fmt.Sprintf( + "{{- $lvls := %d -}}\n"+ + "{{- $no1st := %v -}}\n"+ + "{{- $noMT := %v -}}\n"+ + "{{- $noWs := %v -}}\n"+ + "{{- $idtstr := \"%s\" -}}\n"+ + "{{- $tstr := `%s` -}}\n"+ + "{{ $tstr | extindent $lvls $no1st $noMT $noWs $idtstr }}", + tCase.lvls, + tCase.skipFirst, + tCase.skipEmpty, + tCase.skipWs, + tCase.indt, + cmpstr, + ) + t.Log(tplStr) + if err := runt(tplStr, tCase.tgt); err != nil { + t.Error(err) + } + } +} + func TestReplace(t *testing.T) { tpl := `{{"I Am Henry VIII" | replace " " "-"}}` if err := runt(tpl, "I-Am-Henry-VIII"); err != nil {