Create a gist now

Instantly share code, notes, and snippets.

Enhanced back_and_forth for workspaces in i3.
#!/usr/bin/env python3
"""
Enhanced version of the workspace_back_and_forth of i3. Support a history of up
to 20 previously focused workspaces. See
https://www.reddit.com/r/i3wm/comments/40ncsn/window_back_and_forth_stack/
How to use:
* Put this file somewhere in your `$PATH`.
* In your `.i3/config` file, run the server on startup:
```
exec_always --no-startup-id "python workspace_back_and_forth_enhanced.py"
```
* In your `.i3/config`, use the program to manage workspace change, e.g.:
```
bindsym $mod+agrave exec "echo 10 | socat - UNIX-CONNECT:$XDG_RUNTIME_DIR/i3/i3-back-and-forth-enhanced.sock"
```
* Enjoy!
This script is under an MIT license and has been written by Phyks (Lucas
Verney - http://phyks.me/).
"""
import i3ipc
import os
import socket
from collections import deque
WORKSPACES_STACK = deque(maxlen=20)
# Create the Connection object that can be used to send commands and
# subscribe to events.
i3 = i3ipc.Connection()
def move_with_back_and_forth(target_workspace):
"""
Move to target workspace, handling enhanced back and forth.
"""
current_workspace = [i
for i in i3.get_workspaces() if i["focused"]][0].name
current_workspace = current_workspace.strip()
target_workspace = target_workspace.strip()
if target_workspace != current_workspace:
# Not on the target workspace, no back and forth move
# Push actual workspace and move
WORKSPACES_STACK.append(current_workspace)
return i3.command("workspace %s" % (target_workspace,))
# Else, try to use back and forth
try:
return i3.command("workspace %s" % (WORKSPACES_STACK.pop(),))
except IndexError:
# Stack is empty, do nothing
return
def listen_socket(sock):
"""
Socket listener
"""
while True:
# Wait for a connection
connection, client = sock.accept()
try:
while True:
chunk = connection.recv(16)
if chunk:
data = chunk.decode("utf-8")
move_with_back_and_forth(data)
else:
# No more data
break
finally:
# Close the connection
connection.close()
def main():
"""
Main
"""
# Find Unix socket dir
socket_dir = os.path.join(os.getenv("XDG_RUNTIME_DIR", "/tmp"), "i3")
if not os.path.isdir(socket_dir):
os.mkdir(socket_dir)
# Make sure socket does not already exists
socket_address = os.path.join(socket_dir,
"i3-back-and-forth-enhanced.sock")
try:
os.unlink(socket_address)
except OSError:
if os.path.exists(socket_address):
raise
# Create the socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(socket_address)
sock.listen(1)
# Start listener on socket
try:
listen_socket(sock)
finally:
sock.close()
try:
os.unlink(socket_address)
except OSError:
pass
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
pass
except:
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment