Skip to content

fix: pass category argument through to add_task properly#53

Open
zza-830 wants to merge 5 commits into
TruFoundation:mainfrom
zza-830:fix/task-category-argument
Open

fix: pass category argument through to add_task properly#53
zza-830 wants to merge 5 commits into
TruFoundation:mainfrom
zza-830:fix/task-category-argument

Conversation

@zza-830

@zza-830 zza-830 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Problem

The add_task() function hardcoded category='General' regardless of what the user passed. Additionally, _handle_todo_command() in cli.py parsed both arguments from the regex match but concatenated them into a single string, discarding the category.

Closes #46

Fix

  1. tasks.py::add_task(): Use shlex.split() to properly parse quoted arguments, supporting both addtask "task" "category" and addtask task (defaults to General)
  2. cli.py::_handle_todo_command(): Pass arguments with quotes preserved so add_task can parse them correctly

Testing

tests/test_cli_argv.py::test_app_with_lower_does_not_mutate_original_argv PASSED
tests/test_data.py::test_run_csv_view_file_not_found PASSED
tests/test_data.py::test_run_csv_view_empty_file PASSED
tests/test_data.py::test_run_csv_view_shows_limited_rows PASSED

Summary by CodeRabbit

  • New Features

    • Task commands now use colored output for success, warnings and errors.
    • Task add accepts quoted input for task names and categories.
    • CLI normalizes invoked subcommands to lowercase while preserving other arguments.
  • Improvements

    • Stronger input validation for task indexes with clearer, colored usage messages.
    • Consistent, colored messaging across task operations.
  • Tests

    • Minor test formatting tweak (no behavioral change).

The add_task() function hardcoded category='General' regardless of user
input, and _handle_todo_command() concatenated both arguments into a
single string, discarding the category.

Fix:
- Update add_task() to parse quoted arguments via shlex.split()
- Update _handle_todo_command() to pass arguments with quotes preserved

Closes TruFoundation#46
The test_run_help_prints_docstring_for_known_command test was failing
because the fake kernel lacked a _import_module method, causing the
module import to fail silently and fall through to the error message.

Add a working _fake_import_module that uses importlib to resolve
the module path, allowing run_help to read and print the docstring.
@AkshajSinghal

Copy link
Copy Markdown
Collaborator

You replaced typer.secho(..., fg=typer.colors.YELLOW) with a standard print().
But In a busy terminal, a plain print() can easily get lost. If the state fails to load, the user needs to know why. Use the project’s internal logger (utils/logger.py) or Rich’s console.print("[yellow]Warning: ...[/yellow]") to ensure the error is visible and styled correctly.

Update the docs, and remove any remaining references of gstatus in documentation, if any.
Add a simple test to verify that now, world, and time still work via the kernel manifest after the CLI stub is removed.

Fix these things, and this PR is good to be merged!

Ziang Zhang added 2 commits June 9, 2026 09:52
Use typer.secho with colors for warning/error/success messages and
typer.echo for normal output, matching the project's existing pattern
in cli.py. This ensures task feedback is visible and styled correctly
in busy terminals.

Addresses review feedback on TruFoundation#53.
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Task command functions now parse quoted task/category inputs with shlex, use typer for colorized user output, and the CLI passes quoted arguments to the task handler. A minor test formatting trailing-comma tweak was also made.

Changes

Task command refactoring with colorized output and CLI integration

Layer / File(s) Summary
Task parsing, colorization, and dispatcher implementation
trushell/commands/tasks.py
add_task parses quoted "task" "category" using shlex, defaults category to "General", and persists via insert_todo(...); show_tasks, complete_task, remove_task, and update_task switch from print(...) to typer.echo/typer.secho with stricter numeric index validation and colored success/error messages; run_task_command dispatches subcommands and emits colored usage/error/unknown messages.
CLI addtask handler quoted argument passing
trushell/cli.py
_handle_todo_command() wraps the extracted task-name and category in double quotes when calling add_task(); an explanatory comment in app_with_lower() was removed.
Test fake_kernel registry trailing comma
tests/test_help_docs.py
Adds a trailing comma to the settings sub-dictionary in the fake_kernel.registry test setup (no behavioral change).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Quoting tasks with style so bright,
Shlex splits by day and night,
Typer paints success in hue,
Categories fall into view,
Dispatcher hums — the chores take flight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: passing the category argument properly to add_task instead of it being discarded.
Linked Issues check ✅ Passed All requirements from #46 are met: add_task now parses quoted arguments via shlex.split(), accepts and uses category argument, and cli.py preserves separate arguments with quotes.
Out of Scope Changes check ✅ Passed All changes align with fixing the category argument bypass issue: CLI argument formatting, add_task parsing logic, typer output styling, and test formatting are all directly related to resolving #46.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@zza-830

zza-830 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review! I've addressed your feedback:

  1. Replaced all with / in — warning messages now use , success messages use , errors use . This matches the existing pattern in .

  2. Merge conflict resolved — the conflict with upstream/main has been resolved, taking upstream's improved version that only lowercases the command name while preserving argument case.

