API Reference#

Attention

đźš§ There might be incompatible changes between minor versions of version zero!

If you want to use this library in a project while it’s still on version zero, ensure you pin the dependency to a specific minor version e.g >=0.1,<0.2.

urWIDgets

A collection of widgets for urwid (https://urwid.org)

Functions:

parse_text

Parses a string into a text/widget markup list.

Classes:

Hyperlink

A widget containing hyperlinked text.

TextEmbed

A text widget within which other widgets may be embedded.

urwidgets.parse_text(text, patterns, repl, *repl_args, **repl_kwargs)[source]#

Parses a string into a text/widget markup list.

Parameters:
  • text (str) – The string to parse.

  • patterns (Iterable[re.Pattern]) – An iterable of RegEx pattern objects.

  • repl (Callable[[re.Pattern, Tuple[str | None], Tuple[int, int], ...], Markup]) – A callable to replace a substring of text matched by any of the given RegEx patterns.

  • repl_args (Any) – Additional positional arguments to be passed to repl whenever it’s called.

  • repl_kwargs (Any) – keyword arguments to be passed to repl whenever it’s called.

Returns:

A text/widget markup (see Markup) that should be compatible with TextEmbed and/or urwid.Text, depending on the values returned by repl.

Raises:
  • TypeError – An argument is of an unexpected type.

  • ValueError – patterns is empty.

  • ValueError – A given pattern object was not compiled from a str instance.

Return type:

Markup

Whenever any of the given RegEx patterns matches a non-empty substring of text, repl is called with the following arguments (in the given order):

  • the re.Pattern object that matched the substring

  • a tuple containing the match groups

    • starting with the whole match,

    • followed by the all the subgroups of the match, from 1 up to however many groups are in the pattern, if any (None for each group that didn’t participate in the match)

  • a tuple containing the indexes of the start and end of the substring

  • repl_args unpacked

  • repl_kwargs unpacked

and should return a valid text/widget markup (see Markup). If the value returned is false (such as None or an empty string), it is omitted from the result.

Example:

import re
from urwid import Filler
from urwidgets import Hyperlink, TextEmbed, parse_text

MARKDOWN = {
    re.compile(r"\*\*(.+?)\*\*"): lambda g: ("bold", g[1]),
    re.compile("https://[^ ]+"): (
        lambda g: (min(len(g[0]), 14), Filler(Hyperlink(g[0], "blue")))
    ),
    re.compile(r"\[(.+)\]\((.+)\)"): (
        lambda g: (len(g[1]), Filler(Hyperlink(g[2], "blue", g[1])))
    ),
}

link = "https://urwid.org"
text = f"[This]({link}) is a **link** to {link}"
print(text)
# Output: [This](https://urwid.org) is a **link** to https://urwid.org

markup = parse_text(
    text, MARKDOWN, lambda pattern, groups, span: MARKDOWN[pattern](groups)
)
print(markup)
# Output:
# [
#   (4, <Filler box widget <Hyperlink flow widget>>),
#   ' is a ',
#   ('bold', 'link'),
#   ' to ',
#   (14, <Filler box widget <Hyperlink flow widget>>),
# ]

text_widget = TextEmbed(markup)
canv = text_widget.render(text_widget.pack()[:1])
print(canv.text[0].decode())
# Output: This is a link to https://urwid…
# The hyperlinks will be clickable if supported

Note

In the case of overlapping matches, the substring that occurs first is matched and if they start at the same index, the pattern that appears first in patterns takes precedence.

Bases: urwid.widget.WidgetWrap

A widget containing hyperlinked text.

Parameters:
  • uri (str) –

    The target of the hyperlink in URI (Uniform Resource Identifier)-encoded form.

    May be a web address (http://... or https://...), FTP address (ftp://...), local file (file://...), e-mail address (mailto:), etc.

    Every byte of this string, after being encoded, must be within the range 32 to 126 (both inclusive).

  • attr (DisplayAttribute) – Display attribute of the hyperlink text.

  • text (Optional[str]) – Alternative hyperlink text. If not given or None, the URI itself is used. Must be a single-line string.

Raises:
  • TypeError – An argument is of an unexpected type.

  • ValueError – An argument is of an expected type but of an unexpected value

This widget always renders a single line. If the widget is rendered with a width less than the length of the hyperlink text, it is clipped at the right end with an ellipsis (…) appended. On the other hand, if rendered with a width greater, it is padded with spaces on the right end.

This widget is intended to be embedded in a TextEmbed widget to combine it with pure text or other widgets but may also be used otherwise.

This widget utilizes the OSC 8 escape sequence implemented by a sizable number of mainstream terminal emulators. It utilizes the escape sequence in such a way that hyperlinks right next to one another should be detected, highlighted and treated as separate by any terminal emulator that correctly implements the feature. Also, if a hyperlink is wrapped or clipped, it shouldn’t break.

Attributes:

attrib

The display attirbute of the hyperlink.

text

The alternate text of the hyperlink.

uri

The target of the hyperlink.

property attrib#

The display attirbute of the hyperlink.

Type:

DisplayAttribute

GET:

Returns the display attirbute.

SET:

Sets the display attirbute.

property text#

The alternate text of the hyperlink.

Type:

str

GET:

Returns the alternate text.

SET:

Sets the alternate text.

property uri#

The target of the hyperlink.

Type:

str

GET:

Returns the target.

SET:

Sets the target.

class urwidgets.TextEmbed(markup, align='left', wrap='space', layout=None)[source]#

Bases: urwid.widget.Text

A text widget within which other widgets may be embedded.

This is an extension of the urwid.Text widget. Every feature and interface of Text is supported and works essentially the same, except for the “ellipsis” wrap mode which is currently not implemented. Text markup format is essentially the same, except when embedding widgets.

Embedding Widgets

A widget is embedded by specifying it as a markup element with an integer display attribute, where the display attribute is the number of screen columns the widget should occupy.

Examples:

>>> # w1 spans 2 columns
>>> TextEmbed(["This widget (", (2, w1), ") spans two columns"])
>>> # w1 and w2 span 2 columns
>>> TextEmbed(["These widgets (", (2, [w1, w2]), ") span two columns each"])
>>> # w1 and w2 span 2 columns, the text in-between has no display attribute
>>> TextEmbed([(2, [w1, (None, "and"), w2]), " span two columns each"])
>>> # w1 and w2 span 2 columns, text in the middle is red
>>> TextEmbed((2, [w1, ("red", " i am red "), w2]))
>>> # w1 and w3 span 2 columns, w2 spans 5 columns
>>> TextEmbed((2, [w1, (5, w2), w3]))

Visible embedded widgets are always rendered (may be cached) whenever the TextEmbed widget is re-rendered (i.e an uncached render). Hence, this allows for dynamic parts of text without updating the entire widget. Going a step further, embeddded widgets can be swapped by using urwid.WidgetPlaceholder but their widths will remain the same.

NOTE:
  • Every embedded widget must be a box widget and is always rendered with size (width, 1). urwid.Filler can be used to wrap flow widgets.

  • Each embedded widgets are treated as a single WORD (i.e containing no whitespace). Therefore, consecutive embedded widgets are also treated as a single WORD. This affects the “space” wrap mode.

  • After updating or swapping an embedded widget, this widget’s canvases should be invalidated to ensure it re-renders.

Raises:
  • TypeError – A widget markup element has a non-integer display attribute.

  • ValueError – A widget doesn’t support box sizing.

  • ValueError – A widget has a non-positive width (display attribute).

Attributes:

attrib

Run-length encoding of display attributes of the widget's content.

embedded

Embedded widgets.

text

Raw text content of the widget.

Methods:

get_text

Returns a representation of the widget's content.

set_text

Sets the widget's content.

property attrib#

Run-length encoding of display attributes of the widget’s content.

Type:

List[Tuple[Union[DisplayAttribute, int], int]]

See the description of the second item in the return value of get_text().

property embedded#

Embedded widgets.

Returns:

A list of all embedded widgets and their respective widths, in the same order in which they were given in the text markup.

Type:

List[Tuple[urwid.Widget, int]]

property text#

Raw text content of the widget.

Type:

str

See the description of the first item in the return value of get_text().

get_text()[source]#

Returns a representation of the widget’s content.

Returns:

A tuple (text, attrib), where

  • text is the raw text content of the widget.

    Each embedded widget is represented by a substring starting with a "\x00" character followed by zero or more "\x01" characters, with length equal to the widget’s width.

  • attrib is the run-length encoding of display attributes.

    Any entry containing a display attribute of the int type (e.g (1, 4)) denotes an embedded widget, where the display attirbute is the index of the widget within the embedded widgets list and the run length is the width of the widget.

Return type:

Tuple[str, List[Tuple[DisplayAttribute | int, int]]]

set_text(markup)[source]#

Sets the widget’s content.

Also supports widget markup elements. See the class description.

Type Aliases#

Important

These may not be complete or correct for use with a static type checker. They’re intended for the comprehension of interfaces defined in this package, by programmers.

urwidgets.Markup(*args, **kwargs)#

alias of Union[StringMarkup, ListMarkup, TupleMarkup]

urwidgets.StringMarkup(*args, **kwargs)#

alias of Union[str, bytes]

urwidgets.ListMarkup(*args, **kwargs)#

alias of List[Markup]

urwidgets.TupleMarkup(*args, **kwargs)#

alias of Union[NormalTupleMarkup, WidgetTupleMarkup]

urwidgets.NormalTupleMarkup(*args, **kwargs)#

alias of Tuple[DisplayAttribute, Union[StringMarkup, ListMarkup]]

urwidgets.DisplayAttribute(*args, **kwargs)#

alias of Union[None, str, bytes, urwid.AttrSpec]

urwidgets.WidgetTupleMarkup(*args, **kwargs)#

alias of Tuple[int, Union[urwid.Widget, WidgetListMarkup]]

urwidgets.WidgetListMarkup(*args, **kwargs)#

alias of List[Union[urwid.Widget, Markup, WidgetListMarkup]]