Metadata-Version: 2.4
Name: ttytype
Version: 0.1.0
Summary: A keyboard-first terminal typing test built with Textual
Keywords: terminal,typing,tui,textual
Author: Jake Van Slyke
Author-email: Jake Van Slyke <jakervanslyke@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Games/Entertainment
Classifier: Topic :: Terminals
Requires-Dist: platformdirs>=4.11.2
Requires-Dist: rich>=15.0.0
Requires-Dist: textual>=8.2.8
Requires-Python: >=3.14
Project-URL: Homepage, https://github.com/jakeryderv/ttytype
Project-URL: Repository, https://github.com/jakeryderv/ttytype
Project-URL: Issues, https://github.com/jakeryderv/ttytype/issues
Project-URL: Changelog, https://github.com/jakeryderv/ttytype/blob/main/CHANGELOG.md
Description-Content-Type: text/markdown

# ttytype

[![CI](https://github.com/jakeryderv/ttytype/actions/workflows/ci.yml/badge.svg)](https://github.com/jakeryderv/ttytype/actions/workflows/ci.yml)
[![Python 3.14](https://img.shields.io/badge/Python-3.14-3776AB.svg)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

A keyboard-first terminal typing test built with
[Textual](https://textual.textualize.io/). It supports word-count, timed,
public-domain quote, and private custom-text tests without accounts, telemetry,
or network access.

![ttytype Home screen](docs/screenshots/home.svg)

## Features

- Live raw and net WPM, accuracy, time, progress, and error feedback.
- Word, timed, quote, and custom-text modes.
- Dark and light variants with redundant non-color character-state cues.
- Responsive layouts and a guarded small-terminal fallback.
- Optional local SQLite history, recent results, and personal bests.
- Linux, macOS, and Windows support through Textual and Platformdirs.

## Installation

ttytype requires Python 3.14 or newer. PyPI publication is deferred for the
initial release; install the tagged source with either tool:

```bash
uv tool install "ttytype @ git+https://github.com/jakeryderv/ttytype.git@v0.1.0"
# or
pipx install "ttytype @ git+https://github.com/jakeryderv/ttytype.git@v0.1.0"
```

Run the installed command:

```bash
ttytype
# Equivalent module entry point:
python -m ttytype
```

For a source checkout:

```bash
git clone https://github.com/jakeryderv/ttytype.git
cd ttytype
uv sync --locked
uv run ttytype
```

## Controls

| Context | Key | Action |
| --- | --- | --- |
| Everywhere | Ctrl+Q | Quit |
| Everywhere | Ctrl+T | Toggle light/dark theme |
| Home | Tab / Shift+Tab | Move focus |
| Home | Enter | Open a selection or press a button |
| Typing | Printable keys | Type the target text |
| Typing | Backspace | Remove the final typed character |
| Typing | Tab | Retry the exact target |
| Typing | Escape | Return Home |
| Results | R | Retry the exact target |
| Results | N | Generate new text with the same configuration |
| Results | H | Return Home |
| Results | Q | Quit |

![ttytype active typing screen](docs/screenshots/typing.svg)

## Test modes

- **Words:** 10, 25, 50, or 100 lowercase common words.
- **Timed:** 15, 30, 60, or 120 seconds. Timing starts on the first printable
  character and ends from the monotonic clock; input at the exact deadline is
  rejected. More local words are generated before the visible buffer runs out.
- **Quote:** short, medium, or long public-domain excerpts with capitalization,
  punctuation, author, and work attribution preserved.
- **Custom text:** paste or enter plain text in the TUI. Multiline and repeated
  whitespace are normalized to spaces for a single terminal-friendly target.
  File loading is deferred; no custom text is persisted.

## Scoring

- **Raw WPM:** all printable character keystrokes divided into standard
  five-character words per minute.
- **Net WPM:** currently correct target positions divided into five-character
  words per minute.
- **Accuracy:** correct printable keystrokes divided by all printable
  keystrokes. Backspace is excluded, so a corrected mistake still affects
  accuracy.
- **Errors:** incorrect character attempts remain in the total; corrected and
  currently uncorrected errors are reported separately.

Timing starts on the first printable character using a monotonic nanosecond
clock and remains independent from the UI refresh rate.

## Local history and privacy

ttytype is local-only:

- There are no accounts, network requests, synchronization, telemetry, or
  analytics.
- Completed sessions are saved only when **Save completed tests locally** is
  enabled.
- Home can disable future history and permanently clear existing history after
  confirmation.
- History stores score metadata and chart samples. It does **not** store target
  text, typed text, custom text, or individual keystrokes.
- WPM chart samples use compact JSON arrays with the shape
  `[elapsed_ms, raw_wpm, net_wpm, accuracy]`.

The SQLite database is created lazily when the application first accesses local
preferences or history.

### Storage locations

Paths are selected with `platformdirs.user_data_path("ttytype")`:

| Platform | Default database path |
| --- | --- |
| Linux | `$XDG_DATA_HOME/ttytype/ttytype.sqlite3`, normally `~/.local/share/ttytype/ttytype.sqlite3` |
| macOS | `~/Library/Application Support/ttytype/ttytype.sqlite3` |
| Windows | `%LOCALAPPDATA%\ttytype\ttytype\ttytype.sqlite3` |

Environment and operating-system configuration may change these locations.
Mutable preferences and history share this database. ttytype does not currently
write a TOML configuration file. A future configuration directory is reserved
through `platformdirs.user_config_path("ttytype")`.

## Configuration and CLI

Defaults are 25 words, local history enabled, and the dark theme. Home edits
mode-specific word count, duration, quote length, and history behavior. Ctrl+T
changes the stored theme preference. Custom text itself is never persisted.

Configuration precedence, from lowest to highest, is:

1. application defaults;
2. stored SQLite preferences;
3. explicit command-line overrides;
4. choices made in the running TUI, which are persisted for later launches.

```text
ttytype [--words COUNT] [--history | --no-history] [--theme dark|light]
```

`--words` opens Home in word mode at the requested count. History and theme
options override stored preferences for the running application.

## Supported systems and terminals

CI runs the full Python 3.14 quality suite on current Ubuntu, macOS, and Windows
GitHub-hosted runners. ttytype expects an interactive terminal with Unicode and
ANSI color support. True color improves appearance but is not required because
character states also use bold, reverse, underline, and dim styles.

The typing view requires at least 50 columns by 12 rows. Larger terminals receive
narrow, normal, or wide responsive layouts. Common modern terminals such as
Windows Terminal, iTerm2, Terminal.app, GNOME Terminal, Konsole, and Kitty should
work through Textual; terminal-specific rendering differences may remain.

## Textual cutover

The original curses interface and its compatibility modules have been removed.
These differences are intentional:

- ttytype opens on Home rather than immediately starting a test;
- Escape returns Home, while Ctrl+Q quits globally;
- Tab retries the exact target and Results offers separate retry and new-text
  actions;
- scoring uses event-based raw WPM, net WPM, accuracy, and corrected errors;
- `--words` configures Home instead of bypassing it.

## Development

Install the locked development environment:

```bash
uv sync --locked --all-extras --dev
```

Run the complete local quality gate:

```bash
uv run ruff check .
uv run ruff format --check .
uv run mypy src tests
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 uv run pytest
uv build
```

GitHub Actions runs these checks on Linux, macOS, and Windows and uploads wheel
and source-distribution artifacts. Version tags build separate release artifacts;
PyPI publishing is intentionally not configured yet.

## Project policy

Release notes are maintained in [CHANGELOG.md](CHANGELOG.md). A separate
contribution guide is deferred until the project receives external contribution
workflow requirements. Standalone binaries are also deferred; the initial
release is distributed as Python source and wheel artifacts.

## License

Released under the [MIT License](LICENSE).
