Merge quattro and preserve per-theme wallpaper memory
This commit is contained in:
commit
0385610cfe
582 files changed
+33732
-3163
No files matched your search
+188
-10
@@ -19,6 +19,19 @@ THEME_SET_LOCK="${XDG_RUNTIME_DIR:-/tmp}/omarchy-theme-set.lock"
|
||||
USER_THEMES_PATH="$HOME/.config/omarchy/themes"
|
||||
OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes"
|
||||
|
||||
# What a theme installed from a git repo may not ship, because these run code.
|
||||
# Hyprland requires a theme's hyprland.lua and gum_env.lua at login and Neovim
|
||||
# loads its neovim.lua at startup, so no .lua from such a theme is staged at all.
|
||||
# Each terminal config names the program the terminal launches, and vscode.json
|
||||
# names an extension omarchy-theme-set-vscode installs, a VS Code extension being
|
||||
# arbitrary JavaScript. Everything else a theme ships is colour and is kept.
|
||||
#
|
||||
# Adding a template for another terminal, or for another editor that loads Lua,
|
||||
# means adding it here. test/shell.d/theme-staging-test.sh fails on a generated
|
||||
# theme file that is neither denied here nor recorded there as colour-only.
|
||||
INSTALLED_THEME_DENIED=(alacritty.toml foot.ini ghostty.conf kitty.conf vscode.json)
|
||||
IGNORED_THEME_FILES=()
|
||||
|
||||
run_parallel() {
|
||||
local pid
|
||||
local pids=()
|
||||
@@ -37,12 +50,17 @@ shell_ipc() {
|
||||
timeout 2 omarchy-shell "$@" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
is_video_path() {
|
||||
[[ ${1,,} =~ \.(mp4|m4v|mov|webm|mkv|avi)$ ]]
|
||||
}
|
||||
|
||||
snapshot_background_path() {
|
||||
local background="$1"
|
||||
local name="$2"
|
||||
local snapshot extension
|
||||
|
||||
[[ -f $background ]] || return
|
||||
is_video_path "$background" && return
|
||||
|
||||
mkdir -p "$BACKGROUND_TRANSITION_CACHE"
|
||||
extension=${background##*.}
|
||||
@@ -76,14 +94,25 @@ remember_current_theme_background() {
|
||||
printf '%s\n' "$current_background" >"$state_file"
|
||||
}
|
||||
|
||||
background_transition_uses_snapshots() {
|
||||
local next_background="$1"
|
||||
local current_background
|
||||
|
||||
current_background=$(readlink -f "$CURRENT_BACKGROUND_LINK" 2>/dev/null || true)
|
||||
! is_video_path "$current_background" && ! is_video_path "$next_background"
|
||||
}
|
||||
|
||||
choose_theme_background() {
|
||||
local theme_path="${1:-$CURRENT_THEME_PATH}"
|
||||
local current_theme_backgrounds="$CURRENT_THEME_PATH/backgrounds"
|
||||
local backgrounds=()
|
||||
local current_background remembered_background state_file index next_index i
|
||||
|
||||
CHOSEN_THEME_BACKGROUND=""
|
||||
mapfile -d '' -t backgrounds < <(
|
||||
find -L "$HOME/.config/omarchy/backgrounds/$THEME_NAME/" "$CURRENT_THEME_PATH/backgrounds/" -maxdepth 1 -type f \
|
||||
\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.gif' -o -iname '*.bmp' -o -iname '*.webp' \) \
|
||||
find -L "$HOME/.config/omarchy/backgrounds/$THEME_NAME/" "$theme_path/backgrounds/" -maxdepth 1 -type f \
|
||||
\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.gif' -o -iname '*.bmp' -o -iname '*.webp' \
|
||||
-o -iname '*.mp4' -o -iname '*.m4v' -o -iname '*.mov' -o -iname '*.webm' -o -iname '*.mkv' -o -iname '*.avi' \) \
|
||||
-print0 2>/dev/null | sort -z
|
||||
)
|
||||
|
||||
@@ -91,6 +120,10 @@ choose_theme_background() {
|
||||
|
||||
if [[ $PREVIOUS_THEME_NAME == "$THEME_NAME" ]]; then
|
||||
current_background=$(readlink "$CURRENT_BACKGROUND_LINK" 2>/dev/null || true)
|
||||
if [[ $theme_path != $CURRENT_THEME_PATH && ${current_background%/*} == $current_theme_backgrounds ]]; then
|
||||
current_background="$theme_path/backgrounds/${current_background##*/}"
|
||||
fi
|
||||
|
||||
index=-1
|
||||
for i in "${!backgrounds[@]}"; do
|
||||
if [[ ${backgrounds[$i]} == $current_background ]]; then
|
||||
@@ -110,6 +143,9 @@ choose_theme_background() {
|
||||
|
||||
state_file=$(theme_background_state_file "$THEME_NAME" 2>/dev/null || true)
|
||||
remembered_background=$(cat "$state_file" 2>/dev/null || true)
|
||||
if [[ $theme_path != $CURRENT_THEME_PATH && ${remembered_background%/*} == $current_theme_backgrounds ]]; then
|
||||
remembered_background="$theme_path/backgrounds/${remembered_background##*/}"
|
||||
fi
|
||||
if [[ -f $remembered_background ]]; then
|
||||
CHOSEN_THEME_BACKGROUND="$remembered_background"
|
||||
return
|
||||
@@ -118,6 +154,16 @@ choose_theme_background() {
|
||||
CHOSEN_THEME_BACKGROUND="${backgrounds[0]}"
|
||||
}
|
||||
|
||||
choose_staged_theme_background() {
|
||||
local next_theme_backgrounds="$NEXT_THEME_PATH/backgrounds"
|
||||
|
||||
choose_theme_background "$NEXT_THEME_PATH" || return 1
|
||||
|
||||
if [[ ${CHOSEN_THEME_BACKGROUND%/*} == $next_theme_backgrounds ]]; then
|
||||
CHOSEN_THEME_BACKGROUND="$CURRENT_THEME_PATH/backgrounds/${CHOSEN_THEME_BACKGROUND##*/}"
|
||||
fi
|
||||
}
|
||||
|
||||
set_theme_background_link() {
|
||||
choose_theme_background || return 1
|
||||
ln -nsf "$CHOSEN_THEME_BACKGROUND" "$CURRENT_BACKGROUND_LINK"
|
||||
@@ -126,14 +172,19 @@ set_theme_background_link() {
|
||||
set_theme_background() {
|
||||
local new_background new_background_snapshot
|
||||
|
||||
if ! choose_theme_background; then
|
||||
omarchy-notification-send "No background was found for theme" -t 2000
|
||||
shell_ipc shell applyTheme "$colors_payload" "$shell_payload" || true
|
||||
return
|
||||
if [[ -z $CHOSEN_THEME_BACKGROUND || ! -f $CHOSEN_THEME_BACKGROUND ]]; then
|
||||
if ! choose_theme_background; then
|
||||
omarchy-notification-send "No background was found for theme" -t 2000
|
||||
shell_ipc shell applyTheme "$colors_payload" "$shell_payload" || true
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
new_background="$CHOSEN_THEME_BACKGROUND"
|
||||
new_background_snapshot=$(snapshot_background_path "$new_background" "next")
|
||||
new_background_snapshot=""
|
||||
if [[ $BACKGROUND_TRANSITION_SNAPSHOTS == "true" ]]; then
|
||||
new_background_snapshot=$(snapshot_background_path "$new_background" "next")
|
||||
fi
|
||||
|
||||
if [[ -f $OLD_BACKGROUND_SNAPSHOT && -f $new_background_snapshot ]]; then
|
||||
shell_ipc background themeTransition "$OLD_BACKGROUND_SNAPSHOT" "$new_background_snapshot" "$new_background" "$colors_payload" "$shell_payload" || \
|
||||
@@ -154,12 +205,121 @@ set_theme_background() {
|
||||
ln -nsf "$new_background" "$CURRENT_BACKGROUND_LINK"
|
||||
}
|
||||
|
||||
is_denied_installed_file() {
|
||||
local name="$1"
|
||||
local denied
|
||||
|
||||
[[ $name == *.lua ]] && return 0
|
||||
|
||||
for denied in "${INSTALLED_THEME_DENIED[@]}"; do
|
||||
[[ $name == "$denied" ]] && return 0
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Themes older than colors.toml still get their palette, but their
|
||||
# alacritty.toml never reaches the staged theme: an Alacritty config names the
|
||||
# program the terminal launches.
|
||||
stage_installed_colors_from_alacritty() {
|
||||
local source="$1"
|
||||
local scratch
|
||||
|
||||
if [[ -f $NEXT_THEME_PATH/colors.toml ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ ! -f $source/alacritty.toml || -L $source/alacritty.toml ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
scratch=$(mktemp -d)
|
||||
cp "$source/alacritty.toml" "$scratch/alacritty.toml"
|
||||
omarchy-theme-colors-from-alacritty "$scratch"
|
||||
|
||||
if [[ -f $scratch/colors.toml ]]; then
|
||||
cp "$scratch/colors.toml" "$NEXT_THEME_PATH/colors.toml"
|
||||
fi
|
||||
|
||||
rm -rf "$scratch"
|
||||
}
|
||||
|
||||
# Copies a directory without ever following a symlink: in an installed theme one
|
||||
# points wherever the theme author chose, which is how an unlock.png becomes a
|
||||
# copy of any file the session can read.
|
||||
stage_installed_dir() {
|
||||
local source="$1"
|
||||
local dest="$2"
|
||||
local entry name
|
||||
|
||||
mkdir -p "$dest"
|
||||
|
||||
for entry in "$source"/*; do
|
||||
[[ -e $entry && ! -L $entry ]] || continue
|
||||
name=${entry##*/}
|
||||
|
||||
if [[ -d $entry ]]; then
|
||||
stage_installed_dir "$entry" "$dest/$name"
|
||||
else
|
||||
cp "$entry" "$dest/$name"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# `omarchy theme install` clones into ~/.config/omarchy/themes, so a .git
|
||||
# directory there means the contents came from a stranger and are held to the
|
||||
# list above. A directory the user wrote themselves, and a symlink to their own
|
||||
# working copy, are theirs to fill however they like -- the same distinction
|
||||
# omarchy-theme-extras draws when it decides which themes it may pull.
|
||||
theme_came_from_a_repo() {
|
||||
local source="$1"
|
||||
|
||||
[[ ! -L $source && -d $source/.git ]]
|
||||
}
|
||||
|
||||
stage_installed_theme() {
|
||||
local source="$1"
|
||||
local entry name
|
||||
|
||||
[[ -d $source ]] || return 0
|
||||
|
||||
for entry in "$source"/*; do
|
||||
[[ -e $entry ]] || continue
|
||||
name=${entry##*/}
|
||||
|
||||
if [[ -L $entry ]] || is_denied_installed_file "$name"; then
|
||||
case "${name,,}" in
|
||||
readme* | license* | changelog* | *.md | *.txt) ;;
|
||||
*) IGNORED_THEME_FILES+=("$name") ;;
|
||||
esac
|
||||
elif [[ -d $entry ]]; then
|
||||
stage_installed_dir "$entry" "$NEXT_THEME_PATH/$name"
|
||||
else
|
||||
cp "$entry" "$NEXT_THEME_PATH/$name"
|
||||
fi
|
||||
done
|
||||
|
||||
stage_installed_colors_from_alacritty "$source"
|
||||
}
|
||||
|
||||
report_ignored_theme_files() {
|
||||
(( ${#IGNORED_THEME_FILES[@]} > 0 )) || return 0
|
||||
|
||||
echo "Ignored in $USER_THEMES_PATH/$THEME_NAME: ${IGNORED_THEME_FILES[*]}" >&2
|
||||
echo "A theme installed from a git repo cannot supply Lua, a terminal config, or vscode.json." >&2
|
||||
}
|
||||
|
||||
THEME_NAME=$(echo "$1" | sed -E 's/<[^>]+>//g' | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
|
||||
THEME_HEADLESS=0
|
||||
if [[ ${OMARCHY_THEME_HEADLESS:-} == "1" || ${OMARCHY_THEME_OFFLINE:-} == "1" ]]; then
|
||||
THEME_HEADLESS=1
|
||||
fi
|
||||
|
||||
if [[ -z $THEME_NAME || $THEME_NAME == .* || $THEME_NAME == */* ]]; then
|
||||
echo "Invalid theme name: $1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d $OMARCHY_THEMES_PATH/$THEME_NAME ]] && [[ ! -d $USER_THEMES_PATH/$THEME_NAME ]]; then
|
||||
echo "Theme '$THEME_NAME' does not exist"
|
||||
exit 1
|
||||
@@ -178,9 +338,15 @@ remember_current_theme_background
|
||||
rm -rf "$NEXT_THEME_PATH"
|
||||
mkdir -p "$NEXT_THEME_PATH"
|
||||
|
||||
# Copy official theme first, then overlay user customizations on top
|
||||
# Copy official theme first, then overlay the user's theme on top
|
||||
cp -r "$OMARCHY_THEMES_PATH/$THEME_NAME/"* "$NEXT_THEME_PATH/" 2>/dev/null
|
||||
cp -r "$USER_THEMES_PATH/$THEME_NAME/"* "$NEXT_THEME_PATH/" 2>/dev/null
|
||||
|
||||
if theme_came_from_a_repo "$USER_THEMES_PATH/$THEME_NAME"; then
|
||||
stage_installed_theme "$USER_THEMES_PATH/$THEME_NAME"
|
||||
report_ignored_theme_files
|
||||
else
|
||||
cp -r "$USER_THEMES_PATH/$THEME_NAME/"* "$NEXT_THEME_PATH/" 2>/dev/null
|
||||
fi
|
||||
|
||||
# Generate colors.toml from alacritty.toml if theme is missing colors.toml
|
||||
if [[ ! -f $NEXT_THEME_PATH/colors.toml && -f $NEXT_THEME_PATH/alacritty.toml ]]; then
|
||||
@@ -190,9 +356,19 @@ fi
|
||||
# Generate dynamic configs
|
||||
omarchy-theme-set-templates
|
||||
|
||||
CHOSEN_THEME_BACKGROUND=""
|
||||
OLD_BACKGROUND_SNAPSHOT=""
|
||||
BACKGROUND_TRANSITION_SNAPSHOTS=true
|
||||
if [[ $THEME_HEADLESS != "1" && $OMARCHY_THEME_SKIP_BACKGROUND != "1" ]]; then
|
||||
OLD_BACKGROUND_SNAPSHOT=$(snapshot_current_background)
|
||||
# Resolve the staged choice while the old theme still exists. Video changes
|
||||
# switch directly to the durable path in QML, so neither side needs a copy.
|
||||
if choose_staged_theme_background; then
|
||||
if background_transition_uses_snapshots "$CHOSEN_THEME_BACKGROUND"; then
|
||||
OLD_BACKGROUND_SNAPSHOT=$(snapshot_current_background)
|
||||
else
|
||||
BACKGROUND_TRANSITION_SNAPSHOTS=false
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Swap next theme in as current
|
||||
@@ -233,6 +409,8 @@ post_theme_commands=(
|
||||
omarchy-theme-set-gnome
|
||||
omarchy-theme-set-pi
|
||||
omarchy-theme-set-claude
|
||||
omarchy-theme-set-hermes
|
||||
omarchy-theme-set-t3code
|
||||
omarchy-theme-set-browser
|
||||
omarchy-theme-set-vscode
|
||||
omarchy-theme-set-obsidian
|
||||
|
||||
Reference in new issue
Block a user