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: