#!/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" parser = argparse.ArgumentParser() parser.add_argument( "-n", "--dryrun", help="only simulate and print changes", action="store_true" ) args = parser.parse_args() def extract_tw_data(fname): curdate = "1970-01-01" lines_to_delete = [] in_todotxt_block = False with open(fname) as file: line_number = 0 for line in file: line_number += 1 newdate = re.search(r"^\[(\d{4}-\d{2}-\d{2}).*\] (todotxt$)?", line) # we are entering todotxt data block if newdate and newdate[2]: curdate = newdate[1] in_todotxt_block = True continue # we are in block but not one for todotxt elif newdate and not newdate[2]: in_todotxt_block = False continue if not in_todotxt_block: continue completed_task = re.search(r"^x ((?:\([A-D]\))? ?.*)$", line) if completed_task: log_to_taskwarrior(completed_task[1], curdate) 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 def log_to_taskwarrior(task_string, date): overrides = "rc.context=none rc.hooks=0" cmd = [ "task", overrides, "log", f'"{task_string}"', f"entry:{date}", f"end:{date}", get_prio_string(task_string), ] if is_dryrun: print(cmd) return subprocess.Popen(cmd) def delete_logged_tasks_from_file(fname, lines): if is_dryrun: 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) def is_dryrun(): if args.dryrun: return True return False extract_tw_data(TODOTXT_FILE) sys.exit(0) # The on-launch event is triggered once, after initialization, before any # processing occurs. This hooks script has no effect on processing. # Output: # - Optional feedback/error. # echo 'on-launch' # Status: # - 0: JSON ignored, non-JSON is feedback. # - non-0: JSON ignored, non-JSON is error. # exit 0