babashka

borkdude 2026-01-30T11:32:09.359109Z

A question to linux users. I'm adding support for jline to bb that depends on the new Java FFM feature. But, this only works in the dynamic linux executable, not in the static one (compiled against musl on CI). The static binary has been the default when you install bb with the install script or on brew. I could flip this back to dynamic. The question is: what would be preferable? The jline stuff still works in the static binary but falls back to the "Exec" provider which basically shells out many times to inspect your shell size and then shells out to write something to your terminal. So, TUIs still work, but maybe not in the most performant way. More info: https://github.com/jline/jline3/issues/1566#issuecomment-3819914297 So the choices here are: • we install the dynamic executable again by default, better jline support with the caveat that you might have an incompatible (usually too old?) libc version on your system • we keep installing the static executable, users can install the dynamic one with a flag (easy to do with installer script, also possible in brew? don't know). by default you get a somewhat slower jline experience.

borkdude 2026-01-30T11:32:22.274379Z

cc @rahul080327 @timok

lispyclouds 2026-01-30T11:39:27.021289Z

any way to know how many people dont set the --static flag when installing but expect static always? like alpine users? i for one dont bother about its static or not. as for the choices, im favouring the first one, potential bad perf by default is something i would not expect.

borkdude 2026-01-30T11:41:23.600509Z

on linux the static executable is always chosen, regardless of the static flag. it needs a new --no-static flag to override that

borkdude 2026-01-30T11:41:30.487579Z

or --dynamic or whatever

borkdude 2026-01-30T11:41:47.510099Z

the static executable has been the default now for years

borkdude 2026-01-30T11:42:07.098339Z

via the normal installation methods you don't get to choose a different one

lispyclouds 2026-01-30T11:42:52.537759Z

yeah im saying we could make dynamic the default now but not sure how much breakage is that.

borkdude 2026-01-30T11:44:43.045999Z

tbh I don't see a difference between the execprovider and the ffm provider in practice. the snake game is playable in both

borkdude 2026-01-30T11:44:47.056449Z

(on mac)

lispyclouds 2026-01-30T11:45:31.160839Z

yeah maybe we release it, get some feedback or if there is a way to benchmark

💯 1
lispyclouds 2026-01-30T11:45:47.434139Z

release as it is, static default

borkdude 2026-01-30T11:46:41.208679Z

right. even the file browser in charm.clj is instant (to me) with both versions

borkdude 2026-01-30T11:46:47.292739Z

so indeed, let's just release it as is

lispyclouds 2026-01-30T11:47:24.023759Z

ghostty has a way to measure drawing perf, not sure if that helps, can tinker around later

borkdude 2026-01-30T11:48:04.579289Z

cool. if you want to test the current musl build on linux:

bash <(curl )  --dev-build --dir . 

borkdude 2026-01-30T11:48:25.182579Z

I have ghostty on mac as well.

borkdude 2026-01-30T11:48:28.008819Z

how can I test this?

borkdude 2026-01-30T11:48:47.736529Z

terminal inspector?

lispyclouds 2026-01-30T11:48:54.424439Z

yep

lispyclouds 2026-01-30T11:49:04.360119Z

but not sure what exactly it counts

borkdude 2026-01-30T11:49:25.270089Z

which number in that screen is relevant?

lispyclouds 2026-01-30T11:51:17.485629Z

need to have a look, i vaguely remember something about drawing speeds/refresh rates

cormacc 2026-01-30T11:51:22.042589Z

As a nixos user (don't judge - I know I have control issues), dynamic executables are a problem. So my vote would definitely be for option b -- stick with static by default, and opt-in to dynamic....

lispyclouds 2026-01-30T11:52:54.040319Z

but it could just be measuring ghostty's rendering speeds, not how fast the app produces things

borkdude 2026-01-30T11:53:25.415079Z

thanks for your input @cormacc - appreciated!

👍 1
cormacc 2026-01-30T12:07:55.287499Z

... though thinking it through, it's probably relatively academic for people installing via their distributions package manager -- if making dynamic the default for performance reasons for the majority, just need to make sure the nixpkgs build is updated to use the appropriate flags? Probably good to keep the github binaries static though for distro-agnostic use, or provide static binaries in addition to dynamic ...

timo 2026-01-30T12:09:19.888579Z

is there the possibility to build statically with glibc?

lispyclouds 2026-01-30T12:09:54.979159Z

dont think graalvm supports that

borkdude 2026-01-30T12:11:20.853429Z

indeed, not possible

borkdude 2026-01-30T12:12:14.612949Z

what would work, yould make another alternative to the jline FFM provider that is based on the GraalVM c API. org.graalvm.nativeimage.c.CContext etc. That does work with musl.

timo 2026-01-30T12:13:00.708389Z

this is no alternative?

native-image --static-nolibc

borkdude 2026-01-30T12:13:20.868679Z

that would make the binary static, but still depend on external libc

borkdude 2026-01-30T12:13:46.692709Z

which is the major stumbling block

borkdude 2026-01-30T12:13:57.228179Z

e.g. on nixos as @cormacc said above

timo 2026-01-30T12:14:02.408749Z

alright

borkdude 2026-01-30T12:14:18.885759Z

that option is used for the aarch64 linux binary

james 2026-01-30T12:15:52.120099Z

Maybe static as I am completely used to bb just working. I might appreciate some hint to use the dynamic build if I use something like jline. I don't see static/dynamic in bb describe- it's not technically a feature but it would be useful if it were visible somewhere.

borkdude 2026-01-30T12:16:42.354179Z

you can see this with ldd

james 2026-01-30T12:18:31.056629Z

$ ldd /home/james/.asdf/shims/bb
	not a dynamic executable
Good to know, thanks.

dharrigan 2026-01-30T12:42:37.078979Z

For Arch, it would need to be a new package to support dynamic, as presently it just pulls down the static versions of the packages.

dharrigan 2026-01-30T12:42:57.194459Z

However, nothing to say that Arch can't flip to pull down the dynamic versions, instead of the static versions.

dharrigan 2026-01-30T12:43:20.785589Z

The package depends upon gcc-libs, so it'll get whatever the latest is

borkdude 2026-01-30T13:16:39.874499Z

it seems the jline exec provider is actually pretty good for everything it seems (benchmark written by claude):

JLine Provider Performance Benchmark
=====================================
Platform: Mac OS X
Java: 25.0.2

Operation                    Exec (ms)     FFM (ms)      Speedup
---------------------------------------------------------------
TTY detection                   1,9329       0,0058       335,9x
getSize                         0,0123       0,0021         6,0x
getAttributes                   0,0184       0,0106         1,7x
enterRawMode                    0,1158       0,0483         2,4x
write+flush                     1,4958       1,4709         1,0x
Display.update (full)           0,7969       0,5698         1,4x
Display.update (diff)           0,0144       0,0047         3,0x

borkdude 2026-01-30T13:17:06.358329Z

FFM is overall faster, but the small numbers that exec already has probably don't make a real difference in practice.

borkdude 2026-01-30T13:18:54.156759Z

@timok related to the primeagen video:

⏺ At 60fps, frame budget is ~16.67ms:
  ┌───────────────────┬────────────────────────┬─────────────────┐
  │     Operation     │          Exec          │       FFM       │
  ├───────────────────┼────────────────────────┼─────────────────┤
  │ Full frame render │ 0.8ms = 4.8% of budget │ 0.57ms = 3.4%   │
  ├───────────────────┼────────────────────────┼─────────────────┤
  │ Diff render       │ 0.014ms = 0.08%        │ 0.005ms = 0.03% │
  └───────────────────┴────────────────────────┴─────────────────┘
  Still very comfortable. Even with exec, you're using less than 5% of your frame budget on JLine operations, leaving 95%+ for game logic.

  The real bottleneck at 60fps would likely be the terminal emulator's ability to render that fast, not JLine.

timo 2026-01-30T13:20:43.993509Z

haha, yeah, should be fine i guess

lread 2026-01-30T13:20:46.048389Z

Given that jline works with static, I'd stick with static. Folks can switch to dynamic if they see a need.

👍 2
borkdude 2026-01-30T13:21:39.569899Z

I have convinced the LLM that we basically don't even need the FFM module since exec is always fast enough

borkdude 2026-01-30T13:34:09.492809Z

no wait, better numbers:

Operation                    Exec (ms)     FFM (ms)      Speedup
---------------------------------------------------------------
TTY detection                   1,9446       0,2455         7,9x
getSize                         1,8008       0,0070       257,2x
getAttributes                   2,1393       0,0128       166,6x
enterRawMode                    9,7044       0,1068        90,9x
write+flush                     1,4269       1,4599         1,0x
Display.update (full)           0,6984       0,4805         1,5x
Display.update (diff)           0,0265       0,0046         5,8x

borkdude 2026-01-30T13:34:31.260519Z

so FFM does have an edge over some operations, but those operations usually happen once or are still fast enough for 60pfs

timo 2026-01-30T13:35:40.333849Z

but FFM has other use cases apart from jline right? maybe the benchmark does not show the whole picture?!

borkdude 2026-01-30T13:36:14.473439Z

That crossed my mind too, but couldn't come up with any, do you have one in mind?

borkdude 2026-01-30T13:37:00.974589Z

this is now the benchmark with compiled bb in native-image (previous was running in JVM still):

Exec provider: exec
FFM provider:  ffm

Operation                    Exec (ms)     FFM (ms)      Speedup
---------------------------------------------------------------
TTY detection                   1.3296       0.0141        94.1x
getSize                         1.1657       0.0056       207.1x
getAttributes                   1.6432       0.0054       303.8x
enterRawMode                    7.2588       0.0303       239.8x
write+flush                     0.0185       0.0176         1.1x
Display.update (full)           0.5380       0.5375         1.0x
Display.update (diff)           0.0286       0.0290         1.0x

borkdude 2026-01-30T13:37:27.071309Z

so the writing/updating seems to be equally fast... weird

borkdude 2026-01-30T13:42:17.501339Z

ah it's equally fast because it doesn't need to shell out for that, it works the same in exec / ffm

borkdude 2026-01-30T13:44:27.554659Z

FFM vs Exec. Claude's opinion: For your decision: Case for exec-only: - Works everywhere (musl, glibc, macOS, Windows) - Simpler codebase - one path to maintain - Startup cost (~10ms for raw mode) is imperceptible - Resize cost (~2ms) happens rarely - Rendering performance is identical Case for keeping FFM: - Faster startup (7ms → 0.03ms) - but users won't notice 7ms - Faster resize - but resizes are rare - "Correctness" - direct syscalls vs subprocess - Future-proofing if JLine adds features that need frequent provider calls Honestly, if exec works on Windows too, and the static musl build (your default) can't use FFM anyway... going exec-only simplifies things with no practical downside for users. The only scenario where FFM matters is high-frequency terminal state queries, which well-designed TUI apps (using Display) don't do.

👍 1
🧐 1
borkdude 2026-01-30T13:56:12.552449Z

Aha! Windows does need the FFM provider since exec only works in cygwin/git bash

borkdude 2026-01-30T13:57:36.974669Z

So maybe only include the FFM stuff for windows...?

borkdude 2026-01-30T13:59:36.536559Z

aaah wait, this is the reason why claude code doesn't work in powershell/cmd.exe either and they force you to use git bash for that too

borkdude 2026-01-30T13:59:58.054629Z

which could be something that I prescribe to windows TUI users

timo 2026-01-30T14:01:15.884629Z

is this the only reason jline provides FFM interface? there must be more to it

borkdude 2026-01-30T14:01:39.687609Z

I have asked this to the maintainer, but he doesn't reply

👍 1
borkdude 2026-01-30T14:02:47.484809Z

it is pretty cool that bb TUIs just work in powershell / cmd.exe too

🔥 1
lread 2026-01-30T14:03:21.097909Z

Yes, working in any Windows shell would be cool.

borkdude 2026-01-30T14:04:04.050029Z

ok... I guess .. just the FFM stuff then for everything, but exec for linux (which shouldn't be much of a difference)

borkdude 2026-01-30T14:04:26.659329Z

damn, all those trade-offs ;). the trade-off for including FFM is also binary size, 2mb

borkdude 2026-01-30T14:04:36.056749Z

which is not that big of a deal

lread 2026-01-30T14:04:38.811079Z

Cross-platform scripting, and soon... cross-platform TUI!

🎉 1
borkdude 2026-01-30T14:05:12.915169Z

yeah I guess Anthropic could have adopted bb instead of bun for their stuff, if I was a bit earlier with this :P

borkdude 2026-01-30T14:06:54.682269Z

❯ ah fuck it, cross platform TUI everywhere, with good fallback on linux

⏺ That's the spirit! Best of all worlds:

  - macOS: FFM (native, fast)
  - Linux glibc: FFM (native, fast)
  - Linux musl/static: exec fallback (works fine, Display caches anyway)
  - Windows native: FFM (proper console API support)
  - Windows Git Bash: exec works too

  Users get optimal experience everywhere, with solid fallback on static Linux builds. The benchmark showed the practical difference is minimal anyway since Display is smart about caching.

  Ship it!

lread 2026-01-30T14:10:18.310079Z

timo 2026-01-30T14:20:58.468379Z

- Linux musl/static: exec fallback (works fine, Display caches anyway)
could caching be the source of your ambiguous test results?

borkdude 2026-01-30T14:26:01.634169Z

how so?

timo 2026-01-30T14:26:21.620439Z

no idea, was just wondering because it's mentioned there

borkdude 2026-01-30T14:26:32.136129Z

writing/flushing isn't cached

borkdude 2026-01-30T14:27:03.226859Z

but this all doesn't matter since exec doesn't shell out for this, it works the same way as FFM, you don't really need FFM for this, it's just writing to a stream in both cases

timo 2026-01-30T14:27:14.152299Z

ok, cool

borkdude 2026-01-30T14:27:24.270579Z

it's just for determining size, raw mode and tty detection that you shell out

borkdude 2026-01-30T14:27:58.599699Z

and you usually need to determine the size of the window on each render, since the user could have re-sized. but there is a terminal signal for this, so until you receive that, you can cache the size

borkdude 2026-01-30T14:28:04.984959Z

all this cleverness is in jline

👍 1
seancorfield 2026-01-30T14:56:00.259999Z

A bit late to this discussion but I just want to express concern that bb might get updated to something that doesn't work on older Linux flavors (Ubuntu 20, CentOS 7 -- what we're stuck with at work). As long as bb continues to work on those older versions by default, I have no opinion on TUI stuff because it would not be of any interest to us. To me, jline/TUI stuff isn't useful for a lot of scripting that bb is used for. It's a nice to have for some users. Am I misunderstanding?

