Add .local/bin/fishify-envs

Add .local/bin/fix-loopback
Add .local/bin/hyprtoggle
Add .local/bin/localhost
Add .local/bin/low-battery-warn
Add .local/bin/make-pwa
Add .local/bin/niri-cycle
Add .local/bin/push-chezmoi
Add .local/bin/tmux-sessionizer
Add .local/bin/hooks/generic
This commit is contained in:
Lewis Wynne 2026-01-07 15:08:51 +00:00
parent 9c6f940eb1
commit 9d16d6e6b0
10 changed files with 298 additions and 0 deletions

View file

@ -0,0 +1,20 @@
#!/usr/bin/env bash
in="$1"
if [[ -z "$in" ]]; then
echo "usage: $0 input_file"
exit 1
fi
while IFS= read -r line; do
[[ -z "$line" || "$line" =~ ^# ]] && continue
if [[ "$line" =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; then
var="${BASH_REMATCH[1]}"
val="${BASH_REMATCH[2]}"
val="${val%\"}"
val="${val#\"}"
echo "set -Ux $var \"$val\""
fi
done < "$in"

View file

@ -0,0 +1,3 @@
sudo modprobe v4l2loopback devices=1 video_nr=2 card_label="OBS Virtual Camera" exclusive_caps=1
sudo chmod 666 /dev/video*
sudo usermod -aG video $USER

View file

@ -0,0 +1,46 @@
#!/usr/bin/env bash
# Toggle a specific optional Hyprland config in ~/.config/hypr/hyprland.conf
RESET="\033[0m"
RED="\033[1m\033[031m"
GREEN="\033[1m\033[032m"
CONFIG="$HOME/.config/hypr/hyprland.conf"
hyprtoggle_list() {
grep -E "^[[:space:]#]*source = .*opts/.*\.conf" "$CONFIG" | while read -r line; do
name=$(basename "$(echo "$line" | grep -oE "[^/]+\.conf$")" .conf)
if [[ "$line" =~ ^# ]]; then
echo -e " ${RED}✗${RESET} $name"
else
echo -e " ${GREEN}✓${RESET} $name"
fi
done
}
if [ ! -f "$CONFIG" ]; then
echo -e "${RED}✗${RESET}config not found at $CONFIG"
exit 1
fi
if [ -z "$1" ]; then
echo "usage: hyprtoggle <option_name>"
hyprtoggle_list
exit 1
fi
OPT="$1"
# Check if the line is currently active or commented
if grep -qE "^[[:space:]]*source = .*${OPT}\.conf" "$CONFIG"; then
echo -e "${RED}disabling${RESET} $OPT..."
sed -i "s|^[[:space:]]*source = \(.*${OPT}\.conf\)|# source = \1|" "$CONFIG"
elif grep -qE "^#\s*source = .*${OPT}\.conf" "$CONFIG"; then
echo -e "${GREEN}enabling${RESET} $OPT..."
sed -i "s|^#\s*source = \(.*${OPT}\.conf\)|source = \1|" "$CONFIG"
else
echo -e "${RED}✗ no matching source${RESET} for '$OPT'"
exit 1
fi
hyprtoggle_list

View file

@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
PORT=8000
IP=$(ip route get 1.1.1.1 2>/dev/null | awk '{print $7; exit}')
IP=${IP:-127.0.0.1}
if [[ -t 1 ]]; then
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
BOLD=$(tput bold)
RESET=$(tput sgr0)
else
YELLOW= BLUE= BOLD= RESET=
fi
echo "Serving ${YELLOW}${BOLD}$(pwd)${RESET} at ${BLUE}${BOLD}http://${IP}:${PORT}${RESET}"
exec python3 -m http.server "$PORT"

View file

@ -0,0 +1,26 @@
#!/usr/bin/env bash
THRESHOLD=15
# Find the battery device (first one found)
BATTERY=$(upower -e | grep battery | head -n1)
# If no battery found, exit
if [ -z "$BATTERY" ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') No battery found. Exiting."
exit 0
fi
echo "$(date '+%Y-%m-%d %H:%M:%S') Battery device: $BATTERY"
# Get battery state and percentage
STATE=$(upower -i "$BATTERY" | awk '/state:/ {print $2}')
PERCENT=$(upower -i "$BATTERY" | awk -F'[:%]' '/percentage:/ {gsub(/ /,"",$2); print $2}')
echo "$(date '+%Y-%m-%d %H:%M:%S') Battery state: $STATE, percentage: $PERCENT"
# Only notify if discharging and below threshold
if [ "$STATE" = "discharging" ] && [ "$PERCENT" -lt "$THRESHOLD" ]; then
notify-send "Battery low" "Battery at ${PERCENT}% and discharging."
echo "$(date '+%Y-%m-%d %H:%M:%S') Notification sent: Battery at ${PERCENT}% and discharging."
fi

View file

@ -0,0 +1,92 @@
#!/usr/bin/env bash
#
# make-pwa
# makes a chromium PWA desktop entry for the given url
set -e
usage() {
echo "Usage:"
echo " $0 create <name> <url>"
echo " $0 delete <name>"
exit 1
}
if [ "$#" -lt 2 ]; then
usage
fi
ACTION="$1"
NAME="$2"
DESKTOP_DIR="$HOME/.local/share/applications"
DESKTOP_FILE="$DESKTOP_DIR/pwa-${NAME}.desktop"
ICON_DIR="$HOME/.local/share/icons"
ICON_FILE="$ICON_DIR/pwa-${NAME}.ico"
PNG_ICON_FILE="$ICON_DIR/pwa-${NAME}.png"
fetch_favicon() {
URL="$1"
mkdir -p "$ICON_DIR"
FAVICON_URL="${URL}/favicon.ico"
if curl -fsSL -A "Mozilla/5.0" "$FAVICON_URL" -o "$ICON_FILE"; then
if command -v convert >/dev/null 2>&1; then
if magick "$ICON_FILE[-1]" "$PNG_ICON_FILE"; then
echo "$PNG_ICON_FILE"
else
echo ""
fi
else
echo "$ICON_FILE"
fi
else
echo ""
fi
}
case "$ACTION" in
create)
if [ "$#" -lt 3 ]; then
usage
fi
URL="$3"
if [ "$#" -ge 4 ]; then
ICON_PATH="$4"
else
ICON_PATH=$(fetch_favicon "$URL")
if [ -z "$ICON_PATH" ]; then
ICON_BASENAME="web-browser"
else
ICON_BASENAME="$ICON_PATH"
fi
fi
mkdir -p "$DESKTOP_DIR"
cat > "$DESKTOP_FILE" <<EOF
[Desktop Entry]
Version=1.0
Type=Application
Name=$NAME
Exec=chromium --app=$URL
Icon=$ICON_BASENAME
Terminal=false
Categories=Network;WebBrowser;
EOF
chmod +x "$DESKTOP_FILE"
echo "Created desktop entry: $DESKTOP_FILE"
;;
delete)
if [ -f "$DESKTOP_FILE" ]; then
rm "$DESKTOP_FILE"
echo "Deleted desktop entry: $DESKTOP_FILE"
else
echo "Desktop entry not found: $DESKTOP_FILE"
fi
if [ -f "$ICON_FILE" ]; then
rm "$ICON_FILE"
echo "Deleted icon file: $ICON_FILE"
fi
;;
*)
usage
;;
esac

View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
next="focus-column-right-or-first"
if [[ "${1:-}" == "--back" ]]; then
next="focus-column-left-or-last"
fi
niri msg action "$next"
niri msg action center-column

View file

@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
REPO="$(chezmoi source-path)"
cd "$REPO"
git push

View file

@ -0,0 +1,66 @@
#!/usr/bin/env bash
set -euo pipefail
# Each entry: PATH|minDepth|maxDepth
SEARCH_SPECS=(
"$HOME/src/github|2|2" # username/repo
"$HOME/src/aur|1|1" # AUR pkgs
"$HOME/.config|0|1" # each folder in ~/.config
"$HOME/.local/bin|0|0"
)
# Optional: override via env, e.g.
# SESSIONIZER_SPECS="$HOME/work|1|2,$HOME/projects|2|2"
IFS=',' read -r -a _OVERRIDE <<< "${SESSIONIZER_SPECS:-}"
if [[ ${#_OVERRIDE[@]} -gt 0 && -n ${_OVERRIDE[0]} ]]; then
SEARCH_SPECS=("${_OVERRIDE[@]}")
fi
unset _OVERRIDE
collect() {
local path min max
for spec in "${SEARCH_SPECS[@]}"; do
IFS='|' read -r path min max <<<"$spec"
[[ -d $path ]] || continue
find "$path" -mindepth "$min" -maxdepth "$max" -type d 2>/dev/null
done
}
if [[ $# -eq 1 ]]; then
selected=$1
else
if command -v fd >/dev/null 2>&1; then
mapfile -t CANDIDATES < <(collect | sort -u)
selected=$(printf '%s\n' "${CANDIDATES[@]}" | fzf)
else
selected=$(collect | sort -u | fzf)
fi
fi
[[ -z ${selected:-} ]] && exit 0
selected_name=$(basename "$selected" | tr -c '[:alnum:]' '_' | sed 's/^_*$/'"sess_$(date +%s)"'/' | sed 's/_$//')
tmux_running=$(pgrep tmux || true)
if [[ -z ${TMUX:-} ]] && [[ -z $tmux_running ]]; then
exec tmux new-session -s "$selected_name" -c "$selected"
fi
if ! tmux has-session -t="$selected_name" 2>/dev/null; then
tmux new-session -ds "$selected_name" -c "$selected"
tmux rename-window -t "$selected_name:" "shell"
tmux new-window -t "$selected_name:" -c "$selected" -n "neovim"
tmux send-keys -t "$selected_name:neovim" "nvim" Enter
if [[ -d "$selected/.git" ]]; then
tmux new-window -t "$selected_name:" -c "$selected" -n "git"
tmux send-keys -t "$selected_name:git" "lazygit" Enter
fi
tmux select-window -t "$selected_name:neovim"
fi
if [[ -z ${TMUX:-} ]]; then
tmux attach -t "$selected_name"
else
tmux switch-client -t "$selected_name"
fi
i

View file

@ -0,0 +1,6 @@
#!/bin/bash
HOOK_NAME="$1"
HOOK_VALUE="$2"
notify-send "$HOOK_NAME" "$HOOK_VALUE"