Textual is a TUI (Text User Interface) framework for Python using Rich as a renderer.



Textual is a TUI (Text User Interface) framework for Python using Rich as a renderer.

The end goal is to be able to rapidly create rich terminal applications that look as good as possible (within the restrictions imposed by a terminal emulator).

Rich TUI will integrate tightly with its parent project, Rich. Any of the existing renderables can be used in a more dynamic application.

This project is currently a work in progress and may not be usable for a while. Follow @willmcgugan for progress updates, or post in Discussions if you have any requests / suggestions.


  • Implement Windows Driver

    Implement Windows Driver

    Trying to run the textual.app example on Windows 10 with Python 3.9.5:

    ➜ python -m textual.app
    Traceback (most recent call last):
     File "C:\Program Files\Python39\lib\runpy.py", line 197, in _run_module_as_main
       return _run_code(code, main_globals, None,
     File "C:\Program Files\Python39\lib\runpy.py", line 87, in _run_code
       exec(code, run_globals)
     File "C:\CodeProjects\Python\Manim\manimvenv\lib\site-packages\textual\app.py", line 19, in <module>
       from .driver import Driver
     File "C:\CodeProjects\Python\Manim\manimvenv\lib\site-packages\textual\driver.py", line 8, in <module>
       import curses
     File "C:\Program Files\Python39\lib\curses\__init__.py", line 13, in <module>
       from _curses import *
    ModuleNotFoundError: No module named '_curses'
    opened by kilacoda-old 29
  • As of 0.6.0, bindings on (at least) `left`, `right`, `up` and `down` no longer appear to work

    As of 0.6.0, bindings on (at least) `left`, `right`, `up` and `down` no longer appear to work

    With Textual 0.5.0 I had bindings on the arrow keys that worked fine. Having upgraded to 0.6.0 those bindings no longer seem to work. Isolating the issue I can recreate with this code (some other keys thrown in as control tests)

    from textual.app import App, ComposeResult
    from textual.widgets import TextLog, Header, Footer
    from textual.binding import Binding
    from textual.events import Key
    class Binder( App[ None ] ):
        CSS = """
        TextLog {
            background: #222200;
            color: #BBBB00;
            text-style: bold;
        BINDINGS = [
            Binding( "up",    "log( 'up' )", "Up" ),
            Binding( "down",  "log( 'down' )", "Down" ),
            Binding( "left",  "log( 'left' )", "Left" ),
            Binding( "right", "log( 'right' )", "Right" ),
            Binding( "a", "log( 'a' )", "a" ),
            Binding( "s", "log( 's' )", "s" ),
            Binding( "d", "log( 'd' )", "d" ),
            Binding( "f", "log( 'f' )", "f" ),
            Binding( "left_square_bracket", "log( '[' )", "[" ),
            Binding( "right_square_bracket", "log( ']' )", "]" ),
        def compose( self ) -> ComposeResult:
            yield Header()
            yield TextLog()
            yield Footer()
        def on_mount( self ) -> None:
            self.query_one( TextLog ).write( "Ready..." )
            self.query_one( TextLog ).write( "Key bindings being looked for:" )
            self.query_one( TextLog ).write( ", ".join(
                [ binding.key for binding in self.BINDINGS ]
            ) )
        def action_log( self, name: str ) -> None:
            self.query_one( TextLog ).write( f"Via binding: {name}" )
        def on_key( self, event: Key ) -> None:
            self.query_one( TextLog ).write( f"Via event: {event!r}" )
    if __name__ == "__main__":

    Running the above, pressing the arrow keys vs some of the other keys...

    Screenshot 2022-12-12 at 11 25 12

    opened by davep 21
  • Method to run code in a thread

    Method to run code in a thread

    I'd like to add a convenient method to execute in job in a thread.

    It would probably be added to message pump (used by app / widgets).

    It should allow a method to be called with arbitrary parameters, and should return an awaitable.

    await self.call_threaded(my_code, "foo", "bar")

    I can see this being used for jobs such as reading from disk (which at the moment blocks the vent loop).

    Some considerations: a thread pool may be appropriate. We don't want this to be unbounded and potentially launch an unlimited number of threads. It should probably work with both async and sync functions, which will require a little inspection. If you want to tackle this, please discuss your ideas here first.

    help wanted level:moderate 
    opened by willmcgugan 16
  • error when running examples

    error when running examples

    i installed textual with pip and i tried to run the first example in the readme with python3 filename.py but i get the error TypeError: on_key() takes 1 positional argument but 2 were given when i press a key. got a similiar error with another example. sorry if im being dumb : p

    opened by itsUrcute 16
  • Add more easing functions

    Add more easing functions

    There are a number of 'easing functions' used by the animation system. At the top of _animator.py you will see the following:

    EASING = {
        "none": lambda x: 1.0,
        "round": lambda x: 0.0 if x < 0.5 else 1.0,
        "linear": lambda x: x,
        "in_cubic": lambda x: x * x * x,
        "in_out_cubic": lambda x: 4 * x * x * x if x < 0.5 else 1 - pow(-2 * x + 2, 3) / 2,
        "out_cubic": lambda x: 1 - pow(1 - x, 3),

    These function have been copied from https://easings.net/ and translated from Javascript to Python. I would like to add the remaining functions to the EASING dict above.

    See the animation.py example as a way of testing the above functions.

    help wanted good first issue 
    opened by willmcgugan 15
  • [colors] Add a

    [colors] Add a "auto" color

    When text has color: auto [percentage] it will be displayed with the contrasting colour of its background

    As a result we can have widgets that have color: auto; in their CSS, and see their text colour automatically adapted to their background: Screenshot from 2022-06-29 14-33-56

    opened by olivierphi 14
  • feat: initial datatable reactive values

    feat: initial datatable reactive values

    For #1164, adds the six reactive attributes listed in the docs for DataTable to __init__. I noticed the class has three more reactive attributes (cursor_type, cursor_cell, and hover_cell) that aren't listed, but I left those out. Let me know if any of them should also be included.

    opened by aaronst 13
  • Unclosed event loop with easing example

    Unclosed event loop with easing example

    Every time I close the easing example. I get the following error:

    /usr/lib/python3.9/asyncio/base_events.py:681: ResourceWarning: unclosed event loop <_UnixSelectorEventLoop running=False closed=False debug=False>
      _warn(f"unclosed event loop {self!r}", ResourceWarning, source=self)
    ResourceWarning: Enable tracemalloc to get the object allocation traceback

    I am thinking there are still messages processing at shutdown that are keeping the loop running, but I have not been able to track down the root cause yet.

    Possibly a similar issue to #82?

    OS: Manjaro Linux 21.1.4

    opened by sanders41 13
  • Live console widget

    Live console widget

    It would be nice to have a widget that behaves like a console. At first, just able to print and auto-scroll, and scroll bar, with auto-refresh. console.print("another brick in the wall")

    Maybe reuse Rich's Live View / Console?

    opened by hajdbo 13
  • Wrong CSS styles being applied on hover

    Wrong CSS styles being applied on hover

    I noticed this when adding semantic style variants for Button.

    When I hover over the warning button, the border is being set to tall $primary-lighten-3. I would expect it to be set to tall $warning-lighten-3 given Button.-warning has higher specificity.

    Relevant CSS

        Button {
            border: tall $primary-lighten-3;
        Button.-warning {
            background: $warning;
            color: $text-warning;
            border: tall $warning-lighten-3;  
        Button.-warning :hover {
            background: $warning-darken-1;
            color: $text-warning-darken-1; 
    opened by darrenburns 12
  • Tabbed Widget

    Tabbed Widget


    This PR adds a widget that enables the user to define multiple views as so called tabs and receive a automagically generated bar of tab handles to switch between said views.

    🖼 Some Pictures

    The example code introduced in this PR produces the following: Screenshot 2021-08-11 at 19 09 04 Screenshot 2021-08-11 at 19 09 08 Screenshot 2021-08-11 at 19 09 11

    Some additional info

    • All 4 modes a tab handle can be in are "user-stylable". Those being default, hover, selected, and hover+selected.
    • The type of view a tab uses can be given by the user upon tab creation. Though this is not strictly necessary thanks to DockView.dock_grid().
    opened by timfi 12
  • Scroll optimization

    Scroll optimization

    • Calculates resized widgets more efficiently
    • Added Widget._refresh_scroll to scroll without expensive layout operation
    • Potentially reduced needless repaints
    • Various micro-optimizations
    opened by willmcgugan 0
  • Make default filename for screenshots use ISO8601 datetime format

    Make default filename for screenshots use ISO8601 datetime format

    Currently, the save_screenshot function uses a datetime format by default that (a) introduces spaces to the resulting filename and (b) does not match what is specified in the doc-string. This PR will replace those spaces and bring the datetime format closer to the ISO8601 format. (Since colons are a reserved character, the format will not exactly match ISO8601.)

    Before: (the filename for a screenshot may look like)
    demo 20230107 205720 203616.svg

    After: (the filename for a screenshot may look like)

    • [X] Docstrings on all new or modified functions / classes
    • [X] Updated documentation
    • [X] Updated CHANGELOG.md (where appropriate)

    Feedback welcome

    opened by edrogers 0
  • Call from thread method

    Call from thread method

    This is a step towards having an answer to devs who want to integrate a third-party API with Textual.

    The call_from_thread takes a callback that will be called in the app's loop from a thread. It will block until the callback returns. If integrating with a threaded API (many are under the hood), this will generally give the most predictable behaviour.

    There are downsides: you call it from the same thread as the app. Otherwise it would deadlock.

    I'll leave this method undocumented for now. We will at least have an answer for the next version, and we can work on greater syntactical sugar in the meantime.

    opened by willmcgugan 0
  • Text Log widget cannot select app.console

    Text Log widget cannot select app.console

    I have Text Log widget implemented in a multithreaded app that is receiving callbacks from another python (Lightstreamer) class. More often than not when using the write method of the TextLog class when it tries to map to self.app.console (line 94):

    console = self.app.console

    the debugger throws an error saying it cannot find the app.

    I worked around this by making the assignment during the class initialization. It seems to work fine then. It seems like it loses the app context somehow.

    My fixes:

    from typing import cast
    from rich.console import RenderableType
    from rich.highlighter import ReprHighlighter
    from rich.measure import measure_renderables
    from rich.pretty import Pretty
    from rich.protocol import is_renderable
    from rich.segment import Segment
    from rich.text import Text
    from ..reactive import var
    from ..geometry import Size, Region
    from ..scroll_view import ScrollView
    from .._cache import LRUCache
    from .._segment_tools import line_crop
    from .._types import Lines
    class TextLog(ScrollView, can_focus=True):
        DEFAULT_CSS = """    
            background: $surface;
            color: $text;       
            overflow-y: scroll;
        max_lines: var[int | None] = var(None)
        min_width: var[int] = var(78)
        wrap: var[bool] = var(False)
        highlight: var[bool] = var(False)
        markup: var[bool] = var(False)
        def __init__(
            max_lines: int | None = None,
            min_width: int = 78,
            wrap: bool = False,
            highlight: bool = False,
            markup: bool = False,
            name: str | None = None,
            id: str | None = None,
            classes: str | None = None,
        ) -> None:
            super().__init__(name=name, id=id, classes=classes)
            self.max_lines = max_lines
            self._start_line: int = 0
            self.lines: list[list[Segment]] = []
            self._line_cache: LRUCache[tuple[int, int, int, int], list[Segment]]
            self._line_cache = LRUCache(1024)
            self.max_width: int = 0
            self.min_width = min_width
            self.wrap = wrap
            self.highlight = highlight
            self.markup = markup
            self.highlighter = ReprHighlighter()
            self.myconsole = self.app.console
        def _on_styles_updated(self) -> None:
        def write(self, content: RenderableType | object) -> None:
            """Write text or a rich renderable.
                content (RenderableType): Rich renderable (or text).
            renderable: RenderableType
            if not is_renderable(content):
                renderable = Pretty(content)
                if isinstance(content, str):
                    if self.markup:
                        renderable = Text.from_markup(content)
                        renderable = Text(content)
                    if self.highlight:
                        renderable = self.highlighter(renderable)
                    renderable = cast(RenderableType, content)
            #console = self.app.console
            render_options = self.myconsole.options
            if isinstance(renderable, Text) and not self.wrap:
                render_options = render_options.update(overflow="ignore", no_wrap=True)
            width = max(
                measure_renderables(self.myconsole, render_options, [renderable]).maximum,
            segments = self.myconsole.render(
                renderable, render_options.update_width(width)
            lines = list(Segment.split_lines(segments))
            if not lines:
            self.max_width = max(
                max(sum(segment.cell_length for segment in _line) for _line in lines),
            if self.max_lines is not None and len(self.lines) > self.max_lines:
                self._start_line += len(self.lines) - self.max_lines
                self.lines = self.lines[-self.max_lines :]
            self.virtual_size = Size(self.max_width, len(self.lines))
            self.scroll_end(animate=False, speed=100)
        def clear(self) -> None:
            """Clear the text log."""
            del self.lines[:]
            self._start_line = 0
            self.max_width = 0
            self.virtual_size = Size(self.max_width, len(self.lines))
        def render_line(self, y: int) -> list[Segment]:
            scroll_x, scroll_y = self.scroll_offset
            line = self._render_line(scroll_y + y, scroll_x, self.size.width)
            line = list(Segment.apply_style(line, self.rich_style))
            return line
        def render_lines(self, crop: Region) -> Lines:
            """Render the widget in to lines.
                crop (Region): Region within visible area to.
                Lines: A list of list of segments
            lines = self._styles_cache.render_widget(self, crop)
            return lines
        def _render_line(self, y: int, scroll_x: int, width: int) -> list[Segment]:
            if y >= len(self.lines):
                return [Segment(" " * width, self.rich_style)]
            key = (y + self._start_line, scroll_x, width, self.max_width)
            if key in self._line_cache:
                return self._line_cache[key]
            line = self.lines[y]
            line = Segment.adjust_line_length(
                line, max(self.max_width, width), self.rich_style
            line = line_crop(line, scroll_x, scroll_x + width, self.max_width)
            self._line_cache[key] = line
            return line
    opened by scp7 2
  • Fix

    Fix "tree scrolls back to left"

    this is a proposal for fixing #1453. This passes tests for my locally.

    along the way:

    make Tree._refresh_node somewhat more efficient by: * stopping early * coallescing multiple refresh() calls of single lines into one call

    change "TreeControl" to "Tree" in a few texts (and funny enough, in demo.css, which doesn't even use it);

    remove the (appearantly dead) Tree._refresh_node_line

    Please review the following checklist.

    • [ ] Docstrings on all new or modified functions / classes
    • [ ] Updated documentation
    • [ ] Updated CHANGELOG.md (where appropriate)
    opened by nitzan-shaked 2
  • v0.9.1(Dec 30, 2022)

    Only Python 3.11 has a high resolution sleep by default. This adds a more accurate sleep for windows on Python < 3.11

    [0.9.1] - 2022-12-30


    • Added textual._win_sleep for Python on Windows < 3.11 https://github.com/Textualize/textual/pull/1457
    Source code(tar.gz)
    Source code(zip)
  • v0.9.0(Dec 30, 2022)

    No new functionality so speak of, but performance has improved over the 0.8.x version. A change to how rendered content is stored has made updates faster.

    There is also a fix for slow updates on Windows. See this blog post for details.

    This is likely the last release of the year, so I would like to share this music video which seems strangely appropriate.


    [0.9.0] - 2022-12-30


    • Added textual.strip.Strip primitive
    • Added textual._cache.FIFOCache
    • Added an option to clear columns in DataTable.clear() https://github.com/Textualize/textual/pull/1427


    • Widget.render_line now returns a Strip
    • Fix for slow updates on Windows
    • Bumped Rich dependency
    Source code(tar.gz)
    Source code(zip)
  • v0.8.2(Dec 28, 2022)

  • v0.8.1(Dec 25, 2022)

    I really should be pealing potatoes.

    [0.8.1] - 2022-12-25


    • Fix for overflowing tree issue https://github.com/Textualize/textual/issues/1425
    Source code(tar.gz)
    Source code(zip)
  • v0.8.0(Dec 22, 2022)

    Version 0.8.0 adds a new textual keys command which you can use to preview key events.

    There are a few minor breaking changes in this release. See below for details.

    Screenshot 2022-12-22 at 13 08 11

    [0.8.0] - 2022-12-22


    • Fixed issues with nested auto dimensions https://github.com/Textualize/textual/issues/1402
    • Fixed watch method incorrectly running on first set when value hasn't changed and init=False https://github.com/Textualize/textual/pull/1367
    • App.dark can now be set from App.on_load without an error being raised https://github.com/Textualize/textual/issues/1369
    • Fixed setting visibility changes needing a refresh https://github.com/Textualize/textual/issues/1355


    • Added textual.actions.SkipAction exception which can be raised from an action to allow parents to process bindings.
    • Added textual keys preview.
    • Added ability to bind to a character in addition to key name. i.e. you can bind to "." or "full_stop".
    • Added TextLog.shrink attribute to allow renderable to reduce in size to fit width.


    • Deprecated PRIORITY_BINDINGS class variable.
    • Renamed char to character on Key event.
    • Renamed key_name to name on Key event.
    • Queries/walk_children no longer includes self in results by default https://github.com/Textualize/textual/pull/1416
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Dec 17, 2022)

    Mostly fixes in this release.

    [0.7.0] - 2022-12-17


    • Added PRIORITY_BINDINGS class variable, which can be used to control if a widget's bindings have priority by default. https://github.com/Textualize/textual/issues/1343


    • Renamed the Binding argument universal to priority. https://github.com/Textualize/textual/issues/1343
    • When looking for bindings that have priority, they are now looked from App downwards. https://github.com/Textualize/textual/issues/1343
    • BINDINGS on an App-derived class have priority by default. https://github.com/Textualize/textual/issues/1343
    • BINDINGS on a Screen-derived class have priority by default. https://github.com/Textualize/textual/issues/1343
    • Added a message parameter to Widget.exit


    • Fixed validator not running on first reactive set https://github.com/Textualize/textual/pull/1359
    • Ensure only printable characters are used as key_display https://github.com/Textualize/textual/pull/1361
    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Dec 11, 2022)

    See the blog post for the low down on this release.

    [0.6.0] - 2022-12-11


    • Added "inherited bindings" -- BINDINGS classvar will be merged with base classes, unless inherit_bindings is set to False
    • Added Tree widget which replaces TreeControl.
    • Added widget Placeholder https://github.com/Textualize/textual/issues/1200.


    • Rebuilt DirectoryTree with new Tree control.
    • Empty containers with a dimension set to "auto" will now collapse instead of filling up the available space.
    • Container widgets now have default height of 1fr.
    • The default width of a Label is now auto.


    • Type selectors can now contain numbers https://github.com/Textualize/textual/issues/1253
    • Fixed visibility not affecting children https://github.com/Textualize/textual/issues/1313
    • Fixed issue with auto width/height and relative children https://github.com/Textualize/textual/issues/1319
    • Fixed issue with offset applied to containers https://github.com/Textualize/textual/issues/1256
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Nov 20, 2022)

    [0.5.0] - 2022-11-20


    • Add get_child_by_id and get_widget_by_id, remove get_child https://github.com/Textualize/textual/pull/1146
    • Add easing parameter to Widget.scroll_* methods https://github.com/Textualize/textual/pull/1144
    • Added Widget.call_later which invokes a callback on idle.
    • DOMNode.ancestors no longer includes self.
    • Added DOMNode.ancestors_with_self, which retains the old behaviour of DOMNode.ancestors.
    • Improved the speed of DOMQuery.remove.
    • Added DataTable.clear
    • Added low-level textual.walk methods.
    • It is now possible to await a Widget.remove. https://github.com/Textualize/textual/issues/1094
    • It is now possible to await a DOMQuery.remove. Note that this changes the return value of DOMQuery.remove, which used to return self. https://github.com/Textualize/textual/issues/1094
    • Added Pilot.wait_for_animation
    • Added Widget.move_child https://github.com/Textualize/textual/issues/1121
    • Added a Label widget https://github.com/Textualize/textual/issues/1190
    • Support lazy-instantiated Screens (callables in App.SCREENS) https://github.com/Textualize/textual/pull/1185
    • Display of keys in footer has more sensible defaults https://github.com/Textualize/textual/pull/1213
    • Add App.get_key_display, allowing custom key_display App-wide https://github.com/Textualize/textual/pull/1213


    • Watchers are now called immediately when setting the attribute if they are synchronous. https://github.com/Textualize/textual/pull/1145
    • Widget.call_later has been renamed to Widget.call_after_refresh.
    • Button variant values are now checked at runtime. https://github.com/Textualize/textual/issues/1189
    • Added caching of some properties in Styles object


    • Fixed DataTable row not updating after add https://github.com/Textualize/textual/issues/1026
    • Fixed issues with animation. Now objects of different types may be animated.
    • Fixed containers with transparent background not showing borders https://github.com/Textualize/textual/issues/1175
    • Fixed auto-width in horizontal containers https://github.com/Textualize/textual/pull/1155
    • Fixed Input cursor invisible when placeholder empty https://github.com/Textualize/textual/pull/1202
    • Fixed deadlock when removing widgets from the App https://github.com/Textualize/textual/pull/1219
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Nov 8, 2022)

    Read the blog post: https://textual.textualize.io/blog/2022/11/08/version-040/#version-040

    [0.4.0] - 2022-11-08


    • Dropped support for mounting "named" and "anonymous" widgets via App.mount and Widget.mount. Both methods now simply take one or more widgets as positional arguments.
    • DOMNode.query_one now raises a TooManyMatches exception if there is more than one matching node. https://github.com/Textualize/textual/issues/1096
    • App.mount and Widget.mount have new before and after parameters https://github.com/Textualize/textual/issues/778


    • Added init param to reactive.watch
    • CSS_PATH can now be a list of CSS files https://github.com/Textualize/textual/pull/1079
    • Added DOMQuery.only_one https://github.com/Textualize/textual/issues/1096
    • Writes to stdout are now done in a thread, for smoother animation. https://github.com/Textualize/textual/pull/1104
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Oct 31, 2022)

    A number of fixes, and internal enhancements.

    We have a new API for running textual apps asynchronously, and a much better way of running integration tests. Testing is important and we will be documenting this in a future release.

    Also in this release, we've made fr units more useful. These CSS units can be used to easily create flexible layouts. See the video below:


    Here's the full changelog

    [0.3.0] - 2022-10-31


    • Fixed issue where scrollbars weren't being unmounted
    • Fixed fr units for horizontal and vertical layouts https://github.com/Textualize/textual/pull/1067
    • Fixed textual run breaking sys.argv https://github.com/Textualize/textual/issues/1064
    • Fixed footer not updating styles when toggling dark mode
    • Fixed how the app title in a Header is centred https://github.com/Textualize/textual/issues/1060
    • Fixed the swapping of button variants https://github.com/Textualize/textual/issues/1048
    • Fixed reserved characters in screenshots https://github.com/Textualize/textual/issues/993
    • Fixed issue with TextLog max_lines https://github.com/Textualize/textual/issues/1058


    • DOMQuery now raises InvalidQueryFormat in response to invalid query strings, rather than cryptic CSS error
    • Dropped quit_after, screenshot, and screenshot_title from App.run, which can all be done via auto_pilot
    • Widgets are now closed in reversed DOM order
    • Input widget justify hardcoded to left to prevent text-align interference
    • Changed textual run so that it patches argv in more situations
    • DOM classes and IDs are now always treated fully case-sensitive https://github.com/Textualize/textual/issues/1047


    • Added Unmount event
    • Added App.run_async method
    • Added App.run_test context manager
    • Added auto_pilot to App.run and App.run_async
    • Added Widget._get_virtual_dom to get scrollbars
    • Added size parameter to run and run_async
    • Added always_update to reactive
    • Returned an awaitable from push_screen, switch_screen, and install_screen https://github.com/Textualize/textual/pull/1061
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Oct 22, 2022)

  • v0.2.0(Oct 22, 2022)

    This is a merge of the CSS branch with a whole load of amazing features. Hope you enjoy.

    We are now returning to regular releases and working in the open. Thanks for being patient.

    What's Changed

    • Outline by @willmcgugan in https://github.com/Textualize/textual/pull/195
    • Hover pseudo class by @willmcgugan in https://github.com/Textualize/textual/pull/201
    • Rename visible property to display, add setter by @darrenburns in https://github.com/Textualize/textual/pull/213
    • Visibility by @darrenburns in https://github.com/Textualize/textual/pull/212
    • Splitting out parsing of durations into new token types, avoiding Scalar by @darrenburns in https://github.com/Textualize/textual/pull/214
    • Invisible widgets now dont render by @darrenburns in https://github.com/Textualize/textual/pull/219
    • Use the layout as specified in CSS by @darrenburns in https://github.com/Textualize/textual/pull/225
    • Margin spacing is now invisible by @darrenburns in https://github.com/Textualize/textual/pull/221
    • Docstrings for styling properties by @darrenburns in https://github.com/Textualize/textual/pull/222
    • Underline bar renderable by @darrenburns in https://github.com/Textualize/textual/pull/246
    • Allow user to supply loop to App.run, ensure it closes by @darrenburns in https://github.com/Textualize/textual/pull/236
    • Tokenise CSS variables by @darrenburns in https://github.com/Textualize/textual/pull/250
    • Vertical layout by @darrenburns in https://github.com/Textualize/textual/pull/234
    • Horizontal layout by @darrenburns in https://github.com/Textualize/textual/pull/235
    • Variable support in CSS by @darrenburns in https://github.com/Textualize/textual/pull/258
    • Sparklines by @darrenburns in https://github.com/Textualize/textual/pull/269
    • Inline styles view by @willmcgugan in https://github.com/Textualize/textual/pull/254
    • Render opacity by @darrenburns in https://github.com/Textualize/textual/pull/272
    • Update pyproject.toml homepage link, add docs readme by @darrenburns in https://github.com/Textualize/textual/pull/268
    • Opacity rules by @darrenburns in https://github.com/Textualize/textual/pull/279
    • Tabs by @darrenburns in https://github.com/Textualize/textual/pull/293
    • Bump docs dev dependencies, add Tabs page, add note to docs README by @darrenburns in https://github.com/Textualize/textual/pull/301
    • Layout Resolver enhancement by @willmcgugan in https://github.com/Textualize/textual/pull/295
    • Implement CSS defaults by @willmcgugan in https://github.com/Textualize/textual/pull/294
    • Test animation by @willmcgugan in https://github.com/Textualize/textual/pull/303
    • Query dom - get child by @darrenburns in https://github.com/Textualize/textual/pull/306
    • Regions by @darrenburns in https://github.com/Textualize/textual/pull/319
    • Compositor refactor by @willmcgugan in https://github.com/Textualize/textual/pull/333
    • Add conversion to/from the CIE-L*ab color space. by @rodrigogiraoserrao in https://github.com/Textualize/textual/pull/360
    • Stringify the cast type, for <3.10 support by @tusharsadhwani in https://github.com/Textualize/textual/pull/351
    • WIP New color class by @willmcgugan in https://github.com/Textualize/textual/pull/349
    • Timer fix by @willmcgugan in https://github.com/Textualize/textual/pull/372
    • Custom scrollbars by @willmcgugan in https://github.com/Textualize/textual/pull/376
    • require semi-colons by @willmcgugan in https://github.com/Textualize/textual/pull/377
    • Logging server by @darrenburns in https://github.com/Textualize/textual/pull/366
    • Ensure filename is passed to devtools from init by @darrenburns in https://github.com/Textualize/textual/pull/383
    • tweak to log by @willmcgugan in https://github.com/Textualize/textual/pull/384
    • Redirect standard output to devtools server and logfile by @darrenburns in https://github.com/Textualize/textual/pull/385
    • Textual CLI by @darrenburns in https://github.com/Textualize/textual/pull/397
    • CSS align and box model by @willmcgugan in https://github.com/Textualize/textual/pull/398
    • optimize crop by @willmcgugan in https://github.com/Textualize/textual/pull/414
    • fix for showing scrollbars by @willmcgugan in https://github.com/Textualize/textual/pull/416
    • [css branch] Update _style_properties.py by @lllama in https://github.com/Textualize/textual/pull/415
    • fix for escape key processing by @willmcgugan in https://github.com/Textualize/textual/pull/420
    • [widget] Add a test for types of values we handle in style's size by @olivierphi in https://github.com/Textualize/textual/pull/428
    • [css][bugfix] CSS colors can now have digits at the end of their names by @olivierphi in https://github.com/Textualize/textual/pull/441
    • [layout][bugfix] Horizontal & Vertical layouts shouldn't display children that have display: none by @olivierphi in https://github.com/Textualize/textual/pull/436
    • button widget by @willmcgugan in https://github.com/Textualize/textual/pull/432
    • [colors] Add management of named Web colors to our CSS processing, prefix ANSI ones with ansi_ by @olivierphi in https://github.com/Textualize/textual/pull/443
    • Style error improvements by @darrenburns in https://github.com/Textualize/textual/pull/408
    • fix broken align and error logic by @willmcgugan in https://github.com/Textualize/textual/pull/446
    • Add TEXTUAL features env var by @willmcgugan in https://github.com/Textualize/textual/pull/448
    • [css] Add a "did you mean" suggestion when an unknown CSS property is spotted by @olivierphi in https://github.com/Textualize/textual/pull/445
    • Omit style property setter frames from tracebacks by @darrenburns in https://github.com/Textualize/textual/pull/457
    • Support 3 and 4 character hex strings for colours by @darrenburns in https://github.com/Textualize/textual/pull/459
    • [CI] Check that the "basic.py" sandbox script can be run for a few seconds without crashing by @olivierphi in https://github.com/Textualize/textual/pull/449
    • Skip CI-based MacOS devtools tests by @darrenburns in https://github.com/Textualize/textual/pull/461
    • Remove redundant import by @rjmill in https://github.com/Textualize/textual/pull/460
    • Add Python 3.10 to GitHub actions, upgrade mypy by @darrenburns in https://github.com/Textualize/textual/pull/462
    • Add links to CHANGELOG and fix date for v0.1.18 by @bbugyi200 in https://github.com/Textualize/textual/pull/454
    • Fix README.md typo disapointment->disappointment by @toonarmycaptain in https://github.com/Textualize/textual/pull/453
    • Fix broken overflow CSS rule by @darrenburns in https://github.com/Textualize/textual/pull/467
    • Update connection instructions in devtools header by @darrenburns in https://github.com/Textualize/textual/pull/469
    • Remove codecov from Textual by @darrenburns in https://github.com/Textualize/textual/pull/470
    • Windows CI by @darrenburns in https://github.com/Textualize/textual/pull/464
    • Tab focus by @willmcgugan in https://github.com/Textualize/textual/pull/458
    • [API] Start accepting PathLike objects here and there by @olivierphi in https://github.com/Textualize/textual/pull/463
    • line between logs by @willmcgugan in https://github.com/Textualize/textual/pull/478
    • added auto height by @willmcgugan in https://github.com/Textualize/textual/pull/476
    • CSS focus-within pseudo selector by @darrenburns in https://github.com/Textualize/textual/pull/477
    • diplay event method by @willmcgugan in https://github.com/Textualize/textual/pull/480
    • [tests] Add an integration test for the vertical layout, fix the bug that messes up the layout when the children have align: center top; by @olivierphi in https://github.com/Textualize/textual/pull/482
    • Added scroll_to_widget by @willmcgugan in https://github.com/Textualize/textual/pull/483
    • Scroll to top when widget is larger than container by @willmcgugan in https://github.com/Textualize/textual/pull/492
    • Add style param to Widget render method by @darrenburns in https://github.com/Textualize/textual/pull/479
    • [css] Add a "Did you mean" suggestion when the value of a color is wrong but we can find a close one by @olivierphi in https://github.com/Textualize/textual/pull/486
    • [tests][e2e] Add a test for Widget#scroll_to_widget() by @olivierphi in https://github.com/Textualize/textual/pull/494
    • Optimize Compositor by combining updates by @willmcgugan in https://github.com/Textualize/textual/pull/493
    • Msgpack devtools by @willmcgugan in https://github.com/Textualize/textual/pull/508
    • [App] Remove the focus timer: we now focus from a widget to the next/prev one instantly by @olivierphi in https://github.com/Textualize/textual/pull/505
    • added save_screenshot method and action by @willmcgugan in https://github.com/Textualize/textual/pull/511
    • Compositor deltas by @willmcgugan in https://github.com/Textualize/textual/pull/512
    • [css][scrollbar gutter] Manage the scrollbar-gutter: stable CSS property by @olivierphi in https://github.com/Textualize/textual/pull/501
    • Basic text input by @darrenburns in https://github.com/Textualize/textual/pull/495
    • [css] add "blank" border type by @olivierphi in https://github.com/Textualize/textual/pull/522
    • Auto dimensions by @willmcgugan in https://github.com/Textualize/textual/pull/527
    • Box fix by @willmcgugan in https://github.com/Textualize/textual/pull/532
    • Fix escape key by @willmcgugan in https://github.com/Textualize/textual/pull/534
    • compensated in box mode for scrollbars by @willmcgugan in https://github.com/Textualize/textual/pull/535
    • Mock time during integration tests by @olivierphi in https://github.com/Textualize/textual/pull/507
    • docs plugin by @willmcgugan in https://github.com/Textualize/textual/pull/536
    • Fix Option+Backspace hanging by @willmcgugan in https://github.com/Textualize/textual/pull/539
    • Text input improvements by @darrenburns in https://github.com/Textualize/textual/pull/528
    • [css] add scrollbar-size properties by @olivierphi in https://github.com/Textualize/textual/pull/529
    • [terminal buffering] Add support for the "mode 2026" - aka SynchronizedOutput by @olivierphi in https://github.com/Textualize/textual/pull/533
    • Refresh scrollbars on style changes. by @darrenburns in https://github.com/Textualize/textual/pull/545
    • Docs Refresh by @willmcgugan in https://github.com/Textualize/textual/pull/540
    • [AppTest] hotfix for the "css" branch after commit d45b0448880 by @olivierphi in https://github.com/Textualize/textual/pull/550
    • Swap ControlShiftUp & ControlShiftDown escape codes by @darrenburns in https://github.com/Textualize/textual/pull/549
    • Widget focus keybindings by @darrenburns in https://github.com/Textualize/textual/pull/546
    • Box model fractional by @willmcgugan in https://github.com/Textualize/textual/pull/552
    • simplify scrollbar dimensions by @willmcgugan in https://github.com/Textualize/textual/pull/553
    • Cache arrangements by @willmcgugan in https://github.com/Textualize/textual/pull/555
    • Fix scrollbar not updating with CSS animation by @willmcgugan in https://github.com/Textualize/textual/pull/558
    • Fix combined updates by @willmcgugan in https://github.com/Textualize/textual/pull/559
    • Inheritable CSS by @willmcgugan in https://github.com/Textualize/textual/pull/561
    • Scrolling nested containers by @darrenburns in https://github.com/Textualize/textual/pull/538
    • Support HSL colour space, allow spaces in RGB/HSL values by @darrenburns in https://github.com/Textualize/textual/pull/566
    • Support for bracketed paste mode by @darrenburns in https://github.com/Textualize/textual/pull/567
    • Make devtools deps extras, add note to internal ref docs, raise excep… by @darrenburns in https://github.com/Textualize/textual/pull/579
    • XTerm parsing improvements by @darrenburns in https://github.com/Textualize/textual/pull/570
    • Add success/warning/error button variants by @darrenburns in https://github.com/Textualize/textual/pull/575
    • [perf] Widget classes in textual.widget.__init__.py are now lazy-loaded by @olivierphi in https://github.com/Textualize/textual/pull/584
    • Tests around CSS specificity, and fix ordering in case of specificity clash by @darrenburns in https://github.com/Textualize/textual/pull/582
    • Adding space key to ansi sequences allows binding by @pvmm in https://github.com/Textualize/textual/pull/410
    • add space to keys by @willmcgugan in https://github.com/Textualize/textual/pull/585
    • Scroll view and DataTable Widget by @willmcgugan in https://github.com/Textualize/textual/pull/560
    • [tests] Restore layout integration tests by @olivierphi in https://github.com/Textualize/textual/pull/587
    • [button] Add a brief "active" effect when a button a clicked by @olivierphi in https://github.com/Textualize/textual/pull/588
    • Add a cursor to table by @willmcgugan in https://github.com/Textualize/textual/pull/591
    • User CSS should always take precedence over Widget CSS by @darrenburns in https://github.com/Textualize/textual/pull/595
    • Render cache by @willmcgugan in https://github.com/Textualize/textual/pull/602
    • Render enhancements by @willmcgugan in https://github.com/Textualize/textual/pull/606
    • Improvements to scroll_to_widget by @willmcgugan in https://github.com/Textualize/textual/pull/608
    • Small typo fix by @jacobtomlinson in https://github.com/Textualize/textual/pull/612
    • Color harmony by @willmcgugan in https://github.com/Textualize/textual/pull/619
    • Adds Layers and Docks by @willmcgugan in https://github.com/Textualize/textual/pull/627
    • Document CSS Styles by @willmcgugan in https://github.com/Textualize/textual/pull/629
    • Register callbacks at message pump level, invoke them after refresh by @darrenburns in https://github.com/Textualize/textual/pull/607
    • Focus order by @darrenburns in https://github.com/Textualize/textual/pull/638
    • restore missing callback by @willmcgugan in https://github.com/Textualize/textual/pull/649
    • Add remove by @willmcgugan in https://github.com/Textualize/textual/pull/653
    • center layout by @willmcgugan in https://github.com/Textualize/textual/pull/656
    • fix for layout bug by @willmcgugan in https://github.com/Textualize/textual/pull/662
    • unified events and messages by @willmcgugan in https://github.com/Textualize/textual/pull/660
    • CSS tie breaker by @willmcgugan in https://github.com/Textualize/textual/pull/665
    • partial tree control fix by @willmcgugan in https://github.com/Textualize/textual/pull/667
    • fix for footer by @willmcgugan in https://github.com/Textualize/textual/pull/670
    • Filling the gap between horizontal and vertical scrollbars by @darrenburns in https://github.com/Textualize/textual/pull/664
    • Screens API by @willmcgugan in https://github.com/Textualize/textual/pull/685
    • Improve error message for CSS syntax error by @darrenburns in https://github.com/Textualize/textual/pull/680
    • tests for auto refresh by @willmcgugan in https://github.com/Textualize/textual/pull/696
    • Docs scrollbar gutter by @darrenburns in https://github.com/Textualize/textual/pull/695
    • Animation callback by @darrenburns in https://github.com/Textualize/textual/pull/683
    • Docs content align by @darrenburns in https://github.com/Textualize/textual/pull/700
    • Docs intro by @willmcgugan in https://github.com/Textualize/textual/pull/703
    • Optimize applying CSS styles by @willmcgugan in https://github.com/Textualize/textual/pull/705
    • Docs layout by @darrenburns in https://github.com/Textualize/textual/pull/701
    • text-align CSS support by @darrenburns in https://github.com/Textualize/textual/pull/704
    • Values sections for CSS properties, some rewordings by @darrenburns in https://github.com/Textualize/textual/pull/713
    • table layout by @willmcgugan in https://github.com/Textualize/textual/pull/712
    • calculator example by @willmcgugan in https://github.com/Textualize/textual/pull/714
    • Delay transition by @darrenburns in https://github.com/Textualize/textual/pull/684
    • hotfix for justify by @willmcgugan in https://github.com/Textualize/textual/pull/717
    • Changes to opacity by @darrenburns in https://github.com/Textualize/textual/pull/720
    • CSS Path Relative by @darrenburns in https://github.com/Textualize/textual/pull/724
    • Log verbosity by @willmcgugan in https://github.com/Textualize/textual/pull/722
    • scrollbar fix by @willmcgugan in https://github.com/Textualize/textual/pull/726
    • Default css by @willmcgugan in https://github.com/Textualize/textual/pull/727
    • exclude invisible widgets by @willmcgugan in https://github.com/Textualize/textual/pull/728
    • private by @willmcgugan in https://github.com/Textualize/textual/pull/729
    • validate identifiers by @willmcgugan in https://github.com/Textualize/textual/pull/730
    • added char attribute to Text event by @willmcgugan in https://github.com/Textualize/textual/pull/732
    • App docs by @willmcgugan in https://github.com/Textualize/textual/pull/733
    • Fix auto height layout by @willmcgugan in https://github.com/Textualize/textual/pull/739
    • Make dark mode default by @darrenburns in https://github.com/Textualize/textual/pull/743
    • tree fix by @willmcgugan in https://github.com/Textualize/textual/pull/744
    • Easing preview by @darrenburns in https://github.com/Textualize/textual/pull/740
    • Code browser example by @willmcgugan in https://github.com/Textualize/textual/pull/746
    • Scroll issue by @willmcgugan in https://github.com/Textualize/textual/pull/747
    • focus level bindings by @willmcgugan in https://github.com/Textualize/textual/pull/751
    • App log by @willmcgugan in https://github.com/Textualize/textual/pull/753
    • Layout order by @willmcgugan in https://github.com/Textualize/textual/pull/755
    • Readme by @willmcgugan in https://github.com/Textualize/textual/pull/758
    • auto color by @willmcgugan in https://github.com/Textualize/textual/pull/763
    • Update various broken variables by @darrenburns in https://github.com/Textualize/textual/pull/764
    • Layer order by @willmcgugan in https://github.com/Textualize/textual/pull/765
    • fixes for variable css errors by @willmcgugan in https://github.com/Textualize/textual/pull/768
    • Add verbose tag to events docs by @darrenburns in https://github.com/Textualize/textual/pull/773
    • docs/widgets/Button by @darrenburns in https://github.com/Textualize/textual/pull/769
    • Grid cell margin by @darrenburns in https://github.com/Textualize/textual/pull/772
    • Docs styles by @willmcgugan in https://github.com/Textualize/textual/pull/775
    • Add docs for CSS variables by @darrenburns in https://github.com/Textualize/textual/pull/780
    • Fix broken text in docs by @darrenburns in https://github.com/Textualize/textual/pull/781
    • Initial layout guide stuff by @darrenburns in https://github.com/Textualize/textual/pull/748
    • Log drop critical by @willmcgugan in https://github.com/Textualize/textual/pull/782
    • Document styles by @darrenburns in https://github.com/Textualize/textual/pull/785
    • Minimise rendering when text-opacity/opacity is zero by @darrenburns in https://github.com/Textualize/textual/pull/774
    • Docs events by @willmcgugan in https://github.com/Textualize/textual/pull/787
    • changed to CSS_PATH by @willmcgugan in https://github.com/Textualize/textual/pull/789
    • Expand shrink by @willmcgugan in https://github.com/Textualize/textual/pull/794
    • Remove docks references & other tidying by @darrenburns in https://github.com/Textualize/textual/pull/795
    • Snapshot testing by @darrenburns in https://github.com/Textualize/textual/pull/793
    • Docs for widgets by @willmcgugan in https://github.com/Textualize/textual/pull/800
    • Docs input by @willmcgugan in https://github.com/Textualize/textual/pull/801
    • new align by @willmcgugan in https://github.com/Textualize/textual/pull/802
    • Docs actions by @willmcgugan in https://github.com/Textualize/textual/pull/804
    • Get widget by @willmcgugan in https://github.com/Textualize/textual/pull/808
    • New input by @willmcgugan in https://github.com/Textualize/textual/pull/811
    • optimizations for compositor by @willmcgugan in https://github.com/Textualize/textual/pull/812
    • Docs for reactivity by @willmcgugan in https://github.com/Textualize/textual/pull/815
    • Fix comma separated string in "Bindings" by @darrenburns in https://github.com/Textualize/textual/pull/797
    • Document widgets by @darrenburns in https://github.com/Textualize/textual/pull/819
    • Docs screen by @willmcgugan in https://github.com/Textualize/textual/pull/824
    • Bump 0.2.0 BETA by @willmcgugan in https://github.com/Textualize/textual/pull/822
    • change typing-extensions dependancy by @willmcgugan in https://github.com/Textualize/textual/pull/825
    • Too many "haves" by @driscollis in https://github.com/Textualize/textual/pull/827
    • Highlight import of Container class by @driscollis in https://github.com/Textualize/textual/pull/830
    • Fix some minor typos about the Stopwatch widget by @driscollis in https://github.com/Textualize/textual/pull/831
    • Py typed by @willmcgugan in https://github.com/Textualize/textual/pull/836
    • Note timers ID added to Container object by @kimvanwyk in https://github.com/Textualize/textual/pull/832
    • Highlight changed set_interval line in stopwatch06 example by @kimvanwyk in https://github.com/Textualize/textual/pull/833
    • Table polish by @willmcgugan in https://github.com/Textualize/textual/pull/837
    • Initialize reactive variables earlier by @willmcgugan in https://github.com/Textualize/textual/pull/838
    • fix error on exit from textual console by @willmcgugan in https://github.com/Textualize/textual/pull/841
    • Docs for Animator by @darrenburns in https://github.com/Textualize/textual/pull/840
    • Flag to enable header clock by @darrenburns in https://github.com/Textualize/textual/pull/843
    • Fix minor readability issue in modifying CSS class by @driscollis in https://github.com/Textualize/textual/pull/844
    • Regions optimize by @willmcgugan in https://github.com/Textualize/textual/pull/855
    • monochrome tests by @willmcgugan in https://github.com/Textualize/textual/pull/856
    • Fix issues with Styles.css, update "Grid" styles doc page by @darrenburns in https://github.com/Textualize/textual/pull/854
    • Docs queries by @willmcgugan in https://github.com/Textualize/textual/pull/857
    • DOM Queries typo squish by @davep in https://github.com/Textualize/textual/pull/858
    • Documenting comma-separated bindings in docstring and guide by @darrenburns in https://github.com/Textualize/textual/pull/853
    • Cli colors by @willmcgugan in https://github.com/Textualize/textual/pull/863
    • Typo fix: styles belong to a widget by @davep in https://github.com/Textualize/textual/pull/859
    • Support for key aliases, key handling tests by @darrenburns in https://github.com/Textualize/textual/pull/852
    • add max_idle for screen by @willmcgugan in https://github.com/Textualize/textual/pull/869
    • Update docs: fix copy/paste error for Timers by @lllama in https://github.com/Textualize/textual/pull/879
    • Provide extra hinting for App.query by @davep in https://github.com/Textualize/textual/pull/883
    • Document links by @darrenburns in https://github.com/Textualize/textual/pull/868
    • Win slow by @willmcgugan in https://github.com/Textualize/textual/pull/881
    • Harmonise the types of the App's css path declarations by @davep in https://github.com/Textualize/textual/pull/876
    • update borders with css by @willmcgugan in https://github.com/Textualize/textual/pull/889
    • docs: typos by @aaronst in https://github.com/Textualize/textual/pull/887
    • Fix :focus-within pseudo-selector by @darrenburns in https://github.com/Textualize/textual/pull/885
    • Move focus logic to screen, add more key replacements, collapse bindings in footer by @darrenburns in https://github.com/Textualize/textual/pull/880
    • Use screen offset instead of offset by @darrenburns in https://github.com/Textualize/textual/pull/893
    • Modify the screen examples to import Screen from textual.screen by @davep in https://github.com/Textualize/textual/pull/888
    • Fix _reset_focus being called on app instead of Screen by @darrenburns in https://github.com/Textualize/textual/pull/895
    • Fix textual run path bug on Windows by @darrenburns in https://github.com/Textualize/textual/pull/899
    • Remove unused code by @darrenburns in https://github.com/Textualize/textual/pull/896
    • depth first search by @willmcgugan in https://github.com/Textualize/textual/pull/902
    • Add password as a Input keyword argument by @davep in https://github.com/Textualize/textual/pull/911
    • CSS docs review - Layout by @davep in https://github.com/Textualize/textual/pull/913
    • CSS docs review - Events and Messages by @davep in https://github.com/Textualize/textual/pull/914
    • Reviewing CSS docs by @davep in https://github.com/Textualize/textual/pull/898
    • CSS docs review - CSS by @davep in https://github.com/Textualize/textual/pull/906
    • Get rid of string split key display, bug fix for not showing screen-level bindings by @darrenburns in https://github.com/Textualize/textual/pull/910
    • CSS docs review - Actions by @davep in https://github.com/Textualize/textual/pull/916
    • CSS docs review - Input by @davep in https://github.com/Textualize/textual/pull/915
    • CSS docs review - Styles by @davep in https://github.com/Textualize/textual/pull/904
    • CSS docs review - Reactivity by @davep in https://github.com/Textualize/textual/pull/918
    • README has 'development development' by @adam-huganir in https://github.com/Textualize/textual/pull/920
    • CSS docs review - Widgets by @davep in https://github.com/Textualize/textual/pull/921
    • CSS docs review - Animation by @davep in https://github.com/Textualize/textual/pull/922
    • CSS docs review - Screens by @davep in https://github.com/Textualize/textual/pull/923
    • CSS docs review - Styles reference by @davep in https://github.com/Textualize/textual/pull/925
    • CSS docs review - Events by @davep in https://github.com/Textualize/textual/pull/924
    • CSS docs review - Widgets reference by @davep in https://github.com/Textualize/textual/pull/926
    • Roadmap by @willmcgugan in https://github.com/Textualize/textual/pull/927
    • wait for mount by @willmcgugan in https://github.com/Textualize/textual/pull/912
    • fix cursor delete issue by @willmcgugan in https://github.com/Textualize/textual/pull/931
    • fix error with text-log in docs by @willmcgugan in https://github.com/Textualize/textual/pull/932
    • Some bug fixes in Input + add title to App constructor by @darrenburns in https://github.com/Textualize/textual/pull/934
    • Mention ordering of superpower methods in docs by @darrenburns in https://github.com/Textualize/textual/pull/935
    • fix focus glitch by @willmcgugan in https://github.com/Textualize/textual/pull/936
    • fix alignment bug by @willmcgugan in https://github.com/Textualize/textual/pull/937
    • Add directory of file to run to sys path by @darrenburns in https://github.com/Textualize/textual/pull/947
    • key bindings refactor by @willmcgugan in https://github.com/Textualize/textual/pull/941
    • Add support for action handlers prefixed with _ by @darrenburns in https://github.com/Textualize/textual/pull/946
    • Checkbox polishing + fix auto-width in Horizontal layout by @darrenburns in https://github.com/Textualize/textual/pull/942
    • Ensure scroll events are forwarded to the screen by @darrenburns in https://github.com/Textualize/textual/pull/948
    • Minor doc fixes by @MatrixManAtYrService in https://github.com/Textualize/textual/pull/938
    • docs: remove center layout by @aaronst in https://github.com/Textualize/textual/pull/949
    • Fix variables in Screens, remove dark reactive from Screen by @darrenburns in https://github.com/Textualize/textual/pull/957
    • Modify DOMNode.walk_children to return a list by @davep in https://github.com/Textualize/textual/pull/952
    • Try and better settle focus after a focused widget is removed (redux) by @davep in https://github.com/Textualize/textual/pull/954
    • Populate character on simulated key presses by @darrenburns in https://github.com/Textualize/textual/pull/960
    • Review the use of the bell in various examples and documentation files by @davep in https://github.com/Textualize/textual/pull/958
    • Post-PR #954 tidy up by @davep in https://github.com/Textualize/textual/pull/961
    • Fix bindings as tuples by @darrenburns in https://github.com/Textualize/textual/pull/962
    • Color animate alpha by @darrenburns in https://github.com/Textualize/textual/pull/964
    • Fix color preview by @darrenburns in https://github.com/Textualize/textual/pull/967
    • Update the calculator example to make all keyboard keys work again by @davep in https://github.com/Textualize/textual/pull/968
    • Initial pull of 5x5 into the Textual examples directory by @davep in https://github.com/Textualize/textual/pull/963
    • Switch the dark mode toggle to Ctrl+D by @davep in https://github.com/Textualize/textual/pull/970
    • adds demo by @willmcgugan in https://github.com/Textualize/textual/pull/959
    • docs: remove extra the by @aaronst in https://github.com/Textualize/textual/pull/976
    • added version number to demo, bumped beta by @willmcgugan in https://github.com/Textualize/textual/pull/977
    • Bump020 by @willmcgugan in https://github.com/Textualize/textual/pull/978
    • CSS by @willmcgugan in https://github.com/Textualize/textual/pull/979
    • lock update by @willmcgugan in https://github.com/Textualize/textual/pull/981
    • Abs readme links by @willmcgugan in https://github.com/Textualize/textual/pull/982

    New Contributors

    • @darrenburns made their first contribution in https://github.com/Textualize/textual/pull/213
    • @olivierphi made their first contribution in https://github.com/Textualize/textual/pull/428
    • @rjmill made their first contribution in https://github.com/Textualize/textual/pull/460
    • @bbugyi200 made their first contribution in https://github.com/Textualize/textual/pull/454
    • @toonarmycaptain made their first contribution in https://github.com/Textualize/textual/pull/453
    • @pvmm made their first contribution in https://github.com/Textualize/textual/pull/410
    • @jacobtomlinson made their first contribution in https://github.com/Textualize/textual/pull/612
    • @driscollis made their first contribution in https://github.com/Textualize/textual/pull/827
    • @kimvanwyk made their first contribution in https://github.com/Textualize/textual/pull/832
    • @davep made their first contribution in https://github.com/Textualize/textual/pull/858
    • @aaronst made their first contribution in https://github.com/Textualize/textual/pull/887
    • @adam-huganir made their first contribution in https://github.com/Textualize/textual/pull/920
    • @MatrixManAtYrService made their first contribution in https://github.com/Textualize/textual/pull/938

    Full Changelog: https://github.com/Textualize/textual/compare/v0.1.18...v0.2.0

    Source code(tar.gz)
    Source code(zip)
  • v0.1.18(Apr 30, 2022)

  • v0.1.17(Mar 10, 2022)

  • v0.1.16(Mar 10, 2022)

  • v0.1.15(Jan 31, 2022)

    Windows support has landed. Still experimental -- let us know if you run in to any problems!

    [0.1.15] - 2022-01-31


    • Added Windows Driver
    Source code(tar.gz)
    Source code(zip)
  • v0.1.14(Jan 9, 2022)

  • v0.1.13(Jan 1, 2022)

    [0.1.13] - 2022-01-01


    • Fixed spurious characters when exiting app https://github.com/willmcgugan/textual/issues/82
    • Fixed increasing delay when exiting
    Source code(tar.gz)
    Source code(zip)
  • v0.1.11(Sep 12, 2021)

    [0.1.11] - 2021-09-12


    • Changed message handlers to use prefix handle_
    • Renamed messages to drop the Message suffix
    • Events now bubble by default
    • Refactor of layout


    • Added App.measure
    • Added auto_width to Vertical Layout, WindowView, an ScrollView
    • Added big_table.py example
    • Added easing.py example
    Source code(tar.gz)
    Source code(zip)
  • v0.1.10(Aug 25, 2021)

    [0.1.10] - 2021-08-25


    • Added keyboard control of tree control
    • Added Widget.gutter to calculate space between renderable and outside edge
    • Added margin, padding, and border attributes to Widget


    • Callbacks may be async or non-async.
    • Event handler event argument is optional.
    • Fixed exception in clock example https://github.com/willmcgugan/textual/issues/52
    • Added Message.wait() which waits for a message to be processed
    • Key events are now sent to widgets first, before processing bindings
    Source code(tar.gz)
    Source code(zip)
  • v0.1.3(Jul 5, 2021)

    In this version there is a new more-powerful renderer that supports overlapping regions. There is also a new layout engine which is more intuitive that Rich's Layout clas.

    Source code(tar.gz)
    Source code(zip)
  • v0.1.2(Jun 24, 2021)

