Metadata-Version: 2.4
Name: pinyinIME
Version: 0.2.0
Summary: A simple Input Method Engine, inspired by Rime.
Project-URL: bugs, https://github.com/wwj718/pinyinIME/issues
Project-URL: changelog, https://github.com/wwj718/pinyinIME/blob/main/HISTORY.md
Project-URL: documentation, https://wwj718.github.io/pinyinIME/
Project-URL: homepage, https://github.com/wwj718/pinyinIME
Author-email: Wenjie Wu <wuwenjie718@gmail.com>
Maintainer-email: Wenjie Wu <wuwenjie718@gmail.com>
License: MIT
License-File: LICENSE
Classifier: Typing :: Typed
Requires-Python: >=3.10
Provides-Extra: traditional
Requires-Dist: opencc>=1.2.0; extra == 'traditional'
Description-Content-Type: text/markdown

# pinyinIME

> Know how to solve every problem that has been solved.  -- Feynman

A simple Pinyin Input Method Engine, inspired by [Rime](https://rime.im/).

Pure Python implementation, with no dependencies on any third-party libraries.

Under 500 lines of code!

It is the Chinese input method I currently use in my daily life.

* Author: [Wenjie Wu](https://wwj718.github.io)
* PyPI: https://pypi.org/project/pinyinIME/
* Free software: MIT License

## Features

* **Full pinyin & abbreviation** — `nihao` → 你好；`nh` → 你好（声母缩写）
* **Manual syllable separation(configurable)** — `xi'an` → 西安; `ke'neng` → 可能
* **Emoji input** — type Chinese keywords to get emoji candidates
* **Traditional Chinese** — optional simplified → traditional conversion
* **Python API** — embed the engine directly in your own Python app
* **Custom phrases**
* **HTTP server** — local HTTP daemon for integration with native input method frameworks (e.g. macOS IMKit / Swift)
* **Interactive terminal UI** — optional TUI for trying the IME in your terminal (connects to the HTTP server)
  * **User learning** — records your word choices and promotes them in future lookups


## Installation

```bash
pip install pinyinIME
```

Or with [uv](https://github.com/astral-sh/uv):

```bash
uv tool install pinyinIME
```

To enable traditional Chinese output, install with the optional dependency:

```bash
pip install "pinyinIME[traditional]"
```



## Python API

```python
from pinyinIME.engine import PinyinEngine

engine = PinyinEngine()

# Get candidate words (page=0, page_size=9)
engine.query("nihao", 0, 9)
# {
#   "syllables": ["ni", "hao"],
#   "candidates": [{"word": "你好", "syllables": ["ni", "hao"]}, ...],
#   "max_page": 20
# }

# Get candidates with full pinyin and frequency score
engine.lookup("nh")
# [('你好', 'ni hao', 135314), ('那好', 'na hao', 812), ...]

# FMM syllable segmentation
engine.segment("nihao")      # ['ni', 'hao']

# Record a user selection
engine.commit("你好", ["ni", "hao"])
```

## CLI Usage

```bash
# Look up candidates for a pinyin string
pinyinIME lookup nihao
pinyinIME lookup nh           # abbreviation: 声母缩写
pinyinIME lookup "xi'an"      # manual syllable split → 西安

# Open debug playground in browser (requires server running)
uv run --with bottle pinyinIME serve   # start HTTP server first
pinyinIME playground                   # then open playground in browser

# Enable debug logging
pinyinIME --verbose lookup nihao

# Interactive terminal UI (requires bottle + rich; start server first)
uv run --with bottle pinyinIME serve                              # start HTTP server (default 127.0.0.1:12358)

uv run  pinyinIME playground     # open browser playground (recommended) ✨
uv run --with rich pinyinIME interactive     # or use terminal interactive UI
```

## Development

```bash
git clone https://github.com/wwj718/pinyinIME.git
cd pinyinIME

# Install in editable mode (changes take effect immediately)
uv tool install --editable .

# Run tests
uv run pytest

# Full QA (format, lint, type check, test)
just qa
```

### Architecture Overview

```
PinyinEngine
├── index/
│   ├── builder.py   IndexBuilder → (Prism, Table)
│   ├── prism.py     Spelling → [(syllable_id, SpellingType)]
│   └── table.py     Trie: syllable_id[] → DictEntry[] (sorted by score)
├── pipeline/
│   ├── types.py        SpellingType enum, SPELLING_PENALTY constants
│   ├── segmentor.py    FmmStrategy (forward maximum matching, O(n×6))
│   ├── translator.py   Querier: DFS over segments, Prism+Table lookup, timeout protection
│   └── filter.py       Filter Protocol; TraditionalFilter (simp→trad)
├── tools/
│   ├── cli.py          Typer CLI: lookup / interactive / clear-cache commands
│   ├── server.py       HTTP daemon (bottle); exposes query/commit/segment API
│   ├── interactive.py  Interactive terminal UI (HTTP client mode)
│   └── user_history.py UserHistory management CLI
└── engine.py           PinyinEngine: init, lookup(), candidates(), select(), commit()
```

#### Scoring

Candidates are ranked by an adjusted score:

```
adjusted_score = round((log(max(raw_score, 1)) + spelling_penalty) × 1_000_000)
```

Weight multipliers before the log:

| Source | Multiplier |
|--------|-----------|
| User history | 10,000,000 |
| Custom phrases | 1,000,0 * (1-100) |
| Emoji | 1,000 |
| Essay (Rime) base | 1 |

Spelling penalties: `NORMAL` → 0.0, `ABBREVIATION` → log(0.1) ≈ −2.303

## Author

pinyinIME was created in 2026 by [Wenjie Wu](https://wwj718.github.io).

Built with the [cookiecutter-pypackage](https://github.com/audreyfeldroy/cookiecutter-pypackage) project template.

