initial commit

This commit is contained in:
Barrett Ruth 2026-02-07 00:45:47 -05:00
commit 23d4795228
99 changed files with 6691 additions and 0 deletions

94
scripts/ctl Executable file
View file

@ -0,0 +1,94 @@
#!/bin/sh
case "$1" in
screenshot)
dir="$HOME/img/ss"
mkdir -p "$dir"
file="$dir/$(openssl rand -hex 10)-$(date +'%Y-%m-%d_%H-%M-%S').png"
if [ "${XDG_SESSION_TYPE:-}" = "wayland" ]; then
grim -g "$(slurp)" "$file" && wl-copy < "$file"
else
maim -s "$file" && xclip -selection clipboard -t image/png -i "$file" &
fi
;;
ocr)
dir="$HOME/img/ss"
mkdir -p "$dir"
file="$dir/$(openssl rand -hex 10)-$(date +'%Y-%m-%d_%H-%M-%S').png"
if [ "${XDG_SESSION_TYPE:-}" = "wayland" ]; then
(
region="$(slurp)"
[ -n "$region" ] || exit 0
grim -g "$region" "$file" &&
tesseract -l eng "$file" - 2>/dev/null | wl-copy
) </dev/null >/dev/null 2>&1 &
else
(
maim -s "$file" &&
tesseract -l eng "$file" - 2>/dev/null | xclip -selection clipboard -in
) </dev/null >/dev/null 2>&1 &
fi
;;
keyboard)
case "$2" in
toggle)
if [ "${XDG_SESSION_TYPE:-}" = "wayland" ]; then
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
hyprctl switchxkblayout current next
elif [ "$XDG_CURRENT_DESKTOP" = "sway" ]; then
if swaymsg -t get_inputs | grep -qi "Colemak"; then
swaymsg input type:keyboard xkb_variant "''"
else
swaymsg input type:keyboard xkb_variant colemak
fi
fi
else
current="$(setxkbmap -query | awk '/variant/{print $2}')"
if [ "$current" = "colemak" ]; then
setxkbmap -layout us
else
setxkbmap -layout us -variant colemak
fi
fi
;;
*)
echo "Usage: ctl keyboard {toggle}" >&2
exit 1
;;
esac
;;
audio)
case "$2" in
out)
sinks="$(pactl list short sinks | awk '{print $1": "$2}')"
[ -z "$sinks" ] && exit 0
count="$(printf "%s\n" "$sinks" | wc -l)"
if [ "$XDG_SESSION_TYPE" = x11 ]; then
choice="$(printf "%s\n" "$sinks" | dmenu -i -l "$count" -p "select sink:" | cut -d: -f1)"
else
choice="$(printf "%s\n" "$sinks" | rofi -dmenu -i -lines "$count" -p "select sink" | cut -d: -f1)"
fi
[ "$choice" ] && pactl set-default-sink "$choice"
;;
in)
sources="$(pactl list short sources | awk '{print $1": "$2}')"
[ -z "$sources" ] && exit 0
count="$(printf "%s\n" "$sources" | wc -l)"
if [ "$XDG_SESSION_TYPE" = x11 ]; then
choice="$(printf "%s\n" "$sources" | dmenu -i -l "$count" -p "select source:" | cut -d: -f1)"
else
choice="$(printf "%s\n" "$sources" | rofi -dmenu -i -lines "$count" -p "select source" | cut -d: -f1)"
fi
[ "$choice" ] && pactl set-default-source "$choice"
;;
*)
echo "Usage: ctl audio {in|out}" >&2
exit 1
;;
esac
;;
*)
echo "Usage: ctl {screenshot|ocr|keyboard|audio}" >&2
exit 1
;;
esac

23
scripts/doc Executable file
View file

@ -0,0 +1,23 @@
#!/bin/sh
dir="$HOME/doc"
test -d "$dir" || exit
if [ "$XDG_SESSION_TYPE" = x11 ]; then
picker() { dmenu -i -l 10 -p "Select file or folder: "; }
else
picker() { rofi -dmenu -i -l 10 -p "Select file or folder"; }
fi
while :; do
choice="$(find "$dir" -not -path "$dir/.*" -mindepth 1 -maxdepth 1 \( -type d -printf "%f/\n" -o -type f -printf "%f\n" \) | picker)"
[ -n "$choice" ] || break
if [ -d "$dir/${choice%/}" ]; then
dir="$dir/${choice%/}"
elif [ -f "$dir/$choice" ]; then
sioyek "$dir/$choice" &
break
fi
done

