Theme

Controlling visual aspects of Yuio with themes.

Theme base class

The overall look and feel of a Yuio application is declared in a Theme object:

class yuio.theme.Theme

Base class for Yuio themes.

Warning

Do not change theme contents after it was passed to yuio.io.setup(). Otherwise there’s a risc of race conditions.

progress_bar_width: int = 15

Width of a progress bar for yuio.io.Task.

spinner_update_rate_ms: int = 200

How often the spinner pattern changes.

separate_headings: bool = True

Whether to print newlines before and after yuio.io.heading().

fallback_width: int = 80

Preferred width that will be used if printing to a stream that’s redirected to a file.

msg_decorations_unicode: Mapping[str, str] = {}

Decorative symbols for certain text elements, such as headings, list items, etc.

This mapping becomes immutable once a theme class is created. The only possible way to modify it is by using set_msg_decoration_ascii() or _set_msg_decoration_ascii_if_not_overridden().

set_msg_decoration_unicode(name: str, msg_decoration: str, /)

Set Unicode message decoration by name.

_set_msg_decoration_unicode_if_not_overridden(
name: str,
msg_decoration: str,
/,
)

Set Unicode message decoration by name, but only if it wasn’t overridden in a subclass.

This method should be called from __init__ implementations to dynamically set message decorations. It will only set the decoration if it was not overridden by any child class.

msg_decorations_ascii: Mapping[str, str] = {}

Like msg_decorations_unicode, but suitable for non-unicode terminals.

set_msg_decoration_ascii(name: str, msg_decoration: str, /)

Set ASCII message decoration by name.

_set_msg_decoration_ascii_if_not_overridden(
name: str,
msg_decoration: str,
/,
)

Set ASCII message decoration by name, but only if it wasn’t overridden in a subclass.

This method should be called from __init__ implementations to dynamically set message decorations. It will only set the decoration if it was not overridden by any child class.

colors: Mapping[str, str | Color] = {}

Mapping of color paths to actual colors.

Themes use color paths to describe styles and colors for different parts of an application. Color paths are similar to file paths, they use snake case identifiers separated by slashes, and consist of two parts separated by a colon.

The first part represents an object, i.e. what we’re coloring.

The second part represents a context, i.e. what is the state or location of an object that we’re coloring.

For example, a color for the filled part of the task’s progress bar has path "task/progressbar/done", a color for a text of an error log record has path "log/message:error", and a color for a string escape sequence in a highlighted python code has path "hl/str/esc:python".

A color at a certain path is propagated to all sub-paths. For example, if "task/progressbar" is bold, and "task/progressbar/done" is green, the final color will be bold green.

Each color path can be associated with an instance of Color or with another path.

If path is mapped to a Color, then the path is associated with that particular color.

If path is mapped to another path, then the path is associated with the color value for that other path (please don’t create recursions here).

You can combine multiple paths within the same mapping by separating them with whitespaces. In this case colors for those paths are combined.

For example:

colors = {
    "heading_color": "bold",
    "error_color": "red",
    "tb/heading": "heading_color error_color",
}

Here, color of traceback’s heading "tb/heading" will be bold and red.

When deriving from a theme, you can override this mapping. When looking up colors via get_color(), base classes will be tried for color, in order of method resolution.

This mapping becomes immutable once a theme class is created. The only possible way to modify it is by using set_color() or _set_color_if_not_overridden().

set_color(path: str, color: str | Color, /)

Set color by path.

_set_color_if_not_overridden(path: str, color: str | Color, /)

Set color by path, but only if the color was not overridden in a subclass.

This method should be called from __init__ implementations to dynamically set colors. It will only set the color if it was not overridden by any child class.

get_color(paths: str, /) Color

Lookup a color by path.

to_color(
color_or_path: Color | str | None,
/,
) Color

Convert color or color path to color.

check()

Check theme for recursion.

This method is slow, and should be called from unit tests of your application.

Default theme

Use the following loader to create an instance of the default theme:

yuio.theme.load(
term: Term,
theme_ctor: Callable[[Term], Theme] | None = None,
/,
) Theme

