✅ Source Code Blocks

Source code blocks are the foundation of literate programming in org-mode. They allow you to embed executable code within your documents, creating notebooks that combine narrative text, code, and results.

This guide covers everything you need to know about working with source blocks in Scimax VS Code.

✅ Introduction to Literate Programming

Literate programming, pioneered by Donald Knuth, is a programming paradigm that treats programs as works of literature. Instead of writing code with comments, you write documentation with embedded code.

✅ Benefits of Literate Programming

  • Documentation and code stay synchronized - Your explanations live alongside

  • Better understanding - Force yourself to explain your reasoning

  • Reproducible research - Combine analysis, code, and results in one document

  • Exploratory programming - Test ideas interactively like a notebook

  • Multiple outputs from one source - Tangle code files and export documentation

✅ Literate Programming in Org-Mode

Org-mode's Babel system brings literate programming to org documents:

  • Write code in source blocks with full syntax highlighting

  • Execute blocks and capture results inline

  • Pass data between blocks in different languages

  • Extract (tangle) code to external files

  • Include or exclude code/results in exports

✅ Source Block Syntax

✅ Basic Structure

A source block begins with #+BEGINSRC and ends with #+ENDSRC:

print("Hello, world!")
Hello, world!

✅ Language Declaration

The language comes immediately after #+BEGINSRC:

# Python code here
// JavaScript code here
# Shell commands here

✅ Header Arguments

Header arguments control block behavior and appear after the language:

# This block prints results and uses a persistent session

✅ Results Section

When you execute a block, results appear immediately below in a #+RESULTS: section:

print(2 + 2)
4

✅ Executing Code

✅ Execution Keybindings

KeybindingActionPlatform
----------------------------+-----------------------------------------------
C- / s-Execute current blockAll
C-c C-cExecute current block (Emacs style)All
S-Execute and move to next blockAll

✅ Execution Commands

CommandKey BindingDescription
scimax.org.executeBlockC-c C-cExecute the current source block
scimax.ob.executeAndNextS-EnterExecute and jump to next block
scimax.ob.executeAndNewM-S-EnterExecute and new
scimax.ob.executeToPointExecute all blocks up to cursor
scimax.org.executeAllBlocksExecute all blocks in document

✅ Execution Flow

  1. Place cursor inside a source block

  2. Press C- (or s- on Mac)

  3. Code executes using the appropriate language interpreter

  4. Results appear below the block in a #+RESULTS: section

  5. Previous results are replaced automatically

✅ Example

import math
result = math.sqrt(16)
print(f"The square root of 16 is {result}")
The square root of 16 is 4.0

✅ Supported Languages

Scimax VS Code supports a wide range of programming languages through both direct execution and Jupyter kernel integration.

✅ Direct Execution Languages

These languages execute directly without requiring Jupyter:

LanguageIdentifiersRequirement
Pythonpython, python3, pyPython 3.x in PATH
JavaScriptjavascript, js, nodeNode.js installed
TypeScripttypescript, tsTypeScript installed
Shell/Bashsh, bash, shellBash shell
SQLsql, sqliteDatabase configured

✅ Jupyter Kernel Languages

For enhanced interactive features, use Jupyter kernels by prefixing the language with jupyter- or relying on automatic Jupyter detection:

LanguageExplicit SyntaxAuto-DetectKernel Required
Pythonjupyter-pythonYesipykernel
Rjupyter-rYesIRkernel
Juliajupyter-juliaYesIJulia
Rubyjupyter-rubyYesiruby
Gojupyter-goNogophernotes
Rustjupyter-rustNoevcxr
Perljupyter-perlNoIPerl
Cjupyter-cNojupyter-c-kernel
C++jupyter-cppNoxeus-cling
Javajupyter-javaNoIJava

✅ Jupyter Benefits

Using Jupyter kernels provides:

  • Persistent state - Variables persist between executions in the same session

  • Rich output - Display plots, images, HTML, and LaTeX

  • Interactive widgets - Use ipywidgets and similar libraries

  • Automatic display - Images from matplotlib, plots, etc. appear automatically

✅ Example: Mixing Languages

echo "System: $(uname -s)"
System: Darwin
import platform
print(f"Python version: {platform.python_version()}")
Python version: 3.12.11
console.log(`Node version: ${process.version}`);
Node version: v25.2.1

✅ Header Arguments

Header arguments customize how source blocks execute and how results are handled. They appear after the language name.

✅ Syntax

print(arg1, arg2)
value1 5

