mini-todo/todo/todo.py

129 lines
3.9 KiB
Python

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()