Building TUIs with Textual

 


 

whoami

Bill Melvin

 


 

At work in 1994

Bill at work in 1994

Probably working on a Turbo/Borland Pascal program, in a text-only interface, on a PC running MS-DOS.

I suppose in 1994, it could have been running Windows 3.1, but I don't recall.

 


 

Original Console / Terminal

IBM PC

 


 

Graphical User Interface (GUI)

The Graphical user interface has largely replaced the earlier text-based UIs.

The term Graphical User Interface may have been used more in the past to make the distinction between this new style versus the text-based user interfaces common at the time GUIs were introduced more widely.

 


 

GUI - Python - Desktop

There are multiple options for creating GUIs in Python:

 


 

GUI - Python - Web

Web applications are also GUIs, and Python has many options for creating them:

 


 

GUI - Python - Web/Desktop

PgAdmin4 is an example of a web application that can run locally or on a server.

PgAdmin4 screen

"pgAdmin 4 is a complete rewrite of pgAdmin, built using Python and Javascript/jQuery. A desktop runtime written in NWjs allows it to run standalone for individual users, or the web application code may be deployed directly on a web server for use by one or more users through their web browser."

 


 

Do you need a GUI?

If you're building a web, or mobile, application, the answer is yes (by default).

If you're building a utility that will run on a local machine, the answer is it depends.

 


 

Inputs to Python apps

CLI

Command-line arguments

Promps:

 


 

Python - input

Python input

Python output

 


 

TUI - Textual User Interface

Something in-between a CLI and a GUI

Why would you want to build a TUI?

 


 

Textual

How I heard about Textual

Podcast - Talk Python to Me

Talk Python to Me

Talk Python to Me logo

Episode #336 - Terminal magic with Rich and Textual

Episode #380 - 7 lessons from building a modern TUI framework

 


 

Podcast - Python Bytes

Python Bytes

Python Bytes logo

Episode #299 - Will McGugan drops by

 


 

Podcast - Real Python Podcast

Real Python Podcast

Real Python Podcast logo

Episode #80 - Make Your Python App Interactive With a Text User Interface (TUI)

Article: Python Community Interview With Will McGugan

 


 

Will McGugan

github.com/willmcgugan

Will McGugan GitHub

 


 

Will McGugan - Textualize/Rich

Textualize/rich

"Rich is a Python library for rich text and beautiful formatting in the terminal."

Rich screenshot

 


 

Textualize/Textual

textual.textualize.io

Textual Welcome Screen

 


 

Textual App Examples

bloomberg/memray: Memray is a memory profiler for Python

Textualize/frogmouth: A Markdown browser for your terminal

 


 

Tutorial

Tutorial

 


 

Aspects of Textual

 


 

My Application

A Pomodoro Timer

 


 

Pomodoro Technique

Wikipedia Pomodoro Technique

Pomodoro Technique

 


 

Pomodoro Timer - Classic

Tick, tick, tick... RING!

Pomodoro Timer

 


 

Pomodoro Timer - Home Office

This one beeps when it's done, but doesn't tick the whole time.

Digital Kitchen Timer

 


 

Pomodoro Timer - Cubicle Land

It can be set to blink quietly.

Digital Timer Blinks

 


 

Pomodoro Timer - Not!

Rana Timer

Well, it can be, if you want.

 


 

Spreadsheet

Pomodori Spreadsheet

 


 

Git

I use git for source code management.

Some projects are on GitHub. Others are pushed to a local git server.

Some projects, such as one-off utility scripts, are not in git at all, but are backed up locally (and off-site).

 


 

pipx

"pipx is made specifically for application installation, as it adds isolation yet still makes the apps available in your shell: pipx creates an isolated environment for each application and its associated packages."

I have been using pipx to install Python command-line applications (not libraries).

 


 

pipx - Install Python Applications

I use pipx to install some Python tools.

pipx install hatch

pipx install pgadmin4

I also like to install my own tools, outside of development, using pipx.

pipx install pomodorable

Packages don't have to be on PyPI, but you have to specify the path to a .whl file. One uploaded to a GitHub release will work.

pipx install image_snip@https://github.com/wmelvin/image-snip/releases/download/v2024.03.1/image_snip-2024.3.1-py3-none-any.whl

A .whl file uploaded to a web hosting platform will also work.

pipx install gitramble@https://bogusoft.com/packages/gitramble/gitramble-0.1.dev1-py3-none-any.whl

 


 

Project tools

 


 

ruff

 


 

Just

just a command runner

"just is a handy way to save and run project-specific commands. Commands, called recipes, are stored in a file called justfile with syntax inspired by make..."

I learned about just looking at some of Simon Willison's projects on GitHub. I saw a file named Justfile and wondered what it does.

 


 

Simon Willison

Simon Willison GitHub

 


 

Textual Development Tools

 


 

Showstoppers?

When planning a project, it is good to think about potential showstoppers.

 


 

A Toasty Requirement

For a Pomodoro Timer application to be useful, it needs to notify you when the countdown is finished.

It was encouraging to see that Textual has a Toast widget. Unfortunately, Textual's Toast widget only pops up in the terminal. I want a system notification.

Searching for a Python package to do system notifications turned up a few. Some were Windows-only. Some required installing additional system packages.

I settled on plyer:

 


 

Small POC to verify

Python script toasty

Ran on:

 


 

Project Setup

hatch init

Running hatch init creates scaffolding for a Python project.

I made some edits before doing the initial git commit.

 


 

Project Dependencies

Packages used

 


 

Application

Classes

AppConfig

AppData

UI(App)

 


 

Textual - Bindings

Bindings are declared in the App class.

BINDINGS

Actions are implemented with the method name starting with action_ followed by the action defined in the BINDINGS list.

Actions

The action descriptions show in the app's Footer.

Footer

 


 

Click for CLI

 


 

Testing a Textual App

Textual Guide: Testing

Snapshot testing for Textual apps: pytest-textual-snapshot

 


 

Using the App

Outputs

Data CSV - Stored in user app data location.

Daily CSV - Aligns with the layout of the spreadsheet I've been using for years.

Daily Markdown - Written to an Obsidian Daily Notes file.

 


 

Showstoppers? - Part II

Segfault

Segfault

 


 

What Else?

Some commits to look at (maybe):

Some aspects to look at in the code:

Gotchas

 


 

What's Next?

Possible Enhancements

Here are a few things I may (or may not) do with the Pomodorable app:

 


 

That's All

Thank you

wmelvin.dev


You can find more of my ramblings in my "stuff" repo on GitHub.