nikitabobko / AeroSpace

AeroSpace is an i3-like tiling window manager for macOS
https://nikitabobko.github.io/AeroSpace/guide
MIT License
6.22k stars 101 forks source link

swap two workspaces #310

Closed edgimar closed 1 month ago

edgimar commented 3 months ago

In another tiling WM, I regularly used a "swap with workspace" command that allowed swapping the currently active workspace with some other workspace. Swapping essentially means moving all of the contents (and layout) of the current workspace to the other, and vice-versa. This makes is possible to bring one workspace's contents "near" to other workspaces so that you can easily switch between them using 'workspace prev' and 'workspace next'.

wtianyi commented 3 months ago

Does workspace-back-and-forth work for your purpose?

nikitabobko commented 3 months ago

Sounds like renaming: #245

edgimar commented 3 months ago

workspace-back-and-forth is not the same (though I also use this feature regularly) -- the key idea is that there is a clearly defined ordering of workspaces (which is maybe something else to consider -- instead of automatically sorting, allow the ordered set of workspaces to be explicitly specified) where you can move to "the left" or "the right" of the current workspace. The "swap workspaces" feature would allow swapping, for example, the current (e.g. 4th) workspace with the 9th workspace. Then when I am on the 3rd workspace, I can move "right" to get to what used to be on the 9th. The objective is to allow workspace ordering to be rearranged, for example to group a similar set of workspaces next to each other.

@nikitabobko In lieu of explicit ordering of workspaces, I suppose it is possible to prefix workspace names with numbers, and then rename them using #245, but this sounds like a lot of extra complexity: if you need to swap "3: email" with "7: web" using only renaming, then you need to split each workspace into substrings, swap the first substrings, concatenate, and finally perform the renames. Or were you thinking to have a separate command that handles this (which would require all the workspaces to be named according to a specific format)?

nikitabobko commented 3 months ago

@edgimar please read my proposal https://github.com/nikitabobko/AeroSpace/issues/245#issuecomment-2156003680

You don't need to do manual string manipulation in my proposal

edgimar commented 3 months ago

@edgimar please read my proposal #245 (comment)

You don't need to do manual string manipulation in my proposal

That could work, but it might add more confusion for users by having two different identifiers. Not sure if it's helpful, but Xmonad has a fairly simple definition of a Workspace (see here), and just keeps each workspace in an ordered list, allowing it to be moved around in the list.

nikitabobko commented 3 months ago

I'm not familiar with Xmonad model. I follow the i3 model. In i3, workspaces are stored as Map<String, Workspace>. Workspaces are accessible by their names (names are unique identifiers. Names are keys in the Map)

I don't like the list model, because you can accidentally have duplicated names in the list. Besides, you need to communicate order of workspaces back to the user somehow. IMO, in the "name accessible paradigm", sorting by names works perfectly well. In the "list paradigm", order and names are independent.

"tag" in my proposal is just an additional non-unique string that is attached to the workspace. It is not an identifier, and you can't access workspace by tag. Changing the tag, keeps the workspace accessible by name (keyboard binding keeps working).

But I am open to the discussion. If you think that the Xmonad's "ordered list paradigm" is better, please enlighten me.

edgimar commented 3 months ago

Likewise, I don't know all the capabilities and limitations of the i3 model, but I imagine that it's possible to do the same things with either WM, just that some operations/features might be easier in one WM vs. the other. The XMonad model seems in some sense to be more 'object oriented' because it treats a Workspace as an entity that possesses a tag (name), layout (method for distributing windows), and stack (like a circular list of windows with a cursor). Each physical display is represented as a Screen which points to / possesses a Workspace, along with information that ties it to a particular display.

It seems that using a Map<String, Workspace> still requires some additional synchronized data structure to represent order -- either that, or you need to sort items in the map every time you want to move to the "next" or "previous" workspace. To me that seems more complex than just using a single ordered list, and there's no reason you couldn't enforce uniqueness on workspace names if desired at the time that a new workspace is created.

Communicating order would not be any easier if you change order by renaming -- assume some script performs a rename / swap, and later another script needs to know what the current order is -- it would need to query a list of names in this case (or mirror its own state of the set of names, which may be prone to error). Querying an ordered list of names is what would be needed for the "non-map" case, or if desired one could refer directly to current indices of workspaces in the list.

I hadn't thought about the desire to maintain keybindings to a fixed workspace, but that makes sense. I was actually thinking that it would be nice to be able to have keybindings that take me to a specific location in the workspace list (e.g. alt-1 takes me to index 1 of the list, no matter what workspace is located there). Maybe there would be a way to do both? (e.g. something like workspace 2 takes you to the workspace at index 2, and workspace "2" takes you to the workspace named 2, or maybe a special prefix for indices like idx:2)

nikitabobko commented 3 months ago

It seems that using a Map<String, Workspace> still requires some additional synchronized data structure to represent order

Binary search tree (BST) keeps keys sorted. Unfortunately, Swift doesn't offer BST out of the box, so I indeed have to manually sort workspaces every time users asks next/prev, but I can implement BST myself if it becomes necessary.

Querying an ordered list of names is what would be needed for the "non-map" case

When I said "communicating order back to the user" I meant the status icon in the top right corner (it shows only currently focused workspace). It's no question that order is easily representable when you list all of the workspaces (e.g. scripts)

it would be nice to be able to have keybindings that take me to a specific location in the workspace list

If we sticked to "list paradigm" that would probably be the solution, I agree.


So far, I think that we are talking roughly about the same things. You can think of list of workspaces as about Map<Int, Workspace>. Map<String, Workspace> is just a list, indexed by strings rather than ints.

One of strengths of your model that it's easier to understand, since there are fewer concepts, but once you introduce int index, our models start having the same number of concepts.

I see only two differences between our models:

  1. Implementation performance. If we consider "name-based" as the primary way of navigation then Map<String, Workspace is preferred (I designed the workspace navigation as such, I personally don't use next/prev); otherwise, "list paradigm" is preferred
  2. In my model, workspace string representation always starts with index/name/identifier in the status icon (which I think is a good thing). In your model, it becomes user's responsibility to keep order and string representation in sync (if users even care about this mapping)

Maybe my model would be easier to understand if I renamed "name" to "id"/"index"

nikitabobko commented 1 month ago

Closing in favor of #245