Metadata-Version: 2.4
Name: dunders
Version: 0.1.0
Summary: dunders — Norton Commander–style terminal file manager, text editor, and LLM-agent CLI built on Textual.
Project-URL: Homepage, https://github.com/tumikosha/dunders
Project-URL: Repository, https://github.com/tumikosha/dunders
Project-URL: Issues, https://github.com/tumikosha/dunders/issues
Project-URL: Documentation, https://github.com/tumikosha/dunders#readme
Author-email: tumikosha <tumikosha@gmail.com>
License: MIT
License-File: LICENSE
Keywords: editor,file-manager,folding,macros,mc,midnight-commander,norton-commander,terminal,textual,tui
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Environment :: Console :: Curses
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Text Editors
Classifier: Topic :: Utilities
Requires-Python: >=3.12
Requires-Dist: ptyprocess>=0.7.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: textual>=3.0.0
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Description-Content-Type: text/markdown

# dunders

> **T**erminal · **Y**our · **U**niversal · **I**ntelligence

A Norton Commander–style terminal file manager, text editor, and LLM-agent
CLI for the modern shell — built on
[Textual](https://textual.textualize.io/).

The name `dunders` is the four QWERTY keys right after `qwer`y — picked in the
same spirit as vim's `hjkl`. The CLI command is **`dunders`**.

`dunders` brings back the dual-pane workflow of `mc` / Far Manager — but with a
real windowing layer (Turbo Vision–inspired), code folding, recordable
macros, a command palette, and an embedded LLM/agent CLI mode.

> Status: **alpha**. Core file-manager and editor are usable; agent/CLI
> mode is a stub.

## Quick install (any OS — one line)

Installs [`uv`](https://docs.astral.sh/uv/) if you don't have it, then installs
`dunders` (plus the `__` / `__w` launchers) into an isolated environment — no
system Python needed.

**Linux / macOS / WSL** (bash/zsh):

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh && export PATH="$HOME/.local/bin:$PATH" && uv tool install --force git+https://github.com/tumikosha/dunders.git
```

**Windows** (PowerShell):

```powershell
irm https://astral.sh/uv/install.ps1 | iex; $env:Path = "$env:USERPROFILE\.local\bin;$env:Path"; uv tool install --force git+https://github.com/tumikosha/dunders.git
```

Then run `dunders`. (Already have `uv`? Just `uv tool install git+https://github.com/tumikosha/dunders.git`.)

## Features

- **Dual-pane file manager** with sort, multi-select, quick-search, and
  the classic NC F-key bar (F3 view, F4 edit, F5 copy, F6 move, F7 mkdir,
  F8 delete, F9 menu, F10 quit).
- **Embedded text editor** with split view, search & replace, fold-by-indent,
  and bracket/region folding rules.
- **Recordable macros** with persistent storage.
- **Hex viewer** for binary or large files (mmap-backed, switches in
  automatically above 4 MiB).
- **Turbo Vision–style windowing layer** (`dunders.windowing`) — reusable in
  other Textual apps. Tile, cascade, maximize, modal dialogs, command
  palette, themable via YAML.
- **Mouse support** everywhere, including the menu bar and status bar.
- **LLM agent / CLI mode** (in progress) — bring your own model.

## Install

### Zero-Python install via [uv](https://docs.astral.sh/uv/) (recommended)

`uv` is a single static binary. It installs Python for you, then installs
`dunders` into an isolated environment and puts the `dunders` command on your
`PATH`. No system Python required.

```bash
# 1. Install uv (one-liner, no Python needed)
curl -LsSf https://astral.sh/uv/install.sh | sh        # macOS / Linux
# Windows PowerShell:
#   powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# Or via package manager: brew install uv  /  pipx install uv  /  scoop install uv

# 2. Install dunders (uv fetches Python 3.12+ automatically if missing)
uv tool install dunders

# 3. Run
dunders
```

Try it once without installing:

```bash
uvx --from dunders dunders          # downloads, runs in a temp env, then forgets
```

Upgrade / uninstall:

```bash
uv tool upgrade dunders
uv tool uninstall dunders
```

### If you already have Python 3.12+

```bash
pipx install dunders            # preferred — isolated, on $PATH
# or, inside an active venv:
pip install dunders
```

Requires Python 3.12+ in any path above.

## Usage

```bash
dunders                  # two-panel file manager (default)
dunders path/to/dir      # file manager seeded at a directory
dunders path/to/file     # open a file in the editor
dunders --cli            # agent / CLI mode (stub)
```

### Short launchers

Two extra console scripts are installed alongside `dunders`, differing only in
how embedded shell commands hand off the terminal:

| Command | Terminal mode | Platform |
| ------- | ------------- | -------- |
| `__`    | **relay** — persistent relay subshell | Linux / macOS |
| `__w`   | **suspend** — suspend + subprocess, no persistent session | cross-platform (use this on Windows) |

Both take the same arguments (files open in cascaded editor windows; a lone
directory or no args open the mc-style file manager) and accept `--suspend`
explicitly; `__w` is just `__ --suspend`.

Inside the app:

| Key             | Action                              |
| --------------- | ----------------------------------- |
| `F3`            | View file (hex if binary/large)     |
| `F4`            | Edit file                           |
| `F5` / `F6`     | Copy / Move selected items          |
| `F7` / `F8`     | Mkdir / Delete                      |
| `F9` / `F10`    | Menu / Quit                         |
| `Tab`           | Switch panel                        |
| `Shift+Tab`     | Cycle desktop windows               |
| `Alt+L / Alt+R` | Focus left / right panel            |
| `Ctrl+K`        | Command palette                     |

Editor-scoped keys (Save, Find/Replace, Split, Fold, Record macro) appear in
the status bar when an editor window has focus.

## Development

```bash
git clone https://github.com/tumikosha/dunders dunders
cd dunders
uv sync --extra dev          # or: pip install -e '.[dev]'

pytest                       # full suite
pytest -k fold_engine        # by keyword
ruff check
```

The repository ships a standalone windowing demo to exercise the framework
without the file-manager layer:

```bash
python -m dunders.windowing.demo
```

## Project layout

The PyPI distribution is named **`dunders`**; the importable Python package and
the CLI command are both **`dunders`**.

```
dunders/
├── app.py            # DundersApp shell — wires menus, panels, dispatcher
├── main.py           # entry point (argparse)
├── fm/               # file-manager domain (panels, dialogs, file ops)
├── windowing/        # Turbo Vision–style framework on Textual
│   ├── core/         # buffer, fold engine, macros, search
│   ├── editor/       # embeddable editor widget + content
│   ├── themes/       # palette loader + modern_dark default
│   └── demo/         # standalone framework demo
├── themes/           # dark.yaml / light.yaml palettes
└── config/defaults.py
```

See [`CLAUDE.md`](./CLAUDE.md) for an architecture deep-dive aimed at
contributors and AI coding assistants.

## Terminal limitations on macOS

macOS **Terminal.app** does not report several modifier+key combinations to
the application, so some editor shortcuts can't reach `dunders` there:

- `Shift+↑` / `Shift+↓` / `Shift+Home` / `Shift+End` — selection by line / to
  start/end of line. Terminal.app sends the same sequence as the unmodified
  key, so the selection variant never arrives.
- `Cmd+C`, `Cmd+↑` / `Cmd+↓` — the terminal intercepts `Cmd` shortcuts itself
  and never forwards them.

You can confirm what your terminal sends with `cat -v` (press the combo, then
`Ctrl+C` to quit): if `Shift+↑` prints `^[[A` (same as plain `↑`) the modifier
is being dropped.

**Two fixes:**

1. **Use a terminal that supports the kitty keyboard protocol** — iTerm2,
   Ghostty, Kitty, WezTerm. These deliver `Shift+arrows` and `Cmd+arrows`/`Cmd+C`
   out of the box, no configuration needed. (Recommended.)

2. **Remap the keys in Terminal.app** — Settings → Profiles → *your profile* →
   **Keyboard** → **+**, with Action *Send Text* (`\033` is the Esc character):

| Key    | Modifier | Send Text   |
|--------|----------|-------------|
| `↑`    | Shift    | `\033[1;2A` |
| `↓`    | Shift    | `\033[1;2B` |
| `Home` | Shift    | `\033[1;2H` |
| `End`  | Shift    | `\033[1;2F` |

`Cmd+C` can't be remapped this way (Terminal.app keeps it for its own Copy). In
the editor and command line use `Ctrl+C` to copy instead — in the command line
`Ctrl+C` copies the current selection and otherwise cancels/clears, like a
shell.

## License

MIT — see [LICENSE](./LICENSE).
