This commit is contained in:
Ryan Dwyer 2018-10-29 23:28:23 +10:00
parent 1c2a356dcf
commit 791c216cb8
6 changed files with 450 additions and 0 deletions

112
sway-save-tree/sway-save-tree Executable file
View file

@ -0,0 +1,112 @@
#!/usr/bin/env python
import argparse
import json
import re
import subprocess
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--socket', help='Socket')
parser.add_argument('-w', '--workspace',
help='Specifies the workspace that should be dumped, e.g. 1. ' \
'This can either be a name or the number of a workspace.')
parser.add_argument('-o', '--output',
help='Specifies the output that should be dumped, e.g. LVDS-1')
parser.add_argument('-v', '--version', action='store_true', help='Version')
args = parser.parse_args()
if args.version:
print('sway-save-tree version %s' % '1.0.0')
exit(0)
cmd = ['swaymsg', '-t', 'get_tree']
if args.socket:
cmd.concat(['-s', args.socket])
result = subprocess.check_output(cmd)
tree = json.loads(result)
def filter_tree(tree, args):
if args.workspace:
for output in tree['nodes']:
for ws in output['nodes']:
if ws['name'] == args.workspace:
return ws
if args.output:
for output in tree['nodes']:
if output['name'] == args.output:
return outut
# Focused workspace
output = next(o for o in tree['nodes'] if o['id'] == tree['focus'][0])
ws = next(ws for ws in output['nodes'] if ws['id'] == output['focus'][0])
return ws
root = filter_tree(tree, args)
def prop(node, *keys):
for key in keys:
try:
node = node[key]
except KeyError:
return None
return re.escape('^%s$' % node)
def convert_children(nodes):
children = []
for node in nodes:
child = {}
has_children = len(node['nodes'])
if has_children:
child['_comment'] = '%s container with %i children' % (
node['layout'], len(node['nodes']))
child['border'] = node['border']
child['current_border_width'] = node['current_border_width']
child['floating'] = node['floating'] if 'floating' in node else 'auto_off'
if has_children:
child['layout'] = node['layout']
child['geometry'] = node['rect']
child['name'] = node['name']
child['percent'] = round(node['percent'], 2)
child['swallows'] = {}
child['swallows']['app_id'] = prop(node, ('app_id'))
child['swallows']['class'] = prop(node, ('window_properties', 'class'))
child['swallows']['instance'] = prop(node, ('window_properties', 'instance'))
child['swallows']['title'] = prop(node, ('name'))
child['swallows']['transient_for'] = prop(node, ('window_properties', 'transient_for'))
child['type'] = node['type']
if has_children:
child['nodes'] = convert_children(node['nodes'])
if len(node['floating_nodes']):
child['floating_nodes'] = convert_children(node['floating_nodes'])
if 'marks' in node and len(node['marks']):
child['marks'] = node['marks']
if 'fullscreen_mode' in node and node['fullscreen_mode']:
child['fullscreen_mode'] = True
children.append(child)
return children
# Build new tree containing only the properties we want
newtree = convert_children(root['nodes'])
# Convert it to a JSON string. The root children list should not be an array,
# but rather concatenated json objects.
output = ''
for node in newtree:
output += json.dumps(node, indent=4) + "\n"
output = output.rstrip()
# Replace the _comment element with an actual comment
output = re.sub(r'"_comment": "(.*?)",', '// \\1', output)
# Comment the swallows criteria
output = re.sub(r'("app_id":)', '// \\1', output)
output = re.sub(r'("class":)', '// \\1', output)
output = re.sub(r'("instance":)', '// \\1', output)
output = re.sub(r'("title":)', '// \\1', output)
output = re.sub(r'("transient_for":)', '// \\1', output)
print('// vim:ts=4:sw=4:et')
print(output)