Yocaml.PathSourceA path describes a path in the file system. It is only a description, which does not produce any ad-hoc verification. It is therefore unfortunately possible to describe inconsistent paths (however, the expression of inconsistent paths is captured by the YOCaml core executable).
The implementation of paths is clearly not the most optimised, it would be possible to do much more efficiently (for example, build the list in reverse or use a difference list) but we assume that this is not a catastrophic operation as file paths are generally short.
TODO: The aim of this implementation is to find an API that is easy to extend to capture the different uses in YOCaml. Once this API has stabilised, we can think about a less naive implementation.
The different types used to describe a path. These are essentially aliases for strings and lists of strings.
A fragment is an element of a path. For example, in the following path: "foo/bar/baz", fragments are : "foo", "bar" and "baz".
A path (Path.t) is just a line of fragments. Building paths that are "correct by construction" is an attractive idea, but it involves working with more complicated types. We prefer to use Effect interpretation to deal with incorrect path errors.
rel fragments build a relative path (mostly used for YOCaml rules).
append path fragments Produces a new path which adds the list of given fragments to the end of the given path.
extension path apply Filename.extension on the last fragment of the path. If there is no extension, it returns an empty string.
has_extension ext path returns true if the given path has the extension, ext, false otherwise.
one_of_extensions exts path returns true if the given path has one of the extensions in the list ext, false otherwise.
# one_of_extensions ["html"; "htm"] (rel ["baz"; "index.html"]) ;;
- : bool = trueRemove the extension of the last fragment. If the last fragment has no extension, it keep the original path.
add_extension ext path add the extension ext to the last fragment of the path. If the path or the extension is empty, it keep it without change. .ext is treated like ext.
change_extension ext path replace (or add) ext to the given path. The function follows the same scheme of add_extension. If the extension is invalid, it will returns the path with the extension removed.
move source ~into:target attempts to move the source (the source is the last fragment of the given path) to the target. For exemple:
# move ~into:(rel ["target" ; "html"]) (rel ["source"; "index.html"]) ;;
- : t = ./target/html/index.htmlOnly index.html is moved to into.
relocate source ~into:target is similar to move except that it (virtually) moves the entire path.
If two paths are of the same type (absolute or relative) and have no prefix, the source is concatenated with the target.
# relocate ~into:(rel ["foo"; "bar"]) (rel ["baz"; "index.html"]) ;;
- : t = ./foo/bar/baz/index.html
# relocate ~into:(abs ["foo"; "bar"]) (abs ["baz"; "index.html"]) ;;
- : t = /foo/bar/baz/index.htmlIf the types are different, the target's type takes precedence.
# relocate ~into:(abs ["foo"; "bar"]) (rel ["baz"; "index.html"]) ;;
- : t = /foo/bar/baz/index.html
# relocate ~into:(rel ["foo"; "bar"]) (abs ["baz"; "index.html"]) ;;
- : t = ./foo/bar/baz/index.htmlIf the types are the same and the target is a prefix of the source, then the target merges the prefixes.
# relocate ~into:(rel ["foo"; "bar"]) (rel ["foo"; "bar"; "index.html"]) ;;
- : t = ./foo/bar/index.htmlBut here, foo/bar is not a prefix of bar so the bar fragment is duplicated.
# relocate ~into:(rel ["foo"; "bar"]) (rel ["bar"; "index.html"]) ;;
- : t = ./foo/bar/bar/index.htmltrim ~prefix path trim the prefix of path (if it exists).
# trim ~prefix:(rel ["foo"; "bar"]) (rel ["foo"; "bar"; "index.html"]) ;;
- : t = ./index.html
# trim ~prefix:(rel ["foo"; "bar"]) (rel ["bar"; "index.html"]) ;;
- : t = ./bar/index.htmlPretty printers for t values.
Pretty printers for fragment values.
Comparisons between t. An absolute path will always be smaller than a relative path (for arbitrary and unhelpful reasons).
to_list path returns a path into a list of fragment (and use . for relative path and / for absolute path).
to_pair is like to_list but instead of prefixing the first fragment with . or /, it returns the kind as first element of the tuple.
Supports serialization and deserialization of paths.
from_sexp sexp try to converts a Sexp into a path.
As paths are used somewhat invasively in YOCaml to describe resources and targets, certain infix operators make it easier to manipulate them.
path ++ fragments is append path fragments (the function is left-associative allowing chain).
~/["a"; "b"] is rel ["a; b"]. A conveinent shortcut for expressing relative path.