|
| 1 | +#!/usr/bin/env bash |
| 2 | +# shellcheck disable=SC2154 |
| 3 | + |
| 4 | +# Function to create wallbash substitutions |
| 5 | +create_wallbash_substitutions() { |
| 6 | + local use_inverted=$1 |
| 7 | + local sed_script |
| 8 | + sed_script="s|<wallbash_mode>|$(${use_inverted} && printf "%s" "${dcol_invt:-light}" || printf "%s" "${dcol_mode:-dark}")|g;" |
| 9 | + |
| 10 | + # Add substitutions for all color variables |
| 11 | + for i in {1..4}; do |
| 12 | + # Determine if colors should be reversed |
| 13 | + if ${use_inverted}; then |
| 14 | + rev_i=$((5 - i)) |
| 15 | + src_i=$rev_i |
| 16 | + else |
| 17 | + src_i=$i |
| 18 | + fi |
| 19 | + |
| 20 | + # Get values directly using indirect reference |
| 21 | + local pry_var="dcol_pry${src_i}" |
| 22 | + local txt_var="dcol_txt${src_i}" |
| 23 | + |
| 24 | + # Add RGBA variables |
| 25 | + local pry_rgba_var="dcol_pry${src_i}_rgba" |
| 26 | + local txt_rgba_var="dcol_txt${src_i}_rgba" |
| 27 | + |
| 28 | + # Add RGB variables by converting from RGBA if they exist |
| 29 | + local pry_rgb_var="dcol_pry${src_i}_rgb" |
| 30 | + local txt_rgb_var="dcol_txt${src_i}_rgb" |
| 31 | + |
| 32 | + # If RGB vars don't exist but RGBA does, create RGB from RGBA |
| 33 | + if [[ -n "${!pry_rgba_var:-}" && -z "${!pry_rgb_var:-}" ]]; then |
| 34 | + # Convert RGBA to RGB and export as new variable |
| 35 | + declare -g "${pry_rgb_var}=$(sed -E 's/rgba\(([0-9]+,[0-9]+,[0-9]+),.*/\1/' <<<"${!pry_rgba_var}")" |
| 36 | + export "${pry_rgb_var?}" |
| 37 | + fi |
| 38 | + |
| 39 | + if [[ -n "${!txt_rgba_var:-}" && -z "${!txt_rgb_var:-}" ]]; then |
| 40 | + # Convert RGBA to RGB and export as new variable |
| 41 | + declare -g "${txt_rgb_var}=$(sed -E 's/rgba\(([0-9]+,[0-9]+,[0-9]+),.*/\1/' <<<"${!txt_rgba_var}")" |
| 42 | + export "${txt_rgb_var?}" |
| 43 | + fi |
| 44 | + |
| 45 | + # Add to sed script if variables exist |
| 46 | + [ -n "${!pry_var:-}" ] && sed_script+="s|<wallbash_pry${i}>|${!pry_var}|g;" |
| 47 | + [ -n "${!txt_var:-}" ] && sed_script+="s|<wallbash_txt${i}>|${!txt_var}|g;" |
| 48 | + [ -n "${!pry_rgba_var:-}" ] && sed_script+="s|<wallbash_pry${i}_rgba(\([^)]*\))>|${!pry_rgba_var}|g;" |
| 49 | + [ -n "${!txt_rgba_var:-}" ] && sed_script+="s|<wallbash_txt${i}_rgba(\([^)]*\))>|${!txt_rgba_var}|g;" |
| 50 | + [ -n "${!pry_rgb_var:-}" ] && sed_script+="s|<wallbash_pry${i}_rgb>|${!pry_rgb_var}|g;" |
| 51 | + [ -n "${!txt_rgb_var:-}" ] && sed_script+="s|<wallbash_txt${i}_rgb>|${!txt_rgb_var}|g;" |
| 52 | + |
| 53 | + # Add xa colors with direct variable expansion |
| 54 | + for j in {1..9}; do |
| 55 | + local xa_var="dcol_${src_i}xa${j}" |
| 56 | + local xa_rgba_var="dcol_${src_i}xa${j}_rgba" |
| 57 | + local xa_rgb_var="dcol_${src_i}xa${j}_rgb" |
| 58 | + |
| 59 | + # Create RGB from RGBA if needed |
| 60 | + if [[ -n "${!xa_rgba_var:-}" && -z "${!xa_rgb_var:-}" ]]; then |
| 61 | + declare -g "${xa_rgb_var}=$(sed -E 's/rgba\(([0-9]+,[0-9]+,[0-9]+),.*/\1/' <<<"${!xa_rgba_var}")" |
| 62 | + export "${xa_rgb_var?}" |
| 63 | + fi |
| 64 | + |
| 65 | + [ -n "${!xa_var:-}" ] && sed_script+="s|<wallbash_${i}xa${j}>|${!xa_var}|g;" |
| 66 | + [ -n "${!xa_rgba_var:-}" ] && sed_script+="s|<wallbash_${i}xa${j}_rgba(\([^)]*\))>|${!xa_rgba_var}|g;" |
| 67 | + [ -n "${!xa_rgb_var:-}" ] && sed_script+="s|<wallbash_${i}xa${j}_rgb>|${!xa_rgb_var}|g;" |
| 68 | + done |
| 69 | + done |
| 70 | + |
| 71 | + # Add home directory substitution |
| 72 | + sed_script+="s|<<HOME>>|${HOME}|g" |
| 73 | + |
| 74 | + printf "%s" "$sed_script" |
| 75 | +} |
| 76 | + |
| 77 | +# Preprocess sed scripts for both normal and inverted modes |
| 78 | +preprocess_substitutions() { |
| 79 | + NORMAL_SED_SCRIPT=$(create_wallbash_substitutions false) |
| 80 | + INVERTED_SED_SCRIPT=$(create_wallbash_substitutions true) |
| 81 | + export NORMAL_SED_SCRIPT INVERTED_SED_SCRIPT |
| 82 | +} |
| 83 | + |
| 84 | +fn_wallbash() { |
| 85 | + local template="${1}" |
| 86 | + local temp_target_file exec_command |
| 87 | + WALLBASH_SCRIPTS="${template%%hyde/wallbash*}hyde/wallbash/scripts" |
| 88 | + if [[ "${template}" == *.theme ]]; then |
| 89 | + # This is approach is to handle the theme files |
| 90 | + # We don't want themes to launch the exec_command or any arbitrary codes |
| 91 | + # To enable this we should have a *.dcol file as a companion to the theme file |
| 92 | + IFS=':' read -r -a wallbashDirs <<<"$WALLBASH_DIRS" |
| 93 | + template_name="${template##*/}" |
| 94 | + template_name="${template_name%.*}" |
| 95 | + # echo "${wallbashDirs[@]}" |
| 96 | + dcolTemplate=$(find "${wallbashDirs[@]}" -type f -path "*/theme*" -name "${template_name}.dcol" 2>/dev/null | awk '!seen[substr($0, match($0, /[^/]+$/))]++') |
| 97 | + if [[ -n "${dcolTemplate}" ]]; then |
| 98 | + eval target_file="$(head -1 "${dcolTemplate}" | awk -F '|' '{print $1}')" |
| 99 | + exec_command="$(head -1 "${dcolTemplate}" | awk -F '|' '{print $2}')" |
| 100 | + WALLBASH_SCRIPTS="${dcolTemplate%%hyde/wallbash*}hyde/wallbash/scripts" |
| 101 | + |
| 102 | + fi |
| 103 | + fi |
| 104 | + |
| 105 | + # shellcheck disable=SC1091 |
| 106 | + # shellcheck disable=SC2154 |
| 107 | + [ -f "$HYDE_STATE_HOME/state" ] && source "$HYDE_STATE_HOME/state" |
| 108 | + # shellcheck disable=SC1091 |
| 109 | + [ -f "$HYDE_STATE_HOME/config" ] && source "$HYDE_STATE_HOME/config" |
| 110 | + if [[ -n "${WALLBASH_SKIP_TEMPLATE[*]}" ]]; then |
| 111 | + for skip in "${WALLBASH_SKIP_TEMPLATE[@]}"; do |
| 112 | + if [[ "${template}" =~ ${skip} ]]; then |
| 113 | + print_log -sec "wallbash" -warn "skip '$skip' template " "Template: ${template}" |
| 114 | + return 0 |
| 115 | + fi |
| 116 | + done |
| 117 | + fi |
| 118 | + |
| 119 | + [ -z "${target_file}" ] && eval target_file="$(head -1 "${template}" | awk -F '|' '{print $1}')" |
| 120 | + [ ! -d "$(dirname "${target_file}")" ] && print_log -sec "wallbash" -warn "skip 'missing directory'" "${target_file} // Do you have the dependency installed?" && return 0 |
| 121 | + export wallbashScripts="${WALLBASH_SCRIPTS}" |
| 122 | + export WALLBASH_SCRIPTS confDir hydeConfDir cacheDir thmbDir dcolDir iconsDir themesDir fontsDir wallbashDirs enableWallDcol HYDE_THEME_DIR HYDE_THEME gtkIcon gtkTheme cursorTheme |
| 123 | + export -f pkg_installed print_log |
| 124 | + exec_command="${exec_command:-"$(head -1 "${template}" | awk -F '|' '{print $2}')"}" |
| 125 | + temp_target_file="$(mktemp)" |
| 126 | + sed '1d' "${template}" >"${temp_target_file}" |
| 127 | + |
| 128 | + # Check if we need inverted colors |
| 129 | + if [[ "${revert_colors:-0}" -eq 1 ]] || |
| 130 | + [[ "${enableWallDcol:-0}" -eq 2 && "${dcol_mode:-}" == "light" ]] || |
| 131 | + [[ "${enableWallDcol:-0}" -eq 3 && "${dcol_mode:-}" == "dark" ]]; then |
| 132 | + # Use the preprocessed inverted sed script |
| 133 | + sed -i "${INVERTED_SED_SCRIPT}" "${temp_target_file}" |
| 134 | + else |
| 135 | + # Use the preprocessed normal sed script |
| 136 | + sed -i "${NORMAL_SED_SCRIPT}" "${temp_target_file}" |
| 137 | + fi |
| 138 | + |
| 139 | + if [ -s "${temp_target_file}" ]; then |
| 140 | + mv "${temp_target_file}" "${target_file}" |
| 141 | + fi |
| 142 | + [ -z "${exec_command}" ] || bash -c "${exec_command}" & |
| 143 | + disown |
| 144 | +} |
| 145 | + |
| 146 | +scrDir="$(dirname "$(realpath "$0")")" |
| 147 | +export scrDir |
| 148 | +# shellcheck disable=SC1091 |
| 149 | +source "${scrDir}/globalcontrol.sh" |
| 150 | +wallbash_image="${1}" |
| 151 | + |
| 152 | +# Parse arguments |
| 153 | +dcol_colors="" |
| 154 | +while [[ $# -gt 0 ]]; do |
| 155 | + case "$1" in |
| 156 | + --dcol) |
| 157 | + dcol_colors="$2" |
| 158 | + if [ -f "${dcol_colors}" ]; then |
| 159 | + printf "[Source] %s\n" "${dcol_colors}" |
| 160 | + # shellcheck disable=SC1090 |
| 161 | + source "${dcol_colors}" |
| 162 | + shift 2 |
| 163 | + else |
| 164 | + dcol_colors="$(find "${dcolDir}" -type f -name "*.dcol" | shuf -n 1)" |
| 165 | + printf "[Dcol Colors] %s\n" "${dcol_colors}" |
| 166 | + shift |
| 167 | + fi |
| 168 | + ;; |
| 169 | + --wall) |
| 170 | + wallbash_image="$2" |
| 171 | + shift 2 |
| 172 | + ;; |
| 173 | + --single) |
| 174 | + [ -f "${wallbash_image}" ] || wallbash_image="${cacheDir}/wall.set" |
| 175 | + single_template="$2" |
| 176 | + printf "[wallbash] Single template: %s\n" "${single_template}" |
| 177 | + printf "[wallbash] Wallpaper: %s\n" "${wallbash_image}" |
| 178 | + shift 2 |
| 179 | + # ;; |
| 180 | + # --mode) |
| 181 | + # enableWallDcol="$2" |
| 182 | + # shift 2 |
| 183 | + ;; |
| 184 | + -*) |
| 185 | + printf "Usage: %s [--dcol <mode>] [--wall <image>] [--single] [--mode <mode>] [--help]\n" "$0" |
| 186 | + exit 0 |
| 187 | + ;; |
| 188 | + *) break ;; |
| 189 | + esac |
| 190 | +done |
| 191 | + |
| 192 | +#// validate input |
| 193 | + |
| 194 | +if [ -z "${wallbash_image}" ] || [ ! -f "${wallbash_image}" ]; then |
| 195 | + printf "Error: Input wallpaper not found!\n" |
| 196 | + exit 1 |
| 197 | +fi |
| 198 | +# shellcheck disable=SC2154 |
| 199 | +dcol_file="${dcolDir}/$(set_hash "${wallbash_image}").dcol" |
| 200 | + |
| 201 | +if [ ! -f "${dcol_file}" ]; then |
| 202 | + "${scrDir}/swwwallcache.sh" -w "${wallbash_image}" &>/dev/null |
| 203 | +fi |
| 204 | + |
| 205 | +set -a |
| 206 | +# shellcheck disable=SC1090 |
| 207 | +source "${dcol_file}" |
| 208 | +# shellcheck disable=SC2154 |
| 209 | +if [ -f "${HYDE_THEME_DIR}/theme.dcol" ] && [ "${enableWallDcol}" -eq 0 ]; then |
| 210 | + # shellcheck disable=SC1091 |
| 211 | + source "${HYDE_THEME_DIR}/theme.dcol" |
| 212 | + print_log -sec "wallbash" -stat "override" "dominant colors from ${HYDE_THEME} theme" |
| 213 | + print_log -sec "wallbash" -stat " NOTE" "Remove \"${HYDE_THEME_DIR}/theme.dcol\" to use wallpaper dominant colors" |
| 214 | +fi |
| 215 | + |
| 216 | +# shellcheck disable=SC2154 |
| 217 | +[ "${dcol_mode}" == "dark" ] && dcol_invt="light" || dcol_invt="dark" |
| 218 | +set +a |
| 219 | + |
| 220 | +if [ -z "$gtkTheme" ]; then |
| 221 | + if [ "${enableWallDcol}" -eq 0 ]; then |
| 222 | + gtkTheme="$(get_hyprConf "GTK_THEME")" |
| 223 | + else |
| 224 | + gtkTheme="Wallbash-Gtk" |
| 225 | + fi |
| 226 | +fi |
| 227 | +[ -z "$gtkIcon" ] && gtkIcon="$(get_hyprConf "ICON_THEME")" |
| 228 | +[ -z "$cursorTheme" ] && cursorTheme="$(get_hyprConf "CURSOR_THEME")" |
| 229 | +export gtkTheme gtkIcon cursorTheme |
| 230 | + |
| 231 | +# Preprocess substitutions once before processing any templates |
| 232 | +preprocess_substitutions |
| 233 | +print_log -sec "wallbash" -stat "preprocessed" "color substitutions" |
| 234 | + |
| 235 | +#// deploy wallbash colors |
| 236 | + |
| 237 | +WALLBASH_DIRS="" |
| 238 | +for dir in "${wallbashDirs[@]}"; do |
| 239 | + [ -d "${dir}" ] || wallbashDirs=("${wallbashDirs[@]//$dir/}") |
| 240 | + [ -d "$dir" ] && WALLBASH_DIRS+="$dir:" |
| 241 | +done |
| 242 | +WALLBASH_DIRS="${WALLBASH_DIRS%:}" |
| 243 | + |
| 244 | +if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then PATH="$HOME/.local/bin:${PATH}"; fi |
| 245 | +export WALLBASH_DIRS PATH |
| 246 | +export -f fn_wallbash print_log pkg_installed create_wallbash_substitutions preprocess_substitutions |
| 247 | + |
| 248 | +if [ -n "${dcol_colors}" ]; then |
| 249 | + set -a |
| 250 | + # shellcheck disable=SC1090 |
| 251 | + source "${dcol_colors}" |
| 252 | + print_log -sec "wallbash" -stat "single instance" "Wallbash Colors: ${dcol_colors}" |
| 253 | + set +a |
| 254 | +fi |
| 255 | + |
| 256 | +# Single template mode |
| 257 | +if [ -n "${single_template}" ]; then |
| 258 | + fn_wallbash "${single_template}" |
| 259 | + exit 0 |
| 260 | +fi |
| 261 | + |
| 262 | +# Print to terminal the colors |
| 263 | +[ -t 1 ] && "${scrDir}/wallbash.print.colors.sh" |
| 264 | + |
| 265 | +# Add some hooks here |
| 266 | +toml_write "${confDir}/kdeglobals" "Colors:View" "BackgroundNormal" "#${dcol_pry1:-000000}" |
| 267 | + |
| 268 | +#// switch theme <//> wall based colors |
| 269 | + |
| 270 | +# shellcheck disable=SC2154 |
| 271 | +if [ "${enableWallDcol}" -eq 0 ] && [[ "${reload_flag}" -eq 1 ]]; then |
| 272 | + |
| 273 | + print_log -sec "wallbash" -stat "apply ${dcol_mode} colors" "${HYDE_THEME} theme" |
| 274 | + mapfile -d '' -t deployList < <(find "${HYDE_THEME_DIR}" -type f -name "*.theme" -print0) |
| 275 | + |
| 276 | + while read -r pKey; do |
| 277 | + fKey="$(find "${HYDE_THEME_DIR}" -type f -name "$(basename "${pKey%.dcol}.theme")")" |
| 278 | + [ -z "${fKey}" ] && deployList+=("${pKey}") |
| 279 | + done < <(find "${wallbashDirs[@]}" -type f -path "*/theme*" -name "*.dcol" 2>/dev/null | awk '!seen[substr($0, match($0, /[^/]+$/))]++') |
| 280 | + |
| 281 | + # Add a timeout to parallel to prevent hanging |
| 282 | + parallel --timeout 10 fn_wallbash ::: "${deployList[@]}" || true |
| 283 | + |
| 284 | +elif [ "${enableWallDcol}" -gt 0 ]; then |
| 285 | + print_log -sec "wallbash" -stat "apply ${dcol_mode} colors" "Wallbash theme" |
| 286 | + # This is the reason we avoid SPACES for the wallbash template names |
| 287 | + # Add a timeout to parallel to prevent hanging |
| 288 | + find "${wallbashDirs[@]}" -type f -path "*/theme*" -name "*.dcol" 2>/dev/null | awk '!seen[substr($0, match($0, /[^/]+$/))]++' | parallel --timeout 10 fn_wallbash {} || true |
| 289 | +fi |
| 290 | + |
| 291 | +# Theme mode: detects the color-scheme set in hypr.theme and falls back if nothing is parsed. |
| 292 | +revert_colors=0 |
| 293 | +[ "${enableWallDcol}" -eq 0 ] && { grep -q "${dcol_mode}" <<<"$(get_hyprConf "COLOR_SCHEME")" || revert_colors=1; } |
| 294 | +export revert_colors |
| 295 | + |
| 296 | +# Add a timeout to parallel to prevent hanging |
| 297 | +find "${wallbashDirs[@]}" -type f -path "*/always*" -name "*.dcol" 2>/dev/null | sort | awk '!seen[substr($0, match($0, /[^/]+$/))]++' | parallel --timeout 10 fn_wallbash {} || true |
0 commit comments