Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(API): Jupynium_execute_javascript, :JupyniumKernelInterrupt #46

Merged
merged 1 commit into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,40 @@ If you want custom keymaps, add `textobjects = { use_default_keybindings = false
:JupyniumClearSelectedCellsOutputs
:JupyniumToggleSelectedCellsOutputsScroll

:JupyniumRestartKernel
:JupyniumSelectKernel
:JupyniumKernelRestart
:JupyniumKernelInterrupt
:JupyniumKernelSelect

" Highlight
:JupyniumShortsightedToggle
```

### Lua API

The core API is provided as a global function.

```lua
--- 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

```lua
-- 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
```

## 👨‍💻️ Command-Line Usage (Attach to Remote NeoVim)

**You don't need to install the vim plugin to use Jupynium.**
Expand Down
20 changes: 17 additions & 3 deletions src/jupynium/events_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ def process_request_event(nvim_info: NvimInfo, driver, event):
logger.info("Nvim closed. Clearing nvim")
return False, event[3]

elif event[1] == "get_kernel_spec":
elif event[1] == "kernel_get_spec":
driver.switch_to.window(nvim_info.window_handles[bufnr])
kernel_specs = driver.execute_script(
"return [Jupyter.notebook.kernel.name, Jupyter.kernelselector.kernelspecs];"
Expand All @@ -430,6 +430,17 @@ def process_request_event(nvim_info: NvimInfo, driver, event):
event[3].send(kernel_specs)
return True, None

elif event[1] == "execute_javascript":
(code,) = event_args
if bufnr is not None:
driver.switch_to.window(nvim_info.window_handles[bufnr])
logger.info(f"Executing javascript code in bufnr {bufnr}, code {code}")

logger.info(f"Executing javascript code in bufnr {bufnr}, code {code}")
ret_obj = driver.execute_script(code)
event[3].send(ret_obj)
return True, None

if event[3] is not None:
event[3].send("OK")

Expand Down Expand Up @@ -597,10 +608,13 @@ def process_notification_event(
"Jupyter.notebook.clear_cells_outputs(Jupyter.notebook.get_selected_cells_indices())"
)
# driver.execute_script("Jupyter.notebook.clear_output();")
elif event[1] == "restart_kernel":
elif event[1] == "kernel_restart":
driver.switch_to.window(nvim_info.window_handles[bufnr])
driver.execute_script("Jupyter.notebook.kernel.restart()")
elif event[1] == "change_kernel":
elif event[1] == "kernel_interrupt":
driver.switch_to.window(nvim_info.window_handles[bufnr])
driver.execute_script("Jupyter.notebook.kernel.interrupt()")
elif event[1] == "kernel_change":
(kernel_name,) = event_args
driver.switch_to.window(nvim_info.window_handles[bufnr])
driver.execute_script(
Expand Down
5 changes: 5 additions & 0 deletions src/jupynium/lua/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,10 @@ vim.api.nvim_create_user_command("JupyniumScrollUp", "lua Jupynium_scroll_up()",
vim.api.nvim_create_user_command("JupyniumScrollDown", "lua Jupynium_scroll_down()", {})
vim.api.nvim_create_user_command("JupyniumAutoscrollToggle", "lua Jupynium_autoscroll_toggle()", {})

---@deprecated
vim.api.nvim_create_user_command("JupyniumRestartKernel", "lua Jupynium_restart_kernel()", {})
vim.api.nvim_create_user_command("JupyniumSelectKernel", "lua Jupynium_select_kernel()", {})

vim.api.nvim_create_user_command("JupyniumKernelRestart", "lua Jupynium_kernel_restart()", {})
vim.api.nvim_create_user_command("JupyniumKernelInterrupt", "lua Jupynium_kernel_interrupt()", {})
vim.api.nvim_create_user_command("JupyniumKernelSelect", "lua Jupynium_kernel_select()", {})
60 changes: 53 additions & 7 deletions src/jupynium/lua/helpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,30 @@ function Jupynium_rpcrequest(event, buf, ensure_syncing, ...)
return response
end

--- API: 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
function Jupynium_execute_javascript(bufnr, code)
local ensure_syncing = true
if bufnr == nil then
ensure_syncing = false
elseif bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end

if ensure_syncing and Jupynium_syncing_bufs[bufnr] == nil then
Jupynium_notify.error {
[[Cannot execute javascript because it's not synchronised]],
[[Run `:JupyniumStartSync` or set bufnr=nil in Jupynium_execute_javascript()]],
}
return false, nil
end

-- set ensure_syncing to false, because we checked that already.
return true, Jupynium_rpcrequest("execute_javascript", bufnr, false, code)
end

function Jupynium_grab_entire_buffer(bufnr)
if bufnr == nil or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
Expand Down Expand Up @@ -402,7 +426,7 @@ function Jupynium_clear_selected_cells_outputs(bufnr)
Jupynium_rpcnotify("clear_selected_cells_outputs", bufnr, true)
end

function Jupynium_get_kernel_spec(bufnr)
function Jupynium_kernel_get_spec(bufnr)
-- Users shouldn't have to call this function directly, and thus it won't be available as a command.
-- returns a table
-- ret[1] = current kernel name
Expand All @@ -420,11 +444,11 @@ function Jupynium_get_kernel_spec(bufnr)
return
end

local kernel_spec = Jupynium_rpcrequest("get_kernel_spec", bufnr, true)
local kernel_spec = Jupynium_rpcrequest("kernel_get_spec", bufnr, true)
return kernel_spec
end

function Jupynium_change_kernel(bufnr, kernel_name)
function Jupynium_kernel_change(bufnr, kernel_name)
-- note that the kernel name is different from the display name in the kernel list in Jupyter Notebook.
-- Users shouldn't have to call this function directly, and thus it won't be available as a command.
if bufnr == nil or bufnr == 0 then
Expand All @@ -435,10 +459,14 @@ function Jupynium_change_kernel(bufnr, kernel_name)
return
end

Jupynium_rpcnotify("change_kernel", bufnr, true, kernel_name)
Jupynium_rpcnotify("kernel_change", bufnr, true, kernel_name)
end

function Jupynium_restart_kernel(bufnr)
Jupynium_notify.error { [[Sorry! Command name changed.]], [[Please use :JupyniumKernelRestart]] }
end

function Jupynium_kernel_restart(bufnr)
-- note that the kernel name is different from the display name in the kernel list in Jupyter Notebook.
if bufnr == nil or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
Expand All @@ -448,10 +476,28 @@ function Jupynium_restart_kernel(bufnr)
return
end

Jupynium_rpcnotify("restart_kernel", bufnr, true)
Jupynium_rpcnotify("kernel_restart", bufnr, true)
end

function Jupynium_kernel_interrupt(bufnr)
-- note that the kernel name is different from the display name in the kernel list in Jupyter Notebook.
-- Users shouldn't have to call this function directly, and thus it won't be available as a command.
if bufnr == nil or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
if Jupynium_syncing_bufs[bufnr] == nil then
Jupynium_notify.error { [[Cannot interrupt kernel without synchronising.]], [[Run `:JupyniumStartSync`]] }
return
end

Jupynium_rpcnotify("kernel_interrupt", bufnr, true)
end

function Jupynium_select_kernel(bufnr)
Jupynium_notify.error { [[Sorry! Command name changed.]], [[Please use :JupyniumKernelSelect]] }
end

function Jupynium_kernel_select(bufnr)
-- note that the kernel name is different from the display name in the kernel list in Jupyter Notebook.
if bufnr == nil or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
Expand All @@ -461,7 +507,7 @@ function Jupynium_select_kernel(bufnr)
return
end

local jupynium_kernel_name_and_spec = Jupynium_get_kernel_spec(bufnr)
local jupynium_kernel_name_and_spec = Jupynium_kernel_get_spec(bufnr)
local current_kernel_name = jupynium_kernel_name_and_spec[1]
local kernel_spec = jupynium_kernel_name_and_spec[2]
local kernel_display_names, kernel_dispname_to_name = {}, {}
Expand Down Expand Up @@ -498,6 +544,6 @@ function Jupynium_select_kernel(bufnr)
vim.ui.select(kernel_display_names, {
prompt = "Select a kernel for Jupynium (Jupyter Notebook)",
}, function(selected)
Jupynium_change_kernel(bufnr, kernel_dispname_to_name[selected])
Jupynium_kernel_change(bufnr, kernel_dispname_to_name[selected])
end)
end