mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-10 08:38:32 +02:00
Allow combinations of --change-time
, --delete
, and --edit
while correctly counting the number of entries affected (#1669)
* Remove search mode conditional that added explicit tag search behavior * Fix failing change-time test by using same method signature as base journal class * Fix user input mock - was not appropriately checking return value * Clean up controller - streamline `run` function in `controller.py` - add debug logging - fix unnecessary import of Journal class (only needed for typing) - standardize summary display across different actions * Add currently-failing test conditions for count messages when changing time and deleting * Don't show summary if no entries found and prevent extra line break when no entries found by short-circuiting display method * Track found entry count and remove incorrect modified stat logic * Track journal entry deletion consistently * Remove unneeded exception when editor is empty and fix test that was testing incorrect message * Correct entry edit modified count test * Track modification of entries with --change-time * Preserve existing behavior when editor is empty but make the message more clear * Reconcile tests with new error message when clearing editor in edit mode * Add found/modified counts to edit tests * Add tests for found count with -n equivalent argument * Test combinations of found/deleted messages when using --delete * Add tests for counting combinations of action arguments (change-time, edit, delete) and for change-time counts. Some are failing and should be investigated * Remove extraneous comment in test * Track added/deleted counts in a register in the Journal class instead of attempting to infer it via controller counting * Add encrypted to more tests * Fix merge conflict typo * Change 'write mode' -> 'append mode' in more places --------- Co-authored-by: Micah Jerome Ellison <micah.jerome.ellison@gmail.com>
This commit is contained in:
parent
b3c6f90a35
commit
3c923ae943
18 changed files with 474 additions and 265 deletions
|
@ -16,7 +16,6 @@ from jrnl.config import scope_config
|
||||||
from jrnl.editor import get_text_from_editor
|
from jrnl.editor import get_text_from_editor
|
||||||
from jrnl.editor import get_text_from_stdin
|
from jrnl.editor import get_text_from_stdin
|
||||||
from jrnl.exception import JrnlException
|
from jrnl.exception import JrnlException
|
||||||
from jrnl.journals import Journal
|
|
||||||
from jrnl.journals import open_journal
|
from jrnl.journals import open_journal
|
||||||
from jrnl.messages import Message
|
from jrnl.messages import Message
|
||||||
from jrnl.messages import MsgStyle
|
from jrnl.messages import MsgStyle
|
||||||
|
@ -30,6 +29,7 @@ if TYPE_CHECKING:
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
|
|
||||||
from jrnl.journals import Entry
|
from jrnl.journals import Entry
|
||||||
|
from jrnl.journals import Journal
|
||||||
|
|
||||||
|
|
||||||
def run(args: "Namespace"):
|
def run(args: "Namespace"):
|
||||||
|
@ -39,8 +39,9 @@ def run(args: "Namespace"):
|
||||||
2. Load config
|
2. Load config
|
||||||
3. Run standalone command if it does require config (encrypt, decrypt, etc), then exit
|
3. Run standalone command if it does require config (encrypt, decrypt, etc), then exit
|
||||||
4. Load specified journal
|
4. Load specified journal
|
||||||
5. Start write mode, or search mode
|
5. Start append mode, or search mode
|
||||||
6. Profit
|
6. Perform actions with results from search mode (if needed)
|
||||||
|
7. Profit
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Run command if possible before config is available
|
# Run command if possible before config is available
|
||||||
|
@ -72,56 +73,61 @@ def run(args: "Namespace"):
|
||||||
"args": args,
|
"args": args,
|
||||||
"config": config,
|
"config": config,
|
||||||
"journal": journal,
|
"journal": journal,
|
||||||
|
"old_entries": journal.entries,
|
||||||
}
|
}
|
||||||
|
|
||||||
if _is_write_mode(**kwargs):
|
if _is_append_mode(**kwargs):
|
||||||
write_mode(**kwargs)
|
append_mode(**kwargs)
|
||||||
|
return
|
||||||
|
|
||||||
|
# If not append mode, then we're in search mode (only 2 modes exist)
|
||||||
|
search_mode(**kwargs)
|
||||||
|
entries_found_count = len(journal)
|
||||||
|
_print_entries_found_count(entries_found_count, args)
|
||||||
|
|
||||||
|
# Actions
|
||||||
|
_perform_actions_on_search_results(**kwargs)
|
||||||
|
|
||||||
|
if entries_found_count != 0 and _has_action_args(args):
|
||||||
|
_print_changed_counts(journal)
|
||||||
else:
|
else:
|
||||||
search_mode(**kwargs)
|
# display only occurs if no other action occurs
|
||||||
|
_display_search_results(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def _is_write_mode(args: "Namespace", config: dict, **kwargs) -> bool:
|
def _perform_actions_on_search_results(**kwargs):
|
||||||
"""Determines if we are in write mode (as opposed to search mode)"""
|
args = kwargs["args"]
|
||||||
|
|
||||||
|
# Perform actions (if needed)
|
||||||
|
if args.change_time:
|
||||||
|
_change_time_search_results(**kwargs)
|
||||||
|
|
||||||
|
if args.delete:
|
||||||
|
_delete_search_results(**kwargs)
|
||||||
|
|
||||||
|
# open results in editor (if `--edit` was used)
|
||||||
|
if args.edit:
|
||||||
|
_edit_search_results(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_append_mode(args: "Namespace", config: dict, **kwargs) -> bool:
|
||||||
|
"""Determines if we are in append mode (as opposed to search mode)"""
|
||||||
# Are any search filters present? If so, then search mode.
|
# Are any search filters present? If so, then search mode.
|
||||||
write_mode = not any(
|
append_mode = (
|
||||||
(
|
not _has_search_args(args)
|
||||||
args.contains,
|
and not _has_action_args(args)
|
||||||
args.delete,
|
and not _has_display_args(args)
|
||||||
args.edit,
|
|
||||||
args.change_time,
|
|
||||||
args.excluded,
|
|
||||||
args.exclude_starred,
|
|
||||||
args.exclude_tagged,
|
|
||||||
args.export,
|
|
||||||
args.end_date,
|
|
||||||
args.today_in_history,
|
|
||||||
args.month,
|
|
||||||
args.day,
|
|
||||||
args.year,
|
|
||||||
args.limit,
|
|
||||||
args.on_date,
|
|
||||||
args.short,
|
|
||||||
args.starred,
|
|
||||||
args.start_date,
|
|
||||||
args.strict,
|
|
||||||
args.tagged,
|
|
||||||
args.tags,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Might be writing and want to move to editor part of the way through
|
# Might be writing and want to move to editor part of the way through
|
||||||
if args.edit and args.text:
|
if args.edit and args.text:
|
||||||
write_mode = True
|
append_mode = True
|
||||||
|
|
||||||
# If the text is entirely tags, then we are also searching (not writing)
|
# If the text is entirely tags, then we are also searching (not writing)
|
||||||
if (
|
if append_mode and args.text and _has_only_tags(config["tagsymbols"], args.text):
|
||||||
write_mode
|
append_mode = False
|
||||||
and args.text
|
|
||||||
and all(word[0] in config["tagsymbols"] for word in " ".join(args.text).split())
|
|
||||||
):
|
|
||||||
write_mode = False
|
|
||||||
|
|
||||||
return write_mode
|
return append_mode
|
||||||
|
|
||||||
|
|
||||||
def _read_template_file(template_arg: str, template_path_from_config: str) -> str:
|
def _read_template_file(template_arg: str, template_path_from_config: str) -> str:
|
||||||
|
@ -138,12 +144,12 @@ def _read_template_file(template_arg: str, template_path_from_config: str) -> st
|
||||||
If not, a JrnlException is raised.
|
If not, a JrnlException is raised.
|
||||||
"""
|
"""
|
||||||
logging.debug(
|
logging.debug(
|
||||||
"Write mode: Either a template arg was passed, or the global config is set."
|
"Append mode: Either a template arg was passed, or the global config is set."
|
||||||
)
|
)
|
||||||
|
|
||||||
# If filename is unset, we are in this flow due to a global template being configured
|
# If filename is unset, we are in this flow due to a global template being configured
|
||||||
if not template_arg:
|
if not template_arg:
|
||||||
logging.debug("Write mode: Global template configuration detected.")
|
logging.debug("Append mode: Global template configuration detected.")
|
||||||
global_template_path = absolute_path(template_path_from_config)
|
global_template_path = absolute_path(template_path_from_config)
|
||||||
try:
|
try:
|
||||||
with open(global_template_path, encoding="utf-8") as f:
|
with open(global_template_path, encoding="utf-8") as f:
|
||||||
|
@ -162,7 +168,7 @@ def _read_template_file(template_arg: str, template_path_from_config: str) -> st
|
||||||
else: # A template CLI arg was passed.
|
else: # A template CLI arg was passed.
|
||||||
logging.debug("Trying to load template from $XDG_DATA_HOME/jrnl/templates/")
|
logging.debug("Trying to load template from $XDG_DATA_HOME/jrnl/templates/")
|
||||||
jrnl_template_dir = get_templates_path()
|
jrnl_template_dir = get_templates_path()
|
||||||
logging.debug(f"Write mode: jrnl templates directory: {jrnl_template_dir}")
|
logging.debug(f"Append mode: jrnl templates directory: {jrnl_template_dir}")
|
||||||
template_path = jrnl_template_dir / template_arg
|
template_path = jrnl_template_dir / template_arg
|
||||||
try:
|
try:
|
||||||
with open(template_path, encoding="utf-8") as f:
|
with open(template_path, encoding="utf-8") as f:
|
||||||
|
@ -192,7 +198,7 @@ def _read_template_file(template_arg: str, template_path_from_config: str) -> st
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def write_mode(args: "Namespace", config: dict, journal: Journal, **kwargs) -> None:
|
def append_mode(args: "Namespace", config: dict, journal: "Journal", **kwargs) -> None:
|
||||||
"""
|
"""
|
||||||
Gets input from the user to write to the journal
|
Gets input from the user to write to the journal
|
||||||
0. Check for a template passed as an argument, or in the global config
|
0. Check for a template passed as an argument, or in the global config
|
||||||
|
@ -202,35 +208,35 @@ def write_mode(args: "Namespace", config: dict, journal: Journal, **kwargs) -> N
|
||||||
4. Use stdin.read as last resort
|
4. Use stdin.read as last resort
|
||||||
6. Write any found text to journal, or exit
|
6. Write any found text to journal, or exit
|
||||||
"""
|
"""
|
||||||
logging.debug("Write mode: starting")
|
logging.debug("Append mode: starting")
|
||||||
|
|
||||||
if args.template or config["template"]:
|
if args.template or config["template"]:
|
||||||
logging.debug(f"Write mode: template CLI arg detected: {args.template}")
|
logging.debug(f"Append mode: template CLI arg detected: {args.template}")
|
||||||
# Read template file and pass as raw text into the composer
|
# Read template file and pass as raw text into the composer
|
||||||
template_data = _read_template_file(args.template, config["template"])
|
template_data = _read_template_file(args.template, config["template"])
|
||||||
raw = _write_in_editor(config, template_data)
|
raw = _write_in_editor(config, template_data)
|
||||||
if raw == template_data:
|
if raw == template_data:
|
||||||
logging.error("Write mode: raw text was the same as the template")
|
logging.error("Append mode: raw text was the same as the template")
|
||||||
raise JrnlException(Message(MsgText.NoChangesToTemplate, MsgStyle.NORMAL))
|
raise JrnlException(Message(MsgText.NoChangesToTemplate, MsgStyle.NORMAL))
|
||||||
elif args.text:
|
elif args.text:
|
||||||
logging.debug(f"Write mode: cli text detected: {args.text}")
|
logging.debug(f"Append mode: cli text detected: {args.text}")
|
||||||
raw = " ".join(args.text).strip()
|
raw = " ".join(args.text).strip()
|
||||||
if args.edit:
|
if args.edit:
|
||||||
raw = _write_in_editor(config, raw)
|
raw = _write_in_editor(config, raw)
|
||||||
|
|
||||||
elif not sys.stdin.isatty():
|
elif not sys.stdin.isatty():
|
||||||
logging.debug("Write mode: receiving piped text")
|
logging.debug("Append mode: receiving piped text")
|
||||||
raw = sys.stdin.read()
|
raw = sys.stdin.read()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raw = _write_in_editor(config)
|
raw = _write_in_editor(config)
|
||||||
|
|
||||||
if not raw or raw.isspace():
|
if not raw or raw.isspace():
|
||||||
logging.error("Write mode: couldn't get raw text or entry was empty")
|
logging.error("Append mode: couldn't get raw text or entry was empty")
|
||||||
raise JrnlException(Message(MsgText.NoTextReceived, MsgStyle.NORMAL))
|
raise JrnlException(Message(MsgText.NoTextReceived, MsgStyle.NORMAL))
|
||||||
|
|
||||||
logging.debug(
|
logging.debug(
|
||||||
'Write mode: appending raw text to journal "%s": %s', args.journal_name, raw
|
f"Append mode: appending raw text to journal '{args.journal_name}': {raw}"
|
||||||
)
|
)
|
||||||
journal.new_entry(raw)
|
journal.new_entry(raw)
|
||||||
if args.journal_name != DEFAULT_JOURNAL_KEY:
|
if args.journal_name != DEFAULT_JOURNAL_KEY:
|
||||||
|
@ -242,66 +248,28 @@ def write_mode(args: "Namespace", config: dict, journal: Journal, **kwargs) -> N
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
journal.write()
|
journal.write()
|
||||||
logging.debug("Write mode: completed journal.write()")
|
logging.debug("Append mode: completed journal.write()")
|
||||||
|
|
||||||
|
|
||||||
def search_mode(args: "Namespace", journal: Journal, **kwargs) -> None:
|
def search_mode(args: "Namespace", journal: "Journal", **kwargs) -> None:
|
||||||
"""
|
"""
|
||||||
Search for entries in a journal, then either:
|
Search for entries in a journal, and return the
|
||||||
1. Send them to configured editor for user manipulation (and also
|
results. If no search args, then return all results
|
||||||
change their timestamps if requested)
|
|
||||||
2. Change their timestamps
|
|
||||||
2. Delete them (with confirmation for each entry)
|
|
||||||
3. Display them (with formatting options)
|
|
||||||
"""
|
"""
|
||||||
kwargs = {
|
logging.debug("Search mode: starting")
|
||||||
**kwargs,
|
|
||||||
"args": args,
|
|
||||||
"journal": journal,
|
|
||||||
"old_entries": journal.entries,
|
|
||||||
}
|
|
||||||
|
|
||||||
if _has_search_args(args):
|
# If no search args, then return all results (don't filter anything)
|
||||||
_filter_journal_entries(**kwargs)
|
if not _has_search_args(args) and not _has_display_args(args) and not args.text:
|
||||||
_print_entries_found_count(len(journal), args)
|
logging.debug("Search mode: has no search args")
|
||||||
|
|
||||||
# Where do the search results go?
|
|
||||||
if args.edit:
|
|
||||||
# If we want to both edit and change time in one action
|
|
||||||
if args.change_time:
|
|
||||||
# Generate a new list instead of assigning so it won't be
|
|
||||||
# modified by _change_time_search_results
|
|
||||||
selected_entries = [e for e in journal.entries]
|
|
||||||
|
|
||||||
no_change_time_prompt = len(journal.entries) == 1
|
|
||||||
_change_time_search_results(no_prompt=no_change_time_prompt, **kwargs)
|
|
||||||
|
|
||||||
# Re-filter the journal enties (_change_time_search_results
|
|
||||||
# puts the filtered entries back); use selected_entries
|
|
||||||
# instead of running _search_journal again, because times
|
|
||||||
# have changed since the original search
|
|
||||||
kwargs["old_entries"] = journal.entries
|
|
||||||
journal.entries = selected_entries
|
|
||||||
|
|
||||||
_edit_search_results(**kwargs)
|
|
||||||
|
|
||||||
elif not journal:
|
|
||||||
# Bail out if there are no entries and we're not editing
|
|
||||||
return
|
return
|
||||||
|
|
||||||
elif args.change_time:
|
logging.debug("Search mode: has search args")
|
||||||
_change_time_search_results(**kwargs)
|
_filter_journal_entries(args, journal)
|
||||||
|
|
||||||
elif args.delete:
|
|
||||||
_delete_search_results(**kwargs)
|
|
||||||
|
|
||||||
else:
|
|
||||||
_display_search_results(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def _write_in_editor(config: dict, prepopulated_text: str | None = None) -> str:
|
def _write_in_editor(config: dict, prepopulated_text: str | None = None) -> str:
|
||||||
if config["editor"]:
|
if config["editor"]:
|
||||||
logging.debug("Write mode: opening editor")
|
logging.debug("Append mode: opening editor")
|
||||||
raw = get_text_from_editor(config, prepopulated_text)
|
raw = get_text_from_editor(config, prepopulated_text)
|
||||||
else:
|
else:
|
||||||
raw = get_text_from_stdin()
|
raw = get_text_from_stdin()
|
||||||
|
@ -309,30 +277,7 @@ def _write_in_editor(config: dict, prepopulated_text: str | None = None) -> str:
|
||||||
return raw
|
return raw
|
||||||
|
|
||||||
|
|
||||||
def _has_search_args(args: "Namespace") -> bool:
|
def _filter_journal_entries(args: "Namespace", journal: "Journal", **kwargs) -> None:
|
||||||
return any(
|
|
||||||
(
|
|
||||||
args.on_date,
|
|
||||||
args.today_in_history,
|
|
||||||
args.text,
|
|
||||||
args.month,
|
|
||||||
args.day,
|
|
||||||
args.year,
|
|
||||||
args.start_date,
|
|
||||||
args.end_date,
|
|
||||||
args.strict,
|
|
||||||
args.starred,
|
|
||||||
args.tagged,
|
|
||||||
args.excluded,
|
|
||||||
args.exclude_starred,
|
|
||||||
args.exclude_tagged,
|
|
||||||
args.contains,
|
|
||||||
args.limit,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _filter_journal_entries(args: "Namespace", journal: Journal, **kwargs) -> None:
|
|
||||||
"""Filter journal entries in-place based upon search args"""
|
"""Filter journal entries in-place based upon search args"""
|
||||||
if args.on_date:
|
if args.on_date:
|
||||||
args.start_date = args.end_date = args.on_date
|
args.start_date = args.end_date = args.on_date
|
||||||
|
@ -361,6 +306,7 @@ def _filter_journal_entries(args: "Namespace", journal: Journal, **kwargs) -> No
|
||||||
|
|
||||||
|
|
||||||
def _print_entries_found_count(count: int, args: "Namespace") -> None:
|
def _print_entries_found_count(count: int, args: "Namespace") -> None:
|
||||||
|
logging.debug(f"count: {count}")
|
||||||
if count == 0:
|
if count == 0:
|
||||||
if args.edit or args.change_time:
|
if args.edit or args.change_time:
|
||||||
print_msg(Message(MsgText.NothingToModify, MsgStyle.WARNING))
|
print_msg(Message(MsgText.NothingToModify, MsgStyle.WARNING))
|
||||||
|
@ -368,26 +314,26 @@ def _print_entries_found_count(count: int, args: "Namespace") -> None:
|
||||||
print_msg(Message(MsgText.NothingToDelete, MsgStyle.WARNING))
|
print_msg(Message(MsgText.NothingToDelete, MsgStyle.WARNING))
|
||||||
else:
|
else:
|
||||||
print_msg(Message(MsgText.NoEntriesFound, MsgStyle.NORMAL))
|
print_msg(Message(MsgText.NoEntriesFound, MsgStyle.NORMAL))
|
||||||
elif args.limit:
|
|
||||||
# Don't show count if the user expects a limited number of results
|
|
||||||
return
|
return
|
||||||
elif args.edit or not (args.change_time or args.delete):
|
elif args.limit and args.limit == count:
|
||||||
# Don't show count if we are ONLY changing the time or deleting entries
|
# Don't show count if the user expects a limited number of results
|
||||||
my_msg = (
|
logging.debug("args.limit is true-ish")
|
||||||
MsgText.EntryFoundCountSingular
|
return
|
||||||
if count == 1
|
|
||||||
else MsgText.EntryFoundCountPlural
|
logging.debug("Printing general summary")
|
||||||
)
|
my_msg = (
|
||||||
print_msg(Message(my_msg, MsgStyle.NORMAL, {"num": count}))
|
MsgText.EntryFoundCountSingular if count == 1 else MsgText.EntryFoundCountPlural
|
||||||
|
)
|
||||||
|
print_msg(Message(my_msg, MsgStyle.NORMAL, {"num": count}))
|
||||||
|
|
||||||
|
|
||||||
def _other_entries(journal: Journal, entries: list["Entry"]) -> list["Entry"]:
|
def _other_entries(journal: "Journal", entries: list["Entry"]) -> list["Entry"]:
|
||||||
"""Find entries that are not in journal"""
|
"""Find entries that are not in journal"""
|
||||||
return [e for e in entries if e not in journal.entries]
|
return [e for e in entries if e not in journal.entries]
|
||||||
|
|
||||||
|
|
||||||
def _edit_search_results(
|
def _edit_search_results(
|
||||||
config: dict, journal: Journal, old_entries: list["Entry"], **kwargs
|
config: dict, journal: "Journal", old_entries: list["Entry"], **kwargs
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
1. Send the given journal entries to the user-configured editor
|
1. Send the given journal entries to the user-configured editor
|
||||||
|
@ -406,15 +352,18 @@ def _edit_search_results(
|
||||||
# separate entries we are not editing
|
# separate entries we are not editing
|
||||||
other_entries = _other_entries(journal, old_entries)
|
other_entries = _other_entries(journal, old_entries)
|
||||||
|
|
||||||
# Get stats now for summary later
|
|
||||||
old_stats = _get_predit_stats(journal)
|
|
||||||
|
|
||||||
# Send user to the editor
|
# Send user to the editor
|
||||||
edited = get_text_from_editor(config, journal.editable_str())
|
try:
|
||||||
journal.parse_editable_str(edited)
|
edited = get_text_from_editor(config, journal.editable_str())
|
||||||
|
except JrnlException as e:
|
||||||
|
if e.has_message_text(MsgText.NoTextReceived):
|
||||||
|
raise JrnlException(
|
||||||
|
Message(MsgText.NoEditsReceivedJournalNotDeleted, MsgStyle.WARNING)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
# Print summary if available
|
journal.parse_editable_str(edited)
|
||||||
_print_edited_summary(journal, old_stats)
|
|
||||||
|
|
||||||
# Put back entries we separated earlier, sort, and write the journal
|
# Put back entries we separated earlier, sort, and write the journal
|
||||||
journal.entries += other_entries
|
journal.entries += other_entries
|
||||||
|
@ -422,15 +371,8 @@ def _edit_search_results(
|
||||||
journal.write()
|
journal.write()
|
||||||
|
|
||||||
|
|
||||||
def _print_edited_summary(
|
def _print_changed_counts(journal: "Journal", **kwargs) -> None:
|
||||||
journal: Journal, old_stats: dict[str, int], **kwargs
|
stats = journal.get_change_counts()
|
||||||
) -> None:
|
|
||||||
stats = {
|
|
||||||
"added": len(journal) - old_stats["count"],
|
|
||||||
"deleted": old_stats["count"] - len(journal),
|
|
||||||
"modified": len([e for e in journal.entries if e.modified]),
|
|
||||||
}
|
|
||||||
stats["modified"] -= stats["added"]
|
|
||||||
msgs = []
|
msgs = []
|
||||||
|
|
||||||
if stats["added"] > 0:
|
if stats["added"] > 0:
|
||||||
|
@ -463,17 +405,18 @@ def _print_edited_summary(
|
||||||
print_msgs(msgs)
|
print_msgs(msgs)
|
||||||
|
|
||||||
|
|
||||||
def _get_predit_stats(journal: Journal) -> dict[str, int]:
|
def _get_predit_stats(journal: "Journal") -> dict[str, int]:
|
||||||
return {"count": len(journal)}
|
return {"count": len(journal)}
|
||||||
|
|
||||||
|
|
||||||
def _delete_search_results(
|
def _delete_search_results(
|
||||||
journal: Journal, old_entries: list["Entry"], **kwargs
|
journal: "Journal", old_entries: list["Entry"], **kwargs
|
||||||
) -> None:
|
) -> None:
|
||||||
entries_to_delete = journal.prompt_action_entries(MsgText.DeleteEntryQuestion)
|
entries_to_delete = journal.prompt_action_entries(MsgText.DeleteEntryQuestion)
|
||||||
|
|
||||||
|
journal.entries = old_entries
|
||||||
|
|
||||||
if entries_to_delete:
|
if entries_to_delete:
|
||||||
journal.entries = old_entries
|
|
||||||
journal.delete_entries(entries_to_delete)
|
journal.delete_entries(entries_to_delete)
|
||||||
|
|
||||||
journal.write()
|
journal.write()
|
||||||
|
@ -481,34 +424,27 @@ def _delete_search_results(
|
||||||
|
|
||||||
def _change_time_search_results(
|
def _change_time_search_results(
|
||||||
args: "Namespace",
|
args: "Namespace",
|
||||||
journal: Journal,
|
journal: "Journal",
|
||||||
old_entries: list["Entry"],
|
old_entries: list["Entry"],
|
||||||
no_prompt: bool = False,
|
no_prompt: bool = False,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> None:
|
) -> None:
|
||||||
# separate entries we are not editing
|
# separate entries we are not editing
|
||||||
other_entries = _other_entries(journal, old_entries)
|
# @todo if there's only 1, don't prompt
|
||||||
|
entries_to_change = journal.prompt_action_entries(MsgText.ChangeTimeEntryQuestion)
|
||||||
if no_prompt:
|
|
||||||
entries_to_change = journal.entries
|
|
||||||
else:
|
|
||||||
entries_to_change = journal.prompt_action_entries(
|
|
||||||
MsgText.ChangeTimeEntryQuestion
|
|
||||||
)
|
|
||||||
|
|
||||||
if entries_to_change:
|
if entries_to_change:
|
||||||
other_entries += [e for e in journal.entries if e not in entries_to_change]
|
|
||||||
journal.entries = entries_to_change
|
|
||||||
|
|
||||||
date = time.parse(args.change_time)
|
date = time.parse(args.change_time)
|
||||||
journal.change_date_entries(date)
|
journal.entries = old_entries
|
||||||
|
journal.change_date_entries(date, entries_to_change)
|
||||||
|
|
||||||
journal.entries += other_entries
|
|
||||||
journal.sort()
|
|
||||||
journal.write()
|
journal.write()
|
||||||
|
|
||||||
|
|
||||||
def _display_search_results(args: "Namespace", journal: Journal, **kwargs) -> None:
|
def _display_search_results(args: "Namespace", journal: "Journal", **kwargs) -> None:
|
||||||
|
if len(journal) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
# Get export format from config file if not provided at the command line
|
# Get export format from config file if not provided at the command line
|
||||||
args.export = args.export or kwargs["config"].get("display_format")
|
args.export = args.export or kwargs["config"].get("display_format")
|
||||||
|
|
||||||
|
@ -526,3 +462,50 @@ def _display_search_results(args: "Namespace", journal: Journal, **kwargs) -> No
|
||||||
print(exporter.export(journal, args.filename))
|
print(exporter.export(journal, args.filename))
|
||||||
else:
|
else:
|
||||||
print(journal.pprint())
|
print(journal.pprint())
|
||||||
|
|
||||||
|
|
||||||
|
def _has_search_args(args: "Namespace") -> bool:
|
||||||
|
"""Looking for arguments that filter a journal"""
|
||||||
|
return any(
|
||||||
|
(
|
||||||
|
args.contains,
|
||||||
|
args.tagged,
|
||||||
|
args.excluded,
|
||||||
|
args.exclude_starred,
|
||||||
|
args.exclude_tagged,
|
||||||
|
args.end_date,
|
||||||
|
args.today_in_history,
|
||||||
|
args.month,
|
||||||
|
args.day,
|
||||||
|
args.year,
|
||||||
|
args.limit,
|
||||||
|
args.on_date,
|
||||||
|
args.starred,
|
||||||
|
args.start_date,
|
||||||
|
args.strict, # -and
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _has_action_args(args: "Namespace") -> bool:
|
||||||
|
return any(
|
||||||
|
(
|
||||||
|
args.change_time,
|
||||||
|
args.delete,
|
||||||
|
args.edit,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _has_display_args(args: "Namespace") -> bool:
|
||||||
|
return any(
|
||||||
|
(
|
||||||
|
args.tags,
|
||||||
|
args.short,
|
||||||
|
args.export, # --format
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _has_only_tags(tag_symbols: str, args_text: str) -> bool:
|
||||||
|
return all(word[0] in tag_symbols for word in " ".join(args_text).split())
|
||||||
|
|
|
@ -66,7 +66,7 @@ def get_text_from_stdin() -> str:
|
||||||
try:
|
try:
|
||||||
raw = sys.stdin.read()
|
raw = sys.stdin.read()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logging.error("Write mode: keyboard interrupt")
|
logging.error("Append mode: keyboard interrupt")
|
||||||
raise JrnlException(
|
raise JrnlException(
|
||||||
Message(MsgText.KeyboardInterruptMsg, MsgStyle.ERROR_ON_NEW_LINE),
|
Message(MsgText.KeyboardInterruptMsg, MsgStyle.ERROR_ON_NEW_LINE),
|
||||||
Message(MsgText.JournalNotSaved, MsgStyle.WARNING),
|
Message(MsgText.JournalNotSaved, MsgStyle.WARNING),
|
||||||
|
|
|
@ -7,6 +7,7 @@ from jrnl.output import print_msg
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from jrnl.messages import Message
|
from jrnl.messages import Message
|
||||||
|
from jrnl.messages import MsgText
|
||||||
|
|
||||||
|
|
||||||
class JrnlException(Exception):
|
class JrnlException(Exception):
|
||||||
|
@ -18,3 +19,6 @@ class JrnlException(Exception):
|
||||||
def print(self) -> None:
|
def print(self) -> None:
|
||||||
for msg in self.messages:
|
for msg in self.messages:
|
||||||
print_msg(msg)
|
print_msg(msg)
|
||||||
|
|
||||||
|
def has_message_text(self, message_text: "MsgText"):
|
||||||
|
return any([m.text == message_text for m in self.messages])
|
||||||
|
|
|
@ -91,17 +91,19 @@ class Folder(Journal):
|
||||||
for entry in entries_to_delete:
|
for entry in entries_to_delete:
|
||||||
self.entries.remove(entry)
|
self.entries.remove(entry)
|
||||||
self._diff_entry_dates.append(entry.date)
|
self._diff_entry_dates.append(entry.date)
|
||||||
|
self.deleted_entry_count += 1
|
||||||
|
|
||||||
def change_date_entries(self, date: str) -> None:
|
def change_date_entries(self, date: str, entries_to_change: list["Entry"]) -> None:
|
||||||
"""Changes entry dates to given date."""
|
"""Changes entry dates to given date."""
|
||||||
|
|
||||||
date = time.parse(date)
|
date = time.parse(date)
|
||||||
|
|
||||||
self._diff_entry_dates.append(date)
|
self._diff_entry_dates.append(date)
|
||||||
|
|
||||||
for entry in self.entries:
|
for entry in entries_to_change:
|
||||||
self._diff_entry_dates.append(entry.date)
|
self._diff_entry_dates.append(entry.date)
|
||||||
entry.date = date
|
entry.date = date
|
||||||
|
entry.modified = True
|
||||||
|
|
||||||
def parse_editable_str(self, edited: str) -> None:
|
def parse_editable_str(self, edited: str) -> None:
|
||||||
"""Parses the output of self.editable_str and updates its entries."""
|
"""Parses the output of self.editable_str and updates its entries."""
|
||||||
|
@ -114,4 +116,6 @@ class Folder(Journal):
|
||||||
# modified and how many got deleted later.
|
# modified and how many got deleted later.
|
||||||
for entry in mod_entries:
|
for entry in mod_entries:
|
||||||
entry.modified = not any(entry == old_entry for old_entry in self.entries)
|
entry.modified = not any(entry == old_entry for old_entry in self.entries)
|
||||||
|
|
||||||
|
self.increment_change_counts_by_edit(mod_entries)
|
||||||
self.entries = mod_entries
|
self.entries = mod_entries
|
||||||
|
|
|
@ -51,6 +51,10 @@ class Journal:
|
||||||
self.entries = []
|
self.entries = []
|
||||||
self.encryption_method = None
|
self.encryption_method = None
|
||||||
|
|
||||||
|
# Track changes to journal in session. Modified is tracked in Entry
|
||||||
|
self.added_entry_count = 0
|
||||||
|
self.deleted_entry_count = 0
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
"""Returns the number of entries"""
|
"""Returns the number of entries"""
|
||||||
return len(self.entries)
|
return len(self.entries)
|
||||||
|
@ -305,13 +309,17 @@ class Journal:
|
||||||
"""Deletes specific entries from a journal."""
|
"""Deletes specific entries from a journal."""
|
||||||
for entry in entries_to_delete:
|
for entry in entries_to_delete:
|
||||||
self.entries.remove(entry)
|
self.entries.remove(entry)
|
||||||
|
self.deleted_entry_count += 1
|
||||||
|
|
||||||
def change_date_entries(self, date: datetime.datetime | None) -> None:
|
def change_date_entries(
|
||||||
|
self, date: datetime.datetime, entries_to_change: list[Entry]
|
||||||
|
) -> None:
|
||||||
"""Changes entry dates to given date."""
|
"""Changes entry dates to given date."""
|
||||||
date = time.parse(date)
|
date = time.parse(date)
|
||||||
|
|
||||||
for entry in self.entries:
|
for entry in entries_to_change:
|
||||||
entry.date = date
|
entry.date = date
|
||||||
|
entry.modified = True
|
||||||
|
|
||||||
def prompt_action_entries(self, msg: MsgText) -> list[Entry]:
|
def prompt_action_entries(self, msg: MsgText) -> list[Entry]:
|
||||||
"""Prompts for action for each entry in a journal, using given message.
|
"""Prompts for action for each entry in a journal, using given message.
|
||||||
|
@ -383,8 +391,24 @@ class Journal:
|
||||||
# modified and how many got deleted later.
|
# modified and how many got deleted later.
|
||||||
for entry in mod_entries:
|
for entry in mod_entries:
|
||||||
entry.modified = not any(entry == old_entry for old_entry in self.entries)
|
entry.modified = not any(entry == old_entry for old_entry in self.entries)
|
||||||
|
|
||||||
|
self.increment_change_counts_by_edit(mod_entries)
|
||||||
|
|
||||||
self.entries = mod_entries
|
self.entries = mod_entries
|
||||||
|
|
||||||
|
def increment_change_counts_by_edit(self, mod_entries: Entry) -> None:
|
||||||
|
if len(mod_entries) > len(self.entries):
|
||||||
|
self.added_entry_count += len(mod_entries) - len(self.entries)
|
||||||
|
else:
|
||||||
|
self.deleted_entry_count += len(self.entries) - len(mod_entries)
|
||||||
|
|
||||||
|
def get_change_counts(self) -> dict:
|
||||||
|
return {
|
||||||
|
"added": self.added_entry_count,
|
||||||
|
"deleted": self.deleted_entry_count,
|
||||||
|
"modified": len([e for e in self.entries if e.modified]),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class LegacyJournal(Journal):
|
class LegacyJournal(Journal):
|
||||||
"""Legacy class to support opening journals formatted with the jrnl 1.x
|
"""Legacy class to support opening journals formatted with the jrnl 1.x
|
||||||
|
@ -444,7 +468,7 @@ def open_journal(journal_name: str, config: dict, legacy: bool = False) -> Journ
|
||||||
If legacy is True, it will open Journals with legacy classes build for
|
If legacy is True, it will open Journals with legacy classes build for
|
||||||
backwards compatibility with jrnl 1.x
|
backwards compatibility with jrnl 1.x
|
||||||
"""
|
"""
|
||||||
logging.debug("open_journal start")
|
logging.debug(f"open_journal '{journal_name}'")
|
||||||
validate_journal_name(journal_name, config)
|
validate_journal_name(journal_name, config)
|
||||||
config = config.copy()
|
config = config.copy()
|
||||||
config["journal"] = expand_path(config["journal"])
|
config["journal"] = expand_path(config["journal"])
|
||||||
|
|
|
@ -165,6 +165,14 @@ class MsgText(Enum):
|
||||||
https://jrnl.sh/en/stable/external-editors/
|
https://jrnl.sh/en/stable/external-editors/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
NoEditsReceivedJournalNotDeleted = """
|
||||||
|
No text received from editor. Were you trying to delete all the entries?
|
||||||
|
|
||||||
|
This seems a bit drastic, so the operation was cancelled.
|
||||||
|
|
||||||
|
To delete all entries, use the --delete option.
|
||||||
|
"""
|
||||||
|
|
||||||
NoEditsReceived = "No edits to save, because nothing was changed"
|
NoEditsReceived = "No edits to save, because nothing was changed"
|
||||||
|
|
||||||
NoTextReceived = """
|
NoTextReceived = """
|
||||||
|
|
108
tests/bdd/features/actions.feature
Normal file
108
tests/bdd/features/actions.feature
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
# Copyright © 2012-2023 jrnl contributors
|
||||||
|
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
|
Feature: Test combinations of edit, change-time, and delete
|
||||||
|
|
||||||
|
Scenario Outline: --change-time with --edit modifies selected entries
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we write nothing to the editor if opened
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' --edit" and enter
|
||||||
|
Y
|
||||||
|
N
|
||||||
|
Y
|
||||||
|
Then the error output should contain "No text received from editor. Were you trying to delete all the entries?"
|
||||||
|
And the editor should have been called
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2022-04-23 10:30 Entry the first.
|
||||||
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
Scenario Outline: --delete with --edit deletes selected entries
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we append to the editor if opened
|
||||||
|
[2023-02-21 10:32] Here is a new entry
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl --delete --edit" and enter
|
||||||
|
Y
|
||||||
|
N
|
||||||
|
Y
|
||||||
|
Then the editor should have been called
|
||||||
|
And the error output should contain "3 entries found"
|
||||||
|
And the error output should contain "2 entries deleted"
|
||||||
|
And the error output should contain "1 entry added"
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the error output should contain "2 entries found"
|
||||||
|
And the output should be
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2023-02-21 10:32 Here is a new entry
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
Scenario Outline: --change-time with --delete affects appropriate entries
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
# --change-time is asked first, then --delete
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' --delete" and enter
|
||||||
|
N
|
||||||
|
N
|
||||||
|
Y
|
||||||
|
Y
|
||||||
|
N
|
||||||
|
N
|
||||||
|
Then the error output should contain "3 entries found"
|
||||||
|
And the error output should contain "1 entry deleted"
|
||||||
|
And the error output should contain "1 entry modified"
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
Scenario Outline: Combining --change-time and --delete and --edit affects appropriate entries
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we append to the editor if opened
|
||||||
|
[2023-02-21 10:32] Here is a new entry
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
# --change-time is asked first, then --delete, then --edit
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' --delete --edit" and enter
|
||||||
|
N
|
||||||
|
Y
|
||||||
|
Y
|
||||||
|
Y
|
||||||
|
Y
|
||||||
|
N
|
||||||
|
Then the error output should contain "3 entries found"
|
||||||
|
And the error output should contain "2 entries deleted"
|
||||||
|
And the error output should contain "1 entry modified" # only 1, because the other was deleted
|
||||||
|
And the error output should contain "1 entry added" # by edit
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
2023-02-21 10:32 Here is a new entry
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
|
@ -9,6 +9,8 @@ Feature: Change entry times in journal
|
||||||
Then the output should contain "2020-09-24 09:14 The third entry finally"
|
Then the output should contain "2020-09-24 09:14 The third entry finally"
|
||||||
When we run "jrnl -1 --change-time '2022-04-23 10:30'" and enter
|
When we run "jrnl -1 --change-time '2022-04-23 10:30'" and enter
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "1 entry modified"
|
||||||
|
And the error output should not contain "deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-29 11:11 Entry the first.
|
2020-08-29 11:11 Entry the first.
|
||||||
|
@ -34,6 +36,8 @@ Feature: Change entry times in journal
|
||||||
Y
|
Y
|
||||||
N
|
N
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "3 entries found"
|
||||||
|
And the error output should contain "2 entries modified"
|
||||||
When we run "jrnl --short"
|
When we run "jrnl --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
@ -48,10 +52,15 @@ Feature: Change entry times in journal
|
||||||
# | basic_dayone.yaml | @todo
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Change time flag with nonsense input changes nothing
|
Scenario Outline: Answering "N" to change-time prompt deletes no entries
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl --change-time now asdfasdf"
|
And we use the password "test" if prompted
|
||||||
Then the output should contain "No entries to modify"
|
When we run "jrnl -1"
|
||||||
|
Then the output should contain "2020-09-24 09:14 The third entry finally"
|
||||||
|
When we run "jrnl -1 --change-time '2023-02-21 10:30'" and enter
|
||||||
|
N
|
||||||
|
Then the error output should not contain "modified"
|
||||||
|
And the error output should not contain "deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-29 11:11 Entry the first.
|
2020-08-29 11:11 Entry the first.
|
||||||
|
@ -59,16 +68,40 @@ Feature: Change entry times in journal
|
||||||
2020-09-24 09:14 The third entry finally after weeks without writing.
|
2020-09-24 09:14 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
Examples: Configs
|
Examples: Configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| basic_onefile.yaml |
|
| basic_onefile.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_encrypted.yaml |
|
||||||
| basic_dayone.yaml |
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with nonsense input changes nothing
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl --change-time now asdfasdf"
|
||||||
|
Then the output should contain "No entries to modify"
|
||||||
|
And the error output should not contain "entries modified"
|
||||||
|
And the error output should not contain "entries deleted"
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then 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_encrypted.yaml |
|
||||||
|
| basic_dayone.yaml |
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Change time flag with tag only changes tagged entries
|
Scenario Outline: Change time flag with tag only changes tagged entries
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --change-time '2022-04-23 10:30' @ipsum" and enter
|
When we run "jrnl --change-time '2022-04-23 10:30' @ipsum" and enter
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "1 entry found"
|
||||||
|
And the error output should contain "1 entry modified"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
@ -76,14 +109,16 @@ Feature: Change entry times in journal
|
||||||
2022-04-23 10:30 Entry the first.
|
2022-04-23 10:30 Entry the first.
|
||||||
|
|
||||||
Examples: Configs
|
Examples: Configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| basic_onefile.yaml |
|
| basic_onefile.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
# | basic_dayone.yaml | @todo
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Change time flag with multiple tags changes all entries matching any of the tags
|
Scenario Outline: Change time flag with multiple tags changes all entries matching any of the tags
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --change-time '2022-04-23 10:30' @ipsum @tagthree" and enter
|
When we run "jrnl --change-time '2022-04-23 10:30' @ipsum @tagthree" and enter
|
||||||
Y
|
Y
|
||||||
Y
|
Y
|
||||||
|
@ -94,14 +129,16 @@ Feature: Change entry times in journal
|
||||||
2022-04-23 10:30 The third entry finally after weeks without writing.
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
Examples: Configs
|
Examples: Configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| basic_onefile.yaml |
|
| basic_onefile.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
# | basic_dayone.yaml | @todo
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Change time flag with -and changes boolean AND of tagged entries
|
Scenario Outline: Change time flag with -and changes boolean AND of tagged entries
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --change-time '2022-04-23 10:30' -and @tagone @tagtwo" and enter
|
When we run "jrnl --change-time '2022-04-23 10:30' -and @tagone @tagtwo" and enter
|
||||||
Y
|
Y
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
|
@ -111,14 +148,16 @@ Feature: Change entry times in journal
|
||||||
2022-04-23 10:30 Entry the first.
|
2022-04-23 10:30 Entry the first.
|
||||||
|
|
||||||
Examples: Configs
|
Examples: Configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| basic_onefile.yaml |
|
| basic_onefile.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
# | basic_dayone.yaml | @todo
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Change time flag with -not does not change entries from given tag
|
Scenario Outline: Change time flag with -not does not change entries from given tag
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --change-time '2022-04-23 10:30' @tagone -not @ipsum" and enter
|
When we run "jrnl --change-time '2022-04-23 10:30' @tagone -not @ipsum" and enter
|
||||||
Y
|
Y
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
|
@ -128,14 +167,16 @@ Feature: Change entry times in journal
|
||||||
2022-04-23 10:30 The third entry finally after weeks without writing.
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
Examples: Configs
|
Examples: Configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| basic_onefile.yaml |
|
| basic_onefile.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
# | basic_dayone.yaml | @todo
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Change time flag with -from search operator only changes entries since that date
|
Scenario Outline: Change time flag with -from search operator only changes entries since that date
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --change-time '2022-04-23 10:30' -from 2020-09-01" and enter
|
When we run "jrnl --change-time '2022-04-23 10:30' -from 2020-09-01" and enter
|
||||||
Y
|
Y
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
|
@ -145,14 +186,16 @@ Feature: Change entry times in journal
|
||||||
2022-04-23 10:30 The third entry finally after weeks without writing.
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
Examples: Configs
|
Examples: Configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| basic_onefile.yaml |
|
| basic_onefile.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
# | basic_dayone.yaml | @todo
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Change time flag with -to only changes entries up to specified date
|
Scenario Outline: Change time flag with -to only changes entries up to specified date
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --change-time '2022-04-23 10:30' -to 2020-08-31" and enter
|
When we run "jrnl --change-time '2022-04-23 10:30' -to 2020-08-31" and enter
|
||||||
Y
|
Y
|
||||||
Y
|
Y
|
||||||
|
@ -163,14 +206,16 @@ Feature: Change entry times in journal
|
||||||
2022-04-23 10:30 A second entry in what I hope to be a long series.
|
2022-04-23 10:30 A second entry in what I hope to be a long series.
|
||||||
|
|
||||||
Examples: Configs
|
Examples: Configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| basic_onefile.yaml |
|
| basic_onefile.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
# | basic_dayone.yaml | @todo
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Change time flag with -starred only changes starred entries
|
Scenario Outline: Change time flag with -starred only changes starred entries
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --change-time '2022-04-23 10:30' -starred" and enter
|
When we run "jrnl --change-time '2022-04-23 10:30' -starred" and enter
|
||||||
Y
|
Y
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
|
@ -180,16 +225,19 @@ Feature: Change entry times in journal
|
||||||
2022-04-23 10:30 A second entry in what I hope to be a long series.
|
2022-04-23 10:30 A second entry in what I hope to be a long series.
|
||||||
|
|
||||||
Examples: Configs
|
Examples: Configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| basic_onefile.yaml |
|
| basic_onefile.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
# | basic_dayone.yaml | @todo
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Change time flag with -contains only changes entries containing expression
|
Scenario Outline: Change time flag with -contains only changes entries containing expression
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --change-time '2022-04-23 10:30' -contains dignissim" and enter
|
When we run "jrnl --change-time '2022-04-23 10:30' -contains dignissim" and enter
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "1 entry modified"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
@ -197,13 +245,14 @@ Feature: Change entry times in journal
|
||||||
2022-04-23 10:30 Entry the first.
|
2022-04-23 10:30 Entry the first.
|
||||||
|
|
||||||
Examples: Configs
|
Examples: Configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| basic_onefile.yaml |
|
| basic_onefile.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
# | basic_dayone.yaml | @todo
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Change time flag with no enties specified changes nothing
|
Scenario Outline: Change time flag with no entries specified changes nothing
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
And we use the password "test" if prompted
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --change-time" and enter
|
When we run "jrnl --change-time" and enter
|
||||||
|
@ -217,30 +266,8 @@ Feature: Change entry times in journal
|
||||||
2020-09-24 09:14 The third entry finally after weeks without writing.
|
2020-09-24 09:14 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
Examples: Configs
|
Examples: Configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| basic_onefile.yaml |
|
| basic_onefile.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
| basic_dayone.yaml |
|
| basic_encrypted.yaml |
|
||||||
|
| basic_dayone.yaml |
|
||||||
|
|
||||||
Scenario Outline: --change-time with --edit modifies selected entries
|
|
||||||
Given we use the config "<config_file>"
|
|
||||||
And we write nothing to the editor if opened
|
|
||||||
And we use the password "test" if prompted
|
|
||||||
When we run "jrnl --change-time '2022-04-23 10:30' --edit" and enter
|
|
||||||
Y
|
|
||||||
N
|
|
||||||
Y
|
|
||||||
Then the error output should contain "No entry to save"
|
|
||||||
And the editor should have been called
|
|
||||||
When we run "jrnl -99 --short"
|
|
||||||
Then the output should be
|
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
|
||||||
2022-04-23 10:30 Entry the first.
|
|
||||||
2022-04-23 10:30 The third entry finally after weeks without writing.
|
|
||||||
|
|
||||||
Examples: Configs
|
|
||||||
| config_file |
|
|
||||||
| basic_onefile.yaml |
|
|
||||||
| basic_folder.yaml |
|
|
||||||
# | basic_dayone.yaml | @todo
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ Feature: Delete entries from journal
|
||||||
N
|
N
|
||||||
N
|
N
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "3 entries found"
|
||||||
|
And the error output should contain "1 entry deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-29 11:11 Entry the first.
|
2020-08-29 11:11 Entry the first.
|
||||||
|
@ -28,6 +30,7 @@ Feature: Delete entries from journal
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl --delete -n 1" and enter
|
When we run "jrnl --delete -n 1" and enter
|
||||||
N
|
N
|
||||||
|
Then the error output should not contain "deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-29 11:11 Entry the first.
|
2020-08-29 11:11 Entry the first.
|
||||||
|
@ -44,7 +47,7 @@ Feature: Delete entries from journal
|
||||||
Scenario Outline: Delete flag with nonsense input deletes nothing (issue #932)
|
Scenario Outline: Delete flag with nonsense input deletes nothing (issue #932)
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl --delete asdfasdf"
|
When we run "jrnl --delete asdfasdf"
|
||||||
Then the output should contain "No entries to delete"
|
Then the error output should contain "No entries to delete"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-29 11:11 Entry the first.
|
2020-08-29 11:11 Entry the first.
|
||||||
|
@ -62,6 +65,8 @@ Feature: Delete entries from journal
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl --delete @ipsum" and enter
|
When we run "jrnl --delete @ipsum" and enter
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "1 entry found"
|
||||||
|
Then the error output should contain "1 entry deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
@ -79,6 +84,8 @@ Feature: Delete entries from journal
|
||||||
When we run "jrnl --delete @ipsum @tagthree" and enter
|
When we run "jrnl --delete @ipsum @tagthree" and enter
|
||||||
Y
|
Y
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "2 entries found"
|
||||||
|
And the error output should contain "2 entries deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
@ -94,6 +101,8 @@ Feature: Delete entries from journal
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl --delete -and @tagone @tagtwo" and enter
|
When we run "jrnl --delete -and @tagone @tagtwo" and enter
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "1 entry found"
|
||||||
|
And the error output should contain "1 entry deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
@ -110,6 +119,8 @@ Feature: Delete entries from journal
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl --delete @tagone -not @ipsum" and enter
|
When we run "jrnl --delete @tagone -not @ipsum" and enter
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "1 entry found"
|
||||||
|
And the error output should contain "1 entry deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-29 11:11 Entry the first.
|
2020-08-29 11:11 Entry the first.
|
||||||
|
@ -126,6 +137,8 @@ Feature: Delete entries from journal
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl --delete -from 2020-09-01" and enter
|
When we run "jrnl --delete -from 2020-09-01" and enter
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "1 entry found"
|
||||||
|
And the error output should contain "1 entry deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-29 11:11 Entry the first.
|
2020-08-29 11:11 Entry the first.
|
||||||
|
@ -143,6 +156,8 @@ Feature: Delete entries from journal
|
||||||
When we run "jrnl --delete -to 2020-08-31" and enter
|
When we run "jrnl --delete -to 2020-08-31" and enter
|
||||||
Y
|
Y
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "2 entries found"
|
||||||
|
And the error output should contain "2 entries deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-09-24 09:14 The third entry finally after weeks without writing.
|
2020-09-24 09:14 The third entry finally after weeks without writing.
|
||||||
|
@ -158,6 +173,7 @@ Feature: Delete entries from journal
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl --delete -starred" and enter
|
When we run "jrnl --delete -starred" and enter
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "1 entry deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-29 11:11 Entry the first.
|
2020-08-29 11:11 Entry the first.
|
||||||
|
@ -174,6 +190,8 @@ Feature: Delete entries from journal
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
When we run "jrnl --delete -contains dignissim" and enter
|
When we run "jrnl --delete -contains dignissim" and enter
|
||||||
Y
|
Y
|
||||||
|
Then the error output should contain "1 entry found"
|
||||||
|
And the error output should contain "1 entry deleted"
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should be
|
Then the output should be
|
||||||
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
|
|
@ -372,3 +372,29 @@ Feature: Searching in a journal
|
||||||
2013-06-17 20:38 This entry has a location.
|
2013-06-17 20:38 This entry has a location.
|
||||||
|
|
||||||
2013-07-17 11:38 This entry is starred!
|
2013-07-17 11:38 This entry is starred!
|
||||||
|
|
||||||
|
Scenario Outline: Searching the most recent entry should not show found count
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl -1"
|
||||||
|
Then the error output should not contain "1 entry found"
|
||||||
|
|
||||||
|
Examples: configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
| basic_dayone.yaml |
|
||||||
|
|
||||||
|
Scenario Outline: Searching for more entries than are in the journal should show found count
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl -4"
|
||||||
|
Then the error output should contain "3 entries found"
|
||||||
|
|
||||||
|
Examples: configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
| basic_dayone.yaml |
|
||||||
|
|
|
@ -76,21 +76,21 @@ Feature: Writing new entries.
|
||||||
| basic_dayone.yaml |
|
| basic_dayone.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
|
|
||||||
Scenario Outline: Writing an empty entry from the editor should yield "No entry to save" message
|
Scenario Outline: Clearing the editor's contents should yield "No text received" message
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
And we write nothing to the editor if opened
|
And we write nothing to the editor if opened
|
||||||
And we use the password "test" if prompted
|
And we use the password "test" if prompted
|
||||||
When we run "jrnl --edit"
|
When we run "jrnl --edit"
|
||||||
Then the error output should contain "No entry to save, because no text was received"
|
Then the error output should contain "No text received from editor. Were you trying to delete all the entries?"
|
||||||
And the editor should have been called
|
And the editor should have been called
|
||||||
|
|
||||||
Examples: configs
|
Examples: configs
|
||||||
| config_file |
|
| config_file |
|
||||||
| editor.yaml |
|
| editor.yaml |
|
||||||
| editor_empty_folder.yaml |
|
| basic_onefile.yaml |
|
||||||
| dayone.yaml |
|
| basic_encrypted.yaml |
|
||||||
| basic_encrypted.yaml |
|
| basic_dayone.yaml |
|
||||||
| basic_onefile.yaml |
|
| basic_folder.yaml |
|
||||||
|
|
||||||
Scenario Outline: Writing an empty entry from the command line should yield "No entry to save" message
|
Scenario Outline: Writing an empty entry from the command line should yield "No entry to save" message
|
||||||
Given we use the config "<config_file>"
|
Given we use the config "<config_file>"
|
||||||
|
@ -236,7 +236,9 @@ Feature: Writing new entries.
|
||||||
And we append to the editor if opened
|
And we append to the editor if opened
|
||||||
[2021-11-13] worked on jrnl tests
|
[2021-11-13] worked on jrnl tests
|
||||||
When we run "jrnl --edit"
|
When we run "jrnl --edit"
|
||||||
Then the output should contain "1 entry added"
|
Then the error output should contain "3 entries found"
|
||||||
|
And the error output should contain "1 entry added"
|
||||||
|
|
||||||
|
|
||||||
Examples: configs
|
Examples: configs
|
||||||
| config_file |
|
| config_file |
|
||||||
|
@ -254,7 +256,8 @@ Feature: Writing new entries.
|
||||||
[2021-11-12] worked on jrnl tests again
|
[2021-11-12] worked on jrnl tests again
|
||||||
[2021-11-13] worked on jrnl tests a little bit more
|
[2021-11-13] worked on jrnl tests a little bit more
|
||||||
When we run "jrnl --edit"
|
When we run "jrnl --edit"
|
||||||
Then the error output should contain "3 entries added"
|
Then the error output should contain "3 entries found"
|
||||||
|
And the error output should contain "3 entries added"
|
||||||
|
|
||||||
Examples: configs
|
Examples: configs
|
||||||
| config_file |
|
| config_file |
|
||||||
|
@ -271,7 +274,7 @@ Feature: Writing new entries.
|
||||||
[2021-11-13] I am replacing my whole journal with this entry
|
[2021-11-13] I am replacing my whole journal with this entry
|
||||||
When we run "jrnl --edit"
|
When we run "jrnl --edit"
|
||||||
Then the output should contain "2 entries deleted"
|
Then the output should contain "2 entries deleted"
|
||||||
Then the output should contain "3 entries modified"
|
And the output should contain "1 entry modified"
|
||||||
|
|
||||||
Examples: configs
|
Examples: configs
|
||||||
| config_file |
|
| config_file |
|
||||||
|
@ -287,8 +290,7 @@ Feature: Writing new entries.
|
||||||
And we write to the editor if opened
|
And we write to the editor if opened
|
||||||
[2021-11-13] I am replacing the last entry with this entry
|
[2021-11-13] I am replacing the last entry with this entry
|
||||||
When we run "jrnl --edit -1"
|
When we run "jrnl --edit -1"
|
||||||
Then the output should contain
|
Then the error output should contain "1 entry modified"
|
||||||
1 entry modified
|
|
||||||
|
|
||||||
Examples: configs
|
Examples: configs
|
||||||
| config_file |
|
| config_file |
|
||||||
|
@ -304,8 +306,8 @@ Feature: Writing new entries.
|
||||||
And we append to the editor if opened
|
And we append to the editor if opened
|
||||||
This is a small addendum to my latest entry.
|
This is a small addendum to my latest entry.
|
||||||
When we run "jrnl --edit"
|
When we run "jrnl --edit"
|
||||||
Then the output should contain
|
Then the error output should contain "3 entries found"
|
||||||
1 entry modified
|
And the error output should contain "1 entry modified"
|
||||||
|
|
||||||
Examples: configs
|
Examples: configs
|
||||||
| config_file |
|
| config_file |
|
||||||
|
@ -341,6 +343,7 @@ Feature: Writing new entries.
|
||||||
And we append to the editor if opened
|
And we append to the editor if opened
|
||||||
@newtag
|
@newtag
|
||||||
When we run "jrnl --edit -1"
|
When we run "jrnl --edit -1"
|
||||||
|
Then the error output should contain "1 entry modified"
|
||||||
When we run "jrnl --tags @newtag"
|
When we run "jrnl --tags @newtag"
|
||||||
Then the output should contain
|
Then the output should contain
|
||||||
1 entry found
|
1 entry found
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
from pytest_bdd import scenarios
|
from pytest_bdd import scenarios
|
||||||
|
|
||||||
|
scenarios("features/actions.feature")
|
||||||
scenarios("features/build.feature")
|
scenarios("features/build.feature")
|
||||||
scenarios("features/config_file.feature")
|
scenarios("features/config_file.feature")
|
||||||
scenarios("features/core.feature")
|
scenarios("features/core.feature")
|
||||||
|
|
|
@ -125,7 +125,10 @@ def we_use_the_config(request, temp_dir, working_dir, config_file):
|
||||||
return config_dest
|
return config_dest
|
||||||
|
|
||||||
|
|
||||||
@given(parse('we copy the template "{template_file}" to the default templates folder'), target_fixture="default_templates_path")
|
@given(
|
||||||
|
parse('we copy the template "{template_file}" to the default templates folder'),
|
||||||
|
target_fixture="default_templates_path",
|
||||||
|
)
|
||||||
def we_copy_the_template(request, temp_dir, working_dir, template_file):
|
def we_copy_the_template(request, temp_dir, working_dir, template_file):
|
||||||
# Move into temp dir as cwd
|
# Move into temp dir as cwd
|
||||||
os.chdir(temp_dir.name) # @todo move this step to a more universal place
|
os.chdir(temp_dir.name) # @todo move this step to a more universal place
|
||||||
|
|
|
@ -197,12 +197,12 @@ def config_var_in_memory(config_in_memory, journal_name, it_should, some_yaml):
|
||||||
|
|
||||||
@then("we should be prompted for a password")
|
@then("we should be prompted for a password")
|
||||||
def password_was_called(cli_run):
|
def password_was_called(cli_run):
|
||||||
assert cli_run["mocks"]["user_input"].called
|
assert cli_run["mocks"]["user_input"].return_value.input.called
|
||||||
|
|
||||||
|
|
||||||
@then("we should not be prompted for a password")
|
@then("we should not be prompted for a password")
|
||||||
def password_was_not_called(cli_run):
|
def password_was_not_called(cli_run):
|
||||||
assert not cli_run["mocks"]["user_input"].called
|
assert not cli_run["mocks"]["user_input"].return_value.input.called
|
||||||
|
|
||||||
|
|
||||||
@then(parse("the cache directory should contain the files\n{file_list}"))
|
@then(parse("the cache directory should contain the files\n{file_list}"))
|
||||||
|
|
|
@ -18,15 +18,17 @@ def random_string():
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("export_format", ["pretty", "short"])
|
@pytest.mark.parametrize("export_format", ["pretty", "short"])
|
||||||
@mock.patch("builtins.print")
|
def test_display_search_results_pretty_short(export_format):
|
||||||
@mock.patch("jrnl.controller.Journal.pprint")
|
|
||||||
def test_display_search_results_pretty_short(mock_pprint, mock_print, export_format):
|
|
||||||
mock_args = parse_args(["--format", export_format])
|
mock_args = parse_args(["--format", export_format])
|
||||||
test_journal = mock.Mock(wraps=jrnl.journals.Journal)
|
|
||||||
|
test_journal = jrnl.journals.Journal()
|
||||||
|
test_journal.new_entry("asdf")
|
||||||
|
|
||||||
|
test_journal.pprint = mock.Mock()
|
||||||
|
|
||||||
_display_search_results(mock_args, test_journal)
|
_display_search_results(mock_args, test_journal)
|
||||||
|
|
||||||
mock_print.assert_called_once_with(mock_pprint.return_value)
|
test_journal.pprint.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
@ -40,7 +42,9 @@ def test_display_search_results_builtin_plugins(
|
||||||
test_filename = random_string
|
test_filename = random_string
|
||||||
mock_args = parse_args(["--format", export_format, "--file", test_filename])
|
mock_args = parse_args(["--format", export_format, "--file", test_filename])
|
||||||
|
|
||||||
test_journal = mock.Mock(wraps=jrnl.journals.Journal)
|
test_journal = jrnl.journals.Journal()
|
||||||
|
test_journal.new_entry("asdf")
|
||||||
|
|
||||||
mock_export = mock.Mock()
|
mock_export = mock.Mock()
|
||||||
mock_exporter.return_value.export = mock_export
|
mock_exporter.return_value.export = mock_export
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ def build_card_header(datestr):
|
||||||
|
|
||||||
class TestFancy:
|
class TestFancy:
|
||||||
def test_too_small_linewrap(self, datestr):
|
def test_too_small_linewrap(self, datestr):
|
||||||
|
|
||||||
journal = "test_journal"
|
journal = "test_journal"
|
||||||
content = build_card_header(datestr)
|
content = build_card_header(datestr)
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,6 @@ def test_get_kv_from_pair():
|
||||||
|
|
||||||
class TestDotNotationToList:
|
class TestDotNotationToList:
|
||||||
def test_unpack_dots_to_list(self):
|
def test_unpack_dots_to_list(self):
|
||||||
|
|
||||||
keys = "a.b.c.d.e.f"
|
keys = "a.b.c.d.e.f"
|
||||||
keys_list = _convert_dots_to_list(keys)
|
keys_list = _convert_dots_to_list(keys)
|
||||||
assert len(keys_list) == 6
|
assert len(keys_list) == 6
|
||||||
|
|
|
@ -230,7 +230,6 @@ def test_version_alone():
|
||||||
|
|
||||||
|
|
||||||
def test_editor_override():
|
def test_editor_override():
|
||||||
|
|
||||||
parsed_args = cli_as_dict('--config-override editor "nano"')
|
parsed_args = cli_as_dict('--config-override editor "nano"')
|
||||||
assert parsed_args == expected_args(config_override=[["editor", "nano"]])
|
assert parsed_args == expected_args(config_override=[["editor", "nano"]])
|
||||||
|
|
||||||
|
@ -294,7 +293,6 @@ class TestDeserialization:
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_deserialize_multiword_strings(self, input_str):
|
def test_deserialize_multiword_strings(self, input_str):
|
||||||
|
|
||||||
runtime_config = make_yaml_valid_dict(input_str)
|
runtime_config = make_yaml_valid_dict(input_str)
|
||||||
assert runtime_config.__class__ == dict
|
assert runtime_config.__class__ == dict
|
||||||
assert input_str[0] in runtime_config
|
assert input_str[0] in runtime_config
|
||||||
|
|
Loading…
Add table
Reference in a new issue