{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{- |
   Module      : Text.DocTemplates.Parser
   Copyright   : Copyright (C) 2009-2019 John MacFarlane
   License     : BSD3

   Maintainer  : John MacFarlane <jgm@berkeley.edu>
   Stability   : alpha
   Portability : portable
-}

module Text.DocTemplates.Parser
    ( compileTemplate ) where

import Data.Char (isAlphaNum)
import Control.Monad (guard, when)
import Control.Monad.Trans (lift)
import qualified Text.Parsec as P
import qualified Text.Parsec.Pos as P
import Control.Applicative
import Data.String (IsString(..))
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Read as T
import System.FilePath
import Text.DocTemplates.Internal
import qualified Text.DocLayout as DL
#if MIN_VERSION_base(4,11,0)
#else
import Data.Semigroup ((<>), Semigroup)
#endif

-- | Compile a template.  The FilePath parameter is used
-- to determine a default path and extension for partials
-- and may be left empty if partials are not used.
compileTemplate :: (TemplateMonad m, TemplateTarget a)
                => FilePath -> Text -> m (Either String (Template a))
compileTemplate :: forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
FilePath -> Text -> m (Either FilePath (Template a))
compileTemplate FilePath
templPath Text
template = do
  Either ParseError (Template a)
res <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> u -> FilePath -> s -> m (Either ParseError a)
P.runParserT (forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
Parser m (Template a)
pTemplate forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
P.eof)
           PState{ templatePath :: FilePath
templatePath    = FilePath
templPath
                 , partialNesting :: Int
partialNesting  = Int
1
                 , breakingSpaces :: Bool
breakingSpaces  = Bool
False
                 , firstNonspace :: SourcePos
firstNonspace   = FilePath -> SourcePos
P.initialPos FilePath
templPath
                 , nestedCol :: Maybe Int
nestedCol       = forall a. Maybe a
Nothing
                 , insideDirective :: Bool
insideDirective = Bool
False
                 } FilePath
templPath Text
template
  case Either ParseError (Template a)
res of
       Left ParseError
e   -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> FilePath
show ParseError
e
       Right Template a
x  -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right Template a
x


data PState =
  PState { PState -> FilePath
templatePath    :: FilePath
         , PState -> Int
partialNesting  :: !Int
         , PState -> Bool
breakingSpaces  :: !Bool
         , PState -> SourcePos
firstNonspace   :: P.SourcePos
         , PState -> Maybe Int
nestedCol       :: Maybe Int
         , PState -> Bool
insideDirective :: Bool
         }

type Parser = P.ParsecT Text PState

pTemplate :: (TemplateMonad m, TemplateTarget a) => Parser m (Template a)
pTemplate :: forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
Parser m (Template a)
pTemplate = do
  forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall (m :: * -> *). Monad m => Parser m ()
pComment
  forall a. Monoid a => [a] -> a
mconcat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a. Alternative f => f a -> f [a]
many
    ((forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pLit forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pNewline forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pDirective forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
      forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pEscape) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall (m :: * -> *). Monad m => Parser m ()
pComment)

pEndline :: Monad m => Parser m String
pEndline :: forall (m :: * -> *). Monad m => Parser m FilePath
pEndline = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ do
  FilePath
nls <- forall (m :: * -> *). Monad m => Parser m FilePath
pLineEnding
  Maybe Int
mbNested <- PState -> Maybe Int
nestedCol forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  Bool
inside <- PState -> Bool
insideDirective forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  case Maybe Int
mbNested of
    Just Int
col -> do
      forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall a b. (a -> b) -> a -> b
$ do
        forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Ord a => a -> a -> Bool
< Int
col) forall b c a. (b -> c) -> (a -> b) -> a -> c
. SourcePos -> Int
P.sourceColumn
        forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
' ' forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'\t'
      Int
curcol <- SourcePos -> Int
P.sourceColumn forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition
      forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall a b. (a -> b) -> a -> b
$ Bool
inside Bool -> Bool -> Bool
|| Int
curcol forall a. Ord a => a -> a -> Bool
>= Int
col
    Maybe Int
Nothing  ->  forall (m :: * -> *) a. Monad m => a -> m a
return ()
  forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
nls

