Fix handling of block elements after multiline list items.

This commit is contained in:
Sergio Martínez Portela 2022-11-12 18:01:00 +01:00
parent 6c6c375572
commit b819904457
3 changed files with 44 additions and 13 deletions

View File

@ -871,8 +871,12 @@ class ListItem:
self.tag = tag self.tag = tag
self.content = content self.content = content
@property
def text_start_pos(self):
return len(self.indentation) + 1 # Indentation + bullet
def append_line(self, line): def append_line(self, line):
self.content += parse_content_block('\n' + line[len(self.indentation):]).contents self.content += parse_content_block('\n' + line).contents
TableRow = collections.namedtuple( TableRow = collections.namedtuple(
"TableRow", "TableRow",
@ -1617,10 +1621,7 @@ def dump_contents(raw):
bullet = raw.bullet if raw.bullet else raw.counter + raw.counter_sep bullet = raw.bullet if raw.bullet else raw.counter + raw.counter_sep
content_full = token_list_to_raw(raw.content) content_full = token_list_to_raw(raw.content)
content_lines = content_full.split('\n') content_lines = content_full.split('\n')
content = '\n'.join([content_lines[0], *[ content = '\n'.join(content_lines)
raw.indentation + line
for line in content_lines[1:]
]])
checkbox = f"[{raw.checkbox_value}]" if raw.checkbox_value else "" checkbox = f"[{raw.checkbox_value}]" if raw.checkbox_value else ""
tag = f"{raw.tag_indentation}{token_list_to_raw(raw.tag or '')}::" if raw.tag or raw.tag_indentation else "" tag = f"{raw.tag_indentation}{token_list_to_raw(raw.tag or '')}::" if raw.tag or raw.tag_indentation else ""
return ( return (
@ -2148,12 +2149,15 @@ class OrgDocReader:
nonlocal list_item nonlocal list_item
nonlocal list_item_indentation nonlocal list_item_indentation
if list_item: if list_item:
if line.startswith(list_item_indentation): if ((line[:list_item.text_start_pos].strip() == '')
or (len(line.strip()) == 0)
):
list_item.append_line(line) list_item.append_line(line)
added = True added = True
elif len(line.strip()) > 0: else:
list_item = None list_item = None
list_item_indentation = None list_item_indentation = None
if not added: if not added:
self.add_raw_line(linenum, line) self.add_raw_line(linenum, line)
@ -2164,6 +2168,8 @@ class OrgDocReader:
if m := END_BLOCK_RE.match(line): if m := END_BLOCK_RE.match(line):
self.add_end_block_line(linenum, m) self.add_end_block_line(linenum, m)
in_block = False in_block = False
list_item_indentation = None
list_item = None
else: else:
add_raw_line_with_possible_indentation(linenum, line) add_raw_line_with_possible_indentation(linenum, line)
@ -2180,25 +2186,37 @@ class OrgDocReader:
elif m := BEGIN_BLOCK_RE.match(line): elif m := BEGIN_BLOCK_RE.match(line):
self.add_begin_block_line(linenum, m) self.add_begin_block_line(linenum, m)
in_block = True in_block = True
list_item_indentation = None
list_item = None
elif m := END_BLOCK_RE.match(line): elif m := END_BLOCK_RE.match(line):
self.add_end_block_line(linenum, m) self.add_end_block_line(linenum, m)
in_block = False in_block = False
list_item_indentation = None
list_item = None
# Generic properties # Generic properties
elif m := KEYWORDS_RE.match(line): elif m := KEYWORDS_RE.match(line):
self.add_keyword_line(linenum, m) self.add_keyword_line(linenum, m)
elif m := DRAWER_END_RE.match(line): elif m := DRAWER_END_RE.match(line):
self.add_drawer_end_line(linenum, line, m) self.add_drawer_end_line(linenum, line, m)
in_drawer = False in_drawer = False
list_item_indentation = None
list_item = None
elif (not in_drawer) and (m := DRAWER_START_RE.match(line)): elif (not in_drawer) and (m := DRAWER_START_RE.match(line)):
self.add_property_drawer_line(linenum, line, m) self.add_property_drawer_line(linenum, line, m)
in_drawer = True in_drawer = True
list_item_indentation = None
list_item = None
elif (not in_drawer) and (m := RESULTS_DRAWER_RE.match(line)): elif (not in_drawer) and (m := RESULTS_DRAWER_RE.match(line)):
self.add_results_drawer_line(linenum, line, m) self.add_results_drawer_line(linenum, line, m)
in_drawer = True in_drawer = True
list_item_indentation = None
list_item = None
elif m := NODE_PROPERTIES_RE.match(line): elif m := NODE_PROPERTIES_RE.match(line):
self.add_node_properties_line(linenum, m) self.add_node_properties_line(linenum, m)
elif line.strip().startswith('|'): elif line.strip().startswith('|'):
self.add_table_line(linenum, line) self.add_table_line(linenum, line)
list_item_indentation = None
list_item = None
# Not captured # Not captured
else: else:
add_raw_line_with_possible_indentation(linenum, line) add_raw_line_with_possible_indentation(linenum, line)

View File

@ -63,3 +63,13 @@ Also with markup
- This is another list item... - This is another list item...
that has content on multiple lines that has content on multiple lines
Text after a multiline element
- This is another
multiline list
#+begin_quote
With a block element inside
#+end_quote

View File

@ -551,7 +551,7 @@ class TestSerde(unittest.TestCase):
MarkerToken(closing=False, tok_type=MarkerType.UNDERLINED_MODE), MarkerToken(closing=False, tok_type=MarkerType.UNDERLINED_MODE),
"markup", "markup",
MarkerToken(closing=True, tok_type=MarkerType.UNDERLINED_MODE), MarkerToken(closing=True, tok_type=MarkerType.UNDERLINED_MODE),
".", ".", "\n"
], ],
) )
@ -567,7 +567,7 @@ class TestSerde(unittest.TestCase):
self.assertEqual(lists2[0][0].counter, "1") self.assertEqual(lists2[0][0].counter, "1")
self.assertEqual(lists2[0][0].counter_sep, ".") self.assertEqual(lists2[0][0].counter_sep, ".")
self.assertEqual(lists2[0][1].content, ["Second element"]) self.assertEqual(lists2[0][1].content, ["Second element", "\n"])
self.assertEqual(lists2[0][1].counter, "2") self.assertEqual(lists2[0][1].counter, "2")
self.assertEqual(lists2[0][1].counter_sep, ".") self.assertEqual(lists2[0][1].counter_sep, ".")
@ -575,7 +575,7 @@ class TestSerde(unittest.TestCase):
self.assertEqual(lists2[1][0].counter, "1") self.assertEqual(lists2[1][0].counter, "1")
self.assertEqual(lists2[1][0].counter_sep, ")") self.assertEqual(lists2[1][0].counter_sep, ")")
self.assertEqual(lists2[1][1].content, ["Second element"]) self.assertEqual(lists2[1][1].content, ["Second element", "\n"])
self.assertEqual(lists2[1][1].counter, "2") self.assertEqual(lists2[1][1].counter, "2")
self.assertEqual(lists2[1][1].counter_sep, ")") self.assertEqual(lists2[1][1].counter_sep, ")")
@ -583,13 +583,16 @@ class TestSerde(unittest.TestCase):
# ... # ...
lists4 = hl4.getLists() lists4 = hl4.getLists()
print(lists4) print(lists4)
self.assertEqual(len(lists4), 1) self.assertEqual(len(lists4), 2)
self.assertEqual(lists4[0][0].content, ["This is a list item...", "\n that spans multiple lines"]) self.assertEqual(lists4[0][0].content, ["This is a list item...", "\n that spans multiple lines", "\n"])
self.assertEqual(lists4[0][0].bullet, "-") self.assertEqual(lists4[0][0].bullet, "-")
self.assertEqual(lists4[0][1].content, ["This is another list item...", "\n that has content on multiple lines"]) self.assertEqual(lists4[0][1].content, ["This is another list item...", "\n that has content on multiple lines", "\n"])
self.assertEqual(lists4[0][1].bullet, "-") self.assertEqual(lists4[0][1].bullet, "-")
self.assertEqual(lists4[1][0].content, ["This is another", "\n multiline list", "\n"])
self.assertEqual(lists4[1][0].bullet, "-")
def test_org_roam_07(self): def test_org_roam_07(self):
with open(os.path.join(DIR, "07-org-roam-v2.org")) as f: with open(os.path.join(DIR, "07-org-roam-v2.org")) as f:
orig = f.read() orig = f.read()