283
scripts/hypr Executable file
View file

@ -0,0 +1,283 @@
#!/bin/sh
usage() {
cat <<EOF
Usage: hypr <subcommand> [app] [args...]
Commands:
volume {up,down,toggle} Adjust volume accordingly and notify
brightness {up,down} Adjust brightness accordingly and notify
spawnfocus <app> [args...] Focus existing window or spawn app with args
pull [app] Pull window to current workspace (picker if no app)
borders Initialize dynamic borders
exit Safely exit hyprland
Options:
-h, --help Show this help message
EOF
}
[ -z "$1" ] && {
usage
exit 1
}
cmd="$1"
shift
case "$cmd" in
-h | --help)
usage
exit 0
;;
exit)
pkill hypridle
pkill hyprpaper
hyprctl dispatch exit
exit 0
;;
brightness)
BRIGHT_STEP=5
max_brightness="$(brightnessctl max)"
case "$1" in
up)
brightnessctl set "$BRIGHT_STEP"%+
notify-send -u low -t 2500 -r 5555 "brightness $(brightnessctl get | awk -v max="$max_brightness" '{printf "%d%%", $1*100/max}')"
;;
down)
brightnessctl set "$BRIGHT_STEP"%-
notify-send -u low -t 2500 -r 5555 "brightness $(brightnessctl get | awk -v max="$max_brightness" '{printf "%d%%", $1*100/max}')"
;;
*)
echo "Invalid subcommand: $1" >&2
exit 1
;;
esac
;;
volume)
SINK="@DEFAULT_SINK@"
VOL_STEP=5
get_vol() { pactl get-sink-volume "$SINK" | awk 'NR==1{print $5+0}'; }
case "$1" in
up)
vol=$(get_vol)
[ "$vol" -lt 100 ] && vol=$((vol + VOL_STEP))
[ "$vol" -gt 100 ] && vol=100
pactl set-sink-volume "$SINK" "${vol}%"
;;
down)
vol=$(get_vol)
vol=$((vol - VOL_STEP))
[ "$vol" -lt 0 ] && vol=0
pactl set-sink-volume "$SINK" "${vol}%"
;;
toggle)
pactl set-sink-mute "$SINK" toggle
;;
*)
echo "Invalid subcommand: $1" >&2
exit 1
;;
esac
muted=$(pactl get-sink-mute "$SINK" | awk '{print $2}')
vol=$(get_vol)
[ "$vol" -gt 100 ] && vol=100
if [ "$muted" = "yes" ]; then
notify-send -u low -t 2500 -r 5556 "volume: ${vol}% (muted)"
else
notify-send -u low -t 2500 -r 5556 "volume: ${vol}%"
fi
;;
pull)
APP="$1"
if [ -n "$APP" ]; then
case "$APP" in
google-chrome | google-chrome-stable) CLASS="google-chrome" ;;
chromium | ungoogled-chromium) CLASS="Chromium" ;;
firefox) CLASS="firefox" ;;
alacritty) CLASS="Alacritty" ;;
code | vscodium) CLASS="Code" ;;
signal-desktop | signal) CLASS="signal" ;;
telegram-desktop | telegram) CLASS="TelegramDesktop" ;;
ghostty) CLASS="com.mitchellh.ghostty" ;;
bitwarden-desktop | bitwarden) CLASS="Bitwarden" ;;
slack) CLASS="Slack" ;;
discord) CLASS="discord" ;;
vesktop) CLASS="vesktop" ;;
*) CLASS="$APP" ;;
esac
CUR_ADDR=$(hyprctl -j activewindow | jq -r '.address')
WIN_ADDRS=$(
hyprctl -j clients 2>/dev/null | jq -r --arg class "$CLASS" '
.[]? | select(
((.xdgTag // "") | ascii_downcase | contains($class | ascii_downcase)) or
((.initialClass // "") | ascii_downcase | contains($class | ascii_downcase)) or
((.class // "") | ascii_downcase | contains($class | ascii_downcase))
) | "\(.class)\t\(.title)\t\(.address)"'
)
WIN_COUNT=$(echo "$WIN_ADDRS" | grep -c .)
if [ "$WIN_COUNT" -eq 1 ]; then
WIN_ADDR=$(echo "$WIN_ADDRS" | awk -F'\t' '{print $3}')
elif [ "$WIN_COUNT" -gt 1 ]; then
SELECTED=$(echo "$WIN_ADDRS" |
awk -F'\t' -v cur="$CUR_ADDR" '{if($3!=cur) print $1 ": " $2 "\t" $3}' |
rofi -dmenu -i -p "pull window")
WIN_ADDR=$(echo "$SELECTED" | awk -F'\t' '{print $2}')
fi
fi
if [ -z "$SELECTED" ]; then
exit 0
fi
if [ -z "$WIN_ADDR" ]; then
CUR_ADDR=$(hyprctl -j activewindow | jq -r '.address')
WIN_ADDRS=$(hyprctl -j clients 2>/dev/null | jq -r '.[]? | "\(.class)\t\(.title)\t\(.address)"')
SELECTED=$(echo "$WIN_ADDRS" |
awk -F'\t' -v cur="$CUR_ADDR" '{if($3!=cur) print $1 ": " $2 "\t" $3}' |
rofi -dmenu -i -p "pull window")
WIN_ADDR=$(echo "$SELECTED" | awk -F'\t' '{print $2}')
fi
if [ -n "$WIN_ADDR" ]; then
CURRENT_WS="$(hyprctl activeworkspace | head -n1 | awk -F'[()]' '{print $2}')"
hyprctl dispatch movetoworkspace "$CURRENT_WS,address:$WIN_ADDR"
hyprctl dispatch focuswindow "address:$WIN_ADDR"
fi
;;
spawnfocus)
WS=""
while [ $# -gt 0 ]; do
case "$1" in
--ws)
if [ $# -lt 2 ]; then
echo "Missing workspace number after --ws"
exit 1
fi
WS="$2"
shift 2
;;
-*)
echo "Unknown option $1"
exit 1
;;
*)
break
;;
esac
done
APP="$1"
[ -z "$APP" ] && {
echo 'Specify an app'
exit 1
}
shift
case "$APP" in
google-chrome | google-chrome-stable) CLASS="google-chrome" ;;
chromium | ungoogled-chromium) CLASS="Chromium" ;;
firefox) CLASS="firefox" ;;
alacritty) CLASS="Alacritty" ;;
code | vscodium) CLASS="Code" ;;
signal-desktop | signal) CLASS="signal" ;;
telegram-desktop | telegram) CLASS="TelegramDesktop" ;;
ghostty) CLASS="com.mitchellh.ghostty" ;;
bitwarden-desktop | bitwarden) CLASS="Bitwarden" ;;
slack) CLASS="Slack" ;;
discord) CLASS="discord" ;;
vesktop) CLASS="vesktop" ;;
*) CLASS="$APP" ;;
esac
WIN_ADDRS=$(hyprctl -j clients 2>/dev/null | jq -r --arg class "$CLASS" '
.[]? | select(
((.xdgTag // "") | ascii_downcase | contains($class | ascii_downcase)) or
((.initialClass // "") | ascii_downcase | contains($class | ascii_downcase)) or
((.class // "") | ascii_downcase | contains($class | ascii_downcase))
) | "\(.class)\t\(.title)\t\(.address)"
')
WIN_COUNT=$(echo "$WIN_ADDRS" | grep -c .)
if [ "$WIN_COUNT" -eq 0 ]; then
WIN_ADDR=""
elif [ "$WIN_COUNT" -eq 1 ]; then
WIN_ADDR=$(echo "$WIN_ADDRS" | awk -F'\t' '{print $3}')
elif [ "$WIN_COUNT" -gt 1 ]; then
SELECTED=$(echo "$WIN_ADDRS" | awk -F'\t' '{print $1 ": " $2 "\t" $3}' | rofi -dmenu -i -p "select window")
if [ -z "$SELECTED" ]; then
exit 0
fi
WIN_ADDR=$(echo "$SELECTED" | awk -F'\t' '{print $2}')
fi
if [ -n "$WIN_ADDR" ]; then
if [ -n "$WS" ]; then
WIN_WS=$(hyprctl clients -j | jq -r --arg addr "$WIN_ADDR" '.[] | select(.address == $addr) | .workspace.id')
if [ "$WIN_WS" != "$WS" ]; then
hyprctl dispatch movetoworkspacesilent "$WS,address:$WIN_ADDR"
fi
hyprctl dispatch workspace "$WS"
else
WIN_WS=$(hyprctl clients -j | jq -r --arg addr "$WIN_ADDR" '.[] | select(.address == $addr) | .workspace.id')
hyprctl dispatch workspace "$WIN_WS"
fi
hyprctl dispatch focuswindow "address:$WIN_ADDR"
else
EXISTING_HEX=$(hyprctl -j clients 2>/dev/null | jq -r --arg class "$CLASS" '
.[]? | select(
((.xdgTag // "") | ascii_downcase | contains($class | ascii_downcase)) or
((.initialClass // "") | ascii_downcase | contains($class | ascii_downcase)) or
((.class // "") | ascii_downcase | contains($class | ascii_downcase))
) | .address | ltrimstr("0x")
' | tr '\n' ' ')
if [ -n "$WS" ]; then
hyprctl dispatch workspace "$WS"
fi
if [ $# -eq 0 ]; then
"$APP" &
else
"$APP" "$@" &
fi
socat -u UNIX-CONNECT:"$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" - | while read -r line; do
case "$line" in
openwindow*)
window_id=$(echo "$line" | cut -d'>' -f3 | cut -d',' -f1)
event_class=$(echo "$line" | cut -d'>' -f3 | cut -d',' -f3)
class_lower=$(echo "$event_class" | tr '[:upper:]' '[:lower:]')
target_lower=$(echo "$CLASS" | tr '[:upper:]' '[:lower:]')
case "$class_lower" in
*"$target_lower"*)
case " $EXISTING_HEX " in
*" $window_id "*) ;;
*)
addr="0x$window_id"
if [ -n "$WS" ]; then
hyprctl dispatch movetoworkspacesilent "$WS,address:$addr"
fi
hyprctl dispatch focuswindow "address:$addr"
break
;;
esac
;;
esac
;;
esac
done
fi
;;
*)
echo "Unknown subcommand: $cmd"
usage
exit 1
;;
esac

118
scripts/mux Executable file
View file

@ -0,0 +1,118 @@
#!/bin/sh
spawn_or_focus() {
name="$1"
cmd="$2"
if tmux list-windows -F '#{window_name}' | grep -Fx "$name" >/dev/null; then
tmux select-window -t "${name}"
else
if [ -n "$cmd" ]; then
tmux new-window -c '#{pane_current_path}' -n "${name}" "$cmd"
else
tmux new-window -c '#{pane_current_path}' -n "${name}"
fi
fi
}
case "$1" in
bar)
[ "$2" ] || exit
mouse=""
if [ "$(tmux show-options | grep mouse | awk '{ print $NF }')" = "on" ]; then
mouse='[m]'
fi
set -f
keys="H J K L"
bar_content=""
i=0
total=$(tmux ls -F x | wc -l)
for line in $(tmux ls -F '#{session_id}:#{session_name}'); do
sid="${line%%:*}"
sname="${line#*:}"
if [ $i -lt 4 ]; then
key=$(echo "$keys" | cut -d' ' -f $((i + 1)))
elif [ $i -eq $((total - 1)) ]; then
key='$'
else
key='?'
fi
star=""
[ "$sname" = "$2" ] && star="*"
bar_content="$bar_content#[range=session|${sid}]$key:$sname$star#[norange] "
i=$((i + 1))
done
set +f
left='#[align=left list=on] #{W:#[range=window|#{window_index}]#{window_index}:#{window_name}#{window_flags}#[norange] }#[nolist]'
right="#[align=right]$mouse $bar_content"
tmux set -g 'status-format[0]' "$left$right"
;;
switch)
session="$(tmux ls -F '#S' | tail -n "+$(($2 + 1))" | head -1)"
tmux switch -t "$session"
;;
exec)
name="$(basename "$PWD")"
project="$(basename "$(dirname "$PWD")")/$name"
case "$project" in
*/bmath)
cmd='cmake -B build -DCMAKE_BUILD_TYPE=Debug && cmake --build build && ctest --test-dir build --output-on-failure'
;;
*/ag)
cmd='cp -f autograder.py example && cd example && ./run_autograder'
;;
*/project-a-10)
cmd='. venv/bin/activate && python manage.py runserver'
;;
*/theCourseForum2)
cmd='docker compose up'
;;
*/atlas | */tinyground)
cmd='pnpm run dev'
;;
*/interview-prep)
cmd='pnpm run dev'
;;
*/neovim)
cmd='make'
;;
*/TestCppClient)
cmd='rm -f TestCppClientStatic && cmake -S . -B build/ && make && ./TestCppClientStatic'
;;
sl/*)
cmd='make clean install && make clean'
[ "$name" = 'slock' ] && cmd="doas $cmd"
;;
*/barrettruth.com)
cmd='pnpm dev'
;;
esac
echo " > $cmd" | sed "s|$HOME|~|g"
eval "$cmd"
;;
claude)
spawn_or_focus claude 'claude --chrome'
;;
nvim)
spawn_or_focus nvim 'nvim -c "lua require([[config.tmux]]).run([[nvim]])"'
;;
git)
pane_path=$(tmux display-message -p '#{pane_current_path}')
if ! git -C "$pane_path" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
tmux display-message "Not a git repository"
else
spawn_or_focus git 'nvim -c "lua require([[config.tmux]]).run([[git]])"'
fi
;;
run)
spawn_or_focus run 'nvim -c "lua require([[config.tmux]]).run([[run]])"'
;;
term)
spawn_or_focus term
;;
*)
tmux attach
;;
esac

