littlejonny

Overview

Format output to a text table using unicode box characters.

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.

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.

Parameters:
  • top_left (Point) – starting point in the upper left corner.

  • bottom_right (Point) – ending point (inclusive) in the lower right corner.

  • line_style (LineStyle) – Style to use when rendering the box.

Returns:

An initialized instance.

Rtype Box:

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.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.

__init__(_headings: list[str] = <factory>, _formats: list[str] = <factory>, _cells: list[list[~typing.Any]] = <factory>, _num_columns: int = 0, _num_rows: int = 0) None
draw(style: LineStyle) list[str]

Render the table to a list of lines.

Parameters:

style (LineStyle) – The line style to use for the table.

Rtype Text:

Returns:

A list of rows which make up the rendered table.

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:
  • headings (list[str]) – List of headings.

  • cell_formats (list[str]) – List of cell formats for each column. The formats use the same format-language as Python format strings.

  • cells (list[str]) – Matrix of cell contents, specified column[row].

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:
  • headings (list[str]) – List of headings.

  • cell_formats (list[str]) – List of cell formats for each column.

  • cells (list[str]) – Matrix of cell contents, specified row[column].

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='╠')
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='┣')
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='├')
class pymisclib.littlejonny.OutputFormat(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Format for rendering the output.

ANSI = 1
TEXT = 2
class pymisclib.littlejonny.Point(column: int = 1, row: int = 1)

Coordinate in column (x) / row (y) space.

__init__(column: int = 1, row: int = 1) None
column: int = 1
row: int = 1
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.

Example

from pymisclib.littlejonny import draw_box, print_lines, LineStyle, ColumnTable
print_lines(draw_box(5, 3, LineStyle.light))
print_lines(draw_box(1, 1, LineStyle.double))
print_lines(draw_box(40, 3, LineStyle.heavy))

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. │
└───────┴──────────┴─────────────┴────────────────────────────────┘