Space Panda

select-task.py

Source

#!/usr/bin/env python3
#
# Usage: select-task.py [-c] todo.txt
#
# -c (or --clear, -s, --stop) stops tracking of all tracking tasks
#
# If -c is not provided, it will provide a rofi/wofi/dmenu menu
# for you to select the task you want to start tracking.
# If there's a task running already, the menu will also provide a
# 'Stop tracking' option.
#
import subprocess
import pathlib
import datetime
import sys
import shutil
import pytodotxt
import pter.utils
DMENU_ALTERNATIVES = [
    ('rofi', ['-dmenu']),
    ('wofi', ['-dmenu']),
    ('dmenu', []),
]
STOP_TRACKING = 'Stop tracking'
TODAY = datetime.datetime.today().strftime("%Y-%m-%d")
def safe_t(values):
    if len(values) == 0:
        return '0000-00-00'
    return values[0]
def sort_fnc(task):
    return [task.attributes.get('due', ['9999-99-99'])[0] >= TODAY,
            task.priority or 'ZZZZ',
            task.attributes.get('due', ['9999-99-99'])[0],
            task.bare_description()]
filename = sys.argv[1]
do_clear = False
if sys.argv[1] in ['-s', '--stop', '-c', '--clear']:
    filename = sys.argv[2]
    do_clear = True
todotxt = pytodotxt.TodoTxt(pathlib.Path(filename).expanduser())
tasks = [t for t in todotxt.parse()
         if not t.is_completed and safe_t(t.attributes.get('t', [])) <= TODAY]
if do_clear:
    selection = STOP_TRACKING
else:
    for cmd, params in DMENU_ALTERNATIVES:
        dmenu = [shutil.which(cmd)]
        if dmenu[0] is None:
            continue
        dmenu += params
        break
    if dmenu[0] is None:
        print("Neither rofi, wofi, nor dmenu found", file=sys.stderr)
        sys.exit(-1)
    options = []
    if any(['tracking' in t.attributes for t in tasks]):
        options = [STOP_TRACKING]
    options += [task.description or ""
                for task in sorted(tasks, key=sort_fnc)
                if 'tracking' not in task.attributes]
    dmenu += ['-i', '-p', todotxt.filename.name]
    result = subprocess.run(dmenu, encoding='utf-8', input="\n".join(options) + "\n", capture_output=True)
    if result.returncode == 1:
        sys.exit(1)
    try:
        selection = result.stdout.strip("\n\r")
    except Exception as exc:
        raise exc
changed = False
# stop tracking of currently tracking tasks - there can be only one!
for task in todotxt.tasks:
    if 'tracking' in task.attributes:
        changed = True
        pter.utils.toggle_tracking(task)
if selection != STOP_TRACKING:
    for task in tasks:
        if task.description == selection:
            changed = True
            pter.utils.toggle_tracking(task)
            break
todotxt.save()
sys.exit(0)