borkdude 2026-01-30T15:04:14.717199Z

@seancorfield The TUI stuff is something that bb is already used for, but needs external programs installed like gum or others. Adding jline just makes things easier (and more performant) to create these (and will e.g. also improve the console REPL experience: no more rlwrap needed). We chose the static binary to make it work on virtually every x64 linux since it doesn't depend on any external glibc and this static binary will stay around as long as possible. The discussion was just about what should be the default installed version (which has been static for years now). During this conversation I discovered that the fallback Jline provider (exec) works almost equally well on linux as the more optimal one (FFM which doesn't work in a static binary). So for linux static there isn't a real problem and no reason to change anything. Bottom line: it'll stay the same way as before, just with more features to build TUIs.

👍 1
👍🏻 1
lread 2026-01-30T16:00:38.492299Z

And even if bb TUI (via jline) did not work on some terminal/OS, it is opt-in by actually calling it from your code.

lread 2026-01-30T19:14:19.918039Z

^ update: my statement isn't true for REPL, which will have rlwrap behaviour built-in https://clojurians.slack.com/archives/CLX41ASCS/p1769792315711259

borkdude 2026-01-30T16:58:35.711259Z

I've re-implemented the babashka console REPL using jline, so you don't need rlwrap anymore. Q: the history file with rlwrap used to be at ~/.bb_history. Maybe it would be nicer if we stored the history by project, maybe? Does nREPL does this? rebel-readline?

