187 lines
4.4 KiB
Python
187 lines
4.4 KiB
Python
from datetime import datetime
|
|
import re
|
|
from typing import List, Optional
|
|
|
|
DEFAULT_TEMPLATE = "\\%title: [[%:link|%:description]]\n%:tags\n%U\n\n\n%:link\n%:initial\n"
|
|
|
|
# TODO reuse inorganic/orgparse??
|
|
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)
|
|
|
|
|
|
def empty(s) -> bool:
|
|
return s is None or len(s.strip()) == 0
|
|
|
|
|
|
# TODO protocol??
|
|
# TODO put template in config??
|
|
class Config:
|
|
@staticmethod
|
|
def format_selection(selection: str) -> List[str]: # type: ignore[empty-body]
|
|
...
|
|
|
|
@staticmethod
|
|
def format_comment(comment: str) -> List[str]: # type: ignore[empty-body]
|
|
...
|
|
|
|
|
|
class DefaultConfig(Config):
|
|
@staticmethod
|
|
def format_selection(selection: str) -> List[str]:
|
|
return [
|
|
'Selection:',
|
|
selection,
|
|
]
|
|
|
|
|
|
@staticmethod
|
|
def format_comment(comment: str) -> List[str]:
|
|
return [
|
|
'Comment:',
|
|
comment
|
|
]
|
|
|
|
|
|
def as_org(
|
|
url: str,
|
|
title: str,
|
|
selection: str,
|
|
comment: str,
|
|
tags: List[str],
|
|
org_template: str,
|
|
config: Optional[Config] = None,
|
|
*,
|
|
_now=None,
|
|
):
|
|
"""
|
|
Formats captured results according to org template. Supports all sensible (e.g. non-interactive) template expansions from https://orgmode.org/manual/Template-expansion.html#Template-expansion.
|
|
|
|
Additionally, supports :selection, :comment and :tags expansions.
|
|
|
|
You can look at `test_templates` for some specific examples.
|
|
"""
|
|
py_template = re.sub(r'([^\\])%[:]?([?\w]+)', r'\1{\2}', org_template)
|
|
# replace all escaped % with regular %, safe to do after substitution
|
|
py_template = py_template.replace(r'\%', '%')
|
|
|
|
NOW = datetime.now() if _now is None else _now
|
|
org_date = date2org(NOW)
|
|
org_datetime = datetime2org(NOW)
|
|
|
|
tags_s = '' if len(tags) == 0 else (':' + ':'.join(tags) + ':')
|
|
|
|
if config is None:
|
|
config = DefaultConfig()
|
|
|
|
# TODO tabulate selection and comments?
|
|
# TODO not sure, maybe add as org quote?
|
|
parts = []
|
|
if not empty(selection):
|
|
parts.extend(config.format_selection(selection))
|
|
if not empty(comment):
|
|
parts.extend(config.format_comment(comment))
|
|
initial = '\n'.join(parts)
|
|
|
|
res = py_template.format(
|
|
t=f'<{org_date}>',
|
|
u=f'[{org_date}]',
|
|
T=f'<{org_datetime}>',
|
|
U=f'[{org_datetime}]',
|
|
description=title,
|
|
link=url,
|
|
|
|
initial=initial,
|
|
i=initial,
|
|
|
|
tags=tags_s,
|
|
selection=selection,
|
|
comment=comment,
|
|
annotation=f'[[{url}][{title}]]', # https://orgmode.org/manual/capture-protocol.html
|
|
**{'?': ''}, # just ignore it
|
|
)
|
|
return res
|
|
|
|
|
|
def test_templates() -> None:
|
|
url = 'https://whatever'
|
|
title = 'hello'
|
|
selection = """some
|
|
selected
|
|
text
|
|
"""
|
|
comment = 'fafewfewf'
|
|
tags = ['aba', 'caba']
|
|
|
|
vimzettel_template = r'zettel \%title [%:description] testing'
|
|
# https://orgmode.org/guide/Capture-templates.html
|
|
org_templates = [
|
|
DEFAULT_TEMPLATE,
|
|
"* %? [[%:link][%:description]] \nCaptured On: %U",
|
|
"* %:annotation",
|
|
"* %U %:description :protocol: \n %:link \n%:initial \n\n",
|
|
"* %t captured stuff %:tags \n ",
|
|
"\n** Selection\n%:selection\n** Comment\n%:comment\n",
|
|
"""* TODO [#A] %:link
|
|
** Selection
|
|
%:selection
|
|
** Comment
|
|
%:comment
|
|
""",
|
|
"""* %T %:link %:description
|
|
#+BEGIN_QUOTE
|
|
%:selection
|
|
#+END_QUOTE
|
|
""",
|
|
vimzettel_template,
|
|
]
|
|
# check they aren't crashing
|
|
for org_template in org_templates:
|
|
res = as_org(
|
|
url,
|
|
title,
|
|
selection,
|
|
comment,
|
|
tags,
|
|
org_template=org_template
|
|
|
|
)
|
|
print()
|
|
print(res)
|
|
res = as_org(
|
|
url,
|
|
title,
|
|
selection,
|
|
comment,
|
|
tags,
|
|
org_template=DEFAULT_TEMPLATE,
|
|
_now=datetime(1111, 11, 11),
|
|
)
|
|
expected = '''
|
|
* [1111-11-11 Sat 00:00] hello :aba:caba:
|
|
https://whatever
|
|
Selection:
|
|
some
|
|
selected
|
|
text
|
|
|
|
Comment:
|
|
fafewfewf
|
|
'''.lstrip()
|
|
assert res == expected
|
|
|
|
res = as_org(
|
|
url,
|
|
title,
|
|
selection,
|
|
comment,
|
|
tags,
|
|
org_template=vimzettel_template,
|
|
)
|
|
assert res == 'zettel %title [hello] testing'
|