grasp/server/org_tools.py
2019-01-06 23:57:15 +00:00

76 lines
1.9 KiB
Python

from datetime import datetime
import logging
from pathlib import Path
import re
from typing import List, Optional
def date2org(t: datetime) -> str:
return t.strftime("%Y-%m-%d %a")
def datetime2orgtime(t: datetime) -> str:
return t.strftime("%H:%M")
def datetime2org(t: datetime) -> str:
return date2org(t) + " " + datetime2orgtime(t)
# TODO priority maybe??
# TODO need to sanitize!
def as_org_entry(
heading: Optional[str] = None,
tags: List[str] = [],
body: Optional[str] = None,
created: Optional[datetime]=None,
todo=True,
):
if heading is None:
if body is None:
raise RuntimeError('Both heading and body are empty!!')
heading = body.splitlines()[0] # TODO ??
if body is None:
body = ''
# TODO FIXME escape everything properly!
heading = re.sub(r'\s', ' ', heading)
# TODO remove newlines from body
NOW = datetime.now() # TODO tz??
# appended only added if it's different from created
app = [f':APPENDED: [{datetime2org(NOW)}]'] if created is not None else []
if created is None:
created = NOW
todo_s = ' TODO' if todo else ''
tag_s = ':'.join(tags)
sch = [f' SCHEDULED: <{date2org(NOW)}>'] if todo else []
if len(tag_s) != 0:
tag_s = f':{tag_s}:'
lines = [
f"""*{todo_s} {heading} {tag_s}""",
*sch,
':PROPERTIES:',
*app,
f':CREATED: [{datetime2org(created)}]',
':END:',
body,
"",
"",
]
return '\n'.join(lines)
# TODO should we check if it exists first?
def append_org_entry(
path: Path,
*args,
**kwargs,
):
res = as_org_entry(*args, **kwargs)
# https://stackoverflow.com/a/13232181
if len(res.encode('utf8')) > 4096:
logging.warning("writing out %s might be non-atomic", res)
with path.open('a') as fo:
fo.write(res)