dharrigan 2026-01-30T16:59:35.623669Z

rebel-readline creates a .rebel_readline_history file

dharrigan 2026-01-30T17:00:25.034469Z

looks to be: <millis since epoch>:<command>

dharrigan 2026-01-30T17:00:41.607629Z

i.e.,

dharrigan 2026-01-30T17:00:46.521159Z

1762770286750:(:a foo)
1762770291068:(:b foo)
1762770292839:(:b foo [])
1762770381515:(:b foo {:til "w00t"})

borkdude 2026-01-30T17:02:02.276979Z

that's jline's history thing which I'm also using:

1769792484250:1
1769792484622:2

👍 1
borkdude 2026-01-30T17:02:45.442769Z

is rebel readline always just doing this in the cwd and would this be desirable for bb?

dharrigan 2026-01-30T17:03:07.820329Z

I often use history for going back to commands in jrebel, like ctrl+r

borkdude 2026-01-30T17:03:58.665529Z

that's a shell feature, not a rebel readline feature right

borkdude 2026-01-30T17:04:33.701669Z

or maybe it is a jline feature in this case

borkdude 2026-01-30T17:04:42.471349Z

it does work, but it doesn't suggest anything not from this history

seancorfield 2026-01-30T17:04:43.910319Z

It looks like clj (which uses rlwrap) puts the history in ~/.clojure_history?

