elves / elvish

Powerful scripting language & versatile interactive shell
https://elv.sh/
BSD 2-Clause "Simplified" License
5.67k stars 300 forks source link

Add Ability To Save State #698

Open iwoloschin opened 6 years ago

iwoloschin commented 6 years ago

Elvish has the exec command which can be used to restart a new Elvish session in place. I don't believe exec attempts to save the state of the shell and propagate it forward to the new session, though it does appear that Environmental Variables are saved, but not regular Elvish variables.

The other concern is that rc.elv should not be re-executed if a saved session is to be reloaded.

This should all probably be added as an optional flag to exec to preserve the current usage, which is still useful in many cases.

krader1961 commented 6 years ago

It's not clear what the use case is. I use exec for two reasons:

  1. I want to run a command and and when it terminates I don't want to return to the previous shell. I just want the current terminal session to terminate. Typically for when I'm doing things like connecting to a tmux session.

  2. I want to "undo" the effects of any experiments I've been doing in the current shell such as testing key bindings or a new module. So I'll do exec elvish to get back to a baseline instance of the shell without having to kill the current terminal session and start a new one.

For the second case above the whole point is to discard the current state of the shell. Otherwise why replace the current shell process with a new one? So I feel I must be missing something about your proposal, @iwoloschin.

xiaq commented 6 years ago

Some use cases:

krader1961 commented 6 years ago

Updating Elvish to a newer version.

I imagine that's a bit of a niche case primarily of interest to elvish developers. Which doesn't mean it shouldn't be implemented but does rank it lower in priority than features likely to be used by the average elvish user.

Preserving Elvish sessions across machine reboot.

How would that work? It implies that the default behavior would be to restore a session rather than doing the normal init sequence of loading rc.elv. That seems likely to cause problems. Is there a single saved session or does every elvish instance save its state? If the latter you now need a way to name the sessions and select which one is loaded. And you'll need some way to perform housekeeping; i.e., removing stale saved states.

And what is included in the "session"? Non-exported variables? Function definitions? The state of things like the edit namespace? What happens when the elvish version changes in a way that invalidates the saved state? Yes, that shouldn't be much of an issue once the public APIs are frozen and backward incompatible changes stop being a frequent occurrence. But it's definitely an issue today.

zzamboni commented 6 years ago

I agree with @krader1961. While this idea sounds technically interesting, I'm afraid it would add a lot of implementation complexity and edge cases for minimal benefit. I like that the state of my shell is reset between sessions - that's the whole point of encoding its "desired state" in my config files. The only pieces of state I might be interested in remembering are the command and directory histories, which are persisted already.

xiaq commented 6 years ago

Well, this could easily have more use cases...

You don't have to export or import all states at once. If Elvish is engineered in such a way that all of its state is reproducible, it enables you to export and import the states selectively.

krader1961 commented 6 years ago

Define a function interactively, and save the function to a file.

That is a useful feature and should be implemented regardless of the resolution of this issue. Fish has the funcsave command for that purpose. It takes a single function name and creates an autoload function in your ~/.config/fish/functions. That doesn't require the ability to save and restore the entire state of an elvish session. Just basic introspection, that I believe is already available, of a function.

The other two use cases are potentially useful and would allow implementing the capability @iwoloschin wants. I have no objection to implementing that capability but it should not be the default behavior for exec. In fact, exec doesn't need to be, and shouldn't be, aware of the hypothetical save/restore state capability. If someone wants to make it easier than typing save_state /some/file (or whatever it ends up looking like) followed by exec elvish --restore /some/file a function can be written to combine the two steps.

xiaq commented 6 years ago

I totally agree that this should not be the default behavior of exec; in fact, what you are proposing is exactly what I have in mind.

You can already implement some kind of funcsave in Elvish script. Retrieve the definition of a function is trivial:

~> fn funcdump [name f]{ echo 'fn '$name' '$f[def] }
~> fn l [@a]{ ls -l $@a }
~> funcdump l $l~
fn l [@a]{ ls -l $@a }

This will work only as long as the function does not have any upvalues. Elvish functions are closures and they can "capture" values in the outer scope (see also this example). The ability to serialize closures entails the ability to serialize any value and that is already very close to the ability to serialize the entire state of Elvish.

iwoloschin commented 6 years ago

@krader1961 for the record, I specifically said this should probably not replace the default behavior of exec, but the way exec is currently used does make sense to have it gain options to load a saved state. A new command would probably need to be created to save state, or potentially exec could be smart enough to save and reload the environment, perhaps something like exec --reload.