2021-10-30 17:49:08 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
# From: https://gist.github.com/varunagrawal/2b93c5dc721520ff6876e940c420ab05
|
|
|
|
# This hooks script logs any finished tasks currently in the todo.txt file
|
|
|
|
# pointed to by its settings.
|
|
|
|
# The on-exit event is triggered once, after all processing is complete.
|
|
|
|
|
|
|
|
import re
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import subprocess
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
TODOTXT_FILE = "/home/marty/documents/records/todo.md"
|
2021-10-31 11:05:20 +00:00
|
|
|
TODO_BLOCK_TITLE = "todotxt"
|
2021-10-30 17:49:08 +00:00
|
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument(
|
|
|
|
"-n", "--dryrun", help="only simulate and print changes", action="store_true"
|
|
|
|
)
|
2021-10-31 10:40:36 +00:00
|
|
|
parser.add_argument(
|
|
|
|
"-L",
|
|
|
|
"--nologging",
|
|
|
|
help="don't log done todo items to taskwarrior",
|
|
|
|
action="store_true",
|
|
|
|
)
|
2021-10-30 17:49:08 +00:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
2021-10-31 10:40:36 +00:00
|
|
|
# set options
|
|
|
|
def is_dryrun():
|
|
|
|
if args.dryrun:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def is_logging_done_to_tw():
|
|
|
|
if args.nologging:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
2021-10-30 17:49:08 +00:00
|
|
|
|
2021-10-31 11:05:20 +00:00
|
|
|
def get_todo_block_date(line):
|
|
|
|
result = re.search(
|
|
|
|
rf"^\[(\d{{4}}-\d{{2}}-\d{{2}}).*\] ({re.escape(TODO_BLOCK_TITLE)}$)?",
|
|
|
|
line,
|
|
|
|
)
|
|
|
|
# we are entering todotxt data block
|
|
|
|
if result and result[2]:
|
|
|
|
return result[1]
|
|
|
|
# we are in block but not one for todotxt
|
|
|
|
elif result and not result[2]:
|
|
|
|
return False
|
|
|
|
# nothing changed, we didn't cross a date line
|
|
|
|
return "same"
|
|
|
|
|
|
|
|
|
|
|
|
def parse_file(fname):
|
2021-10-30 17:49:08 +00:00
|
|
|
curdate = "1970-01-01"
|
|
|
|
lines_to_delete = []
|
|
|
|
with open(fname) as file:
|
|
|
|
line_number = 0
|
|
|
|
for line in file:
|
|
|
|
line_number += 1
|
|
|
|
|
2021-10-31 11:05:20 +00:00
|
|
|
todo_block = get_todo_block_date(line)
|
|
|
|
if todo_block == False:
|
|
|
|
continue
|
|
|
|
if todo_block != "same":
|
|
|
|
curdate = todo_block
|
2021-10-30 17:49:08 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
completed_task = re.search(r"^x ((?:\([A-D]\))? ?.*)$", line)
|
2021-10-31 10:40:36 +00:00
|
|
|
if completed_task and is_logging_done_to_tw():
|
|
|
|
log_done_to_taskwarrior(completed_task[1], curdate)
|
2021-10-30 17:49:08 +00:00
|
|
|
lines_to_delete.append(line_number)
|
|
|
|
|
|
|
|
if lines_to_delete:
|
|
|
|
delete_logged_tasks_from_file(TODOTXT_FILE, lines_to_delete)
|
|
|
|
|
|
|
|
|
|
|
|
def get_prio_string(task_string):
|
|
|
|
prio = re.search(r"^\(([ABC])\) (.*)$", task_string)
|
|
|
|
prio_string = ""
|
|
|
|
if prio:
|
|
|
|
task_string = prio[2]
|
|
|
|
if prio[1] == "A":
|
|
|
|
prio_string = "prio:H"
|
|
|
|
elif prio[1] == "B":
|
|
|
|
prio_string = "prio:M"
|
|
|
|
elif prio[1] == "C":
|
|
|
|
prio_string = "prio:L"
|
|
|
|
return prio_string
|
|
|
|
|
|
|
|
|
2021-10-31 10:40:36 +00:00
|
|
|
def log_done_to_taskwarrior(task_string, date):
|
2021-10-31 14:44:41 +00:00
|
|
|
overrides = ["rc.context=none", "rc.verbose=nothing", "rc.hooks=0"]
|
2021-10-30 17:49:08 +00:00
|
|
|
|
|
|
|
cmd = [
|
|
|
|
"task",
|
2021-10-31 14:44:41 +00:00
|
|
|
*overrides,
|
2021-10-30 17:49:08 +00:00
|
|
|
"log",
|
|
|
|
f'"{task_string}"',
|
|
|
|
f"entry:{date}",
|
|
|
|
f"end:{date}",
|
|
|
|
get_prio_string(task_string),
|
|
|
|
]
|
|
|
|
|
2021-10-31 10:40:36 +00:00
|
|
|
if is_dryrun():
|
2021-10-30 17:49:08 +00:00
|
|
|
print(cmd)
|
|
|
|
return
|
|
|
|
|
|
|
|
subprocess.Popen(cmd)
|
|
|
|
|
|
|
|
|
|
|
|
def delete_logged_tasks_from_file(fname, lines):
|
2021-10-31 10:40:36 +00:00
|
|
|
if is_dryrun():
|
|
|
|
print(f"deleting lines: {lines}")
|
2021-10-30 17:49:08 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
cur_line = 0
|
|
|
|
repl_file = fname + ".bak"
|
|
|
|
with open(fname) as read_file, open(repl_file, "w") as write_file:
|
|
|
|
for line in read_file:
|
|
|
|
cur_line += 1
|
|
|
|
if lines and cur_line == lines[0]:
|
|
|
|
lines.pop(0)
|
|
|
|
continue
|
|
|
|
write_file.write(line)
|
|
|
|
os.rename(repl_file, fname)
|
|
|
|
|
|
|
|
|
2021-10-31 11:05:20 +00:00
|
|
|
parse_file(TODOTXT_FILE)
|
2021-10-30 17:49:08 +00:00
|
|
|
sys.exit(0)
|