package yocaml

  1. Overview
  2. Docs

A 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.

Types

The different types used to describe a path. These are essentially aliases for strings and lists of strings.

type fragment = string

A fragment is an element of a path. For example, in the following path: "foo/bar/baz", fragments are : "foo", "bar" and "baz".

type t

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.

Path manipulation

val rel : fragment list -> t

rel fragments build a relative path (mostly used for YOCaml rules).

val abs : fragment list -> t

abs fragments build an absolute path.

val root : t

Returns the root of the file system. root = abs [].

val pwd : t

Returns the current dir of the file system. pwd = rel [].

val append : t -> fragment list -> t

append path fragments Produces a new path which adds the list of given fragments to the end of the given path.

val extension : t -> string

extension path apply Filename.extension on the last fragment of the path. If there is no extension, it returns an empty string.

val extension_opt : t -> string option

Like extension but wrap the result in an option.

val has_extension : string -> t -> bool

has_extension ext path returns true if the given path has the extension, ext, false otherwise.

val remove_extension : t -> t

Remove the extension of the last fragment. If the last fragment has no extension, it keep the original path.

val add_extension : string -> t -> t

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.

val change_extension : string -> t -> t

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.

val basename : t -> fragment option

basename path returns the last fragment of a path.

val dirname : t -> t

dirname path returns the path without the last fragment.

val move : into:t -> t -> t

move source ~into:target attempts to move the source (the source is the last fragment of the given path) to the target. For exemple:

# open Yocaml.Path ;;
# move ~into:(rel ["target" ; "html"]) (rel ["source"; "index.html"]) ;;
- : t = ./target/html/index.html

Only index.html is moved to into.

val relocate : into:t -> t -> t

locate 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.html

If 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.html

If 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.html

But 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.html

Utils

val pp : Stdlib.Format.formatter -> t -> unit

Pretty printers for t values.

val equal : t -> t -> bool

Equality function for t values.

val pp_fragment : Stdlib.Format.formatter -> fragment -> unit

Pretty printers for fragment values.

val equal_fragment : fragment -> fragment -> bool

Equality function for fragment values.

val compare : t -> t -> int

Comparisons between t. An absolute path will always be smaller than a relative path (for arbitrary and unhelpful reasons).

val to_string : t -> string

to_string path lift a path into a string.

val to_list : t -> fragment list

to_list path returns a path into a list of fragment (and use . for relative path and / for absolute path).

val to_pair : t -> [ `Root | `Rel ] * fragment list

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.

val from_string : string -> t

from_string string try to compute a path from a string.

Serialization/Deserialization

Supports serialization and deserialization of paths.

val to_sexp : t -> Sexp.t

to_sexp path Converts a path into a Sexp.

val from_sexp : Sexp.t -> (t, Sexp.invalid) Stdlib.result

from_sexp sexp try to converts a Sexp into a path.

Infix operators

As paths are used somewhat invasively in YOCaml to describe resources and targets, certain infix operators make it easier to manipulate them.

module Infix : sig ... end
val (++) : t -> fragment list -> t

path ++ fragments is append path fragments (the function is left-associative allowing chain).

val (/) : t -> fragment -> t

path / fragment is append path [fragment].

val (~/) : fragment list -> t

~/["a"; "b"] is rel ["a; b"]. A conveinent shortcut for expressing relative path.

Map over using Path as keys

module Map : Stdlib.Map.S with type key = t
OCaml

Innovation. Community. Security.