92 lines
2.6 KiB
Python
Executable file
92 lines
2.6 KiB
Python
Executable file
#!/usr/bin/env python
|
|
|
|
"""
|
|
Module is a copy/paste of https://github.com/mlaradji/task-relative-recur.git
|
|
Difference is, we'll execute completeRecurDue and completeRecurWait as strings.
|
|
|
|
Usage example:
|
|
task add 'Do the dishes' completeRecurWait:"tomorrow +17hours" completeRecurDue:"tomorrow +1day"
|
|
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import subprocess
|
|
import uuid
|
|
import os
|
|
import tempfile
|
|
import time
|
|
|
|
TIME_FORMAT = "%Y%m%dT%H%M%SZ"
|
|
UDA_DUE = "completeRecurDue"
|
|
UDA_WAIT = "completeRecurWait"
|
|
|
|
env = os.environ.copy()
|
|
|
|
# Hand back duration format parsing to task warrior
|
|
def calc(statement):
|
|
calc = subprocess.Popen(
|
|
["task", "rc.verbose=nothing", "rc.date.iso=yes", "calc", statement],
|
|
stdout=subprocess.PIPE,
|
|
env=env,
|
|
)
|
|
out, err = calc.communicate()
|
|
# Workaround for TW-1254 (https://bug.tasktools.org/browse/TW-1254)
|
|
return out.decode("utf-8")
|
|
|
|
|
|
# Parse the modified task
|
|
original = json.loads(sys.stdin.readline())
|
|
modified = sys.stdin.readline()
|
|
|
|
# Return the unmodified modified task, so it is actually changed
|
|
print(modified)
|
|
modified = json.loads(modified)
|
|
|
|
# Has a task with UDA been marked as completed?
|
|
if (
|
|
(UDA_DUE in original or UDA_WAIT in original)
|
|
and original["status"] != "completed"
|
|
and modified["status"] == "completed"
|
|
):
|
|
del original["modified"]
|
|
if "start" in original:
|
|
del original["start"]
|
|
if UDA_DUE in original:
|
|
original["due"] = calc(original[UDA_DUE])
|
|
if UDA_WAIT in original:
|
|
original["wait"] = calc(original[UDA_WAIT])
|
|
original["status"] = "waiting"
|
|
else:
|
|
original["status"] = "pending"
|
|
print("Created follow-up task")
|
|
original["entry"] = modified["end"]
|
|
original["uuid"] = str(uuid.uuid4())
|
|
|
|
# Wait for taskwarrior to finish, so we can safely `task import` the new
|
|
# task.
|
|
sys.stdout.flush()
|
|
task_pid = os.getppid()
|
|
if 0 < os.fork():
|
|
sys.exit(0)
|
|
else:
|
|
# Taskwarrior also waits for stdout to close
|
|
try:
|
|
os.close(sys.stdout.fileno())
|
|
except OSError:
|
|
pass # Thrown because of closing stdout. Don't worry, that's fine.
|
|
|
|
# Wait for taskwarrior to finish
|
|
# while os.path.exists("/proc/%s" % str(task_pid)):
|
|
time.sleep(1)
|
|
|
|
# Import the follow-up task
|
|
with tempfile.NamedTemporaryFile(mode="wt") as new_task:
|
|
new_task.write(json.dumps(original))
|
|
new_task.flush()
|
|
add = subprocess.Popen(
|
|
["task", "rc.verbose=nothing", "import", new_task.name],
|
|
env=env,
|
|
)
|
|
add.communicate()
|
|
|