From f4df50c443e43ed4b3f36041e264192e98b1333f Mon Sep 17 00:00:00 2001 From: Kevin Deldycke Date: Tue, 4 Apr 2023 18:05:49 +0400 Subject: [PATCH] Allow alignments in Markdown tables. Closes #53, superseds #260. --- README.md | 14 +++++++------- tabulate/__init__.py | 40 ++++++++++++++++++++++++---------------- test/test_output.py | 2 +- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index d64b99a..3717933 100644 --- a/README.md +++ b/README.md @@ -213,16 +213,16 @@ eggs 451 bacon 0 ``` -`github` follows the conventions of GitHub flavored Markdown. It -corresponds to the `pipe` format without alignment colons: +`github` follows the conventions of GitHub flavored Markdown. This +format uses colons to indicate column alignment: ```pycon >>> print(tabulate(table, headers, tablefmt="github")) -| item | qty | -|--------|-------| -| spam | 42 | -| eggs | 451 | -| bacon | 0 | +| item | qty | +| :------ | ----: | +| spam | 42 | +| eggs | 451 | +| bacon | 0 | ``` `grid` is like tables formatted by Emacs' diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 3b1a1e1..821a7ea 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -110,27 +110,29 @@ def _is_separating_line(row): return is_sl -def _pipe_segment_with_colons(align, colwidth): +def _segment_with_colons(align, colwidth, sep="-"): """Return a segment of a horizontal line with optional colons which indicate column's alignment (as in `pipe` output format).""" w = colwidth if align in ["right", "decimal"]: - return ("-" * (w - 1)) + ":" + return (sep * (w - 1)) + ":" elif align == "center": - return ":" + ("-" * (w - 2)) + ":" + return ":" + (sep * (w - 2)) + ":" elif align == "left": - return ":" + ("-" * (w - 1)) + return ":" + (sep * (w - 1)) else: - return "-" * w + return sep * w -def _pipe_line_with_colons(colwidths, colaligns): +def _line_with_colons(colwidths, colaligns, begin="|", hline="|", sep="-", end="|"): """Return a horizontal line with optional colons to indicate column's - alignment (as in `pipe` output format).""" + alignment (as in `pipe` and `github` output format).""" if not colaligns: # e.g. printing an empty data frame (github issue #15) colaligns = [""] * len(colwidths) - segments = [_pipe_segment_with_colons(a, w) for a, w in zip(colaligns, colwidths)] - return "|" + "|".join(segments) + "|" + segments = [ + _segment_with_colons(a, w, sep=sep) for a, w in zip(colaligns, colwidths) + ] + return begin + hline.join(segments) + end def _mediawiki_row_with_attrs(separator, cell_values, colwidths, colaligns): @@ -470,18 +472,24 @@ def escape_empty(val): with_header_hide=None, ), "github": TableFormat( - lineabove=Line("|", "-", "|", "|"), - linebelowheader=Line("|", "-", "|", "|"), + lineabove=partial( + _line_with_colons, begin="| ", hline=" | ", sep="-", end=" |" + ), + linebelowheader=partial( + _line_with_colons, begin="| ", hline=" | ", sep="-", end=" |" + ), linebetweenrows=None, linebelow=None, - headerrow=DataRow("|", "|", "|"), - datarow=DataRow("|", "|", "|"), - padding=1, + headerrow=DataRow("| ", " | ", " |"), + datarow=DataRow("| ", " | ", " |"), + padding=0, with_header_hide=["lineabove"], ), "pipe": TableFormat( - lineabove=_pipe_line_with_colons, - linebelowheader=_pipe_line_with_colons, + lineabove=partial(_line_with_colons, begin="|", hline="|", sep="-", end="|"), + linebelowheader=partial( + _line_with_colons, begin="|", hline="|", sep="-", end="|" + ), linebetweenrows=None, linebelow=None, headerrow=DataRow("|", "|", "|"), diff --git a/test/test_output.py b/test/test_output.py index 9043aed..f4ed307 100644 --- a/test/test_output.py +++ b/test/test_output.py @@ -429,7 +429,7 @@ def test_github(): expected = "\n".join( [ "| strings | numbers |", - "|-----------|-----------|", + "| :-------- | --------: |", "| spam | 41.9999 |", "| eggs | 451 |", ]