Metadata-Version: 2.4
Name: tui-ascii-art
Version: 0.1.1
Summary: Programmatic ASCII art generation for TUIs
Author-email: George Kennedy <gkennedy@gcloudns.net>
Requires-Python: >=3.10
Requires-Dist: pillow>=10.0
Requires-Dist: pyfiglet>=1.0
Provides-Extra: dev
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Provides-Extra: rich
Requires-Dist: rich>=13.0; extra == 'rich'
Provides-Extra: textual
Requires-Dist: textual>=0.40; extra == 'textual'
Description-Content-Type: text/markdown

# ascii-art

![Tests](https://img.shields.io/badge/tests-250%20passing-brightgreen)
![Python](https://img.shields.io/badge/python-3.10%2B-blue)
![License](https://img.shields.io/badge/license-MIT-green)
![Type Checked](https://img.shields.io/badge/mypy-strict-blue)
![Code Style](https://img.shields.io/badge/code%20style-ruff-000000)
![Version](https://img.shields.io/badge/version-0.1.1-orange)

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

```bash
pip install ascii-art
```

With optional integrations:

```bash
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

```python
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:

```python
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](https://github.com/pwaller/pyfiglet) fonts with alignment control.

```python
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.

```python
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.

```python
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:

```python
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

```python
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

```python
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

```python
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

```python
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

```python
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

```python
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

```python
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

```bash
# 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

```bash
# 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](https://github.com/pwaller/pyfiglet) — text rendering
- [Pillow](https://python-pillow.org/) — image conversion
