Using the shell source type and the :shebang
option, we can execute org-mode source blocks in a nix-shell. Using this, org-mode can define the dependencies and runtime available for literate programming documents.
Create a shell.nix file
{pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [ pkgs.hello ];
}
Tangle it with `M-x org-babel-tangle`.
hello
This also works with other interpreters:
{pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [ pkgs.python3 ];
name = "World";
}
Tangle again.
import os
print("Hello, {}!".format(os.environ['name']))
{pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [ pkgs.nodejs ];
name = "Emacs";
}
console.log(`Hello, ${process.env.name}!`);
Node is a bit special, the second-line shebang doesn’t work, since #! is not valid nodejs syntax. But thanks to this bug/feature #!nix-shell content in other parts of the file are still processed by nix-shell. In this shebang we wrap the second line in grave symbols and newlines to make it both valid for nix-shell and nodejs.
- Make syntax highlighting work right, emacs doesn’t know that the python and javascript code need to be highlighted differently from shell scripts
- Figure out better way to load nix-shell code than tangling to a temporary directory
- custom org-babel-execute mode for nix-shells
This is an alternative method that I discovered.
It relies on envrc package to load a direnv environment from a temporary directory.
I have only tested it with shell and python so far but it might work with other src blocks.
Notice that the python src block does not require any extra setup.