mirror of
https://github.com/vincentbernat/i3wm-configuration.git
synced 2025-07-10 18:24:22 +02:00
i3-companion: blacken the code
This commit is contained in:
parent
0984436348
commit
0e88b0f545
1 changed files with 73 additions and 67 deletions
118
bin/i3-companion
118
bin/i3-companion
|
@ -24,13 +24,16 @@ logger = logging.getLogger("i3-companion")
|
||||||
|
|
||||||
def on(*events):
|
def on(*events):
|
||||||
"""Tag events that should be provided to the function."""
|
"""Tag events that should be provided to the function."""
|
||||||
|
|
||||||
def decorator(fn):
|
def decorator(fn):
|
||||||
@functools.wraps(fn)
|
@functools.wraps(fn)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
return fn(*args, **kwargs)
|
return fn(*args, **kwargs)
|
||||||
|
|
||||||
on.functions = getattr(on, "functions", {})
|
on.functions = getattr(on, "functions", {})
|
||||||
on.functions[fn] = events
|
on.functions[fn] = events
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +49,8 @@ async def notify(i3, **kwargs):
|
||||||
summary="",
|
summary="",
|
||||||
actions=[],
|
actions=[],
|
||||||
hints={},
|
hints={},
|
||||||
expire_timeout=5000)
|
expire_timeout=5000,
|
||||||
|
)
|
||||||
parameters.update(kwargs)
|
parameters.update(kwargs)
|
||||||
return await interface.Notify(**parameters)
|
return await interface.Notify(**parameters)
|
||||||
|
|
||||||
|
@ -70,14 +74,10 @@ application_icons = {
|
||||||
"steam": "",
|
"steam": "",
|
||||||
"vbeterm": "",
|
"vbeterm": "",
|
||||||
"zathura": "",
|
"zathura": "",
|
||||||
"zoom": ""
|
"zoom": "",
|
||||||
}
|
}
|
||||||
application_icons_nomatch = ""
|
application_icons_nomatch = ""
|
||||||
application_icons_alone = {
|
application_icons_alone = {application_icons[k] for k in {"vbeterm"}}
|
||||||
application_icons[k] for k in {
|
|
||||||
"vbeterm"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@on(Event.WINDOW_MOVE, Event.WINDOW_NEW, Event.WINDOW_CLOSE)
|
@on(Event.WINDOW_MOVE, Event.WINDOW_NEW, Event.WINDOW_CLOSE)
|
||||||
|
@ -89,8 +89,7 @@ async def workspace_rename(i3, event):
|
||||||
|
|
||||||
def application_icon(window):
|
def application_icon(window):
|
||||||
"""Get application icon for a window."""
|
"""Get application icon for a window."""
|
||||||
for attr in ('window_instance',
|
for attr in ("window_instance", "window_class"):
|
||||||
'window_class'):
|
|
||||||
name = getattr(window, attr, None)
|
name = getattr(window, attr, None)
|
||||||
if name is None:
|
if name is None:
|
||||||
continue
|
continue
|
||||||
|
@ -113,7 +112,7 @@ async def workspace_rename(i3, event):
|
||||||
logger.debug(f"rename workspace {workspace.num}")
|
logger.debug(f"rename workspace {workspace.num}")
|
||||||
command = f'rename workspace "{workspace.name}" to "{new_name}"'
|
command = f'rename workspace "{workspace.name}" to "{new_name}"'
|
||||||
commands.append(command)
|
commands.append(command)
|
||||||
await i3.command(';'.join(commands))
|
await i3.command(";".join(commands))
|
||||||
|
|
||||||
|
|
||||||
async def _new_workspace(i3):
|
async def _new_workspace(i3):
|
||||||
|
@ -121,7 +120,7 @@ async def _new_workspace(i3):
|
||||||
workspace_nums = {w.num for w in workspaces}
|
workspace_nums = {w.num for w in workspaces}
|
||||||
max_num = max(workspace_nums)
|
max_num = max(workspace_nums)
|
||||||
available = (set(range(1, max_num + 2)) - workspace_nums).pop()
|
available = (set(range(1, max_num + 2)) - workspace_nums).pop()
|
||||||
logger.info(f'create new workspace number {available}')
|
logger.info(f"create new workspace number {available}")
|
||||||
await i3.command(f'workspace number "{available}"')
|
await i3.command(f'workspace number "{available}"')
|
||||||
return available
|
return available
|
||||||
|
|
||||||
|
@ -140,17 +139,11 @@ async def new_workspace(i3, event):
|
||||||
|
|
||||||
# Move the window to this workspace
|
# Move the window to this workspace
|
||||||
if event == "move-to-new-workspace":
|
if event == "move-to-new-workspace":
|
||||||
await current.command(f'move container to workspace '
|
await current.command(f"move container to workspace " f'number "{num}"')
|
||||||
f'number "{num}"')
|
|
||||||
|
|
||||||
|
|
||||||
exclusive_apps = {
|
exclusive_apps = {"emacs", "firefox"}
|
||||||
"emacs",
|
intrusive_apps = {"vbeterm"}
|
||||||
"firefox"
|
|
||||||
}
|
|
||||||
intrusive_apps = {
|
|
||||||
"vbeterm"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@on(Event.WINDOW_NEW)
|
@on(Event.WINDOW_NEW)
|
||||||
|
@ -163,12 +156,14 @@ async def worksplace_exclusive(i3, event):
|
||||||
"""Can this new window intrude any workspace?"""
|
"""Can this new window intrude any workspace?"""
|
||||||
if w.floating in {"auto_on", "user_on"}:
|
if w.floating in {"auto_on", "user_on"}:
|
||||||
return True
|
return True
|
||||||
if w.ipc_data['window_type'] not in {"normal", "splash", "unknown"}:
|
if w.ipc_data["window_type"] not in {"normal", "splash", "unknown"}:
|
||||||
return True
|
return True
|
||||||
if w.sticky:
|
if w.sticky:
|
||||||
return True
|
return True
|
||||||
ids = {s is not None and s.lower() or None
|
ids = {
|
||||||
for s in {w.name, w.window_class, w.window_instance}}
|
s is not None and s.lower() or None
|
||||||
|
for s in {w.name, w.window_class, w.window_instance}
|
||||||
|
}
|
||||||
if ids.intersection(intrusive_apps):
|
if ids.intersection(intrusive_apps):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -182,10 +177,12 @@ async def worksplace_exclusive(i3, event):
|
||||||
workspace = tree.find_focused().workspace()
|
workspace = tree.find_focused().workspace()
|
||||||
if not workspace:
|
if not workspace:
|
||||||
return
|
return
|
||||||
ids = {s is not None and s.lower() or None
|
ids = {
|
||||||
|
s is not None and s.lower() or None
|
||||||
for ow in workspace.leaves()
|
for ow in workspace.leaves()
|
||||||
for s in {ow.name, ow.window_class, ow.window_instance}
|
for s in {ow.name, ow.window_class, ow.window_instance}
|
||||||
if w.id != ow.id}
|
if w.id != ow.id
|
||||||
|
}
|
||||||
exclusives = ids.intersection(exclusive_apps)
|
exclusives = ids.intersection(exclusive_apps)
|
||||||
if not exclusives:
|
if not exclusives:
|
||||||
logger.debug("no exclusive app, {w.name} can go there")
|
logger.debug("no exclusive app, {w.name} can go there")
|
||||||
|
@ -193,7 +190,7 @@ async def worksplace_exclusive(i3, event):
|
||||||
|
|
||||||
# Create a new workspace and move the window here
|
# Create a new workspace and move the window here
|
||||||
num = await _new_workspace(i3)
|
num = await _new_workspace(i3)
|
||||||
logger.info(f'move window {w.name} to workspace {num}')
|
logger.info(f"move window {w.name} to workspace {num}")
|
||||||
await w.command(f'move container to workspace number "{num}"')
|
await w.command(f'move container to workspace number "{num}"')
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,7 +207,7 @@ async def quake_console(i3, event):
|
||||||
tree = await i3.get_tree()
|
tree = await i3.get_tree()
|
||||||
term = tree.find_instanced(term_name)
|
term = tree.find_instanced(term_name)
|
||||||
if not term:
|
if not term:
|
||||||
await i3.command(f'exec exec {term_exec} --name {term_name}')
|
await i3.command(f"exec exec {term_exec} --name {term_name}")
|
||||||
tries = 5
|
tries = 5
|
||||||
while not term and tries:
|
while not term and tries:
|
||||||
tree = await i3.get_tree()
|
tree = await i3.get_tree()
|
||||||
|
@ -230,11 +227,13 @@ async def quake_console(i3, event):
|
||||||
height = int(ws_height * height)
|
height = int(ws_height * height)
|
||||||
posx = ws_x
|
posx = ws_x
|
||||||
posy = ws_y
|
posy = ws_y
|
||||||
command = (f'[instance={term_name}] '
|
command = (
|
||||||
'border none,'
|
f"[instance={term_name}] "
|
||||||
f'resize set {width} px {height} px,'
|
"border none,"
|
||||||
'scratchpad show,'
|
f"resize set {width} px {height} px,"
|
||||||
f'move absolute position {posx}px {posy}px')
|
"scratchpad show,"
|
||||||
|
f"move absolute position {posx}px {posy}px"
|
||||||
|
)
|
||||||
logger.debug(f"QuakeConsole: {command}")
|
logger.debug(f"QuakeConsole: {command}")
|
||||||
await i3.command(command)
|
await i3.command(command)
|
||||||
|
|
||||||
|
@ -256,23 +255,29 @@ async def container_info(i3, event):
|
||||||
"class": w.window_class,
|
"class": w.window_class,
|
||||||
"instance": w.window_instance,
|
"instance": w.window_instance,
|
||||||
"role": w.window_role,
|
"role": w.window_role,
|
||||||
"type": w.ipc_data['window_type'],
|
"type": w.ipc_data["window_type"],
|
||||||
"sticky": w.sticky,
|
"sticky": w.sticky,
|
||||||
"floating": w.floating,
|
"floating": w.floating,
|
||||||
"geometry": f"{r.width}×{r.height}+{r.x}+{r.y}",
|
"geometry": f"{r.width}×{r.height}+{r.x}+{r.y}",
|
||||||
"layout": w.layout,
|
"layout": w.layout,
|
||||||
"parcent": w.percent,
|
"parcent": w.percent,
|
||||||
"marks": ", ".join(w.marks) or "(none)"
|
"marks": ", ".join(w.marks) or "(none)",
|
||||||
}
|
}
|
||||||
body = "\n".join((f"<tt>{k:10}</tt> {html.escape(str(v))}"
|
body = "\n".join(
|
||||||
|
(
|
||||||
|
f"<tt>{k:10}</tt> {html.escape(str(v))}"
|
||||||
for k, v in info.items()
|
for k, v in info.items()
|
||||||
if v is not None))
|
if v is not None
|
||||||
result = await notify(i3,
|
)
|
||||||
|
)
|
||||||
|
result = await notify(
|
||||||
|
i3,
|
||||||
app_icon="system-search",
|
app_icon="system-search",
|
||||||
expire_timeout=10000,
|
expire_timeout=10000,
|
||||||
summary=summary,
|
summary=summary,
|
||||||
body=body,
|
body=body,
|
||||||
replaces_id=getattr(container_info, "last_id", 0))
|
replaces_id=getattr(container_info, "last_id", 0),
|
||||||
|
)
|
||||||
container_info.last_id = result[0]
|
container_info.last_id = result[0]
|
||||||
|
|
||||||
|
|
||||||
|
@ -286,8 +291,7 @@ async def workspace_info(i3, event):
|
||||||
workspace = focused[0]
|
workspace = focused[0]
|
||||||
summary = f"Workspace {workspace.num} on {workspace.output}"
|
summary = f"Workspace {workspace.num} on {workspace.output}"
|
||||||
tree = await i3.get_tree()
|
tree = await i3.get_tree()
|
||||||
workspace = [w for w in tree.workspaces()
|
workspace = [w for w in tree.workspaces() if w.num == workspace.num]
|
||||||
if w.num == workspace.num]
|
|
||||||
|
|
||||||
def format(container):
|
def format(container):
|
||||||
if container.focused:
|
if container.focused:
|
||||||
|
@ -295,22 +299,22 @@ async def workspace_info(i3, event):
|
||||||
elif not container.window:
|
elif not container.window:
|
||||||
style = 'foreground="#6c98ee"'
|
style = 'foreground="#6c98ee"'
|
||||||
else:
|
else:
|
||||||
style = ''
|
style = ""
|
||||||
if container.window:
|
if container.window:
|
||||||
content = (f"{(container.window_class or '???').lower()}: "
|
content = (
|
||||||
f"{(container.window_title or '???')}")
|
f"{(container.window_class or '???').lower()}: "
|
||||||
elif container.type == 'workspace' and not container.nodes:
|
f"{(container.window_title or '???')}"
|
||||||
|
)
|
||||||
|
elif container.type == "workspace" and not container.nodes:
|
||||||
# Empty workspaces use workspace_layout, but when default,
|
# Empty workspaces use workspace_layout, but when default,
|
||||||
# this is layout...
|
# this is layout...
|
||||||
layout = container.ipc_data['workspace_layout']
|
layout = container.ipc_data["workspace_layout"]
|
||||||
if layout == "default":
|
if layout == "default":
|
||||||
layout = container.layout
|
layout = container.layout
|
||||||
content = f"({layout})"
|
content = f"({layout})"
|
||||||
else:
|
else:
|
||||||
content = f"({container.layout})"
|
content = f"({container.layout})"
|
||||||
root = (f"<span {style}>"
|
root = f"<span {style}>{content.lower()}</span>"
|
||||||
f"{content.lower()}"
|
|
||||||
"</span>")
|
|
||||||
children = []
|
children = []
|
||||||
for child in container.nodes:
|
for child in container.nodes:
|
||||||
if child == container.nodes[-1]:
|
if child == container.nodes[-1]:
|
||||||
|
@ -325,12 +329,14 @@ async def workspace_info(i3, event):
|
||||||
return "\n".join(children)
|
return "\n".join(children)
|
||||||
|
|
||||||
body = format(workspace[0]).lstrip("\n")
|
body = format(workspace[0]).lstrip("\n")
|
||||||
result = await notify(i3,
|
result = await notify(
|
||||||
|
i3,
|
||||||
app_icon="system-search",
|
app_icon="system-search",
|
||||||
expire_timeout=20000,
|
expire_timeout=20000,
|
||||||
summary=summary,
|
summary=summary,
|
||||||
body=body,
|
body=body,
|
||||||
replaces_id=getattr(workspace_info, "last_id", 0))
|
replaces_id=getattr(workspace_info, "last_id", 0),
|
||||||
|
)
|
||||||
workspace_info.last_id = result[0]
|
workspace_info.last_id = result[0]
|
||||||
|
|
||||||
|
|
||||||
|
@ -357,8 +363,7 @@ async def output_update(i3, event):
|
||||||
logger.warning(f"{cmd} exited with {proc.returncode}")
|
logger.warning(f"{cmd} exited with {proc.returncode}")
|
||||||
|
|
||||||
logger.debug("schedule XRandR change")
|
logger.debug("schedule XRandR change")
|
||||||
output_update.running = asyncio.get_event_loop().call_later(
|
output_update.running = asyncio.get_event_loop().call_later(2, output_update_now)
|
||||||
2, output_update_now)
|
|
||||||
|
|
||||||
|
|
||||||
async def main(options):
|
async def main(options):
|
||||||
|
@ -381,7 +386,7 @@ async def main(options):
|
||||||
cmd = event.binding.command
|
cmd = event.binding.command
|
||||||
if not cmd.startswith("nop "):
|
if not cmd.startswith("nop "):
|
||||||
return
|
return
|
||||||
cmd = cmd[4:].strip('"\'')
|
cmd = cmd[4:].strip("\"'")
|
||||||
if not cmd:
|
if not cmd:
|
||||||
return
|
return
|
||||||
kind = cmd.split(":")[0]
|
kind = cmd.split(":")[0]
|
||||||
|
@ -389,6 +394,7 @@ async def main(options):
|
||||||
for e in events:
|
for e in events:
|
||||||
if e == kind:
|
if e == kind:
|
||||||
await fn(i3, cmd)
|
await fn(i3, cmd)
|
||||||
|
|
||||||
i3.on(Event.BINDING, binding_event)
|
i3.on(Event.BINDING, binding_event)
|
||||||
|
|
||||||
await i3.main()
|
await i3.main()
|
||||||
|
@ -400,9 +406,9 @@ if __name__ == "__main__":
|
||||||
for fn, events in on.functions.items():
|
for fn, events in on.functions.items():
|
||||||
description += f" {fn.__doc__}"
|
description += f" {fn.__doc__}"
|
||||||
parser = argparse.ArgumentParser(description=description)
|
parser = argparse.ArgumentParser(description=description)
|
||||||
parser.add_argument("--debug", "-d", action="store_true",
|
parser.add_argument(
|
||||||
default=False,
|
"--debug", "-d", action="store_true", default=False, help="enable debugging"
|
||||||
help="enable debugging")
|
)
|
||||||
options = parser.parse_args()
|
options = parser.parse_args()
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue