Last active
October 15, 2023 21:34
-
-
Save stecman/764da404d32edcdd7960457117da8c6e to your computer and use it in GitHub Desktop.
Scripts to make i3 more natural to use
This file contains hidden or 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
# Move workspace left and right (swap if conflicting) | |
bindsym $mod+Ctrl+Shift+Left exec $HOME/.i3/i3-swap.py left | |
bindsym $mod+Ctrl+Shift+Right exec $HOME/.i3/i3-swap.py right | |
# Make the next free workspace number, whatever that is | |
bindsym $mod+Ctrl+Return exec $HOME/.i3/i3-makews.py | |
# Rotate focus through visible workspaces on different monitors | |
bindsym $mod+x exec $HOME/.i3/i3-nextoutput.py |
This file contains hidden or 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/env python3 | |
""" | |
Move to the next unused workspace number, without needing to think | |
""" | |
import json | |
import subprocess | |
import sys | |
def get_workspaces(): | |
result = subprocess.run(["i3-msg", "-t", "get_workspaces"], check=True, capture_output=True) | |
return json.loads(result.stdout.decode()) | |
workspaces = get_workspaces() | |
# Find the first free workspace number (leaving workspace 0 for comms) | |
existing = set([ws['num'] for ws in workspaces]) | |
target = 2 | |
while target in existing: | |
target += 1 | |
subprocess.run(['i3-msg', 'workspace', str(target)], check=True) |
This file contains hidden or 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/env python3 | |
""" | |
Move all workspaces to the specified output | |
""" | |
import json | |
import subprocess | |
import sys | |
def get_workspaces(): | |
result = subprocess.run(["i3-msg", "-t", "get_workspaces"], check=True, capture_output=True) | |
return json.loads(result.stdout.decode()) | |
for ws in get_workspaces(): | |
subprocess.run(['i3-msg', '[workspace="%s"]' % ws['num'], 'move', 'workspace', 'to', 'output', sys.argv[1]], check=True) | |
This file contains hidden or 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/env python3 | |
""" | |
Focus the visible workspace on the next output | |
A reliable way to switch to the other monitor you're looking at, without | |
needing to prime or keep track of the "back_and_forth" buffer. | |
""" | |
import json | |
import subprocess | |
import sys | |
def get_workspaces(): | |
result = subprocess.run(["i3-msg", "-t", "get_workspaces"], check=True, capture_output=True) | |
return json.loads(result.stdout.decode()) | |
display_workspace = {} | |
current_display = None | |
for ws in get_workspaces(): | |
if ws['visible']: | |
display_workspace[ws['output']] = ws['num'] | |
if ws['focused']: | |
current_display = ws['output'] | |
displays = list(display_workspace.keys()) | |
current_index = displays.index(current_display) | |
next_index = (current_index + 1) % len(displays) | |
next_display = displays[next_index] | |
next_ws = display_workspace[next_display] | |
subprocess.run(['i3-msg', 'workspace', str(next_ws)], check=True) | |
This file contains hidden or 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/env python3 | |
""" | |
Increment or decrement the workspace number, shifting other workspaces out of the way | |
""" | |
import argparse | |
import json | |
import subprocess | |
import sys | |
def rename_workspace(name, new_name): | |
subprocess.run(["i3-msg", "rename", "workspace", name, "to", new_name], check=True) | |
def get_workspaces(): | |
result = subprocess.run(["i3-msg", "-t", "get_workspaces"], check=True, capture_output=True) | |
return json.loads(result.stdout.decode()) | |
parser = argparse.ArgumentParser() | |
parser.add_argument("direction") | |
args = parser.parse_args() | |
workspaces = get_workspaces() | |
# Find focused workspace | |
for index, ws in enumerate(workspaces): | |
if ws['focused']: | |
focused = ws['num'] | |
break | |
# Get next workspace number | |
if args.direction == 'left': | |
target = focused - 1 | |
if target < 0: | |
print("Can't move any further left") | |
sys.exit(1) | |
elif args.direction == 'right': | |
target = focused + 1 | |
else: | |
raise AttributeError("Direction must be 'left' or 'right'. Got '%s'" % args.direction) | |
# Find any conflicting workspace to swap with | |
conflicting = [ws for ws in workspaces if ws['name'] == str(target)] | |
if len(conflicting): | |
# Swap with conflicting workspace | |
rename_workspace(str(target), 'tmp') | |
rename_workspace(str(focused), str(target)) | |
rename_workspace('tmp', str(focused)) | |
else: | |
# Just rename as there's no conflict | |
rename_workspace(str(focused), str(target)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment