276 lines
7.1 KiB
Markdown
276 lines
7.1 KiB
Markdown
# PyOrgPatcher
|
||
|
||
**PyOrgPatcher** is a lightweight command-line utility and Python library for **programmatically editing, extracting, and synchronizing parts of Org-mode documents** — all without Emacs.
|
||
|
||
It provides a simple way to patch Org files from scripts, CI/CD jobs, or AI agents, making it ideal for:
|
||
- Collaborators who work with Org files but don’t use Emacs.
|
||
- Reproducible research pipelines using literate programming.
|
||
- AI systems (e.g., LangChain, LangGraph, or MCP agents) that maintain structured text and code artifacts.
|
||
|
||
All components are under:
|
||
|
||
```
|
||
|
||
./code/
|
||
├── orgpatch.py # main tool
|
||
├── example.org # demonstration Org file
|
||
└── test_orgpatch.py # pytest unit tests
|
||
|
||
````
|
||
|
||
---
|
||
|
||
## 🔧 Installation & Setup
|
||
|
||
### 1. Requirements
|
||
|
||
- **Python 3.8+**
|
||
- **pytest** (for testing)
|
||
|
||
Install dependencies:
|
||
|
||
```bash
|
||
python3 -m venv venv
|
||
source venv/bin/activate
|
||
pip install pytest
|
||
````
|
||
|
||
### 2. Clone or Copy the Tool
|
||
|
||
```bash
|
||
git clone https://git,cns.fyi/welsberr/PyOrgPatcher.git
|
||
cd PyOrgPatcher/code
|
||
```
|
||
|
||
You can also copy just `orgpatch.py` to any project — it’s self-contained and requires no external libraries.
|
||
|
||
---
|
||
|
||
## 🧩 Example Org File
|
||
|
||
[`example.org`](./example.org) demonstrates the types of elements PyOrgPatcher understands:
|
||
|
||
```org
|
||
* Main Title
|
||
** Introduction
|
||
Some intro text.
|
||
|
||
#+NAME: intro-para
|
||
This is a named paragraph that will be replaced.
|
||
|
||
** 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.
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 Basic Command-Line Usage
|
||
|
||
List available patch targets:
|
||
|
||
```bash
|
||
./orgpatch.py list example.org
|
||
```
|
||
|
||
Replace a section body:
|
||
|
||
```bash
|
||
./orgpatch.py replace example.org --section "** My Section" --from section.txt
|
||
```
|
||
|
||
Replace a named block or table:
|
||
|
||
```bash
|
||
./orgpatch.py replace example.org --name code-snippet --from code.py
|
||
```
|
||
|
||
Or from standard input:
|
||
|
||
```bash
|
||
printf "| X | 42 |\n" | ./orgpatch.py replace example.org --name mytable --stdin
|
||
```
|
||
|
||
Use `--backup` to create `example.org.bak`.
|
||
|
||
---
|
||
|
||
## 🔄 JSON Sync Mode
|
||
|
||
Batch operations for multiple elements are defined via JSON mappings.
|
||
|
||
### Example: `mapping.json`
|
||
|
||
```json
|
||
[
|
||
{"name": "code-snippet", "file": "code.py"},
|
||
{"name": "mytable", "file": "table.org"},
|
||
{"section": "** My Section", "file": "section.txt"}
|
||
]
|
||
```
|
||
|
||
### Apply Updates *into* the Org File (files → Org)
|
||
|
||
```bash
|
||
./orgpatch.py sync example.org --map mapping.json --direction in --backup
|
||
```
|
||
|
||
### Export Org Elements *to* Files (Org → files)
|
||
|
||
```bash
|
||
./orgpatch.py sync example.org --map mapping.json --direction out --mkdirs
|
||
```
|
||
|
||
Options:
|
||
|
||
* `--dry-run` — preview only
|
||
* `--backup` — create a backup before modifying
|
||
* `--mkdirs` — create destination folders automatically
|
||
* `--no-overwrite` — skip existing files on export
|
||
|
||
---
|
||
|
||
## 🧪 Running Unit Tests
|
||
|
||
A complete [pytest](https://docs.pytest.org) test suite is included:
|
||
|
||
```bash
|
||
pytest -q
|
||
```
|
||
|
||
This validates:
|
||
|
||
* Parsing of headings and `#+NAME:` blocks
|
||
* Section replacement
|
||
* Named block/table/paragraph replacement
|
||
* JSON mapping synchronization (`sync in` and `sync out`)
|
||
|
||
---
|
||
|
||
## 🧠 Integrating with AI Agent Tooling
|
||
|
||
### Why It Matters
|
||
|
||
Org-mode provides a **hierarchical, semantic structure** perfect for literate programming, documentation, and multi-language code notebooks — but until now, most AI systems couldn’t safely manipulate it without Emacs or brittle regex hacks.
|
||
|
||
**PyOrgPatcher** changes that:
|
||
It gives AI agents and LLM-based systems a structured interface to read, patch, and synchronize `.org` files, **treating them as composable data artifacts**.
|
||
|
||
### Example: Agent Workflow
|
||
|
||
Imagine an **AI documentation agent** that:
|
||
|
||
1. Reads `mapping.json` to identify relevant files and blocks.
|
||
2. Rebuilds code snippets or analyses (e.g., retraining results, data summaries).
|
||
3. Calls `orgpatch.py` (or its Python API) to update the corresponding Org blocks.
|
||
|
||
This lets an AI system manage “literate” files safely without needing to regenerate the entire Org document.
|
||
|
||
### In LangChain / LangGraph
|
||
|
||
Within a LangChain or LangGraph workflow, you can use `PyOrgPatcher` as a tool node:
|
||
|
||
```python
|
||
from langchain.tools import tool
|
||
import subprocess, json
|
||
|
||
@tool("update_org_block")
|
||
def update_org_block(name: str, content: str):
|
||
"""Update a named Org-mode block in example.org."""
|
||
cmd = [
|
||
"python3", "orgpatch.py", "replace", "example.org",
|
||
"--name", name, "--stdin"
|
||
]
|
||
subprocess.run(cmd, input=content.encode("utf-8"), check=True)
|
||
return f"Updated block '{name}' successfully."
|
||
```
|
||
|
||
Agents can then call this tool directly:
|
||
|
||
```python
|
||
update_org_block("analysis-results", "Mean=42\nStd=7.5\n")
|
||
```
|
||
|
||
Similarly, a chain could:
|
||
|
||
* Use `sync in` to load generated files into an Org document.
|
||
* Use `sync out` to extract tables or code for downstream tasks (e.g., testing, publishing, or compiling).
|
||
|
||
### Multi-Component Patch (MCP) Integration
|
||
|
||
In MCP-style systems — where AI agents patch **specific parts of multi-file projects** —
|
||
PyOrgPatcher acts as the **Org-layer patcher**:
|
||
|
||
* `sync in` = inject AI-generated code, results, or summaries.
|
||
* `sync out` = extract training data, code snippets, or narrative text.
|
||
* `replace` = fine-grained control of a single element in context.
|
||
|
||
This makes it ideal for **AI-assisted research notebooks**, **literate AI model reports**, and **collaborative documentation systems**.
|
||
|
||
---
|
||
|
||
## 🧰 Python Library Usage
|
||
|
||
PyOrgPatcher can also be used as a Python module:
|
||
|
||
```python
|
||
import orgpatch as op
|
||
|
||
lines = op.read_lines("example.org")
|
||
new_lines = op.replace_named(lines, "code-snippet", "print('updated via API')\n")
|
||
op.write_lines("example.org", new_lines)
|
||
```
|
||
|
||
This makes it easy to integrate into scripts or notebooks.
|
||
|
||
---
|
||
|
||
## 🧬 Example Use Case: Non-Emacs Collaboration
|
||
|
||
Researchers, engineers, or students who use VS Code, Sublime, or other editors can:
|
||
|
||
* Edit external files (`.py`, `.csv`, `.txt`) directly.
|
||
* Let an automated process update `main.org` via `sync in`.
|
||
* Keep the literate record synchronized without ever opening Emacs.
|
||
|
||
This lowers the barrier for collaboration in mixed-editor teams.
|
||
|
||
---
|
||
|
||
## 🏁 Summary
|
||
|
||
| Feature | Description |
|
||
| -------------------------- | ---------------------------------------------------- |
|
||
| **CLI + Library** | Command-line and Python module usage |
|
||
| **Emacs-Free Editing** | Safely patch `.org` files without Emacs |
|
||
| **JSON Batch Mode** | Bulk updates and exports |
|
||
| **AI/Automation Ready** | Ideal for LangChain, LangGraph, or MCP agents |
|
||
| **Fully Tested** | Comprehensive pytest suite included |
|
||
| **Collaboration-Friendly** | Perfect for teams mixing Org-mode with other editors |
|
||
|
||
---
|
||
|
||
**Author:** Wesley R. Elsberry
|
||
**Project:** PyOrgPatcher
|
||
**License:** MIT
|
||
**Location:** `./code/`
|
||
|
||
> “PyOrgPatcher bridges human-readable structure and machine-editable precision — empowering both collaborators and intelligent agents to work fluently with Org-mode documents.”
|
||
|
||
```
|
||
|
||
---
|
||
|