Revised README.md
This commit is contained in:
parent
24d91bd755
commit
7c25d2a20f
281
README.md
281
README.md
|
|
@ -1,10 +1,275 @@
|
||||||
# PyOrgPatcher
|
# PyOrgPatcher
|
||||||
|
|
||||||
PyOrgPatcher is a Python command-line utility that aid in workflows involving Emacs Org-Mode documents, as used in the PolyPaper project.
|
**PyOrgPatcher** is a lightweight command-line utility and Python library for **programmatically editing, extracting, and synchronizing parts of Org-mode documents** — all without Emacs.
|
||||||
|
|
||||||
Functions:
|
It provides a simple way to patch Org files from scripts, CI/CD jobs, or AI agents, making it ideal for:
|
||||||
- List Org-Mode elements in an Org-Mode file that can be modified or extracted.
|
- Collaborators who work with Org files but don’t use Emacs.
|
||||||
- Replace the content of an Org-Mode element with text from STDIN or from a file.
|
- Reproducible research pipelines using literate programming.
|
||||||
- With a JSON configuration, either extract multiple Org-Mode elements to associated files (without noweb substitution) or update an Org-Mode document's specified elements with the contents of files.
|
- AI systems (e.g., LangChain, LangGraph, or MCP agents) that maintain structured text and code artifacts.
|
||||||
- Dry-run capability.
|
|
||||||
|
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.”
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue