From 0f1a3535a44ec35461bc1c56f8e497d36e8aec32 Mon Sep 17 00:00:00 2001 From: hazel levine Date: Mon, 1 Jun 2020 10:44:54 -0400 Subject: [PATCH] init --- .gitignore | 7 + README.md | 16 + UNLICENSE | 24 + config/X/Xresources | 36 + config/alacritty/alacritty.yml | 202 +++++ config/bat/config | 2 + config/bin/backlight | 23 + config/bin/berun | 23 + config/bin/blocks | 24 + config/bin/emacsc | 3 + config/bin/import-gsettings | 14 + config/bin/keyboard | 64 ++ config/bin/notify-action-alt | 68 ++ config/bin/notify-alt | 312 +++++++ config/bin/scrot | 48 ++ config/bin/volume | 37 + config/bin/xbps-menu | 86 ++ config/doom/blog.org | 191 +++++ config/doom/config.org | 306 +++++++ config/doom/init.el | 93 ++ config/doom/nice.png | Bin 0 -> 93331 bytes config/firefox/userChrome.css | 948 +++++++++++++++++++++ config/fontconfig/conf.d/10-preferred.conf | 71 ++ config/fontconfig/conf.d/69-emoji.conf | 25 + config/fontconfig/conf.d/70-no-dejavu.conf | 30 + config/fontconfig/fonts.conf | 5 + config/i3status-rust/status.toml | 51 ++ config/ncmpcpp/config | 141 +++ config/tmux/tmux.conf | 84 ++ config/tridactyl/tridactylrc | 31 + config/zathura/zathurarc | 31 + config/zsh/zprofile | 41 + config/zsh/zshrc | 210 +++++ home.nix | 57 ++ modules/default.nix | 8 + modules/desktop/alacritty.nix | 6 + modules/desktop/default.nix | 13 + modules/desktop/dirs.nix | 19 + modules/desktop/firefox.nix | 25 + modules/desktop/gtk.nix | 16 + modules/desktop/mako.nix | 26 + modules/desktop/mpd.nix | 62 ++ modules/desktop/sway.nix | 267 ++++++ modules/desktop/zathura.nix | 7 + modules/lang/c.nix | 10 + modules/lang/default.nix | 11 + modules/lang/lisp.nix | 12 + modules/lang/python.nix | 14 + modules/lang/rust.nix | 7 + modules/lang/scala.nix | 11 + modules/lang/tex.nix | 11 + modules/tools/bat.nix | 8 + modules/tools/default.nix | 12 + modules/tools/emacs.nix | 34 + modules/tools/git.nix | 29 + modules/tools/mail.nix | 45 + modules/tools/nix.nix | 10 + modules/tools/passwords.nix | 13 + modules/tools/tmux.nix | 6 + modules/tools/zsh.nix | 27 + packages/bw-git-helper.nix | 29 + packages/default.nix | 32 + packages/zr.nix | 24 + system/configuration.nix | 68 ++ system/desktop.nix | 19 + system/fan-control.nix | 35 + system/fonts.nix | 28 + system/hardware-configuration.nix | 34 + system/networking.nix | 41 + system/power.nix | 33 + 70 files changed, 4356 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 UNLICENSE create mode 100644 config/X/Xresources create mode 100644 config/alacritty/alacritty.yml create mode 100644 config/bat/config create mode 100755 config/bin/backlight create mode 100755 config/bin/berun create mode 100755 config/bin/blocks create mode 100755 config/bin/emacsc create mode 100755 config/bin/import-gsettings create mode 100755 config/bin/keyboard create mode 100755 config/bin/notify-action-alt create mode 100755 config/bin/notify-alt create mode 100755 config/bin/scrot create mode 100755 config/bin/volume create mode 100755 config/bin/xbps-menu create mode 100644 config/doom/blog.org create mode 100644 config/doom/config.org create mode 100644 config/doom/init.el create mode 100644 config/doom/nice.png create mode 100644 config/firefox/userChrome.css create mode 100644 config/fontconfig/conf.d/10-preferred.conf create mode 100644 config/fontconfig/conf.d/69-emoji.conf create mode 100644 config/fontconfig/conf.d/70-no-dejavu.conf create mode 100644 config/fontconfig/fonts.conf create mode 100644 config/i3status-rust/status.toml create mode 100644 config/ncmpcpp/config create mode 100644 config/tmux/tmux.conf create mode 100644 config/tridactyl/tridactylrc create mode 100644 config/zathura/zathurarc create mode 100644 config/zsh/zprofile create mode 100644 config/zsh/zshrc create mode 100644 home.nix create mode 100644 modules/default.nix create mode 100644 modules/desktop/alacritty.nix create mode 100644 modules/desktop/default.nix create mode 100644 modules/desktop/dirs.nix create mode 100644 modules/desktop/firefox.nix create mode 100644 modules/desktop/gtk.nix create mode 100644 modules/desktop/mako.nix create mode 100644 modules/desktop/mpd.nix create mode 100644 modules/desktop/sway.nix create mode 100644 modules/desktop/zathura.nix create mode 100644 modules/lang/c.nix create mode 100644 modules/lang/default.nix create mode 100644 modules/lang/lisp.nix create mode 100644 modules/lang/python.nix create mode 100644 modules/lang/rust.nix create mode 100644 modules/lang/scala.nix create mode 100644 modules/lang/tex.nix create mode 100644 modules/tools/bat.nix create mode 100644 modules/tools/default.nix create mode 100644 modules/tools/emacs.nix create mode 100644 modules/tools/git.nix create mode 100644 modules/tools/mail.nix create mode 100644 modules/tools/nix.nix create mode 100644 modules/tools/passwords.nix create mode 100644 modules/tools/tmux.nix create mode 100644 modules/tools/zsh.nix create mode 100644 packages/bw-git-helper.nix create mode 100644 packages/default.nix create mode 100644 packages/zr.nix create mode 100644 system/configuration.nix create mode 100644 system/desktop.nix create mode 100644 system/fan-control.nix create mode 100644 system/fonts.nix create mode 100644 system/hardware-configuration.nix create mode 100644 system/networking.nix create mode 100644 system/power.nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8fbbfb0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +config/doom/private.el +config/doom/config.el +config/doom/blog.el +config/doom/packages.el +*.elc +system/wg-privkey +config/mpdscribble/* diff --git a/README.md b/README.md new file mode 100644 index 0000000..105b88c --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +etc +--- + +My personal dotfiles. +This branch is dedicated to my experiments with NixOS. It will likely be merged +into master momentarily, as my new system runs NixOS. + +To install it: +- Copy things *selectively* in `system/` to `/etc/nixos` -- much of this is + only relevant if you are on my machine +- ln -s "$(pwd)" ~/.config/nixpkgs +- `home-manager switch` + +...but why would you install my dotfiles? They're mine, not yours. Go away. + +![why are you looking at the alt text](https://p.qtp2t.club/selif/setup.png) diff --git a/UNLICENSE b/UNLICENSE new file mode 100644 index 0000000..68a49da --- /dev/null +++ b/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/config/X/Xresources b/config/X/Xresources new file mode 100644 index 0000000..03bcfb2 --- /dev/null +++ b/config/X/Xresources @@ -0,0 +1,36 @@ +! xft font rendering +Xft.antialias: 1 +Xft.hinting: 1 +Xft.hintstyle: hintfull +Xft.lcdfilter: lcddefault +Xft.rgba: rgb + +! gruvbox +! hard contrast: *background: #f9f5d7 +*background: #fbf1c7 +! soft contrast: *background: #f2e5bc +*foreground: #3c3836 +! Black + DarkGrey +*color0: #fdf4c1 +*color8: #928374 +! DarkRed + Red +*color1: #cc241d +*color9: #9d0006 +! DarkGreen + Green +*color2: #98971a +*color10: #79740e +! DarkYellow + Yellow +*color3: #d79921 +*color11: #b57614 +! DarkBlue + Blue +*color4: #458588 +*color12: #076678 +! DarkMagenta + Magenta +*color5: #b16286 +*color13: #8f3f71 +! DarkCyan + Cyan +*color6: #689d6a +*color14: #427b58 +! LightGrey + White +*color7: #7c6f64 +*color15: #3c3836 diff --git a/config/alacritty/alacritty.yml b/config/alacritty/alacritty.yml new file mode 100644 index 0000000..10dd9e8 --- /dev/null +++ b/config/alacritty/alacritty.yml @@ -0,0 +1,202 @@ +## hazel's alacritty configuration +window: + dimensions: + columns: 80 + lines: 24 + padding: + x: 10 + y: 10 + decorations: full + +# When true, bold text is drawn using the bright variant of colors. +draw_bold_text_with_bright_colors: true + +font: + normal: + family: FiraCode + style: Regular + bold: + family: FiraCode + style: Regular + italic: + family: FiraCode + style: Regular + + size: 10.0 + + offset: + x: 0 + y: 0 + + glyph_offset: + x: 0 + y: 0 + +# Colors (Gruvbox light) +colors: + # Default colors + primary: + # hard contrast: background = '0xf9f5d7' + background: '0xfbf1c7' + # soft contrast: background = '0xf2e5bc' + foreground: '0x3c3836' + + # Normal colors + normal: + black: '0xfbf1c7' + red: '0xcc241d' + green: '0x98971a' + yellow: '0xd79921' + blue: '0x458588' + magenta: '0xb16286' + cyan: '0x689d6a' + white: '0x7c6f64' + + # Bright colors + bright: + black: '0x928374' + red: '0x9d0006' + green: '0x79740e' + yellow: '0xb57614' + blue: '0x076678' + magenta: '0x8f3f71' + cyan: '0x427b58' + white: '0x3c3836' + +visual_bell: + animation: EaseOutExpo + duration: 0 + +background_opacity: 1.0 + +mouse_bindings: + - { mouse: Middle, action: PasteSelection } + +mouse: + double_click: { threshold: 300 } + triple_click: { threshold: 300 } + + faux_scrolling_lines: 1 + + hide_when_typing: true + + url: + launcher: + program: xdg-open + args: [] + +selection: + semantic_escape_chars: ",│`|:\"' ()[]{}<>" + +cursor: + style: Underline + unfocused_hollow: true + +live_config_reload: true + +key_bindings: + - { key: V, mods: Control|Shift, action: Paste } + - { key: C, mods: Control|Shift, action: Copy } + - { key: Paste, action: Paste } + - { key: Copy, action: Copy } + - { key: Q, mods: Command, action: Quit } + - { key: W, mods: Command, action: Quit } + - { key: Insert, mods: Shift, action: PasteSelection } + - { key: Key0, mods: Control, action: ResetFontSize } + - { key: Equals, mods: Control, action: IncreaseFontSize } + - { key: Subtract, mods: Control, action: DecreaseFontSize } + - { key: Home, chars: "\x1bOH", mode: AppCursor } + - { key: Home, chars: "\x1b[H", mode: ~AppCursor } + - { key: End, chars: "\x1bOF", mode: AppCursor } + - { key: End, chars: "\x1b[F", mode: ~AppCursor } + - { key: PageUp, mods: Shift, chars: "\x1b[5;2~" } + - { key: PageUp, mods: Control, chars: "\x1b[5;5~" } + - { key: PageUp, chars: "\x1b[5~" } + - { key: PageDown, mods: Shift, chars: "\x1b[6;2~" } + - { key: PageDown, mods: Control, chars: "\x1b[6;5~" } + - { key: PageDown, chars: "\x1b[6~" } + - { key: Tab, mods: Shift, chars: "\x1b[Z" } + - { key: Back, chars: "\x7f" } + - { key: Back, mods: Alt, chars: "\x1b\x7f" } + - { key: Insert, chars: "\x1b[2~" } + - { key: Delete, chars: "\x1b[3~" } + - { key: Left, mods: Shift, chars: "\x1b[1;2D" } + - { key: Left, mods: Control, chars: "\x1b[1;5D" } + - { key: Left, mods: Alt, chars: "\x1b[1;3D" } + - { key: Left, chars: "\x1b[D", mode: ~AppCursor } + - { key: Left, chars: "\x1bOD", mode: AppCursor } + - { key: Right, mods: Shift, chars: "\x1b[1;2C" } + - { key: Right, mods: Control, chars: "\x1b[1;5C" } + - { key: Right, mods: Alt, chars: "\x1b[1;3C" } + - { key: Right, chars: "\x1b[C", mode: ~AppCursor } + - { key: Right, chars: "\x1bOC", mode: AppCursor } + - { key: Up, mods: Shift, chars: "\x1b[1;2A" } + - { key: Up, mods: Control, chars: "\x1b[1;5A" } + - { key: Up, mods: Alt, chars: "\x1b[1;3A" } + - { key: Up, chars: "\x1b[A", mode: ~AppCursor } + - { key: Up, chars: "\x1bOA", mode: AppCursor } + - { key: Down, mods: Shift, chars: "\x1b[1;2B" } + - { key: Down, mods: Control, chars: "\x1b[1;5B" } + - { key: Down, mods: Alt, chars: "\x1b[1;3B" } + - { key: Down, chars: "\x1b[B", mode: ~AppCursor } + - { key: Down, chars: "\x1bOB", mode: AppCursor } + - { key: F1, chars: "\x1bOP" } + - { key: F2, chars: "\x1bOQ" } + - { key: F3, chars: "\x1bOR" } + - { key: F4, chars: "\x1bOS" } + - { key: F5, chars: "\x1b[15~" } + - { key: F6, chars: "\x1b[17~" } + - { key: F7, chars: "\x1b[18~" } + - { key: F8, chars: "\x1b[19~" } + - { key: F9, chars: "\x1b[20~" } + - { key: F10, chars: "\x1b[21~" } + - { key: F11, chars: "\x1b[23~" } + - { key: F12, chars: "\x1b[24~" } + - { key: F1, mods: Shift, chars: "\x1b[1;2P" } + - { key: F2, mods: Shift, chars: "\x1b[1;2Q" } + - { key: F3, mods: Shift, chars: "\x1b[1;2R" } + - { key: F4, mods: Shift, chars: "\x1b[1;2S" } + - { key: F5, mods: Shift, chars: "\x1b[15;2~" } + - { key: F6, mods: Shift, chars: "\x1b[17;2~" } + - { key: F7, mods: Shift, chars: "\x1b[18;2~" } + - { key: F8, mods: Shift, chars: "\x1b[19;2~" } + - { key: F9, mods: Shift, chars: "\x1b[20;2~" } + - { key: F10, mods: Shift, chars: "\x1b[21;2~" } + - { key: F11, mods: Shift, chars: "\x1b[23;2~" } + - { key: F12, mods: Shift, chars: "\x1b[24;2~" } + - { key: F1, mods: Control, chars: "\x1b[1;5P" } + - { key: F2, mods: Control, chars: "\x1b[1;5Q" } + - { key: F3, mods: Control, chars: "\x1b[1;5R" } + - { key: F4, mods: Control, chars: "\x1b[1;5S" } + - { key: F5, mods: Control, chars: "\x1b[15;5~" } + - { key: F6, mods: Control, chars: "\x1b[17;5~" } + - { key: F7, mods: Control, chars: "\x1b[18;5~" } + - { key: F8, mods: Control, chars: "\x1b[19;5~" } + - { key: F9, mods: Control, chars: "\x1b[20;5~" } + - { key: F10, mods: Control, chars: "\x1b[21;5~" } + - { key: F11, mods: Control, chars: "\x1b[23;5~" } + - { key: F12, mods: Control, chars: "\x1b[24;5~" } + - { key: F1, mods: Alt, chars: "\x1b[1;6P" } + - { key: F2, mods: Alt, chars: "\x1b[1;6Q" } + - { key: F3, mods: Alt, chars: "\x1b[1;6R" } + - { key: F4, mods: Alt, chars: "\x1b[1;6S" } + - { key: F5, mods: Alt, chars: "\x1b[15;6~" } + - { key: F6, mods: Alt, chars: "\x1b[17;6~" } + - { key: F7, mods: Alt, chars: "\x1b[18;6~" } + - { key: F8, mods: Alt, chars: "\x1b[19;6~" } + - { key: F9, mods: Alt, chars: "\x1b[20;6~" } + - { key: F10, mods: Alt, chars: "\x1b[21;6~" } + - { key: F11, mods: Alt, chars: "\x1b[23;6~" } + - { key: F12, mods: Alt, chars: "\x1b[24;6~" } + - { key: F1, mods: Super, chars: "\x1b[1;3P" } + - { key: F2, mods: Super, chars: "\x1b[1;3Q" } + - { key: F3, mods: Super, chars: "\x1b[1;3R" } + - { key: F4, mods: Super, chars: "\x1b[1;3S" } + - { key: F5, mods: Super, chars: "\x1b[15;3~" } + - { key: F6, mods: Super, chars: "\x1b[17;3~" } + - { key: F7, mods: Super, chars: "\x1b[18;3~" } + - { key: F8, mods: Super, chars: "\x1b[19;3~" } + - { key: F9, mods: Super, chars: "\x1b[20;3~" } + - { key: F10, mods: Super, chars: "\x1b[21;3~" } + - { key: F11, mods: Super, chars: "\x1b[23;3~" } + - { key: F12, mods: Super, chars: "\x1b[24;3~" } diff --git a/config/bat/config b/config/bat/config new file mode 100644 index 0000000..c089ab6 --- /dev/null +++ b/config/bat/config @@ -0,0 +1,2 @@ +--theme="ansi-dark" +--style="numbers,changes,header" diff --git a/config/bin/backlight b/config/bin/backlight new file mode 100755 index 0000000..8ad86f1 --- /dev/null +++ b/config/bin/backlight @@ -0,0 +1,23 @@ +#!/bin/sh + +send_notification() { + backlight=$(brightnessctl -m | cut -d, -f4 | sed 's/%//' | awk '{print int($1 / 2.9)}') + # Make the bar with the special character ─ (it's not dash -) + # https://en.wikipedia.org/wiki/Box-drawing_character + bar=$(seq -s "─" "$backlight" | sed 's/[0-9]//g') + # Send the notification + makoctl dismiss + notify-send -t 1000 "mon: $bar" +} + +case $1 in + up) + brightnessctl -q set +10% + send_notification + ;; + down) + brightnessctl -q set 10%- + send_notification + ;; + *) echo "usage: backlight [up|down]" ;; +esac diff --git a/config/bin/berun b/config/bin/berun new file mode 100755 index 0000000..258fc3f --- /dev/null +++ b/config/bin/berun @@ -0,0 +1,23 @@ +#!/bin/sh + +## TODO: figure out whatever the fuck is happening here +#MONITORS="$(swaymsg -t get_outputs | jq -r 'length')" +#FOCUSED="$(swaymsg -t get_workspaces | jq -r '.. | select(.focused?) | .output')" + +#case $FOCUSED in +# eDP1) +#esac + +BG="$(xrq background)" +FG="$(xrq foreground)" +BLK="$(xrq color0)" +HL="$(xrq color1)" +FONT="FiraCode 9" +PROMPT=">" +LINES=10 +LH=20 + +bemenu -m -1 -n -p "$PROMPT" -l "$LINES" --fn "$FONT" -H "$LH" --scrollbar always \ + --tb "$HL" --tf "$BLK" --nb "$BG" --nf "$FG" \ + --hb "$BG" --hf "$HL" --fb "$BLK" --ff "$FG" \ + --scb "$BLK" --scf "$HL" diff --git a/config/bin/blocks b/config/bin/blocks new file mode 100755 index 0000000..c2a424f --- /dev/null +++ b/config/bin/blocks @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Show the terminal colourscheme as blocks +# Inspired by u/dkeg +# Cheers! Addy + +f=3 b=4 +for j in f b; do + for i in {0..7}; do + printf -v $j$i %b "\e[${!j}${i}m" + done +done +d=$'\e[1m' +t=$'\e[0m' +v=$'\e[7m' + +cat << EOF + + $f1██████$d██$t $f2██████$d██$t $f3██████$d██$t $f4██████$d██$t $f5██████$d██$t $f6██████$d██$t + $f1██████$d██$t $f2██████$d██$t $f3██████$d██$t $f4██████$d██$t $f5██████$d██$t $f6██████$d██$t + $f1██████$d██$t $f2██████$d██$t $f3██████$d██$t $f4██████$d██$t $f5██████$d██$t $f6██████$d██$t + $ft██████$d$f7██$t $ft██████$d$f7██$t $ft██████$d$f7██$t $ft██████$d$f7██$t $ft██████$d$f7██$t $ft██████$d$f7██$t + +EOF diff --git a/config/bin/emacsc b/config/bin/emacsc new file mode 100755 index 0000000..1c5ba55 --- /dev/null +++ b/config/bin/emacsc @@ -0,0 +1,3 @@ +#!/bin/sh + +emacsclient -c --socket-name hazel-emacsd $@ diff --git a/config/bin/import-gsettings b/config/bin/import-gsettings new file mode 100755 index 0000000..fe2baff --- /dev/null +++ b/config/bin/import-gsettings @@ -0,0 +1,14 @@ +#!/bin/sh + +if [ -z "$@" ]; then + echo "usage: import-gsettings : : ..." + return 1 +fi + +expression="" +for pair in "$@"; do + IFS=:; set -- $pair + expressions="$expressions -e 's:^$2=(.*)$:gsettings set org.gnome.desktop.interface $1 \1:e'" +done +IFS= +eval exec sed -E $expressions "${XDG_CONFIG_HOME:-$HOME/.config}"/gtk-3.0/settings.ini >/dev/null diff --git a/config/bin/keyboard b/config/bin/keyboard new file mode 100755 index 0000000..3ddf796 --- /dev/null +++ b/config/bin/keyboard @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# +# Control keyboard layout and backlight (Lenovo ThinkPad tested only) +# +# Author: Dave Eddy +# Date: June 25, 2018 +# License: MIT + + +TMPFILE=/tmp/keyboard-status + +# taken from https://wiki.archlinux.org/index.php/Keyboard_backlight +setKeyboardLight() { + echo "$1" > "$TMPFILE" + + dbus-send --system --type=method_call \ + --dest='org.freedesktop.UPower' \ + '/org/freedesktop/UPower/KbdBacklight' \ + 'org.freedesktop.UPower.KbdBacklight.SetBrightness' \ + "int32:$1" +} + +# cycle the current state of the keyboard backlight +cycleKeyboardLight() { + local cur + cur="$(cat $TMPFILE)" + + case "$cur" in + 0) setKeyboardLight 1;; + 1) setKeyboardLight 2;; + 2) setKeyboardLight 0;; + *) exit 1;; + esac +} + +usage() { + local prog=${0##*/} + cat <<-EOF + Usage: $prog + + Examples + # control backlight + $prog [off | dim | bright/on] + + # print help + $prog help + EOF +} + +if [[ ! -f "$TMPFILE" ]]; then + echo '0' > "$TMPFILE" +fi + +case "$1" in + # lights + off) setKeyboardLight 0;; + dim) setKeyboardLight 1;; + on|bright) setKeyboardLight 2;; + cycle) cycleKeyboardLight;; + + help|-h) usage; exit 0;; + + *) usage >&2; exit 1;; +esac diff --git a/config/bin/notify-action-alt b/config/bin/notify-action-alt new file mode 100755 index 0000000..7b8dbb0 --- /dev/null +++ b/config/bin/notify-action-alt @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +GDBUS_MONITOR_PID=/tmp/notify-action-dbus-monitor.$$.pid +GDBUS_MONITOR=(gdbus monitor --session --dest org.freedesktop.Notifications --object-path /org/freedesktop/Notifications) + +NOTIFICATION_ID="$1" +if [[ -z "$NOTIFICATION_ID" ]]; then + echo "no notification id passed: $@" + exit 1; +fi +shift + +ACTION_COMMANDS=("$@") +if [[ -z "$ACTION_COMMANDS" ]]; then + echo "no action commands passed: $@" + exit 1; +fi + +cleanup() { + rm -f "$GDBUS_MONITOR_PID" +} + +create_pid_file(){ + rm -f "$GDBUS_MONITOR_PID" + umask 077 + touch "$GDBUS_MONITOR_PID" +} + +invoke_action() { + invoked_action_id="$1" + local action="" cmd="" + for index in "${!ACTION_COMMANDS[@]}"; do + if [[ $((index % 2)) == 0 ]]; then + action="${ACTION_COMMANDS[$index]}" + else + cmd="${ACTION_COMMANDS[$index]}" + if [[ "$action" == "$invoked_action_id" ]]; then + bash -c "${cmd}" & + fi + fi + done +} + +monitor() { + + create_pid_file + ( "${GDBUS_MONITOR[@]}" & echo $! >&3 ) 3>"$GDBUS_MONITOR_PID" | while read -r line + do + local closed_notification_id="$(sed '/^\/org\/freedesktop\/Notifications: org.freedesktop.Notifications.NotificationClosed (uint32 \([0-9]\+\), uint32 [0-9]\+)$/!d;s//\1/' <<< "$line")" + if [[ -n "$closed_notification_id" ]]; then + if [[ "$closed_notification_id" == "$NOTIFICATION_ID" ]]; then + invoke_action close + break + fi + else + local action_invoked="$(sed '/\/org\/freedesktop\/Notifications: org.freedesktop.Notifications.ActionInvoked (uint32 \([0-9]\+\), '\''\(.*\)'\'')$/!d;s//\1:\2/' <<< "$line")" + IFS=: read invoked_id action_id <<< "$action_invoked" + if [[ "$invoked_id" == "$NOTIFICATION_ID" ]]; then + invoke_action "$action_id" + break + fi + fi + done + kill $(<"$GDBUS_MONITOR_PID") + cleanup +} + +monitor diff --git a/config/bin/notify-alt b/config/bin/notify-alt new file mode 100755 index 0000000..0ef6edf --- /dev/null +++ b/config/bin/notify-alt @@ -0,0 +1,312 @@ +#!/usr/bin/env bash + +# notify-send.sh - drop-in replacement for notify-send with more features +# Copyright (C) 2015-2019 notify-send.sh authors (see AUTHORS file) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Desktop Notifications Specification +# https://developer.gnome.org/notification-spec/ + +VERSION=1.0 +NOTIFY_ARGS=(--session + --dest org.freedesktop.Notifications + --object-path /org/freedesktop/Notifications) +EXPIRE_TIME=-1 +APP_NAME="${0##*/}" +REPLACE_ID=0 +URGENCY=1 +HINTS=() +SUMMARY_SET=n + +help() { + cat < [BODY] - create a notification + +Help Options: + -?|--help Show help options + +Application Options: + -u, --urgency=LEVEL Specifies the urgency level (low, normal, critical). + -t, --expire-time=TIME Specifies the timeout in milliseconds at which to expire the notification. + -f, --force-expire Forcefully closes the notification when the notification has expired. + -a, --app-name=APP_NAME Specifies the app name for the icon. + -i, --icon=ICON[,ICON...] Specifies an icon filename or stock icon to display. + -c, --category=TYPE[,TYPE...] Specifies the notification category. + -h, --hint=TYPE:NAME:VALUE Specifies basic extra data to pass. Valid types are int, double, string and byte. + -o, --action=LABEL:COMMAND Specifies an action. Can be passed multiple times. LABEL is usually a button's label. COMMAND is a shell command executed when action is invoked. + -d, --default-action=COMMAND Specifies the default action which is usually invoked by clicking the notification. + -l, --close-action=COMMAND Specifies the action invoked when notification is closed. + -p, --print-id Print the notification ID to the standard output. + -r, --replace=ID Replace existing notification. + -R, --replace-file=FILE Store and load notification replace ID to/from this file. + -s, --close=ID Close notification. + -v, --version Version of the package. + +EOF +} + +convert_type() { + case "$1" in + int) echo int32 ;; + double|string|byte) echo "$1" ;; + *) echo error; return 1 ;; + esac +} + +make_action_key() { + echo "$(tr -dc _A-Z-a-z-0-9 <<< \"$1\")${RANDOM}" +} + +make_action() { + local action_key="$1" + printf -v text "%q" "$2" + echo "\"$action_key\", \"$text\"" +} + +make_hint() { + type=$(convert_type "$1") + [[ ! $? = 0 ]] && return 1 + name="$2" + [[ "$type" = string ]] && command="\"$3\"" || command="$3" + echo "\"$name\": <$type $command>" +} + +concat_actions() { + local result="$1" + shift + for s in "$@"; do + result="$result, $s" + done + echo "[$result]" +} + +concat_hints() { + local result="$1" + shift + for s in "$@"; do + result="$result, $s" + done + echo "{$result}" +} + +parse_notification_id(){ + sed 's/(uint32 \([0-9]\+\),)/\1/g' +} + +notify() { + local actions="$(concat_actions "${ACTIONS[@]}")" + local hints="$(concat_hints "${HINTS[@]}")" + + NOTIFICATION_ID=$(gdbus call "${NOTIFY_ARGS[@]}" \ + --method org.freedesktop.Notifications.Notify \ + "$APP_NAME" "$REPLACE_ID" "$ICON" "$SUMMARY" "$BODY" \ + "${actions}" "${hints}" "int32 $EXPIRE_TIME" \ + | parse_notification_id) + + if [[ -n "$STORE_ID" ]] ; then + echo "$NOTIFICATION_ID" > $STORE_ID + fi + if [[ -n "$PRINT_ID" ]] ; then + echo "$NOTIFICATION_ID" + fi + + if [[ -n "$FORCE_EXPIRE" ]] ; then + type bc &> /dev/null || { echo "bc command not found. Please install bc package."; exit 1; } + SLEEP_TIME="$(bc <<< "scale=3; $EXPIRE_TIME / 1000")" + ( sleep "$SLEEP_TIME" ; notify_close "$NOTIFICATION_ID" ) & + fi + + maybe_run_action_handler +} + +notify_close () { + gdbus call "${NOTIFY_ARGS[@]}" --method org.freedesktop.Notifications.CloseNotification "$1" >/dev/null +} + +process_urgency() { + case "$1" in + low) URGENCY=0 ;; + normal) URGENCY=1 ;; + critical) URGENCY=2 ;; + *) echo "Unknown urgency $URGENCY specified. Known urgency levels: low, normal, critical." + exit 1 + ;; + esac +} + +process_category() { + IFS=, read -a categories <<< "$1" + for category in "${categories[@]}"; do + hint="$(make_hint string category "$category")" + HINTS=("${HINTS[@]}" "$hint") + done +} + +process_hint() { + IFS=: read type name command <<< "$1" + if [[ -z "$name" ]] || [[ -z "$command" ]] ; then + echo "Invalid hint syntax specified. Use TYPE:NAME:VALUE." + exit 1 + fi + hint="$(make_hint "$type" "$name" "$command")" + if [[ ! $? = 0 ]] ; then + echo "Invalid hint type \"$type\". Valid types are int, double, string and byte." + exit 1 + fi + HINTS=("${HINTS[@]}" "$hint") +} + +maybe_run_action_handler() { + if [[ -n "$NOTIFICATION_ID" ]] && [[ -n "$ACTION_COMMANDS" ]]; then + local notify_action="$(dirname ${BASH_SOURCE[0]})/notify-action.sh" + if [[ -x "$notify_action" ]] ; then + "$notify_action" "$NOTIFICATION_ID" "${ACTION_COMMANDS[@]}" & + exit 0 + else + echo "executable file not found: $notify_action" + exit 1 + fi + fi +} + +process_action() { + IFS=: read name command <<<"$1" + if [[ -z "$name" ]] || [[ -z "$command" ]]; then + echo "Invalid action syntax specified. Use NAME:COMMAND." + exit 1 + fi + + local action_key="$(make_action_key "$name")" + ACTION_COMMANDS=("${ACTION_COMMANDS[@]}" "$action_key" "$command") + + local action="$(make_action "$action_key" "$name")" + ACTIONS=("${ACTIONS[@]}" "$action") +} + +process_special_action() { + action_key="$1" + command="$2" + + if [[ -z "$action_key" ]] || [[ -z "$command" ]]; then + echo "Command must not be empty" + exit 1 + fi + + ACTION_COMMANDS=("${ACTION_COMMANDS[@]}" "$action_key" "$command") + + if [[ "$action_key" != close ]]; then + local action="$(make_action "$action_key" "$name")" + ACTIONS=("${ACTIONS[@]}" "$action") + fi +} + +process_posargs() { + if [[ "$1" = -* ]] && ! [[ "$positional" = yes ]] ; then + echo "Unknown option $1" + exit 1 + else + if [[ "$SUMMARY_SET" = n ]]; then + SUMMARY="$1" + SUMMARY_SET=y + else + BODY="$1" + fi + fi +} + +while (( $# > 0 )) ; do + case "$1" in + -\?|--help) + help + exit 0 + ;; + -v|--version) + echo "${0##*/} $VERSION" + exit 0 + ;; + -u|--urgency|--urgency=*) + [[ "$1" = --urgency=* ]] && urgency="${1#*=}" || { shift; urgency="$1"; } + process_urgency "$urgency" + ;; + -t|--expire-time|--expire-time=*) + [[ "$1" = --expire-time=* ]] && EXPIRE_TIME="${1#*=}" || { shift; EXPIRE_TIME="$1"; } + ;; + -f|--force-expire) + FORCE_EXPIRE=yes + ;; + -a|--app-name|--app-name=*) + [[ "$1" = --app-name=* ]] && APP_NAME="${1#*=}" || { shift; APP_NAME="$1"; } + ;; + -i|--icon|--icon=*) + [[ "$1" = --icon=* ]] && ICON="${1#*=}" || { shift; ICON="$1"; } + ;; + -c|--category|--category=*) + [[ "$1" = --category=* ]] && category="${1#*=}" || { shift; category="$1"; } + process_category "$category" + ;; + -h|--hint|--hint=*) + [[ "$1" = --hint=* ]] && hint="${1#*=}" || { shift; hint="$1"; } + process_hint "$hint" + ;; + -o | --action | --action=*) + [[ "$1" == --action=* ]] && action="${1#*=}" || { shift; action="$1"; } + process_action "$action" + ;; + -d | --default-action | --default-action=*) + [[ "$1" == --default-action=* ]] && default_action="${1#*=}" || { shift; default_action="$1"; } + process_special_action default "$default_action" + ;; + -l | --close-action | --close-action=*) + [[ "$1" == --close-action=* ]] && close_action="${1#*=}" || { shift; close_action="$1"; } + process_special_action close "$close_action" + ;; + -p|--print-id) + PRINT_ID=yes + ;; + -r|--replace|--replace=*) + [[ "$1" = --replace=* ]] && REPLACE_ID="${1#*=}" || { shift; REPLACE_ID="$1"; } + ;; + -R|--replace-file|--replace-file=*) + [[ "$1" = --replace-file=* ]] && filename="${1#*=}" || { shift; filename="$1"; } + if [[ -s "$filename" ]]; then + REPLACE_ID="$(< $filename)" + fi + STORE_ID="$filename" + ;; + -s|--close|--close=*) + [[ "$1" = --close=* ]] && close_id="${1#*=}" || { shift; close_id="$1"; } + notify_close "$close_id" + exit $? + ;; + --) + positional=yes + ;; + *) + process_posargs "$1" + ;; + esac + shift +done + +# urgency is always set +HINTS=("$(make_hint byte urgency "$URGENCY")" "${HINTS[@]}") + +if [[ "$SUMMARY_SET" = n ]] ; then + help + exit 1 +else + notify +fi diff --git a/config/bin/scrot b/config/bin/scrot new file mode 100755 index 0000000..8878ba0 --- /dev/null +++ b/config/bin/scrot @@ -0,0 +1,48 @@ +#!/bin/sh + +SCROT_FILE="/home/hazel/usr/img/scrots/$(date +"scr_%Y-%m-%d_%H-%M-%S").png" + +send_notification() { + if [ -n "$1" ]; then + wl-copy "$1" + notify-send -i "$SCROT_FILE" "Screenshot saved!" "URL: $1" -t 2500 + else + # only copy the image if we aren't already copying the URL + wl-copy -t image/png < "$SCROT_FILE" + notify-send -i "$SCROT_FILE" "Screenshot saved!" -t 2500 + fi +} + +grab_selection() { + SCROT_AREA="$(swaymsg -t get_tree | jq -r '.. | (.nodes? // empty)[] | select(.pid and .visible) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp)" + grim -g "$SCROT_AREA" "$SCROT_FILE" +} + +grab_full() { + grim "$SCROT_FILE" +} + +upload_scrot() { + API_KEY="$(jq -r '.apikey' < "$HOME"/.config/linx-client.conf)" # reinventing the wheel + curl -s -H "Linx-Api-Key: $API_KEY" -H "Linx-Randomize: yes" -H "Accept: application/json" \ + -T "$SCROT_FILE" https://p.qtp2t.club/upload/ | jq -r '.url' +} + +case "$1" in + selup) + grab_selection && send_notification "$(upload_scrot)" + ;; + sel) + grab_selection && send_notification + ;; + fullup) + grab_full && send_notification "$(upload_scrot)" + ;; + full) + grab_full && send_notification + ;; + *) + echo "usage: scrot [full|sel|fullup|selup]" + return 1 + ;; +esac diff --git a/config/bin/volume b/config/bin/volume new file mode 100755 index 0000000..0788d40 --- /dev/null +++ b/config/bin/volume @@ -0,0 +1,37 @@ +#!/bin/sh + +send_notification() { + volume=$(ponymix --sink get-volume | awk '{print int($1 / 2.9)}') + # Make the bar with the special character ─ (it's not dash -) + # https://en.wikipedia.org/wiki/Box-drawing_character + bar=$(seq -s "─" "$volume" | sed 's/[0-9]//g') + # Send the notification + makoctl dismiss + notify-send -t 1000 "vol: $bar" +} + +case $1 in + up) + # Set the volume on (if it was muted) + ponymix --sink unmute + # Up the volume (+ 5%) + ponymix --sink increase 5 + send_notification + ;; + down) + ponymix --sink unmute + ponymix --sink decrease 5 + send_notification + ;; + mute) + # Toggle mute + ponymix --sink toggle + if ponymix --sink is-muted; then + makoctl dismiss + notify-send -t 1000 "volume muted" + else + send_notification + fi + ;; + *) echo "usage: volume [up|down|mute]" ;; +esac diff --git a/config/bin/xbps-menu b/config/bin/xbps-menu new file mode 100755 index 0000000..0af73f1 --- /dev/null +++ b/config/bin/xbps-menu @@ -0,0 +1,86 @@ +#!/bin/sh +# https://github.com/BanchouBoo/dots/blob/master/bin/xbps-menu +# ^ not licensed but... + +# sets XDG_CACHE_HOME to it's default if not set +: "${XDG_CACHE_HOME:=$HOME/.cache}" +cache_file="$XDG_CACHE_HOME/xbps-menu/pkglist" + +options="install +update +sync +remove +autoremove +clean" + +install_preview='pkg={}; pkg="${pkg%% *}"; xbps-query "$pkg" --property state > /dev/null && +# stat="Status: \033[2K\033[00;32mInstalled\033[0m" || +# stat="Status: \033[2K\033[0;31mNot installed\033[0m" +stat="Status: Installed" || +stat="Status: Not installed" +depends=$(xbps-query -R "$pkg" --property run_depends | sed "2,99 s/^/\t\t/") +printf "$stat \tDependencies:\t%s\n" "$depends" | column --separator " " --table' + +remove_preview='pkg={}; pkg="${pkg%% *}"; revdeps=$(xbps-query --revdeps "$pkg" | sed "2,99 s/^/\t\t/") +printf "Dependents:\t%s\n" "$revdeps"' + +log() { + printf "\n[\033[00;34m..\033[0m] %s\n" "$@" +} + +install() { + if [ ! -f "$cache_file" ]; then + log "Cache file doesn't exist, syncing repos and generating cache" + sync + fi + packages=$( + sk --multi --preview "$install_preview" \ + --preview-window "up" < "$cache_file" | \ + while read -r package; do + echo "${package%% *}" + done) + [ "$packages" ] && doas xbps-install -f $packages +} + +update() { + doas xbps-install -u +} + +# syncs the repos and updates the cache +sync() { + log "Syncing remote repositories" + doas xbps-install -S + mkdir -p "$XDG_CACHE_HOME/xbps-menu" + xbps-query -Rs "*" | while read -r line; do + echo "${line#????}" + done > "$cache_file" +} + +remove() { + packages=$( + xbps-query -s "*" | while read -r line; do + echo "${line#????}" + done | \ + sk --multi --preview "$remove_preview" \ + --preview-window "up" | \ + while read -r package; do + echo "${package%% *}" + done) + [ "$packages" ] && doas xbps-remove -R $packages +} + +autoremove() { + log "Removing orphaned packages" + doas xbps-remove -o +} + +clean() { + log "Cleaning cached packages" + doas xbps-remove -O +} + +while :; do + selection=$(echo "$options" | sk) + [ "$selection" ] || exit + "$selection" +done diff --git a/config/doom/blog.org b/config/doom/blog.org new file mode 100644 index 0000000..8ceb902 --- /dev/null +++ b/config/doom/blog.org @@ -0,0 +1,191 @@ +#+TITLE: The Blag +#+AUTHOR: Hazel Levine +#+EMAIL: rose.hazel@protonmail.ch +#+STARTUP: nofold + +This is the source code powering my blog, available at [[https://blog.qtp2t.club][blog.qtp2t.club]]. It sure +does exist. More info can be found on the blog itself [[https://blog.qtp2t.club/2020-01-13-blorgging.html][here]], but basically this +uses pure Org mode with no external dependencies. + +* Global variables +These are defined for later configuration and to avoid repetition, as well as to +modularize things such that if I ever change my home directory structure it +doesn't break everything. + +We define where we want to store the files: +#+BEGIN_SRC emacs-lisp +(setq blog/site-project-path "/home/hazel/usr/doc/blog/") +#+END_SRC + +Where we want the exported HTML to go: +#+BEGIN_SRC emacs-lisp +(setq blog/site-publish-path (concat blog/site-project-path "build/")) +#+END_SRC + +As well as extra content to put in the header and footer. Note that setting +these as variables means =blog.el= has to be reloaded whenever you change the +contents of these files, which has bitten me in the butt /multiple/ times. +#+BEGIN_SRC emacs-lisp +(setq blog/site-extra-head-file (concat blog/site-project-path "templates/headext.html")) +(setq blog/site-header-file (concat blog/site-project-path "templates/header.html")) +(setq blog/site-footer-file (concat blog/site-project-path "templates/footer.html")) +#+END_SRC + +Finally, we host MathJax locally, to avoid using CDNs, as well as the fact that +Org doesn't tango nice with MathJax 3.x for some reason. We use the Neo-Euler +font because I think it looks cool. Note that when deploying this, you probably +don't want to =scp= MathJax; it'll take forever. +#+BEGIN_SRC emacs-lisp +(setq blog/mathjax-options + '((path "./static/mj/MathJax.js?config=TeX-AMS-MML_HTMLorMML") + (scale "100") (align "left") (indent "2em") (tagside "right") + (mathml nil) (font "Neo-Euler"))) +#+END_SRC +* Functions +We define a means to add HTML files as part of a file, such that we can add our +custom headers and footers: +#+BEGIN_SRC emacs-lisp +(defun blog/add-html-file (arg) + (with-temp-buffer + (insert-file-contents arg) + (buffer-string))) +#+END_SRC + +We then take our previous variables defining the header and footer of the site +and convert them into raw strings for usage in Org's exporter: +#+BEGIN_SRC emacs-lisp +(setq blog/site-extra-head-raw (blog/add-html-file blog/site-extra-head-file)) +(setq blog/site-header-raw (blog/add-html-file blog/site-header-file)) +(setq blog/site-footer-raw (blog/add-html-file blog/site-footer-file)) +#+END_SRC + +Additionally, we define a way to format a site entry in our table of contents: +#+BEGIN_SRC emacs-lisp +(defun blog/site-format-entry (entry style project) + (format "[[file:%s][%s]] --- %s" + entry + (org-publish-find-title entry project) + (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)))) +#+END_SRC +* Org-publish +This is the meat of it; what tells Org that we're actually looking to make a +website out of miscalleneous files scattered in my documents folder. It's one +giant call to =setq=. + +We tell Org that the site is a concatenation of all of its components, that we +want to export HTML, and to look recursively. We also tell Org to put stuff in +that's defined later. +#+BEGIN_SRC emacs-lisp :noweb yes +(setq org-publish-project-alist + `(("site" + :components ("site-static", "site-images", "site-articles", "site-dl", "site-rss")) + + <> + <> + <> + <> + <> + + :publishing-function org-html-publish-to-html + :recursive t))) +#+END_SRC +** Static +Static resources, such as MathJax and CSS, should be copied directly to their +respective folders. This also applies for images and public files (=dl=). We +send these files to =blog/site-project-path=. The built-in publishing function +=org-publish-attachment= copies the file directly, and we also tell Org to +search recursively in case there are any subfolders. +#+NAME: static +#+BEGIN_SRC emacs-lisp :tangle no +("site-static" + :base-directory ,(concat blog/site-project-path "static/") + :base-extension ".*" + :publishing-directory ,(concat blog/site-publish-path "static/") + :publishing-function org-publish-attachment + :recursive t) + +("site-images" + :base-directory ,(concat blog/site-project-path "img") + :base-extension ".*" + :publishing-directory ,(concat blog/site-publish-path "img/") + :publishing-function org-publish-attachment + :recursive t) + +("site-dl" + :base-directory ,(concat blog/site-project-path "dl") + :base-extension ".*" + :publishing-directory ,(concat blog/site-publish-path "dl/") + :publishing-function org-publish-attachment + :recursive t) +#+END_SRC +** RSS +I still like RSS. Also, one person asked for it, so I'm happy to oblige. For +some reason, Org likes to repeat the XML header three times (???) at the +beginning of the resulting XML file, so I go back and manually delete it every +time. + +We tell it to look over all the articles, tell it where the blog is, and tell it +to look over =index.org= (which is our table of contents) and nothing else. We +also use =org-rss-publish-to-rss=, which pretty much does what it says it does. +#+NAME: rss +#+BEGIN_SRC emacs-lisp :tangle no +("site-rss" + :base-directory ,(concat blog/site-project-path "articles/") + :base-extension "org" + :publishing-directory ,blog/site-publish-path + :publishing-function org-rss-publish-to-rss + + :html-link-home "https://blog.qtp2t.club" + :html-link-use-abs-url t + + :title "Ziodyne" + :section-numbers nil + :exclude ".*" + :include ("index.org") + :table-of-contents nil) +#+END_SRC +** Articles (HTML) +We tell Org to look over our articles directory, only search through Org files, +and put everything in the site's publish path: +#+NAME: html1 +#+BEGIN_SRC emacs-lisp :tangle no +("site-articles" + :base-directory ,(concat blog/site-project-path "articles/") + :base-extension "org" + :publishing-directory ,blog/site-publish-path +#+END_SRC + +We tell it that we're using HTML5, to include the extra headers, preamble, and +postamble, and that we're operating on the root of the subdomain, as well as +define MathJax to be itself: +#+NAME: html2 +#+BEGIN_SRC emacs-lisp :tangle no + :html-doctype "html5" + :html-link-home "/" + :html-head nil + :html-head-extra ,blog/site-extra-head-raw + :html-head-include-default-style nil + :html-head-include-scripts nil + :html-home/up-format "" + + :html-preamble ,blog/site-header-raw + :html-postamble ,blog/site-footer-raw + + :html-mathjax-options ,blog/mathjax-options +#+END_SRC + +We generate the sitemap, tell it to save the result to =index.org=, and to list +anti-chronologically. We also use the previously defined function +=blog/site-format-entry= to... format entries. +#+NAME: html3 +#+BEGIN_SRC emacs-lisp :tangle no + :makeindex nil + :auto-sitemap t + :sitemap-filename "index.org" + :sitemap-title "Ramblings" + :sitemap-style list + :sitemap-sort-files anti-chronologically + :sitemap-format-entry blog/site-format-entry + :with-toc nil + :section-numbers nil +#+END_SRC diff --git a/config/doom/config.org b/config/doom/config.org new file mode 100644 index 0000000..2ce7299 --- /dev/null +++ b/config/doom/config.org @@ -0,0 +1,306 @@ +#+TITLE: Hazel's DOOM Emacs configuration +#+AUTHOR: Hazel Levine +#+EMAIL: rose.hazel@protonmail.ch +#+STARTUP: nofold + +Whee, literate programming, whoo. I get to type words here. These are words on a +screen. Typing. With /haaaaaaands/. + +In this file, we tangle the following: +#+BEGIN_SRC emacs-lisp +;;; config.el -*- lexical-binding: t -*- +#+END_SRC +#+BEGIN_SRC emacs-lisp :tangle ~/.config/doom/packages.el +;;; packages.el -*- lexical-binding: t -*- +#+END_SRC + +Any calls to =package!= generally get tangled to =packages.el=, whereas +everything else goes to =config.el=. + +* Introduction +** =whoami= +#+BEGIN_SRC emacs-lisp +(setq user-full-name "Hazel Levine" + user-mail-address "me@qtp2t.club") +#+END_SRC +** Custom Elisp +Load up where Void installs the =maxima-emacs= package, for later: +#+BEGIN_SRC emacs-lisp +(add-to-list 'load-path "/usr/share/emacs/site-lisp") +#+END_SRC + +Additionally, load the source code powering +[[https://blog.qtp2t.club][my blog.]] +#+BEGIN_SRC emacs-lisp +(org-babel-load-file (concat doom-private-dir "blog.org")) +#+END_SRC +* UI +** Fonts +I've had font rendering issues with Emacs for /years/, ever since I picked it +up. Namely, Emacs' font always looked just different enough from that of +whatever terminal emulator I'm using to be annoying. Thankfully, [[https://github.com/rocx/.emacs.d][rocx's emacs +config]] held the solution by forcing Emacs to use XFT (which is what =urxvt=, my +terminal emulator, also uses). + +I first define a function to create an XFT font string from whatever font, size, +and options I want: +#+BEGIN_SRC emacs-lisp +(defun hzl/xft-font-string (name size &optional properties) + ;; https://keithp.com/~keithp/render/Xft.tutorial + (concat (format "%s-%d" name size) + (when properties + (apply #'concat (mapcar (lambda (prop) + (format ":%s=%s" (car prop) (cdr prop))) + properties))))) +#+END_SRC + +Across my system, I use [[https://github.com/NerdyPepper/curie][curie]] for anything "system-related" (notifications, +bars, etc...), [[https://github.com/tonsky/FiraCode][Fira Code]] for monospace (read: programming) font with [[https://www.nerdfonts.com/][Nerd Fonts]] +patches, and [[https://fonts.adobe.com/fonts/source-sans][Source Sans Pro]] everywhere else. Size 9 seems to be readable on +both my 1920x1080 external monitor and 1600x900 ThinkPad. +#+BEGIN_SRC emacs-lisp +(defvar hzl/monospace-font + (hzl/xft-font-string "FiraCode" 10 + '((hintstyle . 3) + (hinting . true) + (lcdfilter . 3) + (antialias . true)))) +(defvar hzl/variable-pitch-font + (hzl/xft-font-string "Source Sans Pro" 10 + '((hintstyle . 3) + (autohint . true) + (lcdfilter . 3) + (antialias . true)))) + +(setq doom-font hzl/monospace-font) +(setq doom-variable-pitch-font hzl/variable-pitch-font) +#+END_SRC +** Colorscheme +I use [[http://sourcerer.xero.nu/][xero's sourcerer]] because it's readable, easy on the eyes, and plays well +with a lot of wallpapers (spoken like a true ricer). +#+BEGIN_SRC emacs-lisp +(setq doom-theme 'doom-gruvbox-light) +#+END_SRC +** Everything else +Enable line numbers, because those are nice, and make 'em relative: +#+BEGIN_SRC emacs-lisp +(setq display-line-numbers-type 'relative) +#+END_SRC + +Set the startup screen image to something comfy: +#+BEGIN_SRC emacs-lisp +(setq fancy-splash-image (concat doom-private-dir "nice.png")) +#+END_SRC +* Functionality +For the most part, DOOM Emacs handles 99% of the things I want to do in a text +editor and more, which is why this section is pretty brief. +Pretty much all of the functions I write end up under the "namespace" +=hzl/whatever=, on the merit that I want to avoid any clashes anywhere. +** Void package templates +Void packages are written in a single shell script, so bind that mode to any +file with the name =template=. +#+BEGIN_SRC emacs-lisp +(add-to-list 'auto-mode-alist '("/template\\'" . sh-mode)) +#+END_SRC +** MPDel music player +I usually use =ncmpcpp= for music, but sometimes when I'm working I use this. +It's all MPD, so it's not like they conflict. + +We grab both MPDel and its Ivy interface: +#+BEGIN_SRC emacs-lisp :tangle ~/.config/doom/packages.el +(package! mpdel) +(package! ivy-mpdel) +#+END_SRC + +We also disable evil in MPDel because its keybindings are contingent on doing +so. +#+BEGIN_SRC emacs-lisp +(use-package! mpdel + :config + (mpdel-mode) + (set-evil-initial-state! '(mpdel-playlist-mode + mpdel-browser-mode + mpdel-song-mode + mpdel-tablist-mode) + 'emacs)) +#+END_SRC +* Productivity, papers, etc +For the boring stuff that's not /quite/ programming. +** TeXcount +This is a binding to a Perl script installed via =tlmgr= that... counts words. +Considering most of the papers I write have hard minimum/maximum limits, this +comes in pretty useful pretty often. +#+BEGIN_SRC emacs-lisp +(defun hzl/texcount () + ;; Counts words in a TeX file. + (interactive) + (let* + ((this-file (buffer-file-name)) + (enc-str (symbol-name buffer-file-coding-system)) + (enc-opt + (cond + ((string-match "utf-8" enc-str) "-utf8") + ((string-match "latin" enc-str) "-latin1") + ("-encoding=guess"))) + (word-count + (with-output-to-string + (with-current-buffer standard-output + (call-process "texcount" nil t nil "-0" enc-opt this-file))))) + (message word-count))) +#+END_SRC + +...and then, actually bind it to =C-c w= in LaTeX mode. +#+BEGIN_SRC emacs-lisp +(add-hook 'LaTeX-mode-hook (lambda () (define-key LaTeX-mode-map "\C-cw" 'hzl/texcount))) +#+END_SRC +** AucTeX =latexmk= +I use =latexmk= to build my LaTeX work because I use external files for my +bibliographies. +#+BEGIN_SRC emacs-lisp :tangle ~/.config/doom/packages.el +(package! auctex-latexmk) +#+END_SRC + +We tell it to run the auto-setup function and use PDFs: +#+BEGIN_SRC emacs-lisp +(use-package! auctex-latexmk + :config + (auctex-latexmk-setup) + (setq auctex-latexmk-inherit-TeX-pdf-mode t)) +#+END_SRC +** Maxima +I use this CAS in conjunction with Org to take notes in my physics class, as +well as to take notes on personal projects. It also automatically renders to +LaTeX, and has a really clean Emacs interface. This isn't installed via +=use-package!=, it's the =maxima-emacs= package on Void, which is why it's a +series of autoloads. +#+BEGIN_SRC emacs-lisp +(autoload 'maxima-mode "maxima" "Maxima mode" t) +(autoload 'imaxima "imaxima" "Frontend for maxima with image support" t) +(autoload 'maxima "maxima" "Maxima interaction" t) +(autoload 'imath-mode "imath" "Imath mode for math formula input" t) +#+END_SRC + +Bind =M-x imaxima= to use =maxima-mode=: +#+BEGIN_SRC emacs-lisp +(setq imaxima-use-maxima-mode-flag t) +#+END_SRC + +And bind the right file extensions: +#+BEGIN_SRC emacs-lisp +(add-to-list 'auto-mode-alist '("\\.ma[cx]" . maxima-mode)) +#+END_SRC +** =mu4e= +Since ProtonMail offers an IMAP/SMTP bridge now on Linux, I can use this. + +Tell =mu4e= to use =mbsync=. =offlineimap= was the only piece of software on my +machine binding me to Python 2. +#+BEGIN_SRC emacs-lisp +(setq +mu4e-backend 'mbsync) +#+END_SRC + +Tell it where I save my mail: +#+BEGIN_SRC emacs-lisp +(setq mu4e-maildir "/home/hazel/var/mail/protonmail" + mu4e-attachment-dir "/home/hazel/var/mail/protonmail/attachments") +#+END_SRC + +We tell it how I save my email, too: +#+BEGIN_SRC emacs-lisp +(set-email-account! "ProtonMail" + '((mu4e-sent-folder . "/Sent") + (mu4e-drafts-folder . "/Drafts") + (mu4e-trash-folder . "/Trash") + (mu4e-refile-folder . "/All Mail") + (smtpmail-smtp-user . "me@qtp2t.club") + (smtpmail-smtp-service . 1025) + (user-mail-address . "me@qtp2t.club")) + t) +#+END_SRC + +This took me forever to figure out. In order to let Emacs send mail from the +ProtonMail Bridge's SMTP server, you have to allow its self-signed certificate. +To get this certificate, you can execute the command: +#+BEGIN_SRC sh :tangle no +openssl s_client -connect 127.0.0.1:1025 -starttls smtp 2>/dev/null out.pem +#+END_SRC +Then copy the resulting file =out.pem= to wherever you want, and: +#+BEGIN_SRC emacs-lisp +(add-to-list 'gnutls-trustfiles "/home/hazel/var/certs/protonmail_bridge.pem") +#+END_SRC +** Org-mode +Set the bullets to pretty stuff: +#+BEGIN_SRC emacs-lisp +(setq org-bullets-bullet-list '("☯" "☰" "☱" "☲" "☳" "☴" "☵" "☶" "☷")) +(setq org-ellipsis "↝") +#+END_SRC + +Make sure that Org doesn't try to clutter my home directory, and put stuff where +it's supposed to be: +#+BEGIN_SRC emacs-lisp +(setq org-directory "~/usr/doc/org/") +#+END_SRC + +Set DOOM's scratch buffer, available at any point with =SPC x=, to Org, which I +find useful for taking quick notes: +#+BEGIN_SRC emacs-lisp +(setq doom-scratch-buffer-major-mode 'org-mode) +#+END_SRC +** PDF Tools +Not sure if I'll stick to this over Zathura, but it's nice to have everything in +Emacs. This is bundled with DOOM, so I just tell AucTeX to open stuff up in it. +#+BEGIN_SRC emacs-lisp +(setq TeX-view-program-selection '((output-pdf "PDF Tools"))) +(add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer) +#+END_SRC +* Programming languages +The cool stuff. Unless it's Java. +** FRC Mode +This is a =gradlew= wrapper I hacked together really fast while sitting in my +physics class not paying attention. The officially sanctioned IDE for FIRST +Robotics is Visual Studio Code, which I hate with a burning passion for numerous +reasons. + +We grab it directly from my Git, since it's not in ELPA (and probably never will +be): +#+BEGIN_SRC emacs-lisp :tangle ~/.config/doom/packages.el +(package! frc-mode + :recipe (:host nil :repo "https://git.qtp2t.club/hazel/frc-mode")) +#+END_SRC + +And tell it to run with all Java files. I'd never willingly write Java outside +of FRC, so it's fine. +#+BEGIN_SRC emacs-lisp +(use-package! frc-mode + :hook (java-mode . frc-mode)) +#+END_SRC +** =rust-analyzer= +Iunno, man. Sure. Why not. Racer and RLS keep giving me issues. +#+BEGIN_SRC emacs-lisp +(setq rustic-lsp-server 'rust-analyzer) +#+END_SRC +** vimrc mode +Hey. HEY. CHILL. The irony is not lost on me. This is actually for editing my +[[https://tridactyl.xyz][Tridactyl]] config. +#+BEGIN_SRC emacs-lisp +(define-generic-mode 'vimrc-generic-mode + '() + '() + '(("^[\t ]*:?\\(!\\|ab\\|map\\|unmap\\)[^\r\n\"]*\"[^\r\n\"]*\\(\"[^\r\n\"]*\"[^\r\n\"]*\\)*$" + (0 font-lock-warning-face)) + ("\\(^\\|[\t ]\\)\\(\".*\\)$") + (2 font-lock-comment-face) + ("\"\\([^\n\r\"\\]\\|\\.\\)*\"" + (0 font-lock-string-face))) + '("/vimrc\\'" "\\.vim\\(rc\\)?\\'") + '((lambda () + (modify-syntax-entry ?\" "."))) + "Generic mode for Vim configuration files.") +#+END_SRC +** Shen +A really cool experimental, portable, and typed Lisp. I like it a lot, but I +don't know much about it on the merit that it's locked behind a paywall of a +book that I can't afford nor pirate. +#+BEGIN_SRC emacs-lisp :tangle ~/.config/doom/packages.el +(package! shen-mode) +#+END_SRC diff --git a/config/doom/init.el b/config/doom/init.el new file mode 100644 index 0000000..de782a6 --- /dev/null +++ b/config/doom/init.el @@ -0,0 +1,93 @@ +;;; init.el -*- lexical-binding: t; -*- +;; ,;' `:. NOTE: THERE ARE TWO BFGS IN HELL +;; :: _ ;; +;; `:_|_;' +;; ! + +(doom! :completion + company + (ivy +icons +prescient) + + :ui + doom + doom-dashboard + doom-quit + hl-todo + modeline + nav-flash + ophints + (popup +all +defaults) + (pretty-code +fira) + treemacs + vc-gutter + vi-tilde-fringe + window-select + workspaces + zen + + :editor + (evil +everywhere) + file-templates + fold + multiple-cursors + parinfer + rotate-text + snippets + + :emacs + (dired +icons +ranger) + electric + ibuffer + vc + + :term + eshell + vterm + + :checkers + syntax + spell ; ...is this annoying? yes! do i need it for editing latex papers? + ; also yes! + + :tools + debugger + direnv + (eval +overlay) + gist + (lookup +docsets) + lsp + magit + make + pdf + rgb + + :lang + cc + common-lisp + data + emacs-lisp + go + (haskell +dante) + (java +lsp) + javascript + latex + markdown + nix + (org +dragndrop +pandoc +present) + python + racket + (rust +lsp) + (scala +lsp) + scheme + sh + + :email + (mu4e +gmail) + + :app + irc + (rss +org) + + :config + literate + (default +bindings +smartparens)) diff --git a/config/doom/nice.png b/config/doom/nice.png new file mode 100644 index 0000000000000000000000000000000000000000..3f12e3f0e51336ac0c0f00b8057b42edefbb4fdd GIT binary patch literal 93331 zcmb@thc{f`_Xa$pcOrTxM2YBO^p-@g(d%d-NQ~a=Xwf@~nyArBgkYE90f zM(^eI{k`k`58k`(z2~lT*E)CIz0cmyv-jEOqrR>hISCU9001D@P=9F%007M&o>z$o z9`5V$-{&4Wg5RmC>c4Yv008*XL(}Ee`;=JvZQqoa8?o$htfqaDF{h&S{3Af~MWu?? z!dK+y3F&7EZhoPZC^rNmwZ9sg*iuhXAH{J2TwUKT+veiA6XyROe~4*k$L`DTqk$?d z!xA;lEE7Hpqh%TPLOlYpHk=#@B2n>!qhg!f{N&4rzNr9PEVbOo{bF&c-g7fDqWE7e zqayED$yaxD7BF3UEDlcQJPN#Q;yY2lQmsto!q%+3%rT!t#q&S$raVe47c%L{%hpK_ zNC4Hl%50EIry8Ry3tC+ZTd_m749~ZpjaXGmC(+O~;SqDu{4r3bm8AauUzyq9MA+{E z#q}#5FaGuFh;#?w3zsx&#S8YE{b>PR-2jbA?uqMF5c?A)7kZZ$EL+#Jo))}H2aN5% zW$!E==UsBcCMQ?bl8M3j4h2Psmu9<;&Xpl+xG00cb+03xCRfUAeD zh;0DCR|Ej~4-5dvul10Rf*2 z7#=zaeKd4l5w7Eq(eX==>DE9Vl-(0#WaeXN=g$H0@_75s-HF2|5aPt~f7%Bnm%p)0 zVc{gZ*`kq-I&6`qz+E!j507LZJD#6Y&o@(v7yB_%q26Pu)f4;8F3QeKIX}bi3HWoG zpL{Yo{v5-j^)xP8;NJS9m6}VLkmQKZ63-YJA#_w2f_reTDQnUZfs9>``1O}^b~JWa z;5Ac>m{1;Ppaa;2g~FP`P`sGRy^AH%*{?e;)nUaq8OQR-6D1m3s)%EA(6Zzi+$+U7 zpvHBUOI)27XbhmdNDB8>B(IL0U(;SdD3H>_T@iCIOqb_Eou^m(r|s)!|8m_0f)a@S zMQohmDX3spM>GZlS|_V0%0FWF^?M{@lR^u}+r_y#+o>_KkthBHKNT2=YV8^N-#$v< z8ZA<9IOGi3AjAy_`N+#m5-SDltjLN#Fi&G-QY$+-W_rzc?CvDi6%_e#*|jLxHoL0r zQ<+b5 zcTY+lp?Z}OF~pr&6_F&6Fc?2vRXrG=kWef5HKDdPp^6JPN^r33`ELTUS+E`RLWYyZ z^qXUJDE4e@XZ(Yyc;}Vqrj=XaGhp-cONF6efqHcCc|prK+HLH`Cd2YYw+CRi)#m@t z^YqMYFR&-_^lG@lBg~F4$s5s5g@j5Ixv{nscZZHEV$Xlr?4EYMAKJPlnBINXc6XC{ z8`jM?iXI*sxz+V^m`Kk*sNX6Cfk4vXrI{6!W%j&17em5X)CF>Q1=5?tkIIs&D{9S)qmRuhqkzolmBlJ>hWvx+8K|~ z+X2NR+_n!(L5IS&9bRh#1kgh#0?xW7$aHTor5kx|YXo6!69i=s+G~N`YK2DFTBA(# zc$ZF4Z+k2iWNb+n~@m|Bd@>j zXTQOni&H%L!XAEEo_oJoqS#*6x>B=2f;3a-M@YwkaSkF{D5lNKO6`(?U2!c;@2W4# zwQ~KEJh7oC+mnH&37wt!vVYe~`?hWm|2J^`^uxf(b&6-VJ;m>JpR#v1hwljg`|zQA zDwx-Fgr`g&oCFmmKr&!}Sb5M^nqibELEVet=I9p$C>J8m_43^re^Liww?w_Voc_!@ zgK>EUnJ_fFH*9)$_iY`st?iTDo(sJ@mJ%9lxxE}yN|>XE|CTkIO|}z$c3GNcq&G=3 z06-D2^-+=fE+I;!c2E|L&aE7%>vk&e`gaRWrEaV;G_79&-t$63G zwkqFfkE4$Hg2}4x1@F@-(!_NZB6g~Cudt< z5%Xhec%(0ml8vllYRyRYdeG<$u~`z{uxt>wH8u6OZ$R&4?nK+odM^CJ%{Bm?>-C_R zpY<=S4kWDXz@(wLsBrln7d3A3$}Vi*`@Hzv$-3b* zNXV^ls5^PO_$r;fS4+72&H5|PpHpLDK5oHByg&SZ*zTNP4a*YNyr^xZvf@C?AVF}3 z?~;wEKke>ZJ2xljzTgbrmo5mk*QOU1+nJpIxEXYj>Mdj{+-Vv(NZ=5D78gU5I8X?m zp%ftWGop>|hd|o6E+i-*qLi0X@91(bv(kA>(O`-AAQshsa{K9M+hg^J<-=35oJU(B^vWP#Ds1F8LoJ_)M}$1cngH`h60Dr261S-1gTvMnIS&mnU|F z#MKzyKob8OE^OL(Ogr39-LgS_>H3NgC$qM*Df@$McUMzu+bvLNiqik8Z>ex(W*>Gn z+&Lb;vDV{SeE!0=;qPB8& z%~hN286VMtY%UfhSo>U-2K_IL9_Kw7l7fwBwzh>1^?B3ni!?#WmvA5?1@uEx6NClq zPPDRJYugR-bTu7h#3kjGV#o%1?fK=CS}{?o<*a2e3dtW*=}xQ##d^*ITZ!QrPOxwc z=iO<;-KsF_ZEw#7FA*X|+>-1$oDkIF0Z9Vk_v}}b^{?BDwJQ#?=)@k={u)Fj9?^CVZhTFpB^QGlu9oYp-7Ib7JLRQbp zbQw<@&jnD@r*b|HSqRBzs>tOw*NzjXBo+MB)@)21P5Mto_v?MEHnEC|ia1!g_EUzdVa zQmk;7zm#${pqt-t`t5?~^u3*(d`2a|+bGTH}N`K z{hh*iL_+379Xax3(%7;hj#}R~&Y7mY9PbEmOp1>fQY9xx4=}e%<{5ZlOH?BMsRz{$1ExFMnt3?M%J(eV>$v z)qTnk@<8)*#ezWkH-9>Gprg47q52lfw^o(DVHsSkoKty$^`M-28cJr%bF;zj(MBi> zud0sVRfl17QHat65UgE#;iVMtUf@>xNkZ;9TXy|_%a2VL2XCctmxf%&_&gFzdY5HWj%>gJ-Jrx5j?#)oPydm&fol98v9qg%#v(! zzY%^J4xZXE_ZMOC*R(zr;}5oKQvR)D74BfBUAYyoi?Ym5?3epCy!wa1+rrfw@1WnU zq30(uVCDhLAMl9QX89(?&5A!T)ZhP}QtxSg`1bF+yJyfza0VZLLNgZy|C3RP1k!?1 z5Jx%L^ZJSHRY3^^i&N(Fw~?X*3VB@t094TD2r4t63JF{mo~aH5zz<$YhyWsmrd@F5 z0PLTg0T}bq*Q$}rk`;C$&Mhv^`%HUqtGMU%dolC-SMyemZ1lp8hP4)s{~8)u zjMpBgrl#oHb_Q>ug?&42Z9k3Y650kFpMCz>Xfy6qCqCDJxhnDq6JDO351m1y%kTGC zg<)%y=yt!*nyG*4aB=IM`5=+Exhh0vT8!XPZssq_nesAj{P0-np2IjN8mmJ5E~q!r zS6n3lTAZSWZ&vXB2m#AGf-FQcm;=h;+6Z2OiJ(`R@%WzfJ~CLgWhPKb@%wKhV1yIz|gTgk&xc zF3Qv;bh#~*W9hRy3_G2idpAXI6R;B}{11CBQ<(M6`b%|nhxf9i+aX%jZ53fitP8BK zaEXj6Ca)Hp9EK3PVt~73%g#?oBgD*SOrS9{Dd973MSpGP{;jyPi2v3YD~6r$e zzG*DA!T@Ka>?SI?-;8Qpx(IslW5iXHeq~4k^9ax^sOmAH<~%z95sSo7*Yq!rk5_8D zv5L5mG7vUW!ONps38Fn@Awub8{I|ONa*sbgtF^8_I-*xNJk-1Sk5}RDqiy%~=D+ac z3k2+Pi(TGKm3a5m*mjrWdckV>nw4EeAmGQ(pT~u!Le|&9=+pl?m%}%X!k+S|8RYOK z;EcZExAtF9MOqNPF4?SO z{f&yh&Kybm?x(i{Jc?-<*FkAhsYR|BsWC${EVwt={5gG90yR4LBuLfK zoTRP>kPb5Hh>C*}&FB$DO6YLJM61&@+fbUf5ek*%Z^g(f$SYp$6kqM=DYS>*d(68Y zrZS4Rbo%dK+1}qQZNai1u*l~@(H`EnlZqFiUyGgCyZkoh?>9o14|Le)3$)=3`uG76 zGS{5Dj_n-5FJk5J7#M0>s8ptfERcpKbC}9Mf>E9jWN#29C;o7CZ(n6A>ZVhA;ObPD6xneV$@aDuI>m&hPE@u`uKp7cazGTPrYDkL=chHv<~! z>grnY{q0D%I@QW4;1=2R=d1Z3J#x86B5QtcYolMbEvwD%ex2Io+I38OM?e}mqi}6; zx}z7m7v3IzUe{yadbb#UuXtDb!s!A01l(91!?ndamu1zJ;G5 z7->i%i1$_fUqTNd5o5hKCTI9&m}zwD4GWtBVhyS)_;#!DFAlSHjHjC2>;}U*chI*8 z8Wv3mME6990KSmsL~75?uvSv1`q_74S0~N!2`E46+oKQ#?4-m1N zD3zqaeodMU9u7+urRQ@Jz2=o9h;w8icGibrkgEJKEEHOA9zCt4iO! zO%E&C^$g4(K_weRDx!`;sOYa1;YQ(bkbW>1G&qP-wIt=CtxfGRy^}+OIKe=%8Kl^_Dk#9zKUhf8Q_8 zv)QGIfg0>EDo`zbbGBb(Xjw0UH7@X1wv$eDNX^=Qx4hOI5({OMIf-9w(}c`f_hJ{DPi zJMv#Yz3m0Eu<+mg3~Ku9x~o#DGK;Gs!Z%`aJHn2erbAaHqEv*owhqps&j{sV(e6nU z*g!DW?DYRpi8N^uB%z2udjiw&w+<$?I5BgmYZ>^J^GoK%K%Zxc)srJ1W9_kR@cz6Re% z`ge^MOkze!9pu*pHmn4m8gV@^#a>A%$tH{Ee|HWIQpGGch&Vs+K#Y%tJ~9%%+QrA`Q@=D>fw{ME4O?!SOwn|M5;(q=)^b=r%ZWt;07> z_+v+LASr>$13I%zTMC+ZFT(sO8$!=oKnfx8g^_T=<<``EOZl=4AQzqyKSEVn&pL#H z6Qp7l*Yf2H5~`u26}hPzyN}zJtDwfPN|Y)j+&IXN*}mYUt4~F_P%<;iZj;AhR9^J4 zMb4|{dQ-6Dk#R|q!Q%W=n!$z^@TgLe2)xqQc~lUvI>T+GFP{!@SqF?CH%UvQWml)n zwJu^XM9EW#zBpOmYhbzBqenNj7X#Ehk4s;Goa04+Yb=Yv zTNEH)K)IS5gj>)Q!DCF9i_^&VP6`?Yoy5m~zGX=+c2%f@Ir7~JN07yeUZ{U*&S`d0 zV{1u&CTp#Ih9S?g-#FaM;zQ!JJk*G$GJRaB-w~K6F1T+nM26~8eieL z3NVWD>PwY|L_DOs^xtW&l8TfiDQl1-yo`9`Kw&}{OvNH4Lm~|B;EzBQRBRU39itc(LF#!_q%A6iXJ;)g6>;4dI1bNX#8b_;`* zjU2s_4!oBNznC1`mFm>4zHJt$4+3jxirO7G@b^de`6F)HGkrS^zuEQ7{Nok?9+TZ& zy$~~&Vmg>G9RB&DVt$e3(%7KZWTgLg!!_{S-R=5rZf?%fseD-k-E|6EzC!Grgj9@F zd-a3`*O^=gnLQATe5;zjntq)ykDuSecT(LyB*md*K66pQEZ5jkD?F+@f*Fe(j|2uS zRHfguCVc%RN>-tX@T8=x(kW;mb+8|_rEA41txsh9$@#3p7V-D-eM3KtL^uz_D;fcATYl&rhwVc{@V+DYX^B1uzLMTRE;WV>#h`%4Qz59}tf%a8I(4|Bo^U zrYi;WJbqj3Ipd3}fau~BJuAlcUqDN+=Ee*X0LYkK!57IkMY{@)3#`Q{%v zL0|C$Q5jA-r*JCYC9ByiC2;+n5olJIZb}fE#ZX0Km7XLy!=z@M@?;;(le~R~0!|k2 z$W7#qAv7L%jwW!^a#F;fH1$XX^6Bu(Z$Ct?e@9TNt7h9x~yjXAekLi{b{q{deg z3D|^^bLlARe~c2R05try_Ti?)8BAnv;3O-VxW+ zKq~I3q~j}ZC7}7|#<1mYL&(^Upp7HA3oJY&TLS#j9KMl>c*?fA?#I- zM_{2R%k7@<{eQ>kyWLYuvt8tjhkfXJD0VZmu8#fwj57TC{vY%5?f%$TK{#A!bSi97ptXh%;p(jO_?Nn80W( z#<5OPS#zX>n)u);oEWuY?XH6VnXxJ4{D*ow_q;K-5$&w2k8TrIM+G$TXZtjP-m) zBqxMsO(Eqx&)GdlE}7?A571y zYqkacUV-~7162N-VC1hRvoocD1KLV(vzRYo)d6*}5NIwRaI-!cXuP>`e@rY zfBH5w*l)E})L$d;0SuJ}XwF%6{uQ_@`+Q!Zxqj?63x1u8%Nnevyv1`csx`I*hjV2G zr)UJ)$v}l$OGUE|91eJl@C^JNlR@@VF~(Xh_ANzi3lPO47!Si(!)+b(oyfGm3o@%p zGD2DK;&O46r-9Bx61-sz4fnqQ%pZIXX8!rfvh{LbK3fN zO3mp{6Um#MZ65;oM26tOUS*bd2*&nxby?!qYu(iXq5XkY=Jm159TxR$=DUivMt>`% zcuV!z+1bO62o;Z3WREvoPbc-l{tHxO+C9bopMy2)TiO1deXF%B!$hWULVGA4(+-}+ zu__=@8tEfV$q?U`nN5>Hy&15N`qO8VA%b2yNbifgHS~Ty9CJcyB zb;Dg_`Tiq;=T2v((^ z%@Yz%DyM@eBMGRlVvdaL)?a34ua~cpXZa8DHWFWX&b~{^F?OogcjwvZsa-+o%AT11=@5kXdqD5CEO0WcT>XoXfV-fp0wdoD{EF>4*6_QU&;=ELS%>ef??4@|&d( zetj<9#-^Ll?1!2SKiOivW|S~HE9>oE_DF8Ge$K1A^Sk~YE9V~`eGkimJs)4Nq=b*3 z*31ZzqA(nv<1Ut4T%j~ql%O@RAb!z|M^Eh03FilQuRUD?hO_ueCUI>y^2v@`d}th) z<*B3MD6dg>5J5dR7x)=&y=!vhY0m4YP7by-fp`WLDoia~7Li)yU)ir7@5ViUSbdpc zR{67Ur675?QX7Ns)a3Uf)S*74y>STr|m2VM!6gg!8#WyJiq(Pej&f?xm6i< zSLzmcu;5xb{^%vkE_ zbwuNQ9*&Eh)qyxw#(m)8e8m@280Q}$$~G+uphl50jIYS8v{*ric)n!d8J3^s(Q|%8 zZA>ss9i;hsBLU1~aQ?&$6>7F^Camc$naTVL#wP(bl*T|=i(oZ}V7%D!gh*NR=rLsK zG;uVO)sJ4h;Tn$6s`He42C-1L3O+Qp>b}G=s!XglLzv(@twkvZkZyXZb7Bg94NVdU zvhcZbylORHe>%`o|33C{VfQ?+?H}uke4`aDNI|A=Wra~!j~*mz36`<6Z?%fyr`6dU zmm3%wBHm2Icl^pxR<%NmWl8d`5=gEVG{|PE>4H~R>1Q!H8E}qkZELEUb|77MIy#l| zaos^mOf`P1Jl;qu-bbFOPgGWp8e-diGEyCd`@sbRS}hx27w1?Me|iPBg&bU90u{w} zX{Ti}Z^d#&&-%5luNwr)8PaDN<(%u{e*C=vyg)8Q;kZF1Bm;)%`bqldRJ)oL;jiiS zwUy@aOmMT$8*SiT_+$8Trux-{Pags^Kq$$^I1s7NNJ&VzLjJv8T|&Rp^2KAyRWF$X z7uAUq6!6RClb0M}q6Axy1>b5BA>bGQdmh2M2rdO2l*(HvE~j7)4*oMxlCSdd^{4(Q zXnPj52*F4;a*MqX1711MSw5oJL${~6PeAv4f#U}!`^*qOAO$Iwm7B0u9+>vznB@2g zbmMDW@{)B~p^)~kAj_go7jqdKIe>#n;yl7lLHOWghj{atw%`G^2ybTBk^=eoCwHFC z&N6@whDM1WPZ$ z6O2(UcxWd+9r~xA;J*HL&F|ay=_ZzA^rQ?f6uxgGf=CPXR(w8c${I0E%p-!CWtO^7 zv-1R^3RQ51H3-lIj6%q&y`fP#Nb)krf)xC*RPsEHlUjW%lkrrVYo1teY^NS-a<{C# zSzJZ9l)4k~p>!b++3a}n$C9@__`|_bFgnrWeo)HZO%893CCZb#8n=<=b?(7aHT_5W z$5c$3Mtmc*3B79}9ZJ(XO4T5OO5^7kE=e@of9hcrY|{)Z?0SdWE5s%vB+~#v$9^HJ z8U~+ZD~DFWv@Lvwh!1Uv5;~rKL9w#u`(LUAi1+Ic{_Q`Rg7W zN{y$v@2@CcK$nv#VfWUviwx7|^86T@jPHqmo0XahGKi%Bkk2(7pfnyf93G!{5G>+} z2x{V=AFkkJ1_$9cYzxSpti#!vR4ySNS>RBP-#UE#dRH=Q1Uwym-dCy5`%H!gq&v60`>}0GlJCnrwaslzzlv*rsRY-t5wEVx6eA?v3zj5;6|K=w4Q4+(gj^VUxGBX!ZBBCg#PA6*Ri3zdID7#0@ z9Zp^gz1K(R)w17&F3jDLkpCoBVugz3qSxbw zfMIR6rvPAsDE%h*mHxflUac=kL1DnYs85D133-aoWc>Y8k_cWZxi-7nzKF=Cff*@6 zTIQBh1`6zI0ys|?6C*?P+hfdKo?qBcu!G&YVqSIs$}Hs#SVM&t=s5>$X$gN>_(uTs zN+n^M+M(%Np?dfE`!AvIyzdm44r4!}>1l#e&|3i#cn+pAeU}HSYlqwArnW(c&UY7% zYxe<{N97CmBRvPX|J9yZqHl$!cYK<|{6%Pz&OiB^CV#W3u3cKUQW*Pi@?(useD&V%75ux|bS?^|#Na2V2>Dd*}Q9rZMMzv}BXRQq1yR1lcy+ z`(Z2a&d}I+F5iFOYN+PFY&3YV9Gq8FTspPGsUt2HkWM`c%+TO|R|4)w8gl%U$|`(I zm+MO>IfE(rZNr?}%Rr+Xhb=_9hD9Bh%5Ep(lzxbncm%dXwrwFiM?e8<@Y;xai40v5 z_7Eq8v_PGKMUbKjwW5(FWj%RT$KZkw;CoYmk4*n2B%)mRVB6(mW_E9R{&IvzPZ;B; z6Endaka;ac%(8^Uym8*B-H!($_2C29KlpK}O#|vb_@L+Ln1C6%PY?-4h=>mWkJL!f zZG+a;$#-3D%8wQz`5d+>d9obA)4wALz!Fpe&Qkr(?6n8X#di|F-J>T1RDkAGskzal zO^4eht%%D@mg%brZ4!ND5!|iFjDdOaKW30S*H5v>gEWsKk#EV$RwGT2AMYxB|7|J# zwj`#jAksplKP4%>1LUvibopY*S&CRzG8UhhaUA3(`#!8H>T9Nh%5p?nI`}tnQG2X& zsz@k0kdTM_%3LpRc)zjfx`}&8vT*zkX?yK)w{Ts2ldR{|(jU^PxNXHm5hUy^7Ch(b zohjb^qF?i_6Lo_UU{8(1236 zTIQgwS8Y>322*ohhj$s^?mUN93xq{nm!N3jxWT&Ci7fw*wjUyMvoCWh)TgqZeh;$E zEuGHjQF6}{C5;fxDo5HIm+;k;R2@|%(54hG#_~~m2G*p0cukqF`ewe@%;**V7K;qA zT90sA#jj5}`c$;6sDqw$<6ZYk7q3<;c*h!H6(js~mPyWR0MYvC?jn328Q z&uID&OK_Lj(r-j55ZkBHaPGmah{!TfTBS0_hi zIoj;YjWM?%C4naRADaDJ;Yv{mOVR;Q5u0NF+~s4drDZkYT^q6^4j>YVrx!HKzd;qZ$huz)3s`O>LMYbIy!F-hYBEwNK=%)C7ur#j>AjXvXPcw7ls; zLLOJ=B#GvsDnW7zNZ7T%GbKB^M?Qc2uHNv-!@m=%mRclNANKFKK@mG}^ZsX;Dc&6W z9SrN-H~Ct4hYWd(hMW)IorsxU1MCXV&FJtcQc^tw0^&njm3lH)hRa80(P)(nU-d^cL^nt#ZVeoMp4z4=fyB!Y z{P%J`dDc!kF>&Y15$1C6kzBRyr!-)PwLVKqkLO@k0XI8<`o8Ek37;xlqZKhLN8OF;l93!qi+@8B>P6glakLF4^xENzdEs(DMCPt8_eAX*_?ZzFyPTpGWHE;-I zsfw?loe_@%K=$5*n&g<7a+5p4Wx+6Q)kC;!z%CI>*|TTov_@KNKb z`Z-!wb4$D|W(Psx2wK>FA^k=w@(y0gFT-SC|`nvqu&G8c|iCWCK}JQCJUz6zUYHxUt=bq*Hd4mnCt7X|2W2CF*#_kHsD&z)QuZTQnA#jy@ADmDf`!;^+RyKpyL-iNA{AfM>*rS4>2 zLOsa4aP~d~11v0cGk|fv7Lb-pd-N)@+6QC!Wnrh+B5|NH4kQ;6!TdNt>mF9^Is|esYrs6}_I^Z!49^)km2x9iS*@~h>5Xdi=MI)gi$5+fI_mD~) z5e7RfLbYiaG7nf9OE9CK@aP4rkf1z=NWT%guWo)zCAJV9-rALL7YV#vJaZ9Fuv|$EiL|0si6YV48422pxpFDbFeEC+sVVpuh=p%QPiI>L4d`B!DzafxQ@Q8$# z=i1T6e(T8fvb=3pZf@Y^4B^uLa`=6)?azDL+rK?mSk~p^wdHeb5J>JVC7XPdC@p}n zJgZpysd^?J`|bKxu|LCQLR~`*$8~Pl(SS(45OubXRNK=|sjLikjf}nE81{{lIi%O#orLS%O{7gj6yyCW_2o~EEn#9oR}bZoVG6Wg-xuk zaA`9=8wTgW-onBoRs%>VQ@9@~8;+!z8j(YgZoT2AjCnhZbcvi<+HgF^`j;r7uMT-U z9~wz3#97E*=YuoV8Gh8T_N%YMm1qPwiEunQ1b=#RJqdv=5!)k-w&s#@MB&o7;~H~F zMrb3MCS(wUu#BAPc-T<@pya2?Nn}YPcGrIWMY-Z3n9~*4DS9ku#I)`@h?^C!rS5z7h7h-hb0>SZiB5;N%*>YT z`+l9+egEswa++rev=7CFJWk^2LXV~6RicLogvbQRC@DR8%?E!4jP=xZc774x#~sK3 z1BcBdV?(>J)(xxRU}pdQrM`c`9(Jt-4#6Jmw<`cJPKQ|IbR2xdt`>2*N5jiY*e<7; z&Oa>ju83B{NuEJq4f4b6_tv42%rIQCYNH$Qom|l%w^l6Vhkmtds;=4tuA4F~2FvwB z90-GNITQM+xBP%(azcq4@=MwLydjsP>v_Wm!R3Edt9&mbXGs_tNBIgI;PU}zP zUz5<`EZL|qJjcz-n4MpQLtA)7kV;;(70)ARTy5Yoq+8z>*?sUkJ|euN`@oGr#=rjQ z?7Q+mD9#$PvfD~Ct3^_WpxP=5Ttch%b3;uAeGCrMq-xjxdxX+Wko=vzF6@A9 zIy(5V_EhV17R*mNspZto$O)e=PTQh4M0zW4?5)|TDPID~Yi4yG4(?<(-UiF4@MxFW z$A>n9F6_hrOzUdx+kT>`$XZc|4Z(f%COrPh$J*8jWBk(7mtKdZOS;prj-Kl_o1eb7 zYl@e=ckA}q;)l$|m)iH3?H%x^t;~M=yQt~EQf3}DRX(kMYb3nUft02Yq#o=%DN?%p zcd2gWb(*(dml-PORkuu#$GkjW_08;OS5AB>+W?=Nu0B+5E80Z)tmkUv{-I_81coZJ zS8l0+6czh6H|ZXH&i1*V-{ilycMUf^_tP=OmvcRb%Pkvn;}pdTORI91MU&v8OlH+f zwr@sHvmH^4>w(HL;hQT3#EKe^@yZDCj$ab_OT@nP1Udt22HXBZW10jVo2dy&ama~_ zx~HS*=^6(GSK2#z;{J^h?<l{N~QsQP}`UR=KK; zE8kmBIqQ`%-Zx$6*6c4UUL2Jp)>_2nq~#+YlbPpmYS1`BPy)}AjWoJ^js-g2kvw%w zOSqb4|4J=0?5_HarJsZ?!hxlx89q5jR_aM;x!~Yvs3Pz&`H-sZxz2fOO5~FmQAr9H z7tb{LpijSEkFQS3#fcJVs^fL$Sg7oELFvgL2<^p3|1?R=m$k4~E*6tmjKM29tUFPK z=5WbGhx%M5(6y1X3TKQ;3-3jXKaG3n2|fkFt##BOht}}bT12gH^nztvGj|V^OE`_5 zHv7tnvCEx!JS9`GwH^a|`PAtjH9d2KK@8D^Jf{OEo{J!x*d%IF`6hHkmb8ESU_R*qAW>s- z1ux2!$pj=h%d-tXR}1W2UjDQZd`mbIayd5_a-}u$ceNBbJKpUR=y8fHZM&x$UOwb_ z*Z_9;e(*TT^BZ27cBaG*Fl<&MV`bMiz`NaIv(RhmN>}FO+Vb&!;f(wXezqmWGq$R` zLF_$xr*TGc&9JunatUjHeCbswSnc733Xk``yk;19rgC5;&^+sn{#!AdoKAE|(wXES z_{Nc|ol8{1N*n8GQxDk}6g+;>_SXXUk>I)O{2P`xtebYy&d?9VW+lIX_S-&h7CSsy z7Zw%*f*|pwQ;!9wXrHdV_X%bd>rF|H`AhPNI*%+UvXb%k^+)V?GdfV=*6b1+mlj^0 zzeth#t%|zH>j2I}gLfhA$83v+)1#`dV@lMYnK0Q{$jMj(x)R->#MFHyjtQnhw*6>F z+_Dg)mYL2R%?Txp`QA8e>%2%-`#|EQ4j z9oiiCR)6_Rq-4Nzbx+izJK;bP_f$4g@^dMh{P@mbY==fhsAWb~{>a9Wo%#H8p3Bp^ zq1Td(ltackvCHF(R(YEUY3C%*N0hn|#MscUt+D8(0k75qZRaV|Vm9`WnaRUR#j(Vj z`!e5CrYhruA2zn99M?VfiQyFISVeFu8ygYUd;pp{Rof!Yk|N~a31fcu**ep3&-b^F zA(nm2V=!i4-53fAeWVW%cOWo4p_7eoD(` zcNk>o+XqK1DHk{MAUL_>v<(|yDsv}{YPs5oeDb`WrLupyUODm0(oPtYa-d!Y-$&vd zhs4ZXQbTnU3=~!As=!Z0=!mF4#^rOaD2psbo~!@F*G@UUWJEG&!gEUG{!GSIidp>b z|0*h4rIzN+Mr*wCIqq8 z;(d7m(P4?kFq~a8kQ2;))|M0YOSv^1+ZJBsRIEfzjg>yu zE15?}iPBA*5j~ZAEK<|;hUmW$A2|oZKXZ8avlcaMjZ&O1mjIkMW2$1xvxUbe+@QE& z2El4-(i%I}x!o>8$_);?_SL8{JMre|UPAeZ!%GUvItM^y@d$Oy?Z4+ISMn@{MGhvY z!}SBv`hD9-DiQ%apfhe}q?FF%_pF+`BHM4(-NxU1{ba6IPS2l-V>)f&;x;*CSfx~* zI{Vq14lop%T7gfO{fki8R`oN_ft?apgLMAOHLs|oO2j(?`egV@>(3-YWqJku2!>Ml zsPd=!bICy^9;#-M%}662^(nj*X0N8-1Slq^KYWils(y7<0#hHVd;cE*=0F+0K5#*w zOE5sfVOf<_@~Z~Qi9wJv+9#3S!NUj`h9)So@VWRi0XCBS+d(G!9au{lErLWh;+4VF zEKJI9sLBG%)e=%EbXXTcNH};bRx5}wje^(;w7*o~sa8b^?*Ro8HN=CPEGT)+WT5xz zYGy=xG*S#=_1O9l969IUNubfi)+R&iU}pi+k~LmUVvG15c%b$*uU}Rq(jb_M*Uy19 z@j5mxaZQjFFvh?H{;#dg*I9l2yJ-hkFI^t@rrGz+7qfr%BfsY(%fI*YzxcLRpM6Dx z?2muncZjmkW1m;oFHQE|n`GHLN8|Ag&iFoOYz)RnX_}1syhX9qckH5^~D_b9^J=eG=`EA#tED+D+~rba1pfgq1)>{HG*8AVg&%L9t9Ki`_6k5 z+K|UWoTduYSs1(r_Y6g;@y4SwT;9Kd{mF#rUj#_Pfh_;HU_dZU@j{ZIfjDe%#(@Qu z8}|$*G!(saU|fJRSqmK^BLM)6aVW|X-7KpOtrMA$T_dQIuehkcR|+3+TpznvHTM)i zlZjdntqoDeSRFR%pm4#=8w?_3)y{b^4yaJh#%smmR0GhMn)ZXw1^FRFKUmKQ6c<6L zfDll$tuULNqbw`P08b&@BWo(0ou467NeFrrJd;F0N{OnfV7)~mWHa3&eAYNdo<%BJ z6u!j3#ey|r3*KTtfSxWIm~$2&4|oW0C{F_?S;%B#HVp3x-U<}}Lx4jNyx)V_I12&~ z7qDD_CLzb^8=TYYMJ7fZAQ}%dYV%U|4g`aBW}!raL4WYg%)9rgOP3x2D4$RG{PNaU zB*^~w_k0I)mA)h(zUk!`ZhfHF?SJEVy!q}l%k~GuVXCBL;rIpTjGUSP+GNfHHgG4c zt1b0_mKSOWS~lQ9adc8F6A_*{@{x+u3Yycq4zfTX%G3AHy+LJG$T($zmG`g=u$;*B zBDA_=Hdmk8ffhr_M95yl>?i?I|2KTYk&F*zWGgU1svqGw#yrJ~H?HB)(?d-2IgGPV zSr-S>Id&!kbTUQRkah6JB2$9YTa1MSJY*$YghMNsJiCxFI3lgP+Ns8YaS6pFjIMC9 zC@?Pt-hb^Tdc6$HSs-MfUJ9_39&QMlMgWzxW{NqQj!;h^2!jcEka~I_rr$PABQnBf zn9XK*cyNI0moH)5A3$;u5@HSy0m~&(jhun?4$L{QgolX%bZ=sF&3jL#H=Kt6fO-sh z+w<24Rt0Sa4`Xbt_Hy0^l~-fb-E_R7U1j`HUk91^*?jG5OLRFA?nhCsaB_Br`Fw`q zV1#b3Ur(oS%wxG)V6|Ezks=tfqki9U-xBXO1Ub$il?u43r$Yx#2Ft@iU$Y%rwwKYP zLQ2^Lw3v*DKt<$@Z~{Ii5meecOUXoSrTI*-rq`nV z!gLA*+et_GagZ5v1OV0pX_8G!wfY9{vwwlF=OFuIzwbL$uiv?@wf@kxt2e)UJf6IF zb8GiXlBVNcznd@~0d9ImQI`pA-e3z%^dYklL}l_mW{nn%1EOVJ7x5<-C%FQ3rdF4N zEyL^>uUm z_9pkH(V&M;=PFiZg~Q`xELZ2K`~vf$gp@RGzypvR81*_xWOxXz4X*hv@K7lbxPXgt z?~!l@PHre+7$YN_Lk4JP@$htk{r$_>-Q0jk3FBo#feQ(#1ehXCJQD#LkOBxMHO|rN zdQX!T7zbh7HUzU)cRpguEZ~4;rE&k!QwYv6et8)1Przsgtx1BKNTNF-@O|UK)dU9t z!g@TxC0rm$(+j0>!$NTNY&BMwxU8lwseo}hZv(u*>i5bocuzFFmim5k9_Ug$9JmN_ z-U`R3$C%D$81{$ghX6}|$k=B(JEv(7qDcxaOw$PFIL}Vv;GCL(oW(;w@@t#D7x#N? z_OWL&`Q`wMeh%?DqSuVWAZw_MGk70tCFA=G{~lLNDk4WYLV)qxgpBvbUARxyT9`21 zm|ic8ctZQN={g$&!5I3ip0ob;UB9Iu`-i^$BfQ&9w!7WVhxWF2{%F73|G@6{{*_*T zkoE=xZoPr?764r^j>c7=1N9hn*9P}{kcQG3Fv6`Pl>oc6?ITU9YbTew?1sSDxG(Spk5imt6XTgYari~#9 ztcWxrAEu*HN83A(gV_?fm3Z~aWppz|nXBjUf&)^*2>~Y^-aZkhh);wqwa3)EmzppfLkv!9<2| z*MNI75;+_lAL01q1e=pBjQS%esSwB2SnDyHpX220guEX@)e{ZjV^-Ic)J<^bU^I7) zd6-b1b0J#^N8kZ#UE{~`IbdiKkNA0F1 zESGZ`XpaqyM$a;UIYMMq2gId_f4Jt&=&)vofD32pWXycoZ=}B+~40;**-8~qyg{oZP=->cv-Ma(*=oG`QLO)Aj zstO1rT150k03+;DN*GhYIu8eiPA5YF0b?|5Rlx_f6ypM?ONJL;dKFjqw~;8qOMMV6 zRGxu52J46yDgy7ZK4zpdAo9c15oWe>M*-5hU@CqJ;UG5U`$?e4sHbF$Iz_WB~p`VdOO zX_~-F*ik6&fD7eGyxHwd+b)m50F@{pi~^yD!(Vt1>W3h1c8}U5+0_}-#Y`qD41bHpXvCHAvrb`xl*Nhrep zoX_XD_wYW_G{yGjR{efS>1ME)&+zo%DHf|GM#Fx{>SY~dxW}P9pO27o2ygqQ-9Aov=QFy?FA%e7l8bCj84z1~i zi7@s9p=&FIgE1OX%6hgG3kIa|L8W^eWwLDy?&3ITfN(Pxy1G5557$Sa79aOa)!$cr=~Dp3Pv*16W&Od$NJ+ zdsi?S4Zv9sf+djPuuOn~6G`5Acxgkhb2vOY!TkqMu(!L5-JPxGA@iY}W(>|4c;Nx3 zk#L7=lMyn01GgVP#o@sbM!gRDDnYR-kS|xL${cCR$#9%CfsqbX8>>%9sgNiJjR2>J zh-bSrg?$f9#stPs5i zu~Nc);goXM*?Nt`HUu*8pxARJKn@`IuEKK(%atove&Xhh>)*3E8E$vFndo$S5F#PK-G`DwFbJVg&yx?FNU)fF zx-YqDr*rauehnmNuQcRlvTFyE6)I9VPl7w zG1yRZ*+3Sr8xC<}Ffu(MZv&vxrhaf;z+)?;sjQ8}@DSWDOpFbmS4s&k2~UiM&h0Ec zVtvk0c_{@)qM}KMM@K1GZy|&PXQDps8Dl__(Dg*_xCw|9_cSr8|X#1`Qpo@{LavIAHb><#H_&Z%IC z62{(yEL(W`o}E!21icrLq2-!`fW{KdLnwJ`?$7|LH z1=xTUGJs17Aq9lCb+C@QeV{3$FThG6;I;b#@Sc)~5MW#|6Nj}ppP%9I16GxS%POhD3xgRoWxGent|d!t6217F7sTCfH+!4+Mbv z07|JkgRUEDKKgDDO-o3IN^4YQg|gDH&Y{=sqSx)#CP`&ppwb#enWHQVuN$U; zM7misM3eS6Rk9=twskfg8;Hz%l-8ou8lpk@`0$<)}jjAe8RwZ;*qAUw6 zR;$|{{O8KDT>ax;`S|mWqrdead-u-$(PVSuk8W*l{`sp{uH4$*+DJQ{4r{<~)Vk|h zrigaOH8!=V(;NeB+`KWc*1&uSp2iqRr2>#nuN%qF&zf*VthOl&#l_QG#LSMcBx^0e zJ-h{qRe@EJ!#IypYZzlGlL;y=z}K56TH*Eky)dyfA-02aV4*WhW$Q&Kr0%i;7cjB7 zOr_~xXzoiBBwN?0DF+)#W_)mJMg}K>xQDL|M0`zSLkI?{z6O+eFbaa63{pgw#^ER? z(M<(5M%Qrb>SZkQ9LHy;I6XbZFMRSg#=Sdu<<@mvzj_%w%OHh>X98Ah2nKA8GdSDa z8w7r(^$toV@Y;Ye0nTl}cS#i{nScvldE8B#MKi2CZ=}E>=8r-#O#t zL{^qaGYhDu>D6W<_`p!evZRI%z;Ll-jRxJo1qxo>r4PS0%Q$CQwS&&8|3uOv=V*qE0?qdncCr7pkVud^qyiFXb~xx!*TgS8qSKwcD>FIOKg%kt!BKlvM9 zdzkEZz3<&H+OkWRFYjbo_7gkXTYv7xwJWzKlQE~wkklKssx&+clQad5cBWuRuO(_Z zYfxY@DziCn3@73&C3p`mIZZirEhUYy^@fS1O$<6VW;xMwGc=>xo6mdlNHx}=Dl6o9 zfz#77(*#Be-7zt;m80sAWIxZTAP zug30LWnfgK8Ea}s{;gm;66xf8S!ofjavW&1s2CSs(gjnVgct0&^bp95f^x^O$9{PB<_d#VvfZ3 zG1=OMRDmAo8_Hb_NKy)DV+j8bTN*Vi{~0C zXzf53_e)h()Iin-RaKGsOp>76>4m+}z#qL{4^k?mDuql`T@?XD%Yy*M!y&u}lC*;? z%K~)PR0K8bCj_KaVGqXfOHBo*wMJQ#&|w;fk|ZUMV|&Qm&7#s3in4^xb1+X?a8*^9 zE#_yl#r$WNtJT-UV8{zW_Rsvt4`DW&i}`G}pC;*_yn5xze|qKWrJeDp&uGY=gp>(c z=ot;`9lUh_7mxuTd)A4{S<ES!cV(=(_O~XBS0_xX2-_)3{Lbw#nwP zI~p;zs?w+`8b~*t&XKPwGAZEY-nz!VAG%$(n=O9(&0)k73l!uNgm5H1Y^FbSr z&;8RPDQ2l&M64{>-l z#jUG*7>|cFrrsv*Q=FrRl?w(Q4H2!NlGOuD0Tu>cP<8a^=n0-2KS4jSP^ts(8MG!J z*;*zYf;1R|bsoJeK__9DE@riPIGl&m28d=kFoCoy&`DBqvJxT$&FF*kH!!LU<5 znBbhc%dHdCKcg>>B?{0gzrxs(w(7*e*KSR9so)5JXAC5Z3hvVQS*k;1ZX8yz(7MI&sR_ac=6g5l;#p1J$Z~ze&HcrxVnwqtueAhLP(lxRpaEM z$B~hVKLt?V!i4m_qc|kY`sV-!%7vZCZ z2V4JK#Eiq&l2iuD7po^Zz>`^ylrqR~_Irv_ zd4dQGw5|}VkC@<~u1pQes>F0QLsiC!AA$F6wV$q*_ZO?;@6Q*@d%<4$ZNDS{{HY)Q z0pzPymvQlt!Jz-Y-rC&$&b^&&Ip}x7C<lnyq4k#AwsDgGBC6- zq~JLaq8*}FB?TYC@gi^!A7@j=|MV9!Lg#22>1tKr^yCahRl!)o0EGlpp!1NUezQ3^ z7qG^KW&>%$J<$*9z+?jP-^WeOQ8yL1WAI+qvzCnZD2gSPixQnqf;5wa-wJ_lw|gNQ zagOZkJc8kdV6etE9-X+To{0f4cA#SbqkF;XW?Q^J@j5r~3N>nKKi3)hq~Nm(B@;Trm2m<|y2Er`bu3o-!AtQ9*>&NG( z0Q1<}-9xwAg^U$g;7d12NOKP<0J(bBR$JZJeBFOh2HREwnie)oiorngkNyX7&xGc2 zjp?=mef$%7tc{OB^FE^Zgz+%J7arcxq~!SCtE#Hm29eF-96^HCYLsPxvMjJ%tuUL- zFzEK01j{*}7v=e4x%_*x<^1Os%hmGX`T6sXpI_FJfASCgV4A2--#PPbO3MG$=ElZH zcD5&SIO^3MKT`HIT($ZH3p#abUWJ)Q@U_8+cOJ&+FrhV4plp4Lx_Xl|+|sC)iu&^l z)DY*uC8n1P=N_f&Pnq{j@jHI%Mx_E9m)z58D4{?BKX)O1ZteE@%r7zxOv%OYhxok)Cd9xqV~Q7{e+m9faO4!CvT-hq39BgXv>u1tD(GGAi3SWu&lx5W@13}hf91yS^fg~i~( z37coMS6tY);1@*+(OWojp^lFZadLi!>(_4}RY^;FO@VqgpJBF`V$|LH~t~@fd@CKipgyN{dFC z+-~3?IOJ$;>J!V_3N9!7(io4bvM?3NY>CF<14q+9YZC&ktL1Z?b12nt{Ji(*_PRuK z5j1D0)5%EHWGw;V=X0E&&jAq6QFW8X1Oz~$5|m|Gmxobf-p&}JD^cuzw#nN7YBKn< zq;&5QN_|e4a%h}5ct|ec9Ea8pv)K}PQ6ftdbUG;+F7u|O6oRY(FLtrp>YaA*Yu*!e zZF!w()NoAe^G7r0@FIxjI`Q|l_3~|4rhZ_9l^|o`AaJ&6BYDC_xpU}e3Epw*7VbQH zh|k=9h?lMbo1*~|0SFalT6t<5QAN%PZUU*Ybe`k&H*Vwf_yCiRKqpn8;fk{6!;+(w zLt#9IVX8os?OII@yvZ=bQrhBy8co>gaEtO! z+RyX(4EG=0$M*I%#sMZ^0GX(VDGT$(0>vuFWOtYLhO=Onz9(L1Aq4dZBoEy1nB_L_ z4~T3YPr?_@F9=!MQeU+Gow3-1Pys#&jmY47WsLz#XtaB+RCJA9D7=SjJrnU-#r^AA z2TC1$1OBQ*T%f%idLO|EMstBmS2&-ZV!l{GN`+NXAWJihhC?72iW_aJ%G!Tw;QmTk z7N7h4{YPIDFhLz;2fe}nIaSH_U^vfTtqVT;Es@AaksM)SJCy*}- zlzB<43^4S2-3ul*7wI_wT3HJHU2G<~`fIiL!Cx%>NjBT~bVhwTSnQU&#@(o`xNAMI z&5D^^=r%`DMxgLft;p(9aerqI$7g4Fcz6b5GdDATPAW^~NCyybM6qE5JxN3#z0pS2Is}gy>LZTG<-A;Xo zM;x4(Ijr6%l`f&H3S0J zZJ-nKk7)0Gv;;NJ8qKsB7%{VL2VaJZ&l2a-6Srk8`oxA<>pZbljsQ?QAay%HnDmcezIKswcjI5JT(1{N;i-8Gs3gxUrr8QQ| z9C=ZqDm9kN0!3NWr*f*&+SbrHvVUtV<$P#9gl0tWSB<~Wd-`4>1+1|(2p>mcJ=j!s2F$Ntp|82K? zpvi(52Rw5v{IOARkXew7hAW#h~E!4GVa-k_17K+;h*$Opss%E3W_(c#h7ajfSQijxM{Ixf@+BE-$j4aL$}wdgGH0cp?(OhwJ3@T^Z5$PRgUFi1!F8k;KWIpG#RTD zb>>BE6|A;_xUNxFA!G1_V^ay}Lw1CanUL3{2vi{@ zIHZaVIn)E&O<5HToI4DAeH^AeeD3Z;q@4_x zwm0k1Dc)LYvcMxR3cUW-n>cv-2$zNlx``l+G<2QG5iO2uaaffVJWEkk28uYctCZz%GMIV)jrv2RDe0qlId`dqbXnI5?Yl4r~ z6{fQ(@?weY@h}`HK?Z9L=4Fmmk)y0Mz&H}2kfaIHEJLT0p&NuAe4SpVsWjTz zY&$SU&S@m)rD+-(mGbrcPR>sL`uW+}-RB)Ff2&Il z`aSeEh8Pa};GDtQIKCv71H{Q&u9i4IpJBBsP!u{mAObWGF=j&zf3Kb*01zp>)#Qrf zRN9-QO-pH;WW)`0LA%}h+Oy3X5lSQZM%>E=hss4Hk=Y+`WGv z$4~EIe;}|mP_<1Ti`O!+E*J}=(B~C$!?7wVjJt})$GA9Wi(ysL;nVGiU{@HhTQ0~q z7;SM!+!L&pfKyYqY0Sp^9Tki7`4q=T2N;jXI66A68=&>{jj;cWwU{p#@Rs&TWi)JM zQC1a9u82u#7WUE><`@JI8#! zM4p#mVV)4@4Y#h5%hChhj5&$s9rVzNrh8V~s688)zDQQ;s6_M(b(1I(^MP8v9{7qO z14JBC+)SvA=EH!8NH}(TeZ1HkVzbjB^_er6t(KTA7ckKW6Ae;wVdKQtZDn!PPhwQI z1~m|cn}B(RGL{938Y!ayV?CTLsS;3e>`5&Bs8ny>0}wf~EMTtizP`rZ`MP`T0_%VW zUj`4nq^3n3|d!EDgiD?T}iQM18s>1iq!dHhV$tZ9t`907@Ok_^m~008t^9TiC%T7!WohgDgI zNf0zqIrLN!Sr?p$TvB|px=iI5SjB1$ET+l_WI~%8NkTPLI8rP3k`NVJ)L5?$Wc|KYfjUwRgM@q(0ruEGXRh>Z7@PK z0hWaaJ(jS(b<)Q5EdS0qN6WivaawT1g@!TDaN9kJrL#`^7s_QAk$>k);YKea5l#>WTlA` z5W&h&sf2X)GERu#wNrjAi)I22QDh+k+yG=k;DxI<@VVO+KKhBz;Jxp72`)du(?@qO zJD+3J$uR0C1R*gNj7Mlcxt0ujrAs_GT7soxAKPyNs@$aID>T-)A<~S#=@2ib7SyuF~i|<0T;}j-t1OdK?83JNm9ws@H#_I}~GZjErjHsB9?}VU=;HUBprA z=1efHj@FT$9I^zb4s=y%nhqSssW4VRN{%c`(ChUGUSKuVqQP=~L*;Saf(3uqQNN29 zZoP<~|K(r8eDQHyA2KkLV|!zWEG4Hb8?IUO!D#O{=RF=A&Tw8TjJCIMe(;dE#*Su~ zsnA?3Dvjx?LXvG@&>z+!nsx^MtgBYL;TW@5l885IC1VV9Ss_b1NYf4gV3p^@<)j-E zK7Uhs=lKezs?h1A0OJ^s$Jm}sFd7U(qJd`bM6T*H+|$^fh~F32ml7egtHJmz5scLE zrK6!u+{4cX>Nfq4vqlMMj0uw195y`vb(4(?n)n<PPWiVQ^LJHu*_HG+4THP=ggZAPtV@=lMnuVOF9oQN1E{2Y=Oh0 z6RegEEFi;};`V5WwtO=hp;$`>9??0yO^S{ud{in?gT*)HN;vr=fm;Yk<23{)WltDv z7gu{!bL_%LLzIXmw>z+ciJC6t;ZazNJIfg!uI6y?aEzm{77m218AM@42(~SGVLOwc zrU&X1Kdv@z))o-NRhz@GFZTPS8D}DxkTl(Lc!B_$(w8#5Xu(J&rX|_4H4us#Ceh5C z0%>&84-cn{unmXs9>XL-KT%kgB^C?;&ukQXRjE-H3sjZCa5zAxlQqpb7jX?%A1vJS zde)HR9)o^{o0qTR)1UbS*oMH({Rw13LmC+k4X{>bB)3>q@6xx!`8ubQH${zYevP;LF9uVMTClnN^9?f0lB5|>8fS}l>K9mL_EP1V4VR~3#=Pobp1-u5;+-7b_;b@mz?q|NW6M8&yg?==Ypug7C^ zj*D4s$W$AM1sD1njC1&w1lCv!9yh}P*MsDOrY(dD$XW7xm@O74tE%S2Mi#_$K090H%TFY!di1;lxm@!GX!^;|q5fp)e^5Q6utzA-UKvsRYF;)aOugpH0-o}`A1 z2H{ylvOvwK>_))2E;hj;)r5Uf28=-ci4cVIuAT!A&am_jPE$i82LGt~ikqtDGXfU^ zY<$g_MaCf6KHX~v|WnpmV zV1{&j38TRfckkZDuq&V>>M=5m0S*?6(!j|+di@O=CB%px7_o4oPsM;_$=85$nu@E* z3)nk4tPmQVQYxaqg~JctLl+gwvcRZ6qU#tALGMTqk>@KE>tP_o?$Hqjs&DUy42F8MbCHi=HfC(S4V3GkV6&r$0gEqoC5o3)$AOPz78~69K zl(3qM`;6bNGa9SB#FOJg@>tbhn8~t9dR*D%z;*C0W_cYt??ED=4!2n8%;20*b z$_t#GpFgdt>Q^^RjmMu(CH>jki0H=3m?2V z7C2@h(fW*LPEjDHOpHoR89VcwBLOfL3X@JBdy_3#?r<`l;?3hDI36b#G|)l}t~8+_ zOgS|cjf9j8zG(vy0UfR290M1?LNEx_q*h7U4xa7R&axP5ve5W*Z7&DTJ)SM&+IU&J z%!_`y@jb+hrft$u-xC+jUxF!5FmS1jVcH#U1R1P%jc&a~XX``Ya<`A|BqhfqA;6tQ zzL;TdEO?RzC7ui=r-#-Si$#upfF@!EaiM`Jf(JslHr6@x2R*!a^Cq4=xrh0x#P*oV zsm*Y6>oUACSj^6FbEgk@N4#N976+CD}O9MTS(obuR>HHkd8f*-Af=P`H z%nn{lysdS0aE;x205$o)sn{Y!W$XPG_eJ=4^nHxMI}09YRxuNfD#}LjNXdi?&n!8B z@eBL1T@A)(IaafA(nDDkI6gVX)8k{PG{e@`E{5G6l0Xe}-UnZTX5eI`(rM>#a(<3m z*RMBo%Z$Y`UztU|yyv`o?US$H`I?c={=1gE{pNi@C83k3QR*rL2M*D~Oqmqa>M=uzCA@A==;S_32Bi`uG9NCu$@}{M>TI_iH0gW7EGcK}U|o;meg+$BLknMu zZsuAKkO~Cxm~GO@Pj-AFa$Q4n2QAZMXnd-XcKkJZ=0n$_3*lB)*?TDiSK$t%Ip_y#YvV$!UY4F&S|#D3TZ;D}(E! z5nkBXz&K5yBnP~MGX|1zlw|?W<7j5;q%%%fU!)fK;D-?H^cqcdV`dU3(0Wf3U1Js# zeO_JYlu9KpWSuo$N?M`XCo=}V_WZ6d^-o#LIUUNfyzqBX#~vNy!J84z@PI5G`e}x4 zH$%yR624|ri10wjXf5eIXdJbL(V7Bm2{pLoknExt#`fYLaW(Nn;gprWAw&XOe#D*S>e&C#?J0dZ1y)$6ib|)Kf%?_9+E^saS17bgfox^2qoH;NzCjx7f3>eP6uJbZ?>)8Ld2X+IB4hdDSF*r=tG2_fcG%E zB2M{iip}u|O!E35_8}o~rXdGL^CZDJ(VBpZ^gGby;|wr}z5>K|_Oh7=7Aw2>jKq=g zB2XUNbg#&iiP&zO6J{-$wpbk+m%*o^s;YVfxpfvtN5{DL@F9AGF<#iagkF#fTWjGt zUF*o3jh{JQL+Tqa9G{+GJRBmCG-FL0LvYV>eqgQrC9dSxG;OQBr1OrbH-RpaC`lif zJ8<8WSMj8Fp=9!8n*?Vq@;q-OvvCAVt%nX&5Yddqu+D%Pk3Q#kb!QLn+`5E*mVz+{ zE(Nr8aGc{wF~d?Dpp&#{Tg|#am_|e4iUB0rE^2L{RG`M#ix7vYbp24p?3gnajH<)t z2sVaMn%E|SKfB_A^sK|umm+@?{fc}SD0>aT$TMsSg_kE2> zIvfy9(BL7cRh6zY=yp@B?L!;?&KPQ<6byJ=6-d(*Juji0gBKEx3-q%LG7*>_YAk1Y z?PwLVXTbzK6IkU-ESAR@4hI+x2S^fG)AgLQ&8#Ow1Nk;aV=S+{ggbXX2jCdnqb_BM z5ST744yFa19AfwKKDtW6S&fHJZsYQH2Roybf}khGU+D#&%ow`k8|d^VH25-A0d8=0 z#`i38NCsW2;6U_zqT?UCWO6$NUOrZmCbE*GYKXF`QDSP&q{%(s|9$Pz%o`3SiInX z1%DyP#I8L6B#DGE7G+sn&|#D4BFY7MAX3MfSOE{SuI?3=Wm)rDYpHK*(-Jkz*V)mt z(%vXNBnPpizK*1fYmXWUhY-l*ca(Opx4DH>N-*!C7;sGuQRoV1H4TRNh)p&l>(5E! zK^k*r_&D~Q2c=OElYqlA;6!WW=V!<&gDb-k#+@#NQn2ut&Zn5K=E3hFj3bHnB5tK&d;VO%L<#DW27lz?lEJx)}ky8mdgT+Gi+~eVYax6`{&0fWDn&kN2whgPcfQY z#-Q7S@*c(V1czsb*c@`)+#kbR4N+P+4$N|cc`3lVyXX(L!bT=S6v19?iE?x30EFSk z68~8`*RyzeQ`K2aXEUfIL#i@JK?+97?CDvU&ZZdl2gs5%P_SejsEoC>XF+6+a8Cmc znPBjahyB9Cb&HBGURN!DFn9b(p zJYU_jraF3b{54OHt(OEGd>FDu9eA2F$zTsAV)+qFJOX>D?bsfj zzp^B&M_K>@a|J2LAW0KWSgQ{Z02(Tp6ktLEvT>7l-osQ?D{yN_m7tzkRhMUuMx}6s z2?;TauyEGEJA<;Q>TD?T zh=!+RfJB;!6x1N6*;9;hcxPZ3$C5iN6)?+Z=;|B^7g*^E^Lz!vL>wJK*Dq4kLf4)N zfkbrRz>w!9o<2E7e~_Wq??P~zp1N8UC`$__h>+e%1a>Cdn9dehRtmejSLqr^YT$TX zVYNKLd~t~V%^vnQ`w-5OA(7Tt<{T{DL2t4Hkx}VhS2m1+tJXO7aPTumv*(f|1Hhnl zaUt`s;hyNx%h2$py~S#^#A>xfr_+HHG&KT@WWQBaVLCs@D$lXEvrUJp5VaVE2S|wC zQW(Ao59@Vke7c%7LU4w!_fquEhrme-<^c<7n zunxYQb5us-==^lyjQfm|$;tB$j9&k_ReUCtK%^SSsFGLCB4Q2OXu-mdWzdeN5~NrJvG-fbbVQz27ub7 zDALSovl7l}PE%k2#4c;}QRPBhD3=(*Z1@(x)wecCG`ta9(DczjK92(yqaSVKwHZgk zv>FOl*G^IKeU@d3Bq2DYs!IA@#^H3iz|nMy%Ujz>lz{UV$^#oJ!y^x@%BpF~_&B~? z)`2!g2y0xpM~xCmcwT>=h~tp~5J4q{2lBEE*$#tOjj>2%HMAKeZ8};!ESz&VKVKrx zD`Z)U)oKN;4H<2Rtd22YJQ`waV}hfjQ;d2eY>dW$_oz$-Q=LJuIj(FCFz9q3oy4l} zu;?S_0_gPMeG2QyrEu3}ecDnV5sZdG!RlYhBjD7s>(}S-YJQe^XyssNa7Zq8NANR#GgxZv*FrB9E zp0-P`Hg_~)L!>BjSQaZRK$3Lr9dfHN)fFDirZ|{Rv9cC2NopK8zCR&a-lvFW9$}NbNw$RxZRs{^c%;v&bD9)W

