REPLs with rlwrap, and sending code to be evaluated by REPLs

I’ve been wanting to try and get somewhat similar behaviour of REPLs like Emacs does with SLIME/Sly where you

  • have history of your input (some REPLs need to be wrapped with rlwrap to have this)

  • can send a selection (called a region in Emacs) to the REPL and have it be evaluated

alexherbo’s connect.kak allows me use, say, rlwrap guile just fine. I wish I could have it displayed horizontal to the Kakoune session instead of vertically, but that’s not really a big deal.

Thing is though I’m not sure how to pipe a selection to a currently running REPL. I know connect.kak has the send command, but will that actually work how I think it would?

There are probably other things that will come up with this (like having the REPL to run in your project directory instead of just in $HOME, and possibly making sure it loads in your projects dependencies so you don’t have to do that manually), but baby steps.

Kakoune comes with some REPL plugins in rc/windowing/repl. Currently only kitty, tmux and X11 are supported, and the X11 plugin makes some extra assumptions so it’s not quite as reliable as the others. Nevertheless, they all define the same aliases:

  • :repl CMD will run CMD (which can include arguments) in a new window (much like :new will run Kakoune in a new window)
  • :send-text will type the contents of the current selection into the REPL window

For your use-case, I guess you want to open the REPL window with :repl rlwrap guile, and map some useful key-sequence to :send-text.

Running :repl rlwrap guile

1:1 'repl' wrong argument count

Just :repl guile works so repl can only take 1 argument.

How sad. Does :repl 'rlwrap guile' work?

I guess you could always just put rlwrap guile into a script, and execute that with:repl.

Hmmm, well putting it all in quotes works.

Should it do that?

You can try it. Nothing will break.


I think there’s a desperate need for good repl integration plugin for Kakoune, that will allow not only sending text to repl, but communicating with the REPL process in both ways. Unfortunately all repls work differently, which means we’ll have to do something what Geiser does.

I made a plugin for this a while back, it’s not very polished yet, but it may work for you.

can you briefly describe it’s advantages over built-in REPL support? I see that it populates " register with result, which in my practice is rarely needed feature. Are there another features? Don’t think that I discourage your work, it’s great that you’ve made it, I just want a bit of clarification :slight_smile:

I never got the built-in repl support working, but I will try again to see the differences.
One difference at least is that my plugin can run in the background, so no window is needed.
I often use it to send calculations through python and obtain the results in-place while also keeping state in the python repl.
So I think the biggest difference is that my plugin is 2-way instead of 1-way

Cool, one more question - can I request autocompletion or docstrings from REPL with your plugin to feed those to Kakoune’s completion/info system?

This also got me thinking about a plugin that will allow running tasks from kakoune and managing PIDs of those tasks within Kakoune. We kinda do this with make or ctags but those terminate automatically.

I don’t see anything about completion in the docs of replwrap so I think it’s going to be hard to implement that.
Also, I have no idea if it is possible to somehow trigger completions by sending a tab character, would be cool if that was possible.

I never got the built-in repl support working

This was due to a problem with termite, I switched to alacritty and it’s working now, but indeed, it’s only one-way.

Usually one-way repl is not a problem for me, because I have a working application, that REPL is connected to, so I evaluate things directly from my editor and see the cchanges reflecct working application. IIUC your primary use is to quickly use language facilities to produce some kind of calculations when you’re editing code, e.g. you want to replace some expression with it’s result without doing it with your brainpower, because it might need to gather environment information.

I believe it’s not done that way. Usually some kind of request sent to the REPL via protocol that this REPL supports. It’s more like a language server protocol thing.

IIUC your primary use is to quickly use language facilities to produce some kind of calculations when you’re editing code, e.g. you want to replace some expression with it’s result without doing it with your brainpower, because it might need to gather environment information.

Exactly, sometimes I need to do the sine or cosine or square root of something.
Something else I use it for frequently is incrementing numbers or rounding them to a certain number of decimals.
Another use case is defining a function to do something and sending it to the python environment, then later execution that function on every selection, etc.

Yea. Probably have to write some Scheme code that can find the program that’s “attached” (so to speak) to Kakoune.

In my little experience with it, the thing that bugged me with Geiser was that it asked what Scheme dialect you were using for every. single. file. So if you had a project that had multiple .scm files, every time you opened one you’d have to tell Geiser if you were using Guile, Chicken, Gambit, Chibi, MIT, Chez, or Racket (even though Racket has it’s own file type). Generally, that’s wasn’t a problem if you used 1 dialect of Scheme and had the corresponding symbol to some Geiser specific variable. Racket for Emacs also has it’s own mode.

I’d generally only find myself using Guile, Chicken, or Racket personally.


Chicken Scheme does have this nrepl egg (eggs are Chicken Scheme’s distributed modules).

Hmmm, well from looking at the page for the above egg and the short “Using the interpreter” page and “Writing Portable Scripts”, you’d have to make some script like so:

#! /usr/bin/env sh
exec csi -s "$0" "$@"

(use nrepl)
;; I thought I had a solution but in actuality I didn't.
;; at some point you'd have to do something like `(eval (read))` to just
;; get basic REPL like functionality

I suppose. You can run that script with say rlwrap chick-repl or something. Then you at least have a port you know that…maybe Kakoune could listen on as well? That’s a start…maybe?

You can also just do rlwrap csi -:c.