227
scripts/pipes Executable file
View file

@ -0,0 +1,227 @@
#!/usr/bin/env bash
# pipes.sh: Animated pipes terminal screensaver.
# https://github.com/pipeseroni/pipes.sh
#
# Copyright (c) 2015-2018 Pipeseroni/pipes.sh contributors
# Copyright (c) 2013-2015 Yu-Jie Lin
# Copyright (c) 2010 Matthew Simpson
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# 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 OR COPYRIGHT HOLDERS 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.
VERSION=1.3.0
M=32768 # Bash RANDOM maximum + 1
p=1 # number of pipes
f=75 # frame rate
s=13 # probability of straight fitting
r=2000 # characters limit
t=0 # iteration counter for -r character limit
w=80 # terminal size
h=24
# ab -> sets[][idx] = a*4 + b
# 0: up, 1: right, 2: down, 3: left
# 00 means going up , then going up -> ┃
# 12 means going right, then going down -> ┓
sets=(
"┃┏ ┓┛━┓ ┗┃┛┗ ┏━"
"│╭ ╮╯─╮ ╰│╯╰ ╭─"
"│┌ ┐┘─┐ └│┘└ ┌─"
"║╔ ╗╝═╗ ╚║╝╚ ╔═"
"|+ ++-+ +|++ +-"
"|/ \/-\ \|/\ /-"
".. .... .... .."
".o oo.o o.oo o."
"-\ /\|/ /-\/ \|"
"╿┍ ┑┚╼┒ ┕╽┙┖ ┎╾"
"████▀▀███▀█▀▀██▀"
)
# pipes'
x=() # current position
y=()
l=() # current directions
# 0: up, 1: right, 2: down, 3: left
n=() # new directions
v=() # current types
c=() # current color
# selected pipes'
V=() # types (indexes to sets[])
C=() # colors
VN=0 # number of selected types
CN=0 # number of selected colors
# switches
RNDSTART=0 # randomize starting position and direction
BOLD=1
NOCOLOR=0
KEEPCT=0 # keep pipe color and type
parse() {
OPTIND=1
while getopts "p:t:c:f:s:r:RBCKhv" arg; do
case $arg in
p) ((p = (OPTARG > 0) ? OPTARG : p));;
t)
if [[ "$OPTARG" = c???????????????? ]]; then
V+=(${#sets[@]})
sets+=("${OPTARG:1}")
else
((OPTARG >= 0 && OPTARG < ${#sets[@]})) && V+=($OPTARG)
fi
;;
c) [[ $OPTARG =~ ^[0-7]$ ]] && C+=($OPTARG);;
f) ((f = (OPTARG > 19 && OPTARG < 101) ? OPTARG : f));;
s) ((s = (OPTARG > 4 && OPTARG < 16) ? OPTARG : s));;
r) ((r = (OPTARG >= 0) ? OPTARG : r));;
R) RNDSTART=1;;
B) BOLD=0;;
C) NOCOLOR=1;;
K) KEEPCT=1;;
h) echo -e "Usage: $(basename $0) [OPTION]..."
echo -e "Animated pipes terminal screensaver.\n"
echo -e " -p [1-]\tnumber of pipes (D=1)."
echo -e " -t [0-$((${#sets[@]} - 1))]\ttype of pipes, can be used more than once (D=0)."
echo -e " -c [0-7]\tcolor of pipes, can be used more than once (D=1 2 3 4 5 6 7 0)."
echo -e " -t c[16 chars]\tcustom type of pipes."
echo -e " -f [20-100]\tframerate (D=75)."
echo -e " -s [5-15]\tprobability of a straight fitting (D=13)."
echo -e " -r LIMIT\treset after x characters, 0 if no limit (D=2000)."
echo -e " -R \t\trandomize starting position and direction."
echo -e " -B \t\tno bold effect."
echo -e " -C \t\tno color."
echo -e " -K \t\tpipes keep their color and type when hitting the screen edge."
echo -e " -h\t\thelp (this screen)."
echo -e " -v\t\tprint version number.\n"
exit 0;;
v) echo "$(basename -- "$0") $VERSION"
exit 0
esac
done
# set default values if not by options
((${#V[@]})) || V=(0)
VN=${#V[@]}
((${#C[@]})) || C=(1 2 3 4 5 6 7 0)
CN=${#C[@]}
}
cleanup() {
# clear out standard input
read -t 0.001 && cat </dev/stdin>/dev/null
# terminal has no smcup and rmcup capabilities
((FORCE_RESET)) && reset && exit 0
tput reset # fix for konsole, see pipeseroni/pipes.sh#43
tput rmcup
tput cnorm
# stty echo
((NOCOLOR)) && echo -ne '\e[0m'
exit 0
}
resize() {
w=$(tput cols) h=$(tput lines)
}
init() {
local i
resize
trap resize SIGWINCH
ci=$((KEEPCT ? 0 : CN * RANDOM / M))
vi=$((KEEPCT ? 0 : VN * RANDOM / M))
for ((i = 0; i < p; i++)); {((
n[i] = 0,
l[i] = RNDSTART ? RANDOM % 4 : 0,
x[i] = RNDSTART ? w * RANDOM / M : w / 2,
y[i] = RNDSTART ? h * RANDOM / M : h / 2,
c[i] = C[ci],
v[i] = V[vi],
ci = (ci + 1) % CN,
vi = (vi + 1) % VN
));}
# stty -echo
tput smcup || FORCE_RESET=1
tput civis
tput clear
trap cleanup HUP TERM
}
main() {
local i
parse "$@"
init "$@"
# any key press exits the loop and this script
trap 'break 2' INT
while REPLY=; do
read -t 0.0$((1000 / f)) -n 1 2>/dev/null
case "$REPLY" in
P) ((s = s < 15 ? s + 1 : s));;
O) ((s = s > 3 ? s - 1 : s));;
F) ((f = f < 100 ? f + 1 : f));;
D) ((f = f > 20 ? f - 1 : f));;
B) ((BOLD = (BOLD + 1) % 2));;
C) ((NOCOLOR = (NOCOLOR + 1) % 2));;
K) ((KEEPCT = (KEEPCT + 1) % 2));;
?) break;;
esac
for ((i = 0; i < p; i++)); do
# New position:
# l[] direction = 0: up, 1: right, 2: down, 3: left
((l[i] % 2)) && ((x[i] += -l[i] + 2, 1)) || ((y[i] += l[i] - 1))
# Loop on edges (change color on loop):
((!KEEPCT && (x[i] >= w || x[i] < 0 || y[i] >= h || y[i] < 0))) \
&& ((c[i] = C[CN * RANDOM / M], v[i] = V[VN * RANDOM / M]))
((x[i] = (x[i] + w) % w))
((y[i] = (y[i] + h) % h))
# New random direction:
((n[i] = s * RANDOM / M - 1))
((n[i] = (n[i] > 1 || n[i] == 0) ? l[i] : l[i] + n[i]))
((n[i] = (n[i] < 0) ? 3 : n[i] % 4))
# Print:
tput cup ${y[i]} ${x[i]}
echo -ne "\e[${BOLD}m"
((NOCOLOR)) && echo -ne "\e[0m" || echo -ne "\e[3${c[i]}m"
echo -n "${sets[v[i]]:l[i]*4+n[i]:1}"
l[i]=${n[i]}
done
((r > 0 && t * p >= r)) && tput reset && tput civis && t=0 || ((t++))
done
cleanup
}
main "$@"

