diff --git a/README.md b/README.md index c7e17af..8b9964a 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Usage: anki [OPTIONS] COMMAND [ARGS]... │ decks List decks with review stats. │ │ models List available note types. │ │ search Search notes using Anki query syntax. │ -│ list List notes, optionally filtered by deck and/or tag. │ +│ list List notes, optionally filtered by deck, tag, and/or flag. │ │ show Show full details of one or more notes. │ │ add Add a new note. │ │ edit Edit fields of an existing note. │ diff --git a/src/anki_cli/cli.py b/src/anki_cli/cli.py index be2f1a0..306f96d 100644 --- a/src/anki_cli/cli.py +++ b/src/anki_cli/cli.py @@ -178,15 +178,27 @@ def search( def list_( deck: Annotated[str | None, typer.Option("--deck", "-d", help="Filter by deck")] = None, tag: Annotated[str | None, typer.Option("--tag", "-t", help="Filter by tag")] = None, + flag: Annotated[ + int | None, typer.Option("--flag", "-F", help="Flag color (1-7) or 0 for any") + ] = None, limit: Annotated[int, typer.Option("--limit", "-l", help="Max results")] = 20, brief: Annotated[bool, typer.Option("--brief", "-B", help="Truncated table view")] = False, ) -> None: - """List notes, optionally filtered by deck and/or tag.""" + """List notes, optionally filtered by deck, tag, and/or flag.""" + if flag is not None and not 0 <= flag <= 7: + console.print("[red]--flag must be 0 (any) or 1-7.[/red]") + raise typer.Exit(2) + parts = [] if deck: parts.append(f'"deck:{deck}"') if tag: parts.append(f'"tag:{tag}"') + if flag is not None: + if flag == 0: + parts.append("(" + " OR ".join(f"flag:{i}" for i in range(1, 8)) + ")") + else: + parts.append(f"flag:{flag}") query = " ".join(parts) or "deck:*" client = AnkiClient() @@ -200,6 +212,12 @@ def list_( title = f"Deck: {deck}" if tag: title += f" [tag:{tag}]" if deck else f"Tag: {tag}" + if flag is not None: + flag_label = "Flagged" if flag == 0 else f"Flag: {flag}" + if deck or tag: + title += f" [{flag_label.lower()}]" + else: + title = flag_label _render_notes(infos, len(ids), title, limit, brief) diff --git a/tests/test_cli_search.py b/tests/test_cli_search.py index 2850bb0..aa7e84d 100644 --- a/tests/test_cli_search.py +++ b/tests/test_cli_search.py @@ -23,5 +23,16 @@ def test_fuzzy_score_empty_query_returns_zero(self) -> None: self.assertEqual(_fuzzy_score("", note), 0.0) +class ListFlagTests(unittest.TestCase): + def test_flag_rejects_out_of_range(self) -> None: + result = runner.invoke(app, ["list", "--flag", "9"]) + self.assertEqual(result.exit_code, 2) + self.assertIn("--flag must be 0 (any) or 1-7.", result.stdout) + + def test_flag_rejects_negative(self) -> None: + result = runner.invoke(app, ["list", "--flag", "-1"]) + self.assertNotEqual(result.exit_code, 0) + + if __name__ == "__main__": unittest.main()