Skip to content

Commit

Permalink
Implement --change-time flag (#1452)
Browse files Browse the repository at this point in the history
* Implement --change-time flag
* Remove todo from --change-time bdd folder journal tests
* Add warning when --change-time used with no matching entries
* Add a test to make sure running --change-time with nothing prints a warning and doesn't change anything
* Add prompt for --change-time
* Don't prompt for --change-time when used with --edit and only one entry
* When using --edit and --change-time, change the time before editing
* Add test for --change-time used with --edit
* Modify failing --change-time test to conform to text in develop branch
  • Loading branch information
richardjs committed May 21, 2022
1 parent e6ed64a commit 33c9dce
Show file tree
Hide file tree
Showing 8 changed files with 342 additions and 12 deletions.
12 changes: 12 additions & 0 deletions jrnl/FolderJournal.py
Expand Up @@ -8,6 +8,7 @@
import os

from . import Journal
from . import time


def get_files(journal_config):
Expand Down Expand Up @@ -89,6 +90,17 @@ def delete_entries(self, entries_to_delete):
self.entries.remove(entry)
self._diff_entry_dates.append(entry.date)

def change_date_entries(self, date):
"""Changes entry dates to given date."""

date = time.parse(date)

self._diff_entry_dates.append(date)

for entry in self.entries:
self._diff_entry_dates.append(entry.date)
entry.date = date

def parse_editable_str(self, edited):
"""Parses the output of self.editable_str and updates its entries."""
mod_entries = self._parse(edited)
Expand Down
24 changes: 15 additions & 9 deletions jrnl/Journal.py
Expand Up @@ -261,23 +261,29 @@ def delete_entries(self, entries_to_delete):
for entry in entries_to_delete:
self.entries.remove(entry)

def prompt_delete_entries(self):
"""Prompts for deletion of each of the entries in a journal.
Returns the entries the user wishes to delete."""
def change_date_entries(self, date):
"""Changes entry dates to given date."""
date = time.parse(date)

to_delete = []
for entry in self.entries:
entry.date = date

def prompt_action_entries(self, message):
"""Prompts for action for each entry in a journal, using given message.
Returns the entries the user wishes to apply the action on."""
to_act = []

def ask_delete(entry):
def ask_action(entry):
return yesno(
f"Delete entry '{entry.pprint(short=True)}'?",
f"{message} '{entry.pprint(short=True)}'?",
default=False,
)

for entry in self.entries:
if ask_delete(entry):
to_delete.append(entry)
if ask_action(entry):
to_act.append(entry)

return to_delete
return to_act

def new_entry(self, raw, date=None, sort=True):
"""Constructs a new entry from some raw text input.
Expand Down
8 changes: 8 additions & 0 deletions jrnl/args.py
Expand Up @@ -267,6 +267,14 @@ def parse_args(args=[]):
action="store_true",
help="Interactively deletes selected entries",
)
exporting.add_argument(
"--change-time",
dest="change_time",
nargs="?",
metavar="DATE",
const="now",
help="Change timestamp for seleted entries (default: now)",
)
exporting.add_argument(
"--format",
metavar="TYPE",
Expand Down
57 changes: 54 additions & 3 deletions jrnl/jrnl.py
Expand Up @@ -79,6 +79,7 @@ def _is_write_mode(args, config, **kwargs):
args.contains,
args.delete,
args.edit,
args.change_time,
args.export,
args.end_date,
args.today_in_history,
Expand Down Expand Up @@ -150,7 +151,9 @@ def write_mode(args, config, journal, **kwargs):
def search_mode(args, journal, **kwargs):
"""
Search for entries in a journal, then either:
1. Send them to configured editor for user manipulation
1. Send them to configured editor for user manipulation (and also
change their timestamps if requested)
2. Change their timestamps
2. Delete them (with confirmation for each entry)
3. Display them (with formatting options)
"""
Expand All @@ -166,8 +169,27 @@ def search_mode(args, journal, **kwargs):

# 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 args.change_time:
_change_time_search_results(**kwargs)

elif args.delete:
_delete_search_results(**kwargs)

Expand Down Expand Up @@ -236,6 +258,11 @@ def _search_journal(args, journal, **kwargs):
journal.limit(args.limit)


def _other_entries(journal, entries):
"""Find entries that are not in journal"""
return [e for e in entries if e not in journal.entries]


def _edit_search_results(config, journal, old_entries, **kwargs):
"""
1. Send the given journal entries to the user-configured editor
Expand All @@ -252,7 +279,7 @@ def _edit_search_results(config, journal, old_entries, **kwargs):
)

# separate entries we are not editing
other_entries = [e for e in old_entries if e not in journal.entries]
other_entries = _other_entries(journal, old_entries)

# Get stats now for summary later
old_stats = _get_predit_stats(journal)
Expand Down Expand Up @@ -309,7 +336,7 @@ def _delete_search_results(journal, old_entries, **kwargs):
if not journal.entries:
raise JrnlException(Message(MsgText.NothingToDelete, MsgType.ERROR))

entries_to_delete = journal.prompt_delete_entries()
entries_to_delete = journal.prompt_action_entries("Delete entry")

if entries_to_delete:
journal.entries = old_entries
Expand All @@ -318,6 +345,30 @@ def _delete_search_results(journal, old_entries, **kwargs):
journal.write()


def _change_time_search_results(args, journal, old_entries, no_prompt=False, **kwargs):
if not journal.entries:
raise JrnlException(Message(MsgText.NothingToModify, MsgType.WARNING))

# separate entries we are not editing
other_entries = _other_entries(journal, old_entries)

if no_prompt:
entries_to_change = journal.entries
else:
entries_to_change = journal.prompt_action_entries("Change time")

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)
journal.change_date_entries(date)

journal.entries += other_entries
journal.sort()
journal.write()


def _display_search_results(args, journal, **kwargs):
if args.short or args.export == "short":
print(journal.pprint(short=True))
Expand Down
4 changes: 4 additions & 0 deletions jrnl/messages.py
Expand Up @@ -130,6 +130,10 @@ def __str__(self) -> str:
No entries to delete, because the search returned no results
"""

NothingToModify = """
No entries to modify, because the search returned no results
"""


class Message(NamedTuple):
text: MsgText
Expand Down

0 comments on commit 33c9dce

Please sign in to comment.