Will McGugan
I'm a full-stack software developer, and Python expert. Creator of Rich and @PyFilesystem.
Will McGugan
Python Command-line Application Tools

Clint: Python Command-line Interface Tools Clint is a module filled with a set of awesome tools for developing commandline applications. C ommand L in

Kenneth Reitz Archive 82 Dec 28, 2022
Command line animations based on the state of the system

shell-emotions Command line animations based on the state of the system for Linux or Windows 10 The ascii animations were created using a modified ver

Simon Malave 63 Nov 12, 2022
Typer, build great CLIs. Easy to code. Based on Python type hints.

Typer, build great CLIs. Easy to code. Based on Python type hints. Documentation: https://typer.tiangolo.com Source Code: https://github.com/tiangolo/

Sebastián Ramírez 10.1k Jan 02, 2023
sane is a command runner made simple.

sane is a command runner made simple.

Miguel M. 22 Jan 03, 2023
A simple terminal Christmas tree made with Python

Python Christmas Tree A simple CLI Christmas tree made with Python Installation Just clone the repository and run $ python terminal_tree.py More opti

Francisco B. 64 Dec 27, 2022
plotting in the terminal

bashplotlib plotting in the terminal what is it? bashplotlib is a python package and command line tool for making basic plots in the terminal. It's a

