#!/bin/sh albums_dir="$HOME/Images/Wallpapers/Desktop" declare -A albums=( [sfw]="$albums_dir/SFW" [nsfw]="$albums_dir/( ͡° ͜ʖ ͡°)" [bonk]="$albums_dir/Bonk" [hypr]="/usr/share/hyprland/wall0.png" ) # Declare outside of function to make them global. declare -A colors declare -A params function show_help { cat << EOF Usage: $(basename "$0") ACTION ACTION: a, album ALBUM_NAME[,ALBUM_NAME] Select a random wallpaper from one or more albums & change the theme. h, help Show this help. l, list List all defined albums. r, reload Reload the current theme. w, wallpaper WP_PATH Change the theme using a specific wallpaper. EOF } function check_requirements { req_satisfied=1 for executable in hyprctl hyprpaper kitty magick mako pastel wal waybar wlogout wofi; do if ! which "$executable" > /dev/null; then echo "Executable $executable not found!" req_satisfied=0 fi done if [ $req_satisfied -eq 0 ]; then echo "Missing some requirements, exiting." exit 1 fi } function list_albums { echo "Defined albums:" for album in "${!albums[@]}"; do echo " $album: ${albums[$album]}" done } # Transform comma separated $albums_arg into array ${target_albums[@]} function parse_albums_arg { IFS=', ' read -r -a target_albums <<< "$albums_arg" # Check if entered album(s) are valid. for target_album in "${target_albums[@]}"; do if ! echo "${!albums[@]}" | grep -qP "\b$target_album\b"; then echo "Invalid album name, exiting." exit 1 fi done } # Pick a random wallpaper from ${target_albums[@]} function pick_random_wallpaper { declare -a target_dirs for target_album in "${target_albums[@]}"; do target_dirs+=("${albums[$target_album]}") done echo "Picking a random wallpaper from ${target_dirs[*]}." wallpaper="$(find "${target_dirs[@]}" -type f -regex '.*\.\(jpg\|jpeg\|png\)$' | shuf -n 1)" # Reassign to make variable global. wallpaper="$wallpaper" } function set_theme { echo "Selected wallpaper: $wallpaper" # Generate the colors scheme echo "Generating color scheme using pywal." wal -qni "$wallpaper" --saturate 0.75 # Replace apostrophes around the wallpaper path with quotes # in case there is an apostrophe in the file name sed -iE "/^wallpaper=/,/#/ s/='/=\"/" "$HOME/.cache/wal/colors.sh" sed -iE "/^wallpaper=/,/#/ s/'$/\"/" "$HOME/.cache/wal/colors.sh" # Source colors scheme generated source "$HOME/.cache/wal/colors.sh" set_theme_variables set_gtk_css_file for component in desktop_wallpaper hyprland kitty mako waybar wlogout wofi; do set_${component}_theme & done } function set_theme_variables { # Set colors accent1_dark_hsl="$(pastel darken 1 "$color5" | pastel format hsl)" accent2_dark_hsl="$(pastel darken 1 "$color6" | pastel format hsl)" colors=( [foreground]="$foreground" [good]="#00BB66" [bad]="#AA2222" [urgent]="$color4" [accent1]="$color5" [accent2]="$color6" [background1]="$(pastel lighten 0.2 "$accent1_dark_hsl" | pastel format hex)" [background2]="$(pastel lighten 0.2 "$accent2_dark_hsl" | pastel format hex)" [hovered]="$(pastel lighten 0.25 "$accent1_dark_hsl" | pastel format hex)" [selected]="$(pastel lighten 0.35 "$accent1_dark_hsl" | pastel format hex)" [disabled]="$(pastel lighten 0.35 "$accent1_dark_hsl" | pastel format hex)" [disabled2]="$(pastel lighten 0.35 "$accent2_dark_hsl" | pastel format hex)" ) params=( [border_radius]=4 [border_size]=2 [gaps_out]=15 [gaps_in]=8 [font]="'JetBrainsMono NF'" ) } function set_gtk_css_file { echo -n '' > "$HOME/.config/gtk-3.0/colors.css" for key in "${!colors[@]}"; do value="${colors[$key]}" echo "@define-color $key $value;" >> "$HOME/.config/gtk-3.0/colors.css" done } function set_betterdiscord_theme { if which betterdiscordctl > /dev/null; then echo "Executable found for betterdiscordctl." if [[ ! -f "$HOME/.config/BetterDiscord/data/stable/custom.css" ]]; then echo "Downloading ClearVision theme for BetterDiscord." mkdir -p "$HOME/.config/BetterDiscord/data/stable" wget -O "$HOME/.config/BetterDiscord/data/stable/custom.css" "https://betterdiscord.app/Download?id=23" fi echo "Changing BetterDiscord theme colors." declare -A bd_variables=( [main-color]="${colors[accent1]}" [hover-color]="${colors[accent2]}" [text-normal]="${colors[foreground]}" [background-shading]='0%' [background-overlay]='rgba(0, 0, 0, 0)' [background-image]="linear-gradient(160deg, ${colors[background1]}, ${colors[background2]})" ) for key in "${!bd_variables[@]}"; do value="${bd_variables[$key]}" sed -i "s~--$key:[^;]*~--$key: $value~" "$HOME/.config/BetterDiscord/data/stable/custom.css" done else echo "No executable found for betterdiscordctl, skipping." fi } function set_desktop_wallpaper_theme { if ! pgrep -u "$USER" hyprpaper > /dev/null; then hyprctl dispatch exec hyprpaper > /dev/null fi hyprctl hyprpaper preload "$wallpaper" hyprctl hyprpaper wallpaper "eDP-1,$wallpaper" hyprctl hyprpaper unload unused } function set_hyprland_theme { echo -n '' > "$HOME/.config/hypr/hyprland.d/colors.conf" for key in "${!colors[@]}"; do value="${colors[$key]}" echo '$'"$key=rgb(${value:1})" >> "$HOME/.config/hypr/hyprland.d/colors.conf" done for key in "${!params[@]}"; do value="${params[$key]}" echo '$'"$key=$value" >> "$HOME/.config/hypr/hyprland.d/colors.conf" done hyprctl reload > /dev/null } function set_kitty_theme { declare -A kitty_variables=( [font_family]="${params[font]}" [url_color]="${colors[accent1]}" [tab_bar_background]="${colors[background1]}" [active_tab_background]="${colors[selected]}" [inactive_tab_background]="${colors[hovered]}" [active_tab_foreground]="${colors[foreground]}" [inactive_tab_foreground]="${colors[foreground]}" ) for key in "${!kitty_variables[@]}"; do value="${kitty_variables[$key]}" sed -i "s/^$key.*/$key $value/" "$HOME/.config/kitty/kitty.conf" done killall -SIGUSR1 kitty &> /dev/null } function set_mako_theme { declare -A mako_variables=( [font]="${params[font]} 11" [border-radius]="${params[border_radius]}" [border-size]="${params[border_size]}" [outer-margin]="$((params[gaps_out]*2)),$((params[gaps_out]*2)),0,0" [text-color]="${colors[foreground]}" [background-color]="${colors[background1]}" [border-color]="${colors[accent1]}" ) for key in "${!mako_variables[@]}"; do value="${mako_variables[$key]}" sed -i "s/$key=.*/$key=$value/" "$HOME/.config/mako/config" done if pgrep -u "$USER" mako > /dev/null; then makoctl reload else hyprctl dispatch exec mako > /dev/null fi } function set_openrgb_theme { if which openrgb > /dev/null; then openrgb --noautoconnect -c "${colors[accent1]:1}" > /dev/null fi } function set_pywalfox_theme { if pgrep -u "$USER" firefox &> /dev/null; then pywalfox update fi } function set_waybar_theme { declare -A waybar_variables=( [font-family]="${params[font]}" [border-bottom]="${params[border_size]}px solid transparent" [margin-bottom]="${params[border_size]}px" ) for key in "${!waybar_variables[@]}"; do value="${waybar_variables[$key]}" sed -i "s~$key:[^;]*~$key: $value~" "$HOME/.config/waybar/style.css" done if pgrep -u "$USER" waybar > /dev/null; then killall -SIGUSR2 waybar else hyprctl dispatch exec waybar > /dev/null fi } function set_wlogout_theme { for img in lock reboot shutdown logout; do magick "$HOME/.config/wlogout/$img.png" -fill "${colors[accent1]}" -colorize 100 "$HOME/.config/wlogout/$img.png" magick "$HOME/.config/wlogout/$img-focus.png" -fill "${colors[accent2]}" -colorize 100 "$HOME/.config/wlogout/$img-focus.png" done } function set_wofi_theme { declare -A wofi_variables_window=( [font-family]="${params[font]}" [border]="${params[border_size]}px solid transparent" [border-radius]="${params[border_radius]}px" ) for key in "${!wofi_variables_window[@]}"; do value="${wofi_variables_window[$key]}" sed -i "/^window/,/$key:/ s~$key:[^;]*~$key: $value~" "$HOME/.config/wofi/style.css" done declare -A wofi_variables_input=( [margin]="${params[border_size]}px" [border-radius]="${params[border_radius]}px ${params[border_radius]}px 0 0" ) for key in "${!wofi_variables_input[@]}"; do value="${wofi_variables_input[$key]}" sed -i "/^#input/,/$key:/ s~$key:[^;]*~$key: $value~" "$HOME/.config/wofi/style.css" done # Set entry:selected border-radius sed -i "/^#entry:selected/,/border-radius:/ s/border-radius:[^;]*/border-radius: $(( params[border_radius]/2 ))px/" "$HOME/.config/wofi/style.css" } check_requirements case "$1" in a|album) albums_arg="$2" parse_albums_arg pick_random_wallpaper set_theme ;; h|help) show_help ;; l|list) list_albums ;; r|reload) # Get the current wallpaper in $wallpaper source "$HOME/.cache/wal/colors.sh" set_theme ;; w|wallpaper) wallpaper="$2" check_wallpaper_path set_theme ;; *) show_help exit 1 ;; esac