Advertisement
Guest User

Untitled

a guest
Jan 26th, 2020
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.97 KB | None | 0 0
  1. #! /usr/bin/env python2
  2. #
  3. # Written by Filippo Bonazzi (2016)
  4. #
  5. # This program is free software: you can redistribute it and / or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. #
  18. ##############################################################################
  19. #
  20. # Read the JSON representation of the list of workspaces, get the focused
  21. # workspace and open the first empty workspace available on the same output.
  22. #
  23. # We convert JSON directly to Python data by exploiting the similar syntax,
  24. # we just need to convert "true" and "false" to "True" and "False". This is
  25. # kind of a hack but it works fine for this short script.
  26.  
  27. import subprocess
  28. import argparse
  29. import sys
  30. from operator import itemgetter
  31. import ast
  32. import re
  33.  
  34. # Parse arguments
  35. # A bit overkill for a single option maybe
  36. parser = argparse.ArgumentParser(
  37.     description="Launch a new i3 workspace on the active output.",
  38.     epilog="Designed to run on a dual-monitor setup with odd workspaces "
  39.     "on the left and even workspaces on the right.")
  40. # Fill holes in the numbering
  41. parser.add_argument("-f", "--fill-holes", action="store_true",
  42.                     help="Fill holes in the workspace numbering on the active "
  43.                     "output [Default: False]")
  44. args = parser.parse_args()
  45.  
  46. try: # My own changes
  47.     # Detect if user is running single- or multi-screen config
  48.     screens = subprocess.check_output(["i3-msg", "-t", "get_outputs"])
  49. except subprocess.CalledProcessError as e:
  50.     # Print the error and exit
  51.     print e.output
  52.     print "Could not get number of active monitors from xrandr. Aborting..."
  53.     sys.exit(1)
  54.  
  55.  
  56. try:
  57.     line = subprocess.check_output(["i3-msg", "-t", "get_workspaces"])
  58. except subprocess.CalledProcessError as e:
  59.     # Print the error and exit
  60.     print e.output
  61.     print "Could not get list of workspaces from i3-msg. Aborting..."
  62.     sys.exit(1)
  63.  
  64. # Replace "false"/"true" with "False"/"True" to "convert" JSON to Python
  65. workspaces_str = line.replace("false", "False").replace("true", "True")
  66. # Safely evaluate the data expression. Get a sorted list of workspaces
  67. workspaces = sorted(ast.literal_eval(workspaces_str), key=itemgetter("num"))
  68. workspace_nos = [w["num"] for w in workspaces]
  69.  
  70. # find out if user is using multi-monitor setup
  71. # screens contains info about active outputs - find out how many
  72. # it is expected that user is using 1 or 2 screens
  73. dual_monitor = len(re.findall(r'"active":true,', str(screens))) - 1 # -1 is for it to become 0 or 1 (bool)
  74.  
  75. # num_active_monitors = int(re.split(r'\\n', str(screens))[0][-1]) - 1 # 0 if 1 mon, 1 if 2 monitors so it can be used as boolean
  76.  
  77. # Find the focused workspace and save its output
  78. for w in workspaces:
  79.     if w["focused"]:
  80.         focused_output = w["output"]
  81.         focused_workspace = w["num"]
  82.         break
  83.  
  84. if not dual_monitor: # if single-monitor
  85.     if args.fill_holes:
  86.         # Find the lowest free workspace on the focused output
  87.         # Find the lowest workspace on the focused output
  88.         # Begin with one and search until you find non-taken workspace number
  89.         new = 1
  90.         # While the workspace number is taken, increment it by 1
  91.         while new in workspace_nos:
  92.             new += 1 # this is modified for a single monitor
  93.     else:
  94.         # Find the highest workspace on the focused output and increase it by 1
  95.         highest = 0
  96.         for w in workspaces:
  97.             if w["output"] == focused_output and w["num"] > highest:
  98.                 highest = w["num"]
  99.         new = highest + 1
  100. else: # if dual-monitor
  101.     if args.fill_holes:
  102.         # Find the lowest free workspace on the focused output
  103.         # Find the lowest workspace on the focused output
  104.         new = focused_workspace % 2
  105.         # Workspaces start from 1, not from 0
  106.         if new == 0:
  107.             new = 2
  108.         # While the workspace number is taken, increment it by 2
  109.         while new in workspace_nos:
  110.             new += 2 # this is the original line
  111.     else:
  112.         # Find the highest workspace on the focused output and increase it by 2
  113.         highest = 0
  114.         for w in workspaces:
  115.             if w["output"] == focused_output and w["num"] > highest:
  116.                 highest = w["num"]
  117.         new = highest + 2
  118.  
  119. try:
  120.     subprocess.check_call(["i3-msg", "workspace", str(new)])
  121. except subprocess.CalledProcessError as e:
  122.     # Print the error and exit
  123.     print e
  124.     print "Could not open workspace {}. Aborting...".format(new)
  125.     sys.exit(1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement