From 7fa4b648bb33fbf9d244ba6468750acaf6014a56 Mon Sep 17 00:00:00 2001 From: Micah Hausler Date: Thu, 15 Jun 2017 16:47:54 -0400 Subject: [PATCH] config: multi-line "indent" function This function prepends a number of spaces on to all but the first line of a string containing multiple lines of text. --- config/interpolate_funcs.go | 16 +++++++++++ config/interpolate_funcs_test.go | 28 +++++++++++++++++++ .../docs/configuration/interpolation.html.md | 6 ++++ 3 files changed, 50 insertions(+) diff --git a/config/interpolate_funcs.go b/config/interpolate_funcs.go index f7fd057793..b29b6b65a8 100644 --- a/config/interpolate_funcs.go +++ b/config/interpolate_funcs.go @@ -84,6 +84,7 @@ func Funcs() map[string]ast.Function { "floor": interpolationFuncFloor(), "format": interpolationFuncFormat(), "formatlist": interpolationFuncFormatList(), + "indent": interpolationFuncIndent(), "index": interpolationFuncIndex(), "join": interpolationFuncJoin(), "jsonencode": interpolationFuncJSONEncode(), @@ -675,6 +676,21 @@ func interpolationFuncFormatList() ast.Function { } } +// interpolationFuncIndent indents a multi-line string with the +// specified number of spaces +func interpolationFuncIndent() ast.Function { + return ast.Function{ + ArgTypes: []ast.Type{ast.TypeInt, ast.TypeString}, + ReturnType: ast.TypeString, + Callback: func(args []interface{}) (interface{}, error) { + spaces := args[0].(int) + data := args[1].(string) + pad := strings.Repeat(" ", spaces) + return strings.Replace(data, "\n", "\n"+pad, -1), nil + }, + } +} + // interpolationFuncIndex implements the "index" function that allows one to // find the index of a specific element in a list func interpolationFuncIndex() ast.Function { diff --git a/config/interpolate_funcs_test.go b/config/interpolate_funcs_test.go index 603b49a2ac..684348537d 100644 --- a/config/interpolate_funcs_test.go +++ b/config/interpolate_funcs_test.go @@ -1354,6 +1354,34 @@ func TestInterpolateFuncIndex(t *testing.T) { }) } +func TestInterpolateFuncIndent(t *testing.T) { + testFunction(t, testFunctionConfig{ + Cases: []testFunctionCase{ + { + `${indent(4, "Fleas: +Adam +Had'em + +E.E. Cummings")}`, + "Fleas:\n Adam\n Had'em\n \n E.E. Cummings", + false, + }, + { + `${indent(4, "oneliner")}`, + "oneliner", + false, + }, + { + `${indent(4, "#!/usr/bin/env bash +date +pwd")}`, + "#!/usr/bin/env bash\n date\n pwd", + false, + }, + }, + }) +} + func TestInterpolateFuncJoin(t *testing.T) { testFunction(t, testFunctionConfig{ Vars: map[string]ast.Variable{ diff --git a/website/docs/configuration/interpolation.html.md b/website/docs/configuration/interpolation.html.md index c3f925f35e..8ccc42dac9 100644 --- a/website/docs/configuration/interpolation.html.md +++ b/website/docs/configuration/interpolation.html.md @@ -257,6 +257,12 @@ The supported built-in functions are: `formatlist("instance %v has private ip %v", aws_instance.foo.*.id, aws_instance.foo.*.private_ip)`. Passing lists with different lengths to formatlist results in an error. + * `indent(numspaces, string)` - Prepends the specified number of spaces to all but the first + line of the given multi-line string. May be useful when inserting a multi-line string + into an already-indented context. The first line is not indented, to allow for the + indented string to be placed after some sort of already-indented preamble. + Example: `" \"items\": ${ indent(4, "[\n \"item1\"\n]") },"` + * `index(list, elem)` - Finds the index of a given element in a list. This function only works on flat lists. Example: `index(aws_instance.foo.*.tags.Name, "foo-test")`