pBlankLine :: (TemplateTarget a, Monad m) => Parser m (Template a)
pBlankLine :: forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pBlankLine =
  forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ forall a. Doc a -> Template a
Literal forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IsString a => FilePath -> a
fromString forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). Monad m => Parser m FilePath
pLineEnding forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
P.lookAhead forall (m :: * -> *). Monad m => Parser m ()
pNewlineOrEof

pNewline :: (TemplateTarget a, Monad m) => Parser m (Template a)
pNewline :: forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pNewline = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ do
  FilePath
nls <- forall (m :: * -> *). Monad m => Parser m FilePath
pEndline
  FilePath
sps <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
P.many (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
' ' forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'\t')
  Bool
breakspaces <- PState -> Bool
breakingSpaces forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  SourcePos
pos <- forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition
  forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.updateState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ firstNonspace :: SourcePos
firstNonspace = SourcePos
pos }
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Doc a -> Template a
Literal forall a b. (a -> b) -> a -> b
$
    if Bool
breakspaces
       then forall a. Doc a
DL.BreakingSpace
       else forall a. IsString a => FilePath -> a
fromString forall a b. (a -> b) -> a -> b
$ FilePath
nls forall a. Semigroup a => a -> a -> a
<> FilePath
sps

pLit :: (TemplateTarget a, Monad m) => Parser m (Template a)
pLit :: forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pLit = do
  FilePath
cs <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 (forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
P.satisfy (\Char
c -> Char
c forall a. Eq a => a -> a -> Bool
/= Char
'$' Bool -> Bool -> Bool
&& Char
c forall a. Eq a => a -> a -> Bool
/= Char
'\n' Bool -> Bool -> Bool
&& Char
c forall a. Eq a => a -> a -> Bool
/= Char
'\r'))
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\Char
c -> Char
c forall a. Eq a => a -> a -> Bool
== Char
' ' Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'\t') FilePath
cs) forall a b. (a -> b) -> a -> b
$ do
     SourcePos
pos <- forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition
     forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (SourcePos -> Int
P.sourceLine SourcePos
pos forall a. Eq a => a -> a -> Bool
== Int
1) forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.updateState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ firstNonspace :: SourcePos
firstNonspace = SourcePos
pos }
  Bool
breakspaces <- PState -> Bool
breakingSpaces forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  if Bool
breakspaces
     then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. TemplateTarget a => FilePath -> Template a
toBreakable FilePath
cs
     else forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Doc a -> Template a
Literal forall a b. (a -> b) -> a -> b
$ forall a. IsString a => FilePath -> a
fromString FilePath
cs

toBreakable :: TemplateTarget a => String -> Template a
toBreakable :: forall a. TemplateTarget a => FilePath -> Template a
toBreakable [] = forall a. Template a
Empty
toBreakable FilePath
xs =
  case forall a. (a -> Bool) -> [a] -> ([a], [a])
break Char -> Bool
isSpacy FilePath
xs of
    ([], []) -> forall a. Template a
Empty
    ([], FilePath
zs) -> forall a. Doc a -> Template a
Literal forall a. Doc a
DL.BreakingSpace forall a. Semigroup a => a -> a -> a
<>
                   forall a. TemplateTarget a => FilePath -> Template a
toBreakable (forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpacy FilePath
zs)
    (FilePath
ys, []) -> forall a. Doc a -> Template a
Literal (forall a. IsString a => FilePath -> a
fromString FilePath
ys)
    (FilePath
ys, FilePath
zs) -> forall a. Doc a -> Template a
Literal (forall a. IsString a => FilePath -> a
fromString FilePath
ys) forall a. Semigroup a => a -> a -> a
<> forall a. TemplateTarget a => FilePath -> Template a
toBreakable FilePath
zs

isSpacy :: Char -> Bool
isSpacy :: Char -> Bool
isSpacy Char
' '  = Bool
True
isSpacy Char
'\n' = Bool
True
isSpacy Char
'\r' = Bool
True
isSpacy Char
'\t' = Bool
True
isSpacy Char
_    = Bool
False

backupSourcePos :: Monad m => Int -> Parser m ()
backupSourcePos :: forall (m :: * -> *). Monad m => Int -> Parser m ()
backupSourcePos Int
n = do
  SourcePos
pos <- forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition
  forall (m :: * -> *) s u. Monad m => SourcePos -> ParsecT s u m ()
