No description
Find a file
2020-04-12 08:35:14 -05:00
.github Add FUNDING.yml 2019-07-29 18:18:32 -05:00
js fix: use Bash shell and omit rm errors (#13) 2019-02-06 14:26:52 -06:00
test Rename internal functions for clarity 2020-04-12 08:35:14 -05:00
.ert-runner Add Cask file 2018-11-15 23:04:27 -06:00
.gitignore ignore .cask folder 2020-03-10 23:39:35 -05:00
.travis.yml Fix jupyter-tunnel-connection 2020-04-12 08:35:14 -05:00
appveyor.yml Show Jupyter version info during CI tests 2019-06-22 21:59:00 -05:00
Cask Test against the newest version of org-mode 2019-02-21 17:14:59 -06:00
CHANGELOG.org Keep uppercase characters in kernel language names 2020-04-09 11:33:57 -05:00
COPYING Change License to GPL3 2019-05-31 09:44:39 -05:00
jupyter-base.el Add jupyter-read-connection 2020-04-12 08:35:14 -05:00
jupyter-c++.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-channel-ioloop-comm.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-channel-ioloop.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-channel.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-client.el Rename internal functions for clarity 2020-04-12 08:35:14 -05:00
jupyter-comm-layer.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-env.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-ioloop-comm.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-ioloop.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-javascript.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-julia.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-kernel-manager.el Update/add documentation 2020-04-12 08:35:14 -05:00
jupyter-kernel-process-manager.el Update/add documentation 2020-04-12 08:35:14 -05:00
jupyter-kernelspec.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-messages.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-mime.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-org-client.el Refactor message sending/receiving 2020-04-12 08:35:14 -05:00
jupyter-org-extensions.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-python.el Refactor message sending/receiving 2020-04-12 08:35:14 -05:00
jupyter-R.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-repl.el Refactor message sending/receiving 2020-04-12 08:35:14 -05:00
jupyter-rest-api.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-server-ioloop.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-server.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-tramp.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-widget-client.el Refactor message sending/receiving 2020-04-12 08:35:14 -05:00
jupyter-zmq-channel-comm.el Compatibility with Emacs 27 2020-04-12 08:35:14 -05:00
jupyter-zmq-channel-ioloop.el Bump version 2020-04-07 15:13:51 -05:00
jupyter-zmq-channel.el Bump version 2020-04-07 15:13:51 -05:00
jupyter.el Bump version 2020-04-07 15:13:51 -05:00
jupyter.png Add jupyter image for ob-jupyter tests 2018-02-12 18:04:20 -06:00
MAINTAINERS.org Set back to dev 2020-04-07 15:43:10 -05:00
Makefile Revert commits making ZMQ optional 2020-04-02 10:48:44 -05:00
manual.org [WIP] README update 2020-04-12 08:35:14 -05:00
ob-jupyter.el Keep uppercase characters in kernel language names 2020-04-09 11:33:57 -05:00
README.org [WIP] README update 2020-04-12 08:35:14 -05:00
widget.html Update documentation, cleanup comments 2018-08-30 18:02:13 -05:00

An interface to communicate with Jupyter kernels in Emacs.

Highlights

  • REPL interface to a Jupyter kernel complete with inline graphics, searchable REPL input history,

Interact with a Jupyter kernel through a REPL interface, complete with inline graphics

  • Provides an API for creating Jupyter kernel frontends in Emacs based on the built-in eieio and cl-generic libraries.

    • Communication with a kernel is either done through zmq sockets using the emacs-zmq library or (coming soon) through the Jupyter notebook REST API.

      • All of this communication is abstracted so that a frontend developer should only need to extend a few cl-defmethod definitions in order to implement a frontend.
    • Make it easy to define kernel language specific behavior. See the files jupyter-python.el and jupyter-julia.el for examples.
  • Provides REPL and org-mode source block based frontends.
  • Jupyter kernel interactions are integrated with Emacs's built-in features. For example

    • Inspecting a piece of code under point will display the information for that symbol in the *Help* buffer. You can re-visit inspection requests made to the kernel by calling help-go-back or help-go-forward while in the *Help* buffer.
    • Code completion is done through the completion-at-point interface.
    • If the kernel asks for input from the user, a prompt is displayed in the minibuffer.
    • You can search through REPL history using isearch.

Installation

NOTE: Your Emacs needs to have been built with module support for this package to work since it relies on the emacs-zmq package. See the README of that package for more information.

The recommended way to install this package is through the built-in package manager in Emacs.

Ensure MELPA is in your package-archives

(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))

