aboutsummaryrefslogtreecommitdiff
path: root/internal/config/load.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/config/load.go')
-rw-r--r--internal/config/load.go46
1 files changed, 30 insertions, 16 deletions
diff --git a/internal/config/load.go b/internal/config/load.go
index 14ce635..c75d000 100644
--- a/internal/config/load.go
+++ b/internal/config/load.go
@@ -6,9 +6,10 @@ import (
"errors"
"fmt"
"io/fs"
+ "maps"
"os"
"path/filepath"
- "sort"
+ "slices"
"krino/internal/sexp"
"krino/internal/xdg"
@@ -21,17 +22,22 @@ type Config struct {
Dirs []*Dir
}
-// unusedOverrides reports every override LoadWith never read: text meant
-// for a file this load does not touch, which would otherwise pass as
-// checked while the file on disk was read instead (plan 13 review F4).
-func unusedOverrides(over map[string][]byte, used map[string]bool, mainFile string) []*Diag {
+// unusedOverrides reports text for a file no part of this configuration
+// names: it would otherwise pass as checked while the file on disk was read
+// instead (plan 13 review F4). Text for an included directory this call did
+// not load - an editor holding buffers for several while checking one - is
+// not reported.
+func unusedOverrides(over map[string][]byte, used map[string]bool, mainFile string, include []string) []*Diag {
+ known := map[string]bool{filepath.Clean(mainFile): true}
+ for _, name := range include {
+ known[filepath.Clean(DirFile(mainFile, name))] = true
+ }
var out []*Diag
- for file := range over {
- if !used[file] {
+ for _, file := range slices.Sorted(maps.Keys(over)) {
+ if !used[file] && !known[file] {
out = append(out, &Diag{File: mainFile, Msg: fmt.Sprintf("unsaved text for %s, which this configuration does not read", file)})
}
}
- sort.Slice(out, func(i, j int) bool { return out[i].Msg < out[j].Msg })
return out
}
@@ -48,16 +54,23 @@ func readSource(overrides map[string][]byte, used map[string]bool, file string)
}
// cleanOverrides keys the caller's overrides by cleaned path, so a file
-// named with a "." or ".." segment is still recognised as itself.
-func cleanOverrides(overrides map[string][]byte) map[string][]byte {
+// named with a "." or ".." segment is still recognised as itself. Two keys
+// that name one file are refused rather than resolved by map order.
+func cleanOverrides(overrides map[string][]byte) (map[string][]byte, []*Diag) {
if len(overrides) == 0 {
- return nil
+ return nil, nil
}
out := make(map[string][]byte, len(overrides))
- for file, src := range overrides {
- out[filepath.Clean(file)] = src
+ var errs []*Diag
+ for _, file := range slices.Sorted(maps.Keys(overrides)) {
+ key := filepath.Clean(file)
+ if _, seen := out[key]; seen {
+ errs = append(errs, &Diag{File: key, Msg: "unsaved text given twice for this file"})
+ continue
+ }
+ out[key] = overrides[file]
}
- return out
+ return out, errs
}
// DefaultFile is krino.conf in the XDG config directory.
@@ -83,7 +96,7 @@ func Load(mainFile string, names ...string) (*Config, []*Diag) {
// checked exactly as a run would read it (GUI design ยง1.3). A nil map is
// Load.
func LoadWith(mainFile string, overrides map[string][]byte, names ...string) (*Config, []*Diag) {
- over := cleanOverrides(overrides)
+ over, collisions := cleanOverrides(overrides)
used := map[string]bool{}
src, err := readSource(over, used, mainFile)
if errors.Is(err, fs.ErrNotExist) {
@@ -126,7 +139,8 @@ func LoadWith(mainFile string, overrides map[string][]byte, names ...string) (*C
errs = append(errs, derrs...)
cfg.Dirs = append(cfg.Dirs, dir)
}
- return cfg, append(errs, unusedOverrides(over, used, mainFile)...)
+ errs = append(errs, collisions...)
+ return cfg, append(errs, unusedOverrides(over, used, mainFile, m.Include)...)
}
// Resolved is the settings that apply in dir: built-in, then the main