55 lines
2.5 KiB
Python
Executable File
55 lines
2.5 KiB
Python
Executable File
import subprocess
|
|
import json
|
|
import os
|
|
import argparse
|
|
from typing import Dict, Any, Optional
|
|
|
|
class OrgBridge:
|
|
def __init__(self, lisp_script_path: str = os.path.join(os.path.dirname(__file__), "org-json-bridge.el")):
|
|
self.lisp_path = os.path.abspath(lisp_script_path)
|
|
|
|
def _run_emacs_batch(self, command: str, *args) -> str:
|
|
"""Helper to execute the Emacs batch command with arguments."""
|
|
cmd = [
|
|
"emacs", "--batch",
|
|
"-l", self.lisp_path,
|
|
"--", command, *args
|
|
]
|
|
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
return result.stdout.strip()
|
|
|
|
def parse_to_dict(self, file_path: str) -> Dict[str, Any]:
|
|
"""Reads an Org file and returns its AST as a Python Dictionary."""
|
|
abs_path = os.path.abspath(file_path)
|
|
json_output = self._run_emacs_batch("org-to-json", abs_path)
|
|
return json.loads(json_output)
|
|
|
|
def write_from_dict(self, ast_dict: Dict[str, Any], output_path: str):
|
|
"""Takes a Python Dictionary (AST) and writes it back to an Org file."""
|
|
json_input = json.dumps(ast_dict)
|
|
abs_output_path = os.path.abspath(output_path)
|
|
self._run_emacs_batch("json-to-org", json_input, abs_output_path)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Org-mode to JSON bridge for programmatic manipulation.")
|
|
parser.add_argument("action", choices=["parse", "render"], help="Action to perform: 'parse' an Org file to JSON, or 'render' JSON to an Org file.")
|
|
parser.add_argument("--file-path", help="Path to the Org-mode file (required for 'parse' action).")
|
|
parser.add_argument("--json-input-file", help="Path to a JSON file containing the AST (required for 'render' action).")
|
|
parser.add_argument("--output-file", help="Path to output the Org-mode file (required for 'render' action).")
|
|
|
|
args = parser.parse_args()
|
|
bridge = OrgBridge()
|
|
|
|
if args.action == "parse":
|
|
if not args.file_path:
|
|
parser.error("--file-path is required for the 'parse' action.")
|
|
org_ast = bridge.parse_to_dict(args.file_path)
|
|
print(json.dumps(org_ast, indent=2))
|
|
elif args.action == "render":
|
|
if not args.json_input_file or not args.output_file:
|
|
parser.error("--json-input-file and --output-file are required for the 'render' action.")
|
|
with open(args.json_input_file, 'r') as f:
|
|
ast_dict = json.load(f)
|
|
bridge.write_from_dict(ast_dict, args.output_file)
|