Greg Lamp 1.7k Jan 02, 2023
A thin, practical wrapper around terminal capabilities in Python

Blessings Coding with Blessings looks like this... from blessings import Terminal t = Terminal() print(t.bold('Hi there!')) print(t.bold_red_on_brig

Erik Rose 1.4k Jan 07, 2023
emoji terminal output for Python

Emoji Emoji for Python. This project was inspired by kyokomi. Example The entire set of Emoji codes as defined by the unicode consortium is supported

Taehoon Kim 1.6k Jan 02, 2023
A fast, stateless http slash commands framework for scale. Built by the Crunchy bot team.

Roid 🤖 A fast, stateless http slash commands framework for scale. Built by the Crunchy bot team. 🚀 Installation You can install roid in it's default

Harrison Burt 7 Aug 09, 2022
Simple cross-platform colored terminal text in Python

Colorama Makes ANSI escape character sequences (for producing colored terminal text and cursor positioning) work under MS Windows. PyPI for releases |

Jonathan Hartley 3k Jan 01, 2023
Pythonic command line arguments parser, that will make you smile

docopt creates beautiful command-line interfaces Video introduction to docopt: PyCon UK 2012: Create *beautiful* command-line interfaces with Python N

7.7k Dec 30, 2022
A module for parsing and processing commands.

cmdtools A module for parsing and processing commands. Installation pip install --upgrade cmdtools-py install latest commit from GitHub pip install g

1 Aug 14, 2022
Cement is an advanced Application Framework for Python, with a primary focus on CLI

Cement Framework Cement is an advanced Application Framework for Python, with a primary focus on Command Line Interfaces (CLI). Its goal is to introdu

Data Folk Labs, LLC 1.1k Dec 31, 2022
Terminalcmd - a Python library which can help you to make your own terminal program with high-intellegence instruments

Terminalcmd - a Python library which can help you to make your own terminal program with high-intellegence instruments, that will make your code clear and readable.

Dallas 0 Jun 19, 2022
Python Fire is a library for automatically generating command line interfaces (CLIs) from absolutely any Python object.

Python Fire Python Fire is a library for automatically generating command line interfaces (CLIs) from absolutely any Python object. Python Fire is a s

Google 23.6k Dec 31, 2022
Python composable command line interface toolkit

$ click_ Click is a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary. It's the "Comm

The Pallets Projects 13.3k Dec 31, 2022
prompt_toolkit is a library for building powerful interactive command line applications in Python.

Python Prompt Toolkit prompt_toolkit is a library for building powerful interactive command line applications in Python. Read the documentation on rea

prompt-toolkit 8.1k Jan 04, 2023
Cleo allows you to create beautiful and testable command-line interfaces.

Cleo Create beautiful and testable command-line interfaces. Cleo is mostly a higher level wrapper for CliKit, so a lot of the components and utilities

Sébastien Eustace 984 Jan 02, 2023
Corgy allows you to create a command line interface in Python, without worrying about boilerplate code

corgy Elegant command line parsing for Python. Corgy allows you to create a command line interface in Python, without worrying about boilerplate code.

Jayanth Koushik 7 Nov 17, 2022
Color text streams with a polished command line interface

colout(1) -- Color Up Arbitrary Command Output Synopsis colout [-h] [-r RESOURCE] colout [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORM

nojhan 1.1k Dec 21, 2022