Loads a default theme.

class yuio.theme.BaseTheme

This theme defines common colors that are commonly used in inline color tags.

class yuio.theme.DefaultTheme(term: Term)

Default Yuio theme. Adapts for terminal background color, if one can be detected.

This theme defines main colors, which you can override by subclassing. All other colors are expressed in terms of main colors, so changing a main color will have an effect on the entire theme.

Color paths

common tags

BaseTheme sets up commonly used colors that you can use in formatted messages:

  • code: inline code,

  • note: inline highlighting,

  • path: file paths,

  • flag: CLI flags,

  • bold, b: font style,

  • dim, d: font style,

  • italic, i: font style,

  • underline, u: font style,

  • inverse: swap foreground and background colors,

  • normal: normal foreground,

  • muted: muted foreground (see FORE_NORMAL_DIM),

  • red: foreground,

  • green: foreground,

  • yellow: foreground,

  • blue: foreground,

  • magenta: foreground,

  • cyan: foreground,

Note

We don’t define black and white because they can be invisible with some terminal themes. Prefer muted when you need a muted color.

We also don’t define tags for backgrounds because there’s no way to tell which foreground/background combination will be readable and which will not. Prefer inverse when you need to add a background.

main colors

DefaultTheme defines main colors, which you can override by subclassing.

  • heading_color: for headings,

  • primary_color: for main text,

  • accent_color, accent_color_2: for visually highlighted elements,

  • secondary_color: for visually dimmed elements,

  • error_color: for everything that indicates an error,

  • warning_color: for everything that indicates a warning,

  • success_color: for everything that indicates a success,

  • critical_color: for critical or internal errors,

  • low_priority_color_a: for auxiliary elements such as help widget,

  • low_priority_color_b: for auxiliary elements such as help widget, even lower priority.

term/color

DefaultTheme will export default colors for the attached terminal as term/color. This is useful when defining gradients for progress bars, as they require exact color values for interpolation.

color can be one background, foreground, black, bright_black, red, bright_red, green, bright_green, yellow, bright_yellow, blue, bright_blue, magenta, bright_magenta, cyan, bright_cyan, white, or bright_white.

msg/decoration:tag

Color for decorations in front of messages:

  • msg/decoration:info: messages from yuio.io.info,

  • msg/decoration:warning: messages from yuio.io.warning,

  • msg/decoration:error: messages from yuio.io.error,

  • msg/decoration:success: messages from yuio.io.success,

  • msg/decoration:failure: messages from yuio.io.failure,

  • msg/decoration:heading/level: messages from yuio.io.heading and headings in markdown,

  • msg/decoration:heading/section: first-level headings in CLI help,

  • msg/decoration:question: messages from yuio.io.ask(),

  • msg/decoration:list: bullets in markdown,

  • msg/decoration:quote: quote decorations in markdown,

  • msg/decoration:code: code decorations in markdown,

  • msg/decoration:thematic_break: thematic breaks (i.e. horizontal rulers) in markdown,

  • msg/decoration:hr/weight: horizontal rulers (see yuio.io.hr() and yuio.string.Hr()).

msg/text:tag

Color for the text part of messages:

  • msg/text:info and all other tags from msg/decoration,

  • msg/text:paragraph: plain text in markdown,

  • msg/text:code/syntax: plain text in highlighted code blocks.

task/...:status

Running and finished tasks:

  • task/decoration: decoration before the task,

  • task/progressbar/done: filled portion of the progress bar,

  • task/progressbar/done/start: gradient start for the filled portion of the progress bar,

  • task/progressbar/done/end: gradient end for the filled portion of the progress bar,

  • task/progressbar/pending: unfilled portion of the progress bar,

  • task/progressbar/pending/start: gradient start for the unfilled portion of the progress bar,

  • task/progressbar/pending/end: gradient end for the unfilled portion of the progress bar,

  • task/heading: task title,

  • task/progress: number that indicates task progress,

  • task/comment: task comment.

status can be running, done, or error.

hl/token:syntax

