syl20bnr / spacemacs

A community-driven Emacs distribution - The best editor is neither Emacs nor Vim, it's Emacs *and* Vim!
http://spacemacs.org
GNU General Public License v3.0
23.66k stars 4.89k forks source link

Using eyebrowse and spacemacs-layouts simultaneously #3733

Closed d12frosted closed 8 years ago

d12frosted commented 8 years ago

In my opinion these two layers are not exclusive. And they should work together pretty well, allowing to boost productivity when working on several projects (domains).

Let me explain my usualy workflow with eyebrowse. Usually I separate available workspaces between different domains. For example, usually I had following separation.

workspaces purpose
1-2 org files
3-6 main project I am currently working on
7-8 temp buffers or files
9-0 emacs configs and other dotfiles

As you can see, it perfectly fits the idea of spacemacs-layouts. I have four groups (layouts) of domains. But inside of every group I have several workspaces, because workspace is really useful thing.

So it would be nice to use spacemacs-layouts to separate domains into different layouts and have independent eyebrowse workspaces in every layout. In my opinion it would be ultimate solution for working on different domains at the same time.

But currently this symbioses doesn't work as expected, since eyebrowse isn't configured to work with perspectives. The main problem is that workspaces are not separated between layouts. So you have following problems:

  1. When you create new workspace in one layout, all other layouts also have new workspace.
  2. When you close workspace in one layout, workspace with corresponding number is also closed in all other layouts.
  3. When you create new workspace in one layout and open file in that new workspace - this file can be seen and modified in other layout, though it's not really available in that layout (you can't kill it, you can't switch buffer to it etc). Update: but it's not available in all other layouts, just in one of them, which confuses a lot.

So would like to have it working together :)

d12frosted commented 8 years ago

Also, just to note - spaceline currently shows only tag of layout, but doesn't show tag of workspace - I believe both of them should shown in following form: $layout_name | $workspace_number_or_tag | $window_number.

robbyoconnor commented 8 years ago

:+1:

nixmaniack commented 8 years ago

Yeah! :+1:

syl20bnr commented 8 years ago

I'm not sure to understand the described level of indirection, I need a shorter description of the feature.

What brings eyebrowse to the table ? Different kind of regular layouts which can be applied to any Spacemacs layout ? Like different layouts of Awesome WM ?

TheBB commented 8 years ago

Basically, it would be good if eyebrowse was entirely perspective-local.

d12frosted commented 8 years ago

For example, you are working on one project and need to have four files to be opened at the same time. For example, 3 source files and one shell. With eyebrowse I would use 3 workspaces - two source files in first workspace, third source file in second workspace and shell in the third workspace. They all are related to one project. And it would be nice to separate these 3 workspaces from other workspaces. So overall it looks like

- layout 1 : domain 1
-- workspace1
-- ...
-- workspace0
- layout 2 : domain 2
-- workspace1
-- ...
-- workspace0

And it allows to switch between domains easily. Probably my confusion arrises from the fact that I think about layouts as about domains (be it project or meta-domain). But at this point I think it would be useful.

On other hand, using layouts allows easier switching between buffers which makes it easier to work on several files at the same time while having multiple domains active in the background (with eyebrowse when you hit SPC b b the list of buffers is polluted with items from another workspace, which makes harder to switch, plus buffers with identical names confuse me, because I need to see the ending of the name which is truncated or to check the full path of file... etc).

But in any case, I think it's a good idea to make eyebrowse and perspectives working together.

d12frosted commented 8 years ago

Basically, it would be good if eyebrowse was entirely perspective-local.

Yeah, this is what I mean in one sentence without any reasoning.

syl20bnr commented 8 years ago

We may need to ditch eyebrowse and code a package persp-multiple-windows-configurations to be free to integrate seamlessly with persp-mode.

I want us to avoid to use the word workspace because it may lead to some nasty confusions with the word layout. I would prefer the term windows-configuration.

With this terminology, the windows configuration bindings would be in the SPC w namespace which matches with split, winner-undo etc...

syl20bnr commented 8 years ago

