133 lines
4.1 KiB
Python
133 lines
4.1 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)
|
|
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 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()
|