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
4 changed files with 33 additions and 40 deletions
Showing only changes of commit e583e42dfa - Show all commits
+4 -4
View File
@@ -863,11 +863,11 @@ the Development section below, and who ships a register the four above then draw
`secrets.GITHUB_TOKEN` resolve on either host, so only the names moved. `secrets.GITHUB_TOKEN` resolve on either host, so only the names moved.
- **The vocabulary sits below `doc.go`'s package clause, not in the package doc.** - **The vocabulary sits below `doc.go`'s package clause, not in the package doc.**
Goal 1 is what a developer choosing a library reads first, and the package doc is Goal 1 is what a developer choosing a library reads first, and the package doc is
that page: a glossary of unexported units would fill two thirds of it with names that page: the glossary would fill two thirds of it with the render path's units,
no consumer can call, and Go doc comments have no code markup, so each one would mostly unexported, and Go doc comments have no code markup, so every name would
render its backticks literally. Below the clause it reaches goal 2's reader — who render its backticks literally. Below the clause it reaches goal 2's reader — who
opens the file — and nothing else. Valid while the glossary names units a consumer opens the file — and nothing else. Valid while the glossary's subject is the render
cannot reach; one that came to name the exported API would belong above the clause. path; one written to teach the exported API belongs above the clause.
- **Options and fields share one namespace.** `format`, `weight`, `repeat`, - **Options and fields share one namespace.** `format`, `weight`, `repeat`,
`separator`, `datatype` and `drawGroup` are reserved; every other key is a field. Nesting fields under a `separator`, `datatype` and `drawGroup` are reserved; every other key is a field. Nesting fields under a
key, or prefixing options, would tax every template to guard against a key, or prefixing options, would tax every template to guard against a
+15 -23
View File
@@ -16,31 +16,23 @@ package fejkdata
// Vocabulary // Vocabulary
// //
// The words the rest of the package uses, and the unit that owns each: // - draw — one pick from a choice, or one row taken from a table, and the value a
// // read produced: `pick`, `drawn`, `table.draw`, `draw`.
// - draw — one pick from a choice, or one row taken from a table, and the value // - expansion — one render of one format: `expand`.
// the pick produced: `pick` and `drawn` settle a choice, `table.draw` a row, and
// `draw` carries what a read produced.
// - expansion — one render of one format, by `expand`. A nested template is an
// expansion of its own.
// - render — what owns one `drawSet`, and so what one reference draw spans: // - render — what owns one `drawSet`, and so what one reference draw spans:
// `Generator.Fake`, `FakeRecord`, `FakeStruct`, `Template.Fake` and // `Generator.Fake`, `FakeRecord`, `Template.Fake` and `RecordTemplate.Fake`
// `RecordTemplate.Fake` each start one, as does `expandAnew` per iteration of a // start one each, `FakeStruct` one per record, and `expandAnew` one per
// `template.repeat` — an iteration is an expansion and a render of its own. // iteration of a `template.repeat`.
// - hold — keeping one draw of a name, so every route to it reads that value. // - hold — keeping one draw of a name, so every route to it reads that value:
// `template.held` lists what an expansion holds, `draws` keeps them and // `template.held`, `draws`, `readField`.
// `readField` reads through it; a reference path is held for the whole render. // - draw group — reference draws held apart inside one render:
// - draw group — `template.drawGroup`, which gives the reference paths under it // `template.drawGroup` as the data spells it, `template.drawGroupKey` as a
// draws of their own inside the render. `drawSet` holds the unnamed group's and // render reads it, `drawSet`, `drawScope`.
// each named one's, and `drawScope` says which one a template renders in. // - pin — fixing which row of a table the render uses: `draws.pin`, `draws.rowOf`.
// - pin — fixing which row of a table the render uses. `draws.pin` pins it and the
// rows of its ancestors, and `draws.rowOf` draws one where none is pinned.
// - family — a table and every table reaching it through a chain of // - family — a table and every table reaching it through a chain of
// `table.parentT`, named by the root that chain ends at: `table.family`. // `table.parentT`, named by the root that chain ends at: `table.family`.
// - whole — a read that lands on a `row`, so the row renders through its table's // - whole — a read that lands on a `row`, so the row renders through its table's
// format: `tableRead.whole` says a read did, `table.whole` is the node. // format: `tableRead.whole` says a read did, `table.whole` is the node.
// - fence — a load-time check refusing data that two routes to one draw would // - fence — a load-time check, so rendering a compiled tree cannot fail: `New`
// disagree in, which is why a render cannot fail: `heldCheck` over an // runs them over the data set, `NewTemplate` and `FakeStruct` over what those
// expansion's held names, `drawCheck` over a render's reference paths, and // compile. The draw fences are `heldCheck`, `drawCheck` and `checkFamilies`.
// `checkFamilies` over the rows they pin. `New` runs them over the data set,
// `NewTemplate` and `FakeStruct` over what those compile.
+11 -13
View File
@@ -10,12 +10,10 @@ import (
"testing" "testing"
) )
// Every backtick in the Vocabulary is a symbol, so an unrecognised spelling fails // Every backtick in the Vocabulary is a symbol.
// rather than going unchecked. var backticked = regexp.MustCompile("`([^`\n]+)`")
var backticked = regexp.MustCompile("`([^`]+)`")
// TestVocabularyNamesDeclaredSymbols proves the Vocabulary names symbols this // TestVocabularyNamesDeclaredSymbols holds a renamed unit to its Vocabulary entry.
// package declares, so a renamed unit renames its entry with it.
func TestVocabularyNamesDeclaredSymbols(t *testing.T) { func TestVocabularyNamesDeclaredSymbols(t *testing.T) {
files := sourceFiles(t) files := sourceFiles(t)
declared := declaredSymbols(files) declared := declaredSymbols(files)
@@ -50,23 +48,23 @@ func sourceFiles(t *testing.T) []*ast.File {
func vocabulary(t *testing.T, files []*ast.File) string { func vocabulary(t *testing.T, files []*ast.File) string {
t.Helper() t.Helper()
var found strings.Builder var sections strings.Builder
for _, f := range files { for _, f := range files {
for _, c := range f.Comments { for _, c := range f.Comments {
if section, is := strings.CutPrefix(c.Text(), "Vocabulary\n\n"); is { section, found := strings.CutPrefix(c.Text(), "Vocabulary\n\n")
found.WriteString(section) if found && c.Pos() > f.Package {
sections.WriteString(section)
} }
} }
} }
if found.Len() == 0 { if sections.Len() == 0 {
t.Fatal("no comment opens with a Vocabulary heading, so fence, hold, pin and the rest are defined nowhere a reader of the code meets them") t.Fatal("no comment below a package clause opens with a Vocabulary heading, so the words the package is written in are defined nowhere a reader of the code meets them")
} }
return found.String() return sections.String()
} }
// declaredSymbols is every name the package declares at the top level, a method and // declaredSymbols is every name the package declares at the top level, a method and
// a struct field keyed under its type: draws.pin, tableRead.whole. A name declared // a struct field keyed under its type: draws.pin, tableRead.whole.
// inside a function body is not one a Vocabulary entry may name.
func declaredSymbols(files []*ast.File) map[string]bool { func declaredSymbols(files []*ast.File) map[string]bool {
names := map[string]bool{} names := map[string]bool{}
for _, f := range files { for _, f := range files {
+3
View File
@@ -43,6 +43,9 @@ This round, in order:
- Spell one fresh draw set one way: `newDrawSet` exists, and `render.go` and `draw.go` - Spell one fresh draw set one way: `newDrawSet` exists, and `render.go` and `draw.go`
hand-roll `drawSet{unnamed: draws{s: s}}` at three sites; name the lazy-map variant hand-roll `drawSet{unnamed: draws{s: s}}` at three sites; name the lazy-map variant
if the difference is deliberate. if the difference is deliberate.
- Run the package doc's Go example under test, as `readme_test.go` runs the README's
JSON blocks: `doc.go` and the README both print `Järvedsvägen 43\n891 77 Järved`
for seed 42, and nothing renders either, so a draw that moves leaves both false.
### Data ### Data