:~^:. :YJ?! .Y&J?^
%@@P! :GG&! ~@@&: .PGP? B@&~.
!@@% :&@J ^@@? .#@B. G@# ^!.
!@@% !^ :&@? ^@@? #@G :%~~~~~~~~~~~~~~^B@#~^~~~~~~~~~Y@@#Y^
~?!!!J@@Y~Y&&P^.&@&~!!!?&@&!!!!!&@B :!!~~~~~~~~~~~~~~B@&~~~~~~~~~~~~~~~!^
:~^:^::::%Y?%~.:@@J::::::::::::^PBY G@#
:& &@@?:.:%%: .. .... ^PG?: G@# .?~
PG B@& JJ%%%%%%?B#G?%%%%%J&&&J: ^?!!~~~~~~~~~~B@&!~~~~~~~%B@@B%.
~@P :@&: %@B^ .!~^^^^^^^^^P@@@&G!^^^^^^^^^^^~.
.#@? ?@J :&?^:::^#&:.:..::::JP?^ :G@G#@#~P%
P@G G#. .&@P!!%#@Y!!Y&#%!!%@@&% .Y@&? G@# :PB!
Y@! ^&~ ::.#@J .&@% !@&. #@% .J&&J. G@#. %##J:
.. YB%??!..#@J .#@% %@&. .#@% ^Y#B%. G@#. .?#@G?^.
.^!?&GGJ!: .#@J .#@% %@&. .#@% .%PBY^ B@#. .%G@@#PJ!~^.
.P&&#&%^ .&@J .&@% %@&: #@% .~J&J~ B@#. ^JB@@@#J^
~#! :&@J .&@? ?@@^~!%&@% ^?!^ .#@&. :!J^
:#&? ?J^ ^J?..:P#P! B@#:
^GGGGGG^ %P~ .. %P! ?P^ ?Y~ .Y&: ?P^ ?GGGGGG:. ^YPPJ^ .&Y %P~
.~!@@%~: .&@G B@@~ P@! G@L: Y@@~ :@@P ^~&G&~^ !@B~!&@^ :B&. &B%
#&. J@%@~ B@@#.&@! G@@A /@@@~ Y@@%. Y@% !@G^. ^/ :B#. &B%
.#&: .&!^&G B@Y&.P@! G@#B@&PG@~ :@<^G% Y@% \&BBG% :B#. &B%
.#&: J@! #@~ B@!!@@@! G@^\J@^G@~ Y@! &@: Y@% .: .B@~ :B# &B%
.&@: .&&%%?@G B@% J@@! G@~ ^/ G@~ :@#%^J@% Y@% %@P~~J@^ .#B%~B@~
.PP. !B? &G: ?B~ &G~ YG^ YG^ %B% &P. !B? %PBG&~ :YGBP!
Tanmatsu (η«―ζ«; "terminal" in Japanese) is a Declarative TUI (Terminal User Interface) library, with layout features modelled after modern CSS.
Widget objects can be created by defining a class that inherits from the desired widget class.
For example, a CSS flexbox-style widget that contains a text box and a button can be created declaratively, like so:
class NiceFlexBox(widgets.FlexBox):
text_box = widgets.TextBox(text="Hello World!")
button = widgets.Button(label="Button 2", callback=None)
class Meta:
border_label = "Nice FlexBox"
nice_flex_box = NiceFlexBox()
or imperatively, like so:
children = {
'text_box': widgets.TextBox(text="Hello World!"),
'button': widgets.Button(label="Button 2", callback=None)
}
nice_flex_box = widgets.FlexBox(children=children, border_label="Nice FlexBox")
Tanmatsu supports either style. The declarative syntax should be familiar with anyone who's used Django models before.
which is given by the code:
from tanmatsu import Tanmatsu, widgets
class ButtonList(widgets.List):
class Meta:
border_label = "List"
children = [
widgets.Button(label="Button 1", callback=None),
widgets.Button(label="Button 2", callback=None),
widgets.Button(label="Button 3", callback=None),
]
item_height = 5
class VertSplit(widgets.FlexBox):
text_box = widgets.TextBox(border_label="Text Box", text="Hello World!")
text_log = widgets.TextLog(border_label="Text Log")
button_list = ButtonList()
class Meta:
flex_direction = widgets.FlexDirection.ROW
with Tanmatsu(title="Tanmatsu!") as t:
rw = VertSplit()
t.set_root_widget(rw)
for (i, v) in enumerate(rw.button_list.children):
v.callback = lambda i=i: rw.text_log.append_line(f"Button {i + 1} pressed")
t.loop()
pip install tanmatsu
https://tanmatsu.readthedocs.io/en/latest/
- π¨ Unicode support
- π© Multi-column character support (e.g.,
ο½ο½ο½ο½ο½ο½ο½ο½ο½
orζΌ’ε
) - π¨ Emoji support
- π© Multi-column character support (e.g.,
- π¨ Widgets
- π© Button
- π© Flexbox
- π© flex-direction
- π© justify-content
- π¨ align-items
- π¨ align-content
- π¨ flex-wrap
- π¨ row-gap/column-gap
- π¨ Grid
- π© List
- π© Tab Box
- π© Text Box
- π© Fully editable
- π© Line wrap
- π© Text Log
- π© Scrolling
- π© Tab/Shift+Tab navigation
- π¨ MacOS support
- Python >=3.11
- GNU/Linux
- Full-featured terminal emulator (e.g., Gnome VTE)
- A font with unicode symbols (e.g., Noto)
- tri.declarative
- parsy
- wcwidth
Development dependencies:
- sphinx
- isort
- mypy
- If not running python 3.11, install pyenv.
- Install poetry.
- Run
poetry install
from the repository directory to set up a virtual environment with the necessary python version and packages - Run
fish scripts/installgithooks.fish
to install the appropriate git hooks.
poetry run python3 main.py
poetry run python3 -m unittest
See CHANGELOG.md.
MIT License. For more information, see LICENSE.md.