i3-skip 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- i3_skip-0.1.0/PKG-INFO +51 -0
- i3_skip-0.1.0/README.md +42 -0
- i3_skip-0.1.0/i3_skip/__init__.py +1 -0
- i3_skip-0.1.0/i3_skip/main.py +126 -0
- i3_skip-0.1.0/i3_skip.egg-info/PKG-INFO +51 -0
- i3_skip-0.1.0/i3_skip.egg-info/SOURCES.txt +10 -0
- i3_skip-0.1.0/i3_skip.egg-info/dependency_links.txt +1 -0
- i3_skip-0.1.0/i3_skip.egg-info/entry_points.txt +2 -0
- i3_skip-0.1.0/i3_skip.egg-info/requires.txt +1 -0
- i3_skip-0.1.0/i3_skip.egg-info/top_level.txt +1 -0
- i3_skip-0.1.0/pyproject.toml +18 -0
- i3_skip-0.1.0/setup.cfg +4 -0
i3_skip-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: i3-skip
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: i3 focus motion that treats tabbed/stacked containers as one window
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.8
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: i3ipc>=2.2
|
|
9
|
+
|
|
10
|
+
# i3-skip
|
|
11
|
+
i3 focus motion that treats a tabbed or stacked container as a single window rather than navigating between tabs.
|
|
12
|
+
|
|
13
|
+
AI-generated and unreviewed.
|
|
14
|
+
|
|
15
|
+
## Motivation
|
|
16
|
+
I want two separate forms of motions. One for within tabbed ontainers, the other between visible windows.
|
|
17
|
+
I guess this is because I don't want to futz with my choices for stacked windows while i move around.
|
|
18
|
+
Also, it does kind of make sense to move between what is visible.
|
|
19
|
+
|
|
20
|
+
This program is a companian to i3-glue which glues together certain windows into tabbed containers.
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
i3-skip left # focus the window/group to the left, skipping any tabs inside
|
|
26
|
+
i3-skip right
|
|
27
|
+
i3-skip up
|
|
28
|
+
i3-skip down
|
|
29
|
+
i3-skip toggle # cycle focus within the current tabbed/stacked group
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Bind your motion keys to the directional forms and one key to `toggle`, e.g. in
|
|
33
|
+
your i3 config:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
bindsym $mod+h exec i3-skip left
|
|
37
|
+
bindsym $mod+l exec i3-skip right
|
|
38
|
+
bindsym $mod+k exec i3-skip up
|
|
39
|
+
bindsym $mod+j exec i3-skip down
|
|
40
|
+
bindsym $mod+Tab exec i3-skip toggle
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Flags
|
|
44
|
+
|
|
45
|
+
- `--debug` — print the i3 commands sent
|
|
46
|
+
|
|
47
|
+
## Install (editable, via pipx)
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
pipx install i3-skip
|
|
51
|
+
```
|
i3_skip-0.1.0/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# i3-skip
|
|
2
|
+
i3 focus motion that treats a tabbed or stacked container as a single window rather than navigating between tabs.
|
|
3
|
+
|
|
4
|
+
AI-generated and unreviewed.
|
|
5
|
+
|
|
6
|
+
## Motivation
|
|
7
|
+
I want two separate forms of motions. One for within tabbed ontainers, the other between visible windows.
|
|
8
|
+
I guess this is because I don't want to futz with my choices for stacked windows while i move around.
|
|
9
|
+
Also, it does kind of make sense to move between what is visible.
|
|
10
|
+
|
|
11
|
+
This program is a companian to i3-glue which glues together certain windows into tabbed containers.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
i3-skip left # focus the window/group to the left, skipping any tabs inside
|
|
17
|
+
i3-skip right
|
|
18
|
+
i3-skip up
|
|
19
|
+
i3-skip down
|
|
20
|
+
i3-skip toggle # cycle focus within the current tabbed/stacked group
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Bind your motion keys to the directional forms and one key to `toggle`, e.g. in
|
|
24
|
+
your i3 config:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
bindsym $mod+h exec i3-skip left
|
|
28
|
+
bindsym $mod+l exec i3-skip right
|
|
29
|
+
bindsym $mod+k exec i3-skip up
|
|
30
|
+
bindsym $mod+j exec i3-skip down
|
|
31
|
+
bindsym $mod+Tab exec i3-skip toggle
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Flags
|
|
35
|
+
|
|
36
|
+
- `--debug` — print the i3 commands sent
|
|
37
|
+
|
|
38
|
+
## Install (editable, via pipx)
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
pipx install i3-skip
|
|
42
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
i3-skip — i3 focus motion that treats tabbed/stacked containers as one window.
|
|
4
|
+
|
|
5
|
+
AI-generated. You probably don't want to use it. And yet it exists.
|
|
6
|
+
|
|
7
|
+
i3's directional focus walks *into* a tabbed or stacked container, tab by tab,
|
|
8
|
+
because a container's orientation is also its navigation axis. i3-skip makes
|
|
9
|
+
left/right/up/down step *over* such a container as a single unit, and gives you
|
|
10
|
+
a separate command to move *within* it.
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
i3-skip left | right | up | down directional focus, skipping groups
|
|
14
|
+
i3-skip toggle cycle focus within the current group
|
|
15
|
+
|
|
16
|
+
Bind your motion keys to the directional form, and one key to `toggle`.
|
|
17
|
+
|
|
18
|
+
Flags:
|
|
19
|
+
--debug print the i3 commands sent
|
|
20
|
+
|
|
21
|
+
Runtime deps: i3 (via i3ipc).
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import sys
|
|
25
|
+
|
|
26
|
+
import i3ipc
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
DEBUG = False
|
|
30
|
+
DIRECTIONS = ("left", "right", "up", "down")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def die(msg, code=1):
|
|
34
|
+
print(f"i3-skip: {msg}", file=sys.stderr)
|
|
35
|
+
sys.exit(code)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def dbg(msg):
|
|
39
|
+
if DEBUG:
|
|
40
|
+
print(f"[i3-skip:debug] {msg}", file=sys.stderr, flush=True)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def command(conn, cmd):
|
|
44
|
+
dbg(f"i3-msg: {cmd}")
|
|
45
|
+
for reply in conn.command(cmd):
|
|
46
|
+
if not reply.success:
|
|
47
|
+
print(f"i3-skip: command failed: {cmd!r}: {reply.error}",
|
|
48
|
+
file=sys.stderr)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def group_of(con):
|
|
52
|
+
"""Nearest tabbed/stacked ancestor of `con` — the container to treat as a
|
|
53
|
+
single unit — or None if `con` is not inside one."""
|
|
54
|
+
node = con
|
|
55
|
+
while node is not None:
|
|
56
|
+
if node.layout in ("tabbed", "stacked"):
|
|
57
|
+
return node
|
|
58
|
+
node = node.parent
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def visible_leaf(con):
|
|
63
|
+
"""A focusable leaf for `con`: itself if it is a window, else its first."""
|
|
64
|
+
if con.window:
|
|
65
|
+
return con
|
|
66
|
+
leaves = con.leaves()
|
|
67
|
+
return leaves[0] if leaves else con
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def child_holding(group, target_id):
|
|
71
|
+
"""Index of the group's child that contains the window `target_id`."""
|
|
72
|
+
for i, child in enumerate(group.nodes):
|
|
73
|
+
if child.id == target_id or any(d.id == target_id
|
|
74
|
+
for d in child.descendants()):
|
|
75
|
+
return i
|
|
76
|
+
return 0
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def cmd_toggle(conn):
|
|
80
|
+
"""Cycle focus to the next window within the current group (wraps)."""
|
|
81
|
+
focused = conn.get_tree().find_focused()
|
|
82
|
+
group = group_of(focused)
|
|
83
|
+
if group is None or len(group.nodes) < 2:
|
|
84
|
+
dbg("not in a multi-window group; nothing to toggle")
|
|
85
|
+
return
|
|
86
|
+
i = child_holding(group, focused.id)
|
|
87
|
+
nxt = group.nodes[(i + 1) % len(group.nodes)]
|
|
88
|
+
command(conn, f"[con_id={visible_leaf(nxt).id}] focus")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def cmd_skip(conn, direction):
|
|
92
|
+
"""Directional focus that skips over the focused window's group. Focusing
|
|
93
|
+
the whole group container first makes i3's `focus <dir>` step over its
|
|
94
|
+
internal tabs instead of walking through them."""
|
|
95
|
+
focused = conn.get_tree().find_focused()
|
|
96
|
+
group = group_of(focused)
|
|
97
|
+
if group is not None:
|
|
98
|
+
command(conn, f"[con_id={group.id}] focus")
|
|
99
|
+
command(conn, f"focus {direction}")
|
|
100
|
+
# `focus <dir>` with nowhere to go leaves a non-leaf container focused;
|
|
101
|
+
# drop back into its visible window so focus is always on a real window.
|
|
102
|
+
now = conn.get_tree().find_focused()
|
|
103
|
+
if now is not None and not now.window:
|
|
104
|
+
command(conn, f"[con_id={visible_leaf(now).id}] focus")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def main():
|
|
108
|
+
global DEBUG
|
|
109
|
+
argv = sys.argv[1:]
|
|
110
|
+
if "--debug" in argv:
|
|
111
|
+
DEBUG = True
|
|
112
|
+
argv = [a for a in argv if a != "--debug"]
|
|
113
|
+
if not argv:
|
|
114
|
+
die("usage: i3-skip {left|right|up|down|toggle}")
|
|
115
|
+
|
|
116
|
+
cmd = argv[0]
|
|
117
|
+
conn = i3ipc.Connection()
|
|
118
|
+
if cmd == "toggle":
|
|
119
|
+
return cmd_toggle(conn)
|
|
120
|
+
if cmd in DIRECTIONS:
|
|
121
|
+
return cmd_skip(conn, cmd)
|
|
122
|
+
die(f"unknown command {cmd!r}: use {'|'.join(DIRECTIONS)}|toggle")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
main()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: i3-skip
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: i3 focus motion that treats tabbed/stacked containers as one window
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.8
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: i3ipc>=2.2
|
|
9
|
+
|
|
10
|
+
# i3-skip
|
|
11
|
+
i3 focus motion that treats a tabbed or stacked container as a single window rather than navigating between tabs.
|
|
12
|
+
|
|
13
|
+
AI-generated and unreviewed.
|
|
14
|
+
|
|
15
|
+
## Motivation
|
|
16
|
+
I want two separate forms of motions. One for within tabbed ontainers, the other between visible windows.
|
|
17
|
+
I guess this is because I don't want to futz with my choices for stacked windows while i move around.
|
|
18
|
+
Also, it does kind of make sense to move between what is visible.
|
|
19
|
+
|
|
20
|
+
This program is a companian to i3-glue which glues together certain windows into tabbed containers.
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
i3-skip left # focus the window/group to the left, skipping any tabs inside
|
|
26
|
+
i3-skip right
|
|
27
|
+
i3-skip up
|
|
28
|
+
i3-skip down
|
|
29
|
+
i3-skip toggle # cycle focus within the current tabbed/stacked group
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Bind your motion keys to the directional forms and one key to `toggle`, e.g. in
|
|
33
|
+
your i3 config:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
bindsym $mod+h exec i3-skip left
|
|
37
|
+
bindsym $mod+l exec i3-skip right
|
|
38
|
+
bindsym $mod+k exec i3-skip up
|
|
39
|
+
bindsym $mod+j exec i3-skip down
|
|
40
|
+
bindsym $mod+Tab exec i3-skip toggle
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Flags
|
|
44
|
+
|
|
45
|
+
- `--debug` — print the i3 commands sent
|
|
46
|
+
|
|
47
|
+
## Install (editable, via pipx)
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
pipx install i3-skip
|
|
51
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
i3_skip/__init__.py
|
|
4
|
+
i3_skip/main.py
|
|
5
|
+
i3_skip.egg-info/PKG-INFO
|
|
6
|
+
i3_skip.egg-info/SOURCES.txt
|
|
7
|
+
i3_skip.egg-info/dependency_links.txt
|
|
8
|
+
i3_skip.egg-info/entry_points.txt
|
|
9
|
+
i3_skip.egg-info/requires.txt
|
|
10
|
+
i3_skip.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
i3ipc>=2.2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
i3_skip
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [ "setuptools>=68.0",]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "i3-skip"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "i3 focus motion that treats tabbed/stacked containers as one window"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
dependencies = [ "i3ipc>=2.2",]
|
|
13
|
+
|
|
14
|
+
[project.scripts]
|
|
15
|
+
i3-skip = "i3_skip.main:main"
|
|
16
|
+
|
|
17
|
+
[tool.setuptools]
|
|
18
|
+
packages = [ "i3_skip",]
|
i3_skip-0.1.0/setup.cfg
ADDED