commit
0f1a3535a4
70 changed files with 4356 additions and 0 deletions
@ -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/* |
@ -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. |
|||
|
|||
 |
@ -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 <http://unlicense.org/> |
@ -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 |
@ -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~" } |
@ -0,0 +1,2 @@ |
|||
--theme="ansi-dark" |
|||
--style="numbers,changes,header" |
@ -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 |
@ -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" |
@ -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 |
@ -0,0 +1,3 @@ |
|||
#!/bin/sh |
|||
|
|||
emacsclient -c --socket-name hazel-emacsd $@ |
@ -0,0 +1,14 @@ |
|||
#!/bin/sh |
|||
|
|||
if [ -z "$@" ]; then |
|||
echo "usage: import-gsettings <gsettings key>:<settings.ini key> <gsettings key>:<settings.ini key> ..." |
|||
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 |
@ -0,0 +1,64 @@ |
|||
#!/usr/bin/env bash |
|||
# |
|||
# Control keyboard layout and backlight (Lenovo ThinkPad tested only) |
|||
# |
|||
# Author: Dave Eddy <dave@daveeddy.com> |
|||
# 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 <command> |
|||
|
|||
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 |
@ -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 |
@ -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 <http://www.gnu.org/licenses/>. |
|||
|
|||
# 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 <<EOF |
|||
Usage: |
|||
notify-send.sh [OPTION...] <SUMMARY> [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 |
@ -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 |
@ -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 |
@ -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 |
@ -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")) |
|||
|
|||
<<static>> |
|||
<<rss>> |
|||
<<html1>> |
|||
<<html2>> |
|||
<<html3>> |
|||
|
|||
: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 |
@ -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 </dev/null | \ |
|||
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > 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 |
@ -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)) |
After Width: | Height: | Size: 91 KiB |
@ -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; |
|||
} |
|||
|
|||