Created
January 20, 2023 16:21
-
-
Save erenon/024679fecf849454f54d245537f3a783 to your computer and use it in GitHub Desktop.
Sway sessions à la tmux
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set $mode_session session [s]elect [r]ename [f]latten | |
bindsym $mod+s mode "$mode_session" | |
mode "$mode_session" { | |
bindsym s exec --no-startup-id ~/bin/way_select_session.py, mode "default" | |
bindsym r exec --no-startup-id ~/bin/way_rename_workspace.py, mode "default" | |
bindsym f exec --no-startup-id ~/bin/way_flatten_sessions.py, mode "default" | |
bindsym Escape mode "default" | |
bindsym Return mode "default" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# Assign each workspace the lowest number still available. | |
import json | |
import subprocess | |
# do not move these workspaces | |
protected_workspaces = set([9]) | |
renames = [] | |
index = 1 | |
workspaces = subprocess.check_output(["/usr/bin/swaymsg", "-r", "-t", "get_workspaces"]) | |
workspaces = json.loads(workspaces) | |
for ws in workspaces: | |
if ws["num"] in protected_workspaces: | |
continue | |
session = ws["name"].partition(":")[2] | |
if session: | |
renames.append((ws["name"], f"{index}:{session}")) | |
else: | |
renames.append((ws["name"], f"{index}")) | |
index = index + 1 | |
while index in protected_workspaces: | |
index = index + 1 | |
for rn in renames: | |
subprocess.call(["/usr/bin/swaymsg", "rename", "workspace", rn[0], "to", rn[1]]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# Prompts for a name and renames the current workspace to it, ESC cancels. | |
# It preserves the number of the workspace - therefore the ordering. | |
import json | |
import subprocess | |
def ui_input(prompt): | |
s = subprocess.check_output(["/usr/bin/dmenu", "-b", "-p", prompt], input="", encoding="ascii") | |
return s.strip() | |
def focused_workspace_num(): | |
workspaces = subprocess.check_output(["/usr/bin/swaymsg", "-r", "-t", "get_workspaces"]) | |
workspaces = json.loads(workspaces) | |
for ws in workspaces: | |
if ws["focused"]: | |
return ws["num"] | |
return "" | |
name = ui_input("rename workspace") | |
num = focused_workspace_num() | |
subprocess.check_output(["/usr/bin/swaymsg", "rename", "workspace", "to", f"{num}:{name}"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# Prompts for a workspace name, ESC cancels. | |
# If a name is given, it looks for the selected workspace. | |
# If a workspace is found, it moves that workspace, and every | |
# workspace to the right -- until a different named-workspace is found -- | |
# to the beginning, and moves every other workspace to the end, | |
# starting at workspace number 10. | |
# If no workspace matches the given name, it will be created, | |
# and every other workspace will be moved to the end. | |
# It does not touch workspaces given in `protected_workspaces`. | |
import json | |
import subprocess | |
# do not move these workspaces | |
protected_workspaces = set([1, 9]) | |
def ui_input(prompt, selection): | |
s = subprocess.check_output(["/usr/bin/dmenu", "-b", "-p", prompt], input=selection, encoding="ascii") | |
return s.strip() | |
def strip_before(s, d): | |
a,_,b = s.partition(d) | |
return b or a | |
def selected_range(workspaces, s): | |
first = 0 | |
for ws in workspaces: | |
if ws["name"] == s: | |
break | |
first += 1 | |
last = first + 1 | |
for ws in workspaces[last:]: | |
if ':' in ws["name"]: | |
break | |
last += 1 | |
return first, last | |
def renumber(i, ws): | |
tag = ws["name"].partition(":")[2] | |
return f"{i}:{tag}" if tag else str(i) | |
# select a session, find the range of workspaces that belongs to it | |
workspaces = subprocess.check_output(["/usr/bin/swaymsg", "-r", "-t", "get_workspaces"]) | |
workspaces = json.loads(workspaces) | |
sessions = [] | |
for ws in workspaces: | |
session = ws["name"].partition(":")[2] | |
if session: | |
sessions.append(ws["name"]) | |
selected_session = ui_input("select session", "\n".join(sessions)) | |
first, last = selected_range(workspaces, selected_session) | |
# move selected worspaces to si..., deselected workspaces to di... | |
si = 1 | |
di = max(last-first, 10) | |
renames = [] | |
for (i, ws) in enumerate(workspaces): | |
if ws["num"] in protected_workspaces: | |
continue | |
if first <= i and i < last: | |
while si in protected_workspaces: | |
si += 1 | |
renames.append((ws["name"], renumber(si, ws))) | |
si += 1 | |
else: | |
while di in protected_workspaces: | |
di += 1 | |
if len(renames) == 0 and not ":" in ws["name"]: | |
# first deselected workspace is unnamed, name it "main" to avoid | |
# merging it with the selected session | |
renames.append((ws["name"], str(di) + ":main")) | |
else: | |
renames.append((ws["name"], renumber(di, ws))) | |
di += 1 | |
# move them to tmp names to avoid clashes | |
for (src, dst) in renames: | |
subprocess.call(["/usr/bin/swaymsg", "rename", "workspace", src, "to", f"_{dst}"]) | |
# move them back | |
for (_, dst) in renames: | |
subprocess.call(["/usr/bin/swaymsg", "rename", "workspace", f"_{dst}", "to", dst]) | |
# finally, jump to the leading workspace if the selected session | |
# (this also creates the session if it is a new one) | |
tag = strip_before(selected_session, ":") | |
i = 1 | |
while i in protected_workspaces: | |
i += 1 | |
subprocess.call(["/usr/bin/swaymsg", "--", "workspace", "--no-auto-back-and-forth", f"{i}:{tag}"]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment