Skip to content

Commit

Permalink
Add drop --due-after
Browse files Browse the repository at this point in the history
  • Loading branch information
adaschma committed Jul 26, 2023
1 parent 82464d1 commit f2aa3b7
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
44 changes: 44 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,15 @@ mark these by having the +auto pseudo project in the task.
If at some point you want to remove all chores from your todo list, the `drop`
subcommand is your friend.

.. code::
$ todo-txt chore drop --help
usage: chore chore drop [-h] [--due-after {now,tomorrow}]
options:
-h, --help show this help message and exit
--due-after {now,tomorrow}
.. code::
$ todo-txt ls
Expand Down Expand Up @@ -256,3 +265,38 @@ subcommand is your friend.
7 Plan backyard herb garden @Home
--
TODO: 7 of 7 tasks shown
It is also possible to only drop chores that are not yet due:

.. code::
$ todo-txt chore pull --all
$ todo-txt ls
01 Call Mom @Phone +Family
02 Schedule annual checkup +Health
03 Outilne chapter 5 +Novel @Computer
04 Add cover sheets @Office +TPSReports
05 Download Todo.txt mobile app @Phone
06 Pick up milk @GroceryStore
07 Plan backyard herb garden @Home
08 Change towels in the bathroom chore:1
09 Mop the kitchen floor chore:2
10 Take out the trash chore:3
11 Vacuum the living room floor chore:4
12 Clean the litter box chore:5
13 Change the bed sheets chore:6
--
TODO: 13 of 13 tasks shown
$ todo-txt chore drop --due-after tomorrow
$ todo-txt ls
1 Call Mom @Phone +Family
2 Schedule annual checkup +Health
3 Outilne chapter 5 +Novel @Computer
4 Add cover sheets @Office +TPSReports
5 Download Todo.txt mobile app @Phone
6 Pick up milk @GroceryStore
7 Plan backyard herb garden @Home
8 Mop the kitchen floor chore:2
--
TODO: 8 of 8 tasks shown
32 changes: 31 additions & 1 deletion grocy_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ def as_chore_full(orig: GrocyChore,
) -> GrocyChoreFull:
return GrocyChoreFull({'id': orig['id'], 'name': orig['chore_name'],
'description': orig['description'],
'rescheduled_date': rescheduled_date})
'rescheduled_date': rescheduled_date
})


class GrocyUserFields(TypedDict):
Expand Down Expand Up @@ -383,6 +384,16 @@ def get_chore(self, chore_id: int) -> GrocyChoreFull:
self.assert_valid_response(response)
return cast(GrocyChoreFull, response.json()["chore"])

def get_chore_due(self, chore_id: int) -> GrocyDateTime:
''' Get a chore's due date from grocy '''
url = f'{self.base_url}/chores/{chore_id}'
response = requests.get(url,
headers=self.headers,
timeout=self.timeout)
self.assert_valid_response(response)
return cast(GrocyDateTime,
response.json()["next_estimated_execution_time"])

def purchase(self, product_id: int, amount: float, price: float,
shopping_location_id: int) -> None:
''' Add a purchase to grocy '''
Expand Down Expand Up @@ -453,6 +464,7 @@ class CliArgs(AppArgs):
class TodotxtArgs(AppArgs):
''' Structure of our todo-txt CLI args '''
environ: TodotxtEnvVariables
due_after: Optional[Literal['now', 'tomorrow']]


def normanlize_white_space(orig: str) -> str:
Expand Down Expand Up @@ -1252,11 +1264,26 @@ def given_context_or_no_context_regex(context: str) -> re.Pattern[str]:
return re.compile(rf'{literal_context}|^[^@]*([^ ]@[^@]*)*$')


def chore_due_is_after(time: datetime, chore_id: int, grocy: GrocyApi) -> bool:
return grocy.get_chore_due(chore_id) < time.strftime('%Y-%m-%d %H:%M:%S')


to_datetime = {'now': datetime.now(),
'tomorrow': datetime.now().date() + timedelta(days=1)
}


def todotxt_chore_pull(args: TodotxtArgs,
config: AppConfig,
grocy: GrocyApi,
pull_from_grocy: bool = True) -> None:
'''Replace chores in todo.txt with current ones from grocy'''
keep_chore_if = cast(Callable[[int, GrocyApi], bool],
partial(chore_due_is_after,
to_datetime[args.due_after])
if hasattr(args, 'due_after'
) and args.due_after is not None
else lambda _, __: False)
todo_file = args.environ.TODO_FILE
new_content = []
regex = re.compile(r'chore:(\d+)')
Expand All @@ -1269,6 +1296,8 @@ def todotxt_chore_pull(args: TodotxtArgs,
raise UserError(f'chore {match_.group(1)} is marked'
' as done in todo.txt.\n'
' Run "push" and "archive" first. Aborting.')
elif keep_chore_if(int(match_.group(1)), grocy):
new_content.append(line)
copyfile(todo_file, todo_file + ".bak")
with open(todo_file, 'w') as f:
for line in new_content:
Expand Down Expand Up @@ -1457,6 +1486,7 @@ def get_todotxt_parser(environ: TodotxtEnvVariables) -> ArgumentParser:

chore_drop = subparsers.add_parser('drop',
help='Remove chores from todo-list')
chore_drop.add_argument('--due-after', choices=['now', 'tomorrow'])
chore_drop.set_defaults(func=partial(todotxt_chore_pull,
pull_from_grocy=False))

Expand Down

0 comments on commit f2aa3b7

Please sign in to comment.