✅ Results Arguments

✅ :results - Control Output Format

The :results argument controls how execution results are formatted and displayed.

✅ Collection Types

ValueDescription
outputCapture stdout/stderr (default for most)
valueCapture return value (last expression)

✅ Format Types

ValueDescription
tableFormat output as an org table
listFormat output as a list
verbatimFixed-width verbatim text (default)
fileResult is a file path/link
htmlWrap in #+BEGINEXPORT html block
latexWrap in #+BEGINEXPORT latex block
drawerWrap in :RESULTS: drawer

✅ Handling Types

ValueDescription
replaceReplace previous results (default)
appendAppend to previous results
prependInsert before previous results
silentDon't insert results

✅ Examples

print("Line 1")
print("Line 2")
Line 1
Line 2
42
print("Name,Age,City")
print("Alice,30,NYC")
print("Bob,25,Boston")
NameAgeCity
Alice30NYC
Bob25Boston
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [1, 4, 9])

✅ Export Arguments

✅ :exports - Control What Gets Exported

ValueDescription
codeExport only the code block
resultsExport only the results
bothExport both code and results (default)
noneDon't export anything
# Only this code appears in PDF/HTML export
print("Secret result")

✅ Variable Arguments

✅ :var - Pass Variables to Code

Define input variables for the code block:

print(f"{name} is {age} years old")
Alice is 30 years old

Multiple variables:

result = x + y
print(f"{x} + {y} = {result}")
40 + 20 = 60

Reference named blocks or tables:

NameScore
Alice95
Bob87
for row in data:
    print(f"{row[0]}: {row[1]}")

✅ Session Arguments

✅ :session - Enable Stateful Execution

Use sessions to maintain state between block executions:

x = 42
print("x defined")
x defined
print(f"x = {x}")
x = 42

Session names:

  • :session - Use default session for this language

  • :session name - Use named session

  • :session none - Disable session (each block is isolated)

✅ Directory Arguments

✅ :dir - Set Working Directory

Execute code in a specific directory:

pwd
/private/tmp
import os
print(os.getcwd())
/Users/jkitchin/Dropbox/projects/scimax_vscode/.github

✅ Tangling Arguments

✅ :tangle - Extract Code to Files

Control whether code is extracted during tangling:

ValueDescription
noDon't tangle this block (default)
yesTangle to default file
filename.extTangle to specific file
def helper_function():
    """This function will be extracted to utils.py"""
    return "helper"
from utils import helper_function

def main():
    print(helper_function())

if __name__ == "__main__":
    main()

Use `C-c C-v t' to tangle all blocks in the document.

✅ Cache Arguments

✅ :cache - Cache Execution Results

Cache results to avoid re-execution:

ValueDescription
noDon't cache (re-execute each time)
yesCache results (only re-execute if code changes)
import time
time.sleep(5)  # Expensive operation
result = 42
print(result)
42

On first execution, this waits 5 seconds. On subsequent executions, the cached result is used instantly (unless the code changes).

✅ Other Useful Arguments

✅ :eval - Control Evaluation

ValueDescription
yesEvaluate normally (default)
noNever evaluate
queryAsk before evaluating
ls | head -n2
_minted
_static
ls | head -n2

✅ :wrap - Wrap Results in Block

Wrap results in a custom block:

print("This will be wrapped in a quote block")

This will be wrapped in a quote block

✅ :prologue and :epilogue - Code Injection

Add code before/after the main block code:

print(sys.version)
3.12.11 (main, Jun 12 2025, 12:22:42) [Clang 20.1.4 ]
Done

✅ :cmdline - Command Line Arguments

Pass arguments to the interpreter:

# Shell script runs with -x flag (print commands)
echo "Hello"
Hello

✅ Combining Arguments

Arguments can be combined:

import pandas as pd
df = pd.read_csv('data.csv')
print(df.head())
1  2  3
0  4  5  6

✅ Results Handling and Output Types

✅ Automatic Result Insertion

When you execute a block, results automatically appear below it in a

✅ Result Types by Language

✅ Text Output (Verbatim)

Most languages produce text output by default, formatted with : prefix:

print("Hello")
print("World")
Hello
World

✅ Tables

Python/R code that produces tabular data can be formatted as org tables:

data = [['Alice', 30], ['Bob', 25], ['Carol', 35]]
return data
Alice30
Bob25
Carol35

✅ HTML and LaTeX

Blocks can produce rich formatted output:

html = "<h1>Title</h1><p>Paragraph</p>"
print(html)

Title

Paragraph

✅ Drawers

Use drawers to fold long output:

for i in range(20):
    print(f"Line {i}")

Line 0

Line 1

Line 2

Line 3

Line 4

Line 5

Line 6

Line 7

Line 8

Line 9

Line 10

Line 11

Line 12

Line 13

Line 14

Line 15

Line 16

Line 17

Line 18

Line 19

✅ Error Handling

When execution fails, error messages appear in results:

undefined_variable
Traceback (most recent call last):
  File "<string>", line 50, in <module>
  File "<string>", line 1, in <module>
NameError: name 'undefined_variable' is not defined

✅ Clearing Results

CommandDescription
scimax.ob.clearResultsClear results of current block
scimax.ob.clearAllResultsClear all results in document
scimax.babel.clearResultsClear all results in document

✅ Sessions for Stateful Execution

✅ What Are Sessions?

Sessions maintain a persistent interpreter process that preserves state between executions. This is similar to how Jupyter notebooks work - variables, functions, and imports persist.

✅ Enabling Sessions

Add :session header argument:

x = 42
y = 10
result = x + y
print(result)
52

✅ Named Sessions

Use different session names to maintain separate contexts:

import pandas as pd
df = pd.read_csv('data.csv')
import unittest
# Separate session for tests
# Can still access df here
print(df.head())

✅ Session Scope

  • Sessions are per-language and per-name

  • Default session name (when you just use :session) is language-specific

  • Use :session none to explicitly disable session for a block

  • Sessions persist for the duration of the VS Code window

✅ Jupyter Sessions

When using Jupyter kernels (e.g., jupyter-python), sessions automatically use Jupyter kernel instances:

import numpy as np
data = np.random.randn(100)
import matplotlib.pyplot as plt
plt.hist(data, bins=20);

✅ Benefits of Sessions

  • Avoid re-computation - Load data once, use in multiple blocks

  • Interactive development - Build up code incrementally

  • Shared context - Split long workflows into logical chunks

  • Testing - Set up fixtures in one block, test in others

✅ Session Limitations

  • Sessions consume memory until VS Code closes

  • Long-running sessions can accumulate stale state

  • Restart VS Code to clear all sessions

  • Session state is not saved to disk

✅ Navigation

Moving between source blocks efficiently is essential for productive literate programming.

✅ Block Navigation Keybindings

KeybindingActionPlatform
C-Next source blockAll
C-Previous source blockAll
S-Execute and next blockAll

✅ Navigation Commands

CommandDescription
scimax.ob.nextBlockC-c C-nJump to next source block
scimax.ob.previousBlockC-c C-pJump to previous source block
scimax.ob.jumpToBlockQuick pick menu of all blocks
scimax.ob.jumpToResultsJump to results of current block

✅ Quick Block Selection

Use scimax.ob.jumpToBlock to see a searchable list of all source blocks:

  • Shows language and block name

  • Displays first line as preview

  • Filter by language or content

  • Jump instantly to any block

✅ Example Workflow

  1. Write code in first block

  2. Press S- to execute and move to next block

  3. Write code that depends on previous block

  4. Press S- again

  5. Continue building up your analysis sequentially

✅ Block Manipulation

Scimax VS Code provides powerful commands for creating, modifying, and reorganizing source blocks.

✅ Creating Blocks

✅ Insert Block Above

CommandKey BindingDescription
scimax.ob.insertBlockAboveEsc-aInsert new block above cursor

Prompts for language, creates block, and places cursor inside.

✅ Insert Block Below

CommandKey BindingDescription
scimax.ob.insertBlockBelowEsc-bInsert new block below cursor
scimax.ob.insertBlockBelowSameInsert block with same language

The "same language" variant copies the language from the current block.

✅ Splitting Blocks

✅ Split at Cursor

CommandKey BindingDescription
scimax.ob.splitBlockEsc--Split current block at cursor

Place your cursor in the middle of a source block and split it into two blocks:

Before:

x = 1
y = 2
z = x + y
print(z)

After splitting at line 3:

#+BEGIN_SRC python
x = 1
y = 2
z = x + y
print(z)

Both blocks inherit the original header arguments.

✅ Merging Blocks

✅ Merge with Previous/Next

CommandDescription
scimax.ob.mergeWithPreviousMerge with previous block
scimax.ob.mergeWithNextMerge with next block

Combines code from two adjacent blocks into one. If languages differ, prompts for confirmation.

✅ Copying and Killing

✅ Clone Block

CommandDescription
scimax.ob.cloneBlockDuplicate current block below

Creates an exact copy of the current block including its header arguments.

✅ Copy Block and Results

CommandDescription
scimax.ob.copyBlockCopy block and results to clipboard

Copies the entire block including #+NAME: line (if present) and results section.

✅ Kill Block

CommandDescription
scimax.ob.killBlockDelete block and copy to clipboard

Removes the block and its results, copying everything to clipboard for pasting elsewhere.

✅ Moving Blocks

✅ Move Up/Down

CommandDescription
scimax.ob.moveBlockUpSwap with previous block
scimax.ob.moveBlockDownSwap with next block

Swaps the current block (including results) with the adjacent block, maintaining all content.

✅ Typical Workflows

✅ Notebook-Style Development

  1. Insert block with scimax.ob.insertBlockBelow

  2. Write code

  3. Execute with S- (executes and moves to next)

  4. Repeat

✅ Refactoring Code

  1. Split large block into logical pieces with scimax.ob.splitBlock

  2. Add session to maintain state: :session

  3. Execute sequentially to verify

  4. Reorganize with move commands if needed

✅ Experimenting with Variants

  1. Clone block with scimax.ob.cloneBlock

  2. Modify clone to test alternative approach

  3. Compare results

  4. Kill the version you don't want

✅ Inline Source Blocks

Sometimes you need to execute code inline within a paragraph rather than in a standalone block.

✅ Syntax

src_LANGUAGE{CODE}
src_LANGUAGE[HEADERS]{CODE}

✅ Examples

✅ Simple Inline Computation

The answer is src_python{return 2 + 2} {{{results(=4=)}}} which equals 4.

Result after execution:

The answer is 4 which equals 4.

✅ With Headers

Today is srcpython[:results value]{import datetime; datetime.date.today()} {{{results(datetime.date(2026, 1, 18))}}}.

✅ Accessing Variables

Inline blocks can access session variables:

You have to run this first to create a session:

total = 100
tax_rate = 0.08

The total with tax is srcpython[:session calc]{return total * (1 + taxrate)} {{{results(=108.0=)}}}.

✅ Use Cases

  • Embedding calculations in text

  • Showing dates/times

  • Inserting computed values into sentences

  • Quick one-liners that don't need a full block

✅ Limitations

  • No syntax highlighting

  • Results replace the inline block (can't keep both)

  • Less suitable for multi-line code

  • Harder to debug than regular blocks

✅ Code Tangling

Tangling is the process of extracting source code from your org document into separate source files. This enables the literate programming workflow where documentation is primary but you can still generate working software.

✅ What Is Tangling?

Tangling extracts code from source blocks marked with :tangle into external files:

  • Write narrative documentation with embedded code blocks

  • Extract all code to build/run your project

  • Keep docs and code in perfect sync

✅ Enabling Tangling

Add :tangle filename.ext to source blocks:

#!/usr/bin/env python3

def main():
    print("Hello from tangled code!")

if __name__ == "__main__":
    main()

✅ Tangling Commands

✅ Execute Tangle

KeybindingCommandDescription
C-c C-v tscimax.babel.tangleExtract all tangle blocks

This command:

  1. Finds all blocks with :tangle headers

  2. Groups them by target filename

  3. Writes each file with concatenated code

✅ Tangling Modes

✅ Don't Tangle (Default)

# Not tangled by default

✅ Tangle to Specific File

def utility_function():
    return "useful"
def another_utility():
    return "also useful"

Both blocks tangle to src/utils.py in order.

✅ Tangle with Yes

# Tangles to default file (based on org filename)

If your org file is project.org, this tangles to project.py.

✅ Advanced Tangling

✅ No-Web Style References

Use :noweb to reference other named blocks:

import sys
import os
def helper():
    return "help"
<<imports>>
<<helpers>>

def main():
    print(helper())

When tangled, and are replaced with the code from those named blocks.

✅ Shebang Lines

Add :shebang for executable scripts:

echo "This will be executable"

✅ Comments in Tangled Code

By default, tangled code includes no comments about its origin. Some implementations add comments like:

# [[file:literate.org::*Section Name][Section Name:1]]
# code here
# Section Name:1 ends here

✅ Use Cases

✅ Library Development

Write a tutorial document that tangles to a working library:

  • README.org - Document with examples

  • Tangle to src/lib.py, tests/testlib.py

  • Readers learn from docs, users import the library

✅ Configuration Management

Document your configuration in config.org:

* Database Configuration
We use PostgreSQL with connection pooling.

#+BEGIN_SRC toml :tangle tangled/config.toml
[database]
host = "localhost"
port = 5432
pool_size = 10

✅ Build Scripts

* Build Process

#+BEGIN_SRC makefile :tangle tangled/Makefile
all: build test

build:
	python setup.py build

test:
	pytest tests/

✅ Tangling vs Export

FeatureTanglingExport
PurposeExtract code to filesCreate documentation
OutputSource code filesHTML, PDF, LaTeX, etc.
Controls:tangle:exports
RespectsCode blocks onlyAll org content
Use caseBuild/run softwareShare/publish documentation

✅ Named Blocks and Calls

✅ Named Blocks

Give blocks names using #+NAME: so they can be referenced:

print(x * x)

✅ Calling Named Blocks

Use #+CALL: to invoke a named block with arguments:

25
100
return x * x

✅ Inline Call Syntax

You can also call blocks inline:

The square of 7 is callsquare(x7) {{{results(49=)}}}.

Reference named blocks as variables:

NameValue
Alpha100
Beta200
Gamma150
total = sum(row[1] for row in data[1:])  # Skip header
print(f"Total: {total}")
Total: 450

✅ Call with Headers

Override headers when calling:

121
1

✅ Library of Functions

Build a library of reusable code blocks:

import numpy as np
return np.mean(numbers)
import numpy as np
return np.median(numbers)
10
20
30
40
50
np.float64(30.0)
np.float64(30.0)

✅ Best Practices

  • Use descriptive names: load-data, calculate-statistics, generate-plot

  • Document block parameters in preceding text

  • Keep blocks focused and reusable

  • Use #+CALL: for parameterized re-execution

  • Consider blocks as functions in your literate program

✅ Quick Reference

✅ Essential Keybindings

KeybindingAction
C-Execute current block
S-Execute and move to next
C-Previous block
C-Next block
C-c C-v tTangle all blocks

✅ Common Header Arguments

ArgumentValuesPurpose
:resultsoutput, value, table, silentOutput format
:exportscode, results, both, noneWhat to export
:sessionname or nonePersistent state
:varname=valueInput variables
:tanglefilename or noExtract to file
:dirpathWorking directory
:cacheyes or noCache results

✅ Supported Languages

Direct: python, javascript, typescript, shell, bash, sql

Jupyter: jupyter-python, jupyter-r, jupyter-julia, jupyter-ruby, and many more

✅ Example Templates

✅ Basic Block

# Your code here

✅ Session Block

# Code with persistent state

✅ Data Processing

AB
12
# Process data
return processed

✅ Tangled Library

def my_function():
    """Documented function"""
    pass

✅ Tips and Best Practices

✅ Organization

  • Use headings to group related blocks

  • Name important blocks with #+NAME:

  • Add #+CAPTION: to blocks that produce key results

  • Use sessions to connect related blocks

✅ Performance

  • Use :cache yes for expensive computations

  • Close unnecessary sessions to free memory

  • Use :results silent when you don't need output

  • Limit output size for large datasets

✅ Reproducibility

  • Specify exact versions in documentation

  • Use :dir to set working directory explicitly

  • Document all dependencies in requirements/environment

  • Include data loading steps in the document

✅ Debugging

  • Execute blocks one at a time with C-

  • Check session state in separate test blocks

  • Use :results output to see print statements

  • Clear results and re-execute from top to verify

✅ Collaboration

  • Export to HTML/PDF for non-technical readers (:exports results)

  • Tangle to source files for developers (:tangle yes)

  • Use meaningful block names for #+CALL: references

  • Document assumptions and requirements in text

✅ Common Pitfalls

  • Forgetting to enable sessions when blocks depend on each other

  • Using :results value when you want printed output

  • Not clearing stale results before sharing

  • Referencing blocks that haven't executed yet

  • Mixing session names unintentionally

✅ Additional Resources

✅ Emacs Org-Mode Documentation

While Scimax VS Code implements its own version, the Emacs org-mode documentation is valuable for understanding concepts:

✅ Conclusion

Source code blocks transform org documents into powerful literate programming environments. You can:

  • Write executable documentation

  • Build reproducible analyses

  • Create interactive notebooks

  • Develop software with embedded docs

  • Share knowledge with working examples

Master the keybindings (C-, S-, C-/Down), experiment with header arguments, and leverage sessions for interactive development.

Happy literate programming!

✅ Navigation