131 lines
4.2 KiB
Python
Executable File
131 lines
4.2 KiB
Python
Executable File
import sys
|
|
from pathlib import Path
|
|
|
|
# Import module from same folder
|
|
sys.path.insert(0, str(Path(__file__).parent))
|
|
import orgpatch as op
|
|
|
|
EXAMPLE_ORG = """* Main Title
|
|
** Introduction
|
|
Some intro text.
|
|
|
|
#+NAME: intro-para
|
|
This is a named paragraph that will be replaced.
|
|
It continues until the first blank line.
|
|
|
|
** Data
|
|
#+NAME: mytable
|
|
| Item | Value |
|
|
|------+-------|
|
|
| A | 1 |
|
|
| B | 2 |
|
|
|
|
** Code
|
|
#+NAME: code-snippet
|
|
#+BEGIN_SRC python
|
|
print("hello world")
|
|
#+END_SRC
|
|
|
|
** My Section
|
|
This section body will be replaced.
|
|
It ends at the next heading of level ** or *.
|
|
|
|
** Another Section
|
|
Content of another section.
|
|
"""
|
|
|
|
def write(p: Path, text: str):
|
|
p.write_text(text, encoding="utf-8")
|
|
|
|
def test_parse_headings_and_sections(tmp_path: Path):
|
|
org = tmp_path / "example.org"
|
|
write(org, EXAMPLE_ORG)
|
|
lines = op.read_lines(str(org))
|
|
heads = op.parse_headings(lines)
|
|
titles = [h['title'] for h in heads]
|
|
assert "Introduction" in titles
|
|
assert "My Section" in titles
|
|
b = op.section_bounds(lines, heads, "** My Section")
|
|
assert b is not None
|
|
s, e = b
|
|
body = ''.join(lines[s:e])
|
|
assert "This section body will be replaced." in body
|
|
|
|
def test_parse_named_elements(tmp_path: Path):
|
|
org = tmp_path / "example.org"
|
|
write(org, EXAMPLE_ORG)
|
|
lines = op.read_lines(str(org))
|
|
elems = op.parse_named_elements(lines)
|
|
names = {e['name']: e for e in elems}
|
|
assert names['intro-para']['type'] == 'para'
|
|
assert names['mytable']['type'] == 'table'
|
|
assert names['code-snippet']['type'] == 'block'
|
|
|
|
def test_replace_section(tmp_path: Path):
|
|
org = tmp_path / "example.org"
|
|
write(org, EXAMPLE_ORG)
|
|
lines = op.read_lines(str(org))
|
|
out = op.replace_section(lines, "** My Section", "New body\nMore\n")
|
|
joined = ''.join(out)
|
|
assert "New body" in joined
|
|
assert "This section body will be replaced." not in joined
|
|
|
|
def test_replace_named_block_table_para(tmp_path: Path):
|
|
org = tmp_path / "example.org"
|
|
write(org, EXAMPLE_ORG)
|
|
lines = op.read_lines(str(org))
|
|
|
|
out = op.replace_named(lines, "code-snippet", "print('updated')\n")
|
|
assert "print('updated')" in ''.join(out)
|
|
|
|
out2 = op.replace_named(out, "mytable", "| X | 9 |\n")
|
|
assert "| X | 9 |" in ''.join(out2)
|
|
|
|
out3 = op.replace_named(out2, "intro-para", "New intro\nSecond\n")
|
|
j3 = ''.join(out3)
|
|
assert "New intro" in j3
|
|
assert "named paragraph that will be replaced" not in j3
|
|
|
|
def test_sync_in_and_out(tmp_path: Path):
|
|
org = tmp_path / "example.org"
|
|
write(org, EXAMPLE_ORG)
|
|
|
|
code_src = tmp_path / "code.py"
|
|
tbl_src = tmp_path / "tbl.org"
|
|
sec_src = tmp_path / "section.txt"
|
|
para_src = tmp_path / "intro.txt"
|
|
write(code_src, "print('via in')\n")
|
|
write(tbl_src, "| Col | Val |\n|-----+-----|\n| A | 1 |\n")
|
|
write(sec_src, "Replaced via sync in.\nSecond line.\n")
|
|
write(para_src, "Intro via sync in.\n\n")
|
|
|
|
mapping = [
|
|
{"name": "code-snippet", "file": str(code_src)},
|
|
{"name": "mytable", "file": str(tbl_src)},
|
|
{"section": "** My Section", "file": str(sec_src)},
|
|
{"name": "intro-para", "file": str(para_src)},
|
|
]
|
|
|
|
lines = op.read_lines(str(org))
|
|
new_lines = op.sync_apply_in(lines, mapping)
|
|
out = ''.join(new_lines)
|
|
assert "print('via in')" in out
|
|
assert "| Col | Val |" in out
|
|
assert "Replaced via sync in." in out
|
|
assert "Intro via sync in." in out
|
|
|
|
export_dir = tmp_path / "exported"
|
|
export_dir.mkdir()
|
|
m_out = [
|
|
{"name": "code-snippet", "file": str(export_dir / "code.py")},
|
|
{"name": "mytable", "file": str(export_dir / "table.org")},
|
|
{"section": "** My Section", "file": str(export_dir / "section.txt")},
|
|
{"name": "intro-para", "file": str(export_dir / "intro.txt")},
|
|
]
|
|
op.sync_apply_out(new_lines, m_out, mkdirs=True, overwrite=True)
|
|
|
|
assert (export_dir / "code.py").read_text(encoding="utf-8").strip() == "print('via in')"
|
|
assert "| Col | Val |" in (export_dir / "table.org").read_text(encoding="utf-8")
|
|
assert "Replaced via sync in." in (export_dir / "section.txt").read_text(encoding="utf-8")
|
|
assert "Intro via sync in." in (export_dir / "intro.txt").read_text(encoding="utf-8")
|