From b626f8d848ed01d648357f5b3d223fddcc732dcf Mon Sep 17 00:00:00 2001
From: Ben Lubas <56943754+benlubas@users.noreply.github.com>
Date: Fri, 22 Dec 2023 10:01:31 -0500
Subject: [PATCH] feat: MoltenInit revamp + bug fixes (#103)
---
lua/prompt.lua | 51 ++++++++++++++
rplugin/python3/molten/__init__.py | 102 ++++++++--------------------
rplugin/python3/molten/code_cell.py | 2 +
3 files changed, 83 insertions(+), 72 deletions(-)
create mode 100644 lua/prompt.lua
diff --git a/lua/prompt.lua b/lua/prompt.lua
new file mode 100644
index 0000000..de9a8b1
--- /dev/null
+++ b/lua/prompt.lua
@@ -0,0 +1,51 @@
+local M = {}
+
+---show the MoltenInit prompt with the given kernels
+---started as shared kernels.
+---@param kernels table
list of tuples of (str, bool)
+---@param prompt string
+M.prompt_init = function(kernels, prompt)
+ vim.schedule_wrap(function()
+ vim.ui.select(kernels, {
+ prompt = prompt,
+ format_item = function(item)
+ if item[2] then
+ return "(shared) " .. item[1]
+ else
+ return item[1]
+ end
+ end,
+ }, function(choice)
+ if choice ~= nil then
+ vim.schedule_wrap(function()
+ if choice[2] then
+ vim.cmd("MoltenInit shared " .. choice[1])
+ else
+ vim.cmd("MoltenInit " .. choice[1])
+ end
+ end)()
+ end
+ end)
+ end)()
+end
+
+---prompt the user for a kernel, and then run the command with that kernel. %k in the command means
+---the kernel name will be substituted in.
+---@param kernels table list of kernels
+---@param prompt string
+---@param command string command, with %k substituted for the selected kernel name
+M.select_and_run = function (kernels, prompt, command)
+ vim.schedule_wrap(function()
+ vim.ui.select(kernels, {
+ prompt = prompt,
+ }, function(choice)
+ if choice ~= nil then
+ vim.schedule_wrap(function()
+ vim.cmd(command:gsub("%%k", choice))
+ end)()
+ end
+ end)
+ end)()
+end
+
+return M
diff --git a/rplugin/python3/molten/__init__.py b/rplugin/python3/molten/__init__.py
index d101b7f..6f0c68e 100644
--- a/rplugin/python3/molten/__init__.py
+++ b/rplugin/python3/molten/__init__.py
@@ -71,6 +71,9 @@ def _initialize(self) -> None:
self._setup_highlights()
self._set_autocommands()
+ self.nvim.exec_lua("_prompt_init = require('prompt').prompt_init")
+ self.nvim.exec_lua("_select_and_run = require('prompt').select_and_run")
+
self.initialized = True
def _set_autocommands(self) -> None:
@@ -218,41 +221,21 @@ def command_init(self, args: List[str]) -> None:
self._initialize_buffer(kernel_name, shared=shared)
else:
PROMPT = "Select the kernel to launch:"
- available_kernels = get_available_kernels()
-
- if len(available_kernels) == 0:
- notify_error(self.nvim, "Unable to find any kernels to launch.")
- return
+ available_kernels = [(x, False) for x in get_available_kernels()]
+ running_kernels = [(x, True) for x in self.molten_kernels.keys()]
if shared:
- # Only show kernels that are already tracked by Molten
- available_kernels = list(
- filter(lambda x: x in self.molten_kernels.keys(), available_kernels)
- )
+ # only show running kernels
+ available_kernels = []
- if len(available_kernels) == 0:
+ kernels = available_kernels + running_kernels
+ if len(kernels) == 0:
notify_error(
- self.nvim,
- "No running kernels to share. Please use :MoltenInit without the shared option.",
+ self.nvim, f"Unable to find any {'shared' if shared else ''}kernels to launch."
)
return
- lua = f"""
- vim.schedule_wrap(function()
- vim.ui.select(
- {{{", ".join(repr(x) for x in available_kernels)}}},
- {{prompt = "{PROMPT}"}},
- function(choice)
- if choice ~= nil then
- vim.schedule_wrap(function()
- vim.cmd("MoltenInit {'shared ' if shared else ''}" .. choice)
- end)()
- end
- end
- )
- end)()
- """
- self.nvim.exec_lua(lua, async_=False)
+ self.nvim.lua._prompt_init(kernels, PROMPT)
def _deinit_buffer(self, molten_kernels: List[MoltenKernel]) -> None:
# Have to copy this to get around reference issues
@@ -479,7 +462,9 @@ def commnand_molten_evaluate_argument(self, args: List[str]) -> None:
):
self._do_evaluate_expr(args[0], " ".join(args[1:]))
else:
- self.kernel_check("MoltenEvaluateArgument", " ".join(args), self.nvim.current.buffer)
+ self.kernel_check(
+ f"MoltenEvaluateArgument %k {' '.join(args)}", self.nvim.current.buffer
+ )
@pynvim.command("MoltenEvaluateVisual", nargs="*", sync=True) # type: ignore
@nvimui # type: ignore
@@ -487,7 +472,7 @@ def command_evaluate_visual(self, args) -> None:
if len(args) > 0:
kernel = args[0]
else:
- self.kernel_check("MoltenEvaluateVisual", "", self.nvim.current.buffer)
+ self.kernel_check("MoltenEvaluateVisual %k", self.nvim.current.buffer)
return
_, lineno_begin, colno_begin, _ = self.nvim.funcs.getpos("'<")
_, lineno_end, colno_end, _ = self.nvim.funcs.getpos("'>")
@@ -524,8 +509,7 @@ def evaulate_range(self, args) -> None:
if not kernel:
self.kernel_check(
- "call MoltenEvaluateRange('",
- f"', {start_line}, {end_line}, {start_col}, {end_col})",
+ f"call MoltenEvaluateRange('%k', {start_line}, {end_line}, {start_col}, {end_col})",
self.nvim.current.buffer,
)
return
@@ -556,20 +540,13 @@ def command_evaluate_line(self, args: List[str]) -> None:
if len(args) > 0 and args[0]:
self._do_evaluate(args[0], span)
else:
- self.kernel_check("MoltenEvaluateLine", "", self.nvim.current.buffer)
+ self.kernel_check("MoltenEvaluateLine %k", self.nvim.current.buffer)
- def kernel_check(
- self, command: str, command_args: str, buffer: Buffer, kernel_last=False
- ) -> None:
+ def kernel_check(self, command: str, buffer: Buffer) -> None:
"""Figure out if there is more than one kernel attached to the given buffer. If there is,
- and there is prompt the user for the kernel name, and run the given command with the new
- kernel, and arguments. If there is no kernel, throw an error. If there is one kernel, use
- it"""
-
- def cmd(kernel_id: str):
- if kernel_last:
- return f"{command} {command_args} {kernel_id}"
- return f"{command} {kernel_id} {command_args}"
+ prompt the user for the kernel name, and run the given command with the new kernel subbed in
+ for %k. If there is no kernel, throw an error. If there is one kernel, use it
+ """
kernels = self.buffers.get(buffer.number)
if not kernels:
@@ -577,28 +554,12 @@ def cmd(kernel_id: str):
"Molten has not been initialized for this buffer. Please run :MoltenInit"
)
elif len(kernels) == 1:
- c = cmd(kernels[0].kernel_id)
+ c = command.replace("%k", kernels[0].kernel_id)
self.nvim.command(c)
else:
PROMPT = "Please select a kernel:"
available_kernels = [kernel.kernel_id for kernel in kernels]
-
- lua = f"""
- vim.schedule_wrap(function()
- vim.ui.select(
- {{{", ".join(repr(x) for x in available_kernels)}}},
- {{prompt = "{PROMPT}"}},
- function(choice)
- if choice ~= nil then
- vim.schedule_wrap(function()
- vim.cmd("{cmd('".. choice .."')}")
- end)()
- end
- end
- )
- end)()
- """
- self.nvim.exec_lua(lua, async_=False)
+ self.nvim.lua._select_and_run(available_kernels, PROMPT, command)
@pynvim.command("MoltenReevaluateAll", nargs=0, sync=True) # type: ignore
@nvimui # type: ignore
@@ -634,7 +595,7 @@ def command_interrupt(self, args) -> None:
if len(args) > 0:
kernel = args[0]
else:
- self.kernel_check("MoltenInterrupt", "", self.nvim.current.buffer)
+ self.kernel_check("MoltenInterrupt %k", self.nvim.current.buffer)
return
molten_kernels = self._get_current_buf_kernels(True)
@@ -652,7 +613,7 @@ def command_restart(self, args, bang) -> None:
if len(args) > 0:
kernel = args[0]
else:
- self.kernel_check(f"MoltenRestart{'!' if bang else ''}", "", self.nvim.current.buffer)
+ self.kernel_check(f"MoltenRestart{'!' if bang else ''} %k", self.nvim.current.buffer)
return
molten_kernels = self._get_current_buf_kernels(True)
@@ -671,7 +632,7 @@ def command_delete(self) -> None:
assert molten_kernels is not None
for molten in molten_kernels:
- if molten.current_output is not None:
+ if molten.selected_cell is not None:
molten.delete_current_cell()
return
@@ -727,7 +688,7 @@ def command_import(self, args) -> None:
if len(args) > 1:
kernel = args[1]
else:
- self.kernel_check(f"MoltenImportOutput", path, buf, kernel_last=True)
+ self.kernel_check(f"MoltenImportOutput {path} %k", buf)
return
kernels = self._get_current_buf_kernels(True)
@@ -751,9 +712,7 @@ def command_export(self, args, bang: bool) -> None:
if len(args) > 1:
kernel = args[1]
else:
- self.kernel_check(
- f"MoltenExportOutput{'!' if bang else ''}", path, buf, kernel_last=True
- )
+ self.kernel_check(f"MoltenExportOutput{'!' if bang else ''} {path} %k", buf)
return
kernels = self._get_current_buf_kernels(True)
@@ -777,7 +736,7 @@ def command_save(self, args) -> None:
if len(args) > 1:
kernel = args[1]
else:
- self.kernel_check(f"MoltenSave", path, buf, kernel_last=True)
+ self.kernel_check(f"MoltenSave {path} %k", buf)
return
dirname = os.path.dirname(path)
@@ -919,8 +878,7 @@ def function_molten_operatorfunc(self, args) -> None:
)
self.kernel_check(
- "call MoltenEvaluateRange('",
- f"', {span[0][0]}, {span[1][0]}, {span[0][1]}, {span[1][1]})",
+ f"call MoltenEvaluateRange('%k', {span[0][0]}, {span[1][0]}, {span[0][1]}, {span[1][1]})",
self.nvim.current.buffer,
)
diff --git a/rplugin/python3/molten/code_cell.py b/rplugin/python3/molten/code_cell.py
index c3d56ab..77243d3 100644
--- a/rplugin/python3/molten/code_cell.py
+++ b/rplugin/python3/molten/code_cell.py
@@ -58,6 +58,8 @@ def get_text(self, nvim: Nvim) -> str:
self.bufno, self.begin.lineno, self.end.lineno + 1, False
)
+ if len(lines) == 0:
+ return "" # apparently this can happen...
if len(lines) == 1:
return lines[0][self.begin.colno : self.end.colno]
else: