torus

Send text from Vim to an Interpreter

Let's say you have a Vim and a REPL Interpreter – both opened in terminal. When writing code in certain languages, sometimes you may want to just run some expressions occasionally, to figure out if they are valid, or check which value they reduce to, etc. There is a poor man's way to do that: here's how it works:

require("os")

function GetSelectedText()
    -- Get start and end positions of selection
    local start_line = vim.fn.line('v')
    local end_line = vim.fn.line('.')
    local lines = vim.api.nvim_buf_get_lines(0, start_line - 1, end_line, false)
    for i = 1, #lines do
        --local line = string.sub(lines[i], start_col, end_col)
        os.execute("tmux send-keys -t 0:1.1 " .. string.format("'%s'", lines[i]) .. " Enter")
    end
end

-- bind it whatever you want, of course
vim.keymap.set('v', '<leader>t', function()
    GetSelectedText()
end, { noremap = true })

You add it to nvim directory, either as a separate file or as a part of some other lua file that is loaded at the start of nvim (whichever works for you).

The key thing here is the following command:

tmux send-keys -t 1 "(+ 2 3)" Enter

Interpreter/REPL must be running inside a tmux session. In my case, I opened another native terminal split on the right and started tmux there.

Here -t 0:1.1 means to session 0, window 1, pane number 1. As tmux sometimes may run tens of windows and panes, you may want to specify it in the following fashion: session:window.pane. In my case, only one tmux window was running. So the text is going straight to that window. At the same time inside the tmux some interpreter REPL is running.

It takes 10 minutes in total to get ready and it works with: Python REPL, IPython, Scheme (I tested it with Chez), Lua, Haskell GHCi, SWI-Prolog. Of course it works with Bash/zsh scripts - you can send whole loops there and they will work. Sadly as it stands right now it won't work with Perl and Raku, since those use semicolon to terminate and it is not escaped properly. Ocaml's Utop doesn't work either, since you need not one, but two semicolons (crazy French people) to terminate the expression.

Alternatives do exist, of course. Like, for example iron.nvim. It is incomparable in terms of time of setup needed, versatility and just generally the amount of moving parts. For Haskell probably I would (but I don't) use haskell-tools.nvim still, because multiline evals don't work there without proper scoping and you need proper protocols to talk to the GHC kernel.

Bash: Screenshot 2025-11-30 at 04.42.22.png

Scheme: Screenshot 2025-11-30 at 05.01.06.png

Notes: *You can also send text to tty directly, but it wouldn't execute on neither FreeBSD nor MacOS

Thoughts? Leave a comment