Skip to content

Commit 9e581e5

Browse files
authored
fix(tasks): honor category argument in add_task (#46) (#63)
* fix(tasks): honor category argument in add_task (#46) * fix(cli): pass quoted category to add_task (#46) * test(tasks): add regression tests for category parsing (#46)
1 parent 2540859 commit 9e581e5

3 files changed

Lines changed: 80 additions & 6 deletions

File tree

tests/test_tasks.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,57 @@ def fake_update_todo(index: int, task: str | None, category: str | None) -> None
5050
assert captured["task"] == "New"
5151
# and treats the remainder as the category
5252
assert captured["category"] == "text"
53+
54+
55+
def test_add_task_parses_quoted_category(monkeypatch) -> None:
56+
"""`task add "<task>" "<category>"` stores the supplied category (gh-46)."""
57+
from trushell.commands.tasks import add_task
58+
59+
captured: dict[str, Any] = {}
60+
61+
def fake_insert_todo(todo: Any) -> None:
62+
captured["task"] = todo.task
63+
captured["category"] = todo.category
64+
65+
monkeypatch.setattr("trushell.commands.tasks.insert_todo", fake_insert_todo)
66+
67+
add_task('"Buy milk" "Shopping"')
68+
69+
assert captured["task"] == "Buy milk"
70+
assert captured["category"] == "Shopping"
71+
72+
73+
def test_add_task_defaults_category_when_omitted(monkeypatch) -> None:
74+
"""A quoted task with no category falls back to the "General" category."""
75+
from trushell.commands.tasks import add_task
76+
77+
captured: dict[str, Any] = {}
78+
79+
def fake_insert_todo(todo: Any) -> None:
80+
captured["task"] = todo.task
81+
captured["category"] = todo.category
82+
83+
monkeypatch.setattr("trushell.commands.tasks.insert_todo", fake_insert_todo)
84+
85+
add_task('"Pay rent"')
86+
87+
assert captured["task"] == "Pay rent"
88+
assert captured["category"] == "General"
89+
90+
91+
def test_add_task_unquoted_remains_backwards_compatible(monkeypatch) -> None:
92+
"""Unquoted input keeps the whole remainder as the task text (back-compat)."""
93+
from trushell.commands.tasks import add_task
94+
95+
captured: dict[str, Any] = {}
96+
97+
def fake_insert_todo(todo: Any) -> None:
98+
captured["task"] = todo.task
99+
captured["category"] = todo.category
100+
101+
monkeypatch.setattr("trushell.commands.tasks.insert_todo", fake_insert_todo)
102+
103+
add_task("buy groceries")
104+
105+
assert captured["task"] == "buy groceries"
106+
assert captured["category"] == "General"

trushell/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ def _handle_todo_command(command: str) -> bool:
192192
if add_match:
193193
from trushell.commands.tasks import add_task
194194

195-
add_task(f"{add_match.group(1)} {add_match.group(2)}")
195+
add_task(f'"{add_match.group(1)}" "{add_match.group(2)}"')
196196
return True
197197

198198
update_match = re.match(r'updatetask\s+(\d+)\s+"([^"]+)"\s+"([^"]+)"', command)

trushell/commands/tasks.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,39 @@
11
from __future__ import annotations
22

3+
import re
34
from typing import Callable
45

56
from trushell.core.database import complete_todo, delete_todo, get_all_todos, insert_todo, update_todo
67
from trushell.core.models import Todo
78

89

910
def add_task(args: str) -> None:
10-
"""Add a new task to the todo list. The full remainder is treated as the task."""
11-
if not args.strip():
12-
print("Usage: task add <task>")
11+
"""Add a new task to the todo list.
12+
13+
Accepts an optional quoted category, mirroring ``update_task`` and the
14+
documented ``addtask "<task>" "<category>"`` syntax::
15+
16+
task add "Buy milk" "Shopping" -> task="Buy milk", category="Shopping"
17+
task add "Buy milk" -> task="Buy milk", category="General"
18+
task add Buy milk -> task="Buy milk", category="General"
19+
20+
When no category is supplied the task falls back to the "General" category,
21+
preserving the previous default behaviour.
22+
"""
23+
text = args.strip()
24+
if not text:
25+
print('Usage: task add "<task>" ["<category>"]')
1326
return
1427

15-
task_text = args.strip()
16-
todo = Todo(task=task_text, category="General")
28+
match = re.fullmatch(r'"([^"]+)"(?:\s+"([^"]*)")?', text)
29+
if match:
30+
task_text = match.group(1)
31+
category = match.group(2) or "General"
32+
else:
33+
task_text = text
34+
category = "General"
35+
36+
todo = Todo(task=task_text, category=category)
1737
insert_todo(todo)
1838
print("Task added.")
1939

0 commit comments

Comments
 (0)