From bcc38fba40c1b2d41b60299b9d09048ae84304b5 Mon Sep 17 00:00:00 2001 From: paul-loedige Date: Sat, 17 Feb 2024 23:14:52 +0100 Subject: [PATCH] basic Qtile configuration added --- config.org | 1367 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 1312 insertions(+), 55 deletions(-) diff --git a/config.org b/config.org index b4ff7d4..75b08c4 100644 --- a/config.org +++ b/config.org @@ -11,32 +11,48 @@ - [[#doom-emacs][Doom Emacs]] - [[#zshrc][.zshrc]] - [[#bashrc][.bashrc]] + - [[#autostartsh][autostart.sh]] - [[#package-management][Package Management]] - [[#arch-and-aur-packages][Arch and AUR Packages]] - [[#base-system][Base System]] - [[#arch-linux][Arch Linux]] - - [[#networking][Networking]] + - [[#network-manager][Network Manager]] - [[#man-pages-and-texinfo][Man Pages and Texinfo]] - [[#build-tools][Build Tools]] - [[#desktop-environments-and-window-manager][Desktop Environments and Window Manager]] - [[#lightdm][LightDM]] - [[#gnome][GNOME]] + - [[#qtile][Qtile]] - [[#text-editors][Text Editors]] - [[#doom-emacs-1][Doom Emacs]] - [[#vscode][VSCode]] - - [[#neovim][Neovim]] + - [[#neovim][NeoVim]] +- [[#browser][Browser]] + - [[#firefox][Firefox]] - [[#shells][Shells]] - [[#aliases][Aliases]] - [[#zsh][ZSH]] - [[#bash][Bash]] -- [[#themeing][Themeing]] +- [[#theming][Theming]] - [[#doom-emacs-2][Doom Emacs]] + - [[#vscode-1][VSCode]] + - [[#qtile-1][Qtile]] - [[#git][Git]] - [[#installation][Installation]] - [[#configuration][Configuration]] +- [[#miniconda][Miniconda]] + - [[#installation-1][Installation]] + - [[#zsh-special-settings][ZSH special settings]] + - [[#do-not-activate-base-environment-on-startup][Do not activate base environment on startup]] - [[#misc-programs][Misc Programs]] - [[#zathura][Zathura]] - [[#nextcloud][Nextcloud]] + - [[#bitwarden][Bitwarden]] + - [[#inkscape][Inkscape]] +- [[#manual-tasks-after-tangling][Manual Tasks after tangling]] +- [[#other-todos][Other TODOs]] + - [[#configure-bitwarden-via-config-file][configure Bitwarden via config file]] + - [[#add-firefox-user-via-updatesh][add Firefox user via update.sh]] * Prerequisites - Completed Arch Linux Installation @@ -44,6 +60,7 @@ - encryption - main user * Literate File Headers +This is used to initialize all files that are accessed from multiple places in the config ** update.sh #+begin_src shell :tangle update.sh #!/bin/sh @@ -89,7 +106,7 @@ contains all modifications to the path variables We start by simply defining the standard headers used by the three files. These headers come from the initial files generated by =doom install=, and contain either some Emacs-LISP relevant indicators like =lexical-binding=, or instructions about the contents of the file. *** init.el #+html:
init.el -#+begin_src emacs-lisp :tangle ~/.config/doom/init.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/init.el ;;; init.el -*- lexical-binding: t; -*- ;; DO NOT EDIT THIS FILE DIRECTLY @@ -115,7 +132,7 @@ We start by simply defining the standard headers used by the three files. These *** packages.el #+html:
packages.el -#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/packages.el ;; -*- no-byte-compile: t; -*- ;;; $DOOMDIR/packages.el @@ -174,7 +191,7 @@ We start by simply defining the standard headers used by the three files. These *** config.el #+html:
config.el -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el ;;; $DOOMDIR/config.el -*- lexical-binding: t; -*- ;; DO NOT EDIT THIS FILE DIRECTLY @@ -250,6 +267,15 @@ We start by simply defining the standard headers used by the three files. These # You should make any changes there and regenerate it from Emacs org-mode # using org-babel-tangle (C-c C-v t) +#+end_src +** autostart.sh +#+begin_src shell :mkdirp yes :tangle ~/.config/autostart.sh +#!/bin/sh +# DO NOT EDIT THIS FILE DIRECTLY +# This is a file generated from a literate programing source file +# You should make any changes there and regenerate it from Emacs org-mode +# using org-babel-tangle (C-c C-v t) + #+end_src * Package Management ** Arch and AUR Packages @@ -316,7 +342,8 @@ lvm2 sudo #+end_src -** Networking +** Network Manager +*** Installation This config uses the [[https://wiki.archlinux.org/title/NetworkManager][NetworkManager]] #+begin_src shell :tangle pkg-list.txt networkmanager @@ -330,6 +357,8 @@ if ! systemctl is-enabled --quiet "$systemd_service"; then sudo systemctl start "$systemd_service" fi #+end_src +*** TODO Networks + ** [[https://wiki.archlinux.org/title/Man_page][Man Pages]] and [[https://wiki.archlinux.org/title/GNU#Texinfo][Texinfo]] #+begin_src shell :tangle pkg-list.txt @@ -423,6 +452,1064 @@ xdg-desktop-portal-gnome xdg-user-dirs-gtk yelp #+end_src +** [[https://qtile.org/][Qtile]] +(Almost) all configuration is done via the ~config.py~ file +*** config.py Literate File Header +#+begin_src python :mkdirp yes :tangle ~/.config/qtile/config.py +# DO NOT EDIT THIS FILE DIRECTLY +# This is a file generated from a literate programing source file +# You should make any changes there and regenerate it from Emacs org-mode +# using org-babel-tangle (C-c C-v t) + +#+end_src +*** Installation +#+begin_src shell :tangle pkg-list.txt +qtile +#+end_src +*** Import Qtile Dependencies +#+begin_src python :mkdirp yes :tangle ~/.config/qtile/config.py +from libqtile import layout, bar, widget, hook +from libqtile.config import Key, Drag, Click, Group, Screen, ScratchPad, DropDown +from libqtile.command import lazy +#+end_src +*** Defines +Defines are stored in a separate ~defines.py~ file +**** defines.py Literate File Header +#+begin_src python :mkdirp yes :tangle ~/.config/qtile/defines.py +# DO NOT EDIT THIS FILE DIRECTLY +# This is a file generated from a literate programing source file +# You should make any changes there and regenerate it from Emacs org-mode +# using org-babel-tangle (C-c C-v t) + +#+end_src +**** Terminal +Install [[https://alacritty.org/][Alacritty]] +#+begin_src shell :tangle pkg-list.txt +alacritty +#+end_src +and set it as default +#+begin_src python :tangle ~/.config/qtile/defines.py :mkdirp yes +term = 'alacritty' +#+end_src +**** Main/Mod Key +This config uses the "Master" or "Windows" Key as Main/Mod Key +#+begin_src python :tangle ~/.config/qtile/defines.py :mkdirp yes +mod = 'mod4' +#+end_src + +*** Visual +**** Colors +Colors are set in the [[Theming]] section of this config +**** Border Width +#+begin_src python :tangle ~/.config/qtile/defines.py :mkdirp yes +border_width = 2 +#+end_src +**** Window Margin +#+begin_src python :tangle ~/.config/qtile/defines.py :mkdirp yes +window_margin = 5 +#+end_src +**** Floats kept above +Keep floating windows above others +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +floats_kept_above = True +#+end_src +**** Automatic Full Screen +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +auto_fullscreen = True +#+end_src +**** Automaitc Minimization +If things like steam games want to auto-minimize themselves when losing focus, should we respect this or not? +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +auto_minimize = True +#+end_src +**** _NET_ACTIVATE_WINDOW Behavior +Behavior of the _NET_ACTIVATE_WINDOW message sent by applications +- urgent: urgent flag is set for the window +- focus: automatically focus the window +- smart: automatically focus if the window is in the current group +- never: never automatically focus any window that requests +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +focus_on_window_activation = 'smart' +#+end_src + +**** Widget Defaults +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +from chassis_type import ChassisType, chassis_type +from defines import base_color +widget_defaults = dict( + background=base_color, + font='UbuntuMono Nerd Font', + fontsize=18, + padding=1 if chassis_type == ChassisType.LAPTOP else 5, +) +extension_defaults = widget_defaults.copy() +#+end_src +**** Bar Sizes and Heights +#+begin_src python :tangle ~/.config/qtile/defines.py :mkdirp yes +from chassis_type import ChassisType, chassis_type +main_bar_fontsize=22 +main_bar_height=24 if chassis_type == ChassisType.LAPTOP else 28 +secondary_bar_height=24 +secondary_bar_fontsize=18 +#+end_src +*** Chassis Type Detection +Needed to load correct settings for given hardware (laptop/desktop) +**** chassis_type.py Literate File Header +#+begin_src python :mkdirp yes :tangle ~/.config/qtile/chassis_type.py +# DO NOT EDIT THIS FILE DIRECTLY +# This is a file generated from a literate programing source file +# You should make any changes there and regenerate it from Emacs org-mode +# using org-babel-tangle (C-c C-v t) + +#+end_src +**** Enum +#+begin_src python :tangle ~/.config/qtile/chassis_type.py :mkdirp yes +from enum import Enum +import subprocess + +class ChassisType(Enum): + DESKTOP = 0 + LAPTOP = 1 +#+end_src +**** Detection Function +#+begin_src python :mkdirp yes :tangle ~/.config/qtile/chassis_type.py +def detect_chassis_type() -> ChassisType: + try: + output = subprocess.check_output(["hostnamectl", "status"], universal_newlines=True) + except subprocess.CalledProcessError as e: + print("Error running hostnamectl:", e) + exit(1) + return ChassisType.LAPTOP if "Chassis: laptop" in output else ChassisType.DESKTOP + +chassis_type = detect_chassis_type() +#+end_src +*** Mouse Settings +**** Follow Mouse Focus +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +follow_mouse_focus = True +#+end_src +**** Bring to Front with Click +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +bring_front_click = True +#+end_src +**** Warp Cursor +Cursor should not jump to the window selected via keyboard +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +cursor_warp = False +#+end_src +*** Autostart +#+begin_src python :mkdirp yes :tangle ~/.config/qtile/config.py +import os + +@hook.subscribe.startup_once +def autostart(): + home = os.path.expanduser('~/.config/autostart.sh') + subprocess.call([home]) +#+end_src +*** Custom Microphone Widgets +Based on the [[https://docs.qtile.org/en/stable/manual/ref/widgets.html#volume][Volume]] widget. +It requires some packages to be installed +#+begin_src shell :tangle pkg-list.txt +python-psutil +alsa-utils +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +import subprocess +import psutil +import re + +re_vol = re.compile(r'\[(\d?\d?\d?)%\]') +BUTTON_MUTE = 1 +class Microphone(widget.base._TextBox): + """ + Custom Microphone widget + """ + orientations = widget.base.ORIENTATION_HORIZONTAL + defaults = [ + ("cardid", None, "Card Id"), + ("device", "default", "Device Name"), + ("channel", "Capture", "Channel"), + ("padding", 3, "Padding left and right. Calculated if None."), + ("update_interval", 0.2, "Update time in seconds."), + ("theme_path", None, "Path of the icons"), + ("emoji", False, "Use emoji to display volume states, only if ``theme_path`` is not set." + "The specified font needs to contain the correct unicode characters."), + ("mute_command", None, "Mute command"), + ("volume_app", None, "App to control volume"), + ("volume_up_command", None, "Volume up command"), + ("volume_down_command", None, "Volume down command"), + ("get_volume_command", None, "Command to get the current volume"), + ("step", 2, "Volume change for up an down commands in percentage." + "Only used if ``volume_up_command`` and ``volume_down_command`` are not set.") + ] + + def __init__(self, **config): + widget.base._TextBox.__init__(self, '0', width=bar.CALCULATED, **config) + self.add_defaults(Microphone.defaults) + if self.theme_path: + self.length_type = bar.STATIC + self.length = 0 + self.surfaces = {} + self.volume = None + + def timer_setup(self): + self.timeout_add(self.update_interval, self.update) + if self.theme_path: + self.setup_images() + + def create_amixer_command(self, *args): + cmd = ['amixer'] + cmd.extend([x for x in args]) + return cmd + + def button_press(self, x, y, button): + if button == BUTTON_MUTE: + if self.mute_command is not None: + subprocess.call(self.mute_command, shell=True) + else: + subprocess.call(self.create_amixer_command('-q', + 'sset', + self.channel, + 'toggle')) + self.draw() + + def update(self): + vol = self.get_volume() + if vol != self.volume: + self.volume = vol + # Update the underlying canvas size before actually attempting + # to figure out how big it is and draw it. + self._update_drawer() + self.bar.draw() + self.timeout_add(self.update_interval, self.update) + + def _update_drawer(self): + if self.emoji: + if self.volume > 0: + self.text = '' + elif self.volume <= 0: + self.text = '' + else: + if self.volume == -1: + self.text = 'M' + else: + self.text = '{}%'.format(self.volume) + def get_volume(self): + try: + get_volume_cmd = self.create_amixer_command('sget', + self.channel) + + if self.get_volume_command: + get_volume_cmd = self.get_volume_command + + mixer_out = self.call_process(get_volume_cmd) + except subprocess.CalledProcessError: + return -1 + + if '[off]' in mixer_out: + return -1 + + volgroups = re_vol.search(mixer_out) + if volgroups: + return int(volgroups.groups()[0]) + else: + # this shouldn't happen + return -1 + + def draw(self): + if self.theme_path: + self.drawer.draw(offsetx=self.offset, width=self.length) + else: + widget.base._TextBox.draw(self) + + def cmd_mute(self): + # Emulate button press. + self.button_press(0, 0, BUTTON_MUTE) +#+end_src +*** Widget Groups +To simplify the configuration of the [[Bars]] widgets are grouped +**** Imports +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +from libqtile import widget +from defines import term +from defines import focus_color, light_foreground_color, dark_foreground_color, background_color0, background_color8, base_color +from defines import red_color, light_red_color, green_color, light_green_color, orange_color, yellow_color, light_yellow_color, blue_color, purple_color, light_purple_color, magenta_color, cyan_color +#+end_src +**** Workspace Status +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +def workspace_status_widgets(size, fontsize): + return [ + widget.CurrentLayoutIcon( + scale = 0.9, + ), + widget.TextBox( + text=' ', + foreground=light_foreground_color, + fontsize=fontsize, + background=blue_color + ), + widget.GroupBox( + fontsize=fontsize, + rounded=False, + disable_drag=True, + active=light_foreground_color, + inactive=dark_foreground_color, + highlight_method='block', + highlight_color=red_color, + other_screen_border = light_purple_color, + other_current_screen_border = purple_color, + this_current_screen_border = blue_color, + this_screen_border = blue_color, + urgent_alert_method='block', + urgent_border = red_color, + ), + widget.WindowName(fontsize=fontsize) + ] +#+end_src +**** Audio +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +def audio_widgets(size, fontsize): + return[ + widget.Volume( + foreground=light_foreground_color, + background=blue_color, + emoji=True, + fontsize=fontsize, + ), + widget.Volume( + foreground=light_foreground_color, + background=blue_color, + fontsize=fontsize, + padding=0 + ), + Microphone( + foreground=light_foreground_color, + background=blue_color, + emoji=True, + fontsize=fontsize, + ), + Microphone( + foreground=light_foreground_color, + background=blue_color, + fontsize=fontsize, + padding=0 + ) + ] +#+end_src +**** System Widgets +These change depending on [[Chassis Type Detection][Chassis Type +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +def system_widgets(size,fontsize): + sys_widgets = [] + # first widget is battery for laptop and cpu temp otherwise + if chassis_type == ChassisType.LAPTOP: + sys_widgets.append( + widget.Battery( + foreground=light_foreground_color, + background=orange_color, + fontsize=fontsize, + update_interval=1, + format="{char} {percent:2.0%}", + low_percentage=0.2, + notify_below=True, + low_foreground=red_color, + ) + ) + else: + sys_widgets.extend([ + widget.TextBox( + text='󰈸', + foreground=light_foreground_color, + background=orange_color, + fontsize=fontsize+6 + ), + widget.ThermalSensor( + foreground=light_foreground_color, + background=orange_color, + fontsize=fontsize, + tag_sensor='Tctl', + ) + ]) + sys_widgets.extend([ + widget.TextBox( + text=' ', + foreground=light_foreground_color, + background=green_color, + fontsize=fontsize + ), + widget.CPU( + foreground=light_foreground_color, + background=green_color, + fontsize=fontsize, + format='{load_percent}%' if chassis_type == ChassisType.LAPTOP else'{load_percent}% @ {freq_current}GHz', + ), + widget.TextBox( + text='', + foreground=light_foreground_color, + background=yellow_color, + fontsize=fontsize + ), + widget.Memory( + foreground=light_foreground_color, + background=yellow_color, + fontsize=fontsize, + format='{MemUsed: 2.1f}GB|{SwapUsed: 2.1f}GB' if chassis_type == ChassisType.LAPTOP else'{MemUsed: 2.1f}GB({MemPercent: 2.0f}%) | {SwapUsed: 2.1f}GB({SwapPercent: 2.0f}%)', + measure_mem = 'G', + measure_swap = 'G', + ), + widget.TextBox( + text='󰈀 ', + foreground=light_foreground_color, + background=blue_color, + fontsize=fontsize + ), + widget.Net( + background=blue_color, + foreground=light_foreground_color, + fontsize=fontsize, + prefix='M', + format='{down:6.2f}{down_suffix}↓{up:6.2f}{up_suffix}↑', + ) + ] + ) + return sys_widgets +#+end_src +**** Datetime +These require the [[https://www.keshikan.net/fonts-e.html][DSEG Font]] +#+begin_src shell :tangle pkg-list.txt +ttf-dseg +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +def datetime_widgets(size,fontsize): + return [ + widget.TextBox( + text='󰸗 ', + foreground=light_foreground_color, + background=purple_color, + fontsize=fontsize + ), + widget.Clock( + foreground=light_foreground_color, + background=purple_color, + fontsize=fontsize, + format='%Y-%m-%d' + ), + widget.Clock( + font='dseg7 classic bold', + fontsize=16, + format='%H:%M' + ), + ] +#+end_src +*** Bars +**** Imports +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +from libqtile import widget, bar +from defines import base_color, blue_color +from defines import main_bar_fontsize, main_bar_height, secondary_bar_height, secondary_bar_fontsize +#+end_src +**** Main Bar +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +main_bar = bar.Bar([ + *workspace_status_widgets(main_bar_height,main_bar_fontsize), + widget.Systray(fontsize=main_bar_fontsize), + *audio_widgets(main_bar_height,main_bar_fontsize), + *system_widgets(main_bar_height,main_bar_fontsize), + *datetime_widgets(main_bar_height,main_bar_fontsize), +],main_bar_height) +#+end_src +**** Left Screen Bars +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +left_bar = bar.Bar([ + *workspace_status_widgets(secondary_bar_height,secondary_bar_fontsize), + *audio_widgets(secondary_bar_height,secondary_bar_fontsize), + *datetime_widgets(secondary_bar_height,secondary_bar_fontsize) +],secondary_bar_height) +#+end_src +**** Secondary Bar +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +secondary_bar = bar.Bar([ + *workspace_status_widgets(secondary_bar_height,secondary_bar_fontsize), + *audio_widgets(secondary_bar_height,secondary_bar_fontsize), + *datetime_widgets(secondary_bar_height,secondary_bar_fontsize) +],secondary_bar_height) +#+end_src + +**** Top Screen Bar +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +top_bar = bar.Bar([ + *workspace_status_widgets(secondary_bar_height,secondary_bar_fontsize), + *audio_widgets(secondary_bar_height,secondary_bar_fontsize), + *datetime_widgets(secondary_bar_height,secondary_bar_fontsize) +],secondary_bar_height) +#+end_src + +*** Screens +**** Desktop Screen Detection +On my desktop setup I have to special screens that should be detected +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +main_screen_res = [3440,1440] +top_screen_res = [1440,900] +#+end_src +**** Getting Screen Information +***** Dependencies +#+begin_src shell :tangle pkg-list.txt +xorg-xrandr +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +import subprocess +import re +import numpy as np +from libqtile.config import Screen +#+end_src +***** Reading the Information +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +cmd = ['xrandr'] +p = subprocess.Popen(cmd, stdout=subprocess.PIPE) +resolution_string, junk = p.communicate() +p.stdout.close() +screen_resolutions = [np.array(screen_res.split('x')).astype(int) for screen_res in re.findall('[0-9]+x[0-9]+(?=[^\\\\n]*\*)',str(resolution_string))] +number_of_screens = len(screen_resolutions) +max_width = max(screen_resolutions, key=lambda res: res[0])[0] +#+end_src +**** Setting the Screens +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +screens = [] +defined_main_window = False +for width, height in screen_resolutions: + if width == main_screen_res[0] and height == main_screen_res[1]: + screens.append(Screen(top=main_bar, wallpaper= "~/Pictures/Wallpapers/gruvbox-like.jpg", wallpaper_mode="fill")) + defined_main_window = True + elif width == top_screen_res[0] and height == top_screen_res[1]: + screens.append(Screen(bottom=top_bar, wallpaper="~/Pictures/Wallpapers/wallpaperflare.com_wallpaper.jpg", wallpaper_mode="fill")) + elif width < height: + screens.append(Screen(top=left_bar, wallpaper="~/Pictures/Wallpapers/gruvbox-like-left.jpg", wallpaper_mode="fill")) + elif width == max_width and not defined_main_window: + screens.append(Screen(top=main_bar, wallpaper= "~/Pictures/Wallpapers/gruvbox-like.jpg", wallpaper_mode="fill")) + defined_main_window = True + else: + screens.append(Screen(top=secondary_bar, wallpaper= "~/Pictures/Wallpapers/gruvbox-like.jpg", wallpaper_mode="fill")) +#+end_src +**** Automatically Reconfigure Screens +Controls whether or not to automatically reconfigure screens when there are changes in randr output configuration. +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +reconfigure_screens = True +#+end_src +*** Layouts +**** Basic Layouts +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +from libqtile import layout +from defines import focus_color, border_width, window_margin + +layouts = [ + layout.MonadTall( + align=1, + border_focus = focus_color, + border_width = border_width, + margin=window_margin, + new_client_position = 'after_current', + ), + layout.Floating( + border_focus = focus_color, + border_width = border_width, + margin=window_margin, + ), + layout.Max(), + layout.MonadWide( + border_focus = focus_color, + border_width = border_width, + new_client_position = 'after_current', + margin=window_margin, + ), + layout.Columns( + border_focus = focus_color, + border_width = border_width, + num_columns = 3, + margin = window_margin, + ) +] +#+end_src +**** Floating Layout +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +from libqtile import layout +from libqtile.config import Match +from defines import focus_color, border_width + +floating_layout = layout.Floating( + border_focus = focus_color, + border_width = border_width, + float_rules=[ + # Run the utility of `xprop` to see the wm class and name of an X client. + ,*layout.Floating.default_float_rules, + Match(wm_class='confirmreset'), # gitk + Match(wm_class='makebranch'), # gitk + Match(wm_class='maketag'), # gitk + Match(title='branchdialog'), # gitk + Match(title='pinentry'), # GPG key password entry + Match(wm_class='ssh-askpass'), # ssh-askpass + Match(wm_class='sun-awt-X11-XWindowPeer'), #matlab + Match(wm_class='sun-awt-X11-XDialogPeer'), #matlab +]) +#+end_src +***** Enable Dragging +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +from libqtile.config import Drag, Click +from libqtile.command import lazy +from defines import mod +mouse = [ + Drag([mod], "Button1", lazy.window.set_position_floating(), + start=lazy.window.get_position()), + Drag([mod], "Button3", lazy.window.set_size_floating(), + start=lazy.window.get_size()), + Click([mod], "Button2", lazy.window.bring_to_front()) +] +#+end_src +*** Groups +**** Dependencies +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +from libqtile.config import Group, ScratchPad, DropDown, Key, Match +from libqtile.command import lazy + +import re + +from defines import mod,term +#+end_src +**** Main Groups +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +main_groups_info = [(" ","Org",'o',{'layout': 'monadtall'}), + (" ","Home", 'h',{'layout': 'monadtall'}), + (" ","Browser", 'f',{'layout': 'monadtall'}), + (" ","Mail", 'm',{'layout': 'monadtall', 'matches':[Match(wm_class="Mail")]}), + (" ","Coding", 'c',{'layout': 'monadtall', 'matches' : [Match(wm_class="code")]}), + (" ","Documents", 'l',{'layout': 'monadtall'}), + ("󰝚 ","Music", 'u',{'layout': 'monadtall', 'matches' : [Match(wm_class="spotify")]}), + (" ","Video", 'v',{'layout': 'monadtall', 'matches' : [Match(wm_class="vlc")]}), + ("󰙯 ","VideoChat", 'z',{'layout': 'monadtall', 'matches':[Match(wm_class="discord")]}), + ("一","etc1", '1', {'layout': 'monadtall'}), + ("二","etc2", '2', {'layout': 'monadtall'}), + ("三","etc3", '3', {'layout': 'monadtall'}), + ("四","etc4", '4', {'layout': 'monadtall'})] + +groups = [Group(icon, **kwargs) for icon, name, key, kwargs in main_groups_info] +#+end_src +**** DropDown Groups +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +dropdown_groups_info = [] +#+end_src +***** [[https://christian.amsuess.com/tools/arandr/][ARandR]] +#+begin_src shell :tangle pkg-list.txt +arandr +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'ARandR' +dropdown_groups_info.append((name, + DropDown(name, + 'arandr', + height = 0.5, + width = 0.8, + x = 0.1, # (1-0.8)/2 + on_focus_lost_hide=True, + opacity=1, + match = Match(wm_class='arandr') + ), + [mod],'p')) +#+end_src +***** DropDown Terminal +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'Terminal' +dropdown_groups_info.append((name, + DropDown(name, + term + ), + ['mod1','control'],'space')) +#+end_src +***** [[https://htop.dev/][htop]] +#+begin_src shell :tangle pkg-list.txt +htop +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'htop' +dropdown_groups_info.append((name, + DropDown(name, + term + ' -e htop' + ), + ['control','shift'],'Escape')) +#+end_src +***** Audio Settings +#+begin_src shell :tangle pkg-list.txt +pavucontrol +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'Audio Settings' +dropdown_groups_info.append((name, + DropDown(name, + 'pavucontrol' + ), + ['mod1','control'],'a')) +#+end_src +***** DropDown [[https://wiki.archlinux.org/title/PCManFM][PCManFM]] +#+begin_src shell :tangle pkg-list.txt +pcmanfm-gtk3 +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'filemanager' +dropdown_groups_info.append((name, + DropDown(name, + 'pcmanfm', + on_focus_lost_hide=False + ), + ['mod1','control'],'e')) +#+end_src +***** [[https://bitwarden.com/][Bitwarden]] +#+begin_src shell :tangle pkg-list.txt +bitwarden +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'Bitwarden' +dropdown_groups_info.append((name, + DropDown(name, + 'bitwarden-desktop', + on_focus_lost_hide=False, + match = Match(wm_class='bitwarden') + ), + ['mod1','control'],'b')) +#+end_src +***** WhatsApp +#+begin_src shell :tangle pkg-list.txt +whatsapp-nativefier +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'WhatsApp' +dropdown_groups_info.append((name, + DropDown(name, + 'whatsapp-nativefier', + height = 0.5, + width = 0.8, + x = .1, + on_focus_lost_hide=False, + opacity=1 + ), + ['mod1','control'],'w')) +#+end_src + +***** [[https://www.signal.org/][Signal]] +#+begin_src shell :tangle pkg-list.txt +signal-desktop +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'Signal' +dropdown_groups_info.append((name, + DropDown(name, + 'signal-desktop', + height = 0.5, + width = 0.8, + x = .1, + on_focus_lost_hide=False, + opacity = 1, + match = Match(wm_class='signal') + ), + ['mod1','control'],'i')) +#+end_src +***** [[https://qalculate.github.io/][Qalculate!]] +#+begin_src shell :tangle pkg-list.txt +qalculate-gtk +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'Qalculate!' +dropdown_groups_info.append((name, + DropDown(name, + 'qalculate-gtk', + height = 0.5, + width = 0.5, + x = .25, + on_focus_lost_hide=True, + opacity = 1 + ), + ['mod1','control'],'q')) +#+end_src +***** [[https://slack.com][Slack]] +#+begin_src shell :tangle pkg-list.txt +slack-desktop +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'Slack' +dropdown_groups_info.append((name, + DropDown(name, + 'slack', + height = 0.5, + width = 0.8, + x = 0.1, + on_focus_lost_hide=False, + opacity=1 + ), + ['mod1','control'],'s')) +#+end_src +***** [[https://www.deepl.com/translator][DeepL]] +DeepL is being used inside a [[https://surf.suckless.org/][surf]] DropDown +#+begin_src shell :tangle pkg-list.txt +surf +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'DeepL' +dropdown_groups_info.append((name, + DropDown(name, + 'surf deepl.com', + height = 0.5, + width = 0.8, + x = 0.1, + on_focus_lost_hide=True, + opacity=1 + ), + ['mod1','control'],'d')) +#+end_src +***** [[https://telegram.org/][Telegram]] +#+begin_src shell :tangle pkg-list.txt +telegram-desktop +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'Telegram' +dropdown_groups_info.append((name, + DropDown(name, + 'telegram-desktop', + height = 0.5, + width = 0.8, + x = 0.1, + on_focus_lost_hide=False, + opacity=1, + match = Match(wm_class='telegram-desktop') + ), + ['mod1','control'],'t')) +#+end_src +***** Org Agenda +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +name = 'Org Agenda' +dropdown_groups_info.append((name, + DropDown(name, + 'emacsclient -c -e \'(org-agenda-list)\'', + height = 0.5, + width = 0.8, + x = 0.1, + on_focus_lost_hide=True, + opacity=1, + match = Match(wm_class='emacs') + ), + ['mod1','control'],'k')) +#+end_src +***** Add ScratchPad to Groups +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +groups.append(ScratchPad("scratchpad", + [dropdown for (name,dropdown,base_keys,key) in dropdown_groups_info] + )) +#+end_src +**** Hotkeys +***** Main Group Hotkeys +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +try: + _ = keys +except NameError: + keys = [] +for (icon,name,key, kwargs) in main_groups_info: + keys.extend([ + Key(["mod1","control"], str(key), lazy.group[icon].toscreen(toggle=True), + desc="Switch to group {}".format(name)), + + Key(['mod1','control', "shift"], str(key), lazy.window.togroup(icon), + desc="move focused window to group {}".format(name)), + ]) +#+end_src +***** DropDown Group Hotkeys +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +try: + _ = keys +except NameError: + keys = [] +for (name,dropdown,base_keys,key) in dropdown_groups_info: + keys.extend([ +Key(base_keys,key,lazy.group['scratchpad'].dropdown_toggle(name), desc=f'open the dropdown for {name}') + ]) +#+end_src +*** Keys +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +from libqtile.config import Key +from libqtile.command import lazy + +from defines import mod, term +from chassis_type import ChassisType, chassis_type + +try: + _ = keys +except NameError: + keys = [] +#+end_src +**** Screen Lock +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod], "End" , lazy.spawn('dm-tool lock'),desc="locks session"), + Key([], "Pause" , lazy.spawn('dm-tool lock'),desc="locks session") +]) +#+end_src +**** Moving Focus +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod], "h", lazy.layout.left(),desc="move focus left"), + Key([mod], "l", lazy.layout.right(),desc="move focus right"), + Key([mod], "j", lazy.layout.down(),desc="move focus down"), + Key([mod], "k", lazy.layout.up(),desc="move focus up"), + Key([mod,"mod1"], "n", lazy.next_screen(),desc="move focus to next screen") +]) +#+end_src +**** Moving Windows +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod, "shift"], "h", lazy.layout.swap_left(),desc="move focused window left"), + Key([mod, "shift"], "l", lazy.layout.swap_right(),desc="move focused window right"), + Key([mod, "shift"], "j", lazy.layout.shuffle_down(),desc="move focused window down"), + Key([mod, "shift"], "k", lazy.layout.shuffle_up(),desc="move focused window up"), +]) +#+end_src +**** Resize Windows +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod], "plus", lazy.layout.grow(),desc="increase window size"), + Key([mod], "minus", lazy.layout.shrink(),desc="decrease window size"), + Key([mod], "m", lazy.layout.maximize(),desc="maximize current window"), + Key([mod], "space", lazy.window.toggle_fullscreen(),desc="toggle current window fullscreen"), +]) +#+end_src +**** Toggle Layouts +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod], "Tab", lazy.next_layout(), desc="Toggle between layouts"), +]) +#+end_src +**** Close Current Window +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod], "BackSpace", lazy.window.kill(), desc="Kill focused window"), +]) +#+end_src +**** Qtile Meta Commands +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod, "control"], "r", lazy.restart(), desc="Restart qtile"), + Key([mod, "control"], "q", lazy.shutdown(), desc="Shutdown qtile"), +]) +#+end_src +**** Audio +#+begin_src shell :tangle pkg-list.txt +pulseaudio-ctl +alsa-utils +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([], 'XF86AudioRaiseVolume', lazy.spawn(f'pulseaudio-ctl up {5 if chassis_type == ChassisType.LAPTOP else 1}'), desc="increase speaker volume"), + Key([], 'XF86AudioLowerVolume', lazy.spawn(f'pulseaudio-ctl down {5 if chassis_type == ChassisType.LAPTOP else 1}'), desc="decrease speaker volume"), + Key([], 'XF86AudioMute', lazy.spawn('pulseaudio-ctl mute'), desc="toggle speaker mute"), + Key(['control'], 'XF86AudioRaiseVolume', lazy.spawn(f'amixer set Capture {5 if chassis_type == ChassisType.LAPTOP else 1}%+'), desc="increase mic volume"), + Key(['control'], 'XF86AudioLowerVolume', lazy.spawn(f'amixer set Capture {5 if chassis_type == ChassisType.LAPTOP else 1}%-'), desc="decrease mic volume"), + Key(['control'], 'XF86AudioMute', lazy.spawn('amixer set Capture toggle'), desc="toggle mic mute"), + Key([], 'XF86AudioMicMute', lazy.spawn('amixer set Capture toggle'), desc="toggle mic mute"), +]) +#+end_src +**** Media Playback +#+begin_src shell :tangle pkg-list.txt +playerctl +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([], 'XF86AudioNext', lazy.spawn('playerctl next')), + Key([], 'XF86AudioPrev', lazy.spawn('playerctl previous')), + Key([], 'XF86AudioPlay', lazy.spawn('playerctl play-pause')), + Key([mod], 'Right', lazy.spawn('playerctl next')), + Key([mod], 'Left', lazy.spawn('playerctl previous')), + Key([mod], 'Down', lazy.spawn('playerctl play-pause')), +]) +#+end_src +**** Monitor Backlight +#+begin_src shell :tangle pkg-list.txt +acpilight +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([], 'XF86MonBrightnessUp', lazy.spawn('xbacklight -inc 5')), + Key([], 'XF86MonBrightnessDown', lazy.spawn('xbacklight -dec 5')), +]) +#+end_src +**** App Launch Hotkeys +***** Terminal +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod],"t", lazy.spawn(term), desc="Launch terminal"), +]) +#+end_src +***** [[Firefox]] +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod],"f", lazy.spawn("firefox"),desc="Launch firefox"), +]) +#+end_src +***** PCManFM +#+begin_src shell :tangle pkg-list.txt +pcmanfm-gtk3 +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod],"e", lazy.spawn("pcmanfm"),desc="Launch pcmanfm"), +]) +#+end_src +***** [[VSCode]] +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod],"c", lazy.spawn("code"),desc="Launch visual studio code"), +]) +#+end_src +***** [[NeoVim]] +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod],"v", lazy.spawn(term + " -e nvim"),desc="Launch NeoVim"), +]) +#+end_src +***** Screenshot Tool +#+begin_src shell :tangle pkg-list.txt +gscreenshot +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod, "shift"],"s", lazy.spawn('gscreenshot -s -o -f /tmp/screenshots'),desc="take a screenshot"), +]) +#+end_src +***** [[Doom Emacs]] +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod], "o", lazy.spawn("emacsclient -c -a 'emacs'"), desc="Launch Emacs (Client)"), +]) +#+end_src +***** App Launcher +#+begin_src shell :tangle pkg-list.txt +rofi +#+end_src +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +keys.extend([ + Key([mod],'Return',lazy.spawn("rofi -show drun -show-icons -modi drun"),desc="launch rofi (drun)"), +]) +#+end_src +*** Misc +Miscelaneous settings from the [[https://docs.qtile.org/en/stable/manual/config/default.html][default config]] +**** Deactivate dgroups +dynamic group keys are not needed, because they are assigned manually +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +dgroups_key_binder = None +dgroups_app_rules = [] # type: List +#+end_src +**** Setting WM Name +Nobody really uses or cares about this string besides java UI toolkits; +you can see several discussions on the mailing lists, GitHub issues, and other WM documentation that suggest setting this string if your java app doesn't work correctly. +We may as well just lie and say that we're a working one by default. +We choose LG3D to maximize irony: +it is a 3D non-reparenting WM written in java that happens to be on java's whitelist. +#+begin_src python :tangle ~/.config/qtile/config.py :mkdirp yes +wmname = 'LG3D' +#+end_src * Text Editors ** Doom Emacs *** Installation @@ -448,7 +1535,7 @@ fi export PATH=$PATH:~/.config/emacs/bin #+end_src *** Doom Modules -#+begin_src emacs-lisp :tangle ~/.config/doom/init.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/init.el (doom! :input ;;bidi ; (tfel ot) thgir etirw uoy gnipleh ;;chinese @@ -584,7 +1671,7 @@ export PATH=$PATH:~/.config/emacs/bin (latex +fold +latexmk +lsp) ; writing papers in Emacs has never been so fun ;;lean ; for folks with too much to prove ;;ledger ; be audit you can be - ;;lua ; one-based indices? one-based indices + lua ; one-based indices? one-based indices ;; markdown ; writing docs for people to ignore ;;nim ; python + lisp at the speed of c ;;nix ; I hereby declare "nix geht mehr!" @@ -631,8 +1718,8 @@ export PATH=$PATH:~/.config/emacs/bin #+end_src *** General Configuration -**** TODO User Information -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +**** User Information +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (setq user-full-name "Paul Lödige" user-mail-address "paul@gve-loedige.de") #+end_src @@ -646,7 +1733,7 @@ ttf-ubuntu-mono-nerd ttf-ubuntu-nerd #+end_src and activate it -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (setq doom-font (font-spec :family "Ubuntu Mono" :size 16) doom-variable-pitch-font (font-spec :family "Ubuntu" :size 14)) #+end_src @@ -654,30 +1741,35 @@ and activate it ***** Line Numbering having used Neovim for quiet some time I got used to relative line numbering for navigation. Until I get used to the [[https://github.com/Greduan/emacs-theme-gruvbox][evil-snipe]] navigation I would like to keep them. -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (setq display-line-numbers-type 'relative) #+end_src **** TODO Authentication Authentication information will be stored in a encrypted file that is part of my dotfiles -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (setq auth-sources '((:source "~/.authinfo.gpg"))) #+end_src +**** Start Daemon on Startup +#+begin_src shell :tangle ~/.config/autostart.sh +emacs --daemon & +#+end_src **** Misc ***** Set Start of Week to Monday -#+begin_src emacs-lisp :tangle ~/.config/doom/init.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/init.el (setq calendar-week-start-day 1) #+end_src *** Multilanguage Spellcheck Enables use of multiple dictionaries. In my case German and English install dependencies -#+begin_src shell :tangle pgk-list.txt +#+begin_src shell :tangle pkg-list.txt +hunspell hunspell-de hunspell-en_us #+end_src and configure it -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (with-eval-after-load "ispell" (setq ispell-program-name "hunspell") (setq ispell-dictionary "en_US,de_DE") @@ -688,6 +1780,7 @@ and configure it *** TODO LaTeX install texlive #+begin_src shell :tangle pkg-list.txt +biber texlive-basic texlive-bibtexextra texlive-binextra @@ -729,13 +1822,13 @@ texlive-publishers texlive-xetex #+end_src **** Set PDF Viewer -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (setq +latex-viewers '(zathura)) #+end_src **** Add auto-compile hook for TeX mode Because TeX-command-run-all is an interactive command we need a helper function for the hook. This function could also become useful if we ever want to extend the compile command -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (defun custom-tex-compile () (interactive) (TeX-command-run-all nil)) @@ -753,23 +1846,23 @@ gnome-screenshot graphviz #+end_src **** Default Location -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (setq org-directory "~/org/") #+end_src **** Visual ***** Enable Header Numbering -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org (setq org-startup-numerated t)) #+end_src ***** Image Display as Default [[https://emacs.stackexchange.com/questions/57603/how-to-always-display-inline-images-by-default-existing-solutions-dont-seem-to#comment89772_57607][this stackexchange comment]] states that this has to be done before the [[Add "~/org" to Agenda][adding the ~/org directory to Org Agenda]] -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org (setq org-startup-with-inline-images t)) #+end_src ***** Enable \LaTeX preview on default -#+begin_src emacs-lisp :tangle ~/.config/doom/init.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/init.el (after! org (setq org-startup-latex-with-latex-preview t)) #+end_src @@ -778,18 +1871,18 @@ graphviz [[https://github.com/dengste/org-caldav][org-caldav]] provides a tool for syncing with a CalDAV server (in my case Nextcloud). A lot of the config is also taken from [[https://www.reddit.com/r/orgmode/comments/8rl8ep/comment/e0sb5j0/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button][this]] reddit post. ***** org-caldav installation -#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/packages.el (package! org-caldav) #+end_src ***** Enable TODOs -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org-caldav (setq org-icalendar-include-todo 'all org-caldav-sync-todo t)) #+end_src ***** Configure Sync add the calendars to the org-caldav config -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org-caldav (setq org-caldav-url "https://cloud.ploedige.com/remote.php/dav/calendars/paul-loedige") (setq org-caldav-sync-direction 'org->cal) @@ -803,18 +1896,18 @@ To get a more nuanced overview of my current TODOs I add more progress states. |------------+----------+------+---------+-------------+--------+---------+---+------+-----------+----------+---| | Access Key | i | t | b | i | r | t | | d | | c | | | Log Type | time | time | note | time | note | note | | time | note | note | | -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org (setq org-todo-keywords '((sequence "INACTIVE(i!)" "TODO(t!)" "IN_PROGRESS(p!)" "BLOCKED(b@)" "REVIEW(r@)" "TESTING(e@)" "|" "DONE(d!)" "DELEGATED(x@)" "CANCELED(c@)")))) #+end_src Also set the percent states for [[*CalDAV Sync][CalDAV Sync]] -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org-caldav (setq org-caldav-todo-percent-states '((0 "INACTIVE") (1 "TODO") (2 "IN_PROGRESS") (3 "BLOCKED") (90 "REVIEW") (90 "TESTING") (100 "DONE") (100 "DELEGATED") (100 "CANCELED")))) #+end_src ***** Add "~/org" to Agenda -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org (setq org-agenda-files (f-files "~/org" (lambda (f) @@ -824,7 +1917,7 @@ Also set the percent states for [[*CalDAV Sync][CalDAV Sync]] **** Org Roam ***** set base directory Both the org files themselves and the database should be located in the same directory to enable syncing via Nextcloud -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org (setq org-roam-directory (file-truename "~/org/org-roam")) (org-roam-db-autosync-mode)) @@ -832,7 +1925,7 @@ Both the org files themselves and the database should be located in the same dir ***** Note Templates This contains all the capture templates I am using. Adding the "#+category: " tag improves the Org Agenda View for tasks captured in Org Roam -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org-roam (setq org-roam-capture-templates '(("d" "default" plain @@ -848,19 +1941,22 @@ Adding the "#+category: " tag improves the Org Agenda View for tasks captured in ***** Misc ****** Follow Links on RET Because the normal shortcut for `org-open-at-point` is quite cumbersome I want it to just follow links when clicking the RET button -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org (setq return-follows-link t)) #+end_src **** Org Transclusion ***** Installation -#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/packages.el (package! org-transclusion) #+end_src **** Bibliography -***** TODO Enabling Zotero Links +***** Enabling Zotero Links +#+begin_src shell :tangle pkg-list.txt +zotero +#+end_src Following [[https://www.riccardopinosio.com/blog/posts/zotero_notes_article.html#opening-zotero-pdf-from-org-roam][this guide]] we enable using zotero links with the following code -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! org :custom (org-link-set-parameters "zotero" :follow @@ -871,7 +1967,7 @@ Following [[https://www.riccardopinosio.com/blog/posts/zotero_notes_article.html ***** Citar Config ****** Setting the Citar Bibliography Following the [[https://github.com/doomemacs/doomemacs/tree/master/modules/tools/biblio][Doom Emacs documentation ]]we set the citar bibliography and notes paths -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! oc (setq citar-bibliography '("~/org/biblio.bib")) (setq citar-notes-paths '("~/org/org-roam/"))) @@ -879,7 +1975,7 @@ Following the [[https://github.com/doomemacs/doomemacs/tree/master/modules/tools ****** Citar Templates Following the [[https://github.com/emacs-citar/citar#configuration][citar package documentation]] we modify the note template to contain the pdf link to Zotero *NOTE:* This requires the a [[https://www.riccardopinosio.com/blog/posts/zotero_notes_article.html#opening-zotero-pdf-from-org-roam][specific Zotero Export Configuration]] -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! oc (setq citar-templates '((main . "${author editor:30%sn} ${date year issued:4} ${title:48}") @@ -889,7 +1985,7 @@ Following the [[https://github.com/emacs-citar/citar#configuration][citar packag #+end_src ****** Enable Zotero Link Support In [[https://www.riccardopinosio.com/blog/posts/zotero_notes_article.html#citar][this tutorial]] I found the config for enabling Zotero Link Support through Citar -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! citar (defadvice! riccardo/citar-file-trust-zotero (oldfun &rest r) "Leave Zotero-generated file paths alone, especially zotero://..." @@ -900,23 +1996,33 @@ In [[https://www.riccardopinosio.com/blog/posts/zotero_notes_article.html#citar] (add-to-list 'citar-file-open-functions '("pdf" . citar-file-open-external))) #+end_src +**** Poly-Org +[[Polymode]] for Org +#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el +(package! poly-org) +#+end_src +#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +;; (after! org +;; (require 'poly-org)) +#+end_src +*** Polymode +[[https://polymode.github.io/][Polymode]] enables using multiple major modes inside a single buffer. +This is especially useful for Org Mode as it allows for better code editing inside code blocks +#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el +(package! polymode) +#+end_src *** TODO Python install dependencies #+begin_src shell :tangle pkg-list.txt python-isort python-pipenv python-pytest -miniconda3 -#+end_src -#+begin_src shell :tangle update.sh -if [ ! -e "/etc/profile.d/conda.sh" ]; then - sudo ln -s /opt/miniconda3/etc/profile.d/conda.sh /etc/profile.d/conda.sh -fi +pyright #+end_src **** Set Debugger to debugpy as per the [[https://github.com/doomemacs/doomemacs/tree/master/modules/tools/debugger#dap-python][Doom Emacs Documentation]] it is recommended to set the debugger used for python debugging to debugpy -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (after! dap-mode (setq dap-python-debugger 'debugpy)) #+end_src @@ -926,13 +2032,68 @@ as per the [[https://github.com/doomemacs/doomemacs/tree/master/modules/tools/de #+begin_src shell :tangle pkg-list.txt visual-studio-code-bin #+end_src -*** TODO Add-Ons -** [[https://neovim.io/][Neovim]] +*** Add-On Configuration +**** Config File Header +#+begin_src shell :tangle vscode-extensions.txt +# DO NOT EDIT THIS FILE DIRECTLY +# This is a file generated from a literate programing source file +# You should make any changes there and regenerate it from Emacs org-mode +# using org-babel-tangle (C-c C-v t) + +#+end_src +**** Basic Look & Feel Extensions +***** [[https://github.com/VSCodeVim/Vim][Vim Key Bindings]] +#+begin_src shell :tangle vscode-extensions.txt +vscodevim.vim +#+end_src +**** Useful Tools +***** [[https://github.com/ChristianKohler/PathIntellisense][Path Intellisense]] +#+begin_src shell :tangle vscode-extensions.txt +christian-kohler.path-intellisense +#+end_src +***** [[https://github.com/streetsidesoftware/vscode-spell-checker][Spellcheck]] +#+begin_src shell :tangle vscode-extensions.txt +streetsidesoftware.code-spell-checker +#+end_src +**** Languages +***** [[https://github.com/Microsoft/vscode-python][Python]] +#+begin_src shell :tangle vscode-extensions.txt +ms-python.python +donjayamanne.python-environment-manager +#+end_src + +*** Add-On Sync +remove all packages not in ~vscode-extensions.txt~ and install otherwise +#+begin_src shell :tangle update.sh +INSTALLED_EXTENSIONS=$(code --list-extensions) +KEEP_LIST=$(grep -v '^#' "vscode-extensions.txt") + +for EXTENSION in $INSTALLED_EXTENSIONS; do + if ! echo "$KEEP_LIST" | grep -q "^$EXTENSION$"; then + echo "Removing VS Code Extension: $EXTENSION" + code --uninstall-extension "$EXTENSION" + fi +done +for EXTENSION in $KEEP_LIST; do + echo "Installing VS Code Extension: $EXTENSION" + code --install-extension "$EXTENSION" +done +#+end_src +** NeoVim +[[https://neovim.io/][NeoVim Documentation]] *** Installation #+begin_src shell :tangle pkg-list.txt neovim #+end_src *** TODO Configuration +* Browser +** Firefox +*** Installation +#+begin_src shell :tangle pkg-list.txt +firefox +#+end_src +*** TODO Configuration + * Shells ZSH is used as the default shell ** Aliases @@ -979,7 +2140,7 @@ which #+end_src *** Set as default shell #+begin_src shell :tangle update.sh -if [ "$(basename "$SHELL")" != "zsh" ]; then +if [ "$(basename $SHELL)" != "zsh" ]; then chsh -s $(which zsh) fi #+end_src @@ -1095,18 +2256,52 @@ and start neofetch #+end_src -* Themeing +* Theming +This Config applies the [[https://github.com/gruvbox-community/gruvbox][Gruvbox Theme]] to as many programs as possible ** Doom Emacs -I like the [[https://github.com/Greduan/emacs-theme-gruvbox][Gruvbox Theme by Eduardo Lavaque]]. -For this we first need to install the specific package -#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el +Install specific package +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/packages.el (package! gruvbox-theme) #+end_src and then set it -#+begin_src emacs-lisp :tangle ~/.config/doom/config.el +#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/doom/config.el (setq doom-theme 'gruvbox-dark-hard) #+end_src +** VSCode +#+begin_src shell :tangle vscode-extensions.txt +jdinhlife.gruvbox +#+end_src +** Qtile +#+begin_src python :tangle ~/.config/qtile/defines.py :mkdirp yes +focus_color = '#076678' + +light_foreground_color = ['#fbf1c7','#fbf1c7'] +dark_foreground_color = ['#282828','#282828'] +background_color0 = ['#1d2021','#1d2021'] +background_color8 = ['#7c6f64','#7c6f64'] +base_color = background_color0 +# red +red_color = ['#cc241d','#cc241d'] +light_red_color = ['#fb4934','#fb4934'] +# green +green_color = ['#98971a','#98971a'] +light_green_color = ['#b8bb26','#b8bb26'] +#orange +orange_color = ['#d65d0e','#d65d0e'] +# yellow +yellow_color = ['#d79921','#d79921'] +light_yellow_color = ['#fabd2f','#fabd2f'] +#blue +blue_color = ['#076678','#076678'] +# purple +purple_color = ['#b16286','#b16286'] +light_purple_color = ['#d3869b','#d3869b'] +# magenta +magenta_color = ['#ff79c6','#ff79c6'] +# cyan +cyan_color = ['#8be9fd','#8be9fd'] +#+end_src * Git ** Installation #+begin_src shell :tangle pkg-list.txt @@ -1124,17 +2319,79 @@ set default branch to =main= [init] defaultBranch = main #+end_src -* Misc Programs +* Miniconda +** Installation +#+begin_src shell :tangle pkg-list.txt +miniconda3 +#+end_src +universal link +#+begin_src shell :tangle update.sh +if [ ! -e "/etc/profile.d/conda.sh" ]; then + sudo ln -s /opt/miniconda3/etc/profile.d/conda.sh /etc/profile.d/conda.sh +fi +#+end_src +add to path +#+begin_src shell :tangle ~/.path.sh +source /etc/profile.d/conda.sh +export PATH="/opt/miniconda3/bin:$PATH" +#+end_src +** ZSH special settings +#+begin_src shell :tangle ~/.zshrc +# >>> conda initialize >>> +# !! Contents within this block are managed by 'conda init' !! +__conda_setup="$('/opt/miniconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)" +if [ $? -eq 0 ]; then + eval "$__conda_setup" +else + if [ -f "/opt/miniconda3/etc/profile.d/conda.sh" ]; then + . "/opt/miniconda3/etc/profile.d/conda.sh" + else + export PATH="/opt/miniconda3/bin:$PATH" + fi +fi +unset __conda_setup +# <<< conda initialize <<< +#+end_src +** Do not activate base environment on startup +#+begin_src shell :tangle ~/.condarc +auto_activate_base: false +#+end_src +* TODO Misc Programs ** Zathura *** Installation #+begin_src shell :tangle pkg-list.txt zathura #+end_src *** enable synctex -#+begin_src shell :tangle ~/.config/zathura/zathurarc :mkdirp yes +#+begin_src shell :mkdirp yes :tangle ~/.config/zathura/zathurarc set synctex true #+end_src ** Nextcloud #+begin_src shell :tangle pkg-list.txt nextcloud-client #+end_src +** Bitwarden +*** Installation +#+begin_src shell :tangle pkg-list.txt +bitwarden +#+end_src +*** TODO Configuration + +** Inkscape +*** Installation +#+begin_src shell :tangle pkg-list.txt +inkscape +#+end_src +* Manual Tasks after tangling +1. run ~update.sh~ +2. setup Nextcloud sync directories +3. sign into Bitwarden +4. add Firefox Account +5. configure networks + - [[https://www.scc.kit.edu/dienste/7181.php][eduroam]] + +* Other TODOs +** TODO configure Bitwarden via config file +- remove manual task afterwards +** TODO add Firefox user via update.sh +- remove manual task afterwards