Search code examples
emacsjupyterjupytext

Getting the buffer / file name inside of emacs-ipython-notebook


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?


Solution

  • 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)