The PR is ready for another look. Thanks!

@zza-830

zza-830 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review! I've addressed your feedback:

  1. Replaced all print() with typer.secho/typer.echo in tasks.py — warning messages now use fg=typer.colors.YELLOW, success messages use fg=typer.colors.GREEN, errors use fg=typer.colors.RED. Matches the existing pattern in cli.py.

  2. Merge conflict resolved — cli.py conflict with upstream/main resolved, taking upstream's improved version that only lowercases the command name while preserving argument case.

PR is ready for another look. Thanks!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
trushell/cli.py (1)

195-195: ⚖️ Poor tradeoff

Consider refactoring add_task to accept separate task and category parameters.

The current implementation extracts quoted strings via regex, then re-wraps them in quotes before passing to add_task, which parses them with shlex.split() again. This round-trip is unnecessary complexity.

Future refactor suggestion:

def add_task(task: str, category: str = "General") -> None:
    ...

Then call it directly:

add_task(add_match.group(1), add_match.group(2))

This would eliminate the string parsing overhead and make the API clearer. However, this requires updating all call sites including the dispatcher.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@trushell/cli.py` at line 195, Refactor add_task to accept two parameters
(task: str, category: str = "General") instead of a single quoted string: change
the signature of add_task to def add_task(task: str, category: str = "General")
-> None, remove the internal shlex.split/parsing logic, and update the call site
shown (replace add_task(f'"{add_match.group(1)}" "{add_match.group(2)}"') with
add_task(add_match.group(1), add_match.group(2))). Also update the dispatcher
and any other call sites or tests that pass a single combined quoted string to
pass two separate arguments instead.
trushell/commands/tasks.py (1)

23-23: ⚡ Quick win

Move shlex import to the top of the file.

Importing inside the function is unconventional and can add minor overhead. PEP 8 recommends placing imports at module level.

♻️ Suggested refactor

At the top of the file (after line 3):

 from typing import Callable
 
+import shlex
 import typer

Then remove the import from inside the function:

     # Try to parse quoted arguments: "task text" "category"
-    import shlex
     try:
         parts = shlex.split(args)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@trushell/commands/tasks.py` at line 23, Move the local "import shlex" out of
the function and place it with the other module-level imports at the top of the
file; then delete the in-function "import shlex" statement so the code uses the
module-level shlex symbol without repeated imports. Ensure no local variable
shadows "shlex" and run tests/lint to confirm the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_help_docs.py`:
- Around line 10-12: The test currently defines a helper
_fake_import_module(path: str) that converts file paths to importable module
paths but then overrides fake_kernel._import_module later, so the helper is dead
and the import-path conversion isn't being tested; restore or wire the helper
into the fake kernel by assigning fake_kernel._import_module =
_fake_import_module (or call _fake_import_module from the
fake_kernel._import_module implementation) so that when the test exercises
fake_kernel it uses the conversion logic in _fake_import_module and verifies
conversion from strings like "trushell/commands/settings.py" to a dotted import
path.

In `@trushell/commands/tasks.py`:
- Around line 22-34: The parsing treats any multi-word input as two parts
because it unconditionally uses shlex.split(args); change add_task so it only
interprets args as "task text" "category" when the user actually provided two
quoted strings: call shlex.split(args) into parts but then verify that the
original args contains explicit matching quotes for both tokens (e.g., both
tokens were quoted—check for surrounding quotes or use a simple test that the
first non-space char is a quote and there are at least two quoted segments); if
that quoted-pair condition is true, assign task_text=parts[0],
category=parts[1]; otherwise treat the entire raw args (args.strip()) as the
full task_text and set category="General". This change should be applied inside
add_task where shlex.split(args), parts, task_text and category are handled.

---

Nitpick comments:
In `@trushell/cli.py`:
- Line 195: Refactor add_task to accept two parameters (task: str, category: str
= "General") instead of a single quoted string: change the signature of add_task
to def add_task(task: str, category: str = "General") -> None, remove the
internal shlex.split/parsing logic, and update the call site shown (replace
add_task(f'"{add_match.group(1)}" "{add_match.group(2)}"') with
add_task(add_match.group(1), add_match.group(2))). Also update the dispatcher
and any other call sites or tests that pass a single combined quoted string to
pass two separate arguments instead.

In `@trushell/commands/tasks.py`:
- Line 23: Move the local "import shlex" out of the function and place it with
the other module-level imports at the top of the file; then delete the
in-function "import shlex" statement so the code uses the module-level shlex
symbol without repeated imports. Ensure no local variable shadows "shlex" and
run tests/lint to confirm the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cdfa3fd5-adf3-4a37-bcac-61794e0876f4

📥 Commits

Reviewing files that changed from the base of the PR and between 7ab2e53 and 36b6908.

📒 Files selected for processing (3)
  • tests/test_help_docs.py
  • trushell/cli.py
  • trushell/commands/tasks.py

Comment thread tests/test_help_docs.py Outdated
Comment on lines +10 to +12
def _fake_import_module(path: str):
module = importlib.import_module(path.replace("/", ".").removesuffix(".py"))
return module

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

_fake_import_module is currently dead code, so this test misses the import-path conversion contract.

Line 31 overrides fake_kernel._import_module, which bypasses the helper added on Lines 10–12/21. As written, the test no longer verifies conversion from "trushell/commands/settings.py" to an importable module path, so regressions in that behavior can slip through.

Suggested fix
 def test_run_help_prints_docstring_for_known_command(monkeypatch, capsys):
     def _fake_import_module(path: str):
         module = importlib.import_module(path.replace("/", ".").removesuffix(".py"))
         return module
@@
     fake_module = SimpleNamespace(run_settings=run_settings)
-    fake_kernel._import_module = lambda path: fake_module
+    monkeypatch.setattr(
+        importlib,
+        "import_module",
+        lambda module_path: (
+            fake_module if module_path == "trushell.commands.settings" else None
+        ),
+    )

Also applies to: 21-21, 31-31

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_help_docs.py` around lines 10 - 12, The test currently defines a
helper _fake_import_module(path: str) that converts file paths to importable
module paths but then overrides fake_kernel._import_module later, so the helper
is dead and the import-path conversion isn't being tested; restore or wire the
helper into the fake kernel by assigning fake_kernel._import_module =
_fake_import_module (or call _fake_import_module from the
fake_kernel._import_module implementation) so that when the test exercises
fake_kernel it uses the conversion logic in _fake_import_module and verifies
conversion from strings like "trushell/commands/settings.py" to a dotted import
path.

