Skip to content

Commit fbd513e

Browse files
committed
Closes #9
- Add tests for dot-notation variable names - Restore `-m` parameter - Fix flag handling - Add support for multiple default settings files in folder - Compute reasonable default names for settings and templates - Create examples and move some tests there - Update the README.md
1 parent ac0c784 commit fbd513e

19 files changed

+244
-309
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ PREFIX ?= usr/local
1313

1414
all: release vet test ## Make everything
1515

16-
build: # BUild darwin
16+
build: # Build darwin
1717
goreleaser --config .goreleaser-darwin.yml --debug --rm-dist --skip-publish --skip-validate
1818

1919
release: ## Build releases

README.md

+22-26
Original file line numberDiff line numberDiff line change
@@ -8,49 +8,43 @@ Render Go text templates from the command line.
88

99
Supports providing top-level name/value pairs on the command line:
1010

11-
renderizer --name=value --top=first template-file
11+
echo 'Hello, {{.User}}' | renderizer --user=${USER}
1212

13-
Sets:
14-
15-
Name: value
16-
Top: first
13+
And read from the environment:
1714

18-
**NOTE:**
15+
echo 'Hello, {{.env.User}}' | renderizer
1916

20-
- Template values are provided `--name=value`.
21-
- Renderizer controls are provided using `-NAME[=value]`.
17+
## Usage:
2218

23-
## Example
19+
renderizer [OPTIONS] [--name=value]... [template-file]...
2420

25-
First:
26-
27-
git clone https://github.com/gomatic/renderizer.git
28-
cd renderizer
29-
go build
21+
## Examples
3022

3123
Render the `pod.yaml` using values from `test/.renderizer.yaml`:
3224

33-
renderizer -S=test/.renderizer.yaml test/pod.yaml
25+
renderizer --settings=example/pod/.pod.yaml example/pod/pod.yaml.tmpl
3426

3527
Or set `RENDERIZER` in the environment:
3628

37-
RENDERIZER=test/.renderizer.yaml renderizer test/pod.yaml
29+
RENDERIZER=example/.pod.yaml renderizer example/pod/pod.yaml.tmpl
3830

3931
Alternatively, it'll try `.renderizer.yaml` in the current directory.
4032

41-
(cd test; renderizer pod.yaml)
33+
(cd example/pod; renderizer pod.yaml)
4234

43-
Next, override the `deployment` value to render the "dev" `pod.yaml` (after `cd test/`):
35+
Next, override the `deployment` value to render the "dev" `pod.yaml` (after `cd example/pod`):
4436

4537
renderizer --deployment=dev --name='spaced out' pod.yaml
4638

47-
## Configuration
39+
For more examples, see the [`examples`](examples) folder.
40+
41+
# Configuration
4842

49-
### Settings `-S=`
43+
### Settings
5044

5145
Settings can be loaded from a yaml:
5246

53-
renderizer -S=renderizer.yaml --name=value --top=first template-file
47+
renderizer --settings=.renderizer.yaml --name=value --top=first template-file
5448

5549
### Capitalization `-C`
5650

@@ -65,17 +59,19 @@ Sets:
6559
Name: value
6660
top: first
6761

68-
### Missing Keys `-M=`
62+
### Missing Keys
6963

7064
Control the missingkeys template-engine option:
7165

72-
renderizer -M=zero --top=first template-file
66+
renderizer --missing=zero --top=first template-file
67+
68+
### Environment
7369

74-
### Environment `-E=`
70+
Provide a name for the environment variables:
7571

76-
Provide a default value for missing environment variables:
72+
renderizer --environment=env template-file
7773

78-
renderizer -E=--missing-- template-file
74+
It defaults to `env` which is effectively the same as the above `--environment=env`.
7975

8076
## Template Functions
8177

examples/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Examples
2+
3+
In each folder, just run:
4+
5+
renderizer

examples/basic/.basic.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Name: Renderizer
2+
Items:
3+
- one
4+
- two
5+
- three

examples/document/.document.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
items:
2+
- apple
3+
- banana
4+
- cherry
5+
foo: true
File renamed without changes.

