From d5d9c2655eb44de727e2015aaa806b017ca35fda Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Fri, 18 Sep 2026 20:02:08 +0200 Subject: [PATCH] Give every table its path in one pass, name it in every message, read the layout probes through predicates, and leave the shell to the CLI --- builtins.go | 37 ++++++++++++++++++----------- cmd/fejkdata/main.go | 3 +++ data.go | 1 + family.go | 2 +- record.go | 4 ++-- table.go | 55 +++++++++++++++++++++++++++----------------- template.go | 7 ++++++ 7 files changed, 72 insertions(+), 37 deletions(-) diff --git a/builtins.go b/builtins.go index 2eb8041..61c568c 100644 --- a/builtins.go +++ b/builtins.go @@ -472,8 +472,9 @@ func iban(r rng, cc string) string { const dayLayout = "2006-01-02" -// Alike in no field; layoutDay differs from layoutProbe in its date fields only, -// layoutClock in its clock fields only. +// The instants a layout is proved against: layoutProbe2 is alike in no field, while +// layoutDay differs from layoutProbe in its date fields alone and layoutClock in its +// clock fields alone, so formatting two of them tells which kind a layout names. var ( layoutProbe = time.Date(2001, 2, 3, 4, 5, 6, 0, time.UTC) layoutProbe2 = time.Date(2010, 11, 12, 13, 14, 15, 0, time.UTC) @@ -481,6 +482,18 @@ var ( layoutClock = time.Date(2001, 2, 3, 13, 14, 15, 0, time.UTC) ) +func namesAField(layout string) bool { + return layoutProbe.Format(layout) != layoutProbe2.Format(layout) +} + +func namesADateField(layout string) bool { + return layoutProbe.Format(layout) != layoutDay.Format(layout) +} + +func namesAClockField(layout string) bool { + return layoutProbe.Format(layout) != layoutClock.Format(layout) +} + // quotedLayout reports whether an arg carries the single quotes a layout is written in. func quotedLayout(a string) bool { return len(a) >= 2 && a[0] == '\'' && a[len(a)-1] == '\'' @@ -493,10 +506,10 @@ func layoutArg(a string) (string, error) { if strings.HasPrefix(a, `"`) || strings.HasSuffix(a, `"`) { return "", fmt.Errorf("layout %s is double-quoted; write '%s'", a, bare) } - return "", fmt.Errorf("layout %s is not quoted; write '%s', which a shell keeps only inside a double-quoted argument", a, bare) + return "", fmt.Errorf("layout %s is not quoted; write '%s'", a, bare) } layout := a[1 : len(a)-1] - if layoutProbe.Format(layout) == layoutProbe2.Format(layout) { + if !namesAField(layout) { return "", fmt.Errorf("layout '%s' names no field, so it is the constant %q; write it as text", layout, layout) } return layout, nil @@ -518,15 +531,15 @@ func layoutArity(name string, n int, a []string) error { return nil } hint := "" - if len(a) > n && !split(a[n-1:]) { + if len(a) > n && !holdsQuotedLayout(a[n-1:]) { hint = fmt.Sprintf("; a layout holding a comma is quoted: '%s'", strings.Join(a[n-1:], ", ")) } return fmt.Errorf("%s takes %d argument%s, got %d%s", name, n, plural(n), len(a), hint) } -// split reports whether the surplus args already hold a quoted layout, which no -// comma split apart. -func split(a []string) bool { +// holdsQuotedLayout reports whether the surplus args already carry a quoted layout, +// which no comma split apart. +func holdsQuotedLayout(a []string) bool { for _, arg := range a { if quotedLayout(arg) { return true @@ -535,8 +548,6 @@ func split(a []string) bool { return false } -func plural(n int) string { return map[bool]string{true: "s"}[n != 1] } - func dateArgs(_ map[string]node, a []string) error { if err := layoutArity("date", 3, a); err != nil { return err @@ -556,10 +567,10 @@ func dateArgs(_ map[string]node, a []string) error { if err != nil { return err } - if layoutProbe.Format(layout) == layoutDay.Format(layout) { + if !namesADateField(layout) { return fmt.Errorf("date(from,to,layout): '%s' names no date field; write time('%s')", layout, layout) } - if from.Equal(to) && layoutProbe.Format(layout) == layoutClock.Format(layout) { + if from.Equal(to) && !namesAClockField(layout) { return fmt.Errorf("date(%s,%s,'%s') is the constant %q; write it as text", a[0], a[1], layout, from.Format(layout)) } return nil @@ -573,7 +584,7 @@ func timeArg(_ map[string]node, a []string) error { if err != nil { return err } - if layoutProbe.Format(layout) != layoutDay.Format(layout) { + if namesADateField(layout) { return fmt.Errorf("time(layout): '%s' names a date field; write date(from,to,layout)", layout) } return nil diff --git a/cmd/fejkdata/main.go b/cmd/fejkdata/main.go index dd3d0ef..88b9e69 100644 --- a/cmd/fejkdata/main.go +++ b/cmd/fejkdata/main.go @@ -28,6 +28,9 @@ const usage = `Usage: fejkdata [flags]