From 1caacfd679e954d095150bcccaaeef2617287eb8 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Tue, 6 Jul 2021 10:37:01 +0200 Subject: [PATCH] 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. --- bin/i3-companion | 45 ++++++++++++++++++++ bin/quake | 104 ----------------------------------------------- config | 2 +- 3 files changed, 46 insertions(+), 105 deletions(-) delete mode 100755 bin/quake diff --git a/bin/i3-companion b/bin/i3-companion index a654915..2352053 100755 --- a/bin/i3-companion +++ b/bin/i3-companion @@ -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) diff --git a/bin/quake b/bin/quake deleted file mode 100755 index 1de75f6..0000000 --- a/bin/quake +++ /dev/null @@ -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) diff --git a/config b/config index a38a362..8b48ad3 100644 --- a/config +++ b/config @@ -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"]