Skip to main content

Programmatic ASCII art generation for TUIs

Project description

ascii-art

Tests Python License Type Checked Code Style Version

Programmatic ASCII art generation for TUI applications. Build text banners, convert images, draw shapes, render tables and charts, animate sprites — all as plain text strings ready for terminal display.

Installation

pip install ascii-art

With optional integrations:

pip install ascii-art[rich]      # Rich panels & text objects
pip install ascii-art[textual]   # Textual Static widgets
pip install ascii-art[dev]       # pytest, mypy, ruff

Quick Start

import ascii_art

# Figlet text banner
print(ascii_art.text_render("Hello!", font="slant"))

# Image to ASCII
print(ascii_art.image_render("photo.png", width=60))

# Draw shapes on a canvas
canvas = ascii_art.Canvas(40, 20)
ascii_art.circle(canvas, 20, 10, 8, char="*")
ascii_art.rectangle(canvas, 5, 3, 30, 14, char="#")
print(canvas.render())

# Border frame
print(ascii_art.frame("Important message", style=ascii_art.BorderStyle.ROUNDED, title="Notice"))

# Table
print(ascii_art.table(
    [["Alice", "92"], ["Bob", "87"]],
    headers=["Name", "Score"],
    style=ascii_art.BorderStyle.DOUBLE,
))

# Sparkline chart
print(ascii_art.sparkline([1, 4, 2, 8, 5, 7, 3, 6]))

# Bar chart
print(ascii_art.bar_chart([30, 80, 45, 60], labels=["Q1", "Q2", "Q3", "Q4"], width=30))

# Scatter plot
print(ascii_art.scatter([(1, 2), (3, 7), (5, 4), (8, 9)], width=40, height=15))

Fluent Builder API

Every module provides a Builder class for method-chaining style configuration:

from ascii_art import TextBuilder, BorderBuilder, ShapesBuilder, ChartBuilder

# Text
output = TextBuilder().text("Welcome").font("big").width(100).render()

# Borders
box = BorderBuilder().text("Hello").style(BorderStyle.DOUBLE).title("Greeting").render()

# Shapes — compose multiple primitives
scene = (
    ShapesBuilder()
    .width(60).height(20).char("*")
    .add_circle(30, 10, 8)
    .add_rectangle(5, 3, 50, 14)
    .add_line(0, 0, 59, 19)
    .render()
)

# Charts
chart = ChartBuilder().chart_type("bar").data([10, 20, 30]).width(50).labels(["A", "B", "C"]).render()

Text Rendering

Renders text using pyfiglet fonts with alignment control.

from ascii_art import text_render, list_fonts, Alignment

# List available curated fonts
print(list_fonts())
# ['banner', 'big', 'block', 'bubble', 'digital', 'lean', 'slant', 'small', 'standard', ...]

# Centered text
print(text_render("Title", font="shadow", width=60, align=Alignment.CENTER))

Image Conversion

Converts images to ASCII art using luminance mapping with optional edge detection.

from ascii_art import image_render, DETAILED_CHAR_RAMP, BLOCK_CHAR_RAMP

# Basic conversion
print(image_render("landscape.jpg", width=100))

# Inverted with detailed character set
print(image_render("logo.png", width=60, charset=DETAILED_CHAR_RAMP, invert=True))

# Edge detection (Sobel filter)
print(image_render("diagram.png", width=80, edges=True))

# From a PIL Image object
from PIL import Image
img = Image.open("photo.jpg")
print(image_render(img, width=120))

Three built-in character ramps are available:

Ramp Characters Use case
DEFAULT_CHAR_RAMP .:-=+*#%@ General purpose
DETAILED_CHAR_RAMP 70 chars, fine gradation High detail
BLOCK_CHAR_RAMP ░▒▓█ Block-style output

Shape Drawing

Draw primitives on a Canvas — a 2D character grid. All drawing functions mutate the canvas in-place and return it for chaining.

from ascii_art import Canvas, line, rectangle, circle, ellipse, triangle, diamond, arrow

c = Canvas(60, 25)
rectangle(c, 0, 0, 59, 24, "#")       # border
circle(c, 30, 12, 10, "o")            # centered circle
line(c, 0, 0, 59, 24, ".")            # diagonal
diamond(c, 30, 12, 5, "+")            # diamond overlay
triangle(c, 10, 20, 30, 5, 50, 20)    # triangle
arrow(c, 5, 12, 25, 12)               # horizontal arrow

print(c.render())

Canvases support overlay for compositing:

bg = Canvas(40, 20)
fg = Canvas(10, 5)
circle(fg, 5, 2, 2, "*")
bg.overlay(fg, 15, 7)  # paste fg onto bg at offset (15, 7)

Borders & Frames

from ascii_art import frame, divider, BorderStyle

# Six border styles: SINGLE, DOUBLE, ROUNDED, BOLD, ASCII, DASHED, SHADOW
print(frame("Content here", style=BorderStyle.ROUNDED, padding=2, title="Header"))

# Horizontal dividers
print(divider("Section", width=60, style=BorderStyle.DOUBLE))
# ═══════════════════════════ Section ══════════════════════════

Border Styles

SINGLE:  ┌──┐    DOUBLE:  ╔══╗    ROUNDED: ╭──╮
         │  │             ║  ║             │  │
         └──┘             ╚══╝             ╰──╯

BOLD:    ┏━━┓    ASCII:   +--+    DASHED:  ┌╌╌┐
         ┃  ┃             |  |             ╎  ╎
         ┗━━┛             +--+             └╌╌┘

