Compare commits

...

6 commits

2 changed files with 104 additions and 24 deletions

View file

@ -7,3 +7,6 @@ requires-python = ">=3.13"
dependencies = [ dependencies = [
"tasklib>=2.5.1", "tasklib>=2.5.1",
] ]
[tool.pyright]
typeCheckingMode = "standard"

125
topen
View file

@ -5,46 +5,123 @@
# Edits an existing task note file, # Edits an existing task note file,
# or creates a new one. # or creates a new one.
# It currently assumes an XDG-compliant taskwarrior configuration by default.
import argparse
import os
import subprocess import subprocess
import sys import sys
from pathlib import Path from pathlib import Path
from tasklib import Task, TaskWarrior from tasklib import Task, TaskWarrior
TASK_DATA_DIR = "~/.local/share/task" # TODO: This should not assume XDG compliance for
# no-setup TW instances.
TASK_RC = os.getenv("TASKRC", "~/.config/task/taskrc")
TASK_DATA_DIR = os.getenv("TASKDATA", "~/.local/share/task")
TASKNOTES_DIR = "~/.local/share/task/notes" TOPEN_DIR = os.getenv("TOPEN_DIR", "~/.local/share/task/notes")
TASKNOTES_EXT = "md" TOPEN_EXT = os.getenv("TOPEN_EXT", "md")
TASKNOTES_ANNOT = "Note" TOPEN_ANNOT = os.getenv("TOPEN_ANNOT", "Note")
TOPEN_EDITOR = os.getenv("EDITOR") or os.getenv("VISUAL", "nano")
TOPEN_QUIET = os.getenv("TOPEN_QUIET", False)
tw = TaskWarrior(data_location=TASK_DATA_DIR)
args = sys.argv def parse_cli() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Taskwarrior note editing made easy.")
_ = parser.add_argument(
"id", help="The id/uuid of the taskwarrior task for which we edit notes"
)
_ = parser.add_argument(
"-d",
"--notes-dir",
default=TOPEN_DIR,
help="Location of topen notes files",
)
_ = parser.add_argument(
"--quiet",
default=TOPEN_QUIET,
action="store_true",
help="Silence any verbose displayed information",
)
_ = parser.add_argument(
"--extension", default=TOPEN_EXT, help="Extension of note files"
)
_ = parser.add_argument(
"--annotation",
default=TOPEN_ANNOT,
help="Annotation content to set within taskwarrior",
)
_ = parser.add_argument(
"--task-data", default=TASK_DATA_DIR, help="Location of taskwarrior data"
)
_ = parser.add_argument(
"--editor", default=TOPEN_EDITOR, help="Program to open note files with"
)
if not len(args) == 2: return parser.parse_args()
_ = sys.stderr.write("Please provide task ID as argument.\n")
sys.exit(1)
given_id = args[1]
try: IS_QUIET = False
t = tw.tasks.get(id=given_id)
except Task.DoesNotExist:
t = tw.tasks.get(uuid=given_id)
_ = sys.stderr.write(f"Editing note for: {t['description']} ({t['uuid']})\n")
notes_file = Path(TASKNOTES_DIR).joinpath(f"{t['uuid']}.{TASKNOTES_EXT}") def whisper(text: str) -> None:
if not IS_QUIET:
print(text)
proc = subprocess.Popen(f"nvim {notes_file}", shell=True)
_ = proc.wait()
def add_annotation_if_missing(task: Task) -> None: def main():
for annot in t["annotations"]: args = parse_cli()
if annot["description"] == "Note":
if not args.id:
_ = sys.stderr.write("Please provide task ID as argument.\n")
if args.quiet:
global IS_QUIET
IS_QUIET = True
task = get_task(id=args.id, data_location=args.task_data)
uuid = task["uuid"]
if not uuid:
_ = sys.stderr.write(f"Could not find task for ID: {args.id}.")
sys.exit(1)
fname = get_notes_file(uuid, notes_dir=args.notes_dir, notes_ext=args.extension)
open_editor(fname, editor=args.editor)
add_annotation_if_missing(task, annotation_content=args.annotation)
def get_task(id: str, data_location: str = TASK_DATA_DIR) -> Task:
tw = TaskWarrior(data_location)
try:
t = tw.tasks.get(id=id)
except Task.DoesNotExist:
t = tw.tasks.get(uuid=id)
return t
def get_notes_file(
uuid: str, notes_dir: str = TOPEN_DIR, notes_ext: str = TOPEN_EXT
) -> Path:
return Path(notes_dir).joinpath(f"{uuid}.{notes_ext}")
def open_editor(file: Path, editor: str = TOPEN_EDITOR) -> None:
_ = whisper(f"Editing note: {file}")
proc = subprocess.Popen(f"{editor} {file}", shell=True)
_ = proc.wait()
def add_annotation_if_missing(
task: Task, annotation_content: str = TOPEN_ANNOT
) -> None:
for annot in task["annotations"] or []:
if annot["description"] == annotation_content:
return return
t.add_annotation(TASKNOTES_ANNOT) task.add_annotation(annotation_content)
_ = sys.stderr.write(f"Added annotation.\n") _ = whisper(f"Added annotation: {annotation_content}")
add_annotation_if_missing(t) if __name__ == "__main__":
main()