@@ -35,6 +35,7 @@ module Text.Pandoc.Pretty (
37 , blankline
37 , blankline
@@ -100,7 +101,7 @@ data D = Text Int String
100 | BreakingSpace
101 | BreakingSpace
101 | CarriageReturn
102 | CarriageReturn
102 | NewLine
103 | NewLine
103− | BlankLine
104+ | BlankLines Int -- number of blank lines
104 deriving (Show)
105 deriving (Show)
106newtype Doc = Doc { unDoc :: Seq D }
107newtype Doc = Doc { unDoc :: Seq D }
@@ -113,7 +114,7 @@ isBlank :: D -> Bool
113isBlank BreakingSpace = True
114isBlank BreakingSpace = True
114isBlank CarriageReturn = True
115isBlank CarriageReturn = True
115isBlank NewLine = True
116isBlank NewLine = True
116−isBlank BlankLine = True
117+isBlank (BlankLines _) = True
117isBlank (Text _ (c:_)) = isSpace c
118isBlank (Text _ (c:_)) = isSpace c
118isBlank _ = False
119isBlank _ = False
@@ -190,7 +191,7 @@ vsep = foldr ($+$) empty
190nestle :: Doc -> Doc
191nestle :: Doc -> Doc
191nestle (Doc d) = Doc $ go d
192nestle (Doc d) = Doc $ go d
192 where go x = case viewl x of
193 where go x = case viewl x of
193− (BlankLine :< rest) -> go rest
194+ (BlankLines _ :< rest) -> go rest
194 (NewLine :< rest) -> go rest
195 (NewLine :< rest) -> go rest
@@ -203,7 +204,7 @@ chomp d = Doc (fromList dl')
203 go (BreakingSpace : xs) = go xs
204 go (BreakingSpace : xs) = go xs
204 go (CarriageReturn : xs) = go xs
205 go (CarriageReturn : xs) = go xs
205 go (NewLine : xs) = go xs
206 go (NewLine : xs) = go xs
206− go (BlankLine : xs) = go xs
207+ go (BlankLines _ : xs) = go xs
207 go (Prefixed s d' : xs) = Prefixed s (chomp d') : xs
208 go (Prefixed s d' : xs) = Prefixed s (chomp d') : xs
208 go xs = xs
209 go xs = xs
@@ -216,9 +217,10 @@ outp off s | off < 0 = do -- offset < 0 means newline characters
216 let pref = reverse $ dropWhile isSpace $ reverse rawpref
217 let pref = reverse $ dropWhile isSpace $ reverse rawpref
217 modify $ \st -> st{ output = fromString pref : output st
218 modify $ \st -> st{ output = fromString pref : output st
218 , column = column st + realLength pref }
219 , column = column st + realLength pref }
220+ let numnewlines = length $ takeWhile (=='\n') $ reverse s
219 modify $ \st -> st { output = fromString s : output st
221 modify $ \st -> st { output = fromString s : output st
220 , column = 0
222 , column = 0
221− , newlines = newlines st + 1 }
223+ , newlines = newlines st + numnewlines }
222outp off s = do -- offset >= 0 (0 might be combining char)
224outp off s = do -- offset >= 0 (0 might be combining char)
223 st' <- get
225 st' <- get
224 let pref = prefix st'
226 let pref = prefix st'
@@ -277,15 +279,11 @@ renderList (BeforeNonBlank d : xs) =
277 | otherwise -> renderDoc d >> renderList xs
279 | otherwise -> renderDoc d >> renderList xs
278 [] -> renderList xs
280 [] -> renderList xs
280−renderList (BlankLine : xs) = do
282+renderList (BlankLines num : xs) = do
281 st <- get
283 st <- get
282 case output st of
284 case output st of
283− _ | newlines st > 1 || null xs -> return ()
285+ _ | newlines st > num || null xs -> return ()
284− _ | column st == 0 -> do
286+ | otherwise -> replicateM_ (1 + num - newlines st) (outp (-1) "\n")
289 renderList xs
287 renderList xs
291renderList (CarriageReturn : xs) = do
289renderList (CarriageReturn : xs) = do
@@ -302,7 +300,7 @@ renderList (NewLine : xs) = do
303renderList (BreakingSpace : CarriageReturn : xs) = renderList (CarriageReturn:xs)
301renderList (BreakingSpace : CarriageReturn : xs) = renderList (CarriageReturn:xs)
304renderList (BreakingSpace : NewLine : xs) = renderList (NewLine:xs)
302renderList (BreakingSpace : NewLine : xs) = renderList (NewLine:xs)
305−renderList (BreakingSpace : BlankLine : xs) = renderList (BlankLine:xs)
303+renderList (BreakingSpace : BlankLines n : xs) = renderList (BlankLines n:xs)
306renderList (BreakingSpace : BreakingSpace : xs) = renderList (BreakingSpace:xs)
304renderList (BreakingSpace : BreakingSpace : xs) = renderList (BreakingSpace:xs)
307renderList (BreakingSpace : xs) = do
305renderList (BreakingSpace : xs) = do
308 let isText (Text _ _) = True
306 let isText (Text _ _) = True
@@ -383,9 +381,13 @@ cr = Doc $ singleton CarriageReturn
384-- | Inserts a blank line unless one exists already.
382-- | Inserts a blank line unless one exists already.
385-- (@blankline <> blankline@ has the same effect as @blankline@.
383-- (@blankline <> blankline@ has the same effect as @blankline@.
386−-- If you want multiple blank lines, use @text "\\n\\n"@.
387blankline :: Doc
384blankline :: Doc
388−blankline = Doc $ singleton BlankLine
385+blankline = Doc $ singleton (BlankLines 1)
387+-- | Inserts a blank lines unless they exists already.
388+-- (@blanklines m <> blanklines n@ has the same effect as @blankline (max m n)@.
389+blanklines :: Int -> Doc
390+blanklines n = Doc $ singleton (BlankLines n)
390-- | Uses the specified string as a prefix for every line of
392-- | Uses the specified string as a prefix for every line of
391-- the inside document (except the first, if not at the beginning
393-- the inside document (except the first, if not at the beginning