Metadata-Version: 2.5
Name: pixpop
Version: 0.1.0
Summary: A TUI paint application built with Python and the Textual framework
Project-URL: Repository, https://github.com/umbsublime/pixpop
Author: umbsublime
License: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Graphics :: Editors
Requires-Python: >=3.14
Requires-Dist: pillow>=12.3.0
Requires-Dist: textual-canvas>=1.1.0
Requires-Dist: textual-fspicker>=1.0.1
Requires-Dist: textual>=8.2.8
Description-Content-Type: text/markdown

﻿# Pixpop

![pixpop logo](https://raw.githubusercontent.com/UmBsublime/pixpop/main/screenshots/pixpop_x4.png)

A TUI paint application built with Python 3.14 and the
[Textual](https://textual.textualize.io/) framework.

**[Documentation](https://umbsublime.github.io/pixpop/)**

## Features

- Multiple canvases
- Multiple layers
- Full mouse and keyboard support (drawing is mouse-only)
- Configuration file for application defaults
- Save and export as .ans, .png, and .pix session files
- Open and load .ans, .png, and .pix session files
- Undo-redo stack
- Help screen and tooltips

## Caveats

This application is designed to draw in the terminal, which comes with limitations.
We are able to draw `pixels` (half-characters), but there is no way to know if the mouse is positioned
on the top or bottom pixel. To work around this we have the fine tool.
It allows choosing the top pixel with left-click, the bottom pixel with right-click, and both pixels with middle-click.

## Screenshots

<table>
  <tr>
    <td><img src="https://raw.githubusercontent.com/UmBsublime/pixpop/main/screenshots/app.png" alt="Pixpop main window"></td>
    <td><img src="https://raw.githubusercontent.com/UmBsublime/pixpop/main/screenshots/help.png" alt="Pixpop help dialog"></td>
  </tr>
</table>

## Pixpop session format (.pix)

Pixpop supports saving and loading full sessions as `.pix` files. These are
gzipped JSON files that capture:

- Tabs (canvas names and order)
- Canvas size per tab
- Layers, visibility, and pixel data
- Undo/redo stacks per tab
- Shared tool state and palette selection

The `.pix` format is intended for restoring a working session rather than
exporting artwork. For artwork exports, use PNG or ASCII.



## Setup

```bash
git clone https://github.com/umbsublime/pixpop.git
cd pixpop
uv sync
uv run pixpop
```

## Project structure

```
pixpop/
├── src/pixpop/         # Application package
│   ├── styles/         # Textual CSS
│   ├── screens/        # Modal dialogs
│   ├── state/          # App state, messages, undo/redo
│   ├── tools/          # Drawing tools and registry
│   ├── widgets/        # UI pickers (tool/color/brush/spray/layer)
│   ├── session/        # .pix session save/load
│   └── importers/      # PNG / PIX / ANSI loaders
├── src/assets/         # Palettes and word lists (bundled)
├── tests/              # Snapshot + regression tests
├── screenshots/         # Project logo and screenshots
└── pyproject.toml
```

## Development

### Code quality (Ruff)

```bash
# Lint
uv run ruff check src/

# Auto-fix
uv run ruff check --fix src/

# Format
uv run ruff format src/
```

## Testing

Snapshot tests cover the UI. Run them with:

```bash
uv run pytest
```

Update baselines for intentional UI changes:

```bash
uv run pytest --snapshot-update
```

Always verify changes by running the app:

```bash
uv run pixpop
```

## Powered by

- [textual](https://github.com/Textualize/textual): TUI framework powering the app shell and widgets.
- [textual-canvas](https://github.com/davep/textual-canvas): Pixel canvas widget used for drawing operations.
- [textual-fspicker](https://github.com/davep/textual-fspicker): File picker dialogs for save/load flows.
