Skip to content

feat: Added decimal alignment option #90

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 27 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,26 @@ print(output)
from table2ascii import table2ascii, Alignment

output = table2ascii(
header=["#", "G", "H", "R", "S"],
body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]],
first_col_heading=True,
column_widths=[5, 5, 5, 5, 5],
alignments=[Alignment.LEFT] + [Alignment.RIGHT] * 4,
header=["Product", "Category", "Price", "Rating"],
body=[
["Milk", "Dairy", "$2.99", "6.283"],
["Cheese", "Dairy", "$10.99", "8.2"],
["Apples", "Produce", "$0.99", "10.00"],
],
column_widths=[12, 12, 12, 12],
alignments=[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.DECIMAL],
)

print(output)

"""
╔═════╦═══════════════════════╗
║ # ║ G H R S ║
╟─────╫───────────────────────╢
║ 1 ║ 30 40 35 30 ║
║ 2 ║ 30 40 35 30 ║
╚═════╩═══════════════════════╝
╔═══════════════════════════════════════════════════╗
║ Product Category Price Rating ║
╟───────────────────────────────────────────────────╢
║ Milk Dairy $2.99 6.283 ║
║ Cheese Dairy $10.99 8.2 ║
║ Apples Produce $0.99 10.00 ║
╚═══════════════════════════════════════════════════╝
"""
```

Expand Down Expand Up @@ -199,18 +203,18 @@ All parameters are optional. At least one of `header`, `body`, and `footer` must

Refer to the [documentation](https://table2ascii.readthedocs.io/en/stable/api.html#table2ascii) for more information.

| Option | Type | Default | Description |
| :-----------------: | :----------------------------: | :-------------------: | :-------------------------------------------------------------------------------: |
| `header` | `Sequence[SupportsStr]` | `None` | First table row seperated by header row separator. Values should support `str()` |
| `body` | `Sequence[Sequence[Sequence]]` | `None` | 2D List of rows for the main section of the table. Values should support `str()` |
| `footer` | `Sequence[Sequence]` | `None` | Last table row seperated by header row separator. Values should support `str()` |
| `column_widths` | `Sequence[Optional[int]]` | `None` (automatic) | List of column widths in characters for each column |
| `alignments` | `Sequence[Alignment]` | `None` (all centered) | Column alignments<br/>(ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT]`) |
| `style` | `TableStyle` | `double_thin_compact` | Table style to use for the table\* |
| `first_col_heading` | `bool` | `False` | Whether to add a heading column separator after the first column |
| `last_col_heading` | `bool` | `False` | Whether to add a heading column separator before the last column |
| `cell_padding` | `int` | `1` | The minimum number of spaces to add between the cell content and the cell border |
| `use_wcwidth` | `bool` | `True` | Whether to use [wcwidth][wcwidth] instead of `len()` to calculate cell width |
| Option | Type | Default | Description |
| :-----------------: | :----------------------------: | :-------------------: | :--------------------------------------------------------------------------------------------------: |
| `header` | `Sequence[SupportsStr]` | `None` | First table row seperated by header row separator. Values should support `str()` |
| `body` | `Sequence[Sequence[Sequence]]` | `None` | 2D List of rows for the main section of the table. Values should support `str()` |
| `footer` | `Sequence[Sequence]` | `None` | Last table row seperated by header row separator. Values should support `str()` |
| `column_widths` | `Sequence[Optional[int]]` | `None` (automatic) | List of column widths in characters for each column |
| `alignments` | `Sequence[Alignment]` | `None` (all centered) | Column alignments<br/>(ex. `[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.DECIMAL]`) |
| `style` | `TableStyle` | `double_thin_compact` | Table style to use for the table\* |
| `first_col_heading` | `bool` | `False` | Whether to add a heading column separator after the first column |
| `last_col_heading` | `bool` | `False` | Whether to add a heading column separator before the last column |
| `cell_padding` | `int` | `1` | The minimum number of spaces to add between the cell content and the cell border |
| `use_wcwidth` | `bool` | `True` | Whether to use [wcwidth][wcwidth] instead of `len()` to calculate cell width |

