2026-01-25 19:21:21 +01:00
2026-01-24 13:44:20 +01:00
2026-01-25 09:49:44 +01:00
2026-01-24 13:47:18 +01:00
2026-01-24 13:47:18 +01:00
2026-01-24 17:48:42 +01:00
2026-01-25 19:21:21 +01:00
2026-01-25 09:49:44 +01:00

ob-elixir

Org Babel support for evaluating Elixir code blocks in Emacs org-mode.

Features

  • Execute Elixir code directly in org-mode source blocks
  • Support for :results value and :results output
  • Variable passing with :var header argument
  • Persistent IEx sessions with :session
  • Mix dependency management via #+BEGIN_DEPS blocks
  • Shared imports/aliases via #+BEGIN_IMPORTS blocks
  • Module definitions with :module header argument
  • Automatic conversion of Elixir lists to org tables
  • Configurable error handling and warning display

Requirements

  • Emacs 27.1 or later
  • Org-mode 9.4 or later
  • Elixir installed and available in PATH

Installation

With straight.el

(straight-use-package
 '(ob-elixir :type git :host github :repo "username/ob-elixir"))

With use-package and straight.el

(use-package ob-elixir
  :straight (:type git :host github :repo "username/ob-elixir"))

Manual Installation

Clone the repository and add it to your load path:

(add-to-list 'load-path "/path/to/ob-elixir")
(require 'ob-elixir)

Configuration

Enable Elixir in org-babel:

(org-babel-do-load-languages
 'org-babel-load-languages
 '((elixir . t)))

Usage

Basic Execution

Execute Elixir code with C-c C-c:

#+begin_src elixir
1 + 2
#+end_src

#+RESULTS:
: 3

Results: Value vs Output

By default, blocks return the value of the last expression (:results value):

#+begin_src elixir :results value
Enum.map([1, 2, 3], fn x -> x * 2 end)
#+end_src

#+RESULTS:
| 2 | 4 | 6 |

Use :results output to capture printed output:

#+begin_src elixir :results output
IO.puts("Hello, World!")
IO.puts("Line 2")
#+end_src

#+RESULTS:
: Hello, World!
: Line 2

Variables

Pass variables to Elixir code with :var:

#+begin_src elixir :var name="Elixir" count=3
String.duplicate(name, count)
#+end_src

#+RESULTS:
: ElixirElixirElixir

Variables are automatically converted:

  • Elisp strings become Elixir strings
  • Elisp numbers become Elixir numbers
  • Elisp lists become Elixir lists
  • Elisp vectors become Elixir tuples
  • Elisp t becomes true, nil becomes nil
  • Elisp symbols become atoms

Sessions

Use :session to maintain state across blocks:

#+begin_src elixir :session my-session
x = 10
#+end_src

#+RESULTS:
: 10

#+begin_src elixir :session my-session
x * 2
#+end_src

#+RESULTS:
: 20

Manage sessions with:

  • M-x ob-elixir-kill-session - Kill a specific session
  • M-x ob-elixir-kill-all-sessions - Kill all sessions

Dependencies

Define Mix dependencies with #+BEGIN_DEPS blocks. Dependencies apply to all subsequent Elixir blocks in the document:

#+BEGIN_DEPS elixir
[
  {:jason, "~> 1.4"},
  {:decimal, "~> 2.0"}
]
#+END_DEPS

#+begin_src elixir
Jason.encode!(%{hello: "world"})
#+end_src

#+RESULTS:
: {"hello":"world"}

Dependencies are cached in ~/.cache/ob-elixir/ (configurable via ob-elixir-deps-cache-dir). The first execution fetches and compiles dependencies; subsequent executions reuse the cache.

Manage dependency projects with:

  • M-x ob-elixir-list-deps-projects - List cached projects
  • M-x ob-elixir-cleanup-deps-projects - Delete all cached projects

Imports

Define shared imports, aliases, and requires with #+BEGIN_IMPORTS blocks:

#+BEGIN_IMPORTS elixir
import Enum, only: [map: 2, filter: 2]
alias String, as: S
#+END_IMPORTS

#+begin_src elixir
map([1, 2, 3], &(&1 * 2)) |> filter(&(&1 > 2))
#+end_src

#+RESULTS:
| 4 | 6 |

#+begin_src elixir
S.upcase("hello")
#+end_src

#+RESULTS:
: HELLO

Module Definitions

Define reusable modules with the :module header argument:

#+begin_src elixir :module MyMath
def add(a, b), do: a + b
def multiply(a, b), do: a * b
#+end_src

#+RESULTS:
: Module MyMath: functions defined

Multiple blocks with the same :module name merge their contents:

#+begin_src elixir :module MyMath
def subtract(a, b), do: a - b
#+end_src

Use the module in subsequent blocks (requires explicit import):

#+BEGIN_IMPORTS elixir
import MyMath
#+END_IMPORTS

#+begin_src elixir
add(1, 2) |> multiply(3)
#+end_src

#+RESULTS:
: 9

Tables

Elixir lists are automatically converted to org tables:

#+begin_src elixir
[
  ["Name", "Age"],
  ["Alice", 30],
  ["Bob", 25]
]
#+end_src

#+RESULTS:
| Name  | Age |
| Alice |  30 |
| Bob   |  25 |

Tuples are also supported:

#+begin_src elixir
{:ok, "success"}
#+end_src

#+RESULTS:
| ok | success |

Customization

Commands

  • ob-elixir-command (default: "elixir") - Command to execute Elixir code
  • ob-elixir-iex-command (default: "iex") - Command to start IEx sessions
  • ob-elixir-mix-command (default: "mix") - Command to run Mix

Behavior

  • ob-elixir-signal-errors (default: t) - When non-nil, Elixir errors are signaled as Emacs errors. When nil, errors are returned as result strings.
  • ob-elixir-show-warnings (default: t) - When non-nil, Elixir warnings are included in output.

Paths

  • ob-elixir-deps-cache-dir (default: ~/.cache/ob-elixir/) - Directory for caching temporary Mix projects created for dependencies.

Example Configuration

(use-package ob-elixir
  :after org
  :config
  (setq ob-elixir-signal-errors nil)  ; Return errors as results
  (setq ob-elixir-show-warnings nil)  ; Hide warnings
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((elixir . t))))

Development

Running Tests

Using Make:

make test

Using Eldev:

eldev test

Byte Compilation

make compile

Linting

make lint

Project Structure

ob-elixir/
├── ob-elixir.el      # Main source file
├── Makefile          # Build and test commands
├── Eldev             # Eldev configuration
├── test/             # Test suite
│   ├── test-ob-elixir.el
│   ├── test-ob-elixir-core.el
│   ├── test-ob-elixir-vars.el
│   ├── test-ob-elixir-results.el
│   ├── test-ob-elixir-errors.el
│   ├── test-ob-elixir-org.el
│   ├── test-ob-elixir-deps.el
│   ├── test-ob-elixir-imports.el
│   ├── test-ob-elixir-modules.el
│   └── test-ob-elixir-sessions.el
└── docs/             # Implementation documentation

License

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Description
No description provided
Readme 264 KiB
Languages
Emacs Lisp 96.8%
Nix 2.6%
Makefile 0.6%