commit 87a5d4be65597205f5274981e263804982522dc8 Author: Andrei Stoica Date: Sun Sep 18 10:38:24 2022 -0400 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d35cb3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +*.pyc diff --git a/bin/mini_todo b/bin/mini_todo new file mode 120000 index 0000000..66648bd --- /dev/null +++ b/bin/mini_todo @@ -0,0 +1 @@ +../todo \ No newline at end of file diff --git a/bin/todo b/bin/todo new file mode 100755 index 0000000..bf03de7 --- /dev/null +++ b/bin/todo @@ -0,0 +1,4 @@ +#!/usr/bin/python3 +from mini_todo import todo + +todo.main() diff --git a/todo.cfg b/todo.cfg new file mode 100644 index 0000000..5db3964 --- /dev/null +++ b/todo.cfg @@ -0,0 +1,3 @@ +[DEFAULT] +root_dir=~/todo +editor=vim \ No newline at end of file diff --git a/todo/__init__.py b/todo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/todo/todo.py b/todo/todo.py new file mode 100644 index 0000000..dc65f0b --- /dev/null +++ b/todo/todo.py @@ -0,0 +1,128 @@ +from datetime import datetime +import subprocess +import logging +import configparser +import os +import re + +_DATE_FORMAT = "%Y-%m-%d" +_SECTIONS = ["TODAY", "WEEK", "MONTH", "ANYTIME"] +_SECTION_HEADING = "##" +_MARKERS_COMPLETED = ["X", "[X]"] +_MARKERS_TASK = ["*", "-", "[]", "[ ]"] + + +def loadConfig() -> dict: + cfg_locations = [ + "~/todo/.todo.cfg", + "~/.todo.cfg", + os.path.join(os.path.dirname(__file__), "../todo.cfg"), + ] + for cfg_file in cfg_locations: + cfg_file = os.path.expanduser(cfg_file) + if os.path.exists(cfg_file) and os.path.isfile(cfg_file): + break + + config = configparser.ConfigParser() + print(cfg_file) + config.read(cfg_file) + if cfg_file == cfg_locations[-1]: + default_location = os.path.expanduser(cfg_locations[0]) + config_dir = os.path.dirname(default_location) + + if not os.path.exists(config_dir): + os.makedirs(config_dir) + with open(default_location, "w") as f: + config.write(f) + + paths = ["root_dir"] + props = paths + ["editor"] + cfg = {} + for prop in props: + cfg[prop] = config["DEFAULT"][prop] + for path in paths: + cfg[path] = os.path.expanduser(cfg[path]) + + return cfg + + +def parse_note(note_f: str, line_matcher: re.Pattern) -> dict: + print(note_f) + todo = {} + with open(note_f) as note: + curr_section = None + for line in note: + m = line_matcher.match(line) + if not m: + continue + if m.group(1): + section = m.group(4) + todo[section] = [] + curr_section = section + continue + else: + if m.group(2) and curr_section: + todo[curr_section].append(m.group(4)) + return todo + + +def write_notes(fname: str, date: datetime, yesterdays_notes: dict): + with open(fname, "w") as fout: + fout.write(f"# Daily Tasks {date.strftime(_DATE_FORMAT)}\n") + for section in _SECTIONS: + fout.write(f"\n{_SECTION_HEADING} {section}\n\n") + notes = yesterdays_notes.get(section) + if not notes: + continue + for note in notes: + if note: + fout.write(f" {_MARKERS_TASK[0]} {note}\n") + + +def main(): + logging.basicConfig(level=logging.INFO) + cfg = loadConfig() + today = datetime.strptime(datetime.now().strftime(_DATE_FORMAT), _DATE_FORMAT) + logging.info(cfg) + editor = cfg["editor"] + + root_dir = os.path.expanduser(cfg["root_dir"]) + if not os.path.exists(root_dir): + os.makedirs(root_dir) + todays_notes = f"daily_tracker_{today.strftime(_DATE_FORMAT)}.md" + todays_notes = os.path.join(root_dir, todays_notes) + if not os.path.exists(os.path.join(root_dir, todays_notes)): + todo_marker_groups = "|".join([f"(?:{m})" for m in _MARKERS_TASK]).replace( + "*", r"\*" + ) + comp_marker_groups = "|".join([f"(?:{m})" for m in _MARKERS_COMPLETED]).replace( + "*", r"\*" + ) + line_regex = re.compile( + rf"^\s*({_SECTION_HEADING})?({todo_marker_groups})?({comp_marker_groups})?\s*(\S+)$".replace( + "[", "\[" + ).replace( + "]", "\]" + ) + ) + print(line_regex) + + files = os.listdir(root_dir) + print(files) + file_matcher = re.compile(".*(\d{4}-\d{2}-\d{2}).md") + previous_notes = {} + for file in files: + m = file_matcher.match(file) + if m: + date = datetime.strptime(m.group(1), _DATE_FORMAT) + previous_notes[date] = file + last_note = previous_notes[max(list(previous_notes.keys()))] + last_note = os.path.join(root_dir, last_note) + last_note_content = parse_note(last_note, line_regex) + write_notes(todays_notes, today, last_note_content) + + subprocess.call([editor, todays_notes]) + + +if __name__ == "__main__": + main()