diff --git a/.cursor/skills/taskwal-project-docs/SKILL.md b/.cursor/skills/taskwal-project-docs/SKILL.md new file mode 100644 index 0000000..5bd641e --- /dev/null +++ b/.cursor/skills/taskwal-project-docs/SKILL.md @@ -0,0 +1,40 @@ +--- +name: taskwal-project-docs +description: Maintains TaskWAL user-facing documentation in English and Turkish and TUI screenshots when the CLI, board, or on-disk layout changes. Use when editing src/, adding or changing tw subcommands or TUI behavior, updating README or docs, or when the user asks to sync or refresh project documentation. +--- + +# TaskWAL project documentation + +## Files to keep aligned + +| Asset | Role | +| ----- | ---- | +| [README.md](../../../README.md) | Short overview, quick reference, links to full guides | +| [docs/USAGE.md](../../../docs/USAGE.md) | Full English user guide | +| [docs/KULLANIM.md](../../../docs/KULLANIM.md) | Full Turkish user guide (mirror of USAGE) | +| [docs/images/](../../../docs/images/) | `board.png`, `stats.png` for README and guides | + +## When to update + +1. **CLI change** (`src/main.rs`, `src/commands.rs`): reflect new/changed subcommands, flags, or id rules in README (table or examples), then **both** USAGE and KULLANIM. +2. **TUI change** (`src/ui/`): update keyboard tables, command-line (`:`) behavior, and **refresh screenshots** if the visible layout or colors change materially. +3. **Data paths / env**: keep README, USAGE, and KULLANIM consistent (`TASKWAL_DIR`, WAL path). +4. **Analytics text** (`tw stats` output vs stats screen): keep USAGE/KULLANIM descriptions in sync with `src/` and [src/ui/stats.rs](../../../src/ui/stats.rs). + +## Screenshots + +- Regenerate stylized PNGs after meaningful UI changes: + + ```bash + pip install --target .docgen_pillow pillow # once; .docgen_pillow is gitignored + PYTHONPATH=.docgen_pillow python3 scripts/generate_doc_screenshots.py + ``` + +- Commit updated files under `docs/images/`. The script draws an approximation of the TUI; replace with real terminal captures if you need pixel-perfect fidelity. + +## Checklist + +- [ ] README links to USAGE and KULLANIM +- [ ] English and Turkish guides describe the same commands and keys +- [ ] Image paths in markdown use `images/...` from `docs/*.md` and `docs/images/...` from README root +- [ ] No drive-by edits to unrelated markdown diff --git a/.gitignore b/.gitignore index ecbd5bb..449d372 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target **/*.rs.bk .DS_Store +.docgen_pillow/ diff --git a/README.md b/README.md index cdc95c3..f555f43 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Local-first task tracker using an append-only JSONL write-ahead log (`~/.taskwal/wal.log` on Unix, `%USERPROFILE%\.taskwal\wal.log` on Windows). +![TaskWAL board (TUI)](docs/images/board.png) + ## Build Requires [Rust](https://rustup.rs/) 1.70+. @@ -13,33 +15,58 @@ cargo build --release ## Cross-platform -- **macOS / Linux / Windows**: the same codebase; `crossterm` + `ratatui` work on common terminals. +- **macOS / Linux / Windows:** same codebase; `crossterm` + `ratatui` work on common terminals. - Build on each OS you ship for, or use cross-compilation (e.g. `cargo build --release --target x86_64-pc-windows-gnu` from a configured toolchain). -## Usage +## Documentation + +- **English (full guide):** [docs/USAGE.md](docs/USAGE.md) +- **Türkçe (tam kılavuz):** [docs/KULLANIM.md](docs/KULLANIM.md) -Türkçe ayrıntılı kılavuz: [docs/KULLANIM.md](docs/KULLANIM.md). +## Usage (quick reference) ```bash tw add "Write API" --tag backend -tw start 01HX… # prefix match if unique +tw start 01HX… # prefix match if unique tw done 01HX… +tw back 01HX… # one step back: Done→Doing or Doing→Todo +tw edit 01HX… "New title" +tw note 01HX… "Blocked on API" +tw rm 01HX… + tw ls # Todo/Doing: all open tasks; Done: today (local) by default tw ls --all # Done column: all completed tasks tw ls --date 2026-04-01 -tw stats -tw board + +tw board # interactive Kanban TUI (same view flags as ls) +tw stats # aggregate stats (all-time), text output tw log # raw WAL JSON lines ``` +### Commands + +| Command | Purpose | +|--------|---------| +| `add ` | New task (Todo); `--tag` / `-t` comma-separated tags | +| `start <id>` | Move to Doing | +| `done <id>` | Move to Done | +| `back <id>` | Move one column backward | +| `edit <id> <title>` | Rename task | +| `note <id> <text>` | Append a note | +| `rm <id>` | Remove task (append-only delete event in WAL) | +| `ls` | Print board columns for the current view (`--all`, `--date`) | +| `board` | Full-screen TUI board (`--all`, `--date`) | +| `stats` | Print statistics | +| `log` | Dump WAL as JSON lines | + ### Daily view rules -- **Todo / Doing:** every open task is listed (carry-over across days; nothing unfinished disappears from the default view). +- **Todo / Doing:** every open task is listed (carry-over across days). - **Done:** by default, tasks completed on **today’s local calendar date**. Use `--all` or `--date` to widen. ## Environment -- **`TASKWAL_DIR`**: override the data directory (used by tests and for custom locations). WAL file: `$TASKWAL_DIR/wal.log`. +- **`TASKWAL_DIR`:** override the data directory (used by tests and for custom locations). WAL file: `$TASKWAL_DIR/wal.log`. ## License diff --git a/docs/KULLANIM.md b/docs/KULLANIM.md index c17d55a..a5bcf21 100644 --- a/docs/KULLANIM.md +++ b/docs/KULLANIM.md @@ -2,6 +2,8 @@ Bu belge, projenin **mevcut sürümü** için komut satırı ve TUI kullanımını anlatır. +İngilizce aynı seviyede kılavuz: [USAGE.md](USAGE.md). + ## Uygulama nedir? TaskWAL, görevlerinizi **yerel bilgisayarınızda** tutan bir iş takip aracıdır. Tüm değişiklikler, silme dahil, **append-only** bir günlük dosyasına (WAL) yazılır; uygulama bu dosyayı okuyup güncel pano (Todo / Doing / Done) durumunu **yeniden oynatarak** (replay) üretir. @@ -17,7 +19,7 @@ TaskWAL, görevlerinizi **yerel bilgisayarınızda** tutan bir iş takip aracıd Özel konum için ortam değişkeni: -- `**TASKWAL_DIR`**: Veri klasörü. WAL yolu: `$TASKWAL_DIR/wal.log` (Windows’ta `%TASKWAL_DIR%\wal.log`). +- **`TASKWAL_DIR`**: Veri klasörü. WAL yolu: `$TASKWAL_DIR/wal.log` (Windows’ta `%TASKWAL_DIR%\wal.log`). ## Kurulum ve `tw` komutu @@ -51,8 +53,8 @@ tw <komut> --help **Done** kolonu: - **Varsayılan:** Yerel saat diliminde **seçilen takvim gününde** tamamlanan görevler. Seçim belirtilmezse gün = **bugün**. -- `**--all`:** Tamamlanan **tüm** görevler (geçmiş dahil); Todo/Doing yine tüm açık işlerdir. -- `**--date YYYY-MM-DD`:** Done kolonu yalnızca o yerel güne düşen tamamlamalara göre süzülür. +- **`--all`:** Tamamlanan **tüm** görevler (geçmiş dahil); Todo/Doing yine tüm açık işlerdir. +- **`--date YYYY-MM-DD`:** Done kolonu yalnızca o yerel güne düşen tamamlamalara göre süzülür. `--all` ile `--date` **birlikte kullanılamaz.** @@ -69,7 +71,7 @@ tw add "API taslağını yaz" tw add "Review" --tag backend,urgent ``` -- `**--tag` / `-t`:** Virgülle ayrılmış etiket listesi. +- **`--tag` / `-t`:** Virgülle ayrılmış etiket listesi. ### `tw start <id>` @@ -79,6 +81,10 @@ Görevi **Doing** kolonuna taşır. İlk kez Doing’e geçişte “başlangıç Görevi **Done** kolonuna taşır; tamamlanma zamanı kaydedilir. +### `tw back <id>` + +Görevi **bir kolon geri** alır: Done → Doing → Todo (uygun olduğunda). + ### `tw edit <id> <yeni başlık>` Başlığı günceller. @@ -115,6 +121,10 @@ tw board --all tw board --date 2026-04-01 ``` +![Board TUI](images/board.png) + +**Seçili kolon** kenarlığı vurgulanır. **Seçili satır** açık ve koyu temalarda okunaklı görünsün diye **turuncu** arka plan ve kalın yazı ile gösterilir. + **Klavye (board ekranı):** @@ -124,10 +134,14 @@ tw board --date 2026-04-01 | `↑` / `↓` | Seçili kolonda satır | | `s` | Seçili görevi Doing’e al | | `d` | Seçili görevi Done’a al | +| `b` | Seçili görevi bir kolon geri al (Done→Doing→Todo) | | `a` | Done kolonu: bugünün tamamlananları ↔ tüm tamamlananlar arasında geçiş | | `g` | İstatistik ekranına geç | | `q` | Çıkış | +| `:` | Komut satırı (aşağıya bakın) | +| `Esc` | Komut satırında iptal | +**Komut satırı (`:`):** Örneğin `add Yeni görev` veya `start 01ABC123` yazın (`tw` öneki isteğe bağlı). **Enter** ile çalıştırın, **Esc** ile iptal. **İstatistik ekranı:** @@ -149,7 +163,11 @@ Yeni görev **CLI** ile eklenir: `tw add "…"`. - Ortalama **lead** süresi (gün): oluşturma → tamamlanma - Aktif gün başına düşen ortalama tamamlanan iş - Yerel günlere göre **streak** (ardışık günler) -- Son günlerin kısa dökümü +- Son günlerin kısa dökümü + +`tw board` içindeki tam ekran istatistik görünümü: + +![İstatistik ekranı](images/stats.png) ### `tw log` diff --git a/docs/USAGE.md b/docs/USAGE.md new file mode 100644 index 0000000..a6a07ee --- /dev/null +++ b/docs/USAGE.md @@ -0,0 +1,196 @@ +# TaskWAL (`tw`) — User guide + +This document describes the current CLI and TUI for this project. + +## What is TaskWAL? + +TaskWAL is a **local-first** task tracker. Every change, including deletes, is appended to a **write-ahead log** (WAL) file. The app **replays** that log to build the current board (Todo / Doing / Done). + +## Data location + +| Platform | Default directory | WAL file | +| ----------- | ------------------------ | --------- | +| macOS/Linux | `~/.taskwal/` | `wal.log` | +| Windows | `%USERPROFILE%\.taskwal\` | `wal.log` | + +Override with environment variable: + +- **`TASKWAL_DIR`:** data directory. WAL path: `$TASKWAL_DIR/wal.log` (on Windows, `%TASKWAL_DIR%\wal.log`). + +## Install and the `tw` command + +After building the project: + +```bash +cargo install --path /path/to/taskwal --force +``` + +This usually installs `tw` to `~/.cargo/bin/tw` (Windows: `%USERPROFILE%\.cargo\bin\tw.exe`). If `cargo` is not on your PATH: + +```bash +. "$HOME/.cargo/env" # macOS/Linux +``` + +Re-run `cargo install --path ... --force` after updates. + +Help: + +```bash +tw --help +tw <command> --help +``` + +--- + +## Daily view rules (`ls` and `board`) + +**Todo** and **Doing:** list **all** incomplete tasks, regardless of creation day. Open work carries over to the next day. + +**Done** column: + +- **Default:** tasks completed on the selected **local calendar day**. If you do not pass a date, that day is **today**. +- **`--all`:** all completed tasks (history included); Todo/Doing still show all open work. +- **`--date YYYY-MM-DD`:** Done column filtered to completions on that local day. + +`--all` and **`--date`** cannot be used together. + +--- + +## Commands + +### `tw add <title>` + +Creates a task (Todo by default). Creation day is the current local date. + +```bash +tw add "Draft API" +tw add "Review" --tag backend,urgent +``` + +- **`--tag` / `-t`:** comma-separated tags. + +### `tw start <id>` + +Moves the task to **Doing**. The first move to Doing records a **start** time. + +### `tw done <id>` + +Moves the task to **Done** and records completion time. + +### `tw back <id>` + +Moves one step backward: **Done → Doing → Todo** (when allowed). + +### `tw edit <id> <new title>` + +Renames the task. + +### `tw note <id> <text>` + +Appends a note (previous notes are kept). + +### `tw rm <id>` + +Removes the task from the board (a delete event is appended to the WAL). + +### Task id (`id`) + +Full ULID or a **unique prefix** (e.g. first 8 characters). Ambiguous or missing matches are errors. An empty prefix is not allowed. + +### `tw ls` + +Text view of Todo / Doing / Done for the current view. + +```bash +tw ls +tw ls --all +tw ls --date 2026-04-01 +``` + +### `tw board` + +Full-screen **Kanban** TUI (Ratatui). Same view options as `ls`: + +```bash +tw board +tw board --all +tw board --date 2026-04-01 +``` + +![Board TUI](images/board.png) + +The **focused column** highlights its border. The **selected row** uses an **orange** background with bold text so the cursor stays visible on light and dark terminal themes. + +**Board keys:** + +| Key | Action | +| --------- | ------ | +| `Tab` | Next column (Todo → Doing → Done) | +| `↑` / `↓` | Move selection in the current column | +| `s` | Move selected task to Doing | +| `d` | Move selected task to Done | +| `b` | Move selected task one column back | +| `a` | Toggle Done column: today vs all completed | +| `g` | Open stats screen | +| `q` | Quit | +| `:` | Command line (see below) | +| `Esc` | Cancel command line | + +**Command line (`:`):** type a line such as `add My task` or `start 01ABC123` (optional `tw` prefix). Press **Enter** to run, **Esc** to cancel. + +**Stats screen:** + +| Key | Action | +| ---------- | ------------- | +| `g`, `Esc` | Back to board | +| `q` | Quit app | + +New tasks can also be added from the shell with `tw add "…"`. + +### `tw stats` (text output) + +Prints **all-time** aggregates from completed tasks: + +- Total completed count +- Average **cycle** time (days): first start or creation → completion +- Average **lead** time (days): creation → completion +- Average completed tasks per **active** day +- Local **streak** (consecutive days) +- Short recent-day breakdown + +The full-screen stats view inside `tw board` looks like this: + +![Stats screen](images/stats.png) + +### `tw log` + +Prints raw WAL lines as JSON (backup or debugging). + +--- + +## Example session + +```bash +tw add "Morning standup" +tw add "PR review" --tag code + +tw ls +tw start 01ABC123 +tw done 01ABC123 + +tw stats +tw board +``` + +--- + +## Windows notes + +- **Build:** `cargo build --release` produces `target\release\tw.exe` for distribution. +- **Terminal:** Windows Terminal or another modern console is recommended; the TUI works in most environments. + +--- + +## License + +As stated in `Cargo.toml` (e.g. MIT OR Apache-2.0). diff --git a/docs/images/board.png b/docs/images/board.png new file mode 100644 index 0000000..adf7190 Binary files /dev/null and b/docs/images/board.png differ diff --git a/docs/images/stats.png b/docs/images/stats.png new file mode 100644 index 0000000..893e3d1 Binary files /dev/null and b/docs/images/stats.png differ diff --git a/scripts/generate_doc_screenshots.py b/scripts/generate_doc_screenshots.py new file mode 100644 index 0000000..a0ee03d --- /dev/null +++ b/scripts/generate_doc_screenshots.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 +"""Generate stylized PNG screenshots under docs/images/ for README and guides. + +Requires Pillow: pip install pillow + (or: pip install --target .docgen_pillow pillow && PYTHONPATH=.docgen_pillow python3 ...) + +This renders a visual approximation of the TUI, not a live terminal capture. +""" + +from __future__ import annotations + +import os +from pathlib import Path + +try: + from PIL import Image, ImageDraw, ImageFont +except ImportError as e: + raise SystemExit( + "Pillow is required: pip install pillow\n" + " or: pip install --target .docgen_pillow pillow && PYTHONPATH=.docgen_pillow python3 scripts/generate_doc_screenshots.py" + ) from e + +ROOT = Path(__file__).resolve().parents[1] +OUT = ROOT / "docs" / "images" + +BG = (12, 12, 12) +FG = (230, 230, 230) +CYAN = (0, 200, 220) +YELLOW = (220, 220, 100) +BLUE = (120, 160, 255) +GREEN = (120, 220, 160) +GRAY = (100, 100, 100) +ORANGE = (255, 165, 0) +BLACK = (0, 0, 0) + + +def _font(size: int) -> ImageFont.FreeTypeFont | ImageFont.ImageFont: + for path in ( + "/System/Library/Fonts/Supplemental/Courier New.ttf", + "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", + "/usr/share/fonts/TTF/DejaVuSansMono.ttf", + ): + if os.path.isfile(path): + return ImageFont.truetype(path, size) + return ImageFont.load_default() + + +def draw_board(path: Path) -> None: + w, h = 880, 520 + im = Image.new("RGB", (w, h), BG) + dr = ImageDraw.Draw(im) + mono = _font(14) + small = _font(12) + + today = "2026-04-20" + header = f" TaskWAL — today {today} | Done: {today} (local) " + dr.rectangle([4, 4, w - 5, 28], outline=CYAN, width=1) + dr.text((10, 8), header, fill=CYAN, font=mono) + + col_w = (w - 24) // 3 + y0 = 36 + col_h = h - y0 - 120 + titles = [("TODO", YELLOW, 2), ("DOING", BLUE, 1), ("DONE", GREEN, 1)] + rows_todo = [ + (" o [01ABC123] Write API docs", False), + (" o [01DEF456] Review PR", True), + ] + rows_doing = [(" * [01GHI789] Integrate auth", False)] + rows_done = [(" x [01JKL012] Initial scaffold", False)] + + def col_block( + x: int, + title: str, + border: tuple[int, int, int], + rows: list[tuple[str, bool]], + selected: bool, + ) -> None: + dr.rectangle([x, y0, x + col_w - 4, y0 + col_h], outline=border, width=2 if selected else 1) + dr.text((x + 8, y0 + 4), f" {title} ({len(rows)}) ", fill=border, font=small) + yy = y0 + 28 + for line, is_sel in rows: + if is_sel: + bbox = dr.textbbox((x + 10, yy), line, font=mono) + dr.rectangle([bbox[0] - 2, bbox[1] - 1, bbox[2] + 2, bbox[3] + 1], fill=ORANGE) + dr.text((x + 10, yy), line, fill=BLACK, font=mono) + else: + dr.text((x + 10, yy), line, fill=FG, font=mono) + yy += 20 + + col_block(8, "TODO", titles[0][1], rows_todo, True) + col_block(8 + col_w, "DOING", titles[1][1], rows_doing, False) + col_block(8 + 2 * col_w, "DONE", titles[2][1], rows_done, False) + + fy = y0 + col_h + 8 + dr.rectangle([4, fy, w - 5, fy + 32], outline=GRAY, width=1) + dr.text((10, fy + 8), "> ", fill=GRAY, font=mono) + dr.text((10, fy + 52), " command (press :) ", fill=GRAY, font=small) + hint = " s start | d done | b back | a Done view | Tab | g stats | q | : command | Esc " + dr.text((10, h - 28), hint, fill=GRAY, font=small) + + im.save(path, "PNG") + + +def draw_stats(path: Path) -> None: + w, h = 640, 480 + im = Image.new("RGB", (w, h), BG) + dr = ImageDraw.Draw(im) + mono = _font(15) + small = _font(13) + + title = " Stats (all-time) | g / Esc back | q quit " + dr.rectangle([4, 4, w - 5, 28], outline=CYAN, width=1) + dr.text((10, 8), title, fill=CYAN, font=small) + + body = """ + Total completed : 42 + + Avg cycle time : 2.3 d + + Avg lead time : 4.1 d + + Avg per active day: 3.2 tasks + + Streak (local) : 5 d + + Recent days: + 2026-04-20 -> 4 done + 2026-04-19 -> 2 done + 2026-04-18 -> 5 done +""".strip( + "\n" + ) + y = 44 + for line in body.split("\n"): + dr.text((8, y), line, fill=FG, font=mono) + y += 22 + + im.save(path, "PNG") + + +def main() -> None: + OUT.mkdir(parents=True, exist_ok=True) + draw_board(OUT / "board.png") + draw_stats(OUT / "stats.png") + print(f"Wrote {OUT / 'board.png'}") + print(f"Wrote {OUT / 'stats.png'}") + + +if __name__ == "__main__": + main()