Revised README.md
This commit is contained in:
parent
24d91bd755
commit
7c25d2a20f
281
README.md
281
README.md
|
|
@ -1,10 +1,275 @@
|
|||
# PyOrgPatcher
|
||||
|
||||
PyOrgPatcher is a Python command-line utility that aid in workflows involving Emacs Org-Mode documents, as used in the PolyPaper project.
|
||||
|
||||
Functions:
|
||||
- List Org-Mode elements in an Org-Mode file that can be modified or extracted.
|
||||
- Replace the content of an Org-Mode element with text from STDIN or from a file.
|
||||
- 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.
|
||||
- Dry-run capability.
|
||||
|
||||
**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.”
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue