i3-companion: swallow quake console functionality

While payload could be structured, we keep a string as it is easier to
express it in i3 configuration file.
This commit is contained in:
Vincent Bernat 2021-07-06 10:37:01 +02:00
parent 2a85902609
commit 1caacfd679
3 changed files with 46 additions and 105 deletions

View file

@ -12,6 +12,7 @@ import logging.handlers
import os
import sys
import re
import time
from i3ipc import Connection, Event
@ -135,6 +136,47 @@ def new_workspace(i3, event):
current.command(f'move container to workspace number "{available}"')
def quake_console(i3, event):
"""Spawn a quake console or toggle an existing one."""
if type(event.payload) is not str or \
not event.payload.startswith("quake-console:"):
return
try:
_, term_exec, term_name, height = event.payload.split(":")
height = float(height)
except Exception as exc:
logger.warn(f"unable to parse payload {event.payload}: {exc}")
return
term = i3.get_tree().find_instanced(term_name)
if not term:
i3.command(f'exec {term_exec} --name {term_name}')
tries = 5
while not term and tries:
term = i3.get_tree().find_instanced(term_name)
time.sleep(0.2)
tries -= 1
if not term:
raise RuntimeError("unable to spawn terminal")
term = term[0]
workspace = [ws for ws in i3.get_workspaces() if ws.focused][0]
ws_x = workspace.rect.x
ws_y = workspace.rect.y
ws_width = workspace.rect.width
ws_height = workspace.rect.height
width = ws_width
height = int(ws_height * height)
posx = ws_x
posy = ws_y
command = (f'[instance={term_name}] '
'border none,'
f'resize set {width} px {height} px,'
'scratchpad show,'
f'move absolute position {posx}px {posy}px')
logger.debug(f"QuakeConsole: {command}")
i3.command(command)
if __name__ == "__main__":
options = parse_args()
setup_logging(options)
@ -151,6 +193,9 @@ if __name__ == "__main__":
# Create a new workspace or move to a new workspace
i3.on(Event.TICK, new_workspace)
# Create/display a quake console
i3.on(Event.TICK, quake_console)
i3.main()
except Exception as e:
logger.exception("%s", e)

104
bin/quake
View file

@ -1,104 +0,0 @@
#!/usr/bin/python3
#!/usr/bin/python3
"""Personal i3 companion
This script will listen to i3 events and react accordingly.
"""
import argparse
import logging
import logging.handlers
import os
import sys
import time
from i3ipc import Connection
logger = logging.getLogger(os.path.splitext(os.path.basename(sys.argv[0]))[0])
class CustomFormatter(argparse.RawDescriptionHelpFormatter,
argparse.ArgumentDefaultsHelpFormatter):
pass
def parse_args(args=sys.argv[1:]):
"""Parse arguments."""
parser = argparse.ArgumentParser(
description=sys.modules[__name__].__doc__,
formatter_class=CustomFormatter)
g = parser.add_mutually_exclusive_group()
g.add_argument("--debug", "-d", action="store_true",
default=False,
help="enable debugging")
g.add_argument("--silent", "-s", action="store_true",
default=False,
help="don't log")
parser.add_argument("--height",
default=0.3,
help="height of terminal")
parser.add_argument("--name",
default="UniqueNameForConsole",
help="Unique name to identify terminal")
parser.add_argument("--term",
default="x-terminal-emulator",
help="Terminal emulator to run")
return parser.parse_args(args)
def setup_logging(options):
"""Configure logging."""
root = logging.getLogger("")
root.setLevel(logging.WARNING)
logger.setLevel(options.debug and logging.DEBUG or logging.INFO)
if not options.silent:
ch = logging.StreamHandler()
ch.setFormatter(logging.Formatter(
"%(levelname)s[%(name)s] %(message)s"))
root.addHandler(ch)
if __name__ == "__main__":
options = parse_args()
setup_logging(options)
try:
i3 = Connection()
term = i3.get_tree().find_instanced(options.name)
if not term:
i3.command(f'exec {options.term} --name {options.name}')
tries = 5
while not term and tries:
term = i3.get_tree().find_instanced(options.name)
time.sleep(0.2)
tries -= 1
if not term:
raise RuntimeError("unable to spawn terminal")
term = term[0]
workspace = [ws for ws in i3.get_workspaces() if ws.focused][0]
ws_x = workspace.rect.x
ws_y = workspace.rect.y
ws_width = workspace.rect.width
ws_height = workspace.rect.height
width = ws_width
height = int(ws_height * options.height)
posx = ws_x
posy = ws_y
command = (f'[instance={options.name}] '
'border none,'
f'resize set {width} px {height} px,'
'scratchpad show,'
f'move absolute position {posx}px {posy}px')
logger.debug(f"QuakeConsole: {command}")
i3.command(command)
except Exception as e:
logger.exception("%s", e)
sys.exit(1)
sys.exit(0)

2
config
View file

@ -152,7 +152,7 @@ bindsym Print exec --no-startup-id "flameshot gui -r | xclip -selection clipboar
# Quake window
set $quake "QuakeConsoleNeedsUniqueName"
for_window [instance=$quake title=$term] move window to scratchpad
bindsym $mod+grave exec ~/.config/i3/bin/quake --name $quake --term $term
bindsym $mod+grave exec --no-startup-id i3-msg -t send_tick "quake-console:$term:$quake:0.3"
# Random rules
no_focus [class="zoom" window_type="dialog"]