From 853d152ba5edd78a3cb69ad1eaa9e8ecd9ef8b2f Mon Sep 17 00:00:00 2001 From: Sheikh Arfaz Ahamed <38525086+sheikharfaz@users.noreply.github.com> Date: Mon, 8 Jun 2026 22:28:19 +0530 Subject: [PATCH 1/3] fix(tasks): honor category argument in add_task (#46) --- trushell/commands/tasks.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/trushell/commands/tasks.py b/trushell/commands/tasks.py index 7a1688c..27847f7 100644 --- a/trushell/commands/tasks.py +++ b/trushell/commands/tasks.py @@ -1,5 +1,6 @@ from __future__ import annotations +import re from typing import Callable from trushell.core.database import complete_todo, delete_todo, get_all_todos, insert_todo, update_todo @@ -7,13 +8,32 @@ def add_task(args: str) -> None: - """Add a new task to the todo list. The full remainder is treated as the task.""" - if not args.strip(): - print("Usage: task add ") + """Add a new task to the todo list. + + Accepts an optional quoted category, mirroring ``update_task`` and the + documented ``addtask "" ""`` syntax:: + + task add "Buy milk" "Shopping" -> task="Buy milk", category="Shopping" + task add "Buy milk" -> task="Buy milk", category="General" + task add Buy milk -> task="Buy milk", category="General" + + When no category is supplied the task falls back to the "General" category, + preserving the previous default behaviour. + """ + text = args.strip() + if not text: + print('Usage: task add "" [""]') return - task_text = args.strip() - todo = Todo(task=task_text, category="General") + match = re.fullmatch(r'"([^"]+)"(?:\s+"([^"]*)")?', text) + if match: + task_text = match.group(1) + category = match.group(2) or "General" + else: + task_text = text + category = "General" + + todo = Todo(task=task_text, category=category) insert_todo(todo) print("Task added.") From e640ce6b612490b919c5a7a2c1dcfd70e5a7a902 Mon Sep 17 00:00:00 2001 From: Sheikh Arfaz Ahamed <38525086+sheikharfaz@users.noreply.github.com> Date: Mon, 8 Jun 2026 22:33:48 +0530 Subject: [PATCH 2/3] fix(cli): pass quoted category to add_task (#46) --- trushell/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trushell/cli.py b/trushell/cli.py index 0eb1674..e6c836c 100644 --- a/trushell/cli.py +++ b/trushell/cli.py @@ -195,7 +195,7 @@ def _handle_todo_command(command: str) -> bool: if add_match: from trushell.commands.tasks import add_task - add_task(f"{add_match.group(1)} {add_match.group(2)}") + add_task(f'"{add_match.group(1)}" "{add_match.group(2)}"') return True update_match = re.match(r'updatetask\s+(\d+)\s+"([^"]+)"\s+"([^"]+)"', command) From bdc22d3a96c1628d502e5852ad549563487f53fe Mon Sep 17 00:00:00 2001 From: Sheikh Arfaz Ahamed <38525086+sheikharfaz@users.noreply.github.com> Date: Mon, 8 Jun 2026 22:36:07 +0530 Subject: [PATCH 3/3] test(tasks): add regression tests for category parsing (#46) --- tests/test_tasks.py | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/test_tasks.py b/tests/test_tasks.py index 69e5474..d3dace9 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -50,3 +50,57 @@ def fake_update_todo(index: int, task: str | None, category: str | None) -> None assert captured["task"] == "New" # and treats the remainder as the category assert captured["category"] == "text" + + +def test_add_task_parses_quoted_category(monkeypatch) -> None: + """`task add "" ""` stores the supplied category (gh-46).""" + from trushell.commands.tasks import add_task + + captured: dict[str, Any] = {} + + def fake_insert_todo(todo: Any) -> None: + captured["task"] = todo.task + captured["category"] = todo.category + + monkeypatch.setattr("trushell.commands.tasks.insert_todo", fake_insert_todo) + + add_task('"Buy milk" "Shopping"') + + assert captured["task"] == "Buy milk" + assert captured["category"] == "Shopping" + + +def test_add_task_defaults_category_when_omitted(monkeypatch) -> None: + """A quoted task with no category falls back to the "General" category.""" + from trushell.commands.tasks import add_task + + captured: dict[str, Any] = {} + + def fake_insert_todo(todo: Any) -> None: + captured["task"] = todo.task + captured["category"] = todo.category + + monkeypatch.setattr("trushell.commands.tasks.insert_todo", fake_insert_todo) + + add_task('"Pay rent"') + + assert captured["task"] == "Pay rent" + assert captured["category"] == "General" + + +def test_add_task_unquoted_remains_backwards_compatible(monkeypatch) -> None: + """Unquoted input keeps the whole remainder as the task text (back-compat).""" + from trushell.commands.tasks import add_task + + captured: dict[str, Any] = {} + + def fake_insert_todo(todo: Any) -> None: + captured["task"] = todo.task + captured["category"] = todo.category + + monkeypatch.setattr("trushell.commands.tasks.insert_todo", fake_insert_todo) + + add_task("buy groceries") + + assert captured["task"] == "buy groceries" + assert captured["category"] == "General"