diff --git a/org_rw/org_rw.py b/org_rw/org_rw.py index 625d67a..7e05080 100644 --- a/org_rw/org_rw.py +++ b/org_rw/org_rw.py @@ -290,6 +290,10 @@ class Headline: def id(self): return self.get_property("ID") + @id.setter + def id(self, value): + self.set_property("ID", value) + @property def clock(self): times = [] @@ -326,6 +330,33 @@ class Headline: return default + def set_property(self, name: str, value: str): + for prop in self.properties: + + # A matching property is found, update it + if prop.key == name: + prop.value = value + return + + # No matching property found, add it + else: + if len(self.properties) > 0: + last_prop = self.properties[-1] + last_line = last_prop.linenum + last_match = last_prop.match + else: + last_line = 0 + last_match = None + self.properties.append( + Property( + linenum=last_line, + match=last_match, + key=name, + value=value, + options=None, + ) + ) + def get_links(self): for content in self.contents: yield from get_links_from_content(content) @@ -1220,7 +1251,7 @@ def parse_headline(hl, doc, parent) -> Headline: class OrgDoc: - def __init__(self, headlines, keywords, contents): + def __init__(self, headlines, keywords, contents, list_items): self.todo_keywords = DEFAULT_TODO_KEYWORDS self.done_keywords = DEFAULT_DONE_KEYWORDS @@ -1233,6 +1264,7 @@ class OrgDoc: self.keywords: List[Property] = keywords self.contents: List[RawLine] = contents + self.list_items: List[ListItem] = list_items self._path = None self.headlines: List[Headline] = list( map(lambda hl: parse_headline(hl, self, self), headlines) @@ -1286,9 +1318,15 @@ class OrgDoc: ) def dump_property(self, prop: Property): - plus = prop.match.group("plus") - if plus is None: - plus = "" + plus = "" + indentation = "" + spacing = " " + if prop.match is not None: + plus = prop.match.group("plus") + if plus is None: + plus = "" + indentation = prop.match.group("indentation") + spacing = prop.match.group("spacing") if isinstance(prop.value, TimeRange): value = timerange_to_string(prop.value) @@ -1300,10 +1338,10 @@ class OrgDoc: return ( prop.linenum, "{indentation}:{key}{plus}:{spacing}{value}".format( - indentation=prop.match.group("indentation"), + indentation=indentation, key=prop.key, plus=plus, - spacing=prop.match.group("spacing"), + spacing=spacing, value=value, ), ) @@ -1404,6 +1442,9 @@ class OrgDoc: for line in self.contents: lines.append(dump_contents(line)) + for li in self.list_items: + lines.append(dump_contents(li)) + yield from map(lambda x: x[1], sorted(lines, key=lambda x: x[0])) for headline in self.headlines: @@ -1420,7 +1461,7 @@ class OrgDocReader: self.list_items: List[ListItem] = [] def finalize(self): - return OrgDoc(self.headlines, self.keywords, self.contents) + return OrgDoc(self.headlines, self.keywords, self.contents, self.list_items) ## Construction def add_headline(self, linenum: int, match: re.Match) -> int: diff --git a/org_rw/utils.py b/org_rw/utils.py index 04f0f1a..555671a 100644 --- a/org_rw/utils.py +++ b/org_rw/utils.py @@ -1,3 +1,5 @@ +import uuid + from .org_rw import (Bold, Code, Headline, Italic, Line, RawLine, Strike, Text, Underlined, Verbatim) @@ -36,3 +38,7 @@ def get_raw_contents(doc) -> str: return doc.get_raw() print("Unhandled type: " + str(doc)) raise NotImplementedError("Unhandled type: " + str(doc)) + + +def random_id() -> str: + return str(uuid.uuid4()) diff --git a/tests/test_org.py b/tests/test_org.py index 7730874..6bdda48 100644 --- a/tests/test_org.py +++ b/tests/test_org.py @@ -459,3 +459,32 @@ class TestSerde(unittest.TestCase): # ... lists = hl.getLists() self.assertEqual(len(lists), 3) + self.assertEqual(lists[0][0].content, " This is a simple list.") + self.assertEqual(lists[0][0].bullet, "-") + self.assertEqual( + lists[0][1].content, " This list has multiple elements, with _markup_." + ) + + self.assertEqual(lists[1][0].content, " This is a simple list.") + self.assertEqual(lists[1][0].bullet, "+") + + hl2 = doc.getTopHeadlines()[1] + # ... + lists2 = hl2.getLists() + self.assertEqual(len(lists2), 2) + + self.assertEqual(lists2[0][0].content, " First element") + self.assertEqual(lists2[0][0].counter, "1") + self.assertEqual(lists2[0][0].counter_sep, ".") + + self.assertEqual(lists2[0][1].content, " Second element") + self.assertEqual(lists2[0][1].counter, "2") + self.assertEqual(lists2[0][1].counter_sep, ".") + + self.assertEqual(lists2[1][0].content, " First element") + self.assertEqual(lists2[1][0].counter, "1") + self.assertEqual(lists2[1][0].counter_sep, ")") + + self.assertEqual(lists2[1][1].content, " Second element") + self.assertEqual(lists2[1][1].counter, "2") + self.assertEqual(lists2[1][1].counter_sep, ")")