Add support for reading Headline planning info.

This includes: `SCHEDULED`, `DEADLINE` and `CLOSED`.
This commit is contained in:
Sergio Martínez Portela 2021-01-06 00:25:06 +01:00
parent 09f2aed8fe
commit d71f98f4b9
3 changed files with 57 additions and 1 deletions

View File

@ -4,7 +4,7 @@ import logging
import os
import re
import sys
from datetime import datetime, timedelta
from datetime import date, datetime, timedelta
from enum import Enum
from typing import List, Tuple, Union
@ -55,9 +55,25 @@ NODE_PROPERTIES_RE = re.compile(
)
RAW_LINE_RE = re.compile(r"^\s*([^\s#:*]|$)")
BASE_TIME_STAMP_RE = r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})( ?(?P<dow>[^ ]+))?( (?P<start_hour>\d{1,2}):(?P<start_minute>\d{1,2})(--(?P<end_hour>\d{1,2}):(?P<end_minute>\d{1,2}))?)?"
CLEAN_TIME_STAMP_RE = (
r"\d{4}-\d{2}-\d{2}( ?([^ ]+))?( (\d{1,2}):(\d{1,2})(--(\d{1,2}):(\d{1,2}))?)?"
)
ACTIVE_TIME_STAMP_RE = re.compile(r"<{}>".format(BASE_TIME_STAMP_RE))
INACTIVE_TIME_STAMP_RE = re.compile(r"\[{}\]".format(BASE_TIME_STAMP_RE))
PLANNING_RE = re.compile(
r"(?P<indentation>\s*)"
+ r"(SCHEDULED:\s*(?P<scheduled>[<\[]"
+ CLEAN_TIME_STAMP_RE
+ r"[>\]])\s*"
+ r"|CLOSED:\s*(?P<closed>[<\[]"
+ CLEAN_TIME_STAMP_RE
+ r"[>\]])\s*"
+ r"|DEADLINE:\s*(?P<deadline>[<\[]"
+ CLEAN_TIME_STAMP_RE
+ r"[>\]])\s*"
r")+\s*"
)
# Org-Babel
BEGIN_SRC_RE = re.compile(r"^\s*#\+BEGIN_SRC(?P<content>.*)$", re.I)
@ -180,6 +196,24 @@ class Headline:
self.parent = parent
self.is_todo = is_todo
self.is_done = is_done
self.scheduled = None
self.deadline = None
self.closed = None
# Read planning line
planning_line = self.get_element_in_line(start_line + 1)
# Ignore if not found or is a structural line
if planning_line is None or isinstance(planning_line, tuple):
return
if m := PLANNING_RE.match(planning_line.get_raw()):
if scheduled := m.group("scheduled"):
self.scheduled = time_from_str(scheduled)
if closed := m.group("closed"):
self.closed = time_from_str(closed)
if deadline := m.group("deadline"):
self.deadline = time_from_str(deadline)
@property
def clock(self):
@ -464,6 +498,16 @@ def parse_org_time(value):
)
class OrgTime:
def __init__(self, ts: Timestamp):
self.time = ts
self.date = date(ts.year, ts.month, ts.day)
def time_from_str(s: str):
return OrgTime(parse_org_time(s))
def timerange_to_string(tr: TimeRange):
return timestamp_to_string(tr.start_time) + "--" + timestamp_to_string(tr.end_time)

View File

@ -3,6 +3,7 @@
#+TODO: TODO(t) PAUSED(p) | DONE(d)
* Headline properties
SCHEDULED: <2020-12-12 Sáb> CLOSED: <2020-12-13 Dom> DEADLINE: <2020-12-14 Lun>
:PROPERTIES:
:JUST_DAY: [2020-12-10]
:DAY_AND_WEEKDAY: [2020-12-10 Xov]

View File

@ -1,6 +1,7 @@
import logging
import os
import unittest
from datetime import date
from datetime import datetime as DT
from org_rw import dumps, load, loads
@ -391,3 +392,13 @@ class TestSerde(unittest.TestCase):
doc = loads(orig)
self.assertEqual(dumps(doc), orig)
def test_planning_info_file_05(self):
with open(os.path.join(DIR, "05-dates.org")) as f:
orig = f.read()
doc = loads(orig)
hl = doc.getTopHeadlines()[0]
self.assertEqual(hl.scheduled.date, date(2020, 12, 12))
self.assertEqual(hl.closed.date, date(2020, 12, 13))
self.assertEqual(hl.deadline.date, date(2020, 12, 14))