Neovim and REPLs
Last update: 01/20/2025
Back to home
Back to Posts
This is about sending code that you're editing in a buffer to another process running a REPL (interactive program) for the programming language you're working with. Hopefully, this should help put things in perspective.
My goal is to try to understand how the plugins go about doing their thing.
Disclaimer
I've used vim-slime in the past for some Python coding but am currently using Conjure. I've yet to use Conjure for Clojure coding. I've also submitted some PRs for tiny improvements to Python coding with Conjure. They take advantage of the Tree-sitter support in Neovim.
Various Plugins
There are Vim plugins that help with the goal of sending code to a REPL.
Plugin | Implementation | IPC Mechanism |
---|---|---|
Conjure | Fennel, Lua | uv.spawn(), uv.write() |
iron.nvim | Lua | termopen(), chansend() Uses bracketed paste mode when sending Python code. |
vim-fireplace | Vimscript, Python | jobstart({cmd} ), chansend() where {cmd} is something like ['python', '.../pythonx/fireplace.py', 'nrepl://127.0.0.1:7888'] |
vim-slime | Vimscript | :sp term://{cmd} , chansend() |
vlime | Vimscript | termopen(), chansend() |
neoterm | Vimscript | termopen(), chansend() |
vimcmdline | Vimscript | termopen(), chansend() |
vim-simpl | Vimscript | :execute "term {cmd}" opens {cmd} in a terminal buffer |
Sending Code to a Sub-process
These are the facilities in Neovim that let one send stuff to a child process
spawned by the main Neovim process. For more information about the IPC
Mechanism, see the Neovim help (:help <topic>
; for example: :he luv
).
IPC Mechanism | Create Sub-process | Send To Sub-process | Read From Sub-process |
---|---|---|---|
luv | uv.spawn() (Lua ) |
uv.write() |
Via callback on handle s for stdout and stderr. |
terminal-emulator | termopen() (Vimscript ) |
chansend() |
Via callbacks: on_stdout only (see :he jobstart-options ). |
terminal-emulator | :sp term://{cmd} (Command-line mode ) |
chansend() |
Not available |
job-control | jobstart() (Vimscript ) |
chansend() |
Via callbacks: on_stdout and on_stderr . |
About the Terminal-Emulator
Here are some ways to start a terminal emulator sub-process:
:sp term://{cmd}
or:edit term://{cmd}
or:execute "term {cmd}"
where{cmd}
is an interactive program like bash or python.termopen()
The difference between the two is how they are typically used. The first is
generally invoked in command-line mode for interaction with {cmd}
in a split
window or in the current window.
termopen()
returns the job-id on success so it is useful programmatically. You
can send data to the program running and connected to a terminal buffer using
chansend(job-id, data)
.
While termopen()
and jobstart()
take the same arguments, termopen()
is
more specialized than jobstart()
. termopen()
automatically sets the pty
option of the jobstart-options and connects to a terminal buffer. Also, the
output of the program (cmd
) running in the terminal-emulator is only available
via stdout (as a combination of stdout and stderr).