Last active
February 22, 2021 22:37
-
-
Save Phyks/4fbc2572dcc5eed96caa to your computer and use it in GitHub Desktop.
Enhanced back_and_forth for workspaces in i3.
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/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: | |
raise | |
pass | |
except: | |
raise | |
pass |
Indeed, I updated the script on my side but completely forgot about this gist. I'll update a fixed version of the script right away.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you comment on what version you are using with
i3ipc
?I am currently getting
TypeError: 'WorkspaceReply' object is not subscriptable
when trying to iterate over the list returned byget_workspaces()
.It seems the script could be fixed following this issue.