-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathi3swap.py
executable file
·171 lines (145 loc) · 6.1 KB
/
i3swap.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#!/usr/bin/env python
from typing import Literal, Optional
from sys import stderr
from argparse import ArgumentParser
from i3ipc import Connection, Con
def print_or_nodes(o: Con, depth: int = 0) -> str:
name = o.name or ""
print(
f"{' '*depth}{o.type}: {o.id} {name:.42} ({o.layout} with {len(o.nodes)} children)"
)
if o.nodes:
for n in o.nodes:
print_or_nodes(n, depth + 1)
def find_swapee(
focused_container: Con,
layout: Literal["horizontal", "vertical"],
level: Literal["highest", "lowest"],
neighbor: Literal["first", "last"],
swapee: Literal["first", "last"],
verbose: int = 0,
) -> Optional[Con]:
"""Return swapee depending on criteria
workspace: 94403059612560 2 (splith with 1 children)
con: 94403059613056 (splith with 1 children)
con: 94403059613520 (splith with 1 children)
con: 94403059613984 (splith with 1 children)
con: 94403058970656 (splith with 1 children)
con: 94403059981248 (splith with 1 children)
con: 94403060009888 (splith with 2 children) < common_parent with children(!) (splith, highest)
con: 94403060353904 (splitv with 2 children)
con: 94403059614448 Tilix: vim i3swap.py (splith with 0 children) < swapee (splith, highest, first)
con: 94403060624480 Tilix: ~ (splith with 0 children) < swapee (splith, highest, last)
con: 94403060104288 (splitv with 3 children)
con: 94403060153328 Tilix: IPython: home/syphdias (splith with 0 children)
con: 94403059853696 (splith with 2 children) < common_parent with children(!) (splith, lowest)
con: 94403060640272 (splitv with 2 children)
con: 94403060477552 Tilix: ~ (splith with 0 children) < swapee (splith, lowest, first)
con: 94403060027792 Tilix: ~ (splith with 0 children) < swapee (splith, lowest, last)
con: 94403060474048 (splitv with 3 children)
con: 94403060338064 Tilix: ~/git/private/i3-swap (splith with 0 children)
con: 94403060644688 Tilix: ~/git/private/i3-swap/i3swap.py --l (splith with 0 children) < focused_container
con: 94403060524208 Tilix: ~ (splith with 0 children)
con: 94403059044416 Tilix: ~ (splith with 0 children)
"""
if verbose >= 2:
print_or_nodes(focused_container.workspace())
if layout == "vertical":
layout = "splitv"
else:
layout = "splith"
current_container = focused_container
# find the parent container containing the focused container
# and the one we want to swap with
common_parent = None
while current_container.type != "workspace":
if current_container.layout == layout and len(current_container.nodes) > 1:
# we found the FIRST container with the wanted layout
# decend in the first node that we did not come from
common_parent = current_container
if level == "lowest":
break
if len(current_container.parent.nodes) > 1:
focused_half = current_container
current_container = current_container.parent
# return None if no common parent was found
if not common_parent:
common_parent = focused_half.parent
# we found the current parent, now we need to select a not focused neighbor
# pick either the first (default) or the last neighbor
neighbor_index = 0
if neighbor == "last":
neighbor_index = -1
swapee_neighbor = [node for node in common_parent.nodes if node != focused_half][
neighbor_index
]
# pick either the first (default) or the last container in the swapee half
swapee_index = 0
if swapee == "last":
swapee_index = -1
# we found the focused neighbor, now we need to decent into it
# to find the swapee (first container we find)
while len(swapee_neighbor.nodes) > 0:
swapee_neighbor = swapee_neighbor.nodes[swapee_index]
swapee = swapee_neighbor
if verbose >= 2:
print("common parent:", common_parent.id)
print(" focused half:", focused_half.id)
print(" swapee half:", swapee_neighbor.id)
print(" swapee:", swapee.id)
return swapee
def main(args) -> None:
i3 = Connection()
tree = i3.get_tree()
focused_container = tree.find_focused()
swapee = find_swapee(
focused_container,
layout=args.layout,
level=args.level,
neighbor=args.neighbor,
swapee=args.swapee,
verbose=args.verbose,
)
if not swapee:
if args.verbose:
print("Found no swapee. Nothing to swap.")
return
move_result = focused_container.command(f"swap container with con_id {swapee.id}")
if args.verbose:
print(move_result[0].ipc_data)
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument(
"--layout",
default="horizontal",
choices=["horizontal", "vertical"],
help="Swap horizontally or vertically",
)
parser.add_argument(
"--level",
default="highest",
choices=["highest", "lowest"],
help="Select which hierarchy level you want swap with",
)
parser.add_argument(
"--neighbor",
default="first",
choices=["first", "last"],
help="Take first or last to select the neighbor to swap with",
)
parser.add_argument(
"--swapee",
default="first",
choices=["first", "last"],
help="Take first or last container in the swapping container",
)
parser.add_argument(
"--verbose",
"-v",
action="count",
default=0,
)
args = parser.parse_args()
if args.verbose:
print(args)
main(args)