Geplante Erweiterungen wären eine vereinfachte Schriftauswahl (basierend auf Größe und Stil), sowie Kommandozeilen-Argumente. Außerdem Support für Buchstaben in allen Schriften (wobei sich meine Designer-Fähigkeiten in Grenzen halten) und für Umlaute bzw Nicht-ASCII Zeichen (da bin ich definitiv raus).
Hier auf jeden Fall mein bisheriger Stand:
Code: Alles auswählen
#!/usr/bin/env python3
import urwid
class FontStore:
def __init__(self, utf8_mode=None):
self._fonts = {
self._normalize(font_name): font_class()
for font_name, font_class in urwid.get_all_fonts()
}
if utf8_mode is None:
self.utf8_mode = urwid.get_encoding_mode() == "utf8"
else:
self.utf8_mode = utf8_mode
@staticmethod
def _normalize(font_name):
return font_name.capitalize()
def _is_available(self, font):
if self.utf8_mode:
# All fonts are allowed
return True
return not font.utf8_required
@property
def fonts(self):
return {
name: font for name, font in self._fonts.items()
if self._is_available(font)
}
@property
def font_names(self):
return sorted(self.fonts.keys())
def get_font(self, font_name):
normalized = self._normalize(font_name)
if normalized not in self._fonts:
raise ValueError(f"Unknown font: {font_name}")
font = self._fonts[normalized]
if not self._is_available(font):
raise ValueError(
f"Font {font_name!r} only available in UTF-8 mode"
)
return font
class Renderer:
def __init__(self, font_store=None, encoding=None):
self.font_store = font_store or FontStore()
self.encoding = encoding or urwid.get_encoding_mode()
def get_unsupported(self, text, font_name):
font = self.font_store.get_font(font_name)
allowed_chars = set(font.characters())
return list(set(text) - allowed_chars)
def _check(self, text, font_name):
unsupported = self.get_unsupported(text, font_name)
if len(unsupported) > 0:
raise ValueError(
f"Cannot render these characters: {unsupported}"
)
def render(self, text, font_name, check_chars=True):
if check_chars:
self._check(text, font_name)
font = self.font_store.get_font(font_name)
bigtext = urwid.BigText(text, font)
text = b"\n".join(bigtext.render(()).text)
return text.decode(self.encoding)
def main():
r = Renderer()
print("Available fonts:", r.font_store.font_names, sep="\n")
print(r.render("Hello World", "Thin 6x6"))
# This should fail
# print(r.render("65 mph", "Thin 3x3"))
if __name__ == "__main__":
main()