It's just like a markdown live preview, but it's Jupyter Notebook live preview!
Jupynium uses Selenium to automate Jupyter Notebook, synchronising everything you type on Neovim.
Never leave Neovim. Switch tabs on the browser as you switch files on Neovim.
Note that it doesn't sync from Notebook to Neovim so only modify from Neovim.
The Jupynium server will receive events from Neovim, keep the copy of the buffer and apply that to the Jupyter Notebook by using Selenium browser automation. It interacts only through the front end so it doesn't require installing extensions on the kernel etc., which makes it possible to:
geckodriver -V
# jupyter-console is optional and used for `:JupyniumKernelOpenInTerminal`
pip install notebook nbclassic jupyter-console
Jupynium does not support Notebook 7 yet. In the meantime, you can change the default_notebook_URL = "localhost:8888/nbclassic"
in require("jupynium").setup({ ... })
to use the classic (Notebook 6) interface with Jupynium. This is the new default setting from now on.
Don't forget to upgrade your notebook and install nbclassic (pip install --upgrade notebook nbclassic
) when you set this.
Don't have system Python 3.8? You can use Conda:
conda create -n jupynium python=3
conda activate jupynium
Upgrade pip. This solves many problems:
# pip >= 23.0 recommended
pip3 install --upgrade pip
With π€lazy.nvim:
{
"kiyoon/jupynium.nvim",
build = "pip3 install --user .",
-- build = "conda run --no-capture-output -n jupynium pip install .",
-- enabled = vim.fn.isdirectory(vim.fn.expand "~/miniconda3/envs/jupynium"),
},
"rcarriga/nvim-notify", -- optional
"stevearc/dressing.nvim", -- optional, UI for :JupyniumKernelSelect
The default configuration values are below and work well for system-level Python users. If you're a Conda user, you need to change python_host
to execute using the conda
command instead.
nvim-cmp
to show Jupyter kernel completionlocal cmp = require "cmp"
local compare = cmp.config.compare
cmp.setup {
sources = {
{ name = "jupynium", priority = 1000 }, -- consider higher priority than LSP
{ name = "nvim_lsp", priority = 100 },
-- ...
},
sorting = {
priority_weight = 1.0,
comparators = {
compare.score, -- Jupyter kernel completion shows prior to LSP
compare.recently_used,
compare.locality,
-- ...
},
},
}
nvim-ufo
to fold cellsThere is an API serving as a folds provider, which will return a table with format {startLine=#num, endLine=#num}
.
require("jupynium").get_folds()
You should use it with a fold plugin like nvim-ufo.
See #88 for more detail and an example configuration.
*.ju.py
file.:JupyniumStartAndAttachToServer
. This will open Jupyter Notebook on the Firefox browser.
jupyter_command
or just open the Notebook server by yourself: jupyter notebook
:JupyniumStartSync
. This will create an Untitled.ipynb
file on the browser.# %%
in Neovim to create a code cell.
<space>x
.For detailed instructions, see Usage below.
There are 2 general steps to using Jupynium:
The Jupynium server stays alive as long as the browser is alive. So you can see them as the same thing in this doc. For example:
Jupynium uses a Jupytext's percent format (see the Jupynium file format
section below). This Jupytext file named .ju.py
is what you will primarily be interacting with, rather than the .ipynb
file directly. The contents of the Jupynium file are synced to the browser notebook where it can be viewed in real-time. If you want to keep a copy of the notebook, it can be downloaded as an .ipynb
file later.
First, it's recommended to set a password on your notebook (rather than using tokens):
$ jupyter notebook password
Enter password: π
$ jupyter notebook # leave notebook opened
<filename>.ju.py
There are currently 2 ways of converting an existing .ipynb
file to a Jupynium file:
Option 1: Use an included command line tool:
ipynb2jupytext [-h] [--stdout] [--code_only] file.ipynb [file.ju.py]
If you're already familiar with Jupytext, feel free to use it instead.
Option 2: This method requires that you have already connected to the Jupynium server:
.ipynb
file in the web browser after connecting to the server:JupyniumLoadFromIpynbTab
. This will convert the contents of the notebook file to Jupynium format.<filename>.ju.py
When using Jupynium for the first time, it's recommended to start a new notebook to make sure everything works before trying to load existing files.
(This is for local Neovim only. For remote Neovim, see Command-Line Usage)
In Neovim, with your Jupynium .ju.py
file open, you can run :JupyniumStartAndAttachToServer
to start the notebook server.
You need to be on the main notebook page (file browser) for the next few steps.
Although Neovim is now attached to the server, it won't automatically start syncing.
To sync your Neovim Jupynium file to a notebook, run :JupyniumStartSync
.
You can also:
:JupyniumStartSync filename
to give a name to the notebook (filename.ipynb
) instead of Untitled.ipynb
. This does not open existing files. If a file with that name already exists then the filename argument will just be ignored.:JupyniumStartSync 2
to sync to the 2nd tab (count from 1).At this point, any changes you make within the Neovim Jupynium file will be reflected live in the browser. Make sure you do not make changes inside the browser itself, as the sync is only one-way (from Neovim to browser).
If you want to save a copy of the .ipynb
file, run :JupyniumDownloadIpynb
. There is also a configuration option to enable automatic downloading.
You can sync multiple files at the same time. Simple run :JupyniumStartSync
again with the new file you want to sync.
You can run :JupyniumStartSync
on a new Neovim instance.
If you have auto_attach_to_server = false
during setup, you need to run :JupyniumAttachToServer
and :JupyniumStartSync
.
The Jupynium file format follows Jupytext's percent format. In order for Jupynium to detect the files, name them as *.ju.py
or specify jupynium_file_pattern
in require("jupynium").setup()
.
Code cell:
Any code below this line (and before the next separator) will be the content of a code cell.
# %%
Magic commands
# %time
becomes %time
in notebook.## %time
.Markdown cell: Any code below this line will be markdown cell content.
# %% [md]
# %% [markdown]
In Python, the recommended way is to wrap the whole cell content as a multi-line string.
# %% [md]
"""
# This is a markdown heading
This is markdown content
"""
In other languages like R, you'll need to comment every line.
# %% [md]
# # This is a markdown heading
# This is markdown content
Explicitly specify the first cell separator to use it like a notebook.
<space>x
: Execute selected cells<space>c
: Clear selected cells<PageUp>
, <PageDown>
: Scroll notebook<space>js
: Scroll to cell (if autoscroll is disabled)<space>K
: Hover (inspect a variable)<space>jo
: Toggle output scroll (when output is long)If you want custom keymaps, add use_default_keybindings = false
and follow M.default_keybindings()
in lua/jupynium/init.lua.
[j
, ]j
: go to previous / next cell separator
;
and ,
if you have nvim-treesitter-textobjects.
Follow their instructions for keybindings for this.<space>jj
: go to current cell separatorvaj
,vij
, vaJ
, viJ
: select current cell
a
: include separator, i
: exclude separatorj
: exclude next separator, J
: include next separatorIf you want custom keymaps, add textobjects = { use_default_keybindings = false }
and follow M.default_keybindings()
in lua/jupynium/textobj.lua.
" Server (only used when Neovim is local. See Command-Line Usage for remote neovim)
:JupyniumStartAndAttachToServer [notebook_URL]
:JupyniumStartAndAttachToServerInTerminal [notebook_URL] " Useful for debugging
:JupyniumAttachToServer [notebook_URL]
" Sync
:JupyniumStartSync [filename / tab_index]
:JupyniumStopSync
:JupyniumLoadFromIpynbTab tab_index
:JupyniumLoadFromIpynbTabAndStartSync tab_index
" Notebook (while syncing)
:JupyniumSaveIpynb
:JupyniumDownloadIpynb [filename]
:JupyniumAutoDownloadIpynbToggle
:JupyniumScrollToCell
:JupyniumScrollUp
:JupyniumScrollDown
:JupyniumAutoscrollToggle
:JupyniumExecuteSelectedCells
:JupyniumClearSelectedCellsOutputs
:JupyniumToggleSelectedCellsOutputsScroll
:JupyniumKernelRestart
:JupyniumKernelInterrupt
:JupyniumKernelSelect
:JupyniumKernelHover " See value like LSP hover
:JupyniumKernelOpenInTerminal [hostname] " Connect to kernel of synchronized notebook
" Highlight
:JupyniumShortsightedToggle
The core API is provided as a global function.
--- Execute javascript in the browser. It will switch to the correct tab before executing.
---@param bufnr: integer | nil If given, before executing the code it will switch to the tab of this buffer. Requires syncing in advance.
---@param code string Javascript code
---@return boolean, object: Success, response
Jupynium_execute_javascript(bufnr, code)
Example: get kernel name and language
-- Use bufnr=nil if you don't want to switch tab
local code = [[return [Jupyter.notebook.kernel.name, Jupyter.kernelselector.kernelspecs];]]
local status_ok, kernel_name_and_spec = Jupynium_execute_javascript(0, code)
if status_ok then
local kernel_name = kernel_name_and_spec[1] -- "python3"
local kernel_spec = kernel_name_and_spec[2]
local kernel_language = kernel_spec[kernel_name].spec.language -- "python"
local kernel_display_name = kernel_spec[kernel_name].spec.display_name -- "Python 3 (ipykernel)"
end
You don't need to install the vim plugin to use Jupynium. The plugin is responsible of adding :JupyniumStartAndAttachToServer
etc. that just calls the command line program, plus it has textobjects and shortsighted support.
Install Jupynium if you haven't already:
pip3 install jupynium
Open a python/markdown file with nvim and see :echo v:servername
.
Run Jupynium like:
jupynium --nvim_listen_addr /tmp/your_socket_path
Or, you can run Neovim like
nvim --listen localhost:18898 notebook.ju.py
Then start Jupynium as well as attaching the neovim to it.
jupynium --nvim_listen_addr localhost:18898
Note that you can attach to remote neovim by changing localhost
to servername.com
or using SSH port forwarding.
This will open Firefox with Selenium, defaulting to http://localhost:8888/nbclassic
.
Additionally,
jupynium
command multiple times to attach more than one Neovim instance.jupynium --notebook_URL localhost:18888
to view different notebook.jupynium
without arguments to just leave the server / browser running and wait for nvim to attach.The program is in the alpha stage. If it crashes it's likely that the whole browser turns off without saving!
π½ How do I use different languages / kernels?
Instead of *.ju.py
if you make files named *.ju.*
(e.g. *.ju.r
) you will see all the keybindings and commands.
All the procedures should be the same.
The notebook content is not in sync with vim. How do I fix it?
You probably would have accidentally modified directly from the notebook.
:JupyniumLoadFromIpynbTab [tab_index]
without making changes on vim.