P.setPosition forall a b. (a -> b) -> a -> b
$ SourcePos -> Int -> SourcePos
P.incSourceColumn SourcePos
pos (- Int
n)

pEscape :: (TemplateTarget a, Monad m) => Parser m (Template a)
pEscape :: forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pEscape = forall a. Doc a -> Template a
Literal Doc a
"$" forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"$$" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall (m :: * -> *). Monad m => Int -> Parser m ()
backupSourcePos Int
1)

pDirective :: (TemplateTarget a, TemplateMonad m)
           => Parser m (Template a)
pDirective :: forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pDirective =
  forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pConditional forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pForLoop forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a (m :: * -> *).
(Monoid a, Semigroup a, TemplateMonad m) =>
Parser m (Template a)
pReflowToggle forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pNested forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pInterpolate forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pBarePartial

pEnclosed :: Monad m => Parser m a -> Parser m a
pEnclosed :: forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pEnclosed Parser m a
parser = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ do
  Parser m ()
closer <- forall (m :: * -> *). Monad m => Parser m (Parser m ())
pOpen
  forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall (m :: * -> *). Monad m => Parser m Char
pSpaceOrTab
  a
result <- Parser m a
parser
  forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall (m :: * -> *). Monad m => Parser m Char
pSpaceOrTab
  Parser m ()
closer
  forall (m :: * -> *) a. Monad m => a -> m a
return a
result

pParens :: Monad m => Parser m a -> Parser m a
pParens :: forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pParens Parser m a
parser = do
  forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'('
  a
result <- Parser m a
parser
  forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
')'
  forall (m :: * -> *) a. Monad m => a -> m a
return a
result

pInside :: Monad m
        => Parser m (Template a)
        -> Parser m (Template a)
pInside :: forall (m :: * -> *) a.
Monad m =>
Parser m (Template a) -> Parser m (Template a)
pInside Parser m (Template a)
parser = do
  Bool
oldInside <- PState -> Bool
insideDirective forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.updateState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ insideDirective :: Bool
insideDirective = Bool
True }
  Template a
res <- Parser m (Template a)
parser
  forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.updateState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ insideDirective :: Bool
insideDirective = Bool
oldInside }
  forall (m :: * -> *) a. Monad m => a -> m a
return Template a
res

pConditional :: (TemplateTarget a, TemplateMonad m)
             => Parser m (Template a)
pConditional :: forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pConditional = do
  Variable
v <- forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pEnclosed forall a b. (a -> b) -> a -> b
$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"if" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pParens forall (m :: * -> *). Monad m => Parser m Variable
pVar
  forall (m :: * -> *) a.
Monad m =>
Parser m (Template a) -> Parser m (Template a)
pInside forall a b. (a -> b) -> a -> b
$ do
    Bool
multiline <- forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option Bool
False (Bool
True forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (m :: * -> *). Monad m => Parser m ()
skipEndline)
    -- if newline after the "if", then a newline after "endif" will be swallowed
    Template a
ifContents <- forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
Parser m (Template a)
pTemplate
    Template a
elseContents <- forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option forall a. Monoid a => a
mempty (forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Bool -> Parser m (Template a)
pElse Bool
multiline forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pElseIf)
    forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pEnclosed (forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"endif")
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
multiline forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option () forall (m :: * -> *). Monad m => Parser m ()
skipEndline
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Variable -> Template a -> Template a -> Template a
Conditional Variable
v Template a
ifContents Template a
elseContents

pElse :: (TemplateTarget a, TemplateMonad m)
      => Bool -> Parser m (Template a)
pElse :: forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Bool -> Parser m (Template a)
pElse Bool
multiline = do
  forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pEnclosed (forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"else")
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
multiline forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option () forall (m :: * -> *). Monad m => Parser m ()
skipEndline
  forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
Parser m (Template a)
pTemplate

pElseIf :: (TemplateTarget a, TemplateMonad m) => Parser m (Template a)
pElseIf :: forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pElseIf = do
  Variable
v <- forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pEnclosed forall a b. (a -> b) -> a -> b
$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"elseif" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pParens forall (m :: * -> *). Monad m => Parser m Variable
pVar
  Bool
