I'm playing around with notebooks in emacs. My current setup is EIN (emacs-ipython-notebook
) for interactive support, and jupytext
for converting .ipynb
files to .py
, which is useful for diffs and code reviews. Right now I have to run a jupytext
shell command to do the sync, but I would like to do this automatically on save, similarly to how jupytext
supports this out of the box if you're using Jupyter. I tried the following
(defun sync-jupytext ()
"Sync linked files via jupytext."
(shell-command-to-string (format "jupytext --sync %s" buffer-file-name)))
(add-hook 'after-save-hook #'sync-jupytext)
Unfortunately this doesn't work as buffer-file-name
seems to be nil
once the ein
mode is activated. (It works if I don't C-c C-o
to start interactive mode though.) My e-lisp isn't good enough to figure out what variable or code to write instead to get the file name. Can someone help with this?
Ein uses polymode
to support multiple major modes in a buffer, and as a result the working buffer isn't associated with the notebook file directly.
The notebook path, which should work in place of buffer-file-name
, can be accessed via (ein:$notebook-notebook-name (ein:get-notebook))
.
I think for syncing with jupytext
you could add an advice around ein:notebook-save-notebook-success
to sync the notebook (there might be a cleaner way using the ein:events-on
mechanism, but I'm not sure how).
(defun my@sync-jupytext (orig-fn notebook &rest args)
(apply orig-fn notebook args)
(message "[jupytext] %s"
(shell-command-to-string
(format "jupytext --sync %s"
(expand-file-name (ein:$notebook-notebook-name notebook))))))
(advice-add 'ein:notebook-save-notebook-success :around #'my@sync-jupytext)