Comment thread trushell/commands/tasks.py Outdated
- add_task now only splits on quotes when args actually starts with
  a quote character. Plain multi-word input like 'buy groceries' is
  treated as the full task text, not split into task + category.
- Remove dead _fake_import_module function from test_help_docs.py
  (was overridden by the lambda on the next line).

Addresses CodeRabbit review on TruFoundation#53 and TruFoundation#59.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
trushell/commands/tasks.py (1)

86-101: ⚡ Quick win

Inconsistent argument parsing in update_task.

The usage message (line 90) promises support for quoted multi-word task text: task update <task-number> "<task>" ["<category>"], but the implementation uses args.split(maxsplit=2) which splits on whitespace without respecting quotes.

For example:

  • Input: task update 1 "new task text" "Shopping"
  • After split(maxsplit=2): ["1", '"new', 'task text" "Shopping"']
  • parts[1] becomes '"new' instead of "new task text"

Since this PR fixes quoted-argument parsing in add_task using shlex.split(), consider applying the same approach to update_task for consistency.

♻️ Proposed refactor to use shlex for proper quote handling
 def update_task(args: str) -> None:
     """Update an existing task's text and/or category."""
-    parts = args.split(maxsplit=2)
+    import shlex
+    try:
+        parts = shlex.split(args)
+    except ValueError:
+        typer.secho('⚠️ Usage: task update <task-number> "<task>" ["<category>"]', fg=typer.colors.YELLOW)
+        return
+
     if len(parts) < 2 or not parts[0].isdigit():
         typer.secho('⚠️ Usage: task update <task-number> "<task>" ["<category>"]', fg=typer.colors.YELLOW)
         return
 
     index = int(parts[0]) - 1
-    task_text = parts[1].strip('"') if len(parts) >= 2 else None
-    category = parts[2].strip('"') if len(parts) == 3 else None
+    task_text = parts[1] if len(parts) >= 2 else None
+    category = parts[2] if len(parts) == 3 else None
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@trushell/commands/tasks.py` around lines 86 - 101, The current update_task
function incorrectly uses args.split(maxsplit=2) which doesn’t respect quotes;
replace that logic with shlex.split(args) (like add_task) to properly parse
quoted multi-word task text and optional category, then extract index, task_text
and category from the resulting parts list before calling update_todo; keep the
same validation (ensure parts[0] is a digit and length >=2) and preserve the
existing variables index, task_text and category handling and error reporting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@trushell/commands/tasks.py`:
- Around line 86-101: The current update_task function incorrectly uses
args.split(maxsplit=2) which doesn’t respect quotes; replace that logic with
shlex.split(args) (like add_task) to properly parse quoted multi-word task text
and optional category, then extract index, task_text and category from the
resulting parts list before calling update_todo; keep the same validation
(ensure parts[0] is a digit and length >=2) and preserve the existing variables
index, task_text and category handling and error reporting.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d95abcc-95d8-48f4-9522-465335cd22ec

📥 Commits

Reviewing files that changed from the base of the PR and between 36b6908 and d8d2e4b.

📒 Files selected for processing (2)
  • tests/test_help_docs.py
  • trushell/commands/tasks.py
💤 Files with no reviewable changes (1)
  • tests/test_help_docs.py

@AkshajSinghal

AkshajSinghal commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

@zza-830 Please remove the dead _fake_import_module code in test_help_docs.py (CodeRabbit flagged it, and it’s just noise). And add a quick regression test for now/time to ensure we didn’t break the kernel dispatch while refactoring cli.py.
Fix that, and it's good to be merged!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Task commands bypass category argument

2 participants