multiline <- forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option Bool
False (Bool
True forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (m :: * -> *). Monad m => Parser m ()
skipEndline)
  Template a
ifContents <- forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
Parser m (Template a)
pTemplate
  Template a
elseContents <- forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option forall a. Monoid a => a
mempty (forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Bool -> Parser m (Template a)
pElse Bool
multiline forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pElseIf)
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Variable -> Template a -> Template a -> Template a
Conditional Variable
v Template a
ifContents Template a
elseContents

skipEndline :: Monad m => Parser m ()
skipEndline :: forall (m :: * -> *). Monad m => Parser m ()
skipEndline = do
  forall (m :: * -> *). Monad m => Parser m FilePath
pEndline
  SourcePos
pos <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
P.lookAhead forall a b. (a -> b) -> a -> b
$ do
           forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
' ' forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'\t')
           forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition
  forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.updateState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ firstNonspace :: SourcePos
firstNonspace = SourcePos
pos }

pReflowToggle :: (Monoid a, Semigroup a, TemplateMonad m)
              => Parser m (Template a)
pReflowToggle :: forall a (m :: * -> *).
(Monoid a, Semigroup a, TemplateMonad m) =>
Parser m (Template a)
pReflowToggle = do
  forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pEnclosed forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'~'
  forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.modifyState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ breakingSpaces :: Bool
breakingSpaces = Bool -> Bool
not (PState -> Bool
breakingSpaces PState
st) }
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Monoid a => a
mempty

pNested :: (TemplateTarget a, TemplateMonad m) => Parser m (Template a)
pNested :: forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pNested = do
  Int
col <- SourcePos -> Int
P.sourceColumn forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition
  forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pEnclosed forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'^'
  Maybe Int
oldNested <- PState -> Maybe Int
nestedCol forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.updateState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ nestedCol :: Maybe Int
nestedCol = forall a. a -> Maybe a
Just Int
col }
  Template a
x <- forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
Parser m (Template a)
pTemplate
  [Template a]
xs <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
P.many forall a b. (a -> b) -> a -> b
$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ do
          Template a
y <- forall a. Monoid a => [a] -> a
mconcat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pBlankLine
          Template a
z <- forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
Parser m (Template a)
pTemplate
          forall (m :: * -> *) a. Monad m => a -> m a
return (Template a
y forall a. Semigroup a => a -> a -> a
<> Template a
z)
  let contents :: Template a
contents = Template a
x forall a. Semigroup a => a -> a -> a
<> forall a. Monoid a => [a] -> a
mconcat [Template a]
xs
  forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.updateState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ nestedCol :: Maybe Int
nestedCol = Maybe Int
oldNested }
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Template a -> Template a
Nested Template a
contents

pForLoop :: (TemplateTarget a, TemplateMonad m) => Parser m (Template a)
pForLoop :: forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pForLoop = do
  Variable
v <- forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pEnclosed forall a b. (a -> b) -> a -> b
$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"for" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pParens forall (m :: * -> *). Monad m => Parser m Variable
pVar
  -- if newline after the "for", then a newline after "endfor" will be swallowed
  forall (m :: * -> *) a.
Monad m =>
Parser m (Template a) -> Parser m (Template a)
pInside forall a b. (a -> b) -> a -> b
$ do
    Bool
multiline <- forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option Bool
False forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). Monad m => Parser m ()
skipEndline forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
    Template a
contents <- forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
Parser m (Template a)
pTemplate
    Template a
sep <- forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option forall a. Monoid a => a
mempty forall a b. (a -> b) -> a -> b
$
             do forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pEnclosed (forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"sep")
                forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
multiline forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option () forall (m :: * -> *). Monad m => Parser m ()
skipEndline
                forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
Parser m (Template a)
pTemplate
    forall (m :: * -> *) a. Monad m => Parser m a -> Parser m a
pEnclosed (forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"endfor")
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
multiline forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option () forall (m :: * -> *). Monad m => Parser m ()
skipEndline
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Variable -> Template a -> Template a -> Template a
Iterate Variable
v Template a
contents Template a
sep

pInterpolate :: (TemplateTarget a, TemplateMonad m)
             => Parser m (Template a)
pInterpolate :: forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pInterpolate = do
  SourcePos
pos <- forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition
  -- we don't used pEnclosed here, to get better error messages:
  (Parser m ()
closer, Variable
var) <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ do
    Parser m ()
cl <- forall (m :: * -> *). Monad m => Parser m (Parser m ())
pOpen
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall (m :: * -> *). Monad m => Parser m Char
pSpaceOrTab
    Variable
v <- forall (m :: * -> *). Monad m => Parser m Variable
pVar
    forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
P.notFollowedBy (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'(') -- bare partial
    forall (m :: * -> *) a. Monad m => a -> m a
return (Parser m ()
cl, Variable
v)
  Template a
res <- (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
':' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (forall (m :: * -> *). TemplateMonad m => Parser m FilePath
pPartialName forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Maybe Variable -> FilePath -> Parser m (Template a)
pPartial (forall a. a -> Maybe a
Just Variable
var)))
      forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a. Variable -> Template a -> Template a -> Template a
Iterate Variable
var (forall a. Variable -> Template a
Interpolate ([Text] -> [Pipe] -> Variable
Variable [Text
"it"] [])) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pSep
      forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. Variable -> Template a
Interpolate Variable
var)
  forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall (m :: * -> *). Monad m => Parser m Char
pSpaceOrTab
  Parser m ()
closer
  forall (m :: * -> *) a.
TemplateMonad m =>
Bool -> SourcePos -> Template a -> Parser m (Template a)
handleNesting Bool
False SourcePos
pos Template a
res

pLineEnding :: Monad m => Parser m String
pLineEnding :: forall (m :: * -> *). Monad m => Parser m FilePath
pLineEnding = forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"\n" forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"\r\n") forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"\r"

pNewlineOrEof :: Monad m => Parser m ()
pNewlineOrEof :: forall (m :: * -> *). Monad m => Parser m ()
pNewlineOrEof = () forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (m :: * -> *). Monad m => Parser m FilePath
pLineEnding forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
P.eof

handleNesting :: TemplateMonad m
              => Bool -> P.SourcePos -> Template a -> Parser m (Template a)
handleNesting :: forall (m :: * -> *) a.
TemplateMonad m =>
Bool -> SourcePos -> Template a -> Parser m (Template a)
handleNesting Bool
eatEndline SourcePos
pos Template a
templ = do
  SourcePos
firstNonspacePos <- PState -> SourcePos
firstNonspace forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  let beginline :: Bool
beginline = SourcePos
firstNonspacePos forall a. Eq a => a -> a -> Bool
== SourcePos
pos
  Bool
endofline <- (Bool
True forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
P.lookAhead forall (m :: * -> *). Monad m => Parser m ()
pNewlineOrEof) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
eatEndline Bool -> Bool -> Bool
&& Bool
beginline) forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m ()
P.optional forall (m :: * -> *). Monad m => Parser m ()
skipEndline
  Maybe Int
mbNested <- PState -> Maybe Int
nestedCol forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  let toNested :: Template a -> Template a
toNested t :: Template a
t@(Nested{}) = Template a
t
      toNested Template a
t = case SourcePos -> Int
P.sourceColumn SourcePos
pos of
                     Int
1 -> Template a
t
                     Int
n | forall a. a -> Maybe a
Just Int
n forall a. Eq a => a -> a -> Bool
== Maybe Int
mbNested -> Template a
t
                       | Bool
otherwise          -> forall a. Template a -> Template a
Nested Template a
t
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if Bool
beginline Bool -> Bool -> Bool
&& Bool
endofline
              then forall a. Template a -> Template a
toNested Template a
templ
              else Template a
templ

pBarePartial :: (TemplateTarget a, TemplateMonad m)
             => Parser m (Template a)
pBarePartial :: forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Parser m (Template a)
pBarePartial = do
  SourcePos
pos <- forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition
  (Parser m ()
closer, FilePath
fp) <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ do
    Parser m ()
closer <- forall (m :: * -> *). Monad m => Parser m (Parser m ())
pOpen
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall (m :: * -> *). Monad m => Parser m Char
pSpaceOrTab
    FilePath
fp <- forall (m :: * -> *). TemplateMonad m => Parser m FilePath
pPartialName
    forall (m :: * -> *) a. Monad m => a -> m a
return (Parser m ()
closer, FilePath
fp)
  Template a
res <- forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Maybe Variable -> FilePath -> Parser m (Template a)
pPartial forall a. Maybe a
Nothing FilePath
fp
  forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall (m :: * -> *). Monad m => Parser m Char
pSpaceOrTab
  Parser m ()
closer
  forall (m :: * -> *) a.
TemplateMonad m =>
Bool -> SourcePos -> Template a -> Parser m (Template a)
handleNesting Bool
True SourcePos
pos Template a
res

pPartialName :: TemplateMonad m
             => Parser m FilePath
pPartialName :: forall (m :: * -> *). TemplateMonad m => Parser m FilePath
pPartialName = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ do
  FilePath
fp <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 (forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.alphaNum forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m Char
P.oneOf [Char
'_',Char
'-',Char
'.',Char
'/',Char
'\\'])
  forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"()"
  forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
fp

pPartial :: (TemplateTarget a, TemplateMonad m)
         => Maybe Variable -> FilePath -> Parser m (Template a)
pPartial :: forall a (m :: * -> *).
(TemplateTarget a, TemplateMonad m) =>
Maybe Variable -> FilePath -> Parser m (Template a)
pPartial Maybe Variable
mbvar FilePath
fp = do
  PState
oldst <- forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  Template a
separ <- forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option forall a. Monoid a => a
mempty forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pSep
  FilePath
tp <- PState -> FilePath
templatePath forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  let fp' :: FilePath
fp' = case FilePath -> FilePath
takeExtension FilePath
fp of
               FilePath
"" -> FilePath -> FilePath -> FilePath
replaceBaseName FilePath
tp FilePath
fp
               FilePath
_  -> FilePath -> FilePath -> FilePath
replaceFileName FilePath
tp FilePath
fp
  Text
partial <- forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall a b. (a -> b) -> a -> b
$ Text -> Text
removeFinalNewline forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). TemplateMonad m => FilePath -> m Text
getPartial FilePath
fp'
  Int
nesting <- PState -> Int
partialNesting forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s u. Monad m => ParsecT s u m u
P.getState
  Template a
t <- if Int
nesting forall a. Ord a => a -> a -> Bool
> Int
50
          then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Doc a -> Template a
Literal Doc a
"(loop)"
          else do
            Text
oldInput <- forall (m :: * -> *) s u. Monad m => ParsecT s u m s
P.getInput
            SourcePos
oldPos <- forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition
            forall (m :: * -> *) s u. Monad m => SourcePos -> ParsecT s u m ()
P.setPosition forall a b. (a -> b) -> a -> b
$ FilePath -> SourcePos
P.initialPos FilePath
fp'
            forall (m :: * -> *) s u. Monad m => s -> ParsecT s u m ()
P.setInput Text
partial
            forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.updateState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ partialNesting :: Int
partialNesting = Int
nesting forall a. Num a => a -> a -> a
+ Int
1 }
            forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.updateState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ nestedCol :: Maybe Int
nestedCol = forall a. Maybe a
Nothing }
            Template a
res' <- forall (m :: * -> *) a.
(TemplateMonad m, TemplateTarget a) =>
Parser m (Template a)
pTemplate forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
P.eof
            forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
P.updateState forall a b. (a -> b) -> a -> b
$ \PState
st -> PState
st{ partialNesting :: Int
partialNesting = Int
nesting }
            forall (m :: * -> *) s u. Monad m => s -> ParsecT s u m ()
P.setInput Text
oldInput
            forall (m :: * -> *) s u. Monad m => SourcePos -> ParsecT s u m ()
P.setPosition SourcePos
oldPos
            forall (m :: * -> *) a. Monad m => a -> m a
return Template a
res'
  forall (m :: * -> *) u s. Monad m => u -> ParsecT s u m ()
P.putState PState
oldst
  [Pipe]
fs <- forall (f :: * -> *) a. Alternative f => f a -> f [a]
many forall (m :: * -> *). Monad m => Parser m Pipe
pPipe
  case Maybe Variable
mbvar of
    Just Variable
var -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Variable -> Template a -> Template a -> Template a
Iterate Variable
var (forall a. [Pipe] -> Template a -> Template a
Partial [Pipe]
fs Template a
t) Template a
separ
    Maybe Variable
Nothing  -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. [Pipe] -> Template a -> Template a
Partial [Pipe]
fs Template a
t

removeFinalNewline :: Text -> Text
removeFinalNewline :: Text -> Text
removeFinalNewline Text
t =
  case Text -> Maybe (Text, Char)
T.unsnoc Text
t of
    Just (Text
t', Char
'\n') -> Text
t'
    Maybe (Text, Char)
_ -> Text
t

pSep :: (TemplateTarget a, Monad m) => Parser m (Template a)
pSep :: forall a (m :: * -> *).
(TemplateTarget a, Monad m) =>
Parser m (Template a)
pSep = do
    forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'['
    FilePath
xs <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
P.many (forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
P.satisfy (forall a. Eq a => a -> a -> Bool
/= Char
']'))
    forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
']'
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Doc a -> Template a
Literal (forall a. IsString a => FilePath -> a
fromString FilePath
xs)

pSpaceOrTab :: Monad m => Parser m Char
pSpaceOrTab :: forall (m :: * -> *). Monad m => Parser m Char
pSpaceOrTab = forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
P.satisfy (\Char
c -> Char
c forall a. Eq a => a -> a -> Bool
== Char
' ' Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'\t')

pComment :: Monad m => Parser m ()
pComment :: forall (m :: * -> *). Monad m => Parser m ()
pComment = do
  SourcePos
pos <- forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
P.getPosition
  forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"$--")
  forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany (forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
P.satisfy (forall a. Eq a => a -> a -> Bool
/=Char
'\n'))
  -- If the comment begins in the first column, the line ending
  -- will be consumed; otherwise not.
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (SourcePos -> Int
P.sourceColumn SourcePos
pos forall a. Eq a => a -> a -> Bool
== Int
1) forall a b. (a -> b) -> a -> b
$ () forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (m :: * -> *). Monad m => Parser m ()
pNewlineOrEof

pOpenDollar :: Monad m => Parser m (Parser m ())
pOpenDollar :: forall (m :: * -> *). Monad m => Parser m (Parser m ())
pOpenDollar =
  forall {u}. ParsecT Text u m ()
pCloseDollar forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'$' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*
                   forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
P.notFollowedBy (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'$' forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'{'))
  where
   pCloseDollar :: ParsecT Text u m ()
pCloseDollar = () forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'$'

pOpenBraces :: Monad m => Parser m (Parser m ())
pOpenBraces :: forall (m :: * -> *). Monad m => Parser m (Parser m ())
pOpenBraces =
  forall {u}. ParsecT Text u m ()
pCloseBraces forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"${" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
P.notFollowedBy (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'}'))
  where
   pCloseBraces :: ParsecT Text u m ()
pCloseBraces = () forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'}')

pOpen :: Monad m => Parser m (Parser m ())
pOpen :: forall (m :: * -> *). Monad m => Parser m (Parser m ())
pOpen = forall (m :: * -> *). Monad m => Parser m (Parser m ())
pOpenDollar forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (m :: * -> *). Monad m => Parser m (Parser m ())
pOpenBraces

pVar :: Monad m => Parser m Variable
pVar :: forall (m :: * -> *). Monad m => Parser m Variable
pVar = do
  Text
first <- forall (m :: * -> *). Monad m => Parser m Text
pIdentPart forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (m :: * -> *). Monad m => Parser m Text
pIt
  [Text]
rest <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
P.many (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'.' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall (m :: * -> *). Monad m => Parser m Text
pIdentPart)
  [Pipe]
pipes <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
P.many forall (m :: * -> *). Monad m => Parser m Pipe
pPipe
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ [Text] -> [Pipe] -> Variable
Variable (Text
firstforall a. a -> [a] -> [a]
:[Text]
rest) [Pipe]
pipes

pPipe :: Monad m => Parser m Pipe
pPipe :: forall (m :: * -> *). Monad m => Parser m Pipe
pPipe = do
  forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'/'
  FilePath
pipeName <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.letter
  forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
P.notFollowedBy forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.letter
  case FilePath
pipeName of
    FilePath
"uppercase"  -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
ToUppercase
    FilePath
"lowercase"  -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
ToLowercase
    FilePath
"pairs"      -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
ToPairs
    FilePath
"length"     -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
ToLength
    FilePath
"alpha"      -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
ToAlpha
    FilePath
"roman"      -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
ToRoman
    FilePath
