commit 0f1a3535a44ec35461bc1c56f8e497d36e8aec32 Author: hazel levine Date: Mon Jun 1 10:44:54 2020 -0400 init 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 0000000..3f12e3f Binary files /dev/null and b/config/doom/nice.png differ diff --git a/config/firefox/userChrome.css b/config/firefox/userChrome.css new file mode 100644 index 0000000..4bb4fc3 --- /dev/null +++ b/config/firefox/userChrome.css @@ -0,0 +1,948 @@ +/* + +Quietfox for Firefox 76 + +https://github.com/coekuss/quietfox + +Thanks for using my file + + */ + +* { +/* -------------------- 🎨 Customization 🎨 -------------------- */ + --tab-corner-rounding: 5px; + --button-corner-rounding: 4px; + --menu-corner-rounding: 5px; + --menu-item-height: 30px; + --animation-speed: 0.15s; +} + + +@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); + +/* Bottom corner rounding for tabs, Remove this section if your tab bottom corners look bad */ +tab[visuallyselected] .tab-background::before, +tab[visuallyselected] .tab-background::after { + content: "" !important; + display: inline !important; + position: absolute !important; + width: var(--tab-corner-rounding) !important; + height: var(--tab-corner-rounding) !important; + bottom: -1px !important; + pointer-events: none !important; + background-color: transparent !important; + transition: var(--animation-speed) !important; +} + +tab[visuallyselected] .tab-background::before { + border-bottom-right-radius: var(--tab-corner-rounding) !important; + transform: translateX(calc(-1 * var(--tab-corner-rounding))) !important; + box-shadow: 4px 4px 0px 4px var(--toolbar-bgcolor) !important; + transition: var(--animation-speed) !important; +} + +tab[visuallyselected] .tab-background::after { + border-bottom-left-radius: var(--tab-corner-rounding) !important; + right: 0px !important; + transform: translateX(calc(var(--tab-corner-rounding) + 1px)) !important; + box-shadow: -4px 4px 0px 4px var(--toolbar-bgcolor) !important; + transition: var(--animation-speed) !important; +} +/* --------------------------------------------------------------------------------------- */ + + + + +/* This makes certain menus adapt to your toolbar text color. Can make menu text illegible in +some transparent themes, remove if needed. */ +panelview:not([extension]), +.panel-arrowcontent { + background-color: var(--toolbar-bgcolor) !important; + color: var(--toolbar-color) !important; +} +/*-------------------------------------------------------------------*/ + + + + + +/* -------------------- Transitions for some things -------------------- */ +toolbarbutton, +.subviewbutton, +stack, +.toolbarbutton-icon, +vbox +{ + transition: background-color var(--animation-speed) !important; + +} + + + + +/* -------------------- Style tab bar -------------------- */ + +.titlebar-spacer[type="pre-tabs"] { + border-inline-end: 0px !important; + width: 0px !important; +} + +scrollbox[part="scrollbox"][flex="1"][orient="horizontal"] { + padding-left: 12px !important; +} + + +[sizemode="maximized"] [first-visible-tab] { + margin-left: -12px !important; +} + +[sizemode="maximized"] [first-visible-tab] stack { + margin-left: 12px !important; +} + +.tab-background, .tab-loading-burst { + border-radius: var(--tab-corner-rounding) var(--tab-corner-rounding) 0px 0px !important; + margin: -1px !important; + +} + +tab:not(:active) .tab-background { + transition: background-color var(--animation-speed) !important; +} + + +:root[uidensity="compact"] { + --tab-min-height: 31px !important; +} + +tab:not([selected]):hover .tab-background { + background-color: var(--toolbarbutton-hover-background) !important; +} + +tab { + min-width: 1px !important; + clip-width: 1px !important; + padding-bottom: 1px !important; +} + +.tab-line { + display: none !important; +} + +tab:not([beforeselected-visible])::after { + margin-top: 4px !important; + margin-bottom: 4px !important; + transition: border-color var(--animation-speed), margin-top var(--animation-speed) !important; + +} + +tab[beforehovered]::after, +tab:hover::after { + border-color: transparent !important; + margin-top: 20px !important; +} + +#navigator-toolbox { + --tabs-border-color: transparent !important; +} + + + +tab[visuallyselected] .tab-background { + box-shadow: 0px 3px 12px -5px black !important; +} + +[last-visible-tab] { + margin-right: calc(var(--tab-corner-rounding) + 2px) !important; /* fix unexpected tab overflow */ +} + + + + +/* -------------------- Style toolbar -------------------- */ +.toolbarbutton-icon, .toolbarbutton-badge-stack { + background-color: transparent !important; +} + +toolbarbutton:not(#back-button)[open], .toolbarbutton-1:not(#back-button)[open] { + background-color: var(--toolbarbutton-active-background); +} + +#nav-bar .toolbarbutton-1 { + margin-right: 2px !important; +} + +.close-icon:not(.tab-close-button):hover { + fill-opacity: 0.0 !important; +} + +toolbarbutton:not(#back-button):not([disabled]):not([open]):hover, +.toolbarbutton-1:not(#back-button):not([disabled]):not([open]):hover { + background-color: var(--toolbarbutton-hover-background) !important; +} + +.tab-close-button { + transition: fill-opacity var(--animation-speed) !important; +} + +.findbar-textbox:focus { + border: 1px solid grey !important; +} + +#BMB_bookmarksShowAll { + display: none !important; +} + + + +/* touch and normal density buttons */ + +:root:not([uidensity="compact"]) #back-button > .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; +}