Metadata-Version: 2.4
Name: experttui
Version: 1.0.0
Summary: Simple, keyboard-driven terminal menus for Python (1D lists & 2D grids).
Author-email: Michał Kowalczyk <maler77@int.pl>
License: MIT License
        
        Copyright (c) 2025 Michał Kowalczyk
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Keywords: tui,terminal,menu,cli,interactive,colorama,readchar,2d-menu,checkbox,selector
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Terminals
Classifier: Environment :: Console
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: colorama>=0.4.6
Requires-Dist: readchar>=4.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=4.0; extra == "dev"
Dynamic: license-file

# ExpertTUI

**Simple, keyboard-driven terminal menus for Python — 1D lists and 2D grids.**

[![PyPI](https://img.shields.io/pypi/v/experttui)](https://pypi.org/project/experttui/)
[![Python](https://img.shields.io/pypi/pyversions/experttui)](https://pypi.org/project/experttui/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

```
╭──────────────────────────────────╮      ╭──────────────────┬──────────────────╮
│  Settings                        │      │  New Game        │                  │
│ ─── Audio / Video ────────────── │      ├──────────────────┼──────────────────┤
│  > [x] Music                     │      │  > Class: < Mage │  Diff:   Normal  │
│    [ ] Fullscreen                │      │    Name: hero... │                  │
│    [x] Sound FX                  │      ├──────────────────┼──────────────────┤
│  ────────────────────────────── │      │  > Start         │    Back          │
│    Save & Exit                   │      ╰──────────────────┴──────────────────╯
╰──────────────────────────────────╯
        menu_1D                                      menu_2D
```

---

## Features

- **Five item types** — action, selector (←→), text input, checkbox, hr separator
- **Two layouts** — vertical `menu_1D` and grid-based `menu_2D`
- **Five border styles** — `single` `double` `rounded` `heavy` `block`
  with correct Unicode junction characters where borders meet separators (├ ┤ ┼ ╬ ┬ ┴ …)
- **Column alignment** — `align=True` keeps 2D columns in sync across all rows
- **Gap fill** — styled column separators (`│ ║ ┃ █`) that connect to borders
- **Inline editing** — cursor jumps to the input field; menu stays visible
- **Live border resize** — `width="auto"` shrinks/grows the border as you type
- **Scroll** — `height=N` shows a window, scrolls with the cursor
- **enter_selector** — require Enter to activate a selector (global or per-item)
- **Full type hints** — explicit keyword-only parameters for IDE autocomplete
- **TypedDicts** — importable item types for dict-key autocomplete

---

## Installation

```bash
pip install experttui
```

**Requirements:** Python ≥ 3.8 · `colorama` · `readchar`

---

## Quick Start

```python
from experttui import menu_1D

menu_1D([
    "Choose an option",
    ("Start game",  lambda: print("Starting!")),
    ("Settings",    lambda: print("Opening settings…")),
    ("Quit",        lambda: quit()),
])
```

---

## Item Types

| Type | Format | Description |
|------|--------|-------------|
| Static label | `"text"` | Non-selectable line |
| Action (tuple) | `("label", fn)` | Calls `fn` on Enter |
| Action (dict) | `{"text": …, "function": fn}` | Same, with extra options |
| Selector | `{"type": "selector", "options": […], "index": 0}` | ←→ cycles values |
| Input | `{"type": "input", "value": "", "placeholder": "…"}` | Enter opens inline editor |
| Checkbox | `{"type": "checkbox", "checked": False}` | Enter toggles |
| Separator | `{"type": "hr"}` | Horizontal line connecting to border |

### Extra keys per type

**Action dict** — `disabled` (bool), `color_selected` (str), `prefix` (str), `suffix` (str)

**Selector** — `color_selected`, `color_options`, `enter` (bool — per-item `enter_selector`)

**Input** — `color_selected`

**Checkbox** — `disabled`, `color_selected`

**Hr** — `fill` (border style name), `label` (centred text)

### Importing TypedDicts for autocomplete

```python
from experttui import SelectorItem, InputItem, CheckboxItem, HrItem

quality: SelectorItem = {
    "type": "selector",
    "text": "Quality",
    "options": ["Low", "Medium", "High"],
    "index": 1,
}
```

---

## menu_1D — Full Reference

```python
from experttui import menu_1D

menu_1D(
    items,                           # list — see Item Types above
    *,
    color               = "YELLOW",  # colorama colour name
    selection_type      = "left_arrow",  # "left_arrow" | "two_arrows"
    moving              = "both",    # "both" | "arrows" | "wsad"
    border              = False,     # False | True/"double" | "single" |
                                     # "rounded" | "heavy" | "block"
    wait_after_function = False,     # pause after action before redrawing
    return_after_action = False,     # exit menu after action (skip redraw)
    enter_selector      = False,     # require Enter to activate selector edit mode
    width               = "auto",   # "auto" (live resize) | int (fixed cols)
    height              = "auto",   # "auto" | int (scrollable window)
    margin              = 0,         # space outside border, all sides
    margin_top          = None,      # per-side override
    margin_right        = None,
    margin_bottom       = None,
    margin_left         = None,
    padding             = 0,         # space inside border, all sides
    padding_top         = None,
    padding_right       = None,
    padding_bottom      = None,
    padding_left        = None,
)
```

### Keyboard reference

| Item | Up / Down | Left / Right | Enter | ESC |
|------|-----------|--------------|-------|-----|
| Navigate | ↑↓ / WS | — | — | Exit |
| Action | | | Run function | |
| Selector | | Cycle value | Activate (if `enter_selector`) | |
| Input | | | Open inline editor | Exit editor |
| Checkbox | | | Toggle | |

When `enter_selector` is active for a selector: Enter opens edit mode,
←→/AD change value, Enter confirms, ESC restores the original value.

---

## menu_2D — Full Reference

All `menu_1D` parameters, plus:

```python
menu_2D(
    items,       # list of rows — each row is a list or a single item
    *,
    # … all menu_1D params …
    align    = True,   # align every column to the max width of that column
    gap      = 2,      # columns of space between cells
    gap_fill = False,  # False | border-style name — vertical char in the gap
)
```

Row structure:

```python
menu_2D([
    "Full-width header",               # single item → spans entire row
    {"type": "hr", "label": "Setup"},  # full-width separator
    [selector_a, selector_b],          # two columns
    [input_field],                     # one column (full width)
    [("OK", fn), ("Cancel", fn2)],     # two action buttons
])
```

### Keyboard reference (2D)

| Action | Key |
|--------|-----|
| Move between rows | ↑↓ / WS |
| Move between columns | ←→ / AD |
| Cycle single-col selector | ←→ / AD |
| Activate selector (`enter_selector`) | Enter |

---

## Border Styles

```
single    rounded   double    heavy     block
┌──────┐  ╭──────╮  ╔══════╗  ┏━━━━━━┓  ██████
│ item │  │ item │  ║ item ║  ┃ item ┃  █ item █
└──────┘  ╰──────╯  ╚══════╝  ┗━━━━━━┛  ██████
```

Junction characters are inserted automatically when `border` + `hr` or
`border` + `gap_fill` are both set:

```
┌──────────────┬──────────────┐   ← ┬ where gap meets top border
│ Class: Mage  │ Diff: Normal │
├──────────────┼──────────────┤   ← ┼ where gap meets hr
│ Start        │ Back         │
└──────────────┴──────────────┘   ← ┴ where gap meets bottom border
```

---

## Examples

### Settings menu with checkboxes

```python
from experttui import menu_1D

quality  = {"type": "selector",  "text": "Quality",
            "options": ["Low", "Medium", "High"], "index": 1}
username = {"type": "input",     "text": "Username",
            "value": "", "placeholder": "enter name…"}
music    = {"type": "checkbox",  "text": "Music",    "checked": True}
sfx      = {"type": "checkbox",  "text": "Sound FX", "checked": True}

menu_1D([
    "Settings",
    {"type": "hr", "fill": "single"},
    quality, username,
    {"type": "hr", "fill": "single", "label": "Audio"},
    music, sfx,
    {"type": "hr"},
    ("Save & Exit", lambda: print("Saved!")),
    {"text": "Locked option", "disabled": True},
],
    color="cyan", border="rounded", padding=1, margin_left=2,
    wait_after_function=True, return_after_action=True, width=32,
)
```

### Character select (2D grid)

```python
from experttui import menu_2D

char_class = {"type": "selector", "text": "Class",
              "options": ["Mage", "Warrior", "Rogue"], "index": 0}
difficulty = {"type": "selector", "text": "Diff",
              "options": ["Easy", "Normal", "Hard"], "index": 1,
              "enter": True}   # this one needs Enter to activate
char_name  = {"type": "input",   "text": "Name",
              "value": "", "placeholder": "hero…"}

def start():
    print(f"Class={char_class['options'][char_class['index']]}, "
          f"Diff={difficulty['options'][difficulty['index']]}, "
          f"Name={char_name['value']}")

menu_2D([
    "New Game",
    {"type": "hr"},
    [char_class, difficulty],
    [char_name],
    {"type": "hr"},
    [("Start", start), ("Back", lambda: None)],
],
    color="green", border="single", padding=1,
    gap=3, gap_fill="single", align=True,
    wait_after_function=True,
)
```

---

## Utilities

```python
from experttui import clear_screen, hide_cursor, show_cursor

clear_screen()   # clear the entire terminal
hide_cursor()    # hide blinking cursor
show_cursor()    # restore cursor
```

---

## Contributing

1. Fork → feature branch → PR
2. Run `pytest` before submitting
3. Follow existing code style (type hints, `_` prefix for private functions)

---

## License

MIT — see [LICENSE](LICENSE).

---
---

# ExpertTUI — Dokumentacja (PL)

**Proste, klawiaturowe menu terminalowe dla Pythona — listy 1D i siatki 2D.**

---

## Instalacja

```bash
pip install experttui
```

**Wymagania:** Python ≥ 3.8 · `colorama` · `readchar`

---

## Szybki start

```python
from experttui import menu_1D

menu_1D([
    "Wybierz opcję",
    ("Nowa gra",   lambda: print("Start!")),
    ("Ustawienia", lambda: print("Otwieranie…")),
    ("Wyjście",    lambda: quit()),
])
```

---

## Typy elementów

| Typ | Format | Opis |
|-----|--------|------|
| Etykieta | `"tekst"` | Nieaktywna linia tekstowa |
| Akcja (tupla) | `("etykieta", fn)` | Wywołuje `fn` po Enter |
| Akcja (słownik) | `{"text": …, "function": fn}` | To samo, z dodatkowymi opcjami |
| Selektor | `{"type": "selector", "options": […], "index": 0}` | ←→ zmienia wartość |
| Input | `{"type": "input", "value": "", "placeholder": "…"}` | Enter otwiera edytor |
| Checkbox | `{"type": "checkbox", "checked": False}` | Enter przełącza |
| Separator | `{"type": "hr"}` | Pozioma linia łącząca się z ramką |

---

## menu_1D — Parametry

```python
menu_1D(
    items,
    *,
    color               = "YELLOW",   # kolor zaznaczenia (nazwa colorama)
    selection_type      = "left_arrow",# "left_arrow" | "two_arrows"
    moving              = "both",     # "both" | "arrows" | "wsad"
    border              = False,      # False | "single"|"double"|"rounded"|"heavy"|"block"
    wait_after_function = False,      # czekaj na klawisz po akcji
    return_after_action = False,      # wyjdź z menu po akcji
    enter_selector      = False,      # Enter wymagany do edycji selectora
    width               = "auto",    # "auto" | int
    height              = "auto",    # "auto" | int (scroll)
    margin              = 0,          # margines zewnętrzny (wszystkie strony)
    margin_top/right/bottom/left = None,
    padding             = 0,          # padding wewnętrzny (wszystkie strony)
    padding_top/right/bottom/left = None,
)
```

---

## menu_2D — Dodatkowe parametry

```python
menu_2D(
    items,
    *,
    # … wszystkie parametry menu_1D …
    align    = True,   # wyrównaj kolumny do tej samej szerokości
    gap      = 2,      # odstęp między kolumnami (liczba znaków)
    gap_fill = False,  # False | nazwa stylu ramki — pionowy znak w odstępie
)
```

Struktura `items`:

```python
menu_2D([
    "Nagłówek pełnej szerokości",
    {"type": "hr", "label": "Opcje"},
    [selektor_a, selektor_b],
    [pole_input],
    [("OK", fn), ("Anuluj", fn2)],
])
```

---

## Style ramki

```
single    rounded   double    heavy     block
┌──────┐  ╭──────╮  ╔══════╗  ┏━━━━━━┓  ██████
│ item │  │ item │  ║ item ║  ┃ item ┃  █ item █
└──────┘  ╰──────╯  ╚══════╝  ┗━━━━━━┛  ██████
```

---

## Klawisze

| Akcja | Klawisz |
|-------|---------|
| Góra / dół | ↑↓ lub WS |
| Lewo / prawo (2D, wiele kolumn) | ←→ lub AD |
| Zmiana selectora (1 kolumna) | ←→ lub AD |
| Aktywacja selectora (`enter_selector`) | Enter → ←→ zmieniają wartość → Enter/ESC |
| Otwarcie / potwierdzenie inputu | Enter |
| Anulowanie inputu | ESC |
| Wyjście z menu | ESC |

---

## Licencja

MIT — patrz [LICENSE](LICENSE).
