aboutsummaryrefslogtreecommitdiff
path: root/internal/engine/engine.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 15:16:55 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 15:16:55 +0200
commit0b5d0eb92c5be2f0ddb2fa73990f31e5654e57fe (patch)
tree358e331945b8206ed4a72703e3aedfe8ea7cdcdb /internal/engine/engine.go
parent1d3f2d1e4c59867024470d3444e12698b7ebb22e (diff)
downloadkrino-0b5d0eb92c5be2f0ddb2fa73990f31e5654e57fe.tar.gz
krino-0b5d0eb92c5be2f0ddb2fa73990f31e5654e57fe.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.go58
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
}