Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33

Open
lilleman wants to merge 966 commits from worktree-todo-relative-dates-exact-counts into main
7 changed files with 69 additions and 49 deletions
Showing only changes of commit 0de54c3b15 - Show all commits
+1 -1
View File
@@ -42,7 +42,7 @@ In [docs/decisions.md](docs/decisions.md):
- A struct tag is a template by its shape - A struct tag is a template by its shape
- The CLI renders exactly the template on its stdin, and adds nothing - The CLI renders exactly the template on its stdin, and adds nothing
- A template that does not compile is misuse (exit 2), including a reference that resolves to nothing, save a lone reference under the CLI's `--format` until item 129 - A template that does not compile is misuse (exit 2), including a reference that resolves to nothing, save a lone reference under the CLI's `--format` until item 129
- A padded JSON template is rejected, not trimmed - `NewTemplate` rejects a padded JSON template, and the CLI's stdin drops the whitespace around one
- `FakeTemplate` and `NewTemplate` both stay - `FakeTemplate` and `NewTemplate` both stay
- The shipped data is embedded, not discovered - The shipped data is embedded, not discovered
- With only the shipped set, a category loads on the first call reaching it; beside a `--data-path`, every category loads in `New` - With only the shipped set, a category loads on the first call reaching it; beside a `--data-path`, every category loads in `New`
+2 -2
View File
@@ -28,10 +28,10 @@ replacement, and each removed path, column or flag.
under [Names](README.md#names). under [Names](README.md#names).
- First release: the CLI, the library and the shipped data set. - First release: the CLI, the library and the shipped data set.
- The CLI renders exactly the template on its stdin, `echo '{/sv_SE.person} hihi' | - The CLI renders exactly the template on its stdin, `echo '{/sv_SE.person} hihi' |
fejkdata`, and adds nothing: `echo`'s newline ends the render, and `--separator` fejkdata`, and adds nothing to text: `echo`'s newline ends the render, and `--separator`
defaults to empty. Whitespace around a JSON template is dropped. A lone reference, defaults to empty. Whitespace around a JSON template is dropped. A lone reference,
`{/users}`, is the record `users` under `--format`. An argument other than a flag, an `{/users}`, is the record `users` under `--format`. An argument other than a flag, an
empty stdin, or nothing piped in, exits 2. empty or blank stdin, or nothing piped in, exits 2.
- Table categories: a category JSON naming a `rows` TSV beside it, with the options - Table categories: a category JSON naming a `rows` TSV beside it, with the options
`key`, `name`, `weight` and `parent`; a path selects a row by key or name, `key`, `name`, `weight` and `parent`; a path selects a row by key or name,
`misc.territory[SE]`, and descends to a linked table by name, one path drawing each `misc.territory[SE]`, and descends to a linked table by name, one path drawing each
+6 -4
View File
@@ -23,7 +23,7 @@ echo '{/misc.territory[SE].capital}' | fejkdata # Stockholm — a table
echo '{/geo.SE.locality[Lund].street}' | fejkdata # Fjelievägen — a linked table, drawn inside the row echo '{/geo.SE.locality[Lund].street}' | fejkdata # Fjelievägen — a linked table, drawn inside the row
echo '{/sv_SE.word}' | fejkdata --data-path ./mydata # layer a directory over the shipped data echo '{/sv_SE.word}' | fejkdata --data-path ./mydata # layer a directory over the shipped data
fejkdata --no-shipped-data -d ./mydata --list # only your data fejkdata --no-shipped-data -d ./mydata --list # only your data
echo '{"format":"name: {x}\n","x":["bosse","lina"]}' | fejkdata # name: bosse or name: lina echo '{"format":"name: {x}","x":["bosse","lina"]}' | fejkdata # name: bosse or name: lina
fejkdata < template.txt # a template kept in a file fejkdata < template.txt # a template kept in a file
fejkdata <<'EOF' # born 2003-11-27 — a quoted heredoc passes ', $ and \ as written fejkdata <<'EOF' # born 2003-11-27 — a quoted heredoc passes ', $ and \ as written
born {date(1990-01-01,2010-12-31,'2006-01-02')} born {date(1990-01-01,2010-12-31,'2006-01-02')}
@@ -38,10 +38,12 @@ inside one: each dot segment descends one level — folders, then the category (
file), then fields — and `[SE]` after a [table](#table) selects its row. `--list` prints file), then fields — and `[SE]` after a [table](#table) selects its row. `--list` prints
these paths; a template reads one as `{/path}`. these paths; a template reads one as `{/path}`.
What you send is what renders, and fejkdata adds nothing. A format string keeps every In text, what you send is what renders, and fejkdata adds nothing. A format string keeps every
byte, so `echo`, a file or a heredoc ends each render with its newline, and `printf '%s'` byte, so `echo`, a file or a heredoc ends each render with its newline, and `printf '%s'`
sends none; `-n` joins renders with `--separator`, empty by default. A JSON template is sends none; `-n` joins renders with `--separator`, empty by default. A JSON template is
its JSON, the whitespace around it dropped, so `42`, `true` or `null` alone is refused. A an object, array or string, and the whitespace around it is dropped; `42`, `true` or
`null` alone is refused. A JSON template that should end each render in a newline writes
`\n` in its format, from a quoted heredoc or a file. A
lone reference, one `{/…}` and nothing else, is the record it names under `--format`, one lone reference, one `{/…}` and nothing else, is the record it names under `--format`, one
newline after it allowed. Some shells' `echo` reads a backslash as an escape, so pipe a newline after it allowed. Some shells' `echo` reads a backslash as an escape, so pipe a
template holding one from a quoted heredoc or a file. The rest of stdin's rules are under template holding one from a quoted heredoc or a file. The rest of stdin's rules are under
@@ -63,7 +65,7 @@ template holding one from a quoted heredoc or a file. The rest of stdin's rules
follows (`-n3`, `-n 3`) and short flags bundle (`-hn 3`) — see follows (`-n3`, `-n 3`) and short flags bundle (`-hn 3`) — see
[Decisions](docs/decisions.md#flags-follow-getopt_long); flags go anywhere, `--` ends them. Exit codes: `0` success, `1` runtime error (missing [Decisions](docs/decisions.md#flags-follow-getopt_long); flags go anywhere, `--` ends them. Exit codes: `0` success, `1` runtime error (missing
dir, a lone reference to nothing under `--format`), `2` misuse — a bad flag, an argument dir, a lone reference to nothing under `--format`), `2` misuse — a bad flag, an argument
other than a flag, an empty or unreadable stdin, nothing piped in, or a other than a flag, an empty, blank or unreadable stdin, nothing piped in, or a
template that does not compile. From a checkout: template that does not compile. From a checkout:
`go run ./cmd/fejkdata …`. `go run ./cmd/fejkdata …`.
+26 -19
View File
@@ -28,7 +28,7 @@ const usage = `Usage: <template> | fejkdata [flags]
fejkdata reads one template from stdin and renders it: fejkdata reads one template from stdin and renders it:
echo 'name: {/sv_SE.person.last}' | fejkdata echo 'name: {/sv_SE.person.last}' | fejkdata
echo '{"format":"{x}\n","x":["bosse","lina"]}' | fejkdata echo '{"format":"{x}","x":["bosse","lina"]}' | fejkdata
fejkdata < template.txt fejkdata < template.txt
fejkdata <<'EOF' fejkdata <<'EOF'
@@ -42,21 +42,21 @@ path into one ({/sv_SE.person.last}), a table's row by key or name
({/misc.territory[SE]}), and .. steps up from a row to the row it links to ({/misc.territory[SE]}), and .. steps up from a row to the row it links to
({/geo.SE.locality..municipality.name}). ({/geo.SE.locality..municipality.name}).
What you send is what renders, and fejkdata adds nothing: a format string keeps In text, what you send is what renders, and fejkdata adds nothing: a format string keeps
every byte, so echo's newline ends each render, and printf '%s' sends none. -n every byte, so echo's newline ends each render, and printf '%s' sends none. -n
joins renders with --separator, empty by default. A JSON template is its JSON, the joins renders with --separator, empty by default. A JSON template is an object, array
whitespace around it dropped, so 42, true or null alone is refused. A quoted or string, and the whitespace around it is dropped; 42, true or null alone is refused. A quoted
heredoc, <<'EOF', passes $, a backslash or a quote as written. heredoc, <<'EOF', passes $, a backslash or a quote as written.
With --format json, ndjson, csv or sql the template must be a record — a JSON With --format json, ndjson, csv or sql the template must be a record — a JSON
template whose fields are its columns, or a lone reference, {/sv_SE.person}, one template whose fields are its columns, or a lone reference, one reference and nothing
newline after it allowed — and the rows are written as one JSON array, one JSON else such as {/sv_SE.person}, one newline after it allowed — and the rows are written as one JSON array, one JSON
object per line, one CSV row (after a header), or one INSERT. object per line, one CSV row (after a header), or one INSERT.
-d, --data-path D a data directory to layer over the shipped data (repeatable; last wins on a clash) -d, --data-path D a data directory to layer over the shipped data (repeatable; last wins on a clash)
--format F output form: text (default), json, ndjson, csv or sql --format F output form: text (default), json, ndjson, csv or sql
-h, --help print this help, then exit -h, --help print this help, then exit
--list list the paths the data offers, each one a reference from the root, then exit --list list the paths the data offers, each written after {/ in a template, then exit
--no-shipped-data load only the --data-path directories --no-shipped-data load only the --data-path directories
-n, --repeat N render the template N times, 1..1048576 (default 1) -n, --repeat N render the template N times, 1..1048576 (default 1)
-s, --seed N same seed, version and data: identical output -s, --seed N same seed, version and data: identical output
@@ -279,7 +279,8 @@ func (in invocation) checkFlags() error {
const pipeHint = "echo '{/sv_SE.person}' | fejkdata" const pipeHint = "echo '{/sv_SE.person}' | fejkdata"
// operandError refuses an argument that is no flag, naming the spelling that reads what // operandError refuses an argument that is no flag, naming the spelling that reads what
// it most likely means: stdin for -, a file for a file's name, else a template piped in. // it most likely means: dropping it for -, a file for a file's name, else a template
// piped in.
func operandError(arg string) error { func operandError(arg string) error {
unexpected := "unexpected argument '" + arg + "'" unexpected := "unexpected argument '" + arg + "'"
if arg == "-" { if arg == "-" {
@@ -289,8 +290,10 @@ func operandError(arg string) error {
return fmt.Errorf("%s; read a file from stdin: fejkdata < %s", unexpected, shellQuoted(arg)) return fmt.Errorf("%s; read a file from stdin: fejkdata < %s", unexpected, shellQuoted(arg))
} }
example := pipeHint example := pipeHint
if inline, err := fejkdata.IsTemplate(arg); !inline && err == nil { if inline, err := fejkdata.IsTemplate(arg); inline {
example = "echo '{/" + arg + "}' | fejkdata" example = "echo " + shellQuoted(arg) + " | fejkdata"
} else if _, lone := loneReference("{/" + arg + "}"); lone && err == nil {
example = "echo " + shellQuoted("{/"+arg+"}") + " | fejkdata"
} }
return fmt.Errorf("%s; the template is read from stdin: %s", unexpected, example) return fmt.Errorf("%s; the template is read from stdin: %s", unexpected, example)
} }
@@ -324,9 +327,8 @@ func (in invocation) options() []fejkdata.Option {
return opts return opts
} }
// write streams the input's renders to w, repeat of them joined by the separator. A // write streams the input's renders to w, repeat of them joined by the separator; a write
// value that renders once renders every time, so a render failure comes before anything // failure surfaces from Flush, bufio keeping the first one.
// is written; a write failure surfaces from Flush, bufio keeping the first one.
func (in invocation) write(f *fejkdata.Generator, src input, w io.Writer) error { func (in invocation) write(f *fejkdata.Generator, src input, w io.Writer) error {
if in.writesRecords() { if in.writesRecords() {
return in.writeRecords(f, src, w) return in.writeRecords(f, src, w)
@@ -421,11 +423,15 @@ func defaultTable(path string) string {
// inputError marks a failure that is the input's own fault — no template, one that does // inputError marks a failure that is the input's own fault — no template, one that does
// not compile, or a stdin that cannot be read. run reports it as misuse (exit 2, with a // not compile, or a stdin that cannot be read. run reports it as misuse (exit 2, with a
// pointer to --help), unlike a lone reference to nothing, which is a runtime error (exit 1). // pointer to --help), unlike a lone reference to nothing under --format, which is a runtime
// error (exit 1).
type inputError struct{ error } type inputError struct{ error }
func (e inputError) Unwrap() error { return e.error } func (e inputError) Unwrap() error { return e.error }
// jsonSpace is the whitespace JSON allows around a value.
const jsonSpace = " \t\r\n"
// input is what stdin holds: the template, and the path a lone reference names as a // input is what stdin holds: the template, and the path a lone reference names as a
// record. // record.
type input struct { type input struct {
@@ -433,15 +439,16 @@ type input struct {
record string record string
} }
// parseInput reads stdin. A format string is its every byte; a JSON template sheds the // parseInput reads stdin. A format string is every byte of stdin; a JSON template drops
// whitespace around it; a lone reference names a record less one newline ending it. // the whitespace around it; a lone reference names a record, with one newline ending it
// allowed.
func parseInput(raw string) (input, error) { func parseInput(raw string) (input, error) {
trimmed := strings.TrimSpace(raw) trimmed := strings.Trim(raw, jsonSpace)
if trimmed == "" { if trimmed == "" {
return input{}, fmt.Errorf("stdin holds no template: %s", pipeHint) return input{}, fmt.Errorf("stdin holds no template: %s", pipeHint)
} }
template := raw template := raw
if strings.ContainsRune(`{["`, rune(trimmed[0])) && json.Valid([]byte(trimmed)) { if json.Valid([]byte(trimmed)) {
template = trimmed template = trimmed
} }
text, found := strings.CutSuffix(template, "\n") text, found := strings.CutSuffix(template, "\n")
@@ -485,7 +492,7 @@ func spacedReference(template string, err error) error {
// shellQuoted is s as a shell reads it back: bare where it holds nothing a shell expands. // shellQuoted is s as a shell reads it back: bare where it holds nothing a shell expands.
func shellQuoted(s string) string { func shellQuoted(s string) string {
if s != "" && !strings.ContainsAny(s, " \t'\"$`\\*?[]{}()<>|&;#~!") { if s != "" && !strings.ContainsAny(s, " \t\r\n'\"$`\\*?[]{}()<>|&;#~!") {
return s return s
} }
return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'" return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
+4 -1
View File
@@ -250,7 +250,8 @@ func TestRunTakesNoOperand(t *testing.T) {
}{ }{
{[]string{"sv_SE.person"}, "echo '{/sv_SE.person}' | fejkdata"}, {[]string{"sv_SE.person"}, "echo '{/sv_SE.person}' | fejkdata"},
{[]string{"{/sv_SE.person}"}, "echo '{/sv_SE.person}' | fejkdata"}, {[]string{"{/sv_SE.person}"}, "echo '{/sv_SE.person}' | fejkdata"},
{[]string{"name: {/sv_SE.person.last}"}, "echo '{/sv_SE.person}' | fejkdata"}, {[]string{"name: {/sv_SE.person.last}"}, "echo 'name: {/sv_SE.person.last}' | fejkdata"},
{[]string{"geo.US.locality[O'Fallon].name"}, `echo '{/geo.US.locality[O'\''Fallon].name}' | fejkdata`},
{[]string{"en_US.address"}, "echo '{/en_US.address}' | fejkdata"}, {[]string{"en_US.address"}, "echo '{/en_US.address}' | fejkdata"},
{[]string{"-"}, "drop it"}, {[]string{"-"}, "drop it"},
{[]string{file}, "fejkdata < " + file}, {[]string{file}, "fejkdata < " + file},
@@ -480,6 +481,8 @@ func TestRunTemplateMisuse(t *testing.T) {
"name: {/no.such.path}": "no entry", "name: {/no.such.path}": "no entry",
"a } b": "}}", "a } b": "}}",
"42": "number", "42": "number",
"42\n": "number",
"true\n": "boolean",
"{//sv_SE.person}": "write {/sv_SE.person}", "{//sv_SE.person}": "write {/sv_SE.person}",
} { } {
code, out, errb := runOut(stdin, "--seed", "1") code, out, errb := runOut(stdin, "--seed", "1")
+26 -18
View File
@@ -78,22 +78,27 @@ folder. `IsTemplate` exports the rule, so struct tags and any other caller read
The template comes from stdin, from `echo`, a file or a heredoc, so one command line gets The template comes from stdin, from `echo`, a file or a heredoc, so one command line gets
a value and a quoted heredoc needs no escape. A format string is stdin's every byte, and a value and a quoted heredoc needs no escape. A format string is stdin's every byte, and
fejkdata adds no newline of its own: `echo` ends each render with its newline, fejkdata adds no newline of its own to text: `echo` ends each render with its newline,
`printf '%s'` sends none, and `-n` joins renders with `--separator`, empty by default. A `printf '%s'` sends none, and `-n` joins renders with `--separator`, empty by default. A
bench of the README's personas picked this over dropping a newline, or adding one, on bench of the README's personas picked this on 2026-10-07 over dropping a newline or
2026-10-07: one rule a user states in a sentence, at the cost of `printf` or a adding one: a rule a user states in one sentence, at the cost of `printf` or a
`--separator` now and then. A JSON template is its JSON: the maintainer ruled that the `--separator` now and then.
whitespace around it is not part of the template, so goal 5.7 does not refuse it on
stdin, while `NewTemplate` still refuses a padded one. A lone reference, `{/users}` or A JSON template is its JSON: the maintainer ruled the whitespace around it no part of the
`"{/users}"`, names the record `users` under `--format`, one newline after it allowed, template, so goal 5.7 does not refuse it on stdin, while `NewTemplate` still refuses a
with `users` the default `--table`; one to nothing there exits 1, as an unknown path padded one. Stdin holding only whitespace is misuse, since an unset variable sends just a
does, until `todo.md` item 129 moves the reading into the library, against goal 3.2 newline.
meanwhile. Stdin holding only whitespace is misuse, since an unset variable sends just a
newline. The CLI takes no argument but its flags: one is misuse naming the spelling that A lone reference, `{/users}` or `"{/users}"`, names the record `users` under `--format`,
reads what it likely means, `fejkdata < FILE` for a file's name, dropping it for `-`, one newline after it allowed, with `users` the default `--table`; one to nothing there
and the template piped in otherwise; so is a terminal with nothing piped in, which would exits 1. `todo.md` item 129 moves that reading into the library; until then it works
otherwise wait for typed input. `--list` still prints paths, each read as `{/path}`. against goal 3.2.
Valid while the CLI reads one template per run.
The CLI takes no argument but its flags: one is misuse naming the spelling that reads what
it likely means, `fejkdata < FILE` for a file's name, dropping it for `-`, and the template
piped in otherwise; so is a terminal with nothing piped in, which would otherwise wait for
typed input. `--list` prints paths, each read as `{/path}`. Valid while the CLI reads one
template per run.
## A template that does not compile is misuse (exit 2), including a reference that resolves to nothing, save a lone reference under the CLI's `--format` until item 129 ## A template that does not compile is misuse (exit 2), including a reference that resolves to nothing, save a lone reference under the CLI's `--format` until item 129
@@ -103,12 +108,15 @@ The whole template is the spelling under test, and `NewTemplate` compiles, links
validates as one step. Under the CLI's `--format`, a lone reference to nothing exits 1 validates as one step. Under the CLI's `--format`, a lone reference to nothing exits 1
until item 129: it reads a path, and only the data is absent. until item 129: it reads a path, and only the data is absent.
## A padded JSON template is rejected, not trimmed ## `NewTemplate` rejects a padded JSON template, and the CLI's stdin drops the whitespace around one
2026-09-03, Lilleman auf Larv. Serves goal 5.7. 2026-09-03, Lilleman auf Larv; the CLI's stdin 2026-10-07. Serves goal 5.7.
Padding is the one place the two readings disagree — a format string renders it, JSON Padding is the one place the two readings disagree — a format string renders it, JSON
drops it — so the spelling that renders is named rather than silently chosen. drops it — so `NewTemplate` names the spelling that renders rather than silently
choosing. On stdin the maintainer ruled the whitespace around JSON no part of the
template, as the decision "The CLI renders exactly the template on its stdin, and adds
nothing" records.
## `FakeTemplate` and `NewTemplate` both stay ## `FakeTemplate` and `NewTemplate` both stay
+4 -4
View File
@@ -117,7 +117,7 @@
| 42 | 0.2.0 | | **Refuse a struct tag's `datatype` naming the Go type that sets it before proving its values, as the README's Library section promises.** | 2 | 2 | 4 | 6 | 6 | 14.5 | | 42 | 0.2.0 | | **Refuse a struct tag's `datatype` naming the Go type that sets it before proving its values, as the README's Library section promises.** | 2 | 2 | 4 | 6 | 6 | 14.5 |
| 32 | 0.2.0 | | **Add `misc.browser` as the parent of `misc.useragent`, so `misc.browser[Chrome].useragent` resolves.** | 3 | 3 | 4 | 6 | 4.1 | 14.4 | | 32 | 0.2.0 | | **Add `misc.browser` as the parent of `misc.useragent`, so `misc.browser[Chrome].useragent` resolves.** | 3 | 3 | 4 | 6 | 4.1 | 14.4 |
| 27 | 0.2.0 | | **Merge `en_US.ip` and `sv_SE.ip`, today byte-identical, into one `misc.ip`.** | 3 | 2 | 4 | 6 | 5.7 | 14.1 | | 27 | 0.2.0 | | **Merge `en_US.ip` and `sv_SE.ip`, today byte-identical, into one `misc.ip`.** | 3 | 2 | 4 | 6 | 5.7 | 14.1 |
| 159 | 0.2.0 | | **Name the quoted spelling where a template that is a bare JSON number, boolean or null is refused: `42` names `"42"`.** | 1 | 2 | 3 | 6 | 6, 5.1 | 14.1 | | 159 | 0.2.0 | | **Name the quoted spelling where a template that is a bare JSON number, boolean or null is refused, padded or not: `42` names `"42"`.** | 1 | 2 | 3 | 6 | 6, 5.1 | 14.1 |
| 22 | 0.2.0 | | **Give `url` and `email` a path that draws only domains nobody can register, keeping the wide set as the default.** | 3 | 4 | 7 | 8 | 16 | 14.0 | | 22 | 0.2.0 | | **Give `url` and `email` a path that draws only domains nobody can register, keeping the wide set as the default.** | 3 | 4 | 7 | 8 | 16 | 14.0 |
| 46 | 0.2.0 | | **Report the same error every load for a table with two bad options, and for a folder with two unnamed rows files.** | 2 | 2 | 3 | 7 | 6, 10 | 14.0 | | 46 | 0.2.0 | | **Report the same error every load for a table with two bad options, and for a folder with two unnamed rows files.** | 2 | 2 | 3 | 7 | 6, 10 | 14.0 |
| 158 | 0.2.0 | | **Drop a UTF-8 byte order mark that starts stdin, and say in the README how to stop PowerShell 5.1 sending `Göteborg` as `G?teborg`.** | 2 | 2 | 4 | 5 | 7.2, 5.1 | 13.5 | | 158 | 0.2.0 | | **Drop a UTF-8 byte order mark that starts stdin, and say in the README how to stop PowerShell 5.1 sending `Göteborg` as `G?teborg`.** | 2 | 2 | 4 | 5 | 7.2, 5.1 | 13.5 |
@@ -254,8 +254,8 @@ Goal 5.9. Today a path is a second spelling of the template that reads it; after
- Text that is not a JSON value and holds no `{…}` prints as written (goal 5.1), in a string field's struct tag and `Fake` alike, as stdin's text does in the CLI: `Fake("sv_SE.person")` returns `sv_SE.person`. `CHANGELOG.md` says that a path with no `{…}` prints as its text. A struct tag's `-` still skips its field. - Text that is not a JSON value and holds no `{…}` prints as written (goal 5.1), in a string field's struct tag and `Fake` alike, as stdin's text does in the CLI: `Fake("sv_SE.person")` returns `sv_SE.person`. `CHANGELOG.md` says that a path with no `{…}` prints as its text. A struct tag's `-` still skips its field.
- Where text with no `{…}` is refused, as a record or in a typed struct field, and it spells a path the data offers, the error names `{/that.path}`. - Where text with no `{…}` is refused, as a record or in a typed struct field, and it spells a path the data offers, the error names `{/that.path}`.
- A lone reference to nothing exits 2 under `--format`, where it exits 1 today. - A lone reference to nothing exits 2 under `--format`, where it exits 1 today.
- Decide whether a lone reference under `--format` draws as its path draws today or as a template draws: under one seed, the two pick different rows. - Decide whether a lone reference under `--format` draws as its path draws today or as a template draws: under one seed, drawing `users` as a path and as the template `{/users}` picks different rows.
- This revises the decisions "A struct tag is a template by its shape", "`FakeTemplate` and `NewTemplate` both stay", "`--list` stays a plain list of paths", "The CLI renders exactly the template on its stdin, and adds nothing", and the exit-1 rule for an unknown path in "A template that does not compile is misuse (exit 2), including a reference that resolves to nothing, save a lone reference under the CLI's `--format` until item 129". The README's examples and exit codes, the godoc examples in `doc.go` and `CHANGELOG.md`'s entries move to the template spelling. Delete items 40 and 110, which this closes. - This revises the decisions "A struct tag is a template by its shape", "`FakeTemplate` and `NewTemplate` both stay", "`--list` stays a plain list of paths", "The CLI renders exactly the template on its stdin, and adds nothing", and the exit-1 rule for a lone reference to nothing in "A template that does not compile is misuse (exit 2), including a reference that resolves to nothing, save a lone reference under the CLI's `--format` until item 129". The README's examples and exit codes, the godoc examples in `doc.go` and `CHANGELOG.md`'s entries move to the template spelling. Delete items 40 and 110, which this closes.
Split it into items for the CLI, struct tags and the library before starting. Split it into items for the CLI, struct tags and the library before starting.
@@ -438,7 +438,7 @@ Require the path step to reach a sibling category.
`datatype: boolean` over `{int(1,2)}` on an `int` field answers `prints an integer, not a boolean`. `datatype: boolean` over `{int(1,2)}` on an `int` field answers `prints an integer, not a boolean`.
### 159. Name the quoted spelling where a template that is a bare JSON number, boolean or null is refused: `42` names `"42"`. ### 159. Name the quoted spelling where a template that is a bare JSON number, boolean or null is refused, padded or not: `42` names `"42"`.
On stdin `42` is refused as "a number" and `null` with advice to write `""`, which prints nothing; neither names the text the author meant. The goals audit of the stdin change found it. On stdin `42` is refused as "a number" and `null` with advice to write `""`, which prints nothing; neither names the text the author meant. The goals audit of the stdin change found it.