Skip to content

Instantly share code, notes, and snippets.

@alliefitter
Last active February 14, 2019 16:47
Show Gist options
  • Save alliefitter/a6d0cd4e8142d1628e164412b9cefd10 to your computer and use it in GitHub Desktop.
Save alliefitter/a6d0cd4e8142d1628e164412b9cefd10 to your computer and use it in GitHub Desktop.
Useful lil' script to page through i3wm workspaces.
from collections import defaultdict
from sys import argv
from typing import Dict
from i3ipc import Connection
'''
Pages left or right through workspaces in i3wm, and also moves windows to left or right workspaces.
Add the following lines to ~/.config/i3/config to use with Page Up and Page Down:
bindsym $mod+Next exec python /path/to/script/change_workspace.py next
bindsym $mod+Prior exec python /path/to/script/change_workspace.py previous
bindsym $mod+Shift+Next exec python /path/to/script/change_workspace.py move_next
bindsym $mod+Shift+Prior exec python /path/to/script/change_workspace.py move_previous
'''
def get_args(command: str):
return {
'next': ('workspace {workspace}', 1),
'previous': ('workspace {workspace}', -1),
'move_next': ('move container to workspace {workspace}; workspace {workspace}', 1),
'move_previous': ('move container to workspace {workspace}; workspace {workspace}', -1)
}.get(command)
def parse_workspaces(workspaces: Dict):
focused_output = None
focused_workspace = None
outputs = defaultdict(list)
for workspace in workspaces:
if workspace.get('focused') is True:
focused_output = workspace.get('output')
focused_workspace = workspace.get('num')
outputs[workspace['output']].append(workspace.get('num'))
return {
'outputs': outputs,
'focused_output': focused_output,
'focused_workspace': focused_workspace
}
def change_workspace(i3: Connection, command: str, modifier: int):
parsed_workspaces = parse_workspaces(i3.get_workspaces())
focused_workspace = parsed_workspaces.get('focused_workspace')
focused_output = parsed_workspaces.get('focused_output')
outputs = parsed_workspaces.get('outputs')
workspaces_for_focused_output = outputs.get(focused_output)
non_focused_outputs = {o: w for o, w in outputs.items() if o != focused_output}
occupied_workspaces = [w for o, ws in non_focused_outputs.items() for w in ws]
max_workspace_for_focused_output = max(workspaces_for_focused_output)
max_workspace = max(occupied_workspaces + workspaces_for_focused_output)
default = max_workspace_for_focused_output if modifier < 0 else max_workspace + 1
if modifier > 0:
max_workspace_for_focused_output += modifier
end_of_range = 0 if modifier < 0 else max_workspace + 1
success = False
for x in range(focused_workspace + modifier, end_of_range, modifier):
if success is False and (x in workspaces_for_focused_output or x not in occupied_workspaces):
success = i3.command(command.format(workspace=x))
success or i3.command(command.format(workspace=default))
if __name__ == '__main__':
change_workspace(Connection(), *get_args(argv[1]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment