CommunityCodierung & Entwicklunggithub.com

Literate Programming & Tangling mit Org Babel

Anleitung für literarisches Programmieren, Code-Extraktion (Tangling), Noweb-Makroexpansion, Batch-Kompilierung und Konfigurationsverwaltung mit Org Babel.

Was ist Literate Programming & Tangling mit Org Babel?

Diese Fähigkeit ermöglicht es Entwicklern und KI-Agenten, das Konzept des Literate Programming (nach Donald Knuth) mit Org Babel zu nutzen, um menschenlesbare Dokumentation und ausführbaren Maschinencode aus einer einzigen Quelle zu verwalten. Sie unterstützt die Extraktion von Code-Blöcken in separate Dateien (Tangling) sowie die modulare Zusammenstellung von Code über Noweb-Referenzen. Die Integration in CI/CD-Pipelines und Makefiles wird durch headless Emacs-Batch-Befehle ermöglicht, sodass Code-Generierung und -Kompilierung automatisiert werden können. Die Fähigkeit ist plattformunabhängig und funktioniert mit Org-Dateien, die auf Emacs basieren, aber auch in CI-Umgebungen ohne grafische Oberfläche. Der Skill bietet detaillierte Kontrolle über Tangle-Pfade, Berechtigungen, Noweb-Expansion und Einrückungsverhalten, speziell für sprachsensitive Sprachen wie Python.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/pwquint24/org-babel-agent-skills/tree/HEAD/skills/org-babel-literate-tangle

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Literarisches Programmieren & Tangling mit Org Babel

Org Babel ist eine Implementierung von Donald Knuths Literate Programming-Paradigma. Anstatt Code mit vereinzelten Kommentaren zu schreiben, verfasst man menschenorientierte Prosa, Architekturnotizen und Designentscheidungen und bettet die funktionalen Code-Blöcke darin ein.

Eine einzige Org-Datei dient als endgültige Quelle der Wahrheit für zwei unterschiedliche Ausgaben:

  1. Weaving (Menschliche Dokumentation): Export des Notebooks in formatiertes HTML, LaTeX/PDF oder Markdown für Leser.
  2. Tangling (Maschinenausführung): Extrahieren von reinen, ausführbaren Quellcodedateien (.py, .sh, .c, .conf, .el) für Compiler, Interpreter und Bereitstellungssysteme.

1. Grundlagen des Tangelings: Das :tangle-Header-Argument

Standardmäßig werden Code-Blöcke nicht getangelt. Die :tangle-Familie von Header-Argumenten gibt an, wo und wie Blöcke auf die Festplatte extrahiert werden.

1.1 Die :tangle-Argumentwerte

WertVerhalten
:tangle no (Standard)Block wird in keine Datei geschrieben. (Kann dennoch über <<noweb>> in anderen Blöcken eingefügt werden.)
:tangle "path/to/file.py"Schreibt den Blockkörper direkt in die angegebene Datei (relativ zum Puffer-Verzeichnis oder absolut).
:tangle yesTangelt in eine Datei, die dem Basisnamen der Org-Datei mit der standardmäßigen Dateierweiterung der Sprache entspricht (z. B. model.org -> model.py).

1.2 Zusätzliche Tangle-Header-Argumente

  • :shebang "#!/usr/bin/env python3": Fügt die angegebene Shebang-Zeichenkette als erste Zeile der getangelten Datei ein.
  • :tangle-mode (identity #o755): Setzt Dateisystemberechtigungen für die generierte Datei (z. B. #o755 macht ein Skript ausführbar).
  • :no-expand: Verhindert, dass Variablenzuweisungen (:var) in den getangelten Code eingefügt werden; schreibt nur den rohen Blockkörper.
  • :mkdirp yes: Erstellt automatisch alle nicht existierenden übergeordneten Verzeichnisse im Tangle-Pfad.

2. Tangle-Geltungsbereich: Block-, Unterbaum- und Pufferebene

Tangle-Argumente können sauber über ein gesamtes Projekt hinweg definiert werden:

2.1 Unterbaum-Ebene Tangling (Empfohlenes Muster)

Verschiedene Überschriften können in unterschiedliche Dateien oder Module tangeln:

* Kernfunktionen
:PROPERTIES:
:header-args:python: :tangle src/utils.py :mkdirp yes
:END:

#+BEGIN_SRC python
  def slugify(text: str) -> str:
      return "-".join(text.lower().split())
#+END_SRC

* Datenverarbeitungspipeline
:PROPERTIES:
:header-args:python: :tangle src/pipeline.py :mkdirp yes
:END:

#+BEGIN_SRC python
  from utils import slugify

  def process_record(rec: dict) -> dict:
      rec["slug"] = slugify(rec["name"])
      return rec
#+END_SRC

2.2 Pufferweiter Tangle-Standard

Am Anfang der Datei setzen:

#+PROPERTY: header-args:python :tangle src/main.py

3. Noweb-Syntax: Modulare Code-Zusammenstellung

Noweb ermöglicht es Ihnen, größere Quelldateien aus kleineren, modularen, leicht erklärbaren Fragmenten zusammenzusetzen. Sie verweisen mit <<block_name>> auf einen Code-Block innerhalb eines anderen.

3.1 Noweb-Erweiterung aktivieren

Noweb ist standardmäßig deaktiviert. Steuern Sie es mit dem :noweb-Header-Argument:

:noweb-WertIn Emacs ausgewertet?Auf Festplatte getangelt?Im Dokument exportiert?
no (Standard)NeinNeinNein
yesJaJaJa
tangleNeinJaNein
strip-tangleJaNein (Referenzen entfernt)Ja
no-exportJaJaNein
evalJaNeinNein

3.2 Noweb-Beispiel: Literarische Skriptkonstruktion

#+NAME: imports
#+BEGIN_SRC python :exports none
  import sys
  import argparse
  from pathlib import Path
#+END_SRC

#+NAME: argument-parser
#+BEGIN_SRC python :exports code
  parser = argparse.ArgumentParser(description="Prozessdatensatz.")
  parser.add_argument("--input", required=True, type=Path, help="Pfad zur CSV-Eingabe")
  parser.add_argument("--threshold", default=0.5, type=float, help="Score-Grenzwert")
  args = parser.parse_args()
#+END_SRC

#+NAME: process-data
#+BEGIN_SRC python :exports code
  print(f"Lade Daten von {args.input}...")
  # Verarbeitungslogik hier
#+END_SRC

# Zusammenstellung des endgültigen ausführbaren Skripts:
#+NAME: main-cli
#+BEGIN_SRC python :tangle bin/run_pipeline.py :shebang "#!/usr/bin/env python3" :tangle-mode (identity #o755) :noweb yes :exports none
  <<imports>>

  def main():
      <<argument-parser>>
      <<process-data>>

  if __name__ == "__main__":
      main()
#+END_SRC

Beim Tangling wird bin/run_pipeline.py als sauberes, ausführbares Skript mit allen korrekt platzierten und eingerückten Fragmenten geschrieben!

3.3 Noweb-Präfix & Einrückung

  • Noweb beachtet Einrückungen: Wenn <<argument-parser>> innerhalb von def main(): um 4 Leerzeichen eingerückt ist, wird jede Zeile des expandierten Blocks um 4 Leerzeichen eingerückt.
  • Zum Deaktivieren des Präfixverhaltens: :noweb-prefix no.
  • Um die Ergebnisse der Ausführung eines Blocks anstelle seines Quellcodes einzufügen, fügen Sie Klammern an: <<compute_constant()>>

3.4 Debuggen der Expansion

Um zu überprüfen, wie Noweb-Blöcke vor dem Tangling oder Ausführen expandiert werden:

  • Setzen Sie den Punkt innerhalb des Blocks und drücken Sie C-c C-v v (org-babel-expand-src-block).
  • Org öffnet einen temporären Puffer, der den genauen Code nach allen Noweb- und :var-Substitutionen anzeigt.

4. Einbetten von Konfiguration und Daten in getangelte Dateien

Babel kann Variablen aus Org-Tabellen oder Überschrifteneigenschaften direkt in getangelten Code einbetten:

# Konfiguration, gespeichert in einer Org-Tabelle:
#+NAME: server_config
| Key     | Value            |
|---------+------------------|
| host    | 10.0.1.25        |
| port    | 8080             |
| timeout | 30               |

# Das getangelte Konfigurationsmodul:
#+BEGIN_SRC python :tangle config.py :var cfg=server_config :colnames yes
  HOST = cfg[0][1]
  PORT = int(cfg[1][1])
  TIMEOUT = int(cfg[2][1])
#+END_SRC

Um zu verhindern, dass Babel Variablen-Wrapper im getangelten Code erzeugt, übergeben Sie :no-expand.


5. Einrückungsbehandlung: Leerraum-empfindliche Sprachen

In leerraum-empfindlichen Sprachen wie Python oder YAML kann die automatische Org-Neueinrückung die Syntax beschädigen.

Wichtige Regel für Python-Tangling:

Setzen Sie org-src-preserve-indentation auf t. Wenn t, entfernt oder fügt Org keine Einrückung während des Exports oder Tangelings hinzu:

;; In der Emacs-Konfiguration:
(setq org-src-preserve-indentation t)

Oder pro Block mit dem Schalter -i:

#+BEGIN_SRC python -i :tangle script.py

6. Wie man Tangling ausführt

6.1 Interaktiv in Emacs

TastenkombinationBefehlBeschreibung
C-c C-v t / C-c C-v C-torg-babel-tangleTangelt alle Code-Blöcke im aktuellen Puffer.
C-c C-v f / C-c C-v C-forg-babel-tangle-fileFragt nach einer Org-Datei auf der Festplatte und tangelt sie.

6.2 Navigation von getangelten Dateien zurück zum Org

Beim Tangling fügt Babel Rückverweis-Kommentare in generierte Dateien ein:

# [[file:~/project/notebook.org::*Kernfunktionen][core-slugify]]
def slugify(text: str) -> str:
...
# core-slugify endet hier

In Emacs: Öffnen Sie die generierte Datei und führen Sie M-x org-babel-tangle-jump-to-org aus, um sofort zur genauen Überschrift und zum Block im Quell-.org-Dokument zu springen!

6.3 Kopflose Kommandozeile / CI / Make Batch-Tangling

Tangle-Dateien ohne grafische Emacs-Oberfläche (ideal für Build-Skripte, Makefiles und Continuous Integration):

# Einzelne Datei tangeln:
emacs -Q --batch \
  --eval "(require 'org)" \
  --eval "(require 'ob-tangle)" \
  --eval '(org-babel-tangle-file "analysis.org")'

# Mehrere Dateien aus einer Shell-Schleife oder einem Makefile tangeln:
emacs -Q --batch --eval "
  (progn
    (require 'org)
    (require 'ob-tangle)
    (dolist (file command-line-args-left)
      (with-current-buffer (find-file-noselect file)
        (org-babel-tangle))))" *.org

7. Literarisches Konfigurationsmanagement: Das init.org-Muster

Ein häufiger Anwendungsfall für Org Babel Literate Programming ist die Verwaltung von Emacs-Konfigurationen oder System-Dotfiles.

In ~/.emacs.d/init.el:

;; Bootstrap der literarischen Org Babel-Konfiguration
(require 'org)
(require 'ob-tangle)
(org-babel-load-file (expand-file-name "config.org" user-emacs-directory))

org-babel-load-file prüft automatisch, ob config.org seit der letzten Generierung von config.el geändert wurde, tangelt bei Bedarf die neue Version und lädt die resultierende .el-Datei.


8. Zusammenfassungs-Checkliste für Tangle-Projekte

  1. Explizite Tangle-Pfade: Verwenden Sie explizite Dateinamen (z. B. :tangle "src/core.py").
  2. Noweb für Lesbarkeit verwenden: Zerlegen Sie komplexe Algorithmen in logische Schritte (<<init-weights>>, <<forward-pass>>, <<backprop>>), damit der Erzählfluss für Leser natürlich bleibt.
  3. Einrückung bewahren: Stellen Sie sicher, dass org-src-preserve-indentation für Python-Code auf t gesetzt ist.
  4. Mit Make/CI automatisieren: Fügen Sie einen kopflosen emacs --batch-Tangling-Schritt in Ihr Build-System ein, um generierten Quellcode mit dem Org-Dokument synchron zu halten.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Verwandte Skills