Skip to content

Commit

Permalink
feat: MoltenInit revamp + bug fixes (#103)
Browse files Browse the repository at this point in the history
  • Loading branch information
benlubas committed Dec 22, 2023
1 parent b829b93 commit b626f8d
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 72 deletions.
51 changes: 51 additions & 0 deletions lua/prompt.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
local M = {}

---show the MoltenInit prompt with the given kernels
---started as shared kernels.
---@param kernels table<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<string> 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
102 changes: 30 additions & 72 deletions rplugin/python3/molten/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -479,15 +462,17 @@ 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
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("'>")
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -556,49 +540,26 @@ 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:
raise MoltenException(
"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
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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

Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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,
)

Expand Down
2 changes: 2 additions & 0 deletions rplugin/python3/molten/code_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit b626f8d

Please sign in to comment.