    --------------------------------------------------------------------------------
    -- | An identifier is a type used to uniquely identify an item. An identifier is
    -- conceptually similar to a file path. Examples of identifiers are:
    --
    -- * @posts/foo.markdown@
    --
    -- * @index@
    --
    -- * @error/404@
    {-# LANGUAGE DeriveDataTypeable         #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    module Hakyll.Core.Identifier
        ( Identifier
        , fromFilePath
        , toFilePath
        , identifierVersion
        , setVersion
        ) where

    --------------------------------------------------------------------------------
    import           Control.DeepSeq     (NFData (..))
    import           Data.List           (intercalate)
    import           System.FilePath     (dropTrailingPathSeparator, splitPath,
                                          pathSeparator, normalise)

    --------------------------------------------------------------------------------
    import           Data.Binary         (Binary (..))
    import           Data.Typeable       (Typeable)
    import           GHC.Exts            (IsString, fromString)

    --------------------------------------------------------------------------------
    data Identifier = Identifier
        { Identifier -> Maybe String
    identifierVersion :: Maybe String
        , Identifier -> String
    identifierPath    :: String
        } deriving (Identifier -> Identifier -> Bool
    (Identifier -> Identifier -> Bool)
    -> (Identifier -> Identifier -> Bool) -> Eq Identifier
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Identifier -> Identifier -> Bool
    $c/= :: Identifier -> Identifier -> Bool
    == :: Identifier -> Identifier -> Bool
    $c== :: Identifier -> Identifier -> Bool
    Eq, Eq Identifier
    Eq Identifier =>
    (Identifier -> Identifier -> Ordering)
    -> (Identifier -> Identifier -> Bool)
    -> (Identifier -> Identifier -> Bool)
    -> (Identifier -> Identifier -> Bool)
    -> (Identifier -> Identifier -> Bool)
    -> (Identifier -> Identifier -> Identifier)
    -> (Identifier -> Identifier -> Identifier)
    -> Ord Identifier
    Identifier -> Identifier -> Bool
    Identifier -> Identifier -> Ordering
    Identifier -> Identifier -> Identifier
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    min :: Identifier -> Identifier -> Identifier
    $cmin :: Identifier -> Identifier -> Identifier
    max :: Identifier -> Identifier -> Identifier
    $cmax :: Identifier -> Identifier -> Identifier
    >= :: Identifier -> Identifier -> Bool
    $c>= :: Identifier -> Identifier -> Bool
    > :: Identifier -> Identifier -> Bool
    $c> :: Identifier -> Identifier -> Bool
    <= :: Identifier -> Identifier -> Bool
    $c<= :: Identifier -> Identifier -> Bool
    < :: Identifier -> Identifier -> Bool
    $c< :: Identifier -> Identifier -> Bool
    compare :: Identifier -> Identifier -> Ordering
    $ccompare :: Identifier -> Identifier -> Ordering
    $cp1Ord :: Eq Identifier
    Ord, Typeable)

    --------------------------------------------------------------------------------
    instance Binary Identifier where
        put :: Identifier -> Put
    put (Identifier v :: Maybe String
    v p :: String
    p) = Maybe String -> Put
    forall t. Binary t => t -> Put
    put Maybe String
    v Put -> Put -> Put
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> String -> Put
    forall t. Binary t => t -> Put
    put String
    p
        get :: Get Identifier
    get = Maybe String -> String -> Identifier
    Identifier (Maybe String -> String -> Identifier)
    -> Get (Maybe String) -> Get (String -> Identifier)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Get (Maybe String)
    forall t. Binary t => Get t
    get Get (String -> Identifier) -> Get String -> Get Identifier
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Get String
    forall t. Binary t => Get t
    get

    --------------------------------------------------------------------------------
    instance IsString Identifier where
        fromString :: String -> Identifier
    fromString = String -> Identifier
    fromFilePath

    --------------------------------------------------------------------------------
    instance NFData Identifier where
        rnf :: Identifier -> ()
    rnf (Identifier v :: Maybe String
    v p :: String
    p) = Maybe String -> ()
    forall a. NFData a => a -> ()
    rnf Maybe String
    v () -> () -> ()
    forall a b. a -> b -> b
    `seq` String -> ()
    forall a. NFData a => a -> ()
    rnf String
    p () -> () -> ()
    forall a b. a -> b -> b
    `seq` ()

    --------------------------------------------------------------------------------
    instance Show Identifier where
        show :: Identifier -> String
    show i :: Identifier
    i = case Identifier -> Maybe String
    identifierVersion Identifier
    i of
            Nothing -> Identifier -> String
    toFilePath Identifier
    i
            Just v :: String
    v  -> Identifier -> String
    toFilePath Identifier
    i String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ " (" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    v String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ")"

    --------------------------------------------------------------------------------
    -- | Parse an identifier from a string
    fromFilePath :: FilePath -> Identifier
    fromFilePath :: String -> Identifier
    fromFilePath = Maybe String -> String -> Identifier
    Identifier Maybe String
    forall a. Maybe a
    Nothing (String -> Identifier) -> ShowS -> String -> Identifier
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ShowS
    normalise

    --------------------------------------------------------------------------------
    -- | Convert an identifier to a relative 'FilePath'
    toFilePath :: Identifier -> FilePath
    toFilePath :: Identifier -> String
    toFilePath = ShowS
    normalise ShowS -> (Identifier -> String) -> Identifier -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Identifier -> String
    identifierPath

    --------------------------------------------------------------------------------
    setVersion :: Maybe String -> Identifier -> Identifier
    setVersion :: Maybe String -> Identifier -> Identifier
    setVersion v :: Maybe String
    v i :: Identifier
    i = Identifier
    i {identifierVersion :: Maybe String
    identifierVersion = Maybe String
    v}