122
scripts/theme Executable file
View file

@ -0,0 +1,122 @@
#!/bin/sh
themes="daylight
midnight"
as_list="$(printf "%s\n" "$themes" | awk 'NF{printf "\"%s\",", $0}' | sed 's/,$//')"
case "$(uname)" in
Linux)
if [ -n "$1" ]; then
theme="$1"
else
if [ "$XDG_SESSION_TYPE" = "wayland" ]; then
theme="$(printf "%s\n" "$themes" | rofi -dmenu -p 'theme')"
else
theme="$(printf "%s\n" "$themes" | dmenu -p 'select theme: ')"
fi
fi
;;
Darwin)
if [ -n "$1" ]; then
theme="$1"
else
theme="$(
osascript <<EOF
set theList to {$as_list}
set chosenTheme to (choose from list theList ¬
with title "Theme" ¬
with prompt "Pick a theme" ¬
OK button name "Apply" ¬
cancel button name "Cancel" ¬
without empty selection allowed)
if chosenTheme is false then
return ""
else
return item 1 of chosenTheme
end if
EOF
)"
fi
;;
*)
exit 1
;;
esac
[ -z "$theme" ] && exit 1
echo "$themes" | grep -Fxq "$theme" || exit 1
case "$(uname)" in
Linux)
if command -v gsettings >/dev/null 2>&1; then
case "$theme" in
midnight)
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'
;;
*)
gsettings set org.gnome.desktop.interface color-scheme 'prefer-light'
;;
esac
fi
[ "$XDG_SESSION_TYPE" = "wayland" ] && {
if [ "$XDG_CURRENT_DESKTOP" = 'Hyprland' ]; then
current_theme=$(readlink "$XDG_CONFIG_HOME/hypr/theme.conf" 2>/dev/null | awk -F/ '{print $NF}' | sed 's/\.conf$//')
if [ "$current_theme" != "$theme" ]; then
ln -sf "$XDG_CONFIG_HOME/hypr/themes/$theme.conf" "$XDG_CONFIG_HOME/hypr/theme.conf"
ln -sf "$XDG_CONFIG_HOME/waybar/themes/$theme.css" "$XDG_CONFIG_HOME/waybar/themes/theme.css"
hyprctl reload
pkill -USR1 waybar
pkill -USR1 waybar
fi
elif [ "$XDG_CURRENT_DESKTOP" = 'sway' ]; then
current_theme=$(readlink "$XDG_CONFIG_HOME/sway/themes/theme" 2>/dev/null | sed 's|.*/||')
if [ "$current_theme" != "$theme" ]; then
test -f "$XDG_CONFIG_HOME/sway/themes/theme" && ln -sf "$XDG_CONFIG_HOME/sway/themes/$theme" "$XDG_CONFIG_HOME/sway/themes/theme"
swaymsg reload
fi
fi
}
test -d "$XDG_CONFIG_HOME/rofi/themes" && ln -sf "$XDG_CONFIG_HOME/rofi/themes/$theme.rasi" "$XDG_CONFIG_HOME/rofi/themes/theme.rasi"
;;
Darwin)
case "$theme" in
daylight)
osascript -e 'tell app "System Events" to tell appearance preferences to set dark mode to false' 2>/dev/null || true
;;
midnight)
osascript -e 'tell app "System Events" to tell appearance preferences to set dark mode to true' 2>/dev/null || true
;;
esac
;;
esac
if tmux list-sessions >/dev/null 2>&1; then
test -f "$XDG_CONFIG_HOME/tmux/tmux.conf" && tmux source-file "$XDG_CONFIG_HOME/tmux/tmux.conf"
[ "$TMUX" ] && tmux refresh-client -S
fi
test -d "$XDG_CONFIG_HOME/fzf/themes" && ln -sf "$XDG_CONFIG_HOME/fzf/themes/$theme" "$XDG_CONFIG_HOME/fzf/themes/theme"
test -d "$XDG_CONFIG_HOME/rg/themes" && ln -sf "$XDG_CONFIG_HOME/rg/themes/$theme" "$XDG_CONFIG_HOME/rg/themes/theme"
test -d "$XDG_CONFIG_HOME/task/themes" && ln -sf "$XDG_CONFIG_HOME/task/themes/$theme.theme" "$XDG_CONFIG_HOME/task/themes/theme.theme"
if command -v claude >/dev/null 2>&1; then
case "$theme" in
daylight)
claude config set theme light
;;
midnight)
claude config set theme dark
;;
esac
fi
test -f ~/.zshenv && sed -i "s|^\(export THEME=\).*|\1$theme|" ~/.zshenv
for socket in /tmp/nvim-*.sock; do
test -S "$socket" && nvim --server "$socket" --remote-expr "luaeval('require(\"config.fzf_reload\").reload()')" 2>/dev/null || true
done

