module Text.SmallCaps.Config where
import Data.Default ( Default, def )
import Data.Text ( Text, pack, snoc, append )
import Data.Map ( Map )
import qualified Data.Map as Map ( empty, fromList )
import Control.Monad ( liftM2 )
import Text.SmallCaps.LaTeX ( LaTeX, LaTeXElement
, isPrintable, isMacro, isEnvironment, isBlock, isBBlock, isMath, isComment
, name
)
type SubParser a = ParserState -> a -> Either String (a, ParserState)
data ParserState = ParserState
{ config :: Config
, inputs :: Map FilePath (FilePath, LaTeX)
, profile :: Map Text Config
, stop :: StopState
, ignore :: Bool
}
instance Default ParserState where
def = ParserState
{ config = def
, inputs = Map.empty
, profile = Map.fromList [ (pack "default", def)
, (pack "clean", clean)
, (pack "conservative", conservative)
, (pack "busy", busy)
, (pack "small", small)
]
, stop = def
, ignore = False
}
data Config = Config
{ periodChars :: [Char]
, search :: LaTeXElement -> Bool
, isolate :: LaTeXElement -> Maybe Text
, skip :: LaTeXElement -> Bool
, unskip :: LaTeXElement -> Bool
, eos :: LaTeXElement -> Bool
, replace :: Text -> Text
, inlineConfig :: Bool
}
instance Default Config where
def = Config
{ periodChars = defaultPeriodChars
, search = defaultSearch
, isolate = defaultIsolate
, skip = defaultSkip
, unskip = defaultUnskip
, eos = defaultEos
, replace = defaultReplace
, inlineConfig = True
}
defaultPeriodChars :: [Char]
defaultPeriodChars = ".!?"
defaultSearch :: LaTeXElement -> Bool
defaultSearch = whitelist ["document", "\\\\"]
defaultIsolate :: LaTeXElement -> Maybe Text
defaultIsolate = isolateWith [ ("abstract", "small")
, ("\\footnote", "small")
, ("\\marginpar", "default")
]
defaultSkip :: LaTeXElement -> Bool
defaultSkip = after [ "\\tiny", "\\scriptsize", "\\footnotesize", "\\small"
, "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"]
defaultUnskip :: LaTeXElement -> Bool
defaultUnskip = after ["\\normalsize"]
defaultEos :: LaTeXElement -> Bool
defaultEos = after
[ "\\par"
, "\\part", "\\chapter", "\\section", "\\subsection", "\\subsubsection", "\\paragraph"
, "\\part*", "\\chapter*", "\\section*", "\\subsection*", "\\subsubsection*"
, "\\include"
, "itemize", "enumerate", "description"
]
defaultReplace :: Text -> Text
defaultReplace caps = pack "{\\small " `append` snoc caps '}'
(&&&) :: (LaTeXElement -> Bool) -> (LaTeXElement -> Bool) -> LaTeXElement -> Bool
(&&&) fun gun element = fun element && gun element
(|||) :: (LaTeXElement -> Bool) -> (LaTeXElement -> Bool) -> LaTeXElement -> Bool
(|||) fun gun element = fun element || gun element
clean :: Config
clean = Config
{ periodChars = []
, search = const False
, isolate = isolateWith []
, skip = const False
, unskip = const False
, eos = const False
, replace = id
, inlineConfig = True
}
conservative :: Config
conservative = def
{ search = whitelist []
, isolate = isolateWith []
, eos = after ["\\par"]
}
busy :: Config
busy = conservative { search = blacklist [] }
small :: Config
small = def
{ skip = (not . after ["\\small"]) &&& (after ["\\normalsize"] ||| defaultSkip)
, unskip = (not . after ["\\normalsize"]) &&& (after ["\\small"] ||| defaultUnskip)
, replace = \caps -> pack "{\\footnotesize " `append` snoc caps '}'
}
whitelist :: [String] -> LaTeXElement -> Bool
whitelist names = liftM2 (||) (liftM2 (||) (liftM2 (||) isBlock isBBlock) isPrintable) (after names)
blacklist :: [String] -> LaTeXElement -> Bool
blacklist names = not . liftM2 (||) (liftM2 (||) isMath isComment) (after names)
after :: [String] -> LaTeXElement -> Bool
after names = liftM2 (&&) (liftM2 (||) isMacro isEnvironment) (flip elem (map pack names) . name)
isolateWith :: [(String, String)] -> LaTeXElement -> Maybe Text
isolateWith names x
| isMacro x || isEnvironment x = findConfigName (name x) names
| otherwise = Nothing
findConfigName :: Text -> [(String, String)] -> Maybe Text
findConfigName name' = foldr fun Nothing
where fun (n,c) Nothing | pack n == name' = Just (pack c)
| otherwise = Nothing
fun _ x = x
data StopState
= None
| NewLine
| Stop
| NewSentence
deriving (Show, Eq)
instance Default StopState where
def = NewSentence