Depending on the dependency between persp-mode and windows configurations we may consider putting thembehind SPC l w as already proposed.

StreakyCobra commented 8 years ago

I want us to avoid to use the word workspace because it may lead to some nasty confusions with the word layout. I would prefer the term windows-configuration.

Do we have to stop using the Workspaces label then :smile: ?

syl20bnr commented 8 years ago

@StreakyCobra Thank you, I renamed it :-)

bmag commented 8 years ago

We may need to ditch eyebrowse and code a package persp-multiple-windows-configurations to be free to integrate seamlessly with persp-mode.

Not necessarily. We can customize persp-restore-window-conf-method or persp-window-state-get-function and persp-window-state-put-function so that persp-mode uses eyebrowse as its window configuration engine. Alternatively, we can use persp-activated-hook to load a window configuration from eyebrowse.

This of course doesn't provide perspective-local eyebrowse workspaces, but those could be implemented if persp-mode had perspective-local variables or a persp-deactivated-hook (that would run at the beginning of persp-activate).

Maybe this is worth opening two feature requests (or pull requests) against persp-mode itself? One feature request for integration with eyebrowse/perspective-local workspaces, and a second feature request for perspective-local variables, or at least a persp-deactivated-hook.

bmag commented 8 years ago

Actually eyebrowse stores its workspaces as frame parameters, so it might be tricky (but probably doable) to save them as perspective-local variables, depending on implementation of perspective-local variables (if those will be implemented at all).

syl20bnr commented 8 years ago

Would this be a viable not too ugly solution to define a new data structure which is a perspective that points on a parent perspective which "shares" its buffer list ?

bmag commented 8 years ago

The definition of perspective objects:

(defstruct (perspective
            (:conc-name persp-)
            (:constructor make-persp))
  (name "")
  (buffers nil)
  (window-conf nil)
  (parameters nil))

Honestly, I don't know if your proposition is viable or not, but wouldn't we need to define a new structure and make persp-mode use it instead? We will need to advise/rewrite at least some of the getters and setters that persp-mode defines (i.e. safe-persp-buffers, maybe others as well). Other than that, we will need to modify the commands for switching perspectives so they distinguish between perspectives. We will want one command to switch between perspectives with the same buffer list (a-la eyebrowse workspaces) and another command to switch to a perspective with a different buffer list. My gut feeling (and I may be wrong) is that we're gonna end up duplicating stuff from eyebrowse or writing something equivalent.

However, I believe I found a better and simpler solution. The solution depends on persp-activated-hook, eyebrowse-post-window-switch-hook and perspective parameters. First of all, perspective parameters are like perspective-local variables, so this feature is already implemented :smile: Second of all, eyebrowse workspaces are stored as frame parameters. The workspaces are accessible via (eyebrowse--get 'window-configs), (eyebrowse--get 'current-slot) and (eyebrowse--get 'last-slot). We only need to translate eyebrowse's frame parameters to perspective parameters and keep them in sync. In eyebrowse-post-window-switch-hook we can do something like:

(set-persp-parameter 'eyebrowse-window-configs (eyebrowse--get 'window-configs))
(set-persp-parameter 'eyebrowse-current-slot (eyebrowse--get 'current-slot))
(set-persp-parameter 'eyebrowse-last-slot (eyebrowse--get 'last-slot))

In persp-activated-hook we can do something like:

(eyebrowse--set 'window-configs (persp-parameter 'eyebrowse-window-configs))
(eyebrowse--set 'current-slot (persp-parameter 'eyebrowse-current-slot))
(eyebrowse--set 'last-slot (persp-parameter 'eyebrowse-last-slot))

Note that we don't need to explicitly load the workspace when a perspective is activated, because persp-mode already knows how to restore the correct windows. Some more work needs to be done for the solution to work, but these I think are the crucial points.

TheBB commented 8 years ago

That looks very promising. Good detective work @bmag. :-)

bmag commented 8 years ago

Finally got it working, see #4068. It only took 3 hooks :smile:

d12frosted commented 8 years ago

Wow, thanks a lot! I'll take a look tomorrow in the morning!