Skip to content

Commit 93dbffe

Browse files
authored
task: Move swwwallbash to color.set and refactor color propagation by… (#493)
task: Move swwwallbash to color.set and refactor color propagation by writing the sed script as a struct. - refactor - flexible color propagation - Added a dynamic RGB dcol, useful for latest discord!
1 parent eb04da7 commit 93dbffe

File tree

4 files changed

+311
-382
lines changed

4 files changed

+311
-382
lines changed
Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
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

Comments
 (0)