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