Add support for reading Headline planning info.
This includes: `SCHEDULED`, `DEADLINE` and `CLOSED`.
This commit is contained in:
parent
09f2aed8fe
commit
d71f98f4b9
@ -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)
|
||||||
|
|
||||||
|
@ -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]
|
||||||
|
@ -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))
|
||||||
|
Loading…
Reference in New Issue
Block a user