63 lines
1.9 KiB
Python
Executable File
63 lines
1.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Simple org-babel tangle replacement.
|
|
Extracts #+BEGIN_SRC blocks with :tangle headers and writes target files.
|
|
"""
|
|
import re, os, sys
|
|
|
|
ORG_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
def tangle_file(org_path):
|
|
org_path = os.path.join(ORG_DIR, org_path)
|
|
with open(org_path) as f:
|
|
text = f.read()
|
|
|
|
# Find all #+BEGIN_SRC blocks with :tangle
|
|
pattern = re.compile(
|
|
r'#\+BEGIN_SRC\s+(\w+)\s+(.*?)\n(.*?)\n#\+END_SRC',
|
|
re.DOTALL
|
|
)
|
|
|
|
count = 0
|
|
for match in pattern.finditer(text):
|
|
lang = match.group(1)
|
|
header = match.group(2)
|
|
content = match.group(3)
|
|
|
|
# Extract :tangle path
|
|
tangle_match = re.search(r':tangle\s+(\S+)', header)
|
|
if not tangle_match:
|
|
continue
|
|
tangle_path = tangle_match.group(1)
|
|
|
|
# Resolve relative path
|
|
if tangle_path.startswith('../'):
|
|
target = os.path.normpath(os.path.join(os.path.dirname(org_path), tangle_path))
|
|
else:
|
|
target = os.path.join(ORG_DIR, tangle_path)
|
|
|
|
# Ensure directory exists
|
|
os.makedirs(os.path.dirname(target), exist_ok=True)
|
|
|
|
# Don't write :tangle no blocks
|
|
if tangle_path == 'no':
|
|
continue
|
|
|
|
# Write the content (append if same file already written)
|
|
content = content.rstrip('\n') + '\n'
|
|
if os.path.exists(target):
|
|
with open(target, 'a') as f:
|
|
f.write('\n' + content)
|
|
else:
|
|
with open(target, 'w') as f:
|
|
f.write(content)
|
|
print(f" {target} ({len(content)} bytes)")
|
|
count += 1
|
|
|
|
return count
|
|
|
|
if __name__ == '__main__':
|
|
for f in sys.argv[1:] or ['org/text-input.org']:
|
|
print(f"Tangling {f}...")
|
|
c = tangle_file(f)
|
|
print(f" {c} code blocks")
|