Answer prose round 2 in the docs: weights take 0, the node table states the record-column refusal once, the time refusal joins its list, CHANGELOG lists what now loads, decision titles state their whole ruling, and the JSON-string ruling folds into the struct-tag decision
This commit is contained in:
@@ -43,8 +43,7 @@ In [docs/decisions.md](docs/decisions.md):
|
||||
- The CLI renders exactly the template on its stdin, and adds nothing
|
||||
- The CLI reads only the library's public API
|
||||
- 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
|
||||
- Whitespace around a JSON template is dropped, in `NewTemplate` and on stdin
|
||||
- A JSON string stays a template even where its bare text renders alike
|
||||
- Whitespace around a JSON object, array, string or null is dropped, and a bare number or boolean is a format string
|
||||
- `FakeTemplate` and `NewTemplate` both stay
|
||||
- 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`
|
||||
|
||||
+13
-2
@@ -22,7 +22,8 @@ replacement, and each removed path, column or flag.
|
||||
`{/misc.territory as t}` binds one row of `misc.territory` to `t` and prints nothing;
|
||||
`{t}`, `{t.capital}` and `{lowercase(t.name)}` read that one row. `{x as n}` binds a
|
||||
reference, a sibling field or a path into one; a name lives in the category binding it,
|
||||
and picks again on every iteration of a `repeat` binding it. A struct's tags share its
|
||||
and picks again on every iteration of a `repeat`, or every draw of a choice item,
|
||||
binding it. A struct's tags share its
|
||||
names, `{/sv_SE.person as p}{p.first}` beside `{p.sex}`. A name is a `{calc()}`
|
||||
operand: `{/misc.coordinate.lat as lat}{calc(lat * 60)}`. What `New` refuses is listed
|
||||
under [Names](README.md#names).
|
||||
@@ -32,7 +33,17 @@ replacement, and each removed path, column or flag.
|
||||
defaults to empty. Whitespace around a JSON object, array or string template is
|
||||
dropped, and a bare number or boolean is a format string, printed as written. A lone reference,
|
||||
`{/users}`, is the record `users` under `--format`. An argument other than a flag, or
|
||||
nothing piped in, exits 2; an empty or blank stdin is a template, and renders as it is.
|
||||
nothing piped in, exits 2; an empty or blank stdin is a format string, and renders as
|
||||
sent.
|
||||
- A template or data file loads whatever is well-formed and means one thing, even where
|
||||
part of it does nothing: a default written out, a one-item choice, an object holding only
|
||||
a format, a constant sample such as `{int(5,5)}`, a `weight`, `separator` or `datatype`
|
||||
where it does nothing, a name nothing reads, a repeated item, which counts as written, a
|
||||
weight of `0`, which is never drawn, a `repeat` or count of `0`, which renders nothing,
|
||||
`+5`, `05` and `-0`, and a reference into the category it sits in. A rows file no
|
||||
category names is ignored. `New` with no data loads, and renders templates that read
|
||||
none. The CLI's `-n` takes `0`; `--list` ignores `--repeat`, `--format` and `--table`,
|
||||
and `--table` is ignored without `--format sql`.
|
||||
- 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,
|
||||
`misc.territory[SE]`, and descends to a linked table by name, one path drawing each
|
||||
|
||||
@@ -41,8 +41,8 @@ Under `--format text`, the default, what you send is what renders, and fejkdata
|
||||
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 object, array
|
||||
or string drops the whitespace around it, and `null` alone renders nothing; `42` or `true`
|
||||
alone is a format string, so it prints as written, newline included. An empty or blank stdin is a template too, and
|
||||
renders as it is. A JSON template that should end
|
||||
alone is a format string, so it prints as written, newline included. An empty or blank stdin is a format string like
|
||||
any other, and renders as sent. 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
|
||||
newline after it allowed. Some shells' `echo` reads a backslash as an escape, so pipe a
|
||||
@@ -120,7 +120,7 @@ echo '{/users}' | fejkdata --seed 1 -d ./mydata --format sql --table people # IN
|
||||
|
||||
`--repeat` streams that many records — `json` frames them as one array document,
|
||||
`ndjson` writes one object per line, `csv` a row after a header, `sql` one INSERT
|
||||
per line. Only a category-level template is a record, or a one-item choice of one; a
|
||||
per line. Only a category-level template is a record, or a one-item choice holding one; a
|
||||
field, a choice of more items or a folder errors, and so does a `repeat` on
|
||||
the template itself, which composes the format into one string rather than
|
||||
projecting columns — ask for more records with `--repeat`. A `repeat` on a column
|
||||
@@ -329,7 +329,7 @@ ok, err := fejkdata.IsTemplate(arg) // an inline template by its shape, el
|
||||
| `WithoutShippedData()` | load only what you give |
|
||||
|
||||
`New` refuses data that breaks the grammar, could mean two things or cannot render a valid
|
||||
value, and `NewTemplate` such a template. On a loaded generator:
|
||||
value, and `NewTemplate` refuses such a template. On a loaded generator:
|
||||
|
||||
- `Fake` fails only for a path that names nothing, could name two things, or reads one
|
||||
draw of a level carrying a `repeat`, with the same error every call.
|
||||
@@ -388,8 +388,12 @@ Every value is a **node**, nestable without limit:
|
||||
| choice | `["a", "b", …]` | one item, picked at random |
|
||||
| template | `{"format": "…", …}` | its format, with `{name}` tokens rendering the named fields |
|
||||
| table | `{"format": "…", "rows": "x.tsv", …}` | its format over one row of the TSV beside it ([Table](#table)) |
|
||||
| number | `5`, `1.50` | its text as written; refused in a record column, where it could be text, `"5"`, or a typed value, `{"format": "5", "datatype": "integer"}`, bar a struct tag's, which its field's Go type types |
|
||||
| boolean | `true` | its text; refused in a record column, where it could be text, `"true"`, or a typed value, `{"format": "true", "datatype": "boolean"}`, bar a struct tag's, which its field's Go type types |
|
||||
| number | `5`, `1.50` | its text as written |
|
||||
| boolean | `true` | its text as written |
|
||||
|
||||
In a record column a bare number or boolean is refused, since it could be the text `"5"`
|
||||
or the typed value `{"format": "5", "datatype": "integer"}`. In a struct tag, the
|
||||
field's Go type decides.
|
||||
|
||||
### Format string
|
||||
|
||||
@@ -433,8 +437,8 @@ Renders `070-412 38 91` ten times as often as `08-…`. A string item is weighte
|
||||
writing it as `{ "format": "AB", "weight": 3 }`. A repeated item counts as written,
|
||||
so `["a", "a", "b"]` draws `a` two times in three, and an item of weight `0` is never
|
||||
drawn. A weight outside a choice does nothing, and so does one above `0` on the item of
|
||||
a one-item choice. Rejected at load: a weight that is negative or not a number, and a
|
||||
choice whose every weight is `0`, a one-item choice of weight `0` among them.
|
||||
a one-item choice. Rejected at load: a weight that is negative, not a number, or too
|
||||
close to `0` to tell from it, such as `1e-400`, and a choice whose every weight is `0`, a one-item choice of weight `0` among them.
|
||||
|
||||
### Repeat
|
||||
|
||||
@@ -531,8 +535,8 @@ echo '{/country}' | fejkdata -d ./mydata --format csv # alpha2,name,populati
|
||||
```
|
||||
|
||||
`rows` names the TSV beside the category file; `key` names the column a path
|
||||
selects a row by, `name` a column it also selects by, `weight` a column of positive
|
||||
numbers that skews the draw, and `parent` the table a column links to
|
||||
selects a row by, `name` a column it also selects by, `weight` a column of numbers
|
||||
of 0 or more that skews the draw, and `parent` the table a column links to
|
||||
([Linked tables](#linked-tables)). The format's `{tokens}` read the columns, and the
|
||||
columns are the [record](#records)'s columns, so `--format csv` writes the rows and
|
||||
`--list` shows `country.alpha2`. A cell is a string node: `1{digits(2)} {digits(2)}`
|
||||
@@ -540,8 +544,8 @@ in a cell draws digits and `{/misc.uuid}` reads a reference, while `{name}` in a
|
||||
is refused, since a cell has no sibling. Each cell may select its own row of another
|
||||
table, `{/misc.currency[SEK].symbol}` on one row and `{/misc.currency[EUR].symbol}`
|
||||
on the next, since only one row renders. `New` proves the header, the options and every
|
||||
cell token, and refuses a key that is empty or repeats, a weight that is negative or not
|
||||
a number, every weight `0` across the table or inside one parent row, and a key or name holding `[`, `]`, `{`, `}`,
|
||||
cell token, and refuses a key that is empty or repeats, a weight that is negative, not
|
||||
a number or too close to `0` to tell from it, every weight `0` across the table or inside one parent row, and a key or name holding `[`, `]`, `{`, `}`,
|
||||
`"` or `|`, which a selector cannot spell; `New` maps the keys, and a name or parent column
|
||||
is mapped on the first draw that selects by name or descends through the table. A `name` needs a `key`, since a name naming several rows is reported by
|
||||
their keys, or a `parent`, inside whose row a name names one row, so `first-name[Kim]`
|
||||
@@ -679,10 +683,10 @@ layout prints `UTC` or `Z`.
|
||||
The quotes delimit a layout outside a selector only, so `[O'Fallon]` in an
|
||||
argument stays a name. A layout naming no field prints itself, `date` with a clock-only
|
||||
layout prints the drawn instant's clock, and `date` over one day with no clock field prints
|
||||
that day; `time` with a layout naming a date field is refused, naming `date`, since `time`
|
||||
draws no date.
|
||||
Rejected at `New`: a bound that is no calendar date, or after the other, and an unquoted
|
||||
or double-quoted layout, naming the single-quoted one. `{seq()}` spans `Fake`
|
||||
that day.
|
||||
Rejected at `New`: a bound that is no calendar date, or after the other; an unquoted
|
||||
or double-quoted layout, naming the single-quoted one; and `time` with a layout naming a
|
||||
date field, naming `date`, since `time` draws no date. `{seq()}` spans `Fake`
|
||||
calls and `repeat`, resets with a new generator, and is the natural primary key for
|
||||
the SQL example above.
|
||||
|
||||
@@ -743,8 +747,7 @@ so `{.person.first} {.person.last}` may name two people. Bind the person to a [n
|
||||
{p.last}`. Rejected at `New`: a path that is
|
||||
unknown, names a folder, has no folder above, reads a field not every variant
|
||||
of a choice carries, and a reference that leads back to its own value, directly,
|
||||
mutually or through a chain. A reference into the category it sits in is a fresh draw
|
||||
like any other.
|
||||
mutually or through a chain.
|
||||
|
||||
### Names
|
||||
|
||||
@@ -781,8 +784,8 @@ Refused at `New`, each error naming what to write instead:
|
||||
- a binding of anything but a reference, or a field of the template binding it or a path into
|
||||
one;
|
||||
- a read of a name inside the field bound to it: read it outside that field;
|
||||
- a read outside a choice's item of a name bound inside it, which every other item would
|
||||
leave unbound;
|
||||
- reading a name outside the choice item that binds it, since the other items leave it
|
||||
unbound;
|
||||
- a path through a name that selects a row;
|
||||
- `{n}` beside `{n.w}` where `n`'s category reads `w` twice, as in `{w}-{w}` or
|
||||
`{w.a} {w.b}`;
|
||||
|
||||
+14
-24
@@ -65,7 +65,9 @@ can never collide with any of those spellings, and the leading `[` or `"` is gat
|
||||
valid JSON so a stray copied bracket never swallows a tag — it names nothing, and says
|
||||
so. Reserving the characters whole — though only a leading one
|
||||
could collide — keeps one simple name rule instead of a leading-position special case.
|
||||
A folder-relative `{.name}` or `{..name}` is refused naming
|
||||
A JSON string stays a template even where its bare text renders alike, `"x {/a}"` beside
|
||||
`x {/a}`: inside the quotes `\t` and `\n` write a tab or a newline on one line. A
|
||||
folder-relative `{.name}` or `{..name}` is refused naming
|
||||
`{/name}`, since an inline template sits in no folder. `IsTemplate` exports the rule, so
|
||||
struct tags and any other caller read one.
|
||||
|
||||
@@ -81,9 +83,7 @@ bench of the README's personas picked this on 2026-10-07 over dropping a newline
|
||||
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, so the whitespace around it is no part of the template, per
|
||||
the decision "Whitespace around a JSON template is dropped, in `NewTemplate` and on
|
||||
stdin". Stdin holding only whitespace is a template like any other, and renders it.
|
||||
Stdin holding only whitespace is a format string, and renders as sent.
|
||||
|
||||
A lone reference, `{/users}` or `"{/users}"`, names the record `users` under `--format`,
|
||||
one newline after it allowed, with `users` the default `--table`; one to nothing there
|
||||
@@ -100,9 +100,9 @@ template per run.
|
||||
|
||||
2026-10-07, Lilleman auf Larv. Serves goal 9.6: a CLI carrying your own modules is a few
|
||||
lines of Go and works just like `fejkdata`, so `fejkdata`'s own CLI is such a CLI and
|
||||
imports nothing under `internal/`. It copies one reading the API does not export yet,
|
||||
the lone reference: `isPath`, `hasEmptySegment` and `withoutSelectors` in `cmd/fejkdata`, pinned to the
|
||||
grammar by a test, until `todo.md` item 129 moves that reading into the library.
|
||||
its non-test code imports nothing under `internal/`. Until `todo.md` item 129 moves it into
|
||||
the library, the CLI copies how the grammar tells a lone reference, in `isPath`,
|
||||
`hasEmptySegment` and `withoutSelectors`, and a test pins the copy to the grammar.
|
||||
|
||||
## 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
|
||||
|
||||
@@ -112,7 +112,7 @@ 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
|
||||
until item 129: it reads a path, and only the data is absent.
|
||||
|
||||
## Whitespace around a JSON template is dropped, in `NewTemplate` and on stdin
|
||||
## Whitespace around a JSON object, array, string or null is dropped, and a bare number or boolean is a format string
|
||||
|
||||
2026-10-07, Lilleman auf Larv. Applies KISS.
|
||||
|
||||
@@ -122,15 +122,6 @@ is dropped, as `encoding/json` drops it. `null` stays JSON, since it is how a te
|
||||
renders nothing. A bare number or boolean gains nothing from the JSON reading, so it is a
|
||||
format string, and `echo 42` prints its newline as `echo x` does (goal 5.1).
|
||||
|
||||
## A JSON string stays a template even where its bare text renders alike
|
||||
|
||||
2026-10-07, Lilleman auf Larv. Serves goal 5.7: whatever is well-formed and means one thing
|
||||
loads.
|
||||
|
||||
`"x {/a}"` and `x {/a}` render alike on stdin, in `NewTemplate` and in a struct tag. The
|
||||
quotes are no mistake: inside them `\t` and `\n` write a tab or a newline where the
|
||||
template is one line of a Go string, a struct tag or a file.
|
||||
|
||||
## `FakeTemplate` and `NewTemplate` both stay
|
||||
|
||||
2026-09-03, Lilleman auf Larv.
|
||||
@@ -345,16 +336,14 @@ handle is needed, as the cache already compiles once.
|
||||
2026-09-16, Lilleman auf Larv; revised 2026-10-07. Serves goals 5.2 and 5.7.
|
||||
|
||||
A reference back into a category, `{/users.first}` inside `users`, is a fresh draw, as
|
||||
every `{…}` is; only a cycle is refused. A value two fields share goes in its own
|
||||
category, which one field binds to a name and both read (goal 4.1). A record's column
|
||||
fences run at `New` too, so a category that loads renders as a value and as a record alike.
|
||||
every `{…}` is; only a cycle is refused. A record's column fences run at `New` too, so a category that loads renders as a value and as a record alike.
|
||||
|
||||
## A record's column set is fixed before the first draw
|
||||
|
||||
2026-09-04, Lilleman auf Larv.
|
||||
|
||||
Only a category-level template is a record: a path descending into a field, or naming a
|
||||
folder or a choice, errors. A tail may pass through a choice whose variants carry
|
||||
folder or a choice of more than one item, errors. A tail may pass through a choice whose variants carry
|
||||
different fields, so the columns — and with them the CSV header written once ahead of
|
||||
every row — would vary per draw. A fixed column set is what the CSV and `INSERT`
|
||||
contracts rest on, so the restriction holds even where a particular choice would happen
|
||||
@@ -631,8 +620,9 @@ Table section teaches it.
|
||||
2026-09-18, Lilleman auf Larv. Serves goal 5.6.
|
||||
|
||||
A layout may carry the comma that separates arguments,
|
||||
`'January 2, 2006'`, a bare `2006-01-02` reads like a third date, and a double-quoted one
|
||||
could be quotes printed in the output, so each is refused naming the single-quoted one. The layout is Go's reference time because the
|
||||
`'January 2, 2006'`. A bare `2006-01-02` reads like a third date, and a double-quoted
|
||||
layout could be quotes printed in the output, so both are refused, naming the
|
||||
single-quoted spelling. The layout is Go's reference time because the
|
||||
library renders with it and a Go caller already knows it; its names are English, and a
|
||||
locale's own month and weekday names are data.
|
||||
|
||||
@@ -855,7 +845,7 @@ Valid while names are read only inside the category binding them.
|
||||
|
||||
2026-10-04, Lilleman auf Larv. Serves goal 3 and applies KISS.
|
||||
|
||||
Shipped under the floor by the maintainer's decisions of 2026-10-07: the CLI reading its template from stdin, with the scoring run and its ratchet waived for that chunk; and goal 5.7 loading whatever is well-formed and means one thing, dropping every refusal that guessed at a mistake, with the scoring run and its ratchet waived for that chunk too.
|
||||
Shipped under the floor by the maintainer's decisions of 2026-10-07, each with the scoring run and its ratchet waived: the CLI reading its template from stdin; and goal 5.7 loading whatever is well-formed and means one thing, dropping every refusal that guessed at a mistake.
|
||||
|
||||
Last scoring run, 2026-10-07, on commit ad59967: Navigation 7.00, Locality 5.88, Shape 6.50, Self-sufficiency 6.13, overall 6.38. The nine-seat panel at depth 1, run beside it: Navigation 7.17, Locality 6.06, Shape 6.67, Self-sufficiency 6.56, overall 6.56. Against the runs on ac6158e, the scoring run's overall rose from 6.25 and its Shape from 6.38, while its Self-sufficiency fell from 6.38; the panel's overall held, and its Locality and Self-sufficiency fell by 0.05 each. Locality is lowest again, as at every panel since 2026-09-22. All 13 seats named the named-pick read path hardest: `readField`, `readName`, `readUnder` and `keeps`, with the pick keys `levelKeys` and `addressedKeys` build at load; twelve kept `doc.go`'s vocabulary open beside it. What the two runs found is filed in `todo.md`, and `todo.md` item 153 runs both again. Valid while `AGENTS.md` gates goal 3 at 7.0.
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
| 50 | 0.2.0 | | **Reword `prove`'s refusal of a typed column reading a row, `{/region}`.** | 1 | 2 | 4 | 6 | 6 | 15.5 |
|
||||
| 17 | 0.2.0 | | **Give every shipped category a column for each part its format composes, and one record shape across the national ids; re-pin the shape.** | 5 | 6 | 6 | 6 | 5 | 15.1 |
|
||||
| 29 | 0.2.0 | | **Let a path go from a selected row into the template beside its family: `geo.US.locality[1714000].address`.** | 4 | 4 | 5 | 6 | 5 | 14.6 |
|
||||
| 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` other than its Go type's 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 |
|
||||
| 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.** | 2 | 2 | 3 | 7 | 6, 10 | 14.0 |
|
||||
@@ -435,7 +435,7 @@ Say the format is the table's own (`region's format "{name}"`), name the read to
|
||||
|
||||
Require the path step to reach a sibling category.
|
||||
|
||||
### 42. Refuse a struct tag's `datatype` naming the Go type that sets it before proving its values, as the README's Library section promises.
|
||||
### 42. Refuse a struct tag's `datatype` other than its Go type's before proving its values, as the README's Library section promises.
|
||||
|
||||
`datatype: boolean` over `{int(1,2)}` on an `int` field answers `prints an integer, not a boolean`.
|
||||
|
||||
@@ -503,7 +503,7 @@ Today a cell reads `g.t.b, line 3` (`namedNode.labelIn`), a cell check `t.tsv: l
|
||||
|
||||
### 14. Spell `misc.creditcard`'s digit runs `{digits(n)}`.
|
||||
|
||||
A `"repeat": 14` over `{digits(1)}` draws every 14-digit run with the odds `{digits(14)}` does. Both load; the shipped data writes the shorter one. Re-pin seeded output in its own commit.
|
||||
A `"repeat": 14` over `{digits(1)}` draws every 14-digit run with the odds `{digits(14)}` does. Both load; make the shipped data write the shorter one. Re-pin seeded output in its own commit.
|
||||
|
||||
### 11. Test that every `geo` tree holds the five table names and the `address` columns that port across countries.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user