T(sNAbb4>FE&Xy|}2B@?Xc&!MylL@><25$mU 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 .toolbarbutton-icon { + background-color: transparent !important; + border-color: var(--toolbarbutton-hover-background) !important; + transition: background-color var(--animation-speed) !important; +} + +:root:not([uidensity="compact"]) #back-button:not([disabled]):not([open]):hover > .toolbarbutton-icon { + background-color: var(--toolbarbutton-hover-background) !important; + box-shadow: none !important; +} + +:root:not([uidensity="compact"]) #back-button:not([disabled]):not([open]):active > .toolbarbutton-icon { + background-color: var(--toolbarbutton-active-background) !important; + box-shadow: none !important; +} + +:root:not([uidensity="compact"]) toolbarbutton:not(#back-button):not([disabled]):not([open]):active, +.toolbarbutton-1:not(#back-button):not([disabled]):not([open]):active { + background-color: var(--toolbarbutton-active-background) !important; +} + + + +:root:not([uidensity="compact"]) #back-button[open] > .toolbarbutton-icon { + background-color: var(--toolbarbutton-active-background) !important; +} + +:root:not([uidensity="compact"]) #PersonalToolbar { /* bookmark bar */ + height: 30px !important; +} + + +/* normal density buttons */ + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #nav-bar .toolbarbutton-1:not(#back-button) { + margin-top: 4px !important; + margin-bottom: 4px !important; + margin-left: 0px !important; + margin-right: 0px !important; + padding-left: 3px !important; + padding-right: 3px !important; +} + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #nav-bar .toolbarbutton-1:not(#back-button) image { + margin-bottom: 1px !important; +} + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #back-button { + margin-top: -1px !important; + margin-bottom: -1px !important; +} + + + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #identity-box, +:root:not([uidensity="touch"]):not([uidensity="compact"]) #tracking-protection-icon-container { + padding-left: 8px !important; + padding-right: 8px !important; +} + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #identity-icon, +:root:not([uidensity="touch"]):not([uidensity="compact"]) #tracking-protection-icon-box { + margin-left: 1px !important; + margin-right: 1px !important; +} + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #urlbar { + height: 36px !important; + margin-top: 0px !important; + margin-bottom: 0px !important; + padding-top: 0px !important; + padding-bottom: 0px !important; +} + + +:root:not([uidensity="touch"]):not([uidensity="compact"]) .urlbar-icon:not(#pocket-button) { + width: 34px !important; + height: 36px !important; + padding: 8px !important; +} + + + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #pocket-button { + width: 32px !important; + height: 36px !important; + padding: 8px 8px 6px 8px !important; +} + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #contextual-feature-recommendation { + width: 32px !important; + height: 32px !important; + padding: 2px !important; +} + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #PanelUI-button { + padding-right: 5px !important; + padding-left: 5px !important; + margin-left: 5px !important; +} + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #library-animatable-box { + margin-top: 4px !important; +} + +:root:not([uidensity="touch"]):not([uidensity="compact"]) #tabs-newtab-button { + margin-left: -5px !important; + padding-left: 2px !important; + margin-bottom: 1px !important; + padding-bottom: 1px !important; +} + + +/* compact density buttons */ + +:root[uidensity="compact"] #nav-bar .toolbarbutton-1 { + margin-top: 4px !important; + margin-bottom: 4px !important; + padding: 0px 0px 0px 0px !important; +} + + + + +:root[uidensity="compact"] #nav-bar toolbaritem[animate] box { + margin-top: 1px !important; +} + + +:root[uidensity="compact"] #back-button[open] { + background-color: var(--toolbarbutton-active-background) !important; +} + + +:root[uidensity="compact"] #back-button:not([disabled]):not([open]):hover { + background-color: var(--toolbarbutton-hover-background) !important; +} +:root[uidensity="compact"] #back-button:not([disabled]):not([open]):active { + background-color: var(--toolbarbutton-active-background) !important; +} + +:root[uidensity="compact"] #identity-box, +:root[uidensity="compact"] #tracking-protection-icon-container { + min-width: 2px !important; + padding-left: 6px !important; + padding-right: 6px !important; +} + +:root[uidensity="compact"] #nav-bar{ + padding-top: 1px !important; +} + + +:root[uidensity="compact"] #urlbar { + height: 30px !important; + margin-top: 0px !important; + margin-bottom: 0px !important; + padding-bottom: 0px !important; +} + + + +:root[uidensity="compact"] .urlbar-icon:not(#pocket-button) { + width: 28px !important; + height: 30px !important; + padding: 6px !important; +} + +:root[uidensity="compact"] #pocket-button { + width: 28px !important; + height: 40px !important; + padding: 7px 6px 5px 6px !important; +} + +:root[uidensity="compact"] #contextual-feature-recommendation { + width: 32px !important; + height: 32px !important; + padding: 2px !important; +} + +:root[uidensity="compact"] #PersonalToolbar { + height: 25px !important; +} + +:root[uidensity="compact"] #library-animatable-box { + margin-top: 5px !important; +} + +:root[uidensity="compact"] #tabs-newtab-button { + margin-left: -5px !important; + margin-bottom: 1px !important; + padding-bottom: 1px !important; +} + + +/* touch density buttons */ + +:root[uidensity="touch"] #nav-bar .toolbarbutton-1:not(#back-button) { + margin-top: 5px !important; + margin-bottom: 3px !important; + padding-left: 0px !important; + padding-right: 0px !important; +} + + +:root[uidensity="touch"] #stop-reload-button[animate] .toolbarbutton-animatable-image { + margin-top: 2px !important; +} + +:root[uidensity="touch"] #identity-box, +:root[uidensity="touch"] #tracking-protection-icon-container { + padding-left: 9px !important; + padding-right: 9px !important; +} + + +:root[uidensity="touch"] #urlbar { + height: 36px !important; + margin-top: 0px !important; + margin-bottom: 0px !important; +} + +:root[uidensity="touch"] #nav-bar{ + padding-top: 2px !important; +} + + + +:root[uidensity="touch"] .urlbar-icon:not(#pocket-button) { + width: 34px !important; + height: 36px !important; + padding: 9px !important; +} + +:root[uidensity="touch"] #pocket-button { + width: 34px !important; + height: 36px !important; + padding: 10px 7px 8px 7px !important; +} + +:root[uidensity="touch"] #contextual-feature-recommendation { + width: 32px !important; + height: 33px !important; + padding: 2px !important; +} + +:root[uidensity="touch"] #PanelUI-button { + padding-left: 5px !important; + padding-right: 5px !important; +} + +:root[uidensity="touch"] tab { + height: 40px !important; +} + +:root[uidensity="touch"] #library-animatable-box { + margin-top: 7px !important; +} + +:root[uidensity="touch"] #tabs-newtab-button { + margin-left: -5px !important; + margin-bottom: 2px !important; + padding-right: 3px !important; + padding-left: 3px !important; + padding-bottom: 1px !important; +} + + + +/* various */ +.urlbar-input-box, +#identity-box, +#tracking-protection-icon-container, +.urlbar-history-dropmarker, +.urlbar-page-action, +#reader-mode-button, +[anonid=urlbar-go-button], +.toolbarbutton-1 > stack, +toolbarbutton:not(.titlebar-button):not([class^="findbar-find"]):not([class^="scrollbutton"]), +.close-icon +{ + border-radius: var(--button-corner-rounding)!important; +} + + +.findbar-find-next { + border-radius: 0px var(--button-corner-rounding) var(--button-corner-rounding) 0px !important; +} + +.findbar-textbox { + border-radius: var(--button-corner-rounding) 0px 0px var(--button-corner-rounding) !important; +} + +.bookmark-item { + padding-left: 7px !important; + padding-right: 7px !important; + margin-right: 0px !important; +} + + + +#urlbar { + border-radius: calc(1px + var(--button-corner-rounding)) !important; +} + +/* style identity box */ +#identity-box { + margin-right: 0px !important; +} + + + +/* style address bar */ +#urlbar-background { + background-color: transparent !important; + border-color: transparent !important; + box-shadow: none !important; +} + +#urlbar[breakout][breakout-extend] { + top: 4px !important; + left: 0px !important; + padding: 0px 0px 0px 0px !important; + height: 100% !important; + width: 100% !important; +} + +#urlbar[breakout][breakout-extend] > #urlbar-input-container { + height: var(--urlbar-toolbar-height) !important; + padding-block: 0px !important; + padding-inline: 0px !important; + padding-bottom: 6px !important; + margin-bottom: -5px !important; + margin-top: -1px !important; +} + +.urlbarView.megabar { + width: 100% !important; + margin-inline: 0px !important; + box-shadow: 0px 5px 15px -7px black !important; + border-radius: 0px 0px var(--menu-corner-rounding) var(--menu-corner-rounding) !important; + border: none !important; + padding-top: 0px !important; +} + +.urlbarView-body-inner { + border:none !important; +} + +.search-one-offs { + background-color: var(--toolbar-bgcolor) !important; +} + + + + + +#tracking-protection-icon-container { + border-inline-end: none !important; +} + +#pageActionSeparator { + display: none !important; +} + +.urlbar-icon, #userContext-indicator, #userContext-label { + fill: transparent !important; + background-color: transparent !important; + color: transparent !important; + transition: var(--animation-speed) !important; +} + + +#urlbar:hover .urlbar-icon, +#urlbar:active .urlbar-icon, +#urlbar[focused] .urlbar-icon { + fill: var(--toolbar-color) !important; +} + +#urlbar:hover #userContext-indicator, +#urlbar:active #userContext-indicator, +#urlbar[focused] #userContext-indicator, +#urlbar:hover #userContext-label, +#urlbar:active #userContext-label, +#urlbar[focused] #userContext-label { + color: var(--identity-tab-color) !important; + fill: var(--identity-tab-color) !important; +} + +.urlbar-page-action[open] { + background-color: var(--toolbarbutton-active-background) !important; + fill: var(--toolbar-color) !important; +} + +.urlbar-page-action[open]:hover { + background-color: var(--toolbarbutton-active-background) !important; + fill: var(--toolbar-color) !important; +} + +.urlbar-page-action[open] .urlbar-icon { + fill: var(--toolbar-color) !important; +} + +.urlbar-scheme { + padding-bottom: 11px !important; +} + + +#urlbar-container { + margin-left: -1px !important; + margin-right: -1px !important; +} + +.urlbar-input-box { + padding: 5px 5px !important; +} + +#urlbar { + background-color: transparent !important; + color: var(--lwt-toolbar-field-color, black) !important; +} + + +#urlbar:not(.hidden-focus)[focused="true"] { + background-color: var(--toolbarbutton-hover-background) !important; +} + +#pocket-button { + padding-bottom: 4px !important; +} + +.urlbar-icon-wrapper > .urlbar-icon:hover { + background-color: transparent !important; +} + +.urlbar-icon-wrapper { + background-color: transparent !important; + transition: background-color var(--animation-speed) !important; +} + + + +#urlbar:not([focused]) .urlbar-input-box:hover, +#identity-box:hover, +#tracking-protection-icon-container:hover, +.urlbar-icon:hover, +.urlbar-icon-wrapper:hover, +[anonid=urlbar-go-button]:hover { + background-color: var(--toolbarbutton-hover-background) !important; +} + + +#identity-box:active, +#tracking-protection-icon-container:active, +.urlbar-icon:active, +.urlbar-icon-wrapper:active, +[anonid=urlbar-go-button]:active { + background-color: var(--toolbarbutton-active-background) !important; +} + +.urlbar-input-box, +#identity-box, +#tracking-protection-icon-container, +[anonid=urlbar-go-button], +#urlbar { + transition: background-color var(--animation-speed) !important; +} + +#tracking-protection-icon, +#identity-box image { + transition: fill-opacity var(--animation-speed) !important; +} + +[lwthemetextcolor="dark"] .urlbarView-body-outer { + background-color: #f5f6f7 !important; + color: var(--toolbar-color) !important; +} + +.urlbarView-body-inner { + background-color: var(--toolbar-bgcolor) !important; +} + +.downloadsPanelFooterButton:hover { + outline: none !important; +} + +/* -------------------- Style context menus -------------------- */ +#context-navigation, +#context-sep-navigation, +#context-bookmarklink, +#context-viewinfo, +#context-viewpartialsource-selection, +#inspect-separator, +#context-savelink, +#context-sendimage, +#context-setDesktopBackground, +#context_reloadTab, +#context_moveTabOptions, +#context_bookmarkTab, +.bookmarks-actions-menuseparator, +.openintabs-menuitem { + display: none !important; +} + +menupopup, +menupopup menuitem, +menupopup menu, +menupopup menuseparator { + -moz-appearance: none !important; +} + +menupopup:not(#BMB_bookmarksPopup) { + padding: 6px 9px 9px !important; + margin: -6px -9px 0 !important; + border: 0 !important; + background: 0 !important; +} + +menu[open] menupopup:not(#BMB_bookmarksPopup) { + margin: -12px -9px 0 !important; +} + +#BMB_bookmarksPopup menu[open] menupopup { + transform: translateY(4px) !important; +} + +menupopup menuseparator +{ + margin-top: 5px !important; + margin-bottom: 5px !important; + padding: 0px !important; + border-bottom: none !important; + opacity: 0.2 !important; +} +.menupopup-arrowscrollbox { + background: Menu !important; /* fall back if adaptable colors are removed */ +} + +.menupopup-arrowscrollbox:not(.in-bookmarks-menu) { + padding: 6px 0 !important; +} + + +.panel-arrowcontent { + padding-top: 0px !important; + border: none !important; +} + +/* shadows and rounded corners for menus */ +.menupopup-arrowscrollbox:not(.in-bookmarks-menu) { + border-radius: var(--menu-corner-rounding) !important; + box-shadow: 0px 2px 9px -3px black !important; +} + +.panel-arrowcontainer .panel-arrowcontent, .menupopup-arrowscrollbox, hbox[flex="1"][part="innerbox"] { + border-radius: var(--menu-corner-rounding) !important; +} + + + + +.in-bookmarks-menu { + padding-bottom: 5px !important; + padding-top: 5px !important; +} + + +menu, +menuitem, +menucaption { + -moz-appearance: none !important; + height: var(--menu-item-height) !important; +} + +menu, +menuitem, +menucaption { + padding-left: 5px !important; + padding-right: 5px !important; +} + +menu:not(.subviewbutton) > .menu-right { + margin-top: 2px !important; + margin-right: 0px !important; + width: 0px !important; +} + +menu:not(.subviewbutton) > .menu-right image { + margin-right: -5px !important; + margin-top: -2px !important; + border: 6px solid var(--toolbar-color) !important; + border-top-color: transparent !important; + border-right-color: transparent !important; + border-bottom-color: transparent !important; +} + +panelview toolbarbutton:not(#fxa-manage-account-button) { + height: var(--menu-item-height) !important; +} + +#BMB_bookmarksPopup .menu-right { + height: 23px !important; +} + +#sidebar-switcher-bookmarks, #customization-uidensity-menuitem-compact { + margin-top: 5px !important; +} + +#customization-lwtheme-menu-header { + margin-top: 0px !important; +} + +/* windows-specific adjustments */ +@media (-moz-os-version: windows-win7), (-moz-os-version: windows-win8), (-moz-os-version: windows-win10) { + .bookmark-item .scrollbutton-up { + margin-top: -3px !important; + } + + .bookmark-item .scrollbutton-up > .toolbarbutton-icon { + margin-top: -2px !important; + border: 6px solid MenuText !important; + border-top-color: transparent !important; + border-right-color: transparent !important; + border-left-color: transparent !important; + } + + .bookmark-item .scrollbutton-down { + margin-bottom: -3px !important; + } + + .bookmark-item .scrollbutton-down > .toolbarbutton-icon { + margin-bottom: -2px !important; + border: 6px solid MenuText !important; + border-bottom-color: transparent !important; + border-right-color: transparent !important; + border-left-color: transparent !important; + } + + menu, + menuitem, + menucaption { + padding-left: 5px !important; + padding-right: 5px !important; + } + + menu:not(.subviewbutton) > .menu-right { + margin-right: 0px !important; + padding-left: 0px !important; + } + + .in-bookmarks-menu { + padding-bottom: 5px !important; + padding-top: 1px !important; + } + + #BMB_bookmarksPopup menu menupopup { + transform: translateY(-1px) !important; + } +} + +/* linux and mac-specific adjustments */ +@media not (-moz-os-version: windows-win10) { + @media not (-moz-os-version: windows-win8) { + @media not (-moz-os-version: windows-win7) { + hbox[flex="1"][part="innerbox"] { + box-shadow: 0px 2px 12px -6px black !important; + } + + .menu-iconic-left { + margin: 0px 6px !important; + } + + #BMB_bookmarksPopup menu[open] menupopup { + transform: translateY(1px) !important; + } + } + } +} + + +/* make menus adapt to theme */ +menu, +menuitem, +menucaption { + color: var(--toolbar-color) !important; +} + +.menupopup-arrowscrollbox { + background-color: var(--toolbar-bgcolor, Menu) !important; +} + +menu[_moz-menuactive="true"]:not([disabled="true"]), +menuitem[_moz-menuactive="true"]:not([disabled="true"]), +menucaption[_moz-menuactive="true"]:not([disabled="true"]) { + background-color: var(--toolbarbutton-hover-background, rgba(127,127,127,0.5)) !important; +} + +menu[disabled="true"], +menuitem[disabled="true"], +menucaption[disabled="true"] { + color: var(--toolbarbutton-hover-background, rgba(127,127,127,0.5)) !important; +} + +menu[disabled="true"][_moz-menuactive="true"], +menuitem[disabled="true"][_moz-menuactive="true"], +menucaption[disabled="true"][_moz-menuactive="true"] { + background-color: transparent !important; +} + +.panel-arrow { + fill: var(--toolbar-bgcolor) !important; +} + +[lwthemetextcolor="dark"] panelview:not([extension]), +[lwthemetextcolor="dark"] .panel-arrowcontent { + background-color: #f5f6f7 !important; +} + +.panel-subview-body { + background-color: var(--toolbar-bgcolor) !important; +} + +#downloadsPanel-mainView { + background-color: var(--toolbar-bgcolor) !important; +} + +#identity-popup-mainView { + background-color: var(--toolbar-bgcolor) !important; +} + +#identity-popup-content-blocking-detected { + color: var(--toolbar-active-background) !important; +} + +#identity-popup-permission-empty-hint { + color: var(--toolbar-active-background) !important; +} + +.identity-popup-warning-yellow { + color: black !important; +} + +panel:not([viewId^="PanelUI-webext"]) .panel-arrow { + fill: var(--toolbar-bgcolor) !important; +} + +.bookmark-item [class^="scrollbutton"] { + background-color: var(--toolbar-bgcolor) !important; +} diff --git a/config/fontconfig/conf.d/10-preferred.conf b/config/fontconfig/conf.d/10-preferred.conf new file mode 100644 index 0000000..ecf423d --- /dev/null +++ b/config/fontconfig/conf.d/10-preferred.conf @@ -0,0 +1,71 @@ + + + + + + serif + Tinos + + + sans-serif + Source Sans Pro + + + sans + Source Sans Pro + + + monospace + FiraCode Nerd Font + + + + Arial + + Source Sans Pro + + + + Helvetica + + Source Sans Pro + + + + Verdana + + Source Sans Pro + + + + Tahoma + + Source Sans Pro + + + + + Comic Sans MS + + Source Sans Pro + + + + Times New Roman + + Tinos + + + + Times + + Tinos + + + + Courier New + + FiraCode Nerd Font + + + diff --git a/config/fontconfig/conf.d/69-emoji.conf b/config/fontconfig/conf.d/69-emoji.conf new file mode 100644 index 0000000..d4be365 --- /dev/null +++ b/config/fontconfig/conf.d/69-emoji.conf @@ -0,0 +1,25 @@ + + + + + + + + sans-serif + + Noto Color Emoji + + + + + serif + + Noto Color Emoji + + + + diff --git a/config/fontconfig/conf.d/70-no-dejavu.conf b/config/fontconfig/conf.d/70-no-dejavu.conf new file mode 100644 index 0000000..d09ec74 --- /dev/null +++ b/config/fontconfig/conf.d/70-no-dejavu.conf @@ -0,0 +1,30 @@ + + + + + + + + + + + DejaVu Sans + + + + + DejaVu Serif + + + + + DejaVu Sans Mono + + + + + + diff --git a/config/fontconfig/fonts.conf b/config/fontconfig/fonts.conf new file mode 100644 index 0000000..0abacd6 --- /dev/null +++ b/config/fontconfig/fonts.conf @@ -0,0 +1,5 @@ + + + +

