Lesson: Theme Engine Template Variable Fallbacks¶
The Problem¶
The theme engine (theme-engine.sh) renders {{VARIABLE}} placeholders in template files. When a theme INI doesn't define a color key, the variable resolves to an empty string, leaving the literal {{COLOR_BG}} in the output CSS instead of using the intended default.
How It Works¶
- Theme INI defines colors:
[colors] bg=#1e1e2e - Template has:
background-color: {{COLOR_BG}}; render_template()looks upCOLOR_BGviaini_get("colors.bg", "#1e1e2e")- If the INI defines
bg, the value is used. If not, the default is returned. - The result replaces
{{COLOR_BG}}in the template.
The Bug¶
The case statement in render_template() defines defaults, but they're never used as fallbacks because ini_get always returns something (either the INI value or the default parameter). However, if the INI key exists but is empty, or if the section header is malformed, ini_get returns empty and the template variable is replaced with nothing.
# Bug: empty var_value means the {{VARIABLE}} stays in output
content="${content//\{\{$var_name\}\}/$var_value}"
The Fix¶
Add explicit fallback when var_value is empty:
if [[ -z "$var_value" ]]; then
case "$var_name" in
COLOR_BG) var_value="#1e1e2e" ;;
COLOR_FG) var_value="#cdd6f4" ;;
COLOR_SURFACE) var_value="#1e1e2e" ;;
COLOR_BORDER) var_value="#45475a" ;;
COLOR_ACCENT) var_value="#89b4fa" ;;
COLOR_URGENT) var_value="#f38ba8" ;;
COLOR_OK) var_value="#a6e3a1" ;;
COLOR_MUTED) var_value="#a6adc8" ;;
OCWS_BLUR) var_value="5" ;;
OCWS_BORDER) var_value="1" ;;
OCWS_RADIUS) var_value="8" ;;
OCWS_SHADOW) var_value="4" ;;
esac
fi
content="${content//\{\{$var_name\}\}/$var_value}"
Lesson¶
Always provide fallback defaults at the point of use, not just in the lookup function. The lookup function's default parameter is a convenience, not a guarantee — it can be bypassed by empty INI values, missing sections, or malformed keys.