Fix Headline spacing, add default TODO/DONE keywords.
Additionally, add util function to iterate over all headlines, and fix Timestamp.to_datetime() to work even when no time was given.
This commit is contained in:
parent
cde3481958
commit
1412a2bde1
@ -8,7 +8,7 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import List, Tuple, Union
|
from typing import Generator, List, Tuple, Union
|
||||||
|
|
||||||
BASE_ENVIRONMENT = {
|
BASE_ENVIRONMENT = {
|
||||||
"org-footnote-section": "Footnotes",
|
"org-footnote-section": "Footnotes",
|
||||||
@ -45,8 +45,11 @@ BASE_ENVIRONMENT = {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFAULT_TODO_KEYWORDS = ["TODO"]
|
||||||
|
DEFAULT_DONE_KEYWORDS = ["DONE"]
|
||||||
|
|
||||||
HEADLINE_TAGS_RE = re.compile(r"((:[a-zA-Z0-9_@#%]+)+:)\s*$")
|
HEADLINE_TAGS_RE = re.compile(r"((:[a-zA-Z0-9_@#%]+)+:)\s*$")
|
||||||
HEADLINE_RE = re.compile(r"^(?P<stars>\*+) (?P<spacing>\s*)(?P<line>.*?)$")
|
HEADLINE_RE = re.compile(r"^(?P<stars>\*+)(?P<spacing>\s*)(?P<line>.*?)$")
|
||||||
KEYWORDS_RE = re.compile(
|
KEYWORDS_RE = re.compile(
|
||||||
r"^(?P<indentation>\s*)#\+(?P<key>[^:\[]+)(\[(?P<options>[^\]]*)\])?:(?P<spacing>\s*)(?P<value>.*)$"
|
r"^(?P<indentation>\s*)#\+(?P<key>[^:\[]+)(\[(?P<options>[^\]]*)\])?:(?P<spacing>\s*)(?P<value>.*)$"
|
||||||
)
|
)
|
||||||
@ -182,6 +185,7 @@ class Headline:
|
|||||||
parent,
|
parent,
|
||||||
is_todo,
|
is_todo,
|
||||||
is_done,
|
is_done,
|
||||||
|
spacing,
|
||||||
):
|
):
|
||||||
self.start_line = start_line
|
self.start_line = start_line
|
||||||
self.depth = depth
|
self.depth = depth
|
||||||
@ -205,6 +209,7 @@ class Headline:
|
|||||||
self.scheduled = None
|
self.scheduled = None
|
||||||
self.deadline = None
|
self.deadline = None
|
||||||
self.closed = None
|
self.closed = None
|
||||||
|
self.spacing = spacing
|
||||||
|
|
||||||
# Read planning line
|
# Read planning line
|
||||||
planning_line = self.get_element_in_line(start_line + 1)
|
planning_line = self.get_element_in_line(start_line + 1)
|
||||||
@ -459,8 +464,11 @@ class Timestamp:
|
|||||||
self.minute = minute
|
self.minute = minute
|
||||||
self.repetition = repetition
|
self.repetition = repetition
|
||||||
|
|
||||||
def to_datetime(self) -> datetime:
|
def to_datetime(self) -> Union[datetime, date]:
|
||||||
|
if self.hour is not None:
|
||||||
return datetime(self.year, self.month, self.day, self.hour, self.minute)
|
return datetime(self.year, self.month, self.day, self.hour, self.minute)
|
||||||
|
else:
|
||||||
|
return datetime(self.year, self.month, self.day, 0, 0)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, Timestamp):
|
if not isinstance(other, Timestamp):
|
||||||
@ -1089,6 +1097,7 @@ def dump_contents(raw):
|
|||||||
def parse_headline(hl, doc, parent) -> Headline:
|
def parse_headline(hl, doc, parent) -> Headline:
|
||||||
stars = hl["orig"].group("stars")
|
stars = hl["orig"].group("stars")
|
||||||
depth = len(stars)
|
depth = len(stars)
|
||||||
|
spacing = hl["orig"].group("spacing")
|
||||||
|
|
||||||
# TODO: Parse line for priority, cookies and tags
|
# TODO: Parse line for priority, cookies and tags
|
||||||
line = hl["orig"].group("line")
|
line = hl["orig"].group("line")
|
||||||
@ -1139,6 +1148,7 @@ def parse_headline(hl, doc, parent) -> Headline:
|
|||||||
parent=parent,
|
parent=parent,
|
||||||
is_todo=is_todo,
|
is_todo=is_todo,
|
||||||
is_done=is_done,
|
is_done=is_done,
|
||||||
|
spacing=spacing,
|
||||||
)
|
)
|
||||||
|
|
||||||
headline.children = [
|
headline.children = [
|
||||||
@ -1149,8 +1159,8 @@ def parse_headline(hl, doc, parent) -> Headline:
|
|||||||
|
|
||||||
class OrgDoc:
|
class OrgDoc:
|
||||||
def __init__(self, headlines, keywords, contents):
|
def __init__(self, headlines, keywords, contents):
|
||||||
self.todo_keywords = None
|
self.todo_keywords = DEFAULT_TODO_KEYWORDS
|
||||||
self.done_keywords = None
|
self.done_keywords = DEFAULT_DONE_KEYWORDS
|
||||||
|
|
||||||
for keyword in keywords:
|
for keyword in keywords:
|
||||||
if keyword.key == "TODO":
|
if keyword.key == "TODO":
|
||||||
@ -1184,6 +1194,14 @@ class OrgDoc:
|
|||||||
def getTopHeadlines(self):
|
def getTopHeadlines(self):
|
||||||
return self.headlines
|
return self.headlines
|
||||||
|
|
||||||
|
def getAllHeadlines(self) -> Generator[Headline]:
|
||||||
|
todo = self.headlines[::-1] # We go backwards, to pop/append and go depth-first
|
||||||
|
while len(todo) != 0:
|
||||||
|
hl = todo.pop()
|
||||||
|
todo.extend(hl.children[::-1])
|
||||||
|
|
||||||
|
yield hl
|
||||||
|
|
||||||
def get_code_snippets(self):
|
def get_code_snippets(self):
|
||||||
for headline in self.headlines:
|
for headline in self.headlines:
|
||||||
yield from headline.get_code_snippets()
|
yield from headline.get_code_snippets()
|
||||||
@ -1244,9 +1262,7 @@ class OrgDoc:
|
|||||||
if headline.state:
|
if headline.state:
|
||||||
state = headline.state + " "
|
state = headline.state + " "
|
||||||
|
|
||||||
yield "*" * headline.depth + " " + state + headline.orig.group(
|
yield "*" * headline.depth + headline.spacing + state + headline.title + tags
|
||||||
"spacing"
|
|
||||||
) + headline.title + tags
|
|
||||||
|
|
||||||
planning = headline.get_planning_line()
|
planning = headline.get_planning_line()
|
||||||
if planning is not None:
|
if planning is not None:
|
||||||
|
Loading…
Reference in New Issue
Block a user