template / commit
Consolidated template creation.
README.md | 26 +++++++++-- file.go | 129 ++++++++++++++++++++++++--------------------------- go.mod | 7 ++- go.sum | 15 ++---- main.go | 51 ++++++++++++++------- name_pattern.go | 132 +++++++++++++++++++++++++---------------------------- postscript.go | 61 +++++++++++-------------- postscript_test.go | 87 +++++++++++++++++------------------ templating.go | 34 ++++++++++++++ 9 files changed, 285 insertions(+), 257 deletions(-) diff --git a/README.md b/README.md index 11bba29..02b3ac0 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,26 @@ Creating a folder: template -d "{{.Year}}-{{.Month}}-{{.Day}}-{{.ProjectName}}.txt" Test123 ``` +### Using a script template directly + +You can also specify a template script: + +```sh +template --script "echo 'Hello from {{.YYYY_MM_DD}}!'" +``` + +will result in: + +```txt +> template --script "echo 'Hello from {{.YYYY_MM_DD}}!'" +Project name: +Loaded config from C:\Users\pavel\.template.yaml +Loaded user config from C:\Users\pavel\.template.user.yaml, combining with global config +Executing post script: cmd /c echo 'Hello from 2023-04-02!' +Post script output: 'Hello from 2023-04-02!' + +``` + ## Examples ### Use `daily` profile to create a new file @@ -141,19 +161,19 @@ curl -X GET "https://httpbin.org/delay/3" -H "accept: application/json" 2>&1 | ### Specify file pattern and project name ```sh -template -f "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}-{{.ProjectName}}.txt" test +template -file "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}-{{.ProjectName}}.txt" test ``` ### Specify file pattern, project name, and piped input ```sh -history | template -f "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}-{{.ProjectName}}.txt" "Hi all!" +history | template -file "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}-{{.ProjectName}}.txt" "Hi all!" ``` ### Specify folder pattern and project name ```sh -template -d "{{.Year}}-{{.Month}}-{{.Day}}-{{.ProjectName}}" test123 +template -dir "{{.Year}}-{{.Month}}-{{.Day}}-{{.ProjectName}}" test123 ``` ## Requirements diff --git a/file.go b/file.go index 2b451fe..1f1764b 100644 --- a/file.go +++ b/file.go @@ -1,70 +1,59 @@ -package main - -import ( - "bufio" - "fmt" - "os" - "strings" - "text/template" - - log "github.com/sirupsen/logrus" -) - -func createFile( - prePatternData PrePatternData, - fileTemplate ParameterizedText, - fullPath string, - pipeInputScanner *bufio.Scanner) error { - - useTemplate := fileTemplate != "" - useInputPipe := pipeInputScanner != nil - - if useInputPipe { - log.WithFields(log.Fields{"fullPath": fullPath}).Debug("Creating file from input pipe content", fullPath) - - file, err := monkey.OSCreate(fullPath) - if err != nil { - return fmt.Errorf("error creating file: %v", err) - } - defer file.Close() - - writer := bufio.NewWriter(file) - for pipeInputScanner.Scan() { - line := pipeInputScanner.Text() - _, err := writer.WriteString(line + "\n") - if err != nil { - return fmt.Errorf("error writing file: %v", err) - } - } - writer.Flush() - } else if useTemplate { - postPatternData := createPostPatternData(fullPath, prePatternData) - log.WithFields(log.Fields{"fullPath": fullPath}).Debug("Creating file from template string\n", fullPath) - - // parse template - template, err := template.New("text-template").Parse(string(fileTemplate)) - if err != nil { - return fmt.Errorf("error parsing template text: %v", err) - } - - // create output string - sb := new(strings.Builder) - err = template.Execute(sb, postPatternData) - if err != nil { - return fmt.Errorf("error creating templated file: %v", err) - } - - templateString := sb.String() - err = monkey.OSWriteFile(fullPath, []byte(templateString), os.ModePerm) - if err != nil { - return fmt.Errorf("error writing file: %v", err) - } - } else { - log.WithFields(log.Fields{"fullPath": fullPath}).Debug("Creating empty file", fullPath) - err := monkey.OSWriteFile(fullPath, []byte{}, os.ModePerm) - if err != nil { - return fmt.Errorf("error writing file: %v", err) - } - } - return nil -} +package main + +import ( + "bufio" + "fmt" + "os" + + log "github.com/sirupsen/logrus" +) + +func createFile( + prePatternData PrePatternData, + fileTemplate ParameterizedText, + fullPath string, + pipeInputScanner *bufio.Scanner) error { + + useTemplate := fileTemplate != "" + useInputPipe := pipeInputScanner != nil + + if useInputPipe { + log.WithFields(log.Fields{"fullPath": fullPath}).Debug("Creating file from input pipe content", fullPath) + + file, err := monkey.OSCreate(fullPath) + if err != nil { + return fmt.Errorf("error creating file: %v", err) + } + defer file.Close() + + writer := bufio.NewWriter(file) + for pipeInputScanner.Scan() { + line := pipeInputScanner.Text() + _, err := writer.WriteString(line + "\n") + if err != nil { + return fmt.Errorf("error writing file: %v", err) + } + } + writer.Flush() + } else if useTemplate { + postPatternData := createPostPatternData(fullPath, prePatternData) + log.WithFields(log.Fields{"fullPath": fullPath}).Debug("Creating file from template string\n", fullPath) + + templateString, err := parseAndExecTemplate(newTemplate(), fileTemplate, postPatternData) + if err != nil { + return fmt.Errorf("error creating templated file: %v", err) + } + + err = monkey.OSWriteFile(fullPath, []byte(templateString), os.ModePerm) + if err != nil { + return fmt.Errorf("error writing file: %v", err) + } + } else { + log.WithFields(log.Fields{"fullPath": fullPath}).Debug("Creating empty file", fullPath) + err := monkey.OSWriteFile(fullPath, []byte{}, os.ModePerm) + if err != nil { + return fmt.Errorf("error writing file: %v", err) + } + } + return nil +} diff --git a/go.mod b/go.mod index c8adc7c..6cc1a02 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module gitlab.com/PavelSafronov/template go 1.19 require ( - github.com/Masterminds/sprig/v3 v3.2.2 github.com/sirupsen/logrus v1.9.0 github.com/stretchr/testify v1.8.0 github.com/urfave/cli/v2 v2.16.3 @@ -11,9 +10,11 @@ require ( gopkg.in/yaml.v3 v3.0.1 ) +require github.com/Masterminds/semver v1.5.0 // indirect + require ( github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.1.1 // indirect + github.com/Masterminds/sprig v2.22.0+incompatible github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/google/uuid v1.1.1 // indirect @@ -23,8 +24,6 @@ require ( github.com/mitchellh/reflectwalk v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/shopspring/decimal v1.2.0 // indirect - github.com/spf13/cast v1.3.1 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 // indirect golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect diff --git a/go.sum b/go.sum index 35dfbc7..bb4b6d8 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= -github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -23,16 +23,10 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= @@ -55,7 +49,6 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 5392e2c..4d50cce 100644 --- a/main.go +++ b/main.go @@ -27,6 +27,7 @@ type ArgumentValues struct { projectName string fileTemplate string dirTemplate string + scriptTemplate string configFilePath string userConfigPath string extrasFilePath string @@ -77,6 +78,13 @@ func main() { Usage: "folder pattern to use to create a directory", Destination: &argumentValues.dirTemplate, }, + &cli.StringFlag{ + Name: "script", + Aliases: []string{"s"}, + Value: "", + Usage: "templated script to run in the shell", + Destination: &argumentValues.scriptTemplate, + }, &cli.StringFlag{ Name: "name", Aliases: []string{"n"}, @@ -252,7 +260,7 @@ func createSettings( log.WithFields(log.Fields{"args": args}).Debug("Args parsed") - skipProfile := len(settings.fileTemplate) > 0 || len(settings.dirTemplate) > 0 + skipProfile := len(settings.fileTemplate) > 0 || len(settings.dirTemplate) > 0 || len(settings.scriptTemplate) > 0 currentParamIndex := 0 if !skipProfile { @@ -354,24 +362,33 @@ func findProfile(settings Settings) (Profile, error) { var profile Profile = Profile{} var err error config := settings.config - createTempProfile := len(settings.fileTemplate) > 0 || len(settings.dirTemplate) > 0 + createTempProfile := len(settings.fileTemplate) > 0 || len(settings.dirTemplate) > 0 || len(settings.scriptTemplate) > 0 if createTempProfile { - profileType := FileType - if len(settings.dirTemplate) > 0 { - profileType = FolderType - } - patterns := []ParameterizedText{} - if len(settings.fileTemplate) > 0 { - patterns = append(patterns, ParameterizedText(settings.fileTemplate)) - } else if len(settings.dirTemplate) > 0 { - patterns = append(patterns, ParameterizedText(settings.dirTemplate)) - } - profile = Profile{ - Name: "temp", - Description: "temp", - Type: profileType, - NamePatterns: patterns, + if len(settings.scriptTemplate) > 0 { + profile = Profile{ + Name: "temp", + Description: "temp-script-profile", + Type: ScriptType, + PostScripts: []ParameterizedText{ParameterizedText(settings.scriptTemplate)}, + } + } else { + profileType := FileType + if len(settings.dirTemplate) > 0 { + profileType = FolderType + } + patterns := []ParameterizedText{} + if len(settings.fileTemplate) > 0 { + patterns = append(patterns, ParameterizedText(settings.fileTemplate)) + } else if len(settings.dirTemplate) > 0 { + patterns = append(patterns, ParameterizedText(settings.dirTemplate)) + } + profile = Profile{ + Name: "temp", + Description: fmt.Sprintf("temp-%s-profile", profileType), + Type: profileType, + NamePatterns: patterns, + } } } else { if settings.profile == "" { diff --git a/name_pattern.go b/name_pattern.go index 0c7dde8..da8db8e 100644 --- a/name_pattern.go +++ b/name_pattern.go @@ -1,71 +1,61 @@ -package main - -import ( - "errors" - "fmt" - "strings" - "text/template" - "time" - - "github.com/Masterminds/sprig/v3" -) - -func createNewNameForPatterns( - now time.Time, - patternData PrePatternData, - projectName string, - namePatterns []ParameterizedText, - extras map[string]string, - validator func(newName string) bool) (string, error) { - for index, namePattern := range namePatterns { - - startingVersion := 1 - invokeCount := 0 - funcMap := template.FuncMap{ - "getVersion": func() int { - invokeCount++ - return startingVersion - }, - } - template := template.New("template-name").Funcs(funcMap) - template = template.Funcs(sprig.FuncMap()) - - for { - - template, err := template.Parse(string(namePattern)) - if err != nil { - return "", fmt.Errorf("error parsing name pattern %d: %w", index, err) - } - - sb := new(strings.Builder) - err = template.Execute(sb, patternData) - if err != nil { - return "", fmt.Errorf("error executing name pattern %d: %w", index, err) - } - - newName := sb.String() - isValid := validator(newName) - useIndex := invokeCount > 0 - isLastPattern := index == len(namePatterns)-1 - - // if new name is valid, use this name - if isValid { - return newName, nil - } - - // if index is not being used (template did not invoke getVersion) - // then we're done - if !useIndex { - break - } - - // if getVersion was used, but this isn't the last pattern, report an error - if useIndex && !isLastPattern { - return "", errors.New("cannot use function getVersion in a pattern that is not the last pattern") - } - - startingVersion++ - } - } - return "", errors.New("couldn't find a new name") -} +package main + +import ( + "errors" + "fmt" + "text/template" + "time" +) + +func createNewNameForPatterns( + now time.Time, + patternData PrePatternData, + projectName string, + namePatterns []ParameterizedText, + extras map[string]string, + validator func(newName string) bool) (string, error) { + for index, namePattern := range namePatterns { + + startingVersion := 1 + invokeCount := 0 + funcMap := template.FuncMap{ + "getVersion": func() int { + invokeCount++ + return startingVersion + }, + } + t := newTemplate() + t = t.Funcs(funcMap) + + for { + + newName, err := parseAndExecTemplate(t, namePattern, patternData) + if err != nil { + return "", fmt.Errorf("error templating name pattern %d: %w", index, err) + } + + isValid := validator(newName) + useIndex := invokeCount > 0 + isLastPattern := index == len(namePatterns)-1 + + // if new name is valid, use this name + if isValid { + return newName, nil + } + + // if index is not being used (template did not invoke getVersion) + // then we're done + if !useIndex { + break + } + + // if getVersion was used, but this isn't the last pattern, report an error + if useIndex && !isLastPattern { + return "", errors.New("cannot use function getVersion in a pattern that is not the last pattern") + } + + startingVersion++ + } + } + return "", errors.New("couldn't find a new name") +} diff --git a/postscript.go b/postscript.go index 23d0f6c..a2f353f 100644 --- a/postscript.go +++ b/postscript.go @@ -1,35 +1,26 @@ -package main - -import ( - "fmt" - "strings" - "text/template" -) - -func createPostScriptArrays( - profile Profile, - postPatternData PostPatternData) ([]string, error) { - array := make([]string, 0) - - if profile.PostScripts == nil || len(profile.PostScripts) == 0 { - return nil, fmt.Errorf("no post scripts specified") - } - - for _, postScriptPattern := range profile.PostScripts { - template, err := template.New("postscript").Parse(string(postScriptPattern)) - if err != nil { - return nil, err - } - - sb := new(strings.Builder) - err = template.Execute(sb, postPatternData) - if err != nil { - return nil, err - } - - postScript := sb.String() - array = append(array, postScript) - } - - return array, nil -} +package main + +import ( + "fmt" +) + +func createPostScriptArrays( + profile Profile, + postPatternData PostPatternData) ([]string, error) { + array := make([]string, 0) + + if profile.PostScripts == nil || len(profile.PostScripts) == 0 { + return nil, fmt.Errorf("no post scripts specified") + } + + for _, postScriptPattern := range profile.PostScripts { + postScript, err := parseAndExecTemplate(newTemplate(), postScriptPattern, postPatternData) + if err != nil { + return nil, fmt.Errorf("error parsing post script: %w", err) + } + + array = append(array, postScript) + } + + return array, nil +} diff --git a/postscript_test.go b/postscript_test.go index e4e4fae..a1f9b98 100644 --- a/postscript_test.go +++ b/postscript_test.go @@ -1,46 +1,41 @@ -package main - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestCreatePostScriptArrays(t *testing.T) { - testFailure := func(profile Profile) { - _, err := createPostScriptArrays(profile, PostPatternData{FullPath: "test"}) - assert.NotNil(t, err, "Expected to fail to create post script arrays, but succeeded") - } - testSuccess := func(profile Profile) { - postscripts, err := createPostScriptArrays(profile, PostPatternData{ - FullPath: "test", - PrePatternData: PrePatternData{ - Extras: map[string]string{"foo": "bar"}, - }, - }) - assert.Nil(t, err, "Error creating postscript array") - assert.Equal(t, postscripts, []string{"echo \"test\"-bar "}) - } - - testSuccess(Profile{ - PostScripts: []ParameterizedText{ - "echo \"{{.FullPath}}\"-{{.Extras.foo}} ", - }, - }) - testFailure(Profile{ - PostScripts: nil, - }) - testFailure(Profile{ - PostScripts: []ParameterizedText{}, - }) - testFailure(Profile{ - PostScripts: []ParameterizedText{ - "echo \"{{.Name\"", - }, - }) - testFailure(Profile{ - PostScripts: []ParameterizedText{ - "echo \"{{.NameUnknown}}\"", - }, - }) -} +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCreatePostScriptArrays(t *testing.T) { + callCreatePostScriptArrays := func(postScripts []ParameterizedText) ([]string, error) { + return createPostScriptArrays( + Profile{PostScripts: postScripts}, + PostPatternData{ + FullPath: "test", + PrePatternData: PrePatternData{ + Extras: map[string]string{"foo": "bar"}, + }, + }) + } + + arr, err := callCreatePostScriptArrays([]ParameterizedText{"echo \"{{.FullPath}}\"-{{.Extras.foo}} "}) + assert.Nil(t, err, "Error creating postscript array") + assert.Equal(t, 1, len(arr)) + assert.Equal(t, arr[0], "echo \"test\"-bar ") + + arr, err = callCreatePostScriptArrays(nil) + assert.NotNil(t, err, "nil postscripts should fail") + assert.Nil(t, arr) + + arr, err = callCreatePostScriptArrays([]ParameterizedText{}) + assert.NotNil(t, err, "empty postscripts should fail") + assert.Nil(t, arr) + + arr, err = callCreatePostScriptArrays([]ParameterizedText{"echo \"{{.Name"}) + assert.NotNil(t, err, "invalid template should fail") + assert.Nil(t, arr) + + arr, err = callCreatePostScriptArrays([]ParameterizedText{"echo \"{{.NameUnknown}}\""}) + assert.NotNil(t, err, "invalid template variable should fail") + assert.Nil(t, arr) +} diff --git a/templating.go b/templating.go new file mode 100644 index 0000000..ed70933 --- /dev/null +++ b/templating.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "strings" + "text/template" + + "github.com/Masterminds/sprig" +) + +func newTemplate() *template.Template { + t := template.New("text-template") + t = t.Option("missingkey=error") + t = t.Funcs(sprig.FuncMap()) + return t +} + +func parseAndExecTemplate(t *template.Template, text ParameterizedText, data any) (string, error) { + // parse template + template, err := t.Parse(string(text)) + if err != nil { + return "", fmt.Errorf("error parsing template text: %v", err) + } + + // create output string + sb := new(strings.Builder) + err = template.Execute(sb, data) + if err != nil { + return "", fmt.Errorf("error creating templated file: %v", err) + } + + templateString := sb.String() + return templateString, nil +}