SHADOW:  ┌──┐░
         │  │░
         └──┘░
          ░░░░

Tables

from ascii_art import table, Alignment, BorderStyle

data = [
    ["Alice", "Engineering", "92"],
    ["Bob", "Marketing", "87"],
    ["Carol", "Engineering", "95"],
]

print(table(
    data,
    headers=["Name", "Dept", "Score"],
    style=BorderStyle.BOLD,
    alignments=[Alignment.LEFT, Alignment.LEFT, Alignment.RIGHT],
))

Output:

┏━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┓
┃ Name  ┃ Dept        ┃ Score ┃
┣━━━━━━━╋━━━━━━━━━━━━━╋━━━━━━━┫
┃ Alice ┃ Engineering ┃    92 ┃
┃ Bob   ┃ Marketing   ┃    87 ┃
┃ Carol ┃ Engineering ┃    95 ┃
┗━━━━━━━┻━━━━━━━━━━━━━┻━━━━━━━┛

Charts

from ascii_art import sparkline, bar_chart, scatter

# Sparkline — single-line Unicode block chart
print(sparkline([1, 4, 2, 8, 5, 7, 3, 6]))
# ▁▅▂█▄▆▃▅

# Horizontal bar chart with labels
print(bar_chart([30, 80, 45, 60], labels=["Q1", "Q2", "Q3", "Q4"], width=30))

# Scatter plot
print(scatter([(1, 1), (2, 4), (3, 2), (5, 8), (7, 3)], width=40, height=15))

Sprites & Animation

from ascii_art import Sprite, Animation, SPRITES

# Use a built-in sprite
heart = Sprite(SPRITES["heart"])
print(heart.render())

# Transforms (all return new Sprite)
flipped = heart.flip_h()
big = heart.scale(2)
rotated = heart.rotate(90)

# Animation from frames
frames = [heart, heart.flip_h(), heart.flip_v()]
anim = Animation(frames)
for frame in anim:
    print(frame.render())
    print("---")

Built-in sprites: heart, star, arrow_right, smiley.

Framework Integrations

Rich

from ascii_art.integrations.rich_panel import to_text, to_panel
from rich.console import Console

console = Console()
art = ascii_art.text_render("Hello", font="slant")
console.print(to_panel(art, title="ASCII Art"))

Textual

from ascii_art.integrations.textual_widget import to_static

widget = to_static(ascii_art.text_render("Dashboard"))
# Use in a Textual app's compose() method

Curses

from ascii_art.integrations.curses_win import write_to_window

# Inside a curses application
write_to_window(stdscr, ascii_art.frame("Status: OK"), y=2, x=5)

CLI

# Text banners
ascii-art text "Hello World" --font slant --width 100 --align center

# Image conversion
ascii-art image photo.png --width 80 --invert
ascii-art image diagram.png --edges

# Shape drawing
ascii-art shape circle --width 40 --height 20 --char "o"
ascii-art shape rectangle --width 30 --height 15
ascii-art shape diamond --char "+"

# Border framing (text argument or stdin)
ascii-art border "important text" --style rounded --title "Notice"
echo "piped text" | ascii-art border --style double

# Table from CSV (argument or stdin)
ascii-art table "Name,Score\nAlice,92\nBob,87" --headers --style bold
cat data.csv | ascii-art table --headers

# Charts
ascii-art chart "1,4,2,8,5,7" --type bar --width 30
ascii-art chart "1,4,2,8,5,7" --type sparkline

Development

# Create virtual environment and install dev dependencies
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

# Run tests
pytest

# Run a single test
pytest tests/test_shapes.py::test_rectangle -v

# Performance benchmarks
pytest -m perf

# Type checking (strict mode)
mypy src/

# Lint
ruff check src/ tests/

# Build distribution
python -m build

Project Structure

src/ascii_art/
├── __init__.py          # Public API re-exports
├── __main__.py          # CLI entry point
├── _types.py            # Enums, type aliases, character ramps
├── _builder.py          # BaseBuilder ABC (fluent API pattern)
├── _cache.py            # @cached decorator
├── text.py              # Figlet text rendering
├── image.py             # Image-to-ASCII conversion
├── shapes.py            # Canvas + drawing primitives
├── borders.py           # Frame/divider rendering
├── tables.py            # ASCII table rendering
├── charts.py            # Sparkline, bar chart, scatter plot
├── sprites.py           # Sprite transforms & animation
└── integrations/        # Rich, Textual, curses adapters

Requirements

  • Python 3.10+
  • pyfiglet — text rendering
  • Pillow — image conversion

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tui_ascii_art-0.1.1.tar.gz (30.9 kB view details)

Uploaded Source

File details

Details for the file tui_ascii_art-0.1.1.tar.gz.

File metadata

  • Download URL: tui_ascii_art-0.1.1.tar.gz
  • Upload date:
  • Size: 30.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for tui_ascii_art-0.1.1.tar.gz
Algorithm Hash digest
SHA256 4379c57cf1e2bf7c88d8b1097535311b47ce187ed68788adab5c29252cedf748
MD5 5ef45a428881d6f1b70aea6994b50ac9
BLAKE2b-256 f2a8d23fe110e9b4e3fb1f1e756791d6790e06aa6b0e24a539ace11a701abebc

See more details on using hashes here.

Provenance

The following attestation bundles were made for tui_ascii_art-0.1.1.tar.gz:

Publisher: publish.yml on GCLNS/ascii-art

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page