Skip to content

Commit 12bab03

Browse files
authored
feat: Added decimal alignment option (#90)
1 parent 8d799b5 commit 12bab03

File tree

5 files changed

+254
-144
lines changed

5 files changed

+254
-144
lines changed

README.md

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,26 @@ print(output)
6969
from table2ascii import table2ascii, Alignment
7070

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

7982
print(output)
8083

8184
"""
82-
╔═════╦═══════════════════════╗
83-
║ # ║ G H R S ║
84-
╟─────╫───────────────────────╢
85-
║ 1 ║ 30 40 35 30 ║
86-
║ 2 ║ 30 40 35 30 ║
87-
╚═════╩═══════════════════════╝
85+
╔═══════════════════════════════════════════════════╗
86+
║ Product Category Price Rating ║
87+
╟───────────────────────────────────────────────────╢
88+
║ Milk Dairy $2.99 6.283 ║
89+
║ Cheese Dairy $10.99 8.2 ║
90+
║ Apples Produce $0.99 10.00 ║
91+
╚═══════════════════════════════════════════════════╝
8892
"""
8993
```
9094

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

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

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

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

docs/source/usage.rst

Lines changed: 106 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -6,115 +6,119 @@ Convert lists to ASCII tables
66

77
.. code:: py
88
9-
from table2ascii import table2ascii
10-
11-
output = table2ascii(
12-
header=["#", "G", "H", "R", "S"],
13-
body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]],
14-
footer=["SUM", "130", "140", "135", "130"],
15-
)
16-
17-
print(output)
18-
19-
"""
20-
╔═════════════════════════════╗
21-
║ # G H R S ║
22-
╟─────────────────────────────╢
23-
║ 1 30 40 35 30 ║
24-
║ 2 30 40 35 30 ║
25-
╟─────────────────────────────╢
26-
║ SUM 130 140 135 130 ║
27-
╚═════════════════════════════╝
28-
"""
9+
from table2ascii import table2ascii
10+
11+
output = table2ascii(
12+
header=["#", "G", "H", "R", "S"],
13+
body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]],
14+
footer=["SUM", "130", "140", "135", "130"],
15+
)
16+
17+
print(output)
18+
19+
"""
20+
╔═════════════════════════════╗
21+
║ # G H R S ║
22+
╟─────────────────────────────╢
23+
║ 1 30 40 35 30 ║
24+
║ 2 30 40 35 30 ║
25+
╟─────────────────────────────╢
26+
║ SUM 130 140 135 130 ║
27+
╚═════════════════════════════╝
28+
"""
2929
3030
Set first or last column headings
3131
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3232

3333
.. code:: py
3434
35-
from table2ascii import table2ascii
35+
from table2ascii import table2ascii
3636
37-
output = table2ascii(
38-
body=[["Assignment", "30", "40", "35", "30"], ["Bonus", "10", "20", "5", "10"]],
39-
first_col_heading=True,
40-
)
37+
output = table2ascii(
38+
body=[["Assignment", "30", "40", "35", "30"], ["Bonus", "10", "20", "5", "10"]],
39+
first_col_heading=True,
40+
)
4141
42-
print(output)
42+
print(output)
4343
44-
"""
45-
╔════════════╦═══════════════════╗
46-
║ Assignment ║ 30 40 35 30 ║
47-
║ Bonus ║ 10 20 5 10 ║
48-
╚════════════╩═══════════════════╝
49-
"""
44+
"""
45+
╔════════════╦═══════════════════╗
46+
║ Assignment ║ 30 40 35 30 ║
47+
║ Bonus ║ 10 20 5 10 ║
48+
╚════════════╩═══════════════════╝
49+
"""
5050
5151
Set column widths and alignments
5252
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5353

5454
.. code:: py
5555
56-
from table2ascii import table2ascii, Alignment
56+
from table2ascii import table2ascii, Alignment
5757
58-
output = table2ascii(
59-
header=["#", "G", "H", "R", "S"],
60-
body=[["1", "30", "40", "35", "30"], ["2", "30", "40", "35", "30"]],
61-
first_col_heading=True,
62-
column_widths=[5, 5, 5, 5, 5],
63-
alignments=[Alignment.LEFT] + [Alignment.RIGHT] * 4,
64-
)
58+
output = table2ascii(
59+
header=["Product", "Category", "Price", "Rating"],
60+
body=[
61+
["Milk", "Dairy", "$2.99", "6.283"],
62+
["Cheese", "Dairy", "$10.99", "8.2"],
63+
["Apples", "Produce", "$0.99", "10.00"],
64+
],
65+
column_widths=[12, 12, 12, 12],
66+
alignments=[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.DECIMAL],
67+
)
6568
66-
print(output)
69+
print(output)
6770
68-
"""
69-
╔═════╦═══════════════════════╗
70-
║ # ║ G H R S ║
71-
╟─────╫───────────────────────╢
72-
║ 1 ║ 30 40 35 30 ║
73-
║ 2 ║ 30 40 35 30 ║
74-
╚═════╩═══════════════════════╝
75-
"""
71+
"""
72+
╔═══════════════════════════════════════════════════╗
73+
║ Product Category Price Rating ║
74+
╟───────────────────────────────────────────────────╢
75+
║ Milk Dairy $2.99 6.283 ║
76+
║ Cheese Dairy $10.99 8.2 ║
77+
║ Apples Produce $0.99 10.00 ║
78+
╚═══════════════════════════════════════════════════╝
79+
"""
7680
7781
Use a preset style
7882
~~~~~~~~~~~~~~~~~~
7983

8084
.. code:: py
8185
82-
from table2ascii import table2ascii, Alignment, PresetStyle
83-
84-
output = table2ascii(
85-
header=["First", "Second", "Third", "Fourth"],
86-
body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]],
87-
column_widths=[10, 10, 10, 10],
88-
style=PresetStyle.ascii_box
89-
)
90-
91-
print(output)
92-
93-
"""
94-
+----------+----------+----------+----------+
95-
| First | Second | Third | Fourth |
96-
+----------+----------+----------+----------+
97-
| 10 | 30 | 40 | 35 |
98-
+----------+----------+----------+----------+
99-
| 20 | 10 | 20 | 5 |
100-
+----------+----------+----------+----------+
101-
"""
102-
103-
output = table2ascii(
104-
header=["First", "Second", "Third", "Fourth"],
105-
body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]],
106-
style=PresetStyle.plain,
107-
cell_padding=0,
108-
alignments=[Alignment.LEFT] * 4,
109-
)
110-
111-
print(output)
112-
113-
"""
114-
First Second Third Fourth
115-
10 30 40 35
116-
20 10 20 5
117-
"""
86+
from table2ascii import table2ascii, Alignment, PresetStyle
87+
88+
output = table2ascii(
89+
header=["First", "Second", "Third", "Fourth"],
90+
body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]],
91+
column_widths=[10, 10, 10, 10],
92+
style=PresetStyle.ascii_box
93+
)
94+
95+
print(output)
96+
97+
"""
98+
+----------+----------+----------+----------+
99+
| First | Second | Third | Fourth |
100+
+----------+----------+----------+----------+
101+
| 10 | 30 | 40 | 35 |
102+
+----------+----------+----------+----------+
103+
| 20 | 10 | 20 | 5 |
104+
+----------+----------+----------+----------+
105+
"""
106+
107+
output = table2ascii(
108+
header=["First", "Second", "Third", "Fourth"],
109+
body=[["10", "30", "40", "35"], ["20", "10", "20", "5"]],
110+
style=PresetStyle.plain,
111+
cell_padding=0,
112+
alignments=[Alignment.LEFT] * 4,
113+
)
114+
115+
print(output)
116+
117+
"""
118+
First Second Third Fourth
119+
10 30 40 35
120+
20 10 20 5
121+
"""
118122
119123
Define a custom style
120124
~~~~~~~~~~~~~~~~~~~~~
@@ -123,27 +127,27 @@ Check :ref:`TableStyle` for more info.
123127

124128
.. code:: py
125129
126-
from table2ascii import table2ascii, TableStyle
130+
from table2ascii import table2ascii, TableStyle
127131
128-
my_style = TableStyle.from_string("*-..*||:+-+:+ *''*")
132+
my_style = TableStyle.from_string("*-..*||:+-+:+ *''*")
129133
130-
output = table2ascii(
131-
header=["First", "Second", "Third"],
132-
body=[["10", "30", "40"], ["20", "10", "20"], ["30", "20", "30"]],
133-
style=my_style,
134-
)
134+
output = table2ascii(
135+
header=["First", "Second", "Third"],
136+
body=[["10", "30", "40"], ["20", "10", "20"], ["30", "20", "30"]],
137+
style=my_style,
138+
)
135139
136-
print(output)
140+
print(output)
137141
138-
"""
139-
*-------.--------.-------*
140-
| First : Second : Third |
141-
+-------:--------:-------+
142-
| 10 : 30 : 40 |
143-
| 20 : 10 : 20 |
144-
| 30 : 20 : 30 |
145-
*-------'--------'-------*
146-
"""
142+
"""
143+
*-------.--------.-------*
144+
| First : Second : Third |
145+
+-------:--------:-------+
146+
| 10 : 30 : 40 |
147+
| 20 : 10 : 20 |
148+
| 30 : 20 : 30 |
149+
*-------'--------'-------*
150+
"""
147151
148152
Merge adjacent cells
149153
~~~~~~~~~~~~~~~~~~~~

table2ascii/alignment.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,40 @@ class Alignment(IntEnum):
99
from table2ascii import Alignment, table2ascii
1010
1111
table2ascii(
12-
header=["Product", "Category", "Price", "In Stock"],
12+
header=["Product", "Category", "Price", "Rating"],
1313
body=[
14-
["Milk", "Dairy", "$2.99", "Yes"],
15-
["Cheese", "Dairy", "$10.99", "No"],
16-
["Apples", "Produce", "$0.99", "Yes"],
14+
["Milk", "Dairy", "$2.99", "6.28318"],
15+
["Cheese", "Dairy", "$10.99", "8.2"],
16+
["Apples", "Produce", "$0.99", "10.00"],
1717
],
18-
alignments=[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.LEFT],
18+
alignments=[Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.DECIMAL],
1919
)
2020
2121
\"\"\"
2222
╔════════════════════════════════════════╗
23-
║ Product Category Price In Stock
23+
║ Product Category Price Rating
2424
╟────────────────────────────────────────╢
25-
║ Milk Dairy $2.99 Yes
26-
║ Cheese Dairy $10.99 No
27-
║ Apples Produce $0.99 Yes
25+
║ Milk Dairy $2.99 6.28318
26+
║ Cheese Dairy $10.99 8.2
27+
║ Apples Produce $0.99 10.00
2828
╚════════════════════════════════════════╝
2929
\"\"\"
30+
31+
.. note::
32+
33+
If the :attr:`DECIMAL` alignment type is used, any cell values that are
34+
not valid decimal numbers will be aligned to the center. Decimal numbers
35+
include integers, floats, and strings containing only
36+
:meth:`decimal <str.isdecimal>` characters and at most one decimal point.
37+
38+
.. versionchanged:: 1.1.0
39+
40+
Added :attr:`DECIMAL` alignment -- align decimal numbers such that
41+
the decimal point is aligned with the decimal point of all other numbers
42+
in the same column.
3043
"""
3144

3245
LEFT = 0
3346
CENTER = 1
3447
RIGHT = 2
48+
DECIMAL = 3

0 commit comments

Comments
 (0)