diff --git a/jrnl/args.py b/jrnl/args.py index 53a77462e..436851822 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 d10548140..d7e9b0c0b 100644 --- a/jrnl/journals/Journal.py +++ b/jrnl/journals/Journal.py @@ -246,7 +246,7 @@ def filter( 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 @@ def excluded(tags): 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 @@ def excluded(tags): 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 79e2a84e4..79ddf0871 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 e30360201..2e2d5cd64 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():