{"id":31628192,"url":"https://github.com/pfahlr/figlet-font-curator","last_synced_at":"2026-05-06T13:35:54.065Z","repository":{"id":317807671,"uuid":"1068915946","full_name":"pfahlr/figlet-font-curator","owner":"pfahlr","description":"Scans a directory of figlet fonts comparing them to another directory (your collection) and copies any that do not match any of the fonts already in your collection. ","archived":false,"fork":false,"pushed_at":"2025-10-03T07:10:40.000Z","size":9421,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-03T07:20:54.575Z","etag":null,"topics":["1990s","2000s","ascii","ascii-art","cli","collection","command-line","curated","figlet","figlet-fonts","fonts","retro","terminal"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pfahlr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-03T05:37:04.000Z","updated_at":"2025-10-03T07:10:44.000Z","dependencies_parsed_at":"2025-10-03T07:31:54.194Z","dependency_job_id":null,"html_url":"https://github.com/pfahlr/figlet-font-curator","commit_stats":null,"previous_names":["pfahlr/figlet-font-curator"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/pfahlr/figlet-font-curator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfahlr%2Ffiglet-font-curator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfahlr%2Ffiglet-font-curator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfahlr%2Ffiglet-font-curator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfahlr%2Ffiglet-font-curator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pfahlr","download_url":"https://codeload.github.com/pfahlr/figlet-font-curator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfahlr%2Ffiglet-font-curator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278672195,"owners_count":26025860,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["1990s","2000s","ascii","ascii-art","cli","collection","command-line","curated","figlet","figlet-fonts","fonts","retro","terminal"],"created_at":"2025-10-06T20:19:38.067Z","updated_at":"2025-10-06T20:19:39.600Z","avatar_url":"https://github.com/pfahlr.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"```\n ██████████████████████████████████████████████████████████\n █▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█\n █▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓█\n █▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓█\n █▓░                                                    ░▓█\n █▓░  ╭╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮  ░▓█\n █▓░  ┊                      ###                     ┊  ░▓█\n █▓░  ┊ ####### ###  ###### ###    ######## ######## ┊  ░▓█\n █▓░  ┊         ### ###     ###                ###   ┊  ░▓█\n █▓░  ┊ ####### ### ###  ## ###     #######    ###   ┊  ░▓█\n █▓░  ┊ ##      ### ###  ## ###     ###        ###   ┊  ░▓█\n █▓░  ┊ ##      ###  ###### ####### #######    ###   ┊  ░▓█\n █▓░  ┊ ==========================================   ┊  ░▓█\n █▓░  ┊                           __                 ┊  ░▓█\n █▓░  ┊    _______  ___________ _/ /_____  _____     ┊  ░▓█\n █▓░  ┊   / ___/ / / / ___/ __ `/ __/ __ \\/ ___/     ┊  ░▓█\n █▓░  ┊  / /__/ /_/ / /  / /_/ / /_/ /_/ / /         ┊  ░▓█\n █▓░  ┊  \\___/\\__,_/_/   \\__,_/\\__/\\____/_/          ┊  ░▓█\n █▓░  ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯  ░▓█\n █▓░                                                    ░▓█\n █▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓█\n █▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓█\n █▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█\n ██████████████████████████████████████████████████████████\n```\n\n\n# FIGlet Font Curator \u0026 Browser\n\nA two-part toolkit for building and exploring a clean, well-organized **FIGlet** font collection:\n\n1. **Curator (CLI)** — import `.flf`/`.tlf`/`.flc`, de-duplicate, organize into a repository, with optional *output-based* duplicate detection\n2. **Browser (Textual TUI)** — preview `.flf`/`.tlf` fonts live, filter, and save previews; supports fonts packaged inside ZIP archives\n\n\u003e Built with [Rich](https://github.com/Textualize/rich) / [Textual](https://github.com/Textualize/textual).\n\u003e Rendering uses system `figlet` (and optionally `toilet` for `.tlf`).\n\n---\n\n## Features at a glance\n\n**Curator — `figlet_font_curator.py`**\n\n* Imports `.flf`, `.tlf`, and `.flc` files from `--in` into `--out`\n* **Content-based de-duplication** using fast `xxhash`\n* **Optional output-based de-duplication** (`--compare-output`): hashes the **rendered FIGlet output** for a fixed sample string to detect duplicates that produce identical text output\n* **Versioned name collisions**: `name.ext` → `name_v02.ext`, `name_v03.ext`, …\n* Optional **recursive** scan and **structure preservation** (`--maintain-structure` with `--outsub` + `-r`)\n* **Rich** progress bars and pretty console logs\n* **JSONL** audit log saved to `--out`\n\n**Browser — `figlet_font_browser.py`**\n\n* Recursively scans a font dir for `.flf` and `.tlf`\n* **ZIP support**: transparently previews `.flf`/`.tlf` found *inside* `.zip` files (cached extraction)\n* Live preview of your text (adjustable width)\n* Optional **FIGlet charmap** (`.flc`) via `--flc` (passed to `figlet` with `-C`)\n* Optional `--use-toilet` for `.tlf` rendering\n* Filter/search list; save **current** or **all** previews\n* Robust output normalization: CP437/Latin-1 fallbacks, ANSI repair, backspace overstrike handling\n\n---\n\n## Install\n\n### System requirements\n\n* Python 3.9+ (tested up to 3.13)\n* `figlet` in your `PATH`\n* Optionally `toilet` (only if you plan to render `.tlf` with `--use-toilet`)\n\n### Python dependencies\n\n```bash\n# in your virtualenv\npip install rich textual xxhash\n```\n\n---\n\n## 1) Curator (CLI)\n\n**Script:** `figlet_font_curator.py`\n\nImports `.flf`, `.tlf`, and `.flc` from `--in` to `--out` with de-duplication and optional organization.\nDuplicates are detected either by **raw file content** (fast, default), or by **rendered output** when `--compare-output` is set.\n\n### Usage\n\n```bash\npython figlet_font_curator.py \\\n  --in /path/to/in_fonts \\\n  --out /path/to/out_fonts \\\n  [-r|--recursive] \\\n  [--outsub source_name] \\\n  [--maintain-structure] \\\n  [--compare-output]\n```\n\n### Options\n\n* `--in, -i \u003cdir\u003e`\n  Input directory containing `.flf` / `.tlf` / `.flc`\n* `--out, -o \u003cdir\u003e`\n  Output directory (the master repo)\n* `-r, --recursive`\n  Recurse into `--in` subdirectories\n* `--outsub \u003cname\u003e`\n  Place this run’s copies under `--out/\u003cname\u003e/` (still de-dups against **all of `--out`**)\n* `--maintain-structure`\n  Effective **only** with `--outsub` **and** `--recursive`; preserves the input’s subdirectory layout under `--out/\u003coutsub\u003e/`\n* `--compare-output`\n  Compare fonts by the **FIGlet-rendered output** for a fixed sample string (`\"FIGLET FONT CURATOR\"`) instead of raw file content\n  *(Requires `figlet` to be installed.)*\n\n### How de-duplication works\n\n* **Default (content-based):** A fast `xxhash` digest of the file bytes is used. If a match is found anywhere under `--out` (scanned recursively), the file is skipped.\n* **`--compare-output`:** The Curator runs `figlet` with `-d \u003cfont_dir\u003e -f \u003cfont_name\u003e` using a fixed sample string, and hashes the resulting text. Files that produce **identical output** are treated as duplicates even if their bytes differ.\n\n  * This is useful to collapse near-identical `.flf` files that render the same.\n  * **Important:** Output comparison applies to **`.flf` fonts only**. Non-FIGlet files like `.tlf` or `.flc` **can’t** be rendered by `figlet`; those will be **skipped** (logged as `ERROR_FINGERPRINT`) when `--compare-output` is enabled. If your set includes `.tlf`/`.flc`, prefer the default content-based mode.\n\n### Naming \u0026 versioning\n\nIf a filename collision occurs (same name, different content/output), Curator writes the next available versioned name in the destination folder:\n\n```\nfont.flf → font_v02.flf → font_v03.flf → ...\n```\n\n### Logging\n\n* A JSONL audit log is written to:\n\n  ```\n  --out/figlet_import_YYYYMMDD_HHMMSS.log.jsonl\n  ```\n\n  Each event includes timestamps, inputs, destination, fingerprint method, and action (`COPY`, `COPY_RENAMED`, `SKIP_DUPLICATE`, errors, etc.).\n* Console progress and summaries use **Rich**.\n\n### Examples\n\n```bash\n# Simple flat import (content-based de-dup)\npython figlet_font_curator.py --in ./fonts_in --out ./fonts_repo\n\n# Recursive import grouped under 'dump_2025_10_03' and preserve input tree\npython figlet_font_curator.py --in ./dump --out ./repo -r --outsub dump_2025_10_03 --maintain-structure\n\n# Output-based duplicate detection (FIGlet-rendered equivalence), .flf-only\npython figlet_font_curator.py --in ./flf_only --out ./repo --compare-output\n```\n\n**Notes \u0026 caveats**\n\n* If `--out` is nested inside `--in` and you pass `-r`, Curator automatically **excludes** the `--out` subtree to avoid re-ingesting its own output.\n* `--compare-output` uses a fixed sample string (`\"FIGLET FONT CURATOR\"`). To change the sample text, edit `DEFAULT_COMPARE_TEXT` in the script.\n\n---\n\n## 2) Browser (Textual TUI)\n\n**Script:** `figlet_font_browser.py`\n\nA terminal UI for browsing and previewing FIGlet fonts. It recursively scans a font directory for `.flf` and `.tlf` files, **including those inside ZIP archives**, renders a live preview of your text, and (optionally) applies a FIGlet charmap (`.flc`) via `--flc`. You can filter, page through results, and save outputs.\n\n### Usage\n\n```bash\npython figlet_font_browser.py \\\n  --font-dir ~/figlet-fonts \\\n  --text \"Hello World\" \\\n  [--width 80] \\\n  [--flc /path/to/latin1.flc] \\\n  [--out-dir ./out] \\\n  [--out-prefix run_] \\\n  [--use-toilet]\n```\n\n### Features\n\n* Recursively scans `--font-dir` for:\n\n  * `.flf` (FIGlet fonts)\n  * `.tlf` (TOIlet fonts)\n  * **Inside ZIPs**: `.flf`/`.tlf` files are extracted to a temp cache and previewed seamlessly\n* `--flc`: pass a **FIGlet charmap** via `-C` (FIGlet-only; ignored for `toilet`)\n* Live preview with adjustable width (`w`)\n* Quick filter/search of font list (`/`)\n* Save the current preview (`s`) or **all** filtered previews (`a`)\n* Output normalization:\n\n  * Fixes ANSI sequences that get split by FIGlet’s wrapping\n  * Applies backspace overstrikes (for classic shading/bold tricks)\n  * Decodes with UTF-8, CP437, and Latin-1 fallbacks to preserve block characters\n\n### CLI Options\n\n* `--font-dir \u003cdir\u003e`: Base directory to scan recursively (default: `~/figlet-fonts`)\n* `--text \u003cstring\u003e` **(required)**: The text to render\n* `--width \u003ccols\u003e`: Render width (default: TTY width or `80`)\n* `--flc \u003cpath\u003e`: Path to a `.flc` charmap (FIGlet-only; `toilet` doesn’t support `-C`)\n* `--out-dir \u003cdir\u003e`: Where to save previews (`s` / `a` actions)\n* `--out-prefix \u003cstr\u003e`: Filename prefix when saving\n* `--use-toilet`: Use `toilet` to render `.tlf` (if installed)\n\n### Keybindings\n\n* `/` — focus filter input\n* `w` — change width (type a number, press Enter)\n* `j` / `k` or ↓ / ↑ — move selection\n* `s` — save **current** preview to `--out-dir/\u003cprefix\u003eN.asc`\n* `a` — save **all** filtered previews (with headers) to `--out-dir`\n* `r` — rescan fonts\n* `q` — quit\n\n### Examples\n\n```bash\n# Browse a collection (recursively)\npython figlet_font_browser.py --font-dir ~/figlet-fonts --text JSON\n\n# Apply a specific charmap (FIGlet-only)\npython figlet_font_browser.py --font-dir ~/figlet-fonts --text \"Café déjà vu\" \\\n  --flc ~/figlet-fonts/charmaps/latin1.flc\n\n# Prefer 'toilet' for .tlf fonts\npython figlet_font_browser.py --font-dir ~/figlet-fonts --text \"HELLO\" --use-toilet\n\n# Save previews as you browse\npython figlet_font_browser.py --font-dir ~/figlet-fonts --text \"Hello\" \\\n  --out-dir ./out --out-prefix run_\n```\n\n---\n\n## Recommended workflow\n\n1. **Curate**\n   Use the Curator to gather fonts into a de-duplicated repo at `--out`, optionally grouping each run with `--outsub` and mirroring structure with `--maintain-structure`.\n\n2. **Browse**\n   Point the Browser at your curated repo (or any folder/ZIP collection), try `.flc` charmaps, and export previews to share or compare.\n\n---\n\n## Troubleshooting\n\n**Curator**\n\n* *“It’s ingesting its own output”* → If `--out` is under `--in` and you used `-r`, the Curator excludes `--out` automatically.\n* *“Why are `.tlf` / `.flc` skipped in `--compare-output` mode?”* → Output-comparison renders with `figlet` and is intended for `.flf`; non-FIGlet files can’t be rendered there and are skipped (with error logs). Use the default content-based mode for mixed sets.\n\n**Browser**\n\n* *Charmap not applied* → `--flc` only applies to `.flf` (FIGlet); `toilet` does not support `-C`.\n* *Garbled blocks/ANSI noise* → The app repairs split ANSI, handles backspace overstrikes, and tries CP437/Latin-1 if UTF-8 fails. If a specific font still looks off, try a different width.\n\n---\n\n## Project structure (suggested)\n\n```\n.\n├─ figlet_font_curator.py      # CLI import/dedupe (content or output-based)\n├─ figlet_font_browser.py      # Textual TUI w/ ZIP support\n├─ README.md\n└─ requirements.txt            # rich, textual, xxhash\n```\n\n---\n\n## Contributing\n\n* Code style: Python with **2-space** indents (project preference).\n* Keep CLI (Curator) and TUI (Browser) concerns decoupled.\n* PRs welcome for:\n\n  * Making the Curator’s sample text configurable at runtime\n  * Optional watch mode for Curator (e.g., `watchfiles`)\n  * Fuzzy/regex filter in the Browser\n  * Export presets, batch selection, or side-by-side comparisons in the Browser\n\n---\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpfahlr%2Ffiglet-font-curator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpfahlr%2Ffiglet-font-curator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpfahlr%2Ffiglet-font-curator/lists"}