ConTeXt writer: Use xtables instead of Tables (#4223)

- Default to xtables for context output.
- Added `ntb` extension (affecting context writer only) to use Natural Tables instead.
- Added `Ext_ntb` constructor to `Extension` (API change).
This commit is contained in:
Henri Menke 2018-01-16 14:38:33 +13:00 committed by John MacFarlane
parent c6a55f8e9f
commit 6910267abf
8 changed files with 360 additions and 180 deletions

View file

@ -1960,6 +1960,14 @@ extensions to Emacs Muse markup.
Some aspects of [Pandoc's Markdown citation syntax](#citations) are also accepted
in `org` input.
#### Extension: `ntb` ####
In the `context` output format this enables the use of [Natural Tables
(TABLE)](http://wiki.contextgarden.net/TABLE) instead of the default
[Extreme Tables (xtables)](http://wiki.contextgarden.net/xtables).
Natural tables allow more fine-grained global customization but come
at a performance penalty compared to extreme tables.
Pandoc's Markdown
=================

View file

@ -92,6 +92,11 @@ $endif$
\setupthinrules[width=15em] % width of horizontal rules
\setupxtable[frame=off]
\setupxtable[head][topframe=on,bottomframe=on]
\setupxtable[body][]
\setupxtable[foot][bottomframe=on]
$for(header-includes)$
$header-includes$
$endfor$

View file

@ -133,6 +133,7 @@ data Extension =
| Ext_multiline_tables -- ^ Pandoc-style multiline tables
| Ext_native_divs -- ^ Use Div blocks for contents of <div> tags
| Ext_native_spans -- ^ Use Span inlines for contents of <span>
| Ext_ntb -- ^ ConTeXt Natural Tables
| Ext_old_dashes -- ^ -- = em, - before number = en
| Ext_pandoc_title_block -- ^ Pandoc title block
| Ext_pipe_tables -- ^ Pipe tables (as in PHP markdown extra)

View file

@ -55,6 +55,8 @@ data WriterState =
, stOptions :: WriterOptions -- writer options
}
data Tabl = Xtb | Ntb deriving (Show, Eq)
orderedListStyles :: [Char]
orderedListStyles = cycle "narg"
@ -252,33 +254,77 @@ blockToConTeXt HorizontalRule = return $ "\\thinrule" <> blankline
-- If this is ever executed, provide a default for the reference identifier.
blockToConTeXt (Header level attr lst) = sectionHeader attr level lst
blockToConTeXt (Table caption aligns widths heads rows) = do
let colDescriptor colWidth alignment = (case alignment of
AlignLeft -> 'l'
AlignRight -> 'r'
AlignCenter -> 'c'
AlignDefault -> 'l'):
if colWidth == 0
then "|"
else ("p(" ++ printf "%.2f" colWidth ++ "\\textwidth)|")
let colDescriptors = "|" ++ concat (
zipWith colDescriptor widths aligns)
headers <- if all null heads
then return empty
else liftM ($$ "\\HL") $ tableRowToConTeXt heads
opts <- gets stOptions
let tabl = if isEnabled Ext_ntb opts
then Ntb
else Xtb
captionText <- inlineListToConTeXt caption
rows' <- mapM tableRowToConTeXt rows
return $ "\\placetable" <> (if null caption
then brackets "none"
else empty)
<> braces captionText $$
"\\starttable" <> brackets (text colDescriptors) $$
"\\HL" $$ headers $$
vcat rows' $$ "\\HL" $$ "\\stoptable" <> blankline
headers <- if all null heads
then return empty
else tableRowToConTeXt tabl aligns widths heads
rows' <- mapM (tableRowToConTeXt tabl aligns widths) rows
body <- tableToConTeXt tabl headers rows'
return $ "\\startplacetable" <> brackets (
if null caption
then "location=none"
else "caption=" <> braces captionText
) $$ body $$ "\\stopplacetable" <> blankline
tableRowToConTeXt :: PandocMonad m => [[Block]] -> WM m Doc
tableRowToConTeXt cols = do
cols' <- mapM blockListToConTeXt cols
return $ vcat (map ("\\NC " <>) cols') $$ "\\NC\\AR"
tableToConTeXt :: PandocMonad m => Tabl -> Doc -> [Doc] -> WM m Doc
tableToConTeXt Xtb heads rows =
return $ "\\startxtable" $$
(if isEmpty heads
then empty
else "\\startxtablehead[head]" $$ heads $$ "\\stopxtablehead") $$
(if null rows
then empty
else "\\startxtablebody[body]" $$ vcat (init rows) $$ "\\stopxtablebody" $$
"\\startxtablefoot[foot]" $$ last rows $$ "\\stopxtablefoot") $$
"\\stopxtable"
tableToConTeXt Ntb heads rows =
return $ "\\startTABLE" $$
(if isEmpty heads
then empty
else "\\startTABLEhead" $$ heads $$ "\\stopTABLEhead") $$
(if null rows
then empty
else "\\startTABLEbody" $$ vcat (init rows) $$ "\\stopTABLEbody" $$
"\\startTABLEfoot" $$ last rows $$ "\\stopTABLEfoot") $$
"\\stopTABLE"
tableRowToConTeXt :: PandocMonad m => Tabl -> [Alignment] -> [Double] -> [[Block]] -> WM m Doc
tableRowToConTeXt Xtb aligns widths cols = do
cells <- mapM (tableColToConTeXt Xtb) $ zip3 aligns widths cols
return $ "\\startxrow" $$ vcat cells $$ "\\stopxrow"
tableRowToConTeXt Ntb aligns widths cols = do
cells <- mapM (tableColToConTeXt Ntb) $ zip3 aligns widths cols
return $ vcat cells $$ "\\NC\\NR"
tableColToConTeXt :: PandocMonad m => Tabl -> (Alignment, Double, [Block]) -> WM m Doc
tableColToConTeXt tabl (align, width, blocks) = do
cellContents <- blockListToConTeXt blocks
let colwidth = if width == 0
then empty
else "width=" <> braces (text (printf "%.2f\\textwidth" width))
let halign = alignToConTeXt align
let options = (if keys == empty
then empty
else brackets keys) <> space
where keys = hcat $ intersperse "," $ filter (empty /=) [halign, colwidth]
tableCellToConTeXt tabl options cellContents
tableCellToConTeXt :: PandocMonad m => Tabl -> Doc -> Doc -> WM m Doc
tableCellToConTeXt Xtb options cellContents =
return $ "\\startxcell" <> options <> cellContents <> " \\stopxcell"
tableCellToConTeXt Ntb options cellContents =
return $ "\\NC" <> options <> cellContents
alignToConTeXt :: Alignment -> Doc
alignToConTeXt align = case align of
AlignLeft -> "align=right"
AlignRight -> "align=left"
AlignCenter -> "align=middle"
AlignDefault -> empty
listItemToConTeXt :: PandocMonad m => [Block] -> WM m Doc
listItemToConTeXt list = blockListToConTeXt list >>=

View file

@ -15,6 +15,9 @@ context = unpack . purely (writeConTeXt def) . toPandoc
context' :: (ToPandoc a) => a -> String
context' = unpack . purely (writeConTeXt def{ writerWrapText = WrapNone }) . toPandoc
contextNtb :: (ToPandoc a) => a -> String
contextNtb = unpack . purely (writeConTeXt def{ writerExtensions = enableExtension Ext_ntb pandocExtensions }) . toPandoc
{-
"my test" =: X =?> Y
@ -68,5 +71,57 @@ tests = [ testGroup "inline code"
, " \\stopitemize"
, "\\stopitemize" ]
]
, testGroup "natural tables"
[ test contextNtb "table with header and caption" $
let caption = text "Table 1"
aligns = [(AlignRight, 0.0), (AlignLeft, 0.0), (AlignCenter, 0.0), (AlignDefault, 0.0)]
headers = [plain $ text "Right",
plain $ text "Left",
plain $ text "Center",
plain $ text "Default"]
rows = [[plain $ text "1.1",
plain $ text "1.2",
plain $ text "1.3",
plain $ text "1.4"]
,[plain $ text "2.1",
plain $ text "2.2",
plain $ text "2.3",
plain $ text "2.4"]
,[plain $ text "3.1",
plain $ text "3.2",
plain $ text "3.3",
plain $ text "3.4"]]
in table caption aligns headers rows
=?> unlines [ "\\startplacetable[caption={Table 1}]"
, "\\startTABLE"
, "\\startTABLEhead"
, "\\NC[align=left] Right"
, "\\NC[align=right] Left"
, "\\NC[align=middle] Center"
, "\\NC Default"
, "\\NC\\NR"
, "\\stopTABLEhead"
, "\\startTABLEbody"
, "\\NC[align=left] 1.1"
, "\\NC[align=right] 1.2"
, "\\NC[align=middle] 1.3"
, "\\NC 1.4"
, "\\NC\\NR"
, "\\NC[align=left] 2.1"
, "\\NC[align=right] 2.2"
, "\\NC[align=middle] 2.3"
, "\\NC 2.4"
, "\\NC\\NR"
, "\\stopTABLEbody"
, "\\startTABLEfoot"
, "\\NC[align=left] 3.1"
, "\\NC[align=right] 3.2"
, "\\NC[align=middle] 3.3"
, "\\NC 3.4"
, "\\NC\\NR"
, "\\stopTABLEfoot"
, "\\stopTABLE"
, "\\stopplacetable" ]
]
]

View file

@ -1,175 +1,230 @@
Simple table with caption:
\placetable{Demonstration of simple table syntax.}
\starttable[|r|l|c|l|]
\HL
\NC Right
\NC Left
\NC Center
\NC Default
\NC\AR
\HL
\NC 12
\NC 12
\NC 12
\NC 12
\NC\AR
\NC 123
\NC 123
\NC 123
\NC 123
\NC\AR
\NC 1
\NC 1
\NC 1
\NC 1
\NC\AR
\HL
\stoptable
\startplacetable[caption={Demonstration of simple table syntax.}]
\startxtable
\startxtablehead[head]
\startxrow
\startxcell[align=left] Right \stopxcell
\startxcell[align=right] Left \stopxcell
\startxcell[align=middle] Center \stopxcell
\startxcell Default \stopxcell
\stopxrow
\stopxtablehead
\startxtablebody[body]
\startxrow
\startxcell[align=left] 12 \stopxcell
\startxcell[align=right] 12 \stopxcell
\startxcell[align=middle] 12 \stopxcell
\startxcell 12 \stopxcell
\stopxrow
\startxrow
\startxcell[align=left] 123 \stopxcell
\startxcell[align=right] 123 \stopxcell
\startxcell[align=middle] 123 \stopxcell
\startxcell 123 \stopxcell
\stopxrow
\stopxtablebody
\startxtablefoot[foot]
\startxrow
\startxcell[align=left] 1 \stopxcell
\startxcell[align=right] 1 \stopxcell
\startxcell[align=middle] 1 \stopxcell
\startxcell 1 \stopxcell
\stopxrow
\stopxtablefoot
\stopxtable
\stopplacetable
Simple table without caption:
\placetable[none]{}
\starttable[|r|l|c|l|]
\HL
\NC Right
\NC Left
\NC Center
\NC Default
\NC\AR
\HL
\NC 12
\NC 12
\NC 12
\NC 12
\NC\AR
\NC 123
\NC 123
\NC 123
\NC 123
\NC\AR
\NC 1
\NC 1
\NC 1
\NC 1
\NC\AR
\HL
\stoptable
\startplacetable[location=none]
\startxtable
\startxtablehead[head]
\startxrow
\startxcell[align=left] Right \stopxcell
\startxcell[align=right] Left \stopxcell
\startxcell[align=middle] Center \stopxcell
\startxcell Default \stopxcell
\stopxrow
\stopxtablehead
\startxtablebody[body]
\startxrow
\startxcell[align=left] 12 \stopxcell
\startxcell[align=right] 12 \stopxcell
\startxcell[align=middle] 12 \stopxcell
\startxcell 12 \stopxcell
\stopxrow
\startxrow
\startxcell[align=left] 123 \stopxcell
\startxcell[align=right] 123 \stopxcell
\startxcell[align=middle] 123 \stopxcell
\startxcell 123 \stopxcell
\stopxrow
\stopxtablebody
\startxtablefoot[foot]
\startxrow
\startxcell[align=left] 1 \stopxcell
\startxcell[align=right] 1 \stopxcell
\startxcell[align=middle] 1 \stopxcell
\startxcell 1 \stopxcell
\stopxrow
\stopxtablefoot
\stopxtable
\stopplacetable
Simple table indented two spaces:
\placetable{Demonstration of simple table syntax.}
\starttable[|r|l|c|l|]
\HL
\NC Right
\NC Left
\NC Center
\NC Default
\NC\AR
\HL
\NC 12
\NC 12
\NC 12
\NC 12
\NC\AR
\NC 123
\NC 123
\NC 123
\NC 123
\NC\AR
\NC 1
\NC 1
\NC 1
\NC 1
\NC\AR
\HL
\stoptable
\startplacetable[caption={Demonstration of simple table syntax.}]
\startxtable
\startxtablehead[head]
\startxrow
\startxcell[align=left] Right \stopxcell
\startxcell[align=right] Left \stopxcell
\startxcell[align=middle] Center \stopxcell
\startxcell Default \stopxcell
\stopxrow
\stopxtablehead
\startxtablebody[body]
\startxrow
\startxcell[align=left] 12 \stopxcell
\startxcell[align=right] 12 \stopxcell
\startxcell[align=middle] 12 \stopxcell
\startxcell 12 \stopxcell
\stopxrow
\startxrow
\startxcell[align=left] 123 \stopxcell
\startxcell[align=right] 123 \stopxcell
\startxcell[align=middle] 123 \stopxcell
\startxcell 123 \stopxcell
\stopxrow
\stopxtablebody
\startxtablefoot[foot]
\startxrow
\startxcell[align=left] 1 \stopxcell
\startxcell[align=right] 1 \stopxcell
\startxcell[align=middle] 1 \stopxcell
\startxcell 1 \stopxcell
\stopxrow
\stopxtablefoot
\stopxtable
\stopplacetable
Multiline table with caption:
\placetable{Here's the caption. It may span multiple lines.}
\starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|]
\HL
\NC Centered Header
\NC Left Aligned
\NC Right Aligned
\NC Default aligned
\NC\AR
\HL
\NC First
\NC row
\NC 12.0
\NC Example of a row that spans multiple lines.
\NC\AR
\NC Second
\NC row
\NC 5.0
\NC Here's another one. Note the blank line between rows.
\NC\AR
\HL
\stoptable
\startplacetable[caption={Here's the caption. It may span multiple lines.}]
\startxtable
\startxtablehead[head]
\startxrow
\startxcell[align=middle,width={0.15\textwidth}] Centered Header \stopxcell
\startxcell[align=right,width={0.14\textwidth}] Left Aligned \stopxcell
\startxcell[align=left,width={0.16\textwidth}] Right Aligned \stopxcell
\startxcell[align=right,width={0.34\textwidth}] Default aligned \stopxcell
\stopxrow
\stopxtablehead
\startxtablebody[body]
\startxrow
\startxcell[align=middle,width={0.15\textwidth}] First \stopxcell
\startxcell[align=right,width={0.14\textwidth}] row \stopxcell
\startxcell[align=left,width={0.16\textwidth}] 12.0 \stopxcell
\startxcell[align=right,width={0.34\textwidth}] Example of a row that spans
multiple lines. \stopxcell
\stopxrow
\stopxtablebody
\startxtablefoot[foot]
\startxrow
\startxcell[align=middle,width={0.15\textwidth}] Second \stopxcell
\startxcell[align=right,width={0.14\textwidth}] row \stopxcell
\startxcell[align=left,width={0.16\textwidth}] 5.0 \stopxcell
\startxcell[align=right,width={0.34\textwidth}] Here's another one. Note the
blank line between rows. \stopxcell
\stopxrow
\stopxtablefoot
\stopxtable
\stopplacetable
Multiline table without caption:
\placetable[none]{}
\starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|]
\HL
\NC Centered Header
\NC Left Aligned
\NC Right Aligned
\NC Default aligned
\NC\AR
\HL
\NC First
\NC row
\NC 12.0
\NC Example of a row that spans multiple lines.
\NC\AR
\NC Second
\NC row
\NC 5.0
\NC Here's another one. Note the blank line between rows.
\NC\AR
\HL
\stoptable
\startplacetable[location=none]
\startxtable
\startxtablehead[head]
\startxrow
\startxcell[align=middle,width={0.15\textwidth}] Centered Header \stopxcell
\startxcell[align=right,width={0.14\textwidth}] Left Aligned \stopxcell
\startxcell[align=left,width={0.16\textwidth}] Right Aligned \stopxcell
\startxcell[align=right,width={0.34\textwidth}] Default aligned \stopxcell
\stopxrow
\stopxtablehead
\startxtablebody[body]
\startxrow
\startxcell[align=middle,width={0.15\textwidth}] First \stopxcell
\startxcell[align=right,width={0.14\textwidth}] row \stopxcell
\startxcell[align=left,width={0.16\textwidth}] 12.0 \stopxcell
\startxcell[align=right,width={0.34\textwidth}] Example of a row that spans
multiple lines. \stopxcell
\stopxrow
\stopxtablebody
\startxtablefoot[foot]
\startxrow
\startxcell[align=middle,width={0.15\textwidth}] Second \stopxcell
\startxcell[align=right,width={0.14\textwidth}] row \stopxcell
\startxcell[align=left,width={0.16\textwidth}] 5.0 \stopxcell
\startxcell[align=right,width={0.34\textwidth}] Here's another one. Note the
blank line between rows. \stopxcell
\stopxrow
\stopxtablefoot
\stopxtable
\stopplacetable
Table without column headers:
\placetable[none]{}
\starttable[|r|l|c|r|]
\HL
\NC 12
\NC 12
\NC 12
\NC 12
\NC\AR
\NC 123
\NC 123
\NC 123
\NC 123
\NC\AR
\NC 1
\NC 1
\NC 1
\NC 1
\NC\AR
\HL
\stoptable
\startplacetable[location=none]
\startxtable
\startxtablebody[body]
\startxrow
\startxcell[align=left] 12 \stopxcell
\startxcell[align=right] 12 \stopxcell
\startxcell[align=middle] 12 \stopxcell
\startxcell[align=left] 12 \stopxcell
\stopxrow
\startxrow
\startxcell[align=left] 123 \stopxcell
\startxcell[align=right] 123 \stopxcell
\startxcell[align=middle] 123 \stopxcell
\startxcell[align=left] 123 \stopxcell
\stopxrow
\stopxtablebody
\startxtablefoot[foot]
\startxrow
\startxcell[align=left] 1 \stopxcell
\startxcell[align=right] 1 \stopxcell
\startxcell[align=middle] 1 \stopxcell
\startxcell[align=left] 1 \stopxcell
\stopxrow
\stopxtablefoot
\stopxtable
\stopplacetable
Multiline table without column headers:
\placetable[none]{}
\starttable[|cp(0.15\textwidth)|lp(0.14\textwidth)|rp(0.16\textwidth)|lp(0.34\textwidth)|]
\HL
\NC First
\NC row
\NC 12.0
\NC Example of a row that spans multiple lines.
\NC\AR
\NC Second
\NC row
\NC 5.0
\NC Here's another one. Note the blank line between rows.
\NC\AR
\HL
\stoptable
\startplacetable[location=none]
\startxtable
\startxtablebody[body]
\startxrow
\startxcell[align=middle,width={0.15\textwidth}] First \stopxcell
\startxcell[align=right,width={0.14\textwidth}] row \stopxcell
\startxcell[align=left,width={0.16\textwidth}] 12.0 \stopxcell
\startxcell[width={0.34\textwidth}] Example of a row that spans multiple
lines. \stopxcell
\stopxrow
\stopxtablebody
\startxtablefoot[foot]
\startxrow
\startxcell[align=middle,width={0.15\textwidth}] Second \stopxcell
\startxcell[align=right,width={0.14\textwidth}] row \stopxcell
\startxcell[align=left,width={0.16\textwidth}] 5.0 \stopxcell
\startxcell[width={0.34\textwidth}] Here's another one. Note the blank line
between rows. \stopxcell
\stopxrow
\stopxtablefoot
\stopxtable
\stopplacetable

View file

@ -51,6 +51,11 @@
\setupthinrules[width=15em] % width of horizontal rules
\setupxtable[frame=off]
\setupxtable[head][topframe=on,bottomframe=on]
\setupxtable[body][]
\setupxtable[foot][bottomframe=on]
\starttext
\startalignment[middle]

View file

@ -49,6 +49,11 @@
\setupthinrules[width=15em] % width of horizontal rules
\setupxtable[frame=off]
\setupxtable[head][topframe=on,bottomframe=on]
\setupxtable[body][]
\setupxtable[foot][bottomframe=on]
\starttext