littlejonny
Overview
Format output to a text table using unicode box characters.
Deprecated since version 1.6.0: Will be removed in 2.0.
In case you have been wondering, the name is a reference to https://xkcd.com/327/.
Classes
- class pymisclib.littlejonny.Box(origin_column: int = 1, origin_row: int = 1, width: int = 40, height: int = 20, line_style: ~pymisclib.littlejonny.LineStyle = LineStyle.light, border_style: str = '\x1b[30m\x1b[47m', text_style: str = '\x1b[34m\x1b[103m\x1b[1m', _text: list[str] = <factory>)
A box consisting of a frame with content.
- Constructor arguments:
- param int origin_column:
Top left corner column.
- param int origin_row:
Top left corner row.
- param int width:
Width in columns.
- param int height:
Height in rows.
- param LineStyle line_style:
Border line style.
- param str border_style:
Border color and font style expressed as ANSI format codes.
- param str text_style:
Content text color and font style expressed as ANSI format codes.
- flow_text(text: str, truncate: bool = True)
Flow the given text in to the current box.
- classmethod make_from_points(top_left: Point, bottom_right: Point, line_style: LineStyle = LineStyle.light) Box
Create a new Box instance with the given top left and bottom right points.
- render(output_format: OutputFormat) list[str]
Render the box in the given output_format.
- Parameters:
output_format¶ (OutputFormat) – Rendering format.
- Returns:
A list of lines rendering the instance.
- Rtype Text:
- border_style: str = '\x1b[30m\x1b[47m'
Rendering style (color and font style) of the border.
- height: int = 20
Height of the box in rows.
- line_style: LineStyle = Namespace(down_and_horizontal='┬', down_and_left='┐', down_and_right='┌', horizontal='─', up_and_horizontal='┴', up_and_left='┘', up_and_right='└', vertical='│', vertical_and_horizontal='┼', vertical_and_left='┤', vertical_and_right='├')
Style of the border characters.
- origin_column: int = 1
X-coordinate of the upper left corner of the box.
- origin_row: int = 1
Y-coordinate of the upper left corner of the box.
- property text: list[str]
Text contained in the box.
- text_style: str = '\x1b[34m\x1b[103m\x1b[1m'
Text style (color and font) of the content.
- width: int = 40
Width of the box in columns.
- class pymisclib.littlejonny.CellStyle(heading_style: str = '\x1b[1m', plain_style: str = '')
Styling to use for the cell.
- heading_style: str = '\x1b[1m'
Heading cell content style as a string of ANSI escape codes. Default is bold.
- plain_style: str = ''
Plain cell content style as a string of ANSI escape codes. Default is plain.
- class pymisclib.littlejonny.ColumnTable(_headings: list[str] = <factory>, _formats: list[str] = <factory>, _cells: list[list[~typing.Any]] = <factory>, _num_columns: int = 0, _num_rows: int = 0)
Table with data arranged by column.
Deprecated since version 2.0.0.
- __init__(_headings: list[str] = <factory>, _formats: list[str] = <factory>, _cells: list[list[~typing.Any]] = <factory>, _num_columns: int = 0, _num_rows: int = 0) None
- set_table(headings: list[str], cell_formats: list[str], cells: list[list[str]])
Set the content of the table with cells specified by column.
- Parameters:
Example
ct2 = ColumnTable() ct2.set_table( headings=['First', 'Second', 'Third', 'Fourth'], cell_formats=['3d', '08x', 's', '>s'], cells=[[1, 2, 12, 123, 1000], [0x12345678, 0xffffee01, -1, 0, 23], ['abc def geh', '12345', 'minus one', 'zero', 'First'], ['this is a sample text', 'Short', 'negative hex number', 'Zero hexadecimal number', 'The first column is too large.']] ) print_lines(ct2.draw(LineStyle.light))
Output:
┌───────┬──────────┬─────────────┬────────────────────────────────┐ │ First │ Second │ Third │ Fourth │ ├───────┼──────────┼─────────────┼────────────────────────────────┤ │ 1 │ 12345678 │ abc def geh │ this is a sample text │ │ 2 │ ffffee01 │ 12345 │ Short │ │ 12 │ -0000001 │ minus one │ negative hex number │ │ 123 │ 00000000 │ zero │ Zero hexadecimal number │ │ 1000 │ 00000017 │ First │ The first column is too large. │ └───────┴──────────┴─────────────┴────────────────────────────────┘
- set_table_transposed(headings: list[str], cell_formats: list[str], cells: list[list[str]])
Set the content of the table with cells specified by row.
- Parameters:
Example
ct1 = ColumnTable() ct1.set_table_transposed( headings=['First', 'Second', 'Third', 'Fourth'], cell_formats=['3d', '08x', 's', '>s'], cells=[[1, 0x12345678, 'abc def geh', 'this is a sample text'], [2, 0xffffee01, '12345', 'Short'], [12, -1, 'minus one', 'negative hex number'], [123, 0, 'zero', 'Zero hexadecimal number'], [1000, 23, 'First', 'The first column is too large.']] ) print_lines(ct1.draw(LineStyle.light))
Output:
┌───────┬──────────┬─────────────┬────────────────────────────────┐ │ First │ Second │ Third │ Fourth │ ├───────┼──────────┼─────────────┼────────────────────────────────┤ │ 1 │ 12345678 │ abc def geh │ this is a sample text │ │ 2 │ ffffee01 │ 12345 │ Short │ │ 12 │ -0000001 │ minus one │ negative hex number │ │ 123 │ 00000000 │ zero │ Zero hexadecimal number │ │ 1000 │ 00000017 │ First │ The first column is too large. │ └───────┴──────────┴─────────────┴────────────────────────────────┘
- property cell_formats: list[str]
Return cell formats by columns.
- property headings: list[str]
Return headings by column.
- property num_columns
Number of columns in the table.
- property num_rows
Number of rows in the table.
- class pymisclib.littlejonny.LineStyle(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Rendering style for lines.
- double = Namespace(down_and_horizontal='╦', down_and_left='╗', down_and_right='╔', horizontal='═', up_and_horizontal='╩', up_and_left='╝', up_and_right='╚', vertical='║', vertical_and_horizontal='╬', vertical_and_left='╣', vertical_and_right='╠')
Double line style ║.
- heavy = Namespace(down_and_horizontal='┳', down_and_left='┓', down_and_right='┏', horizontal='━', up_and_horizontal='┻', up_and_left='┛', up_and_right='┗', vertical='┃', vertical_and_horizontal='╋', vertical_and_left='┫', vertical_and_right='┣')
Heavy single line style ┃.
- light = Namespace(down_and_horizontal='┬', down_and_left='┐', down_and_right='┌', horizontal='─', up_and_horizontal='┴', up_and_left='┘', up_and_right='└', vertical='│', vertical_and_horizontal='┼', vertical_and_left='┤', vertical_and_right='├')
Light single line style │.
- class pymisclib.littlejonny.OutputFormat(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Format for rendering the output.
- ANSI = 1
Render for an ANSI terminal.
- TEXT = 2
Render as plain text.
- class pymisclib.littlejonny.Point(column: int = 1, row: int = 1)
Coordinate in column (x) / row (y) space.
- column: int = 1
- row: int = 1
- class pymisclib.littlejonny.Table(cells: list[list[~pymisclib.littlejonny.TableCell]] | None = None, logger: ~logging.Logger = <Logger pymisclib.littlejonny (WARNING)>, default_style: ~pymisclib.littlejonny.CellStyle = <factory>, column_widths: list[int] = <factory>)
Table made up of a rectangle of
TableCellinstances.- Constructor arguments:
- param list[list[TableCell]] | None cells:
Two-dimensional list of
TableCellinstances making up the table. The cells are organized by row and column (.e.g. cells[row][column]).- param logging.Logger logger:
Logger instance for diagnostics.
- param CellsStyle default_style:
All new cells start with this style.
- column(column_idx: int) list[TableCell]
Return the specified column of the table.
- Parameters:
column_idx¶ (int) – Column index [0..table.width[.
- Returns:
List of cells in the column ordered by row.
- Rtype list[TableCell]:
- Raises:
IndexError – Column was invalid
- column_width(column_idx: int) int
Return the configured width of the specified column.
- Parameters:
column_idx¶ (int) – Column index [0..table.width[.
- Returns:
Configured width of the column, or 0 to auto-size.
- Return type:
int
- Raises:
IndexError – Column was invalid
- populate(content: list[list[Any]], column_formats: list[str], column_alignment: list[str] | None = None)
Resize and populate a table with the given content.
- render(output_format: OutputFormat = OutputFormat.TEXT, line_style: LineStyle = LineStyle.light) list[str]
Render the table in the given format to a list of strings.
- Parameters:
output_format¶ (OutputFormat) – Format to render to.
line_style¶ (LineStyle) – Style used to render cell borders.
- Returns:
Rendered repsentation of the instance.
- Return type:
Text
- resize(width: int, height: int)
Resize the table to the given width and height.
- row(row_idx: int) list[TableCell]
Return the specified row of the table.
- Parameters:
row_idx¶ (int) – Row index [0..table.height[.
- Returns:
List of cells in the row, ordered by column.
- Rtype list[TableCell]:
- Raises:
IndexError – Column was invalid
- set_column_width(column_idx: int, width: int)
Set the width in characters of the given column..
- cells: list[list[TableCell]] | None = None
Cells, ordered by row and column, e.g. cells[row][column].
- column_widths: list[int]
- property height: int
Number of rows in the table.
- logger: Logger = <Logger pymisclib.littlejonny (WARNING)>
Logger instance for diagnostics.
- property width: int
Number of columns in the table.
- class pymisclib.littlejonny.TableCell(content: Any = '', fmt: str = 's', is_heading: bool = False, alignment: Alignment = Alignment.Right, style: CellStyle = None, join_right: bool = False, join_bottom: bool = False)
A single cell of a table.
- Constructor arguments:
- param Any content:
Content of the cell. Usually a string or number.
- param str fmt:
f-string format_spec to format the content.
- param bool is_heading:
True if the cell is a heading cell.
- param Alignment alignment:
Alignment of the formatted content in the cell.
- param CellStyle style:
Style of the rendered content.
- render(output_format: OutputFormat = OutputFormat.TEXT, width: int = 0) list[str]
Render the box in the given output_format.
- Parameters:
output_format¶ (OutputFormat) – Rendering format.
width¶ (int) – Width of the cell. If zero, the width is unconstrained and the content will not be aligned.
- Returns:
A list of lines representing the instance.
- Return type:
Text
- set(value: Any, fmt: str = '%s', justify: Alignment = Alignment.Right, is_heading: bool = False)
Set the value of the content and the format string for rendering.
- alignment: Alignment = '>'
- content: Any = ''
- fmt: str = 's'
- is_heading: bool = False
- join_bottom: bool = False
- join_right: bool = False
- pymisclib.littlejonny.Text
Type definition: a Text is a collection of lines, each of which is a string.
The lines are organized by row, so the first string in the list is the first text line.
Functions
- pymisclib.littlejonny.draw_box(x, y, style) list[str]
Construct a box of size x * y with style.
- pymisclib.littlejonny.print_lines(lines: list[str])
Print lines stored as a list of strings to stdout.
Boxes Example
from pymisclib.littlejonny import print_lines, Box, LineStyle, OutputFormat
from pymisclib.ansiterminal import BgColor, FgColor, TextStyle
b1 = Box(8, 3, 17, 9, LineStyle.light,
FgColor.Green.value + BgColor.White.value,
FgColor.Blue.value + BgColor.BrightYellow.value + TextStyle.Italic.value)
b1.text = [
'(8;7) (17;8)',
'',
'',
'',
' * ',
'',
'',
'',
'(8;16) (17;16)',
]
print_lines(b1.render(OutputFormat.TEXT))
This will yield:
┌─────────────────┐
│(8;7) (17;8)│
│ │
│ │
│ │
│ * │
│ │
│ │
│ │
│(8;16) (17;16)│
└─────────────────┘
If you use ANSI style
print_lines(b1.render(OutputFormat.ANSI))
The box will be placed in the terminal at the absolute coordinates over whatever the previous content was, and it will be rendered in color if your terminal supports color:
In [5]: from pymisclib.littlejonny import print_lines, Box, LineStyle, OutputFormat
...:┌─────────────────┐.ansiterminal import BgColor, FgColor, TextStyle
...:│(8;7) (17;8)│ 17, 9, LineStyle.light,
...:│ │or.Green.value + BgColor.White.value,
...:│ │or.Blue.value + BgColor.BrightYellow.value + TextStyle.Italic.value)
...:│ │
...:│ * │ (17;8)',
...:│ │
...:│ │
...:│ │
...:│(8;16) (17;16)│ ',
...:└─────────────────┘
...: '',
In [6]:
b2 = Box(1, 1, 64, 13, LineStyle.double,
FgColor.Red.value + BgColor.Green.value,
FgColor.Black.value + BgColor.BrightWhite.value + TextStyle.Bold.value)
b2.text = [
'',
' 2nd line: This is a line of text and it is much too long for this box.',
' 1 2 3 4 5 6 ',
'1234567890123456789012345678901234567890123456789012345678901234',
'',
' right',
'left',
' center',
]
print_lines(b2.render(OutputFormat.TEXT))
Yields:
╔════════════════════════════════════════════════════════════════╗
║ ║
║ 2nd line: This is a line of text and it is much too long for th║
║ 1 2 3 4 5 6 ║
║1234567890123456789012345678901234567890123456789012345678901234║
║ ║
║ right║
║left ║
║ center ║
║ ║
║ ║
║ ║
║ ║
║ ║
╚════════════════════════════════════════════════════════════════╝
from pymisclib.littlejonny import print_lines, Box, LineStyle, ColumnTable, OutputFormat
from pymisclib.ansiterminal import AnsiColor, BgColor, FgColor, TextStyle
b1 = Box(1, 1, 5, 3, LineStyle.light,FgColor.Green.value + BgColor.White.value,
FgColor.Blue.value + BgColor.BrightYellow.value, TextStyle.Italic.value)
b2 = Box(1, 6, 1, 1, LineStyle.double,
FgColor.Red.value, BgColor.Blue.value, TextStyle.Bold.value)
b2.text = '*'
b3 = Box(5, 9, 40, 3, LineStyle.heavy, FgColor.White.value + AnsiColor(128, 128, 128).bg, FgColor.Green.value + BgColor.BrightYellow.value, TextStyle.Underline.value)
b3.text = 'The quick brown fox jumps over the lazy dog.'
for b in [b1, b2, b3]:
print_lines(b.render(OutputFormat.TEXT))
for b in [b1, b2, b3]:
print_lines(b.render(OutputFormat.ANSI))
ct1 = ColumnTable()
ct1.set_table_transposed(
headings=['First', 'Second', 'Third', 'Fourth'],
cell_formats=['3d', '08x', 's', '>s'],
cells=[[1, 0x12345678, 'abc def geh', 'this is a sample text'],
[2, 0xffffee01, '12345', 'Short'],
[12, -1, 'minus one', 'negative hex number'],
[123, 0, 'zero', 'Zero hexadecimal number'],
[1000, 23, 'First', 'The first column is too large.']]
)
print_lines(ct1.draw(LineStyle.light))
This will yield:
┌─────┐
│ │
│ │
│ │
└─────┘
╔═╗
║ ║
╚═╝
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ┃
┃ ┃
┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┌───────┬──────────┬─────────────┬────────────────────────────────┐
│ First │ Second │ Third │ Fourth │
├───────┼──────────┼─────────────┼────────────────────────────────┤
│ 1 │ 12345678 │ abc def geh │ this is a sample text │
│ 2 │ ffffee01 │ 12345 │ Short │
│ 12 │ -0000001 │ minus one │ negative hex number │
│ 123 │ 00000000 │ zero │ Zero hexadecimal number │
│ 1000 │ 00000017 │ First │ The first column is too large. │
└───────┴──────────┴─────────────┴────────────────────────────────┘
Tables
A Table is made up of instances of TableCell. Each
TableCell instance can hold a value, as well a alignment,
formatting, and style information.
When rendering the table, each cell is rendered using the format, width, alignment, and style specified, in this order.
Each cell in a column of the table has the same width. Unless specified otherwise, the width of each column is the width of the widest cell in the column.
If the content of a cell will not fit into the column width, it will be truncated.
Rendering can be done in several formats:
- ANSI
Use ANSI formatting codes to style the output.
- TEXT
Plain Unicode text rendering.