[wcwidth]: https://pypi.org/project/wcwidth/

Expand Down
208 changes: 106 additions & 102 deletions docs/source/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,115 +6,119 @@ Convert lists to ASCII tables

.. code:: py

from table2ascii import table2ascii

output = table2ascii(
header=["#", "G", "H", "R", "S"],
body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]],
footer=["SUM", "130", "140", "135", "130"],
)

print(output)

"""
╔═════════════════════════════╗
║ # G H R S ║
╟─────────────────────────────╢
║ 1 30 40 35 30 ║
║ 2 30 40 35 30 ║
╟─────────────────────────────╢
║ SUM 130 140 135 130 ║
╚═════════════════════════════╝
"""
from table2ascii import table2ascii

output = table2ascii(
header=["#", "G", "H", "R", "S"],
body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]],
footer=["SUM", "130", "140", "135", "130"],
)

print(output)

"""
╔═════════════════════════════╗
║ # G H R S ║
╟─────────────────────────────╢
║ 1 30 40 35 30 ║
║ 2 30 40 35 30 ║
╟─────────────────────────────╢
║ SUM 130 140 135 130 ║
╚═════════════════════════════╝
"""

Set first or last column headings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: py

from table2ascii import table2ascii
from table2ascii import table2ascii

output = table2ascii(
body=[["Assignment", "30", "40", "35", "30"], ["Bonus", "10", "20", "5", "10"]],
first_col_heading=True,
)
output = table2ascii(
body=[["Assignment", "30", "40", "35", "30"], ["Bonus", "10", "20", "5", "10"]],
first_col_heading=True,
)

print(output)
print(output)

"""
╔════════════╦═══════════════════╗
║ Assignment ║ 30 40 35 30 ║
║ Bonus ║ 10 20 5 10 ║
╚════════════╩═══════════════════╝
"""
"""
╔════════════╦═══════════════════╗
║ Assignment ║ 30 40 35 30 ║
║ Bonus ║ 10 20 5 10 ║
╚════════════╩═══════════════════╝
"""

Set column widths and alignments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: py

from table2ascii import table2ascii, Alignment
from table2ascii import table2ascii, Alignment

output = table2ascii(
header=["#", "G", "H", "R", "S"],
body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]],
first_col_heading=True,
column_widths=[5, 5, 5, 5, 5],
alignments=[Alignment.LEFT] + [Alignment.RIGHT] * 4,
)
output = table2ascii(
header=["Product", "Category", "Price", "Rating"],
body=[
["Milk", "Dairy", "$2.99", "6.283"],
["Cheese", "Dairy", "$10.99", "8.2"],
["Apples", "Produce", "$0.99", "10.00"],
],
column_widths=[12, 12, 12, 12],
alignments=[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.DECIMAL],
)

print(output)
print(output)

"""
╔═════╦═══════════════════════╗
║ # ║ G H R S ║
╟─────╫───────────────────────╢
║ 1 ║ 30 40 35 30 ║
║ 2 ║ 30 40 35 30 ║
╚═════╩═══════════════════════╝
"""
"""
╔═══════════════════════════════════════════════════╗
║ Product Category Price Rating ║
╟───────────────────────────────────────────────────╢
║ Milk Dairy $2.99 6.283 ║
║ Cheese Dairy $10.99 8.2 ║
║ Apples Produce $0.99 10.00 ║
╚═══════════════════════════════════════════════════╝
"""

Use a preset style
~~~~~~~~~~~~~~~~~~

.. code:: py

from table2ascii import table2ascii, Alignment, PresetStyle

output = table2ascii(
header=["First", "Second", "Third", "Fourth"],
body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]],
column_widths=[10, 10, 10, 10],
style=PresetStyle.ascii_box
)

print(output)

"""
+----------+----------+----------+----------+
| First | Second | Third | Fourth |
+----------+----------+----------+----------+
| 10 | 30 | 40 | 35 |
+----------+----------+----------+----------+
| 20 | 10 | 20 | 5 |
+----------+----------+----------+----------+
"""

output = table2ascii(
header=["First", "Second", "Third", "Fourth"],
body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]],
style=PresetStyle.plain,
cell_padding=0,
alignments=[Alignment.LEFT] * 4,
)

print(output)

"""
First Second Third Fourth
10 30 40 35
20 10 20 5
"""
from table2ascii import table2ascii, Alignment, PresetStyle

output = table2ascii(
header=["First", "Second", "Third", "Fourth"],
body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]],
column_widths=[10, 10, 10, 10],
style=PresetStyle.ascii_box
)

print(output)

"""
+----------+----------+----------+----------+
| First | Second | Third | Fourth |
+----------+----------+----------+----------+
| 10 | 30 | 40 | 35 |
+----------+----------+----------+----------+
| 20 | 10 | 20 | 5 |
+----------+----------+----------+----------+
"""

output = table2ascii(
header=["First", "Second", "Third", "Fourth"],
body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]],
style=PresetStyle.plain,
cell_padding=0,
alignments=[Alignment.LEFT] * 4,
)

print(output)

"""
First Second Third Fourth
10 30 40 35
20 10 20 5
"""

Define a custom style
~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -123,27 +127,27 @@ Check :ref:`TableStyle` for more info.

.. code:: py

from table2ascii import table2ascii, TableStyle
from table2ascii import table2ascii, TableStyle

my_style = TableStyle.from_string("*-..*||:+-+:+ *''*")
my_style = TableStyle.from_string("*-..*||:+-+:+ *''*")

output = table2ascii(
header=["First", "Second", "Third"],
body=[["10", "30", "40"], ["20", "10", "20"], ["30", "20", "30"]],
style=my_style,
)
output = table2ascii(
header=["First", "Second", "Third"],
body=[["10", "30", "40"], ["20", "10", "20"], ["30", "20", "30"]],
style=my_style,
)

print(output)
print(output)

"""
*-------.--------.-------*
| First : Second : Third |
+-------:--------:-------+
| 10 : 30 : 40 |
| 20 : 10 : 20 |
| 30 : 20 : 30 |
*-------'--------'-------*
"""
"""
*-------.--------.-------*
| First : Second : Third |
+-------:--------:-------+
| 10 : 30 : 40 |
| 20 : 10 : 20 |
| 30 : 20 : 30 |
*-------'--------'-------*
"""

Merge adjacent cells
~~~~~~~~~~~~~~~~~~~~
Expand Down
32 changes: 23 additions & 9 deletions table2ascii/alignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,40 @@ class Alignment(IntEnum):
from table2ascii import Alignment, table2ascii

table2ascii(
header=["Product", "Category", "Price", "In Stock"],
header=["Product", "Category", "Price", "Rating"],
body=[
["Milk", "Dairy", "$2.99", "Yes"],
["Cheese", "Dairy", "$10.99", "No"],
["Apples", "Produce", "$0.99", "Yes"],
["Milk", "Dairy", "$2.99", "6.28318"],
["Cheese", "Dairy", "$10.99", "8.2"],
["Apples", "Produce", "$0.99", "10.00"],
],
alignments=[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.LEFT],
alignments=[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.DECIMAL],
)

\"\"\"
╔════════════════════════════════════════╗
║ Product Category Price In Stock
║ Product Category Price Rating
╟────────────────────────────────────────╢
║ Milk Dairy $2.99 Yes
║ Cheese Dairy $10.99 No
║ Apples Produce $0.99 Yes
║ Milk Dairy $2.99 6.28318
║ Cheese Dairy $10.99 8.2
║ Apples Produce $0.99 10.00
╚════════════════════════════════════════╝
\"\"\"

.. note::

If the :attr:`DECIMAL` alignment type is used, any cell values that are
not valid decimal numbers will be aligned to the center. Decimal numbers
include integers, floats, and strings containing only
:meth:`decimal <str.isdecimal>` characters and at most one decimal point.

.. versionchanged:: 1.1.0

Added :attr:`DECIMAL` alignment -- align decimal numbers such that
the decimal point is aligned with the decimal point of all other numbers
in the same column.
"""

LEFT = 0
CENTER = 1
RIGHT = 2
DECIMAL = 3
Loading