diff options
| author | Dave Henderson <dhenderson@gmail.com> | 2017-04-08 16:11:42 -0400 |
|---|---|---|
| committer | Dave Henderson <dhenderson@gmail.com> | 2017-04-08 17:41:36 -0400 |
| commit | 3c0171bfb7c02639a15af75ca777fb0cd7fe84d1 (patch) | |
| tree | 5c606c520a23f5db939f5fcbcb2dabc386d2a9bc | |
| parent | 4f04674bee1b0ce19a7a4c3b4e68f7181369de2c (diff) | |
Adding more ways to specify input/output for gomplate
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
| -rw-r--r-- | README.md | 18 | ||||
| -rw-r--r-- | main.go | 77 | ||||
| -rw-r--r-- | main_test.go | 19 |
3 files changed, 101 insertions, 13 deletions
@@ -33,6 +33,8 @@ Gomplate is an alternative that will let you process templates which also includ - [manual install](#manual-install) - [Usage](#usage) - [Commandline Arguments](#commandline-arguments) + - [`--file`/`-f`, `--in`/`-i`, and `--out`/`-o`](#-file-f-in-i-and-out-o) + - [Multiple inputs](#multiple-inputs) - [`--datasource`/`-d`](#-datasource-d) - [Overriding the template delimiters](#overriding-the-template-delimiters) - [Syntax](#syntax) @@ -180,6 +182,18 @@ Hello, hairyhenderson ### Commandline Arguments +#### `--file`/`-f`, `--in`/`-i`, and `--out`/`-o` + +By default, `gomplate` will read from `Stdin` and write to `Stdout`. This behaviour can be changed. + +- Use `--file`/`-f` to use a specific input template file. The special value `-` means `Stdin`. +- Use `--out`/`-o` to save output to file. The special value `-` means `Stdout`. +- Use `--in`/`-i` if you want to set the input template right on the commandline. This overrides `--file`. Because of shell command line lengths, it's probably not a good idea to use a very long value with this argument. + +##### Multiple inputs + +You can specify multiple `--file` and `--out` arguments. The same number of each much be given. This allows `gomplate` to process multiple templates _slightly_ faster than invoking `gomplate` multiple times in a row. + #### `--datasource`/`-d` Add a data source in `name=URL` form. Specify multiple times to add multiple sources. The data can then be used by the [`datasource`](#datasource) function. @@ -246,9 +260,9 @@ An optional default value can be given as well. ##### Example ```console -$ echo 'Hello, {{getenv "USER"}}' | gomplate +$ gomplate -i 'Hello, {{getenv "USER"}}' Hello, hairyhenderson -$ echo 'Hey, {{getenv "FIRSTNAME" "you"}}!' | gomplate +$ gomplate -i 'Hey, {{getenv "FIRSTNAME" "you"}}!' Hey, you! ``` @@ -26,15 +26,11 @@ type Gomplate struct { } // RunTemplate - -func (g *Gomplate) RunTemplate(in io.Reader, out io.Writer) { +func (g *Gomplate) RunTemplate(text string, out io.Writer) { context := &Context{} - text, err := ioutil.ReadAll(in) + tmpl, err := g.createTemplate().Delims(g.leftDelim, g.rightDelim).Parse(text) if err != nil { - log.Fatalf("Read failed!\n%v\n", err) - } - tmpl, err := g.createTemplate().Delims(g.leftDelim, g.rightDelim).Parse(string(text)) - if err != nil { - log.Fatalf("Line %q: %v\n", string(text), err) + log.Fatalf("Line %q: %v\n", text, err) } if err := tmpl.Execute(out, context); err != nil { @@ -82,6 +78,43 @@ func NewGomplate(data *Data, leftDelim, rightDelim string) *Gomplate { } } +func readInputs(input string, files []string) []string { + if input != "" { + return []string{input} + } + if len(files) == 0 { + files = []string{"-"} + } + ins := make([]string, len(files)) + + for n, filename := range files { + var err error + var inFile *os.File + if filename == "-" { + inFile = os.Stdin + } else { + inFile, err = os.Open(filename) + if err != nil { + log.Fatalf("Failed to open %s\n%v", filename, err) + } + defer inFile.Close() // nolint: errcheck + } + bytes, err := ioutil.ReadAll(inFile) + if err != nil { + log.Fatalf("Read failed for %s!\n%v\n", filename, err) + } + ins[n] = string(bytes) + } + return ins +} + +func openOutFile(filename string) (out *os.File, err error) { + if filename == "-" { + return os.Stdout, nil + } + return os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) +} + func runTemplate(c *cli.Context) error { defer runCleanupHooks() data := NewData(c.StringSlice("datasource")) @@ -89,7 +122,23 @@ func runTemplate(c *cli.Context) error { rDelim := c.String("right-delim") g := NewGomplate(data, lDelim, rDelim) - g.RunTemplate(os.Stdin, os.Stdout) + + inputs := readInputs(c.String("in"), c.StringSlice("file")) + + outputs := c.StringSlice("out") + if len(outputs) == 0 { + outputs = []string{"-"} + } + + for n, input := range inputs { + out, err := openOutFile(outputs[n]) + if err != nil { + return err + } + defer out.Close() // nolint: errcheck + g.RunTemplate(input, out) + } + return nil } @@ -102,6 +151,18 @@ func main() { app.Flags = []cli.Flag{ cli.StringSliceFlag{ + Name: "file, f", + Usage: "Template file to process. Omit to use standard input (-), or use --in", + }, + cli.StringFlag{ + Name: "in, i", + Usage: "Template string to process (alternative to --file)", + }, + cli.StringSliceFlag{ + Name: "out, o", + Usage: "Output file name. Omit to use standard output (-).", + }, + cli.StringSliceFlag{ Name: "datasource, d", Usage: "Data source in alias=URL form. Specify multiple times to add multiple sources.", }, diff --git a/main_test.go b/main_test.go index 5c2c925c..268d2afb 100644 --- a/main_test.go +++ b/main_test.go @@ -2,9 +2,9 @@ package main import ( "bytes" + "io/ioutil" "net/http/httptest" "os" - "strings" "testing" "text/template" @@ -14,9 +14,8 @@ import ( ) func testTemplate(g *Gomplate, template string) string { - in := strings.NewReader(template) var out bytes.Buffer - g.RunTemplate(in, &out) + g.RunTemplate(template, &out) return out.String() } @@ -151,3 +150,17 @@ func TestCustomDelim(t *testing.T) { } assert.Equal(t, "hi", testTemplate(g, `[print "hi"]`)) } + +func TestReadInput(t *testing.T) { + actual := readInputs("foo", nil) + assert.Equal(t, "foo", actual[0]) + + // stdin is "" because during tests it's given /dev/null + actual = readInputs("", []string{"-"}) + assert.Equal(t, "", actual[0]) + + actual = readInputs("", []string{"main_test.go"}) + thisFile, _ := os.Open("main_test.go") + expected, _ := ioutil.ReadAll(thisFile) + assert.Equal(t, string(expected), actual[0]) +} |
