Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-workspace projects/scopes #387

Open
1 of 2 tasks
ivanbrennan opened this issue Sep 27, 2020 · 11 comments
Open
1 of 2 tasks

Multi-workspace projects/scopes #387

ivanbrennan opened this issue Sep 27, 2020 · 11 comments

Comments

@ivanbrennan
Copy link
Member

ivanbrennan commented Sep 27, 2020

Problem Description

A project defined by X.A.DynamicProjects or X.A.TopicSpace is limited to a single workspace. I often want to treat a group of workspaces as a scope, constraining workspace cycling and status-bar display to a particular scope.

For example, if I have workspaces A B C D E, I can define a "personal" scope spanning A B and a "work" scope spanning C D. When the "personal" scope is active, my statusbar shows A B and workspace cycling is limited to those workspaces. Switching to the "work" scope behaves similarly, for C D. Switching to unscoped makes all workspaces accessible.

Tmux has a concept of "sessions" that works like this. Each session has an independent set of workspaces (or rather, "windows", in tmux terminology), and you can easily switch between sessions. This provides a nice way to group related workspaces into independent units and choose which unit you want to work with.

I looked into X.A.DynamicWorkspaceGroups, but its group represents a set of simultaneously visible workspaces on a multi-screen setup, as opposed to a set of workspaces that a given screen can cycle through.

Solution

I'm interested in implementing this, but I'm not sure how best to do it. I'd be interested to hear anyone's thoughts/suggestions.

After reading through X.A.DynamicWorkspaceGroups, X.A.DynamicProjects, and X.L.IndependentScreens, I started sketching something out, using ExtensibleState to keep track of which scopes have been defined, activated, etc.

newtype WorkScope = WorkScope { unWorkScope :: !(Set WorkspaceId) }

type WorkScopeName = String

newtype ScopeSets = ScopeSets
  { workScopes   :: !(Map WorkScopeName WorkScope),
    activeScopes :: !(Map ScreenId WorkScopeName) -- TODO: track which workspace is displayed?
  }
  deriving (Typeable, Read, Show)

instance ExtensionClass WorkScopes where
  initialValue = WorkScopes mempty
  extensionType = PersistentExtension

It looks like there's a fair amount of state to keep track of and several edge-cases to consider (e.g. workspaces being renamed/removed, selecting a scope that's active on another screen, ...), so I haven't really settled on how to model it or keep state in sync (maybe using a layout modifier?).

Another approach I'm considering would attach a Maybe WorkScopeName to a workspace, and scoping would involve filtering workspaces based on the relevant scope. I suspect this would be more reliable than my initial Map-based idea, since it wouldn't need to update state any time a workspace is removed or renamed. And X.L.WorkspaceDir provides an example of how to use a layout modifier to attach metadata to a workspace. If we wanted to allow a workspace to be a member of multiple scopes, the Maybe WorkScopeName could instead be a Set WorkScopeName.

Checklist

@jeyj0
Copy link

jeyj0 commented Nov 18, 2020

If we wanted to allow a workspace to be a member of multiple scopes

That's definitely a feature I would want :)

@liskin
Copy link
Member

liskin commented Nov 18, 2020

And X.L.WorkspaceDir provides an example of how to use a layout modifier to attach metadata to a workspace.

Unfortunately it doesn't provide a way to read that metadata.
But I'm working on that, specifically to provide a way to read the dir out of WorkspaceDir, see #398 (comment). The Typeable changes required are merged to xmonad/xmonad-contrib, ale the latest prototype of InspectLayoutModifier is here: liskin@77c1821. I think I'll just need to add a few (overlapping 🙁) instanes and some documentation and we might be good to go.

And I feel like I could use this feature as well! I now have 11 workspaces, 6 of which are related to a project that is currently on hold while I'm hacking on xmonad. Would be awesome to be able to hide those somehow. I'm a bit afraid that this will need to be wired into quite a lot of various places, but we can figure something out!

@mislavzanic
Copy link
Contributor

Hi, I've been working on something similar to this for my personal use.
Here's the module if anyone is still interested.
I'm somewhat of a haskell newbie and the module is a work in progress, so keep that in mind when looking at the code. I've been using this for 2 weeks now and it's good enough for me.

Feel free to message me if you have any suggestions 🙂.

@ivanbrennan
Copy link
Member Author

Thanks @mislavzanic, I for one am still very interested in this feature. Regretfully, I haven't looked into it for a while, but this is a good reason to revisit it.

@ivanbrennan
Copy link
Member Author

@liskin Is there anything I could help with to get InspectLayout ready for a PR?

Experimenting in my config, I was able to make use of your Inspect module, defining a simple layout modifier that attaches metadata to a workspace and using inspectWorkspace to read that data.

@liskin
Copy link
Member

liskin commented Feb 23, 2023

@ivanbrennan If you help me with the docs (TODOs) in https://github.com/liskin/xmonad-contrib/commits/layout-inspect, specifically liskin@07dd219, then a PR can definitely be opened. I've been burned out lately so my initiative is limited, but you're right that this one doesn't need much additional work to be generally usable.

@mislavzanic
Copy link
Contributor

@ivanbrennan I would love to help out, so don't hesitate to contact me.

@ivanbrennan
Copy link
Member Author

@liskin @mislavzanic Thanks! I'll take a look at those TODOs.

I'm just starting to play around with possible implementations of workspace scopes.
At the moment, I'm grouping workspaces into layers, so rather than 1, 2, ..., 9 I have (1_1, 1_2, ..., 1_9), (2_1, 2_2, ..., 2_9), ..., and tracking which layer is considered currently active.

I just came across XMonad.Actions.WorkspaceCursors, which looks very powerful (and cleanly implemented) and could be used to implement such layers.

I haven't yet explored dynamic layer manipulation or naming layers, but plan to do so -- thanks @mislavzanic for sharing the Profiles idea.

@mislavzanic
Copy link
Contributor

Anybody still interested in this? I've been using my extension for about a year.. There may be some details that need to be discussed, but it's working pretty nicely.

If anybody is interested in using it feel free to ping me.

@geekosaur
Copy link
Contributor

There's been some interest expressed on the IRC channel recently. In any case, contrib is always open to new submissions. 😀

@mislavzanic
Copy link
Contributor

Ok, I'll start working on a PR then. Will need a couple of days to tidy up and write the documentation.
Hope to be done by end of the week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants