"""
"""
import urwid
[docs]def prefix_text(text: str, prefix: str, split: str = "\n") -> str:
return split.join(prefix + part for part in text.split(split))
[docs]def row_text(rendered_row):
"""Return all text joined together from the rendered row
"""
return b"".join(x[-1] for x in rendered_row)
[docs]def resolve_bag_of_text_markup_or_widgets(items):
"""Resolve the list of items into either contiguous urwid.Text() instances,
or pre-existing urwid.Widget objects
"""
res = []
curr_text_markup = []
for item in items:
if isinstance(item, tuple) or isinstance(item, str):
curr_text_markup.append(item)
else:
if len(curr_text_markup) > 0:
res.append(urwid.Text(curr_text_markup))
curr_text_markup = []
res.append(item)
if len(curr_text_markup) > 0:
res.append(urwid.Text(curr_text_markup))
return res
[docs]def dict_deep_update(to_update, new_vals):
"""Deeply update the to_update dict with the new_vals
"""
for key, value in new_vals.items():
if isinstance(value, dict):
node = to_update.setdefault(key, {})
dict_deep_update(node, value)
else:
to_update[key] = value
[docs]def spec_from_style(styles):
"""Create an urwid.AttrSpec from a {fg:"", bg:""} style dict. If styles
is a string, it will be used as the foreground
"""
if isinstance(styles, str):
return urwid.AttrSpec(styles, "")
else:
return urwid.AttrSpec(styles.get("fg", ""), styles.get("bg", ""))
[docs]def get_fg_bg_styles(style):
if style is None:
return [], []
def non_empty_split(data):
res = [x.strip() for x in data.split(",")]
return list(filter(None, res))
# from lookatme.config.get_style()
if isinstance(style, dict):
return non_empty_split(style["fg"]), non_empty_split(style["bg"])
# just a str will only set the foreground color
elif isinstance(style, str):
return non_empty_split(style), []
elif isinstance(style, urwid.AttrSpec):
return non_empty_split(style.foreground), non_empty_split(style.background)
else:
raise ValueError("Unsupported style value {!r}".format(style))
[docs]def overwrite_spec(orig_spec, new_spec):
if orig_spec is None:
orig_spec = urwid.AttrSpec("", "")
if new_spec is None:
new_spec = urwid.AttrSpec("", "")
fg_orig = orig_spec.foreground.split(",")
fg_orig_color = orig_spec._foreground_color()
fg_orig.remove(fg_orig_color)
bg_orig = orig_spec.background.split(",")
bg_orig_color = orig_spec._background()
bg_orig.remove(bg_orig_color)
fg_new = new_spec.foreground.split(",")
fg_new_color = new_spec._foreground_color()
fg_new.remove(fg_new_color)
bg_new = new_spec.background.split(",")
bg_new_color = new_spec._background()
bg_new.remove(bg_new_color)
if fg_new_color == "default":
fg_orig.append(fg_orig_color)
else:
fg_new.append(fg_new_color)
if bg_new_color == "default":
bg_orig.append(bg_orig_color)
else:
bg_new.append(bg_new_color)
return urwid.AttrSpec(
",".join(set(fg_orig + fg_new)),
",".join(set(bg_orig + bg_new)),
)
[docs]def flatten_text(text, new_spec=None):
"""Return a flattend list of tuples that can be used as the first argument
to a new urwid.Text().
:param urwid.Text text: The text to flatten
:param urwid.AttrSpec new_spec: A new spec to merge with existing styles
:returns: list of tuples
"""
text, chunk_stylings = text.get_text()
res = []
total_len = 0
for spec, chunk_len in chunk_stylings:
split_text = text[total_len:total_len + chunk_len]
total_len += chunk_len
split_text_spec = overwrite_spec(new_spec, spec)
res.append((split_text_spec, split_text))
if len(text[total_len:]) > 0:
res.append((new_spec, text[total_len:]))
return res
[docs]def can_style_item(item):
"""Return true/false if ``style_text`` can work with the given item
"""
return isinstance(item, (urwid.Text, list, tuple))
[docs]def styled_text(text, new_styles, old_styles=None, supplement_style=False):
"""Return a styled text tuple that can be used within urwid.Text.
.. note::
If an urwid.Text instance is passed in as the ``text`` parameter,
alignment values will be lost and must be explicitly re-added by the
caller.
"""
if isinstance(text, urwid.Text):
new_spec = spec_from_style(new_styles)
return flatten_text(text, new_spec)
elif (isinstance(text, tuple)
and isinstance(text[0], urwid.AttrSpec)
and isinstance(text[1], urwid.Text)):
text = text[1].text
old_styles = text[0]
new_fg, new_bg = get_fg_bg_styles(new_styles)
old_fg, old_bg = get_fg_bg_styles(old_styles)
def join(items):
return ",".join(set(items))
spec = urwid.AttrSpec(
join(new_fg + old_fg),
join(new_bg + old_bg),
)
return (spec, text)
[docs]def pile_or_listbox_add(container, widgets):
"""Add the widget/widgets to the container
"""
if isinstance(container, urwid.ListBox):
return listbox_add(container, widgets)
elif isinstance(container, urwid.Pile):
return pile_add(container, widgets)
else:
raise ValueError("Container was not listbox, nor pile")
[docs]def listbox_add(listbox, widgets):
if not isinstance(widgets, list):
widgets = [widgets]
for w in widgets:
if len(listbox.body) > 0 \
and isinstance(w, urwid.Divider) \
and isinstance(listbox.body[-1], urwid.Divider):
continue
listbox.body.append(w)
[docs]def pile_add(pile, widgets):
"""
"""
if not isinstance(widgets, list):
widgets = [widgets]
for w in widgets:
if len(pile.contents) > 0 \
and isinstance(w, urwid.Divider) \
and isinstance(pile.contents[-1][0], urwid.Divider):
continue
pile.contents.append((w, pile.options()))
[docs]def int_to_roman(integer):
integer = int(integer)
ints = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
nums = ["m", "cm", "d", "cd", "c", "xc",
"l", "xl", "x", "ix", "v", "iv", "i"]
result = []
for i in range(len(ints)):
count = integer // ints[i]
result.append(nums[i] * count)
integer -= ints[i] * count
return "".join(result)