Color for highlighted part of code:

  • hl/comment: code comments,

  • hl/kwd: keyword,

  • hl/lit: non-string literals,

  • hl/lit/builtin: built-in literals, i.e. None, True, False,

  • hl/lit/num: numeric literals,

  • hl/lit/num/bin: binary numeric literals,

  • hl/lit/num/oct: octal numeric literals,

  • hl/lit/num/dec: decimal numeric literals,

  • hl/lit/num/hex: hexadecimal numeric literals,

  • hl/punct: punctuation,

  • hl/str: string literals,

  • hl/str/esc: escape sequences in strings,

  • hl/str/prefix: string prefix, i.e. f in f"str",

  • hl/type: type names,

  • hl/type/builtin: type names for builtin types,

  • hl/type/user: type names for user-defined types,

  • hl/meta: diff meta info for diff highlighting,

  • hl/added: added lines in diff highlighting,

  • hl/removed: removed lines in diff highlighting,

  • hl/prog: program name in CLI usage and shell highlighting,

  • hl/flag: CLI flags,

  • hl/metavar: meta variables in CLI usage.

tb/heading
tb/message
tb/frame/location/...

For highlighted tracebacks:

  • tb/heading: traceback heading,

  • tb/message: error message,

  • tb/frame/location/file/module: module name,

  • tb/frame/location/file/line: line number,

  • tb/frame/location/file/path: file path,

  • tb/frame/location/code: code sample at the error line,

  • tb/frame/location/highlight: highlighting under the code sample.

location is either lib or usr depending on whether the code is located in site-packages or in user code.

log/part:level

Colors for log records. part is name of a log record attribute, level is lowercase name of logging level.

See also

yuio.io.Formatter.

input widget

Colors for yuio.widget.Input:

  • menu/decoration:input: decoration before an input box,

  • menu/text:input: entered text in an input box,

  • menu/text/esc:input: highlights for invisible characters in an input box,

  • menu/text/error:input: highlights for error region reported by a parser,

  • menu/text/placeholder:input: placeholder text in an input box,

grid widgets

Colors for yuio.widget.Grid, yuio.widget.Choice, and other similar widgets:

  • menu/decoration:choice/status/color_tag: decoration before a grid item,

  • menu/decoration/comment:choice/status/color_tag: decoration around comments for a grid item,

  • menu/text:choice/status/color_tag: text of a grid item,

  • menu/text/comment:choice/status/color_tag: comment for a grid item,

  • menu/text/prefix:choice/status/color_tag: prefix before the main text of a grid item (see yuio.widget.Option.display_text_prefix and yuio.complete.Completion.dprefix),

  • menu/text/suffix:choice/status/color_tag: suffix after the main text of a grid item (see yuio.widget.Option.display_text_suffix and yuio.complete.Completion.dsuffix),

  • menu/text:choice/status_line: status line (i.e. “Page x of y”).

  • menu/text:choice/status_line/number: page numbers in a status line.

status is either normal or active:

  • normal for regular grid items,

  • active for the currently selected item.

color_tag is whatever tag specified by yuio.widget.Option.color_tag and yuio.complete.Completion.group_color_tag. Currently supported tags:

  • none: color tag is not given,

  • selected: items selected in yuio.widget.Multiselect,

  • dir: directory (in file completion),

  • exec: executable file (in file completion),

  • symlink: symbolic link (in file completion),

  • socket: socket (in file completion),

  • pipe: FIFO pipe (in file completion),

  • block_device: block device (in file completion),

  • char_device: character device (in file completion),

  • original: original completion item before spelling correction,

  • corrected: completion item that was found after spelling correction.

full screen help menu

Colors for help menu that appears when pressing F1:

  • menu/text/heading:help_menu: section heading,

  • menu/text/help_key:help_menu: key names,

  • menu/text/help_sep:help_menu: separators between key names,

  • menu/decoration:help_menu: decorations.

inline help menu

Colors for help items rendered under a widget:

  • menu/text/help_info:help: help items that aren’t associated with any key,

  • menu/text/help_msg:help: regular help items,

  • menu/text/help_key:help: keybinding names,

  • menu/text/help_sep:help: separator between items.

