From a77a5e27cea083959b082ae640cbe7c8521aa469 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Sun, 4 Jul 2021 23:50:48 +0200 Subject: [PATCH] More configuration Including a Quake console and autosplit in i3-companion. --- bin/i3-companion | 48 +++++++++++++++---- bin/quake | 104 ++++++++++++++++++++++++++++++++++++++++++ config | 18 ++++++-- dotfiles/polybar.conf | 39 +++++++--------- 4 files changed, 173 insertions(+), 36 deletions(-) create mode 100755 bin/quake diff --git a/bin/i3-companion b/bin/i3-companion index aeb01c8..0c1b919 100755 --- a/bin/i3-companion +++ b/bin/i3-companion @@ -2,8 +2,7 @@ """Personal i3 companion -This script will listen to i3 events and react accordingly. Currently, -it will rename workspaces using icons according to their content. +This script will listen to i3 events and react accordingly. """ @@ -12,9 +11,10 @@ import logging import logging.handlers import os import sys -import i3ipc import re +from i3ipc import Connection, Event + logger = logging.getLogger(os.path.splitext(os.path.basename(sys.argv[0]))[0]) @@ -55,20 +55,28 @@ def setup_logging(options): # See https://fontawesome.com/v5.15/icons application_icons = { "chromium": "", - "emacs": "", + "emacs": "", "firefox": "", "gimp": "", "google-chrome": "", + "snes9x-gtk": "", "spotify": "", + "steam": "", "vbeterm": "", "NOMATCH": "" } +application_icons_alone = { + application_icons[k] for k in { + "vbeterm" + } +} def application_icon(window): """Get application icon for a window.""" - for attr in ('name', 'window_title', - 'window_instance', 'window_class'): + for attr in ('name', + 'window_instance', + 'window_class'): name = getattr(window, attr, None) if name is None: continue @@ -89,6 +97,8 @@ def workspace_rename(i3, event): icon = application_icon(window) if icon is not None: icons.add(icon) + if any([i not in application_icons_alone for i in icons]): + icons -= application_icons_alone new_name = f"{workspace.num}:{'|'.join(icons)}" if workspace.name != new_name: logger.debug(f"rename workspace {workspace.num}") @@ -97,18 +107,38 @@ def workspace_rename(i3, event): i3.command(';'.join(commands)) +def autosplit(i3, event): + """Split on shortest side.""" + window = event.container + if not window.rect: + return + if window.layout in {'stacked', 'tabbed'}: + return + height = window.rect.height + width = window.rect.width + if height > width: + layout = 'vertical' + else: + layout = 'horizontal' + window.command(f"split {layout}") + + if __name__ == "__main__": options = parse_args() setup_logging(options) try: - i3 = i3ipc.Connection() + i3 = Connection() # Rename workspace depending on what is inside - for event in ('window::move', 'window::new', - 'window::title', 'window::close'): + for event in {Event.WINDOW_MOVE, + Event.WINDOW_NEW, + Event.WINDOW_CLOSE}: i3.on(event, workspace_rename) + # Autosplit + i3.on(Event.WINDOW_FOCUS, autosplit) + i3.main() except Exception as e: logger.exception("%s", e) diff --git a/bin/quake b/bin/quake new file mode 100755 index 0000000..1de75f6 --- /dev/null +++ b/bin/quake @@ -0,0 +1,104 @@ +#!/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 bdd980a..112b0b1 100644 --- a/config +++ b/config @@ -67,18 +67,20 @@ bindsym $mod+Shift+$left move left bindsym $mod+Shift+$down move down bindsym $mod+Shift+$up move up bindsym $mod+Shift+$right move right +bindsym $mod+o move container to output right # resize focused window -bindsym $mod+Ctrl+$left resize shrink width 10 px or 10 ppt -bindsym $mod+Ctrl+$down resize grow height 10 px or 10 ppt -bindsym $mod+Ctrl+$up resize shrink height 10 px or 10 ppt -bindsym $mod+Ctrl+$right resize grow width 10 px or 10 ppt +bindsym $mod+Ctrl+$left resize shrink width 10 px or 2 ppt +bindsym $mod+Ctrl+$down resize grow height 10 px or 2 ppt +bindsym $mod+Ctrl+$up resize shrink height 10 px or 2 ppt +bindsym $mod+Ctrl+$right resize grow width 10 px or 2 ppt # change split orientation bindsym $mod+v split toggle # enter fullscreen mode for the focused container bindsym $mod+f fullscreen toggle +bindsym $mod+Shift+f fullscreen toggle global # change container layout (stacked, tabbed, toggle split) bindsym $mod+s layout stacking @@ -131,14 +133,20 @@ bindsym $mod+Shift+7 move container to workspace number $ws7 bindsym $mod+Shift+8 move container to workspace number $ws8 bindsym $mod+Shift+9 move container to workspace number $ws9 bindsym $mod+Shift+0 move container to workspace number $ws10 +bindsym $mod+Shift+o move workspace to output right # reload/restart bindsym $mod+Shift+c reload bindsym $mod+Shift+r restart -# Lock screen +# Lock screen and print screen bindsym XF86ScreenSaver exec --no-startup-id xset s activate bindsym $mod+Delete exec --no-startup-id xset s activate +bindsym Print exec --no-startup-id "flameshot gui -r | xclip -selection clipboard -t image/png" + +set $quake "QuakeConsoleNeedsUniqueName" +for_window [instance=$quake] move window to scratchpad +bindsym $mod+grave exec ~/.config/i3/bin/quake --name $quake --term $term # start stuff exec_always --no-startup-id systemctl --user start --no-block wallpaper.service diff --git a/dotfiles/polybar.conf b/dotfiles/polybar.conf index 577f8f6..8e5764a 100644 --- a/dotfiles/polybar.conf +++ b/dotfiles/polybar.conf @@ -1,5 +1,5 @@ [colors] -background = #a0000000 +background = #c0000000 foreground = #eaeaea highlight = #4c7899 @@ -21,16 +21,16 @@ module-margin = 1 background = ${colors.background} foreground = ${colors.foreground} -font-0 = Hack:style=Regular:size=10;2 +font-0 = Iosevka:style=Regular:size=10;2 font-1 = Font Awesome 5 Pro:style=Solid:size=10;2 font-2 = Font Awesome 5 Brands:style=Regular:size=10;2 modules-left = i3 -modules-right = date +modules-center = date [bar/primary] inherit = bar/secondary -modules-center = cpu memory pulseaudio ethernet wlan battery +modules-right = cpu memory pulseaudio battery ethernet wlan [module/i3] type = internal/i3 @@ -89,32 +89,27 @@ type = internal/date interval = 2 date = %a %d.%m time = %H:%M -label = %date% %time% +label = %date% %time% [module/battery] type = internal/battery battery = BAT0 adapter = ADP1 -full-at = 99 interval = 5 -format-charging = -label-charging = %percentage: 2%% -format-discharging = -label-discharging = %percentage: 2%% +format-charging = +label-charging =  %percentage: 2%% +format-discharging = +label-discharging = %percentage: 2%%%{F-} format-full = label-full =  -animation-charging-0 =  -animation-charging-1 =  -animation-charging-2 =  -animation-charging-3 =  -animation-charging-4 =  -animation-charging-framerate = 1000 -animation-discharging-0 =  -animation-discharging-1 =  -animation-discharging-2 =  -animation-discharging-3 =  -animation-discharging-4 =  -animation-discharging-framerate = 1000 +ramp-capacity-0 = %{F#ff0000} +ramp-capacity-1 =  +ramp-capacity-2 =  +ramp-capacity-3 =  +ramp-capacity-4 =  +ramp-capacity-5 =  +ramp-capacity-6 =  +ramp-capacity-7 =  [module/pulseaudio] type = internal/pulseaudio