module Text.LaTeX.LambdaTeX.Selection.Internal where import Data.List (isPrefixOf) import Text.LaTeX.LambdaTeX.Selection.Types import Text.LaTeX.LambdaTeX.Types -- | Whether a part is selected by a given list of selectors. -- -- A part is selected if: -- -- All parts are selected or -- It it is matched and not ignored. selects :: Part -> [Selector] -> Bool selects (Part ps) ss = go ps ss False where go :: [Text] -> [Selector] -> Bool -> Bool go _ [] b = b go ps (All:ss) _ = go ps ss True go ps ((Match s):ss) b = if (ps `isPrefixOf` s || s `isPrefixOf` ps) then go ps ss True else go ps ss b go ps ((Ignore s):ss) True = if s `isPrefixOf` ps then go ps ss False else go ps ss True go ps ((Ignore _):ss) False = go ps ss False -- | Whether the current part is selected to be generated isSelected :: Monad m => ΛTeXT m Bool isSelected = do part <- currentPart sels <- λasks configSelection return $ selects part sels -- * Current part Helpers -- | Returns the current part from the ΛTeX state currentPart :: Monad m => ΛTeXT m Part currentPart = λgets stateCurrentPart -- | Execute the following function with a given sub-part name inPart :: Monad m => Text -> ΛTeXT m () -> ΛTeXT m () inPart partname func = do pushCurrentPart partname func popCurrentPart -- | Push a new part name onto the current part stack -- -- WARNING: This should never be used outside of 'inPart' pushCurrentPart :: Monad m => Text -> ΛTeXT m () pushCurrentPart partname = λmodify (\s -> s { stateCurrentPart = pushPart (stateCurrentPart s) partname}) -- | Pop a part name off the current part stack -- -- WARNING: This should never be used outside of 'inPart' popCurrentPart :: Monad m => ΛTeXT m () popCurrentPart = λmodify (\s -> s { stateCurrentPart = popPart $ stateCurrentPart s }) -- * Text Helpers -- | Split a string on a dot. -- This can be useful to convert from a 'Selector's textual representation back to a selector -- -- > split = splitOn '.' split :: String -> [String] split = splitOn '.' -- | Split a string on a specific character splitOn :: Char -> String -> [String] splitOn c s = go s [] where go :: String -> String -> [String] go [] s = [s] go (sc:ss) acc | sc == c = acc : go [] ss | otherwise = go ss (acc ++ [sc])