This package adds additional features to ob-python that I found lacking when trying to use it as a replacement for jupyter notebooks. I’ve been using it instead of jupyter notebooks for about a year now, slowly accumulating fixes to things that I miss from jupyter, or things that seem cool that jupyter doesn’t support but emacs makes easy.
- Mix image and text output in the same cell, by mocking matplotlib to save images and return references.
- Print pandas dataframes as org tables always, by overwriting the __repr__ method. Uses tabulate if available.
- Press C-c C-c over an image for a full-size view
For example:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({"x": [1, 2, 3, 4, 5,6,7,], "y": [10, 11, 12, 13, 14,15,16]})
print(df)
df.plot(x="x", y="y", kind="line")
plt.show()
print("...tada!")
idx | x | y |
---|---|---|
0 | 1 | 10 |
1 | 2 | 11 |
2 | 3 | 12 |
3 | 4 | 13 |
4 | 5 | 14 |
5 | 6 | 15 |
6 | 7 | 16 |
- Cell timers (configurable via :timer-show {yes/no})
- Cell interruption with C-c C-k
- Capturing tracebacks in the results (with the option to use rich tracebacks via :errors “rich no-locals frames 3 extra 5”)
- Alerts on long running cells, using libnotify for system alerts and pop ups inside of doom
- Functions to send a block and the results (e.g. the traceback) to a gptel buffer, get a patch, view the diff, and optionally apply it.
- Ability to trigger this automatically when a cell fails.
Configured scripts for converting org files in a directory to ipynb files, or ipynb files to org files. These rely on pandoc.
These commands are intended to be called from dired buffers.
run-ipynb-to-org-conversion-script
- Convert all .ipynb files in current directory to .org (removes various artifacts that pandoc creates also, cleaning can be disabled by removing the -c flag)
run-ipynb-to-org-conversion-script-recursively
- Convert all .ipynb files in current directory and subdirectories to .org
run-org-to-ipynb-conversion-script
- Convert all .org files in current directory to .ipynb
Also includes a git precommit hook that’s useful for automatically converting org to ipynb.
- Special mode inherits the same python interpreter as specified for the cell, giving access to documentation and completion. (Requires eglot.)
Activate with
(ob-python-extras/add-org-edit-special-advice)
https://github.com/karthink/org-src-context
- Python packages: Rich, tabulate (optional, but recommended), matplotlib
- System: Libnotify (for alerts), Pandoc (For conversions)
- Emacs: Gptel (For the gptel extensions), Doom (for now required for alerts), Eglot (for lsp integrations), Dired (For the conversion scripts)
(package! ob-python-extras
:recipe (:host github
:repo "ElleNajt/ob-python-extras"
:files ("*.el" "python" "bashscripts")))
(after! ob-python-extras
(ob-python-extras/map-suggested-keyindings))
If you want my keybindings, run:
(ob-python-extras/map-suggested-keyindings)
(after! ob-python-extras
(ob-python-extras-load-gptel-integration))
This requires gptel-default-mode to be set to org-mode to work, since it expects an org block in the response.
(gptel-default-mode 'org-mode)
The conversation happens in the CELL ERRORS buffer.
Key | Command | Description |
---|---|---|
SPC o c s | send-block-to-gptel | Send block to GPTel, and ask for a fix. |
SPC o c p | patch-gptel-blocks | Apply the fix |
SPC o c f | gptel-fix-block | Do the two things at once |
If you set:
(setq ob-python-extras/auto-send-on-traceback t)
Then blocks will be sent automatically when a traceback is detected in the response. This can rack up a bill with API calls!
(after! ob-python-extras
(ob-python-extras-load-alerts))
Matplotlib is configured to save and display images without transparency by
default. The default can be changed with (setq
ob-python-extras/transparent-images t)
. This default, in turn, can be
overridden at the org-src-block level with :transparent nil
or :transparent
t
.
See this org file for examples of the different functionality and configurations.
In my personal config I use the following keybindings as well, based on a vendored version guilt-dolphin’s org-evil with keybindings stripped. These make it easier to manipulate source blocks:
(org-evil--define-key 'motion 'org-evil-motion-mode
"[[" 'org-evil-motion-backward-block-begin
"]]" 'org-evil-motion-forward-block-begin)
(add-hook! 'org-mode-hook 'org-evil-mode)
(undefine-key! evil-motion-state-map "[ s" "] s")
(map! (:mode org-mode
:n "] r" #'org-babel-goto-src-block-results
:n "[ s" 'org-evil-block-beginning-of-block
:n "] s" 'org-evil-block-end-of-block))
(org-evil--define-key 'motion 'org-evil-block-mode
"[ s" 'org-evil-block-beginning-of-block
"] s" 'org-evil-block-end-of-block)
(dolist (mode '(operator visual))
(org-evil--define-key mode 'org-evil-block-mode
"ib" 'org-evil-block-inner-block
"ab" 'org-evil-block-a-block))
- Aspen for teaching me a bunch about emacs and suggesting mocking out matplotlib
- Claude for writing most of the code ^^
https://github.com/emacs-jupyter/jupyter This package provides some overlapping functionality, and as far as I understand it does it by connecting to jupyter kernels and providing a front end in org mode for the kernel. I have not used this myself yet. It may ultimately make more sense for this project to be refactored to extend emacs-jupyter instead of ob-python, e.g. by adding the gptel integrations or other features that emacs-jupyter lacks.
https://github.com/millejoh/emacs-ipython-notebook Similar to Emacs-Jupyter. No longer maintained.