From 8957ceb74d7567c75645d9f70d677b7f84cfe645 Mon Sep 17 00:00:00 2001 From: Ricardo Ruiz Date: Tue, 21 May 2024 06:16:33 +0200 Subject: [PATCH] Fix -contains to allow multiple terms with "OR" logic unless -and is added (#1890) * Store multiple -contains arguments (OR default). Allow multiple occurrences of the -contains argument to be stored in a list. Previously, only the last occurrence was considered. Additionally, the behavior has been modified to default to OR logic, meaning that if multiple -contains arguments are provided, entries matching any of them will be included in the results. * Solved issue #1877 "-and" flag with multiple instances of the -contains option. * Run poe format * Fix unit test for contains to allow list instead of single value * Add BDD tests for multiple contains with and without -and * Black version updated. * Revert pyproject.toml to appease poetry --------- Co-authored-by: Micah Jerome Ellison --- jrnl/args.py | 1 + jrnl/journals/Journal.py | 20 ++++++++++++++++---- tests/bdd/features/search.feature | 30 ++++++++++++++++++++++++++++++ tests/unit/test_parse_args.py | 2 +- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/jrnl/args.py b/jrnl/args.py index 53a77462..43685182 100644 --- a/jrnl/args.py +++ b/jrnl/args.py @@ -265,6 +265,7 @@ def parse_args(args: list[str] = []) -> argparse.Namespace: reading.add_argument( "-contains", dest="contains", + action="append", metavar="TEXT", help="Show entries containing specific text (put quotes around text with " "spaces)", diff --git a/jrnl/journals/Journal.py b/jrnl/journals/Journal.py index d1054814..d7e9b0c0 100644 --- a/jrnl/journals/Journal.py +++ b/jrnl/journals/Journal.py @@ -246,7 +246,7 @@ class Journal: exclude_starred=False, exclude_tagged=False, strict=False, - contains=None, + contains=[], exclude=[], ): """Removes all entries from the journal that don't match the filter. @@ -276,7 +276,7 @@ class Journal: return 0 < len([tag for tag in tags if tag in excluded_tags]) if contains: - contains_lower = contains.casefold() + contains_lower = [substring.casefold() for substring in contains] # Create datetime object for comparison below # this approach allows various formats @@ -298,8 +298,20 @@ class Journal: and ( not contains or ( - contains_lower in entry.title.casefold() - or contains_lower in entry.body.casefold() + strict + and all( + substring in entry.title.casefold() + or substring in entry.body.casefold() + for substring in contains_lower + ) + ) + or ( + not strict + and any( + substring in entry.title.casefold() + or substring in entry.body.casefold() + for substring in contains_lower + ) ) ) ] diff --git a/tests/bdd/features/search.feature b/tests/bdd/features/search.feature index 79e2a84e..79ddf087 100644 --- a/tests/bdd/features/search.feature +++ b/tests/bdd/features/search.feature @@ -86,6 +86,36 @@ Feature: Searching in a journal | basic_folder.yaml | | basic_dayone.yaml | + Scenario Outline: Multiple -contains returns entries that match any + Given we use the config "" + When we run "jrnl -contains emojis -contains lorem --short" + Then we should get no error + And the output should contain "3 entries found" + And the output should be + 2020-08-29 11:11 Entry the first. + 2020-08-31 14:32 A second entry in what I hope to be a long series. + 2020-09-24 09:14 The third entry finally after weeks without writing. + + Examples: configs + | config_file | + | basic_onefile.yaml | + | basic_folder.yaml | + | basic_dayone.yaml | + + Scenario Outline: Multiple -contains with -and returns only entries that match all + Given we use the config "" + When we run "jrnl -contains emojis -contains nulla -and --short" + Then we should get no error + And the output should contain "1 entry found" + And the output should be + 2020-09-24 09:14 The third entry finally after weeks without writing. + + Examples: configs + | config_file | + | basic_onefile.yaml | + | basic_folder.yaml | + | basic_dayone.yaml | + Scenario Outline: Searching for a string within tag results Given we use the config "" When we run "jrnl @tagone -contains maybe" diff --git a/tests/unit/test_parse_args.py b/tests/unit/test_parse_args.py index e3036020..2e2d5cd6 100644 --- a/tests/unit/test_parse_args.py +++ b/tests/unit/test_parse_args.py @@ -55,7 +55,7 @@ def test_empty(): def test_contains_alone(): - assert cli_as_dict("-contains whatever") == expected_args(contains="whatever") + assert cli_as_dict("-contains whatever") == expected_args(contains=["whatever"]) def test_debug_alone():