jx/internal/folio/searchpath.go

66 lines
1.5 KiB
Go
Raw Normal View History

// 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())
}