zellij-org / zellij

A terminal workspace with batteries included
https://zellij.dev
MIT License
20.61k stars 638 forks source link

[Feature request] Restore Zellij environment after system restart #575

Closed VasanthakumarV closed 11 months ago

VasanthakumarV commented 3 years ago

Currently, all the Zellij sessions are lost after the System restarts, it will be nice to have them restored for a seamless experience.

Reference

alekspickle commented 1 year ago

Oh I have some tests on my branch. I was a bit busy at work myself...

imsnif commented 1 year ago

@AlixBernard @alekspickle - I'm currently concentrating on the upcoming release (coming hopefully next week) and afterwards I'll be on vacation for a couple of weeks at the beginning of September. I hope you can make progress without me (minus questions here and there when I'm not cycling in the mountains)?

Otherwise in mid-september I'll come back and can hop in if you need me so we'll get this polished and ready for the release afterwards. Looking forward to seeing what you two come up with!

AlixBernard commented 1 year ago

@alekspickle Yes thanks! I saw your commit add tests; print resulting kdl that defined tests) However it seems to still use strings such as r#"[ {"x": 0, "y": 0, "cols": 100, "rows": 50}, {"x": 0, "y": 50, "rows": 50, "cols": 50}, {"x": 50, "y": 50, "rows": 50, "cols": 50} ]"#, which was fine when flexible panes were not to take into account. Now we need to use the real input we will have (ie PaneGeoms) as they provide a Dimension that itself has a Constraint defining if the pane is fixed or flexible. Also the way the input is provided may be important as it may give information as whether the panes are part of a tab or not (I hope).

Possible layouts to use ```kdl layout { pane size=1 borderless=true { plugin location="zellij:tab-bar" } pane pane size=2 borderless=true { plugin location="zellij:status-bar" } } ``` ```kdl layout { tab { pane pane size=20 split_direction="vertical" { pane size=50 pane } } } ``` ```kdl layout { pane size=20 { pane size=10 pane size=10 } pane split_direction="vertical" { pane size=30 pane } } ``` ```kdl layout { tab { pane size=10 split_direction="vertical" { pane pane } pane split_direction="vertical" { pane size=40 pane pane size=40 } pane size=10 split_direction="vertical" { pane pane } } } ``` ```kdl layout { tab { pane split_direction="vertical" { pane size="70%" { pane split_direction="vertical" { pane { pane size="35%" // Doesn't work when at 40% or more? pane size="35%" // Doesn't work when at 40% or more? pane } pane } pane size=10 } pane size="30%" } } } ``` ```kdl layout { default_tab_template { pane size=1 borderless=true { plugin location="zellij:tab-bar" } children pane size=2 borderless=true { plugin location="zellij:status-bar" } } tab name="tab1" { pane } tab name="tab2" split_direction="vertical" { pane pane } tab name="tab3" split_direction="vertical" { pane size="60%" pane } tab name="tab4" split_direction="horizontal" { pane size=20 { pane size=8 pane size=12 } pane } } ```
AlixBernard commented 1 year ago

@imsnif No problem, as I said in my previous message, we just need to make tests with real input (I don't know if @alekspickle knows how to get them, or maybe you can do it if it's not too much time consuming for you) so I can correct eventual errors. The rest I guess we can manage and if not we will wait for your come back)

alekspickle commented 1 year ago

no problem! do you need the debug version of PaneGeom?

AlixBernard commented 1 year ago

By the debug version I assume that you mean the string obtained using {:?}? This could work but getting the PaneGeom structures directly would be easier) The best would be to have test functions, as I wrote above, but that provide me with the PaneGeoms in a vector, hashmap, or another structure if it makes sense (if possible in a way that allows me to know if they are part of a tab or no)

imsnif commented 1 year ago

Just to chime in, could we maybe use mock data for these tests? As in instantiate an arbitrary vector of PaneGeoms for each test case?

AlixBernard commented 1 year ago

