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 os
import re import re
import sys import sys
from datetime import 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 List, Tuple, Union
@ -55,9 +55,25 @@ NODE_PROPERTIES_RE = re.compile(
) )
RAW_LINE_RE = re.compile(r"^\s*([^\s#:*]|$)") 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}))?)?" 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)) ACTIVE_TIME_STAMP_RE = re.compile(r"<{}>".format(BASE_TIME_STAMP_RE))
INACTIVE_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 # Org-Babel
BEGIN_SRC_RE = re.compile(r"^\s*#\+BEGIN_SRC(?P<content>.*)$", re.I) BEGIN_SRC_RE = re.compile(r"^\s*#\+BEGIN_SRC(?P<content>.*)$", re.I)
@ -180,6 +196,24 @@ class Headline:
self.parent = parent self.parent = parent
self.is_todo = is_todo self.is_todo = is_todo
self.is_done = is_done 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 @property
def clock(self): 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): def timerange_to_string(tr: TimeRange):
return timestamp_to_string(tr.start_time) + "--" + timestamp_to_string(tr.end_time) 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) #+TODO: TODO(t) PAUSED(p) | DONE(d)
* Headline properties * Headline properties
SCHEDULED: <2020-12-12 Sáb> CLOSED: <2020-12-13 Dom> DEADLINE: <2020-12-14 Lun>
:PROPERTIES: :PROPERTIES:
:JUST_DAY: [2020-12-10] :JUST_DAY: [2020-12-10]
:DAY_AND_WEEKDAY: [2020-12-10 Xov] :DAY_AND_WEEKDAY: [2020-12-10 Xov]

View File

@ -1,6 +1,7 @@
import logging import logging
import os import os
import unittest import unittest
from datetime import date
from datetime import datetime as DT from datetime import datetime as DT
from org_rw import dumps, load, loads from org_rw import dumps, load, loads
@ -391,3 +392,13 @@ class TestSerde(unittest.TestCase):
doc = loads(orig) doc = loads(orig)
self.assertEqual(dumps(doc), 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))