Stream: ideas

Topic: Repl save history feature


view this post on Zulip Nicholas Cahill (Feb 27 2022 at 02:52):

So I took a stab at implementing this with rustyline's builtin history dump feature, but it was pointed out that we should probably spend some time talking about the design first. https://github.com/rtfeldman/roc/issues/2510

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 02:57):

Also might be a good time to talk about the repl command parser architecture a bit, since this is the first command that takes an argument!

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:10):

very cool idea!

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:11):

so one thought that comes immediately to mind: what if we just saved it automatically, instead of having a command?

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:11):

like you bring up the repl again and press up, and it just remembers what was there the last time you used the repl?

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:18):

A persistent history would also be great yeah. It might be convenient to keep a 'dump session' feature on top of that so people don't have to slice and dice their whole repl scrollback and that file can stay someplace relatively out-of-the-way

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:19):

hm, so what would the use case for that be? :thinking:

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:19):

I've never used a feature like that in a repl! :big_smile:

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:27):

I use repls as a drafting table pretty often, but I think it's fair that that's not a feature most people expect from a repl, although it's unclear if they don't expect it because it's not well-implemented or because it's not a part of their workflow (or maybe it's a chicken-and-egg thing.)

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:27):

interesting! I'm curious what your workflow looks like

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:27):

is it a per-project thing?

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:31):

I move around from project to project a lot so I'm often working on code I don't own, robust repls and debuggers make my life much easier

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:33):

Actually my hackathon and CTF workflow benefits a lot from that too. Tough to beat notebooks for that kind of draft-test-iterate workflow but repls can be pretty close

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:33):

cool, so let's say you have like 5 different projects in 5 different folders on your machine

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:34):

and let's say you're working on one of those projects right now

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:34):

and let's also say that (somehow) when you brought up the repl in that project, it just automatically remembered your command history from the last time you brought it up in this project

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:35):

at that point, would you still use a dump/restore session feature, within the bounds of that project alone?

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:40):

I think I would; but I feel like the real question is, if I draft something complicated in the repl and I'm happy with it, how can I easily get it into my project?

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:41):

ahh gotcha! so in that use case, it's not so much about the command history as the code?

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:41):

Yes exactly

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:41):

ok I understand

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:41):

so what if we separated the two features?

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:42):

does that seem like a reasonable design direction?

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:42):

for the way you use repls

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:42):

Yeah absolutely

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:44):

ok cool! so for exporting the code, there's a bit of groundwork we need in the repl first

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:44):

because right now, it doesn't really "remember" anything :sweat_smile:

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:44):

like if you enter an expression, it evaluates it, prints the result, and then forgets all about it

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:45):

(this is not the long-term design, it's just that we've never taught it to do anything else!)

view this post on Zulip Ayaz Hafiz (Feb 27 2022 at 03:45):

(For context, this use case is the reason I filed the issue initially. I have the same workflow and I think it works best in notebooks, but those are heavy weight and don’t work for every language, so it’s nice if a repl supports it.)

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:45):

so because of the way Roc expressions work, you can do this in the repl:

x = 5

x + 1

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:45):

because that's one expression in Roc

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:46):

but once I've entered that one expression, the repl has forgotten all about x

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:46):

so I need to redefine it from scratch again in a fresh expression if I want to use it again

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:46):

similarly, we also don't have a way to refer to previous repl executions

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:47):

Right. It saves your input, but not any of the state from prior commands being executed

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:47):

yeah

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:47):

which it totally should! It just doesn't yet.

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:47):

I've used other repls that also generate some automatic name for expressions you enter

view this post on Zulip Ayaz Hafiz (Feb 27 2022 at 03:47):

I filed a related issue around that topic too, in case it is of any use: https://github.com/rtfeldman/roc/issues/2509

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:47):

like if I just put in 5 + 5 it might generate the name repl1 for that (and print it out along with the answer)

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:48):

so I can refer to it later without having to enter it again

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:48):

I think that would also be a nice feature, and generating names that are conducive to export seems like a good thing to keep in mind for it

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:49):

e.g. I know some languages will name previous values things with special repl-only characters (like automatically generating the name $1 instead of repl1)

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:50):

that avoids potential namespace collisions, but it makes it harder to export them to a file, because if I enter $1 + 5 and then export that to a file later, that won't make sense in a normal .roc file

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:50):

(as opposed to like repl1 + 5

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:50):

)

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:50):

:thinking: one way to avoid the namespace issue might be to put the auto-generated names in an auto-generated module like Repl

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:50):

so maybe you write Repl.v1 for the first value the repl printed out

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:51):