borkdude 2026-01-30T17:04:54.503089Z

rlwrap does that

borkdude 2026-01-30T17:04:59.840259Z

<cmd>_history

seancorfield 2026-01-30T17:05:19.508599Z

I'm on the fence. Sometimes I'd prefer per-project history, sometimes I'd prefer global history. /unhelpful 🙂

borkdude 2026-01-30T17:05:32.472519Z

I could just continue doing what bb and clj always did for now

borkdude 2026-01-30T17:05:47.206589Z

I'll save it to HOME/.bb_repl_history

borkdude 2026-01-30T17:06:00.773899Z

to not conflict with the bb_history file

borkdude 2026-01-30T17:06:12.613939Z

(which already happened to me and jline then decided to reformat it)

dharrigan 2026-01-30T17:07:01.948709Z

I'm in the per-project camp 🙂

seancorfield 2026-01-30T17:08:34.812519Z

I lean slightly toward per-project history. Perhaps because I have a ~/clojure folder I use as a general scratch area and don't want that "project" history to interfere with my work project history. But it's a very mild preference.

borkdude 2026-01-30T17:09:44.590939Z

One concern is that bb can be invoked from non-project directories and what makes a project (e.g. bb.edn in the current dir?) can be up for interpretation. Also you can have this ambiguous situation:

bb --config other-dir/bb.edn repl

exitsandman 2026-01-30T17:13:48.390029Z

That ambiguity alone would make me consider the path of the edn file itself as the definition of a "project" over anything else.

borkdude 2026-01-30T17:15:11.365159Z

yeah I was thinking the same

borkdude 2026-01-30T17:15:25.146749Z

I always kinda hate tools that write local files to my projects, that's one argument against

exitsandman 2026-01-30T17:16:21.318379Z

Re: what to do with projectless, what would stop one from having a default history?

borkdude 2026-01-30T17:18:48.659809Z

I'll stay on the current behavior and park this for a later time, but at least now it's under bb's control :)

seancorfield 2026-01-30T17:25:10.428259Z

Interesting. That is a pretty compelling argument. My "gut" says that if bb.edn is used, the history should go in the directory with bb.edn, wherever that is, else in $HOME. But that's a potentially complex/confusing approach, whereas always using $HOME is both simple and easy to understand.

Bob B 2026-01-30T17:58:36.263669Z

