Tabling is a Python library for creating highly customizable tables in the console.
Project description
Tabling
Tabling is a Python library for creating highly customizable tables in the console.
Table of Contents
- Introduction
- Features
- Installation
- Usage
- Templates
- Effects
- Applications
- Contributing
- License
- Conclusion
Introduction
Tabling was inspired by HTML and CSS. It is row-centric, like in HTML tables, but supports direct column operations. It can be used not only for tabular data but also for designing user interfaces in the console (similar to how HTML tables were once used before the rise of CSS Grid and Flexbox).
Features
- Add/remove rows, columns, cells
- Sort rows/columns based on key
- Find/replace values with new ones
- Import/export table to JSON, CSV, TXT
- Customize
background,border,font,margin,padding - Modify text alignment, justification, wrap, direction, visibility
- CSS-like syntax e.g.,
border.stylefor CSSborder-style - 140+ color names; all RGB values; & all HEX color codes
- 5 border styles:
single,double,dashed,dotted,solid - 5+ font styles:
bold,italic,strikethrough,underline
Installation
pip install tabling
Usage
1. Import library
from tabling import Table
2. Create table
table = Table(colspacing=1, rowspacing=0)
3. Perform operations
The table below shows available Tabling table operations:
| Method | Description |
|---|---|
add_row(entries: Iterable) |
Adds a row |
add_column(entries: Iterable) |
Adds a column |
insert_row(index: int, entries: Iterable) |
Inserts a row at an index |
insert_column(index: int, entries: Iterable) |
Inserts a column at an index |
remove_row(index: int) |
Removes the row at an index |
remove_column(index: int) |
Removes the column at an index |
swap_rows(index1: int, index2: int) |
Swaps positions of two rows |
swap_columns(index1: int, index2: int) |
Swaps positions of two columns |
sort_rows(key: int, start=0, reverse=False) |
Sorts rows by a key column |
sort_columns(key: int, start=0, reverse=False) |
Sorts columns by a key row |
find(value: Any) |
Prints a table, highlighting matches |
replace(value: Any, repl: Any) |
Replaces a value with a new one |
export_csv(filepath: str) |
Exports rows to csv file |
import_csv(filepath: str) |
Imports rows from csv file |
export_json(filepath: str, key=None, as_objects=True) |
Exports rows to json file |
import_json(filepath: str, key=None) |
Imports rows from json file |
export_txt(filepath: str) |
Exports plain table to txt file |
Example
table.add_row(("Name", "Age", "Sex"))
table.add_row(("Wesley", 20, "M"))
table.add_row(("Ashley", 12, "F"))
table.add_row(("Lesley", 12, "M"))
table.add_column(("Married", True, False, False))
4. Customize
The table below describes all customizable element properties:
| Property Attribute | Description | Example values |
|---|---|---|
background.color |
Background color | red, green, blue, black, white |
border.style |
Border style | single, double, dashed, solid |
border.color |
Border color | red, green, blue, black, white |
border.left.style |
Border-left style | single, double, dashed, solid |
border.left.color |
Border-left color | red, green, blue, black, white |
border.right.style |
Border-right style | single, double, dashed, solid |
border.right.color |
Border-right color | red, green, blue, black, white |
border.top.style |
Border-top style | single, double, dashed, solid |
border.top.color |
Border-top color | red, green, blue, black, white |
border.bottom.style |
Border-bottom style | single, double, dashed, solid |
border.bottom.color |
Border-bottom color | red, green, blue, black, white |
font.style |
Font style | bold, italic, strikethrough |
font.color |
Font color | red, green, blue, black, white |
margin.left |
Margin to the left | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |
margin.right |
Margin to the right | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |
margin.top |
Margin to the top | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |
margin.bottom |
Margin to the bottom | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |
padding.left |
Padding to the left | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |
padding.right |
Padding to the right | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |
padding.top |
Padding to the top | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |
padding.bottom |
Padding to the bottom | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |
text.justify |
Horizontal text alignment | left, center, right |
text.align |
Vertical text alignment | top, center, bottom |
text.wrap |
Whether to wrap text | True, False |
text.visible |
Whether to show text | True, False |
text.reverse |
Whether to reverse text | True, False |
text.letter_spacing |
Spacing between letters | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |
text.word_spacing |
Spacing between words | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 |
The table below shows how to reference elements for customization:
| Element | Method |
|---|---|
| table | table |
| row | table[row_index] |
| cell | table[row_index][column_index] |
| rows | for row in table: |
| cells | for cell in row: |
Example
table.border.style = "single"
table[0].font.style = "bold"
for row in table:
row[1].text.justify = "center"
row[2].text.justify = "center"
5. Display
print(table)
Templates
Templates are pre-written, border-related, styles you can copy and customize.
1. Headed
Adds a border between the header and body.
table.border.style = "single"
table[0].border.bottom.style = "single"
table[1].margin.top = max(0, table.rowspacing - 1)
for row in table[2:]:
row.margin.top = max(0, table.rowspacing)
table.rowspacing = 0
2. Stacked
Creates a stack of rows with collapsed horizontal borders.
table.border.style = "single"
for row in table[1:]:
row.border.top.style = "single"
3. Queued
Creates column-separated borders with equal column spacing.
for cell in table[0]:
cell.border.top.style = "single"
for row in table:
for cell in row:
cell.border.left.style = "single"
cell.border.right.style = "single"
row[0].height += table.rowspacing
for cell in table[-1]:
cell.border.bottom.style = "single"
for cell in table[0]:
cell.width += table.colspacing
table.rowspacing = table.colspacing = 0
4. Queued - Collapsed
Collapses horizontal borders while keeping column structure.
for cell in table[0]:
cell.border.top.style = "single"
for row in table:
for cell in row:
cell.border.left.style = "single"
row[-1].border.right.style = "single"
row[0].height += table.rowspacing
for cell in table[-1]:
cell.border.bottom.style = "single"
for cell in table[0]:
cell.width += table.colspacing
table.rowspacing = table.colspacing = 0
5. Grid
Adds full borders to every cell.
for row in table:
for cell in row:
cell.border.style = "single"
6. Grid - Collapsed
A compact version of the grid layout with collapsed cell borders.
table.border.style = "single"
for row in table:
for cell in row[:-1]:
cell.border.right.style = "single"
row[0].height += table.rowspacing
for row in table[:-1]:
for cell in row:
cell.border.bottom.style = "single"
for cell in table[0]:
cell.width += table.colspacing
table.rowspacing = table.colspacing = 0
Effects
Effects are pre-written, color-related, styles you can copy and customize.
1. Striped
Alternates row colors.
for row in table[1::2]:
row.background.color = "#999"
2. Banded
Alternates column colors.
for row in table:
for cell in row[1::2]:
cell.background.color = "#999"
3. Checkered
Alternates every cell’s color for a chessboard-like effect.
table.background.color = "#333"
for row in table:
row[0].height += table.rowspacing
for row in table[0::2]:
for cell in row[0::2]:
cell.background.color = "#222"
for row in table[1::2]:
for cell in row[1::2]:
cell.background.color = "#222"
for cell in table[0]:
cell.width += table.colspacing
table.rowspacing = table.colspacing = 0
Applications
These are real world examples where Tabling was used to design console-based user interfaces.
1. Menu
A menu-driven interface where a user selects a numbered option.
from tabling import Table
question = "What's your favorite programming language?"
answers = ("Python", "C", "C++", "Javascript")
options = (f"{i}." for i in range(1, len(answers) + 1))
menu = Table(colspacing=1, rowspacing=0)
menu.add_column(options)
menu.add_column(answers)
menu.padding.left = 2
print(question)
print(menu)
option = int(input("> "))
print(f"You chose: {menu[option-1][1]}")
2. Calendar
A customizable calendar for May 2025.
from tabling import Table
calendar = Table(colspacing=0, rowspacing=0)
calendar.add_row(("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"))
calendar.add_row(("", "", "", "", 1, 2, 3))
calendar.add_row((4, 5, 6, 7, 8, 9, 10))
calendar.add_row((11, 12, 13, 14, 15, 16, 17))
calendar.add_row((18, 19, 20, 21, 22, 23, 24))
calendar.add_row((25, 26, 27, 28, 29, 30, 31))
calendar[0].background.color = "#888"
calendar[3][3].background.color = "lightgray"
for row in calendar:
row[0].background.color = "#999"
for cell in row:
cell.width = 5
cell.height = 2
print(" May 2025")
print(calendar)
3. Bar Graph
A terminal-based bar graph made using Tabling.
from tabling import Table
graph = Table(colspacing=4)
graph.add_column((12, 10, 8, 6, 4, 2))
for _ in range(4):
graph.add_column(("", "", "", "", "", ""))
for column_index in range(1, 5):
graph[0][column_index].width = 6
graph.margin.top = 1
graph[0][-1].margin.right = 3
graph[-1].border.bottom.style = "single"
for row_index, row in enumerate(graph):
row[0].border.right.style = "single"
row[0].height = 3
if row_index > 2:
row[1].background.color = "tomato"
if row_index > 3:
row[2].background.color = "crimson"
if row_index > 0:
row[3].background.color = "maroon"
if row_index > 1:
row[4].background.color = "brown"
graph.add_row(("", "A","B", "C", "D"))
for cell in graph[-1]:
cell.text.justify = "center"
print(graph)
4. Calculator
A terminal-based calculator interface using Tabling.
from tabling import Table
SCREEN_HEIGHT = 10
calculator = Table(colspacing=1, rowspacing=0)
calculator.border.style = "solid"
for _ in range(SCREEN_HEIGHT):
calculator.add_row(("", "", "", "", ""))
calculator.add_row(("Menu", "⯇", "⏵", "⨯", "AC"))
calculator.add_row(("DEG", "sin", "cos", "tan", "π"))
calculator.add_row(("Shift", "√x", "ⁿ√x", "(", ")"))
calculator.add_row(("%", "x²", "xⁿ", "□∕□", "÷"))
calculator.add_row(("log", 7, 8, 9, "×"))
calculator.add_row(("ln", 4, 5, 6, "−"))
calculator.add_row(("e", 1, 2, 3, "+"))
calculator.add_row(("□", "Ans", 0, ".", "="))
calculator[0].border.top.style = "single"
for row in calculator[:SCREEN_HEIGHT]:
row.border.left.style = "single"
row.border.right.style = "single"
calculator[SCREEN_HEIGHT - 1].border.bottom.style = "single"
for row in calculator[SCREEN_HEIGHT:]:
for cell in row:
cell.width = 5
cell.text.justify = "center"
cell.border.style = "single"
print(calculator)
5. Chess Board
A fully drawn chess board using Tabling.
from tabling import Table
chess_board = Table(colspacing=0, rowspacing=0)
for _ in range(8):
chess_board.add_row(("",)*8)
chess_board.font.style = "bold"
chess_board.background.color = "burlywood"
for row in chess_board:
for cell in row:
cell.padding.block = 1, 1
cell.padding.inline = 2, 2
for row in chess_board[0::2]:
for cell in row[0::2]:
cell.background.color = "#333"
for row in chess_board[1::2]:
for cell in row[1::2]:
cell.background.color = "#333"
chess_board.insert_column(0, range(8, 0, -1))
chess_board.add_column(range(8, 0, -1))
chess_board.add_row(" ABCDEFGH")
chess_board.insert_row(0, " ABCDEFGH")
print(chess_board)
FAQ/Troubleshooting
-
How do I enter RGB and HEX colors?
Use r,g,b for RGB (e.g., 255,0,0) and #rrggbb or #rgb for HEX (e.g., #ff0000 or #f00) -
How do I change a cell value?
Usetable[row_index][column_index].value = new_value -
How do I check the data type of a cell value?
Usetype(cell.value). Cell values are stored as provided by the user. -
How can I implement cell merging?
Currently, Tabling does not support cell merging (rowspan, colspan). However, you can simulate merged cells by adjusting width, height, padding, and border properties across adjacent cells to create the visual illusion of merging. -
Is there a shorter way to set margin and padding of all sides?
Taking margin and padding as just spacing, usespacing.inline = left, rightto set spacing-left and spacing-right andspacing.block = top, bottomto set spacing-top and spacing-bottom. For example,margin.top = 2, 1setsmargin.top = 2andmargin.bottom = 1. -
Can table rendering be made a bit faster?
Yes, by settingtable.preserve = False. This means that normalization changes will directly affect the original table. In contrast, settingtable.preserve = Truecreates a copy of the table each time it needs to be rendered. Preservation is safe and predictable but slower, whereas disabling preservation is faster but can be unsafe and unpredictable. -
Why are rows, longer than my terminal, leaking to new lines?
Most terminals wrap text when it's longer than their current width. Resize your terminal or zoom out to fit long rows. If they still don't fit, useprint(f"\x1b[?7l{table}\x1b[?7h")to truncate the rows at the terminal width. Alternatively, usetable.export_txt(filepath)to export the plain table to a text file, and then open the file with a non-wrapping editor. -
Why are some colors not shown as expected?
Make sure you use your Operating System's native terminal to display the table. IDE, such as VS Code (old versions), offer a terminal that is not as complete as an OS's terminal. The missing features might be essential for rendering the table. So, either update your IDE to the latest version, or use your OS's terminal (Recommended). -
What is a
keywhen importing/exporting to JSON files?
A key is like an address where the rows and columns are stored (when importing) or are to be stored (when exporting). A key must only be used where a JSON file has or is to have an object root. For an array root, leave the key as None. Ideally a key must be like a table title, but it can be named anything. -
Are there any other import/export file types to be supported?
Yes, many of them. Excel files support (using openpyxl) is currently in beta phase. HTML and PDF files are in the alpha phase. These features will be released once they reach stable.
Contributing
Contributions are welcome and appreciated! Whether it's a bug report, feature suggestion, or a pull request, your input helps make Tabling a better tool for everyone.
Follow the following steps when contributing:
-
Fork the repository
Click the Fork button at the top right of the GitHub repository to create your own copy -
Clone your fork
git clone https://github.com/<your-username>/tabling.git cd tabling
-
Create a new branch
git checkout -b feature/my-new-feature
-
Make your changes
- Use tools like black, pylint, and mypy for code changes
- Make sure your changes do not break existing functionality
- Update documentation if needed
-
Commit your changes
git commit -m "feat: add my new feature"
-
Push your fork
git push origin feature/my-new-feature
-
Create a Pull Request
Go to the original repository and open a pull request with a clear description of your changes.
License
This project is licensed under the MIT License – see the LICENSE file for details.
Conclusion
Tabling makes it easy to create clean, customizable tables in the terminal. It’s fast, flexible, and built with a CSS-like approach that’s intuitive for anyone familiar with web design. Whether you're formatting data or building full console interfaces, Tabling gets out of your way and lets you focus on structure and style. Simple as that.
“Tabling is a great tool not because of what it does but because of what it enables you to do.” — Haripo Wesley T.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tabling-1.2.1.tar.gz.
File metadata
- Download URL: tabling-1.2.1.tar.gz
- Upload date:
- Size: 23.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef956230871064f64f86e221acd76aac20be0b089920d41129fd512a29d756ec
|
|
| MD5 |
8ab07f871587f2046b9cd2b9a19cfd32
|
|
| BLAKE2b-256 |
9b70a16dd464e2cff39b787b0ec806c29723ee4e2dee0c7bc6195b7f916bb4cb
|
File details
Details for the file tabling-1.2.1-py3-none-any.whl.
File metadata
- Download URL: tabling-1.2.1-py3-none-any.whl
- Upload date:
- Size: 21.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df674a360c09637a6c546d614ecaef22a7102790258a303826994a78e263fec6
|
|
| MD5 |
7cc042b2b743576ee84d7272491d3a80
|
|
| BLAKE2b-256 |
6666e8e3a1ebd3ecb3bd6d19964a53df04f23f5bd8c090d7ba474664c796039b
|