diff --git a/doteki/plugins/figlet.py b/doteki/plugins/figlet.py new file mode 100644 index 0000000..43bb856 --- /dev/null +++ b/doteki/plugins/figlet.py @@ -0,0 +1,46 @@ +import logging +import pyfiglet # type: ignore +from typing import Any + + +def run(settings: dict[str, Any]) -> str | None: + if not validate_settings(settings): + return None + + text = str(settings.get("ascii_text")) + font = settings.get("font", "standard") + + try: + result = pyfiglet.figlet_format(text, font) + except pyfiglet.FontNotFound: + logging.error("Invalid font for the FIGlet plugin") + return None + + result_lines = result.splitlines() + trimmed_result_lines = trim_leading_and_trailing_empty_lines(result_lines) + result = "\n".join(trimmed_result_lines) + + pre_text = "```text\n" + post_text = "\n```" + result = pre_text + result.rstrip() + post_text + return str(result) + + +def validate_settings(settings: dict[str, Any]) -> bool: + if "ascii_text" not in settings: + logging.error("No text provided for the FIGlet plugin") + return False + + return True + + +def trim_leading_and_trailing_empty_lines(lines: list[str]) -> list[str]: + # Leading lines. + while lines and lines[0].strip() == "": + lines.pop(0) + + # Trailing lines. + while lines and lines[-1].strip() == "": + lines.pop() + + return lines diff --git a/poetry.lock b/poetry.lock index 8e87fd8..d3f31fe 100644 --- a/poetry.lock +++ b/poetry.lock @@ -388,6 +388,17 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "pyfiglet" +version = "1.0.2" +description = "Pure-python FIGlet implementation" +optional = true +python-versions = ">=3.9" +files = [ + {file = "pyfiglet-1.0.2-py3-none-any.whl", hash = "sha256:889b351d79c99e50a3f619c8f8e6ffdb27fd8c939fc43ecbd7559bd57d5f93ea"}, + {file = "pyfiglet-1.0.2.tar.gz", hash = "sha256:758788018ab8faaddc0984e1ea05ff330d3c64be663c513cc1f105f6a3066dab"}, +] + [[package]] name = "pytest" version = "8.0.1" @@ -499,11 +510,12 @@ socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [extras] -all = ["feedparser", "requests"] +all = ["feedparser", "pyfiglet", "requests"] feed = ["feedparser", "requests"] +figlet = ["pyfiglet"] lastfm = ["requests"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "feb00fe505fc34afb577ba582ed9ca0b6a16aa9783ff188e66355bd5dda8e2a6" +content-hash = "b547f085367a4a065736dff67fa9fc6f442f56a4aa81089c1d340e1bc04759fc" diff --git a/pyproject.toml b/pyproject.toml index d27d70a..c3e592d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,7 @@ python = "^3.11" # Optional dependencies for plugins. feedparser = { version = "^6.0", optional = true } requests = { version = "^2.28", optional = true } +pyfiglet = { version = "^1.0.2", optional = true} [tool.poetry.extras] @@ -36,9 +37,11 @@ requests = { version = "^2.28", optional = true } all = [ # This enables `pip install doteki[all]`. Should contain all dependencies below. "requests", "feedparser", + "pyfiglet", ] lastfm = ["requests"] feed = ["requests", "feedparser"] +figlet = ["pyfiglet"] [build-system] requires = ["poetry-core"] diff --git a/tests/plugins/test_figlet.py b/tests/plugins/test_figlet.py new file mode 100644 index 0000000..4755f6c --- /dev/null +++ b/tests/plugins/test_figlet.py @@ -0,0 +1,60 @@ +import logging +import pytest +from doteki.plugins.figlet import run, trim_leading_and_trailing_empty_lines + + +def test_default_font(): + settings = {"ascii_text": "hola"} + expected = r""" _ _ +| |__ ___ | | __ _ +| '_ \ / _ \| |/ _` | +| | | | (_) | | (_| | +|_| |_|\___/|_|\__,_|""" + result = run(settings) + assert expected in str(result) + + +def test_empty_text(caplog): + settings = {"font": "standard"} + with caplog.at_level(logging.ERROR): + result = run(settings) + assert result is None + assert "No text provided for the FIGlet plugin" in caplog.text + + +def test_invalid_font_returns_none(caplog): + settings = {"ascii_text": "hola", "font": "invalid_font"} + with caplog.at_level(logging.ERROR): + result = run(settings) + assert result is None + assert "Invalid font for the FIGlet plugin" in caplog.text + + +def test_int_text(): + settings = {"ascii_text": 42, "font": "standard"} + expected = r""" _ _ ____ +| || ||___ \ +| || |_ __) | +|__ _/ __/ + |_||_____|""" + result = run(settings) + assert expected in str(result) + + +@pytest.mark.parametrize( + "lines, expected", + [ + # Removes leading and trailing empty lines. + (["", " ", "Hello", "World", "", " "], ["Hello", "World"]), + # Do not remove empty lines in the middle. + (["Hello", "", " ", "World"], ["Hello", "", " ", "World"]), + # Leave non-empty lines as is. + (["Hello", "World"], ["Hello", "World"]), + # If there are only empty lines, return an empty list. + (["", " ", " "], []), + # If no lines are provided, return an empty list. + ([], []), + ], +) +def test_trim_leading_and_trailing_empty_lines(lines, expected): + assert trim_leading_and_trailing_empty_lines(lines) == expected diff --git a/website/docs/plugins/figlet.md b/website/docs/plugins/figlet.md new file mode 100644 index 0000000..0294835 --- /dev/null +++ b/website/docs/plugins/figlet.md @@ -0,0 +1,43 @@ +# FIGlet Plugin + +Display text with customizable ASCII art using FIGlet fonts. + +## Configuration + +The FIGlet plugin can be configured with the following parameters: + +- `text`: Text to be rendered in ASCII font. +- `font`: FIGlet font to use. Defaults to `standard`. + +## Usage + +Here's an example configuration: + +```toml title="doteki.toml" +[sections.ascii_art] +plugin = "figlet" +ascii_text = "hello" +font = "isometric1" +``` + +This will render the following: + +```text + ___ ___ ___ ___ ___ + /\__\ /\ \ /\__\ /\__\ /\ \ + /:/ / /::\ \ /:/ / /:/ / /::\ \ + /:/__/ /:/\:\ \ /:/ / /:/ / /:/\:\ \ + /::\ \ ___ /::\~\:\ \ /:/ / /:/ / /:/ \:\ \ + /:/\:\ /\__\ /:/\:\ \:\__\ /:/__/ /:/__/ /:/__/ \:\__\ + \/__\:\/:/ / \:\~\:\ \/__/ \:\ \ \:\ \ \:\ \ /:/ / + \::/ / \:\ \:\__\ \:\ \ \:\ \ \:\ /:/ / + /:/ / \:\ \/__/ \:\ \ \:\ \ \:\/:/ / + /:/ / \:\__\ \:\__\ \:\__\ \::/ / + \/__/ \/__/ \/__/ \/__/ \/__/ +``` + +## Frequently Asked Questions + +### Where can I find a list of available fonts? + +Check the [FIGlet official site](http://www.figlet.org/examples.html) to explore the available fonts.