144
scripts/wp Executable file
View file

@ -0,0 +1,144 @@
#!/usr/bin/env python3
import os
import random
import subprocess
import sys
from PIL import Image, ImageDraw
HOME = os.environ["HOME"]
DIR = f"{HOME}/img/screen"
os.makedirs(DIR, exist_ok=True)
def get_resolution():
output = "1920x1080"
if "WAYLAND_DISPLAY" in os.environ:
desktop = os.environ.get("XDG_CURRENT_DESKTOP", "")
if desktop == "Hyprland":
output = (
subprocess.check_output(
"hyprctl monitors -j | jq -r '.[] | select(.focused==true) | .width, .height' | paste -sd x -",
shell=True,
)
.decode()
.strip()
)
elif desktop == "sway":
output = (
subprocess.check_output(
"swaymsg -t get_outputs -r | jq -r '.[] | select(.active==true) | .current_mode.width,.current_mode.height' | paste -sd x -",
shell=True,
)
.decode()
.strip()
)
else:
output = (
subprocess.check_output(
"xrandr | grep '*' | awk '{print $1}'", shell=True
)
.decode()
.strip()
)
return map(int, output.split("x"))
def lock():
W, H = get_resolution()
UNIT = 16
grid_w = W // UNIT
grid_h = H // UNIT
bg_color = tuple(random.randint(0, 255) for _ in range(3))
img = Image.new("RGB", (W, H), bg_color)
draw = ImageDraw.Draw(img)
MU = 0.8
SIGMA = 0.7
SCALE_FACTOR = 1.8
S = {(x, y) for x in range(grid_w) for y in range(grid_h)}
N = len(S)
while S:
if random.random() < 1 / N:
break
gx, gy = S.pop()
w_units = max(
1,
min(
grid_w - gx,
int(round(random.lognormvariate(MU, SIGMA) * SCALE_FACTOR)),
),
)
h_units = max(
1,
min(
grid_h - gy,
int(round(random.lognormvariate(MU, SIGMA) * SCALE_FACTOR)),
),
)
color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
dx = random.choice([1, -1])
dy = random.choice([1, -1])
gx_end = gx + dx * (w_units - 1)
gy_end = gy + dy * (h_units - 1)
x0, x1 = sorted([gx, gx_end])
y0, y1 = sorted([gy, gy_end])
draw.rectangle(
[x0 * UNIT, y0 * UNIT, (x1 + 1) * UNIT - 1, (y1 + 1) * UNIT - 1],
fill=color,
)
img.save(f"{DIR}/lock.jpg", quality=95)
def wall():
W, H = get_resolution()
colors = [
"#aa0000",
"#ff3333",
"#ff7777",
"#ffbb55",
"#ffcc88",
"#ff88ff",
"#aaaaff",
"#77ddbb",
"#77ff77",
"#cccccc",
]
colors.reverse()
img = Image.new("RGB", (W, H), "white")
draw = ImageDraw.Draw(img)
num_bars = len(colors)
for i, color in enumerate(reversed(colors)):
top = round(i * H / num_bars)
bottom = round((i + 1) * H / num_bars)
draw.rectangle([0, top, W, bottom], fill=color)
img.save(f"{DIR}/wallpaper.jpg", quality=95)
if len(sys.argv) < 2:
print("Usage: wp {lock|wall}", file=sys.stderr)
sys.exit(1)
cmd = sys.argv[1]
if cmd == "lock":
lock()
elif cmd == "wall":
wall()
else:
print("Usage: wp {lock|wall}", file=sys.stderr)
sys.exit(1)

