diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-14 15:16:55 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-14 15:16:55 +0200 |
| commit | 0b5d0eb92c5be2f0ddb2fa73990f31e5654e57fe (patch) | |
| tree | 358e331945b8206ed4a72703e3aedfe8ea7cdcdb /internal/engine/engine.go | |
| parent | 1d3f2d1e4c59867024470d3444e12698b7ebb22e (diff) | |
| download | krino-bb84b57c34f2e21fd4c5174770128c0a8fe4ceb2.tar.gz krino-bb84b57c34f2e21fd4c5174770128c0a8fe4ceb2.zip | |
krino: 0.0.5 โ keyword cache, t and d in reviewv0.0.5
Diffstat (limited to 'internal/engine/engine.go')
| -rw-r--r-- | internal/engine/engine.go | 58 |
1 files changed, 28 insertions, 30 deletions
diff --git a/internal/engine/engine.go b/internal/engine/engine.go index 8cffbd1..b50728e 100644 --- a/internal/engine/engine.go +++ b/internal/engine/engine.go @@ -8,6 +8,7 @@ package engine import ( "fmt" "os" + "sort" "strings" "time" @@ -26,6 +27,11 @@ type Engine struct { Extract *extract.Extractor Now func() time.Time // time.Now; tests replace it MainFile string + + // CacheDir holds each directory's keyword cache (spec ยง6.1), as + // NAME.cache; "" means no cache is read or written. Load leaves it + // empty: the command line sets it. + CacheDir string } // Dir is one configured directory, with its ignore matcher and rules @@ -38,13 +44,11 @@ type Dir struct { Ignore *ignore.Matcher Rules []*Rule - // ContentVariants is the distinct (IgnoreCase, Fold) pairs any of - // Rules' content tests evaluate under, in first-seen order. B2: when - // this holds exactly one variant, facts.Content releases a file's raw - // extracted text once that variant's normalised copy exists, since no - // other variant will ever be asked for; with more than one, both must - // stay memoised, as before. - ContentVariants []cond.Options + // ContentKeywords is every content keyword the directory's excludes + // and rules test, once each, sorted by Key. When a file's text is + // extracted, every one of them is answered at once, so one extraction + // serves every content test and fills the keyword cache. + ContentKeywords []cond.Keyword // Excludes are the (exclude ...) forms that apply here, compiled with the // directory's settings: krino.conf's first, then the directory's own. A @@ -135,7 +139,7 @@ func Load(mainFile string, names ...string) (*Engine, []*config.Diag) { } } } - dir.ContentVariants = contentVariants(dir.Rules, dir.Excludes, dirOpt) + dir.ContentKeywords = contentKeywords(dir.Rules, dir.Excludes) dir.DupScopes = dupScopes(dir.Rules) dirs = append(dirs, dir) } @@ -216,32 +220,26 @@ func dedupeNames(names []string) []string { return out } -// contentVariants returns the distinct (IgnoreCase, Fold) pairs any content -// test evaluates under - each exclude's (under the directory's settings, -// dirOpt) and each rule's - in first-seen order โ B2's per-Dir -// ContentVariants. A rule whose condition has no content test at all -// (Cond.UsesContent false) never calls facts.Content, so its resolved -// case/fold settings contribute no variant here. -func contentVariants(rules []*Rule, excludes []*Exclude, dirOpt cond.Options) []cond.Options { - var out []cond.Options - seen := map[cond.Options]bool{} - for _, x := range excludes { - if x.Cond.UsesContent && !seen[dirOpt] { - seen[dirOpt] = true - out = append(out, dirOpt) +// contentKeywords returns every content keyword excludes and rules test, +// each once, sorted by Key: Dir.ContentKeywords. +func contentKeywords(rules []*Rule, excludes []*Exclude) []cond.Keyword { + seen := map[string]bool{} + var out []cond.Keyword + add := func(c *cond.Cond) { + for _, k := range c.Keywords { + if !seen[k.Key()] { + seen[k.Key()] = true + out = append(out, k) + } } } + for _, x := range excludes { + add(x.Cond) + } for _, r := range rules { - if !r.Cond.UsesContent { - continue - } - opt := cond.Options{IgnoreCase: r.Settings.Case == config.CaseIgnore, Fold: r.Settings.Fold} - if seen[opt] { - continue - } - seen[opt] = true - out = append(out, opt) + add(r.Cond) } + sort.Slice(out, func(i, j int) bool { return out[i].Key() < out[j].Key() }) return out } |
