Move how the template language is written into internal/grammar
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package grammar
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A reference names a node by path rather than as a sibling field: {/a.b} from the
|
||||
// data root, {.a} from the folder this file sits in, {..a} from the folder above.
|
||||
func IsRef(name string) bool { return strings.HasPrefix(name, ".") || strings.HasPrefix(name, "/") }
|
||||
|
||||
// RefShape splits a reference into its sigil and the dotted path after it.
|
||||
func RefShape(name string) (sigil, rest string, err error) {
|
||||
switch {
|
||||
case strings.HasPrefix(name, "/"):
|
||||
sigil, rest = "/", name[1:]
|
||||
case strings.HasPrefix(name, ".."):
|
||||
sigil, rest = "..", name[2:]
|
||||
default:
|
||||
sigil, rest = ".", name[1:]
|
||||
}
|
||||
if rest == "" {
|
||||
return "", "", fmt.Errorf("reference has no path")
|
||||
}
|
||||
if strings.HasPrefix(rest, "/") {
|
||||
return "", "", fmt.Errorf("the path after %s starts at a name, not a /; write {%s%s}", sigil, sigil, rest[1:])
|
||||
}
|
||||
if strings.HasPrefix(rest, ".") {
|
||||
return "", "", fmt.Errorf("a reference starts with / (the root), . (this folder) or .. (the folder above)")
|
||||
}
|
||||
segs, err := SplitPath(rest)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
for _, seg := range segs {
|
||||
if seg == "" {
|
||||
return "", "", fmt.Errorf("path has an empty segment")
|
||||
}
|
||||
}
|
||||
return sigil, rest, nil
|
||||
}
|
||||
Reference in New Issue
Block a user