56
scripts/x Executable file
View file

@ -0,0 +1,56 @@
#!/bin/sh
cmd="$1"; shift
case "$cmd" in
setup)
xrdb -merge "$XDG_CONFIG_HOME"/X11/xresources."$THEME"
xset b off
xset m 0
xset r rate 300 50
xset s 300
xset dpms 420 540 720
xmodmap "$XDG_CONFIG_HOME"/X11/xmodmap
xss-lock -- slock &
;;
bg)
randr="$(xrandr | rg ' connected ')"
mons="$(echo "$randr" | wc -l)"
wpdir="$HOME"/img/wp
[ "$1" ] && bgone="$1" || bgone="$wpdir"/one/cliff.jpg
cmd="feh --no-fehbg --bg-fill $bgone"
if [ "$mons" = 2 ]; then
[ "$2" ] && bgtwo="$2" || bgtwo="$wpdir"/two/lilies.jpg
cmd="$cmd --bg-fill $bgtwo"
else
cmd="feh --no-fehbg --bg-fill $bgone"
fi
eval "$cmd"
;;
mon)
mons="$(xrandr | rg --no-config ' connected ' | awk '{ print $1 }')"
one="$(echo "$mons" | head -n 1)"
two="$(echo "$mons" | tail -n 1)"
case "$two" in
*None* | "$one")
unset two
;;
esac
xrandr --auto
xrandr --output "$one" --primary --mode 1920x1200 --scale 1x1 --set TearFree on --dpi 161.73
[ -z "$two" ] && exit
xrandr --output "$one" --pos 960x2160 --output "$two" --scale 1.5x1.5 --pos 0x0
;;
*)
echo "Usage: x {setup|bg|mon}" >&2
exit 1
;;
esac