Decorations

info

Messages from yuio.io.info.

warning

Messages from yuio.io.warning.

error

Messages from yuio.io.error.

success

Messages from yuio.io.success.

failure

Messages from yuio.io.failure.

heading/level

Messages from yuio.io.heading and headings in markdown.

heading/section

First-level headings in CLI help.

question

Messages from yuio.io.ask().

list

Bullets in markdown.

quote

Quote decorations in markdown.

code

Code decorations in markdown.

thematic_break

Thematic breaks (i.e. horizontal rulers) in markdown.

overflow

Ellipsis symbol for lines that don’t fit terminal width. Must be one character wide.

progress_bar/position

Decorations for progress bars.

Available positions are:

Start_symbol:

Start of the progress bar.

Done_symbol:

Tiles finished portion of the progress bar, must be one character wide.

Pending_symbol:

Tiles unfinished portion of the progress bar, must be one character wide.

End_symbol:

End of the progress bar.

Transition_pattern:

If this decoration is empty, there’s no symbol between finished and unfinished parts of the progress bar.

Otherwise, this decoration defines a left-to-right gradient of transition characters, ordered from most filled to least filled. Each character must be one character wide.

    [------>          ]
    │└┬───┘│└┬───────┘│
    │ │    │ │       end_symbol
    │ │    │ └ pending_symbol
    │ │    └ transition_pattern
    │ └ done_symbol
    └ start_symbol

Example:

To get the classic blocky look, you can do the following:

class BlockProgressTheme(yuio.theme.DefaultTheme):
    msg_decorations = {
        "progress_bar/start_symbol": "|",
        "progress_bar/end_symbol": "|",
        "progress_bar/done_symbol": "█",
        "progress_bar/pending_symbol": " ",
        "progress_bar/transition_pattern": "█▉▊▋▌▍▎▏ ",
    }
spinner/pattern

Defines a sequence of symbols that will be used to show spinners for tasks without known progress. Next element of the sequence will be shown every spinner_update_rate_ms.

You can find some pre-made patterns in py-spinners package.

spinner/static_symbol

Static spinner symbol, for sub-tasks that’ve finished running but’.

hr/weight/position

Decorations for horizontal rulers (see yuio.io.hr() and yuio.string.Hr()).

Default theme defines three weights:

  • 0 prints no ruler (but still prints centered text),

  • 1 prints normal ruler,

  • 2 prints bold ruler.

Available positions are:

Left_start:

Start of the ruler to the left of the message.

Left_middle:

Filler of the ruler to the left of the message.

Left_end:

End of the ruler to the left of the message.

Middle:

Filler of the ruler that’s used if msg is empty.

Right_start:

Start of the ruler to the right of the message.

Right_middle:

Filler of the ruler to the right of the message.

Right_end:

End of the ruler to the right of the message.

    <------>message<------>
    │└┬───┘│       │└┬───┘│
    │ │    │       │ │   right_end
    │ │    │       │ └ right_middle
    │ │    │       └ right_start
    │ │    └ left_end
    │ └ left_middle
    └ left_start

    <--------------------->
    │└┬──────────────────┘│
    │ middle             right_end
    └ left_start
input widget

Decorations for yuio.widget.Input:

  • menu/input/decoration: decoration before an input box,

  • menu/input/decoration_search: decoration before a search input box.

choice and multiselect widget

Decorations for yuio.widget.Choice and yuio.widget.Multiselect:

  • menu/choice/decoration/active_item: current item,

  • menu/choice/decoration/selected_item: selected item in multiselect widget,

  • menu/choice/decoration/deselected_item: deselected item in multiselect widget.

inline help and help menu

Decorations for widget help:

  • menu/help/decoration: decoration at the bottom of the help menu,

  • menu/help/key/key: text for functional keys.

    key can be one of ctrl, shift, enter, escape, insert, delete, backspace, tab, home, end, page_up, page_down, arrow_up, arrow_down, arrow_left, arrow_right, space, f1f12.