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.
- **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
that page: a glossary of unexported units would fill two thirds of it with names
no consumer can call, and Go doc comments have no code markup, so each one would
that page: the glossary would fill two thirds of it with the render path's units,
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
opens the file — and nothing else. Valid while the glossary names units a consumer
cannot reach; one that came to name the exported API would belong above the clause.
opens the file — and nothing else. Valid while the glossary's subject is the render
path; one written to teach the exported API belongs above the clause.
- **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
key, or prefixing options, would tax every template to guard against a
+15 -23
View File
@@ -16,31 +16,23 @@ package fejkdata
// 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
// 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.
// - draw — one pick from a choice, or one row taken from a table, and the value a
// read produced: `pick`, `drawn`, `table.draw`, `draw`.
// - expansion — one render of one format: `expand`.
// - render — what owns one `drawSet`, and so what one reference draw spans:
// `Generator.Fake`, `FakeRecord`, `FakeStruct`, `Template.Fake` and
// `RecordTemplate.Fake` each start one, as does `expandAnew` per iteration of a
// `template.repeat` — an iteration is an expansion and a render of its own.
// - 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
// `readField` reads through it; a reference path is held for the whole render.
// - draw group — `template.drawGroup`, which gives the reference paths under it
// draws of their own inside the render. `drawSet` holds the unnamed group's and
// 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` pins it and the
// rows of its ancestors, and `draws.rowOf` draws one where none is pinned.
// `Generator.Fake`, `FakeRecord`, `Template.Fake` and `RecordTemplate.Fake`
// start one each, `FakeStruct` one per record, and `expandAnew` one per
// iteration of a `template.repeat`.
// - hold — keeping one draw of a name, so every route to it reads that value:
// `template.held`, `draws`, `readField`.
// - draw group — reference draws held apart inside one render:
// `template.drawGroup` as the data spells it, `template.drawGroupKey` as a
// render reads it, `drawSet`, `drawScope`.
// - pin — fixing which row of a table the render uses: `draws.pin`, `draws.rowOf`.
// - family — a table and every table reaching it through a chain of
// `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
// 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
// disagree in, which is why a render cannot fail: `heldCheck` over an
// expansion's held names, `drawCheck` over a render's reference paths, and
// `checkFamilies` over the rows they pin. `New` runs them over the data set,
// `NewTemplate` and `FakeStruct` over what those compile.
// - fence — a load-time check, so rendering a compiled tree cannot fail: `New`
// runs them over the data set, `NewTemplate` and `FakeStruct` over what those
// compile. The draw fences are `heldCheck`, `drawCheck` and `checkFamilies`.
+11 -13
View File
@@ -10,12 +10,10 @@ import (
"testing"
)
// Every backtick in the Vocabulary is a symbol, so an unrecognised spelling fails
// rather than going unchecked.
var backticked = regexp.MustCompile("`([^`]+)`")
// Every backtick in the Vocabulary is a symbol.
var backticked = regexp.MustCompile("`([^`\n]+)`")
// TestVocabularyNamesDeclaredSymbols proves the Vocabulary names symbols this
// package declares, so a renamed unit renames its entry with it.
// TestVocabularyNamesDeclaredSymbols holds a renamed unit to its Vocabulary entry.
func TestVocabularyNamesDeclaredSymbols(t *testing.T) {
files := sourceFiles(t)
declared := declaredSymbols(files)
@@ -50,23 +48,23 @@ func sourceFiles(t *testing.T) []*ast.File {
func vocabulary(t *testing.T, files []*ast.File) string {
t.Helper()
var found strings.Builder
var sections strings.Builder
for _, f := range files {
for _, c := range f.Comments {
if section, is := strings.CutPrefix(c.Text(), "Vocabulary\n\n"); is {
found.WriteString(section)
section, found := strings.CutPrefix(c.Text(), "Vocabulary\n\n")
if found && c.Pos() > f.Package {
sections.WriteString(section)
}
}
}
if found.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")
if sections.Len() == 0 {
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
// a struct field keyed under its type: draws.pin, tableRead.whole. A name declared
// inside a function body is not one a Vocabulary entry may name.
// a struct field keyed under its type: draws.pin, tableRead.whole.
func declaredSymbols(files []*ast.File) map[string]bool {
names := map[string]bool{}
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`
hand-roll `drawSet{unnamed: draws{s: s}}` at three sites; name the lazy-map variant
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