Metadata-Version: 2.4
Name: liannnix-todo-cli
Version: 1.1.0
Summary: CLI tool for managing TODO.md files
Project-URL: Homepage, https://altlinux.space/liannnix/liannnix-todo-cli
Project-URL: Repository, https://altlinux.space/liannnix/liannnix-todo-cli
Project-URL: Issues, https://altlinux.space/liannnix/liannnix-todo-cli/issues
Project-URL: Changelog, https://altlinux.space/liannnix/liannnix-todo-cli/src/branch/main/CHANGELOG.md
Author-email: Andrey Limachko <liannnix@altlinux.org>
License-Expression: GPL-3.0-or-later
License-File: LICENSE
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business
Classifier: Topic :: Text Processing :: Markup :: Markdown
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: rich>=13
Requires-Dist: typer>=0.15
Description-Content-Type: text/markdown

# ltc

CLI-инструмент для управления `TODO.md` файлами прямо из терминала.

`ltc` читает и записывает обычные markdown-файлы с задачами — без базы
данных, без проприетарных форматов, без привязки к редактору. Изменения
применяются точечно через patch-based сериализатор: ваш `TODO.md`
сохраняет комментарии, пустые строки и форматирование нетронутыми.

```text
  $ ltc init
  Created TODO.md

  $ ltc add backend: Реализовать API [!!]
  Created group backend
  Added Реализовать API → backend

  $ ltc add auth Добавить OAuth2 -n "Использовать PKCE flow"
  Added Добавить OAuth2 → auth

  $ ltc done auth
  Done: Добавить OAuth2

  $ ltc
  ## backend
    ✓ backend.1 Реализовать API [!!]

  ## auth
    ✓ auth.1 Добавить OAuth2

  1/2 tasks done
```

---

## Содержание

