textual-plotext

repository·main·Indexed 42 days ago

https://github.com/textualize/textual-plotext

A Textual widget wrapper for the Plotext plotting library, enabling the rendering of high-quality terminal plots within Textual TUI applications. It provides the PlotextPlot and Plot widgets to manage plot state without relying on global state, along with support for standard Plotext themes and specialized full-color Textual themes.

Tokens
2.6K
Snippets
14
Records
18
Agent score
53%

What's inside textual-plotext

  1. How PlotextPlot themes and auto-theming work

    main

    The PlotextPlot widget supports standard Plotext themes. However, because ANSI colors can look inconsistent across different terminals, textual-plotext provides theme copies prefixed with textual- (e.g., textual-theme-name) that use full RGB coloring for consistent rendering.

    By default, the widget uses two special themes:

    • textual-design-dark
    • textual-design-light

    It automatically switches between these when your Textual application toggles between dark and light mode. To disable this automatic switching, set the auto_theme property of your plot to False.

    # Example of disabling auto-theme
    plt = self.query_one(PlotextPlot).plt
    plt.auto_theme = False
  2. Use the PlotextPlot widget in a Textual app

    main

    The library provides a single widget: PlotextPlot. To use it, yield it in your compose method. To manipulate the plot, access the .plt property of the widget instance. This property provides the standard Plotext API. Note that you do not call plt.show(); the widget handles rendering automatically.

    from textual.app import App, ComposeResult
    from textual_plotext import PlotextPlot
    
    class ScatterApp(App[None]):
    
        def compose(self) -> ComposeResult:
            yield PlotextPlot()
    
        def on_mount(self) -> None: 
            # Access the plot via the .plt property
            plt = self.query_one(PlotextPlot).plt
            y = plt.sin() 
            plt.scatter(y)
            plt.title("Scatter Plot")
            # Do NOT call plt.show()
    
    if __name__ == "__main__":
        ScatterApp().run()
  3. Use the PlotextPlot widget in Textual

    main

    The PlotextPlot widget is the primary way to integrate plotext charts into a Textual application. It acts as a container for rendering plots within the Textual TUI framework.

    For a complete implementation pattern, refer to the textual_towers_weather.py example, which demonstrates how to use the widget alongside Textual's worker API to fetch data in a background thread without blocking the UI.

    # Refer to textual_towers_weather.py for the full implementation pattern
    # The core component is the PlotextPlot widget
    from textual_plotext import PlotextPlot
    
    # In your Textual App or Widget:
    # self.query_one(PlotextPlot).plot(...)
  4. What is the Plot class and how does it differ from plotext?

    main
    The Plot class is a wrapper around Plotext's figure class. While the standard plotext module relies on global state (making it difficult to manage multiple independent plots), the Plot class allows you to instantiate independent plotting objects. This is essential for Textual applications where you might want to embed multiple different plots in different parts of the UI without them interfering with each other.
  5. Workaround for log scale ValueError

    main

    There is a known issue where repeated calls to build (which happens during widget resizing) for a plot with x or y scales set to "log" results in a ValueError: math domain error.

    To resolve this in a Textual application, after your initial plot setup, call .build() and then reset the problematic scale back to "linear".

    # Workaround for log scale issues
    _ = self.plt.build()
    self.plt.xscale("linear")
  6. Reference: Supported and No-op Plotext functions

    main

    The following functions are available via PlotextPlot.plt:

    • plt.sin
    • plt.square
    • plt.colorize
    • plt.uncolorize

    Some functions are implemented as no-ops (they can be called without error but do nothing) to prevent side effects that don't make sense in a Textual environment:

    • plt.clear_terminal
    • plt.show
    • plt.save_fig
  7. Use the Plot class for stateful plotting

    main

    The Plot class provides a Textual-friendly interface to plotext. It acts as a thin wrapper around a plotext figure, allowing you to manage plot state without relying on global state or external side-effects. This makes it ideal for use within Textual applications where multiple plot instances might exist.

    Plot inherits from Plotext's figure class, meaning it supports all standard Plotext plotting methods (like .scatter(), .plot(), etc.) while providing additional utility methods.

    from textual_plotext import Plot
    
    plt = Plot()
    plt.title("Scatter Plot")
    plt.scatter([1, 2, 3, 4])
  8. Use the PlotextPlot widget

    main

    The PlotextPlot widget is the primary interface for displaying plots within a Textual application. Instead of importing the global plotext module, you should interact with the widget's plt property to perform plotting operations. This ensures that the plots are correctly scoped to the widget and rendered within the Textual UI.

    from textual_plotext import PlotextPlot
    
    # Inside a Textual App or Widget
    plot_widget = PlotextPlot()
    self.mount(plot_widget)
    
    # Use the .plt property to call plotext functions
    plot_widget.plt.scatter([1, 2, 3], [4, 5, 6])
    plot_widget.plt.title("My Plot")