Merge branch 'jrnl-org:develop' into develop

This commit is contained in:
Briscoooe 2023-02-01 22:06:33 +00:00 committed by GitHub
commit e6c6fe2ad4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 18 deletions

View file

@ -7,6 +7,7 @@
**Implemented enhancements:**
- Don't import cryptography package if not needed [\#1521](https://github.com/jrnl-org/jrnl/issues/1521)
- Search for entries with no tags or stars with `-not -starred` and `-not -tagged` [\#1663](https://github.com/jrnl-org/jrnl/pull/1663) ([cjcon90](https://github.com/cjcon90))
- Refactor flow for easier access to some files \(avoid things like `jrnl.Journal.Journal` and `jrnl.jrnl` co-existing\) [\#1662](https://github.com/jrnl-org/jrnl/pull/1662) ([wren](https://github.com/wren))
- Add more type hints [\#1642](https://github.com/jrnl-org/jrnl/pull/1642) ([outa](https://github.com/outa))
- Add `rich` handler to debug logging [\#1627](https://github.com/jrnl-org/jrnl/pull/1627) ([wren](https://github.com/wren))

View file

@ -28,6 +28,43 @@ class WrappingFormatter(argparse.RawTextHelpFormatter):
return text
class IgnoreNoneAppendAction(argparse._AppendAction):
"""
Pass -not without a following string and avoid appending
a None value to the excluded list
"""
def __call__(self, parser, namespace, values, option_string=None):
if values is not None:
super().__call__(parser, namespace, values, option_string)
def parse_not_arg(
args: list[str], parsed_args: argparse.Namespace, parser: argparse.ArgumentParser
) -> argparse.Namespace:
"""
It's possible to use -not as a precursor to -starred and -tagged
to reverse their behaviour, however this requires some extra logic
to parse, and to ensure we still do not allow passing an empty -not
"""
parsed_args.exclude_starred = False
parsed_args.exclude_tagged = False
if "-not-starred" in "".join(args):
parsed_args.starred = False
parsed_args.exclude_starred = True
if "-not-tagged" in "".join(args):
parsed_args.tagged = False
parsed_args.exclude_tagged = True
if "-not" in args and not any(
[parsed_args.exclude_starred, parsed_args.exclude_tagged, parsed_args.excluded]
):
parser.error("argument -not: expected 1 argument")
return parsed_args
def parse_args(args: list[str] = []) -> argparse.Namespace:
"""
Argument parsing that is doable before the config is available.
@ -237,6 +274,12 @@ def parse_args(args: list[str] = []) -> argparse.Namespace:
action="store_true",
help="Show only starred entries (marked with *)",
)
reading.add_argument(
"-tagged",
dest="tagged",
action="store_true",
help="Show only entries that have at least one tag",
)
reading.add_argument(
"-n",
dest="limit",
@ -249,11 +292,15 @@ def parse_args(args: list[str] = []) -> argparse.Namespace:
reading.add_argument(
"-not",
dest="excluded",
nargs=1,
nargs="?",
default=[],
metavar="TAG",
action="extend",
help="Exclude entries with this tag",
metavar="TAG/FLAG",
action=IgnoreNoneAppendAction,
help=(
"If passed a string, will exclude entries with that tag. "
"Can be also used before -starred or -tagged flags, to exclude "
"starred or tagged entries respectively."
),
)
search_options_msg = """ These help you do various tasks with the selected entries from your search.
@ -388,5 +435,7 @@ def parse_args(args: list[str] = []) -> argparse.Namespace:
# Handle '-123' as a shortcut for '-n 123'
num = re.compile(r"^-(\d+)$")
args = [num.sub(r"-n \1", arg) for arg in args]
parsed_args = parser.parse_intermixed_args(args)
parsed_args = parse_not_arg(args, parsed_args, parser)
return parser.parse_intermixed_args(args)
return parsed_args

View file

@ -89,6 +89,8 @@ def _is_write_mode(args: "Namespace", config: dict, **kwargs) -> bool:
args.edit,
args.change_time,
args.excluded,
args.exclude_starred,
args.exclude_tagged,
args.export,
args.end_date,
args.today_in_history,
@ -101,6 +103,7 @@ def _is_write_mode(args: "Namespace", config: dict, **kwargs) -> bool:
args.starred,
args.start_date,
args.strict,
args.tagged,
args.tags,
)
)
@ -273,7 +276,10 @@ def _has_search_args(args: "Namespace") -> bool:
args.end_date,
args.strict,
args.starred,
args.tagged,
args.excluded,
args.exclude_starred,
args.exclude_tagged,
args.contains,
args.limit,
)
@ -299,7 +305,10 @@ def _filter_journal_entries(args: "Namespace", journal: Journal, **kwargs) -> No
end_date=args.end_date,
strict=args.strict,
starred=args.starred,
tagged=args.tagged,
exclude=args.excluded,
exclude_starred=args.exclude_starred,
exclude_tagged=args.exclude_tagged,
contains=args.contains,
)
journal.limit(args.limit)

