I'm trying to open a notebook with molten.nvim, using the setup guide. Only stuff I haven't done is the treesitter stuff at the bottom.
However, when I open the notebook, it shows a blank screen (see image).
Any idea how to fix the error? Let me know what other stuff is worth providing as well.
Setup + Result
I'm using Lazy to set up my notebook with settings for molten (with image, jupytext, and quarto as dependencies), quarto, jupytext, vim-slime, img-clip, and nabla. Config files are below
One weird thing I've noticed is that whenever I run jupyter-notebook, localhost:8888/tree is blank, so I have to open up 127.0.0.1:8888/tree, exit my browser, and then click into my browser again before being able to see. However, VSCode doesn't seem to have that issue.
molten.lua
molten.lua
```lua
return {
"benlubas/molten-nvim",
dependencies = {
"3rd/image.nvim",
"GCBallesteros/jupytext.nvim",
"quarto-dev/quarto-nvim",
},
build = ":UpdateRemotePlugins",
init = function()
vim.g.molten_auto_open_output = false
vim.g.molten_image_provider = "image.nvim"
vim.g.molten_output_win_max_height = 20
vim.g.molten_wrap_output = true
vim.g.molten_virt_text_output = true
vim.g.molten_virt_lines_off_by_1 = true
end,
config = function()
vim.g.molten_virt_text_output = true
-- automatically import output chunks from a jupyter notebook
-- tries to find a kernel that matches the kernel in the jupyter notebook
-- falls back to a kernel that matches the name of the active venv (if any)
local imb = function(e) -- init molten buffer
vim.schedule(function()
local kernels = vim.fn.MoltenAvailableKernels()
local try_kernel_name = function()
local metadata = vim.json.decode(io.open(e.file, "r"):read("a"))["metadata"]
return metadata.kernelspec.name
end
local ok, kernel_name = pcall(try_kernel_name)
if not ok or not vim.tbl_contains(kernels, kernel_name) then
kernel_name = nil
local venv = os.getenv("VIRTUAL_ENV")
if venv ~= nil then
kernel_name = string.match(venv, "/.+/(.+)")
end
end
if kernel_name ~= nil and vim.tbl_contains(kernels, kernel_name) then
vim.cmd(("MoltenInit %s"):format(kernel_name))
end
vim.cmd("MoltenImportOutput")
end)
end
-- automatically import output chunks from a jupyter notebook
vim.api.nvim_create_autocmd("BufAdd", {
pattern = { "*.ipynb" },
callback = imb,
})
-- we have to do this as well so that we catch files opened like nvim ./hi.ipynb
vim.api.nvim_create_autocmd("BufEnter", {
pattern = { "*.ipynb" },
callback = function(e)
if vim.api.nvim_get_vvar("vim_did_enter") ~= 1 then
imb(e)
end
end,
})
-- automatically export output chunks to a jupyter notebook on write
vim.api.nvim_create_autocmd("BufWritePost", {
pattern = { "*.ipynb" },
callback = function()
if require("molten.status").initialized() == "Molten" then
vim.cmd("MoltenExportOutput!")
end
end,
})
-- change the configuration when editing a python file
vim.api.nvim_create_autocmd("BufEnter", {
pattern = "*.py",
callback = function(e)
if string.match(e.file, ".otter.") then
return
end
if require("molten.status").initialized() == "Molten" then -- this is kinda a hack...
vim.fn.MoltenUpdateOption("virt_lines_off_by_1", false)
vim.fn.MoltenUpdateOption("virt_text_output", false)
else
vim.g.molten_virt_lines_off_by_1 = false
vim.g.molten_virt_text_output = false
end
end,
})
-- Undo those config changes when we go back to a markdown or quarto file
vim.api.nvim_create_autocmd("BufEnter", {
pattern = { "*.qmd", "*.md", "*.ipynb" },
callback = function(e)
if string.match(e.file, ".otter.") then
return
end
if require("molten.status").initialized() == "Molten" then
vim.fn.MoltenUpdateOption("virt_lines_off_by_1", true)
vim.fn.MoltenUpdateOption("virt_text_output", true)
else
vim.g.molten_virt_lines_off_by_1 = true
vim.g.molten_virt_text_output = true
end
end,
})
vim.keymap.set("n", "mi", ":MoltenInit", { silent = true, desc = "Initialize the plugin" })
vim.keymap.set(
"n",
"mr",
":MoltenEvaluateOperator",
{ silent = true, desc = "run operator selection" }
)
vim.keymap.set("n", "mrl", ":MoltenEvaluateLine", { silent = true, desc = "evaluate line" })
vim.keymap.set("n", "mrr", ":MoltenReevaluateCell", { silent = true, desc = "re-evaluate cell" })
vim.keymap.set(
"v",
"mrv",
":MoltenEvaluateVisualgv",
{ silent = true, desc = "evaluate visual selection" }
)
vim.keymap.set("n", "md", ":MoltenDelete", { silent = true, desc = "molten delete cell" })
vim.keymap.set("n", "mh", ":MoltenHideOutput", { silent = true, desc = "hide output" })
vim.keymap.set(
"n",
"mo",
":noautocmd MoltenEnterOutput",
{ silent = true, desc = "show/enter output" }
)
vim.keymap.set(
"n",
"mb",
":MoltenOpenInBrowser",
{ desc = "open output in browser", silent = true }
)
vim.keymap.set("n", "mnc", ":MoltenNext", { silent = true, desc = "molten next cell" })
vim.keymap.set("n", "mpk", ":MoltenPrev", { silent = true, desc = "molten prev cell" })
vim.keymap.set("n", "mr", ":MoltenRestart", { silent = true, desc = "molten restart" })
-- Provide a command to create a blank new Python notebook
-- note: the metadata is needed for Jupytext to understand how to parse the notebook.
-- if you use another language than Python, you should change it in the template.
local default_notebook = [[
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython"
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
]]
local function new_notebook(filename)
local path = filename .. ".ipynb"
local file = io.open(path, "w")
if file then
file:write(default_notebook)
file:close()
vim.cmd("edit " .. path)
else
print("Error: Could not open new notebook file for writing.")
end
end
vim.api.nvim_create_user_command("NewNotebook", function(opts)
new_notebook(opts.args)
end, {
nargs = 1,
complete = "file",
})
end,
}
```
quarto.lua
quarto.lua
```lua
return {
{ -- requires plugins in lua/plugins/treesitter.lua and lua/plugins/lsp.lua
-- for complete functionality (language features)
"quarto-dev/quarto-nvim",
ft = { "quarto", "markdown" },
dev = false,
opts = {},
dependencies = {
-- for language features in code cells
-- configured in lua/plugins/lsp.lua and
-- added as a nvim-cmp source in lua/plugins/completion.lua
"jmbuhr/otter.nvim",
},
config = function()
local quarto = require("quarto")
quarto.setup()
vim.keymap.set("n", "qp", quarto.quartoPreview, { silent = true, noremap = true })
local runner = require("quarto.runner")
vim.keymap.set("n", "nrc", runner.run_cell, { desc = "run cell", silent = true })
vim.keymap.set("n", "nra", runner.run_above, { desc = "run cell and above", silent = true })
vim.keymap.set("n", "nrA", runner.run_all, { desc = "run all cells", silent = true })
vim.keymap.set("n", "nrl", runner.run_line, { desc = "run line", silent = true })
vim.keymap.set("v", "nr", runner.run_range, { desc = "run visual range", silent = true })
vim.keymap.set("n", "nRA", function()
runner.run_all(true)
end, { desc = "run all cells of all languages", silent = true })
end,
},
{ -- directly open ipynb files as quarto docuements
-- and convert back behind the scenes
"GCBallesteros/jupytext.nvim",
opts = {
-- custom_language_formatting = {
-- python = {
-- extension = "qmd",
-- style = "quarto",
-- force_ft = "quarto",
-- },
-- r = {
-- extension = "qmd",
-- style = "quarto",
-- force_ft = "quarto",
-- },
-- },
},
config = function()
require("jupytext").setup({
style = "markdown",
output_extension = "md",
force_ft = "markdown",
})
end,
},
{ -- send code from python/r/qmd documets to a terminal or REPL
-- like ipython, R, bash
"jpalardy/vim-slime",
dev = false,
init = function()
vim.b["quarto_is_python_chunk"] = false
Quarto_is_in_python_chunk = function()
require("otter.tools.functions").is_otter_language_context("python")
end
vim.cmd([[
let g:slime_dispatch_ipython_pause = 100
function SlimeOverride_EscapeText_quarto(text)
call v:lua.Quarto_is_in_python_chunk()
if exists('g:slime_python_ipython') && len(split(a:text,"\n")) > 1 && b:quarto_is_python_chunk && !(exists('b:quarto_is_r_mode') && b:quarto_is_r_mode)
return ["%cpaste -q\n", g:slime_dispatch_ipython_pause, a:text, "--", "\n"]
else
if exists('b:quarto_is_r_mode') && b:quarto_is_r_mode && b:quarto_is_python_chunk
return [a:text, "\n"]
else
return [a:text]
end
end
endfunction
]])
vim.g.slime_target = "neovim"
vim.g.slime_no_mappings = true
vim.g.slime_python_ipython = 1
end,
config = function()
vim.g.slime_input_pid = false
vim.g.slime_suggest_default = true
vim.g.slime_menu_config = false
vim.g.slime_neovim_ignore_unlisted = true
local function mark_terminal()
local job_id = vim.b.terminal_job_id
vim.print("job_id: " .. job_id)
end
local function set_terminal()
vim.fn.call("slime#config", {})
end
vim.keymap.set("n", "cm", mark_terminal, { desc = "[m]ark terminal" })
vim.keymap.set("n", "cs", set_terminal, { desc = "[s]et terminal" })
end,
},
{ -- paste an image from the clipboard or drag-and-drop
"HakonHarnes/img-clip.nvim",
event = "BufEnter",
ft = { "markdown", "quarto", "latex" },
opts = {
default = {
dir_path = "img",
},
filetypes = {
markdown = {
url_encode_path = true,
template = "![$CURSOR]($FILE_PATH)",
drag_and_drop = {
download_images = false,
},
},
quarto = {
url_encode_path = true,
template = "![$CURSOR]($FILE_PATH)",
drag_and_drop = {
download_images = false,
},
},
},
},
config = function(_, opts)
require("img-clip").setup(opts)
vim.keymap.set("n", "ii", ":PasteImage", { desc = "insert [i]mage from clipboard" })
end,
},
{ -- preview equations
"jbyuki/nabla.nvim",
keys = {
{ "qm", ':lua require"nabla".toggle_virt()', desc = "toggle [m]ath equations" },
},
},
}
```
The issue
I'm trying to open a notebook with molten.nvim, using the setup guide. Only stuff I haven't done is the treesitter stuff at the bottom. However, when I open the notebook, it shows a blank screen (see image). Any idea how to fix the error? Let me know what other stuff is worth providing as well.
Setup + Result
jupyter-notebook
,localhost:8888/tree
is blank, so I have to open up127.0.0.1:8888/tree
, exit my browser, and then click into my browser again before being able to see. However, VSCode doesn't seem to have that issue.molten.lua
molten.lua
```lua return { "benlubas/molten-nvim", dependencies = { "3rd/image.nvim", "GCBallesteros/jupytext.nvim", "quarto-dev/quarto-nvim", }, build = ":UpdateRemotePlugins", init = function() vim.g.molten_auto_open_output = false vim.g.molten_image_provider = "image.nvim" vim.g.molten_output_win_max_height = 20 vim.g.molten_wrap_output = true vim.g.molten_virt_text_output = true vim.g.molten_virt_lines_off_by_1 = true end, config = function() vim.g.molten_virt_text_output = true -- automatically import output chunks from a jupyter notebook -- tries to find a kernel that matches the kernel in the jupyter notebook -- falls back to a kernel that matches the name of the active venv (if any) local imb = function(e) -- init molten buffer vim.schedule(function() local kernels = vim.fn.MoltenAvailableKernels() local try_kernel_name = function() local metadata = vim.json.decode(io.open(e.file, "r"):read("a"))["metadata"] return metadata.kernelspec.name end local ok, kernel_name = pcall(try_kernel_name) if not ok or not vim.tbl_contains(kernels, kernel_name) then kernel_name = nil local venv = os.getenv("VIRTUAL_ENV") if venv ~= nil then kernel_name = string.match(venv, "/.+/(.+)") end end if kernel_name ~= nil and vim.tbl_contains(kernels, kernel_name) then vim.cmd(("MoltenInit %s"):format(kernel_name)) end vim.cmd("MoltenImportOutput") end) end -- automatically import output chunks from a jupyter notebook vim.api.nvim_create_autocmd("BufAdd", { pattern = { "*.ipynb" }, callback = imb, }) -- we have to do this as well so that we catch files opened like nvim ./hi.ipynb vim.api.nvim_create_autocmd("BufEnter", { pattern = { "*.ipynb" }, callback = function(e) if vim.api.nvim_get_vvar("vim_did_enter") ~= 1 then imb(e) end end, }) -- automatically export output chunks to a jupyter notebook on write vim.api.nvim_create_autocmd("BufWritePost", { pattern = { "*.ipynb" }, callback = function() if require("molten.status").initialized() == "Molten" then vim.cmd("MoltenExportOutput!") end end, }) -- change the configuration when editing a python file vim.api.nvim_create_autocmd("BufEnter", { pattern = "*.py", callback = function(e) if string.match(e.file, ".otter.") then return end if require("molten.status").initialized() == "Molten" then -- this is kinda a hack... vim.fn.MoltenUpdateOption("virt_lines_off_by_1", false) vim.fn.MoltenUpdateOption("virt_text_output", false) else vim.g.molten_virt_lines_off_by_1 = false vim.g.molten_virt_text_output = false end end, }) -- Undo those config changes when we go back to a markdown or quarto file vim.api.nvim_create_autocmd("BufEnter", { pattern = { "*.qmd", "*.md", "*.ipynb" }, callback = function(e) if string.match(e.file, ".otter.") then return end if require("molten.status").initialized() == "Molten" then vim.fn.MoltenUpdateOption("virt_lines_off_by_1", true) vim.fn.MoltenUpdateOption("virt_text_output", true) else vim.g.molten_virt_lines_off_by_1 = true vim.g.molten_virt_text_output = true end end, }) vim.keymap.set("n", "quarto.lua
quarto.lua
```lua return { { -- requires plugins in lua/plugins/treesitter.lua and lua/plugins/lsp.lua -- for complete functionality (language features) "quarto-dev/quarto-nvim", ft = { "quarto", "markdown" }, dev = false, opts = {}, dependencies = { -- for language features in code cells -- configured in lua/plugins/lsp.lua and -- added as a nvim-cmp source in lua/plugins/completion.lua "jmbuhr/otter.nvim", }, config = function() local quarto = require("quarto") quarto.setup() vim.keymap.set("n", "Error