mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-12 09:28:31 +02:00
Add -tagged
and -not -tagged
functionality
This commit is contained in:
parent
c573ca9418
commit
161d9c7262
5 changed files with 87 additions and 12 deletions
54
jrnl/args.py
54
jrnl/args.py
|
@ -27,11 +27,44 @@ class WrappingFormatter(argparse.RawTextHelpFormatter):
|
|||
text = [item for sublist in text for item in sublist]
|
||||
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.
|
||||
|
@ -241,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",
|
||||
|
@ -257,8 +296,10 @@ def parse_args(args: list[str] = []) -> argparse.Namespace:
|
|||
default=[],
|
||||
metavar="TAG/FLAG",
|
||||
action=IgnoreNoneAppendAction,
|
||||
help=("If passed a string, will exclude entries with that tag. "
|
||||
"If it preceeds -starred flag, will exclude starred entries"
|
||||
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."
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -395,13 +436,6 @@ def parse_args(args: list[str] = []) -> argparse.Namespace:
|
|||
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.exclude_starred = False
|
||||
|
||||
# Handle -not where it is reversing the behaviour of a flag
|
||||
if "-not-starred" in "".join(args):
|
||||
parsed_args.starred = False
|
||||
parsed_args.exclude_starred = True
|
||||
if "-not" in args and not any([parsed_args.exclude_starred, parsed_args.excluded]):
|
||||
return parser.error("argument -not: expected 1 argument")
|
||||
parsed_args = parse_not_arg(args, parsed_args, parser)
|
||||
|
||||
return parsed_args
|
||||
|
|
|
@ -90,6 +90,7 @@ def _is_write_mode(args: "Namespace", config: dict, **kwargs) -> bool:
|
|||
args.change_time,
|
||||
args.excluded,
|
||||
args.exclude_starred,
|
||||
args.exclude_tagged,
|
||||
args.export,
|
||||
args.end_date,
|
||||
args.today_in_history,
|
||||
|
@ -102,6 +103,7 @@ def _is_write_mode(args: "Namespace", config: dict, **kwargs) -> bool:
|
|||
args.starred,
|
||||
args.start_date,
|
||||
args.strict,
|
||||
args.tagged,
|
||||
args.tags,
|
||||
)
|
||||
)
|
||||
|
@ -271,8 +273,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,
|
||||
)
|
||||
|
@ -298,8 +302,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)
|
||||
|
|
|
@ -236,7 +236,9 @@ class Journal:
|
|||
start_date=None,
|
||||
end_date=None,
|
||||
starred=False,
|
||||
tagged=False,
|
||||
exclude_starred=False,
|
||||
exclude_tagged=False,
|
||||
strict=False,
|
||||
contains=None,
|
||||
exclude=[],
|
||||
|
@ -260,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])
|
||||
|
@ -276,8 +278,9 @@ class Journal:
|
|||
result = [
|
||||
entry
|
||||
for entry in self.entries
|
||||
if (not tags or tagged(entry.tags))
|
||||
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)
|
||||
|
|
|
@ -138,6 +138,36 @@ Feature: Searching in a journal
|
|||
| 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"
|
||||
|
|
|
@ -24,6 +24,7 @@ def expected_args(**kwargs):
|
|||
"edit": False,
|
||||
"end_date": None,
|
||||
"exclude_starred": False,
|
||||
"exclude_tagged": False,
|
||||
"today_in_history": False,
|
||||
"month": None,
|
||||
"day": None,
|
||||
|
@ -39,6 +40,7 @@ def expected_args(**kwargs):
|
|||
"starred": False,
|
||||
"start_date": None,
|
||||
"strict": False,
|
||||
"tagged": False,
|
||||
"tags": False,
|
||||
"text": [],
|
||||
"config_override": [],
|
||||
|
|
Loading…
Add table
Reference in a new issue