Skip to content

Textual Blog

Algorithms for high performance terminal apps

I've had the fortune of being able to work fulltime on a FOSS project for the last three plus years.

DemoApp Paul AtreidesLady JessicaBaron Vladimir HarkonnenLeto AtreidesStilgarChaniThufir Hawat ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Heir to House Atreides who becomes the Fremen messiah Muad'Dib. Born with extraordinary mental  abilities due to Bene Gesserit breeding program. TextArea A powerful and highly configurable text area that supports syntax highlighting, line numbers,  soft wrapping, and more. ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Python ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ 1  # Start building! 2  fromtextualimportApp,ComposeResult 3   4  TEXTUAL="1.0" 5  print("Welcome to Textual!") ▄▄ ▃▃ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁  ^s Screenshot ^p palette

Textual has been a constant source of programming challenges. Often frustrating but never boring, the challenges arise because the terminal "specification" says nothing about how to build a modern User Interface. The building blocks are there: after some effort you can move the cursor, write colored text, read keys and mouse movements, but that's about it. Everything else we had to build from scratch. From the most basic button to a syntax highlighted TextArea, and everything along the way.

I wanted to write-up some of the solutions we came up with, and the 1.0 milestone we just passed makes this a perfect time.

Anatomy of a Textual User Interface

My bad 🤦

The date is wrong on this post—it was actually published on the 2nd of September 2024. I don't want to fix it, as that would break the URL.

I recently wrote a TUI to chat to an AI agent in the terminal. I'm not the first to do this (shout out to Elia and Paita), but I may be the first to have it reply as if it were the AI from the Aliens movies?

Here's a video of it in action:

Now let's dissect the code like Bishop dissects a facehugger.

Behind the Curtain of Inline Terminal Applications

Textual recently added the ability to run inline terminal apps. You can see this in action if you run the calculator example:

Inline Calculator

The application appears directly under the prompt, rather than occupying the full height of the screen—which is more typical of TUI applications. You can interact with this calculator using keys or the mouse. When you press Ctrl+Q the calculator disappears and returns you to the prompt.

Here's another app that creates an inline code editor:

from textual.app import App, ComposeResult
from textual.widgets import TextArea


class InlineApp(App):
    CSS = """
    TextArea {
        height: auto;
        max-height: 50vh;
    }
    """

    def compose(self) -> ComposeResult:
        yield TextArea(language="python")


if __name__ == "__main__":
    InlineApp().run(inline=True)

This post will cover some of what goes on under the hood to make such inline apps work.

It's not going to go in to too much detail. I'm assuming most readers will be more interested in a birds-eye view rather than all the gory details.

Remote memory profiling with Memray

Memray is a memory profiler for Python, built by some very smart devs at Bloomberg. It is a fantastic tool to identify memory leaks in your code or other libraries (down to the C level)!

They recently added a Textual interface which looks amazing, and lets you monitor your process right from the terminal:

Memray

Things I learned building a text editor for the terminal

TextArea is the latest widget to be added to Textual's growing collection. It provides a multi-line space to edit text, and features optional syntax highlighting for a selection of languages.

text-area-welcome.gif

Adding a TextArea to your Textual app is as simple as adding this to your compose method:

yield TextArea()

Enabling syntax highlighting for a language is as simple as:

yield TextArea(language="python")

Working on the TextArea widget for Textual taught me a lot about Python and my general approach to software engineering. It gave me an appreciation for the subtle functionality behind the editors we use on a daily basis — features we may not even notice, despite some engineer spending hours perfecting it to provide a small boost to our development experience.

This post is a tour of some of these learnings.