Ensure the latest versions of MELPA packages are available

M-x package-refresh-contents RET

Install Jupyter

M-x package-install RET jupyter RET

Building a package archive using cask

One way to install this package is to build a package archive using cask (https://github.com/cask/cask) to build a local Emacs package file. To do this, clone the repository, enter its directory, and run the following at the command line:

cask package

This creates a file dist/jupyter-0.6.0.tar containing the package archive. To install it

  1. Start your Emacs normally
  2. Ensure MELPA is in your package-archives
  3. M-x package-initialize
  4. M-x package-refresh-contents
  5. M-x package-install-file ~/path/to/jupyter/dist/jupyter-0.6.0.tar

Manual installation

For a manual installation you can add the repository directory to your load-path and ensure the following dependencies are installed:

markdown-mode (optional)
https://jblevins.org/projects/markdown-mode/
company-mode (optional)
http://company-mode.github.io/
emacs-websocket
https://github.com/ahyatt/emacs-websocket
simple-httpd
https://github.com/skeeto/emacs-web-server
zmq
http://github.com/dzop/emacs-zmq
(add-to-list 'load-path "~/path/to/jupyter")
(require 'jupyter)

Building the widget support (EXPERIMENTAL)

There is also support for interacting with Jupyter widgets through an external browser. If a widget is to be displayed, an external browser is opened first to display the widget. In this case, Emacs acts as a relay for passing messages between the kernel and the external browser.

If you would like to try out this limited support, you will need to have node installed on your system to build the necessary javascript. Then you will have to run the following commands from the root project directory:

make widgets

How does this package compare to other similar packages?

ob-ipython

The org-mode source block frontend in emacs-jupyter is similar to what is offered by ob-ipython (and also the scimax version), below are some of the differences between emacs-jupyter and ob-ipython (biased in favor of emacs-jupyter):

  • Faster than ob-ipython

    • ob-ipython starts a new process for every request made to a kernel and does not persist the connection it makes to the kernel. This means that for every request made there is the overhead of both starting a new process and establishing communication with the kernel. emacs-jupyter starts a process on every new kernel connection only and the connection is persisted for the lifetime of the client (frontend) connected to the kernel. This difference is most notable when comparing the code completion features of both packages. ob-ipython code completion is basically unusable for quick completions while typing.
  • Better REPL interface

    • ob-ipython uses python-shell-make-comint to create a REPL connected to a kernel. There are two problems with this (1) no syntax highlighting for kernel languages other than Python (2) comint only groks text based output, but a Jupyter kernel can provide much richer representations of data, e.g. HTML, markdown, or png images to name a few. The REPL frontend experience of emacs-jupyter is much closer to what one would get when using jupyer qtconsole (see https://qtconsole.readthedocs.io/en/stable/).
  • Better integration with org-mode source block :session features

    • All of the extension points that org-mode offers for source block languages like org-babel-edit-prep, org-babel-load-in-session, etc. are all fully supported. ob-ipython does not provide some of these features, e.g. org-babel-load-in-session.
  • Similar features to the scimax version of ob-ipython

    • The scimax version has some really neat features like custom keybindings when inside an org-mode source block, selective display of mimetypes, jumping to source block error locations, and others. Many of these features have also been implemented in emacs-jupyter, e.g. you can add language specific keybindings using the jupyter-org-define-key function.

emacs-ipython-notebook (ein)

ein is a complete Jupyter notebook interface in Emacs with many powerful features for Python kernels. There is some overlap in the features provided by emacs-jupyter and ein, but I have never used ein so I cannot speak very much about their similarities/differences.

I would say that emacs-jupyter aims to be a generic API for interacting with Jupyter kernels that just happens to have a built-in REPL and org-mode source block frontend whereas ein aims to be a fully featured Jupyter notebook frontend. Also ein can read and write .ipynb files, this feature is lacking in emacs-jupyter at the moment. In the future it would be nice to add some kind of notebook interface in emacs-jupyter or at least an efficient conversion process between notebook files and org-mode.

How do I use the built-in frontends?

REPL

To start a new kernel on the localhost and connect a REPL client to it M-x jupyter-run-repl. Alternatively you can connect to an existing kernel by supplying the kernel's connection file using M-x jupyter-connect-repl.

The REPL supports most of the rich output that a kernel may send to a client. If the kernel requests a widget to be displayed, a browser is opened that displays the widget. If the kernel sends image data, the image will be displayed in the REPL buffer. If LaTeX is sent, it will be compiled (using org-mode) and displayed.

Rich kernel output

A Jupyter kernel provides many representations of results that may be used by the frontend, in this case Emacs. Luckily, Emacs provides good support for most of the available representations.

The supported mimetypes along with their dependencies are shown below in order of priority if multiple representations are returned. Note, if a dependency is not available in your Emacs, a mimetype with a lower priority will be used to display output.

Mimetype Dependency
application/vnd.jupyter.widget-view+json websocket, simple-httpd
text/html Emacs built with libxml2
text/markdown markdown-mode
text/latex org-mode
image/svg+xml Emacs built with librsvg2
image/png none
text/plain none

Inspection

To send an inspect request to the kernel, press M-i when the cursor is at the location of the code you would like to inspect.

Completion

Completion is implemented through the completion-at-point interface. In addition to completing symbols in the REPL buffer, completion also works in buffers associated with a REPL. For org-mode users, there is even completion in the org-mode buffer when editing the contents of a Jupyter source code block.

REPL history

You can navigate through the REPL history using C-n and C-p or M-n and M-p.

You can also search through the history using isearch. To search through history, use the standard isearch keybindings: C-s to search forward through history and C-s C-r to search backward.

Associating other buffers with a REPL (jupyter-repl-interaction-mode)

After starting a REPL, it is possible to associate the REPL with other buffers if they pass certain criteria. Currently, the buffer must have the major-mode that corresponds to the REPL's kernel language. To associate a buffer with a REPL you can run the command jupyter-repl-associate-buffer.

jupyter-repl-associate-buffer will ask you for the REPL you would like to associate with the current-buffer and enable the minor mode jupyter-repl-interaction-mode. This minor mode populates the following keybindings for interacting with the REPL:

Key binding Command
C-M-x jupyter-eval-defun
M-i jupyter-inspect-at-point
C-c C-b jupyter-eval-buffer
C-c C-c jupyter-eval-line-or-region
C-c C-i jupyter-repl-interrupt-kernel
C-c C-r jupyter-repl-restart-kernel
C-c C-s jupyter-repl-scratch-buffer
C-c C-o jupyter-eval-remove-overlays
C-c M-: jupyter-eval-string
Integration with emacsclient

If code sent for evaluation causes a file to be opened via emacsclient, the opened file is associated with the corresponding REPL client if possible. This behavior is most useful, for example, when using the edit function in IJulia.

To enable server-mode in Emacs you should have something like the following in your Emacs configuration before starting any kernels.

(server-mode 1)
(setenv "EDITOR" "emacsclient")

Note this probably wont work properly when there are multiple competing clients sending requests to their underlying kernels that want to open files. Or if the underlying kernel takes longer than jupyter-long-timeout seconds to open a file.

See jupyter-server-mode-set-client for more details.

jupyter-repl-persistent-mode

A global minor mode that will persist a kernel connection to a buffer about to be displayed if the current buffer is in jupyter-repl-interaction-mode and the buffer being switched to has the same major-mode. This mode is automatically enabled whenever jupyter-run-repl or jupyter-connect-repl is called.

jupyter-repl-maximum-size

Set the maximum number of lines before the REPL buffer is truncated.

jupyter-repl-allow-RET-when-busy

If non-nil, allow inserting a newline in a REPL cell whenever the kernel is busy. Normally this isn't allowed since the REPL relies on the kernel responding to messages when RET is pressed, but a kernel does not respond to messages when it is busy.

jupyter-repl-echo-eval-p

If non-nil, when evaluating code using the jupyter-eval-* functions like M-x jupyter-eval-line-or-region, copy the evaluated code as a REPL input cell and display any output generated in the REPL. When this variable is nil, copying to the REPL does not occur and output/results are inserted in pop-up buffers or added to the *Messages* buffer according to jupyter-eval-short-result-max-lines and jupyter-eval-short-result-display-function.

Widget support

There is also support for Jupyter widgets integrated into the REPL. If any of the results returned by a kernel have a widget representation, a browser is opened and the widget is displayed in the browser. There is only one browser per client.

This feature is currently considered experimental and has only been tested for simple uses of widgets. See jupyter-widget-client.

org-mode source blocks

For users of org-mode, integration with org-babel is provided through the ob-jupyter library. To enable Jupyter support for source code blocks, add jupyter to org-babel-load-languages.

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (julia . t)
   (python . t)
   (jupyter . t)))

Note, jupyter should be added as the last element when loading languages since it depends on the values of variables such as org-src-lang-modes and org-babel-tangle-lang-exts. After ob-jupyter has been loaded, new source code blocks with names of the form jupyter-LANG will be available. LANG can be any one of the kernel languages found on your system. See jupyter-available-kernelspecs.

Every Jupyter source code block requires that the :session parameter be specified since all interaction with a kernel is through a REPL. For example, to interact with a python kernel you would create a new source block like so

#+BEGIN_SRC jupyter-python :session py
x = 'foo'
y = 'bar'
x + ' ' + y
#+END_SRC

By default, source blocks are executed synchronously. To execute a source block asynchronously set the :async parameter to yes:

#+BEGIN_SRC jupyter-python :session py :async yes
x = 'foo'
y = 'bar'
x + ' ' + y
#+END_SRC

Since a particular language may have multiple kernels available, the default kernel used will be the first one found by jupyter-available-kernelspecs for the language. To change the kernel, set the :kernel parameter:

#+BEGIN_SRC jupyter-python :session py :async yes :kernel python2
x = 'foo'
y = 'bar'
x + ' ' + y
#+END_SRC

Note, the same session name can be used for different values of :kernel since the underlying REPL buffer's name is based on both :session and :kernel.

Any of the defaults for a language can be changed by setting org-babel-default-header-args:jupyter-LANG to an appropriate value. For example to change the defaults for the julia kernel, you can set org-babel-default-header-args:jupyter-julia to something like

(setq org-babel-default-header-args:jupyter-julia '((:async . "yes")
                                                    (:session . "jl")
                                                    (:kernel . "julia-1.0")))

Note on the language name provided by a kernelspec

Some kernelspecs use spaces in the name of the kernel language. Those get replaced by dashes in the language name you need to use for the source block, e.g. Wolfram Language becomes jupyter-Wolfram-Language.

Integration with ob-async

If you use the ob-async package, make sure you add the Jupyter source block languages to ob-async-no-async-languages-alist so that ob-async doesn't override emacs-jupyter when the :async header argument is specified. For example you can put the following in your configuration:

(setq ob-async-no-async-languages-alist '("jupyter-python" "jupyter-julia"))

Issues with ob-ipython

If you already have ob-ipython installed, you may experience issues with it conflicting with emacs-jupyter (e.g. this issue): i.e. instead of actual results of source block execution, you'll got only long GUIDs, and message like error in process sentinel: Search failed: "b5d6bfb3-e37f-4c58-a2e5-edcf1ad2430f" in minibuffer

This is because both emacs-jupyter and ob-ipython try to own jupyter-LANG source blocks, and conflicts with each other. It seems there is no way to make them both work together.

If you have issues like described above, then try disable ob-ipython and see, is it help. Usually, it is enough to remove ipython from (org-babel-do-load-languages ...) list, and restart your Emacs.

Overriding built-in src-block languages

You may find having to specify the names of Jupyter source blocks using jupyter-LANG a bit verbose and want to have the built-in support for LANG source blocks overridden to use the machinery of jupyter-LANG source blocks. This can be done by calling the function org-babel-jupyter-override-src-block.

For example, to override the behavior of python source blocks so that they act like jupyter-python source blocks, you can add the following in your initialization (after calling org-babel-do-load-languages):

(org-babel-jupyter-override-src-block "python")

After calling the above function, all python source blocks are effectively aliases of jupyter-python source blocks and the variable org-babel-default-header-args:python will be set to the value of org-babel-default-header-args:jupyter-python. Note, org-babel-default-header-args:python will not be an alias of org-babel-default-header-args:jupyter-python, the value of the former is merely set to the value of the latter after calling org-babel-jupyter-override-src-block.

If you decide you want to go back to the original behavior or python source blocks, you can restore the overridden functions by calling org-babel-jupyter-restore-src-block.

(org-babel-jupyter-restore-src-block "python")

Rich kernel output

In org-mode a code block returns scalar data (plain text, numbers, lists, tables, …), an image file name, or code from another language. All of this information must be specified in the code block's header arguments, but all of this information is already provided in the messages passed between a Jupyter kernel and its frontends.

When a kernel provides representations of results other than plain text, those richer representations have priority. For example if the kernel returns LaTeX code, the results are wrapped in a LaTeX source block. Similarly for HTML and markdown. If an image is returned, the image is automatically saved to file and a link to the file will be the result of the code block.

Below are the supported mimetypes ordered by priority

  • text/org
  • image/svg+xml, image/jpeg, image/png
  • text/html
  • text/markdown
  • text/latex
  • text/plain

Since it is possible to determine how a result should be represented in org-mode via its MIME type, only a few header arguments are supported.

A note on using the :results header argument

Results are inserted in the org-mode buffer in such a way that most header arguments that control how results should be inserted don't need to specified. There are some cases where this behavior is not wanted and which can be controlled by setting the :results header argument.

Insert unwrapped LaTeX
Normally LaTeX results are wrapped in a BEGIN_EXPORT block, in order to insert LaTeX unwrapped, specify :results raw.
Suppress table creation
Whenever a result can be converted into an org-mode table, e.g. when it look like [1, 2 , 3], it is automatically converted into a table. To suppress this behavior you can specify :results scalar.
Fixing the file name of images with the :file argument

Whenever an image result is returned, a random image file name is generated and the image is written into org-babel-jupyter-resourse-directory. In order to specify your own file name for the image, you can give an appropriate value to the :file header argument.

Changing the mime-type priority with the :display argument

The priority of mimetypes used to display results can be overwritten using the :display option. If instead of displaying HTML results we'd wish to display plain text, the argument :display text/plain text/html would prioritize plain text results over html ones. The following example displays plain text instead of HTML:

#+BEGIN_SRC jupyter-python :session py :display plain
import pandas as pd
data = [[1, 2], [3, 4]]
pd.DataFrame(data, columns=["Foo", "Bar"])
#+END_SRC
Image output without the :file header argument

For images sent by the kernel, if no :file parameter is provided to the code block, a file name is automatically generated based on the image data and the image is written to file in org-babel-jupyter-resource-directory. This is great for quickly generating throw-away plots while you are working on your code. Once you are happy with your results you can specify the :file parameter to fix the file name.

org-babel-jupyter-resource-directory

This variable is similar to org-preview-latex-image-directory but solely for any files created when Jupyter code blocks are run, e.g. automatically generated image file names.

Deletion of generated image files

Whenever you run a code block multiple times and replace its results, before the results are replaced, any generated files will be deleted to reduce the clutter in org-babel-jupyter-resource-directory.

Convert rich kernel output with the :pandoc header argument

By default html, markdown, and latex results are wrapped in a BEGIN_EXPORT block. If the header argument :pandoc t is set, they are instead converted to org-mode format with pandoc. You can control which outputs get converted with the custom variable jupyter-org-pandoc-convertable.

Editing the contents of a code block

When editing a Jupyter code block's contents, i.e. by pressing C-c ' when at a code block, jupyter-repl-interaction-mode is automatically enabled in the edit buffer and the buffer will be associated with the REPL session of the code block (see jupyter-repl-associate-buffer).

You may also bind the command org-babel-jupyter-scratch-buffer to an appropriate key in org-mode to display a scratch buffer in the code block's major-mode and connected to the code block's session.

Connecting to an existing kernel

To connect to an existing kernel, pass the kernel's connection file as the value of the :session parameter. The name of the file must have a .json suffix for this to work.

Remote kernels

If the connection file is a remote file name, i.e. has a prefix like /method:host:, the kernel's ports are assumed to live on host. Before attempting to connect to the kernel, ssh tunnels for the connection are created. So if you had a remote kernel on a host named ec2 whose connection file is /run/user/1000/jupyter/kernel-julia-0.6.json on that host, you could specify the :session like

#+BEGIN_SRC jupyter-julia :session /ssh:ec2:/run/user/1000/jupyter/kernel-julia-0.6.json
...
#+END_SRC

Note, the kernel on the remote host needs to have the ZMQ socket ports exposed. This means that starting a kernel using

jupyter notebook --no-browser

currently doesn't work since the notebook server does not allow communication with a kernel using ZMQ sockets. You will have to use the connection file created from using something like

jupyter kernel --kernel=python
Password handling for remote connections

Currently there is no password handling, so if your ssh connection requires a password I suggest you instead use key-based authentication. Or if you are connecting to a server using a pem file add something like

Host ec2
    User <user>
    HostName <host>
    IdentityFile <identity>.pem

to your ~/.ssh/config file.

Starting a remote kernel

If :session is a remote file name that doesn't end in .json, e.g. /ssh:ec2:jl, then a kernel on the remote host /ssh:ec2: is started using the jupyter kernel command on the host. The local part of the session name serves to distinguish different remote sessions on the same host.

Communicating with kernel (notebook) servers

If :session is a TRAMP file name like /jpy:localhost#8888:NAME it is interpreted as corresponding to a connection to a kernel through a Jupyter notebook server located at http://localhost:8888.

If NAME is a kernel ID corresponding to an existing kernel on a server, e.g. /jpy::161b2318-180c-497a-b4bf-de76176061d9, then a connection to an existing kernel with the corresponding ID will be made. Otherwise, a new kernel will be launched on the server and NAME will be used as an identifier for the session.

When a new kernel is launched, NAME will also be associated with the kernel's ID, see jupyter-server-kernel-names. This is useful to distinguish Org mode :session kernels from other ones in the buffer shown by jupyter-server-list-kernels.

When connecting to an existing kernel, i.e. when NAME is the ID of a kernel, the :kernel header argument must match the name of the kernel's kernelspec.

To connect to a kernel behind an HTTPS connection, use a TRAMP file name that looks like /jpys:... instead.

TODO Standard output, displayed data, and code block results

One significant difference between Jupyter code blocks and regular org-mode code blocks is that the underlying Jupyter kernel can request that the client display extra data in addition to output or the result of a code block. See display_data messages.

To account for this, Jupyter code blocks do not go through the normal org-mode result insertion mechanism (see org-babel-insert-result). The downside of this is that, compared to normal code blocks, only a small subset of the header arguments common to all code blocks are supported. The upside is that all forms of results produced by a kernel can be inserted into the buffer similar to a Jupyter notebook.

The implementation of org-mode code blocks is really meant to handle either capturing the standard output or the result of a code block. When using Jupyter code blocks, if the kernel produces output or asks to display extra information, the results are appended to a :RESULTS: drawer.

jupyter-org-interaction-mode

A minor mode that enables completion and custom keybindings when point is inside a Jupyter code block. This mode is enabled by default in org-mode buffers, but only has an effect when point is inside a Jupyter code block.

Custom keybindings inside Jupyter code blocks

You can define new keybindings that are enabled when point is inside a Jupyter code block by using the function jupyter-org-define-key. These bindings are added to jupyter-org-interaction-mode-map and are only active when jupyter-org-interaction-mode is enabled.

By default the following keybindings from jupyter-repl-interaction-mode are available when jupyter-org-interaction-mode is enabled

Key binding Command
C-M-x jupyter-eval-defun
M-i jupyter-inspect-at-point
C-x C-e jupyter-eval-line-or-region
C-c C-i jupyter-repl-interrupt-kernel
C-c C-r jupyter-repl-restart-kernel

Kernel/notebook server

Managing live kernels

The main entry point for working working with a kernel server is the jupyter-server-list-kernels command which shows a list of all live kernels from the server URL that you provide when first calling the command. Any subsequent calls to the command will use the same URL as the first call. To change server URLs give a prefix argument, C-u M-x jupyter-server-list-kernels. This will then set the current server URL for future calls to the one you provide. See the jupyter-current-server command for more details.

From the buffer shown by jupyter-server-list-kernels you can launch new kernels (C-RET), connect a REPL to an existing kernel (RET), interrupt a kernel (C-c TAB), kill a kernel (C-c C-d or d), refresh the list of kernels (g) etc. See the jupyter-server-kernel-list-mode for all the available key bindings.

Note, the default-directory of the jupyter-server-kernel-list-mode buffer will be the root directory of the kernel server (so that dired-jump will show a dired listing of the directory). See the section on TRAMP integration below.

Naming kernels

From the jupyter-server-list-kernels buffer one can also name (or rename) a kernel (R) so that it has an identifier other than its ID. Naming a kernel adds the name to the jupyter-server-kernel-names global variable in a form suitable for persisting across Emacs sessions. See its documentation for more details about persisting its value.

TRAMP integration

There is also integration with the Jupyter notebook contents API in the form of a TRAMP backend. This means that reading/writing the contents of directories the notebook server has access to can be done using normal Emacs file operations using file names with TRAMP syntax. Two new TRAMP file name methods are defined, jpy for HTTP connections and jpys for HTTPS connections. So suppose you have a local notebook server at http://localhost:8888, then to access its directory contents you can type

M-x dired RET /jpy:localhost#8888:/

Note localhost is the default host and 8888 is the default port so /jpy:: is equivalent to /jpy:localhost#8888:. You can change the defaults by modifying the jpy or jpys methods in the variable tramp-methods and tramp-default-host-alist.

jupyter-api-authentication-method

Authentication method used for new notebook server connections. By default, when connecting to a new notebook server you will be asked if either a password or a token should be used for authentication. If you only use tokens for authentication you can change this variable to avoid being asked on every new connection.

Customizable variables available for all frontends

jupyter-eval-use-overlays

The variable jupyter-eval-use-overlays controls whether or not the results of evaluations, e.g. results obtained by pressing C-c C-c (jupyter-eval-line-or-region) or similar, should be displayed as overlays in the current buffer. If non-nil, then the results of evaluation are displayed at the end of the line or region being evaluated using an overlay. Only the text/plain representation of a result is displayed inline, images and non-text results are still displayed in pop-up buffers.

You can control how the overlay looks by modifying the jupyter-eval-overlay face. You can also change the prefix string added before the evaluation result, see jupyter-eval-overlay-prefix.

All evaluation result overlays can be cleared from the buffer by calling jupyter-eval-remove-overlays (C-c C-o). Individual overlays are removed whenever the text in the region that was evaluated is modified.

For multi-line overlays you can fold/unfold the overlay by pressing S-RET when point is inside the region of code that caused the overlay to be created. See jupyter-eval-overlay-keymap.

jupyter-eval-short-result-max-lines

If the number of lines of an evaluation result is smaller than this variable, the function stored in jupyter-eval-short-result-display-function is used to display the result. Otherwise the result is displayed in a pop-up buffer.

This variable is mainly used by the jupyter-eval-* commands such as M-x jupyter-eval-line-or-region.