"reverse"    -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
Reverse
    FilePath
"first"      -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
FirstItem
    FilePath
"rest"       -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
Rest
    FilePath
"last"       -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
LastItem
    FilePath
"allbutlast" -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
AllButLast
    FilePath
"chomp"      -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
Chomp
    FilePath
"nowrap"     -> forall (m :: * -> *) a. Monad m => a -> m a
return Pipe
NoWrap
    FilePath
"left"       -> Alignment -> Int -> Border -> Pipe
Block Alignment
LeftAligned forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). Monad m => Parser m Int
pBlockWidth forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (m :: * -> *). Monad m => Parser m Border
pBlockBorders
    FilePath
"right"      -> Alignment -> Int -> Border -> Pipe
Block Alignment
RightAligned forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). Monad m => Parser m Int
pBlockWidth forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (m :: * -> *). Monad m => Parser m Border
pBlockBorders
    FilePath
"center"     -> Alignment -> Int -> Border -> Pipe
Block Alignment
Centered forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). Monad m => Parser m Int
pBlockWidth forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (m :: * -> *). Monad m => Parser m Border
pBlockBorders
    FilePath
_            -> forall (m :: * -> *) a. MonadFail m => FilePath -> m a
fail forall a b. (a -> b) -> a -> b
$ FilePath
"Unknown pipe " forall a. [a] -> [a] -> [a]
++ FilePath
pipeName

pBlockWidth :: Monad m => Parser m Int
pBlockWidth :: forall (m :: * -> *). Monad m => Parser m Int
pBlockWidth = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (do
  FilePath
_ <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.space
  FilePath
ds <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.digit
  case forall a. Integral a => Reader a
T.decimal (FilePath -> Text
T.pack FilePath
ds) of
        Right (Int
n,Text
"") -> forall (m :: * -> *) a. Monad m => a -> m a
return Int
n
        Either FilePath (Int, Text)
_            -> forall (m :: * -> *) a. MonadFail m => FilePath -> m a
fail FilePath
"Expected integer parameter for pipe") forall s u (m :: * -> *) a.
ParsecT s u m a -> FilePath -> ParsecT s u m a
P.<?>
          FilePath
"integer parameter for pipe"

pBlockBorders :: Monad m => Parser m Border
pBlockBorders :: forall (m :: * -> *). Monad m => Parser m Border
pBlockBorders = do
  forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.space
  let pBorder :: ParsecT Text u m Text
pBorder = do
        forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'"'
        FilePath
cs <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
P.many forall a b. (a -> b) -> a -> b
$ (forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m Char
P.noneOf [Char
'"',Char
'\\']) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'\\' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.anyChar)
        forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'"'
        forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
P.skipMany forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.space
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ FilePath -> Text
T.pack FilePath
cs
  Text -> Text -> Border
Border forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option forall a. Monoid a => a
mempty forall {u}. ParsecT Text u m Text
pBorder forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option forall a. Monoid a => a
mempty forall {u}. ParsecT Text u m Text
pBorder

pIt :: Monad m => Parser m Text
pIt :: forall (m :: * -> *). Monad m => Parser m Text
pIt = forall a. IsString a => FilePath -> a
fromString forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try (forall s (m :: * -> *) u.
Stream s m Char =>
FilePath -> ParsecT s u m FilePath
P.string FilePath
"it")

pIdentPart :: Monad m => Parser m Text
pIdentPart :: forall (m :: * -> *). Monad m => Parser m Text
pIdentPart = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
P.try forall a b. (a -> b) -> a -> b
$ do
  Char
first <- forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.letter
  FilePath
rest <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
P.many (forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
P.satisfy (\Char
c -> Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'_' Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'-'))
  let part :: FilePath
part = Char
first forall a. a -> [a] -> [a]
: FilePath
rest
  forall (f :: * -> *). Alternative f => Bool -> f ()
guard forall a b. (a -> b) -> a -> b
$ FilePath
part forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [FilePath]
reservedWords
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. IsString a => FilePath -> a
fromString FilePath
part

reservedWords :: [String]
reservedWords :: [FilePath]
reservedWords = [FilePath
"if",FilePath
"else",FilePath
"endif",FilePath
"elseif",FilePath
"for",FilePath
"endfor",FilePath
"sep",FilePath
"it"]