and then when you export it, it puts all those declarations into a file

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:53):

That would be really nice with some refactoring/renaming features

view this post on Zulip Ayaz Hafiz (Feb 27 2022 at 03:54):

I think being a little imperfect is okay, what is written in a repl is usually drafty/prototypey and would likely require manual cleanup anyway

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:55):

Yeah that's part of why I felt confident to just charge ahead with the rustyline builtin hahah

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:55):

yeah, although I think rustyline only knows about inputs and not declarations :big_smile:

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:55):

so we need something like https://github.com/rtfeldman/roc/issues/2509 to get the actual export

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:55):

but!

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:55):

rustyline can totally be used to preserve input history

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:56):

for that, I was thinking now might be the time to start storing local per-project caches, which we'll want later for incremental compilation anyway

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 03:56):

Yes. It's literally just dumping what you typed into a file, whether it was parsed successfully or not.

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:56):

specifically I was thinking of introducing a .roc-cache folder

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:57):

the folder structure would be:

.roc-cache/version-number-or-git-commit-sha-of-compiler/datafile-goes-here

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:58):

so if you're building from source on commit 1aec997843764c44f6774a8a39d34be775f7ab2f, and you start using the repl, every time you enter an expression, it would write to .roc-cache/1aec997843764c44f6774a8a39d34be775f7ab2f/repl-history.dat

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:58):

and then whenever you bring up a new repl, it would look for that file

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:59):

actually I could also see an argument for the repl history existing outside the compiler version :thinking:

view this post on Zulip Richard Feldman (Feb 27 2022 at 03:59):

like the compiler versioning makes sense because otherwise it might have stale compilation artifacts that aren't compatible between versions (and might even cause bugs)

view this post on Zulip Richard Feldman (Feb 27 2022 at 04:00):

but maybe for the repl it's just best to keep all the raw inputs even if you're (for example) upgrading compiler versions

view this post on Zulip Richard Feldman (Feb 27 2022 at 04:00):

because most of them will probably still make sense, and be useful, after the upgrade

view this post on Zulip Richard Feldman (Feb 27 2022 at 04:00):

thoughts?

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 04:01):

Agree; I wouldn't want my history wiped on an update in normal circumstances

view this post on Zulip Richard Feldman (Feb 27 2022 at 04:01):

ok cool! so then .roc-cache/repl-history.dat

view this post on Zulip Richard Feldman (Feb 27 2022 at 04:01):

as a subdirectory of the current working directory where you opened the repl

view this post on Zulip Richard Feldman (Feb 27 2022 at 04:02):

does that seem like a good design?

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 04:02):

Sounds good to me!

view this post on Zulip Richard Feldman (Feb 27 2022 at 04:03):

awesome! let's give others some time to weigh in (like 24 hours let's say) so we get some more perspectives before proceeding, but I'm really liking this direction! :smiley:

view this post on Zulip Ayaz Hafiz (Feb 27 2022 at 04:27):

I like the per-project repl history!

view this post on Zulip Ayaz Hafiz (Feb 27 2022 at 04:28):

Two suggestions:

view this post on Zulip Ayaz Hafiz (Feb 27 2022 at 04:29):

Could we also persist the history in a global history file? So if I'm in "directory A", the history of the repl for my current session will be saved to a file in .roc-cache there, but also be written through to a global repl history file. The reason for this is so that I can have a global view of all repl history, without having to necessarily remember what directory I came from.

view this post on Zulip Ayaz Hafiz (Feb 27 2022 at 04:33):

The second is could we still have a method to save the current session state to a file? I think there is still value to this, in at least that

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 04:34):

I think that's kind of another question; should the repl be contextual or should it be like a shell, where your command history is global? Like if I just fire up a shell to test something while I'm in a meeting or something, I might still expect to see those commands when I start a repl elsewhere

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 04:36):

But I definitely still think a dump-session-history-to-file command is a good idea

view this post on Zulip Ayaz Hafiz (Feb 27 2022 at 04:36):

We could prioritize contextual and fallback on the global history, that way you don't have to go hunting if you forget what directory you were in, but if you do remember, you can "continue where you left off"

view this post on Zulip Nicholas Cahill (Feb 27 2022 at 04:39):

I also definitely think a user should never need to know what/where that history file is in order to accomplish what they want

view this post on Zulip Nicholas Cahill (Mar 20 2022 at 11:45):

Got a new draft of this feature I feel okay about; it's interacting a little weirdly with the unit tests so I'm wondering about a no-history command line flag or something like that https://github.com/rtfeldman/roc/pull/2598


Last updated: Jun 16 2026 at 16:19 UTC