{-# LANGUAGE OverloadedStrings #-}

module Data.Makefile.Render.Internal where
import           Data.Makefile
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.IO as TL
import Data.Text.Lazy.Builder

writeMakefile :: FilePath -> Makefile -> IO ()
writeMakefile :: FilePath -> Makefile -> IO ()
writeMakefile FilePath
f = FilePath -> Text -> IO ()
TL.writeFile FilePath
f (Text -> IO ()) -> (Makefile -> Text) -> Makefile -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Makefile -> Text
encodeMakefile

encodeMakefile :: Makefile -> TL.Text
encodeMakefile :: Makefile -> Text
encodeMakefile = Builder -> Text
toLazyText (Builder -> Text) -> (Makefile -> Builder) -> Makefile -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Makefile -> Builder
renderMakefile

renderMakefile :: Makefile -> Builder
renderMakefile :: Makefile -> Builder
renderMakefile (Makefile [Entry]
es ) =
    [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder) -> [Builder] -> Builder
forall a b. (a -> b) -> a -> b
$ Entry -> Builder
renderEntry (Entry -> Builder) -> [Entry] -> [Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Entry]
es

encodeEntry :: Entry -> TL.Text
encodeEntry :: Entry -> Text
encodeEntry = Builder -> Text
toLazyText (Builder -> Text) -> (Entry -> Builder) -> Entry -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Entry -> Builder
renderEntry

renderEntry :: Entry -> Builder
renderEntry :: Entry -> Builder
renderEntry = (Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
singleton Char
'\n') (Builder -> Builder) -> (Entry -> Builder) -> Entry -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Entry -> Builder
renderEntry'
  where
    -- renderEntry' does /not/ append a new line
    renderEntry' :: Entry -> Builder
renderEntry' (Assignment AssignmentType
RecursiveAssign Text
key Text
value ) =
      Text -> Builder
fromText Text
key Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
singleton Char
'=' Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
value
    renderEntry' (Assignment AssignmentType
SimpleAssign Text
key Text
value ) =
      Text -> Builder
fromText Text
key Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
":=" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
value
    renderEntry' (Assignment AssignmentType
SimplePosixAssign Text
key Text
value ) =
      Text -> Builder
fromText Text
key Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
"::=" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
value
    renderEntry' (Assignment AssignmentType
ConditionalAssign Text
key Text
value ) =
      Text -> Builder
fromText Text
key Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
"?=" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
value
    renderEntry' (Assignment AssignmentType
ShellAssign Text
key Text
value ) =
      Text -> Builder
fromText Text
key Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
"!=" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
value
    renderEntry' (Assignment AssignmentType
AppendAssign Text
key Text
value ) =
      Text -> Builder
fromText Text
key Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
"+=" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
value
    renderEntry' (Rule (Target Text
t) [Dependency]
ds [Command]
cs) =
        Text -> Builder
fromText Text
t Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
singleton Char
':' Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
deps'
          Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
cmds
      where
        deps :: [Builder]
deps = (\Dependency
dep -> Char -> Builder
singleton Char
' ' Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Dependency -> Builder
renderDep Dependency
dep) (Dependency -> Builder) -> [Dependency] -> [Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Dependency]
ds
        deps' :: Builder
deps' = case [Builder]
deps of { [] -> Builder
forall a. Monoid a => a
mempty; [Builder]
xs -> [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat [Builder]
xs }
        cmds :: Builder
cmds =
          case Command -> Builder
renderCmd (Command -> Builder) -> [Command] -> [Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Command]
cs of
            [] -> Builder
forall a. Monoid a => a
mempty
            [Builder]
xs -> Char -> Builder
singleton Char
'\n' Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder -> [Builder] -> Builder
forall a. Monoid a => a -> [a] -> a
intercalate Builder
"\n" [Builder]
xs

    renderEntry' (OtherLine Text
t) = Text -> Builder
fromText Text
t

intercalate :: Monoid a => a -> [a] -> a
intercalate :: forall a. Monoid a => a -> [a] -> a
intercalate a
i (a
x:a
y:[a]
xs) = a
x a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
i a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a -> [a] -> a
forall a. Monoid a => a -> [a] -> a
intercalate a
i (a
ya -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs)
intercalate a
_ [a
x] = a
x
intercalate a
_ [] = a
forall a. Monoid a => a
mempty

renderDep :: Dependency -> Builder
renderDep :: Dependency -> Builder
renderDep (Dependency Text
dep ) = Text -> Builder
fromText Text
dep

renderCmd :: Command -> Builder
renderCmd :: Command -> Builder
renderCmd (Command Text
cmd) = Char -> Builder
singleton Char
'\t' Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
cmd