git.iko.soy/typeable/pandoc
on master help sign in
LaTeX writer: improve longtable output.

- Don't create minipages for regular paragraphs. - Put width and alignment information in the longtable column descriptors. - Closes #6883.

commit7c4d7db9c7b582c7eb574c8ef9381f41cd419a6e authorJohn MacFarlane <jgm@berkeley.edu> dateWed 25 Nov 2020, 15:42 (6 years ago) parentb50ac3a
2 files changed+61−41
data/templates/default.latex+1−1 src/Text/Pandoc/Writers/LaTeX.hs+60−40
data/templates/default.latex+1−1
@@ -256,7 +256,7 @@ $if(highlighting-macros)$
256256$highlighting-macros$
257257$endif$
258258$if(tables)$
259−\usepackage{longtable,booktabs}
259+\usepackage{longtable,booktabs,array}
260260\usepackage{calc} % for calculating minipage widths
261261$if(beamer)$
262262\usepackage{caption}
src/Text/Pandoc/Writers/LaTeX.hs+60−40
@@ -778,8 +778,17 @@ blockToLaTeX (Header level (id',classes,_) lst) = do
778778 return hdr
779779blockToLaTeX (Table _ blkCapt specs thead tbody tfoot) = do
780780 let (caption, aligns, widths, heads, rows) = toLegacyTable blkCapt specs thead tbody tfoot
781+ -- simple tables have to have simple cells:
782+ let isSimple [Plain _] = True
783+ isSimple [Para _] = True
784+ isSimple [] = True
785+ isSimple _ = False
786+ let widths' = if all (== 0) widths && not (all (all isSimple) rows)
787+ then replicate (length aligns)
788+ (1 / fromIntegral (length aligns))
789+ else widths
781790 (captionText, captForLof, captNotes) <- getCaption False caption
782− let toHeaders hs = do contents <- tableRowToLaTeX True aligns widths hs
791+ let toHeaders hs = do contents <- tableRowToLaTeX True aligns hs
783792 return ("\\toprule" $$ contents $$ "\\midrule")
784793 let removeNote (Note _) = Span ("", [], []) []
785794 removeNote x = x
@@ -796,8 +805,12 @@ blockToLaTeX (Table _ blkCapt specs thead tbody tfoot) = do
796805 then empty
797806 else "\\caption" <> captForLof <> braces captionText
798807 <> "\\tabularnewline"
799− rows' <- mapM (tableRowToLaTeX False aligns widths) rows
800− let colDescriptors = literal $ T.concat $ map toColDescriptor aligns
808+ rows' <- mapM (tableRowToLaTeX False aligns) rows
809+ let colDescriptors =
810+ (if all (== 0) widths'
811+ then hcat . map literal
812+ else (\xs -> cr <> nest 2 (vcat $ map literal xs))) $
813+ zipWith (toColDescriptor (length widths')) aligns widths'
801814 modify $ \s -> s{ stTable = True }
802815 notes <- notesToLaTeX <$> gets stNotes
803816 return $ "\\begin{longtable}[]" <>
@@ -832,13 +845,26 @@ getCaption externalNotes txt = do
832845 else return empty
833846 return (capt, captForLof, footnotes)
834847
835−toColDescriptor :: Alignment -> Text
836−toColDescriptor align =
848+toColDescriptor :: Int -> Alignment -> Double -> Text
849+toColDescriptor _numcols align 0 =
837850 case align of
838851 AlignLeft -> "l"
839852 AlignRight -> "r"
840853 AlignCenter -> "c"
841854 AlignDefault -> "l"
855+toColDescriptor numcols align width =
856+ T.pack $ printf
857+ ">{%s\\arraybackslash}p{(\\columnwidth - %d\\tabcolsep) * \\real{%0.2f}}"
858+ align'
859+ ((numcols - 1) * 2)
860+ width
861+ where
862+ align' :: String
863+ align' = case align of
864+ AlignLeft -> "\\raggedright"
865+ AlignRight -> "\\raggedleft"
866+ AlignCenter -> "\\centering"
867+ AlignDefault -> "\\raggedright"
842868
843869blockListToLaTeX :: PandocMonad m => [Block] -> LW m (Doc Text)
844870blockListToLaTeX lst =
@@ -847,21 +873,10 @@ blockListToLaTeX lst =
847873tableRowToLaTeX :: PandocMonad m
848874 => Bool
849875 -> [Alignment]
850− -> [Double]
851876 -> [[Block]]
852877 -> LW m (Doc Text)
853−tableRowToLaTeX header aligns widths cols = do
854− let isSimple [Plain _] = True
855− isSimple [Para _] = True
856− isSimple [] = True
857− isSimple _ = False
858− -- simple tables have to have simple cells:
859− let widths' = if all (== 0) widths && not (all isSimple cols)
860− then replicate (length aligns)
861− (1 / fromIntegral (length aligns))
862− else widths
863− let numcols = length widths'
864− cells <- mapM (tableCellToLaTeX header numcols) $ zip3 widths' aligns cols
878+tableRowToLaTeX header aligns cols = do
879+ cells <- mapM (tableCellToLaTeX header) $ zip aligns cols
865880 return $ hsep (intersperse "&" cells) <> " \\\\ \\addlinespace"
866881
867882-- For simple latex tables (without minipages or parboxes),
@@ -889,34 +904,39 @@ displayMathToInline (Math DisplayMath x) = Math InlineMath x
889904displayMathToInline x = x
890905
891906tableCellToLaTeX :: PandocMonad m
892− => Bool -> Int -> (Double, Alignment, [Block])
907+ => Bool -> (Alignment, [Block])
893908 -> LW m (Doc Text)
894−tableCellToLaTeX _ _ (0, _, blocks) =
895− blockListToLaTeX $ walk fixLineBreaks $ walk displayMathToInline blocks
896−tableCellToLaTeX header numcols (width, align, blocks) = do
909+tableCellToLaTeX header (align, blocks) = do
897910 beamer <- gets stBeamer
898911 externalNotes <- gets stExternalNotes
899912 inMinipage <- gets stInMinipage
900913 -- See #5367 -- footnotehyper/footnote don't work in beamer,
901914 -- so we need to produce the notes outside the table...
902− modify $ \st -> st{ stExternalNotes = beamer,
903− stInMinipage = True }
904− cellContents <- blockListToLaTeX blocks
905− modify $ \st -> st{ stExternalNotes = externalNotes,
906− stInMinipage = inMinipage }
907− let valign = text $ if header then "[b]" else "[t]"
908− let halign = case align of
909− AlignLeft -> "\\raggedright"
910− AlignRight -> "\\raggedleft"
911− AlignCenter -> "\\centering"
912− AlignDefault -> "\\raggedright"
913− return $ "\\begin{minipage}" <> valign <>
914− braces (text (printf
915− "(\\columnwidth - %d\\tabcolsep) * \\real{%.2f}"
916− (2 * (numcols - 1)) width)) <>
917− halign <> cr <> cellContents <> cr <>
918− "\\end{minipage}"
919−-- (\columnwidth - 8\tabcolsep) * \real{0.15}
915+ modify $ \st -> st{ stExternalNotes = beamer }
916+ let isPlainOrPara Para{} = True
917+ isPlainOrPara Plain{} = True
918+ isPlainOrPara _ = False
919+ result <-
920+ if all isPlainOrPara blocks
921+ then
922+ blockListToLaTeX $ walk fixLineBreaks $ walk displayMathToInline blocks
923+ else do
924+ modify $ \st -> st{ stInMinipage = True }
925+ cellContents <- blockListToLaTeX blocks
926+ modify $ \st -> st{ stInMinipage = inMinipage }
927+ let valign = text $ if header then "[b]" else "[t]"
928+ let halign = case align of
929+ AlignLeft -> "\\raggedright"
930+ AlignRight -> "\\raggedleft"
931+ AlignCenter -> "\\centering"
932+ AlignDefault -> "\\raggedright"
933+ return $ "\\begin{minipage}" <> valign <>
934+ braces "\\linewidth" <> halign <> cr <>
935+ cellContents <> cr <>
936+ "\\end{minipage}"
937+ modify $ \st -> st{ stExternalNotes = externalNotes }
938+ return result
939+
920940
921941notesToLaTeX :: [Doc Text] -> Doc Text
922942notesToLaTeX [] = empty