summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Henderson <dhenderson@gmail.com>2017-04-08 16:11:42 -0400
committerDave Henderson <dhenderson@gmail.com>2017-04-08 17:41:36 -0400
commit3c0171bfb7c02639a15af75ca777fb0cd7fe84d1 (patch)
tree5c606c520a23f5db939f5fcbcb2dabc386d2a9bc
parent4f04674bee1b0ce19a7a4c3b4e68f7181369de2c (diff)
Adding more ways to specify input/output for gomplate
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
-rw-r--r--README.md18
-rw-r--r--main.go77
-rw-r--r--main_test.go19
3 files changed, 101 insertions, 13 deletions
diff --git a/README.md b/README.md
index d0ba12ce..2c7b8526 100644
--- a/README.md
+++ b/README.md
@@ -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!
```
diff --git a/main.go b/main.go
index c2511422..eedebb76 100644
--- a/main.go
+++ b/main.go
@@ -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])
+}