Stream: ideas

Topic: REPL history


view this post on Zulip Hristo (Mar 16 2024 at 13:32):

I haven't been able to find a related discussion here, although I strongly suspect there may have been multiple already.

When using the REPL, I've found myself frequently having to re-run it multiple times, after an unexpected crash. Every time, I have to resort to copy-and-pasting the lines of code which I'm interested in from a file, because that history doesn't seem to get stored in any way (I have to admit I haven't checked thoroughly that part of the codebase yet; so this observation is predominantly from a user's perspective).

I wouldn't want to propose more than a minimalistic approach (so, I'm not discussing anything SQL-based in this original post), so I was thinking, would the following be OK (i.e., not too simplistic):
Whilst the REPL is running, we keep track of a sliding windows of the last N (as an upper bound) "commands" in memory and dump those to a cache file upon exiting the REPL. Then that file gets parsed and the (maximum of) N commands get loaded as history that's possible to navigate via the arrow keys (and as a bonus - searchable via Ctrl+R/Cmd+R).

Some reasonable value of N itself could be set as a default, and optionally configurable by the user via a command-line argument.

view this post on Zulip Richard Feldman (Mar 16 2024 at 14:26):

I like that idea!

view this post on Zulip Hristo (Mar 17 2024 at 11:15):

https://github.com/roc-lang/roc/pull/6593 :pray: (obviously, not an urgent review request)

view this post on Zulip Kevin Gillette (Mar 17 2024 at 13:41):

Something I'd request (at least long term): history be based on "outer expressions" when in an outer expression context, rather than history based on individual lines. For example, it'd be preferable to allow pulling in a 10 line function from history all at once, rather than needing to reconstruct that function from 10 separate line-based history fetches.

Python repl history handling is line based, and it's quite tedious for anything non-trivial.

view this post on Zulip Hristo (Mar 17 2024 at 13:54):

@Kevin Gillette, my apologies for having not provided sufficient context from my PR.

tl;dr Yes, indeed that's how it will work, as per the proposed PR.

More details

Yes, that's definitely what I had in mind when I wrote my original message yesterday. I was thinking about what kind of sentinels would be best used to represent these kinds of "command breaks" (as opposed to actual line breaks), and the parallel in my mind was exactly Python's REPL (and ipython, which is able to handle multi-line "commands").

In terms of the context which I didn't copy from the PR here: when I wrote my original message, I hadn't looked at the corresponding parts of the codebase in sufficient detail. When I did do it, I realised that rustyline's history loading and saving capabilities could be utilised to enable preserving Roc REPL history across sessions (e.g., in the event of a REPL crash). rustiline is already capable of doing all associated heavy-lifting, but this particular class of features (loading/saving history) hasn't been utilised in the Roc REPL yet (whilst rustyline itself is an existing dependency, so no new dependencies are introduced in the PR).

view this post on Zulip Kevin Gillette (Mar 17 2024 at 13:58):

awesome, thanks for the clarification, and the work on supporting this!


Last updated: Jun 16 2026 at 16:19 UTC