66 lines
1.5 KiB
Go
66 lines
1.5 KiB
Go
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
|
|
|
package folio
|
|
|
|
import (
|
|
"decl/internal/ext"
|
|
"decl/internal/ds"
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
"path/filepath"
|
|
"decl/internal/data"
|
|
)
|
|
|
|
var (
|
|
ErrSearchPathNotExist error = errors.New("Search path does not exist.")
|
|
)
|
|
|
|
// A search path should find a file in list of paths
|
|
|
|
type SearchPath struct {
|
|
paths *ds.OrderedSet[string]
|
|
}
|
|
|
|
func NewSearchPath(paths []string) (s *SearchPath) {
|
|
s = &SearchPath{ paths: ds.NewOrderedSet[string]() }
|
|
s.paths.AddItems(paths)
|
|
return
|
|
}
|
|
|
|
func (s *SearchPath) AddPath(path string) error {
|
|
if newPath := ext.FilePath(path).Abs(); newPath.Exists() {
|
|
s.paths.Add(string(newPath))
|
|
} else {
|
|
return fmt.Errorf("%w: %s", ErrSearchPathNotExist, path)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *SearchPath) Find(relative string) string {
|
|
pathValues := s.paths.Items()
|
|
for i := len(pathValues) - 1; i >= 0; i-- {
|
|
p := *pathValues[i]
|
|
searchPath := ext.FilePath(p)
|
|
searchPath.Add(relative)
|
|
slog.Info("SearchPath.Find()", "searchpath", p, "file", relative, "target", searchPath)
|
|
if searchPath.Exists() {
|
|
return string(searchPath)
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (s *SearchPath) FindParsedURI(uri data.URIParser) (result URI) {
|
|
u := uri.URL()
|
|
filePath := filepath.Join(u.Hostname(), u.Path)
|
|
if absPath := s.Find(filePath); absPath != "" {
|
|
result = URI(fmt.Sprintf("%s://%s", u.Scheme, string(absPath)))
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *SearchPath) FindURI(uri URI) (result URI) {
|
|
return s.FindParsedURI(uri.Parse())
|
|
}
|