aboutsummaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2016-01-18 11:38:44 +0000
committerGregor Kleen <gkleen@yggdrasil.li>2016-01-18 11:38:44 +0000
commitabb427bdccfe78649f5d75654a8179093201609c (patch)
tree3c2fbed64af3b1eb4a50a098655be1f109e743fa /spec
parent1ec5c1cb2f118c906a27b3763c73c0098fe67b4a (diff)
downloadthermoprint-abb427bdccfe78649f5d75654a8179093201609c.tar
thermoprint-abb427bdccfe78649f5d75654a8179093201609c.tar.gz
thermoprint-abb427bdccfe78649f5d75654a8179093201609c.tar.bz2
thermoprint-abb427bdccfe78649f5d75654a8179093201609c.tar.xz
thermoprint-abb427bdccfe78649f5d75654a8179093201609c.zip
Moved handling of lines in block context
Now allows arbitrary (instead of prefix only) switching between block and line contexts
Diffstat (limited to 'spec')
-rw-r--r--spec/src/Thermoprint/Printout/BBCode.hs24
1 files changed, 21 insertions, 3 deletions
diff --git a/spec/src/Thermoprint/Printout/BBCode.hs b/spec/src/Thermoprint/Printout/BBCode.hs
index 8825732..ce2aa43 100644
--- a/spec/src/Thermoprint/Printout/BBCode.hs
+++ b/spec/src/Thermoprint/Printout/BBCode.hs
@@ -29,6 +29,8 @@ import Data.Typeable (Typeable)
29import Data.Bifunctor (bimap, first) 29import Data.Bifunctor (bimap, first)
30import Control.Monad (join) 30import Control.Monad (join)
31 31
32import Data.List (groupBy)
33
32import Text.BBCode (DomForest, DomTree(..), TreeError(..)) 34import Text.BBCode (DomForest, DomTree(..), TreeError(..))
33import qualified Text.BBCode as Raw (bbcode, BBCodeError(..)) 35import qualified Text.BBCode as Raw (bbcode, BBCodeError(..))
34 36
@@ -63,6 +65,7 @@ data ParseResult = RBlock Block -- ^ Parses only as 'Block'
63 | RLine Line -- ^ Parses only as 'Line' 65 | RLine Line -- ^ Parses only as 'Line'
64 | RAmbiguous Block Line -- ^ Parses as either 'Block' or 'Line' depending on context 66 | RAmbiguous Block Line -- ^ Parses as either 'Block' or 'Line' depending on context
65 | RNoParse SemanticError SemanticError -- ^ Does not parse as either 'Block' or 'Line' 67 | RNoParse SemanticError SemanticError -- ^ Does not parse as either 'Block' or 'Line'
68 deriving (Show)
66 69
67-- | Current parser context 70-- | Current parser context
68data Context a where 71data Context a where
@@ -80,6 +83,16 @@ extract LineCtx (RNoParse _ lErr) = Left lErr
80extract BlockCtx _ = Left LineInBlockContext 83extract BlockCtx _ = Left LineInBlockContext
81extract LineCtx _ = Left BlockInLineContext 84extract LineCtx _ = Left BlockInLineContext
82 85
86hasBlockCtx :: ParseResult -> Bool
87-- ^ Result can be 'extract'ed in a 'Block' 'Context'
88hasBlockCtx (RLine _) = False
89hasBlockCtx _ = True
90
91hasLineCtx :: ParseResult -> Bool
92-- ^ Result can be 'extract'ed in a 'Line' 'Context'
93hasLineCtx (RBlock _) = False
94hasLineCtx _ = True
95
83bbcode :: Text -> Either BBCodeError Printout 96bbcode :: Text -> Either BBCodeError Printout
84-- ^ Parse BBCode 97-- ^ Parse BBCode
85bbcode = join . fmap (first SemanticError) . bimap morph' morph . Raw.bbcode 98bbcode = join . fmap (first SemanticError) . bimap morph' morph . Raw.bbcode
@@ -88,7 +101,7 @@ morph :: DomForest -> Either SemanticError Printout
88-- ^ Parse a list of paragraphs 101-- ^ Parse a list of paragraphs
89-- 102--
90-- Since we permit only cooked input via 'Raw' 'Paragraph' is identical to 'Block' 103-- Since we permit only cooked input via 'Raw' 'Paragraph' is identical to 'Block'
91morph f = Seq.fromList <$> mapM (\t -> Seq.singleton . Cooked <$> parse BlockCtx t) f 104morph = fmap Seq.fromList . mapM (\t -> Seq.singleton . Cooked <$> parse BlockCtx t)
92 105
93parseDom :: DomTree -> ParseResult 106parseDom :: DomTree -> ParseResult
94-- ^ Invoke 'asLine' and 'asBlock' to parse a single 'DomTree' 107-- ^ Invoke 'asLine' and 'asBlock' to parse a single 'DomTree'
@@ -107,7 +120,6 @@ parseDom (Element t attrs cs)
107mergeResult :: Monoid a => Context a -> [ParseResult] -> Either SemanticError a 120mergeResult :: Monoid a => Context a -> [ParseResult] -> Either SemanticError a
108-- ^ Merge a list of 'ParseResults' in a certain 'Context' 121-- ^ Merge a list of 'ParseResults' in a certain 'Context'
109mergeResult _ [] = Right mempty 122mergeResult _ [] = Right mempty
110mergeResult BlockCtx xs@((RLine _):_) = bimap (const LineInBlockContext) Line $ mergeResult LineCtx xs
111mergeResult ctx (amb@(RAmbiguous _ _):xs) = mappend <$> extract ctx amb <*> mergeResult ctx xs 123mergeResult ctx (amb@(RAmbiguous _ _):xs) = mappend <$> extract ctx amb <*> mergeResult ctx xs
112mergeResult ctx (err@(RNoParse _ _):_) = extract ctx err 124mergeResult ctx (err@(RNoParse _ _):_) = extract ctx err
113mergeResult ctx (x:xs) = mappend <$> extract ctx x <*> mergeResult ctx xs 125mergeResult ctx (x:xs) = mappend <$> extract ctx x <*> mergeResult ctx xs
@@ -116,7 +128,13 @@ parse :: Monoid a => Context a -> [DomTree] -> Either SemanticError a
116-- ^ Parse a list of 'DomTree's in a certain 'Context' 128-- ^ Parse a list of 'DomTree's in a certain 'Context'
117-- 129--
118-- @parse ctx = 'mergeResult' ctx . map 'parseDom'@ 130-- @parse ctx = 'mergeResult' ctx . map 'parseDom'@
119parse ctx = mergeResult ctx . map parseDom 131parse BlockCtx = fmap mconcat . mapM mergeResult' . groupBy sameCtx . map parseDom
132 where
133 sameCtx a b = (hasLineCtx a && hasLineCtx b) || (hasBlockCtx a && hasBlockCtx b)
134 mergeResult' xs
135 | hasLineCtx `all` xs = Line <$> mergeResult LineCtx xs
136 | otherwise = mergeResult BlockCtx xs
137parse ctx = mergeResult ctx . map parseDom
120 138
121asBlock :: CI Text -> [DomTree] -> Map (CI Text) Text -> Either SemanticError Block 139asBlock :: CI Text -> [DomTree] -> Map (CI Text) Text -> Either SemanticError Block
122asBlock "VSpace" _ = Right . VSpace . lookupAttr "height" True 1 140asBlock "VSpace" _ = Right . VSpace . lookupAttr "height" True 1