pandoc-crossref-0.3.19: lib-internal/Text/Pandoc/CrossRef/Util/Template.hs
{-
pandoc-crossref is a pandoc filter for numbering figures,
equations, tables and cross-references to them.
Copyright (C) 2015 Nikolay Yakimov <root@livid.pp.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-}
module Text.Pandoc.CrossRef.Util.Template
( Template
, BlockTemplate
, MkTemplate
, makeTemplate
, makeIndexedTemplate
, applyTemplate
, applyTemplate'
) where
import Control.Applicative
import Data.Data
import qualified Data.Map as M hiding (fromList, singleton, toList)
import qualified Data.Text as T
import Text.Pandoc.Builder
import Text.Pandoc.CrossRef.Util.Meta
import Text.Pandoc.CrossRef.References.Types
import Text.Pandoc.Generic
import Text.Read
type VarFunc = T.Text -> Maybe MetaValue
newtype Template = Template (VarFunc -> [Inline])
newtype BlockTemplate = BlockTemplate (VarFunc -> [Block])
class Data a => MkTemplate a b where
mkTemplate :: (VarFunc -> [a]) -> b
applyTemplate' :: M.Map T.Text [Inline] -> b -> [a]
instance MkTemplate Inline Template where
mkTemplate = Template
applyTemplate' vars (Template g) = g (internalVars vars)
instance MkTemplate Block BlockTemplate where
mkTemplate = BlockTemplate
applyTemplate' vars (BlockTemplate g) = g (internalVars vars)
makeTemplate :: MkTemplate a b => Meta -> [a] -> b
makeTemplate dtv xs' = mkTemplate \vf -> scan (\var -> vf var <|> lookupMeta var dtv) xs'
where
scan = bottomUp . go
go vf (x@(Math DisplayMath var):xs)
| (vn, idxBr) <- T.span (/='[') var
, not (T.null idxBr)
, T.last idxBr == ']'
= let idxVar = T.drop 1 $ T.takeWhile (/=']') idxBr
idx = readMaybe . T.unpack . toString ("index variable " <> idxVar) =<< vf idxVar
arr = do
i <- idx
v <- lookupMeta vn dtv
getList i v
in toList $ fromList (replaceVar var arr [x]) <> fromList xs
| otherwise = toList $ fromList (replaceVar var (vf var) [x]) <> fromList xs
go _ (x:xs) = toList $ singleton x <> fromList xs
go _ [] = []
replaceVar var val def' = maybe def' (toInlines ("variable " <> var)) val
makeIndexedTemplate :: T.Text -> Meta -> Prefix -> Template
makeIndexedTemplate name meta pfx =
makeTemplate meta $ case lookupMeta name meta of
Just (MetaMap m) -> case lookupMeta subname (Meta m) of
Just x -> toInlines name x
Nothing -> getMetaInlines "default" (Meta m)
Just x -> toInlines name x
Nothing -> []
where
subname = pfxText pfx
internalVars :: M.Map T.Text [Inline] -> T.Text -> Maybe MetaValue
internalVars vars x = MetaInlines <$> M.lookup x vars
applyTemplate :: MkTemplate a b => [Inline] -> [Inline] -> b -> [a]
applyTemplate i t =
applyTemplate' (M.fromDistinctAscList [("i", i), ("t", t)])