packages feed

document-build-0.2.0.0: src/Document/Build/Directories.hs

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wall #-}

{- | The directories of a build.

A 'Directories' is a product: its fields are named 'outputDirectory', 'inputDirectories' and 'fontsDirectory'.
-}
module Document.Build.Directories (
  -- * Type
  Directories (..),

  -- * Optics
  DirectoriesLike (..),
  lawNamesDirectories,
  InheritDirectories,
  inheritDirectories,
) where

import Control.DeepSeq (NFData)
import Control.Lens (Optic, cloneLens, view)
import Data.Data (Data)
import Data.Functor.Const (Const)
import Document.Build.Name.FontsDirectory (FontsDirectoryLike (..))
import Document.Build.Name.InputDirectories (InputDirectoriesLike (..))
import Document.Build.Name.OutputDirectory (OutputDirectoryLike (..))
import GHC.Generics (Generic)

{- $setup
>>> import Control.Lens (cloneLens, set, view)
-}

{- | The directories of a build: the output directory ('outputDirectory'), which
the build removes and writes to; the input directories ('inputDirectories'),
whose files the rules run on, in order; and the fonts directory
('fontsDirectory'), whose fonts LibreOffice uses during the build, if there is
one.

>>> view (cloneLens outputDirectory) (Directories "public" ["src"] Nothing)
"public"

>>> view (cloneLens fontsDirectory) (set fontsDirectory (Just "fonts") (Directories "public" ["src"] Nothing))
Just "fonts"

@since 0.1.0.0
-}
data Directories
  = Directories FilePath [FilePath] (Maybe FilePath)
  deriving stock (Eq, Ord, Show, Generic, Data)
  deriving anyclass (NFData)

{- | The class of 'Directories'.

@since 0.2.0.0
-}
class DirectoriesLike p f x x' where
  directories ::
    Optic p f x x' Directories Directories

{- | Identity

@since 0.2.0.0
-}
instance (x' ~ Directories) => DirectoriesLike p f Directories x' where
  directories =
    id
  {-# INLINE directories #-}

{- | Lens

@since 0.2.0.0
-}
instance (p ~ (->), Functor f, x' ~ Directories) => OutputDirectoryLike p f Directories x' where
  outputDirectory f (Directories x1 x2 x3) =
    fmap (\x1' -> Directories x1' x2 x3) (f x1)
  {-# INLINE outputDirectory #-}

{- | Lens

@since 0.2.0.0
-}
instance (p ~ (->), Functor f, x' ~ Directories) => InputDirectoriesLike p f Directories x' where
  inputDirectories f (Directories x1 x2 x3) =
    fmap (\x2' -> Directories x1 x2' x3) (f x2)
  {-# INLINE inputDirectories #-}

{- | Lens

@since 0.2.0.0
-}
instance (p ~ (->), Functor f, x' ~ Directories) => FontsDirectoryLike p f Directories x' where
  fontsDirectory f (Directories x1 x2 x3) =
    fmap (Directories x1 x2) (f x3)
  {-# INLINE fontsDirectory #-}

{- | Rebuild a value using only the name of each field.

Laws:

> lawNamesDirectories == id

@since 0.2.0.0
-}
lawNamesDirectories :: Directories -> Directories
lawNamesDirectories s =
  Directories
    (view (cloneLens outputDirectory) s)
    (view (cloneLens inputDirectories) s)
    (view (cloneLens fontsDirectory) s)

{- | The classes that a data type holding 'Directories' inherits.

@since 0.2.0.0
-}
type InheritDirectories s =
  ( DirectoriesLike (->) (Const ()) s s
  , OutputDirectoryLike (->) (Const ()) s s
  , InputDirectoriesLike (->) (Const ()) s s
  , FontsDirectoryLike (->) (Const ()) s s
  )

{- | Check, where it is applied, that @s@ inherits every name of 'Directories'.

@since 0.2.0.0
-}
inheritDirectories :: (InheritDirectories s) => proxy s -> ()
inheritDirectories _ =
  ()