~/.fonts + diff --git a/config/i3status-rust/status.toml b/config/i3status-rust/status.toml new file mode 100644 index 0000000..95e7f21 --- /dev/null +++ b/config/i3status-rust/status.toml @@ -0,0 +1,51 @@ +[icons] +name = "awesome" + +[theme] +name = "solarized-dark" +[theme.overrides] +idle_bg = "#cc241d" +idle_fg = "#fbf1c7" +info_bg = "#fbf1c7" +info_fg = "#3c3836" +good_bg = "#79740e" +good_fg = "#fbf1c7" +warning_bg = "#b57614" +warning_fg = "#fbf1c7" +critical_bg = "#9d0006" +critical_fg = "#fbf1c7" +separator = "" + +#[[block]] +#block = "music" +#buttons = ["play", "next"] + +[[block]] +block = "battery" + +[[block]] +block = "maildir" +interval = 180 +inboxes = ["/home/hazel/var/mail/INBOX"] +threshold_warning = 1 +threshold_critical = 10 +display_type = "new" + +[[block]] +block = "net" +device = "wg0" +speed_up = false +speed_down = false + +[[block]] +block = "net" +device = "wlp1s0" +ssid = true +signal_strength = true +ip = false +speed_up = false +speed_down = false + +[[block]] +block = "time" +format = "%Y-%m-%d %I:%M" diff --git a/config/ncmpcpp/config b/config/ncmpcpp/config new file mode 100644 index 0000000..002ceff --- /dev/null +++ b/config/ncmpcpp/config @@ -0,0 +1,141 @@ +####################################################################### +## This is configuration file. Copy it to $HOME/.ncmpcpp/config ## +## or $XDG_CONFIG_HOME/ncmpcpp/config and set up your preferences ## +####################################################################### + +### directories ### + +ncmpcpp_directory = ~/.ncmpcpp + + +### Directory for storing downloaded lyrics ### + +lyrics_directory = ~/.lyrics + + +################################ + +% egrep -v '^#' .ncmpcpp/config + +visualizer_in_stereo = "no" +visualizer_fifo_path = "~/.local/share/mpd/fifo" +visualizer_output_name = "my_fifo" +visualizer_sync_interval = "10" +visualizer_type = "ellipse" +#visualizer_look = "▋▋" +visualizer_look = "▀▋" +visualizer_color = "blue, cyan, green, yellow, magenta, red, black" + +message_delay_time = "2" + +playlist_shorten_total_times = "yes" +playlist_display_mode = "classic" +playlist_editor_display_mode = "columns" + +browser_display_mode = "columns" + +search_engine_display_mode = "columns" + +autocenter_mode = "yes" + +mouse_support = "yes" + +centered_cursor = "yes" + +user_interface = "classic" + +follow_now_playing_lyrics = "yes" + +locked_screen_width_part = "60" + +display_bitrate = "no" + +external_editor = "vim" + +progressbar_elapsed_color = "white" +progressbar_color = "black" + +#progressbar_look = "▃▃▃" +#progressbar_look = "──" +progressbar_look = "==─" + +header_visibility = "no" +statusbar_visibility = "yes" +titles_visibility = "no" + +statusbar_color = "white" + +enable_window_title = "yes" + +now_playing_prefix = "$b$1" +now_playing_suffix = "$8$/b" + +#now_playing_prefix = "$u$2" +#now_playing_suffix = "$2$/u$2" + +song_columns_list_format = "(6)[]{} (23)[red]{a} (26)[yellow]{t|f} (40)[green]{b} (4)[blue]{l}" + +#song_list_format = " $7%l $2%t $R$5%a " +song_list_format = "$1> $2%a$8 - $3%b - $8%t $R $3%l " + +song_status_format = "$b$7♫ $2%a $8- $3%b $8- $8%t " +song_window_title_format = " {%a} - {%t}" + + +################### +## song format ## +## +## For a song format you can use: +## +## %l - length +## %f - filename +## %D - directory +## %a - artist +## %A - album artist +## %t - title +## %b - album +## %y - date +## %n - track number (01/12 -> 01) +## %N - full track info (01/12 -> 01/12) +## %g - genre +## %c - composer +## %p - performer +## %d - disc +## %C - comment +## %P - priority +## $R - begin right alignment +## +## +## Colors: +## +## - 0 - default window color (discards all other colors) +## - 1 - black +## - 2 - red +## - 3 - green +## - 4 - yellow +## - 5 - blue +## - 6 - magenta +## - 7 - cyan +## - 8 - white +## - 9 - end of current color +## - b - bold text +## - u - underline text +## - r - reverse colors +## - a - use alternative character set +## +## +################################################################### +## Custom command that will be executed each time song changes ## +## +#execute_on_song_change = +# +## +########################################################################### +## Custom command that will be executed each time player state changes ## +## The environment variable MPD_PLAYER_STATE is set to the current ## +## state (either unknown, play, pause, or stop) for its duration ## +## +# +#execute_on_player_state_change = notify-send "$(mpc current)" + +startup_slave_screen=visualizer diff --git a/config/tmux/tmux.conf b/config/tmux/tmux.conf new file mode 100644 index 0000000..b17aa39 --- /dev/null +++ b/config/tmux/tmux.conf @@ -0,0 +1,84 @@ +## SETTINGS +set -g default-shell /bin/zsh +set -g default-command /bin/zsh + +# force tmux to acknowledge xst's properties +set -g mouse on +set -g set-clipboard on +set -ga terminal-overrides ',xst-256color:RGB' + +set -g escape-time 0 +set -g base-index 1 + +## PLUGINS +set -g @plugin 'tmux-plugins/tpm' +set -g @plugin 'tmux-plugins/tmux-sensible' +set -g @plugin 'tmux-plugins/tmux-pain-control' +set -g @plugin 'tmux-plugins/tmux-open' + +# if tpm isn't installed, do that +if "test ! -d ~/.tmux/plugins/tpm" \ + "run 'git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm && ~/.tmux/plugins/tpm/bin/install_plugins'" + +run '~/.tmux/plugins/tpm/tpm' + +## UI +# tabs +set -g @tab_0l '#[fg=#cc241d,bg=default]' +set -g @tab_0r '#[bg=default,fg=#cc241d]' +set -g @tab_1l '#[bg=default,fg=#f9f5d7]#[bg=#f9f5d7,fg=default]' +set -g @tab_1r '#[bg=default,fg=#f9f5d7]' +set -g @tab_2l '#[bg=default,fg=#cc241d]#[bg=#cc241d,fg=#fbf1c7]' +set -g @tab_2r '#[bg=default,fg=#cc241d]' + +# statusline +set -g status-position bottom +set -g status-justify left +set-option -g status-style "bg=default" + +set -g status-left " " + +set -g status-right-length 24 +set -g status-right '#{@tab_0l} #H#{?#{==:#S,0},,: #S} #{@tab_0r}' + +setw -g window-status-separator ' ' +set -g window-status-format "#{@tab_1l} #I #{?#{==:#{pane_current_path},$HOME},#W,#{b:pane_current_path}} #{@tab_1r}" +set -g window-status-current-format "#{@tab_2l} #I #{?#{==:#{pane_current_path},$HOME},#W,#{b:pane_current_path}} #{@tab_2r}" + +# pane borders +set -g pane-border-style 'fg=default,bg=default' +set -g pane-active-border-style 'fg=#cc241d,bg=default' + +# pane contents +set -g window-style 'fg=default,bg=default' +set -g window-active-style 'fg=default,bg=default' + +## BINDINGS +# prefix +unbind C-b +set-option -g prefix C-a +bind-key C-a send-prefix + +# split panes w/ |/- +bind | split-window -h +bind - split-window -v +unbind '"' +unbind % + +# reload config +bind r source-file ~/.tmux.conf + +# vim-ish +set-window-option -g mode-keys vi +bind -n 'M-:' command-prompt +bind -n 'M-y' copy-mode +bind -n 'M-p' run "tmux set-buffer \"$(wl-paste)\"; tmux paste-buffer" + +bind -T copy-mode-vi 'y' send -X copy-selection-and-cancel +bind -T copy-mode-vi 'v' send -X begin-selection +bind -T copy-mode-vi 'V' send -X select-line +bind -T copy-mode-vi 'C-v' send -X rectangle-toggle +bind -T copy-mode-vi 'i' send -X cancel +bind -T copy-mode-vi 'a' send -X cancel +bind -T copy-mode-vi '[' send -X start-of-line\; send -X search-backward "❯" +bind -T copy-mode-vi ']' send -X end-of-line\; send -X search-forward "❯" diff --git a/config/tridactyl/tridactylrc b/config/tridactyl/tridactylrc new file mode 100644 index 0000000..79cbed0 --- /dev/null +++ b/config/tridactyl/tridactylrc @@ -0,0 +1,31 @@ +" nice +colors shydactyl + +" self-explanatory +set searchengine duckduckgo +set historyresults 10 + +" the irony is not lost on me +js tri.browserBg.runtime.getPlatformInfo().then(os=>{const editorcmd = os.os=="linux" ? "emacs" : "auto"; tri.config.set("editorcmd", editorcmd)}) + +" only hint search results on google & ddg +bindurl www.google.com f hint -Jc .rc > .r > a +bindurl www.google.com F hint -Jbc .rc>.r>a + +bindurl ^https://duckduckgo.com f hint -Jc [class=result__a] +bindurl ^https://duckduckgo.com F hint -Jbc [class=result__a] + +" better hinting +set hintfiltermode vimperator-reflow +set hintnames numeric + +" inject google translate upon `:translate` cmd +" again, irony not lost on me. +" also, for the record, Tridactyl doesn't support multi-line JS +command translate js let googleTranslateCallback = document.createElement('script'); googleTranslateCallback.innerHTML = "function googleTranslateElementInit(){ new google.translate.TranslateElement(); }"; document.body.insertBefore(googleTranslateCallback, document.body.firstChild); let googleTranslateScript = document.createElement('script'); googleTranslateScript.charset="UTF-8"; googleTranslateScript.src = "https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit&tl=&sl=&hl="; document.body.insertBefore(googleTranslateScript, document.body.firstChild); + +" quickref: https://quickref.dev +set searchurls.qrf https://quickref.dev/search?type=all&q= + +" new reddit is bad +autocmd DocStart ^http(s?)://www.reddit.com js tri.excmds.urlmodify("-t", "www", "old") diff --git a/config/zathura/zathurarc b/config/zathura/zathurarc new file mode 100644 index 0000000..fba9926 --- /dev/null +++ b/config/zathura/zathurarc @@ -0,0 +1,31 @@ +set window-title-home-tilde true +set statusbar-basename true +set selection-clipboard clipboard + +set font "FiraCode 9" + +set completion-bg "#fbf1c7" +set completion-fg "#3c3836" +set completion-group-bg "#fbf1c7" +set completion-group-fg "#8f6f8f" +set completion-highlight-bg "#3c3836" +set completion-highlight-fg "#fbf1c7" +set recolor-lightcolor "#fbf1c7" +set recolor-darkcolor "#3c3836" +set default-bg "#fbf1c7" +set inputbar-bg "#fbf1c7" +set inputbar-fg "#3c3836" +set notification-bg "#fbf1c7" +set notification-fg "#3c3836" +set notification-error-bg "aa4450" +set notification-error-fg "#3c3836" +set notification-warning-bg "aa4450" +set notification-warning-fg "#3c3836" +set statusbar-bg "#fbf1c7" +set statusbar-fg "#3c3836" +set index-bg "#fbf1c7" +set index-fg "#3c3836" +set index-active-bg "#3c3836" +set index-active-fg "#fbf1c7" +set render-loading-bg "#fbf1c7" +set render-loading-fg "#3c3836" diff --git a/config/zsh/zprofile b/config/zsh/zprofile new file mode 100644 index 0000000..b995317 --- /dev/null +++ b/config/zsh/zprofile @@ -0,0 +1,41 @@ +# -*- mode: sh; -*- +## hazel's zprofile + +## PATH +## also in zshrc +typeset -gU cdpath fpath mailpath path + +path=( + $path + ~/bin + ~/.local/bin + ~/.emacs.d/bin + ~/.cargo/bin + ~/.cabal/bin + ~/.go/bin + /opt/texlive/2020/bin/x86_64-linux +) + +## AUTOSTART SWAY +if [[ ! $WAYLAND_DISPLAY && "$(tty)" = "/dev/tty1" ]] ; then + # env vars, force wayland + ## mozilla + export MOZ_ENABLE_WAYLAND=1 + ## libreoffice + export SAL_USE_VCLPLUGIN=gtk3 + ## qt + export QT_QPA_PLATFORM=wayland-egl + export QT_WAYLAND_DISABLE_WINDOWDECORATION=1 + ## efl + export ECORE_EVAS_ENGINE=wayland_egl + export ELM_ENGINE=wayland_egl + ## sdl + export SDL_VIDEODRIVER=wayland + ## java is bad + export _JAVA_AWT_WM_NONREPARENTING=1 + ## xdg session + export XDG_SESSION_TYPE="wayland" + export XDG_CURRENT_DESKTOP="sway" + + exec sway +fi diff --git a/config/zsh/zshrc b/config/zsh/zshrc new file mode 100644 index 0000000..4c467ff --- /dev/null +++ b/config/zsh/zshrc @@ -0,0 +1,210 @@ +## ^ THE ABOVE IS AUTO-GENERATED! +## hazel's zsh config + +## CHRIST +[[ "$TERM" == "dumb" ]] && unsetopt zle && PS1='fuck you $ ' && return + +## PATH +typeset -gU cdpath fpath mailpath path + +path=( + $path + ~/bin + ~/.local/bin + ~/.emacs.d/bin + ~/.cargo/bin + ~/.cabal/bin + ~/.go/bin + /opt/texlive/2020/bin/x86_64-linux +) + +## HISTORY +setopt HIST_IGNORE_ALL_DUPS + +## I/O +# vim mode +bindkey -v + +# remove path separator from WORDCHARS +WORDCHARS=${WORDCHARS//[\/]} + +## ZR +zrinit() { + zr load zdharma/fast-syntax-highlighting \ + geometry-zsh/geometry > ~/.config/zr.zsh +} + +if [[ ! -f ~/.config/zr.zsh ]] || [[ ~/.zshrc -nt ~/.config/zr.zsh ]]; then + zrinit +fi + +source ~/.config/zr.zsh + +## PLUGINS +ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets) + +PROMPT_TITLE="$USER@$HOST: $PWD" + +GEOMETRY_PROMPT=(geometry_status geometry_path) +GEOMETRY_RPROMPT=(geometry_exitcode geometry_git) +GEOMETRY_SEPARATOR=" " + +GEOMETRY_STATUS_SYMBOL="λ" +GEOMETRY_STATUS_SYMBOL_ERROR="λ" +GEOMETRY_STATUS_COLOR_ERROR="red" +GEOMETRY_STATUS_COLOR="11" +GEOMETRY_STATUS_COLOR_ROOT="red" + +GEOMETRY_PATH_COLOR="green" + +## ENVIRONMENT +export WINIT_HIDPI_FACTOR=1.0 + +### dircolors +test -r ~/.config/dir_colors && eval $(dircolors ~/.config/dir_colors) + +### browser +export BROWSER='firefox' + +### code +export CC=clang +export CXX=clang++ +export GOPATH=~/.go +export XBPS_DISTDIR=~/var/packages +export RUST_SRC_PATH="$(rustc --print sysroot)/lib/rustlib/src/rust/src" +export BUNDLE_PATH=~/.gems +export GEM_HOME=~/.gems + +### tex +export TEXMFHOME=~/.texmf +export TEXMFVAR=~/.texmf-var +export TEXMFCONFIG=~/.texmf-config + +### editors +export EDITOR='emacsclient -c' +export VISUAL='emacsclient -c' +export PAGER='less' + +### lang +if [[ -z "$LANG" ]]; then + export LANG='en_US.UTF-8' +fi + +### xdg config +export XDG_CONFIG_HOME=~/.config + +### pager +export LESS='-F -g -i -M -R -S -w -X -z-4' + +if (( $#commands[(i)lesspipe(|.sh)] )); then + export LESSOPEN="| /usr/bin/env $commands[(i)lesspipe(|.sh)] %s 2>&-" +fi + +### temp +if [[ ! -d "$TMPDIR" ]]; then + export TMPDIR="/tmp/$LOGNAME" + mkdir -p -m 700 "$TMPDIR" +fi + +TMPPREFIX="${TMPDIR%/}/zsh" + +### nq +export NQDIR=~/var/queue + +## FUNCTIONS +function man() { + env \ + LESS_TERMCAP_md=$(tput bold; tput setaf 4) \ + LESS_TERMCAP_me=$(tput sgr0) \ + LESS_TERMCAP_mb=$(tput blink) \ + LESS_TERMCAP_us=$(tput setaf 2) \ + LESS_TERMCAP_ue=$(tput sgr0) \ + LESS_TERMCAP_so=$(tput smso) \ + LESS_TERMCAP_se=$(tput rmso) \ + PAGER="${commands[less]:-$PAGER}" \ + man "$@" +} + +## ALIASES +### redirecting functionality +alias ls="exa --group-directories-first --git --extended -h" +alias la="exa --group-directories-first --git --extended -a" +alias l="exa --group-directories-first --grid --git --extended -lh" +alias ll="exa --group-directories-first --grid --git --extended -lah" +alias cat="bat" +alias rm="rm -ir" +alias lc="linx-client" +alias less="less -SR" +alias sbcl="rlwrap sbcl" +alias shen="rlwrap shen" +alias provedit="shen eval -l ~/src/lpc/provedit!.shen -e '(provedit!)'" +alias bitch="sudo" +alias svu="SVDIR=~/var/service sv" # 'sv user' +alias rsfetch="rsfetch -PdeHklcsuU@w -p xbps -L $HOME/.config/rsfetch_ascii" + +### speed. i am. sspeed +alias t="tmux" +alias q="exit" +alias e="$VISUAL" +alias x="clear" +alias m="ncmpcpp" +alias rnb="toilet --gay -f future" +alias mtl="toilet --metal -f future" +alias rnt="toilet --gay -f term" + +### literally just git. +### i have a problem. +alias g='git' + +#### branching +alias gb='git branch' +alias gbc='git checkout -b' +alias gbd='git branch --delete' +alias gbD='git branch --delete --force' +alias gco='git checkout' +alias gm='git merge' + +#### committing +alias gc='git commit --verbose' +alias gca='git commit --amend --reuse-message HEAD' +alias gcm='git commit --message' + +#### fetching, pulling +alias gcl='git clone' +alias gcL='git clone --recurse-submodules' +alias gfm='git pull' + +#### indexing, adding +alias gia='git add' +alias giA='git add -A' +alias gir='git reset' + +#### log, status, diff, etc +alias gl='git log --topo-order' +alias gls='git log --topo-order --stat' +alias gld='git log --topo-order --stat --patch --full-diff' +alias glc='git shortlog --summary --numbered' +alias glS='git log --show-signature' +alias gd='git diff --no-ext-diff' +alias gD='git diff --no-ext-diff --word-diff' +alias gs='git status --short' # dont care about ghostscript +alias gS='git status' + +#### push +alias gp='git push' +alias gpF='git push --force-with-lease' + +#### rebase +alias gr='git rebase' +alias gra='git rebase --abort' +alias grc='git rebase --continue' +alias gri='git rebase --interactive' +alias grs='git rebase --skip' + +#### remote +alias gR='git remote' +alias gRa='git remote add' +alias gRx='git remote rm' +alias gRm='git remote rename' +alias gRs='git remote set-url' +alias gRu='git remote update' diff --git a/home.nix b/home.nix new file mode 100644 index 0000000..a5b8e5b --- /dev/null +++ b/home.nix @@ -0,0 +1,57 @@ +{ config, pkgs, ... }: +{ + imports = [ + ./modules + ]; + + # let home-manager manage itself + programs.home-manager.enable = true; + + nixpkgs.overlays = import ./packages; + nixpkgs.config = { + allowUnfree = true; # sorry, Stallman + packageOverrides = pkgs: { + unstable = import { + config = config.nixpkgs.config; + }; + }; + }; + + # run the gpg agent + services.gpg-agent.enable = true; + + # for things that would be stupid to modularize + home.packages = with pkgs; [ + nix-index # for file searchin' + + # desktop apps + firefox-wayland + pavucontrol + pcmanfm + networkmanagerapplet + imv + mpv + + # chattin' + profanity # xmpp + dino # also xmpp + riot-desktop # may tricks + tdesktop # dash dash dot + discord # garbage + + # fetchin' + neofetch + tokei + toilet # heehee hoohoo + + # encryptin' + bitwarden-cli + pass-wayland + pinentry-gtk2 + age + minisign + gnupg + ]; + + home.stateVersion = "20.03"; +} diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..9ef1acd --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,8 @@ +{ config, lib, pkgs, ... }: +{ + imports = [ + ./desktop + ./lang + ./tools + ]; +} diff --git a/modules/desktop/alacritty.nix b/modules/desktop/alacritty.nix new file mode 100644 index 0000000..b433832 --- /dev/null +++ b/modules/desktop/alacritty.nix @@ -0,0 +1,6 @@ +{ config, pkgs, lib, ...}: +{ + programs.alacritty.enable = true; + + xdg.configFile."alacritty/alacritty.yml".source = lib.mkForce ../../config/alacritty/alacritty.yml; +} diff --git a/modules/desktop/default.nix b/modules/desktop/default.nix new file mode 100644 index 0000000..ed4acc6 --- /dev/null +++ b/modules/desktop/default.nix @@ -0,0 +1,13 @@ +{ config, lib, pkgs, ... }: +{ + imports = [ + ./alacritty.nix + ./dirs.nix + ./firefox.nix + ./gtk.nix + ./mako.nix + ./mpd.nix + ./sway.nix + ./zathura.nix + ]; +} diff --git a/modules/desktop/dirs.nix b/modules/desktop/dirs.nix new file mode 100644 index 0000000..2c6991e --- /dev/null +++ b/modules/desktop/dirs.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: +{ + xdg.enable = true; + xdg.userDirs.enable = true; + + # don't know why I have to do this + xdg.configFile."user-dirs.conf".text = lib.mkForce '' + enabled=True + ''; + + xdg.userDirs.desktop = "\$HOME/.cache/junk"; + xdg.userDirs.documents = "$\HOME/usr/doc"; + xdg.userDirs.download = "\$HOME/tmp"; + xdg.userDirs.music = "\$HOME/usr/music"; + xdg.userDirs.pictures = "\$HOME/usr/img"; + xdg.userDirs.publicShare = "\$HOME/.cache/junk/pub"; + xdg.userDirs.templates = "\$HOME/.cache/junk/tmp"; + xdg.userDirs.videos = "\$HOME/usr/video"; +} diff --git a/modules/desktop/firefox.nix b/modules/desktop/firefox.nix new file mode 100644 index 0000000..7e216d9 --- /dev/null +++ b/modules/desktop/firefox.nix @@ -0,0 +1,25 @@ +{ config, pkgs, lib, ...}: +{ + # sipp ramm + programs.firefox = { + enable = true; + package = pkgs.firefox-wayland; + + profiles = { + default = { + isDefault = true; + id = 0; + settings = { + "toolkit.legacyUserProfileCustomizations.stylesheets" = "true"; + }; + userChrome = (builtins.readFile ../../config/firefox/userChrome.css); + }; + }; + }; + + xdg.configFile."tridactyl/tridactylrc".source = ../../config/tridactyl/tridactylrc; + + home.packages = with pkgs; [ + tridactyl-native + ]; +} diff --git a/modules/desktop/gtk.nix b/modules/desktop/gtk.nix new file mode 100644 index 0000000..5200f63 --- /dev/null +++ b/modules/desktop/gtk.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: +{ + gtk.enable = true; + gtk.font = { + package = pkgs.source-sans-pro; + name = "Source Sans Pro 10"; + }; + gtk.iconTheme = { + package = pkgs.papirus-icon-theme; + name = "Papirus"; + }; + gtk.theme = { + package = pkgs.ant-theme; + name = "Ant"; + }; +} diff --git a/modules/desktop/mako.nix b/modules/desktop/mako.nix new file mode 100644 index 0000000..382f022 --- /dev/null +++ b/modules/desktop/mako.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: +{ + programs.mako = { + enable = true; + + font = "FiraCode 9"; + + backgroundColor = "#cc241d"; + textColor = "#fbf1c7"; + progressColor = "over #fbf1c7"; + borderSize = 0; + + margin = "20,20,10"; + padding = "10"; + + defaultTimeout = 4000; + maxVisible = 4; + layer = "overlay"; + groupBy = "summary"; + maxIconSize = 40; + }; + + home.packages = with pkgs; [ + libnotify + ]; +} diff --git a/modules/desktop/mpd.nix b/modules/desktop/mpd.nix new file mode 100644 index 0000000..3430534 --- /dev/null +++ b/modules/desktop/mpd.nix @@ -0,0 +1,62 @@ +{ config, pkgs, lib, ...}: +{ + # the music player daemon + services.mpd = { + enable = true; + musicDirectory = /home/hazel/usr/music; + + # enable pulse and ncmpcpp visualizer + extraConfig = '' + audio_output { + type "pulse" + name "pulse audio" + } + + audio_output { + type "fifo" + name "my_fifo" + path "~/.local/share/mpd/fifo" + format "44100:16:2" + } + ''; + }; + + # for playerctl and notifications + services.mpdris2 = { + enable = true; + notifications = true; + }; + + # load the mpdscribble config. this is private. + xdg.configFile."mpdscribble/mpdscribble.conf".source = + ../../config/mpdscribble/mpdscribble.conf; + + # create a systemd service for mpdscribble + # https://github.com/MusicPlayerDaemon/mpdscribble/blob/master/systemd/user/mpdscribble.service.in + systemd.user.services.mpdscribble = { + Unit = { + Description = "Audio scrobbler for MPD"; + Documentation = [ "man:mpdscribble(1)" ]; + After = [ "mpd.service" ]; + }; + + Service = { + Type = "simple"; + ExecStart = "${pkgs.mpdscribble}/bin/mpdscribble --no-daemon --conf /home/hazel/.config/mpdscribble/mpdscribble.conf"; + }; + + Install = { + WantedBy = [ "multi-user.target" ]; + }; + }; + + # the client + home.file.".ncmpcpp/config".source = ../../config/ncmpcpp/config; + + home.packages = with pkgs; [ + hazel.ncmpcppWithVisualizer + mpdscribble + playerctl + mpdris2 + ]; +} diff --git a/modules/desktop/sway.nix b/modules/desktop/sway.nix new file mode 100644 index 0000000..3600b4d --- /dev/null +++ b/modules/desktop/sway.nix @@ -0,0 +1,267 @@ +{ config, pkgs, lib, ... }: +let + colors = { + bg = "#fbf1c7"; + fg = "#3c3837"; + hl = "#cc241d"; + blk = "#3c3836"; + urg = "#d79921"; + nil = "#000000"; + }; + + workspaces = [ + "1: I " + "2: II " + "3: III " + "4: IV " + "5: V " + "6: VI " + "7: VII " + "8: VIII " + ]; + + systemMode = "system: (x) exit (l) lock (h) suspend (r) reboot (s) shutdown (i) reload"; + launchMode = "launch: (b) firefox (e) emacs (f) files (m) ncmpcpp"; + + # create a workspace bind from one workspace + genWSBind = with builtins; (ws: let + modifier = config.wayland.windowManager.sway.config.modifier; + wsNum = substring 0 1 ws; # kind of a hack, don't go above single digits. + in { + "${modifier}+${wsNum}" = ''workspace "${ws}"''; + "${modifier}+Shift+${wsNum}" = ''move container to workspace "${ws}"''; + }); +in +{ + # compositor of choice + wayland.windowManager.sway = { + enable = true; + wrapperFeatures.gtk = true; # force wayland + + config = { + startup = [ + { command = "xrdb -load ~/etc/config/X/Xresources"; always = true; } + { command = '' + swayidle -w \ + timeout 300 'swaylock -f -c 000000' \ + timeout 600 'swaymsg "output * dpms off"' \ + resume 'swaymsg "output * dpms on"' \ + before-sleep 'swaylock -f -c 000000' + ''; } + { command = "mako"; } + { command = "mpDris2"; } + { command = "protonmail-bridge --no-window"; } + ]; + + output = { + eDP-1 = { + bg = "~/usr/img/papes/desktop/5e497b8f7007061f.png fill"; + res = "1920x1080"; + pos = "1920 0"; + }; + HDMI-A-1 = { + bg = "~/usr/img/papes/desktop/0bb88c9800785d9b.jpg fill"; + res = "1920x1080"; + pos = "0 0"; + }; + }; + + # ACKSHUALLY, these are useless, but I'm putting them here anyway + modifier = "Mod4"; + terminal = "alacritty"; + menu = "berun"; # script + + # not doing mkOptionDefault because eh. too much is custom. + # execs are in PATH, so I shouldn't have to specify ${pkgs.package}... + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + term = config.wayland.windowManager.sway.config.terminal; + menu = config.wayland.windowManager.sway.config.menu; + in { + # laptop and media hotkeys + "XF86AudioRaiseVolume" = "exec volume up"; + "XF86AudioLowerVolume" = "exec volume down"; + "XF86AudioMute" = "exec volume mute"; + "XF86AudioMicMute" = "exec ponymix --source toggle"; + "XF86Tools" = "exec keyboard cycle"; + "XF86MonBrightnessUp" = "exec backlight up"; + "XF86MonBrightnessDown" = "exec backlight down"; + + "Shift+XF86AudioRaiseVolume" = "exec playerctl play-pause"; + "Shift+XF86AudioLowerVolume" = "exec playerctl next"; + + "Print" = "exec scrot sel"; + "Shift+Print" = "exec scrot full"; + "${modifier}+Print" = "exec scrot selup"; + "${modifier}+Shift+Print" = "exec scrot fullup"; + + # important + "${modifier}+Space" = "exec j4-dmenu-desktop --dmenu=${menu}"; + "${modifier}+Return" = "exec ${term}"; + "${modifier}+q" = "kill"; + "${modifier}+Shift+r" = "reload"; + + # jump around + "${modifier}+h" = "focus left"; + "${modifier}+j" = "focus down"; + "${modifier}+k" = "focus up"; + "${modifier}+l" = "focus right"; + + "${modifier}+Shift+h" = "move left"; + "${modifier}+Shift+j" = "move down"; + "${modifier}+Shift+k" = "move up"; + "${modifier}+Shift+l" = "move right"; + + # layouts + "${modifier}+b" = "splith"; + "${modifier}+v" = "splitv"; + "${modifier}+e" = "layout toggle split"; + "${modifier}+f" = "fullscreen"; + "${modifier}+Shift+f" = "floating toggle"; + "${modifier}+a" = "focus parent"; + "${modifier}+s" = "layout stacking"; + "${modifier}+w" = "layout tabbed"; + + # scratchpad + "${modifier}+Shift+backslash" = "move scratchpad"; + "${modifier}+backslash" = "scratchpad show"; + + # modes + "${modifier}+r" = ''mode "resize"''; + "${modifier}+semicolon" = ''mode "${launchMode}"''; + "${modifier}+Shift+semicolon" = ''mode "${systemMode}"''; + } // (builtins.foldl' (x: y: x // y) {} (map genWSBind workspaces)); + # ^ generate workspaces + + modes = { + "resize" = { + "h" = "resize shrink width 20px"; + "j" = "resize grow height 20px"; + "k" = "resize shrink height 20px"; + "l" = "resize grow width 20px"; + + "Return" = ''mode "default"''; + "Escape" = ''mode "default"''; + }; + + "${launchMode}" = { + "b" = ''exec firefox; mode "default"''; + "e" = ''exec emacsclient -c; mode "default"''; + "m" = ''exec alacritty -e ncmpcpp; mode "default"''; + "f" = ''exec pcmanfm; mode "default"''; + + "Return" = ''mode "default"''; + "Escape" = ''mode "default"''; + }; + + "${systemMode}" = { + "l" = ''exec swaylock -f -c 000000; mode "default";''; + "h" = "exec systemctl suspend"; + "r" = "exec systemctl reboot"; + "s" = "exec systemctl shutdown"; + "x" = "exit"; + "i" = "reload"; + + "Return" = ''mode "default"''; + "Escape" = ''mode "default"''; + }; + }; + + gaps = { + inner = 5; + smartBorders = "on"; + smartGaps = true; + }; + + fonts = [ "FiraCode 9" ]; + colors = { + focused = { + background = colors.hl; + text = colors.bg; + indicator = colors.hl; + border = colors.hl; + childBorder = colors.hl; + }; + focusedInactive = { + background = colors.bg; + text = colors.fg; + indicator = colors.blk; + border = colors.blk; + childBorder = colors.blk; + }; + # these are getting kind of long, huh... + unfocused = config.wayland.windowManager.sway.config.colors.focusedInactive; + urgent = { + background = colors.urg; + text = colors.blk; + indicator = colors.urg; + border = colors.urg; + childBorder = colors.urg; + }; + background = colors.hl; + }; + + bars = [{ + position = "top"; + fonts = [ "FontAwesome" "FiraCode 9" ]; + workspaceNumbers = false; + trayOutput = "none"; + statusCommand = "i3status-rs ~/etc/config/i3status-rust/status.toml"; + extraConfig = "height 20"; + + colors = { + separator = colors.fg; + background = colors.blk; + statusline = colors.fg; + focusedWorkspace = { + background = colors.hl; + text = colors.bg; + border = colors.hl; + }; + activeWorkspace = { + background = colors.bg; + text = colors.fg; + border = colors.bg; + }; + # ... + inactiveWorkspace = + (builtins.head config.wayland.windowManager.sway.config.bars).colors.activeWorkspace; + bindingMode = { + background = colors.blk; + text = colors.bg; + border = colors.blk; + }; + urgentWorkspace = { + background = colors.urg; + text = colors.bg; + border = colors.urg; + }; + }; + }]; + }; + + extraConfig = '' + seat * hide_cursor 1500 + ''; + }; + + home.packages = with pkgs; [ + swaylock # lockscreen + swayidle # locker + xwayland # xorg compatibility + + grim # screenshots + slurp # screenshot select + wl-clipboard # control c control v + + bemenu # app launcher + j4-dmenu-desktop # app launcher, for real + i3status-rust # bar + + jq # processing sway's data + ponymix # volume scripts + brightnessctl # take a wild guess + xorg.xrdb # xresources + xrq # for a script + ]; +} diff --git a/modules/desktop/zathura.nix b/modules/desktop/zathura.nix new file mode 100644 index 0000000..1e60248 --- /dev/null +++ b/modules/desktop/zathura.nix @@ -0,0 +1,7 @@ +{ config, lib, pkgs, ... }: +{ + programs.zathura = { + enable = true; + extraConfig = (builtins.readFile ../../config/zathura/zathurarc); + }; +} diff --git a/modules/lang/c.nix b/modules/lang/c.nix new file mode 100644 index 0000000..9cefdbb --- /dev/null +++ b/modules/lang/c.nix @@ -0,0 +1,10 @@ +{ config, lib, pkgs, ... }: +{ + home.packages = with pkgs; [ + clang + bear + gdb + cmake + llvmPackages.libcxx + ]; +} diff --git a/modules/lang/default.nix b/modules/lang/default.nix new file mode 100644 index 0000000..577ab8b --- /dev/null +++ b/modules/lang/default.nix @@ -0,0 +1,11 @@ +{ config, lib, pkgs, ... }: +{ + imports = [ + ./c.nix + ./lisp.nix + ./python.nix + ./rust.nix + ./scala.nix + ./tex.nix + ]; +} diff --git a/modules/lang/lisp.nix b/modules/lang/lisp.nix new file mode 100644 index 0000000..f973440 --- /dev/null +++ b/modules/lang/lisp.nix @@ -0,0 +1,12 @@ +{ config, lib, pkgs, ... }: +{ + home.packages = with pkgs; [ + # common lisp + sbcl # THIS IS A STRICTLY STEEL BANK HOUSEHOLD + lispPackages.quicklisp + rlwrap # for sbcl + + # the good shit + racket + ]; +} diff --git a/modules/lang/python.nix b/modules/lang/python.nix new file mode 100644 index 0000000..62d2db1 --- /dev/null +++ b/modules/lang/python.nix @@ -0,0 +1,14 @@ +{ config, lib, pkgs, ... }: +{ + home.packages = with pkgs; [ + python37 + python37Packages.pip + python37Packages.ipython + python37Packages.black + python37Packages.setuptools + python37Packages.pylint + python37Packages.poetry + python37Packages.pwntools + hazel.jupyterWithBatteries + ]; +} diff --git a/modules/lang/rust.nix b/modules/lang/rust.nix new file mode 100644 index 0000000..aa1fc05 --- /dev/null +++ b/modules/lang/rust.nix @@ -0,0 +1,7 @@ +{ config, lib, pkgs, ... }: +{ + home.packages = with pkgs; [ + rustup + hazel.crate2nix + ]; +} diff --git a/modules/lang/scala.nix b/modules/lang/scala.nix new file mode 100644 index 0000000..4c180ae --- /dev/null +++ b/modules/lang/scala.nix @@ -0,0 +1,11 @@ +{ config, lib, pkgs, ... }: +{ + home.packages = with pkgs; [ + scala + jdk + + sbt + coursier + metals + ]; +} diff --git a/modules/lang/tex.nix b/modules/lang/tex.nix new file mode 100644 index 0000000..e74b7bf --- /dev/null +++ b/modules/lang/tex.nix @@ -0,0 +1,11 @@ +{ config, lib, pkgs, ... }: +{ + home.packages = with pkgs; [ + texlive.combined.scheme-medium + ]; + + home.file.".latexmkrc".text = '' + $pdf_mode = 1; + $pdflatex = 'xelatex --shell-escape -interaction=nonstopmode %O %S -file-line-error -synctex=1'; + ''; +} diff --git a/modules/tools/bat.nix b/modules/tools/bat.nix new file mode 100644 index 0000000..ac03c59 --- /dev/null +++ b/modules/tools/bat.nix @@ -0,0 +1,8 @@ +{ config, lib, pkgs, ... }: +{ + xdg.configFile."bat/config".source = ../../config/bat/config; + + home.packages = with pkgs; [ + bat + ]; +} diff --git a/modules/tools/default.nix b/modules/tools/default.nix new file mode 100644 index 0000000..fd92cc9 --- /dev/null +++ b/modules/tools/default.nix @@ -0,0 +1,12 @@ +{ config, lib, pkgs, ... }: +{ + imports = [ + ./bat.nix + ./emacs.nix + ./git.nix + ./mail.nix + ./nix.nix + ./tmux.nix + ./zsh.nix + ]; +} diff --git a/modules/tools/emacs.nix b/modules/tools/emacs.nix new file mode 100644 index 0000000..7f834de --- /dev/null +++ b/modules/tools/emacs.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: +with import { + # grab the emacs overlay + overlays = [ + (import (builtins.fetchTarball { + url = "https://github.com/nix-community/emacs-overlay/archive/master.tar.gz"; + })) + ]; +}; + +{ + programs.emacs = { + enable = true; + extraPackages = epkgs: [ + epkgs.emacs-libvterm # doom vterm module + ]; + package = emacsUnstable; # emacs 27.0.91 + }; + + # run the emacs daemon + services.emacs.enable = true; + + home.packages = with pkgs; [ + (ripgrep.override { withPCRE2 = true; }) + gnutls + imagemagick + zstd + aspell + aspellDicts.en + aspellDicts.en-computers + aspellDicts.en-science + sqlite + ]; +} diff --git a/modules/tools/git.nix b/modules/tools/git.nix new file mode 100644 index 0000000..2d06533 --- /dev/null +++ b/modules/tools/git.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: +{ + programs.git = { + enable = true; + userName = "hazel levine"; + userEmail = "rose.hazel@protonmail.ch"; + extraConfig = { + credential = { + helper = "!bw-git-helper $@"; + useHttpPath = true; + }; + }; + }; + + xdg.configFile."bw-git-helper/config.ini".text = '' + [*github.com*] + target=7734c9e1-8174-4796-846b-feefe5f88d2c + + [*qtp2t.club*] + target=a268d28a-12f2-487e-8333-c3ddbd834e76 + + [config] + pinentry=pinentry-gtk-2 + ''; + + home.packages = with pkgs; [ + hazel.bw-git-helper + ]; +} diff --git a/modules/tools/mail.nix b/modules/tools/mail.nix new file mode 100644 index 0000000..dcdbc10 --- /dev/null +++ b/modules/tools/mail.nix @@ -0,0 +1,45 @@ +{ config, lib, pkgs, ... }: +{ + accounts.email = { + maildirBasePath = "var/mail"; + certificatesFile = /home/hazel/var/certs/protonmail_bridge.pem; + + accounts.protonmail = { + primary = true; + address = "me@qtp2t.club"; + # couldn't figure out how to use pass here. + # also storing my password in plaintext isn't really an issue when it only + # works if it's on my machine. + passwordCommand = "${pkgs.coreutils}/bin/cat /home/hazel/.config/mbsync-pass"; + userName = config.accounts.email.accounts.protonmail.address; + + imap = { + host = "127.0.0.1"; + port = 1143; + tls.enable = false; + }; + mbsync = { + enable = true; + create = "both"; + }; + + smtp = { + host = "127.0.0.1"; + port = 1025; + tls.useStartTls = true; + }; + }; + }; + + services.mbsync = { + enable = true; + frequency = "*-*-* *:0,30:00"; + }; + + programs.mbsync.enable = true; + + home.packages = with pkgs; [ + protonmail-bridge + unstable.mu + ]; +} diff --git a/modules/tools/nix.nix b/modules/tools/nix.nix new file mode 100644 index 0000000..9ae8f0c --- /dev/null +++ b/modules/tools/nix.nix @@ -0,0 +1,10 @@ +{ config, lib, pkgs, ... }: +{ + services.lorri.enable = true; + + programs.direnv.enable = true; + + home.packages = with pkgs; [ + niv + ]; +} diff --git a/modules/tools/passwords.nix b/modules/tools/passwords.nix new file mode 100644 index 0000000..4ac2c65 --- /dev/null +++ b/modules/tools/passwords.nix @@ -0,0 +1,13 @@ +{ config, lib, pkgs, ... }: +{ + # haha you thought + home.packages = with pkgs; [ + bitwarden-cli + pass-wayland + pinentry-gtk2 + + age + minisign + gnupg + ]; +} diff --git a/modules/tools/tmux.nix b/modules/tools/tmux.nix new file mode 100644 index 0000000..bbeb348 --- /dev/null +++ b/modules/tools/tmux.nix @@ -0,0 +1,6 @@ +{ config, lib, pkgs, ... }: +{ + programs.tmux = { + enable = true; + }; +} diff --git a/modules/tools/zsh.nix b/modules/tools/zsh.nix new file mode 100644 index 0000000..56bb0e5 --- /dev/null +++ b/modules/tools/zsh.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: +{ + programs.zsh = { + enable = true; + initExtra = (builtins.readFile ../../config/zsh/zshrc); + profileExtra = (builtins.readFile ../../config/zsh/zprofile); + }; + + programs.z-lua = { + enable = true; + enableAliases = true; + }; + + programs.skim = { + enable = true; + defaultCommand = "fd --type f"; + }; + + home.packages = with pkgs; [ + nix-zsh-completions + exa + fd + htop + tree + hazel.zr + ]; +} diff --git a/packages/bw-git-helper.nix b/packages/bw-git-helper.nix new file mode 100644 index 0000000..6505c73 --- /dev/null +++ b/packages/bw-git-helper.nix @@ -0,0 +1,29 @@ +{ pkgs, stdenv, buildGoModule, fetchFromGitHub }: +let + spdx = lic: lic // { + url = "https://spdx.org/licenses/${lic.spdxId}.html"; + }; +in +buildGoModule rec { + pname = "bw-git-helper"; + version = "unstable"; + + src = fetchFromGitHub { + owner = "tudurom"; + repo = pname; + rev = "d68a8db52a38061a0c9a60b3f29d81413d2e4425"; + sha256 = "1p7q3k1gfszm9k9sm4gp87464lh8l703w9jk0jrlrqhprj4wn1np"; + }; + + modSha256 = "1ck6bagvf9sjrp79lpx2w7v451ykn6hr3csm9zkqz1rqqd2z0smj"; + + buildInputs = with pkgs; [ bitwarden-cli ]; + + meta = with stdenv.lib; { + description = "A git credential helper using BitWarden as a backend"; + homepage = "https://github.com/tudurom/bw-git-helper"; + license = spdx { spdxId = "EUPL-1.2"; }; + maintainers = [ maintainers.hazel ]; + platforms = platforms.all; + }; +} diff --git a/packages/default.nix b/packages/default.nix new file mode 100644 index 0000000..19b8a9d --- /dev/null +++ b/packages/default.nix @@ -0,0 +1,32 @@ +[ + (self: super: with super; { + hazel = { + bw-git-helper = (callPackage ./bw-git-helper.nix {}); + crate2nix = + (callPackage + (builtins.fetchTarball + "https://github.com/kolloch/crate2nix/tarball/0.8.0") {}); + jupyterWithBatteries = super.jupyter.override { + definitions = { + python3 = let + env = (super.python3.withPackages(ps: with ps; [ + numpy + scipy + matplotlib + pandas + pwntools + ])); + in { + displayName = "Python 3"; + argv = []; + language = "python"; + logo32 = "${env.sitePackages}/ipykernel/resources/logo-32x32.png"; + logo64 = "${env.sitePackages}/ipykernel/resources/logo-64x64.png"; + }; + }; + }; + ncmpcppWithVisualizer = super.ncmpcpp.override { visualizerSupport = true; }; + zr = (callPackage ./zr.nix {}); + }; + }) +] diff --git a/packages/zr.nix b/packages/zr.nix new file mode 100644 index 0000000..47f0b20 --- /dev/null +++ b/packages/zr.nix @@ -0,0 +1,24 @@ +{ pkgs, stdenv, fetchFromGitHub, rustPlatform }: +rustPlatform.buildRustPackage rec { + pname = "zr"; + version = "0.9.0"; + + src = fetchFromGitHub { + owner = "jedahan"; + repo = pname; + rev = version; + sha256 = "15jcvasmm60mdhzrxw6dlbxjijh09n297h7wjbf3d3cdk4my2lgd"; + }; + + cargoSha256 = "0cp4gpikrr51hif14h4gdrrsxxcrpzl6mg7k5sz7lfpw8mq4f8kc"; + + buildInputs = with pkgs; [ pkgconfig openssl ]; + + meta = with stdenv.lib; { + description = "zsh plugin manager written in rust"; + homepage = "https://github.com/jedahan/zr/"; + license = licenses.mpl20; + maintainers = [ maintainers.hazel ]; + platforms = platforms.all; + }; +} diff --git a/system/configuration.nix b/system/configuration.nix new file mode 100644 index 0000000..f15d57a --- /dev/null +++ b/system/configuration.nix @@ -0,0 +1,68 @@ +{ config, pkgs, lib, ... }: +{ + imports = + [ + ./hardware-configuration.nix + ./desktop.nix + ./fonts.nix + ./networking.nix + ./power.nix + ]; + + # systemd-boot + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + # clear /tmp on reboot + boot.cleanTmpDir = true; + + # enable ZFS support + boot.supportedFilesystems = [ "zfs" ]; + services.zfs.trim.enable = true; + + # unfortunately, I live here + i18n.defaultLocale = "en_US.UTF-8"; + console = { + font = "Lat2-Terminus16"; + keyMap = "us"; + }; + + time.timeZone = "America/Indiana/Indianapolis"; + + nixpkgs.config.allowUnfree = true; # sorry, Stallman + + # the bare minimum + environment.systemPackages = with pkgs; [ + coreutils + git + killall + unzip + wget + vim + cryptsetup + gnumake + ripgrep + mesa + ]; + + # beep boop? boop beep. + sound.enable = true; + hardware.pulseaudio.enable = true; + + # the true keyboard layout + services.interception-tools.enable = true; + + # firm ware up daet + services.fwupd.enable = true; + + # unfortunately for everyone, it's me + users.users.hazel = { + isNormalUser = true; + uid = 1000; + extraGroups = [ "wheel" "audio" "video" "networkmanager" ]; + shell = pkgs.zsh; + }; + + system.stateVersion = "20.03"; +} + diff --git a/system/desktop.nix b/system/desktop.nix new file mode 100644 index 0000000..a6ec4f0 --- /dev/null +++ b/system/desktop.nix @@ -0,0 +1,19 @@ +{ config, pkgs, lib, ... }: +{ + # sway is managed by home-manager, BUT without this things break... + programs.sway.enable = true; + + # allow setting GTK themes via home-manager. also generally useful despite + # imo being mildly cursed + programs.dconf.enable = true; + + # without this, swaylock does not unlock + security.pam.services.swaylock = { + text = '' + auth include login + ''; + }; + + # idk + fonts.fontconfig.allowBitmaps = true; +} diff --git a/system/fan-control.nix b/system/fan-control.nix new file mode 100644 index 0000000..174d672 --- /dev/null +++ b/system/fan-control.nix @@ -0,0 +1,35 @@ +{ config, pkgs, lib, ... }: +{ + boot.extraModprobeConfig = '' + options thinkpad_acpi fan_control=1 experimental=1 + ''; + + + services.thinkfan = { + enable = true; + + sensors = '' + # Entries here discovered by: + # find /sys/devices -type f -name "temp*_input" + hwmon /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/temp6_input + hwmon /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/temp3_input + hwmon /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/temp7_input + hwmon /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/temp4_input + hwmon /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/temp1_input + hwmon /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/temp5_input + hwmon /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/temp2_input + hwmon /sys/devices/virtual/thermal/thermal_zone0/hwmon4/temp1_input + ''; + + levels = '' + (0, 0, 42) + (1, 40, 47) + (2, 45, 52) + (3, 50, 57) + (4, 55, 62) + (5, 60, 77) + (7, 73, 93) + (127, 85, 32767) + ''; + }; +} diff --git a/system/fonts.nix b/system/fonts.nix new file mode 100644 index 0000000..f50c783 --- /dev/null +++ b/system/fonts.nix @@ -0,0 +1,28 @@ +{ config, pkgs, lib, ... }: +let + basefonts = (with pkgs; [ + fira-code + corefonts + font-awesome_4 + source-sans-pro + ]); + + extrafonts = (with pkgs; [ + dejavu_fonts + noto-fonts + powerline-fonts + roboto + roboto-slab + source-code-pro + emacs-all-the-icons-fonts + ]); +in +{ + # rock 'n roll + # fonts.fonts = basefonts ++ []; + + fonts.fonts = + basefonts ++ + extrafonts ++ + []; +} diff --git a/system/hardware-configuration.nix b/system/hardware-configuration.nix new file mode 100644 index 0000000..00860a7 --- /dev/null +++ b/system/hardware-configuration.nix @@ -0,0 +1,34 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, ... }: + +{ + imports = + [ + ]; + + boot.initrd.availableKernelModules = [ "nvme" "ehci_pci" "xhci_pci" "rtsx_pci_sdmmc" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "rpool/root/nixos"; + fsType = "zfs"; + }; + + fileSystems."/home" = + { device = "rpool/home"; + fsType = "zfs"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/CCF8-E5E8"; + fsType = "vfat"; + }; + + swapDevices = [ ]; + + nix.maxJobs = lib.mkDefault 8; +} diff --git a/system/networking.nix b/system/networking.nix new file mode 100644 index 0000000..425cd80 --- /dev/null +++ b/system/networking.nix @@ -0,0 +1,41 @@ +{ config, pkgs, lib, ... }: +{ + # hostname and hostid (for zfs) + networking.hostName = "hyacinth"; + networking.hostId = "3ae0d799"; + + # it works I guess + networking.networkmanager.enable = true; + + networking.useDHCP = false; + networking.interfaces.enp3s0f0.useDHCP = true; + networking.interfaces.enp4s0.useDHCP = true; + networking.interfaces.wlp1s0.useDHCP = true; + + # wireguard vpn + networking.wireguard.interfaces = { + wg0 = { + # client ip + ips = [ "10.66.66.2/24" "fd42:42:42::2/64" ]; + + privateKeyFile = "/etc/nixos/wg-privkey"; # go away + + peers = [ + { + # server's public key + publicKey = "uPBpljWQp7cuKZ5sOiksuhf+sR/v/mdIjLA00Vluc2Q="; + + # server IP, and forward all traffic through VPN + allowedIPs = [ "10.66.66.1/32" "fd42:42:42::1/128" + "0.0.0.0/0" "::/0" ]; + + # the server + endpoint = "45.79.140.85:51820"; + + # keep the NAT alive + persistentKeepalive = 25; + } + ]; + }; + }; +} diff --git a/system/power.nix b/system/power.nix new file mode 100644 index 0000000..4defed8 --- /dev/null +++ b/system/power.nix @@ -0,0 +1,33 @@ +{ config, pkgs, lib, ... }: +{ + # fan control modules + boot.extraModprobeConfig = '' + options thinkpad_acpi fan_control=1 experimental=1 + ''; + + # thinkfan fan controller + services.thinkfan = { + enable = true; + + # i don't know what these mean but only the first one works + sensors = '' + tp_thermal /proc/acpi/ibm/thermal (0, 0, 0, 0, 0, 0, 0, 0) + ''; + + levels = '' + (0, 0, 42) + (1, 40, 47) + (2, 45, 52) + (3, 50, 57) + (4, 55, 62) + (5, 60, 77) + (7, 73, 93) + (127, 85, 32767) + ''; + }; + + # battery optimizations + services.tlp.enable = true; + powerManagement.powertop.enable = true; + services.upower.enable = true; +}