Russ Tokuyama

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 handles 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).