2007-07-04 22:21:08 +00:00
|
|
|
module Text.Pandoc.Blocks
|
2007-07-04 18:53:12 +00:00
|
|
|
(
|
2007-07-04 22:21:08 +00:00
|
|
|
TextBlock (..),
|
2007-07-04 18:53:12 +00:00
|
|
|
docToBlock,
|
|
|
|
blockToDoc,
|
|
|
|
widthOfBlock,
|
|
|
|
heightOfBlock,
|
|
|
|
hcatBlocks,
|
2007-07-04 22:21:08 +00:00
|
|
|
hsepBlocks,
|
|
|
|
centerAlignBlock,
|
|
|
|
leftAlignBlock,
|
|
|
|
rightAlignBlock
|
2007-07-04 18:53:12 +00:00
|
|
|
)
|
|
|
|
where
|
|
|
|
|
|
|
|
import Text.PrettyPrint
|
|
|
|
import Data.List (transpose, intersperse)
|
|
|
|
|
|
|
|
data TextBlock = TextBlock Int Int [String] -- width height lines
|
|
|
|
instance Show TextBlock where
|
|
|
|
show x = show $ blockToDoc x
|
|
|
|
|
|
|
|
docToBlock :: Int -> Doc -> TextBlock
|
|
|
|
docToBlock width doc =
|
|
|
|
let rendered = renderStyle (style {lineLength = width,
|
|
|
|
ribbonsPerLine = 1}) doc
|
|
|
|
lns = lines rendered
|
|
|
|
chop [] = []
|
|
|
|
chop (l:ls) = if length l > width
|
|
|
|
then (take width l):(chop ((drop width l):ls))
|
|
|
|
else l:(chop ls)
|
|
|
|
lns' = chop lns
|
|
|
|
in TextBlock width (length lns') lns'
|
|
|
|
|
|
|
|
blockToDoc :: TextBlock -> Doc
|
|
|
|
blockToDoc (TextBlock _ _ lns) =
|
|
|
|
if null lns
|
|
|
|
then empty
|
2007-07-04 22:21:08 +00:00
|
|
|
else vcat $ map text lns
|
2007-07-04 18:53:12 +00:00
|
|
|
|
|
|
|
widthOfBlock :: TextBlock -> Int
|
|
|
|
widthOfBlock (TextBlock width _ _) = width
|
|
|
|
|
|
|
|
heightOfBlock :: TextBlock -> Int
|
|
|
|
heightOfBlock (TextBlock _ height _) = height
|
|
|
|
|
|
|
|
-- pad line out to width using spaces
|
|
|
|
hPad :: Int -> String -> String
|
|
|
|
hPad width line =
|
|
|
|
let lineLength = length line
|
|
|
|
in if lineLength <= width
|
|
|
|
then line ++ replicate (width - lineLength) ' '
|
|
|
|
else take width line
|
|
|
|
|
|
|
|
hcatBlocks :: [TextBlock] -> TextBlock
|
|
|
|
hcatBlocks [] = TextBlock 0 0 []
|
|
|
|
hcatBlocks ((TextBlock width1 height1 lns1):xs) =
|
|
|
|
let (TextBlock width2 height2 lns2) = hcatBlocks xs
|
|
|
|
height = max height1 height2
|
|
|
|
width = width1 + width2
|
|
|
|
lns1' = map (hPad width1) $ lns1 ++ replicate (height - height1) ""
|
|
|
|
lns2' = lns2 ++ replicate (height - height2) ""
|
|
|
|
lns = zipWith (++) lns1' lns2'
|
|
|
|
in TextBlock width height lns
|
|
|
|
|
|
|
|
hsepBlocks = hcatBlocks . (intersperse (TextBlock 1 1 [" "]))
|
|
|
|
|
2007-07-04 22:21:08 +00:00
|
|
|
isWhitespace x = x `elem` " \t"
|
|
|
|
|
|
|
|
leftAlignBlock :: TextBlock -> TextBlock
|
|
|
|
leftAlignBlock (TextBlock width height lns) =
|
|
|
|
TextBlock width height $
|
|
|
|
map (dropWhile isWhitespace) lns
|
|
|
|
|
|
|
|
rightAlignBlock :: TextBlock -> TextBlock
|
|
|
|
rightAlignBlock (TextBlock width height lns) =
|
|
|
|
let rightAlignLine ln =
|
|
|
|
let (spaces, rest) = span isWhitespace $ reverse $ hPad width ln
|
|
|
|
in reverse (rest ++ spaces)
|
|
|
|
in TextBlock width height $ map rightAlignLine lns
|
|
|
|
|
|
|
|
centerAlignBlock :: TextBlock -> TextBlock
|
|
|
|
centerAlignBlock (TextBlock width height lns) =
|
|
|
|
let centerAlignLine ln =
|
|
|
|
let ln' = hPad width ln
|
|
|
|
(startSpaces, rest) = span isWhitespace ln'
|
|
|
|
endSpaces = takeWhile isWhitespace (reverse ln')
|
|
|
|
numSpaces = length (startSpaces ++ endSpaces)
|
|
|
|
startSpaces' = replicate (quot numSpaces 2) ' '
|
|
|
|
in startSpaces' ++ rest
|
|
|
|
in TextBlock width height $ map centerAlignLine lns
|
|
|
|
|