Apologies for the late-ish and not overly helpful comment, but I very much agree with the local files dislike (especially for things like history) - really irks me. And I kind of feel like I'd rather be able to get history across projects - filtering history down is probably easier than aggregating dispersed history files.

👍 1
lread 2026-01-30T18:48:02.132519Z

Is there a possibility of jline being problematic on some terminals? Would there need to be an option to turn off jline-rlwrap support?

borkdude 2026-01-30T19:03:53.672599Z

Without rlwrap the console REPL is barely usable (left/right arrow won't work). rlwrap works. the jline stuff makes rlwrap obsolete. It should work everywhere.

borkdude 2026-01-30T19:04:11.683089Z

I'm going to merge the REPL improvements and people can test the dev build

borkdude 2026-01-30T19:05:25.511589Z

The next step will be adding auto-completions etc to the console REPL

borkdude 2026-01-30T19:06:20.258929Z

If people report errors, I'll make a flag to revert to the old console REPL (which is still there, it's used when you pipe input to bb's console REPL)

borkdude 2026-01-30T19:07:03.620719Z

I tested this on Windows already, works well in pwsh, cmd.exe, cygwin, etc. Mac also tested

lread 2026-01-30T19:09:02.209119Z

Very exciting, @borkdude!

seancorfield 2026-01-30T19:09:50.428389Z

Looking forward to testing this on Ubuntu 20.04 🙂

Bob B 2026-01-30T19:17:44.212259Z

> Ubuntu 20.04 ... and I thought my machine was on an old version 😏

borkdude 2026-01-30T19:18:21.951129Z

@seancorfield you're already using bb on that system right? I'll notify you when you can test the new REPL

seancorfield 2026-01-30T19:18:52.050709Z

I have 22 and 24 installed (WSL on Windows) but haven't gotten around to fully setting them up and switching my big ol' work project to either of those newer versions.

seancorfield 2026-01-30T19:19:18.768609Z

@borkdude Yup. bb is used by "most" of the projects I run on that old Ubuntu at this point.

seancorfield 2026-01-30T19:20:02.381749Z

Once latest updates to the new version of bb, I can easily test it on CentOS 7 on our QA servers too.

lread 2026-01-30T19:23:37.348399Z

I remember it was not that long ago that you weren't so sure about this bb thing, Sean! It's so nice to see that you are enjoying bb as much as I am!

seancorfield 2026-01-30T19:27:45.683349Z

A year or so back, we'd talked about it at work, but the consensus then was that we didn't want to introduce a new dependency on our QA/production systems. So I'd also been hesitant to introduce it as a requirement in my OSS projects. But now:

> find oss workspace -name bb.edn
oss/next-jdbc/bb.edn
oss/durable-queue/bb.edn
oss/polylith/bb.edn
oss/slingshot/bb.edn
oss/honeysql/bb.edn
workspace/wsmain/bb.edn
That last one is work. And the tipping point there was New Relic breaking our old deployment recording machinery and requiring a new CLI tool to be installed, at which point I figured "Hey, if I need the newrelic CLI installed, why don't I also install bb?" 🙂

2
borkdude 2026-01-30T20:36:41.317979Z

The new console REPL is merged. You can test it with:

bash <(curl )  --dev-build --dir .
(this download also works in Git bash on Windows) This will download the dev bb to your current directory. Try ./bb and see if you can type expression, up arrow, left arrow, etc should work, without rlwrap. Play around and see if anything obvious is broken. Next I will add: • multiline expression history and editing • completions Those aren't difficult to add, but maybe good to test this first version

🔥 4
seancorfield 2026-01-30T20:41:35.982009Z

Basic stuff seems to work on Ubuntu 20.04.

🎉 1
lread 2026-01-30T20:42:43.900609Z

And on MX Linux 25!

🎉 1
seancorfield 2026-01-30T20:43:26.236489Z

And on CentOS 7 on one of our QA servers (I did a manual install into a new folder to test).

🎉 1
lread 2026-01-30T20:56:35.188809Z

And on Windows 10 Powershell and CMD prompt. (Had to figure out how to turn off VirtualBox's grabbing of Ctrl-C first!) On my Windows VM, I hear an error chime when I try to up arrow past start of history or down arrow past end of history.

🎉 1
lispyclouds 2026-01-30T21:00:26.258319Z

Looks fine on latest Fedora with latest kernel 6.18.8 too

🎉 1
2026-01-30T21:22:20.631479Z

Looking good on macOS Tahoe 26.2

dharrigan 2026-01-30T21:24:06.186209Z

Works on Arch Linux.

Bob B 2026-01-30T21:24:17.062469Z

the basics work on Ubuntu(ish) 24.04 - a thing that (unsurprisingly) doesn't work is opening the current command in an editor 🙂

borkdude 2026-01-30T21:26:13.845289Z

what's that?

borkdude 2026-01-30T21:27:57.358239Z

I mean: current command?

seancorfield 2026-01-30T21:41:02.148419Z

Something to consider: if you enter a partial expression in Rebel Readline and press enter, you get this (`|` is the cursor):

[Rebel readline] Type :repl/help for online help info
user=> (* 1 2 3
  #_=>    |
but if you do the same thing in the new bb, you get this:
user=> (* 1 2 3
   |
so it is a lot less obvious that it is waiting for input.

borkdude 2026-01-30T21:46:27.393739Z

I'm working on that. It's called multi-line input

👍🏻 1
borkdude 2026-01-30T21:46:35.264049Z

it will also work with the up-arrow

Bob B 2026-01-30T21:56:01.377369Z

The "current command in editor" thing is a readline-ish mechanism where you can do something like <C-x><C-e>, and it opens your edtior with a temp file containg the current content of whatever's in the line. You can edit the line as desired, and then save and exit your editor, and the thing that uses readline (e.g. bash) treats the file content as though it was input at the prompt. It's not unlike if you do a git commit at the CLI without a message and it opens the editor. JLine has the <C-x><C-e> binding (it would appear), but throws when it's invoked. It probably shouldn't be a priority at all, but I was just toying around; sometimes multi-line editing is nicer to work with in an editor.

Bob B 2026-01-30T22:10:43.588739Z

would you like issues/discussions for things that are like "nice to have" or "beyond the basics", so they're written down but they don't need to be at the forefront of anyone's mind?

seancorfield 2026-01-30T22:22:34.908269Z

@highpressurecarsalesm I just tried that in Rebel Readline and it is bound to "eval current expr", i.e., at cursor.

borkdude 2026-01-30T22:23:00.597139Z

C-x C-e is an emacs thing for evaluate

seancorfield 2026-01-30T22:23:14.352459Z

Ah, that explains why Rebel went that way then...

borkdude 2026-01-30T22:23:15.512479Z

yeah sure, nice to haves a are good to write down in a Github discussion

Bob B 2026-01-30T22:23:29.256209Z

ahh... so there's a bind conflict there to be worked out

seancorfield 2026-01-30T22:24:47.921859Z

C-x C-d (doc) is the thing I use most in Rebel, followed by C-x C-s (source) but mostly I just navigate around and edit. C-x C-e for eval is kinda cool tho' TIL!

seancorfield 2026-01-30T22:28:13.474219Z

I hadn't really dug into the key bindings in Rebel... lots of cool stuff there... but unclear how much is Rebel vs plain JLine?

seancorfield 2026-01-30T22:28:51.712469Z

Ooh, the incremental backward search works in the new bb... nice!

borkdude 2026-01-30T22:32:21.441999Z

rebel uses jline

borkdude 2026-01-30T22:32:31.490799Z

so in theory I could turn the bb console repl into something like rebel

borkdude 2026-01-30T23:33:35.941839Z

I merged multi-line support. Wait 10 minutes from now and then re-install the dev build. You should be able to enter multi-line expressions and press up arrow to retrieve it back, also you can navigate in the lines to edit the expression. Intentionally I did not print

#_=>
before each multi-line like rebel does, because I kinda dislike those when copy-pasting expressions. I could add it and do it the same as rebel though. Let me know what you want. I'm AFK now getting some needed sleep!

seancorfield 2026-01-30T23:38:14.993549Z

Heh, that prompt is exactly what I like about Rebel because it makes clear it is waiting for more input 🙂

borkdude 2026-01-30T23:38:53.777659Z

ok, I can add it tomorrow, looking forward to what you all have said when I return

borkdude 2026-01-30T23:50:22.386869Z

it should be there now

Bob B 2026-01-31T06:55:28.387239Z

I experimented with adding classes to see if it'd be possible to run rebel using bb, and I ended up running up against proxy-super not being found - presumably a difference in how proxy works (can work?) in the native-image context.

borkdude 2026-01-31T09:25:07.134659Z

rebel-readline's code is a bit hacky, it also contains references to .impl classes which are not public API

borkdude 2026-01-31T10:56:37.429109Z

I changed the promptto #_=> now like rebel-readline for multiline stuff

borkdude 2026-01-31T10:57:16.837639Z

I think showing docs would be nice and completions. Not sure about colored output and indentation, two other things rebel-readline provides. I'll focus on completions first

borkdude 2026-01-31T10:58:06.956529Z

Oh I guess we're on par with leiningen now also REPL-wise:

user=> (+
  #_=> 1
  #_=> 2
  #_=> 3)
6

borkdude 2026-01-31T10:59:03.562779Z

I guess lein is also using jline

borkdude 2026-01-31T11:37:12.631829Z

wow nice

🎉 1
seancorfield 2026-01-31T16:19:26.814899Z

That is really nice @borkdude! Just updated my local dev copy to play with. Love it! (press tab to get completions, for anyone not sure how that works)

seancorfield 2026-01-31T16:20:44.154589Z

My personal priority for features would be C-x C-d for docs, C-x C-e for eval at cursor, C-x C-s for source, indentation, code-coloring 🙂 But it is super-usable already at this point!

Bob B 2026-01-31T16:46:18.639029Z

a builtin keybind that I like for building stuff up is alt-a, which accepts the current line and keeps it as the next line

seancorfield 2026-01-31T17:22:15.609539Z

TIL! Wow, that's neat!

borkdude 2026-01-31T17:22:42.415049Z

on my mac alt-a is å.... how do I turn that off? ;)

borkdude 2026-01-31T17:34:46.738979Z

pushed a couple more improvements for class completions, e.g.:

String -> String/.length, String/new

Bob B 2026-01-31T17:51:23.543899Z

I don't know macos very well, but the accented-a thing is (I think) an OS-level keyboard setting. I think that is default behavior on an "international" keyboard layout. It should be possible to turn on something like "option sends meta" in either your terminal emulator settings and/or OS-level keyboard settings. I think it's also possible to change the behavior of only the left or right, so if you use the mechanism to enter other accents/diacritics, you might be able to have access to both capabilities.

Bob B 2026-01-31T17:52:51.136859Z

... with that said, emacs-y keybinds might make that obsolete in short order, so 🤷

borkdude 2026-01-31T17:57:21.264779Z

ok, I now configured left option as esc+ and when I do:

user=> (+ 1 2 3)<alt-a>
6
user=> (+ 1 2 3)
I see this, does that make sense?

Bob B 2026-01-31T17:58:51.736669Z

yeah - since I sometimes end up wanting to build things up (like tacking add'l fns on the end of a threading macro), that's just a tiny bit nicer than "enter, up"

borkdude 2026-01-31T17:59:24.336919Z

ah you mean with multi line stuff?

👍 1
borkdude 2026-01-30T17:14:28.888299Z

Console REPL improvement inspired by Node.js: • Input + ctrl-c ignores the input and yields next prompt • ctrl-c on empty input yields warning: next ctrl-c quits the REPL

$ clojure -M:babashka/dev
Babashka v1.12.215-SNAPSHOT REPL.
Use :repl/quit or :repl/exit to quit the REPL.
Clojure rocks, Bash reaches.

user=>
(To exit, press Ctrl+C again or Ctrl+D or type :repl/quit)
user=>

💯 2
🆒 1