Chapter 11: Code Blocks and Literate Programming - Executable Documents
Remember in Chapter 3 when we mentioned code blocks? Time to unlock their full power. Org-Mode code blocks aren’t just syntax highlighting—they’re executable. Your documentation can run programs, generate output, produce graphs, and manipulate data.
Welcome to literate programming: where code and documentation are one.
1. The Basic Code Block
We’ve seen this syntax:
#+BEGIN_SRC python
def hello():
print("Hello from Org-Mode!")
#+end_src
But here’s the magic. Put cursor in the block and press C-c C-c:
#+RESULTS: : Hello from Org-Mode!
The code executed. The output appeared. In your plain text document.
Let that sink in.
2. Enabling Code Execution
First, allow languages you’ll use:
(org-babel-do-load-languages 'org-babel-load-languages '((python . t) (shell . t) (emacs-lisp . t) (js . t) (ruby . t) (sql . t) (sqlite . t) (dot . t) (R . t)))
Enable what you need. Org supports dozens of languages.
For security, confirm before execution:
(setq org-confirm-babel-evaluate t) ; Prompt before running code
Or disable for trusted files:
(setq org-confirm-babel-evaluate nil) ; Run without prompting (careful!)
Or per-language:
(setq org-confirm-babel-evaluate (lambda (lang body) (not (member lang '("python" "emacs-lisp")))))
Prompt for most languages, but not Python or Elisp.
3. Editing Code Blocks
Press C-c ' (Control-c single-quote) inside a code block.
A new buffer opens with:
- Full language mode activated (Python mode, JS mode, etc.)
- Syntax highlighting
- Language-specific features (indentation, completion, linting)
- All your normal coding tools
Edit comfortably. Press C-c ' again—changes transfer back to org file.
This is how you write real code in org documents without losing coding conveniences.
4. Code Block Headers
Control execution with header arguments:
#+BEGIN_SRC python :results output :exports both
print("Line 1")
print("Line 2")
print("Line 3")
#+end_src
Execute with C-c C-c:
#+RESULTS: : Line 1 : Line 2 : Line 3
4.1. Essential Header Arguments
:results - How to handle output:
:results output- Capture stdout (print statements):results value- Return value of last expression:results silent- Execute but don’t show results:results replace- Replace existing results (default):results append- Add to existing results
:exports - What to export in documents:
:exports code- Only code:exports results- Only results:exports both- Code and results:exports none- Neither (execute but hide)
:session - Persistent environment:
:session- Use default session:session mysession- Named session- No session - Fresh environment each time
:var - Pass variables:
:var x=5- Variable from value:var data=table-name- Variable from org table:var x=other-block- Variable from another block’s output
More headers coming…
5. Session-Based Execution
Without sessions, each block runs in isolation:
#+BEGIN_SRC python x = 42 #+end_src
print(x) # Error: x not defined
With sessions, state persists:
#+BEGIN_SRC python :session x = 42 #+end_src
print(x) # Works! Outputs: 42
Same Python interpreter, same namespace. Variables, functions, imports—all persist.
Multiple named sessions:
#+BEGIN_SRC python :session project-a x = 1 #+end_src
x = 2
Separate environments, same document.
6. Passing Data Between Blocks
6.1. Variables from Values
#+BEGIN_SRC python :var name="Alice" age=30
print(f"{name} is {age} years old")
#+end_src
Alice is 30 years old
6.2. Variables from Tables
#+NAME: sales-data | Product | Q1 | Q2 | Q3 | Q4 | |---------+----+----+----+----| | Widget | 10 | 15 | 12 | 18 | | Gadget | 20 | 25 | 30 | 28 | #+BEGIN_SRC python :var data=sales-data import pandas as pd df = pd.DataFrame(data[1:], columns=data[0]) print(df.sum(numeric_only=True)) #+end_src
Q1 30 Q2 40 Q3 42 Q4 46
Table becomes 2D list. Process with any language.
6.3. Variables from Block Output
#+NAME: generate-data #+BEGIN_SRC python return [1, 2, 3, 4, 5] #+end_src
print(sum(numbers))
15
Chain blocks together. One block’s output feeds another’s input.
7. Returning Results to Tables
Code can generate tables:
#+BEGIN_SRC python :results value table
return [
['Name', 'Age', 'City'],
['Alice', 28, 'Portland'],
['Bob', 35, 'Seattle'],
['Carol', 42, 'Vancouver']
]
#+end_src
| Name | Age | City |
|---|---|---|
| Alice | 28 | Portland |
| Bob | 35 | Seattle |
| Carol | 42 | Vancouver |
Generate org tables from code. Add formulas. Instant data reports.
8. Graphics and Plots
Generate graphs:
#+BEGIN_SRC python :results file
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title('Sine Wave')
plt.savefig('sine.png')
return 'sine.png'
#+end_src
The plot appears in your document. Update code, re-execute, plot updates.
With R:
#+BEGIN_SRC R :results graphics file :file plot.png plot(cars) #+end_src
With gnuplot, ditaa, graphviz—dozens of options.
9. Literate Programming: The Full Vision
Donald Knuth’s original idea: write programs as explanations, with code woven throughout.
#+begin_example
10. Calculate Fibonacci Numbers
The Fibonacci sequence starts with 0 and 1. Each subsequent number is the sum of the previous two.
First, we’ll implement a recursive version:
def fib_recursive(n): """Recursive Fibonacci (inefficient but clear)""" if n <= 1: return n return fib_recursive(n-1) + fib_recursive(n-2)
#+end_example
This is elegant but slow due to repeated calculations. Let’s test it:
print([fib_recursive(i) for i in range(10)])
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
For larger numbers, we need a better approach. Here’s an iterative version:
def fib_iterative(n): """Iterative Fibonacci (efficient)""" a, b = 0, 1 for _ in range(n): a, b = b, a + b return a
Let’s time both approaches:
import time n = 30 start = time.time() result1 = fib_recursive(n) time1 = time.time() - start start = time.time() result2 = fib_iterative(n) time2 = time.time() - start print(f"Recursive: {result1} in {time1:.4f}s") print(f"Iterative: {result2} in {time2:.6f}s") print(f"Speedup: {time1/time2:.0f}x")
Code, explanation, tests, benchmarks—all in one document. Export to PDF for sharing, execute for verification.
11. Tangling: Extract Source Files
Write code in org, export to source files:
#+BEGIN_SRC python :tangle fib.py
def fibonacci(n):
"""Calculate nth Fibonacci number"""
if n <= 1:
return n
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
if __name__ == "__main__":
print([fibonacci(i) for i in range(10)])
#+end_src
Run M-x org-babel-tangle or C-c C-v t. Org extracts code to fib.py.
Multiple blocks can contribute to one file:
#+BEGIN_SRC python :tangle program.py import sys #+end_src
def main(): print("Hello, World!")
if __name__ == "__main__": main()
Tangle creates program.py with all blocks combined in order.
11.1. Tangle with Noweb References
Reference other blocks by name:
#+NAME: imports #+BEGIN_SRC python :tangle no import sys import os #+end_src
def helper(): return 42
<<imports>> <<functions>> def main(): print(helper()) if __name__ == "__main__": main()
<<blockname>> inserts that block’s content. Compose programs from pieces.
12. Inline Code
Execute code inline with results in text:
The sum of 2 + 2 is src_python[:exports results]{return 2+2} {{{results(=4=)}}}.
Exports as: “The sum of 2 + 2 is 4.”
Live calculations in prose.
13. SQL and Database Queries
Query databases directly:
#+BEGIN_SRC sqlite :db mydatabase.db SELECT name, age FROM users WHERE age > 25; #+end_src
| name | age |
|---|---|
| Alice | 28 |
| Bob | 35 |
| Carol | 42 |
Results as org tables. Add formulas, analyze data.
With PostgreSQL:
#+BEGIN_SRC sql :engine postgresql :database mydb :user myuser SELECT * FROM orders WHERE status = 'pending'; #+end_src
Your documentation queries production databases. Be careful, but powerful.
14. Shell Scripts
#+BEGIN_SRC shell ls -la ~/org | head -10 #+end_src
total 128 drwxr-xr-x 12 user staff 384 Jan 15 09:30 . drwxr-xr-x+ 87 user staff 2784 Jan 15 09:15 .. -rw-r--r-- 1 user staff 2048 Jan 14 15:20 inbox.org ...
Document system administration with executable examples.
15. Advanced Header Arguments
:dir - Working directory:
#+BEGIN_SRC shell :dir ~/projects/myapp ls #+end_src
:file - Output file:
#+BEGIN_SRC dot :file diagram.png
digraph { A -> B; B -> C; }
#+end_src
:cache - Cache results:
#+BEGIN_SRC python :cache yes # Expensive computation import time time.sleep(5) return "Done" #+end_src
Re-run only if code changes.
:cmdline - Command-line arguments:
#+BEGIN_SRC shell :cmdline -n 5 head #+end_src
:stdin - Provide input:
#+BEGIN_SRC python :stdin example-data import sys print(sys.stdin.read().upper()) #+end_src
16. Document-Wide Defaults
Set defaults for entire file:
#+PROPERTY: header-args :session mysession :results output
All blocks in file use these settings unless overridden.
Per-subtree:
#+begin_example
17. Python Examples
17.1. Example 1
print("Uses :session py :results output")
#+end_example
18. Reproducible Research
Org-Mode + code blocks = reproducible research:
- Gather data (code block)
- Clean data (code block)
- Analyze (code block)
- Visualize (code block)
- Export paper (org export)
Anyone can re-run analysis. Change assumption? Re-execute. New data? Re-run pipeline.
Science that actually reproduces.
19. Org-Mode as Jupyter Alternative
Jupyter notebooks but:
- Plain text (version control friendly)
- Multiple languages in one document
- Emacs editing power
- Outliner structure
- Offline, no server required
- Export to any format
Not for everyone, but for text-oriented programmers? Paradise.
20. Your Exercise
- Enable at least 3 languages in
org-babel-load-languages - Write a code block in your favorite language and execute it
- Create a code block that reads from an org table
- Generate a table from code output
- Try session-based execution (multiple blocks sharing state)
- Create a simple plot/graph
- Experiment with noweb references
- Tangle code to a source file
21. The Philosophy of Literate Programming
Knuth argued programs should be written for humans first, computers second. Org-Mode makes this practical.
Your documentation isn’t separate from your code—it IS your code. The explanation and implementation are one artifact.
Update the code? Update the explanation. They’re the same file.
This is documentation that can’t become outdated because it’s executable. Change the code, re-run, results update.
22. Next: Export and Publishing
You’ve built amazing documents with structure, data, code, and results. Now let’s share them. Chapter 12 covers exporting to HTML, PDF, LaTeX, Markdown, and more. Your plain text becomes beautiful documents.