Yes it's possible, I've done it for the most basic cases. It however requires a lot of code for what it is so I thought that parsing the kdl layout to obtain the PaneGeoms would make more sense.

AlixBernard commented 1 year ago

So, as suggested, I mocked the data for some test cases and, after a couple of fixes, my code works! (See the output example below) Now, as I mentioned before, solely based on a vector of PaneGeoms it cannot be inferred what is the current working directory in the pane, what is the application running, etc. or if the pane contains a plugin. I don't know either how are grouped the PaneGeoms into tabs but this should be easy to add to the code.

@imsnif, @alekspickle - For now that's all I am able to do, let me know when you are available so we can move forward. (Maybe I could do a pull request to the branch alekspickle/zellij/tree/feat/saving-tab-layout-to-a-file to add my code?)

Output example Target, ie the kdl layout used to mock the data: ```kdl layout { tab { pane split_direction="vertical" { pane size="70%" { pane split_direction="vertical" { pane { pane size="30%" pane size="30%" pane } pane } pane size=10 } pane size="30%" } } } ``` Output obtained from the mocked data: ```kdl layout { tab { pane split_direction="vertical" { pane size="70%" { pane split_direction="vertical" { pane size="50%" { pane size="30%" pane size="30%" pane size="40%" } pane size="50%" } pane size=10 } pane size="30%" } } } ```
imsnif commented 1 year ago

@AlixBernard - that's amazing!

Just to make sure, this also works with mixed fixed/flexible sizes, right? So that for example in our default layout, with the status-bar and tab-bar taking up 1 and 2 lines each with all other panes being a percentage of the remainder it'll still work?

As for the pane contents (cwd, command, etc.) I can take that on myself. I think I can both do it quickly and I also have specific opinions on what the user experience needs to be here :) I'll take care of it in mid-september when I get back from my vacation.

@alekspickle - until then, if you are available, do you think you can help out with integrating what we currently have into your branch? If we manage to get to a point where everything works and on an arbitrary keyboard shortcut we dump the session state to a layout on disk that'll be gold.

alekspickle commented 1 year ago

Sure no problem! I can wait for a PR to my branch or you can ping me in discord @AlixBernard, whatever works for you

AlixBernard commented 1 year ago

@imsnif - Yes I confirm it works with mixed fixed/flexible pane sizes. My previous example has one pane with fixed size in it and the default layout also works.

@alekspickle - Alright, I'll make the PR tomorrow

imsnif commented 1 year ago

That's fabulous. I'm very excited to see this moving forward.

imsnif commented 1 year ago

Hey @AlixBernard @alekspickle - I'm back from vacation and ready to do my part. What's the status? Is there a branch with all work concentrated?

AlixBernard commented 1 year ago

Hey @imsnif! I made a PR on @alekspickle 's branch. Let me know if you need an explanation on the code or else

alekspickle commented 1 year ago

Yeah, it somehow slipped my github feed I'm rebasing and testing it now

imsnif commented 12 months ago

To update: I rebased the PR branch and added commands to the dumped layout. Next thing is to add plugins, then command panes, editor panes... and small adjustments like floating panes, stacked panes, etc. Making progress! Will continue working on this in the next few days and keep this thread updated.

imsnif commented 12 months ago

Btw, @alekspickle @AlixBernard - is one of you using a mac by any chance? I'd be curious to see if the pgrep method I used would work there. Essentially to test you can check out the branch, start a session, run any type of long running commnand (eg. htop) and do a dump layout while it's still running... see if it's reflected in the layout. In linux it works like a charm for me, if it doesn't on macos I'll find another method.

imsnif commented 12 months ago

@alekspickle @AlixBernard - I'm a bit dense about non-explicit communication, so I'm not sure what the emoji reaction means... can you please help me out?

AlixBernard commented 12 months ago

Fair enough! I meant no, in the sense that I do not have a mac and cannot test what you are asking for unfortunately

imsnif commented 12 months ago

