REPL looses local variables after :edit #1195

Open
opened 2026-04-27 14:11:35 +00:00 by blokyk · 5 comments
Member

Describe the bug

After running a simple :edit command, I lost all my local variables, seemingly because the REPL is reloading.

Steps To Reproduce

$ echo 'foo { a = 7; }' > default.nix
$ nix repl
Lix 2.95.1
Type :? for help.
nix-repl> fn = import ./.
Added fn.

nix-repl> :e fn
<Close the editor>
nix-repl> fn
error: undefined variable 'fn'
       at «string»:1:1:
            1| fn
             | ^

Note that when using repl-overlays, this displays Loading 'repl-overlays'... and Added 114 variables. which means it's actually reloading the REPL every time.

Expected behavior

Local variables like fn are still available after edit, and no reload is performed.

nix --version output

nix (Lix, like Nix) 2.95.1
System type: x86_64-linux
Additional system types: i686-linux, x86_64-v1-linux, x86_64-v2-linux, x86_64-v3-linux
Features: gc, signed-caches
System configuration file: /etc/nix/nix.conf
User configuration files: /home/courvoie/.config/nix/nix.conf:/etc/xdg/xdg-ubuntu-xorg/nix/nix.conf:/etc/xdg/nix/nix.conf
Store directory: /nix/store
State directory: /nix/var/nix
Data directory: /nix/store/slkbw0cg08jhfsax6kc0bf6rvw7rkl26-lix-2.95.1/share

Additional context

I quickly tested CppNix 2.31.3 and it also happens, so this is not because of one of our changes and there's a lower chance it's a regression (though it's still possible, I haven't checked).

## Describe the bug After running a simple `:edit` command, I lost all my local variables, seemingly because the REPL is reloading. ## Steps To Reproduce ```sh $ echo 'foo { a = 7; }' > default.nix $ nix repl Lix 2.95.1 Type :? for help. nix-repl> fn = import ./. Added fn. nix-repl> :e fn <Close the editor> nix-repl> fn error: undefined variable 'fn' at «string»:1:1: 1| fn | ^ ``` Note that when using repl-overlays, this displays `Loading 'repl-overlays'...` and `Added 114 variables.` which means it's actually reloading the REPL every time. ## Expected behavior Local variables like `fn` are still available after edit, and no reload is performed. ## `nix --version` output ``` nix (Lix, like Nix) 2.95.1 System type: x86_64-linux Additional system types: i686-linux, x86_64-v1-linux, x86_64-v2-linux, x86_64-v3-linux Features: gc, signed-caches System configuration file: /etc/nix/nix.conf User configuration files: /home/courvoie/.config/nix/nix.conf:/etc/xdg/xdg-ubuntu-xorg/nix/nix.conf:/etc/xdg/nix/nix.conf Store directory: /nix/store State directory: /nix/var/nix Data directory: /nix/store/slkbw0cg08jhfsax6kc0bf6rvw7rkl26-lix-2.95.1/share ``` ## Additional context I quickly tested CppNix 2.31.3 and it also happens, so this is not because of one of our changes and there's a lower chance it's a regression (though it's still possible, I haven't checked).
Owner

My vibe is that this is intentional: the workflow I think :e expects you to be using is to be doing nix repl -f . in nixpkgs and then it will reload after each of your changes so that you can re-run whatever expression you had again against your edited version.

We maybe should document that it's intended to reload (or test it somehow? maybe set a fucked up thing in $EDITOR? idk).

maybe it shouldn't reload if the file in question is in the nix store already since it would thus be immutable? dunno how useful that would actually be.

My vibe is that this is intentional: the workflow I think :e expects you to be using is to be doing nix repl -f . in nixpkgs and then it will reload after each of your changes so that you can re-run whatever expression you had again against your edited version. We maybe should document that it's intended to reload (or test it somehow? maybe set a fucked up thing in $EDITOR? idk). *maybe* it shouldn't reload if the file in question is in the nix store already since it would thus be immutable? dunno how useful that would actually be.
Author
Member

Personally I mostly use :e to see the code of the function I'm calling, or to look around in a file, so while I'm just exploring and trying expressions out it's very annoying to loose all local variables.

Since most of the time, the code i'm looking at is in the system's pinned nixpkgs, it might be fine if it only reloaded if the file is read-only/in the nix store, but it's still surprising behavior to me. Would it be possible to extend that to checking that the file being edited has the same hash before and after spawning the editor?

Ideally, the local bindings would still be in scope but their evaluator cache would be cleared so that they'd be recomputed; I'm just not sure how doable that is since i don't know much about the evaluator's internals. but if we can do that, all workflows would work as expected; we might have some performance hits in theory, but only in scenarios that weren't allowed before, so it's better than nothing.

But as it stands right now it's mildly/very annoying if you're trying to test more than just one expression (and/or you're not doing nixpkgs-hacking, which i suspect a large part of our users are not doing, and i'm not sure the "nixlang tutorial/exploratory entry point" that the REPL is should be geared towards nixpkgs maintainers).

Personally I mostly use `:e` to see the code of the function I'm calling, or to look around in a file, so while I'm just exploring and trying expressions out it's very annoying to loose all local variables. Since most of the time, the code i'm looking at is in the system's pinned nixpkgs, it might be fine if it only reloaded if the file is read-only/in the nix store, but it's still surprising behavior to me. Would it be possible to extend that to checking that the file being edited has the same hash before and after spawning the editor? Ideally, the local bindings would still be in scope but their evaluator cache would be cleared so that they'd be recomputed; I'm just not sure how doable that is since i don't know much about the evaluator's internals. but if we can do that, all workflows would work as expected; we might have some performance hits in theory, but only in scenarios that weren't allowed before, so it's better than nothing. But as it stands right now it's mildly/very annoying if you're trying to test more than just one expression (and/or you're not doing nixpkgs-hacking, which i suspect a large part of our users are not doing, and i'm not sure the "nixlang tutorial/exploratory entry point" that the REPL is should be geared towards nixpkgs maintainers).
Owner

Would it be possible to extend that to checking that the file being edited has the same hash before and after spawning the editor?

not sure that's actually helpful because you may have navigated around in your editor session and changed other files instead, also influencing the reëvaluation result. but we could add a dedicated command for browsing sources instead without causing a reload, because that does sound pretty useful?

I'm just not sure how doable that is

it's completely impossible in the current setup and will remain so for at least quite a while to come

> Would it be possible to extend that to checking that the file being edited has the same hash before and after spawning the editor? not sure that's actually helpful because you may have navigated around in your editor session and changed *other* files instead, also influencing the reëvaluation result. but we could add a dedicated command for browsing sources instead without causing a reload, because that does sound pretty useful? > I'm just not sure how doable that is it's completely impossible in the current setup and will remain so for at least quite a while to come
Author
Member

you may have navigated around and changed other files instead

i hear you, but i think that represents a fraction of a fraction of users, so doing a "best effort" solution is better than nothing in my opinion, and worse case scenario the user just has to do a :r after exiting the editor, which isn't too hard an ask imo.

as for a hypothetical "viewing-only" command: i'm unsure how doable it might be to open $EDITOR in read-only mode without special-casing them (and then what do we do if it's one we don't don't special-case for?), and honestly I think it's too close to :e to really merit a separate command when we could instead ensure that :e reloads less often

> you may have navigated around and changed _other_ files instead i hear you, but i think that represents a fraction of a fraction of users, so doing a "best effort" solution is better than nothing in my opinion, and worse case scenario the user just has to do a `:r` after exiting the editor, which isn't too hard an ask imo. as for a hypothetical "viewing-only" command: i'm unsure how doable it might be to open `$EDITOR` in read-only mode without special-casing them (and then what do we do if it's one we don't don't special-case for?), and honestly I think it's too close to `:e` to really merit a separate command when we could instead ensure that `:e` reloads less often
Owner

Personally I would be rather surprised if people regularly use :e to ferret around random other files, edit them, then reload because that sounds like terrible ergonomics vs having a terminal multiplexer and hitting :r, so I would totally stamp a "don't reload if there's no changes" CL. Seems to improve the ergonomics of the common case, improving the overall average experience.

Worst case users who are doing that just hit :r, because I do find the reading case is way more common from my own experience.

Oh btw random idea, what if we supported :h :e to surface better help text for commands? I'll file a ticket. e: #1201

Personally I would be rather surprised if people regularly use :e to ferret around random other files, edit them, then reload because that sounds like terrible ergonomics vs having a terminal multiplexer and hitting :r, so I would totally stamp a "don't reload if there's no changes" CL. Seems to improve the ergonomics of the common case, improving the overall average experience. Worst case users who are doing that just hit :r, because I do find the reading case is way more common from my own experience. Oh btw random idea, what if we supported `:h :e` to surface better help text for commands? I'll file a ticket. e: https://git.lix.systems/lix-project/lix/issues/1201
Sign in to join this conversation.
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lix-project/lix#1195
No description provided.