View file

@ -229,16 +229,19 @@ class Journal:
def filter(
self,
tags: list = [],
month: str | int | None = None,
day: str | int | None = None,
year: str | None = None,
start_date: str | None = None,
end_date: str | None = None,
starred: bool = False,
strict: bool = False,
contains: bool = None,
exclude: list = [],
tags=[],
month=None,
day=None,
year=None,
start_date=None,
end_date=None,
starred=False,
tagged=False,
exclude_starred=False,
exclude_tagged=False,
strict=False,
contains=None,
exclude=[],
):
"""Removes all entries from the journal that don't match the filter.
@ -259,7 +262,7 @@ class Journal:
start_date = time.parse(start_date)
# If strict mode is on, all tags have to be present in entry
tagged = self.search_tags.issubset if strict else self.search_tags.intersection
has_tags = self.search_tags.issubset if strict else self.search_tags.intersection
def excluded(tags):
return 0 < len([tag for tag in tags if tag in excluded_tags])
@ -275,8 +278,9 @@ class Journal:
result = [
entry
for entry in self.entries
if (not tags or tagged(entry.tags))
and (not starred or entry.starred)
if (not tags or has_tags(entry.tags))
and (not (starred or exclude_starred) or entry.starred == starred)
and (not (tagged or exclude_tagged) or bool(entry.tags) == tagged)
and (not month or entry.date.month == compare_d.month)
and (not day or entry.date.day == compare_d.day)
and (not year or entry.date.year == compare_d.year)

View file

@ -124,6 +124,50 @@ Feature: Searching in a journal
| basic_folder.yaml |
| basic_dayone.yaml |
Scenario: Searching for unstarred entries
Given we use the config "<config_file>"
And we use the password "test" if prompted
When we run "jrnl -not -starred"
Then we should get no error
And the output should contain "2 entries found"
Examples: configs
| config_file |
| basic_onefile.yaml |
| basic_folder.yaml |
| basic_dayone.yaml |
Scenario: Searching for tagged entries
Given we use the config "<config_file>"
And we use the password "test" if prompted
When we run "jrnl -tagged"
Then we should get no error
And the output should contain "3 entries found"
Examples: configs
| config_file |
| basic_onefile.yaml |
| basic_folder.yaml |
| basic_dayone.yaml |
Scenario: Searching for untagged entries
Given we use the config "empty_folder.yaml"
When we run "jrnl Tagged entry. This one has a @tag."
Then we should get no error
When we run "jrnl Untagged entry. This one has no tag."
Then we should get no error
When we run "jrnl -not -tagged"
Then we should get no error
And the output should contain "1 entry found"
And the output should contain "This one has no tag"
Examples: configs
| config_file |
| basic_onefile.yaml |
| basic_folder.yaml |
| basic_dayone.yaml |
Scenario Outline: Searching for dates
Given we use the config "<config_file>"
When we run "jrnl -on 2020-08-31 --short"

View file

@ -23,6 +23,8 @@ def expected_args(**kwargs):
"change_time": None,
"edit": False,
"end_date": None,
"exclude_starred": False,
"exclude_tagged": False,
"today_in_history": False,
"month": None,
"day": None,
@ -38,6 +40,7 @@ def expected_args(**kwargs):
"starred": False,
"start_date": None,
"strict": False,
"tagged": False,
"tags": False,
"text": [],
"config_override": [],