- [Установка](#установка)
- [Быстрый старт](#быстрый-старт)
- [Формат TODO.md](#формат-todomd)
- [Команды](#команды)
  - [init — создать файл](#init--создать-файл)
  - [ls — список и фильтры](#ls--список-и-фильтры)
  - [add — добавить задачу](#add--добавить-задачу)
  - [done / undone — статус](#done--undone--статус)
  - [edit — редактирование](#edit--редактирование)
  - [rm — удаление](#rm--удаление)
  - [note — описание](#note--описание)
  - [groups / group — управление группами](#groups--group--управление-группами)
- [Reference resolution](#reference-resolution)
- [Приоритеты](#приоритеты)
- [Опции](#опции)
- [Разработка](#разработка)
- [Лицензия](#лицензия)

---

## Установка

### Из исходников (uv)

```bash
git clone https://github.com/liannnix/ltc.git
cd ltc
uv sync
uv run ltc --help
```

### Глобальная установка (pip)

```bash
pip install .
ltc --help
```

> **Требование:** Python ≥ 3.12

---

## Быстрый старт

```bash
ltc init                           # создать TODO.md
ltc Fix баг в парсере              # добавить задачу в Inbox
ltc !! tests: Покрыть тестами      →  группа tests, высокий приоритет
ltc                                # показать список
ltc done 1                         # отметить выполненной
```

---

## Формат TODO.md

`ltc` работает с обычными markdown-файлами. Пример:

```markdown
# TODO

## Backend

- [ ] Реализовать API [!!]
  - [x] Настроить роутинг
  - [ ] Добавить middleware
    Использовать composition pattern
- [ ] Деплой на staging

## Inbox

- [ ] Купить кофе
```

### Элементы формата

| Элемент     | Синтаксис               | Описание                        |
|-------------|-------------------------|---------------------------------|
| Группа      | `## Name`               | Заголовок второго уровня        |
| Задача      | `- [ ] Title`           | Незавершённая                   |
| Выполнена   | `- [x] Title`           | Завершённая                     |
| Подзадача   | `  - [ ] Title`         | Вложенный чекбокс (отступ 2+)   |
| Описание    | `  Текст с отступом`    | Строки ниже задачи без чекбокса |
| Приоритет   | `Title [!!]`            | Маркер в конце строки задачи    |

### Группа Inbox

Задачи без указанной группы попадают в **Inbox**. Inbox всегда отображается
последним при выводе списка. Новые группы вставляются перед Inbox в файле.
Пустой Inbox не отображается.

### Приоритеты

| Маркер | Уровень | Пример                          |
|--------|---------|---------------------------------|
| `[!!]` | Высокий | `- [ ] Срочный баг [!!]`        |
| `[!]`  | Средний | `- [ ] Важно, но не срочно [!]` |
| `[]`   | Низкий  | `- [ ] Когда-нибудь []`         |
| нет    | Обычный | `- [ ] Обычная задача`          |

Приоритет указывается **в конце строки задачи**. Маркер не в конце строки
считается частью названия.

### Подзадачи

Подзадачи обозначаются вложенным чекбоксом с отступом (2+ пробела или таб)
относительно родительской задачи. Уровень вложенности определяется
относительным отступом, а не абсолютным количеством пробелов:

```markdown
- [ ] Родительская задача
  - [ ] Дочерняя задача (отступ 2)
    - [ ] Внучатая задача (отступ 4)
      Deep nested description
```

### Описания

Описание задачи — текст с отступом ниже чекбокса, не являющийся
подзадачей. Описание может быть многострочным и содержать code blocks:

```markdown
- [ ] Реализовать OAuth2
  Использовать PKCE flow
  ```
  const verifier = generateCodeVerifier();
  ```
```

### Passthrough

Строки, не распознанные как элементы TODO (комментарии, произвольный
текст, `H3+` заголовки), сохраняются как есть и не модифицируются при
сериализации.

---

## Команды

### `init` — создать файл

Создаёт пустой `TODO.md` с заголовком и группой Inbox.

```bash
ltc init
```

```text
# TODO

## Inbox
```

С указанием пути:

```bash
ltc init -f ~/projects/myapp/TODO.md
```

---

### `ls` — список и фильтры

Без аргументов — вывод всех задач по группам:

```bash
ltc ls
```

```text
## Backend
  ✓ backend.1 Реализовать API [!!]
    ✓ backend.1.1 Настроить роутинг
    [ ] backend.1.2 Добавить middleware
  [ ] backend.2 Деплой на staging

## Inbox
  [ ] inbox.1 Купить кофе

3/5 tasks done
```

#### Фильтры

Аргументы к `ls` объединяются через AND:

| Фильтр       | Пример             | Действие                          |
|--------------|--------------------|-----------------------------------|
| Группа       | `ltc ls backend`   | Только задачи группы backend      |
| Приоритет    | `ltc ls !!`        | Только высокий приоритет          |
| Приоритет    | `ltc ls !`         | Только средний приоритет          |
| Статус       | `ltc ls done`      | Только завершённые                |
| Статус       | `ltc ls undone`    | Только незавершённые              |
| Подстрока    | `ltc ls auth`      | Title содержит "auth" (ignorecase)|

Комбинирование:

```bash
# Незавершённые задачи с высоким приоритетом в backend
ltc ls backend !! undone

# Все незавершённые задачи, содержащие "api"
ltc ls undone api

# Завершённые подзадачи в группе auth
ltc ls auth done
```

#### Короткая форма

`ltc` без субкоманды и без аргументов — то же, что `ltc ls`:

```bash
ltc                    # = ltc ls
```

---

### `add` — добавить задачу

Команда `add` использует **order-independent** парсинг аргументов:
порядок токенов не важен. Команда сама определяет, что вы хотите —
новую задачу, подзадачу или группу.

#### Базовые примеры

```bash
# Простая задача в Inbox
ltc add Fix баг в парсере

# То же самое через default-команду (без слова add)
ltc Fix баг в парсере

# Задача с высоким приоритетом
ltc add !! Fix критический баг
ltc add Fix критический баг !!          # порядок не важен

# Задача в конкретной группе (группа создаётся автоматически)
ltc add backend: Реализовать API [!!]

# Все токены можно менять местами
ltc add [!!] Реализовать API backend:
ltc add Реализовать API backend: !!
```

#### Группа автоматически создаётся

Если указана группа, которой не существует — она создаётся автоматически:

```bash
ltc add tests: Написать unit-тесты
```

```text
Created group tests
Added Написать unit-тесты → tests
```

#### Подзадачи через ref

Если первый значимый токен резолвится в существующую задачу —
создаётся подзадача:

```bash
# По точному ID
ltc add 1 Добавить валидацию
ltc add backend.1 Обработать ошибки

# По fuzzy-совпадению
ltc add api Добавить rate limiting
# → подзадача к "Реализовать API"

# С приоритетом и описанием
ltc add 1 Важная подзадача !! -n "Не забыть про edge cases"
```

#### С описанием

```bash
ltc add Настроить CI/CD -n "GitHub Actions + Docker"
ltc add auth: Интеграция с Google -n "OAuth2, scope: email profile"
```

#### Создание пустой группы

Если указать только группу без названия задачи:

```bash
ltc add docs:
```

```text
Created group docs
```

---

### `done` / `undone` — статус

Отмечает задачу выполненной или возвращает в pending.
Если у задачи есть подзадачи — они меняют статус вместе с родителем.

```bash
# По индексу
ltc done 1

# По group.index
ltc done backend.2

# По fuzzy
ltc done deploy
ltc done auth

# Возврат в pending
ltc undone 1
ltc undone auth
```

Пример каскадного выполнения:

```text
  $ ltc done backend.1
  Done: Реализовать API
    2 child(ren) also marked done
```

---

### `edit` — редактирование

Изменяет существующую задачу. Ref обязателен. Все остальные параметры
опциональны и применяются частично — только то, что указано.

#### Изменение названия

```bash
ltc edit 1 Новое название
ltc edit backend.1 Refactor API layer
```

#### Изменение приоритета

```bash
ltc edit 1 [!!]
ltc edit auth !!
ltc edit backend.2 []                  # низкий приоритет
```

#### Изменение описания

```bash
ltc edit 1 -n "Новое описание"
ltc edit auth -n "Updated: использовать Keycloak"
```

#### Перемещение между группами

```bash
ltc edit 1 frontend:
ltc edit backend.2 inbox:
```

#### Комбинированное редактирование

```bash
# Название + приоритет + группа + описание — всё сразу
ltc edit 1 Новый заголовок !! frontend: -n "Полное обновление"

# То же самое в другом порядке токенов
ltc edit 1 frontend: !! Новый заголовок -n "Полное обновление"
```

#### Только описание (без названия)

```bash
ltc edit 1 -n "Только меняю описание, title не трогаю"
```

---

### `rm` — удаление

Удаляет задачу и все её подзадачи.

```bash
# По индексу
ltc rm 1

# По group.index
ltc rm backend.2

# По fuzzy
ltc rm deploy
```

---

### `note` — описание

Устанавливает описание задачи. Удобно для добавления деталей без
полного `edit`.

```bash
ltc note 1 JWT-based auth with RS256
ltc note auth Использовать PKCE flow вместо implicit
```

---

### `groups` / `group` — управление группами

#### `groups` — таблица групп

```bash
ltc groups
```

```text
  Group     Tasks   Done
 ─────────────────────────
  Backend        5      3
  Auth           2      2
  Tests          4      1
```

#### `group` — создать пустую группу

```bash
ltc group DevOps
```

```text
Created group DevOps
```

---

## Reference resolution

Аргумент `<ref>` во всех командах (`done`, `undone`, `edit`, `rm`,
`note`, `add` для подзадач) резолвится следующими способами:

| Приоритет | Формат         | Пример       | Описание                          |
|-----------|----------------|--------------|-----------------------------------|
| 1         | `group.index`  | `backend.1`  | Имя группы + номер задачи         |
| 1         | `group.idx.sub`| `backend.1.2`| Группа + путь к подзадаче         |
| 2         | `N.M`          | `2.3`        | Глобальный индекс группы и задачи |
| 3         | `N`            | `5`          | Сквозной номер задачи             |
| 4         | `fuzzy`        | `auth`       | Substring-поиск по title          |

### Примеры fuzzy

```bash
# Задача "Реализовать API [!!]" в группе backend
ltc done api             # ✓ 1 match → resolved
ltc done реализовать     # ✓ 1 match → resolved (ignorecase)

# Две задачи с "test" в названии
ltc done test            # ✗ "Ambiguous match. Candidates:"
                         #   Backend: Test parser
                         #   Tests: Test serializer

# Нет совпадений
ltc done xyz             # ✗ "Nothing matches 'xyz'"
```

### Ref в команде add

При добавлении подзадачи ref определяется автоматически из токенов:

```bash
# "1" похож на ID → всегда трактуется как ref
ltc add 1 Subtask title

# "api" НЕ похож на ID → fuzzy, но есть title → становится ref
ltc add api Refactor endpoints

# "auth" единственный токен → не ref, а название новой задачи
ltc add auth
# → создаётся задача "auth" в Inbox, а НЕ подзадача

# Fuzzy + приоритет + описание
ltc add api rate limiting !! -n "100 req/min"
```

---

## Опции

### `--file` / `-f`

Все команды поддерживают указание пути к `TODO.md`:

```bash
ltc ls -f ~/projects/myapp/TODO.md
ltc add Fix bug -f ~/work/project/TODO.md
ltc done 1 -f ~/projects/myapp/TODO.md
```

По умолчанию используется `./TODO.md`.

### `--note` / `-n`

Добавление или изменение описания задачи:

```bash
ltc add Task -n "Описание задачи"
ltc add 1 Subtask -n "Детали подзадачи"
ltc edit 1 -n "Обновлённое описание"
```

---

## Разработка

### Технологии

- **Python** ≥ 3.12
- **Typer** — CLI-фреймворк
- **Rich** — форматирование вывода
- **uv** — управление зависимостями
- **ruff** — линтер
- **mypy** (strict) — типизация
- **pytest** — тесты

### Команды разработки

```bash
uv sync                  # установить зависимости
uv run pytest            # запустить тесты
uv run pytest --cov=ltc  # тесты с покрытием
uv run ruff check        # линтер
uv run mypy ltc          # типизация
```

### Архитектура

Подробное описание архитектуры — в [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).

---

## Лицензия

[GPL-3.0-or-later](LICENSE) © Andrey Limachko
