git.iko.soy/typeable/pandoc
on master help sign in
More refactoring of grid table code.
commit6a8fa53f6cb276d034c607f58d3c458a712b6eae authorJohn MacFarlane <jgm@berkeley.edu> dateMon 5 Jul 2010, 23:43 (16 years ago) parentba19dff
3 files changed+85−107
src/Text/Pandoc/Parsing.hs+60−8 src/Text/Pandoc/Readers/Markdown.hs+19−47 src/Text/Pandoc/Readers/RST.hs+6−52
src/Text/Pandoc/Parsing.hs+60−8
@@ -53,10 +53,8 @@ module Text.Pandoc.Parsing ( (>>~),
5353 anyOrderedListMarker,
5454 orderedListMarker,
5555 charRef,
56− gridTableHeader,
57− gridTableRow,
58− gridTableSep,
59− gridTableFooter,
56+ tableWith,
57+ gridTableWith,
6058 readWith,
6159 testStringWith,
6260 ParserState (..),
@@ -408,7 +406,58 @@ charRef = do
408406 c <- characterReference
409407 return $ Str [c]
410408
411−-- grid tables, common to RST and Markdown:
409+-- | Parse a table using 'headerParser', 'rowParser',
410+-- 'lineParser', and 'footerParser'.
411+tableWith :: GenParser Char ParserState ([[Block]], [Alignment], [Int])
412+ -> ([Int] -> GenParser Char ParserState [[Block]])
413+ -> GenParser Char ParserState sep
414+ -> GenParser Char ParserState end
415+ -> GenParser Char ParserState [Inline]
416+ -> GenParser Char ParserState Block
417+tableWith headerParser rowParser lineParser footerParser captionParser = try $ do
418+ (heads, aligns, indices) <- headerParser
419+ lines' <- rowParser indices `sepEndBy` lineParser
420+ footerParser
421+ caption <- option [] captionParser
422+ state <- getState
423+ let numColumns = stateColumns state
424+ let widths = widthsFromIndices numColumns indices
425+ return $ Table caption aligns widths heads lines'
426+
427+-- Calculate relative widths of table columns, based on indices
428+widthsFromIndices :: Int -- Number of columns on terminal
429+ -> [Int] -- Indices
430+ -> [Double] -- Fractional relative sizes of columns
431+widthsFromIndices _ [] = []
432+widthsFromIndices numColumns indices =
433+ let lengths' = zipWith (-) indices (0:indices)
434+ lengths = reverse $
435+ case reverse lengths' of
436+ [] -> []
437+ [x] -> [x]
438+ -- compensate for the fact that intercolumn
439+ -- spaces are counted in widths of all columns
440+ -- but the last...
441+ (x:y:zs) -> if x < y && y - x <= 2
442+ then y:y:zs
443+ else x:y:zs
444+ totLength = sum lengths
445+ quotient = if totLength > numColumns
446+ then fromIntegral totLength
447+ else fromIntegral numColumns
448+ fracs = map (\l -> (fromIntegral l) / quotient) lengths in
449+ tail fracs
450+
451+-- Parse a grid table: starts with row of '-' on top, then header
452+-- (which may be grid), then the rows,
453+-- which may be grid, separated by blank lines, and
454+-- ending with a footer (dashed line followed by blank line).
455+gridTableWith :: GenParser Char ParserState Block -- ^ Block parser
456+ -> GenParser Char ParserState [Inline] -- ^ Caption parser
457+ -> Bool -- ^ Headerless table
458+ -> GenParser Char ParserState Block
459+gridTableWith block tableCaption headless =
460+ tableWith (gridTableHeader headless block) (gridTableRow block) (gridTableSep '-') gridTableFooter tableCaption
412461
413462gridTableSplitLine :: [Int] -> String -> [String]
414463gridTableSplitLine indices line =
@@ -433,8 +482,9 @@ gridTableSep ch = try $ gridDashedLines ch >> return '\n'
433482
434483-- | Parse header for a grid table.
435484gridTableHeader :: Bool -- ^ Headerless table
436− -> GenParser Char ParserState ([String], [Alignment], [Int])
437−gridTableHeader headless = try $ do
485+ -> GenParser Char ParserState Block
486+ -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
487+gridTableHeader headless block = try $ do
438488 optional blanklines
439489 dashes <- gridDashedLines '-'
440490 rawContent <- if headless
@@ -453,7 +503,9 @@ gridTableHeader headless = try $ do
453503 then replicate (length dashes) ""
454504 else map (intercalate " ") $ transpose
455505 $ map (gridTableSplitLine indices) rawContent
456− return (rawHeads, aligns, indices)
506+ heads <- mapM (parseFromString $ many block) $
507+ map removeLeadingTrailingSpace rawHeads
508+ return (heads, aligns, indices)
457509
458510gridTableRawLine :: [Int] -> GenParser Char ParserState [String]
459511gridTableRawLine indices = do
src/Text/Pandoc/Readers/Markdown.hs+19−47
@@ -717,7 +717,7 @@ dashedLine ch = do
717717-- Parse a table header with dashed lines of '-' preceded by
718718-- one (or zero) line of text.
719719simpleTableHeader :: Bool -- ^ Headerless table
720− -> GenParser Char ParserState ([[Char]], [Alignment], [Int])
720+ -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
721721simpleTableHeader headless = try $ do
722722 rawContent <- if headless
723723 then return ""
@@ -736,7 +736,9 @@ simpleTableHeader headless = try $ do
736736 let rawHeads' = if headless
737737 then replicate (length dashes) ""
738738 else rawHeads
739− return (rawHeads', aligns, indices)
739+ heads <- mapM (parseFromString (many plain)) $
740+ map removeLeadingTrailingSpace rawHeads'
741+ return (heads, aligns, indices)
740742
741743-- Parse a table footer - dashed lines followed by blank line.
742744tableFooter :: GenParser Char ParserState [Char]
@@ -765,34 +767,9 @@ multilineRow :: [Int]
765767 -> GenParser Char ParserState [[Block]]
766768multilineRow indices = do
767769 colLines <- many1 (rawTableLine indices)
768− optional blanklines
769770 let cols = map unlines $ transpose colLines
770771 mapM (parseFromString (many plain)) cols
771772
772−-- Calculate relative widths of table columns, based on indices
773−widthsFromIndices :: Int -- Number of columns on terminal
774− -> [Int] -- Indices
775− -> [Double] -- Fractional relative sizes of columns
776−widthsFromIndices _ [] = []
777−widthsFromIndices numColumns indices =
778− let lengths' = zipWith (-) indices (0:indices)
779− lengths = reverse $
780− case reverse lengths' of
781− [] -> []
782− [x] -> [x]
783− -- compensate for the fact that intercolumn
784− -- spaces are counted in widths of all columns
785− -- but the last...
786− (x:y:zs) -> if x < y && y - x <= 2
787− then y:y:zs
788− else x:y:zs
789− totLength = sum lengths
790− quotient = if totLength > numColumns
791− then fromIntegral totLength
792− else fromIntegral numColumns
793− fracs = map (\l -> (fromIntegral l) / quotient) lengths in
794− tail fracs
795−
796773-- Parses a table caption: inlines beginning with 'Table:'
797774-- and followed by blank lines.
798775tableCaption :: GenParser Char ParserState [Inline]
@@ -803,27 +780,14 @@ tableCaption = try $ do
803780 blanklines
804781 return $ normalizeSpaces result
805782
806−-- Parse a table using 'headerParser', 'lineParser', and 'footerParser'.
807−tableWith :: GenParser Char ParserState ([[Char]], [Alignment], [Int])
808− -> ([Int] -> GenParser Char ParserState [[Block]])
809− -> GenParser Char ParserState end
810− -> GenParser Char ParserState Block
811−tableWith headerParser lineParser footerParser = try $ do
812− (rawHeads, aligns, indices) <- headerParser
813− lines' <- many1Till (lineParser indices) footerParser
814− caption <- option [] tableCaption
815− heads <- mapM (parseFromString (many plain)) rawHeads
816− state <- getState
817− let numColumns = stateColumns state
818− let widths = widthsFromIndices numColumns indices
819− return $ Table caption aligns widths heads lines'
820−
821783-- Parse a simple table with '---' header and one line per row.
822784simpleTable :: Bool -- ^ Headerless table
823785 -> GenParser Char ParserState Block
824786simpleTable headless = do
825787 Table c a _w h l <- tableWith (simpleTableHeader headless) tableLine
826− (if headless then tableFooter else tableFooter <|> blanklines)
788+ (return ())
789+ (if headless then tableFooter else tableFooter <|> blanklines)
790+ tableCaption
827791 -- Simple tables get 0s for relative column widths (i.e., use default)
828792 return $ Table c a (replicate (length a) 0) h l
829793
@@ -834,10 +798,10 @@ simpleTable headless = do
834798multilineTable :: Bool -- ^ Headerless table
835799 -> GenParser Char ParserState Block
836800multilineTable headless =
837− tableWith (multilineTableHeader headless) multilineRow tableFooter
801+ tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter tableCaption
838802
839803multilineTableHeader :: Bool -- ^ Headerless table
840− -> GenParser Char ParserState ([String], [Alignment], [Int])
804+ -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
841805multilineTableHeader headless = try $ do
842806 if headless
843807 then return '\n'
@@ -861,7 +825,9 @@ multilineTableHeader headless = try $ do
861825 let rawHeads = if headless
862826 then replicate (length dashes) ""
863827 else map (intercalate " ") rawHeadsList
864− return ((map removeLeadingTrailingSpace rawHeads), aligns, indices)
828+ heads <- mapM (parseFromString (many plain)) $
829+ map removeLeadingTrailingSpace rawHeads
830+ return (heads, aligns, indices)
865831
866832-- Returns an alignment type for a table, based on a list of strings
867833-- (the rows of the column header) and a number (the length of the
@@ -881,9 +847,15 @@ alignType strLst len =
881847 (True, True) -> AlignCenter
882848 (False, False) -> AlignDefault
883849
850+gridTable :: Bool -- ^ Headerless table
851+ -> GenParser Char ParserState Block
852+gridTable = gridTableWith block tableCaption
853+
854+-- TODO - add grid tables here...add tests for markdown grid tables...document markdown grid tables.
884855table :: GenParser Char ParserState Block
885856table = multilineTable False <|> simpleTable True <|>
886− simpleTable False <|> multilineTable True <?> "table"
857+ simpleTable False <|> multilineTable True <|>
858+ gridTable False <|> gridTable True <?> "table"
887859
888860--
889861-- inline
src/Text/Pandoc/Readers/RST.hs+6−52
@@ -636,32 +636,8 @@ simpleTableSplitLine indices line =
636636 map removeLeadingTrailingSpace
637637 $ tail $ splitByIndices (init indices) line
638638
639−-- Calculate relative widths of table columns, based on indices
640−widthsFromIndices :: Int -- Number of columns on terminal
641− -> [Int] -- Indices
642− -> [Double] -- Fractional relative sizes of columns
643−widthsFromIndices _ [] = []
644−widthsFromIndices numColumns indices =
645− let lengths' = zipWith (-) indices (0:indices)
646− lengths = reverse $
647− case reverse lengths' of
648− [] -> []
649− [x] -> [x]
650− -- compensate for the fact that intercolumn
651− -- spaces are counted in widths of all columns
652− -- but the last...
653− (x:y:zs) -> if x < y && y - x <= 2
654− then y:y:zs
655− else x:y:zs
656− totLength = sum lengths
657− quotient = if totLength > numColumns
658− then fromIntegral totLength
659− else fromIntegral numColumns
660− fracs = map (\l -> (fromIntegral l) / quotient) lengths in
661− tail fracs
662−
663639simpleTableHeader :: Bool -- ^ Headerless table
664− -> GenParser Char ParserState ([[Char]], [Alignment], [Int])
640+ -> GenParser Char ParserState ([[Block]], [Alignment], [Int])
665641simpleTableHeader headless = try $ do
666642 optional blanklines
667643 rawContent <- if headless
@@ -675,45 +651,23 @@ simpleTableHeader headless = try $ do
675651 let rawHeads = if headless
676652 then replicate (length dashes) ""
677653 else simpleTableSplitLine indices rawContent
678− return (rawHeads, aligns, indices)
679−
680−-- Parse a table using 'headerParser', 'lineParser', and 'footerParser'.
681−tableWith :: GenParser Char ParserState ([[Char]], [Alignment], [Int])
682− -> ([Int]
683− -> GenParser Char ParserState [[Block]])
684− -> GenParser Char ParserState sep
685− -> GenParser Char ParserState end
686− -> GenParser Char ParserState Block
687−tableWith headerParser rowParser lineParser footerParser = try $ do
688− (rawHeads, aligns, indices) <- headerParser
689− lines' <- rowParser indices `sepEndBy` lineParser
690− footerParser
691− heads <- mapM (parseFromString (many plain)) rawHeads
692− state <- getState
693− let captions = [] -- no notion of captions in RST
694− let numColumns = stateColumns state
695− let widths = widthsFromIndices numColumns indices
696− return $ Table captions aligns widths heads lines'
654+ heads <- mapM (parseFromString (many plain)) $
655+ map removeLeadingTrailingSpace rawHeads
656+ return (heads, aligns, indices)
697657
698658-- Parse a simple table with '---' header and one line per row.
699659simpleTable :: Bool -- ^ Headerless table
700660 -> GenParser Char ParserState Block
701661simpleTable headless = do
702− Table c a _w h l <- tableWith (simpleTableHeader headless) simpleTableRow sep simpleTableFooter
662+ Table c a _w h l <- tableWith (simpleTableHeader headless) simpleTableRow sep simpleTableFooter (return [])
703663 -- Simple tables get 0s for relative column widths (i.e., use default)
704664 return $ Table c a (replicate (length a) 0) h l
705665 where
706666 sep = return () -- optional (simpleTableSep '-')
707667
708−-- Parse a grid table: starts with row of '-' on top, then header
709−-- (which may be grid), then the rows,
710−-- which may be grid, separated by blank lines, and
711−-- ending with a footer (dashed line followed by blank line).
712668gridTable :: Bool -- ^ Headerless table
713669 -> GenParser Char ParserState Block
714−gridTable headless =
715− tableWith (gridTableHeader headless) (gridTableRow block) (gridTableSep '-') gridTableFooter
716−
670+gridTable = gridTableWith block (return [])
717671
718672table :: GenParser Char ParserState Block
719673table = gridTable False <|> simpleTable False <|>