Support updating ranges with contents with different size.
This commit is contained in:
parent
ebecc5feca
commit
83710a4fc1
@ -76,17 +76,33 @@ def get_tokens(value):
|
|||||||
|
|
||||||
|
|
||||||
class RangeInRaw:
|
class RangeInRaw:
|
||||||
def __init__(self, content, start, end):
|
def __init__(self, content, start_token, end_token):
|
||||||
self._content = content
|
self._content = content
|
||||||
self._start = start
|
self._start_id = id(start_token)
|
||||||
self._end = end
|
self._end_id = id(end_token)
|
||||||
|
|
||||||
def update_range(self, contents):
|
def update_range(self, new_contents):
|
||||||
if len(contents) == (self._end) - self._start:
|
# Find start token
|
||||||
for i in range(self._start, self._end):
|
for start_idx, tok in enumerate(self._content.contents):
|
||||||
self._content.contents[i] = contents[i - self._start]
|
if id(tok) == self._start_id:
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError()
|
raise Exception("Start token not found")
|
||||||
|
|
||||||
|
# Find end token
|
||||||
|
for offset, tok in enumerate(self._content.contents[start_idx:]):
|
||||||
|
if id(tok) == self._end_id:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise Exception("End token not found")
|
||||||
|
|
||||||
|
# Remove old contents
|
||||||
|
for i in range(1, offset):
|
||||||
|
self._content.contents.pop(start_idx + 1)
|
||||||
|
|
||||||
|
# Add new ones
|
||||||
|
for i, element in enumerate(new_contents):
|
||||||
|
self._content.contents.insert(start_idx + i + 1, element)
|
||||||
|
|
||||||
|
|
||||||
def get_links_from_content(content):
|
def get_links_from_content(content):
|
||||||
@ -99,11 +115,11 @@ def get_links_from_content(content):
|
|||||||
if isinstance(tok, LinkToken):
|
if isinstance(tok, LinkToken):
|
||||||
if tok.tok_type == LinkTokenType.OPEN_LINK:
|
if tok.tok_type == LinkTokenType.OPEN_LINK:
|
||||||
in_link = True
|
in_link = True
|
||||||
open_link_token = i + 1
|
open_link_token = tok
|
||||||
elif tok.tok_type == LinkTokenType.OPEN_DESCRIPTION:
|
elif tok.tok_type == LinkTokenType.OPEN_DESCRIPTION:
|
||||||
in_description = True
|
in_description = True
|
||||||
elif tok.tok_type == LinkTokenType.CLOSE:
|
elif tok.tok_type == LinkTokenType.CLOSE:
|
||||||
rng = RangeInRaw(content, open_link_token, i)
|
rng = RangeInRaw(content, open_link_token, tok)
|
||||||
yield Link(
|
yield Link(
|
||||||
"".join(link_value),
|
"".join(link_value),
|
||||||
"".join(link_description) if in_description else None,
|
"".join(link_description) if in_description else None,
|
||||||
|
@ -1,20 +1,9 @@
|
|||||||
from .org_dom import (
|
from .org_dom import (Bold, Code, Headline, Italic, Line, RawLine, Strike,
|
||||||
Bold,
|
Text, Underlined, Verbatim)
|
||||||
Code,
|
|
||||||
Headline,
|
|
||||||
Italic,
|
|
||||||
Line,
|
|
||||||
RawLine,
|
|
||||||
Strike,
|
|
||||||
Text,
|
|
||||||
Underlined,
|
|
||||||
Verbatim,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_hl_raw_contents(doc: Headline) -> str:
|
def get_hl_raw_contents(doc: Headline) -> str:
|
||||||
lines = []
|
lines = []
|
||||||
|
|
||||||
for content in doc.contents:
|
for content in doc.contents:
|
||||||
lines.append(get_raw_contents(content))
|
lines.append(get_raw_contents(content))
|
||||||
|
|
||||||
|
@ -11,3 +11,7 @@
|
|||||||
This is a [[https://codigoparallevar.com/1][web link]].
|
This is a [[https://codigoparallevar.com/1][web link]].
|
||||||
|
|
||||||
This is a /italized [[https://codigoparallevar.com/2][web link]]/.
|
This is a /italized [[https://codigoparallevar.com/2][web link]]/.
|
||||||
|
|
||||||
|
This is a link with no description to [[* First level]].
|
||||||
|
|
||||||
|
This is [[id:03-markup-first-level-id][a link to a section by id]].
|
||||||
|
@ -200,12 +200,19 @@ class TestSerde(unittest.TestCase):
|
|||||||
doc = load(f)
|
doc = load(f)
|
||||||
|
|
||||||
links = list(doc.get_links())
|
links = list(doc.get_links())
|
||||||
self.assertEqual(len(links), 2)
|
self.assertEqual(len(links), 4)
|
||||||
self.assertEqual(links[0].value, "https://codigoparallevar.com/1")
|
self.assertEqual(links[0].value, "https://codigoparallevar.com/1")
|
||||||
self.assertEqual(links[0].description, "web link")
|
self.assertEqual(links[0].description, "web link")
|
||||||
|
|
||||||
self.assertEqual(links[1].value, "https://codigoparallevar.com/2")
|
self.assertEqual(links[1].value, "https://codigoparallevar.com/2")
|
||||||
self.assertEqual(links[1].description, "web link")
|
self.assertEqual(links[1].description, "web link")
|
||||||
|
|
||||||
|
self.assertEqual(links[2].value, "* First level")
|
||||||
|
self.assertEqual(links[2].description, None)
|
||||||
|
|
||||||
|
self.assertEqual(links[3].value, "id:03-markup-first-level-id")
|
||||||
|
self.assertEqual(links[3].description, "a link to a section by id")
|
||||||
|
|
||||||
ex = Dom(
|
ex = Dom(
|
||||||
props=[
|
props=[
|
||||||
("TITLE", "03-Links"),
|
("TITLE", "03-Links"),
|
||||||
@ -238,17 +245,34 @@ class TestSerde(unittest.TestCase):
|
|||||||
),
|
),
|
||||||
".\n",
|
".\n",
|
||||||
),
|
),
|
||||||
|
SPAN("\n"),
|
||||||
|
SPAN(
|
||||||
|
" This is a link with no description to ",
|
||||||
|
WEB_LINK(None, "* First level"),
|
||||||
|
".\n",
|
||||||
|
),
|
||||||
|
SPAN("\n"),
|
||||||
|
SPAN(
|
||||||
|
" This is ",
|
||||||
|
WEB_LINK(
|
||||||
|
"a link to a section by id",
|
||||||
|
"id:03-markup-first-level-id",
|
||||||
|
),
|
||||||
|
".\n",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ex.assert_matches(self, doc)
|
||||||
|
|
||||||
def test_update_links_file_03(self):
|
def test_update_links_file_03(self):
|
||||||
with open(os.path.join(DIR, "03-links.org")) as f:
|
with open(os.path.join(DIR, "03-links.org")) as f:
|
||||||
doc = load(f)
|
doc = load(f)
|
||||||
|
|
||||||
links = list(doc.get_links())
|
links = list(doc.get_links())
|
||||||
self.assertEqual(len(links), 2)
|
self.assertEqual(len(links), 4)
|
||||||
self.assertEqual(links[0].value, "https://codigoparallevar.com/1")
|
self.assertEqual(links[0].value, "https://codigoparallevar.com/1")
|
||||||
self.assertEqual(links[0].description, "web link")
|
self.assertEqual(links[0].description, "web link")
|
||||||
links[0].value = "https://codigoparallevar.com/1-updated"
|
links[0].value = "https://codigoparallevar.com/1-updated"
|
||||||
@ -259,6 +283,16 @@ class TestSerde(unittest.TestCase):
|
|||||||
links[1].value = "https://codigoparallevar.com/2-updated"
|
links[1].value = "https://codigoparallevar.com/2-updated"
|
||||||
links[1].description = "web link #2 with update"
|
links[1].description = "web link #2 with update"
|
||||||
|
|
||||||
|
self.assertEqual(links[2].value, "* First level")
|
||||||
|
self.assertEqual(links[2].description, None)
|
||||||
|
links[2].value = "* Non-existent level"
|
||||||
|
links[2].description = "a description now"
|
||||||
|
|
||||||
|
self.assertEqual(links[3].value, "id:03-markup-first-level-id")
|
||||||
|
self.assertEqual(links[3].description, "a link to a section by id")
|
||||||
|
links[3].value = "id:03-markup-non-existent-level-id"
|
||||||
|
links[3].description = None
|
||||||
|
|
||||||
ex = Dom(
|
ex = Dom(
|
||||||
props=[
|
props=[
|
||||||
("TITLE", "03-Links"),
|
("TITLE", "03-Links"),
|
||||||
@ -295,6 +329,21 @@ class TestSerde(unittest.TestCase):
|
|||||||
),
|
),
|
||||||
".\n",
|
".\n",
|
||||||
),
|
),
|
||||||
|
SPAN("\n"),
|
||||||
|
SPAN(
|
||||||
|
" This is a link with no description to ",
|
||||||
|
WEB_LINK("a description now", "* Non-existent level"),
|
||||||
|
".\n",
|
||||||
|
),
|
||||||
|
SPAN("\n"),
|
||||||
|
SPAN(
|
||||||
|
" This is ",
|
||||||
|
WEB_LINK(
|
||||||
|
None,
|
||||||
|
"id:03-markup-non-existent-level-id",
|
||||||
|
),
|
||||||
|
".\n",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -2,17 +2,8 @@ import collections
|
|||||||
import unittest
|
import unittest
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from org_dom import (
|
from org_dom import (Bold, Code, Italic, Line, Strike, Text, Underlined,
|
||||||
Bold,
|
Verbatim, get_raw_contents)
|
||||||
Code,
|
|
||||||
Italic,
|
|
||||||
Line,
|
|
||||||
Strike,
|
|
||||||
Text,
|
|
||||||
Underlined,
|
|
||||||
Verbatim,
|
|
||||||
get_raw_contents,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def timestamp_to_datetime(ts):
|
def timestamp_to_datetime(ts):
|
||||||
@ -209,7 +200,10 @@ class WEB_LINK:
|
|||||||
self.link = link
|
self.link = link
|
||||||
|
|
||||||
def get_raw(self):
|
def get_raw(self):
|
||||||
|
if self.text:
|
||||||
return "[[{}][{}]]".format(self.link, self.text)
|
return "[[{}][{}]]".format(self.link, self.text)
|
||||||
|
else:
|
||||||
|
return "[[{}]]".format(self.link)
|
||||||
|
|
||||||
def assertEqual(self, test_case, other):
|
def assertEqual(self, test_case, other):
|
||||||
test_case.assertTrue(isinstance(other, WebLink))
|
test_case.assertTrue(isinstance(other, WebLink))
|
||||||
|
Loading…
Reference in New Issue
Block a user