Thanks! If @alekspickle meant the same, I'm sure I'll be able to find someone to test this before we merge.

alekspickle commented 12 months ago

Yeah, sorry, not an apple boi :grimacing:

brneor commented 12 months ago

@imsnif if you can provide instructions on how to test this specific branch, what to test and what kind of feedback do you need I have a mac and some little free time available to test it.

imsnif commented 12 months ago

Thanks @brenor! I think it's a bit involved at this stage but I'll keep you in mind.

alekspickle commented 12 months ago

As soon as I finish rebase(it became very messy) and test it out a bit I'll add proper description to a PR

imsnif commented 12 months ago

@alekspickle - just to make sure we're not doing double work here: I'm not sure if this is what you mean, but I already rebased and started working on your branch... I have it working with (non-floating) terminal panes and am now wrapping up plugins.

alekspickle commented 12 months ago

I am not sure, last I checked the proposed code did not have tabs_to_kdl, meaning it handled only 1 tab setups. I am a bit lost in all new stuff so I was just adding stuff needed for plugin actions for some reason and also adding logic & tests for converting all the tabs to a KDL layout

imsnif commented 12 months ago

Yeah, it was a minor function addition so I added it. The code is working now - I see you closed the PR though, why?

imsnif commented 12 months ago

I think I can take it from here, there's not a lot of stuff to do and it's mostly annoying threading stuff. I know the code-base well so can do it quickly. If you'd like to keep working on it, it'd be very valuable to find a way to test all of this...

alekspickle commented 12 months ago

Ok go ahead then, I see you prioritized it already :grimacing: testing it should be easy - just compare to expected layout strings, no?

alekspickle commented 12 months ago

Yeah, it was a minor function addition so I added it. The code is working now - I see you closed the PR though, why?

I did not, at least on purpose...

imsnif commented 12 months ago

Ok go ahead then, I see you prioritized it already 😬

Yes! Let's get this merged.

testing it should be easy - just compare to expected layout strings, no?

Well, yes. But I don't think there's any place in the code base that mocks all relevant threads in tests (screen, plugin, pty). Might be best to add an e2e test, but they're a bit flaky and involved to get right.

alekspickle commented 12 months ago

I am not sure what you did, but that was not me closing PR but some github rules, whatever you did - it reacted to it, I did not even push, and I doubt I can force push. In any way - the PR summary says Pull request successfully merged and closed but it was not merged and new PR from my branch is impossible since apparently no new commits. Github being funny?...

imsnif commented 12 months ago

Moving the conversation to the PR: https://github.com/zellij-org/zellij/pull/2451

imsnif commented 12 months ago

More updates: plugins are being properly dumped into the layout, as well as floating panes. Not a lot left to do on the serialization side, I hope to wrap it up in the next few days and then figure out the best UX for the resurrection itself.

imsnif commented 11 months ago

Even more updates: The session serialization is all but complete, the PR's dump-layout action now dumps all panes, respecting their CWD and running commands. It also consolidates the CWD into relative paths (eg. if one pane is /home/aram/code/zellij and another pane is /home/aram/code/rustlang, the first will be zellij, the second will be rustlang and the global cwd will be /home/aram/code - so it should be relatively easy to manually edit this field in order to share sessions between machines).

There are some minor edge cases left with the serialization itself (eg. panes editing the scrollback, copying the custom pane/tab names, etc.) - and afterwards all that is left is the resurrection itself.

Right now my thoughts are: by default if attaching to a session with zellij attach <session-name>, a "dead" session by that name will be resurrected if it exists, if the --override flag will be provided, the dead session will be deleted and a new session by that name started.

This along with some nice sugar like listing the dead sessions within our new session-manager (and of course allowing them to be resurrected from there) as well as in zellij list-sessions.

I hope to have most of this merged by the end of the week.

imsnif commented 11 months ago

So, I realize I'm overdue but: all serialization edge cases have been dealt with.

