packages feed

filepather-0.7.0.0: README.md

# filepather

![System F Logo](https://logo.systemf.com.au/systemf-450x450.png)

Computations that depend on a file path, and named build steps that record
the files they make.

## `FilePather`

```haskell
newtype FilePather f a = FilePather (FilePath -> f a)
type FilePather' a = FilePather Identity a
```

A `FilePather` is isomorphic to `ReaderT FilePath f a`, with the same
instances, and `ask` is the file path being operated on.
`System.FilePather.Combinators` builds larger `FilePather` values from
smaller ones:

* `p ~> q` runs `q` on the file path that `p` produces, and `p ~>> q` runs `q`
  on each of the file paths that `p` produces.
* `onFile` runs on another file path, and `hoistFilePather` changes `f`.
* A `Rule f a` is a `FilePather` that applies to some file paths and not
  others. Make one with `rule predicate x`, and combine rules with `<|>`,
  where the first rule that applies is used.
* `everyFile directoryFiles r` applies the rule `r` to every file in the
  directory being operated on.

## `Tracked`

```haskell
newtype Tracked f a = Tracked (FilePather (ReaderT Trail (ExceptT Cycle f)) (Outputs, a))
type Outputs = [(FilePath, Step)]
```

A `Tracked` value is a build step, or several, run on a file path with the
`Trail` of that file: the `Step`s that built it, nearest first, back to its
source file. It produces its result and the files it made, each with the step
that made it.

* `step name outputs x` names the `FilePather` `x`, which makes the files
  `outputs` gives for its input. Before `x` runs, the step is checked against
  the trail: a step whose name is already in the trail (`RepeatsStep`), or
  that would make a file already in the trail (`ReproducesInput`), is
  stopped with a `Cycle`, and `x` does not run.
* `step' name x` names a `FilePather` that returns the files it made, for a
  step whose outputs are known only after it runs. It is checked after it
  runs.
* `stepWith Repeatable` allows a step to appear more than once in a trail.
* `whenPath`, `whenTrail`, `onPath`, `askTrail` and `untracked` choose
  files, and run `FilePather` values that make no files.
* `displayCycle` describes the chain of a `Cycle`:

```
src/a.md → markdown to pdf → public/a.pdf → pdf page 1 → public/a_page1.pdf → pdf page 1 again
```

`Tracked` is separate from `FilePather`, so that `FilePather` keeps all of its
instances (`Distributive`, `Representable`, `Selective`, `Decidable`, and the
`MonadError` and `MonadWriter` of `f`). `Tracked` has `Functor`, `Apply`,
`Applicative`, `Bind`, `Monad`, `Selective`, `Alt`, `Plus`, `Alternative`,
`MonadPlus`, `Semigroup`, `Monoid`, `Filterable`, `MonadTrans`, `MonadIO`,
`MonadFail`, `MonadReader FilePath`, `MonadState`, `MonadError`,
`MonadWriter` and `Contravariant` instances. `<>` runs both steps and keeps
the outputs of both; `<|>` and `catchError` alternate in `f`; and a `Cycle`
is never caught or discarded by any of them.

## Development

This package is built and tested with
[document-build](https://gitlab.com/tonymorris/document-build), which
uses it:

```
cabal build all
cabal test all
bin/lint.sh --check
```