Metadata-Version: 2.4
Name: relayout
Version: 0.1.0
Summary: Add your description here
License-File: LICENSE
Requires-Python: >=3.14
Description-Content-Type: text/markdown

# relayout

A pure Python library that detects and fixes text typed in the wrong keyboard layout.

```python
import relayout

relayout.fix("ghbdtn")   # → "привет"
relayout.fix("привет")   # → "ghbdtn"
```

No clipboard. No hotkeys. No UI. Just a function that takes a string and returns a string.

## Installation

```sh
pip install relayout
```

## Usage

### `fix(text)` — auto-detect and convert

```python
import relayout

# Typed "привет" but keyboard was in EN layout
relayout.fix("ghbdtn")        # → "привет"

# Typed "hello" but keyboard was in RU layout
relayout.fix("рудди")         # → "hello"

# Neutral text (digits, spaces) is returned unchanged
relayout.fix("hello 123")     # → "hello 123"
```

### `detect(text)` — identify which layout was used

```python
relayout.detect("ghbdtn")     # → "en"
relayout.detect("привет")     # → "ru"
relayout.detect("123 456")    # → None  (inconclusive)
```

### `convert(text, source_id)` — convert without auto-detection

```python
# You know the text is in EN, convert to RU
relayout.convert("ghbdtn", "en")   # → "привет"

# You know the text is in RU, convert to EN
relayout.convert("привет", "ru")   # → "ghbdtn"
```

### List available layouts

```python
relayout.list_layouts()   # → ["en_ru"]
```

## Adding a custom layout

You can register any layout at runtime without modifying the library:

```python
from relayout import LayoutMap, register_layout, fix

ua_ru = LayoutMap.from_parallel_strings(
    id="ua_ru",
    layout_ids=("ua", "ru"),
    chars_a="йцукенгшщзїфівапролджєячсмитьбю",
    chars_b="йцукенгшщзхъфывапролджэячсмитьбю",
)
register_layout(ua_ru)

fix("...", layout_id="ua_ru")
```

## Supported layouts

| ID | Languages |
|---|---|
| `en_ru` | English ↔ Russian (QWERTY / JCUKEN) |

## How it works

1. **Detect** — counts characters exclusive to each layout side. Majority wins. Ties and neutral text return `None`.
2. **Convert** — applies a character-by-character translation using Python's `str.translate()`.

Each layout is defined as a `.toml` file with two parallel strings — one per keyboard side. Adding a new language pair requires only adding a new file.

## Development

```sh
git clone https://github.com/yourusername/relayout
cd relayout
uv sync
uv run pytest
```

## License

AGPL-3.0