Attaching to a dead session works, zellij ls now lists dead sessions as wise-river (DEAD, attach to resurrect). There's a new zellij delete <session-name> and zellij delete-all-sessions pair of commands that remove the resurrection assets. They also have a --force flag which will also kill an active session before deleting its contents.

What's mostly left is restoring tab/pane focus when starting a session, as well as making sure all commands (by default) are placed behind a start_suspended true, so that users will be prompted before running them (so that eg. if your session crashed in the middle of a cargo publish or anything that starts with rm, it won't be awkward). Will probably add some escape hatch for that too.

Oh! And then getting the session-manager and thus the plugin API to be aware of all of this, but that might be a following PR.

imsnif commented 11 months ago

New zellij ls:

img-2023-10-04-165521

imsnif commented 11 months ago

Pane contents (viewport) and scrollback are now also being resurrected. Currently this is opt-in behind a config, I'm considering what the best default here would be though - will likely change before the release.

imsnif commented 11 months ago

PR is up: https://github.com/zellij-org/zellij/pull/2801

imsnif commented 11 months ago

Implemented and merged. Thanks everyone, and especially @AlixBernard and @alekspickle for helping make this happen.

This will be released in the next version, but I ask for your patience as I want to include a few other features in the release.

AlixBernard commented 11 months ago

Amazing work! It was great to collaborate with both of you) Looking forward to the next release

Slate245 commented 11 months ago

This is seriously amazing! Looking forward for the new release!

thedenisnikulin commented 11 months ago

LET'S GO!

sommerper commented 10 months ago

I have been waiting for this so I can finally switch!

sgon00 commented 7 months ago

A newbie question. Maybe I am dumb. What does the current saved session do? I tried it, it didn't recover anything except the layout. But from my point of view, the most important things are different command history logs, different directory paths (different pwd) and different text displays (buffer history) of all tabs. But none of them is restored.

oldgithubman commented 4 months ago

A newbie question. Maybe I am dumb. What does the current saved session do? I tried it, it didn't recover anything except the layout. But from my point of view, the most important things are different command history logs, different directory paths (different pwd) and different text displays (buffer history) of all tabs. But none of them is restored.

This is what I'm looking for too and I thought Zellij had it but maybe not? Specifically looking for restoration of different command history logs. So like a separate bash history for each pane that gets properly saved even in the event of a crash. Heck even a single bash history that gets saved even if crashed would be better than nothing. If anyone knows how to achieve this, please let me know

adrian-gierakowski commented 3 months ago

Heck even a single bash history that gets saved even if crashed would be better than nothing.

Use fish, you’ll get this for free

merikan commented 3 months ago

A newbie question. Maybe I am dumb. What does the current saved session do? I tried it, it didn't recover anything except the layout. But from my point of view, the most important things are different command history logs, different directory paths (different pwd) and different text displays (buffer history) of all tabs. But none of them is restored.

This is what I'm looking for too and I thought Zellij had it but maybe not? Specifically looking for restoration of different command history logs. So like a separate bash history for each pane that gets properly saved even in the event of a crash. Heck even a single bash history that gets saved even if crashed would be better than nothing. If anyone knows how to achieve this, please let me know

@oldmanjk have you tried using pane_viewport_serialization and scrollback_lines_to_serialize

oldgithubman commented 3 months ago

A newbie question. Maybe I am dumb. What does the current saved session do? I tried it, it didn't recover anything except the layout. But from my point of view, the most important things are different command history logs, different directory paths (different pwd) and different text displays (buffer history) of all tabs. But none of them is restored.

This is what I'm looking for too and I thought Zellij had it but maybe not? Specifically looking for restoration of different command history logs. So like a separate bash history for each pane that gets properly saved even in the event of a crash. Heck even a single bash history that gets saved even if crashed would be better than nothing. If anyone knows how to achieve this, please let me know

@oldmanjk have you tried using pane_viewport_serialization and scrollback_lines_to_serialize

No, I moved on. Thanks though