go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
github.com/gomatic/funcmap v0.0.0-20170407194050-9ab29796c307 h1:vdV1B6lc0iOnze2OvoHREif4bzaYTY5WHo1+HhBD2io=
22
github.com/gomatic/funcmap v0.0.0-20170407194050-9ab29796c307/go.mod h1:tgYMANYRbfiPtGpM0in6m2dnRENPq5Oj0f+eJkTBT1E=
3+
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
34
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
45
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 h1:PJPDf8OUfOK1bb/NeTKd4f1QXZItOX389VN3B6qC8ro=
56
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=

main.go

+94-34
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"os"
88
"path/filepath"
99
"strings"
10-
"time"
1110

1211
"github.com/kardianos/osext"
1312
"github.com/urfave/cli"
@@ -19,11 +18,9 @@ var (
1918
commit = "unknown"
2019
date = "none"
2120
selfn, _ = osext.Executable()
22-
selfd, _ = osext.ExecutableFolder()
2321
selfz = filepath.Base(selfn)
2422
semver = version + "-" + commit[:7] + "." + date
2523
appver = selfz + "/" + semver
26-
started = time.Now().Format("20060102T150405Z0700")
2724
)
2825

2926
//
@@ -33,16 +30,20 @@ type Settings struct {
3330
// Set the Missing Key template option. Defaults to "error".
3431
MissingKey string
3532
// Configuration yaml
36-
ConfigFiles []string
33+
ConfigFiles cli.StringSlice
3734
Defaulted bool
3835
Config map[string]interface{}
3936
//
4037
Arguments []string
4138
// Add the environment map to the variables.
4239
Environment string
4340
//
41+
OutputExtension string
42+
//
4443
TimeFormat string
4544
//
45+
Stdin bool
46+
//
4647
Debugging bool
4748
//
4849
Verbose bool
@@ -55,6 +56,7 @@ var settings = Settings{
5556
TimeFormat: "20060102T150405",
5657
Environment: "env",
5758
Config: map[string]interface{}{},
59+
ConfigFiles: []string{},
5860
Arguments: []string{},
5961
}
6062

@@ -66,24 +68,8 @@ func main() {
6668
app.UsageText = "Template renderer"
6769
app.Version = appver
6870
app.EnableBashCompletion = true
69-
configs := cli.StringSlice([]string{".renderizer.yaml"})
7071

71-
// Remove args that are not processed by urfave/cli
72-
var args []string
73-
for _, arg := range os.Args {
74-
larg := strings.ToLower(arg)
75-
switch {
76-
case larg == "-c":
77-
fallthrough
78-
case strings.HasPrefix(arg, "--") && strings.Contains(arg, "="):
79-
settings.Arguments = append(settings.Arguments, arg)
80-
81-
case strings.HasPrefix(arg, "--"):
82-
fallthrough
83-
default:
84-
args = append(args, arg)
85-
}
86-
}
72+
configs := cli.StringSlice{}
8773

8874
app.Commands = []cli.Command{
8975
{
@@ -98,22 +84,29 @@ func main() {
9884

9985
app.Flags = []cli.Flag{
10086
cli.StringSliceFlag{
101-
Name: "settings, S",
102-
Usage: "load the settings from the provided YAMLs",
87+
Name: "settings, S, s",
88+
Usage: `load the settings from the provided YAMLs (default: ".renderizer.yaml")`,
10389
Value: &configs,
10490
EnvVar: "RENDERIZER",
10591
},
10692
cli.StringFlag{
107-
Name: "environment, env, E",
108-
Usage: "load the environment into the variable name instead of as 'env'",
109-
},
110-
cli.StringFlag{
111-
Name: "missing, M",
93+
Name: "missing, M, m",
11294
Usage: "the 'missingkey' template option (default|zero|error)",
11395
Value: "error",
11496
EnvVar: "RENDERIZER_MISSINGKEY",
11597
Destination: &settings.MissingKey,
11698
},
99+
cli.StringFlag{
100+
Name: "environment, env, E, e",
101+
Usage: "load the environment into the variable name instead of as 'env'",
102+
Value: settings.Environment,
103+
EnvVar: "RENDERIZER_ENVIRONMENT",
104+
},
105+
cli.BoolFlag{
106+
Name: "stdin, c",
107+
Usage: "read from stdin",
108+
Destination: &settings.Stdin,
109+
},
117110
cli.BoolFlag{
118111
Name: "debugging, debug, D",
119112
Usage: "enable debugging server",
@@ -127,7 +120,35 @@ func main() {
127120
}
128121

129122
app.Before = func(ctx *cli.Context) error {
123+
124+
fi, _ := os.Stdin.Stat()
125+
126+
settings.Stdin = settings.Stdin || (fi.Mode()&os.ModeCharDevice) == 0
127+
130128
settings.Arguments = append(settings.Arguments, ctx.Args()...)
129+
if len(settings.Arguments) == 0 && !settings.Stdin {
130+
// Try default the template name
131+
folderName, err := os.Getwd()
132+
if err != nil {
133+
log.Println(err)
134+
folderName = "renderizer"
135+
} else {
136+
folderName = filepath.Base(folderName)
137+
}
138+
139+
for _, ext := range []string{".tmpl", ""} {
140+
for _, try := range []string{"yaml", "json", "html", "txt", "xml", ""} {
141+
name := fmt.Sprintf("%s.%s%s", folderName, try, ext)
142+
if _, err := os.Stat(name); err == nil {
143+
if settings.Verbose {
144+
log.Printf("using template: %+v", name)
145+
}
146+
settings.Arguments = []string{name}
147+
}
148+
}
149+
}
150+
151+
}
131152

132153
switch settings.MissingKey {
133154
case "zero", "error", "default", "invalid":
@@ -136,9 +157,15 @@ func main() {
136157
settings.MissingKey = "error"
137158
}
138159

139-
if len(settings.ConfigFiles) == 0 {
160+
if len(configs) == 0 {
161+
name := "renderizer"
162+
if len(settings.Arguments) >= 1 {
163+
name = strings.Split(strings.TrimLeft(filepath.Base(settings.Arguments[0]), "."), ".")[0]
164+
}
140165
settings.Defaulted = true
141-
settings.ConfigFiles = []string{".renderizer.yaml"}
166+
settings.ConfigFiles = []string{"." + name + ".yaml"}
167+
} else {
168+
settings.ConfigFiles = configs
142169
}
143170

144171
for _, config := range settings.ConfigFiles {
@@ -149,22 +176,55 @@ func main() {
149176
}
150177
} else {
151178
yaml.Unmarshal(in, &settings.Config)
152-
if settings.Verbose && settings.Defaulted {
153-
log.Printf("used config: %+v", settings.ConfigFiles)
179+
if settings.Verbose || settings.Defaulted {
180+
log.Printf("using settings: %+v", settings.ConfigFiles)
154181
}
155182
}
156183
if settings.Debugging {
157-
log.Printf("-settings:%#v", settings)
184+
log.Printf("--settings:%#v", settings)
158185
log.Printf("loaded: %#v", settings.Config)
159186
} else if settings.Verbose {
160-
log.Printf("-settings:%+v", settings)
187+
log.Printf("--settings:%+v", settings)
161188
log.Printf("loaded: %+v", settings.Config)
162189
}
163190
}
164191

165192
return nil
166193
}
167194

195+
// Remove args that are not processed by urfave/cli
196+
args := []string{os.Args[0]}
197+
if len(os.Args) > 1 {
198+
next := false
199+
for _, arg := range os.Args[1:] {
200+
larg := strings.ToLower(arg)
201+
if next {
202+
args = append(args, arg)
203+
next = false
204+
continue
205+
}
206+
if strings.HasPrefix(larg, "--") {
207+
flag := larg
208+
parts := strings.SplitN(larg, "=", 2)
209+
if len(parts) == 2 {
210+
flag = parts[0]
211+
}
212+
switch flag[2:] {
213+
case "settings", "missing":
214+
// If the flag requires a parameter but it is not specified with an =, grab the next argument too.
215+
if !strings.Contains(larg, "=") {
216+
next = true
217+
}
218+
fallthrough
219+
case "debug", "verbose", "version", "stdin":
220+
args = append(args, arg)
221+
continue
222+
}
223+
}
224+
settings.Arguments = append(settings.Arguments, arg)
225+
}
226+
}
227+
168228
app.Action = renderizer
169229
app.Run(args)
170230
}

0 commit comments

Comments
 (0)