from datetime import datetime, timedelta from pathlib import Path from subprocess import run from typing import Union import sys import re JOURNAL_PATH = '/Users/olari/workspace/journal' entry_re = re.compile(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}') def get_daily_file_paths() -> list[Path]: return list(sorted(Path(JOURNAL_PATH).glob('*.md'))) def resolve_relative_time_expression(now: datetime, expr: str) -> datetime: weekdays = [ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ] if expr == 'today': return now elif expr == 'tomorrow': return now + timedelta(days=1) elif expr == 'yesterday': return now - timedelta(days=1) elif expr in weekdays: return now - timedelta(days=now.weekday()) + weekdays.index(expr) else: return None def parse_godword(content: str) -> list[str]: return content.split() def parse_habits(content: str) -> dict[str, bool]: return { line[4:]: line[1] == 'x' for line in content.splitlines() } header_modules = { 'godword': (None, parse_godword), 'habits': (None, parse_habits), } def parse_header_module(content: str) -> tuple[str, Union[list, dict]]: name, *content = content.splitlines() name = name.removesuffix(':').lower() content = '\n'.join(content) _, parse = header_modules[name] return name, parse(content) def parse_header(header): title, *modules = header.split('\n\n') title = title.removeprefix('# ') return { 'title': title, 'modules': dict(parse_header_module(module) for module in modules) } def parse_diet(content): pass def parse_content(content): content = content.strip() return { 'blocks': [b.replace('\n', ' ') for b in content.split('\n\n')] } def parse_timestamp(timestamp): return datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S') def parse_entry(entry): return { 'timestamp': int(parse_timestamp(entry[:19]).timestamp()), 'content': parse_content(entry[19:]), } def parse_file(fpath): header = {} entries = [] buf = [] for i, line in enumerate(fpath.read_text().splitlines()): if entry_re.match(line): if not header: header = parse_header('\n'.join([c.strip() for c in buf])) else: entries.append(parse_entry('\n'.join(buf))) buf = [line] else: buf.append(line) return { 'header': header, 'entries': entries, } def parse_journal(): result = {} for fpath in get_daily_file_paths()[-5:]: info = parse_file(fpath) result[info['header']['title']] = info return result import json open('journal.json', 'w').write(json.dumps(parse_journal()))