Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update and add more examples #4

Merged
merged 3 commits into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pip install git+https://github.com/AnonymouX47/urwidgets.git

**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`.**

See the [docs](https://urwidgets.readthedocs.io) for the API Reference.
See the [docs](https://urwidgets.readthedocs.io) for the API Reference (with usage examples).

## Contribution

Expand Down
1 change: 1 addition & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"sphinx_toolbox.github",
"sphinx_toolbox.sidebar_links",
"sphinx_toolbox.more_autosummary",
"sphinx_toolbox.collapse",
]

# -- Options for HTML output -------------------------------------------------
Expand Down
27 changes: 27 additions & 0 deletions src/urwidgets/hyperlink.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,33 @@ class Hyperlink(urwid.WidgetWrap):
separate by any terminal emulator that correctly implements the feature. Also, if a
hyperlink is wrapped or clipped, it shouldn't break.

.. collapse:: 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(len(url))
>>> 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(hyperlink.pack()[:1])
>>> print(canv.text[0].decode())
Urwid Website

.. seealso::
- `OSC 8 Specification
<https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda>`_
Expand Down
127 changes: 76 additions & 51 deletions src/urwidgets/text_embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,18 @@ class TextEmbed(urwid.Text):
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]))
.. collapse:: 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
Expand All @@ -94,6 +94,31 @@ class TextEmbed(urwid.Text):
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).

.. collapse:: 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(text_embed.pack()[:1])
>>> # 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
"""

PLACEHOLDER_HEAD: ClassVar[str] = "\uf8fe"
Expand Down Expand Up @@ -508,45 +533,45 @@ def parse_text(
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
.. collapse:: 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(text_widget.pack()[:1])
>>> # 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
Expand Down
Loading