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) print(line, m) 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)) elif not m.group(3) and curr_section: todo[curr_section][-1] += f"\n {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*(.+)$".replace( "[", r"\[" ).replace( "]", r"\]" ) ) 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) print(last_note_content) write_notes(todays_notes, today, last_note_content) subprocess.call([editor, todays_notes]) if __name__ == "__main__": main()