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:
Parses a string into a text/widget markup. |
Classes:
A widget containing hyperlinked text. |
|
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.
- 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 withTextEmbedand/orurwid.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
strinstance.
- 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
Patternobject that matched the substringa 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 (
Nonefor each group that didn’t participate in the match)
a tuple containing the span (start and end indexes) 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 asNoneor 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: (len(g[0]), Filler(Hyperlink(g[0]))) >>> ), >>> re.compile(r"\[(.+)\]\((.+)\)"): ( >>> lambda g: (len(g[1]), Filler(Hyperlink(g[2], text=g[1]))) >>> ), >>> } >>> >>> link = "https://urwid.org" >>> text = f"[This]({link}) is a **link** to {link}" >>> print(text) [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) [ (4, <Filler box widget <Hyperlink flow widget>>), ' is a ', ('bold', 'link'), ' to ', (17, <Filler box widget <Hyperlink flow widget>>), ] >>> >>> text_widget = TextEmbed(markup) >>> canv = text_widget.render(()) >>> # The hyperlinks (`This` and `https://urwid.org`) should be highlighted >>> # on mouse hover and clickable (in the terminal), if supported. >>> print(canv.text[0].decode()) This is a link to https://urwid.org
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.
- class urwidgets.Hyperlink(uri, attr=None, text=None)[source]#
Bases:
urwid.widget.widget.WidgetWrapA 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://...orhttps://...), FTP address (ftp://...), local file (file://...), e-mail address (mailto:), etc.Every byte of this string, after being encoded, must be within the range
32to126(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, with left alignment and the ellipsis wrap mode of
urwid.Texti.e 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
TextEmbedwidget to combine it with pure text or other widgets but may as well be used otherwise.This widget utilizes the
OSC 8escape 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.Examples:
>>> from urwidgets import Hyperlink >>> >>> url = "https://urwid.org" >>> >>> # The hyperlinks in the outputs should be highlighted on mouse hover >>> # and clickable (in the terminal), if supported. >>> >>> # Raw URI >>> link = Hyperlink(url) >>> canv = link.render(()) >>> print(canv.text[0].decode()) https://urwid.org >>> >>> # Clipped (with an ellipsis appended) when the render width (maxcols) is >>> # shorter than the link text >>> canv = link.render((len(url) - 4,)) >>> print(canv.text[0].decode()) https://urwid… >>> >>> # URI with custom text >>> hyperlink = Hyperlink(url, text="Urwid Website") >>> canv = hyperlink.render(()) >>> print(canv.text[0].decode()) Urwid Website
See also
- OSC 8 Specification
Official specification for hyperlinks in terminals.
- OSC 8 adoption in terminal emulators
Documentation of the adoption of the feature across terminal emulators and terminal-based applications.
TextEmbedA widget that enables the use of hyperlinks amidst normal text.
Attributes:
The display attirbute of the hyperlink.
The alternate text of the hyperlink.
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:
- GET:
Returns the alternate text.
- SET:
Sets the alternate text.
- class urwidgets.TextEmbed(markup, align=Align.LEFT, wrap=WrapMode.SPACE, layout=None)[source]#
Bases:
urwid.widget.text.TextA text widget within which other widgets may be embedded.
This is an extension of the
urwid.Textwidget. Every feature and interface ofTextis 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
TextEmbedwidget 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 usingurwid.WidgetPlaceholderbut their widths will remain the same.Note
Every embedded widget must be a box widget and is always rendered with size
(width, 1).urwid.Fillercan be used to wrap flow widgets.As regards the “space” wrap mode, each embedded widget is treated as a single WORD (i.e containing no whitespace). In other words, whitespace within embedded widgets do not influence wrapping.
After updating or swapping an embedded widget, the containing
TextEmbedwidget’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).
Example:
>>> from urwidgets import TextEmbed, Hyperlink >>> from urwid import Filler >>> >>> url = "https://urwid.org" >>> this = Hyperlink(url, text="This") >>> link = Hyperlink(url) >>> >>> text_embed = TextEmbed( ... [ ... (4, Filler(this)), ... " is a ", ... ("bold", "link"), ... " to ", ... (len(url), Filler(link)), ... ] ... ) >>> >>> canv = text_embed.render(()) >>> # The hyperlinks (`This` and `https://urwid.org`) should be highlighted >>> # on mouse hover and clickable (in the terminal), if supported. >>> print(canv.text[0].decode()) This is a link to https://urwid.org
See also
parse_text()Parses a string into a text/widget markup that can be used with this class.
Attributes:
Embedded widgets' text placeholder components.
Run-length encoding of display attributes of the widget's content.
Embedded widgets.
Raw text content of the widget.
Methods:
- PLACEHOLDER_TAIL: ClassVar[str] = '\uf8ff'#
Embedded widgets’ text placeholder components.
Each should be a unique unicode codepoint that:
occupies exactly one column on a terminal screen.
is guaranteed to not occur in the text content of the widget, if any.
Either or both may only be overriden on subclasses (during their creation, not after), as in:
class TextEmbedSub(TextEmbed): PLACEHOLDER_HEAD = "=" PLACEHOLDER_TAIL = "-"
Note
In most cases, the defaults should be sufficient. There’s no need to override these except it’s possible for the default values to occur in the widget’s text content (if any), which is highly unlikely.
That said, the default values should be considered implementation detail; hence, may change at any time without notice. They’re only provided to help the user avoid conflicts with actual text content. If the values are depended upon, then they should be overriden on a subclass, as described above.
- property attrib#
Run-length encoding of display attributes of the widget’s content.
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:
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), wheretext is the raw text content of the widget.
Each embedded widget is represented by a placeholder substring 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
inttype (e.g(1, 4)) denotes an embedded widget, where the display attirbute is the index of the widget within theembeddedwidgets list and the run length is the width of the widget.
- Return type:
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.TupleMarkup(*args, **kwargs)#
alias of
Union[NormalTupleMarkup,WidgetTupleMarkup]
- urwidgets.NormalTupleMarkup(*args, **kwargs)#
alias of
Tuple[DisplayAttribute,Union[StringMarkup,ListMarkup]]
- urwidgets.WidgetTupleMarkup(*args, **kwargs)#
alias of
Tuple[int,Union[urwid.Widget,WidgetListMarkup]]
- urwidgets.WidgetListMarkup(*args, **kwargs)#
alias of
List[Union[urwid.Widget,Markup,WidgetListMarkup]]